mx-bluesky 1.4.9__py3-none-any.whl → 1.5.1__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/i24/serial/__init__.py +4 -2
- mx_bluesky/beamlines/i24/serial/blueapi_config.yaml +4 -0
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +8 -8
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +36 -4
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +6 -5
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +2 -2
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +5 -5
- mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +79 -10
- mx_bluesky/common/device_setup_plans/manipulate_sample.py +4 -1
- mx_bluesky/common/device_setup_plans/robot_load_unload.py +123 -0
- mx_bluesky/common/device_setup_plans/utils.py +49 -0
- mx_bluesky/common/{plans → experiment_plans}/common_flyscan_xray_centre_plan.py +12 -19
- mx_bluesky/{hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py → common/experiment_plans/common_grid_detect_then_xray_centre_plan.py} +108 -136
- mx_bluesky/common/{plans → experiment_plans}/inner_plans/do_fgs.py +1 -1
- mx_bluesky/common/experiment_plans/oav_grid_detection_plan.py +5 -13
- mx_bluesky/{hyperion → common}/experiment_plans/oav_snapshot_plan.py +5 -2
- mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +26 -24
- mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +0 -1
- mx_bluesky/common/external_interaction/nexus/write_nexus.py +2 -2
- mx_bluesky/common/parameters/components.py +8 -3
- mx_bluesky/common/parameters/constants.py +4 -3
- mx_bluesky/common/parameters/device_composites.py +65 -0
- mx_bluesky/common/utils/__init__.py +0 -0
- mx_bluesky/common/xrc_result.py +25 -2
- mx_bluesky/hyperion/device_setup_plans/utils.py +0 -48
- mx_bluesky/hyperion/experiment_plans/__init__.py +3 -3
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +3 -3
- mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +46 -41
- mx_bluesky/hyperion/experiment_plans/hyperion_grid_detect_then_xray_centre_plan.py +60 -0
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +26 -8
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +26 -15
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +21 -75
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +10 -8
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +20 -15
- mx_bluesky/hyperion/external_interaction/agamemnon.py +4 -4
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/{robot_load → robot_actions}/ispyb_callback.py +28 -19
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py +3 -0
- mx_bluesky/hyperion/external_interaction/config_server.py +0 -11
- mx_bluesky/hyperion/parameters/constants.py +1 -6
- mx_bluesky/hyperion/parameters/device_composites.py +5 -27
- mx_bluesky/hyperion/parameters/gridscan.py +2 -6
- mx_bluesky/hyperion/parameters/load_centre_collect.py +15 -0
- mx_bluesky/hyperion/parameters/rotation.py +7 -3
- {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/METADATA +5 -4
- {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/RECORD +56 -52
- mx_bluesky/hyperion/utils/validation.py +0 -196
- /mx_bluesky/common/{plans → experiment_plans}/__init__.py +0 -0
- /mx_bluesky/common/{plans → experiment_plans}/inner_plans/__init__ .py +0 -0
- /mx_bluesky/common/{plans → experiment_plans}/read_hardware.py +0 -0
- /mx_bluesky/common/{plans → experiment_plans}/write_sample_status.py +0 -0
- {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/WHEEL +0 -0
- {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/licenses/LICENSE +0 -0
- {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/top_level.txt +0 -0
|
@@ -7,35 +7,32 @@ from functools import partial
|
|
|
7
7
|
import bluesky.plan_stubs as bps
|
|
8
8
|
import bluesky.preprocessors as bpp
|
|
9
9
|
import numpy as np
|
|
10
|
-
import pydantic
|
|
11
10
|
from bluesky.protocols import Readable
|
|
12
11
|
from bluesky.utils import MsgGenerator
|
|
13
|
-
from dodal.devices.eiger import EigerDetector
|
|
14
12
|
from dodal.devices.fast_grid_scan import (
|
|
15
13
|
FastGridScanCommon,
|
|
16
14
|
)
|
|
17
|
-
from dodal.devices.smargon import Smargon
|
|
18
|
-
from dodal.devices.synchrotron import Synchrotron
|
|
19
15
|
from dodal.devices.zocalo import ZocaloResults
|
|
20
16
|
from dodal.devices.zocalo.zocalo_results import (
|
|
21
17
|
XrcResult,
|
|
22
18
|
get_full_processing_results,
|
|
23
19
|
)
|
|
24
20
|
|
|
21
|
+
from mx_bluesky.common.experiment_plans.inner_plans.do_fgs import (
|
|
22
|
+
ZOCALO_STAGE_GROUP,
|
|
23
|
+
kickoff_and_complete_gridscan,
|
|
24
|
+
)
|
|
25
|
+
from mx_bluesky.common.experiment_plans.read_hardware import (
|
|
26
|
+
read_hardware_plan,
|
|
27
|
+
)
|
|
25
28
|
from mx_bluesky.common.parameters.constants import (
|
|
26
29
|
DocDescriptorNames,
|
|
27
30
|
GridscanParamConstants,
|
|
28
31
|
PlanGroupCheckpointConstants,
|
|
29
32
|
PlanNameConstants,
|
|
30
33
|
)
|
|
34
|
+
from mx_bluesky.common.parameters.device_composites import FlyScanEssentialDevices
|
|
31
35
|
from mx_bluesky.common.parameters.gridscan import SpecifiedThreeDGridScan
|
|
32
|
-
from mx_bluesky.common.plans.inner_plans.do_fgs import (
|
|
33
|
-
ZOCALO_STAGE_GROUP,
|
|
34
|
-
kickoff_and_complete_gridscan,
|
|
35
|
-
)
|
|
36
|
-
from mx_bluesky.common.plans.read_hardware import (
|
|
37
|
-
read_hardware_plan,
|
|
38
|
-
)
|
|
39
36
|
from mx_bluesky.common.utils.exceptions import (
|
|
40
37
|
CrystalNotFoundException,
|
|
41
38
|
SampleException,
|
|
@@ -45,14 +42,6 @@ from mx_bluesky.common.utils.tracing import TRACER
|
|
|
45
42
|
from mx_bluesky.common.xrc_result import XRayCentreResult
|
|
46
43
|
|
|
47
44
|
|
|
48
|
-
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
49
|
-
class FlyScanEssentialDevices:
|
|
50
|
-
eiger: EigerDetector
|
|
51
|
-
synchrotron: Synchrotron
|
|
52
|
-
zocalo: ZocaloResults
|
|
53
|
-
smargon: Smargon
|
|
54
|
-
|
|
55
|
-
|
|
56
45
|
@dataclasses.dataclass
|
|
57
46
|
class BeamlineSpecificFGSFeatures:
|
|
58
47
|
setup_trigger_plan: Callable[..., MsgGenerator]
|
|
@@ -251,6 +240,9 @@ def run_gridscan(
|
|
|
251
240
|
parameters.scan_indices,
|
|
252
241
|
plan_during_collection=beamline_specific.read_during_collection_plan,
|
|
253
242
|
)
|
|
243
|
+
|
|
244
|
+
# GDA's gridscans requires Z steps to be at 0, so make sure we leave this device
|
|
245
|
+
# in a GDA-happy state.
|
|
254
246
|
yield from bps.abs_set(beamline_specific.fgs_motors.z_steps, 0, wait=False)
|
|
255
247
|
|
|
256
248
|
|
|
@@ -296,6 +288,7 @@ def _xrc_result_in_boxes_to_result_in_mm(
|
|
|
296
288
|
),
|
|
297
289
|
max_count=xrc_result["max_count"],
|
|
298
290
|
total_count=xrc_result["total_count"],
|
|
291
|
+
sample_id=xrc_result["sample_id"],
|
|
299
292
|
)
|
|
300
293
|
|
|
301
294
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import Protocol, TypeVar
|
|
4
5
|
|
|
5
|
-
from blueapi.core import BlueskyContext
|
|
6
6
|
from bluesky import plan_stubs as bps
|
|
7
7
|
from bluesky import preprocessors as bpp
|
|
8
8
|
from bluesky.preprocessors import subs_decorator
|
|
@@ -10,20 +10,27 @@ from bluesky.utils import MsgGenerator
|
|
|
10
10
|
from dodal.devices.backlight import BacklightPosition
|
|
11
11
|
from dodal.devices.eiger import EigerDetector
|
|
12
12
|
from dodal.devices.oav.oav_parameters import OAVParameters
|
|
13
|
-
from dodal.plans.preprocessors.verify_undulator_gap import (
|
|
14
|
-
verify_undulator_gap_before_run_decorator,
|
|
15
|
-
)
|
|
16
13
|
|
|
17
14
|
from mx_bluesky.common.device_setup_plans.manipulate_sample import (
|
|
18
15
|
move_aperture_if_required,
|
|
19
16
|
)
|
|
17
|
+
from mx_bluesky.common.device_setup_plans.utils import (
|
|
18
|
+
start_preparing_data_collection_then_do_plan,
|
|
19
|
+
)
|
|
20
20
|
from mx_bluesky.common.experiment_plans.change_aperture_then_move_plan import (
|
|
21
21
|
change_aperture_then_move_to_xtal,
|
|
22
22
|
)
|
|
23
|
+
from mx_bluesky.common.experiment_plans.common_flyscan_xray_centre_plan import (
|
|
24
|
+
BeamlineSpecificFGSFeatures,
|
|
25
|
+
common_flyscan_xray_centre,
|
|
26
|
+
)
|
|
23
27
|
from mx_bluesky.common.experiment_plans.oav_grid_detection_plan import (
|
|
24
28
|
OavGridDetectionComposite,
|
|
25
29
|
grid_detection_plan,
|
|
26
30
|
)
|
|
31
|
+
from mx_bluesky.common.experiment_plans.oav_snapshot_plan import (
|
|
32
|
+
setup_beamline_for_OAV,
|
|
33
|
+
)
|
|
27
34
|
from mx_bluesky.common.external_interaction.callbacks.common.grid_detection_callback import (
|
|
28
35
|
GridDetectionCallback,
|
|
29
36
|
GridParamUpdate,
|
|
@@ -31,62 +38,97 @@ from mx_bluesky.common.external_interaction.callbacks.common.grid_detection_call
|
|
|
31
38
|
from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
|
|
32
39
|
ispyb_activation_wrapper,
|
|
33
40
|
)
|
|
34
|
-
from mx_bluesky.common.parameters.constants import
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
BeamlineSpecificFGSFeatures,
|
|
38
|
-
common_flyscan_xray_centre,
|
|
41
|
+
from mx_bluesky.common.parameters.constants import (
|
|
42
|
+
OavConstants,
|
|
43
|
+
PlanGroupCheckpointConstants,
|
|
39
44
|
)
|
|
40
|
-
from mx_bluesky.common.
|
|
41
|
-
|
|
45
|
+
from mx_bluesky.common.parameters.device_composites import (
|
|
46
|
+
FlyScanEssentialDevices,
|
|
47
|
+
GridDetectThenXRayCentreComposite,
|
|
42
48
|
)
|
|
43
|
-
from mx_bluesky.common.
|
|
49
|
+
from mx_bluesky.common.parameters.gridscan import GridCommon, SpecifiedThreeDGridScan
|
|
44
50
|
from mx_bluesky.common.utils.log import LOGGER
|
|
45
51
|
from mx_bluesky.common.xrc_result import XRayCentreEventHandler
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
from mx_bluesky.hyperion.experiment_plans.hyperion_flyscan_xray_centre_plan import (
|
|
50
|
-
construct_hyperion_specific_features,
|
|
51
|
-
)
|
|
52
|
-
from mx_bluesky.hyperion.experiment_plans.oav_snapshot_plan import (
|
|
53
|
-
setup_beamline_for_OAV,
|
|
54
|
-
)
|
|
55
|
-
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
56
|
-
from mx_bluesky.hyperion.parameters.device_composites import (
|
|
57
|
-
GridDetectThenXRayCentreComposite,
|
|
58
|
-
HyperionFlyScanXRayCentreComposite,
|
|
52
|
+
|
|
53
|
+
TFlyScanEssentialDevices = TypeVar(
|
|
54
|
+
"TFlyScanEssentialDevices", bound=FlyScanEssentialDevices, contravariant=True
|
|
59
55
|
)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
HyperionSpecifiedThreeDGridScan,
|
|
56
|
+
TSpecifiedThreeDGridScan = TypeVar(
|
|
57
|
+
"TSpecifiedThreeDGridScan", bound=SpecifiedThreeDGridScan, contravariant=True
|
|
63
58
|
)
|
|
64
59
|
|
|
65
60
|
|
|
66
|
-
def
|
|
67
|
-
|
|
61
|
+
def grid_detect_then_xray_centre(
|
|
62
|
+
composite: GridDetectThenXRayCentreComposite,
|
|
63
|
+
parameters: GridCommon,
|
|
64
|
+
xrc_params_type: type[SpecifiedThreeDGridScan],
|
|
65
|
+
construct_beamline_specific: ConstructBeamlineSpecificFeatures,
|
|
66
|
+
oav_config: str = OavConstants.OAV_CONFIG_JSON,
|
|
67
|
+
) -> MsgGenerator:
|
|
68
|
+
"""
|
|
69
|
+
A plan which combines the collection of snapshots from the OAV and the determination
|
|
70
|
+
of the grid dimensions to use for the following grid scan.
|
|
71
|
+
"""
|
|
68
72
|
|
|
73
|
+
eiger: EigerDetector = composite.eiger
|
|
69
74
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
eiger.set_detector_parameters(parameters.detector_params)
|
|
76
|
+
|
|
77
|
+
oav_params = OAVParameters("xrayCentring", oav_config)
|
|
78
|
+
|
|
79
|
+
flyscan_event_handler = XRayCentreEventHandler()
|
|
80
|
+
|
|
81
|
+
@subs_decorator(flyscan_event_handler)
|
|
82
|
+
def plan_to_perform():
|
|
83
|
+
yield from ispyb_activation_wrapper(
|
|
84
|
+
detect_grid_and_do_gridscan(
|
|
85
|
+
composite,
|
|
86
|
+
parameters,
|
|
87
|
+
oav_params,
|
|
88
|
+
xrc_params_type,
|
|
89
|
+
construct_beamline_specific,
|
|
90
|
+
),
|
|
91
|
+
parameters,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
yield from start_preparing_data_collection_then_do_plan(
|
|
95
|
+
composite.beamstop,
|
|
96
|
+
eiger,
|
|
97
|
+
composite.detector_motion,
|
|
98
|
+
parameters.detector_params.detector_distance,
|
|
99
|
+
plan_to_perform(),
|
|
100
|
+
group=PlanGroupCheckpointConstants.GRID_READY_FOR_DC,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
assert flyscan_event_handler.xray_centre_results, (
|
|
104
|
+
"Flyscan result event not received or no crystal found and exception not raised"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
yield from change_aperture_then_move_to_xtal(
|
|
108
|
+
flyscan_event_handler.xray_centre_results[0],
|
|
109
|
+
composite.smargon,
|
|
110
|
+
composite.aperture_scatterguard,
|
|
111
|
+
)
|
|
79
112
|
|
|
80
113
|
|
|
81
114
|
def detect_grid_and_do_gridscan(
|
|
82
115
|
composite: GridDetectThenXRayCentreComposite,
|
|
83
116
|
parameters: GridCommon,
|
|
84
117
|
oav_params: OAVParameters,
|
|
118
|
+
xrc_params_type: type[SpecifiedThreeDGridScan],
|
|
119
|
+
construct_beamline_specific: ConstructBeamlineSpecificFeatures,
|
|
85
120
|
):
|
|
86
121
|
snapshot_template = f"{parameters.detector_params.prefix}_{parameters.detector_params.run_number}_{{angle}}"
|
|
87
122
|
|
|
88
123
|
grid_params_callback = GridDetectionCallback()
|
|
89
124
|
|
|
125
|
+
yield from setup_beamline_for_OAV(
|
|
126
|
+
composite.smargon,
|
|
127
|
+
composite.backlight,
|
|
128
|
+
composite.aperture_scatterguard,
|
|
129
|
+
wait=True,
|
|
130
|
+
)
|
|
131
|
+
|
|
90
132
|
@bpp.subs_decorator([grid_params_callback])
|
|
91
133
|
def run_grid_detection_plan(
|
|
92
134
|
oav_params,
|
|
@@ -109,19 +151,12 @@ def detect_grid_and_do_gridscan(
|
|
|
109
151
|
parameters.box_size_um,
|
|
110
152
|
)
|
|
111
153
|
|
|
112
|
-
yield from setup_beamline_for_OAV(
|
|
113
|
-
composite.smargon,
|
|
114
|
-
composite.backlight,
|
|
115
|
-
composite.aperture_scatterguard,
|
|
116
|
-
wait=True,
|
|
117
|
-
)
|
|
118
|
-
|
|
119
154
|
if parameters.selected_aperture:
|
|
120
155
|
# Start moving the aperture/scatterguard into position without moving it in
|
|
121
156
|
yield from bps.prepare(
|
|
122
157
|
composite.aperture_scatterguard,
|
|
123
158
|
parameters.selected_aperture,
|
|
124
|
-
group=
|
|
159
|
+
group=PlanGroupCheckpointConstants.PREPARE_APERTURE,
|
|
125
160
|
)
|
|
126
161
|
|
|
127
162
|
yield from run_grid_detection_plan(
|
|
@@ -131,105 +166,42 @@ def detect_grid_and_do_gridscan(
|
|
|
131
166
|
)
|
|
132
167
|
|
|
133
168
|
yield from bps.abs_set(
|
|
134
|
-
composite.backlight,
|
|
169
|
+
composite.backlight,
|
|
170
|
+
BacklightPosition.OUT,
|
|
171
|
+
group=PlanGroupCheckpointConstants.GRID_READY_FOR_DC,
|
|
135
172
|
)
|
|
136
173
|
|
|
137
|
-
yield from bps.wait(
|
|
174
|
+
yield from bps.wait(PlanGroupCheckpointConstants.PREPARE_APERTURE)
|
|
138
175
|
yield from move_aperture_if_required(
|
|
139
176
|
composite.aperture_scatterguard,
|
|
140
177
|
parameters.selected_aperture,
|
|
141
|
-
group=
|
|
178
|
+
group=PlanGroupCheckpointConstants.GRID_READY_FOR_DC,
|
|
142
179
|
)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
aperture_scatterguard=composite.aperture_scatterguard,
|
|
146
|
-
attenuator=composite.attenuator,
|
|
147
|
-
backlight=composite.backlight,
|
|
148
|
-
eiger=composite.eiger,
|
|
149
|
-
panda_fast_grid_scan=composite.panda_fast_grid_scan,
|
|
150
|
-
flux=composite.flux,
|
|
151
|
-
s4_slit_gaps=composite.s4_slit_gaps,
|
|
152
|
-
smargon=composite.smargon,
|
|
153
|
-
undulator=composite.undulator,
|
|
154
|
-
synchrotron=composite.synchrotron,
|
|
155
|
-
xbpm_feedback=composite.xbpm_feedback,
|
|
156
|
-
zebra=composite.zebra,
|
|
157
|
-
zocalo=composite.zocalo,
|
|
158
|
-
panda=composite.panda,
|
|
159
|
-
zebra_fast_grid_scan=composite.zebra_fast_grid_scan,
|
|
160
|
-
dcm=composite.dcm,
|
|
161
|
-
robot=composite.robot,
|
|
162
|
-
sample_shutter=composite.sample_shutter,
|
|
180
|
+
xrc_params = create_parameters_for_flyscan_xray_centre(
|
|
181
|
+
parameters, grid_params_callback.get_grid_parameters(), xrc_params_type
|
|
163
182
|
)
|
|
183
|
+
beamline_specific = construct_beamline_specific(composite, xrc_params)
|
|
164
184
|
|
|
165
|
-
|
|
166
|
-
parameters, grid_params_callback.get_grid_parameters()
|
|
167
|
-
)
|
|
185
|
+
yield from common_flyscan_xray_centre(composite, xrc_params, beamline_specific)
|
|
168
186
|
|
|
169
|
-
beamline_specific = construct_hyperion_specific_features(xrc_composite, params)
|
|
170
187
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
def _gridscan_with_undulator_checks(
|
|
175
|
-
composite: HyperionFlyScanXRayCentreComposite,
|
|
176
|
-
params: HyperionSpecifiedThreeDGridScan,
|
|
177
|
-
beamline_specific: BeamlineSpecificFGSFeatures,
|
|
188
|
+
class ConstructBeamlineSpecificFeatures(
|
|
189
|
+
Protocol[TFlyScanEssentialDevices, TSpecifiedThreeDGridScan]
|
|
178
190
|
):
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
yield from common_flyscan_xray_centre(composite, params, beamline_specific)
|
|
185
|
-
|
|
186
|
-
yield from _inner()
|
|
191
|
+
def __call__(
|
|
192
|
+
self,
|
|
193
|
+
xrc_composite: TFlyScanEssentialDevices,
|
|
194
|
+
xrc_parameters: TSpecifiedThreeDGridScan,
|
|
195
|
+
) -> BeamlineSpecificFGSFeatures: ...
|
|
187
196
|
|
|
188
197
|
|
|
189
|
-
def
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
) ->
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
""
|
|
198
|
-
|
|
199
|
-
eiger: EigerDetector = composite.eiger
|
|
200
|
-
|
|
201
|
-
eiger.set_detector_parameters(parameters.detector_params)
|
|
202
|
-
|
|
203
|
-
oav_params = OAVParameters("xrayCentring", oav_config)
|
|
204
|
-
|
|
205
|
-
flyscan_event_handler = XRayCentreEventHandler()
|
|
206
|
-
|
|
207
|
-
@subs_decorator(flyscan_event_handler)
|
|
208
|
-
def plan_to_perform():
|
|
209
|
-
yield from ispyb_activation_wrapper(
|
|
210
|
-
detect_grid_and_do_gridscan(
|
|
211
|
-
composite,
|
|
212
|
-
parameters,
|
|
213
|
-
oav_params,
|
|
214
|
-
),
|
|
215
|
-
parameters,
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
yield from start_preparing_data_collection_then_do_plan(
|
|
219
|
-
composite.beamstop,
|
|
220
|
-
eiger,
|
|
221
|
-
composite.detector_motion,
|
|
222
|
-
parameters.detector_params.detector_distance,
|
|
223
|
-
plan_to_perform(),
|
|
224
|
-
group=CONST.WAIT.GRID_READY_FOR_DC,
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
assert flyscan_event_handler.xray_centre_results, (
|
|
228
|
-
"Flyscan result event not received or no crystal found and exception not raised"
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
yield from change_aperture_then_move_to_xtal(
|
|
232
|
-
flyscan_event_handler.xray_centre_results[0],
|
|
233
|
-
composite.smargon,
|
|
234
|
-
composite.aperture_scatterguard,
|
|
235
|
-
)
|
|
198
|
+
def create_parameters_for_flyscan_xray_centre(
|
|
199
|
+
parameters: GridCommon,
|
|
200
|
+
grid_parameters: GridParamUpdate,
|
|
201
|
+
xrc_params_type: type[SpecifiedThreeDGridScan],
|
|
202
|
+
) -> SpecifiedThreeDGridScan:
|
|
203
|
+
params_json = parameters.model_dump()
|
|
204
|
+
params_json.update(grid_parameters)
|
|
205
|
+
flyscan_xray_centre_parameters = xrc_params_type(**params_json)
|
|
206
|
+
LOGGER.info(f"Parameters for FGS: {flyscan_xray_centre_parameters}")
|
|
207
|
+
return flyscan_xray_centre_parameters
|
|
@@ -14,10 +14,10 @@ from dodal.log import LOGGER
|
|
|
14
14
|
from dodal.plan_stubs.check_topup import check_topup_and_wait_if_necessary
|
|
15
15
|
from scanspec.core import AxesPoints, Axis
|
|
16
16
|
|
|
17
|
+
from mx_bluesky.common.experiment_plans.read_hardware import read_hardware_for_zocalo
|
|
17
18
|
from mx_bluesky.common.parameters.constants import (
|
|
18
19
|
PlanNameConstants,
|
|
19
20
|
)
|
|
20
|
-
from mx_bluesky.common.plans.read_hardware import read_hardware_for_zocalo
|
|
21
21
|
from mx_bluesky.common.utils.tracing import TRACER
|
|
22
22
|
|
|
23
23
|
|
|
@@ -5,9 +5,7 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
|
|
6
6
|
import bluesky.plan_stubs as bps
|
|
7
7
|
import numpy as np
|
|
8
|
-
import pydantic
|
|
9
8
|
from blueapi.core import BlueskyContext
|
|
10
|
-
from dodal.devices.backlight import Backlight
|
|
11
9
|
from dodal.devices.oav.oav_detector import OAV
|
|
12
10
|
from dodal.devices.oav.pin_image_recognition import PinTipDetection
|
|
13
11
|
from dodal.devices.oav.pin_image_recognition.utils import NONE_VALUE
|
|
@@ -17,7 +15,11 @@ from dodal.devices.smargon import Smargon
|
|
|
17
15
|
from mx_bluesky.common.device_setup_plans.setup_oav import (
|
|
18
16
|
pre_centring_setup_oav,
|
|
19
17
|
)
|
|
20
|
-
from mx_bluesky.common.parameters.constants import
|
|
18
|
+
from mx_bluesky.common.parameters.constants import (
|
|
19
|
+
DocDescriptorNames,
|
|
20
|
+
HardwareConstants,
|
|
21
|
+
)
|
|
22
|
+
from mx_bluesky.common.parameters.device_composites import OavGridDetectionComposite
|
|
21
23
|
from mx_bluesky.common.utils.context import device_composite_from_context
|
|
22
24
|
from mx_bluesky.common.utils.exceptions import catch_exception_and_warn
|
|
23
25
|
from mx_bluesky.common.utils.log import LOGGER
|
|
@@ -26,16 +28,6 @@ if TYPE_CHECKING:
|
|
|
26
28
|
from dodal.devices.oav.oav_parameters import OAVParameters
|
|
27
29
|
|
|
28
30
|
|
|
29
|
-
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
30
|
-
class OavGridDetectionComposite:
|
|
31
|
-
"""All devices which are directly or indirectly required by this plan"""
|
|
32
|
-
|
|
33
|
-
backlight: Backlight
|
|
34
|
-
oav: OAV
|
|
35
|
-
smargon: Smargon
|
|
36
|
-
pin_tip_detection: PinTipDetection
|
|
37
|
-
|
|
38
|
-
|
|
39
31
|
def create_devices(context: BlueskyContext) -> OavGridDetectionComposite:
|
|
40
32
|
return device_composite_from_context(context, OavGridDetectionComposite)
|
|
41
33
|
|
|
@@ -11,7 +11,10 @@ from dodal.devices.smargon import Smargon
|
|
|
11
11
|
|
|
12
12
|
from mx_bluesky.common.device_setup_plans.setup_oav import setup_general_oav_params
|
|
13
13
|
from mx_bluesky.common.parameters.components import WithSnapshot
|
|
14
|
-
from mx_bluesky.
|
|
14
|
+
from mx_bluesky.common.parameters.constants import (
|
|
15
|
+
DocDescriptorNames,
|
|
16
|
+
PlanGroupCheckpointConstants,
|
|
17
|
+
)
|
|
15
18
|
|
|
16
19
|
OAV_SNAPSHOT_SETUP_SHOT = "oav_snapshot_setup_shot"
|
|
17
20
|
OAV_SNAPSHOT_GROUP = "oav_snapshot_group"
|
|
@@ -28,7 +31,7 @@ def setup_beamline_for_OAV(
|
|
|
28
31
|
smargon: Smargon,
|
|
29
32
|
backlight: Backlight,
|
|
30
33
|
aperture_scatterguard: ApertureScatterguard,
|
|
31
|
-
group=
|
|
34
|
+
group=PlanGroupCheckpointConstants.READY_FOR_OAV,
|
|
32
35
|
wait=False,
|
|
33
36
|
):
|
|
34
37
|
max_vel = yield from bps.rd(smargon.omega.max_velocity)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import configparser
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from enum import StrEnum
|
|
4
|
+
from typing import Any, Literal
|
|
4
5
|
|
|
6
|
+
from event_model.documents import Event
|
|
5
7
|
from requests import JSONDecodeError, patch, post
|
|
6
8
|
from requests.auth import AuthBase
|
|
7
9
|
|
|
@@ -63,6 +65,19 @@ assert all(len(value) <= 20 for value in BLSampleStatus), (
|
|
|
63
65
|
)
|
|
64
66
|
|
|
65
67
|
|
|
68
|
+
def create_update_data_from_event_doc(
|
|
69
|
+
mapping: dict[str, str], event: Event
|
|
70
|
+
) -> dict[str, Any]:
|
|
71
|
+
"""Given a mapping between bluesky event data and an event itself this function will
|
|
72
|
+
create a dict that can be used to update exp-eye."""
|
|
73
|
+
event_data = event["data"]
|
|
74
|
+
return {
|
|
75
|
+
target_key: event_data[source_key]
|
|
76
|
+
for source_key, target_key in mapping.items()
|
|
77
|
+
if source_key in event_data
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
66
81
|
class ExpeyeInteraction:
|
|
67
82
|
"""Exposes functionality from the Expeye core API"""
|
|
68
83
|
|
|
@@ -74,24 +89,22 @@ class ExpeyeInteraction:
|
|
|
74
89
|
self._base_url = url
|
|
75
90
|
self._auth = BearerAuth(token)
|
|
76
91
|
|
|
77
|
-
def
|
|
92
|
+
def start_robot_action(
|
|
78
93
|
self,
|
|
94
|
+
action_type: Literal["LOAD", "UNLOAD"],
|
|
79
95
|
proposal_reference: str,
|
|
80
96
|
visit_number: int,
|
|
81
97
|
sample_id: int,
|
|
82
|
-
dewar_location: int,
|
|
83
|
-
container_location: int,
|
|
84
98
|
) -> RobotActionID:
|
|
85
|
-
"""Create a robot
|
|
99
|
+
"""Create a robot action entry in ispyb.
|
|
86
100
|
|
|
87
101
|
Args:
|
|
102
|
+
action_type ("LOAD" | "UNLOAD"): The robot action being performed
|
|
88
103
|
proposal_reference (str): The proposal of the experiment e.g. cm37235
|
|
89
104
|
visit_number (int): The visit number for the proposal, usually this can be
|
|
90
105
|
found added to the end of the proposal e.g. the data for
|
|
91
106
|
visit number 2 of proposal cm37235 is in cm37235-2
|
|
92
107
|
sample_id (int): The id of the sample in the database
|
|
93
|
-
dewar_location (int): Which puck in the dewar the sample is in
|
|
94
|
-
container_location (int): Which pin in that puck has the sample
|
|
95
108
|
|
|
96
109
|
Returns:
|
|
97
110
|
RobotActionID: The id of the robot load action that is created
|
|
@@ -102,39 +115,28 @@ class ExpeyeInteraction:
|
|
|
102
115
|
|
|
103
116
|
data = {
|
|
104
117
|
"startTimestamp": get_current_time_string(),
|
|
118
|
+
"actionType": action_type,
|
|
105
119
|
"sampleId": sample_id,
|
|
106
|
-
"actionType": "LOAD",
|
|
107
|
-
"containerLocation": container_location,
|
|
108
|
-
"dewarLocation": dewar_location,
|
|
109
120
|
}
|
|
110
121
|
response = _send_and_get_response(self._auth, url, data, post)
|
|
111
122
|
return response["robotActionId"]
|
|
112
123
|
|
|
113
|
-
def
|
|
124
|
+
def update_robot_action(
|
|
114
125
|
self,
|
|
115
126
|
action_id: RobotActionID,
|
|
116
|
-
|
|
117
|
-
snapshot_before_path: str,
|
|
118
|
-
snapshot_after_path: str,
|
|
127
|
+
data: dict[str, Any],
|
|
119
128
|
):
|
|
120
|
-
"""Update
|
|
129
|
+
"""Update an existing robot action to contain additional info.
|
|
121
130
|
|
|
122
131
|
Args:
|
|
123
132
|
action_id (RobotActionID): The id of the action to update
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
snapshot_after_path (str): Path to the snapshot after robot load
|
|
133
|
+
data (dict): The data to update with, where the keys match those expected
|
|
134
|
+
by exp-eye.
|
|
127
135
|
"""
|
|
128
136
|
url = self._base_url + self.UPDATE_ROBOT_ACTION.format(action_id=action_id)
|
|
129
|
-
|
|
130
|
-
data = {
|
|
131
|
-
"sampleBarcode": barcode,
|
|
132
|
-
"xtalSnapshotBefore": snapshot_before_path,
|
|
133
|
-
"xtalSnapshotAfter": snapshot_after_path,
|
|
134
|
-
}
|
|
135
137
|
_send_and_get_response(self._auth, url, data, patch)
|
|
136
138
|
|
|
137
|
-
def
|
|
139
|
+
def end_robot_action(self, action_id: RobotActionID, status: str, reason: str):
|
|
138
140
|
"""Finish an existing robot action, providing final information about how it went
|
|
139
141
|
|
|
140
142
|
Args:
|
|
@@ -20,13 +20,13 @@ from mx_bluesky.common.external_interaction.nexus.nexus_utils import (
|
|
|
20
20
|
create_goniometer_axes,
|
|
21
21
|
get_start_and_predicted_end_time,
|
|
22
22
|
)
|
|
23
|
-
from mx_bluesky.common.parameters.components import
|
|
23
|
+
from mx_bluesky.common.parameters.components import DiffractionExperiment
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class NexusWriter:
|
|
27
27
|
def __init__(
|
|
28
28
|
self,
|
|
29
|
-
parameters:
|
|
29
|
+
parameters: DiffractionExperiment,
|
|
30
30
|
data_shape: tuple[int, int, int],
|
|
31
31
|
scan_points: AxesPoints,
|
|
32
32
|
*,
|
|
@@ -136,7 +136,7 @@ class WithSnapshot(BaseModel):
|
|
|
136
136
|
|
|
137
137
|
@model_validator(mode="after")
|
|
138
138
|
def _validate_omegas_with_grid_snapshots(self) -> Self:
|
|
139
|
-
assert not self.use_grid_snapshots or self.snapshot_omegas_deg
|
|
139
|
+
assert not self.use_grid_snapshots or not self.snapshot_omegas_deg, (
|
|
140
140
|
"snapshot_omegas may not be specified with use_grid_snapshots"
|
|
141
141
|
)
|
|
142
142
|
return self
|
|
@@ -238,9 +238,14 @@ class TopNByMaxCountSelection(MultiXtalSelection):
|
|
|
238
238
|
n: int
|
|
239
239
|
|
|
240
240
|
|
|
241
|
+
class TopNByMaxCountForEachSampleSelection(MultiXtalSelection):
|
|
242
|
+
name: Literal["TopNByMaxCountForEachSample"] = "TopNByMaxCountForEachSample" # pyright: ignore [reportIncompatibleVariableOverride]
|
|
243
|
+
n: int
|
|
244
|
+
|
|
245
|
+
|
|
241
246
|
class WithCentreSelection(BaseModel):
|
|
242
|
-
select_centres: TopNByMaxCountSelection =
|
|
243
|
-
discriminator="name", default=TopNByMaxCountSelection(n=1)
|
|
247
|
+
select_centres: TopNByMaxCountSelection | TopNByMaxCountForEachSampleSelection = (
|
|
248
|
+
Field(discriminator="name", default=TopNByMaxCountSelection(n=1))
|
|
244
249
|
)
|
|
245
250
|
|
|
246
251
|
@property
|
|
@@ -15,8 +15,8 @@ TEST_MODE = BEAMLINE == "test"
|
|
|
15
15
|
|
|
16
16
|
@dataclass(frozen=True)
|
|
17
17
|
class DocDescriptorNames:
|
|
18
|
-
# Robot load event descriptor
|
|
19
|
-
|
|
18
|
+
# Robot load/unload event descriptor
|
|
19
|
+
ROBOT_UPDATE = "robot_update"
|
|
20
20
|
# For callbacks to use
|
|
21
21
|
OAV_ROTATION_SNAPSHOT_TRIGGERED = "rotation_snapshot_triggered"
|
|
22
22
|
OAV_GRID_SNAPSHOT_TRIGGERED = "snapshot_to_ispyb"
|
|
@@ -41,8 +41,9 @@ class OavConstants:
|
|
|
41
41
|
@dataclass(frozen=True)
|
|
42
42
|
class PlanNameConstants:
|
|
43
43
|
LOAD_CENTRE_COLLECT = "load_centre_collect"
|
|
44
|
-
# Robot
|
|
44
|
+
# Robot subplans
|
|
45
45
|
ROBOT_LOAD = "robot_load"
|
|
46
|
+
ROBOT_UNLOAD = "robot_unload"
|
|
46
47
|
# Gridscan
|
|
47
48
|
GRID_DETECT_AND_DO_GRIDSCAN = "grid_detect_and_do_gridscan"
|
|
48
49
|
GRID_DETECT_INNER = "grid_detect"
|