mx-bluesky 1.5.11__py3-none-any.whl → 1.5.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mx_bluesky/_version.py +2 -2
- mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/__init__.py +0 -0
- mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/robot_load_plan.py +198 -0
- mx_bluesky/beamlines/aithre_lasershaping/parameters/__init__.py +0 -0
- mx_bluesky/beamlines/aithre_lasershaping/parameters/constants.py +17 -0
- mx_bluesky/beamlines/aithre_lasershaping/parameters/robot_load_parameters.py +13 -0
- mx_bluesky/beamlines/aithre_lasershaping/pin_tip_centring.py +31 -0
- mx_bluesky/beamlines/aithre_lasershaping/robot_load.py +80 -0
- mx_bluesky/beamlines/i04/__init__.py +6 -2
- mx_bluesky/beamlines/i04/callbacks/murko_callback.py +27 -12
- mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +87 -13
- mx_bluesky/beamlines/i04/external_interaction/__init__.py +0 -0
- mx_bluesky/beamlines/i04/external_interaction/config_server.py +15 -0
- mx_bluesky/beamlines/i04/oav_centering_plans/__init__.py +0 -0
- mx_bluesky/beamlines/i04/oav_centering_plans/oav_imaging.py +115 -0
- mx_bluesky/beamlines/i04/parameters/__init__.py +0 -0
- mx_bluesky/beamlines/i04/parameters/constants.py +21 -0
- mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +24 -1
- mx_bluesky/beamlines/i04/thawing_plan.py +147 -152
- mx_bluesky/beamlines/i24/serial/dcid.py +4 -5
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_extruder_collect_py3v2.py +5 -2
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/CustomChip_py3v1.edl +11 -11
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DetStage.edl +3 -3
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +142 -142
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/MappingLite-oxford_py3v1.edl +135 -135
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/PMAC_Command.edl +8 -8
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +13 -13
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_chip_collect_py3v1.py +7 -4
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_chip_manager_py3v1.py +35 -32
- mx_bluesky/beamlines/i24/serial/parameters/utils.py +5 -5
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +113 -306
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +8 -2
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +1 -1
- mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +1 -1
- mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py +64 -0
- mx_bluesky/{hyperion/device_setup_plans/smargon.py → common/device_setup_plans/gonio.py} +9 -6
- mx_bluesky/common/device_setup_plans/manipulate_sample.py +8 -1
- mx_bluesky/common/device_setup_plans/robot_load_unload.py +1 -1
- mx_bluesky/common/device_setup_plans/setup_oav.py +8 -0
- mx_bluesky/common/device_setup_plans/setup_zebra_and_shutter.py +0 -5
- mx_bluesky/common/device_setup_plans/xbpm_feedback.py +8 -1
- mx_bluesky/common/experiment_plans/beamstop_check.py +229 -0
- mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py +2 -0
- mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py +5 -2
- mx_bluesky/common/experiment_plans/oav_snapshot_plan.py +0 -1
- mx_bluesky/{hyperion → common}/experiment_plans/pin_tip_centring_plan.py +20 -21
- mx_bluesky/common/external_interaction/callbacks/common/grid_detection_callback.py +5 -0
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +10 -12
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +3 -5
- mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +5 -5
- mx_bluesky/common/external_interaction/config_server.py +2 -2
- mx_bluesky/common/external_interaction/ispyb/data_model.py +11 -4
- mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +159 -2
- mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +76 -166
- mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py +0 -14
- mx_bluesky/common/parameters/components.py +1 -0
- mx_bluesky/common/parameters/constants.py +3 -2
- mx_bluesky/common/parameters/device_composites.py +4 -2
- mx_bluesky/common/utils/exceptions.py +15 -0
- mx_bluesky/common/utils/log.py +9 -0
- mx_bluesky/common/utils/utils.py +48 -0
- mx_bluesky/hyperion/__main__.py +3 -13
- mx_bluesky/hyperion/baton_handler.py +23 -6
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +5 -6
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +3 -10
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +4 -2
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +8 -2
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/udc_default_state.py +160 -0
- mx_bluesky/hyperion/external_interaction/agamemnon.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +2 -2
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +1 -0
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +1 -4
- mx_bluesky/hyperion/external_interaction/config_server.py +5 -5
- mx_bluesky/hyperion/parameters/constants.py +10 -3
- mx_bluesky/hyperion/parameters/device_composites.py +2 -2
- mx_bluesky/hyperion/parameters/robot_load.py +1 -9
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/METADATA +6 -5
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/RECORD +83 -69
- mx_bluesky/common/experiment_plans/inner_plans/udc_default_state.py +0 -86
- mx_bluesky/common/external_interaction/callbacks/common/logging_callback.py +0 -29
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/WHEEL +0 -0
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/licenses/LICENSE +0 -0
- {mx_bluesky-1.5.11.dist-info → mx_bluesky-1.5.12.dist-info}/top_level.txt +0 -0
|
@@ -6,7 +6,9 @@ from mx_bluesky.common.utils.log import LOGGER
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def unpause_xbpm_feedback_and_set_transmission_to_1(
|
|
9
|
-
xbpm_feedback: XBPMFeedback,
|
|
9
|
+
xbpm_feedback: XBPMFeedback,
|
|
10
|
+
attenuator: BinaryFilterAttenuator,
|
|
11
|
+
timeout_for_stable: float = 0,
|
|
10
12
|
):
|
|
11
13
|
"""Turns the XBPM feedback back on and sets transmission to 1 so that it keeps the
|
|
12
14
|
beam aligned whilst not collecting.
|
|
@@ -15,8 +17,13 @@ def unpause_xbpm_feedback_and_set_transmission_to_1(
|
|
|
15
17
|
xbpm_feedback (XBPMFeedback): The XBPM device that is responsible for keeping
|
|
16
18
|
the beam in position
|
|
17
19
|
attenuator (BinaryFilterAttenuator): The attenuator used to set transmission
|
|
20
|
+
timeout_for_stable: If specified and non-zero, specifies the time in seconds to wait for
|
|
21
|
+
feedback to stabilise, otherwise we do not wait.
|
|
18
22
|
"""
|
|
19
23
|
yield from bps.mv(xbpm_feedback.pause_feedback, Pause.RUN, attenuator, 1.0)
|
|
24
|
+
if timeout_for_stable:
|
|
25
|
+
yield from bps.trigger(xbpm_feedback, group="feedback")
|
|
26
|
+
yield from bps.wait(group="feedback", timeout=timeout_for_stable)
|
|
20
27
|
|
|
21
28
|
|
|
22
29
|
def check_and_pause_feedback(
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import pydantic
|
|
2
|
+
from bluesky import plan_stubs as bps
|
|
3
|
+
from bluesky.utils import MsgGenerator
|
|
4
|
+
from dodal.common.beamlines.beamline_parameters import GDABeamlineParameters
|
|
5
|
+
from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureValue
|
|
6
|
+
from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
|
|
7
|
+
from dodal.devices.backlight import Backlight
|
|
8
|
+
from dodal.devices.baton import Baton
|
|
9
|
+
from dodal.devices.detector.detector_motion import DetectorMotion, ShutterState
|
|
10
|
+
from dodal.devices.ipin import IPin, IPinGain
|
|
11
|
+
from dodal.devices.mx_phase1.beamstop import Beamstop, BeamstopPositions
|
|
12
|
+
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
13
|
+
from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter, ZebraShutterState
|
|
14
|
+
from ophyd_async.core import InOut
|
|
15
|
+
|
|
16
|
+
from mx_bluesky.common.device_setup_plans.xbpm_feedback import (
|
|
17
|
+
unpause_xbpm_feedback_and_set_transmission_to_1,
|
|
18
|
+
)
|
|
19
|
+
from mx_bluesky.common.utils.exceptions import BeamlineCheckFailureError
|
|
20
|
+
from mx_bluesky.common.utils.log import LOGGER
|
|
21
|
+
|
|
22
|
+
_GROUP_PRE_BEAMSTOP_OUT_CHECK = "pre_background_check"
|
|
23
|
+
_GROUP_POST_BEAMSTOP_OUT_CHECK = "post_background_check"
|
|
24
|
+
_PARAM_IPIN_THRESHOLD = "ipin_threshold"
|
|
25
|
+
|
|
26
|
+
_FEEDBACK_TIMEOUT_S = 10
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
30
|
+
class BeamstopCheckDevices:
|
|
31
|
+
aperture_scatterguard: ApertureScatterguard
|
|
32
|
+
attenuator: BinaryFilterAttenuator
|
|
33
|
+
backlight: Backlight
|
|
34
|
+
baton: Baton
|
|
35
|
+
beamstop: Beamstop
|
|
36
|
+
detector_motion: DetectorMotion
|
|
37
|
+
ipin: IPin
|
|
38
|
+
sample_shutter: ZebraShutter
|
|
39
|
+
xbpm_feedback: XBPMFeedback
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SampleCurrentBelowThresholdError(BeamlineCheckFailureError): ...
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class BeamstopNotInPositionError(BeamlineCheckFailureError): ...
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class BeamObstructedError(BeamlineCheckFailureError): ...
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def move_beamstop_in_and_verify_using_diode(
|
|
52
|
+
devices: BeamstopCheckDevices,
|
|
53
|
+
beamline_parameters: GDABeamlineParameters,
|
|
54
|
+
detector_min_z_mm: float,
|
|
55
|
+
detector_max_z_mm: float,
|
|
56
|
+
) -> MsgGenerator:
|
|
57
|
+
"""
|
|
58
|
+
Move the beamstop into the data collection position, checking the beam current
|
|
59
|
+
via the diode on the detector shutter, first with the beamstop out and then with
|
|
60
|
+
the beamstop in.
|
|
61
|
+
These checks aim to ensure that
|
|
62
|
+
* The beam is not obstructed by something other than the beamstop
|
|
63
|
+
* The beamstop has been successfully moved and is intercepting the beam
|
|
64
|
+
|
|
65
|
+
As a side-effect, this plan also does the following things:
|
|
66
|
+
* Move the detector z-axis in range
|
|
67
|
+
* Move the backlight out
|
|
68
|
+
* Unpauses feedback
|
|
69
|
+
* Sets xmission to 100%
|
|
70
|
+
* Sets IPin gain to 10^4 low noise
|
|
71
|
+
* Moves aperture scatterguard to OUT_OF_BEAM if it is currently in beam
|
|
72
|
+
|
|
73
|
+
Implementation note:
|
|
74
|
+
Some checks are repeated here such as closing the sample shutter, so that at a
|
|
75
|
+
future point this plan may be run independently of the udc default state script
|
|
76
|
+
if desired.
|
|
77
|
+
Note on commissioning mode:
|
|
78
|
+
When commissioning mode is enabled, the beamstop check will execute normally except
|
|
79
|
+
where it expects beam to be present, the absence of beam will be ignored.
|
|
80
|
+
Args:
|
|
81
|
+
devices: The device composite containing the necessary devices
|
|
82
|
+
beamline_parameters: A mapping containing the beamlineParameters
|
|
83
|
+
detector_min_z_mm: Detector minimum distance at which beamstop is effective
|
|
84
|
+
detector_max_z_mm: Detector maximum distance at which beamstop is effective
|
|
85
|
+
Raises:
|
|
86
|
+
SampleCurrentBelowThresholdError: If we do not have sufficient sample current to perform
|
|
87
|
+
the check.
|
|
88
|
+
BeamstopNotInPositionError: If the ipin current is too high, indicating that the
|
|
89
|
+
beamstop is not in the correct position.
|
|
90
|
+
BeamObstructedError: If the ipin current is too low after the first check
|
|
91
|
+
with the beamstop out, indicating a likely obstruction.
|
|
92
|
+
"""
|
|
93
|
+
LOGGER.info("Performing beamstop check...")
|
|
94
|
+
commissioning_mode_enabled = yield from bps.rd(devices.baton.commissioning)
|
|
95
|
+
beamstop_threshold_uA = beamline_parameters[_PARAM_IPIN_THRESHOLD] # noqa: N806
|
|
96
|
+
|
|
97
|
+
yield from _start_moving_detector_if_needed(
|
|
98
|
+
devices, detector_min_z_mm, detector_max_z_mm, _GROUP_POST_BEAMSTOP_OUT_CHECK
|
|
99
|
+
)
|
|
100
|
+
yield from _pre_beamstop_out_check_actions(devices)
|
|
101
|
+
yield from _beamstop_out_check(
|
|
102
|
+
devices, beamstop_threshold_uA, commissioning_mode_enabled
|
|
103
|
+
)
|
|
104
|
+
yield from _post_beamstop_out_check_actions(devices, _GROUP_POST_BEAMSTOP_OUT_CHECK)
|
|
105
|
+
yield from _beamstop_in_check(devices, beamstop_threshold_uA)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _pre_beamstop_out_check_actions(devices: BeamstopCheckDevices):
|
|
109
|
+
# Re-verify that the sample shutter is closed
|
|
110
|
+
yield from bps.abs_set(devices.sample_shutter, ZebraShutterState.CLOSE, wait=True)
|
|
111
|
+
LOGGER.info("Unpausing feedback, transmission to 100%, wait for feedback stable...")
|
|
112
|
+
try:
|
|
113
|
+
yield from unpause_xbpm_feedback_and_set_transmission_to_1(
|
|
114
|
+
devices.xbpm_feedback,
|
|
115
|
+
devices.attenuator,
|
|
116
|
+
_FEEDBACK_TIMEOUT_S,
|
|
117
|
+
)
|
|
118
|
+
except TimeoutError as e:
|
|
119
|
+
raise SampleCurrentBelowThresholdError(
|
|
120
|
+
"Unable to perform beamstop check - xbpm feedback did not become stable "
|
|
121
|
+
" - check if beam present?"
|
|
122
|
+
) from e
|
|
123
|
+
|
|
124
|
+
yield from bps.abs_set(
|
|
125
|
+
devices.backlight, InOut.OUT, group=_GROUP_PRE_BEAMSTOP_OUT_CHECK
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
yield from bps.abs_set(
|
|
129
|
+
devices.aperture_scatterguard.selected_aperture,
|
|
130
|
+
ApertureValue.OUT_OF_BEAM,
|
|
131
|
+
group=_GROUP_PRE_BEAMSTOP_OUT_CHECK,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
yield from bps.abs_set(
|
|
135
|
+
devices.ipin.gain,
|
|
136
|
+
IPinGain.GAIN_10E4_LOW_NOISE,
|
|
137
|
+
group=_GROUP_PRE_BEAMSTOP_OUT_CHECK,
|
|
138
|
+
)
|
|
139
|
+
yield from bps.abs_set(
|
|
140
|
+
devices.detector_motion.shutter,
|
|
141
|
+
ShutterState.CLOSED,
|
|
142
|
+
group=_GROUP_PRE_BEAMSTOP_OUT_CHECK,
|
|
143
|
+
)
|
|
144
|
+
yield from bps.abs_set(
|
|
145
|
+
devices.beamstop.selected_pos,
|
|
146
|
+
BeamstopPositions.OUT_OF_BEAM,
|
|
147
|
+
group=_GROUP_PRE_BEAMSTOP_OUT_CHECK,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
LOGGER.info("Waiting for pre-background-check motions to complete...")
|
|
151
|
+
yield from bps.wait(group=_GROUP_PRE_BEAMSTOP_OUT_CHECK)
|
|
152
|
+
|
|
153
|
+
# Check detector shutter is closed
|
|
154
|
+
detector_shutter_state = yield from bps.rd(devices.detector_motion.shutter)
|
|
155
|
+
detector_shutter_is_closed = detector_shutter_state == ShutterState.CLOSED
|
|
156
|
+
if not detector_shutter_is_closed:
|
|
157
|
+
raise RuntimeError(
|
|
158
|
+
"Unable to proceed with beamstop background check, detector shutter did not close"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _start_moving_detector_if_needed(
|
|
163
|
+
devices: BeamstopCheckDevices,
|
|
164
|
+
detector_min_z_mm: float,
|
|
165
|
+
detector_max_z_mm: float,
|
|
166
|
+
group: str = None,
|
|
167
|
+
):
|
|
168
|
+
detector_current_z = yield from bps.rd(devices.detector_motion.z)
|
|
169
|
+
target_z = max(min(detector_current_z, detector_max_z_mm), detector_min_z_mm)
|
|
170
|
+
if detector_current_z != target_z:
|
|
171
|
+
LOGGER.info(
|
|
172
|
+
f"Detector distance {detector_current_z}mm outside acceptable range for diode "
|
|
173
|
+
f"check {detector_min_z_mm} <= z <= {detector_max_z_mm}, moving it."
|
|
174
|
+
)
|
|
175
|
+
yield from bps.abs_set(devices.detector_motion.z, target_z, group=group)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _post_beamstop_out_check_actions(devices: BeamstopCheckDevices, group: str):
|
|
179
|
+
yield from bps.abs_set(
|
|
180
|
+
devices.beamstop.selected_pos,
|
|
181
|
+
BeamstopPositions.DATA_COLLECTION,
|
|
182
|
+
group=group,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
LOGGER.info("Waiting for detector motion to complete...")
|
|
186
|
+
yield from bps.wait(group=group)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _beamstop_out_check(
|
|
190
|
+
devices: BeamstopCheckDevices,
|
|
191
|
+
beamstop_threshold_uA: float, # noqa: N803
|
|
192
|
+
commissioning_mode_enabled: bool,
|
|
193
|
+
):
|
|
194
|
+
ipin_beamstop_out_uA = yield from _check_ipin(devices) # noqa: N806
|
|
195
|
+
|
|
196
|
+
LOGGER.info(f"Beamstop out ipin = {ipin_beamstop_out_uA}uA")
|
|
197
|
+
if ipin_beamstop_out_uA < beamstop_threshold_uA:
|
|
198
|
+
msg = (
|
|
199
|
+
f"IPin current {ipin_beamstop_out_uA}uA below threshold "
|
|
200
|
+
f"{beamstop_threshold_uA} with beamstop out - check "
|
|
201
|
+
f"that beam is not obstructed."
|
|
202
|
+
)
|
|
203
|
+
if commissioning_mode_enabled:
|
|
204
|
+
LOGGER.warning(msg + " - commissioning mode enabled - ignoring this")
|
|
205
|
+
else:
|
|
206
|
+
raise BeamObstructedError(msg)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _beamstop_in_check(devices: BeamstopCheckDevices, beamstop_threshold_uA: float): # noqa: N803
|
|
210
|
+
ipin_in_beam_uA = yield from _check_ipin(devices) # noqa: N806
|
|
211
|
+
if ipin_in_beam_uA > beamstop_threshold_uA:
|
|
212
|
+
raise BeamstopNotInPositionError(
|
|
213
|
+
f"Ipin is too high at {ipin_in_beam_uA} - check that beamstop is "
|
|
214
|
+
f"in the correct position."
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _check_ipin(devices: BeamstopCheckDevices):
|
|
219
|
+
try:
|
|
220
|
+
yield from bps.abs_set(
|
|
221
|
+
devices.sample_shutter, ZebraShutterState.OPEN, wait=True
|
|
222
|
+
)
|
|
223
|
+
yield from bps.sleep(1) # wait for reading to settle
|
|
224
|
+
|
|
225
|
+
return (yield from bps.rd(devices.ipin.pin_readback)) # noqa: N806
|
|
226
|
+
finally:
|
|
227
|
+
yield from bps.abs_set(
|
|
228
|
+
devices.sample_shutter, ZebraShutterState.CLOSE, wait=True
|
|
229
|
+
)
|
|
@@ -279,6 +279,8 @@ def run_gridscan(
|
|
|
279
279
|
raise SampleError(
|
|
280
280
|
"Scan invalid - gridscan not valid for detected pin position"
|
|
281
281
|
) from e
|
|
282
|
+
else:
|
|
283
|
+
raise e
|
|
282
284
|
|
|
283
285
|
LOGGER.info("Waiting for arming to finish")
|
|
284
286
|
yield from bps.wait(PlanGroupCheckpointConstants.GRID_READY_FOR_DC)
|
|
@@ -4,13 +4,14 @@ import bluesky.plan_stubs as bps
|
|
|
4
4
|
from bluesky.protocols import Readable
|
|
5
5
|
from dodal.devices.aperturescatterguard import ApertureScatterguard
|
|
6
6
|
from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
|
|
7
|
+
from dodal.devices.beamsize.beamsize import BeamsizeBase
|
|
7
8
|
from dodal.devices.common_dcm import DoubleCrystalMonochromator
|
|
8
9
|
from dodal.devices.eiger import EigerDetector
|
|
9
10
|
from dodal.devices.flux import Flux
|
|
10
11
|
from dodal.devices.s4_slit_gaps import S4SlitGaps
|
|
11
12
|
from dodal.devices.smargon import Smargon
|
|
12
13
|
from dodal.devices.synchrotron import Synchrotron
|
|
13
|
-
from dodal.devices.undulator import
|
|
14
|
+
from dodal.devices.undulator import UndulatorInKeV
|
|
14
15
|
|
|
15
16
|
from mx_bluesky.common.parameters.constants import (
|
|
16
17
|
DocDescriptorNames,
|
|
@@ -40,7 +41,7 @@ def read_hardware_for_zocalo(detector: EigerDetector):
|
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
def standard_read_hardware_pre_collection(
|
|
43
|
-
undulator:
|
|
44
|
+
undulator: UndulatorInKeV,
|
|
44
45
|
synchrotron: Synchrotron,
|
|
45
46
|
s4_slit_gaps: S4SlitGaps,
|
|
46
47
|
dcm: DoubleCrystalMonochromator,
|
|
@@ -65,6 +66,7 @@ def standard_read_hardware_during_collection(
|
|
|
65
66
|
flux: Flux,
|
|
66
67
|
dcm: DoubleCrystalMonochromator,
|
|
67
68
|
detector: EigerDetector,
|
|
69
|
+
beamsize: BeamsizeBase,
|
|
68
70
|
):
|
|
69
71
|
signals_to_read_during_collection = [
|
|
70
72
|
aperture_scatterguard,
|
|
@@ -72,6 +74,7 @@ def standard_read_hardware_during_collection(
|
|
|
72
74
|
flux.flux_reading,
|
|
73
75
|
dcm.energy_in_keV,
|
|
74
76
|
detector.bit_depth,
|
|
77
|
+
beamsize,
|
|
75
78
|
]
|
|
76
79
|
yield from read_hardware_plan(
|
|
77
80
|
signals_to_read_during_collection, DocDescriptorNames.HARDWARE_READ_DURING
|
|
@@ -4,7 +4,7 @@ import bluesky.plan_stubs as bps
|
|
|
4
4
|
import pydantic
|
|
5
5
|
from blueapi.core import BlueskyContext
|
|
6
6
|
from bluesky.utils import Msg
|
|
7
|
-
from dodal.devices.
|
|
7
|
+
from dodal.devices.motors import XYZOmegaStage
|
|
8
8
|
from dodal.devices.oav.oav_detector import OAV
|
|
9
9
|
from dodal.devices.oav.oav_parameters import OAV_CONFIG_JSON, OAVParameters
|
|
10
10
|
from dodal.devices.oav.pin_image_recognition import PinTipDetection, Tip
|
|
@@ -14,27 +14,26 @@ from dodal.devices.oav.utils import (
|
|
|
14
14
|
get_move_required_so_that_beam_is_at_pixel,
|
|
15
15
|
wait_for_tip_to_be_found,
|
|
16
16
|
)
|
|
17
|
-
from dodal.devices.smargon import Smargon
|
|
18
17
|
|
|
18
|
+
from mx_bluesky.common.device_setup_plans.gonio import (
|
|
19
|
+
move_gonio_warn_on_out_of_range,
|
|
20
|
+
)
|
|
19
21
|
from mx_bluesky.common.device_setup_plans.setup_oav import pre_centring_setup_oav
|
|
22
|
+
from mx_bluesky.common.parameters.constants import HardwareConstants
|
|
20
23
|
from mx_bluesky.common.utils.context import device_composite_from_context
|
|
21
24
|
from mx_bluesky.common.utils.exceptions import SampleError, catch_exception_and_warn
|
|
22
25
|
from mx_bluesky.common.utils.log import LOGGER
|
|
23
|
-
from mx_bluesky.hyperion.device_setup_plans.smargon import (
|
|
24
|
-
move_smargon_warn_on_out_of_range,
|
|
25
|
-
)
|
|
26
|
-
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
27
26
|
|
|
28
27
|
DEFAULT_STEP_SIZE = 0.5
|
|
28
|
+
CONST = HardwareConstants()
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
32
32
|
class PinTipCentringComposite:
|
|
33
33
|
"""All devices which are directly or indirectly required by this plan"""
|
|
34
34
|
|
|
35
|
-
backlight: Backlight
|
|
36
35
|
oav: OAV
|
|
37
|
-
|
|
36
|
+
gonio: XYZOmegaStage
|
|
38
37
|
pin_tip_detection: PinTipDetection
|
|
39
38
|
|
|
40
39
|
|
|
@@ -53,7 +52,7 @@ def trigger_and_return_pin_tip(
|
|
|
53
52
|
|
|
54
53
|
def move_pin_into_view(
|
|
55
54
|
pin_tip_device: PinTipDetection,
|
|
56
|
-
|
|
55
|
+
gonio: XYZOmegaStage,
|
|
57
56
|
step_magnitude_mm: float = DEFAULT_STEP_SIZE,
|
|
58
57
|
max_steps: int = 2,
|
|
59
58
|
) -> Generator[Msg, None, Pixel]:
|
|
@@ -63,7 +62,7 @@ def move_pin_into_view(
|
|
|
63
62
|
|
|
64
63
|
Args:
|
|
65
64
|
pin_tip_device (PinTipDetection): The device being used to detect the pin
|
|
66
|
-
|
|
65
|
+
gonio (XYZOmegaStage): The stage(gonio) to move the tip
|
|
67
66
|
step_magnitude_mm (float, optional): Distance to move the gonio (in mm) for each
|
|
68
67
|
step of the search. Defaults to 0.5.
|
|
69
68
|
max_steps (int, optional): The number of steps to search with. Defaults to 2.
|
|
@@ -88,20 +87,20 @@ def move_pin_into_view(
|
|
|
88
87
|
direction_multiple = -1 if tip_xy_px[0] == 0 else 1
|
|
89
88
|
step_vector_mm = step_magnitude_mm * direction_multiple
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
ideal_move_to_find_pin = float(
|
|
93
|
-
high_limit = yield from bps.rd(
|
|
94
|
-
low_limit = yield from bps.rd(
|
|
90
|
+
stage_x = yield from bps.rd(gonio.x.user_readback)
|
|
91
|
+
ideal_move_to_find_pin = float(stage_x) + step_vector_mm
|
|
92
|
+
high_limit = yield from bps.rd(gonio.x.high_limit_travel)
|
|
93
|
+
low_limit = yield from bps.rd(gonio.x.low_limit_travel)
|
|
95
94
|
move_within_limits = max(min(ideal_move_to_find_pin, high_limit), low_limit)
|
|
96
95
|
if move_within_limits != ideal_move_to_find_pin:
|
|
97
96
|
LOGGER.warning(
|
|
98
97
|
f"Pin tip is off screen, and moving {step_vector_mm}mm would cross limits, "
|
|
99
98
|
f"moving to {move_within_limits} instead"
|
|
100
99
|
)
|
|
101
|
-
yield from bps.mv(
|
|
100
|
+
yield from bps.mv(gonio.x, move_within_limits)
|
|
102
101
|
|
|
103
102
|
# Some time for the view to settle after the move
|
|
104
|
-
yield from bps.sleep(CONST.
|
|
103
|
+
yield from bps.sleep(CONST.OAV_REFRESH_DELAY)
|
|
105
104
|
|
|
106
105
|
tip_xy_px = yield from trigger_and_return_pin_tip(pin_tip_device)
|
|
107
106
|
|
|
@@ -127,7 +126,7 @@ def pin_tip_centre_plan(
|
|
|
127
126
|
to be.
|
|
128
127
|
"""
|
|
129
128
|
oav: OAV = composite.oav
|
|
130
|
-
|
|
129
|
+
gonio: XYZOmegaStage = composite.gonio
|
|
131
130
|
oav_params = OAVParameters("pinTipCentring", oav_config_file)
|
|
132
131
|
|
|
133
132
|
pin_tip_setup = composite.pin_tip_detection
|
|
@@ -139,10 +138,10 @@ def pin_tip_centre_plan(
|
|
|
139
138
|
def offset_and_move(tip: Pixel):
|
|
140
139
|
pixel_to_move_to = (tip[0] + tip_offset_px, tip[1])
|
|
141
140
|
position_mm = yield from get_move_required_so_that_beam_is_at_pixel(
|
|
142
|
-
|
|
141
|
+
gonio, pixel_to_move_to, oav
|
|
143
142
|
)
|
|
144
143
|
LOGGER.info(f"Tip centring moving to : {position_mm}")
|
|
145
|
-
yield from
|
|
144
|
+
yield from move_gonio_warn_on_out_of_range(gonio, position_mm)
|
|
146
145
|
|
|
147
146
|
LOGGER.info(f"Tip offset in pixels: {tip_offset_px}")
|
|
148
147
|
|
|
@@ -152,10 +151,10 @@ def pin_tip_centre_plan(
|
|
|
152
151
|
|
|
153
152
|
yield from pre_centring_setup_oav(oav, oav_params, pin_tip_setup)
|
|
154
153
|
|
|
155
|
-
tip = yield from move_pin_into_view(pin_tip_detect,
|
|
154
|
+
tip = yield from move_pin_into_view(pin_tip_detect, gonio)
|
|
156
155
|
yield from offset_and_move(tip)
|
|
157
156
|
|
|
158
|
-
yield from bps.mvr(
|
|
157
|
+
yield from bps.mvr(gonio.omega, -90)
|
|
159
158
|
|
|
160
159
|
# need to wait for the OAV image to update
|
|
161
160
|
# See #673 for improvements
|
|
@@ -83,12 +83,17 @@ class GridDetectionCallback(CallbackBase):
|
|
|
83
83
|
beam_x = data["oav-beam_centre_i"]
|
|
84
84
|
beam_y = data["oav-beam_centre_j"]
|
|
85
85
|
|
|
86
|
+
x_direction = data["oav-x_direction"]
|
|
87
|
+
y_direction = data["oav-y_direction"]
|
|
88
|
+
z_direction = data["oav-z_direction"]
|
|
89
|
+
|
|
86
90
|
position_grid_start_mm = calculate_x_y_z_of_pixel(
|
|
87
91
|
current_xyz,
|
|
88
92
|
smargon_omega,
|
|
89
93
|
centre_of_first_box,
|
|
90
94
|
(beam_x, beam_y),
|
|
91
95
|
(microns_per_pixel_x, microns_per_pixel_y),
|
|
96
|
+
(x_direction, y_direction, z_direction),
|
|
92
97
|
)
|
|
93
98
|
LOGGER.info(f"Calculated start position {position_grid_start_mm}")
|
|
94
99
|
|
|
@@ -5,14 +5,10 @@ from collections.abc import Callable, Sequence
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import TYPE_CHECKING, Any, TypeVar, cast
|
|
7
7
|
|
|
8
|
-
from dodal.beamline_specific_utils.i03 import beam_size_from_aperture
|
|
9
8
|
from dodal.devices.detector import DetectorParams
|
|
10
9
|
from dodal.devices.detector.det_resolution import resolution
|
|
11
10
|
from dodal.devices.synchrotron import SynchrotronMode
|
|
12
11
|
|
|
13
|
-
from mx_bluesky.common.external_interaction.callbacks.common.logging_callback import (
|
|
14
|
-
format_doc_for_log,
|
|
15
|
-
)
|
|
16
12
|
from mx_bluesky.common.external_interaction.callbacks.common.plan_reactive_callback import (
|
|
17
13
|
PlanReactiveCallback,
|
|
18
14
|
)
|
|
@@ -28,7 +24,11 @@ from mx_bluesky.common.external_interaction.ispyb.ispyb_store import (
|
|
|
28
24
|
from mx_bluesky.common.external_interaction.ispyb.ispyb_utils import get_ispyb_config
|
|
29
25
|
from mx_bluesky.common.parameters.components import DiffractionExperimentWithSample
|
|
30
26
|
from mx_bluesky.common.parameters.constants import DocDescriptorNames
|
|
31
|
-
from mx_bluesky.common.utils.log import
|
|
27
|
+
from mx_bluesky.common.utils.log import (
|
|
28
|
+
ISPYB_ZOCALO_CALLBACK_LOGGER,
|
|
29
|
+
format_doc_for_log,
|
|
30
|
+
set_dcgid_tag,
|
|
31
|
+
)
|
|
32
32
|
from mx_bluesky.common.utils.utils import convert_ev_to_angstrom
|
|
33
33
|
|
|
34
34
|
D = TypeVar("D")
|
|
@@ -147,18 +147,16 @@ class BaseISPyBCallback(PlanReactiveCallback):
|
|
|
147
147
|
)
|
|
148
148
|
return scan_data_infos
|
|
149
149
|
|
|
150
|
-
def _handle_ispyb_transmission_flux_read(
|
|
150
|
+
def _handle_ispyb_transmission_flux_read(
|
|
151
|
+
self, doc: Event
|
|
152
|
+
) -> Sequence[ScanDataInfo]:
|
|
151
153
|
assert self.params
|
|
152
154
|
aperture = doc["data"]["aperture_scatterguard-selected_aperture"]
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
beamsize_x_mm = beamsize.x_um / 1000 if beamsize.x_um else None
|
|
156
|
-
beamsize_y_mm = beamsize.y_um / 1000 if beamsize.y_um else None
|
|
155
|
+
beamsize_x_mm = doc["data"]["beamsize-x_um"] / 1000
|
|
156
|
+
beamsize_y_mm = doc["data"]["beamsize-y_um"] / 1000
|
|
157
157
|
hwscan_data_collection_info = DataCollectionInfo(
|
|
158
158
|
beamsize_at_samplex=beamsize_x_mm,
|
|
159
159
|
beamsize_at_sampley=beamsize_y_mm,
|
|
160
|
-
focal_spot_size_at_samplex=beamsize_x_mm,
|
|
161
|
-
focal_spot_size_at_sampley=beamsize_y_mm,
|
|
162
160
|
flux=doc["data"]["flux-flux_reading"],
|
|
163
161
|
)
|
|
164
162
|
if transmission := doc["data"]["attenuator-actual_transmission"]:
|
|
@@ -4,15 +4,14 @@ from mx_bluesky.common.external_interaction.ispyb.data_model import (
|
|
|
4
4
|
DataCollectionGroupInfo,
|
|
5
5
|
DataCollectionInfo,
|
|
6
6
|
)
|
|
7
|
-
from mx_bluesky.common.external_interaction.ispyb.ispyb_store import (
|
|
8
|
-
EIGER_FILE_SUFFIX,
|
|
9
|
-
I03_EIGER_DETECTOR,
|
|
10
|
-
)
|
|
11
7
|
from mx_bluesky.common.external_interaction.ispyb.ispyb_utils import (
|
|
12
8
|
get_current_time_string,
|
|
13
9
|
)
|
|
14
10
|
from mx_bluesky.common.parameters.components import DiffractionExperimentWithSample
|
|
15
11
|
|
|
12
|
+
I03_EIGER_DETECTOR = 78
|
|
13
|
+
EIGER_FILE_SUFFIX = "h5"
|
|
14
|
+
|
|
16
15
|
|
|
17
16
|
def populate_data_collection_group(params: DiffractionExperimentWithSample):
|
|
18
17
|
dcg_info = DataCollectionGroupInfo(
|
|
@@ -31,7 +30,6 @@ def populate_remaining_data_collection_info(
|
|
|
31
30
|
):
|
|
32
31
|
data_collection_info.visit_string = params.visit
|
|
33
32
|
data_collection_info.parent_id = data_collection_group_id
|
|
34
|
-
data_collection_info.sample_id = params.sample_id
|
|
35
33
|
data_collection_info.detector_id = I03_EIGER_DETECTOR
|
|
36
34
|
data_collection_info.comments = comment
|
|
37
35
|
data_collection_info.detector_distance = params.detector_params.detector_distance
|
|
@@ -240,7 +240,7 @@ class GridscanISPyBCallback(BaseISPyBCallback):
|
|
|
240
240
|
f"{y_steps} by {z_steps}."
|
|
241
241
|
)
|
|
242
242
|
|
|
243
|
-
self._populate_axis_info(data_collection_info,
|
|
243
|
+
self._populate_axis_info(data_collection_info, doc["data"])
|
|
244
244
|
|
|
245
245
|
scan_data_info = ScanDataInfo(
|
|
246
246
|
data_collection_info=data_collection_info,
|
|
@@ -254,15 +254,15 @@ class GridscanISPyBCallback(BaseISPyBCallback):
|
|
|
254
254
|
self._oav_snapshot_event_idx += 1
|
|
255
255
|
return [scan_data_info]
|
|
256
256
|
|
|
257
|
-
def _populate_axis_info(
|
|
258
|
-
|
|
259
|
-
):
|
|
260
|
-
if omega_start is not None:
|
|
257
|
+
def _populate_axis_info(self, data_collection_info: DataCollectionInfo, doc: dict):
|
|
258
|
+
if (omega_start := doc.get("smargon-omega")) is not None:
|
|
261
259
|
omega_in_gda_space = -omega_start
|
|
262
260
|
data_collection_info.omega_start = omega_in_gda_space
|
|
263
261
|
data_collection_info.axis_start = omega_in_gda_space
|
|
264
262
|
data_collection_info.axis_end = omega_in_gda_space
|
|
265
263
|
data_collection_info.axis_range = 0
|
|
264
|
+
if (chi_start := doc.get("smargon-chi")) is not None:
|
|
265
|
+
data_collection_info.chi_start = chi_start
|
|
266
266
|
|
|
267
267
|
def populate_info_for_update(
|
|
268
268
|
self,
|
|
@@ -9,7 +9,7 @@ from pydantic import TypeAdapter
|
|
|
9
9
|
|
|
10
10
|
from mx_bluesky.common.parameters.constants import (
|
|
11
11
|
GDA_DOMAIN_PROPERTIES_PATH,
|
|
12
|
-
|
|
12
|
+
FeatureSettings,
|
|
13
13
|
FeatureSettingSources,
|
|
14
14
|
OavConstants,
|
|
15
15
|
)
|
|
@@ -19,7 +19,7 @@ FEATURE_FLAG_CACHE_LENGTH_S = 60 * 5
|
|
|
19
19
|
# Used by the config server when refreshing its cache
|
|
20
20
|
_JSON_CONFIG_PATHS = [OavConstants.OAV_CONFIG_JSON]
|
|
21
21
|
|
|
22
|
-
T = TypeVar("T", bound=
|
|
22
|
+
T = TypeVar("T", bound=FeatureSettings)
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class MXConfigClient(ConfigServer, Generic[T]):
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO replace these with autogenerated schema classes from the ExpEye API
|
|
3
|
+
https://github.com/DiamondLightSource/mx-bluesky/issues/1419
|
|
4
|
+
"""
|
|
5
|
+
|
|
1
6
|
from dataclasses import asdict, dataclass
|
|
2
7
|
from enum import Enum
|
|
3
8
|
|
|
@@ -18,6 +23,9 @@ class DataCollectionGroupInfo:
|
|
|
18
23
|
|
|
19
24
|
@dataclass(kw_only=True)
|
|
20
25
|
class DataCollectionInfo:
|
|
26
|
+
# This is used internally to keep track of the DataCollectionGroup ID
|
|
27
|
+
parent_id: int | None = None
|
|
28
|
+
|
|
21
29
|
omega_start: float | None = None
|
|
22
30
|
data_collection_number: int | None = None
|
|
23
31
|
xtal_snapshot1: str | None = None
|
|
@@ -28,15 +36,12 @@ class DataCollectionInfo:
|
|
|
28
36
|
n_images: int | None = None
|
|
29
37
|
axis_range: float | None = None
|
|
30
38
|
axis_end: float | None = None
|
|
39
|
+
chi_start: float | None = None
|
|
31
40
|
kappa_start: float | None = None
|
|
32
41
|
|
|
33
|
-
parent_id: int | None = None
|
|
34
42
|
visit_string: str | None = None
|
|
35
|
-
sample_id: int | None = None
|
|
36
43
|
detector_id: int | None = None
|
|
37
44
|
axis_start: float | None = None
|
|
38
|
-
focal_spot_size_at_samplex: float | None = None
|
|
39
|
-
focal_spot_size_at_sampley: float | None = None
|
|
40
45
|
slitgap_vertical: float | None = None
|
|
41
46
|
slitgap_horizontal: float | None = None
|
|
42
47
|
beamsize_at_samplex: float | None = None
|
|
@@ -60,6 +65,8 @@ class DataCollectionInfo:
|
|
|
60
65
|
synchrotron_mode: str | None = None
|
|
61
66
|
undulator_gap1: float | None = None
|
|
62
67
|
start_time: str | None = None
|
|
68
|
+
end_time: str | None = None
|
|
69
|
+
run_status: str | None = None
|
|
63
70
|
|
|
64
71
|
|
|
65
72
|
@dataclass
|