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
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import abc
|
|
2
2
|
import asyncio
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from enum import Enum
|
|
5
4
|
from typing import Any
|
|
6
5
|
|
|
7
6
|
import numpy as np
|
|
8
7
|
from bluesky.protocols import Movable
|
|
9
8
|
from ophyd_async.core import (
|
|
10
9
|
AsyncStatus,
|
|
11
|
-
|
|
12
|
-
HintedSignal,
|
|
10
|
+
Reference,
|
|
13
11
|
StandardReadable,
|
|
12
|
+
StandardReadableFormat,
|
|
13
|
+
StrictEnum,
|
|
14
14
|
soft_signal_r_and_setter,
|
|
15
15
|
wait_for_value,
|
|
16
16
|
)
|
|
17
|
-
from ophyd_async.epics.
|
|
17
|
+
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw, epics_signal_w
|
|
18
18
|
from pydantic import BaseModel, ConfigDict, RootModel
|
|
19
19
|
|
|
20
20
|
from dodal.log import LOGGER
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class UndulatorGateStatus(
|
|
23
|
+
class UndulatorGateStatus(StrictEnum):
|
|
24
24
|
open = "Open"
|
|
25
25
|
close = "Closed"
|
|
26
26
|
|
|
@@ -128,12 +128,12 @@ class UndulatorGap(StandardReadable, Movable):
|
|
|
128
128
|
)
|
|
129
129
|
# This is calculated acceleration from speed
|
|
130
130
|
self.acceleration_time = epics_signal_r(float, prefix + "IDGSETACC")
|
|
131
|
-
with self.add_children_as_readables(
|
|
131
|
+
with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
|
|
132
132
|
# Unit
|
|
133
133
|
self.motor_egu = epics_signal_r(str, prefix + "BLGAPMTR.EGU")
|
|
134
134
|
# Gap velocity
|
|
135
135
|
self.velocity = epics_signal_rw(float, prefix + "BLGSETVEL")
|
|
136
|
-
with self.add_children_as_readables(
|
|
136
|
+
with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
|
|
137
137
|
# Gap readback value
|
|
138
138
|
self.user_readback = epics_signal_r(float, prefix + "CURRGAPD")
|
|
139
139
|
super().__init__(name)
|
|
@@ -187,10 +187,10 @@ class UndulatorPhaseMotor(StandardReadable):
|
|
|
187
187
|
self.user_setpoint_demand_readback = epics_signal_r(float, fullPV + "DMD")
|
|
188
188
|
|
|
189
189
|
fullPV = fullPV + "MTR"
|
|
190
|
-
with self.add_children_as_readables(
|
|
190
|
+
with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
|
|
191
191
|
self.user_setpoint_readback = epics_signal_r(float, fullPV + ".RBV")
|
|
192
192
|
|
|
193
|
-
with self.add_children_as_readables(
|
|
193
|
+
with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
|
|
194
194
|
self.motor_egu = epics_signal_r(str, fullPV + ".EGU")
|
|
195
195
|
self.velocity = epics_signal_rw(float, fullPV + ".VELO")
|
|
196
196
|
|
|
@@ -388,10 +388,10 @@ class Apple2(StandardReadable, Movable):
|
|
|
388
388
|
|
|
389
389
|
# Attributes are set after super call so they are not renamed to
|
|
390
390
|
# <name>-undulator, etc.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
with self.add_children_as_readables(
|
|
391
|
+
self.gap = Reference(id_gap)
|
|
392
|
+
self.phase = Reference(id_phase)
|
|
393
|
+
|
|
394
|
+
with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
|
|
395
395
|
# Store the polarisation for readback.
|
|
396
396
|
self.polarisation, self._polarisation_set = soft_signal_r_and_setter(
|
|
397
397
|
str, initial_value=None
|
|
@@ -437,16 +437,16 @@ class Apple2(StandardReadable, Movable):
|
|
|
437
437
|
"""
|
|
438
438
|
|
|
439
439
|
# Only need to check gap as the phase motors share both fault and gate with gap.
|
|
440
|
-
await self.gap.check_id_status()
|
|
440
|
+
await self.gap().check_id_status()
|
|
441
441
|
await asyncio.gather(
|
|
442
|
-
self.phase.top_outer.user_setpoint.set(value=value.top_outer),
|
|
443
|
-
self.phase.top_inner.user_setpoint.set(value=value.top_inner),
|
|
444
|
-
self.phase.btm_inner.user_setpoint.set(value=value.btm_inner),
|
|
445
|
-
self.phase.btm_outer.user_setpoint.set(value=value.btm_outer),
|
|
446
|
-
self.gap.user_setpoint.set(value=value.gap),
|
|
442
|
+
self.phase().top_outer.user_setpoint.set(value=value.top_outer),
|
|
443
|
+
self.phase().top_inner.user_setpoint.set(value=value.top_inner),
|
|
444
|
+
self.phase().btm_inner.user_setpoint.set(value=value.btm_inner),
|
|
445
|
+
self.phase().btm_outer.user_setpoint.set(value=value.btm_outer),
|
|
446
|
+
self.gap().user_setpoint.set(value=value.gap),
|
|
447
447
|
)
|
|
448
448
|
timeout = np.max(
|
|
449
|
-
await asyncio.gather(self.gap.get_timeout(), self.phase.get_timeout())
|
|
449
|
+
await asyncio.gather(self.gap().get_timeout(), self.phase().get_timeout())
|
|
450
450
|
)
|
|
451
451
|
LOGGER.info(
|
|
452
452
|
f"Moving f{self.name} energy and polorisation to {energy}, {self.pol}"
|
|
@@ -454,10 +454,12 @@ class Apple2(StandardReadable, Movable):
|
|
|
454
454
|
)
|
|
455
455
|
|
|
456
456
|
await asyncio.gather(
|
|
457
|
-
self.gap.set_move.set(value=1, timeout=timeout),
|
|
458
|
-
self.phase.set_move.set(value=1, timeout=timeout),
|
|
457
|
+
self.gap().set_move.set(value=1, timeout=timeout),
|
|
458
|
+
self.phase().set_move.set(value=1, timeout=timeout),
|
|
459
|
+
)
|
|
460
|
+
await wait_for_value(
|
|
461
|
+
self.gap().gate, UndulatorGateStatus.close, timeout=timeout
|
|
459
462
|
)
|
|
460
|
-
await wait_for_value(self.gap.gate, UndulatorGateStatus.close, timeout=timeout)
|
|
461
463
|
self._energy_set(energy) # Update energy for after move for readback.
|
|
462
464
|
|
|
463
465
|
def _get_id_gap_phase(self, energy: float) -> tuple[float, float]:
|
|
@@ -522,12 +524,11 @@ class Apple2(StandardReadable, Movable):
|
|
|
522
524
|
(May be for future one can use the inverse poly to work out the energy and try to match it with the current energy
|
|
523
525
|
to workout the polarisation but during my test the inverse poly is too unstable for general use.)
|
|
524
526
|
"""
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
gap = cur_loc[self.gap.user_readback.name]["value"]
|
|
527
|
+
top_outer = await self.phase().top_outer.user_setpoint_readback.get_value()
|
|
528
|
+
top_inner = await self.phase().top_inner.user_setpoint_readback.get_value()
|
|
529
|
+
btm_inner = await self.phase().btm_inner.user_setpoint_readback.get_value()
|
|
530
|
+
btm_outer = await self.phase().btm_outer.user_setpoint_readback.get_value()
|
|
531
|
+
gap = await self.gap().user_readback.get_value()
|
|
531
532
|
if gap > MAXIMUM_GAP_MOTOR_POSITION:
|
|
532
533
|
raise RuntimeError(
|
|
533
534
|
f"{self.name} is not in use, close gap or set polarisation to use this ID"
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
from
|
|
1
|
+
from ophyd_async.core import StandardReadable, StrictEnum
|
|
2
|
+
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
2
3
|
|
|
3
|
-
from ophyd_async.core import StandardReadable
|
|
4
|
-
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
class ColorMode(str, Enum):
|
|
5
|
+
class ColorMode(StrictEnum):
|
|
8
6
|
"""
|
|
9
7
|
Enum to store the various color modes of the camera. We use RGB1.
|
|
10
8
|
"""
|
|
@@ -6,7 +6,7 @@ import aiofiles
|
|
|
6
6
|
from aiohttp import ClientSession
|
|
7
7
|
from bluesky.protocols import Triggerable
|
|
8
8
|
from ophyd_async.core import AsyncStatus, StandardReadable, soft_signal_rw
|
|
9
|
-
from ophyd_async.epics.
|
|
9
|
+
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
10
10
|
from PIL import Image
|
|
11
11
|
|
|
12
12
|
from dodal.log import LOGGER
|
dodal/devices/attenuator.py
CHANGED
|
@@ -9,7 +9,7 @@ from ophyd_async.core import (
|
|
|
9
9
|
StandardReadable,
|
|
10
10
|
wait_for_value,
|
|
11
11
|
)
|
|
12
|
-
from ophyd_async.epics.
|
|
12
|
+
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw, epics_signal_x
|
|
13
13
|
|
|
14
14
|
from dodal.log import LOGGER
|
|
15
15
|
|
dodal/devices/backlight.py
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
from asyncio import sleep
|
|
2
|
-
from enum import Enum
|
|
3
2
|
|
|
4
3
|
from bluesky.protocols import Movable
|
|
5
|
-
from ophyd_async.core import AsyncStatus, StandardReadable
|
|
6
|
-
from ophyd_async.epics.
|
|
4
|
+
from ophyd_async.core import AsyncStatus, StandardReadable, StrictEnum
|
|
5
|
+
from ophyd_async.epics.core import epics_signal_rw
|
|
7
6
|
|
|
8
7
|
|
|
9
|
-
class BacklightPower(
|
|
8
|
+
class BacklightPower(StrictEnum):
|
|
10
9
|
ON = "On"
|
|
11
10
|
OFF = "Off"
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
class BacklightPosition(
|
|
13
|
+
class BacklightPosition(StrictEnum):
|
|
15
14
|
IN = "In"
|
|
16
15
|
OUT = "Out"
|
|
17
16
|
|
dodal/devices/cryostream.py
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
from
|
|
1
|
+
from ophyd_async.core import StandardReadable, StrictEnum
|
|
2
|
+
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
2
3
|
|
|
3
|
-
from ophyd_async.core import StandardReadable
|
|
4
|
-
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
class InOut(str, Enum):
|
|
5
|
+
class InOut(StrictEnum):
|
|
8
6
|
IN = "In"
|
|
9
7
|
OUT = "Out"
|
|
10
8
|
|
dodal/devices/dcm.py
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import numpy as np
|
|
2
|
+
from numpy.typing import NDArray
|
|
3
|
+
from ophyd_async.core import StandardReadable, soft_signal_r_and_setter
|
|
4
|
+
from ophyd_async.epics.core import epics_signal_r
|
|
2
5
|
from ophyd_async.epics.motor import Motor
|
|
3
|
-
|
|
6
|
+
|
|
7
|
+
from dodal.common.crystal_metadata import (
|
|
8
|
+
CrystalMetadata,
|
|
9
|
+
MaterialsEnum,
|
|
10
|
+
make_crystal_metadata_from_material,
|
|
11
|
+
)
|
|
4
12
|
|
|
5
13
|
|
|
6
14
|
class DCM(StandardReadable):
|
|
@@ -17,7 +25,11 @@ class DCM(StandardReadable):
|
|
|
17
25
|
self,
|
|
18
26
|
prefix: str,
|
|
19
27
|
name: str = "",
|
|
28
|
+
crystal_metadata: CrystalMetadata | None = None,
|
|
20
29
|
) -> None:
|
|
30
|
+
cm = crystal_metadata or make_crystal_metadata_from_material(
|
|
31
|
+
MaterialsEnum.Si, (1, 1, 1)
|
|
32
|
+
)
|
|
21
33
|
with self.add_children_as_readables():
|
|
22
34
|
self.bragg_in_degrees = Motor(prefix + "BRAGG")
|
|
23
35
|
self.roll_in_mrad = Motor(prefix + "ROLL")
|
|
@@ -36,4 +48,16 @@ class DCM(StandardReadable):
|
|
|
36
48
|
self.perp_temp = epics_signal_r(float, prefix + "TEMP6")
|
|
37
49
|
self.perp_sub_assembly_temp = epics_signal_r(float, prefix + "TEMP7")
|
|
38
50
|
|
|
51
|
+
self.crystal_metadata_usage, _ = soft_signal_r_and_setter(
|
|
52
|
+
str, initial_value=cm.usage
|
|
53
|
+
)
|
|
54
|
+
self.crystal_metadata_type, _ = soft_signal_r_and_setter(
|
|
55
|
+
str, initial_value=cm.type
|
|
56
|
+
)
|
|
57
|
+
reflection_array = np.array(cm.reflection)
|
|
58
|
+
self.crystal_metadata_reflection, _ = soft_signal_r_and_setter(
|
|
59
|
+
NDArray[np.uint64],
|
|
60
|
+
initial_value=reflection_array,
|
|
61
|
+
)
|
|
62
|
+
self.crystal_metadata_d_spacing = epics_signal_r(float, "DSPACING:RBV")
|
|
39
63
|
super().__init__(name)
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from ophyd_async.core import Device
|
|
1
|
+
from ophyd_async.core import Device, StrictEnum
|
|
2
|
+
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
4
3
|
from ophyd_async.epics.motor import Motor
|
|
5
|
-
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
|
|
6
4
|
|
|
7
5
|
|
|
8
|
-
class ShutterState(
|
|
6
|
+
class ShutterState(StrictEnum):
|
|
9
7
|
CLOSED = "Closed"
|
|
10
8
|
OPEN = "Open"
|
|
11
9
|
|
dodal/devices/diamond_filter.py
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
1
|
from typing import Generic, TypeVar
|
|
3
2
|
|
|
4
|
-
from ophyd_async.core import StandardReadable
|
|
3
|
+
from ophyd_async.core import StandardReadable, StrictEnum
|
|
4
|
+
from ophyd_async.epics.core import epics_signal_rw
|
|
5
5
|
from ophyd_async.epics.motor import Motor
|
|
6
|
-
from ophyd_async.epics.signal import epics_signal_rw
|
|
7
6
|
|
|
8
7
|
|
|
9
|
-
class _Filters(
|
|
8
|
+
class _Filters(StrictEnum):
|
|
10
9
|
pass
|
|
11
10
|
|
|
12
11
|
|
dodal/devices/fast_grid_scan.py
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
from
|
|
1
|
+
from ophyd_async.core import StandardReadable, StrictEnum
|
|
2
|
+
from ophyd_async.epics.core import epics_signal_r
|
|
2
3
|
|
|
3
|
-
from ophyd_async.core import StandardReadable
|
|
4
|
-
from ophyd_async.epics.signal import epics_signal_r
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
IN = 1
|
|
5
|
+
class FluorescenceDetectorControlState(StrictEnum):
|
|
6
|
+
OUT = "Out"
|
|
7
|
+
IN = "In"
|
|
10
8
|
|
|
11
9
|
|
|
12
10
|
class FluorescenceDetector(StandardReadable):
|
dodal/devices/focusing_mirror.py
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
|
-
|
|
3
1
|
from ophyd_async.core import (
|
|
4
2
|
AsyncStatus,
|
|
5
|
-
ConfigSignal,
|
|
6
3
|
Device,
|
|
7
4
|
DeviceVector,
|
|
8
|
-
HintedSignal,
|
|
9
5
|
StandardReadable,
|
|
6
|
+
StandardReadableFormat,
|
|
7
|
+
StrictEnum,
|
|
10
8
|
observe_value,
|
|
11
9
|
soft_signal_r_and_setter,
|
|
12
10
|
)
|
|
13
|
-
from ophyd_async.epics.
|
|
14
|
-
from ophyd_async.epics.signal import (
|
|
11
|
+
from ophyd_async.epics.core import (
|
|
15
12
|
epics_signal_r,
|
|
16
13
|
epics_signal_rw,
|
|
17
14
|
epics_signal_x,
|
|
18
15
|
)
|
|
16
|
+
from ophyd_async.epics.motor import Motor
|
|
19
17
|
|
|
20
18
|
from dodal.log import LOGGER
|
|
21
19
|
|
|
@@ -25,20 +23,20 @@ VOLTAGE_POLLING_DELAY_S = 0.5
|
|
|
25
23
|
DEFAULT_SETTLE_TIME_S = 60
|
|
26
24
|
|
|
27
25
|
|
|
28
|
-
class MirrorType(
|
|
26
|
+
class MirrorType(StrictEnum):
|
|
29
27
|
"""See https://manual.nexusformat.org/classes/base_classes/NXmirror.html"""
|
|
30
28
|
|
|
31
29
|
SINGLE = "single"
|
|
32
30
|
MULTI = "multi"
|
|
33
31
|
|
|
34
32
|
|
|
35
|
-
class MirrorStripe(
|
|
33
|
+
class MirrorStripe(StrictEnum):
|
|
36
34
|
RHODIUM = "Rhodium"
|
|
37
35
|
BARE = "Bare"
|
|
38
36
|
PLATINUM = "Platinum"
|
|
39
37
|
|
|
40
38
|
|
|
41
|
-
class MirrorVoltageDemand(
|
|
39
|
+
class MirrorVoltageDemand(StrictEnum):
|
|
42
40
|
N_A = "N/A"
|
|
43
41
|
OK = "OK"
|
|
44
42
|
FAIL = "FAIL"
|
|
@@ -151,8 +149,11 @@ class FocusingMirror(StandardReadable):
|
|
|
151
149
|
# regardless of orientation of the mirror
|
|
152
150
|
self.incident_angle = Motor(prefix + "PITCH")
|
|
153
151
|
|
|
154
|
-
self.add_readables(
|
|
155
|
-
|
|
152
|
+
self.add_readables(
|
|
153
|
+
[self.incident_angle.user_readback],
|
|
154
|
+
format=StandardReadableFormat.HINTED_SIGNAL,
|
|
155
|
+
)
|
|
156
|
+
self.add_readables([self.type], format=StandardReadableFormat.CONFIG_SIGNAL)
|
|
156
157
|
super().__init__(name)
|
|
157
158
|
|
|
158
159
|
|
dodal/devices/hutch_shutter.py
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
|
-
|
|
3
1
|
from bluesky.protocols import Movable
|
|
4
2
|
from ophyd_async.core import (
|
|
5
3
|
DEFAULT_TIMEOUT,
|
|
6
4
|
AsyncStatus,
|
|
7
5
|
StandardReadable,
|
|
6
|
+
StrictEnum,
|
|
8
7
|
wait_for_value,
|
|
9
8
|
)
|
|
10
|
-
from ophyd_async.epics.
|
|
9
|
+
from ophyd_async.epics.core import epics_signal_r, epics_signal_w
|
|
11
10
|
|
|
12
11
|
HUTCH_SAFE_FOR_OPERATIONS = 0 # Hutch is locked and can't be entered
|
|
13
12
|
|
|
@@ -16,13 +15,13 @@ class ShutterNotSafeToOperateError(Exception):
|
|
|
16
15
|
pass
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
class ShutterDemand(
|
|
18
|
+
class ShutterDemand(StrictEnum):
|
|
20
19
|
OPEN = "Open"
|
|
21
20
|
CLOSE = "Close"
|
|
22
21
|
RESET = "Reset"
|
|
23
22
|
|
|
24
23
|
|
|
25
|
-
class ShutterState(
|
|
24
|
+
class ShutterState(StrictEnum):
|
|
26
25
|
FAULT = "Fault"
|
|
27
26
|
OPEN = "Open"
|
|
28
27
|
OPENING = "Opening"
|
dodal/devices/i10/i10_apple2.py
CHANGED
|
@@ -2,14 +2,15 @@ import asyncio
|
|
|
2
2
|
import csv
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any, SupportsFloat
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
from bluesky.protocols import Movable
|
|
9
9
|
from ophyd_async.core import (
|
|
10
10
|
AsyncStatus,
|
|
11
|
-
|
|
11
|
+
Reference,
|
|
12
12
|
StandardReadable,
|
|
13
|
+
StandardReadableFormat,
|
|
13
14
|
soft_signal_r_and_setter,
|
|
14
15
|
soft_signal_rw,
|
|
15
16
|
)
|
|
@@ -118,14 +119,15 @@ class I10Apple2(Apple2):
|
|
|
118
119
|
name=name,
|
|
119
120
|
)
|
|
120
121
|
with self.add_children_as_readables():
|
|
121
|
-
self.id_jaw_phase = id_jaw_phase
|
|
122
|
+
self.id_jaw_phase = Reference(id_jaw_phase)
|
|
122
123
|
|
|
123
124
|
@AsyncStatus.wrap
|
|
124
|
-
async def set(self, value:
|
|
125
|
+
async def set(self, value: SupportsFloat) -> None:
|
|
125
126
|
"""
|
|
126
127
|
Check polarisation state and use it together with the energy(value)
|
|
127
128
|
to calculate the required gap and phases before setting it.
|
|
128
129
|
"""
|
|
130
|
+
value = float(value)
|
|
129
131
|
if self.pol is None:
|
|
130
132
|
LOGGER.warning("Polarisation not set attempting to read from hardware")
|
|
131
133
|
pol, phase = await self.determinePhaseFromHardware()
|
|
@@ -146,8 +148,8 @@ class I10Apple2(Apple2):
|
|
|
146
148
|
LOGGER.info(f"Setting polarisation to {self.pol}, with {id_set_val}")
|
|
147
149
|
await self._set(value=id_set_val, energy=value)
|
|
148
150
|
if self.pol != "la":
|
|
149
|
-
await self.id_jaw_phase.set(0)
|
|
150
|
-
await self.id_jaw_phase.set_move.set(1)
|
|
151
|
+
await self.id_jaw_phase().set(0)
|
|
152
|
+
await self.id_jaw_phase().set_move.set(1)
|
|
151
153
|
|
|
152
154
|
def update_lookuptable(self):
|
|
153
155
|
"""
|
|
@@ -195,18 +197,17 @@ class I10Apple2PGM(StandardReadable, Movable):
|
|
|
195
197
|
New device name.
|
|
196
198
|
"""
|
|
197
199
|
super().__init__(name=name)
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
with self.add_children_as_readables(HintedSignal):
|
|
200
|
+
self.id_ref = Reference(id)
|
|
201
|
+
self.pgm_ref = Reference(pgm)
|
|
202
|
+
with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
|
|
202
203
|
self.energy_offset = soft_signal_rw(float, initial_value=0)
|
|
203
204
|
|
|
204
205
|
@AsyncStatus.wrap
|
|
205
206
|
async def set(self, value: float) -> None:
|
|
206
207
|
LOGGER.info(f"Moving f{self.name} energy to {value}.")
|
|
207
208
|
await asyncio.gather(
|
|
208
|
-
self.
|
|
209
|
-
self.
|
|
209
|
+
self.id_ref().set(value=value + await self.energy_offset.get_value()),
|
|
210
|
+
self.pgm_ref().energy.set(value),
|
|
210
211
|
)
|
|
211
212
|
|
|
212
213
|
|
|
@@ -273,22 +274,22 @@ class LinearArbitraryAngle(StandardReadable, Movable):
|
|
|
273
274
|
polynomial parameters highest power first.
|
|
274
275
|
"""
|
|
275
276
|
super().__init__(name=name)
|
|
276
|
-
|
|
277
|
-
self.id = id
|
|
277
|
+
self.id_ref = Reference(id)
|
|
278
278
|
self.jaw_phase_from_angle = np.poly1d(jaw_phase_poly_param)
|
|
279
279
|
self.angle_threshold_deg = angle_threshold_deg
|
|
280
280
|
self.jaw_phase_limit = jaw_phase_limit
|
|
281
|
-
with self.add_children_as_readables(
|
|
281
|
+
with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
|
|
282
282
|
self.angle, self._angle_set = soft_signal_r_and_setter(
|
|
283
283
|
float, initial_value=None
|
|
284
284
|
)
|
|
285
285
|
|
|
286
286
|
@AsyncStatus.wrap
|
|
287
|
-
async def set(self, value:
|
|
288
|
-
|
|
287
|
+
async def set(self, value: SupportsFloat) -> None:
|
|
288
|
+
value = float(value)
|
|
289
|
+
pol = self.id_ref().pol
|
|
289
290
|
if pol != "la":
|
|
290
291
|
raise RuntimeError(
|
|
291
|
-
f"Angle control is not available in polarisation {pol} with {self.
|
|
292
|
+
f"Angle control is not available in polarisation {pol} with {self.id_ref().name}"
|
|
292
293
|
)
|
|
293
294
|
# Moving to real angle which is 210 to 30.
|
|
294
295
|
alpha_real = value if value > self.angle_threshold_deg else value + ALPHA_OFFSET
|
|
@@ -298,7 +299,7 @@ class LinearArbitraryAngle(StandardReadable, Movable):
|
|
|
298
299
|
f"jaw_phase position for angle ({value}) is outside permitted range"
|
|
299
300
|
f" [-{self.jaw_phase_limit}, {self.jaw_phase_limit}]"
|
|
300
301
|
)
|
|
301
|
-
await self.
|
|
302
|
+
await self.id_ref().id_jaw_phase().set(jaw_phase)
|
|
302
303
|
self._angle_set(value)
|
|
303
304
|
|
|
304
305
|
|