works for hdf5, needs refactoring

This commit is contained in:
2024-12-04 00:52:36 +01:00
parent 4233509615
commit b23e697e26
2 changed files with 190 additions and 62 deletions

View File

@@ -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