mx-bluesky 1.5.11__py3-none-any.whl → 1.5.14__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/Getting started.ipynb +170 -0
- 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 +74 -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 +88 -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 +6 -6
- 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 +5 -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/hyperion_flyscan_xray_centre_plan.py +1 -0
- 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 +166 -0
- mx_bluesky/hyperion/external_interaction/agamemnon.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +48 -21
- 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 +4 -2
- mx_bluesky/hyperion/parameters/robot_load.py +1 -9
- mx_bluesky/hyperion/plan_runner.py +31 -0
- mx_bluesky/hyperion/plan_runner_api.py +14 -1
- mx_bluesky/hyperion/utils/context.py +2 -2
- mx_bluesky/jupyter_example.ipynb +9 -1
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.14.dist-info}/METADATA +7 -6
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.14.dist-info}/RECORD +90 -75
- 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.14.dist-info}/WHEEL +0 -0
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.14.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.14.dist-info}/licenses/LICENSE +0 -0
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.14.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,166 @@
|
|
|
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 (
|
|
10
|
+
CryoStreamGantry,
|
|
11
|
+
CryoStreamSelection,
|
|
12
|
+
OxfordCryoJet,
|
|
13
|
+
OxfordCryoStream,
|
|
14
|
+
)
|
|
15
|
+
from dodal.devices.cryostream import InOut as CryoInOut
|
|
16
|
+
from dodal.devices.fluorescence_detector_motion import FluorescenceDetector
|
|
17
|
+
from dodal.devices.fluorescence_detector_motion import InOut as FlouInOut
|
|
18
|
+
from dodal.devices.hutch_shutter import HutchShutter, ShutterDemand
|
|
19
|
+
from dodal.devices.mx_phase1.beamstop import BeamstopPositions
|
|
20
|
+
from dodal.devices.robot import BartRobot, PinMounted
|
|
21
|
+
from dodal.devices.scintillator import InOut as ScinInOut
|
|
22
|
+
from dodal.devices.scintillator import Scintillator
|
|
23
|
+
from dodal.devices.smargon import Smargon
|
|
24
|
+
from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutterState
|
|
25
|
+
|
|
26
|
+
from mx_bluesky.common.experiment_plans.beamstop_check import (
|
|
27
|
+
BeamstopCheckDevices,
|
|
28
|
+
move_beamstop_in_and_verify_using_diode,
|
|
29
|
+
)
|
|
30
|
+
from mx_bluesky.common.utils.exceptions import BeamlineCheckFailureError
|
|
31
|
+
from mx_bluesky.common.utils.log import LOGGER
|
|
32
|
+
from mx_bluesky.hyperion.external_interaction.config_server import (
|
|
33
|
+
get_hyperion_config_client,
|
|
34
|
+
)
|
|
35
|
+
from mx_bluesky.hyperion.parameters.constants import CONST, HyperionFeatureSettings
|
|
36
|
+
|
|
37
|
+
_GROUP_PRE_BEAMSTOP_CHECK = "pre_beamstop_check"
|
|
38
|
+
_GROUP_POST_BEAMSTOP_CHECK = "post_beamstop_check"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
42
|
+
class UDCDefaultDevices(BeamstopCheckDevices):
|
|
43
|
+
collimation_table: CollimationTable
|
|
44
|
+
cryojet: OxfordCryoJet
|
|
45
|
+
cryostream: OxfordCryoStream
|
|
46
|
+
cryostream_gantry: CryoStreamGantry
|
|
47
|
+
fluorescence_det_motion: FluorescenceDetector
|
|
48
|
+
hutch_shutter: HutchShutter
|
|
49
|
+
robot: BartRobot
|
|
50
|
+
scintillator: Scintillator
|
|
51
|
+
smargon: Smargon
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class UnexpectedSampleError(BeamlineCheckFailureError): ...
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class CryoStreamError(BeamlineCheckFailureError): ...
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def move_to_udc_default_state(devices: UDCDefaultDevices):
|
|
61
|
+
"""Moves beamline to known positions prior to UDC start"""
|
|
62
|
+
yield from _verify_correct_cryostream_selected(devices.cryostream_gantry)
|
|
63
|
+
|
|
64
|
+
cryostream_temp = yield from bps.rd(devices.cryostream.temp)
|
|
65
|
+
cryostream_pressure = yield from bps.rd(devices.cryostream.back_pressure)
|
|
66
|
+
if cryostream_temp > CONST.HARDWARE.MAX_CRYO_TEMP_K:
|
|
67
|
+
raise CryoStreamError("Cryostream temperature is too high, not starting UDC")
|
|
68
|
+
if cryostream_pressure > CONST.HARDWARE.MAX_CRYO_PRESSURE_BAR:
|
|
69
|
+
raise CryoStreamError("Cryostream back pressure is too high, not starting UDC")
|
|
70
|
+
|
|
71
|
+
yield from _verify_no_sample_present(devices.robot)
|
|
72
|
+
|
|
73
|
+
# Close fast shutter before opening hutch shutter
|
|
74
|
+
yield from bps.abs_set(devices.sample_shutter, ZebraShutterState.CLOSE, wait=True)
|
|
75
|
+
|
|
76
|
+
commissioning_mode_enabled = yield from bps.rd(devices.baton.commissioning)
|
|
77
|
+
|
|
78
|
+
if commissioning_mode_enabled:
|
|
79
|
+
LOGGER.warning("Not opening hutch shutter - commissioning mode is enabled.")
|
|
80
|
+
else:
|
|
81
|
+
yield from bps.abs_set(
|
|
82
|
+
devices.hutch_shutter, ShutterDemand.OPEN, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
yield from bps.abs_set(devices.scintillator.selected_pos, ScinInOut.OUT, wait=True)
|
|
86
|
+
|
|
87
|
+
yield from bps.abs_set(
|
|
88
|
+
devices.fluorescence_det_motion.pos,
|
|
89
|
+
FlouInOut.OUT,
|
|
90
|
+
group=_GROUP_PRE_BEAMSTOP_CHECK,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
yield from bps.abs_set(
|
|
94
|
+
devices.collimation_table.inboard_y,
|
|
95
|
+
0,
|
|
96
|
+
group=_GROUP_PRE_BEAMSTOP_CHECK,
|
|
97
|
+
)
|
|
98
|
+
yield from bps.abs_set(
|
|
99
|
+
devices.collimation_table.outboard_y, 0, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
100
|
+
)
|
|
101
|
+
yield from bps.abs_set(
|
|
102
|
+
devices.collimation_table.upstream_y, 0, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
103
|
+
)
|
|
104
|
+
yield from bps.abs_set(
|
|
105
|
+
devices.collimation_table.upstream_x, 0, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
106
|
+
)
|
|
107
|
+
yield from bps.abs_set(
|
|
108
|
+
devices.collimation_table.downstream_x, 0, group=_GROUP_PRE_BEAMSTOP_CHECK
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Wait for all of the above to complete
|
|
112
|
+
yield from bps.wait(group=_GROUP_PRE_BEAMSTOP_CHECK, timeout=0.1)
|
|
113
|
+
|
|
114
|
+
feature_flags: HyperionFeatureSettings = (
|
|
115
|
+
get_hyperion_config_client().get_feature_flags()
|
|
116
|
+
)
|
|
117
|
+
if feature_flags.BEAMSTOP_DIODE_CHECK:
|
|
118
|
+
beamline_parameters = get_beamline_parameters()
|
|
119
|
+
config_client = get_hyperion_config_client()
|
|
120
|
+
features_settings: HyperionFeatureSettings = config_client.get_feature_flags()
|
|
121
|
+
detector_min_z = features_settings.DETECTOR_DISTANCE_LIMIT_MIN_MM
|
|
122
|
+
detector_max_z = features_settings.DETECTOR_DISTANCE_LIMIT_MAX_MM
|
|
123
|
+
yield from move_beamstop_in_and_verify_using_diode(
|
|
124
|
+
devices, beamline_parameters, detector_min_z, detector_max_z
|
|
125
|
+
)
|
|
126
|
+
else:
|
|
127
|
+
yield from bps.abs_set(
|
|
128
|
+
devices.beamstop.selected_pos, BeamstopPositions.DATA_COLLECTION, wait=True
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
yield from bps.abs_set(
|
|
132
|
+
devices.aperture_scatterguard.selected_aperture,
|
|
133
|
+
ApertureValue.SMALL,
|
|
134
|
+
group=_GROUP_POST_BEAMSTOP_CHECK,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
yield from bps.abs_set(
|
|
138
|
+
devices.cryojet.coarse, CryoInOut.IN, group=_GROUP_POST_BEAMSTOP_CHECK
|
|
139
|
+
)
|
|
140
|
+
yield from bps.abs_set(
|
|
141
|
+
devices.cryojet.fine, CryoInOut.IN, group=_GROUP_POST_BEAMSTOP_CHECK
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
yield from bps.wait(_GROUP_POST_BEAMSTOP_CHECK)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _verify_correct_cryostream_selected(
|
|
148
|
+
cryostream_gantry: CryoStreamGantry,
|
|
149
|
+
) -> MsgGenerator:
|
|
150
|
+
cryostream_selection = yield from bps.rd(cryostream_gantry.cryostream_selector)
|
|
151
|
+
cryostream_selected = yield from bps.rd(cryostream_gantry.cryostream_selected)
|
|
152
|
+
if cryostream_selection != CryoStreamSelection.CRYOJET or cryostream_selected != 1:
|
|
153
|
+
raise CryoStreamError(
|
|
154
|
+
f"Cryostream is not selected for use, control PV selection = {cryostream_selection}, "
|
|
155
|
+
f"current status {cryostream_selected}"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _verify_no_sample_present(robot: BartRobot):
|
|
160
|
+
pin_mounted = yield from bps.rd(robot.gonio_pin_sensor)
|
|
161
|
+
|
|
162
|
+
if pin_mounted != PinMounted.NO_PIN_MOUNTED:
|
|
163
|
+
# Cannot unload this sample because we do not know the correct visit for it
|
|
164
|
+
raise UnexpectedSampleError(
|
|
165
|
+
"An unexpected sample was found, please unload the sample manually."
|
|
166
|
+
)
|
|
@@ -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}
|
|
@@ -2,6 +2,8 @@ import logging
|
|
|
2
2
|
from collections.abc import Callable, Sequence
|
|
3
3
|
from threading import Thread
|
|
4
4
|
from time import sleep # noqa
|
|
5
|
+
from urllib import request
|
|
6
|
+
from urllib.error import URLError
|
|
5
7
|
|
|
6
8
|
from bluesky.callbacks import CallbackBase
|
|
7
9
|
from bluesky.callbacks.zmq import Proxy, RemoteDispatcher
|
|
@@ -51,14 +53,17 @@ from mx_bluesky.hyperion.external_interaction.callbacks.snapshot_callback import
|
|
|
51
53
|
BeamDrawingCallback,
|
|
52
54
|
)
|
|
53
55
|
from mx_bluesky.hyperion.parameters.cli import parse_callback_dev_mode_arg
|
|
54
|
-
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
56
|
+
from mx_bluesky.hyperion.parameters.constants import CONST, HyperionConstants
|
|
55
57
|
from mx_bluesky.hyperion.parameters.gridscan import (
|
|
56
58
|
GridCommonWithHyperionDetectorParams,
|
|
57
59
|
HyperionSpecifiedThreeDGridScan,
|
|
58
60
|
)
|
|
59
61
|
|
|
62
|
+
PING_TIMEOUT_S = 1
|
|
63
|
+
|
|
60
64
|
LIVENESS_POLL_SECONDS = 1
|
|
61
65
|
ERROR_LOG_BUFFER_LINES = 5000
|
|
66
|
+
HYPERION_PING_INTERVAL_S = 19
|
|
62
67
|
|
|
63
68
|
|
|
64
69
|
def create_gridscan_callbacks() -> tuple[
|
|
@@ -128,21 +133,6 @@ def setup_logging(dev_mode: bool):
|
|
|
128
133
|
log_debug("nexgen logger added to nexus logger")
|
|
129
134
|
|
|
130
135
|
|
|
131
|
-
def setup_threads():
|
|
132
|
-
proxy = Proxy(*CONST.CALLBACK_0MQ_PROXY_PORTS)
|
|
133
|
-
dispatcher = RemoteDispatcher(f"localhost:{CONST.CALLBACK_0MQ_PROXY_PORTS[1]}")
|
|
134
|
-
log_debug("Created proxy and dispatcher objects")
|
|
135
|
-
|
|
136
|
-
def start_proxy():
|
|
137
|
-
proxy.start()
|
|
138
|
-
|
|
139
|
-
def start_dispatcher(callbacks: list[Callable]):
|
|
140
|
-
[dispatcher.subscribe(cb) for cb in callbacks]
|
|
141
|
-
dispatcher.start()
|
|
142
|
-
|
|
143
|
-
return proxy, dispatcher, start_proxy, start_dispatcher
|
|
144
|
-
|
|
145
|
-
|
|
146
136
|
def log_info(msg, *args, **kwargs):
|
|
147
137
|
ISPYB_ZOCALO_CALLBACK_LOGGER.info(msg, *args, **kwargs)
|
|
148
138
|
NEXUS_LOGGER.info(msg, *args, **kwargs)
|
|
@@ -175,20 +165,57 @@ class HyperionCallbackRunner:
|
|
|
175
165
|
set_alerting_service(LoggingAlertService(CONST.GRAYLOG_STREAM_ID))
|
|
176
166
|
|
|
177
167
|
self.callbacks = setup_callbacks()
|
|
178
|
-
self.proxy, self.dispatcher, start_proxy, start_dispatcher = setup_threads()
|
|
179
|
-
log_info("Created 0MQ proxy and local RemoteDispatcher.")
|
|
180
168
|
|
|
181
|
-
self.
|
|
169
|
+
self.proxy = Proxy(*CONST.CALLBACK_0MQ_PROXY_PORTS)
|
|
170
|
+
self.proxy_thread = Thread(
|
|
171
|
+
target=self.proxy.start, daemon=True, name="0MQ Proxy"
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
self.dispatcher = RemoteDispatcher(
|
|
175
|
+
f"localhost:{CONST.CALLBACK_0MQ_PROXY_PORTS[1]}"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def start_dispatcher(callbacks: list[Callable]):
|
|
179
|
+
for cb in callbacks:
|
|
180
|
+
self.dispatcher.subscribe(cb)
|
|
181
|
+
self.dispatcher.start()
|
|
182
|
+
|
|
182
183
|
self.dispatcher_thread = Thread(
|
|
183
|
-
target=start_dispatcher,
|
|
184
|
+
target=start_dispatcher,
|
|
185
|
+
args=[self.callbacks],
|
|
186
|
+
daemon=True,
|
|
187
|
+
name="0MQ Dispatcher",
|
|
184
188
|
)
|
|
185
189
|
|
|
190
|
+
self.watchdog_thread = Thread(target=run_watchdog, daemon=True, name="Watchdog")
|
|
191
|
+
log_info("Created 0MQ proxy and local RemoteDispatcher.")
|
|
192
|
+
|
|
186
193
|
def start(self):
|
|
187
194
|
log_info(f"Launching threads, with callbacks: {self.callbacks}")
|
|
188
195
|
self.proxy_thread.start()
|
|
189
196
|
self.dispatcher_thread.start()
|
|
197
|
+
self.watchdog_thread.start()
|
|
190
198
|
log_info("Proxy and dispatcher thread launched.")
|
|
191
|
-
wait_for_threads_forever(
|
|
199
|
+
wait_for_threads_forever(
|
|
200
|
+
[self.proxy_thread, self.dispatcher_thread, self.watchdog_thread]
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def run_watchdog():
|
|
205
|
+
log_info("Hyperion watchdog keepalive running")
|
|
206
|
+
while True:
|
|
207
|
+
try:
|
|
208
|
+
with request.urlopen(
|
|
209
|
+
f"http://localhost:{HyperionConstants.HYPERION_PORT}/callbackPing",
|
|
210
|
+
timeout=PING_TIMEOUT_S,
|
|
211
|
+
) as response:
|
|
212
|
+
if response.status != 200:
|
|
213
|
+
log_debug(
|
|
214
|
+
f"Unable to ping Hyperion liveness endpoint, status {response.status}"
|
|
215
|
+
)
|
|
216
|
+
except URLError as e:
|
|
217
|
+
log_debug("Unable to ping Hyperion liveness endpoint", exc_info=e)
|
|
218
|
+
sleep(HYPERION_PING_INTERVAL_S)
|
|
192
219
|
|
|
193
220
|
|
|
194
221
|
def main(dev_mode=False) -> None:
|
|
@@ -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,
|