Program Listing for File h5stream.hpp#
↰ Return to documentation for file (utils/h5stream.hpp
)
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <H5Cpp.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
// #include <vector>
// Maps C++ type to HDF5 type
template <typename T> inline const H5::PredType &get_datatype_for_hdf5();
// Reference:
// https://www.hdfgroup.org/HDF5/doc/cpplus_RM/class_h5_1_1_pred_type.html
template <> inline const H5::PredType &get_datatype_for_hdf5<char>() {
return H5::PredType::NATIVE_CHAR;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<unsigned char>() {
return H5::PredType::NATIVE_UCHAR;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<short>() {
return H5::PredType::NATIVE_SHORT;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<unsigned short>() {
return H5::PredType::NATIVE_USHORT;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<int>() {
return H5::PredType::NATIVE_INT;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<unsigned int>() {
return H5::PredType::NATIVE_UINT;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<long>() {
return H5::PredType::NATIVE_LONG;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<unsigned long>() {
return H5::PredType::NATIVE_ULONG;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<long long>() {
return H5::PredType::NATIVE_LLONG;
}
template <>
inline const H5::PredType &get_datatype_for_hdf5<unsigned long long>() {
return H5::PredType::NATIVE_ULLONG;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<float>() {
return H5::PredType::NATIVE_FLOAT;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<double>() {
return H5::PredType::NATIVE_DOUBLE;
}
template <> inline const H5::PredType &get_datatype_for_hdf5<long double>() {
return H5::PredType::NATIVE_LDOUBLE;
}
//---------------------------------------------------------
namespace h5stream {
template <typename T> struct h5str1 {
std::string keyName;
T *data;
const unsigned dataSize{};
};
} // namespace h5stream
//
namespace h5stream {
class dspace {
public:
H5::DataSet dataset;
explicit dspace(const H5::DataSet &datasetx) : dataset(datasetx) {};
template <typename T>
void write_atr(const T &data, const H5std_string &dataname) {
auto type = get_datatype_for_hdf5<T>();
H5::DataSpace attr_dataspace = H5::DataSpace(H5S_SCALAR);
H5::Attribute attribute =
dataset.createAttribute(dataname, type, attr_dataspace);
attribute.write(type, &data);
}
template <typename T> void read_atr(T &data, const H5std_string &dataname) {
// auto type = get_datatype_for_hdf5<T>();
H5::Attribute attribute = dataset.openAttribute(dataname);
H5::DataType type = attribute.getDataType();
attribute.read(type, &data);
}
//----------------------
};
// ---- -----------------------------------
class gspace { // for group
public:
H5::Group dataset;
explicit gspace(const H5::Group &datasetx) : dataset(datasetx) {};
template <typename T>
void write_atr(const T data, const H5std_string &dataname) {
auto type = get_datatype_for_hdf5<T>();
H5::DataSpace attr_dataspace = H5::DataSpace(H5S_SCALAR);
H5::Attribute attribute =
dataset.createAttribute(dataname, type, attr_dataspace);
attribute.write(type, &data);
}
template <typename T> void read_atr(T &data, const H5std_string &dataname) {
// auto type = get_datatype_for_hdf5<T>();
H5::Attribute attribute = dataset.openAttribute(dataname);
H5::DataType type = attribute.getDataType();
attribute.read(type, &data);
}
//----------------------
};
} // namespace h5stream
//******************************************************************
// namespace h5stream
//----------------------------------------------------------
namespace h5stream {
class h5stream {
bool debug = false;
public:
H5std_string hdf5FileName;
H5::H5File hdf5File;
h5stream() = default;
;
explicit h5stream(const std::string &fileName,
const std::string &rw = std::string("tr")) {
setFileName(fileName, rw);
}
void setFileName(const H5std_string &fileName, // NOLINT
const std::string &rw = std::string("tr")) {
hdf5FileName = fileName;
std::cout << "hdf5FileName:" << hdf5FileName << std::endl;
try {
H5::Exception::dontPrint();
if (rw == "r") {
hdf5File = H5::H5File(fileName, H5F_ACC_RDONLY);
}
if (rw == "rw") {
hdf5File = H5::H5File(fileName, H5F_ACC_RDWR);
}
if (rw == "x") {
hdf5File = H5::H5File(fileName, H5F_ACC_EXCL);
}
if (rw == "tr") {
hdf5File = H5::H5File(fileName, H5F_ACC_TRUNC);
}
} catch (...) {
std::cout << " Error :: Unable to setFileName! " << fileName
<< std::endl;
}
}
template <typename T = double, template <typename...> class vec>
void write(const std::vector<vec<T>> &data, const H5std_string &datasetName) {
for (size_t i = 0; i < data.size(); i++) {
write<T, vec>(data[i], datasetName + std::to_string(i));
}
}
template <typename T = double, template <typename...> class vec = std::vector>
void write(const vec<T> &data, const H5std_string &datasetName) {
write<T>(datasetName, data.data(), data.size());
}
// Write raw pointer
template <typename T = double>
void write(const H5std_string &datasetName, const T *data,
unsigned data_size) {
try {
H5::Exception::dontPrint();
const int RANK = 1;
auto type = get_datatype_for_hdf5<T>();
hsize_t dimsf[1]; // dataset dimensions
dimsf[0] = data_size; //
H5::DataSpace dataspace(RANK, dimsf);
H5::DataSet dataset =
hdf5File.createDataSet(datasetName, type, dataspace);
if (data_size != 0) { // Dont write if it zero
dataset.write(data, type);
}
} catch (...) {
std::string errString = "Error! :: Unable to write datasetName " +
datasetName + " in the file " + hdf5FileName;
throw std::runtime_error(errString);
}
}
// Read file
template <typename T = double, template <typename...> class vec = std::vector>
void read(vec<T> &data, const H5std_string &datasetName) {
try {
H5::Exception::dontPrint();
auto type = get_datatype_for_hdf5<T>();
H5::DataSet dataset = hdf5File.openDataSet(datasetName);
H5::DataSpace dataspace = dataset.getSpace();
hsize_t dim[1];
dataspace.getSimpleExtentDims(dim, nullptr);
data.resize(dim[0]);
if (dim[0] != 0) { // Dont read if it zero
dataset.read(data.data(), type, dataspace, dataspace);
}
} catch (...) {
std::string errString = "Error! :: Unable to READ datasetName " +
datasetName + " from the file " + hdf5FileName;
throw std::runtime_error(errString);
// H5::FileIException::printErrorStack();
}
}
// Higher order vector or matrix type
// User has to give the correct size of the std::vector
template <typename T = double, template <typename...> class vec>
void read(std::vector<vec<T>> &data, const H5std_string &datasetName) {
data.clear();
size_t icount{0};
bool foundKey{true};
while (foundKey) {
// for (size_t i = 0; i < 10; i++) {
try {
std::vector<T> aa;
read<T, std::vector>(aa, datasetName + std::to_string(icount));
data.push_back(aa);
icount++;
} catch (std::exception &e) {
// foundKey = false;
// std::cout << "foundKey: " << foundKey << e.what() << std::endl;
break;
}
}
// throw warning if the dataset name was not found
if (icount == 0) {
std::string err_string =
"Error :: Unable to read dataset! " + std::string(datasetName);
throw std::runtime_error(err_string);
}
}
void close() { hdf5File.close(); }
[[nodiscard]] double fileSize() const {
return static_cast<double>(hdf5File.getFileSize()) / (1024 * 1024.);
}
dspace getDataspace(const H5std_string &dataset_name) {
return dspace(hdf5File.openDataSet(dataset_name));
}
gspace getGroup(const H5std_string &dataset_name) {
return gspace(hdf5File.openGroup(dataset_name));
}
auto createGroup(const H5std_string &group_name) {
return gspace(hdf5File.createGroup(group_name));
}
//*************************************************
// write metadata at the root label
template <typename T>
void writeMetadata(const T &data, const H5std_string &label) {
//
auto ds = getDataspace("");
ds.write_atr(data, label);
}
template <typename T> void readMetadata(T &data, const H5std_string &label) {
//
auto ds = getDataspace("");
ds.read_atr(data, label);
}
//*************************************************
// overload << and >>
template <typename T>
friend h5stream &operator<<(h5stream &out, const h5str1<T> &struct1) {
out.write<T>(struct1.keyName, struct1.data, struct1.dataSize);
return out;
}
template <typename T>
friend h5stream &operator>>(h5stream &out, const h5str1<T> &struct1) {
out.read<T>(struct1.keyName, struct1.data, struct1.dataSize);
return out;
}
//-------------------------------------------------
};
} // namespace h5stream