mx-bluesky 1.5.11__py3-none-any.whl → 1.5.12__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.
- mx_bluesky/_version.py +2 -2
- mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/__init__.py +0 -0
- mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/robot_load_plan.py +198 -0
- mx_bluesky/beamlines/aithre_lasershaping/parameters/__init__.py +0 -0
- mx_bluesky/beamlines/aithre_lasershaping/parameters/constants.py +17 -0
- mx_bluesky/beamlines/aithre_lasershaping/parameters/robot_load_parameters.py +13 -0
- mx_bluesky/beamlines/aithre_lasershaping/pin_tip_centring.py +31 -0
- mx_bluesky/beamlines/aithre_lasershaping/robot_load.py +80 -0
- mx_bluesky/beamlines/i04/__init__.py +6 -2
- mx_bluesky/beamlines/i04/callbacks/murko_callback.py +27 -12
- mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +87 -13
- mx_bluesky/beamlines/i04/external_interaction/__init__.py +0 -0
- mx_bluesky/beamlines/i04/external_interaction/config_server.py +15 -0
- mx_bluesky/beamlines/i04/oav_centering_plans/__init__.py +0 -0
- mx_bluesky/beamlines/i04/oav_centering_plans/oav_imaging.py +115 -0
- mx_bluesky/beamlines/i04/parameters/__init__.py +0 -0
- mx_bluesky/beamlines/i04/parameters/constants.py +21 -0
- mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +24 -1
- mx_bluesky/beamlines/i04/thawing_plan.py +147 -152
- mx_bluesky/beamlines/i24/serial/dcid.py +4 -5
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_extruder_collect_py3v2.py +5 -2
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/CustomChip_py3v1.edl +11 -11
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DetStage.edl +3 -3
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +142 -142
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/MappingLite-oxford_py3v1.edl +135 -135
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/PMAC_Command.edl +8 -8
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +13 -13
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_chip_collect_py3v1.py +7 -4
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_chip_manager_py3v1.py +35 -32
- mx_bluesky/beamlines/i24/serial/parameters/utils.py +5 -5
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +113 -306
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +8 -2
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +1 -1
- mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +1 -1
- mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py +64 -0
- mx_bluesky/{hyperion/device_setup_plans/smargon.py → common/device_setup_plans/gonio.py} +9 -6
- mx_bluesky/common/device_setup_plans/manipulate_sample.py +8 -1
- mx_bluesky/common/device_setup_plans/robot_load_unload.py +1 -1
- mx_bluesky/common/device_setup_plans/setup_oav.py +8 -0
- mx_bluesky/common/device_setup_plans/setup_zebra_and_shutter.py +0 -5
- mx_bluesky/common/device_setup_plans/xbpm_feedback.py +8 -1
- mx_bluesky/common/experiment_plans/beamstop_check.py +229 -0
- mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py +2 -0
- mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py +5 -2
- mx_bluesky/common/experiment_plans/oav_snapshot_plan.py +0 -1
- mx_bluesky/{hyperion → common}/experiment_plans/pin_tip_centring_plan.py +20 -21
- mx_bluesky/common/external_interaction/callbacks/common/grid_detection_callback.py +5 -0
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +10 -12
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +3 -5
- mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +5 -5
- mx_bluesky/common/external_interaction/config_server.py +2 -2
- mx_bluesky/common/external_interaction/ispyb/data_model.py +11 -4
- mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +159 -2
- mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +76 -166
- mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py +0 -14
- mx_bluesky/common/parameters/components.py +1 -0
- mx_bluesky/common/parameters/constants.py +3 -2
- mx_bluesky/common/parameters/device_composites.py +4 -2
- mx_bluesky/common/utils/exceptions.py +15 -0
- mx_bluesky/common/utils/log.py +9 -0
- mx_bluesky/common/utils/utils.py +48 -0
- mx_bluesky/hyperion/__main__.py +3 -13
- mx_bluesky/hyperion/baton_handler.py +23 -6
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +5 -6
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +3 -10
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +4 -2
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +8 -2
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/udc_default_state.py +160 -0
- mx_bluesky/hyperion/external_interaction/agamemnon.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +2 -2
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +1 -0
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +1 -4
- mx_bluesky/hyperion/external_interaction/config_server.py +5 -5
- mx_bluesky/hyperion/parameters/constants.py +10 -3
- mx_bluesky/hyperion/parameters/device_composites.py +2 -2
- mx_bluesky/hyperion/parameters/robot_load.py +1 -9
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/METADATA +6 -5
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/RECORD +83 -69
- mx_bluesky/common/experiment_plans/inner_plans/udc_default_state.py +0 -86
- mx_bluesky/common/external_interaction/callbacks/common/logging_callback.py +0 -29
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/WHEEL +0 -0
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/licenses/LICENSE +0 -0
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/top_level.txt +0 -0
mx_bluesky/common/utils/utils.py
CHANGED
|
@@ -4,6 +4,8 @@ from math import asin
|
|
|
4
4
|
from scanspec.core import AxesPoints, Axis
|
|
5
5
|
from scipy.constants import physical_constants
|
|
6
6
|
|
|
7
|
+
from mx_bluesky.common.utils.log import LOGGER
|
|
8
|
+
|
|
7
9
|
hc_in_ev_and_angstrom: float = (
|
|
8
10
|
physical_constants["speed of light in vacuum"][0]
|
|
9
11
|
* physical_constants["Planck constant in eV/Hz"][0]
|
|
@@ -40,3 +42,49 @@ def energy_to_bragg_angle(energy_kev: float, d_a: float) -> float:
|
|
|
40
42
|
wavelength_a = convert_ev_to_angstrom(energy_kev * 1000)
|
|
41
43
|
d = d_a
|
|
42
44
|
return asin(wavelength_a / (2 * d)) * 180 / math.pi
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def fix_transmission_and_exposure_time_for_current_wavelength(
|
|
48
|
+
current_wavelength_a: float,
|
|
49
|
+
assumed_wavelength_a_from_settings: float,
|
|
50
|
+
requested_trans_frac: float = 100,
|
|
51
|
+
requested_exposure_time_s: float = 0.004,
|
|
52
|
+
) -> tuple[float, float]:
|
|
53
|
+
"""
|
|
54
|
+
Calculates an exposure time and transmission fraction for XRC which will provide a good signal
|
|
55
|
+
on the detector by using a known good wavelength, comparing it to the beamlines current wavelength,
|
|
56
|
+
then scaling accordingly.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
current_wavelength_a: Current energy of the beamline in angstroms.
|
|
60
|
+
assumed_wavelength_a_from_settings: The known "good" wavelength. This should be read from
|
|
61
|
+
'gda.px.expttable.default.wavelength' in GDA's domain.properties, via the config server.
|
|
62
|
+
requested_trans_frac: Requested transmission fraction to use.
|
|
63
|
+
requested_exposure_time_s: Requested exposure time to use.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
The scaled transmission fraction and exposure time respectively, in a tuple.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
wavelength_scale = (assumed_wavelength_a_from_settings / current_wavelength_a) ** 2
|
|
70
|
+
|
|
71
|
+
# Transmission frac needed to get ideal signal
|
|
72
|
+
ideal_trans_frac = requested_trans_frac * wavelength_scale
|
|
73
|
+
if ideal_trans_frac <= 1:
|
|
74
|
+
new_trans_frac = ideal_trans_frac
|
|
75
|
+
new_exposure_time_s = requested_exposure_time_s
|
|
76
|
+
else:
|
|
77
|
+
# If the scaling would result in transmission fraction > 1,
|
|
78
|
+
# cap it to 1, find remaining scaling needed, and apply it
|
|
79
|
+
# to exposure time instead.
|
|
80
|
+
new_trans_frac = 1
|
|
81
|
+
scaling_applied_to_trans = new_trans_frac / requested_trans_frac
|
|
82
|
+
remaining_scaling_needed = wavelength_scale / scaling_applied_to_trans
|
|
83
|
+
new_exposure_time_s = requested_exposure_time_s * remaining_scaling_needed
|
|
84
|
+
|
|
85
|
+
LOGGER.info(
|
|
86
|
+
f"Fixing transmission fraction to {new_trans_frac} and exposure time to {new_exposure_time_s}s"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Exposure time in FGS IOC is in ms, and must be an integer, so round it here
|
|
90
|
+
return new_trans_frac, round(new_exposure_time_s, 3)
|
mx_bluesky/hyperion/__main__.py
CHANGED
|
@@ -45,21 +45,13 @@ from mx_bluesky.hyperion.runner import (
|
|
|
45
45
|
from mx_bluesky.hyperion.utils.context import setup_context
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def compose_start_args(context: BlueskyContext, plan_name: str
|
|
48
|
+
def compose_start_args(context: BlueskyContext, plan_name: str):
|
|
49
49
|
experiment_registry_entry = PLAN_REGISTRY.get(plan_name)
|
|
50
50
|
if experiment_registry_entry is None:
|
|
51
51
|
raise PlanNotFoundError(f"Experiment plan '{plan_name}' not found in registry.")
|
|
52
52
|
|
|
53
53
|
experiment_internal_param_type = experiment_registry_entry.get("param_type")
|
|
54
54
|
plan = context.plan_functions.get(plan_name)
|
|
55
|
-
if experiment_internal_param_type is None:
|
|
56
|
-
raise PlanNotFoundError(
|
|
57
|
-
f"Corresponding internal param type for '{plan_name}' not found in registry."
|
|
58
|
-
)
|
|
59
|
-
if plan is None:
|
|
60
|
-
raise PlanNotFoundError(
|
|
61
|
-
f"Experiment plan '{plan_name}' not found in context. Context has {context.plan_functions.keys()}"
|
|
62
|
-
)
|
|
63
55
|
try:
|
|
64
56
|
parameters = experiment_internal_param_type(**json.loads(request.data))
|
|
65
57
|
parameters = update_params_from_agamemnon(parameters)
|
|
@@ -80,13 +72,11 @@ class RunExperiment(Resource):
|
|
|
80
72
|
self.runner = runner
|
|
81
73
|
self.context = context
|
|
82
74
|
|
|
83
|
-
def put(self, plan_name: str, action:
|
|
75
|
+
def put(self, plan_name: str, action: str):
|
|
84
76
|
status_and_message = StatusAndMessage(Status.FAILED, f"{action} not understood")
|
|
85
77
|
if action == Actions.START.value:
|
|
86
78
|
try:
|
|
87
|
-
plan, params, plan_name = compose_start_args(
|
|
88
|
-
self.context, plan_name, action
|
|
89
|
-
)
|
|
79
|
+
plan, params, plan_name = compose_start_args(self.context, plan_name)
|
|
90
80
|
status_and_message = self.runner.start(plan, params, plan_name)
|
|
91
81
|
except Exception as e:
|
|
92
82
|
status_and_message = make_error_status_and_message(e)
|
|
@@ -15,10 +15,6 @@ from dodal.devices.robot import BartRobot
|
|
|
15
15
|
from dodal.devices.smargon import Smargon
|
|
16
16
|
|
|
17
17
|
from mx_bluesky.common.device_setup_plans.robot_load_unload import robot_unload
|
|
18
|
-
from mx_bluesky.common.experiment_plans.inner_plans.udc_default_state import (
|
|
19
|
-
UDCDefaultDevices,
|
|
20
|
-
move_to_udc_default_state,
|
|
21
|
-
)
|
|
22
18
|
from mx_bluesky.common.external_interaction.alerting import (
|
|
23
19
|
AlertService,
|
|
24
20
|
get_alerting_service,
|
|
@@ -28,11 +24,16 @@ from mx_bluesky.common.utils.context import (
|
|
|
28
24
|
device_composite_from_context,
|
|
29
25
|
find_device_in_context,
|
|
30
26
|
)
|
|
27
|
+
from mx_bluesky.common.utils.exceptions import BeamlineCheckFailureError
|
|
31
28
|
from mx_bluesky.common.utils.log import LOGGER
|
|
32
29
|
from mx_bluesky.hyperion.experiment_plans.load_centre_collect_full_plan import (
|
|
33
30
|
create_devices,
|
|
34
31
|
load_centre_collect_full,
|
|
35
32
|
)
|
|
33
|
+
from mx_bluesky.hyperion.experiment_plans.udc_default_state import (
|
|
34
|
+
UDCDefaultDevices,
|
|
35
|
+
move_to_udc_default_state,
|
|
36
|
+
)
|
|
36
37
|
from mx_bluesky.hyperion.external_interaction.agamemnon import (
|
|
37
38
|
create_parameters_from_agamemnon,
|
|
38
39
|
)
|
|
@@ -100,7 +101,11 @@ def run_udc_when_requested(context: BlueskyContext, runner: PlanRunner):
|
|
|
100
101
|
runner: The runner
|
|
101
102
|
"""
|
|
102
103
|
_raise_udc_start_alert(get_alerting_service())
|
|
103
|
-
yield from
|
|
104
|
+
yield from bpp.contingency_wrapper(
|
|
105
|
+
_move_to_udc_default_state(context),
|
|
106
|
+
except_plan=trap_default_state_exception,
|
|
107
|
+
auto_raise=False,
|
|
108
|
+
)
|
|
104
109
|
|
|
105
110
|
# re-fetch the baton because the device has been reinstantiated
|
|
106
111
|
baton = _get_baton(context)
|
|
@@ -121,8 +126,20 @@ def run_udc_when_requested(context: BlueskyContext, runner: PlanRunner):
|
|
|
121
126
|
yield from bps.abs_set(baton.current_user, NO_USER, wait=True)
|
|
122
127
|
_raise_baton_released_alert(get_alerting_service(), previous_requested_user)
|
|
123
128
|
|
|
129
|
+
def trap_default_state_exception(e: Exception):
|
|
130
|
+
yield from bps.null()
|
|
131
|
+
if isinstance(e, BeamlineCheckFailureError):
|
|
132
|
+
LOGGER.warning("Caught default state check failure:", exc_info=e)
|
|
133
|
+
raise PlanError("Caught default state check failure") from e
|
|
134
|
+
else:
|
|
135
|
+
LOGGER.warning("Caught unexpected exception", exc_info=e)
|
|
136
|
+
raise PlanError("Unexpected exception from UDC Default State plan") from e
|
|
137
|
+
|
|
124
138
|
def collect_then_release() -> MsgGenerator:
|
|
125
|
-
yield from bpp.contingency_wrapper(
|
|
139
|
+
yield from bpp.contingency_wrapper(
|
|
140
|
+
collect(),
|
|
141
|
+
final_plan=release_baton,
|
|
142
|
+
)
|
|
126
143
|
|
|
127
144
|
context.run_engine(acquire_baton())
|
|
128
145
|
_initialise_udc(context, runner.is_dev_mode)
|
|
@@ -21,6 +21,10 @@ from mx_bluesky.common.experiment_plans.common_grid_detect_then_xray_centre_plan
|
|
|
21
21
|
from mx_bluesky.common.experiment_plans.oav_snapshot_plan import (
|
|
22
22
|
setup_beamline_for_oav,
|
|
23
23
|
)
|
|
24
|
+
from mx_bluesky.common.experiment_plans.pin_tip_centring_plan import (
|
|
25
|
+
PinTipCentringComposite,
|
|
26
|
+
pin_tip_centre_plan,
|
|
27
|
+
)
|
|
24
28
|
from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
|
|
25
29
|
ispyb_activation_wrapper,
|
|
26
30
|
)
|
|
@@ -31,10 +35,6 @@ from mx_bluesky.common.xrc_result import XRayCentreEventHandler
|
|
|
31
35
|
from mx_bluesky.hyperion.experiment_plans.hyperion_flyscan_xray_centre_plan import (
|
|
32
36
|
construct_hyperion_specific_features,
|
|
33
37
|
)
|
|
34
|
-
from mx_bluesky.hyperion.experiment_plans.pin_tip_centring_plan import (
|
|
35
|
-
PinTipCentringComposite,
|
|
36
|
-
pin_tip_centre_plan,
|
|
37
|
-
)
|
|
38
38
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
39
39
|
from mx_bluesky.hyperion.parameters.device_composites import (
|
|
40
40
|
HyperionGridDetectThenXRayCentreComposite,
|
|
@@ -78,8 +78,7 @@ def pin_centre_then_flyscan_plan(
|
|
|
78
78
|
|
|
79
79
|
pin_tip_centring_composite = PinTipCentringComposite(
|
|
80
80
|
oav=composite.oav,
|
|
81
|
-
|
|
82
|
-
backlight=composite.backlight,
|
|
81
|
+
gonio=composite.smargon,
|
|
83
82
|
pin_tip_detection=composite.pin_tip_detection,
|
|
84
83
|
)
|
|
85
84
|
|
|
@@ -20,7 +20,7 @@ from dodal.devices.motors import XYZStage
|
|
|
20
20
|
from dodal.devices.oav.oav_detector import OAV
|
|
21
21
|
from dodal.devices.robot import BartRobot, SampleLocation
|
|
22
22
|
from dodal.devices.smargon import Smargon
|
|
23
|
-
from dodal.devices.thawer import Thawer
|
|
23
|
+
from dodal.devices.thawer import OnOff, Thawer
|
|
24
24
|
from dodal.devices.webcam import Webcam
|
|
25
25
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
26
26
|
|
|
@@ -82,7 +82,6 @@ def do_robot_load(
|
|
|
82
82
|
sample_location: SampleLocation,
|
|
83
83
|
sample_id: int,
|
|
84
84
|
demand_energy_ev: float | None,
|
|
85
|
-
thawing_time: float,
|
|
86
85
|
):
|
|
87
86
|
yield from bps.abs_set(composite.robot.next_sample_id, sample_id, wait=True)
|
|
88
87
|
|
|
@@ -96,13 +95,10 @@ def do_robot_load(
|
|
|
96
95
|
|
|
97
96
|
yield from bps.wait("robot_load")
|
|
98
97
|
|
|
99
|
-
yield from bps.abs_set(
|
|
100
|
-
composite.thawer.thaw_for_time_s,
|
|
101
|
-
thawing_time,
|
|
102
|
-
group="thawing_finished",
|
|
103
|
-
)
|
|
104
98
|
yield from wait_for_smargon_not_disabled(composite.smargon)
|
|
105
99
|
|
|
100
|
+
yield from bps.mv(composite.thawer, OnOff.ON)
|
|
101
|
+
|
|
106
102
|
|
|
107
103
|
def pin_already_loaded(
|
|
108
104
|
robot: BartRobot, sample_location: SampleLocation
|
|
@@ -120,7 +116,6 @@ def robot_load_and_snapshots(
|
|
|
120
116
|
location: SampleLocation,
|
|
121
117
|
snapshot_directory: Path,
|
|
122
118
|
sample_id: int,
|
|
123
|
-
thawing_time: float,
|
|
124
119
|
demand_energy_ev: float | None,
|
|
125
120
|
):
|
|
126
121
|
yield from bps.abs_set(composite.backlight, InOut.IN, group="snapshot")
|
|
@@ -134,7 +129,6 @@ def robot_load_and_snapshots(
|
|
|
134
129
|
location,
|
|
135
130
|
sample_id,
|
|
136
131
|
demand_energy_ev,
|
|
137
|
-
thawing_time,
|
|
138
132
|
)
|
|
139
133
|
|
|
140
134
|
gonio_finished = yield from do_plan_while_lower_gonio_at_home(
|
|
@@ -173,7 +167,6 @@ def robot_load_and_change_energy_plan(
|
|
|
173
167
|
sample_location,
|
|
174
168
|
params.snapshot_directory,
|
|
175
169
|
params.sample_id,
|
|
176
|
-
params.thawing_time,
|
|
177
170
|
params.demand_energy_ev,
|
|
178
171
|
),
|
|
179
172
|
md={
|
|
@@ -10,6 +10,7 @@ from bluesky.utils import MsgGenerator
|
|
|
10
10
|
from dodal.devices.aperturescatterguard import ApertureScatterguard
|
|
11
11
|
from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
|
|
12
12
|
from dodal.devices.backlight import Backlight
|
|
13
|
+
from dodal.devices.beamsize.beamsize import BeamsizeBase
|
|
13
14
|
from dodal.devices.detector.detector_motion import DetectorMotion
|
|
14
15
|
from dodal.devices.eiger import EigerDetector
|
|
15
16
|
from dodal.devices.fast_grid_scan import PandAFastGridScan, ZebraFastGridScanThreeD
|
|
@@ -26,7 +27,7 @@ from dodal.devices.s4_slit_gaps import S4SlitGaps
|
|
|
26
27
|
from dodal.devices.smargon import Smargon
|
|
27
28
|
from dodal.devices.synchrotron import Synchrotron
|
|
28
29
|
from dodal.devices.thawer import Thawer
|
|
29
|
-
from dodal.devices.undulator import
|
|
30
|
+
from dodal.devices.undulator import UndulatorInKeV
|
|
30
31
|
from dodal.devices.webcam import Webcam
|
|
31
32
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
32
33
|
from dodal.devices.zebra.zebra import Zebra
|
|
@@ -70,6 +71,7 @@ class RobotLoadThenCentreComposite:
|
|
|
70
71
|
# HyperionGridDetectThenXRayCentreComposite fields
|
|
71
72
|
aperture_scatterguard: ApertureScatterguard
|
|
72
73
|
backlight: Backlight
|
|
74
|
+
beamsize: BeamsizeBase
|
|
73
75
|
detector_motion: DetectorMotion
|
|
74
76
|
eiger: EigerDetector
|
|
75
77
|
zebra_fast_grid_scan: ZebraFastGridScanThreeD
|
|
@@ -79,7 +81,7 @@ class RobotLoadThenCentreComposite:
|
|
|
79
81
|
smargon: Smargon
|
|
80
82
|
synchrotron: Synchrotron
|
|
81
83
|
s4_slit_gaps: S4SlitGaps
|
|
82
|
-
undulator:
|
|
84
|
+
undulator: UndulatorInKeV
|
|
83
85
|
zebra: Zebra
|
|
84
86
|
zocalo: ZocaloResults
|
|
85
87
|
panda: HDFPanda
|
|
@@ -10,6 +10,7 @@ from bluesky.utils import MsgGenerator
|
|
|
10
10
|
from dodal.devices.aperturescatterguard import ApertureScatterguard
|
|
11
11
|
from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
|
|
12
12
|
from dodal.devices.backlight import Backlight
|
|
13
|
+
from dodal.devices.beamsize.beamsize import BeamsizeBase
|
|
13
14
|
from dodal.devices.detector.detector_motion import DetectorMotion
|
|
14
15
|
from dodal.devices.eiger import EigerDetector
|
|
15
16
|
from dodal.devices.flux import Flux
|
|
@@ -21,7 +22,8 @@ from dodal.devices.robot import BartRobot
|
|
|
21
22
|
from dodal.devices.s4_slit_gaps import S4SlitGaps
|
|
22
23
|
from dodal.devices.smargon import CombinedMove, Smargon
|
|
23
24
|
from dodal.devices.synchrotron import Synchrotron
|
|
24
|
-
from dodal.devices.
|
|
25
|
+
from dodal.devices.thawer import Thawer
|
|
26
|
+
from dodal.devices.undulator import UndulatorInKeV
|
|
25
27
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
26
28
|
from dodal.devices.zebra.zebra import RotationDirection, Zebra
|
|
27
29
|
from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
|
|
@@ -74,6 +76,7 @@ class RotationScanComposite(OavSnapshotComposite):
|
|
|
74
76
|
aperture_scatterguard: ApertureScatterguard
|
|
75
77
|
attenuator: BinaryFilterAttenuator
|
|
76
78
|
backlight: Backlight
|
|
79
|
+
beamsize: BeamsizeBase
|
|
77
80
|
beamstop: Beamstop
|
|
78
81
|
dcm: DCM
|
|
79
82
|
detector_motion: DetectorMotion
|
|
@@ -81,13 +84,14 @@ class RotationScanComposite(OavSnapshotComposite):
|
|
|
81
84
|
flux: Flux
|
|
82
85
|
robot: BartRobot
|
|
83
86
|
smargon: Smargon
|
|
84
|
-
undulator:
|
|
87
|
+
undulator: UndulatorInKeV
|
|
85
88
|
synchrotron: Synchrotron
|
|
86
89
|
s4_slit_gaps: S4SlitGaps
|
|
87
90
|
sample_shutter: ZebraShutter
|
|
88
91
|
zebra: Zebra
|
|
89
92
|
oav: OAV
|
|
90
93
|
xbpm_feedback: XBPMFeedback
|
|
94
|
+
thawer: Thawer
|
|
91
95
|
|
|
92
96
|
|
|
93
97
|
def create_devices(context: BlueskyContext) -> RotationScanComposite:
|
|
@@ -258,6 +262,7 @@ def rotation_scan_plan(
|
|
|
258
262
|
composite.aperture_scatterguard,
|
|
259
263
|
params.selected_aperture,
|
|
260
264
|
composite.backlight,
|
|
265
|
+
composite.thawer,
|
|
261
266
|
group=CONST.WAIT.ROTATION_READY_FOR_DC,
|
|
262
267
|
)
|
|
263
268
|
|
|
@@ -301,6 +306,7 @@ def rotation_scan_plan(
|
|
|
301
306
|
composite.flux,
|
|
302
307
|
composite.dcm,
|
|
303
308
|
composite.eiger,
|
|
309
|
+
composite.beamsize,
|
|
304
310
|
)
|
|
305
311
|
|
|
306
312
|
yield from _rotation_scan_plan(motion_values, composite)
|
|
@@ -12,7 +12,7 @@ from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
|
|
|
12
12
|
from dodal.devices.focusing_mirror import FocusingMirrorWithStripes, MirrorVoltages
|
|
13
13
|
from dodal.devices.i03.dcm import DCM
|
|
14
14
|
from dodal.devices.i03.undulator_dcm import UndulatorDCM
|
|
15
|
-
from dodal.devices.undulator import
|
|
15
|
+
from dodal.devices.undulator import UndulatorInKeV
|
|
16
16
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
17
17
|
|
|
18
18
|
from mx_bluesky.common.parameters.constants import PlanNameConstants
|
|
@@ -39,7 +39,7 @@ class SetEnergyComposite:
|
|
|
39
39
|
# Remove composite after https://github.com/DiamondLightSource/dodal/issues/1092
|
|
40
40
|
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
41
41
|
class XBPMWrapperComposite:
|
|
42
|
-
undulator:
|
|
42
|
+
undulator: UndulatorInKeV
|
|
43
43
|
xbpm_feedback: XBPMFeedback
|
|
44
44
|
attenuator: BinaryFilterAttenuator
|
|
45
45
|
dcm: DCM
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import bluesky.plan_stubs as bps
|
|
2
|
+
import pydantic
|
|
3
|
+
from bluesky.utils import MsgGenerator
|
|
4
|
+
from dodal.common.beamlines.beamline_parameters import (
|
|
5
|
+
get_beamline_parameters,
|
|
6
|
+
)
|
|
7
|
+
from dodal.devices.aperturescatterguard import ApertureValue
|
|
8
|
+
from dodal.devices.collimation_table import CollimationTable
|
|
9
|
+
from dodal.devices.cryostream import CryoStream, CryoStreamGantry, CryoStreamSelection
|
|
10
|
+
from dodal.devices.cryostream import InOut as CryoInOut
|
|
11
|
+
from dodal.devices.fluorescence_detector_motion import FluorescenceDetector
|
|
12
|
+
from dodal.devices.fluorescence_detector_motion import InOut as FlouInOut
|
|
13
|
+
from dodal.devices.hutch_shutter import HutchShutter, ShutterDemand
|
|
14
|
+
from dodal.devices.mx_phase1.beamstop import BeamstopPositions
|
|
15
|
+
from dodal.devices.robot import BartRobot, PinMounted
|
|
16
|
+
from dodal.devices.scintillator import InOut as ScinInOut
|
|
17
|
+
from dodal.devices.scintillator import Scintillator
|
|
18
|
+
from dodal.devices.smargon import Smargon
|
|
19
|
+
from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutterState
|
|
20
|
+
|
|
21
|
+
from mx_bluesky.common.experiment_plans.beamstop_check import (
|
|
22
|
+
BeamstopCheckDevices,
|
|
23
|
+
move_beamstop_in_and_verify_using_diode,
|
|
24
|
+
)
|
|
25
|
+
from mx_bluesky.common.utils.exceptions import BeamlineCheckFailureError
|
|
26
|
+
from mx_bluesky.common.utils.log import LOGGER
|
|
27
|
+
from mx_bluesky.hyperion.external_interaction.config_server import (
|
|
28
|
+
get_hyperion_config_client,
|
|
29
|
+
)
|
|
30
|
+
from mx_bluesky.hyperion.parameters.constants import HyperionFeatureSettings
|
|
31
|
+
|
|
32
|
+
_GROUP_PRE_BEAMSTOP_CHECK = "pre_beamstop_check"
|
|
33
|
+
_GROUP_POST_BEAMSTOP_CHECK = "post_beamstop_check"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
37
|
+
class UDCDefaultDevices(BeamstopCheckDevices):
|
|
38
|
+
collimation_table: CollimationTable
|
|
39
|
+
cryostream: CryoStream
|
|
40
|
+
cryostream_gantry: CryoStreamGantry
|
|
41
|
+
fluorescence_det_motion: FluorescenceDetector
|
|
42
|
+
hutch_shutter: HutchShutter
|
|
43
|
+
robot: BartRobot
|
|
44
|
+
scintillator: Scintillator
|
|
45
|
+
smargon: Smargon
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class UnexpectedSampleError(BeamlineCheckFailureError): ...
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class CryoStreamError(BeamlineCheckFailureError): ...
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def move_to_udc_default_state(devices: UDCDefaultDevices):
|
|
55
|
+
"""Moves beamline to known positions prior to UDC start"""
|
|
56
|
+
yield from _verify_correct_cryostream_selected(devices.cryostream_gantry)
|
|
57
|
+
|
|
58
|
+
cryostream_temp = yield from bps.rd(devices.cryostream.temperature_k)
|
|
59
|
+
cryostream_pressure = yield from bps.rd(devices.cryostream.back_pressure_bar)
|
|
60
|
+
if cryostream_temp > devices.cryostream.MAX_TEMP_K:
|
|
61
|
+
raise CryoStreamError("Cryostream temperature is too high, not starting UDC")
|
|
62
|
+
if cryostream_pressure > devices.cryostream.MAX_PRESSURE_BAR:
|
|
63
|
+
raise CryoStreamError("Cryostream back pressure is too high, not starting UDC")
|
|
64
|
+
|
|
65
|
+
yield from _verify_no_sample_present(devices.robot)
|
|
66
|
+
|
|
67
|
+
# Close fast shutter before opening hutch shutter
|
|
68
|
+
yield from bps.abs_set(devices.sample_shutter, ZebraShutterState.CLOSE, wait=True)
|
|
69
|
+
|
|
70
|
+
commissioning_mode_enabled = yield from bps.rd(devices.baton.commissioning)
|
|
71
|
+
|
|
72
|
+
if commissioning_mode_enabled:
|
|
73
|
+
LOGGER.warning("Not opening hutch shutter - commissioning mode is enabled.")
|
|
74
|
+
else:
|
|
75
|
+
yield from bps.abs_set(
|
|
76
|
+
devices.hutch_shutter, ShutterDemand.OPEN, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
yield from bps.abs_set(devices.scintillator.selected_pos, ScinInOut.OUT, wait=True)
|
|
80
|
+
|
|
81
|
+
yield from bps.abs_set(
|
|
82
|
+
devices.fluorescence_det_motion.pos,
|
|
83
|
+
FlouInOut.OUT,
|
|
84
|
+
group=_GROUP_PRE_BEAMSTOP_CHECK,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
yield from bps.abs_set(
|
|
88
|
+
devices.collimation_table.inboard_y,
|
|
89
|
+
0,
|
|
90
|
+
group=_GROUP_PRE_BEAMSTOP_CHECK,
|
|
91
|
+
)
|
|
92
|
+
yield from bps.abs_set(
|
|
93
|
+
devices.collimation_table.outboard_y, 0, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
94
|
+
)
|
|
95
|
+
yield from bps.abs_set(
|
|
96
|
+
devices.collimation_table.upstream_y, 0, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
97
|
+
)
|
|
98
|
+
yield from bps.abs_set(
|
|
99
|
+
devices.collimation_table.upstream_x, 0, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
100
|
+
)
|
|
101
|
+
yield from bps.abs_set(
|
|
102
|
+
devices.collimation_table.downstream_x, 0, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Wait for all of the above to complete
|
|
106
|
+
yield from bps.wait(group=_GROUP_PRE_BEAMSTOP_CHECK, timeout=0.1)
|
|
107
|
+
|
|
108
|
+
feature_flags: HyperionFeatureSettings = (
|
|
109
|
+
get_hyperion_config_client().get_feature_flags()
|
|
110
|
+
)
|
|
111
|
+
if feature_flags.BEAMSTOP_DIODE_CHECK:
|
|
112
|
+
beamline_parameters = get_beamline_parameters()
|
|
113
|
+
config_client = get_hyperion_config_client()
|
|
114
|
+
features_settings: HyperionFeatureSettings = config_client.get_feature_flags()
|
|
115
|
+
detector_min_z = features_settings.DETECTOR_DISTANCE_LIMIT_MIN_MM
|
|
116
|
+
detector_max_z = features_settings.DETECTOR_DISTANCE_LIMIT_MAX_MM
|
|
117
|
+
yield from move_beamstop_in_and_verify_using_diode(
|
|
118
|
+
devices, beamline_parameters, detector_min_z, detector_max_z
|
|
119
|
+
)
|
|
120
|
+
else:
|
|
121
|
+
yield from bps.abs_set(
|
|
122
|
+
devices.beamstop.selected_pos, BeamstopPositions.DATA_COLLECTION, wait=True
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
yield from bps.abs_set(
|
|
126
|
+
devices.aperture_scatterguard.selected_aperture,
|
|
127
|
+
ApertureValue.SMALL,
|
|
128
|
+
group=_GROUP_POST_BEAMSTOP_CHECK,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
yield from bps.abs_set(
|
|
132
|
+
devices.cryostream.course, CryoInOut.IN, group=_GROUP_POST_BEAMSTOP_CHECK
|
|
133
|
+
)
|
|
134
|
+
yield from bps.abs_set(
|
|
135
|
+
devices.cryostream.fine, CryoInOut.IN, group=_GROUP_POST_BEAMSTOP_CHECK
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
yield from bps.wait(_GROUP_POST_BEAMSTOP_CHECK)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _verify_correct_cryostream_selected(
|
|
142
|
+
cryostream_gantry: CryoStreamGantry,
|
|
143
|
+
) -> MsgGenerator:
|
|
144
|
+
cryostream_selection = yield from bps.rd(cryostream_gantry.cryostream_selector)
|
|
145
|
+
cryostream_selected = yield from bps.rd(cryostream_gantry.cryostream_selected)
|
|
146
|
+
if cryostream_selection != CryoStreamSelection.CRYOJET or cryostream_selected != 1:
|
|
147
|
+
raise CryoStreamError(
|
|
148
|
+
f"Cryostream is not selected for use, control PV selection = {cryostream_selection}, "
|
|
149
|
+
f"current status {cryostream_selected}"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _verify_no_sample_present(robot: BartRobot):
|
|
154
|
+
pin_mounted = yield from bps.rd(robot.gonio_pin_sensor)
|
|
155
|
+
|
|
156
|
+
if pin_mounted != PinMounted.NO_PIN_MOUNTED:
|
|
157
|
+
# Cannot unload this sample because we do not know the correct visit for it
|
|
158
|
+
raise UnexpectedSampleError(
|
|
159
|
+
"An unexpected sample was found, please unload the sample manually."
|
|
160
|
+
)
|
|
@@ -220,7 +220,7 @@ def _get_withvisit_parameters_from_agamemnon(parameters: dict) -> tuple:
|
|
|
220
220
|
def _get_withenergy_parameters_from_agamemnon(parameters: dict) -> dict[str, Any]:
|
|
221
221
|
try:
|
|
222
222
|
first_collection: dict = parameters["collection"][0]
|
|
223
|
-
wavelength = first_collection.get("wavelength")
|
|
223
|
+
wavelength: float | None = first_collection.get("wavelength")
|
|
224
224
|
assert isinstance(wavelength, float)
|
|
225
225
|
demand_energy_ev = convert_angstrom_to_ev(wavelength)
|
|
226
226
|
return {"demand_energy_ev": demand_energy_ev}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from collections.abc import Callable, Sequence
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
6
|
from dodal.devices.zocalo import ZocaloStartInfo
|
|
7
7
|
|
|
@@ -92,7 +92,7 @@ class RotationISPyBCallback(BaseISPyBCallback):
|
|
|
92
92
|
ISPYB_ZOCALO_CALLBACK_LOGGER.info("Beginning ispyb deposition")
|
|
93
93
|
data_collection_group_info = populate_data_collection_group(self.params)
|
|
94
94
|
data_collection_info = populate_data_collection_info_for_rotation(
|
|
95
|
-
|
|
95
|
+
self.params
|
|
96
96
|
)
|
|
97
97
|
data_collection_info = populate_remaining_data_collection_info(
|
|
98
98
|
self.params.comment,
|
|
@@ -6,6 +6,7 @@ from mx_bluesky.hyperion.parameters.rotation import SingleRotationScan
|
|
|
6
6
|
|
|
7
7
|
def populate_data_collection_info_for_rotation(params: SingleRotationScan):
|
|
8
8
|
info = DataCollectionInfo(
|
|
9
|
+
chi_start=params.chi_start_deg,
|
|
9
10
|
omega_start=params.omega_start_deg,
|
|
10
11
|
data_collection_number=params.detector_params.run_number, # type:ignore # the validator always makes this int
|
|
11
12
|
n_images=params.num_images,
|
|
@@ -2,9 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
-
from mx_bluesky.common.external_interaction.callbacks.common.logging_callback import (
|
|
6
|
-
format_doc_for_log,
|
|
7
|
-
)
|
|
8
5
|
from mx_bluesky.common.external_interaction.callbacks.common.plan_reactive_callback import (
|
|
9
6
|
PlanReactiveCallback,
|
|
10
7
|
)
|
|
@@ -14,7 +11,7 @@ from mx_bluesky.common.external_interaction.nexus.nexus_utils import (
|
|
|
14
11
|
vds_type_based_on_bit_depth,
|
|
15
12
|
)
|
|
16
13
|
from mx_bluesky.common.external_interaction.nexus.write_nexus import NexusWriter
|
|
17
|
-
from mx_bluesky.common.utils.log import NEXUS_LOGGER
|
|
14
|
+
from mx_bluesky.common.utils.log import NEXUS_LOGGER, format_doc_for_log
|
|
18
15
|
from mx_bluesky.hyperion.parameters.constants import CONST, I03Constants
|
|
19
16
|
from mx_bluesky.hyperion.parameters.rotation import SingleRotationScan
|
|
20
17
|
|
|
@@ -2,15 +2,15 @@ from functools import cache
|
|
|
2
2
|
|
|
3
3
|
from mx_bluesky.common.external_interaction.config_server import MXConfigClient
|
|
4
4
|
from mx_bluesky.hyperion.parameters.constants import (
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
HyperionFeatureSettings,
|
|
6
|
+
HyperionFeatureSettingsSources,
|
|
7
7
|
)
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@cache
|
|
11
|
-
def get_hyperion_config_client() -> MXConfigClient[
|
|
11
|
+
def get_hyperion_config_client() -> MXConfigClient[HyperionFeatureSettings]:
|
|
12
12
|
return MXConfigClient(
|
|
13
|
-
feature_sources=
|
|
14
|
-
feature_dc=
|
|
13
|
+
feature_sources=HyperionFeatureSettingsSources,
|
|
14
|
+
feature_dc=HyperionFeatureSettings,
|
|
15
15
|
url="https://daq-config.diamond.ac.uk",
|
|
16
16
|
)
|
|
@@ -8,7 +8,7 @@ from mx_bluesky.common.parameters.constants import (
|
|
|
8
8
|
DocDescriptorNames,
|
|
9
9
|
EnvironmentConstants,
|
|
10
10
|
ExperimentParamConstants,
|
|
11
|
-
|
|
11
|
+
FeatureSettings,
|
|
12
12
|
FeatureSettingSources,
|
|
13
13
|
HardwareConstants,
|
|
14
14
|
OavConstants,
|
|
@@ -32,20 +32,27 @@ class I03Constants:
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
# These currently exist in GDA domain.properties
|
|
35
|
-
class
|
|
35
|
+
class HyperionFeatureSettingsSources(FeatureSettingSources):
|
|
36
36
|
USE_GPU_RESULTS = "gda.mx.hyperion.xrc.use_gpu_results"
|
|
37
37
|
USE_PANDA_FOR_GRIDSCAN = "gda.mx.hyperion.use_panda_for_gridscans"
|
|
38
38
|
SET_STUB_OFFSETS = "gda.mx.hyperion.do_stub_offsets"
|
|
39
39
|
PANDA_RUNUP_DISTANCE_MM = "gda.mx.hyperion.panda_runup_distance_mm"
|
|
40
|
+
DETECTOR_DISTANCE_LIMIT_MAX_MM = "gda.detector.distance.limit.max"
|
|
41
|
+
DETECTOR_DISTANCE_LIMIT_MIN_MM = "gda.detector.distance.limit.min"
|
|
42
|
+
BEAMSTOP_DIODE_CHECK = "gda.mx.hyperion.enable_beamstop_diode_check"
|
|
40
43
|
|
|
41
44
|
|
|
42
45
|
# Use these defaults if we can't read from the config server
|
|
43
46
|
@dataclass
|
|
44
|
-
class
|
|
47
|
+
class HyperionFeatureSettings(FeatureSettings):
|
|
45
48
|
USE_GPU_RESULTS: bool = True
|
|
46
49
|
USE_PANDA_FOR_GRIDSCAN: bool = False
|
|
47
50
|
SET_STUB_OFFSETS: bool = False
|
|
48
51
|
PANDA_RUNUP_DISTANCE_MM: float = 0.16
|
|
52
|
+
# From GDA mx-config hutch_utilities.py default values
|
|
53
|
+
DETECTOR_DISTANCE_LIMIT_MAX_MM: float = 700
|
|
54
|
+
DETECTOR_DISTANCE_LIMIT_MIN_MM: float = 250
|
|
55
|
+
BEAMSTOP_DIODE_CHECK: bool = False
|
|
49
56
|
|
|
50
57
|
|
|
51
58
|
@dataclass(frozen=True)
|
|
@@ -16,7 +16,7 @@ from dodal.devices.flux import Flux
|
|
|
16
16
|
from dodal.devices.robot import BartRobot
|
|
17
17
|
from dodal.devices.s4_slit_gaps import S4SlitGaps
|
|
18
18
|
from dodal.devices.synchrotron import Synchrotron
|
|
19
|
-
from dodal.devices.undulator import
|
|
19
|
+
from dodal.devices.undulator import UndulatorInKeV
|
|
20
20
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
21
21
|
from dodal.devices.zebra.zebra import Zebra
|
|
22
22
|
from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
|
|
@@ -41,7 +41,7 @@ class HyperionFlyScanXRayCentreComposite(FlyScanEssentialDevices):
|
|
|
41
41
|
eiger: EigerDetector
|
|
42
42
|
flux: Flux
|
|
43
43
|
s4_slit_gaps: S4SlitGaps
|
|
44
|
-
undulator:
|
|
44
|
+
undulator: UndulatorInKeV
|
|
45
45
|
synchrotron: Synchrotron
|
|
46
46
|
zebra: Zebra
|
|
47
47
|
zocalo: ZocaloResults
|