dls-dodal 1.35.0__py3-none-any.whl → 1.36.1a0__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 (46) hide show
  1. {dls_dodal-1.35.0.dist-info → dls_dodal-1.36.1a0.dist-info}/METADATA +33 -31
  2. {dls_dodal-1.35.0.dist-info → dls_dodal-1.36.1a0.dist-info}/RECORD +46 -37
  3. {dls_dodal-1.35.0.dist-info → dls_dodal-1.36.1a0.dist-info}/WHEEL +1 -1
  4. dodal/_version.py +2 -2
  5. dodal/beamlines/b01_1.py +16 -31
  6. dodal/beamlines/i22.py +124 -265
  7. dodal/beamlines/i24.py +56 -7
  8. dodal/beamlines/p38.py +16 -1
  9. dodal/beamlines/p99.py +22 -53
  10. dodal/beamlines/training_rig.py +16 -26
  11. dodal/cli.py +54 -8
  12. dodal/common/beamlines/beamline_utils.py +32 -2
  13. dodal/common/beamlines/device_helpers.py +2 -0
  14. dodal/devices/aperture.py +7 -0
  15. dodal/devices/aperturescatterguard.py +195 -79
  16. dodal/devices/dcm.py +5 -4
  17. dodal/devices/eiger.py +88 -49
  18. dodal/devices/fast_grid_scan.py +21 -46
  19. dodal/devices/focusing_mirror.py +8 -3
  20. dodal/devices/i24/beam_center.py +12 -0
  21. dodal/devices/i24/focus_mirrors.py +60 -0
  22. dodal/devices/i24/pilatus_metadata.py +44 -0
  23. dodal/devices/linkam3.py +1 -1
  24. dodal/devices/motors.py +14 -10
  25. dodal/devices/oav/oav_detector.py +2 -2
  26. dodal/devices/oav/pin_image_recognition/__init__.py +4 -5
  27. dodal/devices/oav/utils.py +1 -0
  28. dodal/devices/p99/sample_stage.py +12 -16
  29. dodal/devices/pressure_jump_cell.py +299 -0
  30. dodal/devices/robot.py +1 -1
  31. dodal/devices/tetramm.py +1 -1
  32. dodal/devices/undulator.py +4 -1
  33. dodal/devices/undulator_dcm.py +3 -19
  34. dodal/devices/zocalo/zocalo_results.py +7 -7
  35. dodal/plan_stubs/__init__.py +0 -0
  36. dodal/{plans/data_session_metadata.py → plan_stubs/data_session.py} +2 -2
  37. dodal/{plans/motor_util_plans.py → plan_stubs/motor_utils.py} +2 -2
  38. dodal/plan_stubs/wrapped.py +150 -0
  39. dodal/plans/__init__.py +4 -0
  40. dodal/plans/scanspec.py +66 -0
  41. dodal/plans/wrapped.py +57 -0
  42. dodal/utils.py +151 -2
  43. {dls_dodal-1.35.0.dist-info → dls_dodal-1.36.1a0.dist-info}/LICENSE +0 -0
  44. {dls_dodal-1.35.0.dist-info → dls_dodal-1.36.1a0.dist-info}/entry_points.txt +0 -0
  45. {dls_dodal-1.35.0.dist-info → dls_dodal-1.36.1a0.dist-info}/top_level.txt +0 -0
  46. /dodal/{plans → plan_stubs}/check_topup.py +0 -0
