mx-bluesky 1.4.5__py3-none-any.whl → 1.4.7__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 (90) hide show
  1. mx_bluesky/_version.py +9 -4
  2. mx_bluesky/beamlines/aithre_lasershaping/__init__.py +13 -0
  3. mx_bluesky/beamlines/aithre_lasershaping/check_goniometer_performance.py +29 -0
  4. mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py +18 -0
  5. mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +45 -28
  6. mx_bluesky/beamlines/i04/thawing_plan.py +19 -14
  7. mx_bluesky/beamlines/i24/serial/__init__.py +14 -0
  8. mx_bluesky/beamlines/i24/serial/dcid.py +3 -1
  9. mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +12 -12
  10. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +31 -30
  11. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +16 -14
  12. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +19 -21
  13. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +11 -4
  14. mx_bluesky/beamlines/i24/serial/parameters/constants.py +1 -1
  15. mx_bluesky/beamlines/i24/serial/set_visit_directory.sh +1 -1
  16. mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +16 -16
  17. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +48 -49
  18. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +2 -2
  19. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +11 -9
  20. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +109 -0
  21. mx_bluesky/beamlines/i24/serial/write_nexus.py +5 -4
  22. mx_bluesky/common/device_setup_plans/xbpm_feedback.py +45 -0
  23. mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +2 -4
  24. mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +1 -1
  25. mx_bluesky/common/external_interaction/callbacks/common/plan_reactive_callback.py +2 -2
  26. mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py +18 -15
  27. mx_bluesky/common/external_interaction/callbacks/sample_handling/__init__.py +0 -0
  28. mx_bluesky/{hyperion → common}/external_interaction/callbacks/sample_handling/sample_handling_callback.py +29 -12
  29. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +43 -7
  30. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_mapping.py +1 -1
  31. mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py +2 -1
  32. mx_bluesky/common/external_interaction/ispyb/data_model.py +1 -0
  33. mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +6 -2
  34. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +21 -1
  35. mx_bluesky/common/external_interaction/nexus/nexus_utils.py +1 -1
  36. mx_bluesky/common/parameters/constants.py +3 -1
  37. mx_bluesky/common/parameters/gridscan.py +36 -1
  38. mx_bluesky/common/plans/do_fgs.py +4 -6
  39. mx_bluesky/common/plans/read_hardware.py +78 -0
  40. mx_bluesky/common/plans/write_sample_status.py +46 -0
  41. mx_bluesky/common/preprocessors/__init__.py +0 -0
  42. mx_bluesky/common/preprocessors/preprocessors.py +105 -0
  43. mx_bluesky/common/protocols/__init__.py +0 -0
  44. mx_bluesky/common/protocols/protocols.py +10 -0
  45. mx_bluesky/common/utils/context.py +68 -0
  46. mx_bluesky/{hyperion/experiment_plans/common → common}/xrc_result.py +16 -0
  47. mx_bluesky/hyperion/__main__.py +7 -9
  48. mx_bluesky/hyperion/baton_handler.py +84 -0
  49. mx_bluesky/hyperion/device_setup_plans/setup_oav.py +5 -5
  50. mx_bluesky/hyperion/device_setup_plans/setup_panda.py +5 -1
  51. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +2 -2
  52. mx_bluesky/hyperion/device_setup_plans/smargon.py +6 -6
  53. mx_bluesky/hyperion/device_setup_plans/utils.py +2 -2
  54. mx_bluesky/hyperion/experiment_plans/__init__.py +0 -4
  55. mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +12 -31
  56. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +0 -7
  57. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +44 -97
  58. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +6 -6
  59. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +8 -6
  60. mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +11 -11
  61. mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +5 -5
  62. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +1 -1
  63. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +2 -4
  64. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +15 -13
  65. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +10 -10
  66. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +1 -29
  67. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +30 -27
  68. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +25 -6
  69. mx_bluesky/hyperion/external_interaction/agamemnon.py +242 -0
  70. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +12 -6
  71. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +1 -1
  72. mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py +107 -0
  73. mx_bluesky/hyperion/external_interaction/config_server.py +6 -6
  74. mx_bluesky/hyperion/parameters/device_composites.py +49 -0
  75. mx_bluesky/hyperion/parameters/gridscan.py +3 -3
  76. mx_bluesky/hyperion/parameters/rotation.py +1 -1
  77. mx_bluesky/hyperion/utils/__init__.py +1 -0
  78. mx_bluesky/hyperion/utils/context.py +0 -65
  79. mx_bluesky/hyperion/utils/validation.py +3 -3
  80. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.7.dist-info}/METADATA +6 -5
  81. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.7.dist-info}/RECORD +86 -72
  82. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.7.dist-info}/WHEEL +1 -1
  83. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.7.dist-info}/entry_points.txt +1 -0
  84. mx_bluesky/common/device_setup_plans/read_hardware_for_setup.py +0 -14
  85. mx_bluesky/common/external_interaction/callbacks/common/aperture_change_callback.py +0 -22
  86. mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +0 -54
  87. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +0 -103
  88. /mx_bluesky/{hyperion/external_interaction/callbacks/sample_handling → beamlines/i24/serial/web_gui_plans}/__init__.py +0 -0
  89. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.7.dist-info/licenses}/LICENSE +0 -0
  90. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.7.dist-info}/top_level.txt +0 -0
