After session with Klaus

This commit is contained in:
gac-x05la
2025-02-20 12:42:33 +01:00
parent 76cf6ac447
commit f15fd00712
3 changed files with 104 additions and 29 deletions

View File

@@ -13,7 +13,7 @@ import requests
import os import os
from ophyd import Signal, Component, Kind from ophyd import Signal, Component, Kind
from ophyd.status import SubscriptionStatus from ophyd.status import SubscriptionStatus, Status
from websockets.sync.client import connect, ClientConnection from websockets.sync.client import connect, ClientConnection
from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError
@@ -41,6 +41,9 @@ class StdDaqMixin(CustomDeviceMixin):
# Fish out our configuration from scaninfo (via explicit or generic addressing) # Fish out our configuration from scaninfo (via explicit or generic addressing)
# NOTE: Scans don't have to fully configure the device # NOTE: Scans don't have to fully configure the device
d = {} d = {}
scan_parameters = self.parent.scaninfo.scan_msg.scan_parameters
std_daq_params = scan_parameters.get("std_daq_params")
if "kwargs" in self.parent.scaninfo.scan_msg.info: if "kwargs" in self.parent.scaninfo.scan_msg.info:
scanargs = self.parent.scaninfo.scan_msg.info["kwargs"] scanargs = self.parent.scaninfo.scan_msg.info["kwargs"]
if "image_width" in scanargs and scanargs["image_width"] is not None: if "image_width" in scanargs and scanargs["image_width"] is not None:
@@ -88,6 +91,7 @@ class StdDaqMixin(CustomDeviceMixin):
if points_valid: if points_valid:
d["num_points_total"] = num_points d["num_points_total"] = num_points
# Perform bluesky-style configuration # Perform bluesky-style configuration
if len(d) > 0: if len(d) > 0:
# Configure new run (will restart the stdDAQ) # Configure new run (will restart the stdDAQ)
@@ -97,7 +101,9 @@ class StdDaqMixin(CustomDeviceMixin):
sleep(0.5) sleep(0.5)
# Try to start a new run (reconnects) # Try to start a new run (reconnects)
self.parent.bluestage() if std_daq_params.get("reconnect",True):
self.parent.bluestage()
# And start status monitoring # And start status monitoring
self._mon = Thread(target=self.monitor, daemon=True) self._mon = Thread(target=self.monitor, daemon=True)
self._mon.start() self._mon.start()
@@ -159,6 +165,7 @@ class StdDaqClient(PSIDeviceBase):
"state", "state",
"bluestage", "bluestage",
"blueunstage", "blueunstage",
"complete",
] ]
_wsclient = None _wsclient = None
@@ -277,6 +284,8 @@ class StdDaqClient(PSIDeviceBase):
images (limited by the ringbuffer size and backend speed). images (limited by the ringbuffer size and backend speed).
file_path: str, optional file_path: str, optional
File path to save the data, usually GPFS. File path to save the data, usually GPFS.
file_prefix: str, optional
File prefix to save the data [default = file].
image_width : int, optional image_width : int, optional
ROI size in the x-direction [pixels]. ROI size in the x-direction [pixels].
image_height : int, optional image_height : int, optional
@@ -299,6 +308,10 @@ class StdDaqClient(PSIDeviceBase):
# Run parameters # Run parameters
if "num_points_total" in d: if "num_points_total" in d:
self.num_images.set(d["num_points_total"]).wait() self.num_images.set(d["num_points_total"]).wait()
if "file_path" in d:
self.file_path.set(d["file_path"]).wait()
if "file_prefix" in d:
self.file_prefix.set(d["file_prefix"]).wait()
# Restart the DAQ if resolution changed # Restart the DAQ if resolution changed
cfg = self.get_daq_config() cfg = self.get_daq_config()
@@ -322,6 +335,15 @@ class StdDaqClient(PSIDeviceBase):
sleep(1) sleep(1)
self.get_daq_config(update=True) self.get_daq_config(update=True)
# def configure(self, d:dict):
# if "num_points_total" in d:
# num_points = d.pop("num_points_total")
# self.num_images.set(num_points).wait()
# super().configure(d)
# self.set_daq_config()
# sleep(1)
# self.get_daq_config(update=True)
def bluestage(self): def bluestage(self):
"""Stages the stdDAQ """Stages the stdDAQ
@@ -351,6 +373,7 @@ class StdDaqClient(PSIDeviceBase):
file_path = self.file_path.get() file_path = self.file_path.get()
num_images = self.num_images.get() num_images = self.num_images.get()
file_prefix = self.name
file_prefix = self.file_prefix.get() file_prefix = self.file_prefix.get()
print(file_prefix) print(file_prefix)
@@ -427,12 +450,18 @@ class StdDaqClient(PSIDeviceBase):
def complete(self) -> SubscriptionStatus: def complete(self) -> SubscriptionStatus:
"""Wait for current run. Must end in status 'file_saved'.""" """Wait for current run. Must end in status 'file_saved'."""
# Return immediately if we're detached
# TODO: Maybe check for connection (not sure if it's better)
if self.state() in ["idle", "file_saved", "error"]:
status = Status(self)
status.set_finished()
return status
def is_running(*args, value, timestamp, **kwargs): def is_running(*args, value, timestamp, **kwargs):
result = value in ["idle", "file_saved", "error"] result = value in ["idle", "file_saved", "error"]
return result return result
status = SubscriptionStatus(self.runstatus, is_running, settle_time=0.5) status = SubscriptionStatus(self.runstatus, is_running, settle_time=0.5)
# status.set_finished()
return status return status
def get_daq_config(self, update=False) -> dict: def get_daq_config(self, update=False) -> dict:

