mx-bluesky 1.5.1__py3-none-any.whl → 1.5.2__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 (33) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/i04/__init__.py +4 -1
  3. mx_bluesky/beamlines/i04/callbacks/murko_callback.py +56 -1
  4. mx_bluesky/beamlines/i04/experiment_plans/__init__.py +0 -0
  5. mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +259 -0
  6. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +3 -1
  7. mx_bluesky/common/experiment_plans/change_aperture_then_move_plan.py +5 -1
  8. mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py +26 -3
  9. mx_bluesky/common/experiment_plans/common_grid_detect_then_xray_centre_plan.py +1 -0
  10. mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py +3 -1
  11. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +11 -6
  12. mx_bluesky/common/parameters/__init__.py +0 -0
  13. mx_bluesky/common/parameters/constants.py +1 -0
  14. mx_bluesky/common/parameters/device_composites.py +1 -1
  15. mx_bluesky/common/parameters/gridscan.py +1 -0
  16. mx_bluesky/hyperion/__main__.py +1 -1
  17. mx_bluesky/hyperion/baton_handler.py +36 -4
  18. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +4 -93
  19. mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +19 -37
  20. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +5 -5
  21. mx_bluesky/hyperion/parameters/constants.py +1 -2
  22. mx_bluesky/hyperion/utils/context.py +19 -5
  23. mx_bluesky/phase1_zebra/__init__.py +1 -0
  24. mx_bluesky/phase1_zebra/device_setup_plans/__init__.py +0 -0
  25. mx_bluesky/phase1_zebra/device_setup_plans/setup_zebra.py +112 -0
  26. {mx_bluesky-1.5.1.dist-info → mx_bluesky-1.5.2.dist-info}/METADATA +3 -3
  27. {mx_bluesky-1.5.1.dist-info → mx_bluesky-1.5.2.dist-info}/RECORD +33 -27
  28. /mx_bluesky/common/experiment_plans/{read_hardware.py → inner_plans/read_hardware.py} +0 -0
  29. /mx_bluesky/common/experiment_plans/{write_sample_status.py → inner_plans/write_sample_status.py} +0 -0
  30. {mx_bluesky-1.5.1.dist-info → mx_bluesky-1.5.2.dist-info}/WHEEL +0 -0
  31. {mx_bluesky-1.5.1.dist-info → mx_bluesky-1.5.2.dist-info}/entry_points.txt +0 -0
  32. {mx_bluesky-1.5.1.dist-info → mx_bluesky-1.5.2.dist-info}/licenses/LICENSE +0 -0
  33. {mx_bluesky-1.5.1.dist-info → mx_bluesky-1.5.2.dist-info}/top_level.txt +0 -0
mx_bluesky/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '1.5.1'
21
- __version_tuple__ = version_tuple = (1, 5, 1)
20
+ __version__ = version = '1.5.2'
21
+ __version_tuple__ = version_tuple = (1, 5, 2)
@@ -1,3 +1,6 @@
1
+ from mx_bluesky.beamlines.i04.experiment_plans import (
2
+ i04_grid_detect_then_xray_centre_plan,
3
+ )
1
4
  from mx_bluesky.beamlines.i04.thawing_plan import thaw, thaw_and_stream_to_redis
2
5
 
3
- __all__ = ["thaw", "thaw_and_stream_to_redis"]
6
+ __all__ = ["thaw", "thaw_and_stream_to_redis", "i04_grid_detect_then_xray_centre_plan"]
@@ -1,6 +1,7 @@
1
1
  import copy
2
2
  import json
3
3
  from datetime import timedelta
4
+ from typing import TypedDict
4
5
 
5
6
  from bluesky.callbacks import CallbackBase
6
7
  from dodal.log import LOGGER
@@ -8,7 +9,43 @@ from event_model.documents import Event, RunStart, RunStop
8
9
  from redis import StrictRedis
9
10
 
10
11
 
12
+ class OmegaReading(TypedDict):
13
+ value: float
14
+ timestamp: float
15
+
16
+
17
+ def extrapolate_omega(
18
+ latest_omega: OmegaReading, previous_omega: OmegaReading, image_timestamp: float
19
+ ) -> float:
20
+ """Extrapolate an image omega from previous omegas.
21
+
22
+ There are a number of assumptions in this calculation:
23
+ * The speed of the smargon is fixed
24
+ * The timestamps from the two different devices are synchronised and match the data
25
+ exactly
26
+
27
+ These are accepted to be reasonable based on larger errors likely coming from murko
28
+ itself and that the results ultimately will be averaged out.
29
+ """
30
+ omega_per_sec = (latest_omega["value"] - previous_omega["value"]) / (
31
+ latest_omega["timestamp"] - previous_omega["timestamp"]
32
+ )
33
+ time_elapsed = image_timestamp - latest_omega["timestamp"]
34
+ return latest_omega["value"] + time_elapsed * omega_per_sec
35
+
36
+
11
37
  class MurkoCallback(CallbackBase):
38
+ """A callback that triggers murko processing of images.
39
+
40
+ It combines metadata readings from e.g the goniometer rotation with the uuid's given
41
+ to us by an `OAVToRedisForwarder` (which describe the location of images in redis).
42
+ And writes these as a package to redis. A separate service then forwards this to murko.
43
+
44
+ The metadata and image data arrive independently, it is expected that the image data
45
+ is arriving at a faster rate than gonio metadata and so the value of omega for when
46
+ the image arrives is extrapolated based on previous omega readings.
47
+ """
48
+
12
49
  DATA_EXPIRY_DAYS = 7
13
50
 
14
51
  def __init__(self, redis_host: str, redis_password: str, redis_db: int = 0):
@@ -16,6 +53,7 @@ class MurkoCallback(CallbackBase):
16
53
  host=redis_host, password=redis_password, db=redis_db
17
54
  )
18
55
  self.last_uuid = None
56
+ self.previous_omegas: list[OmegaReading] = []
19
57
 
20
58
  def start(self, doc: RunStart) -> RunStart | None:
21
59
  self.sample_id = doc.get("sample_id")
@@ -28,14 +66,31 @@ class MurkoCallback(CallbackBase):
28
66
  "sample_id": self.sample_id,
29
67
  }
30
68
  self.last_uuid = None
69
+ self.previous_omegas = []
31
70
  LOGGER.info(f"Starting to stream metadata to murko under {self.sample_id}")
32
71
  return doc
33
72
 
34
73
  def event(self, doc: Event) -> Event:
35
74
  if latest_omega := doc["data"].get("smargon-omega"):
36
- if self.last_uuid is not None:
75
+ if len(self.previous_omegas) <= 2 and self.last_uuid:
76
+ # For the first few images there's not enough data to extrapolate so we
77
+ # match them one to one
37
78
  self.call_murko(self.last_uuid, latest_omega)
79
+ self.previous_omegas.append(
80
+ OmegaReading(
81
+ value=latest_omega,
82
+ timestamp=doc["timestamps"]["smargon-omega"],
83
+ )
84
+ )
38
85
  elif (uuid := doc["data"].get("oav_to_redis_forwarder-uuid")) is not None:
86
+ if len(self.previous_omegas) >= 2:
87
+ omega = extrapolate_omega(
88
+ self.previous_omegas[-1],
89
+ self.previous_omegas[-2],
90
+ doc["timestamps"]["oav_to_redis_forwarder-uuid"],
91
+ )
92
+ LOGGER.info(f"Using extrapolated omega of {omega}")
93
+ self.call_murko(uuid, omega)
39
94
  self.last_uuid = uuid
40
95
  return doc
41
96
 