@@ -40,15 +40,15 @@ class ZoomController(StandardReadable):
40
40
  """
41
41
 
42
42
  def __init__(self, prefix: str, name: str = "") -> None:
43
- super().__init__(name=name)
44
43
  self.percentage = epics_signal_rw(float, f"{prefix}ZOOMPOSCMD")
45
44
 
46
45
  # Level is the string description of the zoom level e.g. "1.0x" or "1.0"
47
46
  self.level = epics_signal_rw(str, f"{prefix}MP:SELECT")
47
+ super().__init__(name=name)
48
48
 
49
49
  async def _get_allowed_zoom_levels(self) -> list:
50
50
  zoom_levels = await self.level.describe()
51
- return zoom_levels["level"]["choices"] # type: ignore
51
+ return zoom_levels[self.level.name]["choices"] # type: ignore
52
52
 
53
53
  @AsyncStatus.wrap
54
54
  async def set(self, level_to_set: str):
@@ -2,7 +2,6 @@ import asyncio
2
2
  import time
3
3
 
4
4
  import numpy as np
5
- from numpy.typing import NDArray
6
5
  from ophyd_async.core import (
7
6
  Array1D,
8
7
  AsyncStatus,
@@ -57,12 +56,12 @@ class PinTipDetection(StandardReadable):
57
56
  Tip, name="triggered_tip"
58
57
  )
59
58
  self.triggered_top_edge, self._top_edge_setter = soft_signal_r_and_setter(
60
- NDArray[np.uint32], name="triggered_top_edge"
59
+ Array1D[np.int32], name="triggered_top_edge"
61
60
  )
62
61
  self.triggered_bottom_edge, self._bottom_edge_setter = soft_signal_r_and_setter(
63
- NDArray[np.uint32], name="triggered_bottom_edge"
62
+ Array1D[np.int32], name="triggered_bottom_edge"
64
63
  )
65
- self.array_data = epics_signal_r(NDArray[np.uint8], f"pva://{prefix}PVA:ARRAY")
64
+ self.array_data = epics_signal_r(Array1D[np.uint8], f"pva://{prefix}PVA:ARRAY")
66
65
 
67
66
  # Soft parameters for pin-tip detection.
68
67
  self.preprocess_operation = soft_signal_rw(int, 10, name="preprocess")
@@ -101,7 +100,7 @@ class PinTipDetection(StandardReadable):
101
100
  self._bottom_edge_setter(results.edge_bottom)
102
101
 
103
102
  async def _get_tip_and_edge_data(
104
- self, array_data: NDArray[np.uint8]
103
+ self, array_data: Array1D[np.uint8]
105
104
  ) -> SampleLocation:
106
105
  """
107
106
  Gets the location of the pin tip and the top and bottom edges.
@@ -87,6 +87,7 @@ def calculate_x_y_z_of_pixel(
87
87
  beam_centre: tuple[int, int],
88
88
  microns_per_pixel: tuple[float, float],
89
89
  ) -> np.ndarray:
90
+ """Get the x, y, z position of a pixel in mm"""
90
91
  beam_distance_px: Pixel = calculate_beam_distance(beam_centre, *pixel)
91
92
 