View File

@@ -4,6 +4,11 @@ import numpy as np
from bec_lib.device import DeviceBase from bec_lib.device import DeviceBase
from bec_server.scan_server.scans import Acquire, AsyncFlyScanBase from bec_server.scan_server.scans import Acquire, AsyncFlyScanBase
from bec_lib import bec_logger
logger = bec_logger.logger
class AcquireDark(Acquire): class AcquireDark(Acquire):
scan_name = "acquire_dark" scan_name = "acquire_dark"
required_kwargs = ["exp_burst"] required_kwargs = ["exp_burst"]
@@ -295,6 +300,7 @@ class AcquireRefs(Acquire):
self.num_flats = num_flats self.num_flats = num_flats
self.file_prefix_dark = file_prefix_dark self.file_prefix_dark = file_prefix_dark
self.file_prefix_white = file_prefix_white self.file_prefix_white = file_prefix_white
self.scan_parameters["std_daq_params"] = {"reconnect": False}
def scan_core(self): def scan_core(self):
@@ -308,11 +314,16 @@ class AcquireRefs(Acquire):
) )
# to set signals on a device # to set signals on a device
yield from self.stubs.send_rpc_and_wait("gfdaq", "file_prefix.set", self.file_prefix_dark) cameras = [cam.name for cam in self.device_manager.devices.get_devices_with_tags("camera") if cam.enabled]
# yield from self.stubs.send_rpc_and_wait("gfdaq", "num_images.set", self.num_darks) for cam in cameras:
yield from self.stubs.send_rpc_and_wait(cam, "file_prefix.set", f"{self.file_prefix}_{cam}_dark")
yield from self.stubs.send_rpc_and_wait(cam, "num_images.set", self.num_darks)
yield from self.stubs.send_rpc_and_wait(cam, "bluestage") # rename to arm
darks = AcquireDark( darks = AcquireDark(
exp_burst=self.num_darks, exp_burst=self.num_darks,
# file_prefix=self.file_prefix_dark,
device_manager=self.device_manager, device_manager=self.device_manager,
metadata=self.metadata, metadata=self.metadata,
instruction_handler=self.stubs._instruction_handler, instruction_handler=self.stubs._instruction_handler,
@@ -320,33 +331,52 @@ class AcquireRefs(Acquire):
) )
yield from darks.scan_core() yield from darks.scan_core()
yield from self.stubs.send_rpc_and_wait("gfdaq", "complete")
yield from self.stubs.send_rpc_and_wait("gfdaq", "unstage")
self.point_id = darks.point_id self.point_id = darks.point_id
status_sample_out_angle.wait() status_sample_out_angle.wait()
# if self.num_flats: if self.num_flats:
# self.connector.send_client_info( self.connector.send_client_info(
# f"Acquiring {self.num_flats} flat field images", f"Acquiring {self.num_flats} flat field images",
# show_asap=True, show_asap=True,
# rid=self.metadata.get("RID"), rid=self.metadata.get("RID"),
# ) )
# yield from self.stubs.send_rpc_and_wait("gfdaq", "file_prefix.set", self.file_prefix_white) yield from self.stubs.send_rpc_and_wait("gfdaq", "file_prefix.set", self.file_prefix_white)
# yield from self.stubs.send_rpc_and_wait("gfdaq", "num_images.set", self.num_flats) yield from self.stubs.send_rpc_and_wait("gfdaq", "num_images.set", self.num_flats)
yield from self.stubs.send_rpc_and_wait("gfdaq", "bluestage")
# flats = AcquireWhite( logger.warning("Calling AcquireWhite")
# exp_burst=self.num_flats,
# #sample_position_out=self.sample_position_out, flats = AcquireWhite(
# #sample_angle_out=self.sample_angle_out, exp_burst=self.num_flats,
# #motor=self.motor, #sample_position_out=self.sample_position_out,
# device_manager=self.device_manager, #sample_angle_out=self.sample_angle_out,
# metadata=self.metadata, #motor=self.motor,
# instruction_handler=self.stubs._instruction_handler, device_manager=self.device_manager,
# **self.caller_kwargs, metadata=self.metadata,
# ) instruction_handler=self.stubs._instruction_handler,
# flats.point_id = self.point_id **self.caller_kwargs,
# yield from flats.scan_core() )
# self.point_id = flats.point_id
# ## TODO move sample in beam and do not wait
# ## TODO move rotation to angle and do not wait
flats.point_id = self.point_id
yield from flats.scan_core()
logger.warning("Unstaging the DAQ")
yield from self.stubs.send_rpc_and_wait("gfdaq", "complete")
yield from self.stubs.send_rpc_and_wait("gfdaq", "unstage")
logger.warning("Completing the DAQ")
logger.warning("Finished the DAQ")
self.point_id = flats.point_id
## TODO move sample in beam and do not wait
## TODO move rotation to angle and do not wait
logger.warning("Done with scan_core")
class TutorialFlyScanContLine(AsyncFlyScanBase): class TutorialFlyScanContLine(AsyncFlyScanBase):

View File

@@ -547,3 +547,19 @@ class Measurement:
image_height=self.roiy, acq_mode='default', file_path=self.file_path, nr_writers=2, base_path=self.base_path, image_height=self.roiy, acq_mode='default', file_path=self.file_path, nr_writers=2, base_path=self.base_path,
file_prefix_dark=file_prefix_dark, file_prefix_white=file_prefix_white, file_prefix_dark=file_prefix_dark, file_prefix_white=file_prefix_white,
ddc_trigger=4, ddc_source0=1, **kwargs) ddc_trigger=4, ddc_source0=1, **kwargs)
def start_preview(self, exposure_time=None, exposure_period=None,
preview_strategy='', preview_paramters=200, **kwargs):
"""
Start the camera in preview mode, no data will be written.
Parameters
----------
exposure_time : float, optional
"""
if exposure_time is None:
exposure_time = self.exposure_time
if exposure_period is None:
exposure_period = 50 # no need to go faster for a preview