ophyd-async 0.4.0__py3-none-any.whl → 0.5.1__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 +86 -73
- ophyd_async/core/{detector.py → _detector.py} +42 -36
- 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 -8
- 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} +7 -7
- ophyd_async/{protocols.py → core/_protocol.py} +1 -1
- ophyd_async/core/_providers.py +24 -37
- ophyd_async/core/{standard_readable.py → _readable.py} +6 -16
- ophyd_async/core/{signal.py → _signal.py} +79 -35
- 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 +47 -0
- ophyd_async/epics/adcore/_core_io.py +138 -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} +54 -29
- ophyd_async/epics/{areadetector/single_trigger_det.py → adcore/_single_trigger.py} +5 -6
- ophyd_async/epics/adcore/_utils.py +132 -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} +9 -5
- 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} +15 -17
- ophyd_async/epics/{areadetector/drivers/pilatus_driver.py → adpilatus/_pilatus_io.py} +6 -4
- 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} +9 -17
- ophyd_async/epics/{areadetector/drivers/vimba_driver.py → advimba/_vimba_io.py} +11 -8
- 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} +28 -14
- 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 +15 -7
- ophyd_async/epics/{_backend/common.py → signal/_common.py} +2 -2
- ophyd_async/epics/signal/_epics_transport.py +3 -3
- ophyd_async/epics/{_backend → signal}/_p4p.py +18 -14
- 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 +20 -15
- ophyd_async/{panda/_common_blocks.py → fastcs/panda/_block.py} +5 -3
- ophyd_async/{panda/_panda_controller.py → fastcs/panda/_control.py} +2 -1
- ophyd_async/{panda → fastcs/panda}/_hdf_panda.py +5 -10
- ophyd_async/{panda → fastcs/panda}/_trigger.py +3 -7
- ophyd_async/{panda/writers/_hdf_writer.py → fastcs/panda/_writer.py} +36 -28
- ophyd_async/plan_stubs/__init__.py +5 -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/plan_stubs/_nd_attributes.py +63 -0
- 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} +9 -7
- 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} +13 -11
- 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.1.dist-info}/METADATA +46 -44
- ophyd_async-0.5.1.dist-info/RECORD +90 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.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/utils.py +0 -104
- 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.1.dist-info}/LICENSE +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/entry_points.txt +0 -0
- {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/top_level.txt +0 -0
ophyd_async/core/_providers.py
CHANGED
|
@@ -13,34 +13,24 @@ class PathInfo:
|
|
|
13
13
|
"""
|
|
14
14
|
Information about where and how to write a file.
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
different applications mounting filesystems at different mount points.
|
|
18
|
-
The portion of this path which is relevant only for the writer is the 'root',
|
|
19
|
-
while the path from an agreed upon mutual mounting is the resource_path.
|
|
20
|
-
The resource_dir is used with the filename to construct the resource_path.
|
|
21
|
-
|
|
22
|
-
:param root: Path of a root directory, relevant only for the file writer
|
|
23
|
-
:param resource_dir: Directory into which files should be written, relative to root
|
|
16
|
+
:param directory_path: Directory into which files should be written
|
|
24
17
|
:param filename: Base filename to use generated by FilenameProvider, w/o extension
|
|
25
18
|
:param create_dir_depth: Optional depth of directories to create if they do not
|
|
26
19
|
exist
|
|
27
20
|
"""
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
resource_dir: Path
|
|
22
|
+
directory_path: Path
|
|
31
23
|
filename: str
|
|
32
24
|
create_dir_depth: int = 0
|
|
33
25
|
|
|
34
26
|
|
|
35
27
|
class FilenameProvider(Protocol):
|
|
36
28
|
@abstractmethod
|
|
37
|
-
def __call__(self) -> str:
|
|
29
|
+
def __call__(self, device_name: Optional[str] = None) -> str:
|
|
38
30
|
"""Get a filename to use for output data, w/o extension"""
|
|
39
31
|
|
|
40
32
|
|
|
41
33
|
class PathProvider(Protocol):
|
|
42
|
-
_filename_provider: FilenameProvider
|
|
43
|
-
|
|
44
34
|
@abstractmethod
|
|
45
35
|
def __call__(self, device_name: Optional[str] = None) -> PathInfo:
|
|
46
36
|
"""Get the current directory to write files into"""
|
|
@@ -50,7 +40,7 @@ class StaticFilenameProvider(FilenameProvider):
|
|
|
50
40
|
def __init__(self, filename: str):
|
|
51
41
|
self._static_filename = filename
|
|
52
42
|
|
|
53
|
-
def __call__(self) -> str:
|
|
43
|
+
def __call__(self, device_name: Optional[str] = None) -> str:
|
|
54
44
|
return self._static_filename
|
|
55
45
|
|
|
56
46
|
|
|
@@ -63,7 +53,7 @@ class UUIDFilenameProvider(FilenameProvider):
|
|
|
63
53
|
self._uuid_call_func = uuid_call_func
|
|
64
54
|
self._uuid_call_args = uuid_call_args or []
|
|
65
55
|
|
|
66
|
-
def __call__(self) -> str:
|
|
56
|
+
def __call__(self, device_name: Optional[str] = None) -> str:
|
|
67
57
|
if (
|
|
68
58
|
self._uuid_call_func in [uuid.uuid3, uuid.uuid5]
|
|
69
59
|
and len(self._uuid_call_args) < 2
|
|
@@ -92,7 +82,7 @@ class AutoIncrementFilenameProvider(FilenameProvider):
|
|
|
92
82
|
self._increment = increment
|
|
93
83
|
self._inc_delimeter = inc_delimeter
|
|
94
84
|
|
|
95
|
-
def __call__(self):
|
|
85
|
+
def __call__(self, device_name: Optional[str] = None) -> str:
|
|
96
86
|
if len(str(self._current_value)) > self._max_digits:
|
|
97
87
|
raise ValueError(
|
|
98
88
|
f"Auto incrementing filename counter \
|
|
@@ -112,20 +102,17 @@ class StaticPathProvider(PathProvider):
|
|
|
112
102
|
self,
|
|
113
103
|
filename_provider: FilenameProvider,
|
|
114
104
|
directory_path: Path,
|
|
115
|
-
resource_dir: Path = Path("."),
|
|
116
105
|
create_dir_depth: int = 0,
|
|
117
106
|
) -> None:
|
|
118
107
|
self._filename_provider = filename_provider
|
|
119
108
|
self._directory_path = directory_path
|
|
120
|
-
self._resource_dir = resource_dir
|
|
121
109
|
self._create_dir_depth = create_dir_depth
|
|
122
110
|
|
|
123
111
|
def __call__(self, device_name: Optional[str] = None) -> PathInfo:
|
|
124
|
-
filename = self._filename_provider()
|
|
112
|
+
filename = self._filename_provider(device_name)
|
|
125
113
|
|
|
126
114
|
return PathInfo(
|
|
127
|
-
|
|
128
|
-
resource_dir=self._resource_dir,
|
|
115
|
+
directory_path=self._directory_path,
|
|
129
116
|
filename=filename,
|
|
130
117
|
create_dir_depth=self._create_dir_depth,
|
|
131
118
|
)
|
|
@@ -135,7 +122,7 @@ class AutoIncrementingPathProvider(PathProvider):
|
|
|
135
122
|
def __init__(
|
|
136
123
|
self,
|
|
137
124
|
filename_provider: FilenameProvider,
|
|
138
|
-
|
|
125
|
+
base_directory_path: Path,
|
|
139
126
|
create_dir_depth: int = 0,
|
|
140
127
|
max_digits: int = 5,
|
|
141
128
|
starting_value: int = 0,
|
|
@@ -145,7 +132,7 @@ class AutoIncrementingPathProvider(PathProvider):
|
|
|
145
132
|
base_name: str = None,
|
|
146
133
|
) -> None:
|
|
147
134
|
self._filename_provider = filename_provider
|
|
148
|
-
self.
|
|
135
|
+
self._base_directory_path = base_directory_path
|
|
149
136
|
self._create_dir_depth = create_dir_depth
|
|
150
137
|
self._base_name = base_name
|
|
151
138
|
self._starting_value = starting_value
|
|
@@ -157,15 +144,17 @@ class AutoIncrementingPathProvider(PathProvider):
|
|
|
157
144
|
self._inc_delimeter = inc_delimeter
|
|
158
145
|
|
|
159
146
|
def __call__(self, device_name: Optional[str] = None) -> PathInfo:
|
|
160
|
-
filename = self._filename_provider()
|
|
147
|
+
filename = self._filename_provider(device_name)
|
|
161
148
|
|
|
162
149
|
padded_counter = f"{self._current_value:0{self._max_digits}}"
|
|
163
150
|
|
|
164
|
-
|
|
151
|
+
auto_inc_dir_name = str(padded_counter)
|
|
165
152
|
if self._base_name is not None:
|
|
166
|
-
|
|
153
|
+
auto_inc_dir_name = (
|
|
154
|
+
f"{self._base_name}{self._inc_delimeter}{padded_counter}"
|
|
155
|
+
)
|
|
167
156
|
elif device_name is not None:
|
|
168
|
-
|
|
157
|
+
auto_inc_dir_name = f"{device_name}{self._inc_delimeter}{padded_counter}"
|
|
169
158
|
|
|
170
159
|
self._inc_counter += 1
|
|
171
160
|
if self._inc_counter == self._num_calls_per_inc:
|
|
@@ -173,8 +162,7 @@ class AutoIncrementingPathProvider(PathProvider):
|
|
|
173
162
|
self._current_value += self._increment
|
|
174
163
|
|
|
175
164
|
return PathInfo(
|
|
176
|
-
|
|
177
|
-
resource_dir=resource_dir,
|
|
165
|
+
directory_path=self._base_directory_path / auto_inc_dir_name,
|
|
178
166
|
filename=filename,
|
|
179
167
|
create_dir_depth=self._create_dir_depth,
|
|
180
168
|
)
|
|
@@ -184,12 +172,12 @@ class YMDPathProvider(PathProvider):
|
|
|
184
172
|
def __init__(
|
|
185
173
|
self,
|
|
186
174
|
filename_provider: FilenameProvider,
|
|
187
|
-
|
|
175
|
+
base_directory_path: Path,
|
|
188
176
|
create_dir_depth: int = -3, # Default to -3 to create YMD dirs
|
|
189
177
|
device_name_as_base_dir: bool = False,
|
|
190
178
|
) -> None:
|
|
191
179
|
self._filename_provider = filename_provider
|
|
192
|
-
self.
|
|
180
|
+
self._base_directory_path = Path(base_directory_path)
|
|
193
181
|
self._create_dir_depth = create_dir_depth
|
|
194
182
|
self._device_name_as_base_dir = device_name_as_base_dir
|
|
195
183
|
|
|
@@ -197,22 +185,21 @@ class YMDPathProvider(PathProvider):
|
|
|
197
185
|
sep = os.path.sep
|
|
198
186
|
current_date = date.today().strftime(f"%Y{sep}%m{sep}%d")
|
|
199
187
|
if device_name is None:
|
|
200
|
-
|
|
188
|
+
ymd_dir_path = current_date
|
|
201
189
|
elif self._device_name_as_base_dir:
|
|
202
|
-
|
|
190
|
+
ymd_dir_path = os.path.join(
|
|
203
191
|
current_date,
|
|
204
192
|
device_name,
|
|
205
193
|
)
|
|
206
194
|
else:
|
|
207
|
-
|
|
195
|
+
ymd_dir_path = os.path.join(
|
|
208
196
|
device_name,
|
|
209
197
|
current_date,
|
|
210
198
|
)
|
|
211
199
|
|
|
212
|
-
filename = self._filename_provider()
|
|
200
|
+
filename = self._filename_provider(device_name)
|
|
213
201
|
return PathInfo(
|
|
214
|
-
|
|
215
|
-
resource_dir=resource_dir,
|
|
202
|
+
directory_path=self._base_directory_path / ymd_dir_path,
|
|
216
203
|
filename=filename,
|
|
217
204
|
create_dir_depth=self._create_dir_depth,
|
|
218
205
|
)
|
|
@@ -1,24 +1,14 @@
|
|
|
1
1
|
import warnings
|
|
2
2
|
from contextlib import contextmanager
|
|
3
|
-
from typing import
|
|
4
|
-
Callable,
|
|
5
|
-
Dict,
|
|
6
|
-
Generator,
|
|
7
|
-
Optional,
|
|
8
|
-
Sequence,
|
|
9
|
-
Tuple,
|
|
10
|
-
Type,
|
|
11
|
-
Union,
|
|
12
|
-
)
|
|
3
|
+
from typing import Callable, Dict, Generator, Optional, Sequence, Tuple, Type, Union
|
|
13
4
|
|
|
14
5
|
from bluesky.protocols import DataKey, HasHints, Hints, Reading
|
|
15
6
|
|
|
16
|
-
from
|
|
17
|
-
|
|
18
|
-
from .
|
|
19
|
-
from .
|
|
20
|
-
from .
|
|
21
|
-
from .utils import merge_gathered_dicts
|
|
7
|
+
from ._device import Device, DeviceVector
|
|
8
|
+
from ._protocol import AsyncConfigurable, AsyncReadable, AsyncStageable
|
|
9
|
+
from ._signal import SignalR
|
|
10
|
+
from ._status import AsyncStatus
|
|
11
|
+
from ._utils import merge_gathered_dicts
|
|
22
12
|
|
|
23
13
|
ReadableChild = Union[AsyncReadable, AsyncConfigurable, AsyncStageable, HasHints]
|
|
24
14
|
ReadableChildWrapper = Union[
|
|
@@ -12,6 +12,7 @@ from typing import (
|
|
|
12
12
|
Optional,
|
|
13
13
|
Tuple,
|
|
14
14
|
Type,
|
|
15
|
+
TypeVar,
|
|
15
16
|
Union,
|
|
16
17
|
)
|
|
17
18
|
|
|
@@ -25,14 +26,15 @@ from bluesky.protocols import (
|
|
|
25
26
|
Subscribable,
|
|
26
27
|
)
|
|
27
28
|
|
|
28
|
-
from
|
|
29
|
-
from
|
|
29
|
+
from ._device import Device
|
|
30
|
+
from ._mock_signal_backend import MockSignalBackend
|
|
31
|
+
from ._protocol import AsyncConfigurable, AsyncReadable, AsyncStageable
|
|
32
|
+
from ._signal_backend import SignalBackend
|
|
33
|
+
from ._soft_signal_backend import SignalMetadata, SoftSignalBackend
|
|
34
|
+
from ._status import AsyncStatus
|
|
35
|
+
from ._utils import DEFAULT_TIMEOUT, CalculatableTimeout, CalculateTimeout, Callback, T
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
from .device import Device
|
|
33
|
-
from .signal_backend import SignalBackend
|
|
34
|
-
from .soft_signal_backend import SignalMetadata, SoftSignalBackend
|
|
35
|
-
from .utils import DEFAULT_TIMEOUT, CalculatableTimeout, CalculateTimeout, Callback, T
|
|
37
|
+
S = TypeVar("S")
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
def _add_timeout(func):
|
|
@@ -43,15 +45,6 @@ def _add_timeout(func):
|
|
|
43
45
|
return wrapper
|
|
44
46
|
|
|
45
47
|
|
|
46
|
-
def _fail(self, other, *args, **kwargs):
|
|
47
|
-
if isinstance(other, Signal):
|
|
48
|
-
raise TypeError(
|
|
49
|
-
"Can't compare two Signals, did you mean await signal.get_value() instead?"
|
|
50
|
-
)
|
|
51
|
-
else:
|
|
52
|
-
return NotImplemented
|
|
53
|
-
|
|
54
|
-
|
|
55
48
|
class Signal(Device, Generic[T]):
|
|
56
49
|
"""A Device with the concept of a value, with R, RW, W and X flavours"""
|
|
57
50
|
|
|
@@ -116,12 +109,6 @@ class Signal(Device, Generic[T]):
|
|
|
116
109
|
"""Like ca://PV_PREFIX:SIGNAL, or "" if not set"""
|
|
117
110
|
return self._backend.source(self.name)
|
|
118
111
|
|
|
119
|
-
__lt__ = __le__ = __eq__ = __ge__ = __gt__ = __ne__ = _fail
|
|
120
|
-
|
|
121
|
-
def __hash__(self):
|
|
122
|
-
# Restore the default implementation so we can use in a set or dict
|
|
123
|
-
return hash(id(self))
|
|
124
|
-
|
|
125
112
|
|
|
126
113
|
class _SignalCache(Generic[T]):
|
|
127
114
|
def __init__(self, backend: SignalBackend[T], signal: Signal):
|
|
@@ -525,7 +512,9 @@ class _ValueChecker(Generic[T]):
|
|
|
525
512
|
|
|
526
513
|
|
|
527
514
|
async def wait_for_value(
|
|
528
|
-
signal: SignalR[T],
|
|
515
|
+
signal: SignalR[T],
|
|
516
|
+
match: Union[T, Callable[[T], bool]],
|
|
517
|
+
timeout: Optional[float],
|
|
529
518
|
):
|
|
530
519
|
"""Wait for a signal to have a matching value.
|
|
531
520
|
|
|
@@ -557,6 +546,66 @@ async def wait_for_value(
|
|
|
557
546
|
await checker.wait_for_value(signal, timeout)
|
|
558
547
|
|
|
559
548
|
|
|
549
|
+
async def set_and_wait_for_other_value(
|
|
550
|
+
set_signal: SignalRW[T],
|
|
551
|
+
set_value: T,
|
|
552
|
+
read_signal: SignalR[S],
|
|
553
|
+
read_value: S,
|
|
554
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
555
|
+
set_timeout: Optional[float] = None,
|
|
556
|
+
) -> AsyncStatus:
|
|
557
|
+
"""Set a signal and monitor another signal until it has the specified value.
|
|
558
|
+
|
|
559
|
+
This function sets a set_signal to a specified set_value and waits for
|
|
560
|
+
a read_signal to have the read_value.
|
|
561
|
+
|
|
562
|
+
Parameters
|
|
563
|
+
----------
|
|
564
|
+
signal:
|
|
565
|
+
The signal to set
|
|
566
|
+
set_value:
|
|
567
|
+
The value to set it to
|
|
568
|
+
read_signal:
|
|
569
|
+
The signal to monitor
|
|
570
|
+
read_value:
|
|
571
|
+
The value to wait for
|
|
572
|
+
timeout:
|
|
573
|
+
How long to wait for the signal to have the value
|
|
574
|
+
set_timeout:
|
|
575
|
+
How long to wait for the set to complete
|
|
576
|
+
|
|
577
|
+
Notes
|
|
578
|
+
-----
|
|
579
|
+
Example usage::
|
|
580
|
+
|
|
581
|
+
set_and_wait_for_value(device.acquire, 1, device.acquire_rbv, 1)
|
|
582
|
+
"""
|
|
583
|
+
# Start monitoring before the set to avoid a race condition
|
|
584
|
+
values_gen = observe_value(read_signal)
|
|
585
|
+
|
|
586
|
+
# Get the initial value from the monitor to make sure we've created it
|
|
587
|
+
current_value = await anext(values_gen)
|
|
588
|
+
|
|
589
|
+
status = set_signal.set(set_value, timeout=set_timeout)
|
|
590
|
+
|
|
591
|
+
# If the value was the same as before no need to wait for it to change
|
|
592
|
+
if current_value != read_value:
|
|
593
|
+
|
|
594
|
+
async def _wait_for_value():
|
|
595
|
+
async for value in values_gen:
|
|
596
|
+
if value == read_value:
|
|
597
|
+
break
|
|
598
|
+
|
|
599
|
+
try:
|
|
600
|
+
await asyncio.wait_for(_wait_for_value(), timeout)
|
|
601
|
+
except asyncio.TimeoutError as e:
|
|
602
|
+
raise TimeoutError(
|
|
603
|
+
f"{read_signal.name} didn't match {read_value} in {timeout}s"
|
|
604
|
+
) from e
|
|
605
|
+
|
|
606
|
+
return status
|
|
607
|
+
|
|
608
|
+
|
|
560
609
|
async def set_and_wait_for_value(
|
|
561
610
|
signal: SignalRW[T],
|
|
562
611
|
value: T,
|
|
@@ -566,19 +615,14 @@ async def set_and_wait_for_value(
|
|
|
566
615
|
"""Set a signal and monitor it until it has that value.
|
|
567
616
|
|
|
568
617
|
Useful for busy record, or other Signals with pattern:
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
- Return the Status so calling code can wait for operation to complete
|
|
573
|
-
|
|
574
|
-
This function sets a signal to a specified value, optionally with or without a
|
|
575
|
-
ca/pv put callback, and waits for the readback value of the signal to match the
|
|
576
|
-
value it was set to.
|
|
618
|
+
- Set Signal with wait=True and stash the Status
|
|
619
|
+
- Read the same Signal to check the operation has started
|
|
620
|
+
- Return the Status so calling code can wait for operation to complete
|
|
577
621
|
|
|
578
622
|
Parameters
|
|
579
623
|
----------
|
|
580
624
|
signal:
|
|
581
|
-
The signal to set
|
|
625
|
+
The signal to set
|
|
582
626
|
value:
|
|
583
627
|
The value to set it to
|
|
584
628
|
timeout:
|
|
@@ -592,6 +636,6 @@ async def set_and_wait_for_value(
|
|
|
592
636
|
|
|
593
637
|
set_and_wait_for_value(device.acquire, 1)
|
|
594
638
|
"""
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
639
|
+
return await set_and_wait_for_other_value(
|
|
640
|
+
signal, value, signal, value, timeout, status_timeout
|
|
641
|
+
)
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
|
-
from typing import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Literal,
|
|
7
|
-
Optional,
|
|
8
|
-
Tuple,
|
|
9
|
-
Type,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
from bluesky.protocols import DataKey, Reading
|
|
13
|
-
|
|
14
|
-
from .utils import DEFAULT_TIMEOUT, ReadingValueCallback, T
|
|
2
|
+
from typing import TYPE_CHECKING, ClassVar, Generic, Literal, Optional, Tuple, Type
|
|
3
|
+
|
|
4
|
+
from ._protocol import DataKey, Reading
|
|
5
|
+
from ._utils import DEFAULT_TIMEOUT, ReadingValueCallback, T
|
|
15
6
|
|
|
16
7
|
|
|
17
8
|
class SignalBackend(Generic[T]):
|
|
@@ -4,23 +4,14 @@ import inspect
|
|
|
4
4
|
import time
|
|
5
5
|
from collections import abc
|
|
6
6
|
from enum import Enum
|
|
7
|
-
from typing import
|
|
8
|
-
Dict,
|
|
9
|
-
Generic,
|
|
10
|
-
Optional,
|
|
11
|
-
Tuple,
|
|
12
|
-
Type,
|
|
13
|
-
Union,
|
|
14
|
-
cast,
|
|
15
|
-
get_origin,
|
|
16
|
-
)
|
|
7
|
+
from typing import Dict, Generic, Optional, Tuple, Type, Union, cast, get_origin
|
|
17
8
|
|
|
18
9
|
import numpy as np
|
|
19
10
|
from bluesky.protocols import DataKey, Dtype, Reading
|
|
20
11
|
from typing_extensions import TypedDict
|
|
21
12
|
|
|
22
|
-
from .
|
|
23
|
-
from .
|
|
13
|
+
from ._signal_backend import RuntimeSubsetEnum, SignalBackend
|
|
14
|
+
from ._utils import DEFAULT_TIMEOUT, ReadingValueCallback, T, get_dtype
|
|
24
15
|
|
|
25
16
|
primitive_dtypes: Dict[type, Dtype] = {
|
|
26
17
|
str: "string",
|
|
@@ -4,20 +4,12 @@ import asyncio
|
|
|
4
4
|
import functools
|
|
5
5
|
import time
|
|
6
6
|
from dataclasses import asdict, replace
|
|
7
|
-
from typing import
|
|
8
|
-
AsyncIterator,
|
|
9
|
-
Awaitable,
|
|
10
|
-
Callable,
|
|
11
|
-
Generic,
|
|
12
|
-
Type,
|
|
13
|
-
TypeVar,
|
|
14
|
-
cast,
|
|
15
|
-
)
|
|
7
|
+
from typing import AsyncIterator, Awaitable, Callable, Generic, Type, TypeVar, cast
|
|
16
8
|
|
|
17
9
|
from bluesky.protocols import Status
|
|
18
10
|
|
|
19
|
-
from
|
|
20
|
-
from .
|
|
11
|
+
from ._protocol import Watcher
|
|
12
|
+
from ._utils import Callback, P, T, WatcherUpdate
|
|
21
13
|
|
|
22
14
|
AS = TypeVar("AS", bound="AsyncStatus")
|
|
23
15
|
WAS = TypeVar("WAS", bound="WatchableAsyncStatus")
|
|
@@ -3,12 +3,10 @@ from typing import get_args
|
|
|
3
3
|
from bluesky.protocols import HasHints, Hints
|
|
4
4
|
|
|
5
5
|
from ophyd_async.core import PathProvider, StandardDetector
|
|
6
|
-
from ophyd_async.epics
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
from
|
|
10
|
-
from ophyd_async.epics.areadetector.drivers.aravis_driver import AravisDriver
|
|
11
|
-
from ophyd_async.epics.areadetector.writers import HDFWriter, NDFileHDF
|
|
6
|
+
from ophyd_async.epics import adcore
|
|
7
|
+
|
|
8
|
+
from ._aravis_controller import AravisController
|
|
9
|
+
from ._aravis_io import AravisDriverIO
|
|
12
10
|
|
|
13
11
|
|
|
14
12
|
class AravisDetector(StandardDetector, HasHints):
|
|
@@ -19,7 +17,7 @@ class AravisDetector(StandardDetector, HasHints):
|
|
|
19
17
|
"""
|
|
20
18
|
|
|
21
19
|
_controller: AravisController
|
|
22
|
-
_writer:
|
|
20
|
+
_writer: adcore.ADHDFWriter
|
|
23
21
|
|
|
24
22
|
def __init__(
|
|
25
23
|
self,
|
|
@@ -30,16 +28,16 @@ class AravisDetector(StandardDetector, HasHints):
|
|
|
30
28
|
name="",
|
|
31
29
|
gpio_number: AravisController.GPIO_NUMBER = 1,
|
|
32
30
|
):
|
|
33
|
-
self.drv =
|
|
34
|
-
self.hdf =
|
|
31
|
+
self.drv = AravisDriverIO(prefix + drv_suffix)
|
|
32
|
+
self.hdf = adcore.NDFileHDFIO(prefix + hdf_suffix)
|
|
35
33
|
|
|
36
34
|
super().__init__(
|
|
37
35
|
AravisController(self.drv, gpio_number=gpio_number),
|
|
38
|
-
|
|
36
|
+
adcore.ADHDFWriter(
|
|
39
37
|
self.hdf,
|
|
40
38
|
path_provider,
|
|
41
39
|
lambda: self.name,
|
|
42
|
-
ADBaseShapeProvider(self.drv),
|
|
40
|
+
adcore.ADBaseShapeProvider(self.drv),
|
|
43
41
|
),
|
|
44
42
|
config_sigs=(self.drv.acquire_time,),
|
|
45
43
|
name=name,
|
ophyd_async/epics/{areadetector/controllers/aravis_controller.py → adaravis/_aravis_controller.py}
RENAMED
|
@@ -7,12 +7,9 @@ from ophyd_async.core import (
|
|
|
7
7
|
DetectorTrigger,
|
|
8
8
|
set_and_wait_for_value,
|
|
9
9
|
)
|
|
10
|
-
from ophyd_async.epics
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
AravisTriggerSource,
|
|
14
|
-
)
|
|
15
|
-
from ophyd_async.epics.areadetector.utils import ImageMode, stop_busy_record
|
|
10
|
+
from ophyd_async.epics import adcore
|
|
11
|
+
|
|
12
|
+
from ._aravis_io import AravisDriverIO, AravisTriggerMode, AravisTriggerSource
|
|
16
13
|
|
|
17
14
|
# The deadtime of an ADaravis controller varies depending on the exact model of camera.
|
|
18
15
|
# Ideally we would maximize performance by dynamically retrieving the deadtime at
|
|
@@ -23,7 +20,7 @@ _HIGHEST_POSSIBLE_DEADTIME = 1961e-6
|
|
|
23
20
|
class AravisController(DetectorControl):
|
|
24
21
|
GPIO_NUMBER = Literal[1, 2, 3, 4]
|
|
25
22
|
|
|
26
|
-
def __init__(self, driver:
|
|
23
|
+
def __init__(self, driver: AravisDriverIO, gpio_number: GPIO_NUMBER) -> None:
|
|
27
24
|
self._drv = driver
|
|
28
25
|
self.gpio_number = gpio_number
|
|
29
26
|
|
|
@@ -37,9 +34,9 @@ class AravisController(DetectorControl):
|
|
|
37
34
|
exposure: Optional[float] = None,
|
|
38
35
|
) -> AsyncStatus:
|
|
39
36
|
if num == 0:
|
|
40
|
-
image_mode = ImageMode.continuous
|
|
37
|
+
image_mode = adcore.ImageMode.continuous
|
|
41
38
|
else:
|
|
42
|
-
image_mode = ImageMode.multiple
|
|
39
|
+
image_mode = adcore.ImageMode.multiple
|
|
43
40
|
if exposure is not None:
|
|
44
41
|
await self._drv.acquire_time.set(exposure)
|
|
45
42
|
|
|
@@ -76,4 +73,4 @@ class AravisController(DetectorControl):
|
|
|
76
73
|
return (AravisTriggerMode.on, f"Line{self.gpio_number}")
|
|
77
74
|
|
|
78
75
|
async def disarm(self):
|
|
79
|
-
await stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
76
|
+
await adcore.stop_busy_record(self._drv.acquire, False, timeout=1)
|
|
@@ -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,47 @@
|
|
|
1
|
+
from ._core_io import (
|
|
2
|
+
ADBaseIO,
|
|
3
|
+
DetectorState,
|
|
4
|
+
NDArrayBaseIO,
|
|
5
|
+
NDFileHDFIO,
|
|
6
|
+
NDPluginStatsIO,
|
|
7
|
+
)
|
|
8
|
+
from ._core_logic import (
|
|
9
|
+
DEFAULT_GOOD_STATES,
|
|
10
|
+
ADBaseShapeProvider,
|
|
11
|
+
set_exposure_time_and_acquire_period_if_supplied,
|
|
12
|
+
start_acquiring_driver_and_ensure_status,
|
|
13
|
+
)
|
|
14
|
+
from ._hdf_writer import ADHDFWriter
|
|
15
|
+
from ._single_trigger import SingleTriggerDetector
|
|
16
|
+
from ._utils import (
|
|
17
|
+
ADBaseDataType,
|
|
18
|
+
FileWriteMode,
|
|
19
|
+
ImageMode,
|
|
20
|
+
NDAttributeDataType,
|
|
21
|
+
NDAttributeParam,
|
|
22
|
+
NDAttributePv,
|
|
23
|
+
NDAttributePvDbrType,
|
|
24
|
+
stop_busy_record,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"ADBaseIO",
|
|
29
|
+
"DetectorState",
|
|
30
|
+
"NDArrayBaseIO",
|
|
31
|
+
"NDFileHDFIO",
|
|
32
|
+
"NDPluginStatsIO",
|
|
33
|
+
"DEFAULT_GOOD_STATES",
|
|
34
|
+
"ADBaseShapeProvider",
|
|
35
|
+
"set_exposure_time_and_acquire_period_if_supplied",
|
|
36
|
+
"start_acquiring_driver_and_ensure_status",
|
|
37
|
+
"ADHDFWriter",
|
|
38
|
+
"SingleTriggerDetector",
|
|
39
|
+
"ADBaseDataType",
|
|
40
|
+
"FileWriteMode",
|
|
41
|
+
"ImageMode",
|
|
42
|
+
"NDAttributePv",
|
|
43
|
+
"NDAttributeParam",
|
|
44
|
+
"NDAttributeDataType",
|
|
45
|
+
"stop_busy_record",
|
|
46
|
+
"NDAttributePvDbrType",
|
|
47
|
+
]
|