diff --git a/csaxs_bec/devices/epics/delay_generator_csaxs/ddg_1.py b/csaxs_bec/devices/epics/delay_generator_csaxs/ddg_1.py index 597b032..6a032dc 100644 --- a/csaxs_bec/devices/epics/delay_generator_csaxs/ddg_1.py +++ b/csaxs_bec/devices/epics/delay_generator_csaxs/ddg_1.py @@ -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. diff --git a/csaxs_bec/devices/epics/delay_generator_csaxs/delay_generator_csaxs.py b/csaxs_bec/devices/epics/delay_generator_csaxs/delay_generator_csaxs.py index 4789f5c..6e4c2dc 100644 --- a/csaxs_bec/devices/epics/delay_generator_csaxs/delay_generator_csaxs.py +++ b/csaxs_bec/devices/epics/delay_generator_csaxs/delay_generator_csaxs.py @@ -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", ) diff --git a/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py b/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py index afc4aa1..fd83bda 100644 --- a/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py +++ b/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py @@ -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) diff --git a/csaxs_bec/scans/scans_v4/cont_grid.py b/csaxs_bec/scans/scans_v4/cont_grid.py index d85c0a1..7296793 100644 --- a/csaxs_bec/scans/scans_v4/cont_grid.py +++ b/csaxs_bec/scans/scans_v4/cont_grid.py @@ -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