File without changes
@@ -0,0 +1,259 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import partial
4
+
5
+ import bluesky.plan_stubs as bps
6
+ import bluesky.preprocessors as bpp
7
+ from blueapi.core import BlueskyContext
8
+ from bluesky.utils import MsgGenerator
9
+ from dodal.common import inject
10
+ from dodal.devices.aperturescatterguard import ApertureScatterguard
11
+ from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
12
+ from dodal.devices.backlight import Backlight
13
+ from dodal.devices.common_dcm import BaseDCM
14
+ from dodal.devices.detector.detector_motion import DetectorMotion
15
+ from dodal.devices.eiger import EigerDetector
16
+ from dodal.devices.fast_grid_scan import (
17
+ ZebraFastGridScan,
18
+ set_fast_grid_scan_params,
19
+ )
20
+ from dodal.devices.flux import Flux
21
+ from dodal.devices.mx_phase1.beamstop import Beamstop
22
+ from dodal.devices.oav.oav_detector import OAV
23
+ from dodal.devices.oav.pin_image_recognition import PinTipDetection
24
+ from dodal.devices.robot import BartRobot
25
+ from dodal.devices.s4_slit_gaps import S4SlitGaps
26
+ from dodal.devices.smargon import Smargon
27
+ from dodal.devices.synchrotron import Synchrotron
28
+ from dodal.devices.undulator import Undulator
29
+ from dodal.devices.xbpm_feedback import XBPMFeedback
30
+ from dodal.devices.zebra.zebra import Zebra
31
+ from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
32
+ from dodal.devices.zocalo import ZocaloResults
33
+ from dodal.plans.preprocessors.verify_undulator_gap import (
34
+ verify_undulator_gap_before_run_decorator,
35
+ )
36
+
37
+ from mx_bluesky.common.experiment_plans.common_flyscan_xray_centre_plan import (
38
+ BeamlineSpecificFGSFeatures,
39
+ construct_beamline_specific_FGS_features,
40
+ )
41
+ from mx_bluesky.common.experiment_plans.common_grid_detect_then_xray_centre_plan import (
42
+ grid_detect_then_xray_centre,
43
+ )
44
+ from mx_bluesky.common.experiment_plans.oav_snapshot_plan import (
45
+ setup_beamline_for_OAV,
46
+ )
47
+ from mx_bluesky.common.external_interaction.callbacks.common.zocalo_callback import (
48
+ ZocaloCallback,
49
+ )
50
+ from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
51
+ GridscanISPyBCallback,
52
+ )
53
+ from mx_bluesky.common.external_interaction.callbacks.xray_centre.nexus_callback import (
54
+ GridscanNexusFileCallback,
55
+ )
56
+ from mx_bluesky.common.parameters.constants import (
57
+ EnvironmentConstants,
58
+ OavConstants,
59
+ PlanGroupCheckpointConstants,
60
+ PlanNameConstants,
61
+ )
62
+ from mx_bluesky.common.parameters.device_composites import (
63
+ GridDetectThenXRayCentreComposite,
64
+ )
65
+ from mx_bluesky.common.parameters.gridscan import GridCommon, SpecifiedThreeDGridScan
66
+ from mx_bluesky.common.preprocessors.preprocessors import (
67
+ transmission_and_xbpm_feedback_for_collection_decorator,
68
+ )
69
+ from mx_bluesky.common.utils.context import device_composite_from_context
70
+ from mx_bluesky.phase1_zebra.device_setup_plans.setup_zebra import (
71
+ setup_zebra_for_gridscan,
72
+ tidy_up_zebra_after_gridscan,
73
+ )
74
+
75
+
76
+ def create_devices(
77
+ context: BlueskyContext,
78
+ ) -> GridDetectThenXRayCentreComposite:
79
+ return device_composite_from_context(context, GridDetectThenXRayCentreComposite)
80
+
81
+
82
+ # See https://github.com/DiamondLightSource/blueapi/issues/506 for using device composites
83
+ def i04_grid_detect_then_xray_centre(
84
+ parameters: GridCommon,
85
+ aperture_scatterguard: ApertureScatterguard = inject("aperture_scatterguard"),
86
+ attenuator: BinaryFilterAttenuator = inject("attenuator"),
87
+ backlight: Backlight = inject("backlight"),
88
+ beamstop: Beamstop = inject("beamstop"),
89
+ dcm: BaseDCM = inject("dcm"),
90
+ zebra_fast_grid_scan: ZebraFastGridScan = inject("zebra_fast_grid_scan"),
91
+ flux: Flux = inject("flux"),
92
+ oav: OAV = inject("oav"),
93
+ pin_tip_detection: PinTipDetection = inject("pin_tip_detection"),
94
+ s4_slit_gaps: S4SlitGaps = inject("s4_slit_gaps"),
95
+ undulator: Undulator = inject("undulator"),
96
+ xbpm_feedback: XBPMFeedback = inject("xbpm_feedback"),
97
+ zebra: Zebra = inject("zebra"),
98
+ robot: BartRobot = inject("robot"),
99
+ sample_shutter: ZebraShutter = inject("sample_shutter"),
100
+ eiger: EigerDetector = inject("eiger"),
101
+ synchrotron: Synchrotron = inject("synchrotron"),
102
+ zocalo: ZocaloResults = inject("zocalo"),
103
+ smargon: Smargon = inject("smargon"),
104
+ detector_motion: DetectorMotion = inject("detector_motion"),
105
+ oav_config: str = OavConstants.OAV_CONFIG_JSON,
106
+ udc: bool = False,
107
+ ) -> MsgGenerator:
108
+ """
109
+ A composite plan which:
110
+ - Uses the OAV to draw a virtual grid over the sample and to take snapshots of the sample
111
+ - Scans through the grid to identify the crystal centre
112
+ - Changes the aperture to match the beam size to the crystal size
113
+ - Moves the sample to the crystal centre of mass
114
+
115
+
116
+ i04's implementation of this plan is very similar to Hyperion. However, since i04
117
+ isn't running in a continious Bluesky UDC loop, we take additional steps in beamline
118
+ tidy-up.
119
+ """
120
+
121
+ composite = GridDetectThenXRayCentreComposite(
122
+ eiger,
123
+ synchrotron,
124
+ zocalo,
125
+ smargon,
126
+ aperture_scatterguard,
127
+ attenuator,
128
+ backlight,
129
+ beamstop,
130
+ dcm,
131
+ detector_motion,
132
+ zebra_fast_grid_scan,
133
+ flux,
134
+ oav,
135
+ pin_tip_detection,
136
+ s4_slit_gaps,
137
+ undulator,
138
+ xbpm_feedback,
139
+ zebra,
140
+ robot,
141
+ sample_shutter,
142
+ )
143
+
144
+ def tidy_beamline_if_not_udc():
145
+ if not udc:
146
+ yield from get_ready_for_oav_and_close_shutter(
147
+ composite.smargon,
148
+ composite.backlight,
149
+ composite.aperture_scatterguard,
150
+ composite.detector_motion,
151
+ )
152
+
153
+ @bpp.finalize_decorator(tidy_beamline_if_not_udc)
154
+ def _inner_grid_detect_then_xrc():
155
+ # These callbacks let us talk to ISPyB and Nexgen. They aren't included in the common plan because
156
+ # Hyperion handles its callbacks differently to BlueAPI-managed plans, see
157
+ # https://github.com/DiamondLightSource/mx-bluesky/issues/1117
158
+ callbacks = create_gridscan_callbacks()
159
+
160
+ @bpp.subs_decorator(callbacks)
161
+ @verify_undulator_gap_before_run_decorator(composite)
162
+ @transmission_and_xbpm_feedback_for_collection_decorator(
163
+ composite, parameters.transmission_frac, PlanNameConstants.GRIDSCAN_OUTER
164
+ )
165
+ def grid_detect_then_xray_centre_with_callbacks():
166
+ yield from grid_detect_then_xray_centre(
167
+ composite=composite,
168
+ parameters=parameters,
169
+ xrc_params_type=SpecifiedThreeDGridScan,
170
+ construct_beamline_specific=construct_i04_specific_features,
171
+ oav_config=oav_config,
172
+ )
173
+
174
+ yield from grid_detect_then_xray_centre_with_callbacks()
175
+
176
+ yield from _inner_grid_detect_then_xrc()
177
+
178
+
179
+ def get_ready_for_oav_and_close_shutter(
180
+ smargon: Smargon,
181
+ backlight: Backlight,
182
+ aperture_scatterguard: ApertureScatterguard,
183
+ detector_motion: DetectorMotion,
184
+ ):
185
+ yield from bps.wait(PlanGroupCheckpointConstants.GRID_READY_FOR_DC)
186
+ group = "get_ready_for_oav_and_close_shutter"
187
+ yield from setup_beamline_for_OAV(
188
+ smargon, backlight, aperture_scatterguard, group=group
189
+ )
190
+ yield from bps.abs_set(
191
+ detector_motion.shutter,
192
+ 0,
193
+ group=group,
194
+ )
195
+ yield from bps.wait(group)
196
+
197
+
198
+ def create_gridscan_callbacks() -> tuple[
199
+ GridscanNexusFileCallback, GridscanISPyBCallback
200
+ ]:
201
+ return (
202
+ GridscanNexusFileCallback(param_type=SpecifiedThreeDGridScan),
203
+ GridscanISPyBCallback(
204
+ param_type=GridCommon,
205
+ emit=ZocaloCallback(
206
+ PlanNameConstants.DO_FGS, EnvironmentConstants.ZOCALO_ENV
207
+ ),
208
+ ),
209
+ )
210
+
211
+
212
+ def construct_i04_specific_features(
213
+ xrc_composite: GridDetectThenXRayCentreComposite,
214
+ xrc_parameters: SpecifiedThreeDGridScan,
215
+ ) -> BeamlineSpecificFGSFeatures:
216
+ """
217
+ Get all the information needed to do the i04 XRC flyscan.
218
+ """
219
+ signals_to_read_pre_flyscan = [
220
+ xrc_composite.undulator.current_gap,
221
+ xrc_composite.synchrotron.synchrotron_mode,
222
+ xrc_composite.s4_slit_gaps.xgap,
223
+ xrc_composite.s4_slit_gaps.ygap,
224
+ xrc_composite.smargon.x,
225
+ xrc_composite.smargon.y,
226
+ xrc_composite.smargon.z,
227
+ xrc_composite.dcm.energy_in_kev,
228
+ ]
229
+
230
+ signals_to_read_during_collection = [
231
+ xrc_composite.aperture_scatterguard,
232
+ xrc_composite.attenuator.actual_transmission,
233
+ xrc_composite.flux.flux_reading,
234
+ xrc_composite.dcm.energy_in_kev,
235
+ xrc_composite.eiger.bit_depth,
236
+ ]
237
+
238
+ tidy_plan = partial(
239
+ tidy_up_zebra_after_gridscan,
240
+ xrc_composite.zebra,
241
+ xrc_composite.sample_shutter,
242
+ group="flyscan_zebra_tidy",
243
+ wait=True,
244
+ )
245
+ set_flyscan_params_plan = partial(
246
+ set_fast_grid_scan_params,
247
+ xrc_composite.zebra_fast_grid_scan,
248
+ xrc_parameters.FGS_params,
249
+ )
250
+ fgs_motors = xrc_composite.zebra_fast_grid_scan
251
+ return construct_beamline_specific_FGS_features(
252
+ setup_zebra_for_gridscan,
253
+ tidy_plan,
254
+ set_flyscan_params_plan,
255
+ fgs_motors,
256
+ signals_to_read_pre_flyscan,
257
+ signals_to_read_during_collection,
258
+ get_xrc_results_from_zocalo=True,
259
+ )
@@ -490,7 +490,9 @@ def run_aborted_plan(pmac: PMAC, dcid: DCID, exception: Exception):
490
490
  either by pressing the Abort button or because of a timeout, and to reset the \
