mx-bluesky 1.4.2__py3-none-any.whl → 1.4.4__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 (92) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/i24/serial/dcid.py +3 -3
  3. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +24 -9
  4. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +13 -4
  5. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +1 -1
  6. mx_bluesky/beamlines/i24/serial/parameters/__init__.py +2 -1
  7. mx_bluesky/beamlines/i24/serial/parameters/constants.py +13 -5
  8. mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +20 -4
  9. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +40 -11
  10. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +81 -40
  11. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/aperture_change_callback.py +1 -1
  12. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/grid_detection_callback.py +19 -1
  13. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/ispyb_callback_base.py +40 -34
  14. mx_bluesky/{hyperion → common}/external_interaction/callbacks/common/ispyb_mapping.py +4 -4
  15. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/logging_callback.py +1 -1
  16. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/zocalo_callback.py +13 -19
  17. mx_bluesky/{hyperion → common}/external_interaction/callbacks/xray_centre/ispyb_callback.py +39 -34
  18. mx_bluesky/{hyperion → common}/external_interaction/callbacks/xray_centre/ispyb_mapping.py +2 -2
  19. mx_bluesky/{hyperion → common}/external_interaction/callbacks/xray_centre/nexus_callback.py +20 -15
  20. mx_bluesky/common/external_interaction/config_server.py +11 -0
  21. mx_bluesky/common/external_interaction/ispyb/__init__.py +0 -0
  22. mx_bluesky/{hyperion → common}/external_interaction/ispyb/data_model.py +2 -0
  23. mx_bluesky/{hyperion → common}/external_interaction/ispyb/exp_eye_store.py +5 -5
  24. mx_bluesky/{hyperion → common}/external_interaction/ispyb/ispyb_store.py +20 -18
  25. mx_bluesky/{hyperion → common}/external_interaction/ispyb/ispyb_utils.py +2 -2
  26. mx_bluesky/common/external_interaction/nexus/__init__.py +0 -0
  27. mx_bluesky/{hyperion → common}/external_interaction/nexus/nexus_utils.py +21 -6
  28. mx_bluesky/{hyperion → common}/external_interaction/nexus/write_nexus.py +5 -5
  29. mx_bluesky/common/external_interaction/test_config_server.py +38 -0
  30. mx_bluesky/common/parameters/components.py +9 -8
  31. mx_bluesky/common/parameters/constants.py +1 -0
  32. mx_bluesky/common/parameters/gridscan.py +107 -53
  33. mx_bluesky/common/plans/do_fgs.py +4 -10
  34. mx_bluesky/{hyperion → common/utils}/exceptions.py +15 -1
  35. mx_bluesky/common/utils/log.py +17 -7
  36. mx_bluesky/hyperion/__main__.py +15 -14
  37. mx_bluesky/hyperion/device_setup_plans/check_beamstop.py +27 -0
  38. mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +13 -6
  39. mx_bluesky/hyperion/device_setup_plans/manipulate_sample.py +1 -1
  40. mx_bluesky/hyperion/device_setup_plans/position_detector.py +1 -1
  41. mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +3 -3
  42. mx_bluesky/hyperion/device_setup_plans/setup_panda.py +21 -4
  43. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +62 -36
  44. mx_bluesky/hyperion/device_setup_plans/smargon.py +1 -1
  45. mx_bluesky/hyperion/device_setup_plans/utils.py +4 -0
  46. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +8 -8
  47. mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +28 -17
  48. mx_bluesky/hyperion/experiment_plans/common/xrc_result.py +10 -1
  49. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -9
  50. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +39 -49
  51. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +22 -23
  52. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +4 -11
  53. mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +3 -3
  54. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +6 -14
  55. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +12 -11
  56. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +2 -2
  57. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +9 -4
  58. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +10 -11
  59. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +33 -17
  60. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -2
  61. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +32 -23
  62. mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +60 -34
  63. mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +22 -15
  64. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +25 -24
  65. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +1 -1
  66. mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +13 -9
  67. mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +12 -46
  68. mx_bluesky/hyperion/external_interaction/config_server.py +15 -1
  69. mx_bluesky/hyperion/parameters/components.py +3 -2
  70. mx_bluesky/hyperion/parameters/constants.py +1 -0
  71. mx_bluesky/hyperion/parameters/gridscan.py +54 -89
  72. mx_bluesky/hyperion/parameters/load_centre_collect.py +51 -6
  73. mx_bluesky/hyperion/parameters/robot_load.py +40 -0
  74. mx_bluesky/hyperion/parameters/rotation.py +28 -3
  75. mx_bluesky/hyperion/utils/context.py +1 -1
  76. mx_bluesky/hyperion/utils/validation.py +4 -2
  77. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.4.dist-info}/METADATA +6 -6
  78. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.4.dist-info}/RECORD +89 -87
  79. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.4.dist-info}/WHEEL +1 -1
  80. mx_bluesky/common/parameters/robot_load.py +0 -16
  81. mx_bluesky/hyperion/external_interaction/exceptions.py +0 -4
  82. mx_bluesky/hyperion/log.py +0 -15
  83. /mx_bluesky/{hyperion/external_interaction/callbacks/xray_centre → common/external_interaction}/__init__.py +0 -0
  84. /mx_bluesky/{hyperion/external_interaction/ispyb → common/external_interaction/callbacks/common}/__init__.py +0 -0
  85. /mx_bluesky/{hyperion → common}/external_interaction/callbacks/common/abstract_event.py +0 -0
  86. /mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/log_uid_tag_callback.py +0 -0
  87. /mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/plan_reactive_callback.py +0 -0
  88. /mx_bluesky/{hyperion/external_interaction/nexus → common/external_interaction/callbacks/xray_centre}/__init__.py +0 -0
  89. /mx_bluesky/{hyperion → common}/utils/utils.py +0 -0
  90. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.4.dist-info}/LICENSE +0 -0
  91. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.4.dist-info}/entry_points.txt +0 -0
  92. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.4.dist-info}/top_level.txt +0 -0
