fix(cont-grid): fix cont grid timing issue
CI for csaxs_bec / test (push) Failing after 1m23s

This commit is contained in:
2026-06-19 13:54:11 +02:00
parent 778c3c6bf1
commit 91e611fec9
4 changed files with 56 additions and 9 deletions
@@ -135,7 +135,12 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
device_manager (DeviceManagerBase | None, optional): Device manager. Defaults to None.
"""
USER_ACCESS = ["keep_shutter_open_during_scan", "set_trigger", "get_shutter_to_open_delay"]
USER_ACCESS = [
"keep_shutter_open_during_scan",
"set_trigger",
"get_shutter_to_open_delay",
"prepare_mcs_on_trigger",
]
# TODO Consider using the 'fsh' device instead.
fast_shutter_readback = Cpt(
@@ -359,7 +364,7 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
time.sleep(0.2)
logger.info(f"DDG {self.name} on_stage completed in {time.time() - start_time:.3f}s.")
def _prepare_mcs_on_trigger(self, mcs: MCSCardCSAXS) -> None:
def prepare_mcs_on_trigger(self, mcs: MCSCardCSAXS) -> None:
"""
This method is used by the DDG1 on_trigger method to prepare the MCS card for the next trigger.
@@ -508,6 +508,7 @@ class DelayGeneratorCSAXS(Device):
EpicsSignal,
"TriggerDelayBO",
name="trigger_shot",
use_complete=True,
kind=Kind.omitted,
doc="Software trigger, needs to be in correct mode to work",
)
@@ -97,7 +97,7 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
prefix (str, optional): Prefix for the EPICS PVs. Defaults to "".
"""
USER_ACCESS = ["mcs_recovery"]
USER_ACCESS = ["mcs_recovery", "get_transition_status", "get_compare_status"]
# NOTE The number of MCA channels is fixed to 32 for the CSAXS MCS card.
# On the IOC, we receive a 'warning' or 'error' once we set this channel for the
@@ -601,3 +601,32 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
# We restore the callback suppression after timeout to ensure proper operation afterwards.
with suppress_mca_callbacks(self, restore_after_timeout=sleep_time):
self.erase_all.put(1)
def get_transition_status(self, signal_name: str, transition: list) -> TransitionStatus:
"""
Get the transition status for a signal of the device.
Args:
signal_name: The name of the signal to check the transition status for.
transition (list): List of transitions to check.
"""
signal = getattr(self, signal_name, None)
if signal is None:
raise ValueError(f"Signal {signal_name} not found in device {self.name}.")
return TransitionStatus(signal, transition)
def get_compare_status(
self, signal_name: str, expected_value: any, operation_success: str = "=="
) -> CompareStatus:
"""
Get the compare status for a signal of the device.
Args:
signal_name: The name of the signal to check the compare status for.
expected_value: The expected value to compare against.
operation_success: The comparison operation to use. Defaults to "==".
"""
signal = getattr(self, signal_name, None)
if signal is None:
raise ValueError(f"Signal {signal_name} not found in device {self.name}.")
return CompareStatus(signal, expected_value, operation_success=operation_success)
+18 -6
View File
@@ -265,10 +265,21 @@ class ContGrid(ScanBase):
"""
# Only use every second position, at each point will use
for line_index in range(self._cont_motor_params["num_lines"]):
self.actions.set(
self.motors, [self.fast_start, self.positions[line_index][1]], wait=True
status_mcs = self.ddg1.prepare_mcs_on_trigger()
status_motor = self.actions.set(
self.motors, [self.fast_start, self.positions[line_index][1]]
)
status_motor.wait()
status_mcs.wait()
mcs_aquiring_status = self.mcs.get_transition_status(
signal="acquiring", transition=[1, 0]
)
self.at_each_point(
motors=[self.fast_axis],
positions=np.array([self.fast_end]),
status_mcs=mcs_aquiring_status,
)
self.at_each_point(motors=[self.fast_axis], positions=np.array([self.fast_end]))
self._restore_motor_properties()
@scan_hook
@@ -276,6 +287,7 @@ class ContGrid(ScanBase):
self,
motors: list[str | DeviceBase],
positions: np.ndarray,
status_mcs,
last_positions: np.ndarray | None = None,
):
"""
@@ -287,7 +299,7 @@ class ContGrid(ScanBase):
self.fast_axis.acceleration.set(self._cont_motor_params["acc_time"]).wait(timeout=5)
move_status = self.actions.set(motors, positions, wait=False)
time.sleep(self._cont_motor_params["acc_time"])
trigger_status = self.ddg1.trigger()
self.ddg1.trigger_shot.put(1)
while not move_status.done:
self.actions.read_monitored_devices(wait=True)
try:
@@ -296,10 +308,10 @@ class ContGrid(ScanBase):
continue
try:
trigger_status.wait(timeout=2)
status_mcs.wait(timeout=3)
except TimeoutError as exc:
raise ScanAbortion(
f"Status for delay generator trigger {self.ddg1.name} did not resolve after 2 seconds. "
f"MCS card did not go back to DONE after receiving all triggers and an extra 3 seconds. "
) from exc
@scan_hook