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.
- {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/METADATA +2 -2
- {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/RECORD +70 -67
- {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/WHEEL +1 -1
- dodal/_version.py +2 -2
- dodal/beamlines/i22.py +24 -11
- dodal/beamlines/i24.py +4 -4
- dodal/beamlines/p38.py +23 -11
- dodal/common/beamlines/beamline_utils.py +1 -2
- dodal/common/crystal_metadata.py +61 -0
- dodal/common/signal_utils.py +10 -14
- dodal/devices/CTAB.py +1 -1
- dodal/devices/aperture.py +1 -1
- dodal/devices/aperturescatterguard.py +20 -8
- dodal/devices/apple2_undulator.py +30 -29
- dodal/devices/areadetector/plugins/CAM.py +3 -5
- dodal/devices/areadetector/plugins/MJPG.py +1 -1
- dodal/devices/attenuator.py +1 -1
- dodal/devices/backlight.py +4 -5
- dodal/devices/cryostream.py +3 -5
- dodal/devices/dcm.py +26 -2
- dodal/devices/detector/detector_motion.py +3 -5
- dodal/devices/diamond_filter.py +3 -4
- dodal/devices/fast_grid_scan.py +1 -1
- dodal/devices/fluorescence_detector_motion.py +5 -7
- dodal/devices/focusing_mirror.py +12 -11
- dodal/devices/hutch_shutter.py +4 -5
- dodal/devices/i10/i10_apple2.py +20 -19
- dodal/devices/i10/i10_setting_data.py +2 -2
- dodal/devices/i22/dcm.py +43 -75
- dodal/devices/i22/fswitch.py +5 -5
- dodal/devices/i24/aperture.py +3 -5
- dodal/devices/i24/beamstop.py +3 -5
- dodal/devices/i24/dcm.py +1 -1
- dodal/devices/i24/dual_backlight.py +4 -6
- dodal/devices/i24/pmac.py +35 -46
- dodal/devices/i24/vgonio.py +16 -0
- dodal/devices/ipin.py +5 -3
- dodal/devices/linkam3.py +7 -7
- dodal/devices/oav/oav_detector.py +3 -3
- dodal/devices/oav/oav_to_redis_forwarder.py +8 -7
- dodal/devices/oav/pin_image_recognition/__init__.py +9 -7
- dodal/devices/oav/snapshots/grid_overlay.py +16 -16
- dodal/devices/oav/snapshots/snapshot_with_beam_centre.py +5 -5
- dodal/devices/oav/snapshots/snapshot_with_grid.py +6 -6
- dodal/devices/oav/utils.py +2 -2
- dodal/devices/p99/sample_stage.py +3 -5
- dodal/devices/pgm.py +5 -6
- dodal/devices/qbpm.py +1 -1
- dodal/devices/robot.py +3 -3
- dodal/devices/smargon.py +1 -1
- dodal/devices/synchrotron.py +9 -4
- dodal/devices/tetramm.py +7 -7
- dodal/devices/thawer.py +13 -7
- dodal/devices/undulator.py +5 -5
- dodal/devices/util/epics_util.py +1 -1
- dodal/devices/watsonmarlow323_pump.py +45 -0
- dodal/devices/webcam.py +9 -2
- dodal/devices/xbpm_feedback.py +3 -5
- dodal/devices/xspress3/xspress3.py +8 -9
- dodal/devices/xspress3/xspress3_channel.py +3 -5
- dodal/devices/zebra.py +7 -6
- dodal/devices/zebra_controlled_shutter.py +5 -6
- dodal/devices/zocalo/__init__.py +2 -2
- dodal/devices/zocalo/zocalo_constants.py +3 -0
- dodal/devices/zocalo/zocalo_interaction.py +2 -1
- dodal/devices/zocalo/zocalo_results.py +92 -79
- dodal/utils.py +4 -0
- dodal/devices/i24/i24_vgonio.py +0 -17
- {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/LICENSE +0 -0
- {dls_dodal-1.34.1.dist-info → dls_dodal-1.35.0.dist-info}/entry_points.txt +0 -0
- {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:
|
|
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 (
|
|
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:
|
|
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:
|
|
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.
|
|
56
|
-
self.
|
|
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.
|
|
61
|
-
beam_y = await self.
|
|
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(
|
|
18
|
-
self.top_left_y = soft_signal_rw(
|
|
19
|
-
self.box_width = soft_signal_rw(
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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}")
|
dodal/devices/oav/utils.py
CHANGED
|
@@ -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
|
|
110
|
+
return Pixel((int(found_tip[0]), int(found_tip[1])))
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
from
|
|
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(
|
|
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[
|
|
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(
|
|
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
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.
|
|
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(
|
|
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
|
|
dodal/devices/synchrotron.py
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
-
from ophyd_async.core import
|
|
4
|
-
|
|
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(
|
|
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(
|
|
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.
|
|
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(
|
|
24
|
+
class TetrammRange(StrictEnum):
|
|
25
25
|
uA = "+- 120 uA"
|
|
26
26
|
nA = "+- 120 nA"
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
class TetrammTrigger(
|
|
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(
|
|
36
|
+
class TetrammChannels(StrictEnum):
|
|
37
37
|
One = "1"
|
|
38
38
|
Two = "2"
|
|
39
39
|
Four = "4"
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
class TetrammResolution(
|
|
42
|
+
class TetrammResolution(StrictEnum):
|
|
43
43
|
SixteenBits = "16 bits"
|
|
44
44
|
TwentyFourBits = "24 bits"
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
class TetrammGeometry(
|
|
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
|
|
6
|
-
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
39
|
+
await self._control_signal_ref().set(ThawerStates.OFF)
|
|
34
40
|
|
|
35
41
|
@AsyncStatus.wrap
|
|
36
42
|
async def stop(self, *args, **kwargs):
|
dodal/devices/undulator.py
CHANGED
|
@@ -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(
|
|
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(
|
|
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,
|
dodal/devices/util/epics_util.py
CHANGED
|
@@ -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.
|
|
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
|
|
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(
|
|
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):
|
dodal/devices/xbpm_feedback.py
CHANGED
|
@@ -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.
|
|
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(
|
|
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.
|
|
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(
|
|
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(
|
|
37
|
+
class UpdateRBV(StrictEnum):
|
|
39
38
|
DISABLED = "Disabled"
|
|
40
39
|
ENABLED = "Enabled"
|
|
41
40
|
|
|
42
41
|
|
|
43
|
-
class AcquireRBVState(
|
|
42
|
+
class AcquireRBVState(StrictEnum):
|
|
44
43
|
DONE = "Done"
|
|
45
44
|
ACQUIRE = "Acquiring"
|
|
46
45
|
|
|
47
46
|
|
|
48
|
-
class DetectorState(
|
|
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(
|
|
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
|
|
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.
|
|
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(
|
|
50
|
+
class ArmSource(StrictEnum):
|
|
50
51
|
SOFT = "Soft"
|
|
51
52
|
EXTERNAL = "External"
|
|
52
53
|
|
|
53
54
|
|
|
54
|
-
class TrigSource(
|
|
55
|
+
class TrigSource(StrictEnum):
|
|
55
56
|
POSITION = "Position"
|
|
56
57
|
TIME = "Time"
|
|
57
58
|
EXTERNAL = "External"
|
|
58
59
|
|
|
59
60
|
|
|
60
|
-
class EncEnum(
|
|
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(
|
|
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(
|
|
97
|
+
class SoftInState(StrictEnum):
|
|
97
98
|
YES = "Yes"
|
|
98
99
|
NO = "No"
|
|
99
100
|
|