mx-bluesky 1.2.0__py3-none-any.whl → 1.4.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/__init__.py +8 -3
- mx_bluesky/__main__.py +12 -7
- mx_bluesky/_version.py +2 -2
- mx_bluesky/beamlines/i04/callbacks/murko_callback.py +14 -4
- mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +178 -0
- mx_bluesky/beamlines/i04/thawing_plan.py +49 -11
- mx_bluesky/beamlines/i24/serial/__init__.py +3 -0
- mx_bluesky/beamlines/i24/serial/dcid.py +143 -171
- mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +1 -1
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +121 -110
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +3 -6
- mx_bluesky/beamlines/i24/serial/fixed_target/ft_utils.py +0 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +164 -169
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +149 -225
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +7 -216
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +18 -17
- mx_bluesky/beamlines/i24/serial/log.py +58 -49
- mx_bluesky/beamlines/i24/serial/parameters/__init__.py +4 -0
- mx_bluesky/beamlines/i24/serial/parameters/constants.py +6 -1
- mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +42 -15
- mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +3 -3
- mx_bluesky/beamlines/i24/serial/run_extruder.sh +30 -5
- mx_bluesky/beamlines/i24/serial/run_fixed_target.sh +30 -5
- mx_bluesky/beamlines/i24/serial/run_serial.py +24 -8
- mx_bluesky/beamlines/i24/serial/setup_beamline/ca.py +0 -2
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +2 -0
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +104 -82
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +9 -20
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +26 -28
- mx_bluesky/beamlines/i24/serial/write_nexus.py +74 -72
- mx_bluesky/common/__init__.py +0 -0
- mx_bluesky/common/device_setup_plans/read_hardware_for_setup.py +14 -0
- mx_bluesky/common/external_interaction/config_server.py +46 -0
- mx_bluesky/common/parameters/components.py +258 -0
- mx_bluesky/common/parameters/constants.py +143 -0
- mx_bluesky/common/parameters/gridscan.py +94 -0
- mx_bluesky/common/parameters/robot_load.py +16 -0
- mx_bluesky/common/plans/__init__.py +1 -0
- mx_bluesky/common/plans/do_fgs.py +121 -0
- mx_bluesky/common/utils/log.py +118 -0
- mx_bluesky/{hyperion → common/utils}/tracing.py +2 -2
- mx_bluesky/hyperion/__main__.py +13 -10
- mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +47 -52
- mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +6 -12
- mx_bluesky/hyperion/device_setup_plans/setup_oav.py +6 -12
- mx_bluesky/hyperion/device_setup_plans/setup_panda.py +5 -6
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +49 -18
- mx_bluesky/hyperion/device_setup_plans/smargon.py +9 -9
- mx_bluesky/hyperion/device_setup_plans/utils.py +2 -2
- mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +4 -4
- mx_bluesky/hyperion/exceptions.py +13 -1
- mx_bluesky/hyperion/experiment_plans/__init__.py +4 -0
- mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +83 -0
- mx_bluesky/hyperion/experiment_plans/common/xrc_result.py +47 -0
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -9
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +147 -169
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +48 -22
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +75 -9
- mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +21 -20
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +9 -6
- mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +40 -21
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +22 -22
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +43 -39
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +69 -18
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +17 -7
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +13 -13
- mx_bluesky/hyperion/external_interaction/callbacks/__init__.py +0 -4
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +5 -2
- mx_bluesky/hyperion/external_interaction/callbacks/common/abstract_event.py +66 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +5 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/ispyb_mapping.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/grid_detection_callback.py +30 -25
- mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py +29 -12
- mx_bluesky/hyperion/external_interaction/callbacks/log_uid_tag_callback.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +19 -11
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +7 -4
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +5 -3
- mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/__init__.py +0 -0
- mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +84 -0
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +38 -27
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py +5 -4
- mx_bluesky/hyperion/external_interaction/config_server.py +11 -28
- mx_bluesky/hyperion/external_interaction/exceptions.py +0 -9
- mx_bluesky/hyperion/external_interaction/ispyb/exp_eye_store.py +65 -15
- mx_bluesky/hyperion/external_interaction/ispyb/ispyb_store.py +1 -1
- mx_bluesky/hyperion/external_interaction/nexus/nexus_utils.py +2 -2
- mx_bluesky/hyperion/external_interaction/nexus/write_nexus.py +1 -1
- mx_bluesky/hyperion/log.py +0 -84
- mx_bluesky/hyperion/parameters/components.py +4 -251
- mx_bluesky/hyperion/parameters/constants.py +22 -119
- mx_bluesky/hyperion/parameters/gridscan.py +35 -74
- mx_bluesky/hyperion/parameters/load_centre_collect.py +16 -11
- mx_bluesky/hyperion/parameters/rotation.py +23 -10
- mx_bluesky/hyperion/utils/utils.py +17 -0
- mx_bluesky/hyperion/utils/validation.py +5 -6
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/METADATA +36 -33
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/RECORD +102 -89
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/WHEEL +1 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Mapping_py3v1.py +0 -161
- mx_bluesky/example.py +0 -19
- mx_bluesky/hyperion/parameters/robot_load.py +0 -16
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/LICENSE +0 -0
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import dataclasses
|
|
4
3
|
from collections.abc import Generator
|
|
5
4
|
from datetime import datetime
|
|
6
5
|
from pathlib import Path
|
|
@@ -8,12 +7,13 @@ from typing import cast
|
|
|
8
7
|
|
|
9
8
|
import bluesky.plan_stubs as bps
|
|
10
9
|
import bluesky.preprocessors as bpp
|
|
10
|
+
import pydantic
|
|
11
11
|
from blueapi.core import BlueskyContext
|
|
12
12
|
from bluesky.utils import Msg
|
|
13
13
|
from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureValue
|
|
14
14
|
from dodal.devices.attenuator import Attenuator
|
|
15
15
|
from dodal.devices.dcm import DCM
|
|
16
|
-
from dodal.devices.focusing_mirror import FocusingMirrorWithStripes,
|
|
16
|
+
from dodal.devices.focusing_mirror import FocusingMirrorWithStripes, MirrorVoltages
|
|
17
17
|
from dodal.devices.motors import XYZPositioner
|
|
18
18
|
from dodal.devices.oav.oav_detector import OAV
|
|
19
19
|
from dodal.devices.robot import BartRobot, SampleLocation
|
|
@@ -22,22 +22,22 @@ from dodal.devices.thawer import Thawer
|
|
|
22
22
|
from dodal.devices.undulator_dcm import UndulatorDCM
|
|
23
23
|
from dodal.devices.webcam import Webcam
|
|
24
24
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
25
|
-
from dodal.
|
|
25
|
+
from dodal.plan_stubs.motor_utils import MoveTooLarge, home_and_reset_wrapper
|
|
26
26
|
|
|
27
|
+
from mx_bluesky.common.parameters.robot_load import RobotLoadAndEnergyChange
|
|
27
28
|
from mx_bluesky.hyperion.experiment_plans.set_energy_plan import (
|
|
28
29
|
SetEnergyComposite,
|
|
29
30
|
set_energy_plan,
|
|
30
31
|
)
|
|
31
32
|
from mx_bluesky.hyperion.log import LOGGER
|
|
32
33
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
33
|
-
from mx_bluesky.hyperion.parameters.robot_load import RobotLoadAndEnergyChange
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
@dataclasses.dataclass
|
|
36
|
+
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
37
37
|
class RobotLoadAndEnergyChangeComposite:
|
|
38
38
|
# SetEnergyComposite fields
|
|
39
39
|
vfm: FocusingMirrorWithStripes
|
|
40
|
-
|
|
40
|
+
mirror_voltages: MirrorVoltages
|
|
41
41
|
dcm: DCM
|
|
42
42
|
undulator_dcm: UndulatorDCM
|
|
43
43
|
xbpm_feedback: XBPMFeedback
|
|
@@ -100,15 +100,17 @@ def prepare_for_robot_load(
|
|
|
100
100
|
group="prepare_robot_load",
|
|
101
101
|
)
|
|
102
102
|
|
|
103
|
-
yield from bps.mv(smargon.stub_offsets, StubPosition.RESET_TO_ROBOT_LOAD)
|
|
103
|
+
yield from bps.mv(smargon.stub_offsets, StubPosition.RESET_TO_ROBOT_LOAD) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
104
104
|
|
|
105
105
|
# fmt: off
|
|
106
|
-
yield from bps.mv(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
yield from bps.mv(
|
|
107
|
+
smargon.x, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
108
|
+
smargon.y, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
109
|
+
smargon.z, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
110
|
+
smargon.omega, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
111
|
+
smargon.chi, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
112
|
+
smargon.phi, 0 # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
113
|
+
)
|
|
112
114
|
# fmt: on
|
|
113
115
|
|
|
114
116
|
yield from bps.wait("prepare_robot_load")
|
|
@@ -126,16 +128,14 @@ def do_robot_load(
|
|
|
126
128
|
group="robot_load",
|
|
127
129
|
)
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
yield from set_energy_plan(
|
|
131
|
-
demand_energy_ev / 1000,
|
|
132
|
-
cast(SetEnergyComposite, composite),
|
|
133
|
-
)
|
|
131
|
+
yield from set_energy_plan(demand_energy_ev, cast(SetEnergyComposite, composite))
|
|
134
132
|
|
|
135
133
|
yield from bps.wait("robot_load")
|
|
136
134
|
|
|
137
135
|
yield from bps.abs_set(
|
|
138
|
-
composite.thawer.thaw_for_time_s,
|
|
136
|
+
composite.thawer.thaw_for_time_s, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
137
|
+
thawing_time,
|
|
138
|
+
group="thawing_finished",
|
|
139
139
|
)
|
|
140
140
|
yield from wait_for_smargon_not_disabled(composite.smargon)
|
|
141
141
|
|
|
@@ -195,7 +195,7 @@ def robot_load_and_snapshots(
|
|
|
195
195
|
|
|
196
196
|
yield from bps.create(name=CONST.DESCRIPTORS.ROBOT_LOAD)
|
|
197
197
|
yield from bps.read(composite.robot.barcode)
|
|
198
|
-
yield from bps.read(composite.oav.snapshot)
|
|
198
|
+
yield from bps.read(composite.oav.snapshot) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
199
199
|
yield from bps.read(composite.webcam)
|
|
200
200
|
yield from bps.save()
|
|
201
201
|
|
|
@@ -214,24 +214,28 @@ def robot_load_and_change_energy_plan(
|
|
|
214
214
|
yield from prepare_for_robot_load(
|
|
215
215
|
composite.aperture_scatterguard, composite.smargon
|
|
216
216
|
)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
"
|
|
229
|
-
"
|
|
230
|
-
|
|
231
|
-
|
|
217
|
+
|
|
218
|
+
yield from bpp.set_run_key_wrapper(
|
|
219
|
+
bpp.run_wrapper(
|
|
220
|
+
robot_load_and_snapshots(
|
|
221
|
+
composite,
|
|
222
|
+
sample_location,
|
|
223
|
+
params.snapshot_directory,
|
|
224
|
+
params.thawing_time,
|
|
225
|
+
params.demand_energy_ev,
|
|
226
|
+
),
|
|
227
|
+
md={
|
|
228
|
+
"subplan_name": CONST.PLAN.ROBOT_LOAD,
|
|
229
|
+
"metadata": {
|
|
230
|
+
"visit": params.visit,
|
|
231
|
+
"sample_id": params.sample_id,
|
|
232
|
+
"sample_puck": sample_location.puck,
|
|
233
|
+
"sample_pin": sample_location.pin,
|
|
234
|
+
},
|
|
235
|
+
"activate_callbacks": [
|
|
236
|
+
"RobotLoadISPyBCallback",
|
|
237
|
+
],
|
|
232
238
|
},
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
],
|
|
236
|
-
},
|
|
239
|
+
),
|
|
240
|
+
CONST.PLAN.ROBOT_LOAD_AND_SNAPSHOTS,
|
|
237
241
|
)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import dataclasses
|
|
4
3
|
from typing import cast
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
import bluesky.preprocessors as bpp
|
|
6
|
+
import pydantic
|
|
7
|
+
from blueapi.core import BlueskyContext
|
|
8
|
+
from bluesky.utils import MsgGenerator
|
|
7
9
|
from dodal.devices.aperturescatterguard import ApertureScatterguard
|
|
8
10
|
from dodal.devices.attenuator import Attenuator
|
|
9
11
|
from dodal.devices.backlight import Backlight
|
|
@@ -12,7 +14,7 @@ from dodal.devices.detector.detector_motion import DetectorMotion
|
|
|
12
14
|
from dodal.devices.eiger import EigerDetector
|
|
13
15
|
from dodal.devices.fast_grid_scan import PandAFastGridScan, ZebraFastGridScan
|
|
14
16
|
from dodal.devices.flux import Flux
|
|
15
|
-
from dodal.devices.focusing_mirror import FocusingMirrorWithStripes,
|
|
17
|
+
from dodal.devices.focusing_mirror import FocusingMirrorWithStripes, MirrorVoltages
|
|
16
18
|
from dodal.devices.motors import XYZPositioner
|
|
17
19
|
from dodal.devices.oav.oav_detector import OAV
|
|
18
20
|
from dodal.devices.oav.pin_image_recognition import PinTipDetection
|
|
@@ -31,26 +33,37 @@ from dodal.devices.zocalo import ZocaloResults
|
|
|
31
33
|
from dodal.log import LOGGER
|
|
32
34
|
from ophyd_async.fastcs.panda import HDFPanda
|
|
33
35
|
|
|
36
|
+
from mx_bluesky.common.parameters.constants import OavConstants
|
|
37
|
+
from mx_bluesky.common.parameters.gridscan import RobotLoadThenCentre
|
|
34
38
|
from mx_bluesky.hyperion.device_setup_plans.utils import (
|
|
35
39
|
fill_in_energy_if_not_supplied,
|
|
36
40
|
start_preparing_data_collection_then_do_plan,
|
|
37
41
|
)
|
|
42
|
+
from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import (
|
|
43
|
+
change_aperture_then_move_to_xtal,
|
|
44
|
+
)
|
|
45
|
+
from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
|
|
46
|
+
XRayCentreEventHandler,
|
|
47
|
+
)
|
|
38
48
|
from mx_bluesky.hyperion.experiment_plans.grid_detect_then_xray_centre_plan import (
|
|
39
49
|
GridDetectThenXRayCentreComposite,
|
|
40
50
|
)
|
|
41
51
|
from mx_bluesky.hyperion.experiment_plans.pin_centre_then_xray_centre_plan import (
|
|
42
|
-
|
|
52
|
+
pin_centre_then_flyscan_plan,
|
|
43
53
|
)
|
|
44
54
|
from mx_bluesky.hyperion.experiment_plans.robot_load_and_change_energy import (
|
|
45
55
|
RobotLoadAndEnergyChangeComposite,
|
|
46
56
|
pin_already_loaded,
|
|
47
57
|
robot_load_and_change_energy_plan,
|
|
48
58
|
)
|
|
59
|
+
from mx_bluesky.hyperion.experiment_plans.set_energy_plan import (
|
|
60
|
+
SetEnergyComposite,
|
|
61
|
+
set_energy_plan,
|
|
62
|
+
)
|
|
49
63
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
50
|
-
from mx_bluesky.hyperion.parameters.gridscan import RobotLoadThenCentre
|
|
51
64
|
|
|
52
65
|
|
|
53
|
-
@dataclasses.dataclass
|
|
66
|
+
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
54
67
|
class RobotLoadThenCentreComposite:
|
|
55
68
|
# common fields
|
|
56
69
|
xbpm_feedback: XBPMFeedback
|
|
@@ -78,7 +91,7 @@ class RobotLoadThenCentreComposite:
|
|
|
78
91
|
|
|
79
92
|
# SetEnergyComposite fields
|
|
80
93
|
vfm: FocusingMirrorWithStripes
|
|
81
|
-
|
|
94
|
+
mirror_voltages: MirrorVoltages
|
|
82
95
|
dcm: DCM
|
|
83
96
|
undulator_dcm: UndulatorDCM
|
|
84
97
|
|
|
@@ -87,6 +100,10 @@ class RobotLoadThenCentreComposite:
|
|
|
87
100
|
webcam: Webcam
|
|
88
101
|
lower_gonio: XYZPositioner
|
|
89
102
|
|
|
103
|
+
@property
|
|
104
|
+
def sample_motors(self):
|
|
105
|
+
return self.smargon
|
|
106
|
+
|
|
90
107
|
|
|
91
108
|
def create_devices(context: BlueskyContext) -> RobotLoadThenCentreComposite:
|
|
92
109
|
from mx_bluesky.hyperion.utils.context import device_composite_from_context
|
|
@@ -94,32 +111,57 @@ def create_devices(context: BlueskyContext) -> RobotLoadThenCentreComposite:
|
|
|
94
111
|
return device_composite_from_context(context, RobotLoadThenCentreComposite)
|
|
95
112
|
|
|
96
113
|
|
|
97
|
-
def
|
|
114
|
+
def _flyscan_plan_from_robot_load_params(
|
|
98
115
|
composite: RobotLoadThenCentreComposite,
|
|
99
116
|
params: RobotLoadThenCentre,
|
|
117
|
+
oav_config_file: str = OavConstants.OAV_CONFIG_JSON,
|
|
100
118
|
):
|
|
101
|
-
yield from
|
|
119
|
+
yield from pin_centre_then_flyscan_plan(
|
|
102
120
|
cast(GridDetectThenXRayCentreComposite, composite),
|
|
103
121
|
params.pin_centre_then_xray_centre_params(),
|
|
104
122
|
)
|
|
105
123
|
|
|
106
124
|
|
|
107
|
-
def
|
|
125
|
+
def _robot_load_then_flyscan_plan(
|
|
108
126
|
composite: RobotLoadThenCentreComposite,
|
|
109
127
|
params: RobotLoadThenCentre,
|
|
128
|
+
oav_config_file: str = OavConstants.OAV_CONFIG_JSON,
|
|
110
129
|
):
|
|
111
130
|
yield from robot_load_and_change_energy_plan(
|
|
112
131
|
cast(RobotLoadAndEnergyChangeComposite, composite),
|
|
113
132
|
params.robot_load_params(),
|
|
114
133
|
)
|
|
115
134
|
|
|
116
|
-
yield from
|
|
135
|
+
yield from _flyscan_plan_from_robot_load_params(composite, params, oav_config_file)
|
|
117
136
|
|
|
118
137
|
|
|
119
138
|
def robot_load_then_centre(
|
|
120
139
|
composite: RobotLoadThenCentreComposite,
|
|
121
140
|
parameters: RobotLoadThenCentre,
|
|
122
141
|
) -> MsgGenerator:
|
|
142
|
+
"""Perform pin-tip detection followed by a flyscan to determine centres of interest.
|
|
143
|
+
Performs a robot load if necessary. Centre on the best diffracting centre.
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
xray_centre_event_handler = XRayCentreEventHandler()
|
|
147
|
+
|
|
148
|
+
yield from bpp.subs_wrapper(
|
|
149
|
+
robot_load_then_xray_centre(composite, parameters), xray_centre_event_handler
|
|
150
|
+
)
|
|
151
|
+
flyscan_results = xray_centre_event_handler.xray_centre_results
|
|
152
|
+
if flyscan_results is not None:
|
|
153
|
+
yield from change_aperture_then_move_to_xtal(
|
|
154
|
+
flyscan_results[0], composite.smargon, composite.aperture_scatterguard
|
|
155
|
+
)
|
|
156
|
+
# else no chi change, no need to recentre.
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def robot_load_then_xray_centre(
|
|
160
|
+
composite: RobotLoadThenCentreComposite,
|
|
161
|
+
parameters: RobotLoadThenCentre,
|
|
162
|
+
) -> MsgGenerator:
|
|
163
|
+
"""Perform pin-tip detection followed by a flyscan to determine centres of interest.
|
|
164
|
+
Performs a robot load if necessary."""
|
|
123
165
|
eiger: EigerDetector = composite.eiger
|
|
124
166
|
|
|
125
167
|
# TODO: get these from one source of truth #254
|
|
@@ -135,17 +177,26 @@ def robot_load_then_centre(
|
|
|
135
177
|
doing_chi_change = parameters.chi_start_deg is not None
|
|
136
178
|
|
|
137
179
|
if doing_sample_load:
|
|
138
|
-
|
|
180
|
+
LOGGER.info("Pin not loaded, loading and centring")
|
|
181
|
+
plan = _robot_load_then_flyscan_plan(
|
|
139
182
|
composite,
|
|
140
183
|
parameters,
|
|
141
184
|
)
|
|
142
|
-
LOGGER.info("Pin not loaded, loading and centring")
|
|
143
|
-
elif doing_chi_change:
|
|
144
|
-
plan = centring_plan_from_robot_load_params(composite, parameters)
|
|
145
|
-
LOGGER.info("Pin already loaded but chi changed so centring")
|
|
146
185
|
else:
|
|
147
|
-
|
|
148
|
-
|
|
186
|
+
# Robot load normally sets the energy so we should do this explicitly if no load is
|
|
187
|
+
# being done
|
|
188
|
+
demand_energy_ev = parameters.demand_energy_ev
|
|
189
|
+
LOGGER.info(f"Setting the energy to {demand_energy_ev}eV")
|
|
190
|
+
yield from set_energy_plan(
|
|
191
|
+
demand_energy_ev, cast(SetEnergyComposite, composite)
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
if doing_chi_change:
|
|
195
|
+
plan = _flyscan_plan_from_robot_load_params(composite, parameters)
|
|
196
|
+
LOGGER.info("Pin already loaded but chi changed so centring")
|
|
197
|
+
else:
|
|
198
|
+
LOGGER.info("Pin already loaded and chi not changed so doing nothing")
|
|
199
|
+
return
|
|
149
200
|
|
|
150
201
|
detector_params = yield from fill_in_energy_if_not_supplied(
|
|
151
202
|
composite.dcm, parameters.detector_params
|
|
@@ -4,7 +4,9 @@ import dataclasses
|
|
|
4
4
|
|
|
5
5
|
import bluesky.plan_stubs as bps
|
|
6
6
|
import bluesky.preprocessors as bpp
|
|
7
|
-
|
|
7
|
+
import pydantic
|
|
8
|
+
from blueapi.core import BlueskyContext
|
|
9
|
+
from bluesky.utils import MsgGenerator
|
|
8
10
|
from dodal.devices.aperturescatterguard import ApertureScatterguard
|
|
9
11
|
from dodal.devices.attenuator import Attenuator
|
|
10
12
|
from dodal.devices.backlight import Backlight
|
|
@@ -22,8 +24,11 @@ from dodal.devices.undulator import Undulator
|
|
|
22
24
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
23
25
|
from dodal.devices.zebra import RotationDirection, Zebra
|
|
24
26
|
from dodal.devices.zebra_controlled_shutter import ZebraShutter
|
|
25
|
-
from dodal.
|
|
27
|
+
from dodal.plan_stubs.check_topup import check_topup_and_wait_if_necessary
|
|
26
28
|
|
|
29
|
+
from mx_bluesky.common.device_setup_plans.read_hardware_for_setup import (
|
|
30
|
+
read_hardware_for_zocalo,
|
|
31
|
+
)
|
|
27
32
|
from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import (
|
|
28
33
|
cleanup_sample_environment,
|
|
29
34
|
move_phi_chi_omega,
|
|
@@ -32,7 +37,6 @@ from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import (
|
|
|
32
37
|
)
|
|
33
38
|
from mx_bluesky.hyperion.device_setup_plans.read_hardware_for_setup import (
|
|
34
39
|
read_hardware_during_collection,
|
|
35
|
-
read_hardware_for_zocalo,
|
|
36
40
|
read_hardware_pre_collection,
|
|
37
41
|
)
|
|
38
42
|
from mx_bluesky.hyperion.device_setup_plans.setup_zebra import (
|
|
@@ -60,7 +64,7 @@ from mx_bluesky.hyperion.parameters.rotation import (
|
|
|
60
64
|
from mx_bluesky.hyperion.utils.context import device_composite_from_context
|
|
61
65
|
|
|
62
66
|
|
|
63
|
-
@dataclasses.dataclass
|
|
67
|
+
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
64
68
|
class RotationScanComposite(OavSnapshotComposite):
|
|
65
69
|
"""All devices which are directly or indirectly required by this plan"""
|
|
66
70
|
|
|
@@ -252,7 +256,7 @@ def rotation_scan_plan(
|
|
|
252
256
|
composite.undulator,
|
|
253
257
|
composite.synchrotron,
|
|
254
258
|
composite.s4_slit_gaps,
|
|
255
|
-
composite.
|
|
259
|
+
composite.dcm,
|
|
256
260
|
composite.smargon,
|
|
257
261
|
)
|
|
258
262
|
|
|
@@ -348,7 +352,7 @@ def rotation_scan(
|
|
|
348
352
|
md={
|
|
349
353
|
"subplan_name": CONST.PLAN.ROTATION_OUTER,
|
|
350
354
|
CONST.TRIGGER.ZOCALO: CONST.PLAN.ROTATION_MAIN,
|
|
351
|
-
"zocalo_environment":
|
|
355
|
+
"zocalo_environment": CONST.ZOCALO_ENV,
|
|
352
356
|
"hyperion_parameters": parameters.model_dump_json(),
|
|
353
357
|
"activate_callbacks": [
|
|
354
358
|
"RotationISPyBCallback",
|
|
@@ -379,7 +383,7 @@ def rotation_scan(
|
|
|
379
383
|
rotation_with_cleanup_and_stage(params),
|
|
380
384
|
group=CONST.WAIT.ROTATION_READY_FOR_DC,
|
|
381
385
|
)
|
|
382
|
-
yield from bps.unstage(eiger)
|
|
386
|
+
yield from bps.unstage(eiger) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
383
387
|
|
|
384
388
|
yield from rotation_scan_plan_with_stage_and_cleanup(parameters)
|
|
385
389
|
|
|
@@ -407,6 +411,11 @@ def multi_rotation_scan(
|
|
|
407
411
|
}
|
|
408
412
|
)
|
|
409
413
|
@bpp.stage_decorator([eiger])
|
|
414
|
+
@transmission_and_xbpm_feedback_for_collection_decorator(
|
|
415
|
+
composite.xbpm_feedback,
|
|
416
|
+
composite.attenuator,
|
|
417
|
+
parameters.transmission_frac,
|
|
418
|
+
)
|
|
410
419
|
@bpp.finalize_decorator(lambda: _cleanup_plan(composite))
|
|
411
420
|
def _multi_rotation_scan():
|
|
412
421
|
for single_scan in parameters.single_rotation_scans:
|
|
@@ -416,6 +425,7 @@ def multi_rotation_scan(
|
|
|
416
425
|
md={
|
|
417
426
|
"subplan_name": CONST.PLAN.ROTATION_OUTER,
|
|
418
427
|
CONST.TRIGGER.ZOCALO: CONST.PLAN.ROTATION_MAIN,
|
|
428
|
+
"zocalo_environment": CONST.ZOCALO_ENV,
|
|
419
429
|
"hyperion_parameters": single_scan.model_dump_json(),
|
|
420
430
|
}
|
|
421
431
|
)
|
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
* reenable feedback
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import
|
|
9
|
-
|
|
8
|
+
import pydantic
|
|
10
9
|
from bluesky import plan_stubs as bps
|
|
11
10
|
from dodal.devices.attenuator import Attenuator
|
|
12
11
|
from dodal.devices.dcm import DCM
|
|
13
|
-
from dodal.devices.focusing_mirror import FocusingMirrorWithStripes,
|
|
12
|
+
from dodal.devices.focusing_mirror import FocusingMirrorWithStripes, MirrorVoltages
|
|
14
13
|
from dodal.devices.undulator_dcm import UndulatorDCM
|
|
15
14
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
16
15
|
|
|
@@ -24,10 +23,10 @@ DESIRED_TRANSMISSION_FRACTION = 0.1
|
|
|
24
23
|
UNDULATOR_GROUP = "UNDULATOR_GROUP"
|
|
25
24
|
|
|
26
25
|
|
|
27
|
-
@dataclasses.dataclass
|
|
26
|
+
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
28
27
|
class SetEnergyComposite:
|
|
29
28
|
vfm: FocusingMirrorWithStripes
|
|
30
|
-
|
|
29
|
+
mirror_voltages: MirrorVoltages
|
|
31
30
|
dcm: DCM
|
|
32
31
|
undulator_dcm: UndulatorDCM
|
|
33
32
|
xbpm_feedback: XBPMFeedback
|
|
@@ -42,19 +41,20 @@ def _set_energy_plan(
|
|
|
42
41
|
yield from dcm_pitch_roll_mirror_adjuster.adjust_dcm_pitch_roll_vfm_from_lut(
|
|
43
42
|
composite.undulator_dcm,
|
|
44
43
|
composite.vfm,
|
|
45
|
-
composite.
|
|
44
|
+
composite.mirror_voltages,
|
|
46
45
|
energy_kev,
|
|
47
46
|
)
|
|
48
47
|
yield from bps.wait(group=UNDULATOR_GROUP)
|
|
49
48
|
|
|
50
49
|
|
|
51
50
|
def set_energy_plan(
|
|
52
|
-
|
|
51
|
+
energy_ev: float | None,
|
|
53
52
|
composite: SetEnergyComposite,
|
|
54
53
|
):
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
if energy_ev:
|
|
55
|
+
yield from transmission_and_xbpm_feedback_for_collection_wrapper(
|
|
56
|
+
_set_energy_plan(energy_ev / 1000, composite),
|
|
57
|
+
composite.xbpm_feedback,
|
|
58
|
+
composite.attenuator,
|
|
59
|
+
DESIRED_TRANSMISSION_FRACTION,
|
|
60
|
+
)
|
|
@@ -7,6 +7,7 @@ from bluesky.callbacks.zmq import Proxy, RemoteDispatcher
|
|
|
7
7
|
from dodal.log import LOGGER as dodal_logger
|
|
8
8
|
from dodal.log import set_up_all_logging_handlers
|
|
9
9
|
|
|
10
|
+
from mx_bluesky.common.utils.log import _get_logging_dir, tag_filter
|
|
10
11
|
from mx_bluesky.hyperion.external_interaction.callbacks.log_uid_tag_callback import (
|
|
11
12
|
LogUidTaggingCallback,
|
|
12
13
|
)
|
|
@@ -19,6 +20,9 @@ from mx_bluesky.hyperion.external_interaction.callbacks.rotation.ispyb_callback
|
|
|
19
20
|
from mx_bluesky.hyperion.external_interaction.callbacks.rotation.nexus_callback import (
|
|
20
21
|
RotationNexusFileCallback,
|
|
21
22
|
)
|
|
23
|
+
from mx_bluesky.hyperion.external_interaction.callbacks.sample_handling.sample_handling_callback import (
|
|
24
|
+
SampleHandlingCallback,
|
|
25
|
+
)
|
|
22
26
|
from mx_bluesky.hyperion.external_interaction.callbacks.xray_centre.ispyb_callback import (
|
|
23
27
|
GridscanISPyBCallback,
|
|
24
28
|
)
|
|
@@ -31,8 +35,6 @@ from mx_bluesky.hyperion.external_interaction.callbacks.zocalo_callback import (
|
|
|
31
35
|
from mx_bluesky.hyperion.log import (
|
|
32
36
|
ISPYB_LOGGER,
|
|
33
37
|
NEXUS_LOGGER,
|
|
34
|
-
_get_logging_dir,
|
|
35
|
-
tag_filter,
|
|
36
38
|
)
|
|
37
39
|
from mx_bluesky.hyperion.parameters.cli import parse_callback_dev_mode_arg
|
|
38
40
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
@@ -50,6 +52,7 @@ def setup_callbacks():
|
|
|
50
52
|
RotationISPyBCallback(emit=zocalo),
|
|
51
53
|
LogUidTaggingCallback(),
|
|
52
54
|
RobotLoadISPyBCallback(),
|
|
55
|
+
SampleHandlingCallback(),
|
|
53
56
|
]
|
|
54
57
|
|
|
55
58
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import builtins
|
|
2
|
+
import dataclasses
|
|
3
|
+
import time
|
|
4
|
+
from abc import ABC
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from bluesky.protocols import Readable, Reading
|
|
8
|
+
from event_model import DataKey
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclasses.dataclass(frozen=True)
|
|
12
|
+
class AbstractEvent(Readable, ABC):
|
|
13
|
+
"""An abstract superclass that can be extended to provide lightweight software events
|
|
14
|
+
for bluesky plans, without having to incur the overhead of creating ophyd-async devices
|
|
15
|
+
specifically for the purpose.
|
|
16
|
+
|
|
17
|
+
The currently supported types for field annotations in the event are ``str``, ``int``, ``float``, ``bool``
|
|
18
|
+
|
|
19
|
+
In future array types may be supported.
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
Subclasses should extend this class and decorate with::
|
|
23
|
+
|
|
24
|
+
@dataclasses.dataclass(frozen=True)
|
|
25
|
+
|
|
26
|
+
To raise an event, simply construct the event and then ``read`` it as you would a device::
|
|
27
|
+
|
|
28
|
+
yield from bps.create("MY_EVENT_NAME")
|
|
29
|
+
my_event = MyEvent(an_int=1)
|
|
30
|
+
yield from bps.read(my_event)
|
|
31
|
+
yield from bps.save()
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def read(self) -> dict[str, Reading]:
|
|
35
|
+
return {
|
|
36
|
+
f.name: AbstractEvent._reading_from_value(getattr(self, f.name))
|
|
37
|
+
for f in dataclasses.fields(self)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def describe(self) -> dict[str, DataKey]:
|
|
41
|
+
return {
|
|
42
|
+
f.name: DataKey(dtype=AbstractEvent._dtype_of(f.type), shape=[], source="")
|
|
43
|
+
for f in dataclasses.fields(self)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def _reading_from_value(cls, value):
|
|
48
|
+
return Reading(timestamp=time.time(), value=value)
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def _dtype_of(cls, t) -> Literal["string", "number", "boolean", "integer"]:
|
|
52
|
+
match t:
|
|
53
|
+
case builtins.str:
|
|
54
|
+
return "string"
|
|
55
|
+
case builtins.bool:
|
|
56
|
+
return "boolean"
|
|
57
|
+
case builtins.int:
|
|
58
|
+
return "integer"
|
|
59
|
+
case builtins.float:
|
|
60
|
+
return "number"
|
|
61
|
+
# TODO array support
|
|
62
|
+
raise ValueError(f"Unsupported type for AbstractEvent: {t}")
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def name(self) -> str:
|
|
66
|
+
return type(self).__name__
|
|
@@ -11,6 +11,9 @@ from mx_bluesky.hyperion.external_interaction.callbacks.rotation.ispyb_callback
|
|
|
11
11
|
from mx_bluesky.hyperion.external_interaction.callbacks.rotation.nexus_callback import (
|
|
12
12
|
RotationNexusFileCallback,
|
|
13
13
|
)
|
|
14
|
+
from mx_bluesky.hyperion.external_interaction.callbacks.sample_handling.sample_handling_callback import (
|
|
15
|
+
SampleHandlingCallback,
|
|
16
|
+
)
|
|
14
17
|
from mx_bluesky.hyperion.external_interaction.callbacks.xray_centre.ispyb_callback import (
|
|
15
18
|
GridscanISPyBCallback,
|
|
16
19
|
)
|
|
@@ -53,6 +56,7 @@ def create_load_centre_collect_callbacks() -> (
|
|
|
53
56
|
RobotLoadISPyBCallback,
|
|
54
57
|
RotationNexusFileCallback,
|
|
55
58
|
RotationISPyBCallback,
|
|
59
|
+
SampleHandlingCallback,
|
|
56
60
|
]
|
|
57
61
|
):
|
|
58
62
|
return (
|
|
@@ -61,4 +65,5 @@ def create_load_centre_collect_callbacks() -> (
|
|
|
61
65
|
RobotLoadISPyBCallback(),
|
|
62
66
|
RotationNexusFileCallback(),
|
|
63
67
|
RotationISPyBCallback(emit=ZocaloCallback()),
|
|
68
|
+
SampleHandlingCallback(),
|
|
64
69
|
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from mx_bluesky.common.parameters.components import DiffractionExperimentWithSample
|
|
3
4
|
from mx_bluesky.hyperion.external_interaction.ispyb.data_model import (
|
|
4
5
|
DataCollectionGroupInfo,
|
|
5
6
|
DataCollectionInfo,
|
|
@@ -11,7 +12,6 @@ from mx_bluesky.hyperion.external_interaction.ispyb.ispyb_store import (
|
|
|
11
12
|
from mx_bluesky.hyperion.external_interaction.ispyb.ispyb_utils import (
|
|
12
13
|
get_current_time_string,
|
|
13
14
|
)
|
|
14
|
-
from mx_bluesky.hyperion.parameters.components import DiffractionExperimentWithSample
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def populate_data_collection_group(params: DiffractionExperimentWithSample):
|