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
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from ophyd_async.core import StrictEnum, SupersetEnum
|
|
2
|
+
|
|
1
3
|
from dodal.devices.electron_analyser.abstract.base_driver_io import (
|
|
2
4
|
AbstractAnalyserDriverIO,
|
|
3
5
|
)
|
|
@@ -18,15 +20,29 @@ from dodal.devices.electron_analyser.vgscienta.detector import (
|
|
|
18
20
|
VGScientaDetector,
|
|
19
21
|
)
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
AnyAcqMode = StrictEnum
|
|
24
|
+
AnyLensMode = SupersetEnum | StrictEnum
|
|
25
|
+
|
|
26
|
+
# Electron analyser types that encompasses all implementations, useful for tests and
|
|
27
|
+
# plans
|
|
28
|
+
ElectronAnalyserDetectorImpl = (
|
|
29
|
+
VGScientaDetector[AnyLensMode] | SpecsDetector[AnyLensMode]
|
|
30
|
+
)
|
|
31
|
+
ElectronAnalyserDriverImpl = (
|
|
32
|
+
VGScientaAnalyserDriverIO[AnyLensMode] | SpecsAnalyserDriverIO[AnyLensMode]
|
|
33
|
+
)
|
|
23
34
|
|
|
35
|
+
# Short hand the type so less verbose
|
|
36
|
+
AbstractBaseRegion = AbstractBaseRegion[AnyAcqMode, AnyLensMode]
|
|
37
|
+
|
|
38
|
+
# Generic electron analyser types that supports full typing with the abstract classes.
|
|
24
39
|
GenericElectronAnalyserDetector = ElectronAnalyserDetector[
|
|
25
|
-
AbstractAnalyserDriverIO[AbstractBaseRegion],
|
|
26
|
-
AbstractBaseSequence,
|
|
40
|
+
AbstractAnalyserDriverIO[AbstractBaseRegion, AnyAcqMode, AnyLensMode],
|
|
41
|
+
AbstractBaseSequence[AbstractBaseRegion, AnyLensMode],
|
|
27
42
|
AbstractBaseRegion,
|
|
28
43
|
]
|
|
29
44
|
|
|
30
45
|
GenericElectronAnalyserRegionDetector = ElectronAnalyserRegionDetector[
|
|
31
|
-
AbstractAnalyserDriverIO[AbstractBaseRegion],
|
|
46
|
+
AbstractAnalyserDriverIO[AbstractBaseRegion, AnyAcqMode, AnyLensMode],
|
|
47
|
+
AbstractBaseRegion,
|
|
32
48
|
]
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from typing import Generic
|
|
3
|
+
|
|
4
|
+
from ophyd_async.core import SignalR
|
|
5
|
+
|
|
6
|
+
from dodal.devices.electron_analyser.abstract.base_region import TLensMode
|
|
1
7
|
from dodal.devices.electron_analyser.detector import (
|
|
2
8
|
ElectronAnalyserDetector,
|
|
3
9
|
)
|
|
@@ -12,11 +18,20 @@ from dodal.devices.electron_analyser.vgscienta.region import (
|
|
|
12
18
|
|
|
13
19
|
class VGScientaDetector(
|
|
14
20
|
ElectronAnalyserDetector[
|
|
15
|
-
VGScientaAnalyserDriverIO,
|
|
16
|
-
VGScientaSequence,
|
|
17
|
-
VGScientaRegion,
|
|
18
|
-
]
|
|
21
|
+
VGScientaAnalyserDriverIO[TLensMode],
|
|
22
|
+
VGScientaSequence[TLensMode],
|
|
23
|
+
VGScientaRegion[TLensMode],
|
|
24
|
+
],
|
|
25
|
+
Generic[TLensMode],
|
|
19
26
|
):
|
|
20
|
-
def __init__(
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
prefix: str,
|
|
30
|
+
lens_mode_type: type[TLensMode],
|
|
31
|
+
energy_sources: Mapping[str, SignalR[float]],
|
|
32
|
+
name: str = "",
|
|
33
|
+
):
|
|
34
|
+
driver = VGScientaAnalyserDriverIO[TLensMode](
|
|
35
|
+
prefix, lens_mode_type, energy_sources
|
|
36
|
+
)
|
|
37
|
+
super().__init__(VGScientaSequence[lens_mode_type], driver, name)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
from collections.abc import Mapping
|
|
3
|
+
from typing import Generic
|
|
2
4
|
|
|
3
5
|
import numpy as np
|
|
4
6
|
from ophyd_async.core import (
|
|
@@ -13,6 +15,7 @@ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
|
13
15
|
from dodal.devices.electron_analyser.abstract.base_driver_io import (
|
|
14
16
|
AbstractAnalyserDriverIO,
|
|
15
17
|
)
|
|
18
|
+
from dodal.devices.electron_analyser.abstract.base_region import TLensMode
|
|
16
19
|
from dodal.devices.electron_analyser.util import to_kinetic_energy
|
|
17
20
|
from dodal.devices.electron_analyser.vgscienta.enums import AcquisitionMode
|
|
18
21
|
from dodal.devices.electron_analyser.vgscienta.region import (
|
|
@@ -21,8 +24,17 @@ from dodal.devices.electron_analyser.vgscienta.region import (
|
|
|
21
24
|
)
|
|
22
25
|
|
|
23
26
|
|
|
24
|
-
class VGScientaAnalyserDriverIO(
|
|
25
|
-
|
|
27
|
+
class VGScientaAnalyserDriverIO(
|
|
28
|
+
AbstractAnalyserDriverIO[VGScientaRegion, AcquisitionMode, TLensMode],
|
|
29
|
+
Generic[TLensMode],
|
|
30
|
+
):
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
prefix: str,
|
|
34
|
+
lens_mode_type: type[TLensMode],
|
|
35
|
+
energy_sources: Mapping[str, SignalR[float]],
|
|
36
|
+
name: str = "",
|
|
37
|
+
) -> None:
|
|
26
38
|
with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
|
|
27
39
|
# Used for setting up region data acquisition.
|
|
28
40
|
self.centre_energy = epics_signal_rw(float, prefix + "CENTRE_ENERGY")
|
|
@@ -32,14 +44,10 @@ class VGScientaAnalyserDriverIO(AbstractAnalyserDriverIO[VGScientaRegion]):
|
|
|
32
44
|
self.y_channel_size = epics_signal_rw(int, prefix + "SizeY")
|
|
33
45
|
self.detector_mode = epics_signal_rw(DetectorMode, prefix + "DETECTOR_MODE")
|
|
34
46
|
|
|
35
|
-
|
|
36
|
-
# Used to read detector data after acqusition.
|
|
37
|
-
self.external_io = epics_signal_r(Array1D[np.float64], prefix + "EXTIO")
|
|
38
|
-
|
|
39
|
-
super().__init__(prefix, AcquisitionMode, name)
|
|
47
|
+
super().__init__(prefix, AcquisitionMode, lens_mode_type, energy_sources, name)
|
|
40
48
|
|
|
41
49
|
@AsyncStatus.wrap
|
|
42
|
-
async def set(self, region: VGScientaRegion):
|
|
50
|
+
async def set(self, region: VGScientaRegion[TLensMode]):
|
|
43
51
|
await super().set(region)
|
|
44
52
|
|
|
45
53
|
excitation_energy = await self.excitation_energy.get_value()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import uuid
|
|
2
|
+
from typing import Generic
|
|
2
3
|
|
|
3
4
|
from pydantic import Field
|
|
4
5
|
|
|
@@ -6,6 +7,7 @@ from dodal.devices.electron_analyser.abstract.base_region import (
|
|
|
6
7
|
AbstractBaseRegion,
|
|
7
8
|
AbstractBaseSequence,
|
|
8
9
|
JavaToPythonModel,
|
|
10
|
+
TLensMode,
|
|
9
11
|
)
|
|
10
12
|
from dodal.devices.electron_analyser.vgscienta.enums import (
|
|
11
13
|
AcquisitionMode,
|
|
@@ -14,9 +16,11 @@ from dodal.devices.electron_analyser.vgscienta.enums import (
|
|
|
14
16
|
)
|
|
15
17
|
|
|
16
18
|
|
|
17
|
-
class VGScientaRegion(
|
|
19
|
+
class VGScientaRegion(
|
|
20
|
+
AbstractBaseRegion[AcquisitionMode, TLensMode], Generic[TLensMode]
|
|
21
|
+
):
|
|
18
22
|
# Override defaults of base region class
|
|
19
|
-
lens_mode:
|
|
23
|
+
lens_mode: TLensMode
|
|
20
24
|
pass_energy: int = 5
|
|
21
25
|
acquisition_mode: AcquisitionMode = AcquisitionMode.SWEPT
|
|
22
26
|
low_energy: float = 8.0
|
|
@@ -28,7 +32,6 @@ class VGScientaRegion(AbstractBaseRegion[AcquisitionMode]):
|
|
|
28
32
|
fix_energy: float = 9.0
|
|
29
33
|
total_steps: float = 13.0
|
|
30
34
|
total_time: float = 13.0
|
|
31
|
-
exposure_time: float = 1.0
|
|
32
35
|
first_x_channel: int = 1
|
|
33
36
|
last_x_channel: int = 1000
|
|
34
37
|
first_y_channel: int = 101
|
|
@@ -49,15 +52,17 @@ class VGScientaExcitationEnergySource(JavaToPythonModel):
|
|
|
49
52
|
value: float = 0
|
|
50
53
|
|
|
51
54
|
|
|
52
|
-
class VGScientaSequence(
|
|
55
|
+
class VGScientaSequence(
|
|
56
|
+
AbstractBaseSequence[VGScientaRegion, TLensMode], Generic[TLensMode]
|
|
57
|
+
):
|
|
53
58
|
element_set: str = Field(default="Unknown")
|
|
54
59
|
excitation_energy_sources: list[VGScientaExcitationEnergySource] = Field(
|
|
55
60
|
default_factory=lambda: []
|
|
56
61
|
)
|
|
57
|
-
regions: list[VGScientaRegion] = Field(default_factory=lambda: [])
|
|
62
|
+
regions: list[VGScientaRegion[TLensMode]] = Field(default_factory=lambda: [])
|
|
58
63
|
|
|
59
64
|
def get_excitation_energy_source_by_region(
|
|
60
|
-
self, region: VGScientaRegion
|
|
65
|
+
self, region: VGScientaRegion[TLensMode]
|
|
61
66
|
) -> VGScientaExcitationEnergySource:
|
|
62
67
|
value = next(
|
|
63
68
|
(
|
dodal/devices/fast_grid_scan.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
from abc import ABC, abstractmethod
|
|
3
2
|
from typing import Generic, TypeVar
|
|
4
3
|
|
|
@@ -258,7 +257,7 @@ class FastGridScanCommon(StandardReadable, Flyable, ABC, Generic[ParamType]):
|
|
|
258
257
|
async def complete(self):
|
|
259
258
|
try:
|
|
260
259
|
await wait_for_value(self.status, 0, self.COMPLETE_STATUS)
|
|
261
|
-
except
|
|
260
|
+
except TimeoutError:
|
|
262
261
|
LOGGER.error(
|
|
263
262
|
"Hyperion timed out waiting for FGS motion to complete. This may have been caused by a goniometer stage getting stuck.\n\
|
|
264
263
|
Forcibly stopping the FGS motion program..."
|
dodal/devices/i04/constants.py
CHANGED
|
@@ -4,6 +4,6 @@ from dataclasses import dataclass
|
|
|
4
4
|
|
|
5
5
|
@dataclass(frozen=True)
|
|
6
6
|
class RedisConstants:
|
|
7
|
-
REDIS_HOST = os.environ.get("
|
|
7
|
+
REDIS_HOST = os.environ.get("VALKEY_FOR_MURKO_PROD_SVC_SERVICE_HOST", "test_redis")
|
|
8
8
|
REDIS_PASSWORD = os.environ.get("VALKEY_PASSWORD", "test_redis_password")
|
|
9
9
|
MURKO_REDIS_DB = 7
|
dodal/devices/i09/dcm.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from ophyd_async.core import derived_signal_r
|
|
2
|
+
|
|
3
|
+
from dodal.devices.common_dcm import BaseDCM, PitchAndRollCrystal, StationaryCrystal
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DCM(BaseDCM[PitchAndRollCrystal, StationaryCrystal]):
|
|
7
|
+
"""
|
|
8
|
+
I09 double crystal monochromator (DCM), used to select the energy of the beam.
|
|
9
|
+
Differences:
|
|
10
|
+
|
|
11
|
+
1. Can provide energy in eV via dcm.energy_in_ev read signal
|
|
12
|
+
|
|
13
|
+
This DCM is available on i09 and i09_1 endstations.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, prefix: str, name: str = "") -> None:
|
|
17
|
+
super().__init__(prefix, PitchAndRollCrystal, StationaryCrystal, name)
|
|
18
|
+
self.energy_in_ev = derived_signal_r(
|
|
19
|
+
self._convert_keV_to_eV, energy_signal=self.energy_in_kev.user_readback
|
|
20
|
+
)
|
|
21
|
+
# Set name so that new child signals get correct name
|
|
22
|
+
# need to do it until https://github.com/bluesky/ophyd-async/pull/899 merged
|
|
23
|
+
self.set_name(self.name)
|
|
24
|
+
|
|
25
|
+
def _convert_keV_to_eV(self, energy_signal: float) -> float:
|
|
26
|
+
return energy_signal * 1000
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from ophyd_async.core import StrictEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Grating(StrictEnum):
|
|
5
|
+
G_300 = "300 lines/mm"
|
|
6
|
+
G_400 = "400 lines/mm"
|
|
7
|
+
G_800 = "800 lines/mm"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LensMode(StrictEnum):
|
|
11
|
+
TRANSMISSION = "Transmission"
|
|
12
|
+
ANGULAR45 = "Angular45"
|
|
13
|
+
ANGULAR60 = "Angular60"
|
|
14
|
+
ANGULAR56 = "Angular56"
|
|
15
|
+
ANGULAR45VUV = "Angular45VUV"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from ophyd_async.core import SupersetEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class LensMode(SupersetEnum):
|
|
5
|
+
LARGE_AREA = "LargeArea"
|
|
6
|
+
MEDIUM_ANGULAR_DISPERSION = "MediumAngularDispersion"
|
|
7
|
+
MEDIUM_AREA = "MediumArea"
|
|
8
|
+
SMALL_AREA = "SmallArea"
|
|
9
|
+
HIGH_MAGNIFICATION = "HighMagnification"
|
|
10
|
+
LOW_ANGULAR_DISPERSION = "LowAngularDispersion"
|
|
11
|
+
LOW_ANGULAR_DISPERSION2 = "LowAngularDispersion2"
|
|
12
|
+
HIGH_ANGULAR_DISPERSION = "HighAngularDispersion"
|
|
13
|
+
WIDE_ANGLE_MODE = "WideAngleMode"
|
|
14
|
+
MEDIUM_ANGLE_MODE = "MediumAngleMode"
|
|
15
|
+
MEDIUM_MAGNIFICATION = "MediumMagnification"
|
|
16
|
+
LOW_MAGNIFICATION = "LowMagnification"
|
|
17
|
+
HIGH_MAGNIFICATION2 = "HighMagnification2"
|
|
18
|
+
RAMP_MODE = "RampMode"
|
|
19
|
+
NOT_CONNECTED = "Not connected"
|
dodal/devices/i10/mirrors.py
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
from ophyd_async.core import StandardReadable
|
|
2
1
|
from ophyd_async.epics.core import epics_signal_rw
|
|
3
2
|
from ophyd_async.epics.motor import Motor
|
|
4
3
|
|
|
4
|
+
from dodal.devices.motors import XYZStage
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
class PiezoMirror(XYZStage):
|
|
7
8
|
def __init__(
|
|
8
9
|
self,
|
|
9
10
|
prefix: str,
|
|
10
11
|
name: str = "",
|
|
11
12
|
):
|
|
12
13
|
with self.add_children_as_readables():
|
|
13
|
-
self.x = Motor(prefix + "X")
|
|
14
|
-
self.y = Motor(prefix + "Y")
|
|
15
|
-
self.z = Motor(prefix + "Z")
|
|
16
14
|
self.yaw = Motor(prefix + "YAW")
|
|
17
15
|
self.pitch = Motor(prefix + "PITCH")
|
|
18
16
|
self.roll = Motor(prefix + "ROLL")
|
|
@@ -21,4 +19,4 @@ class PiezoMirror(StandardReadable):
|
|
|
21
19
|
read_pv=prefix + "FPITCH:RBV:AI",
|
|
22
20
|
write_pv=prefix + "FPITCH:DMD:AO",
|
|
23
21
|
)
|
|
24
|
-
super().__init__(name
|
|
22
|
+
super().__init__(prefix, name)
|
|
@@ -2,20 +2,6 @@ from ophyd_async.core import StandardReadable
|
|
|
2
2
|
from ophyd_async.epics.motor import Motor
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
class PinHole(StandardReadable):
|
|
6
|
-
"Two motors stage for rasor pinhole"
|
|
7
|
-
|
|
8
|
-
def __init__(
|
|
9
|
-
self,
|
|
10
|
-
prefix: str,
|
|
11
|
-
name: str = "",
|
|
12
|
-
):
|
|
13
|
-
with self.add_children_as_readables():
|
|
14
|
-
self.x = Motor(prefix + "X")
|
|
15
|
-
self.y = Motor(prefix + "Y")
|
|
16
|
-
super().__init__(name=name)
|
|
17
|
-
|
|
18
|
-
|
|
19
5
|
class Diffractometer(StandardReadable):
|
|
20
6
|
def __init__(
|
|
21
7
|
self,
|
dodal/devices/i19/beamstop.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from ophyd_async.core import StandardReadable, StrictEnum
|
|
2
2
|
from ophyd_async.epics.core import epics_signal_rw, epics_signal_x
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
from dodal.devices.motors import XYZStage
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class HomeGroup(StrictEnum):
|
|
@@ -18,13 +19,8 @@ class HomingControl(StandardReadable):
|
|
|
18
19
|
super().__init__(name)
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
class BeamStop(
|
|
22
|
+
class BeamStop(XYZStage):
|
|
22
23
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
23
|
-
with self.add_children_as_readables():
|
|
24
|
-
self.x = Motor(f"{prefix}X")
|
|
25
|
-
self.y = Motor(f"{prefix}Y")
|
|
26
|
-
self.z = Motor(f"{prefix}Z")
|
|
27
|
-
|
|
28
24
|
self.homing = HomingControl(f"{prefix}HM", name)
|
|
29
25
|
|
|
30
26
|
super().__init__(name)
|
dodal/devices/i24/aperture.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
from ophyd_async.core import
|
|
1
|
+
from ophyd_async.core import StrictEnum
|
|
2
2
|
from ophyd_async.epics.core import epics_signal_rw
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
from dodal.devices.motors import XYStage
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class AperturePositions(StrictEnum):
|
|
@@ -10,7 +11,7 @@ class AperturePositions(StrictEnum):
|
|
|
10
11
|
MANUAL = "Manual Mounting"
|
|
11
12
|
|
|
12
13
|
|
|
13
|
-
class Aperture(
|
|
14
|
+
class Aperture(XYStage):
|
|
14
15
|
"""Device to trigger the aperture motor move on I24.
|
|
15
16
|
|
|
16
17
|
The aperture positioner has 4 possible positions: In, Out, Robot and Manual.
|
|
@@ -20,8 +21,5 @@ class Aperture(StandardReadable):
|
|
|
20
21
|
"""
|
|
21
22
|
|
|
22
23
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
23
|
-
self.x = Motor(prefix + "X")
|
|
24
|
-
self.y = Motor(prefix + "Y")
|
|
25
|
-
|
|
26
24
|
self.position = epics_signal_rw(AperturePositions, prefix + "MP:SELECT")
|
|
27
25
|
super().__init__(name)
|
dodal/devices/i24/beamstop.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
from ophyd_async.core import
|
|
1
|
+
from ophyd_async.core import StrictEnum
|
|
2
2
|
from ophyd_async.epics.core import epics_signal_rw
|
|
3
3
|
from ophyd_async.epics.motor import Motor
|
|
4
4
|
|
|
5
|
+
from dodal.devices.motors import XYZStage
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
class BeamstopPositions(StrictEnum):
|
|
7
9
|
CHECK_BEAM = "CheckBeam"
|
|
@@ -12,7 +14,7 @@ class BeamstopPositions(StrictEnum):
|
|
|
12
14
|
ROBOT = "Robot"
|
|
13
15
|
|
|
14
16
|
|
|
15
|
-
class Beamstop(
|
|
17
|
+
class Beamstop(XYZStage):
|
|
16
18
|
"""Device to move the beamstop.
|
|
17
19
|
|
|
18
20
|
The positioner moves the x,y,z motors when a position is selected.
|
|
@@ -25,12 +27,7 @@ class Beamstop(StandardReadable):
|
|
|
25
27
|
"""
|
|
26
28
|
|
|
27
29
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
28
|
-
self.x = Motor(prefix + "X")
|
|
29
|
-
self.y = Motor(prefix + "Y")
|
|
30
|
-
self.z = Motor(prefix + "Z")
|
|
31
|
-
|
|
32
30
|
self.y_rotation = Motor(prefix + "ROTY")
|
|
33
|
-
|
|
34
31
|
self.pos_select = epics_signal_rw(BeamstopPositions, prefix + "MP:SELECT")
|
|
35
32
|
|
|
36
|
-
super().__init__(name)
|
|
33
|
+
super().__init__(prefix, name)
|
dodal/devices/i24/pmac.py
CHANGED
|
@@ -9,13 +9,13 @@ from ophyd_async.core import (
|
|
|
9
9
|
Reference,
|
|
10
10
|
SignalR,
|
|
11
11
|
SignalRW,
|
|
12
|
-
StandardReadable,
|
|
13
12
|
observe_signals_value,
|
|
14
13
|
soft_signal_rw,
|
|
15
14
|
wait_for_value,
|
|
16
15
|
)
|
|
17
16
|
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
18
|
-
|
|
17
|
+
|
|
18
|
+
from dodal.devices.motors import XYZStage
|
|
19
19
|
|
|
20
20
|
HOME_STR = r"\#1hmz\#2hmz\#3hmz" # Command to home the PMAC motors
|
|
21
21
|
ZERO_STR = "!x0y0z0" # Command to blend any ongoing move into new position
|
|
@@ -192,7 +192,7 @@ class ProgramAbort(Triggerable):
|
|
|
192
192
|
)
|
|
193
193
|
|
|
194
194
|
|
|
195
|
-
class PMAC(
|
|
195
|
+
class PMAC(XYZStage):
|
|
196
196
|
"""Device to control the chip stage on I24."""
|
|
197
197
|
|
|
198
198
|
def __init__(self, prefix: str, name: str = "") -> None:
|
|
@@ -209,10 +209,6 @@ class PMAC(StandardReadable):
|
|
|
209
209
|
self.pmac_string,
|
|
210
210
|
)
|
|
211
211
|
|
|
212
|
-
self.x = Motor(prefix + "X")
|
|
213
|
-
self.y = Motor(prefix + "Y")
|
|
214
|
-
self.z = Motor(prefix + "Z")
|
|
215
|
-
|
|
216
212
|
# These next signals are readback values on PVARS which are set by the motion
|
|
217
213
|
# program.
|
|
218
214
|
self.scanstatus = epics_signal_r(float, "BL24I-MO-STEP-14:signal:P2401")
|
|
@@ -232,4 +228,4 @@ class PMAC(StandardReadable):
|
|
|
232
228
|
)
|
|
233
229
|
self.abort_program = ProgramAbort(self.pmac_string, self.scanstatus)
|
|
234
230
|
|
|
235
|
-
super().__init__(name)
|
|
231
|
+
super().__init__(prefix, name)
|
dodal/devices/linkam3.py
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import time
|
|
3
|
-
|
|
4
|
-
from bluesky.protocols import Location
|
|
5
1
|
from ophyd_async.core import (
|
|
6
2
|
StandardReadable,
|
|
7
3
|
StandardReadableFormat,
|
|
8
4
|
StrictEnum,
|
|
9
|
-
WatchableAsyncStatus,
|
|
10
|
-
WatcherUpdate,
|
|
11
|
-
observe_value,
|
|
12
5
|
)
|
|
13
6
|
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
|
|
14
7
|
|
|
@@ -18,6 +11,8 @@ class PumpControl(StrictEnum):
|
|
|
18
11
|
AUTO = "Auto"
|
|
19
12
|
|
|
20
13
|
|
|
14
|
+
# TODO: Make use of Status PV:
|
|
15
|
+
# https://github.com/DiamondLightSource/dodal/issues/338
|
|
21
16
|
class Linkam3(StandardReadable):
|
|
22
17
|
"""Device to represent a Linkam3 temperature controller
|
|
23
18
|
|
|
@@ -34,81 +29,30 @@ class Linkam3(StandardReadable):
|
|
|
34
29
|
settle_time: int = 0
|
|
35
30
|
|
|
36
31
|
def __init__(self, prefix: str, name: str = ""):
|
|
37
|
-
self.
|
|
38
|
-
|
|
39
|
-
self.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
self.chamber_vac = epics_signal_r(float, prefix + "VAC_CHAMBER:")
|
|
57
|
-
self.sensor_vac = epics_signal_r(float, prefix + "VAC_DATA1:")
|
|
58
|
-
|
|
59
|
-
self.error = epics_signal_r(str, prefix + "CTRLLR:ERR:")
|
|
60
|
-
|
|
61
|
-
# status is a bitfield stored in a double?
|
|
62
|
-
self.status = epics_signal_r(float, prefix + "STATUS:")
|
|
63
|
-
|
|
64
|
-
self.add_readables((self.temp,), format=StandardReadableFormat.HINTED_SIGNAL)
|
|
65
|
-
self.add_readables(
|
|
66
|
-
(self.ramp_rate, self.speed, self.set_point),
|
|
67
|
-
format=StandardReadableFormat.CONFIG_SIGNAL,
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
super().__init__(name=name)
|
|
71
|
-
|
|
72
|
-
@WatchableAsyncStatus.wrap
|
|
73
|
-
async def set(self, new_position: float, timeout: float | None = None):
|
|
74
|
-
# time.monotonic won't go backwards in case of NTP corrections
|
|
75
|
-
start = time.monotonic()
|
|
76
|
-
old_position = await self.set_point.get_value()
|
|
77
|
-
await self.set_point.set(new_position, wait=True)
|
|
78
|
-
async for current_position in observe_value(self.temp):
|
|
79
|
-
yield WatcherUpdate(
|
|
80
|
-
name=self.name,
|
|
81
|
-
current=current_position,
|
|
82
|
-
initial=old_position,
|
|
83
|
-
target=new_position,
|
|
84
|
-
time_elapsed=time.monotonic() - start,
|
|
32
|
+
with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
|
|
33
|
+
self.temp = epics_signal_r(float, prefix + "TEMP")
|
|
34
|
+
with self.add_children_as_readables():
|
|
35
|
+
self.dsc = epics_signal_r(float, prefix + "DSC")
|
|
36
|
+
self.start_heat = epics_signal_rw(bool, prefix + "STARTHEAT")
|
|
37
|
+
|
|
38
|
+
self.ramp_rate = epics_signal_rw(
|
|
39
|
+
float, prefix + "RAMPRATE", prefix + "RAMPRATE:SET"
|
|
40
|
+
)
|
|
41
|
+
self.ramp_time = epics_signal_r(float, prefix + "RAMPTIME")
|
|
42
|
+
self.set_point = epics_signal_rw(
|
|
43
|
+
float, prefix + "SETPOINT", prefix + "SETPOINT:SET"
|
|
44
|
+
)
|
|
45
|
+
self.pump_control = epics_signal_r(
|
|
46
|
+
PumpControl,
|
|
47
|
+
prefix + "LNP_MODE:SET",
|
|
48
|
+
)
|
|
49
|
+
self.speed = epics_signal_rw(
|
|
50
|
+
float, prefix + "LNP_SPEED", prefix + "LNP_SPEED:SET"
|
|
85
51
|
)
|
|
86
|
-
if abs(current_position - new_position) < self.tolerance:
|
|
87
|
-
await asyncio.sleep(self.settle_time)
|
|
88
|
-
break
|
|
89
|
-
|
|
90
|
-
# TODO: Make use of values in Status.
|
|
91
|
-
# https://github.com/DiamondLightSource/dodal/issues/338
|
|
92
|
-
async def _is_nth_bit_set(self, n: int) -> bool:
|
|
93
|
-
return bool(int(await self.status.get_value()) & 1 << n)
|
|
94
|
-
|
|
95
|
-
async def in_error(self) -> bool:
|
|
96
|
-
return await self._is_nth_bit_set(0)
|
|
97
|
-
|
|
98
|
-
async def at_setpoint(self) -> bool:
|
|
99
|
-
return await self._is_nth_bit_set(1)
|
|
100
|
-
|
|
101
|
-
async def heater_on(self) -> bool:
|
|
102
|
-
return await self._is_nth_bit_set(2)
|
|
103
52
|
|
|
104
|
-
|
|
105
|
-
|
|
53
|
+
self.chamber_vac = epics_signal_r(float, prefix + "VAC_CHAMBER")
|
|
54
|
+
self.sensor_vac = epics_signal_r(float, prefix + "VAC_DATA1")
|
|
106
55
|
|
|
107
|
-
|
|
108
|
-
return await self._is_nth_bit_set(4)
|
|
56
|
+
self.error = epics_signal_r(str, prefix + "CTRLLR:ERR")
|
|
109
57
|
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
"readback": await self.temp.get_value(),
|
|
113
|
-
"setpoint": await self.set_point.get_value(),
|
|
114
|
-
}
|
|
58
|
+
super().__init__(name=name)
|