mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-14 08:17:13 +02:00
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
8354439605 | |||
11fa95b23c | |||
4976ec1651 |
2
.github/workflows/build_docs.yml
vendored
2
.github/workflows/build_docs.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_DOCS=ON
|
||||
cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_PYTHON_BINDINGS=ON -DAARE_DOCS=ON
|
||||
make -j 2
|
||||
make docs
|
||||
|
||||
|
@ -53,7 +53,6 @@ option(AARE_DOCS "Build documentation" OFF)
|
||||
option(AARE_VERBOSE "Verbose output" OFF)
|
||||
option(AARE_CUSTOM_ASSERT "Use custom assert" OFF)
|
||||
option(AARE_INSTALL_PYTHONEXT "Install the python extension in the install tree under CMAKE_INSTALL_PREFIX/aare/" OFF)
|
||||
option(AARE_HDF5 "Hdf5 File Format" OFF)
|
||||
option(AARE_ASAN "Enable AddressSanitizer" OFF)
|
||||
|
||||
# Configure which of the dependencies to use FetchContent for
|
||||
@ -82,7 +81,7 @@ if(AARE_VERBOSE)
|
||||
add_compile_definitions(AARE_VERBOSE)
|
||||
add_compile_definitions(AARE_LOG_LEVEL=aare::logDEBUG5)
|
||||
else()
|
||||
add_compile_definitions(AARE_LOG_LEVEL=aare::logINFOBLUE)
|
||||
add_compile_definitions(AARE_LOG_LEVEL=aare::logERROR)
|
||||
endif()
|
||||
|
||||
if(AARE_CUSTOM_ASSERT)
|
||||
@ -357,10 +356,6 @@ set(PUBLICHEADERS
|
||||
include/aare/CtbRawFile.hpp
|
||||
include/aare/ClusterVector.hpp
|
||||
include/aare/decode.hpp
|
||||
include/aare/type_traits.hpp
|
||||
include/aare/scan_parameters.hpp
|
||||
include/aare/to_string.hpp
|
||||
include/aare/string_utils.hpp
|
||||
include/aare/defs.hpp
|
||||
include/aare/Dtype.hpp
|
||||
include/aare/File.hpp
|
||||
@ -371,7 +366,6 @@ set(PUBLICHEADERS
|
||||
include/aare/GainMap.hpp
|
||||
include/aare/geo_helpers.hpp
|
||||
include/aare/JungfrauDataFile.hpp
|
||||
include/aare/logger.hpp
|
||||
include/aare/NDArray.hpp
|
||||
include/aare/NDView.hpp
|
||||
include/aare/NumpyFile.hpp
|
||||
@ -389,8 +383,6 @@ set(PUBLICHEADERS
|
||||
set(SourceFiles
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/CtbRawFile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/defs.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/string_utils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/decode.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp
|
||||
@ -410,22 +402,6 @@ set(SourceFiles
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/ifstream_helpers.cpp
|
||||
)
|
||||
|
||||
# HDF5
|
||||
if (AARE_HDF5)
|
||||
find_package(HDF5 1.10 COMPONENTS CXX REQUIRED)
|
||||
add_definitions(
|
||||
${HDF5_DEFINITIONS}
|
||||
)
|
||||
list (APPEND PUBLICHEADERS
|
||||
include/aare/Hdf5File.hpp
|
||||
include/aare/Hdf5MasterFile.hpp
|
||||
)
|
||||
list (APPEND SourceFiles
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Hdf5File.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Hdf5MasterFile.cpp
|
||||
)
|
||||
endif (AARE_HDF5)
|
||||
|
||||
add_library(aare_core STATIC ${SourceFiles})
|
||||
target_include_directories(aare_core PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
@ -448,16 +424,6 @@ target_link_libraries(
|
||||
|
||||
)
|
||||
|
||||
if (AARE_HDF5 AND HDF5_FOUND)
|
||||
add_definitions(-DHDF5_FOUND)
|
||||
target_link_libraries(aare_core PUBLIC
|
||||
${HDF5_LIBRARIES}
|
||||
)
|
||||
target_include_directories(aare_core PUBLIC
|
||||
${HDF5_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(aare_core PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
PUBLIC_HEADER "${PUBLICHEADERS}"
|
||||
@ -471,8 +437,6 @@ if(AARE_TESTS)
|
||||
set(TestSources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/algorithm.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/defs.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/scan_parameters.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/decode.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp
|
||||
@ -495,18 +459,11 @@ if(AARE_TESTS)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.test.cpp
|
||||
|
||||
)
|
||||
if(HDF5_FOUND)
|
||||
list (APPEND TestSources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Hdf5MasterFile.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Hdf5File.test.cpp
|
||||
)
|
||||
endif()
|
||||
target_sources(tests PRIVATE ${TestSources} )
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
###------------------------------------------------------------------------------------------
|
||||
###------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -14,6 +14,7 @@ set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR})
|
||||
file(GLOB SPHINX_SOURCE_FILES CONFIGURE_DEPENDS "src/*.rst")
|
||||
|
||||
|
||||
|
||||
foreach(filename ${SPHINX_SOURCE_FILES})
|
||||
get_filename_component(fname ${filename} NAME)
|
||||
message(STATUS "Copying ${filename} to ${SPHINX_BUILD}/src/${fname}")
|
||||
|
@ -4,4 +4,5 @@ ClusterFile
|
||||
.. doxygenclass:: aare::ClusterFile
|
||||
:members:
|
||||
:undoc-members:
|
||||
:private-members:
|
||||
:private-members:
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
Hdf5File
|
||||
===============
|
||||
|
||||
|
||||
.. doxygenclass:: aare::Hdf5File
|
||||
:members:
|
||||
:undoc-members:
|
||||
:private-members:
|
@ -1,14 +0,0 @@
|
||||
Hdf5MasterFile
|
||||
===============
|
||||
|
||||
|
||||
.. doxygenclass:: aare::Hdf5MasterFile
|
||||
:members:
|
||||
:undoc-members:
|
||||
:private-members:
|
||||
|
||||
|
||||
.. doxygenclass:: aare::Hdf5FileNameComponents
|
||||
:members:
|
||||
:undoc-members:
|
||||
:private-members:
|
@ -31,8 +31,6 @@ AARE
|
||||
pyJungfrauDataFile
|
||||
pyRawFile
|
||||
pyRawMasterFile
|
||||
pyHdf5File
|
||||
pyHdf5MasterFile
|
||||
pyVarClusterFinder
|
||||
|
||||
pyFit
|
||||
@ -57,8 +55,6 @@ AARE
|
||||
RawFile
|
||||
RawSubFile
|
||||
RawMasterFile
|
||||
Hdf5File
|
||||
Hdf5MasterFile
|
||||
VarClusterFinder
|
||||
|
||||
|
||||
|
@ -2,9 +2,24 @@
|
||||
ClusterFile
|
||||
============
|
||||
|
||||
|
||||
The :class:`ClusterFile` class is the main interface to read and write clusters in aare. Unfortunately the
|
||||
old file format does not include metadata like the cluster size and the data type. This means that the
|
||||
user has to know this information from other sources. Specifying the wrong cluster size or data type
|
||||
will lead to garbage data being read.
|
||||
|
||||
.. py:currentmodule:: aare
|
||||
|
||||
.. autoclass:: ClusterFile
|
||||
:members:
|
||||
:undoc-members:
|
||||
:inherited-members:
|
||||
|
||||
|
||||
Below is the API of the ClusterFile_Cluster3x3i but all variants share the same API.
|
||||
|
||||
.. autoclass:: aare._aare.ClusterFile_Cluster3x3i
|
||||
:special-members: __init__
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
@ -2,8 +2,10 @@ ClusterVector
|
||||
================
|
||||
|
||||
The ClusterVector, holds clusters from the ClusterFinder. Since it is templated
|
||||
in C++ we use a suffix indicating the data type in python. The suffix is
|
||||
``_i`` for integer, ``_f`` for float, and ``_d`` for double.
|
||||
in C++ we use a suffix indicating the type of cluster it holds. The suffix follows
|
||||
the same pattern as for ClusterFile i.e. ``ClusterVector_Cluster3x3i``
|
||||
for a vector holding 3x3 integer clusters.
|
||||
|
||||
|
||||
At the moment the functionality from python is limited and it is not supported
|
||||
to push_back clusters to the vector. The intended use case is to pass it to
|
||||
@ -26,7 +28,8 @@ C++ functions that support the ClusterVector or to view it as a numpy array.
|
||||
|
||||
.. py:currentmodule:: aare
|
||||
|
||||
.. autoclass:: ClusterVector_i
|
||||
.. autoclass:: aare._aare.ClusterVector_Cluster3x3i
|
||||
:special-members: __init__
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
@ -1,10 +0,0 @@
|
||||
Hdf5File
|
||||
===================
|
||||
|
||||
.. py:currentmodule:: aare
|
||||
|
||||
.. autoclass:: Hdf5File
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
:inherited-members:
|
@ -1,10 +0,0 @@
|
||||
Hdf5MasterFile
|
||||
===================
|
||||
|
||||
.. py:currentmodule:: aare
|
||||
|
||||
.. autoclass:: Hdf5MasterFile
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
:inherited-members:
|
@ -5,9 +5,12 @@ dependencies:
|
||||
- anaconda-client
|
||||
- conda-build
|
||||
- doxygen
|
||||
- sphinx=7.1.2
|
||||
- sphinx
|
||||
- breathe
|
||||
- sphinx_rtd_theme
|
||||
- furo
|
||||
- zeromq
|
||||
- pybind11
|
||||
- numpy
|
||||
- matplotlib
|
||||
|
||||
|
@ -7,7 +7,7 @@ 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, NumpyFile or Hdf5File classes directly. Wraps
|
||||
* 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
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "aare/Dtype.hpp"
|
||||
#include "aare/Frame.hpp"
|
||||
#include "aare/to_string.hpp"
|
||||
#include "aare/defs.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
@ -46,7 +46,7 @@ struct FileConfig {
|
||||
|
||||
/**
|
||||
* @brief FileInterface class to define the interface for file operations
|
||||
* @note parent class for NumpyFile, RawFile and Hdf5File
|
||||
* @note parent class for NumpyFile and RawFile
|
||||
* @note all functions are pure virtual and must be implemented by the derived
|
||||
* classes
|
||||
*/
|
||||
|
@ -1,211 +0,0 @@
|
||||
#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 {
|
||||
|
||||
class 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;
|
||||
std::vector<hsize_t> dims;
|
||||
std::vector<hsize_t> count;
|
||||
std::vector<hsize_t> offset;
|
||||
|
||||
public:
|
||||
H5Handles(const std::string &fname, const std::string &dname)
|
||||
: file_name(fname), dataset_name(dname), file(fname, H5F_ACC_RDONLY),
|
||||
dataset(file.openDataSet(dname)), dataspace(dataset.getSpace()),
|
||||
datatype(dataset.getDataType()) {
|
||||
intialize_dimensions();
|
||||
initialize_memspace();
|
||||
}
|
||||
|
||||
std::vector<hsize_t> get_dims() const { return dims; }
|
||||
|
||||
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_data_into(size_t frame_index, std::byte *frame_buffer,
|
||||
size_t n_frames = 1) {
|
||||
seek(frame_index);
|
||||
count[0] = static_cast<hsize_t>(n_frames);
|
||||
// std::cout << "offset:" << ToString(offset) << " count:" <<
|
||||
// ToString(count) << std::endl;
|
||||
dataspace.selectHyperslab(H5S_SELECT_SET, count.data(), offset.data());
|
||||
dataset.read(frame_buffer, datatype, *memspace, dataspace);
|
||||
}
|
||||
|
||||
void get_header_into(size_t frame_index, int part_index,
|
||||
std::byte *header_buffer) {
|
||||
seek(frame_index);
|
||||
offset[1] = static_cast<hsize_t>(part_index);
|
||||
// std::cout << "offset:" << ToString(offset) << " count:" <<
|
||||
// ToString(count) << std::endl;
|
||||
dataspace.selectHyperslab(H5S_SELECT_SET, count.data(), offset.data());
|
||||
dataset.read(header_buffer, datatype, *memspace, dataspace);
|
||||
}
|
||||
|
||||
private:
|
||||
void intialize_dimensions() {
|
||||
int rank = dataspace.getSimpleExtentNdims();
|
||||
dims.resize(rank);
|
||||
dataspace.getSimpleExtentDims(dims.data(), nullptr);
|
||||
}
|
||||
|
||||
void initialize_memspace() {
|
||||
int rank = dataspace.getSimpleExtentNdims();
|
||||
count.clear();
|
||||
offset.clear();
|
||||
|
||||
// header datasets or header virtual datasets
|
||||
if (rank == 1 || rank == 2) {
|
||||
count = std::vector<hsize_t>(rank, 1); // slice 1 value
|
||||
offset = std::vector<hsize_t>(rank, 0);
|
||||
memspace = std::make_unique<H5::DataSpace>(H5S_SCALAR);
|
||||
} else if (rank >= 3) {
|
||||
// data dataset (frame x height x width)
|
||||
count = {1, dims[1], dims[2]};
|
||||
offset = {0, 0, 0};
|
||||
hsize_t dims_image[2] = {dims[1], dims[2]};
|
||||
memspace = std::make_unique<H5::DataSpace>(2, dims_image);
|
||||
} else {
|
||||
throw std::runtime_error(
|
||||
LOCATION + "Invalid rank for dataset: " + std::to_string(rank));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Fn>
|
||||
void read_hdf5_header_fields(DetectorHeader *header, Fn &&fn_read_field) {
|
||||
fn_read_field(0, reinterpret_cast<std::byte *>(&(header->frameNumber)));
|
||||
fn_read_field(1, reinterpret_cast<std::byte *>(&(header->expLength)));
|
||||
fn_read_field(2, reinterpret_cast<std::byte *>(&(header->packetNumber)));
|
||||
fn_read_field(3, reinterpret_cast<std::byte *>(&(header->bunchId)));
|
||||
fn_read_field(4, reinterpret_cast<std::byte *>(&(header->timestamp)));
|
||||
fn_read_field(5, reinterpret_cast<std::byte *>(&(header->modId)));
|
||||
fn_read_field(6, reinterpret_cast<std::byte *>(&(header->row)));
|
||||
fn_read_field(7, reinterpret_cast<std::byte *>(&(header->column)));
|
||||
fn_read_field(8, reinterpret_cast<std::byte *>(&(header->reserved)));
|
||||
fn_read_field(9, reinterpret_cast<std::byte *>(&(header->debug)));
|
||||
fn_read_field(10, reinterpret_cast<std::byte *>(&(header->roundRNumber)));
|
||||
fn_read_field(11, reinterpret_cast<std::byte *>(&(header->detType)));
|
||||
fn_read_field(12, reinterpret_cast<std::byte *>(&(header->version)));
|
||||
fn_read_field(13, reinterpret_cast<std::byte *>(&(header->packetMask)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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{};
|
||||
|
||||
static const std::string metadata_group_name;
|
||||
static const std::vector<std::string> header_dataset_names;
|
||||
std::unique_ptr<H5Handles> m_data_dataset{nullptr};
|
||||
std::vector<std::unique_ptr<H5Handles>> m_header_datasets{};
|
||||
|
||||
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_modules() const;
|
||||
Hdf5MasterFile master() const;
|
||||
|
||||
DetectorType detector_type() const override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @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 frame at the given frame index into the image buffer
|
||||
* @param frame_number frame number to read
|
||||
* @param n_frames number of frames to read (default is 1)
|
||||
* @param image_buf buffer to store the frame
|
||||
*/
|
||||
void get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||
size_t n_frames = 1, DetectorHeader *header = nullptr);
|
||||
|
||||
/**
|
||||
* @brief read the frame at the given frame index into the image buffer
|
||||
* @param frame_index frame number to read
|
||||
* @param n_frames number of frames to read (default is 1)
|
||||
* @param frame_buffer buffer to store the frame
|
||||
*/
|
||||
void get_data_into(size_t frame_index, std::byte *frame_buffer,
|
||||
size_t n_frames = 1);
|
||||
|
||||
/**
|
||||
* @brief read the header at the given frame index into the header buffer
|
||||
* @param frame_index frame number to read
|
||||
* @param part_index part index to read (for virtual datasets)
|
||||
* @param header buffer to store the header
|
||||
*/
|
||||
void get_header_into(size_t frame_index, int part_index,
|
||||
DetectorHeader *header);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
void open_data_file();
|
||||
void open_header_files();
|
||||
};
|
||||
|
||||
} // namespace aare
|
@ -1,135 +0,0 @@
|
||||
#pragma once
|
||||
#include "aare/defs.hpp"
|
||||
#include "aare/scan_parameters.hpp"
|
||||
|
||||
#include "H5Cpp.h"
|
||||
#include <filesystem>
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
|
||||
namespace aare {
|
||||
|
||||
using ns = std::chrono::nanoseconds;
|
||||
|
||||
/**
|
||||
* @brief Class for parsing a master file either in our .json format or the old
|
||||
* .Hdf5 format
|
||||
*/
|
||||
class Hdf5MasterFile {
|
||||
std::filesystem::path m_file_name{};
|
||||
std::string m_version;
|
||||
DetectorType m_type;
|
||||
TimingMode m_timing_mode;
|
||||
xy m_geometry{};
|
||||
int m_image_size_in_bytes{};
|
||||
int m_pixels_y{};
|
||||
int m_pixels_x{};
|
||||
int m_max_frames_per_file{};
|
||||
FrameDiscardPolicy m_frame_discard_policy{};
|
||||
int m_frame_padding{};
|
||||
std::optional<ScanParameters> m_scan_parameters{};
|
||||
size_t m_total_frames_expected{};
|
||||
std::optional<ns> m_exptime{};
|
||||
std::optional<ns> m_period{};
|
||||
std::optional<BurstMode> m_burst_mode{};
|
||||
std::optional<int> m_number_of_udp_interfaces{};
|
||||
int m_bitdepth{};
|
||||
std::optional<bool> m_ten_giga{};
|
||||
std::optional<int> m_threshold_energy{};
|
||||
std::optional<std::vector<int>> m_threshold_energy_all{};
|
||||
std::optional<ns> m_subexptime{};
|
||||
std::optional<ns> m_subperiod{};
|
||||
std::optional<bool> m_quad{};
|
||||
std::optional<int> m_number_of_rows{};
|
||||
std::optional<std::vector<size_t>> m_rate_corrections{};
|
||||
std::optional<uint32_t> m_adc_mask{};
|
||||
bool m_analog_flag{};
|
||||
std::optional<int> m_analog_samples{};
|
||||
bool m_digital_flag{};
|
||||
std::optional<int> m_digital_samples{};
|
||||
std::optional<int> m_dbit_offset{};
|
||||
std::optional<size_t> m_dbit_list{};
|
||||
std::optional<int> m_transceiver_mask{};
|
||||
bool m_transceiver_flag{};
|
||||
std::optional<int> m_transceiver_samples{};
|
||||
// g1 roi - will not be implemented?
|
||||
std::optional<ROI> m_roi{};
|
||||
std::optional<int> m_counter_mask{};
|
||||
std::optional<std::vector<ns>> m_exptime_array{};
|
||||
std::optional<std::vector<ns>> m_gate_delay_array{};
|
||||
std::optional<int> m_gates{};
|
||||
std::optional<std::map<std::string, std::string>>
|
||||
m_additional_json_header{};
|
||||
size_t m_frames_in_file{};
|
||||
|
||||
// TODO! should these be bool?
|
||||
|
||||
public:
|
||||
Hdf5MasterFile(const std::filesystem::path &fpath);
|
||||
|
||||
std::filesystem::path file_name() const;
|
||||
|
||||
const std::string &version() const; //!< For example "7.2"
|
||||
const DetectorType &detector_type() const;
|
||||
const TimingMode &timing_mode() const;
|
||||
xy geometry() const;
|
||||
int image_size_in_bytes() const;
|
||||
int pixels_y() const;
|
||||
int pixels_x() const;
|
||||
int max_frames_per_file() const;
|
||||
const FrameDiscardPolicy &frame_discard_policy() const;
|
||||
int frame_padding() const;
|
||||
std::optional<ScanParameters> scan_parameters() const;
|
||||
size_t total_frames_expected() const;
|
||||
std::optional<ns> exptime() const;
|
||||
std::optional<ns> period() const;
|
||||
std::optional<BurstMode> burst_mode() const;
|
||||
std::optional<int> number_of_udp_interfaces() const;
|
||||
int bitdepth() const;
|
||||
std::optional<bool> ten_giga() const;
|
||||
std::optional<int> threshold_energy() const;
|
||||
std::optional<std::vector<int>> threshold_energy_all() const;
|
||||
std::optional<ns> subexptime() const;
|
||||
std::optional<ns> subperiod() const;
|
||||
std::optional<bool> quad() const;
|
||||
std::optional<int> number_of_rows() const;
|
||||
std::optional<std::vector<size_t>> rate_corrections() const;
|
||||
std::optional<uint32_t> adc_mask() const;
|
||||
bool analog_flag() const;
|
||||
std::optional<int> analog_samples() const;
|
||||
bool digital_flag() const;
|
||||
std::optional<int> digital_samples() const;
|
||||
std::optional<int> dbit_offset() const;
|
||||
std::optional<size_t> dbit_list() const;
|
||||
std::optional<int> transceiver_mask() const;
|
||||
bool transceiver_flag() const;
|
||||
std::optional<int> transceiver_samples() const;
|
||||
// g1 roi - will not be implemented?
|
||||
std::optional<ROI> roi() const;
|
||||
std::optional<int> counter_mask() const;
|
||||
std::optional<std::vector<ns>> exptime_array() const;
|
||||
std::optional<std::vector<ns>> gate_delay_array() const;
|
||||
std::optional<int> gates() const;
|
||||
std::optional<std::map<std::string, std::string>>
|
||||
additional_json_header() const;
|
||||
size_t frames_in_file() const;
|
||||
size_t n_modules() 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
|
@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
#include "aare/defs.hpp"
|
||||
#include "aare/scan_parameters.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
@ -41,6 +39,28 @@ class RawFileNameComponents {
|
||||
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();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class for parsing a master file either in our .json format or the old
|
||||
* .raw format
|
||||
|
@ -1,15 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "aare/Dtype.hpp"
|
||||
#include "aare/type_traits.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
@ -250,12 +246,17 @@ enum class DetectorType {
|
||||
|
||||
enum class TimingMode { Auto, Trigger };
|
||||
enum class FrameDiscardPolicy { NoDiscard, Discard, DiscardPartial };
|
||||
enum class BurstMode {
|
||||
Burst_Interal,
|
||||
Burst_External,
|
||||
Continuous_Internal,
|
||||
Continuous_External
|
||||
};
|
||||
|
||||
template <class T> T StringTo(const std::string &arg) { return T(arg); }
|
||||
|
||||
template <class T> std::string ToString(T arg) { return T(arg); }
|
||||
|
||||
template <> DetectorType StringTo(const std::string & /*name*/);
|
||||
template <> std::string ToString(DetectorType arg);
|
||||
|
||||
template <> TimingMode StringTo(const std::string & /*mode*/);
|
||||
|
||||
template <> FrameDiscardPolicy StringTo(const std::string & /*mode*/);
|
||||
|
||||
using DataTypeVariants = std::variant<uint16_t, uint32_t>;
|
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace aare {
|
||||
|
||||
class ScanParameters {
|
||||
bool m_enabled = false;
|
||||
std::string m_dac;
|
||||
int m_start = 0;
|
||||
int m_stop = 0;
|
||||
int m_step = 0;
|
||||
// ns m_dac_settle_time{0};
|
||||
// TODO! add settleTime, requires string to time conversion
|
||||
|
||||
public:
|
||||
// "[enabled\ndac dac 4\nstart 500\nstop 2200\nstep 5\nsettleTime 100us\n]"
|
||||
// TODO: use StringTo<ScanParameters> and move this to to_string
|
||||
// add ways of setting the members of the class
|
||||
|
||||
ScanParameters(const std::string &par) {
|
||||
std::istringstream iss(par.substr(1, par.size() - 2));
|
||||
std::string line;
|
||||
while (std::getline(iss, line)) {
|
||||
if (line == "enabled") {
|
||||
m_enabled = true;
|
||||
} else if (line.find("dac") != std::string::npos) {
|
||||
m_dac = line.substr(4);
|
||||
} else if (line.find("start") != std::string::npos) {
|
||||
m_start = std::stoi(line.substr(6));
|
||||
} else if (line.find("stop") != std::string::npos) {
|
||||
m_stop = std::stoi(line.substr(5));
|
||||
} else if (line.find("step") != std::string::npos) {
|
||||
m_step = std::stoi(line.substr(5));
|
||||
}
|
||||
}
|
||||
};
|
||||
ScanParameters() = default;
|
||||
ScanParameters(const ScanParameters &) = default;
|
||||
ScanParameters &operator=(const ScanParameters &) = default;
|
||||
ScanParameters(ScanParameters &&) = default;
|
||||
int start() const { return m_start; };
|
||||
int stop() const { return m_stop; };
|
||||
int step() const { return m_step; };
|
||||
const std::string &dac() const { return m_dac; };
|
||||
bool enabled() const { return m_enabled; };
|
||||
void increment_stop() { m_stop += 1; };
|
||||
};
|
||||
|
||||
} // namespace aare
|
@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace aare {
|
||||
|
||||
std::string RemoveUnit(std::string &str);
|
||||
|
||||
void TrimWhiteSpaces(std::string &s);
|
||||
|
||||
} // namespace aare
|
@ -1,288 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "aare/defs.hpp"
|
||||
#include "aare/scan_parameters.hpp"
|
||||
#include "aare/string_utils.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
|
||||
|
||||
namespace aare {
|
||||
|
||||
// generic
|
||||
template <class T, typename = std::enable_if_t<!is_duration<T>::value>>
|
||||
std::string ToString(T arg) {
|
||||
return T(arg);
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
std::enable_if_t<!is_duration<T>::value && !is_container<T>::value,
|
||||
int> = 0>
|
||||
T StringTo(const std::string &arg) {
|
||||
return T(arg);
|
||||
}
|
||||
|
||||
// time
|
||||
|
||||
/** Convert std::chrono::duration with specified output unit */
|
||||
template <typename T, typename Rep = double>
|
||||
typename std::enable_if<is_duration<T>::value, std::string>::type
|
||||
ToString(T t, const std::string &unit) {
|
||||
using std::chrono::duration;
|
||||
using std::chrono::duration_cast;
|
||||
std::ostringstream os;
|
||||
if (unit == "ns")
|
||||
os << duration_cast<duration<Rep, std::nano>>(t).count() << unit;
|
||||
else if (unit == "us")
|
||||
os << duration_cast<duration<Rep, std::micro>>(t).count() << unit;
|
||||
else if (unit == "ms")
|
||||
os << duration_cast<duration<Rep, std::milli>>(t).count() << unit;
|
||||
else if (unit == "s")
|
||||
os << duration_cast<duration<Rep>>(t).count() << unit;
|
||||
else
|
||||
throw std::runtime_error("Unknown unit: " + unit);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/** Convert std::chrono::duration automatically selecting the unit */
|
||||
template <typename From>
|
||||
typename std::enable_if<is_duration<From>::value, std::string>::type
|
||||
ToString(From t) {
|
||||
|
||||
using std::chrono::abs;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::microseconds;
|
||||
using std::chrono::milliseconds;
|
||||
using std::chrono::nanoseconds;
|
||||
auto tns = duration_cast<nanoseconds>(t);
|
||||
if (abs(tns) < microseconds(1)) {
|
||||
return ToString(tns, "ns");
|
||||
} else if (abs(tns) < milliseconds(1)) {
|
||||
return ToString(tns, "us");
|
||||
} else if (abs(tns) < milliseconds(99)) {
|
||||
return ToString(tns, "ms");
|
||||
} else {
|
||||
return ToString(tns, "s");
|
||||
}
|
||||
}
|
||||
template <class Rep, class Period>
|
||||
std::ostream &operator<<(std::ostream &os,
|
||||
const std::chrono::duration<Rep, Period> &d) {
|
||||
return os << ToString(d);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T StringTo(const std::string &t, const std::string &unit) {
|
||||
double tval{0};
|
||||
try {
|
||||
tval = std::stod(t);
|
||||
} catch (const std::invalid_argument &e) {
|
||||
throw std::invalid_argument("[ERROR] Could not convert string to time");
|
||||
}
|
||||
|
||||
using std::chrono::duration;
|
||||
using std::chrono::duration_cast;
|
||||
if (unit == "ns") {
|
||||
return duration_cast<T>(duration<double, std::nano>(tval));
|
||||
} else if (unit == "us") {
|
||||
return duration_cast<T>(duration<double, std::micro>(tval));
|
||||
} else if (unit == "ms") {
|
||||
return duration_cast<T>(duration<double, std::milli>(tval));
|
||||
} else if (unit == "s" || unit.empty()) {
|
||||
return duration_cast<T>(std::chrono::duration<double>(tval));
|
||||
} else {
|
||||
throw std::invalid_argument("[ERROR] Invalid unit in conversion from "
|
||||
"string to std::chrono::duration");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<is_duration<T>::value, int> = 0>
|
||||
T StringTo(const std::string &t) {
|
||||
std::string tmp{t};
|
||||
auto unit = RemoveUnit(tmp);
|
||||
return StringTo<T>(tmp, unit);
|
||||
}
|
||||
|
||||
template <> inline bool StringTo(const std::string &s) {
|
||||
int i = std::stoi(s, nullptr, 10);
|
||||
switch (i) {
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
return true;
|
||||
default:
|
||||
throw std::runtime_error("Unknown boolean. Expecting be 0 or 1.");
|
||||
}
|
||||
}
|
||||
|
||||
template <> inline uint8_t StringTo(const std::string &s) {
|
||||
int base = s.find("0x") != std::string::npos ? 16 : 10;
|
||||
int value = std::stoi(s, nullptr, base);
|
||||
if (value < std::numeric_limits<uint8_t>::min() ||
|
||||
value > std::numeric_limits<uint8_t>::max()) {
|
||||
throw std::runtime_error("Cannot scan uint8_t from string '" + s +
|
||||
"'. Value must be in range 0 - 255.");
|
||||
}
|
||||
return static_cast<uint8_t>(value);
|
||||
}
|
||||
|
||||
template <> inline uint16_t StringTo(const std::string &s) {
|
||||
int base = s.find("0x") != std::string::npos ? 16 : 10;
|
||||
int value = std::stoi(s, nullptr, base);
|
||||
if (value < std::numeric_limits<uint16_t>::min() ||
|
||||
value > std::numeric_limits<uint16_t>::max()) {
|
||||
throw std::runtime_error("Cannot scan uint16_t from string '" + s +
|
||||
"'. Value must be in range 0 - 65535.");
|
||||
}
|
||||
return static_cast<uint16_t>(value);
|
||||
}
|
||||
|
||||
template <> inline uint32_t StringTo(const std::string &s) {
|
||||
int base = s.find("0x") != std::string::npos ? 16 : 10;
|
||||
return std::stoul(s, nullptr, base);
|
||||
}
|
||||
|
||||
template <> inline uint64_t StringTo(const std::string &s) {
|
||||
int base = s.find("0x") != std::string::npos ? 16 : 10;
|
||||
return std::stoull(s, nullptr, base);
|
||||
}
|
||||
|
||||
template <> inline int StringTo(const std::string &s) {
|
||||
int base = s.find("0x") != std::string::npos ? 16 : 10;
|
||||
return std::stoi(s, nullptr, base);
|
||||
}
|
||||
|
||||
/*template <> inline size_t StringTo(const std::string &s) {
|
||||
int base = s.find("0x") != std::string::npos ? 16 : 10;
|
||||
return std::stoull(s, nullptr, base);
|
||||
}*/
|
||||
|
||||
// vector
|
||||
template <typename T> std::string ToString(const std::vector<T> &vec) {
|
||||
std::ostringstream oss;
|
||||
oss << "[";
|
||||
for (size_t i = 0; i < vec.size(); ++i) {
|
||||
oss << vec[i];
|
||||
if (i != vec.size() - 1)
|
||||
oss << ", ";
|
||||
}
|
||||
oss << "]";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
|
||||
return os << ToString(v);
|
||||
}
|
||||
|
||||
template <typename Container,
|
||||
std::enable_if_t<is_container<Container>::value &&
|
||||
!is_std_string_v<Container> /*&&
|
||||
!is_map_v<Container>*/
|
||||
,
|
||||
int> = 0>
|
||||
Container StringTo(const std::string &s) {
|
||||
using Value = typename Container::value_type;
|
||||
|
||||
// strip outer brackets
|
||||
std::string str = s;
|
||||
str.erase(
|
||||
std::remove_if(str.begin(), str.end(),
|
||||
[](unsigned char c) { return c == '[' || c == ']'; }),
|
||||
str.end());
|
||||
|
||||
std::stringstream ss(str);
|
||||
std::string item;
|
||||
Container result;
|
||||
|
||||
while (std::getline(ss, item, ',')) {
|
||||
TrimWhiteSpaces(item);
|
||||
if (!item.empty()) {
|
||||
result.push_back(StringTo<Value>(item));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// map
|
||||
template <typename KeyType, typename ValueType>
|
||||
std::string ToString(const std::map<KeyType, ValueType> &m) {
|
||||
std::ostringstream os;
|
||||
os << '{';
|
||||
if (!m.empty()) {
|
||||
auto it = m.cbegin();
|
||||
os << ToString(it->first) << ": " << ToString(it->second);
|
||||
it++;
|
||||
while (it != m.cend()) {
|
||||
os << ", " << ToString(it->first) << ": " << ToString(it->second);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
os << '}';
|
||||
return os.str();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::map<std::string, std::string> StringTo(const std::string &s) {
|
||||
std::map<std::string, std::string> result;
|
||||
std::string str = s;
|
||||
|
||||
// Remove outer braces if present
|
||||
if (!str.empty() && str.front() == '{' && str.back() == '}') {
|
||||
str = str.substr(1, str.size() - 2);
|
||||
}
|
||||
|
||||
std::stringstream ss(str);
|
||||
std::string item;
|
||||
|
||||
while (std::getline(ss, item, ',')) {
|
||||
auto colon_pos = item.find(':');
|
||||
if (colon_pos == std::string::npos)
|
||||
throw std::runtime_error("Missing ':' in item: " + item);
|
||||
|
||||
std::string key = item.substr(0, colon_pos);
|
||||
std::string value = item.substr(colon_pos + 1);
|
||||
|
||||
TrimWhiteSpaces(key);
|
||||
TrimWhiteSpaces(value);
|
||||
|
||||
result[key] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// optional
|
||||
template <class T> std::string ToString(const std::optional<T> &opt) {
|
||||
return opt ? ToString(*opt) : "nullopt";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
|
||||
if (opt)
|
||||
os << *opt;
|
||||
else
|
||||
os << "nullopt";
|
||||
return os;
|
||||
}
|
||||
|
||||
// enums
|
||||
template <> std::string ToString(DetectorType arg);
|
||||
template <> DetectorType StringTo(const std::string & /*name*/);
|
||||
|
||||
template <> std::string ToString(TimingMode arg);
|
||||
template <> TimingMode StringTo(const std::string & /*mode*/);
|
||||
|
||||
template <> std::string ToString(FrameDiscardPolicy arg);
|
||||
template <> FrameDiscardPolicy StringTo(const std::string & /*mode*/);
|
||||
|
||||
template <> std::string ToString(BurstMode arg);
|
||||
template <> BurstMode StringTo(const std::string & /*mode*/);
|
||||
|
||||
template <> std::string ToString(ROI arg);
|
||||
std::ostream &operator<<(std::ostream &os, const ROI &roi);
|
||||
|
||||
template <> std::string ToString(ScanParameters arg);
|
||||
std::ostream &operator<<(std::ostream &os, const ScanParameters &r);
|
||||
|
||||
} // namespace aare
|
@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace aare {
|
||||
|
||||
/**
|
||||
* Type trait to check if a template parameter is a std::chrono::duration
|
||||
*/
|
||||
|
||||
template <typename T, typename _ = void>
|
||||
struct is_duration : std::false_type {};
|
||||
|
||||
template <typename... Ts> struct is_duration_helper {};
|
||||
|
||||
template <typename T>
|
||||
struct is_duration<T,
|
||||
typename std::conditional<
|
||||
false,
|
||||
is_duration_helper<typename T::rep, typename T::period,
|
||||
decltype(std::declval<T>().min()),
|
||||
decltype(std::declval<T>().max()),
|
||||
decltype(std::declval<T>().zero())>,
|
||||
void>::type> : public std::true_type {};
|
||||
|
||||
/**
|
||||
* Type trait to evaluate if template parameter is
|
||||
* complying with a standard container
|
||||
*/
|
||||
template <typename T, typename _ = void>
|
||||
struct is_container : std::false_type {};
|
||||
|
||||
template <typename... Ts> struct is_container_helper {};
|
||||
|
||||
template <typename T>
|
||||
struct is_container<
|
||||
T, typename std::conditional<
|
||||
false,
|
||||
is_container_helper<
|
||||
typename std::remove_reference<T>::type::value_type,
|
||||
typename std::remove_reference<T>::type::size_type,
|
||||
typename std::remove_reference<T>::type::iterator,
|
||||
typename std::remove_reference<T>::type::const_iterator,
|
||||
decltype(std::declval<T>().size()),
|
||||
decltype(std::declval<T>().begin()),
|
||||
decltype(std::declval<T>().end()),
|
||||
decltype(std::declval<T>().cbegin()),
|
||||
decltype(std::declval<T>().cend()),
|
||||
decltype(std::declval<T>().empty())>,
|
||||
void>::type> : public std::true_type {};
|
||||
|
||||
/**
|
||||
* Type trait to evaluate if template parameter is
|
||||
* complying with a std::string
|
||||
*/
|
||||
template <typename T>
|
||||
inline constexpr bool is_std_string_v =
|
||||
std::is_same_v<std::decay_t<T>, std::string>;
|
||||
|
||||
/**
|
||||
* Type trait to evaluate if template parameter is
|
||||
* complying with std::map
|
||||
*/
|
||||
template <typename T> struct is_map : std::false_type {};
|
||||
|
||||
template <typename K, typename V, typename... Args>
|
||||
struct is_map<std::map<K, V, Args...>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_map_v = is_map<std::decay_t<T>>::value;
|
||||
|
||||
} // namespace aare
|
@ -1,16 +1,8 @@
|
||||
|
||||
# from ._aare import ClusterFinder_Cluster3x3i, ClusterFinder_Cluster2x2i, ClusterFinderMT_Cluster3x3i, ClusterFinderMT_Cluster2x2i, ClusterCollector_Cluster3x3i, ClusterCollector_Cluster2x2i
|
||||
|
||||
|
||||
# from ._aare import ClusterFileSink_Cluster3x3i, ClusterFileSink_Cluster2x2i
|
||||
|
||||
from . import _aare
|
||||
import numpy as np
|
||||
|
||||
_supported_cluster_sizes = [(2,2), (3,3), (5,5), (7,7), (9,9),]
|
||||
|
||||
# def _get_class()
|
||||
|
||||
def _type_to_char(dtype):
|
||||
if dtype == np.int32:
|
||||
return 'i'
|
||||
@ -74,11 +66,22 @@ def ClusterFileSink(clusterfindermt, cluster_file, dtype=np.int32):
|
||||
return cls(clusterfindermt, cluster_file)
|
||||
|
||||
|
||||
def ClusterFile(fname, cluster_size=(3,3), dtype=np.int32):
|
||||
def ClusterFile(fname, cluster_size=(3,3), dtype=np.int32, chunk_size = 1000):
|
||||
"""
|
||||
Factory function to create a ClusterFile object. Provides a cleaner syntax for
|
||||
the templated ClusterFile in C++.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aare import ClusterFile
|
||||
|
||||
with ClusterFile("clusters.clust", cluster_size=(3,3), dtype=np.int32) as cf:
|
||||
# cf is now a ClusterFile_Cluster3x3i object but you don't need to know that.
|
||||
for clusters in cf:
|
||||
# Loop over clusters in chunks of 1000
|
||||
# The type of clusters will be a ClusterVector_Cluster3x3i in this case
|
||||
|
||||
"""
|
||||
|
||||
cls = _get_class("ClusterFile", cluster_size, dtype)
|
||||
return cls(fname)
|
||||
return cls(fname, chunk_size=chunk_size)
|
||||
|
@ -1,66 +0,0 @@
|
||||
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
|
@ -2,7 +2,7 @@
|
||||
from . import _aare
|
||||
|
||||
|
||||
from ._aare import File, RawMasterFile, RawSubFile, Hdf5MasterFile, JungfrauDataFile
|
||||
from ._aare import File, RawMasterFile, RawSubFile, JungfrauDataFile
|
||||
from ._aare import Pedestal_d, Pedestal_f, ClusterFinder_Cluster3x3i, VarClusterFinder
|
||||
from ._aare import DetectorType
|
||||
from ._aare import hitmap
|
||||
@ -23,7 +23,6 @@ from ._aare import apply_custom_weights
|
||||
|
||||
from .CtbRawFile import CtbRawFile
|
||||
from .RawFile import RawFile
|
||||
from .Hdf5File import Hdf5File
|
||||
from .ScanParameters import ScanParameters
|
||||
|
||||
from .utils import random_pixels, random_pixel, flat_list, add_colorbar
|
||||
|
@ -38,19 +38,20 @@ void define_ClusterFile(py::module &m, const std::string &typestr) {
|
||||
self.read_clusters(n_clusters));
|
||||
return v;
|
||||
},
|
||||
py::return_value_policy::take_ownership)
|
||||
py::return_value_policy::take_ownership, py::arg("n_clusters"))
|
||||
.def("read_frame",
|
||||
[](ClusterFile<ClusterType> &self) {
|
||||
auto v = new ClusterVector<ClusterType>(self.read_frame());
|
||||
return v;
|
||||
})
|
||||
.def("set_roi", &ClusterFile<ClusterType>::set_roi)
|
||||
.def("set_roi", &ClusterFile<ClusterType>::set_roi,
|
||||
py::arg("roi"))
|
||||
.def(
|
||||
"set_noise_map",
|
||||
[](ClusterFile<ClusterType> &self, py::array_t<int32_t> noise_map) {
|
||||
auto view = make_view_2d(noise_map);
|
||||
self.set_noise_map(view);
|
||||
})
|
||||
}, py::arg("noise_map"))
|
||||
|
||||
.def("set_gain_map",
|
||||
[](ClusterFile<ClusterType> &self, py::array_t<double> gain_map) {
|
||||
|
@ -5,11 +5,6 @@
|
||||
#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"
|
||||
|
||||
|
@ -1,106 +0,0 @@
|
||||
#include "H5Cpp.h"
|
||||
#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);
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
|
||||
#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);
|
||||
}
|
@ -14,10 +14,6 @@
|
||||
#include "file.hpp"
|
||||
#include "fit.hpp"
|
||||
#include "interpolation.hpp"
|
||||
#ifdef HDF5_FOUND
|
||||
#include "hdf5_file.hpp"
|
||||
#include "hdf5_master_file.hpp"
|
||||
#endif
|
||||
#include "jungfrau_data_file.hpp"
|
||||
#include "pedestal.hpp"
|
||||
#include "pixel_map.hpp"
|
||||
@ -58,10 +54,6 @@ PYBIND11_MODULE(_aare, m) {
|
||||
define_raw_sub_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_d");
|
||||
|
15
src/File.cpp
15
src/File.cpp
@ -1,7 +1,4 @@
|
||||
#include "aare/File.hpp"
|
||||
#ifdef HDF5_FOUND
|
||||
#include "aare/Hdf5File.hpp"
|
||||
#endif
|
||||
#include "aare/JungfrauDataFile.hpp"
|
||||
#include "aare/NumpyFile.hpp"
|
||||
#include "aare/RawFile.hpp"
|
||||
@ -30,17 +27,7 @@ File::File(const std::filesystem::path &fname, const std::string &mode,
|
||||
} else if (fname.extension() == ".npy") {
|
||||
// file_impl = new NumpyFile(fname, mode, cfg);
|
||||
file_impl = std::make_unique<NumpyFile>(fname, mode, cfg);
|
||||
}
|
||||
#ifdef HDF5_FOUND
|
||||
else if (fname.extension() == ".h5") {
|
||||
file_impl = std::make_unique<Hdf5File>(fname, mode);
|
||||
}
|
||||
#else
|
||||
else if (fname.extension() == ".h5") {
|
||||
throw std::runtime_error("Enable HDF5 compile option: AARE_HDF5=ON");
|
||||
}
|
||||
#endif
|
||||
else if (fname.extension() == ".dat") {
|
||||
} else if (fname.extension() == ".dat") {
|
||||
file_impl = std::make_unique<JungfrauDataFile>(fname);
|
||||
} else {
|
||||
throw std::runtime_error("Unsupported file type");
|
||||
|
234
src/Hdf5File.cpp
234
src/Hdf5File.cpp
@ -1,234 +0,0 @@
|
||||
#include "aare/Hdf5File.hpp"
|
||||
#include "aare/PixelMap.hpp"
|
||||
#include "aare/defs.hpp"
|
||||
#include "aare/logger.hpp"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace aare {
|
||||
|
||||
Hdf5File::Hdf5File(const std::filesystem::path &fname, const std::string &mode)
|
||||
: m_master(fname) {
|
||||
m_mode = mode;
|
||||
if (mode == "r") {
|
||||
open_data_file();
|
||||
open_header_files();
|
||||
} else {
|
||||
throw std::runtime_error(LOCATION +
|
||||
"Unsupported mode. Can only read Hdf5Files.");
|
||||
}
|
||||
}
|
||||
|
||||
Frame Hdf5File::read_frame() { return get_frame(m_current_frame++); }
|
||||
|
||||
Frame Hdf5File::read_frame(size_t frame_number) {
|
||||
seek(frame_number);
|
||||
return read_frame();
|
||||
}
|
||||
|
||||
std::vector<Frame> Hdf5File::read_n(size_t n_frames) {
|
||||
// TODO: implement this in a more efficient way
|
||||
std::vector<Frame> frames;
|
||||
for (size_t i = 0; i < n_frames; i++) {
|
||||
frames.push_back(this->get_frame(m_current_frame));
|
||||
m_current_frame++;
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
void Hdf5File::read_into(std::byte *image_buf, size_t n_frames) {
|
||||
get_frame_into(m_current_frame++, image_buf, n_frames);
|
||||
}
|
||||
|
||||
void Hdf5File::read_into(std::byte *image_buf) {
|
||||
get_frame_into(m_current_frame++, image_buf);
|
||||
}
|
||||
|
||||
void Hdf5File::read_into(std::byte *image_buf, DetectorHeader *header) {
|
||||
|
||||
get_frame_into(m_current_frame, image_buf, 1, header);
|
||||
}
|
||||
|
||||
void Hdf5File::read_into(std::byte *image_buf, size_t n_frames,
|
||||
DetectorHeader *header) {
|
||||
get_frame_into(m_current_frame++, image_buf, n_frames, header);
|
||||
}
|
||||
|
||||
size_t Hdf5File::frame_number(size_t frame_index) {
|
||||
// TODO: check if it should check total_Frames() at any point
|
||||
// check why this->read_into.. as in RawFile
|
||||
// refactor multiple frame reads into a single one using hyperslab
|
||||
if (frame_index >= m_master.frames_in_file()) {
|
||||
throw std::runtime_error(LOCATION + " Frame number out of range");
|
||||
}
|
||||
uint64_t fnum{0};
|
||||
int part_index = 0; // assuming first part
|
||||
m_header_datasets[0]->get_header_into(frame_index, part_index,
|
||||
reinterpret_cast<std::byte *>(&fnum));
|
||||
return fnum;
|
||||
}
|
||||
|
||||
size_t Hdf5File::bytes_per_frame() {
|
||||
return m_rows * m_cols * m_master.bitdepth() / 8;
|
||||
}
|
||||
|
||||
size_t Hdf5File::pixels_per_frame() { return m_rows * m_cols; }
|
||||
size_t Hdf5File::bytes_per_pixel() const { return m_master.bitdepth() / 8; }
|
||||
|
||||
void Hdf5File::seek(size_t frame_index) {
|
||||
m_data_dataset->seek(frame_index);
|
||||
for (size_t i = 0; i != header_dataset_names.size(); ++i) {
|
||||
m_header_datasets[i]->seek(frame_index);
|
||||
}
|
||||
m_current_frame = frame_index;
|
||||
}
|
||||
|
||||
size_t Hdf5File::tell() { return m_current_frame; }
|
||||
size_t Hdf5File::total_frames() const { return m_total_frames; }
|
||||
size_t Hdf5File::rows() const { return m_rows; }
|
||||
size_t Hdf5File::cols() const { return m_cols; }
|
||||
size_t Hdf5File::bitdepth() const { return m_master.bitdepth(); }
|
||||
xy Hdf5File::geometry() { return m_master.geometry(); }
|
||||
size_t Hdf5File::n_modules() const { return m_master.n_modules(); }
|
||||
Hdf5MasterFile Hdf5File::master() const { return m_master; }
|
||||
|
||||
DetectorType Hdf5File::detector_type() const {
|
||||
return m_master.detector_type();
|
||||
}
|
||||
|
||||
Frame Hdf5File::get_frame(size_t frame_index) {
|
||||
auto f = Frame(m_rows, m_cols, Dtype::from_bitdepth(m_master.bitdepth()));
|
||||
std::byte *frame_buffer = f.data();
|
||||
get_frame_into(frame_index, frame_buffer);
|
||||
return f;
|
||||
}
|
||||
|
||||
void Hdf5File::get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||
size_t n_frames, DetectorHeader *header) {
|
||||
if ((frame_index + n_frames - 1) >= m_master.frames_in_file()) {
|
||||
throw std::runtime_error(LOCATION + "Frame number out of range");
|
||||
}
|
||||
get_data_into(frame_index, frame_buffer);
|
||||
m_current_frame += n_frames;
|
||||
if (header) {
|
||||
for (size_t i = 0; i < n_frames; i++) {
|
||||
for (size_t part_idx = 0; part_idx != m_master.n_modules();
|
||||
++part_idx) {
|
||||
get_header_into(frame_index + i, part_idx, header);
|
||||
header++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Hdf5File::get_data_into(size_t frame_index, std::byte *frame_buffer,
|
||||
size_t n_frames) {
|
||||
m_data_dataset->get_data_into(frame_index, frame_buffer, n_frames);
|
||||
}
|
||||
|
||||
void Hdf5File::get_header_into(size_t frame_index, int part_index,
|
||||
DetectorHeader *header) {
|
||||
try {
|
||||
read_hdf5_header_fields(header, [&](size_t iParameter,
|
||||
std::byte *dest) {
|
||||
m_header_datasets[iParameter]->get_header_into(frame_index,
|
||||
part_index, dest);
|
||||
});
|
||||
LOG(logDEBUG5) << "Read 1D header for frame " << frame_index;
|
||||
} catch (const H5::Exception &e) {
|
||||
fmt::print("Exception type: {}\n", typeid(e).name());
|
||||
e.printErrorStack();
|
||||
throw std::runtime_error(
|
||||
LOCATION + "\nCould not to access header datasets in given file.");
|
||||
}
|
||||
}
|
||||
|
||||
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]));
|
||||
}
|
||||
read_hdf5_header_fields(&h, [&](size_t iParameter, std::byte *dest) {
|
||||
handles[iParameter]->get_header_into(0, 0, dest);
|
||||
});
|
||||
LOG(logDEBUG5) << "Read 1D header for frame 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.");
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
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_data_file() {
|
||||
if (m_mode != "r")
|
||||
throw std::runtime_error(LOCATION +
|
||||
"Unsupported mode. Can only read Hdf5 files.");
|
||||
try {
|
||||
m_data_dataset = std::make_unique<H5Handles>(
|
||||
m_master.file_name().string(), metadata_group_name + "/data");
|
||||
|
||||
m_total_frames = m_data_dataset->get_dims()[0];
|
||||
m_rows = m_data_dataset->get_dims()[1];
|
||||
m_cols = m_data_dataset->get_dims()[2];
|
||||
// fmt::print("Data Dataset dimensions: frames = {}, rows = {}, cols =
|
||||
// {}\n",
|
||||
// m_total_frames, m_rows, m_cols);
|
||||
} catch (const H5::Exception &e) {
|
||||
m_data_dataset.reset();
|
||||
fmt::print("Exception type: {}\n", typeid(e).name());
|
||||
e.printErrorStack();
|
||||
throw std::runtime_error(
|
||||
LOCATION + "\nCould not to access 'data' dataset in master 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_datasets.push_back(std::make_unique<H5Handles>(
|
||||
m_master.file_name().string(),
|
||||
metadata_group_name + header_dataset_names[i]));
|
||||
LOG(logDEBUG) << header_dataset_names[i]
|
||||
<< " Dataset dimensions: size = "
|
||||
<< m_header_datasets[i]->get_dims()[0];
|
||||
}
|
||||
} catch (const H5::Exception &e) {
|
||||
m_header_datasets.clear();
|
||||
m_data_dataset.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
|
@ -1,565 +0,0 @@
|
||||
#include "aare/Hdf5MasterFile.hpp"
|
||||
#include "aare/logger.hpp"
|
||||
#include "aare/to_string.hpp"
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
namespace aare {
|
||||
|
||||
Hdf5MasterFile::Hdf5MasterFile(const std::filesystem::path &fpath)
|
||||
: m_file_name(fpath) {
|
||||
if (!std::filesystem::exists(fpath)) {
|
||||
throw std::runtime_error(LOCATION + " File does not exist");
|
||||
}
|
||||
parse_acquisition_metadata(fpath);
|
||||
}
|
||||
|
||||
std::filesystem::path Hdf5MasterFile::file_name() const {
|
||||
return m_file_name;
|
||||
}
|
||||
|
||||
const std::string &Hdf5MasterFile::version() const { return m_version; }
|
||||
const DetectorType &Hdf5MasterFile::detector_type() const { return m_type; }
|
||||
const TimingMode &Hdf5MasterFile::timing_mode() const { return m_timing_mode; }
|
||||
xy Hdf5MasterFile::geometry() const { return m_geometry; }
|
||||
int Hdf5MasterFile::image_size_in_bytes() const {
|
||||
return m_image_size_in_bytes;
|
||||
}
|
||||
int Hdf5MasterFile::pixels_y() const { return m_pixels_y; }
|
||||
int Hdf5MasterFile::pixels_x() const { return m_pixels_x; }
|
||||
int Hdf5MasterFile::max_frames_per_file() const {
|
||||
return m_max_frames_per_file;
|
||||
}
|
||||
const FrameDiscardPolicy &Hdf5MasterFile::frame_discard_policy() const {
|
||||
return m_frame_discard_policy;
|
||||
}
|
||||
int Hdf5MasterFile::frame_padding() const { return m_frame_padding; }
|
||||
std::optional<ScanParameters> Hdf5MasterFile::scan_parameters() const {
|
||||
return m_scan_parameters;
|
||||
}
|
||||
size_t Hdf5MasterFile::total_frames_expected() const {
|
||||
return m_total_frames_expected;
|
||||
}
|
||||
std::optional<ns> Hdf5MasterFile::exptime() const { return m_exptime; }
|
||||
std::optional<ns> Hdf5MasterFile::period() const { return m_period; }
|
||||
std::optional<BurstMode> Hdf5MasterFile::burst_mode() const {
|
||||
return m_burst_mode;
|
||||
}
|
||||
std::optional<int> Hdf5MasterFile::number_of_udp_interfaces() const {
|
||||
return m_number_of_udp_interfaces;
|
||||
}
|
||||
int Hdf5MasterFile::bitdepth() const { return m_bitdepth; }
|
||||
std::optional<bool> Hdf5MasterFile::ten_giga() const { return m_ten_giga; }
|
||||
std::optional<int> Hdf5MasterFile::threshold_energy() const {
|
||||
return m_threshold_energy;
|
||||
}
|
||||
std::optional<std::vector<int>> Hdf5MasterFile::threshold_energy_all() const {
|
||||
return m_threshold_energy_all;
|
||||
}
|
||||
std::optional<ns> Hdf5MasterFile::subexptime() const { return m_subexptime; }
|
||||
std::optional<ns> Hdf5MasterFile::subperiod() const { return m_subperiod; }
|
||||
std::optional<bool> Hdf5MasterFile::quad() const { return m_quad; }
|
||||
std::optional<int> Hdf5MasterFile::number_of_rows() const {
|
||||
return m_number_of_rows;
|
||||
}
|
||||
std::optional<std::vector<size_t>> Hdf5MasterFile::rate_corrections() const {
|
||||
return m_rate_corrections;
|
||||
}
|
||||
std::optional<uint32_t> Hdf5MasterFile::adc_mask() const { return m_adc_mask; }
|
||||
bool Hdf5MasterFile::analog_flag() const { return m_analog_flag; }
|
||||
std::optional<int> Hdf5MasterFile::analog_samples() const {
|
||||
return m_analog_samples;
|
||||
}
|
||||
bool Hdf5MasterFile::digital_flag() const { return m_digital_flag; }
|
||||
std::optional<int> Hdf5MasterFile::digital_samples() const {
|
||||
return m_digital_samples;
|
||||
}
|
||||
std::optional<int> Hdf5MasterFile::dbit_offset() const { return m_dbit_offset; }
|
||||
std::optional<size_t> Hdf5MasterFile::dbit_list() const { return m_dbit_list; }
|
||||
std::optional<int> Hdf5MasterFile::transceiver_mask() const {
|
||||
return m_transceiver_mask;
|
||||
}
|
||||
bool Hdf5MasterFile::transceiver_flag() const { return m_transceiver_flag; }
|
||||
std::optional<int> Hdf5MasterFile::transceiver_samples() const {
|
||||
return m_transceiver_samples;
|
||||
}
|
||||
// g1 roi
|
||||
std::optional<ROI> Hdf5MasterFile::roi() const { return m_roi; }
|
||||
std::optional<int> Hdf5MasterFile::counter_mask() const {
|
||||
return m_counter_mask;
|
||||
}
|
||||
std::optional<std::vector<ns>> Hdf5MasterFile::exptime_array() const {
|
||||
return m_exptime_array;
|
||||
}
|
||||
std::optional<std::vector<ns>> Hdf5MasterFile::gate_delay_array() const {
|
||||
return m_gate_delay_array;
|
||||
}
|
||||
std::optional<int> Hdf5MasterFile::gates() const { return m_gates; }
|
||||
std::optional<std::map<std::string, std::string>>
|
||||
Hdf5MasterFile::additional_json_header() const {
|
||||
return m_additional_json_header;
|
||||
}
|
||||
size_t Hdf5MasterFile::frames_in_file() const { return m_frames_in_file; }
|
||||
size_t Hdf5MasterFile::n_modules() const {
|
||||
return m_geometry.row * m_geometry.col;
|
||||
}
|
||||
|
||||
// optional values, these may or may not be present in the master file
|
||||
// and are therefore modeled as std::optional
|
||||
|
||||
const std::string Hdf5MasterFile::metadata_group_name =
|
||||
"/entry/instrument/detector/";
|
||||
|
||||
template <typename T>
|
||||
T Hdf5MasterFile::h5_read_scalar_dataset(const H5::DataSet &dataset,
|
||||
const H5::DataType &data_type) {
|
||||
T value;
|
||||
dataset.read(&value, data_type);
|
||||
return value;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string Hdf5MasterFile::h5_read_scalar_dataset<std::string>(
|
||||
const H5::DataSet &dataset, const H5::DataType &data_type) {
|
||||
size_t size = data_type.getSize();
|
||||
std::vector<char> buffer(size + 1, 0);
|
||||
dataset.read(buffer.data(), data_type);
|
||||
return std::string(buffer.data());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T Hdf5MasterFile::h5_get_scalar_dataset(const H5::H5File &file,
|
||||
const std::string &dataset_name) {
|
||||
H5::DataSet dataset = file.openDataSet(dataset_name);
|
||||
H5::DataSpace dataspace = dataset.getSpace();
|
||||
if (dataspace.getSimpleExtentNdims() != 0) {
|
||||
throw std::runtime_error(LOCATION + "Expected " + dataset_name +
|
||||
" to be a scalar dataset");
|
||||
}
|
||||
H5::DataType data_type = dataset.getDataType();
|
||||
return h5_read_scalar_dataset<T>(dataset, data_type);
|
||||
}
|
||||
|
||||
void Hdf5MasterFile::parse_acquisition_metadata(
|
||||
const std::filesystem::path &fpath) {
|
||||
try {
|
||||
H5::H5File file(fpath, H5F_ACC_RDONLY);
|
||||
|
||||
// Attribute - version
|
||||
double dVersion{0.0};
|
||||
{
|
||||
H5::Attribute attr = file.openAttribute("version");
|
||||
H5::DataType attr_type = attr.getDataType();
|
||||
attr.read(attr_type, &dVersion);
|
||||
std::ostringstream oss;
|
||||
oss << std::fixed << std::setprecision(1) << dVersion;
|
||||
m_version = oss.str();
|
||||
LOG(logDEBUG) << "Version: " << m_version;
|
||||
}
|
||||
|
||||
// Scalar Dataset
|
||||
H5::Exception::dontPrint();
|
||||
|
||||
// Detector Type
|
||||
m_type = StringTo<DetectorType>(h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Detector Type")));
|
||||
LOG(logDEBUG) << "Detector Type: " << ToString(m_type);
|
||||
|
||||
// Timing Mode
|
||||
m_timing_mode = StringTo<TimingMode>(h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Timing Mode")));
|
||||
LOG(logDEBUG) << "Timing Mode: " << ToString(m_timing_mode);
|
||||
|
||||
// Geometry
|
||||
m_geometry.row = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Geometry in y axis"));
|
||||
m_geometry.col = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Geometry in x axis"));
|
||||
LOG(logDEBUG) << "Geometry: " << m_geometry.to_string();
|
||||
|
||||
// Image Size
|
||||
m_image_size_in_bytes = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Image Size"));
|
||||
LOG(logDEBUG) << "Image size: " << m_image_size_in_bytes;
|
||||
|
||||
// Pixels y
|
||||
m_pixels_y = h5_get_scalar_dataset<int>(
|
||||
file,
|
||||
std::string(metadata_group_name + "Number of pixels in y axis"));
|
||||
LOG(logDEBUG) << "Pixels in y: " << m_pixels_y;
|
||||
|
||||
// Pixels x
|
||||
m_pixels_x = h5_get_scalar_dataset<int>(
|
||||
file,
|
||||
std::string(metadata_group_name + "Number of pixels in x axis"));
|
||||
LOG(logDEBUG) << "Pixels in x: " << m_pixels_x;
|
||||
|
||||
// Max Frames Per File
|
||||
m_max_frames_per_file = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Maximum frames per file"));
|
||||
LOG(logDEBUG) << "Max frames per File: " << m_max_frames_per_file;
|
||||
|
||||
// Frame Discard Policy
|
||||
m_frame_discard_policy =
|
||||
StringTo<FrameDiscardPolicy>(h5_get_scalar_dataset<std::string>(
|
||||
file,
|
||||
std::string(metadata_group_name + "Frame Discard Policy")));
|
||||
LOG(logDEBUG) << "Frame Discard Policy: "
|
||||
<< ToString(m_frame_discard_policy);
|
||||
|
||||
// Frame Padding
|
||||
m_frame_padding = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Frame Padding"));
|
||||
LOG(logDEBUG) << "Frame Padding: " << m_frame_padding;
|
||||
|
||||
// Scan Parameters
|
||||
try {
|
||||
std::string scan_parameters = h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Scan Parameters"));
|
||||
m_scan_parameters = ScanParameters(scan_parameters);
|
||||
if (dVersion < 6.61) {
|
||||
m_scan_parameters
|
||||
->increment_stop(); // adjust for endpoint being included
|
||||
}
|
||||
LOG(logDEBUG) << "Scan Parameters: " << ToString(m_scan_parameters);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Total Frames Expected
|
||||
m_total_frames_expected = h5_get_scalar_dataset<size_t>(
|
||||
file, std::string(metadata_group_name + "Total Frames"));
|
||||
LOG(logDEBUG) << "Total Frames: " << m_total_frames_expected;
|
||||
|
||||
// Exptime
|
||||
try {
|
||||
m_exptime = StringTo<ns>(h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Exposure Time")));
|
||||
LOG(logDEBUG) << "Exptime: " << ToString(m_exptime);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Period
|
||||
try {
|
||||
m_period = StringTo<ns>(h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Acquisition Period")));
|
||||
LOG(logDEBUG) << "Period: " << ToString(m_period);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// burst mode
|
||||
try {
|
||||
m_burst_mode =
|
||||
StringTo<BurstMode>(h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Burst Mode")));
|
||||
LOG(logDEBUG) << "Burst Mode: " << ToString(m_burst_mode);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Number of UDP Interfaces
|
||||
// Not all detectors write the Number of UDP Interfaces but in case
|
||||
try {
|
||||
m_number_of_udp_interfaces = h5_get_scalar_dataset<int>(
|
||||
file,
|
||||
std::string(metadata_group_name + "Number of UDP Interfaces"));
|
||||
LOG(logDEBUG) << "Number of UDP Interfaces: "
|
||||
<< m_number_of_udp_interfaces;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Bit Depth
|
||||
// Not all detectors write the bitdepth but in case
|
||||
// its not there it is 16
|
||||
try {
|
||||
m_bitdepth = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Dynamic Range"));
|
||||
LOG(logDEBUG) << "Bit Depth: " << m_bitdepth;
|
||||
} catch (H5::FileIException &e) {
|
||||
m_bitdepth = 16;
|
||||
}
|
||||
|
||||
// Ten Giga
|
||||
try {
|
||||
m_ten_giga = h5_get_scalar_dataset<bool>(
|
||||
file, std::string(metadata_group_name + "Ten Giga Enable"));
|
||||
LOG(logDEBUG) << "Ten Giga Enable: " << m_ten_giga;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Threshold Energy
|
||||
try {
|
||||
m_threshold_energy = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Threshold Energy"));
|
||||
LOG(logDEBUG) << "Threshold Energy: " << m_threshold_energy;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Threshold All Energy
|
||||
try {
|
||||
m_threshold_energy_all =
|
||||
StringTo<std::vector<int>>(h5_get_scalar_dataset<std::string>(
|
||||
file,
|
||||
std::string(metadata_group_name + "Threshold Energies")));
|
||||
LOG(logDEBUG) << "Threshold Energies: "
|
||||
<< ToString(m_threshold_energy_all);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Subexptime
|
||||
try {
|
||||
m_subexptime = StringTo<ns>(h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Sub Exposure Time")));
|
||||
LOG(logDEBUG) << "Subexptime: " << ToString(m_subexptime);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Subperiod
|
||||
try {
|
||||
m_subperiod = StringTo<ns>(h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Sub Period")));
|
||||
LOG(logDEBUG) << "Subperiod: " << ToString(m_subperiod);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Quad
|
||||
try {
|
||||
m_quad = h5_get_scalar_dataset<bool>(
|
||||
file, std::string(metadata_group_name + "Quad"));
|
||||
LOG(logDEBUG) << "Quad: " << m_quad;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Number of Rows
|
||||
// Not all detectors write the Number of rows but in case
|
||||
try {
|
||||
m_number_of_rows = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Number of rows"));
|
||||
LOG(logDEBUG) << "Number of rows: " << m_number_of_rows;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Rate Corrections
|
||||
try {
|
||||
m_rate_corrections = StringTo<std::vector<size_t>>(
|
||||
h5_get_scalar_dataset<std::string>(
|
||||
file,
|
||||
std::string(metadata_group_name + "Rate Corrections")));
|
||||
LOG(logDEBUG) << "Rate Corrections: "
|
||||
<< ToString(m_rate_corrections);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// ADC Mask
|
||||
try {
|
||||
m_adc_mask = h5_get_scalar_dataset<uint32_t>(
|
||||
file, std::string(metadata_group_name + "ADC Mask"));
|
||||
LOG(logDEBUG) << "ADC Mask: " << m_adc_mask;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Analog Flag
|
||||
// ----------------------------------------------------------------
|
||||
// Special treatment of analog flag because of Moench03
|
||||
try {
|
||||
m_analog_flag = h5_get_scalar_dataset<uint8_t>(
|
||||
file, std::string(metadata_group_name + "Analog Flag"));
|
||||
LOG(logDEBUG) << "Analog Flag: " << m_analog_flag;
|
||||
} catch (H5::FileIException &e) {
|
||||
// if it doesn't work still set it to one
|
||||
// to try to decode analog samples (Old Moench03)
|
||||
m_analog_flag = 1;
|
||||
}
|
||||
|
||||
// Analog Samples
|
||||
try {
|
||||
if (m_analog_flag) {
|
||||
m_analog_samples = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Analog Samples"));
|
||||
LOG(logDEBUG) << "Analog Samples: " << m_analog_samples;
|
||||
}
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
// and set analog flag to 0
|
||||
m_analog_flag = false;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
// Digital Flag, Digital Samples
|
||||
try {
|
||||
m_digital_flag = h5_get_scalar_dataset<bool>(
|
||||
file, std::string(metadata_group_name + "Digital Flag"));
|
||||
LOG(logDEBUG) << "Digital Flag: " << m_digital_flag;
|
||||
if (m_digital_flag) {
|
||||
m_digital_samples = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Digital Samples"));
|
||||
}
|
||||
LOG(logDEBUG) << "Digital Samples: " << m_digital_samples;
|
||||
} catch (H5::FileIException &e) {
|
||||
m_digital_flag = false;
|
||||
}
|
||||
|
||||
// Dbit Offset
|
||||
try {
|
||||
m_dbit_offset = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Dbit Offset"));
|
||||
LOG(logDEBUG) << "Dbit Offset: " << m_dbit_offset;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Dbit List
|
||||
try {
|
||||
m_dbit_list = h5_get_scalar_dataset<size_t>(
|
||||
file, std::string(metadata_group_name + "Dbit Bitset List"));
|
||||
LOG(logDEBUG) << "Dbit list: " << m_dbit_list;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Transceiver Mask
|
||||
try {
|
||||
m_transceiver_mask = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Transceiver Mask"));
|
||||
LOG(logDEBUG) << "Transceiver Mask: " << m_transceiver_mask;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Transceiver Flag, Transceiver Samples
|
||||
try {
|
||||
m_transceiver_flag = h5_get_scalar_dataset<bool>(
|
||||
file, std::string(metadata_group_name + "Transceiver Flag"));
|
||||
LOG(logDEBUG) << "Transceiver Flag: " << m_transceiver_flag;
|
||||
if (m_transceiver_flag) {
|
||||
m_transceiver_samples = h5_get_scalar_dataset<int>(
|
||||
file,
|
||||
std::string(metadata_group_name + "Transceiver Samples"));
|
||||
LOG(logDEBUG)
|
||||
<< "Transceiver Samples: " << m_transceiver_samples;
|
||||
}
|
||||
} catch (H5::FileIException &e) {
|
||||
m_transceiver_flag = false;
|
||||
}
|
||||
|
||||
// Rx ROI
|
||||
try {
|
||||
ROI tmp_roi;
|
||||
tmp_roi.xmin = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "receiver roi xmin"));
|
||||
tmp_roi.xmax = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "receiver roi xmax"));
|
||||
tmp_roi.ymin = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "receiver roi ymin"));
|
||||
tmp_roi.ymax = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "receiver roi ymax"));
|
||||
|
||||
// if any of the values are set update the roi
|
||||
if (tmp_roi.xmin != -1 || tmp_roi.xmax != -1 ||
|
||||
tmp_roi.ymin != -1 || tmp_roi.ymax != -1) {
|
||||
// why?? TODO
|
||||
//if (dVersion < 6.6) {
|
||||
tmp_roi.xmax++;
|
||||
tmp_roi.ymax++;
|
||||
//}
|
||||
m_roi = tmp_roi;
|
||||
}
|
||||
|
||||
LOG(logDEBUG) << "ROI: " << m_roi;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Update detector type for Moench
|
||||
// TODO! How does this work with old .h5 master files?
|
||||
#ifdef AARE_VERBOSE
|
||||
fmt::print("Detecting Moench03: m_pixels_y: {}, "
|
||||
"m_analog_samples: {}\n",
|
||||
m_pixels_y, m_analog_samples.value_or(0));
|
||||
#endif
|
||||
if (m_type == DetectorType::Moench && !m_analog_samples &&
|
||||
m_pixels_y == 400) {
|
||||
m_type = DetectorType::Moench03;
|
||||
} else if (m_type == DetectorType::Moench && m_pixels_y == 400 &&
|
||||
m_analog_samples == 5000) {
|
||||
m_type = DetectorType::Moench03_old;
|
||||
}
|
||||
|
||||
// Counter Mask
|
||||
try {
|
||||
m_counter_mask = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Counter Mask"));
|
||||
LOG(logDEBUG) << "Counter Mask: " << m_counter_mask;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Exposure Time Array
|
||||
try {
|
||||
m_exptime_array =
|
||||
StringTo<std::vector<ns>>(h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Exposure Times")));
|
||||
LOG(logDEBUG) << "Exposure Times: " << ToString(m_exptime_array);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Gate Delay Array
|
||||
try {
|
||||
m_gate_delay_array =
|
||||
StringTo<std::vector<ns>>(h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name + "Gate Delays")));
|
||||
LOG(logDEBUG) << "Gate Delays: " << ToString(m_gate_delay_array);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Gates
|
||||
try {
|
||||
m_gates = h5_get_scalar_dataset<int>(
|
||||
file, std::string(metadata_group_name + "Gates"));
|
||||
LOG(logDEBUG) << "Gates: " << m_gates;
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Additional Json Header
|
||||
try {
|
||||
m_additional_json_header =
|
||||
StringTo<std::map<std::string, std::string>>(
|
||||
h5_get_scalar_dataset<std::string>(
|
||||
file, std::string(metadata_group_name +
|
||||
"Additional JSON Header")));
|
||||
LOG(logDEBUG) << "Additional JSON Header: "
|
||||
<< ToString(m_additional_json_header);
|
||||
} catch (H5::FileIException &e) {
|
||||
// keep the optional empty
|
||||
}
|
||||
|
||||
// Frames in File
|
||||
m_frames_in_file = h5_get_scalar_dataset<size_t>(
|
||||
file, std::string(metadata_group_name + "Frames in File"));
|
||||
LOG(logDEBUG) << "Frames in File: " << m_frames_in_file;
|
||||
|
||||
H5Eset_auto(H5E_DEFAULT, reinterpret_cast<H5E_auto2_t>(H5Eprint2),
|
||||
stderr);
|
||||
|
||||
} catch (const H5::Exception &e) {
|
||||
fmt::print("Exception type: {}\n", typeid(e).name());
|
||||
e.printErrorStack();
|
||||
throw std::runtime_error(LOCATION + "\nCould not parse master file");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace aare
|
@ -1,168 +0,0 @@
|
||||
#include "aare/Hdf5MasterFile.hpp"
|
||||
#include "aare/to_string.hpp"
|
||||
|
||||
#include "test_config.hpp"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
using namespace aare;
|
||||
|
||||
TEST_CASE("Parse a multi module jungfrau master file in .h5 format", "[.integration][.hdf5]") {
|
||||
auto fpath = test_data_path() / "hdf5" / "virtual" / "jungfrau" /
|
||||
"two_modules_master_0.h5";
|
||||
REQUIRE(std::filesystem::exists(fpath));
|
||||
Hdf5MasterFile f(fpath);
|
||||
|
||||
REQUIRE(f.version() == "6.6");
|
||||
// "Timestamp": "Tue Feb 20 08:28:24 2024",
|
||||
REQUIRE(f.detector_type() == DetectorType::Jungfrau);
|
||||
REQUIRE(f.timing_mode() == TimingMode::Auto);
|
||||
REQUIRE(f.geometry().col == 1);
|
||||
REQUIRE(f.geometry().row == 2);
|
||||
REQUIRE(f.image_size_in_bytes() == 1048576);
|
||||
REQUIRE(f.pixels_x() == 1024);
|
||||
REQUIRE(f.pixels_y() == 512);
|
||||
REQUIRE(f.max_frames_per_file() == 10000);
|
||||
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard);
|
||||
REQUIRE(f.frame_padding() == 1);
|
||||
REQUIRE(f.scan_parameters()->enabled() == false);
|
||||
REQUIRE(f.total_frames_expected() == 5);
|
||||
REQUIRE(f.exptime() == std::chrono::microseconds(10));
|
||||
REQUIRE(f.period() == std::chrono::milliseconds(2));
|
||||
REQUIRE_FALSE(f.burst_mode().has_value());
|
||||
REQUIRE(f.number_of_udp_interfaces() == 1);
|
||||
// Jungfrau doesn't write but it is 16
|
||||
REQUIRE(f.bitdepth() == 16);
|
||||
REQUIRE_FALSE(f.ten_giga().has_value());
|
||||
REQUIRE_FALSE(f.threshold_energy().has_value());
|
||||
REQUIRE_FALSE(f.threshold_energy_all().has_value());
|
||||
REQUIRE_FALSE(f.subexptime().has_value());
|
||||
REQUIRE_FALSE(f.subperiod().has_value());
|
||||
REQUIRE_FALSE(f.quad().has_value());
|
||||
REQUIRE(f.number_of_rows() == 512);
|
||||
REQUIRE_FALSE(f.rate_corrections().has_value());
|
||||
REQUIRE_FALSE(f.adc_mask().has_value());
|
||||
REQUIRE_FALSE(f.analog_flag());
|
||||
REQUIRE_FALSE(f.analog_samples().has_value());
|
||||
REQUIRE_FALSE(f.digital_flag());
|
||||
REQUIRE_FALSE(f.digital_samples().has_value());
|
||||
REQUIRE_FALSE(f.dbit_offset().has_value());
|
||||
REQUIRE_FALSE(f.dbit_list().has_value());
|
||||
REQUIRE_FALSE(f.transceiver_mask().has_value());
|
||||
REQUIRE_FALSE(f.transceiver_flag());
|
||||
REQUIRE_FALSE(f.transceiver_samples().has_value());
|
||||
REQUIRE_FALSE(f.roi().has_value());
|
||||
REQUIRE_FALSE(f.counter_mask().has_value());
|
||||
REQUIRE_FALSE(f.exptime_array().has_value());
|
||||
REQUIRE_FALSE(f.gate_delay_array().has_value());
|
||||
REQUIRE_FALSE(f.gates().has_value());
|
||||
REQUIRE_FALSE(f.additional_json_header().has_value());
|
||||
REQUIRE(f.frames_in_file() == 5);
|
||||
REQUIRE(f.n_modules() == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse a single module jungfrau master file in .h5 format", "[.integration][.hdf5]") {
|
||||
auto fpath = test_data_path() / "hdf5" / "virtual" / "jungfrau" /
|
||||
"single_module_master_2.h5";
|
||||
REQUIRE(std::filesystem::exists(fpath));
|
||||
Hdf5MasterFile f(fpath);
|
||||
|
||||
REQUIRE(f.version() == "6.6");
|
||||
// "Timestamp": "Tue Feb 20 08:28:24 2024",
|
||||
REQUIRE(f.detector_type() == DetectorType::Jungfrau);
|
||||
REQUIRE(f.timing_mode() == TimingMode::Auto);
|
||||
REQUIRE(f.geometry().col == 1);
|
||||
REQUIRE(f.geometry().row == 1);
|
||||
REQUIRE(f.image_size_in_bytes() == 1048576);
|
||||
REQUIRE(f.pixels_x() == 1024);
|
||||
REQUIRE(f.pixels_y() == 512);
|
||||
REQUIRE(f.max_frames_per_file() == 10000);
|
||||
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard);
|
||||
REQUIRE(f.frame_padding() == 1);
|
||||
REQUIRE(f.scan_parameters()->enabled() == false);
|
||||
REQUIRE(f.total_frames_expected() == 5);
|
||||
REQUIRE(f.exptime() == std::chrono::microseconds(10));
|
||||
REQUIRE(f.period() == std::chrono::milliseconds(2));
|
||||
REQUIRE_FALSE(f.burst_mode().has_value());
|
||||
REQUIRE(f.number_of_udp_interfaces() == 1);
|
||||
// Jungfrau doesn't write but it is 16
|
||||
REQUIRE(f.bitdepth() == 16);
|
||||
REQUIRE_FALSE(f.ten_giga().has_value());
|
||||
REQUIRE_FALSE(f.threshold_energy().has_value());
|
||||
REQUIRE_FALSE(f.threshold_energy_all().has_value());
|
||||
REQUIRE_FALSE(f.subexptime().has_value());
|
||||
REQUIRE_FALSE(f.subperiod().has_value());
|
||||
REQUIRE_FALSE(f.quad().has_value());
|
||||
REQUIRE(f.number_of_rows() == 512);
|
||||
REQUIRE_FALSE(f.rate_corrections().has_value());
|
||||
REQUIRE_FALSE(f.adc_mask().has_value());
|
||||
REQUIRE_FALSE(f.analog_flag());
|
||||
REQUIRE_FALSE(f.analog_samples().has_value());
|
||||
REQUIRE_FALSE(f.digital_flag());
|
||||
REQUIRE_FALSE(f.digital_samples().has_value());
|
||||
REQUIRE_FALSE(f.dbit_offset().has_value());
|
||||
REQUIRE_FALSE(f.dbit_list().has_value());
|
||||
REQUIRE_FALSE(f.transceiver_mask().has_value());
|
||||
REQUIRE_FALSE(f.transceiver_flag());
|
||||
REQUIRE_FALSE(f.transceiver_samples().has_value());
|
||||
REQUIRE_FALSE(f.roi().has_value());
|
||||
REQUIRE_FALSE(f.counter_mask().has_value());
|
||||
REQUIRE_FALSE(f.exptime_array().has_value());
|
||||
REQUIRE_FALSE(f.gate_delay_array().has_value());
|
||||
REQUIRE_FALSE(f.gates().has_value());
|
||||
REQUIRE_FALSE(f.additional_json_header().has_value());
|
||||
REQUIRE(f.frames_in_file() == 5);
|
||||
REQUIRE(f.n_modules() == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse a mythen3 master file in .h5 format", "[.integration][.hdf5]") {
|
||||
auto fpath = test_data_path() / "hdf5" / "virtual" / "mythen3" /
|
||||
"one_module_master_0.h5";
|
||||
REQUIRE(std::filesystem::exists(fpath));
|
||||
Hdf5MasterFile f(fpath);
|
||||
|
||||
REQUIRE(f.version() == "6.7");
|
||||
// "Timestamp": "Tue Feb 20 08:28:24 2024",
|
||||
REQUIRE(f.detector_type() == DetectorType::Mythen3);
|
||||
REQUIRE(f.timing_mode() == TimingMode::Auto);
|
||||
REQUIRE(f.geometry().col == 1);
|
||||
REQUIRE(f.geometry().row == 1);
|
||||
REQUIRE(f.image_size_in_bytes() == 15360);
|
||||
REQUIRE(f.pixels_x() == 3840);
|
||||
REQUIRE(f.pixels_y() == 1);
|
||||
REQUIRE(f.max_frames_per_file() == 10000);
|
||||
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard);
|
||||
REQUIRE(f.frame_padding() == 1);
|
||||
REQUIRE(f.scan_parameters()->enabled() == false);
|
||||
REQUIRE(f.total_frames_expected() == 1);
|
||||
REQUIRE_FALSE(f.exptime().has_value());
|
||||
REQUIRE(f.period() == std::chrono::nanoseconds(0));
|
||||
REQUIRE_FALSE(f.burst_mode().has_value());
|
||||
REQUIRE_FALSE(f.number_of_udp_interfaces().has_value());
|
||||
REQUIRE(f.bitdepth() == 32);
|
||||
REQUIRE(f.ten_giga() == 1);
|
||||
REQUIRE_FALSE(f.threshold_energy().has_value());
|
||||
REQUIRE(ToString(f.threshold_energy_all()) == "[-1, -1, -1]");
|
||||
REQUIRE_FALSE(f.subexptime().has_value());
|
||||
REQUIRE_FALSE(f.subperiod().has_value());
|
||||
REQUIRE_FALSE(f.quad().has_value());
|
||||
REQUIRE_FALSE(f.number_of_rows().has_value());
|
||||
REQUIRE_FALSE(f.rate_corrections().has_value());
|
||||
REQUIRE_FALSE(f.adc_mask().has_value());
|
||||
REQUIRE_FALSE(f.analog_flag());
|
||||
REQUIRE_FALSE(f.analog_samples().has_value());
|
||||
REQUIRE_FALSE(f.digital_flag());
|
||||
REQUIRE_FALSE(f.digital_samples().has_value());
|
||||
REQUIRE_FALSE(f.dbit_offset().has_value());
|
||||
REQUIRE_FALSE(f.dbit_list().has_value());
|
||||
REQUIRE_FALSE(f.transceiver_mask().has_value());
|
||||
REQUIRE_FALSE(f.transceiver_flag());
|
||||
REQUIRE_FALSE(f.transceiver_samples().has_value());
|
||||
REQUIRE_FALSE(f.roi().has_value());
|
||||
REQUIRE(f.counter_mask() == 0x7);
|
||||
REQUIRE(ToString(f.exptime_array()) == "[0.1s, 0.1s, 0.1s]");
|
||||
REQUIRE(ToString(f.gate_delay_array()) == "[0ns, 0ns, 0ns]");
|
||||
REQUIRE(f.gates() == 1);
|
||||
REQUIRE_FALSE(f.additional_json_header().has_value());
|
||||
REQUIRE(f.frames_in_file() == 1);
|
||||
REQUIRE(f.n_modules() == 1);
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
#include "aare/RawMasterFile.hpp"
|
||||
#include "aare/to_string.hpp"
|
||||
#include <sstream>
|
||||
namespace aare {
|
||||
|
||||
@ -62,6 +61,32 @@ const std::string &RawFileNameComponents::base_name() const {
|
||||
const std::string &RawFileNameComponents::ext() const { return m_ext; }
|
||||
int RawFileNameComponents::file_index() const { return m_file_index; }
|
||||
|
||||
// "[enabled\ndac dac 4\nstart 500\nstop 2200\nstep 5\nsettleTime 100us\n]"
|
||||
ScanParameters::ScanParameters(const std::string &par) {
|
||||
std::istringstream iss(par.substr(1, par.size() - 2));
|
||||
std::string line;
|
||||
while (std::getline(iss, line)) {
|
||||
if (line == "enabled") {
|
||||
m_enabled = true;
|
||||
} else if (line.find("dac") != std::string::npos) {
|
||||
m_dac = line.substr(4);
|
||||
} else if (line.find("start") != std::string::npos) {
|
||||
m_start = std::stoi(line.substr(6));
|
||||
} else if (line.find("stop") != std::string::npos) {
|
||||
m_stop = std::stoi(line.substr(5));
|
||||
} else if (line.find("step") != std::string::npos) {
|
||||
m_step = std::stoi(line.substr(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ScanParameters::start() const { return m_start; }
|
||||
int ScanParameters::stop() const { return m_stop; }
|
||||
void ScanParameters::increment_stop() { m_stop += 1; }
|
||||
int ScanParameters::step() const { return m_step; }
|
||||
const std::string &ScanParameters::dac() const { return m_dac; }
|
||||
bool ScanParameters::enabled() const { return m_enabled; }
|
||||
|
||||
RawMasterFile::RawMasterFile(const std::filesystem::path &fpath)
|
||||
: m_fnc(fpath) {
|
||||
if (!std::filesystem::exists(fpath)) {
|
||||
|
@ -46,6 +46,25 @@ TEST_CASE("Master file name does not fit pattern") {
|
||||
REQUIRE_THROWS(RawFileNameComponents("test_master_1.txt"));
|
||||
}
|
||||
|
||||
TEST_CASE("Parse scan parameters") {
|
||||
ScanParameters s("[enabled\ndac dac 4\nstart 500\nstop 2200\nstep "
|
||||
"5\nsettleTime 100us\n]");
|
||||
REQUIRE(s.enabled());
|
||||
REQUIRE(s.dac() == "dac 4");
|
||||
REQUIRE(s.start() == 500);
|
||||
REQUIRE(s.stop() == 2200);
|
||||
REQUIRE(s.step() == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("A disabled scan") {
|
||||
ScanParameters s("[disabled]");
|
||||
REQUIRE_FALSE(s.enabled());
|
||||
REQUIRE(s.dac() == "");
|
||||
REQUIRE(s.start() == 0);
|
||||
REQUIRE(s.stop() == 0);
|
||||
REQUIRE(s.step() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse a master file in .json format", "[.integration]") {
|
||||
auto fpath =
|
||||
test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
||||
|
107
src/defs.cpp
107
src/defs.cpp
@ -1,4 +1,6 @@
|
||||
#include "aare/defs.hpp"
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <fmt/core.h>
|
||||
namespace aare {
|
||||
@ -8,4 +10,109 @@ void assert_failed(const std::string &msg) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a DetectorType to a string
|
||||
* @param type DetectorType
|
||||
* @return string representation of the DetectorType
|
||||
*/
|
||||
template <> std::string ToString(DetectorType arg) {
|
||||
switch (arg) {
|
||||
case DetectorType::Generic:
|
||||
return "Generic";
|
||||
case DetectorType::Eiger:
|
||||
return "Eiger";
|
||||
case DetectorType::Gotthard:
|
||||
return "Gotthard";
|
||||
case DetectorType::Jungfrau:
|
||||
return "Jungfrau";
|
||||
case DetectorType::ChipTestBoard:
|
||||
return "ChipTestBoard";
|
||||
case DetectorType::Moench:
|
||||
return "Moench";
|
||||
case DetectorType::Mythen3:
|
||||
return "Mythen3";
|
||||
case DetectorType::Gotthard2:
|
||||
return "Gotthard2";
|
||||
case DetectorType::Xilinx_ChipTestBoard:
|
||||
return "Xilinx_ChipTestBoard";
|
||||
|
||||
// Custom ones
|
||||
case DetectorType::Moench03:
|
||||
return "Moench03";
|
||||
case DetectorType::Moench03_old:
|
||||
return "Moench03_old";
|
||||
case DetectorType::Unknown:
|
||||
return "Unknown";
|
||||
|
||||
// no default case to trigger compiler warning if not all
|
||||
// enum values are handled
|
||||
}
|
||||
throw std::runtime_error("Could not decode detector to string");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a DetectorType
|
||||
* @param name string representation of the DetectorType
|
||||
* @return DetectorType
|
||||
* @throw runtime_error if the string does not match any DetectorType
|
||||
*/
|
||||
template <> DetectorType StringTo(const std::string &arg) {
|
||||
if (arg == "Generic")
|
||||
return DetectorType::Generic;
|
||||
if (arg == "Eiger")
|
||||
return DetectorType::Eiger;
|
||||
if (arg == "Gotthard")
|
||||
return DetectorType::Gotthard;
|
||||
if (arg == "Jungfrau")
|
||||
return DetectorType::Jungfrau;
|
||||
if (arg == "ChipTestBoard")
|
||||
return DetectorType::ChipTestBoard;
|
||||
if (arg == "Moench")
|
||||
return DetectorType::Moench;
|
||||
if (arg == "Mythen3")
|
||||
return DetectorType::Mythen3;
|
||||
if (arg == "Gotthard2")
|
||||
return DetectorType::Gotthard2;
|
||||
if (arg == "Xilinx_ChipTestBoard")
|
||||
return DetectorType::Xilinx_ChipTestBoard;
|
||||
|
||||
// Custom ones
|
||||
if (arg == "Moench03")
|
||||
return DetectorType::Moench03;
|
||||
if (arg == "Moench03_old")
|
||||
return DetectorType::Moench03_old;
|
||||
if (arg == "Unknown")
|
||||
return DetectorType::Unknown;
|
||||
|
||||
throw std::runtime_error("Could not decode detector from: \"" + arg + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a TimingMode
|
||||
* @param mode string representation of the TimingMode
|
||||
* @return TimingMode
|
||||
* @throw runtime_error if the string does not match any TimingMode
|
||||
*/
|
||||
template <> TimingMode StringTo(const std::string &arg) {
|
||||
if (arg == "auto")
|
||||
return TimingMode::Auto;
|
||||
if (arg == "trigger")
|
||||
return TimingMode::Trigger;
|
||||
throw std::runtime_error("Could not decode timing mode from: \"" + arg +
|
||||
"\"");
|
||||
}
|
||||
|
||||
template <> FrameDiscardPolicy StringTo(const std::string &arg) {
|
||||
if (arg == "nodiscard")
|
||||
return FrameDiscardPolicy::NoDiscard;
|
||||
if (arg == "discard")
|
||||
return FrameDiscardPolicy::Discard;
|
||||
if (arg == "discardpartial")
|
||||
return FrameDiscardPolicy::DiscardPartial;
|
||||
throw std::runtime_error("Could not decode frame discard policy from: \"" +
|
||||
arg + "\"");
|
||||
}
|
||||
|
||||
// template <> TimingMode StringTo<TimingMode>(std::string mode);
|
||||
|
||||
} // namespace aare
|
@ -1,6 +1,54 @@
|
||||
#include "aare/defs.hpp"
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <string>
|
||||
|
||||
using aare::StringTo;
|
||||
using aare::ToString;
|
||||
|
||||
TEST_CASE("Enum to string conversion") {
|
||||
// TODO! By the way I don't think the enum string conversions should be in
|
||||
// the defs.hpp file but let's use this to show a test
|
||||
REQUIRE(ToString(aare::DetectorType::Generic) == "Generic");
|
||||
REQUIRE(ToString(aare::DetectorType::Eiger) == "Eiger");
|
||||
REQUIRE(ToString(aare::DetectorType::Gotthard) == "Gotthard");
|
||||
REQUIRE(ToString(aare::DetectorType::Jungfrau) == "Jungfrau");
|
||||
REQUIRE(ToString(aare::DetectorType::ChipTestBoard) == "ChipTestBoard");
|
||||
REQUIRE(ToString(aare::DetectorType::Moench) == "Moench");
|
||||
REQUIRE(ToString(aare::DetectorType::Mythen3) == "Mythen3");
|
||||
REQUIRE(ToString(aare::DetectorType::Gotthard2) == "Gotthard2");
|
||||
REQUIRE(ToString(aare::DetectorType::Xilinx_ChipTestBoard) ==
|
||||
"Xilinx_ChipTestBoard");
|
||||
REQUIRE(ToString(aare::DetectorType::Moench03) == "Moench03");
|
||||
REQUIRE(ToString(aare::DetectorType::Moench03_old) == "Moench03_old");
|
||||
REQUIRE(ToString(aare::DetectorType::Unknown) == "Unknown");
|
||||
}
|
||||
|
||||
TEST_CASE("String to enum") {
|
||||
REQUIRE(StringTo<aare::DetectorType>("Generic") ==
|
||||
aare::DetectorType::Generic);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Eiger") == aare::DetectorType::Eiger);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Gotthard") ==
|
||||
aare::DetectorType::Gotthard);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Jungfrau") ==
|
||||
aare::DetectorType::Jungfrau);
|
||||
REQUIRE(StringTo<aare::DetectorType>("ChipTestBoard") ==
|
||||
aare::DetectorType::ChipTestBoard);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Moench") ==
|
||||
aare::DetectorType::Moench);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Mythen3") ==
|
||||
aare::DetectorType::Mythen3);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Gotthard2") ==
|
||||
aare::DetectorType::Gotthard2);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Xilinx_ChipTestBoard") ==
|
||||
aare::DetectorType::Xilinx_ChipTestBoard);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Moench03") ==
|
||||
aare::DetectorType::Moench03);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Moench03_old") ==
|
||||
aare::DetectorType::Moench03_old);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Unknown") ==
|
||||
aare::DetectorType::Unknown);
|
||||
}
|
||||
|
||||
TEST_CASE("Enum values") {
|
||||
// Since some of the enums are written to file we need to make sure
|
||||
|
@ -1,26 +0,0 @@
|
||||
#include "aare/scan_parameters.hpp"
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
using namespace aare;
|
||||
|
||||
// TODO: Move these to to_string.test.cpp once ToSTring is implemented
|
||||
TEST_CASE("Parse scan parameters") {
|
||||
ScanParameters s("[enabled\ndac dac 4\nstart 500\nstop 2200\nstep "
|
||||
"5\nsettleTime 100us\n]");
|
||||
REQUIRE(s.enabled());
|
||||
REQUIRE(s.dac() == "dac 4");
|
||||
REQUIRE(s.start() == 500);
|
||||
REQUIRE(s.stop() == 2200);
|
||||
REQUIRE(s.step() == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("A disabled scan") {
|
||||
ScanParameters s("[disabled]");
|
||||
REQUIRE_FALSE(s.enabled());
|
||||
REQUIRE(s.dac() == "");
|
||||
REQUIRE(s.start() == 0);
|
||||
REQUIRE(s.stop() == 0);
|
||||
REQUIRE(s.step() == 0);
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
#include "aare/string_utils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace aare {
|
||||
|
||||
std::string RemoveUnit(std::string &str) {
|
||||
auto it = str.begin();
|
||||
while (it != str.end()) {
|
||||
if (std::isalpha(*it))
|
||||
break;
|
||||
++it;
|
||||
}
|
||||
auto pos = it - str.begin();
|
||||
auto unit = str.substr(pos);
|
||||
str.erase(it, end(str));
|
||||
return unit;
|
||||
}
|
||||
|
||||
void TrimWhiteSpaces(std::string &s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char c) {
|
||||
return !std::isspace(c);
|
||||
}));
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(),
|
||||
[](unsigned char c) { return !std::isspace(c); })
|
||||
.base(),
|
||||
s.end());
|
||||
}
|
||||
|
||||
} // namespace aare
|
@ -1,226 +0,0 @@
|
||||
#include "aare/to_string.hpp"
|
||||
|
||||
namespace aare {
|
||||
|
||||
/**
|
||||
* @brief Convert a DetectorType to a string
|
||||
* @param type DetectorType
|
||||
* @return string representation of the DetectorType
|
||||
*/
|
||||
template <> std::string ToString(DetectorType arg) {
|
||||
switch (arg) {
|
||||
case DetectorType::Generic:
|
||||
return "Generic";
|
||||
case DetectorType::Eiger:
|
||||
return "Eiger";
|
||||
case DetectorType::Gotthard:
|
||||
return "Gotthard";
|
||||
case DetectorType::Jungfrau:
|
||||
return "Jungfrau";
|
||||
case DetectorType::ChipTestBoard:
|
||||
return "ChipTestBoard";
|
||||
case DetectorType::Moench:
|
||||
return "Moench";
|
||||
case DetectorType::Mythen3:
|
||||
return "Mythen3";
|
||||
case DetectorType::Gotthard2:
|
||||
return "Gotthard2";
|
||||
case DetectorType::Xilinx_ChipTestBoard:
|
||||
return "Xilinx_ChipTestBoard";
|
||||
|
||||
// Custom ones
|
||||
case DetectorType::Moench03:
|
||||
return "Moench03";
|
||||
case DetectorType::Moench03_old:
|
||||
return "Moench03_old";
|
||||
case DetectorType::Unknown:
|
||||
return "Unknown";
|
||||
|
||||
// no default case to trigger compiler warning if not all
|
||||
// enum values are handled
|
||||
}
|
||||
throw std::runtime_error("Could not decode detector to string");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a DetectorType
|
||||
* @param name string representation of the DetectorType
|
||||
* @return DetectorType
|
||||
* @throw runtime_error if the string does not match any DetectorType
|
||||
*/
|
||||
template <> DetectorType StringTo(const std::string &arg) {
|
||||
if (arg == "Generic")
|
||||
return DetectorType::Generic;
|
||||
if (arg == "Eiger")
|
||||
return DetectorType::Eiger;
|
||||
if (arg == "Gotthard")
|
||||
return DetectorType::Gotthard;
|
||||
if (arg == "Jungfrau")
|
||||
return DetectorType::Jungfrau;
|
||||
if (arg == "ChipTestBoard")
|
||||
return DetectorType::ChipTestBoard;
|
||||
if (arg == "Moench")
|
||||
return DetectorType::Moench;
|
||||
if (arg == "Mythen3")
|
||||
return DetectorType::Mythen3;
|
||||
if (arg == "Gotthard2")
|
||||
return DetectorType::Gotthard2;
|
||||
if (arg == "Xilinx_ChipTestBoard")
|
||||
return DetectorType::Xilinx_ChipTestBoard;
|
||||
|
||||
// Custom ones
|
||||
if (arg == "Moench03")
|
||||
return DetectorType::Moench03;
|
||||
if (arg == "Moench03_old")
|
||||
return DetectorType::Moench03_old;
|
||||
if (arg == "Unknown")
|
||||
return DetectorType::Unknown;
|
||||
|
||||
throw std::runtime_error("Could not decode detector from: \"" + arg + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a TimingMode to a string
|
||||
* @param type TimingMode
|
||||
* @return string representation of the TimingMode
|
||||
*/
|
||||
template <> std::string ToString(TimingMode arg) {
|
||||
switch (arg) {
|
||||
case TimingMode::Auto:
|
||||
return "Auto";
|
||||
case TimingMode::Trigger:
|
||||
return "Trigger";
|
||||
|
||||
// no default case to trigger compiler warning if not all
|
||||
// enum values are handled
|
||||
}
|
||||
throw std::runtime_error("Could not decode timing mode to string");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a TimingMode
|
||||
* @param mode string representation of the TimingMode
|
||||
* @return TimingMode
|
||||
* @throw runtime_error if the string does not match any TimingMode
|
||||
*/
|
||||
template <> TimingMode StringTo(const std::string &arg) {
|
||||
if (arg == "auto")
|
||||
return TimingMode::Auto;
|
||||
if (arg == "trigger")
|
||||
return TimingMode::Trigger;
|
||||
throw std::runtime_error("Could not decode timing mode from: \"" + arg +
|
||||
"\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a FrameDiscardPolicy to a string
|
||||
* @param type FrameDiscardPolicy
|
||||
* @return string representation of the FrameDiscardPolicy
|
||||
*/
|
||||
template <> std::string ToString(FrameDiscardPolicy arg) {
|
||||
switch (arg) {
|
||||
case FrameDiscardPolicy::NoDiscard:
|
||||
return "nodiscard";
|
||||
case FrameDiscardPolicy::Discard:
|
||||
return "discard";
|
||||
case FrameDiscardPolicy::DiscardPartial:
|
||||
return "discardpartial";
|
||||
|
||||
// no default case to trigger compiler warning if not all
|
||||
// enum values are handled
|
||||
}
|
||||
throw std::runtime_error("Could not decode frame discard policy to string");
|
||||
}
|
||||
|
||||
template <> FrameDiscardPolicy StringTo(const std::string &arg) {
|
||||
if (arg == "nodiscard")
|
||||
return FrameDiscardPolicy::NoDiscard;
|
||||
if (arg == "discard")
|
||||
return FrameDiscardPolicy::Discard;
|
||||
if (arg == "discardpartial")
|
||||
return FrameDiscardPolicy::DiscardPartial;
|
||||
throw std::runtime_error("Could not decode frame discard policy from: \"" +
|
||||
arg + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a BurstMode to a string
|
||||
* @param type BurstMode
|
||||
* @return string representation of the BurstMode
|
||||
*/
|
||||
template <> std::string ToString(BurstMode arg) {
|
||||
switch (arg) {
|
||||
case BurstMode::Burst_Interal:
|
||||
return "burst_internal";
|
||||
case BurstMode::Burst_External:
|
||||
return "burst_external";
|
||||
case BurstMode::Continuous_Internal:
|
||||
return "continuous_internal";
|
||||
case BurstMode::Continuous_External:
|
||||
return "continuous_external";
|
||||
}
|
||||
throw std::runtime_error("Could not decode burst mode to string");
|
||||
}
|
||||
|
||||
template <> BurstMode StringTo(const std::string &arg) {
|
||||
if (arg == "burst_internal")
|
||||
return BurstMode::Burst_Interal;
|
||||
if (arg == "burst_external")
|
||||
return BurstMode::Burst_External;
|
||||
if (arg == "continuous_internal")
|
||||
return BurstMode::Continuous_Internal;
|
||||
if (arg == "continuous_external")
|
||||
return BurstMode::Continuous_External;
|
||||
throw std::runtime_error("Could not decode burst mode from: \"" + arg +
|
||||
"\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a ScanParameters to a string
|
||||
* @param type ScanParameters
|
||||
* @return string representation of the ScanParameters
|
||||
*/
|
||||
template <> std::string ToString(ScanParameters arg) {
|
||||
std::ostringstream oss;
|
||||
oss << '[';
|
||||
if (arg.enabled()) {
|
||||
oss << "enabled" << std::endl
|
||||
<< "dac " << arg.dac() << std::endl
|
||||
<< "start " << arg.start() << std::endl
|
||||
<< "stop " << arg.stop() << std::endl
|
||||
<< "step " << arg.step()
|
||||
<< std::endl
|
||||
//<< "settleTime "
|
||||
// << ToString(std::chrono::nanoseconds{arg.dacSettleTime_ns})
|
||||
<< std::endl;
|
||||
} else {
|
||||
oss << "disabled";
|
||||
}
|
||||
oss << ']';
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const ScanParameters &r) {
|
||||
return os << ToString(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a ROI to a string
|
||||
* @param type ROI
|
||||
* @return string representation of the ROI
|
||||
*/
|
||||
template <> std::string ToString(ROI arg) {
|
||||
std::ostringstream oss;
|
||||
oss << '[' << arg.xmin << ", " << arg.xmax;
|
||||
if (arg.ymin != -1 || arg.ymax != -1) {
|
||||
oss << ", " << arg.ymin << ", " << arg.ymax;
|
||||
}
|
||||
oss << ']';
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const ROI &roi) {
|
||||
return os << ToString(roi);
|
||||
}
|
||||
|
||||
} // namespace aare
|
@ -1,224 +0,0 @@
|
||||
#include "aare/to_string.hpp"
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
using aare::StringTo;
|
||||
using aare::ToString;
|
||||
|
||||
TEST_CASE("Detector Type to string conversion") {
|
||||
// TODO! By the way I don't think the enum string conversions should be in
|
||||
// the defs.hpp file but let's use this to show a test
|
||||
REQUIRE(ToString(aare::DetectorType::Generic) == "Generic");
|
||||
REQUIRE(ToString(aare::DetectorType::Eiger) == "Eiger");
|
||||
REQUIRE(ToString(aare::DetectorType::Gotthard) == "Gotthard");
|
||||
REQUIRE(ToString(aare::DetectorType::Jungfrau) == "Jungfrau");
|
||||
REQUIRE(ToString(aare::DetectorType::ChipTestBoard) == "ChipTestBoard");
|
||||
REQUIRE(ToString(aare::DetectorType::Moench) == "Moench");
|
||||
REQUIRE(ToString(aare::DetectorType::Mythen3) == "Mythen3");
|
||||
REQUIRE(ToString(aare::DetectorType::Gotthard2) == "Gotthard2");
|
||||
REQUIRE(ToString(aare::DetectorType::Xilinx_ChipTestBoard) ==
|
||||
"Xilinx_ChipTestBoard");
|
||||
REQUIRE(ToString(aare::DetectorType::Moench03) == "Moench03");
|
||||
REQUIRE(ToString(aare::DetectorType::Moench03_old) == "Moench03_old");
|
||||
REQUIRE(ToString(aare::DetectorType::Unknown) == "Unknown");
|
||||
}
|
||||
|
||||
TEST_CASE("String to Detector Type") {
|
||||
REQUIRE(StringTo<aare::DetectorType>("Generic") ==
|
||||
aare::DetectorType::Generic);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Eiger") == aare::DetectorType::Eiger);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Gotthard") ==
|
||||
aare::DetectorType::Gotthard);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Jungfrau") ==
|
||||
aare::DetectorType::Jungfrau);
|
||||
REQUIRE(StringTo<aare::DetectorType>("ChipTestBoard") ==
|
||||
aare::DetectorType::ChipTestBoard);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Moench") ==
|
||||
aare::DetectorType::Moench);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Mythen3") ==
|
||||
aare::DetectorType::Mythen3);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Gotthard2") ==
|
||||
aare::DetectorType::Gotthard2);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Xilinx_ChipTestBoard") ==
|
||||
aare::DetectorType::Xilinx_ChipTestBoard);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Moench03") ==
|
||||
aare::DetectorType::Moench03);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Moench03_old") ==
|
||||
aare::DetectorType::Moench03_old);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Unknown") ==
|
||||
aare::DetectorType::Unknown);
|
||||
}
|
||||
|
||||
TEST_CASE("conversion from duration to string") {
|
||||
using ns = std::chrono::nanoseconds;
|
||||
using us = std::chrono::microseconds;
|
||||
using ms = std::chrono::milliseconds;
|
||||
using s = std::chrono::seconds;
|
||||
REQUIRE(ToString(ns(150)) == "150ns");
|
||||
REQUIRE(ToString(ms(783)) == "0.783s");
|
||||
REQUIRE(ToString(ms(783), "ms") == "783ms");
|
||||
REQUIRE(ToString(us(0)) == "0ns"); // Defaults to the lowest unit
|
||||
REQUIRE(ToString(us(0), "s") == "0s");
|
||||
REQUIRE(ToString(s(-1)) == "-1s");
|
||||
REQUIRE(ToString(us(-100)) == "-100us");
|
||||
}
|
||||
|
||||
TEST_CASE("Convert vector of time") {
|
||||
using ns = std::chrono::nanoseconds;
|
||||
using us = std::chrono::microseconds;
|
||||
using ms = std::chrono::milliseconds;
|
||||
using s = std::chrono::seconds;
|
||||
std::vector<ns> vec{ns(150), us(10), ns(600)};
|
||||
REQUIRE(ToString(vec) == "[150ns, 10us, 600ns]");
|
||||
vec[0] = ms(150);
|
||||
vec[1] = s(10);
|
||||
REQUIRE(ToString(vec) == "[0.15s, 10s, 600ns]");
|
||||
// REQUIRE(ToString(vec, "ns") == "[150ns, 10000ns, 600ns]");
|
||||
}
|
||||
|
||||
TEST_CASE("string to std::chrono::duration") {
|
||||
using ns = std::chrono::nanoseconds;
|
||||
using us = std::chrono::microseconds;
|
||||
using ms = std::chrono::milliseconds;
|
||||
using s = std::chrono::seconds;
|
||||
REQUIRE(StringTo<ns>("150", "ns") == ns(150));
|
||||
REQUIRE(StringTo<ns>("150us") == us(150));
|
||||
REQUIRE(StringTo<ns>("150ms") == ms(150));
|
||||
REQUIRE(StringTo<s>("3 s") == s(3));
|
||||
REQUIRE_THROWS(StringTo<ns>("5xs"));
|
||||
REQUIRE_THROWS(StringTo<ns>("asvn"));
|
||||
}
|
||||
|
||||
TEST_CASE("Vector of int") {
|
||||
std::vector<int> vec;
|
||||
REQUIRE(ToString(vec) == "[]");
|
||||
|
||||
vec.push_back(1);
|
||||
REQUIRE(ToString(vec) == "[1]");
|
||||
|
||||
vec.push_back(172);
|
||||
REQUIRE(ToString(vec) == "[1, 172]");
|
||||
|
||||
vec.push_back(5000);
|
||||
REQUIRE(ToString(vec) == "[1, 172, 5000]");
|
||||
}
|
||||
|
||||
TEST_CASE("Vector of double") {
|
||||
std::vector<double> vec;
|
||||
REQUIRE(ToString(vec) == "[]");
|
||||
|
||||
vec.push_back(1.3);
|
||||
REQUIRE(ToString(vec) == "[1.3]");
|
||||
|
||||
// vec.push_back(5669.325);
|
||||
// REQUIRE(ToString(vec) == "[1.3, 5669.325]");
|
||||
|
||||
// vec.push_back(-5669.325005);
|
||||
// REQUIRE(ToString(vec) == "[1.3, 5669.325, -5669.325005]");
|
||||
}
|
||||
|
||||
TEST_CASE("String to string") {
|
||||
std::string k = "hej";
|
||||
REQUIRE(ToString(k) == "hej");
|
||||
}
|
||||
|
||||
TEST_CASE("vector of strings") {
|
||||
std::vector<std::string> vec{"5", "s"};
|
||||
REQUIRE(ToString(vec) == "[5, s]");
|
||||
|
||||
std::vector<std::string> vec2{"some", "strange", "words", "75"};
|
||||
REQUIRE(ToString(vec2) == "[some, strange, words, 75]");
|
||||
}
|
||||
|
||||
TEST_CASE("uint32 from string") {
|
||||
REQUIRE(StringTo<uint32_t>("0") == 0);
|
||||
REQUIRE(StringTo<uint32_t>("5") == 5u);
|
||||
REQUIRE(StringTo<uint32_t>("16") == 16u);
|
||||
REQUIRE(StringTo<uint32_t>("20") == 20u);
|
||||
REQUIRE(StringTo<uint32_t>("0x14") == 20u);
|
||||
REQUIRE(StringTo<uint32_t>("0x15") == 21u);
|
||||
REQUIRE(StringTo<uint32_t>("0x15") == 0x15);
|
||||
REQUIRE(StringTo<uint32_t>("0xffffff") == 0xffffff);
|
||||
}
|
||||
|
||||
TEST_CASE("uint64 from string") {
|
||||
REQUIRE(StringTo<uint64_t>("0") == 0);
|
||||
REQUIRE(StringTo<uint64_t>("5") == 5u);
|
||||
REQUIRE(StringTo<uint64_t>("16") == 16u);
|
||||
REQUIRE(StringTo<uint64_t>("20") == 20u);
|
||||
REQUIRE(StringTo<uint64_t>("0x14") == 20u);
|
||||
REQUIRE(StringTo<uint64_t>("0x15") == 21u);
|
||||
REQUIRE(StringTo<uint64_t>("0xffffff") == 0xffffff);
|
||||
}
|
||||
|
||||
TEST_CASE("int from string") {
|
||||
REQUIRE(StringTo<int>("-1") == -1);
|
||||
REQUIRE(StringTo<int>("-0x1") == -0x1);
|
||||
REQUIRE(StringTo<int>("-0x1") == -1);
|
||||
REQUIRE(StringTo<int>("0") == 0);
|
||||
REQUIRE(StringTo<int>("5") == 5);
|
||||
REQUIRE(StringTo<int>("16") == 16);
|
||||
REQUIRE(StringTo<int>("20") == 20);
|
||||
REQUIRE(StringTo<int>("0x14") == 20);
|
||||
REQUIRE(StringTo<int>("0x15") == 21);
|
||||
REQUIRE(StringTo<int>("0xffffff") == 0xffffff);
|
||||
}
|
||||
|
||||
TEST_CASE("std::map of strings") {
|
||||
std::map<std::string, std::string> m;
|
||||
m["key"] = "value";
|
||||
auto s = ToString(m);
|
||||
REQUIRE(s == "{key: value}");
|
||||
|
||||
m["chrusi"] = "musi";
|
||||
REQUIRE(ToString(m) == "{chrusi: musi, key: value}");
|
||||
|
||||
m["test"] = "tree";
|
||||
REQUIRE(ToString(m) == "{chrusi: musi, key: value, test: tree}");
|
||||
}
|
||||
|
||||
TEST_CASE("Formatting ROI") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 5;
|
||||
roi.xmax = 159;
|
||||
roi.ymin = 6;
|
||||
roi.ymax = 170;
|
||||
REQUIRE(ToString(roi) == "[5, 159, 6, 170]");
|
||||
}
|
||||
|
||||
TEST_CASE("Streaming of ROI") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 50;
|
||||
roi.xmax = 109;
|
||||
roi.ymin = 6;
|
||||
roi.ymax = 130;
|
||||
std::ostringstream oss;
|
||||
oss << roi;
|
||||
REQUIRE(oss.str() == "[50, 109, 6, 130]");
|
||||
}
|
||||
|
||||
// TODO: After StringTo<scanParameters> is implemented
|
||||
/*TEST_CASE("Streaming of scanParameters") {
|
||||
using namespace sls;
|
||||
{
|
||||
aare::scanParameters t{};
|
||||
std::ostringstream oss;
|
||||
oss << t;
|
||||
REQUIRE(oss.str() == "[disabled]");
|
||||
}
|
||||
{
|
||||
aare::scanParameters t{defs::VTH2, 500, 1500, 500};
|
||||
std::ostringstream oss;
|
||||
oss << t;
|
||||
REQUIRE(oss.str() == "[enabled\ndac vth2\nstart 500\nstop 1500\nstep "
|
||||
"500\nsettleTime 1ms\n]");
|
||||
}
|
||||
{
|
||||
aare::scanParameters t{defs::VTH2, 500, 1500, 500,
|
||||
std::chrono::milliseconds{500}};
|
||||
std::ostringstream oss;
|
||||
oss << t;
|
||||
REQUIRE(oss.str() == "[enabled\ndac vth2\nstart 500\nstop 1500\nstep "
|
||||
"500\nsettleTime 0.5s\n]");
|
||||
}
|
||||
}*/
|
Reference in New Issue
Block a user