mx-bluesky 1.5.8__py3-none-any.whl → 1.5.9__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 (25) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +33 -10
  3. mx_bluesky/beamlines/i24/jungfrau_commissioning/__init__.py +0 -0
  4. mx_bluesky/common/device_setup_plans/__init__.py +0 -0
  5. mx_bluesky/common/device_setup_plans/manipulate_sample.py +2 -2
  6. mx_bluesky/common/device_setup_plans/robot_load_unload.py +8 -4
  7. mx_bluesky/common/device_setup_plans/setup_zebra_and_shutter.py +245 -0
  8. mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py +9 -21
  9. mx_bluesky/common/experiment_plans/inner_plans/__init__.py +0 -0
  10. mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py +4 -2
  11. mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +4 -3
  12. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +34 -25
  13. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +2 -100
  14. mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +7 -5
  15. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +4 -2
  16. mx_bluesky/hyperion/external_interaction/callbacks/alert_on_container_change.py +14 -5
  17. mx_bluesky/hyperion/external_interaction/callbacks/robot_actions/__init__.py +0 -0
  18. {mx_bluesky-1.5.8.dist-info → mx_bluesky-1.5.9.dist-info}/METADATA +2 -2
  19. {mx_bluesky-1.5.8.dist-info → mx_bluesky-1.5.9.dist-info}/RECORD +24 -20
  20. mx_bluesky/phase1_zebra/device_setup_plans/setup_zebra.py +0 -112
  21. /mx_bluesky/{common/experiment_plans/inner_plans/__init__ .py → beamlines/i04/callbacks/__init__.py} +0 -0
  22. {mx_bluesky-1.5.8.dist-info → mx_bluesky-1.5.9.dist-info}/WHEEL +0 -0
  23. {mx_bluesky-1.5.8.dist-info → mx_bluesky-1.5.9.dist-info}/entry_points.txt +0 -0
  24. {mx_bluesky-1.5.8.dist-info → mx_bluesky-1.5.9.dist-info}/licenses/LICENSE +0 -0
  25. {mx_bluesky-1.5.8.dist-info → mx_bluesky-1.5.9.dist-info}/top_level.txt +0 -0
mx_bluesky/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.5.8'
32
- __version_tuple__ = version_tuple = (1, 5, 8)
31
+ __version__ = version = '1.5.9'
32
+ __version_tuple__ = version_tuple = (1, 5, 9)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -6,7 +6,7 @@ import bluesky.plan_stubs as bps
6
6
  import bluesky.preprocessors as bpp
7
7
  from bluesky.utils import MsgGenerator
8
8
  from dodal.common import inject
9
- from dodal.devices.aperturescatterguard import ApertureScatterguard
9
+ from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureValue
10
10
  from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
11
11
  from dodal.devices.backlight import Backlight
12
12
  from dodal.devices.common_dcm import BaseDCM
@@ -17,6 +17,7 @@ from dodal.devices.fast_grid_scan import (
17
17
  set_fast_grid_scan_params,
18
18
  )
19
19
  from dodal.devices.flux import Flux
20
+ from dodal.devices.i04.transfocator import Transfocator
20
21
  from dodal.devices.mx_phase1.beamstop import Beamstop
21
22
  from dodal.devices.oav.oav_detector import OAV
22
23
  from dodal.devices.oav.pin_image_recognition import PinTipDetection
@@ -33,6 +34,10 @@ from dodal.plans.preprocessors.verify_undulator_gap import (
33
34
  verify_undulator_gap_before_run_decorator,
34
35
  )
35
36
 