@@ -16,7 +16,7 @@ from bluesky.utils import MsgGenerator
16
16
  from dodal.devices.aperturescatterguard import (
17
17
  ApertureScatterguard,
18
18
  )
19
- from dodal.devices.attenuator import Attenuator
19
+ from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
20
20
  from dodal.devices.backlight import Backlight
21
21
  from dodal.devices.dcm import DCM
22
22
  from dodal.devices.eiger import EigerDetector
@@ -35,8 +35,8 @@ from dodal.devices.smargon import Smargon
35
35
  from dodal.devices.synchrotron import Synchrotron
36
36
  from dodal.devices.undulator import Undulator
37
37
  from dodal.devices.xbpm_feedback import XBPMFeedback
38
- from dodal.devices.zebra import Zebra
39
- from dodal.devices.zebra_controlled_shutter import ZebraShutter
38
+ from dodal.devices.zebra.zebra import Zebra
39
+ from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
40
40
  from dodal.devices.zocalo.zocalo_results import (
41
41
  ZOCALO_READING_PLAN_NAME,
42
42
  ZOCALO_STAGE_GROUP,
@@ -47,7 +47,15 @@ from dodal.devices.zocalo.zocalo_results import (
47
47
  from event_model import RunStart
48
48
  from ophyd_async.fastcs.panda import HDFPanda
49
49
 
50
+ from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
51
+ ispyb_activation_wrapper,
52
+ )
50
53
  from mx_bluesky.common.plans.do_fgs import kickoff_and_complete_gridscan
54
+ from mx_bluesky.common.utils.exceptions import (
55
+ CrystalNotFoundException,
56
+ SampleException,
57
+ )
58
+ from mx_bluesky.common.utils.log import LOGGER
51
59
  from mx_bluesky.common.utils.tracing import TRACER
52
60
  from mx_bluesky.hyperion.device_setup_plans.read_hardware_for_setup import (
53
61
  read_hardware_during_collection,
@@ -66,17 +74,12 @@ from mx_bluesky.hyperion.device_setup_plans.setup_zebra import (
66
74
  from mx_bluesky.hyperion.device_setup_plans.xbpm_feedback import (
67
75
  transmission_and_xbpm_feedback_for_collection_decorator,
68
76
  )
69
- from mx_bluesky.hyperion.exceptions import CrystalNotFoundException, SampleException
70
77
  from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import (
71
78
  change_aperture_then_move_to_xtal,
72
79
  )
73
80
  from mx_bluesky.hyperion.experiment_plans.common.xrc_result import XRayCentreResult
74
- from mx_bluesky.hyperion.external_interaction.callbacks.xray_centre.ispyb_callback import (
75
- ispyb_activation_wrapper,
76
- )
77
- from mx_bluesky.hyperion.log import LOGGER
78
81
  from mx_bluesky.hyperion.parameters.constants import CONST
79
- from mx_bluesky.hyperion.parameters.gridscan import HyperionThreeDGridScan
82
+ from mx_bluesky.hyperion.parameters.gridscan import HyperionSpecifiedThreeDGridScan
80
83
  from mx_bluesky.hyperion.utils.context import device_composite_from_context
81
84
 
82
85
  ZOCALO_MIN_TOTAL_COUNT_THRESHOLD = 3
@@ -91,7 +94,7 @@ class FlyScanXRayCentreComposite:
91
94
  """All devices which are directly or indirectly required by this plan"""
92
95
 
93
96
  aperture_scatterguard: ApertureScatterguard
94
- attenuator: Attenuator
97
+ attenuator: BinaryFilterAttenuator
95
98
  backlight: Backlight
96
99
  dcm: DCM
97
100
  eiger: EigerDetector
@@ -109,11 +112,6 @@ class FlyScanXRayCentreComposite:
109
112
  robot: BartRobot
110
113
  sample_shutter: ZebraShutter
111
114
 
112
- @property
113
- def sample_motors(self) -> Smargon:
114
- """Convenience alias with a more user-friendly name"""
115
- return self.smargon
116
-
117
115
 
118
116
  class XRayCentreEventHandler(CallbackBase):
119
117
  def __init__(self):
@@ -135,7 +133,7 @@ def create_devices(context: BlueskyContext) -> FlyScanXRayCentreComposite:
135
133
 
136
134
 
137
135
  def flyscan_xray_centre_no_move(
138
- composite: FlyScanXRayCentreComposite, parameters: HyperionThreeDGridScan
136
+ composite: FlyScanXRayCentreComposite, parameters: HyperionSpecifiedThreeDGridScan
139
137
  ) -> MsgGenerator:
140
138
  """Perform a flyscan and determine the centres of interest"""
141
139
  parameters.features.update_self_from_server()
@@ -149,7 +147,7 @@ def flyscan_xray_centre_no_move(
149
147
  @bpp.run_decorator( # attach experiment metadata to the start document
150
148
  md={
151
149
  "subplan_name": CONST.PLAN.GRIDSCAN_OUTER,
152
- "hyperion_parameters": parameters.model_dump_json(),
150
+ "mx_bluesky_parameters": parameters.model_dump_json(),
153
151
  "activate_callbacks": [
154
152
  "GridscanNexusFileCallback",
155
153
  ],
@@ -163,7 +161,7 @@ def flyscan_xray_centre_no_move(
163
161
  )
164
162
  def run_gridscan_and_fetch_and_tidy(
165
163
  fgs_composite: FlyScanXRayCentreComposite,
166
- params: HyperionThreeDGridScan,
164
+ params: HyperionSpecifiedThreeDGridScan,
167
165
  feature_controlled: _FeatureControlled,
168
166
  ) -> MsgGenerator:
169
167
  yield from run_gridscan_and_fetch_results(
@@ -177,7 +175,7 @@ def flyscan_xray_centre_no_move(
177
175
 
178
176
  def flyscan_xray_centre(
179
177
  composite: FlyScanXRayCentreComposite,
180
- parameters: HyperionThreeDGridScan,
178
+ parameters: HyperionSpecifiedThreeDGridScan,
181
179
  ) -> MsgGenerator:
182
180
  """Create the plan to run the grid scan based on provided parameters.
183
181
 
@@ -185,7 +183,7 @@ def flyscan_xray_centre(
185
183
  at any point in it.
186
184
 
187
185
  Args:
188
- parameters (ThreeDGridScan): The parameters to run the scan.
186
+ parameters (HyperionSpecifiedThreeDGridScan): The parameters to run the scan.
189
187
 
190
188
  Returns:
191
189
  Generator: The plan for the gridscan
@@ -201,9 +199,9 @@ def flyscan_xray_centre(
201
199
  yield from flyscan_and_fetch_results()
202
200
 
203
201
  xray_centre_results = xrc_event_handler.xray_centre_results
204
- assert (
205
- xray_centre_results
206
- ), "Flyscan result event not received or no crystal found and exception not raised"
202
+ assert xray_centre_results, (
203
+ "Flyscan result event not received or no crystal found and exception not raised"
204
+ )
207
205
  yield from change_aperture_then_move_to_xtal(
208
206
  xray_centre_results[0],
209
207
  composite.smargon,
@@ -216,22 +214,13 @@ def flyscan_xray_centre(
216
214
  @bpp.run_decorator(md={"subplan_name": CONST.PLAN.GRIDSCAN_AND_MOVE})
217
215
  def run_gridscan_and_fetch_results(
218
216
  fgs_composite: FlyScanXRayCentreComposite,
219
- parameters: HyperionThreeDGridScan,
217
+ parameters: HyperionSpecifiedThreeDGridScan,
220
218
  feature_controlled: _FeatureControlled,
221
219
  ) -> MsgGenerator:
222
220
  """A multi-run plan which runs a gridscan, gets the results from zocalo
223
221
  and fires an event with the centres of mass determined by zocalo"""
224
222
 
225
- # We get the initial motor positions so we can return to them on zocalo failure
226
- initial_xyz = np.array(
227
- [
228
- (yield from bps.rd(fgs_composite.sample_motors.x)),
229
- (yield from bps.rd(fgs_composite.sample_motors.y)),
230
- (yield from bps.rd(fgs_composite.sample_motors.z)),
231
- ]
232
- )
233
-
234
- yield from feature_controlled.setup_trigger(fgs_composite, parameters, initial_xyz)
223
+ yield from feature_controlled.setup_trigger(fgs_composite, parameters)
235
224
 
236
225
  LOGGER.info("Starting grid scan")
237
226
  yield from bps.stage(
@@ -280,20 +269,26 @@ def run_gridscan_and_fetch_results(
280
269
 
281
270
 
282
271
  def _xrc_result_in_boxes_to_result_in_mm(
283
- xrc_result: XrcResult, parameters: HyperionThreeDGridScan
272
+ xrc_result: XrcResult, parameters: HyperionSpecifiedThreeDGridScan
284
273
  ) -> XRayCentreResult:
285
274
  fgs_params = parameters.FGS_params
286
275
  xray_centre = fgs_params.grid_position_to_motor_position(
287
276
  np.array(xrc_result["centre_of_mass"])
288
277
  )
278
+ # A correction is applied to the bounding box to map discrete grid coordinates to
279
+ # the corners of the box in motor-space; we do not apply this correction
280
+ # to the xray-centre as it is already in continuous space and the conversion has
281
+ # been performed already
282
+ # In other words, xrc_result["bounding_box"] contains the position of the box centre,
283
+ # so we subtract half a box to get the corner of the box
289
284
  return XRayCentreResult(
290
285
  centre_of_mass_mm=xray_centre,
291
286
  bounding_box_mm=(
292
287
  fgs_params.grid_position_to_motor_position(
293
- np.array(xrc_result["bounding_box"][0])
288
+ np.array(xrc_result["bounding_box"][0]) - 0.5
294
289
  ),
295
290
  fgs_params.grid_position_to_motor_position(
296
- np.array(xrc_result["bounding_box"][1])
291
+ np.array(xrc_result["bounding_box"][1]) - 0.5
297
292
  ),
298
293
  ),
299
294
  max_count=xrc_result["max_count"],
@@ -316,17 +311,15 @@ def _fire_xray_centre_result_event(results: Sequence[XRayCentreResult]):
316
311
  @bpp.run_decorator(md={"subplan_name": CONST.PLAN.GRIDSCAN_MAIN})
317
312
  def run_gridscan(
318
313
  fgs_composite: FlyScanXRayCentreComposite,
319
- parameters: HyperionThreeDGridScan,
314
+ parameters: HyperionSpecifiedThreeDGridScan,
320
315
  feature_controlled: _FeatureControlled,
321
316
  md={ # noqa
322
317
  "plan_name": CONST.PLAN.GRIDSCAN_MAIN,
323
318
  },
324
319
  ):
325
- sample_motors = fgs_composite.sample_motors
326
-
327
320
  # Currently gridscan only works for omega 0, see #
328
321
  with TRACER.start_span("moving_omega_to_0"):
329
- yield from bps.abs_set(sample_motors.omega, 0)
322
+ yield from bps.abs_set(fgs_composite.smargon.omega, 0)
330
323
 
331
324
  # We only subscribe to the communicator callback for run_gridscan, so this is where
332
325
  # we should generate an event reading the values which need to be included in the
@@ -398,8 +391,7 @@ class _FeatureControlled:
398
391
  def __call__(
399
392
  self,
400
393
  fgs_composite: FlyScanXRayCentreComposite,
401
- parameters: HyperionThreeDGridScan,
402
- initial_xyz: np.ndarray,
394
+ parameters: HyperionSpecifiedThreeDGridScan,
403
395
  ) -> MsgGenerator: ...
404
396
 
405
397
  setup_trigger: _ExtraSetup
@@ -410,7 +402,7 @@ class _FeatureControlled:
410
402
 
411
403
  def _get_feature_controlled(
412
404
  fgs_composite: FlyScanXRayCentreComposite,
413
- parameters: HyperionThreeDGridScan,
405
+ parameters: HyperionSpecifiedThreeDGridScan,
414
406
  ):
415
407
  if parameters.features.use_panda_for_gridscan:
416
408
  return _FeatureControlled(
@@ -459,8 +451,7 @@ def _panda_tidy(fgs_composite: FlyScanXRayCentreComposite):
459
451
 
460
452
  def _zebra_triggering_setup(
461
453
  fgs_composite: FlyScanXRayCentreComposite,
462
- parameters: HyperionThreeDGridScan,
463
- initial_xyz: np.ndarray,
454
+ parameters: HyperionSpecifiedThreeDGridScan,
464
455
  ):
465
456
  yield from setup_zebra_for_gridscan(
466
457
  fgs_composite.zebra, fgs_composite.sample_shutter, wait=True
@@ -469,8 +460,7 @@ def _zebra_triggering_setup(
469
460
 
470
461
  def _panda_triggering_setup(
471
462
  fgs_composite: FlyScanXRayCentreComposite,
472
- parameters: HyperionThreeDGridScan,
473
- initial_xyz: np.ndarray,
463
+ parameters: HyperionSpecifiedThreeDGridScan,
474
464
  ):
475
465
  LOGGER.info("Setting up Panda for flyscan")
476
466
 
@@ -515,7 +505,7 @@ def _panda_triggering_setup(
515
505
  yield from setup_panda_for_flyscan(
516
506
  fgs_composite.panda,
517
507
  parameters.panda_FGS_params,
518
- initial_xyz[0],
508
+ fgs_composite.smargon,
519
509
  parameters.exposure_time_s,
520
510
  time_between_x_steps_ms,
521
511
  sample_velocity_mm_per_s,
@@ -9,13 +9,14 @@ from bluesky import preprocessors as bpp
9
9
  from bluesky.preprocessors import subs_decorator
10
10
  from bluesky.utils import MsgGenerator
11
11
  from dodal.devices.aperturescatterguard import ApertureScatterguard
12
- from dodal.devices.attenuator import Attenuator
12
+ from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
13
13
  from dodal.devices.backlight import Backlight, BacklightPosition
14
14
  from dodal.devices.dcm import DCM
15
15
  from dodal.devices.detector.detector_motion import DetectorMotion
16
16
  from dodal.devices.eiger import EigerDetector
17
17
  from dodal.devices.fast_grid_scan import PandAFastGridScan, ZebraFastGridScan
18
18
  from dodal.devices.flux import Flux
19
+ from dodal.devices.i03.beamstop import Beamstop
19
20
  from dodal.devices.oav.oav_detector import OAV
20
21
  from dodal.devices.oav.oav_parameters import OAVParameters
21
22
  from dodal.devices.oav.pin_image_recognition import PinTipDetection
@@ -25,13 +26,20 @@ from dodal.devices.smargon import Smargon
25
26
  from dodal.devices.synchrotron import Synchrotron
26
27
  from dodal.devices.undulator import Undulator
27
28
  from dodal.devices.xbpm_feedback import XBPMFeedback
28
- from dodal.devices.zebra import Zebra
29
- from dodal.devices.zebra_controlled_shutter import ZebraShutter
29
+ from dodal.devices.zebra.zebra import Zebra
30
+ from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
30
31
  from dodal.devices.zocalo import ZocaloResults
31
32
  from ophyd_async.fastcs.panda import HDFPanda
32
33
 
34
+ from mx_bluesky.common.external_interaction.callbacks.common.grid_detection_callback import (
35
+ GridDetectionCallback,
36
+ GridParamUpdate,
37
+ )
38
+ from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
39
+ ispyb_activation_wrapper,
40
+ )
33
41
  from mx_bluesky.common.parameters.constants import OavConstants
34
- from mx_bluesky.common.parameters.gridscan import GridScanWithEdgeDetect
42
+ from mx_bluesky.common.utils.log import LOGGER
35
43
  from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import (
36
44
  move_aperture_if_required,
37
45
  )
@@ -52,17 +60,10 @@ from mx_bluesky.hyperion.experiment_plans.oav_grid_detection_plan import (
52
60
  OavGridDetectionComposite,
53
61
  grid_detection_plan,
54
62
  )
55
- from mx_bluesky.hyperion.external_interaction.callbacks.grid_detection_callback import (
56
- GridDetectionCallback,
57
- GridParamUpdate,
58
- )
59
- from mx_bluesky.hyperion.external_interaction.callbacks.xray_centre.ispyb_callback import (
60
- ispyb_activation_wrapper,
61
- )
62
- from mx_bluesky.hyperion.log import LOGGER
63
63
  from mx_bluesky.hyperion.parameters.constants import CONST
64
64
  from mx_bluesky.hyperion.parameters.gridscan import (
65
- HyperionThreeDGridScan,
65
+ GridScanWithEdgeDetect,
66
+ HyperionSpecifiedThreeDGridScan,
66
67
  )
67
68
  from mx_bluesky.hyperion.utils.context import device_composite_from_context
68
69
 
@@ -72,8 +73,9 @@ class GridDetectThenXRayCentreComposite:
72
73
  """All devices which are directly or indirectly required by this plan"""
73
74
 
74
75
  aperture_scatterguard: ApertureScatterguard
75
- attenuator: Attenuator
76
+ attenuator: BinaryFilterAttenuator
76
77
  backlight: Backlight
78
+ beamstop: Beamstop
77
79
  dcm: DCM
78
80
  detector_motion: DetectorMotion
79
81
  eiger: EigerDetector
@@ -93,10 +95,6 @@ class GridDetectThenXRayCentreComposite:
93
95
  robot: BartRobot
94
96
  sample_shutter: ZebraShutter
95
97
 
96
- @property
97
- def sample_motors(self):
98
- return self.smargon
99
-
100
98
 
101
99
  def create_devices(context: BlueskyContext) -> GridDetectThenXRayCentreComposite:
102
100
  return device_composite_from_context(context, GridDetectThenXRayCentreComposite)
@@ -105,10 +103,10 @@ def create_devices(context: BlueskyContext) -> GridDetectThenXRayCentreComposite
105
103
  def create_parameters_for_flyscan_xray_centre(
106
104
  grid_scan_with_edge_params: GridScanWithEdgeDetect,
107
105
  grid_parameters: GridParamUpdate,
108
- ) -> HyperionThreeDGridScan:
106
+ ) -> HyperionSpecifiedThreeDGridScan:
109
107
  params_json = grid_scan_with_edge_params.model_dump()
110
108
  params_json.update(grid_parameters)
111
- flyscan_xray_centre_parameters = HyperionThreeDGridScan(**params_json)
109
+ flyscan_xray_centre_parameters = HyperionSpecifiedThreeDGridScan(**params_json)
112
110
  LOGGER.info(f"Parameters for FGS: {flyscan_xray_centre_parameters}")
113
111
  return flyscan_xray_centre_parameters
114
112
 
@@ -217,6 +215,7 @@ def grid_detect_then_xray_centre(
217
215
  )
218
216
 
219
217
  yield from start_preparing_data_collection_then_do_plan(
218
+ composite.beamstop,
220
219
  eiger,
221
220
  composite.detector_motion,
222
221
  parameters.detector_params.detector_distance,
@@ -224,9 +223,9 @@ def grid_detect_then_xray_centre(
224
223
  group=CONST.WAIT.GRID_READY_FOR_DC,
225
224
  )
226
225
 
227
- assert (
228
- flyscan_event_handler.xray_centre_results
229
- ), "Flyscan result event not received or no crystal found and exception not raised"
226
+ assert flyscan_event_handler.xray_centre_results, (
227
+ "Flyscan result event not received or no crystal found and exception not raised"
228
+ )
230
229
 
231
230
  yield from change_aperture_then_move_to_xtal(
232
231
  flyscan_event_handler.xray_centre_results[0],
@@ -7,9 +7,9 @@ from blueapi.core import BlueskyContext
7
7
  from bluesky.preprocessors import run_decorator, set_run_key_decorator, subs_wrapper
8
8
  from bluesky.utils import MsgGenerator
9
9
  from dodal.devices.oav.oav_parameters import OAVParameters
10
- from dodal.devices.smargon import Smargon
11
10
 
12
11
  import mx_bluesky.hyperion.experiment_plans.common.xrc_result as flyscan_result
12
+ from mx_bluesky.common.utils.log import LOGGER
13
13
  from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
14
14
  XRayCentreEventHandler,
15
15
  )
@@ -22,10 +22,6 @@ from mx_bluesky.hyperion.experiment_plans.rotation_scan_plan import (
22
22
  RotationScanComposite,
23
23
  multi_rotation_scan,
24
24
  )
25
- from mx_bluesky.hyperion.external_interaction.callbacks.sample_handling.sample_handling_callback import (
26
- sample_handling_callback_decorator,
27
- )
28
- from mx_bluesky.hyperion.log import LOGGER
29
25
  from mx_bluesky.hyperion.parameters.constants import CONST
30
26
  from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
31
27
  from mx_bluesky.hyperion.utils.context import device_composite_from_context
@@ -35,10 +31,6 @@ from mx_bluesky.hyperion.utils.context import device_composite_from_context
35
31
  class LoadCentreCollectComposite(RobotLoadThenCentreComposite, RotationScanComposite):
36
32
  """Composite that provides access to the required devices."""
37
33
 
38
- @property
39
- def sample_motors(self) -> Smargon:
40
- return self.smargon
41
-
42
34
 
43
35
  def create_devices(context: BlueskyContext) -> LoadCentreCollectComposite:
44
36
  """Create the necessary devices for the plan."""
@@ -67,7 +59,6 @@ def load_centre_collect_full(
67
59
  "activate_callbacks": ["SampleHandlingCallback"],
68
60
  }
69
61
  )
70
- @sample_handling_callback_decorator()
71
62
  def plan_with_callback_subs():
72
63
  flyscan_event_handler = XRayCentreEventHandler()
73
64
  yield from subs_wrapper(
@@ -75,7 +66,9 @@ def load_centre_collect_full(
75
66
  flyscan_event_handler,
76
67
  )
77
68
 
78
- assert flyscan_event_handler.xray_centre_results, "Flyscan result event not received or no crystal found and exception not raised"
69
+ assert flyscan_event_handler.xray_centre_results, (
70
+ "Flyscan result event not received or no crystal found and exception not raised"
71
+ )
79
72
 
80
73
  selection_func = flyscan_result.resolve_selection_fn(
81
74
  parameters.selection_params
@@ -14,11 +14,11 @@ from dodal.devices.oav.pin_image_recognition.utils import NONE_VALUE
14
14
  from dodal.devices.oav.utils import PinNotFoundException, wait_for_tip_to_be_found
15
15
  from dodal.devices.smargon import Smargon
16
16
 
17
+ from mx_bluesky.common.utils.exceptions import catch_exception_and_warn
18
+ from mx_bluesky.common.utils.log import LOGGER
17
19
  from mx_bluesky.hyperion.device_setup_plans.setup_oav import (
18
20
  pre_centring_setup_oav,
19
21
  )
20
- from mx_bluesky.hyperion.exceptions import catch_exception_and_warn
21
- from mx_bluesky.hyperion.log import LOGGER
22
22
  from mx_bluesky.hyperion.parameters.constants import CONST
23
23
  from mx_bluesky.hyperion.utils.context import device_composite_from_context
24
24
 
@@ -139,7 +139,7 @@ def grid_detection_plan(
139
139
  # See https://github.com/DiamondLightSource/hyperion/wiki/PandA-constant%E2%80%90motion-scanning#motion-program-summary
140
140
  if y_steps % 2 and angle == 0:
141
141
  LOGGER.debug(
142
- f"Forcing number of rows in first grid to be even: Adding an extra row onto bottom of first grid and shifting grid upwards by {box_size_y_pixels/2}"
142
+ f"Forcing number of rows in first grid to be even: Adding an extra row onto bottom of first grid and shifting grid upwards by {box_size_y_pixels / 2}"
143
143
  )
144
144
  y_steps += 1
145
145
  min_y -= box_size_y_pixels / 2
@@ -5,11 +5,11 @@ import bluesky.preprocessors as bpp
5
5
  import numpy as np
6
6
  import pydantic
7
7
  from blueapi.core import BlueskyContext
8
- from dodal.devices.attenuator import Attenuator
8
+ from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
9
9
  from dodal.devices.xspress3.xspress3 import Xspress3
10
- from dodal.devices.zebra_controlled_shutter import ZebraShutter, ZebraShutterState
10
+ from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter, ZebraShutterState
11
11
 
12
- from mx_bluesky.hyperion.log import LOGGER
12
+ from mx_bluesky.common.utils.log import LOGGER
13
13
  from mx_bluesky.hyperion.utils.context import device_composite_from_context
14
14
 
15
15
 
@@ -26,7 +26,7 @@ class Direction(Enum):
26
26
  class OptimizeAttenuationComposite:
27
27
  """All devices which are directly or indirectly required by this plan"""
28
28
 
29
- attenuator: Attenuator
29
+ attenuator: BinaryFilterAttenuator
30
30
  sample_shutter: ZebraShutter
31
31
  xspress3mini: Xspress3
32
32
 
@@ -197,11 +197,7 @@ def deadtime_optimisation(
197
197
  cycles to complete.
198
198
 
199
199
  Args:
200
- attenuator: (Attenuator) Ophyd device
201
-
202
- xspress3mini: (Xspress3Mini) Ophyd device
203
-
204
- sample_shutter: (ZebraShutter) Ophyd_async device for the fast shutter
200
+ composite: (OptimizeAttenuationComposite) Devices required to optimise attenuation
205
201
 
206
202
  transmission: (float)
207
203
  The initial transmission value to use for the optimising
@@ -302,11 +298,7 @@ def total_counts_optimisation(
302
298
  defined by the lower and upper limit. To protect the sample, the transmission has a maximum value of 10%.
303
299
 
304
300
  Args:
305
- attenuator: (Attenuator) Ophyd device
306
-
307
- xspress3mini: (Xspress3Mini) Ophyd device
308
-
309
- sample_shutter: (ZebraShutter) Ophyd_async device for the fast shutter
301
+ composite: (OptimizeAttenuationComposite) Devices required to optimise attenuation
310
302
 
311
303
  transmission: (float)
312
304
  The initial transmission value to use for the optimising
@@ -8,11 +8,11 @@ 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.parameters.constants import OavConstants
12
- from mx_bluesky.common.parameters.gridscan import (
13
- GridScanWithEdgeDetect,
14
- PinTipCentreThenXrayCentre,
11
+ from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
12
+ ispyb_activation_wrapper,
15
13
  )
14
+ from mx_bluesky.common.parameters.constants import OavConstants
15
+ from mx_bluesky.common.utils.log import LOGGER
16
16
  from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import move_phi_chi_omega
17
17
  from mx_bluesky.hyperion.device_setup_plans.utils import (
18
18
  start_preparing_data_collection_then_do_plan,
@@ -34,11 +34,11 @@ from mx_bluesky.hyperion.experiment_plans.pin_tip_centring_plan import (
34
34
  PinTipCentringComposite,
35
35
  pin_tip_centre_plan,
36
36
  )
37
- from mx_bluesky.hyperion.external_interaction.callbacks.xray_centre.ispyb_callback import (
38
- ispyb_activation_wrapper,
39
- )
40
- from mx_bluesky.hyperion.log import LOGGER
41
37
  from mx_bluesky.hyperion.parameters.constants import CONST
38
+ from mx_bluesky.hyperion.parameters.gridscan import (
39
+ GridScanWithEdgeDetect,
40
+ PinTipCentreThenXrayCentre,
41
+ )
42
42
  from mx_bluesky.hyperion.utils.context import device_composite_from_context
43
43
 
44
44
 
@@ -121,6 +121,7 @@ def pin_tip_centre_then_xray_centre(
121
121
  @bpp.subs_decorator(flyscan_event_handler)
122
122
  def pin_centre_flyscan_then_fetch_results() -> MsgGenerator:
123
123
  yield from start_preparing_data_collection_then_do_plan(
124
+ composite.beamstop,
124
125
  eiger,
125
126
  composite.detector_motion,
126
127
  parameters.detector_params.detector_distance,
@@ -130,9 +131,9 @@ def pin_tip_centre_then_xray_centre(
130
131
 
131
132
  yield from pin_centre_flyscan_then_fetch_results()
132
133
  flyscan_results = flyscan_event_handler.xray_centre_results
133
- assert (
134
- flyscan_results
135
- ), "Flyscan result event not received or no crystal found and exception not raised"
134
+ assert flyscan_results, (
135
+ "Flyscan result event not received or no crystal found and exception not raised"
136
+ )
136
137
  yield from change_aperture_then_move_to_xtal(
137
138
  flyscan_results[0], composite.smargon, composite.aperture_scatterguard
138
139
  )
@@ -15,12 +15,12 @@ from dodal.devices.oav.utils import (
15
15
  )
16
16
  from dodal.devices.smargon import Smargon
17
17
 
18
+ from mx_bluesky.common.utils.exceptions import SampleException
19
+ from mx_bluesky.common.utils.log import LOGGER
18
20
  from mx_bluesky.hyperion.device_setup_plans.setup_oav import pre_centring_setup_oav
19
21
  from mx_bluesky.hyperion.device_setup_plans.smargon import (
20
22
  move_smargon_warn_on_out_of_range,
21
23
  )
22
- from mx_bluesky.hyperion.exceptions import SampleException
23
- from mx_bluesky.hyperion.log import LOGGER
24
24
  from mx_bluesky.hyperion.parameters.constants import CONST
25
25
  from mx_bluesky.hyperion.utils.context import device_composite_from_context
26
26
 
@@ -11,7 +11,7 @@ import pydantic
11
11
  from blueapi.core import BlueskyContext
12
12
  from bluesky.utils import Msg
13
13
  from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureValue
14
- from dodal.devices.attenuator import Attenuator
14
+ from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
15
15
  from dodal.devices.dcm import DCM
16
16
  from dodal.devices.focusing_mirror import FocusingMirrorWithStripes, MirrorVoltages
17
17
  from dodal.devices.motors import XYZPositioner
@@ -24,13 +24,13 @@ from dodal.devices.webcam import Webcam
24
24
  from dodal.devices.xbpm_feedback import XBPMFeedback
25
25
  from dodal.plan_stubs.motor_utils import MoveTooLarge, home_and_reset_wrapper
26
26
 
27
- from mx_bluesky.common.parameters.robot_load import RobotLoadAndEnergyChange
27
+ from mx_bluesky.common.utils.log import LOGGER
28
28
  from mx_bluesky.hyperion.experiment_plans.set_energy_plan import (
29
29
  SetEnergyComposite,
30
30
  set_energy_plan,
31
31
  )
32
- from mx_bluesky.hyperion.log import LOGGER
33
32
  from mx_bluesky.hyperion.parameters.constants import CONST
33
+ from mx_bluesky.hyperion.parameters.robot_load import RobotLoadAndEnergyChange
34
34
 
35
35
 
36
36
  @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
@@ -41,7 +41,7 @@ class RobotLoadAndEnergyChangeComposite:
41
41
  dcm: DCM
42
42
  undulator_dcm: UndulatorDCM
43
43
  xbpm_feedback: XBPMFeedback
44
- attenuator: Attenuator
44
+ attenuator: BinaryFilterAttenuator
45
45
 
46
46
  # RobotLoad fields
47
47
  robot: BartRobot
@@ -122,6 +122,11 @@ def do_robot_load(
122
122
  demand_energy_ev: float | None,
123
123
  thawing_time: float,
124
124
  ):
125
+ error_code = yield from bps.rd(composite.robot.error_code)
126
+ # Reset robot if light curtains were tripped
127
+ if error_code == 40:
128
+ yield from bps.trigger(composite.robot.reset, wait=True)
129
+
125
130
  yield from bps.abs_set(
126
131
  composite.robot,
127
132
  sample_location,