#ifdef HDF5C #pragma once /************************************************ * @file HDF5FileStatic.h * @short creating, closing, writing and reading * from HDF5 files ***********************************************/ /** *@short creating, closing, writing and reading from HDF5 files */ #include "H5Cpp.h" #ifndef H5_NO_NAMESPACE using namespace H5; #endif #include "sls_detector_defs.h" #include "logger.h" #include #include #include #include #include //malloc #include #include //memset class HDF5FileStatic: public virtual slsDetectorDefs { public: /** Constructor */ HDF5FileStatic(){}; /** Destructor */ virtual ~HDF5FileStatic(){}; /** * Create File Name in format fpath/fnameprefix_fx_dy_z.raw, * where x is fnum, y is (dindex * numunits + unitindex) and z is findex * @param fpath file path * @param fnameprefix file name prefix * @param findex file index * @param subfindex sub file index * @param dindex readout index * @param numunits number of units per readout. eg. eiger has 2 udp units per readout * @param unitindex unit index * @returns complete file name created */ static std::string CreateFileName(char *fpath, char *fprefix, uint64_t findex, uint64_t subfindex, int dindex, int numunits = 1, int unitindex = 0) { std::ostringstream os; os << fpath << "/" << fprefix << "_d" << (dindex * numunits + unitindex) << "_f" << subfindex << '_' << findex << ".h5"; return os.str(); } /** * Create master file name * @param fpath file path * @param fnameprefix file name prefix * @param findex file index * @returns master file name */ static std::string CreateMasterFileName(char* fpath, char* fnameprefix, uint64_t findex) { std::ostringstream os; os << fpath << "/" << fnameprefix << "_master" << "_" << findex << ".h5"; return os.str(); } /** * Create virtual file name * @param fpath file path * @param fnameprefix file name prefix * @param fnum current frame number * @param findex file index * @returns virtual file name */ static std::string CreateVirtualFileName(char* fpath, char* fnameprefix, uint64_t findex) { std::ostringstream osfn; osfn << fpath << "/" << fnameprefix; osfn << "_virtual"; osfn << "_" << findex; osfn << ".h5"; return osfn.str(); } /** * Close File * @param ind index for debugging * @param fd file pointer * @param dp dataspace pointer * @param ds dataset pointer * @param ds_para pointer to array of parameter datasets */ static void CloseDataFile(int ind, H5File*& fd) { try { Exception::dontPrint(); //to handle errors if (fd) { delete fd; fd = 0; } } catch(const Exception& error) { FILE_LOG(logERROR) << "Could not close HDF5 handles of index " << ind; error.printErrorStack(); } } /* * Close master file * @param fd master hdf5 file object */ static void CloseMasterDataFile(H5File*& fd) { try { Exception::dontPrint(); //to handle errors if (fd) { delete fd; fd = 0; } } catch(const Exception& error) { FILE_LOG(logERROR) << "Could not close master HDF5 handles"; error.printErrorStack(); } } /* * Close virtual file * (in C because H5Pset_virtual doesnt exist yet in C++) * @param fd virtual hdf5 file handle */ static void CloseVirtualDataFile(hid_t& fd) { if(fd) { if (H5Fclose(fd) < 0 ) { FILE_LOG(logERROR) << "Could not close virtual HDF5 handles"; } fd = 0; } } /** * Write data to file * @param ind object index for debugging * @param buf buffer to write from * @param nDimx image number in file (imagenumber%maxframesinfile) * @param nDimy number of pixels in y direction * @param nDimz number of pixels in x direction * @param dspace dataspace pointer * @param dset dataset pointer * @param dtype datatype * @returns 0 for success and 1 for fail */ static int WriteDataFile(int ind, char* buf, uint64_t nDimx, uint32_t nDimy, uint32_t nDimz, DataSpace* dspace, DataSet* dset, DataType dtype) { hsize_t count[3] = {1, nDimy, nDimz}; hsize_t start[3] = {nDimx, 0, 0}; hsize_t dims2[2] = {nDimy, nDimz}; try{ Exception::dontPrint(); //to handle errors dspace->selectHyperslab( H5S_SELECT_SET, count, start); DataSpace memspace(2,dims2); dset->write(buf, dtype, memspace, *dspace); memspace.close(); } catch(const Exception& error){ FILE_LOG(logERROR) << "Could not write to file in object " << ind; error.printErrorStack(); return 1; } return 0; } /** * Write Parameter Arrays as datasets (to virtual file) * @param ind self index * @param dspace_para parameter dataspace * @param fnum current frame number * @param dset_para vector or dataset pointers of parameters * @param rheader sls_receiver_header pointer * @param parameterDataTypes parameter datatypes */ static int WriteParameterDatasets(int ind, DataSpace* dspace_para, uint64_t fnum, std::vector dset_para,sls_receiver_header* rheader, std::vector parameterDataTypes) { sls_detector_header header = rheader->detHeader; hsize_t count[1] = {1}; hsize_t start[1] = {fnum}; int i = 0; try{ Exception::dontPrint(); //to handle errors dspace_para->selectHyperslab( H5S_SELECT_SET, count, start); DataSpace memspace(H5S_SCALAR); dset_para[0]->write(&header.frameNumber, parameterDataTypes[0], memspace, *dspace_para);i=1; dset_para[1]->write(&header.expLength, parameterDataTypes[1], memspace, *dspace_para);i=2; dset_para[2]->write(&header.packetNumber, parameterDataTypes[2], memspace, *dspace_para);i=3; dset_para[3]->write(&header.bunchId, parameterDataTypes[3], memspace, *dspace_para);i=4; dset_para[4]->write(&header.timestamp, parameterDataTypes[4], memspace, *dspace_para);i=5; dset_para[5]->write(&header.modId, parameterDataTypes[5], memspace, *dspace_para);i=6; dset_para[6]->write(&header.row, parameterDataTypes[6], memspace, *dspace_para);i=7; dset_para[7]->write(&header.column, parameterDataTypes[7], memspace, *dspace_para);i=8; dset_para[8]->write(&header.reserved, parameterDataTypes[8], memspace, *dspace_para);i=9; dset_para[9]->write(&header.debug, parameterDataTypes[9], memspace, *dspace_para);i=10; dset_para[10]->write(&header.roundRNumber, parameterDataTypes[10], memspace, *dspace_para);i=11; dset_para[11]->write(&header.detType, parameterDataTypes[11], memspace, *dspace_para);i=12; dset_para[12]->write(&header.version, parameterDataTypes[12], memspace, *dspace_para);i=13; // contiguous bitset if (sizeof(sls_bitset) == sizeof(bitset_storage)) { dset_para[13]->write((char*)&(rheader->packetsMask), parameterDataTypes[13], memspace, *dspace_para); } // not contiguous bitset else { // get contiguous representation of bit mask bitset_storage storage; memset(storage, 0 , sizeof(bitset_storage)); sls_bitset bits = rheader->packetsMask; for (int i = 0; i < MAX_NUM_PACKETS; ++i) storage[i >> 3] |= (bits[i] << (i & 7)); // write bitmask dset_para[13]->write((char*)storage, parameterDataTypes[13], memspace, *dspace_para); }i=14; } catch(const Exception& error){ FILE_LOG(logERROR) << "Could not write parameters (index:" << i << ") to file in object " << ind; error.printErrorStack(); return 1; } return 0; } /** * Extend datasets in #images dimension (x dimension) * @param ind self index * @param dpace data space pointer address * @param dset data set pointer * @param dspace_para parameter dataspace address pointer * @param dset dataset parameter pointer * @param initialNumImages initial number of images * @returns 0 for success and 1 for fail */ static int ExtendDataset(int ind, DataSpace*& dspace, DataSet* dset, DataSpace*& dspace_para, std::vector dset_para, uint64_t initialNumImages) { try{ Exception::dontPrint(); //to handle errors hsize_t dims[3]; dspace->getSimpleExtentDims(dims); dims[0] += initialNumImages; dset->extend(dims); delete dspace; dspace = 0; dspace = new DataSpace(dset->getSpace()); hsize_t dims_para[1] = {dims[0]}; for (unsigned int i = 0; i < dset_para.size(); ++i) dset_para[i]->extend(dims_para); delete dspace_para; dspace_para = 0; dspace_para = new DataSpace(dset_para[0]->getSpace()); } catch(const Exception& error){ FILE_LOG(logERROR) << "Could not extend dataset in object " << ind; error.printErrorStack(); return 1; } return 0; } /** * Create master file * @param fname master file name * @param owenable overwrite enable * @param attr master file attributes * @returns 0 for success and 1 for fail */ static int CreateMasterDataFile(H5File*& fd, std::string fname, bool owenable, masterAttributes& attr) { try { Exception::dontPrint(); //to handle errors FileAccPropList flist; flist.setFcloseDegree(H5F_CLOSE_STRONG); fd = 0; if(!owenable) fd = new H5File( fname.c_str(), H5F_ACC_EXCL, FileCreatPropList::DEFAULT, flist ); else fd = new H5File( fname.c_str(), H5F_ACC_TRUNC, FileCreatPropList::DEFAULT, flist ); //variables DataSpace dataspace = DataSpace (H5S_SCALAR); Attribute attribute; DataSet dataset; int iValue=0; double dValue=0; StrType strdatatype(PredType::C_S1,256); //create attributes //version dValue = attr.version; attribute = fd->createAttribute("version",PredType::NATIVE_DOUBLE, dataspace); attribute.write(PredType::NATIVE_DOUBLE, &dValue); //Create a group in the file Group group1( fd->createGroup( "entry" ) ); Group group2( group1.createGroup("data") ); Group group3( group1.createGroup("instrument") ); Group group4( group3.createGroup("beam") ); Group group5( group3.createGroup("detector") ); Group group6( group1.createGroup("sample") ); //Dynamic Range dataset = group5.createDataSet ( "dynamic range", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.dynamicRange), PredType::NATIVE_INT); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("bits")); //Ten Giga iValue = attr.tenGiga; dataset = group5.createDataSet ( "ten giga enable", PredType::NATIVE_INT, dataspace ); dataset.write ( &iValue, PredType::NATIVE_INT); //Image Size dataset = group5.createDataSet ( "image size", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.imageSize), PredType::NATIVE_INT); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("bytes")); //x dataset = group5.createDataSet ( "number of pixels in x axis", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.nPixelsX), PredType::NATIVE_INT); //y dataset = group5.createDataSet ( "number of pixels in y axis", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.nPixelsY), PredType::NATIVE_INT); //Maximum frames per file dataset = group5.createDataSet ( "maximum frames per file", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.maxFramesPerFile), PredType::NATIVE_INT); //Total Frames dataset = group5.createDataSet ( "total frames", PredType::STD_U64LE, dataspace ); dataset.write ( &(attr.totalFrames), PredType::STD_U64LE); //Exptime dataset = group5.createDataSet ( "exposure time", PredType::STD_U64LE, dataspace ); dataset.write ( &(attr.exptimeNs), PredType::STD_U64LE); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("ns")); //SubExptime dataset = group5.createDataSet ( "sub exposure time", PredType::STD_U64LE, dataspace ); dataset.write ( &(attr.subExptimeNs), PredType::STD_U64LE); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("ns")); //SubPeriod dataset = group5.createDataSet ( "sub period", PredType::STD_U64LE, dataspace ); dataset.write ( &(attr.subPeriodNs), PredType::STD_U64LE); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("ns")); //Period dataset = group5.createDataSet ( "acquisition period", PredType::STD_U64LE, dataspace ); dataset.write ( &(attr.periodNs), PredType::STD_U64LE); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("ns")); //Gap Pixels Enable dataset = group5.createDataSet ( "gap pixels enable", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); //Quad Enable dataset = group5.createDataSet ( "quad enable", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); //Gap Pixels Enable dataset = group5.createDataSet ( "gap pixels enable", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); //Quad Enable dataset = group5.createDataSet ( "quad enable", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); //Analog Flag dataset = group5.createDataSet ( "analog flag", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); //Digital Flag dataset = group5.createDataSet ( "digital flag", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); //ADC Mask dataset = group5.createDataSet ( "adc mask", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); //Dbit Offset dataset = group5.createDataSet ( "dbit offset", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); // Dbit List dataset = group5.createDataSet ( "dbit bitset list", PredType::STD_U64LE, dataspace ); dataset.write ( &(attr.periodNs), PredType::STD_U64LE); // Roi xmin dataset = group5.createDataSet ( "roi xmin", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.roiXmin), PredType::NATIVE_INT); // Roi xmax dataset = group5.createDataSet ( "roi xmax", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.roiXmax), PredType::NATIVE_INT); //Timestamp time_t t = time(0); dataset = group5.createDataSet ( "timestamp", strdatatype, dataspace ); dataset.write ( std::string(ctime(&t)), strdatatype ); fd->close(); } catch(const Exception& error) { FILE_LOG(logERROR) << "Could not create master HDF5 handles"; error.printErrorStack(); if (fd) fd->close(); return 1; } return 0; } /** * Create File * @param ind object index for debugging * @param owenable overwrite enable * @param fname complete file name * @param frindexenable frame index enable * @param fnum current image number * @param nDimx number of pixels in x dim (#frames) * @param nDimy number of pixels in y dim (height y dir) * @param nDimz number of pixels in z dim (width x dir) * @param dtype data type * @param fd file pointer * @param dspace dataspace pointer * @param dset dataset pointer * @param version version of software for hdf5 writing * @param maxchunkedimages maximum chunked images * @param dspace_para dataspace of parameters * @param dset_para vector of datasets of parameters * @param parameterNames parameter names * @param parameterDataTypes parameter datatypes * @returns 0 for success and 1 for fail */ static int CreateDataFile(int ind, bool owenable, std::string fname, bool frindexenable, uint64_t fnum, uint64_t nDimx, uint32_t nDimy, uint32_t nDimz, DataType dtype, H5File*& fd, DataSpace*& dspace, DataSet*& dset, double version, uint64_t maxchunkedimages, DataSpace*& dspace_para, std::vector& dset_para, std::vector parameterNames, std::vector parameterDataTypes) { try { Exception::dontPrint(); //to handle errors //file FileAccPropList fapl; fapl.setFcloseDegree(H5F_CLOSE_STRONG); fd = 0; if(!owenable) fd = new H5File( fname.c_str(), H5F_ACC_EXCL, FileCreatPropList::DEFAULT, fapl ); else fd = new H5File( fname.c_str(), H5F_ACC_TRUNC, FileCreatPropList::DEFAULT, fapl ); //attributes - version double dValue=version; DataSpace dataspace_attr = DataSpace (H5S_SCALAR); Attribute attribute = fd->createAttribute("version",PredType::NATIVE_DOUBLE, dataspace_attr); attribute.write(PredType::NATIVE_DOUBLE, &dValue); //dataspace hsize_t srcdims[3] = {nDimx, nDimy, nDimz}; hsize_t srcdimsmax[3] = {H5S_UNLIMITED, nDimy, nDimz}; dspace = 0; dspace = new DataSpace (3,srcdims,srcdimsmax); //dataset name std::ostringstream osfn; osfn << "/data"; if (frindexenable) osfn << "_f" << std::setfill('0') << std::setw(12) << fnum; std::string dsetname = osfn.str(); //dataset //fill value DSetCreatPropList plist; int fill_value = -1; plist.setFillValue(dtype, &fill_value); // always create chunked dataset as unlimited is only supported with chunked layout hsize_t chunk_dims[3] ={maxchunkedimages, nDimy, nDimz}; plist.setChunk(3, chunk_dims); dset = 0; dset = new DataSet (fd->createDataSet(dsetname.c_str(), dtype, *dspace, plist)); //create parameter datasets hsize_t dims[1] = {nDimx}; hsize_t dimsmax[1] = {H5S_UNLIMITED}; dspace_para = 0; dspace_para = new DataSpace (1,dims,dimsmax); // always create chunked dataset as unlimited is only supported with chunked layout DSetCreatPropList paralist; hsize_t chunkpara_dims[3] = {maxchunkedimages}; paralist.setChunk(1, chunkpara_dims); for (unsigned int i = 0; i < parameterNames.size(); ++i){ DataSet* ds = new DataSet(fd->createDataSet(parameterNames[i], parameterDataTypes[i], *dspace_para, paralist)); dset_para.push_back(ds); } } catch(const Exception& error){ FILE_LOG(logERROR) << "Could not create HDF5 handles in object " << ind; error.printErrorStack(); if (fd) fd->close(); return 1; } return 0; } /** * Create virtual file * (in C because H5Pset_virtual doesnt exist yet in C++) * @param virtualFileName virtual file name * @param fd virtual file handle * @param masterFileName master file name * @param fpath file path * @param fnameprefix file name prefix * @param findex file index * @param frindexenable frame index enable * @param dindex readout index * @param numunits number of units per readout. eg. eiger has 2 udp units per readout * @param maxFramesPerFile maximum frames per file * @param numf number of frames caught * @param srcDataseName source dataset name * @param dataType datatype of data dataset * @param numDety number of readouts in Y dir * @param numDetz number of readouts in Z dir * @param nDimy number of objects in y dimension in source file (Number of pixels in y dir) * @param nDimz number of objects in z dimension in source file (Number of pixels in x dir) * @param version version of software for hdf5 writing * @param parameterNames parameter names * @param parameterDataTypes parameter datatypes * @returns 0 for success and 1 for fail */ static int CreateVirtualDataFile( std::string virtualFileName, hid_t& fd, std::string masterFileName, char* fpath, char* fnameprefix, uint64_t findex, bool frindexenable, int dindex, int numunits, uint32_t maxFramesPerFile, uint64_t numf, std::string srcDataseName, DataType dataType, int numDety, int numDetz, uint32_t nDimy, uint32_t nDimz, double version, std::vector parameterNames, std::vector parameterDataTypes) { //file hid_t dfal = H5Pcreate (H5P_FILE_ACCESS); if (dfal < 0) return CloseFileOnError(fd, std::string("Could not create file access property for virtual file ") + virtualFileName + std::string("\n")); if (H5Pset_fclose_degree (dfal, H5F_CLOSE_STRONG) < 0) return CloseFileOnError(fd, std::string("Could not set strong file close degree for virtual file ") + virtualFileName + std::string("\n")); fd = H5Fcreate( virtualFileName.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, dfal); if (fd < 0) return CloseFileOnError(fd, std::string("Could not create virtual file ") + virtualFileName + std::string("\n")); //attributes - version hid_t dataspace_attr = H5Screate (H5S_SCALAR); if (dataspace_attr < 0) return CloseFileOnError(fd, std::string("Could not create dataspace for attribute in virtual file ") + virtualFileName + std::string("\n")); hid_t attrid = H5Acreate2 (fd, "version", H5T_NATIVE_DOUBLE, dataspace_attr, H5P_DEFAULT, H5P_DEFAULT); if (attrid < 0) return CloseFileOnError(fd, std::string("Could not create attribute in virtual file ") + virtualFileName + std::string("\n")); double attr_data = version; if (H5Awrite (attrid, H5T_NATIVE_DOUBLE, &attr_data) < 0) return CloseFileOnError(fd, std::string("Could not write attribute in virtual file ") + virtualFileName + std::string("\n")); if (H5Aclose (attrid) < 0) return CloseFileOnError(fd, std::string("Could not close attribute in virtual file ") + virtualFileName + std::string("\n")); //virtual dataspace hsize_t vdsdims[3] = {numf, numDety * nDimy, numDetz * nDimz}; hid_t vdsDataspace = H5Screate_simple(3, vdsdims ,NULL); if (vdsDataspace < 0) return CloseFileOnError(fd, std::string("Could not create virtual dataspace in virtual file ") + virtualFileName + std::string("\n")); hsize_t vdsdims_para[2] = {numf, (unsigned int) numDety * numDetz}; hid_t vdsDataspace_para = H5Screate_simple(2, vdsdims_para, NULL); if (vdsDataspace_para < 0) return CloseFileOnError(fd, std::string("Could not create virtual dataspace (parameters) in virtual file ") + virtualFileName + std::string("\n")); //fill values hid_t dcpl = H5Pcreate (H5P_DATASET_CREATE); if (dcpl < 0) return CloseFileOnError(fd, std::string("Could not create file creation properties in virtual file ") + virtualFileName + std::string("\n")); int fill_value = -1; if (H5Pset_fill_value (dcpl, GetDataTypeinC(dataType), &fill_value) < 0) return CloseFileOnError(fd, std::string("Could not create fill value in virtual file ") + virtualFileName + std::string("\n")); hid_t dcpl_para[parameterNames.size()]; for (unsigned int i = 0; i < parameterNames.size(); ++i) { dcpl_para[i] = H5Pcreate (H5P_DATASET_CREATE); if (dcpl_para[i] < 0) return CloseFileOnError(fd, std::string("Could not create file creation properties (parameters) in virtual file ") + virtualFileName + std::string("\n")); if (H5Pset_fill_value (dcpl_para[i], GetDataTypeinC(parameterDataTypes[i]), &fill_value) < 0) return CloseFileOnError(fd, std::string("Could not create fill value (parameters) in virtual file ") + virtualFileName + std::string("\n")); } //hyperslab int numMajorHyperslab = numf/maxFramesPerFile; if (numf%maxFramesPerFile) numMajorHyperslab++; bool error = false; uint64_t framesSaved = 0; for (int j = 0; j < numMajorHyperslab; j++) { uint64_t nDimx = ((numf - framesSaved) > maxFramesPerFile) ? maxFramesPerFile : (numf-framesSaved); hsize_t offset[3] = {framesSaved, 0, 0}; hsize_t count[3] = {nDimx, nDimy, nDimz}; hsize_t offset_para[2] = {framesSaved, 0}; hsize_t count_para[2] = {nDimx, 1}; for (int i = 0; i < numDety * numDetz; ++i) { //setect hyperslabs if (H5Sselect_hyperslab (vdsDataspace, H5S_SELECT_SET, offset, NULL, count, NULL) < 0) { FILE_LOG(logERROR) << "Could not select hyperslab"; error = true; break; } if (H5Sselect_hyperslab (vdsDataspace_para, H5S_SELECT_SET, offset_para, NULL, count_para, NULL) < 0) { FILE_LOG(logERROR) << "Could not select hyperslab for parameters"; error = true; break; } //source file name std::string srcFileName = HDF5FileStatic::CreateFileName(fpath, fnameprefix, findex, j, dindex, numunits, i); FILE_LOG(logERROR) << srcFileName; // find relative path std::string relative_srcFileName = srcFileName; { size_t i = srcFileName.rfind('/', srcFileName.length()); if (i != std::string::npos) relative_srcFileName = (srcFileName.substr(i+1, srcFileName.length() - i)); } //source dataset name std::ostringstream osfn; osfn << "/data"; if (frindexenable) osfn << "_f" << std::setfill('0') << std::setw(12) << j; std::string srcDatasetName = osfn.str(); //source dataspace hsize_t srcdims[3] = {nDimx, nDimy, nDimz}; hsize_t srcdimsmax[3] = {H5S_UNLIMITED, nDimy, nDimz}; hid_t srcDataspace = H5Screate_simple(3, srcdims, srcdimsmax); if (srcDataspace < 0) return CloseFileOnError(fd, std::string("Could not create source dataspace in virtual file ") + virtualFileName + std::string("\n")); hsize_t srcdims_para[1] = {nDimx}; hsize_t srcdimsmax_para[1] = {H5S_UNLIMITED}; hid_t srcDataspace_para = H5Screate_simple(1, srcdims_para, srcdimsmax_para); if (srcDataspace_para < 0) return CloseFileOnError(fd, std::string("Could not create source dataspace (parameters) in virtual file ") + virtualFileName + std::string("\n")); //mapping if (H5Pset_virtual(dcpl, vdsDataspace, relative_srcFileName.c_str(), srcDatasetName.c_str(), srcDataspace) < 0) { FILE_LOG(logERROR) << "Could not set mapping for paramter 1"; error = true; break; } for (unsigned int k = 0; k < parameterNames.size(); ++k) { if (H5Pset_virtual(dcpl_para[k], vdsDataspace_para, relative_srcFileName.c_str(), parameterNames[k], srcDataspace_para) < 0) { FILE_LOG(logERROR) << "Could not set mapping for paramter " << k; error = true; break; } } //H5Sclose(srcDataspace); //H5Sclose(srcDataspace_para); offset[2] += nDimz; if (offset[2] >= (numDetz * nDimz)) { offset[2] = 0; offset[1] += nDimy; } offset_para[1]++; } framesSaved += nDimx; } if (error) return CloseFileOnError(fd, std::string("Could not map files in virtual file ") + virtualFileName + std::string("\n")); //dataset std::string virtualDatasetName = srcDataseName; hid_t vdsdataset = H5Dcreate2 (fd, virtualDatasetName.c_str(), GetDataTypeinC(dataType), vdsDataspace, H5P_DEFAULT, dcpl, H5P_DEFAULT); if (vdsdataset < 0) return CloseFileOnError(fd, std::string("Could not create virutal dataset in virtual file ") + virtualFileName + std::string("\n")); //virtual parameter dataset for (unsigned int i = 0; i < parameterNames.size(); ++i) { hid_t vdsdataset_para = H5Dcreate2 (fd, parameterNames[i], GetDataTypeinC(parameterDataTypes[i]), vdsDataspace_para, H5P_DEFAULT, dcpl_para[i], H5P_DEFAULT); if (vdsdataset_para < 0) return CloseFileOnError(fd, std::string("Could not create virutal dataset (parameters) in virtual file ") + virtualFileName + std::string("\n")); } //close H5Fclose(fd); fd = 0; //link return LinkVirtualInMaster(masterFileName, virtualFileName, virtualDatasetName, parameterNames); } /** * Copy file to another file (mainly to view virutal files in hdfviewer) * @param dataType data type * @param owenable overwrite enable * @param oldFileName file name including path of file to copy * @param oldDatasetName dataset name to copy * @param newFileName file name including path of file to copy to * @param newDatasetName dataset name to copy to * @param rank rank * @param nDimx Number of objects in x dimension * @param nDimy Number of objects in y dimension * @param nDimz Number of objects in z dimension * @returns 0 for success and 1 for fail */ template static int CopyVirtualFile(T datatype, bool owenable, std::string oldFileName, std::string oldDatasetName, std::string newFileName, std::string newDatasetName, int rank, uint64_t nDimx, uint32_t nDimy, uint32_t nDimz=0) { T *data_out; switch (rank) { case 2: data_out = (T*)malloc(sizeof(T)*(nDimx*nDimy)); break; case 3: data_out = (T*)malloc(sizeof(T)*(nDimx*nDimy*nDimz)); break; default: FILE_LOG(logERROR) << "Invalid rank. Options: 2 or 3"; return 0; } if (datatype == PredType::STD_U16LE) { FILE_LOG(logINFO) << "datatype:16"; } else if (datatype == PredType::STD_U32LE) { FILE_LOG(logINFO) << "datatype:32"; } else if (datatype == PredType::STD_U64LE) { FILE_LOG(logINFO) << "datatype:64"; } else if (datatype == PredType::STD_U8LE) { FILE_LOG(logINFO) << "datatype:8"; } else { FILE_LOG(logERROR) << "Unknown datatype: " << datatype; return 1; } FILE_LOG(logINFO) << "owenable:" << (owenable?1:0) << std::endl << "oldFileName:" << oldFileName << std::endl << "oldDatasetName:" << oldDatasetName << std::endl << "newFileName:" << newFileName << std::endl << "newDatasetName:" << newDatasetName << std::endl << "rank:" << rank << std::endl << "nDimx:" << nDimx << std::endl << "nDimy:" << nDimy << std::endl << "nDimz:" << nDimz; H5File* oldfd; H5File* newfd; try { Exception::dontPrint(); //to handle errors //open old file oldfd = new H5File( oldFileName.c_str(), H5F_ACC_RDONLY); DataSet oldDataset = oldfd->openDataSet( oldDatasetName.c_str()); //read dataset oldDataset.read( data_out, datatype); //new file FileAccPropList fapl; fapl.setFcloseDegree(H5F_CLOSE_STRONG); newfd = 0; if(!owenable) newfd = new H5File( newFileName.c_str(), H5F_ACC_EXCL, FileCreatPropList::DEFAULT, fapl ); else newfd = new H5File( newFileName.c_str(), H5F_ACC_TRUNC, FileCreatPropList::DEFAULT, fapl ); //dataspace and dataset DataSpace* newDataspace = 0; if (rank == 3) { hsize_t dims[3] = {nDimx, nDimy, nDimz}; newDataspace = new DataSpace (3,dims); } else if (rank == 2) { hsize_t dims[2] = {nDimx, nDimy}; newDataspace = new DataSpace (2,dims); } DataSet* newDataset = 0; newDataset = new DataSet( newfd->createDataSet(newDatasetName.c_str(), datatype, *newDataspace)); //write and close newDataset->write(data_out,datatype); newfd->close(); oldfd->close(); } catch(const Exception& error){ FILE_LOG(logERROR) << "Could not copy virtual files"; error.printErrorStack(); free(data_out); oldfd->close(); newfd->close(); return 1; } free(data_out); return 0; } /** * Link the Virtual File in the Master File * In C because H5Lcreate_external exists only in C * @param masterFileName master file name * @param virtualfname virtual file name * @param virtualDatasetname virtual dataset name * @param parameterNames parameter names * @returns 0 for success and 1 for fail */ static int LinkVirtualInMaster(std::string masterFileName, std::string virtualfname, std::string virtualDatasetname, std::vector parameterNames) { char linkname[100]; hid_t vfd = 0; hid_t dfal = H5Pcreate (H5P_FILE_ACCESS); if (dfal < 0) return CloseFileOnError( vfd, std::string("Could not create file access property for link\n")); if (H5Pset_fclose_degree (dfal, H5F_CLOSE_STRONG) < 0) return CloseFileOnError( vfd, std::string("Could not set strong file close degree for link\n")); //open master file hid_t mfd = H5Fopen( masterFileName.c_str(), H5F_ACC_RDWR, dfal); if (mfd < 0) return CloseFileOnError( vfd, std::string("Could not open master file\n")); //open virtual file vfd = H5Fopen( virtualfname.c_str(), H5F_ACC_RDWR, dfal); if (vfd < 0) { H5Fclose(mfd); mfd = 0; return CloseFileOnError( vfd, std::string("Could not open virtual file\n")); } // find relative path std::string relative_virtualfname = virtualfname; { size_t i = virtualfname.rfind('/', virtualfname.length()); if (i != std::string::npos) relative_virtualfname = (virtualfname.substr(i+1, virtualfname.length() - i)); } //**data dataset** hid_t vdset = H5Dopen2( vfd, virtualDatasetname.c_str(), H5P_DEFAULT); if (vdset < 0) { H5Fclose(mfd); return CloseFileOnError( vfd, std::string("Could not open virtual data dataset\n")); } sprintf(linkname, "/entry/data/%s",virtualDatasetname.c_str()); if(H5Lcreate_external( relative_virtualfname.c_str(), virtualDatasetname.c_str(), mfd, linkname, H5P_DEFAULT, H5P_DEFAULT) < 0) { H5Fclose(mfd); mfd = 0; return CloseFileOnError( vfd, std::string("Could not create link to data dataset\n")); } H5Dclose(vdset); //**paramter datasets** for (unsigned int i = 0; i < parameterNames.size(); ++i){ hid_t vdset_para = H5Dopen2( vfd, (std::string (parameterNames[i])).c_str(), H5P_DEFAULT); if (vdset_para < 0) { H5Fclose(mfd); mfd = 0; return CloseFileOnError( vfd, std::string("Could not open virtual parameter dataset to create link\n")); } sprintf(linkname, "/entry/data/%s",(std::string (parameterNames[i])).c_str()); if(H5Lcreate_external( relative_virtualfname.c_str(), (std::string (parameterNames[i])).c_str(), mfd, linkname, H5P_DEFAULT, H5P_DEFAULT) < 0) { H5Fclose(mfd); mfd = 0; return CloseFileOnError( vfd, std::string("Could not create link to virtual parameter dataset\n")); } } H5Fclose(mfd); mfd = 0; H5Fclose(vfd); vfd = 0; return 0; } /** * Print Error msg and Close File and called on error * @returns 1 for fail */ static int CloseFileOnError(hid_t& fd, const std::string msg) { FILE_LOG(logERROR) << msg; if(fd > 0) H5Fclose(fd); fd = 0; return 1; } /** * Get Data type in C * @param dtype datatype in C++ * @returns datatype in C */ static hid_t GetDataTypeinC(DataType dtype) { if (dtype == PredType::STD_U8LE) return H5T_STD_U8LE; else if (dtype == PredType::STD_U16LE) return H5T_STD_U16LE; else if (dtype == PredType::STD_U32LE) return H5T_STD_U32LE; else if (dtype == PredType::STD_U64LE) return H5T_STD_U64LE; else { hid_t s = H5Tcopy(H5T_C_S1); H5Tset_size(s, MAX_NUM_PACKETS); return s; } } }; #endif