@@ -57,7 +57,7 @@ def _setup_oav(
57
57
  ):
58
58
  yield from setup_general_oav_params(composite.oav, oav_parameters)
59
59
  yield from bps.abs_set(
60
- composite.oav.snapshot.directory, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
60
+ composite.oav.snapshot.directory,
61
61
  str(parameters.snapshot_directory),
62
62
  )
63
63
 
@@ -67,14 +67,14 @@ def _take_oav_snapshot(composite: OavSnapshotComposite, omega: float):
67
67
  composite.smargon.omega, omega, group=OAV_SNAPSHOT_SETUP_SHOT
68
68
  )
69
69
  time_now = datetime.now()
70
- filename = f"{time_now.strftime('%H%M%S')}_oav_snapshot_{omega:.0f}"
70
+ filename = f"{time_now.strftime('%H%M%S%f')[:8]}_oav_snapshot_{omega:.0f}"
71
71
  yield from bps.abs_set(
72
- composite.oav.snapshot.filename, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
72
+ composite.oav.snapshot.filename,
73
73
  filename,
74
74
  group=OAV_SNAPSHOT_SETUP_SHOT,
75
75
  )
76
76
  yield from bps.wait(group=OAV_SNAPSHOT_SETUP_SHOT)
77
- 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)
78
78
  yield from bps.create(DocDescriptorNames.OAV_ROTATION_SNAPSHOT_TRIGGERED)
79
- yield from bps.read(composite.oav.snapshot) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
79
+ yield from bps.read(composite.oav)
80
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:
@@ -9,20 +9,21 @@ from dodal.devices.oav.oav_detector import OAV
9
9
  from dodal.devices.oav.oav_parameters import OAV_CONFIG_JSON, OAVParameters
10
10
  from dodal.devices.oav.pin_image_recognition import PinTipDetection, Tip
11
11
  from dodal.devices.oav.utils import (
12
+ PinNotFoundException,
12
13
  Pixel,
13
14
  get_move_required_so_that_beam_is_at_pixel,
14
15
  wait_for_tip_to_be_found,
15
16
  )
16
17
  from dodal.devices.smargon import Smargon
17
18
 
18
- from mx_bluesky.common.utils.exceptions import SampleException
19
+ from mx_bluesky.common.utils.context import device_composite_from_context
20
+ from mx_bluesky.common.utils.exceptions import SampleException, catch_exception_and_warn
19
21
  from mx_bluesky.common.utils.log import LOGGER