37
+ from mx_bluesky.common.device_setup_plans.setup_zebra_and_shutter import (
38
+ setup_zebra_for_gridscan,
39
+ tidy_up_zebra_after_gridscan,
40
+ )
36
41
  from mx_bluesky.common.experiment_plans.common_flyscan_xray_centre_plan import (
37
42
  BeamlineSpecificFGSFeatures,
38
43
  construct_beamline_specific_FGS_features,
@@ -67,10 +72,22 @@ from mx_bluesky.common.preprocessors.preprocessors import (
67
72
  transmission_and_xbpm_feedback_for_collection_decorator,
68
73
  )
69
74
  from mx_bluesky.common.utils.log import LOGGER
70
- from mx_bluesky.phase1_zebra.device_setup_plans.setup_zebra import (
71
- setup_zebra_for_gridscan,
72
- tidy_up_zebra_after_gridscan,
73
- )
75
+
76
+ DEFAULT_BEAMSIZE_MICRONS = 20
77
+
78
+
79
+ def _change_beamsize(
80
+ transfocator: Transfocator, beamsize: float, parameters: GridCommon
81
+ ):
82
+ """i04 always uses the large aperture and changes beamsize with the transfocator.
83
+
84
+ An aperture is needed to reduce scatter but the transfocator is best used for beamsize
85
+ changes as it gives more flux compared to a bigger beam with a small aperture.
86
+ """
87
+ parameters.selected_aperture = ApertureValue.LARGE
88
+ yield from bps.abs_set(
89
+ transfocator, beamsize, group=PlanGroupCheckpointConstants.GRID_READY_FOR_DC
90
+ )
74
91
 
75
92
 
76
93
  # See https://github.com/DiamondLightSource/blueapi/issues/506 for using device composites
@@ -96,6 +113,7 @@ def i04_grid_detect_then_xray_centre(
96
113
  zocalo: ZocaloResults = inject("zocalo"),
97
114
  smargon: Smargon = inject("smargon"),
98
115
  detector_motion: DetectorMotion = inject("detector_motion"),
116
+ transfocator: Transfocator = inject("transfocator"),
99
117
  oav_config: str = OavConstants.OAV_CONFIG_JSON,
100
118
  udc: bool = False,
101
119
  ) -> MsgGenerator:
@@ -108,7 +126,7 @@ def i04_grid_detect_then_xray_centre(
108
126
 
109
127
 
110
128
  i04's implementation of this plan is very similar to Hyperion. However, since i04
111
- isn't running in a continious Bluesky UDC loop, we take additional steps in beamline
129
+ isn't running in a continuous Bluesky UDC loop, we take additional steps in beamline
112
130
  tidy-up.
113
131
  """
114
132
 
@@ -134,8 +152,9 @@ def i04_grid_detect_then_xray_centre(
134
152
  robot,
135
153
  sample_shutter,
136
154
  )
155
+ initial_beamsize = yield from bps.rd(transfocator.beamsize_set_microns)
137
156
 
138
- def tidy_beamline_if_not_udc():
157
+ def tidy_beamline():
139
158
  if not udc:
140
159
  yield from get_ready_for_oav_and_close_shutter(
141
160
  composite.smargon,
@@ -143,8 +162,9 @@ def i04_grid_detect_then_xray_centre(
143
162
  composite.aperture_scatterguard,
144
163
  composite.detector_motion,
145
164
  )
165
+ yield from bps.mv(transfocator, initial_beamsize)
146
166
 
147
- @bpp.finalize_decorator(tidy_beamline_if_not_udc)
167
+ @bpp.finalize_decorator(tidy_beamline)
148
168
  def _inner_grid_detect_then_xrc():
149
169
  # These callbacks let us talk to ISPyB and Nexgen. They aren't included in the common plan because
150
170
  # Hyperion handles its callbacks differently to BlueAPI-managed plans, see
@@ -167,6 +187,7 @@ def i04_grid_detect_then_xray_centre(
167
187
 
168
188
  yield from grid_detect_then_xray_centre_with_callbacks()
169
189
 
190
+ yield from _change_beamsize(transfocator, DEFAULT_BEAMSIZE_MICRONS, parameters)
170
191
  yield from _inner_grid_detect_then_xrc()
171
192
 
172
193
 
@@ -178,7 +199,7 @@ def get_ready_for_oav_and_close_shutter(
178
199
  ):
179
200
  yield from bps.wait(PlanGroupCheckpointConstants.GRID_READY_FOR_DC)
180
201
  group = "get_ready_for_oav_and_close_shutter"
181
- LOGGER.info("Non-udc tidy: Seting up beamline for OAV")
202
+ LOGGER.info("Non-udc tidy: Setting up beamline for OAV")
182
203
  yield from setup_beamline_for_OAV(
183
204
  smargon, backlight, aperture_scatterguard, group=group
184
205
  )
@@ -247,7 +268,9 @@ def construct_i04_specific_features(
247
268
  )
248
269
  fgs_motors = xrc_composite.zebra_fast_grid_scan
249
270
  return construct_beamline_specific_FGS_features(
250
- setup_zebra_for_gridscan,
271
+ partial(
272
+ setup_zebra_for_gridscan,
273
+ ),
251
274
  tidy_plan,
252
275
  set_flyscan_params_plan,
253
276
  fgs_motors,
File without changes
@@ -9,8 +9,8 @@ from dodal.devices.backlight import Backlight, InOut
9
9
  from dodal.devices.detector.detector_motion import DetectorMotion
10
10
  from dodal.devices.smargon import CombinedMove, Smargon
11
11
 
12
+ from mx_bluesky.common.parameters.constants import PlanGroupCheckpointConstants
12
13
  from mx_bluesky.common.utils.log import LOGGER
13
- from mx_bluesky.hyperion.parameters.constants import CONST
14
14
 
15
15
  LOWER_DETECTOR_SHUTTER_AFTER_SCAN = True
16
16
 
@@ -48,7 +48,7 @@ def move_aperture_if_required(
48
48
 
49
49
  else:
50
50
  LOGGER.info(f"Setting aperture position to {aperture_value}")
51
- yield from bps.wait(CONST.WAIT.PREPARE_APERTURE)
51
+ yield from bps.wait(PlanGroupCheckpointConstants.PREPARE_APERTURE)
52
52
  yield from bps.abs_set(
53
53
  aperture_scatterguard.selected_aperture,
54
54
  aperture_value,
@@ -9,8 +9,12 @@ from dodal.devices.robot import BartRobot
9
9
  from dodal.devices.smargon import CombinedMove, Smargon, StubPosition
10
10
  from dodal.plan_stubs.motor_utils import MoveTooLarge, home_and_reset_wrapper
11
11
 
12
+ from mx_bluesky.common.parameters.constants import (
13
+ DocDescriptorNames,
14
+ HardwareConstants,
15
+ PlanNameConstants,
16
+ )
12
17
  from mx_bluesky.common.utils.log import LOGGER
13
- from mx_bluesky.hyperion.parameters.constants import CONST
14
18
 
15
19
  SLEEP_PER_CHECK = 0.1
16
20
 
@@ -60,7 +64,7 @@ def do_plan_while_lower_gonio_at_home(plan: MsgGenerator, lower_gonio: XYZStage)
60
64
  plan,
61
65
  lower_gonio,
62
66
  BartRobot.LOAD_TOLERANCE_MM,
63
- CONST.HARDWARE.CRYOJET_MARGIN_MM,
67
+ HardwareConstants.CRYOJET_MARGIN_MM,
64
68
  "lower_gonio",
65
69
  wait_for_all=False,
66
70
  ),
@@ -100,7 +104,7 @@ def robot_unload(
100
104
 
101
105
  @bpp.run_decorator(
102
106
  md={
103
- "subplan_name": CONST.PLAN.ROBOT_UNLOAD,
107
+ "subplan_name": PlanNameConstants.ROBOT_UNLOAD,
104
108
  "metadata": {"visit": visit, "sample_id": sample_id},
105
109
  "activate_callbacks": [
106
110
  "RobotLoadISPyBCallback",
@@ -108,7 +112,7 @@ def robot_unload(
108
112
  },
109
113
  )
110
114
  def do_robot_unload_and_send_to_ispyb():
111
- yield from bps.create(name=CONST.DESCRIPTORS.ROBOT_UPDATE)
115
+ yield from bps.create(name=DocDescriptorNames.ROBOT_UPDATE)
112
116
  yield from bps.read(robot)
113
117
  yield from bps.save()
114
118
 
@@ -0,0 +1,245 @@
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
+ ArmDemand,
7
+ EncEnum,
8
+ I03Axes,
9
+ RotationDirection,
10
+ Zebra,
11
+ )
12
+ from dodal.devices.zebra.zebra_controlled_shutter import (
13
+ ZebraShutter,
14
+ ZebraShutterControl,
15
+ )
16
+
17
+ from mx_bluesky.common.parameters.constants import ZEBRA_STATUS_TIMEOUT
18
+ from mx_bluesky.common.utils.log import LOGGER
19
+
20
+ """Plans in this file will work as intended if the zebra has the following configuration:
21
+ - A fast shutter is connected through TTL inputs from the Zebra.
22
+ - When the zebra shutter is set to auto mode, the IOC sets the Zebra's SOFT_IN1 signal high.
23
+ - When the zebra shutter is set to manual mode, the IOC sets the Zebra's SOFT_IN1 signal low.
24
+ """
25
+
26
+
27
+ @runtime_checkable
28
+ class GridscanSetupDevices(Protocol):
29
+ zebra: Zebra
30
+ sample_shutter: ZebraShutter
31
+
32
+
33
+ def setup_zebra_for_gridscan(
34
+ composite: GridscanSetupDevices, # XRC gridscan's generic trigger setup expects a composite rather than individual devices
35
+ group="setup_zebra_for_gridscan",
36
+ wait=True,
37
+ ttl_input_for_detector_to_use: None | int = None,
38
+ ) -> MsgGenerator:
39
+ """
40
+ Configure the zebra for an MX XRC gridscan by allowing the zebra to trigger the fast shutter and detector via signals
41
+ sent from the motion controller.
42
+
43
+ Args:
44
+ composite: Composite device containing a zebra and zebra shutter
45
+ group: Bluesky group to use when waiting on completion
46
+ wait: If true, block until completion
47
+ ttl_input_for_detector_to_use: If the zebra isn't using the TTL_DETECTOR zebra input, manually
48
+ specify which TTL input is being used for the desired detector
49
+
50
+ This plan assumes that the motion controller, as part of its gridscan PLC, will send triggers as required to the zebra's
51
+ IN4_TTL and IN3_TTL to control the fast_shutter and detector respectively
52
+
53
+ """
54
+ zebra = composite.zebra
55
+ ttl_detector = ttl_input_for_detector_to_use or zebra.mapping.outputs.TTL_DETECTOR
56
+ # Set shutter to automatic and to trigger via motion controller GPIO signal (IN4_TTL)
57
+ yield from configure_zebra_and_shutter_for_auto_shutter(
58
+ zebra, composite.sample_shutter, zebra.mapping.sources.IN4_TTL, group=group
59
+ )
60
+
61
+ yield from bps.abs_set(
62
+ zebra.output.out_pvs[ttl_detector],
63
+ zebra.mapping.sources.IN3_TTL,
64
+ group=group,
65
+ )
66
+
67
+ if wait:
68
+ yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
69
+
70
+
71
+ def set_shutter_auto_input(zebra: Zebra, input: int, group="set_shutter_trigger"):
72
+ """Set the signal that controls the shutter. We use the second input to the
73
+ Zebra's AND_GATE_FOR_AUTO_SHUTTER for this input. ZebraShutter control mode must be in auto for this input to take control
74
+
75
+ For more details see the ZebraShutter device."""
76
+ auto_gate = zebra.mapping.AND_GATE_FOR_AUTO_SHUTTER
77
+ auto_shutter_control = zebra.logic_gates.and_gates[auto_gate]
78
+ yield from bps.abs_set(auto_shutter_control.sources[2], input, group)
79
+
80
+
81
+ def configure_zebra_and_shutter_for_auto_shutter(
82
+ zebra: Zebra, zebra_shutter: ZebraShutter, input: int, group="use_automatic_shutter"
83
+ ):
84
+ """Set the shutter to auto mode, and configure the zebra to trigger the shutter on
85
+ an input source. For the input, use one of the source constants in zebra.py
86
+
87
+ When the shutter is in auto/manual, logic in EPICS sets the Zebra's
88
+ SOFT_IN1 to low/high respectively. The Zebra's AND_GATE_FOR_AUTO_SHUTTER should be used to control the shutter while in auto mode.
89
+ To do this, we need (AND_GATE_FOR_AUTO_SHUTTER = SOFT_IN1 AND input), where input is the zebra signal we want to control the shutter when in auto mode.
90
+ """
91
+
92
+ # Set shutter to auto mode
93
+ yield from bps.abs_set(
94
+ zebra_shutter.control_mode, ZebraShutterControl.AUTO, group=group
95
+ )
96
+
97
+ auto_gate = zebra.mapping.AND_GATE_FOR_AUTO_SHUTTER
98
+
99
+ # Set first input of AND_GATE_FOR_AUTO_SHUTTER to SOFT_IN1, which is high when shutter is in auto mode
100
+ # Note the Zebra should ALWAYS be setup this way. See https://github.com/DiamondLightSource/mx-bluesky/issues/551
101
+ yield from bps.abs_set(
102
+ zebra.logic_gates.and_gates[auto_gate].sources[1],
103
+ zebra.mapping.sources.SOFT_IN1,
104
+ group=group,
105
+ )
106
+
107
+ # Set the second input of AND_GATE_FOR_AUTO_SHUTTER to the requested zebra input source
108
+ yield from set_shutter_auto_input(zebra, input, group=group)
109
+
110
+
111
+ def tidy_up_zebra_after_gridscan(
112
+ zebra: Zebra,
113
+ zebra_shutter: ZebraShutter,
114
+ group="tidy_up_zebra_after_gridscan",
115
+ wait=True,
116
+ ttl_input_for_detector_to_use: int | None = None,
117
+ ) -> MsgGenerator:
118
+ """
119
+ Set the zebra back to a state which is expected by GDA.
120
+
121
+ Args:
122
+ zebra: Zebra device.
123
+ zebra_shutter: Zebra shutter device.
124
+ group: Bluesky group to use when waiting on completion.
125
+ wait: If true, block until completion.
126
+ ttl_input_for_detector_to_use: If the zebra isn't using the TTL_DETECTOR zebra input, manually
127
+ specify which TTL input is being used for the desired detector.
128
+ """
129
+
130
+ LOGGER.info("Tidying up Zebra")
131
+
132
+ ttl_detector = ttl_input_for_detector_to_use or zebra.mapping.outputs.TTL_DETECTOR
133
+
134
+ yield from bps.abs_set(
135
+ zebra.output.out_pvs[ttl_detector],
136
+ zebra.mapping.sources.PC_PULSE,
137
+ group=group,
138
+ )
139
+ yield from bps.abs_set(
140
+ zebra_shutter.control_mode, ZebraShutterControl.MANUAL, group=group
141
+ )
142
+ yield from set_shutter_auto_input(zebra, zebra.mapping.sources.PC_GATE, group=group)
143
+
144
+ if wait:
145
+ yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
146
+
147
+
148
+ def setup_zebra_for_rotation(
149
+ zebra: Zebra,
150
+ zebra_shutter: ZebraShutter,
151
+ axis: EncEnum = I03Axes.OMEGA,
152
+ start_angle: float = 0,
153
+ scan_width: float = 360,
154
+ shutter_opening_deg: float = 2.5,
155
+ shutter_opening_s: float = 0.04,
156
+ direction: RotationDirection = RotationDirection.POSITIVE,
157
+ group: str = "setup_zebra_for_rotation",
158
+ wait: bool = True,
159
+ ttl_input_for_detector_to_use: int | None = None,
160
+ ):
161
+ """Set up the Zebra to collect a rotation dataset. Any plan using this is
162
+ responsible for setting the smargon velocity appropriately so that the desired
163
+ image width is achieved with the exposure time given here.
164
+
165
+ Parameters:
166
+ zebra: The zebra device to use
167
+ axis: Encoder enum representing which axis to use for position
168
+ compare. Currently always omega.
169
+ start_angle: Position at which the scan should begin, in degrees.
170
+ scan_width: Total angle through which to collect, in degrees.
171
+ shutter_opening_deg:How many degrees of rotation it takes for the fast shutter
172
+ to open. Increases the gate width.
173
+ shutter_opening_s: How many seconds it takes for the fast shutter to open. The
174
+ detector pulse is delayed after the shutter signal by this
175
+ amount.
176
+ direction: RotationDirection enum for positive or negative.
177
+ Defaults to Positive.
178
+ group: A name for the group of statuses generated
179
+ wait: Block until all the settings have completed
180
+ ttl_input_for_detector_to_use: If the zebra isn't using the TTL_DETECTOR zebra input,
181
+ manually specify which TTL input is being used for the desired detector
182
+ """
183
+
184
+ ttl_detector = ttl_input_for_detector_to_use or zebra.mapping.outputs.TTL_DETECTOR
185
+
186
+ if not isinstance(direction, RotationDirection):
187
+ raise ValueError(
188
+ "Disallowed rotation direction provided to Zebra setup plan. "
189
+ "Use RotationDirection.POSITIVE or RotationDirection.NEGATIVE."
190
+ )
191
+ yield from bps.abs_set(zebra.pc.dir, direction.value, group=group)
192
+ LOGGER.info("ZEBRA SETUP: START")
193
+ # Set gate start, adjust for shutter opening time if necessary
194
+ LOGGER.info(f"ZEBRA SETUP: degrees to adjust for shutter = {shutter_opening_deg}")
195
+ LOGGER.info(f"ZEBRA SETUP: start angle start: {start_angle}")
196
+ LOGGER.info(f"ZEBRA SETUP: start angle adjusted, gate start set to: {start_angle}")
197
+ yield from bps.abs_set(zebra.pc.gate_start, start_angle, group=group)
198
+ # set gate width to total width
199
+ yield from bps.abs_set(
200
+ zebra.pc.gate_width, scan_width + shutter_opening_deg, group=group
201
+ )
202
+ LOGGER.info(
203
+ f"Pulse start set to shutter open time, set to: {abs(shutter_opening_s)}"
204
+ )
205
+ yield from bps.abs_set(zebra.pc.pulse_start, abs(shutter_opening_s), group=group)
206
+ # Set gate position to be angle of interest
207
+ yield from bps.abs_set(zebra.pc.gate_trigger, axis.value, group=group)
208
+ # Set shutter to automatic and to trigger via PC_GATE
209
+ yield from configure_zebra_and_shutter_for_auto_shutter(
210
+ zebra, zebra_shutter, zebra.mapping.sources.PC_GATE, group=group
211
+ )
212
+ # Trigger the detector with a pulse
213
+ yield from bps.abs_set(
214
+ zebra.output.out_pvs[ttl_detector],
215
+ zebra.mapping.sources.PC_PULSE,
216
+ group=group,
217
+ )
218
+
219
+ LOGGER.info(f"ZEBRA SETUP: END - {'' if wait else 'not'} waiting for completion")
220
+ if wait:
221
+ yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
222
+
223
+
224
+ def tidy_up_zebra_after_rotation_scan(
225
+ zebra: Zebra,
226
+ zebra_shutter: ZebraShutter,
227
+ group="tidy_up_zebra_after_rotation",
228
+ wait=True,
229
+ ):
230
+ """
231
+ Set the zebra back to a state which is expected by GDA.
232
+
233
+ Args:
234
+ zebra: Zebra device.
235
+ zebra_shutter: Zebra shutter device.
236
+ group: Bluesky group to use when waiting on completion.
237
+ wait: If true, block until completion.
238
+ """
239
+
240
+ yield from bps.abs_set(zebra.pc.arm, ArmDemand.DISARM, group=group)
241
+ yield from bps.abs_set(
242
+ zebra_shutter.control_mode, ZebraShutterControl.MANUAL, group=group
243
+ )
244
+ if wait:
245
+ yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
@@ -8,11 +8,12 @@ import bluesky.plan_stubs as bps
8
8
  import bluesky.preprocessors as bpp
9
9
  import numpy as np
10
10
  from bluesky.protocols import Readable
11
- from bluesky.utils import MsgGenerator
11
+ from bluesky.utils import FailedStatus, MsgGenerator
12
12
  from dodal.common.beamlines.commissioning_mode import read_commissioning_mode
13
13
  from dodal.devices.fast_grid_scan import (
14
14
  FastGridScanCommon,
15
15
  FastGridScanThreeD,
16
+ GridScanInvalidException,
16
17
  )
17
18
  from dodal.devices.zocalo import ZocaloResults
18
19
  from dodal.devices.zocalo.zocalo_results import (
@@ -270,10 +271,14 @@ def run_gridscan(
270
271
  yield from beamline_specific.read_pre_flyscan_plan()
271
272
 
272
273
  LOGGER.info("Setting fgs params")
273
- yield from beamline_specific.set_flyscan_params_plan()
274
274
 
275
- LOGGER.info("Waiting for gridscan validity check")
276
- yield from wait_for_gridscan_valid(beamline_specific.fgs_motors)
275
+ try:
276
+ yield from beamline_specific.set_flyscan_params_plan()
277
+ except FailedStatus as e:
278
+ if isinstance(e.__cause__, GridScanInvalidException):
279
+ raise SampleException(
280
+ "Scan invalid - gridscan not valid for detected pin position"
281
+ ) from e
277
282
 
278
283
  LOGGER.info("Waiting for arming to finish")
279
284
  yield from bps.wait(PlanGroupCheckpointConstants.GRID_READY_FOR_DC)
@@ -293,23 +298,6 @@ def run_gridscan(
293
298
  yield from bps.abs_set(beamline_specific.fgs_motors.z_steps, 0, wait=False)
294
299
 
295
300
 
296
- def wait_for_gridscan_valid(fgs_motors: FastGridScanCommon, timeout=0.5):
297
- LOGGER.info("Waiting for valid fgs_params")
298
- SLEEP_PER_CHECK = 0.1
299
- times_to_check = int(timeout / SLEEP_PER_CHECK)
300
- for _ in range(times_to_check):
301
- scan_invalid = yield from bps.rd(fgs_motors.scan_invalid)
302
- pos_counter = yield from bps.rd(fgs_motors.position_counter)
303
- LOGGER.debug(
304
- f"Scan invalid: {scan_invalid} and position counter: {pos_counter}"
305
- )
306
- if not scan_invalid and pos_counter == 0:
307
- LOGGER.info("Gridscan scan valid and position counter reset")
308
- return
309
- yield from bps.sleep(SLEEP_PER_CHECK)
310
- raise SampleException("Scan invalid - pin too long/short/bent and out of range")
311
-
312
-
313
301
  def _xrc_result_in_boxes_to_result_in_mm(
314
302
  xrc_result: XrcResult, parameters: SpecifiedThreeDGridScan
315
303
  ) -> XRayCentreResult:
@@ -94,8 +94,10 @@ def kickoff_and_complete_gridscan(
94
94
  md={
95
95
  "subplan_name": plan_name,
96
96
  "omega_to_scan_spec": {
97
- GridscanPlane.OMEGA_XY: scan_points[0],
98
- GridscanPlane.OMEGA_XZ: scan_points[1],
97
+ # These have to be cast to strings due to a bug in orsjon. See
98
+ # https://github.com/ijl/orjson/issues/414
99
+ str(GridscanPlane.OMEGA_XY): scan_points[0],
100
+ str(GridscanPlane.OMEGA_XZ): scan_points[1],
99
101
  },
100
102
  }
101
103
  )
@@ -50,9 +50,10 @@ def populate_remaining_data_collection_info(
50
50
  data_collection_info.xbeam = beam_position[0]
51
51
  data_collection_info.ybeam = beam_position[1]
52
52
  data_collection_info.start_time = get_current_time_string()
53
- # temporary file template until nxs filewriting is integrated and we can use
54
- # that file name
55
- data_collection_info.file_template = f"{params.detector_params.prefix}_{data_collection_info.data_collection_number}_master.h5"
53
+ if data_collection_info.data_collection_number is not None:
54
+ # Do not write the file template if we don't have sufficient information - for gridscans we may not
55
+ # know the data collection number until later
56
+ data_collection_info.file_template = f"{params.detector_params.prefix}_{data_collection_info.data_collection_number}_master.h5"
56
57
  return data_collection_info
57
58
 
58
59
 
@@ -105,6 +105,7 @@ class GridscanISPyBCallback(BaseISPyBCallback):
105
105
  self._start_of_fgs_uid: str | None = None
106
106
  self._processing_start_time: float | None = None
107
107
  self._grid_plane_to_id_map: dict[GridscanPlane, int] = {}
108
+ self._grid_plane_to_width_map: dict[GridscanPlane, int] = {}
108
109
  self.data_collection_group_info: DataCollectionGroupInfo | None
109
110
 
110
111
  def activity_gated_start(self, doc: RunStart):
@@ -131,9 +132,7 @@ class GridscanISPyBCallback(BaseISPyBCallback):
131
132
  data_collection_info=populate_remaining_data_collection_info(
132
133
  "MX-Bluesky: Xray centring 1 -",
133
134
  None,
134
- DataCollectionInfo(
135
- data_collection_number=self.params.detector_params.run_number,
136
- ),
135
+ DataCollectionInfo(),
137
136
  self.params,
138
137
  ),
139
138
  ),
@@ -141,11 +140,7 @@ class GridscanISPyBCallback(BaseISPyBCallback):
141
140
  data_collection_info=populate_remaining_data_collection_info(
142
141
  "MX-Bluesky: Xray centring 2 -",
143
142
  None,
144
- DataCollectionInfo(
145
- data_collection_number=(
146
- self.params.detector_params.run_number + 1
147
- ),
148
- ),
143
+ DataCollectionInfo(),
149
144
  self.params,
150
145
  )
151
146
  ),
@@ -192,6 +187,15 @@ class GridscanISPyBCallback(BaseISPyBCallback):
192
187
  assert self.params, "ISPyB handler didn't receive parameters!"
193
188
  assert self.data_collection_group_info, "No data collection group"
194
189
  data = doc["data"]
190
+ omega = doc["data"]["smargon-omega"]
191
+ grid_plane = _smargon_omega_to_xyxz_plane(omega)
192
+ ISPYB_ZOCALO_CALLBACK_LOGGER.info(
193
+ f"Generating dc info for gridplane {grid_plane}, omega {omega}"
194
+ )
195
+ data_collection_number = self.data_collection_number_from_gridplane(grid_plane)
196
+ file_template = (
197
+ f"{self.params.detector_params.prefix}_{data_collection_number}_master.h5"
198
+ )
195
199
  data_collection_info = DataCollectionInfo(
196
200
  xtal_snapshot1=data.get("oav-grid_snapshot-last_path_full_overlay"),
197
201
  xtal_snapshot2=data.get("oav-grid_snapshot-last_path_outer"),
@@ -200,6 +204,8 @@ class GridscanISPyBCallback(BaseISPyBCallback):
200
204
  data["oav-grid_snapshot-num_boxes_x"]
201
205
  * data["oav-grid_snapshot-num_boxes_y"]
202
206
  ),
207
+ data_collection_number=data_collection_number,
208
+ file_template=file_template,
203
209
  )
204
210
  microns_per_pixel_x = data["oav-microns_per_pixel_x"]
205
211
  microns_per_pixel_y = data["oav-microns_per_pixel_y"]
@@ -219,21 +225,22 @@ class GridscanISPyBCallback(BaseISPyBCallback):
219
225
  data_collection_grid_info
220
226
  )
221
227
 
222
- if self.data_collection_group_info.comments:
223
- self.data_collection_group_info.comments += (
224
- f"by {data_collection_grid_info.steps_y}."
225
- )
226
- else:
227
- self.data_collection_group_info.comments = (
228
- f"Diffraction grid scan of "
229
- f"{data_collection_grid_info.steps_x} "
230
- f"by {data_collection_grid_info.steps_y} "
231
- )
232
-
228
+ # Snapshots may be triggered in a different order to gridscans, so save
229
+ # the mapping to the data collection id in order to trigger Zocalo correctly.
233
230
  data_collection_id = self.ispyb_ids.data_collection_ids[
234
- self._oav_snapshot_event_idx
231
+ 0 if grid_plane == GridscanPlane.OMEGA_XY else 1
235
232
  ]
236
- self._populate_axis_info(data_collection_info, doc["data"]["smargon-omega"])
233
+ self._grid_plane_to_id_map[grid_plane] = data_collection_id
234
+ self._grid_plane_to_width_map[grid_plane] = data_collection_grid_info.steps_y
235
+
236
+ y_steps = self._grid_plane_to_width_map.get(GridscanPlane.OMEGA_XY, "_")
237
+ z_steps = self._grid_plane_to_width_map.get(GridscanPlane.OMEGA_XZ, "_")
238
+ self.data_collection_group_info.comments = (
239
+ f"Diffraction grid scan of {data_collection_grid_info.steps_x} by "
240
+ f"{y_steps} by {z_steps}."
241
+ )
242
+
243
+ self._populate_axis_info(data_collection_info, omega)
237
244
 
238
245
  scan_data_info = ScanDataInfo(
239
246
  data_collection_info=data_collection_info,
@@ -243,10 +250,6 @@ class GridscanISPyBCallback(BaseISPyBCallback):
243
250
  ISPYB_ZOCALO_CALLBACK_LOGGER.info(
244
251
  "Updating ispyb data collection after oav snapshot."
245
252
  )
246
- grid_plane = _smargon_omega_to_xyxz_plane(doc["data"]["smargon-omega"])
247
- # Snapshots may be triggered in a different order to gridscans, so save
248
- # the mapping to the data collection id in order to trigger Zocalo correctly.
249
- self._grid_plane_to_id_map[grid_plane] = data_collection_id
250
253
 
251
254
  self._oav_snapshot_event_idx += 1
252
255
  return [scan_data_info]
@@ -315,6 +318,7 @@ class GridscanISPyBCallback(BaseISPyBCallback):
315
318
  )
316
319
  self.data_collection_group_info = None
317
320
  self._grid_plane_to_id_map.clear()
321
+ self._grid_plane_to_width_map.clear()
318
322
  return super().activity_gated_stop(doc)
319
323
  return self.tag_doc(doc)
320
324
 
@@ -325,6 +329,11 @@ class GridscanISPyBCallback(BaseISPyBCallback):
325
329
  doc["grid_plane_to_id_map"] = self._grid_plane_to_id_map
326
330
  return doc # type: ignore
327
331
 
332
+ def data_collection_number_from_gridplane(self, plane) -> int:
333
+ assert self.params
334
+ base_number = self.params.detector_params.run_number
335
+ return base_number if plane == GridscanPlane.OMEGA_XY else base_number + 1
336
+
328
337
 
329
338
  def generate_start_info_from_omega_map() -> ZocaloInfoGenerator:
330
339
  """
@@ -1,120 +1,22 @@
1
1
  import bluesky.plan_stubs as bps
2
2
  from dodal.devices.zebra.zebra import (
3
3
  ArmDemand,
4
- EncEnum,
5
- I03Axes,
6
- RotationDirection,
7
4
  Zebra,
8
5
  )
9
6
  from dodal.devices.zebra.zebra_controlled_shutter import (
10
7
  ZebraShutter,
11
- ZebraShutterControl,
12
8
  )
13
9
 
14
- from mx_bluesky.common.parameters.constants import ZEBRA_STATUS_TIMEOUT
15
- from mx_bluesky.common.utils.log import LOGGER
16
- from mx_bluesky.phase1_zebra.device_setup_plans.setup_zebra import (
10
+ from mx_bluesky.common.device_setup_plans.setup_zebra_and_shutter import (
17
11
  configure_zebra_and_shutter_for_auto_shutter,
18
12
  )
13
+ from mx_bluesky.common.parameters.constants import ZEBRA_STATUS_TIMEOUT
19
14
 
20
15
 
21
16
  def arm_zebra(zebra: Zebra):
22
17
  yield from bps.abs_set(zebra.pc.arm, ArmDemand.ARM, wait=True)
23
18
 
24
19
 
25
- def tidy_up_zebra_after_rotation_scan(
26
- zebra: Zebra,
27
- zebra_shutter: ZebraShutter,
28
- group="tidy_up_zebra_after_rotation",
29
- wait=True,
30
- ):
31
- yield from bps.abs_set(zebra.pc.arm, ArmDemand.DISARM, group=group)
32
- yield from bps.abs_set(
33
- zebra_shutter.control_mode, ZebraShutterControl.MANUAL, group=group
34
- )
35
- if wait:
36
- yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
37
-
38
-
39
- def setup_zebra_for_rotation(
40
- zebra: Zebra,
41
- zebra_shutter: ZebraShutter,
42
- axis: EncEnum = I03Axes.OMEGA,
43
- start_angle: float = 0,
44
- scan_width: float = 360,
45
- shutter_opening_deg: float = 2.5,
46
- shutter_opening_s: float = 0.04,
47
- direction: RotationDirection = RotationDirection.POSITIVE,
48
- group: str = "setup_zebra_for_rotation",
49
- wait: bool = True,
50
- ):
51
- """Set up the Zebra to collect a rotation dataset. Any plan using this is
52
- responsible for setting the smargon velocity appropriately so that the desired
53
- image width is achieved with the exposure time given here.
54
-
55
- Parameters:
56
- zebra: The zebra device to use
57
- axis: I03 axes enum representing which axis to use for position
58
- compare. Currently always omega.
59
- start_angle: Position at which the scan should begin, in degrees.
60
- scan_width: Total angle through which to collect, in degrees.
61
- shutter_opening_deg:How many degrees of rotation it takes for the fast shutter
62
- to open. Increases the gate width.
63
- shutter_opening_s: How many seconds it takes for the fast shutter to open. The
64
- detector pulse is delayed after the shutter signal by this
65
- amount.
66
- direction: RotationDirection enum for positive or negative.
67
- Defaults to Positive.
68
- group: A name for the group of statuses generated
69
- wait: Block until all the settings have completed
70
- """
71
-
72
- if not isinstance(direction, RotationDirection):
73
- raise ValueError(
74
- "Disallowed rotation direction provided to Zebra setup plan. "
75
- "Use RotationDirection.POSITIVE or RotationDirection.NEGATIVE."
76
- )
77
- yield from bps.abs_set(zebra.pc.dir, direction.value, group=group)
78
- LOGGER.info("ZEBRA SETUP: START")
79
- # Set gate start, adjust for shutter opening time if necessary
80
- LOGGER.info(f"ZEBRA SETUP: degrees to adjust for shutter = {shutter_opening_deg}")
81
- LOGGER.info(f"ZEBRA SETUP: start angle start: {start_angle}")
82
- LOGGER.info(f"ZEBRA SETUP: start angle adjusted, gate start set to: {start_angle}")
83
- yield from bps.abs_set(zebra.pc.gate_start, start_angle, group=group)
84
- # set gate width to total width
85
- yield from bps.abs_set(
86
- zebra.pc.gate_width, scan_width + shutter_opening_deg, group=group
87
- )
88
- LOGGER.info(
89
- f"Pulse start set to shutter open time, set to: {abs(shutter_opening_s)}"
90
- )
91
- yield from bps.abs_set(zebra.pc.pulse_start, abs(shutter_opening_s), group=group)
92
- # Set gate position to be angle of interest
93
- yield from bps.abs_set(zebra.pc.gate_trigger, axis.value, group=group)
94
- # Set shutter to automatic and to trigger via PC_GATE
95
- yield from configure_zebra_and_shutter_for_auto_shutter(
96
- zebra, zebra_shutter, zebra.mapping.sources.PC_GATE, group=group
97
- )
98
- # Trigger the detector with a pulse
99
- yield from bps.abs_set(
100
- zebra.output.out_pvs[zebra.mapping.outputs.TTL_DETECTOR],
101
- zebra.mapping.sources.PC_PULSE,
102
- group=group,
103
- )
104
- # Don't use the fluorescence detector
105
- yield from bps.abs_set(
106
- zebra.output.out_pvs[zebra.mapping.outputs.TTL_XSPRESS3],
107
- zebra.mapping.sources.DISCONNECT,
108
- group=group,
109
- )
110
- yield from bps.abs_set(
111
- zebra.output.pulse_1.input, zebra.mapping.sources.DISCONNECT, group=group
112
- )
113
- LOGGER.info(f"ZEBRA SETUP: END - {'' if wait else 'not'} waiting for completion")
114
- if wait:
115
- yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
116
-
117
-
118
20
  def setup_zebra_for_panda_flyscan(
119
21
  zebra: Zebra,
120
22
  zebra_shutter: ZebraShutter,
@@ -10,6 +10,10 @@ from dodal.devices.fast_grid_scan import (
10
10
  set_fast_grid_scan_params,
11
11
  )
12
12
 
13
+ from mx_bluesky.common.device_setup_plans.setup_zebra_and_shutter import (
14
+ setup_zebra_for_gridscan,
15
+ tidy_up_zebra_after_gridscan,
16
+ )
13
17
  from mx_bluesky.common.experiment_plans.common_flyscan_xray_centre_plan import (
14
18
  construct_beamline_specific_FGS_features,
15
19
  )
@@ -29,10 +33,6 @@ from mx_bluesky.hyperion.parameters.device_composites import (
29
33
  HyperionFlyScanXRayCentreComposite,
30
34
  )
31
35
  from mx_bluesky.hyperion.parameters.gridscan import HyperionSpecifiedThreeDGridScan
32
- from mx_bluesky.phase1_zebra.device_setup_plans.setup_zebra import (
33
- setup_zebra_for_gridscan,
34
- tidy_up_zebra_after_gridscan,
35
- )
36
36
 
37
37
 
38
38
  class SmargonSpeedException(Exception):
@@ -78,7 +78,9 @@ def construct_hyperion_specific_features(
78
78
  fgs_motors = xrc_composite.panda_fast_grid_scan
79
79
 
80
80
  else:
81
- setup_trigger_plan = setup_zebra_for_gridscan
81
+ setup_trigger_plan = partial(
82
+ setup_zebra_for_gridscan,
83
+ )
82
84
  tidy_plan = partial(
83
85
  tidy_up_zebra_after_gridscan,
84
86
  xrc_composite.zebra,
@@ -34,6 +34,10 @@ from mx_bluesky.common.device_setup_plans.manipulate_sample import (
34
34
  cleanup_sample_environment,
35
35
  setup_sample_environment,
36
36
  )
37
+ from mx_bluesky.common.device_setup_plans.setup_zebra_and_shutter import (
38
+ setup_zebra_for_rotation,
39
+ tidy_up_zebra_after_rotation_scan,
40
+ )
37
41
  from mx_bluesky.common.device_setup_plans.utils import (
38
42
  start_preparing_data_collection_then_do_plan,
39
43
  )
@@ -55,8 +59,6 @@ from mx_bluesky.common.utils.context import device_composite_from_context
55
59
  from mx_bluesky.common.utils.log import LOGGER
56
60
  from mx_bluesky.hyperion.device_setup_plans.setup_zebra import (
57
61
  arm_zebra,
58
- setup_zebra_for_rotation,
59
- tidy_up_zebra_after_rotation_scan,
60
62
  )
61
63
  from mx_bluesky.hyperion.parameters.constants import CONST, I03Constants
62
64
  from mx_bluesky.hyperion.parameters.rotation import (
@@ -1,5 +1,5 @@
1
1
  from dodal.utils import get_beamline_name
2
- from event_model import Event, EventDescriptor, RunStart
2
+ from event_model import Event, EventDescriptor, RunStart, RunStop
3
3
 
4
4
  from mx_bluesky.common.external_interaction.alerting import (
5
5
  Metadata,
@@ -48,7 +48,16 @@ class AlertOnContainerChange(PlanReactiveCallback):
48
48
  return doc
49
49
 
50
50
  def activity_gated_start(self, doc: RunStart):
51
- metadata = doc.get("metadata", {})
52
- self._new_container = metadata.get("container")
53
- self._sample_id = metadata.get("sample_id")
54
- self._visit = metadata.get("visit")
51
+ if not self._sample_id:
52
+ ISPYB_ZOCALO_CALLBACK_LOGGER.info("Capturing container info for alerts")
53
+ metadata = doc.get("metadata", {})
54
+ self._new_container = metadata.get("container")
55
+ self._sample_id = metadata.get("sample_id")
56
+ self._visit = metadata.get("visit")
57
+
58
+ def activity_gated_stop(self, doc: RunStop):
59
+ if not self.active:
60
+ ISPYB_ZOCALO_CALLBACK_LOGGER.info("Resetting state")
61
+ self._new_container = None
62
+ self._sample_id = None
63
+ self._visit = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mx-bluesky
3
- Version: 1.5.8
3
+ Version: 1.5.9
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
@@ -241,7 +241,7 @@ Requires-Dist: blueapi>=0.15.0
241
241
  Requires-Dist: ophyd>=1.10.5
242
242
  Requires-Dist: ophyd-async>=0.10.0a2
243
243
  Requires-Dist: bluesky>=1.13.1
244
- Requires-Dist: dls-dodal==1.61.0
244
+ Requires-Dist: dls-dodal==1.62.0
245
245
  Provides-Extra: dev
246
246
  Requires-Dist: black; extra == "dev"
247
247
  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=QlBPCHWJHsKOjOT6a1pMTyQvJ4_hi1jBIVqdqRIdaR0,704
3
+ mx_bluesky/_version.py,sha256=R8NtNnDKq3ku-8r0RS1XECjtWqIXXUTnvgF1AljQn-k,704
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
@@ -13,12 +13,14 @@ mx_bluesky/beamlines/i02_1/parameters/gridscan.py,sha256=P-WBnYSKcFQxMyeziIlWPht
13
13
  mx_bluesky/beamlines/i04/__init__.py,sha256=DM5-pkoPb2jill-VmKdhEylsV1jryA92gygCIFSv3Fo,383
14
14
  mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py,sha256=LViC4Dql47EXIDnI2hkt9CMtIyF1_e8h0s4GyIAllmA,6656
15
15
  mx_bluesky/beamlines/i04/thawing_plan.py,sha256=eSqX3VKHKw_KDGxjpszDifRpdb_RkwQxMKAZlOgl_7c,9759
16
+ mx_bluesky/beamlines/i04/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
17
  mx_bluesky/beamlines/i04/callbacks/murko_callback.py,sha256=C2KoIxwMIWxD46utmq1-69SIc8MspocXJ1sccO1lwAY,4458
17
18
  mx_bluesky/beamlines/i04/experiment_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py,sha256=NYbJfC8sksF-H8m1fCmQTWHBLQKzzpIqBJVjihYp4ew,9232
19
+ mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py,sha256=3Nv3EFNS5k5ivMMo15aR9br7mfz9WQ0S9_Olphe9D4Y,10168
19
20
  mx_bluesky/beamlines/i23/__init__.py,sha256=7nwQiKBZAXLnvPhCqaI2VC1k4TOzQalOUvwF6SQ3Yd4,95
20
21
  mx_bluesky/beamlines/i23/serial.py,sha256=XVbHM8NevnJMFAJD9jkxG-VnPaWX6t_k-wlipRw0pmY,2055
21
22
  mx_bluesky/beamlines/i24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ mx_bluesky/beamlines/i24/jungfrau_commissioning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
24
  mx_bluesky/beamlines/i24/jungfrau_commissioning/do_external_acquisition.py,sha256=p5ZOhM3COwiBjolMzHs8HNZGbTiIBjys4iUNQtUMKI0,1573
23
25
  mx_bluesky/beamlines/i24/jungfrau_commissioning/do_internal_acquisition.py,sha256=cNj4z3TFv8UgtDJax-v8Di74-gKLsTVKtwbCya-wwcw,1744
24
26
  mx_bluesky/beamlines/i24/jungfrau_commissioning/plan_utils.py,sha256=IaOw0pX8os-14EoLTwGTrFsl4PUZdL0ymbvdS7lhTto,2789
@@ -75,21 +77,23 @@ mx_bluesky/beamlines/i24/serial/web_gui_plans/__init__.py,sha256=47DEQpj8HBSa-_T
75
77
  mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py,sha256=4Cn7B-ZaNdcBkpsBg3BNLaNW5YZ-YkTSiJ4iJV-k4Y8,8471
76
78
  mx_bluesky/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
79
  mx_bluesky/common/xrc_result.py,sha256=tUJ6qkDTTB6H1F71IvVAKtmHCRyHSU_tj9GRzVmnE7w,3219
78
- mx_bluesky/common/device_setup_plans/manipulate_sample.py,sha256=bM4D0ezAqCJqclN5-hIVUoN_X55F8Yiv_ap6_ChKCA0,3091
80
+ mx_bluesky/common/device_setup_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
+ mx_bluesky/common/device_setup_plans/manipulate_sample.py,sha256=bKVWiXQnibXEjKjCNvy9PX4kUSh1CsBQCkqO5tUgrOU,3130
79
82
  mx_bluesky/common/device_setup_plans/position_detector.py,sha256=S49ml0KNZ6wXPQqOxNJ2whKTCyRTcKdBXBhyeEyFDQQ,635
80
- mx_bluesky/common/device_setup_plans/robot_load_unload.py,sha256=k3JSKBznJQWfYTlM6QO26BmpK5D3w4GJkvcJHLlujIw,4416
83
+ mx_bluesky/common/device_setup_plans/robot_load_unload.py,sha256=_pUrKEm34qSVdaUM83ypu3i2bAOdYqRLPU1ONhPowD4,4493
81
84
  mx_bluesky/common/device_setup_plans/setup_oav.py,sha256=7WLElZZU5mWq9g2WP86p3P81uiSPuj2V4kIkqXlap3o,2692
82
85
  mx_bluesky/common/device_setup_plans/setup_panda.py,sha256=OF-ZygZyAyQEUdrAWiIxWZ6QhAsVx4Mm9ngRYB1mzKI,433
86
+ mx_bluesky/common/device_setup_plans/setup_zebra_and_shutter.py,sha256=y83Szce7QxXdpLeGXpgyhceOr1HCE6fs6zmZr77IYAE,10066
83
87
  mx_bluesky/common/device_setup_plans/utils.py,sha256=S_Us1KfLkyaRzWxmqnoVxHj2Suq-Vs0n5fMRygHgrTw,1859
84
88
  mx_bluesky/common/device_setup_plans/xbpm_feedback.py,sha256=WsUMdeOZBgbj-bFp7x66aHp2oWffQmjyp61-qmtQAmI,2153
85
89
  mx_bluesky/common/experiment_plans/__init__.py,sha256=FMA-4VN1TJCPcyURKF0qPIQ8uo8YBbtHPRdJokVF4MA,129
86
90
  mx_bluesky/common/experiment_plans/change_aperture_then_move_plan.py,sha256=407E9rp0yGWWIU1fJrgqK_hC19mVwRK-Und7fMlGNDc,3062
87
- mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py,sha256=wf22Xwx79UXg_kKG8cD9IeIP_4gY0-p2aNhrUn37eFI,14213
91
+ mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py,sha256=JIRgSYqhgGu3I8lY3Oq2cyFNjcf_duRuWf0bhMgtOiU,13613
88
92
  mx_bluesky/common/experiment_plans/common_grid_detect_then_xray_centre_plan.py,sha256=jspOKPc3uxvG-a5-LXs7Yfwy8HTvGXBj4snke9j5gYE,7033
89
93
  mx_bluesky/common/experiment_plans/oav_grid_detection_plan.py,sha256=gkRpRb3USUx7xDJk-1GghV-sxPp7wy5clubwhlx1v80,7162
90
94
  mx_bluesky/common/experiment_plans/oav_snapshot_plan.py,sha256=8TRAvHG2W9bn1xb06bYZTWkfhT2q1EtfyxyiMMKmWcw,3623
91
- mx_bluesky/common/experiment_plans/inner_plans/__init__ .py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
- mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py,sha256=J8SF-ejb9PpB_wpL1QuS7_FIB5YxDN70odokc5dSIXY,4717
95
+ mx_bluesky/common/experiment_plans/inner_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
96
+ mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py,sha256=8Umn101RqCbtSKuw6duHKShPG2Cu3gYi_Cc51d29g7U,4865
93
97
  mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py,sha256=Og7Uz8lAB1_Z6puN6ws_2kwOqCvgQMqfmyZPFZMRneY,2351
94
98
  mx_bluesky/common/experiment_plans/inner_plans/udc_default_state.py,sha256=TnO5hv1I_UWlB1Vz7dCQ-nGj4LLsu9nQgetaK6hc_YM,2704
95
99
  mx_bluesky/common/experiment_plans/inner_plans/write_sample_status.py,sha256=pmS4Lsndp90CCIKzD_wssvbzt1qu7rEzfXgxvDwDrQ8,1313
@@ -102,7 +106,7 @@ mx_bluesky/common/external_interaction/callbacks/common/__init__.py,sha256=47DEQ
102
106
  mx_bluesky/common/external_interaction/callbacks/common/abstract_event.py,sha256=iBj4WNK5ikieZzTePBZ9AEu6ehlnpew1nDK3ONJqibI,2093
103
107
  mx_bluesky/common/external_interaction/callbacks/common/grid_detection_callback.py,sha256=hfFJjICMer26TowK5Nq-AEjDe1TAHIgJAvTFhs-o-Zg,4901
104
108
  mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py,sha256=--eZl4flvtrKZQz5ZhLO87Z1kDboQevIkujrXCADZEI,9869
105
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py,sha256=bHtnDZfxIR5zzSRiBSehZ51y42wzkEcCJ7rFg93aONA,2578
109
+ mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py,sha256=pzDlNEGhXACc5MyO_FAT2PlCYz6r_bnz_S08hXEGjdk,2707
106
110
  mx_bluesky/common/external_interaction/callbacks/common/log_uid_tag_callback.py,sha256=pfZxQfS9SnXep3F2YAPptDX5bjjWvbXtgy5fINfsoTU,626
107
111
  mx_bluesky/common/external_interaction/callbacks/common/logging_callback.py,sha256=NHb8Gp86TAk6PRTV3inWrlW-Lj96LmnZda7ZGewlrFA,712
108
112
  mx_bluesky/common/external_interaction/callbacks/common/plan_reactive_callback.py,sha256=567fx-ONKTZ7V5y5dk0YthxxDJt0s6dZtqrYA0AkfAk,4088
@@ -110,7 +114,7 @@ mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py,sha25
110
114
  mx_bluesky/common/external_interaction/callbacks/sample_handling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
115
  mx_bluesky/common/external_interaction/callbacks/sample_handling/sample_handling_callback.py,sha256=BfUru03fRYmndjiWHpnqBIWPc5kRIy4PTmG94bz3gLw,3886
112
116
  mx_bluesky/common/external_interaction/callbacks/xray_centre/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
113
- mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py,sha256=ezC3bbz84NLSPswHeUNVZr1eJEt_X6aPr7sn-IxdI9I,14879
117
+ mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py,sha256=fwPPwOvy1yGC8D5KOlpZitBWtVNzfNjK2yz-ZTT6q9Q,15398
114
118
  mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_mapping.py,sha256=yElqODhPm2HZlpF7vNOX0SQNjwJ_m8kNMS-c_cp4KUU,1163
115
119
  mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py,sha256=bxFMkTsMvZZJyp4zeGlZkThgZnQqT6dgflKRpqkT1Vc,4709
116
120
  mx_bluesky/common/external_interaction/ispyb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -145,12 +149,12 @@ mx_bluesky/hyperion/runner.py,sha256=x683wuzL-XO1Ws4N2fpPO__TLhlep0br_-8ubml1qG0
145
149
  mx_bluesky/hyperion/device_setup_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
146
150
  mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py,sha256=ciNdz_r9XGvghehpejdziL-aMw60oUsIJdVR3yz3nOo,5010
147
151
  mx_bluesky/hyperion/device_setup_plans/setup_panda.py,sha256=96eFp4acQLOthe1PA-S14uv635uGVP71DpP7qy_uo40,8509
148
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py,sha256=e3ocVsncImQIrfL6d0UoH5fCl8AR0pM_4AIXSxc8dgQ,5749
152
+ mx_bluesky/hyperion/device_setup_plans/setup_zebra.py,sha256=dOfBQMibyH3CjSh_m5RJKsxs2DtaM3jtwEs7lkqQppo,1525
149
153
  mx_bluesky/hyperion/device_setup_plans/smargon.py,sha256=eb3TCXg33SW6TlfElh5KjYwCXhELDprj0B27CwYcd9c,967
150
154
  mx_bluesky/hyperion/device_setup_plans/utils.py,sha256=96JlzyikMhWN7LzdiMx8URZInXoGR3OjoxYmCIp9tts,425
151
155
  mx_bluesky/hyperion/experiment_plans/__init__.py,sha256=dJjwLk0EQP-1hKhbs8aRxTF_LxUXgB7kcgDlaP-tMnk,787
152
156
  mx_bluesky/hyperion/experiment_plans/experiment_registry.py,sha256=bGp2c3nKutqHMnDxuqjp6yCF-JKykSzX-IUfxk3oVlM,1701
153
- mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py,sha256=aaDnO_fWOesB7IUMtedinBaJUdliWZe47wxq9ECFoFY,6036
157
+ mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py,sha256=qYDI39ic1kOfy8GL9_744kjuEzwPUBji65okxbOpWEE,6074
154
158
  mx_bluesky/hyperion/experiment_plans/hyperion_grid_detect_then_xray_centre_plan.py,sha256=e4w4226ONSGQF2dnXzxOfcJ9i57CZIJrqQ1YCLlaBNo,2153
155
159
  mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py,sha256=obUMizdLRGt-uCLnEzwiCGHn8wqHt0OVo1uvVvivWr4,7675
156
160
  mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py,sha256=5ZAH17F5T1YyVgA2ML0NEf4ufrD1G0jPRU0_5pINdTg,16195
@@ -158,7 +162,7 @@ mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py,sha256=
158
162
  mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py,sha256=1g3vs2hSgEYGhwDoqB8VsWTZ4q_Hd37493n_csoLnI8,6248
159
163
  mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py,sha256=bqG4enP2bZQ6ND0c5XqwDySQTkQRBdK7gvWf61VEnWM,6051
160
164
  mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py,sha256=samWAztWJU9sRo1FtIicWWQZ7TjUwg7Y9y9oqhkcb5o,6904
161
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py,sha256=jyJMN9atG99hmYG0i3lgrBK9Jx1SR4QVPFhZgA6Dl8s,15886
165
+ mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py,sha256=oFZ3HoWfgVRnuz2crTzSPUvdM2l7wz7RPbygUcTeo0Q,15963
162
166
  mx_bluesky/hyperion/experiment_plans/set_energy_plan.py,sha256=8FAqN-aJgRwZSiCX-hNdeGmaijt0l8owdShVBwNchfE,2643
163
167
  mx_bluesky/hyperion/external_interaction/__init__.py,sha256=95DwXDmKsx36RgAL-AtLZl2LQoLPKbzeYdlkkP_4Coc,559
164
168
  mx_bluesky/hyperion/external_interaction/agamemnon.py,sha256=B2Q7NR1VSRoCGg4hlCiZDrh2Fa0s4B4ZIws1H7oBfOk,12020
@@ -167,8 +171,9 @@ mx_bluesky/hyperion/external_interaction/alerting/__init__.py,sha256=47DEQpj8HBS
167
171
  mx_bluesky/hyperion/external_interaction/alerting/constants.py,sha256=8wE_MDF8vOqomQ6SBiwZKb1W4NRO_hmrBLVfLVnKdSg,170
168
172
  mx_bluesky/hyperion/external_interaction/callbacks/__init__.py,sha256=1XHaxDljMveu_DYIlk7n963gHffyC6r4C_RhF6HA-N8,283
169
173
  mx_bluesky/hyperion/external_interaction/callbacks/__main__.py,sha256=6-CqBh3uIi-mu_eWSJQ0hBQhoQaC7m8mSi8cHmyrjK0,6827
170
- mx_bluesky/hyperion/external_interaction/callbacks/alert_on_container_change.py,sha256=QnA8P8QFDRr1XHyx6Qdd4uJal2GhQVcqSTbkLOEjw-Q,2299
174
+ mx_bluesky/hyperion/external_interaction/callbacks/alert_on_container_change.py,sha256=54RU20RuwKHYwB6DtAc0aWg6hz3TXFhwDzTmSC2XYVE,2689
171
175
  mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py,sha256=ee1ZIJGp8RQakMDYRfflXjSwi-UgxqdZNkZ1azBIDGQ,11705
176
+ mx_bluesky/hyperion/external_interaction/callbacks/robot_actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
172
177
  mx_bluesky/hyperion/external_interaction/callbacks/robot_actions/ispyb_callback.py,sha256=Ta8w0W_3LI0PGpwxKlQsS7X0B_hsfJoZdzR2K3J0KHo,4467
173
178
  mx_bluesky/hyperion/external_interaction/callbacks/rotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
174
179
  mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py,sha256=4XW5eTwlPKGLk3MS76QRu5U6DOYAQHBEUBKqaNDnVhs,8885
@@ -188,10 +193,9 @@ mx_bluesky/hyperion/utils/__init__.py,sha256=f4E8wInL1Ll4eeFtAiyKmipOBTPlUtKmVK-
188
193
  mx_bluesky/hyperion/utils/context.py,sha256=yxMYn3YFET6SanFZ4YWXDmZDdp3WkaXhDc3ySxHYpAE,1033
189
194
  mx_bluesky/phase1_zebra/__init__.py,sha256=Edhhn2L9MVXnjJhyD5_yKQVUDo7XW98rvuT7dlzIn58,132
190
195
  mx_bluesky/phase1_zebra/device_setup_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
191
- mx_bluesky/phase1_zebra/device_setup_plans/setup_zebra.py,sha256=zfEnDvh5Rh9cPmg_Q_0EnJOZNIwIGmHeIDiJ9kg9Z4c,4129
192
- mx_bluesky-1.5.8.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
193
- mx_bluesky-1.5.8.dist-info/METADATA,sha256=Sgd23MlRNkDX8FybwhVs0WYSqmA7Elx1hCMuSps2fJw,17424
194
- mx_bluesky-1.5.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
195
- mx_bluesky-1.5.8.dist-info/entry_points.txt,sha256=HgVtwgWoMRn9-X6rxCcSY3Jz_paspJTIlc-t2NFzWpo,409
196
- mx_bluesky-1.5.8.dist-info/top_level.txt,sha256=S4rrzXIUef58ulf_04wn01XGZ3xeJjXs4LPEJ_xoF-I,11
197
- mx_bluesky-1.5.8.dist-info/RECORD,,
196
+ mx_bluesky-1.5.9.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
197
+ mx_bluesky-1.5.9.dist-info/METADATA,sha256=cLEcoIhuVwQrVcBG0-AWiw3LdWaXVDPX4WE9dTtOPXU,17424
198
+ mx_bluesky-1.5.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
199
+ mx_bluesky-1.5.9.dist-info/entry_points.txt,sha256=HgVtwgWoMRn9-X6rxCcSY3Jz_paspJTIlc-t2NFzWpo,409
200
+ mx_bluesky-1.5.9.dist-info/top_level.txt,sha256=S4rrzXIUef58ulf_04wn01XGZ3xeJjXs4LPEJ_xoF-I,11
201
+ mx_bluesky-1.5.9.dist-info/RECORD,,
@@ -1,112 +0,0 @@
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)