ophyd-async 0.3a2__py3-none-any.whl → 0.3a4__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 (53) hide show
  1. ophyd_async/_version.py +1 -1
  2. ophyd_async/core/__init__.py +35 -11
  3. ophyd_async/core/async_status.py +2 -0
  4. ophyd_async/core/detector.py +8 -9
  5. ophyd_async/core/device.py +22 -9
  6. ophyd_async/core/flyer.py +2 -2
  7. ophyd_async/core/mock_signal_backend.py +86 -0
  8. ophyd_async/core/mock_signal_utils.py +149 -0
  9. ophyd_async/core/signal.py +140 -49
  10. ophyd_async/core/signal_backend.py +2 -2
  11. ophyd_async/core/{sim_signal_backend.py → soft_signal_backend.py} +29 -39
  12. ophyd_async/core/standard_readable.py +211 -24
  13. ophyd_async/epics/_backend/_aioca.py +17 -13
  14. ophyd_async/epics/_backend/_p4p.py +28 -18
  15. ophyd_async/epics/_backend/common.py +17 -17
  16. ophyd_async/epics/areadetector/__init__.py +4 -4
  17. ophyd_async/epics/areadetector/aravis.py +7 -9
  18. ophyd_async/epics/areadetector/controllers/__init__.py +2 -1
  19. ophyd_async/epics/areadetector/controllers/kinetix_controller.py +49 -0
  20. ophyd_async/epics/areadetector/controllers/vimba_controller.py +66 -0
  21. ophyd_async/epics/areadetector/drivers/__init__.py +6 -0
  22. ophyd_async/epics/areadetector/drivers/ad_base.py +12 -10
  23. ophyd_async/epics/areadetector/drivers/aravis_driver.py +7 -5
  24. ophyd_async/epics/areadetector/drivers/kinetix_driver.py +27 -0
  25. ophyd_async/epics/areadetector/drivers/pilatus_driver.py +5 -2
  26. ophyd_async/epics/areadetector/drivers/vimba_driver.py +63 -0
  27. ophyd_async/epics/areadetector/kinetix.py +46 -0
  28. ophyd_async/epics/areadetector/pilatus.py +7 -12
  29. ophyd_async/epics/areadetector/single_trigger_det.py +14 -6
  30. ophyd_async/epics/areadetector/utils.py +2 -12
  31. ophyd_async/epics/areadetector/vimba.py +43 -0
  32. ophyd_async/epics/areadetector/writers/hdf_writer.py +6 -3
  33. ophyd_async/epics/areadetector/writers/nd_file_hdf.py +21 -18
  34. ophyd_async/epics/areadetector/writers/nd_plugin.py +6 -7
  35. ophyd_async/epics/demo/__init__.py +19 -22
  36. ophyd_async/epics/motion/motor.py +16 -13
  37. ophyd_async/epics/pvi/pvi.py +11 -11
  38. ophyd_async/epics/signal/signal.py +1 -1
  39. ophyd_async/log.py +130 -0
  40. ophyd_async/panda/_hdf_panda.py +3 -3
  41. ophyd_async/panda/writers/_hdf_writer.py +3 -3
  42. ophyd_async/protocols.py +26 -3
  43. ophyd_async/sim/demo/sim_motor.py +14 -12
  44. ophyd_async/sim/pattern_generator.py +9 -9
  45. ophyd_async/sim/sim_pattern_detector_writer.py +2 -2
  46. ophyd_async/sim/sim_pattern_generator.py +2 -2
  47. {ophyd_async-0.3a2.dist-info → ophyd_async-0.3a4.dist-info}/METADATA +20 -3
  48. ophyd_async-0.3a4.dist-info/RECORD +85 -0
  49. ophyd_async-0.3a2.dist-info/RECORD +0 -76
  50. {ophyd_async-0.3a2.dist-info → ophyd_async-0.3a4.dist-info}/LICENSE +0 -0
  51. {ophyd_async-0.3a2.dist-info → ophyd_async-0.3a4.dist-info}/WHEEL +0 -0
  52. {ophyd_async-0.3a2.dist-info → ophyd_async-0.3a4.dist-info}/entry_points.txt +0 -0
  53. {ophyd_async-0.3a2.dist-info → ophyd_async-0.3a4.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ from typing import Callable, List, Optional
4
4
 
5
5
  from bluesky.protocols import Movable, Stoppable
6
6
 
7
- from ophyd_async.core import AsyncStatus, StandardReadable
7
+ from ophyd_async.core import AsyncStatus, ConfigSignal, HintedSignal, StandardReadable
8
8
 
9
9
  from ..signal.signal import epics_signal_r, epics_signal_rw, epics_signal_x
10
10
 
@@ -14,26 +14,25 @@ class Motor(StandardReadable, Movable, Stoppable):
14
14
 
15
15
  def __init__(self, prefix: str, name="") -> None:
16
16
  # Define some signals
17
+ with self.add_children_as_readables(ConfigSignal):
18
+ self.motor_egu = epics_signal_r(str, prefix + ".EGU")
19
+ self.velocity = epics_signal_rw(float, prefix + ".VELO")
20
+
21
+ with self.add_children_as_readables(HintedSignal):
22
+ self.user_readback = epics_signal_r(float, prefix + ".RBV")
23
+
17
24
  self.user_setpoint = epics_signal_rw(float, prefix + ".VAL")
18
- self.user_readback = epics_signal_r(float, prefix + ".RBV")
19
- self.velocity = epics_signal_rw(float, prefix + ".VELO")
20
25
  self.max_velocity = epics_signal_r(float, prefix + ".VMAX")
21
26
  self.acceleration_time = epics_signal_rw(float, prefix + ".ACCL")
22
- self.motor_egu = epics_signal_r(str, prefix + ".EGU")
23
27
  self.precision = epics_signal_r(int, prefix + ".PREC")
24
28
  self.deadband = epics_signal_r(float, prefix + ".RDBD")
25
- self.motor_done_move = epics_signal_r(float, prefix + ".DMOV")
26
- self.low_limit_travel = epics_signal_rw(int, prefix + ".LLM")
27
- self.high_limit_travel = epics_signal_rw(int, prefix + ".HLM")
29
+ self.motor_done_move = epics_signal_r(int, prefix + ".DMOV")
30
+ self.low_limit_travel = epics_signal_rw(float, prefix + ".LLM")
31
+ self.high_limit_travel = epics_signal_rw(float, prefix + ".HLM")
28
32
 
29
33
  self.motor_stop = epics_signal_x(prefix + ".STOP")
30
34
  # Whether set() should complete successfully or not
31
35
  self._set_success = True
32
- # Set name and signals for read() and read_configuration()
33
- self.set_readable_signals(
34
- read=[self.user_readback],
35
- config=[self.velocity, self.motor_egu],
36
- )
37
36
  super().__init__(name=name)
38
37
 
39
38
  def set_name(self, name: str):
@@ -41,7 +40,11 @@ class Motor(StandardReadable, Movable, Stoppable):
41
40
  # Readback should be named the same as its parent in read()
42
41
  self.user_readback.set_name(name)
43
42
 
44
- async def _move(self, new_position: float, watchers: List[Callable] = []):
43
+ async def _move(
44
+ self, new_position: float, watchers: Optional[List[Callable]] = None
45
+ ):
46
+ if watchers is None:
47
+ watchers = []
45
48
  self._set_success = True
46
49
  start = time.monotonic()
47
50
  old_position, units, precision = await asyncio.gather(
@@ -17,7 +17,7 @@ from typing import (
17
17
  get_type_hints,
18
18
  )
19
19
 
20
- from ophyd_async.core import Device, DeviceVector, SimSignalBackend
20
+ from ophyd_async.core import Device, DeviceVector, SoftSignalBackend
21
21
  from ophyd_async.core.signal import Signal
22
22
  from ophyd_async.core.utils import DEFAULT_TIMEOUT
23
23
  from ophyd_async.epics._backend._p4p import PvaSignalBackend
@@ -156,7 +156,7 @@ def _parse_type(
156
156
  return is_device_vector, is_signal, signal_dtype, device_cls
157
157
 
158
158
 
159
- def _sim_common_blocks(device: Device, stripped_type: Optional[Type] = None):
159
+ def _mock_common_blocks(device: Device, stripped_type: Optional[Type] = None):
160
160
  device_t = stripped_type or type(device)
161
161
  sub_devices = (
162
162
  (field, field_type)
@@ -175,23 +175,23 @@ def _sim_common_blocks(device: Device, stripped_type: Optional[Type] = None):
175
175
 
176
176
  if is_device_vector:
177
177
  if is_signal:
178
- sub_device_1 = device_cls(SimSignalBackend(signal_dtype))
179
- sub_device_2 = device_cls(SimSignalBackend(signal_dtype))
178
+ sub_device_1 = device_cls(SoftSignalBackend(signal_dtype))
179
+ sub_device_2 = device_cls(SoftSignalBackend(signal_dtype))
180
180
  sub_device = DeviceVector({1: sub_device_1, 2: sub_device_2})
181
181
  else:
182
182
  sub_device = DeviceVector({1: device_cls(), 2: device_cls()})
183
183
 
184
184
  for sub_device_in_vector in sub_device.values():
185
- _sim_common_blocks(sub_device_in_vector, stripped_type=device_cls)
185
+ _mock_common_blocks(sub_device_in_vector, stripped_type=device_cls)
186
186
 
187
187
  for value in sub_device.values():
188
188
  value.parent = sub_device
189
189
  else:
190
190
  if is_signal:
191
- sub_device = device_cls(SimSignalBackend(signal_dtype))
191
+ sub_device = device_cls(SoftSignalBackend(signal_dtype))
192
192
  else:
193
193
  sub_device = getattr(device, device_name, device_cls())
194
- _sim_common_blocks(sub_device, stripped_type=device_cls)
194
+ _mock_common_blocks(sub_device, stripped_type=device_cls)
195
195
 
196
196
  setattr(device, device_name, sub_device)
197
197
  sub_device.parent = device
@@ -269,16 +269,16 @@ def _set_device_attributes(entry: PVIEntry):
269
269
 
270
270
 
271
271
  async def fill_pvi_entries(
272
- device: Device, root_pv: str, timeout=DEFAULT_TIMEOUT, sim=False
272
+ device: Device, root_pv: str, timeout=DEFAULT_TIMEOUT, mock=False
273
273
  ):
274
274
  """
275
275
  Fills a ``device`` with signals from a the ``root_pvi:PVI`` table.
276
276
 
277
277
  If the device names match with parent devices of ``device`` then types are used.
278
278
  """
279
- if sim:
280
- # set up sim signals for the common annotations
281
- _sim_common_blocks(device)
279
+ if mock:
280
+ # set up mock signals for the common annotations
281
+ _mock_common_blocks(device)
282
282
  else:
283
283
  # check the pvi table for devices and fill the device with them
284
284
  root_entry = PVIEntry(
@@ -79,7 +79,7 @@ def epics_signal_r(datatype: Type[T], read_pv: str, name: str = "") -> SignalR[T
79
79
  """Create a `SignalR` backed by 1 EPICS PV
80
80
 
81
81
  Parameters
82
- ---------
82
+ ----------
83
83
  datatype
84
84
  Check that the PV is of this type
85
85
  read_pv:
ophyd_async/log.py ADDED
@@ -0,0 +1,130 @@
1
+ import logging
2
+ import sys
3
+
4
+ import colorlog
5
+
6
+ __all__ = (
7
+ "config_ophyd_async_logging",
8
+ "logger",
9
+ "set_handler",
10
+ )
11
+
12
+ DEFAULT_FORMAT = (
13
+ "%(log_color)s[%(levelname)1.1s %(asctime)s.%(msecs)03d "
14
+ "%(module)s:%(lineno)d] %(message)s"
15
+ )
16
+
17
+ DEFAULT_DATE_FORMAT = "%y%m%d %H:%M:%S"
18
+
19
+ DEFAULT_LOG_COLORS = {
20
+ "DEBUG": "cyan",
21
+ "INFO": "green",
22
+ "WARNING": "yellow",
23
+ "ERROR": "red",
24
+ "CRITICAL": "red,bg_white",
25
+ }
26
+
27
+
28
+ class ColoredFormatterWithDeviceName(colorlog.ColoredFormatter):
29
+ def format(self, record):
30
+ message = super().format(record)
31
+ if hasattr(record, "ophyd_async_device_name"):
32
+ message = f"[{record.ophyd_async_device_name}]{message}"
33
+ return message
34
+
35
+
36
+ def _validate_level(level) -> int:
37
+ """
38
+ Return an int for level comparison
39
+ """
40
+ if isinstance(level, int):
41
+ levelno = level
42
+ elif isinstance(level, str):
43
+ levelno = logging.getLevelName(level)
44
+
45
+ if isinstance(levelno, int):
46
+ return levelno
47
+ else:
48
+ raise ValueError(
49
+ "Your level is illegal, please use "
50
+ "'CRITICAL', 'FATAL', 'ERROR', 'WARNING', 'INFO', or 'DEBUG'."
51
+ )
52
+
53
+
54
+ logger = logging.getLogger("ophyd_async")
55
+
56
+ current_handler = None # overwritten below
57
+
58
+
59
+ def config_ophyd_async_logging(
60
+ file=sys.stdout,
61
+ fmt=DEFAULT_FORMAT,
62
+ datefmt=DEFAULT_DATE_FORMAT,
63
+ color=True,
64
+ level="WARNING",
65
+ ):
66
+ """
67
+ Set a new handler on the ``logging.getLogger('ophyd_async')`` logger.
68
+ If this is called more than once, the handler from the previous invocation
69
+ is removed (if still present) and replaced.
70
+
71
+ Parameters
72
+ ----------
73
+ file : object with ``write`` method or filename string
74
+ Default is ``sys.stdout``.
75
+ fmt : Overall logging format
76
+ datefmt : string
77
+ Date format. Default is ``'%H:%M:%S'``.
78
+ color : boolean
79
+ Use ANSI color codes. True by default.
80
+ level : str or int
81
+ Python logging level, given as string or corresponding integer.
82
+ Default is 'WARNING'.
83
+ Returns
84
+ -------
85
+ handler : logging.Handler
86
+ The handler, which has already been added to the 'ophyd_async' logger.
87
+ Examples
88
+ --------
89
+ Log to a file.
90
+ config_ophyd_async_logging(file='/tmp/what_is_happening.txt')
91
+ Include the date along with the time. (The log messages will always include
92
+ microseconds, which are configured separately, not as part of 'datefmt'.)
93
+ config_ophyd_async_logging(datefmt="%Y-%m-%d %H:%M:%S")
94
+ Turn off ANSI color codes.
95
+ config_ophyd_async_logging(color=False)
96
+ Increase verbosity: show level DEBUG or higher.
97
+ config_ophyd_async_logging(level='DEBUG')
98
+ """
99
+ global current_handler
100
+
101
+ if isinstance(file, str):
102
+ handler = logging.FileHandler(file)
103
+ formatter = ColoredFormatterWithDeviceName(
104
+ fmt=fmt, datefmt=datefmt, no_color=True
105
+ )
106
+ else:
107
+ handler = colorlog.StreamHandler(file)
108
+ formatter = ColoredFormatterWithDeviceName(
109
+ fmt=fmt, datefmt=datefmt, log_colors=DEFAULT_LOG_COLORS, no_color=color
110
+ )
111
+
112
+ levelno = _validate_level(level)
113
+ handler.setFormatter(formatter)
114
+ handler.setLevel(levelno)
115
+
116
+ if current_handler in logger.handlers:
117
+ logger.removeHandler(current_handler)
118
+ logger.addHandler(handler)
119
+
120
+ current_handler = handler
121
+
122
+ if logger.getEffectiveLevel() > levelno:
123
+ logger.setLevel(levelno)
124
+ try:
125
+ return handler
126
+ finally:
127
+ handler.close()
128
+
129
+
130
+ set_handler = config_ophyd_async_logging # for back-compat
@@ -42,7 +42,7 @@ class HDFPanda(CommonPandaBlocks, StandardDetector):
42
42
  )
43
43
 
44
44
  async def connect(
45
- self, sim: bool = False, timeout: float = DEFAULT_TIMEOUT
45
+ self, mock: bool = False, timeout: float = DEFAULT_TIMEOUT
46
46
  ) -> None:
47
- await fill_pvi_entries(self, self._prefix + "PVI", timeout=timeout, sim=sim)
48
- await super().connect(sim=sim, timeout=timeout)
47
+ await fill_pvi_entries(self, self._prefix + "PVI", timeout=timeout, mock=mock)
48
+ await super().connect(mock=mock, timeout=timeout)
@@ -4,7 +4,7 @@ from enum import Enum
4
4
  from pathlib import Path
5
5
  from typing import Any, AsyncGenerator, AsyncIterator, Dict, List, Optional
6
6
 
7
- from bluesky.protocols import Descriptor, StreamAsset
7
+ from bluesky.protocols import DataKey, StreamAsset
8
8
  from p4p.client.thread import Context
9
9
 
10
10
  from ophyd_async.core import (
@@ -107,7 +107,7 @@ class PandaHDFWriter(DetectorWriter):
107
107
  self._multiplier = 1
108
108
 
109
109
  # Triggered on PCAP arm
110
- async def open(self, multiplier: int = 1) -> Dict[str, Descriptor]:
110
+ async def open(self, multiplier: int = 1) -> Dict[str, DataKey]:
111
111
  """Retrieve and get descriptor of all PandA signals marked for capture"""
112
112
 
113
113
  # Get capture PVs by looking at panda. Gives mapping of dotted attribute path
@@ -162,7 +162,7 @@ class PandaHDFWriter(DetectorWriter):
162
162
  )
163
163
 
164
164
  describe = {
165
- ds.name: Descriptor(
165
+ ds.name: DataKey(
166
166
  source=self.panda_device.data.hdf_directory.source,
167
167
  shape=ds.shape,
168
168
  dtype="array" if ds.shape != [1] else "number",
ophyd_async/protocols.py CHANGED
@@ -1,7 +1,9 @@
1
1
  from abc import abstractmethod
2
2
  from typing import Dict, Protocol, runtime_checkable
3
3
 
4
- from bluesky.protocols import Descriptor, HasName, Reading
4
+ from bluesky.protocols import DataKey, HasName, Reading
5
+
6
+ from ophyd_async.core.async_status import AsyncStatus
5
7
 
6
8
 
7
9
  @runtime_checkable
@@ -23,7 +25,7 @@ class AsyncReadable(HasName, Protocol):
23
25
  ...
24
26
 
25
27
  @abstractmethod
26
- async def describe(self) -> Dict[str, Descriptor]:
28
+ async def describe(self) -> Dict[str, DataKey]:
27
29
  """Return an OrderedDict with exactly the same keys as the ``read``
28
30
  method, here mapped to per-scan metadata about each field.
29
31
 
@@ -53,7 +55,7 @@ class AsyncConfigurable(Protocol):
53
55
  ...
54
56
 
55
57
  @abstractmethod
56
- async def describe_configuration(self) -> Dict[str, Descriptor]:
58
+ async def describe_configuration(self) -> Dict[str, DataKey]:
57
59
  """Same API as ``describe``, but corresponding to the keys in
58
60
  ``read_configuration``.
59
61
  """
@@ -71,3 +73,24 @@ class AsyncPausable(Protocol):
71
73
  async def resume(self) -> None:
72
74
  """Perform device-specific work when the RunEngine resumes after a pause."""
73
75
  ...
76
+
77
+
78
+ @runtime_checkable
79
+ class AsyncStageable(Protocol):
80
+ @abstractmethod
81
+ def stage(self) -> AsyncStatus:
82
+ """An optional hook for "setting up" the device for acquisition.
83
+
84
+ It should return a ``Status`` that is marked done when the device is
85
+ done staging.
86
+ """
87
+ ...
88
+
89
+ @abstractmethod
90
+ def unstage(self) -> AsyncStatus:
91
+ """A hook for "cleaning up" the device after acquisition.
92
+
93
+ It should return a ``Status`` that is marked done when the device is finished
94
+ unstaging.
95
+ """
96
+ ...
@@ -6,7 +6,8 @@ from bluesky.protocols import Movable, Stoppable
6
6
 
7
7
  from ophyd_async.core import StandardReadable
8
8
  from ophyd_async.core.async_status import AsyncStatus
9
- from ophyd_async.core.signal import soft_signal_r_and_backend, soft_signal_rw
9
+ from ophyd_async.core.signal import soft_signal_r_and_setter, soft_signal_rw
10
+ from ophyd_async.core.standard_readable import ConfigSignal, HintedSignal
10
11
 
11
12
 
12
13
  class SimMotor(StandardReadable, Movable, Stoppable):
@@ -19,20 +20,21 @@ class SimMotor(StandardReadable, Movable, Stoppable):
19
20
  - name: str: name of device
20
21
  - instant: bool: whether to move instantly, or with a delay
21
22
  """
23
+ with self.add_children_as_readables(HintedSignal):
24
+ self.user_readback, self._user_readback_set = soft_signal_r_and_setter(
25
+ float, 0
26
+ )
27
+
28
+ with self.add_children_as_readables(ConfigSignal):
29
+ self.velocity = soft_signal_rw(float, 1.0)
30
+ self.egu = soft_signal_rw(float, "mm")
31
+
22
32
  self._instant = instant
23
33
  self._move_task: Optional[asyncio.Task] = None
24
34
 
25
35
  # Define some signals
26
36
  self.user_setpoint = soft_signal_rw(float, 0)
27
- self.user_readback, self._user_readback = soft_signal_r_and_backend(float, 0)
28
- self.velocity = soft_signal_rw(float, 1.0)
29
- self.egu = soft_signal_rw(float, "mm")
30
-
31
- # Set name and signals for read() and read_configuration()
32
- self.set_readable_signals(
33
- read=[self.user_readback],
34
- config=[self.velocity, self.egu],
35
- )
37
+
36
38
  super().__init__(name=name)
37
39
 
38
40
  # Whether set() should complete successfully or not
@@ -82,7 +84,7 @@ class SimMotor(StandardReadable, Movable, Stoppable):
82
84
  # update position based on time elapsed
83
85
  if time_elapsed >= travel_time:
84
86
  # successfully reached our target position
85
- await self._user_readback.put(new_position)
87
+ self._user_readback_set(new_position)
86
88
  self._set_success = True
87
89
  break
88
90
  else:
@@ -90,7 +92,7 @@ class SimMotor(StandardReadable, Movable, Stoppable):
90
92
  old_position + distance * time_elapsed / travel_time
91
93
  )
92
94
 
93
- await self._user_readback.put(current_position)
95
+ self._user_readback_set(current_position)
94
96
 
95
97
  # notify watchers of the new position
96
98
  for watcher in watchers:
@@ -13,7 +13,7 @@ from typing import (
13
13
 
14
14
  import h5py
15
15
  import numpy as np
16
- from bluesky.protocols import Descriptor, StreamAsset
16
+ from bluesky.protocols import DataKey, StreamAsset
17
17
  from event_model import (
18
18
  ComposeStreamResource,
19
19
  ComposeStreamResourceBundle,
@@ -23,8 +23,8 @@ from event_model import (
23
23
  )
24
24
 
25
25
  from ophyd_async.core import DirectoryInfo, DirectoryProvider
26
+ from ophyd_async.core.mock_signal_backend import MockSignalBackend
26
27
  from ophyd_async.core.signal import SignalR, observe_value
27
- from ophyd_async.core.sim_signal_backend import SimSignalBackend
28
28
  from ophyd_async.core.utils import DEFAULT_TIMEOUT
29
29
 
30
30
  # raw data path
@@ -52,12 +52,12 @@ class DatasetConfig:
52
52
  def get_full_file_description(
53
53
  datasets: List[DatasetConfig], outer_shape: tuple[int, ...]
54
54
  ):
55
- full_file_description: Dict[str, Descriptor] = {}
55
+ full_file_description: Dict[str, DataKey] = {}
56
56
  for d in datasets:
57
57
  source = f"soft://{d.name}"
58
58
  shape = outer_shape + tuple(d.shape)
59
59
  dtype = "number" if d.shape == [1] else "array"
60
- descriptor = Descriptor(
60
+ descriptor = DataKey(
61
61
  source=source, shape=shape, dtype=dtype, external="STREAM:"
62
62
  )
63
63
  key = d.name.replace("/", "_")
@@ -158,8 +158,8 @@ class PatternGenerator:
158
158
  self.written_images_counter: int = 0
159
159
 
160
160
  # it automatically initializes to 0
161
- self.signal_backend = SimSignalBackend(int)
162
- self.sim_signal = SignalR(self.signal_backend)
161
+ self.signal_backend = MockSignalBackend(int)
162
+ self.mock_signal = SignalR(self.signal_backend)
163
163
  blob = np.array(
164
164
  generate_gaussian_blob(width=detector_width, height=detector_height)
165
165
  * MAX_UINT8_VALUE
@@ -219,8 +219,8 @@ class PatternGenerator:
219
219
 
220
220
  async def open_file(
221
221
  self, directory: DirectoryProvider, multiplier: int = 1
222
- ) -> Dict[str, Descriptor]:
223
- await self.sim_signal.connect()
222
+ ) -> Dict[str, DataKey]:
223
+ await self.mock_signal.connect()
224
224
 
225
225
  self.target_path = self._get_new_path(directory)
226
226
 
@@ -314,5 +314,5 @@ class PatternGenerator:
314
314
  async def observe_indices_written(
315
315
  self, timeout=DEFAULT_TIMEOUT
316
316
  ) -> AsyncGenerator[int, None]:
317
- async for num_captured in observe_value(self.sim_signal, timeout=timeout):
317
+ async for num_captured in observe_value(self.mock_signal, timeout=timeout):
318
318
  yield num_captured // self.multiplier
@@ -1,6 +1,6 @@
1
1
  from typing import AsyncGenerator, AsyncIterator, Dict
2
2
 
3
- from bluesky.protocols import Descriptor
3
+ from bluesky.protocols import DataKey
4
4
 
5
5
  from ophyd_async.core import DirectoryProvider
6
6
  from ophyd_async.core.detector import DetectorWriter
@@ -16,7 +16,7 @@ class SimPatternDetectorWriter(DetectorWriter):
16
16
  self.pattern_generator = pattern_generator
17
17
  self.directory_provider = directoryProvider
18
18
 
19
- async def open(self, multiplier: int = 1) -> Dict[str, Descriptor]:
19
+ async def open(self, multiplier: int = 1) -> Dict[str, DataKey]:
20
20
  return await self.pattern_generator.open_file(
21
21
  self.directory_provider, multiplier
22
22
  )
@@ -3,7 +3,7 @@ from typing import Sequence
3
3
 
4
4
  from ophyd_async.core import DirectoryProvider, StaticDirectoryProvider
5
5
  from ophyd_async.core.detector import StandardDetector
6
- from ophyd_async.core.signal import SignalR
6
+ from ophyd_async.protocols import AsyncReadable
7
7
  from ophyd_async.sim.pattern_generator import PatternGenerator
8
8
 
9
9
  from .sim_pattern_detector_control import SimPatternDetectorControl
@@ -14,7 +14,7 @@ class SimPatternDetector(StandardDetector):
14
14
  def __init__(
15
15
  self,
16
16
  path: Path,
17
- config_sigs: Sequence[SignalR] = [],
17
+ config_sigs: Sequence[AsyncReadable] = [],
18
18
  name: str = "sim_pattern_detector",
19
19
  writer_timeout: float = 1,
20
20
  ) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ophyd-async
3
- Version: 0.3a2
3
+ Version: 0.3a4
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
@@ -48,6 +48,7 @@ Requires-Dist: bluesky >=1.13.0a3
48
48
  Requires-Dist: event-model <1.21.0
49
49
  Requires-Dist: p4p
50
50
  Requires-Dist: pyyaml
51
+ Requires-Dist: colorlog
51
52
  Provides-Extra: ca
52
53
  Requires-Dist: aioca >=1.6 ; extra == 'ca'
53
54
  Provides-Extra: dev
@@ -70,7 +71,7 @@ Requires-Dist: pipdeptree ; extra == 'dev'
70
71
  Requires-Dist: pre-commit ; extra == 'dev'
71
72
  Requires-Dist: pydata-sphinx-theme >=0.12 ; extra == 'dev'
72
73
  Requires-Dist: pyepics >=3.4.2 ; extra == 'dev'
73
- Requires-Dist: pyside6 ==6.6.2 ; extra == 'dev'
74
+ Requires-Dist: pyside6 ==6.7.0 ; extra == 'dev'
74
75
  Requires-Dist: pytest ; extra == 'dev'
75
76
  Requires-Dist: pytest-asyncio ; extra == 'dev'
76
77
  Requires-Dist: pytest-cov ; extra == 'dev'
@@ -79,6 +80,7 @@ Requires-Dist: pytest-rerunfailures ; extra == 'dev'
79
80
  Requires-Dist: pytest-timeout ; extra == 'dev'
80
81
  Requires-Dist: ruff ; extra == 'dev'
81
82
  Requires-Dist: sphinx-autobuild ; extra == 'dev'
83
+ Requires-Dist: sphinxcontrib-mermaid ; extra == 'dev'
82
84
  Requires-Dist: sphinx-copybutton ; extra == 'dev'
83
85
  Requires-Dist: sphinx-design ; extra == 'dev'
84
86
  Requires-Dist: tox-direct ; extra == 'dev'
@@ -92,7 +94,7 @@ Requires-Dist: p4p ; extra == 'pva'
92
94
  [![PyPI](https://img.shields.io/pypi/v/ophyd-async.svg)](https://pypi.org/project/ophyd-async)
93
95
  [![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
94
96
 
95
- # ophyd_async
97
+ # ophyd-async
96
98
 
97
99
  Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
98
100
 
@@ -102,6 +104,21 @@ Asynchronous Bluesky hardware abstraction code, compatible with control systems
102
104
  | Documentation | <https://bluesky.github.io/ophyd-async> |
103
105
  | Releases | <https://github.com/bluesky/ophyd-async/releases> |
104
106
 
107
+ Ophyd-async is a Python library for asynchronously interfacing with hardware, intended to
108
+ be used as an abstraction layer that enables experiment orchestration and data acquisition code to operate above the specifics of particular devices and control
109
+ systems.
110
+
111
+ Both ophyd and ophyd-async are typically used with the [Bluesky Run Engine][] for experiment orchestration and data acquisition.
112
+
113
+ While [EPICS][] is the most common control system layer that ophyd-async can interface with, support for other control systems like [Tango][] will be supported in the future. The focus of ophyd-async is:
114
+
115
+ * Asynchronous signal access, opening the possibility for hardware-triggered scanning (also known as fly-scanning)
116
+ * Simpler instantiation of devices (groupings of signals) with less reliance upon complex class hierarchies
117
+
118
+ [Bluesky Run Engine]: http://blueskyproject.io/bluesky
119
+ [EPICS]: http://www.aps.anl.gov/epics/
120
+ [Tango]: https://www.tango-controls.org/
121
+
105
122
  <!-- README only content. Anything below this line won't be included in index.md -->
106
123
 
107
124
  See https://bluesky.github.io/ophyd-async for more detailed documentation.
@@ -0,0 +1,85 @@
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=KnUL22nu-ueGx6I5b6OJXJXe49pxXyZLEJ7g8y71WnM,408
4
+ ophyd_async/log.py,sha256=DbMjt0bkfUOLHIinZYt0Q0FHZmCXXi5x8y0uFiEmqoQ,3587
5
+ ophyd_async/protocols.py,sha256=48jqS78KAMvy6LmenL21ARoTAD8oOL9YdVmIlI0E0VA,2890
6
+ ophyd_async/core/__init__.py,sha256=h1jha-uq0_QfQx2ZD8wit5a58doHfNebyK1mxHMKTUI,2843
7
+ ophyd_async/core/_providers.py,sha256=LrlTMPHKXWOPVkpAOw-pqBq0kip-c3C9ZZPoFfiaV4M,2212
8
+ ophyd_async/core/async_status.py,sha256=7cf5vfOaP6qZ8GW7sl--IZOi8CaLfPM5ULa8H1K3aeA,2803
9
+ ophyd_async/core/detector.py,sha256=OkdaaJnj2v8DKF4k7VsTo8ReAvIzyFjBqbqdiYf7FBE,11179
10
+ ophyd_async/core/device.py,sha256=xoxz0Iz4vovOWwpUzecDFLtLyJb_aLVi2EBnwxMyeMQ,6209
11
+ ophyd_async/core/device_save_loader.py,sha256=RXA3dPUPihAR2ZGDStlGiA-TAsr_xqL0snsCjMsMnfA,9138
12
+ ophyd_async/core/flyer.py,sha256=LfO3EQTW2zMeNqZh8TLXvE92E30Duds2RXskRYAdJ_4,2299
13
+ ophyd_async/core/mock_signal_backend.py,sha256=MZQr1oGv2ssnAK9WxItthiZogCh8rw4BL2N4YoHCgww,3041
14
+ ophyd_async/core/mock_signal_utils.py,sha256=weaH1PnjyzIxo2FmhLwx4o5i-X71srvvvsHsN3C4XqY,4267
15
+ ophyd_async/core/signal.py,sha256=zjfS_QuPNx9bm8K4tpZYrxqba5A1CHAlRPYg1kokrAQ,14674
16
+ ophyd_async/core/signal_backend.py,sha256=qDdWz8X4CWStuYknxcj4G76BLq4TzrAIyZO1NOEq9ao,1519
17
+ ophyd_async/core/soft_signal_backend.py,sha256=56zvcEi4c8n1yYbafTbp7X0VhSkhoehm3L8RBhu2fik,5596
18
+ ophyd_async/core/standard_readable.py,sha256=uVG3vs3s7-Kzg5dRCtT4I2mhZPqwVGYy2dxNmaOpDVU,8980
19
+ ophyd_async/core/utils.py,sha256=AVF5e42CVG_GaLoHJSI82iC4KAO60fb9fEJMISHBCNM,5043
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=cpPNZmRMi7FnAh2-3ec5uklLVFOqsmEmpI1nh5Ud1Ls,8794
23
+ ophyd_async/epics/_backend/_p4p.py,sha256=lIKx7kQ2o8h3M4wPwrq8JBo8xuDnasJxpDH2ATVBY78,12257
24
+ ophyd_async/epics/_backend/common.py,sha256=16mAuxDwA3eZFjUW8DHMabaW3CtEI0Qe8DLpP2xlW7Y,814
25
+ ophyd_async/epics/areadetector/__init__.py,sha256=ViKzx-wUxkRyNR33wfpL11QB97o0J47_KMyI2C_NphI,510
26
+ ophyd_async/epics/areadetector/aravis.py,sha256=ujO82hYZ5D5GIaBhz0JNC2G5uVSgowY8xxsY2tunzi4,2277
27
+ ophyd_async/epics/areadetector/kinetix.py,sha256=7rE2MLnz9DEmeiN9pCekDfpXuZ2DErnMajRp_9eoLZY,1359
28
+ ophyd_async/epics/areadetector/pilatus.py,sha256=ki-BOBCEIiUD2wAtmujBIB1eX-nbXB4yMLJK_Q3opRM,1398
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=vRiSexnFzijG8eEwowMAFIe730xFNMmgjjbXQVi4zrc,2394
35
+ ophyd_async/epics/areadetector/controllers/kinetix_controller.py,sha256=9QmydX85QOXfQL_UX49M9EQ2b2hUZPVzLxgGQn-A9Oc,1611
36
+ ophyd_async/epics/areadetector/controllers/pilatus_controller.py,sha256=cd1CKkaXlwkpQ0I1VL7nN0U8R4VweTsa08WhvHYI4nY,2243
37
+ ophyd_async/epics/areadetector/controllers/vimba_controller.py,sha256=Eh4Hr9rWgq1mKvE93JzgixntjPHxF3_07GTFqiOdZqE,2123
38
+ ophyd_async/epics/areadetector/drivers/__init__.py,sha256=-Ib0Lz4fFQQmB7K0uFxMDvAerkLxadMQERH7lNAvrs4,495
39
+ ophyd_async/epics/areadetector/drivers/ad_base.py,sha256=cE7I-IsfQz3UR9yqghy4czAxHeHERTTKe080GB9sCFQ,3847
40
+ ophyd_async/epics/areadetector/drivers/aravis_driver.py,sha256=2KbfcsAN2lYXWDc773KS0tE37Fw5gs7IATbDBOyLD-8,5704
41
+ ophyd_async/epics/areadetector/drivers/kinetix_driver.py,sha256=yIV23BkGBJ4i0VskLiLL7AFbadCCR6Ch1UwUDJ9r2YM,743
42
+ ophyd_async/epics/areadetector/drivers/pilatus_driver.py,sha256=0DsUu9vAPXDa2v8_V0f_kPjBtLu3y4_EkmFfFjYO4Gk,553
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=e7EbusP3Ell-2npdLtDWcZ_kDIRidUwHeqcbeMx4mlU,5427
48
+ ophyd_async/epics/areadetector/writers/nd_file_hdf.py,sha256=whKDkvKnU1qiDym4xQq4Fd1jHEhtDu552xhhGSnB--w,1910
49
+ ophyd_async/epics/areadetector/writers/nd_plugin.py,sha256=sG4XZAS_k065g88n9U3IJGtYI4PPHfyJMcVqh9hVAa4,979
50
+ ophyd_async/epics/demo/__init__.py,sha256=D-jYrorqa5C3gLzIi2Hkn8f8uaE9wb5S-WX3YYuHV48,6052
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=9sWF2oawtKLL1JZIT8FZc8WtKhrZVKfmwgyQv0x48B4,3826
56
+ ophyd_async/epics/pvi/__init__.py,sha256=TbOQNY4enQWgtr1T7x129vpo2p7FIFlr8cyZqqv5Lk4,158
57
+ ophyd_async/epics/pvi/pvi.py,sha256=5Hd9BkULbVv9mCmEn3LFafs2oz77xqlGHn-X48nJ-4o,11331
58
+ ophyd_async/epics/signal/__init__.py,sha256=wb93RTqvSbGKVFQj8OHykbVLGLmwKHU72oi5xYu2UaY,188
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=ZaD1nRgGKAGFGdpP1WWF-FnX3wcGuYqqq0QRZbaSBYQ,692
62
+ ophyd_async/panda/_common_blocks.py,sha256=n0PPc1rar43oDSIA-yNubTc8fR5YCW1tyjQU58whsg0,1038
63
+ ophyd_async/panda/_hdf_panda.py,sha256=QjfZyYos0ZBlIqBiZ5UbyEd_wuh_cGzwV8QE9jvLiIY,1419
64
+ ophyd_async/panda/_panda_controller.py,sha256=dIqcjmaIHVrki8UXSoDx46kk6I2Lhpe2o3sXNg5f-RQ,1238
65
+ ophyd_async/panda/_table.py,sha256=dLoRP4zYNOkD_s0Vkp2wVYAwkjVG8nNdf8-FaXOTfPo,5655
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=_KlawqQHuWXLCvhGg1N6S4dQ8LhM88NbHsbXryxPvPA,7617
70
+ ophyd_async/panda/writers/_panda_hdf_file.py,sha256=42iHaTax4JjOBpNC7d4nkNL9SM14OTnFPTIcXv2jg-4,1759
71
+ ophyd_async/planstubs/__init__.py,sha256=G9B80_d87lnOThUsGbAYPqzMw9xDelq2TbS7dkB692o,188
72
+ ophyd_async/planstubs/prepare_trigger_and_dets.py,sha256=0c4XDAxVkSanyDKtaMda0VgPEbk2jM0geVzAx707DhI,1772
73
+ ophyd_async/sim/__init__.py,sha256=ScjH1g7FMo5yPACfJRZE6xGBWCHU4bKDzNQk1tqObnA,366
74
+ ophyd_async/sim/pattern_generator.py,sha256=pvSk2zb82D08j2jiKAMqMAfRohGnYd_rpjUraLrCD6c,10640
75
+ ophyd_async/sim/sim_pattern_detector_control.py,sha256=Ypz8IuRYAY2J243IhVbNyGr_Z-XtpJZ1qxma6NR3TgM,1838
76
+ ophyd_async/sim/sim_pattern_detector_writer.py,sha256=ESpcVyHd1TP7Cojznv2hJAwLinu3XbgAiVKfX12FCII,1237
77
+ ophyd_async/sim/sim_pattern_generator.py,sha256=fbcwWxTPYKLK33OzIY15vGylnonOO8HIudz1y_56GZU,1336
78
+ ophyd_async/sim/demo/__init__.py,sha256=9mxKpslrL89cfSj4g3og8Br3O--pMj3hhWZS-Xu6kyA,56
79
+ ophyd_async/sim/demo/sim_motor.py,sha256=knpfyrqeNr7HnlV54TQGUr3pLnDyg84vfj_4vKB9UYc,4065
80
+ ophyd_async-0.3a4.dist-info/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
81
+ ophyd_async-0.3a4.dist-info/METADATA,sha256=wPoVN6LuWFSMlFzEaAriOPfJD-XncaJHVzpao8HUBlg,6284
82
+ ophyd_async-0.3a4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
83
+ ophyd_async-0.3a4.dist-info/entry_points.txt,sha256=O0YNJTEufO0w9BozXi-JurTy2U1_o0ypeCgJLQ727Jk,58
84
+ ophyd_async-0.3a4.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
85
+ ophyd_async-0.3a4.dist-info/RECORD,,