Medusa  1.1
Coordinate Free Mehless Method implementation
HDF.hpp
Go to the documentation of this file.
1 #ifndef MEDUSA_BITS_IO_HDF_HPP_
2 #define MEDUSA_BITS_IO_HDF_HPP_
3 
9 #include "HDF_fwd.hpp"
11 #include <tuple>
12 
13 namespace mm {
14 
15 template <class T>
16 T HDF::readAttribute(const std::string& attr_name) const {
17  assert_msg(H5Iis_valid(group), "Group id %d invalid. Did you open a group before reading?",
18  group);
19  hid_t attr = H5Aopen(group, attr_name.c_str(), H5P_DEFAULT);
20  assert_msg(attr >= 0, "Attribute '%s' could not be accessed in group '%s' in file '%s'.",
21  attr_name, group_name_, filename_);
22 
23  hid_t type = H5Aget_type(attr);
24  assert_msg(type >= 0, "Failed getting type of attribute '%s' in group '%s' in file '%s'.",
25  attr_name, group_name_, filename_);
26 
27  T result;
28  herr_t status = H5Aread(attr, type, &result);
29  assert_msg(status >= 0, "Failed reading attribute '%s' from group '%s' in file '%s'.",
30  attr_name, groupName(), filename_);
31 
32  H5Tclose(type);
33  H5Aclose(attr);
34  return result;
35 }
36 
37 template <class T>
38 void HDF::writeAttribute(const std::string& attr_name, const T& value, const hid_t& type,
39  bool overwrite) const {
40  assert_msg(H5Iis_valid(group), "Group id %d invalid. Did you open a group before writing?",
41  group);
42  if (H5Aexists(group, attr_name.c_str())) {
43  if (!overwrite) {
44  assert_msg(false, "Attribute '%s' in group '%s' in file '%s' already exists. To "
45  "overwrite its contents use parameter overwrite=true.",
46  attr_name, group_name_, filename_);
47  return;
48  }
49  herr_t status = H5Adelete(group, attr_name.c_str());
50  assert_msg(status >= 0, "Failed deleting existing attribute '%s' in group '%s' in "
51  "file '%s' before writing a new one.",
52  attr_name, group_name_, filename_);
53  }
54 
55  hid_t space = H5Screate(H5S_SCALAR);
56  hid_t attr = H5Acreate(group, attr_name.c_str(), type, space, H5P_DEFAULT, H5P_DEFAULT);
57  assert_msg(attr >= 0, "Failed creating attribute '%s' in group '%s' in file '%s'.",
58  attr_name, group_name_, filename_);
59  herr_t status = H5Awrite(attr, type, &value);
60  assert_msg(status >= 0, "Failed writing attribute '%s' to group '%s' in file '%s'.",
61  attr_name, group_name_, filename_);
62  H5Sclose(space);
63  H5Aclose(attr);
64 }
65 
66 template <typename T>
67 std::pair<std::vector<hsize_t>, std::vector<T>>
68 HDF::readLinearArray(const std::string& dataset_name) const {
69  assert_msg(H5Iis_valid(group), "Group id %d invalid. Did you open a group before reading?",
70  group);
71  hid_t dataset = H5Dopen(group, dataset_name.c_str(), H5P_DEFAULT);
72  assert_msg(dataset >= 0, "Dataset '%s' could not be accessed in group '%s' in file '%s'.",
73  dataset_name, group_name_, filename_);
74 
75  hid_t dataspace = H5Dget_space(dataset);
76  const int ndims = H5Sget_simple_extent_ndims(dataspace);
77  std::vector<hsize_t> dims(ndims);
78  H5Sget_simple_extent_dims(dataspace, dims.data(), nullptr); // read dimension into dims
79  hsize_t size = 1;
80  for (int d = 0; d < ndims; ++d) size *= dims[d];
81 
82  std::vector<T> linear_value(size);
83  hid_t type = H5Dget_type(dataset);
84  herr_t status = H5Dread(dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT,
85  linear_value.data());
86  assert_msg(status >= 0, "Failed reading dataset '%s' from group '%s' in file '%s'.",
87  dataset_name, group_name_, filename_);
88  H5Tclose(type);
89  H5Sclose(dataspace);
90  H5Dclose(dataset);
91  return {dims, linear_value};
92 }
93 
94 template <typename T>
95 std::vector<T> HDF::read1DArray(const std::string& dataset_name) const {
96  std::vector<hsize_t> dims;
97  std::vector<T> value;
98  std::tie(dims, value) = readLinearArray<T>(dataset_name);
99  assert_msg(dims.size() == 1, "This function is for one dimensional arrays only, got %d-D "
100  "array with sizes %s.", dims.size(), dims);
101  return value;
102 }
103 
104 template <typename T>
105 std::vector<std::vector<T>> HDF::read2DArray(const std::string& dataset_name) const {
106  std::vector<hsize_t> dims;
107  std::vector<T> linear_value;
108  std::tie(dims, linear_value) = readLinearArray<T>(dataset_name);
109  assert_msg(dims.size() == 2, "This function is for two dimensional arrays only, got %d-D "
110  "array with sizes %s.", dims.size(), dims);
111  hsize_t cols = dims[0];
112  hsize_t rows = dims[1];
113 
114  std::vector<std::vector<T>> value(rows, std::vector<T>(cols));
115  for (hsize_t i = 0; i < rows; i++)
116  for (hsize_t j = 0; j < cols; j++)
117  value[i][j] = linear_value[j * rows + i];
118 
119  return value;
120 }
121 
122 template <typename T>
123 std::vector<std::vector<std::vector<T>>> HDF::read3DArray(const std::string& dataset_name) const {
124  std::vector<hsize_t> dims;
125  std::vector<T> linear_value;
126  std::tie(dims, linear_value) = readLinearArray<T>(dataset_name);
127  assert_msg(dims.size() == 3, "This function is for three dimensional arrays only, got %d-D "
128  "array with sizes %s.", dims.size(), dims);
129  hsize_t tubes = dims[0];
130  hsize_t cols = dims[1];
131  hsize_t rows = dims[2];
132 
133  std::vector<std::vector<std::vector<T>>> value(rows, std::vector<std::vector<T>>(
134  cols, std::vector<T>(tubes)));
135  for (hsize_t i = 0; i < rows; i++)
136  for (hsize_t j = 0; j < cols; j++)
137  for (hsize_t k = 0; k < tubes; k++)
138  value[i][j][k] = linear_value[k * cols * rows + j * rows + i];
139 
140  return value;
141 }
142 
143 template <int dim, typename T>
144 void HDF::writeLinearArray(const std::string& dataset_name, const T* value,
145  const std::array<hsize_t, dim>& sizes, hid_t type,
146  bool overwrite) const {
147  assert_msg(H5Iis_valid(group), "Group id %d invalid. Did you open a group before writing?",
148  group);
149  hid_t dataset;
150  if (H5Lexists(group, dataset_name.c_str(), H5P_DEFAULT)) {
151  if (!overwrite) {
152  assert_msg(false, "Dataset '%s' in group '%s' in file '%s' already exists. To "
153  "overwrite its contents use parameter overwrite=true.",
154  dataset_name, group_name_, filename_);
155  return;
156  }
157  dataset = H5Dopen(group, dataset_name.c_str(), H5P_DEFAULT);
158  assert_msg(dataset >= 0, "Failed opening dataset '%s' in group '%s' in file '%s'.",
159  dataset_name, group_name_, filename_);
160  hid_t dataspace = H5Dget_space(dataset);
161  const int ndims = H5Sget_simple_extent_ndims(dataspace);
162  assert_msg(ndims == dim, "Expected %d-dim array, got %d-dim.", dim, ndims);
163  hsize_t cur_dims[dim]; // NOLINT(*)
164  H5Sget_simple_extent_dims(dataspace, cur_dims, nullptr); // read dimension into sizes
165  for (int d = 0; d < dim; ++d) {
166  assert_msg(cur_dims[d] == sizes[d],
167  "Only data of same old_size can be overwritten, but new dataset has "
168  "old_size '%d' and existing has old_size '%d'.", sizes[d], cur_dims[d]);
169  }
170  H5Sclose(dataspace);
171  } else {
172  hid_t dataspace;
173  const int rank = dim;
174  const hsize_t* max_dims = nullptr; // same as sizes
175  dataspace = H5Screate_simple(rank, &sizes[0], max_dims);
176  dataset = H5Dcreate(group, dataset_name.c_str(), type, dataspace,
177  H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
178  assert_msg(dataset >= 0, "Failed creating dataset '%s' in group '%s' in file '%s'.",
179  dataset_name, group_name_, filename_);
180  H5Sclose(dataspace);
181  }
182  int size = 1; for (int d = 0; d < dim; ++d) { size *= sizes[d]; }
183  herr_t status = H5Dwrite(dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, value);
184  assert_msg(status >= 0, "Failed writing dataset '%s' to group '%s' in file '%s'.",
185  dataset_name, group_name_, filename_);
186  H5Dclose(dataset);
187 }
188 
189 template <typename T, typename array_t>
190 void HDF::write1DArray(const std::string& dataset_name, const array_t& value, hid_t type,
191  bool overwrite) const {
192  hsize_t size = value.size();
193  std::vector<T> cast_value(size);
194  for (hsize_t j = 0; j < size; j++) { cast_value[j] = static_cast<T>(value[j]); }
195  writeLinearArray<1>(dataset_name, cast_value.data(), {size}, type, overwrite);
196 }
197 
198 template <typename T, class array_t>
199 void HDF::write2DArray(const std::string& dataset_name, const array_t& value, hid_t type,
200  bool overwrite, std::false_type) const {
201  size_t rows = value.size();
202  size_t cols = (rows == 0) ? 0 : value[0].size();
203  std::vector<T> linear_value(rows * cols);
204  for (size_t i = 0; i < rows; i++) {
205  assert_msg(static_cast<size_t>(value[i].size()) == cols,
206  "Not all subarrays are of the same size, subarray 0 has size %d, but subarray "
207  "%d has size %d. Maybe use pad to fix raggedness?", cols, i, value[i].size());
208  for (size_t j = 0; j < cols; j++) {
209  linear_value[j * rows + i] = static_cast<T>(value[i][j]);
210  }
211  }
212  writeLinearArray<2>(dataset_name, linear_value.data(), {cols, rows}, type, overwrite);
213 }
214 
215 template <typename T, class array_t>
216 void HDF::write3DArray(const std::string& dataset_name, const array_t& value, hid_t type,
217  bool overwrite) const {
218  size_t rows = value.size();
219  size_t cols = (rows == 0) ? 0 : value[0].size();
220  size_t tubes = (cols == 0) ? 0 : value[0][0].size();
221  std::vector<T> linear_value(rows * cols * tubes);
222  for (size_t i = 0; i < rows; i++) {
223  assert_msg(static_cast<size_t>(value[i].size()) == cols,
224  "Not all subarrays are of the same size, subarray 0 has size %d, but subarray "
225  "%d has size %d. Maybe use pad to fix raggedness?", cols, i, value[i].size());
226  for (size_t j = 0; j < cols; j++) {
227  assert_msg(static_cast<size_t>(value[i][j].size()) == tubes,
228  "Not all subarrays are of the same size, subarray (0, 0) has size %d, "
229  "but subarray (%d, %d) has size %d. Maybe use pad to fix raggedness?",
230  tubes, i, j, value[i][j].size());
231  for (size_t k = 0; k < tubes; ++k) {
232  linear_value[k * cols * rows + j * rows + i] = static_cast<T>(value[i][j][k]);
233  }
234  }
235  }
236  writeLinearArray<3>(dataset_name, linear_value.data(), {tubes, cols, rows}, type, overwrite);
237 }
238 
239 template <typename array_t>
240 void HDF::writeIntArray(const std::string& dataset_name, const array_t& value,
241  bool overwrite) const {
242  write1DArray<int>(dataset_name, value, H5T_NATIVE_INT, overwrite);
243 }
244 
245 template <typename array_t>
246 void HDF::writeDoubleArray(const std::string& dataset_name, const array_t& value,
247  bool overwrite) const {
248  write1DArray<double>(dataset_name, value, H5T_NATIVE_DOUBLE, overwrite);
249 }
250 
251 template <typename array_t>
252 void HDF::writeFloatArray(const std::string& dataset_name, const array_t& value,
253  bool overwrite) const {
254  write1DArray<float>(dataset_name, value, H5T_NATIVE_FLOAT, overwrite);
255 }
256 
257 template <typename array_t>
258 void HDF::writeInt2DArray(const std::string& dataset_name, const array_t& value,
259  bool overwrite) const {
260  write2DArray<int>(dataset_name, value, H5T_NATIVE_INT, overwrite);
261 }
262 
263 template <typename array_t>
264 void HDF::writeDouble2DArray(const std::string& dataset_name, const array_t& value,
265  bool overwrite) const {
266  write2DArray<double>(dataset_name, value, H5T_NATIVE_DOUBLE, overwrite);
267 }
268 
269 template <typename array_t>
270 void HDF::writeFloat2DArray(const std::string& dataset_name, const array_t& value,
271  bool overwrite) const {
272  write2DArray<float>(dataset_name, value, H5T_NATIVE_FLOAT, overwrite);
273 }
274 
275 template <typename array_t>
276 void HDF::writeInt3DArray(const std::string& dataset_name, const array_t& value,
277  bool overwrite) const {
278  write3DArray<int>(dataset_name, value, H5T_NATIVE_INT, overwrite);
279 }
280 
281 template <typename array_t>
282 void HDF::writeDouble3DArray(const std::string& dataset_name, const array_t& value,
283  bool overwrite) const {
284  write3DArray<double>(dataset_name, value, H5T_NATIVE_DOUBLE, overwrite);
285 }
286 
287 template <typename array_t>
288 void HDF::writeFloat3DArray(const std::string& dataset_name, const array_t& value,
289  bool overwrite) const {
290  write3DArray<float>(dataset_name, value, H5T_NATIVE_FLOAT, overwrite);
291 }
292 
293 template <typename conf_t>
294 void HDF::writeXML(const std::string& name, const conf_t& conf, bool overwrite) {
295  std::string group = group_name_;
296  assert_msg(!group.empty(), "Open a group before writing.");
297  if (group.back() == '/') openGroup(group+name);
298  else openGroup(group+'/'+name);
299  std::vector<std::pair<std::string, std::string>> data = conf.getAll();
300  for (const auto& kv : data) {
301  try {
302  std::string::size_type num_read;
303  double x = std::stod(kv.second, &num_read);
304  if (num_read < kv.second.size()) { // some characters were not read, it's a string
305  throw std::invalid_argument(kv.second);
306  }
307  writeDoubleAttribute(kv.first, x, overwrite);
308  } catch (const std::invalid_argument&) {
309  writeStringAttribute(kv.first, kv.second, overwrite);
310  }
311  }
312  openGroup(group);
313 }
314 
315 template <typename SparseMatrixType>
316 void HDF::writeSparseMatrix(const std::string& name, SparseMatrixType& matrix, bool one_based,
317  bool overwrite) {
318  std::vector<std::array<double, 3>> triplets(matrix.nonZeros());
319  int c = 0;
320  for (int k = 0; k < matrix.outerSize(); ++k) {
321  for (typename SparseMatrixType::InnerIterator it(matrix, k); it; ++it) {
322  triplets[c][0] = one_based+it.row();
323  triplets[c][1] = one_based+it.col();
324  triplets[c][2] = it.value();
325  ++c;
326  }
327  }
328  writeDouble2DArray(name, triplets, overwrite);
329 }
330 
331 template <typename domain_t>
332 void HDF::writeDomain(const std::string& name, const domain_t& domain, bool overwrite) {
333  std::string group = group_name_;
334  assert_msg(!group.empty(), "Open a group before writing.");
335  if (group.back() == '/') openGroup(group+name);
336  else openGroup(group+'/'+name);
337  writeDouble2DArray("pos", domain.positions(), overwrite);
338  writeIntAttribute("N", domain.size(), overwrite);
339  writeIntArray("types", domain.types(), overwrite);
340  writeIntArray("bmap", domain.bmap(), overwrite);
341  writeDouble2DArray("normals", domain.normals(), overwrite);
342  openGroup(group);
343 }
344 
345 template <typename timer_t>
346 void HDF::writeTimer(const std::string& name, const timer_t& timer, bool overwrite) {
347  std::string group = group_name_;
348  assert_msg(!group.empty(), "Open a group before writing.");
349  if (group.back() == '/') openGroup(group+name);
350  else openGroup(group+'/'+name);
351  std::vector<std::string> labels = timer.labels();
352  int size = labels.size();
353  if (size == 0) return;
354  for (int i = 1; i < size; ++i) {
355  writeDoubleAttribute(labels[i-1]+"-"+labels[i], timer.duration(labels[i-1], labels[i]),
356  overwrite);
357  }
358  writeDoubleAttribute("total", timer.duration(labels.front(), labels.back()), overwrite);
359  openGroup(group);
360 }
361 
362 } // namespace mm
363 
364 #endif // MEDUSA_BITS_IO_HDF_HPP_
mm::HDF::write2DArray
void write2DArray(const std::string &dataset_name, const array_t &value, hid_t type, bool overwrite) const
Writes given 2D array of given value and type to file.
Definition: HDF_fwd.hpp:296
mm
Root namespace for the whole library.
Definition: Gaussian.hpp:14
mm::HDF::writeFloatArray
void writeFloatArray(const std::string &dataset_name, const array_t &value, bool overwrite=false) const
Write given value as a 1D array of floatss.
Definition: HDF.hpp:252
mm::HDF::write1DArray
void write1DArray(const std::string &dataset_name, const array_t &value, hid_t type, bool overwrite) const
Writes given 1D array with given value and type to file.
Definition: HDF.hpp:190
mm::HDF::writeTimer
void writeTimer(const std::string &name, const timer_t &timer, bool overwrite=false)
Writes given timer to file.
Definition: HDF.hpp:346
dim
@ dim
Number of elements of this matrix.
Definition: MatrixBaseAddons.hpp:14
mm::HDF::read2DArray
std::vector< std::vector< T > > read2DArray(const std::string &dataset_name) const
Read given dataset into 2D array of vectors.
Definition: HDF.hpp:105
mm::HDF::writeDoubleAttribute
void writeDoubleAttribute(const std::string &attr_name, double value, bool overwrite=false) const
Write double attribute.
Definition: HDF.cpp:146
mm::HDF::group
hid_t group
Currently open group identifier.
Definition: HDF_fwd.hpp:80
mm::HDF::readLinearArray
std::pair< std::vector< hsize_t >, std::vector< T > > readLinearArray(const std::string &dataset_name) const
Read given dataset into linear dim-D array.
Definition: HDF.hpp:68
assert_msg
#define assert_msg(cond,...)
Assert with better error reporting.
Definition: assert.hpp:75
mm::HDF::writeFloat3DArray
void writeFloat3DArray(const std::string &dataset_name, const array_t &value, bool overwrite=false) const
Write given value as a 3D array of floats.
Definition: HDF.hpp:288
mm::HDF::read1DArray
std::vector< T > read1DArray(const std::string &dataset_name) const
Read 1D dataset given by dataset_name.
Definition: HDF.hpp:95
mm::HDF::group_name_
std::string group_name_
Current group name.
Definition: HDF_fwd.hpp:77
mm::HDF::writeIntArray
void writeIntArray(const std::string &dataset_name, const array_t &value, bool overwrite=false) const
Write given value as a 1D array of ints.
Definition: HDF.hpp:240
mm::HDF::writeStringAttribute
void writeStringAttribute(const std::string &attr_name, const std::string &value, bool overwrite=false) const
Write string attribute.
Definition: HDF.cpp:154
HDF_fwd.hpp
mm::HDF::write3DArray
void write3DArray(const std::string &dataset_name, const array_t &value, hid_t type, bool overwrite) const
Writes given 3D array of given value and type to file.
Definition: HDF.hpp:216
mm::HDF::read3DArray
std::vector< std::vector< std::vector< T > > > read3DArray(const std::string &dataset_name) const
Read given dataset into 3D array of vectors.
Definition: HDF.hpp:123
mm::HDF::readAttribute
T readAttribute(const std::string &attr_name) const
Read attribute given by attr_name.
Definition: HDF.hpp:16
mm::HDF::writeInt2DArray
void writeInt2DArray(const std::string &dataset_name, const array_t &value, bool overwrite=false) const
Write given value as a 2D array of ints.
Definition: HDF.hpp:258
mm::HDF::writeFloat2DArray
void writeFloat2DArray(const std::string &dataset_name, const array_t &value, bool overwrite=false) const
Write given value as a 2D array of floats.
Definition: HDF.hpp:270
assert.hpp
mm::HDF::writeInt3DArray
void writeInt3DArray(const std::string &dataset_name, const array_t &value, bool overwrite=false) const
Write given value as a 3D array of ints.
Definition: HDF.hpp:276
mm::HDF::filename_
std::string filename_
Current file name.
Definition: HDF_fwd.hpp:76
mm::HDF::groupName
const std::string & groupName() const
Get current group name.
Definition: HDF_fwd.hpp:174
mm::HDF::writeIntAttribute
void writeIntAttribute(const std::string &attr_name, int value, bool overwrite=false) const
Write int attribute.
Definition: HDF.cpp:138
mm::HDF::writeDouble2DArray
void writeDouble2DArray(const std::string &dataset_name, const array_t &value, bool overwrite=false) const
Write given value as a 2D array of doubles.
Definition: HDF.hpp:264
mm::HDF::writeLinearArray
void writeLinearArray(const std::string &dataset_name, const T *value, const std::array< hsize_t, dim > &sizes, hid_t type, bool overwrite) const
Writes a dim-dimensional dataset stored in 1D array in col-major fashion.
Definition: HDF.hpp:144
mm::HDF::writeAttribute
void writeAttribute(const std::string &attr_name, const T &value, const hid_t &type, bool overwrite=false) const
Writes given attribute with given value and type to file.
Definition: HDF.hpp:38
mm::HDF::writeDoubleArray
void writeDoubleArray(const std::string &dataset_name, const array_t &value, bool overwrite=false) const
Write given value as a 1D array of doubles.
Definition: HDF.hpp:246
mm::HDF::writeDouble3DArray
void writeDouble3DArray(const std::string &dataset_name, const array_t &value, bool overwrite=false) const
Write given value as a 3D array of doubles.
Definition: HDF.hpp:282
mm::HDF::writeDomain
void writeDomain(const std::string &name, const domain_t &domain, bool overwrite=false)
Writes given domain discretization to file.
Definition: HDF.hpp:332
mm::HDF::openGroup
void openGroup(std::string group_name)
Open given group, closing any previously opened group().
Definition: HDF.cpp:48
mm::HDF::writeXML
void writeXML(const std::string &name, const conf_t &conf, bool overwrite=false)
Writes given XML object to file.
Definition: HDF.hpp:294
mm::HDF::writeSparseMatrix
void writeSparseMatrix(const std::string &name, SparseMatrixType &matrix, bool one_based=true, bool overwrite=false)
Writes a sparse matrix.
Definition: HDF.hpp:316