From 5cc8cb7d735eaa2a60918c7c34397c4cead2934b Mon Sep 17 00:00:00 2001 From: Xiaoqiang Wang Date: Sun, 12 Mar 2023 10:07:16 +0100 Subject: [PATCH 1/5] correct a few signals' kind --- ophyd_devices/epics/devices/X07MADevices.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ophyd_devices/epics/devices/X07MADevices.py b/ophyd_devices/epics/devices/X07MADevices.py index f1d4ca3..c2aff34 100644 --- a/ophyd_devices/epics/devices/X07MADevices.py +++ b/ophyd_devices/epics/devices/X07MADevices.py @@ -144,13 +144,13 @@ class X07MAAnalogSignals(Device): ADC inputs """ - s1 = Cpt(EpicsSignalRO, "SIGNAL0") - s2 = Cpt(EpicsSignalRO, "SIGNAL1") - s3 = Cpt(EpicsSignalRO, "SIGNAL2") - s4 = Cpt(EpicsSignalRO, "SIGNAL3") - s5 = Cpt(EpicsSignalRO, "SIGNAL4") - s6 = Cpt(EpicsSignalRO, "SIGNAL5") - s7 = Cpt(EpicsSignalRO, "SIGNAL6") + s1 = Cpt(EpicsSignalRO, "SIGNAL0", kind=Kind.hinted, auto_monitor=True) + s2 = Cpt(EpicsSignalRO, "SIGNAL1", kind=Kind.hinted, auto_monitor=True) + s3 = Cpt(EpicsSignalRO, "SIGNAL2", kind=Kind.hinted, auto_monitor=True) + s4 = Cpt(EpicsSignalRO, "SIGNAL3", kind=Kind.hinted, auto_monitor=True) + s5 = Cpt(EpicsSignalRO, "SIGNAL4", kind=Kind.hinted, auto_monitor=True) + s6 = Cpt(EpicsSignalRO, "SIGNAL5", kind=Kind.hinted, auto_monitor=True) + s7 = Cpt(EpicsSignalRO, "SIGNAL6", kind=Kind.hinted, auto_monitor=True) # Aliases tey = s1 @@ -186,4 +186,4 @@ class X07MAAutoTemperatureControl(Device): """ control = Cpt(EpicsSignal, "CONTROL") - status = Cpt(EpicsSignalRO, "STATUS", kind=Kind.hinted, string=True, auto_monitor=True) + status = Cpt(EpicsSignalRO, "STATUS", string=True, auto_monitor=True) From b7ead905c0fc683f38e1f7cd9083ae4b90040941 Mon Sep 17 00:00:00 2001 From: Xiaoqiang Wang Date: Mon, 13 Mar 2023 10:18:11 +0100 Subject: [PATCH 2/5] use FlyerInterface for PGM OtF scan --- ophyd_devices/epics/devices/X07MADevices.py | 45 ++++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/ophyd_devices/epics/devices/X07MADevices.py b/ophyd_devices/epics/devices/X07MADevices.py index c2aff34..80eb942 100644 --- a/ophyd_devices/epics/devices/X07MADevices.py +++ b/ophyd_devices/epics/devices/X07MADevices.py @@ -1,12 +1,16 @@ """ ophyd device classes for X07MA beamline """ +from collections import OrderedDict +import time from typing import Any from ophyd import Component as Cpt from ophyd import FormattedComponent as FCpt from ophyd import Device, EpicsSignal, EpicsSignalRO, Kind, PVPositioner, EpicsMotor +from ophyd.flyers import FlyerInterface +from ophyd.status import DeviceStatus, SubscriptionStatus from ophyd.pv_positioner import PVPositionerComparator __all__ = [ @@ -53,7 +57,7 @@ class PGMMonochromator(PVPositioner): with_undulator = Cpt(EpicsSignal, "PHS-E:OPT", kind=Kind.config) -class PGMOtFScan(Device): +class PGMOtFScan(FlyerInterface, Device): """ PGM on-the-fly scan """ @@ -63,8 +67,45 @@ class PGMOtFScan(Device): time = Cpt(EpicsSignal, "TIME") folder = Cpt(EpicsSignal, "FOLDER") file = Cpt(EpicsSignal, "FILE") - start = Cpt(EpicsSignal, "START") + acquire = Cpt(EpicsSignal, "START", auto_monitor=True) + edata = Cpt(EpicsSignalRO, "EDATA", kind=Kind.hinted, auto_monitor=True) + data = Cpt(EpicsSignalRO, "DATA", kind=Kind.hinted, auto_monitor=True) + idata = Cpt(EpicsSignalRO, "IDATA", kind=Kind.hinted, auto_monitor=True) + fdata = Cpt(EpicsSignalRO, "FDATA", kind=Kind.hinted, auto_monitor=True) + def kickoff(self): + self._start_time = time.time() + self.acquire.put(1, use_complete=True) + status = DeviceStatus(self) + status.set_finished() + return status + + def complete(self): + def check_value(*, old_value, value, **kwargs): + return (old_value == 1 and value == 0) + + status = SubscriptionStatus(self.acquire, check_value, event_type=self.acquire.SUB_VALUE) + return status + + def collect(self): + data = { + "time": self._start_time, + "data": {}, + "timestamps": {} + } + for attr in ("edata", "data", "idata", "fdata"): + obj = getattr(self, attr) + data["data"][attr] = obj.value + data["timestamps"][attr] = obj.timestamp + + return data + + def describe(self): + desc = OrderedDict() + for attr in ("edata", "data", "idata", "fdata"): + desc.update(getattr(self, attr).describe()) + desc[attr]["dtype"] = "array" + return desc class VacuumValve(PVPositionerComparator): """ From 66d18e8ad4a33af4be800f931332caceb0e2f7f5 Mon Sep 17 00:00:00 2001 From: Xiaoqiang Wang Date: Mon, 13 Mar 2023 11:15:16 +0100 Subject: [PATCH 3/5] fix describe_collect method --- ophyd_devices/epics/devices/X07MADevices.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ophyd_devices/epics/devices/X07MADevices.py b/ophyd_devices/epics/devices/X07MADevices.py index 80eb942..b20f3e2 100644 --- a/ophyd_devices/epics/devices/X07MADevices.py +++ b/ophyd_devices/epics/devices/X07MADevices.py @@ -100,11 +100,10 @@ class PGMOtFScan(FlyerInterface, Device): return data - def describe(self): + def describe_collect(self): desc = OrderedDict() for attr in ("edata", "data", "idata", "fdata"): desc.update(getattr(self, attr).describe()) - desc[attr]["dtype"] = "array" return desc class VacuumValve(PVPositionerComparator): From 6692e53018b7933dfe76bed425ce4416528032b7 Mon Sep 17 00:00:00 2001 From: Xiaoqiang Wang Date: Mon, 13 Mar 2023 15:38:50 +0100 Subject: [PATCH 4/5] add SUB_VALUE event to publish intermediate steps --- ophyd_devices/epics/devices/X07MADevices.py | 22 +++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/ophyd_devices/epics/devices/X07MADevices.py b/ophyd_devices/epics/devices/X07MADevices.py index b20f3e2..e03f97c 100644 --- a/ophyd_devices/epics/devices/X07MADevices.py +++ b/ophyd_devices/epics/devices/X07MADevices.py @@ -61,6 +61,7 @@ class PGMOtFScan(FlyerInterface, Device): """ PGM on-the-fly scan """ + SUB_VALUE = "value" e1 = Cpt(EpicsSignal, "E1") e2 = Cpt(EpicsSignal, "E2") @@ -72,6 +73,12 @@ class PGMOtFScan(FlyerInterface, Device): data = Cpt(EpicsSignalRO, "DATA", kind=Kind.hinted, auto_monitor=True) idata = Cpt(EpicsSignalRO, "IDATA", kind=Kind.hinted, auto_monitor=True) fdata = Cpt(EpicsSignalRO, "FDATA", kind=Kind.hinted, auto_monitor=True) + count = Cpt(EpicsSignalRO, "COUNT", kind=Kind.omitted, auto_monitor=True) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.acquire.subscribe(self._update_status, run=False) + self.count.subscribe(self._update_data, run=False) def kickoff(self): self._start_time = time.time() @@ -95,8 +102,8 @@ class PGMOtFScan(FlyerInterface, Device): } for attr in ("edata", "data", "idata", "fdata"): obj = getattr(self, attr) - data["data"][attr] = obj.value - data["timestamps"][attr] = obj.timestamp + data["data"][obj.name] = obj.get() + data["timestamps"][obj.name] = obj.timestamp return data @@ -106,6 +113,17 @@ class PGMOtFScan(FlyerInterface, Device): desc.update(getattr(self, attr).describe()) return desc + def _update_status(self, *, old_value, value, **kwargs): + if old_value == 1 and value == 0: + self._done_acquiring() + + def _update_data(self, value, **kwargs): + if value == 0: + return + data = self.collect() + self._run_subs(sub_type=self.SUB_VALUE, value=data) + + class VacuumValve(PVPositionerComparator): """ EPS vacuum valve. From d3d5aa1d472a9ce38b11f6f2b5bd547d110284a9 Mon Sep 17 00:00:00 2001 From: Xiaoqiang Wang Date: Wed, 15 Mar 2023 09:25:31 +0100 Subject: [PATCH 5/5] mark scan params as configuration attrs --- ophyd_devices/epics/devices/X07MADevices.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ophyd_devices/epics/devices/X07MADevices.py b/ophyd_devices/epics/devices/X07MADevices.py index e03f97c..54b1a88 100644 --- a/ophyd_devices/epics/devices/X07MADevices.py +++ b/ophyd_devices/epics/devices/X07MADevices.py @@ -63,11 +63,11 @@ class PGMOtFScan(FlyerInterface, Device): """ SUB_VALUE = "value" - e1 = Cpt(EpicsSignal, "E1") - e2 = Cpt(EpicsSignal, "E2") - time = Cpt(EpicsSignal, "TIME") - folder = Cpt(EpicsSignal, "FOLDER") - file = Cpt(EpicsSignal, "FILE") + e1 = Cpt(EpicsSignal, "E1", kind=Kind.config) + e2 = Cpt(EpicsSignal, "E2", kind=Kind.config) + time = Cpt(EpicsSignal, "TIME", kind=Kind.config) + folder = Cpt(EpicsSignal, "FOLDER", kind=Kind.config) + file = Cpt(EpicsSignal, "FILE", kind=Kind.config) acquire = Cpt(EpicsSignal, "START", auto_monitor=True) edata = Cpt(EpicsSignalRO, "EDATA", kind=Kind.hinted, auto_monitor=True) data = Cpt(EpicsSignalRO, "DATA", kind=Kind.hinted, auto_monitor=True) @@ -77,6 +77,7 @@ class PGMOtFScan(FlyerInterface, Device): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + self._start_time = 0 self.acquire.subscribe(self._update_status, run=False) self.count.subscribe(self._update_data, run=False)