MCKL
Monte Carlo Kernel Library
hdf5.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/utility/hdf5.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_UTILITY_HDF5_HPP
33 #define MCKL_UTILITY_HDF5_HPP
34 
35 #include <mckl/internal/common.hpp>
36 #include <mckl/core/matrix.hpp>
37 #include <hdf5.h>
38 
39 extern "C" inline ::herr_t mckl_hdf5_add_link(
40  ::hid_t, const char *name, const ::H5L_info_t *, void *opdata)
41 {
42  auto links = reinterpret_cast<std::vector<std::string> *>(opdata);
43  links->emplace_back(name);
44 
45  return 0;
46 }
47 
48 extern "C" inline ::herr_t mckl_hdf5_inc_link(
49  ::hid_t, const char *, const ::H5L_info_t *, void *opdata)
50 {
51  auto links = reinterpret_cast<std::size_t *>(opdata);
52  ++(*links);
53 
54  return 0;
55 }
56 
57 namespace mckl {
58 
61 template <typename Derived>
62 class HDF5ID
63 {
64  public:
65  HDF5ID() : id_(-1) {}
66 
67  explicit HDF5ID(::hid_t id) : id_(id) {}
68 
69  HDF5ID(const HDF5ID &other)
70  : id_(other.good() ? Derived::copy(other.id_) : other.id_)
71  {
72  }
73 
74  HDF5ID &operator=(const HDF5ID &other)
75  {
76  if (this != &other) {
77  if (good()) {
78  Derived::close(id_);
79  }
80  id_ = other.good() ? Derived::copy(other.id_) : other.id_;
81  }
82 
83  return *this;
84  }
85 
86  HDF5ID(HDF5ID &&other) : id_(other.id_) { other.id_ = -1; }
87 
89  {
90  std::swap(id_, other.id_);
91  return *this;
92  }
93 
95  {
96  if (good()) {
97  Derived::close(id_);
98  }
99  }
100 
101  ::hid_t id() const { return id_; }
102  bool good() const { return id_ >= 0; }
103  bool operator!() const { return !good(); }
104  explicit operator bool() const { return good(); }
105 
106  protected:
108 }; // class HDF5ID
109 
110 class HDF5File;
111 class HDF5Group;
112 class HDF5DataType;
113 class HDF5DataSpace;
114 class HDF5Attribute;
115 class HDF5DataSet;
116 class HDF5PropertyList;
117 
125 inline bool hdf5_error_printing(bool enabled)
126 {
127  ::H5E_auto2_t f = nullptr;
128  ::H5Eget_auto2(H5E_DEFAULT, &f, nullptr);
129  if (enabled) {
130  ::H5Eset_auto2(
131  H5E_DEFAULT, reinterpret_cast<::H5E_auto2_t>(::H5Eprint2), stderr);
132  } else {
133  ::H5Eset_auto2(H5E_DEFAULT, nullptr, nullptr);
134  }
135 
136  return f != nullptr;
137 }
138 
141 class HDF5File : public HDF5ID<HDF5File>
142 {
143  public:
145 
146  HDF5File() = default;
147 
149  explicit HDF5File(const std::string &filename) : HDF5ID<HDF5File>(-1)
150  {
151  bool print_error = hdf5_error_printing(false);
152  id_ = ::H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
153  hdf5_error_printing(print_error);
154  if (!good()) {
155  id_ = ::H5Fcreate(
156  filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
157  }
158  }
159 
165  HDF5File(const std::string &filename, bool append)
166  : HDF5ID<HDF5File>(append ?
167  ::H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT) :
168  ::H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT,
169  H5P_DEFAULT))
170  {
171  }
172 
179  HDF5File(const std::string &filename, bool append, bool read_only)
180  : HDF5ID<HDF5File>(append ?
181  ::H5Fopen(filename.c_str(),
182  (read_only ? H5F_ACC_RDONLY : H5F_ACC_RDWR),
183  H5P_DEFAULT) :
184  ::H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT,
185  H5P_DEFAULT))
186  {
187  }
188 
189  static ::hid_t copy(::hid_t) = delete;
190 
191  static void close(::hid_t id) { ::H5Fclose(id); }
192 }; // class HDF5File
193 
196 class HDF5Group : public HDF5ID<HDF5Group>
197 {
198  public:
200 
201  HDF5Group() = default;
202 
204  HDF5Group(const HDF5File &file, const std::string &groupname)
205  : HDF5ID<HDF5Group>(-1)
206  {
207  if (!file) {
208  return;
209  }
210  bool print_error = hdf5_error_printing(false);
211  id_ = ::H5Gopen2(file.id(), groupname.c_str(), H5P_DEFAULT);
212  hdf5_error_printing(print_error);
213  if (!good()) {
214  id_ = ::H5Gcreate2(file.id(), groupname.c_str(), H5P_DEFAULT,
215  H5P_DEFAULT, H5P_DEFAULT);
216  }
217  }
218 
220  HDF5Group(const HDF5Group &group, const std::string &groupname)
221  : HDF5ID<HDF5Group>(-1)
222  {
223  if (!group) {
224  return;
225  }
226  bool print_error = hdf5_error_printing(false);
227  id_ = ::H5Gopen2(group.id(), groupname.c_str(), H5P_DEFAULT);
228  hdf5_error_printing(print_error);
229  if (!good()) {
230  id_ = ::H5Gcreate2(group.id(), groupname.c_str(), H5P_DEFAULT,
231  H5P_DEFAULT, H5P_DEFAULT);
232  }
233  }
234 
236  std::vector<std::string> links() const
237  {
238  std::vector<std::string> links;
239  ::H5Literate(id_, H5_INDEX_NAME, H5_ITER_INC, nullptr,
240  mckl_hdf5_add_link, &links);
241 
242  return links;
243  }
244 
246  std::size_t size() const
247  {
248  std::size_t links = 0;
249  ::H5Literate(id_, H5_INDEX_NAME, H5_ITER_INC, nullptr,
250  mckl_hdf5_inc_link, &links);
251 
252  return links;
253  }
254 
255  static ::hid_t copy(::hid_t) = delete;
256 
257  static void close(::hid_t id) { ::H5Gclose(id); }
258 }; // class HDF5Group
259 
262 class HDF5DataType : public HDF5ID<HDF5DataType>
263 {
264  public:
266 
267  HDF5DataType() = default;
268 
269  explicit HDF5DataType(const HDF5DataSet &);
270 
271  bool commit(const HDF5File &file, const std::string &name) const
272  {
273  return ::H5Tcommit2(file.id(), name.c_str(), id_, H5P_DEFAULT,
274  H5P_DEFAULT, H5P_DEFAULT);
275  }
276 
277  bool commit(const HDF5Group &group, const std::string &name) const
278  {
279  return ::H5Tcommit2(group.id(), name.c_str(), id_, H5P_DEFAULT,
280  H5P_DEFAULT, H5P_DEFAULT);
281  }
282 
283  void size(std::size_t s) const { ::H5Tset_size(id_, s); }
284 
285  std::size_t size() const { return ::H5Tget_size(id_); }
286 
287  static ::hid_t copy(::hid_t id) { return ::H5Tcopy(id); }
288 
289  static void close(::hid_t id) { ::H5Tclose(id); }
290 }; // class HDF5DataType
291 
294 class HDF5DataSpace : public HDF5ID<HDF5DataSpace>
295 {
296  public:
298 
299  HDF5DataSpace() = default;
300 
301  explicit HDF5DataSpace(
302  int rank, ::hsize_t *dim, ::hsize_t *maxdims = nullptr)
303  : HDF5ID<HDF5DataSpace>(::H5Screate_simple(rank, dim, maxdims))
304  {
305  }
306 
307  std::size_t npoints() const
308  {
309  return static_cast<std::size_t>(::H5Sget_simple_extent_npoints(id_));
310  }
311 
312  std::size_t ndims() const
313  {
314  return static_cast<std::size_t>(::H5Sget_simple_extent_ndims(id_));
315  }
316 
317  std::size_t dims(::hsize_t *dest) const
318  {
319  return static_cast<std::size_t>(
320  ::H5Sget_simple_extent_dims(id_, dest, nullptr));
321  }
322 
323  static ::hid_t copy(::hid_t) = delete;
324 
325  static void close(::hid_t id) { ::H5Sclose(id); }
326 }; // class HDF5DataSpace
327 
330 class HDF5Attribute : public HDF5ID<HDF5Attribute>
331 {
332  public:
334 
335  HDF5Attribute() = default;
336 
337  HDF5Attribute(const HDF5File &file, const std::string &name)
339  ::H5Aopen(file.id(), name.c_str(), H5P_DEFAULT))
340  {
341  }
342 
343  HDF5Attribute(const HDF5Group &group, const std::string &name)
345  ::H5Aopen(group.id(), name.c_str(), H5P_DEFAULT))
346  {
347  }
348 
349  HDF5Attribute(const HDF5File &file, const std::string &name,
350  const HDF5DataType &type, const HDF5DataSpace &space)
351  : HDF5ID<HDF5Attribute>(::H5Acreate2(file.id(), name.c_str(),
352  type.id(), space.id(), H5P_DEFAULT, H5P_DEFAULT))
353  {
354  }
355 
356  HDF5Attribute(const HDF5Group &group, const std::string &name,
357  const HDF5DataType &type, const HDF5DataSpace &space)
358  : HDF5ID<HDF5Attribute>(::H5Acreate2(group.id(), name.c_str(),
359  type.id(), space.id(), H5P_DEFAULT, H5P_DEFAULT))
360  {
361  }
362 
363  HDF5DataSpace space() const { return HDF5DataSpace(::H5Aget_space(id_)); }
364 
365  HDF5DataType type() const { return HDF5DataType(::H5Aget_type(id_)); }
366 
367  bool write(const HDF5DataType &type, const void *mem) const
368  {
369  if (this->space().npoints() == 0) {
370  return false;
371  }
372 
373  return ::H5Awrite(id_, type.id(), mem) >= 0;
374  }
375 
376  bool read(const HDF5DataType &type, void *mem) const
377  {
378  if (this->space().npoints() == 0) {
379  return false;
380  }
381 
382  return ::H5Aread(id_, type.id(), mem) >= 0;
383  }
384 
385  static ::hid_t copy(::hid_t) = delete;
386 
387  static void close(::hid_t id) { ::H5Aclose(id); }
388 }; // class HDF5Attribute
389 
392 class HDF5DataSet : public HDF5ID<HDF5DataSet>
393 {
394  public:
396 
397  HDF5DataSet() = default;
398 
399  HDF5DataSet(const HDF5File &file, const std::string &name)
400  : HDF5ID<HDF5DataSet>(::H5Dopen2(file.id(), name.c_str(), H5P_DEFAULT))
401  {
402  }
403 
404  HDF5DataSet(const HDF5Group &group, const std::string &name)
405  : HDF5ID<HDF5DataSet>(
406  ::H5Dopen2(group.id(), name.c_str(), H5P_DEFAULT))
407  {
408  }
409 
410  HDF5DataSet(const HDF5File &file, const std::string &name,
411  const HDF5DataType &type, const HDF5DataSpace &space)
412  : HDF5ID<HDF5DataSet>(::H5Dcreate2(file.id(), name.c_str(), type.id(),
413  space.id(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT))
414  {
415  }
416 
417  HDF5DataSet(const HDF5Group &group, const std::string &name,
418  const HDF5DataType &type, const HDF5DataSpace &space)
419  : HDF5ID<HDF5DataSet>(::H5Dcreate2(group.id(), name.c_str(), type.id(),
420  space.id(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT))
421  {
422  }
423 
424  HDF5DataSpace space() const { return HDF5DataSpace(::H5Dget_space(id_)); }
425 
426  HDF5DataType type() const { return HDF5DataType(::H5Dget_type(id_)); }
427 
428  bool write(const HDF5DataType &type, const void *mem) const
429  {
430  if (this->space().npoints() == 0) {
431  return false;
432  }
433 
434  return ::H5Dwrite(
435  id_, type.id(), H5S_ALL, H5S_ALL, H5P_DEFAULT, mem) >= 0;
436  }
437 
438  bool read(const HDF5DataType &type, void *mem) const
439  {
440  if (this->space().npoints() == 0) {
441  return false;
442  }
443 
444  return ::H5Dread(id_, type.id(), H5S_ALL, H5S_ALL, H5P_DEFAULT, mem) >=
445  0;
446  }
447 
448  static ::hid_t copy(::hid_t) = delete;
449 
450  static void close(::hid_t id) { ::H5Dclose(id); }
451 }; // class HDF5DataSet
452 
454  : HDF5ID<HDF5DataType>(::H5Tcopy(data.id()))
455 {
456 }
457 
460 class HDF5PropertyList : public HDF5ID<HDF5PropertyList>
461 {
462  public:
464 
465  HDF5PropertyList() = default;
466 
467  static ::hid_t copy(::hid_t) = delete;
468 
469  static void close(::hid_t id) { ::H5Pclose(id); }
470 }; // class HDF5PropertyList
471 
474 inline ::hid_t hdf5typeid(char *) { return ::H5Tcopy(H5T_NATIVE_CHAR); }
475 
478 inline ::hid_t hdf5typeid(signed char *)
479 {
480  return ::H5Tcopy(H5T_NATIVE_SCHAR);
481 }
482 
485 inline ::hid_t hdf5typeid(unsigned char *)
486 {
487  return ::H5Tcopy(H5T_NATIVE_UCHAR);
488 }
489 
492 inline ::hid_t hdf5typeid(short *) { return ::H5Tcopy(H5T_NATIVE_SHORT); }
493 
496 inline ::hid_t hdf5typeid(unsigned short *)
497 {
498  return ::H5Tcopy(H5T_NATIVE_UCHAR);
499 }
500 
503 inline ::hid_t hdf5typeid(int *) { return ::H5Tcopy(H5T_NATIVE_INT); }
504 
507 inline ::hid_t hdf5typeid(unsigned int *)
508 {
509  return ::H5Tcopy(H5T_NATIVE_UINT);
510 }
511 
514 inline ::hid_t hdf5typeid(long *) { return ::H5Tcopy(H5T_NATIVE_LONG); }
515 
518 inline ::hid_t hdf5typeid(unsigned long *)
519 {
520  return ::H5Tcopy(H5T_NATIVE_ULONG);
521 }
522 
525 inline ::hid_t hdf5typeid(long long *) { return ::H5Tcopy(H5T_NATIVE_LLONG); }
526 
529 inline ::hid_t hdf5typeid(unsigned long long *)
530 {
531  return ::H5Tcopy(H5T_NATIVE_ULLONG);
532 }
533 
536 inline ::hid_t hdf5typeid(float *) { return ::H5Tcopy(H5T_NATIVE_FLOAT); }
537 
540 inline ::hid_t hdf5typeid(double *) { return ::H5Tcopy(H5T_NATIVE_DOUBLE); }
541 
544 inline ::hid_t hdf5typeid(long double *)
545 {
546  return ::H5Tcopy(H5T_NATIVE_LDOUBLE);
547 }
548 
550 template <typename T>
552 {
553  return HDF5DataType(hdf5typeid(static_cast<T *>(nullptr)));
554 }
555 
558 template <typename Location, typename T>
559 inline bool hdf5store(Location &&location, const std::string &name,
560  const T &value, bool isattr = false, decltype(hdf5type<T>()) * = nullptr)
561 {
562  auto type = hdf5type<T>();
563  if (!type) {
564  return false;
565  }
566 
567  ::hsize_t dims[] = {1};
568  HDF5DataSpace space(1, dims);
569  if (!space) {
570  return false;
571  }
572 
573  if (isattr) {
574  HDF5Attribute attr(location, name, type, space);
575  if (!attr) {
576  return false;
577  }
578  return attr.write(type, &value);
579  }
580 
581  HDF5DataSet data(location, name, type, space);
582  if (!data) {
583  return false;
584  }
585  return data.write(type, &value);
586 }
587 
590 template <typename Location>
591 inline bool hdf5store(Location &&location, const std::string &name,
592  const std::string &str, bool isattr = false)
593 {
594  if (str.empty()) {
595  std::string empty_str;
596  empty_str.push_back('\0');
597  return hdf5store(location, name, empty_str, isattr);
598  }
599 
600  HDF5DataType type(::H5Tcopy(H5T_C_S1));
601  if (!type) {
602  return false;
603  }
604 
605  type.size(str.size());
606  if (!type) {
607  return false;
608  }
609 
610  ::hsize_t dims[] = {1};
611  HDF5DataSpace space(1, dims);
612  if (!space) {
613  return false;
614  }
615 
616  if (isattr) {
617  HDF5Attribute attr(location, name, type, space);
618  if (!attr) {
619  return false;
620  }
621  return attr.write(type, str.c_str());
622  }
623 
624  HDF5DataSet data(location, name, type, space);
625  if (!data) {
626  return false;
627  }
628 
629  return data.write(type, str.c_str());
630 }
631 
634 template <typename Location, typename T, typename Alloc>
635 inline bool hdf5store(Location &&location, const std::string &name,
636  const Vector<T, Alloc> &vec, bool isattr = false, bool extensible = false,
637  std::size_t chunk_size = 1024)
638 {
639  auto type = hdf5type<T>();
640  if (!type) {
641  return false;
642  }
643 
644  auto ext = extensible && !isattr;
645  ::hsize_t dims[] = {vec.size()};
646  ::hsize_t maxdims[] = {ext ? H5S_UNLIMITED : vec.size()};
647  HDF5DataSpace space(1, dims, maxdims);
648  if (!space) {
649  return false;
650  }
651 
652  if (isattr) {
653  HDF5Attribute attr(location, name, type, space);
654  if (!attr) {
655  return false;
656  }
657  return attr.write(type, vec.data());
658  }
659 
660  HDF5DataSet data;
661  if (ext) {
662  HDF5PropertyList plist(::H5Pcreate(H5P_DATASET_CREATE));
663  if (!plist) {
664  return false;
665  }
666 
667  if (::H5Pset_layout(plist.id(), H5D_CHUNKED) != 0) {
668  return false;
669  }
670 
671  ::hsize_t chunk_dims[] = {chunk_size};
672  if (::H5Pset_chunk(plist.id(), 1, chunk_dims) != 0) {
673  return false;
674  }
675 
676  data = HDF5DataSet(::H5Dcreate2(location.id(), name.c_str(), type.id(),
677  space.id(), H5P_DEFAULT, plist.id(), H5P_DEFAULT));
678  } else {
679  data = HDF5DataSet(location, name, type, space);
680  }
681 
682  if (!data) {
683  return false;
684  }
685 
686  return data.write(type, vec.data());
687 }
688 
691 template <typename Location, typename T, typename Alloc>
692 inline bool hdf5append(
693  Location &&location, const std::string &name, const Vector<T, Alloc> &vec)
694 {
695  if (vec.empty()) {
696  return true;
697  }
698 
699  auto type = hdf5type<T>();
700  if (!type) {
701  return false;
702  }
703 
704  HDF5DataSet data(location, name);
705  if (!data) {
706  return false;
707  }
708 
709  auto space = data.space();
710  if (!space) {
711  return false;
712  }
713 
714  ::hsize_t offset[] = {space.npoints()};
715  ::hsize_t exts[] = {vec.size()};
716  ::hsize_t dims[] = {offset[0] + exts[0]};
717  if (::H5Dset_extent(data.id(), dims) != 0) {
718  return false;
719  }
720 
721  space = data.space();
722  if (!space) {
723  return false;
724  }
725 
726  if (::H5Sselect_hyperslab(
727  space.id(), H5S_SELECT_SET, offset, nullptr, exts, nullptr) != 0) {
728  return false;
729  }
730 
731  HDF5DataSpace mspace(1, exts);
732  if (!mspace) {
733  return false;
734  }
735 
736  if (::H5Dwrite(data.id(), type.id(), mspace.id(), space.id(), H5P_DEFAULT,
737  vec.data()) != 0) {
738  return false;
739  }
740 
741  return true;
742 }
743 
746 template <typename Location, typename T, MatrixLayout Layout, typename Alloc>
747 inline bool hdf5store(Location &&location, const std::string &name,
748  const Matrix<T, Layout, Alloc> &mat, bool isattr = false)
749 {
750  auto type = hdf5type<T>();
751  if (!type) {
752  return false;
753  }
754 
755  ::hsize_t dims[2];
756  if (Layout == RowMajor) {
757  dims[0] = mat.nrow();
758  dims[1] = mat.ncol();
759  }
760  if (Layout == ColMajor) {
761  dims[0] = mat.ncol();
762  dims[1] = mat.nrow();
763  }
764  HDF5DataSpace space(2, dims);
765  if (!space) {
766  return false;
767  }
768 
769  if (isattr) {
770  HDF5Attribute attr(location, name, type, space);
771  if (!attr) {
772  return false;
773  }
774  return attr.write(type, mat.data());
775  }
776 
777  HDF5DataSet data(location, name, type, space);
778  if (!data) {
779  return false;
780  }
781  return data.write(type, mat.data());
782 }
783 
786 template <typename Location, typename T>
787 inline bool hdf5load(Location &&location, const std::string &name, T *value,
788  bool isattr = false, decltype(hdf5type<T>()) * = nullptr)
789 {
790  auto type = hdf5type<T>();
791  if (!type) {
792  return false;
793  }
794 
795  if (isattr) {
796  HDF5Attribute attr(location, name);
797  if (!attr) {
798  return false;
799  }
800  return attr.read(type, value);
801  }
802 
803  HDF5DataSet data(location, name);
804  if (!data) {
805  return false;
806  }
807  return data.read(type, value);
808 }
809 
812 template <typename Location>
813 inline bool hdf5load(Location &&location, const std::string &name,
814  std::string *str, bool isattr = false)
815 {
816  if (isattr) {
817  HDF5Attribute attr(location, name);
818  if (!attr) {
819  return false;
820  }
821 
822  auto type = attr.type();
823  if (!type) {
824  return false;
825  }
826 
827  str->resize(type.size());
828 
829  return attr.read(type, const_cast<char *>(str->data()));
830  }
831 
832  HDF5DataSet data(location, name);
833  if (!data) {
834  return false;
835  }
836 
837  auto type = data.type();
838  if (!type) {
839  return false;
840  }
841 
842  str->resize(type.size());
843 
844  return data.read(type, const_cast<char *>(str->data()));
845 }
846 
849 template <typename Location, typename T, typename Alloc>
850 inline bool hdf5load(Location &&location, const std::string &name,
851  Vector<T, Alloc> *vec, bool isattr = false)
852 {
853  auto type = hdf5type<T>();
854  if (!type) {
855  return false;
856  }
857 
858  if (isattr) {
859  HDF5Attribute attr(location, name);
860  if (!attr) {
861  return false;
862  }
863 
864  auto space = attr.space();
865  if (!space) {
866  return false;
867  }
868 
869  vec->resize(space.npoints());
870  if (vec->empty()) {
871  return true;
872  }
873 
874  return attr.read(type, vec->data());
875  }
876 
877  HDF5DataSet data(location, name);
878  if (!data) {
879  return false;
880  }
881 
882  auto space = data.space();
883  if (!space) {
884  return false;
885  }
886 
887  vec->resize(space.npoints());
888  if (vec->empty()) {
889  return true;
890  }
891 
892  return data.read(type, vec->data());
893 }
894 
897 template <typename Location, typename T, MatrixLayout Layout, typename Alloc>
898 inline bool hdf5load(Location &&location, const std::string &name,
899  Matrix<T, Layout, Alloc> *mat, bool isattr = false)
900 {
901  auto type = hdf5type<T>();
902  if (!type) {
903  return false;
904  }
905 
906  if (isattr) {
907  HDF5Attribute attr(location, name);
908  if (!attr) {
909  return false;
910  }
911 
912  auto space = attr.space();
913  if (!space) {
914  return false;
915  }
916 
917  if (space.ndims() != 2) {
918  return false;
919  }
920 
921  ::hsize_t dims[2];
922  if (space.dims(dims) != 2) {
923  return false;
924  }
925 
926  if (Layout == RowMajor) {
927  mat->resize(dims[0], dims[1]);
928  }
929  if (Layout == ColMajor) {
930  mat->resize(dims[1], dims[0]);
931  }
932  if (mat->empty()) {
933  return true;
934  }
935 
936  return attr.read(type, mat->data());
937  }
938 
939  HDF5DataSet data(location, name);
940  if (!data) {
941  return false;
942  }
943 
944  auto space = data.space();
945  if (!space) {
946  return false;
947  }
948 
949  if (space.ndims() != 2) {
950  return false;
951  }
952 
953  ::hsize_t dims[2];
954  if (space.dims(dims) != 2) {
955  return false;
956  }
957 
958  if (Layout == RowMajor) {
959  mat->resize(dims[0], dims[1]);
960  }
961  if (Layout == ColMajor) {
962  mat->resize(dims[1], dims[0]);
963  }
964  if (mat->empty()) {
965  return true;
966  }
967 
968  return data.read(type, mat->data());
969 }
970 
971 } // namespace mckl
972 
973 #endif // MCKL_UTILITY_HDF5_HPP
void size(std::size_t s) const
Definition: hdf5.hpp:283
inline ::herr_t mckl_hdf5_inc_link(::hid_t, const char *, const ::H5L_info_t *, void *opdata)
Definition: hdf5.hpp:48
bool operator!() const
Definition: hdf5.hpp:103
RAII class for HDF5 IDs.
Definition: hdf5.hpp:62
size_type ncol() const
The number of columns.
Definition: matrix.hpp:488
void resize(size_type nrow, size_type ncol)
Resize the matrix.
Definition: matrix.hpp:506
std::size_t ndims() const
Definition: hdf5.hpp:312
HDF5DataSet(const HDF5File &file, const std::string &name)
Definition: hdf5.hpp:399
::hid_t copy(::hid_t id)
Definition: hdf5.hpp:287
RAII class for HDF5 data type.
Definition: hdf5.hpp:262
inline ::hid_t hdf5typeid(char *)
HDF5 data type id overload for char.
Definition: hdf5.hpp:474
HDF5Attribute(const HDF5File &file, const std::string &name)
Definition: hdf5.hpp:337
bool write(const HDF5DataType &type, const void *mem) const
Definition: hdf5.hpp:428
::hid_t id_
Definition: hdf5.hpp:107
std::vector< T, Alloc > Vector
std::vector with Allocator as the default allocator
Definition: memory.hpp:435
HDF5Attribute(const HDF5Group &group, const std::string &name, const HDF5DataType &type, const HDF5DataSpace &space)
Definition: hdf5.hpp:356
Matrix container.
Definition: matrix.hpp:49
bool empty() const
If the matrix is empty, i.e., nrow() * ncol() == 0
Definition: matrix.hpp:482
bool hdf5store(Location &&location, const std::string &name, const T &value, bool isattr=false, decltype(hdf5type< T >()) *=nullptr)
Store a value in HDF5 format.
Definition: hdf5.hpp:559
static void close(::hid_t id)
Definition: hdf5.hpp:191
::hid_t id() const
Definition: hdf5.hpp:101
bool good() const
Definition: hdf5.hpp:102
HDF5ID & operator=(HDF5ID &&other)
Definition: hdf5.hpp:88
bool write(const HDF5DataType &type, const void *mem) const
Definition: hdf5.hpp:367
RAII class for HDF5 attribute.
Definition: hdf5.hpp:330
std::vector< std::string > links() const
Get the names of all links in the group.
Definition: hdf5.hpp:236
HDF5File(const std::string &filename, bool append, bool read_only)
Open or create an HDF5 file.
Definition: hdf5.hpp:179
std::size_t size() const
Get the number of links in the group.
Definition: hdf5.hpp:246
bool commit(const HDF5Group &group, const std::string &name) const
Definition: hdf5.hpp:277
static void close(::hid_t id)
Definition: hdf5.hpp:450
pointer data()
Pointer to the upper left corner of the matrix.
Definition: matrix.hpp:437
HDF5DataSet(const HDF5File &file, const std::string &name, const HDF5DataType &type, const HDF5DataSpace &space)
Definition: hdf5.hpp:410
bool read(const HDF5DataType &type, void *mem) const
Definition: hdf5.hpp:376
RAII class for HDF5 group.
Definition: hdf5.hpp:196
static void close(::hid_t id)
Definition: hdf5.hpp:469
std::size_t dims(::hsize_t *dest) const
Definition: hdf5.hpp:317
HDF5DataSpace space() const
Definition: hdf5.hpp:363
HDF5ID(const HDF5ID &other)
Definition: hdf5.hpp:69
static void close(::hid_t id)
Definition: hdf5.hpp:257
RAII class for HDF5 data space.
Definition: hdf5.hpp:294
HDF5Group(const HDF5File &file, const std::string &groupname)
Open a group if possible, otherwise create a new one.
Definition: hdf5.hpp:204
bool read(const HDF5DataType &type, void *mem) const
Definition: hdf5.hpp:438
bool hdf5_error_printing(bool enabled)
Enable and disable HDF5 low level error printing.
Definition: hdf5.hpp:125
bool commit(const HDF5File &file, const std::string &name) const
Definition: hdf5.hpp:271
static void close(::hid_t id)
Definition: hdf5.hpp:387
Definition: mcmc.hpp:40
HDF5DataType type() const
Definition: hdf5.hpp:365
HDF5DataSet(const HDF5Group &group, const std::string &name)
Definition: hdf5.hpp:404
std::size_t size() const
Definition: hdf5.hpp:285
HDF5ID(HDF5ID &&other)
Definition: hdf5.hpp:86
inline ::herr_t mckl_hdf5_add_link(::hid_t, const char *name, const ::H5L_info_t *, void *opdata)
Definition: hdf5.hpp:39
HDF5Attribute(const HDF5File &file, const std::string &name, const HDF5DataType &type, const HDF5DataSpace &space)
Definition: hdf5.hpp:349
size_type nrow() const
The number of rows.
Definition: matrix.hpp:485
HDF5DataSet(const HDF5Group &group, const std::string &name, const HDF5DataType &type, const HDF5DataSpace &space)
Definition: hdf5.hpp:417
HDF5ID & operator=(const HDF5ID &other)
Definition: hdf5.hpp:74
HDF5DataType type() const
Definition: hdf5.hpp:426
bool hdf5append(Location &&location, const std::string &name, const Vector< T, Alloc > &vec)
Append a vector in HDF5 format.
Definition: hdf5.hpp:692
HDF5DataSpace space() const
Definition: hdf5.hpp:424
RAII class for HDF5 property list.
Definition: hdf5.hpp:460
RAII class for HDF5 file object.
Definition: hdf5.hpp:141
HDF5File(const std::string &filename)
Open an HDF5 file if it possible, otherwise create a new one.
Definition: hdf5.hpp:149
static void close(::hid_t id)
Definition: hdf5.hpp:289
HDF5DataSpace(int rank, ::hsize_t *dim, ::hsize_t *maxdims=nullptr)
Definition: hdf5.hpp:301
HDF5DataType()=default
RAII class for HDF5 data set.
Definition: hdf5.hpp:392
static void close(::hid_t id)
Definition: hdf5.hpp:325
HDF5ID(::hid_t id)
Definition: hdf5.hpp:67
HDF5File(const std::string &filename, bool append)
Open or create an HDF5 file.
Definition: hdf5.hpp:165
HDF5Attribute(const HDF5Group &group, const std::string &name)
Definition: hdf5.hpp:343
HDF5Group(const HDF5Group &group, const std::string &groupname)
Open a group if possible, otherwise create a new one.
Definition: hdf5.hpp:220
std::size_t npoints() const
Definition: hdf5.hpp:307
HDF5DataType hdf5type()
HDF5 data type.
Definition: hdf5.hpp:551
bool hdf5load(Location &&location, const std::string &name, T *value, bool isattr=false, decltype(hdf5type< T >()) *=nullptr)
Load a value form HDF5 format.
Definition: hdf5.hpp:787