TECA
The Toolkit for Extreme Climate Analysis
teca_table.h
1 #ifndef teca_table_h
2 #define teca_table_h
3 
4 #include "teca_config.h"
5 #include "teca_dataset.h"
6 #include "teca_variant_array.h"
7 #include "teca_array_collection.h"
8 #include "teca_shared_object.h"
9 
10 #include <map>
11 #include <vector>
12 #include <string>
13 
14 TECA_SHARED_OBJECT_FORWARD_DECL(teca_table)
15 
16 /** @brief
17  * A collection of columnar data with row based accessors and communication and
18  * I/O support.
19  */
21 {
22 public:
23  TECA_DATASET_STATIC_NEW(teca_table)
24  TECA_DATASET_NEW_INSTANCE()
25  TECA_DATASET_NEW_COPY()
26 
27  virtual ~teca_table() = default;
28 
29  /// @name temporal metadata
30  /** Specifies the temporal extents of the data and the calendaring system
31  * used to define the time axis.
32  */
33  ///@{
34  TECA_DATASET_METADATA(calendar, std::string, 1)
35  TECA_DATASET_METADATA(time_units, std::string, 1)
36  ///@}
37 
38  /// @name attribute metadata
39  /** Provides access to the array attributes metadata, which contains
40  * information such as dimensions, units, data type, description, etc.
41  */
42  ///@{
43  TECA_DATASET_METADATA(attributes, teca_metadata, 1)
44  ///@}
45 
46  /// remove all column definitions and data
47  void clear();
48 
49  /** Define the table columns. requires name,type pairs. For example,
50  * declare_columns("c1",int(),"c2",float()) creates a table with 2 columns
51  * the first storing int the second storing float.
52  */
53  template<typename nT, typename cT, typename... oT>
54  void declare_columns(nT &&col_name, cT col_type, oT &&...args);
55 
56  /// Adds a column definition to the table.
57  template<typename nT, typename cT>
58  void declare_column(nT &&col_name, cT col_type);
59 
60  /// set the allocator to use with ::declare_column
61  void set_default_allocator(allocator alloc)
62  { m_impl->columns->set_default_allocator(alloc); }
63 
64  /// get the number of columns
65  unsigned int get_number_of_columns() const noexcept;
66 
67  /// get the number of rows
68  unsigned long get_number_of_rows() const noexcept;
69 
70  /// get a specific column. return a nullptr if the column doesn't exist.
71  p_teca_variant_array get_column(unsigned int i);
72 
73  /// get a specific column. return a nullptr if the column doesn't exist.
74  p_teca_variant_array get_column(const std::string &col_name);
75 
76  /// get a specific column. return a nullptr if the column doesn't exist.
77  const_p_teca_variant_array get_column(unsigned int i) const;
78 
79  /// get a specific column. return a nullptr if the column doesn't exist.
80  const_p_teca_variant_array get_column(const std::string &col_name) const;
81 
82  /// get a specific column. return a nullptr if the column doesn't exist.
83  template <typename array_t>
84  std::shared_ptr<array_t> get_column_as(unsigned int i)
85  {
86  return std::dynamic_pointer_cast<array_t>(this->get_column(i));
87  }
88 
89  /// get a specific column. return a nullptr if the column doesn't exist.
90  template <typename array_t>
91  std::shared_ptr<array_t> get_column_as(const std::string &col_name)
92  {
93  return std::dynamic_pointer_cast<array_t>(this->get_column(col_name));
94  }
95 
96  /// get a specific column. return a nullptr if the column doesn't exist.
97  template <typename array_t>
98  std::shared_ptr<const array_t> get_column_as(unsigned int i) const
99  {
100  return std::dynamic_pointer_cast<const array_t>(this->get_column(i));
101  }
102 
103  /// get a specific column. return a nullptr if the column doesn't exist.
104  template <typename array_t>
105  std::shared_ptr<const array_t> get_column_as(const std::string &col_name) const
106  {
107  return std::dynamic_pointer_cast<const array_t>(this->get_column(col_name));
108  }
109 
110  /// test for the existence of a specific column
111  bool has_column(const std::string &col_name) const
112  { return m_impl->columns->has(col_name); }
113 
114  /// get the name of column i, see also get_number_of_columns
115  std::string get_column_name(unsigned int i) const
116  { return m_impl->columns->get_name(i); }
117 
118  /// add a column to the table
120  { return m_impl->columns->append(array); }
121 
122  /// add a column to the table
123  int append_column(const std::string &name, p_teca_variant_array array)
124  { return m_impl->columns->append(name, array); }
125 
126  /// remove a column
127  int remove_column(unsigned int i)
128  { return m_impl->columns->remove(i); }
129 
130  /// remove a column
131  int remove_column(const std::string &name)
132  { return m_impl->columns->remove(name); }
133 
134  /// get the container holding the columns
135  p_teca_array_collection get_columns()
136  { return m_impl->columns; }
137 
138  /// get the container holding the columns
139  const_p_teca_array_collection get_columns() const
140  { return m_impl->columns; }
141 
142  /// resize the table to hold n rows of data, new rows are default initialized
143  void resize(unsigned long n);
144 
145  /// reserve memory for n rows of data without changing the tables size
146  void reserve(unsigned long n);
147 
148  /**append the collection of data in succession to each column. see also
149  * operator<< for sequential stream insertion like append.
150  */
151  template<typename cT, typename... oT>
152  void append(cT &&val, oT &&... args);
153 
154  /// return a unique string identifier
155  std::string get_class_name() const override
156  { return "teca_table"; }
157 
158  /// return an integer identifier uniquely naming the dataset type
159  int get_type_code() const override;
160 
161  /// covert to boolean. true if the dataset is not empty, otherwise false.
162  explicit operator bool() const noexcept
163  { return !this->empty(); }
164 
165  /// return true if the dataset is empty.
166  bool empty() const noexcept override;
167 
168  /// serialize the dataset to the given stream for I/O or communication
169  int to_stream(teca_binary_stream &) const override;
170 
171  /// deserialize the dataset from the given stream for I/O or communication
172  int from_stream(teca_binary_stream &) override;
173 
174  /// serialize to the stream in human readable representation
175  int to_stream(std::ostream &) const override;
176 
177  /// deserialize from the stream in human readable representation
178  int from_stream(std::istream &) override;
179 
180  /// @copydoc teca_dataset::copy(const const_p_teca_dataset &,allocator)
181  void copy(const const_p_teca_dataset &other,
182  allocator alloc = allocator::malloc) override;
183 
184  /// deep copy a subset of row values.
185  void copy(const const_p_teca_table &other,
186  unsigned long first_row, unsigned long last_row,
187  allocator alloc = allocator::malloc);
188 
189  /// @copydoc teca_dataset::shallow_copy(const p_teca_dataset &)
190  void shallow_copy(const p_teca_dataset &other) override;
191 
192  /// copy the column layout and types
193  void copy_structure(const const_p_teca_table &other);
194 
195  /// swap internals of the two objects
196  void swap(const p_teca_dataset &other) override;
197 
198  /// append rows from the passed in table which must have identical columns.
199  void concatenate_rows(const const_p_teca_table &other);
200 
201  /** append columns from the passed in table which must have same number of
202  * rows. if deep flag is true a full copy of the data is made, else a
203  * shallow copy is made.
204  */
205  void concatenate_cols(const const_p_teca_table &other, bool deep=false);
206 
207 #if defined(SWIG)
208 protected:
209 #else
210 public:
211 #endif
212  // NOTE: constructors are public to enable std::make_shared. do not use.
213  teca_table();
214 
215 protected:
216  teca_table(const teca_table &other) = delete;
217  teca_table(teca_table &&other) = delete;
218  teca_table &operator=(const teca_table &other) = delete;
219 
220  void declare_columns(){}
221  void append(){}
222 
223 private:
224  struct impl_t
225  {
226  impl_t();
227  //
228  p_teca_array_collection columns;
229  unsigned int active_column;
230  };
231  std::shared_ptr<impl_t> m_impl;
232 };
233 
234 
235 
236 
237 
238 // --------------------------------------------------------------------------
239 inline
241 {
242  return m_impl->columns->get(i);
243 }
244 
245 // --------------------------------------------------------------------------
246 inline
248 {
249  return m_impl->columns->get(i);
250 }
251 
252 // --------------------------------------------------------------------------
253 template<typename nT, typename cT, typename... oT>
254 void teca_table::declare_columns(nT &&col_name, cT col_type, oT &&... args)
255 {
256  m_impl->columns->declare(std::forward<nT>(col_name), col_type);
257  this->declare_columns(args...);
258 }
259 
260 // --------------------------------------------------------------------------
261 template<typename nT, typename cT>
262 void teca_table::declare_column(nT &&col_name, cT col_type)
263 {
264  m_impl->columns->declare(std::forward<nT>(col_name), col_type);
265 }
266 
267 // --------------------------------------------------------------------------
268 template<typename cT, typename... oT>
269 void teca_table::append(cT &&val, oT &&... args)
270 {
271  unsigned int col = m_impl->active_column++%this->get_number_of_columns();
272  m_impl->columns->get(col)->append(std::forward<cT>(val));
273  this->append(args...);
274 }
275 
276 template<typename T>
277 p_teca_table &operator<<(p_teca_table &t, T &&v)
278 {
279  t->append(std::forward<T>(v));
280  return t;
281 }
282 
283 #endif
Serialize objects into a binary stream.
Definition: teca_binary_stream.h:17
Interface for TECA datasets.
Definition: teca_dataset.h:232
A generic container for meta data in the form of name=value pairs.
Definition: teca_metadata.h:22
A collection of columnar data with row based accessors and communication and I/O support.
Definition: teca_table.h:21
int get_type_code() const override
return an integer identifier uniquely naming the dataset type
void resize(unsigned long n)
resize the table to hold n rows of data, new rows are default initialized
const_p_teca_array_collection get_columns() const
get the container holding the columns
Definition: teca_table.h:139
bool empty() const noexcept override
return true if the dataset is empty.
void reserve(unsigned long n)
reserve memory for n rows of data without changing the tables size
std::shared_ptr< const array_t > get_column_as(unsigned int i) const
get a specific column. return a nullptr if the column doesn't exist.
Definition: teca_table.h:98
void append(cT &&val, oT &&... args)
Definition: teca_table.h:269
int remove_column(unsigned int i)
remove a column
Definition: teca_table.h:127
p_teca_array_collection get_columns()
get the container holding the columns
Definition: teca_table.h:135
int remove_column(const std::string &name)
remove a column
Definition: teca_table.h:131
void set_default_allocator(allocator alloc)
set the allocator to use with ::declare_column
Definition: teca_table.h:61
std::shared_ptr< const array_t > get_column_as(const std::string &col_name) const
get a specific column. return a nullptr if the column doesn't exist.
Definition: teca_table.h:105
unsigned int get_number_of_columns() const noexcept
get the number of columns
void declare_column(nT &&col_name, cT col_type)
Adds a column definition to the table.
Definition: teca_table.h:262
std::string get_column_name(unsigned int i) const
get the name of column i, see also get_number_of_columns
Definition: teca_table.h:115
int append_column(const std::string &name, p_teca_variant_array array)
add a column to the table
Definition: teca_table.h:123
void declare_columns(nT &&col_name, cT col_type, oT &&...args)
Definition: teca_table.h:254
p_teca_variant_array get_column(unsigned int i)
get a specific column. return a nullptr if the column doesn't exist.
Definition: teca_table.h:240
int append_column(p_teca_variant_array array)
add a column to the table
Definition: teca_table.h:119
std::shared_ptr< array_t > get_column_as(const std::string &col_name)
get a specific column. return a nullptr if the column doesn't exist.
Definition: teca_table.h:91
bool has_column(const std::string &col_name) const
test for the existence of a specific column
Definition: teca_table.h:111
std::string get_class_name() const override
return a unique string identifier
Definition: teca_table.h:155
p_teca_error_handler error_handler TECA_EXPORT
The global error handler instance.
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_EXPORT bool append(teca_variant_array *varr, PyObject *obj)
Append values from the object to the variant array.
Definition: teca_py_array.h:221
TECA_EXPORT std::ostream & operator<<(std::ostream &os, const teca_calendar_util::time_point &tpt)
send the time_point to a stream in humnan readable form
std::shared_ptr< teca_variant_array > p_teca_variant_array
Definition: teca_variant_array.h:27
std::shared_ptr< const teca_variant_array > const_p_teca_variant_array
Definition: teca_variant_array.h:27