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