Add script test_falcon.py, which allows testing falcon device in local iphython shell

This commit is contained in:
gac-x07mb
2024-10-17 14:46:13 +02:00
committed by wakonig_k
parent e10be3e9bf
commit 55e723ba24
5 changed files with 864 additions and 38 deletions

View File

@ -387,15 +387,15 @@ class FalconPhoenix(PSIDetectorBase):
# Parameters for individual detector elements
# Note: need to wrote 'dxp: here, but not dxp'
dxp1 = Cpt(EpicsDXPFalcon, "dxp1:")
dxp2 = Cpt(EpicsDXPFalcon, "dxp2:")
dxp3 = Cpt(EpicsDXPFalcon, "dxp3:")
dxp4 = Cpt(EpicsDXPFalcon, "dxp4:")
# dxp2 = Cpt(EpicsDXPFalcon, "dxp2:")
# dxp3 = Cpt(EpicsDXPFalcon, "dxp3:")
# dxp4 = Cpt(EpicsDXPFalcon, "dxp4:")
# need to write 'mca1', but not 'mca1:'
mca1 = Cpt(EpicsMCARecord, "mca1")
mca2 = Cpt(EpicsMCARecord, "mca2")
mca3 = Cpt(EpicsMCARecord, "mca3")
mca4 = Cpt(EpicsMCARecord, "mca4")
# mca2 = Cpt(EpicsMCARecord, "mca2")
# mca3 = Cpt(EpicsMCARecord, "mca3")
# mca4 = Cpt(EpicsMCARecord, "mca4")
# other general parameters
hdf5 = Cpt(FalconHDF5Plugins, "HDF1:")
@ -435,4 +435,4 @@ class FalconPhoenix(PSIDetectorBase):
if __name__ == "__main__":
falcon = FalconPHOENIX(name="falcon_hdf5", prefix="X07MB-SITORO:", sim_mode=True)
falcon = FalconPhoenix(name="falcon_hdf5", prefix="X07MB-SITORO:", sim_mode=True)

View File

