From 5819d6b1fd3ef811fc2f1c20d23b99c1007e9726 Mon Sep 17 00:00:00 2001 From: x01dc Date: Thu, 29 Oct 2026 11:24:05 +0100 Subject: [PATCH] fix(aerotech): limit abort explains the run-up separately from the scan range The message now says whether the scan range itself is outside the limits or only the extra run-up travel for acceleration and settling, by how much, and what to do about it. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01M8zoDzDfsCTY2o5bT3J7Wv --- .../scans/scans_v4/aerotech_cont_grid.py | 25 ++++++++++++++----- .../test_aerotech_cont_grid_scan.py | 11 +++++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/csaxs_bec/scans/scans_v4/aerotech_cont_grid.py b/csaxs_bec/scans/scans_v4/aerotech_cont_grid.py index db384575..ba9a5523 100644 --- a/csaxs_bec/scans/scans_v4/aerotech_cont_grid.py +++ b/csaxs_bec/scans/scans_v4/aerotech_cont_grid.py @@ -506,14 +506,27 @@ class AerotechContGrid(ScanBase): def _check_line_limits(self): """The lines including run-up / run-out and the step axis range must fit the limits.""" line = self._line + name = self.fast_axis.name low, high = self.fast_axis.limits - if low < high and (line["line_start"] < low or line["line_end"] > high): - run_up = line["trigger_low"] - line["line_start"] + if low < high and (self.fast_start < low or self.fast_end > high): raise ScanAbortion( - f"{self.fast_axis.name} range {line['line_start']:.4f} .. {line['line_end']:.4f}" - f" (including {run_up:.4f} run-up / run-out on each side at" - f" {line['target_velocity']} / s, acceleration {line['acceleration']} / s^2)" - f" is outside the limits ({low}, {high})." + f"Scan range of {name} {self.fast_start:.4f} .. {self.fast_end:.4f} is outside" + f" the limits ({low}, {high})." + ) + if low < high and (line["line_start"] < low or line["line_end"] > high): + extra = self.fast_start - line["line_start"] + if line["line_end"] > high: + beyond = f"beyond the high limit {high} by {line['line_end'] - high:.4f}" + else: + beyond = f"beyond the low limit {low} by {low - line['line_start']:.4f}" + raise ScanAbortion( + f"The scan range of {name} {self.fast_start:.4f} .. {self.fast_end:.4f} is" + f" within the limits, but {name} needs {extra:.4f} extra travel on each side" + f" to accelerate to the scan velocity {line['target_velocity']:g} / s and" + f" settle (acceleration {line['acceleration']:g} / s^2, settle_time" + f" {self.settle_time:g} s). It would travel {line['line_start']:.4f} .." + f" {line['line_end']:.4f}, {beyond}. Move the scan away from the limit or" + " scan slower (larger exp_time or smaller fast_step_size)." ) low, high = self.stepper_axis.limits stepper_range = sorted((self.stepper_start, self.stepper_stop)) diff --git a/tests/tests_scans/test_aerotech_cont_grid_scan.py b/tests/tests_scans/test_aerotech_cont_grid_scan.py index 6dcdf027..f775af0d 100644 --- a/tests/tests_scans/test_aerotech_cont_grid_scan.py +++ b/tests/tests_scans/test_aerotech_cont_grid_scan.py @@ -207,7 +207,16 @@ def test_run_up_outside_limits_aborts(v4_scan_assembler, device_manager): scan = v4_scan_assembler( "aerotech_cont_grid", "aerox", -4.0, 4.0, 0.1, "aeroy", -2.0, 2.0, 2, exp_time=0.005 ) - with pytest.raises(ScanAbortion, match="run-up"): + with pytest.raises(ScanAbortion, match="within the limits, but aerox needs .* extra travel"): + scan.prepare_scan() + + +def test_scan_range_outside_limits_aborts(v4_scan_assembler, device_manager): + _add_devices(device_manager) + scan = v4_scan_assembler( + "aerotech_cont_grid", "aerox", -1.0, 11.0, 0.5, "aeroy", -2.0, 2.0, 2, exp_time=0.1 + ) + with pytest.raises(ScanAbortion, match="Scan range of aerox"): scan.prepare_scan()