Basic PCO functionality tested

This commit is contained in:
gac-x05la
2025-01-31 12:24:01 +01:00
parent 0a1e11ed4f
commit a78077139a

View File

@@ -5,11 +5,8 @@ Created on Wed Dec 6 11:33:54 2023
@author: mohacsi_i
"""
from ophyd import Device, Component, EpicsMotor, EpicsSignal, EpicsSignalRO, Kind
from ophyd.status import Status, SubscriptionStatus, StatusBase, DeviceStatus
from time import sleep
import warnings
import numpy as np
from ophyd import Component, EpicsSignal, EpicsSignalRO, Kind
from ophyd.status import SubscriptionStatus
import time
from ophyd_devices.interfaces.base_classes.psi_detector_base import PSIDetectorBase as PSIDeviceBase
from ophyd_devices.interfaces.base_classes.psi_detector_base import CustomDetectorMixin as CustomDeviceMixin
@@ -32,10 +29,10 @@ class PcoEdgeCameraMixin(CustomDeviceMixin):
"""
# Gigafrost can finish a run without explicit unstaging
if self.parent.infoBusyFlag.value:
logger.warning("Camera is already running, unstaging it first!")
if self.parent.state not in ("IDLE"):
logger.warning(f"Trying to stage the camera from state {self.parent.state}, unstaging it first!")
self.parent.unstage()
sleep(0.5)
time.sleep(0.5)
# Fish out our configuration from scaninfo (via explicit or generic addressing)
scanparam = self.parent.scaninfo.scan_msg.info
@@ -95,8 +92,6 @@ class HelgeCameraBase(PSIDeviceBase):
The status flag state machine during re-configuration is:
BUSY low, SET low -> BUSY high, SET low -> BUSY low, SET high -> BUSY low, SET low
"""
# Specify Mixin class
custom_prepare_cls = HelgeCameraMixin
# ########################################################################
# General hardware info (in AD nomenclature)
@@ -166,14 +161,9 @@ class HelgeCameraBase(PSIDeviceBase):
def configure(self, d: dict = {}) -> tuple:
""" Configure the base Helge camera device"""
if self.state in ["OFFLINE", "REMOVED", "RUNNING"]:
if self.state not in ("IDLE"):
raise RuntimeError(f"Can't change configuration from state {self.state}")
# Stop acquisition
self.unstage()
if not self._initialized:
pass
# If Bluesky style configure
if d is not None:
# Commonly changed settings
@@ -209,7 +199,7 @@ class HelgeCameraBase(PSIDeviceBase):
# Subscribe and wait for update
def isRunning(*args, old_value, value, timestamp, **kwargs):
return bool(self.state=="RUNNING")
return bool(value==6)
status = SubscriptionStatus(self.camStatusCode, isRunning, timeout=5, settle_time=0.2)
status.wait()
@@ -222,7 +212,7 @@ class HelgeCameraBase(PSIDeviceBase):
# Subscribe and wait for update
def isIdle(*args, old_value, value, timestamp, **kwargs):
return bool(value==2)
status = SubscriptionStatus(self.parent.camStatusCode, isIdle, timeout=5, settle_time=0.2)
status = SubscriptionStatus(self.camStatusCode, isIdle, timeout=5, settle_time=0.2)
status.wait()
@@ -265,8 +255,6 @@ class PcoEdgeBase(HelgeCameraBase):
bufferRecMode = Component(EpicsSignalRO, "RECMODE", auto_monitor=True, kind=Kind.config)
bufferStoreMode = Component(EpicsSignalRO, "STOREMODE", auto_monitor=True, kind=Kind.config)
fileRecMode = Component(EpicsSignalRO, "RECMODE", auto_monitor=True, kind=Kind.config)
def configure(self, d: dict = {}) -> tuple:
"""
@@ -276,9 +264,29 @@ class PcoEdgeBase(HelgeCameraBase):
both send the settings to the camera and allocate the necessary buffers in the correct
size and shape (that takes time). Starting the exposure with CAMERASTATUS will also
call SET_PARAM, but it might take long.
"""
old = self.read_configuration()
NOTE:
The camera IOC will automatically round up RoiX coordinates to the
next multiple of 160. This means that configure can only change image
width in steps of 320 pixels (or manually of 160). Roi
Parameters as 'd' dictionary
----------------------------
exposure_time_ms : float, optional
Exposure time [ms].
exposure_period_ms : float, optional
Exposure period [ms], ignored in soft trigger mode.
image_width : int, optional
ROI size in the x-direction, multiple of 320 [pixels]
image_height : int, optional
ROI size in the y-direction, multiple of 2 [pixels]
image_binx : int optional
Binning along image width [pixels]
image_biny: int, optional
Binning along image height [pixels]
acq_mode : str, not yet implemented
Select one of the pre-configured trigger behavior
"""
if d is not None:
# Need to be smart how we set the ROI....
# Image sensor is 2560x2160 (X and Y)
@@ -300,20 +308,9 @@ class PcoEdgeBase(HelgeCameraBase):
super().configure(d)
# Automatically connect to test camera if directly invoked
if __name__ == "__main__":
# Drive data collection
cam = HelgeCameraBase("X02DA-CCDCAM2:", name="mcpcam")
cam = PcoEdgeBase("X02DA-CCDCAM2:", name="mcpcam")
cam.wait_for_connection()