Merge branch 'main' into dev/strixels/remap_simple
Build on RHEL9 / build (push) Successful in 2m28s
Build on RHEL8 / build (push) Successful in 3m10s
Run tests using data on local RHEL8 / build (push) Successful in 3m59s

This commit is contained in:
2026-08-24 19:07:46 +02:00
8 changed files with 605 additions and 36 deletions
+7 -17
View File
@@ -500,9 +500,8 @@ endif()
add_custom_target(
check-format
COMMAND
find \\ (-name "*.cpp" -o -name "*.hpp" \\) -not -path "./build/*" | xargs
-I {} -n 1 -P 10 bash -c
"clang-format -Werror -style=\"file:.clang-format\" {} | diff {} -"
bash -c
[=[ find \( -name "*.cpp" -o -name "*.hpp" \) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -Werror -style=\"file:.clang-format\" {} | diff {} -" ]=]
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Checking code formatting with clang-format"
VERBATIM)
@@ -510,8 +509,8 @@ add_custom_target(
add_custom_target(
format-files
COMMAND
find \\ (-name "*.cpp" -o -name "*.hpp" \\) -not -path "./build/*" | xargs
-I {} -n 1 -P 10 bash -c "clang-format -i -style=\"file:.clang-format\" {}"
bash -c
[=[ find \( -name "*.cpp" -o -name "*.hpp" \) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -i -style=\"file:.clang-format\" {}" ]=]
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Formatting with clang-format"
VERBATIM)
@@ -526,18 +525,9 @@ endif()
add_custom_target(
clang-tidy
COMMAND
find \\ (-path
"./src/*"
-a
-not
-path
"./src/python/*"
-a
\\
(-name "*.cpp" -not -name "*.test.cpp" \\)
\\) -not -name "CircularFifo.hpp" -not -name
"ProducerConsumerQueue.hpp" -not -name "VariableSizeClusterFinder.hpp" |
xargs -I {} -n 1 -P 10 bash -c
find -path "./src/*" -not -path "./src/python/*" -not -name "*.test.cpp"
-not -name "CircularFifo.hpp" -not -name "ProducerConsumerQueue.hpp" -not
-name "VariableSizeClusterFinder.hpp" | xargs -I {} -n 1 -P 10 bash -c
"${CLANG_TIDY_COMMAND} --config-file=.clang-tidy -p build {}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "linting with clang-tidy"
+3
View File
@@ -12,6 +12,9 @@
evaluators. Model objects are callable and provide the replacement, for
example ``Gaussian()(x, par)``.
### Bugfixes:
- Fixed broken reading of old (pre reordering) Moench03
## 2026.7.2
+7 -6
View File
@@ -506,12 +506,13 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
return *this;
}
/**
* @brief Create a view of the NDArray.
*
* @return NDView<T, Ndim>
*/
NDView<T, Ndim> view() const { return NDView<T, Ndim>{data_, shape_}; }
/** @brief Create a mutable view of the NDArray. */
NDView<T, Ndim> view() { return NDView<T, Ndim>{data_, shape_}; }
/** @brief Create a read-only view of a const NDArray. */
NDView<const T, Ndim> view() const {
return NDView<const T, Ndim>{data_, shape_};
}
private:
/**
+2 -2
View File
@@ -45,7 +45,7 @@ template <typename SUM_TYPE = double> class Pedestal {
NDArray<SUM_TYPE, 2> mean() { return m_mean; }
const NDView<SUM_TYPE, 2> view() const { return m_mean.view(); }
NDView<const SUM_TYPE, 2> view() const { return m_mean.view(); }
SUM_TYPE mean(const uint32_t row, const uint32_t col) const {
return m_mean(row, col);
@@ -221,4 +221,4 @@ template <typename SUM_TYPE = double> class Pedestal {
m_mean(row, col) = m_sum(row, col) / m_samples;
}
};
} // namespace aare
} // namespace aare
+2 -2
View File
@@ -42,7 +42,7 @@ template <typename T, typename StorageType> class PixelHistogramImpl {
// Zero-copy view of the underlying [rows x cols x n_bins] storage.
// Lifetime is tied to *this. Use for low-level merge/stitching paths;
// prefer values() for the public API where you want an owned copy.
NDView<StorageType, 3> view() const;
NDView<const StorageType, 3> view() const;
NDArray<T, 1> bin_centers() const;
NDArray<T, 1> bin_edges() const;
};
@@ -122,7 +122,7 @@ NDArray<StorageType, 3> PixelHistogramImpl<T, StorageType>::values() const {
}
template <typename T, typename StorageType>
NDView<StorageType, 3> PixelHistogramImpl<T, StorageType>::view() const {
NDView<const StorageType, 3> PixelHistogramImpl<T, StorageType>::view() const {
return m_values.view();
}
+15
View File
@@ -4,6 +4,7 @@
#include <catch2/benchmark/catch_benchmark.hpp>
#include <catch2/catch_test_macros.hpp>
#include <numeric>
#include <type_traits>
using aare::NDArray;
using aare::NDView;
@@ -71,6 +72,20 @@ TEST_CASE("Accessing a const object") {
REQUIRE(img.shape(2) == 5);
}
TEST_CASE("A const NDArray returns a read-only view") {
NDArray<int, 2> mutable_array({2, 3}, 1);
const auto &const_array = mutable_array;
static_assert(
std::is_same_v<decltype(mutable_array.view()), NDView<int, 2>>);
static_assert(
std::is_same_v<decltype(const_array.view()), NDView<const int, 2>>);
auto view = const_array.view();
static_assert(std::is_same_v<decltype(view.data()), const int *>);
REQUIRE(view(1, 2) == 1);
}
TEST_CASE("Indexing of a 2D image") {
std::array<ssize_t, 2> shape{{3, 7}};
NDArray<long> img(shape, 5);
+21 -8
View File
@@ -303,18 +303,31 @@ void RawMasterFile::parse_json(std::istream &is) {
}
// ----------------------------------------------------------------
// Special treatment of analog flag because of Moench03
m_analog_flag = v < 8.0 && (m_type == DetectorType::Moench);
// Special treatment of analog flag because of Moench03.
// Before SW 8.0.0 (NOT json file version v8!) Moench03 had Analog Samples
// but no Analog Flag. Therefore we need to set analog flag to true and try
// to read analog samples The detector type is later set depending on analog
// samples and number of pixels.
try {
m_analog_flag = static_cast<bool>(j.at("Analog Flag").get<int>());
if (m_analog_flag) {
m_analog_samples = j.at("Analog Samples");
if (m_type == DetectorType::Moench) {
if (auto it = j.find("Analog Samples"); it != j.end()) {
m_analog_flag = true;
m_analog_samples = it->get<size_t>();
} else {
m_analog_flag = false;
}
} else {
if (auto it = j.find("Analog Flag"); it != j.end()) {
m_analog_flag = static_cast<bool>(it->get<int>());
if (m_analog_flag) {
m_analog_samples = j.at("Analog Samples");
}
} else {
m_analog_flag = false;
}
} catch (const json::out_of_range &e) {
// keep the optional empty
}
//-----------------------------------------------------------------
try {
m_quad = j.at("Quad");
} catch (const json::out_of_range &e) {
+548 -1
View File
@@ -411,6 +411,10 @@ TEST_CASE("Parse EIGER 7.2 master from string stream") {
REQUIRE(f.frame_padding() == 1);
REQUIRE(f.total_frames_expected() == 3);
REQUIRE(f.quad() == 0);
REQUIRE(f.number_of_rows() == 256);
REQUIRE(f.n_modules() == 4);
REQUIRE(f.bitdepth() == 32);
REQUIRE(f.frames_in_file() == 3);
@@ -489,9 +493,473 @@ TEST_CASE("Parse JUNGFRAU 7.2 master from string stream") {
REQUIRE(f.number_of_rows() == 512);
REQUIRE(f.frames_in_file() == 10);
REQUIRE(f.quad() == 0);
REQUIRE(f.n_modules() == 2);
REQUIRE(f.udp_interfaces_per_module() == xy{2, 1});
}
TEST_CASE(
"Parse CTB 7.2 master (SW 7.0.3) with analog samples from string stream") {
std::string master_content = R"({
"Version": 7.2,
"Timestamp": "Wed Aug 19 09:45:29 2026",
"Detector Type": "ChipTestBoard",
"Timing Mode": "auto",
"Geometry": {
"x": 1,
"y": 1
},
"Image Size in bytes": 192000,
"Pixels": {
"x": 32,
"y": 1
},
"Max Frames Per File": 20000,
"Frame Discard Policy": "nodiscard",
"Frame Padding": 1,
"Scan Parameters": "[disabled]",
"Total Frames": 1,
"Receiver Roi": {
"xmin": 4294967295,
"xmax": 4294967295,
"ymin": 4294967295,
"ymax": 4294967295
},
"Exptime": "0ns",
"Period": "1ms",
"Ten Giga": 0,
"ADC Mask": "0xffffffff",
"Analog Flag": 1,
"Analog Samples": 3000,
"Digital Flag": 0,
"Digital Samples": 2000,
"Dbit Offset": 0,
"Dbit Bitset": 0,
"Frames in File": 1,
"Frame Header Format": {
"Frame Number": "8 bytes",
"SubFrame Number/ExpLength": "4 bytes",
"Packet Number": "4 bytes",
"Bunch ID": "8 bytes",
"Timestamp": "8 bytes",
"Module Id": "2 bytes",
"Row": "2 bytes",
"Column": "2 bytes",
"Reserved": "2 bytes",
"Debug": "4 bytes",
"Round Robin Number": "2 bytes",
"Detector Type": "1 byte",
"Header Version": "1 byte",
"Packets Caught Mask": "64 bytes"
}
})";
std::istringstream iss(master_content);
RawMasterFile f(iss, "test_master_0.json");
REQUIRE(f.version() == "7.2");
REQUIRE(f.detector_type() == DetectorType::ChipTestBoard);
REQUIRE(f.timing_mode() == TimingMode::Auto);
REQUIRE(f.geometry() == xy{1, 1});
REQUIRE(f.image_size_in_bytes() == 192000);
REQUIRE(f.pixels_x() == 32);
REQUIRE(f.pixels_y() == 1);
REQUIRE(f.max_frames_per_file() == 20000);
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard);
REQUIRE(f.frame_padding() == 1);
REQUIRE(f.total_frames_expected() == 1);
REQUIRE(f.exptime() == std::chrono::nanoseconds(0));
REQUIRE(f.period() == std::chrono::milliseconds(1));
REQUIRE(f.analog_samples() == 3000);
REQUIRE(f.digital_samples() == std::nullopt);
REQUIRE(f.transceiver_samples() == std::nullopt);
REQUIRE(f.frames_in_file() == 1);
}
TEST_CASE(
"Parse CTB 7.2 master (SW 7.0.3) with digital samples from string stream") {
std::string master_content = R"({
"Version": 7.2,
"Timestamp": "Wed Aug 19 09:48:34 2026",
"Detector Type": "ChipTestBoard",
"Timing Mode": "auto",
"Geometry": {
"x": 1,
"y": 1
},
"Image Size in bytes": 16000,
"Pixels": {
"x": 64,
"y": 1
},
"Max Frames Per File": 20000,
"Frame Discard Policy": "nodiscard",
"Frame Padding": 1,
"Scan Parameters": "[disabled]",
"Total Frames": 1,
"Receiver Roi": {
"xmin": 4294967295,
"xmax": 4294967295,
"ymin": 4294967295,
"ymax": 4294967295
},
"Exptime": "0ns",
"Period": "1ms",
"Ten Giga": 0,
"ADC Mask": "0xffffffff",
"Analog Flag": 0,
"Analog Samples": 3000,
"Digital Flag": 1,
"Digital Samples": 2000,
"Dbit Offset": 0,
"Dbit Bitset": 0,
"Frames in File": 1,
"Frame Header Format": {
"Frame Number": "8 bytes",
"SubFrame Number/ExpLength": "4 bytes",
"Packet Number": "4 bytes",
"Bunch ID": "8 bytes",
"Timestamp": "8 bytes",
"Module Id": "2 bytes",
"Row": "2 bytes",
"Column": "2 bytes",
"Reserved": "2 bytes",
"Debug": "4 bytes",
"Round Robin Number": "2 bytes",
"Detector Type": "1 byte",
"Header Version": "1 byte",
"Packets Caught Mask": "64 bytes"
}
})";
std::istringstream iss(master_content);
RawMasterFile f(iss, "test_master_0.json");
REQUIRE(f.version() == "7.2");
REQUIRE(f.detector_type() == DetectorType::ChipTestBoard);
REQUIRE(f.timing_mode() == TimingMode::Auto);
REQUIRE(f.geometry() == xy{1, 1});
REQUIRE(f.image_size_in_bytes() == 16000);
REQUIRE(f.pixels_x() == 64);
REQUIRE(f.pixels_y() == 1);
REQUIRE(f.max_frames_per_file() == 20000);
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard);
REQUIRE(f.frame_padding() == 1);
REQUIRE(f.total_frames_expected() == 1);
REQUIRE(f.exptime() == std::chrono::nanoseconds(0));
REQUIRE(f.period() == std::chrono::milliseconds(1));
REQUIRE(f.analog_samples() == std::nullopt);
REQUIRE(f.digital_samples() == 2000);
REQUIRE(f.transceiver_samples() == std::nullopt);
REQUIRE(f.frames_in_file() == 1);
}
TEST_CASE("Parse Moench 7.2 master (SW 7.0.3) from string stream") {
std::string master_content = R"({
"Version": 7.2,
"Timestamp": "Wed Aug 19 10:32:06 2026",
"Detector Type": "Moench",
"Timing Mode": "auto",
"Geometry": {
"x": 1,
"y": 1
},
"Image Size in bytes": 320000,
"Pixels": {
"x": 400,
"y": 400
},
"Max Frames Per File": 100000,
"Frame Discard Policy": "nodiscard",
"Frame Padding": 1,
"Scan Parameters": "[disabled]",
"Total Frames": 1,
"Receiver Roi": {
"xmin": 4294967295,
"xmax": 4294967295,
"ymin": 4294967295,
"ymax": 4294967295
},
"Exptime": "20us",
"Period": "2ms",
"Ten Giga": 0,
"ADC Mask": "0xffffffff",
"Analog Samples": 5000,
"Frames in File": 1,
"Frame Header Format": {
"Frame Number": "8 bytes",
"SubFrame Number/ExpLength": "4 bytes",
"Packet Number": "4 bytes",
"Bunch ID": "8 bytes",
"Timestamp": "8 bytes",
"Module Id": "2 bytes",
"Row": "2 bytes",
"Column": "2 bytes",
"Reserved": "2 bytes",
"Debug": "4 bytes",
"Round Robin Number": "2 bytes",
"Detector Type": "1 byte",
"Header Version": "1 byte",
"Packets Caught Mask": "64 bytes"
}
})";
std::istringstream iss(master_content);
RawMasterFile f(iss, "test_master_0.json");
REQUIRE(f.version() == "7.2");
REQUIRE(f.detector_type() == DetectorType::Moench03_old);
REQUIRE(f.timing_mode() == TimingMode::Auto);
REQUIRE(f.geometry() == xy{1, 1});
REQUIRE(f.image_size_in_bytes() == 320000);
REQUIRE(f.pixels_x() == 400);
REQUIRE(f.pixels_y() == 400);
REQUIRE(f.max_frames_per_file() == 100000);
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard);
REQUIRE(f.frame_padding() == 1);
REQUIRE(f.total_frames_expected() == 1);
REQUIRE(f.exptime() == std::chrono::microseconds(20));
REQUIRE(f.period() == std::chrono::milliseconds(2));
REQUIRE(f.analog_samples() == 5000);
REQUIRE(f.digital_samples() == std::nullopt);
REQUIRE(f.transceiver_samples() == std::nullopt);
REQUIRE(f.frames_in_file() == 1);
}
TEST_CASE("Parse Moench 7.2 master (SW 8.0.0) from string stream") {
std::string master_content = R"({
"Version": 7.2,
"Timestamp": "Wed Aug 19 09:54:53 2026",
"Detector Type": "Moench",
"Timing Mode": "auto",
"Geometry": {
"x": 1,
"y": 1
},
"Image Size in bytes": 320000,
"Pixels": {
"x": 400,
"y": 400
},
"Max Frames Per File": 100000,
"Frame Discard Policy": "discardpartial",
"Frame Padding": 1,
"Scan Parameters": "[disabled]",
"Total Frames": 1,
"Receiver Roi": {
"xmin": 4294967295,
"xmax": 4294967295,
"ymin": 4294967295,
"ymax": 4294967295
},
"Exptime": "10us",
"Period": "2ms",
"Number of UDP Interfaces": 1,
"Number of rows": 400,
"Frames in File": 1,
"Frame Header Format": {
"Frame Number": "8 bytes",
"SubFrame Number/ExpLength": "4 bytes",
"Packet Number": "4 bytes",
"Bunch ID": "8 bytes",
"Timestamp": "8 bytes",
"Module Id": "2 bytes",
"Row": "2 bytes",
"Column": "2 bytes",
"Reserved": "2 bytes",
"Debug": "4 bytes",
"Round Robin Number": "2 bytes",
"Detector Type": "1 byte",
"Header Version": "1 byte",
"Packets Caught Mask": "64 bytes"
}
})";
std::istringstream iss(master_content);
RawMasterFile f(iss, "test_master_0.json");
REQUIRE(f.version() == "7.2");
REQUIRE(f.detector_type() == DetectorType::Moench03);
REQUIRE(f.timing_mode() == TimingMode::Auto);
REQUIRE(f.geometry() == xy{1, 1});
REQUIRE(f.image_size_in_bytes() == 320000);
REQUIRE(f.pixels_x() == 400);
REQUIRE(f.pixels_y() == 400);
REQUIRE(f.max_frames_per_file() == 100000);
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::DiscardPartial);
REQUIRE(f.frame_padding() == 1);
REQUIRE(f.total_frames_expected() == 1);
REQUIRE(f.exptime() == std::chrono::microseconds(10));
REQUIRE(f.period() == std::chrono::milliseconds(2));
REQUIRE(f.number_of_rows() == 400);
REQUIRE(f.frames_in_file() == 1);
REQUIRE(f.analog_samples() == std::nullopt);
REQUIRE(f.digital_samples() == std::nullopt);
REQUIRE(f.transceiver_samples() == std::nullopt);
REQUIRE(f.udp_interfaces_per_module() == xy{1, 1});
}
TEST_CASE("Parse CTB 7.2 master (SW 8.0.0) from string stream") {
std::string master_content = R"({
"Version": 7.2,
"Timestamp": "Wed Aug 19 09:56:30 2026",
"Detector Type": "ChipTestBoard",
"Timing Mode": "auto",
"Geometry": {
"x": 1,
"y": 1
},
"Image Size in bytes": 192000,
"Pixels": {
"x": 32,
"y": 1
},
"Max Frames Per File": 20000,
"Frame Discard Policy": "nodiscard",
"Frame Padding": 1,
"Scan Parameters": "[disabled]",
"Total Frames": 1,
"Receiver Roi": {
"xmin": 4294967295,
"xmax": 4294967295,
"ymin": 4294967295,
"ymax": 4294967295
},
"Exptime": "0ns",
"Period": "1ms",
"Ten Giga": 0,
"ADC Mask": "0xffffffff",
"Analog Flag": 1,
"Analog Samples": 3000,
"Digital Flag": 0,
"Digital Samples": 2000,
"Dbit Offset": 0,
"Dbit Bitset": 0,
"Transceiver Mask": "0x3",
"Transceiver Flag": 0,
"Transceiver Samples": 1,
"Frames in File": 1,
"Frame Header Format": {
"Frame Number": "8 bytes",
"SubFrame Number/ExpLength": "4 bytes",
"Packet Number": "4 bytes",
"Bunch ID": "8 bytes",
"Timestamp": "8 bytes",
"Module Id": "2 bytes",
"Row": "2 bytes",
"Column": "2 bytes",
"Reserved": "2 bytes",
"Debug": "4 bytes",
"Round Robin Number": "2 bytes",
"Detector Type": "1 byte",
"Header Version": "1 byte",
"Packets Caught Mask": "64 bytes"
}
})";
std::istringstream iss(master_content);
RawMasterFile f(iss, "test_master_0.json");
REQUIRE(f.version() == "7.2");
REQUIRE(f.detector_type() == DetectorType::ChipTestBoard);
REQUIRE(f.timing_mode() == TimingMode::Auto);
REQUIRE(f.geometry() == xy{1, 1});
REQUIRE(f.image_size_in_bytes() == 192000);
REQUIRE(f.pixels_x() == 32);
REQUIRE(f.pixels_y() == 1);
REQUIRE(f.max_frames_per_file() == 20000);
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard);
REQUIRE(f.frame_padding() == 1);
REQUIRE(f.total_frames_expected() == 1);
REQUIRE(f.exptime() == std::chrono::nanoseconds(0));
REQUIRE(f.period() == std::chrono::milliseconds(1));
REQUIRE(f.analog_samples() == 3000);
REQUIRE(f.digital_samples() == std::nullopt);
REQUIRE(f.transceiver_samples() == std::nullopt);
REQUIRE(f.frames_in_file() == 1);
}
TEST_CASE(
"Parse CTB 7.2 master (SW 8.0.0) with digital samples from string stream") {
std::string master_content = R"({
"Version": 7.2,
"Timestamp": "Wed Aug 19 09:58:22 2026",
"Detector Type": "ChipTestBoard",
"Timing Mode": "auto",
"Geometry": {
"x": 1,
"y": 1
},
"Image Size in bytes": 16000,
"Pixels": {
"x": 64,
"y": 1
},
"Max Frames Per File": 20000,
"Frame Discard Policy": "nodiscard",
"Frame Padding": 1,
"Scan Parameters": "[disabled]",
"Total Frames": 1,
"Receiver Roi": {
"xmin": 4294967295,
"xmax": 4294967295,
"ymin": 4294967295,
"ymax": 4294967295
},
"Exptime": "0ns",
"Period": "1ms",
"Ten Giga": 0,
"ADC Mask": "0xffffffff",
"Analog Flag": 0,
"Analog Samples": 3000,
"Digital Flag": 1,
"Digital Samples": 2000,
"Dbit Offset": 0,
"Dbit Bitset": 0,
"Transceiver Mask": "0x3",
"Transceiver Flag": 0,
"Transceiver Samples": 1,
"Frames in File": 1,
"Frame Header Format": {
"Frame Number": "8 bytes",
"SubFrame Number/ExpLength": "4 bytes",
"Packet Number": "4 bytes",
"Bunch ID": "8 bytes",
"Timestamp": "8 bytes",
"Module Id": "2 bytes",
"Row": "2 bytes",
"Column": "2 bytes",
"Reserved": "2 bytes",
"Debug": "4 bytes",
"Round Robin Number": "2 bytes",
"Detector Type": "1 byte",
"Header Version": "1 byte",
"Packets Caught Mask": "64 bytes"
}
})";
std::istringstream iss(master_content);
RawMasterFile f(iss, "test_master_0.json");
REQUIRE(f.version() == "7.2");
REQUIRE(f.detector_type() == DetectorType::ChipTestBoard);
REQUIRE(f.timing_mode() == TimingMode::Auto);
REQUIRE(f.geometry() == xy{1, 1});
REQUIRE(f.image_size_in_bytes() == 16000);
REQUIRE(f.pixels_x() == 64);
REQUIRE(f.pixels_y() == 1);
REQUIRE(f.max_frames_per_file() == 20000);
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard);
REQUIRE(f.frame_padding() == 1);
REQUIRE(f.total_frames_expected() == 1);
REQUIRE(f.exptime() == std::chrono::nanoseconds(0));
REQUIRE(f.period() == std::chrono::milliseconds(1));
REQUIRE(f.analog_samples() == std::nullopt);
REQUIRE(f.digital_samples() == 2000);
REQUIRE(f.transceiver_samples() == std::nullopt);
REQUIRE(f.frames_in_file() == 1);
}
TEST_CASE("Parse a CTB file from stream") {
std::string master_content = R"({
"Version": 8.0,
@@ -738,4 +1206,83 @@ TEST_CASE("Parse a v7.1 Mythen3 from stream") {
// Period is ok though
REQUIRE(f.period() == std::chrono::milliseconds(2));
}
}
TEST_CASE("Parse old Moench03 from stream") {
std::string master_content = R"(
{
"Version": 7.1,
"Timestamp": "Mon Mar 25 10:07:02 2024",
"Detector Type": "Moench",
"Timing Mode": "auto",
"Geometry": {
"x": 1,
"y": 1
},
"Image Size in bytes": 320000,
"Pixels": {
"x": 400,
"y": 400
},
"Max Frames Per File": 100000,
"Frame Discard Policy": "discardpartial",
"Frame Padding": 1,
"Scan Parameters": "[disabled]",
"Total Frames": 1000000,
"Receiver Roi": {
"xmin": 4294967295,
"xmax": 4294967295,
"ymin": 4294967295,
"ymax": 4294967295
},
"Exptime": "50us",
"Period": "600us",
"Ten Giga": 1,
"ADC Mask": "0xffffffff",
"Analog Samples": 5000,
"Additional Json Header": "{detectorMode: analog, frameMode: newPedestal}",
"Frames in File": 999995,
"Frame Header Format": {
"Frame Number": "8 bytes",
"SubFrame Number/ExpLength": "4 bytes",
"Packet Number": "4 bytes",
"Bunch ID": "8 bytes",
"Timestamp": "8 bytes",
"Module Id": "2 bytes",
"Row": "2 bytes",
"Column": "2 bytes",
"Reserved": "2 bytes",
"Debug": "4 bytes",
"Round Robin Number": "2 bytes",
"Detector Type": "1 byte",
"Header Version": "1 byte",
"Packets Caught Mask": "64 bytes"
}
}
)";
std::istringstream iss(master_content);
RawMasterFile f(iss, "test_master_0.json");
REQUIRE(f.version() == "7.1");
REQUIRE(f.detector_type() == DetectorType::Moench03_old);
REQUIRE(f.timing_mode() == TimingMode::Auto);
REQUIRE(f.geometry().col == 1);
REQUIRE(f.geometry().row == 1);
REQUIRE(f.image_size_in_bytes() == 320000);
REQUIRE(f.pixels_x() == 400);
REQUIRE(f.pixels_y() == 400);
REQUIRE(f.max_frames_per_file() == 100000);
REQUIRE((f.total_frames_expected() ==
1000000)); // This is Total Frames in the master file
REQUIRE(f.frames_in_file() == 999995);
REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::DiscardPartial);
REQUIRE(f.frame_padding() == 1);
REQUIRE(f.n_modules() == 1);
REQUIRE(f.quad() == 0);
REQUIRE(f.bitdepth() == 16);
REQUIRE(f.exptime() == std::chrono::microseconds(50));
REQUIRE(f.period() == std::chrono::microseconds(600));
REQUIRE(f.analog_samples() == 5000);
}