dls-dodal 1.34.1__py3-none-any.whl → 1.35.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 (71) hide show
  1. {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/METADATA +2 -2
  2. {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/RECORD +70 -67
  3. {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/WHEEL +1 -1
  4. dodal/_version.py +2 -2
  5. dodal/beamlines/i22.py +24 -11
  6. dodal/beamlines/i24.py +4 -4
  7. dodal/beamlines/p38.py +23 -11
  8. dodal/common/beamlines/beamline_utils.py +1 -2
  9. dodal/common/crystal_metadata.py +61 -0
  10. dodal/common/signal_utils.py +10 -14
  11. dodal/devices/CTAB.py +1 -1
  12. dodal/devices/aperture.py +1 -1
  13. dodal/devices/aperturescatterguard.py +20 -8
  14. dodal/devices/apple2_undulator.py +30 -29
  15. dodal/devices/areadetector/plugins/CAM.py +3 -5
  16. dodal/devices/areadetector/plugins/MJPG.py +1 -1
  17. dodal/devices/attenuator.py +1 -1
  18. dodal/devices/backlight.py +4 -5
  19. dodal/devices/cryostream.py +3 -5
  20. dodal/devices/dcm.py +26 -2
  21. dodal/devices/detector/detector_motion.py +3 -5
  22. dodal/devices/diamond_filter.py +3 -4
  23. dodal/devices/fast_grid_scan.py +1 -1
  24. dodal/devices/fluorescence_detector_motion.py +5 -7
  25. dodal/devices/focusing_mirror.py +12 -11
  26. dodal/devices/hutch_shutter.py +4 -5
  27. dodal/devices/i10/i10_apple2.py +20 -19
  28. dodal/devices/i10/i10_setting_data.py +2 -2
  29. dodal/devices/i22/dcm.py +43 -75
  30. dodal/devices/i22/fswitch.py +5 -5
  31. dodal/devices/i24/aperture.py +3 -5
  32. dodal/devices/i24/beamstop.py +3 -5
  33. dodal/devices/i24/dcm.py +1 -1
  34. dodal/devices/i24/dual_backlight.py +4 -6
  35. dodal/devices/i24/pmac.py +35 -46
  36. dodal/devices/i24/vgonio.py +16 -0
  37. dodal/devices/ipin.py +5 -3
  38. dodal/devices/linkam3.py +7 -7
  39. dodal/devices/oav/oav_detector.py +3 -3
  40. dodal/devices/oav/oav_to_redis_forwarder.py +8 -7
  41. dodal/devices/oav/pin_image_recognition/__init__.py +9 -7
  42. dodal/devices/oav/snapshots/grid_overlay.py +16 -16
  43. dodal/devices/oav/snapshots/snapshot_with_beam_centre.py +5 -5
  44. dodal/devices/oav/snapshots/snapshot_with_grid.py +6 -6
  45. dodal/devices/oav/utils.py +2 -2
  46. dodal/devices/p99/sample_stage.py +3 -5
  47. dodal/devices/pgm.py +5 -6
  48. dodal/devices/qbpm.py +1 -1
  49. dodal/devices/robot.py +3 -3
  50. dodal/devices/smargon.py +1 -1
  51. dodal/devices/synchrotron.py +9 -4
  52. dodal/devices/tetramm.py +7 -7
  53. dodal/devices/thawer.py +13 -7
  54. dodal/devices/undulator.py +5 -5
  55. dodal/devices/util/epics_util.py +1 -1
  56. dodal/devices/watsonmarlow323_pump.py +45 -0
  57. dodal/devices/webcam.py +9 -2
  58. dodal/devices/xbpm_feedback.py +3 -5
  59. dodal/devices/xspress3/xspress3.py +8 -9
  60. dodal/devices/xspress3/xspress3_channel.py +3 -5
  61. dodal/devices/zebra.py +7 -6
  62. dodal/devices/zebra_controlled_shutter.py +5 -6
  63. dodal/devices/zocalo/__init__.py +2 -2
  64. dodal/devices/zocalo/zocalo_constants.py +3 -0
  65. dodal/devices/zocalo/zocalo_interaction.py +2 -1
  66. dodal/devices/zocalo/zocalo_results.py +92 -79
  67. dodal/utils.py +4 -0
  68. dodal/devices/i24/i24_vgonio.py +0 -17
  69. {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/LICENSE +0 -0
  70. {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/entry_points.txt +0 -0
  71. {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,7 @@ def _add_parallel_lines_to_image(
14
14
  start_x: int,
15
15
  start_y: int,
16
16
  line_length: int,
17
- spacing: int,
17
+ spacing: float,
18
18
  num_lines: int,
19
19
  orientation=Orientation.horizontal,
20
20
  ):
@@ -32,7 +32,7 @@ def _add_parallel_lines_to_image(
32
32
  start_x (int): The x coordinate (in pixels) of the start of the initial line.
33
33
  start_y (int): The y coordinate (in pixels) of the start of the initial line.
34
34
  line_length (int): The length of each of the parallel lines in pixels.
35
- spacing (int): The spacing, in pixels, between each parallel line. Strictly, \
35
+ spacing (float): The spacing, in pixels, between each parallel line. Strictly, \
36
36
  there are spacing-1 pixels between each line
37
37
  num_lines (int): The total number of parallel lines to draw.
38
38
  orientation (Orientation): The orientation (horizontal or vertical) of the \
@@ -40,13 +40,13 @@ def _add_parallel_lines_to_image(
40
40
  lines = [
41
41
  (
42
42
  (
43
- (start_x, start_y + i * spacing),
44
- (start_x + line_length, start_y + i * spacing),
43
+ (start_x, start_y + int(i * spacing)),
44
+ (start_x + line_length, start_y + int(i * spacing)),
45
45
  )
46
46
  if orientation == Orientation.horizontal
47
47
  else (
48
- (start_x + i * spacing, start_y),
49
- (start_x + i * spacing, start_y + line_length),
48
+ (start_x + int(i * spacing), start_y),
49
+ (start_x + int(i * spacing), start_y + line_length),
50
50
  )
51
51
  )
52
52
  for i in range(num_lines)
@@ -70,7 +70,7 @@ def add_grid_border_overlay_to_image(
70
70
  image: Image.Image,
71
71
  top_left_x: int,
72
72
  top_left_y: int,
73
- box_width: int,
73
+ box_width: float,
74
74
  num_boxes_x: int,
75
75
  num_boxes_y: int,
76
76
  ):
@@ -78,16 +78,16 @@ def add_grid_border_overlay_to_image(
78
78
  image,
79
79
  start_x=top_left_x,
80
80
  start_y=top_left_y,
81
- line_length=num_boxes_y * box_width,
82
- spacing=num_boxes_x * box_width,
81
+ line_length=int(num_boxes_y * box_width),
82
+ spacing=int(num_boxes_x * box_width),
83
83
  num_lines=2,
84
84
  )
85
85
  _add_horizontal_parallel_lines_to_image(
86
86
  image,
87
87
  start_x=top_left_x,
88
88
  start_y=top_left_y,
89
- line_length=num_boxes_x * box_width,
90
- spacing=num_boxes_y * box_width,
89
+ line_length=int(num_boxes_x * box_width),
90
+ spacing=int(num_boxes_y * box_width),
91
91
  num_lines=2,
92
92
  )
93
93
 
@@ -96,23 +96,23 @@ def add_grid_overlay_to_image(
96
96
  image: Image.Image,
97
97
  top_left_x: int,
98
98
  top_left_y: int,
99
- box_width: int,
99
+ box_width: float,
100
100
  num_boxes_x: int,
101
101
  num_boxes_y: int,
102
102
  ):
103
103
  _add_vertical_parallel_lines_to_image(
104
104
  image,
105
- start_x=top_left_x + box_width,
105
+ start_x=int(top_left_x + box_width),
106
106
  start_y=top_left_y,
107
- line_length=num_boxes_y * box_width,
107
+ line_length=int(num_boxes_y * box_width),
108
108
  spacing=box_width,
109
109
  num_lines=num_boxes_x - 1,
110
110
  )
111
111
  _add_horizontal_parallel_lines_to_image(
112
112
  image,
113
113
  start_x=top_left_x,
114
- start_y=top_left_y + box_width,
115
- line_length=num_boxes_x * box_width,
114
+ start_y=int(top_left_y + box_width),
115
+ line_length=int(num_boxes_x * box_width),
116
116
  spacing=box_width,
117
117
  num_lines=num_boxes_y - 1,
118
118
  )
@@ -1,4 +1,4 @@
1
- from ophyd_async.core import SignalR
1
+ from ophyd_async.core import Reference, SignalR
2
2
  from PIL import Image, ImageDraw
3
3
 
4
4
  from dodal.devices.areadetector.plugins.MJPG import MJPG
@@ -52,13 +52,13 @@ class SnapshotWithBeamCentre(MJPG):
52
52
  name: str = "",
53
53
  ) -> None:
54
54
  with self.add_children_as_readables():
55
- self.beam_centre_i = beam_x_signal
56
- self.beam_centre_j = beam_y_signal
55
+ self._beam_centre_i_ref = Reference(beam_x_signal)
56
+ self._beam_centre_j_ref = Reference(beam_y_signal)
57
57
  super().__init__(prefix, name)
58
58
 
59
59
  async def post_processing(self, image: Image.Image):
60
- beam_x = await self.beam_centre_i.get_value()
61
- beam_y = await self.beam_centre_j.get_value()
60
+ beam_x = await self._beam_centre_i_ref().get_value()
61
+ beam_y = await self._beam_centre_j_ref().get_value()
62
62
  draw_crosshair(image, beam_x, beam_y)
63
63
 
64
64
  await self._save_image(image)
@@ -14,9 +14,9 @@ from dodal.log import LOGGER
14
14
  class SnapshotWithGrid(MJPG):
15
15
  def __init__(self, prefix: str, name: str = "") -> None:
16
16
  with self.add_children_as_readables():
17
- self.top_left_x = soft_signal_rw(int)
18
- self.top_left_y = soft_signal_rw(int)
19
- self.box_width = soft_signal_rw(int)
17
+ self.top_left_x = soft_signal_rw(float)
18
+ self.top_left_y = soft_signal_rw(float)
19
+ self.box_width = soft_signal_rw(float)
20
20
  self.num_boxes_x = soft_signal_rw(int)
21
21
  self.num_boxes_y = soft_signal_rw(int)
22
22
 
@@ -31,7 +31,7 @@ class SnapshotWithGrid(MJPG):
31
31
 
32
32
  top_left_x = await self.top_left_x.get_value()
33
33
  top_left_y = await self.top_left_y.get_value()
34
- box_witdh = await self.box_width.get_value()
34
+ box_width = await self.box_width.get_value()
35
35
  num_boxes_x = await self.num_boxes_x.get_value()
36
36
  num_boxes_y = await self.num_boxes_y.get_value()
37
37
 
@@ -39,7 +39,7 @@ class SnapshotWithGrid(MJPG):
39
39
  assert isinstance(directory_str := await self.directory.get_value(), str)
40
40
 
41
41
  add_grid_border_overlay_to_image(
42
- image, top_left_x, top_left_y, box_witdh, num_boxes_x, num_boxes_y
42
+ image, int(top_left_x), int(top_left_y), box_width, num_boxes_x, num_boxes_y
43
43
  )
44
44
 
45
45
  path = path_join(directory_str, f"{filename_str}_outer_overlay.{IMG_FORMAT}")
@@ -48,7 +48,7 @@ class SnapshotWithGrid(MJPG):
48
48
  await asyncio_save_image(image, path)
49
49
 
50
50
  add_grid_overlay_to_image(
51
- image, top_left_x, top_left_y, box_witdh, num_boxes_x, num_boxes_y
51
+ image, int(top_left_x), int(top_left_y), box_width, num_boxes_x, num_boxes_y
52
52
  )
53
53
 
54
54
  path = path_join(directory_str, f"{filename_str}_grid_overlay.{IMG_FORMAT}")
@@ -103,8 +103,8 @@ def wait_for_tip_to_be_found(
103
103
  ) -> Generator[Msg, None, Pixel]:
104
104
  yield from bps.trigger(ophyd_pin_tip_detection, wait=True)
105
105
  found_tip = yield from bps.rd(ophyd_pin_tip_detection.triggered_tip)
106
- if found_tip == ophyd_pin_tip_detection.INVALID_POSITION:
106
+ if all(found_tip == ophyd_pin_tip_detection.INVALID_POSITION):
107
107
  timeout = yield from bps.rd(ophyd_pin_tip_detection.validity_timeout)
108
108
  raise PinNotFoundException(f"No pin found after {timeout} seconds")
109
109
 
110
- return found_tip # type: ignore
110
+ return Pixel((int(found_tip[0]), int(found_tip[1])))
@@ -1,7 +1,5 @@
1
- from enum import Enum
2
-
3
- from ophyd_async.core import Device
4
- from ophyd_async.epics.signal import epics_signal_rw
1
+ from ophyd_async.core import Device, SubsetEnum
2
+ from ophyd_async.epics.core import epics_signal_rw
5
3
 
6
4
 
7
5
  class SampleAngleStage(Device):
@@ -18,7 +16,7 @@ class SampleAngleStage(Device):
18
16
  super().__init__(name=name)
19
17
 
20
18
 
21
- class p99StageSelections(str, Enum):
19
+ class p99StageSelections(SubsetEnum):
22
20
  Empty = "Empty"
23
21
  Mn5um = "Mn 5um"
24
22
  Fe = "Fe (empty)"
dodal/devices/pgm.py CHANGED
@@ -1,11 +1,10 @@
1
- from enum import Enum
2
-
3
1
  from ophyd_async.core import (
4
- ConfigSignal,
5
2
  StandardReadable,
3
+ StandardReadableFormat,
4
+ StrictEnum,
6
5
  )
6
+ from ophyd_async.epics.core import epics_signal_rw
7
7
  from ophyd_async.epics.motor import Motor
8
- from ophyd_async.epics.signal import epics_signal_rw
9
8
 
10
9
 
11
10
  class PGM(StandardReadable):
@@ -16,7 +15,7 @@ class PGM(StandardReadable):
16
15
  def __init__(
17
16
  self,
18
17
  prefix: str,
19
- grating: type[Enum],
18
+ grating: type[StrictEnum],
20
19
  gratingPv: str,
21
20
  name: str = "",
22
21
  ) -> None:
@@ -34,7 +33,7 @@ class PGM(StandardReadable):
34
33
  """
35
34
  with self.add_children_as_readables():
36
35
  self.energy = Motor(prefix + "ENERGY")
37
- with self.add_children_as_readables(ConfigSignal):
36
+ with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
38
37
  self.grating = epics_signal_rw(grating, prefix + gratingPv)
39
38
  self.cff = epics_signal_rw(float, prefix + "CFF")
40
39
 
dodal/devices/qbpm.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from ophyd_async.core import StandardReadable
2
- from ophyd_async.epics.signal import epics_signal_r
2
+ from ophyd_async.epics.core import epics_signal_r
3
3
 
4
4
 
5
5
  class QBPM(StandardReadable):
dodal/devices/robot.py CHANGED
@@ -1,16 +1,16 @@
1
1
  import asyncio
2
2
  from asyncio import FIRST_COMPLETED, CancelledError, Task, wait_for
3
3
  from dataclasses import dataclass
4
- from enum import Enum
5
4
 
6
5
  from bluesky.protocols import Movable
7
6
  from ophyd_async.core import (
8
7
  AsyncStatus,
9
8
  StandardReadable,
9
+ StrictEnum,
10
10
  set_and_wait_for_value,
11
11
  wait_for_value,
12
12
  )
13
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw_rbv, epics_signal_x
13
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw_rbv, epics_signal_x
14
14
 
15
15
  from dodal.log import LOGGER
16
16
 
@@ -33,7 +33,7 @@ class SampleLocation:
33
33
  pin: int
34
34
 
35
35
 
36
- class PinMounted(str, Enum):
36
+ class PinMounted(StrictEnum):
37
37
  NO_PIN_MOUNTED = "No Pin Mounted"
38
38
  PIN_MOUNTED = "Pin Mounted"
39
39
 
dodal/devices/smargon.py CHANGED
@@ -7,8 +7,8 @@ from typing import cast
7
7
  from bluesky import plan_stubs as bps
8
8
  from bluesky.utils import Msg
9
9
  from ophyd_async.core import AsyncStatus, Device, StandardReadable, wait_for_value
10
+ from ophyd_async.epics.core import epics_signal_r
10
11
  from ophyd_async.epics.motor import Motor
11
- from ophyd_async.epics.signal import epics_signal_r
12
12
 
13
13
  from dodal.devices.util.epics_util import SetWhenEnabled
14
14
 
@@ -1,7 +1,12 @@
1
1
  from enum import Enum
2
2
 
3
- from ophyd_async.core import ConfigSignal, StandardReadable, soft_signal_r_and_setter
4
- from ophyd_async.epics.signal import epics_signal_r
3
+ from ophyd_async.core import (
4
+ StandardReadable,
5
+ StandardReadableFormat,
6
+ StrictEnum,
7
+ soft_signal_r_and_setter,
8
+ )
9
+ from ophyd_async.epics.core import epics_signal_r
5
10
 
6
11
 
7
12
  class Prefix(str, Enum):
@@ -19,7 +24,7 @@ class Suffix(str, Enum):
19
24
  END_COUNTDOWN = "ENDCOUNTDN"
20
25
 
21
26
 
22
- class SynchrotronMode(str, Enum):
27
+ class SynchrotronMode(StrictEnum):
23
28
  SHUTDOWN = "Shutdown"
24
29
  INJECTION = "Injection"
25
30
  NOBEAM = "No Beam"
@@ -44,7 +49,7 @@ class Synchrotron(StandardReadable):
44
49
  self.current = epics_signal_r(float, signal_prefix + Suffix.SIGNAL)
45
50
  self.energy = epics_signal_r(float, status_prefix + Suffix.BEAM_ENERGY)
46
51
 
47
- with self.add_children_as_readables(ConfigSignal):
52
+ with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
48
53
  self.probe, _ = soft_signal_r_and_setter(str, initial_value="x-ray")
49
54
  self.type, _ = soft_signal_r_and_setter(
50
55
  str, initial_value="Synchrotron X-ray Source"
dodal/devices/tetramm.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import asyncio
2
- from enum import Enum
3
2
 
4
3
  from bluesky.protocols import Hints
5
4
  from ophyd_async.core import (
@@ -9,42 +8,43 @@ from ophyd_async.core import (
9
8
  Device,
10
9
  PathProvider,
11
10
  StandardDetector,
11
+ StrictEnum,
12
12
  TriggerInfo,
13
13
  set_and_wait_for_value,
14
14
  soft_signal_r_and_setter,
15
15
  )
16
16
  from ophyd_async.epics.adcore import ADHDFWriter, NDFileHDFIO, stop_busy_record
17
- from ophyd_async.epics.signal import (
17
+ from ophyd_async.epics.core import (
18
18
  epics_signal_r,
19
19
  epics_signal_rw,
20
20
  epics_signal_rw_rbv,
21
21
  )
22
22
 
23
23
 
24
- class TetrammRange(str, Enum):
24
+ class TetrammRange(StrictEnum):
25
25
  uA = "+- 120 uA"
26
26
  nA = "+- 120 nA"
27
27
 
28
28
 
29
- class TetrammTrigger(str, Enum):
29
+ class TetrammTrigger(StrictEnum):
30
30
  FreeRun = "Free run"
31
31
  ExtTrigger = "Ext. trig."
32
32
  ExtBulb = "Ext. bulb"
33
33
  ExtGate = "Ext. gate"
34
34
 
35
35
 
36
- class TetrammChannels(str, Enum):
36
+ class TetrammChannels(StrictEnum):
37
37
  One = "1"
38
38
  Two = "2"
39
39
  Four = "4"
40
40
 
41
41
 
42
- class TetrammResolution(str, Enum):
42
+ class TetrammResolution(StrictEnum):
43
43
  SixteenBits = "16 bits"
44
44
  TwentyFourBits = "24 bits"
45
45
 
46
46
 
47
- class TetrammGeometry(str, Enum):
47
+ class TetrammGeometry(StrictEnum):
48
48
  Diamond = "Diamond"
49
49
  Square = "Square"
50
50
 
dodal/devices/thawer.py CHANGED
@@ -1,36 +1,42 @@
1
1
  from asyncio import Task, create_task, sleep
2
- from enum import Enum
3
2
 
4
3
  from bluesky.protocols import Stoppable
5
- from ophyd_async.core import AsyncStatus, Device, SignalRW, StandardReadable
6
- from ophyd_async.epics.signal import epics_signal_rw
4
+ from ophyd_async.core import (
5
+ AsyncStatus,
6
+ Device,
7
+ Reference,
8
+ SignalRW,
9
+ StandardReadable,
10
+ StrictEnum,
11
+ )
12
+ from ophyd_async.epics.core import epics_signal_rw
7
13
 
8
14
 
9
15
  class ThawingException(Exception):
10
16
  pass
11
17
 
12
18
 
13
- class ThawerStates(str, Enum):
19
+ class ThawerStates(StrictEnum):
14
20
  OFF = "Off"
15
21
  ON = "On"
16
22
 
17
23
 
18
24
  class ThawingTimer(Device, Stoppable):
19
25
  def __init__(self, control_signal: SignalRW[ThawerStates]) -> None:
20
- self._control_signal = control_signal
26
+ self._control_signal_ref = Reference(control_signal)
21
27
  self._thawing_task: Task | None = None
22
28
  super().__init__("thaw_for_time_s")
23
29
 
24
30
  @AsyncStatus.wrap
25
31
  async def set(self, time_to_thaw_for: float):
26
- await self._control_signal.set(ThawerStates.ON)
32
+ await self._control_signal_ref().set(ThawerStates.ON)
27
33
  if self._thawing_task and not self._thawing_task.done():
28
34
  raise ThawingException("Thawing task already in progress")
29
35
  self._thawing_task = create_task(sleep(time_to_thaw_for))
30
36
  try:
31
37
  await self._thawing_task
32
38
  finally:
33
- await self._control_signal.set(ThawerStates.OFF)
39
+ await self._control_signal_ref().set(ThawerStates.OFF)
34
40
 
35
41
  @AsyncStatus.wrap
36
42
  async def stop(self, *args, **kwargs):
@@ -1,17 +1,17 @@
1
1
  import os
2
- from enum import Enum
3
2
 
4
3
  import numpy as np
5
4
  from bluesky.protocols import Movable
6
5
  from numpy import argmin, ndarray
7
6
  from ophyd_async.core import (
8
7
  AsyncStatus,
9
- ConfigSignal,
10
8
  StandardReadable,
9
+ StandardReadableFormat,
10
+ StrictEnum,
11
11
  soft_signal_r_and_setter,
12
12
  )
13
+ from ophyd_async.epics.core import epics_signal_r
13
14
  from ophyd_async.epics.motor import Motor
14
- from ophyd_async.epics.signal import epics_signal_r
15
15
 
16
16
  from dodal.log import LOGGER
17
17
 
@@ -33,7 +33,7 @@ UNDULATOR_DISCREPANCY_THRESHOLD_MM = 2e-3
33
33
  STATUS_TIMEOUT_S: float = 10.0
34
34
 
35
35
 
36
- class UndulatorGapAccess(str, Enum):
36
+ class UndulatorGapAccess(StrictEnum):
37
37
  ENABLED = "ENABLED"
38
38
  DISABLED = "DISABLED"
39
39
 
@@ -75,7 +75,7 @@ class Undulator(StandardReadable, Movable):
75
75
  self.current_gap = epics_signal_r(float, prefix + "CURRGAPD")
76
76
  self.gap_access = epics_signal_r(UndulatorGapAccess, prefix + "IDBLENA")
77
77
 
78
- with self.add_children_as_readables(ConfigSignal):
78
+ with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
79
79
  self.gap_discrepancy_tolerance_mm, _ = soft_signal_r_and_setter(
80
80
  float,
81
81
  initial_value=UNDULATOR_DISCREPANCY_THRESHOLD_MM,
@@ -7,7 +7,7 @@ from ophyd import Device as OphydDevice
7
7
  from ophyd.status import Status, StatusBase
8
8
  from ophyd_async.core import AsyncStatus, wait_for_value
9
9
  from ophyd_async.core import Device as OphydAsyncDevice
10
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
10
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
11
11
 
12
12
  from dodal.log import LOGGER
13
13
 
@@ -0,0 +1,45 @@
1
+ from ophyd_async.core import StandardReadable, StandardReadableFormat, StrictEnum
2
+ from ophyd_async.epics.core import epics_signal_rw
3
+
4
+
5
+ class WatsonMarlow323PumpEnable(StrictEnum):
6
+ DISABLED = "Disabled"
7
+ ENABLED = "Enabled"
8
+
9
+
10
+ class WatsonMarlow323PumpDirection(StrictEnum):
11
+ CLOCKWISE = "CW"
12
+ COUNTER_CLOCKWISE = "CCW"
13
+
14
+
15
+ class WatsonMarlow323PumpState(StrictEnum):
16
+ STOPPED = "STOP"
17
+ STARTED = "START"
18
+
19
+
20
+ class WatsonMarlow323Pump(StandardReadable):
21
+ """Watson Marlow 323 Peristaltic Pump device"""
22
+
23
+ def __init__(self, prefix: str, name: str = "") -> None:
24
+ with self.add_children_as_readables():
25
+ self.direction = epics_signal_rw(
26
+ WatsonMarlow323PumpDirection,
27
+ read_pv=prefix + "INFO:DIR",
28
+ write_pv=prefix + "SET:DIR",
29
+ )
30
+ self.state = epics_signal_rw(
31
+ WatsonMarlow323PumpState,
32
+ read_pv=prefix + "INFO:RUN",
33
+ write_pv=prefix + "SET:RUN",
34
+ )
35
+ self.speed = epics_signal_rw(
36
+ float, read_pv=prefix + "INFO:SPD", write_pv=prefix + "SET:SPD"
37
+ )
38
+
39
+ with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
40
+ self.enabled = epics_signal_rw(
41
+ WatsonMarlow323PumpEnable,
42
+ prefix + "DISABLE",
43
+ )
44
+
45
+ super().__init__(name=name)
dodal/devices/webcam.py CHANGED
@@ -5,7 +5,12 @@ from pathlib import Path
5
5
  import aiofiles
6
6
  from aiohttp import ClientSession
7
7
  from bluesky.protocols import Triggerable
8
- from ophyd_async.core import AsyncStatus, HintedSignal, StandardReadable, soft_signal_rw
8
+ from ophyd_async.core import (
9
+ AsyncStatus,
10
+ StandardReadable,
11
+ StandardReadableFormat,
12
+ soft_signal_rw,
13
+ )
9
14
  from PIL import Image
10
15
 
11
16
  from dodal.log import LOGGER
@@ -27,7 +32,9 @@ class Webcam(StandardReadable, Triggerable):
27
32
  self.directory = soft_signal_rw(str, name="directory")
28
33
  self.last_saved_path = soft_signal_rw(str, name="last_saved_path")
29
34
 
30
- self.add_readables([self.last_saved_path], wrapper=HintedSignal)
35
+ self.add_readables(
36
+ [self.last_saved_path], format=StandardReadableFormat.HINTED_SIGNAL
37
+ )
31
38
  super().__init__(name=name)
32
39
 
33
40
  async def _write_image(self, file_path: str, image: ByteString):
@@ -1,11 +1,9 @@
1
- from enum import Enum
2
-
3
1
  from bluesky.protocols import Triggerable
4
- from ophyd_async.core import AsyncStatus, Device, observe_value
5
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
2
+ from ophyd_async.core import AsyncStatus, Device, StrictEnum, observe_value
3
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
6
4
 
7
5
 
8
- class Pause(str, Enum):
6
+ class Pause(StrictEnum):
9
7
  PAUSE = "Paused" # 0
10
8
  RUN = "Ok to Run" # 1
11
9
 
@@ -1,15 +1,14 @@
1
- from enum import Enum
2
-
3
1
  from bluesky.protocols import Stageable
4
2
  from numpy import float64
5
- from numpy.typing import NDArray
6
3
  from ophyd_async.core import (
4
+ Array1D,
7
5
  AsyncStatus,
8
6
  Device,
9
7
  DeviceVector,
8
+ StrictEnum,
10
9
  wait_for_value,
11
10
  )
12
- from ophyd_async.epics.signal import (
11
+ from ophyd_async.epics.core import (
13
12
  epics_signal_r,
14
13
  epics_signal_rw,
15
14
  epics_signal_rw_rbv,
@@ -23,7 +22,7 @@ from dodal.devices.xspress3.xspress3_channel import (
23
22
  from dodal.log import LOGGER
24
23
 
25
24
 
26
- class TriggerMode(str, Enum):
25
+ class TriggerMode(StrictEnum):
27
26
  SOFTWARE = "Software"
28
27
  HARDWARE = "Hardware"
29
28
  BURST = "Burst"
@@ -35,17 +34,17 @@ class TriggerMode(str, Enum):
35
34
  LVDS_both = "LVDS Both"
36
35
 
37
36
 
38
- class UpdateRBV(str, Enum):
37
+ class UpdateRBV(StrictEnum):
39
38
  DISABLED = "Disabled"
40
39
  ENABLED = "Enabled"
41
40
 
42
41
 
43
- class AcquireRBVState(str, Enum):
42
+ class AcquireRBVState(StrictEnum):
44
43
  DONE = "Done"
45
44
  ACQUIRE = "Acquiring"
46
45
 
47
46
 
48
- class DetectorState(str, Enum):
47
+ class DetectorState(StrictEnum):
49
48
  IDLE = "Idle"
50
49
  ACQUIRE = "Acquire"
51
50
  READOUT = "Readout"
@@ -101,7 +100,7 @@ class Xspress3(Device, Stageable):
101
100
  """signal for the corrected MCA spectrum (1d array)"""
102
101
  self.dt_corrected_latest_mca = DeviceVector(
103
102
  {
104
- i: epics_signal_r(NDArray[float64], f"{prefix}ARR{i}:ArrayData")
103
+ i: epics_signal_r(Array1D[float64], f"{prefix}ARR{i}:ArrayData")
105
104
  for i in range(1, num_channels + 1)
106
105
  }
107
106
  )
@@ -1,10 +1,8 @@
1
- from enum import Enum
1
+ from ophyd_async.core import Device, StrictEnum
2
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
2
3
 
3
- from ophyd_async.core import Device
4
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
5
4
 
6
-
7
- class AcquireState(str, Enum):
5
+ class AcquireState(StrictEnum):
8
6
  DONE = "Done"
9
7
  ACQUIRE = "Acquire"
10
8
 
dodal/devices/zebra.py CHANGED
@@ -9,9 +9,10 @@ from ophyd_async.core import (
9
9
  DeviceVector,
10
10
  SignalRW,
11
11
  StandardReadable,
12
+ StrictEnum,
12
13
  observe_value,
13
14
  )
14
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
15
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
15
16
 
16
17
  # These constants refer to I03's Zebra. See https://github.com/DiamondLightSource/dodal/issues/772
17
18
  # Sources
@@ -46,18 +47,18 @@ AUTO_SHUTTER_INPUT_1 = 1
46
47
  AUTO_SHUTTER_INPUT_2 = 2
47
48
 
48
49
 
49
- class ArmSource(str, Enum):
50
+ class ArmSource(StrictEnum):
50
51
  SOFT = "Soft"
51
52
  EXTERNAL = "External"
52
53
 
53
54
 
54
- class TrigSource(str, Enum):
55
+ class TrigSource(StrictEnum):
55
56
  POSITION = "Position"
56
57
  TIME = "Time"
57
58
  EXTERNAL = "External"
58
59
 
59
60
 
60
- class EncEnum(str, Enum):
61
+ class EncEnum(StrictEnum):
61
62
  Enc1 = "Enc1"
62
63
  Enc2 = "Enc2"
63
64
  Enc3 = "Enc3"
@@ -79,7 +80,7 @@ class I24Axes:
79
80
  VGON_YH = EncEnum.Enc4
80
81
 
81
82
 
82
- class RotationDirection(str, Enum):
83
+ class RotationDirection(StrictEnum):
83
84
  POSITIVE = "Positive"
84
85
  NEGATIVE = "Negative"
85
86
 
@@ -93,7 +94,7 @@ class ArmDemand(Enum):
93
94
  DISARM = 0
94
95
 
95
96
 
96
- class SoftInState(str, Enum):
97
+ class SoftInState(StrictEnum):
97
98
  YES = "Yes"
98
99
  NO = "No"
99
100