ophyd-async 0.9.0a1__py3-none-any.whl → 0.10.0a1__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/__init__.py +5 -8
- ophyd_async/_docs_parser.py +12 -0
- ophyd_async/_version.py +9 -4
- ophyd_async/core/__init__.py +102 -74
- ophyd_async/core/_derived_signal.py +271 -0
- ophyd_async/core/_derived_signal_backend.py +300 -0
- ophyd_async/core/_detector.py +158 -153
- ophyd_async/core/_device.py +143 -115
- ophyd_async/core/_device_filler.py +82 -9
- ophyd_async/core/_flyer.py +16 -7
- ophyd_async/core/_hdf_dataset.py +29 -22
- ophyd_async/core/_log.py +14 -23
- ophyd_async/core/_mock_signal_backend.py +11 -3
- ophyd_async/core/_protocol.py +65 -45
- ophyd_async/core/_providers.py +28 -9
- ophyd_async/core/_readable.py +74 -58
- ophyd_async/core/_settings.py +113 -0
- ophyd_async/core/_signal.py +304 -174
- ophyd_async/core/_signal_backend.py +60 -14
- ophyd_async/core/_soft_signal_backend.py +18 -12
- ophyd_async/core/_status.py +72 -24
- ophyd_async/core/_table.py +54 -17
- ophyd_async/core/_utils.py +101 -52
- ophyd_async/core/_yaml_settings.py +66 -0
- ophyd_async/epics/__init__.py +1 -0
- ophyd_async/epics/adandor/__init__.py +9 -0
- ophyd_async/epics/adandor/_andor.py +45 -0
- ophyd_async/epics/adandor/_andor_controller.py +51 -0
- ophyd_async/epics/adandor/_andor_io.py +34 -0
- ophyd_async/epics/adaravis/__init__.py +8 -1
- ophyd_async/epics/adaravis/_aravis.py +23 -41
- ophyd_async/epics/adaravis/_aravis_controller.py +23 -55
- ophyd_async/epics/adaravis/_aravis_io.py +13 -28
- ophyd_async/epics/adcore/__init__.py +36 -14
- ophyd_async/epics/adcore/_core_detector.py +81 -0
- ophyd_async/epics/adcore/_core_io.py +145 -95
- ophyd_async/epics/adcore/_core_logic.py +179 -88
- ophyd_async/epics/adcore/_core_writer.py +223 -0
- ophyd_async/epics/adcore/_hdf_writer.py +51 -92
- ophyd_async/epics/adcore/_jpeg_writer.py +26 -0
- ophyd_async/epics/adcore/_single_trigger.py +6 -5
- ophyd_async/epics/adcore/_tiff_writer.py +26 -0
- ophyd_async/epics/adcore/_utils.py +3 -2
- ophyd_async/epics/adkinetix/__init__.py +2 -1
- ophyd_async/epics/adkinetix/_kinetix.py +32 -27
- ophyd_async/epics/adkinetix/_kinetix_controller.py +11 -21
- ophyd_async/epics/adkinetix/_kinetix_io.py +12 -13
- ophyd_async/epics/adpilatus/__init__.py +7 -2
- ophyd_async/epics/adpilatus/_pilatus.py +28 -40
- ophyd_async/epics/adpilatus/_pilatus_controller.py +25 -22
- ophyd_async/epics/adpilatus/_pilatus_io.py +11 -9
- ophyd_async/epics/adsimdetector/__init__.py +8 -1
- ophyd_async/epics/adsimdetector/_sim.py +22 -16
- ophyd_async/epics/adsimdetector/_sim_controller.py +9 -43
- ophyd_async/epics/adsimdetector/_sim_io.py +10 -0
- ophyd_async/epics/advimba/__init__.py +10 -1
- ophyd_async/epics/advimba/_vimba.py +26 -25
- ophyd_async/epics/advimba/_vimba_controller.py +12 -24
- ophyd_async/epics/advimba/_vimba_io.py +23 -28
- ophyd_async/epics/core/_aioca.py +66 -30
- ophyd_async/epics/core/_epics_connector.py +4 -0
- ophyd_async/epics/core/_epics_device.py +2 -0
- ophyd_async/epics/core/_p4p.py +50 -18
- ophyd_async/epics/core/_pvi_connector.py +65 -8
- ophyd_async/epics/core/_signal.py +51 -51
- ophyd_async/epics/core/_util.py +5 -5
- ophyd_async/epics/demo/__init__.py +11 -49
- ophyd_async/epics/demo/__main__.py +31 -0
- ophyd_async/epics/demo/_ioc.py +32 -0
- ophyd_async/epics/demo/_motor.py +82 -0
- ophyd_async/epics/demo/_point_detector.py +42 -0
- ophyd_async/epics/demo/_point_detector_channel.py +22 -0
- ophyd_async/epics/demo/_stage.py +15 -0
- ophyd_async/epics/demo/{mover.db → motor.db} +2 -1
- ophyd_async/epics/demo/point_detector.db +59 -0
- ophyd_async/epics/demo/point_detector_channel.db +21 -0
- ophyd_async/epics/eiger/_eiger.py +1 -3
- ophyd_async/epics/eiger/_eiger_controller.py +11 -4
- ophyd_async/epics/eiger/_eiger_io.py +2 -0
- ophyd_async/epics/eiger/_odin_io.py +1 -2
- ophyd_async/epics/motor.py +83 -38
- ophyd_async/epics/signal.py +4 -1
- ophyd_async/epics/testing/__init__.py +14 -14
- ophyd_async/epics/testing/_example_ioc.py +68 -73
- ophyd_async/epics/testing/_utils.py +19 -44
- ophyd_async/epics/testing/test_records.db +16 -0
- ophyd_async/epics/testing/test_records_pva.db +17 -16
- ophyd_async/fastcs/__init__.py +1 -0
- ophyd_async/fastcs/core.py +6 -0
- ophyd_async/fastcs/odin/__init__.py +1 -0
- ophyd_async/fastcs/panda/__init__.py +8 -8
- ophyd_async/fastcs/panda/_block.py +29 -9
- ophyd_async/fastcs/panda/_control.py +12 -2
- ophyd_async/fastcs/panda/_hdf_panda.py +5 -1
- ophyd_async/fastcs/panda/_table.py +13 -7
- ophyd_async/fastcs/panda/_trigger.py +23 -9
- ophyd_async/fastcs/panda/_writer.py +27 -30
- ophyd_async/plan_stubs/__init__.py +16 -0
- ophyd_async/plan_stubs/_ensure_connected.py +12 -17
- ophyd_async/plan_stubs/_fly.py +3 -5
- ophyd_async/plan_stubs/_nd_attributes.py +9 -5
- ophyd_async/plan_stubs/_panda.py +14 -0
- ophyd_async/plan_stubs/_settings.py +152 -0
- ophyd_async/plan_stubs/_utils.py +3 -0
- ophyd_async/plan_stubs/_wait_for_awaitable.py +13 -0
- ophyd_async/sim/__init__.py +29 -0
- ophyd_async/sim/__main__.py +43 -0
- ophyd_async/sim/_blob_detector.py +33 -0
- ophyd_async/sim/_blob_detector_controller.py +48 -0
- ophyd_async/sim/_blob_detector_writer.py +105 -0
- ophyd_async/sim/_mirror_horizontal.py +46 -0
- ophyd_async/sim/_mirror_vertical.py +74 -0
- ophyd_async/sim/_motor.py +233 -0
- ophyd_async/sim/_pattern_generator.py +124 -0
- ophyd_async/sim/_point_detector.py +86 -0
- ophyd_async/sim/_stage.py +19 -0
- ophyd_async/tango/__init__.py +1 -0
- ophyd_async/tango/core/__init__.py +6 -1
- ophyd_async/tango/core/_base_device.py +41 -33
- ophyd_async/tango/core/_converters.py +81 -0
- ophyd_async/tango/core/_signal.py +21 -33
- ophyd_async/tango/core/_tango_readable.py +2 -19
- ophyd_async/tango/core/_tango_transport.py +148 -74
- ophyd_async/tango/core/_utils.py +47 -0
- ophyd_async/tango/demo/_counter.py +2 -0
- ophyd_async/tango/demo/_detector.py +2 -0
- ophyd_async/tango/demo/_mover.py +10 -6
- ophyd_async/tango/demo/_tango/_servers.py +4 -0
- ophyd_async/tango/testing/__init__.py +6 -0
- ophyd_async/tango/testing/_one_of_everything.py +200 -0
- ophyd_async/testing/__init__.py +48 -7
- ophyd_async/testing/__pytest_assert_rewrite.py +4 -0
- ophyd_async/testing/_assert.py +200 -96
- ophyd_async/testing/_mock_signal_utils.py +59 -73
- ophyd_async/testing/_one_of_everything.py +146 -0
- ophyd_async/testing/_single_derived.py +87 -0
- ophyd_async/testing/_utils.py +3 -0
- {ophyd_async-0.9.0a1.dist-info → ophyd_async-0.10.0a1.dist-info}/METADATA +25 -26
- ophyd_async-0.10.0a1.dist-info/RECORD +149 -0
- {ophyd_async-0.9.0a1.dist-info → ophyd_async-0.10.0a1.dist-info}/WHEEL +1 -1
- ophyd_async/core/_device_save_loader.py +0 -274
- ophyd_async/epics/demo/_mover.py +0 -95
- ophyd_async/epics/demo/_sensor.py +0 -37
- ophyd_async/epics/demo/sensor.db +0 -19
- ophyd_async/fastcs/panda/_utils.py +0 -16
- ophyd_async/sim/demo/__init__.py +0 -19
- ophyd_async/sim/demo/_pattern_detector/__init__.py +0 -13
- ophyd_async/sim/demo/_pattern_detector/_pattern_detector.py +0 -42
- ophyd_async/sim/demo/_pattern_detector/_pattern_detector_controller.py +0 -62
- ophyd_async/sim/demo/_pattern_detector/_pattern_detector_writer.py +0 -41
- ophyd_async/sim/demo/_pattern_detector/_pattern_generator.py +0 -207
- ophyd_async/sim/demo/_sim_motor.py +0 -107
- ophyd_async/sim/testing/__init__.py +0 -0
- ophyd_async-0.9.0a1.dist-info/RECORD +0 -119
- ophyd_async-0.9.0a1.dist-info/entry_points.txt +0 -2
- {ophyd_async-0.9.0a1.dist-info → ophyd_async-0.10.0a1.dist-info/licenses}/LICENSE +0 -0
- {ophyd_async-0.9.0a1.dist-info → ophyd_async-0.10.0a1.dist-info}/top_level.txt +0 -0
ophyd_async/core/_hdf_dataset.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
from collections.abc import Iterator
|
|
2
|
-
from dataclasses import dataclass, field
|
|
1
|
+
from collections.abc import Iterator
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
from urllib.parse import urlunparse
|
|
5
4
|
|
|
@@ -10,44 +9,53 @@ from event_model import (
|
|
|
10
9
|
StreamRange,
|
|
11
10
|
StreamResource,
|
|
12
11
|
)
|
|
12
|
+
from pydantic import BaseModel, Field
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
class HDFDatasetDescription(BaseModel):
|
|
16
|
+
"""A description of the type and shape of a dataset in an HDF file."""
|
|
17
|
+
|
|
17
18
|
data_key: str
|
|
19
|
+
"""The data_key that will appear in the event descriptor,
|
|
20
|
+
e.g. det or det.data"""
|
|
21
|
+
|
|
18
22
|
dataset: str
|
|
19
|
-
|
|
23
|
+
"""The dataset name within the HDF file,
|
|
24
|
+
e.g. /entry/data/data or /entry/instrument/NDAttributes/sum"""
|
|
25
|
+
|
|
26
|
+
shape: tuple[int, ...] = Field(default_factory=tuple)
|
|
27
|
+
"""The shape of a single event's data in the HDF file,
|
|
28
|
+
e.g. (1, 768, 1024) for arrays or () for scalars"""
|
|
29
|
+
|
|
20
30
|
dtype_numpy: str = ""
|
|
31
|
+
"""The numpy dtype for this field,
|
|
32
|
+
e.g. <i2 or <f8"""
|
|
33
|
+
|
|
34
|
+
chunk_shape: tuple[int, ...]
|
|
35
|
+
"""The explicit chunk size written to disk"""
|
|
36
|
+
|
|
21
37
|
multiplier: int = 1
|
|
22
|
-
|
|
23
|
-
# Represents explicit chunk size written to disk.
|
|
24
|
-
chunk_shape: tuple[int, ...] = ()
|
|
38
|
+
"""Won't be used soon."""
|
|
25
39
|
|
|
26
40
|
|
|
27
41
|
SLICE_NAME = "AD_HDF5_SWMR_SLICE"
|
|
28
42
|
|
|
29
43
|
|
|
30
|
-
class
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
:param
|
|
44
|
+
class HDFDocumentComposer:
|
|
45
|
+
"""A helper class to make stream resource and datums for HDF datasets.
|
|
46
|
+
|
|
47
|
+
:param full_file_name: Absolute path to the file that has been written
|
|
48
|
+
:param datasets: Descriptions of each of the datasets that will appear in the file
|
|
34
49
|
"""
|
|
35
50
|
|
|
36
51
|
def __init__(
|
|
37
52
|
self,
|
|
38
53
|
full_file_name: Path,
|
|
39
|
-
datasets: list[
|
|
54
|
+
datasets: list[HDFDatasetDescription],
|
|
40
55
|
hostname: str = "localhost",
|
|
41
56
|
) -> None:
|
|
42
57
|
self._last_emitted = 0
|
|
43
58
|
self._hostname = hostname
|
|
44
|
-
|
|
45
|
-
if len(datasets) == 0:
|
|
46
|
-
self._bundles = []
|
|
47
|
-
return None
|
|
48
|
-
|
|
49
|
-
bundler_composer = ComposeStreamResource()
|
|
50
|
-
|
|
51
59
|
uri = urlunparse(
|
|
52
60
|
(
|
|
53
61
|
"file",
|
|
@@ -58,7 +66,7 @@ class HDFFile:
|
|
|
58
66
|
None,
|
|
59
67
|
)
|
|
60
68
|
)
|
|
61
|
-
|
|
69
|
+
bundler_composer = ComposeStreamResource()
|
|
62
70
|
self._bundles: list[ComposeStreamResourceBundle] = [
|
|
63
71
|
bundler_composer(
|
|
64
72
|
mimetype="application/x-hdf5",
|
|
@@ -66,7 +74,6 @@ class HDFFile:
|
|
|
66
74
|
data_key=ds.data_key,
|
|
67
75
|
parameters={
|
|
68
76
|
"dataset": ds.dataset,
|
|
69
|
-
"swmr": ds.swmr,
|
|
70
77
|
"multiplier": ds.multiplier,
|
|
71
78
|
"chunk_shape": ds.chunk_shape,
|
|
72
79
|
},
|
ophyd_async/core/_log.py
CHANGED
|
@@ -63,31 +63,23 @@ def config_ophyd_async_logging(
|
|
|
63
63
|
color=True,
|
|
64
64
|
level="WARNING",
|
|
65
65
|
):
|
|
66
|
-
"""
|
|
67
|
-
|
|
66
|
+
"""Set a new handler on the ``logging.getLogger('ophyd_async')`` logger.
|
|
67
|
+
|
|
68
68
|
If this is called more than once, the handler from the previous invocation
|
|
69
69
|
is removed (if still present) and replaced.
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Returns
|
|
85
|
-
-------
|
|
86
|
-
handler : logging.Handler
|
|
87
|
-
The handler, which has already been added to the 'ophyd_async' logger.
|
|
88
|
-
|
|
89
|
-
Examples
|
|
90
|
-
--------
|
|
71
|
+
|
|
72
|
+
:param file:
|
|
73
|
+
object with ``write`` method or filename string. Default is `sys.stdout`.
|
|
74
|
+
:param fmt: str Overall logging format
|
|
75
|
+
:param datefmt: str Date format. Default is `'%H:%M:%S'`.
|
|
76
|
+
:param color: bool Use ANSI color codes. True by default.
|
|
77
|
+
:param level: str or int Python logging level, given as string or
|
|
78
|
+
corresponding integer. Default is 'WARNING'.
|
|
79
|
+
|
|
80
|
+
:returns: The handler, which has already been added to the 'ophyd_async' logger.
|
|
81
|
+
|
|
82
|
+
:examples:
|
|
91
83
|
Log to a file.
|
|
92
84
|
|
|
93
85
|
config_ophyd_async_logging(file='/tmp/what_is_happening.txt')
|
|
@@ -104,7 +96,6 @@ def config_ophyd_async_logging(
|
|
|
104
96
|
Increase verbosity: show level DEBUG or higher.
|
|
105
97
|
|
|
106
98
|
config_ophyd_async_logging(level='DEBUG')
|
|
107
|
-
|
|
108
99
|
"""
|
|
109
100
|
global current_handler
|
|
110
101
|
|
|
@@ -3,8 +3,10 @@ from collections.abc import Callable
|
|
|
3
3
|
from functools import cached_property
|
|
4
4
|
from unittest.mock import AsyncMock
|
|
5
5
|
|
|
6
|
-
from bluesky.protocols import
|
|
6
|
+
from bluesky.protocols import Reading
|
|
7
|
+
from event_model import DataKey
|
|
7
8
|
|
|
9
|
+
from ._derived_signal_backend import DerivedSignalBackend
|
|
8
10
|
from ._signal_backend import SignalBackend, SignalDatatypeT
|
|
9
11
|
from ._soft_signal_backend import SoftSignalBackend
|
|
10
12
|
from ._utils import Callback, LazyMock
|
|
@@ -23,7 +25,7 @@ class MockSignalBackend(SignalBackend[SignalDatatypeT]):
|
|
|
23
25
|
|
|
24
26
|
self.initial_backend = initial_backend
|
|
25
27
|
|
|
26
|
-
if isinstance(self.initial_backend, SoftSignalBackend):
|
|
28
|
+
if isinstance(self.initial_backend, SoftSignalBackend | DerivedSignalBackend):
|
|
27
29
|
# Backend is already a SoftSignalBackend, so use it
|
|
28
30
|
self.soft_backend = self.initial_backend
|
|
29
31
|
else:
|
|
@@ -38,11 +40,13 @@ class MockSignalBackend(SignalBackend[SignalDatatypeT]):
|
|
|
38
40
|
|
|
39
41
|
@cached_property
|
|
40
42
|
def put_mock(self) -> AsyncMock:
|
|
43
|
+
"""Return the mock that will track calls to `put()`."""
|
|
41
44
|
put_mock = AsyncMock(name="put", spec=Callable)
|
|
42
45
|
self.mock().attach_mock(put_mock, "put")
|
|
43
46
|
return put_mock
|
|
44
47
|
|
|
45
48
|
def set_value(self, value: SignalDatatypeT):
|
|
49
|
+
"""Set the value of the signal."""
|
|
46
50
|
self.soft_backend.set_value(value)
|
|
47
51
|
|
|
48
52
|
def source(self, name: str, read: bool) -> str:
|
|
@@ -53,6 +57,10 @@ class MockSignalBackend(SignalBackend[SignalDatatypeT]):
|
|
|
53
57
|
|
|
54
58
|
@cached_property
|
|
55
59
|
def put_proceeds(self) -> asyncio.Event:
|
|
60
|
+
"""Return an Event that will block `put()` until set.
|
|
61
|
+
|
|
62
|
+
The Event is initially set, but can be unset to block `put()`.
|
|
63
|
+
"""
|
|
56
64
|
put_proceeds = asyncio.Event()
|
|
57
65
|
put_proceeds.set()
|
|
58
66
|
return put_proceeds
|
|
@@ -72,7 +80,7 @@ class MockSignalBackend(SignalBackend[SignalDatatypeT]):
|
|
|
72
80
|
async def get_setpoint(self) -> SignalDatatypeT:
|
|
73
81
|
return await self.soft_backend.get_setpoint()
|
|
74
82
|
|
|
75
|
-
async def get_datakey(self, source: str) ->
|
|
83
|
+
async def get_datakey(self, source: str) -> DataKey:
|
|
76
84
|
return await self.soft_backend.get_datakey(source)
|
|
77
85
|
|
|
78
86
|
def set_callback(self, callback: Callback[Reading[SignalDatatypeT]] | None) -> None:
|
ophyd_async/core/_protocol.py
CHANGED
|
@@ -10,67 +10,66 @@ from typing import (
|
|
|
10
10
|
runtime_checkable,
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
-
from bluesky.protocols import HasName, Reading
|
|
13
|
+
from bluesky.protocols import HasName, Location, Reading, T_co
|
|
14
14
|
from event_model import DataKey
|
|
15
15
|
|
|
16
|
+
from ._utils import T
|
|
17
|
+
|
|
16
18
|
if TYPE_CHECKING:
|
|
17
19
|
from ._status import AsyncStatus
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
@runtime_checkable
|
|
21
23
|
class AsyncReadable(HasName, Protocol):
|
|
24
|
+
"""Async implementations of the sync [](#bluesky.protocols.Readable)."""
|
|
25
|
+
|
|
22
26
|
@abstractmethod
|
|
23
27
|
async def read(self) -> dict[str, Reading]:
|
|
24
|
-
"""Return
|
|
25
|
-
of values and timestamps and optional per-point metadata.
|
|
26
|
-
|
|
27
|
-
Example return value:
|
|
28
|
+
"""Return value, timestamp, optional per-point metadata for each field name.
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
For example:
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
{
|
|
33
|
+
"channel1": {"value": 5, "timestamp": 1472493713.271991},
|
|
34
|
+
"channel2": {"value": 16, "timestamp": 1472493713.539238},
|
|
35
|
+
}
|
|
35
36
|
"""
|
|
36
37
|
|
|
37
38
|
@abstractmethod
|
|
38
39
|
async def describe(self) -> dict[str, DataKey]:
|
|
39
|
-
"""Return
|
|
40
|
-
method, here mapped to per-scan metadata about each field.
|
|
40
|
+
"""Return per-scan metadata for each field name in `read()`.
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
For example:
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
'dtype': 'number',
|
|
49
|
-
'shape': []}),
|
|
50
|
-
('channel2',
|
|
51
|
-
{'source': 'XF23-ID:SOME_PV_NAME',
|
|
52
|
-
'dtype': 'number',
|
|
53
|
-
'shape': []}))
|
|
44
|
+
{
|
|
45
|
+
"channel1": {"source": "SOME_PV1", "dtype": "number", "shape": []},
|
|
46
|
+
"channel2": {"source": "SOME_PV2", "dtype": "number", "shape": []},
|
|
47
|
+
}
|
|
54
48
|
"""
|
|
55
49
|
|
|
56
50
|
|
|
57
51
|
@runtime_checkable
|
|
58
52
|
class AsyncConfigurable(HasName, Protocol):
|
|
53
|
+
"""Async implementation of the sync [](#bluesky.protocols.Configurable)."""
|
|
54
|
+
|
|
59
55
|
@abstractmethod
|
|
60
56
|
async def read_configuration(self) -> dict[str, Reading]:
|
|
61
|
-
"""
|
|
62
|
-
|
|
57
|
+
"""Return value, timestamp, optional per-point metadata for each field name.
|
|
58
|
+
|
|
59
|
+
Same API as [](#AsyncReadable.read) but for slow-changing fields related to
|
|
60
|
+
configuration. e.g., exposure time. These will typically be read only
|
|
61
|
+
once per run.
|
|
63
62
|
"""
|
|
64
63
|
|
|
65
64
|
@abstractmethod
|
|
66
65
|
async def describe_configuration(self) -> dict[str, DataKey]:
|
|
67
|
-
"""
|
|
68
|
-
``read_configuration``.
|
|
69
|
-
"""
|
|
66
|
+
"""Return per-scan metadata for each field name in `read_configuration()`."""
|
|
70
67
|
|
|
71
68
|
|
|
72
69
|
@runtime_checkable
|
|
73
70
|
class AsyncPausable(Protocol):
|
|
71
|
+
"""Async implementation of the sync [](#bluesky.protocols.Pausable)."""
|
|
72
|
+
|
|
74
73
|
@abstractmethod
|
|
75
74
|
async def pause(self) -> None:
|
|
76
75
|
"""Perform device-specific work when the RunEngine pauses."""
|
|
@@ -82,20 +81,40 @@ class AsyncPausable(Protocol):
|
|
|
82
81
|
|
|
83
82
|
@runtime_checkable
|
|
84
83
|
class AsyncStageable(Protocol):
|
|
84
|
+
"""Async implementation of the sync [](#bluesky.protocols.Stageable)."""
|
|
85
|
+
|
|
85
86
|
@abstractmethod
|
|
86
87
|
def stage(self) -> AsyncStatus:
|
|
87
|
-
"""
|
|
88
|
+
"""Set up the device for acquisition.
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
done staging.
|
|
90
|
+
:return: An `AsyncStatus` that is marked done when the device is done staging.
|
|
91
91
|
"""
|
|
92
92
|
|
|
93
93
|
@abstractmethod
|
|
94
94
|
def unstage(self) -> AsyncStatus:
|
|
95
|
-
"""
|
|
95
|
+
"""Clean up the device after acquisition.
|
|
96
|
+
|
|
97
|
+
:return: An `AsyncStatus` that is marked done when the device is done unstaging.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@runtime_checkable
|
|
102
|
+
class AsyncMovable(Protocol[T_co]):
|
|
103
|
+
@abstractmethod
|
|
104
|
+
def set(self, value: T_co) -> AsyncStatus:
|
|
105
|
+
"""Return a ``Status`` that is marked done when the device is done moving."""
|
|
96
106
|
|
|
97
|
-
|
|
98
|
-
|
|
107
|
+
|
|
108
|
+
@runtime_checkable
|
|
109
|
+
class AsyncLocatable(AsyncMovable[T], Protocol):
|
|
110
|
+
@abstractmethod
|
|
111
|
+
async def locate(self) -> Location[T]:
|
|
112
|
+
"""Return the current location of a Device.
|
|
113
|
+
|
|
114
|
+
While a ``Readable`` reports many values, a ``Movable`` will have the
|
|
115
|
+
concept of location. This is where the Device currently is, and where it
|
|
116
|
+
was last requested to move to. This protocol formalizes how to get the
|
|
117
|
+
location from a ``Movable``.
|
|
99
118
|
"""
|
|
100
119
|
|
|
101
120
|
|
|
@@ -103,16 +122,17 @@ C = TypeVar("C", contravariant=True)
|
|
|
103
122
|
|
|
104
123
|
|
|
105
124
|
class Watcher(Protocol, Generic[C]):
|
|
106
|
-
|
|
125
|
+
"""Protocol for watching changes in values."""
|
|
126
|
+
|
|
107
127
|
def __call__(
|
|
108
|
-
|
|
109
|
-
current: C,
|
|
110
|
-
initial: C,
|
|
111
|
-
target: C,
|
|
112
|
-
name: str | None,
|
|
113
|
-
unit: str | None,
|
|
114
|
-
precision:
|
|
115
|
-
fraction: float | None,
|
|
116
|
-
time_elapsed: float | None,
|
|
117
|
-
time_remaining: float | None,
|
|
128
|
+
self,
|
|
129
|
+
current: C | None = None,
|
|
130
|
+
initial: C | None = None,
|
|
131
|
+
target: C | None = None,
|
|
132
|
+
name: str | None = None,
|
|
133
|
+
unit: str | None = None,
|
|
134
|
+
precision: int | None = None,
|
|
135
|
+
fraction: float | None = None,
|
|
136
|
+
time_elapsed: float | None = None,
|
|
137
|
+
time_remaining: float | None = None,
|
|
118
138
|
) -> Any: ...
|
ophyd_async/core/_providers.py
CHANGED
|
@@ -10,8 +10,7 @@ from typing import Protocol
|
|
|
10
10
|
|
|
11
11
|
@dataclass
|
|
12
12
|
class PathInfo:
|
|
13
|
-
"""
|
|
14
|
-
Information about where and how to write a file.
|
|
13
|
+
"""Information about where and how to write a file.
|
|
15
14
|
|
|
16
15
|
:param directory_path: Directory into which files should be written
|
|
17
16
|
:param filename: Base filename to use generated by FilenameProvider, w/o extension
|
|
@@ -25,18 +24,24 @@ class PathInfo:
|
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
class FilenameProvider(Protocol):
|
|
27
|
+
"""Base class for callable classes providing filenames."""
|
|
28
|
+
|
|
28
29
|
@abstractmethod
|
|
29
30
|
def __call__(self, device_name: str | None = None) -> str:
|
|
30
|
-
"""Get a filename to use for output data, w/o extension"""
|
|
31
|
+
"""Get a filename to use for output data, w/o extension."""
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
class PathProvider(Protocol):
|
|
35
|
+
"""Abstract class that tells a detector where to write its data."""
|
|
36
|
+
|
|
34
37
|
@abstractmethod
|
|
35
38
|
def __call__(self, device_name: str | None = None) -> PathInfo:
|
|
36
|
-
"""Get the current directory to write files into"""
|
|
39
|
+
"""Get the current directory to write files into."""
|
|
37
40
|
|
|
38
41
|
|
|
39
42
|
class StaticFilenameProvider(FilenameProvider):
|
|
43
|
+
"""Provides a constant filename on every call."""
|
|
44
|
+
|
|
40
45
|
def __init__(self, filename: str):
|
|
41
46
|
self._static_filename = filename
|
|
42
47
|
|
|
@@ -45,6 +50,8 @@ class StaticFilenameProvider(FilenameProvider):
|
|
|
45
50
|
|
|
46
51
|
|
|
47
52
|
class UUIDFilenameProvider(FilenameProvider):
|
|
53
|
+
"""Files will have a UUID as a filename."""
|
|
54
|
+
|
|
48
55
|
def __init__(
|
|
49
56
|
self,
|
|
50
57
|
uuid_call_func: Callable = uuid.uuid4,
|
|
@@ -68,6 +75,8 @@ class UUIDFilenameProvider(FilenameProvider):
|
|
|
68
75
|
|
|
69
76
|
|
|
70
77
|
class AutoIncrementFilenameProvider(FilenameProvider):
|
|
78
|
+
"""Provides a new numerically incremented filename on each call."""
|
|
79
|
+
|
|
71
80
|
def __init__(
|
|
72
81
|
self,
|
|
73
82
|
base_filename: str = "",
|
|
@@ -98,14 +107,16 @@ class AutoIncrementFilenameProvider(FilenameProvider):
|
|
|
98
107
|
|
|
99
108
|
|
|
100
109
|
class StaticPathProvider(PathProvider):
|
|
110
|
+
"""All files will be within a static directory."""
|
|
111
|
+
|
|
101
112
|
def __init__(
|
|
102
113
|
self,
|
|
103
114
|
filename_provider: FilenameProvider,
|
|
104
|
-
directory_path: Path,
|
|
115
|
+
directory_path: Path | str,
|
|
105
116
|
create_dir_depth: int = 0,
|
|
106
117
|
) -> None:
|
|
107
118
|
self._filename_provider = filename_provider
|
|
108
|
-
self._directory_path = directory_path
|
|
119
|
+
self._directory_path = Path(directory_path)
|
|
109
120
|
self._create_dir_depth = create_dir_depth
|
|
110
121
|
|
|
111
122
|
def __call__(self, device_name: str | None = None) -> PathInfo:
|
|
@@ -119,6 +130,8 @@ class StaticPathProvider(PathProvider):
|
|
|
119
130
|
|
|
120
131
|
|
|
121
132
|
class AutoIncrementingPathProvider(PathProvider):
|
|
133
|
+
"""Provides a new numerically incremented path on each call."""
|
|
134
|
+
|
|
122
135
|
def __init__(
|
|
123
136
|
self,
|
|
124
137
|
filename_provider: FilenameProvider,
|
|
@@ -169,6 +182,8 @@ class AutoIncrementingPathProvider(PathProvider):
|
|
|
169
182
|
|
|
170
183
|
|
|
171
184
|
class YMDPathProvider(PathProvider):
|
|
185
|
+
"""Provides a path with the date included in the directory name."""
|
|
186
|
+
|
|
172
187
|
def __init__(
|
|
173
188
|
self,
|
|
174
189
|
filename_provider: FilenameProvider,
|
|
@@ -206,16 +221,20 @@ class YMDPathProvider(PathProvider):
|
|
|
206
221
|
|
|
207
222
|
|
|
208
223
|
class NameProvider(Protocol):
|
|
224
|
+
"""Base class for callable classes providing data keys."""
|
|
225
|
+
|
|
209
226
|
@abstractmethod
|
|
210
227
|
def __call__(self) -> str:
|
|
211
|
-
"""Get the name to be used as a data_key in the descriptor document"""
|
|
228
|
+
"""Get the name to be used as a data_key in the descriptor document."""
|
|
212
229
|
|
|
213
230
|
|
|
214
231
|
class DatasetDescriber(Protocol):
|
|
232
|
+
"""For describing datasets in file writing."""
|
|
233
|
+
|
|
215
234
|
@abstractmethod
|
|
216
235
|
async def np_datatype(self) -> str:
|
|
217
|
-
"""
|
|
236
|
+
"""Return the numpy datatype for this dataset."""
|
|
218
237
|
|
|
219
238
|
@abstractmethod
|
|
220
239
|
async def shape(self) -> tuple[int, ...]:
|
|
221
|
-
"""Get the shape of the data collection"""
|
|
240
|
+
"""Get the shape of the data collection."""
|