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

@@ -5,12 +5,12 @@
namespace aare {
/**
* @brief RAII File class for reading, and in the future potentially writing
* image files in various formats. Minimal generic interface. For specail fuctions
* plase use the RawFile or NumpyFile classes directly.
* Wraps FileInterface to abstract the underlying file format
* @note **frame_number** refers the the frame number sent by the detector while **frame_index**
* is the position of the frame in the file
* @brief RAII File class for reading, and in the future potentially writing
* image files in various formats. Minimal generic interface. For specail
* fuctions plase use the RawFile, NumpyFile or Hdf5File classes directly. Wraps
* FileInterface to abstract the underlying file format
* @note **frame_number** refers the the frame number sent by the detector while
* **frame_index** is the position of the frame in the file
*/
class File {
std::unique_ptr<FileInterface> file_impl;

View File

@@ -41,8 +41,9 @@ struct FileConfig {
/**
* @brief FileInterface class to define the interface for file operations
* @note parent class for NumpyFile and RawFile
* @note all functions are pure virtual and must be implemented by the derived classes
* @note parent class for NumpyFile, RawFile and Hdf5File
* @note all functions are pure virtual and must be implemented by the derived
* classes
*/
class FileInterface {
public:

96
include/aare/Hdf5File.hpp Normal file
View File

@@ -0,0 +1,96 @@
#pragma once
#include "aare/FileInterface.hpp"
#include "aare/Frame.hpp"
#include "aare/Hdf5MasterFile.hpp"
#include "aare/NDArray.hpp" //for pixel map
#include <optional>
namespace aare {
/**
* @brief Class to read .h5 files. The class will parse the master file
* to find the correct geometry for the frames.
* @note A more generic interface is available in the aare::File class.
* Consider using that unless you need hdf5 file specific functionality.
*/
class Hdf5File : public FileInterface {
Hdf5MasterFile m_master;
size_t m_current_frame{};
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:
/**
* @brief Hdf5File constructor
* @param fname path to the master file (.json)
* @param mode file mode (only "r" is supported at the moment)
*/
Hdf5File(const std::filesystem::path &fname, const std::string &mode = "r");
virtual ~Hdf5File() override;
Frame read_frame() override;
Frame read_frame(size_t frame_number) override;
std::vector<Frame> read_n(size_t n_frames) override;
void read_into(std::byte *image_buf) override;
void read_into(std::byte *image_buf, size_t n_frames) override;
// TODO! do we need to adapt the API?
void read_into(std::byte *image_buf, DetectorHeader *header);
void read_into(std::byte *image_buf, size_t n_frames,
DetectorHeader *header);
size_t frame_number(size_t frame_index) override;
size_t bytes_per_frame() override;
size_t pixels_per_frame() override;
size_t bytes_per_pixel() const;
void seek(size_t frame_index) override;
size_t tell() override;
size_t total_frames() const override;
size_t rows() const override;
size_t cols() const override;
size_t bitdepth() const override;
xy geometry();
size_t n_mod() const;
Hdf5MasterFile master() const;
DetectorType detector_type() const override;
private:
/**
* @brief read the frame at the given frame index into the image buffer
* @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 get the frame at the given frame index
* @param frame_number frame number to read
* @return Frame
*/
Frame get_frame(size_t frame_index);
/**
* @brief read the header of the file
* @param fname path to the data subfile
* @return DetectorHeader
*/
static DetectorHeader read_header(const std::filesystem::path &fname);
static const std::string metadata_group_name;
void open_file();
};
} // namespace aare

View File

@@ -0,0 +1,173 @@
#pragma once
#include "H5Cpp.h"
#include "aare/defs.hpp"
#include <filesystem>
#include <fmt/format.h>
#include <fstream>
#include <optional>
namespace fmt {
template <typename T> struct formatter<std::optional<T>> : formatter<T> {
template <typename FormatContext>
auto format(const std::optional<T> &opt, FormatContext &ctx) {
if (opt) {
return formatter<T>::format(*opt, ctx);
} else {
return format_to(ctx.out(), "nullopt");
}
}
};
} // namespace fmt
namespace aare {
/**
* @brief Implementation used in Hdf5MasterFile to parse the file name
*/
class Hdf5FileNameComponents {
bool m_old_scheme{false};
std::filesystem::path m_base_path{};
std::string m_base_name{};
std::string m_ext{};
int m_file_index{}; // TODO! is this measurement_index?
public:
Hdf5FileNameComponents(const std::filesystem::path &fname);
/// @brief Get the filename including path of the master file.
/// (i.e. what was passed in to the constructor))
std::filesystem::path master_fname() const;
/// @brief Get the filename including path of the data file.
/// @param mod_id module id run_d[module_id]_f0_0
/// @param file_id file id run_d0_f[file_id]_0
std::filesystem::path data_fname(size_t mod_id, size_t file_id) const;
const std::filesystem::path &base_path() const;
const std::string &base_name() const;
const std::string &ext() const;
int file_index() const;
void set_old_scheme(bool old_scheme);
};
/*
class ScanParameters {
bool m_enabled = false;
std::string m_dac;
int m_start = 0;
int m_stop = 0;
int m_step = 0;
// TODO! add settleTime, requires string to time conversion
public:
ScanParameters(const std::string &par);
ScanParameters() = default;
ScanParameters(const ScanParameters &) = default;
ScanParameters &operator=(const ScanParameters &) = default;
ScanParameters(ScanParameters &&) = default;
int start() const;
int stop() const;
int step() const;
const std::string &dac() const;
bool enabled() const;
void increment_stop();
};
struct ROI {
int64_t xmin{};
int64_t xmax{};
int64_t ymin{};
int64_t ymax{};
int64_t height() const { return ymax - ymin; }
int64_t width() const { return xmax - xmin; }
};
*/
/**
* @brief Class for parsing a master file either in our .json format or the old
* .Hdf5 format
*/
class Hdf5MasterFile {
Hdf5FileNameComponents m_fnc;
std::string m_version;
DetectorType m_type;
TimingMode m_timing_mode;
size_t m_image_size_in_bytes{};
size_t m_frames_in_file{};
size_t m_total_frames_expected{};
size_t m_pixels_y{};
size_t m_pixels_x{};
size_t m_bitdepth{};
xy m_geometry{};
size_t m_max_frames_per_file{};
// uint32_t m_adc_mask{}; // TODO! implement reading
FrameDiscardPolicy m_frame_discard_policy{};
size_t m_frame_padding{};
// TODO! should these be bool?
uint8_t m_analog_flag{};
uint8_t m_digital_flag{};
uint8_t m_transceiver_flag{};
// ScanParameters m_scan_parameters;
std::optional<size_t> m_analog_samples;
std::optional<size_t> m_digital_samples;
std::optional<size_t> m_transceiver_samples;
std::optional<size_t> m_number_of_rows;
std::optional<uint8_t> m_quad;
// std::optional<ROI> m_roi;
public:
Hdf5MasterFile(const std::filesystem::path &fpath);
std::filesystem::path master_fname() const;
std::filesystem::path data_fname(size_t mod_id, size_t file_id) const;
const std::string &version() const; //!< For example "7.2"
const DetectorType &detector_type() const;
const TimingMode &timing_mode() const;
size_t image_size_in_bytes() const;
size_t frames_in_file() const;
size_t pixels_y() const;
size_t pixels_x() const;
size_t max_frames_per_file() const;
size_t bitdepth() const;
size_t frame_padding() const;
const FrameDiscardPolicy &frame_discard_policy() const;
size_t total_frames_expected() const;
xy geometry() const;
std::optional<size_t> analog_samples() const;
std::optional<size_t> digital_samples() const;
std::optional<size_t> transceiver_samples() const;
std::optional<size_t> number_of_rows() const;
std::optional<uint8_t> quad() const;
// std::optional<ROI> roi() const;
// ScanParameters scan_parameters() const;
private:
static const std::string metadata_group_name;
void parse_acquisition_metadata(const std::filesystem::path &fpath);
template <typename T>
T h5_read_scalar_dataset(const H5::DataSet &dataset,
const H5::DataType &data_type);
template <typename T>
T h5_get_scalar_dataset(const H5::H5File &file,
const std::string &dataset_name);
};
template <>
std::string Hdf5MasterFile::h5_read_scalar_dataset<std::string>(
const H5::DataSet &dataset, const H5::DataType &data_type);
} // namespace aare

View File

@@ -225,8 +225,10 @@ template <> DetectorType StringTo(const std::string & /*name*/);
template <> std::string ToString(DetectorType arg);
template <> TimingMode StringTo(const std::string & /*mode*/);
template <> std::string ToString(TimingMode arg);
template <> FrameDiscardPolicy StringTo(const std::string & /*mode*/);
template <> std::string ToString(FrameDiscardPolicy arg);
using DataTypeVariants = std::variant<uint16_t, uint32_t>;