ReFRACtor
hdf_file.cc
Go to the documentation of this file.
1 #include "hdf_file.h"
2 
3 using namespace FullPhysics;
4 using namespace blitz;
5 using namespace H5;
6 
7 #ifdef HAVE_LUA
8 #include "register_lua.h"
9 double hdf_file_apriori_double(const HdfFile& h, const std::string& gname)
10 {
11  return h.read_field<double, 1>(gname + "/a_priori")(0);
12 }
13 
14 std::string hdf_file_read_string(const HdfFile& h, const std::string& fname)
15 {
16  return h.read_field<std::string>(fname);
17 }
18 
19 std::vector<std::string> hdf_file_read_string_vector(const HdfFile& h, const std::string& fname)
20 {
21  blitz::Array<std::string, 1> str_arr = h.read_field<std::string, 1>(fname);
22  std::vector<std::string> result;
23  for(int i = 0; i < str_arr.rows(); i++)
24  result.push_back(str_arr(i));
25  return result;
26 }
27 
28 std::vector<std::string> hdf_file_read_string_vector_row(const HdfFile& h, const std::string& fname, int row)
29 {
30  blitz::Array<std::string, 2> str_arr = h.read_field<std::string, 2>(fname);
31  std::vector<std::string> result;
32  for(int i = 0; i < str_arr.cols(); i++)
33  result.push_back(str_arr(0,i));
34  return result;
35 }
36 
37 Array<int, 1> hdf_file_read_int_1d(const HdfFile& h, const std::string& fname)
38 {
39  return h.read_field<int, 1>(fname);
40 }
41 
42 Array<int, 2> hdf_file_read_int_2d(const HdfFile& h, const std::string& fname)
43 {
44  return h.read_field<int, 2>(fname);
45 }
46 
47 Array<int, 3> hdf_file_read_int_3d(const HdfFile& h, const std::string& fname)
48 {
49  return h.read_field<int, 3>(fname);
50 }
51 
52 double hdf_file_read_double_scalar(const HdfFile& h, const std::string& gname)
53 {
54  return h.read_field<double>(gname);
55 }
56 
57 Array<double, 1> hdf_file_read_double_1d(const HdfFile& h,
58  const std::string& fname)
59 {
60  return h.read_field<double, 1>(fname);
61 }
62 
63 double hdf_file_read_double_1d_i(const HdfFile& h,
64  const std::string& fname,
65  int I)
66 {
67  blitz::TinyVector<int,1> start;
68  blitz::TinyVector<int,1> sz;
69  start = I;
70  sz = 1;
71  return h.read_field<double, 1>(fname, start, sz)(0);
72 }
73 
74 ArrayWithUnit<double, 1> hdf_file_read_double_with_unit_1d(const HdfFile& h,
75  const std::string& fname)
76 {
77  return h.read_field_with_unit<double, 1>(fname);
78 }
79 
80 
81 Array<double, 2> hdf_file_read_double_2d(const HdfFile& h,
82  const std::string& fname)
83 {
84  return h.read_field<double, 2>(fname);
85 }
86 
87 double hdf_file_read_double_2d_i(const HdfFile& h,
88  const std::string& fname,
89  int I, int J)
90 {
91  blitz::TinyVector<int,2> start;
92  blitz::TinyVector<int,2> sz;
93  start = I, J;
94  sz = 1, 1;
95  return h.read_field<double, 2>(fname, start, sz)(0, 0);
96 }
97 
98 ArrayWithUnit<double, 2> hdf_file_read_double_with_unit_2d(const HdfFile& h,
99  const std::string& fname)
100 {
101  return h.read_field_with_unit<double, 2>(fname);
102 }
103 
104 
105 Array<double, 3> hdf_file_read_double_3d(const HdfFile& h,
106  const std::string& fname)
107 {
108  return h.read_field<double, 3>(fname);
109 }
110 
111 double hdf_file_read_double_3d_i(const HdfFile& h,
112  const std::string& fname,
113  int I, int J, int K)
114 {
115  blitz::TinyVector<int,3> start;
116  blitz::TinyVector<int,3> sz;
117  start = I, J, K;
118  sz = 1, 1, 1;
119  return h.read_field<double, 3>(fname, start, sz)(0, 0, 0);
120 }
121 
122 ArrayWithUnit<double, 3> hdf_file_read_double_with_unit_3d(const HdfFile& h,
123  const std::string& fname)
124 {
125  return h.read_field_with_unit<double, 3>(fname);
126 }
127 
128 Array<double, 4> hdf_file_read_double_4d(const HdfFile& h,
129  const std::string& fname)
130 {
131  return h.read_field<double, 4>(fname);
132 }
133 
134 // We have a number of places where we read a 4d field and only want
135 // one sounding number. Have code for doing this.
136 Array<double, 3> hdf_file_read_double_4d_sounding(const HdfFile& h,
137  const std::string& fname,
138  int Sounding_num)
139 {
140  TinyVector<int, 4> shp = h.read_shape<4>(fname);
141  TinyVector<int,4> start;
142  TinyVector<int,4> sz;
143  start = 0, Sounding_num, 0, 0;
144  sz = shp(0), 1, shp(2), shp(3);
145  return h.read_field<double, 4>(fname, start, sz)(Range::all(), 0,
146  Range::all(), Range::all());
147 }
148 
149 
150 double hdf_file_read_double_4d_i(const HdfFile& h,
151  const std::string& fname,
152  int I, int J, int K, int L)
153 {
154  blitz::TinyVector<int,4> start;
155  blitz::TinyVector<int,4> sz;
156  start = I, J, K, L;
157  sz = 1, 1, 1, 1;
158  return h.read_field<double, 4>(fname, start, sz)(0, 0, 0, 0);
159 }
160 
161 Array<double, 5> hdf_file_read_double_5d(const HdfFile& h,
162  const std::string& fname)
163 {
164  return h.read_field<double, 5>(fname);
165 }
166 
167 Array<double, 1> hdf_file_apriori(const HdfFile& h,
168  const std::string& gname)
169 {
170  return h.read_field<double, 1>(gname + "/a_priori");
171 }
172 
173 ArrayWithUnit<double, 1> hdf_file_apriori_with_unit(const HdfFile& h,
174  const std::string& gname)
175 {
176  return h.read_field_with_unit<double, 1>(gname + "/a_priori");
177 }
178 
179 Array<double, 1> hdf_file_apriori2(const HdfFile& h,
180  const std::string& gname,
181  int row)
182 {
183  return h.read_field<double, 2>(gname + "/a_priori")(row, Range::all());
184 }
185 
186 Array<double, 1> hdf_file_apriori3(const HdfFile& h,
187  const std::string& gname,
188  int row, int col)
189 {
190  return h.read_field<double, 3>(gname + "/a_priori")(row, col, Range::all());
191 }
192 
193 ArrayWithUnit<double, 1> hdf_file_apriori2_with_unit(const HdfFile& h,
194  const std::string& gname,
195  int row)
196 {
197  ArrayWithUnit<double, 1> res = h.read_field_with_unit<double, 2>(gname + "/a_priori")(row, Range::all());
198  return res;
199 }
200 
201 Array<double, 2> hdf_file_covariance(const HdfFile& h,
202  const std::string& gname)
203 {
204  return h.read_field<double, 2>(gname + "/covariance");
205 }
206 
207 Array<double, 2> hdf_file_covariance2(const HdfFile& h,
208  const std::string& gname,
209  int row)
210 {
211  return h.read_field<double, 3>(gname + "/covariance")(row, Range::all(),
212  Range::all());
213 }
214 
215 Array<double, 2> hdf_file_covariance3(const HdfFile& h,
216  const std::string& gname,
217  int row, int col)
218 {
219  return h.read_field<double, 4>(gname + "/covariance")(row, col, Range::all(),
220  Range::all());
221 }
222 
224 .def(luabind::constructor<std::string>())
225 .def("read_string", &hdf_file_read_string)
226 .def("read_string_vector", &hdf_file_read_string_vector)
227 .def("read_string_vector", &hdf_file_read_string_vector_row)
228 .def("read_int_1d", &hdf_file_read_int_1d)
229 .def("read_int_2d", &hdf_file_read_int_2d)
230 .def("read_int_3d", &hdf_file_read_int_3d)
231 .def("read_double_scalar", &hdf_file_read_double_scalar)
232 .def("read_double_1d", &hdf_file_read_double_1d)
233 .def("read_double_1d", &hdf_file_read_double_1d_i)
234 .def("read_double_with_unit_1d", &hdf_file_read_double_with_unit_1d)
235 .def("read_double_2d", &hdf_file_read_double_2d)
236 .def("read_double_2d", &hdf_file_read_double_2d_i)
237 .def("read_double_with_unit_2d", &hdf_file_read_double_with_unit_2d)
238 .def("read_double_3d", &hdf_file_read_double_3d)
239 .def("read_double_3d", &hdf_file_read_double_3d_i)
240 .def("read_double_with_unit_3d", &hdf_file_read_double_with_unit_3d)
241 .def("read_double_4d", &hdf_file_read_double_4d)
242 .def("read_double_4d_sounding", &hdf_file_read_double_4d_sounding)
243 .def("read_double_5d", &hdf_file_read_double_5d)
244 .def("apriori", &hdf_file_apriori)
245 .def("apriori_with_unit", &hdf_file_apriori_with_unit)
246 .def("apriori", &hdf_file_apriori2)
247 .def("apriori_with_unit", &hdf_file_apriori2_with_unit)
248 .def("apriori", &hdf_file_apriori3)
249 .def("apriori_double", &hdf_file_apriori_double)
250 .def("covariance", &hdf_file_covariance)
251 .def("covariance", &hdf_file_covariance2)
252 .def("covariance", &hdf_file_covariance3)
253 .def("has_object", &HdfFile::has_object)
255 #endif
256 
257 //-----------------------------------------------------------------------
259 //-----------------------------------------------------------------------
260 
261 HdfFile::HdfFile(const std::string& Fname, Mode M)
262 : fname(Fname), mode_(M)
263 {
264  unsigned int flag;
265  switch(M) {
266  case READ:
267  flag = H5F_ACC_RDONLY;
268  break;
269  case READ_WRITE:
270  flag = H5F_ACC_RDWR;
271  break;
272  case CREATE:
273  flag = H5F_ACC_TRUNC;
274  break;
275  default:
276  throw Exception("This shouldn't happen");
277  }
278  H5::Exception::dontPrint(); // We'll report exceptions ourself,
279  // don't have HDF library print
280  // Warning messages.
281  try {
282 
283  FileAccPropList file_access = FileAccPropList();
284  file_access.setFcloseDegree(H5F_CLOSE_SEMI);
285 
286  h.reset(new H5File(Fname, flag, FileCreatPropList::DEFAULT, file_access));
287  } catch(const H5::Exception& e) {
288  Exception en;
289  en << "While trying to open file '" << Fname
290  << "' a HDF 5 Exception thrown:\n"
291  << " " << e.getDetailMsg();
292  throw en;
293  }
294 }
295 
296 //-----------------------------------------------------------------------
299 //-----------------------------------------------------------------------
300 
301 // In HDF5 1.10: "CommonFG will be deprecated in future releases. In 1.10.1, most member functions are moved to H5Location."
302 #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR >= 10 && H5_VERS_RELEASE >= 1
303 void HdfFile::create_group_if_needed(const std::string& Dataname, H5::H5Location& Parent)
304 #else
305 void HdfFile::create_group_if_needed(const std::string& Dataname, H5::CommonFG& Parent)
306 #endif
307 {
308  size_t i = Dataname.find_first_of('/');
309  if(i ==std::string::npos)
310  return;
311  if(i ==0) // If "/" is at beginning, then just
312  // strip it off
313  create_group_if_needed(Dataname.substr(i + 1), Parent);
314  else {
315  std::string gname = Dataname.substr(0, i);
316  if(!is_present(gname, Parent)) {
317  Group g = Parent.createGroup(gname);
318  create_group_if_needed(Dataname.substr(i + 1), g);
319  } else {
320  Group g = Parent.openGroup(gname);
321  create_group_if_needed(Dataname.substr(i + 1), g);
322  }
323  }
324 }
325 
326 //-----------------------------------------------------------------------
328 //-----------------------------------------------------------------------
329 
330 bool HdfFile::is_group(const std::string& Objname) const
331 {
332  H5G_stat_t statbuf;
333  h->getObjinfo(Objname, statbuf);
334  return statbuf.type == H5G_GROUP;
335 }
336 
337 //-----------------------------------------------------------------------
339 //-----------------------------------------------------------------------
340 
341 // In HDF5 1.10: "CommonFG will be deprecated in future releases. In 1.10.1, most member functions are moved to H5Location."
342 #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR >= 10 && H5_VERS_RELEASE >= 1
343 bool HdfFile::is_present(const std::string& Objname,
344  const H5::H5Location& Parent) const
345 #else
346 bool HdfFile::is_present(const std::string& Objname,
347  const H5::CommonFG& Parent) const
348 #endif
349 {
350  try {
351  H5G_stat_t statbuf;
352  Parent.getObjinfo(Objname, statbuf);
353  } catch(const H5::Exception& E) {
354  return false;
355  }
356  return true;
357 }
358 
359 //-----------------------------------------------------------------------
361 //-----------------------------------------------------------------------
362 
363 bool HdfFile::has_attribute(const std::string& Aname) const
364 {
365  try {
366  open_attribute(Aname);
367  } catch(const H5::Exception& E) {
368  return false;
369  }
370  return true;
371 }
372 
373 //-----------------------------------------------------------------------
376 //-----------------------------------------------------------------------
377 
378 H5::Attribute HdfFile::open_attribute(const std::string& Aname) const
379 {
380  size_t i = Aname.find_last_of('/');
381  if(i == std::string::npos) {
383  e << "The attribute name '" << Aname << "' is not a valid name";
384  throw e;
385  }
386  std::string gname = Aname.substr(0, i);
387  std::string aname = Aname.substr(i + 1);
388  if(is_group(gname)) {
389  Group attr_group = h->openGroup(gname);
390  return attr_group.openAttribute(aname);
391  } else {
392  DataSet attr_dataset = h->openDataSet(gname);
393  return attr_dataset.openAttribute(aname);
394  }
395 }
396 
397 //-----------------------------------------------------------------------
399 //-----------------------------------------------------------------------
400 
401 Unit HdfFile::read_units(const std::string& Dataname) const
402 {
403  Unit res;
404  // Older OCO data does not have the "Units" attribute, but rather
405  // has a older "Unit" attribute. Provide limited support for this
406  // older format, so we can read the older data. This support can go
407  // away in the future when we don't need this support any longer.
408  if(has_attribute(Dataname + "/Unit") &&
409  !has_attribute(Dataname + "/Units")) {
410  std::string u = read_attribute<std::string>(Dataname + "/Unit");
411  if(u == "Rotation_deg")
412  res = units::deg;
413  else if(u == "Distance_m")
414  res = units::m;
415  else if(u == "Velocity")
416  res = units::m / units::s;
417  else if(u == "Radiance")
418  res = units::W / pow(units::cm, 2) / units::sr / units::inv_cm;
419  else if(u == "Wavelength_microns")
420  res = units::micron;
421  else
422  throw Exception("Unrecognized unit '" + u + " found for attribute "
423  + Dataname + "/Unit");
424  } else
425  // Otherwise, just process the Units string.
426  res = Unit(read_attribute<std::string>(Dataname + "/Units"));
427  return res;
428 }
429 
430 //-----------------------------------------------------------------------
432 //-----------------------------------------------------------------------
433 
434 H5::Attribute HdfFile::create_attribute(const std::string& Aname,
435  const H5::DataSpace& Ds, const H5::DataType& P)
436 {
437  size_t i = Aname.find_last_of('/');
438  if(i == std::string::npos) {
440  e << "The attribute name '" << Aname << "' is not a valid name";
441  throw e;
442  }
443  std::string gname = Aname.substr(0, i);
444  std::string aname = Aname.substr(i + 1);
445  if(!is_present(gname, *h))
446  create_group_if_needed(Aname, *h);
447  if(is_group(gname)) {
448  Group attr_group = h->openGroup(gname);
449  return attr_group.createAttribute(aname, P, Ds);
450  } else {
451  DataSet attr_dataset = h->openDataSet(gname);
452  return attr_dataset.createAttribute(aname, P, Ds);
453  }
454 }
455 
456 //-----------------------------------------------------------------------
461 //-----------------------------------------------------------------------
462 
463 void HdfFile::dimension_metadata(const std::string& Name,
464  const std::string& Description,
465  int Size)
466 {
467  write_attribute("/Dimensions/" + Name + "/Size", Size);
468  write_attribute("/Dimensions/" + Name + "/Description", Description);
469 }
470 
471 //-----------------------------------------------------------------------
476 //-----------------------------------------------------------------------
477 
478 void HdfFile::shape_metadata(const std::string& Name, const std::string& Dim1)
479 {
480  write_attribute("/Shapes/" + Name + "/Rank", 1);
481  write_attribute("/Shapes/" + Name + "/Dimensions", Dim1);
482 }
483 
484 //-----------------------------------------------------------------------
489 //-----------------------------------------------------------------------
490 
491 void HdfFile::shape_metadata(const std::string& Name, const std::string& Dim1,
492  const std::string& Dim2)
493 {
494  write_attribute("/Shapes/" + Name + "/Rank", 2);
495  std::vector<std::string> dim;
496  dim.push_back(Dim1);
497  dim.push_back(Dim2);
498  write_attribute("/Shapes/" + Name + "/Dimensions", dim);
499 }
500 
501 //-----------------------------------------------------------------------
506 //-----------------------------------------------------------------------
507 
508 void HdfFile::shape_metadata(const std::string& Name, const std::string& Dim1,
509  const std::string& Dim2,
510  const std::string& Dim3)
511 {
512  write_attribute("/Shapes/" + Name + "/Rank", 3);
513  std::vector<std::string> dim;
514  dim.push_back(Dim1);
515  dim.push_back(Dim2);
516  dim.push_back(Dim3);
517  write_attribute("/Shapes/" + Name + "/Dimensions", dim);
518 }
519 
520 //-----------------------------------------------------------------------
528 //-----------------------------------------------------------------------
529 
530 void HdfFile::write_type(const std::string& Dataname, const H5::DataType& P)
531 {
532  if(P ==PredType::NATIVE_INT32)
533  write_attribute(Dataname + "/Type", "Int32");
534  else if(P ==PredType::NATIVE_FLOAT)
535  write_attribute(Dataname + "/Type", "Float32");
536  // we just ignore this if we don't recognize the type.
537 }
538 
539 void HdfFile::print(std::ostream& Os) const
540 {
541  Os << "HdfFile: \n"
542  << " File name: " << file_name() << "\n";
543 }
blitz::TinyVector< int, D > read_shape(const std::string &Dataname) const
Reads the shape of a dataset.
Definition: hdf_file.h:553
const Unit s("s", 1.0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0)
blitz::Array< T, D > read_field(const std::string &Dataname) const
Read a given field.
Definition: hdf_file.h:564
bool has_object(const std::string &Objname) const
Check to see if an object (such as a Dataset) is in the file.
Definition: hdf_file.h:48
const Unit cm("cm", 1e-2 *m)
void print(std::ostream &Os) const
Definition: hdf_file.cc:539
Unit read_units(const std::string &Dataname) const
Read the units for a dataset.
Definition: hdf_file.cc:401
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
const Unit sr("sr", 1.0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0)
const Unit J("J", N *m)
const Unit micron("micron", 1e-6 *m)
This class reads and writes a HDF5 file.
Definition: hdf_file.h:39
#define REGISTER_LUA_CLASS(X)
Definition: register_lua.h:116
Apply value function to a blitz array.
const Unit inv_cm("cm^-1", pow(cm, -1))
void dimension_metadata(const std::string &Name, const std::string &Description, int Size)
The SDOS products have a particular metadata convention where the information about each of the Dimen...
Definition: hdf_file.cc:463
const Unit K("K", 1.0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0)
const Unit m("m", 1.0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
Unit pow(const Unit &Dunit, const boost::rational< int > &Exponent)
Definition: unit.cc:158
void write_attribute(const std::string &Aname, const blitz::Array< T, D > &Data)
Write attribute to file.
Definition: hdf_file.h:694
const std::string & file_name() const
File name.
Definition: hdf_file.h:131
const Unit g("g", 1e-3 *kg)
Libraries such as boost::units allow unit handling where we know the units at compile time...
Definition: unit.h:25
HdfFile(const std::string &Fname, Mode M=READ)
Open the given file with the given mode.
Definition: hdf_file.cc:261
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
#define REGISTER_LUA_END()
Definition: register_lua.h:134
ArrayWithUnit< T, D > read_field_with_unit(const std::string &Dataname) const
Read a given field, along with metadata describing the units.
Definition: hdf_file.h:575
void shape_metadata(const std::string &Name, const std::string &Dim1)
The SDOS products have a particular metadata convention where the information about each of the Shape...
Definition: hdf_file.cc:478
bool has_attribute(const std::string &Aname) const
Check to see if a attribute is in the file.
Definition: hdf_file.cc:363
const Unit deg("deg", pi/180.0 *rad)
const Unit W("W", J/s)

Copyright © 2017, California Institute of Technology.
ALL RIGHTS RESERVED.
U.S. Government Sponsorship acknowledged.
Generated Fri Aug 24 2018 15:44:11