20
22
  from mx_bluesky.hyperion.device_setup_plans.setup_oav import pre_centring_setup_oav
21
23
  from mx_bluesky.hyperion.device_setup_plans.smargon import (
22
24
  move_smargon_warn_on_out_of_range,
23
25
  )
24
26
  from mx_bluesky.hyperion.parameters.constants import CONST
25
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
26
27
 
27
28
  DEFAULT_STEP_SIZE = 0.5
28
29
 
@@ -53,7 +54,7 @@ def trigger_and_return_pin_tip(
53
54
  def move_pin_into_view(
54
55
  pin_tip_device: PinTipDetection,
55
56
  smargon: Smargon,
56
- step_size_mm: float = DEFAULT_STEP_SIZE,
57
+ step_magnitude_mm: float = DEFAULT_STEP_SIZE,
57
58
  max_steps: int = 2,
58
59
  ) -> Generator[Msg, None, Pixel]:
59
60
  """Attempt to move the pin into view and return the tip location in pixels if found.
@@ -63,7 +64,7 @@ def move_pin_into_view(
63
64
  Args:
64
65
  pin_tip_device (PinTipDetection): The device being used to detect the pin
65
66
  smargon (Smargon): The gonio to move the tip
66
- step_size (float, optional): Distance to move the gonio (in mm) for each
67
+ step_magnitude_mm (float, optional): Distance to move the gonio (in mm) for each
67
68
  step of the search. Defaults to 0.5.
68
69
  max_steps (int, optional): The number of steps to search with. Defaults to 2.
69
70
 
@@ -83,21 +84,21 @@ def move_pin_into_view(
83
84
  if pin_tip_valid(tip_xy_px):
84
85
  return (int(tip_xy_px[0]), int(tip_xy_px[1]))
85
86
 
86
- if tip_xy_px[0] == 0:
87
- # Pin is off in the -ve direction
88
- step_size_mm = -step_size_mm
87
+ # Pin is off in the -ve direction if the returned tip x pixel value is 0
88
+ direction_multiple = -1 if tip_xy_px[0] == 0 else 1
89
+ step_vector_mm = step_magnitude_mm * direction_multiple
89
90
 
90
91
  smargon_x = yield from bps.rd(smargon.x.user_readback)
91
- ideal_move_to_find_pin = float(smargon_x) + step_size_mm
92
+ ideal_move_to_find_pin = float(smargon_x) + step_vector_mm
92
93
  high_limit = yield from bps.rd(smargon.x.high_limit_travel)
93
94
  low_limit = yield from bps.rd(smargon.x.low_limit_travel)
94
95
  move_within_limits = max(min(ideal_move_to_find_pin, high_limit), low_limit)
95
96
  if move_within_limits != ideal_move_to_find_pin:
96
97
  LOGGER.warning(
97
- f"Pin tip is off screen, and moving {step_size_mm} mm would cross limits, "
98
+ f"Pin tip is off screen, and moving {step_vector_mm}mm would cross limits, "
98
99
  f"moving to {move_within_limits} instead"
99
100
  )
100
- yield from bps.mv(smargon.x, move_within_limits) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
101
+ yield from bps.mv(smargon.x, move_within_limits)
101
102
 
102
103
  # Some time for the view to settle after the move
103
104
  yield from bps.sleep(CONST.HARDWARE.OAV_REFRESH_DELAY)
@@ -154,11 +155,12 @@ def pin_tip_centre_plan(
154
155
  tip = yield from move_pin_into_view(pin_tip_detect, smargon)
155
156
  yield from offset_and_move(tip)
156
157
 
157
- yield from bps.mvr(smargon.omega, 90) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
158
+ yield from bps.mvr(smargon.omega, 90)
158
159
 
159
160
  # need to wait for the OAV image to update
160
161
  # See #673 for improvements
161
162
  yield from bps.sleep(0.3)
162
-
163
- tip = yield from wait_for_tip_to_be_found(pin_tip_detect)
163
+ tip = yield from catch_exception_and_warn(
164
+ PinNotFoundException, wait_for_tip_to_be_found, pin_tip_detect
165
+ )
164
166
  yield from offset_and_move(tip)
@@ -54,7 +54,7 @@ class RobotLoadAndEnergyChangeComposite:
54
54
 
55
55
 
56
56
  def create_devices(context: BlueskyContext) -> RobotLoadAndEnergyChangeComposite:
57
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
57
+ from mx_bluesky.common.utils.context import device_composite_from_context
58
58
 
59
59
  return device_composite_from_context(context, RobotLoadAndEnergyChangeComposite)
60
60
 
@@ -98,16 +98,16 @@ def prepare_for_robot_load(
98
98
  aperture_scatterguard, ApertureValue.OUT_OF_BEAM, group="prepare_robot_load"
99
99
  )
100
100
 
101
- yield from bps.mv(smargon.stub_offsets, StubPosition.RESET_TO_ROBOT_LOAD) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
101
+ yield from bps.mv(smargon.stub_offsets, StubPosition.RESET_TO_ROBOT_LOAD)
102
102
 
103
103
  # fmt: off
104
104
  yield from bps.mv(
105
- smargon.x, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
106
- smargon.y, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
107
- smargon.z, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
108
- smargon.omega, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
109
- smargon.chi, 0, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
110
- smargon.phi, 0 # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
105
+ smargon.x, 0,
106
+ smargon.y, 0,
107
+ smargon.z, 0,
108
+ smargon.omega, 0,
109
+ smargon.chi, 0,
110
+ smargon.phi, 0
111
111
  )
112
112
  # fmt: on
113
113
 
@@ -131,7 +131,7 @@ def do_robot_load(
131
131
  yield from bps.wait("robot_load")
132
132
 
133
133
  yield from bps.abs_set(
134
- composite.thawer.thaw_for_time_s, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
134
+ composite.thawer.thaw_for_time_s,
135
135
  thawing_time,
136
136
  group="thawing_finished",
137
137
  )
@@ -193,7 +193,7 @@ def robot_load_and_snapshots(
193
193
 
194
194
  yield from bps.create(name=CONST.DESCRIPTORS.ROBOT_LOAD)
195
195
  yield from bps.read(composite.robot.barcode)
196
- yield from bps.read(composite.oav.snapshot) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
196
+ yield from bps.read(composite.oav.snapshot)
197
197
  yield from bps.read(composite.webcam)
198
198
  yield from bps.save()
199
199
 
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from math import isclose
4
4
  from typing import cast
5
5
 
6
- import bluesky.preprocessors as bpp
7
6
  import pydantic
8
7
  from blueapi.core import BlueskyContext
9
8
  from bluesky import plan_stubs as bps
@@ -41,12 +40,6 @@ from mx_bluesky.hyperion.device_setup_plans.utils import (
41
40
  fill_in_energy_if_not_supplied,
42
41
  start_preparing_data_collection_then_do_plan,
43
42
  )
44
- from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import (
45
- change_aperture_then_move_to_xtal,
46
- )
47
- from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
48
- XRayCentreEventHandler,
49
- )
50
43
  from mx_bluesky.hyperion.experiment_plans.grid_detect_then_xray_centre_plan import (
51
44
  GridDetectThenXRayCentreComposite,
52
45
  )
@@ -106,7 +99,7 @@ class RobotLoadThenCentreComposite:
106
99
 
107
100
 
108
101
  def create_devices(context: BlueskyContext) -> RobotLoadThenCentreComposite:
109
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
102
+ from mx_bluesky.common.utils.context import device_composite_from_context
110
103
 
111
104
  return device_composite_from_context(context, RobotLoadThenCentreComposite)
112
105
 
@@ -135,27 +128,6 @@ def _robot_load_then_flyscan_plan(
135
128
  yield from _flyscan_plan_from_robot_load_params(composite, params, oav_config_file)
136
129
 
137
130
 
138
- def robot_load_then_centre(
139
- composite: RobotLoadThenCentreComposite,
140
- parameters: RobotLoadThenCentre,
141
- ) -> MsgGenerator:
142
- """Perform pin-tip detection followed by a flyscan to determine centres of interest.
143
- Performs a robot load if necessary. Centre on the best diffracting centre.
144
- """
145
-
146
- xray_centre_event_handler = XRayCentreEventHandler()
147
-
148
- yield from bpp.subs_wrapper(
149
- robot_load_then_xray_centre(composite, parameters), xray_centre_event_handler
150
- )
151
- flyscan_results = xray_centre_event_handler.xray_centre_results
152
- if flyscan_results is not None:
153
- yield from change_aperture_then_move_to_xtal(
154
- flyscan_results[0], composite.smargon, composite.aperture_scatterguard
155
- )
156
- # else no chi change, no need to recentre.
157
-
158
-
159
131
  def robot_load_then_xray_centre(
160
132
  composite: RobotLoadThenCentreComposite,
161
133
  parameters: RobotLoadThenCentre,
@@ -26,10 +26,20 @@ from dodal.devices.xbpm_feedback import XBPMFeedback
26
26
  from dodal.devices.zebra.zebra import RotationDirection, Zebra
27
27
  from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
28
28
  from dodal.plan_stubs.check_topup import check_topup_and_wait_if_necessary
29
+ from dodal.plans.preprocessors.verify_undulator_gap import (
30
+ verify_undulator_gap_before_run_decorator,
31
+ )
29
32
 
30
- from mx_bluesky.common.device_setup_plans.read_hardware_for_setup import (
33
+ from mx_bluesky.common.parameters.components import WithSnapshot
34
+ from mx_bluesky.common.plans.read_hardware import (
31
35
  read_hardware_for_zocalo,
36
+ standard_read_hardware_during_collection,
37
+ standard_read_hardware_pre_collection,
38
+ )
39
+ from mx_bluesky.common.preprocessors.preprocessors import (
40
+ transmission_and_xbpm_feedback_for_collection_decorator,
32
41
  )
42
+ from mx_bluesky.common.utils.context import device_composite_from_context
33
43
  from mx_bluesky.common.utils.log import LOGGER
34
44
  from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import (
35
45
  cleanup_sample_environment,
@@ -37,10 +47,6 @@ from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import (
37
47
  move_x_y_z,
38
48
  setup_sample_environment,
39
49
  )
40
- from mx_bluesky.hyperion.device_setup_plans.read_hardware_for_setup import (
41
- read_hardware_during_collection,
42
- read_hardware_pre_collection,
43
- )
44
50
  from mx_bluesky.hyperion.device_setup_plans.setup_zebra import (
45
51
  arm_zebra,
46
52
  setup_zebra_for_rotation,
@@ -49,9 +55,6 @@ from mx_bluesky.hyperion.device_setup_plans.setup_zebra import (
49
55
  from mx_bluesky.hyperion.device_setup_plans.utils import (
50
56
  start_preparing_data_collection_then_do_plan,
51
57
  )
52
- from mx_bluesky.hyperion.device_setup_plans.xbpm_feedback import (
53
- transmission_and_xbpm_feedback_for_collection_decorator,
54
- )
55
58
  from mx_bluesky.hyperion.experiment_plans.oav_snapshot_plan import (
56
59
  OavSnapshotComposite,
57
60
  oav_snapshot_plan,
@@ -62,7 +65,6 @@ from mx_bluesky.hyperion.parameters.rotation import (
62
65
  MultiRotationScan,
63
66
  RotationScan,
64
67
  )
65
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
66
68
 
67
69
 
68
70
  @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
@@ -267,7 +269,7 @@ def rotation_scan_plan(
267
269
  # get some information for the ispyb deposition and trigger the callback
268
270
  yield from read_hardware_for_zocalo(composite.eiger)
269
271
 
270
- yield from read_hardware_pre_collection(
272
+ yield from standard_read_hardware_pre_collection(
271
273
  composite.undulator,
272
274
  composite.synchrotron,
273
275
  composite.s4_slit_gaps,
@@ -293,7 +295,7 @@ def rotation_scan_plan(
293
295
  LOGGER.info("Executing rotation scan")
294
296
  yield from bps.rel_set(axis, motion_values.distance_to_move_deg, wait=True)
295
297
 
296
- yield from read_hardware_during_collection(
298
+ yield from standard_read_hardware_during_collection(
297
299
  composite.aperture_scatterguard,
298
300
  composite.attenuator,
299
301
  composite.flux,
@@ -371,24 +373,26 @@ def rotation_scan(
371
373
  if not oav_params:
372
374
  oav_params = OAVParameters(context="xrayCentring")
373
375
 
376
+ @transmission_and_xbpm_feedback_for_collection_decorator(
377
+ composite,
378
+ parameters.transmission_frac,
379
+ )
380
+ @verify_undulator_gap_before_run_decorator(composite)
374
381
  @bpp.set_run_key_decorator("rotation_scan")
375
382
  @bpp.run_decorator( # attach experiment metadata to the start document
376
383
  md={
377
384
  "subplan_name": CONST.PLAN.ROTATION_OUTER,
378
385
  "mx_bluesky_parameters": parameters.model_dump_json(),
386
+ "with_snapshot": parameters.model_dump_json(
387
+ include=WithSnapshot.model_fields.keys() # type: ignore
388
+ ),
379
389
  "activate_callbacks": [
390
+ "BeamDrawingCallback",
380
391
  "RotationISPyBCallback",
381
392
  "RotationNexusFileCallback",
382
393
  ],
383
394
  }
384
395
  )
385
- @transmission_and_xbpm_feedback_for_collection_decorator(
386
- composite.undulator,
387
- composite.xbpm_feedback,
388
- composite.attenuator,
389
- composite.dcm,
390
- parameters.transmission_frac,
391
- )
392
396
  def rotation_scan_plan_with_stage_and_cleanup(
393
397
  params: RotationScan,
394
398
  ):
@@ -408,7 +412,7 @@ def rotation_scan(
408
412
  rotation_with_cleanup_and_stage(params),
409
413
  group=CONST.WAIT.ROTATION_READY_FOR_DC,
410
414
  )
411
- yield from bps.unstage(eiger) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
415
+ yield from bps.unstage(eiger)
412
416
 
413
417
  yield from rotation_scan_plan_with_stage_and_cleanup(parameters)
414
418
 
@@ -424,6 +428,10 @@ def multi_rotation_scan(
424
428
  eiger: EigerDetector = composite.eiger
425
429
  eiger.set_detector_parameters(parameters.detector_params)
426
430
 
431
+ @transmission_and_xbpm_feedback_for_collection_decorator(
432
+ composite,
433
+ parameters.transmission_frac,
434
+ )
427
435
  @bpp.set_run_key_decorator("multi_rotation_scan")
428
436
  @bpp.run_decorator(
429
437
  md={
@@ -436,17 +444,11 @@ def multi_rotation_scan(
436
444
  ],
437
445
  }
438
446
  )
439
- @transmission_and_xbpm_feedback_for_collection_decorator(
440
- composite.undulator,
441
- composite.xbpm_feedback,
442
- composite.attenuator,
443
- composite.dcm,
444
- parameters.transmission_frac,
445
- )
446
447
  @bpp.finalize_decorator(lambda: _cleanup_plan(composite))
447
448
  def _multi_rotation_scan():
448
449
  for single_scan in parameters.single_rotation_scans:
449
450
 
451
+ @verify_undulator_gap_before_run_decorator(composite)
450
452
  @bpp.set_run_key_decorator("rotation_scan")
451
453
  @bpp.run_decorator( # attach experiment metadata to the start document
452
454
  md={
@@ -461,6 +463,8 @@ def multi_rotation_scan(
461
463
 
462
464
  yield from rotation_scan_core(single_scan)
463
465
 
466
+ yield from bps.unstage(eiger)
467
+
464
468
  LOGGER.info("setting up and staging eiger...")
465
469
  yield from start_preparing_data_collection_then_do_plan(
466
470
  composite.beamstop,
@@ -470,4 +474,3 @@ def multi_rotation_scan(
470
474
  _multi_rotation_scan(),
471
475
  group=CONST.WAIT.ROTATION_READY_FOR_DC,
472
476
  )
473
- yield from bps.unstage(eiger)
@@ -5,18 +5,21 @@
5
5
  * reenable feedback
6
6
  """
7
7
 
8
+ import bluesky.preprocessors as bpp
8
9
  import pydantic
9
10
  from bluesky import plan_stubs as bps
10
11
  from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
11
12
  from dodal.devices.dcm import DCM
12
13
  from dodal.devices.focusing_mirror import FocusingMirrorWithStripes, MirrorVoltages
14
+ from dodal.devices.undulator import Undulator
13
15
  from dodal.devices.undulator_dcm import UndulatorDCM
14
16
  from dodal.devices.xbpm_feedback import XBPMFeedback
15
17
 
16
- from mx_bluesky.hyperion.device_setup_plans import dcm_pitch_roll_mirror_adjuster
17
- from mx_bluesky.hyperion.device_setup_plans.xbpm_feedback import (
18
+ from mx_bluesky.common.parameters.constants import PlanNameConstants
19
+ from mx_bluesky.common.preprocessors.preprocessors import (
18
20
  transmission_and_xbpm_feedback_for_collection_wrapper,
19
21
  )
22
+ from mx_bluesky.hyperion.device_setup_plans import dcm_pitch_roll_mirror_adjuster
20
23
 
21
24
  DESIRED_TRANSMISSION_FRACTION = 0.1
22
25
 
@@ -33,6 +36,17 @@ class SetEnergyComposite:
33
36
  attenuator: BinaryFilterAttenuator
34
37
 
35
38
 
39
+ # Remove composite after https://github.com/DiamondLightSource/dodal/issues/1092
40
+ @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
41
+ class XBPMWrapperComposite:
42
+ undulator: Undulator
43
+ xbpm_feedback: XBPMFeedback
44
+ attenuator: BinaryFilterAttenuator
45
+ dcm: DCM
46
+
47
+
48
+ @bpp.set_run_key_decorator(PlanNameConstants.SET_ENERGY)
49
+ @bpp.run_decorator()
36
50
  def _set_energy_plan(
37
51
  energy_kev,
38
52
  composite: SetEnergyComposite,
@@ -51,12 +65,17 @@ def set_energy_plan(
51
65
  energy_ev: float | None,
52
66
  composite: SetEnergyComposite,
53
67
  ):
68
+ # Remove conversion after https://github.com/DiamondLightSource/dodal/issues/1092
69
+ composite_for_wrapper = XBPMWrapperComposite(
70
+ composite.undulator_dcm.undulator_ref._obj, # noqa: SLF001
71
+ composite.xbpm_feedback,
72
+ composite.attenuator,
73
+ composite.dcm,
74
+ )
75
+
54
76
  if energy_ev:
55
77
  yield from transmission_and_xbpm_feedback_for_collection_wrapper(
56
78
  _set_energy_plan(energy_ev / 1000, composite),
57
- composite.undulator_dcm.undulator_ref(),
58
- composite.xbpm_feedback,
59
- composite.attenuator,
60
- composite.dcm,
79
+ composite_for_wrapper,
61
80
  DESIRED_TRANSMISSION_FRACTION,
62
81
  )