HOPS
HOPS class reference
MHO_ContainerHDF5Converter.hh
Go to the documentation of this file.
1 #ifndef MHO_ContainerHDF5Converter_HH__
2 #define MHO_ContainerHDF5Converter_HH__
3 
4 #include "MHO_ClassIdentity.hh"
7 
8 #include "MHO_Axis.hh"
9 #include "MHO_AxisPack.hh"
10 #include "MHO_ObjectTags.hh"
11 #include "MHO_ScalarContainer.hh"
12 #include "MHO_TableContainer.hh"
13 #include "MHO_Taggable.hh"
14 #include "MHO_VectorContainer.hh"
15 
16 #include <sstream>
17 
18 #include "hdf5.h"
19 #include "hdf5_hl.h"
20 
21 #include "MHO_HDF5TypeCode.hh"
22 #include "MHO_NumpyTypeCode.hh"
23 // #include "MHO_HDF5Attributes.hh"
24 // #include "MHO_HDF5Datasets.hh"
26 
27 namespace hops
28 {
29 
40 {
41  public:
43  virtual ~MHO_HDF5Converter(){};
44 
45  virtual void SetObjectToConvert(MHO_Serializable* ) = 0;
46 
47  virtual void SetObjectMetaData(const mho_json& mdata) { fMetaData = mdata; }
48 
49  virtual void WriteToHDF5File(hid_t /*file_id*/, std::string /*group_prefix*/) = 0;
50 
51  protected:
53 };
54 
55 template< typename XContainerType > class MHO_ContainerHDF5Converter: public MHO_HDF5Converter
56 {
57  public:
58  MHO_ContainerHDF5Converter(): MHO_HDF5Converter() { fContainer = nullptr; }
59 
61  {
62  fContainer = dynamic_cast< XContainerType* >(element);
63  }
64 
66 
67  virtual void SetObjectToConvert(MHO_Serializable* obj) { fContainer = dynamic_cast< XContainerType* >(obj); };
68 
69  virtual void WriteToHDF5File(hid_t file_id, std::string group_prefix)
70  {
71  if(fContainer != nullptr)
72  {
73  ConstructHDF5(file_id, group_prefix, fContainer);
74  }
75  }
76 
77  private:
78  XContainerType* fContainer;
79 
80  protected:
81  //unspecialized template doesn't do much
82  template< typename XCheckType >
83  void ConstructHDF5(hid_t /*file_id*/, std::string /*group_prefix*/, const XCheckType* obj)
84  {
85  std::string class_name = MHO_ClassIdentity::ClassName< XCheckType >();
86  std::string class_uuid = MHO_ClassIdentity::GetUUIDFromClass< XCheckType >().as_string();
87  };
88 
89  //use SFINAE to generate specialization for the rest of the container types
90  //that we actually care about
91 
92  //scalar specialization
93  template< typename XCheckType = XContainerType >
94  typename std::enable_if< std::is_base_of< MHO_ScalarContainerBase, XCheckType >::value, void >::type
95  ConstructHDF5(hid_t file_id, std::string group_prefix, const XContainerType* obj)
96  {
97  std::string class_name = MHO_ClassIdentity::ClassName< XContainerType >();
98  std::string class_uuid = MHO_ClassIdentity::GetUUIDFromClass< XContainerType >().as_string();
99  std::string object_uuid = obj->GetObjectUUID().as_string();
100  msg_debug("hdf5interface", "creating scalar type for object with uuid: " << object_uuid << eom);
101  std::string item_group = group_prefix + "/" + object_uuid;
102 
103  if(H5Lexists(file_id, item_group.c_str(), H5P_DEFAULT) == 0)
104  {
105  hid_t group_id = H5Gcreate(file_id, item_group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
106  if(group_id < 0)
107  {
108  msg_error("hdf5interface", "failed to create HDF5 group: " << item_group << eom);
109  }
110  else
111  {
112  std::string name = item_group + "/data";
113  //write the data
114  hid_t dataset_id = -1;
115  herr_t status = make_scalar_dataset< typename XContainerType::value_type >(
116  file_id, dataset_id, name, fContainer->GetValue()); //fMetaData);
117  H5Gclose(group_id);
118  }
119  }
120  };
121 
122  //vector specialization (but not an axis!)
123  template< typename XCheckType = XContainerType >
124  typename std::enable_if< (std::is_base_of< MHO_VectorContainerBase, XCheckType >::value &&
125  !std::is_base_of< MHO_AxisBase, XCheckType >::value),
126  void >::type
127  ConstructHDF5(hid_t file_id, std::string group_prefix, const XContainerType* obj)
128  {
129  std::string class_name = MHO_ClassIdentity::ClassName< XContainerType >();
130  std::string class_uuid = MHO_ClassIdentity::GetUUIDFromClass< XContainerType >().as_string();
131  std::string object_uuid = obj->GetObjectUUID().as_string();
132  msg_debug("hdf5interface", "creating vector type for object with uuid: " << object_uuid << eom);
133 
134  //grab the rank and dimensions
135  hsize_t rank = 1;
136  hsize_t dims[1];
137  auto dim_array = fContainer->GetDimensionArray();
138  for(std::size_t i = 0; i < rank; i++)
139  {
140  dims[i] = dim_array[i];
141  }
142  std::string item_group = group_prefix + "/" + object_uuid;
143 
144  if(H5Lexists(file_id, item_group.c_str(), H5P_DEFAULT) == 0)
145  {
146  hid_t group_id = H5Gcreate(file_id, item_group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
147  if(group_id < 0)
148  {
149  msg_error("hdf5interface", "failed to create HDF5 group: " << item_group << eom);
150  }
151  else
152  {
153  std::string name = item_group + "/data";
154  //write the data
155  hid_t dataset_id = -1;
156  herr_t status = make_dataset< typename XContainerType::value_type >(file_id, dataset_id, name, rank, dims,
157  fContainer->GetData(), fMetaData);
158 
159  H5Gclose(group_id);
160  }
161  }
162  };
163 
164  //axis specialization
165  template< typename XCheckType = XContainerType >
166  typename std::enable_if< std::is_base_of< MHO_AxisBase, XCheckType >::value, void >::type
167  ConstructHDF5(hid_t file_id, std::string group_prefix, const XContainerType* obj)
168  {
169  std::string class_name = MHO_ClassIdentity::ClassName< XContainerType >();
170  std::string class_uuid = MHO_ClassIdentity::GetUUIDFromClass< XContainerType >().as_string();
171  std::string object_uuid = obj->GetObjectUUID().as_string();
172  msg_debug("hdf5interface", "creating axis type for object with uuid: " << object_uuid << eom);
173 
174  //grab the rank and dimensions
175  hsize_t rank = 1;
176  hsize_t dims[1];
177  auto dim_array = fContainer->GetDimensionArray();
178  for(std::size_t i = 0; i < rank; i++)
179  {
180  dims[i] = dim_array[i];
181  }
182  std::string item_group = group_prefix + "/" + object_uuid;
183 
184  if(H5Lexists(file_id, item_group.c_str(), H5P_DEFAULT) == 0)
185  {
186  hid_t group_id = H5Gcreate(file_id, item_group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
187  if(group_id < 0)
188  {
189  msg_error("hdf5interface", "failed to create HDF5 group: " << item_group << eom);
190  }
191  else
192  {
193  std::string name = item_group + "/data";
194  //write the data
195  hid_t dataset_id = -1;
196  herr_t status = make_dataset< typename XContainerType::value_type >(file_id, dataset_id, name, rank, dims,
197  fContainer->GetData(), fMetaData);
198 
199  H5Gclose(group_id);
200  }
201  }
202  };
203 
204  //table specialization
205  template< typename XCheckType = XContainerType >
206  typename std::enable_if< std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
207  ConstructHDF5(hid_t file_id, std::string group_prefix, const XContainerType* obj)
208  {
209  std::string class_name = MHO_ClassIdentity::ClassName< XContainerType >();
210  std::string class_uuid = MHO_ClassIdentity::GetUUIDFromClass< XContainerType >().as_string();
211  std::string object_uuid = obj->GetObjectUUID().as_string();
212  msg_debug("hdf5interface", "creating table type for object with uuid: " << object_uuid << eom);
213 
214  //grab the rank and dimensions
215  hsize_t rank = XContainerType::rank::value;
216  hsize_t dims[XContainerType::rank::value];
217  auto dim_array = obj->GetDimensionArray();
218  for(std::size_t i = 0; i < rank; i++)
219  {
220  dims[i] = dim_array[i];
221  }
222 
223  std::string item_group = group_prefix + "/" + object_uuid;
224 
225  if(H5Lexists(file_id, item_group.c_str(), H5P_DEFAULT) == 0)
226  {
227  hid_t group_id = H5Gcreate(file_id, item_group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
228  if(group_id < 0)
229  {
230  msg_error("hdf5interface", "failed to create HDF5 group: " << item_group << eom);
231  }
232  else
233  {
234  std::string name = item_group + "/data";
235  //write the data
236  hid_t dataset_id = -1;
237  herr_t status = make_dataset< typename XContainerType::value_type >(file_id, dataset_id, name, rank, dims,
238  fContainer->GetData(), fMetaData);
239  // make_dataset< typename XContainerType::value_type >(file_id, dataset_id, name, rank, dims, fContainer->GetData(), fMetaData["tags"]);
240 
241  //now attach the table axes
242  name = item_group;
243  AxisDumper axis_dumper(file_id, dataset_id, name, fMetaData);
244  for(std::size_t idx = 0; idx < obj->GetRank(); idx++)
245  {
246  axis_dumper.SetIndex(idx);
247  apply_at< typename XContainerType::axis_pack_tuple_type, AxisDumper >(*obj, idx, axis_dumper);
248  }
249 
250  H5Gclose(group_id);
251  }
252  }
253  };
254 
256  {
257  public:
258  AxisDumper(hid_t file_id, hid_t ds_id, const std::string& parent, const mho_json& pmetadata)
259  : fFileID(file_id), fDataSetID(ds_id), fParentName(parent), fParentMetadata(pmetadata){};
260 
261  AxisDumper(): fFileID(-1), fDataSetID(-1), fParentName(""){};
263 
264  void SetIndex(std::size_t idx) { fIndex = idx; }
265 
266  void SetFileID(hid_t file_id) { fFileID = file_id; }
267 
268  void SetDataSetID(hid_t ds_id) { fDataSetID = ds_id; }
269 
270  template< typename XAxisType > void operator()(const XAxisType& axis)
271  {
272  mho_json j;
273  std::string class_name = MHO_ClassIdentity::ClassName< XAxisType >();
274  std::string class_uuid = MHO_ClassIdentity::GetUUIDFromClass< XAxisType >().as_string();
275 
276  std::stringstream ssn;
277  ssn << "axis_" << fIndex;
278  std::string ax_name = ssn.str();
279 
280  std::stringstream ss;
281  ss << fParentName << "/axis_";
282  ss << fIndex;
283  std::string item_group = ss.str();
284 
285  if(H5Lexists(fFileID, item_group.c_str(), H5P_DEFAULT) == 0)
286  {
287  hid_t group_id = H5Gcreate(fFileID, item_group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
288  if(group_id < 0)
289  {
290  msg_error("hdf5interface", "failed to create HDF5 group: " << item_group << eom);
291  }
292  else
293  {
294  std::string name = item_group + "/data";
295 
296  mho_json mdata;
297  if(fParentMetadata.contains(ax_name))
298  {
299  mdata = fParentMetadata[ax_name];
300  }
301  msg_debug("hdf5interface", "creating an axis object with name: " << name << eom);
302 
303  //copy the data into a temporary vector (needed to deal with string axes)
304  std::size_t n = axis.GetSize();
305  std::vector< typename XAxisType::value_type > axis_data;
306  for(std::size_t i = 0; i < n; i++)
307  {
308  axis_data.push_back(axis.at(i));
309  }
310 
311  hsize_t dims[1];
312  dims[0] = n;
313  hid_t dataset_id = -1;
314  herr_t status = make_scale< typename XAxisType::value_type >(fFileID, fDataSetID, fIndex,
315  item_group, name, &axis_data, mdata);
316 
317  H5Gclose(group_id);
318  }
319  }
320  };
321 
322  private:
323  hid_t fFileID;
324  hid_t fDataSetID;
325  std::string fParentName;
326  std::size_t fIndex;
327  const mho_json& fParentMetadata;
328  };
329 };
330 
332 {
333  public:
334  MHO_ContainerHDF5Converter(): MHO_HDF5Converter() { fContainer = nullptr; }
335 
337  {
338  fContainer = dynamic_cast< MHO_ObjectTags* >(element);
339  }
340 
342 
343  virtual void SetObjectToConvert(MHO_Serializable* obj) { fContainer = dynamic_cast< MHO_ObjectTags* >(obj); };
344 
345  virtual void WriteToHDF5File(hid_t file_id, std::string group_prefix)
346  {
347  if(fContainer != nullptr)
348  {
349  ConstructHDF5(file_id, group_prefix, fContainer);
350  }
351  }
352 
353  private:
354  void ConstructHDF5(hid_t file_id, std::string group_prefix, const MHO_ObjectTags* obj)
355  {
356  std::string class_name = MHO_ClassIdentity::ClassName< MHO_ObjectTags >();
357  std::string class_uuid = MHO_ClassIdentity::GetUUIDFromClass< MHO_ObjectTags >().as_string();
358  std::string object_uuid = obj->GetObjectUUID().as_string();
359  msg_debug("hdf5interface", "creating tag type for object with uuid: " << object_uuid << eom);
360 
361  std::string item_group = group_prefix + "/" + object_uuid;
362 
363  if(H5Lexists(file_id, item_group.c_str(), H5P_DEFAULT) == 0)
364  {
365  hid_t group_id = H5Gcreate(file_id, item_group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
366  if(group_id < 0)
367  {
368  msg_error("hdf5interface", "failed to create HDF5 group: " << item_group << eom);
369  }
370  else
371  {
372  std::string name = item_group + "/uuid_set";
373  //the data we want to store is a vector of the object UUIDs that we are tagging
374  std::vector< MHO_UUID > uvec = obj->GetAllObjectUUIDs();
375  //now convert these to a vector of strings
376  std::vector< std::string > uuid_vec;
377  for(std::size_t i = 0; i < uvec.size(); i++)
378  {
379  uuid_vec.push_back(uvec[i].as_string());
380  }
381  mho_json mdata = obj->GetMetaDataAsJSON();
382 
383  mdata["class_name"] = class_name;
384  mdata["class_uuid"] = class_uuid;
385  hid_t dataset_id = -1;
386  herr_t status = make_string_vector_dataset(file_id, dataset_id, name, &uuid_vec, mdata);
387 
388  //store plot data as a separate object
389  if(mdata.contains("plot_data"))
390  {
391  std::string plot_group = item_group + "/" + "plot_data";
392  hid_t plot_group_id = H5Gcreate(file_id, plot_group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
393  json_to_hdf5_attributes(mdata["plot_data"], plot_group_id);
394  H5Gclose(plot_group_id);
395  // hid_t pd_dset_id = -1;
396  // std::string plot_data_name = item_group + "/plot_data";
397  // std::string plot_data = mdata["plot_data"].dump();
398  // make_scalar_dataset(file_id, pd_dset_id, plot_data_name, plot_data);
399  }
400 
401  //store paramters as a separate object
402  if(mdata.contains("parameters"))
403  {
404  std::string param_group = item_group + "/" + "parameters";
405  hid_t param_group_id = H5Gcreate(file_id, param_group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
406  json_to_hdf5_attributes(mdata["parameters"], param_group_id);
407  H5Gclose(param_group_id);
408 
409  // hid_t pm_dset_id = -1;
410  // std::string param_data_name = item_group + "/parameters";
411  // std::string param_data = mdata["parameters"].dump();
412  // make_scalar_dataset(file_id, pm_dset_id, param_data_name, param_data);
413  }
414 
415  H5Gclose(group_id);
416  }
417  }
418  };
419 
420  MHO_ObjectTags* fContainer;
421 };
422 
423 } // namespace hops
424 
425 #endif
nlohmann::json mho_json
Definition: MHO_JSONHeaderWrapper.hh:5
#define msg_debug(xKEY, xCONTENT)
Definition: MHO_Message.hh:291
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:238
int axis(char *y_axis, char *x_axis)
Definition: axis.c:22
Definition: MHO_ContainerHDF5Converter.hh:256
void SetFileID(hid_t file_id)
Definition: MHO_ContainerHDF5Converter.hh:266
~AxisDumper()
Definition: MHO_ContainerHDF5Converter.hh:262
AxisDumper(hid_t file_id, hid_t ds_id, const std::string &parent, const mho_json &pmetadata)
Definition: MHO_ContainerHDF5Converter.hh:258
void operator()(const XAxisType &axis)
Definition: MHO_ContainerHDF5Converter.hh:270
AxisDumper()
Definition: MHO_ContainerHDF5Converter.hh:261
void SetIndex(std::size_t idx)
Definition: MHO_ContainerHDF5Converter.hh:264
void SetDataSetID(hid_t ds_id)
Definition: MHO_ContainerHDF5Converter.hh:268
MHO_ContainerHDF5Converter()
Definition: MHO_ContainerHDF5Converter.hh:334
virtual void SetObjectToConvert(MHO_Serializable *obj)
Definition: MHO_ContainerHDF5Converter.hh:343
virtual ~MHO_ContainerHDF5Converter()
Definition: MHO_ContainerHDF5Converter.hh:341
MHO_ContainerHDF5Converter(MHO_ExtensibleElement *element)
Definition: MHO_ContainerHDF5Converter.hh:336
virtual void WriteToHDF5File(hid_t file_id, std::string group_prefix)
Definition: MHO_ContainerHDF5Converter.hh:345
Converts a given ndarray-based container into a HDF5 representation - export only for now.
Definition: MHO_ContainerHDF5Converter.hh:56
MHO_ContainerHDF5Converter()
Definition: MHO_ContainerHDF5Converter.hh:58
std::enable_if< std::is_base_of< MHO_ScalarContainerBase, XCheckType >::value, void >::type ConstructHDF5(hid_t file_id, std::string group_prefix, const XContainerType *obj)
Definition: MHO_ContainerHDF5Converter.hh:95
virtual ~MHO_ContainerHDF5Converter()
Definition: MHO_ContainerHDF5Converter.hh:65
virtual void WriteToHDF5File(hid_t file_id, std::string group_prefix)
Definition: MHO_ContainerHDF5Converter.hh:69
MHO_ContainerHDF5Converter(MHO_ExtensibleElement *element)
Definition: MHO_ContainerHDF5Converter.hh:60
std::enable_if< std::is_base_of< MHO_AxisBase, XCheckType >::value, void >::type ConstructHDF5(hid_t file_id, std::string group_prefix, const XContainerType *obj)
Definition: MHO_ContainerHDF5Converter.hh:167
void ConstructHDF5(hid_t, std::string, const XCheckType *obj)
Definition: MHO_ContainerHDF5Converter.hh:83
virtual void SetObjectToConvert(MHO_Serializable *obj)
Definition: MHO_ContainerHDF5Converter.hh:67
std::enable_if<(std::is_base_of< MHO_VectorContainerBase, XCheckType >::value &&!std::is_base_of< MHO_AxisBase, XCheckType >::value), void >::type ConstructHDF5(hid_t file_id, std::string group_prefix, const XContainerType *obj)
Definition: MHO_ContainerHDF5Converter.hh:127
std::enable_if< std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type ConstructHDF5(hid_t file_id, std::string group_prefix, const XContainerType *obj)
Definition: MHO_ContainerHDF5Converter.hh:207
Class MHO_ExtensibleElement.
Definition: MHO_ExtensibleElement.hh:60
Definition: MHO_ContainerHDF5Converter.hh:40
virtual void SetObjectMetaData(const mho_json &mdata)
Definition: MHO_ContainerHDF5Converter.hh:47
virtual void SetObjectToConvert(MHO_Serializable *)=0
mho_json fMetaData
Definition: MHO_ContainerHDF5Converter.hh:52
virtual ~MHO_HDF5Converter()
Definition: MHO_ContainerHDF5Converter.hh:43
virtual void WriteToHDF5File(hid_t, std::string)=0
MHO_HDF5Converter()
Definition: MHO_ContainerHDF5Converter.hh:42
Class MHO_ObjectTags.
Definition: MHO_ObjectTags.hh:28
std::vector< MHO_UUID > GetAllObjectUUIDs() const
Getter for all object uuids at once.
Definition: MHO_ObjectTags.hh:83
Class MHO_Serializable.
Definition: MHO_Serializable.hh:26
MHO_UUID GetObjectUUID() const
Getter for object uuid.
Definition: MHO_Serializable.hh:61
mho_json GetMetaDataAsJSON() const
Getter for all meta data stored in this object as a json object.
Definition: MHO_Taggable.hh:95
std::string as_string() const
Definition: MHO_UUID.hh:125
struct type_status status
Definition: fourfit3.c:53
Definition: MHO_AdhocFlagging.hh:18
herr_t make_string_vector_dataset(hid_t group_id, hid_t dataset_id, const std::string &name, const std::vector< std::string > *data, const mho_json &metadata)
Definition: MHO_HDF5Datasets.hh:261
void json_to_hdf5_attributes(const mho_json &j, hid_t parent_group)
Definition: MHO_HDF5ConversionHelpers.hh:38