#ifndef HDFIO_H #define HDFIO_H #include #include #include #include #include #include /** * HDFIO class * * This class represents an HDF5 object/file and provides basic * HDF operations like opening a file, reading data form a dataset * of that file, creating new HDF files and datasets and writing * datasets into a created file. There are also some functions * for getting and setting different attributes, like the * dimensionaltity of the HDF dataset to be written or the * datasetnames inside an HDF5 file. * * @author Christoph Federrath * @version 2007-2013 * */ class HDFIO { private: std::string Filename; int Rank; //dimensionality of the field // HDF5 stuff hid_t File_id, Dataset_id, Dataspace_id; hsize_t HDFSize, HDFDims[4]; herr_t HDF5_status, HDF5_error; public: /** * Default constructor. * */ HDFIO() : Filename(), //create Nullstring Rank(1), //dimensionality 1 (x only) File_id(0), //set all to 0 Dataset_id(0), Dataspace_id(0), HDFSize(0), //set Buffersize to 0 HDF5_status(0), //set HDF5 status to 0 HDF5_error(-1) //set to -1 { for(int i = 0; i < 4; i++) HDFDims[i] = 0; //set Dimensions to (0,0,0,0) } /** * open an HDF5 file * @param Filename HDF5 filename * @param read_write_char 'r': read only flag, 'w': write flag * */ void open(const std::string Filename, const char read_write_char) { this->Filename = Filename; switch (read_write_char) { case 'r': { // open HDF5 file in read only mode File_id = H5Fopen(Filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); assert( File_id != HDF5_error ); break; } case 'w': { // open HDF5 file in write mode File_id = H5Fopen(Filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT); assert( File_id != HDF5_error ); break; } default: { // open HDF5 file in read only mode File_id = H5Fopen(Filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); assert( File_id != HDF5_error ); break; } } }; /** * close HDF5 file * */ void close(void) { // close HDF5 file HDF5_status = H5Fclose(File_id); assert( HDF5_status != HDF5_error ); } /** * read data from a dataset * @param *DataBuffer pointer to double/float/int array to which data is to be written * @param Datasetname datasetname * @param DataType (i.e. H5T_STD_I32LE) * */ void read(void* const DataBuffer, const std::string Datasetname, const hid_t DataType) { // get dimensional information from dataspace and update HDFSize getDims(Datasetname); // open dataset Dataset_id = H5Dopen(File_id, Datasetname.c_str()); assert( Dataset_id != HDF5_error ); // open dataspace (to get dimensions) Dataspace_id = H5Dget_space(Dataset_id); assert( Dataspace_id != HDF5_error ); // read buffer //memspaceid //filespaceid HDF5_status = H5Dread( Dataset_id, DataType, H5S_ALL, H5S_ALL, H5P_DEFAULT, DataBuffer ); assert( HDF5_status != HDF5_error ); HDF5_status = H5Sclose(Dataspace_id); assert( HDF5_status != HDF5_error ); HDF5_status = H5Dclose(Dataset_id); assert( HDF5_status != HDF5_error ); }//read /** * read a slab of data from a dataset * @param *DataBuffer pointer to double/float/int array to which data is to be written * @param Datasetname datasetname * @param DataType (i.e. H5T_STD_I32LE) * @param offset (offset array) * @param count (count array, i.e. the number of cells[dim] to be selected) * @param out_rank (rank of the output array selected) * @param out_offset (output offset array) * @param out_count (output count array, i.e. the number of cells[dim] in output) * */ void read_slab(void* const DataBuffer, const std::string Datasetname, const hid_t DataType, const hsize_t offset[], const hsize_t count[], const hsize_t out_rank, const hsize_t out_offset[], const hsize_t out_count[]) { // get dimensional information from dataspace and update HDFSize getDims(Datasetname); // open dataset Dataset_id = H5Dopen(File_id, Datasetname.c_str()); assert( Dataset_id != HDF5_error ); // open dataspace (to get dimensions) Dataspace_id = H5Dget_space(Dataset_id); assert( Dataspace_id != HDF5_error ); // select hyperslab HDF5_status = H5Sselect_hyperslab(Dataspace_id, H5S_SELECT_SET, offset, NULL, count, NULL); assert( HDF5_status != HDF5_error ); // create memspace hid_t Memspace_ID = H5Screate_simple(out_rank,out_count,NULL); HDF5_status = H5Sselect_hyperslab(Memspace_ID, H5S_SELECT_SET, out_offset, NULL, out_count, NULL); assert( HDF5_status != HDF5_error ); // read buffer HDF5_status = H5Dread( Dataset_id, DataType, Memspace_ID, Dataspace_id, H5P_DEFAULT, DataBuffer ); assert( HDF5_status != HDF5_error ); HDF5_status = H5Sclose(Dataspace_id); assert( HDF5_status != HDF5_error ); HDF5_status = H5Dclose(Dataset_id); assert( HDF5_status != HDF5_error ); }//read_slab /** * overwrite data of an existing dataset * @param *DataBuffer pointer to double/float/int array containing data to be written * @param Datasetname datasetname * @param DataType (i.e. H5T_STD_I32LE) * */ void overwrite(const void* const DataBuffer, const std::string Datasetname, const hid_t DataType) { // get dimensional information from dataspace and update HDFSize getDims(Datasetname); // open dataset Dataset_id = H5Dopen(File_id, Datasetname.c_str()); assert( Dataset_id != HDF5_error ); // open dataspace (to get dimensions) Dataspace_id = H5Dget_space(Dataset_id); assert( Dataspace_id != HDF5_error ); // overwrite dataset HDF5_status = H5Dwrite( Dataset_id, DataType, H5S_ALL, H5S_ALL, H5P_DEFAULT, DataBuffer); assert( HDF5_status != HDF5_error ); HDF5_status = H5Sclose(Dataspace_id); assert( HDF5_status != HDF5_error ); HDF5_status = H5Dclose(Dataset_id); assert( HDF5_status != HDF5_error ); }//overwrite /** * create new HDF5 file * @param Filename HDF5 filename * */ void create(const std::string Filename) { this->Filename = Filename; // create HDF5 file File_id = H5Fcreate(Filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); assert( File_id != HDF5_error ); } /** * write HDF5 dataset * @param DataBuffer int/float/double array containing the data * @param Datasetname datasetname * @param Dimensions dataset dimensions * @param DataType (i.e. H5T_STD_I32LE) * */ void write(const void* const DataBuffer, const std::string Datasetname, const std::vector Dimensions, const hid_t DataType) { setDims(Dimensions); // set dimensions write(DataBuffer, Datasetname, DataType); // call write() } /** * write HDF5 dataset * @param *DataBuffer pointer to int/float/double array containing the data * @param Datasetname datasetname * @param DataType (i.e. H5T_IEEE_F32BE, H5T_STD_I32LE, ...) * */ void write(const void* const DataBuffer, const std::string Datasetname, const hid_t DataType) { // -------------- create dataspace Dataspace_id = H5Screate_simple(Rank, HDFDims, NULL); assert( Dataspace_id != HDF5_error ); // -------------- create dataset Dataset_id = H5Dcreate(File_id, Datasetname.c_str(), DataType, Dataspace_id, H5P_DEFAULT); assert( Dataset_id != HDF5_error ); // -------------- write dataset HDF5_status = H5Dwrite(Dataset_id, DataType, H5S_ALL, H5S_ALL, H5P_DEFAULT, DataBuffer); assert( HDF5_status != HDF5_error ); // -------------- close dataset HDF5_status = H5Dclose(Dataset_id); assert( HDF5_status != HDF5_error ); // -------------- close dataspace HDF5_status = H5Sclose(Dataspace_id); assert( HDF5_status != HDF5_error ); } /** * set the rank of a dataset * @param Rank the rank, dimensionality (0,1,2) * */ void setRank(const int Rank) { this->Rank = Rank; } /** * set array dimension in different directions * @param dim dimension of the array * */ void setDimX(const int dim_x) { HDFDims[0] = static_cast(dim_x); } void setDimY(const int dim_y) { HDFDims[1] = static_cast(dim_y); } void setDimZ(const int dim_z) { HDFDims[2] = static_cast(dim_z); } void setDims(const std::vector Dimensions) { Rank = Dimensions.size(); for(int i = 0; i < Rank; i++) HDFDims[i] = static_cast(Dimensions[i]); } /** * get the rank of the current dataset * @return int dimensionality * */ int getRank(void) const { return Rank; } /** * get the rank of a dataset with name datasetname * @param Datasetname datasetname * @return int dimensionality * */ int getRank(const std::string Datasetname) { // get dimensional information from dataspace and update HDFSize getDims(Datasetname); return Rank; } /** * get array dimension in different directions * @return dimension of the array * */ int getDimX(void) const { return static_cast(HDFDims[0]); } int getDimY(void) const { return static_cast(HDFDims[1]); } int getDimZ(void) const { return static_cast(HDFDims[2]); } /** * get dataset size of dataset with datasetname * @param Datasetname datasetname * @return size of the dataset * */ int getSize(const std::string Datasetname) { // open dataset Dataset_id = H5Dopen(File_id, Datasetname.c_str()); if (Dataset_id == HDF5_error) { std::cout << "HDFIO: getSize(): CAUTION: Datasetname '" << Datasetname << "' does not exists in file '"<getFilename()<<"'. Continuing..." << std::endl; return 0; } assert( Dataset_id != HDF5_error ); // open dataspace Dataspace_id = H5Dget_space(Dataset_id); assert( Dataspace_id != HDF5_error ); // get dimensional information from dataspace hsize_t HDFxdims[4], HDFmaxdims[4]; Rank = H5Sget_simple_extent_dims(Dataspace_id, HDFxdims, HDFmaxdims); // from the dimensional info, calculate the size of the buffer. HDFSize = 1; for (int i = 0; i < Rank; i++) { HDFDims[i] = HDFxdims[i]; HDFSize *= HDFDims[i]; } HDF5_status = H5Sclose(Dataspace_id); assert( HDF5_status != HDF5_error ); HDF5_status = H5Dclose(Dataset_id); assert( HDF5_status != HDF5_error ); return static_cast(HDFSize); } /** * get array dimension in different directions and update HDFSize * @param Datasetname datasetname for which dimensional info is read * @return dimension of the array * */ std::vector getDims(const std::string Datasetname) { // open dataset Dataset_id = H5Dopen(File_id, Datasetname.c_str()); assert( Dataset_id != HDF5_error ); // open dataspace Dataspace_id = H5Dget_space(Dataset_id); assert( Dataspace_id != HDF5_error ); // get dimensional information from dataspace hsize_t HDFxdims[4], HDFmaxdims[4]; Rank = H5Sget_simple_extent_dims(Dataspace_id, HDFxdims, HDFmaxdims); // from the dimensional info, calculate the size of the buffer. HDFSize = 1; for (int i = 0; i < Rank; i++) { HDFDims[i] = HDFxdims[i]; HDFSize *= HDFDims[i]; } HDF5_status = H5Sclose(Dataspace_id); assert( HDF5_status != HDF5_error ); HDF5_status = H5Dclose(Dataset_id); assert( HDF5_status != HDF5_error ); std::vector ReturnDims(Rank); for(int i = 0; i < Rank; i++) ReturnDims[i] = static_cast(HDFDims[i]); return ReturnDims; } /** * get HDF5 filename * @return filename * */ std::string getFilename(void) const { return Filename; } /** * get number of datasets in HDF5 file * @return the number of datasets * */ int getNumberOfDatasets(void) const { hsize_t *NumberofObjects = new hsize_t[1]; H5Gget_num_objs(File_id, NumberofObjects); int returnNumber = static_cast(NumberofObjects[0]); delete [] NumberofObjects; return returnNumber; } /** * get HDF5 datasetname * @param datasetnumber integer number identifying the dataset * @return datasetname * */ std::string getDatasetname(const int datasetnumber) const { char *Name = new char[256]; H5Gget_objname_by_idx(File_id, datasetnumber, Name, 256); std::string returnName = static_cast(Name); delete [] Name; return returnName; } }; // end: HDFIO #endif