ReFRACtor
hdf_file.h
Go to the documentation of this file.
1 #ifndef HDF_FILE_H
2 #define HDF_FILE_H
3 #include "printable.h"
4 #include "fp_exception.h"
5 #include "linear_algebra.h"
6 #include "array_with_unit.h"
7 #include <blitz/array.h>
8 #include <boost/shared_ptr.hpp>
9 #include <H5Cpp.h>
10 #include <vector>
11 #include <stdint.h>
12 #include <string.h>
13 
14 namespace FullPhysics {
15 /****************************************************************/
39 class HdfFile : public Printable<HdfFile> {
40 public:
42  HdfFile(const std::string& Fname, Mode M = READ);
43  virtual ~HdfFile() {}
44 
45 //-----------------------------------------------------------------------
47 //-----------------------------------------------------------------------
48  bool has_object(const std::string& Objname) const
49  { return is_present(Objname, *h); }
50 
51 //-----------------------------------------------------------------------
53 //-----------------------------------------------------------------------
54  bool has_attribute(const std::string& Aname) const;
55 
56  Unit read_units(const std::string& Dataname) const;
57  template<int D> blitz::TinyVector<int,D> read_shape(
58  const std::string& Dataname) const;
59  template<class T, int D> blitz::Array<T, D> read_field(
60  const std::string& Dataname) const;
61  template<class T, int D> ArrayWithUnit<T, D> read_field_with_unit(
62  const std::string& Dataname) const;
63  template<class T, int D> ArrayWithUnit<T, D> read_field_with_unit(
64  const std::string& Dataname, const Unit& Default_unit) const;
65  template<class T, int D> ArrayWithUnit<T, D> read_field_with_unit(
66  const std::string& Dataname,
67  const blitz::TinyVector<int,D>& Start,
68  const blitz::TinyVector<int,D>& Size) const;
69  template<class T, int D> ArrayWithUnit<T, D> read_field_with_unit(
70  const std::string& Dataname, const Unit& Default_unit,
71  const blitz::TinyVector<int,D>& Start,
72  const blitz::TinyVector<int,D>& Size) const;
73  template<class T, int D> blitz::Array<T, D> read_field(
74  const std::string& Dataname,
75  const blitz::TinyVector<int,D>& Start,
76  const blitz::TinyVector<int,D>& Size) const;
77  template<class T> T read_field(
78  const std::string& Dataname) const;
79  template<class T, int D> blitz::Array<T, D>
80  read_attribute(const std::string& Aname) const;
81  template<class T> T read_attribute(const std::string& Aname) const;
82  template<class T, int D> void write_attribute(const std::string& Aname,
83  const blitz::Array<T, D>& Data);
84  template<class T> void write_attribute(const std::string& Aname,
85  const T& Data);
86  void write_attribute(const std::string& Aname, const char* Data);
87  template<class T, int D> void write_field(const std::string& Dataname,
88  const blitz::Array<T, D>& Data);
89  template<int D> inline void write_field(const std::string& Dataname,
90  const blitz::Array<std::string, D>& Data);
91  template<int D> inline void write_field(const std::string& Dataname,
92  const blitz::Array<const char *, D>& Data);
93  template<class T> void write_field(const std::string& Dataname,
94  const T& Data);
95  void write_field(const std::string& Dataname,
96  const std::string& Data);
97  void write_field(const std::string& Dataname,
98  const char* Data);
99  template<class T> void write_field(const std::string& Dataname,
100  const T& Data,
101  H5::DataType P);
102  template<class T, int D> void write_field(const std::string& Dataname,
103  const blitz::Array<T, D>& Data,
104  H5::DataType P);
105  void dimension_metadata(const std::string& Name,
106  const std::string& Description,
107  int Size);
108  void shape_metadata(const std::string& Name, const std::string& Dim1);
109  void shape_metadata(const std::string& Name, const std::string& Dim1,
110  const std::string& Dim2);
111  void shape_metadata(const std::string& Name, const std::string& Dim1,
112  const std::string& Dim2, const std::string& Dim3);
113 
114 //-----------------------------------------------------------------------
116 //-----------------------------------------------------------------------
117 
118  Mode mode() const {return mode_;}
119 
120 //-----------------------------------------------------------------------
124 //-----------------------------------------------------------------------
125 
126  void close() { h->close(); }
127 
128 //-----------------------------------------------------------------------
130 //-----------------------------------------------------------------------
131  const std::string& file_name() const {return fname;}
132 
133 //-----------------------------------------------------------------------
135 //-----------------------------------------------------------------------
136 
137  static bool is_hdf(const std::string& Fname)
138  {
139  try {
140  return H5::H5File::isHdf5(Fname);
141  } catch(const H5::FileIException& e) {
143  err << "Error determining if file: "
144  << Fname << " is an HDF file: "
145  << e.getDetailMsg();
146  throw err;
147  }
148  }
149 
150  // Map native type to type of blitz array
151  template<class T> H5::PredType pred_arr() const;
152  // Map type of blitz array to type of data in file.
153  template<class T> H5::PredType pred_data() const;
154  void print(std::ostream& Os) const;
155  H5::H5File& h5_file() { return *h; };
156  const H5::H5File& h5_file() const { return *h; };
157 private:
159  std::string fname;
160  Mode mode_;
161 
162 // In HDF5 1.10: "CommonFG will be deprecated in future releases. In 1.10.1, most member functions are moved to H5Location."
163 #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR >= 10 && H5_VERS_RELEASE >= 1
164  void create_group_if_needed(const std::string& Dataname,
165  H5::H5Location& Parent);
166 #else
167  void create_group_if_needed(const std::string& Dataname,
168  H5::CommonFG& Parent);
169 #endif
170  H5::Attribute open_attribute(const std::string& Aname) const;
171  H5::Attribute create_attribute(const std::string& Aname,
172  const H5::DataSpace& Ds, const H5::DataType& P);
173  bool is_group(const std::string& Objname) const;
174 #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR >= 10 && H5_VERS_RELEASE >= 1
175  bool is_present(const std::string& Objname,
176  const H5::H5Location& Parent) const;
177 #else
178  bool is_present(const std::string& Objname,
179  const H5::CommonFG& Parent) const;
180 #endif
181  void write_type(const std::string& Dataname, const H5::DataType& P);
182 };
183 
184 template<> inline H5::PredType HdfFile::pred_arr<int>() const
185 {return H5::PredType::NATIVE_INT;}
186 template<> inline H5::PredType HdfFile::pred_arr<int64_t>() const
187 {return H5::PredType::NATIVE_INT64;}
188 template<> inline H5::PredType HdfFile::pred_arr<double>() const
189 {return H5::PredType::NATIVE_DOUBLE;}
190 template<> inline H5::PredType HdfFile::pred_arr<float>() const
191 {return H5::PredType::NATIVE_FLOAT;}
192 template<> inline H5::PredType HdfFile::pred_data<int>() const
193 {return H5::PredType::NATIVE_INT32;}
194 template<> inline H5::PredType HdfFile::pred_data<int64_t>() const
195 {return H5::PredType::NATIVE_INT64;}
196 template<> inline H5::PredType HdfFile::pred_data<double>() const
197 {return H5::PredType::NATIVE_DOUBLE;}
198 template<> inline H5::PredType HdfFile::pred_data<float>() const
199 {return H5::PredType::NATIVE_FLOAT;}
200 
201 //-----------------------------------------------------------------------
203 //-----------------------------------------------------------------------
204 
205 template<class T, int D> inline blitz::Array<T, D>
206 HdfFile::read_attribute(const std::string& Aname) const
207 {
208  try {
209  using namespace H5;
210  Attribute a = open_attribute(Aname);
211  DataSpace ds = a.getSpace();
212  if(ds.getSimpleExtentNdims() != D) {
213  Exception e;
214  e << "Attribute " << Aname << " does not have the expected rank of "
215  << D;
216  throw e;
217  }
218  hsize_t dims[D];
219  ds.getSimpleExtentDims(dims, NULL);
220  blitz::TinyVector<int,D> dims2;
221  for(int i = 0; i < D; ++i)
222  dims2(i) = (int) dims[i];
223  blitz::Array<T, D> res(dims2);
224  a.read(pred_arr<T>(), res.dataFirst());
225  return res;
226  } catch(const H5::Exception& e) {
227  Exception en;
228  en << "While reading attribute " << Aname
229  << " for the file '" << fname
230  << "' a HDF 5 Exception thrown:\n"
231  << " " << e.getDetailMsg();
232  throw en;
233  }
234 }
235 
236 //-----------------------------------------------------------------------
238 //-----------------------------------------------------------------------
239 
240 template<class T> inline T
241 HdfFile::read_attribute(const std::string& Aname) const
242 {
243  return read_attribute<T, 1>(Aname)(0);
244 }
245 
246 //-----------------------------------------------------------------------
248 //-----------------------------------------------------------------------
249 
250 template<> inline std::string HdfFile::read_attribute<std::string>(const
251  std::string& Aname) const
252 {
253  try {
254  using namespace H5;
255  Attribute a = open_attribute(Aname);
256  std::string res;
257  a.read(a.getStrType(),res);
258  // Fixed length strings may have trailing spaces. Truncate them.
259  size_t t = res.find_last_not_of(" ");
260  if(t != std::string::npos)
261  res.erase(t + 1);
262  return res;
263  } catch(const H5::Exception& e) {
264  Exception en;
265  en << "While reading attribute " << Aname
266  << " for the file '" << fname
267  << "' a HDF 5 Exception thrown:\n"
268  << " " << e.getDetailMsg();
269  throw en;
270  }
271 }
272 
273 //-----------------------------------------------------------------------
275 //-----------------------------------------------------------------------
276 
277 template<> inline std::vector<std::string>
278 HdfFile::read_attribute<std::vector<std::string> >(const
279  std::string& Aname) const
280 {
281  try {
282  using namespace H5;
283  Attribute a = open_attribute(Aname);
284  DataSpace ds = a.getSpace();
285  if(ds.getSimpleExtentNdims() != 1) {
286  Exception e;
287  e << "Attribute " << Aname << " does not have the expected rank of 1";
288  throw e;
289  }
290  hsize_t dims[1];
291  ds.getSimpleExtentDims(dims, NULL);
292  int nelem = (int) dims[0];
293  std::vector<char*> ptr(nelem);
294  a.read(a.getStrType(),&(*ptr.begin()));
295  std::vector<std::string> res(nelem);
296  for(int i = 0; i < nelem; ++i) {
297  res[i] = std::string(ptr[i]);
298  // Fixed length strings may have trailing spaces. Truncate them.
299  size_t t = res[i].find_last_not_of(" ");
300  if(t != std::string::npos)
301  res[i].erase(t + 1);
302  }
303  return res;
304  } catch(const H5::Exception& e) {
305  Exception en;
306  en << "While reading attribute " << Aname
307  << " for the file '" << fname
308  << "' a HDF 5 Exception thrown:\n"
309  << " " << e.getDetailMsg();
310  throw en;
311  }
312 }
313 
314 //-----------------------------------------------------------------------
315 // Somewhat annoyingly, C++ doesn't allow function partial
316 // specialization. Introduce a class as a roundabout way to do this,
317 // since we can do partial template specialization of a class.
318 //-----------------------------------------------------------------------
319 // Don't have Doxygen document this class.
321 template<int D> class HdfFilePartialDimHelper {
322 public:
323 
324 blitz::TinyVector<int,D> read_shape(const HdfFile& hf,
325  const H5::H5File& h,
326  const std::string& Dataname) const
327 {
328  try {
329  using namespace H5;
330  DataSet d = h.openDataSet(Dataname);
331  DataSpace ds = d.getSpace();
332  if(ds.getSimpleExtentNdims() != D) {
333  Exception e;
334  e << "Dataset " << Dataname << " does not have the expected rank of "
335  << D;
336  throw e;
337  }
338  hsize_t dims[D];
339  ds.getSimpleExtentDims(dims, NULL);
340  blitz::TinyVector<int,D> dims2;
341  for(int i = 0; i < D; ++i)
342  dims2(i) = (int) dims[i];
343  return dims2;
344  } catch(const H5::Exception& e) {
345  Exception en;
346  en << "While reading shape " << Dataname
347  << " for the file '" << hf.file_name()
348  << "' a HDF 5 Exception thrown:\n"
349  << " " << e.getDetailMsg();
350  throw en;
351  }
352 }
353 
354 };
355 
356 template<class T, int D> class HdfFilePartialSpecialHelper {
357 public:
358 
359 blitz::Array<T, D> read_field(const HdfFile& hf,
360  const H5::H5File& h,
361  const std::string& Dataname) const
362 {
363  try {
364  using namespace H5;
365  DataSet d = h.openDataSet(Dataname);
366  DataSpace ds = d.getSpace();
367  if(ds.getSimpleExtentNdims() != D) {
368  Exception e;
369  e << "Dataset " << Dataname << " does not have the expected rank of "
370  << D;
371  throw e;
372  }
373  hsize_t dims[D];
374  ds.getSimpleExtentDims(dims, NULL);
375  blitz::TinyVector<int,D> dims2;
376  for(int i = 0; i < D; ++i)
377  dims2(i) = (int) dims[i];
378  blitz::Array<T, D> res(dims2);
379  d.read(res.dataFirst(), hf.pred_arr<T>());
380  return res;
381  } catch(const H5::Exception& e) {
382  Exception en;
383  en << "While reading field " << Dataname
384  << " for the file '" << hf.file_name()
385  << "' a HDF 5 Exception thrown:\n"
386  << " " << e.getDetailMsg();
387  throw en;
388  }
389 }
390 
391 blitz::Array<T, D> read_field(const HdfFile& hf,
392  const H5::H5File& h,
393  const std::string& Dataname,
394  const blitz::TinyVector<hsize_t,D>& Start,
395  const blitz::TinyVector<hsize_t,D>& Size) const
396 {
397  try {
398  using namespace H5;
399  DataSet d = h.openDataSet(Dataname);
400  DataSpace ds = d.getSpace();
401  if(ds.getSimpleExtentNdims() != D) {
402  Exception e;
403  e << "Dataset " << Dataname << " does not have the expected rank of "
404  << D;
405  throw e;
406  }
407  DataSpace ms(D, &Size[0]);
408  ds.selectHyperslab(H5S_SELECT_SET, &Size[0], &Start[0]);
409  blitz::Array<T, D> res(Size);
410  d.read(res.dataFirst(), hf.pred_arr<T>(), ms, ds);
411  return res;
412  } catch(const H5::Exception& e) {
413  Exception en;
414  en << "While reading field " << Dataname
415  << " for the file '" << hf.file_name()
416  << "' a HDF 5 Exception thrown:\n"
417  << " " << e.getDetailMsg();
418  throw en;
419  }
420 }
421 
422 };
423 
424 template<int D> class HdfFilePartialSpecialHelper<std::string, D> {
425 public:
426 blitz::Array<std::string, D> read_field(const HdfFile& hf,
427  const H5::H5File& h,
428  const std::string& Dataname) const
429 {
430  try {
431  using namespace H5;
432  DataSet d = h.openDataSet(Dataname);
433  DataSpace ds = d.getSpace();
434  if(ds.getSimpleExtentNdims() != D) {
435  Exception e;
436  e << "Dataset " << Dataname << " does not have the expected rank of "
437  << D;
438  throw e;
439  }
440  hsize_t dims[D];
441  ds.getSimpleExtentDims(dims, NULL);
442  blitz::TinyVector<int,D> dims2;
443  for(int i = 0; i < D; ++i)
444  dims2(i) = (int) dims[i];
445 
446  DataType dt = d.getDataType();
447  blitz::Array<std::string, D> result_data(dims2);
448  if(dt.isVariableStr()) {
449  blitz::Array<const char*, D> read_data(result_data.shape());
450  StrType st(PredType::C_S1, H5T_VARIABLE);
451  d.read(read_data.dataFirst(), st);
452 
453  typename blitz::Array<const char*, D>::const_iterator i1;
454  typename blitz::Array<std::string, D>::iterator i2 = result_data.begin();
455  for(i1 = read_data.begin(); i1 != read_data.end(); ++i1, ++i2)
456  *i2 = std::string(*i1);
457  } else {
458  int flat_size = 1;
459  for(int i = 0; i < D; i++)
460  flat_size *= dims2[i];
461  flat_size *= dt.getSize();
462  blitz::Array<char, 1> read_data(flat_size);
463  d.read(read_data.dataFirst(), d.getStrType());
464 
465  char* i1 = read_data.dataFirst();
466  typename blitz::Array<std::string, D>::iterator i2;
467  for(i2 = result_data.begin(); i2 != result_data.end();
468  ++i2, i1 += dt.getSize()) {
469  // By our fairly odd convention, this string may contain a
470  // trailing '\0'. So we strip that off if we find it.
471  std::string s(i1, i1 + dt.getSize());
472  *i2 = std::string(s.c_str());
473  }
474  }
475  return result_data;
476  } catch(const H5::Exception& e) {
477  Exception en;
478  en << "While reading field " << Dataname
479  << " for the file '" << hf.file_name()
480  << "' a HDF 5 Exception thrown:\n"
481  << " " << e.getDetailMsg();
482  throw en;
483  }
484 }
485 
486 blitz::Array<std::string, D> read_field(const HdfFile& hf,
487  const H5::H5File& h,
488  const std::string& Dataname,
489  const blitz::TinyVector<hsize_t,D>& Start,
490  const blitz::TinyVector<hsize_t,D>& Size) const
491 {
492  try {
493  using namespace H5;
494  DataSet d = h.openDataSet(Dataname);
495  DataSpace ds = d.getSpace();
496  if(ds.getSimpleExtentNdims() != D) {
497  Exception e;
498  e << "Dataset " << Dataname << " does not have the expected rank of "
499  << D;
500  throw e;
501  }
502  DataSpace ms(D, &Size[0]);
503  ds.selectHyperslab(H5S_SELECT_SET, &Size[0], &Start[0]);
504  DataType dt = d.getDataType();
505  blitz::Array<std::string, D> result_data(Size);
506  if(dt.isVariableStr()) {
507  blitz::Array<const char*, D> read_data(result_data.shape());
508  StrType st(PredType::C_S1, H5T_VARIABLE);
509  d.read(read_data.dataFirst(), st, ms, ds);
510 
511  typename blitz::Array<const char*, D>::const_iterator i1;
512  typename blitz::Array<std::string, D>::iterator i2 = result_data.begin();
513  for(i1 = read_data.begin(); i1 != read_data.end(); ++i1, ++i2)
514  *i2 = std::string(*i1);
515  } else {
516  int flat_size = 1;
517  for(int i = 0; i < D; i++)
518  flat_size *= Size(i);
519  flat_size *= dt.getSize();
520  blitz::Array<char, 1> read_data(flat_size);
521  d.read(read_data.dataFirst(), d.getStrType(), ms, ds);
522 
523  char* i1 = read_data.dataFirst();
524  typename blitz::Array<std::string, D>::iterator i2;
525  for(i2 = result_data.begin(); i2 != result_data.end();
526  ++i2, i1 += dt.getSize()) {
527  // By our fairly odd convention, this string may contain a
528  // trailing '\0'. So we strip that off if we find it.
529  std::string s(i1, i1 + dt.getSize());
530  *i2 = std::string(s.c_str());
531  }
532  }
533  return result_data;
534  } catch(const H5::Exception& e) {
535  Exception en;
536  en << "While reading field " << Dataname
537  << " for the file '" << hf.file_name()
538  << "' a HDF 5 Exception thrown:\n"
539  << " " << e.getDetailMsg();
540  throw en;
541  }
542 }
543 
544 };
545 
547 
548 
549 //-----------------------------------------------------------------------
551 //-----------------------------------------------------------------------
552 template<int D> inline blitz::TinyVector<int,D>
553 HdfFile::read_shape(const std::string& Dataname) const
554 {
555  HdfFilePartialDimHelper<D> helper;
556  return helper.read_shape(*this, *h, Dataname);
557 }
558 
559 //-----------------------------------------------------------------------
561 //-----------------------------------------------------------------------
562 
563 template<class T, int D> inline blitz::Array<T, D>
564 HdfFile::read_field(const std::string& Dataname) const
565 {
566  HdfFilePartialSpecialHelper<T,D> helper;
567  return helper.read_field(*this, *h, Dataname);
568 }
569 
570 //-----------------------------------------------------------------------
572 //-----------------------------------------------------------------------
573 
574 template<class T, int D> inline ArrayWithUnit<T, D>
575 HdfFile::read_field_with_unit(const std::string& Dataname) const
576 {
578  res.value.reference(read_field<T, D>(Dataname));
579  res.units = read_units(Dataname);
580  return res;
581 }
582 
583 //-----------------------------------------------------------------------
585 // With a start and size given.
586 //-----------------------------------------------------------------------
587 
588 template<class T, int D> inline ArrayWithUnit<T, D>
589 HdfFile::read_field_with_unit(const std::string& Dataname,
590  const blitz::TinyVector<int,D>& Start,
591  const blitz::TinyVector<int,D>& Size) const
592 {
594  res.data.reference(read_field<T, D>(Dataname, Start, Size));
595  res.units = read_units(Dataname);
596  return res;
597 }
598 
599 //-----------------------------------------------------------------------
604 //-----------------------------------------------------------------------
605 
606 template<class T, int D> inline ArrayWithUnit<T, D>
608 (const std::string& Dataname, const Unit& Default_unit) const
609 {
611  res.value.reference(read_field<T, D>(Dataname));
612  if(!has_attribute(Dataname + "/Unit") &&
613  !has_attribute(Dataname + "/Units"))
614  res.units = Default_unit;
615  else
616  res.units = read_units(Dataname);
617  return res;
618 }
619 
620 //-----------------------------------------------------------------------
622 //-----------------------------------------------------------------------
623 
624 template<class T, int D> inline ArrayWithUnit<T, D>
626 (const std::string& Dataname, const Unit& Default_unit,
627  const blitz::TinyVector<int,D>& Start,
628  const blitz::TinyVector<int,D>& Size) const
629 {
631  res.value.reference(read_field<T, D>(Dataname, Start, Size));
632  if(!has_attribute(Dataname + "/Unit") &&
633  !has_attribute(Dataname + "/Units"))
634  res.units = Default_unit;
635  else
636  res.units = read_units(Dataname);
637  return res;
638 }
639 
640 //-----------------------------------------------------------------------
643 //-----------------------------------------------------------------------
644 
645 template<class T, int D> blitz::Array<T, D>
647  const std::string& Dataname,
648  const blitz::TinyVector<int,D>& Start,
649  const blitz::TinyVector<int,D>& Size) const
650 {
651  HdfFilePartialSpecialHelper<T,D> helper;
652  blitz::TinyVector<hsize_t, D> start2, size2;
653  start2 = Start;
654  size2 = Size;
655  return helper.read_field(*this, *h, Dataname, start2, size2);
656 }
657 
658 //-----------------------------------------------------------------------
661 //-----------------------------------------------------------------------
662 
663 template<class T> inline
664 T HdfFile::read_field(const std::string& Dataname) const
665 {
666  try {
667  using namespace H5;
668  DataSet d = h->openDataSet(Dataname);
669  DataSpace ds = d.getSpace();
670  T res;
671  d.read(&res, pred_arr<T>());
672  return res;
673  } catch(const H5::Exception& e) {
674  Exception en;
675  en << "While reading field " << Dataname
676  << " for the file '" << file_name()
677  << "' a HDF 5 Exception thrown:\n"
678  << " " << e.getDetailMsg();
679  throw en;
680  }
681 }
682 
683 template<> inline
684 std::string HdfFile::read_field(const std::string& Dataname) const
685 {
686  return read_field<std::string, 1>(Dataname)(0);
687 }
688 
689 //-----------------------------------------------------------------------
691 //-----------------------------------------------------------------------
692 
693 template<class T, int D> inline
694 void HdfFile::write_attribute(const std::string& Aname,
695  const blitz::Array<T, D>& Data)
696 {
697  try {
698  using namespace H5;
699  blitz::Array<T, D> data2 = to_c_order_const(Data);
700  hsize_t dim[D];
701  for(int i = 0; i < D; ++i)
702  dim[i] = Data.extent(i);
703  DataSpace ds(D, dim);
704  Attribute a = create_attribute(Aname, ds, pred_data<T>());
705  a.write(pred_arr<T>(), data2.dataFirst());
706  } catch(const H5::Exception& e) {
707  Exception en;
708  en << "While writing attribute " << Aname
709  << " for the file '" << fname
710  << "' a HDF 5 Exception thrown:\n"
711  << " " << e.getDetailMsg();
712  throw en;
713  }
714 }
715 
716 //-----------------------------------------------------------------------
718 //-----------------------------------------------------------------------
719 
720 template<class T> inline
721 void HdfFile::write_attribute(const std::string& Aname,
722  const T& Data)
723 {
724  try {
725  using namespace H5;
726  hsize_t dim[1] = {1};
727  DataSpace ds(1, dim);
728  Attribute a = create_attribute(Aname, ds, pred_data<T>());
729  a.write(pred_arr<T>(), &Data);
730  } catch(const H5::Exception& e) {
731  Exception en;
732  en << "While writing attribute " << Aname
733  << " for the file '" << fname
734  << "' a HDF 5 Exception thrown:\n"
735  << " " << e.getDetailMsg();
736  throw en;
737  }
738 }
739 
740 //-----------------------------------------------------------------------
742 //-----------------------------------------------------------------------
743 
744 template<> inline
745 void HdfFile::write_attribute<std::string>(const std::string& Aname,
746  const std::string& Data)
747 {
748  try {
749  using namespace H5;
750  hsize_t dim[1] = {1};
751  DataSpace ds(1, dim);
752  StrType st(PredType::C_S1, H5T_VARIABLE);
753  Attribute a = create_attribute(Aname, ds, st);
754  a.write(st, Data);
755  } catch(const H5::Exception& e) {
756  Exception en;
757  en << "While writing attribute " << Aname
758  << " for the file '" << fname
759  << "' a HDF 5 Exception thrown:\n"
760  << " " << e.getDetailMsg();
761  throw en;
762  }
763 }
764 
765 //-----------------------------------------------------------------------
767 //-----------------------------------------------------------------------
768 
769 template<> inline
770 void HdfFile::write_attribute<std::vector<std::string> >(const
771  std::string& Aname, const std::vector<std::string>& Data)
772 {
773  try {
774  using namespace H5;
775  int nelem = (int) Data.size();
776  hsize_t dim[1] = {Data.size()};
777  DataSpace ds(1, dim);
778  StrType st(PredType::C_S1, H5T_VARIABLE);
779  Attribute a = create_attribute(Aname, ds, st);
780  std::vector<const char*> ptr(nelem);
781  for(int i = 0; i < nelem; ++i)
782  ptr[i] = Data[i].c_str();
783  a.write(st, &(*ptr.begin()));
784  } catch(const H5::Exception& e) {
785  Exception en;
786  en << "While writing attribute " << Aname
787  << " for the file '" << fname
788  << "' a HDF 5 Exception thrown:\n"
789  << " " << e.getDetailMsg();
790  throw en;
791  }
792 }
793 
794 //-----------------------------------------------------------------------
797 //-----------------------------------------------------------------------
798 
799 template<class T, int D> inline void
800 HdfFile::write_field(const std::string& Dataname,
801  const blitz::Array<T, D>& Data)
802 {
803  write_field(Dataname, Data, pred_data<T>());
804 }
805 
806 template<int D> inline void
807 HdfFile::write_field(const std::string& Dataname,
808  const blitz::Array<std::string, D>& Data)
809 {
810  try {
811  using namespace H5;
812  create_group_if_needed(Dataname, *h);
813  hsize_t dim[D];
814  for(int i = 0; i < D; ++i)
815  dim[i] = Data.extent(i);
816  DataSpace ds(D, dim);
817  StrType st(H5::PredType::C_S1, H5T_VARIABLE);
818  DataSet d = h->createDataSet(Dataname, st, ds);
819  blitz::Array<std::string, D> data2 = to_c_order_const(Data);
820  blitz::Array<const char*, D> data3(data2.shape());
821  typename blitz::Array<std::string, D>::const_iterator i1;
822  typename blitz::Array<const char*, D>::iterator i2 = data3.begin();
823  for(i1 = data2.begin(); i1 != data2.end(); ++i1, ++i2)
824  *i2 = i1->c_str();
825  d.write(data3.dataFirst(), st);
826  write_attribute(Dataname + "/Type", "VarLenStr");
827  } catch(const H5::Exception& e) {
828  Exception en;
829  en << "While writing field " << Dataname
830  << " for the file '" << fname
831  << "' a HDF 5 Exception thrown:\n"
832  << " " << e.getDetailMsg();
833  throw en;
834  }
835 }
836 
837 template<int D> inline void
838 HdfFile::write_field(const std::string& Dataname,
839  const blitz::Array<const char*, D>& Data)
840 {
841  try {
842  using namespace H5;
843 
844  // Figure out maximum length for char* since we
845  // are creating a fixed length string dataset
846  int max_len = 0;
847  typename blitz::Array<const char*, D>::const_iterator i1;
848  for(i1 = Data.begin(); i1 != Data.end(); ++i1)
849  max_len = std::max((int) strlen(*i1), max_len);
850  // +1 for fairly odd convention of add a "\0" at the end
851  H5::StrType dtype = H5::StrType(H5::PredType::C_S1, max_len + 1);
852 
853  create_group_if_needed(Dataname, *h);
854  hsize_t dim[D];
855  int flat_size = 1;
856  for(int i = 0; i < D; ++i) {
857  dim[i] = Data.extent(i);
858  flat_size *= Data.extent(i);
859  }
860 
861  DataSpace ds(D, dim);
862  DataSet d = h->createDataSet(Dataname, dtype, ds);
863 
864  // Copy string data to a flattened version as expected
865  // by HDF5 library
866  blitz::Array<char, 2> data2(flat_size, max_len + 1);
867  data2 = ' ';
868  data2(blitz::Range::all(), max_len) = '\0';
869  typename blitz::Array<char, 2>::iterator i2 = data2.begin();
870  for(i1 = Data.begin(); i1 != Data.end(); ++i1) {
871  strcpy(&(*i2), *i1);
872  for(int j = 0; j < max_len + 1; j++)
873  i2++;
874  }
875 
876  d.write(data2.dataFirst(), dtype);
877  write_type(Dataname, dtype);
878  } catch(const H5::Exception& e) {
879  Exception en;
880  en << "While writing field " << Dataname
881  << " for the file '" << fname
882  << "' a HDF 5 Exception thrown:\n"
883  << " " << e.getDetailMsg();
884  throw en;
885  }
886 }
887 
888 inline void HdfFile::write_attribute(const std::string& Aname, const char* Data)
889 { write_attribute(Aname, std::string(Data)); }
890 
891 //-----------------------------------------------------------------------
897 //-----------------------------------------------------------------------
898 
899 template<class T, int D> inline void
900 HdfFile::write_field(const std::string& Dataname,
901  const blitz::Array<T, D>& Data,
902  H5::DataType P)
903 {
904  try {
905  using namespace H5;
906  create_group_if_needed(Dataname, *h);
907  hsize_t dim[D];
908  for(int i = 0; i < D; ++i)
909  dim[i] = Data.extent(i);
910  DataSpace ds(D, dim);
911  DataSet d = h->createDataSet(Dataname, P, ds);
912  blitz::Array<T, D> data2 = to_c_order_const(Data);
913  d.write(data2.dataFirst(), pred_arr<T>());
914  write_type(Dataname, P);
915  } catch(const H5::Exception& e) {
916  Exception en;
917  en << "While writing field " << Dataname
918  << " for the file '" << fname
919  << "' a HDF 5 Exception thrown:\n"
920  << " " << e.getDetailMsg();
921  throw en;
922  }
923 }
924 
925 //-----------------------------------------------------------------------
933 //-----------------------------------------------------------------------
934 template<class T> inline void HdfFile::write_field(const std::string& Dataname,
935  const T& Data)
936 {
937  write_field(Dataname, Data, pred_data<T>());
938 }
939 
940 inline void HdfFile::write_field(const std::string& Dataname,
941  const std::string& Data)
942 {
943  try {
944  using namespace H5;
945  create_group_if_needed(Dataname, *h);
946  hsize_t dim[1] = {1};
947  DataSpace ds(1, dim);
948  StrType st(PredType::C_S1, H5T_VARIABLE);
949  DataSet d = h->createDataSet(Dataname, st, ds);
950  const char* data2 = Data.c_str();
951  d.write(&data2, st);
952  write_attribute(Dataname + "/Type", "VarLenStr");
953  } catch(const H5::Exception& e) {
954  Exception en;
955  en << "While writing field " << Dataname
956  << " for the file '" << fname
957  << "' a HDF 5 Exception thrown:\n"
958  << " " << e.getDetailMsg();
959  throw en;
960  }
961 }
962 
963 inline void HdfFile::write_field(const std::string& Dataname,
964  const char* Data)
965 {
966  try {
967  using namespace H5;
968  create_group_if_needed(Dataname, *h);
969  hsize_t dim[1] = {1};
970  DataSpace ds(1, dim);
971  // +1 is for the odd convention of including the trailing "\0" in
972  // the data.
973  H5::StrType dtype = H5::StrType(H5::PredType::C_S1, strlen(Data) + 1);
974  DataSet d = h->createDataSet(Dataname, dtype, ds);
975  d.write(Data, dtype);
976  write_type(Dataname, dtype);
977  } catch(const H5::Exception& e) {
978  Exception en;
979  en << "While writing field " << Dataname
980  << " for the file '" << fname
981  << "' a HDF 5 Exception thrown:\n"
982  << " " << e.getDetailMsg();
983  throw en;
984  }
985 }
986 
987 //-----------------------------------------------------------------------
995 //-----------------------------------------------------------------------
996 template<class T> inline void HdfFile::write_field(const std::string& Dataname,
997  const T& Data,
998  H5::DataType P)
999 {
1000  try {
1001  using namespace H5;
1002  create_group_if_needed(Dataname, *h);
1003  hsize_t dim[1] = {1};
1004  DataSpace ds(1, dim);
1005  DataSet d = h->createDataSet(Dataname, P, ds);
1006  d.write(&Data, pred_arr<T>());
1007  write_type(Dataname, P);
1008  } catch(const H5::Exception& e) {
1009  Exception en;
1010  en << "While writing field " << Dataname
1011  << " for the file '" << fname
1012  << "' a HDF 5 Exception thrown:\n"
1013  << " " << e.getDetailMsg();
1014  throw en;
1015  }
1016 }
1017 
1018 }
1019 #endif
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)
We frequently have a array of numbers with units associated with them.
blitz::Array< T, D > read_field(const std::string &Dataname) const
Read a given field.
Definition: hdf_file.h:564
void close()
Close the underlying file.
Definition: hdf_file.h:126
H5::PredType pred_arr() const
void write_field(const std::string &Dataname, const blitz::Array< T, D > &Data)
Write a given field.
Definition: hdf_file.h:800
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
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
static bool is_hdf(const std::string &Fname)
Return true if the given file is an HDF file.
Definition: hdf_file.h:137
blitz::Array< T, D > to_c_order_const(const blitz::Array< T, D > &In)
Ensure that a given blitz::Array is contiguous, not reversed, and in C RowMajorArray format...
This is a Mixin for classes that can be printed.
Definition: printable.h:24
blitz::Array< T, D > value
This class reads and writes a HDF5 file.
Definition: hdf_file.h:39
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
H5::PredType pred_data() const
Mode mode() const
Mode file was opened with.
Definition: hdf_file.h:118
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
Libraries such as boost::units allow unit handling where we know the units at compile time...
Definition: unit.h:25
blitz::Array< T, D > read_attribute(const std::string &Aname) const
Read the given attribute attached to a group or dataset.
Definition: hdf_file.h:206
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
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
const H5::H5File & h5_file() const
Definition: hdf_file.h:156
H5::H5File & h5_file()
Definition: hdf_file.h:155
bool has_attribute(const std::string &Aname) const
Check to see if a attribute is in the file.
Definition: hdf_file.cc:363
virtual ~HdfFile()
Definition: hdf_file.h:43

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