@ -0,0 +1,240 @@
335.86742186546326 sec Dummy_device Dummy_PSIDetector.__init__
335.87204146385193 sec Dummy_device Dummy_PSIDetector._update_scaninfo
335.8751003742218 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
335.8772876262665 sec Dummy_device Dummy_PSIDetector._update_filewriter
335.87958455085754 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
335.88146352767944 sec Dummy_device Dummy_PSIDetector._init
335.8835377693176 sec Dummy_device Dummy_PSIDetector._init ... done
335.88587188720703 sec Dummy_device Dummy_PSIDetector._update_service_config
335.88780546188354 sec Dummy_device Dummy_PSIDetector._update_scaninfo
335.8908131122589 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
335.8929853439331 sec Dummy_device Dummy_PSIDetector._update_filewriter
335.89518213272095 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
335.8972976207733 sec Dummy_device Dummy_PSIDetector._init
335.8996033668518 sec Dummy_device Dummy_PSIDetector._init ... done
335.9022822380066 sec Dummy_device Dummy_PSIDetector.__init__ .. done
300.2472941875458 sec Dummy_device Dummy_PSIDetector.__init__
300.2497909069061 sec Dummy_device Dummy_PSIDetector._update_scaninfo
300.2532637119293 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
300.2575738430023 sec Dummy_device Dummy_PSIDetector._update_filewriter
300.25977396965027 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
300.26182532310486 sec Dummy_device Dummy_PSIDetector._init
300.263964176178 sec Dummy_device Dummy_PSIDetector._init ... done
300.26622343063354 sec Dummy_device Dummy_PSIDetector._update_service_config
300.2685146331787 sec Dummy_device Dummy_PSIDetector._update_scaninfo
300.27183842658997 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
300.27371311187744 sec Dummy_device Dummy_PSIDetector._update_filewriter
300.27582836151123 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
300.27784299850464 sec Dummy_device Dummy_PSIDetector._init
300.27999567985535 sec Dummy_device Dummy_PSIDetector._init ... done
300.28196930885315 sec Dummy_device Dummy_PSIDetector.__init__ .. done
328.7905592918396 sec Dummy_device Dummy_PSIDetector.__init__
328.7932097911835 sec Dummy_device Dummy_PSIDetector._update_scaninfo
328.7954728603363 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
328.79737162590027 sec Dummy_device Dummy_PSIDetector._update_filewriter
328.7993049621582 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
328.80120611190796 sec Dummy_device Dummy_PSIDetector._init
328.8031406402588 sec Dummy_device Dummy_PSIDetector._init ... done
328.80515456199646 sec Dummy_device Dummy_PSIDetector._update_service_config
328.807252407074 sec Dummy_device Dummy_PSIDetector._update_scaninfo
328.81015849113464 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
328.81217980384827 sec Dummy_device Dummy_PSIDetector._update_filewriter
328.81431341171265 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
328.81639194488525 sec Dummy_device Dummy_PSIDetector._init
328.8186950683594 sec Dummy_device Dummy_PSIDetector._init ... done
328.82083559036255 sec Dummy_device Dummy_PSIDetector.__init__ .. done
475.4403340816498 sec Dummy_device Dummy_PSIDetector.__init__
475.4432635307312 sec Dummy_device Dummy_PSIDetector._update_scaninfo
475.44979977607727 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
475.4522285461426 sec Dummy_device Dummy_PSIDetector._update_filewriter
475.4545283317566 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
475.456636428833 sec Dummy_device Dummy_PSIDetector._init
475.45890951156616 sec Dummy_device Dummy_PSIDetector._init ... done
475.4610731601715 sec Dummy_device Dummy_PSIDetector._update_service_config
475.46812438964844 sec Dummy_device Dummy_PSIDetector._update_scaninfo
475.4717495441437 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
475.47418761253357 sec Dummy_device Dummy_PSIDetector._update_filewriter
475.4776928424835 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
475.48009753227234 sec Dummy_device Dummy_PSIDetector._init
475.4822597503662 sec Dummy_device Dummy_PSIDetector._init ... done
475.4843051433563 sec Dummy_device Dummy_PSIDetector.__init__ .. done
90.38811612129211 sec Dummy_device Dummy_PSIDetector.__init__
90.39096760749817 sec Dummy_device Dummy_PSIDetector._update_scaninfo
90.39355659484863 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
90.39581418037415 sec Dummy_device Dummy_PSIDetector._update_filewriter
90.39806294441223 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
90.40018606185913 sec Dummy_device Dummy_PSIDetector._init
90.40238237380981 sec Dummy_device Dummy_PSIDetector._init ... done
90.40471291542053 sec Dummy_device Dummy_PSIDetector._update_service_config
90.4069573879242 sec Dummy_device Dummy_PSIDetector._update_scaninfo
90.41017866134644 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
90.41258692741394 sec Dummy_device Dummy_PSIDetector._update_filewriter
90.41526460647583 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
90.41762042045593 sec Dummy_device Dummy_PSIDetector._init
90.42192840576172 sec Dummy_device Dummy_PSIDetector._init ... done
90.42451310157776 sec Dummy_device Dummy_PSIDetector.__init__ .. done
109.83998537063599 sec Dummy_device Dummy_PSIDetector.__init__
109.84398102760315 sec Dummy_device Dummy_PSIDetector._update_scaninfo
109.84782004356384 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
109.8508472442627 sec Dummy_device Dummy_PSIDetector._update_filewriter
109.85375642776489 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
109.85648727416992 sec Dummy_device Dummy_PSIDetector._init
109.85949063301086 sec Dummy_device Dummy_PSIDetector._init ... done
109.8626561164856 sec Dummy_device Dummy_PSIDetector._update_service_config
109.8660044670105 sec Dummy_device Dummy_PSIDetector._update_scaninfo
109.86980724334717 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
109.8729784488678 sec Dummy_device Dummy_PSIDetector._update_filewriter
109.87575602531433 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
109.87866473197937 sec Dummy_device Dummy_PSIDetector._init
109.88176965713501 sec Dummy_device Dummy_PSIDetector._init ... done
109.8846321105957 sec Dummy_device Dummy_PSIDetector.__init__ .. done
113.19893550872803 sec Dummy_device Dummy_PSIDetector.__init__
113.20220613479614 sec Dummy_device Dummy_PSIDetector._update_scaninfo
113.20514917373657 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
113.2079541683197 sec Dummy_device Dummy_PSIDetector._update_filewriter
113.21054434776306 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
113.21308469772339 sec Dummy_device Dummy_PSIDetector._init
113.21552276611328 sec Dummy_device Dummy_PSIDetector._init ... done
113.21809101104736 sec Dummy_device Dummy_PSIDetector._update_service_config
113.2209620475769 sec Dummy_device Dummy_PSIDetector._update_scaninfo
113.22531485557556 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
113.23195886611938 sec Dummy_device Dummy_PSIDetector._update_filewriter
113.23536491394043 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
113.23783016204834 sec Dummy_device Dummy_PSIDetector._init
113.24021744728088 sec Dummy_device Dummy_PSIDetector._init ... done
113.24268960952759 sec Dummy_device Dummy_PSIDetector.__init__ .. done
162.08518886566162 sec Dummy_device Dummy_PSIDetector.__init__
162.08826613426208 sec Dummy_device Dummy_PSIDetector._update_scaninfo
162.09175372123718 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
162.0940601825714 sec Dummy_device Dummy_PSIDetector._update_filewriter
162.09600925445557 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
162.09812116622925 sec Dummy_device Dummy_PSIDetector._init
162.10056066513062 sec Dummy_device Dummy_PSIDetector._init ... done
162.10289812088013 sec Dummy_device Dummy_PSIDetector._update_service_config
162.10535383224487 sec Dummy_device Dummy_PSIDetector._update_scaninfo
162.1090052127838 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
162.11114287376404 sec Dummy_device Dummy_PSIDetector._update_filewriter
162.1133759021759 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
162.1152641773224 sec Dummy_device Dummy_PSIDetector._init
162.11768627166748 sec Dummy_device Dummy_PSIDetector._init ... done
162.11997199058533 sec Dummy_device Dummy_PSIDetector.__init__ .. done
233.90994000434875 sec Dummy_device Dummy_PSIDetector.__init__
233.91418266296387 sec Dummy_device Dummy_PSIDetector._update_scaninfo
233.91928625106812 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
233.92156839370728 sec Dummy_device Dummy_PSIDetector._update_filewriter
233.92394065856934 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
233.9268913269043 sec Dummy_device Dummy_PSIDetector._init
233.9293007850647 sec Dummy_device Dummy_PSIDetector._init ... done
233.9316327571869 sec Dummy_device Dummy_PSIDetector._update_service_config
233.9339635372162 sec Dummy_device Dummy_PSIDetector._update_scaninfo
233.939471244812 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
233.94238090515137 sec Dummy_device Dummy_PSIDetector._update_filewriter
233.9449393749237 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
233.94733595848083 sec Dummy_device Dummy_PSIDetector._init
233.95000672340393 sec Dummy_device Dummy_PSIDetector._init ... done
233.9525544643402 sec Dummy_device Dummy_PSIDetector.__init__ .. done
271.92675018310547 sec Dummy_device Dummy_PSIDetector.__init__
271.93059253692627 sec Dummy_device Dummy_PSIDetector._update_scaninfo
271.93377327919006 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
271.9364731311798 sec Dummy_device Dummy_PSIDetector._update_filewriter
271.9393870830536 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
271.9427864551544 sec Dummy_device Dummy_PSIDetector._init
271.94557547569275 sec Dummy_device Dummy_PSIDetector._init ... done
271.9482548236847 sec Dummy_device Dummy_PSIDetector._update_service_config
271.95098328590393 sec Dummy_device Dummy_PSIDetector._update_scaninfo
271.9548728466034 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
271.9576189517975 sec Dummy_device Dummy_PSIDetector._update_filewriter
271.96227741241455 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
271.9647195339203 sec Dummy_device Dummy_PSIDetector._init
271.9670441150665 sec Dummy_device Dummy_PSIDetector._init ... done
271.9696171283722 sec Dummy_device Dummy_PSIDetector.__init__ .. done
274.2615315914154 sec Dummy_device Dummy_PSIDetector.__init__
274.2650673389435 sec Dummy_device Dummy_PSIDetector._update_scaninfo
274.2682113647461 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
274.2709422111511 sec Dummy_device Dummy_PSIDetector._update_filewriter
274.27347803115845 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
274.27603006362915 sec Dummy_device Dummy_PSIDetector._init
274.27846097946167 sec Dummy_device Dummy_PSIDetector._init ... done
274.28107810020447 sec Dummy_device Dummy_PSIDetector._update_service_config
274.28359174728394 sec Dummy_device Dummy_PSIDetector._update_scaninfo
274.2874596118927 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
274.2898247241974 sec Dummy_device Dummy_PSIDetector._update_filewriter
274.29388880729675 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
274.29678750038147 sec Dummy_device Dummy_PSIDetector._init
274.2992432117462 sec Dummy_device Dummy_PSIDetector._init ... done
274.30156898498535 sec Dummy_device Dummy_PSIDetector.__init__ .. done
294.353533744812 sec Dummy_device Dummy_PSIDetector.__init__
294.3567740917206 sec Dummy_device Dummy_PSIDetector._update_scaninfo
294.35972356796265 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
294.3630163669586 sec Dummy_device Dummy_PSIDetector._update_filewriter
294.36538767814636 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
294.3680098056793 sec Dummy_device Dummy_PSIDetector._init
294.37078166007996 sec Dummy_device Dummy_PSIDetector._init ... done
294.3731310367584 sec Dummy_device Dummy_PSIDetector._update_service_config
294.3752555847168 sec Dummy_device Dummy_PSIDetector._update_scaninfo
294.37840962409973 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
294.38084959983826 sec Dummy_device Dummy_PSIDetector._update_filewriter
294.38422083854675 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
294.38660955429077 sec Dummy_device Dummy_PSIDetector._init
294.38908863067627 sec Dummy_device Dummy_PSIDetector._init ... done
294.3915419578552 sec Dummy_device Dummy_PSIDetector.__init__ .. done
304.78483295440674 sec Dummy_device Dummy_PSIDetector.__init__
304.7881119251251 sec Dummy_device Dummy_PSIDetector._update_scaninfo
304.7934236526489 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
304.79776787757874 sec Dummy_device Dummy_PSIDetector._update_filewriter
304.8020315170288 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
304.8044664859772 sec Dummy_device Dummy_PSIDetector._init
304.8082823753357 sec Dummy_device Dummy_PSIDetector._init ... done
304.81395411491394 sec Dummy_device Dummy_PSIDetector._update_service_config
304.8168818950653 sec Dummy_device Dummy_PSIDetector._update_scaninfo
304.82032346725464 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
304.8228225708008 sec Dummy_device Dummy_PSIDetector._update_filewriter
304.82708072662354 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
304.83106684684753 sec Dummy_device Dummy_PSIDetector._init
304.8337640762329 sec Dummy_device Dummy_PSIDetector._init ... done
304.8364191055298 sec Dummy_device Dummy_PSIDetector.__init__ .. done
338.80613946914673 sec Dummy_device Dummy_PSIDetector.__init__
338.8091824054718 sec Dummy_device Dummy_PSIDetector._update_scaninfo
338.81241273880005 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
338.8149781227112 sec Dummy_device Dummy_PSIDetector._update_filewriter
338.8177545070648 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
338.82268142700195 sec Dummy_device Dummy_PSIDetector._init
338.8252160549164 sec Dummy_device Dummy_PSIDetector._init ... done
338.82740783691406 sec Dummy_device Dummy_PSIDetector._update_service_config
338.8297481536865 sec Dummy_device Dummy_PSIDetector._update_scaninfo
338.83335185050964 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
338.8363780975342 sec Dummy_device Dummy_PSIDetector._update_filewriter
338.8388833999634 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
338.84141182899475 sec Dummy_device Dummy_PSIDetector._init
338.84392642974854 sec Dummy_device Dummy_PSIDetector._init ... done
338.8477563858032 sec Dummy_device Dummy_PSIDetector.__init__ .. done
344.0475420951843 sec Dummy_device Dummy_PSIDetector.__init__
344.05141711235046 sec Dummy_device Dummy_PSIDetector._update_scaninfo
344.0571393966675 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
344.060818195343 sec Dummy_device Dummy_PSIDetector._update_filewriter
344.06363105773926 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
344.0659351348877 sec Dummy_device Dummy_PSIDetector._init
344.06850934028625 sec Dummy_device Dummy_PSIDetector._init ... done
344.070965051651 sec Dummy_device Dummy_PSIDetector._update_service_config
344.0734348297119 sec Dummy_device Dummy_PSIDetector._update_scaninfo
344.07675218582153 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
344.0791103839874 sec Dummy_device Dummy_PSIDetector._update_filewriter
344.08180046081543 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
344.08495712280273 sec Dummy_device Dummy_PSIDetector._init
344.0874013900757 sec Dummy_device Dummy_PSIDetector._init ... done
344.0897550582886 sec Dummy_device Dummy_PSIDetector.__init__ .. done
376.99036693573 sec Dummy_device Dummy_PSIDetector.__init__
376.99428820610046 sec Dummy_device Dummy_PSIDetector._update_scaninfo
376.99768900871277 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
377.0007600784302 sec Dummy_device Dummy_PSIDetector._update_filewriter
377.003769159317 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
377.00663924217224 sec Dummy_device Dummy_PSIDetector._init
377.01268792152405 sec Dummy_device Dummy_PSIDetector._init ... done
377.0166575908661 sec Dummy_device Dummy_PSIDetector._update_service_config
377.0196464061737 sec Dummy_device Dummy_PSIDetector._update_scaninfo
377.02573013305664 sec Dummy_device Dummy_PSIDetector._update_scaninfo .. done
377.0286810398102 sec Dummy_device Dummy_PSIDetector._update_filewriter
377.03132462501526 sec Dummy_device Dummy_PSIDetector._update_filewriter .. done
377.0341477394104 sec Dummy_device Dummy_PSIDetector._init
377.0375759601593 sec Dummy_device Dummy_PSIDetector._init ... done
377.0406606197357 sec Dummy_device Dummy_PSIDetector.__init__ .. done

