dls-dodal 1.68.0__py3-none-any.whl → 1.69.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.68.0.dist-info → dls_dodal-1.69.0.dist-info}/METADATA +1 -31
- {dls_dodal-1.68.0.dist-info → dls_dodal-1.69.0.dist-info}/RECORD +57 -49
- dodal/_version.py +2 -2
- dodal/beamlines/adsim.py +30 -23
- dodal/beamlines/i02_1.py +14 -42
- dodal/beamlines/i02_2.py +5 -11
- dodal/beamlines/i03.py +4 -1
- dodal/beamlines/i03_supervisor.py +19 -0
- dodal/beamlines/i04.py +74 -179
- dodal/beamlines/i05.py +8 -0
- dodal/beamlines/i06_1.py +24 -0
- dodal/beamlines/i09.py +53 -9
- dodal/beamlines/i09_1.py +8 -0
- dodal/beamlines/i09_2.py +4 -4
- dodal/beamlines/i16.py +11 -0
- dodal/beamlines/i20_1.py +14 -0
- dodal/beamlines/i21.py +12 -4
- dodal/beamlines/i23.py +19 -25
- dodal/beamlines/i24.py +55 -105
- dodal/beamlines/p60.py +11 -1
- dodal/common/__init__.py +2 -1
- dodal/common/maths.py +80 -0
- dodal/devices/eiger.py +29 -14
- dodal/devices/electron_analyser/base/__init__.py +3 -3
- dodal/devices/electron_analyser/base/base_controller.py +19 -8
- dodal/devices/electron_analyser/base/base_enums.py +0 -5
- dodal/devices/electron_analyser/base/base_region.py +2 -1
- dodal/devices/electron_analyser/base/energy_sources.py +27 -26
- dodal/devices/electron_analyser/specs/specs_detector.py +7 -6
- dodal/devices/electron_analyser/vgscienta/vgscienta_detector.py +7 -6
- dodal/devices/fast_shutter.py +108 -25
- dodal/devices/i04/beam_centre.py +84 -0
- dodal/devices/i04/max_pixel.py +4 -17
- dodal/devices/i04/murko_results.py +18 -3
- dodal/devices/i10/i10_apple2.py +6 -6
- dodal/devices/i17/i17_apple2.py +6 -6
- dodal/devices/i24/commissioning_jungfrau.py +9 -10
- dodal/devices/insertion_device/__init__.py +12 -8
- dodal/devices/insertion_device/apple2_controller.py +380 -0
- dodal/devices/insertion_device/apple2_undulator.py +152 -531
- dodal/devices/insertion_device/energy.py +88 -0
- dodal/devices/insertion_device/energy_motor_lookup.py +1 -1
- dodal/devices/insertion_device/lookup_table_models.py +2 -2
- dodal/devices/insertion_device/polarisation.py +36 -0
- dodal/devices/oav/oav_detector.py +66 -1
- dodal/devices/oav/utils.py +17 -0
- dodal/devices/robot.py +35 -18
- dodal/devices/selectable_source.py +38 -0
- dodal/devices/zebra/zebra.py +15 -0
- dodal/devices/zebra/zebra_constants_mapping.py +1 -0
- dodal/plans/configure_arm_trigger_and_disarm_detector.py +0 -1
- dodal/testing/__init__.py +0 -0
- {dls_dodal-1.68.0.dist-info → dls_dodal-1.69.0.dist-info}/WHEEL +0 -0
- {dls_dodal-1.68.0.dist-info → dls_dodal-1.69.0.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.68.0.dist-info → dls_dodal-1.69.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.68.0.dist-info → dls_dodal-1.69.0.dist-info}/top_level.txt +0 -0
- /dodal/devices/insertion_device/{id_enum.py → enum.py} +0 -0
dodal/beamlines/i20_1.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
3
|
from ophyd_async.epics.motor import Motor
|
|
4
|
+
from ophyd_async.epics.pmac import PmacIO
|
|
4
5
|
from ophyd_async.fastcs.panda import HDFPanda
|
|
5
6
|
|
|
6
7
|
from dodal.common.beamlines.beamline_utils import (
|
|
@@ -58,6 +59,19 @@ def turbo_slit_x() -> Motor:
|
|
|
58
59
|
return Motor(f"{PREFIX.beamline_prefix}-OP-PCHRO-01:TS:XFINE")
|
|
59
60
|
|
|
60
61
|
|
|
62
|
+
@device_factory()
|
|
63
|
+
def turbo_slit_pmac() -> PmacIO:
|
|
64
|
+
"""
|
|
65
|
+
PMac controller using running fly scans with trajectory
|
|
66
|
+
"""
|
|
67
|
+
motor = turbo_slit_x()
|
|
68
|
+
return PmacIO(
|
|
69
|
+
prefix=f"{PREFIX.beamline_prefix}-MO-STEP-06:",
|
|
70
|
+
raw_motors=[motor],
|
|
71
|
+
coord_nums=[3],
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
61
75
|
@device_factory()
|
|
62
76
|
def panda() -> HDFPanda:
|
|
63
77
|
return HDFPanda(
|
dodal/beamlines/i21.py
CHANGED
|
@@ -24,6 +24,9 @@ from dodal.devices.insertion_device.energy_motor_lookup import (
|
|
|
24
24
|
from dodal.devices.insertion_device.lookup_table_models import LookupTableColumnConfig
|
|
25
25
|
from dodal.devices.pgm import PlaneGratingMonochromator
|
|
26
26
|
from dodal.devices.synchrotron import Synchrotron
|
|
27
|
+
from dodal.devices.temperture_controller import (
|
|
28
|
+
Lakeshore336,
|
|
29
|
+
)
|
|
27
30
|
from dodal.log import set_beamline as set_log_beamline
|
|
28
31
|
from dodal.utils import BeamlinePrefix, get_beamline_name
|
|
29
32
|
|
|
@@ -71,18 +74,18 @@ def id_phase() -> UndulatorPhaseAxes:
|
|
|
71
74
|
|
|
72
75
|
|
|
73
76
|
@device_factory()
|
|
74
|
-
def id() -> Apple2:
|
|
77
|
+
def id() -> Apple2[UndulatorPhaseAxes]:
|
|
75
78
|
"""I21 insertion device."""
|
|
76
|
-
return Apple2(
|
|
79
|
+
return Apple2[UndulatorPhaseAxes](
|
|
77
80
|
id_gap=id_gap(),
|
|
78
81
|
id_phase=id_phase(),
|
|
79
82
|
)
|
|
80
83
|
|
|
81
84
|
|
|
82
85
|
@device_factory()
|
|
83
|
-
def id_controller() -> Apple2EnforceLHMoveController:
|
|
86
|
+
def id_controller() -> Apple2EnforceLHMoveController[UndulatorPhaseAxes]:
|
|
84
87
|
"""i21 insertion device controller."""
|
|
85
|
-
return Apple2EnforceLHMoveController(
|
|
88
|
+
return Apple2EnforceLHMoveController[UndulatorPhaseAxes](
|
|
86
89
|
apple2=id(),
|
|
87
90
|
gap_energy_motor_lut=ConfigServerEnergyMotorLookup(
|
|
88
91
|
lut_config=LookupTableColumnConfig(grating=I21_GRATING_COLUMNS),
|
|
@@ -114,3 +117,8 @@ def id_polarisation() -> InsertionDevicePolarisation:
|
|
|
114
117
|
def energy_jid() -> BeamEnergy:
|
|
115
118
|
"""Beam energy."""
|
|
116
119
|
return BeamEnergy(id_energy=id_energy(), mono=pgm().energy)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@device_factory()
|
|
123
|
+
def sample_temperature_controller() -> Lakeshore336:
|
|
124
|
+
return Lakeshore336(prefix=f"{PREFIX.beamline_prefix}-EA-TCTRL-01:")
|
dodal/beamlines/i23.py
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
+
from functools import cache
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
|
|
3
|
-
from ophyd_async.core import InOut, StrictEnum
|
|
4
|
+
from ophyd_async.core import InOut, PathProvider, StrictEnum
|
|
4
5
|
from ophyd_async.epics.adpilatus import PilatusDetector
|
|
5
6
|
|
|
6
|
-
from dodal.common.beamlines.beamline_utils import (
|
|
7
|
-
device_factory,
|
|
8
|
-
get_path_provider,
|
|
9
|
-
set_path_provider,
|
|
10
|
-
)
|
|
11
7
|
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
|
|
12
8
|
from dodal.common.beamlines.device_helpers import HDF5_SUFFIX
|
|
13
9
|
from dodal.common.visit import LocalDirectoryServiceClient, StaticVisitPathProvider
|
|
10
|
+
from dodal.device_manager import DeviceManager
|
|
14
11
|
from dodal.devices.motors import SixAxisGonio
|
|
15
12
|
from dodal.devices.oav.pin_image_recognition import PinTipDetection
|
|
16
13
|
from dodal.devices.positioner import Positioner1D
|
|
@@ -25,18 +22,22 @@ from dodal.log import set_beamline as set_log_beamline
|
|
|
25
22
|
from dodal.utils import BeamlinePrefix, get_beamline_name, get_hostname
|
|
26
23
|
|
|
27
24
|
BL = get_beamline_name("i23")
|
|
25
|
+
PREFIX = BeamlinePrefix(BL)
|
|
28
26
|
set_log_beamline(BL)
|
|
29
27
|
set_utils_beamline(BL)
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
devices = DeviceManager()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@devices.fixture
|
|
33
|
+
@cache
|
|
34
|
+
def path_provider() -> PathProvider:
|
|
35
|
+
return StaticVisitPathProvider(
|
|
33
36
|
BL,
|
|
34
37
|
Path("/tmp"),
|
|
35
38
|
client=LocalDirectoryServiceClient(),
|
|
36
39
|
)
|
|
37
|
-
)
|
|
38
40
|
|
|
39
|
-
PREFIX = BeamlinePrefix(BL)
|
|
40
41
|
|
|
41
42
|
I23_ZEBRA_MAPPING = ZebraMapping(
|
|
42
43
|
outputs=ZebraTTLOutputs(TTL_DETECTOR=1, TTL_SHUTTER=4),
|
|
@@ -59,51 +60,44 @@ def _is_i23_machine():
|
|
|
59
60
|
return hostname.startswith("i23-ws") or hostname.startswith("i23-control")
|
|
60
61
|
|
|
61
62
|
|
|
62
|
-
@
|
|
63
|
+
@devices.factory(skip=lambda: not _is_i23_machine())
|
|
63
64
|
def oav_pin_tip_detection() -> PinTipDetection:
|
|
64
|
-
"""Get the i23 OAV pin-tip detection device."""
|
|
65
|
-
|
|
66
65
|
return PinTipDetection(
|
|
67
66
|
f"{PREFIX.beamline_prefix}-DI-OAV-01:",
|
|
68
67
|
"pin_tip_detection",
|
|
69
68
|
)
|
|
70
69
|
|
|
71
70
|
|
|
72
|
-
@
|
|
71
|
+
@devices.factory()
|
|
73
72
|
def shutter() -> ZebraShutter:
|
|
74
|
-
"""Get the i23 zebra controlled shutter."""
|
|
75
73
|
return ZebraShutter(f"{PREFIX.beamline_prefix}-EA-SHTR-01:")
|
|
76
74
|
|
|
77
75
|
|
|
78
|
-
@
|
|
76
|
+
@devices.factory()
|
|
79
77
|
def gonio() -> SixAxisGonio:
|
|
80
|
-
"""Get the i23 goniometer"""
|
|
81
78
|
return SixAxisGonio(f"{PREFIX.beamline_prefix}-MO-GONIO-01:")
|
|
82
79
|
|
|
83
80
|
|
|
84
|
-
@
|
|
81
|
+
@devices.factory()
|
|
85
82
|
def zebra() -> Zebra:
|
|
86
|
-
"""Get the i23 zebra"""
|
|
87
83
|
return Zebra(
|
|
88
84
|
prefix=f"{PREFIX.beamline_prefix}-EA-ZEBRA-01:ZEBRA:",
|
|
89
85
|
mapping=I23_ZEBRA_MAPPING,
|
|
90
86
|
)
|
|
91
87
|
|
|
92
88
|
|
|
93
|
-
@
|
|
94
|
-
def pilatus() -> PilatusDetector:
|
|
95
|
-
"""Get the i23 pilatus"""
|
|
89
|
+
@devices.factory()
|
|
90
|
+
def pilatus(path_provider: PathProvider) -> PilatusDetector:
|
|
96
91
|
return PilatusDetector(
|
|
97
92
|
prefix=f"{PREFIX.beamline_prefix}-EA-PILAT-01:",
|
|
98
|
-
path_provider=
|
|
93
|
+
path_provider=path_provider,
|
|
99
94
|
drv_suffix="cam1:",
|
|
100
95
|
fileio_suffix=HDF5_SUFFIX,
|
|
101
96
|
)
|
|
102
97
|
|
|
103
98
|
|
|
104
|
-
@
|
|
99
|
+
@devices.factory()
|
|
105
100
|
def detector_motion() -> Positioner1D[I23DetectorPositions]:
|
|
106
|
-
"""Get the i23 detector"""
|
|
107
101
|
return Positioner1D[I23DetectorPositions](
|
|
108
102
|
f"{PREFIX.beamline_prefix}-EA-DET-01:Z",
|
|
109
103
|
datatype=I23DetectorPositions,
|
dodal/beamlines/i24.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
from
|
|
1
|
+
from functools import cache
|
|
2
|
+
from pathlib import Path
|
|
2
3
|
|
|
3
|
-
from ophyd_async.core import
|
|
4
|
+
from ophyd_async.core import AutoMaxIncrementingPathProvider, PathProvider
|
|
4
5
|
|
|
5
|
-
from dodal.common.beamlines.beamline_utils import
|
|
6
|
-
BL,
|
|
7
|
-
device_factory,
|
|
8
|
-
)
|
|
6
|
+
from dodal.common.beamlines.beamline_utils import BL
|
|
9
7
|
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
|
|
8
|
+
from dodal.common.visit import LocalDirectoryServiceClient, StaticVisitPathProvider
|
|
9
|
+
from dodal.device_manager import DeviceManager
|
|
10
10
|
from dodal.devices.attenuator.attenuator import EnumFilterAttenuator
|
|
11
11
|
from dodal.devices.attenuator.filter_selections import (
|
|
12
12
|
I24FilterOneSelections,
|
|
@@ -25,12 +25,14 @@ from dodal.devices.i24.vgonio import VerticalGoniometer
|
|
|
25
25
|
from dodal.devices.motors import YZStage
|
|
26
26
|
from dodal.devices.oav.oav_detector import OAVBeamCentreFile
|
|
27
27
|
from dodal.devices.oav.oav_parameters import OAVConfigBeamCentre
|
|
28
|
+
from dodal.devices.synchrotron import Synchrotron
|
|
28
29
|
from dodal.devices.zebra.zebra import Zebra
|
|
29
30
|
from dodal.devices.zebra.zebra_constants_mapping import (
|
|
30
31
|
ZebraMapping,
|
|
31
32
|
ZebraSources,
|
|
32
33
|
ZebraTTLOutputs,
|
|
33
34
|
)
|
|
35
|
+
from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
|
|
34
36
|
from dodal.log import set_beamline as set_log_beamline
|
|
35
37
|
from dodal.utils import BeamlinePrefix, get_beamline_name
|
|
36
38
|
|
|
@@ -45,111 +47,67 @@ set_log_beamline(BL)
|
|
|
45
47
|
set_utils_beamline(BL)
|
|
46
48
|
|
|
47
49
|
I24_ZEBRA_MAPPING = ZebraMapping(
|
|
48
|
-
outputs=ZebraTTLOutputs(TTL_EIGER=1,
|
|
50
|
+
outputs=ZebraTTLOutputs(TTL_EIGER=1, TTL_JUNGFRAU=2, TTL_FAST_SHUTTER=4),
|
|
49
51
|
sources=ZebraSources(),
|
|
50
52
|
)
|
|
51
53
|
|
|
52
54
|
PREFIX = BeamlinePrefix(BL)
|
|
53
55
|
|
|
56
|
+
devices = DeviceManager()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@devices.fixture
|
|
60
|
+
@cache
|
|
61
|
+
def path_provider() -> PathProvider:
|
|
62
|
+
return StaticVisitPathProvider(
|
|
63
|
+
BL,
|
|
64
|
+
Path("/tmp"),
|
|
65
|
+
client=LocalDirectoryServiceClient(),
|
|
66
|
+
)
|
|
67
|
+
|
|
54
68
|
|
|
55
|
-
@
|
|
69
|
+
@devices.factory()
|
|
56
70
|
def attenuator() -> EnumFilterAttenuator:
|
|
57
|
-
"""Get a read-only attenuator device for i24, instantiate it if it hasn't already
|
|
58
|
-
been. If this is called when already instantiated in i24, it will return the
|
|
59
|
-
existing object."""
|
|
60
71
|
return EnumFilterAttenuator(
|
|
61
72
|
f"{PREFIX.beamline_prefix}-OP-ATTN-01:",
|
|
62
73
|
filter_selection=(I24FilterOneSelections, I24FilterTwoSelections),
|
|
63
74
|
)
|
|
64
75
|
|
|
65
76
|
|
|
66
|
-
@
|
|
77
|
+
@devices.factory()
|
|
67
78
|
def aperture() -> Aperture:
|
|
68
|
-
""
|
|
69
|
-
If this is called when already instantiated in i24, it will return the existing object.
|
|
70
|
-
"""
|
|
71
|
-
return Aperture(
|
|
72
|
-
f"{PREFIX.beamline_prefix}-AL-APTR-01:",
|
|
73
|
-
)
|
|
79
|
+
return Aperture(f"{PREFIX.beamline_prefix}-AL-APTR-01:")
|
|
74
80
|
|
|
75
81
|
|
|
76
|
-
@
|
|
82
|
+
@devices.factory()
|
|
77
83
|
def beamstop() -> Beamstop:
|
|
78
|
-
""
|
|
79
|
-
If this is called when already instantiated in i24, it will return the existing object.
|
|
80
|
-
"""
|
|
81
|
-
return Beamstop(
|
|
82
|
-
f"{PREFIX.beamline_prefix}-MO-BS-01:",
|
|
83
|
-
)
|
|
84
|
+
return Beamstop(f"{PREFIX.beamline_prefix}-MO-BS-01:")
|
|
84
85
|
|
|
85
86
|
|
|
86
|
-
@
|
|
87
|
+
@devices.factory()
|
|
87
88
|
def backlight() -> DualBacklight:
|
|
88
|
-
|
|
89
|
-
If this is called when already instantiated in i24, it will return the existing object.
|
|
90
|
-
"""
|
|
91
|
-
return DualBacklight(
|
|
92
|
-
prefix=PREFIX.beamline_prefix,
|
|
93
|
-
)
|
|
89
|
+
return DualBacklight(prefix=PREFIX.beamline_prefix)
|
|
94
90
|
|
|
95
91
|
|
|
96
|
-
@
|
|
92
|
+
@devices.factory()
|
|
97
93
|
def detector_motion() -> YZStage:
|
|
98
|
-
""
|
|
99
|
-
If this is called when already instantiated in i24, it will return the existing object.
|
|
100
|
-
"""
|
|
101
|
-
return YZStage(
|
|
102
|
-
prefix=f"{PREFIX.beamline_prefix}-EA-DET-01:",
|
|
103
|
-
)
|
|
94
|
+
return YZStage(prefix=f"{PREFIX.beamline_prefix}-EA-DET-01:")
|
|
104
95
|
|
|
105
96
|
|
|
106
|
-
@
|
|
97
|
+
@devices.factory()
|
|
107
98
|
def dcm() -> DCM:
|
|
108
|
-
"""Get the i24 DCM device, instantiate it if it hasn't already been.
|
|
109
|
-
If this is called when already instantiated in i24, it will return the existing object.
|
|
110
|
-
"""
|
|
111
99
|
return DCM(
|
|
112
100
|
prefix=f"{PREFIX.beamline_prefix}-DI-DCM-01:",
|
|
113
101
|
motion_prefix=f"{PREFIX.beamline_prefix}-MO-DCM-01:",
|
|
114
102
|
)
|
|
115
103
|
|
|
116
104
|
|
|
117
|
-
|
|
118
|
-
# https://github.com/DiamondLightSource/mx-bluesky/issues/62
|
|
119
|
-
# @skip_device(lambda: BL == "s24")
|
|
120
|
-
# def eiger(
|
|
121
|
-
# wait_for_connection: bool = True,
|
|
122
|
-
# fake_with_ophyd_sim: bool = False,
|
|
123
|
-
# params: DetectorParams | None = None,
|
|
124
|
-
# ) -> EigerDetector:
|
|
125
|
-
# """Get the i24 Eiger device, instantiate it if it hasn't already been.
|
|
126
|
-
# If this is called when already instantiated, it will return the existing object.
|
|
127
|
-
# If called with params, will update those params to the Eiger object.
|
|
128
|
-
# """
|
|
129
|
-
#
|
|
130
|
-
# def set_params(eiger: EigerDetector):
|
|
131
|
-
# if params is not None:
|
|
132
|
-
# eiger.set_detector_parameters(params)
|
|
133
|
-
#
|
|
134
|
-
# return device_instantiation(
|
|
135
|
-
# device_factory=EigerDetector,
|
|
136
|
-
# name="eiger",
|
|
137
|
-
# prefix="-EA-EIGER-01:",
|
|
138
|
-
# wait=wait_for_connection,
|
|
139
|
-
# fake=fake_with_ophyd_sim,
|
|
140
|
-
# post_create=set_params,
|
|
141
|
-
# )
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
@device_factory()
|
|
105
|
+
@devices.factory()
|
|
145
106
|
def pmac() -> PMAC:
|
|
146
|
-
"""Get the i24 PMAC device, instantiate it if it hasn't already been.
|
|
147
|
-
If this is called when already instantiated in i24, it will return the existing object.
|
|
148
|
-
"""
|
|
149
107
|
return PMAC(PREFIX.beamline_prefix)
|
|
150
108
|
|
|
151
109
|
|
|
152
|
-
@
|
|
110
|
+
@devices.factory()
|
|
153
111
|
def oav() -> OAVBeamCentreFile:
|
|
154
112
|
return OAVBeamCentreFile(
|
|
155
113
|
prefix=f"{PREFIX.beamline_prefix}-DI-OAV-01:",
|
|
@@ -157,62 +115,54 @@ def oav() -> OAVBeamCentreFile:
|
|
|
157
115
|
)
|
|
158
116
|
|
|
159
117
|
|
|
160
|
-
@
|
|
118
|
+
@devices.factory()
|
|
161
119
|
def vgonio() -> VerticalGoniometer:
|
|
162
|
-
"""Get the i24 vertical goniometer device, instantiate it if it hasn't already been.
|
|
163
|
-
If this is called when already instantiated, it will return the existing object.
|
|
164
|
-
"""
|
|
165
120
|
return VerticalGoniometer(f"{PREFIX.beamline_prefix}-MO-VGON-01:")
|
|
166
121
|
|
|
167
122
|
|
|
168
|
-
@
|
|
123
|
+
@devices.factory()
|
|
169
124
|
def zebra() -> Zebra:
|
|
170
|
-
"""Get the i24 zebra device, instantiate it if it hasn't already been.
|
|
171
|
-
If this is called when already instantiated in i24, it will return the existing object.
|
|
172
|
-
"""
|
|
173
125
|
return Zebra(
|
|
174
126
|
prefix=f"{PREFIX.beamline_prefix}-EA-ZEBRA-01:",
|
|
175
127
|
mapping=I24_ZEBRA_MAPPING,
|
|
176
128
|
)
|
|
177
129
|
|
|
178
130
|
|
|
179
|
-
@
|
|
131
|
+
@devices.factory()
|
|
180
132
|
def shutter() -> HutchShutter:
|
|
181
|
-
"""Get the i24 hutch shutter device, instantiate it if it hasn't already been.
|
|
182
|
-
If this is called when already instantiated, it will return the existing object.
|
|
183
|
-
"""
|
|
184
133
|
return HutchShutter(f"{PREFIX.beamline_prefix}-PS-SHTR-01:")
|
|
185
134
|
|
|
186
135
|
|
|
187
|
-
@
|
|
136
|
+
@devices.factory()
|
|
188
137
|
def focus_mirrors() -> FocusMirrorsMode:
|
|
189
|
-
"""Get the i24 focus mirror devise to find the beam size."""
|
|
190
138
|
return FocusMirrorsMode(f"{PREFIX.beamline_prefix}-OP-MFM-01:")
|
|
191
139
|
|
|
192
140
|
|
|
193
|
-
@
|
|
141
|
+
@devices.factory()
|
|
194
142
|
def eiger_beam_center() -> DetectorBeamCenter:
|
|
195
|
-
""
|
|
196
|
-
return DetectorBeamCenter(
|
|
197
|
-
f"{PREFIX.beamline_prefix}-EA-EIGER-01:CAM:",
|
|
198
|
-
"eiger_bc",
|
|
199
|
-
)
|
|
143
|
+
return DetectorBeamCenter(f"{PREFIX.beamline_prefix}-EA-EIGER-01:CAM:", "eiger_bc")
|
|
200
144
|
|
|
201
145
|
|
|
202
|
-
@
|
|
146
|
+
@devices.factory()
|
|
203
147
|
def commissioning_jungfrau(
|
|
204
|
-
|
|
205
|
-
filename: str = "jf_output", # but these should be manually entered when commissioning
|
|
148
|
+
path_provider: PathProvider,
|
|
206
149
|
) -> CommissioningJungfrau:
|
|
207
150
|
"""Get the commissionning Jungfrau 9M device, which uses a temporary filewriter
|
|
208
|
-
device in place of Odin while the detector is in commissioning.
|
|
209
|
-
Instantiates the device if it hasn't already been.
|
|
210
|
-
If this is called when already instantiated, it will return the existing object."""
|
|
211
|
-
|
|
151
|
+
device in place of Odin while the detector is in commissioning."""
|
|
212
152
|
return CommissioningJungfrau(
|
|
213
153
|
f"{PREFIX.beamline_prefix}-EA-JFRAU-01:",
|
|
214
154
|
f"{PREFIX.beamline_prefix}-JUNGFRAU-META:FD:",
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
155
|
+
AutoMaxIncrementingPathProvider(path_provider),
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@devices.factory()
|
|
160
|
+
def synchrotron() -> Synchrotron:
|
|
161
|
+
return Synchrotron()
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@devices.factory()
|
|
165
|
+
def sample_shutter() -> ZebraShutter:
|
|
166
|
+
return ZebraShutter(
|
|
167
|
+
f"{PREFIX.beamline_prefix}-EA-SHTR-01:",
|
|
218
168
|
)
|
dodal/beamlines/p60.py
CHANGED
|
@@ -11,6 +11,7 @@ from dodal.devices.p60 import (
|
|
|
11
11
|
PassEnergy,
|
|
12
12
|
PsuMode,
|
|
13
13
|
)
|
|
14
|
+
from dodal.devices.selectable_source import SourceSelector
|
|
14
15
|
from dodal.log import set_beamline as set_log_beamline
|
|
15
16
|
from dodal.utils import BeamlinePrefix, get_beamline_name
|
|
16
17
|
|
|
@@ -20,6 +21,11 @@ set_log_beamline(BL)
|
|
|
20
21
|
set_utils_beamline(BL)
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
@device_factory()
|
|
25
|
+
def source_selector() -> SourceSelector:
|
|
26
|
+
return SourceSelector()
|
|
27
|
+
|
|
28
|
+
|
|
23
29
|
@device_factory()
|
|
24
30
|
def al_kalpha_source() -> LabXraySourceReadable:
|
|
25
31
|
return LabXraySourceReadable(LabXraySource.AL_KALPHA)
|
|
@@ -32,7 +38,11 @@ def mg_kalpha_source() -> LabXraySourceReadable:
|
|
|
32
38
|
|
|
33
39
|
@device_factory()
|
|
34
40
|
def energy_source() -> DualEnergySource:
|
|
35
|
-
return DualEnergySource(
|
|
41
|
+
return DualEnergySource(
|
|
42
|
+
al_kalpha_source().energy_ev,
|
|
43
|
+
mg_kalpha_source().energy_ev,
|
|
44
|
+
source_selector().selected_source,
|
|
45
|
+
)
|
|
36
46
|
|
|
37
47
|
|
|
38
48
|
# Connect will work again after this work completed
|
dodal/common/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from .coordination import group_uuid, inject
|
|
2
2
|
from .enums import EnabledDisabledUpper, InOutUpper, OnOffUpper
|
|
3
|
-
from .maths import in_micros, step_to_num
|
|
3
|
+
from .maths import Rectangle2D, in_micros, step_to_num
|
|
4
4
|
from .types import MsgGenerator, PlanGenerator
|
|
5
5
|
|
|
6
6
|
__all__ = [
|
|
@@ -13,4 +13,5 @@ __all__ = [
|
|
|
13
13
|
"MsgGenerator",
|
|
14
14
|
"PlanGenerator",
|
|
15
15
|
"step_to_num",
|
|
16
|
+
"Rectangle2D",
|
|
16
17
|
]
|
dodal/common/maths.py
CHANGED
|
@@ -48,3 +48,83 @@ def in_micros(t: float) -> int:
|
|
|
48
48
|
if t < 0:
|
|
49
49
|
raise ValueError(f"Expected a positive time in seconds, got {t!r}")
|
|
50
50
|
return int(np.ceil(t * 1e6))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class Rectangle2D:
|
|
54
|
+
"""
|
|
55
|
+
A 2D rectangle defined by two opposite corners.
|
|
56
|
+
|
|
57
|
+
This class represents a rectangle in 2D space using two points: (x1, y1) and (x2, y2).
|
|
58
|
+
It provides methods to query rectangle properties and check point containment.
|
|
59
|
+
|
|
60
|
+
Attributes:
|
|
61
|
+
x1 (float): The x-coordinate of the first corner.
|
|
62
|
+
y1 (float): The y-coordinate of the first corner.
|
|
63
|
+
x2 (float): The x-coordinate of the second corner.
|
|
64
|
+
y2 (float): The y-coordinate of the second corner.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def __init__(self, x1: float, y1: float, x2: float, y2: float):
|
|
68
|
+
"""
|
|
69
|
+
Initialize a Rectangle2D with two corner points.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
x1 (float): The x-coordinate of the first corner.
|
|
73
|
+
y1 (float): The y-coordinate of the first corner.
|
|
74
|
+
x2 (float): The x-coordinate of the second corner.
|
|
75
|
+
y2 (float): The y-coordinate of the second corner.
|
|
76
|
+
"""
|
|
77
|
+
self.x1, self.y1 = x1, y1
|
|
78
|
+
self.x2, self.y2 = x2, y2
|
|
79
|
+
|
|
80
|
+
def get_max_x(self) -> float:
|
|
81
|
+
"""
|
|
82
|
+
Get the maximum x-coordinate of the rectangle.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
float: The larger of the two x-coordinates (x1, x2).
|
|
86
|
+
"""
|
|
87
|
+
return max(self.x1, self.x2)
|
|
88
|
+
|
|
89
|
+
def get_min_x(self) -> float:
|
|
90
|
+
"""
|
|
91
|
+
Get the minimum x-coordinate of the rectangle.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
float: The smaller of the two x-coordinates (x1, x2).
|
|
95
|
+
"""
|
|
96
|
+
return min(self.x1, self.x2)
|
|
97
|
+
|
|
98
|
+
def get_max_y(self) -> float:
|
|
99
|
+
"""
|
|
100
|
+
Get the maximum y-coordinate of the rectangle.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
float: The larger of the two y-coordinates (y1, y2).
|
|
104
|
+
"""
|
|
105
|
+
return max(self.y1, self.y2)
|
|
106
|
+
|
|
107
|
+
def get_min_y(self) -> float:
|
|
108
|
+
"""
|
|
109
|
+
Get the minimum y-coordinate of the rectangle.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
float: The smaller of the two y-coordinates (y1, y2).
|
|
113
|
+
"""
|
|
114
|
+
return min(self.y1, self.y2)
|
|
115
|
+
|
|
116
|
+
def contains(self, x: float, y: float) -> bool:
|
|
117
|
+
"""
|
|
118
|
+
Check if a point is contained within the rectangle.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
x (float): The x-coordinate of the point.
|
|
122
|
+
y (float): The y-coordinate of the point.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
bool: True if the point is within the rectangle bounds, False otherwise.
|
|
126
|
+
"""
|
|
127
|
+
return (
|
|
128
|
+
self.get_min_x() <= x <= self.get_max_x()
|
|
129
|
+
and self.get_min_y() <= y <= self.get_max_y()
|
|
130
|
+
)
|
dodal/devices/eiger.py
CHANGED
|
@@ -4,6 +4,7 @@ from enum import Enum
|
|
|
4
4
|
from bluesky.protocols import Stageable
|
|
5
5
|
from ophyd import Component, Device, EpicsSignalRO, Signal
|
|
6
6
|
from ophyd.areadetector.cam import EigerDetectorCam
|
|
7
|
+
from ophyd.signal import AttributeSignal
|
|
7
8
|
from ophyd.status import AndStatus, Status, StatusBase, SubscriptionStatus
|
|
8
9
|
|
|
9
10
|
from dodal.devices.detector import DetectorParams, TriggerMode
|
|
@@ -55,7 +56,6 @@ class EigerDetector(Device, Stageable):
|
|
|
55
56
|
|
|
56
57
|
stale_params = Component(EpicsSignalRO, "CAM:StaleParameters_RBV")
|
|
57
58
|
bit_depth = Component(EpicsSignalRO, "CAM:BitDepthImage_RBV")
|
|
58
|
-
|
|
59
59
|
filewriters_finished: StatusBase
|
|
60
60
|
|
|
61
61
|
detector_params: DetectorParams | None = None
|
|
@@ -63,9 +63,24 @@ class EigerDetector(Device, Stageable):
|
|
|
63
63
|
arming_status = Status()
|
|
64
64
|
arming_status.set_finished()
|
|
65
65
|
|
|
66
|
-
def __init__(
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
beamline: str = "i03",
|
|
69
|
+
ispyb_detector_id: int | None = None,
|
|
70
|
+
*args,
|
|
71
|
+
**kwargs,
|
|
72
|
+
):
|
|
67
73
|
super().__init__(*args, **kwargs)
|
|
68
74
|
self.beamline = beamline
|
|
75
|
+
|
|
76
|
+
self.detector_id = ispyb_detector_id
|
|
77
|
+
self.ispyb_detector_id = AttributeSignal(
|
|
78
|
+
attr="detector_id",
|
|
79
|
+
parent=self,
|
|
80
|
+
name="eiger-ispyb_detector_id",
|
|
81
|
+
write_access=False,
|
|
82
|
+
)
|
|
83
|
+
|
|
69
84
|
# using i03 timeouts as default
|
|
70
85
|
self.timeouts = AVAILABLE_TIMEOUTS.get(beamline, AVAILABLE_TIMEOUTS["i03"])
|
|
71
86
|
self.disarming_status = None
|
|
@@ -74,10 +89,11 @@ class EigerDetector(Device, Stageable):
|
|
|
74
89
|
def with_params(
|
|
75
90
|
cls,
|
|
76
91
|
params: DetectorParams,
|
|
77
|
-
name: str = "EigerDetector",
|
|
78
92
|
beamline: str = "i03",
|
|
93
|
+
ispyb_detector_id: int | None = None,
|
|
94
|
+
name: str = "EigerDetector",
|
|
79
95
|
):
|
|
80
|
-
det = cls(name=name, beamline=beamline)
|
|
96
|
+
det = cls(name=name, beamline=beamline, ispyb_detector_id=ispyb_detector_id)
|
|
81
97
|
det.set_detector_parameters(params)
|
|
82
98
|
return det
|
|
83
99
|
|
|
@@ -286,25 +302,24 @@ class EigerDetector(Device, Stageable):
|
|
|
286
302
|
beam_x_pixels, beam_y_pixels = self.detector_params.get_beam_position_pixels(
|
|
287
303
|
self.detector_params.detector_distance
|
|
288
304
|
)
|
|
289
|
-
|
|
305
|
+
self.cam.beam_center_x.set(
|
|
290
306
|
beam_x_pixels, timeout=self.timeouts.general_status_timeout
|
|
291
|
-
)
|
|
292
|
-
|
|
307
|
+
).wait(timeout=self.timeouts.general_status_timeout)
|
|
308
|
+
self.cam.beam_center_y.set(
|
|
293
309
|
beam_y_pixels, timeout=self.timeouts.general_status_timeout
|
|
294
|
-
)
|
|
295
|
-
|
|
310
|
+
).wait(timeout=self.timeouts.general_status_timeout)
|
|
311
|
+
self.cam.det_distance.set(
|
|
296
312
|
self.detector_params.detector_distance,
|
|
297
313
|
timeout=self.timeouts.general_status_timeout,
|
|
298
|
-
)
|
|
299
|
-
|
|
314
|
+
).wait(timeout=self.timeouts.general_status_timeout)
|
|
315
|
+
self.cam.omega_start.set(
|
|
300
316
|
self.detector_params.omega_start,
|
|
301
317
|
timeout=self.timeouts.general_status_timeout,
|
|
302
|
-
)
|
|
303
|
-
status
|
|
318
|
+
).wait(timeout=self.timeouts.general_status_timeout)
|
|
319
|
+
status = self.cam.omega_incr.set(
|
|
304
320
|
self.detector_params.omega_increment,
|
|
305
321
|
timeout=self.timeouts.general_status_timeout,
|
|
306
322
|
)
|
|
307
|
-
|
|
308
323
|
return status
|
|
309
324
|
|
|
310
325
|
def set_detector_threshold(self, energy: float, tolerance: float = 0.1) -> Status:
|
|
@@ -15,7 +15,7 @@ from .base_driver_io import (
|
|
|
15
15
|
GenericAnalyserDriverIO,
|
|
16
16
|
TAbstractAnalyserDriverIO,
|
|
17
17
|
)
|
|
18
|
-
from .base_enums import EnergyMode
|
|
18
|
+
from .base_enums import EnergyMode
|
|
19
19
|
from .base_region import (
|
|
20
20
|
AbstractBaseRegion,
|
|
21
21
|
AbstractBaseSequence,
|
|
@@ -27,7 +27,7 @@ from .base_region import (
|
|
|
27
27
|
TLensMode,
|
|
28
28
|
)
|
|
29
29
|
from .base_util import to_binding_energy, to_kinetic_energy
|
|
30
|
-
from .energy_sources import DualEnergySource, EnergySource
|
|
30
|
+
from .energy_sources import AbstractEnergySource, DualEnergySource, EnergySource
|
|
31
31
|
|
|
32
32
|
__all__ = [
|
|
33
33
|
"ElectronAnalyserController",
|
|
@@ -42,7 +42,6 @@ __all__ = [
|
|
|
42
42
|
"GenericAnalyserDriverIO",
|
|
43
43
|
"TAbstractAnalyserDriverIO",
|
|
44
44
|
"EnergyMode",
|
|
45
|
-
"SelectedSource",
|
|
46
45
|
"AbstractBaseRegion",
|
|
47
46
|
"AbstractBaseSequence",
|
|
48
47
|
"GenericRegion",
|
|
@@ -53,6 +52,7 @@ __all__ = [
|
|
|
53
52
|
"TLensMode",
|
|
54
53
|
"to_binding_energy",
|
|
55
54
|
"to_kinetic_energy",
|
|
55
|
+
"AbstractEnergySource",
|
|
56
56
|
"DualEnergySource",
|
|
57
57
|
"EnergySource",
|
|
58
58
|
]
|