491
491
  P variable.
492
492
  """
493
- SSX_LOGGER.warning(f"Data Collection Aborted: {format_exception(exception)}")
493
+ SSX_LOGGER.warning(
494
+ f"Data Collection Aborted: {''.join(format_exception(exception))}"
495
+ )
494
496
  yield from bps.trigger(pmac.abort_program, wait=True)
495
497
 
496
498
  end_time = datetime.now()
@@ -4,6 +4,7 @@ from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureVal
4
4
  from dodal.devices.smargon import Smargon, StubPosition
5
5
 
6
6
  from mx_bluesky.common.device_setup_plans.manipulate_sample import move_x_y_z
7
+ from mx_bluesky.common.parameters.constants import PlanGroupCheckpointConstants
7
8
  from mx_bluesky.common.utils.log import LOGGER
8
9
  from mx_bluesky.common.utils.tracing import TRACER
9
10
  from mx_bluesky.common.xrc_result import XRayCentreResult
@@ -43,6 +44,7 @@ def change_aperture_then_move_to_xtal(
43
44
  def set_aperture_for_bbox_mm(
44
45
  aperture_device: ApertureScatterguard,
45
46
  bbox_size_mm: list[float] | numpy.ndarray,
47
+ group=PlanGroupCheckpointConstants.GRID_READY_FOR_DC,
46
48
  ):
47
49
  """Sets aperture size based on bbox_size.
48
50
 
@@ -71,4 +73,6 @@ def set_aperture_for_bbox_mm(
71
73
  f"Setting aperture to {new_selected_aperture} based on bounding box size {bbox_size_mm}."
72
74
  )
73
75
 
74
- yield from bps.abs_set(aperture_device.selected_aperture, new_selected_aperture)
76
+ yield from bps.abs_set(
77
+ aperture_device.selected_aperture, new_selected_aperture, group=group
78
+ )
@@ -22,7 +22,7 @@ from mx_bluesky.common.experiment_plans.inner_plans.do_fgs import (
22
22
  ZOCALO_STAGE_GROUP,
23
23
  kickoff_and_complete_gridscan,
24
24
  )
