dls-dodal 1.69.0__py3-none-any.whl → 2.0.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.69.0.dist-info → dls_dodal-2.0.0.dist-info}/METADATA +1 -1
- dls_dodal-2.0.0.dist-info/RECORD +354 -0
- {dls_dodal-1.69.0.dist-info → dls_dodal-2.0.0.dist-info}/WHEEL +1 -1
- dodal/_version.py +2 -2
- dodal/beamlines/__init__.py +10 -17
- dodal/beamlines/adsim.py +17 -17
- dodal/beamlines/b01_1.py +11 -0
- dodal/beamlines/b07.py +17 -21
- dodal/beamlines/b07_1.py +20 -22
- dodal/beamlines/b07_shared.py +12 -0
- dodal/beamlines/b16.py +1 -1
- dodal/beamlines/b21.py +15 -6
- dodal/beamlines/i02_1.py +3 -3
- dodal/beamlines/i02_2.py +1 -1
- dodal/beamlines/i03.py +4 -4
- dodal/beamlines/i04.py +16 -8
- dodal/beamlines/i05.py +7 -45
- dodal/beamlines/i05_1.py +4 -13
- dodal/beamlines/i05_shared.py +51 -0
- dodal/beamlines/i06_1.py +7 -5
- dodal/beamlines/{i06.py → i06_shared.py} +25 -14
- dodal/beamlines/i07.py +14 -16
- dodal/beamlines/i09.py +54 -51
- dodal/beamlines/i09_1.py +25 -64
- dodal/beamlines/i09_1_shared.py +61 -0
- dodal/beamlines/i09_2.py +6 -100
- dodal/beamlines/i09_2_shared.py +110 -0
- dodal/beamlines/i10.py +60 -54
- dodal/beamlines/i10_1.py +99 -10
- dodal/beamlines/{i10_optics.py → i10_shared.py} +80 -66
- dodal/beamlines/i11.py +31 -18
- dodal/beamlines/i13_1.py +1 -1
- dodal/beamlines/i15.py +6 -6
- dodal/beamlines/i15_1.py +6 -6
- dodal/beamlines/i17.py +37 -28
- dodal/beamlines/i18.py +3 -4
- dodal/beamlines/i19_1.py +95 -34
- dodal/beamlines/i19_2.py +68 -52
- dodal/beamlines/i19_optics.py +26 -13
- dodal/beamlines/i20_1.py +6 -14
- dodal/beamlines/i21.py +35 -28
- dodal/beamlines/i22.py +19 -4
- dodal/beamlines/i23.py +1 -2
- dodal/beamlines/i24.py +11 -10
- dodal/beamlines/k07.py +99 -5
- dodal/beamlines/p38.py +3 -3
- dodal/beamlines/p60.py +28 -17
- dodal/beamlines/p99.py +16 -15
- dodal/beamlines/training_rig.py +20 -12
- dodal/cli.py +36 -2
- dodal/common/beamlines/beamline_parameters.py +2 -1
- dodal/common/beamlines/beamline_utils.py +11 -9
- dodal/common/beamlines/commissioning_mode.py +6 -3
- dodal/common/coordination.py +12 -14
- dodal/common/crystal_metadata.py +5 -8
- dodal/common/device_utils.py +4 -3
- dodal/common/maths.py +28 -40
- dodal/common/udc_directory_provider.py +13 -8
- dodal/common/visit.py +18 -21
- dodal/common/watcher_utils.py +13 -12
- dodal/device_manager.py +94 -54
- dodal/devices/aperturescatterguard.py +26 -27
- dodal/devices/areadetector/plugins/cam.py +1 -3
- dodal/devices/areadetector/plugins/mjpg.py +6 -5
- dodal/devices/attenuator/attenuator.py +12 -11
- dodal/devices/beamlines/b07/__init__.py +3 -0
- dodal/devices/{b07_1 → beamlines/b07_1}/__init__.py +2 -2
- dodal/devices/{b07_1 → beamlines/b07_1}/ccmc.py +5 -10
- dodal/devices/{b16 → beamlines/b16}/detector.py +2 -3
- dodal/devices/{i02_1 → beamlines/i02_1}/fast_grid_scan.py +2 -3
- dodal/devices/{i02_1 → beamlines/i02_1}/sample_motors.py +1 -1
- dodal/devices/{i03 → beamlines/i03}/beamsize.py +11 -7
- dodal/devices/{i03 → beamlines/i03}/dcm.py +1 -2
- dodal/devices/{i03 → beamlines/i03}/undulator_dcm.py +4 -5
- dodal/devices/beamlines/i04/beam_centre.py +151 -0
- dodal/devices/{i04 → beamlines/i04}/beamsize.py +11 -7
- dodal/devices/{i04 → beamlines/i04}/murko_results.py +5 -5
- dodal/devices/{i04 → beamlines/i04}/transfocator.py +10 -15
- dodal/devices/beamlines/i05/__init__.py +3 -0
- dodal/devices/beamlines/i06_shared/__init__.py +3 -0
- dodal/devices/beamlines/i06_shared/i06_enum.py +7 -0
- dodal/devices/{i07 → beamlines/i07}/dcm.py +2 -3
- dodal/devices/{i07 → beamlines/i07}/id.py +8 -9
- dodal/devices/beamlines/i09/__init__.py +3 -0
- dodal/devices/{i09_1_shared → beamlines/i09_1_shared}/hard_energy.py +5 -6
- dodal/devices/{i09_1_shared → beamlines/i09_1_shared}/hard_undulator_functions.py +19 -16
- dodal/devices/{i10 → beamlines/i10}/diagnostics.py +4 -3
- dodal/devices/{i10 → beamlines/i10}/i10_apple2.py +31 -45
- dodal/devices/{i10 → beamlines/i10}/rasor/rasor_current_amp.py +1 -24
- dodal/devices/{i10 → beamlines/i10}/rasor/rasor_motors.py +2 -2
- dodal/devices/{i10 → beamlines/i10}/slits.py +5 -3
- dodal/devices/beamlines/i10_1/__init__.py +9 -0
- dodal/devices/beamlines/i10_1/electromagnet/magnet.py +16 -0
- dodal/devices/beamlines/i10_1/electromagnet/stages.py +14 -0
- dodal/devices/beamlines/i10_1/scaler_cards.py +13 -0
- dodal/devices/{i11 → beamlines/i11}/cyberstar_blower.py +1 -1
- dodal/devices/{i11 → beamlines/i11}/diff_stages.py +4 -6
- dodal/devices/{i11 → beamlines/i11}/mythen.py +3 -4
- dodal/devices/{i11 → beamlines/i11}/nx100robot.py +6 -6
- dodal/devices/{i11 → beamlines/i11}/spinner.py +1 -1
- dodal/devices/{i13_1 → beamlines/i13_1}/merlin.py +1 -1
- dodal/devices/{i15 → beamlines/i15}/dcm.py +1 -2
- dodal/devices/{i15 → beamlines/i15}/focussing_mirror.py +5 -5
- dodal/devices/{i15 → beamlines/i15}/jack.py +2 -2
- dodal/devices/{i15 → beamlines/i15}/multilayer_mirror.py +1 -1
- dodal/devices/{i17 → beamlines/i17}/i17_apple2.py +10 -16
- dodal/devices/{i18 → beamlines/i18}/diode.py +1 -1
- dodal/devices/{i19 → beamlines/i19}/access_controlled/attenuator_motor_squad.py +12 -8
- dodal/devices/{i19 → beamlines/i19}/access_controlled/blueapi_device.py +16 -15
- dodal/devices/beamlines/i19/access_controlled/piezo_control.py +72 -0
- dodal/devices/{i19 → beamlines/i19}/access_controlled/shutter.py +11 -9
- dodal/devices/{i19 → beamlines/i19}/backlight.py +3 -1
- dodal/devices/{i19 → beamlines/i19}/mapt_configuration.py +2 -1
- dodal/devices/{i19 → beamlines/i19}/pin_col_stages.py +11 -8
- dodal/devices/beamlines/i19/pin_tip.py +32 -0
- dodal/devices/beamlines/i21/__init__.py +3 -0
- dodal/devices/{i22 → beamlines/i22}/dcm.py +1 -2
- dodal/devices/{i22 → beamlines/i22}/fswitch.py +1 -3
- dodal/devices/{i22 → beamlines/i22}/nxsas.py +5 -4
- dodal/devices/{i24 → beamlines/i24}/beam_center.py +1 -1
- dodal/devices/{i24 → beamlines/i24}/beamstop.py +2 -2
- dodal/devices/{i24 → beamlines/i24}/commissioning_jungfrau.py +3 -2
- dodal/devices/{i24 → beamlines/i24}/dcm.py +1 -3
- dodal/devices/{i24 → beamlines/i24}/dual_backlight.py +3 -3
- dodal/devices/{i24 → beamlines/i24}/pmac.py +9 -7
- dodal/devices/{p60 → beamlines/p60}/lab_xray_source.py +1 -1
- dodal/devices/beamlines/p99/__init__.py +0 -0
- dodal/devices/{p99 → beamlines/p99}/andor2_point.py +11 -15
- dodal/devices/bimorph_mirror.py +22 -20
- dodal/devices/collimation_table.py +3 -2
- dodal/devices/common_dcm.py +30 -20
- dodal/devices/controllers.py +2 -2
- dodal/devices/cryostream.py +8 -0
- dodal/devices/current_amplifiers/current_amplifier.py +16 -18
- dodal/devices/current_amplifiers/current_amplifier_detector.py +9 -10
- dodal/devices/current_amplifiers/femto.py +8 -9
- dodal/devices/current_amplifiers/sr570.py +16 -16
- dodal/devices/current_amplifiers/struck_scaler_counter.py +5 -5
- dodal/devices/detector/det_resolution.py +9 -8
- dodal/devices/detector/detector.py +4 -2
- dodal/devices/diamond_filter.py +3 -4
- dodal/devices/eiger.py +3 -3
- dodal/devices/eiger_odin.py +1 -1
- dodal/devices/electron_analyser/base/base_controller.py +13 -13
- dodal/devices/electron_analyser/base/base_detector.py +15 -20
- dodal/devices/electron_analyser/base/base_driver_io.py +39 -46
- dodal/devices/electron_analyser/base/base_region.py +27 -30
- dodal/devices/electron_analyser/base/base_util.py +18 -16
- dodal/devices/electron_analyser/base/energy_sources.py +13 -19
- dodal/devices/eurotherm.py +3 -2
- dodal/devices/fast_grid_scan.py +31 -34
- dodal/devices/fast_shutter.py +24 -21
- dodal/devices/flux.py +1 -1
- dodal/devices/focusing_mirror.py +29 -11
- dodal/devices/hutch_shutter.py +6 -6
- dodal/devices/insertion_device/__init__.py +8 -0
- dodal/devices/insertion_device/apple2_controller.py +51 -60
- dodal/devices/insertion_device/apple2_undulator.py +40 -64
- dodal/devices/insertion_device/apple_knot_controller.py +222 -0
- dodal/devices/insertion_device/energy.py +100 -27
- dodal/devices/insertion_device/energy_motor_lookup.py +20 -27
- dodal/devices/insertion_device/lookup_table_models.py +45 -50
- dodal/devices/insertion_device/polarisation.py +1 -1
- dodal/devices/ipin.py +1 -1
- dodal/devices/linkam3.py +7 -5
- dodal/devices/motors.py +107 -19
- dodal/devices/mx_phase1/beamstop.py +2 -4
- dodal/devices/oav/oav_calculations.py +20 -13
- dodal/devices/oav/oav_detector.py +28 -23
- dodal/devices/oav/oav_parameters.py +4 -9
- dodal/devices/oav/oav_to_redis_forwarder.py +22 -18
- dodal/devices/oav/pin_image_recognition/__init__.py +4 -6
- dodal/devices/oav/pin_image_recognition/manual_test.py +1 -2
- dodal/devices/oav/pin_image_recognition/utils.py +30 -32
- dodal/devices/oav/snapshots/grid_overlay.py +10 -9
- dodal/devices/oav/snapshots/snapshot_image_processing.py +15 -13
- dodal/devices/oav/utils.py +9 -12
- dodal/devices/p45.py +3 -9
- dodal/devices/pgm.py +8 -14
- dodal/devices/pressure_jump_cell.py +93 -32
- dodal/devices/qbpm.py +1 -3
- dodal/devices/robot.py +12 -4
- dodal/devices/s4_slit_gaps.py +1 -1
- dodal/devices/selectable_source.py +5 -2
- dodal/devices/slits.py +2 -5
- dodal/devices/smargon.py +2 -3
- dodal/devices/temperture_controller/lakeshore/lakeshore.py +38 -64
- dodal/devices/temperture_controller/lakeshore/lakeshore_io.py +21 -35
- dodal/devices/tetramm.py +7 -7
- dodal/devices/turbo_slit.py +8 -7
- dodal/devices/undulator.py +42 -56
- dodal/devices/util/adjuster_plans.py +2 -3
- dodal/devices/util/epics_util.py +10 -10
- dodal/devices/util/lookup_tables.py +17 -18
- dodal/devices/v2f.py +2 -3
- dodal/devices/watsonmarlow323_pump.py +1 -1
- dodal/devices/xbpm_feedback.py +3 -2
- dodal/devices/xspress3/xspress3.py +8 -11
- dodal/devices/xspress3/xspress3_channel.py +3 -6
- dodal/devices/zebra/zebra.py +6 -7
- dodal/devices/zebra/zebra_constants_mapping.py +11 -7
- dodal/devices/zebra/zebra_controlled_shutter.py +2 -1
- dodal/devices/zocalo/zocalo_interaction.py +14 -14
- dodal/devices/zocalo/zocalo_results.py +33 -33
- dodal/log.py +23 -20
- dodal/plan_stubs/check_topup.py +15 -15
- dodal/plan_stubs/data_session.py +6 -6
- dodal/plan_stubs/motor_utils.py +22 -18
- dodal/plan_stubs/pressure_jump_cell.py +18 -0
- dodal/plan_stubs/wrapped.py +40 -55
- dodal/plans/bimorph.py +63 -52
- dodal/plans/device_setup_plans/__init__.py +5 -0
- dodal/plans/device_setup_plans/setup_pin_tip_params.py +63 -0
- dodal/plans/preprocessors/verify_undulator_gap.py +10 -8
- dodal/plans/spec_path.py +3 -5
- dodal/plans/verify_undulator_gap.py +1 -2
- dodal/plans/wrapped.py +4 -3
- dodal/testing/electron_analyser/device_factory.py +5 -7
- dodal/testing/fixtures/devices/apple2.py +38 -0
- dodal/testing/fixtures/run_engine.py +3 -7
- dodal/testing/fixtures/utils.py +1 -2
- dodal/utils.py +60 -58
- dls_dodal-1.69.0.dist-info/RECORD +0 -338
- dodal/beamline_specific_utils/i05_shared.py +0 -14
- dodal/devices/b07/__init__.py +0 -3
- dodal/devices/i04/beam_centre.py +0 -84
- dodal/devices/i05/__init__.py +0 -3
- dodal/devices/i09/__init__.py +0 -3
- dodal/devices/i21/__init__.py +0 -5
- {dls_dodal-1.69.0.dist-info → dls_dodal-2.0.0.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.69.0.dist-info → dls_dodal-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.69.0.dist-info → dls_dodal-2.0.0.dist-info}/top_level.txt +0 -0
- /dodal/{beamline_specific_utils → devices/beamlines}/__init__.py +0 -0
- /dodal/devices/{b07 → beamlines/b07}/enums.py +0 -0
- /dodal/devices/{b07_1 → beamlines/b07_1}/enums.py +0 -0
- /dodal/devices/{b16 → beamlines/b16}/__init__.py +0 -0
- /dodal/devices/{i02_1 → beamlines/i02_1}/__init__.py +0 -0
- /dodal/devices/{i02_2 → beamlines/i02_2}/__init__.py +0 -0
- /dodal/devices/{i03 → beamlines/i03}/__init__.py +0 -0
- /dodal/devices/{i03 → beamlines/i03}/constants.py +0 -0
- /dodal/devices/{i04 → beamlines/i04}/__init__.py +0 -0
- /dodal/devices/{i04 → beamlines/i04}/constants.py +0 -0
- /dodal/devices/{i04 → beamlines/i04}/max_pixel.py +0 -0
- /dodal/devices/{i05 → beamlines/i05}/enums.py +0 -0
- /dodal/devices/{i07 → beamlines/i07}/__init__.py +0 -0
- /dodal/devices/{i09 → beamlines/i09}/enums.py +0 -0
- /dodal/devices/{i09_1 → beamlines/i09_1}/__init__.py +0 -0
- /dodal/devices/{i09_1 → beamlines/i09_1}/enums.py +0 -0
- /dodal/devices/{i09_1_shared → beamlines/i09_1_shared}/__init__.py +0 -0
- /dodal/devices/{i09_2_shared → beamlines/i09_2_shared}/__init__.py +0 -0
- /dodal/devices/{i09_2_shared → beamlines/i09_2_shared}/i09_apple2.py +0 -0
- /dodal/devices/{i10 → beamlines/i10}/__init__.py +0 -0
- /dodal/devices/{i10 → beamlines/i10}/i10_setting_data.py +0 -0
- /dodal/devices/{i10 → beamlines/i10}/mirrors.py +0 -0
- /dodal/devices/{i10 → beamlines/i10}/rasor/__init__.py +0 -0
- /dodal/devices/{i10 → beamlines/i10}/rasor/rasor_scaler_cards.py +0 -0
- /dodal/devices/{i11 → beamlines/i10_1/electromagnet}/__init__.py +0 -0
- /dodal/devices/{i13_1 → beamlines/i11}/__init__.py +0 -0
- /dodal/devices/{i15 → beamlines/i13_1}/__init__.py +0 -0
- /dodal/devices/{i13_1 → beamlines/i13_1}/merlin_controller.py +0 -0
- /dodal/devices/{i17 → beamlines/i15}/__init__.py +0 -0
- /dodal/devices/{i15 → beamlines/i15}/laue.py +0 -0
- /dodal/devices/{i15 → beamlines/i15}/motors.py +0 -0
- /dodal/devices/{i15 → beamlines/i15}/rail.py +0 -0
- /dodal/devices/{i18 → beamlines/i17}/__init__.py +0 -0
- /dodal/devices/{i19 → beamlines/i18}/__init__.py +0 -0
- /dodal/devices/{i18 → beamlines/i18}/kb_mirror.py +0 -0
- /dodal/devices/{i19/access_controlled → beamlines/i19}/__init__.py +0 -0
- /dodal/devices/{i20_1 → beamlines/i19/access_controlled}/__init__.py +0 -0
- /dodal/devices/{i19 → beamlines/i19}/access_controlled/hutch_access.py +0 -0
- /dodal/devices/{i19 → beamlines/i19}/beamstop.py +0 -0
- /dodal/devices/{i19 → beamlines/i19}/diffractometer.py +0 -0
- /dodal/devices/{i22 → beamlines/i20_1}/__init__.py +0 -0
- /dodal/devices/{i21 → beamlines/i21}/enums.py +0 -0
- /dodal/devices/{i24 → beamlines/i22}/__init__.py +0 -0
- /dodal/devices/{p99 → beamlines/i24}/__init__.py +0 -0
- /dodal/devices/{i24 → beamlines/i24}/aperture.py +0 -0
- /dodal/devices/{i24 → beamlines/i24}/focus_mirrors.py +0 -0
- /dodal/devices/{i24 → beamlines/i24}/vgonio.py +0 -0
- /dodal/devices/{p60 → beamlines/p60}/__init__.py +0 -0
- /dodal/devices/{p60 → beamlines/p60}/enums.py +0 -0
- /dodal/devices/{p99 → beamlines/p99}/sample_stage.py +0 -0
dodal/devices/focusing_mirror.py
CHANGED
|
@@ -27,7 +27,7 @@ DEFAULT_SETTLE_TIME_S = 60
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class MirrorType(StrictEnum):
|
|
30
|
-
"""See https://manual.nexusformat.org/classes/base_classes/NXmirror.html"""
|
|
30
|
+
"""See https://manual.nexusformat.org/classes/base_classes/NXmirror.html."""
|
|
31
31
|
|
|
32
32
|
SINGLE = "single"
|
|
33
33
|
MULTI = "multi"
|
|
@@ -53,8 +53,9 @@ class MirrorVoltageDemand(StrictEnum):
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
class SingleMirrorVoltage(Device):
|
|
56
|
-
"""Abstract the bimorph mirror voltage PVs into a single device that can be set
|
|
57
|
-
the demanded voltage setpoint is accepted, without
|
|
56
|
+
"""Abstract the bimorph mirror voltage PVs into a single device that can be set
|
|
57
|
+
asynchronously and returns when the demanded voltage setpoint is accepted, without
|
|
58
|
+
blocking the caller as this process can take significant time.
|
|
58
59
|
"""
|
|
59
60
|
|
|
60
61
|
def __init__(self, prefix: str, name: str = ""):
|
|
@@ -66,11 +67,14 @@ class SingleMirrorVoltage(Device):
|
|
|
66
67
|
@AsyncStatus.wrap
|
|
67
68
|
async def set(self, value, *args, **kwargs):
|
|
68
69
|
"""Combine the following operations into a single set:
|
|
69
|
-
1. apply the value to the setpoint PV
|
|
70
|
-
3. Wait until demand is accepted
|
|
71
|
-
4. When either demand is accepted or DEFAULT_SETTLE_TIME expires, signal the result on the Status
|
|
72
|
-
"""
|
|
73
70
|
|
|
71
|
+
1. apply the value to the setpoint PV.
|
|
72
|
+
|
|
73
|
+
3. Wait until demand is accepted.
|
|
74
|
+
|
|
75
|
+
4. When either demand is accepted or DEFAULT_SETTLE_TIME expires, signal the
|
|
76
|
+
result on the Status.
|
|
77
|
+
""" # noqa D415
|
|
74
78
|
setpoint_v = self._setpoint_v
|
|
75
79
|
demand_accepted = self._demand_accepted
|
|
76
80
|
|
|
@@ -136,7 +140,7 @@ class MirrorVoltages(StandardReadable):
|
|
|
136
140
|
|
|
137
141
|
|
|
138
142
|
class SimpleMirror(XYPitchStage):
|
|
139
|
-
"""Simple Focusing Mirror"""
|
|
143
|
+
"""Simple Focusing Mirror."""
|
|
140
144
|
|
|
141
145
|
def __init__(
|
|
142
146
|
self,
|
|
@@ -165,7 +169,7 @@ class SimpleMirror(XYPitchStage):
|
|
|
165
169
|
|
|
166
170
|
|
|
167
171
|
class FocusingMirror(StandardReadable):
|
|
168
|
-
"""Focusing Mirror"""
|
|
172
|
+
"""Focusing Mirror."""
|
|
169
173
|
|
|
170
174
|
def __init__(
|
|
171
175
|
self,
|
|
@@ -202,7 +206,8 @@ class FocusingMirror(StandardReadable):
|
|
|
202
206
|
|
|
203
207
|
class FocusingMirrorWithStripes(FocusingMirror):
|
|
204
208
|
"""A focusing mirror where the stripe material can be changed. This is usually done
|
|
205
|
-
based on the energy of the beamline.
|
|
209
|
+
based on the energy of the beamline.
|
|
210
|
+
"""
|
|
206
211
|
|
|
207
212
|
def __init__(self, prefix: str, name: str = "", *args, **kwargs):
|
|
208
213
|
self.stripe = epics_signal_rw(MirrorStripe, prefix + "STRP:DVAL")
|
|
@@ -212,9 +217,22 @@ class FocusingMirrorWithStripes(FocusingMirror):
|
|
|
212
217
|
super().__init__(prefix, name, *args, **kwargs)
|
|
213
218
|
|
|
214
219
|
def energy_to_stripe(self, energy_kev) -> MirrorStripeConfiguration:
|
|
215
|
-
"""Return the stripe, yaw angle and lateral position for the specified energy"""
|
|
220
|
+
"""Return the stripe, yaw angle and lateral position for the specified energy."""
|
|
216
221
|
# In future, this should be configurable per-mirror
|
|
217
222
|
if energy_kev < 7:
|
|
218
223
|
return {"stripe": MirrorStripe.BARE, "yaw_mrad": 6.2, "lat_mm": 0.0}
|
|
219
224
|
else:
|
|
220
225
|
return {"stripe": MirrorStripe.RHODIUM, "yaw_mrad": 0.0, "lat_mm": 10.0}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class FocusingMirrorWithPiezo(FocusingMirror):
|
|
229
|
+
"""A focusing mirror which also has a piezoelectric actuator.
|
|
230
|
+
A voltage can be applied to the piezo to steer the beam by making the material
|
|
231
|
+
shrink or expand.
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
def __init__(self, prefix: str, name: str = "", *args, **kwargs):
|
|
235
|
+
with self.add_children_as_readables():
|
|
236
|
+
self.piezo = epics_signal_rw(float, f"{prefix}AOFPITCH")
|
|
237
|
+
self.piezo_rbv = epics_signal_r(float, f"{prefix}AOFPITCH:RBV")
|
|
238
|
+
super().__init__(prefix, name, *args, **kwargs)
|
dodal/devices/hutch_shutter.py
CHANGED
|
@@ -58,14 +58,14 @@ class HutchInterlock(StandardReadable):
|
|
|
58
58
|
class HutchShutter(StandardReadable, Movable[ShutterDemand]):
|
|
59
59
|
"""Device to operate the hutch shutter.
|
|
60
60
|
|
|
61
|
-
When a demand is sent, the device should first check the hutch status
|
|
62
|
-
and raise an error if it's not interlocked (searched and locked), meaning it's not
|
|
61
|
+
When a demand is sent, the device should first check the hutch status
|
|
62
|
+
and raise an error if it's not interlocked (searched and locked), meaning it's not
|
|
63
63
|
safe to operate the shutter.
|
|
64
64
|
|
|
65
|
-
If the requested shutter position is "Open", the shutter control PV should first
|
|
66
|
-
go to "Reset" and then move to "Open". This is because before opening the hutch
|
|
67
|
-
shutter, the interlock status PV (`-PS-SHTR-01:ILKSTA`) will show as `failed` until
|
|
68
|
-
the hutch shutter is reset. This will set the interlock status to `OK`, allowing
|
|
65
|
+
If the requested shutter position is "Open", the shutter control PV should first
|
|
66
|
+
go to "Reset" and then move to "Open". This is because before opening the hutch
|
|
67
|
+
shutter, the interlock status PV (`-PS-SHTR-01:ILKSTA`) will show as `failed` until
|
|
68
|
+
the hutch shutter is reset. This will set the interlock status to `OK`, allowing
|
|
69
69
|
for shutter operations. Until this step is done, the hutch shutter can't be opened.
|
|
70
70
|
The reset is not needed for closing the shutter.
|
|
71
71
|
"""
|
|
@@ -2,6 +2,7 @@ from .apple2_controller import (
|
|
|
2
2
|
MAXIMUM_MOVE_TIME,
|
|
3
3
|
Apple2Controller,
|
|
4
4
|
Apple2EnforceLHMoveController,
|
|
5
|
+
Apple2Type,
|
|
5
6
|
EnergyMotorConvertor,
|
|
6
7
|
)
|
|
7
8
|
from .apple2_undulator import (
|
|
@@ -17,6 +18,10 @@ from .apple2_undulator import (
|
|
|
17
18
|
UndulatorPhaseAxes,
|
|
18
19
|
UnstoppableMotor,
|
|
19
20
|
)
|
|
21
|
+
from .apple_knot_controller import (
|
|
22
|
+
AppleKnotController,
|
|
23
|
+
AppleKnotPathFinder,
|
|
24
|
+
)
|
|
20
25
|
from .energy import BeamEnergy, InsertionDeviceEnergy, InsertionDeviceEnergyBase
|
|
21
26
|
from .energy_motor_lookup import (
|
|
22
27
|
ConfigServerEnergyMotorLookup,
|
|
@@ -33,8 +38,11 @@ from .polarisation import InsertionDevicePolarisation
|
|
|
33
38
|
|
|
34
39
|
__all__ = [
|
|
35
40
|
"Apple2",
|
|
41
|
+
"Apple2Type",
|
|
36
42
|
"Apple2Controller",
|
|
37
43
|
"Apple2EnforceLHMoveController",
|
|
44
|
+
"AppleKnotController",
|
|
45
|
+
"AppleKnotPathFinder",
|
|
38
46
|
"UndulatorGap",
|
|
39
47
|
"UndulatorPhaseAxes",
|
|
40
48
|
"UndulatorJawPhase",
|
|
@@ -33,7 +33,7 @@ MAXIMUM_GAP_MOTOR_POSITION = 100
|
|
|
33
33
|
|
|
34
34
|
class EnergyMotorConvertor(Protocol):
|
|
35
35
|
def __call__(self, energy: float, pol: Pol) -> float:
|
|
36
|
-
"""Protocol to provide energy to motor position conversion"""
|
|
36
|
+
"""Protocol to provide energy to motor position conversion."""
|
|
37
37
|
...
|
|
38
38
|
|
|
39
39
|
|
|
@@ -41,44 +41,51 @@ Apple2Type = TypeVar("Apple2Type", bound=Apple2)
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
class Apple2Controller(abc.ABC, StandardReadable, Generic[Apple2Type]):
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
Abstract base class for controlling an Apple2 undulator device.
|
|
44
|
+
"""Abstract base class for controlling an Apple2 undulator device.
|
|
47
45
|
|
|
48
46
|
This class manages the undulator's gap and phase motors, and provides an interface
|
|
49
47
|
for controlling polarisation and energy settings. It exposes derived signals for
|
|
50
48
|
energy and polarisation, and handles conversion between energy/polarisation and
|
|
51
49
|
motor positions via a user-supplied conversion callable.
|
|
52
50
|
|
|
53
|
-
Attributes
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
51
|
+
Attributes:
|
|
52
|
+
apple2 (Reference[Apple2Type]): Reference to the Apple2 device containing gap
|
|
53
|
+
and phase motors.
|
|
54
|
+
energy (derived_signal_rw): Derived signal for moving and reading back energy.
|
|
55
|
+
polarisation_setpoint (SignalR): Soft signal for the polarisation setpoint.
|
|
56
|
+
polarisation (derived_signal_rw): Hardware-backed signal for polarisation
|
|
57
|
+
readback and control.
|
|
58
|
+
gap_energy_to_motor_converter (EnergyMotorConvertor): Callable that converts
|
|
59
|
+
energy and polarisation to gap motor positions.
|
|
60
|
+
phase_energy_to_motor_converter (EnergyMotorConvertor): Callable that converts
|
|
61
|
+
energy and polarisation to phase motor positions.
|
|
62
|
+
maximum_gap_motor_position (float): Maximum allowed position for the gap motor.
|
|
63
|
+
maximum_phase_motor_position (float): Maximum allowed position for the raw phase
|
|
64
|
+
motors.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
apple2 (Apple2): An Apple2 device.
|
|
68
|
+
gap_energy_motor_converter (EnergyMotorConvertor): The callable that handles
|
|
69
|
+
the gap look up table logic for the insertion device.
|
|
70
|
+
phase_energy_motor_converter (EnergyMotorConvertor): The callable that
|
|
71
|
+
handles the phase look up table logic for the insertion device.
|
|
72
|
+
maximum_gap_motor_position (float): Maximum allowed position for the gap motor.
|
|
73
|
+
maximum_phase_motor_position (float): Maximum allowed position for the raw phase
|
|
74
|
+
motors.
|
|
75
|
+
units (str): the units of this device. Defaults to eV.
|
|
76
|
+
name (str): Name of the device.
|
|
77
|
+
|
|
78
|
+
Abstract Methods:
|
|
79
|
+
_get_apple2_value(gap: float, phase: float) -> Apple2Val
|
|
80
|
+
Abstract method to return the Apple2Val used to set the apple2 with.
|
|
81
|
+
|
|
82
|
+
Notes:
|
|
83
|
+
- Subclasses must implement `_get_apple2_value` for beamline-specific logic.
|
|
84
|
+
- LH3 polarisation is indistinguishable from LH in hardware; special handling is
|
|
85
|
+
provided.
|
|
86
|
+
- Supports multiple polarisation modes, including linear horizontal (LH), linear
|
|
87
|
+
vertical (LV), positive circular (PC), negative circular (NC), and linear
|
|
88
|
+
arbitrary (LA).
|
|
82
89
|
|
|
83
90
|
"""
|
|
84
91
|
|
|
@@ -92,21 +99,6 @@ class Apple2Controller(abc.ABC, StandardReadable, Generic[Apple2Type]):
|
|
|
92
99
|
units: str = "eV",
|
|
93
100
|
name: str = "",
|
|
94
101
|
) -> None:
|
|
95
|
-
"""
|
|
96
|
-
|
|
97
|
-
Parameters
|
|
98
|
-
----------
|
|
99
|
-
apple2: Apple2
|
|
100
|
-
An Apple2 device.
|
|
101
|
-
gap_energy_motor_converter: EnergyMotorConvertor
|
|
102
|
-
The callable that handles the gap look up table logic for the insertion device.
|
|
103
|
-
phase_energy_motor_converter: EnergyMotorConvertor
|
|
104
|
-
The callable that handles the phase look up table logic for the insertion device.
|
|
105
|
-
units: str
|
|
106
|
-
the units of this device. Defaults to eV.
|
|
107
|
-
name: str
|
|
108
|
-
Name of the device.
|
|
109
|
-
"""
|
|
110
102
|
self.apple2 = Reference(apple2)
|
|
111
103
|
self.gap_energy_motor_converter = gap_energy_motor_converter
|
|
112
104
|
self.phase_energy_motor_converter = phase_energy_motor_converter
|
|
@@ -156,8 +148,7 @@ class Apple2Controller(abc.ABC, StandardReadable, Generic[Apple2Type]):
|
|
|
156
148
|
|
|
157
149
|
@abc.abstractmethod
|
|
158
150
|
def _get_apple2_value(self, gap: float, phase: float, pol: Pol) -> Apple2Val:
|
|
159
|
-
"""
|
|
160
|
-
This method should be implemented by the beamline specific ID class as the
|
|
151
|
+
"""This method should be implemented by the beamline specific ID class as the
|
|
161
152
|
motor positions will be different for each beamline depending on the
|
|
162
153
|
undulator design.
|
|
163
154
|
"""
|
|
@@ -182,8 +173,7 @@ class Apple2Controller(abc.ABC, StandardReadable, Generic[Apple2Type]):
|
|
|
182
173
|
return energy
|
|
183
174
|
|
|
184
175
|
async def _check_and_get_pol_setpoint(self) -> Pol:
|
|
185
|
-
"""
|
|
186
|
-
Check the polarisation setpoint and if it is NONE try to read it from
|
|
176
|
+
"""Check the polarisation setpoint and if it is NONE try to read it from
|
|
187
177
|
hardware.
|
|
188
178
|
"""
|
|
189
179
|
pol = await self.polarisation_setpoint.get_value()
|
|
@@ -246,11 +236,11 @@ class Apple2Controller(abc.ABC, StandardReadable, Generic[Apple2Type]):
|
|
|
246
236
|
btm_outer: float,
|
|
247
237
|
gap: float,
|
|
248
238
|
) -> tuple[Pol, float]:
|
|
249
|
-
"""
|
|
250
|
-
Determine polarisation and phase value using motor position patterns.
|
|
239
|
+
"""Determine polarisation and phase value using motor position patterns.
|
|
251
240
|
However there is no way to return lh3 polarisation or higher harmonic setting.
|
|
252
|
-
(May be for future one can use the inverse poly to work out the energy and try
|
|
253
|
-
to
|
|
241
|
+
(May be for future one can use the inverse poly to work out the energy and try
|
|
242
|
+
to match it with the current energy to workout the polarisation but during my
|
|
243
|
+
test the inverse poly is too unstable for general use).
|
|
254
244
|
"""
|
|
255
245
|
if gap > self.maximum_gap_motor_position:
|
|
256
246
|
raise RuntimeError(
|
|
@@ -266,16 +256,16 @@ class Apple2Controller(abc.ABC, StandardReadable, Generic[Apple2Type]):
|
|
|
266
256
|
if (
|
|
267
257
|
isclose(
|
|
268
258
|
top_outer,
|
|
269
|
-
|
|
259
|
+
btm_inner,
|
|
270
260
|
abs_tol=ROW_PHASE_MOTOR_TOLERANCE,
|
|
271
261
|
)
|
|
272
262
|
and isclose(top_inner, 0.0, abs_tol=ROW_PHASE_MOTOR_TOLERANCE)
|
|
263
|
+
and isclose(btm_outer, 0.0, abs_tol=ROW_PHASE_MOTOR_TOLERANCE)
|
|
273
264
|
and isclose(
|
|
274
|
-
btm_inner,
|
|
265
|
+
abs(btm_inner),
|
|
275
266
|
self.maximum_phase_motor_position,
|
|
276
267
|
abs_tol=ROW_PHASE_MOTOR_TOLERANCE,
|
|
277
268
|
)
|
|
278
|
-
and isclose(btm_outer, 0.0, abs_tol=ROW_PHASE_MOTOR_TOLERANCE)
|
|
279
269
|
):
|
|
280
270
|
LOGGER.info("Determined polarisation: LV (Linear Vertical).")
|
|
281
271
|
return Pol.LV, self.maximum_phase_motor_position
|
|
@@ -321,7 +311,8 @@ class Apple2EnforceLHMoveController(
|
|
|
321
311
|
However, because of the high forces involved in polarization changes,
|
|
322
312
|
all movements must be performed using the Linear Horizontal (LH) mode.
|
|
323
313
|
A look-up table must also be used to determine the highest energy that can
|
|
324
|
-
be reached in LH mode.
|
|
314
|
+
be reached in LH mode.
|
|
315
|
+
"""
|
|
325
316
|
|
|
326
317
|
def __init__(
|
|
327
318
|
self,
|
|
@@ -170,19 +170,14 @@ class GapSafeMotorNoStop(UnstoppableMotor, UndulatorBase[float]):
|
|
|
170
170
|
|
|
171
171
|
|
|
172
172
|
class UndulatorGap(GapSafeMotorNoStop):
|
|
173
|
-
"""Apple 2 undulator gap motor device. With PV corrections.
|
|
173
|
+
"""Apple 2 undulator gap motor device. With PV corrections.
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
----------
|
|
180
|
-
prefix : str
|
|
181
|
-
Beamline specific part of the PV
|
|
182
|
-
name : str
|
|
183
|
-
Name of the Id device
|
|
175
|
+
Args:
|
|
176
|
+
prefix (str): Beamline specific part of the PV
|
|
177
|
+
name (str): Name of the Id device
|
|
178
|
+
"""
|
|
184
179
|
|
|
185
|
-
|
|
180
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
186
181
|
self.set_move = epics_signal_rw(int, prefix + "BLGSETP")
|
|
187
182
|
# Nothing move until this is set to 1 and it will return to 0 when done.
|
|
188
183
|
super().__init__(self.set_move, prefix, name)
|
|
@@ -201,8 +196,7 @@ class UndulatorGap(GapSafeMotorNoStop):
|
|
|
201
196
|
|
|
202
197
|
@AsyncStatus.wrap
|
|
203
198
|
async def prepare(self, value: FlyMotorInfo) -> None:
|
|
204
|
-
"""
|
|
205
|
-
Prepare for a fly scan by moving to the run-up position at max velocity.
|
|
199
|
+
"""Prepare for a fly scan by moving to the run-up position at max velocity.
|
|
206
200
|
Stores fly info for later use in kickoff.
|
|
207
201
|
"""
|
|
208
202
|
max_velocity, min_velocity, egu = await asyncio.gather(
|
|
@@ -228,18 +222,14 @@ class UndulatorGap(GapSafeMotorNoStop):
|
|
|
228
222
|
|
|
229
223
|
|
|
230
224
|
class UndulatorPhaseMotor(UnstoppableMotor):
|
|
231
|
-
"""Phase motor that will not stop.
|
|
225
|
+
"""Phase motor that will not stop.
|
|
232
226
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
227
|
+
Args:
|
|
228
|
+
prefix (str): The setting prefix PV.
|
|
229
|
+
name (str, optional): Name of the Id phase device.
|
|
230
|
+
"""
|
|
237
231
|
|
|
238
|
-
|
|
239
|
-
The setting prefix PV.
|
|
240
|
-
name : str
|
|
241
|
-
Name of the Id phase device
|
|
242
|
-
"""
|
|
232
|
+
def __init__(self, prefix: str, name: str = ""):
|
|
243
233
|
motor_pv = f"{prefix}MTR"
|
|
244
234
|
super().__init__(prefix=motor_pv, name=name)
|
|
245
235
|
self.user_setpoint = epics_signal_rw(str, prefix + "SET")
|
|
@@ -275,10 +265,9 @@ class UndulatorLockedPhaseAxes(SafeUndulatorMover[Apple2PhaseValType]):
|
|
|
275
265
|
)
|
|
276
266
|
|
|
277
267
|
async def get_timeout(self) -> float:
|
|
268
|
+
"""Get all motor speed, current positions and target positions to calculate
|
|
269
|
+
required timeout.
|
|
278
270
|
"""
|
|
279
|
-
Get all motor speed, current positions and target positions to calculate required timeout.
|
|
280
|
-
"""
|
|
281
|
-
|
|
282
271
|
timeouts = await asyncio.gather(
|
|
283
272
|
*[
|
|
284
273
|
estimate_motor_timeout(
|
|
@@ -291,20 +280,19 @@ class UndulatorLockedPhaseAxes(SafeUndulatorMover[Apple2PhaseValType]):
|
|
|
291
280
|
)
|
|
292
281
|
"""A 2.0 multiplier is required to prevent premature motor timeouts in phase
|
|
293
282
|
axes as it is a master-slave system, where the slave's movement,
|
|
294
|
-
being dependent on the master, can take up to twice as long to complete.
|
|
295
|
-
"""
|
|
283
|
+
being dependent on the master, can take up to twice as long to complete."""
|
|
296
284
|
return np.max(timeouts) * 2.0
|
|
297
285
|
|
|
298
286
|
|
|
299
287
|
class UndulatorPhaseAxes(UndulatorLockedPhaseAxes[Apple2PhasesVal]):
|
|
300
|
-
"""
|
|
301
|
-
|
|
302
|
-
e.g. top_outer == Q1
|
|
303
|
-
top_inner == Q2
|
|
304
|
-
btm_inner == q3
|
|
305
|
-
btm_outer == q4
|
|
288
|
+
"""A collection of 4 phase Motor to make up the full id phase motion. We are using
|
|
289
|
+
the diamond PV convention. e.g.::
|
|
306
290
|
|
|
307
|
-
|
|
291
|
+
top_outer == Q1
|
|
292
|
+
top_inner == Q2
|
|
293
|
+
btm_inner == q3
|
|
294
|
+
btm_outer == q4
|
|
295
|
+
""" # noqa D415
|
|
308
296
|
|
|
309
297
|
def __init__(
|
|
310
298
|
self,
|
|
@@ -333,9 +321,8 @@ class UndulatorPhaseAxes(UndulatorLockedPhaseAxes[Apple2PhasesVal]):
|
|
|
333
321
|
|
|
334
322
|
|
|
335
323
|
class UndulatorJawPhase(SafeUndulatorMover[float]):
|
|
336
|
-
"""
|
|
337
|
-
|
|
338
|
-
linear arbitrary polarisation but only on some of the beamline.
|
|
324
|
+
"""A JawPhase movable, this is use for moving the jaw phase which is use to control
|
|
325
|
+
the linear arbitrary polarisation but only on some of the beamline.
|
|
339
326
|
"""
|
|
340
327
|
|
|
341
328
|
def __init__(
|
|
@@ -357,8 +344,8 @@ class UndulatorJawPhase(SafeUndulatorMover[float]):
|
|
|
357
344
|
await self.jaw_phase.user_setpoint.set(value=str(value))
|
|
358
345
|
|
|
359
346
|
async def get_timeout(self) -> float:
|
|
360
|
-
"""
|
|
361
|
-
|
|
347
|
+
"""Get motor speed, current position and target position to calculate required
|
|
348
|
+
timeout.
|
|
362
349
|
"""
|
|
363
350
|
return await estimate_motor_timeout(
|
|
364
351
|
self.jaw_phase.user_setpoint_readback,
|
|
@@ -371,29 +358,20 @@ PhaseAxesType = TypeVar("PhaseAxesType", bound=UndulatorLockedPhaseAxes)
|
|
|
371
358
|
|
|
372
359
|
|
|
373
360
|
class Apple2(StandardReadable, Movable[Apple2Val], Generic[PhaseAxesType]):
|
|
374
|
-
"""
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
361
|
+
"""Device representing the combined motor controls for an Apple2 undulator.
|
|
362
|
+
|
|
363
|
+
Attributes:
|
|
364
|
+
gap (UndulatorGap): The undulator gap motor device.
|
|
365
|
+
phase (UndulatorPhaseAxes): The undulator phase axes device, consisting of four
|
|
366
|
+
phase motors.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
id_gap (UndulatorGap): An UndulatorGap device.
|
|
370
|
+
id_phase (UndulatorPhaseAxes): An UndulatorPhaseAxes device.
|
|
371
|
+
name (str, optional): Name of the device.
|
|
383
372
|
"""
|
|
384
373
|
|
|
385
374
|
def __init__(self, id_gap: UndulatorGap, id_phase: PhaseAxesType, name=""):
|
|
386
|
-
"""
|
|
387
|
-
Parameters
|
|
388
|
-
----------
|
|
389
|
-
|
|
390
|
-
id_gap: UndulatorGap
|
|
391
|
-
An UndulatorGap device.
|
|
392
|
-
id_phase: UndulatorPhaseAxes
|
|
393
|
-
An UndulatorPhaseAxes device.
|
|
394
|
-
name: str
|
|
395
|
-
Name of the device.
|
|
396
|
-
"""
|
|
397
375
|
with self.add_children_as_readables():
|
|
398
376
|
self.gap = Reference(id_gap)
|
|
399
377
|
self.phase = Reference(id_phase)
|
|
@@ -401,11 +379,9 @@ class Apple2(StandardReadable, Movable[Apple2Val], Generic[PhaseAxesType]):
|
|
|
401
379
|
|
|
402
380
|
@AsyncStatus.wrap
|
|
403
381
|
async def set(self, id_motor_values: Apple2Val) -> None:
|
|
382
|
+
"""Check ID is in a movable state and set all the demand value before moving
|
|
383
|
+
them all at the same time.
|
|
404
384
|
"""
|
|
405
|
-
Check ID is in a movable state and set all the demand value before moving them
|
|
406
|
-
all at the same time.
|
|
407
|
-
"""
|
|
408
|
-
|
|
409
385
|
# Only need to check gap as the phase motors share both status and gate with gap.
|
|
410
386
|
await self.gap().raise_if_cannot_move()
|
|
411
387
|
|