dls-dodal 1.68.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.68.0.dist-info → dls_dodal-2.0.0.dist-info}/METADATA +1 -31
- dls_dodal-2.0.0.dist-info/RECORD +354 -0
- {dls_dodal-1.68.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 +40 -33
- 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 +17 -45
- dodal/beamlines/i02_2.py +6 -12
- dodal/beamlines/i03.py +8 -5
- dodal/beamlines/i03_supervisor.py +19 -0
- dodal/beamlines/i04.py +87 -184
- dodal/beamlines/i05.py +9 -39
- dodal/beamlines/i05_1.py +4 -13
- dodal/beamlines/i05_shared.py +51 -0
- dodal/beamlines/i06_1.py +26 -0
- dodal/beamlines/{i06.py → i06_shared.py} +25 -14
- dodal/beamlines/i07.py +14 -16
- dodal/beamlines/i09.py +76 -29
- dodal/beamlines/i09_1.py +25 -56
- 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/i16.py +11 -0
- 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 +17 -11
- dodal/beamlines/i21.py +44 -29
- dodal/beamlines/i22.py +19 -4
- dodal/beamlines/i23.py +20 -27
- dodal/beamlines/i24.py +64 -113
- dodal/beamlines/k07.py +99 -5
- dodal/beamlines/p38.py +3 -3
- dodal/beamlines/p60.py +35 -14
- dodal/beamlines/p99.py +16 -15
- dodal/beamlines/training_rig.py +20 -12
- dodal/cli.py +36 -2
- dodal/common/__init__.py +2 -1
- 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 +87 -19
- 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/beamlines/i04/max_pixel.py +25 -0
- dodal/devices/{i04 → beamlines/i04}/murko_results.py +23 -8
- 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 +37 -51
- 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 +16 -22
- 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 +12 -12
- 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 +32 -17
- dodal/devices/eiger_odin.py +1 -1
- dodal/devices/electron_analyser/base/__init__.py +3 -3
- dodal/devices/electron_analyser/base/base_controller.py +32 -21
- 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_enums.py +0 -5
- dodal/devices/electron_analyser/base/base_region.py +29 -31
- dodal/devices/electron_analyser/base/base_util.py +18 -16
- dodal/devices/electron_analyser/base/energy_sources.py +35 -40
- dodal/devices/electron_analyser/specs/specs_detector.py +7 -6
- dodal/devices/electron_analyser/vgscienta/vgscienta_detector.py +7 -6
- dodal/devices/eurotherm.py +3 -2
- dodal/devices/fast_grid_scan.py +31 -34
- dodal/devices/fast_shutter.py +125 -39
- 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 +20 -8
- dodal/devices/insertion_device/apple2_controller.py +371 -0
- dodal/devices/insertion_device/apple2_undulator.py +184 -587
- dodal/devices/insertion_device/apple_knot_controller.py +222 -0
- dodal/devices/insertion_device/energy.py +161 -0
- dodal/devices/insertion_device/energy_motor_lookup.py +21 -28
- dodal/devices/insertion_device/lookup_table_models.py +47 -52
- dodal/devices/insertion_device/polarisation.py +36 -0
- 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 +92 -22
- 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 +20 -6
- 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 +45 -20
- dodal/devices/s4_slit_gaps.py +1 -1
- dodal/devices/selectable_source.py +41 -0
- 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 +21 -7
- dodal/devices/zebra/zebra_constants_mapping.py +12 -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/configure_arm_trigger_and_disarm_detector.py +0 -1
- 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/__init__.py +0 -0
- 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.68.0.dist-info/RECORD +0 -330
- dodal/beamline_specific_utils/i05_shared.py +0 -14
- dodal/devices/b07/__init__.py +0 -3
- dodal/devices/i04/max_pixel.py +0 -38
- dodal/devices/i05/__init__.py +0 -3
- dodal/devices/i09/__init__.py +0 -3
- dodal/devices/i21/__init__.py +0 -5
- {dls_dodal-1.68.0.dist-info → dls_dodal-2.0.0.dist-info}/entry_points.txt +0 -0
- {dls_dodal-1.68.0.dist-info → dls_dodal-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {dls_dodal-1.68.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/{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/insertion_device/{id_enum.py → enum.py} +0 -0
dodal/devices/bimorph_mirror.py
CHANGED
|
@@ -43,10 +43,19 @@ class BimorphMirrorChannel(StandardReadable, EpicsDevice):
|
|
|
43
43
|
"""Collection of PVs comprising a single bimorph channel.
|
|
44
44
|
|
|
45
45
|
Attributes:
|
|
46
|
-
target_voltage: Float RW_RBV for target voltage, which can be set
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
target_voltage (SignalRW): Float RW_RBV for target voltage, which can be set
|
|
47
|
+
using parent mirror's all target proc.
|
|
48
|
+
output_voltage (SignalRW): Float RW_RBV for current voltage on bimorph.
|
|
49
|
+
status (SignalR): BimorphMirrorOnOff readable for ON/OFF status of channel.
|
|
50
|
+
shift (SignalW): Float writeable shifting channel voltage.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
prefix (str): PV prefix.
|
|
54
|
+
number_of_channels (int): Number of channels on bimorph mirror (can be zero).
|
|
55
|
+
name (str, optional): Name of device.
|
|
56
|
+
|
|
57
|
+
Raises:
|
|
58
|
+
ValueError: number_of_channels is less than zero.
|
|
50
59
|
"""
|
|
51
60
|
|
|
52
61
|
target_voltage: A[SignalRW[float], PvSuffix.rbv("VTRGT"), Format.CONFIG_SIGNAL]
|
|
@@ -59,21 +68,14 @@ class BimorphMirror(StandardReadable, Movable[list[float]]):
|
|
|
59
68
|
"""Class to represent CAENels Bimorph Mirrors.
|
|
60
69
|
|
|
61
70
|
Attributes:
|
|
62
|
-
channels: DeviceVector of BimorphMirrorChannel, indexed from 1,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
channels (DeviceVector): DeviceVector of BimorphMirrorChannel, indexed from 1,
|
|
72
|
+
for each channel.
|
|
73
|
+
enabled (SignalW): Writeable BimorphOnOff.
|
|
74
|
+
status (SignalR): Readable BimorphMirrorStatus Busy/Idle status.
|
|
75
|
+
err (SignalR): Alarm status.
|
|
76
|
+
"""
|
|
66
77
|
|
|
67
78
|
def __init__(self, prefix: str, number_of_channels: int, name=""):
|
|
68
|
-
"""
|
|
69
|
-
Args:
|
|
70
|
-
prefix: str PV prefix
|
|
71
|
-
number_of_channels: int number of channels on bimorph mirror (can be zero)
|
|
72
|
-
name: str name of device
|
|
73
|
-
|
|
74
|
-
Raises:
|
|
75
|
-
ValueError: number_of_channels is less than zero"""
|
|
76
|
-
|
|
77
79
|
if number_of_channels < 0:
|
|
78
80
|
raise ValueError(f"Number of channels is below zero: {number_of_channels}")
|
|
79
81
|
|
|
@@ -95,11 +97,11 @@ class BimorphMirror(StandardReadable, Movable[list[float]]):
|
|
|
95
97
|
"""Sets bimorph voltages in parallel via target voltage and all proc.
|
|
96
98
|
|
|
97
99
|
Args:
|
|
98
|
-
value: List of float target voltages
|
|
100
|
+
value (list[float]): List of float target voltages.
|
|
99
101
|
|
|
100
102
|
Raises:
|
|
101
|
-
ValueError: On set to non-existent channel
|
|
102
|
-
|
|
103
|
+
ValueError: On set to non-existent channel.
|
|
104
|
+
"""
|
|
103
105
|
if len(value) != len(self.channels):
|
|
104
106
|
raise ValueError(
|
|
105
107
|
f"Length of value input array does not match number of \
|
|
@@ -13,8 +13,9 @@ class CollimationTable(StandardReadable):
|
|
|
13
13
|
There are 2 physical horizontal motors 1 upstream, 1 downstream. These provide yaw.
|
|
14
14
|
|
|
15
15
|
Table motion is disabled by an object being within the laser curtain area and can be
|
|
16
|
-
overridden by use of the dead man's handle device or locking the hutch. The effect
|
|
17
|
-
these disabling systems is to cut power to the motors - signal for this is
|
|
16
|
+
overridden by use of the dead man's handle device or locking the hutch. The effect
|
|
17
|
+
of these disabling systems is to cut power to the motors - signal for this is
|
|
18
|
+
`crate_power`.
|
|
18
19
|
"""
|
|
19
20
|
|
|
20
21
|
def __init__(self, prefix: str, name: str = ""):
|
dodal/devices/common_dcm.py
CHANGED
|
@@ -33,19 +33,23 @@ Xtal_2 = TypeVar("Xtal_2", bound=StationaryCrystal)
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
class DoubleCrystalMonochromatorBase(StandardReadable, Generic[Xtal_1, Xtal_2]):
|
|
36
|
-
"""
|
|
37
|
-
|
|
36
|
+
"""Base device for the double crystal monochromator (DCM), used to select the energy
|
|
37
|
+
of the beam.
|
|
38
38
|
|
|
39
|
-
Features common across all DCM's should include virtual motors to set
|
|
40
|
-
each of which can be movable. Some DCM's
|
|
41
|
-
|
|
39
|
+
Features common across all DCM's should include virtual motors to set
|
|
40
|
+
energy/wavelength and contain two crystals, each of which can be movable. Some DCM's
|
|
41
|
+
contain crystals with roll motors, and some contain crystals with roll and pitch
|
|
42
|
+
motors. This base device accounts for all combinations of this.
|
|
43
|
+
|
|
44
|
+
This device should act as a parent for beamline-specific DCM's which do not match
|
|
45
|
+
the standard EPICS interface, it provides only energy and the crystal configuration.
|
|
46
|
+
Most beamlines should use DoubleCrystalMonochromator instead.
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
Bluesky plans using DCM's should be typed to specify which types of crystals are
|
|
49
|
+
required. For example, a plan which only requires one crystal which can roll should
|
|
50
|
+
be typed::
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
which only requires one crystal which can roll should be typed
|
|
48
|
-
'def my_plan(dcm: DoubleCrystalMonochromatorBase[RollCrystal, StationaryCrystal])`
|
|
52
|
+
def my_plan(dcm: DoubleCrystalMonochromatorBase[RollCrystal,StationaryCrystal])
|
|
49
53
|
"""
|
|
50
54
|
|
|
51
55
|
def __init__(
|
|
@@ -78,17 +82,23 @@ class DoubleCrystalMonochromatorBase(StandardReadable, Generic[Xtal_1, Xtal_2]):
|
|
|
78
82
|
class DoubleCrystalMonochromator(
|
|
79
83
|
DoubleCrystalMonochromatorBase, Generic[Xtal_1, Xtal_2]
|
|
80
84
|
):
|
|
81
|
-
"""
|
|
82
|
-
|
|
85
|
+
"""Common device for the double crystal monochromator (DCM), used to select the
|
|
86
|
+
energy of the beam.
|
|
83
87
|
|
|
84
|
-
Features common across all DCM's should include virtual motors to set
|
|
85
|
-
each of which can be movable. Some DCM's
|
|
88
|
+
Features common across all DCM's should include virtual motors to set
|
|
89
|
+
energy/wavelength and contain two crystals, each of which can be movable. Some DCM's
|
|
90
|
+
contain crystals with roll motors, and some contain crystals with roll and pitch
|
|
91
|
+
motors.
|
|
86
92
|
This base device accounts for all combinations of this.
|
|
87
93
|
|
|
88
|
-
This device should act as a parent for beamline-specific DCM's, in which any other
|
|
94
|
+
This device should act as a parent for beamline-specific DCM's, in which any other
|
|
95
|
+
missing signals can be added.
|
|
96
|
+
|
|
97
|
+
Bluesky plans using DCM's should be typed to specify which types of crystals are
|
|
98
|
+
required. For example, a plan which only requires one crystal which can roll should
|
|
99
|
+
be typed::
|
|
89
100
|
|
|
90
|
-
|
|
91
|
-
requires one crystal which can roll should be typed 'def my_plan(dcm: DoubleCrystalMonochromator[RollCrystal, StationaryCrystal])`
|
|
101
|
+
def my_plan(dcm: DoubleCrystalMonochromator[RollCrystal, StationaryCrystal])
|
|
92
102
|
"""
|
|
93
103
|
|
|
94
104
|
def __init__(
|
|
@@ -109,9 +119,9 @@ class DoubleCrystalMonochromator(
|
|
|
109
119
|
class DoubleCrystalMonochromatorWithDSpacing(
|
|
110
120
|
DoubleCrystalMonochromator, Generic[Xtal_1, Xtal_2]
|
|
111
121
|
):
|
|
112
|
-
"""
|
|
113
|
-
|
|
114
|
-
|
|
122
|
+
"""Adds crystal D-spacing metadata to the DoubleCrystalMonochromator class. This
|
|
123
|
+
should be used in preference to the DoubleCrystalMonochromator on beamlines which
|
|
124
|
+
have a "DSPACING:RBV" pv on their DCM.
|
|
115
125
|
"""
|
|
116
126
|
|
|
117
127
|
def __init__(
|
dodal/devices/controllers.py
CHANGED
|
@@ -6,8 +6,8 @@ ADBaseIOT = TypeVar("ADBaseIOT", bound=ADBaseIO)
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ConstantDeadTimeController(ADBaseController[ADBaseIOT]):
|
|
9
|
-
"""
|
|
10
|
-
|
|
9
|
+
"""ADBaseController with a configured constant deadtime for a driver of type
|
|
10
|
+
ADBaseIO.
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
def __init__(
|
dodal/devices/cryostream.py
CHANGED
|
@@ -87,6 +87,14 @@ class OxfordCryoJet(StandardReadable):
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
class CryoStreamGantry(StandardReadable):
|
|
90
|
+
"""Gantry controlling whether the standard Cryostream or the
|
|
91
|
+
HC1 cryostream is in position.
|
|
92
|
+
|
|
93
|
+
Note: this device is currently implemented read-only; moving the gantry without
|
|
94
|
+
adequate checks risks a collision if the gantry is moved while HC1 is selected
|
|
95
|
+
and in the IN position.
|
|
96
|
+
"""
|
|
97
|
+
|
|
90
98
|
def __init__(self, prefix: str, name: str = ""):
|
|
91
99
|
with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
|
|
92
100
|
self.cryostream_selector = epics_signal_r(
|
|
@@ -9,14 +9,13 @@ from ophyd_async.core import AsyncStatus, StandardReadable
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class CurrentAmp(ABC, StandardReadable, Movable):
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
a current amplifier needs:
|
|
12
|
+
"""Base class for current amplifier, it contains the minimal functionality
|
|
13
|
+
a current amplifier needs:
|
|
15
14
|
|
|
16
15
|
Attributes:
|
|
17
16
|
gain_conversion_table (Enum): The conversion table between current
|
|
18
|
-
|
|
19
|
-
"""
|
|
17
|
+
and gain setting.
|
|
18
|
+
""" # noqa D415
|
|
20
19
|
|
|
21
20
|
def __init__(self, gain_conversion_table: type[Enum], name: str = "") -> None:
|
|
22
21
|
self.gain_conversion_table = gain_conversion_table
|
|
@@ -40,7 +39,7 @@ class CurrentAmp(ABC, StandardReadable, Movable):
|
|
|
40
39
|
|
|
41
40
|
@abstractmethod
|
|
42
41
|
async def get_gain(self) -> Enum:
|
|
43
|
-
"""Get the current gain setting
|
|
42
|
+
"""Get the current gain setting.
|
|
44
43
|
|
|
45
44
|
Returns:
|
|
46
45
|
Enum: The member name of the current gain setting in gain_conversion_table.
|
|
@@ -48,17 +47,16 @@ class CurrentAmp(ABC, StandardReadable, Movable):
|
|
|
48
47
|
|
|
49
48
|
@abstractmethod
|
|
50
49
|
async def get_upperlimit(self) -> float:
|
|
51
|
-
"""Get the upper limit of the current amplifier"""
|
|
50
|
+
"""Get the upper limit of the current amplifier."""
|
|
52
51
|
|
|
53
52
|
@abstractmethod
|
|
54
53
|
async def get_lowerlimit(self) -> float:
|
|
55
|
-
"""Get the lower limit of the current amplifier"""
|
|
54
|
+
"""Get the lower limit of the current amplifier."""
|
|
56
55
|
|
|
57
56
|
|
|
58
57
|
class CurrentAmpCounter(ABC, StandardReadable, Preparable):
|
|
59
|
-
"""
|
|
60
|
-
|
|
61
|
-
required for a counter/detector to function with CurrentAmpDet:
|
|
58
|
+
"""Base class for current amplifier counter, it contain the minimal implementations
|
|
59
|
+
required for a counter/detector to function with CurrentAmpDet.
|
|
62
60
|
|
|
63
61
|
Attributes:
|
|
64
62
|
count_per_volt (float): The conversion factor between counter output and voltage.
|
|
@@ -70,29 +68,29 @@ class CurrentAmpCounter(ABC, StandardReadable, Preparable):
|
|
|
70
68
|
|
|
71
69
|
@abstractmethod
|
|
72
70
|
async def get_count(self) -> float:
|
|
73
|
-
"""
|
|
71
|
+
"""Get count.
|
|
74
72
|
|
|
75
73
|
Returns:
|
|
76
|
-
float: Current count
|
|
74
|
+
float: Current count.
|
|
77
75
|
"""
|
|
78
76
|
|
|
79
77
|
@abstractmethod
|
|
80
78
|
async def get_count_per_sec(self) -> float:
|
|
81
|
-
"""Get count per second
|
|
79
|
+
"""Get count per second.
|
|
82
80
|
|
|
83
81
|
Returns:
|
|
84
|
-
float: Current count per second
|
|
82
|
+
float: Current count per second.
|
|
85
83
|
"""
|
|
86
84
|
|
|
87
85
|
@abstractmethod
|
|
88
86
|
async def get_voltage_per_sec(self) -> float:
|
|
89
|
-
"""Get count per second in voltage
|
|
87
|
+
"""Get count per second in voltage.
|
|
90
88
|
|
|
91
89
|
Returns:
|
|
92
|
-
float: Current count in volt per second
|
|
90
|
+
float: Current count in volt per second.
|
|
93
91
|
"""
|
|
94
92
|
|
|
95
93
|
@abstractmethod
|
|
96
94
|
@AsyncStatus.wrap
|
|
97
95
|
async def prepare(self, value: float) -> None:
|
|
98
|
-
"""Prepare method for setting up the counter"""
|
|
96
|
+
"""Prepare method for setting up the counter."""
|
|
@@ -18,11 +18,11 @@ from dodal.log import LOGGER
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class CurrentAmpDet(StandardReadable, Preparable):
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
"""CurrentAmpDet composed of a CurrentAmp and a CurrentAmpCounter. It provides
|
|
22
|
+
the option for automatically changing the CurrentAmp gain to within the optimal
|
|
23
|
+
range. It also converts the currentAmp/counter output back into the detector
|
|
24
|
+
current output in Amp.
|
|
25
|
+
|
|
26
26
|
Attributes:
|
|
27
27
|
current_amp (currentAmp): Current amplifier type device.
|
|
28
28
|
counter (CurrentAmpCounter): Counter that capture the current amplifier output.
|
|
@@ -48,9 +48,8 @@ class CurrentAmpDet(StandardReadable, Preparable):
|
|
|
48
48
|
super().__init__(name)
|
|
49
49
|
|
|
50
50
|
async def read(self) -> dict[str, Reading]:
|
|
51
|
-
"""
|
|
52
|
-
|
|
53
|
-
taking the final reading
|
|
51
|
+
"""Read is modified so that if auto_mode is true it will optimise gain before
|
|
52
|
+
taking the final reading.
|
|
54
53
|
"""
|
|
55
54
|
if await self.auto_mode.get_value():
|
|
56
55
|
LOGGER.info(f"{self.name}-Attempting auto-gain")
|
|
@@ -85,8 +84,8 @@ class CurrentAmpDet(StandardReadable, Preparable):
|
|
|
85
84
|
within_limits = True
|
|
86
85
|
|
|
87
86
|
async def get_corrected_current(self) -> float:
|
|
88
|
-
"""
|
|
89
|
-
|
|
87
|
+
"""Convert the output (count and gain) back into the read detector output in
|
|
88
|
+
Amp.
|
|
90
89
|
"""
|
|
91
90
|
current_gain, voltage_per_sec = await asyncio.gather(
|
|
92
91
|
self.current_amp().get_gain(),
|
|
@@ -13,7 +13,7 @@ from dodal.log import LOGGER
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class Femto3xxGainTable(StrictEnum):
|
|
16
|
-
"""These are the sensitivity setting for Femto 3xx current amplifier"""
|
|
16
|
+
"""These are the sensitivity setting for Femto 3xx current amplifier."""
|
|
17
17
|
|
|
18
18
|
SEN_1 = "10^4"
|
|
19
19
|
SEN_2 = "10^5"
|
|
@@ -28,7 +28,7 @@ class Femto3xxGainTable(StrictEnum):
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class Femto3xxGainToCurrentTable(float, Enum):
|
|
31
|
-
"""These are the voltage to current setting for Femto 3xx current amplifier"""
|
|
31
|
+
"""These are the voltage to current setting for Femto 3xx current amplifier."""
|
|
32
32
|
|
|
33
33
|
SEN_1 = 1e4
|
|
34
34
|
SEN_2 = 1e5
|
|
@@ -43,7 +43,7 @@ class Femto3xxGainToCurrentTable(float, Enum):
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class Femto3xxRaiseTime(float, Enum):
|
|
46
|
-
"""These are the gain dependent raise time(s) for Femto 3xx current amplifier"""
|
|
46
|
+
"""These are the gain dependent raise time(s) for Femto 3xx current amplifier."""
|
|
47
47
|
|
|
48
48
|
SEN_1 = 0.8e-3
|
|
49
49
|
SEN_2 = 0.8e-3
|
|
@@ -58,10 +58,10 @@ class Femto3xxRaiseTime(float, Enum):
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
class FemtoDDPCA(CurrentAmp):
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
"""Femto current amplifier device, this class should cover all DDPCA Femto current
|
|
62
|
+
amplifiers, As the main different between all the DDPCA Femto is their gain table
|
|
63
|
+
and response time table.
|
|
64
|
+
|
|
65
65
|
Attributes:
|
|
66
66
|
gain (SignalRW): This is the epic signal that control current amplifier gain.
|
|
67
67
|
gain_table (strictEnum): The table epic use to set gain.
|
|
@@ -69,8 +69,7 @@ class FemtoDDPCA(CurrentAmp):
|
|
|
69
69
|
lowerlimit (float): lowerlimit of the current amplifier
|
|
70
70
|
timeout (float): Maximum waiting time in second for setting gain.
|
|
71
71
|
raise_timetable (Enum): Table contain the minimum amount of time to wait after
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
changing gain.
|
|
74
73
|
"""
|
|
75
74
|
|
|
76
75
|
def __init__(
|
|
@@ -13,7 +13,7 @@ from dodal.log import LOGGER
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class SR570GainTable(StrictEnum):
|
|
16
|
-
"""Coarse/unit sensitivity setting for SR570 current amplifier"""
|
|
16
|
+
"""Coarse/unit sensitivity setting for SR570 current amplifier."""
|
|
17
17
|
|
|
18
18
|
SEN_1 = "mA/V"
|
|
19
19
|
SEN_2 = "uA/V"
|
|
@@ -22,7 +22,7 @@ class SR570GainTable(StrictEnum):
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class SR570FineGainTable(StrictEnum):
|
|
25
|
-
"""Fine sensitivity setting for SR570 current amplifier"""
|
|
25
|
+
"""Fine sensitivity setting for SR570 current amplifier."""
|
|
26
26
|
|
|
27
27
|
SEN_1 = "1"
|
|
28
28
|
SEN_2 = "2"
|
|
@@ -36,7 +36,7 @@ class SR570FineGainTable(StrictEnum):
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class SR570RaiseTimeTable(float, Enum):
|
|
39
|
-
"""These are the gain dependent raise time(s) for SR570 current amplifier"""
|
|
39
|
+
"""These are the gain dependent raise time(s) for SR570 current amplifier."""
|
|
40
40
|
|
|
41
41
|
SEN_1 = 1e-4
|
|
42
42
|
SEN_2 = 1e-2
|
|
@@ -46,7 +46,8 @@ class SR570RaiseTimeTable(float, Enum):
|
|
|
46
46
|
|
|
47
47
|
class SR570FullGainTable(Enum):
|
|
48
48
|
"""Combined gain table, as each gain step is a combination of both coarse gain and
|
|
49
|
-
fine gain setting
|
|
49
|
+
fine gain setting.
|
|
50
|
+
"""
|
|
50
51
|
|
|
51
52
|
SEN_1 = [SR570GainTable.SEN_1, SR570FineGainTable.SEN_1]
|
|
52
53
|
SEN_2 = [SR570GainTable.SEN_2, SR570FineGainTable.SEN_9]
|
|
@@ -79,7 +80,7 @@ class SR570FullGainTable(Enum):
|
|
|
79
80
|
|
|
80
81
|
|
|
81
82
|
class SR570GainToCurrentTable(float, Enum):
|
|
82
|
-
"""Conversion table for gain (sensitivity) to current"""
|
|
83
|
+
"""Conversion table for gain (sensitivity) to current."""
|
|
83
84
|
|
|
84
85
|
SEN_1 = 1e3
|
|
85
86
|
SEN_2 = 2e3
|
|
@@ -112,10 +113,10 @@ class SR570GainToCurrentTable(float, Enum):
|
|
|
112
113
|
|
|
113
114
|
|
|
114
115
|
class SR570(CurrentAmp):
|
|
115
|
-
"""
|
|
116
|
-
SR570
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
"""SR570 current amplifier device. This is similar to Femto with the only different
|
|
117
|
+
is SR570 has two gain setting fine and coarse, therefore it requires extra
|
|
118
|
+
gain tables.
|
|
119
|
+
|
|
119
120
|
Attributes:
|
|
120
121
|
fine_gain (SignalRW): This is the epic signal that control SR570 fine gain.
|
|
121
122
|
coarse_gain (SignalRW): This is the epic signal that control SR570 coarse gain.
|
|
@@ -129,18 +130,17 @@ class SR570(CurrentAmp):
|
|
|
129
130
|
setting in gain_conversion_table.
|
|
130
131
|
upperlimit (float): upperlimit of the current amplifier
|
|
131
132
|
lowerlimit (float): lowerlimit of the current amplifier
|
|
132
|
-
|
|
133
133
|
"""
|
|
134
134
|
|
|
135
135
|
def __init__(
|
|
136
136
|
self,
|
|
137
137
|
prefix: str,
|
|
138
|
-
suffix: str,
|
|
139
|
-
fine_gain_table: type[StrictEnum],
|
|
140
|
-
coarse_gain_table: type[StrictEnum],
|
|
141
|
-
combined_table: type[Enum],
|
|
142
|
-
gain_to_current_table: type[Enum],
|
|
143
|
-
raise_timetable: type[Enum],
|
|
138
|
+
suffix: str = "SENS:SEL",
|
|
139
|
+
fine_gain_table: type[StrictEnum] = SR570FineGainTable,
|
|
140
|
+
coarse_gain_table: type[StrictEnum] = SR570GainTable,
|
|
141
|
+
combined_table: type[Enum] = SR570FullGainTable,
|
|
142
|
+
gain_to_current_table: type[Enum] = SR570GainToCurrentTable,
|
|
143
|
+
raise_timetable: type[Enum] = SR570RaiseTimeTable,
|
|
144
144
|
upperlimit: float = 4.8,
|
|
145
145
|
lowerlimit: float = 0.4,
|
|
146
146
|
timeout: float = 1,
|
|
@@ -25,11 +25,11 @@ COUNT_PER_VOLTAGE = 100000
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class StruckScaler(CurrentAmpCounter):
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
"""StruckScaler is a counting card that record the output signal from a wide
|
|
29
|
+
range of detectors. This class contains the basic control to run the struckscaler
|
|
30
|
+
card together with a current amplifier. It has functions that provide conversion
|
|
31
|
+
between count and voltage.
|
|
32
|
+
|
|
33
33
|
Attributes:
|
|
34
34
|
readout(SignalR): Scaler card output.
|
|
35
35
|
count_mode (SignalR[CountMode]): Counting card setting.
|
|
@@ -47,17 +47,18 @@ def _calc_useful_radius(detector_radius_mm, beam_x_mm, beam_y_mm):
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def _calc_res_at_angle(wavelength_angstroms, angular_shift_radians):
|
|
50
|
-
"""Base definition of maximum resolution (from Bragg's Law with n=1)"""
|
|
50
|
+
"""Base definition of maximum resolution (from Bragg's Law with n=1)."""
|
|
51
51
|
return 0.5 * wavelength_angstroms / sin(angular_shift_radians)
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def _calc_res_off_axis_detector(
|
|
55
55
|
wavelength_angstroms, usable_radius, det_distance_mm, two_theta_radians
|
|
56
56
|
):
|
|
57
|
-
"""
|
|
58
|
-
|
|
59
|
-
No correction for position of beam centre on detector face at twoTheta=0
|
|
60
|
-
Here radius and distance parameters can be in any length unit, provided it is the
|
|
57
|
+
"""Calculate maximum resolution given detector distance and extent (radius) that
|
|
58
|
+
detector face extends.
|
|
59
|
+
No correction for position of beam centre on detector face at twoTheta=0.
|
|
60
|
+
Here radius and distance parameters can be in any length unit, provided it is the
|
|
61
|
+
same, millimetres is the convention.
|
|
61
62
|
"""
|
|
62
63
|
angular_shift_radians = atan(usable_radius / det_distance_mm)
|
|
63
64
|
return _calc_res_at_angle(
|
|
@@ -68,9 +69,9 @@ def _calc_res_off_axis_detector(
|
|
|
68
69
|
def _max_res_for_mx(
|
|
69
70
|
wavelength_angstroms, detector_radius_mm, det_distance_mm, beam_x_mm, beam_y_mm
|
|
70
71
|
):
|
|
71
|
-
"""
|
|
72
|
-
|
|
73
|
-
Correct the radius for position of beam centre on detector face at twoTheta=0
|
|
72
|
+
"""Calculate maximum resolution given MX Use Case (detector at twoTheta=0) and beam
|
|
73
|
+
centre on detector face.
|
|
74
|
+
Correct the radius for position of beam centre on detector face at twoTheta=0.
|
|
74
75
|
"""
|
|
75
76
|
usable_radius = _calc_useful_radius(detector_radius_mm, beam_x_mm, beam_y_mm)
|
|
76
77
|
return _calc_res_off_axis_detector(
|
|
@@ -19,7 +19,8 @@ from dodal.utils import get_run_number
|
|
|
19
19
|
|
|
20
20
|
class TriggerMode(Enum):
|
|
21
21
|
"""In set frames the number of frames is known at arm time. In free run they are
|
|
22
|
-
not known until the detector is unstaged.
|
|
22
|
+
not known until the detector is unstaged.
|
|
23
|
+
"""
|
|
23
24
|
|
|
24
25
|
SET_FRAMES = auto()
|
|
25
26
|
FREE_RUN = auto()
|
|
@@ -27,7 +28,8 @@ class TriggerMode(Enum):
|
|
|
27
28
|
|
|
28
29
|
class DetectorParams(BaseModel):
|
|
29
30
|
"""Holds parameters for the detector. Provides access to a list of Dectris detector
|
|
30
|
-
sizes and a converter for distance to beam centre.
|
|
31
|
+
sizes and a converter for distance to beam centre.
|
|
32
|
+
"""
|
|
31
33
|
|
|
32
34
|
# https://github.com/pydantic/pydantic/issues/8379
|
|
33
35
|
# Must use model_dump(by_alias=True) if serialising!
|
dodal/devices/diamond_filter.py
CHANGED
|
@@ -26,9 +26,8 @@ T = TypeVar("T", bound=_Filters)
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class DiamondFilter(Positioner1D[T]):
|
|
29
|
-
"""
|
|
30
|
-
A filter set that is used to reduce the heat load on the monochromator.
|
|
29
|
+
"""A filter set that is used to reduce the heat load on the monochromator.
|
|
31
30
|
|
|
32
|
-
It has 4 slots that can contain filters of different thickness. Changing the
|
|
33
|
-
signal will move the filter set to select this filter.
|
|
31
|
+
It has 4 slots that can contain filters of different thickness. Changing the
|
|
32
|
+
thickness signal will move the filter set to select this filter.
|
|
34
33
|
"""
|
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,36 +302,35 @@ 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:
|
|
311
|
-
"""Ensures the energy threshold on the detector is set to the specified energy
|
|
312
|
-
within the specified tolerance.
|
|
326
|
+
"""Ensures the energy threshold on the detector is set to the specified energy
|
|
327
|
+
(in eV), within the specified tolerance.
|
|
328
|
+
|
|
313
329
|
Args:
|
|
314
330
|
energy (float): The energy to set (in eV)
|
|
315
331
|
tolerance (float, optional): If the energy is already set to within
|
|
316
332
|
this tolerance it is not set again. Defaults to 0.1eV.
|
|
317
333
|
"""
|
|
318
|
-
|
|
319
334
|
current_energy = float(self.cam.photon_energy.get())
|
|
320
335
|
if abs(current_energy - energy) > tolerance:
|
|
321
336
|
LOGGER.info(f"Setting detector threshold to {energy}")
|
dodal/devices/eiger_odin.py
CHANGED
|
@@ -167,7 +167,7 @@ class EigerOdin(Device):
|
|
|
167
167
|
return not error_strings, "\n".join(error_strings)
|
|
168
168
|
|
|
169
169
|
def stop(self) -> StatusBase:
|
|
170
|
-
"""Stop odin manually"""
|
|
170
|
+
"""Stop odin manually."""
|
|
171
171
|
LOGGER.info("Stopping Odin...")
|
|
172
172
|
status = self.file_writer.capture.set(0)
|
|
173
173
|
status &= self.meta.stop_writing.set(1)
|