This commit is contained in:
2025-09-03 20:00:25 +02:00
parent b0a6be2573
commit 576f9a6a5b

View File

@@ -15,7 +15,13 @@ from ophyd import EpicsSignal, Kind
from ophyd.areadetector.cam import ADBase, PilatusDetectorCam
from ophyd.areadetector.plugins import HDF5Plugin_V22 as HDF5Plugin
from ophyd.status import WaitTimeoutError
from ophyd_devices import AndStatus, CompareStatus, DeviceStatus, FileEventSignal, PreviewSignal
from ophyd_devices import (
AndStatusWithList,
CompareStatus,
DeviceStatus,
FileEventSignal,
PreviewSignal,
)
from ophyd_devices.devices.areadetector.plugins import ImagePlugin_V35 as ImagePlugin
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
from ophyd_devices.utils.psi_device_base_utils import TaskStatus
@@ -178,6 +184,9 @@ class Pilatus(PSIDeviceBase, ADBase):
last_image = self.preview.get()
if np.array_equal(data, last_image):
# No update if image is the same, ~2.5ms on 2400x2400 image (6M)
logger.debug(
f"Pilatus preview image for {self.name} is the same as last one, not updating."
)
return
self.preview.put(data)
@@ -245,7 +254,7 @@ class Pilatus(PSIDeviceBase, ADBase):
self.cam.array_callbacks.set(1).wait(5) # Enable array callbacks
self.hdf.enable.set(1).wait(5) # Enable HDF5 plugin
# Camera settings
self.cam.num_exposures.set(1).wait(5) # why
self.cam.num_exposures.set(1).wait(5)
self.cam.num_images.set(n_images).wait(5)
self.cam.acquire_time.set(detector_exp_time).wait(5)
self.cam.acquire_period.set(PILATUS_ACQUIRE_TIME).wait(5)
@@ -272,9 +281,11 @@ class Pilatus(PSIDeviceBase, ADBase):
else:
status_hdf = CompareStatus(self.hdf.capture, ACQUIREMODE.ACQUIRING.value)
status_cam = CompareStatus(self.cam.acquire, ACQUIREMODE.ACQUIRING.value)
status = AndStatus(status_hdf, status_cam) # , name=f"{self.name}_on_pre_scan")
status = AndStatusWithList(device=self, status_list=[status_hdf, status_cam])
self.cam.acquire.put(1)
self.hdf.capture.put(1)
status.add_callback(self._on_failure_callback) # Callback on failure
self.cancel_on_stop(status)
return status
def on_trigger(self) -> DeviceStatus | None:
@@ -289,6 +300,7 @@ class Pilatus(PSIDeviceBase, ADBase):
status = CompareStatus(self.hdf.num_captured, img_counter + 1)
logger.warning(f"Triggering took image {time.time() - start_time:.3f} seconds")
self.trigger_shot.put(1)
status.add_callback(self._on_failure_callback) # Callback on failure
self.cancel_on_stop(status)
return status
@@ -315,12 +327,27 @@ class Pilatus(PSIDeviceBase, ADBase):
"frames_per_trigger", 1
)
status_img_written = CompareStatus(self.hdf.num_captured, num_images)
# TODO change to new ANDSTATUS
status_cam = AndStatus(status_hdf, status_cam)
status = AndStatus(status_cam, status_img_written) # , name=f"{self.name}_on_complete")
# status.add_callback(self._complete_callback) # Callback that writing was successful
status = AndStatusWithList(
device=self, status_list=[status_hdf, status_cam, status_img_written]
)
status.add_callback(self._complete_callback) # Callback that writing was successful
status.add_callback(self._on_failure_callback) # Callback on failure
self.cancel_on_stop(status)
return status
def _on_failure_callback(self, status: DeviceStatus | AndStatusWithList):
"""
This is a best effort cleanup procedure for the Pilatus backend.
It seems as if the CamServer is likely to crash, and needs a restart
if an acquisition is interrupted pre-dominantly and not properly stopped.
So we attach it to any status object during the acquisition.
Args:
status (DeviceStatus | AndStatusWithList): The status object to check.
"""
if not status.success:
status.device.on_stop()
def on_kickoff(self) -> None:
"""Called to kickoff a device for a fly scan. Has to be called explicitly."""
@@ -343,6 +370,8 @@ if __name__ == "__main__":
logger.info(f"Connecting to pilatus...")
pilatus.on_connected()
for exp_time, scan_number, n_pnts in zip([0.5, 1.0, 2.0], [1, 2, 3], [30, 20, 10]):
logger.info(f"Sleeping for 5s")
time.sleep(5)
pilatus.scan_info.msg.num_points = n_pnts
pilatus.scan_info.msg.scan_parameters["exposure_time"] = exp_time
pilatus.scan_info.msg.scan_parameters["frames_per_trigger"] = 1