fix(lamni): arm ddg1 for external triggering in lamni_fermat_scan
CI for csaxs_bec / test (push) Successful in 3m1s

Switch ddg1 to EXT_RISING_EDGE in pre_scan and back to SINGLE_SHOT in
post_scan and on_exception, as flomni_fermat_scan already does. Without
this the RT controller triggers never reached the detectors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
x12saandClaude Opus 5.5 committed 2026-10-13 13:54:47 +02:00
1 parent ca96f41a45
commit 0866f1007c
2 files changed
+30

No files matched your search

+5
View File
@@ -26,6 +26,7 @@ from bec_server.scan_server.errors import ScanAbortion
from bec_server.scan_server.scans.scan_base import ScanBase, ScanType
from bec_server.scan_server.scans.scan_modifier import scan_hook
from csaxs_bec.devices.epics.delay_generator_csaxs.delay_generator_csaxs import TRIGGERSOURCE
from csaxs_bec.scans.fermat_spiral_utils import compute_fermat_spiral_n_max
from csaxs_bec.scans.lamni_components import LamNIComponents
@@ -206,6 +207,8 @@ class LamniFermatScan(ScanBase):
devices, e.g. devices that have a short timeout.
The pre-scan logic is typically implemented on the device itself.
"""
# Prepare DDG1 to be triggered externally by the RT controller
self.dev.ddg1.set_trigger(TRIGGERSOURCE.EXT_RISING_EDGE.value)
self.actions.pre_scan_all_devices()
@scan_hook
@@ -236,6 +239,7 @@ class LamniFermatScan(ScanBase):
Post-scan steps to be executed after the main scan logic.
"""
self.actions.complete_all_devices()
self.dev.ddg1.set_trigger(TRIGGERSOURCE.SINGLE_SHOT.value)
@scan_hook
def unstage(self):
@@ -257,6 +261,7 @@ class LamniFermatScan(ScanBase):
This is a good place to implement any cleanup logic that needs to be executed in case of an exception,
such as returning the devices to a safe state or moving the motors back to their starting position.
"""
self.dev.ddg1.set_trigger(TRIGGERSOURCE.SINGLE_SHOT.value)
#######################################################
######### Helper methods for the scan logic ###########
@@ -95,3 +95,28 @@ def test_shift_and_center_are_mm_and_positions_are_um():
np.testing.assert_allclose(shifted_x - base, [[10.0, 0.0]] * len(base), atol=1e-9)
np.testing.assert_allclose(shifted_y - base, [[0.0, 5.0]] * len(base), atol=1e-9)
np.testing.assert_allclose(centered_x - base, [[10.0, 0.0]] * len(base), atol=1e-9)
def test_ddg1_armed_in_pre_scan_and_reset_after_scan():
"""ddg1 must be switched to external triggering before the devices are pre-scanned,
and back to single shot after the scan and on exceptions."""
from csaxs_bec.devices.epics.delay_generator_csaxs.delay_generator_csaxs import TRIGGERSOURCE
scan = mock.MagicMock()
manager = mock.MagicMock()
manager.attach_mock(scan.dev.ddg1.set_trigger, "set_trigger")
manager.attach_mock(scan.actions.pre_scan_all_devices, "pre_scan_all_devices")
LamniFermatScan.pre_scan(scan)
assert manager.mock_calls == [
mock.call.set_trigger(TRIGGERSOURCE.EXT_RISING_EDGE.value),
mock.call.pre_scan_all_devices(),
]
scan.dev.ddg1.set_trigger.reset_mock()
LamniFermatScan.post_scan(scan)
scan.dev.ddg1.set_trigger.assert_called_once_with(TRIGGERSOURCE.SINGLE_SHOT.value)
scan.dev.ddg1.set_trigger.reset_mock()
LamniFermatScan.on_exception(scan, RuntimeError("boom"))
scan.dev.ddg1.set_trigger.assert_called_once_with(TRIGGERSOURCE.SINGLE_SHOT.value)