ophyd-async 0.4.0__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ophyd_async/_version.py +2 -2
- ophyd_async/core/__init__.py +84 -73
- ophyd_async/core/{detector.py → _detector.py} +4 -8
- ophyd_async/core/{device.py → _device.py} +1 -1
- ophyd_async/core/{device_save_loader.py → _device_save_loader.py} +3 -3
- ophyd_async/core/{flyer.py → _flyer.py} +6 -8
- ophyd_async/{epics/areadetector/writers/general_hdffile.py → core/_hdf_dataset.py} +4 -4
- ophyd_async/{log.py → core/_log.py} +11 -3
- ophyd_async/core/{mock_signal_backend.py → _mock_signal_backend.py} +3 -3
- ophyd_async/core/{mock_signal_utils.py → _mock_signal_utils.py} +3 -4
- ophyd_async/{protocols.py → core/_protocol.py} +1 -1
- ophyd_async/core/{standard_readable.py → _readable.py} +6 -16
- ophyd_async/core/{signal.py → _signal.py} +7 -8
- ophyd_async/core/{signal_backend.py → _signal_backend.py} +4 -13
- ophyd_async/core/{soft_signal_backend.py → _soft_signal_backend.py} +3 -12
- ophyd_async/core/{async_status.py → _status.py} +3 -11
- ophyd_async/epics/adaravis/__init__.py +9 -0
- ophyd_async/epics/{areadetector/aravis.py → adaravis/_aravis.py} +9 -11
- ophyd_async/epics/{areadetector/controllers/aravis_controller.py → adaravis/_aravis_controller.py} +7 -10
- ophyd_async/epics/{areadetector/drivers/aravis_driver.py → adaravis/_aravis_io.py} +6 -3
- ophyd_async/epics/adcore/__init__.py +36 -0
- ophyd_async/epics/adcore/_core_io.py +114 -0
- ophyd_async/epics/{areadetector/drivers/ad_base.py → adcore/_core_logic.py} +16 -52
- ophyd_async/epics/{areadetector/writers/hdf_writer.py → adcore/_hdf_writer.py} +12 -11
- ophyd_async/epics/{areadetector/single_trigger_det.py → adcore/_single_trigger.py} +5 -6
- ophyd_async/epics/{areadetector/utils.py → adcore/_utils.py} +29 -0
- ophyd_async/epics/adkinetix/__init__.py +9 -0
- ophyd_async/epics/{areadetector/kinetix.py → adkinetix/_kinetix.py} +9 -11
- ophyd_async/epics/{areadetector/controllers/kinetix_controller.py → adkinetix/_kinetix_controller.py} +6 -9
- ophyd_async/epics/{areadetector/drivers/kinetix_driver.py → adkinetix/_kinetix_io.py} +5 -4
- ophyd_async/epics/adpilatus/__init__.py +11 -0
- ophyd_async/epics/{areadetector/pilatus.py → adpilatus/_pilatus.py} +10 -14
- ophyd_async/epics/{areadetector/controllers/pilatus_controller.py → adpilatus/_pilatus_controller.py} +14 -16
- ophyd_async/epics/{areadetector/drivers/pilatus_driver.py → adpilatus/_pilatus_io.py} +5 -3
- ophyd_async/epics/adsimdetector/__init__.py +7 -0
- ophyd_async/epics/{demo/demo_ad_sim_detector.py → adsimdetector/_sim.py} +10 -11
- ophyd_async/epics/{areadetector/controllers/ad_sim_controller.py → adsimdetector/_sim_controller.py} +8 -14
- ophyd_async/epics/advimba/__init__.py +9 -0
- ophyd_async/epics/{areadetector/vimba.py → advimba/_vimba.py} +9 -9
- ophyd_async/epics/{areadetector/controllers/vimba_controller.py → advimba/_vimba_controller.py} +6 -14
- ophyd_async/epics/{areadetector/drivers/vimba_driver.py → advimba/_vimba_io.py} +5 -4
- ophyd_async/epics/demo/__init__.py +9 -132
- ophyd_async/epics/demo/_mover.py +97 -0
- ophyd_async/epics/demo/_sensor.py +36 -0
- ophyd_async/epics/{motion/motor.py → motor.py} +13 -12
- ophyd_async/epics/pvi/__init__.py +2 -2
- ophyd_async/epics/pvi/{pvi.py → _pvi.py} +17 -14
- ophyd_async/epics/signal/__init__.py +7 -1
- ophyd_async/epics/{_backend → signal}/_aioca.py +3 -2
- ophyd_async/epics/{_backend/common.py → signal/_common.py} +1 -1
- ophyd_async/epics/signal/_epics_transport.py +3 -3
- ophyd_async/epics/{_backend → signal}/_p4p.py +4 -3
- ophyd_async/epics/signal/{signal.py → _signal.py} +10 -9
- ophyd_async/fastcs/odin/__init__.py +0 -0
- ophyd_async/{panda → fastcs/panda}/__init__.py +18 -13
- ophyd_async/{panda → fastcs/panda}/_common_blocks.py +3 -3
- ophyd_async/{panda → fastcs/panda}/_hdf_panda.py +2 -7
- ophyd_async/{panda/writers → fastcs/panda}/_hdf_writer.py +8 -7
- ophyd_async/{panda → fastcs/panda}/_panda_controller.py +2 -1
- ophyd_async/{panda → fastcs/panda}/_trigger.py +3 -7
- ophyd_async/plan_stubs/__init__.py +2 -2
- ophyd_async/plan_stubs/{ensure_connected.py → _ensure_connected.py} +1 -2
- ophyd_async/plan_stubs/{fly.py → _fly.py} +13 -9
- ophyd_async/sim/__init__.py +0 -11
- ophyd_async/sim/demo/__init__.py +18 -2
- ophyd_async/sim/demo/_pattern_detector/__init__.py +13 -0
- ophyd_async/sim/{sim_pattern_generator.py → demo/_pattern_detector/_pattern_detector.py} +8 -8
- ophyd_async/sim/{sim_pattern_detector_control.py → demo/_pattern_detector/_pattern_detector_controller.py} +4 -5
- ophyd_async/sim/{sim_pattern_detector_writer.py → demo/_pattern_detector/_pattern_detector_writer.py} +4 -4
- ophyd_async/sim/{pattern_generator.py → demo/_pattern_detector/_pattern_generator.py} +12 -8
- ophyd_async/sim/demo/{sim_motor.py → _sim_motor.py} +7 -5
- ophyd_async/sim/testing/__init__.py +0 -0
- ophyd_async/tango/__init__.py +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.0.dist-info}/METADATA +1 -1
- ophyd_async-0.5.0.dist-info/RECORD +89 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.0.dist-info}/WHEEL +1 -1
- ophyd_async/epics/areadetector/__init__.py +0 -23
- ophyd_async/epics/areadetector/controllers/__init__.py +0 -5
- ophyd_async/epics/areadetector/drivers/__init__.py +0 -23
- ophyd_async/epics/areadetector/writers/__init__.py +0 -5
- ophyd_async/epics/areadetector/writers/nd_file_hdf.py +0 -43
- ophyd_async/epics/areadetector/writers/nd_plugin.py +0 -68
- ophyd_async/epics/motion/__init__.py +0 -3
- ophyd_async/panda/writers/__init__.py +0 -3
- ophyd_async-0.4.0.dist-info/RECORD +0 -84
- /ophyd_async/core/{utils.py → _utils.py} +0 -0
- /ophyd_async/{epics/_backend → fastcs}/__init__.py +0 -0
- /ophyd_async/{panda → fastcs/panda}/_table.py +0 -0
- /ophyd_async/{panda → fastcs/panda}/_utils.py +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.0.dist-info}/LICENSE +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.0.dist-info}/entry_points.txt +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.0.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from .
|
|
3
|
+
from ophyd_async.epics import adcore
|
|
4
|
+
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw_rbv
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class PilatusTriggerMode(str, Enum):
|
|
@@ -12,7 +12,9 @@ class PilatusTriggerMode(str, Enum):
|
|
|
12
12
|
alignment = "Alignment"
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class
|
|
15
|
+
class PilatusDriverIO(adcore.ADBaseIO):
|
|
16
|
+
"""This mirrors the interface provided by ADPilatus/db/pilatus.template."""
|
|
17
|
+
|
|
16
18
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
17
19
|
self.trigger_mode = epics_signal_rw_rbv(
|
|
18
20
|
PilatusTriggerMode, prefix + "TriggerMode"
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
from typing import Sequence
|
|
2
2
|
|
|
3
3
|
from ophyd_async.core import PathProvider, SignalR, StandardDetector
|
|
4
|
+
from ophyd_async.epics import adcore
|
|
4
5
|
|
|
5
|
-
from
|
|
6
|
-
from ..areadetector.drivers import ADBase, ADBaseShapeProvider
|
|
7
|
-
from ..areadetector.writers import HDFWriter, NDFileHDF
|
|
6
|
+
from ._sim_controller import SimController
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
class
|
|
11
|
-
_controller:
|
|
12
|
-
_writer:
|
|
9
|
+
class SimDetector(StandardDetector):
|
|
10
|
+
_controller: SimController
|
|
11
|
+
_writer: adcore.ADHDFWriter
|
|
13
12
|
|
|
14
13
|
def __init__(
|
|
15
14
|
self,
|
|
16
|
-
drv:
|
|
17
|
-
hdf:
|
|
15
|
+
drv: adcore.ADBaseIO,
|
|
16
|
+
hdf: adcore.NDFileHDFIO,
|
|
18
17
|
path_provider: PathProvider,
|
|
19
18
|
name: str = "",
|
|
20
19
|
config_sigs: Sequence[SignalR] = (),
|
|
@@ -23,12 +22,12 @@ class DemoADSimDetector(StandardDetector):
|
|
|
23
22
|
self.hdf = hdf
|
|
24
23
|
|
|
25
24
|
super().__init__(
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
SimController(self.drv),
|
|
26
|
+
adcore.ADHDFWriter(
|
|
28
27
|
self.hdf,
|
|
29
28
|
path_provider,
|
|
30
29
|
lambda: self.name,
|
|
31
|
-
ADBaseShapeProvider(self.drv),
|
|
30
|
+
adcore.ADBaseShapeProvider(self.drv),
|
|
32
31
|
),
|
|
33
32
|
config_sigs=config_sigs,
|
|
34
33
|
name=name,
|
ophyd_async/epics/{areadetector/controllers/ad_sim_controller.py → adsimdetector/_sim_controller.py}
RENAMED
|
@@ -7,20 +7,14 @@ from ophyd_async.core import (
|
|
|
7
7
|
DetectorControl,
|
|
8
8
|
DetectorTrigger,
|
|
9
9
|
)
|
|
10
|
-
|
|
11
|
-
from ..drivers.ad_base import (
|
|
12
|
-
DEFAULT_GOOD_STATES,
|
|
13
|
-
ADBase,
|
|
14
|
-
DetectorState,
|
|
15
|
-
ImageMode,
|
|
16
|
-
start_acquiring_driver_and_ensure_status,
|
|
17
|
-
)
|
|
18
|
-
from ..utils import stop_busy_record
|
|
10
|
+
from ophyd_async.epics import adcore
|
|
19
11
|
|
|
20
12
|
|
|
21
|
-
class
|
|
13
|
+
class SimController(DetectorControl):
|
|
22
14
|
def __init__(
|
|
23
|
-
self,
|
|
15
|
+
self,
|
|
16
|
+
driver: adcore.ADBaseIO,
|
|
17
|
+
good_states: Set[adcore.DetectorState] = set(adcore.DEFAULT_GOOD_STATES),
|
|
24
18
|
) -> None:
|
|
25
19
|
self.driver = driver
|
|
26
20
|
self.good_states = good_states
|
|
@@ -40,13 +34,13 @@ class ADSimController(DetectorControl):
|
|
|
40
34
|
frame_timeout = DEFAULT_TIMEOUT + await self.driver.acquire_time.get_value()
|
|
41
35
|
await asyncio.gather(
|
|
42
36
|
self.driver.num_images.set(num),
|
|
43
|
-
self.driver.image_mode.set(ImageMode.multiple),
|
|
37
|
+
self.driver.image_mode.set(adcore.ImageMode.multiple),
|
|
44
38
|
)
|
|
45
|
-
return await start_acquiring_driver_and_ensure_status(
|
|
39
|
+
return await adcore.start_acquiring_driver_and_ensure_status(
|
|
46
40
|
self.driver, good_states=self.good_states, timeout=frame_timeout
|
|
47
41
|
)
|
|
48
42
|
|
|
49
43
|
async def disarm(self):
|
|
50
44
|
# We can't use caput callback as we already used it in arm() and we can't have
|
|
51
45
|
# 2 or they will deadlock
|
|
52
|
-
await stop_busy_record(self.driver.acquire, False, timeout=1)
|
|
46
|
+
await adcore.stop_busy_record(self.driver.acquire, False, timeout=1)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from bluesky.protocols import HasHints, Hints
|
|
2
2
|
|
|
3
3
|
from ophyd_async.core import PathProvider, StandardDetector
|
|
4
|
-
from ophyd_async.epics
|
|
5
|
-
|
|
6
|
-
from
|
|
7
|
-
from
|
|
4
|
+
from ophyd_async.epics import adcore
|
|
5
|
+
|
|
6
|
+
from ._vimba_controller import VimbaController
|
|
7
|
+
from ._vimba_io import VimbaDriverIO
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class VimbaDetector(StandardDetector, HasHints):
|
|
@@ -13,7 +13,7 @@ class VimbaDetector(StandardDetector, HasHints):
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
_controller: VimbaController
|
|
16
|
-
_writer:
|
|
16
|
+
_writer: adcore.ADHDFWriter
|
|
17
17
|
|
|
18
18
|
def __init__(
|
|
19
19
|
self,
|
|
@@ -23,16 +23,16 @@ class VimbaDetector(StandardDetector, HasHints):
|
|
|
23
23
|
hdf_suffix="HDF1:",
|
|
24
24
|
name="",
|
|
25
25
|
):
|
|
26
|
-
self.drv =
|
|
27
|
-
self.hdf =
|
|
26
|
+
self.drv = VimbaDriverIO(prefix + drv_suffix)
|
|
27
|
+
self.hdf = adcore.NDFileHDFIO(prefix + hdf_suffix)
|
|
28
28
|
|
|
29
29
|
super().__init__(
|
|
30
30
|
VimbaController(self.drv),
|
|
31
|
-
|
|
31
|
+
adcore.ADHDFWriter(
|
|
32
32
|
self.hdf,
|
|
33
33
|
path_provider,
|
|
34
34
|
lambda: self.name,
|
|
35
|
-
ADBaseShapeProvider(self.drv),
|
|
35
|
+
adcore.ADBaseShapeProvider(self.drv),
|
|
36
36
|
),
|
|
37
37
|
config_sigs=(self.drv.acquire_time,),
|
|
38
38
|
name=name,
|
ophyd_async/epics/{areadetector/controllers/vimba_controller.py → advimba/_vimba_controller.py}
RENAMED
|
@@ -2,17 +2,9 @@ import asyncio
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
from ophyd_async.core import AsyncStatus, DetectorControl, DetectorTrigger
|
|
5
|
-
from ophyd_async.epics
|
|
6
|
-
start_acquiring_driver_and_ensure_status,
|
|
7
|
-
)
|
|
5
|
+
from ophyd_async.epics import adcore
|
|
8
6
|
|
|
9
|
-
from
|
|
10
|
-
VimbaDriver,
|
|
11
|
-
VimbaExposeOutMode,
|
|
12
|
-
VimbaOnOff,
|
|
13
|
-
VimbaTriggerSource,
|
|
14
|
-
)
|
|
15
|
-
from ..utils import ImageMode, stop_busy_record
|
|
7
|
+
from ._vimba_io import VimbaDriverIO, VimbaExposeOutMode, VimbaOnOff, VimbaTriggerSource
|
|
16
8
|
|
|
17
9
|
TRIGGER_MODE = {
|
|
18
10
|
DetectorTrigger.internal: VimbaOnOff.off,
|
|
@@ -32,7 +24,7 @@ EXPOSE_OUT_MODE = {
|
|
|
32
24
|
class VimbaController(DetectorControl):
|
|
33
25
|
def __init__(
|
|
34
26
|
self,
|
|
35
|
-
driver:
|
|
27
|
+
driver: VimbaDriverIO,
|
|
36
28
|
) -> None:
|
|
37
29
|
self._drv = driver
|
|
38
30
|
|
|
@@ -49,7 +41,7 @@ class VimbaController(DetectorControl):
|
|
|
49
41
|
self._drv.trigger_mode.set(TRIGGER_MODE[trigger]),
|
|
50
42
|
self._drv.expose_mode.set(EXPOSE_OUT_MODE[trigger]),
|
|
51
43
|
self._drv.num_images.set(num),
|
|
52
|
-
self._drv.image_mode.set(ImageMode.multiple),
|
|
44
|
+
self._drv.image_mode.set(adcore.ImageMode.multiple),
|
|
53
45
|
)
|
|
54
46
|
if exposure is not None and trigger not in [
|
|
55
47
|
DetectorTrigger.variable_gate,
|
|
@@ -60,7 +52,7 @@ class VimbaController(DetectorControl):
|
|
|
60
52
|
self._drv.trig_source.set(VimbaTriggerSource.line1)
|
|
61
53
|
else:
|
|
62
54
|
self._drv.trig_source.set(VimbaTriggerSource.freerun)
|
|
63
|
-
return await start_acquiring_driver_and_ensure_status(self._drv)
|
|
55
|
+
return await adcore.start_acquiring_driver_and_ensure_status(self._drv)
|
|
64
56
|
|
|
65
57
|
async def disarm(self):
|
|
66
|
-
await stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
58
|
+
await adcore.stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
-
from ophyd_async.epics
|
|
4
|
-
|
|
5
|
-
from .ad_base import ADBase
|
|
3
|
+
from ophyd_async.epics import adcore
|
|
4
|
+
from ophyd_async.epics.signal import epics_signal_rw_rbv
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class VimbaPixelFormat(str, Enum):
|
|
@@ -46,7 +45,9 @@ class VimbaExposeOutMode(str, Enum):
|
|
|
46
45
|
trigger_width = "TriggerWidth" # Expose for length of high signal
|
|
47
46
|
|
|
48
47
|
|
|
49
|
-
class
|
|
48
|
+
class VimbaDriverIO(adcore.ADBaseIO):
|
|
49
|
+
"""This mirrors the interface provided by ADVimba/db/vimba.template."""
|
|
50
|
+
|
|
50
51
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
51
52
|
# self.pixel_format = epics_signal_rw_rbv(PixelFormat, prefix + "PixelFormat")
|
|
52
53
|
self.convert_format = epics_signal_rw_rbv(
|
|
@@ -1,145 +1,22 @@
|
|
|
1
1
|
"""Demo EPICS Devices for the tutorial"""
|
|
2
2
|
|
|
3
|
-
import asyncio
|
|
4
3
|
import atexit
|
|
5
4
|
import random
|
|
6
5
|
import string
|
|
7
6
|
import subprocess
|
|
8
7
|
import sys
|
|
9
|
-
from enum import Enum
|
|
10
8
|
from pathlib import Path
|
|
11
9
|
|
|
12
|
-
import
|
|
13
|
-
from
|
|
10
|
+
from ._mover import Mover, SampleStage
|
|
11
|
+
from ._sensor import EnergyMode, Sensor, SensorGroup
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
observe_value,
|
|
23
|
-
)
|
|
24
|
-
from ophyd_async.core.async_status import AsyncStatus
|
|
25
|
-
from ophyd_async.core.utils import (
|
|
26
|
-
DEFAULT_TIMEOUT,
|
|
27
|
-
CalculatableTimeout,
|
|
28
|
-
CalculateTimeout,
|
|
29
|
-
WatcherUpdate,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
from ..signal.signal import epics_signal_r, epics_signal_rw, epics_signal_x
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class EnergyMode(str, Enum):
|
|
36
|
-
"""Energy mode for `Sensor`"""
|
|
37
|
-
|
|
38
|
-
#: Low energy mode
|
|
39
|
-
low = "Low Energy"
|
|
40
|
-
#: High energy mode
|
|
41
|
-
high = "High Energy"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class Sensor(StandardReadable):
|
|
45
|
-
"""A demo sensor that produces a scalar value based on X and Y Movers"""
|
|
46
|
-
|
|
47
|
-
def __init__(self, prefix: str, name="") -> None:
|
|
48
|
-
# Define some signals
|
|
49
|
-
with self.add_children_as_readables(HintedSignal):
|
|
50
|
-
self.value = epics_signal_r(float, prefix + "Value")
|
|
51
|
-
with self.add_children_as_readables(ConfigSignal):
|
|
52
|
-
self.mode = epics_signal_rw(EnergyMode, prefix + "Mode")
|
|
53
|
-
|
|
54
|
-
super().__init__(name=name)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class SensorGroup(StandardReadable):
|
|
58
|
-
def __init__(self, prefix: str, name: str = "", sensor_count: int = 3) -> None:
|
|
59
|
-
with self.add_children_as_readables():
|
|
60
|
-
self.sensors = DeviceVector(
|
|
61
|
-
{i: Sensor(f"{prefix}{i}:") for i in range(1, sensor_count + 1)}
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
super().__init__(name)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class Mover(StandardReadable, Movable, Stoppable):
|
|
68
|
-
"""A demo movable that moves based on velocity"""
|
|
69
|
-
|
|
70
|
-
def __init__(self, prefix: str, name="") -> None:
|
|
71
|
-
# Define some signals
|
|
72
|
-
with self.add_children_as_readables(HintedSignal):
|
|
73
|
-
self.readback = epics_signal_r(float, prefix + "Readback")
|
|
74
|
-
with self.add_children_as_readables(ConfigSignal):
|
|
75
|
-
self.velocity = epics_signal_rw(float, prefix + "Velocity")
|
|
76
|
-
self.units = epics_signal_r(str, prefix + "Readback.EGU")
|
|
77
|
-
self.setpoint = epics_signal_rw(float, prefix + "Setpoint")
|
|
78
|
-
self.precision = epics_signal_r(int, prefix + "Readback.PREC")
|
|
79
|
-
# Signals that collide with standard methods should have a trailing underscore
|
|
80
|
-
self.stop_ = epics_signal_x(prefix + "Stop.PROC")
|
|
81
|
-
# Whether set() should complete successfully or not
|
|
82
|
-
self._set_success = True
|
|
83
|
-
|
|
84
|
-
super().__init__(name=name)
|
|
85
|
-
|
|
86
|
-
def set_name(self, name: str):
|
|
87
|
-
super().set_name(name)
|
|
88
|
-
# Readback should be named the same as its parent in read()
|
|
89
|
-
self.readback.set_name(name)
|
|
90
|
-
|
|
91
|
-
@WatchableAsyncStatus.wrap
|
|
92
|
-
async def set(
|
|
93
|
-
self, new_position: float, timeout: CalculatableTimeout = CalculateTimeout
|
|
94
|
-
):
|
|
95
|
-
self._set_success = True
|
|
96
|
-
old_position, units, precision, velocity = await asyncio.gather(
|
|
97
|
-
self.setpoint.get_value(),
|
|
98
|
-
self.units.get_value(),
|
|
99
|
-
self.precision.get_value(),
|
|
100
|
-
self.velocity.get_value(),
|
|
101
|
-
)
|
|
102
|
-
if timeout is CalculateTimeout:
|
|
103
|
-
assert velocity > 0, "Mover has zero velocity"
|
|
104
|
-
timeout = abs(new_position - old_position) / velocity + DEFAULT_TIMEOUT
|
|
105
|
-
# Make an Event that will be set on completion, and a Status that will
|
|
106
|
-
# error if not done in time
|
|
107
|
-
done = asyncio.Event()
|
|
108
|
-
done_status = AsyncStatus(asyncio.wait_for(done.wait(), timeout))
|
|
109
|
-
# Wait for the value to set, but don't wait for put completion callback
|
|
110
|
-
await self.setpoint.set(new_position, wait=False)
|
|
111
|
-
async for current_position in observe_value(
|
|
112
|
-
self.readback, done_status=done_status
|
|
113
|
-
):
|
|
114
|
-
yield WatcherUpdate(
|
|
115
|
-
current=current_position,
|
|
116
|
-
initial=old_position,
|
|
117
|
-
target=new_position,
|
|
118
|
-
name=self.name,
|
|
119
|
-
unit=units,
|
|
120
|
-
precision=precision,
|
|
121
|
-
)
|
|
122
|
-
if np.isclose(current_position, new_position):
|
|
123
|
-
done.set()
|
|
124
|
-
break
|
|
125
|
-
if not self._set_success:
|
|
126
|
-
raise RuntimeError("Motor was stopped")
|
|
127
|
-
|
|
128
|
-
async def stop(self, success=True):
|
|
129
|
-
self._set_success = success
|
|
130
|
-
status = self.stop_.trigger()
|
|
131
|
-
await status
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
class SampleStage(Device):
|
|
135
|
-
"""A demo sample stage with X and Y movables"""
|
|
136
|
-
|
|
137
|
-
def __init__(self, prefix: str, name="") -> None:
|
|
138
|
-
# Define some child Devices
|
|
139
|
-
self.x = Mover(prefix + "X:")
|
|
140
|
-
self.y = Mover(prefix + "Y:")
|
|
141
|
-
# Set name of device and child devices
|
|
142
|
-
super().__init__(name=name)
|
|
13
|
+
__all__ = [
|
|
14
|
+
"Mover",
|
|
15
|
+
"SampleStage",
|
|
16
|
+
"EnergyMode",
|
|
17
|
+
"Sensor",
|
|
18
|
+
"SensorGroup",
|
|
19
|
+
]
|
|
143
20
|
|
|
144
21
|
|
|
145
22
|
def start_ioc_subprocess() -> str:
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from bluesky.protocols import Movable, Stoppable
|
|
5
|
+
|
|
6
|
+
from ophyd_async.core import (
|
|
7
|
+
DEFAULT_TIMEOUT,
|
|
8
|
+
AsyncStatus,
|
|
9
|
+
CalculatableTimeout,
|
|
10
|
+
CalculateTimeout,
|
|
11
|
+
ConfigSignal,
|
|
12
|
+
Device,
|
|
13
|
+
HintedSignal,
|
|
14
|
+
StandardReadable,
|
|
15
|
+
WatchableAsyncStatus,
|
|
16
|
+
WatcherUpdate,
|
|
17
|
+
observe_value,
|
|
18
|
+
)
|
|
19
|
+
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw, epics_signal_x
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Mover(StandardReadable, Movable, Stoppable):
|
|
23
|
+
"""A demo movable that moves based on velocity"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, prefix: str, name="") -> None:
|
|
26
|
+
# Define some signals
|
|
27
|
+
with self.add_children_as_readables(HintedSignal):
|
|
28
|
+
self.readback = epics_signal_r(float, prefix + "Readback")
|
|
29
|
+
with self.add_children_as_readables(ConfigSignal):
|
|
30
|
+
self.velocity = epics_signal_rw(float, prefix + "Velocity")
|
|
31
|
+
self.units = epics_signal_r(str, prefix + "Readback.EGU")
|
|
32
|
+
self.setpoint = epics_signal_rw(float, prefix + "Setpoint")
|
|
33
|
+
self.precision = epics_signal_r(int, prefix + "Readback.PREC")
|
|
34
|
+
# Signals that collide with standard methods should have a trailing underscore
|
|
35
|
+
self.stop_ = epics_signal_x(prefix + "Stop.PROC")
|
|
36
|
+
# Whether set() should complete successfully or not
|
|
37
|
+
self._set_success = True
|
|
38
|
+
|
|
39
|
+
super().__init__(name=name)
|
|
40
|
+
|
|
41
|
+
def set_name(self, name: str):
|
|
42
|
+
super().set_name(name)
|
|
43
|
+
# Readback should be named the same as its parent in read()
|
|
44
|
+
self.readback.set_name(name)
|
|
45
|
+
|
|
46
|
+
@WatchableAsyncStatus.wrap
|
|
47
|
+
async def set(
|
|
48
|
+
self, new_position: float, timeout: CalculatableTimeout = CalculateTimeout
|
|
49
|
+
):
|
|
50
|
+
self._set_success = True
|
|
51
|
+
old_position, units, precision, velocity = await asyncio.gather(
|
|
52
|
+
self.setpoint.get_value(),
|
|
53
|
+
self.units.get_value(),
|
|
54
|
+
self.precision.get_value(),
|
|
55
|
+
self.velocity.get_value(),
|
|
56
|
+
)
|
|
57
|
+
if timeout is CalculateTimeout:
|
|
58
|
+
assert velocity > 0, "Mover has zero velocity"
|
|
59
|
+
timeout = abs(new_position - old_position) / velocity + DEFAULT_TIMEOUT
|
|
60
|
+
# Make an Event that will be set on completion, and a Status that will
|
|
61
|
+
# error if not done in time
|
|
62
|
+
done = asyncio.Event()
|
|
63
|
+
done_status = AsyncStatus(asyncio.wait_for(done.wait(), timeout))
|
|
64
|
+
# Wait for the value to set, but don't wait for put completion callback
|
|
65
|
+
await self.setpoint.set(new_position, wait=False)
|
|
66
|
+
async for current_position in observe_value(
|
|
67
|
+
self.readback, done_status=done_status
|
|
68
|
+
):
|
|
69
|
+
yield WatcherUpdate(
|
|
70
|
+
current=current_position,
|
|
71
|
+
initial=old_position,
|
|
72
|
+
target=new_position,
|
|
73
|
+
name=self.name,
|
|
74
|
+
unit=units,
|
|
75
|
+
precision=precision,
|
|
76
|
+
)
|
|
77
|
+
if np.isclose(current_position, new_position):
|
|
78
|
+
done.set()
|
|
79
|
+
break
|
|
80
|
+
if not self._set_success:
|
|
81
|
+
raise RuntimeError("Motor was stopped")
|
|
82
|
+
|
|
83
|
+
async def stop(self, success=True):
|
|
84
|
+
self._set_success = success
|
|
85
|
+
status = self.stop_.trigger()
|
|
86
|
+
await status
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class SampleStage(Device):
|
|
90
|
+
"""A demo sample stage with X and Y movables"""
|
|
91
|
+
|
|
92
|
+
def __init__(self, prefix: str, name="") -> None:
|
|
93
|
+
# Define some child Devices
|
|
94
|
+
self.x = Mover(prefix + "X:")
|
|
95
|
+
self.y = Mover(prefix + "Y:")
|
|
96
|
+
# Set name of device and child devices
|
|
97
|
+
super().__init__(name=name)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
from ophyd_async.core import ConfigSignal, DeviceVector, HintedSignal, StandardReadable
|
|
4
|
+
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class EnergyMode(str, Enum):
|
|
8
|
+
"""Energy mode for `Sensor`"""
|
|
9
|
+
|
|
10
|
+
#: Low energy mode
|
|
11
|
+
low = "Low Energy"
|
|
12
|
+
#: High energy mode
|
|
13
|
+
high = "High Energy"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Sensor(StandardReadable):
|
|
17
|
+
"""A demo sensor that produces a scalar value based on X and Y Movers"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, prefix: str, name="") -> None:
|
|
20
|
+
# Define some signals
|
|
21
|
+
with self.add_children_as_readables(HintedSignal):
|
|
22
|
+
self.value = epics_signal_r(float, prefix + "Value")
|
|
23
|
+
with self.add_children_as_readables(ConfigSignal):
|
|
24
|
+
self.mode = epics_signal_rw(EnergyMode, prefix + "Mode")
|
|
25
|
+
|
|
26
|
+
super().__init__(name=name)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SensorGroup(StandardReadable):
|
|
30
|
+
def __init__(self, prefix: str, name: str = "", sensor_count: int = 3) -> None:
|
|
31
|
+
with self.add_children_as_readables():
|
|
32
|
+
self.sensors = DeviceVector(
|
|
33
|
+
{i: Sensor(f"{prefix}{i}:") for i in range(1, sensor_count + 1)}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
super().__init__(name)
|
|
@@ -5,21 +5,18 @@ from bluesky.protocols import Flyable, Movable, Preparable, Stoppable
|
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
7
|
from ophyd_async.core import (
|
|
8
|
+
DEFAULT_TIMEOUT,
|
|
9
|
+
AsyncStatus,
|
|
10
|
+
CalculatableTimeout,
|
|
11
|
+
CalculateTimeout,
|
|
8
12
|
ConfigSignal,
|
|
9
13
|
HintedSignal,
|
|
10
14
|
StandardReadable,
|
|
11
15
|
WatchableAsyncStatus,
|
|
12
|
-
)
|
|
13
|
-
from ophyd_async.core.async_status import AsyncStatus
|
|
14
|
-
from ophyd_async.core.signal import observe_value
|
|
15
|
-
from ophyd_async.core.utils import (
|
|
16
|
-
DEFAULT_TIMEOUT,
|
|
17
|
-
CalculatableTimeout,
|
|
18
|
-
CalculateTimeout,
|
|
19
16
|
WatcherUpdate,
|
|
17
|
+
observe_value,
|
|
20
18
|
)
|
|
21
|
-
|
|
22
|
-
from ..signal.signal import epics_signal_r, epics_signal_rw, epics_signal_x
|
|
19
|
+
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw, epics_signal_x
|
|
23
20
|
|
|
24
21
|
|
|
25
22
|
class MotorLimitsException(Exception):
|
|
@@ -116,6 +113,7 @@ class Motor(StandardReadable, Movable, Stoppable, Flyable, Preparable):
|
|
|
116
113
|
)
|
|
117
114
|
|
|
118
115
|
await self.set(fly_prepared_position)
|
|
116
|
+
await self.velocity.set(fly_velocity)
|
|
119
117
|
|
|
120
118
|
@AsyncStatus.wrap
|
|
121
119
|
async def kickoff(self):
|
|
@@ -182,7 +180,7 @@ class Motor(StandardReadable, Movable, Stoppable, Flyable, Preparable):
|
|
|
182
180
|
async def _prepare_velocity(
|
|
183
181
|
self, start_position: float, end_position: float, time_for_move: float
|
|
184
182
|
) -> float:
|
|
185
|
-
fly_velocity = (
|
|
183
|
+
fly_velocity = (end_position - start_position) / time_for_move
|
|
186
184
|
max_speed, egu = await asyncio.gather(
|
|
187
185
|
self.max_velocity.get_value(), self.motor_egu.get_value()
|
|
188
186
|
)
|
|
@@ -191,7 +189,8 @@ class Motor(StandardReadable, Movable, Stoppable, Flyable, Preparable):
|
|
|
191
189
|
f"Motor speed of {abs(fly_velocity)} {egu}/s was requested for a motor "
|
|
192
190
|
f" with max speed of {max_speed} {egu}/s"
|
|
193
191
|
)
|
|
194
|
-
|
|
192
|
+
# move to prepare position at maximum velocity
|
|
193
|
+
await self.velocity.set(abs(max_speed))
|
|
195
194
|
return fly_velocity
|
|
196
195
|
|
|
197
196
|
async def _prepare_motor_path(
|
|
@@ -199,7 +198,9 @@ class Motor(StandardReadable, Movable, Stoppable, Flyable, Preparable):
|
|
|
199
198
|
) -> float:
|
|
200
199
|
# Distance required for motor to accelerate from stationary to fly_velocity, and
|
|
201
200
|
# distance required for motor to decelerate from fly_velocity to stationary
|
|
202
|
-
run_up_distance = (
|
|
201
|
+
run_up_distance = (
|
|
202
|
+
(await self.acceleration_time.get_value()) * fly_velocity * 0.5
|
|
203
|
+
)
|
|
203
204
|
|
|
204
205
|
self._fly_completed_position = end_position + run_up_distance
|
|
205
206
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .
|
|
1
|
+
from ._pvi import create_children_from_annotations, fill_pvi_entries
|
|
2
2
|
|
|
3
|
-
__all__ = ["
|
|
3
|
+
__all__ = ["fill_pvi_entries", "create_children_from_annotations"]
|