ophyd-async 0.3.4a1__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. ophyd_async/_version.py +2 -2
  2. ophyd_async/core/__init__.py +86 -63
  3. ophyd_async/core/{detector.py → _detector.py} +18 -23
  4. ophyd_async/core/{device.py → _device.py} +19 -7
  5. ophyd_async/core/{device_save_loader.py → _device_save_loader.py} +3 -3
  6. ophyd_async/core/{flyer.py → _flyer.py} +6 -8
  7. ophyd_async/core/_hdf_dataset.py +97 -0
  8. ophyd_async/{log.py → core/_log.py} +11 -3
  9. ophyd_async/core/{mock_signal_backend.py → _mock_signal_backend.py} +3 -3
  10. ophyd_async/core/{mock_signal_utils.py → _mock_signal_utils.py} +3 -4
  11. ophyd_async/{protocols.py → core/_protocol.py} +1 -1
  12. ophyd_async/core/_providers.py +186 -24
  13. ophyd_async/core/{standard_readable.py → _readable.py} +6 -16
  14. ophyd_async/core/{signal.py → _signal.py} +39 -16
  15. ophyd_async/core/{signal_backend.py → _signal_backend.py} +4 -13
  16. ophyd_async/core/{soft_signal_backend.py → _soft_signal_backend.py} +24 -18
  17. ophyd_async/core/{async_status.py → _status.py} +3 -11
  18. ophyd_async/epics/adaravis/__init__.py +9 -0
  19. ophyd_async/epics/{areadetector/aravis.py → adaravis/_aravis.py} +12 -14
  20. ophyd_async/epics/{areadetector/controllers/aravis_controller.py → adaravis/_aravis_controller.py} +8 -10
  21. ophyd_async/epics/{areadetector/drivers/aravis_driver.py → adaravis/_aravis_io.py} +6 -3
  22. ophyd_async/epics/adcore/__init__.py +36 -0
  23. ophyd_async/epics/adcore/_core_io.py +114 -0
  24. ophyd_async/epics/{areadetector/drivers/ad_base.py → adcore/_core_logic.py} +17 -52
  25. ophyd_async/epics/{areadetector/writers/hdf_writer.py → adcore/_hdf_writer.py} +36 -18
  26. ophyd_async/epics/{areadetector/single_trigger_det.py → adcore/_single_trigger.py} +5 -6
  27. ophyd_async/epics/{areadetector/utils.py → adcore/_utils.py} +29 -0
  28. ophyd_async/epics/adkinetix/__init__.py +9 -0
  29. ophyd_async/epics/{areadetector/kinetix.py → adkinetix/_kinetix.py} +12 -14
  30. ophyd_async/epics/{areadetector/controllers/kinetix_controller.py → adkinetix/_kinetix_controller.py} +6 -9
  31. ophyd_async/epics/{areadetector/drivers/kinetix_driver.py → adkinetix/_kinetix_io.py} +5 -4
  32. ophyd_async/epics/adpilatus/__init__.py +11 -0
  33. ophyd_async/epics/{areadetector/pilatus.py → adpilatus/_pilatus.py} +12 -16
  34. ophyd_async/epics/{areadetector/controllers/pilatus_controller.py → adpilatus/_pilatus_controller.py} +14 -16
  35. ophyd_async/epics/{areadetector/drivers/pilatus_driver.py → adpilatus/_pilatus_io.py} +5 -3
  36. ophyd_async/epics/adsimdetector/__init__.py +7 -0
  37. ophyd_async/epics/adsimdetector/_sim.py +34 -0
  38. ophyd_async/epics/{areadetector/controllers/ad_sim_controller.py → adsimdetector/_sim_controller.py} +8 -14
  39. ophyd_async/epics/advimba/__init__.py +9 -0
  40. ophyd_async/epics/advimba/_vimba.py +43 -0
  41. ophyd_async/epics/{areadetector/controllers/vimba_controller.py → advimba/_vimba_controller.py} +6 -14
  42. ophyd_async/epics/{areadetector/drivers/vimba_driver.py → advimba/_vimba_io.py} +5 -4
  43. ophyd_async/epics/demo/__init__.py +9 -132
  44. ophyd_async/epics/demo/_mover.py +97 -0
  45. ophyd_async/epics/demo/_sensor.py +36 -0
  46. ophyd_async/epics/motor.py +228 -0
  47. ophyd_async/epics/pvi/__init__.py +2 -2
  48. ophyd_async/epics/pvi/{pvi.py → _pvi.py} +17 -14
  49. ophyd_async/epics/signal/__init__.py +7 -1
  50. ophyd_async/epics/{_backend → signal}/_aioca.py +6 -2
  51. ophyd_async/epics/{_backend/common.py → signal/_common.py} +4 -2
  52. ophyd_async/epics/signal/_epics_transport.py +3 -3
  53. ophyd_async/epics/{_backend → signal}/_p4p.py +53 -4
  54. ophyd_async/epics/signal/{signal.py → _signal.py} +10 -9
  55. ophyd_async/fastcs/odin/__init__.py +0 -0
  56. ophyd_async/{panda → fastcs/panda}/__init__.py +28 -9
  57. ophyd_async/{panda → fastcs/panda}/_common_blocks.py +24 -3
  58. ophyd_async/{panda → fastcs/panda}/_hdf_panda.py +6 -9
  59. ophyd_async/{panda/writers → fastcs/panda}/_hdf_writer.py +24 -14
  60. ophyd_async/{panda → fastcs/panda}/_panda_controller.py +2 -1
  61. ophyd_async/{panda → fastcs/panda}/_table.py +20 -18
  62. ophyd_async/fastcs/panda/_trigger.py +90 -0
  63. ophyd_async/plan_stubs/__init__.py +2 -2
  64. ophyd_async/plan_stubs/_ensure_connected.py +26 -0
  65. ophyd_async/plan_stubs/{fly.py → _fly.py} +67 -12
  66. ophyd_async/sim/__init__.py +0 -11
  67. ophyd_async/sim/demo/__init__.py +18 -2
  68. ophyd_async/sim/demo/_pattern_detector/__init__.py +13 -0
  69. ophyd_async/sim/demo/_pattern_detector/_pattern_detector.py +42 -0
  70. ophyd_async/sim/{sim_pattern_detector_control.py → demo/_pattern_detector/_pattern_detector_controller.py} +6 -7
  71. ophyd_async/sim/{sim_pattern_detector_writer.py → demo/_pattern_detector/_pattern_detector_writer.py} +12 -8
  72. ophyd_async/sim/demo/_pattern_detector/_pattern_generator.py +211 -0
  73. ophyd_async/sim/demo/{sim_motor.py → _sim_motor.py} +7 -5
  74. ophyd_async/sim/testing/__init__.py +0 -0
  75. ophyd_async/tango/__init__.py +0 -0
  76. {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.5.0.dist-info}/METADATA +7 -2
  77. ophyd_async-0.5.0.dist-info/RECORD +89 -0
  78. {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.5.0.dist-info}/WHEEL +1 -1
  79. ophyd_async/epics/areadetector/__init__.py +0 -23
  80. ophyd_async/epics/areadetector/controllers/__init__.py +0 -5
  81. ophyd_async/epics/areadetector/drivers/__init__.py +0 -23
  82. ophyd_async/epics/areadetector/vimba.py +0 -43
  83. ophyd_async/epics/areadetector/writers/__init__.py +0 -5
  84. ophyd_async/epics/areadetector/writers/_hdfdataset.py +0 -10
  85. ophyd_async/epics/areadetector/writers/_hdffile.py +0 -54
  86. ophyd_async/epics/areadetector/writers/nd_file_hdf.py +0 -40
  87. ophyd_async/epics/areadetector/writers/nd_plugin.py +0 -38
  88. ophyd_async/epics/demo/demo_ad_sim_detector.py +0 -35
  89. ophyd_async/epics/motion/__init__.py +0 -3
  90. ophyd_async/epics/motion/motor.py +0 -97
  91. ophyd_async/panda/_trigger.py +0 -39
  92. ophyd_async/panda/writers/__init__.py +0 -3
  93. ophyd_async/panda/writers/_panda_hdf_file.py +0 -54
  94. ophyd_async/plan_stubs/ensure_connected.py +0 -22
  95. ophyd_async/sim/pattern_generator.py +0 -318
  96. ophyd_async/sim/sim_pattern_generator.py +0 -35
  97. ophyd_async-0.3.4a1.dist-info/RECORD +0 -86
  98. /ophyd_async/core/{utils.py → _utils.py} +0 -0
  99. /ophyd_async/{epics/_backend → fastcs}/__init__.py +0 -0
  100. /ophyd_async/{panda → fastcs/panda}/_utils.py +0 -0
  101. {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.5.0.dist-info}/LICENSE +0 -0
  102. {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.5.0.dist-info}/entry_points.txt +0 -0
  103. {ophyd_async-0.3.4a1.dist-info → ophyd_async-0.5.0.dist-info}/top_level.txt +0 -0
