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.
- mx_bluesky/Getting started.ipynb +170 -0
- mx_bluesky/_version.py +2 -2
- mx_bluesky/beamlines/aithre_lasershaping/robot_load.py +4 -10
- mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +4 -5
- mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +5 -5
- mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py +21 -0
- mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py +1 -0
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +1 -0
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +1 -0
- mx_bluesky/common/external_interaction/ispyb/data_model.py +3 -0
- mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +4 -2
- mx_bluesky/common/parameters/constants.py +2 -0
- mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +4 -5
- mx_bluesky/hyperion/experiment_plans/udc_default_state.py +23 -11
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +48 -21
- mx_bluesky/hyperion/parameters/device_composites.py +2 -0
- mx_bluesky/hyperion/plan_runner.py +31 -0
- mx_bluesky/hyperion/plan_runner_api.py +14 -1
- mx_bluesky/hyperion/utils/context.py +2 -2
- mx_bluesky/jupyter_example.ipynb +9 -1
- {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/METADATA +3 -3
- {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/RECORD +26 -25
- {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/WHEEL +0 -0
- {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.5.12.dist-info → mx_bluesky-1.5.15.dist-info}/licenses/LICENSE +0 -0
- {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.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 5,
|
|
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}/{
|
|
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}/{
|
|
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
|
|
282
|
-
xrc_composite.
|
|
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
|
-
|
|
93
|
-
|
|
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] *
|
|
96
|
-
y_um = position_px[1] *
|
|
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)
|
|
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)
|
|
@@ -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
|
|
@@ -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
|
-
"
|
|
337
|
-
"
|
|
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
|
|
53
|
-
xrc_composite.
|
|
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
|
|
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
|
-
|
|
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.
|
|
59
|
-
cryostream_pressure = yield from bps.rd(devices.cryostream.
|
|
60
|
-
if cryostream_temp >
|
|
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 >
|
|
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=
|
|
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.
|
|
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.
|
|
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.
|
|
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,
|
|
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(
|
|
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.
|
|
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:
|
mx_bluesky/jupyter_example.ipynb
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
93
|
-
mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py,sha256=
|
|
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=
|
|
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=
|
|
127
|
-
mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py,sha256=
|
|
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
|
|
139
|
-
mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py,sha256=
|
|
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=
|
|
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=
|
|
164
|
-
mx_bluesky/hyperion/plan_runner_api.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
213
|
-
mx_bluesky-1.5.
|
|
214
|
-
mx_bluesky-1.5.
|
|
215
|
-
mx_bluesky-1.5.
|
|
216
|
-
mx_bluesky-1.5.
|
|
217
|
-
mx_bluesky-1.5.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|