mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2026-09-03 01:20:43 +02:00
Merge branch 'main' into dev/strixels/remap_simple
This commit is contained in:
+7
-17
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user