PCO Edge in regular beamline config
This commit is contained in:
@@ -176,15 +176,43 @@ daq_stream1:
|
|||||||
readoutPriority: monitored
|
readoutPriority: monitored
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
|
|
||||||
pco_stream0:
|
|
||||||
description: Raw camera stream from PCO.edge
|
pcocam:
|
||||||
deviceClass: tomcat_bec.devices.StdDaqPreviewDetector
|
description: PCO.edge camera client
|
||||||
|
deviceClass: tomcat_bec.devices.PcoEdge5M
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
url: 'tcp://129.129.106.124:8080'
|
prefix: 'X02DA-CCDCAM2:'
|
||||||
|
deviceTags:
|
||||||
|
- camera
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: monitored
|
||||||
|
softwareTrigger: false
|
||||||
|
|
||||||
|
pcodaq:
|
||||||
|
description: GigaFrost stdDAQ client
|
||||||
|
deviceClass: tomcat_bec.devices.StdDaqClient
|
||||||
|
deviceConfig:
|
||||||
|
ws_url: 'ws://129.129.95.111:8081'
|
||||||
|
rest_url: 'http://129.129.95.111:5010'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
- std-daq
|
- std-daq
|
||||||
enabled: true
|
enabled: true
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: async
|
readoutPriority: monitored
|
||||||
|
softwareTrigger: false
|
||||||
|
|
||||||
|
pco_stream0:
|
||||||
|
description: stdDAQ preview (2 every 555)
|
||||||
|
deviceClass: tomcat_bec.devices.StdDaqPreviewDetector
|
||||||
|
deviceConfig:
|
||||||
|
url: 'tcp://129.129.95.111:20010'
|
||||||
|
deviceTags:
|
||||||
|
- std-daq
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: monitored
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
|
|||||||
@@ -11,5 +11,7 @@ from .grashopper_tomcat import GrashopperTOMCAT
|
|||||||
from .psimotor import EpicsMotorMR, EpicsMotorEC
|
from .psimotor import EpicsMotorMR, EpicsMotorEC
|
||||||
|
|
||||||
from .gigafrost.gigafrostcamera import GigaFrostCamera
|
from .gigafrost.gigafrostcamera import GigaFrostCamera
|
||||||
|
from .gigafrost.pcoedgecamera import PcoEdge5M
|
||||||
|
|
||||||
from .gigafrost.stddaq_client import StdDaqClient
|
from .gigafrost.stddaq_client import StdDaqClient
|
||||||
from .gigafrost.stddaq_preview import StdDaqPreviewDetector
|
from .gigafrost.stddaq_preview import StdDaqPreviewDetector
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class PcoEdgeCameraMixin(CustomDeviceMixin):
|
|||||||
"""Configure and arm PCO.Edge camera for acquisition
|
"""Configure and arm PCO.Edge camera for acquisition
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Gigafrost can finish a run without explicit unstaging
|
# PCO can finish a run without explicit unstaging
|
||||||
if self.parent.state not in ("IDLE"):
|
if self.parent.state not in ("IDLE"):
|
||||||
logger.warning(f"Trying to stage the camera from state {self.parent.state}, unstaging it first!")
|
logger.warning(f"Trying to stage the camera from state {self.parent.state}, unstaging it first!")
|
||||||
self.parent.unstage()
|
self.parent.unstage()
|
||||||
@@ -36,25 +36,30 @@ class PcoEdgeCameraMixin(CustomDeviceMixin):
|
|||||||
|
|
||||||
# Fish out our configuration from scaninfo (via explicit or generic addressing)
|
# Fish out our configuration from scaninfo (via explicit or generic addressing)
|
||||||
scanparam = self.parent.scaninfo.scan_msg.info
|
scanparam = self.parent.scaninfo.scan_msg.info
|
||||||
alias = self.parent.parent.name if self.parent.parent is not None else self.parent.name
|
|
||||||
# logger.warning(f"[{alias}] Scan parameters:\n{scanparam}")
|
|
||||||
d = {}
|
d = {}
|
||||||
if 'kwargs' in scanparam:
|
if 'kwargs' in scanparam:
|
||||||
scanargs = scanparam['kwargs']
|
scanargs = scanparam['kwargs']
|
||||||
if 'image_width' in scanargs and scanargs['image_width']!=None:
|
if 'num_images_total' in scanargs and scanargs['num_images_total'] is not None:
|
||||||
|
d['images_total'] = scanargs['num_images_total']
|
||||||
|
if 'image_width' in scanargs and scanargs['image_width'] is not None:
|
||||||
d['image_width'] = scanargs['image_width']
|
d['image_width'] = scanargs['image_width']
|
||||||
if 'image_height' in scanargs and scanargs['image_height']!=None:
|
if 'image_height' in scanargs and scanargs['image_height'] is not None:
|
||||||
d['image_height'] = scanargs['image_height']
|
d['image_height'] = scanargs['image_height']
|
||||||
if 'exp_time' in scanargs and scanargs['exp_time']!=None:
|
if 'exp_time' in scanargs and scanargs['exp_time'] is not None:
|
||||||
d['exposure_time_ms'] = scanargs['exp_time']
|
d['exposure_time_ms'] = scanargs['exp_time']
|
||||||
if 'exp_period' in scanargs and scanargs['exp_period']!=None:
|
if 'exp_period' in scanargs and scanargs['exp_period'] is not None:
|
||||||
d['exposure_period_ms'] = scanargs['exp_period']
|
d['exposure_period_ms'] = scanargs['exp_period']
|
||||||
# if 'exp_burst' in scanargs and scanargs['exp_burst']!=None:
|
# if 'exp_burst' in scanargs and scanargs['exp_burst'] is not None:
|
||||||
# d['exposure_num_burst'] = scanargs['exp_burst']
|
# d['exposure_num_burst'] = scanargs['exp_burst']
|
||||||
# if 'acq_mode' in scanargs and scanargs['acq_mode']!=None:
|
# if 'acq_mode' in scanargs and scanargs['acq_mode'] is not None:
|
||||||
# d['acq_mode'] = scanargs['acq_mode']
|
# d['acq_mode'] = scanargs['acq_mode']
|
||||||
# elif self.parent.scaninfo.scan_type == "step":
|
# elif self.parent.scaninfo.scan_type == "step":
|
||||||
# d['acq_mode'] = "default"
|
# d['acq_mode'] = "default"
|
||||||
|
if 'pco_store_mode' in scanargs and scanargs['pco_store_mode'] is not None:
|
||||||
|
d['store_mode'] = scanargs['pco_store_mode']
|
||||||
|
if 'pco_data_format' in scanargs and scanargs['pco_data_format'] is not None:
|
||||||
|
d['data_format'] = scanargs['pco_data_format']
|
||||||
|
|
||||||
|
|
||||||
# Perform bluesky-style configuration
|
# Perform bluesky-style configuration
|
||||||
if len(d) > 0:
|
if len(d) > 0:
|
||||||
@@ -136,6 +141,24 @@ class HelgeCameraBase(PSIDeviceBase):
|
|||||||
camError = Component(EpicsSignalRO, "ERRCODE", auto_monitor=True, kind=Kind.config)
|
camError = Component(EpicsSignalRO, "ERRCODE", auto_monitor=True, kind=Kind.config)
|
||||||
camWarning = Component(EpicsSignalRO, "WARNCODE", auto_monitor=True, kind=Kind.config)
|
camWarning = Component(EpicsSignalRO, "WARNCODE", auto_monitor=True, kind=Kind.config)
|
||||||
|
|
||||||
|
# ########################################################################
|
||||||
|
# Buffer configuration
|
||||||
|
bufferRecMode = Component(EpicsSignalRO, "RECMODE", auto_monitor=True, kind=Kind.config)
|
||||||
|
bufferStoreMode = Component(EpicsSignal, "STOREMODE", auto_monitor=True, kind=Kind.config)
|
||||||
|
fileRecMode = Component(EpicsSignalRO, "RECMODE", auto_monitor=True, kind=Kind.config)
|
||||||
|
|
||||||
|
buffer_used = Component(EpicsSignalRO, "PIC_BUFFER", auto_monitor=True, kind=Kind.normal)
|
||||||
|
buffer_size = Component(EpicsSignalRO, "PIC_MAX", auto_monitor=True, kind=Kind.normal)
|
||||||
|
|
||||||
|
# ########################################################################
|
||||||
|
# File saving interface
|
||||||
|
cam_data_rate = Component(EpicsSignalRO, "CAMRATE", auto_monitor=True, kind=Kind.normal)
|
||||||
|
file_data_rate = Component(EpicsSignalRO, "FILERATE", auto_monitor=True, kind=Kind.normal)
|
||||||
|
file_savestart = Component(EpicsSignal, "SAVESTART", put_complete=True, kind=Kind.config)
|
||||||
|
file_savestop = Component(EpicsSignal, "SAVESTOP", put_complete=True, kind=Kind.config)
|
||||||
|
file_format = Component(EpicsSignal, "FILEFORMAT", put_complete=True, kind=Kind.config)
|
||||||
|
file_transfer = Component(EpicsSignal, "FTRANSFER", put_complete=True, kind=Kind.config)
|
||||||
|
|
||||||
# ########################################################################
|
# ########################################################################
|
||||||
# Configuration state maschine with separate transition states
|
# Configuration state maschine with separate transition states
|
||||||
camStatusCode = Component(EpicsSignalRO, "STATUSCODE", auto_monitor=True, kind=Kind.config)
|
camStatusCode = Component(EpicsSignalRO, "STATUSCODE", auto_monitor=True, kind=Kind.config)
|
||||||
@@ -176,18 +199,42 @@ class HelgeCameraBase(PSIDeviceBase):
|
|||||||
raise ReadOnlyError("State is a ReadOnly property")
|
raise ReadOnlyError("State is a ReadOnly property")
|
||||||
|
|
||||||
def configure(self, d: dict = {}) -> tuple:
|
def configure(self, d: dict = {}) -> tuple:
|
||||||
""" Configure the base Helge camera device"""
|
""" Configure the base Helge camera device
|
||||||
|
|
||||||
|
Parameters as 'd' dictionary
|
||||||
|
----------------------------
|
||||||
|
num_images : int
|
||||||
|
Number of images to be taken during each scan. Meaning depends on
|
||||||
|
store mode.
|
||||||
|
exposure_time_ms : float
|
||||||
|
Exposure time [ms], usually gets set back to 20 ms
|
||||||
|
exposure_period_ms : float
|
||||||
|
Exposure period [ms], up to 200 ms.
|
||||||
|
store_mode : str
|
||||||
|
Buffer operation mode
|
||||||
|
*'Recorder' to record in buffer
|
||||||
|
*'FIFO buffer' for continous streaming
|
||||||
|
data_format : str
|
||||||
|
Usually set to 'ZEROMQ'
|
||||||
|
"""
|
||||||
if self.state not in ("IDLE"):
|
if self.state not in ("IDLE"):
|
||||||
raise RuntimeError(f"Can't change configuration from state {self.state}")
|
raise RuntimeError(f"Can't change configuration from state {self.state}")
|
||||||
|
|
||||||
# If Bluesky style configure
|
# If Bluesky style configure
|
||||||
if d is not None:
|
if d is not None:
|
||||||
# Commonly changed settings
|
# Commonly changed settings
|
||||||
|
if 'num_images' in d:
|
||||||
|
self.file_savestop.set(d['num_images']).wait()
|
||||||
if 'exposure_time_ms' in d:
|
if 'exposure_time_ms' in d:
|
||||||
self.acquire_time.set(d['exposure_time_ms']).wait()
|
self.acquire_time.set(d['exposure_time_ms']).wait()
|
||||||
if 'exposure_period_ms' in d:
|
if 'exposure_period_ms' in d:
|
||||||
# acquire_time = d['exposure_time_ms'] if 'exposure_time_ms' in d else self.acquire_time.get()
|
|
||||||
self.acquire_delay.set(d['exposure_period_ms']).wait()
|
self.acquire_delay.set(d['exposure_period_ms']).wait()
|
||||||
|
if 'exposure_period_ms' in d:
|
||||||
|
self.acquire_delay.set(d['exposure_period_ms']).wait()
|
||||||
|
if 'store_mode' in d:
|
||||||
|
self.bufferStoreMode.set(d['store_mode']).wait()
|
||||||
|
if 'data_format' in d:
|
||||||
|
self.file_format.set(d['data_format']).wait()
|
||||||
|
|
||||||
# State machine
|
# State machine
|
||||||
# Initial: BUSY and SET both low
|
# Initial: BUSY and SET both low
|
||||||
@@ -231,8 +278,20 @@ class HelgeCameraBase(PSIDeviceBase):
|
|||||||
status = SubscriptionStatus(self.camStatusCode, isIdle, timeout=5, settle_time=0.2)
|
status = SubscriptionStatus(self.camStatusCode, isIdle, timeout=5, settle_time=0.2)
|
||||||
status.wait()
|
status.wait()
|
||||||
|
|
||||||
|
# Data streaming is stopped by setting the max index to 0
|
||||||
|
self.file_savestop.set(0).wait()
|
||||||
|
|
||||||
class PcoEdgeBase(HelgeCameraBase):
|
|
||||||
|
def bluekickoff(self):
|
||||||
|
""" Start data transfer
|
||||||
|
|
||||||
|
TODO: Need to revisit this once triggering is complete
|
||||||
|
"""
|
||||||
|
self.file_transfer.set(1).wait()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PcoEdge5M(HelgeCameraBase):
|
||||||
"""Ophyd baseclass for PCO.Edge cameras
|
"""Ophyd baseclass for PCO.Edge cameras
|
||||||
|
|
||||||
This class provides wrappers for Helge's camera IOCs around SwissFEL and
|
This class provides wrappers for Helge's camera IOCs around SwissFEL and
|
||||||
@@ -241,7 +300,7 @@ class PcoEdgeBase(HelgeCameraBase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
custom_prepare_cls = PcoEdgeCameraMixin
|
custom_prepare_cls = PcoEdgeCameraMixin
|
||||||
USER_ACCESS = ["bluestage", "blueunstage"]
|
USER_ACCESS = ["bluestage", "blueunstage", "bluekickoff"]
|
||||||
|
|
||||||
# ########################################################################
|
# ########################################################################
|
||||||
# Additional status info
|
# Additional status info
|
||||||
@@ -266,12 +325,6 @@ class PcoEdgeBase(HelgeCameraBase):
|
|||||||
pxRoiY_lo = Component(EpicsSignal, "REGIONY_START", put_complete=True, auto_monitor=True, kind=Kind.config)
|
pxRoiY_lo = Component(EpicsSignal, "REGIONY_START", put_complete=True, auto_monitor=True, kind=Kind.config)
|
||||||
pxRoiY_hi = Component(EpicsSignal, "REGIONY_END", put_complete=True, auto_monitor=True, kind=Kind.config)
|
pxRoiY_hi = Component(EpicsSignal, "REGIONY_END", put_complete=True, auto_monitor=True, kind=Kind.config)
|
||||||
|
|
||||||
# ########################################################################
|
|
||||||
# Buffer configuration
|
|
||||||
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:
|
def configure(self, d: dict = {}) -> tuple:
|
||||||
"""
|
"""
|
||||||
Camera configuration instructions:
|
Camera configuration instructions:
|
||||||
|
|||||||
Reference in New Issue
Block a user