From 58caf2ddd3416deaace82b6e321fc0753771b282 Mon Sep 17 00:00:00 2001 From: appel_c Date: Tue, 5 Sep 2023 16:16:17 +0200 Subject: [PATCH] fix: working acquire, line and grid scan using mcs, ddg and eiger9m --- .../epics/devices/DelayGeneratorDG645.py | 39 ++++++++++++++----- ophyd_devices/epics/devices/eiger9m_csaxs.py | 12 +++++- ophyd_devices/epics/devices/mcs_csaxs.py | 18 ++++++--- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/ophyd_devices/epics/devices/DelayGeneratorDG645.py b/ophyd_devices/epics/devices/DelayGeneratorDG645.py index 4a897c2..2b04981 100644 --- a/ophyd_devices/epics/devices/DelayGeneratorDG645.py +++ b/ophyd_devices/epics/devices/DelayGeneratorDG645.py @@ -301,6 +301,13 @@ class DelayGeneratorDG645(Device): config_storage_name="ddg_config", ) + trigger_width = Component( + bec_utils.ConfigSignal, + name="trigger_width", + kind="config", + config_storage_name="ddg_config", + ) + def __init__( self, prefix="", @@ -348,6 +355,7 @@ class DelayGeneratorDG645(Device): f"{name}_set_high_on_exposure": False, f"{name}_set_high_on_stage": False, f"{name}_set_trigger_source": "SINGLE_SHOT", + f"{name}_trigger_width": None, } if ddg_config is not None: [self.ddg_config.update({f"{name}_{key}": value}) for key, value in ddg_config.items()] @@ -479,18 +487,19 @@ class DelayGeneratorDG645(Device): if self.set_high_on_exposure.get(): self._set_trigger(getattr(TriggerSource, self.set_trigger_source.get())) num_burst_cycle = 1 + self.additional_triggers.get() - exp_time = ( - self.delta_width.get() - + self.scaninfo.num_points - * self.scaninfo.frames_per_trigger - * (self.scaninfo.exp_time + self.scaninfo.readout_time) + + exp_time = self.delta_width.get() + self.scaninfo.frames_per_trigger * ( + self.scaninfo.exp_time + self.scaninfo.readout_time ) total_exposure = exp_time delay_burst = self.delay_burst.get() self.burst_enable(num_burst_cycle, delay_burst, total_exposure, config="first") self.set_channels("delay", 0) # Set burst length to half of the experimental time! - self.set_channels("width", exp_time) + if not self.trigger_width.get(): + self.set_channels("width", exp_time) + else: + self.set_channels("width", self.trigger_width.get()) else: self._set_trigger(getattr(TriggerSource, self.set_trigger_source.get())) exp_time = self.delta_width.get() + self.scaninfo.exp_time @@ -501,7 +510,10 @@ class DelayGeneratorDG645(Device): self.burst_enable(num_burst_cycle, delay_burst, total_exposure, config="first") self.set_channels("delay", 0) # Set burst length to half of the experimental time! - self.set_channels("width", exp_time) + if not self.trigger_width.get(): + self.set_channels("width", exp_time) + else: + self.set_channels("width", self.trigger_width.get()) elif self.scaninfo.scan_type == "fly": if self.set_high_on_exposure.get(): # define parameters @@ -519,7 +531,10 @@ class DelayGeneratorDG645(Device): self.burst_enable(num_burst_cycle, delay_burst, total_exposure, config="first") self.set_channels("delay", 0.0) # Set burst length to half of the experimental time! - self.set_channels("width", exp_time) + if not self.trigger_width.get(): + self.set_channels("width", exp_time) + else: + self.set_channels("width", self.trigger_width.get()) else: # define parameters self._set_trigger(getattr(TriggerSource, self.set_trigger_source.get())) @@ -531,7 +546,10 @@ class DelayGeneratorDG645(Device): self.burst_enable(num_burst_cycle, delay_burst, total_exposure, config="first") self.set_channels("delay", 0.0) # Set burst length to half of the experimental time! - self.set_channels("width", exp_time) + if not self.trigger_width.get(): + self.set_channels("width", exp_time) + else: + self.set_channels("width", self.trigger_width.get()) else: raise DDGError(f"Unknown scan type {self.scaninfo.scan_type}") @@ -554,7 +572,8 @@ class DelayGeneratorDG645(Device): # if self.scaninfo.scan_type == "step": if self.source.read()[self.source.name]["value"] == int(TriggerSource.SINGLE_SHOT): self.trigger_shot.set(1).wait() - status = super().trigger() + # status = super().trigger(status=) + status = DeviceStatus(self) burst_state = threading.Thread(target=self._check_burst_cycle, args=(status,), daemon=True) burst_state.start() return status diff --git a/ophyd_devices/epics/devices/eiger9m_csaxs.py b/ophyd_devices/epics/devices/eiger9m_csaxs.py index 2cd6d80..45dded0 100644 --- a/ophyd_devices/epics/devices/eiger9m_csaxs.py +++ b/ophyd_devices/epics/devices/eiger9m_csaxs.py @@ -220,7 +220,7 @@ class Eiger9mCsaxs(DetectorBase): # self.cam.acquire_period.set( # self.scaninfo.exp_time + (self.scaninfo.readout_time - self.reduce_readout) # ) - self.cam.num_cycles.set(self.scaninfo.num_frames) + self.cam.num_cycles.set(int(self.scaninfo.num_points * self.scaninfo.frames_per_trigger)) self.cam.num_frames.set(1) def _set_trigger(self, trigger_source: TriggerSource) -> None: @@ -240,7 +240,10 @@ class Eiger9mCsaxs(DetectorBase): # self._close_file_writer() logger.info(f" std_daq output filepath {self.filepath}") self.std_client.start_writer_async( - {"output_file": self.filepath, "n_images": self.scaninfo.num_frames} + { + "output_file": self.filepath, + "n_images": int(self.scaninfo.num_points * self.scaninfo.frames_per_trigger), + } ) while True: det_ctrl = self.std_client.get_status()["acquisition"]["state"] @@ -264,6 +267,11 @@ class Eiger9mCsaxs(DetectorBase): self._prep_file_writer() logger.info("std_daq is ready") + msg = BECMessage.FileMessage(file_path=self.filepath, done=False) + self._producer.set_and_publish( + MessageEndpoints.public_file(self.scaninfo.scanID, self.name), + msg.dumps(), + ) msg = BECMessage.FileMessage(file_path=self.filepath, done=False) self._producer.set_and_publish( MessageEndpoints.public_file(self.scaninfo.scanID, self.name), diff --git a/ophyd_devices/epics/devices/mcs_csaxs.py b/ophyd_devices/epics/devices/mcs_csaxs.py index 49a46ad..c2806cb 100644 --- a/ophyd_devices/epics/devices/mcs_csaxs.py +++ b/ophyd_devices/epics/devices/mcs_csaxs.py @@ -230,7 +230,10 @@ class McsCsaxs(SIS38XX): self._updated = True self._counter += 1 - if self._counter == self.num_lines.get(): + logger.info(f"counter {self._counter}") + if (self.scaninfo.scan_type == "fly" and self._counter == self.num_lines.get()) or ( + self.scaninfo.scan_type == "step" and self._counter == self.scaninfo.num_points + ): self._acquisition_done = True self.stop_all.put(1, use_complete=False) self._send_data_to_bec() @@ -272,12 +275,17 @@ class McsCsaxs(SIS38XX): self._set_trigger(TriggerSource.MODE3) def _set_acquisition_params(self) -> None: - n_points = self.scaninfo.num_frames / int(self.num_lines.get()) - if n_points > 9999: + if self.scaninfo.scan_type == "step": + n_points = self.scaninfo.frames_per_trigger + 1 + elif self.scaninfo.scan_type == "fly": + n_points = self.scaninfo.num_points / int(self.num_lines.get()) + 1 + else: + raise MCSError(f"Scantype {self.scaninfo} not implemented for MCS card") + if n_points > 1000: raise MCSError( - f"Requested number of points {n_points+1} exceeds hardware limit of 10000 (n+1)" + f"Requested number of points N={n_points} exceeds hardware limit of mcs card 10000 (N-1)" ) - self.num_use_all.set(n_points + 1) + self.num_use_all.set(n_points) self.preset_real.set(0) def _set_trigger(self, trigger_source: TriggerSource) -> None: