fix(timepix_scan): reject empty on/off windows and test argument validation
This commit is contained in:
1 parent
26e268aef1
commit
ef8bf026f1
2 files changed
+86
-8
No files matched your search
@@ -47,20 +47,23 @@ class TimepixScan(LineScan):
|
||||
# fmt: off
|
||||
time_roi_step: Annotated[int, ScanArgument(display_name="Time ROI step", description="Bin size", gt=0)],
|
||||
time_roi_n: Annotated[int, ScanArgument(display_name="Time ROI n", description="Number of time points", gt=0)],
|
||||
idx_off_start: Annotated[int, ScanArgument(display_name="Index Off Start", description="Start Index for Off Level", ge=0)],
|
||||
idx_off_stop: Annotated[int, ScanArgument(display_name="Index Off Stop", description="Stop Index for Off Level", ge=0)],
|
||||
idx_on_start: Annotated[int, ScanArgument(display_name="Index On Start", description="Start Index for On Level", ge=0)],
|
||||
idx_on_stop: Annotated[int, ScanArgument(display_name="Index On Stop", description="Stop Index for On Level", ge=0)],
|
||||
idx_off_start: Annotated[int, ScanArgument(display_name="Index Off Start", description="Start Index for Off Level (first time bin)", ge=0)],
|
||||
idx_off_stop: Annotated[int, ScanArgument(display_name="Index Off Stop", description="Stop Index for Off Level (exclusive)", ge=0)],
|
||||
idx_on_start: Annotated[int, ScanArgument(display_name="Index On Start", description="Start Index for On Level (first time bin)", ge=0)],
|
||||
idx_on_stop: Annotated[int, ScanArgument(display_name="Index On Stop", description="Stop Index for On Level (exclusive)", ge=0)],
|
||||
# fmt: on
|
||||
**kwargs,
|
||||
):
|
||||
if idx_off_start > idx_off_stop:
|
||||
# The on/off windows are half-open index ranges [start, stop) over the time_roi_n time
|
||||
# bins; the Timepix device averages each window into xes_level_*. An empty window
|
||||
# (start == stop) would only produce NaN, so it is rejected here as well.
|
||||
if idx_off_start >= idx_off_stop:
|
||||
raise ValueError(
|
||||
f"idx_off_start ({idx_off_start}) cannot be bigger than idx_off_stop ({idx_off_stop})!"
|
||||
f"idx_off_start ({idx_off_start}) must be smaller than idx_off_stop ({idx_off_stop})!"
|
||||
)
|
||||
if idx_on_start > idx_on_stop:
|
||||
if idx_on_start >= idx_on_stop:
|
||||
raise ValueError(
|
||||
f"idx_on_start ({idx_on_start}) cannot be bigger than idx_on_stop ({idx_on_stop})!"
|
||||
f"idx_on_start ({idx_on_start}) must be smaller than idx_on_stop ({idx_on_stop})!"
|
||||
)
|
||||
for name, idx in (
|
||||
("idx_off_start", idx_off_start),
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# pylint: skip-file
|
||||
import pytest
|
||||
from bec_lib.bec_errors import ScanInputValidationError
|
||||
from bec_server.scan_server.tests.scan_fixtures import *
|
||||
|
||||
from superxas_bec.scans.timepix_scan import TimepixScan
|
||||
|
||||
TIMEPIX_PARAMETERS = {
|
||||
"time_roi_step": 1,
|
||||
"time_roi_n": 10,
|
||||
"idx_off_start": 0,
|
||||
"idx_off_stop": 4,
|
||||
"idx_on_start": 5,
|
||||
"idx_on_stop": 10,
|
||||
}
|
||||
|
||||
|
||||
def _assemble_timepix_scan(scan_assembler, **overrides):
|
||||
params = {**TIMEPIX_PARAMETERS, **overrides}
|
||||
return scan_assembler(
|
||||
"timepix_scan", "samx", -1.0, 1.0, steps=3, relative=False, exp_time=0.1, **params
|
||||
)
|
||||
|
||||
|
||||
def test_timepix_scan_forwards_parameters_to_scan_info(scan_assembler):
|
||||
"""The Timepix device reads the parameters from additional_scan_parameters."""
|
||||
scan = _assemble_timepix_scan(scan_assembler)
|
||||
|
||||
assert isinstance(scan, TimepixScan)
|
||||
assert scan.scan_info.scan_name == "timepix_scan"
|
||||
for name, value in TIMEPIX_PARAMETERS.items():
|
||||
assert scan.scan_info.additional_scan_parameters[name] == value
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"overrides, match",
|
||||
[
|
||||
({"idx_off_start": 5, "idx_off_stop": 4}, "idx_off_start"),
|
||||
({"idx_on_start": 9, "idx_on_stop": 6}, "idx_on_start"),
|
||||
# start == stop would be an empty window
|
||||
({"idx_off_start": 3, "idx_off_stop": 3}, "idx_off_start"),
|
||||
({"idx_on_start": 7, "idx_on_stop": 7}, "idx_on_start"),
|
||||
],
|
||||
)
|
||||
def test_timepix_scan_rejects_start_not_smaller_than_stop(scan_assembler, overrides, match):
|
||||
with pytest.raises(ValueError, match=match):
|
||||
_assemble_timepix_scan(scan_assembler, **overrides)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"overrides, name",
|
||||
[
|
||||
({"idx_off_stop": 11}, "idx_off_stop"),
|
||||
({"idx_on_stop": 11}, "idx_on_stop"),
|
||||
({"idx_on_start": 11, "idx_on_stop": 12}, "idx_on_start"),
|
||||
],
|
||||
)
|
||||
def test_timepix_scan_rejects_index_above_time_roi_n(scan_assembler, overrides, name):
|
||||
with pytest.raises(ValueError, match=f"{name} with value"):
|
||||
_assemble_timepix_scan(scan_assembler, **overrides)
|
||||
|
||||
|
||||
def test_timepix_scan_accepts_stop_equal_to_time_roi_n(scan_assembler):
|
||||
"""stop is exclusive, so a window may end at time_roi_n."""
|
||||
scan = _assemble_timepix_scan(scan_assembler, idx_on_start=9, idx_on_stop=10)
|
||||
|
||||
assert scan.scan_info.additional_scan_parameters["idx_on_stop"] == 10
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"overrides", [{"idx_off_start": -1}, {"time_roi_n": 0}, {"time_roi_step": 0}]
|
||||
)
|
||||
def test_timepix_scan_argument_bounds_are_validated(scan_assembler, overrides):
|
||||
with pytest.raises(ScanInputValidationError):
|
||||
_assemble_timepix_scan(scan_assembler, **overrides)
|
||||
Reference in new issue
Block a user