@@ -1,97 +0,0 @@
1
- import asyncio
2
-
3
- from bluesky.protocols import Movable, Stoppable
4
-
5
- from ophyd_async.core import (
6
- ConfigSignal,
7
- HintedSignal,
8
- StandardReadable,
9
- WatchableAsyncStatus,
10
- )
11
- from ophyd_async.core.signal import observe_value
12
- from ophyd_async.core.utils import (
13
- DEFAULT_TIMEOUT,
14
- CalculatableTimeout,
15
- CalculateTimeout,
16
- WatcherUpdate,
17
- )
18
-
19
- from ..signal.signal import epics_signal_r, epics_signal_rw, epics_signal_x
20
-
21
-
22
- class Motor(StandardReadable, Movable, Stoppable):
23
- """Device that moves a motor record"""
24
-
25
- def __init__(self, prefix: str, name="") -> None:
26
- # Define some signals
27
- with self.add_children_as_readables(ConfigSignal):
28
- self.motor_egu = epics_signal_r(str, prefix + ".EGU")
29
- self.velocity = epics_signal_rw(float, prefix + ".VELO")
30
-
31
- with self.add_children_as_readables(HintedSignal):
32
- self.user_readback = epics_signal_r(float, prefix + ".RBV")
33
-
34
- self.user_setpoint = epics_signal_rw(float, prefix + ".VAL")
35
- self.max_velocity = epics_signal_r(float, prefix + ".VMAX")
36
- self.acceleration_time = epics_signal_rw(float, prefix + ".ACCL")
37
- self.precision = epics_signal_r(int, prefix + ".PREC")
38
- self.deadband = epics_signal_r(float, prefix + ".RDBD")
39
- self.motor_done_move = epics_signal_r(int, prefix + ".DMOV")
40
- self.low_limit_travel = epics_signal_rw(float, prefix + ".LLM")
41
- self.high_limit_travel = epics_signal_rw(float, prefix + ".HLM")
42
-
43
- self.motor_stop = epics_signal_x(prefix + ".STOP")
44
- # Whether set() should complete successfully or not
45
- self._set_success = True
46
- super().__init__(name=name)
47
-
48
- def set_name(self, name: str):
49
- super().set_name(name)
50
- # Readback should be named the same as its parent in read()
51
- self.user_readback.set_name(name)
52
-
53
- @WatchableAsyncStatus.wrap
54
- async def set(
55
- self, new_position: float, timeout: CalculatableTimeout = CalculateTimeout
56
- ):
57
- self._set_success = True
58
- (
59
- old_position,
60
- units,
61
- precision,
62
- velocity,
63
- acceleration_time,
64
- ) = await asyncio.gather(
65
- self.user_setpoint.get_value(),
66
- self.motor_egu.get_value(),
67
- self.precision.get_value(),
68
- self.velocity.get_value(),
69
- self.acceleration_time.get_value(),
70
- )
71
- if timeout is CalculateTimeout:
72
- assert velocity > 0, "Motor has zero velocity"
73
- timeout = (
74
- abs(new_position - old_position) / velocity
75
- + 2 * acceleration_time
76
- + DEFAULT_TIMEOUT
77
- )
78
- move_status = self.user_setpoint.set(new_position, wait=True, timeout=timeout)
79
- async for current_position in observe_value(
80
- self.user_readback, done_status=move_status
81
- ):
82
- yield WatcherUpdate(
83
- current=current_position,
84
- initial=old_position,
85
- target=new_position,
86
- name=self.name,
87
- unit=units,
88
- precision=precision,
89
- )
90
- if not self._set_success:
91
- raise RuntimeError("Motor was stopped")
92
-
93
- async def stop(self, success=False):
94
- self._set_success = success
95
- # Put with completion will never complete as we are waiting for completion on
96
- # the move above, so need to pass wait=False
97
- await self.motor_stop.trigger(wait=False)
@@ -1,39 +0,0 @@
1
- import asyncio
2
- from dataclasses import dataclass
3
-
4
- from ophyd_async.core import TriggerLogic, wait_for_value
5
- from ophyd_async.panda import SeqBlock, SeqTable, TimeUnits
6
-
7
-
8
- @dataclass
9
- class SeqTableInfo:
10
- sequence_table: SeqTable
11
- repeats: int
12
- prescale_as_us: float = 1 # microseconds
13
-
14
-
15
- class StaticSeqTableTriggerLogic(TriggerLogic[SeqTableInfo]):
16
- def __init__(self, seq: SeqBlock) -> None:
17
- self.seq = seq
18
-
19
- async def prepare(self, value: SeqTableInfo):
20
- await asyncio.gather(
21
- self.seq.prescale_units.set(TimeUnits.us),
22
- self.seq.enable.set("ZERO"),
23
- )
24
- await asyncio.gather(
25
- self.seq.prescale.set(value.prescale_as_us),
26
- self.seq.repeats.set(value.repeats),
27
- self.seq.table.set(value.sequence_table),
28
- )
29
-
30
- async def kickoff(self) -> None:
31
- await self.seq.enable.set("ONE")
32
- await wait_for_value(self.seq.active, True, timeout=1)
33
-
34
- async def complete(self) -> None:
35
- await wait_for_value(self.seq.active, False, timeout=None)
36
-
37
- async def stop(self):
38
- await self.seq.enable.set("ZERO")
39
- await wait_for_value(self.seq.active, False, timeout=1)
@@ -1,3 +0,0 @@
1
- from ._hdf_writer import PandaHDFWriter
2
-
3
- __all__ = ["PandaHDFWriter"]
@@ -1,54 +0,0 @@
1
- from dataclasses import dataclass
2
- from pathlib import Path
3
- from typing import Iterator, List
4
-
5
- from event_model import StreamDatum, StreamResource, compose_stream_resource
6
-
7
- from ophyd_async.core import DirectoryInfo
8
-
9
-
10
- @dataclass
11
- class _HDFDataset:
12
- data_key: str
13
- internal_path: str
14
- shape: List[int]
15
- multiplier: int
16
-
17
-
18
- class _HDFFile:
19
- def __init__(
20
- self,
21
- directory_info: DirectoryInfo,
22
- full_file_name: Path,
23
- datasets: List[_HDFDataset],
24
- ) -> None:
25
- self._last_emitted = 0
26
- self._bundles = [
27
- compose_stream_resource(
28
- spec="AD_HDF5_SWMR_SLICE",
29
- root=str(directory_info.root),
30
- data_key=ds.data_key,
31
- resource_path=(f"{str(directory_info.root)}/{full_file_name}"),
32
- resource_kwargs={
33
- "path": ds.internal_path,
34
- "multiplier": ds.multiplier,
35
- "timestamps": "/entry/instrument/NDAttributes/NDArrayTimeStamp",
36
- },
37
- )
38
- for ds in datasets
39
- ]
40
-
41
- def stream_resources(self) -> Iterator[StreamResource]:
42
- for bundle in self._bundles:
43
- yield bundle.stream_resource_doc
44
-
45
- def stream_data(self, indices_written: int) -> Iterator[StreamDatum]:
46
- # Indices are relative to resource
47
- if indices_written > self._last_emitted:
48
- indices = {
49
- "start": self._last_emitted,
50
- "stop": indices_written,
51
- }
52
- self._last_emitted = indices_written
53
- for bundle in self._bundles:
54
- yield bundle.compose_stream_datum(indices)
@@ -1,22 +0,0 @@
1
- import bluesky.plan_stubs as bps
2
-
3
- from ophyd_async.core.device import Device
4
- from ophyd_async.core.utils import DEFAULT_TIMEOUT, wait_for_connection
5
-
6
-
7
- def ensure_connected(
8
- *devices: Device,
9
- mock: bool = False,
10
- timeout: float = DEFAULT_TIMEOUT,
11
- force_reconnect=False,
12
- ):
13
- yield from bps.wait_for(
14
- [
15
- lambda: wait_for_connection(
16
- **{
17
- device.name: device.connect(mock, timeout, force_reconnect)
18
- for device in devices
19
- }
20
- )
21
- ]
22
- )
@@ -1,318 +0,0 @@
1
- from dataclasses import dataclass
2
- 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
- )
13
-
14
- import h5py
15
- import numpy as np
16
- from bluesky.protocols import DataKey, StreamAsset
17
- from event_model import (
18
- ComposeStreamResource,
19
- ComposeStreamResourceBundle,
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
28
- from ophyd_async.core.utils import DEFAULT_TIMEOUT
29
-
30
- # raw data path
31
- DATA_PATH = "/entry/data/data"
32
-
33
- # pixel sum path
34
- SUM_PATH = "/entry/sum"
35
-
36
- MAX_UINT8_VALUE = np.iinfo(np.uint8).max
37
-
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
-
68
- def generate_gaussian_blob(height: int, width: int) -> np.ndarray:
69
- """Make a Gaussian Blob with float values in range 0..1"""
70
- x, y = np.meshgrid(np.linspace(-1, 1, width), np.linspace(-1, 1, height))
71
- d = np.sqrt(x * x + y * y)
72
- blob = np.exp(-(d**2))
73
- return blob
74
-
75
-
76
- def generate_interesting_pattern(x: float, y: float) -> float:
77
- """This function is interesting in x and y in range -10..10, returning
78
- a float value in range 0..1
79
- """
80
- z = 0.5 + (np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)) / 2
81
- return z
82
-
83
-
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
- class PatternGenerator:
146
- def __init__(
147
- self,
148
- saturation_exposure_time: float = 1,
149
- detector_width: int = 320,
150
- detector_height: int = 240,
151
- ) -> None:
152
- self.saturation_exposure_time = saturation_exposure_time
153
- self.exposure = saturation_exposure_time
154
- self.x = 0.0
155
- self.y = 0.0
156
- self.height = detector_height
157
- self.width = detector_width
158
- self.written_images_counter: int = 0
159
-
160
- # it automatically initializes to 0
161
- self.signal_backend = MockSignalBackend(int)
162
- self.mock_signal = SignalR(self.signal_backend)
163
- blob = np.array(
164
- generate_gaussian_blob(width=detector_width, height=detector_height)
165
- * MAX_UINT8_VALUE
166
- )
167
- self.STARTING_BLOB = blob
168
- self._hdf_stream_provider: Optional[HdfStreamProvider] = None
169
- self._handle_for_h5_file: Optional[h5py.File] = None
170
- self.target_path: Optional[Path] = None
171
-
172
- async def write_image_to_file(self) -> None:
173
- assert self._handle_for_h5_file, "no file has been opened!"
174
- # prepare - resize the fixed hdf5 data structure
175
- # so that the new image can be written
176
- new_layer = self.written_images_counter + 1
177
- target_dimensions = (new_layer, self.height, self.width)
178
-
179
- # generate the simulated data
180
- intensity: float = generate_interesting_pattern(self.x, self.y)
181
- detector_data: np.uint8 = np.uint8(
182
- self.STARTING_BLOB
183
- * intensity
184
- * self.exposure
185
- / 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,))
195
-
196
- # write data to disc (intermediate step)
197
- self._handle_for_h5_file[DATA_PATH][self.written_images_counter] = detector_data
198
- self._handle_for_h5_file[SUM_PATH][self.written_images_counter] = np.sum(
199
- detector_data
200
- )
201
-
202
- # save metadata - so that it's discoverable
203
- self._handle_for_h5_file[DATA_PATH].flush()
204
- self._handle_for_h5_file[SUM_PATH].flush()
205
-
206
- # counter increment is last
207
- # as only at this point the new data is visible from the outside
208
- self.written_images_counter += 1
209
- await self.signal_backend.put(self.written_images_counter)
210
-
211
- def set_exposure(self, value: float) -> None:
212
- self.exposure = value
213
-
214
- def set_x(self, value: float) -> None:
215
- self.x = value
216
-
217
- def set_y(self, value: float) -> None:
218
- self.y = value
219
-
220
- async def open_file(
221
- self, directory: DirectoryProvider, multiplier: int = 1
222
- ) -> Dict[str, DataKey]:
223
- await self.mock_signal.connect()
224
-
225
- self.target_path = self._get_new_path(directory)
226
-
227
- self._handle_for_h5_file = h5py.File(self.target_path, "w", libver="latest")
228
-
229
- assert self._handle_for_h5_file, "not loaded the file right"
230
-
231
- datasets = self._get_datasets()
232
- for d in datasets:
233
- self._handle_for_h5_file.create_dataset(
234
- name=d.name,
235
- shape=d.shape,
236
- dtype=d.dtype,
237
- maxshape=d.maxshape,
238
- )
239
-
240
- # once datasets written, can switch the model to single writer multiple reader
241
- self._handle_for_h5_file.swmr_mode = True
242
-
243
- outer_shape = (multiplier,) if multiplier > 1 else ()
244
- full_file_description = get_full_file_description(datasets, outer_shape)
245
-
246
- # cache state to self
247
- self._datasets = datasets
248
- self.multiplier = multiplier
249
- self._directory_provider = directory
250
- return full_file_description
251
-
252
- def _get_new_path(self, directory: DirectoryProvider) -> Path:
253
- info = directory()
254
- filename = f"{info.prefix}pattern{info.suffix}.h5"
255
- new_path: Path = info.root / info.resource_dir / filename
256
- return new_path
257
-
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
- async def collect_stream_docs(
279
- self, indices_written: int
280
- ) -> AsyncIterator[StreamAsset]:
281
- """
282
- stream resource says "here is a dataset",
283
- stream datum says "here are N frames in that stream resource",
284
- you get one stream resource and many stream datums per scan
285
- """
286
- if self._handle_for_h5_file:
287
- self._handle_for_h5_file.flush()
288
- # when already something was written to the file
289
- if indices_written:
290
- # if no frames arrived yet, there's no file to speak of
291
- # cannot get the full filename the HDF writer will write
292
- # until the first frame comes in
293
- if not self._hdf_stream_provider:
294
- assert self.target_path, "open file has not been called"
295
- datasets = self._get_datasets()
296
- self._datasets = datasets
297
- self._hdf_stream_provider = HdfStreamProvider(
298
- self._directory_provider(),
299
- self.target_path,
300
- self._datasets,
301
- )
302
- for doc in self._hdf_stream_provider.stream_resources():
303
- yield "stream_resource", doc
304
- if self._hdf_stream_provider:
305
- for doc in self._hdf_stream_provider.stream_data(indices_written):
306
- yield "stream_datum", doc
307
-
308
- def close(self) -> None:
309
- if self._handle_for_h5_file:
310
- self._handle_for_h5_file.close()
311
- print("file closed")
312
- self._handle_for_h5_file = None
313
-
314
- async def observe_indices_written(
315
- self, timeout=DEFAULT_TIMEOUT
316
- ) -> AsyncGenerator[int, None]:
317
- async for num_captured in observe_value(self.mock_signal, timeout=timeout):
318
- yield num_captured // self.multiplier
@@ -1,35 +0,0 @@
1
- from pathlib import Path
2
- from typing import Sequence
3
-
4
- from ophyd_async.core import DirectoryProvider, StaticDirectoryProvider
5
- from ophyd_async.core.detector import StandardDetector
6
- from ophyd_async.protocols import AsyncReadable
7
- from ophyd_async.sim.pattern_generator import PatternGenerator
8
-
9
- from .sim_pattern_detector_control import SimPatternDetectorControl
10
- from .sim_pattern_detector_writer import SimPatternDetectorWriter
11
-
12
-
13
- class SimPatternDetector(StandardDetector):
14
- def __init__(
15
- self,
16
- path: Path,
17
- config_sigs: Sequence[AsyncReadable] = [],
18
- name: str = "sim_pattern_detector",
19
- ) -> None:
20
- self.directory_provider: DirectoryProvider = StaticDirectoryProvider(path)
21
- self.pattern_generator = PatternGenerator()
22
- writer = SimPatternDetectorWriter(
23
- pattern_generator=self.pattern_generator,
24
- directoryProvider=self.directory_provider,
25
- )
26
- controller = SimPatternDetectorControl(
27
- pattern_generator=self.pattern_generator,
28
- directory_provider=self.directory_provider,
29
- )
30
- super().__init__(
31
- controller=controller,
32
- writer=writer,
33
- config_sigs=config_sigs,
34
- name=name,
35
- )
@@ -1,86 +0,0 @@
1
- ophyd_async/__init__.py,sha256=v-rRiDOgZ3sQSMQKq0vgUQZvpeOkoHFXissAx6Ktg84,61
2
- ophyd_async/__main__.py,sha256=G-Zcv_G9zK7Nhx6o5L5w-wyhMxdl_WgyMELu8IMFqAE,328
3
- ophyd_async/_version.py,sha256=GeD2BgjHboEmcr7_O2gtjDoE83JU6uGSFLE7dAp8RDQ,413
4
- ophyd_async/log.py,sha256=DbMjt0bkfUOLHIinZYt0Q0FHZmCXXi5x8y0uFiEmqoQ,3587
5
- ophyd_async/protocols.py,sha256=EF2W9nfElV-0QNMYrX1zusL1PqDJR3kNsjlalR29j0I,3412
6
- ophyd_async/core/__init__.py,sha256=xqO9riU_uKqGAOi0ty0cbcI4Oawi_J3XTYLtwNSXGOE,3061
7
- ophyd_async/core/_providers.py,sha256=LrlTMPHKXWOPVkpAOw-pqBq0kip-c3C9ZZPoFfiaV4M,2212
8
- ophyd_async/core/async_status.py,sha256=9TOgOXIAuH62RDo5t-Y5GdjrJ76d_6TFlBxYv-5_a88,4367
9
- ophyd_async/core/detector.py,sha256=NMX8y_yiViHbv3CaJ7LxzXYkH6tCWI3LocpQ3w4lGEQ,11176
10
- ophyd_async/core/device.py,sha256=280zFnLCoiMZAA-Dh1_AjUSnhxUfKYGgj4H_2S1njOA,7086
11
- ophyd_async/core/device_save_loader.py,sha256=EK7FB5oWiLI_s2KZ1BNDQ2AUKVbFLlimMl0vXfsjcgo,8223
12
- ophyd_async/core/flyer.py,sha256=bIjzBkrl8HVAlKgsZ_FF0WL69Qvksyzp9ZWmTLl8Yrw,2304
13
- ophyd_async/core/mock_signal_backend.py,sha256=Ug6jK72wm9vM6EueoUrYgcXtiFzdPUEISRe86LdyYKc,2844
14
- ophyd_async/core/mock_signal_utils.py,sha256=LE8VxNq3jfaTePnHHpZpKCi1vwKi8EIg-g1jfw-Q5bQ,4726
15
- ophyd_async/core/signal.py,sha256=hPpMcdq7zx6HOkyQCJrMD5F3uLBEJJTfwL6DsbcTELo,17601
16
- ophyd_async/core/signal_backend.py,sha256=U9J6jzHXRNIrdtGiZBVxXTRtzeejXiXEEIOGRIQhiS8,2678
17
- ophyd_async/core/soft_signal_backend.py,sha256=6ve1NWuEZFW4oFkAdSfTKFg06fv7rDLgr5IAEr_axeo,6262
18
- ophyd_async/core/standard_readable.py,sha256=fhq_WAZtLYWrw6DvvrFRYRAPOUP2_IcX4qLucoEEeOg,9049
19
- ophyd_async/core/utils.py,sha256=3oZcXNqAUHX4ZWMBH5gSuK6cFWEhSkZ9GSDYv0pf8jc,5783
20
- ophyd_async/epics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- ophyd_async/epics/_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- ophyd_async/epics/_backend/_aioca.py,sha256=YsKHGaHtYjBte5Tz-AftTENaeV6UGRnonX-1UmAQGqg,11319
23
- ophyd_async/epics/_backend/_p4p.py,sha256=oCT8MeVWlhmsxZ8YRSrelrY8W3NvfpXcMlfAKL_AUNY,14331
24
- ophyd_async/epics/_backend/common.py,sha256=ffdcKhtUc8Mmm0AsV0K7cUoOttF6avcN6Kdd4QHjrSw,1833
25
- ophyd_async/epics/areadetector/__init__.py,sha256=ViKzx-wUxkRyNR33wfpL11QB97o0J47_KMyI2C_NphI,510
26
- ophyd_async/epics/areadetector/aravis.py,sha256=YklN4V0loqUQBs4swVX304N49JIGPvrNOk8iA5EWofg,2127
27
- ophyd_async/epics/areadetector/kinetix.py,sha256=7rE2MLnz9DEmeiN9pCekDfpXuZ2DErnMajRp_9eoLZY,1359
28
- ophyd_async/epics/areadetector/pilatus.py,sha256=hs3v8QUIwTHNg7i1mRSg9SbIIsoUZg90OxJ740gEKpo,2044
29
- ophyd_async/epics/areadetector/single_trigger_det.py,sha256=U92dqhioIfnve3jtCThq9gXBCdEzzqzY4ezk6rZV19g,1182
30
- ophyd_async/epics/areadetector/utils.py,sha256=p66UbVdKRFj6Sm1Qvm23kmlVyBMMqIvXFxA3x17YnSk,2824
31
- ophyd_async/epics/areadetector/vimba.py,sha256=IxG8KLzfb84iLtzf6ZoX9JikqZLP49lwkWu33bkDV9Y,1291
32
- ophyd_async/epics/areadetector/controllers/__init__.py,sha256=af58ci7X2z2s_FyUwR3IGQrws8q4TKcBw7vFyIS5FoI,217
33
- ophyd_async/epics/areadetector/controllers/ad_sim_controller.py,sha256=mthZ6WxajMEgUKptq3bnkIctbLhjzTagV66i1auB8cg,1587
34
- ophyd_async/epics/areadetector/controllers/aravis_controller.py,sha256=CIfnZdq_NobO_UMC2TJoAfUEP9GlzZg5z5bz6Dn1DxY,2669
35
- ophyd_async/epics/areadetector/controllers/kinetix_controller.py,sha256=9QmydX85QOXfQL_UX49M9EQ2b2hUZPVzLxgGQn-A9Oc,1611
36
- ophyd_async/epics/areadetector/controllers/pilatus_controller.py,sha256=6AiMz2yBA9xig-BrAIAc9CDxwM4Cjfebc4dd7QRutB0,2740
37
- ophyd_async/epics/areadetector/controllers/vimba_controller.py,sha256=Eh4Hr9rWgq1mKvE93JzgixntjPHxF3_07GTFqiOdZqE,2123
38
- ophyd_async/epics/areadetector/drivers/__init__.py,sha256=X-KdXw7YWNXpaUCXby2Spqvho2x2n72OavR-3mRlxzk,605
39
- ophyd_async/epics/areadetector/drivers/ad_base.py,sha256=OMySyCE9dcFRcVLC5Q0wUkri3QtRljIbn4KFdkumI4M,4553
40
- ophyd_async/epics/areadetector/drivers/aravis_driver.py,sha256=K1if0Nv1ZNEvcOha6NVYA9t9VqsBNxKCmbajlysGF2Q,1491
41
- ophyd_async/epics/areadetector/drivers/kinetix_driver.py,sha256=yIV23BkGBJ4i0VskLiLL7AFbadCCR6Ch1UwUDJ9r2YM,743
42
- ophyd_async/epics/areadetector/drivers/pilatus_driver.py,sha256=0DBBuiR_FtwzVVdDW0ifdSrdKZtnprWuy87g66o8RlQ,619
43
- ophyd_async/epics/areadetector/drivers/vimba_driver.py,sha256=J54VtWkOklfbSqZYxGWH1e6Uzm9_Gph_ZbCf9Zax0LU,1713
44
- ophyd_async/epics/areadetector/writers/__init__.py,sha256=tpPcrYd1hs8WS7C0gmCnR2EBwjE5RzCljI7WwZ2V_LM,191
45
- ophyd_async/epics/areadetector/writers/_hdfdataset.py,sha256=E0C9VgsPyY35h7k0mvcIhjsIVNavApLxizqNWlM388w,167
46
- ophyd_async/epics/areadetector/writers/_hdffile.py,sha256=YtUgOKX53m0TaFEGBW671qXqNuuEKxEyLV5Ein1fjvo,1799
47
- ophyd_async/epics/areadetector/writers/hdf_writer.py,sha256=ZpbVilNVv81OpbCrqaeZUoHLarrjzRWEGe-zI1Wxyyw,5436
48
- ophyd_async/epics/areadetector/writers/nd_file_hdf.py,sha256=EkiaEh_0U6Iz17jFi2IIsRPsVQTQIJRG8EPNCiAHkkU,1762
49
- ophyd_async/epics/areadetector/writers/nd_plugin.py,sha256=GUzaeTMdG07Rb1x0WzBBxMEltBhr10jb5dL29tEWXEQ,1547
50
- ophyd_async/epics/demo/__init__.py,sha256=ZcuZ66aIQ58WSydLOSKnk-h_W-aWjhDRZkWQA6f3sig,5790
51
- ophyd_async/epics/demo/demo_ad_sim_detector.py,sha256=06y65yvaqXvL2rDocjYyLz9kTVzuwV-LeuPhEfExdOA,944
52
- ophyd_async/epics/demo/mover.db,sha256=RFz0rxZue689Wh1sWTZwWeFMUrH04ttPq2u5xJH_Fp4,998
53
- ophyd_async/epics/demo/sensor.db,sha256=AVtiydrdtwAz2EFurO2Ult9SSRtre3r0akOBbL98LT0,554
54
- ophyd_async/epics/motion/__init__.py,sha256=tnmVRIwKa9PdN_xonJdAUD04UpEceh-hoD7XI62yDB0,46
55
- ophyd_async/epics/motion/motor.py,sha256=tqLV4TaW2MIapZsmx4wxnGOdKfkhxKLUPbTHA4YLdYE,3514
56
- ophyd_async/epics/pvi/__init__.py,sha256=TbOQNY4enQWgtr1T7x129vpo2p7FIFlr8cyZqqv5Lk4,158
57
- ophyd_async/epics/pvi/pvi.py,sha256=Kc3klnA9F82h_p2atFYXe-wFO9OzN5TV69Tc56tD2do,12204
58
- ophyd_async/epics/signal/__init__.py,sha256=JXKBSGpRL9y3auh27JRxsqDn_rBOXpJjtd4nCuDOX2g,261
59
- ophyd_async/epics/signal/_epics_transport.py,sha256=DEIL0iYUAWssysVEgWGu1fHSM1l-ATV2kjUgPtDN9LY,858
60
- ophyd_async/epics/signal/signal.py,sha256=M8ZVG_zLdYJfroCRX-u_w8c3yIhswSRw8e3RkW2szio,3166
61
- ophyd_async/panda/__init__.py,sha256=FuSnvp-RtdA0X4RcHEF0nTiXymRts2MNdFmF_1_i41w,775
62
- ophyd_async/panda/_common_blocks.py,sha256=OrA_mSJslxuhjIAD8Liye1-1yTl3DihqFDBXvJGlPFs,1088
63
- ophyd_async/panda/_hdf_panda.py,sha256=LWWQErG_cxM7zWqKG8c40O55ZpfTu3F70d4jVvRaeMo,1308
64
- ophyd_async/panda/_panda_controller.py,sha256=dIqcjmaIHVrki8UXSoDx46kk6I2Lhpe2o3sXNg5f-RQ,1238
65
- ophyd_async/panda/_table.py,sha256=keCGT66y91feO_MD3a6aMsgx27JuLYWLrAkl0lRXUKY,5854
66
- ophyd_async/panda/_trigger.py,sha256=tBH8uq_4o1ASG9yofVxq3tjf5v8LPzniDTRL4yjramI,1195
67
- ophyd_async/panda/_utils.py,sha256=VHW5kPVISyEkmse_qQcyisBkkEwMO6GG2Ago-CH1AFA,487
68
- ophyd_async/panda/writers/__init__.py,sha256=xy7BguVQG4HNIDBfKPjMj0KQo1tptC9LbCpEuMcVGaM,70
69
- ophyd_async/panda/writers/_hdf_writer.py,sha256=SP71y2-LTKhlNIFxLIddmtjmrg6MDwGvuwQ7X-5OP98,4698
70
- ophyd_async/panda/writers/_panda_hdf_file.py,sha256=WnGvNWuLe4KljhlmBLM4Y0HKSJCIBNWOwXxioPkGu6Y,1673
71
- ophyd_async/plan_stubs/__init__.py,sha256=nO9ELG9J7fYwfVTVRWVorz4kffeszYpwk1ROh6Ha--w,405
72
- ophyd_async/plan_stubs/ensure_connected.py,sha256=1MkDu8UqVRPHLnW9IXRn-QvKiG8-rCV8T4KDbjf9K6w,557
73
- ophyd_async/plan_stubs/fly.py,sha256=fQwBeLw57-NeBsroVxKDa8kpuu6fgTWYWimbsatCL28,4999
74
- ophyd_async/sim/__init__.py,sha256=ScjH1g7FMo5yPACfJRZE6xGBWCHU4bKDzNQk1tqObnA,366
75
- ophyd_async/sim/pattern_generator.py,sha256=pvSk2zb82D08j2jiKAMqMAfRohGnYd_rpjUraLrCD6c,10640
76
- ophyd_async/sim/sim_pattern_detector_control.py,sha256=Ypz8IuRYAY2J243IhVbNyGr_Z-XtpJZ1qxma6NR3TgM,1838
77
- ophyd_async/sim/sim_pattern_detector_writer.py,sha256=ESpcVyHd1TP7Cojznv2hJAwLinu3XbgAiVKfX12FCII,1237
78
- ophyd_async/sim/sim_pattern_generator.py,sha256=L4jTnEVUFBRXIWq_UMHqx00YDdbGO2pjo_IuuVwpzXE,1258
79
- ophyd_async/sim/demo/__init__.py,sha256=9mxKpslrL89cfSj4g3og8Br3O--pMj3hhWZS-Xu6kyA,56
80
- ophyd_async/sim/demo/sim_motor.py,sha256=a2p5wnHXjF-V5zOFai7jnszk4kbGmrZRnUqBtkOgEfQ,3733
81
- ophyd_async-0.3.4a1.dist-info/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
82
- ophyd_async-0.3.4a1.dist-info/METADATA,sha256=JNwQkJEsOunynK3sUNPtQMHoTBBf8M7kfrl7HDTJYHM,6294
83
- ophyd_async-0.3.4a1.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
84
- ophyd_async-0.3.4a1.dist-info/entry_points.txt,sha256=O0YNJTEufO0w9BozXi-JurTy2U1_o0ypeCgJLQ727Jk,58
85
- ophyd_async-0.3.4a1.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
86
- ophyd_async-0.3.4a1.dist-info/RECORD,,
File without changes
File without changes
File without changes