ophyd-async 0.10.0a4__py3-none-any.whl → 0.10.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/_derived_signal.py +1 -1
- ophyd_async/core/_derived_signal_backend.py +7 -5
- ophyd_async/core/_hdf_dataset.py +1 -1
- ophyd_async/core/_providers.py +1 -1
- ophyd_async/core/_signal.py +6 -1
- ophyd_async/core/_signal_backend.py +1 -1
- ophyd_async/epics/adcore/_core_logic.py +34 -10
- ophyd_async/epics/adcore/_hdf_writer.py +15 -0
- {ophyd_async-0.10.0a4.dist-info → ophyd_async-0.10.1.dist-info}/METADATA +2 -2
- {ophyd_async-0.10.0a4.dist-info → ophyd_async-0.10.1.dist-info}/RECORD +14 -14
- {ophyd_async-0.10.0a4.dist-info → ophyd_async-0.10.1.dist-info}/WHEEL +1 -1
- {ophyd_async-0.10.0a4.dist-info → ophyd_async-0.10.1.dist-info}/licenses/LICENSE +0 -0
- {ophyd_async-0.10.0a4.dist-info → ophyd_async-0.10.1.dist-info}/top_level.txt +0 -0
ophyd_async/_version.py
CHANGED
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '0.10.
|
|
21
|
-
__version_tuple__ = version_tuple = (0, 10,
|
|
20
|
+
__version__ = version = '0.10.1'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 10, 1)
|
|
@@ -248,7 +248,7 @@ def derived_signal_rw(
|
|
|
248
248
|
if raw_to_derived_datatype != set_derived_datatype:
|
|
249
249
|
msg = (
|
|
250
250
|
f"{raw_to_derived} has datatype {raw_to_derived_datatype} "
|
|
251
|
-
f"!= {set_derived_datatype}
|
|
251
|
+
f"!= {set_derived_datatype} datatype {set_derived_datatype}"
|
|
252
252
|
)
|
|
253
253
|
raise TypeError(msg)
|
|
254
254
|
|
|
@@ -61,7 +61,7 @@ class Transform(BaseModel, Generic[RawT, DerivedT]):
|
|
|
61
61
|
TransformT = TypeVar("TransformT", bound=Transform)
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
def
|
|
64
|
+
def validate_by_type(raw_devices: Mapping[str, Any], type_: type[T]) -> dict[str, T]:
|
|
65
65
|
filtered_devices: dict[str, T] = {}
|
|
66
66
|
for name, device in raw_devices.items():
|
|
67
67
|
if not isinstance(device, type_):
|
|
@@ -91,21 +91,23 @@ class SignalTransformer(Generic[TransformT]):
|
|
|
91
91
|
|
|
92
92
|
@cached_property
|
|
93
93
|
def raw_locatables(self) -> dict[str, AsyncLocatable]:
|
|
94
|
-
return
|
|
94
|
+
return validate_by_type(self._raw_devices, AsyncLocatable)
|
|
95
95
|
|
|
96
96
|
@cached_property
|
|
97
97
|
def transform_readables(self) -> dict[str, AsyncReadable]:
|
|
98
|
-
return
|
|
98
|
+
return validate_by_type(self._transform_devices, AsyncReadable)
|
|
99
99
|
|
|
100
100
|
@cached_property
|
|
101
101
|
def raw_and_transform_readables(self) -> dict[str, AsyncReadable]:
|
|
102
|
-
return
|
|
102
|
+
return validate_by_type(
|
|
103
103
|
self._raw_devices | self._transform_devices, AsyncReadable
|
|
104
104
|
)
|
|
105
105
|
|
|
106
106
|
@cached_property
|
|
107
107
|
def raw_and_transform_subscribables(self) -> dict[str, Subscribable]:
|
|
108
|
-
return
|
|
108
|
+
return validate_by_type(
|
|
109
|
+
self._raw_devices | self._transform_devices, Subscribable
|
|
110
|
+
)
|
|
109
111
|
|
|
110
112
|
def _complete_cached_reading(self) -> dict[str, Reading] | None:
|
|
111
113
|
if self._cached_readings and len(self._cached_readings) == len(
|
ophyd_async/core/_hdf_dataset.py
CHANGED
|
@@ -23,7 +23,7 @@ class HDFDatasetDescription(BaseModel):
|
|
|
23
23
|
"""The dataset name within the HDF file,
|
|
24
24
|
e.g. /entry/data/data or /entry/instrument/NDAttributes/sum"""
|
|
25
25
|
|
|
26
|
-
shape: tuple[int, ...] = Field(default_factory=tuple)
|
|
26
|
+
shape: tuple[int | None, ...] = Field(default_factory=tuple)
|
|
27
27
|
"""The shape of a single event's data in the HDF file,
|
|
28
28
|
e.g. (1, 768, 1024) for arrays or () for scalars"""
|
|
29
29
|
|
ophyd_async/core/_providers.py
CHANGED
ophyd_async/core/_signal.py
CHANGED
|
@@ -163,7 +163,12 @@ class _SignalCache(Generic[SignalDatatypeT]):
|
|
|
163
163
|
self._notify(function, want_value)
|
|
164
164
|
|
|
165
165
|
def unsubscribe(self, function: Callback) -> bool:
|
|
166
|
-
self._listeners.pop(function)
|
|
166
|
+
_listener = self._listeners.pop(function, None)
|
|
167
|
+
if not _listener:
|
|
168
|
+
self._signal.log.warning(
|
|
169
|
+
f"Unsubscribe failed: subscriber {function} was not found "
|
|
170
|
+
f" in listeners list: {list(self._listeners)}"
|
|
171
|
+
)
|
|
167
172
|
return self._staged or bool(self._listeners)
|
|
168
173
|
|
|
169
174
|
def set_staged(self, staged: bool) -> bool:
|
|
@@ -176,7 +176,7 @@ def _datakey_dtype_numpy(
|
|
|
176
176
|
raise TypeError(f"Can't make dtype_numpy for {datatype}")
|
|
177
177
|
|
|
178
178
|
|
|
179
|
-
def _datakey_shape(value: SignalDatatype) -> list[int]:
|
|
179
|
+
def _datakey_shape(value: SignalDatatype) -> list[int | None]:
|
|
180
180
|
if type(value) in _primitive_dtype or isinstance(value, EnumTypes):
|
|
181
181
|
return []
|
|
182
182
|
elif isinstance(value, np.ndarray):
|
|
@@ -7,6 +7,7 @@ from ophyd_async.core import (
|
|
|
7
7
|
DetectorController,
|
|
8
8
|
DetectorTrigger,
|
|
9
9
|
TriggerInfo,
|
|
10
|
+
observe_value,
|
|
10
11
|
set_and_wait_for_value,
|
|
11
12
|
)
|
|
12
13
|
|
|
@@ -89,34 +90,57 @@ class ADBaseController(DetectorController, Generic[ADBaseIOT]):
|
|
|
89
90
|
self.driver.acquire_period.set(full_frame_time, timeout=timeout),
|
|
90
91
|
)
|
|
91
92
|
|
|
92
|
-
async def start_acquiring_driver_and_ensure_status(
|
|
93
|
+
async def start_acquiring_driver_and_ensure_status(
|
|
94
|
+
self,
|
|
95
|
+
start_timeout: float = DEFAULT_TIMEOUT,
|
|
96
|
+
state_timeout: float = DEFAULT_TIMEOUT,
|
|
97
|
+
) -> AsyncStatus:
|
|
93
98
|
"""Start acquiring driver, raising ValueError if the detector is in a bad state.
|
|
94
99
|
|
|
95
100
|
This sets driver.acquire to True, and waits for it to be True up to a timeout.
|
|
96
101
|
Then, it checks that the DetectorState PV is in DEFAULT_GOOD_STATES,
|
|
97
102
|
and otherwise raises a ValueError.
|
|
98
103
|
|
|
104
|
+
|
|
105
|
+
:param start_timeout:
|
|
106
|
+
Timeout used for waiting for the driver to start
|
|
107
|
+
acquiring.
|
|
108
|
+
:param state_timeout:
|
|
109
|
+
Timeout used for waiting for the detector to be in a good
|
|
110
|
+
state after it stops acquiring.
|
|
99
111
|
:returns AsyncStatus:
|
|
100
112
|
An AsyncStatus that can be awaited to set driver.acquire to True and perform
|
|
101
113
|
subsequent raising (if applicable) due to detector state.
|
|
114
|
+
|
|
102
115
|
"""
|
|
103
116
|
status = await set_and_wait_for_value(
|
|
104
117
|
self.driver.acquire,
|
|
105
118
|
True,
|
|
106
|
-
timeout=
|
|
119
|
+
timeout=start_timeout,
|
|
107
120
|
wait_for_set_completion=False,
|
|
108
121
|
)
|
|
109
122
|
|
|
110
123
|
async def complete_acquisition() -> None:
|
|
111
|
-
# NOTE: possible race condition here between the callback from
|
|
112
|
-
# set_and_wait_for_value and the detector state updating.
|
|
113
124
|
await status
|
|
114
|
-
state =
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
state = None
|
|
126
|
+
try:
|
|
127
|
+
async for state in observe_value(
|
|
128
|
+
self.driver.detector_state, done_timeout=state_timeout
|
|
129
|
+
):
|
|
130
|
+
if state in self.good_states:
|
|
131
|
+
return
|
|
132
|
+
except asyncio.TimeoutError as exc:
|
|
133
|
+
if state is not None:
|
|
134
|
+
raise ValueError(
|
|
135
|
+
f"Final detector state {state.value} not in valid end "
|
|
136
|
+
f"states: {self.good_states}"
|
|
137
|
+
) from exc
|
|
138
|
+
else:
|
|
139
|
+
# No updates from the detector, something else is wrong
|
|
140
|
+
raise asyncio.TimeoutError(
|
|
141
|
+
"Could not monitor detector state: "
|
|
142
|
+
+ self.driver.detector_state.source
|
|
143
|
+
) from exc
|
|
120
144
|
|
|
121
145
|
return AsyncStatus(complete_acquisition())
|
|
122
146
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from collections.abc import AsyncIterator
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import TypeGuard
|
|
4
5
|
from xml.etree import ElementTree as ET
|
|
5
6
|
|
|
6
7
|
from bluesky.protocols import StreamAsset
|
|
@@ -22,6 +23,10 @@ from ._utils import (
|
|
|
22
23
|
)
|
|
23
24
|
|
|
24
25
|
|
|
26
|
+
def _is_fully_described(shape: tuple[int | None, ...]) -> TypeGuard[tuple[int, ...]]:
|
|
27
|
+
return None not in shape
|
|
28
|
+
|
|
29
|
+
|
|
25
30
|
class ADHDFWriter(ADWriter[NDFileHDFIO]):
|
|
26
31
|
"""Allow `NDFileHDFIO` to be used within `StandardDetector`."""
|
|
27
32
|
|
|
@@ -75,6 +80,16 @@ class ADHDFWriter(ADWriter[NDFileHDFIO]):
|
|
|
75
80
|
# Determine number of frames that will be saved per HDF chunk
|
|
76
81
|
frames_per_chunk = await self.fileio.num_frames_chunks.get_value()
|
|
77
82
|
|
|
83
|
+
if not _is_fully_described(detector_shape):
|
|
84
|
+
# Questions:
|
|
85
|
+
# - Can AreaDetector support this?
|
|
86
|
+
# - How to deal with chunking?
|
|
87
|
+
# Don't support for now - leave option open to support it later
|
|
88
|
+
raise ValueError(
|
|
89
|
+
"Datasets with partially unknown dimensionality "
|
|
90
|
+
"are not currently supported by ADHDFWriter."
|
|
91
|
+
)
|
|
92
|
+
|
|
78
93
|
# Add the main data
|
|
79
94
|
self._datasets = [
|
|
80
95
|
HDFDatasetDescription(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.1
|
|
4
4
|
Summary: Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
|
|
5
5
|
Author-email: Tom Cobb <tom.cobb@diamond.ac.uk>
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -43,7 +43,7 @@ Description-Content-Type: text/markdown
|
|
|
43
43
|
License-File: LICENSE
|
|
44
44
|
Requires-Dist: numpy
|
|
45
45
|
Requires-Dist: bluesky>=1.13.1rc2
|
|
46
|
-
Requires-Dist: event-model>=1.
|
|
46
|
+
Requires-Dist: event-model>=1.23
|
|
47
47
|
Requires-Dist: pyyaml
|
|
48
48
|
Requires-Dist: colorlog
|
|
49
49
|
Requires-Dist: pydantic>=2.0
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
ophyd_async/__init__.py,sha256=dcAA3qsj1nNIMe5l-v2tlduZ_ypwBmyuHe45Lsq4k4w,206
|
|
2
2
|
ophyd_async/__main__.py,sha256=n_U4O9bgm97OuboUB_9eK7eFiwy8BZSgXJ0OzbE0DqU,481
|
|
3
3
|
ophyd_async/_docs_parser.py,sha256=gPYrigfSbYCF7QoSf2UvE-cpQu4snSssl7ZWN-kKDzI,352
|
|
4
|
-
ophyd_async/_version.py,sha256=
|
|
4
|
+
ophyd_async/_version.py,sha256=StiR6uxiq6hqMzT3MUIl_ZooIq2cetH9oWrHUI_qWFU,513
|
|
5
5
|
ophyd_async/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
ophyd_async/core/__init__.py,sha256=mSoldXL3hou1UifwsUcos2Q3Vy_pAaNJJWdMc0VInyg,4516
|
|
7
|
-
ophyd_async/core/_derived_signal.py,sha256=
|
|
8
|
-
ophyd_async/core/_derived_signal_backend.py,sha256=
|
|
7
|
+
ophyd_async/core/_derived_signal.py,sha256=7ZZrDUnS2DGVwJZNX6_u0u-lAHKHCC7bL5auIfYV9w8,11440
|
|
8
|
+
ophyd_async/core/_derived_signal_backend.py,sha256=AZpyMmt3-ssymtDIa3138qPp1srmaId137A_yzQuFD0,12243
|
|
9
9
|
ophyd_async/core/_detector.py,sha256=PbWpv7lyBvYEJV-prG9qU0DadmxhyzMhQ9oLC0N7vwQ,15193
|
|
10
10
|
ophyd_async/core/_device.py,sha256=QSOgjXkvBpPWE1VhQ21tIC8d9z4Oadr6C_1tk4J21W4,14617
|
|
11
11
|
ophyd_async/core/_device_filler.py,sha256=MDz8eQQ-eEAwo-UEMxfqPfpcBuMG01tLCGR6utwVnmE,14825
|
|
12
12
|
ophyd_async/core/_flyer.py,sha256=YPCGAokF0GofOOO2OLrsSLoZSXs_RzmmrNglBunA31o,1924
|
|
13
|
-
ophyd_async/core/_hdf_dataset.py,sha256=
|
|
13
|
+
ophyd_async/core/_hdf_dataset.py,sha256=MKgA-6uxtCg-cxpGKAIxdWOw55CZp66si8lsak5e9CA,2875
|
|
14
14
|
ophyd_async/core/_log.py,sha256=DxKR4Nz3SgTaTzKBZWqt-w48yT8WUAr_3Qr223TEWRw,3587
|
|
15
15
|
ophyd_async/core/_mock_signal_backend.py,sha256=SPdCbVWss6-iL9C3t9u0IvR_Ln9JeDypVd18WlivdjE,3156
|
|
16
16
|
ophyd_async/core/_protocol.py,sha256=wQ_snxhTprHqEjQb1HgFwBljwolMY6A8C3xgV1PXwdU,4051
|
|
17
|
-
ophyd_async/core/_providers.py,sha256=
|
|
17
|
+
ophyd_async/core/_providers.py,sha256=1XuLUw9sT1pKMfH_PsDEpIi1gulla7NfPSp3IR3KfEA,7545
|
|
18
18
|
ophyd_async/core/_readable.py,sha256=iBo1YwA5bsAbzLbznvmSnzKDWUuGkLh850Br3BXsgeU,11707
|
|
19
19
|
ophyd_async/core/_settings.py,sha256=_ZccbXKP7j5rG6-bMKk7aaLr8hChdRDAPY_YSR71XXM,4213
|
|
20
|
-
ophyd_async/core/_signal.py,sha256=
|
|
21
|
-
ophyd_async/core/_signal_backend.py,sha256=
|
|
20
|
+
ophyd_async/core/_signal.py,sha256=1XHhnYwXa0yusSKdaRAiPUoVA5atcWd0S1ztBSaEi9k,27369
|
|
21
|
+
ophyd_async/core/_signal_backend.py,sha256=PvwTbbSVEGqM-2s5BNRrKGwM_MiYL71qMxYAgyZ7wRM,6930
|
|
22
22
|
ophyd_async/core/_soft_signal_backend.py,sha256=zrE7H2ojHY6oQBucLkFgukszrkdvbIZuavLjEUqc_xM,6227
|
|
23
23
|
ophyd_async/core/_status.py,sha256=h4TtWFM7wFtpxxyAYYSITgcVzArYZdYBHbya6qIX5t0,6553
|
|
24
24
|
ophyd_async/core/_table.py,sha256=l5GzL3La68ZkXpcOOVntnYr8ofFV8kWGr1hzY1ek83w,6897
|
|
@@ -38,9 +38,9 @@ ophyd_async/epics/adaravis/_aravis_io.py,sha256=af5RxeXF2ligvAXwMNMKHA4QHTR_WmNF
|
|
|
38
38
|
ophyd_async/epics/adcore/__init__.py,sha256=GipuBZwaAju4g15WjvGs78S4zjGVxmbPel4E29zHFvE,1583
|
|
39
39
|
ophyd_async/epics/adcore/_core_detector.py,sha256=mRDaHgXCTZF-MIVsU1csoQx9jObutYDpMWayugx2-jI,2631
|
|
40
40
|
ophyd_async/epics/adcore/_core_io.py,sha256=jm4gQUSq727xnPriuH6jFHqlDBZceKxr_XyBNj5F65U,7392
|
|
41
|
-
ophyd_async/epics/adcore/_core_logic.py,sha256=
|
|
41
|
+
ophyd_async/epics/adcore/_core_logic.py,sha256=IH7iOSVIsVj4e97ClhdBFpmdMkb8TznSaLkd3ohEhUs,8884
|
|
42
42
|
ophyd_async/epics/adcore/_core_writer.py,sha256=S58plRmbNzig-r7gubKjDVDni_nf4CASaV1OJvudbHw,8019
|
|
43
|
-
ophyd_async/epics/adcore/_hdf_writer.py,sha256=
|
|
43
|
+
ophyd_async/epics/adcore/_hdf_writer.py,sha256=GW_3NKRTF3kc9Wwz6vf5a7eqlnl81LXgk8afLgZaeNU,6134
|
|
44
44
|
ophyd_async/epics/adcore/_jpeg_writer.py,sha256=7XC4Twx_MaCBjeol27UA-hStOCQEjkEAb3ToVMPUlZ8,670
|
|
45
45
|
ophyd_async/epics/adcore/_single_trigger.py,sha256=tFGLT1b_rZzAvbqWP-hyCccxJMRY26T5IER-VAqKXmc,1275
|
|
46
46
|
ophyd_async/epics/adcore/_tiff_writer.py,sha256=Na30osfkgrq4VQhUzDcuS52Gy7FS08CzbgEmKwljTmk,671
|
|
@@ -143,8 +143,8 @@ ophyd_async/testing/_one_of_everything.py,sha256=Di0hPoKwrDOSsx50-2UdSHM2EbIKrPG
|
|
|
143
143
|
ophyd_async/testing/_single_derived.py,sha256=5-HOTzgePcZ354NK_ssVpyIbJoJmKyjVQCxSwQXUC-4,2730
|
|
144
144
|
ophyd_async/testing/_utils.py,sha256=zClRo5ve8RGia7wQnby41W-Zprj-slOA5da1LfYnuhw,45
|
|
145
145
|
ophyd_async/testing/_wait_for_pending.py,sha256=YZAR48n-CW0GsPey3zFRzMJ4byDAr3HvMIoawjmTrHw,732
|
|
146
|
-
ophyd_async-0.10.
|
|
147
|
-
ophyd_async-0.10.
|
|
148
|
-
ophyd_async-0.10.
|
|
149
|
-
ophyd_async-0.10.
|
|
150
|
-
ophyd_async-0.10.
|
|
146
|
+
ophyd_async-0.10.1.dist-info/licenses/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
|
|
147
|
+
ophyd_async-0.10.1.dist-info/METADATA,sha256=T43wg7KEoYRyA7xllFJLv9fM7OvNqYjuA047uX2zNlw,7071
|
|
148
|
+
ophyd_async-0.10.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
149
|
+
ophyd_async-0.10.1.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
|
|
150
|
+
ophyd_async-0.10.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|