diff --git a/slsDetectorCalibration/dataStructures/HDF5File.cpp b/slsDetectorCalibration/dataStructures/HDF5File.cpp index 60adc7eb5..90571221c 100644 --- a/slsDetectorCalibration/dataStructures/HDF5File.cpp +++ b/slsDetectorCalibration/dataStructures/HDF5File.cpp @@ -2,215 +2,217 @@ #include "ansi.h" -#include +#include +#include HDF5File::HDF5File () { - //InitializeParameters(); + //InitializeParameters(); //old } HDF5File::~HDF5File () { - if(frame_index_list) - delete [] frame_index_list; if(current_image) delete [] current_image; } -void HDF5File::InitializeParameters () { - /* - memset(file_name, 0, MAX_STR_LENGTH); //awkward, initializes all file_name characters to 0 - file = -1; - dataspace = -1; - //memspace = -1; - dataset = -1; - number_of_frames = 0; - frame_index_list = NULL; - current_image = NULL; - */ - for (int i = 0; i < RANK; ++i) { - file_dims[i] = 0; //also awkward - chunk_dims[i] = 0; - frame_offset[i] = 0; - } +void HDF5File::SetImageDataPath (std::string const& name) { data_datasetname = name; } + +void HDF5File::SetFrameIndexPath (std::string const& name) { index_datasetname = name; } + +void HDF5File::InitializeDimensions () { + + rank = H5Sget_simple_extent_ndims(dataspace); + file_dims.resize(rank); + H5Sget_simple_extent_dims(dataspace, file_dims.data(), nullptr); + + std::cout << "Dataset dimensions: ("; + for (size_t i = 0; i < file_dims.size(); ++i) { + std::cout << file_dims[i]; + if (i < file_dims.size() - 1) std::cout << ", "; + } + std::cout << ")\n"; + } +std::vector HDF5File::GetDatasetDimensions() { + return file_dims; +} + +std::vector HDF5File::GetChunkDimensions() { + return chunk_dims; +} + +bool HDF5File::ValidateDimensions () { + + // validate rank + if(rank != RANK) { + cprintf(RED,"rank found %d. Expected %d\n", rank, RANK); + std::cerr << "Error: Rank could not be validated\n"; + return false; + } + + // validate file dimensions of x and y (assuming those are the last two dimensions of the dataset) + if ( (file_dims[file_dims.size()-2] != DEFAULT_X_DIMS) || (file_dims[file_dims.size()-1] != DEFAULT_Y_DIMS) ) { + cprintf(RED,"file dimensions of x found %llu. Expected %d\n", file_dims[file_dims.size()-2], DEFAULT_X_DIMS); + cprintf(RED,"file dimensions of y found %llu. Expected %d\n", file_dims[file_dims.size()-1], DEFAULT_Y_DIMS); + std::cerr << "Error: Dataset dimensions could not be validated\n"; + return false; + } + + cprintf(GREEN, "File rank & dimensions validated."); + return true; +} + +bool HDF5File::ReadChunkDimensions () { + + // Get layout + hid_t plist_id = H5Dget_create_plist(dataset); + + if (H5Pget_layout (plist_id) != H5D_CHUNKED) { + cprintf(RED,"NOTE: Dataset is not chunked!\n"); + std::cerr << "Error: Dataset is not chunked\n"; + return false; + } + + // Get Chunk Dimensions + int rank_chunk = H5Pget_chunk (plist_id, 0, nullptr); + chunk_dims.resize(rank_chunk); + H5Pget_chunk (plist_id, rank_chunk, chunk_dims.data()); + + std::cout << "Chunk dimensions: ("; + for (size_t i = 0; i < chunk_dims.size(); ++i) { + std::cout << chunk_dims[i]; + if (i < chunk_dims.size() - 1) std::cout << ", "; + } + std::cout << ")\n"; + + H5Pclose (plist_id); + + return true; + +} + +bool HDF5File::ValidateChunkDimensions () { + + // validate rank + if(chunk_dims.size() != rank) { + cprintf(RED,"Chunk rank does not match dataset rank! Found %d. Expected %d\n", chunk_dims.size(), rank); + std::cerr << "Error: Chunk rank does not match dataset rank\n"; + return false; + } + + // validate chunk dimensions of x and y (assuming those are the last two dimensions of the dataset) + if ( (chunk_dims[chunk_dims.size()-2] != DEFAULT_CHUNK_X_DIMS) || (chunk_dims[chunk_dims.size()-1] != DEFAULT_CHUNK_Y_DIMS) ) { + cprintf(RED,"file dimensions of x found %llu. Expected %d\n", chunk_dims[chunk_dims.size()-2], DEFAULT_CHUNK_X_DIMS); + cprintf(RED,"file dimensions of y found %llu. Expected %d\n", chunk_dims[chunk_dims.size()-1], DEFAULT_CHUNK_Y_DIMS); + std::cerr << "Error: Chunk dimensions could not be validated\n"; + return false; + } + + cprintf(GREEN, "Chunk rank & dimensions validated."); + return true; + +} + +bool HDF5File::OpenFrameIndexDataset() { + + // Get all the frame numbers + // Open frame index dataset + hid_t fi_dataset = H5Dopen2 (file, index_datasetname.c_str(), H5P_DEFAULT); + if (fi_dataset < 0){ + cprintf (RED,"Could not open frame index dataset %s\n", index_datasetname.c_str()); + std::cerr << "Error: Could not open frame index dataset\n"; + return false; + } + + hid_t fi_dataspace = H5Dget_space (fi_dataset); + int fi_rank = H5Sget_simple_extent_ndims(fi_dataspace); + std::vector fi_dims(fi_rank); + H5Sget_simple_extent_dims (fi_dataspace, fi_dims.data(), nullptr); + + std::cout << "Frame index dataset dimensions: ("; + for (size_t i = 0; i < fi_dims.size(); ++i) { + std::cout << fi_dims[i]; + if (i < fi_dims.size() - 1) std::cout << ", "; + } + std::cout << ")\n"; + + // validate size + if (fi_dims[0] != file_dims[0]) { + cprintf (RED,"Frame index dimensions of z found %llu. Expected %llu\n", fi_dims[0], file_dims[0]); + std::cerr << "Error: Z dimension of frame index dataset does not align with z dimension of image dataset\n"; + H5Sclose (fi_dataspace); + H5Dclose (fi_dataset); + return false; + } + H5Sclose (fi_dataspace); + + // allocate frame index memory + frame_index_list.resize(file_dims[0]); + + //read frame index values + //Is u32 correct? I would think not. But I get a segmentation fault if I use u64. + if (H5Dread (fi_dataset, H5T_STD_U32LE, H5S_ALL, H5S_ALL, H5P_DEFAULT, frame_index_list.data()) < 0) { + cprintf (RED,"Could not read frame index dataset %s\n", index_datasetname); + std::cerr << "Error: Could not read frame index dataset\n"; + H5Dclose (fi_dataset); + return false; + } + H5Dclose(fi_dataset); + return true; +} int HDF5File::OpenResources (char const*const fname, bool validate) { - // Initialize - //InitializeParameters(); - // Open File file = H5Fopen (fname, H5F_ACC_RDONLY, H5P_DEFAULT); if (file < 0) { - cprintf(RED,"could not open hdf5 file\n"); + cprintf(RED,"Could not open hdf5 file\n"); + std::cerr << "Error: H5Fopen failed\n"; return 0; } cprintf(BLUE, "Opened File: %s\n", fname); - // Open Dataset - dataset = H5Dopen2 (file, DATA_DATASETNAME, H5P_DEFAULT); + dataset = H5Dopen2 (file, data_datasetname.c_str(), H5P_DEFAULT); if (dataset < 0){ - cprintf(RED,"could not open dataset\n"); + cprintf(RED,"Could not open dataset\n"); + std::cerr << "Error: H5Dopen2 failed\n"; CloseResources (); return 0; } - cprintf(BLUE, "Opened Dataset: %s\n", DATA_DATASETNAME); - + cprintf(BLUE, "Opened Dataset: %s\n", data_datasetname.c_str()); // Create Dataspace dataspace = H5Dget_space (dataset); if (dataspace < 0){ - cprintf(RED,"could not open dataspace\n"); + cprintf(RED,"Could not open dataspace\n"); + std::cerr << "Error: H5Dget_space failed\n"; CloseResources (); return 0; } - // Get Dimensions - int rank = H5Sget_simple_extent_dims (dataspace, file_dims, NULL); - cprintf (BLUE, "Number of Images: %llu\n", file_dims[Z]); - - // validate file dimensions - if (validate) { - - // validate rank - if(rank != RANK) { - cprintf(RED,"rank found %d. Expected %d\n", rank, RANK); - CloseResources (); - return 0; - } - - // validate file dimensions of x and y - if (file_dims[X] != DEFAULT_X_DIMS) { - cprintf(RED,"file dimensions of x found %llu. Expected %d\n", file_dims[X], DEFAULT_X_DIMS); - CloseResources (); - return 0; - } - if (file_dims[Y] != DEFAULT_Y_DIMS) { - cprintf(RED,"file dimensions of y found %llu. Expected %d\n", file_dims[Y], DEFAULT_Y_DIMS); - CloseResources (); - return 0; - } - cprintf(GREEN, "File rank & dimensions validated. " - "Rank: %d, Dimensions: %llu x %llu x %llu\n", - rank, file_dims[Z], file_dims[Y], file_dims[X]); - } - - - - // Get layout - hid_t cparms = H5Dget_create_plist(dataset); - - // validate chunk layout - if (validate) { - if (H5D_CHUNKED != H5Pget_layout (cparms)) { - cprintf(RED,"not chunked data file\n"); - H5Pclose(cparms); - CloseResources (); - return 0; - } - cprintf(GREEN, "Chunk layout validated\n"); - } - - // Get Chunk Dimensions - int rank_chunk = H5Pget_chunk (cparms, RANK, chunk_dims); - - // validate dimensions - if (validate) { - - // validate rank - if(rank_chunk != RANK) { - cprintf(RED,"chunk rank found %d. Expected %d\n", rank, RANK); - H5Pclose(cparms); - CloseResources (); - return 0; - } - - // validate file dimensions of x, y and z - if (chunk_dims[X] != DEFAULT_CHUNK_X_DIMS) { - cprintf(RED,"chunk dimensions of x found %llu. Expected %d\n", chunk_dims[X], DEFAULT_CHUNK_X_DIMS); - H5Pclose(cparms); - CloseResources (); - return 0; - } - if (chunk_dims[Y] != DEFAULT_CHUNK_Y_DIMS) { - cprintf(RED,"chunk dimensions of y found %llu. Expected %d\n", chunk_dims[Y], DEFAULT_CHUNK_Y_DIMS); - H5Pclose(cparms); - CloseResources (); - return 0; - } - /*if (chunk_dims[Z] != DEFAULT_CHUNK_Z_DIMS) { - cprintf(RED,"chunk dimensions of z found %llu. Expected %d\n", chunk_dims[Z], DEFAULT_CHUNK_Z_DIMS); - H5Pclose(cparms); - CloseResources (); - return 0; - }*/ - - cprintf(GREEN, "Chunk rank & dimensions validated. " - "Rank: %d, Dimensions: %llu x %llu x %llu\n", - rank_chunk, chunk_dims[Z], chunk_dims[Y], chunk_dims[X]); - - } - - H5Pclose (cparms); - - // allocate chunk memory - //current_image = new uint16_t[chunk_dims[Z]*DEFAULT_CHUNK_Y_DIMS*DEFAULT_CHUNK_X_DIMS]; - //current_image = new uint16_t[DEFAULT_X_DIMS*DEFAULT_Y_DIMS]; - - // Define memory space - //memspace = H5Screate_simple (RANK, chunk_dims, NULL); - - - // Get all the frame numbers - // Open frame index dataset - hid_t fi_dataset = H5Dopen2 (file, INDEX_DATASETNAME, H5P_DEFAULT); - if (fi_dataset < 0){ - cprintf (RED,"could not open frame index dataset %s\n", INDEX_DATASETNAME); - CloseResources (); + InitializeDimensions(); + // Get chunk dimensions + if (!ReadChunkDimensions()) { + CloseResources(); return 0; } - // validate size of frame index dataset + // validate file dimensions if (validate) { - hsize_t fi_dims[2]; - hid_t fi_dataspace = H5Dget_space (fi_dataset); - int fi_rank = H5Sget_simple_extent_dims (fi_dataspace, fi_dims, NULL); - - // validate rank - if(fi_rank != 2) { - cprintf(RED,"Frame index dataset rank found %d. Expected %d\n", fi_rank, 2); - H5Sclose (fi_dataspace); - H5Dclose (fi_dataset); - CloseResources (); - return 0; + if ( !ValidateDimensions() || !ValidateChunkDimensions() ) { + CloseResources(); + return 0; } - - // validate size - if (fi_dims[Z] != file_dims[Z]) { - cprintf (RED,"Frame index dimensions of z found %llu. Expected %llu\n", fi_dims[Z], file_dims[Z]); - H5Sclose (fi_dataspace); - H5Dclose (fi_dataset); - CloseResources (); - return 0; - } - H5Sclose (fi_dataspace); } - - // allocate frame index memory - frame_index_list = new unsigned int[file_dims[Z]]; - - //read frame index values - //Is u32 correct? I would think not. But I get a segmentation fault if I use u64. - if (H5Dread (fi_dataset, H5T_STD_U32LE, H5S_ALL, H5S_ALL, H5P_DEFAULT, frame_index_list) < 0) { - cprintf (RED,"Could not read frame index dataset %s\n", INDEX_DATASETNAME); - H5Dclose (fi_dataset); - CloseResources (); + //Read frame indices + if (!OpenFrameIndexDataset()) { + CloseResources(); + return 0; } - H5Dclose(fi_dataset); - + return 1; } @@ -228,73 +230,179 @@ void HDF5File::CloseResources () { H5Fclose(file); file = -1; } - //if (memspace >= 0) H5Sclose(memspace); // VH: I am getting memory leaks after recompilation } /* * Function takes uint16_t* argument to make explicit that the caller has to handle memory allocation and deallocation. * This is legacy caused by the structure with which the slsDetectorCalibration cluster finder is written. - * Best practice for modern C++ would be to rewrite using smart pointers. + * (Best practice for modern C++ would be using smart pointers.) + * + * Originially, this function took uint16_t** which may lead to memory management issues since image gets redirected + * to point to current_image, which is owned by HDF5File. + * (Good practice in classic C-style. HDF5File needs to clean up the resource at destruction.) + * + * \param image pointer to uint16_t, buffer which the image is read into. (Memory handled by caller!) + * \param offset contains iFrame at [0] and storage cell number at [1], + * depending on dimensionality of the dataset, the storage cell number may not be included. + * Note that frame number (as read from file) may (likely) differ from frame index (in the dataset)! */ -int HDF5File::ReadImage (uint16_t* image, int& iFrame) { - /* - * Originially, this function took uint16_t** but this may lead to memory management issues since image gets redirected - * to point to current_image, which is owned by HDF5File. - * (Usually, this would be good practice and classic C-style.) - */ +int HDF5File::ReadImage (uint16_t* image, std::vector& offset ) { - // no images in this frame - if (frame_index_list[frame_offset[Z]] == 0) { - cprintf (RED,"No images in this frame offset %llu\n", frame_offset[Z]); + // Validate input arguments + if (!image) { + std::cerr << "Error: image buffer is null.\n"; + return -99; + } + if ( offset.size() != rank-2 ) { + cprintf ( RED,"Offset vector must have size %llu. Found %llu\n", rank-2, offset.size() ); + std::cerr << "Error: Wrong offset vector size\n"; + CloseResources (); + return -99; + } + + // Initialize frame_offset + if (frame_offset.empty()) + frame_offset.resize(rank,0); + + // Validate frame_offset index + if (frame_offset[0] >= frame_index_list.size()) { + std::cerr << "Error: frame_offset[0] out of bounds.\n"; + return -99; + } + + // Check if images exist at the current frame offset + if (frame_index_list[frame_offset[0]] == 0) { + cprintf (RED,"No images at this frame offset %llu\n", frame_offset[0]); + std::cerr << "Error: Framenumber 0 at this frame offset\n"; CloseResources (); return -99; } - if (frame_offset[Z] == file_dims[Z]-1) { + // Check if we reached the end of file + // Compares that the offsets of frame and storage cell (Z and S) have reached the end of file + // Excludes X and Y indices (of the image dataset) from the comparison + if( std::equal( frame_offset.cbegin(), frame_offset.cend()-2, file_dims.cbegin() ) ) { + printf("End of file reached\n"); + return -1; + } + /* //old + if (frame_offset[0] == file_dims[0]-1) { printf("end of file\n"); return -1; } + */ - hsize_t frame_size[RANK] = {1, file_dims[X], file_dims[Y]}; + // Optional: Ensure dataset and dataspace are valid + if (dataset < 0) { + std::cerr << "Error: Invalid dataset ID.\n"; + return -99; + } + if (dataspace < 0) { + std::cerr << "Error: Invalid dataspace.\n"; + return -99; + } + + // Define the size of the hyperslab to read + std::vector frame_size(rank, 1); + std::copy(file_dims.begin() + rank-2, file_dims.end(), frame_size.begin() + rank-2); + /* + for ( int d=0; d < rank; ++d ) { + if (d < rank-2) + frame_size[d] = 1; + if ( d >= rank-2 ) + frame_size[d] = file_dims[d]; + } + */ // Define memory space - hid_t memspace = H5Screate_simple (RANK, frame_size, NULL); + hid_t memspace = H5Screate_simple (rank, frame_size.data(), nullptr); + if (memspace < 0) { + std::cerr << "Error: Failed to create memory space for HDF5 read operation\n"; + CloseResources(); + return -99; + } - // create hyperslab + // Create hyperslab selection // This aligns dataspace such that we read the correct frame - if (H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, frame_offset, NULL, frame_size, NULL) < 0 ) { - cprintf (RED,"Could not create hyperslab for frame count %llu\n", frame_offset[Z]); - CloseResources (); + if (H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, frame_offset.data(), nullptr, frame_size.data(), nullptr) < 0 ) { + cprintf (RED,"Could not create hyperslab for frame offset %s\n", vectorToString(frame_offset)); + std::cerr << "Error: Hyperslab creation failed for frame offset " << vectorToString(frame_offset) << "\n"; + CloseResources(); + H5Sclose(memspace); return -99; } - // read dataset into current_image - if (H5Dread(dataset, H5T_STD_U16LE, memspace, dataspace, H5P_DEFAULT, image /*was 'current_image'*/) < 0 ) { - cprintf (RED,"Could not read dataset for frame count %llu\n", frame_offset[Z]); + // Read dataset into image buffer (previously read to current_image owned by HDF5File) + if (H5Dread(dataset, H5T_STD_U16LE, memspace, dataspace, H5P_DEFAULT, image) < 0 ) { + cprintf (RED,"Could not read dataset for frame offset %s\n", vectorToString(frame_offset)); + std::cerr << "Error: Reading of dataset failed for given start frame offset " << vectorToString(frame_offset) << "\n"; CloseResources (); + H5Sclose(memspace); return -99; } + + // Clean up memory space + H5Sclose(memspace); + //*image = current_image; //if uint16_t** is passed, HDF5File owns the resource image points to, which is potentially dangerous - // return frame number and then increment frame count number - unsigned int retval = frame_index_list[frame_offset[Z]]; - iFrame = (int)frame_offset[Z]; - ++frame_offset[Z]; + // Return frame number + unsigned int retval = frame_index_list[frame_offset[0]]; + + // Pass updated frame offset value(s) via offset parameter vector + std::copy_n(frame_offset.begin(), offset.size(), offset.begin()); + /* + std::transform( offset.begin(), offset.end(), offset.begin(), + [&, i = 0](size_t) mutable { return frame_offset[i++]; } ); + */ + + // Increment frame offset correctly + conditionalIncrement(frame_offset, file_dims[1]); + //++frame_offset[0]; //old + return retval; } - - -void HDF5File::PrintCurrentImage () { +void HDF5File::PrintCurrentImage (uint16_t* image) { printf("\n"); - printf("Frame %llu, Image: %d\n", frame_offset[Z]-1, frame_index_list[frame_offset[Z]-1]); + printf("Frame %llu, Image: %d\n", frame_offset[0]-1, frame_index_list[frame_offset[0]-1]); - unsigned long long int size = file_dims[Y] * file_dims[X]; - for (unsigned int i = 0; i < size; ++i){ - printf("%u ", current_image[i]); - if (!((i+1) % file_dims[X] )) + hsize_t size = file_dims[rank-1] * file_dims[rank-2]; + for (hsize_t i = 0; i < size; ++i){ + printf("%u ", image[i]); + if (!((i+1) % file_dims[rank-2] )) printf("\n\n"); } printf("\n\n\n\n"); } +/* + * No class member helper functions + */ +std::string vectorToString(std::vector const& v) { + return fmt::format("({})", fmt::join(v, ", ")); +} + +/* + * increment frame offset (if s dimension exists, loop through all before incrementing z) + * should also work if file_dims[1] is not s but x (in that case we ignore it) + */ +void conditionalIncrement(std::vector& vec, int max_value) { + + if (vec.size() < 3) { + throw std::invalid_argument("Vector must have at least 3 elements."); + } + + // If vector has 4 elements, increment vec[1] first + if (vec.size() == 4) { + if (++vec[1] >= max_value) { //max_value is never reached! + vec[1] = 0; // Reset and increment vec[0] + ++vec[0]; + } + } + // If vector has 3 elements, increment vec[0] directly + else if (vec.size() == 3) { + ++vec[0]; + } +} + diff --git a/slsDetectorCalibration/dataStructures/HDF5File.h b/slsDetectorCalibration/dataStructures/HDF5File.h index 75edfcf9f..97141c587 100644 --- a/slsDetectorCalibration/dataStructures/HDF5File.h +++ b/slsDetectorCalibration/dataStructures/HDF5File.h @@ -2,41 +2,45 @@ /************************************************ * @file HDF5Fle.h * @short functions to open/close/read HDF5 File + * Adapted for generalization, accepts rank 3 and 4 + * Supports control over storage cells ***********************************************/ /** *@short functions to open/close/read HDF5 File */ +#include +#include +#include + #include "hdf5.h" #include "hdf5_hl.h" -#define MAX_STR_LENGTH 1000 +//#define MAX_STR_LENGTH 1000 -#define RANK 3 // Dimension of the image -#define DEFAULT_Z_DIMS 10000 -#define DEFAULT_Y_DIMS 1024 -#define DEFAULT_X_DIMS 512 -//#define DEFAULT_S_DIMS 1 // Storage cells +#define RANK 4 // Dimension of the image dataset, only for validation +#define DEFAULT_Z_DIMS 10000 // only for validation +#define DEFAULT_Y_DIMS 1024 // only for validation +#define DEFAULT_X_DIMS 512 // only for validation +//#define DEFAULT_S_DIMS 1 // Storage cells -#define DEFAULT_CHUNK_Z_DIMS 1 -#define DEFAULT_CHUNK_Y_DIMS 1024 -#define DEFAULT_CHUNK_X_DIMS 512 +#define DEFAULT_CHUNK_Z_DIMS 100 // only for validation +#define DEFAULT_CHUNK_Y_DIMS 1024 // only for validation +#define DEFAULT_CHUNK_X_DIMS 512 // only for validation //#define DEFAULT_CHUNK_S_DIMS 1 -/** Assuming each chunk is one image 1024 x 512*/ #define DATA_DATASETNAME "/data/JF18T01V01/data" //Furka JF #define INDEX_DATASETNAME "/data/JF18T01V01/frame_index" -enum{Z,X,Y}; //S is the storage cell +//enum{Z,S,X,Y}; //S is the storage cell //enum is not used class HDF5File { public: - /** * Constructor */ @@ -47,10 +51,16 @@ public: */ ~HDF5File (); - /** - * Initialize Parameters for each new file - */ - void InitializeParameters (); + + std::vector GetDatasetDimensions (); + + std::vector GetChunkDimensions (); + + void SetImageDataPath (std::string const& name); + + void SetFrameIndexPath (std::string const& name); + + /** * Open HDF5 file and dataset, @@ -68,52 +78,80 @@ public: void CloseResources (); /** - * Read an image into current_image + * Read an image into current_image, + * increment Z-offset (frame) and (if rank==4) storage cell * @returns frame number read, */ - int ReadImage (uint16_t* image, int& iFrame); + int ReadImage (uint16_t* image, std::vector& offset); /** * Print current image in memory */ - void PrintCurrentImage (); + void PrintCurrentImage (uint16_t* image); private: + /** + * Initialize dimensions of image dataset for each new file + */ + void InitializeDimensions (); + + bool ReadChunkDimensions (); + + bool ValidateDimensions (); + + bool ValidateChunkDimensions (); + + /** + * Open dataset containing the frame numbers + */ + bool OpenFrameIndexDataset (); + + /** file name */ std::string file_name{}; + /** dataset name for image data */ + std::string data_datasetname = DATA_DATASETNAME; + /** dataset name for frame index data */ + std::string index_datasetname = INDEX_DATASETNAME; /** file handle */ hid_t file{}; - /** dataspace handle */ hid_t dataspace{}; - /** memory space handle */ - //hid_t memspace; - + //hid_t memspace; //old /** dataset handle */ hid_t dataset{}; - /** file dimensions */ - hsize_t file_dims[RANK]{}; //static array (dimensions are known) //I think the {} initialization should work... + std::vector file_dims{}; + //hsize_t file_dims[RANK]{}; //static array (dimensions are known) - /** chunk dimensions */ - hsize_t chunk_dims[RANK]{}; + /** chunk dimensions + ** not necessarily required + ** useful for optimization or validation */ + std::vector chunk_dims{}; + //hsize_t chunk_dims[RANK]{}; + + /** Rank of the image dataset */ + hsize_t rank{}; /** number of frames */ unsigned int number_of_frames{}; /** frame index list */ - unsigned int* frame_index_list{NULL}; //dynamic array + std::vector frame_index_list{}; - - /** current image */ - uint16_t* current_image{NULL}; //dynamic array + /** Current image + ** dynamic array + ** uint16_t pointer format is chosen to support use with slsDetectorCalibration cluster finder */ + uint16_t* current_image{nullptr}; //uint16_t current_chunk[DEFAULT_CHUNK_Z_DIMS][DEFAULT_CHUNK_Y_DIMS][DEFAULT_CHUNK_X_DIMS]; - /** current frame offset */ - hsize_t frame_offset[RANK]{}; //array (frame_offset[Z], 0, 0) I believe + /** Current frame offset + ** (Z-offset, S-offset, 0, 0) or (Z-offset, 0, 0), increments automatically with ReadImage */ + std::vector frame_offset{}; + //hsize_t frame_offset[RANK]{}; }; diff --git a/slsDetectorCalibration/dataStructures/jungfrauLGADStrixelsDataQuadH5.h b/slsDetectorCalibration/dataStructures/jungfrauLGADStrixelsDataQuadH5.h index c7d232cba..c222057e3 100644 --- a/slsDetectorCalibration/dataStructures/jungfrauLGADStrixelsDataQuadH5.h +++ b/slsDetectorCalibration/dataStructures/jungfrauLGADStrixelsDataQuadH5.h @@ -333,16 +333,17 @@ class jungfrauLGADStrixelsDataQuadH5 : public slsDetectorData { char* readNextFrame( HDF5File& hfile ) { - int fn = 0, iframe = 0; - return readNextFrame(hfile, fn, iframe); + int fn = 0; + std::vector h5offset(1); + return readNextFrame(hfile, fn, h5offset); }; char* readNextFrame( HDF5File& hfile, int& fn ) { - int iframe = 0; - return readNextFrame(hfile, fn, iframe); + std::vector h5offset(1); + return readNextFrame(hfile, fn, h5offset); }; - char* readNextFrame( HDF5File& hfile, int& fn, int& iframe ) { + char* readNextFrame( HDF5File& hfile, int& fn, std::vector& h5offset ) { // Ensure dataSize is a valid size for allocation if (dataSize <= 0) { @@ -351,7 +352,7 @@ class jungfrauLGADStrixelsDataQuadH5 : public slsDetectorData { } char* data = new char[dataSize]; - char* readResult = readNextFrame(hfile, fn, iframe, data); + char* readResult = readNextFrame(hfile, fn, h5offset, data); // Check if reading failed if (readResult == nullptr) { @@ -369,15 +370,16 @@ class jungfrauLGADStrixelsDataQuadH5 : public slsDetectorData { * The overloads are legacy! * Note that caller has to allocate and deallocate memory for data! */ - char* readNextFrame( HDF5File& hfile, int& framenumber, int& iframe, char* data ) { + char* readNextFrame( HDF5File& hfile, int& framenumber, std::vector& h5offset, char* data ) { - if (iframe >= 0) { + if (h5offset[0] >= 0) { std::cout << "*"; //Storing the reinterpret_cast in the variable data_ptr ensures that I can pass it to a function that expects at uint16_t* uint16_t* data_ptr = reinterpret_cast(data); //now data_ptr points where data points (thus modifies the same memory) - iframe = hfile.ReadImage( data_ptr, framenumber ); + framenumber = hfile.ReadImage( data_ptr, h5offset ); + iframe = h5offset[0]; //iframe is a class member! return data; // return reinterpret_cast(data_ptr); // Equivalent } diff --git a/slsDetectorCalibration/jungfrauExecutables/jungfrauRawDataProcess_filetxtH5.cpp b/slsDetectorCalibration/jungfrauExecutables/jungfrauRawDataProcess_filetxtH5.cpp index c1af20617..e2b3cc5c3 100644 --- a/slsDetectorCalibration/jungfrauExecutables/jungfrauRawDataProcess_filetxtH5.cpp +++ b/slsDetectorCalibration/jungfrauExecutables/jungfrauRawDataProcess_filetxtH5.cpp @@ -30,6 +30,11 @@ using json = nlohmann::json; */ +/*Dataset paths according to different beamlines*/ +std::string const data_datasetname_furka("/data/JF18T01V01/data"); +std::string const index_datasetname_furka("/data/JF18T01V01/frame_index"); +std::string const data_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/adc"); +std::string const index_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/frameNumber"); std::string getRootString( std::string const& filepath ) { size_t pos1; @@ -64,9 +69,11 @@ int main(int argc, char *argv[]) { if (argc < 4) { std::cout << "Usage is " << argv[0] - << " filestxt outdir [pedfile (h5)] optional: [bool validate h5 rank] " - "[xmin xmax ymin ymax] [threshold] [nframes] " - "NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS! " + << " filestxt outdir [pedfile (h5)] " + " optional: [int dataset path; 0 means Furka, 1 means XFEL; overwrites default given in HDF5File.h] " + " [bool validate h5 rank] " + " [xmin xmax ymin ymax] [threshold] [nframes] " + " NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS! " << std::endl; std::cout << "threshold <0 means analog; threshold=0 means cluster finder; " @@ -91,18 +98,35 @@ int main(int argc, char *argv[]) { std::string const outdir(argv[2]); std::string const pedfilename(argv[3]); + std::string datasetpath{}; + std::string frameindexpath{}; + if (argc > 4) { + switch (atoi(argv[4])) { + case 0: + datasetpath = data_datasetname_furka; + frameindexpath = index_datasetname_furka; + break; + case 1: + datasetpath = data_datasetname_xfelSCS; + frameindexpath = index_datasetname_xfelSCS; + break; + default: + break; + } + } + bool validate_rank=true; - if (argc > 4) - validate_rank = atoi(argv[4]); + if (argc > 5) + validate_rank = atoi(argv[5]); double thr = 0; double thr1 = 1; - if (argc > 8) - thr = atof(argv[8]); + if (argc > 9) + thr = atof(argv[9]); int nframes = 0; - if (argc > 9) - nframes = atoi(argv[9]); + if (argc > 10) + nframes = atoi(argv[10]); //Get vector of filenames from input txt-file std::vector filenames{}; @@ -142,11 +166,11 @@ int main(int argc, char *argv[]) { //Cluster finder ROI int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1; - if (argc > 8) { - xmin = atoi(argv[5]); - xmax = atoi(argv[6]); - ymin = atoi(argv[7]); - ymax = atoi(argv[8]); + if (argc > 9) { + xmin = atoi(argv[6]); + xmax = atoi(argv[7]); + ymin = atoi(argv[8]); + ymax = atoi(argv[9]); } std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]" << std::endl; @@ -214,7 +238,7 @@ int main(int argc, char *argv[]) { int ifr = 0; //frame counter of while loop int framenumber = -1; //framenumber as read from file (detector) - int iframe = 0; //frame counter internal to HDF5File::ReadImage (provided for sanity check/debugging) + std::vector h5offset(1,0); //frame counter internal to HDF5File::ReadImage (provided for sanity check/debugging) if (pedfilename.length()>1) { @@ -232,13 +256,15 @@ int main(int argc, char *argv[]) { //HDF5File pedefile; auto pedefile = std::make_unique(); + pedefile->SetFrameIndexPath(frameindexpath); + pedefile->SetFrameIndexPath(datasetpath); // //open file if ( pedefile->OpenResources(fname.c_str(),validate_rank) ) { std::cout << "bbbb " << std::ctime(&end_time) << std::endl; framenumber = -1; - while ( decoder->readNextFrame(*pedefile, framenumber, iframe, buff) ) { + while ( decoder->readNextFrame(*pedefile, framenumber, h5offset, buff) ) { if ((ifr + 1) % 100 == 0) { std::cout @@ -250,7 +276,7 @@ int main(int argc, char *argv[]) { mt->popFree(buff); ++ifr; if (ifr % 100 == 0) { - std::cout << " ****" << ifr << " " << framenumber << " " << iframe + std::cout << " ****" << ifr << " " << framenumber << " " << h5offset[0] << std::endl; } // else @@ -316,6 +342,8 @@ int main(int argc, char *argv[]) { //HDF5File fileh5; auto fileh5 = std::make_unique(); + fileh5->SetFrameIndexPath(frameindexpath); + fileh5->SetImageDataPath(datasetpath); // //open file ioutfile = 0; if ( fileh5->OpenResources(filenames[ifile].c_str(), validate_rank) ) { @@ -344,10 +372,10 @@ int main(int argc, char *argv[]) { // //while read frame framenumber = -1; - iframe = 0; + h5offset[0] = 0; ifr = 0; //std::cout << "Here! " << framenumber << " "; - while ( decoder->readNextFrame(*fileh5, framenumber, iframe, buff) ) { + while ( decoder->readNextFrame(*fileh5, framenumber, h5offset, buff) ) { //std::cout << "Here! " << framenumber << " "; // //push if ((ifr + 1) % 1000 == 0) { @@ -364,7 +392,8 @@ int main(int argc, char *argv[]) { ++ifr; if (ifr % 1000 == 0) - std::cout << " " << ifr << " " << framenumber << std::endl; + std::cout << " " << ifr << " " << framenumber << " " << h5offset[0] + << std::endl; if (nframes > 0) { if (ifr % nframes == 0) { imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", ioutfile );