PCO Edge in regular beamline config
This commit is contained in:
@@ -176,15 +176,43 @@ daq_stream1:
|
||||
readoutPriority: monitored
|
||||
softwareTrigger: false
|
||||
|
||||
pco_stream0:
|
||||
description: Raw camera stream from PCO.edge
|
||||
deviceClass: tomcat_bec.devices.StdDaqPreviewDetector
|
||||
|
||||
pcocam:
|
||||
description: PCO.edge camera client
|
||||
deviceClass: tomcat_bec.devices.PcoEdge5M
|
||||
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:
|
||||
- std-daq
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
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
|
||||
|
||||
@@ -11,5 +11,7 @@ from .grashopper_tomcat import GrashopperTOMCAT
|
||||
from .psimotor import EpicsMotorMR, EpicsMotorEC
|
||||
|
||||
from .gigafrost.gigafrostcamera import GigaFrostCamera
|
||||
from .gigafrost.pcoedgecamera import PcoEdge5M
|
||||
|
||||
from .gigafrost.stddaq_client import StdDaqClient
|
||||
from .gigafrost.stddaq_preview import StdDaqPreviewDetector
|
||||
|
||||
@@ -28,7 +28,7 @@ class PcoEdgeCameraMixin(CustomDeviceMixin):
|
||||
"""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"):
|
||||
logger.warning(f"Trying to stage the camera from state {self.parent.state}, unstaging it first!")
|
||||
self.parent.unstage()
|
||||
@@ -36,25 +36,30 @@ class PcoEdgeCameraMixin(CustomDeviceMixin):
|
||||
|
||||
# Fish out our configuration from scaninfo (via explicit or generic addressing)
|
||||
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 = {}
|
||||
if 'kwargs' in scanparam:
|
||||
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']
|
||||
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']
|
||||
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']
|
||||
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']
|
||||
# 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']
|
||||
# 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']
|
||||
# elif self.parent.scaninfo.scan_type == "step":
|
||||
# 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
|
||||
if len(d) > 0:
|
||||
@@ -136,6 +141,24 @@ class HelgeCameraBase(PSIDeviceBase):
|
||||
camError = Component(EpicsSignalRO, "ERRCODE", 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
|
||||
camStatusCode = Component(EpicsSignalRO, "STATUSCODE", auto_monitor=True, kind=Kind.config)
|
||||
@@ -176,19 +199,43 @@ class HelgeCameraBase(PSIDeviceBase):
|
||||
raise ReadOnlyError("State is a ReadOnly property")
|
||||
|
||||
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"):
|
||||
raise RuntimeError(f"Can't change configuration from state {self.state}")
|
||||
|
||||
# If Bluesky style configure
|
||||
if d is not None:
|
||||
# Commonly changed settings
|
||||
if 'num_images' in d:
|
||||
self.file_savestop.set(d['num_images']).wait()
|
||||
if 'exposure_time_ms' in d:
|
||||
self.acquire_time.set(d['exposure_time_ms']).wait()
|
||||
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()
|
||||
|
||||
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
|
||||
# Initial: BUSY and SET both low
|
||||
# 0. Write 1 to SET_PARAM
|
||||
@@ -231,17 +278,29 @@ class HelgeCameraBase(PSIDeviceBase):
|
||||
status = SubscriptionStatus(self.camStatusCode, isIdle, timeout=5, settle_time=0.2)
|
||||
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
|
||||
|
||||
This class provides wrappers for Helge's camera IOCs around SwissFEL and
|
||||
for high performance SLS 2.0 cameras. Theese are mostly PCO cameras running
|
||||
on a special Windows IOC host with lots of RAM and CPU power.
|
||||
"""
|
||||
"""
|
||||
|
||||
custom_prepare_cls = PcoEdgeCameraMixin
|
||||
USER_ACCESS = ["bluestage", "blueunstage"]
|
||||
USER_ACCESS = ["bluestage", "blueunstage", "bluekickoff"]
|
||||
|
||||
# ########################################################################
|
||||
# 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_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:
|
||||
"""
|
||||
Camera configuration instructions:
|
||||
@@ -302,7 +355,7 @@ class PcoEdgeBase(HelgeCameraBase):
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user