mirror of
https://github.com/bec-project/ophyd_devices.git
synced 2025-05-25 09:50:41 +02:00
fix: online changes to integrate devices in BEC
This commit is contained in:
parent
d694f6594d
commit
fbfa562713
@ -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"""
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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"
|
||||
)
|
||||
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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()}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user