mx-bluesky 1.4.4__py3-none-any.whl → 1.4.6__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 (74) hide show
  1. mx_bluesky/_version.py +9 -4
  2. mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +14 -3
  3. mx_bluesky/beamlines/i04/thawing_plan.py +9 -13
  4. mx_bluesky/beamlines/i24/serial/__init__.py +14 -0
  5. mx_bluesky/beamlines/i24/serial/dcid.py +3 -1
  6. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +1 -1
  7. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +6 -3
  8. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +11 -11
  9. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +3 -3
  10. mx_bluesky/beamlines/i24/serial/log.py +0 -1
  11. mx_bluesky/beamlines/i24/serial/parameters/constants.py +1 -1
  12. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +3 -3
  13. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +1 -1
  14. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +2 -2
  15. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +109 -0
  16. mx_bluesky/beamlines/i24/serial/write_nexus.py +2 -2
  17. mx_bluesky/common/device_setup_plans/setup_panda.py +9 -0
  18. mx_bluesky/common/external_interaction/callbacks/common/plan_reactive_callback.py +2 -2
  19. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +11 -3
  20. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_mapping.py +1 -1
  21. mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +6 -2
  22. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +7 -0
  23. mx_bluesky/common/parameters/constants.py +16 -0
  24. mx_bluesky/common/parameters/gridscan.py +36 -1
  25. mx_bluesky/common/plans/do_fgs.py +4 -6
  26. mx_bluesky/common/plans/read_hardware.py +78 -0
  27. mx_bluesky/common/utils/context.py +68 -0
  28. mx_bluesky/common/utils/exceptions.py +2 -1
  29. mx_bluesky/{hyperion/experiment_plans/common → common}/xrc_result.py +16 -0
  30. mx_bluesky/definitions.py +4 -0
  31. mx_bluesky/hyperion/__main__.py +11 -42
  32. mx_bluesky/hyperion/device_setup_plans/setup_oav.py +5 -5
  33. mx_bluesky/hyperion/device_setup_plans/setup_panda.py +9 -8
  34. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +2 -2
  35. mx_bluesky/hyperion/device_setup_plans/smargon.py +6 -6
  36. mx_bluesky/hyperion/device_setup_plans/utils.py +2 -2
  37. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +14 -4
  38. mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +2 -6
  39. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +0 -15
  40. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +42 -93
  41. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +14 -6
  42. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +26 -21
  43. mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +11 -11
  44. mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +5 -9
  45. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +1 -1
  46. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +2 -4
  47. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +10 -10
  48. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +11 -18
  49. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +2 -4
  50. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +19 -10
  51. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -0
  52. mx_bluesky/hyperion/external_interaction/agamemnon.py +104 -0
  53. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +19 -2
  54. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +1 -1
  55. mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +14 -9
  56. mx_bluesky/hyperion/external_interaction/config_server.py +13 -2
  57. mx_bluesky/hyperion/parameters/cli.py +1 -9
  58. mx_bluesky/hyperion/parameters/constants.py +6 -1
  59. mx_bluesky/hyperion/parameters/device_composites.py +49 -0
  60. mx_bluesky/hyperion/parameters/gridscan.py +5 -3
  61. mx_bluesky/hyperion/resources/panda/panda-gridscan.yaml +1006 -964
  62. mx_bluesky/hyperion/utils/__init__.py +1 -0
  63. mx_bluesky/hyperion/utils/context.py +0 -65
  64. mx_bluesky/hyperion/utils/validation.py +23 -20
  65. {mx_bluesky-1.4.4.dist-info → mx_bluesky-1.4.6.dist-info}/METADATA +5 -4
  66. {mx_bluesky-1.4.4.dist-info → mx_bluesky-1.4.6.dist-info}/RECORD +71 -66
  67. {mx_bluesky-1.4.4.dist-info → mx_bluesky-1.4.6.dist-info}/WHEEL +1 -1
  68. {mx_bluesky-1.4.4.dist-info → mx_bluesky-1.4.6.dist-info}/entry_points.txt +1 -0
  69. mx_bluesky/common/device_setup_plans/read_hardware_for_setup.py +0 -14
  70. mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +0 -54
  71. mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +0 -95
  72. /mx_bluesky/{hyperion/external_interaction/callbacks/common → beamlines/i24/serial/web_gui_plans}/__init__.py +0 -0
  73. {mx_bluesky-1.4.4.dist-info → mx_bluesky-1.4.6.dist-info}/LICENSE +0 -0
  74. {mx_bluesky-1.4.4.dist-info → mx_bluesky-1.4.6.dist-info}/top_level.txt +0 -0