View File

@ -0,0 +1,568 @@
"""
This module contains the DeviceManagerDS class, which is a subclass of
the DeviceManagerBase class and is the main device manager for devices
in BEC. It is the only place where devices are initialized and managed.
"""
from __future__ import annotations
import inspect
import time
import traceback
from functools import reduce
import numpy as np
import ophyd
import ophyd_devices as opd
from ophyd.ophydobj import OphydObject
from ophyd.signal import EpicsSignalBase
from typeguard import typechecked
from bec_lib import messages, plugin_helper
from bec_lib.bec_errors import DeviceConfigError
from bec_lib.bec_service import BECService
from bec_lib.device import DeviceBase
from bec_lib.devicemanager import DeviceManagerBase
from bec_lib.endpoints import MessageEndpoints
from bec_lib.logger import bec_logger
from bec_server.device_server.devices.config_update_handler import ConfigUpdateHandler
from bec_server.device_server.devices.device_serializer import get_device_info
logger = bec_logger.logger
def rgetattr(obj, attr, *args):
"""See https://stackoverflow.com/questions/31174295/getattr-and-setattr-on-nested-objects"""
def _getattr(obj, attr):
return getattr(obj, attr, *args)
return reduce(_getattr, [obj] + attr.split("."))
class DSDevice(DeviceBase):
def __init__(self, name, obj, config, parent=None):
super().__init__(name=name, config=config, parent=parent)
self.obj = obj
self.metadata = {}
self.initialized = False
def __getattr__(self, name: str) -> inspect.Any:
if hasattr(self.obj, name):
# compatibility with ophyd devices accessed on the client side
return rgetattr(self.obj, name)
return super().__getattr__(name)
def initialize_device_buffer(self, connector):
"""initialize the device read and readback buffer on redis with a new reading"""
dev_msg = messages.DeviceMessage(signals=self.obj.read(), metadata={})
dev_config_msg = messages.DeviceMessage(signals=self.obj.read_configuration(), metadata={})
if hasattr(self.obj, "low_limit_travel") and hasattr(self.obj, "high_limit_travel"):
limits = {
"low": {"value": self.obj.low_limit_travel.get()},
"high": {"value": self.obj.high_limit_travel.get()},
}
else:
limits = None
pipe = connector.pipeline()
connector.set_and_publish(MessageEndpoints.device_readback(self.name), dev_msg, pipe=pipe)
connector.set_and_publish(
topic=MessageEndpoints.device_read(self.name), msg=dev_msg, pipe=pipe
)
connector.set_and_publish(
MessageEndpoints.device_read_configuration(self.name), dev_config_msg, pipe=pipe
)
if limits is not None:
connector.set_and_publish(
MessageEndpoints.device_limits(self.name),
messages.DeviceMessage(signals=limits),
pipe=pipe,
)
pipe.execute()
self.initialized = True
class DeviceManagerDS(DeviceManagerBase):
def __init__(
self,
service: BECService,
config_update_handler: ConfigUpdateHandler = None,
status_cb: list = None,
):
super().__init__(service, status_cb)
self._config_request_connector = None
self._device_instructions_connector = None
self._config_update_handler_cls = config_update_handler
self.config_update_handler = None
self.failed_devices = []
def initialize(self, bootstrap_server) -> None:
self.config_update_handler = (
self._config_update_handler_cls
if self._config_update_handler_cls is not None
else ConfigUpdateHandler(device_manager=self)
)
super().initialize(bootstrap_server)
def _reload_action(self) -> None:
pass
@staticmethod
def _get_device_class(dev_type: str) -> type:
"""Get the device class from the device type"""
return plugin_helper.get_plugin_class(dev_type, [opd, ophyd])
def _load_session(self, *_args, **_kwargs):
delayed_init = []
if not self._is_config_valid():
self._reset_config()
return
try:
self.failed_devices = {}
for dev in self._session["devices"]:
name = dev.get("name")
enabled = dev.get("enabled")
logger.info(f"Adding device {name}: {'ENABLED' if enabled else 'DISABLED'}")
dev_cls = self._get_device_class(dev.get("deviceClass"))
if issubclass(dev_cls, (opd.DeviceProxy, opd.ComputedSignal)):
delayed_init.append(dev)
continue
obj, config = self.construct_device_obj(dev, device_manager=self)
try:
self.initialize_device(dev, config, obj)
# pylint: disable=broad-except
except Exception:
msg = traceback.format_exc()
self.failed_devices[name] = msg
for dev in delayed_init:
name = dev.get("name")
obj, config = self.construct_device_obj(dev, device_manager=self)
try:
self.initialize_delayed_devices(dev, config, obj)
# pylint: disable=broad-except
except Exception:
msg = traceback.format_exc()
self.failed_devices[name] = msg
self.config_update_handler.handle_failed_device_inits()
except Exception as exc:
content = traceback.format_exc()
logger.error(
f"Failed to initialize device: {dev}: {content}. The config will be reset."
)
self._reset_config()
raise DeviceConfigError(
f"Failed to initialize device: {dev}: {content}. The config will be reset."
) from exc
def initialize_delayed_devices(self, dev: dict, config: dict, obj: OphydObject) -> None:
"""Initialize delayed device after all other devices have been initialized."""
name = dev.get("name")
enabled = dev.get("enabled")
logger.info(f"Adding device {name}: {'ENABLED' if enabled else 'DISABLED'}")
obj = self.initialize_device(dev, config, obj)
if hasattr(obj.obj, "lookup"):
self._register_device_proxy(name)
def _register_device_proxy(self, name: str) -> None:
obj_lookup = self.devices.get(name).obj.lookup
for key in obj_lookup.keys():
signal_name = obj_lookup[key].get("signal_name")
if key not in self.devices:
raise DeviceConfigError(
f"Failed to init DeviceProxy {name}, no device {key} found in device manager."
)
dev_obj = self.devices[key].obj
registered_proxies = dev_obj.registered_proxies
if not hasattr(dev_obj, signal_name):
raise DeviceConfigError(
f"Failed to init DeviceProxy {name}, no signal {signal_name} found for device {key}."
)
if key not in registered_proxies:
# pylint: disable=protected-access
self.devices[key].obj._registered_proxies.update({name: signal_name})
continue
if key in registered_proxies and signal_name not in registered_proxies[key]:
# pylint: disable=protected-access
self.devices[key].obj._registered_proxies.update({name: signal_name})
continue
if key in registered_proxies.keys() and signal_name in registered_proxies[key]:
raise RuntimeError(
f"Failed to init DeviceProxy {name}, device {key} already has a registered DeviceProxy for {signal_name}. Only one DeviceProxy can be active per signal."
)
def _reset_config(self):
current_config = self._session["devices"]
if current_config:
# store the current config in the history
current_config_msg = messages.AvailableResourceMessage(
resource=current_config, metadata={"removed_at": time.time()}
)
self.producer.lpush(
MessageEndpoints.device_config_history(), current_config_msg, max_size=50
)
msg = messages.AvailableResourceMessage(resource=[])
self.producer.set(MessageEndpoints.device_config(), msg)
reload_msg = messages.DeviceConfigMessage(action="reload", config={})
self.producer.send(MessageEndpoints.device_config_update(), reload_msg)
@staticmethod
def update_config(obj: OphydObject, config: dict) -> None:
"""Update an ophyd device's config
Args:
obj (Ophydobj): Ophyd object that should be updated
config (dict): Config dictionary
"""
if hasattr(obj, "_update_device_config"):
obj._update_device_config(config)
else:
for config_key, config_value in config.items():
# first handle the ophyd exceptions...
if config_key == "limits":
if hasattr(obj, "low_limit_travel") and hasattr(obj, "high_limit_travel"):
low_limit_status = obj.low_limit_travel.set(config_value[0])
high_limit_status = obj.high_limit_travel.set(config_value[1])
low_limit_status.wait()
high_limit_status.wait()
continue
if config_key == "labels":
if not config_value:
config_value = set()
# pylint: disable=protected-access
obj._ophyd_labels_ = set(config_value)
continue
if not hasattr(obj, config_key):
raise DeviceConfigError(
f"Unknown config parameter {config_key} for device of type"
f" {obj.__class__.__name__}."
)
config_attr = getattr(obj, config_key)
if isinstance(config_attr, ophyd.Signal):
config_attr.set(config_value)
elif callable(config_attr):
config_attr(config_value)
else:
setattr(obj, config_key, config_value)
@staticmethod
def construct_device_obj(dev: dict, device_manager: DeviceManagerDS) -> (OphydObject, dict):
"""
Construct a device object from a device config dictionary.
Args:
dev (dict): device config dictionary
device_manager (DeviceManagerDS): device manager instance
Returns:
(OphydObject, dict): device object and updated config dictionary
"""
name = dev.get("name")
dev_cls = DeviceManagerDS._get_device_class(dev["deviceClass"])
device_config = dev.get("deviceConfig")
device_config = device_config if device_config is not None else {}
config = device_config.copy()
config["name"] = name
# pylint: disable=protected-access
device_classes = [dev_cls]
if issubclass(dev_cls, ophyd.Signal):
device_classes.append(ophyd.Signal)
if issubclass(dev_cls, EpicsSignalBase):
device_classes.append(EpicsSignalBase)
if issubclass(dev_cls, ophyd.OphydObject):
device_classes.append(ophyd.OphydObject)
# get all init parameters of the device class and its parents
class_params = set()
for device_class in device_classes:
class_params.update(inspect.signature(device_class)._parameters)
class_params_and_config_keys = class_params & config.keys()
init_kwargs = {key: config.pop(key) for key in class_params_and_config_keys}
device_access = config.pop("device_access", None)
if device_access or (device_access is None and config.get("device_mapping")):
init_kwargs["device_manager"] = device_manager
signature = inspect.signature(dev_cls)
if "device_manager" in signature.parameters:
init_kwargs["device_manager"] = device_manager
# initialize the device object
obj = dev_cls(**init_kwargs)
return obj, config
def initialize_device(self, dev: dict, config: dict, obj: OphydObject) -> DSDevice:
"""
Prepares a device for later usage.
This includes inspecting the device class signature,
initializing the object, refreshing the device info and buffer,
as well as adding subscriptions.
Args:
dev (dict): device config dictionary
config (dict): device config dictionary
obj (OphydObject): device object
Returns:
DSDevice: initialized device object
"""
name = dev.get("name")
enabled = dev.get("enabled")
self.update_config(obj, config)
# refresh the device info
pipe = self.connector.pipeline()
self.reset_device_data(obj, pipe)
self.publish_device_info(obj, pipe)
pipe.execute()
# insert the created device obj into the device manager
opaas_obj = DSDevice(name=name, obj=obj, config=dev, parent=self)
# pylint:disable=protected-access # this function is shared with clients and it is currently not foreseen that clients add new devices
self.devices._add_device(name, opaas_obj)
if not enabled:
return opaas_obj
# update device buffer for enabled devices
# try:
self.initialize_enabled_device(opaas_obj)
# pylint:disable=broad-except
# except Exception:
# error_traceback = traceback.format_exc()
# logger.error(
# f"{error_traceback}. Failed to stage {opaas_obj.name}. The device will be disabled."
# )
# opaas_obj.enabled = False
obj = opaas_obj.obj
# add subscriptions
if not hasattr(obj, "event_types"):
return opaas_obj
if "readback" in obj.event_types:
obj.subscribe(self._obj_callback_readback, run=opaas_obj.enabled)
elif "value" in obj.event_types:
obj.subscribe(self._obj_callback_readback, run=opaas_obj.enabled)
if "device_monitor_2d" in obj.event_types:
obj.subscribe(self._obj_callback_device_monitor_2d, run=False)
if "done_moving" in obj.event_types:
obj.subscribe(self._obj_callback_done_moving, event_type="done_moving", run=False)
if "flyer" in obj.event_types:
obj.subscribe(self._obj_flyer_callback, event_type="flyer", run=False)
if "progress" in obj.event_types:
obj.subscribe(self._obj_progress_callback, event_type="progress", run=False)
if hasattr(obj, "motor_is_moving"):
obj.motor_is_moving.subscribe(self._obj_callback_is_moving, run=opaas_obj.enabled)
if hasattr(obj, "component_names"):
for component_name in obj.component_names:
component = getattr(obj, component_name)
if not getattr(component, "_auto_monitor", False):
continue
if component.kind in (ophyd.Kind.normal, ophyd.Kind.hinted):
component.subscribe(self._obj_callback_readback, run=False)
elif component.kind == ophyd.Kind.config:
component.subscribe(self._obj_callback_configuration, run=False)
return opaas_obj
def initialize_enabled_device(self, opaas_obj):
"""connect to an enabled device and initialize the device buffer"""
self.connect_device(opaas_obj.obj)
opaas_obj.initialize_device_buffer(self.connector)
@staticmethod
def disconnect_device(obj):
"""disconnect from a device"""
if not obj.connected:
return
if hasattr(obj, "controller"):
obj.controller.off()
return
obj.destroy()
def reset_device(self, obj: DSDevice):
"""reset a device"""
obj.initialized = False
@staticmethod
def connect_device(obj, wait_for_all=False):
"""establish a connection to a device"""
try:
if obj.connected:
return
if hasattr(obj, "controller"):
obj.controller.on()
return
if hasattr(obj, "wait_for_connection"):
try:
obj.wait_for_connection(all_signals=wait_for_all, timeout=30)
except TypeError:
obj.wait_for_connection(timeout=30)
return
logger.error(
f"Device {obj.name} does not implement the socket controller interface nor"
" wait_for_connection and cannot be turned on."
)
raise ConnectionError(f"Failed to establish a connection to device {obj.name}")
except Exception:
error_traceback = traceback.format_exc()
logger.error(f"{error_traceback}. Failed to connect to {obj.name}.")
raise ConnectionError(f"Failed to establish a connection to device {obj.name}")
def publish_device_info(self, obj: OphydObject, pipe=None) -> None:
"""
Publish the device info to redis. The device info contains
inter alia the class name, user functions and signals.
Args:
obj (_type_): _description_
"""
interface = get_device_info(obj)
self.connector.set(
MessageEndpoints.device_info(obj.name),
messages.DeviceInfoMessage(device=obj.name, info=interface),
pipe,
)
def reset_device_data(self, obj: OphydObject, pipe=None) -> None:
"""delete all device data and device info"""
self.connector.delete(MessageEndpoints.device_status(obj.name), pipe)
self.connector.delete(MessageEndpoints.device_read(obj.name), pipe)
self.connector.delete(MessageEndpoints.device_info(obj.name), pipe)
def _obj_callback_readback(self, *_args, obj: OphydObject, **kwargs):
if not obj.connected:
return
name = obj.root.name
signals = obj.root.read()
metadata = self.devices.get(obj.root.name).metadata
dev_msg = messages.DeviceMessage(signals=signals, metadata=metadata)
pipe = self.connector.pipeline()
self.connector.set_and_publish(MessageEndpoints.device_readback(name), dev_msg, pipe)
pipe.execute()
def _obj_callback_configuration(self, *_args, obj: OphydObject, **kwargs):
if not obj.connected:
return
name = obj.root.name
signals = obj.root.read_configuration()
metadata = self.devices.get(obj.root.name).metadata
dev_msg = messages.DeviceMessage(signals=signals, metadata=metadata)
pipe = self.connector.pipeline()
self.connector.set_and_publish(
MessageEndpoints.device_read_configuration(name), dev_msg, pipe
)
pipe.execute()
@typechecked
def _obj_callback_device_monitor_2d(
self, *_args, obj: OphydObject, value: np.ndarray, timestamp: float | None = None, **kwargs
):
"""
Callback for ophyd monitor events. Sends the data to redis.
Introduces a check of the data size, and incoporates a limit which is defined in max_size (in MB)
Args:
obj (OphydObject): ophyd object
value (np.ndarray): data from ophyd device
"""
# Convert sizes from bytes to MB
dsize = len(value.tobytes()) / 1e6
max_size = 1000
if dsize > max_size:
logger.warning(
f"Data size of single message is too large to send, current max_size {max_size}."
)
return
if obj.connected:
name = obj.root.name
metadata = self.devices[name].metadata
msg = messages.DeviceMonitor2DMessage(
device=name,
data=value,
metadata=metadata,
timestamp=timestamp if timestamp else time.time(),
)
stream_msg = {"data": msg}
self.connector.xadd(
MessageEndpoints.device_monitor_2d(name),
stream_msg,
max_size=min(100, int(max_size // dsize)),
)
def _obj_callback_acq_done(self, *_args, **kwargs):
device = kwargs["obj"].root.name
status = 0
metadata = self.devices[device].metadata
self.connector.set(
MessageEndpoints.device_status(device),
messages.DeviceStatusMessage(device=device, status=status, metadata=metadata),
)
def _obj_callback_done_moving(self, *args, **kwargs):
self._obj_callback_readback(*args, **kwargs)
# self._obj_callback_acq_done(*args, **kwargs)
def _obj_callback_is_moving(self, *_args, **kwargs):
device = kwargs["obj"].root.name
status = int(kwargs.get("value"))
metadata = self.devices[device].metadata
self.connector.set(
MessageEndpoints.device_status(device),
messages.DeviceStatusMessage(device=device, status=status, metadata=metadata),
)
def _obj_flyer_callback(self, *_args, **kwargs):
obj = kwargs["obj"]
data = kwargs["value"].get("data")
ds_obj = self.devices[obj.root.name]
metadata = ds_obj.metadata
if "scan_id" not in metadata:
return
if not hasattr(ds_obj, "emitted_points"):
ds_obj.emitted_points = {}
emitted_points = ds_obj.emitted_points.get(metadata["scan_id"], 0)
# make sure all arrays are of equal length
max_points = min(len(d) for d in data.values())
bundle = messages.BundleMessage()
for ii in range(emitted_points, max_points):
timestamp = time.time()
signals = {}
for key, val in data.items():
signals[key] = {"value": val[ii], "timestamp": timestamp}
bundle.append(
messages.DeviceMessage(signals=signals, metadata={"point_id": ii, **metadata})
)
ds_obj.emitted_points[metadata["scan_id"]] = max_points
pipe = self.connector.pipeline()
self.connector.send(MessageEndpoints.device_read(obj.root.name), bundle, pipe=pipe)
msg = messages.DeviceStatusMessage(
device=obj.root.name, status=max_points, metadata=metadata
)
self.connector.set_and_publish(
MessageEndpoints.device_progress(obj.root.name), msg, pipe=pipe
)
pipe.execute()
def _obj_progress_callback(self, *_args, obj, value, max_value, done, **kwargs):
metadata = self.devices[obj.root.name].metadata
msg = messages.ProgressMessage(
value=value, max_value=max_value, done=done, metadata=metadata
)
self.connector.set_and_publish(MessageEndpoints.device_progress(obj.root.name), msg)

View File

@ -0,0 +1,17 @@
# against all rues, make sure ff and falcon are really
# creates newly
ff = 0
falcon = 0
from ophyd import Component as Cpt
import phoenix_bec.devices.falcon_phoenix as ff
falcon = ff.FalconPhoenix(name="falcon_hdf5", prefix="X07MB-SITORO:")
# make a 'get to read all epics channels
# there will be an error message, if device contains a channel whcih does not exist
w = falcon.get()
print(w)

View File

@ -1,42 +1,44 @@
from ophyd import Device, EpicsMotor, EpicsSignal, EpicsSignalRO
from ophyd import Component as Cpt
#option I via direct acces to classes
# option I via direct acces to classes
def print_dic(clname,cl):
print('')
print('-------- ',clname)
def print_dic(clname, cl):
print("")
print("-------- ", clname)
for ii in cl.__dict__:
if '_' not in ii:
if "_" not in ii:
try:
print(ii,' ---- ',cl.__getattribute__(ii))
print(ii, " ---- ", cl.__getattribute__(ii))
except:
print(ii)
ScanX = EpicsMotor(name='ScanX',prefix='X07MB-ES-MA1:ScanX')
ScanY = EpicsMotor(name='ScanY',prefix='X07MB-ES-MA1:ScanY')
DIODE = EpicsSignal(name='SI',read_pv='X07MB-OP2-SAI_07:MEAN')
SMPL = EpicsSignal(name='SMPL',read_pv='X07MB-OP2:SMPL')
CYCLES = EpicsSignal(name='SMPL',read_pv='X07MB-OP2:TOTAL-CYCLES',write_pv='X07MB-OP2:TOTAL-CYCLES')
ScanX = EpicsMotor(name="ScanX", prefix="X07MB-ES-MA1:ScanX")
ScanY = EpicsMotor(name="ScanY", prefix="X07MB-ES-MA1:ScanY")
DIODE = EpicsSignal(name="SI", read_pv="X07MB-OP2-SAI_07:MEAN")
SMPL = EpicsSignal(name="SMPL", read_pv="X07MB-OP2:SMPL")
CYCLES = EpicsSignal(
name="SMPL", read_pv="X07MB-OP2:TOTAL-CYCLES", write_pv="X07MB-OP2:TOTAL-CYCLES"
)
#prefix='XXXX:'
y_cpt = Cpt(EpicsMotor, 'ScanX')
# prefix='XXXX:'
y_cpt = Cpt(EpicsMotor, "ScanX")
# Option 2 using component
device_ins=Device('X07MB-ES-MA1:',name=('device_name'))
print(' initialzation of device_in=Device(X07MB-ES-MA1:,name=(device_name)')
print('device_ins.__init__')
device_ins = Device("X07MB-ES-MA1:", name=("device_name"))
print(" initialzation of device_in=Device(X07MB-ES-MA1:,name=(device_name)")
print("device_ins.__init__")
print(device_ins.__init__)
print_dic('class Device',Device)
print_dic('instance of device device_ins',device_ins)
print_dic("class Device", Device)
print_dic("instance of device device_ins", device_ins)
print(' ')
print('DEFINE class StageXY... prefix variable not defined ')
print(" ")
print("DEFINE class StageXY... prefix variable not defined ")
class StageXY(Device):
@ -48,20 +50,19 @@ class StageXY(Device):
# hard to understand, moist likely using calss methods..
#
x = Cpt(EpicsMotor, 'ScanX')
y = Cpt(EpicsMotor, 'ScanY')
x = Cpt(EpicsMotor, "ScanX")
y = Cpt(EpicsMotor, "ScanY")
# end class
print()
print('init xy_stage, use input parameter from Device and prefix is defined in call ')
xy_stage = StageXY('X07MB-ES-MA1:', name='stageXXX')
print_dic('class StageXY',StageXY)
print_dic('instance of StageXY',xy_stage)
print("init xy_stage, use input parameter from Device and prefix is defined in call ")
xy_stage = StageXY("X07MB-ES-MA1:", name="stageXXX")
print_dic("class StageXY", StageXY)
print_dic("instance of StageXY", xy_stage)
#############################################
@ -81,7 +82,7 @@ print_dic('instance of StageXY',xy_stage)
#
#########################################################
print('xy_stage.x.prefix')
print("xy_stage.x.prefix")
print(xy_stage.x.prefix)
xy_stage.__dict__