Hi5Write.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 
32 #include "Hi5.h" // to define H5_USE_*_API_DEFAULT
33 
34 #ifndef Hi5WRITE
35 #define Hi5WRITE
36 
37 // TODO rename class to H52Tree
38 
39 #include <hdf5.h>
40 
41 #include <string>
42 #include <list>
43 
44 #include "drain/util/TreeOrdered.h"
45 #include <drain/TypeUtils.h> // debugging
46 #include "drain/image/Image.h"
47 
48 /*
49  *
50  * TODO:
51  * - classify (hide methods)
52  *
53  */
54 
55 
56 namespace hi5 {
57 
59 
63 class Writer : public Hi5Base {
64 
65 public:
66 
68  static
69  void writeFile(const std::string &filename, const Hi5Tree &tree);
70 
72  //static
73  //void writeText(std::ostream & ostr, const Hi5Tree &tree);
74 
75 
77 
82  static
83  void treeToH5File(const Hi5Tree &tree, hid_t fid, const Hi5Tree::path_t & path);
84 
86  static
87  void dataToH5Attribute(const drain::Variable &d, hid_t fid, const Hi5Tree::path_t &path, const std::string &attribute);
88 
90  /* template <class T>
91  static
92  void dataToH5AttributeT(const drain::Variable &d, hid_t fid, const std::string &path, const std::string &attribute);
93  */
94 
96  static // ,const std::string &path
97  void dataToH5AttributeString(const drain::Variable &d, hid_t fid, const Hi5Tree::path_t &path, const std::string &attribute);
98 
100  static
101  hid_t imageToH5DataSet(const drain::image::Image &image, hid_t fid, const Hi5Tree::path_t & path);
102 
103 
104  // Under constr
105 
107 
118  template <class K, class V>
119  static
120  void vectorToH5Compound(const std::vector<std::pair<K,V> > & v, hid_t fid, const Hi5Tree::path_t & path, const char *labelFirst="key", const char *labelSecond="value");
121 
123  // template <class T> static void vectorToH5Compound(const std::vector<T> ... )
124 
126 
130  template <class K, class V>
131  static
132  void mapToH5Compound(const std::map<K,V> & m, hid_t fid, const Hi5Tree::path_t & path, const char *labelFirst="key", const char *labelSecond="value");
133 
134 
136  // static void dataToH5Compound(const drain::VariableMap & m, hid_t fid, const std::string &path);
137 
138 
140  static
141  void linkToH5Attribute(hid_t lid, hid_t fid, const std::string &path, const std::string &attribute);
142 
143  // deprecated (exclude from save marker)
144  //static char tempPathSuffix;
145 
146  static
147  unsigned short compressionLevel;
148 
149 
150 protected:
151 
153 
158  static
159  hsize_t deriveDimensions(const drain::image::Geometry & g, std::vector<hsize_t> & dims, std::vector<hsize_t> & chunkDims);
160 
161  template <class T>
162  class CompoundConv {
163 
164  public:
165 
166  typedef T conv_t;
167 
168  static inline
169  const conv_t & conv(const T & x){
170  return x;
171  }
172 
173  };
174 
175 
176 };
177 
178 template <class K, class V>
179 void Writer::vectorToH5Compound(const std::vector<std::pair<K,V> > & v, hid_t fid, const Hi5Tree::path_t & path, const char *labelFirst, const char *labelSecond){
180 
181  drain::Logger mout(__FILE__, __FUNCTION__);
182 
183  typedef std::vector<std::pair<K,V> > vect_t;
184  typedef typename vect_t::value_type pair_t;
185  typedef typename pair_t::first_type first_type;
186  typedef typename pair_t::second_type second_type;
188  // drain::Type::call<drain::simpleName>(second_type));
189 
190 
191  // General return code checking
192  herr_t status;
193 
194  const hsize_t size = sizeof(pair_t);
195  mout.special(path, ": ", v.size(), " elements x ", size, "b");
196 
197  const hid_t first_h5t = Hi5Base::getH5NativeDataType(typeid(first_type));
198  const hid_t second_h5t = Hi5Base::getH5NativeDataType(typeid(second_type));
199  mout.debug("datatypes: ", first_h5t, ", ", second_h5t);
200 
201  // Create the compound datatype for memory.
202  hid_t memtype = H5Tcreate (H5T_COMPOUND, size);
203  mout.debug("H5Tcreate, memtype=", memtype);
204 
205 
206  // HOFFSET(pair_t, first)
207  status = H5Tinsert (memtype, labelFirst, 0, first_h5t); // Hi5Base::getH5NativeDataType(typeid(int));
208  handleStatus(status, "H5Tinsert failed", mout, __LINE__);
209  //if (status < 0) mout.error() << "H5Tinsert failed for pair.first type, path=" << path << mout.endl;
210 
211  status = H5Tinsert (memtype, labelSecond, sizeof(first_type), second_h5t); // Hi5Base::getH5NativeDataType(typeid(int));
212  handleStatus(status, "H5Tinsert failed", mout, __LINE__);
213  //if (status < 0) mout.error() << "H5Tinsert failed for pair.second type, path=" << path << mout.endl;
214 
215 
216  const hid_t std_t1 = Hi5Base::getH5StandardType(typeid(first_type));
217  const hid_t std_t2 = Hi5Base::getH5StandardType(typeid(second_type));
218  mout.debug("h5 (file) types: ", std_t1, ", ", std_t2);
219 
220  const hsize_t s1 = H5Tget_size(std_t1);
221  const hsize_t s2 = H5Tget_size(std_t2);
222  mout.debug("h5 element sizes [bytes]: ", s1, ", ", s2);
223 
224  hid_t filetype = H5Tcreate (H5T_COMPOUND, s1+s2); // size wrong if hvt_t ?
225  H5Tinsert(filetype, labelFirst, 0, std_t1);
226  H5Tinsert(filetype, labelSecond, s1, std_t2); // TODO? Hi5Base::getH5StandardType(typeid(int));
227 
228  // Create dataspace. Setting maximum size to NULL sets the maximum size to be the current size.
229  hsize_t dims[1]; // 1-dimensional = list
230  dims[0] = v.size();
231  hid_t space = H5Screate_simple (1, dims, NULL);
232 
233  const std::string pathStr(path);
234  mout.debug("experimental: creating compound at ", pathStr);
235 
236  if (H5Lexists(fid, pathStr.c_str(), H5P_DEFAULT)){
237  mout.warn("compound object exists already (combining is not supported) : ", pathStr);
238  }
239  else {
240  // mout.debug3() << "does not exist, creating " << pathStr << mout.endl;
241  hid_t dset = H5Dcreate(fid, pathStr.c_str(), filetype, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
242  handleStatus(dset, "H5Dcreate failed", mout, __LINE__);
243  if (dset >= 0){
244  // Create the dataset and write the compound data to it.
245  status = H5Dwrite (dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, &v.at(0));
246  handleStatus(dset, "H5Dwrite failed", mout, __LINE__);
247  //H5Dclose();
248  status = H5Dclose(dset);
249  handleStatus(status, "H5Dclose failed", mout, __LINE__);
250  }
251  }
252 
253  status = H5Sclose(space);
254  handleStatus(status, "H5Sclose failed", mout, __LINE__);
255 
256 }
257 
259 template <>
261 
262 public:
263 
264  typedef long int conv_t;
265 
266  static inline
267  conv_t conv(int x){
268  return static_cast<conv_t>(x);
269  }
270 
271 };
272 
273 
274 template <>
275 class Writer::CompoundConv<std::string> {
276 
277 public:
278 
279  typedef const char * conv_t;
280 
281  static inline
282  conv_t conv(const std::string & x){
283  return x.c_str();
284  }
285 
286 };
287 
288 template <class K, class V>
289 void Writer::mapToH5Compound(const std::map<K,V> & m, hid_t fid, const Hi5Tree::path_t & path, const char *labelFirst, const char *labelSecond){
290 
291  drain::Logger mout(__FILE__, __FUNCTION__);
292 
293  typedef typename CompoundConv<K>::conv_t key_t;
294  typedef typename CompoundConv<V>::conv_t val_t;
295 
296  typedef std::vector<std::pair<key_t,val_t> > vect_t;
297  vect_t v(m.size());
298  //v.resize(m.size());
299 
300  typename vect_t::iterator vit = v.begin();
301  for (typename std::map<K,V>::const_iterator it = m.begin(); it != m.end(); ++it) {
302  vit->first = CompoundConv<K>::conv(it->first);
303  vit->second = CompoundConv<V>::conv(it->second);
304  mout.debug2() << vit->first << ':' << vit->second << mout.endl;
305  ++vit;
306  }
307 
308  Writer::vectorToH5Compound(v, fid, path, labelFirst, labelSecond);
309 
310 }
311 
312 
313 
314 
315 /*
316 template <>
317 inline
318 void Writer::dataToH5AttributeT<std::string>(const drain::Variable & data, hid_t fid, const std::string & path, const std::string & attribute){
319  dataToH5AttributeString(d, fid, path, attribute);
320 }
321 */
322 
323 /*
324  *
325 
326 template <class T>
327 void Writer::dataToH5AttributeT(const drain::Variable &d, hid_t fid, const std::string &path, const std::string &attribute){
328 
329  drain::Logger mout(hi5::hi5monitor, "Hi5Write", __FUNCTION__);
330 
331  if (d.isCharArrayString() || (d.getType() == typeid(std::string))){
332  dataToH5AttributeString(d, fid, path, attribute);
333  return;
334  }
335 
336 
337  int status = 0;
338 
339  const hid_t tid = getH5NativeDataType(typeid(T));
340 
341  // New
342  const hsize_t elements = d.getElementCount();
343  const bool isArray = (elements > 1); // && false;
344 
345  //const hid_t sid = isArray ? H5Screate_simple(1, &elements, NULL) : H5Screate(H5S_SCALAR);
346  const hid_t sid = isArray ? H5Screate_simple(1, &elements, &elements) : H5Screate(H5S_SCALAR);
347  if (sid < 0){
348  mout.error() << ": H5Screate failed for attribute, path=" << path;
349  mout << ", size=" << elements << mout.endl;
350  }
351  //H5Sc
352 
353 */
354  // NEW
355  /*
356  if (isArray){
357  mout.debug() << ": creating array of size " << elements;
358  mout << ", path=" << path << mout.endl;
359  status = H5Sset_extent_simple(sid, 1, &elements, &elements); //NULL);
360  if (status < 0)
361  mout.error() << ": H5Screate failed for ARRAY, path=" << path << mout.endl;
362  return;
363  }
364  */
365 /*
366  const hid_t oid = H5Oopen(fid, path.c_str(), H5P_DEFAULT);
367  if (oid < 0)
368  mout.error() << "H5Oopen failed, path=" << path << mout.endl;
369  //const hid_t gid = H5Gopen2(fid,path.c_str(),H5P_DEFAULT);
370  //if (gid < 0)
371  // mout.error() << ": H5Gopen failed, path=" << path << mout.endl;
372 
373  const hid_t aid = H5Acreate2(oid, attribute.c_str(), tid, sid, H5P_DEFAULT, H5P_DEFAULT);
374  if (aid < 0)
375  mout.error() << "H5Acreate failed, path=" << path << mout.endl;
376 
377  // OLD const T x = d;
378  // status = H5Awrite(aid,tid,&x);
379  // New
380  status = H5Awrite(aid, tid, d.getPtr());
381  if (status < 0)
382  mout.error() << "H5Awrite failed, path=" << path << mout.endl;
383 
384 
385  status = H5Aclose(aid);
386  if (status < 0)
387  mout.error() << ": H5 close failed, path=" << path << mout.endl;
388 
389  //status = H5Gclose(gid);
390  status = H5Oclose(oid);
391  if (status < 0)
392  mout.error() << ": H5 close failed, path=" << path << mout.endl;
393 
394  status = H5Sclose(sid);
395  if (status < 0)
396  mout.error() << ": H5 close failed, path=" << path << mout.endl;
397 
398 }
399 */
400 
401 
402 
403 
404 
405 } // ::hi5
406 
407 #endif
408 
409 // Rack
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & special(const TT &... args)
Other useful information.
Definition: Log.h:527
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:426
Logger & debug(const TT &... args)
Public, yet typically used "internally", when TIMING=true.
Definition: Log.h:676
Logger & debug2(const TT &... args)
Debug information.
Definition: Log.h:686
Definition: Geometry.h:145
Class for multi-channel digital images. Supports dynamic typing with base types (char,...
Definition: Image.h:184
Base class for Reader and Writer, essentially just wrapping some utilities.
Definition: Hi5.h:122
static hid_t getH5StandardType(const std::type_info &type)
Give a native C++ type, returns a standard(?) HDF5 data type.
Definition: Hi5.cpp:128
static hid_t getH5NativeDataType()
Given a native C++ type, returns a native HDF5 data type.
Definition: Hi5.h:155
Definition: Hi5Write.h:162
Converts Rack's h5 structure to native h5 structure applied for file output.
Definition: Hi5Write.h:63
static void dataToH5Attribute(const drain::Variable &d, hid_t fid, const Hi5Tree::path_t &path, const std::string &attribute)
Converts drain::Variable to an HDF5 attribute of a group or dataset.
Definition: Hi5Write.cpp:419
static void writeFile(const std::string &filename, const Hi5Tree &tree)
Writes Rack's hi5 object to an HDF5 file.
Definition: Hi5Write.cpp:54
static hid_t imageToH5DataSet(const drain::image::Image &image, hid_t fid, const Hi5Tree::path_t &path)
Converts drain::image::Image to an HDF5 dataset.
Definition: Hi5Write.cpp:327
static void vectorToH5Compound(const std::vector< std::pair< K, V > > &v, hid_t fid, const Hi5Tree::path_t &path, const char *labelFirst="key", const char *labelSecond="value")
Write a vector of paired values.
Definition: Hi5Write.h:179
static hsize_t deriveDimensions(const drain::image::Geometry &g, std::vector< hsize_t > &dims, std::vector< hsize_t > &chunkDims)
Definition: Hi5Write.cpp:271
static void dataToH5AttributeString(const drain::Variable &d, hid_t fid, const Hi5Tree::path_t &path, const std::string &attribute)
Creates and writes scalar (non-std::string) attributes to group.
Definition: Hi5Write.cpp:506
static void linkToH5Attribute(hid_t lid, hid_t fid, const std::string &path, const std::string &attribute)
Under constr.
static void mapToH5Compound(const std::map< K, V > &m, hid_t fid, const Hi5Tree::path_t &path, const char *labelFirst="key", const char *labelSecond="value")
TODO:
Definition: Hi5Write.h:289
static void treeToH5File(const Hi5Tree &tree, hid_t fid, const Hi5Tree::path_t &path)
Writes Rack's hi5 object to an HDF5 file.
Definition: Hi5Write.cpp:110
DRAIN_VARIABLE Variable
Value container supporting dynamic type.
Definition: Variable.h:63
Definition: Type.h:542