mx-bluesky 1.4.6__py3-none-any.whl → 1.4.8__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/_version.py +2 -2
- mx_bluesky/beamlines/aithre_lasershaping/__init__.py +13 -0
- mx_bluesky/beamlines/aithre_lasershaping/check_goniometer_performance.py +29 -0
- mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py +18 -0
- mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +35 -29
- mx_bluesky/beamlines/i04/thawing_plan.py +18 -3
- mx_bluesky/beamlines/i23/__init__.py +3 -0
- mx_bluesky/beamlines/i23/serial.py +71 -0
- mx_bluesky/beamlines/i24/serial/__init__.py +2 -0
- mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +12 -12
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +36 -30
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +3 -3
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +15 -66
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +8 -10
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +10 -3
- mx_bluesky/beamlines/i24/serial/log.py +9 -9
- mx_bluesky/beamlines/i24/serial/parameters/utils.py +36 -7
- mx_bluesky/beamlines/i24/serial/set_visit_directory.sh +1 -1
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +16 -17
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv_abstract.py +4 -4
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +51 -52
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +3 -2
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +9 -7
- mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +71 -11
- mx_bluesky/beamlines/i24/serial/write_nexus.py +6 -5
- mx_bluesky/{hyperion → common}/device_setup_plans/check_beamstop.py +1 -1
- mx_bluesky/{hyperion → common}/device_setup_plans/manipulate_sample.py +1 -1
- mx_bluesky/{hyperion → common}/device_setup_plans/setup_oav.py +12 -6
- mx_bluesky/common/device_setup_plans/xbpm_feedback.py +45 -0
- mx_bluesky/{hyperion → common}/experiment_plans/change_aperture_then_move_plan.py +13 -29
- mx_bluesky/{hyperion → common}/experiment_plans/oav_grid_detection_plan.py +6 -6
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +8 -9
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +1 -1
- mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py +18 -15
- mx_bluesky/{hyperion → common}/external_interaction/callbacks/sample_handling/sample_handling_callback.py +16 -4
- mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +50 -45
- mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py +2 -1
- mx_bluesky/common/external_interaction/ispyb/data_model.py +1 -0
- mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +18 -2
- mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py +4 -4
- mx_bluesky/common/external_interaction/nexus/nexus_utils.py +1 -1
- mx_bluesky/common/parameters/components.py +22 -2
- mx_bluesky/common/parameters/constants.py +6 -16
- mx_bluesky/common/parameters/gridscan.py +36 -32
- mx_bluesky/common/plans/common_flyscan_xray_centre_plan.py +316 -0
- mx_bluesky/common/plans/inner_plans/__init__ .py +0 -0
- mx_bluesky/common/plans/read_hardware.py +3 -3
- mx_bluesky/common/plans/write_sample_status.py +46 -0
- mx_bluesky/common/preprocessors/__init__.py +0 -0
- mx_bluesky/common/preprocessors/preprocessors.py +105 -0
- mx_bluesky/common/protocols/__init__.py +0 -0
- mx_bluesky/common/protocols/protocols.py +10 -0
- mx_bluesky/common/utils/log.py +15 -12
- mx_bluesky/hyperion/__main__.py +5 -24
- mx_bluesky/hyperion/baton_handler.py +84 -0
- mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +4 -4
- mx_bluesky/hyperion/device_setup_plans/setup_panda.py +5 -1
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +0 -33
- mx_bluesky/hyperion/device_setup_plans/utils.py +4 -4
- mx_bluesky/hyperion/experiment_plans/__init__.py +0 -10
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +0 -16
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +71 -88
- mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +183 -0
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +17 -8
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +29 -8
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +4 -4
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +6 -4
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +11 -3
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +9 -34
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +35 -68
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +27 -8
- mx_bluesky/hyperion/external_interaction/agamemnon.py +140 -10
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +17 -9
- mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py +259 -0
- mx_bluesky/hyperion/parameters/cli.py +2 -10
- mx_bluesky/hyperion/parameters/constants.py +0 -5
- mx_bluesky/hyperion/parameters/device_composites.py +40 -5
- mx_bluesky/hyperion/parameters/gridscan.py +9 -58
- mx_bluesky/hyperion/parameters/rotation.py +1 -5
- mx_bluesky/hyperion/utils/context.py +2 -5
- mx_bluesky/hyperion/utils/validation.py +13 -10
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/METADATA +10 -9
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/RECORD +92 -79
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/WHEEL +1 -1
- mx_bluesky/common/external_interaction/callbacks/common/aperture_change_callback.py +0 -22
- mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +0 -103
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +0 -466
- /mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/{short1-laser.png → s1l.png} +0 -0
- /mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/{short2-laser.png → s2l.png} +0 -0
- /mx_bluesky/{hyperion → common}/device_setup_plans/position_detector.py +0 -0
- /mx_bluesky/{hyperion → common}/external_interaction/callbacks/sample_handling/__init__.py +0 -0
- /mx_bluesky/common/plans/{do_fgs.py → inner_plans/do_fgs.py} +0 -0
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info/licenses}/LICENSE +0 -0
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from typing import Protocol, runtime_checkable
|
|
2
|
+
|
|
3
|
+
from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
|
|
4
|
+
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@runtime_checkable
|
|
8
|
+
class XBPMPauseDevices(Protocol):
|
|
9
|
+
xbpm_feedback: XBPMFeedback
|
|
10
|
+
attenuator: BinaryFilterAttenuator
|
mx_bluesky/common/utils/log.py
CHANGED
|
@@ -66,14 +66,15 @@ def do_default_logging_setup(
|
|
|
66
66
|
"""Configures dodal logger so that separate debug and info log files are created,
|
|
67
67
|
info logs are sent to Graylog, info logs are streamed to sys.sterr, and logs from ophyd
|
|
68
68
|
and bluesky and ophyd-async are optionally included."""
|
|
69
|
-
|
|
69
|
+
logging_path, debug_logging_path = _get_logging_dirs()
|
|
70
70
|
handlers = set_up_all_logging_handlers(
|
|
71
71
|
dodal_logger,
|
|
72
|
-
|
|
72
|
+
logging_path,
|
|
73
73
|
file_name,
|
|
74
74
|
dev_mode,
|
|
75
75
|
ERROR_LOG_BUFFER_LINES,
|
|
76
76
|
graylog_port,
|
|
77
|
+
debug_logging_path,
|
|
77
78
|
)
|
|
78
79
|
|
|
79
80
|
if integrate_all_logs:
|
|
@@ -102,8 +103,8 @@ def flush_debug_handler() -> str:
|
|
|
102
103
|
return handler.target.baseFilename
|
|
103
104
|
|
|
104
105
|
|
|
105
|
-
def
|
|
106
|
-
"""Get the
|
|
106
|
+
def _get_logging_dirs() -> tuple[Path, Path]:
|
|
107
|
+
"""Get the paths to write the mx_bluesky log files to.
|
|
107
108
|
|
|
108
109
|
Log location can be specified in the LOG_DIR environment variable, otherwise MX bluesky logs are written to 'dls_sw/ixx/logs/bluesky'.
|
|
109
110
|
This directory will be created if it is not found
|
|
@@ -111,18 +112,20 @@ def _get_logging_dir() -> Path:
|
|
|
111
112
|
Logs are written to ./tmp/logs/bluesky if BEAMLINE environment variable is not found
|
|
112
113
|
|
|
113
114
|
Returns:
|
|
114
|
-
|
|
115
|
+
tuple[Path, Path]: Paths to the standard log file and to the debug log file, for the file handlers to write to
|
|
115
116
|
"""
|
|
116
117
|
|
|
117
118
|
logging_str = environ.get("LOG_DIR")
|
|
119
|
+
beamline = environ.get("BEAMLINE")
|
|
118
120
|
if logging_str:
|
|
119
121
|
logging_path = Path(logging_str)
|
|
122
|
+
debug_logging_path = logging_path
|
|
123
|
+
elif beamline:
|
|
124
|
+
logging_path = Path(f"/dls_sw/{beamline}/logs/bluesky/")
|
|
125
|
+
debug_logging_path = Path(f"/dls/tmp/{beamline}/logs/bluesky/")
|
|
120
126
|
else:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
Path(f"/dls_sw/{beamline}/logs/bluesky/")
|
|
124
|
-
if beamline
|
|
125
|
-
else Path("/tmp/logs/bluesky")
|
|
126
|
-
)
|
|
127
|
+
logging_path = Path("/tmp/logs/bluesky")
|
|
128
|
+
debug_logging_path = logging_path
|
|
127
129
|
Path.mkdir(logging_path, exist_ok=True, parents=True)
|
|
128
|
-
|
|
130
|
+
Path.mkdir(debug_logging_path, exist_ok=True, parents=True)
|
|
131
|
+
return logging_path, debug_logging_path
|
mx_bluesky/hyperion/__main__.py
CHANGED
|
@@ -16,9 +16,6 @@ from flask import Flask, request
|
|
|
16
16
|
from flask_restful import Api, Resource
|
|
17
17
|
from pydantic.dataclasses import dataclass
|
|
18
18
|
|
|
19
|
-
from mx_bluesky.common.external_interaction.callbacks.common.aperture_change_callback import (
|
|
20
|
-
ApertureChangeCallback,
|
|
21
|
-
)
|
|
22
19
|
from mx_bluesky.common.external_interaction.callbacks.common.log_uid_tag_callback import (
|
|
23
20
|
LogUidTaggingCallback,
|
|
24
21
|
)
|
|
@@ -39,6 +36,7 @@ from mx_bluesky.hyperion.experiment_plans.experiment_registry import (
|
|
|
39
36
|
PlanNotFound,
|
|
40
37
|
)
|
|
41
38
|
from mx_bluesky.hyperion.external_interaction.agamemnon import (
|
|
39
|
+
compare_params,
|
|
42
40
|
update_params_from_agamemnon,
|
|
43
41
|
)
|
|
44
42
|
from mx_bluesky.hyperion.parameters.cli import parse_cli_args
|
|
@@ -84,18 +82,15 @@ class BlueskyRunner:
|
|
|
84
82
|
self,
|
|
85
83
|
RE: RunEngine,
|
|
86
84
|
context: BlueskyContext,
|
|
87
|
-
skip_startup_connection=False,
|
|
88
85
|
) -> None:
|
|
89
86
|
self.command_queue: Queue[Command] = Queue()
|
|
90
87
|
self.current_status: StatusAndMessage = StatusAndMessage(Status.IDLE)
|
|
91
88
|
self.last_run_aborted: bool = False
|
|
92
|
-
self.aperture_change_callback = ApertureChangeCallback()
|
|
93
89
|
self.logging_uid_tag_callback = LogUidTaggingCallback()
|
|
94
90
|
self.context: BlueskyContext
|
|
95
91
|
|
|
96
92
|
self.RE = RE
|
|
97
93
|
self.context = context
|
|
98
|
-
RE.subscribe(self.aperture_change_callback)
|
|
99
94
|
RE.subscribe(self.logging_uid_tag_callback)
|
|
100
95
|
|
|
101
96
|
LOGGER.info("Connecting to external callback ZMQ proxy...")
|
|
@@ -105,12 +100,6 @@ class BlueskyRunner:
|
|
|
105
100
|
if VERBOSE_EVENT_LOGGING:
|
|
106
101
|
RE.subscribe(VerbosePlanExecutionLoggingCallback())
|
|
107
102
|
|
|
108
|
-
self.skip_startup_connection = skip_startup_connection
|
|
109
|
-
if not self.skip_startup_connection:
|
|
110
|
-
LOGGER.info("Initialising dodal devices...")
|
|
111
|
-
for plan_name in PLAN_REGISTRY:
|
|
112
|
-
PLAN_REGISTRY[plan_name]["setup"](context)
|
|
113
|
-
|
|
114
103
|
def start(
|
|
115
104
|
self,
|
|
116
105
|
experiment: Callable,
|
|
@@ -175,10 +164,7 @@ class BlueskyRunner:
|
|
|
175
164
|
with TRACER.start_span("do_run"):
|
|
176
165
|
self.RE(command.experiment(command.devices, command.parameters))
|
|
177
166
|
|
|
178
|
-
self.current_status = StatusAndMessage(
|
|
179
|
-
Status.IDLE,
|
|
180
|
-
self.aperture_change_callback.last_selected_aperture,
|
|
181
|
-
)
|
|
167
|
+
self.current_status = StatusAndMessage(Status.IDLE)
|
|
182
168
|
|
|
183
169
|
self.last_run_aborted = False
|
|
184
170
|
except WarningException as exception:
|
|
@@ -212,6 +198,7 @@ def compose_start_args(context: BlueskyContext, plan_name: str, action: Actions)
|
|
|
212
198
|
try:
|
|
213
199
|
parameters = experiment_internal_param_type(**json.loads(request.data))
|
|
214
200
|
parameters = update_params_from_agamemnon(parameters)
|
|
201
|
+
compare_params(parameters)
|
|
215
202
|
if parameters.model_extra:
|
|
216
203
|
raise ValueError(f"Extra fields not allowed {parameters.model_extra}")
|
|
217
204
|
except Exception as e:
|
|
@@ -284,15 +271,11 @@ class FlushLogs(Resource):
|
|
|
284
271
|
def create_app(
|
|
285
272
|
test_config=None,
|
|
286
273
|
RE: RunEngine = RunEngine({}),
|
|
287
|
-
skip_startup_connection: bool = False,
|
|
288
274
|
) -> tuple[Flask, BlueskyRunner]:
|
|
289
|
-
context = setup_context(
|
|
290
|
-
wait_for_connection=not skip_startup_connection,
|
|
291
|
-
)
|
|
275
|
+
context = setup_context()
|
|
292
276
|
runner = BlueskyRunner(
|
|
293
277
|
RE,
|
|
294
278
|
context=context,
|
|
295
|
-
skip_startup_connection=skip_startup_connection,
|
|
296
279
|
)
|
|
297
280
|
app = Flask(__name__)
|
|
298
281
|
if test_config:
|
|
@@ -322,9 +305,7 @@ def create_targets():
|
|
|
322
305
|
CONST.LOG_FILE_NAME, CONST.GRAYLOG_PORT, dev_mode=args.dev_mode
|
|
323
306
|
)
|
|
324
307
|
LOGGER.info(f"Hyperion launched with args:{argv}")
|
|
325
|
-
app, runner = create_app(
|
|
326
|
-
skip_startup_connection=args.skip_startup_connection,
|
|
327
|
-
)
|
|
308
|
+
app, runner = create_app()
|
|
328
309
|
return app, runner, hyperion_port, args.dev_mode
|
|
329
310
|
|
|
330
311
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from bluesky import plan_stubs as bps
|
|
2
|
+
from bluesky import preprocessors as bpp
|
|
3
|
+
from dodal.devices.baton import Baton
|
|
4
|
+
|
|
5
|
+
from mx_bluesky.common.utils.exceptions import WarningException
|
|
6
|
+
from mx_bluesky.hyperion.experiment_plans.load_centre_collect_full_plan import (
|
|
7
|
+
LoadCentreCollectComposite,
|
|
8
|
+
load_centre_collect_full,
|
|
9
|
+
)
|
|
10
|
+
from mx_bluesky.hyperion.external_interaction.agamemnon import (
|
|
11
|
+
create_parameters_from_agamemnon,
|
|
12
|
+
)
|
|
13
|
+
from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
|
|
14
|
+
|
|
15
|
+
HYPERION_USER = "Hyperion"
|
|
16
|
+
NO_USER = "None"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def wait_for_hyperion_requested(baton: Baton):
|
|
20
|
+
SLEEP_PER_CHECK = 0.1
|
|
21
|
+
while True:
|
|
22
|
+
requested_user = yield from bps.rd(baton.requested_user)
|
|
23
|
+
if requested_user == HYPERION_USER:
|
|
24
|
+
break
|
|
25
|
+
yield from bps.sleep(SLEEP_PER_CHECK)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def ignore_sample_errors(exception: Exception):
|
|
29
|
+
yield from bps.null()
|
|
30
|
+
# For sample errors we want to continue the loop
|
|
31
|
+
if not isinstance(exception, WarningException):
|
|
32
|
+
raise exception
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def main_hyperion_loop(baton: Baton, composite: LoadCentreCollectComposite):
|
|
36
|
+
requested_user = yield from bps.rd(baton.requested_user)
|
|
37
|
+
while requested_user == HYPERION_USER:
|
|
38
|
+
|
|
39
|
+
def inner_loop():
|
|
40
|
+
parameters: LoadCentreCollect | None = create_parameters_from_agamemnon() # type: ignore # not complete until https://github.com/DiamondLightSource/mx-bluesky/issues/773
|
|
41
|
+
if parameters:
|
|
42
|
+
yield from load_centre_collect_full(composite, parameters)
|
|
43
|
+
else:
|
|
44
|
+
yield from bps.mv(baton.requested_user, NO_USER)
|
|
45
|
+
|
|
46
|
+
yield from bpp.contingency_wrapper(
|
|
47
|
+
inner_loop(), except_plan=ignore_sample_errors, auto_raise=False
|
|
48
|
+
)
|
|
49
|
+
requested_user = yield from bps.rd(baton.requested_user)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def move_to_default_state():
|
|
53
|
+
# To be filled in in https://github.com/DiamondLightSource/mx-bluesky/issues/396
|
|
54
|
+
yield from bps.null()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def run_udc_when_requested(baton: Baton, composite: LoadCentreCollectComposite):
|
|
58
|
+
"""This will wait for the baton to be handed to hyperion and then run through the
|
|
59
|
+
UDC queue from agamemnon until:
|
|
60
|
+
1. There are no more instructions from agamemnon
|
|
61
|
+
2. There is an error on the beamline
|
|
62
|
+
3. The baton is requested by another party
|
|
63
|
+
|
|
64
|
+
In the case of 1. or 2. hyperion will immediately release the baton. In the case of
|
|
65
|
+
3. the baton will be released after the next collection has finished."""
|
|
66
|
+
|
|
67
|
+
yield from wait_for_hyperion_requested(baton)
|
|
68
|
+
yield from bps.abs_set(baton.current_user, HYPERION_USER)
|
|
69
|
+
|
|
70
|
+
def default_state_then_collect():
|
|
71
|
+
yield from move_to_default_state()
|
|
72
|
+
yield from main_hyperion_loop(baton, composite)
|
|
73
|
+
|
|
74
|
+
def release_baton():
|
|
75
|
+
# If hyperion has given up the baton itself we need to also release requested
|
|
76
|
+
# user so that hyperion doesn't think we're requested again
|
|
77
|
+
requested_user = yield from bps.rd(baton.requested_user)
|
|
78
|
+
if requested_user == HYPERION_USER:
|
|
79
|
+
yield from bps.abs_set(baton.requested_user, NO_USER)
|
|
80
|
+
yield from bps.abs_set(baton.current_user, NO_USER)
|
|
81
|
+
|
|
82
|
+
yield from bpp.contingency_wrapper(
|
|
83
|
+
default_state_then_collect(), final_plan=release_baton
|
|
84
|
+
)
|
|
@@ -6,7 +6,7 @@ from dodal.devices.focusing_mirror import (
|
|
|
6
6
|
MirrorStripe,
|
|
7
7
|
MirrorVoltages,
|
|
8
8
|
)
|
|
9
|
-
from dodal.devices.undulator_dcm import UndulatorDCM
|
|
9
|
+
from dodal.devices.i03.undulator_dcm import UndulatorDCM
|
|
10
10
|
from dodal.devices.util.adjuster_plans import lookup_table_adjuster
|
|
11
11
|
from dodal.devices.util.lookup_tables import (
|
|
12
12
|
linear_interpolation_lut,
|
|
@@ -102,7 +102,7 @@ def adjust_dcm_pitch_roll_vfm_from_lut(
|
|
|
102
102
|
dcm = undulator_dcm.dcm_ref()
|
|
103
103
|
LOGGER.info(f"Adjusting DCM and VFM for {energy_kev} keV")
|
|
104
104
|
d_spacing_a: float = yield from bps.rd(
|
|
105
|
-
undulator_dcm.dcm_ref().
|
|
105
|
+
undulator_dcm.dcm_ref().crystal_metadata_d_spacing_a
|
|
106
106
|
)
|
|
107
107
|
bragg_deg = energy_to_bragg_angle(energy_kev, d_spacing_a)
|
|
108
108
|
LOGGER.info(f"Target Bragg angle = {bragg_deg} degrees")
|
|
@@ -110,7 +110,7 @@ def adjust_dcm_pitch_roll_vfm_from_lut(
|
|
|
110
110
|
linear_interpolation_lut(
|
|
111
111
|
*parse_lookup_table(undulator_dcm.pitch_energy_table_path)
|
|
112
112
|
),
|
|
113
|
-
dcm.pitch_in_mrad,
|
|
113
|
+
dcm.xtal_1.pitch_in_mrad,
|
|
114
114
|
bragg_deg,
|
|
115
115
|
)
|
|
116
116
|
yield from dcm_pitch_adjuster(DCM_GROUP)
|
|
@@ -122,7 +122,7 @@ def adjust_dcm_pitch_roll_vfm_from_lut(
|
|
|
122
122
|
linear_interpolation_lut(
|
|
123
123
|
*parse_lookup_table(undulator_dcm.roll_energy_table_path)
|
|
124
124
|
),
|
|
125
|
-
dcm.roll_in_mrad,
|
|
125
|
+
dcm.xtal_1.roll_in_mrad,
|
|
126
126
|
bragg_deg,
|
|
127
127
|
)
|
|
128
128
|
yield from dcm_roll_adjuster(DCM_GROUP)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
from enum import Enum
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import cast
|
|
4
5
|
|
|
5
6
|
import bluesky.plan_stubs as bps
|
|
6
7
|
from bluesky.utils import MsgGenerator
|
|
7
8
|
from dodal.common.beamlines.beamline_utils import get_path_provider
|
|
9
|
+
from dodal.common.types import UpdatingPathProvider
|
|
8
10
|
from dodal.devices.fast_grid_scan import PandAGridScanParams
|
|
9
11
|
from dodal.devices.smargon import Smargon
|
|
10
12
|
from ophyd_async.fastcs.panda import (
|
|
@@ -222,6 +224,8 @@ def set_panda_directory(panda_directory: Path) -> MsgGenerator:
|
|
|
222
224
|
suffix = datetime.now().strftime("_%Y%m%d%H%M%S")
|
|
223
225
|
|
|
224
226
|
async def set_panda_dir():
|
|
225
|
-
await get_path_provider().update(
|
|
227
|
+
await cast(UpdatingPathProvider, get_path_provider()).update(
|
|
228
|
+
directory=panda_directory, suffix=suffix
|
|
229
|
+
)
|
|
226
230
|
|
|
227
231
|
yield from bps.wait_for([set_panda_dir])
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
|
-
from functools import wraps
|
|
3
|
-
|
|
4
1
|
import bluesky.plan_stubs as bps
|
|
5
|
-
import bluesky.preprocessors as bpp
|
|
6
2
|
from bluesky.utils import MsgGenerator
|
|
7
3
|
from dodal.devices.zebra.zebra import (
|
|
8
4
|
ArmDemand,
|
|
@@ -21,31 +17,6 @@ from mx_bluesky.common.utils.log import LOGGER
|
|
|
21
17
|
ZEBRA_STATUS_TIMEOUT = 30
|
|
22
18
|
|
|
23
19
|
|
|
24
|
-
def bluesky_retry(func: Callable):
|
|
25
|
-
"""Decorator that will retry the decorated plan if it fails.
|
|
26
|
-
|
|
27
|
-
Use this with care as it knows nothing about the state of the world when things fail.
|
|
28
|
-
If it is possible that your plan fails when the beamline is in a transient state that
|
|
29
|
-
the plan could not act on do not use this decorator without doing some more intelligent
|
|
30
|
-
clean up.
|
|
31
|
-
|
|
32
|
-
You should avoid using this decorator often in general production as it hides errors,
|
|
33
|
-
instead it should be used only for debugging these underlying errors.
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
@wraps(func)
|
|
37
|
-
def newfunc(*args, **kwargs):
|
|
38
|
-
def log_and_retry(exception):
|
|
39
|
-
LOGGER.error(f"Function {func.__name__} failed with {exception}, retrying")
|
|
40
|
-
yield from func(*args, **kwargs)
|
|
41
|
-
|
|
42
|
-
yield from bpp.contingency_wrapper(
|
|
43
|
-
func(*args, **kwargs), except_plan=log_and_retry, auto_raise=False
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
return newfunc
|
|
47
|
-
|
|
48
|
-
|
|
49
20
|
def arm_zebra(zebra: Zebra):
|
|
50
21
|
yield from bps.abs_set(zebra.pc.arm, ArmDemand.ARM, wait=True)
|
|
51
22
|
|
|
@@ -105,7 +76,6 @@ def configure_zebra_and_shutter_for_auto_shutter(
|
|
|
105
76
|
yield from set_shutter_auto_input(zebra, input, group=group)
|
|
106
77
|
|
|
107
78
|
|
|
108
|
-
@bluesky_retry
|
|
109
79
|
def setup_zebra_for_rotation(
|
|
110
80
|
zebra: Zebra,
|
|
111
81
|
zebra_shutter: ZebraShutter,
|
|
@@ -185,7 +155,6 @@ def setup_zebra_for_rotation(
|
|
|
185
155
|
yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
|
|
186
156
|
|
|
187
157
|
|
|
188
|
-
@bluesky_retry
|
|
189
158
|
def setup_zebra_for_gridscan(
|
|
190
159
|
zebra: Zebra,
|
|
191
160
|
zebra_shutter: ZebraShutter,
|
|
@@ -215,7 +184,6 @@ def setup_zebra_for_gridscan(
|
|
|
215
184
|
yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
|
|
216
185
|
|
|
217
186
|
|
|
218
|
-
@bluesky_retry
|
|
219
187
|
def tidy_up_zebra_after_gridscan(
|
|
220
188
|
zebra: Zebra,
|
|
221
189
|
zebra_shutter: ZebraShutter,
|
|
@@ -236,7 +204,6 @@ def tidy_up_zebra_after_gridscan(
|
|
|
236
204
|
yield from bps.wait(group, timeout=ZEBRA_STATUS_TIMEOUT)
|
|
237
205
|
|
|
238
206
|
|
|
239
|
-
@bluesky_retry
|
|
240
207
|
def setup_zebra_for_panda_flyscan(
|
|
241
208
|
zebra: Zebra,
|
|
242
209
|
zebra_shutter: ZebraShutter,
|
|
@@ -3,16 +3,16 @@ from collections.abc import Generator
|
|
|
3
3
|
from bluesky import plan_stubs as bps
|
|
4
4
|
from bluesky import preprocessors as bpp
|
|
5
5
|
from bluesky.utils import Msg
|
|
6
|
-
from dodal.devices.dcm import DCM
|
|
7
6
|
from dodal.devices.detector import (
|
|
8
7
|
DetectorParams,
|
|
9
8
|
)
|
|
10
9
|
from dodal.devices.detector.detector_motion import DetectorMotion, ShutterState
|
|
11
10
|
from dodal.devices.eiger import EigerDetector
|
|
12
|
-
from dodal.devices.i03
|
|
11
|
+
from dodal.devices.i03 import Beamstop
|
|
12
|
+
from dodal.devices.i03.dcm import DCM
|
|
13
13
|
|
|
14
|
-
from mx_bluesky.
|
|
15
|
-
from mx_bluesky.
|
|
14
|
+
from mx_bluesky.common.device_setup_plans.check_beamstop import check_beamstop
|
|
15
|
+
from mx_bluesky.common.device_setup_plans.position_detector import (
|
|
16
16
|
set_detector_z_position,
|
|
17
17
|
set_shutter,
|
|
18
18
|
)
|
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
The __all__ list in here are the plans that are externally available from outside Hyperion.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
|
|
7
|
-
flyscan_xray_centre,
|
|
8
|
-
)
|
|
9
6
|
from mx_bluesky.hyperion.experiment_plans.grid_detect_then_xray_centre_plan import (
|
|
10
7
|
grid_detect_then_xray_centre,
|
|
11
8
|
)
|
|
@@ -15,20 +12,13 @@ from mx_bluesky.hyperion.experiment_plans.load_centre_collect_full_plan import (
|
|
|
15
12
|
from mx_bluesky.hyperion.experiment_plans.pin_centre_then_xray_centre_plan import (
|
|
16
13
|
pin_tip_centre_then_xray_centre,
|
|
17
14
|
)
|
|
18
|
-
from mx_bluesky.hyperion.experiment_plans.robot_load_then_centre_plan import (
|
|
19
|
-
robot_load_then_centre,
|
|
20
|
-
)
|
|
21
15
|
from mx_bluesky.hyperion.experiment_plans.rotation_scan_plan import (
|
|
22
16
|
multi_rotation_scan,
|
|
23
|
-
rotation_scan,
|
|
24
17
|
)
|
|
25
18
|
|
|
26
19
|
__all__ = [
|
|
27
|
-
"flyscan_xray_centre",
|
|
28
20
|
"grid_detect_then_xray_centre",
|
|
29
|
-
"rotation_scan",
|
|
30
21
|
"pin_tip_centre_then_xray_centre",
|
|
31
22
|
"multi_rotation_scan",
|
|
32
|
-
"robot_load_then_centre",
|
|
33
23
|
"load_centre_collect_full",
|
|
34
24
|
]
|
|
@@ -3,13 +3,11 @@ from __future__ import annotations
|
|
|
3
3
|
from collections.abc import Callable
|
|
4
4
|
from typing import TypedDict
|
|
5
5
|
|
|
6
|
-
import mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan as flyscan_xray_centre_plan
|
|
7
6
|
import mx_bluesky.hyperion.experiment_plans.rotation_scan_plan as rotation_scan_plan
|
|
8
7
|
from mx_bluesky.hyperion.experiment_plans import (
|
|
9
8
|
grid_detect_then_xray_centre_plan,
|
|
10
9
|
load_centre_collect_full_plan,
|
|
11
10
|
pin_centre_then_xray_centre_plan,
|
|
12
|
-
robot_load_then_centre_plan,
|
|
13
11
|
)
|
|
14
12
|
from mx_bluesky.hyperion.parameters.gridscan import (
|
|
15
13
|
GridScanWithEdgeDetect,
|
|
@@ -17,7 +15,6 @@ from mx_bluesky.hyperion.parameters.gridscan import (
|
|
|
17
15
|
PinTipCentreThenXrayCentre,
|
|
18
16
|
)
|
|
19
17
|
from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
|
|
20
|
-
from mx_bluesky.hyperion.parameters.robot_load import RobotLoadThenCentre
|
|
21
18
|
from mx_bluesky.hyperion.parameters.rotation import MultiRotationScan, RotationScan
|
|
22
19
|
|
|
23
20
|
|
|
@@ -38,31 +35,18 @@ class ExperimentRegistryEntry(TypedDict):
|
|
|
38
35
|
| MultiRotationScan
|
|
39
36
|
| PinTipCentreThenXrayCentre
|
|
40
37
|
| LoadCentreCollect
|
|
41
|
-
| RobotLoadThenCentre
|
|
42
38
|
]
|
|
43
39
|
|
|
44
40
|
|
|
45
41
|
PLAN_REGISTRY: dict[str, ExperimentRegistryEntry] = {
|
|
46
|
-
"flyscan_xray_centre": {
|
|
47
|
-
"setup": flyscan_xray_centre_plan.create_devices,
|
|
48
|
-
"param_type": HyperionSpecifiedThreeDGridScan,
|
|
49
|
-
},
|
|
50
42
|
"grid_detect_then_xray_centre": {
|
|
51
43
|
"setup": grid_detect_then_xray_centre_plan.create_devices,
|
|
52
44
|
"param_type": GridScanWithEdgeDetect,
|
|
53
45
|
},
|
|
54
|
-
"rotation_scan": {
|
|
55
|
-
"setup": rotation_scan_plan.create_devices,
|
|
56
|
-
"param_type": RotationScan,
|
|
57
|
-
},
|
|
58
46
|
"pin_tip_centre_then_xray_centre": {
|
|
59
47
|
"setup": pin_centre_then_xray_centre_plan.create_devices,
|
|
60
48
|
"param_type": PinTipCentreThenXrayCentre,
|
|
61
49
|
},
|
|
62
|
-
"robot_load_then_centre": {
|
|
63
|
-
"setup": robot_load_then_centre_plan.create_devices,
|
|
64
|
-
"param_type": RobotLoadThenCentre,
|
|
65
|
-
},
|
|
66
50
|
"multi_rotation_scan": {
|
|
67
51
|
"setup": rotation_scan_plan.create_devices,
|
|
68
52
|
"param_type": MultiRotationScan,
|