Generalize HDF5 reader for 3- or 4-dimensional datasets

This commit is contained in:
hinger_v 2025-02-03 17:28:33 +01:00
parent 25854f7736
commit 71ca4e9f0f
4 changed files with 438 additions and 261 deletions

View File

@ -2,214 +2,216 @@
#include "ansi.h"
#include <string.h>
#include <algorithm>
#include <fmt/ranges.h>
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<hsize_t> HDF5File::GetDatasetDimensions() {
return file_dims;
}
std::vector<hsize_t> 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<hsize_t> 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 ();
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<hsize_t>& 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<hsize_t> 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<hsize_t> 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<hsize_t>& 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];
}
}

View File

@ -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 <iostream>
#include <vector>
#include <string>
#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<hsize_t> GetDatasetDimensions ();
std::vector<hsize_t> 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<hsize_t>& 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<hsize_t> 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<hsize_t> 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<hsize_t> 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<hsize_t> frame_offset{};
//hsize_t frame_offset[RANK]{};
};

View File

@ -333,16 +333,17 @@ class jungfrauLGADStrixelsDataQuadH5 : public slsDetectorData<uint16_t> {
char* readNextFrame( HDF5File& hfile ) {
int fn = 0, iframe = 0;
return readNextFrame(hfile, fn, iframe);
int fn = 0;
std::vector<hsize_t> h5offset(1);
return readNextFrame(hfile, fn, h5offset);
};
char* readNextFrame( HDF5File& hfile, int& fn ) {
int iframe = 0;
return readNextFrame(hfile, fn, iframe);
std::vector<hsize_t> h5offset(1);
return readNextFrame(hfile, fn, h5offset);
};
char* readNextFrame( HDF5File& hfile, int& fn, int& iframe ) {
char* readNextFrame( HDF5File& hfile, int& fn, std::vector<hsize_t>& h5offset ) {
// Ensure dataSize is a valid size for allocation
if (dataSize <= 0) {
@ -351,7 +352,7 @@ class jungfrauLGADStrixelsDataQuadH5 : public slsDetectorData<uint16_t> {
}
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<uint16_t> {
* 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<hsize_t>& 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<uint16_t*>(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<char*>(data_ptr); // Equivalent
}

View File

@ -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<std::string> 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<hsize_t> 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<HDF5File>();
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<HDF5File>();
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 );