TECA
The Toolkit for Extreme Climate Analysis
teca_multi_cf_reader.h
1 #ifndef teca_multi_cf_reader_h
2 #define teca_multi_cf_reader_h
3 
4 #include "teca_algorithm.h"
5 #include "teca_metadata.h"
6 #include "teca_shared_object.h"
7 #include "teca_cf_reader.h"
8 
9 #include <set>
10 #include <vector>
11 #include <string>
12 
13 TECA_SHARED_OBJECT_FORWARD_DECL(teca_multi_cf_reader)
14 
15 class teca_multi_cf_reader_internals;
16 using p_teca_multi_cf_reader_internals = std::shared_ptr<teca_multi_cf_reader_internals>;
17 
18 /// A reader for data stored in NetCDF CF format in multiple files.
19 /**
20  * The data read is presented to the down stream as a single dataset
21  *
22  * use the add_reader method to specify regular expression and corresponding
23  * list of variables to read. a reader, not necessarily the same one, must be
24  * selected to provide the time and spatial axes.
25  *
26  * this reader could handle spatio-temporal interpolations as well, however
27  * that is currently not implemented. as a result all data is expected to be
28  * on the same coordinate system.
29  *
30  * A number of algorithm properties modify run time behavior, most of these
31  * are exposed from teca_cf_reader. see the teca_cf_reader for details.
32  *
33  * The reader may be initialized via a configuration file. The configuration
34  * file consists of name = value pairs and flags organized in sections.
35  * Sections are declared using []. There is an optional global section
36  * followed by a number of [cf_reader] sections. Each [cf_reader] section
37  * consists of a name(optional), a regex, a list of variables, a provides_time
38  * flag(optional) and a provides geometry flag(optional). At least one section
39  * must contain a provides_time and provides geometry flag. The global section
40  * may contain a data_root. Occurrences of the string %data_root% in the regex
41  * are replaced with the value of data_root.
42  *
43  * The following example configures the reader to read hus,ua and va.
44  *
45  * ```
46  * # TECA multi_cf_reader config
47  *
48  * data_root = /opt/TECA_data/HighResMIP/ECMWF-IFS-HR-SST-present
49  *
50  * [cf_reader]
51  * regex = %data_root%/hus/hus.*\.nc$
52  * variables = hus
53  * provides_time
54  * provides_geometry
55  *
56  * [cf_reader]
57  * regex = %data_root%/va/va.*\.nc$
58  * variables = va
59  *
60  * [cf_reader]
61  * regex = %data_root%/ua/ua.*\.nc$
62  * variables = ua
63  * ```
64  */
66 {
67 public:
68  TECA_ALGORITHM_STATIC_NEW(teca_multi_cf_reader)
69  TECA_ALGORITHM_DELETE_COPY_ASSIGN(teca_multi_cf_reader)
70  TECA_ALGORITHM_CLASS_NAME(teca_multi_cf_reader)
72 
73  // report/initialize to/from Boost program options
74  // objects.
75  TECA_GET_ALGORITHM_PROPERTIES_DESCRIPTION()
76  TECA_SET_ALGORITHM_PROPERTIES()
77 
78  /**
79  * Set the MCF configuration file that describes the dataset to read.
80  * Each section in the MCF file adds an internal reader.
81  */
82  int set_input_file(const std::string &input_file);
83  std::string get_input_file() { return this->input_file; }
84 
85  /**
86  * Adds a reader to the collection and at the same time specifies how it
87  * will be used. This is alternative way to configure the multi_cf_reader
88  * instead of providing the configuration via an MCF file (see
89  * set_input_file).
90  */
91  int add_reader(const std::string &regex,
92  const std::string &key, int provides_time,
93  int provides_geometry,
94  const std::vector<std::string> &variables);
95 
96  /// sets the reader that provides the time axis
97  int set_time_reader(const std::string &key);
98 
99  /// sets the reader that provides the mesh geometry
100  int set_geometry_reader(const std::string &key);
101 
102  /// adds to the list of variables that a reader will provide
103  int add_variable_reader(const std::string &key,
104  const std::string &variable);
105 
106  /// sets the list of variable that a reader will provide.
107  int set_variable_reader(const std::string &key,
108  const std::vector<std::string> &variable);
109 
110  /// get the list of variables that the reader will serve up
111  void get_variables(std::vector<std::string> &vars);
112 
113  /** @name periodic_in_x
114  * Set to indicate the presence of a periodic boundary in the x direction.
115  * If set this will override the corresponding setting from the MCF file
116  * for all internal readers.
117  */
118  ///@{
119  void set_periodic_in_x(int flag);
120  int get_periodic_in_x() const;
121  ///@}
122 
123  /** @name x_axis_variable
124  * Set the variable to use for the mesh x-axis. If set this will override
125  * the corresponding setting from the MCF file for all internal readers.
126  */
127  ///@{
128  void set_x_axis_variable(const std::string &var);
129  std::string get_x_axis_variable() const;
130  ///@}
131 
132  /** @name y_axis_variable
133  * Set the variable to use for the mesh y-axis. If set this will override
134  * the corresponding setting from the MCF file for all internal readers.
135  */
136  ///@{
137  void set_y_axis_variable(const std::string &var);
138  std::string get_y_axis_variable() const;
139  ///@}
140 
141  /** @name z_axis_variable
142  * Set the variable to use for the mesh z-axis. Leaving the z-axis empty
143  * results in a 2D mesh. You must set this to the correct vertical
144  * coordinate dimension to produce a 3D mesh. If set this will override
145  * the corresponding setting from the MCF file for all internal readers.
146  */
147  ///@{
148  void set_z_axis_variable(const std::string &var);
149  std::string get_z_axis_variable() const;
150  ///@}
151 
152  /** @name t_axis_variable_
153  * Set the variable to use for the mesh t-axis. Default "time". Setting
154  * this to an empty string disables the time axis. If set this will
155  * override the corresponding setting from the MCF file for all internal
156  * readers.
157  */
158  ///@{
159  void set_t_axis_variable(const std::string &var);
160  std::string get_t_axis_variable() const;
161  ///@}
162 
163  /** @name calendar
164  * Use this to override the calendar, or set one when specifying t_values
165  * directly. If set this will override the corresponding setting from the
166  * MCF file for all internal readers.
167  */
168  ///@{
169  void set_calendar(const std::string &calendar);
170  std::string get_calendar() const;
171  ///@}
172 
173  /** @name t_units
174  * Use this to set or override the time units. This is necessary when
175  * specifying time values directly. If set this will override the
176  * corresponding setting from the MCF file for all internal readers.
177  */
178  ///@{
179  void set_t_units(const std::string &units);
180  std::string get_t_units() const;
181  ///@}
182 
183  /** @name filename_time_template
184  * a way to infer time from the filename if the time axis is not stored in
185  * the file itself. If set this will override the corresponding setting
186  * from the MCF file for all internal readers.
187  *
188  * strftime format codes are used. For example for the files:
189  * ```
190  * my_file_20170516_00.nc
191  * my_file_20170516_03.nc
192  * ...
193  * ```
194  * the template would be
195  * ```
196  * my_file_%Y%m%d_%H.nc
197  * ```
198  */
199  ///@{
200  void set_filename_time_template(const std::string &templ);
201  std::string get_filename_time_template() const;
202  ///@}
203 
204  /** @name t_values
205  * Set the time values to use instead if a time variable doesn't exist or
206  * you need to override it. If set this will override the corresponding
207  * setting from the MCF file for all internal readers.
208  */
209  ///@{
210  TECA_ALGORITHM_VECTOR_PROPERTY(double, t_value)
211  ///@}
212 
213  /** @name max_metadata_ranks
214  * set/get the number of ranks used to read the time axis. If set this
215  * will override the corresponding setting from the MCF file for all
216  * internal readers.
217  */
218  ///@{
219  TECA_ALGORITHM_PROPERTY(int, max_metadata_ranks)
220  ///@}
221 
222  /** @name periodic_in_x
223  * Set to indicate the presence of a periodic boundary in the x direction.
224  * If set this will override the corresponding setting from the MCF file
225  * for all internal readers.
226  */
227  ///@{
228  ///@}
229 
230  /** @name clamp_dimensions_of_one
231  * If set the requested extent will be clamped in a given direction if the
232  * coorinate axis in that direction has a length of 1 and the requested
233  * extent would be out of bounds. This is a work around to enable loading
234  * 2D data with a vertical dimension of 1, into a 3D mesh and should be
235  * used with caution.
236  */
237  ///@{
238  void set_clamp_dimensions_of_one(int flag);
239  int get_clamp_dimensions_of_one() const;
240  ///@}
241 
242  /** @name target_bounds
243  * If set a teca_cartesian_mesh_coordinate_transform will be added to the
244  * internal pipeline of each managed reader. There must always be 6 values
245  * provided in the form "X0, x1, y0, y1, z0, z1" that define the bounds to
246  * which each axis will be transformed. Use "1, 0" for axis that should be
247  * passed through without applying the transform.
248  */
249  ///@{
250  void set_target_bounds(const std::vector<double> &bounds);
251  const std::vector<double> &get_target_bounds() const;
252  ///@}
253 
254  /** @name target_x_axis_variable
255  * Set the name of the variable to use for the transformed x-coordinate
256  * axis. If not set the name is passed through.
257  */
258  ///@{
259  void set_target_x_axis_variable(const std::string &flag);
260  std::string get_target_x_axis_variable() const;
261  ///@}
262 
263  /** @name target_y_axis_variable
264  * Set the name of the variable to use for the transformed y-coordinate
265  * axis.. If not set the name is passed through.
266  */
267  ///@{
268  void set_target_y_axis_variable(const std::string &flag);
269  std::string get_target_y_axis_variable() const;
270  ///@}
271  /** @name target_z_axis_variable
272  * Set the name of the variable to use for the transformed z-coordinate
273  * axis.. If not set the name is passed through.
274  */
275  ///@{
276  void set_target_z_axis_variable(const std::string &flag);
277  std::string get_target_z_axis_variable() const;
278  ///@}
279 
280  /** @name target_x_axis_units
281  * set/get the units for the transformed x-coordinate axis. If not set the
282  * units are passed through.
283  */
284  ///@{
285  void set_target_x_axis_units(const std::string &flag);
286  std::string get_target_x_axis_units() const;
287  ///@}
288 
289  /** @name target_y_axis_units
290  * set/get the units for the transformed y-coordinate axis. If not set the
291  * units are passed through.
292  */
293  ///@{
294  void set_target_y_axis_units(const std::string &flag);
295  std::string get_target_y_axis_units() const;
296  ///@}
297 
298  /** @name target_z_axis_units
299  * set/get the units for the transformed z-coordinate axis. If not set the
300  * units are passed through.
301  */
302  ///@{
303  void set_target_z_axis_units(const std::string &flag);
304  std::string get_target_z_axis_units() const;
305  ///@}
306 
307  /** @name validate_time_axis
308  * If set consistency checks are made to ensure that time axis from managed
309  * readers match each other. Names, calendar, units, and values of each array
310  * are verified.
311  */
312  ///@{
313  TECA_ALGORITHM_PROPERTY(int, validate_time_axis)
314  ///@}
315 
316  /** @name validate_spatial_coordinates
317  * If set consistency checks are made to ensure that spatial axes from managed
318  * readers match each other. Names, units, and values of each array
319  * are verified.
320  */
321  ///@{
322  TECA_ALGORITHM_PROPERTY(int, validate_spatial_coordinates)
323  ///@}
324 
325 protected:
327 
328 private:
329  void clear_cached_metadata();
330 
331  teca_metadata get_output_metadata(unsigned int port,
332  const std::vector<teca_metadata> &input_md) override;
333 
334  const_p_teca_dataset execute(unsigned int port,
335  const std::vector<const_p_teca_dataset> &input_data,
336  const teca_metadata &request) override;
337 
338  void set_modified() override;
339 
340 private:
341  std::string input_file;
342  std::string x_axis_variable;
343  std::string y_axis_variable;
344  std::string z_axis_variable;
345  std::string t_axis_variable;
346  std::string calendar;
347  std::string t_units;
348  std::string filename_time_template;
349  std::vector<double> t_values;
350  std::vector<double> target_bounds;
351  std::string target_x_axis_variable;
352  std::string target_y_axis_variable;
353  std::string target_z_axis_variable;
354  std::string target_x_axis_units;
355  std::string target_y_axis_units;
356  std::string target_z_axis_units;
357  int periodic_in_x;
358  int max_metadata_ranks;
359  int clamp_dimensions_of_one;
360  int validate_time_axis;
361  int validate_spatial_coordinates;
362 
363  p_teca_multi_cf_reader_internals internals;
364 };
365 
366 #endif
teca_metadata
A generic container for meta data in the form of name=value pairs.
Definition: teca_metadata.h:18
teca_multi_cf_reader::add_variable_reader
int add_variable_reader(const std::string &key, const std::string &variable)
adds to the list of variables that a reader will provide
teca_multi_cf_reader::set_input_file
int set_input_file(const std::string &input_file)
teca_multi_cf_reader::set_variable_reader
int set_variable_reader(const std::string &key, const std::vector< std::string > &variable)
sets the list of variable that a reader will provide.
teca_multi_cf_reader::set_geometry_reader
int set_geometry_reader(const std::string &key)
sets the reader that provides the mesh geometry
teca_multi_cf_reader::set_time_reader
int set_time_reader(const std::string &key)
sets the reader that provides the time axis
teca_multi_cf_reader
A reader for data stored in NetCDF CF format in multiple files.
Definition: teca_multi_cf_reader.h:65
teca_shared_object.h
teca_multi_cf_reader::add_reader
int add_reader(const std::string &regex, const std::string &key, int provides_time, int provides_geometry, const std::vector< std::string > &variables)
teca_algorithm
The interface to TECA pipeline architecture.
Definition: teca_algorithm.h:237
teca_multi_cf_reader::get_variables
void get_variables(std::vector< std::string > &vars)
get the list of variables that the reader will serve up