first draft of hdf5, reads master metadata, reads data dims, process of hyperslab

This commit is contained in:
2024-12-03 21:16:58 +01:00
parent b43003966f
commit 4233509615
26 changed files with 1417 additions and 11 deletions

View File

@ -34,6 +34,31 @@ set( PYTHON_FILES
aare/utils.py
)
# Conditionally add HDF5-related Python files
# HDF5
# if (AARE_HDF5)
# find_package(h5py REQUIRED)
# find_package(HDF5 1.10 COMPONENTS CXX REQUIRED)
# add_definitions(
# ${HDF5_DEFINITIONS}
# )
# list(APPEND PYTHON_FILES
# aare/Hdf5File.py
# )
# if(HDF5_FOUND)
# target_sources(_aare PRIVATE
# ${CMAKE_CURRENT_SOURCE_DIR}/src/Hdf5File.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/src/Hdf5MasterFile.cpp
# )
# target_link_libraries(_aare PUBLIC ${HDF5_LIBRARIES})
# target_include_directories(_aare PUBLIC ${HDF5_INCLUDE_DIRS})
# endif()
# if(H5PY_FOUND)
# set(H5PY_INCLUDE_DIRS ${H5PY_INCLUDE_DIR})
# set(H5PY_LIBRARIES ${PYTHON_LIBRARIES})
# endif()
# Copy the python files to the build directory
foreach(FILE ${PYTHON_FILES})
configure_file(${FILE} ${CMAKE_BINARY_DIR}/${FILE} )

66
python/aare/Hdf5File.py Normal file
View File

@ -0,0 +1,66 @@
from . import _aare
import numpy as np
#from .ScanParameters import ScanParameters
class Hdf5File(_aare.Hdf5File):
def __init__(self, fname, chunk_size = 1):
super().__init__(fname)
self._chunk_size = chunk_size
def read(self) -> tuple:
"""Read the entire file.
Seeks to the beginning of the file before reading.
Returns:
tuple: header, data
"""
self.seek(0)
return self.read_n(self.total_frames)
# @property
# def scan_parameters(self):
# """Return the scan parameters.
# Returns:
# ScanParameters: Scan parameters.
# """
# return ScanParameters(self.master.scan_parameters)
@property
def master(self):
"""Return the master file.
Returns:
Hdf5MasterFile: Master file.
"""
return super().master
def __len__(self) -> int:
"""Return the number of frames in the file.
Returns:
int: Number of frames in file.
"""
return super().frames_in_file
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
pass
def __iter__(self):
return self
def __next__(self):
try:
if self._chunk_size == 1:
return self.read_frame()
else:
return self.read_n(self._chunk_size)
except RuntimeError:
# TODO! find a good way to check that we actually have the right exception
raise StopIteration

View File

@ -11,4 +11,22 @@ from .CtbRawFile import CtbRawFile
from .RawFile import RawFile
from .ScanParameters import ScanParameters
from .utils import random_pixels, random_pixel
from .utils import random_pixels, random_pixel
try:
import h5py
HDF5_FOUND = True
except ImportError:
HDF5_FOUND = False
if HDF5_FOUND:
from ._aare import Hdf5MasterFile
from .Hdf5File import Hdf5File
else:
class Hdf5MasterFile:
def __init__(self, *args, **kwargs):
raise ImportError("h5py library not found. HDF5 Master File is not available.")
class Hdf5File:
def __init__(self, *args, **kwargs):
raise ImportError("h5py library not found. HDF5 File is not available.")

View File

@ -5,6 +5,11 @@
#include "aare/RawMasterFile.hpp"
#include "aare/RawSubFile.hpp"
#ifdef HDF5_FOUND
#include "aare/Hdf5File.hpp"
#include "aare/Hdf5MasterFile.hpp"
#endif
#include "aare/defs.hpp"
// #include "aare/fClusterFileV2.hpp"

105
python/src/hdf5_file.hpp Normal file
View File

