fix: online changes to integrate devices in BEC

This commit is contained in:
e21206 2023-08-30 22:27:47 +02:00
parent d694f6594d
commit fbfa562713
10 changed files with 122 additions and 43 deletions

View File

@ -334,7 +334,8 @@ class DelayGeneratorDG645(Device):
self._producer = bec_utils.MockProducer()
self.device_manager = bec_utils.MockDeviceManager()
self.scaninfo = BecScaninfoMixin(device_manager, sim_mode)
self.all_channels = ["channelT0", "channelAB", "channelCD", "channelEF", "channelGH"]
self._all_channels = ["channelT0", "channelAB", "channelCD", "channelEF", "channelGH"]
self._all_delay_pairs = ["AB", "CD", "EF", "GH"]
self.wait_for_connection() # Make sure to be connected before talking to PVs
self._init_ddg()
self._ddg_is_okay()
@ -386,7 +387,7 @@ class DelayGeneratorDG645(Device):
def _set_channels(self, signal: str, value: Any, channels: List = None) -> None:
if not channels:
channels = self.all_channels
channels = self._all_channels
for chname in channels:
channel = getattr(self, chname, None)
if not channel:
@ -404,6 +405,17 @@ class DelayGeneratorDG645(Device):
self._init_ddg_pol_allchannels(self.polarity.get())
self._init_ddg_amp_allchannels(self.amplitude.get())
self._init_ddg_offset_allchannels(self.offset.get())
self._set_channels(
"reference",
0,
[f"channel{self._all_delay_pairs[ii]}.ch1" for ii in range(len(self._all_delay_pairs))],
)
for ii in range(len(self._all_delay_pairs)):
self._set_channels(
"reference",
2 * ii + 1,
[f"channel{self._all_delay_pairs[ii]}.ch2"],
)
self._set_trigger(TriggerSource.SINGLE_SHOT)
self.level.set(self.thres_trig_level.get())
@ -474,6 +486,7 @@ class DelayGeneratorDG645(Device):
# if self.scaninfo.scan_type == "step":
if self.source.read()[self.source.name]["value"] == int(TriggerSource.SINGLE_SHOT):
self.trigger_shot.set(1).wait()
super().trigger()
def burstEnable(self, count, delay, period, config="all"):
"""Enable the burst mode"""

View File

