Loading...
Searching...
No Matches
Hi5Write.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood 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
56namespace hi5 {
57
59
63class Writer : public Hi5Base {
64
65public:
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
150protected:
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>
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
178template <class K, class V>
179void 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
259template <>
261
262public:
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
274template <>
275class Writer::CompoundConv<std::string> {
276
277public:
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
288template <class K, class V>
289void 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/*
316template <>
317inline
318void 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
326template <class T>
327void 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:312
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:430
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:666
Logger & special(const TT &... args)
Other useful information.
Definition Log.h:531
Logger & debug2(const TT &... args)
Debug information.
Definition Log.h:676
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:159
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:192
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:421
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:329
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:273
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:508
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