25
- from mx_bluesky.common.experiment_plans.read_hardware import (
25
+ from mx_bluesky.common.experiment_plans.inner_plans.read_hardware import (
26
26
  read_hardware_plan,
27
27
  )
28
28
  from mx_bluesky.common.parameters.constants import (
@@ -55,6 +55,25 @@ class BeamlineSpecificFGSFeatures:
55
55
  get_xrc_results_from_zocalo: bool
56
56
 
57
57
 
58
+ def generic_tidy(xrc_composite: FlyScanEssentialDevices, wait=True) -> MsgGenerator:
59
+ """Tidy Zocalo and turn off Eiger dev/shm. Ran after the beamline-specific tidy plan"""
60
+
61
+ LOGGER.info("Tidying up Zocalo")
62
+ group = "generic_tidy"
63
+ # make sure we don't consume any other results
64
+ yield from bps.unstage(xrc_composite.zocalo, group=group)
65
+
66
+ # Turn off dev/shm streaming to avoid filling disk, see https://github.com/DiamondLightSource/hyperion/issues/1395
67
+ LOGGER.info("Turning off Eiger dev/shm streaming")
68
+ # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
69
+ yield from bps.abs_set(
70
+ xrc_composite.eiger.odin.fan.dev_shm_enable, # type: ignore
71
+ 0,
72
+ group=group,
73
+ )
74
+ yield from bps.wait(group)
75
+
76
+
58
77
  def construct_beamline_specific_FGS_features(
59
78
  setup_trigger_plan: Callable[..., MsgGenerator],
60
79
  tidy_plan: Callable[..., MsgGenerator],
@@ -71,7 +90,7 @@ def construct_beamline_specific_FGS_features(
71
90
  Ran directly before kicking off the gridscan.
72
91
 
73
92
  tidy_plan (Callable): Tidy up states of devices. Ran at the end of the flyscan, regardless of
74
- whether or not it finished successfully.
93
+ whether or not it finished successfully. Zocalo and Eiger are cleaned up separately
75
94
 
76
95
  set_flyscan_params_plan (Callable): Set PV's for the relevant Fast Grid Scan dodal device
77
96
 
@@ -135,6 +154,10 @@ def common_flyscan_xray_centre(
135
154
  There are a few other useful decorators to use with this plan, see: verify_undulator_gap_before_run_decorator, transmission_and_xbpm_feedback_for_collection_decorator
136
155
  """
137
156
 
157
+ def _overall_tidy():
158
+ yield from beamline_specific.tidy_plan()
159
+ yield from generic_tidy(composite)
160
+
138
161
  def _decorated_flyscan():
139
162
  @bpp.set_run_key_decorator(PlanNameConstants.GRIDSCAN_OUTER)
140
163
  @bpp.run_decorator( # attach experiment metadata to the start document
@@ -146,7 +169,7 @@ def common_flyscan_xray_centre(
146
169
  ],
147
170
  }
148
171
  )
149
- @bpp.finalize_decorator(lambda: beamline_specific.tidy_plan(composite))
172
+ @bpp.finalize_decorator(lambda: _overall_tidy())
150
173
  def run_gridscan_and_tidy(
151
174
  fgs_composite: FlyScanEssentialDevices,
152
175
  params: SpecifiedThreeDGridScan,
@@ -111,6 +111,7 @@ def grid_detect_then_xray_centre(
111
111
  )
112
112
 
113
113
 
114
+ # This function should be private but is currently called by Hyperion, see https://github.com/DiamondLightSource/mx-bluesky/issues/1148
114
115
  def detect_grid_and_do_gridscan(
115
116
  composite: GridDetectThenXRayCentreComposite,
116
117
  parameters: GridCommon,
@@ -14,7 +14,9 @@ from dodal.log import LOGGER
14
14
  from dodal.plan_stubs.check_topup import check_topup_and_wait_if_necessary
15
15
  from scanspec.core import AxesPoints, Axis
16
16
 
17
- from mx_bluesky.common.experiment_plans.read_hardware import read_hardware_for_zocalo
17
+ from mx_bluesky.common.experiment_plans.inner_plans.read_hardware import (
18
+ read_hardware_for_zocalo,
19
+ )
18
20
  from mx_bluesky.common.parameters.constants import (
19
21
  PlanNameConstants,
20
22
  )
@@ -145,11 +145,17 @@ class StoreInIspyb:
145
145
  def append_to_comment(
146
146
  self, data_collection_id: int, comment: str, delimiter: str = " "
147
147
  ) -> None:
148
- with ispyb.open(self.ISPYB_CONFIG_PATH) as conn:
149
- assert conn is not None, "Failed to connect to ISPyB!"
150
- mx_acquisition: MXAcquisition = conn.mx_acquisition
151
- mx_acquisition.update_data_collection_append_comments(
152
- data_collection_id, comment, delimiter
148
+ try:
149
+ with ispyb.open(self.ISPYB_CONFIG_PATH) as conn:
150
+ assert conn is not None, "Failed to connect to ISPyB!"
151
+ mx_acquisition: MXAcquisition = conn.mx_acquisition
152
+ mx_acquisition.update_data_collection_append_comments(
153
+ data_collection_id, comment, delimiter
154
+ )
155
+ except ispyb.ReadWriteError as e:
156
+ ISPYB_ZOCALO_CALLBACK_LOGGER.warning(
157
+ f"Unable to log comment, comment probably exceeded column length: {comment}",
158
+ exc_info=e,
153
159
  )
154
160
 
155
161
  def update_data_collection_group_table(
@@ -186,7 +192,6 @@ class StoreInIspyb:
186
192
  params["parentid"] = data_collection_group_id
187
193
  params["endtime"] = end_time
188
194
  params["run_status"] = run_status
189
-
190
195
  mx_acquisition.upsert_data_collection(list(params.values()))
191
196
 
192
197
  def _store_position_table(
File without changes
@@ -11,6 +11,7 @@ from mx_bluesky.definitions import ROOT_DIR
11
11
 
12
12
  BEAMLINE = get_beamline_name("test")
13
13
  TEST_MODE = BEAMLINE == "test"
14
+ ZEBRA_STATUS_TIMEOUT = 30
14
15
 
15
16
 
16
17
  @dataclass(frozen=True)
@@ -11,7 +11,7 @@ from dodal.devices.fast_grid_scan import (
11
11
  ZebraFastGridScan,
12
12
  )
13
13
  from dodal.devices.flux import Flux
14
- from dodal.devices.i03 import Beamstop
14
+ from dodal.devices.mx_phase1.beamstop import Beamstop
15
15
  from dodal.devices.oav.oav_detector import OAV
16
16
  from dodal.devices.oav.pin_image_recognition import PinTipDetection
17
17
  from dodal.devices.robot import BartRobot
@@ -30,6 +30,7 @@ DETECTOR_SIZE_PER_BEAMLINE = {
30
30
  "i02-1": EIGER2_X_9M_SIZE,
31
31
  "dev": EIGER2_X_16M_SIZE,
32
32
  "i03": EIGER2_X_16M_SIZE,
33
+ "i04": EIGER2_X_16M_SIZE,
33
34
  }
34
35
 
35
36
 
@@ -218,7 +218,7 @@ class RunExperiment(Resource):
218
218
  status_and_message = self.runner.start(plan, params, plan_name)
219
219
  except Exception as e:
220
220
  status_and_message = make_error_status_and_message(e)
221
- LOGGER.error(format_exception(e))
221
+ LOGGER.error("".join(format_exception(e)))
222
222
 
223
223
  elif action == Actions.STOP.value:
224
224
  status_and_message = self.runner.stop()
@@ -1,18 +1,26 @@
1
1
  from collections.abc import Sequence
2
2
 
3
+ from blueapi.core import BlueskyContext
3
4
  from bluesky import plan_stubs as bps
4
5
  from bluesky import preprocessors as bpp
5
6
  from dodal.devices.baton import Baton
6
7
 
8
+ from mx_bluesky.common.utils.context import find_device_in_context
7
9
  from mx_bluesky.common.utils.exceptions import WarningException
10
+ from mx_bluesky.common.utils.log import LOGGER
8
11
  from mx_bluesky.hyperion.experiment_plans.load_centre_collect_full_plan import (
9
12
  LoadCentreCollectComposite,
13
+ create_devices,
10
14
  load_centre_collect_full,
11
15
  )
12
16
  from mx_bluesky.hyperion.external_interaction.agamemnon import (
13
17
  create_parameters_from_agamemnon,
14
18
  )
15
19
  from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
20
+ from mx_bluesky.hyperion.utils.context import (
21
+ clear_all_device_caches,
22
+ setup_devices,
23
+ )
16
24
 
17
25
  HYPERION_USER = "Hyperion"
18
26
  NO_USER = "None"
@@ -59,7 +67,24 @@ def move_to_default_state():
59
67
  yield from bps.null()
60
68
 
61
69
 
62
- def run_udc_when_requested(baton: Baton, composite: LoadCentreCollectComposite):
70
+ def initialise_udc(context: BlueskyContext, dev_mode: bool = False):
71
+ """
72
+ Perform all initialisation that happens at the start of UDC just after the
73
+ baton is acquired, but before we execute any plans or move hardware.
74
+
75
+ Beamline devices are unloaded and reloaded in order to pick up any new configuration,
76
+ bluesky context gets new set of devices.
77
+ """
78
+ LOGGER.info("Initialising mx-bluesky for UDC start...")
79
+ clear_all_device_caches(context)
80
+ setup_devices(context, dev_mode)
81
+
82
+
83
+ def _get_baton(context: BlueskyContext) -> Baton:
84
+ return find_device_in_context(context, "baton", Baton)
85
+
86
+
87
+ def run_udc_when_requested(context: BlueskyContext, dev_mode: bool = False):
63
88
  """This will wait for the baton to be handed to hyperion and then run through the
64
89
  UDC queue from agamemnon until:
65
90
  1. There are no more instructions from agamemnon
@@ -69,21 +94,28 @@ def run_udc_when_requested(baton: Baton, composite: LoadCentreCollectComposite):
69
94
  In the case of 1. or 2. hyperion will immediately release the baton. In the case of
70
95
  3. the baton will be released after the next collection has finished."""
71
96
 
97
+ baton = _get_baton(context)
72
98
  yield from wait_for_hyperion_requested(baton)
73
99
  yield from bps.abs_set(baton.current_user, HYPERION_USER)
74
100
 
75
- def default_state_then_collect():
101
+ def initialise_then_collect():
102
+ initialise_udc(context, dev_mode)
76
103
  yield from move_to_default_state()
77
- yield from main_hyperion_loop(baton, composite)
104
+
105
+ # re-fetch the baton because the device has been reinstantiated
106
+ new_baton = _get_baton(context)
107
+ composite = create_devices(context)
108
+ yield from main_hyperion_loop(new_baton, composite)
78
109
 
79
110
  def release_baton():
80
111
  # If hyperion has given up the baton itself we need to also release requested
81
112
  # user so that hyperion doesn't think we're requested again
113
+ baton = _get_baton(context)
82
114
  requested_user = yield from bps.rd(baton.requested_user)
83
115
  if requested_user == HYPERION_USER:
84
116
  yield from bps.abs_set(baton.requested_user, NO_USER)
85
117
  yield from bps.abs_set(baton.current_user, NO_USER)
86
118
 
87
119
  yield from bpp.contingency_wrapper(
88
- default_state_then_collect(), final_plan=release_baton
120
+ initialise_then_collect(), final_plan=release_baton
89
121
  )
@@ -1,5 +1,4 @@
1
1
  import bluesky.plan_stubs as bps
2
- from bluesky.utils import MsgGenerator
3
2
  from dodal.devices.zebra.zebra import (
4
3
  ArmDemand,
5
4
  EncEnum,
@@ -12,9 +11,11 @@ from dodal.devices.zebra.zebra_controlled_shutter import (
12
11
  ZebraShutterControl,
13
12
  )
14
13
 
14
+ from mx_bluesky.common.parameters.constants import ZEBRA_STATUS_TIMEOUT
15
15
  from mx_bluesky.common.utils.log import LOGGER
16
-
17
- ZEBRA_STATUS_TIMEOUT = 30
16
+ from mx_bluesky.phase1_zebra.device_setup_plans.setup_zebra import (
17
+ configure_zebra_and_shutter_for_auto_shutter,
18
+ )
18
19
 
19
20
 
20
21
  def arm_zebra(zebra: Zebra):
@@ -35,47 +36,6 @@ def tidy_up_zebra_after_rotation_scan(
35
36
  yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
36
37
 
37
38
 
38
- def set_shutter_auto_input(zebra: Zebra, input: int, group="set_shutter_trigger"):
39
- """Set the signal that controls the shutter. We use the second input to the
40
- Zebra's AND2 gate for this input. ZebraShutter control mode must be in auto for this input to take control
41
-
42
- For more details see the ZebraShutter device."""
43
- auto_gate = zebra.mapping.AND_GATE_FOR_AUTO_SHUTTER
44
- auto_shutter_control = zebra.logic_gates.and_gates[auto_gate]
45
- yield from bps.abs_set(auto_shutter_control.sources[2], input, group)
46
-
47
-
48
- def configure_zebra_and_shutter_for_auto_shutter(
49
- zebra: Zebra, zebra_shutter: ZebraShutter, input: int, group="use_automatic_shutter"
50
- ):
51
- """Set the shutter to auto mode, and configure the zebra to trigger the shutter on
52
- an input source. For the input, use one of the source constants in zebra.py
53
-
54
- When the shutter is in auto/manual, logic in EPICS sets the Zebra's
55
- SOFT_IN1 to low/high respectively. The Zebra's AND2 gate should be used to control the shutter while in auto mode.
56
- To do this, we need (AND2 = SOFT_IN1 AND input), where input is the zebra signal we want to control the shutter when in auto mode.
57
- """
58
- # See https://github.com/DiamondLightSource/dodal/issues/813 for better typing here.
59
-
60
- # Set shutter to auto mode
61
- yield from bps.abs_set(
62
- zebra_shutter.control_mode, ZebraShutterControl.AUTO, group=group
63
- )
64
-
65
- auto_gate = zebra.mapping.AND_GATE_FOR_AUTO_SHUTTER
66
-
67
- # Set first input of AND2 gate to SOFT_IN1, which is high when shutter is in auto mode
68
- # Note the Zebra should ALWAYS be setup this way. See https://github.com/DiamondLightSource/mx-bluesky/issues/551
69
- yield from bps.abs_set(
70
- zebra.logic_gates.and_gates[auto_gate].sources[1],
71
- zebra.mapping.sources.SOFT_IN1,
72
- group=group,
73
- )
74
-
75
- # Set the second input of AND2 gate to the requested zebra input source
76
- yield from set_shutter_auto_input(zebra, input, group=group)
77
-
78
-
79
39
  def setup_zebra_for_rotation(
80
40
  zebra: Zebra,
81
41
  zebra_shutter: ZebraShutter,
@@ -155,55 +115,6 @@ def setup_zebra_for_rotation(
155
115
  yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
156
116
 
157
117
 
158
- def setup_zebra_for_gridscan(
159
- zebra: Zebra,
160
- zebra_shutter: ZebraShutter,
161
- group="setup_zebra_for_gridscan",
162
- wait=True,
163
- ):
164
- # Set shutter to automatic and to trigger via motion controller GPIO signal (IN4_TTL)
165
- yield from configure_zebra_and_shutter_for_auto_shutter(
166
- zebra, zebra_shutter, zebra.mapping.sources.IN4_TTL, group=group
167
- )
168
-
169
- yield from bps.abs_set(
170
- zebra.output.out_pvs[zebra.mapping.outputs.TTL_DETECTOR],
171
- zebra.mapping.sources.IN3_TTL,
172
- group=group,
173
- )
174
- yield from bps.abs_set(
175
- zebra.output.out_pvs[zebra.mapping.outputs.TTL_XSPRESS3],
176
- zebra.mapping.sources.DISCONNECT,
177
- group=group,
178
- )
179
- yield from bps.abs_set(
180
- zebra.output.pulse_1.input, zebra.mapping.sources.DISCONNECT, group=group
181
- )
182
-
183
- if wait:
184
- yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
185
-
186
-
187
- def tidy_up_zebra_after_gridscan(
188
- zebra: Zebra,
189
- zebra_shutter: ZebraShutter,
190
- group="tidy_up_zebra_after_gridscan",
191
- wait=True,
192
- ) -> MsgGenerator:
193
- yield from bps.abs_set(
194
- zebra.output.out_pvs[zebra.mapping.outputs.TTL_DETECTOR],
195
- zebra.mapping.sources.PC_PULSE,
196
- group=group,
197
- )
198
- yield from bps.abs_set(
199
- zebra_shutter.control_mode, ZebraShutterControl.MANUAL, group=group
200
- )
201
- yield from set_shutter_auto_input(zebra, zebra.mapping.sources.PC_GATE, group=group)
202
-
203
- if wait:
204
- yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
205
-
206
-
207
118
  def setup_zebra_for_panda_flyscan(
208
119
  zebra: Zebra,
209
120
  zebra_shutter: ZebraShutter,
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Callable
3
4
  from functools import partial
4
5
  from pathlib import Path
5
6
 
@@ -19,14 +20,16 @@ from mx_bluesky.hyperion.device_setup_plans.setup_panda import (
19
20
  setup_panda_for_flyscan,
20
21
  )
21
22
  from mx_bluesky.hyperion.device_setup_plans.setup_zebra import (
22
- setup_zebra_for_gridscan,
23
23
  setup_zebra_for_panda_flyscan,
24
- tidy_up_zebra_after_gridscan,
25
24
  )
26
25
  from mx_bluesky.hyperion.parameters.device_composites import (
27
26
  HyperionFlyScanXRayCentreComposite,
28
27
  )
29
28
  from mx_bluesky.hyperion.parameters.gridscan import HyperionSpecifiedThreeDGridScan
29
+ from mx_bluesky.phase1_zebra.device_setup_plans.setup_zebra import (
30
+ setup_zebra_for_gridscan,
31
+ tidy_up_zebra_after_gridscan,
32
+ )
30
33
 
31
34
 
32
35
  class SmargonSpeedException(Exception):
@@ -59,9 +62,11 @@ def construct_hyperion_specific_features(
59
62
  xrc_composite.eiger.bit_depth,
60
63
  ]
61
64
 
65
+ setup_trigger_plan: Callable[..., MsgGenerator]
66
+
62
67
  if xrc_parameters.features.use_panda_for_gridscan:
63
68
  setup_trigger_plan = _panda_triggering_setup
64
- tidy_plan = _panda_tidy
69
+ tidy_plan = partial(_panda_tidy, xrc_composite)
65
70
  set_flyscan_params_plan = partial(
66
71
  set_fast_grid_scan_params,
67
72
  xrc_composite.panda_fast_grid_scan,
@@ -70,8 +75,14 @@ def construct_hyperion_specific_features(
70
75
  fgs_motors = xrc_composite.panda_fast_grid_scan
71
76
 
72
77
  else:
73
- setup_trigger_plan = _zebra_triggering_setup
74
- tidy_plan = partial(_generic_tidy, group="flyscan_zebra_tidy", wait=True)
78
+ setup_trigger_plan = setup_zebra_for_gridscan
79
+ tidy_plan = partial(
80
+ tidy_up_zebra_after_gridscan,
81
+ xrc_composite.zebra,
82
+ xrc_composite.sample_shutter,
83
+ group="flyscan_zebra_tidy",
84
+ wait=True,
85
+ )
75
86
  set_flyscan_params_plan = partial(
76
87
  set_fast_grid_scan_params,
77
88
  xrc_composite.zebra_fast_grid_scan,
@@ -89,46 +100,17 @@ def construct_hyperion_specific_features(
89
100
  )
90
101
 
91
102
 
92
- def _generic_tidy(
93
- xrc_composite: HyperionFlyScanXRayCentreComposite, group, wait=True
94
- ) -> MsgGenerator:
95
- LOGGER.info("Tidying up Zebra")
96
- yield from tidy_up_zebra_after_gridscan(
97
- xrc_composite.zebra, xrc_composite.sample_shutter, group=group, wait=wait
98
- )
99
- LOGGER.info("Tidying up Zocalo")
100
- # make sure we don't consume any other results
101
- yield from bps.unstage(xrc_composite.zocalo, group=group, wait=wait)
102
-
103
- # Turn off dev/shm streaming to avoid filling disk, see https://github.com/DiamondLightSource/hyperion/issues/1395
104
- LOGGER.info("Turning off Eiger dev/shm streaming")
105
- # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
106
- yield from bps.abs_set(
107
- xrc_composite.eiger.odin.fan.dev_shm_enable, # type: ignore
108
- 0,
109
- group=group,
110
- wait=wait,
111
- )
112
-
113
-
114
103
  def _panda_tidy(xrc_composite: HyperionFlyScanXRayCentreComposite):
115
104
  group = "panda_flyscan_tidy"
116
105
  LOGGER.info("Disabling panda blocks")
117
106
  yield from disarm_panda_for_gridscan(xrc_composite.panda, group)
118
- yield from _generic_tidy(xrc_composite, group, False)
107
+ yield from tidy_up_zebra_after_gridscan(
108
+ xrc_composite.zebra, xrc_composite.sample_shutter, group=group, wait=False
109
+ )
119
110
  yield from bps.wait(group, timeout=10)
120
111
  yield from bps.unstage(xrc_composite.panda)
121
112
 
122
113
 
123
- def _zebra_triggering_setup(
124
- xrc_composite: HyperionFlyScanXRayCentreComposite,
125
- parameters: HyperionSpecifiedThreeDGridScan,
126
- ) -> MsgGenerator:
127
- yield from setup_zebra_for_gridscan(
128
- xrc_composite.zebra, xrc_composite.sample_shutter, wait=True
129
- )
130
-
131
-
132
114
  def _panda_triggering_setup(
133
115
  xrc_composite: HyperionFlyScanXRayCentreComposite,
134
116
  parameters: HyperionSpecifiedThreeDGridScan,
@@ -37,16 +37,16 @@ from mx_bluesky.common.device_setup_plans.manipulate_sample import (
37
37
  from mx_bluesky.common.device_setup_plans.utils import (
38
38
  start_preparing_data_collection_then_do_plan,
39
39
  )
40
+ from mx_bluesky.common.experiment_plans.inner_plans.read_hardware import (
41
+ read_hardware_for_zocalo,
42
+ standard_read_hardware_during_collection,
43
+ standard_read_hardware_pre_collection,
44
+ )
40
45
  from mx_bluesky.common.experiment_plans.oav_snapshot_plan import (
41
46
  OavSnapshotComposite,
42
47
  oav_snapshot_plan,
43
48
  setup_beamline_for_OAV,
44
49
  )
45
- from mx_bluesky.common.experiment_plans.read_hardware import (
46
- read_hardware_for_zocalo,
47
- standard_read_hardware_during_collection,
48
- standard_read_hardware_pre_collection,
49
- )
50
50
  from mx_bluesky.common.parameters.components import WithSnapshot
51
51
  from mx_bluesky.common.preprocessors.preprocessors import (
52
52
  transmission_and_xbpm_feedback_for_collection_decorator,
@@ -35,7 +35,6 @@ class I03Constants:
35
35
 
36
36
  @dataclass(frozen=True)
37
37
  class HyperionConstants:
38
- DESCRIPTORS = DocDescriptorNames()
39
38
  ZOCALO_ENV = EnvironmentConstants.ZOCALO_ENV
40
39
  HARDWARE = HardwareConstants()
41
40
  I03 = I03Constants()
@@ -49,7 +48,7 @@ class HyperionConstants:
49
48
  if TEST_MODE
50
49
  else "https://daq-config.diamond.ac.uk/api"
51
50
  )
52
- GRAYLOG_PORT = 12232
51
+ GRAYLOG_PORT = 12232 # Hyperion stream
53
52
  PARAMETER_SCHEMA_DIRECTORY = "src/hyperion/parameters/schemas/"
54
53
  LOG_FILE_NAME = "hyperion.log"
55
54
  DEVICE_SETTINGS_CONSTANTS = DeviceSettingsConstants()
@@ -1,5 +1,6 @@
1
1
  from blueapi.core import BlueskyContext
2
- from dodal.utils import get_beamline_based_on_environment_variable
2
+ from dodal.common.beamlines.beamline_utils import clear_devices
3
+ from dodal.utils import collect_factories, get_beamline_based_on_environment_variable
3
4
 
4
5
  import mx_bluesky.hyperion.experiment_plans as hyperion_plans
5
6
  from mx_bluesky.common.utils.log import LOGGER
@@ -9,11 +10,24 @@ def setup_context(dev_mode: bool = False) -> BlueskyContext:
9
10
  context = BlueskyContext()
10
11
  context.with_plan_module(hyperion_plans)
11
12
 
12
- context.with_dodal_module(
13
- get_beamline_based_on_environment_variable(),
14
- mock=dev_mode,
15
- )
13
+ setup_devices(context, dev_mode)
16
14
 
17
15
  LOGGER.info(f"Plans found in context: {context.plan_functions.keys()}")
18
16
 
19
17
  return context
18
+
19
+
20
+ def clear_all_device_caches(context: BlueskyContext):
21
+ context.unregister_all_devices()
22
+ clear_devices()
23
+
24
+ for f in collect_factories(get_beamline_based_on_environment_variable()).values():
25
+ if hasattr(f, "cache_clear"):
26
+ f.cache_clear() # type: ignore
27
+
28
+
29
+ def setup_devices(context: BlueskyContext, dev_mode: bool):
30
+ context.with_dodal_module(
31
+ get_beamline_based_on_environment_variable(),
32
+ mock=dev_mode,
33
+ )
@@ -0,0 +1 @@
1
+ """The zebra on i03 and i04 (phase1 beamlines) are configured in a specific way which are compatible to the plans in this module"""
File without changes
@@ -0,0 +1,112 @@
1
+ from typing import Protocol, runtime_checkable
2
+
3
+ import bluesky.plan_stubs as bps
4
+ from bluesky.utils import MsgGenerator
5
+ from dodal.devices.zebra.zebra import (
6
+ Zebra,
7
+ )
8
+ from dodal.devices.zebra.zebra_controlled_shutter import (
9
+ ZebraShutter,
10
+ ZebraShutterControl,
11
+ )
12
+
13
+ from mx_bluesky.common.parameters.constants import ZEBRA_STATUS_TIMEOUT
14
+ from mx_bluesky.common.utils.log import LOGGER
15
+
16
+
17
+ @runtime_checkable
18
+ class GridscanSetupDevices(Protocol):
19
+ zebra: Zebra
20
+ sample_shutter: ZebraShutter
21
+
22
+
23
+ def setup_zebra_for_gridscan(
24
+ composite: GridscanSetupDevices, # XRC gridscan's generic trigger setup expects a composite rather than individual devices
25
+ group="setup_zebra_for_gridscan",
26
+ wait=True,
27
+ ) -> MsgGenerator:
28
+ zebra = composite.zebra
29
+ # Set shutter to automatic and to trigger via motion controller GPIO signal (IN4_TTL)
30
+ yield from configure_zebra_and_shutter_for_auto_shutter(
31
+ zebra, composite.sample_shutter, zebra.mapping.sources.IN4_TTL, group=group
32
+ )
33
+
34
+ yield from bps.abs_set(
35
+ zebra.output.out_pvs[zebra.mapping.outputs.TTL_DETECTOR],
36
+ zebra.mapping.sources.IN3_TTL,
37
+ group=group,
38
+ )
39
+ yield from bps.abs_set(
40
+ zebra.output.out_pvs[zebra.mapping.outputs.TTL_XSPRESS3],
41
+ zebra.mapping.sources.DISCONNECT,
42
+ group=group,
43
+ )
44
+ yield from bps.abs_set(
45
+ zebra.output.pulse_1.input, zebra.mapping.sources.DISCONNECT, group=group
46
+ )
47
+
48
+ if wait:
49
+ yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
50
+
51
+
52
+ def set_shutter_auto_input(zebra: Zebra, input: int, group="set_shutter_trigger"):
53
+ """Set the signal that controls the shutter. We use the second input to the
54
+ Zebra's AND2 gate for this input. ZebraShutter control mode must be in auto for this input to take control
55
+
56
+ For more details see the ZebraShutter device."""
57
+ auto_gate = zebra.mapping.AND_GATE_FOR_AUTO_SHUTTER
58
+ auto_shutter_control = zebra.logic_gates.and_gates[auto_gate]
59
+ yield from bps.abs_set(auto_shutter_control.sources[2], input, group)
60
+
61
+
62
+ def configure_zebra_and_shutter_for_auto_shutter(
63
+ zebra: Zebra, zebra_shutter: ZebraShutter, input: int, group="use_automatic_shutter"
64
+ ):
65
+ """Set the shutter to auto mode, and configure the zebra to trigger the shutter on
66
+ an input source. For the input, use one of the source constants in zebra.py
67
+
68
+ When the shutter is in auto/manual, logic in EPICS sets the Zebra's
69
+ SOFT_IN1 to low/high respectively. The Zebra's AND2 gate should be used to control the shutter while in auto mode.
70
+ To do this, we need (AND2 = SOFT_IN1 AND input), where input is the zebra signal we want to control the shutter when in auto mode.
71
+ """
72
+ # See https://github.com/DiamondLightSource/dodal/issues/813 for better typing here.
73
+
74
+ # Set shutter to auto mode
75
+ yield from bps.abs_set(
76
+ zebra_shutter.control_mode, ZebraShutterControl.AUTO, group=group
77
+ )
78
+
79
+ auto_gate = zebra.mapping.AND_GATE_FOR_AUTO_SHUTTER
80
+
81
+ # Set first input of AND2 gate to SOFT_IN1, which is high when shutter is in auto mode
82
+ # Note the Zebra should ALWAYS be setup this way. See https://github.com/DiamondLightSource/mx-bluesky/issues/551
83
+ yield from bps.abs_set(
84
+ zebra.logic_gates.and_gates[auto_gate].sources[1],
85
+ zebra.mapping.sources.SOFT_IN1,
86
+ group=group,
87
+ )
88
+
89
+ # Set the second input of AND2 gate to the requested zebra input source
90
+ yield from set_shutter_auto_input(zebra, input, group=group)
91
+
92
+
93
+ def tidy_up_zebra_after_gridscan(
94
+ zebra: Zebra,
95
+ zebra_shutter: ZebraShutter,
96
+ group="tidy_up_zebra_after_gridscan",
97
+ wait=True,
98
+ ) -> MsgGenerator:
99
+ LOGGER.info("Tidying up Zebra")
100
+
101
+ yield from bps.abs_set(
102
+ zebra.output.out_pvs[zebra.mapping.outputs.TTL_DETECTOR],
103
+ zebra.mapping.sources.PC_PULSE,
104
+ group=group,
105
+ )
106
+ yield from bps.abs_set(
107
+ zebra_shutter.control_mode, ZebraShutterControl.MANUAL, group=group
108
+ )
109
+ yield from set_shutter_auto_input(zebra, zebra.mapping.sources.PC_GATE, group=group)
110
+
111
+ if wait:
112
+ yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mx-bluesky
3
- Version: 1.5.1
3
+ Version: 1.5.2
4
4
  Summary: Bluesky tools for MX Beamlines at DLS
5
5
  Author-email: Dominic Oram <dominic.oram@diamond.ac.uk>
6
6
  License: Apache License
@@ -235,12 +235,12 @@ Requires-Dist: scipy
235
235
  Requires-Dist: semver
236
236
  Requires-Dist: deepdiff
237
237
  Requires-Dist: matplotlib
238
- Requires-Dist: blueapi>=0.11.1
238
+ Requires-Dist: blueapi>=0.15.0
239
239
  Requires-Dist: daq-config-server==0.1.1
240
240
  Requires-Dist: ophyd>=1.10.5
241
241
  Requires-Dist: ophyd-async>=0.10.0a2
242
242
  Requires-Dist: bluesky>=1.13.1
243
- Requires-Dist: dls-dodal==1.51.0
243
+ Requires-Dist: dls-dodal==1.52.0
244
244
  Provides-Extra: dev
245
245
  Requires-Dist: black; extra == "dev"
246
246
  Requires-Dist: build; extra == "dev"
@@ -1,6 +1,6 @@
1
1
  mx_bluesky/__init__.py,sha256=Ksms_WJF8LTkbm38gEpm1jBpGqcQ8NGvmb2ZJlOE1j8,198
2
2
  mx_bluesky/__main__.py,sha256=RVqPnxDisFMIn_aoEi0drlThNHgKTJULnSrotouIKI0,480
3
- mx_bluesky/_version.py,sha256=FasBapRYrTzegTWgTLGzFg84_c9eAAt8ZkOEeQxlLC4,511
3
+ mx_bluesky/_version.py,sha256=ULxoARbzjBMKCLCwFpnGZ1a36HS9SymijR2WGye0UeQ,511
4
4
  mx_bluesky/definitions.py,sha256=ULpEYAUzdQiEbBoTgYTMxfUf3DDDjhYtvDxofs7Qxqw,168
5
5
  mx_bluesky/jupyter_example.ipynb,sha256=wpwvPrBvwtRMS5AIFk8F54cIlUoD0o4ji8tKK5cZHA4,1672
6
6
  mx_bluesky/beamlines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -8,10 +8,12 @@ mx_bluesky/beamlines/aithre_lasershaping/__init__.py,sha256=A0dlifkBYPlCiMkTEovT
8
8
  mx_bluesky/beamlines/aithre_lasershaping/beamline_safe.py,sha256=-GTu2w7dIKtssZB8vXwE2f1zF-Pg1zC_jwBbB-r2Goo,1233
9
9
  mx_bluesky/beamlines/aithre_lasershaping/check_goniometer_performance.py,sha256=AqWAFey_Ih1JcRxVNiZDGFsVg4kvA9LH2p5SJeXfe2I,834
10
10
  mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py,sha256=1La4vJmQdKp3_Ib1DMgavJBdYLTxp7S7dEr_lqNknV0,1828
11
- mx_bluesky/beamlines/i04/__init__.py,sha256=jZjAMN5_oOEjQoR3iTrnMFW3ElxlHhQ7pEQZIv21Y4I,129
11
+ mx_bluesky/beamlines/i04/__init__.py,sha256=5ainxns2EcIh7EXqdZJRLI8yYDCBpY1-Dflqn7JDm-c,271
12
12
  mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py,sha256=T6K0LOwwGxB05YvS6FV-UU4O2N2GMQdEM2vj9BSow_U,6618
13
13
  mx_bluesky/beamlines/i04/thawing_plan.py,sha256=uvm1wfp012GN5yE7TcURSQeDtC9nWnW5X__6UCXazjA,5085
14
- mx_bluesky/beamlines/i04/callbacks/murko_callback.py,sha256=ZIwkY6gdcmIE-aMBvehN8DVcjGRtb9wwzpgHJNMZ39Q,2125
14
+ mx_bluesky/beamlines/i04/callbacks/murko_callback.py,sha256=C2KoIxwMIWxD46utmq1-69SIc8MspocXJ1sccO1lwAY,4458
15
+ mx_bluesky/beamlines/i04/experiment_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py,sha256=hWMnQSnmCrlVQgxi4qyqD0WtFt65_rSpSwYB_9bHMXY,9236
15
17
  mx_bluesky/beamlines/i23/__init__.py,sha256=7nwQiKBZAXLnvPhCqaI2VC1k4TOzQalOUvwF6SQ3Yd4,95
16
18
  mx_bluesky/beamlines/i23/serial.py,sha256=XVbHM8NevnJMFAJD9jkxG-VnPaWX6t_k-wlipRw0pmY,2055
17
19
  mx_bluesky/beamlines/i24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -33,7 +35,7 @@ mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.ed
33
35
  mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/microdrop_alignment.edl,sha256=K79vmGAcf9qVEQLXTgr0g4bZDWaJ7nFoK4e0Ex7qAwM,14690
34
36
  mx_bluesky/beamlines/i24/serial/fixed_target/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
37
  mx_bluesky/beamlines/i24/serial/fixed_target/ft_utils.py,sha256=puO1vg0x-TPgv8FbEFg73ohJqbwDpcG50_2cLUTa2FA,1210
36
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py,sha256=d5eG8xllmCf0wJO-tsN2vzALaahMr7igm6ap94hGqrY,25515
38
+ mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py,sha256=aUwzEQAuib9V0AZsnnk34FhJ2IVi4XsPV5D2OnfySHk,25538
37
39
  mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py,sha256=fjX_UKOfdA38u-3hhe6t7Y9c6r-HijyWqOi3kLUY3M8,33098
38
40
  mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py,sha256=Vokr_Gl_lpqcUwG18C2h8TYMmyTx1HmUSDd9zgR9-7M,3275
39
41
  mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py,sha256=QLg4wryENBeFfOYFaIgE9R12r2KvUuKIP9ZY8iyYibY,6582
@@ -76,15 +78,15 @@ mx_bluesky/common/device_setup_plans/setup_panda.py,sha256=OF-ZygZyAyQEUdrAWiIxW
76
78
  mx_bluesky/common/device_setup_plans/utils.py,sha256=S_Us1KfLkyaRzWxmqnoVxHj2Suq-Vs0n5fMRygHgrTw,1859
77
79
  mx_bluesky/common/device_setup_plans/xbpm_feedback.py,sha256=WsUMdeOZBgbj-bFp7x66aHp2oWffQmjyp61-qmtQAmI,2153
78
80
  mx_bluesky/common/experiment_plans/__init__.py,sha256=FMA-4VN1TJCPcyURKF0qPIQ8uo8YBbtHPRdJokVF4MA,129
79
- mx_bluesky/common/experiment_plans/change_aperture_then_move_plan.py,sha256=IY5pq8ni_LKD4LTZG0bbKrC3fEXAnxiunIkp6Oray_c,2897
80
- mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py,sha256=Zus9VDwse1iDJu_920UutWyddEtviJXt2ORYvQKIhqg,12304
81
- mx_bluesky/common/experiment_plans/common_grid_detect_then_xray_centre_plan.py,sha256=N9LXiKJWCOOJ_AyKJu6jMIKocvOidjTA5JOOG5xWPmw,6921
81
+ mx_bluesky/common/experiment_plans/change_aperture_then_move_plan.py,sha256=407E9rp0yGWWIU1fJrgqK_hC19mVwRK-Und7fMlGNDc,3062
82
+ mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py,sha256=jLo9nrd8CW85Px7t3I6QlnfD71VhApyVJMfWB6-gJgk,13245
83
+ mx_bluesky/common/experiment_plans/common_grid_detect_then_xray_centre_plan.py,sha256=BxBKc9cn843eoMlmlV7j0tqIG-DRPL6A0n-S6JLyDjg,7057
82
84
  mx_bluesky/common/experiment_plans/oav_grid_detection_plan.py,sha256=Djfqfny7Bs-PlpxJUXLDZv-n3uWnk_99YQjAvlvqm8k,6733
83
85
  mx_bluesky/common/experiment_plans/oav_snapshot_plan.py,sha256=Zvz8j9ZgK6hIYRTkSjYBr1ARLyMRixOsou_wSuR97U4,3647
84
- mx_bluesky/common/experiment_plans/read_hardware.py,sha256=Og7Uz8lAB1_Z6puN6ws_2kwOqCvgQMqfmyZPFZMRneY,2351
85
- mx_bluesky/common/experiment_plans/write_sample_status.py,sha256=pmS4Lsndp90CCIKzD_wssvbzt1qu7rEzfXgxvDwDrQ8,1313
86
86
  mx_bluesky/common/experiment_plans/inner_plans/__init__ .py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
- mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py,sha256=wn2Bi1icVngLQsgHzl6QBGOR5Uw6pZlZSozDlmUv6JM,4786
87
+ mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py,sha256=WjtoyMxpTFSrfFzxxoYKRlRbwRHfEBeEItq82mad0Pw,4807
88
+ mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py,sha256=Og7Uz8lAB1_Z6puN6ws_2kwOqCvgQMqfmyZPFZMRneY,2351
89
+ mx_bluesky/common/experiment_plans/inner_plans/write_sample_status.py,sha256=pmS4Lsndp90CCIKzD_wssvbzt1qu7rEzfXgxvDwDrQ8,1313
88
90
  mx_bluesky/common/external_interaction/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
89
91
  mx_bluesky/common/external_interaction/config_server.py,sha256=EmvLfOkvoJlnKa0sffAKNICkY26YsQQqY9sYHKmOGzw,2441
90
92
  mx_bluesky/common/external_interaction/callbacks/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -105,15 +107,16 @@ mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py,s
105
107
  mx_bluesky/common/external_interaction/ispyb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
108
  mx_bluesky/common/external_interaction/ispyb/data_model.py,sha256=HJZPT_j5EMK7-j-0tdaugiS3kDp44_jzvVoP-xcFCsA,2738
107
109
  mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py,sha256=7j7ybxW1CB4WiuaTf4N2ZeeVbNNy7v5aN1KbbcW74wo,6080
108
- mx_bluesky/common/external_interaction/ispyb/ispyb_store.py,sha256=Q23dZOGN9VfpwN69K4A41merojNhp4VFTEDAe8G9xws,11132
110
+ mx_bluesky/common/external_interaction/ispyb/ispyb_store.py,sha256=PVV8MzpDCaUHNX1LtRhHLVcrmVNZVWwxAw3DxhmjE3Q,11396
109
111
  mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py,sha256=5-8wHmY1KvMuRpXUxN5YBCQP3M-Jk-sTcfDm-CC84Mw,732
110
112
  mx_bluesky/common/external_interaction/nexus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
113
  mx_bluesky/common/external_interaction/nexus/nexus_utils.py,sha256=n97KHJJd_C59SOVJHcJ3RbNkvxkoUrF6fIJx3jXBuI0,5580
112
114
  mx_bluesky/common/external_interaction/nexus/write_nexus.py,sha256=s8xT05_Fn_s64KbPOnR5cm-AooklMKRj2cXxLstl7e0,4067
115
+ mx_bluesky/common/parameters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
113
116
  mx_bluesky/common/parameters/components.py,sha256=LKkFiGWEzU3dPHGG_M9gzNu4XUA-0nc7Q3ceRiWJFTk,8536
114
- mx_bluesky/common/parameters/constants.py,sha256=Aj5vRZWy2xaKQNLku1posPsgo5tLW_wqRMBJht4fBio,4467
115
- mx_bluesky/common/parameters/device_composites.py,sha256=aUBH8RozQb-TqNLWXFpjxETSZckPsugcDVwuJTiu8hg,2238
116
- mx_bluesky/common/parameters/gridscan.py,sha256=XHlXi6zSJoag11hrS4_k44v_NZSIdCS-QBveben2nPw,7034
117
+ mx_bluesky/common/parameters/constants.py,sha256=dEq6rRbifNgX23yIH26ul1KH3_CquMXr7OPPFhuWLpI,4493
118
+ mx_bluesky/common/parameters/device_composites.py,sha256=F_msgzMTzwIYXufkBwRCg47f5-Z4sJlQVbsWnUqjXSw,2253
119
+ mx_bluesky/common/parameters/gridscan.py,sha256=vcSKOBKfAAq1ONTanmzWxm37w48y7WY22Z-xr2ZxqYQ,7064
117
120
  mx_bluesky/common/preprocessors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
118
121
  mx_bluesky/common/preprocessors/preprocessors.py,sha256=BNpSM7S9gxhVbG39rjH14k89sOmKiII0cqApH3pF_H0,4476
119
122
  mx_bluesky/common/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -125,17 +128,17 @@ mx_bluesky/common/utils/log.py,sha256=CepibF7U5GnN-ICl4bmhbEwqRzWsSFyfNtBDJejK0e
125
128
  mx_bluesky/common/utils/tracing.py,sha256=stnBZIvPuKiAm2wVc8lFr3ns7V5C52rUigULi9V-IFs,1171
126
129
  mx_bluesky/common/utils/utils.py,sha256=q2uCaK1E8zLVk1BFmj7qlTnQf3JRKjCjyadIVnL1-4M,1180
127
130
  mx_bluesky/hyperion/__init__.py,sha256=f4E8wInL1Ll4eeFtAiyKmipOBTPlUtKmVK-m_LOQG4M,35
128
- mx_bluesky/hyperion/__main__.py,sha256=2TEoxvKU3JaG74rW3VKCf-DQhl6CRl_eZNQ0u5dW6EA,11406
129
- mx_bluesky/hyperion/baton_handler.py,sha256=AC3Qca5d3KdM5eN2nTqA2HmPkN4ZciOuCxtCKLfK0Uc,3276
131
+ mx_bluesky/hyperion/__main__.py,sha256=zRAkEuHCAcVyQrTHr9myJ37AmW1q9Fez5sd2lxddFSw,11415
132
+ mx_bluesky/hyperion/baton_handler.py,sha256=2xcaDuxNOjuqhFMj9EiD_x3P3K7nt1vj8uA0d1mp-to,4429
130
133
  mx_bluesky/hyperion/device_setup_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
134
  mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py,sha256=iQawC-nIOVSoMMSYl4mleIkVYs-BaKKMTgOWX4efHTg,4723
132
135
  mx_bluesky/hyperion/device_setup_plans/setup_panda.py,sha256=96eFp4acQLOthe1PA-S14uv635uGVP71DpP7qy_uo40,8509
133
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py,sha256=_PnV4PyrcoN7_CBi-HLWWNMKMKarpFUTcNcXsEx3sZo,9076
136
+ mx_bluesky/hyperion/device_setup_plans/setup_zebra.py,sha256=e3ocVsncImQIrfL6d0UoH5fCl8AR0pM_4AIXSxc8dgQ,5749
134
137
  mx_bluesky/hyperion/device_setup_plans/smargon.py,sha256=9znQLGF8Uqif1SZ_H4GyqcnhR3xCI1FIniCaGLRY3zM,758
135
138
  mx_bluesky/hyperion/device_setup_plans/utils.py,sha256=96JlzyikMhWN7LzdiMx8URZInXoGR3OjoxYmCIp9tts,425
136
139
  mx_bluesky/hyperion/experiment_plans/__init__.py,sha256=dJjwLk0EQP-1hKhbs8aRxTF_LxUXgB7kcgDlaP-tMnk,787
137
140
  mx_bluesky/hyperion/experiment_plans/experiment_registry.py,sha256=bGp2c3nKutqHMnDxuqjp6yCF-JKykSzX-IUfxk3oVlM,1701
138
- mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py,sha256=MzoJ0ts8eeHWi6lt95toZRVsEJ0I21zJ9Z6iYwr2Lps,6643
141
+ mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py,sha256=OZq6cYajQEbCXuOFzw2h-YoGju3J0nYzitgFW5mCc9U,5908
139
142
  mx_bluesky/hyperion/experiment_plans/hyperion_grid_detect_then_xray_centre_plan.py,sha256=e4w4226ONSGQF2dnXzxOfcJ9i57CZIJrqQ1YCLlaBNo,2153
140
143
  mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py,sha256=G_r8NIHkvRpC8jGYPYZAtG6uVPTwzlH1P2Akd2ykP4o,6877
141
144
  mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py,sha256=5ZAH17F5T1YyVgA2ML0NEf4ufrD1G0jPRU0_5pINdTg,16195
@@ -143,7 +146,7 @@ mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py,sha256=
143
146
  mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py,sha256=FP_tAhq7Txljbxvvr3eEMoapDtXj8siPyWd9qcYevBg,6247
144
147
  mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py,sha256=AFQtQ-goN7cbMXiYaxd3-PSDKG2llnMr0dKkYdbCIB4,5942
145
148
  mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py,sha256=II-4v2AOyC7QbCqLZFSq1fT1OjWSg8P5MmSQFzQI0D0,6892
146
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py,sha256=EzxvClv7Gc3izpBVOQaBskFqdpIl66vIUyjqNtaM3H4,15913
149
+ mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py,sha256=ymYtfLvB2A4Ux_FV_kIRtY35IFF8OoE4Iv9zSpTpyWI,15925
147
150
  mx_bluesky/hyperion/experiment_plans/set_energy_plan.py,sha256=8FAqN-aJgRwZSiCX-hNdeGmaijt0l8owdShVBwNchfE,2643
148
151
  mx_bluesky/hyperion/external_interaction/__init__.py,sha256=95DwXDmKsx36RgAL-AtLZl2LQoLPKbzeYdlkkP_4Coc,559
149
152
  mx_bluesky/hyperion/external_interaction/agamemnon.py,sha256=y80qaZ43fwUdDBDkRYs7yJH1I8zXVla_7GTnRkXBOnQ,9959
@@ -159,7 +162,7 @@ mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py,sh
159
162
  mx_bluesky/hyperion/parameters/__init__.py,sha256=kf2wfcILBUBpT0tJ8-W39BywQUkn67yxl9IVsfrr1LE,115
160
163
  mx_bluesky/hyperion/parameters/cli.py,sha256=zciAE1-7Ahx0B8-RNNk25hB40xBMrmrR7cK1GbEDgaM,1177
161
164
  mx_bluesky/hyperion/parameters/components.py,sha256=uXxdW6nIE1VZnh4ZXe5O-LOwsx4MbENEWfLGm2ACvsI,313
162
- mx_bluesky/hyperion/parameters/constants.py,sha256=-_dCUu5uqw1iHqZ2FE_HkLeaWYHGPB-poNNiqpnfEms,1665
165
+ mx_bluesky/hyperion/parameters/constants.py,sha256=_-8nlAGAWDBAFRauk2G9rQjE3raSvES6QzdIUKQDKBM,1645
163
166
  mx_bluesky/hyperion/parameters/device_composites.py,sha256=wXr0VH66Qm5xT0WBBy4hmXjONrAxieP3aAFdt0rM6kY,2139
164
167
  mx_bluesky/hyperion/parameters/gridscan.py,sha256=snER6auUYTdj31Qa_sjp7zPIpXMo_lwLq7Ugn-YlG6k,3663
165
168
  mx_bluesky/hyperion/parameters/load_centre_collect.py,sha256=bT4jXBPKeOTfi3U2lECJ-bbKLkmlCz_MMydqdbCE4xI,4361
@@ -167,10 +170,13 @@ mx_bluesky/hyperion/parameters/robot_load.py,sha256=DSOwIosO629WoXbVFokEjmgqKZz3
167
170
  mx_bluesky/hyperion/parameters/rotation.py,sha256=Ws3iic17Btmleatc5PStL_N8iO41kVe2UtZ1I8F2Uz8,7546
168
171
  mx_bluesky/hyperion/resources/panda/panda-gridscan.yaml,sha256=mhLBJTSjHCkM9F6mjtqbhNmmrV8qSctbCUfhb0q7pYo,28085
169
172
  mx_bluesky/hyperion/utils/__init__.py,sha256=f4E8wInL1Ll4eeFtAiyKmipOBTPlUtKmVK-m_LOQG4M,35
170
- mx_bluesky/hyperion/utils/context.py,sha256=TXvARIUZNLcz-KY_-xPkQvK-tMe1sV_cjFDh6IqPgfo,568
171
- mx_bluesky-1.5.1.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
172
- mx_bluesky-1.5.1.dist-info/METADATA,sha256=vM2XcXEYwdurLg9LtfQzf8VBzHRnmrHKKSw1rfH96UE,17392
173
- mx_bluesky-1.5.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
174
- mx_bluesky-1.5.1.dist-info/entry_points.txt,sha256=-hM2jXf6TAwgqnUHaEVx02j7sdB0L_WaeHW_tIRuj6o,600
175
- mx_bluesky-1.5.1.dist-info/top_level.txt,sha256=S4rrzXIUef58ulf_04wn01XGZ3xeJjXs4LPEJ_xoF-I,11
176
- mx_bluesky-1.5.1.dist-info/RECORD,,
173
+ mx_bluesky/hyperion/utils/context.py,sha256=yxMYn3YFET6SanFZ4YWXDmZDdp3WkaXhDc3ySxHYpAE,1033
174
+ mx_bluesky/phase1_zebra/__init__.py,sha256=Edhhn2L9MVXnjJhyD5_yKQVUDo7XW98rvuT7dlzIn58,132
175
+ mx_bluesky/phase1_zebra/device_setup_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
176
+ mx_bluesky/phase1_zebra/device_setup_plans/setup_zebra.py,sha256=zfEnDvh5Rh9cPmg_Q_0EnJOZNIwIGmHeIDiJ9kg9Z4c,4129
177
+ mx_bluesky-1.5.2.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
178
+ mx_bluesky-1.5.2.dist-info/METADATA,sha256=Ao71REUS-SrRGSViHIXTrKwF-wP1MRp5e5eG_H6uAoM,17392
179
+ mx_bluesky-1.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
180
+ mx_bluesky-1.5.2.dist-info/entry_points.txt,sha256=-hM2jXf6TAwgqnUHaEVx02j7sdB0L_WaeHW_tIRuj6o,600
181
+ mx_bluesky-1.5.2.dist-info/top_level.txt,sha256=S4rrzXIUef58ulf_04wn01XGZ3xeJjXs4LPEJ_xoF-I,11
182
+ mx_bluesky-1.5.2.dist-info/RECORD,,