OpenGM  2.3.x
Discrete Graphical Model Library
marray_hdf5.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef MARRAY_HDF5_HXX
3 #define MARRAY_HDF5_HXX
4 
5 // compat fix for buggy hdf5 1.8 versions
6 #include <H5version.h>
7 #if (H5_VERS_MAJOR == 1 && H5_VERS_MINOR >= 8 && defined(H5_USE_16_API_DEFAULT))
8 #define H5Gcreate_vers 2
9 #define H5Gopen_vers 2
10 #define H5Dopen_vers 2
11 #define H5Dcreate_vers 2
12 #define H5Acreate_vers 2
13 #endif
14 
15 #include <cstring>
16 
17 #include "marray.hxx"
18 #include "hdf5.h"
19 
20 namespace marray {
22 namespace hdf5 {
23 
24 // assertion testing
25 
26 // \cond suppress doxygen
27 template<bool B> class HandleCheck;
28 template<> class HandleCheck<false> {
29 public:
30  HandleCheck()
31  { counter_ = H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL); }
32  void check()
33  { marray_detail::Assert( counter_ == H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL)); }
34 private:
35  ssize_t counter_;
36 };
37 template<> class HandleCheck<true> {
38 public:
39  void check() {}
40 };
41 // \endcond
42 
43 // namespace variables
44 
45 const char reverseShapeAttributeName[14] = "reverse-shape";
46 
47 // prototypes
48 
51 
52 inline hid_t createFile(const std::string&, HDF5Version = DEFAULT_HDF5_VERSION);
53 inline hid_t openFile(const std::string&, FileAccessMode = READ_ONLY, HDF5Version = DEFAULT_HDF5_VERSION);
54 inline void closeFile(const hid_t&);
55 
56 inline hid_t createGroup(const hid_t&, const std::string&);
57 inline hid_t openGroup(const hid_t&, const std::string&);
58 inline void closeGroup(const hid_t&);
59 
60 template<class T>
61  void save(const hid_t&, const std::string&, const Marray<T>&);
62 template<class T, bool isConst>
63  void save(const hid_t&, const std::string&, const View<T, isConst>&);
64 template<class T>
65  void save(const hid_t&, const std::string&, const std::vector<T>&);
66 template<class T, class BaseIterator, class ShapeIterator>
67  void saveHyperslab(const hid_t&, const std::string&,
68  BaseIterator, BaseIterator, ShapeIterator, const Marray<T>&);
69 template<class T, class ShapeIterator>
70  void create(const hid_t&, const std::string&, ShapeIterator,
71  ShapeIterator, CoordinateOrder);
72 
73 template<class T>
74  void load(const hid_t&, const std::string&, Marray<T>&);
75 template<class T>
76  void loadShape(const hid_t&, const std::string&, Vector<T>&);
77 template<class T>
78  void loadVec(const hid_t&, const std::string&, std::vector<T>&);
79 template<class T, class BaseIterator, class ShapeIterator>
80  void loadHyperslab(const hid_t&, const std::string&,
81  BaseIterator, BaseIterator, ShapeIterator, Marray<T>&);
82 
83 // type conversion from C++ to HDF5
84 
85 #ifdef BIGENDIAN
86 // \cond suppress doxygen
87 template<class T>
88 inline hid_t uintTypeHelper() {
89  switch(sizeof(T)) {
90  case 1:
91  return H5T_STD_U8BE;
92  case 2:
93  return H5T_STD_U16BE;
94  case 4:
95  return H5T_STD_U32BE;
96  case 8:
97  return H5T_STD_U64BE;
98  default:
99  throw std::runtime_error("No matching HDF5 type.");
100  }
101 }
102 
103 template<class T>
104 inline hid_t intTypeHelper() {
105  switch(sizeof(T)) {
106  case 1:
107  return H5T_STD_I8BE;
108  case 2:
109  return H5T_STD_I16BE;
110  case 4:
111  return H5T_STD_I32BE;
112  case 8:
113  return H5T_STD_I64BE;
114  default:
115  throw std::runtime_error("No matching HDF5 type.");
116  }
117 }
118 
119 template<class T>
120 inline hid_t floatingTypeHelper() {
121  switch(sizeof(T)) {
122  case 4:
123  return H5T_IEEE_F32BE;
124  case 8:
125  return H5T_IEEE_F64BE;
126  default:
127  throw std::runtime_error("No matching HDF5 type.");
128  }
129 }
130 #else
131 // \cond suppress doxygen
132 template<class T>
133 inline hid_t uintTypeHelper() {
134  switch(sizeof(T)) {
135  case 1:
136  return H5T_STD_U8LE;
137  case 2:
138  return H5T_STD_U16LE;
139  case 4:
140  return H5T_STD_U32LE;
141  case 8:
142  return H5T_STD_U64LE;
143  default:
144  throw std::runtime_error("No matching HDF5 type.");
145  }
146 }
147 
148 template<class T>
149 inline hid_t intTypeHelper() {
150  switch(sizeof(T)) {
151  case 1:
152  return H5T_STD_I8LE;
153  case 2:
154  return H5T_STD_I16LE;
155  case 4:
156  return H5T_STD_I32LE;
157  case 8:
158  return H5T_STD_I64LE;
159  default:
160  throw std::runtime_error("No matching HDF5 type.");
161  }
162 }
163 
164 template<class T>
165 inline hid_t floatingTypeHelper() {
166  switch(sizeof(T)) {
167  case 4:
168  return H5T_IEEE_F32LE;
169  case 8:
170  return H5T_IEEE_F64LE;
171  default:
172  throw std::runtime_error("No matching HDF5 type.");
173  }
174 }
175 #endif
176 
177 template<class T>
178 inline hid_t hdf5Type();
179 
180 template<> inline hid_t hdf5Type<unsigned char>()
181  { return uintTypeHelper<unsigned char>(); }
182 template<> inline hid_t hdf5Type<unsigned short>()
183  { return uintTypeHelper<unsigned short>(); }
184 template<> inline hid_t hdf5Type<unsigned int>()
185  { return uintTypeHelper<unsigned int>(); }
186 template<> inline hid_t hdf5Type<unsigned long>()
187  { return uintTypeHelper<unsigned long>(); }
188 template<> inline hid_t hdf5Type<unsigned long long>()
189  { return uintTypeHelper<unsigned long long>(); }
190 
191 template<> inline hid_t hdf5Type<char>()
192  { return uintTypeHelper<char>(); }
193 template<> inline hid_t hdf5Type<signed char>()
194  { return intTypeHelper<signed char>(); }
195 template<> inline hid_t hdf5Type<short>()
196  { return intTypeHelper<short>(); }
197 template<> inline hid_t hdf5Type<int>()
198  { return intTypeHelper<int>(); }
199 template<> inline hid_t hdf5Type<long>()
200  { return intTypeHelper<long>(); }
201 template<> inline hid_t hdf5Type<long long>()
202  { return intTypeHelper<long long>(); }
203 
204 template<> inline hid_t hdf5Type<float>()
205  { return floatingTypeHelper<float>(); }
206 template<> inline hid_t hdf5Type<double>()
207  { return floatingTypeHelper<double>(); }
208 // \endcond
209 
210 // implementation
211 
222 template<class T, class ShapeIterator>
223 void create(
224  const hid_t& groupHandle,
225  const std::string& datasetName,
226  ShapeIterator begin,
227  ShapeIterator end,
228  CoordinateOrder coordinateOrder
229 ) {
230  marray_detail::Assert(MARRAY_NO_ARG_TEST || groupHandle >= 0);
231  HandleCheck<MARRAY_NO_DEBUG> handleCheck;
232 
233  // build dataspace
234  hid_t datatype = H5Tcopy(hdf5Type<T>());
235  size_t dimension = std::distance(begin, end);
236  Vector<hsize_t> shape((size_t)(dimension));
237  if(coordinateOrder == FirstMajorOrder) {
238  // copy shape as is
239  for(size_t j=0; j<dimension; ++j) {
240  shape[j] = hsize_t(*begin);
241  ++begin;
242  }
243  }
244  else {
245  // reverse shape
246  for(size_t j=0; j<dimension; ++j) {
247  shape[dimension-j-1] = hsize_t(*begin);
248  ++begin;
249  }
250  }
251  hid_t dataspace = H5Screate_simple(dimension, &shape[0], NULL);
252  if(dataspace < 0) {
253  H5Tclose(datatype);
254  throw std::runtime_error("Marray cannot create dataspace.");
255  }
256 
257 
258  // create new dataset
259  hid_t dataset = H5Dcreate(groupHandle, datasetName.c_str(), datatype,
260  dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
261  if(dataset < 0) {
262  H5Sclose(dataspace);
263  H5Tclose(datatype);
264  throw std::runtime_error("Marray cannot create dataset.");
265  }
266 
267  // write attribute to indicate whether shape is reversed
268  if(coordinateOrder == LastMajorOrder) {
269  hsize_t attributeShape[1] = {1};
270  hid_t attributeDataspace = H5Screate_simple(1, attributeShape, NULL);
271  if(attributeDataspace < 0) {
272  H5Dclose(dataset);
273  H5Sclose(dataspace);
274  H5Tclose(datatype);
275  throw std::runtime_error("Marray cannot create dataspace.");
276  }
277  hid_t attribute = H5Acreate(dataset, reverseShapeAttributeName,
278  H5T_STD_U8LE, attributeDataspace, H5P_DEFAULT, H5P_DEFAULT);
279  if(attribute < 0) {
280  H5Sclose(attributeDataspace);
281  H5Dclose(dataset);
282  H5Sclose(dataspace);
283  H5Tclose(datatype);
284  throw std::runtime_error("Marray cannot create attribute.");
285  }
286  unsigned int data = 1;
287  herr_t err = H5Awrite(attribute, H5T_STD_U8LE, &data);
288  H5Aclose(attribute);
289  H5Sclose(attributeDataspace);
290  if(err < 0) {
291  H5Dclose(dataset);
292  H5Sclose(dataspace);
293  H5Tclose(datatype);
294  throw std::runtime_error("Marray cannot create write to attribute.");
295  }
296  }
297 
298  // clean up
299  H5Dclose(dataset);
300  H5Sclose(dataspace);
301  H5Tclose(datatype);
302  handleCheck.check();
303 }
304 
313 template<class T>
314 void save(
315  const hid_t& groupHandle,
316  const std::string& datasetName,
317  const Marray<T>& in
318 ) {
319  marray_detail::Assert(MARRAY_NO_ARG_TEST || groupHandle >= 0);
320  HandleCheck<MARRAY_NO_DEBUG> handleCheck;
321 
322  // build dataspace
323  hid_t datatype = H5Tcopy(hdf5Type<T>());
324  Vector<hsize_t> shape(in.dimension());
325  if(in.coordinateOrder() == FirstMajorOrder) {
326  // copy shape as is
327  for(size_t j=0; j<in.dimension(); ++j) {
328  shape[j] = hsize_t(in.shape(j));
329  }
330  }
331  else {
332  // reverse shape
333  for(size_t j=0; j<in.dimension(); ++j) {
334  shape[size_t(in.dimension()-j-1)] = hsize_t(in.shape(j));
335  }
336  }
337  hid_t dataspace = H5Screate_simple(in.dimension(), &shape[0], NULL);
338  if(dataspace < 0) {
339  H5Tclose(datatype);
340  throw std::runtime_error("Marray cannot create dataspace.");
341  }
342 
343  // create new dataset
344  hid_t dataset = H5Dcreate(groupHandle, datasetName.c_str(), datatype,
345  dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
346  if(dataset < 0) {
347  H5Sclose(dataspace);
348  H5Tclose(datatype);
349  throw std::runtime_error("Marray cannot create dataset.");
350  }
351 
352  // write attribute to indicate whether shape is reversed
353  if(in.coordinateOrder() == LastMajorOrder) {
354  hsize_t attributeShape[1] = {1};
355  hid_t attributeDataspace = H5Screate_simple(1, attributeShape, NULL);
356  if(attributeDataspace < 0) {
357  H5Dclose(dataset);
358  H5Sclose(dataspace);
359  H5Tclose(datatype);
360  throw std::runtime_error("Marray cannot create dataspace.");
361  }
362  hid_t attribute = H5Acreate(dataset, reverseShapeAttributeName,
363  H5T_STD_U8LE, attributeDataspace, H5P_DEFAULT, H5P_DEFAULT);
364  if(attribute < 0) {
365  H5Sclose(attributeDataspace);
366  H5Dclose(dataset);
367  H5Sclose(dataspace);
368  H5Tclose(datatype);
369  throw std::runtime_error("Marray cannot create attribute.");
370  }
371  unsigned int data = 1;
372  herr_t err = H5Awrite(attribute, H5T_STD_U8LE, &data);
373  H5Aclose(attribute);
374  H5Sclose(attributeDataspace);
375  if(err < 0) {
376  H5Dclose(dataset);
377  H5Sclose(dataspace);
378  H5Tclose(datatype);
379  throw std::runtime_error("Marray cannot create write to attribute.");
380  }
381  }
382 
383  // write
384  herr_t status = H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL,
385  H5P_DEFAULT, &in(0));
386  H5Dclose(dataset);
387  H5Sclose(dataspace);
388  H5Tclose(datatype);
389  if(status < 0) {
390  throw std::runtime_error("Marray cannot write to dataset.");
391  }
392 
393  handleCheck.check();
394 }
395 
404 template<class T, bool isConst>
405 inline void save(
406  const hid_t& groupHandle,
407  const std::string& datasetName,
408  const View<T, isConst>& in
409 ) {
410  Marray<T> m = in;
411  save(groupHandle, datasetName, m);
412 }
413 
422 template<class T>
423 void save(
424  const hid_t& groupHandle,
425  const std::string& datasetName,
426  const std::vector<T>& in
427 )
428 {
429  marray::Vector<T> v(in.size());
430  for(size_t j=0; j<in.size(); ++j) {
431  v[j] = in[j];
432  }
433  save(groupHandle, datasetName, v);
434 }
435 
444 template<class T>
445 void load(
446  const hid_t& groupHandle,
447  const std::string& datasetName,
448  Marray<T>& out
449 ) {
450  marray_detail::Assert(MARRAY_NO_ARG_TEST || groupHandle >= 0);
451  HandleCheck<MARRAY_NO_DEBUG> handleCheck;
452 
453  hid_t dataset = H5Dopen(groupHandle, datasetName.c_str(), H5P_DEFAULT);
454  if(dataset < 0) {
455  throw std::runtime_error("Marray cannot open dataset.");
456  }
457  hid_t filespace = H5Dget_space(dataset);
458  hid_t type = H5Dget_type(dataset);
459  hid_t nativeType = H5Tget_native_type(type, H5T_DIR_DESCEND);
460  if(!H5Tequal(nativeType, hdf5Type<T>())) {
461  H5Dclose(dataset);
462  H5Tclose(nativeType);
463  H5Tclose(type);
464  H5Sclose(filespace);
465  throw std::runtime_error("Data types not equal error.");
466  }
467  int dimension = H5Sget_simple_extent_ndims(filespace);
468  Vector<hsize_t> shape(dimension);
469  herr_t status = H5Sget_simple_extent_dims(filespace, &shape[0], NULL);
470  if(status < 0) {
471  H5Dclose(dataset);
472  H5Tclose(nativeType);
473  H5Tclose(type);
474  H5Sclose(filespace);
475  throw std::runtime_error("H5Sget_simple_extent_dims error.");
476  }
477  hid_t memspace = H5Screate_simple(dimension, &shape[0], NULL);
478 
479  // resize marray
480  marray::Vector<size_t> newShape((size_t)(dimension));
481  for(size_t j=0; j<newShape.size(); ++j) {
482  newShape(j) = (size_t)(shape[j]);
483  }
484  if(H5Aexists(dataset, reverseShapeAttributeName) > 0) {
485  // reverse shape
486  out = Marray<T>(SkipInitialization, newShape.rbegin(),
487  newShape.rend(), LastMajorOrder);
488  }
489  else {
490  // don't reverse shape
491  out = Marray<T>(SkipInitialization, newShape.begin(),
492  newShape.end(), FirstMajorOrder);
493  }
494 
495  // read
496  status = H5Dread(dataset, nativeType, memspace, filespace,
497  H5P_DEFAULT, &out(0));
498  H5Dclose(dataset);
499  H5Tclose(nativeType);
500  H5Tclose(type);
501  H5Sclose(memspace);
502  H5Sclose(filespace);
503  if(status < 0) {
504  throw std::runtime_error("Marray cannot read from dataset.");
505  }
506 
507  handleCheck.check();
508 }
509 
518 template<class T>
520  const hid_t& groupHandle,
521  const std::string& datasetName,
522  Vector<T>& out
523 ) {
524  marray_detail::Assert(MARRAY_NO_ARG_TEST || groupHandle >= 0);
525  HandleCheck<MARRAY_NO_DEBUG> handleCheck;
526 
527  // load shape from HDF5 file
528  hid_t dataset = H5Dopen(groupHandle, datasetName.c_str(), H5P_DEFAULT);
529  if(dataset < 0) {
530  throw std::runtime_error("Marray cannot open dataset.");
531  }
532  hid_t filespace = H5Dget_space(dataset);
533  hsize_t dimension = H5Sget_simple_extent_ndims(filespace);
534  hsize_t* shape = new hsize_t[(size_t)(dimension)];
535  herr_t status = H5Sget_simple_extent_dims(filespace, shape, NULL);
536  if(status < 0) {
537  H5Dclose(dataset);
538  H5Sclose(filespace);
539  delete[] shape;
540  throw std::runtime_error("Marray cannot get extension of dataset.");
541  }
542 
543  // write shape to out
544  out = Vector<T>((size_t)(dimension));
545  if(H5Aexists(dataset, reverseShapeAttributeName) > 0) {
546  for(size_t j=0; j<out.size(); ++j) {
547  out[out.size()-j-1] = T(shape[j]);
548  }
549  }
550  else {
551  for(size_t j=0; j<out.size(); ++j) {
552  out[j] = T(shape[j]);
553  }
554  }
555 
556  // clean up
557  delete[] shape;
558  H5Dclose(dataset);
559  H5Sclose(filespace);
560  handleCheck.check();
561 }
562 
571 template<class T>
572 void loadVec(
573  const hid_t& groupHandle,
574  const std::string& datasetName,
575  std::vector<T>& out
576 )
577 {
579  load( groupHandle,datasetName,v);
580  out.resize(v.size());
581  for(size_t j=0; j<v.size(); ++j) {
582  out[j] = v(j);
583  }
584 }
585 
597 template<class T, class BaseIterator, class ShapeIterator>
599  const hid_t& groupHandle,
600  const std::string& datasetName,
601  BaseIterator baseBegin,
602  BaseIterator baseEnd,
603  ShapeIterator shapeBegin,
604  Marray<T>& out
605 ) {
606  marray_detail::Assert(MARRAY_NO_ARG_TEST || groupHandle >= 0);
607  HandleCheck<MARRAY_NO_DEBUG> handleCheck;
608 
609  // open dataset
610  hid_t dataset = H5Dopen(groupHandle, datasetName.c_str(), H5P_DEFAULT);
611  if(dataset < 0) {
612  throw std::runtime_error("Marray cannot open dataset.");
613  }
614 
615  // determine shape of hyperslab and array
616  size_t size = std::distance(baseBegin, baseEnd);
617  Vector<hsize_t> offset(size);
618  Vector<hsize_t> slabShape(size);
619  Vector<hsize_t> marrayShape(size);
620  CoordinateOrder coordinateOrder;
621  if(H5Aexists(dataset, reverseShapeAttributeName) > 0) {
622  // reverse base and shape
623  coordinateOrder = LastMajorOrder;
624  size_t j = size-1;
625  size_t k = 0;
626  for(;;) {
627  offset[j] = hsize_t(*baseBegin);
628  slabShape[j] = hsize_t(*shapeBegin);
629  marrayShape[k] = slabShape[j];
630  if(j == 0) {
631  break;
632  }
633  else {
634  ++baseBegin;
635  ++shapeBegin;
636  ++k;
637  --j;
638  }
639  }
640  }
641  else {
642  // don't reverse base and shape
643  coordinateOrder = FirstMajorOrder;
644  for(size_t j=0; j<size; ++j) {
645  offset[j] = hsize_t(*baseBegin);
646  slabShape[j] = hsize_t(*shapeBegin);
647  marrayShape[j] = slabShape[j];
648  ++baseBegin;
649  ++shapeBegin;
650  }
651  }
652 
653  // select dataspace hyperslab
654  hid_t datatype = H5Dget_type(dataset);
655 
656  if(!H5Tequal(datatype, hdf5Type<T>())) {
657  throw std::runtime_error("data type of stored hdf5 dataset and passed array do not match in loadHyperslab");
658  }
659 
660  hid_t dataspace = H5Dget_space(dataset);
661  herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
662  &offset[0], NULL, &slabShape[0], NULL);
663  if(status < 0) {
664  H5Tclose(datatype);
665  H5Sclose(dataspace);
666  H5Dclose(dataset);
667  throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
668  }
669 
670  // select memspace hyperslab
671  hid_t memspace = H5Screate_simple(int(size), &marrayShape[0], NULL);
672  Vector<hsize_t> offsetOut(size, 0); // no offset
673  status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &offsetOut[0],
674  NULL, &marrayShape[0], NULL);
675  if(status < 0) {
676  H5Sclose(memspace);
677  H5Tclose(datatype);
678  H5Sclose(dataspace);
679  H5Dclose(dataset);
680  throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
681  }
682 
683  // read from dataspace into memspace
684  out = Marray<T>(SkipInitialization, &marrayShape[0],
685  (&marrayShape[0])+size, coordinateOrder);
686  status = H5Dread(dataset, datatype, memspace, dataspace,
687  H5P_DEFAULT, &(out(0)));
688 
689  // clean up
690  H5Sclose(memspace);
691  H5Tclose(datatype);
692  H5Sclose(dataspace);
693  H5Dclose(dataset);
694  if(status < 0) {
695  throw std::runtime_error("Marray cannot read from dataset.");
696  }
697  handleCheck.check();
698 }
699 
711 template<class T, class BaseIterator, class ShapeIterator>
712 void
714  const hid_t& groupHandle,
715  const std::string& datasetName,
716  BaseIterator baseBegin,
717  BaseIterator baseEnd,
718  ShapeIterator shapeBegin,
719  const Marray<T>& in
720 ) {
721  marray_detail::Assert(MARRAY_NO_ARG_TEST || groupHandle >= 0);
722  HandleCheck<MARRAY_NO_DEBUG> handleCheck;
723 
724  // open dataset
725  hid_t dataset = H5Dopen(groupHandle, datasetName.c_str(), H5P_DEFAULT);
726  if(dataset < 0) {
727  throw std::runtime_error("Marray cannot open dataset.");
728  }
729 
730  // determine hyperslab shape
731  Vector<hsize_t> memoryShape(in.dimension());
732  for(size_t j=0; j<in.dimension(); ++j) {
733  memoryShape[j] = in.shape(j);
734  }
735  size_t size = std::distance(baseBegin, baseEnd);
736  Vector<hsize_t> offset(size);
737  Vector<hsize_t> slabShape(size);
738  bool reverseShapeAttribute =
739  (H5Aexists(dataset, reverseShapeAttributeName) > 0);
740  if(reverseShapeAttribute && in.coordinateOrder() == LastMajorOrder) {
741  // reverse base and shape
742  size_t j = size-1;
743  for(;;) {
744  offset[j] = hsize_t(*baseBegin);
745  slabShape[j] = hsize_t(*shapeBegin);
746  if(j == 0) {
747  break;
748  }
749  else {
750  ++baseBegin;
751  ++shapeBegin;
752  --j;
753  }
754  }
755  }
756  else if(!reverseShapeAttribute && in.coordinateOrder() == FirstMajorOrder) {
757  for(size_t j=0; j<size; ++j) {
758  offset[j] = hsize_t(*baseBegin);
759  slabShape[j] = hsize_t(*shapeBegin);
760  ++baseBegin;
761  ++shapeBegin;
762  }
763  }
764  else {
765  H5Dclose(dataset);
766  throw std::runtime_error("Marray cannot write to HDF5 file. A different order was used when the file was created.");
767  }
768 
769  // select dataspace hyperslab
770  hid_t datatype = H5Dget_type(dataset);
771  hid_t dataspace = H5Dget_space(dataset);
772  herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
773  &offset[0], NULL, &slabShape[0], NULL);
774  if(status < 0) {
775  H5Tclose(datatype);
776  H5Sclose(dataspace);
777  H5Dclose(dataset);
778  throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
779  }
780 
781  // select memspace hyperslab
782  hid_t memspace = H5Screate_simple(int(in.dimension()), &memoryShape[0], NULL);
783  Vector<hsize_t> memoryOffset(int(in.dimension()), 0); // no offset
784  status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &memoryOffset[0], NULL,
785  &memoryShape[0], NULL);
786  if(status < 0) {
787  H5Sclose(memspace);
788  H5Tclose(datatype);
789  H5Sclose(dataspace);
790  H5Dclose(dataset);
791  throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
792  }
793 
794  // write from memspace to dataspace
795  status = H5Dwrite(dataset, datatype, memspace, dataspace, H5P_DEFAULT, &(in(0)));
796 
797  // clean up
798  H5Sclose(memspace);
799  H5Tclose(datatype);
800  H5Sclose(dataspace);
801  H5Dclose(dataset);
802  if(status < 0) {
803  throw std::runtime_error("Marray cannot write to dataset.");
804  }
805  handleCheck.check();
806 }
807 
817 inline hid_t
819 (
820  const std::string& filename,
821  HDF5Version hdf5version
822 )
823 {
824  hid_t version = H5P_DEFAULT;
825  if(hdf5version == LATEST_HDF5_VERSION) {
826  version = H5Pcreate(H5P_FILE_ACCESS);
827  H5Pset_libver_bounds(version, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
828  }
829 
830  hid_t fileHandle = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, version);
831  if(fileHandle < 0) {
832  throw std::runtime_error("Could not create HDF5 file: " + filename);
833  }
834 
835  return fileHandle;
836 }
837 
848 inline hid_t
849 openFile
850 (
851  const std::string& filename,
852  FileAccessMode fileAccessMode,
853  HDF5Version hdf5version
854 )
855 {
856  hid_t access = H5F_ACC_RDONLY;
857  if(fileAccessMode == READ_WRITE) {
858  access = H5F_ACC_RDWR;
859  }
860 
861  hid_t version = H5P_DEFAULT;
862  if(hdf5version == LATEST_HDF5_VERSION) {
863  version = H5Pcreate(H5P_FILE_ACCESS);
864  H5Pset_libver_bounds(version, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
865  }
866 
867  hid_t fileHandle = H5Fopen(filename.c_str(), access, version);
868  if(fileHandle < 0) {
869  throw std::runtime_error("Could not open HDF5 file: " + filename);
870  }
871 
872  return fileHandle;
873 }
874 
881 inline void closeFile
882 (
883  const hid_t& handle
884 )
885 {
886  H5Fclose(handle);
887 }
888 
897 inline hid_t
899 (
900  const hid_t& parentHandle,
901  const std::string& groupName
902 )
903 {
904  hid_t groupHandle = H5Gcreate(parentHandle, groupName.c_str(),
905  H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
906  if(groupHandle < 0) {
907  throw std::runtime_error("Could not create HDF5 group.");
908  }
909  return groupHandle;
910 }
911 
920 inline hid_t
921 openGroup
922 (
923  const hid_t& parentHandle,
924  const std::string& groupName
925 )
926 {
927  hid_t groupHandle = H5Gopen(parentHandle, groupName.c_str(), H5P_DEFAULT);
928  if(groupHandle < 0) {
929  throw std::runtime_error("Could not open HDF5 group.");
930  }
931  return groupHandle;
932 }
933 
940 inline void
942 (
943  const hid_t& handle
944 )
945 {
946  H5Gclose(handle);
947 }
948 
949 } // namespace hdf5
950 } // namespace marray
951 
952 #endif // #ifndef MARRAY_HDF5_HXX
953 
void loadVec(const hid_t &, const std::string &, std::vector< T > &)
Load a vector of an HDF5 dataset.
hid_t createFile(const std::string &, HDF5Version=DEFAULT_HDF5_VERSION)
Create an HDF5 file.
const char reverseShapeAttributeName[14]
Definition: marray_hdf5.hxx:45
Runtime-flexible multi-dimensional views and arrays.
Definition: marray.hxx:20
const CoordinateOrder & coordinateOrder() const
Get the coordinate order used for scalar indexing and iterators.
Definition: marray.hxx:1815
iterator end()
Get the end-iterator.
Definition: marray.hxx:2727
reverse_iterator rbegin()
Get a reserve iterator to the beginning.
Definition: marray.hxx:2767
Array-Interface to an interval of memory.
Definition: marray.hxx:44
void create(const hid_t &, const std::string &, ShapeIterator, ShapeIterator, CoordinateOrder)
Create and close an HDF5 dataset to store Marray data.
hid_t createGroup(const hid_t &, const std::string &)
Create an HDF5 group.
void load(const hid_t &, const std::string &, Marray< T > &)
Load an Marray from an HDF5 dataset.
iterator begin()
Get an iterator to the beginning.
Definition: marray.hxx:2714
void loadHyperslab(const hid_t &, const std::string &, BaseIterator, BaseIterator, ShapeIterator, Marray< T > &)
Load a hyperslab from an HDF5 dataset into an Marray.
const bool MARRAY_NO_ARG_TEST
Argument testing enabled.
Definition: marray.hxx:60
void loadShape(const hid_t &, const std::string &, Vector< T > &)
Load the shape of an HDF5 dataset.
CoordinateOrder
Definition: marray.hxx:23
void closeFile(const hid_t &)
Close an HDF5 file.
void save(const hid_t &, const std::string &, const Marray< T > &)
Save an Marray as an HDF5 dataset.
const size_t dimension() const
Get the dimension.
Definition: marray.hxx:1711
void closeGroup(const hid_t &)
Close an HDF5 group.
reverse_iterator rend()
Get the reverse end-iterator.
Definition: marray.hxx:2779
const size_t shape(const size_t) const
Get the shape in one dimension.
Definition: marray.hxx:1725
static const InitializationSkipping SkipInitialization
Flag to indicate initialization skipping.
Definition: marray.hxx:29
void saveHyperslab(const hid_t &, const std::string &, BaseIterator, BaseIterator, ShapeIterator, const Marray< T > &)
Save an Marray as a hyperslab into an HDF5 dataset.
hid_t openFile(const std::string &, FileAccessMode=READ_ONLY, HDF5Version=DEFAULT_HDF5_VERSION)
Open an HDF5 file.
const size_t size() const
Get the number of data items.
Definition: marray.hxx:1698
hid_t openGroup(const hid_t &, const std::string &)
Open an HDF5 group.