@@ -11,13 +11,6 @@ from mx_bluesky.hyperion.experiment_plans import (
11
11
  pin_centre_then_xray_centre_plan,
12
12
  robot_load_then_centre_plan,
13
13
  )
14
- from mx_bluesky.hyperion.external_interaction.callbacks.common.callback_util import (
15
- CallbacksFactory,
16
- create_gridscan_callbacks,
17
- create_load_centre_collect_callbacks,
18
- create_robot_load_and_centre_callbacks,
19
- create_rotation_callbacks,
20
- )
21
14
  from mx_bluesky.hyperion.parameters.gridscan import (
22
15
  GridScanWithEdgeDetect,
23
16
  HyperionSpecifiedThreeDGridScan,
@@ -47,44 +40,36 @@ class ExperimentRegistryEntry(TypedDict):
47
40
  | LoadCentreCollect
48
41
  | RobotLoadThenCentre
49
42
  ]
50
- callbacks_factory: CallbacksFactory
51
43
 
52
44
 
53
45
  PLAN_REGISTRY: dict[str, ExperimentRegistryEntry] = {
54
46
  "flyscan_xray_centre": {
55
47
  "setup": flyscan_xray_centre_plan.create_devices,
56
48
  "param_type": HyperionSpecifiedThreeDGridScan,
57
- "callbacks_factory": create_gridscan_callbacks,
58
49
  },
59
50
  "grid_detect_then_xray_centre": {
60
51
  "setup": grid_detect_then_xray_centre_plan.create_devices,
61
52
  "param_type": GridScanWithEdgeDetect,
62
- "callbacks_factory": create_gridscan_callbacks,
63
53
  },
64
54
  "rotation_scan": {
65
55
  "setup": rotation_scan_plan.create_devices,
66
56
  "param_type": RotationScan,
67
- "callbacks_factory": create_rotation_callbacks,
68
57
  },
69
58
  "pin_tip_centre_then_xray_centre": {
70
59
  "setup": pin_centre_then_xray_centre_plan.create_devices,
71
60
  "param_type": PinTipCentreThenXrayCentre,
72
- "callbacks_factory": create_gridscan_callbacks,
73
61
  },
74
62
  "robot_load_then_centre": {
75
63
  "setup": robot_load_then_centre_plan.create_devices,
76
64
  "param_type": RobotLoadThenCentre,
77
- "callbacks_factory": create_robot_load_and_centre_callbacks,
78
65
  },
79
66
  "multi_rotation_scan": {
80
67
  "setup": rotation_scan_plan.create_devices,
81
68
  "param_type": MultiRotationScan,
82
- "callbacks_factory": create_rotation_callbacks,
83
69
  },
84
70
  "load_centre_collect_full": {
85
71
  "setup": load_centre_collect_full_plan.create_devices,
86
72
  "param_type": LoadCentreCollect,
87
- "callbacks_factory": create_load_centre_collect_callbacks,
88
73
  },
89
74
  }
90
75
 
@@ -9,58 +9,39 @@ from typing import Protocol
9
9
  import bluesky.plan_stubs as bps
10
10
  import bluesky.preprocessors as bpp
11
11
  import numpy as np
12
- import pydantic
13
12
  from blueapi.core import BlueskyContext
14
- from bluesky.callbacks import CallbackBase
15
13
  from bluesky.utils import MsgGenerator
16
- from dodal.devices.aperturescatterguard import (
17
- ApertureScatterguard,
18
- )
19
- from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
20
- from dodal.devices.backlight import Backlight
21
- from dodal.devices.dcm import DCM
22
- from dodal.devices.eiger import EigerDetector
23
14
  from dodal.devices.fast_grid_scan import (
24
15
  FastGridScanCommon,
25
- PandAFastGridScan,
26
- ZebraFastGridScan,
27
16
  )
28
17
  from dodal.devices.fast_grid_scan import (
29
18
  set_fast_grid_scan_params as set_flyscan_params,
30
19
  )
31
- from dodal.devices.flux import Flux
32
- from dodal.devices.robot import BartRobot
33
- from dodal.devices.s4_slit_gaps import S4SlitGaps
34
- from dodal.devices.smargon import Smargon
35
- from dodal.devices.synchrotron import Synchrotron
36
- from dodal.devices.undulator import Undulator
37
- from dodal.devices.xbpm_feedback import XBPMFeedback
38
20
  from dodal.devices.zebra.zebra import Zebra
39
- from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
40
21
  from dodal.devices.zocalo.zocalo_results import (
41
22
  ZOCALO_READING_PLAN_NAME,
42
23
  ZOCALO_STAGE_GROUP,
43
24
  XrcResult,
44
- ZocaloResults,
45
25
  get_full_processing_results,
46
26
  )
