2 #ifndef ANDRES_GRAPH_HDF5_HXX
3 #define ANDRES_GRAPH_HDF5_HXX
12 #include <H5version.h>
13 #if (H5_VERS_MAJOR == 1 && H5_VERS_MINOR >= 8 && defined(H5_USE_16_API_DEFAULT))
14 #define H5Gcreate_vers 2
15 #define H5Gopen_vers 2
16 #define H5Dopen_vers 2
17 #define H5Dcreate_vers 2
18 #define H5Acreate_vers 2
24 #define ANDRES_GRAPH_HDF5_DEBUG true
26 #define ANDRES_GRAPH_HDF5_DEBUG false
34 class GraphTraitsHDF5;
37 template<
bool B = true>
class HandleCheck;
38 template<>
class HandleCheck<true> {
41 { counter_ = H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL); }
43 { assert( counter_ == H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL)); }
48 template<>
class HandleCheck<false> {
57 case 1:
return H5T_STD_U8LE;
58 case 2:
return H5T_STD_U16LE;
59 case 4:
return H5T_STD_U32LE;
60 case 8:
return H5T_STD_U64LE;
61 default:
throw std::runtime_error(
"No matching HDF5 type.");
68 case 1:
return H5T_STD_I8LE;
69 case 2:
return H5T_STD_I16LE;
70 case 4:
return H5T_STD_I32LE;
71 case 8:
return H5T_STD_I64LE;
72 default:
throw std::runtime_error(
"No matching HDF5 type.");
79 case 4:
return H5T_IEEE_F32LE;
80 case 8:
return H5T_IEEE_F64LE;
81 default:
throw std::runtime_error(
"No matching HDF5 type.");
89 {
return uintTypeHelper<unsigned char>(); }
91 {
return uintTypeHelper<unsigned short>(); }
93 {
return uintTypeHelper<unsigned int>(); }
95 {
return uintTypeHelper<unsigned long>(); }
97 {
return uintTypeHelper<unsigned long long>(); }
99 {
return uintTypeHelper<char>(); }
102 {
return intTypeHelper<signed char>(); }
104 {
return intTypeHelper<short>(); }
106 {
return intTypeHelper<int>(); }
108 {
return intTypeHelper<long>(); }
110 {
return intTypeHelper<long long>(); }
113 {
return floatingTypeHelper<float>(); }
115 {
return floatingTypeHelper<double>(); }
118 enum class HDF5Version {DEFAULT_HDF5_VERSION, LATEST_HDF5_VERSION};
124 hid_t
createGroup(
const hid_t&,
const std::string& groupName);
125 hid_t
openGroup(
const hid_t&,
const std::string&,
const bool =
false);
129 void save(
const hid_t&,
const std::string&, std::initializer_list<std::size_t>,
const T *
const);
131 void save(
const hid_t&,
const std::string&,
const T&);
134 void load(
const hid_t&,
const std::string&, std::vector<std::size_t>&, std::vector<T>&);
136 void load(
const hid_t&,
const std::string&, std::vector<std::vector<T> >&);
138 void load(
const hid_t&,
const std::string&, T&);
151 const std::string& filename,
154 hid_t version = H5P_DEFAULT;
155 if(hdf5version == HDF5Version::LATEST_HDF5_VERSION) {
156 version = H5Pcreate(H5P_FILE_ACCESS);
157 H5Pset_libver_bounds(version, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
159 hid_t fileHandle = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, version);
162 throw std::runtime_error(
"Could not create HDF5 file: " + filename);
179 const std::string& filename,
183 hid_t access = H5F_ACC_RDONLY;
184 if(fileAccessMode == FileAccessMode::READ_WRITE) {
185 access = H5F_ACC_RDWR;
188 hid_t version = H5P_DEFAULT;
189 if(hdf5version == HDF5Version::LATEST_HDF5_VERSION) {
190 version = H5Pcreate(H5P_FILE_ACCESS);
191 H5Pset_libver_bounds(version, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
194 hid_t fileHandle = H5Fopen(filename.c_str(), access, version);
195 if(hdf5version == HDF5Version::LATEST_HDF5_VERSION) {
199 throw std::runtime_error(
"Could not open HDF5 file: " + filename);
226 const hid_t& parentHandle,
227 const std::string& groupName
229 hid_t groupHandle = H5Gcreate(parentHandle, groupName.c_str(),
230 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
231 if(groupHandle < 0) {
232 throw std::runtime_error(
"Could not create HDF5 group.");
248 const hid_t& parentHandle,
249 const std::string& groupName,
250 const bool createIfNonexistent
254 if(createIfNonexistent) {
255 H5E_auto2_t old_func;
256 void *old_client_data;
257 H5Eget_auto(H5E_DEFAULT, &old_func, &old_client_data);
258 H5Eset_auto(H5E_DEFAULT, NULL, NULL);
259 groupHandle = H5Gopen(parentHandle, groupName.c_str(), H5P_DEFAULT);
260 H5Eset_auto2(H5E_DEFAULT, old_func, old_client_data);
261 if(groupHandle != 0) {
262 groupHandle =
createGroup(parentHandle, groupName);
264 if(groupHandle < 0) {
265 throw std::runtime_error(
"HDF5: Could not open or create HDF5 group " + groupName +
".");
268 groupHandle = H5Gopen(parentHandle, groupName.c_str(), H5P_DEFAULT);
269 if(groupHandle < 0) {
270 throw std::runtime_error(
"HDF5: Could not open HDF5 group " + groupName +
".");
298 const hid_t& parentHandle,
299 const std::string& datasetName,
300 const std::initializer_list<std::size_t> shape,
303 assert(parentHandle >= 0);
304 HandleCheck<ANDRES_GRAPH_HDF5_DEBUG> handleCheck;
306 hid_t datatype, dataspace, dataset;
310 datatype = H5Tcopy(hdf5Type<T>());
312 std::vector<hsize_t> storeShape(shape.begin(), shape.end());
313 dataspace = H5Screate_simple(storeShape.size(), &storeShape[0], NULL);
316 sError =
"Dataspace creation failed.";
321 dataset = H5Dcreate(parentHandle, datasetName.c_str(), datatype,
322 dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
324 sError =
"Dataset creation failed.";
328 if(H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL,H5P_DEFAULT, data)<0) {
329 sError =
"Failed to write data to dataset.";
339 if(!sError.empty()) {
340 throw std::runtime_error(
"HDF5: Saving sataset '"+datasetName+
"' failed: " + sError);
352 const hid_t& parentHandle,
353 const std::string& datasetName,
356 assert(parentHandle >= 0);
357 HandleCheck<ANDRES_GRAPH_HDF5_DEBUG> handleCheck;
360 hid_t datatype, dataspace, dataset;
362 datatype = H5Tcopy(hdf5Type<T>());
363 dataspace = H5Screate(H5S_SCALAR);
365 sError =
"Cannot create dataspace.";
370 dataset = H5Dcreate(parentHandle, datasetName.c_str(), datatype,
371 dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
373 sError =
"Cannot create dataset.";
377 if(H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL,H5P_DEFAULT, &data)!=0) {
378 sError =
"Cannot write data.";
387 if(!sError.empty()) {
388 throw std::runtime_error(
389 "HDF5: Saving dataset '"+datasetName+
"' failed: " + sError
404 const hid_t& parentHandle,
405 const std::string& datasetName,
406 std::vector<std::size_t>& shape,
409 assert(parentHandle >= 0);
410 HandleCheck<ANDRES_GRAPH_HDF5_DEBUG> handleCheck;
412 hid_t dataset, memspace, filespace, type, nativeType;
414 std::vector<hsize_t> storedShape;
418 dataset = H5Dopen(parentHandle, datasetName.c_str(), H5P_DEFAULT);
420 sError =
"Cannot open dataset.";
423 filespace = H5Dget_space(dataset);
424 type = H5Dget_type(dataset);
425 nativeType = H5Tget_native_type(type, H5T_DIR_DESCEND);
426 if(!H5Tequal(nativeType, hdf5Type<T>())) {
427 sError =
"Requested data type does not matched stored one.";
432 ndims = H5Sget_simple_extent_ndims(filespace);
434 sError = ndims == 0?
"Dataset is a scalar.":
"Cannot get number of dimensions.";
437 storedShape.resize(ndims);
438 if(H5Sget_simple_extent_dims(filespace, &storedShape[0], NULL)<0) {
439 sError =
"Cannot get simple extent dimensions.";
442 memspace = H5Screate_simple(ndims, &storedShape[0], NULL);
444 sError =
"Could not allocate memory space.";
450 std::size_t numberOfElements = 1;
451 for(std::size_t i=0;i<storedShape.size();++i)
452 numberOfElements *= storedShape[i];
453 data.resize(numberOfElements);
455 if(H5Dread(dataset, nativeType, memspace, filespace,H5P_DEFAULT, &data[0])!=0) {
456 sError =
"Could not read data from dataset.";
459 shape.assign(storedShape.begin(),storedShape.end());
465 H5Tclose(nativeType);
469 if(!sError.empty()) {
470 throw std::runtime_error(
"HDF5: Loading dataset '"+datasetName+
"' failed: "+sError);
484 const hid_t& parentHandle,
485 const std::string& datasetName,
488 assert(parentHandle >= 0);
489 HandleCheck<ANDRES_GRAPH_HDF5_DEBUG> handleCheck;
492 hid_t dataset, filespace, type, nativeType, memspace;
494 dataset = H5Dopen(parentHandle, datasetName.c_str(), H5P_DEFAULT);
496 sError =
"Cannot open dataset.";
499 filespace = H5Dget_space(dataset);
500 type = H5Dget_type(dataset);
501 nativeType = H5Tget_native_type(type, H5T_DIR_DESCEND);
502 if(!H5Tequal(nativeType, hdf5Type<T>())) {
503 sError =
"Stored data type does not match the one requested.";
506 ndims = H5Sget_simple_extent_ndims(filespace);
508 sError =
"Dataset dimension is not zero.";
511 memspace = H5Screate(H5S_SCALAR);
513 sError =
"Failed to create memory dataspace.";
516 if(H5Dread(dataset, nativeType, memspace, filespace,H5P_DEFAULT, &data)<0) {
517 sError =
"Failed to write scalar.";
524 H5Tclose(nativeType);
529 if(!sError.empty()) {
530 throw std::runtime_error(
531 "HDF5:Loading scalar from dataset '"+datasetName+
"' failed: " + sError
548 const hid_t& parentHandle,
549 const std::string& datasetName,
552 assert(parentHandle>0);
553 HandleCheck<ANDRES_GRAPH_HDF5_DEBUG> handleCheck;
557 hid_t dataSet, fileType, dataSpace, memType;
560 dataSet = H5Dopen (parentHandle, datasetName.c_str(), H5P_DEFAULT);
561 fileType = H5Dget_type(dataSet);
562 dataSpace = H5Dget_space(dataSet);
566 hsize_t ndims = H5Sget_simple_extent_dims(dataSpace, NULL, NULL);
568 sError =
"Dataset spans more than 1 dimensions.";
571 ndims = H5Sget_simple_extent_dims(dataSpace, dims, NULL);
574 sError =
"Dataset contains more than 1 elements.";
580 htri_t isVariable = H5Tis_variable_str(fileType);
582 sError =
"String type is unsupported.";
592 stringSize = H5Tget_size(fileType);
593 memType = H5Tcopy(H5T_C_S1);
594 H5Tset_size(memType,stringSize);
596 std::vector<char> buf(stringSize);
597 herr_t status = H5Dread (dataSet, memType, H5S_ALL, H5S_ALL, H5P_DEFAULT, &buf[0]);
599 sError =
"Could not read string data.";
602 data.assign(&buf[0]);
608 H5Sclose (dataSpace);
611 if(!sError.empty()) {
612 throw std::runtime_error(
613 "HDF5: Loading string from dataset '"+datasetName+
"' failed: "+sError
623 #endif // #ifndef ANDRES_GRAPH_HDF5_HXX