ophyd-async 0.3.4a1__py3-none-any.whl → 0.4.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 +20 -8
- ophyd_async/core/_providers.py +186 -24
- ophyd_async/core/detector.py +14 -15
- ophyd_async/core/device.py +18 -6
- ophyd_async/core/signal.py +32 -8
- ophyd_async/core/soft_signal_backend.py +21 -6
- ophyd_async/epics/_backend/_aioca.py +3 -0
- ophyd_async/epics/_backend/_p4p.py +50 -2
- ophyd_async/epics/_backend/common.py +3 -1
- ophyd_async/epics/areadetector/aravis.py +3 -3
- ophyd_async/epics/areadetector/controllers/aravis_controller.py +1 -0
- ophyd_async/epics/areadetector/drivers/ad_base.py +3 -2
- ophyd_async/epics/areadetector/kinetix.py +3 -3
- ophyd_async/epics/areadetector/pilatus.py +3 -3
- ophyd_async/epics/areadetector/vimba.py +3 -3
- ophyd_async/epics/areadetector/writers/__init__.py +2 -2
- ophyd_async/epics/areadetector/writers/general_hdffile.py +97 -0
- ophyd_async/epics/areadetector/writers/hdf_writer.py +27 -10
- ophyd_async/epics/areadetector/writers/nd_file_hdf.py +3 -0
- ophyd_async/epics/areadetector/writers/nd_plugin.py +30 -0
- ophyd_async/epics/demo/demo_ad_sim_detector.py +3 -3
- ophyd_async/epics/motion/motor.py +132 -2
- ophyd_async/panda/__init__.py +15 -1
- ophyd_async/panda/_common_blocks.py +22 -1
- ophyd_async/panda/_hdf_panda.py +5 -3
- ophyd_async/panda/_table.py +20 -18
- ophyd_async/panda/_trigger.py +62 -7
- ophyd_async/panda/writers/_hdf_writer.py +17 -8
- ophyd_async/plan_stubs/ensure_connected.py +7 -2
- ophyd_async/plan_stubs/fly.py +58 -7
- ophyd_async/sim/pattern_generator.py +71 -182
- ophyd_async/sim/sim_pattern_detector_control.py +3 -3
- ophyd_async/sim/sim_pattern_detector_writer.py +9 -5
- ophyd_async/sim/sim_pattern_generator.py +12 -5
- {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.4.0.dist-info}/METADATA +7 -2
- {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.4.0.dist-info}/RECORD +41 -43
- {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.4.0.dist-info}/WHEEL +1 -1
- ophyd_async/epics/areadetector/writers/_hdfdataset.py +0 -10
- ophyd_async/epics/areadetector/writers/_hdffile.py +0 -54
- ophyd_async/panda/writers/_panda_hdf_file.py +0 -54
- {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.4.0.dist-info}/LICENSE +0 -0
- {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.4.0.dist-info}/entry_points.txt +0 -0
- {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -1,31 +1,14 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
1
|
from pathlib import Path
|
|
3
|
-
from typing import
|
|
4
|
-
Any,
|
|
5
|
-
AsyncGenerator,
|
|
6
|
-
AsyncIterator,
|
|
7
|
-
Dict,
|
|
8
|
-
Iterator,
|
|
9
|
-
List,
|
|
10
|
-
Optional,
|
|
11
|
-
Sequence,
|
|
12
|
-
)
|
|
2
|
+
from typing import AsyncGenerator, AsyncIterator, Dict, Optional
|
|
13
3
|
|
|
14
4
|
import h5py
|
|
15
5
|
import numpy as np
|
|
16
6
|
from bluesky.protocols import DataKey, StreamAsset
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
StreamDatum,
|
|
21
|
-
StreamRange,
|
|
22
|
-
StreamResource,
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
from ophyd_async.core import DirectoryInfo, DirectoryProvider
|
|
26
|
-
from ophyd_async.core.mock_signal_backend import MockSignalBackend
|
|
27
|
-
from ophyd_async.core.signal import SignalR, observe_value
|
|
7
|
+
|
|
8
|
+
from ophyd_async.core import PathProvider
|
|
9
|
+
from ophyd_async.core.signal import observe_value, soft_signal_r_and_setter
|
|
28
10
|
from ophyd_async.core.utils import DEFAULT_TIMEOUT
|
|
11
|
+
from ophyd_async.epics.areadetector.writers.general_hdffile import _HDFDataset, _HDFFile
|
|
29
12
|
|
|
30
13
|
# raw data path
|
|
31
14
|
DATA_PATH = "/entry/data/data"
|
|
@@ -35,35 +18,6 @@ SUM_PATH = "/entry/sum"
|
|
|
35
18
|
|
|
36
19
|
MAX_UINT8_VALUE = np.iinfo(np.uint8).max
|
|
37
20
|
|
|
38
|
-
SLICE_NAME = "AD_HDF5_SWMR_SLICE"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
@dataclass
|
|
42
|
-
class DatasetConfig:
|
|
43
|
-
name: str
|
|
44
|
-
shape: Sequence[int]
|
|
45
|
-
maxshape: tuple[Any, ...] = (None,)
|
|
46
|
-
path: Optional[str] = None
|
|
47
|
-
multiplier: Optional[int] = 1
|
|
48
|
-
dtype: Optional[Any] = None
|
|
49
|
-
fillvalue: Optional[int] = None
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def get_full_file_description(
|
|
53
|
-
datasets: List[DatasetConfig], outer_shape: tuple[int, ...]
|
|
54
|
-
):
|
|
55
|
-
full_file_description: Dict[str, DataKey] = {}
|
|
56
|
-
for d in datasets:
|
|
57
|
-
source = f"soft://{d.name}"
|
|
58
|
-
shape = outer_shape + tuple(d.shape)
|
|
59
|
-
dtype = "number" if d.shape == [1] else "array"
|
|
60
|
-
descriptor = DataKey(
|
|
61
|
-
source=source, shape=shape, dtype=dtype, external="STREAM:"
|
|
62
|
-
)
|
|
63
|
-
key = d.name.replace("/", "_")
|
|
64
|
-
full_file_description[key] = descriptor
|
|
65
|
-
return full_file_description
|
|
66
|
-
|
|
67
21
|
|
|
68
22
|
def generate_gaussian_blob(height: int, width: int) -> np.ndarray:
|
|
69
23
|
"""Make a Gaussian Blob with float values in range 0..1"""
|
|
@@ -81,71 +35,10 @@ def generate_interesting_pattern(x: float, y: float) -> float:
|
|
|
81
35
|
return z
|
|
82
36
|
|
|
83
37
|
|
|
84
|
-
class HdfStreamProvider:
|
|
85
|
-
def __init__(
|
|
86
|
-
self,
|
|
87
|
-
directory_info: DirectoryInfo,
|
|
88
|
-
full_file_name: Path,
|
|
89
|
-
datasets: List[DatasetConfig],
|
|
90
|
-
) -> None:
|
|
91
|
-
self._last_emitted = 0
|
|
92
|
-
self._bundles: List[ComposeStreamResourceBundle] = self._compose_bundles(
|
|
93
|
-
directory_info, full_file_name, datasets
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
def _compose_bundles(
|
|
97
|
-
self,
|
|
98
|
-
directory_info: DirectoryInfo,
|
|
99
|
-
full_file_name: Path,
|
|
100
|
-
datasets: List[DatasetConfig],
|
|
101
|
-
) -> List[StreamAsset]:
|
|
102
|
-
path = str(full_file_name.relative_to(directory_info.root))
|
|
103
|
-
root = str(directory_info.root)
|
|
104
|
-
bundler_composer = ComposeStreamResource()
|
|
105
|
-
|
|
106
|
-
bundles: List[ComposeStreamResourceBundle] = []
|
|
107
|
-
|
|
108
|
-
bundles = [
|
|
109
|
-
bundler_composer(
|
|
110
|
-
spec=SLICE_NAME,
|
|
111
|
-
root=root,
|
|
112
|
-
resource_path=path,
|
|
113
|
-
data_key=d.name.replace("/", "_"),
|
|
114
|
-
resource_kwargs={
|
|
115
|
-
"path": d.path,
|
|
116
|
-
"multiplier": d.multiplier,
|
|
117
|
-
"timestamps": "/entry/instrument/NDAttributes/NDArrayTimeStamp",
|
|
118
|
-
},
|
|
119
|
-
)
|
|
120
|
-
for d in datasets
|
|
121
|
-
]
|
|
122
|
-
return bundles
|
|
123
|
-
|
|
124
|
-
def stream_resources(self) -> Iterator[StreamResource]:
|
|
125
|
-
for bundle in self._bundles:
|
|
126
|
-
yield bundle.stream_resource_doc
|
|
127
|
-
|
|
128
|
-
def stream_data(self, indices_written: int) -> Iterator[StreamDatum]:
|
|
129
|
-
# Indices are relative to resource
|
|
130
|
-
if indices_written > self._last_emitted:
|
|
131
|
-
updated_stream_range = StreamRange(
|
|
132
|
-
start=self._last_emitted,
|
|
133
|
-
stop=indices_written,
|
|
134
|
-
)
|
|
135
|
-
self._last_emitted = indices_written
|
|
136
|
-
for bundle in self._bundles:
|
|
137
|
-
yield bundle.compose_stream_datum(indices=updated_stream_range)
|
|
138
|
-
return None
|
|
139
|
-
|
|
140
|
-
def close(self) -> None:
|
|
141
|
-
for bundle in self._bundles:
|
|
142
|
-
bundle.close()
|
|
143
|
-
|
|
144
|
-
|
|
145
38
|
class PatternGenerator:
|
|
146
39
|
def __init__(
|
|
147
40
|
self,
|
|
148
|
-
saturation_exposure_time: float = 1,
|
|
41
|
+
saturation_exposure_time: float = 0.1,
|
|
149
42
|
detector_width: int = 320,
|
|
150
43
|
detector_height: int = 240,
|
|
151
44
|
) -> None:
|
|
@@ -155,17 +48,15 @@ class PatternGenerator:
|
|
|
155
48
|
self.y = 0.0
|
|
156
49
|
self.height = detector_height
|
|
157
50
|
self.width = detector_width
|
|
158
|
-
self.
|
|
51
|
+
self.image_counter: int = 0
|
|
159
52
|
|
|
160
53
|
# it automatically initializes to 0
|
|
161
|
-
self.
|
|
162
|
-
self.
|
|
163
|
-
blob = np.array(
|
|
54
|
+
self.counter_signal, self._set_counter_signal = soft_signal_r_and_setter(int)
|
|
55
|
+
self._full_intensity_blob = (
|
|
164
56
|
generate_gaussian_blob(width=detector_width, height=detector_height)
|
|
165
57
|
* MAX_UINT8_VALUE
|
|
166
58
|
)
|
|
167
|
-
self.
|
|
168
|
-
self._hdf_stream_provider: Optional[HdfStreamProvider] = None
|
|
59
|
+
self._hdf_stream_provider: Optional[_HDFFile] = None
|
|
169
60
|
self._handle_for_h5_file: Optional[h5py.File] = None
|
|
170
61
|
self.target_path: Optional[Path] = None
|
|
171
62
|
|
|
@@ -173,31 +64,24 @@ class PatternGenerator:
|
|
|
173
64
|
assert self._handle_for_h5_file, "no file has been opened!"
|
|
174
65
|
# prepare - resize the fixed hdf5 data structure
|
|
175
66
|
# so that the new image can be written
|
|
176
|
-
|
|
177
|
-
|
|
67
|
+
self._handle_for_h5_file[DATA_PATH].resize(
|
|
68
|
+
(self.image_counter + 1, self.height, self.width)
|
|
69
|
+
)
|
|
70
|
+
self._handle_for_h5_file[SUM_PATH].resize((self.image_counter + 1,))
|
|
178
71
|
|
|
179
72
|
# generate the simulated data
|
|
180
73
|
intensity: float = generate_interesting_pattern(self.x, self.y)
|
|
181
|
-
detector_data
|
|
182
|
-
self.
|
|
74
|
+
detector_data = (
|
|
75
|
+
self._full_intensity_blob
|
|
183
76
|
* intensity
|
|
184
77
|
* self.exposure
|
|
185
78
|
/ self.saturation_exposure_time
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
self._handle_for_h5_file[DATA_PATH].resize(target_dimensions)
|
|
189
|
-
|
|
190
|
-
print(f"writing image {new_layer}")
|
|
191
|
-
assert self._handle_for_h5_file, "no file has been opened!"
|
|
192
|
-
self._handle_for_h5_file[DATA_PATH].resize(target_dimensions)
|
|
193
|
-
|
|
194
|
-
self._handle_for_h5_file[SUM_PATH].resize((new_layer,))
|
|
79
|
+
).astype(np.uint8)
|
|
195
80
|
|
|
196
81
|
# write data to disc (intermediate step)
|
|
197
|
-
self._handle_for_h5_file[DATA_PATH][self.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
)
|
|
82
|
+
self._handle_for_h5_file[DATA_PATH][self.image_counter] = detector_data
|
|
83
|
+
sum = np.sum(detector_data)
|
|
84
|
+
self._handle_for_h5_file[SUM_PATH][self.image_counter] = sum
|
|
201
85
|
|
|
202
86
|
# save metadata - so that it's discoverable
|
|
203
87
|
self._handle_for_h5_file[DATA_PATH].flush()
|
|
@@ -205,8 +89,8 @@ class PatternGenerator:
|
|
|
205
89
|
|
|
206
90
|
# counter increment is last
|
|
207
91
|
# as only at this point the new data is visible from the outside
|
|
208
|
-
self.
|
|
209
|
-
|
|
92
|
+
self.image_counter += 1
|
|
93
|
+
self._set_counter_signal(self.image_counter)
|
|
210
94
|
|
|
211
95
|
def set_exposure(self, value: float) -> None:
|
|
212
96
|
self.exposure = value
|
|
@@ -218,63 +102,70 @@ class PatternGenerator:
|
|
|
218
102
|
self.y = value
|
|
219
103
|
|
|
220
104
|
async def open_file(
|
|
221
|
-
self,
|
|
105
|
+
self, path_provider: PathProvider, name: str, multiplier: int = 1
|
|
222
106
|
) -> Dict[str, DataKey]:
|
|
223
|
-
await self.
|
|
107
|
+
await self.counter_signal.connect()
|
|
224
108
|
|
|
225
|
-
self.target_path = self._get_new_path(
|
|
109
|
+
self.target_path = self._get_new_path(path_provider)
|
|
110
|
+
self._path_provider = path_provider
|
|
226
111
|
|
|
227
112
|
self._handle_for_h5_file = h5py.File(self.target_path, "w", libver="latest")
|
|
228
113
|
|
|
229
114
|
assert self._handle_for_h5_file, "not loaded the file right"
|
|
230
115
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
self.
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
116
|
+
self._handle_for_h5_file.create_dataset(
|
|
117
|
+
name=DATA_PATH,
|
|
118
|
+
shape=(0, self.height, self.width),
|
|
119
|
+
dtype=np.uint8,
|
|
120
|
+
maxshape=(None, self.height, self.width),
|
|
121
|
+
)
|
|
122
|
+
self._handle_for_h5_file.create_dataset(
|
|
123
|
+
name=SUM_PATH,
|
|
124
|
+
shape=(0,),
|
|
125
|
+
dtype=np.float64,
|
|
126
|
+
maxshape=(None,),
|
|
127
|
+
)
|
|
239
128
|
|
|
240
129
|
# once datasets written, can switch the model to single writer multiple reader
|
|
241
130
|
self._handle_for_h5_file.swmr_mode = True
|
|
131
|
+
self.multiplier = multiplier
|
|
242
132
|
|
|
243
133
|
outer_shape = (multiplier,) if multiplier > 1 else ()
|
|
244
|
-
full_file_description = get_full_file_description(datasets, outer_shape)
|
|
245
134
|
|
|
246
135
|
# cache state to self
|
|
247
|
-
|
|
248
|
-
self.
|
|
249
|
-
|
|
250
|
-
|
|
136
|
+
# Add the main data
|
|
137
|
+
self._datasets = [
|
|
138
|
+
_HDFDataset(
|
|
139
|
+
data_key=name,
|
|
140
|
+
dataset=DATA_PATH,
|
|
141
|
+
shape=(self.height, self.width),
|
|
142
|
+
multiplier=multiplier,
|
|
143
|
+
),
|
|
144
|
+
_HDFDataset(
|
|
145
|
+
f"{name}-sum",
|
|
146
|
+
dataset=SUM_PATH,
|
|
147
|
+
shape=(),
|
|
148
|
+
multiplier=multiplier,
|
|
149
|
+
),
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
describe = {
|
|
153
|
+
ds.data_key: DataKey(
|
|
154
|
+
source="sim://pattern-generator-hdf-file",
|
|
155
|
+
shape=outer_shape + tuple(ds.shape),
|
|
156
|
+
dtype="array" if ds.shape else "number",
|
|
157
|
+
external="STREAM:",
|
|
158
|
+
)
|
|
159
|
+
for ds in self._datasets
|
|
160
|
+
}
|
|
161
|
+
return describe
|
|
251
162
|
|
|
252
|
-
def _get_new_path(self,
|
|
253
|
-
info =
|
|
254
|
-
filename =
|
|
163
|
+
def _get_new_path(self, path_provider: PathProvider) -> Path:
|
|
164
|
+
info = path_provider(device_name="pattern")
|
|
165
|
+
filename = info.filename
|
|
255
166
|
new_path: Path = info.root / info.resource_dir / filename
|
|
256
167
|
return new_path
|
|
257
168
|
|
|
258
|
-
def _get_datasets(self) -> List[DatasetConfig]:
|
|
259
|
-
raw_dataset = DatasetConfig(
|
|
260
|
-
# name=data_name,
|
|
261
|
-
name=DATA_PATH,
|
|
262
|
-
dtype=np.uint8,
|
|
263
|
-
shape=(1, self.height, self.width),
|
|
264
|
-
maxshape=(None, self.height, self.width),
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
sum_dataset = DatasetConfig(
|
|
268
|
-
name=SUM_PATH,
|
|
269
|
-
dtype=np.float64,
|
|
270
|
-
shape=(1,),
|
|
271
|
-
maxshape=(None,),
|
|
272
|
-
fillvalue=-1,
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
datasets: List[DatasetConfig] = [raw_dataset, sum_dataset]
|
|
276
|
-
return datasets
|
|
277
|
-
|
|
278
169
|
async def collect_stream_docs(
|
|
279
170
|
self, indices_written: int
|
|
280
171
|
) -> AsyncIterator[StreamAsset]:
|
|
@@ -292,10 +183,8 @@ class PatternGenerator:
|
|
|
292
183
|
# until the first frame comes in
|
|
293
184
|
if not self._hdf_stream_provider:
|
|
294
185
|
assert self.target_path, "open file has not been called"
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
self._hdf_stream_provider = HdfStreamProvider(
|
|
298
|
-
self._directory_provider(),
|
|
186
|
+
self._hdf_stream_provider = _HDFFile(
|
|
187
|
+
self._path_provider(),
|
|
299
188
|
self.target_path,
|
|
300
189
|
self._datasets,
|
|
301
190
|
)
|
|
@@ -314,5 +203,5 @@ class PatternGenerator:
|
|
|
314
203
|
async def observe_indices_written(
|
|
315
204
|
self, timeout=DEFAULT_TIMEOUT
|
|
316
205
|
) -> AsyncGenerator[int, None]:
|
|
317
|
-
async for num_captured in observe_value(self.
|
|
206
|
+
async for num_captured in observe_value(self.counter_signal, timeout=timeout):
|
|
318
207
|
yield num_captured // self.multiplier
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
|
-
from ophyd_async.core import
|
|
4
|
+
from ophyd_async.core import PathProvider
|
|
5
5
|
from ophyd_async.core.async_status import AsyncStatus
|
|
6
6
|
from ophyd_async.core.detector import DetectorControl, DetectorTrigger
|
|
7
7
|
from ophyd_async.sim.pattern_generator import PatternGenerator
|
|
@@ -11,12 +11,12 @@ class SimPatternDetectorControl(DetectorControl):
|
|
|
11
11
|
def __init__(
|
|
12
12
|
self,
|
|
13
13
|
pattern_generator: PatternGenerator,
|
|
14
|
-
|
|
14
|
+
path_provider: PathProvider,
|
|
15
15
|
exposure: float = 0.1,
|
|
16
16
|
) -> None:
|
|
17
17
|
self.pattern_generator: PatternGenerator = pattern_generator
|
|
18
18
|
self.pattern_generator.set_exposure(exposure)
|
|
19
|
-
self.
|
|
19
|
+
self.path_provider: PathProvider = path_provider
|
|
20
20
|
self.task: Optional[asyncio.Task] = None
|
|
21
21
|
super().__init__()
|
|
22
22
|
|
|
@@ -2,7 +2,7 @@ from typing import AsyncGenerator, AsyncIterator, Dict
|
|
|
2
2
|
|
|
3
3
|
from bluesky.protocols import DataKey
|
|
4
4
|
|
|
5
|
-
from ophyd_async.core import
|
|
5
|
+
from ophyd_async.core import NameProvider, PathProvider
|
|
6
6
|
from ophyd_async.core.detector import DetectorWriter
|
|
7
7
|
from ophyd_async.sim.pattern_generator import PatternGenerator
|
|
8
8
|
|
|
@@ -11,14 +11,18 @@ class SimPatternDetectorWriter(DetectorWriter):
|
|
|
11
11
|
pattern_generator: PatternGenerator
|
|
12
12
|
|
|
13
13
|
def __init__(
|
|
14
|
-
self,
|
|
14
|
+
self,
|
|
15
|
+
pattern_generator: PatternGenerator,
|
|
16
|
+
path_provider: PathProvider,
|
|
17
|
+
name_provider: NameProvider,
|
|
15
18
|
) -> None:
|
|
16
19
|
self.pattern_generator = pattern_generator
|
|
17
|
-
self.
|
|
20
|
+
self.path_provider = path_provider
|
|
21
|
+
self.name_provider = name_provider
|
|
18
22
|
|
|
19
23
|
async def open(self, multiplier: int = 1) -> Dict[str, DataKey]:
|
|
20
24
|
return await self.pattern_generator.open_file(
|
|
21
|
-
self.
|
|
25
|
+
self.path_provider, self.name_provider(), multiplier
|
|
22
26
|
)
|
|
23
27
|
|
|
24
28
|
async def close(self) -> None:
|
|
@@ -31,4 +35,4 @@ class SimPatternDetectorWriter(DetectorWriter):
|
|
|
31
35
|
return self.pattern_generator.observe_indices_written()
|
|
32
36
|
|
|
33
37
|
async def get_indices_written(self) -> int:
|
|
34
|
-
return self.pattern_generator.
|
|
38
|
+
return self.pattern_generator.image_counter
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from typing import Sequence
|
|
3
3
|
|
|
4
|
-
from ophyd_async.core import
|
|
4
|
+
from ophyd_async.core import (
|
|
5
|
+
FilenameProvider,
|
|
6
|
+
PathProvider,
|
|
7
|
+
StaticFilenameProvider,
|
|
8
|
+
StaticPathProvider,
|
|
9
|
+
)
|
|
5
10
|
from ophyd_async.core.detector import StandardDetector
|
|
6
11
|
from ophyd_async.protocols import AsyncReadable
|
|
7
12
|
from ophyd_async.sim.pattern_generator import PatternGenerator
|
|
@@ -15,17 +20,19 @@ class SimPatternDetector(StandardDetector):
|
|
|
15
20
|
self,
|
|
16
21
|
path: Path,
|
|
17
22
|
config_sigs: Sequence[AsyncReadable] = [],
|
|
18
|
-
name: str = "
|
|
23
|
+
name: str = "",
|
|
19
24
|
) -> None:
|
|
20
|
-
|
|
25
|
+
fp: FilenameProvider = StaticFilenameProvider(name)
|
|
26
|
+
self.path_provider: PathProvider = StaticPathProvider(fp, path)
|
|
21
27
|
self.pattern_generator = PatternGenerator()
|
|
22
28
|
writer = SimPatternDetectorWriter(
|
|
23
29
|
pattern_generator=self.pattern_generator,
|
|
24
|
-
|
|
30
|
+
path_provider=self.path_provider,
|
|
31
|
+
name_provider=lambda: self.name,
|
|
25
32
|
)
|
|
26
33
|
controller = SimPatternDetectorControl(
|
|
27
34
|
pattern_generator=self.pattern_generator,
|
|
28
|
-
|
|
35
|
+
path_provider=self.path_provider,
|
|
29
36
|
)
|
|
30
37
|
super().__init__(
|
|
31
38
|
controller=controller,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
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
|
|
@@ -45,10 +45,12 @@ Requires-Dist: numpy <2.0.0
|
|
|
45
45
|
Requires-Dist: packaging
|
|
46
46
|
Requires-Dist: pint
|
|
47
47
|
Requires-Dist: bluesky >=1.13.0a3
|
|
48
|
-
Requires-Dist: event-model
|
|
48
|
+
Requires-Dist: event-model
|
|
49
49
|
Requires-Dist: p4p
|
|
50
50
|
Requires-Dist: pyyaml
|
|
51
51
|
Requires-Dist: colorlog
|
|
52
|
+
Requires-Dist: pydantic >=2.0
|
|
53
|
+
Requires-Dist: pydantic-numpy
|
|
52
54
|
Provides-Extra: ca
|
|
53
55
|
Requires-Dist: aioca >=1.6 ; extra == 'ca'
|
|
54
56
|
Provides-Extra: dev
|
|
@@ -79,10 +81,13 @@ Requires-Dist: pytest-faulthandler ; extra == 'dev'
|
|
|
79
81
|
Requires-Dist: pytest-rerunfailures ; extra == 'dev'
|
|
80
82
|
Requires-Dist: pytest-timeout ; extra == 'dev'
|
|
81
83
|
Requires-Dist: ruff ; extra == 'dev'
|
|
84
|
+
Requires-Dist: sphinx <7.4.0 ; extra == 'dev'
|
|
82
85
|
Requires-Dist: sphinx-autobuild ; extra == 'dev'
|
|
86
|
+
Requires-Dist: autodoc-pydantic ; extra == 'dev'
|
|
83
87
|
Requires-Dist: sphinxcontrib-mermaid ; extra == 'dev'
|
|
84
88
|
Requires-Dist: sphinx-copybutton ; extra == 'dev'
|
|
85
89
|
Requires-Dist: sphinx-design ; extra == 'dev'
|
|
90
|
+
Requires-Dist: super-state-machine ; extra == 'dev'
|
|
86
91
|
Requires-Dist: tox-direct ; extra == 'dev'
|
|
87
92
|
Requires-Dist: types-mock ; extra == 'dev'
|
|
88
93
|
Requires-Dist: types-pyyaml ; extra == 'dev'
|
|
@@ -1,86 +1,84 @@
|
|
|
1
1
|
ophyd_async/__init__.py,sha256=v-rRiDOgZ3sQSMQKq0vgUQZvpeOkoHFXissAx6Ktg84,61
|
|
2
2
|
ophyd_async/__main__.py,sha256=G-Zcv_G9zK7Nhx6o5L5w-wyhMxdl_WgyMELu8IMFqAE,328
|
|
3
|
-
ophyd_async/_version.py,sha256=
|
|
3
|
+
ophyd_async/_version.py,sha256=j90u3VVU4UrJf1fgMUhaZarHK_Do2XGYXr-vZvOFzVo,411
|
|
4
4
|
ophyd_async/log.py,sha256=DbMjt0bkfUOLHIinZYt0Q0FHZmCXXi5x8y0uFiEmqoQ,3587
|
|
5
5
|
ophyd_async/protocols.py,sha256=EF2W9nfElV-0QNMYrX1zusL1PqDJR3kNsjlalR29j0I,3412
|
|
6
|
-
ophyd_async/core/__init__.py,sha256=
|
|
7
|
-
ophyd_async/core/_providers.py,sha256
|
|
6
|
+
ophyd_async/core/__init__.py,sha256=smUUnG2xf5XJMTk_aGKAPg2ZEZTWhABd-p4qCExipqY,3366
|
|
7
|
+
ophyd_async/core/_providers.py,sha256=-HlisysZZcqs6z1yQsWCpof7hQ9QTbg2IYpm4XaErGQ,7454
|
|
8
8
|
ophyd_async/core/async_status.py,sha256=9TOgOXIAuH62RDo5t-Y5GdjrJ76d_6TFlBxYv-5_a88,4367
|
|
9
|
-
ophyd_async/core/detector.py,sha256=
|
|
10
|
-
ophyd_async/core/device.py,sha256=
|
|
9
|
+
ophyd_async/core/detector.py,sha256=x6zxmDjbh8d6meJc8L2NidxI3Uj5bFPWo_FSaRDDBoM,11271
|
|
10
|
+
ophyd_async/core/device.py,sha256=mb-zxxmr5RftdBO8YPDJayP4ovNWEgW4qh2v1UU7ROg,7553
|
|
11
11
|
ophyd_async/core/device_save_loader.py,sha256=EK7FB5oWiLI_s2KZ1BNDQ2AUKVbFLlimMl0vXfsjcgo,8223
|
|
12
12
|
ophyd_async/core/flyer.py,sha256=bIjzBkrl8HVAlKgsZ_FF0WL69Qvksyzp9ZWmTLl8Yrw,2304
|
|
13
13
|
ophyd_async/core/mock_signal_backend.py,sha256=Ug6jK72wm9vM6EueoUrYgcXtiFzdPUEISRe86LdyYKc,2844
|
|
14
14
|
ophyd_async/core/mock_signal_utils.py,sha256=LE8VxNq3jfaTePnHHpZpKCi1vwKi8EIg-g1jfw-Q5bQ,4726
|
|
15
|
-
ophyd_async/core/signal.py,sha256=
|
|
15
|
+
ophyd_async/core/signal.py,sha256=9zRoHLkSHoa451LmABtpzSvymo0GmC3jAQDQDp0kuMU,18531
|
|
16
16
|
ophyd_async/core/signal_backend.py,sha256=U9J6jzHXRNIrdtGiZBVxXTRtzeejXiXEEIOGRIQhiS8,2678
|
|
17
|
-
ophyd_async/core/soft_signal_backend.py,sha256=
|
|
17
|
+
ophyd_async/core/soft_signal_backend.py,sha256=96Zk8ly8Qw6_l4RmB7NW95fbFCsRUTXH2H2JtH46_pY,6688
|
|
18
18
|
ophyd_async/core/standard_readable.py,sha256=fhq_WAZtLYWrw6DvvrFRYRAPOUP2_IcX4qLucoEEeOg,9049
|
|
19
19
|
ophyd_async/core/utils.py,sha256=3oZcXNqAUHX4ZWMBH5gSuK6cFWEhSkZ9GSDYv0pf8jc,5783
|
|
20
20
|
ophyd_async/epics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
ophyd_async/epics/_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
-
ophyd_async/epics/_backend/_aioca.py,sha256=
|
|
23
|
-
ophyd_async/epics/_backend/_p4p.py,sha256=
|
|
24
|
-
ophyd_async/epics/_backend/common.py,sha256=
|
|
22
|
+
ophyd_async/epics/_backend/_aioca.py,sha256=JwMX_8E1kw8GWlIRhXpJ2BExbZG7Ps2OOQWgdqwzo8c,11433
|
|
23
|
+
ophyd_async/epics/_backend/_p4p.py,sha256=RN3skNzG9PKKvIUccqnccVvsfgm4lS1x4g02X5ds00c,15816
|
|
24
|
+
ophyd_async/epics/_backend/common.py,sha256=gxI3c0T_Y-TVnAPabzPF0Y5Xo12xSvtpp5ytAfCxwWA,1863
|
|
25
25
|
ophyd_async/epics/areadetector/__init__.py,sha256=ViKzx-wUxkRyNR33wfpL11QB97o0J47_KMyI2C_NphI,510
|
|
26
|
-
ophyd_async/epics/areadetector/aravis.py,sha256=
|
|
27
|
-
ophyd_async/epics/areadetector/kinetix.py,sha256=
|
|
28
|
-
ophyd_async/epics/areadetector/pilatus.py,sha256=
|
|
26
|
+
ophyd_async/epics/areadetector/aravis.py,sha256=zRhC0tQTZvBUUcPqJV9EZFJhCL_4ib-O8VcSbPxf9wg,2107
|
|
27
|
+
ophyd_async/epics/areadetector/kinetix.py,sha256=lO-vuE_joIklLL2f0isUZCwVyhFcb4HkXqeCa-gD4kQ,1339
|
|
28
|
+
ophyd_async/epics/areadetector/pilatus.py,sha256=u-c_imklak1GQObqvQ-ziiS3_GEHP5csPlsVfaM_sDU,2024
|
|
29
29
|
ophyd_async/epics/areadetector/single_trigger_det.py,sha256=U92dqhioIfnve3jtCThq9gXBCdEzzqzY4ezk6rZV19g,1182
|
|
30
30
|
ophyd_async/epics/areadetector/utils.py,sha256=p66UbVdKRFj6Sm1Qvm23kmlVyBMMqIvXFxA3x17YnSk,2824
|
|
31
|
-
ophyd_async/epics/areadetector/vimba.py,sha256=
|
|
31
|
+
ophyd_async/epics/areadetector/vimba.py,sha256=9KkgXJjJJHc0QQ7E4FAt6n7d6-leUAnEgLVzrIoLE6c,1271
|
|
32
32
|
ophyd_async/epics/areadetector/controllers/__init__.py,sha256=af58ci7X2z2s_FyUwR3IGQrws8q4TKcBw7vFyIS5FoI,217
|
|
33
33
|
ophyd_async/epics/areadetector/controllers/ad_sim_controller.py,sha256=mthZ6WxajMEgUKptq3bnkIctbLhjzTagV66i1auB8cg,1587
|
|
34
|
-
ophyd_async/epics/areadetector/controllers/aravis_controller.py,sha256=
|
|
34
|
+
ophyd_async/epics/areadetector/controllers/aravis_controller.py,sha256=2C3pGdvzVDBlYsJv4USv-hZ-BpyQUxoZqJTKz0_zPLY,2707
|
|
35
35
|
ophyd_async/epics/areadetector/controllers/kinetix_controller.py,sha256=9QmydX85QOXfQL_UX49M9EQ2b2hUZPVzLxgGQn-A9Oc,1611
|
|
36
36
|
ophyd_async/epics/areadetector/controllers/pilatus_controller.py,sha256=6AiMz2yBA9xig-BrAIAc9CDxwM4Cjfebc4dd7QRutB0,2740
|
|
37
37
|
ophyd_async/epics/areadetector/controllers/vimba_controller.py,sha256=Eh4Hr9rWgq1mKvE93JzgixntjPHxF3_07GTFqiOdZqE,2123
|
|
38
38
|
ophyd_async/epics/areadetector/drivers/__init__.py,sha256=X-KdXw7YWNXpaUCXby2Spqvho2x2n72OavR-3mRlxzk,605
|
|
39
|
-
ophyd_async/epics/areadetector/drivers/ad_base.py,sha256=
|
|
39
|
+
ophyd_async/epics/areadetector/drivers/ad_base.py,sha256=AB1exQsxL_207Uz88GapYqkWblODqTumaaW2CPLYLV4,4583
|
|
40
40
|
ophyd_async/epics/areadetector/drivers/aravis_driver.py,sha256=K1if0Nv1ZNEvcOha6NVYA9t9VqsBNxKCmbajlysGF2Q,1491
|
|
41
41
|
ophyd_async/epics/areadetector/drivers/kinetix_driver.py,sha256=yIV23BkGBJ4i0VskLiLL7AFbadCCR6Ch1UwUDJ9r2YM,743
|
|
42
42
|
ophyd_async/epics/areadetector/drivers/pilatus_driver.py,sha256=0DBBuiR_FtwzVVdDW0ifdSrdKZtnprWuy87g66o8RlQ,619
|
|
43
43
|
ophyd_async/epics/areadetector/drivers/vimba_driver.py,sha256=J54VtWkOklfbSqZYxGWH1e6Uzm9_Gph_ZbCf9Zax0LU,1713
|
|
44
|
-
ophyd_async/epics/areadetector/writers/__init__.py,sha256=
|
|
45
|
-
ophyd_async/epics/areadetector/writers/
|
|
46
|
-
ophyd_async/epics/areadetector/writers/
|
|
47
|
-
ophyd_async/epics/areadetector/writers/
|
|
48
|
-
ophyd_async/epics/areadetector/writers/
|
|
49
|
-
ophyd_async/epics/areadetector/writers/nd_plugin.py,sha256=GUzaeTMdG07Rb1x0WzBBxMEltBhr10jb5dL29tEWXEQ,1547
|
|
44
|
+
ophyd_async/epics/areadetector/writers/__init__.py,sha256=bzUzlEYa3eIKWnT-uVXPiRDdxH1OAzCJCRLJJBF37QA,225
|
|
45
|
+
ophyd_async/epics/areadetector/writers/general_hdffile.py,sha256=aFS_qXC99cUVWPPxgeqgxeF89IinJhtNVQIZ3C5K-C4,2608
|
|
46
|
+
ophyd_async/epics/areadetector/writers/hdf_writer.py,sha256=GzvaXSzRSLjGktGh4ihfkB1Vpv69g8PCMN0h1RqSv08,5940
|
|
47
|
+
ophyd_async/epics/areadetector/writers/nd_file_hdf.py,sha256=fMj_rGV5PX4VlayGzWvyEkFIPM2Mj9w5MEADA3yxSrw,1983
|
|
48
|
+
ophyd_async/epics/areadetector/writers/nd_plugin.py,sha256=OR2-UFypfBW-lLTrVD1_FFbWK-tl863cOxCrH06x7FA,2393
|
|
50
49
|
ophyd_async/epics/demo/__init__.py,sha256=ZcuZ66aIQ58WSydLOSKnk-h_W-aWjhDRZkWQA6f3sig,5790
|
|
51
|
-
ophyd_async/epics/demo/demo_ad_sim_detector.py,sha256=
|
|
50
|
+
ophyd_async/epics/demo/demo_ad_sim_detector.py,sha256=x7aD2shaHBvYHP_PTSutXi9Yep8lvOMqeNHxMT7ZGY0,924
|
|
52
51
|
ophyd_async/epics/demo/mover.db,sha256=RFz0rxZue689Wh1sWTZwWeFMUrH04ttPq2u5xJH_Fp4,998
|
|
53
52
|
ophyd_async/epics/demo/sensor.db,sha256=AVtiydrdtwAz2EFurO2Ult9SSRtre3r0akOBbL98LT0,554
|
|
54
53
|
ophyd_async/epics/motion/__init__.py,sha256=tnmVRIwKa9PdN_xonJdAUD04UpEceh-hoD7XI62yDB0,46
|
|
55
|
-
ophyd_async/epics/motion/motor.py,sha256=
|
|
54
|
+
ophyd_async/epics/motion/motor.py,sha256=GrlIgyCK45nfVFw7gRccdt4qy8jXWdcbBzcp6MD3OY4,8466
|
|
56
55
|
ophyd_async/epics/pvi/__init__.py,sha256=TbOQNY4enQWgtr1T7x129vpo2p7FIFlr8cyZqqv5Lk4,158
|
|
57
56
|
ophyd_async/epics/pvi/pvi.py,sha256=Kc3klnA9F82h_p2atFYXe-wFO9OzN5TV69Tc56tD2do,12204
|
|
58
57
|
ophyd_async/epics/signal/__init__.py,sha256=JXKBSGpRL9y3auh27JRxsqDn_rBOXpJjtd4nCuDOX2g,261
|
|
59
58
|
ophyd_async/epics/signal/_epics_transport.py,sha256=DEIL0iYUAWssysVEgWGu1fHSM1l-ATV2kjUgPtDN9LY,858
|
|
60
59
|
ophyd_async/epics/signal/signal.py,sha256=M8ZVG_zLdYJfroCRX-u_w8c3yIhswSRw8e3RkW2szio,3166
|
|
61
|
-
ophyd_async/panda/__init__.py,sha256=
|
|
62
|
-
ophyd_async/panda/_common_blocks.py,sha256=
|
|
63
|
-
ophyd_async/panda/_hdf_panda.py,sha256=
|
|
60
|
+
ophyd_async/panda/__init__.py,sha256=RjEow4N-rgEPEZdlsDZElUv-VsLGRX3Awoo4Zij_mIQ,1058
|
|
61
|
+
ophyd_async/panda/_common_blocks.py,sha256=fl8rGfAAslgN7kIzQhbqQkRXVlWvKT6nqiYEE_30Ono,1601
|
|
62
|
+
ophyd_async/panda/_hdf_panda.py,sha256=TU0xa3wLd5zaf_GRBwDFjYirpHAyIRRZ-V8JxHyaLuY,1350
|
|
64
63
|
ophyd_async/panda/_panda_controller.py,sha256=dIqcjmaIHVrki8UXSoDx46kk6I2Lhpe2o3sXNg5f-RQ,1238
|
|
65
|
-
ophyd_async/panda/_table.py,sha256=
|
|
66
|
-
ophyd_async/panda/_trigger.py,sha256=
|
|
64
|
+
ophyd_async/panda/_table.py,sha256=atd9wiam0XQH89doqzn0U6J42CFQBKDs9K1_q5GcJR8,6093
|
|
65
|
+
ophyd_async/panda/_trigger.py,sha256=6G30e--M9OGV4TFpGmYOSru6sx5q4KpOJrV6aOsvVN4,3069
|
|
67
66
|
ophyd_async/panda/_utils.py,sha256=VHW5kPVISyEkmse_qQcyisBkkEwMO6GG2Ago-CH1AFA,487
|
|
68
67
|
ophyd_async/panda/writers/__init__.py,sha256=xy7BguVQG4HNIDBfKPjMj0KQo1tptC9LbCpEuMcVGaM,70
|
|
69
|
-
ophyd_async/panda/writers/_hdf_writer.py,sha256=
|
|
70
|
-
ophyd_async/panda/writers/_panda_hdf_file.py,sha256=WnGvNWuLe4KljhlmBLM4Y0HKSJCIBNWOwXxioPkGu6Y,1673
|
|
68
|
+
ophyd_async/panda/writers/_hdf_writer.py,sha256=D1cdERT_12nTN19p6sDYD7WqYYOGAmEhJsKArNFH46g,5138
|
|
71
69
|
ophyd_async/plan_stubs/__init__.py,sha256=nO9ELG9J7fYwfVTVRWVorz4kffeszYpwk1ROh6Ha--w,405
|
|
72
|
-
ophyd_async/plan_stubs/ensure_connected.py,sha256=
|
|
73
|
-
ophyd_async/plan_stubs/fly.py,sha256=
|
|
70
|
+
ophyd_async/plan_stubs/ensure_connected.py,sha256=iTisEupUXrCTFikoPw9cf-BuwO_tvOmFmbkOUlPkF-E,752
|
|
71
|
+
ophyd_async/plan_stubs/fly.py,sha256=64bJqfvxrQHBUoJeMFY8qLlkvE_8Gw8YTu3Hek_NiLA,6421
|
|
74
72
|
ophyd_async/sim/__init__.py,sha256=ScjH1g7FMo5yPACfJRZE6xGBWCHU4bKDzNQk1tqObnA,366
|
|
75
|
-
ophyd_async/sim/pattern_generator.py,sha256=
|
|
76
|
-
ophyd_async/sim/sim_pattern_detector_control.py,sha256=
|
|
77
|
-
ophyd_async/sim/sim_pattern_detector_writer.py,sha256=
|
|
78
|
-
ophyd_async/sim/sim_pattern_generator.py,sha256=
|
|
73
|
+
ophyd_async/sim/pattern_generator.py,sha256=5MOkU6JqizxQPZ4Z6kQswHsqZv-vPhsEeo8lUSvSv4Q,7369
|
|
74
|
+
ophyd_async/sim/sim_pattern_detector_control.py,sha256=azkKfPYIAfH8CoCBpkBfqlmOUTTN8GOoCEemRsL0emQ,1808
|
|
75
|
+
ophyd_async/sim/sim_pattern_detector_writer.py,sha256=yH__i1rSHAcFc3mXJPXNQElMCyyCHxpsOdTkEad33sM,1333
|
|
76
|
+
ophyd_async/sim/sim_pattern_generator.py,sha256=pQbXJ5mJQHypg4MTD2FNRs85OJRV9JksYmjl0r9NSSQ,1366
|
|
79
77
|
ophyd_async/sim/demo/__init__.py,sha256=9mxKpslrL89cfSj4g3og8Br3O--pMj3hhWZS-Xu6kyA,56
|
|
80
78
|
ophyd_async/sim/demo/sim_motor.py,sha256=a2p5wnHXjF-V5zOFai7jnszk4kbGmrZRnUqBtkOgEfQ,3733
|
|
81
|
-
ophyd_async-0.
|
|
82
|
-
ophyd_async-0.
|
|
83
|
-
ophyd_async-0.
|
|
84
|
-
ophyd_async-0.
|
|
85
|
-
ophyd_async-0.
|
|
86
|
-
ophyd_async-0.
|
|
79
|
+
ophyd_async-0.4.0.dist-info/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
|
|
80
|
+
ophyd_async-0.4.0.dist-info/METADATA,sha256=iXknBXp3IJkO7yB9_P4CRNKksn_h0m_dUKCmnFbJcLE,6491
|
|
81
|
+
ophyd_async-0.4.0.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
|
|
82
|
+
ophyd_async-0.4.0.dist-info/entry_points.txt,sha256=O0YNJTEufO0w9BozXi-JurTy2U1_o0ypeCgJLQ727Jk,58
|
|
83
|
+
ophyd_async-0.4.0.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
|
|
84
|
+
ophyd_async-0.4.0.dist-info/RECORD,,
|