47
- from event_model import RunStart
48
- from ophyd_async.fastcs.panda import HDFPanda
49
27
 
50
28
  from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
51
29
  ispyb_activation_wrapper,
52
30
  )
31
+ from mx_bluesky.common.parameters.constants import HardwareConstants
53
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
54
38
  from mx_bluesky.common.utils.exceptions import (
55
39
  CrystalNotFoundException,
56
40
  SampleException,
57
41
  )
58
42
  from mx_bluesky.common.utils.log import LOGGER
59
43
  from mx_bluesky.common.utils.tracing import TRACER
60
- from mx_bluesky.hyperion.device_setup_plans.read_hardware_for_setup import (
61
- read_hardware_during_collection,
62
- read_hardware_pre_collection,
63
- )
44
+ from mx_bluesky.common.xrc_result import XRayCentreEventHandler, XRayCentreResult
64
45
  from mx_bluesky.hyperion.device_setup_plans.setup_panda import (
65
46
  disarm_panda_for_gridscan,
66
47
  set_panda_directory,
@@ -77,10 +58,11 @@ from mx_bluesky.hyperion.device_setup_plans.xbpm_feedback import (
77
58
  from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import (
78
59
  change_aperture_then_move_to_xtal,
79
60
  )
80
- from mx_bluesky.hyperion.experiment_plans.common.xrc_result import XRayCentreResult
81
61
  from mx_bluesky.hyperion.parameters.constants import CONST
62
+ from mx_bluesky.hyperion.parameters.device_composites import (
63
+ HyperionFlyScanXRayCentreComposite,
64
+ )
82
65
  from mx_bluesky.hyperion.parameters.gridscan import HyperionSpecifiedThreeDGridScan
83
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
84
66
 
85
67
  ZOCALO_MIN_TOTAL_COUNT_THRESHOLD = 3
86
68
 
@@ -89,57 +71,23 @@ class SmargonSpeedException(Exception):
89
71
  pass
90
72
 
91
73
 
92
- @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
93
- class FlyScanXRayCentreComposite:
94
- """All devices which are directly or indirectly required by this plan"""
95
-
96
- aperture_scatterguard: ApertureScatterguard
97
- attenuator: BinaryFilterAttenuator
98
- backlight: Backlight
99
- dcm: DCM
100
- eiger: EigerDetector
101
- zebra_fast_grid_scan: ZebraFastGridScan
102
- flux: Flux
103
- s4_slit_gaps: S4SlitGaps
104
- smargon: Smargon
105
- undulator: Undulator
106
- synchrotron: Synchrotron
107
- xbpm_feedback: XBPMFeedback
108
- zebra: Zebra
109
- zocalo: ZocaloResults
110
- panda: HDFPanda
111
- panda_fast_grid_scan: PandAFastGridScan
112
- robot: BartRobot
113
- sample_shutter: ZebraShutter
114
-
115
-
116
- class XRayCentreEventHandler(CallbackBase):
117
- def __init__(self):
118
- super().__init__()
119
- self.xray_centre_results: Sequence[XRayCentreResult] | None = None
120
-
121
- def start(self, doc: RunStart) -> RunStart | None:
122
- if "xray_centre_results" in doc:
123
- self.xray_centre_results = [
124
- XRayCentreResult(**result_dict)
125
- for result_dict in doc["xray_centre_results"] # type: ignore
126
- ]
127
- return doc
128
-
129
-
130
- def create_devices(context: BlueskyContext) -> FlyScanXRayCentreComposite:
74
+ def create_devices(context: BlueskyContext) -> HyperionFlyScanXRayCentreComposite:
131
75
  """Creates the devices required for the plan and connect to them"""
132
- return device_composite_from_context(context, FlyScanXRayCentreComposite)
76
+ return device_composite_from_context(context, HyperionFlyScanXRayCentreComposite)
133
77
 
134
78
 
135
79
  def flyscan_xray_centre_no_move(
136
- composite: FlyScanXRayCentreComposite, parameters: HyperionSpecifiedThreeDGridScan
80
+ composite: HyperionFlyScanXRayCentreComposite,
81
+ parameters: HyperionSpecifiedThreeDGridScan,
137
82
  ) -> MsgGenerator:
138
83
  """Perform a flyscan and determine the centres of interest"""
139
- parameters.features.update_self_from_server()
84
+
140
85
  composite.eiger.set_detector_parameters(parameters.detector_params)
141
86
  composite.zocalo.zocalo_environment = CONST.ZOCALO_ENV
87
+
88
+ parameters.features.update_self_from_server()
142
89
  composite.zocalo.use_cpu_and_gpu = parameters.features.compare_cpu_and_gpu_zocalo
90
+ composite.zocalo.use_gpu = parameters.features.use_gpu_results
143
91
 
144
92
  feature_controlled = _get_feature_controlled(composite, parameters)
145
93
 
@@ -155,12 +103,14 @@ def flyscan_xray_centre_no_move(
155
103
  )
156
104
  @bpp.finalize_decorator(lambda: feature_controlled.tidy_plan(composite))
157
105
  @transmission_and_xbpm_feedback_for_collection_decorator(
106
+ composite.undulator,
158
107
  composite.xbpm_feedback,
159
108
  composite.attenuator,
109
+ composite.dcm,
160
110
  parameters.transmission_frac,
161
111
  )
162
112
  def run_gridscan_and_fetch_and_tidy(
163
- fgs_composite: FlyScanXRayCentreComposite,
113
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
164
114
  params: HyperionSpecifiedThreeDGridScan,
165
115
  feature_controlled: _FeatureControlled,
166
116
  ) -> MsgGenerator:
@@ -174,7 +124,7 @@ def flyscan_xray_centre_no_move(
174
124
 
175
125
 
176
126
  def flyscan_xray_centre(
177
- composite: FlyScanXRayCentreComposite,
127
+ composite: HyperionFlyScanXRayCentreComposite,
178
128
  parameters: HyperionSpecifiedThreeDGridScan,
179
129
  ) -> MsgGenerator:
180
130
  """Create the plan to run the grid scan based on provided parameters.
@@ -213,7 +163,7 @@ def flyscan_xray_centre(
213
163
  @bpp.set_run_key_decorator(CONST.PLAN.GRIDSCAN_AND_MOVE)
214
164
  @bpp.run_decorator(md={"subplan_name": CONST.PLAN.GRIDSCAN_AND_MOVE})
215
165
  def run_gridscan_and_fetch_results(
216
- fgs_composite: FlyScanXRayCentreComposite,
166
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
217
167
  parameters: HyperionSpecifiedThreeDGridScan,
218
168
  feature_controlled: _FeatureControlled,
219
169
  ) -> MsgGenerator:
@@ -261,7 +211,7 @@ def run_gridscan_and_fetch_results(
261
211
  finally:
262
212
  # Turn off dev/shm streaming to avoid filling disk, see https://github.com/DiamondLightSource/hyperion/issues/1395
263
213
  LOGGER.info("Turning off Eiger dev/shm streaming")
264
- yield from bps.abs_set(fgs_composite.eiger.odin.fan.dev_shm_enable, 0) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
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)
265
215
 
266
216
  # Wait on everything before returning to GDA (particularly apertures), can be removed
267
217
  # when we do not return to GDA here
@@ -303,14 +253,14 @@ def _fire_xray_centre_result_event(results: Sequence[XRayCentreResult]):
303
253
 
304
254
  yield from bpp.run_wrapper(
305
255
  empty_plan(),
306
- md={"xray_centre_results": [dataclasses.asdict(r) for r in results]},
256
+ md={CONST.PLAN.FLYSCAN_RESULTS: [dataclasses.asdict(r) for r in results]},
307
257
  )
308
258
 
309
259
 
310
260
  @bpp.set_run_key_decorator(CONST.PLAN.GRIDSCAN_MAIN)
311
261
  @bpp.run_decorator(md={"subplan_name": CONST.PLAN.GRIDSCAN_MAIN})
312
262
  def run_gridscan(
313
- fgs_composite: FlyScanXRayCentreComposite,
263
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
314
264
  parameters: HyperionSpecifiedThreeDGridScan,
315
265
  feature_controlled: _FeatureControlled,
316
266
  md={ # noqa
@@ -325,7 +275,7 @@ def run_gridscan(
325
275
  # we should generate an event reading the values which need to be included in the
326
276
  # ispyb deposition
327
277
  with TRACER.start_span("ispyb_hardware_readings"):
328
- yield from read_hardware_pre_collection(
278
+ yield from standard_read_hardware_pre_collection(
329
279
  fgs_composite.undulator,
330
280
  fgs_composite.synchrotron,
331
281
  fgs_composite.s4_slit_gaps,
@@ -334,7 +284,7 @@ def run_gridscan(
334
284
  )
335
285
 
336
286
  read_during_collection = partial(
337
- read_hardware_during_collection,
287
+ standard_read_hardware_during_collection,
338
288
  fgs_composite.aperture_scatterguard,
339
289
  fgs_composite.attenuator,
340
290
  fgs_composite.flux,
@@ -350,7 +300,7 @@ def run_gridscan(
350
300
 
351
301
  LOGGER.info("Waiting for arming to finish")
352
302
  yield from bps.wait(CONST.WAIT.GRID_READY_FOR_DC)
353
- yield from bps.stage(fgs_composite.eiger) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
303
+ yield from bps.stage(fgs_composite.eiger)
354
304
 
355
305
  yield from kickoff_and_complete_gridscan(
356
306
  feature_controlled.fgs_motors,
@@ -390,18 +340,18 @@ class _FeatureControlled:
390
340
  class _ExtraSetup(Protocol):
391
341
  def __call__(
392
342
  self,
393
- fgs_composite: FlyScanXRayCentreComposite,
343
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
394
344
  parameters: HyperionSpecifiedThreeDGridScan,
395
345
  ) -> MsgGenerator: ...
396
346
 
397
347
  setup_trigger: _ExtraSetup
398
- tidy_plan: Callable[[FlyScanXRayCentreComposite], MsgGenerator]
348
+ tidy_plan: Callable[[HyperionFlyScanXRayCentreComposite], MsgGenerator]
399
349
  set_flyscan_params: Callable[[], MsgGenerator]
400
350
  fgs_motors: FastGridScanCommon
401
351
 
402
352
 
403
353
  def _get_feature_controlled(
404
- fgs_composite: FlyScanXRayCentreComposite,
354
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
405
355
  parameters: HyperionSpecifiedThreeDGridScan,
406
356
  ):
407
357
  if parameters.features.use_panda_for_gridscan:
@@ -429,7 +379,7 @@ def _get_feature_controlled(
429
379
 
430
380
 
431
381
  def _generic_tidy(
432
- fgs_composite: FlyScanXRayCentreComposite, group, wait=True
382
+ fgs_composite: HyperionFlyScanXRayCentreComposite, group, wait=True
433
383
  ) -> MsgGenerator:
434
384
  LOGGER.info("Tidying up Zebra")
435
385
  yield from tidy_up_zebra_after_gridscan(
@@ -440,7 +390,7 @@ def _generic_tidy(
440
390
  yield from bps.unstage(fgs_composite.zocalo, group=group, wait=wait)
441
391
 
442
392
 
443
- def _panda_tidy(fgs_composite: FlyScanXRayCentreComposite):
393
+ def _panda_tidy(fgs_composite: HyperionFlyScanXRayCentreComposite):
444
394
  group = "panda_flyscan_tidy"
445
395
  LOGGER.info("Disabling panda blocks")
446
396
  yield from disarm_panda_for_gridscan(fgs_composite.panda, group)
@@ -450,7 +400,7 @@ def _panda_tidy(fgs_composite: FlyScanXRayCentreComposite):
450
400
 
451
401
 
452
402
  def _zebra_triggering_setup(
453
- fgs_composite: FlyScanXRayCentreComposite,
403
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
454
404
  parameters: HyperionSpecifiedThreeDGridScan,
455
405
  ):
456
406
  yield from setup_zebra_for_gridscan(
@@ -459,7 +409,7 @@ def _zebra_triggering_setup(
459
409
 
460
410
 
461
411
  def _panda_triggering_setup(
462
- fgs_composite: FlyScanXRayCentreComposite,
412
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
463
413
  parameters: HyperionSpecifiedThreeDGridScan,
464
414
  ):
465
415
  LOGGER.info("Setting up Panda for flyscan")
@@ -468,10 +418,9 @@ def _panda_triggering_setup(
468
418
  fgs_composite.panda_fast_grid_scan.run_up_distance_mm
469
419
  )
470
420
 
471
- # Set the time between x steps pv
472
- DEADTIME_S = 1e-6 # according to https://www.dectris.com/en/detectors/x-ray-detectors/eiger2/eiger2-for-synchrotrons/eiger2-x/
473
-
474
- time_between_x_steps_ms = (DEADTIME_S + parameters.exposure_time_s) * 1e3
421
+ time_between_x_steps_ms = (
422
+ HardwareConstants.PANDA_FGS_EIGER_DEADTIME_S + parameters.exposure_time_s
423
+ ) * 1e3
475
424
 
476
425
  smargon_speed_limit_mm_per_s = yield from bps.rd(
477
426
  fgs_composite.smargon.x.max_velocity
@@ -490,13 +439,13 @@ def _panda_triggering_setup(
490
439
  )
491
440
  else:
492
441
  LOGGER.info(
493
- f"Panda grid scan: Smargon speed set to {smargon_speed_limit_mm_per_s} mm/s"
442
+ f"Panda grid scan: Smargon speed set to {sample_velocity_mm_per_s} mm/s"
494
443
  f" and using a run-up distance of {run_up_distance_mm}"
495
444
  )
496
445
 
497
446
  yield from bps.mv(
498
- fgs_composite.panda_fast_grid_scan.time_between_x_steps_ms, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
499
- time_between_x_steps_ms, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
447
+ fgs_composite.panda_fast_grid_scan.time_between_x_steps_ms,
448
+ time_between_x_steps_ms,
500
449
  )
501
450
 
502
451
  directory_provider_root = Path(parameters.storage_directory)
@@ -39,7 +39,9 @@ from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback
39
39
  ispyb_activation_wrapper,
40
40
  )
41
41
  from mx_bluesky.common.parameters.constants import OavConstants
42
+ from mx_bluesky.common.utils.context import device_composite_from_context
42
43
  from mx_bluesky.common.utils.log import LOGGER
44
+ from mx_bluesky.common.xrc_result import XRayCentreEventHandler
43
45
  from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import (
44
46
  move_aperture_if_required,
45
47
  )
@@ -50,10 +52,6 @@ from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import
50
52
  change_aperture_then_move_to_xtal,
51
53
  )
52
54
  from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
53
- FlyScanXRayCentreComposite as FlyScanXRayCentreComposite,
54
- )
55
- from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
56
- XRayCentreEventHandler,
57
55
  flyscan_xray_centre_no_move,
58
56
  )
59
57
  from mx_bluesky.hyperion.experiment_plans.oav_grid_detection_plan import (
@@ -61,11 +59,13 @@ from mx_bluesky.hyperion.experiment_plans.oav_grid_detection_plan import (
61
59
  grid_detection_plan,
62
60
  )
63
61
  from mx_bluesky.hyperion.parameters.constants import CONST
62
+ from mx_bluesky.hyperion.parameters.device_composites import (
63
+ HyperionFlyScanXRayCentreComposite,
64
+ )
64
65
  from mx_bluesky.hyperion.parameters.gridscan import (
65
66
  GridScanWithEdgeDetect,
66
67
  HyperionSpecifiedThreeDGridScan,
67
68
  )
68
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
69
69
 
70
70
 
71
71
  @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
@@ -142,6 +142,14 @@ def detect_grid_and_do_gridscan(
142
142
  parameters.box_size_um,
143
143
  )
144
144
 
145
+ if parameters.selected_aperture:
146
+ # Start moving the aperture/scatterguard into position without moving it in
147
+ yield from bps.prepare(
148
+ composite.aperture_scatterguard,
149
+ parameters.selected_aperture,
150
+ group=CONST.WAIT.GRID_READY_FOR_DC,
151
+ )
152
+
145
153
  yield from run_grid_detection_plan(
146
154
  oav_params,
147
155
  snapshot_template,
@@ -159,7 +167,7 @@ def detect_grid_and_do_gridscan(
159
167
  )
160
168
 
161
169
  yield from flyscan_xray_centre_no_move(
162
- FlyScanXRayCentreComposite(
170
+ HyperionFlyScanXRayCentreComposite(
163
171
  aperture_scatterguard=composite.aperture_scatterguard,
164
172
  attenuator=composite.attenuator,
165
173
  backlight=composite.backlight,
@@ -1,18 +1,17 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Sequence
4
-
3
+ import bluesky.plan_stubs as bps
4
+ import numpy as np
5
5
  import pydantic
6
6
  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
10
 
11
- import mx_bluesky.hyperion.experiment_plans.common.xrc_result as flyscan_result
11
+ import mx_bluesky.common.xrc_result as flyscan_result
12
+ from mx_bluesky.common.utils.context import device_composite_from_context
12
13
  from mx_bluesky.common.utils.log import LOGGER
13
- from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
14
- XRayCentreEventHandler,
15
- )
14
+ from mx_bluesky.common.xrc_result import XRayCentreEventHandler
16
15
  from mx_bluesky.hyperion.experiment_plans.robot_load_then_centre_plan import (
17
16
  RobotLoadThenCentreComposite,
18
17
  robot_load_then_xray_centre,
@@ -24,7 +23,6 @@ from mx_bluesky.hyperion.experiment_plans.rotation_scan_plan import (
24
23
  )
25
24
  from mx_bluesky.hyperion.parameters.constants import CONST
26
25
  from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
27
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
28
26
 
29
27
 
30
28
  @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
@@ -66,33 +64,40 @@ def load_centre_collect_full(
66
64
  flyscan_event_handler,
67
65
  )
68
66
 
69
- assert flyscan_event_handler.xray_centre_results, (
70
- "Flyscan result event not received or no crystal found and exception not raised"
71
- )
67
+ locations_to_collect_um: list[np.ndarray] = []
72
68
 
73
- selection_func = flyscan_result.resolve_selection_fn(
74
- parameters.selection_params
75
- )
76
- hits: Sequence[flyscan_result.XRayCentreResult] = selection_func(
77
- flyscan_event_handler.xray_centre_results
78
- )
79
- LOGGER.info(
80
- f"Selected hits {hits} using {selection_func}, args={parameters.selection_params}"
81
- )
69
+ if flyscan_event_handler.xray_centre_results:
70
+ selection_func = flyscan_result.resolve_selection_fn(
71
+ parameters.selection_params
72
+ )
73
+ hits = selection_func(flyscan_event_handler.xray_centre_results)
74
+ locations_to_collect_um = [hit.centre_of_mass_mm * 1000 for hit in hits]
75
+
76
+ LOGGER.info(
77
+ f"Selected hits {hits} using {selection_func}, args={parameters.selection_params}"
78
+ )
79
+ else:
80
+ # If the xray centring hasn't found a result but has not thrown an error it
81
+ # means that we do not need to recentre and can collect where we are
82
+ initial_x = yield from bps.rd(composite.smargon.x.user_readback)
83
+ initial_y = yield from bps.rd(composite.smargon.y.user_readback)
84
+ initial_z = yield from bps.rd(composite.smargon.z.user_readback)
85
+
86
+ locations_to_collect_um = [np.array([initial_x, initial_y, initial_z])]
82
87
 
83
88
  multi_rotation = parameters.multi_rotation_scan
84
89
  rotation_template = multi_rotation.rotation_scans.copy()
85
90
 
86
91
  multi_rotation.rotation_scans.clear()
87
92
 
88
- for hit in hits:
93
+ for location in locations_to_collect_um:
89
94
  for rot in rotation_template:
90
95
  combination = rot.model_copy()
91
96
  (
92
97
  combination.x_start_um,
93
98
  combination.y_start_um,
94
99
  combination.z_start_um,
95
- ) = (axis * 1000 for axis in hit.centre_of_mass_mm)
100
+ ) = location
96
101
  multi_rotation.rotation_scans.append(combination)
97
102
  multi_rotation = MultiRotationScan.model_validate(multi_rotation)
98
103
 
@@ -14,13 +14,13 @@ 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.context import device_composite_from_context
17
18
  from mx_bluesky.common.utils.exceptions import catch_exception_and_warn
18
19
  from mx_bluesky.common.utils.log import LOGGER
19
20
  from mx_bluesky.hyperion.device_setup_plans.setup_oav import (
20
21
  pre_centring_setup_oav,
21
22
  )
22
23
  from mx_bluesky.hyperion.parameters.constants import CONST
23
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
24
24
 
25
25
  if TYPE_CHECKING:
26
26
  from dodal.devices.oav.oav_parameters import OAVParameters
@@ -100,7 +100,7 @@ def grid_detection_plan(
100
100
 
101
101
  # The FGS uses -90 so we need to match it
102
102
  for angle in [0, -90]:
103
- yield from bps.mv(smargon.omega, angle) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
103
+ yield from bps.mv(smargon.omega, angle)
104
104
  # need to wait for the OAV image to update
105
105
  # See #673 for improvements
106
106
  yield from bps.sleep(CONST.HARDWARE.OAV_REFRESH_DELAY)
@@ -152,20 +152,20 @@ def grid_detection_plan(
152
152
 
153
153
  upper_left = (tip_x_px, min_y)
154
154
 
155
- yield from bps.abs_set(oav.grid_snapshot.top_left_x, upper_left[0]) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
156
- yield from bps.abs_set(oav.grid_snapshot.top_left_y, upper_left[1]) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
157
- yield from bps.abs_set(oav.grid_snapshot.box_width, box_size_x_pixels) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
158
- yield from bps.abs_set(oav.grid_snapshot.num_boxes_x, x_steps) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
159
- yield from bps.abs_set(oav.grid_snapshot.num_boxes_y, y_steps) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
155
+ yield from bps.abs_set(oav.grid_snapshot.top_left_x, upper_left[0])
156
+ yield from bps.abs_set(oav.grid_snapshot.top_left_y, upper_left[1])
157
+ yield from bps.abs_set(oav.grid_snapshot.box_width, box_size_x_pixels)
158
+ yield from bps.abs_set(oav.grid_snapshot.num_boxes_x, x_steps)
159
+ yield from bps.abs_set(oav.grid_snapshot.num_boxes_y, y_steps)
160
160
 
161
161
  snapshot_filename = snapshot_template.format(angle=abs(angle))
162
162
 
163
- yield from bps.abs_set(oav.grid_snapshot.filename, snapshot_filename) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
164
- yield from bps.abs_set(oav.grid_snapshot.directory, snapshot_dir) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
165
- yield from bps.trigger(oav.grid_snapshot, wait=True) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
163
+ yield from bps.abs_set(oav.grid_snapshot.filename, snapshot_filename)
164
+ yield from bps.abs_set(oav.grid_snapshot.directory, snapshot_dir)
165
+ yield from bps.trigger(oav.grid_snapshot, wait=True)
166
166
  yield from bps.create(CONST.DESCRIPTORS.OAV_GRID_SNAPSHOT_TRIGGERED)
167
167
 
168
- yield from bps.read(oav) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
168
+ yield from bps.read(oav)
169
169
  yield from bps.read(smargon)
170
170
  yield from bps.save()
171
171
 
@@ -34,9 +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,
38
- ApertureValue.ROBOT_LOAD,
39
- group=group,
37
+ aperture_scatterguard, ApertureValue.OUT_OF_BEAM, group=group
40
38
  )
41
39
 
42
40
 
@@ -44,11 +42,9 @@ def oav_snapshot_plan(
44
42
  composite: OavSnapshotComposite,
45
43
  parameters: WithSnapshot,
46
44
  oav_parameters: OAVParameters,
47
- wait: bool = True,
48
45
  ) -> MsgGenerator:
49
46
  if not parameters.take_snapshots:
50
47
  return
51
- yield from bps.wait(group=CONST.WAIT.READY_FOR_OAV)
52
48
  yield from _setup_oav(composite, parameters, oav_parameters)
53
49
  for omega in parameters.snapshot_omegas_deg or []:
54
50
  yield from _take_oav_snapshot(composite, omega)
@@ -61,7 +57,7 @@ def _setup_oav(
61
57
  ):
62
58
  yield from setup_general_oav_params(composite.oav, oav_parameters)
63
59
  yield from bps.abs_set(
64
- composite.oav.snapshot.directory, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
60
+ composite.oav.snapshot.directory,
65
61
  str(parameters.snapshot_directory),
66
62
  )
67
63
 
@@ -73,12 +69,12 @@ def _take_oav_snapshot(composite: OavSnapshotComposite, omega: float):
73
69
  time_now = datetime.now()
74
70
  filename = f"{time_now.strftime('%H%M%S')}_oav_snapshot_{omega:.0f}"
75
71
  yield from bps.abs_set(
76
- composite.oav.snapshot.filename, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
72
+ composite.oav.snapshot.filename,
77
73
  filename,
78
74
  group=OAV_SNAPSHOT_SETUP_SHOT,
79
75
  )
80
76
  yield from bps.wait(group=OAV_SNAPSHOT_SETUP_SHOT)
81
- yield from bps.trigger(composite.oav.snapshot, wait=True) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
77
+ yield from bps.trigger(composite.oav.snapshot, wait=True)
82
78
  yield from bps.create(DocDescriptorNames.OAV_ROTATION_SNAPSHOT_TRIGGERED)
83
- yield from bps.read(composite.oav.snapshot) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
79
+ yield from bps.read(composite.oav.snapshot)
84
80
  yield from bps.save()
@@ -9,8 +9,8 @@ from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
9
9
  from dodal.devices.xspress3.xspress3 import Xspress3
10
10
  from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter, ZebraShutterState
11
11
 
12
+ from mx_bluesky.common.utils.context import device_composite_from_context
12
13
  from mx_bluesky.common.utils.log import LOGGER
13
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
14
14
 
15
15
 
16
16
  class AttenuationOptimisationFailedException(Exception):
@@ -12,7 +12,9 @@ from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback
12
12
  ispyb_activation_wrapper,
13
13
  )
14
14
  from mx_bluesky.common.parameters.constants import OavConstants
15
+ from mx_bluesky.common.utils.context import device_composite_from_context
15
16
  from mx_bluesky.common.utils.log import LOGGER
17
+ from mx_bluesky.common.xrc_result import XRayCentreEventHandler
16
18
  from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import move_phi_chi_omega
17
19
  from mx_bluesky.hyperion.device_setup_plans.utils import (
18
20
  start_preparing_data_collection_then_do_plan,
@@ -20,9 +22,6 @@ from mx_bluesky.hyperion.device_setup_plans.utils import (
20
22
  from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import (
21
23
  change_aperture_then_move_to_xtal,
22
24
  )
23
- from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
24
- XRayCentreEventHandler,
25
- )
26
25
  from mx_bluesky.hyperion.experiment_plans.grid_detect_then_xray_centre_plan import (
27
26
  GridDetectThenXRayCentreComposite,
28
27
  detect_grid_and_do_gridscan,
@@ -39,7 +38,6 @@ from mx_bluesky.hyperion.parameters.gridscan import (
39
38
  GridScanWithEdgeDetect,
40
39
  PinTipCentreThenXrayCentre,
41
40
  )
42
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
43
41
 
44
42
 
45
43
  def create_devices(context: BlueskyContext) -> GridDetectThenXRayCentreComposite: