mx-bluesky 1.4.6__py3-none-any.whl → 1.4.8__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.
Files changed (95) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/aithre_lasershaping/__init__.py +13 -0
  3. mx_bluesky/beamlines/aithre_lasershaping/check_goniometer_performance.py +29 -0
  4. mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py +18 -0
  5. mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +35 -29
  6. mx_bluesky/beamlines/i04/thawing_plan.py +18 -3
  7. mx_bluesky/beamlines/i23/__init__.py +3 -0
  8. mx_bluesky/beamlines/i23/serial.py +71 -0
  9. mx_bluesky/beamlines/i24/serial/__init__.py +2 -0
  10. mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +12 -12
  11. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +36 -30
  12. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +3 -3
  13. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +15 -66
  14. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +8 -10
  15. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +10 -3
  16. mx_bluesky/beamlines/i24/serial/log.py +9 -9
  17. mx_bluesky/beamlines/i24/serial/parameters/utils.py +36 -7
  18. mx_bluesky/beamlines/i24/serial/set_visit_directory.sh +1 -1
  19. mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +16 -17
  20. mx_bluesky/beamlines/i24/serial/setup_beamline/pv_abstract.py +4 -4
  21. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +51 -52
  22. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +3 -2
  23. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +9 -7
  24. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +71 -11
  25. mx_bluesky/beamlines/i24/serial/write_nexus.py +6 -5
  26. mx_bluesky/{hyperion → common}/device_setup_plans/check_beamstop.py +1 -1
  27. mx_bluesky/{hyperion → common}/device_setup_plans/manipulate_sample.py +1 -1
  28. mx_bluesky/{hyperion → common}/device_setup_plans/setup_oav.py +12 -6
  29. mx_bluesky/common/device_setup_plans/xbpm_feedback.py +45 -0
  30. mx_bluesky/{hyperion → common}/experiment_plans/change_aperture_then_move_plan.py +13 -29
  31. mx_bluesky/{hyperion → common}/experiment_plans/oav_grid_detection_plan.py +6 -6
  32. mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +8 -9
  33. mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +1 -1
  34. mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py +18 -15
  35. mx_bluesky/{hyperion → common}/external_interaction/callbacks/sample_handling/sample_handling_callback.py +16 -4
  36. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +50 -45
  37. mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py +2 -1
  38. mx_bluesky/common/external_interaction/ispyb/data_model.py +1 -0
  39. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +18 -2
  40. mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py +4 -4
  41. mx_bluesky/common/external_interaction/nexus/nexus_utils.py +1 -1
  42. mx_bluesky/common/parameters/components.py +22 -2
  43. mx_bluesky/common/parameters/constants.py +6 -16
  44. mx_bluesky/common/parameters/gridscan.py +36 -32
  45. mx_bluesky/common/plans/common_flyscan_xray_centre_plan.py +316 -0
  46. mx_bluesky/common/plans/inner_plans/__init__ .py +0 -0
  47. mx_bluesky/common/plans/read_hardware.py +3 -3
  48. mx_bluesky/common/plans/write_sample_status.py +46 -0
  49. mx_bluesky/common/preprocessors/__init__.py +0 -0
  50. mx_bluesky/common/preprocessors/preprocessors.py +105 -0
  51. mx_bluesky/common/protocols/__init__.py +0 -0
  52. mx_bluesky/common/protocols/protocols.py +10 -0
  53. mx_bluesky/common/utils/log.py +15 -12
  54. mx_bluesky/hyperion/__main__.py +5 -24
  55. mx_bluesky/hyperion/baton_handler.py +84 -0
  56. mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +4 -4
  57. mx_bluesky/hyperion/device_setup_plans/setup_panda.py +5 -1
  58. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +0 -33
  59. mx_bluesky/hyperion/device_setup_plans/utils.py +4 -4
  60. mx_bluesky/hyperion/experiment_plans/__init__.py +0 -10
  61. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +0 -16
  62. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +71 -88
  63. mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +183 -0
  64. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +17 -8
  65. mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +29 -8
  66. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +4 -4
  67. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +6 -4
  68. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +11 -3
  69. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +9 -34
  70. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +35 -68
  71. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +27 -8
  72. mx_bluesky/hyperion/external_interaction/agamemnon.py +140 -10
  73. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +17 -9
  74. mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py +259 -0
  75. mx_bluesky/hyperion/parameters/cli.py +2 -10
  76. mx_bluesky/hyperion/parameters/constants.py +0 -5
  77. mx_bluesky/hyperion/parameters/device_composites.py +40 -5
  78. mx_bluesky/hyperion/parameters/gridscan.py +9 -58
  79. mx_bluesky/hyperion/parameters/rotation.py +1 -5
  80. mx_bluesky/hyperion/utils/context.py +2 -5
  81. mx_bluesky/hyperion/utils/validation.py +13 -10
  82. {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/METADATA +10 -9
  83. {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/RECORD +92 -79
  84. {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/WHEEL +1 -1
  85. mx_bluesky/common/external_interaction/callbacks/common/aperture_change_callback.py +0 -22
  86. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +0 -103
  87. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +0 -466
  88. /mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/{short1-laser.png → s1l.png} +0 -0
  89. /mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/{short2-laser.png → s2l.png} +0 -0
  90. /mx_bluesky/{hyperion → common}/device_setup_plans/position_detector.py +0 -0
  91. /mx_bluesky/{hyperion → common}/external_interaction/callbacks/sample_handling/__init__.py +0 -0
  92. /mx_bluesky/common/plans/{do_fgs.py → inner_plans/do_fgs.py} +0 -0
  93. {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/entry_points.txt +0 -0
  94. {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info/licenses}/LICENSE +0 -0
  95. {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/top_level.txt +0 -0
@@ -1,466 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import dataclasses
4
- from collections.abc import Callable, Sequence
5
- from functools import partial
6
- from pathlib import Path
7
- from typing import Protocol
8
-
9
- import bluesky.plan_stubs as bps
10
- import bluesky.preprocessors as bpp
11
- import numpy as np
12
- from blueapi.core import BlueskyContext
13
- from bluesky.utils import MsgGenerator
14
- from dodal.devices.fast_grid_scan import (
15
- FastGridScanCommon,
16
- )
17
- from dodal.devices.fast_grid_scan import (
18
- set_fast_grid_scan_params as set_flyscan_params,
19
- )
20
- from dodal.devices.zebra.zebra import Zebra
21
- from dodal.devices.zocalo.zocalo_results import (
22
- ZOCALO_READING_PLAN_NAME,
23
- ZOCALO_STAGE_GROUP,
24
- XrcResult,
25
- get_full_processing_results,
26
- )
27
-
28
- from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
29
- ispyb_activation_wrapper,
30
- )
31
- from mx_bluesky.common.parameters.constants import HardwareConstants
32
- from mx_bluesky.common.plans.do_fgs import kickoff_and_complete_gridscan
33
- from mx_bluesky.common.plans.read_hardware import (
34
- standard_read_hardware_during_collection,
35
- standard_read_hardware_pre_collection,
36
- )
37
- from mx_bluesky.common.utils.context import device_composite_from_context
38
- from mx_bluesky.common.utils.exceptions import (
39
- CrystalNotFoundException,
40
- SampleException,
41
- )
42
- from mx_bluesky.common.utils.log import LOGGER
43
- from mx_bluesky.common.utils.tracing import TRACER
44
- from mx_bluesky.common.xrc_result import XRayCentreEventHandler, XRayCentreResult
45
- from mx_bluesky.hyperion.device_setup_plans.setup_panda import (
46
- disarm_panda_for_gridscan,
47
- set_panda_directory,
48
- setup_panda_for_flyscan,
49
- )
50
- from mx_bluesky.hyperion.device_setup_plans.setup_zebra import (
51
- setup_zebra_for_gridscan,
52
- setup_zebra_for_panda_flyscan,
53
- tidy_up_zebra_after_gridscan,
54
- )
55
- from mx_bluesky.hyperion.device_setup_plans.xbpm_feedback import (
56
- transmission_and_xbpm_feedback_for_collection_decorator,
57
- )
58
- from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import (
59
- change_aperture_then_move_to_xtal,
60
- )
61
- from mx_bluesky.hyperion.parameters.constants import CONST
62
- from mx_bluesky.hyperion.parameters.device_composites import (
63
- HyperionFlyScanXRayCentreComposite,
64
- )
65
- from mx_bluesky.hyperion.parameters.gridscan import HyperionSpecifiedThreeDGridScan
66
-
67
- ZOCALO_MIN_TOTAL_COUNT_THRESHOLD = 3
68
-
69
-
70
- class SmargonSpeedException(Exception):
71
- pass
72
-
73
-
74
- def create_devices(context: BlueskyContext) -> HyperionFlyScanXRayCentreComposite:
75
- """Creates the devices required for the plan and connect to them"""
76
- return device_composite_from_context(context, HyperionFlyScanXRayCentreComposite)
77
-
78
-
79
- def flyscan_xray_centre_no_move(
80
- composite: HyperionFlyScanXRayCentreComposite,
81
- parameters: HyperionSpecifiedThreeDGridScan,
82
- ) -> MsgGenerator:
83
- """Perform a flyscan and determine the centres of interest"""
84
-
85
- composite.eiger.set_detector_parameters(parameters.detector_params)
86
- composite.zocalo.zocalo_environment = CONST.ZOCALO_ENV
87
-
88
- parameters.features.update_self_from_server()
89
- composite.zocalo.use_cpu_and_gpu = parameters.features.compare_cpu_and_gpu_zocalo
90
- composite.zocalo.use_gpu = parameters.features.use_gpu_results
91
-
92
- feature_controlled = _get_feature_controlled(composite, parameters)
93
-
94
- @bpp.set_run_key_decorator(CONST.PLAN.GRIDSCAN_OUTER)
95
- @bpp.run_decorator( # attach experiment metadata to the start document
96
- md={
97
- "subplan_name": CONST.PLAN.GRIDSCAN_OUTER,
98
- "mx_bluesky_parameters": parameters.model_dump_json(),
99
- "activate_callbacks": [
100
- "GridscanNexusFileCallback",
101
- ],
102
- }
103
- )
104
- @bpp.finalize_decorator(lambda: feature_controlled.tidy_plan(composite))
105
- @transmission_and_xbpm_feedback_for_collection_decorator(
106
- composite.undulator,
107
- composite.xbpm_feedback,
108
- composite.attenuator,
109
- composite.dcm,
110
- parameters.transmission_frac,
111
- )
112
- def run_gridscan_and_fetch_and_tidy(
113
- fgs_composite: HyperionFlyScanXRayCentreComposite,
114
- params: HyperionSpecifiedThreeDGridScan,
115
- feature_controlled: _FeatureControlled,
116
- ) -> MsgGenerator:
117
- yield from run_gridscan_and_fetch_results(
118
- fgs_composite, params, feature_controlled
119
- )
120
-
121
- yield from run_gridscan_and_fetch_and_tidy(
122
- composite, parameters, feature_controlled
123
- )
124
-
125
-
126
- def flyscan_xray_centre(
127
- composite: HyperionFlyScanXRayCentreComposite,
128
- parameters: HyperionSpecifiedThreeDGridScan,
129
- ) -> MsgGenerator:
130
- """Create the plan to run the grid scan based on provided parameters.
131
-
132
- The ispyb handler should be added to the whole gridscan as we want to capture errors
133
- at any point in it.
134
-
135
- Args:
136
- parameters (HyperionSpecifiedThreeDGridScan): The parameters to run the scan.
137
-
138
- Returns:
139
- Generator: The plan for the gridscan
140
- """
141
- xrc_event_handler = XRayCentreEventHandler()
142
-
143
- @bpp.subs_decorator(xrc_event_handler)
144
- def flyscan_and_fetch_results() -> MsgGenerator:
145
- yield from ispyb_activation_wrapper(
146
- flyscan_xray_centre_no_move(composite, parameters), parameters
147
- )
148
-
149
- yield from flyscan_and_fetch_results()
150
-
151
- xray_centre_results = xrc_event_handler.xray_centre_results
152
- assert xray_centre_results, (
153
- "Flyscan result event not received or no crystal found and exception not raised"
154
- )
155
- yield from change_aperture_then_move_to_xtal(
156
- xray_centre_results[0],
157
- composite.smargon,
158
- composite.aperture_scatterguard,
159
- parameters,
160
- )
161
-
162
-
163
- @bpp.set_run_key_decorator(CONST.PLAN.GRIDSCAN_AND_MOVE)
164
- @bpp.run_decorator(md={"subplan_name": CONST.PLAN.GRIDSCAN_AND_MOVE})
165
- def run_gridscan_and_fetch_results(
166
- fgs_composite: HyperionFlyScanXRayCentreComposite,
167
- parameters: HyperionSpecifiedThreeDGridScan,
168
- feature_controlled: _FeatureControlled,
169
- ) -> MsgGenerator:
170
- """A multi-run plan which runs a gridscan, gets the results from zocalo
171
- and fires an event with the centres of mass determined by zocalo"""
172
-
173
- yield from feature_controlled.setup_trigger(fgs_composite, parameters)
174
-
175
- LOGGER.info("Starting grid scan")
176
- yield from bps.stage(
177
- fgs_composite.zocalo, group=ZOCALO_STAGE_GROUP
178
- ) # connect to zocalo and make sure the queue is clear
179
- yield from run_gridscan(fgs_composite, parameters, feature_controlled)
180
-
181
- LOGGER.info("Grid scan finished, getting results.")
182
-
183
- try:
184
- with TRACER.start_span("wait_for_zocalo"):
185
- yield from bps.trigger_and_read(
186
- [fgs_composite.zocalo], name=ZOCALO_READING_PLAN_NAME
187
- )
188
- LOGGER.info("Zocalo triggered and read, interpreting results.")
189
- xrc_results = yield from get_full_processing_results(fgs_composite.zocalo)
190
- LOGGER.info(f"Got xray centres, top 5: {xrc_results[:5]}")
191
- filtered_results = [
192
- result
193
- for result in xrc_results
194
- if result["total_count"] >= ZOCALO_MIN_TOTAL_COUNT_THRESHOLD
195
- ]
196
- discarded_count = len(xrc_results) - len(filtered_results)
197
- if discarded_count > 0:
198
- LOGGER.info(
199
- f"Removed {discarded_count} results because below threshold"
200
- )
201
- if filtered_results:
202
- flyscan_results = [
203
- _xrc_result_in_boxes_to_result_in_mm(xr, parameters)
204
- for xr in filtered_results
205
- ]
206
- else:
207
- LOGGER.warning("No X-ray centre received")
208
- raise CrystalNotFoundException()
209
- yield from _fire_xray_centre_result_event(flyscan_results)
210
-
211
- finally:
212
- # Turn off dev/shm streaming to avoid filling disk, see https://github.com/DiamondLightSource/hyperion/issues/1395
213
- LOGGER.info("Turning off Eiger dev/shm streaming")
214
- yield from bps.abs_set(fgs_composite.eiger.odin.fan.dev_shm_enable, 0) # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
215
-
216
- # Wait on everything before returning to GDA (particularly apertures), can be removed
217
- # when we do not return to GDA here
218
- yield from bps.wait()
219
-
220
-
221
- def _xrc_result_in_boxes_to_result_in_mm(
222
- xrc_result: XrcResult, parameters: HyperionSpecifiedThreeDGridScan
223
- ) -> XRayCentreResult:
224
- fgs_params = parameters.FGS_params
225
- xray_centre = fgs_params.grid_position_to_motor_position(
226
- np.array(xrc_result["centre_of_mass"])
227
- )
228
- # A correction is applied to the bounding box to map discrete grid coordinates to
229
- # the corners of the box in motor-space; we do not apply this correction
230
- # to the xray-centre as it is already in continuous space and the conversion has
231
- # been performed already
232
- # In other words, xrc_result["bounding_box"] contains the position of the box centre,
233
- # so we subtract half a box to get the corner of the box
234
- return XRayCentreResult(
235
- centre_of_mass_mm=xray_centre,
236
- bounding_box_mm=(
237
- fgs_params.grid_position_to_motor_position(
238
- np.array(xrc_result["bounding_box"][0]) - 0.5
239
- ),
240
- fgs_params.grid_position_to_motor_position(
241
- np.array(xrc_result["bounding_box"][1]) - 0.5
242
- ),
243
- ),
244
- max_count=xrc_result["max_count"],
245
- total_count=xrc_result["total_count"],
246
- )
247
-
248
-
249
- @bpp.set_run_key_decorator(CONST.PLAN.FLYSCAN_RESULTS)
250
- def _fire_xray_centre_result_event(results: Sequence[XRayCentreResult]):
251
- def empty_plan():
252
- return iter([])
253
-
254
- yield from bpp.run_wrapper(
255
- empty_plan(),
256
- md={CONST.PLAN.FLYSCAN_RESULTS: [dataclasses.asdict(r) for r in results]},
257
- )
258
-
259
-
260
- @bpp.set_run_key_decorator(CONST.PLAN.GRIDSCAN_MAIN)
261
- @bpp.run_decorator(md={"subplan_name": CONST.PLAN.GRIDSCAN_MAIN})
262
- def run_gridscan(
263
- fgs_composite: HyperionFlyScanXRayCentreComposite,
264
- parameters: HyperionSpecifiedThreeDGridScan,
265
- feature_controlled: _FeatureControlled,
266
- md={ # noqa
267
- "plan_name": CONST.PLAN.GRIDSCAN_MAIN,
268
- },
269
- ):
270
- # Currently gridscan only works for omega 0, see #
271
- with TRACER.start_span("moving_omega_to_0"):
272
- yield from bps.abs_set(fgs_composite.smargon.omega, 0)
273
-
274
- # We only subscribe to the communicator callback for run_gridscan, so this is where
275
- # we should generate an event reading the values which need to be included in the
276
- # ispyb deposition
277
- with TRACER.start_span("ispyb_hardware_readings"):
278
- yield from standard_read_hardware_pre_collection(
279
- fgs_composite.undulator,
280
- fgs_composite.synchrotron,
281
- fgs_composite.s4_slit_gaps,
282
- fgs_composite.dcm,
283
- fgs_composite.smargon,
284
- )
285
-
286
- read_during_collection = partial(
287
- standard_read_hardware_during_collection,
288
- fgs_composite.aperture_scatterguard,
289
- fgs_composite.attenuator,
290
- fgs_composite.flux,
291
- fgs_composite.dcm,
292
- fgs_composite.eiger,
293
- )
294
-
295
- LOGGER.info("Setting fgs params")
296
- yield from feature_controlled.set_flyscan_params()
297
-
298
- LOGGER.info("Waiting for gridscan validity check")
299
- yield from wait_for_gridscan_valid(feature_controlled.fgs_motors)
300
-
301
- LOGGER.info("Waiting for arming to finish")
302
- yield from bps.wait(CONST.WAIT.GRID_READY_FOR_DC)
303
- yield from bps.stage(fgs_composite.eiger)
304
-
305
- yield from kickoff_and_complete_gridscan(
306
- feature_controlled.fgs_motors,
307
- fgs_composite.eiger,
308
- fgs_composite.synchrotron,
309
- [parameters.scan_points_first_grid, parameters.scan_points_second_grid],
310
- parameters.scan_indices,
311
- plan_during_collection=read_during_collection,
312
- )
313
- yield from bps.abs_set(feature_controlled.fgs_motors.z_steps, 0, wait=False)
314
-
315
-
316
- def wait_for_gridscan_valid(fgs_motors: FastGridScanCommon, timeout=0.5):
317
- LOGGER.info("Waiting for valid fgs_params")
318
- SLEEP_PER_CHECK = 0.1
319
- times_to_check = int(timeout / SLEEP_PER_CHECK)
320
- for _ in range(times_to_check):
321
- scan_invalid = yield from bps.rd(fgs_motors.scan_invalid)
322
- pos_counter = yield from bps.rd(fgs_motors.position_counter)
323
- LOGGER.debug(
324
- f"Scan invalid: {scan_invalid} and position counter: {pos_counter}"
325
- )
326
- if not scan_invalid and pos_counter == 0:
327
- LOGGER.info("Gridscan scan valid and position counter reset")
328
- return
329
- yield from bps.sleep(SLEEP_PER_CHECK)
330
- raise SampleException("Scan invalid - pin too long/short/bent and out of range")
331
-
332
-
333
- @dataclasses.dataclass
334
- class _FeatureControlled:
335
- class _ZebraSetup(Protocol):
336
- def __call__(
337
- self, zebra: Zebra, group="setup_zebra_for_gridscan", wait=True
338
- ) -> MsgGenerator: ...
339
-
340
- class _ExtraSetup(Protocol):
341
- def __call__(
342
- self,
343
- fgs_composite: HyperionFlyScanXRayCentreComposite,
344
- parameters: HyperionSpecifiedThreeDGridScan,
345
- ) -> MsgGenerator: ...
346
-
347
- setup_trigger: _ExtraSetup
348
- tidy_plan: Callable[[HyperionFlyScanXRayCentreComposite], MsgGenerator]
349
- set_flyscan_params: Callable[[], MsgGenerator]
350
- fgs_motors: FastGridScanCommon
351
-
352
-
353
- def _get_feature_controlled(
354
- fgs_composite: HyperionFlyScanXRayCentreComposite,
355
- parameters: HyperionSpecifiedThreeDGridScan,
356
- ):
357
- if parameters.features.use_panda_for_gridscan:
358
- return _FeatureControlled(
359
- setup_trigger=_panda_triggering_setup,
360
- tidy_plan=_panda_tidy,
361
- set_flyscan_params=partial(
362
- set_flyscan_params,
363
- fgs_composite.panda_fast_grid_scan,
364
- parameters.panda_FGS_params,
365
- ),
366
- fgs_motors=fgs_composite.panda_fast_grid_scan,
367
- )
368
- else:
369
- return _FeatureControlled(
370
- setup_trigger=_zebra_triggering_setup,
371
- tidy_plan=partial(_generic_tidy, group="flyscan_zebra_tidy", wait=True),
372
- set_flyscan_params=partial(
373
- set_flyscan_params,
374
- fgs_composite.zebra_fast_grid_scan,
375
- parameters.FGS_params,
376
- ),
377
- fgs_motors=fgs_composite.zebra_fast_grid_scan,
378
- )
379
-
380
-
381
- def _generic_tidy(
382
- fgs_composite: HyperionFlyScanXRayCentreComposite, group, wait=True
383
- ) -> MsgGenerator:
384
- LOGGER.info("Tidying up Zebra")
385
- yield from tidy_up_zebra_after_gridscan(
386
- fgs_composite.zebra, fgs_composite.sample_shutter, group=group, wait=wait
387
- )
388
- LOGGER.info("Tidying up Zocalo")
389
- # make sure we don't consume any other results
390
- yield from bps.unstage(fgs_composite.zocalo, group=group, wait=wait)
391
-
392
-
393
- def _panda_tidy(fgs_composite: HyperionFlyScanXRayCentreComposite):
394
- group = "panda_flyscan_tidy"
395
- LOGGER.info("Disabling panda blocks")
396
- yield from disarm_panda_for_gridscan(fgs_composite.panda, group)
397
- yield from _generic_tidy(fgs_composite, group, False)
398
- yield from bps.wait(group, timeout=10)
399
- yield from bps.unstage(fgs_composite.panda)
400
-
401
-
402
- def _zebra_triggering_setup(
403
- fgs_composite: HyperionFlyScanXRayCentreComposite,
404
- parameters: HyperionSpecifiedThreeDGridScan,
405
- ):
406
- yield from setup_zebra_for_gridscan(
407
- fgs_composite.zebra, fgs_composite.sample_shutter, wait=True
408
- )
409
-
410
-
411
- def _panda_triggering_setup(
412
- fgs_composite: HyperionFlyScanXRayCentreComposite,
413
- parameters: HyperionSpecifiedThreeDGridScan,
414
- ):
415
- LOGGER.info("Setting up Panda for flyscan")
416
-
417
- run_up_distance_mm = yield from bps.rd(
418
- fgs_composite.panda_fast_grid_scan.run_up_distance_mm
419
- )
420
-
421
- time_between_x_steps_ms = (
422
- HardwareConstants.PANDA_FGS_EIGER_DEADTIME_S + parameters.exposure_time_s
423
- ) * 1e3
424
-
425
- smargon_speed_limit_mm_per_s = yield from bps.rd(
426
- fgs_composite.smargon.x.max_velocity
427
- )
428
-
429
- sample_velocity_mm_per_s = (
430
- parameters.panda_FGS_params.x_step_size_mm * 1e3 / time_between_x_steps_ms
431
- )
432
- if sample_velocity_mm_per_s > smargon_speed_limit_mm_per_s:
433
- raise SmargonSpeedException(
434
- f"Smargon speed was calculated from x step size\
435
- {parameters.panda_FGS_params.x_step_size_mm}mm and\
436
- time_between_x_steps_ms {time_between_x_steps_ms} as\
437
- {sample_velocity_mm_per_s}mm/s. The smargon's speed limit is\
438
- {smargon_speed_limit_mm_per_s}mm/s."
439
- )
440
- else:
441
- LOGGER.info(
442
- f"Panda grid scan: Smargon speed set to {sample_velocity_mm_per_s} mm/s"
443
- f" and using a run-up distance of {run_up_distance_mm}"
444
- )
445
-
446
- yield from bps.mv(
447
- fgs_composite.panda_fast_grid_scan.time_between_x_steps_ms,
448
- time_between_x_steps_ms,
449
- )
450
-
451
- directory_provider_root = Path(parameters.storage_directory)
452
- yield from set_panda_directory(directory_provider_root)
453
-
454
- yield from setup_panda_for_flyscan(
455
- fgs_composite.panda,
456
- parameters.panda_FGS_params,
457
- fgs_composite.smargon,
458
- parameters.exposure_time_s,
459
- time_between_x_steps_ms,
460
- sample_velocity_mm_per_s,
461
- )
462
-
463
- LOGGER.info("Setting up Zebra for panda flyscan")
464
- yield from setup_zebra_for_panda_flyscan(
465
- fgs_composite.zebra, fgs_composite.sample_shutter, wait=True
466
- )