Panel id on spots and the panel table in the start message
SpotToSave gains int16_t panel (-1 = no panel table). It sits in the padding after the two bools, so sizeof(SpotToSave) stays 80. It is serialised only where it is set: CBOR spot key "panel", HDF5 /entry/MX/peakPanel (data file, plus a virtual dataset in a VDS master when the start message has panels), read back by HDF5MetadataSource. For a flat detector none of these is written, so files and streams for existing data are byte-for-byte unchanged. The start message carries the panel table (detector_modules, CBOR key absent when empty), filled from the experiment; JFJochHttpReader takes it, so a stream viewer knows the panels too. AssignModules takes the spot's panel id where it has one - the stored pixel box it was found in - and falls back to the plane position otherwise (every spot until per-panel spot finding sets the id). Reflection deliberately gets no panel id (owner decision): it is needed only between prediction and integration, and the struct feeds GPU layout and memory budgets. Tests: CBORSerialize_SpotPanelId, CBORSerialize_StartDetectorModules, JFJochReader_PanelId (VDS/legacy/integrated, with and without panels). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
This commit is contained in:
1 parent
c8fb472f4d
commit
dc784c073d
15 files changed
+274
-4
No files matched your search
@@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#include <algorithm>
|
||||
#include <catch2/catch_all.hpp>
|
||||
|
||||
#include "../frame_serialize/CBORStream2Serializer.h"
|
||||
@@ -1507,3 +1508,83 @@ TEST_CASE("CBORDeserialize_Start_CompressedLookupTable", "[CBOR]") {
|
||||
REQUIRE(deserialized->start_message);
|
||||
CHECK(deserialized->start_message->countrate_correction_lookup_table == lut);
|
||||
}
|
||||
|
||||
// The panel id of a spot is a CBOR key only for a detector with a panel table: a spot with panel -1
|
||||
// serialises to the same bytes as before the key existed.
|
||||
TEST_CASE("CBORSerialize_SpotPanelId", "[CBOR][PanelId]") {
|
||||
std::vector<uint8_t> buffer(1 << 20);
|
||||
const std::string key = "panel";
|
||||
std::vector<uint16_t> test(512);
|
||||
CompressedImage image(test, 256, 2);
|
||||
|
||||
auto serialize = [&](int16_t p0, int16_t p1) {
|
||||
CBORStream2Serializer serializer(buffer.data(), buffer.size());
|
||||
DataMessage message{
|
||||
.number = 1,
|
||||
.image = image,
|
||||
.spots = {SpotToSave{.x = 7, .y = 8, .intensity = 34, .panel = p0},
|
||||
SpotToSave{.x = 37, .y = 48, .intensity = 123, .panel = p1}}
|
||||
};
|
||||
serializer.SerializeImage(message);
|
||||
return std::vector<uint8_t>(buffer.begin(), buffer.begin() + serializer.GetBufferSize());
|
||||
};
|
||||
|
||||
const auto absent = serialize(-1, -1);
|
||||
CHECK(std::search(absent.begin(), absent.end(), key.begin(), key.end()) == absent.end());
|
||||
auto deserialized = CBORStream2Deserialize(absent.data(), absent.size());
|
||||
REQUIRE(deserialized->data_message);
|
||||
REQUIRE(deserialized->data_message->spots.size() == 2);
|
||||
CHECK(deserialized->data_message->spots[0].panel == -1);
|
||||
CHECK(deserialized->data_message->spots[1].panel == -1);
|
||||
|
||||
const auto present = serialize(3, 0);
|
||||
CHECK(std::search(present.begin(), present.end(), key.begin(), key.end()) != present.end());
|
||||
deserialized = CBORStream2Deserialize(present.data(), present.size());
|
||||
REQUIRE(deserialized->data_message);
|
||||
REQUIRE(deserialized->data_message->spots.size() == 2);
|
||||
CHECK(deserialized->data_message->spots[0].panel == 3);
|
||||
CHECK(deserialized->data_message->spots[1].panel == 0);
|
||||
CHECK(deserialized->data_message->spots[1].x == 37);
|
||||
}
|
||||
|
||||
// The start message carries the panel table only when there is one.
|
||||
TEST_CASE("CBORSerialize_StartDetectorModules", "[CBOR][PanelId]") {
|
||||
std::vector<uint8_t> buffer(8 * 1024 * 1024);
|
||||
const std::string key = "detector_modules";
|
||||
|
||||
StartMessage message{};
|
||||
message.image_size_x = 256;
|
||||
message.image_size_y = 128;
|
||||
{
|
||||
CBORStream2Serializer serializer(buffer.data(), buffer.size());
|
||||
serializer.SerializeSequenceStart(message);
|
||||
CHECK(std::search(buffer.begin(), buffer.begin() + serializer.GetBufferSize(), key.begin(), key.end())
|
||||
== buffer.begin() + serializer.GetBufferSize());
|
||||
auto deserialized = CBORStream2Deserialize(buffer.data(), serializer.GetBufferSize());
|
||||
REQUIRE(deserialized->start_message);
|
||||
CHECK(deserialized->start_message->detector_modules.empty());
|
||||
}
|
||||
|
||||
DetectorModule turned{.x0 = 0, .y0 = 64, .width = 256, .height = 64,
|
||||
.ox = 300.25, .oy = -12.5, .fx = 0, .fy = 1, .sx = -1, .sy = 0};
|
||||
message.detector_modules = {DetectorModule::AsImaged(0, 0, 256, 64), turned};
|
||||
{
|
||||
CBORStream2Serializer serializer(buffer.data(), buffer.size());
|
||||
serializer.SerializeSequenceStart(message);
|
||||
auto deserialized = CBORStream2Deserialize(buffer.data(), serializer.GetBufferSize());
|
||||
REQUIRE(deserialized->start_message);
|
||||
const auto &m = deserialized->start_message->detector_modules;
|
||||
REQUIRE(m.size() == 2);
|
||||
CHECK(m[0].x0 == 0);
|
||||
CHECK(m[0].height == 64);
|
||||
CHECK(m[0].fx == 1);
|
||||
CHECK(m[1].y0 == 64);
|
||||
CHECK(m[1].width == 256);
|
||||
CHECK(m[1].ox == 300.25);
|
||||
CHECK(m[1].oy == -12.5);
|
||||
CHECK(m[1].fx == 0);
|
||||
CHECK(m[1].fy == 1);
|
||||
CHECK(m[1].sx == -1);
|
||||
CHECK(m[1].sy == 0);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user