92
93
  return current_x_y_z + camera_coordinates_to_xyz(
@@ -1,18 +1,13 @@
1
- from ophyd_async.core import Device, SubsetEnum
2
- from ophyd_async.epics.core import epics_signal_rw
1
+ from ophyd_async.core import StandardReadable, SubsetEnum
2
+ from ophyd_async.epics.core import epics_signal_rw, epics_signal_rw_rbv
3
3
 
4
4
 
5
- class SampleAngleStage(Device):
6
- def __init__(self, prefix: str, name: str):
7
- self.theta = epics_signal_rw(
8
- float, prefix + "WRITETHETA:RBV", prefix + "WRITETHETA"
9
- )
10
- self.roll = epics_signal_rw(
11
- float, prefix + "WRITEROLL:RBV", prefix + "WRITEROLL"
12
- )
13
- self.pitch = epics_signal_rw(
14
- float, prefix + "WRITEPITCH:RBV", prefix + "WRITEPITCH"
15
- )
5
+ class SampleAngleStage(StandardReadable):
6
+ def __init__(self, prefix: str, name: str = ""):
7
+ with self.add_children_as_readables():
8
+ self.theta = epics_signal_rw_rbv(float, prefix + "WRITETHETA", ":RBV")
9
+ self.roll = epics_signal_rw_rbv(float, prefix + "WRITEROLL", ":RBV")
10
+ self.pitch = epics_signal_rw_rbv(float, prefix + "WRITEPITCH", ":RBV")
16
11
  super().__init__(name=name)
17
12
 
18
13
 
@@ -35,7 +30,8 @@ class p99StageSelections(SubsetEnum):
35
30
  User = "User"
36
31
 
37
32
 
38
- class FilterMotor(Device):
39
- def __init__(self, prefix: str, name: str):
40
- self.user_setpoint = epics_signal_rw(p99StageSelections, prefix)
33
+ class FilterMotor(StandardReadable):
34
+ def __init__(self, prefix: str, name: str = ""):
35
+ with self.add_children_as_readables():
36
+ self.user_setpoint = epics_signal_rw(p99StageSelections, prefix)
41
37
  super().__init__(name=name)
@@ -0,0 +1,299 @@
1
+ import asyncio
2
+ from dataclasses import dataclass
3
+
4
+ from bluesky.protocols import HasName, Movable
5
+ from ophyd_async.core import (
6
+ AsyncStatus,
7
+ DeviceVector,
8
+ SignalR,
9
+ StandardReadable,
10
+ StandardReadableFormat,
11
+ StrictEnum,
12
+ )
13
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
14
+
15
+ OPENSEQ_PULSE_LENGTH = 0.2
16
+
17
+
18
+ class PumpState(StrictEnum):
19
+ MANUAL = "Manual"
20
+ AUTO_PRESSURE = "Auto Pressure"
21
+ AUTO_POSITION = "Auto Position"
22
+
23
+
24
+ class StopState(StrictEnum):
25
+ CONTINUE = "CONTINUE"
26
+ STOP = "STOP"
27
+
28
+
29
+ class FastValveControlRequest(StrictEnum):
30
+ OPEN = "Open"
31
+ CLOSE = "Close"
32
+ RESET = "Reset"
33
+ ARM = "Arm"
34
+ DISARM = "Disarm"
35
+
36
+
37
+ class ValveControlRequest(StrictEnum):
38
+ OPEN = "Open"
39
+ CLOSE = "Close"
40
+ RESET = "Reset"
41
+
42
+
43
+ class ValveOpenSeqRequest(StrictEnum):
44
+ INACTIVE = 0
45
+ OPEN_SEQ = 1
46
+
47
+
48
+ class PumpMotorDirectionState(StrictEnum):
49
+ EMPTY = ""
50
+ FORWARD = "Forward"
51
+ REVERSE = "Reverse"
52
+
53
+
54
+ class ValveState(StrictEnum):
55
+ FAULT = "Fault"
56
+ OPEN = "Open"
57
+ OPENING = "Opening"
58
+ CLOSED = "Closed"
59
+ CLOSING = "Closing"
60
+
61
+
62
+ class FastValveState(StrictEnum):
63
+ FAULT = "Fault"
64
+ OPEN = "Open"
65
+ OPEN_ARMED = "Open Armed"
66
+ CLOSED = "Closed"
67
+ CLOSED_ARMED = "Closed Armed"
68
+ NONE = "Unused"
69
+
70
+
71
+ @dataclass
72
+ class AllValvesControlState:
73
+ valve_1: ValveControlRequest | None = None
74
+ valve_3: ValveControlRequest | None = None
75
+ valve_5: FastValveControlRequest | None = None
76
+ valve_6: FastValveControlRequest | None = None
77
+
78
+
79
+ class AllValvesControl(StandardReadable, Movable):
80
+ """
81
+ valves 2, 4, 7, 8 are not controlled by the IOC,
82
+ as they are under manual control.
83
+ fast_valves: tuple[int, ...] = (5, 6)
84
+ slow_valves: tuple[int, ...] = (1, 3)
85
+ """
86
+
87
+ def __init__(
88
+ self,
89
+ prefix: str,
90
+ name: str = "",
91
+ fast_valves: tuple[int, ...] = (5, 6),
92
+ slow_valves: tuple[int, ...] = (1, 3),
93
+ ) -> None:
94
+ self.fast_valves = fast_valves
95
+ self.slow_valves = slow_valves
96
+ with self.add_children_as_readables():
97
+ self.valve_states: DeviceVector[SignalR[ValveState]] = DeviceVector(
98
+ {
99
+ i: epics_signal_r(ValveState, f"{prefix}V{i}:STA")
100
+ for i in self.slow_valves
101
+ }
102
+ )
103
+ self.fast_valve_states: DeviceVector[SignalR[FastValveState]] = (
104
+ DeviceVector(
105
+ {
106
+ i: epics_signal_r(FastValveState, f"{prefix}V{i}:STA")
107
+ for i in self.fast_valves
108
+ }
109
+ )
110
+ )
111
+
112
+ self.fast_valve_control: DeviceVector[FastValveControl] = DeviceVector(
113
+ {i: FastValveControl(f"{prefix}V{i}") for i in self.fast_valves}
114
+ )
115
+
116
+ self.valve_control: DeviceVector[ValveControl] = DeviceVector(
117
+ {i: ValveControl(f"{prefix}V{i}") for i in self.slow_valves}
118
+ )
119
+
120
+ super().__init__(name)
121
+
122
+ async def set_valve(
123
+ self,
124
+ valve: int,
125
+ value: ValveControlRequest | FastValveControlRequest,
126
+ ):
127
+ if valve in self.slow_valves and (isinstance(value, ValveControlRequest)):
128
+ if value == ValveControlRequest.OPEN:
129
+ await self.valve_control[valve].set(ValveOpenSeqRequest.OPEN_SEQ)
130
+ await asyncio.sleep(OPENSEQ_PULSE_LENGTH)
131
+ await self.valve_control[valve].set(ValveOpenSeqRequest.INACTIVE)
132
+ else:
133
+ await self.valve_control[valve].set(value)
134
+
135
+ elif valve in self.fast_valves and (isinstance(value, FastValveControlRequest)):
136
+ if value == FastValveControlRequest.OPEN:
137
+ await self.fast_valve_control[valve].set(ValveOpenSeqRequest.OPEN_SEQ)
138
+ await asyncio.sleep(OPENSEQ_PULSE_LENGTH)
139
+ await self.fast_valve_control[valve].set(ValveOpenSeqRequest.INACTIVE)
140
+ else:
141
+ await self.fast_valve_control[valve].set(value)
142
+
143
+ @AsyncStatus.wrap
144
+ async def set(self, value: AllValvesControlState):
145
+ await asyncio.gather(
146
+ *(
147
+ self.set_valve(int(i[-1]), value)
148
+ for i, value in value.__dict__.items()
149
+ if value is not None
150
+ )
151
+ )
152
+
153
+
154
+ class ValveControl(StandardReadable):
155
+ def __init__(self, prefix: str, name: str = "") -> None:
156
+ with self.add_children_as_readables():
157
+ self.close = epics_signal_rw(ValveControlRequest, prefix + ":CON")
158
+ self.open = epics_signal_rw(ValveOpenSeqRequest, prefix + ":OPENSEQ")
159
+
160
+ super().__init__(name)
161
+
162
+ def set(self, value: ValveControlRequest | ValveOpenSeqRequest) -> AsyncStatus:
163
+ set_status = None
164
+
165
+ if isinstance(value, ValveControlRequest):
166
+ set_status = self.close.set(value)
167
+ elif isinstance(value, ValveOpenSeqRequest):
168
+ set_status = self.open.set(value)
169
+
170
+ return set_status
171
+
172
+
173
+ class FastValveControl(StandardReadable):
174
+ def __init__(self, prefix: str, name: str = "") -> None:
175
+ with self.add_children_as_readables():
176
+ self.close = epics_signal_rw(FastValveControlRequest, prefix + ":CON")
177
+ self.open = epics_signal_rw(ValveOpenSeqRequest, prefix + ":OPENSEQ")
178
+
179
+ super().__init__(name)
180
+
181
+ def set(self, value: FastValveControlRequest | ValveOpenSeqRequest) -> AsyncStatus:
182
+ set_status = None
183
+
184
+ if isinstance(value, FastValveControlRequest):
185
+ set_status = self.close.set(value)
186
+ elif isinstance(value, ValveOpenSeqRequest):
187
+ set_status = self.open.set(value)
188
+
189
+ return set_status
190
+
191
+
192
+ class Pump(StandardReadable):
193
+ def __init__(self, prefix: str, name: str = "") -> None:
194
+ with self.add_children_as_readables():
195
+ self.pump_position = epics_signal_r(float, prefix + "POS")
196
+ self.pump_motor_direction = epics_signal_r(
197
+ PumpMotorDirectionState, prefix + "MTRDIR"
198
+ )
199
+ self.pump_speed = epics_signal_rw(
200
+ float, write_pv=prefix + "MSPEED", read_pv=prefix + "MSPEED_RBV"
201
+ )
202
+
203
+ with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
204
+ self.pump_mode = epics_signal_rw(PumpState, prefix + "SP:AUTO")
205
+
206
+ super().__init__(name)
207
+
208
+
209
+ class PressureTransducer(StandardReadable):
210
+ """
211
+ Pressure transducer for a high pressure X-ray cell.
212
+ This is the chamber and there are three of them.
213
+ 1 is the start, 3 is where the sample is.
214
+ NOTE: the distinction between the adc prefix and the cell prefix is kept here.
215
+
216
+ """
217
+
218
+ def __init__(
219
+ self,
220
+ prefix: str,
221
+ cell_prefix: str,
222
+ number: int,
223
+ name: str = "",
224
+ full_different_prefix_adc: str = "",
225
+ ) -> None:
226
+ final_prefix = f"{prefix}{cell_prefix}"
227
+ with self.add_children_as_readables():
228
+ self.omron_pressure = epics_signal_r(
229
+ float, f"{final_prefix}PP{number}:PRES"
230
+ )
231
+ self.omron_voltage = epics_signal_r(float, f"{final_prefix}PP{number}:RAW")
232
+ self.beckhoff_pressure = epics_signal_r(
233
+ float, f"{final_prefix}STATP{number}:MeanValue_RBV"
234
+ )
235
+ self.slow_beckhoff_voltage_readout = epics_signal_r(
236
+ float, f"{full_different_prefix_adc}CH1"
237
+ )
238
+
239
+ super().__init__(name)
240
+
241
+
242
+ class PressureJumpCellController(HasName):
243
+ def __init__(self, prefix: str, name: str = "") -> None:
244
+ self.stop = epics_signal_rw(StopState, f"{prefix}STOP")
245
+
246
+ self.target_pressure = epics_signal_rw(float, f"{prefix}TARGET")
247
+ self.timeout = epics_signal_rw(float, f"{prefix}TIMER.HIGH")
248
+ self.go = epics_signal_rw(bool, f"{prefix}GO")
249
+
250
+ ## Jump logic ##
251
+ self.start_pressure = epics_signal_rw(float, f"{prefix}JUMPF")
252
+ self.target_pressure = epics_signal_rw(float, f"{prefix}JUMPT")
253
+ self.jump_ready = epics_signal_rw(bool, f"{prefix}SETJUMP")
254
+
255
+ self._name = name
256
+ super().__init__()
257
+
258
+ @property
259
+ def name(self):
260
+ return self._name
261
+
262
+
263
+ class PressureJumpCell(StandardReadable):
264
+ """
265
+ High pressure X-ray cell, used to apply pressure or pressure jumps to a sample.
266
+ prefix: str
267
+ The prefix of beamline - SPECIAL - unusual that the cell prefix is computed separately
268
+ """
269
+
270
+ def __init__(
271
+ self,
272
+ prefix: str,
273
+ cell_prefix: str = "-HPXC-01:",
274
+ adc_prefix: str = "-ADC",
275
+ name: str = "",
276
+ ):
277
+ self.all_valves_control = AllValvesControl(f"{prefix}{cell_prefix}", name)
278
+ self.pump = Pump(f"{prefix}{cell_prefix}", name)
279
+
280
+ self.controller = PressureJumpCellController(
281
+ f"{prefix}{cell_prefix}CTRL:", name
282
+ )
283
+
284
+ with self.add_children_as_readables():
285
+ self.pressure_transducers: DeviceVector[PressureTransducer] = DeviceVector(
286
+ {
287
+ i: PressureTransducer(
288
+ prefix=prefix,
289
+ number=i,
290
+ cell_prefix=cell_prefix,
291
+ full_different_prefix_adc=f"{prefix}{adc_prefix}-0{i}:",
292
+ )
293
+ for i in [1, 2, 3]
294
+ }
295
+ )
296
+
297
+ self.cell_temperature = epics_signal_r(float, f"{prefix}{cell_prefix}TEMP")
298
+
299
+ super().__init__(name)
dodal/devices/robot.py CHANGED
@@ -42,7 +42,7 @@ class BartRobot(StandardReadable, Movable):
42
42
  """The sample changing robot."""
43
43
 
44
44
  # How long to wait for the robot if it is busy soaking/drying
45
- NOT_BUSY_TIMEOUT = 60
45
+ NOT_BUSY_TIMEOUT = 5 * 60
46
46
  # How long to wait for the actual load to happen
47
47
  LOAD_TIMEOUT = 60
48
48
  NO_PIN_ERROR_CODE = 25
dodal/devices/tetramm.py CHANGED
@@ -219,7 +219,7 @@ class TetrammDetector(StandardDetector):
219
219
  self,
220
220
  prefix: str,
221
221
  path_provider: PathProvider,
222
- name: str,
222
+ name: str = "",
223
223
  type: str | None = None,
224
224
  **scalar_sigs: str,
225
225
  ) -> None:
