Reject raw files without padding if discard partial is not set (#374)
Build on RHEL9 / build (push) Successful in 3m3s
Build on RHEL8 / build (push) Successful in 3m25s
Run tests using data on local RHEL8 / build (push) Successful in 4m21s
Build on local RHEL8 / build (push) Successful in 3m5s

We have no code in aare to deal with RawFiles that have missing packets
if they are not padded to full size or frames with packet loss dropped.

Added: 
- check that we don't try to read files that are not supported
- python bindings for frame discard policy

at least we get the check in: 
closes #171

---------

Co-authored-by: AliceMazzoleni99 <alice.mazzoleni@psi.ch>
This commit is contained in:
Erik Fröjdh
2026-09-18 17:06:11 +02:00
committed by GitHub
co-authored by mazzol_a
parent 97ddf6e7c1
commit 0dc72634a9
12 changed files with 181 additions and 8 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ from ._aare import (
RawSubFile,
)
from ._aare import Pedestal_d, Pedestal_f, ClusterFinder_Cluster3x3i, VarClusterFinder
from ._aare import DetectorType, ReadoutMode
from ._aare import DetectorType, FrameDiscardPolicy, ReadoutMode
from ._aare import hitmap
from ._aare import ROI
from ._aare import corner
+5
View File
@@ -95,4 +95,9 @@ void define_defs_bindings(py::module &m) {
.value("GATED", TimingMode::GATED)
.value("BURST_TRIGGER", TimingMode::BURST_TRIGGER)
.value("TRIGGER_GATED", TimingMode::TRIGGER_GATED);
py::enum_<FrameDiscardPolicy>(m, "FrameDiscardPolicy")
.value("NoDiscard", FrameDiscardPolicy::NoDiscard)
.value("Discard", FrameDiscardPolicy::Discard)
.value("DiscardPartial", FrameDiscardPolicy::DiscardPartial);
}
+55
View File
@@ -28,6 +28,61 @@ def small_raw_file(tmp_path):
return master_path
@pytest.mark.parametrize("reader_type", [RawFile, File])
@pytest.mark.parametrize("legacy_master", [False, True])
@pytest.mark.parametrize("padding, policy, supported", [
(0, "nodiscard", False),
(0, "discard", False),
(0, "discardpartial", True),
(1, "nodiscard", True),
(1, "discard", True),
(1, "discardpartial", True),
])
def test_raw_frame_policy(small_raw_file, reader_type, legacy_master,
padding, policy, supported):
master_path = small_raw_file
if legacy_master:
master_path = master_path.with_suffix(".raw")
master_path.write_text(
"Version : 6.4\n"
"Detector Type : Jungfrau\n"
"Timing Mode : auto\n"
"Geometry : [1, 1]\n"
"Image Size : 12\n"
"Pixels : [3, 2]\n"
"Dynamic Range : 16\n"
"Max Frames Per File : 1\n"
"Total Frames : 2\n"
"Frames in File : 2\n"
f"Frame Padding : {padding}\n"
f"Frame Discard Policy : {policy}\n"
)
else:
metadata = json.loads(master_path.read_text())
metadata["Frame Padding"] = padding
metadata["Frame Discard Policy"] = policy
master_path.write_text(json.dumps(metadata))
if supported:
reader = reader_type(master_path)
assert reader.total_frames == 2
frame = reader.read_frame()
if reader_type is RawFile:
_, frame = frame
np.testing.assert_array_equal(frame, np.arange(6).reshape(2, 3))
else:
message = "requires frame padding or discardpartial"
with pytest.raises(RuntimeError, match=message) as error:
reader_type(master_path)
assert str(master_path) in str(error.value)
for index in range(2):
(master_path.parent / f"run_d0_f{index}_0.raw").unlink()
with pytest.raises(RuntimeError, match=message) as error:
reader_type(master_path)
assert str(master_path) in str(error.value)
@pytest.mark.parametrize("method, args, kwargs", [
("read_frame", (), {}),
("read_n", (1,), {}),
+14 -3
View File
@@ -3,7 +3,7 @@
import json
import pytest
from aare import RawMasterFile, ReadoutMode, DetectorType
from aare import RawMasterFile, ReadoutMode, DetectorType, FrameDiscardPolicy
@pytest.mark.withdata
@@ -16,7 +16,15 @@ def test_read_rawfile_quad_eiger_and_compare_to_numpy(test_data_path):
assert(f.detector_type == DetectorType.Jungfrau)
def test_raw_master_file_context_manager(tmp_path):
@pytest.mark.parametrize(
"policy, expected_policy",
[
("nodiscard", FrameDiscardPolicy.NoDiscard),
("discard", FrameDiscardPolicy.Discard),
("discardpartial", FrameDiscardPolicy.DiscardPartial),
],
)
def test_raw_master_file_context_manager(tmp_path, policy, expected_policy):
file_name = tmp_path / "run_master_0.json"
file_name.write_text(json.dumps({
"Version": 7.2,
@@ -29,10 +37,13 @@ def test_raw_master_file_context_manager(tmp_path):
"Total Frames": 2,
"Frames in File": 2,
"Frame Padding": 1,
"Frame Discard Policy": "nodiscard",
"Frame Discard Policy": policy,
}))
with RawMasterFile(file_name) as context_file:
assert context_file.reading_mode == ReadoutMode.UNKNOWN
assert context_file.detector_type == DetectorType.Jungfrau
frame_discard_policy = context_file.frame_discard_policy
assert isinstance(frame_discard_policy, FrameDiscardPolicy)
assert frame_discard_policy == expected_policy