Found out stdDAQ filename problem

This commit is contained in:
gac-x05la
2025-04-28 17:37:17 +02:00
parent 672cb60e72
commit b3e0a64bf1
5 changed files with 85 additions and 54 deletions

View File

@@ -102,7 +102,7 @@ es1_psod:
onFailure: buffer
readOnly: false
readoutPriority: monitored
softwareTrigger: true
softwareTrigger: false
es1_ddaq:
@@ -133,22 +133,22 @@ es1_ddaq:
# softwareTrigger: true
gfcam:
description: GigaFrost camera client
deviceClass: tomcat_bec.devices.GigaFrostCamera
deviceConfig:
prefix: 'X02DA-CAM-GF2:'
backend_url: 'http://sls-daq-001:8080'
auto_soft_enable: true
deviceTags:
- camera
- trigger
- gfcam
enabled: true
onFailure: buffer
readOnly: false
readoutPriority: monitored
softwareTrigger: true
# gfcam:
# description: GigaFrost camera client
# deviceClass: tomcat_bec.devices.GigaFrostCamera
# deviceConfig:
# prefix: 'X02DA-CAM-GF2:'
# backend_url: 'http://sls-daq-001:8080'
# auto_soft_enable: true
# deviceTags:
# - camera
# - trigger
# - gfcam
# enabled: true
# onFailure: buffer
# readOnly: false
# readoutPriority: monitored
# softwareTrigger: true
# gfcam:
@@ -202,30 +202,11 @@ gfcam:
# softwareTrigger: false
pcocam:
description: PCO.edge camera client
deviceClass: tomcat_bec.devices.PcoEdge5M
deviceConfig:
prefix: 'X02DA-CCDCAM2:'
deviceTags:
- camera
- trigger
- pcocam
enabled: true
onFailure: buffer
readOnly: false
readoutPriority: monitored
softwareTrigger: true
# pcocam:
# description: PCO.edge camera client
# deviceClass: tomcat_bec.devices.PcoEdge5M
# deviceConfig:
# prefix: 'X02DA-CCDCAM2:'
# std_daq_live: 'tcp://129.129.95.111:20010'
# std_daq_ws: 'ws://129.129.95.111:8081'
# std_daq_rest: 'http://129.129.95.111:5010'
# deviceTags:
# - camera
# - trigger
@@ -236,6 +217,25 @@ pcocam:
# readoutPriority: monitored
# softwareTrigger: true
pcocam:
description: PCO.edge camera client
deviceClass: tomcat_bec.devices.PcoEdge5M
deviceConfig:
prefix: 'X02DA-CCDCAM2:'
std_daq_live: 'tcp://129.129.95.111:20010'
std_daq_ws: 'ws://129.129.95.111:8081'
std_daq_rest: 'http://129.129.95.111:5010'
deviceTags:
- camera
- trigger
- pcocam
enabled: true
onFailure: buffer
readOnly: false
readoutPriority: monitored
softwareTrigger: true
# pcodaq:
# description: GigaFrost stdDAQ client
# deviceClass: tomcat_bec.devices.StdDaqClient

View File