@@ -108,10 +108,13 @@ class Undulator(StandardReadable, Movable):
108
108
  """
109
109
  await self._set_undulator_gap(value)
110
110
 
111
- async def _set_undulator_gap(self, energy_kev: float) -> None:
111
+ async def raise_if_not_enabled(self):
112
112
  access_level = await self.gap_access.get_value()
113
113
  if access_level is UndulatorGapAccess.DISABLED and not TEST_MODE:
114
114
  raise AccessError("Undulator gap access is disabled. Contact Control Room")
115
+
116
+ async def _set_undulator_gap(self, energy_kev: float) -> None:
117
+ await self.raise_if_not_enabled()
115
118
  LOGGER.info(f"Setting undulator gap to {energy_kev:.2f} kev")
116
119
  target_gap = await self._get_gap_to_match_energy(energy_kev)
117
120
 
@@ -6,17 +6,10 @@ from ophyd_async.core import AsyncStatus, StandardReadable
6
6
  from dodal.common.beamlines.beamline_parameters import get_beamline_parameters
7
7
 
8
8
  from .dcm import DCM
9
- from .undulator import Undulator, UndulatorGapAccess
9
+ from .undulator import Undulator
10
10
 
11
11
  ENERGY_TIMEOUT_S: float = 30.0
12
12
 
13
- # Enable to allow testing when the beamline is down, do not change in production!
14
- TEST_MODE = False
15
-
16
-
17
- class AccessError(Exception):
18
- pass
19
-
20
13
 
21
14
  class UndulatorDCM(StandardReadable, Movable):
22
15
  """
