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,8 +1,8 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
3
|
from ophyd_async.core import SubsetEnum
|
|
4
|
-
from ophyd_async.epics
|
|
5
|
-
from ophyd_async.epics.signal
|
|
4
|
+
from ophyd_async.epics import adcore
|
|
5
|
+
from ophyd_async.epics.signal import epics_signal_rw_rbv
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class AravisTriggerMode(str, Enum):
|
|
@@ -22,12 +22,15 @@ class AravisTriggerMode(str, Enum):
|
|
|
22
22
|
AravisTriggerSource = SubsetEnum["Freerun", "Line1"]
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
class
|
|
25
|
+
class AravisDriverIO(adcore.ADBaseIO):
|
|
26
26
|
# If instantiating a new instance, ensure it is supported in the _deadtimes dict
|
|
27
27
|
"""Generic Driver supporting the Manta and Mako drivers.
|
|
28
28
|
Fetches deadtime prior to use in a Streaming scan.
|
|
29
|
+
|
|
29
30
|
Requires driver firmware up to date:
|
|
30
31
|
- Model_RBV must be of the form "^(Mako|Manta) (model)$"
|
|
32
|
+
|
|
33
|
+
This mirrors the interface provided by ADAravis/db/aravisCamera.template.
|
|
31
34
|
"""
|
|
32
35
|
|
|
33
36
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from ._core_io import ADBaseIO, DetectorState, NDFileHDFIO, NDPluginStatsIO
|
|
2
|
+
from ._core_logic import (
|
|
3
|
+
DEFAULT_GOOD_STATES,
|
|
4
|
+
ADBaseShapeProvider,
|
|
5
|
+
set_exposure_time_and_acquire_period_if_supplied,
|
|
6
|
+
start_acquiring_driver_and_ensure_status,
|
|
7
|
+
)
|
|
8
|
+
from ._hdf_writer import ADHDFWriter
|
|
9
|
+
from ._single_trigger import SingleTriggerDetector
|
|
10
|
+
from ._utils import (
|
|
11
|
+
ADBaseDataType,
|
|
12
|
+
FileWriteMode,
|
|
13
|
+
ImageMode,
|
|
14
|
+
NDAttributeDataType,
|
|
15
|
+
NDAttributesXML,
|
|
16
|
+
stop_busy_record,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"ADBaseIO",
|
|
21
|
+
"DetectorState",
|
|
22
|
+
"NDFileHDFIO",
|
|
23
|
+
"NDPluginStatsIO",
|
|
24
|
+
"DEFAULT_GOOD_STATES",
|
|
25
|
+
"ADBaseShapeProvider",
|
|
26
|
+
"set_exposure_time_and_acquire_period_if_supplied",
|
|
27
|
+
"start_acquiring_driver_and_ensure_status",
|
|
28
|
+
"ADHDFWriter",
|
|
29
|
+
"SingleTriggerDetector",
|
|
30
|
+
"ADBaseDataType",
|
|
31
|
+
"FileWriteMode",
|
|
32
|
+
"ImageMode",
|
|
33
|
+
"NDAttributeDataType",
|
|
34
|
+
"NDAttributesXML",
|
|
35
|
+
"stop_busy_record",
|
|
36
|
+
]
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
from ophyd_async.core import Device
|
|
4
|
+
from ophyd_async.epics.signal import (
|
|
5
|
+
epics_signal_r,
|
|
6
|
+
epics_signal_rw,
|
|
7
|
+
epics_signal_rw_rbv,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from ._utils import ADBaseDataType, FileWriteMode, ImageMode
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Callback(str, Enum):
|
|
14
|
+
Enable = "Enable"
|
|
15
|
+
Disable = "Disable"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NDArrayBaseIO(Device):
|
|
19
|
+
def __init__(self, prefix: str, name: str = "") -> None:
|
|
20
|
+
self.unique_id = epics_signal_r(int, prefix + "UniqueId_RBV")
|
|
21
|
+
self.nd_attributes_file = epics_signal_rw(str, prefix + "NDAttributesFile")
|
|
22
|
+
self.acquire = epics_signal_rw_rbv(bool, prefix + "Acquire")
|
|
23
|
+
self.array_size_x = epics_signal_r(int, prefix + "ArraySizeX_RBV")
|
|
24
|
+
self.array_size_y = epics_signal_r(int, prefix + "ArraySizeY_RBV")
|
|
25
|
+
self.data_type = epics_signal_r(ADBaseDataType, prefix + "NDDataType_RBV")
|
|
26
|
+
self.array_counter = epics_signal_rw_rbv(int, prefix + "ArrayCounter")
|
|
27
|
+
# There is no _RBV for this one
|
|
28
|
+
self.wait_for_plugins = epics_signal_rw(bool, prefix + "WaitForPlugins")
|
|
29
|
+
|
|
30
|
+
super().__init__(name=name)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class NDPluginBaseIO(NDArrayBaseIO):
|
|
34
|
+
def __init__(self, prefix: str, name: str = "") -> None:
|
|
35
|
+
self.nd_array_port = epics_signal_rw_rbv(str, prefix + "NDArrayPort")
|
|
36
|
+
self.enable_callback = epics_signal_rw_rbv(Callback, prefix + "EnableCallbacks")
|
|
37
|
+
self.nd_array_address = epics_signal_rw_rbv(int, prefix + "NDArrayAddress")
|
|
38
|
+
self.array_size0 = epics_signal_r(int, prefix + "ArraySize0_RBV")
|
|
39
|
+
self.array_size1 = epics_signal_r(int, prefix + "ArraySize1_RBV")
|
|
40
|
+
super().__init__(prefix, name)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class NDPluginStatsIO(NDPluginBaseIO):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class DetectorState(str, Enum):
|
|
48
|
+
"""
|
|
49
|
+
Default set of states of an AreaDetector driver.
|
|
50
|
+
See definition in ADApp/ADSrc/ADDriver.h in https://github.com/areaDetector/ADCore
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
Idle = "Idle"
|
|
54
|
+
Acquire = "Acquire"
|
|
55
|
+
Readout = "Readout"
|
|
56
|
+
Correct = "Correct"
|
|
57
|
+
Saving = "Saving"
|
|
58
|
+
Aborting = "Aborting"
|
|
59
|
+
Error = "Error"
|
|
60
|
+
Waiting = "Waiting"
|
|
61
|
+
Initializing = "Initializing"
|
|
62
|
+
Disconnected = "Disconnected"
|
|
63
|
+
Aborted = "Aborted"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ADBaseIO(NDArrayBaseIO):
|
|
67
|
+
def __init__(self, prefix: str, name: str = "") -> None:
|
|
68
|
+
# Define some signals
|
|
69
|
+
self.acquire_time = epics_signal_rw_rbv(float, prefix + "AcquireTime")
|
|
70
|
+
self.acquire_period = epics_signal_rw_rbv(float, prefix + "AcquirePeriod")
|
|
71
|
+
self.num_images = epics_signal_rw_rbv(int, prefix + "NumImages")
|
|
72
|
+
self.image_mode = epics_signal_rw_rbv(ImageMode, prefix + "ImageMode")
|
|
73
|
+
self.detector_state = epics_signal_r(
|
|
74
|
+
DetectorState, prefix + "DetectorState_RBV"
|
|
75
|
+
)
|
|
76
|
+
super().__init__(prefix, name=name)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class Compression(str, Enum):
|
|
80
|
+
none = "None"
|
|
81
|
+
nbit = "N-bit"
|
|
82
|
+
szip = "szip"
|
|
83
|
+
zlib = "zlib"
|
|
84
|
+
blosc = "Blosc"
|
|
85
|
+
bslz4 = "BSLZ4"
|
|
86
|
+
lz4 = "LZ4"
|
|
87
|
+
jpeg = "JPEG"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class NDFileHDFIO(NDPluginBaseIO):
|
|
91
|
+
def __init__(self, prefix: str, name="") -> None:
|
|
92
|
+
# Define some signals
|
|
93
|
+
self.position_mode = epics_signal_rw_rbv(bool, prefix + "PositionMode")
|
|
94
|
+
self.compression = epics_signal_rw_rbv(Compression, prefix + "Compression")
|
|
95
|
+
self.num_extra_dims = epics_signal_rw_rbv(int, prefix + "NumExtraDims")
|
|
96
|
+
self.file_path = epics_signal_rw_rbv(str, prefix + "FilePath")
|
|
97
|
+
self.file_name = epics_signal_rw_rbv(str, prefix + "FileName")
|
|
98
|
+
self.file_path_exists = epics_signal_r(bool, prefix + "FilePathExists_RBV")
|
|
99
|
+
self.file_template = epics_signal_rw_rbv(str, prefix + "FileTemplate")
|
|
100
|
+
self.full_file_name = epics_signal_r(str, prefix + "FullFileName_RBV")
|
|
101
|
+
self.file_write_mode = epics_signal_rw_rbv(
|
|
102
|
+
FileWriteMode, prefix + "FileWriteMode"
|
|
103
|
+
)
|
|
104
|
+
self.num_capture = epics_signal_rw_rbv(int, prefix + "NumCapture")
|
|
105
|
+
self.num_captured = epics_signal_r(int, prefix + "NumCaptured_RBV")
|
|
106
|
+
self.swmr_mode = epics_signal_rw_rbv(bool, prefix + "SWMRMode")
|
|
107
|
+
self.lazy_open = epics_signal_rw_rbv(bool, prefix + "LazyOpen")
|
|
108
|
+
self.capture = epics_signal_rw_rbv(bool, prefix + "Capture")
|
|
109
|
+
self.flush_now = epics_signal_rw(bool, prefix + "FlushNow")
|
|
110
|
+
self.xml_file_name = epics_signal_rw_rbv(str, prefix + "XMLFileName")
|
|
111
|
+
self.array_size0 = epics_signal_r(int, prefix + "ArraySize0")
|
|
112
|
+
self.array_size1 = epics_signal_r(int, prefix + "ArraySize1")
|
|
113
|
+
self.create_dir_depth = epics_signal_rw(int, prefix + "CreateDirectory")
|
|
114
|
+
super().__init__(prefix, name)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from enum import Enum
|
|
3
2
|
from typing import FrozenSet, Set
|
|
4
3
|
|
|
5
4
|
from ophyd_async.core import (
|
|
@@ -10,53 +9,31 @@ from ophyd_async.core import (
|
|
|
10
9
|
set_and_wait_for_value,
|
|
11
10
|
)
|
|
12
11
|
|
|
13
|
-
from
|
|
14
|
-
from ..utils import ImageMode
|
|
15
|
-
from ..writers.nd_plugin import NDArrayBase
|
|
12
|
+
from ._core_io import ADBaseIO, DetectorState
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
class DetectorState(str, Enum):
|
|
19
|
-
"""
|
|
20
|
-
Default set of states of an AreaDetector driver.
|
|
21
|
-
See definition in ADApp/ADSrc/ADDriver.h in https://github.com/areaDetector/ADCore
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
Idle = "Idle"
|
|
25
|
-
Acquire = "Acquire"
|
|
26
|
-
Readout = "Readout"
|
|
27
|
-
Correct = "Correct"
|
|
28
|
-
Saving = "Saving"
|
|
29
|
-
Aborting = "Aborting"
|
|
30
|
-
Error = "Error"
|
|
31
|
-
Waiting = "Waiting"
|
|
32
|
-
Initializing = "Initializing"
|
|
33
|
-
Disconnected = "Disconnected"
|
|
34
|
-
Aborted = "Aborted"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
#: Default set of states that we should consider "good" i.e. the acquisition
|
|
14
|
+
# Default set of states that we should consider "good" i.e. the acquisition
|
|
38
15
|
# is complete and went well
|
|
39
16
|
DEFAULT_GOOD_STATES: FrozenSet[DetectorState] = frozenset(
|
|
40
17
|
[DetectorState.Idle, DetectorState.Aborted]
|
|
41
18
|
)
|
|
42
19
|
|
|
43
20
|
|
|
44
|
-
class
|
|
45
|
-
def __init__(self,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
21
|
+
class ADBaseShapeProvider(ShapeProvider):
|
|
22
|
+
def __init__(self, driver: ADBaseIO) -> None:
|
|
23
|
+
self._driver = driver
|
|
24
|
+
|
|
25
|
+
async def __call__(self) -> tuple:
|
|
26
|
+
shape = await asyncio.gather(
|
|
27
|
+
self._driver.array_size_y.get_value(),
|
|
28
|
+
self._driver.array_size_x.get_value(),
|
|
29
|
+
self._driver.data_type.get_value(),
|
|
53
30
|
)
|
|
54
|
-
|
|
31
|
+
return shape
|
|
55
32
|
|
|
56
33
|
|
|
57
34
|
async def set_exposure_time_and_acquire_period_if_supplied(
|
|
58
35
|
controller: DetectorControl,
|
|
59
|
-
driver:
|
|
36
|
+
driver: ADBaseIO,
|
|
60
37
|
exposure: float | None = None,
|
|
61
38
|
timeout: float = DEFAULT_TIMEOUT,
|
|
62
39
|
) -> None:
|
|
@@ -70,7 +47,7 @@ async def set_exposure_time_and_acquire_period_if_supplied(
|
|
|
70
47
|
controller:
|
|
71
48
|
Controller that can supply a deadtime.
|
|
72
49
|
driver:
|
|
73
|
-
The driver to start acquiring. Must subclass
|
|
50
|
+
The driver to start acquiring. Must subclass ADBaseIO.
|
|
74
51
|
exposure:
|
|
75
52
|
Desired exposure time, this is a noop if it is None.
|
|
76
53
|
timeout:
|
|
@@ -85,7 +62,7 @@ async def set_exposure_time_and_acquire_period_if_supplied(
|
|
|
85
62
|
|
|
86
63
|
|
|
87
64
|
async def start_acquiring_driver_and_ensure_status(
|
|
88
|
-
driver:
|
|
65
|
+
driver: ADBaseIO,
|
|
89
66
|
good_states: Set[DetectorState] = set(DEFAULT_GOOD_STATES),
|
|
90
67
|
timeout: float = DEFAULT_TIMEOUT,
|
|
91
68
|
) -> AsyncStatus:
|
|
@@ -99,7 +76,7 @@ async def start_acquiring_driver_and_ensure_status(
|
|
|
99
76
|
Parameters
|
|
100
77
|
----------
|
|
101
78
|
driver:
|
|
102
|
-
The driver to start acquiring. Must subclass
|
|
79
|
+
The driver to start acquiring. Must subclass ADBaseIO.
|
|
103
80
|
good_states:
|
|
104
81
|
set of states defined in DetectorState enum which are considered good states.
|
|
105
82
|
timeout:
|
|
@@ -125,16 +102,3 @@ async def start_acquiring_driver_and_ensure_status(
|
|
|
125
102
|
)
|
|
126
103
|
|
|
127
104
|
return AsyncStatus(complete_acquisition())
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
class ADBaseShapeProvider(ShapeProvider):
|
|
131
|
-
def __init__(self, driver: ADBase) -> None:
|
|
132
|
-
self._driver = driver
|
|
133
|
-
|
|
134
|
-
async def __call__(self) -> tuple:
|
|
135
|
-
shape = await asyncio.gather(
|
|
136
|
-
self._driver.array_size_y.get_value(),
|
|
137
|
-
self._driver.array_size_x.get_value(),
|
|
138
|
-
self._driver.data_type.get_value(),
|
|
139
|
-
)
|
|
140
|
-
return shape
|
|
@@ -8,23 +8,24 @@ from ophyd_async.core import (
|
|
|
8
8
|
DEFAULT_TIMEOUT,
|
|
9
9
|
AsyncStatus,
|
|
10
10
|
DetectorWriter,
|
|
11
|
+
HDFDataset,
|
|
12
|
+
HDFFile,
|
|
11
13
|
NameProvider,
|
|
12
14
|
PathProvider,
|
|
13
15
|
ShapeProvider,
|
|
16
|
+
observe_value,
|
|
14
17
|
set_and_wait_for_value,
|
|
15
18
|
wait_for_value,
|
|
16
19
|
)
|
|
17
|
-
from ophyd_async.core.signal import observe_value
|
|
18
20
|
|
|
19
|
-
from .
|
|
20
|
-
from .
|
|
21
|
-
from .nd_plugin import convert_ad_dtype_to_np
|
|
21
|
+
from ._core_io import NDFileHDFIO
|
|
22
|
+
from ._utils import FileWriteMode, convert_ad_dtype_to_np
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
class
|
|
25
|
+
class ADHDFWriter(DetectorWriter):
|
|
25
26
|
def __init__(
|
|
26
27
|
self,
|
|
27
|
-
hdf:
|
|
28
|
+
hdf: NDFileHDFIO,
|
|
28
29
|
path_provider: PathProvider,
|
|
29
30
|
name_provider: NameProvider,
|
|
30
31
|
shape_provider: ShapeProvider,
|
|
@@ -36,8 +37,8 @@ class HDFWriter(DetectorWriter):
|
|
|
36
37
|
self._shape_provider = shape_provider
|
|
37
38
|
self._scalar_datasets_paths = scalar_datasets_paths
|
|
38
39
|
self._capture_status: Optional[AsyncStatus] = None
|
|
39
|
-
self._datasets: List[
|
|
40
|
-
self._file: Optional[
|
|
40
|
+
self._datasets: List[HDFDataset] = []
|
|
41
|
+
self._file: Optional[HDFFile] = None
|
|
41
42
|
self._multiplier = 1
|
|
42
43
|
|
|
43
44
|
async def open(self, multiplier: int = 1) -> Dict[str, DataKey]:
|
|
@@ -80,7 +81,7 @@ class HDFWriter(DetectorWriter):
|
|
|
80
81
|
|
|
81
82
|
# Add the main data
|
|
82
83
|
self._datasets = [
|
|
83
|
-
|
|
84
|
+
HDFDataset(
|
|
84
85
|
data_key=name,
|
|
85
86
|
dataset="/entry/data/data",
|
|
86
87
|
shape=frame_shape,
|
|
@@ -91,7 +92,7 @@ class HDFWriter(DetectorWriter):
|
|
|
91
92
|
# And all the scalar datasets
|
|
92
93
|
for ds_name, ds_path in self._scalar_datasets_paths.items():
|
|
93
94
|
self._datasets.append(
|
|
94
|
-
|
|
95
|
+
HDFDataset(
|
|
95
96
|
f"{name}-{ds_name}",
|
|
96
97
|
f"/entry/instrument/NDAttributes/{ds_path}",
|
|
97
98
|
(),
|
|
@@ -131,7 +132,7 @@ class HDFWriter(DetectorWriter):
|
|
|
131
132
|
if indices_written:
|
|
132
133
|
if not self._file:
|
|
133
134
|
path = Path(await self.hdf.full_file_name.get_value())
|
|
134
|
-
self._file =
|
|
135
|
+
self._file = HDFFile(
|
|
135
136
|
self._path_provider(),
|
|
136
137
|
# See https://github.com/bluesky/ophyd-async/issues/122
|
|
137
138
|
path,
|
|
@@ -11,18 +11,17 @@ from ophyd_async.core import (
|
|
|
11
11
|
StandardReadable,
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
-
from .
|
|
15
|
-
from .
|
|
16
|
-
from .writers.nd_plugin import NDPluginBase
|
|
14
|
+
from ._core_io import ADBaseIO, NDPluginBaseIO
|
|
15
|
+
from ._utils import ImageMode
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
class
|
|
18
|
+
class SingleTriggerDetector(StandardReadable, Triggerable):
|
|
20
19
|
def __init__(
|
|
21
20
|
self,
|
|
22
|
-
drv:
|
|
21
|
+
drv: ADBaseIO,
|
|
23
22
|
read_uncached: Sequence[SignalR] = (),
|
|
24
23
|
name="",
|
|
25
|
-
**plugins:
|
|
24
|
+
**plugins: NDPluginBaseIO,
|
|
26
25
|
) -> None:
|
|
27
26
|
self.drv = drv
|
|
28
27
|
self.__dict__.update(plugins)
|
|
@@ -5,6 +5,35 @@ from xml.etree import cElementTree as ET
|
|
|
5
5
|
from ophyd_async.core import DEFAULT_TIMEOUT, SignalRW, T, wait_for_value
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
class ADBaseDataType(str, Enum):
|
|
9
|
+
Int8 = "Int8"
|
|
10
|
+
UInt8 = "UInt8"
|
|
11
|
+
Int16 = "Int16"
|
|
12
|
+
UInt16 = "UInt16"
|
|
13
|
+
Int32 = "Int32"
|
|
14
|
+
UInt32 = "UInt32"
|
|
15
|
+
Int64 = "Int64"
|
|
16
|
+
UInt64 = "UInt64"
|
|
17
|
+
Float32 = "Float32"
|
|
18
|
+
Float64 = "Float64"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def convert_ad_dtype_to_np(ad_dtype: ADBaseDataType) -> str:
|
|
22
|
+
ad_dtype_to_np_dtype = {
|
|
23
|
+
ADBaseDataType.Int8: "|i1",
|
|
24
|
+
ADBaseDataType.UInt8: "|u1",
|
|
25
|
+
ADBaseDataType.Int16: "<i2",
|
|
26
|
+
ADBaseDataType.UInt16: "<u2",
|
|
27
|
+
ADBaseDataType.Int32: "<i4",
|
|
28
|
+
ADBaseDataType.UInt32: "<u4",
|
|
29
|
+
ADBaseDataType.Int64: "<i8",
|
|
30
|
+
ADBaseDataType.UInt64: "<u8",
|
|
31
|
+
ADBaseDataType.Float32: "<f4",
|
|
32
|
+
ADBaseDataType.Float64: "<f8",
|
|
33
|
+
}
|
|
34
|
+
return ad_dtype_to_np_dtype[ad_dtype]
|
|
35
|
+
|
|
36
|
+
|
|
8
37
|
class FileWriteMode(str, Enum):
|
|
9
38
|
single = "Single"
|
|
10
39
|
capture = "Capture"
|
|
@@ -1,12 +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
|
-
|
|
7
|
-
from
|
|
8
|
-
from ophyd_async.epics.areadetector.drivers.kinetix_driver import KinetixDriver
|
|
9
|
-
from ophyd_async.epics.areadetector.writers import HDFWriter, NDFileHDF
|
|
4
|
+
from ophyd_async.epics import adcore
|
|
5
|
+
|
|
6
|
+
from ._kinetix_controller import KinetixController
|
|
7
|
+
from ._kinetix_io import KinetixDriverIO
|
|
10
8
|
|
|
11
9
|
|
|
12
10
|
class KinetixDetector(StandardDetector, HasHints):
|
|
@@ -16,7 +14,7 @@ class KinetixDetector(StandardDetector, HasHints):
|
|
|
16
14
|
"""
|
|
17
15
|
|
|
18
16
|
_controller: KinetixController
|
|
19
|
-
_writer:
|
|
17
|
+
_writer: adcore.ADHDFWriter
|
|
20
18
|
|
|
21
19
|
def __init__(
|
|
22
20
|
self,
|
|
@@ -26,16 +24,16 @@ class KinetixDetector(StandardDetector, HasHints):
|
|
|
26
24
|
hdf_suffix="HDF1:",
|
|
27
25
|
name="",
|
|
28
26
|
):
|
|
29
|
-
self.drv =
|
|
30
|
-
self.hdf =
|
|
27
|
+
self.drv = KinetixDriverIO(prefix + drv_suffix)
|
|
28
|
+
self.hdf = adcore.NDFileHDFIO(prefix + hdf_suffix)
|
|
31
29
|
|
|
32
30
|
super().__init__(
|
|
33
31
|
KinetixController(self.drv),
|
|
34
|
-
|
|
32
|
+
adcore.ADHDFWriter(
|
|
35
33
|
self.hdf,
|
|
36
34
|
path_provider,
|
|
37
35
|
lambda: self.name,
|
|
38
|
-
ADBaseShapeProvider(self.drv),
|
|
36
|
+
adcore.ADBaseShapeProvider(self.drv),
|
|
39
37
|
),
|
|
40
38
|
config_sigs=(self.drv.acquire_time,),
|
|
41
39
|
name=name,
|
|
@@ -2,12 +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
|
-
from ..utils import ImageMode, stop_busy_record
|
|
7
|
+
from ._kinetix_io import KinetixDriverIO, KinetixTriggerMode
|
|
11
8
|
|
|
12
9
|
KINETIX_TRIGGER_MODE_MAP = {
|
|
13
10
|
DetectorTrigger.internal: KinetixTriggerMode.internal,
|
|
@@ -20,7 +17,7 @@ KINETIX_TRIGGER_MODE_MAP = {
|
|
|
20
17
|
class KinetixController(DetectorControl):
|
|
21
18
|
def __init__(
|
|
22
19
|
self,
|
|
23
|
-
driver:
|
|
20
|
+
driver: KinetixDriverIO,
|
|
24
21
|
) -> None:
|
|
25
22
|
self._drv = driver
|
|
26
23
|
|
|
@@ -36,14 +33,14 @@ class KinetixController(DetectorControl):
|
|
|
36
33
|
await asyncio.gather(
|
|
37
34
|
self._drv.trigger_mode.set(KINETIX_TRIGGER_MODE_MAP[trigger]),
|
|
38
35
|
self._drv.num_images.set(num),
|
|
39
|
-
self._drv.image_mode.set(ImageMode.multiple),
|
|
36
|
+
self._drv.image_mode.set(adcore.ImageMode.multiple),
|
|
40
37
|
)
|
|
41
38
|
if exposure is not None and trigger not in [
|
|
42
39
|
DetectorTrigger.variable_gate,
|
|
43
40
|
DetectorTrigger.constant_gate,
|
|
44
41
|
]:
|
|
45
42
|
await self._drv.acquire_time.set(exposure)
|
|
46
|
-
return await start_acquiring_driver_and_ensure_status(self._drv)
|
|
43
|
+
return await adcore.start_acquiring_driver_and_ensure_status(self._drv)
|
|
47
44
|
|
|
48
45
|
async def disarm(self):
|
|
49
|
-
await stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
46
|
+
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 KinetixTriggerMode(str, Enum):
|
|
@@ -17,7 +16,9 @@ class KinetixReadoutMode(str, Enum):
|
|
|
17
16
|
dynamic_range = 3
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
class
|
|
19
|
+
class KinetixDriverIO(adcore.ADBaseIO):
|
|
20
|
+
"""This mirrors the interface provided by ADKinetix/db/ADKinetix.template."""
|
|
21
|
+
|
|
21
22
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
22
23
|
# self.pixel_format = epics_signal_rw_rbv(PixelFormat, prefix + "PixelFormat")
|
|
23
24
|
self.trigger_mode = epics_signal_rw_rbv(
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from ._pilatus import PilatusDetector, PilatusReadoutTime
|
|
2
|
+
from ._pilatus_controller import PilatusController
|
|
3
|
+
from ._pilatus_io import PilatusDriverIO, PilatusTriggerMode
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"PilatusDetector",
|
|
7
|
+
"PilatusReadoutTime",
|
|
8
|
+
"PilatusController",
|
|
9
|
+
"PilatusDriverIO",
|
|
10
|
+
"PilatusTriggerMode",
|
|
11
|
+
]
|
|
@@ -2,15 +2,11 @@ from enum import Enum
|
|
|
2
2
|
|
|
3
3
|
from bluesky.protocols import Hints
|
|
4
4
|
|
|
5
|
-
from ophyd_async.core import PathProvider
|
|
6
|
-
from ophyd_async.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
from ophyd_async.epics.areadetector.drivers.ad_base import ADBaseShapeProvider
|
|
11
|
-
from ophyd_async.epics.areadetector.drivers.pilatus_driver import PilatusDriver
|
|
12
|
-
from ophyd_async.epics.areadetector.writers.hdf_writer import HDFWriter
|
|
13
|
-
from ophyd_async.epics.areadetector.writers.nd_file_hdf import NDFileHDF
|
|
5
|
+
from ophyd_async.core import PathProvider, StandardDetector
|
|
6
|
+
from ophyd_async.epics import adcore
|
|
7
|
+
|
|
8
|
+
from ._pilatus_controller import PilatusController
|
|
9
|
+
from ._pilatus_io import PilatusDriverIO
|
|
14
10
|
|
|
15
11
|
|
|
16
12
|
#: Cite: https://media.dectris.com/User_Manual-PILATUS2-V1_4.pdf
|
|
@@ -31,7 +27,7 @@ class PilatusDetector(StandardDetector):
|
|
|
31
27
|
"""A Pilatus StandardDetector writing HDF files"""
|
|
32
28
|
|
|
33
29
|
_controller: PilatusController
|
|
34
|
-
_writer:
|
|
30
|
+
_writer: adcore.ADHDFWriter
|
|
35
31
|
|
|
36
32
|
def __init__(
|
|
37
33
|
self,
|
|
@@ -42,16 +38,16 @@ class PilatusDetector(StandardDetector):
|
|
|
42
38
|
hdf_suffix: str = "HDF1:",
|
|
43
39
|
name: str = "",
|
|
44
40
|
):
|
|
45
|
-
self.drv =
|
|
46
|
-
self.hdf =
|
|
41
|
+
self.drv = PilatusDriverIO(prefix + drv_suffix)
|
|
42
|
+
self.hdf = adcore.NDFileHDFIO(prefix + hdf_suffix)
|
|
47
43
|
|
|
48
44
|
super().__init__(
|
|
49
45
|
PilatusController(self.drv, readout_time=readout_time.value),
|
|
50
|
-
|
|
46
|
+
adcore.ADHDFWriter(
|
|
51
47
|
self.hdf,
|
|
52
48
|
path_provider,
|
|
53
49
|
lambda: self.name,
|
|
54
|
-
ADBaseShapeProvider(self.drv),
|
|
50
|
+
adcore.ADBaseShapeProvider(self.drv),
|
|
55
51
|
),
|
|
56
52
|
config_sigs=(self.drv.acquire_time,),
|
|
57
53
|
name=name,
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
|
-
from ophyd_async.core import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
from ophyd_async.core import (
|
|
5
|
+
DEFAULT_TIMEOUT,
|
|
6
|
+
AsyncStatus,
|
|
7
|
+
DetectorControl,
|
|
8
|
+
DetectorTrigger,
|
|
9
|
+
wait_for_value,
|
|
10
10
|
)
|
|
11
|
-
from ophyd_async.epics
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
)
|
|
15
|
-
from ophyd_async.epics.areadetector.utils import ImageMode, stop_busy_record
|
|
11
|
+
from ophyd_async.epics import adcore
|
|
12
|
+
|
|
13
|
+
from ._pilatus_io import PilatusDriverIO, PilatusTriggerMode
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
class PilatusController(DetectorControl):
|
|
@@ -24,7 +22,7 @@ class PilatusController(DetectorControl):
|
|
|
24
22
|
|
|
25
23
|
def __init__(
|
|
26
24
|
self,
|
|
27
|
-
driver:
|
|
25
|
+
driver: PilatusDriverIO,
|
|
28
26
|
readout_time: float,
|
|
29
27
|
) -> None:
|
|
30
28
|
self._drv = driver
|
|
@@ -40,17 +38,17 @@ class PilatusController(DetectorControl):
|
|
|
40
38
|
exposure: Optional[float] = None,
|
|
41
39
|
) -> AsyncStatus:
|
|
42
40
|
if exposure is not None:
|
|
43
|
-
await set_exposure_time_and_acquire_period_if_supplied(
|
|
41
|
+
await adcore.set_exposure_time_and_acquire_period_if_supplied(
|
|
44
42
|
self, self._drv, exposure
|
|
45
43
|
)
|
|
46
44
|
await asyncio.gather(
|
|
47
45
|
self._drv.trigger_mode.set(self._get_trigger_mode(trigger)),
|
|
48
46
|
self._drv.num_images.set(999_999 if num == 0 else num),
|
|
49
|
-
self._drv.image_mode.set(ImageMode.multiple),
|
|
47
|
+
self._drv.image_mode.set(adcore.ImageMode.multiple),
|
|
50
48
|
)
|
|
51
49
|
|
|
52
50
|
# Standard arm the detector and wait for the acquire PV to be True
|
|
53
|
-
idle_status = await start_acquiring_driver_and_ensure_status(self._drv)
|
|
51
|
+
idle_status = await adcore.start_acquiring_driver_and_ensure_status(self._drv)
|
|
54
52
|
|
|
55
53
|
# The pilatus has an additional PV that goes True when the camserver
|
|
56
54
|
# is actually ready. Should wait for that too or we risk dropping
|
|
@@ -74,4 +72,4 @@ class PilatusController(DetectorControl):
|
|
|
74
72
|
return cls._supported_trigger_types[trigger]
|
|
75
73
|
|
|
76
74
|
async def disarm(self):
|
|
77
|
-
await stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
75
|
+
await adcore.stop_busy_record(self._drv.acquire, False, timeout=1)
|