40 #include "../utility/utility.h"
56 hid_t require_attribute(hid_t file_id,
string path,
57 hid_t data_type, hid_t data_id)
59 size_t attr_start = path.rfind(
"/");
60 string node_path =
".";
61 string attr_name =
"";
62 if (attr_start == string::npos){
65 node_path = path.substr(0, attr_start);
68 attr_name = path.substr(attr_start);
69 if (H5Aexists_by_name(file_id, node_path.c_str(), attr_name.c_str(),
71 return H5Aopen_by_name(file_id, node_path.c_str(), attr_name.c_str(),
72 H5P_DEFAULT, H5P_DEFAULT);
74 return H5Acreate_by_name(file_id, node_path.c_str(), attr_name.c_str(),
76 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
83 hid_t require_group(hid_t file,
string path)
85 vector<string> pathTokens;
91 for (
unsigned int ii = 0; ii < pathTokens.size(); ++ii){
92 exists = H5Lexists(prev, pathTokens[ii].c_str(), H5P_DEFAULT);
94 current = H5Gopen2(prev, pathTokens[ii].c_str(), H5P_DEFAULT);
96 current = H5Gcreate2(prev, pathTokens[ii].c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
99 if(H5Gclose(prev) < 0){
114 hid_t HDF5WriterBase::createDoubleDataset(hid_t parent_id, std::string
name, hsize_t size, hsize_t maxsize)
117 hsize_t dims[1] = {size};
118 hsize_t maxdims[] = {maxsize};
119 hsize_t _chunkSize = chunkSize_;
120 if (_chunkSize > maxsize){
121 _chunkSize = maxsize;
123 hsize_t chunk_dims[] = {_chunkSize};
124 hid_t chunk_params = H5Pcreate(H5P_DATASET_CREATE);
125 status = H5Pset_chunk(chunk_params, 1, chunk_dims);
126 assert( status >= 0 );
127 if (compressor_ ==
"zlib"){
128 status = H5Pset_deflate(chunk_params, compression_);
129 }
else if (compressor_ ==
"szip"){
131 unsigned sz_opt_mask = H5_SZIP_NN_OPTION_MASK;
132 status = H5Pset_szip(chunk_params, sz_opt_mask,
133 HDF5WriterBase::CHUNK_SIZE);
135 hid_t dataspace = H5Screate_simple(1, dims, maxdims);
136 hid_t dataset_id = H5Dcreate2(parent_id, name.c_str(),
137 H5T_NATIVE_DOUBLE, dataspace,
138 H5P_DEFAULT, chunk_params, H5P_DEFAULT);
140 H5Pclose(chunk_params);
144 hid_t HDF5WriterBase::createStringDataset(hid_t parent_id,
string name, hsize_t size, hsize_t maxsize)
147 hid_t ftype = H5Tcopy(H5T_C_S1);
148 if (H5Tset_size(ftype, H5T_VARIABLE) < 0){
151 hsize_t dims[] = {size};
152 hsize_t maxdims[] = {maxsize};
153 hsize_t _chunkSize = chunkSize_;
154 if (maxsize < _chunkSize){
155 _chunkSize = maxsize;
157 hsize_t chunk_dims[] = {_chunkSize};
158 hid_t chunk_params = H5Pcreate(H5P_DATASET_CREATE);
159 status = H5Pset_chunk(chunk_params, 1, chunk_dims);
160 assert( status >= 0 );
161 if (compressor_ ==
"zlib"){
162 status = H5Pset_deflate(chunk_params, compression_);
163 }
else if (compressor_ ==
"szip"){
165 unsigned sz_opt_mask = H5_SZIP_NN_OPTION_MASK;
166 status = H5Pset_szip(chunk_params, sz_opt_mask,
167 HDF5WriterBase::CHUNK_SIZE);
169 hid_t dataspace = H5Screate_simple(1, dims, maxdims);
170 hid_t dataset_id = H5Dcreate2(parent_id, name.c_str(),
172 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
175 H5Pclose(chunk_params);
183 herr_t HDF5WriterBase::appendToDataset(hid_t dataset_id,
const vector< double >& data)
189 hid_t filespace = H5Dget_space(dataset_id);
193 if (data.size() == 0){
196 hsize_t size = H5Sget_simple_extent_npoints(filespace) + data.size();
197 status = H5Dset_extent(dataset_id, &size);
201 filespace = H5Dget_space(dataset_id);
202 hsize_t size_increment = data.size();
203 hid_t memspace = H5Screate_simple(1, &size_increment, NULL);
204 hsize_t start = size - data.size();
205 H5Sselect_hyperslab(filespace, H5S_SELECT_SET, &start, NULL,
206 &size_increment, NULL);
207 status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, memspace, filespace,
208 H5P_DEFAULT, &data[0]);
217 hid_t HDF5WriterBase::createDataset2D(hid_t parent,
string name,
unsigned int rows)
224 hsize_t chunkdims[] = {rows, chunkSize_};
225 hid_t chunk_params = H5Pcreate(H5P_DATASET_CREATE);
226 status = H5Pset_chunk(chunk_params, 2, chunkdims);
228 if (compressor_ ==
"zlib"){
229 status = H5Pset_deflate(chunk_params, compression_);
230 }
else if (compressor_ ==
"szip"){
232 unsigned sz_opt_mask = H5_SZIP_NN_OPTION_MASK;
233 status = H5Pset_szip(chunk_params, sz_opt_mask,
234 HDF5WriterBase::CHUNK_SIZE);
236 hsize_t dims[2] = {rows, 0};
237 hsize_t maxdims[2] = {rows, H5S_UNLIMITED};
238 hid_t dataspace = H5Screate_simple(2, dims, maxdims);
239 hid_t dset = H5Dcreate2(parent, name.c_str(), H5T_NATIVE_DOUBLE, dataspace, H5P_DEFAULT, chunk_params, H5P_DEFAULT);
240 H5Pclose(chunk_params);
249 template <
typename A>
250 herr_t writeScalarAttributesFromMap(hid_t file_id, map < string, A > path_value_map)
252 for (
typename map< string, A >::const_iterator ii = path_value_map.begin();
253 ii != path_value_map.end(); ++ii){
254 herr_t status = writeScalarAttr<A>(file_id,
255 ii->first, ii->second);
257 cerr <<
"Error: writing attribute " << ii->first
258 <<
" returned status code " << status << endl;
269 template <
typename A>
270 herr_t writeVectorAttributesFromMap(hid_t file_id, map <
string, vector < A > > path_value_map)
272 for (
typename map<
string, vector < A > >::const_iterator ii = path_value_map.begin();
273 ii != path_value_map.end(); ++ii){
274 herr_t status = writeVectorAttr<A>(file_id,
275 ii->first, ii->second);
277 cerr <<
"Error: writing attribute " << ii->first
278 <<
" returned status code " << status << endl;
289 herr_t writeScalarAttr(hid_t file_id,
string path,
string value)
291 hid_t data_id = H5Screate(H5S_SCALAR);
292 hid_t dtype = H5Tcopy(H5T_C_S1);
293 H5Tset_size(dtype, value.length()+1);
294 const char * data = value.c_str();
295 hid_t attr_id = require_attribute(file_id, path, dtype, data_id);
296 herr_t status = H5Awrite(attr_id, dtype, data);
302 herr_t writeScalarAttr(hid_t file_id,
string path,
double value)
304 hid_t data_id = H5Screate(H5S_SCALAR);
305 hid_t dtype = H5T_NATIVE_DOUBLE;
306 hid_t attr_id = require_attribute(file_id, path, dtype, data_id);
307 herr_t status = H5Awrite(attr_id, dtype, (
void*)(&value));
313 herr_t writeScalarAttr(hid_t file_id,
string path,
long value)
315 hid_t data_id = H5Screate(H5S_SCALAR);
316 hid_t dtype = H5T_NATIVE_LONG;
317 hid_t attr_id = require_attribute(file_id, path, dtype, data_id);
318 herr_t status = H5Awrite(attr_id, dtype, (
void*)(&value));
324 herr_t writeScalarAttr(hid_t file_id,
string path,
int value)
326 hid_t data_id = H5Screate(H5S_SCALAR);
327 hid_t dtype = H5T_NATIVE_INT;
328 hid_t attr_id = require_attribute(file_id, path, dtype, data_id);
329 herr_t status = H5Awrite(attr_id, dtype, (
void*)(&value));
339 herr_t writeVectorAttr(hid_t file_id,
string path, vector < string > value)
341 hsize_t dims[] = {value.size()};
342 hid_t space = H5Screate_simple(1, dims, NULL);
343 hid_t dtype = H5Tcopy(H5T_C_S1);
344 H5Tset_size(dtype, H5T_VARIABLE);
345 const char ** data = (
const char **)calloc(value.size(),
346 sizeof(
const char*));
347 for (
unsigned int ii = 0; ii < value.size(); ++ii){
348 data[ii] = value[ii].c_str();
350 hid_t attr_id = require_attribute(file_id, path, dtype, space);
351 herr_t status = H5Awrite(attr_id, dtype, data);
358 herr_t writeVectorAttr(hid_t file_id,
string path, vector < double > value)
360 hsize_t dims[] = {value.size()};
361 hid_t data_id = H5Screate_simple(1, dims, NULL);
362 hid_t dtype = H5T_NATIVE_DOUBLE;
363 H5Tset_size(dtype, value.size());
364 void * data = &value[0];
365 hid_t attr_id = require_attribute(file_id, path, dtype, data_id);
366 herr_t status = H5Awrite(attr_id, dtype, data);
372 herr_t writeVectorAttr(hid_t file_id,
string path, vector < long > value)
374 hsize_t dims[] = {value.size()};
375 hid_t data_id = H5Screate_simple(1, dims, NULL);
376 hid_t dtype = H5T_NATIVE_LONG;
377 H5Tset_size(dtype, value.size());
378 void * data = &value[0];
379 hid_t attr_id = require_attribute(file_id, path, dtype, data_id);
380 herr_t status = H5Awrite(attr_id, dtype, data);
387 const Cinfo* HDF5WriterBase::initCinfo()
395 "Name of the file associated with this HDF5 writer object.",
396 &HDF5WriterBase::setFilename,
397 &HDF5WriterBase::getFilename);
401 "True if this object has an open file handle.",
402 &HDF5WriterBase::isOpen);
406 "Depending on mode, if file already exists, if mode=1, data will be"
407 " appended to existing file, if mode=2, file will be truncated, if "
408 " mode=4, no writing will happen.",
409 &HDF5WriterBase::setMode,
410 &HDF5WriterBase::getMode);
414 "Chunksize for writing array data. Defaults to 100.",
415 &HDF5WriterBase::setChunkSize,
416 &HDF5WriterBase::getChunkSize);
420 "Compression type for array data. zlib and szip are supported. Defaults to zlib.",
421 &HDF5WriterBase::setCompressor,
422 &HDF5WriterBase::getCompressor);
426 "Compression level for array data. Defaults to 6.",
427 &HDF5WriterBase::setCompression,
428 &HDF5WriterBase::getCompression);
432 "String attributes. The key is attribute name, value is attribute value"
434 &HDF5WriterBase::setStringAttr,
435 &HDF5WriterBase::getStringAttr);
439 "Double precision floating point attributes. The key is attribute name,"
440 " value is attribute value (double).",
441 &HDF5WriterBase::setDoubleAttr,
442 &HDF5WriterBase::getDoubleAttr);
446 "Long integer attributes. The key is attribute name, value is attribute"
448 &HDF5WriterBase::setLongAttr,
449 &HDF5WriterBase::getLongAttr);
453 "String vector attributes. The key is attribute name, value is attribute value (string).",
454 &HDF5WriterBase::setStringVecAttr,
455 &HDF5WriterBase::getStringVecAttr);
459 "Double vector attributes. The key is attribute name, value is"
460 " attribute value (vector of double).",
461 &HDF5WriterBase::setDoubleVecAttr,
462 &HDF5WriterBase::getDoubleVecAttr);
466 "Long integer vector attributes. The key is attribute name, value is"
467 " attribute value (vector of long).",
468 &HDF5WriterBase::setLongVecAttr,
469 &HDF5WriterBase::getLongVecAttr);
472 "Write all buffer contents to file and clear the buffers.",
477 "Close the underlying file. This is a safety measure so that file is not in an invalid state even if a crash happens at exit.",
481 static Finfo * finfos[] = {
497 static string doc[] = {
498 "Name",
"HDF5WriterBase",
499 "Author",
"Subhasis Ray",
500 "Description",
"HDF5 file writer base class. This is not to be used directly. Instead,"
501 " it should be subclassed to provide specific data writing functions."
502 " This class provides most basic properties like filename, file opening"
503 " mode, file open status."
508 static Cinfo hdf5Cinfo(
512 sizeof(finfos)/
sizeof(
Finfo*),
514 doc,
sizeof(doc)/
sizeof(
string));
518 const hssize_t HDF5WriterBase::CHUNK_SIZE = 1024;
521 HDF5WriterBase::HDF5WriterBase():
523 filename_(
"moose_output.h5"),
524 openmode_(H5F_ACC_EXCL),
525 chunkSize_(CHUNK_SIZE),
531 HDF5WriterBase::~HDF5WriterBase()
537 void HDF5WriterBase::setFilename(
string filename)
539 if (filename_ == filename){
551 filename_ = filename;
555 string HDF5WriterBase::getFilename()
const
560 bool HDF5WriterBase::isOpen()
const
562 return filehandle_ >= 0;
565 herr_t HDF5WriterBase::openFile()
568 if (filehandle_ >= 0){
569 cout <<
"Warning: closing already open file and opening " << filename_ << endl;
570 status = H5Fclose(filehandle_);
573 cerr <<
"Error: failed to close currently open HDF5 file. Error code: " << status << endl;
577 hid_t fapl_id = H5Pcreate(H5P_FILE_ACCESS);
579 H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG);
580 ifstream infile(filename_.c_str());
581 bool fexists = infile.good();
583 if (!fexists || openmode_ == H5F_ACC_TRUNC){
584 filehandle_ = H5Fcreate(filename_.c_str(), openmode_, H5P_DEFAULT, fapl_id);
585 }
else if (openmode_ == H5F_ACC_RDWR) {
586 filehandle_ = H5Fopen(filename_.c_str(), openmode_, fapl_id);
588 cerr <<
"Error: File \"" << filename_ <<
"\" already exists. Specify mode=" << H5F_ACC_RDWR
589 <<
" for appending to it, mode=" << H5F_ACC_TRUNC
590 <<
" for overwriting it. mode=" << H5F_ACC_EXCL
591 <<
" requires the file does not exist." << endl;
594 if (filehandle_ < 0){
595 cerr <<
"Error: Could not open file for writing: " << filename_ << endl;
601 void HDF5WriterBase::setMode(
unsigned int mode)
603 if (mode == H5F_ACC_RDWR || mode == H5F_ACC_TRUNC || mode == H5F_ACC_EXCL){
608 unsigned HDF5WriterBase::getMode()
const
613 void HDF5WriterBase::setChunkSize(
unsigned int size)
618 unsigned int HDF5WriterBase::getChunkSize()
const
623 void HDF5WriterBase::setCompressor(
string name)
626 std::transform(compressor_.begin(), compressor_.end(), compressor_.begin(), ::tolower);
629 string HDF5WriterBase::getCompressor()
const
634 void HDF5WriterBase::setCompression(
unsigned int level)
636 compression_ = level;
639 unsigned int HDF5WriterBase::getCompression()
const
647 void HDF5WriterBase::flush()
658 void HDF5WriterBase::flushAttributes()
660 if (filehandle_ < 0){
664 writeScalarAttributesFromMap< string >(filehandle_, sattr_);
665 writeScalarAttributesFromMap< double >(filehandle_, dattr_);
666 writeScalarAttributesFromMap< long >(filehandle_, lattr_);
668 writeVectorAttributesFromMap< string >(filehandle_, svecattr_);
669 writeVectorAttributesFromMap< double >(filehandle_, dvecattr_);
670 writeVectorAttributesFromMap< long >(filehandle_, lvecattr_);
673 void HDF5WriterBase::close()
675 if (filehandle_ < 0){
679 herr_t status = H5Fclose(filehandle_);
682 cerr <<
"Error: closing file returned status code=" << status << endl;
686 void HDF5WriterBase::setStringAttr(
string name,
string value)
691 void HDF5WriterBase::setDoubleAttr(
string name,
double value)
696 void HDF5WriterBase::setLongAttr(
string name,
long value)
701 string HDF5WriterBase::getStringAttr(
string name)
const
703 map <string, string>::const_iterator ii = sattr_.find(name);
704 if (ii != sattr_.end()){
707 cerr <<
"Error: no attribute named " << name << endl;
711 double HDF5WriterBase::getDoubleAttr(
string name)
const
713 map <string, double>::const_iterator ii = dattr_.find(name);
714 if (ii != dattr_.end()){
717 cerr <<
"Error: no attribute named " << name << endl;
721 long HDF5WriterBase::getLongAttr(
string name)
const
723 map <string, long>::const_iterator ii = lattr_.find(name);
724 if (ii != lattr_.end()){
727 cerr <<
"Error: no attribute named " << name << endl;
735 void HDF5WriterBase::setStringVecAttr(
string name, vector < string > value)
740 void HDF5WriterBase::setDoubleVecAttr(
string name, vector < double > value)
745 void HDF5WriterBase::setLongVecAttr(
string name, vector < long >value)
750 vector < string > HDF5WriterBase::getStringVecAttr(
string name)
const
752 map <string, vector < string > >::const_iterator ii = svecattr_.find(name);
753 if (ii != svecattr_.end()){
756 cerr <<
"Error: no attribute named " << name << endl;
757 return vector<string>();
760 vector < double > HDF5WriterBase::getDoubleVecAttr(
string name)
const
762 map <string, vector < double > >::const_iterator ii = dvecattr_.find(name);
763 if (ii != dvecattr_.end()){
766 cerr <<
"Error: no attribute named " << name << endl;
767 return vector<double>();
770 vector < long > HDF5WriterBase::getLongVecAttr(
string name)
const
772 map <string, vector < long > >::const_iterator ii = lvecattr_.find(name);
773 if (ii != lvecattr_.end()){
776 cerr <<
"Error: no attribute named " << name << endl;
777 return vector<long>();
void tokenize(const string &str, const string &delimiters, vector< string > &tokens)
static const Cinfo * initCinfo()