@ -0,0 +1,105 @@
#include "aare/File.hpp"
#include "aare/Frame.hpp"
#include "aare/Hdf5File.hpp"
#include "aare/Hdf5MasterFile.hpp"
#include "aare/defs.hpp"
// #include "aare/fClusterFileV2.hpp"
#include <cstdint>
#include <filesystem>
#include <pybind11/iostream.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl/filesystem.h>
#include <string>
namespace py = pybind11;
using namespace ::aare;
void define_hdf5_file_io_bindings(py::module &m) {
py::class_<Hdf5File>(m, "Hdf5File")
.def(py::init<const std::filesystem::path &>())
.def("read_frame",
[](Hdf5File &self) {
py::array image;
std::vector<ssize_t> shape;
shape.reserve(2);
shape.push_back(self.rows());
shape.push_back(self.cols());
// return headers from all subfiles
py::array_t<DetectorHeader> header(self.n_mod());
const uint8_t item_size = self.bytes_per_pixel();
if (item_size == 1) {
image = py::array_t<uint8_t>(shape);
} else if (item_size == 2) {
image = py::array_t<uint16_t>(shape);
} else if (item_size == 4) {
image = py::array_t<uint32_t>(shape);
}
self.read_into(
reinterpret_cast<std::byte *>(image.mutable_data()),
header.mutable_data());
return py::make_tuple(header, image);
})
.def(
"read_n",
[](Hdf5File &self, size_t n_frames) {
// adjust for actual frames left in the file
n_frames =
std::min(n_frames, self.total_frames() - self.tell());
if (n_frames == 0) {
throw std::runtime_error("No frames left in file");
}
std::vector<size_t> shape{n_frames, self.rows(), self.cols()};
// return headers from all subfiles
py::array_t<DetectorHeader> header;
if (self.n_mod() == 1) {
header = py::array_t<DetectorHeader>(n_frames);
} else {
header =
py::array_t<DetectorHeader>({self.n_mod(), n_frames});
}
// py::array_t<DetectorHeader> header({self.n_mod(), n_frames});
py::array image;
const uint8_t item_size = self.bytes_per_pixel();
if (item_size == 1) {
image = py::array_t<uint8_t>(shape);
} else if (item_size == 2) {
image = py::array_t<uint16_t>(shape);
} else if (item_size == 4) {
image = py::array_t<uint32_t>(shape);
}
self.read_into(
reinterpret_cast<std::byte *>(image.mutable_data()),
n_frames, header.mutable_data());
return py::make_tuple(header, image);
},
R"(
Read n frames from the file.
)")
.def("frame_number", &Hdf5File::frame_number)
.def_property_readonly("bytes_per_frame", &Hdf5File::bytes_per_frame)
.def_property_readonly("pixels_per_frame", &Hdf5File::pixels_per_frame)
.def_property_readonly("bytes_per_pixel", &Hdf5File::bytes_per_pixel)
.def("seek", &Hdf5File::seek, R"(
Seek to a frame index in file.
)")
.def("tell", &Hdf5File::tell, R"(
Return the current frame number.)")
.def_property_readonly("total_frames", &Hdf5File::total_frames)
.def_property_readonly("rows", &Hdf5File::rows)
.def_property_readonly("cols", &Hdf5File::cols)
.def_property_readonly("bitdepth", &Hdf5File::bitdepth)
.def_property_readonly("geometry", &Hdf5File::geometry)
.def_property_readonly("n_mod", &Hdf5File::n_mod)
.def_property_readonly("detector_type", &Hdf5File::detector_type)
.def_property_readonly("master", &Hdf5File::master);
}

View File

@ -0,0 +1,86 @@
#include "aare/File.hpp"
#include "aare/Frame.hpp"
#include "aare/Hdf5File.hpp"
#include "aare/Hdf5MasterFile.hpp"
#include "aare/defs.hpp"
// #include "aare/fClusterFileV2.hpp"
#include <cstdint>
#include <filesystem>
#include <pybind11/iostream.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl/filesystem.h>
#include <string>
namespace py = pybind11;
using namespace ::aare;
void define_hdf5_master_file_bindings(py::module &m) {
py::class_<Hdf5MasterFile>(m, "Hdf5MasterFile")
.def(py::init<const std::filesystem::path &>())
.def("data_fname", &Hdf5MasterFile::data_fname, R"(
Parameters
------------
module_index : int
module index (d0, d1 .. dN)
file_index : int
file index (f0, f1 .. fN)
Returns
----------
os.PathLike
The name of the data file.
)")
.def_property_readonly("version", &Hdf5MasterFile::version)
.def_property_readonly("detector_type", &Hdf5MasterFile::detector_type)
.def_property_readonly("timing_mode", &Hdf5MasterFile::timing_mode)
.def_property_readonly("image_size_in_bytes",
&Hdf5MasterFile::image_size_in_bytes)
.def_property_readonly("frames_in_file",
&Hdf5MasterFile::frames_in_file)
.def_property_readonly("pixels_y", &Hdf5MasterFile::pixels_y)
.def_property_readonly("pixels_x", &Hdf5MasterFile::pixels_x)
.def_property_readonly("max_frames_per_file",
&Hdf5MasterFile::max_frames_per_file)
.def_property_readonly("bitdepth", &Hdf5MasterFile::bitdepth)
.def_property_readonly("frame_padding", &Hdf5MasterFile::frame_padding)
.def_property_readonly("frame_discard_policy",
&Hdf5MasterFile::frame_discard_policy)
.def_property_readonly("total_frames_expected",
&Hdf5MasterFile::total_frames_expected)
.def_property_readonly("geometry", &Hdf5MasterFile::geometry)
.def_property_readonly("analog_samples",
&Hdf5MasterFile::analog_samples, R"(
Number of analog samples
Returns
----------
int | None
The number of analog samples in the file (or None if not enabled)
)")
.def_property_readonly("digital_samples",
&Hdf5MasterFile::digital_samples, R"(
Number of digital samples
Returns
----------
int | None
The number of digital samples in the file (or None if not enabled)
)")
.def_property_readonly("transceiver_samples",
&Hdf5MasterFile::transceiver_samples)
.def_property_readonly("number_of_rows",
&Hdf5MasterFile::number_of_rows)
.def_property_readonly("quad", &Hdf5MasterFile::quad)
.def_property_readonly("scan_parameters",
&Hdf5MasterFile::scan_parameters)
.def_property_readonly("roi", &Hdf5MasterFile::roi);
}

View File

@ -3,6 +3,10 @@
#include "raw_file.hpp"
#include "ctb_raw_file.hpp"
#include "raw_master_file.hpp"
#ifdef HDF5_FOUND
#include "hdf5_file.hpp"
#include "hdf5_master_file.hpp"
#endif
#include "var_cluster.hpp"
#include "pixel_map.hpp"
#include "pedestal.hpp"
@ -20,6 +24,10 @@ PYBIND11_MODULE(_aare, m) {
define_raw_file_io_bindings(m);
define_ctb_raw_file_io_bindings(m);
define_raw_master_file_bindings(m);
#ifdef HDF5_FOUND
define_hdf5_file_io_bindings(m);
define_hdf5_master_file_bindings(m);
#endif
define_var_cluster_finder_bindings(m);
define_pixel_map_bindings(m);
define_pedestal_bindings<double>(m, "Pedestal");