mx-bluesky 1.5.12__py3-none-any.whl → 1.5.15__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 (26) hide show
  1. mx_bluesky/Getting started.ipynb +170 -0
  2. mx_bluesky/_version.py +2 -2
  3. mx_bluesky/beamlines/aithre_lasershaping/robot_load.py +4 -10
  4. mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +4 -5
  5. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +5 -5
  6. mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py +21 -0
  7. mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py +1 -0
  8. mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +1 -0
  9. mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +1 -0
  10. mx_bluesky/common/external_interaction/ispyb/data_model.py +3 -0
  11. mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +4 -2
  12. mx_bluesky/common/parameters/constants.py +2 -0
  13. mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +4 -5
  14. mx_bluesky/hyperion/experiment_plans/udc_default_state.py +23 -11
  15. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +48 -21
  16. mx_bluesky/hyperion/parameters/device_composites.py +2 -0
  17. mx_bluesky/hyperion/plan_runner.py +31 -0
  18. mx_bluesky/hyperion/plan_runner_api.py +14 -1
  19. mx_bluesky/hyperion/utils/context.py +2 -2
  20. mx_bluesky/jupyter_example.ipynb +9 -1
  21. {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/METADATA +3 -3
  22. {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/RECORD +26 -25
  23. {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/WHEEL +0 -0
  24. {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/entry_points.txt +0 -0
  25. {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/licenses/LICENSE +0 -0
  26. {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,170 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "57c4caad-c26c-45af-9089-659c32e96c18",
6
+ "metadata": {},
7
+ "source": [
8
+ "Welcome to MX-Bluesky! This introduction is aimed at beamline scientists running from a beamline workstation. To confirm your environment is setup correctly,\n",
9
+ "run the below command to see if you get your expected beamline"
10
+ ]
11
+ },
12
+ {
13
+ "cell_type": "code",
14
+ "execution_count": null,
15
+ "id": "9d4cd08b-7097-46c2-9c1a-a71a19681c8d",
16
+ "metadata": {},
17
+ "outputs": [],
18
+ "source": [
19
+ "from dodal.utils import get_beamline_name\n",
20
+ "\n",
21
+ "beamline = get_beamline_name(\"dev\")\n",
22
+ "beamline = beamline.replace(\"-\",\"_\") # Convert ixx-n to ixx_n as this is the dodal format\n",
23
+ "print(f\"Beamline is {beamline}\")"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "markdown",
28
+ "id": "fe671aa3-a6b5-4a96-b27f-36c3d52453d6",
29
+ "metadata": {},
30
+ "source": [
31
+ "Now let's import your beamline module and see what devices are available"
32
+ ]
33
+ },
34
+ {
35
+ "cell_type": "code",
36
+ "execution_count": 21,
37
+ "id": "535811e1-ac7c-435e-af00-681caefd4787",
38
+ "metadata": {
39
+ "scrolled": true
40
+ },
41
+ "outputs": [
42
+ {
43
+ "name": "stdout",
44
+ "output_type": "stream",
45
+ "text": [
46
+ "synchrotron\n",
47
+ "sample_motors\n"
48
+ ]
49
+ }
50
+ ],
51
+ "source": [
52
+ "import importlib\n",
53
+ "\n",
54
+ "from dodal.utils import collect_factories\n",
55
+ "beamline = \"i02_2\"\n",
56
+ "module_name = f\"dodal.beamlines.{beamline}\"\n",
57
+ "beamline_module = importlib.import_module(module_name)\n",
58
+ "\n",
59
+ "for device in collect_factories(beamline_module):\n",
60
+ " print(device)"
61
+ ]
62
+ },
63
+ {
64
+ "cell_type": "markdown",
65
+ "id": "60768231-ae13-4e64-a1ec-eeec6136514a",
66
+ "metadata": {},
67
+ "source": [
68
+ "The Bluesky RunEngine must be used to interact with these devices. The RunEngine does a lot of things and is quite complicated. Some important benefits:\n",
69
+ "It can protect against using devices incorrectly, it allows us to pause and resume experiments, we can easily trace the sequence of events in experiments,\n",
70
+ "and we can customize it to do useful things like automatic plotting.\n",
71
+ "\n",
72
+ "A Bluesky plan is the name for any experimental procedure. A plan can be anything from a simple motor movement to a complex data collection involving tens of devices. A plan is made up of plan stubs, which are the most simple atomic operations. The two most common plan stubs are called \"abs_set\" and \"rd\", and these are essentially just writing to and reading from the PV of a device. Here's what that would look like on a simulated motor:"
73
+ ]
74
+ },
75
+ {
76
+ "cell_type": "code",
77
+ "execution_count": null,
78
+ "id": "30aaf9a1-3921-4be6-9afa-e81c2b216be8",
79
+ "metadata": {},
80
+ "outputs": [],
81
+ "source": [
82
+ "from bluesky import RunEngine\n",
83
+ "from bluesky import plan_stubs as bps\n",
84
+ "from ophyd_async.sim import SimMotor\n",
85
+ "\n",
86
+ "RE = RunEngine() # Create the RunEngine. We only should be doing this once.\n",
87
+ "fake_motor = SimMotor() # Create the simulated motor\n",
88
+ "\n",
89
+ "# Create the overall plan we want to run in the RunEngine\n",
90
+ "def my_plan():\n",
91
+ " initial_position = yield from bps.rd(fake_motor.user_readback)\n",
92
+ " print(f\"Position of the motor before moving it is {initial_position}\")\n",
93
+ " #Now move the motor\n",
94
+ " yield from bps.abs_set(fake_motor, 5, wait=True) #The code will wait here until the motor has finished moving. The units will be the same as that in EPICS\n",
95
+ " final_position = yield from bps.rd(fake_motor.user_readback)\n",
96
+ " print(f\"Position of the motor after moving it is {final_position}\")\n",
97
+ "\n",
98
+ "# In Bluesky, when we actually run a plan, we must do it through the RunEngine like this\n",
99
+ "RE(my_plan())\n"
100
+ ]
101
+ },
102
+ {
103
+ "cell_type": "markdown",
104
+ "id": "37d4bee0-561c-423a-85a4-ba8f157bc02a",
105
+ "metadata": {},
106
+ "source": [
107
+ "The above code can look confusing, mainly because of the \"yield from\" syntax. We need this because Bluesky plans are python generators rather then regular functions.\n",
108
+ "You don't need to understand generators to use Bluesky, you just need to remember than when calling a plan stub, you need to do \"yield from plan_name()\". If you try and call it like a regular function, eg, just doing \"plan_name()\", this won't actually run, and the code may not error - it catches everyone out!\n",
109
+ " \n",
110
+ "The above code ran instantly because the simulated motor has infinite velocity by default. We could set it to a realistic speed, then the code would take time to complete. Let's set the velocity using abs_set and try again:"
111
+ ]
112
+ },
113
+ {
114
+ "cell_type": "code",
115
+ "execution_count": null,
116
+ "id": "a2b7420b-d319-4ea7-b23f-4f4dad94eb34",
117
+ "metadata": {},
118
+ "outputs": [],
119
+ "source": [
120
+ "from time import time\n",
121
+ "\n",
122
+ "RE(bps.abs_set(fake_motor, 0, wait=True)) # Move motor back to 0\n",
123
+ "RE(bps.abs_set(fake_motor.velocity, 2, wait=True)) #2 units per second\n",
124
+ "start_time = time()\n",
125
+ "RE(my_plan())\n",
126
+ "print(f\"Movement took {round(time()-start_time,2)}s\")"
127
+ ]
128
+ },
129
+ {
130
+ "cell_type": "markdown",
131
+ "id": "897483ec-bb9f-42f3-ad8b-15820bf613ee",
132
+ "metadata": {},
133
+ "source": [
134
+ "Note that the default acceleration of a fake motor is 0.5 units/s/s. To see what a device looks like and what signals are available to it, we recommend navigating the codebase using VSCode. With many devices including motors, the signals\n",
135
+ "of the dodal device will map very closely to the EPICS interface for that device. With a few exceptions, anything you are used to changing using EDM screens will also be doable inside a Bluesky plan.\n",
136
+ "\n",
137
+ "Now try writing a simple Bluesky plan to move a real motor available using the above example code to help."
138
+ ]
139
+ },
140
+ {
141
+ "cell_type": "code",
142
+ "execution_count": null,
143
+ "id": "bb69130d-ffc2-428c-83bf-56c4cbd47ca2",
144
+ "metadata": {},
145
+ "outputs": [],
146
+ "source": []
147
+ }
148
+ ],
149
+ "metadata": {
150
+ "kernelspec": {
151
+ "display_name": "Python 3 (ipykernel)",
152
+ "language": "python",
153
+ "name": "python3"
154
+ },
155
+ "language_info": {
156
+ "codemirror_mode": {
157
+ "name": "ipython",
158
+ "version": 3
159
+ },
160
+ "file_extension": ".py",
161
+ "mimetype": "text/x-python",
162
+ "name": "python",
163
+ "nbconvert_exporter": "python",
164
+ "pygments_lexer": "ipython3",
165
+ "version": "3.12.11"
166
+ }
167
+ },
168
+ "nbformat": 4,
169
+ "nbformat_minor": 5
170
+ }
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.12'
32
- __version_tuple__ = version_tuple = (1, 5, 12)
31
+ __version__ = version = '1.5.15'
32
+ __version_tuple__ = version_tuple = (1, 5, 15)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -28,15 +28,12 @@ def robot_load_and_snapshot(
28
28
  sample_puck: int = 0,
29
29
  sample_pin: int = 0,
30
30
  sample_id: int = 0,
31
+ sample_name: str = "test",
31
32
  visit: str = "cm40645-5",
32
- categories: str = "",
33
33
  ) -> MsgGenerator:
34
- """
35
- categories: type of the sample, e.g. Germ, ProteinaseK, Screening
36
- """
37
34
  time_now = datetime.datetime.now()
38
35
  year_now = str(time_now.year)
39
- snapshot_directory = f"/dls/i23/data/{year_now}/{visit}/{categories}"
36
+ snapshot_directory = f"/dls/i23/data/{year_now}/{visit}/{sample_name}/snapshots"
40
37
  composite = RobotLoadComposite(robot, gonio, oav, gonio)
41
38
  params = AithreRobotLoad(
42
39
  sample_id=sample_id,
@@ -59,15 +56,12 @@ def robot_unload(
59
56
  sample_puck: int = 0,
60
57
  sample_pin: int = 0,
61
58
  sample_id: int = 0,
59
+ sample_name: str = "test",
62
60
  visit: str = "cm40645-5",
63
- categories: str = "",
64
61
  ) -> MsgGenerator:
65
- """
66
- categories: type of the sample, e.g. Germ, ProteinaseK, Screening
67
- """
68
62
  time_now = datetime.datetime.now()
69
63
  year_now = str(time_now.year)
70
- snapshot_directory = f"/dls/i23/data/{year_now}/{visit}/{categories}"
64
+ snapshot_directory = f"/dls/i23/data/{year_now}/{visit}/{sample_name}/snapshots"
71
65
  composite = RobotLoadComposite(robot, gonio, oav, gonio)
72
66
  params = AithreRobotLoad(
73
67
  sample_id=sample_id,
@@ -278,11 +278,8 @@ def construct_i04_specific_features(
278
278
  signals_to_read_pre_flyscan = [
279
279
  xrc_composite.undulator.current_gap,
280
280
  xrc_composite.synchrotron.synchrotron_mode,
281
- xrc_composite.s4_slit_gaps.xgap,
282
- xrc_composite.s4_slit_gaps.ygap,
283
- xrc_composite.smargon.x,
284
- xrc_composite.smargon.y,
285
- xrc_composite.smargon.z,
281
+ xrc_composite.s4_slit_gaps,
282
+ xrc_composite.smargon,
286
283
  xrc_composite.dcm.energy_in_keV,
287
284
  ]
288
285
 
@@ -292,6 +289,8 @@ def construct_i04_specific_features(
292
289
  xrc_composite.flux.flux_reading,
293
290
  xrc_composite.dcm.energy_in_keV,
294
291
  xrc_composite.eiger.bit_depth,
292
+ xrc_composite.beamsize,
293
+ xrc_composite.eiger.cam.roi_mode,
295
294
  ]
296
295
 
297
296
  tidy_plan = partial(
@@ -89,14 +89,14 @@ def gui_gonio_move_on_click(position_px: tuple[int, int]) -> MsgGenerator:
89
89
  oav = i24.oav()
90
90
  gonio = i24.vgonio()
91
91
 
92
- x_pixels_per_micron = yield from bps.rd(oav.microns_per_pixel_x)
93
- y_pixels_per_micron = yield from bps.rd(oav.microns_per_pixel_y)
92
+ x_microns_per_pixel = yield from bps.rd(oav.microns_per_pixel_x)
93
+ y_microns_per_pixel = yield from bps.rd(oav.microns_per_pixel_y)
94
94
 
95
- x_um = position_px[0] * x_pixels_per_micron
96
- y_um = position_px[1] * y_pixels_per_micron
95
+ x_um = position_px[0] * x_microns_per_pixel
96
+ y_um = position_px[1] * y_microns_per_pixel
97
97
 
98
98
  # gonio is in mm?
99
- yield from bps.mv(gonio.x, x_um / 1000, gonio.yh, y_um / 1000) # type: ignore
99
+ yield from bps.mv(gonio.x, x_um / 1000, gonio.yh, y_um / 1000)
100
100
 
101
101
 
102
102
  @bpp.run_decorator()
@@ -1,6 +1,7 @@
1
1
  from enum import Enum
2
2
 
3
3
  import bluesky.plan_stubs as bps
4
+ from bluesky.utils import MsgGenerator
4
5
  from dodal.common import inject
5
6
  from dodal.devices.i24.pmac import PMAC
6
7
 
@@ -17,6 +18,11 @@ class Direction(Enum):
17
18
  RIGHT = "right"
18
19
 
19
20
 
21
+ class FocusDirection(Enum):
22
+ IN = "in"
23
+ OUT = "out"
24
+
25
+
20
26
  def _move_direction(magnitude: float, direction: Direction, pmac):
21
27
  y_move = 0.0
22
28
  x_move = 0.0
@@ -62,3 +68,18 @@ def move_nudge_on_arrow_click(
62
68
  magnitude = 0.0060
63
69
 
64
70
  yield from _move_direction(magnitude, direction, pmac)
71
+
72
+
73
+ def focus_on_oav_view(
74
+ direction: FocusDirection, size_of_move: MoveSize, pmac: PMAC = inject("pmac")
75
+ ) -> MsgGenerator:
76
+ match size_of_move:
77
+ case MoveSize.SMALL:
78
+ magnitude = 0.0200
79
+ case MoveSize.BIG:
80
+ magnitude = 0.1200
81
+
82
+ if direction == FocusDirection.IN:
83
+ magnitude = -magnitude
84
+
85
+ yield from bps.abs_set(pmac.z, magnitude, wait=True)
@@ -75,6 +75,7 @@ def standard_read_hardware_during_collection(
75
75
  dcm.energy_in_keV,
76
76
  detector.bit_depth,
77
77
  beamsize,
78
+ detector.cam.roi_mode,
78
79
  ]
79
80
  yield from read_hardware_plan(
80
81
  signals_to_read_during_collection, DocDescriptorNames.HARDWARE_READ_DURING
@@ -158,6 +158,7 @@ class BaseISPyBCallback(PlanReactiveCallback):
158
158
  beamsize_at_samplex=beamsize_x_mm,
159
159
  beamsize_at_sampley=beamsize_y_mm,
160
160
  flux=doc["data"]["flux-flux_reading"],
161
+ detector_mode="ROI" if doc["data"]["eiger_cam_roi_mode"] else "FULL",
161
162
  )
162
163
  if transmission := doc["data"]["attenuator-actual_transmission"]:
163
164
  # Ispyb wants the transmission in a percentage, we use fractions
@@ -28,6 +28,7 @@ def populate_remaining_data_collection_info(
28
28
  data_collection_info: DataCollectionInfo,
29
29
  params: DiffractionExperimentWithSample,
30
30
  ):
31
+ data_collection_info.sample_id = params.sample_id
31
32
  data_collection_info.visit_string = params.visit
32
33
  data_collection_info.parent_id = data_collection_group_id
33
34
  data_collection_info.detector_id = I03_EIGER_DETECTOR
@@ -67,6 +67,9 @@ class DataCollectionInfo:
67
67
  start_time: str | None = None
68
68
  end_time: str | None = None
69
69
  run_status: str | None = None
70
+ detector_mode: str | None = None
71
+
72
+ sample_id: int | None = None
70
73
 
71
74
 
72
75
  @dataclass
@@ -309,6 +309,8 @@ def _data_collection_info_to_json(data: DataCollectionInfo) -> dict:
309
309
  "startTime": data.start_time,
310
310
  "endTime": data.end_time,
311
311
  "runStatus": data.run_status,
312
+ "sampleId": data.sample_id,
313
+ "detectorMode": data.detector_mode,
312
314
  }
313
315
  )
314
316
 
@@ -333,8 +335,8 @@ def _grid_info_to_json(data: DataCollectionGridInfo) -> dict:
333
335
  "stepsX": data.steps_x,
334
336
  "stepsY": data.steps_y,
335
337
  "orientation": data.orientation.value,
336
- "pixelsPerMicronX": 1 / data.microns_per_pixel_x,
337
- "pixelsPerMicronY": 1 / data.microns_per_pixel_y,
338
+ "micronsPerPixelX": data.microns_per_pixel_x,
339
+ "micronsPerPixelY": data.microns_per_pixel_y,
338
340
  "snaked": data.snaked,
339
341
  }
340
342
  )
@@ -88,6 +88,8 @@ class HardwareConstants:
88
88
  PANDA_FGS_RUN_UP_DEFAULT = 0.17
89
89
  CRYOJET_MARGIN_MM = 0.2
90
90
  TIP_OFFSET_UM = 0
91
+ MAX_CRYO_TEMP_K = 110
92
+ MAX_CRYO_PRESSURE_BAR = 0.1
91
93
 
92
94
  # Value quoted in https://www.dectris.com/en/detectors/x-ray-detectors/eiger2/eiger2-for-synchrotrons/eiger2-x/,
93
95
  # causes dropped frames, so increase value for safety
@@ -49,11 +49,8 @@ def construct_hyperion_specific_features(
49
49
  signals_to_read_pre_flyscan = [
50
50
  xrc_composite.undulator.current_gap,
51
51
  xrc_composite.synchrotron.synchrotron_mode,
52
- xrc_composite.s4_slit_gaps.xgap,
53
- xrc_composite.s4_slit_gaps.ygap,
54
- xrc_composite.smargon.x,
55
- xrc_composite.smargon.y,
56
- xrc_composite.smargon.z,
52
+ xrc_composite.s4_slit_gaps,
53
+ xrc_composite.smargon,
57
54
  xrc_composite.dcm.energy_in_keV,
58
55
  ]
59
56
 
@@ -63,6 +60,8 @@ def construct_hyperion_specific_features(
63
60
  xrc_composite.flux.flux_reading,
64
61
  xrc_composite.dcm.energy_in_keV,
65
62
  xrc_composite.eiger.bit_depth,
63
+ xrc_composite.beamsize,
64
+ xrc_composite.eiger.cam.roi_mode,
66
65
  ]
67
66
 
68
67
  setup_trigger_plan: Callable[..., MsgGenerator]
@@ -6,12 +6,18 @@ from dodal.common.beamlines.beamline_parameters import (
6
6
  )
7
7
  from dodal.devices.aperturescatterguard import ApertureValue
8
8
  from dodal.devices.collimation_table import CollimationTable
9
- from dodal.devices.cryostream import CryoStream, CryoStreamGantry, CryoStreamSelection
9
+ from dodal.devices.cryostream import (
10
+ CryoStreamGantry,
11
+ CryoStreamSelection,
12
+ OxfordCryoJet,
13
+ OxfordCryoStream,
14
+ )
10
15
  from dodal.devices.cryostream import InOut as CryoInOut
11
16
  from dodal.devices.fluorescence_detector_motion import FluorescenceDetector
12
17
  from dodal.devices.fluorescence_detector_motion import InOut as FlouInOut
13
18
  from dodal.devices.hutch_shutter import HutchShutter, ShutterDemand
14
19
  from dodal.devices.mx_phase1.beamstop import BeamstopPositions
20
+ from dodal.devices.oav.oav_detector import OAV
15
21
  from dodal.devices.robot import BartRobot, PinMounted
16
22
  from dodal.devices.scintillator import InOut as ScinInOut
17
23
  from dodal.devices.scintillator import Scintillator
@@ -27,7 +33,7 @@ from mx_bluesky.common.utils.log import LOGGER
27
33
  from mx_bluesky.hyperion.external_interaction.config_server import (
28
34
  get_hyperion_config_client,
29
35
  )
30
- from mx_bluesky.hyperion.parameters.constants import HyperionFeatureSettings
36
+ from mx_bluesky.hyperion.parameters.constants import CONST, HyperionFeatureSettings
31
37
 
32
38
  _GROUP_PRE_BEAMSTOP_CHECK = "pre_beamstop_check"
33
39
  _GROUP_POST_BEAMSTOP_CHECK = "post_beamstop_check"
@@ -36,13 +42,15 @@ _GROUP_POST_BEAMSTOP_CHECK = "post_beamstop_check"
36
42
  @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
37
43
  class UDCDefaultDevices(BeamstopCheckDevices):
38
44
  collimation_table: CollimationTable
39
- cryostream: CryoStream
45
+ cryojet: OxfordCryoJet
46
+ cryostream: OxfordCryoStream
40
47
  cryostream_gantry: CryoStreamGantry
41
48
  fluorescence_det_motion: FluorescenceDetector
42
49
  hutch_shutter: HutchShutter
43
50
  robot: BartRobot
44
51
  scintillator: Scintillator
45
52
  smargon: Smargon
53
+ oav: OAV
46
54
 
47
55
 
48
56
  class UnexpectedSampleError(BeamlineCheckFailureError): ...
@@ -55,11 +63,11 @@ def move_to_udc_default_state(devices: UDCDefaultDevices):
55
63
  """Moves beamline to known positions prior to UDC start"""
56
64
  yield from _verify_correct_cryostream_selected(devices.cryostream_gantry)
57
65
 
58
- cryostream_temp = yield from bps.rd(devices.cryostream.temperature_k)
59
- cryostream_pressure = yield from bps.rd(devices.cryostream.back_pressure_bar)
60
- if cryostream_temp > devices.cryostream.MAX_TEMP_K:
66
+ cryostream_temp = yield from bps.rd(devices.cryostream.temp)
67
+ cryostream_pressure = yield from bps.rd(devices.cryostream.back_pressure)
68
+ if cryostream_temp > CONST.HARDWARE.MAX_CRYO_TEMP_K:
61
69
  raise CryoStreamError("Cryostream temperature is too high, not starting UDC")
62
- if cryostream_pressure > devices.cryostream.MAX_PRESSURE_BAR:
70
+ if cryostream_pressure > CONST.HARDWARE.MAX_CRYO_PRESSURE_BAR:
63
71
  raise CryoStreamError("Cryostream back pressure is too high, not starting UDC")
64
72
 
65
73
  yield from _verify_no_sample_present(devices.robot)
@@ -103,7 +111,7 @@ def move_to_udc_default_state(devices: UDCDefaultDevices):
103
111
  )
104
112
 
105
113
  # Wait for all of the above to complete
106
- yield from bps.wait(group=_GROUP_PRE_BEAMSTOP_CHECK, timeout=0.1)
114
+ yield from bps.wait(group=_GROUP_PRE_BEAMSTOP_CHECK, timeout=10)
107
115
 
108
116
  feature_flags: HyperionFeatureSettings = (
109
117
  get_hyperion_config_client().get_feature_flags()
@@ -129,13 +137,17 @@ def move_to_udc_default_state(devices: UDCDefaultDevices):
129
137
  )
130
138
 
131
139
  yield from bps.abs_set(
132
- devices.cryostream.course, CryoInOut.IN, group=_GROUP_POST_BEAMSTOP_CHECK
140
+ devices.cryojet.coarse, CryoInOut.IN, group=_GROUP_POST_BEAMSTOP_CHECK
141
+ )
142
+ yield from bps.abs_set(
143
+ devices.cryojet.fine, CryoInOut.IN, group=_GROUP_POST_BEAMSTOP_CHECK
133
144
  )
145
+
134
146
  yield from bps.abs_set(
135
- devices.cryostream.fine, CryoInOut.IN, group=_GROUP_POST_BEAMSTOP_CHECK
147
+ devices.oav.zoom_controller, "1.0x", group=_GROUP_POST_BEAMSTOP_CHECK
136
148
  )
137
149
 
138
- yield from bps.wait(_GROUP_POST_BEAMSTOP_CHECK)
150
+ yield from bps.wait(_GROUP_POST_BEAMSTOP_CHECK, timeout=10)
139
151
 
140
152
 
141
153
  def _verify_correct_cryostream_selected(
@@ -2,6 +2,8 @@ import logging
2
2
  from collections.abc import Callable, Sequence
3
3
  from threading import Thread
4
4
  from time import sleep # noqa
5
+ from urllib import request
6
+ from urllib.error import URLError
5
7
 
6
8
  from bluesky.callbacks import CallbackBase
7
9
  from bluesky.callbacks.zmq import Proxy, RemoteDispatcher
@@ -51,14 +53,17 @@ from mx_bluesky.hyperion.external_interaction.callbacks.snapshot_callback import
51
53
  BeamDrawingCallback,
52
54
  )
53
55
  from mx_bluesky.hyperion.parameters.cli import parse_callback_dev_mode_arg
54
- from mx_bluesky.hyperion.parameters.constants import CONST
56
+ from mx_bluesky.hyperion.parameters.constants import CONST, HyperionConstants
55
57
  from mx_bluesky.hyperion.parameters.gridscan import (
56
58
  GridCommonWithHyperionDetectorParams,
57
59
  HyperionSpecifiedThreeDGridScan,
58
60
  )
59
61
 
62
+ PING_TIMEOUT_S = 1
63
+
60
64
  LIVENESS_POLL_SECONDS = 1
61
65
  ERROR_LOG_BUFFER_LINES = 5000
66
+ HYPERION_PING_INTERVAL_S = 19
62
67
 
63
68
 
64
69
  def create_gridscan_callbacks() -> tuple[
@@ -128,21 +133,6 @@ def setup_logging(dev_mode: bool):
128
133
  log_debug("nexgen logger added to nexus logger")
129
134
 
130
135
 
131
- def setup_threads():
132
- proxy = Proxy(*CONST.CALLBACK_0MQ_PROXY_PORTS)
133
- dispatcher = RemoteDispatcher(f"localhost:{CONST.CALLBACK_0MQ_PROXY_PORTS[1]}")
134
- log_debug("Created proxy and dispatcher objects")
135
-
136
- def start_proxy():
137
- proxy.start()
138
-
139
- def start_dispatcher(callbacks: list[Callable]):
140
- [dispatcher.subscribe(cb) for cb in callbacks]
141
- dispatcher.start()
142
-
143
- return proxy, dispatcher, start_proxy, start_dispatcher
144
-
145
-
146
136
  def log_info(msg, *args, **kwargs):
147
137
  ISPYB_ZOCALO_CALLBACK_LOGGER.info(msg, *args, **kwargs)
148
138
  NEXUS_LOGGER.info(msg, *args, **kwargs)
@@ -175,20 +165,57 @@ class HyperionCallbackRunner:
175
165
  set_alerting_service(LoggingAlertService(CONST.GRAYLOG_STREAM_ID))
176
166
 
177
167
  self.callbacks = setup_callbacks()
178
- self.proxy, self.dispatcher, start_proxy, start_dispatcher = setup_threads()
179
- log_info("Created 0MQ proxy and local RemoteDispatcher.")
180
168
 
181
- self.proxy_thread = Thread(target=start_proxy, daemon=True)
169
+ self.proxy = Proxy(*CONST.CALLBACK_0MQ_PROXY_PORTS)
170
+ self.proxy_thread = Thread(
171
+ target=self.proxy.start, daemon=True, name="0MQ Proxy"
172
+ )
173
+
174
+ self.dispatcher = RemoteDispatcher(
175
+ f"localhost:{CONST.CALLBACK_0MQ_PROXY_PORTS[1]}"
176
+ )
177
+
178
+ def start_dispatcher(callbacks: list[Callable]):
179
+ for cb in callbacks:
180
+ self.dispatcher.subscribe(cb)
181
+ self.dispatcher.start()
182
+
182
183
  self.dispatcher_thread = Thread(
183
- target=start_dispatcher, args=[self.callbacks], daemon=True
184
+ target=start_dispatcher,
185
+ args=[self.callbacks],
186
+ daemon=True,
187
+ name="0MQ Dispatcher",
184
188
  )
185
189
 
190
+ self.watchdog_thread = Thread(target=run_watchdog, daemon=True, name="Watchdog")
191
+ log_info("Created 0MQ proxy and local RemoteDispatcher.")
192
+
186
193
  def start(self):
187
194
  log_info(f"Launching threads, with callbacks: {self.callbacks}")
188
195
  self.proxy_thread.start()
189
196
  self.dispatcher_thread.start()
197
+ self.watchdog_thread.start()
190
198
  log_info("Proxy and dispatcher thread launched.")
191
- wait_for_threads_forever([self.proxy_thread, self.dispatcher_thread])
199
+ wait_for_threads_forever(
200
+ [self.proxy_thread, self.dispatcher_thread, self.watchdog_thread]
201
+ )
202
+
203
+
204
+ def run_watchdog():
205
+ log_info("Hyperion watchdog keepalive running")
206
+ while True:
207
+ try:
208
+ with request.urlopen(
209
+ f"http://localhost:{HyperionConstants.HYPERION_PORT}/callbackPing",
210
+ timeout=PING_TIMEOUT_S,
211
+ ) as response:
212
+ if response.status != 200:
213
+ log_debug(
214
+ f"Unable to ping Hyperion liveness endpoint, status {response.status}"
215
+ )
216
+ except URLError as e:
217
+ log_debug("Unable to ping Hyperion liveness endpoint", exc_info=e)
218
+ sleep(HYPERION_PING_INTERVAL_S)
192
219
 
193
220
 
194
221
  def main(dev_mode=False) -> None:
@@ -13,6 +13,7 @@ from dodal.devices.fast_grid_scan import (
13
13
  ZebraFastGridScanThreeD,
14
14
  )
15
15
  from dodal.devices.flux import Flux
16
+ from dodal.devices.i03.beamsize import Beamsize
16
17
  from dodal.devices.robot import BartRobot
17
18
  from dodal.devices.s4_slit_gaps import S4SlitGaps
18
19
  from dodal.devices.synchrotron import Synchrotron
@@ -52,6 +53,7 @@ class HyperionFlyScanXRayCentreComposite(FlyScanEssentialDevices):
52
53
  backlight: Backlight
53
54
  xbpm_feedback: XBPMFeedback
54
55
  zebra_fast_grid_scan: ZebraFastGridScanThreeD
56
+ beamsize: Beamsize
55
57
 
56
58
 
57
59
  @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
@@ -1,7 +1,9 @@
1
1
  import threading
2
+ import time
2
3
  from collections.abc import Callable
3
4
 
4
5
  from blueapi.core import BlueskyContext
6
+ from bluesky import plan_stubs as bps
5
7
  from bluesky.utils import MsgGenerator, RequestAbort
6
8
 
7
9
  from mx_bluesky.common.parameters.constants import Status
@@ -19,10 +21,15 @@ class PlanError(Exception):
19
21
  class PlanRunner(BaseRunner):
20
22
  """Runner that executes experiments from inside a running Bluesky plan"""
21
23
 
24
+ EXTERNAL_CALLBACK_WATCHDOG_TIMER_S = 60
25
+ EXTERNAL_CALLBACK_POLL_INTERVAL_S = 1
26
+
22
27
  def __init__(self, context: BlueskyContext, dev_mode: bool) -> None:
23
28
  super().__init__(context)
24
29
  self.current_status: Status = Status.IDLE
25
30
  self.is_dev_mode = dev_mode
31
+ self._callbacks_started = False
32
+ self._callback_watchdog_expiry = time.monotonic()
26
33
 
27
34
  def execute_plan(
28
35
  self,
@@ -38,6 +45,20 @@ class PlanRunner(BaseRunner):
38
45
  self.current_status = Status.BUSY
39
46
 
40
47
  try:
48
+ callback_expiry = time.monotonic() + self.EXTERNAL_CALLBACK_WATCHDOG_TIMER_S
49
+ while time.monotonic() < callback_expiry:
50
+ if self._callbacks_started:
51
+ break
52
+ # If on first launch the external callbacks aren't started yet, wait until they are
53
+ LOGGER.info("Waiting for external callbacks to start")
54
+ yield from bps.sleep(self.EXTERNAL_CALLBACK_POLL_INTERVAL_S)
55
+ else:
56
+ raise RuntimeError("External callbacks not running - try restarting")
57
+
58
+ if not self._external_callbacks_are_alive():
59
+ raise RuntimeError(
60
+ "External callback watchdog timer expired, check external callbacks are running."
61
+ )
41
62
  yield from experiment()
42
63
  self.current_status = Status.IDLE
43
64
  except WarningError as e:
@@ -74,3 +95,13 @@ class PlanRunner(BaseRunner):
74
95
  stopping_thread = threading.Thread(target=issue_abort)
75
96
  stopping_thread.start()
76
97
  return
98
+
99
+ def reset_callback_watchdog_timer(self):
100
+ """Called periodically to reset the watchdog timer when the external callbacks ping us."""
101
+ self._callbacks_started = True
102
+ self._callback_watchdog_expiry = (
103
+ time.monotonic() + self.EXTERNAL_CALLBACK_WATCHDOG_TIMER_S
104
+ )
105
+
106
+ def _external_callbacks_are_alive(self) -> bool:
107
+ return time.monotonic() < self._callback_watchdog_expiry
@@ -24,10 +24,11 @@ def create_server_for_udc(runner: PlanRunner) -> Thread: # pragma: no cover
24
24
  return flask_thread
25
25
 
26
26
 
27
- def create_app_for_udc(runner):
27
+ def create_app_for_udc(runner: PlanRunner):
28
28
  app = Flask(__name__)
29
29
  api = Api(app)
30
30
  api.add_resource(StatusResource, "/status", resource_class_args=[runner])
31
+ api.add_resource(CallbackLiveness, "/callbackPing", resource_class_args=[runner])
31
32
  return app
32
33
 
33
34
 
@@ -41,3 +42,15 @@ class StatusResource(Resource):
41
42
  def get(self):
42
43
  status = self._runner.current_status
43
44
  return {"status": status.value}
45
+
46
+
47
+ class CallbackLiveness(Resource):
48
+ """Called periodically by the external callbacks to indicate that they are still running"""
49
+
50
+ def __init__(self, runner: PlanRunner):
51
+ super().__init__()
52
+ self._runner = runner
53
+
54
+ def get(self):
55
+ LOGGER.debug("External callback ping received.")
56
+ self._runner.reset_callback_watchdog_timer()
@@ -27,8 +27,8 @@ def clear_all_device_caches(context: BlueskyContext):
27
27
 
28
28
 
29
29
  def setup_devices(context: BlueskyContext, dev_mode: bool):
30
- _, exceptions = context.with_dodal_module(
31
- get_beamline_based_on_environment_variable(),
30
+ _, exceptions = context.with_device_manager(
31
+ get_beamline_based_on_environment_variable().devices,
32
32
  mock=dev_mode,
33
33
  )
34
34
  if exceptions:
@@ -48,6 +48,14 @@
48
48
  "\n",
49
49
  "run_engine(scan(dets, motor, -1, 1, 10))"
50
50
  ]
51
+ },
52
+ {
53
+ "cell_type": "code",
54
+ "execution_count": null,
55
+ "id": "d117ffc8-882c-44fb-b65d-7e57544255d4",
56
+ "metadata": {},
57
+ "outputs": [],
58
+ "source": []
51
59
  }
52
60
  ],
53
61
  "metadata": {
@@ -66,7 +74,7 @@
66
74
  "name": "python",
67
75
  "nbconvert_exporter": "python",
68
76
  "pygments_lexer": "ipython3",
69
- "version": "3.10.4"
77
+ "version": "3.12.11"
70
78
  }
71
79
  },
72
80
  "nbformat": 4,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mx-bluesky
3
- Version: 1.5.12
3
+ Version: 1.5.15
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
@@ -237,11 +237,11 @@ Requires-Dist: deepdiff
237
237
  Requires-Dist: matplotlib
238
238
  Requires-Dist: cachetools
239
239
  Requires-Dist: daq-config-server>=v1.0.0-rc.2
240
- Requires-Dist: blueapi>=1.6.3
240
+ Requires-Dist: blueapi>=1.8.0
241
241
  Requires-Dist: ophyd>=1.10.5
242
242
  Requires-Dist: ophyd-async>=0.14.0
243
243
  Requires-Dist: bluesky>=1.14.6
244
- Requires-Dist: dls-dodal==1.66.0
244
+ Requires-Dist: dls-dodal==1.68.0
245
245
  Provides-Extra: dev
246
246
  Requires-Dist: black; extra == "dev"
247
247
  Requires-Dist: build; extra == "dev"
@@ -1,15 +1,16 @@
1
+ mx_bluesky/Getting started.ipynb,sha256=0dqcrIA3Gq3otbjR-csWQeLBsmQMsmi29WPt-GVsXGQ,6503
1
2
  mx_bluesky/__init__.py,sha256=Ksms_WJF8LTkbm38gEpm1jBpGqcQ8NGvmb2ZJlOE1j8,198
2
3
  mx_bluesky/__main__.py,sha256=RVqPnxDisFMIn_aoEi0drlThNHgKTJULnSrotouIKI0,480
3
- mx_bluesky/_version.py,sha256=TL6wrn4QI80JHCPVFzYKILNOnoWs_pn-RUeoNFokTsI,706
4
+ mx_bluesky/_version.py,sha256=Om_yIWjr9CmfMFQtiMr-8lpdGJ5MY2yQmv5N7zsGePI,706
4
5
  mx_bluesky/definitions.py,sha256=ULpEYAUzdQiEbBoTgYTMxfUf3DDDjhYtvDxofs7Qxqw,168
5
- mx_bluesky/jupyter_example.ipynb,sha256=oxNpKVGRQp28paV6XM5ZQyN4llhH-EpFeHSBXK1JNPU,1696
6
+ mx_bluesky/jupyter_example.ipynb,sha256=oGYWduEjWrSpciCBe9strBng1Mh_dPZuQt6dOYnrPdU,1860
6
7
  mx_bluesky/beamlines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
8
  mx_bluesky/beamlines/aithre_lasershaping/__init__.py,sha256=rwbS3QJnC3nq-VKddgEa0M0p22GOCkNrGuwhzz8k-FQ,637
8
9
  mx_bluesky/beamlines/aithre_lasershaping/beamline_safe.py,sha256=E7tNwX9LFPNfBCF1DpNNtWpchPkEvGP0nrrTq4t2s38,1927
9
10
  mx_bluesky/beamlines/aithre_lasershaping/check_goniometer_performance.py,sha256=AqWAFey_Ih1JcRxVNiZDGFsVg4kvA9LH2p5SJeXfe2I,834
10
11
  mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py,sha256=Db95Mgc24wVw_8ghvpfbVOR7-MwgHdJkq4J4Xe7iy_I,1828
11
12
  mx_bluesky/beamlines/aithre_lasershaping/pin_tip_centring.py,sha256=-Hoa40YiCio_zALyxlqwmRmwcnF0AI2qpMArdRliFvc,1049
12
- mx_bluesky/beamlines/aithre_lasershaping/robot_load.py,sha256=_oQCRknaAILmHFf86i2q4SWTfamKlClpFPyavOcLjfA,2571
13
+ mx_bluesky/beamlines/aithre_lasershaping/robot_load.py,sha256=VT9c8-BiNL9xYSASwoT84eZ-lPpVxxd1ug-XjhmzTkg,2431
13
14
  mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
15
  mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/robot_load_plan.py,sha256=Y1FbWwCM5Qy978X2NSd26StWHcg_3M7z-Y35zKFKkRE,6243
15
16
  mx_bluesky/beamlines/aithre_lasershaping/parameters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -23,7 +24,7 @@ mx_bluesky/beamlines/i04/thawing_plan.py,sha256=fFePelD3SHjSSduJzaXHQ1r1oTYouGH2
23
24
  mx_bluesky/beamlines/i04/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
25
  mx_bluesky/beamlines/i04/callbacks/murko_callback.py,sha256=tmpALQZZreD03TH7mvoaKzTWHrm1l_bIpcg7pv8YCQU,5011
25
26
  mx_bluesky/beamlines/i04/experiment_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py,sha256=H46PfTaHL9QRZqDKkIdfVWnt2lCJdUhYca8s_QkT75o,12767
27
+ mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py,sha256=8Lm6dGJtSQXkbEaIQpuJchiafx41tCUoPX0lyp5-wZU,12727
27
28
  mx_bluesky/beamlines/i04/external_interaction/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
29
  mx_bluesky/beamlines/i04/external_interaction/config_server.py,sha256=Zpair6Qw1nBgm-w8eAg0f-4mjHouAnaF2Fu2Pj8zTeU,425
29
30
  mx_bluesky/beamlines/i04/oav_centering_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -89,8 +90,8 @@ mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py,sha256=BNn2FRn7
89
90
  mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py,sha256=AAOfQpqHbMjHN7NVJ96c68lvC_HL1ZwviAE2dr1qbg4,2926
90
91
  mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py,sha256=zJu2kzWHUTdir1ojYmXWCM-cz0IIXcp2kJmCS90PjeQ,17458
91
92
  mx_bluesky/beamlines/i24/serial/web_gui_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
- mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py,sha256=QvwNYwWuIYZ9cqnrFsib8lr8I1TvedGLLxLcoVzoK5Y,11820
93
- mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py,sha256=GTN6T3E_2UAxh1O4s4H44XKaW-gEh1gL6eJ6dD9U9IU,1557
93
+ mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py,sha256=Gck3y6geOeqE3gC7Ne9mK27fYiu7owj1bXEEosSYsm0,11804
94
+ mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py,sha256=YxbSNsNPo1jcEMbRkHf1x3mQ1m6qQF1bL_J6j5cjvQ4,2054
94
95
  mx_bluesky/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
96
  mx_bluesky/common/xrc_result.py,sha256=tUJ6qkDTTB6H1F71IvVAKtmHCRyHSU_tj9GRzVmnE7w,3219
96
97
  mx_bluesky/common/device_setup_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -113,7 +114,7 @@ mx_bluesky/common/experiment_plans/oav_snapshot_plan.py,sha256=3xhEen8Op_lPSB63s
113
114
  mx_bluesky/common/experiment_plans/pin_tip_centring_plan.py,sha256=DTBdm7zMwrJUkhS_pu2IHAfKMgYnzBZNa-QIuusxCSo,6184
114
115
  mx_bluesky/common/experiment_plans/inner_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
116
  mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py,sha256=IMsfA1-4POl5h5X3mczN-Hll-OlGwrp8RaI32TMlyjM,4884
116
- mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py,sha256=tp4A2X-Ti7YEOo-TvnX6sNhrtFLLofcjkGC2MoShB3k,2521
117
+ mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py,sha256=6DOoUJQcjitMf1ydGtm0jEauYjAi7i_L-oW-EgF3FME,2552
117
118
  mx_bluesky/common/experiment_plans/inner_plans/write_sample_status.py,sha256=iRgp49666zSUMDijjqQyHuxj84ID5mbQ2yCRjMD2ZIY,1305
118
119
  mx_bluesky/common/external_interaction/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
119
120
  mx_bluesky/common/external_interaction/config_server.py,sha256=9kik1dO0n6o3D3_ohIxb4JmrXf5U7lkZV6ovvV-tjpQ,6549
@@ -123,8 +124,8 @@ mx_bluesky/common/external_interaction/alerting/log_based_service.py,sha256=KCTU
123
124
  mx_bluesky/common/external_interaction/callbacks/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
125
  mx_bluesky/common/external_interaction/callbacks/common/abstract_event.py,sha256=iBj4WNK5ikieZzTePBZ9AEu6ehlnpew1nDK3ONJqibI,2093
125
126
  mx_bluesky/common/external_interaction/callbacks/common/grid_detection_callback.py,sha256=m4b-LDVynkPVzpd3MzdrBQD4CZJwexIkM-_J44dbhD0,5093
126
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py,sha256=Df7wclsKLmKr97JfOZAA9qBoG9JtWwLnTyl5zS3kyOU,9482
127
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py,sha256=Q5RgYNLSyXvqVTHJsafwc732ODOvOe607U72yRknOj8,2583
127
+ mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py,sha256=gL3EIy_cDycpuLoOAfQ4xJUTOFnnUxWzCazikDuwvXw,9564
128
+ mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py,sha256=Tdj2jVxTriHoU75uNheD2uq-MFlTG1voSjA2i26tvCE,2637
128
129
  mx_bluesky/common/external_interaction/callbacks/common/log_uid_tag_callback.py,sha256=pfZxQfS9SnXep3F2YAPptDX5bjjWvbXtgy5fINfsoTU,626
129
130
  mx_bluesky/common/external_interaction/callbacks/common/plan_reactive_callback.py,sha256=LWV-OoUKCg12TyVQScToPTEUmKh9aywrHU00u4gJqeU,4089
130
131
  mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py,sha256=4_125UmckEuZE9UhrP3qdF7j2rYkydHvrGm5FQhgKsk,4181
@@ -135,8 +136,8 @@ mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py,s
135
136
  mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_mapping.py,sha256=yElqODhPm2HZlpF7vNOX0SQNjwJ_m8kNMS-c_cp4KUU,1163
136
137
  mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py,sha256=QCjGzKUKv2jVOLmqd1nEK22TKd42VOCOHF6xbI787hc,4717
137
138
  mx_bluesky/common/external_interaction/ispyb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
- mx_bluesky/common/external_interaction/ispyb/data_model.py,sha256=4f60-Fl9irQpDgXbaZKja3w53hJF0SPSy5vqeCMvKt4,2920
139
- mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py,sha256=X5er8xNg69Li0onhu7QXv9OOg1d8JnqpfgNcKcdxcVo,11676
139
+ mx_bluesky/common/external_interaction/ispyb/data_model.py,sha256=-covQl9zNfHG9_jljgBaRugeVidccnNGKfnshHF_U8I,2991
140
+ mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py,sha256=GM2gXG6fsak6kQlJsW-v4tZz_1BI-WgFNbFvSt-d24s,11756
140
141
  mx_bluesky/common/external_interaction/ispyb/ispyb_store.py,sha256=sMVCbquk_DJBGxumj5ENjVpUDXBqqQ-mrXnBoR2QLfM,8023
141
142
  mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py,sha256=zHZvzL0u6nvaY8CrqoYRDWqmRIczqWq2TwM0lDAO-RI,307
142
143
  mx_bluesky/common/external_interaction/nexus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -144,7 +145,7 @@ mx_bluesky/common/external_interaction/nexus/nexus_utils.py,sha256=EXHKd6Kc6J7Ck
144
145
  mx_bluesky/common/external_interaction/nexus/write_nexus.py,sha256=PAc-vuywgLCo5AoOs-bQNS5i_lM3qSSax4nvwSgyAMY,4067
145
146
  mx_bluesky/common/parameters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
146
147
  mx_bluesky/common/parameters/components.py,sha256=v7FHSsvpCLqC97Lama9DjkZxUDnTLt1ljjXd-6Yq00Y,8653
147
- mx_bluesky/common/parameters/constants.py,sha256=ZkmpyXjrFy1OZlVvXlAUA2ADg-jPwJeZJHFrL7uG_KE,5245
148
+ mx_bluesky/common/parameters/constants.py,sha256=D8sm-e8bGXXWBf_QVVbGcg7GVK_GYUD9UUcrL5yaWlQ,5303
148
149
  mx_bluesky/common/parameters/device_composites.py,sha256=gyCcryP6nzgGtEQ6x_oU3mALbk3a7jixxJZogV2AZxc,2397
149
150
  mx_bluesky/common/parameters/gridscan.py,sha256=OQkzrDsEKEjTvCI9LhqPe_B2jPNCjRM09AOwgdyECt8,7652
150
151
  mx_bluesky/common/preprocessors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -160,8 +161,8 @@ mx_bluesky/common/utils/utils.py,sha256=2H6h5DJjI8rRFIOfOXR4TxVpmx0-NYa5oqnBmU9L
160
161
  mx_bluesky/hyperion/__init__.py,sha256=f4E8wInL1Ll4eeFtAiyKmipOBTPlUtKmVK-m_LOQG4M,35
161
162
  mx_bluesky/hyperion/__main__.py,sha256=0S8Izf_u8uuY8In3aLG4GWFCJWewMP3qCfW_xevwXbk,6863
162
163
  mx_bluesky/hyperion/baton_handler.py,sha256=qZzHWUay_hyl1XLJfk1zN-Ao5zh5PFJNzXip9O54vmY,10893
163
- mx_bluesky/hyperion/plan_runner.py,sha256=If2XodutzRDQYu3KQFtLsWLOfxx6x4pMegBgtnqRNDI,2816
164
- mx_bluesky/hyperion/plan_runner_api.py,sha256=Kq-UyaI6q8eU98odTLBk2RoTiEJ9s7OqYo73k_ep9w4,1296
164
+ mx_bluesky/hyperion/plan_runner.py,sha256=ueU6ZLZUzdLtH5gTI94j6grO7BUCUKX7aq-iJSA_v64,4257
165
+ mx_bluesky/hyperion/plan_runner_api.py,sha256=UeCZh941ed965u9fHhb7tzIu3N_7D4rqwc7QCTJ6Ygc,1758
165
166
  mx_bluesky/hyperion/runner.py,sha256=YSdHgtAmMitHfooDwicA9mLhav457MGzLijlhFYeDCo,7167
166
167
  mx_bluesky/hyperion/device_setup_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
168
  mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py,sha256=ciNdz_r9XGvghehpejdziL-aMw60oUsIJdVR3yz3nOo,5010
@@ -170,7 +171,7 @@ mx_bluesky/hyperion/device_setup_plans/setup_zebra.py,sha256=dOfBQMibyH3CjSh_m5R
170
171
  mx_bluesky/hyperion/device_setup_plans/utils.py,sha256=XlbHaIAnuCyHY5PmutiCf_j9MmFvITcmURA9yXfXD1o,425
171
172
  mx_bluesky/hyperion/experiment_plans/__init__.py,sha256=dJjwLk0EQP-1hKhbs8aRxTF_LxUXgB7kcgDlaP-tMnk,787
172
173
  mx_bluesky/hyperion/experiment_plans/experiment_registry.py,sha256=L7nMBaGkP3c1Fq80osYmxPEBsEtGzP2AfAYsUu33gKs,1706
173
- mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py,sha256=JhvwqahXO1ZASgCiEEDKRjV0ui8Dqv6lG9UQJd81MeM,5988
174
+ mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py,sha256=cH7tW1sOCfz3q8ZduySJc9Ay9qMwMObWHhshlUv3-_g,5948
174
175
  mx_bluesky/hyperion/experiment_plans/hyperion_grid_detect_then_xray_centre_plan.py,sha256=e4w4226ONSGQF2dnXzxOfcJ9i57CZIJrqQ1YCLlaBNo,2153
175
176
  mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py,sha256=UIt2dRNv2s3gWx0jNiEFDsTQZ_Hqnv2NHC3sw8AJhsg,7949
176
177
  mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py,sha256=9M65cboRt5FR0V2sOjjyq6eLXA0L6xnSeXFzLpW67zw,16169
@@ -179,14 +180,14 @@ mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py,sha256=jq_b
179
180
  mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py,sha256=SB_dRsRKFW7hkSXSQR-wcN_h0-5_wvKs_eklBrLLRBA,6998
180
181
  mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py,sha256=mt2BkEaHcJtfENyiET0pRtUR20hnvxM_zeTvdO5ffoc,16189
181
182
  mx_bluesky/hyperion/experiment_plans/set_energy_plan.py,sha256=m0MmiHRS0JlpakyccDbI63kYts_FR_RnUCBZ1J-acJ4,2653
182
- mx_bluesky/hyperion/experiment_plans/udc_default_state.py,sha256=oyaxD_FHNwx1FUgAYP4h26tuqxE34zm3WefyiRhDJSI,6333
183
+ mx_bluesky/hyperion/experiment_plans/udc_default_state.py,sha256=pzwRQdid3a2TAr_CUFAzSfNNWVlmiACvKCkE6wntn1Q,6582
183
184
  mx_bluesky/hyperion/external_interaction/__init__.py,sha256=95DwXDmKsx36RgAL-AtLZl2LQoLPKbzeYdlkkP_4Coc,559
184
185
  mx_bluesky/hyperion/external_interaction/agamemnon.py,sha256=Eumu2fXdW_t49ms1CTM0aN2CiagdDXrvmVuim2CyAfU,12034
185
186
  mx_bluesky/hyperion/external_interaction/config_server.py,sha256=4QIcx_3U4PJfPA9UrGEybJJpd6sTejsdhmDXqUoW00o,498
186
187
  mx_bluesky/hyperion/external_interaction/alerting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
187
188
  mx_bluesky/hyperion/external_interaction/alerting/constants.py,sha256=8wE_MDF8vOqomQ6SBiwZKb1W4NRO_hmrBLVfLVnKdSg,170
188
189
  mx_bluesky/hyperion/external_interaction/callbacks/__init__.py,sha256=1XHaxDljMveu_DYIlk7n963gHffyC6r4C_RhF6HA-N8,283
189
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py,sha256=4AIBtsfgdpffWAgtymEE9wlZaRxWZiFNlmSZV8QTXIE,6827
190
+ mx_bluesky/hyperion/external_interaction/callbacks/__main__.py,sha256=fQZDT0dkMs_XYhKOZw-VyQDvSAzcC20X7Lk5pIbykUE,7671
190
191
  mx_bluesky/hyperion/external_interaction/callbacks/alert_on_container_change.py,sha256=54RU20RuwKHYwB6DtAc0aWg6hz3TXFhwDzTmSC2XYVE,2689
191
192
  mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py,sha256=ee1ZIJGp8RQakMDYRfflXjSwi-UgxqdZNkZ1azBIDGQ,11705
192
193
  mx_bluesky/hyperion/external_interaction/callbacks/robot_actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -199,19 +200,19 @@ mx_bluesky/hyperion/parameters/__init__.py,sha256=kf2wfcILBUBpT0tJ8-W39BywQUkn67
199
200
  mx_bluesky/hyperion/parameters/cli.py,sha256=I-NY3Kt3la5HNUB4qRA6NtuxbJSr78yx-sM_cRx_pY4,1514
200
201
  mx_bluesky/hyperion/parameters/components.py,sha256=eIUEcFNqcEad21IThSDatoX-NRa9GdfBOwt6ZUwb88U,292
201
202
  mx_bluesky/hyperion/parameters/constants.py,sha256=VfJmT5TIk5P_f_NC93FmJhQkPmKutP69fKEKQG7e63w,2681
202
- mx_bluesky/hyperion/parameters/device_composites.py,sha256=okfzsWC0eB60DQ5OVRYgTTM6wRCUlYIia7ieTEzj440,2223
203
+ mx_bluesky/hyperion/parameters/device_composites.py,sha256=QROUpZJY2YRLNDGhgyn37cibMoMVUcY3N_VNsCFNNiA,2294
203
204
  mx_bluesky/hyperion/parameters/gridscan.py,sha256=dnK2veiDFfW4U02A4MTzODu0TJPZk-hE_dTCQnb3tSU,3916
204
205
  mx_bluesky/hyperion/parameters/load_centre_collect.py,sha256=8dlKwb7WmgDeohQ9QsdMWQMMM73EaC2cZ0wKg6vOP60,3727
205
206
  mx_bluesky/hyperion/parameters/robot_load.py,sha256=kZRBzsw_nQKCq1FfnAk_dDzHoSgDKKkShcVP9GPv5V8,844
206
207
  mx_bluesky/hyperion/parameters/rotation.py,sha256=0QNov3jykC__iIHMxdTq3znBsKLyQGk-vzSVMf7rSyA,7360
207
208
  mx_bluesky/hyperion/resources/panda/panda-gridscan.yaml,sha256=mhLBJTSjHCkM9F6mjtqbhNmmrV8qSctbCUfhb0q7pYo,28085
208
209
  mx_bluesky/hyperion/utils/__init__.py,sha256=f4E8wInL1Ll4eeFtAiyKmipOBTPlUtKmVK-m_LOQG4M,35
209
- mx_bluesky/hyperion/utils/context.py,sha256=VYAu1yxhDBrI98ul7UErotuquF64s1EDHtqPQLRpyvY,1227
210
+ mx_bluesky/hyperion/utils/context.py,sha256=3mXVpWnuHkZz37Fa-VsfbF_RZxIVGERlyGHL0rWxWgE,1237
210
211
  mx_bluesky/phase1_zebra/__init__.py,sha256=Edhhn2L9MVXnjJhyD5_yKQVUDo7XW98rvuT7dlzIn58,132
211
212
  mx_bluesky/phase1_zebra/device_setup_plans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
212
- mx_bluesky-1.5.12.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
213
- mx_bluesky-1.5.12.dist-info/METADATA,sha256=Yzzq6mi-9l0UJrPx0Xc3KEbA6vlulohk_J31l7gxnQ0,17539
214
- mx_bluesky-1.5.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
215
- mx_bluesky-1.5.12.dist-info/entry_points.txt,sha256=HgVtwgWoMRn9-X6rxCcSY3Jz_paspJTIlc-t2NFzWpo,409
216
- mx_bluesky-1.5.12.dist-info/top_level.txt,sha256=S4rrzXIUef58ulf_04wn01XGZ3xeJjXs4LPEJ_xoF-I,11
217
- mx_bluesky-1.5.12.dist-info/RECORD,,
213
+ mx_bluesky-1.5.15.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
214
+ mx_bluesky-1.5.15.dist-info/METADATA,sha256=jIrDI3yinOT-Z1asYv9Z_yf_QjcojcbdH0ARAlV7pn8,17539
215
+ mx_bluesky-1.5.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
216
+ mx_bluesky-1.5.15.dist-info/entry_points.txt,sha256=HgVtwgWoMRn9-X6rxCcSY3Jz_paspJTIlc-t2NFzWpo,409
217
+ mx_bluesky-1.5.15.dist-info/top_level.txt,sha256=S4rrzXIUef58ulf_04wn01XGZ3xeJjXs4LPEJ_xoF-I,11
218
+ mx_bluesky-1.5.15.dist-info/RECORD,,