mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-03 03:20:40 +02:00
works for hdf5, needs refactoring
This commit is contained in:
parent
4233509615
commit
b23e697e26
@ -8,6 +8,66 @@
|
||||
|
||||
namespace aare {
|
||||
|
||||
struct H5Handles {
|
||||
std::string file_name{};
|
||||
std::string dataset_name{};
|
||||
H5::H5File file;
|
||||
H5::DataSet dataset;
|
||||
H5::DataSpace dataspace;
|
||||
H5::DataType datatype;
|
||||
std::unique_ptr<H5::DataSpace> memspace{nullptr};
|
||||
std::vector<hsize_t>dims;
|
||||
std::vector<hsize_t> count;
|
||||
std::vector<hsize_t> offset;
|
||||
|
||||
H5Handles(const std::string& fname, const std::string& dname, int rank):
|
||||
file_name(fname),
|
||||
dataset_name(dname),
|
||||
file(fname, H5F_ACC_RDONLY),
|
||||
dataset(file.openDataSet(dname)),
|
||||
dataspace(dataset.getSpace()),
|
||||
datatype(dataset.getDataType())
|
||||
{
|
||||
if (dataspace.getSimpleExtentNdims() != rank) {
|
||||
throw std::runtime_error(LOCATION + "Expected rank of " + dname + " dataset to be 1. Got " + std::to_string(rank));
|
||||
}
|
||||
dims.resize(rank);
|
||||
dataspace.getSimpleExtentDims(dims.data(), nullptr);
|
||||
|
||||
// to slice 1 frame with hyperslab
|
||||
count.push_back(1);
|
||||
offset.push_back(0);
|
||||
|
||||
// header datasets
|
||||
if (rank == 1) {
|
||||
memspace = std::make_unique<H5::DataSpace>(H5S_SCALAR);
|
||||
}
|
||||
// data dataset
|
||||
else {
|
||||
hsize_t dimsm[2] = {dims[1], dims[2]};
|
||||
memspace = std::make_unique<H5::DataSpace>(2, dimsm);
|
||||
count.push_back(dims[1]);
|
||||
count.push_back(dims[2]);
|
||||
offset.push_back(0);
|
||||
offset.push_back(0);
|
||||
}
|
||||
};
|
||||
|
||||
void seek(size_t frame_index) {
|
||||
if (frame_index >= dims[0]) {
|
||||
throw std::runtime_error(LOCATION + "Invalid frame number");
|
||||
}
|
||||
offset[0] = static_cast<hsize_t>(frame_index);
|
||||
};
|
||||
|
||||
void get_frame_into(size_t frame_index, std::byte *frame_buffer) {
|
||||
seek(frame_index);
|
||||
dataspace.selectHyperslab(H5S_SELECT_SET, count.data(), offset.data());
|
||||
dataset.read(frame_buffer, datatype, *memspace, dataspace);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to read .h5 files. The class will parse the master file
|
||||
* to find the correct geometry for the frames.
|
||||
@ -21,11 +81,6 @@ class Hdf5File : public FileInterface {
|
||||
size_t m_total_frames{};
|
||||
size_t m_rows{};
|
||||
size_t m_cols{};
|
||||
H5::DataType m_datatype{};
|
||||
|
||||
std::unique_ptr<H5::H5File> file{nullptr};
|
||||
std::unique_ptr<H5::DataSet> dataset{nullptr};
|
||||
std::unique_ptr<H5::DataSpace> dataspace{nullptr};
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -71,10 +126,23 @@ class Hdf5File : public FileInterface {
|
||||
* @param frame_number frame number to read
|
||||
* @param image_buf buffer to store the frame
|
||||
*/
|
||||
|
||||
void get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||
DetectorHeader *header = nullptr);
|
||||
|
||||
|
||||
/**
|
||||
* @brief read the frame at the given frame index into the image buffer
|
||||
* @param frame_index frame number to read
|
||||
* @param frame_buffer buffer to store the frame
|
||||
*/
|
||||
void get_data_into(size_t frame_index, std::byte *frame_buffer);
|
||||
|
||||
/**
|
||||
* @brief read the header at the given frame index into the header buffer
|
||||
* @param frame_index frame number to read
|
||||
* @param header buffer to store the header
|
||||
*/
|
||||
void get_header_into(size_t frame_index, DetectorHeader *header);
|
||||
|
||||
/**
|
||||
* @brief get the frame at the given frame index
|
||||
* @param frame_number frame number to read
|
||||
@ -90,7 +158,13 @@ class Hdf5File : public FileInterface {
|
||||
static DetectorHeader read_header(const std::filesystem::path &fname);
|
||||
|
||||
static const std::string metadata_group_name;
|
||||
void open_file();
|
||||
static const std::vector<std::string> header_dataset_names;
|
||||
|
||||
std::unique_ptr<H5Handles> m_data_file{nullptr};
|
||||
std::vector<std::unique_ptr<H5Handles>> m_header_files;
|
||||
|
||||
void open_data_file();
|
||||
void open_header_files();
|
||||
};
|
||||
|
||||
} // namespace aare
|
162
src/Hdf5File.cpp
162
src/Hdf5File.cpp
@ -10,7 +10,8 @@ Hdf5File::Hdf5File(const std::filesystem::path &fname, const std::string &mode)
|
||||
: m_master(fname) {
|
||||
m_mode = mode;
|
||||
if (mode == "r") {
|
||||
open_file();
|
||||
open_data_file();
|
||||
open_header_files();
|
||||
} else {
|
||||
throw std::runtime_error(LOCATION +
|
||||
"Unsupported mode. Can only read Hdf5Files.");
|
||||
@ -66,12 +67,9 @@ DetectorType Hdf5File::detector_type() const {
|
||||
}
|
||||
|
||||
void Hdf5File::seek(size_t frame_index) {
|
||||
// check if the frame number is greater than the total frames
|
||||
// if frame_number == total_frames, then the next read will throw an error
|
||||
if (frame_index > total_frames()) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("frame number {} is greater than total frames {}",
|
||||
frame_index, total_frames()));
|
||||
m_data_file->seek(frame_index);
|
||||
for (size_t i = 0; i != header_dataset_names.size(); ++i) {
|
||||
m_header_files[i]->seek(frame_index);
|
||||
}
|
||||
m_current_frame = frame_index;
|
||||
};
|
||||
@ -86,6 +84,37 @@ xy Hdf5File::geometry() { return m_master.geometry(); }
|
||||
|
||||
DetectorHeader Hdf5File::read_header(const std::filesystem::path &fname) {
|
||||
DetectorHeader h{};
|
||||
std::vector<std::unique_ptr<H5Handles>> handles;
|
||||
try {
|
||||
for (size_t i = 0; i != header_dataset_names.size(); ++i) {
|
||||
handles.push_back(std::make_unique<H5Handles>(fname.string(), metadata_group_name+ header_dataset_names[i], 1));
|
||||
}
|
||||
handles[0]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.frameNumber)));
|
||||
handles[1]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.expLength)));
|
||||
handles[2]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.packetNumber)));
|
||||
handles[3]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.bunchId)));
|
||||
handles[4]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.timestamp)));
|
||||
handles[5]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.modId)));
|
||||
handles[6]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.row)));
|
||||
handles[7]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.column)));
|
||||
handles[8]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.reserved)));
|
||||
handles[9]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.debug)));
|
||||
handles[10]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.roundRNumber)));
|
||||
handles[11]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.detType)));
|
||||
handles[12]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.version)));
|
||||
handles[13]->get_frame_into(0, reinterpret_cast<std::byte *>(&(h.packetMask)));
|
||||
|
||||
fmt::print("Read 1D header for frame {}\n", 0);
|
||||
} catch (const H5::Exception &e) {
|
||||
handles.clear();
|
||||
fmt::print("Exception type: {}\n", typeid(e).name());
|
||||
e.printErrorStack();
|
||||
throw std::runtime_error(
|
||||
LOCATION + "\nCould not to access header datasets in given file.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
FILE *fp = fopen(fname.string().c_str(), "r");
|
||||
if (!fp)
|
||||
throw std::runtime_error(
|
||||
@ -114,27 +143,35 @@ size_t Hdf5File::bytes_per_pixel() const { return m_master.bitdepth() / 8; }
|
||||
|
||||
void Hdf5File::get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||
DetectorHeader *header) {
|
||||
get_data_into(frame_index, frame_buffer);
|
||||
get_header_into(frame_index, header);
|
||||
}
|
||||
|
||||
// Check if the frame number is valid
|
||||
if (frame_index < 0 || frame_index >= m_total_frames) {
|
||||
throw std::runtime_error(LOCATION + "Invalid frame number");
|
||||
}
|
||||
|
||||
// Define the hyperslab to select the 2D slice for the given frame number
|
||||
hsize_t offset[3] = {static_cast<hsize_t>(frame_index), 0, 0};
|
||||
hsize_t count[3] = {1, m_rows, m_cols};
|
||||
dataspace->selectHyperslab(H5S_SELECT_SET, count, offset);
|
||||
|
||||
// Define the memory space for the 2D slice
|
||||
hsize_t dimsm[2] = {m_rows, m_cols};
|
||||
H5::DataSpace memspace(2, dimsm);
|
||||
|
||||
// Read the data into the provided 2D array
|
||||
dataset->read(frame_buffer, m_datatype, memspace, dataspace);
|
||||
|
||||
void Hdf5File::get_data_into(size_t frame_index, std::byte *frame_buffer) {
|
||||
m_data_file->get_frame_into(frame_index, frame_buffer);
|
||||
fmt::print("Read 2D data for frame {}\n", frame_index);
|
||||
}
|
||||
|
||||
void Hdf5File::get_header_into(size_t frame_index, DetectorHeader *header) {
|
||||
if (header) {
|
||||
m_header_files[0]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->frameNumber)));
|
||||
m_header_files[1]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->expLength)));
|
||||
m_header_files[2]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->packetNumber)));
|
||||
m_header_files[3]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->bunchId)));
|
||||
m_header_files[4]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->timestamp)));
|
||||
m_header_files[5]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->modId)));
|
||||
m_header_files[6]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->row)));
|
||||
m_header_files[7]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->column)));
|
||||
m_header_files[8]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->reserved)));
|
||||
m_header_files[9]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->debug)));
|
||||
m_header_files[10]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->roundRNumber)));
|
||||
m_header_files[11]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->detType)));
|
||||
m_header_files[12]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->version)));
|
||||
m_header_files[13]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&(header->packetMask)));
|
||||
fmt::print("Read 1D header for frame {}\n", frame_index);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Frame> Hdf5File::read_n(size_t n_frames) {
|
||||
// TODO: implement this in a more efficient way
|
||||
std::vector<Frame> frames;
|
||||
@ -146,48 +183,45 @@ std::vector<Frame> Hdf5File::read_n(size_t n_frames) {
|
||||
}
|
||||
|
||||
size_t Hdf5File::frame_number(size_t frame_index) {
|
||||
if (frame_index >= m_master.frames_in_file()) {
|
||||
throw std::runtime_error(LOCATION + " Frame number out of range");
|
||||
}
|
||||
size_t subfile_id = frame_index / m_master.max_frames_per_file();
|
||||
/*if (subfile_id >= subfiles.size()) {
|
||||
throw std::runtime_error(
|
||||
LOCATION + " Subfile out of range. Possible missing data.");
|
||||
}*/
|
||||
return 1; // subfiles[subfile_id][0]->frame_number(
|
||||
// frame_index % m_master.max_frames_per_file());
|
||||
uint64_t fnum{0};
|
||||
m_header_files[0]->get_frame_into(frame_index, reinterpret_cast<std::byte *>(&fnum));
|
||||
return fnum;
|
||||
}
|
||||
|
||||
Hdf5File::~Hdf5File() {}
|
||||
|
||||
const std::string Hdf5File::metadata_group_name = "/entry/data/";
|
||||
const std::vector<std::string> Hdf5File::header_dataset_names = {
|
||||
"frame number",
|
||||
"exp length or sub exposure time",
|
||||
"packets caught",
|
||||
"detector specific 1",
|
||||
"timestamp",
|
||||
"mod id",
|
||||
"row",
|
||||
"column",
|
||||
"detector specific 2",
|
||||
"detector specific 3",
|
||||
"detector specific 4",
|
||||
"detector type",
|
||||
"detector header version",
|
||||
"packets caught bit mask"
|
||||
};
|
||||
|
||||
void Hdf5File::open_file() {
|
||||
void Hdf5File::open_data_file() {
|
||||
if (m_mode != "r")
|
||||
throw std::runtime_error(LOCATION +
|
||||
"Unsupported mode. Can only read Hdf5 files.");
|
||||
try {
|
||||
file = std::make_unique<H5::H5File>(m_master.master_fname().string(),
|
||||
H5F_ACC_RDONLY);
|
||||
dataset = std::make_unique<H5::DataSet>(
|
||||
file->openDataSet(metadata_group_name + "/data"));
|
||||
dataspace = std::make_unique<H5::DataSpace>(dataset->getSpace());
|
||||
int rank = dataspace->getSimpleExtentNdims();
|
||||
if (rank != 3) {
|
||||
throw std::runtime_error(
|
||||
LOCATION + "Expected rank of '/data' dataset to be 3. Got " +
|
||||
std::to_string(rank));
|
||||
}
|
||||
hsize_t dims[3];
|
||||
dataspace->getSimpleExtentDims(dims, nullptr);
|
||||
m_total_frames = dims[0];
|
||||
m_rows = dims[1];
|
||||
m_cols = dims[2];
|
||||
m_datatype = dataset->getDataType();
|
||||
fmt::print("Dataset dimensions: frames = {}, rows = {}, cols = {}\n",
|
||||
m_data_file = std::make_unique<H5Handles>(m_master.master_fname().string(), metadata_group_name + "/data", 3);
|
||||
|
||||
m_total_frames = m_data_file->dims[0];
|
||||
m_rows = m_data_file->dims[1];
|
||||
m_cols = m_data_file->dims[2];
|
||||
fmt::print("Data Dataset dimensions: frames = {}, rows = {}, cols = {}\n",
|
||||
m_total_frames, m_rows, m_cols);
|
||||
} catch (const H5::Exception &e) {
|
||||
file->close();
|
||||
m_data_file.reset();
|
||||
fmt::print("Exception type: {}\n", typeid(e).name());
|
||||
e.printErrorStack();
|
||||
throw std::runtime_error(
|
||||
@ -195,4 +229,24 @@ void Hdf5File::open_file() {
|
||||
}
|
||||
}
|
||||
|
||||
void Hdf5File::open_header_files() {
|
||||
if (m_mode != "r")
|
||||
throw std::runtime_error(LOCATION +
|
||||
"Unsupported mode. Can only read Hdf5 files.");
|
||||
try {
|
||||
for (size_t i = 0; i != header_dataset_names.size(); ++i) {
|
||||
m_header_files.push_back(std::make_unique<H5Handles>(m_master.master_fname().string(), metadata_group_name + header_dataset_names[i], 1));
|
||||
fmt::print("{} Dataset dimensions: size = {}\n",
|
||||
header_dataset_names[i], m_header_files[i]->dims[0]);
|
||||
}
|
||||
} catch (const H5::Exception &e) {
|
||||
m_header_files.clear();
|
||||
m_data_file.reset();
|
||||
fmt::print("Exception type: {}\n", typeid(e).name());
|
||||
e.printErrorStack();
|
||||
throw std::runtime_error(
|
||||
LOCATION + "\nCould not to access header datasets in master file.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace aare
|
Loading…
x
Reference in New Issue
Block a user