cfvariable.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #ifndef LPJGUESS_GUESSNC_CFVARIABLE_H
  2. #define LPJGUESS_GUESSNC_CFVARIABLE_H
  3. #ifdef HAVE_NETCDF
  4. #include <vector>
  5. #include <string>
  6. #include "cftime.h"
  7. namespace GuessNC {
  8. namespace CF {
  9. /// Class for reading data from a NetCDF file following a limited CF convention
  10. /** Expected to be used for dealing with one gridcell at a time, so the NetCDF
  11. * file should also be stored in that order to get acceptable performance.
  12. *
  13. * Limitations on top of CF:
  14. *
  15. * * Main variable and time coordinate must be numeric NetCDF classic data types.
  16. *
  17. * * Time and 2D space dimensions are understood by the class. The main variable
  18. * may also have an additional extra dimension (for instance for height), which
  19. * this class simply treats as 'the extra dimension' if available.
  20. */
  21. class GridcellOrderedVariable {
  22. public:
  23. /// Constructor
  24. /** \param filename The NetCDF file to open
  25. * \param variable The name of the variable to read from
  26. */
  27. GridcellOrderedVariable(const char* filename, const char* variable);
  28. /// Destructor, releases resources
  29. ~GridcellOrderedVariable();
  30. /// Loads data for all timesteps for a given location
  31. /**
  32. * This version of the function is to be used for datasets where
  33. * locations are identified with an x- and a y-coordinate.
  34. *
  35. * x and y could be coordinates in lon and lat dimensions, but could
  36. * also represent coordinates in some other coordinate system, with
  37. * longitude and latitude represented by an auxiliary coordinate
  38. * variable.
  39. *
  40. * \param x The x coordinate in main variable's coordinate system
  41. * \param y The y coordinate in main variable's coordinate system
  42. * \returns whether the location exists and has only valid (non-missing) values.
  43. */
  44. bool load_data_for(size_t x, size_t y);
  45. /// Loads data for all timesteps for a given land id
  46. /**
  47. * This version of the function is to be used for datasets
  48. * using a reduced horizontal grid, as in the example in
  49. * section 5.3 of the 1.6 version of the CF spec.
  50. *
  51. * \param landid Index identifying the cell in the main variable's coordinate system
  52. * \returns whether the location exists and has only valid (non-missing) values.
  53. */
  54. bool load_data_for(size_t landid);
  55. /// Are locations identified with one or two indices?
  56. /** In a variable with a reduced horizontal grid, the locations are
  57. * identified with a simple land id. Otherwise an (x,y)-pair is used.
  58. *
  59. * \see load_data_for
  60. */
  61. bool is_reduced() const;
  62. /// Retrieves actual (lon, lat)-coordinates for a given location
  63. void get_coords_for(size_t x, size_t y, double& lon, double& lat) const;
  64. /// Retrieves actual (lon,lat)-coordinates for a given location
  65. void get_coords_for(size_t landid, double& lon, double& lat) const;
  66. /// Gets the number of timesteps for the variable
  67. int get_timesteps() const;
  68. /// Gets variable's value for currently loaded location in a certain timestep
  69. /** Use this function to retrieve values in a 3 dimensional data set,
  70. * where each (lat,lon,time) triple corresponds to a single scalar value.
  71. *
  72. * \see get_values for data sets with an extra dimension
  73. *
  74. * If this function is used with a data set with an extra dimension,
  75. * it will return the first value for the given time step.
  76. */
  77. double get_value(int timestep) const;
  78. /// Gets all values for currently loaded location in a certain timestep
  79. /** Use this function to retrieve values in a 4 dimensional data set,
  80. * for instance when height is a fourth dimension.
  81. *
  82. * The values vector will be resized if necessary.
  83. */
  84. void get_values(int timestep, std::vector<double>& values) const;
  85. /// Gets a DateTime corresponding to a timestep
  86. DateTime get_date_time(int timestep) const;
  87. /// Checks if data exists for a given location
  88. bool location_exists(size_t x, size_t y) const;
  89. /// Checks if data exists for a given location
  90. bool location_exists(size_t landid) const;
  91. /// Returns the 'units' attribute of the main variable
  92. std::string get_units() const;
  93. /// Returns the main variable's name
  94. std::string get_variable_name() const;
  95. /// Returns the main variable's standard name
  96. /** Can be used to identify the variable */
  97. std::string get_standard_name() const;
  98. /// Returns a descriptive name of the variable
  99. /** Should be used for presentation for the user, not for
  100. * identification of the variable.
  101. */
  102. std::string get_long_name() const;
  103. /// Gets the values for each coordinate value in the 'extra' dimension
  104. /** Returns an empty vector if there is no extra dimension.
  105. */
  106. void get_extra_dimension(std::vector<double>& coordinate_values) const;
  107. /// Gets the values for each coordinate value in the 'extra' dimension
  108. /** Returns an empty vector if there is no extra dimension.
  109. *
  110. * Only defined if compiled with support for NetCDF4 files (needs the
  111. * string data type).
  112. */
  113. void get_extra_dimension(std::vector<std::string>& coordinate_values) const;
  114. /// \returns the calendar type used by this variable
  115. CalendarType get_calendar_type() const;
  116. /// Checks if another GridcellOrderedVariable has the same spatial domain as this one
  117. bool same_spatial_domain(const GridcellOrderedVariable& other) const;
  118. private:
  119. /** Called by constructor to figure out all we need to know about
  120. * the time dimension and how to interpret time.
  121. *
  122. * Assumes ncid_file and ncid_var already set.
  123. */
  124. void find_time_dimension();
  125. /** Called by constructor to figure out all we need to know about
  126. * the spatial dimensions.
  127. *
  128. * Assumes ncid_file and ncid_var already set.
  129. */
  130. void find_spatial_dimensions();
  131. /** Called by constructor to figure out if there is an extra
  132. * dimension, and if so, its id and size.
  133. *
  134. * Assumes time and spatial dimensions already found.
  135. */
  136. void find_extra_dimension();
  137. /** Unpacks the raw data according to scale_factor and add_offset
  138. * arguments, if present.
  139. */
  140. void unpack_data();
  141. /// Help function for same_spatial_domain, compares either the lat coordinate variable or lon
  142. bool same_spatial_coordinates(int ncid_my_coordvar,
  143. const GridcellOrderedVariable& other,
  144. int ncid_other_coordvar) const;
  145. /// NC handle to NetCDF file
  146. int ncid_file;
  147. /// NC handle to main variable
  148. int ncid_var;
  149. /// Name of main variable (for error messages)
  150. std::string variable_name;
  151. /// Data for all timesteps for current location
  152. std::vector<double> data;
  153. /// Time offsets for all timesteps
  154. /** The times are relative to a starting time given in time_spec.
  155. * This follows how times are represented in CF, see CF spec
  156. * for overview.
  157. */
  158. std::vector<double> time;
  159. /// Reference time specification
  160. /** Defines how the time offsets in the time vector are to be
  161. * interpreted, \see TimeUnitSpecification for more information.
  162. */
  163. TimeUnitSpecification time_spec;
  164. /// The calendar used by the variable
  165. CalendarType calendar;
  166. // The order of the dimensions in the main variable
  167. size_t t_dimension_index;
  168. size_t x_dimension_index;
  169. size_t y_dimension_index;
  170. size_t landid_dimension_index;
  171. size_t extra_dimension_index;
  172. // NC handles to the dimensions of the main variable
  173. int ncid_x_dimension;
  174. int ncid_y_dimension;
  175. int ncid_landid_dimension;
  176. int ncid_t_dimension;
  177. int ncid_extra_dimension;
  178. // NC handles to variables with lon/lat values,
  179. // either regular coordinate variables as in COARDS, or auxiliary
  180. // coordinate variables as defined by CF
  181. int ncid_lon;
  182. int ncid_lat;
  183. /// Whether the spatial coordinate system is a reduced horizontal grid
  184. bool reduced;
  185. /// The size of the 'extra' dimension (for instance height)
  186. /** Set to 1 if there is no extra dimension */
  187. size_t extra_dimension_size;
  188. };
  189. }
  190. }
  191. #endif // HAVE_NETCDF
  192. #endif // LPJGUESS_GUESSNC_CFVARIABLE_H