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.
Files changed (95) hide show
  1. ophyd_async/_version.py +2 -2
  2. ophyd_async/core/__init__.py +86 -73
  3. ophyd_async/core/{detector.py → _detector.py} +42 -36
  4. ophyd_async/core/{device.py → _device.py} +1 -1
  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/{epics/areadetector/writers/general_hdffile.py → core/_hdf_dataset.py} +4 -8
  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} +7 -7
  11. ophyd_async/{protocols.py → core/_protocol.py} +1 -1
  12. ophyd_async/core/_providers.py +24 -37
  13. ophyd_async/core/{standard_readable.py → _readable.py} +6 -16
  14. ophyd_async/core/{signal.py → _signal.py} +79 -35
  15. ophyd_async/core/{signal_backend.py → _signal_backend.py} +4 -13
  16. ophyd_async/core/{soft_signal_backend.py → _soft_signal_backend.py} +3 -12
  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} +9 -11
  20. ophyd_async/epics/{areadetector/controllers/aravis_controller.py → adaravis/_aravis_controller.py} +7 -10
  21. ophyd_async/epics/{areadetector/drivers/aravis_driver.py → adaravis/_aravis_io.py} +6 -3
  22. ophyd_async/epics/adcore/__init__.py +47 -0
  23. ophyd_async/epics/adcore/_core_io.py +138 -0
  24. ophyd_async/epics/{areadetector/drivers/ad_base.py → adcore/_core_logic.py} +16 -52
  25. ophyd_async/epics/{areadetector/writers/hdf_writer.py → adcore/_hdf_writer.py} +54 -29
  26. ophyd_async/epics/{areadetector/single_trigger_det.py → adcore/_single_trigger.py} +5 -6
  27. ophyd_async/epics/adcore/_utils.py +132 -0
  28. ophyd_async/epics/adkinetix/__init__.py +9 -0
  29. ophyd_async/epics/{areadetector/kinetix.py → adkinetix/_kinetix.py} +9 -11
  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} +9 -5
  32. ophyd_async/epics/adpilatus/__init__.py +11 -0
  33. ophyd_async/epics/{areadetector/pilatus.py → adpilatus/_pilatus.py} +10 -14
  34. ophyd_async/epics/{areadetector/controllers/pilatus_controller.py → adpilatus/_pilatus_controller.py} +15 -17
  35. ophyd_async/epics/{areadetector/drivers/pilatus_driver.py → adpilatus/_pilatus_io.py} +6 -4
  36. ophyd_async/epics/adsimdetector/__init__.py +7 -0
  37. ophyd_async/epics/{demo/demo_ad_sim_detector.py → adsimdetector/_sim.py} +10 -11
  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/{areadetector/vimba.py → advimba/_vimba.py} +9 -9
  41. ophyd_async/epics/{areadetector/controllers/vimba_controller.py → advimba/_vimba_controller.py} +9 -17
  42. ophyd_async/epics/{areadetector/drivers/vimba_driver.py → advimba/_vimba_io.py} +11 -8
  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/{motion/motor.py → motor.py} +28 -14
  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 +15 -7
  51. ophyd_async/epics/{_backend/common.py → signal/_common.py} +2 -2
  52. ophyd_async/epics/signal/_epics_transport.py +3 -3
  53. ophyd_async/epics/{_backend → signal}/_p4p.py +18 -14
  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 +20 -15
  57. ophyd_async/{panda/_common_blocks.py → fastcs/panda/_block.py} +5 -3
  58. ophyd_async/{panda/_panda_controller.py → fastcs/panda/_control.py} +2 -1
  59. ophyd_async/{panda → fastcs/panda}/_hdf_panda.py +5 -10
  60. ophyd_async/{panda → fastcs/panda}/_trigger.py +3 -7
  61. ophyd_async/{panda/writers/_hdf_writer.py → fastcs/panda/_writer.py} +36 -28
  62. ophyd_async/plan_stubs/__init__.py +5 -2
  63. ophyd_async/plan_stubs/{ensure_connected.py → _ensure_connected.py} +1 -2
  64. ophyd_async/plan_stubs/{fly.py → _fly.py} +13 -9
  65. ophyd_async/plan_stubs/_nd_attributes.py +63 -0
  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/{sim_pattern_generator.py → demo/_pattern_detector/_pattern_detector.py} +8 -8
  70. ophyd_async/sim/{sim_pattern_detector_control.py → demo/_pattern_detector/_pattern_detector_controller.py} +9 -7
  71. ophyd_async/sim/{sim_pattern_detector_writer.py → demo/_pattern_detector/_pattern_detector_writer.py} +4 -4
  72. ophyd_async/sim/{pattern_generator.py → demo/_pattern_detector/_pattern_generator.py} +13 -11
  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.4.0.dist-info → ophyd_async-0.5.1.dist-info}/METADATA +46 -44
  77. ophyd_async-0.5.1.dist-info/RECORD +90 -0
  78. {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.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/utils.py +0 -104
  83. ophyd_async/epics/areadetector/writers/__init__.py +0 -5
  84. ophyd_async/epics/areadetector/writers/nd_file_hdf.py +0 -43
  85. ophyd_async/epics/areadetector/writers/nd_plugin.py +0 -68
  86. ophyd_async/epics/motion/__init__.py +0 -3
  87. ophyd_async/panda/writers/__init__.py +0 -3
  88. ophyd_async-0.4.0.dist-info/RECORD +0 -84
  89. /ophyd_async/core/{utils.py → _utils.py} +0 -0
  90. /ophyd_async/{epics/_backend → fastcs}/__init__.py +0 -0
  91. /ophyd_async/{panda → fastcs/panda}/_table.py +0 -0
  92. /ophyd_async/{panda → fastcs/panda}/_utils.py +0 -0
  93. {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/LICENSE +0 -0
  94. {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/entry_points.txt +0 -0
  95. {ophyd_async-0.4.0.dist-info → ophyd_async-0.5.1.dist-info}/top_level.txt +0 -0
@@ -13,34 +13,24 @@ class PathInfo:
13
13
  """
14
14
  Information about where and how to write a file.
15
15
 
16
- The bluesky event model splits the URI for a resource into two segments to aid in
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
- root: Path
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
- root=self._directory_path,
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
- directory_path: Path,
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._directory_path = directory_path
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
- resource_dir = str(padded_counter)
151
+ auto_inc_dir_name = str(padded_counter)
165
152
  if self._base_name is not None:
166
- resource_dir = f"{self._base_name}{self._inc_delimeter}{padded_counter}"
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
- resource_dir = f"{device_name}{self._inc_delimeter}{padded_counter}"
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
- root=self._directory_path,
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
- directory_path: Path,
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._directory_path = Path(directory_path)
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
- resource_dir = current_date
188
+ ymd_dir_path = current_date
201
189
  elif self._device_name_as_base_dir:
202
- resource_dir = os.path.join(
190
+ ymd_dir_path = os.path.join(
203
191
  current_date,
204
192
  device_name,
205
193
  )
206
194
  else:
207
- resource_dir = os.path.join(
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
- root=self._directory_path,
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 ophyd_async.protocols import AsyncConfigurable, AsyncReadable, AsyncStageable
17
-
18
- from .async_status import AsyncStatus
19
- from .device import Device, DeviceVector
20
- from .signal import SignalR
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 ophyd_async.core.mock_signal_backend import MockSignalBackend
29
- from ophyd_async.protocols import AsyncConfigurable, AsyncReadable, AsyncStageable
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
- from .async_status import AsyncStatus
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], match: Union[T, Callable[[T], bool]], timeout: Optional[float]
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
- - Set Signal with wait=True and stash the Status
571
- - Read the same Signal to check the operation has started
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 and monitor
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
- status = signal.set(value, timeout=status_timeout)
596
- await wait_for_value(signal, value, timeout=timeout)
597
- return status
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
- TYPE_CHECKING,
4
- ClassVar,
5
- Generic,
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 .signal_backend import RuntimeSubsetEnum, SignalBackend
23
- from .utils import DEFAULT_TIMEOUT, ReadingValueCallback, T, get_dtype
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 ..protocols import Watcher
20
- from .utils import Callback, P, T, WatcherUpdate
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")
@@ -0,0 +1,9 @@
1
+ from ._aravis import AravisDetector
2
+ from ._aravis_controller import AravisController
3
+ from ._aravis_io import AravisDriverIO
4
+
5
+ __all__ = [
6
+ "AravisDetector",
7
+ "AravisController",
8
+ "AravisDriverIO",
9
+ ]
@@ -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.areadetector.controllers.aravis_controller import (
7
- AravisController,
8
- )
9
- from ophyd_async.epics.areadetector.drivers import ADBaseShapeProvider
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: HDFWriter
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 = AravisDriver(prefix + drv_suffix)
34
- self.hdf = NDFileHDF(prefix + hdf_suffix)
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
- HDFWriter(
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,
@@ -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.areadetector.drivers.aravis_driver import (
11
- AravisDriver,
12
- AravisTriggerMode,
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: AravisDriver, gpio_number: GPIO_NUMBER) -> None:
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.areadetector.drivers import ADBase
5
- from ophyd_async.epics.signal.signal import epics_signal_rw_rbv
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 AravisDriver(ADBase):
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
+ ]