dls-dodal 1.50.0__py3-none-any.whl → 1.52.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.
- {dls_dodal-1.50.0.dist-info → dls_dodal-1.52.0.dist-info}/METADATA +5 -5
- {dls_dodal-1.50.0.dist-info → dls_dodal-1.52.0.dist-info}/RECORD +76 -68
- dodal/_version.py +2 -2
- dodal/beamlines/adsim.py +5 -3
- dodal/beamlines/b01_1.py +41 -5
- dodal/beamlines/b07.py +13 -2
- dodal/beamlines/b07_1.py +13 -2
- dodal/beamlines/b16.py +8 -4
- dodal/beamlines/b21.py +148 -0
- dodal/beamlines/i03.py +10 -12
- dodal/beamlines/i04.py +7 -7
- dodal/beamlines/i09.py +25 -2
- dodal/beamlines/i09_1.py +13 -2
- dodal/beamlines/i09_2.py +24 -0
- dodal/beamlines/i10.py +5 -6
- dodal/beamlines/i13_1.py +5 -5
- dodal/beamlines/i18.py +5 -6
- dodal/beamlines/i22.py +18 -1
- dodal/beamlines/i24.py +5 -5
- dodal/beamlines/p45.py +4 -3
- dodal/beamlines/p60.py +21 -2
- dodal/beamlines/p99.py +19 -5
- dodal/beamlines/training_rig.py +3 -3
- dodal/common/beamlines/beamline_utils.py +5 -2
- dodal/common/device_utils.py +45 -0
- dodal/devices/aithre_lasershaping/goniometer.py +4 -5
- dodal/devices/aperture.py +4 -7
- dodal/devices/aperturescatterguard.py +2 -2
- dodal/devices/attenuator/attenuator.py +5 -3
- dodal/devices/b07/__init__.py +3 -0
- dodal/devices/b07/enums.py +24 -0
- dodal/devices/b07_1/__init__.py +3 -0
- dodal/devices/b07_1/enums.py +18 -0
- dodal/devices/detector/detector_motion.py +19 -17
- dodal/devices/electron_analyser/abstract/__init__.py +4 -0
- dodal/devices/electron_analyser/abstract/base_driver_io.py +44 -28
- dodal/devices/electron_analyser/abstract/base_region.py +20 -7
- dodal/devices/electron_analyser/detector.py +3 -13
- dodal/devices/electron_analyser/specs/detector.py +24 -4
- dodal/devices/electron_analyser/specs/driver_io.py +20 -5
- dodal/devices/electron_analyser/specs/region.py +9 -5
- dodal/devices/electron_analyser/types.py +21 -5
- dodal/devices/electron_analyser/vgscienta/detector.py +22 -7
- dodal/devices/electron_analyser/vgscienta/driver_io.py +16 -8
- dodal/devices/electron_analyser/vgscienta/region.py +11 -6
- dodal/devices/fast_grid_scan.py +1 -2
- dodal/devices/i04/constants.py +1 -1
- dodal/devices/i09/__init__.py +4 -0
- dodal/devices/i09/dcm.py +26 -0
- dodal/devices/i09/enums.py +15 -0
- dodal/devices/i09_1/__init__.py +3 -0
- dodal/devices/i09_1/enums.py +19 -0
- dodal/devices/i10/mirrors.py +4 -6
- dodal/devices/i10/rasor/rasor_motors.py +0 -14
- dodal/devices/i19/beamstop.py +3 -7
- dodal/devices/i24/aperture.py +4 -6
- dodal/devices/i24/beamstop.py +5 -8
- dodal/devices/i24/pmac.py +4 -8
- dodal/devices/linkam3.py +25 -81
- dodal/devices/motors.py +92 -35
- dodal/devices/oav/pin_image_recognition/__init__.py +11 -14
- dodal/devices/p45.py +0 -12
- dodal/devices/p60/__init__.py +4 -0
- dodal/devices/p60/enums.py +10 -0
- dodal/devices/p60/lab_xray_source.py +21 -0
- dodal/devices/pgm.py +1 -1
- dodal/devices/robot.py +11 -7
- dodal/devices/smargon.py +8 -9
- dodal/devices/tetramm.py +134 -150
- dodal/devices/xbpm_feedback.py +6 -3
- dodal/devices/zocalo/zocalo_results.py +27 -78
- dodal/plans/configure_arm_trigger_and_disarm_detector.py +7 -5
- dodal/devices/adsim.py +0 -13
- dodal/devices/i18/table.py +0 -14
- dodal/devices/i18/thor_labs_stage.py +0 -12
- dodal/devices/i24/i24_detector_motion.py +0 -12
- dodal/devices/scatterguard.py +0 -11
- dodal/devices/training_rig/__init__.py +0 -0
- dodal/devices/training_rig/sample_stage.py +0 -10
- {dls_dodal-1.50.0.dist-info → dls_dodal-1.52.0.dist-info}/WHEEL +0 -0
- {dls_dodal-1.50.0.dist-info → dls_dodal-1.52.0.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.50.0.dist-info → dls_dodal-1.52.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.50.0.dist-info → dls_dodal-1.52.0.dist-info}/top_level.txt +0 -0
dodal/devices/motors.py
CHANGED
|
@@ -1,61 +1,118 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
|
|
1
3
|
from ophyd_async.core import StandardReadable
|
|
2
4
|
from ophyd_async.epics.motor import Motor
|
|
3
5
|
|
|
6
|
+
_X, _Y, _Z = "X", "Y", "Z"
|
|
4
7
|
|
|
5
|
-
class XYZPositioner(StandardReadable):
|
|
6
|
-
"""
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
class Stage(StandardReadable, ABC):
|
|
10
|
+
"""
|
|
11
|
+
For these devices, the following co-ordinates are typical but not enforced:
|
|
12
|
+
- z is horizontal & parallel to the direction of beam travel
|
|
13
|
+
- y is vertical and antiparallel to the force of gravity
|
|
14
|
+
- x is the cross product of y🞬z
|
|
10
15
|
|
|
11
16
|
Parameters
|
|
12
17
|
----------
|
|
13
18
|
prefix:
|
|
14
|
-
EPICS PV
|
|
19
|
+
Common part of the EPICS PV for all motors, including ":".
|
|
15
20
|
name:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Notes
|
|
20
|
-
-----
|
|
21
|
-
Example usage::
|
|
22
|
-
async with init_devices():
|
|
23
|
-
xyz_stage = XYZPositioner("BLXX-MO-STAGE-XX:")
|
|
24
|
-
Or::
|
|
25
|
-
with init_devices():
|
|
26
|
-
xyz_stage = XYZPositioner("BLXX-MO-STAGE-XX:", infix = ("A", "B", "C"))
|
|
27
|
-
|
|
21
|
+
Name of the stage, each child motor will be named "{name}-{field_name}"
|
|
22
|
+
*_infix:
|
|
23
|
+
Infix between the common prefix and the EPICS motor record fields for the field.
|
|
28
24
|
"""
|
|
29
25
|
|
|
26
|
+
...
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class XThetaStage(Stage):
|
|
30
|
+
def __init__(
|
|
31
|
+
self, prefix: str, name: str = "", x_infix: str = _X, theta_infix: str = "A"
|
|
32
|
+
):
|
|
33
|
+
with self.add_children_as_readables():
|
|
34
|
+
self.x = Motor(prefix + x_infix)
|
|
35
|
+
self.theta = Motor(prefix + theta_infix)
|
|
36
|
+
super().__init__(name=name)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class XYStage(Stage):
|
|
40
|
+
def __init__(
|
|
41
|
+
self, prefix: str, name: str = "", x_infix: str = _X, y_infix: str = _Y
|
|
42
|
+
):
|
|
43
|
+
with self.add_children_as_readables():
|
|
44
|
+
self.x = Motor(prefix + x_infix)
|
|
45
|
+
self.y = Motor(prefix + y_infix)
|
|
46
|
+
super().__init__(name=name)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class XYZStage(XYStage):
|
|
30
50
|
def __init__(
|
|
31
51
|
self,
|
|
32
52
|
prefix: str,
|
|
33
53
|
name: str = "",
|
|
34
|
-
|
|
54
|
+
x_infix: str = _X,
|
|
55
|
+
y_infix: str = _Y,
|
|
56
|
+
z_infix: str = _Z,
|
|
35
57
|
):
|
|
36
58
|
with self.add_children_as_readables():
|
|
37
|
-
self.
|
|
38
|
-
|
|
39
|
-
self.z = Motor(prefix + infix[2])
|
|
40
|
-
super().__init__(name=name)
|
|
59
|
+
self.z = Motor(prefix + z_infix)
|
|
60
|
+
super().__init__(prefix, name, x_infix, y_infix)
|
|
41
61
|
|
|
42
62
|
|
|
43
|
-
class
|
|
63
|
+
class XYZThetaStage(XYZStage):
|
|
44
64
|
def __init__(
|
|
45
65
|
self,
|
|
46
66
|
prefix: str,
|
|
47
67
|
name: str = "",
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
),
|
|
68
|
+
x_infix: str = _X,
|
|
69
|
+
y_infix: str = _Y,
|
|
70
|
+
z_infix: str = _Z,
|
|
71
|
+
theta_infix: str = _Z,
|
|
72
|
+
) -> None:
|
|
73
|
+
with self.add_children_as_readables():
|
|
74
|
+
self.theta = Motor(prefix + theta_infix)
|
|
75
|
+
super().__init__(prefix, name, x_infix, y_infix, z_infix)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class XYPitchStage(XYStage):
|
|
79
|
+
def __init__(
|
|
80
|
+
self,
|
|
81
|
+
prefix: str,
|
|
82
|
+
x_infix: str = _X,
|
|
83
|
+
y_infix: str = _Y,
|
|
84
|
+
pitch_infix: str = "PITCH",
|
|
85
|
+
name: str = "",
|
|
86
|
+
) -> None:
|
|
87
|
+
with self.add_children_as_readables():
|
|
88
|
+
self.pitch = Motor(prefix + pitch_infix)
|
|
89
|
+
super().__init__(prefix, name, x_infix, y_infix)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class SixAxisGonio(XYZStage):
|
|
93
|
+
def __init__(
|
|
94
|
+
self,
|
|
95
|
+
prefix: str,
|
|
96
|
+
name: str = "",
|
|
97
|
+
x_infix: str = _X,
|
|
98
|
+
y_infix: str = _Y,
|
|
99
|
+
z_infix: str = _Z,
|
|
100
|
+
kappa_infix: str = "KAPPA",
|
|
101
|
+
phi_infix: str = "PHI",
|
|
102
|
+
omega_infix: str = "OMEGA",
|
|
56
103
|
):
|
|
57
104
|
with self.add_children_as_readables():
|
|
58
|
-
self.kappa = Motor(prefix +
|
|
59
|
-
self.phi = Motor(prefix +
|
|
60
|
-
self.omega = Motor(prefix +
|
|
61
|
-
super().__init__(name
|
|
105
|
+
self.kappa = Motor(prefix + kappa_infix)
|
|
106
|
+
self.phi = Motor(prefix + phi_infix)
|
|
107
|
+
self.omega = Motor(prefix + omega_infix)
|
|
108
|
+
super().__init__(prefix, name, x_infix, y_infix, z_infix)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class YZStage(Stage):
|
|
112
|
+
def __init__(
|
|
113
|
+
self, prefix: str, name: str = "", y_infix: str = _Y, z_infix: str = _Z
|
|
114
|
+
) -> None:
|
|
115
|
+
with self.add_children_as_readables():
|
|
116
|
+
self.y = Motor(prefix + y_infix)
|
|
117
|
+
self.z = Motor(prefix + z_infix)
|
|
118
|
+
super().__init__(name)
|
|
@@ -141,14 +141,16 @@ class PinTipDetection(StandardReadable):
|
|
|
141
141
|
|
|
142
142
|
@AsyncStatus.wrap
|
|
143
143
|
async def trigger(self):
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
async for value in observe_value(
|
|
144
|
+
"""Monitors the camera data and updates the triggered_tip signal.
|
|
145
|
+
|
|
146
|
+
* If a tip is found it will update the signal and stop monitoring
|
|
147
|
+
* If no tip is found it will retry with the next monitored value, if this
|
|
148
|
+
continues for {validity_timeout} seconds it will timeout.
|
|
149
|
+
"""
|
|
150
|
+
try:
|
|
151
|
+
async for value in observe_value(
|
|
152
|
+
self.array_data, done_timeout=await self.validity_timeout.get_value()
|
|
153
|
+
):
|
|
152
154
|
try:
|
|
153
155
|
location = await self._get_tip_and_edge_data(value)
|
|
154
156
|
self._set_triggered_values(location)
|
|
@@ -157,12 +159,7 @@ class PinTipDetection(StandardReadable):
|
|
|
157
159
|
f"Failed to detect pin-tip location, will retry with next image: {e}"
|
|
158
160
|
)
|
|
159
161
|
else:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
try:
|
|
163
|
-
await asyncio.wait_for(
|
|
164
|
-
_set_triggered_tip(), timeout=await self.validity_timeout.get_value()
|
|
165
|
-
)
|
|
162
|
+
break
|
|
166
163
|
except asyncio.exceptions.TimeoutError:
|
|
167
164
|
LOGGER.error(
|
|
168
165
|
f"No tip found in {await self.validity_timeout.get_value()} seconds."
|
dodal/devices/p45.py
CHANGED
|
@@ -41,15 +41,3 @@ class TomoStageWithStretchAndSkew(StandardReadable):
|
|
|
41
41
|
self.y = SampleY(prefix)
|
|
42
42
|
self.theta = SampleTheta(prefix)
|
|
43
43
|
super().__init__(name)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class Choppers(StandardReadable):
|
|
47
|
-
"""
|
|
48
|
-
Grouping for the P45 chopper motors
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
def __init__(self, prefix: str, name: str = ""):
|
|
52
|
-
with self.add_children_as_readables():
|
|
53
|
-
self.x = Motor(prefix + "ENDAT")
|
|
54
|
-
self.y = Motor(prefix + "BISS")
|
|
55
|
-
super().__init__(name)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from ophyd_async.core import StrictEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class LensMode(StrictEnum):
|
|
5
|
+
TRANSMISSION = "Transmission"
|
|
6
|
+
ANGULAR14 = "Angular14"
|
|
7
|
+
ANGULAR7NF = "Angular7NF"
|
|
8
|
+
ANGULAR30 = "Angular30"
|
|
9
|
+
ANGULAR30_SMALLSPOT = "Angular30_SmallSpot"
|
|
10
|
+
ANGULAR14_SMALLSPOT = "Angular14_SmallSpot"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from ophyd_async.core import (
|
|
2
|
+
StandardReadable,
|
|
3
|
+
StrictEnum,
|
|
4
|
+
soft_signal_r_and_setter,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class LabXraySource(StrictEnum):
|
|
9
|
+
AL_KALPHA = 1486.6
|
|
10
|
+
MG_KALPHA = 1253.6
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LabXraySourceReadable(StandardReadable):
|
|
14
|
+
"""Simple device to get the laboratory x-ray tube energy reading"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, xraysource: LabXraySource, name: str = "") -> None:
|
|
17
|
+
with self.add_children_as_readables():
|
|
18
|
+
self.energy_ev, _ = soft_signal_r_and_setter(
|
|
19
|
+
float, initial_value=xraysource.value, units="eV"
|
|
20
|
+
)
|
|
21
|
+
super().__init__(name)
|
dodal/devices/pgm.py
CHANGED
dodal/devices/robot.py
CHANGED
|
@@ -7,6 +7,7 @@ from ophyd_async.core import (
|
|
|
7
7
|
AsyncStatus,
|
|
8
8
|
Device,
|
|
9
9
|
StandardReadable,
|
|
10
|
+
StandardReadableFormat,
|
|
10
11
|
StrictEnum,
|
|
11
12
|
set_and_wait_for_value,
|
|
12
13
|
wait_for_value,
|
|
@@ -74,18 +75,21 @@ class BartRobot(StandardReadable, Movable[SampleLocation]):
|
|
|
74
75
|
LOAD_TOLERANCE_MM = 0.02
|
|
75
76
|
|
|
76
77
|
def __init__(self, name: str, prefix: str) -> None:
|
|
77
|
-
self.
|
|
78
|
-
|
|
78
|
+
with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
|
|
79
|
+
self.barcode = epics_signal_r(str, prefix + "BARCODE")
|
|
80
|
+
self.gonio_pin_sensor = epics_signal_r(PinMounted, prefix + "PIN_MOUNTED")
|
|
81
|
+
|
|
82
|
+
self.current_puck = epics_signal_r(float, prefix + "CURRENT_PUCK_RBV")
|
|
83
|
+
self.current_pin = epics_signal_r(float, prefix + "CURRENT_PIN_RBV")
|
|
79
84
|
|
|
80
85
|
self.next_pin = epics_signal_rw_rbv(float, prefix + "NEXT_PIN")
|
|
81
86
|
self.next_puck = epics_signal_rw_rbv(float, prefix + "NEXT_PUCK")
|
|
82
|
-
self.current_puck = epics_signal_r(float, prefix + "CURRENT_PUCK_RBV")
|
|
83
|
-
self.current_pin = epics_signal_r(float, prefix + "CURRENT_PIN_RBV")
|
|
84
87
|
|
|
85
|
-
self.next_sample_id = epics_signal_rw_rbv(int, prefix + "NEXT_ID")
|
|
86
88
|
self.sample_id = epics_signal_r(int, prefix + "CURRENT_ID_RBV")
|
|
89
|
+
self.next_sample_id = epics_signal_rw_rbv(int, prefix + "NEXT_ID")
|
|
87
90
|
|
|
88
91
|
self.load = epics_signal_x(prefix + "LOAD.PROC")
|
|
92
|
+
self.unload = epics_signal_x(prefix + "UNLD.PROC")
|
|
89
93
|
self.program_running = epics_signal_r(bool, prefix + "PROGRAM_RUNNING")
|
|
90
94
|
self.program_name = epics_signal_r(str, prefix + "PROGRAM_NAME")
|
|
91
95
|
|
|
@@ -93,7 +97,7 @@ class BartRobot(StandardReadable, Movable[SampleLocation]):
|
|
|
93
97
|
self.controller_error = ErrorStatus(prefix + "CNTL")
|
|
94
98
|
|
|
95
99
|
self.reset = epics_signal_x(prefix + "RESET.PROC")
|
|
96
|
-
self.
|
|
100
|
+
self.abort = epics_signal_x(prefix + "ABORT.PROC")
|
|
97
101
|
self.init = epics_signal_x(prefix + "INIT.PROC")
|
|
98
102
|
self.soak = epics_signal_x(prefix + "SOAK.PROC")
|
|
99
103
|
self.home = epics_signal_x(prefix + "GOHM.PROC")
|
|
@@ -173,7 +177,7 @@ class BartRobot(StandardReadable, Movable[SampleLocation]):
|
|
|
173
177
|
self._load_pin_and_puck(value),
|
|
174
178
|
timeout=self.LOAD_TIMEOUT + self.NOT_BUSY_TIMEOUT,
|
|
175
179
|
)
|
|
176
|
-
except
|
|
180
|
+
except TimeoutError as e:
|
|
177
181
|
# Will only need to catch asyncio.TimeoutError after https://github.com/bluesky/ophyd-async/issues/572
|
|
178
182
|
await self.prog_error.raise_if_error(e)
|
|
179
183
|
await self.controller_error.raise_if_error(e)
|
dodal/devices/smargon.py
CHANGED
|
@@ -3,7 +3,7 @@ from collections.abc import Collection, Generator
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from enum import Enum
|
|
5
5
|
from math import isclose
|
|
6
|
-
from typing import TypedDict, cast
|
|
6
|
+
from typing import NotRequired, TypedDict, cast
|
|
7
7
|
|
|
8
8
|
from bluesky import plan_stubs as bps
|
|
9
9
|
from bluesky.protocols import Movable
|
|
@@ -11,14 +11,13 @@ from bluesky.utils import Msg
|
|
|
11
11
|
from ophyd_async.core import (
|
|
12
12
|
AsyncStatus,
|
|
13
13
|
Device,
|
|
14
|
-
StandardReadable,
|
|
15
14
|
StrictEnum,
|
|
16
15
|
wait_for_value,
|
|
17
16
|
)
|
|
18
17
|
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
19
18
|
from ophyd_async.epics.motor import Motor
|
|
20
|
-
from typing_extensions import NotRequired
|
|
21
19
|
|
|
20
|
+
from dodal.devices.motors import XYZStage
|
|
22
21
|
from dodal.devices.util.epics_util import SetWhenEnabled
|
|
23
22
|
|
|
24
23
|
|
|
@@ -116,7 +115,7 @@ class CombinedMove(TypedDict):
|
|
|
116
115
|
chi: NotRequired[float | None]
|
|
117
116
|
|
|
118
117
|
|
|
119
|
-
class Smargon(
|
|
118
|
+
class Smargon(XYZStage, Movable):
|
|
120
119
|
"""
|
|
121
120
|
Real motors added to allow stops following pin load (e.g. real_x1.stop() )
|
|
122
121
|
X1 and X2 real motors provide compound chi motion as well as the compound X travel,
|
|
@@ -126,9 +125,6 @@ class Smargon(StandardReadable, Movable):
|
|
|
126
125
|
|
|
127
126
|
def __init__(self, prefix: str = "", name: str = ""):
|
|
128
127
|
with self.add_children_as_readables():
|
|
129
|
-
self.x = Motor(prefix + "X")
|
|
130
|
-
self.y = Motor(prefix + "Y")
|
|
131
|
-
self.z = Motor(prefix + "Z")
|
|
132
128
|
self.chi = Motor(prefix + "CHI")
|
|
133
129
|
self.phi = Motor(prefix + "PHI")
|
|
134
130
|
self.omega = Motor(prefix + "OMEGA")
|
|
@@ -143,7 +139,7 @@ class Smargon(StandardReadable, Movable):
|
|
|
143
139
|
|
|
144
140
|
self.defer_move = epics_signal_rw(DeferMoves, prefix + "CS1:DeferMoves")
|
|
145
141
|
|
|
146
|
-
super().__init__(name)
|
|
142
|
+
super().__init__(prefix, name)
|
|
147
143
|
|
|
148
144
|
def get_xyz_limits(self) -> Generator[Msg, None, XYZLimits]:
|
|
149
145
|
"""Obtain a plan stub that returns the smargon XYZ axis limits
|
|
@@ -171,6 +167,9 @@ class Smargon(StandardReadable, Movable):
|
|
|
171
167
|
for k, v in value.items():
|
|
172
168
|
if v is not None:
|
|
173
169
|
tasks.append(getattr(self, k).set(v))
|
|
174
|
-
await asyncio.gather(*tasks)
|
|
175
170
|
finally:
|
|
176
171
|
await self.defer_move.set(DeferMoves.OFF)
|
|
172
|
+
# The set() coroutines will not complete until after defer moves has been
|
|
173
|
+
# switched back off so we cannot wait for them until this point.
|
|
174
|
+
# see https://github.com/DiamondLightSource/dodal/issues/1315
|
|
175
|
+
await asyncio.gather(*tasks)
|