HOPS
HOPS class reference
MHO_HDF5Attributes.hh
Go to the documentation of this file.
1 #ifndef MHO_HDF5Attributes_HH__
2 #define MHO_HDF5Attributes_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 
24 namespace hops
25 {
26 
36 //generic - write a scalar attribute
37 template< typename XValueType > inline void make_attribute(const std::string& key, XValueType value, hid_t parent_dataset_id)
38 {
39  if(H5Aexists(parent_dataset_id, key.c_str()) > 0)
40  {
41  msg_error("hdf5interface", "attribute: " << key << " already exists, skipping" << eom);
42  return;
43  }
44 
45  hid_t TYPE_CODE = MHO_HDF5TypeCode< XValueType >();
46  hid_t attr_space = H5Screate(H5S_SCALAR);
47  hid_t attr_id = H5Acreate(parent_dataset_id, key.c_str(), TYPE_CODE, attr_space, H5P_DEFAULT, H5P_DEFAULT);
48  if(attr_id < 0)
49  {
50  msg_error("hdf5interface", "could not create attribute: " << key << ", id code is: " << attr_id << eom);
51  return;
52  }
53 
54  H5Awrite(attr_id, TYPE_CODE, &value);
55  H5Aclose(attr_id);
56  H5Sclose(attr_space);
57 }
58 
59 //specialization for std::string
60 template<> inline void make_attribute< std::string >(const std::string& key, std::string value, hid_t parent_dataset_id)
61 {
62  if(H5Aexists(parent_dataset_id, key.c_str()) > 0)
63  {
64  msg_error("hdf5interface", "string attribute: " << key << " already exists, skipping" << eom);
65  return;
66  }
67 
68  if(value.size() < 1)
69  {
70  msg_error("hdf5interface", "string attribute: " << key << " has size: " << value.size() << ", skipping" << eom);
71  return;
72  }
73 
74  hid_t attr_space = H5Screate(H5S_SCALAR);
75  hid_t TYPE_CODE = H5Tcopy(H5T_C_S1);
76  H5Tset_size(TYPE_CODE, value.size());
77  H5Tset_strpad(TYPE_CODE, H5T_STR_NULLTERM);
78  hid_t attr_id = H5Acreate(parent_dataset_id, key.c_str(), TYPE_CODE, attr_space, H5P_DEFAULT, H5P_DEFAULT);
79  if(attr_id < 0)
80  {
81  msg_error("hdf5interface", "could not create string attribute: " << key << ", id code is: " << attr_id << eom);
82  return;
83  }
84  H5Awrite(attr_id, TYPE_CODE, value.c_str());
85  H5Aclose(attr_id);
86  H5Sclose(attr_space);
87  H5Tclose(TYPE_CODE);
88  return;
89 }
90 
91 //generic - write a vector attribute
92 template< typename XDataType >
93 herr_t inline make_vector_attribute(const std::string& key, const std::vector< XDataType >* data, hid_t parent_dataset_id)
94 {
95  herr_t status = -1;
96  if(H5Aexists(parent_dataset_id, key.c_str()) > 0)
97  {
98  msg_error("hdf5interface", "attribute: " << key << " already exists, skipping" << eom);
99  return status;
100  }
101 
102  hsize_t dims[1];
103  dims[0] = data->size();
104  hid_t attr_space = H5Screate_simple(1, dims, NULL);
105  //get the type code
106  hid_t TYPE_CODE = MHO_HDF5TypeCode< XDataType >();
107  hid_t attr_id = H5Acreate(parent_dataset_id, key.c_str(), TYPE_CODE, attr_space, H5P_DEFAULT, H5P_DEFAULT);
108  if(attr_id < 0)
109  {
110  msg_error("hdf5interface", "could not create vector attribute: " << key << ", id code is: " << attr_id << eom);
111  return status;
112  }
113  status = H5Awrite(attr_id, TYPE_CODE, data->data());
114  H5Aclose(attr_id);
115  H5Sclose(attr_space);
116  return status;
117 }
118 
119 //specialization for vector of strings
120 template<>
121 herr_t inline make_vector_attribute(const std::string& key, const std::vector< std::string >* data, hid_t parent_dataset_id)
122 {
123  herr_t status = -1;
124  if(H5Aexists(parent_dataset_id, key.c_str()) > 0)
125  {
126  msg_error("hdf5interface", "attribute: " << key << " already exists, skipping" << eom);
127  return status;
128  }
129 
130  hsize_t dims[1];
131  dims[0] = data->size();
132  hid_t TYPE_CODE = H5Tcopy(H5T_C_S1);
133  H5Tset_size(TYPE_CODE, H5T_VARIABLE);
134 
135  //convert to const chars
136  std::vector< const char* > cstrs;
137  for(const auto& s : *data)
138  {
139  cstrs.push_back(s.c_str());
140  }
141  hid_t attr_space = H5Screate_simple(1, dims, NULL);
142  hid_t attr_id = H5Acreate(parent_dataset_id, key.c_str(), TYPE_CODE, attr_space, H5P_DEFAULT, H5P_DEFAULT);
143  if(attr_id < 0)
144  {
145  msg_error("hdf5interface", "could not create string vector attribute: " << key << ", id code is: " << attr_id << eom);
146  return status;
147  }
148  status = H5Awrite(attr_id, TYPE_CODE, cstrs.data());
149  H5Aclose(attr_id);
150  H5Sclose(attr_space);
151 
152  return status;
153 }
154 
155 //wrapper function to write attributes in a json object
156 inline void make_attribute(const std::string& key, const mho_json& value, hid_t parent_dataset_id)
157 {
158  msg_debug("hdf5interface", "creating attribute with key: " << key << eom);
159  //for now we can only handle scalar types
160  hid_t attr_space = H5Screate(H5S_SCALAR);
161  hid_t TYPE_CODE;
162  void* attr_data;
163 
164  if(value.is_string())
165  {
166  std::string strv = value.get< std::string >();
167  make_attribute(key, strv, parent_dataset_id);
168  }
169  else if(value.is_number_integer())
170  {
171  int v = value.get< int >();
172  make_attribute(key, v, parent_dataset_id);
173  }
174  else if(value.is_number_unsigned())
175  {
176  unsigned int v = value.get< unsigned int >();
177  make_attribute(key, v, parent_dataset_id);
178  }
179  else if(value.is_number_float())
180  {
181  double v = value.get< double >();
182  make_attribute(key, v, parent_dataset_id);
183  }
184  else if(value.is_boolean())
185  {
186  uint8_t v = value.get< bool >() ? 1 : 0;
187  make_attribute(key, v, parent_dataset_id);
188  }
189  else if(value.is_array() && value.size() != 0)
190  {
191  if(!(value.begin()->is_object())) //no arrays of composite objects
192  {
193  //all of these assume we are not mixing types in the array --
194  //this is a safe assumption for HOPS4 data containers
195  if(value.begin()->is_number_integer())
196  {
197  std::vector< int > data = value.get< std::vector< int > >();
198  make_vector_attribute(key, &data, parent_dataset_id);
199  }
200  if(value.begin()->is_number_unsigned())
201  {
202  std::vector< unsigned int > data = value.get< std::vector< unsigned int > >();
203  make_vector_attribute(key, &data, parent_dataset_id);
204  }
205  if(value.begin()->is_number_float())
206  {
207  std::vector< double > data = value.get< std::vector< double > >();
208  make_vector_attribute(key, &data, parent_dataset_id);
209  }
210  if(value.begin()->is_string())
211  {
212  std::vector< std::string > data = value.get< std::vector< std::string > >();
213  make_vector_attribute(key, &data, parent_dataset_id);
214  }
215  }
216  }
217  else if(value.is_object())
218  {
219  //for composite objects, we have to dump them into a string
220  //HDF5 doesn't support nesting of attributes
221  msg_debug("hdf5interface", "composite object attribute: " << key << ", will stored as string" << eom);
222  std::stringstream ss;
223  ss << value.dump();
224  std::string sval = ss.str();
225  make_attribute(key, sval, parent_dataset_id);
226  }
227 }
228 
229 } // namespace hops
230 
231 #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
Definition: fit_gsl.h:54
struct type_status status
Definition: fourfit3.c:53
Definition: MHO_AdhocFlagging.hh:18
void make_attribute(const std::string &key, XValueType value, hid_t parent_dataset_id)
Definition: MHO_HDF5Attributes.hh:37
void make_attribute< std::string >(const std::string &key, std::string value, hid_t parent_dataset_id)
Definition: MHO_HDF5Attributes.hh:60
herr_t make_vector_attribute(const std::string &key, const std::vector< XDataType > *data, hid_t parent_dataset_id)
Definition: MHO_HDF5Attributes.hh:93
Definition: vex.h:175