@ -21,3 +21,8 @@ from .specMotors import (
from ophyd import EpicsSignal, EpicsSignalRO, EpicsMotor
from ophyd.sim import SynAxis, SynSignal, SynPeriodicSignal
from ophyd.quadem import QuadEM
# cSAXS
from .mcs_csaxs import McsCsaxs
from .eiger9m_csaxs import Eiger9mCsaxs
from .pilatus_csaxs import PilatusCsaxs

View File

@ -7,6 +7,21 @@ class BecScaninfoMixin:
def __init__(self, device_manager: DeviceManagerBase = None, sim_mode=False) -> None:
self.device_manager = device_manager
self.sim_mode = sim_mode
self.bec_info_msg = {
"RID": "mockrid",
"queueID": "mockqueuid",
"scan_number": 1,
"exp_time": 26e-3,
"num_points": 10000,
"readout_time": 2e-3,
"scan_type": "fly",
}
def get_bec_info_msg(self) -> None:
return self.bec_info_msg
def change_config(self, bec_info_msg: dict) -> None:
self.bec_info_msg = bec_info_msg
def _get_current_scan_msg(self) -> BECMessage.ScanStatusMessage:
if not self.sim_mode:
@ -16,15 +31,7 @@ class BecScaninfoMixin:
return BECMessage.ScanStatusMessage(
scanID="1",
status={},
info={
"RID": "mockrid",
"queueID": "mockqueuid",
"scan_number": 1,
"exp_time": 26e-3,
"num_points": 10000,
"readout_time": 2e-3,
"scan_type": "fly",
},
info=self.bec_info_msg,
)
def _get_username(self) -> str:

View File

@ -4,7 +4,7 @@ from typing import Any, List
import numpy as np
from ophyd import EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV
from ophyd import CamBase, DetectorBase
from ophyd import CamBase, DetectorBase, Device
from ophyd import ADComponent as ADCpt
from ophyd.areadetector.plugins import FileBase
@ -25,7 +25,7 @@ class EigerError(Exception):
pass
class SlsDetectorCam(CamBase, FileBase):
class SlsDetectorCam(Device): # CamBase, FileBase):
detector_type = ADCpt(EpicsSignalRO, "DetectorType_RBV")
setting = ADCpt(EpicsSignalWithRBV, "Setting")
delay_time = ADCpt(EpicsSignalWithRBV, "DelayTime")
@ -63,6 +63,10 @@ class SlsDetectorCam(CamBase, FileBase):
json_frame_mode = ADCpt(EpicsSignalWithRBV, "JsonFrameMode")
json_detector_mode = ADCpt(EpicsSignalWithRBV, "JsonDetectorMode")
# fixes due to missing PVs from CamBase
acquire = ADCpt(EpicsSignal, "Acquire")
detector_state = ADCpt(EpicsSignalRO, "DetectorState_RBV")
class TriggerSource(int, enum.Enum):
AUTO = 0
@ -127,8 +131,8 @@ class Eiger9mCsaxs(DetectorBase):
self.name = name
self.wait_for_connection() # Make sure to be connected before talking to PVs
if not sim_mode:
self._producer = self.device_manager.producer
self.device_manager = device_manager
self._producer = self.device_manager.producer
else:
self._producer = bec_utils.MockProducer()
self.device_manager = bec_utils.MockDeviceManager()
@ -139,7 +143,6 @@ class Eiger9mCsaxs(DetectorBase):
self.filewriter = FileWriterMixin(self.service_cfg)
self.reduce_readout = 1e-3 # 3 ms
self.triggermode = 0 # 0 : internal, scan must set this if hardware triggered
self.mokev = 12
self._init_eiger9m()
self._init_standard_daq()
@ -149,7 +152,6 @@ class Eiger9mCsaxs(DetectorBase):
def _init_eiger9m(self) -> None:
"""Init parameters for Eiger 9m"""
self._set_det_threshold()
self._set_trigger(TriggerSource.GATING)
self.cam.acquire.set(0)
@ -184,7 +186,7 @@ class Eiger9mCsaxs(DetectorBase):
def _prep_det(self) -> None:
self._set_det_threshold()
self._set_acquisition_params()
self._set_trigger(TriggerSource.TRIGGER)
self._set_trigger(TriggerSource.GATING)
def _set_det_threshold(self) -> None:
# threshold_energy PV exists on Eiger 9M?
@ -226,7 +228,6 @@ class Eiger9mCsaxs(DetectorBase):
self.std_client.start_writer_async(
{"output_file": self.filepath, "n_images": self.scaninfo.num_frames}
)
logger.info("Waiting for std daq to be armed")
while True:
det_ctrl = self.std_client.get_status()["acquisition"]["state"]
if det_ctrl == "WAITING_IMAGES":
@ -240,16 +241,18 @@ class Eiger9mCsaxs(DetectorBase):
def stage(self) -> List[object]:
"""stage the detector and file writer"""
self.scaninfo.load_scan_metadata()
self.mokev = self.device_manager.devices.mokev.read()[
self.mokev = self.device_manager.devices.mokev.obj.read()[
self.device_manager.devices.mokev.name
]["value"]
self._prep_det()
logger.info("Waiting for std daq to be armed")
self._prep_file_writer()
logger.info("std_daq is ready")
msg = BECMessage.FileMessage(file_path=self.filepath, done=False)
self._producer.set_and_publish(
MessageEndpoints.public_file(self.scaninfo.scanID, "eiger9m"),
MessageEndpoints.public_file(self.scaninfo.scanID, self.name),
msg.dumps(),
)
self.arm_acquisition()
@ -279,13 +282,13 @@ class Eiger9mCsaxs(DetectorBase):
break
time.sleep(0.005)
# Message to BEC
# state = True
state = True
# msg = BECMessage.FileMessage(file_path=self.filepath, done=True, successful=state)
# self._producer.set_and_publish(
# MessageEndpoints.public_file(self.metadata["scanID"], self.name),
# msg.dumps(),
# )
msg = BECMessage.FileMessage(file_path=self.filepath, done=True, successful=state)
self._producer.set_and_publish(
MessageEndpoints.public_file(self.scaninfo.scanID, self.name),
msg.dumps(),
)
return super().unstage()
def arm_acquisition(self) -> None:

View File

@ -9,6 +9,9 @@ from ophyd.areadetector.plugins import HDF5Plugin, HDF5Plugin_V21, FilePlugin_V2
from bec_lib.core.file_utils import FileWriterMixin
from bec_lib.core import MessageEndpoints, BECMessage, RedisConnector
from bec_lib.core import bec_logger
from ophyd_devices.epics.devices.bec_scaninfo_mixin import BecScaninfoMixin
from ophyd_devices.utils import bec_utils
logger = bec_logger.logger
@ -34,6 +37,10 @@ class EpicsDXPFalcon(Device):
current_pixel = Cpt(EpicsSignalRO, "CurrentPixel")
class FalconError(Exception):
pass
class FalconHDF5Plugins(HDF5Plugin_V21, FilePlugin_V22):
pass
@ -80,6 +87,7 @@ class FalconCsaxs(Device):
configuration_attrs=None,
parent=None,
device_manager=None,
sim_mode=False,
**kwargs,
):
super().__init__(
@ -91,15 +99,23 @@ class FalconCsaxs(Device):
parent=parent,
**kwargs,
)
self.device_manager = device_manager
self.name = name
self.username = "e21206"
# TODO once running from BEC
# self.username = self.device_manager.producer.get(MessageEndpoints.account()).decode()
if device_manager is None and not sim_mode:
raise FalconError("Add DeviceManager to initialization or init with sim_mode=True")
self.service_cfg = {"base_path": f"/sls/X12SA/data/{self.username}/Data10/data/"}
self.name = name
self.wait_for_connection() # Make sure to be connected before talking to PVs
if not sim_mode:
self.device_manager = device_manager
self._producer = self.device_manager.producer
else:
self._producer = bec_utils.MockProducer()
self.device_manager = bec_utils.MockDeviceManager()
self.scaninfo = BecScaninfoMixin(device_manager, sim_mode)
# TODO
self.scaninfo.username = "e21206"
self.service_cfg = {"base_path": f"/sls/X12SA/data/{self.scaninfo.username}/Data10/"}
self.filewriter = FileWriterMixin(self.service_cfg)
self._producer = RedisConnector(["localhost:6379"]).producer()
self.readout = 0.003 # 3 ms
self._value_pixel_per_buffer = 16
# TODO create file template from filewriter compile filename
@ -218,3 +234,20 @@ class FalconCsaxs(Device):
# TODO raise error
logger.warning("Returned in unknown state")
return state
def stop(self, *, success=False) -> None:
"""Stop acquisition
Stop or Stop and Erase
"""
self._clean_up.set(1)
# self.erase_all.set(1)
self.unstage()
super().stop(success=success)
self._stopped = True
# Automatically connect to test environmenr if directly invoked
if __name__ == "__main__":
falcon = FalconCsaxs(name="falcon", prefix="X12SA-SITORO::", sim_mode=True)
falcon.stage()

View File

@ -154,8 +154,8 @@ class McsCsaxs(SIS38XX):
self.name = name
self.wait_for_connection() # Make sure to be connected before talking to PVs
if not sim_mode:
self._producer = self.device_manager.producer
self.device_manager = device_manager
self._producer = self.device_manager.producer
else:
self._producer = bec_utils.MockProducer()
self.device_manager = bec_utils.MockDeviceManager()
@ -164,6 +164,7 @@ class McsCsaxs(SIS38XX):
self.scaninfo.username = "e21206"
self.service_cfg = {"base_path": f"/sls/X12SA/data/{self.scaninfo.username}/Data10/"}
self.filewriter = FileWriterMixin(self.service_cfg)
self._stopped = False
self._init_mcs()
def _init_mcs(self) -> None:
@ -202,11 +203,12 @@ class McsCsaxs(SIS38XX):
"""Set readout mode of mcs card
Check ReadoutMode class for more information about options
"""
# self.read_mode.set(ReadoutMode.EVENT)
self.read_mode.set(ReadoutMode.PASSIVE)
def _read_mcs_card(self) -> None:
# TODO how to properly trigger the readout!!!
self.read_all.set(1)
self.read_all.put(1, use_complete=False)
def readout_data(self) -> List:
self._read_mcs_card()
@ -250,8 +252,11 @@ class McsCsaxs(SIS38XX):
det_ctrl = self.acquiring.read()[self.acquiring.name]["value"]
if det_ctrl == 0:
break
if self._stopped:
break
time.sleep(0.005)
self._read_mcs_card()
if not self._stopped:
self._read_mcs_card()
# Message to BEC
# state = True
@ -260,6 +265,7 @@ class McsCsaxs(SIS38XX):
# MessageEndpoints.public_file(self.metadata["scanID"], self.name),
# msg.dumps(),
# )
self._stopped = False
return super().unstage()
def arm_acquisition(self) -> None:
@ -277,7 +283,7 @@ class McsCsaxs(SIS38XX):
"""
self.stop_all.set(1)
# self.erase_all.set(1)
self.unstage()
# self.unstage()
super().stop(success=success)
self._stopped = True

View File

@ -248,3 +248,9 @@ class PilatusCsaxs(DetectorBase):
self.unstage()
super().stop(success=success)
self._stopped = True
# Automatically connect to test environmenr if directly invoked
if __name__ == "__main__":
pilatus_2 = PilatusCsaxs(name="pilatus_2", prefix="X12SA-ES-PILATUS300K:", sim_mode=True)
pilatus_2.stage()

View File

@ -181,7 +181,7 @@ class MonoTheta2(VirtualEpicsSignalRO):
MONO_THETA2_OFFSETS_FILENAME = (
"/import/work/sls/spec/local/X12SA/macros/spec_data/mono_th2_offsets.txt"
"/sls/X12SA/data/gac-x12saop/spec/macros/spec_data/mono_th2_offsets.txt"
)

View File

@ -247,6 +247,7 @@ class GalilController(Controller):
interval_x: int,
exp_time: float,
readtime: float,
**kwargs,
) -> tuple:
"""_summary_
@ -266,9 +267,8 @@ class GalilController(Controller):
LimitError: Raised if the speed is above 2mm/s or below 0.02mm/s
"""
# time.sleep(0.2)
#
axes_referenced = self.controller.axis_is_referenced()
# Check limits
# TODO check sign of stage, or not necessary
check_values = [start_y, end_y, start_x, end_x]

View File

@ -16,9 +16,15 @@ class MockDeviceManager:
self.devices = devices()
class OphydObject:
def __init__(self) -> None:
self.name = "mock_mokev"
self.obj = mokev()
class devices:
def __init__(self):
self.mokev = mokev()
self.mokev = OphydObject()
class mokev:
@ -26,4 +32,4 @@ class mokev:
self.name = "mock_mokev"
def read(self):
return {self.name: {"value": 12.4, "timestamp": time.time()}}
return {self.name: {"value": 16.0, "timestamp": time.time()}}