mx-bluesky 1.4.7__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 (70) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +4 -4
  3. mx_bluesky/beamlines/i04/thawing_plan.py +8 -2
  4. mx_bluesky/beamlines/i23/__init__.py +3 -0
  5. mx_bluesky/beamlines/i23/serial.py +71 -0
  6. mx_bluesky/beamlines/i24/serial/__init__.py +2 -0
  7. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +7 -2
  8. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +3 -3
  9. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +6 -56
  10. mx_bluesky/beamlines/i24/serial/log.py +9 -10
  11. mx_bluesky/beamlines/i24/serial/parameters/utils.py +36 -7
  12. mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +0 -1
  13. mx_bluesky/beamlines/i24/serial/setup_beamline/pv_abstract.py +4 -4
  14. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +4 -4
  15. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +2 -1
  16. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +71 -11
  17. mx_bluesky/beamlines/i24/serial/write_nexus.py +3 -3
  18. mx_bluesky/{hyperion → common}/device_setup_plans/check_beamstop.py +1 -1
  19. mx_bluesky/{hyperion → common}/device_setup_plans/manipulate_sample.py +1 -1
  20. mx_bluesky/{hyperion → common}/device_setup_plans/setup_oav.py +12 -6
  21. mx_bluesky/{hyperion → common}/experiment_plans/change_aperture_then_move_plan.py +4 -5
  22. mx_bluesky/{hyperion → common}/experiment_plans/oav_grid_detection_plan.py +6 -6
  23. mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +6 -5
  24. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +16 -47
  25. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +4 -1
  26. mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py +4 -4
  27. mx_bluesky/common/parameters/components.py +22 -2
  28. mx_bluesky/common/parameters/constants.py +4 -16
  29. mx_bluesky/common/parameters/gridscan.py +36 -32
  30. mx_bluesky/common/plans/common_flyscan_xray_centre_plan.py +316 -0
  31. mx_bluesky/common/plans/inner_plans/__init__ .py +0 -0
  32. mx_bluesky/common/plans/read_hardware.py +3 -3
  33. mx_bluesky/common/utils/log.py +15 -12
  34. mx_bluesky/hyperion/__main__.py +2 -15
  35. mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +4 -4
  36. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +0 -33
  37. mx_bluesky/hyperion/device_setup_plans/utils.py +4 -4
  38. mx_bluesky/hyperion/experiment_plans/__init__.py +0 -6
  39. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +0 -9
  40. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +71 -88
  41. mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +183 -0
  42. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +12 -7
  43. mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +28 -7
  44. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +4 -4
  45. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +1 -1
  46. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +11 -3
  47. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +9 -8
  48. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +18 -56
  49. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -2
  50. mx_bluesky/hyperion/external_interaction/agamemnon.py +62 -70
  51. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +8 -6
  52. mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py +183 -31
  53. mx_bluesky/hyperion/parameters/cli.py +2 -10
  54. mx_bluesky/hyperion/parameters/constants.py +0 -5
  55. mx_bluesky/hyperion/parameters/device_composites.py +40 -5
  56. mx_bluesky/hyperion/parameters/gridscan.py +9 -58
  57. mx_bluesky/hyperion/parameters/rotation.py +0 -4
  58. mx_bluesky/hyperion/utils/context.py +2 -5
  59. mx_bluesky/hyperion/utils/validation.py +13 -10
  60. {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/METADATA +5 -4
  61. {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/RECORD +69 -65
  62. {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/WHEEL +1 -1
  63. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +0 -467
  64. /mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/{short1-laser.png → s1l.png} +0 -0
  65. /mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/{short2-laser.png → s2l.png} +0 -0
  66. /mx_bluesky/{hyperion → common}/device_setup_plans/position_detector.py +0 -0
  67. /mx_bluesky/common/plans/{do_fgs.py → inner_plans/do_fgs.py} +0 -0
  68. {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/entry_points.txt +0 -0
  69. {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/licenses/LICENSE +0 -0
  70. {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/top_level.txt +0 -0
@@ -2,35 +2,28 @@ from __future__ import annotations
2
2
 
3
3
  from pathlib import Path
4
4
 
5
- import pydantic
6
5
  from blueapi.core import BlueskyContext
7
6
  from bluesky import plan_stubs as bps
8
7
  from bluesky import preprocessors as bpp
9
8
  from bluesky.preprocessors import subs_decorator
10
9
  from bluesky.utils import MsgGenerator
11
- from dodal.devices.aperturescatterguard import ApertureScatterguard
12
- from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
13
- from dodal.devices.backlight import Backlight, BacklightPosition
14
- from dodal.devices.dcm import DCM
15
- from dodal.devices.detector.detector_motion import DetectorMotion
10
+ from dodal.devices.backlight import BacklightPosition
16
11
  from dodal.devices.eiger import EigerDetector
17
- from dodal.devices.fast_grid_scan import PandAFastGridScan, ZebraFastGridScan
18
- from dodal.devices.flux import Flux
19
- from dodal.devices.i03.beamstop import Beamstop
20
- from dodal.devices.oav.oav_detector import OAV
21
12
  from dodal.devices.oav.oav_parameters import OAVParameters
22
- from dodal.devices.oav.pin_image_recognition import PinTipDetection
23
- from dodal.devices.robot import BartRobot
24
- from dodal.devices.s4_slit_gaps import S4SlitGaps
25
- from dodal.devices.smargon import Smargon
26
- from dodal.devices.synchrotron import Synchrotron
27
- from dodal.devices.undulator import Undulator
28
- from dodal.devices.xbpm_feedback import XBPMFeedback
29
- from dodal.devices.zebra.zebra import Zebra
30
- from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
31
- from dodal.devices.zocalo import ZocaloResults
32
- from ophyd_async.fastcs.panda import HDFPanda
13
+ from dodal.plans.preprocessors.verify_undulator_gap import (
14
+ verify_undulator_gap_before_run_decorator,
15
+ )
33
16
 
17
+ from mx_bluesky.common.device_setup_plans.manipulate_sample import (
18
+ move_aperture_if_required,
19
+ )
20
+ from mx_bluesky.common.experiment_plans.change_aperture_then_move_plan import (
21
+ change_aperture_then_move_to_xtal,
22
+ )
23
+ from mx_bluesky.common.experiment_plans.oav_grid_detection_plan import (
24
+ OavGridDetectionComposite,
25
+ grid_detection_plan,
26
+ )
34
27
  from mx_bluesky.common.external_interaction.callbacks.common.grid_detection_callback import (
35
28
  GridDetectionCallback,
36
29
  GridParamUpdate,
@@ -39,27 +32,26 @@ from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback
39
32
  ispyb_activation_wrapper,
40
33
  )
41
34
  from mx_bluesky.common.parameters.constants import OavConstants
35
+ from mx_bluesky.common.parameters.gridscan import GridCommon
36
+ from mx_bluesky.common.plans.common_flyscan_xray_centre_plan import (
37
+ BeamlineSpecificFGSFeatures,
38
+ common_flyscan_xray_centre,
39
+ )
40
+ from mx_bluesky.common.preprocessors.preprocessors import (
41
+ transmission_and_xbpm_feedback_for_collection_decorator,
42
+ )
42
43
  from mx_bluesky.common.utils.context import device_composite_from_context
43
44
  from mx_bluesky.common.utils.log import LOGGER
44
45
  from mx_bluesky.common.xrc_result import XRayCentreEventHandler
45
- from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import (
46
- move_aperture_if_required,
47
- )
48
46
  from mx_bluesky.hyperion.device_setup_plans.utils import (
49
47
  start_preparing_data_collection_then_do_plan,
50
48
  )
51
- from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import (
52
- change_aperture_then_move_to_xtal,
53
- )
54
- from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
55
- flyscan_xray_centre_no_move,
56
- )
57
- from mx_bluesky.hyperion.experiment_plans.oav_grid_detection_plan import (
58
- OavGridDetectionComposite,
59
- grid_detection_plan,
49
+ from mx_bluesky.hyperion.experiment_plans.hyperion_flyscan_xray_centre_plan import (
50
+ construct_hyperion_specific_features,
60
51
  )
61
52
  from mx_bluesky.hyperion.parameters.constants import CONST
62
53
  from mx_bluesky.hyperion.parameters.device_composites import (
54
+ GridDetectThenXRayCentreComposite,
63
55
  HyperionFlyScanXRayCentreComposite,
64
56
  )
65
57
  from mx_bluesky.hyperion.parameters.gridscan import (
@@ -68,40 +60,12 @@ from mx_bluesky.hyperion.parameters.gridscan import (
68
60
  )
69
61
 
70
62
 
71
- @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
72
- class GridDetectThenXRayCentreComposite:
73
- """All devices which are directly or indirectly required by this plan"""
74
-
75
- aperture_scatterguard: ApertureScatterguard
76
- attenuator: BinaryFilterAttenuator
77
- backlight: Backlight
78
- beamstop: Beamstop
79
- dcm: DCM
80
- detector_motion: DetectorMotion
81
- eiger: EigerDetector
82
- zebra_fast_grid_scan: ZebraFastGridScan
83
- flux: Flux
84
- oav: OAV
85
- pin_tip_detection: PinTipDetection
86
- smargon: Smargon
87
- synchrotron: Synchrotron
88
- s4_slit_gaps: S4SlitGaps
89
- undulator: Undulator
90
- xbpm_feedback: XBPMFeedback
91
- zebra: Zebra
92
- zocalo: ZocaloResults
93
- panda: HDFPanda
94
- panda_fast_grid_scan: PandAFastGridScan
95
- robot: BartRobot
96
- sample_shutter: ZebraShutter
97
-
98
-
99
63
  def create_devices(context: BlueskyContext) -> GridDetectThenXRayCentreComposite:
100
64
  return device_composite_from_context(context, GridDetectThenXRayCentreComposite)
101
65
 
102
66
 
103
67
  def create_parameters_for_flyscan_xray_centre(
104
- grid_scan_with_edge_params: GridScanWithEdgeDetect,
68
+ grid_scan_with_edge_params: GridCommon,
105
69
  grid_parameters: GridParamUpdate,
106
70
  ) -> HyperionSpecifiedThreeDGridScan:
107
71
  params_json = grid_scan_with_edge_params.model_dump()
@@ -113,7 +77,7 @@ def create_parameters_for_flyscan_xray_centre(
113
77
 
114
78
  def detect_grid_and_do_gridscan(
115
79
  composite: GridDetectThenXRayCentreComposite,
116
- parameters: GridScanWithEdgeDetect,
80
+ parameters: GridCommon,
117
81
  oav_params: OAVParameters,
118
82
  ):
119
83
  snapshot_template = f"{parameters.detector_params.prefix}_{parameters.detector_params.run_number}_{{angle}}"
@@ -147,7 +111,7 @@ def detect_grid_and_do_gridscan(
147
111
  yield from bps.prepare(
148
112
  composite.aperture_scatterguard,
149
113
  parameters.selected_aperture,
150
- group=CONST.WAIT.GRID_READY_FOR_DC,
114
+ group=CONST.WAIT.PREPARE_APERTURE,
151
115
  )
152
116
 
153
117
  yield from run_grid_detection_plan(
@@ -160,38 +124,57 @@ def detect_grid_and_do_gridscan(
160
124
  composite.backlight, BacklightPosition.OUT, group=CONST.WAIT.GRID_READY_FOR_DC
161
125
  )
162
126
 
127
+ yield from bps.wait(CONST.WAIT.PREPARE_APERTURE)
163
128
  yield from move_aperture_if_required(
164
129
  composite.aperture_scatterguard,
165
130
  parameters.selected_aperture,
166
131
  group=CONST.WAIT.GRID_READY_FOR_DC,
167
132
  )
168
133
 
169
- yield from flyscan_xray_centre_no_move(
170
- HyperionFlyScanXRayCentreComposite(
171
- aperture_scatterguard=composite.aperture_scatterguard,
172
- attenuator=composite.attenuator,
173
- backlight=composite.backlight,
174
- eiger=composite.eiger,
175
- panda_fast_grid_scan=composite.panda_fast_grid_scan,
176
- flux=composite.flux,
177
- s4_slit_gaps=composite.s4_slit_gaps,
178
- smargon=composite.smargon,
179
- undulator=composite.undulator,
180
- synchrotron=composite.synchrotron,
181
- xbpm_feedback=composite.xbpm_feedback,
182
- zebra=composite.zebra,
183
- zocalo=composite.zocalo,
184
- panda=composite.panda,
185
- zebra_fast_grid_scan=composite.zebra_fast_grid_scan,
186
- dcm=composite.dcm,
187
- robot=composite.robot,
188
- sample_shutter=composite.sample_shutter,
189
- ),
190
- create_parameters_for_flyscan_xray_centre(
191
- parameters, grid_params_callback.get_grid_parameters()
192
- ),
134
+ xrc_composite = HyperionFlyScanXRayCentreComposite(
135
+ aperture_scatterguard=composite.aperture_scatterguard,
136
+ attenuator=composite.attenuator,
137
+ backlight=composite.backlight,
138
+ eiger=composite.eiger,
139
+ panda_fast_grid_scan=composite.panda_fast_grid_scan,
140
+ flux=composite.flux,
141
+ s4_slit_gaps=composite.s4_slit_gaps,
142
+ smargon=composite.smargon,
143
+ undulator=composite.undulator,
144
+ synchrotron=composite.synchrotron,
145
+ xbpm_feedback=composite.xbpm_feedback,
146
+ zebra=composite.zebra,
147
+ zocalo=composite.zocalo,
148
+ panda=composite.panda,
149
+ zebra_fast_grid_scan=composite.zebra_fast_grid_scan,
150
+ dcm=composite.dcm,
151
+ robot=composite.robot,
152
+ sample_shutter=composite.sample_shutter,
153
+ )
154
+
155
+ params = create_parameters_for_flyscan_xray_centre(
156
+ parameters, grid_params_callback.get_grid_parameters()
193
157
  )
194
158
 
159
+ beamline_specific = construct_hyperion_specific_features(xrc_composite, params)
160
+
161
+ yield from _gridscan_with_undulator_checks(xrc_composite, params, beamline_specific)
162
+
163
+
164
+ def _gridscan_with_undulator_checks(
165
+ composite: HyperionFlyScanXRayCentreComposite,
166
+ params: HyperionSpecifiedThreeDGridScan,
167
+ beamline_specific: BeamlineSpecificFGSFeatures,
168
+ ):
169
+ @transmission_and_xbpm_feedback_for_collection_decorator(
170
+ composite, params.transmission_frac
171
+ )
172
+ @verify_undulator_gap_before_run_decorator(composite)
173
+ def _inner():
174
+ yield from common_flyscan_xray_centre(composite, params, beamline_specific)
175
+
176
+ yield from _inner()
177
+
195
178
 
196
179
  def grid_detect_then_xray_centre(
197
180
  composite: GridDetectThenXRayCentreComposite,
@@ -0,0 +1,183 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import partial
4
+ from pathlib import Path
5
+
6
+ import bluesky.plan_stubs as bps
7
+ from bluesky.utils import MsgGenerator
8
+ from dodal.devices.fast_grid_scan import (
9
+ set_fast_grid_scan_params,
10
+ )
11
+
12
+ from mx_bluesky.common.plans.common_flyscan_xray_centre_plan import (
13
+ construct_beamline_specific_FGS_features,
14
+ )
15
+ from mx_bluesky.common.utils.log import LOGGER
16
+ from mx_bluesky.hyperion.device_setup_plans.setup_panda import (
17
+ disarm_panda_for_gridscan,
18
+ set_panda_directory,
19
+ setup_panda_for_flyscan,
20
+ )
21
+ from mx_bluesky.hyperion.device_setup_plans.setup_zebra import (
22
+ setup_zebra_for_gridscan,
23
+ setup_zebra_for_panda_flyscan,
24
+ tidy_up_zebra_after_gridscan,
25
+ )
26
+ from mx_bluesky.hyperion.parameters.device_composites import (
27
+ HyperionFlyScanXRayCentreComposite,
28
+ )
29
+ from mx_bluesky.hyperion.parameters.gridscan import HyperionSpecifiedThreeDGridScan
30
+
31
+
32
+ class SmargonSpeedException(Exception):
33
+ pass
34
+
35
+
36
+ def construct_hyperion_specific_features(
37
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
38
+ parameters: HyperionSpecifiedThreeDGridScan,
39
+ ):
40
+ """
41
+ Get all the information needed to do the Hyperion-specific parts of the XRC flyscan.
42
+ """
43
+
44
+ signals_to_read_pre_flyscan = [
45
+ fgs_composite.undulator.current_gap,
46
+ fgs_composite.synchrotron.synchrotron_mode,
47
+ fgs_composite.s4_slit_gaps.xgap,
48
+ fgs_composite.s4_slit_gaps.ygap,
49
+ fgs_composite.smargon.x,
50
+ fgs_composite.smargon.y,
51
+ fgs_composite.smargon.z,
52
+ fgs_composite.dcm.energy_in_kev,
53
+ ]
54
+
55
+ signals_to_read_during_collection = [
56
+ fgs_composite.aperture_scatterguard,
57
+ fgs_composite.attenuator.actual_transmission,
58
+ fgs_composite.flux.flux_reading,
59
+ fgs_composite.dcm.energy_in_kev,
60
+ fgs_composite.eiger.bit_depth,
61
+ ]
62
+
63
+ if parameters.features.use_panda_for_gridscan:
64
+ setup_trigger_plan = _panda_triggering_setup
65
+ tidy_plan = _panda_tidy
66
+ set_flyscan_params_plan = partial(
67
+ set_fast_grid_scan_params,
68
+ fgs_composite.panda_fast_grid_scan,
69
+ parameters.panda_FGS_params,
70
+ )
71
+ fgs_motors = fgs_composite.panda_fast_grid_scan
72
+
73
+ else:
74
+ setup_trigger_plan = _zebra_triggering_setup
75
+ tidy_plan = partial(_generic_tidy, group="flyscan_zebra_tidy", wait=True)
76
+ set_flyscan_params_plan = partial(
77
+ set_fast_grid_scan_params,
78
+ fgs_composite.zebra_fast_grid_scan,
79
+ parameters.FGS_params,
80
+ )
81
+ fgs_motors = fgs_composite.zebra_fast_grid_scan
82
+ return construct_beamline_specific_FGS_features(
83
+ setup_trigger_plan,
84
+ tidy_plan,
85
+ set_flyscan_params_plan,
86
+ fgs_motors,
87
+ signals_to_read_pre_flyscan,
88
+ signals_to_read_during_collection,
89
+ get_xrc_results_from_zocalo=True,
90
+ )
91
+
92
+
93
+ def _generic_tidy(
94
+ fgs_composite: HyperionFlyScanXRayCentreComposite, group, wait=True
95
+ ) -> MsgGenerator:
96
+ LOGGER.info("Tidying up Zebra")
97
+ yield from tidy_up_zebra_after_gridscan(
98
+ fgs_composite.zebra, fgs_composite.sample_shutter, group=group, wait=wait
99
+ )
100
+ LOGGER.info("Tidying up Zocalo")
101
+ # make sure we don't consume any other results
102
+ yield from bps.unstage(fgs_composite.zocalo, group=group, wait=wait)
103
+
104
+ # Turn off dev/shm streaming to avoid filling disk, see https://github.com/DiamondLightSource/hyperion/issues/1395
105
+ LOGGER.info("Turning off Eiger dev/shm streaming")
106
+ 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)
107
+
108
+
109
+ def _panda_tidy(fgs_composite: HyperionFlyScanXRayCentreComposite):
110
+ group = "panda_flyscan_tidy"
111
+ LOGGER.info("Disabling panda blocks")
112
+ yield from disarm_panda_for_gridscan(fgs_composite.panda, group)
113
+ yield from _generic_tidy(fgs_composite, group, False)
114
+ yield from bps.wait(group, timeout=10)
115
+ yield from bps.unstage(fgs_composite.panda)
116
+
117
+
118
+ def _zebra_triggering_setup(
119
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
120
+ parameters: HyperionSpecifiedThreeDGridScan,
121
+ ) -> MsgGenerator:
122
+ yield from setup_zebra_for_gridscan(
123
+ fgs_composite.zebra, fgs_composite.sample_shutter, wait=True
124
+ )
125
+
126
+
127
+ def _panda_triggering_setup(
128
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
129
+ parameters: HyperionSpecifiedThreeDGridScan,
130
+ ) -> MsgGenerator:
131
+ LOGGER.info("Setting up Panda for flyscan")
132
+
133
+ run_up_distance_mm = yield from bps.rd(
134
+ fgs_composite.panda_fast_grid_scan.run_up_distance_mm
135
+ )
136
+
137
+ # Set the time between x steps pv
138
+ DEADTIME_S = 1e-6 # according to https://www.dectris.com/en/detectors/x-ray-detectors/eiger2/eiger2-for-synchrotrons/eiger2-x/
139
+
140
+ time_between_x_steps_ms = (DEADTIME_S + parameters.exposure_time_s) * 1e3
141
+
142
+ smargon_speed_limit_mm_per_s = yield from bps.rd(
143
+ fgs_composite.smargon.x.max_velocity
144
+ )
145
+
146
+ sample_velocity_mm_per_s = (
147
+ parameters.panda_FGS_params.x_step_size_mm * 1e3 / time_between_x_steps_ms
148
+ )
149
+ if sample_velocity_mm_per_s > smargon_speed_limit_mm_per_s:
150
+ raise SmargonSpeedException(
151
+ f"Smargon speed was calculated from x step size\
152
+ {parameters.panda_FGS_params.x_step_size_mm}mm and\
153
+ time_between_x_steps_ms {time_between_x_steps_ms} as\
154
+ {sample_velocity_mm_per_s}mm/s. The smargon's speed limit is\
155
+ {smargon_speed_limit_mm_per_s}mm/s."
156
+ )
157
+ else:
158
+ LOGGER.info(
159
+ f"Panda grid scan: Smargon speed set to {smargon_speed_limit_mm_per_s} mm/s"
160
+ f" and using a run-up distance of {run_up_distance_mm}"
161
+ )
162
+
163
+ yield from bps.mv(
164
+ fgs_composite.panda_fast_grid_scan.time_between_x_steps_ms, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
165
+ time_between_x_steps_ms, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
166
+ )
167
+
168
+ directory_provider_root = Path(parameters.storage_directory)
169
+ yield from set_panda_directory(directory_provider_root)
170
+
171
+ yield from setup_panda_for_flyscan(
172
+ fgs_composite.panda,
173
+ parameters.panda_FGS_params,
174
+ fgs_composite.smargon,
175
+ parameters.exposure_time_s,
176
+ time_between_x_steps_ms,
177
+ sample_velocity_mm_per_s,
178
+ )
179
+
180
+ LOGGER.info("Setting up Zebra for panda flyscan")
181
+ yield from setup_zebra_for_panda_flyscan(
182
+ fgs_composite.zebra, fgs_composite.sample_shutter, wait=True
183
+ )
@@ -20,7 +20,7 @@ from mx_bluesky.hyperion.experiment_plans.robot_load_then_centre_plan import (
20
20
  from mx_bluesky.hyperion.experiment_plans.rotation_scan_plan import (
21
21
  MultiRotationScan,
22
22
  RotationScanComposite,
23
- multi_rotation_scan,
23
+ multi_rotation_scan_internal,
24
24
  )
25
25
  from mx_bluesky.hyperion.parameters.constants import CONST
26
26
  from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
@@ -50,6 +50,7 @@ def load_centre_collect_full(
50
50
  """
51
51
  if not oav_params:
52
52
  oav_params = OAVParameters(context="xrayCentring")
53
+ oav_config_file = oav_params.oav_config_json
53
54
 
54
55
  @set_run_key_decorator(CONST.PLAN.LOAD_CENTRE_COLLECT)
55
56
  @run_decorator(
@@ -64,7 +65,9 @@ def load_centre_collect_full(
64
65
  def plan_with_callback_subs():
65
66
  flyscan_event_handler = XRayCentreEventHandler()
66
67
  yield from subs_wrapper(
67
- robot_load_then_xray_centre(composite, parameters.robot_load_then_centre),
68
+ robot_load_then_xray_centre(
69
+ composite, parameters.robot_load_then_centre, oav_config_file
70
+ ),
68
71
  flyscan_event_handler,
69
72
  )
70
73
 
@@ -83,11 +86,13 @@ def load_centre_collect_full(
83
86
  else:
84
87
  # If the xray centring hasn't found a result but has not thrown an error it
85
88
  # means that we do not need to recentre and can collect where we are
86
- initial_x = yield from bps.rd(composite.smargon.x.user_readback)
87
- initial_y = yield from bps.rd(composite.smargon.y.user_readback)
88
- initial_z = yield from bps.rd(composite.smargon.z.user_readback)
89
+ initial_x_mm = yield from bps.rd(composite.smargon.x.user_readback)
90
+ initial_y_mm = yield from bps.rd(composite.smargon.y.user_readback)
91
+ initial_z_mm = yield from bps.rd(composite.smargon.z.user_readback)
89
92
 
90
- locations_to_collect_um = [np.array([initial_x, initial_y, initial_z])]
93
+ locations_to_collect_um = [
94
+ np.array([initial_x_mm, initial_y_mm, initial_z_mm]) * 1000
95
+ ]
91
96
 
92
97
  multi_rotation = parameters.multi_rotation_scan
93
98
  rotation_template = multi_rotation.rotation_scans.copy()
@@ -109,6 +114,6 @@ def load_centre_collect_full(
109
114
  multi_rotation.demand_energy_ev
110
115
  == parameters.robot_load_then_centre.demand_energy_ev
111
116
  ), "Setting a different energy for gridscan and rotation is not supported"
112
- yield from multi_rotation_scan(composite, multi_rotation, oav_params)
117
+ yield from multi_rotation_scan_internal(composite, multi_rotation, oav_params)
113
118
 
114
119
  yield from plan_with_callback_subs()
@@ -9,8 +9,8 @@ from dodal.devices.oav.oav_detector import OAV
9
9
  from dodal.devices.oav.oav_parameters import OAVParameters
10
10
  from dodal.devices.smargon import Smargon
11
11
 
12
+ from mx_bluesky.common.device_setup_plans.setup_oav import setup_general_oav_params
12
13
  from mx_bluesky.common.parameters.components import WithSnapshot
13
- from mx_bluesky.hyperion.device_setup_plans.setup_oav import setup_general_oav_params
14
14
  from mx_bluesky.hyperion.parameters.constants import CONST, DocDescriptorNames
15
15
 
16
16
  OAV_SNAPSHOT_SETUP_SHOT = "oav_snapshot_setup_shot"
@@ -34,7 +34,7 @@ def setup_beamline_for_OAV(
34
34
  yield from bps.abs_set(smargon.omega.velocity, max_vel, group=group)
35
35
  yield from bps.abs_set(backlight, BacklightPosition.IN, group=group)
36
36
  yield from bps.abs_set(
37
- aperture_scatterguard, ApertureValue.OUT_OF_BEAM, group=group
37
+ aperture_scatterguard.selected_aperture, ApertureValue.OUT_OF_BEAM, group=group
38
38
  )
39
39
 
40
40
 
@@ -45,9 +45,12 @@ def oav_snapshot_plan(
45
45
  ) -> MsgGenerator:
46
46
  if not parameters.take_snapshots:
47
47
  return
48
- yield from _setup_oav(composite, parameters, oav_parameters)
49
- for omega in parameters.snapshot_omegas_deg or []:
50
- yield from _take_oav_snapshot(composite, omega)
48
+ if parameters.use_grid_snapshots:
49
+ yield from _generate_oav_snapshots(composite, parameters)
50
+ else:
51
+ yield from _setup_oav(composite, parameters, oav_parameters)
52
+ for omega in parameters.snapshot_omegas_deg or []:
53
+ yield from _take_oav_snapshot(composite, omega)
51
54
 
52
55
 
53
56
  def _setup_oav(
@@ -62,12 +65,24 @@ def _setup_oav(
62
65
  )
63
66
 
64
67
 
68
+ def _generate_oav_snapshots(composite: OavSnapshotComposite, params: WithSnapshot):
69
+ """Generate rotation snapshots from previously captured grid snapshots"""
70
+ yield from bps.abs_set(
71
+ composite.oav.snapshot.directory, str(params.snapshot_directory)
72
+ )
73
+ for _ in 0, 270:
74
+ yield from bps.create(DocDescriptorNames.OAV_ROTATION_SNAPSHOT_TRIGGERED)
75
+ yield from bps.read(composite.oav)
76
+ yield from bps.read(composite.smargon)
77
+ yield from bps.save()
78
+
79
+
65
80
  def _take_oav_snapshot(composite: OavSnapshotComposite, omega: float):
81
+ """Create new snapshots by triggering the OAV"""
66
82
  yield from bps.abs_set(
67
83
  composite.smargon.omega, omega, group=OAV_SNAPSHOT_SETUP_SHOT
68
84
  )
69
- time_now = datetime.now()
70
- filename = f"{time_now.strftime('%H%M%S%f')[:8]}_oav_snapshot_{omega:.0f}"
85
+ filename = _snapshot_filename(omega)
71
86
  yield from bps.abs_set(
72
87
  composite.oav.snapshot.filename,
73
88
  filename,
@@ -78,3 +93,9 @@ def _take_oav_snapshot(composite: OavSnapshotComposite, omega: float):
78
93
  yield from bps.create(DocDescriptorNames.OAV_ROTATION_SNAPSHOT_TRIGGERED)
79
94
  yield from bps.read(composite.oav)
80
95
  yield from bps.save()
96
+
97
+
98
+ def _snapshot_filename(omega):
99
+ time_now = datetime.now()
100
+ filename = f"{time_now.strftime('%H%M%S%f')[:8]}_oav_snapshot_{omega:.0f}"
101
+ return filename
@@ -8,6 +8,10 @@ from bluesky.utils import MsgGenerator
8
8
  from dodal.devices.eiger import EigerDetector
9
9
  from dodal.devices.oav.oav_parameters import OAVParameters
10
10
 
11
+ from mx_bluesky.common.device_setup_plans.manipulate_sample import move_phi_chi_omega
12
+ from mx_bluesky.common.experiment_plans.change_aperture_then_move_plan import (
13
+ change_aperture_then_move_to_xtal,
14
+ )
11
15
  from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
12
16
  ispyb_activation_wrapper,
13
17
  )
@@ -15,13 +19,9 @@ from mx_bluesky.common.parameters.constants import OavConstants
15
19
  from mx_bluesky.common.utils.context import device_composite_from_context
16
20
  from mx_bluesky.common.utils.log import LOGGER
17
21
  from mx_bluesky.common.xrc_result import XRayCentreEventHandler
18
- from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import move_phi_chi_omega
19
22
  from mx_bluesky.hyperion.device_setup_plans.utils import (
20
23
  start_preparing_data_collection_then_do_plan,
21
24
  )
22
- from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import (
23
- change_aperture_then_move_to_xtal,
24
- )
25
25
  from mx_bluesky.hyperion.experiment_plans.grid_detect_then_xray_centre_plan import (
26
26
  GridDetectThenXRayCentreComposite,
27
27
  detect_grid_and_do_gridscan,
@@ -16,10 +16,10 @@ from dodal.devices.oav.utils import (
16
16
  )
17
17
  from dodal.devices.smargon import Smargon
18
18
 
19
+ from mx_bluesky.common.device_setup_plans.setup_oav import pre_centring_setup_oav
19
20
  from mx_bluesky.common.utils.context import device_composite_from_context
20
21
  from mx_bluesky.common.utils.exceptions import SampleException, catch_exception_and_warn
21
22
  from mx_bluesky.common.utils.log import LOGGER
22
- from mx_bluesky.hyperion.device_setup_plans.setup_oav import pre_centring_setup_oav
23
23
  from mx_bluesky.hyperion.device_setup_plans.smargon import (
24
24
  move_smargon_warn_on_out_of_range,
25
25
  )
@@ -12,14 +12,15 @@ 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.attenuator import BinaryFilterAttenuator
15
- from dodal.devices.dcm import DCM
15
+ from dodal.devices.backlight import Backlight, BacklightPosition
16
16
  from dodal.devices.focusing_mirror import FocusingMirrorWithStripes, MirrorVoltages
17
+ from dodal.devices.i03.dcm import DCM
18
+ from dodal.devices.i03.undulator_dcm import UndulatorDCM
17
19
  from dodal.devices.motors import XYZPositioner
18
20
  from dodal.devices.oav.oav_detector import OAV
19
21
  from dodal.devices.robot import BartRobot, SampleLocation
20
22
  from dodal.devices.smargon import Smargon, StubPosition
21
23
  from dodal.devices.thawer import Thawer
22
- from dodal.devices.undulator_dcm import UndulatorDCM
23
24
  from dodal.devices.webcam import Webcam
24
25
  from dodal.devices.xbpm_feedback import XBPMFeedback
25
26
  from dodal.plan_stubs.motor_utils import MoveTooLarge, home_and_reset_wrapper
@@ -51,6 +52,7 @@ class RobotLoadAndEnergyChangeComposite:
51
52
  oav: OAV
52
53
  smargon: Smargon
53
54
  aperture_scatterguard: ApertureScatterguard
55
+ backlight: Backlight
54
56
 
55
57
 
56
58
  def create_devices(context: BlueskyContext) -> RobotLoadAndEnergyChangeComposite:
@@ -95,7 +97,9 @@ def prepare_for_robot_load(
95
97
  aperture_scatterguard: ApertureScatterguard, smargon: Smargon
96
98
  ):
97
99
  yield from bps.abs_set(
98
- aperture_scatterguard, ApertureValue.OUT_OF_BEAM, group="prepare_robot_load"
100
+ aperture_scatterguard.selected_aperture,
101
+ ApertureValue.OUT_OF_BEAM,
102
+ group="prepare_robot_load",
99
103
  )
100
104
 
101
105
  yield from bps.mv(smargon.stub_offsets, StubPosition.RESET_TO_ROBOT_LOAD)
@@ -166,6 +170,8 @@ def robot_load_and_snapshots(
166
170
  thawing_time: float,
167
171
  demand_energy_ev: float | None,
168
172
  ):
173
+ yield from bps.abs_set(composite.backlight, BacklightPosition.IN, group="snapshot")
174
+
169
175
  robot_load_plan = do_robot_load(
170
176
  composite,
171
177
  location,
@@ -189,6 +195,8 @@ def robot_load_and_snapshots(
189
195
  except_plan=raise_exception_if_moved_out_of_cryojet,
190
196
  )
191
197
 
198
+ yield from bps.wait(group="snapshot")
199
+
192
200
  yield from take_robot_snapshots(composite.oav, composite.webcam, snapshot_directory)
193
201
 
194
202
  yield from bps.create(name=CONST.DESCRIPTORS.ROBOT_LOAD)