@@ -61,17 +54,8 @@ class UndulatorDCM(StandardReadable, Movable):
61
54
 
62
55
  @AsyncStatus.wrap
63
56
  async def set(self, value: float):
57
+ await self.undulator.raise_if_not_enabled()
64
58
  await asyncio.gather(
65
- self._set_dcm_energy(value),
59
+ self.dcm.energy_in_kev.set(value, timeout=ENERGY_TIMEOUT_S),
66
60
  self.undulator.set(value),
67
61
  )
68
-
69
- async def _set_dcm_energy(self, energy_kev: float) -> None:
70
- access_level = await self.undulator.gap_access.get_value()
71
- if access_level is UndulatorGapAccess.DISABLED and not TEST_MODE:
72
- raise AccessError("Undulator gap access is disabled. Contact Control Room")
73
-
74
- await self.dcm.energy_in_kev.set(
75
- energy_kev,
76
- timeout=ENERGY_TIMEOUT_S,
77
- )
@@ -12,8 +12,8 @@ import workflows.transport
12
12
  from bluesky.protocols import Triggerable
13
13
  from bluesky.utils import Msg
14
14
  from deepdiff import DeepDiff
15
- from numpy.typing import NDArray
16
15
  from ophyd_async.core import (
16
+ Array1D,
17
17
  AsyncStatus,
18
18
  StandardReadable,
19
19
  StandardReadableFormat,
@@ -133,22 +133,22 @@ class ZocaloResults(StandardReadable, Triggerable):
133
133
  self.use_cpu_and_gpu = use_cpu_and_gpu
134
134
 
135
135
  self.centre_of_mass, self._com_setter = soft_signal_r_and_setter(
136
- NDArray[np.uint64], name="centre_of_mass"
136
+ Array1D[np.uint64], name="centre_of_mass"
137
137
  )
138
138
  self.bounding_box, self._bounding_box_setter = soft_signal_r_and_setter(
139
- NDArray[np.uint64], name="bounding_box"
139
+ Array1D[np.uint64], name="bounding_box"
140
140
  )
141
141
  self.max_voxel, self._max_voxel_setter = soft_signal_r_and_setter(
142
- NDArray[np.uint64], name="max_voxel"
142
+ Array1D[np.uint64], name="max_voxel"
143
143
  )
144
144
  self.max_count, self._max_count_setter = soft_signal_r_and_setter(
145
- NDArray[np.uint64], name="max_count"
145
+ Array1D[np.uint64], name="max_count"
146
146
  )
147
147
  self.n_voxels, self._n_voxels_setter = soft_signal_r_and_setter(
148
- NDArray[np.uint64], name="n_voxels"
148
+ Array1D[np.uint64], name="n_voxels"
149
149
  )
150
150
  self.total_count, self._total_count_setter = soft_signal_r_and_setter(
151
- NDArray[np.uint64], name="total_count"
151
+ Array1D[np.uint64], name="total_count"
152
152
  )
153
153
  self.ispyb_dcid, self._ispyb_dcid_setter = soft_signal_r_and_setter(
154
154
  int, name="ispyb_dcid"
File without changes
@@ -2,7 +2,7 @@ from bluesky import plan_stubs as bps
2
2
  from bluesky import preprocessors as bpp
3
3
  from bluesky.utils import MsgGenerator, make_decorator
4
4
 
5
- from dodal.common.beamlines import beamline_utils
5
+ from dodal.common.beamlines.beamline_utils import get_path_provider
6
6
  from dodal.common.types import UpdatingPathProvider
7
7
 
8
8
  DATA_SESSION = "data_session"
@@ -31,7 +31,7 @@ def attach_data_session_metadata_wrapper(
31
31
  Iterator[Msg]: Plan messages
32
32
  """
33
33
  if provider is None:
34
- provider = beamline_utils.get_path_provider()
34
+ provider = get_path_provider()
35
35
  yield from bps.wait_for([provider.update])
36
36
  ress = yield from bps.wait_for([provider.data_session])
37
37
  data_session = ress[0].result()
@@ -23,7 +23,7 @@ class MoveTooLarge(Exception):
23
23
  super().__init__(*args)
24
24
 
25
25
 
26
- def _check_and_cache_values(
26
+ def check_and_cache_values(
27
27
  devices_and_positions: dict[MovableReadableDevice, float],
28
28
  smallest_move: float,
29
29
  maximum_move: float,
@@ -89,7 +89,7 @@ def move_and_reset_wrapper(
89
89
  on. If false it is left up to the caller to wait on
90
90
  them. Defaults to True.
91
91
  """
92
- initial_positions = yield from _check_and_cache_values(
92
+ initial_positions = yield from check_and_cache_values(
93
93
  device_and_positions, smallest_move, maximum_move
94
94
  )
95
95