@@ -199,7 +199,7 @@ class GigaFrostCamera(PSIDeviceBase, GigaFrostBase):
supplied signal. Use external enable instead, that works!
"""
if acq_mode == "default":
if acq_mode in ["default", "step"]:
# NOTE: Software trigger via softEnable (actually works)
# Trigger parameters
self.fix_nframes_mode = "start"
@@ -630,14 +630,11 @@ class GigaFrostCamera(PSIDeviceBase, GigaFrostBase):
and self.trigger_mode == "auto"
and self.enable_mode == "soft"
):
t_start = time()
# BEC teststand operation mode: posedge of SoftEnable if Started
self.soft_enable.set(0).wait()
self.soft_enable.set(1).wait()
logger.info(f"Elapsed: {time()-t_start}")
if self.acquire_block.get():
if self.acquire_block.get() or self.backend is None:
wait_time = 0.2 + 0.001 * self.num_exposures.value * max(
self.acquire_time.value, self.acquire_period.value
)

View File

@@ -59,7 +59,6 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
USER_ACCESS = [
"complete",
"backend",
# "acq_done",
"live_preview",
"arm",
"disarm",
@@ -125,6 +124,8 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
*'FIFO buffer' for continous streaming
data_format : str
Usually set to 'ZEROMQ'
acq_mode : str
Store mode and data format according to preconfigured settings
"""
if self.state not in ("IDLE"):
raise RuntimeError(f"Can't change configuration from state {self.state}")
@@ -149,6 +150,10 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
if "data_format" in d:
self.file_format.set(d["data_format"]).wait()
# If a pre-configured acquisition mode is specified, set it
if "acq_mode" in d:
self.set_acquisition_mode(d["acq_mode"])
# State machine
# Initial: BUSY and SET both low
# 0. Write 1 to SET_PARAM
@@ -165,6 +170,19 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
self.set_param.set(1).wait()
status.wait()
def set_acquisition_mode(self, acq_mode):
"""Set acquisition mode
Utility function to quickly select between pre-configured and tested
acquisition modes.
"""
if acq_mode in ["default", "step"]:
# NOTE: Trigger duration requires a consumer
self.bufferStoreMode.set("Recorder").wait()
# self.file_format.set("ZEROMQ").wait()
else:
raise RuntimeError(f"Unsupported acquisition mode: {acq_mode}")
def arm(self):
"""Bluesky style stage: arm the detector"""
logger.warning("Staging PCO")
@@ -206,6 +224,7 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
def _on_preview_update(self, img: np.ndarray, header: dict):
"""Send preview stream and update frame index counter"""
# FIXME: There's also a recorded images counter provided by the stdDAQ writer
self.num_images_counter.put(header["frame"], force=True)
self._run_subs(sub_type=self.SUB_DEVICE_MONITOR_2D, obj=self, value=img)
@@ -251,8 +270,6 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
}
d = {}
if "exp_burst" in scan_args and scan_args["exp_burst"] is not None:
d["exposure_num_burst"] = scan_args["exp_burst"]
if "image_width" in scan_args and scan_args["image_width"] is not None:
d["image_width"] = scan_args["image_width"]
if "image_height" in scan_args and scan_args["image_height"] is not None:
@@ -261,10 +278,16 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
d["exposure_time_ms"] = scan_args["exp_time"]
if "exp_period" in scan_args and scan_args["exp_period"] is not None:
d["exposure_period_ms"] = scan_args["exp_period"]
# if 'exp_burst' in scan_args and scan_args['exp_burst'] is not None:
# d['exposure_num_burst'] = scan_args['exp_burst']
# if 'acq_mode' in scan_args and scan_args['acq_mode'] is not None:
# d['acq_mode'] = scan_args['acq_mode']
if 'exp_burst' in scan_args and scan_args['exp_burst'] is not None:
d['exposure_num_burst'] = scan_args['exp_burst']
if "acq_time" in scan_args and scan_args["acq_time"] is not None:
d["exposure_time_ms"] = scan_args["acq_time"]
if "acq_period" in scan_args and scan_args["acq_period"] is not None:
d["exposure_period_ms"] = scan_args["acq_period"]
if 'acq_burst' in scan_args and scan_args['acq_burst'] is not None:
d['exposure_num_burst'] = scan_args['acq_burst']
if 'acq_mode' in scan_args and scan_args['acq_mode'] is not None:
d['acq_mode'] = scan_args['acq_mode']
# elif self.scaninfo.scan_type == "step":
# d['acq_mode'] = "default"
if "pco_store_mode" in scan_args and scan_args["pco_store_mode"] is not None:
@@ -305,6 +328,7 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
def on_pre_scan(self) -> DeviceStatus | None:
"""Called right before the scan starts on all devices automatically."""
logger.warning("Called op_prescan on PCO camera")
# First start the stdDAQ
if self.backend is not None:
self.backend.start(
@@ -371,8 +395,7 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
def on_complete(self) -> DeviceStatus | None:
"""Called to inquire if a device has completed a scans."""
# return self.acq_done()
return None
return self.acq_done()
def on_kickoff(self) -> DeviceStatus | None:
"""Start data transfer

View File

@@ -48,9 +48,10 @@ class StdDaqStatus(str, enum.Enum):
class StdDaqClient:
USER_ACCESS = ["status", "start", "stop", "get_config", "set_config", "reset", "_status"]
USER_ACCESS = ["status", "count", "start", "stop", "get_config", "set_config", "reset", "_status"]
_ws_client: ws.ClientConnection | None = None
_count: int = 0
_status: StdDaqStatus = StdDaqStatus.UNDEFINED
_status_timestamp: float | None = None
_ws_recv_mutex = threading.Lock()
@@ -81,6 +82,11 @@ class StdDaqClient:
"""
return self._status
@property
def count(self) -> int:
""" Get the recorded frame count"""
return self._count
def add_status_callback(
self, status: DeviceStatus, success: list[StdDaqStatus], error: list[StdDaqStatus]
):
@@ -113,15 +119,17 @@ class StdDaqClient:
# Ensure connection
self.wait_for_connection()
logger.info(f"Starting StdDaq backend. Current status: {self.status}")
status = StatusBase()
self.add_status_callback(status, success=["waiting_for_first_image"], error=["rejected"])
# NOTE: CREATING_FILE --> IDLE is a known error, the exact cause is unknown, nut might be botched overwrite protection
# Changing file_prefix often solves the problem, but still allows overwrites
self.add_status_callback(status, success=["waiting_for_first_image"], error=["rejected", "idle"])
message = {
"command": "start",
"path": file_path,
"file_prefix": file_prefix,
"n_image": num_images,
}
logger.info(f"Starting StdDaq backend. Current status: {self.status}. Message: {message}")
self._ws_client.send(json.dumps(message))
if wait:
status.wait(timeout=timeout)
@@ -327,7 +335,10 @@ class StdDaqClient:
continue
msg = json.loads(msg)
if self._status != msg["status"]:
logger.info(f"stdDAQ state transition by: {msg}")
logger.warning(f"stdDAQ state transition: {self._status} --> {msg}")
if msg["status"] == "recording":
self._count = msg.get("count", 0)
# Update status and run callbacks
self._status = msg["status"]
self._status_timestamp = msg_timestamp
self._run_status_callbacks()

View File