Found out stdDAQ filename problem
This commit is contained in:
@@ -102,7 +102,7 @@ es1_psod:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: monitored
|
readoutPriority: monitored
|
||||||
softwareTrigger: true
|
softwareTrigger: false
|
||||||
|
|
||||||
|
|
||||||
es1_ddaq:
|
es1_ddaq:
|
||||||
@@ -133,22 +133,22 @@ es1_ddaq:
|
|||||||
# softwareTrigger: true
|
# softwareTrigger: true
|
||||||
|
|
||||||
|
|
||||||
gfcam:
|
# gfcam:
|
||||||
description: GigaFrost camera client
|
# description: GigaFrost camera client
|
||||||
deviceClass: tomcat_bec.devices.GigaFrostCamera
|
# deviceClass: tomcat_bec.devices.GigaFrostCamera
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X02DA-CAM-GF2:'
|
# prefix: 'X02DA-CAM-GF2:'
|
||||||
backend_url: 'http://sls-daq-001:8080'
|
# backend_url: 'http://sls-daq-001:8080'
|
||||||
auto_soft_enable: true
|
# auto_soft_enable: true
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- camera
|
# - camera
|
||||||
- trigger
|
# - trigger
|
||||||
- gfcam
|
# - gfcam
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readOnly: false
|
# readOnly: false
|
||||||
readoutPriority: monitored
|
# readoutPriority: monitored
|
||||||
softwareTrigger: true
|
# softwareTrigger: true
|
||||||
|
|
||||||
|
|
||||||
# gfcam:
|
# gfcam:
|
||||||
@@ -202,30 +202,11 @@ gfcam:
|
|||||||
# softwareTrigger: false
|
# 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:
|
# pcocam:
|
||||||
# description: PCO.edge camera client
|
# description: PCO.edge camera client
|
||||||
# deviceClass: tomcat_bec.devices.PcoEdge5M
|
# deviceClass: tomcat_bec.devices.PcoEdge5M
|
||||||
# deviceConfig:
|
# deviceConfig:
|
||||||
# prefix: 'X02DA-CCDCAM2:'
|
# 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:
|
# deviceTags:
|
||||||
# - camera
|
# - camera
|
||||||
# - trigger
|
# - trigger
|
||||||
@@ -236,6 +217,25 @@ pcocam:
|
|||||||
# readoutPriority: monitored
|
# readoutPriority: monitored
|
||||||
# softwareTrigger: true
|
# 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:
|
# pcodaq:
|
||||||
# description: GigaFrost stdDAQ client
|
# description: GigaFrost stdDAQ client
|
||||||
# deviceClass: tomcat_bec.devices.StdDaqClient
|
# deviceClass: tomcat_bec.devices.StdDaqClient
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ class GigaFrostCamera(PSIDeviceBase, GigaFrostBase):
|
|||||||
supplied signal. Use external enable instead, that works!
|
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)
|
# NOTE: Software trigger via softEnable (actually works)
|
||||||
# Trigger parameters
|
# Trigger parameters
|
||||||
self.fix_nframes_mode = "start"
|
self.fix_nframes_mode = "start"
|
||||||
@@ -630,14 +630,11 @@ class GigaFrostCamera(PSIDeviceBase, GigaFrostBase):
|
|||||||
and self.trigger_mode == "auto"
|
and self.trigger_mode == "auto"
|
||||||
and self.enable_mode == "soft"
|
and self.enable_mode == "soft"
|
||||||
):
|
):
|
||||||
t_start = time()
|
|
||||||
# BEC teststand operation mode: posedge of SoftEnable if Started
|
# BEC teststand operation mode: posedge of SoftEnable if Started
|
||||||
self.soft_enable.set(0).wait()
|
self.soft_enable.set(0).wait()
|
||||||
self.soft_enable.set(1).wait()
|
self.soft_enable.set(1).wait()
|
||||||
|
|
||||||
logger.info(f"Elapsed: {time()-t_start}")
|
if self.acquire_block.get() or self.backend is None:
|
||||||
|
|
||||||
if self.acquire_block.get():
|
|
||||||
wait_time = 0.2 + 0.001 * self.num_exposures.value * max(
|
wait_time = 0.2 + 0.001 * self.num_exposures.value * max(
|
||||||
self.acquire_time.value, self.acquire_period.value
|
self.acquire_time.value, self.acquire_period.value
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
|
|||||||
USER_ACCESS = [
|
USER_ACCESS = [
|
||||||
"complete",
|
"complete",
|
||||||
"backend",
|
"backend",
|
||||||
# "acq_done",
|
|
||||||
"live_preview",
|
"live_preview",
|
||||||
"arm",
|
"arm",
|
||||||
"disarm",
|
"disarm",
|
||||||
@@ -125,6 +124,8 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
|
|||||||
*'FIFO buffer' for continous streaming
|
*'FIFO buffer' for continous streaming
|
||||||
data_format : str
|
data_format : str
|
||||||
Usually set to 'ZEROMQ'
|
Usually set to 'ZEROMQ'
|
||||||
|
acq_mode : str
|
||||||
|
Store mode and data format according to preconfigured settings
|
||||||
"""
|
"""
|
||||||
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}")
|
||||||
@@ -149,6 +150,10 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
|
|||||||
if "data_format" in d:
|
if "data_format" in d:
|
||||||
self.file_format.set(d["data_format"]).wait()
|
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
|
# State machine
|
||||||
# Initial: BUSY and SET both low
|
# Initial: BUSY and SET both low
|
||||||
# 0. Write 1 to SET_PARAM
|
# 0. Write 1 to SET_PARAM
|
||||||
@@ -165,6 +170,19 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
|
|||||||
self.set_param.set(1).wait()
|
self.set_param.set(1).wait()
|
||||||
status.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):
|
def arm(self):
|
||||||
"""Bluesky style stage: arm the detector"""
|
"""Bluesky style stage: arm the detector"""
|
||||||
logger.warning("Staging PCO")
|
logger.warning("Staging PCO")
|
||||||
@@ -206,6 +224,7 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
|
|||||||
|
|
||||||
def _on_preview_update(self, img: np.ndarray, header: dict):
|
def _on_preview_update(self, img: np.ndarray, header: dict):
|
||||||
"""Send preview stream and update frame index counter"""
|
"""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.num_images_counter.put(header["frame"], force=True)
|
||||||
self._run_subs(sub_type=self.SUB_DEVICE_MONITOR_2D, obj=self, value=img)
|
self._run_subs(sub_type=self.SUB_DEVICE_MONITOR_2D, obj=self, value=img)
|
||||||
|
|
||||||
@@ -251,8 +270,6 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
d = {}
|
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:
|
if "image_width" in scan_args and scan_args["image_width"] is not None:
|
||||||
d["image_width"] = scan_args["image_width"]
|
d["image_width"] = scan_args["image_width"]
|
||||||
if "image_height" in scan_args and scan_args["image_height"] is not None:
|
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"]
|
d["exposure_time_ms"] = scan_args["exp_time"]
|
||||||
if "exp_period" in scan_args and scan_args["exp_period"] is not None:
|
if "exp_period" in scan_args and scan_args["exp_period"] is not None:
|
||||||
d["exposure_period_ms"] = scan_args["exp_period"]
|
d["exposure_period_ms"] = scan_args["exp_period"]
|
||||||
# if 'exp_burst' in scan_args and scan_args['exp_burst'] is not None:
|
if 'exp_burst' in scan_args and scan_args['exp_burst'] is not None:
|
||||||
# d['exposure_num_burst'] = scan_args['exp_burst']
|
d['exposure_num_burst'] = scan_args['exp_burst']
|
||||||
# if 'acq_mode' in scan_args and scan_args['acq_mode'] is not None:
|
if "acq_time" in scan_args and scan_args["acq_time"] is not None:
|
||||||
# d['acq_mode'] = scan_args['acq_mode']
|
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":
|
# elif self.scaninfo.scan_type == "step":
|
||||||
# d['acq_mode'] = "default"
|
# d['acq_mode'] = "default"
|
||||||
if "pco_store_mode" in scan_args and scan_args["pco_store_mode"] is not None:
|
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:
|
def on_pre_scan(self) -> DeviceStatus | None:
|
||||||
"""Called right before the scan starts on all devices automatically."""
|
"""Called right before the scan starts on all devices automatically."""
|
||||||
|
logger.warning("Called op_prescan on PCO camera")
|
||||||
# First start the stdDAQ
|
# First start the stdDAQ
|
||||||
if self.backend is not None:
|
if self.backend is not None:
|
||||||
self.backend.start(
|
self.backend.start(
|
||||||
@@ -371,8 +395,7 @@ class PcoEdge5M(PSIDeviceBase, PcoEdgeBase):
|
|||||||
|
|
||||||
def on_complete(self) -> DeviceStatus | None:
|
def on_complete(self) -> DeviceStatus | None:
|
||||||
"""Called to inquire if a device has completed a scans."""
|
"""Called to inquire if a device has completed a scans."""
|
||||||
# return self.acq_done()
|
return self.acq_done()
|
||||||
return None
|
|
||||||
|
|
||||||
def on_kickoff(self) -> DeviceStatus | None:
|
def on_kickoff(self) -> DeviceStatus | None:
|
||||||
"""Start data transfer
|
"""Start data transfer
|
||||||
|
|||||||
@@ -48,9 +48,10 @@ class StdDaqStatus(str, enum.Enum):
|
|||||||
|
|
||||||
class StdDaqClient:
|
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
|
_ws_client: ws.ClientConnection | None = None
|
||||||
|
_count: int = 0
|
||||||
_status: StdDaqStatus = StdDaqStatus.UNDEFINED
|
_status: StdDaqStatus = StdDaqStatus.UNDEFINED
|
||||||
_status_timestamp: float | None = None
|
_status_timestamp: float | None = None
|
||||||
_ws_recv_mutex = threading.Lock()
|
_ws_recv_mutex = threading.Lock()
|
||||||
@@ -81,6 +82,11 @@ class StdDaqClient:
|
|||||||
"""
|
"""
|
||||||
return self._status
|
return self._status
|
||||||
|
|
||||||
|
@property
|
||||||
|
def count(self) -> int:
|
||||||
|
""" Get the recorded frame count"""
|
||||||
|
return self._count
|
||||||
|
|
||||||
def add_status_callback(
|
def add_status_callback(
|
||||||
self, status: DeviceStatus, success: list[StdDaqStatus], error: list[StdDaqStatus]
|
self, status: DeviceStatus, success: list[StdDaqStatus], error: list[StdDaqStatus]
|
||||||
):
|
):
|
||||||
@@ -113,15 +119,17 @@ class StdDaqClient:
|
|||||||
# Ensure connection
|
# Ensure connection
|
||||||
self.wait_for_connection()
|
self.wait_for_connection()
|
||||||
|
|
||||||
logger.info(f"Starting StdDaq backend. Current status: {self.status}")
|
|
||||||
status = StatusBase()
|
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 = {
|
message = {
|
||||||
"command": "start",
|
"command": "start",
|
||||||
"path": file_path,
|
"path": file_path,
|
||||||
"file_prefix": file_prefix,
|
"file_prefix": file_prefix,
|
||||||
"n_image": num_images,
|
"n_image": num_images,
|
||||||
}
|
}
|
||||||
|
logger.info(f"Starting StdDaq backend. Current status: {self.status}. Message: {message}")
|
||||||
self._ws_client.send(json.dumps(message))
|
self._ws_client.send(json.dumps(message))
|
||||||
if wait:
|
if wait:
|
||||||
status.wait(timeout=timeout)
|
status.wait(timeout=timeout)
|
||||||
@@ -327,7 +335,10 @@ class StdDaqClient:
|
|||||||
continue
|
continue
|
||||||
msg = json.loads(msg)
|
msg = json.loads(msg)
|
||||||
if self._status != msg["status"]:
|
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 = msg["status"]
|
||||||
self._status_timestamp = msg_timestamp
|
self._status_timestamp = msg_timestamp
|
||||||
self._run_status_callbacks()
|
self._run_status_callbacks()
|
||||||
|
|||||||
Reference in New Issue
Block a user