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