TECA
The Toolkit for Extreme Climate Analysis
teca_dataset.h
1 #ifndef teca_dataset_h
2 #define teca_dataset_h
3 
4 #include "teca_config.h"
5 #include "teca_common.h"
6 #include "teca_shared_object.h"
7 #include "teca_variant_array.h"
9 
10 #include <vector>
11 #include <iosfwd>
12 #include <type_traits>
13 
14 class teca_binary_stream;
15 class teca_metadata;
16 
17 TECA_SHARED_OBJECT_FORWARD_DECL(teca_dataset)
18 
19 // this is a convenience macro to be used to
20 // declare New and enable seamless operation
21 // with std C++11 shared pointer
22 #define TECA_DATASET_STATIC_NEW(T) \
23  \
24 static p_##T New() \
25 { \
26  return std::make_shared<T>(); \
27 } \
28  \
29 std::shared_ptr<T> shared_from_this() \
30 { \
31  return std::static_pointer_cast<T>( \
32  teca_dataset::shared_from_this()); \
33 } \
34  \
35 std::shared_ptr<T const> shared_from_this() const \
36 { \
37  return std::static_pointer_cast<T const>( \
38  teca_dataset::shared_from_this()); \
39 }
40 
41 // convenience macro implementing new_instance method
42 #define TECA_DATASET_NEW_INSTANCE() \
43 virtual p_teca_dataset new_instance() const override \
44 { \
45  return std::make_shared \
46  <std::remove_const<std::remove_reference \
47  <decltype(*this)>::type>::type >(); \
48 }
49 
50 // convenience macro implementing new_copy method
51 #define TECA_DATASET_NEW_COPY() \
52 /** @copydoc teca_dataset::new_copy(allocator) */ \
53 virtual p_teca_dataset new_copy(allocator alloc = \
54  allocator::malloc) const override \
55 { \
56  p_teca_dataset o = std::make_shared \
57  <std::remove_const<std::remove_reference \
58  <decltype(*this)>::type>::type>(); \
59  \
60  o->copy(this->shared_from_this(), alloc); \
61  \
62  return o; \
63 } \
64  \
65 virtual p_teca_dataset new_shallow_copy() override \
66 { \
67  p_teca_dataset o = std::make_shared \
68  <std::remove_const<std::remove_reference \
69  <decltype(*this)>::type>::type>(); \
70  \
71  o->shallow_copy(this->shared_from_this()); \
72  \
73  return o; \
74 }
75 
76 // convenience macro for adding properties to dataset
77 // objects
78 #define TECA_DATASET_PROPERTY(T, name) \
79  \
80 void set_##name(const T &val) \
81 { \
82  this->name = val; \
83 } \
84  \
85 const T &get_##name() const \
86 { \
87  return this->name; \
88 } \
89  \
90 T &get_##name() \
91 { \
92  return this->name; \
93 }
94 
95 // convenience set get methods for dataset metadata
96 #define TECA_DATASET_METADATA(key, T, len) \
97 TECA_DATASET_METADATA_V(T, key, len) \
98 TECA_DATASET_METADATA_A(T, key, len) \
99 TECA_DATASET_METADATA_ ## len (T, key)
100 
101 
102 #define TECA_DATASET_METADATA_1(T, key) \
103 void set_##key(const T & val_1) \
104 { \
105  this->get_metadata().set<T>(#key, val_1); \
106 } \
107  \
108 int get_##key(T &val_1) const \
109 { \
110  return this->get_metadata().get<T>( \
111  #key, val_1); \
112 }
113 
114 #define TECA_DATASET_METADATA_2(T, key) \
115 void set_##key(const T & val_1, const T & val_2) \
116 { \
117  this->get_metadata().set<T>( \
118  #key, {val_1, val_2}); \
119 } \
120  \
121 int get_##key(T &val_1, T &val_2) const \
122 { \
123  std::vector<T> vals; \
124  if (this->get_metadata().get<T>(#key, vals)) \
125  return -1; \
126  val_1 = vals[0]; \
127  val_2 = vals[1]; \
128  return 0; \
129 }
130 
131 #define TECA_DATASET_METADATA_3(T, key) \
132 void set_##key(const T & val_1, const T & val_2, \
133  const T & val_3) \
134 { \
135  this->get_metadata().set<T>(#key, \
136  {val_1, val_2, val_3}); \
137 } \
138  \
139 int get_##key(T &val_1, T &val_2, T &val_3) const \
140 { \
141  std::vector<T> vals; \
142  if (this->get_metadata().get<T>(#key, vals)) \
143  return -1; \
144  val_1 = vals[0]; \
145  val_2 = vals[1]; \
146  val_3 = vals[2]; \
147  return 0; \
148 }
149 
150 #define TECA_DATASET_METADATA_4(T, key) \
151 void set_##key(const T & val_1, const T & val_2, \
152  const T & val_3, const T & val_4) \
153 { \
154  this->get_metadata().set<T>(#key, \
155  {val_1, val_2, val_3, val_4}); \
156 }
157 
158 #define TECA_DATASET_METADATA_6(T, key) \
159 void set_##key(const T & val_1, const T & val_2, \
160  const T & val_3, const T & val_4, \
161  const T & val_5, const T & val_6) \
162 { \
163  this->get_metadata().set<T>(#key, \
164  {val_1, val_2, val_3, \
165  val_4, val_5, val_6}); \
166 }
167 
168 #define TECA_DATASET_METADATA_8(T, key) \
169 void set_##key(const T & val_1, const T & val_2, \
170  const T & val_3, const T & val_4, \
171  const T & val_5, const T & val_6, \
172  const T & val_7, const T & val_8) \
173 { \
174  this->get_metadata().set<T>(#key, \
175  {val_1, val_2, val_3, val_4, val_5, \
176  val_6, val_7, val_8}); \
177 }
178 
179 #define TECA_DATASET_METADATA_V(T, key, len) \
180 void set_##key(const std::vector<T> &vals) \
181 { \
182  if (vals.size() != len) \
183  { \
184  TECA_ERROR(#key " requires " #len " values") \
185  } \
186  this->get_metadata().set<T>(#key, vals); \
187 } \
188  \
189 int get_##key(std::vector<T> &vals) const \
190 { \
191  return this->get_metadata().get<T>(#key, vals); \
192 } \
193  \
194 void set_##key(const p_teca_variant_array &vals) \
195 { \
196  if (vals->size() != len) \
197  { \
198  TECA_ERROR(#key " requires " #len " values") \
199  } \
200  this->get_metadata().set(#key, vals); \
201 } \
202  \
203 int get_##key(p_teca_variant_array vals) const \
204 { \
205  return this->get_metadata().get(#key, vals); \
206 } \
207  \
208 void set_##key(const std::initializer_list<T> &l) \
209 { \
210  std::vector<T> vals(l); \
211  if (vals.size() != len) \
212  { \
213  TECA_ERROR(#key " requires " #len " values") \
214  } \
215  this->get_metadata().set<T>(#key, vals); \
216 } \
217 
218 #define TECA_DATASET_METADATA_A(T, key, len) \
219 void set_##key(const T *vals) \
220 { \
221  this->get_metadata().set<T>(#key, vals, len); \
222 } \
223  \
224 int get_##key(T *vals) const \
225 { \
226  return this->get_metadata().get<T>( \
227  #key, vals, len); \
228 }
229 
230 /// Interface for TECA datasets.
231 class TECA_EXPORT teca_dataset : public std::enable_shared_from_this<teca_dataset>
232 {
233 public:
234  using allocator = teca_variant_array::allocator;
235 
236  virtual ~teca_dataset();
237 
238  // the name of the key that holds the index identifying this dataset
239  // this should be set by the algorithm that creates the dataset.
240  TECA_DATASET_METADATA(index_request_key, std::string, 1)
241 
242  // a dataset metadata that uses the value of index_request_key to
243  // store the index that identifies this dataset. this should be set
244  // by the algorithm that creates the dataset.
245  virtual int get_request_index(long &val) const;
246  virtual int set_request_index(const std::string &key, long val);
247  virtual int set_request_index(long val);
248 
249  // covert to boolean. true if the dataset is not empty.
250  // otherwise false.
251  explicit operator bool() const noexcept
252  { return !this->empty(); }
253 
254  // return true if the dataset is empty.
255  virtual bool empty() const noexcept
256  { return true; }
257 
258  // virtual constructor. return a new dataset of the same type.
259  virtual p_teca_dataset new_instance() const = 0;
260 
261  /** Virtual copy constructor. return a deep copy of this dataset in a new
262  * instance.
263  *
264  * @param[in] alloc The allocator to use for alloctions of data structures
265  * to hold the copy. The default is a CPU based allocator.
266  */
267  virtual p_teca_dataset new_copy(allocator alloc = allocator::malloc) const = 0;
268 
269  /** Virtual shallow copy constructor. return a shallow copy of this dataset
270  * in a new instance. References to source data structures are taken, but
271  * metadata is always deep copied.
272  */
273  virtual p_teca_dataset new_shallow_copy() = 0;
274 
275  // return a string identifier uniquely naming the dataset type
276  virtual std::string get_class_name() const = 0;
277 
278  // return an integer identifier uniquely naming the dataset type
279  virtual int get_type_code() const = 0;
280 
281  /** Deep copy data and metdata.
282  *
283  * @param[in] other The dataset to copy.
284  * @param[in] alloc The allocator to use for alloctions of data structures
285  * to hold the copy. The default is a CPU based allocator.
286  */
287  virtual void copy(const const_p_teca_dataset &other,
288  allocator alloc = allocator::malloc);
289 
290  /** Shallow copy data and metadata. The shallow copy takes references to
291  * the source data structures. Metadata is always deep copied.
292  *
293  * @param[in] other The dataset to copy.
294  */
295  virtual void shallow_copy(const p_teca_dataset &other);
296 
297  // copy metadata. always a deep copy.
298  virtual void copy_metadata(const const_p_teca_dataset &other);
299 
300  // swap internals of the two objects
301  virtual void swap(const p_teca_dataset &other);
302 
303  // access metadata
304  virtual teca_metadata &get_metadata() noexcept;
305  virtual const teca_metadata &get_metadata() const noexcept;
306  virtual void set_metadata(const teca_metadata &md);
307 
308  // serialize the dataset to/from the given stream
309  // for I/O or communication
310  virtual int to_stream(teca_binary_stream &) const;
311  virtual int from_stream(teca_binary_stream &);
312 
313  // stream to/from human readable representation
314  virtual int to_stream(std::ostream &) const;
315  virtual int from_stream(std::istream &);
316 
317 protected:
318  teca_dataset();
319 
320  teca_dataset(const teca_dataset &) = delete;
321  teca_dataset(const teca_dataset &&) = delete;
322 
323  void operator=(const p_teca_dataset &other) = delete;
324  void operator=(p_teca_dataset &&other) = delete;
325 
326  teca_metadata *metadata;
327 };
328 
329 #endif
teca_variant_array.h
teca_binary_stream
Serialize objects into a binary stream.
Definition: teca_binary_stream.h:16
teca_metadata
A generic container for meta data in the form of name=value pairs.
Definition: teca_metadata.h:21
teca_dataset
Interface for TECA datasets.
Definition: teca_dataset.h:231
teca_variant_array::allocator
hamr::buffer_allocator allocator
allocator types
Definition: teca_variant_array.h:46
teca_common.h
teca_py_array::copy
TECA_EXPORT bool copy(teca_variant_array *varr, PyObject *obj)
Copy values from the object into variant array.
Definition: teca_py_array.h:290
teca_shared_object.h
teca_error::TECA_EXPORT
p_teca_error_handler error_handler TECA_EXPORT
The global error handler instance.
teca_variant_array_impl.h