openPMD-api
HDF5Auxiliary.hpp
1 /* Copyright 2017-2020 Fabian Koller
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * openPMD-api is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 #pragma once
22 
23 #include "openPMD/auxiliary/StringManip.hpp"
24 #include "openPMD/backend/Attribute.hpp"
25 #include "openPMD/backend/Writable.hpp"
26 #include "openPMD/IO/HDF5/HDF5FilePosition.hpp"
27 
28 #include <hdf5.h>
29 
30 #include <complex>
31 #include <stack>
32 #include <string>
33 #include <typeinfo>
34 #include <unordered_map>
35 #include <utility>
36 
37 
38 namespace openPMD
39 {
41 {
42  std::unordered_map< std::string, hid_t > m_userTypes;
43 
44  GetH5DataType( std::unordered_map< std::string, hid_t > userTypes )
45  : m_userTypes{ std::move(userTypes) }
46  {
47  }
48 
49  hid_t
50  operator()(Attribute const &att)
51  {
52  using DT = Datatype;
53  switch (att.dtype) {
54  case DT::CHAR:
55  case DT::VEC_CHAR:
56  return H5Tcopy(H5T_NATIVE_CHAR);
57  case DT::UCHAR:
58  case DT::VEC_UCHAR:
59  return H5Tcopy(H5T_NATIVE_UCHAR);
60  case DT::SHORT:
61  case DT::VEC_SHORT:
62  return H5Tcopy(H5T_NATIVE_SHORT);
63  case DT::INT:
64  case DT::VEC_INT:
65  return H5Tcopy(H5T_NATIVE_INT);
66  case DT::LONG:
67  case DT::VEC_LONG:
68  return H5Tcopy(H5T_NATIVE_LONG);
69  case DT::LONGLONG:
70  case DT::VEC_LONGLONG:
71  return H5Tcopy(H5T_NATIVE_LLONG);
72  case DT::USHORT:
73  case DT::VEC_USHORT:
74  return H5Tcopy(H5T_NATIVE_USHORT);
75  case DT::UINT:
76  case DT::VEC_UINT:
77  return H5Tcopy(H5T_NATIVE_UINT);
78  case DT::ULONG:
79  case DT::VEC_ULONG:
80  return H5Tcopy(H5T_NATIVE_ULONG);
81  case DT::ULONGLONG:
82  case DT::VEC_ULONGLONG:
83  return H5Tcopy(H5T_NATIVE_ULLONG);
84  case DT::FLOAT:
85  case DT::VEC_FLOAT:
86  return H5Tcopy(H5T_NATIVE_FLOAT);
87  case DT::DOUBLE:
88  case DT::ARR_DBL_7:
89  case DT::VEC_DOUBLE:
90  return H5Tcopy(H5T_NATIVE_DOUBLE);
91  case DT::LONG_DOUBLE:
92  case DT::VEC_LONG_DOUBLE:
93  return H5Tcopy(H5T_NATIVE_LDOUBLE);
94  case DT::CFLOAT:
95  case DT::VEC_CFLOAT:
96  return H5Tcopy( m_userTypes.at( typeid(std::complex< float >).name() ) );
97  case DT::CDOUBLE:
98  case DT::VEC_CDOUBLE:
99  return H5Tcopy( m_userTypes.at( typeid(std::complex< double >).name() ) );
100  case DT::CLONG_DOUBLE:
101  case DT::VEC_CLONG_DOUBLE:
102  return H5Tcopy( m_userTypes.at( typeid(std::complex< long double >).name() ) );
103  case DT::STRING: {
104  hid_t string_t_id = H5Tcopy(H5T_C_S1);
105  H5Tset_size(string_t_id, att.get<std::string>().size());
106  return string_t_id;
107  }
108  case DT::VEC_STRING: {
109  hid_t string_t_id = H5Tcopy(H5T_C_S1);
110  size_t max_len = 0;
111  for (std::string const &s : att.get<std::vector<std::string> >())
112  max_len = std::max(max_len, s.size());
113  H5Tset_size(string_t_id, max_len);
114  return string_t_id;
115  }
116  case DT::BOOL:
117  return H5Tcopy( m_userTypes.at( typeid(bool).name() ) );
118  case DT::DATATYPE:
119  throw std::runtime_error("[HDF5] Meta-Datatype leaked into IO");
120  case DT::UNDEFINED:
121  throw std::runtime_error("[HDF5] Unknown Attribute datatype (HDF5 datatype)");
122  default:
123  throw std::runtime_error("[HDF5] Datatype not implemented");
124  }
125  }
126 };
127 
128 inline hid_t
129 getH5DataSpace(Attribute const& att)
130 {
131  using DT = Datatype;
132  switch( att.dtype )
133  {
134  case DT::CHAR:
135  case DT::UCHAR:
136  case DT::SHORT:
137  case DT::INT:
138  case DT::LONG:
139  case DT::LONGLONG:
140  case DT::USHORT:
141  case DT::UINT:
142  case DT::ULONG:
143  case DT::ULONGLONG:
144  case DT::FLOAT:
145  case DT::DOUBLE:
146  case DT::LONG_DOUBLE:
147  case DT::CFLOAT:
148  case DT::CDOUBLE:
149  case DT::CLONG_DOUBLE:
150  case DT::STRING:
151  case DT::BOOL:
152  return H5Screate(H5S_SCALAR);
153  case DT::VEC_CHAR:
154  {
155  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
156  hsize_t dims[1] = {att.get< std::vector< char > >().size()};
157  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
158  return vec_t_id;
159  }
160  case DT::VEC_SHORT:
161  {
162  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
163  hsize_t dims[1] = {att.get< std::vector< short > >().size()};
164  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
165  return vec_t_id;
166  }
167  case DT::VEC_INT:
168  {
169  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
170  hsize_t dims[1] = {att.get< std::vector< int > >().size()};
171  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
172  return vec_t_id;
173  }
174  case DT::VEC_LONG:
175  {
176  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
177  hsize_t dims[1] = {att.get< std::vector< long > >().size()};
178  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
179  return vec_t_id;
180  }
181  case DT::VEC_LONGLONG:
182  {
183  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
184  hsize_t dims[1] = {att.get< std::vector< long long > >().size()};
185  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
186  return vec_t_id;
187  }
188  case DT::VEC_UCHAR:
189  {
190  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
191  hsize_t dims[1] = {att.get< std::vector< unsigned char > >().size()};
192  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
193  return vec_t_id;
194  }
195  case DT::VEC_USHORT:
196  {
197  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
198  hsize_t dims[1] = {att.get< std::vector< unsigned short > >().size()};
199  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
200  return vec_t_id;
201  }
202  case DT::VEC_UINT:
203  {
204  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
205  hsize_t dims[1] = {att.get< std::vector< unsigned int > >().size()};
206  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
207  return vec_t_id;
208  }
209  case DT::VEC_ULONG:
210  {
211  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
212  hsize_t dims[1] = {att.get< std::vector< unsigned long > >().size()};
213  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
214  return vec_t_id;
215  }
216  case DT::VEC_ULONGLONG:
217  {
218  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
219  hsize_t dims[1] = {att.get< std::vector< unsigned long long > >().size()};
220  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
221  return vec_t_id;
222  }
223  case DT::VEC_FLOAT:
224  {
225  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
226  hsize_t dims[1] = {att.get< std::vector< float > >().size()};
227  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
228  return vec_t_id;
229  }
230  case DT::VEC_DOUBLE:
231  {
232  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
233  hsize_t dims[1] = {att.get< std::vector< double > >().size()};
234  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
235  return vec_t_id;
236  }
237  case DT::VEC_LONG_DOUBLE:
238  {
239  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
240  hsize_t dims[1] = {att.get< std::vector< long double > >().size()};
241  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
242  return vec_t_id;
243  }
244  case DT::VEC_CFLOAT:
245  {
246  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
247  hsize_t dims[1] = {att.get< std::vector< std::complex< float > > >().size()};
248  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
249  return vec_t_id;
250  }
251  case DT::VEC_CDOUBLE:
252  {
253  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
254  hsize_t dims[1] = {att.get< std::vector< std::complex< double > > >().size()};
255  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
256  return vec_t_id;
257  }
258  case DT::VEC_CLONG_DOUBLE:
259  {
260  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
261  hsize_t dims[1] = {att.get< std::vector< std::complex< long double > > >().size()};
262  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
263  return vec_t_id;
264  }
265  case DT::VEC_STRING:
266  {
267  hid_t vec_t_id = H5Screate(H5S_SIMPLE);
268  hsize_t dims[1] = {att.get< std::vector< std::string > >().size()};
269  H5Sset_extent_simple(vec_t_id, 1, dims, nullptr);
270  return vec_t_id;
271  }
272  case DT::ARR_DBL_7:
273  {
274  hid_t array_t_id = H5Screate(H5S_SIMPLE);
275  hsize_t dims[1] = {7};
276  H5Sset_extent_simple(array_t_id, 1, dims, nullptr);
277  return array_t_id;
278  }
279  case DT::UNDEFINED:
280  throw std::runtime_error("Unknown Attribute datatype (HDF5 dataspace)");
281  default:
282  throw std::runtime_error("Datatype not implemented in HDF5 IO");
283  }
284 }
285 
286 inline std::string
287 concrete_h5_file_position(Writable* w)
288 {
289  std::stack< Writable* > hierarchy;
290  if( !w->abstractFilePosition )
291  w = w->parent;
292  while( w )
293  {
294  hierarchy.push(w);
295  w = w->parent;
296  }
297 
298  std::string pos;
299  while( !hierarchy.empty() )
300  {
301  pos += std::dynamic_pointer_cast< HDF5FilePosition >(hierarchy.top()->abstractFilePosition)->location;
302  hierarchy.pop();
303  }
304 
305  return auxiliary::replace_all(pos, "//", "/");
306 }
307 } // openPMD
U get() const
Retrieve a stored specific Attribute and cast if convertible.
Definition: Attribute.hpp:232
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:42
Varidic datatype supporting at least all formats for attributes specified in the openPMD standard...
Definition: Attribute.hpp:50
Definition: HDF5Auxiliary.hpp:40
Public definitions of openPMD-api.
Definition: Date.cpp:29
Layer to mirror structure of logical data and persistent data in file.
Definition: Writable.hpp:55
Definition: HDF5FilePosition.hpp:28