mx-bluesky 1.4.8__py3-none-any.whl → 1.4.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mx_bluesky/_version.py +2 -2
- mx_bluesky/beamlines/aithre_lasershaping/__init__.py +8 -0
- mx_bluesky/beamlines/aithre_lasershaping/beamline_safe.py +36 -0
- mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py +43 -0
- mx_bluesky/beamlines/i24/serial/blueapi_config.yaml +2 -1
- mx_bluesky/beamlines/i24/serial/dcid.py +5 -5
- mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DetStage.edl +2 -2
- mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +9 -9
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +18 -3
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DetStage.edl +2 -2
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +14 -14
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +2 -2
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +23 -4
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +7 -1
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +0 -8
- mx_bluesky/common/device_setup_plans/manipulate_sample.py +5 -13
- mx_bluesky/common/external_interaction/nexus/nexus_utils.py +2 -2
- mx_bluesky/common/utils/log.py +12 -11
- mx_bluesky/hyperion/__main__.py +6 -11
- mx_bluesky/hyperion/baton_handler.py +8 -3
- mx_bluesky/hyperion/device_setup_plans/smargon.py +2 -7
- mx_bluesky/hyperion/device_setup_plans/utils.py +4 -3
- mx_bluesky/hyperion/experiment_plans/__init__.py +2 -2
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +3 -4
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +10 -0
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +40 -10
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +3 -0
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +2 -11
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +22 -25
- mx_bluesky/hyperion/external_interaction/agamemnon.py +68 -62
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +3 -3
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +6 -3
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +2 -2
- mx_bluesky/hyperion/external_interaction/config_server.py +4 -1
- mx_bluesky/hyperion/parameters/cli.py +3 -10
- mx_bluesky/hyperion/parameters/constants.py +1 -0
- mx_bluesky/hyperion/parameters/load_centre_collect.py +4 -4
- mx_bluesky/hyperion/parameters/rotation.py +9 -8
- mx_bluesky/hyperion/utils/context.py +5 -2
- mx_bluesky/hyperion/utils/validation.py +10 -17
- {mx_bluesky-1.4.8.dist-info → mx_bluesky-1.4.9.dist-info}/METADATA +4 -4
- {mx_bluesky-1.4.8.dist-info → mx_bluesky-1.4.9.dist-info}/RECORD +47 -48
- {mx_bluesky-1.4.8.dist-info → mx_bluesky-1.4.9.dist-info}/WHEEL +1 -1
- mx_bluesky/common/device_setup_plans/check_beamstop.py +0 -27
- mx_bluesky/common/external_interaction/test_config_server.py +0 -38
- {mx_bluesky-1.4.8.dist-info → mx_bluesky-1.4.9.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.4.8.dist-info → mx_bluesky-1.4.9.dist-info}/licenses/LICENSE +0 -0
- {mx_bluesky-1.4.8.dist-info → mx_bluesky-1.4.9.dist-info}/top_level.txt +0 -0
|
@@ -158,6 +158,6 @@ def create_beam_and_attenuator_parameters(
|
|
|
158
158
|
tuple[Beam, Attenuator]: Descriptions of the beam and attenuator for nexgen.
|
|
159
159
|
"""
|
|
160
160
|
return (
|
|
161
|
-
Beam(convert_eV_to_angstrom(energy_kev * 1000), flux),
|
|
162
|
-
Attenuator(transmission_fraction),
|
|
161
|
+
Beam(wavelength=convert_eV_to_angstrom(energy_kev * 1000), flux=flux),
|
|
162
|
+
Attenuator(transmission=transmission_fraction),
|
|
163
163
|
)
|
mx_bluesky/common/utils/log.py
CHANGED
|
@@ -66,7 +66,7 @@ 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
|
-
logging_path, debug_logging_path = _get_logging_dirs()
|
|
69
|
+
logging_path, debug_logging_path = _get_logging_dirs(dev_mode)
|
|
70
70
|
handlers = set_up_all_logging_handlers(
|
|
71
71
|
dodal_logger,
|
|
72
72
|
logging_path,
|
|
@@ -103,7 +103,7 @@ def flush_debug_handler() -> str:
|
|
|
103
103
|
return handler.target.baseFilename
|
|
104
104
|
|
|
105
105
|
|
|
106
|
-
def _get_logging_dirs() -> tuple[Path, Path]:
|
|
106
|
+
def _get_logging_dirs(dev_mode: bool) -> tuple[Path, Path]:
|
|
107
107
|
"""Get the paths to write the mx_bluesky log files to.
|
|
108
108
|
|
|
109
109
|
Log location can be specified in the LOG_DIR environment variable, otherwise MX bluesky logs are written to 'dls_sw/ixx/logs/bluesky'.
|
|
@@ -115,17 +115,18 @@ def _get_logging_dirs() -> tuple[Path, Path]:
|
|
|
115
115
|
tuple[Path, Path]: Paths to the standard log file and to the debug log file, for the file handlers to write to
|
|
116
116
|
"""
|
|
117
117
|
|
|
118
|
-
logging_str = environ.get("LOG_DIR")
|
|
119
118
|
beamline = environ.get("BEAMLINE")
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
logging_path = Path(f"/dls_sw/{beamline}/logs/bluesky/")
|
|
125
|
-
debug_logging_path = Path(f"/dls/tmp/{beamline}/logs/bluesky/")
|
|
119
|
+
|
|
120
|
+
if beamline and not dev_mode:
|
|
121
|
+
default_logging_str = f"/dls_sw/{beamline}/logs/bluesky/"
|
|
122
|
+
default_debug_logging_str = f"/dls/tmp/{beamline}/logs/bluesky/"
|
|
126
123
|
else:
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
default_logging_str = "/tmp/logs/bluesky"
|
|
125
|
+
default_debug_logging_str = default_logging_str
|
|
126
|
+
|
|
127
|
+
logging_path = Path(environ.get("LOG_DIR", default_logging_str))
|
|
128
|
+
debug_logging_path = Path(environ.get("DEBUG_LOG_DIR", default_debug_logging_str))
|
|
129
|
+
|
|
129
130
|
Path.mkdir(logging_path, exist_ok=True, parents=True)
|
|
130
131
|
Path.mkdir(debug_logging_path, exist_ok=True, parents=True)
|
|
131
132
|
return logging_path, debug_logging_path
|
mx_bluesky/hyperion/__main__.py
CHANGED
|
@@ -19,9 +19,6 @@ from pydantic.dataclasses import dataclass
|
|
|
19
19
|
from mx_bluesky.common.external_interaction.callbacks.common.log_uid_tag_callback import (
|
|
20
20
|
LogUidTaggingCallback,
|
|
21
21
|
)
|
|
22
|
-
from mx_bluesky.common.external_interaction.callbacks.common.logging_callback import (
|
|
23
|
-
VerbosePlanExecutionLoggingCallback,
|
|
24
|
-
)
|
|
25
22
|
from mx_bluesky.common.parameters.components import MxBlueskyParameters
|
|
26
23
|
from mx_bluesky.common.parameters.constants import Actions, Status
|
|
27
24
|
from mx_bluesky.common.utils.exceptions import WarningException
|
|
@@ -41,10 +38,9 @@ from mx_bluesky.hyperion.external_interaction.agamemnon import (
|
|
|
41
38
|
)
|
|
42
39
|
from mx_bluesky.hyperion.parameters.cli import parse_cli_args
|
|
43
40
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
41
|
+
from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
|
|
44
42
|
from mx_bluesky.hyperion.utils.context import setup_context
|
|
45
43
|
|
|
46
|
-
VERBOSE_EVENT_LOGGING: bool | None = None
|
|
47
|
-
|
|
48
44
|
|
|
49
45
|
@dataclass
|
|
50
46
|
class Command:
|
|
@@ -97,9 +93,6 @@ class BlueskyRunner:
|
|
|
97
93
|
self.publisher = Publisher(f"localhost:{CONST.CALLBACK_0MQ_PROXY_PORTS[0]}")
|
|
98
94
|
RE.subscribe(self.publisher)
|
|
99
95
|
|
|
100
|
-
if VERBOSE_EVENT_LOGGING:
|
|
101
|
-
RE.subscribe(VerbosePlanExecutionLoggingCallback())
|
|
102
|
-
|
|
103
96
|
def start(
|
|
104
97
|
self,
|
|
105
98
|
experiment: Callable,
|
|
@@ -198,7 +191,8 @@ def compose_start_args(context: BlueskyContext, plan_name: str, action: Actions)
|
|
|
198
191
|
try:
|
|
199
192
|
parameters = experiment_internal_param_type(**json.loads(request.data))
|
|
200
193
|
parameters = update_params_from_agamemnon(parameters)
|
|
201
|
-
|
|
194
|
+
if isinstance(parameters, LoadCentreCollect):
|
|
195
|
+
compare_params(parameters)
|
|
202
196
|
if parameters.model_extra:
|
|
203
197
|
raise ValueError(f"Extra fields not allowed {parameters.model_extra}")
|
|
204
198
|
except Exception as e:
|
|
@@ -271,8 +265,9 @@ class FlushLogs(Resource):
|
|
|
271
265
|
def create_app(
|
|
272
266
|
test_config=None,
|
|
273
267
|
RE: RunEngine = RunEngine({}),
|
|
268
|
+
dev_mode: bool = False,
|
|
274
269
|
) -> tuple[Flask, BlueskyRunner]:
|
|
275
|
-
context = setup_context()
|
|
270
|
+
context = setup_context(dev_mode=dev_mode)
|
|
276
271
|
runner = BlueskyRunner(
|
|
277
272
|
RE,
|
|
278
273
|
context=context,
|
|
@@ -305,7 +300,7 @@ def create_targets():
|
|
|
305
300
|
CONST.LOG_FILE_NAME, CONST.GRAYLOG_PORT, dev_mode=args.dev_mode
|
|
306
301
|
)
|
|
307
302
|
LOGGER.info(f"Hyperion launched with args:{argv}")
|
|
308
|
-
app, runner = create_app()
|
|
303
|
+
app, runner = create_app(dev_mode=args.dev_mode)
|
|
309
304
|
return app, runner, hyperion_port, args.dev_mode
|
|
310
305
|
|
|
311
306
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
|
|
1
3
|
from bluesky import plan_stubs as bps
|
|
2
4
|
from bluesky import preprocessors as bpp
|
|
3
5
|
from dodal.devices.baton import Baton
|
|
@@ -37,9 +39,12 @@ def main_hyperion_loop(baton: Baton, composite: LoadCentreCollectComposite):
|
|
|
37
39
|
while requested_user == HYPERION_USER:
|
|
38
40
|
|
|
39
41
|
def inner_loop():
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
parameter_list: Sequence[LoadCentreCollect] = (
|
|
43
|
+
create_parameters_from_agamemnon()
|
|
44
|
+
)
|
|
45
|
+
if parameter_list:
|
|
46
|
+
for parameters in parameter_list:
|
|
47
|
+
yield from load_centre_collect_full(composite, parameters)
|
|
43
48
|
else:
|
|
44
49
|
yield from bps.mv(baton.requested_user, NO_USER)
|
|
45
50
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
from bluesky import plan_stubs as bps
|
|
3
|
-
from dodal.devices.smargon import Smargon
|
|
3
|
+
from dodal.devices.smargon import CombinedMove, Smargon
|
|
4
4
|
|
|
5
5
|
from mx_bluesky.common.utils.exceptions import SampleException
|
|
6
6
|
|
|
@@ -16,10 +16,5 @@ def move_smargon_warn_on_out_of_range(
|
|
|
16
16
|
"Pin tip centring failed - pin too long/short/bent and out of range"
|
|
17
17
|
)
|
|
18
18
|
yield from bps.mv(
|
|
19
|
-
smargon
|
|
20
|
-
position[0],
|
|
21
|
-
smargon.y,
|
|
22
|
-
position[1],
|
|
23
|
-
smargon.z,
|
|
24
|
-
position[2],
|
|
19
|
+
smargon, CombinedMove(x=position[0], y=position[1], z=position[2])
|
|
25
20
|
)
|
|
@@ -8,10 +8,9 @@ from dodal.devices.detector import (
|
|
|
8
8
|
)
|
|
9
9
|
from dodal.devices.detector.detector_motion import DetectorMotion, ShutterState
|
|
10
10
|
from dodal.devices.eiger import EigerDetector
|
|
11
|
-
from dodal.devices.i03 import Beamstop
|
|
12
11
|
from dodal.devices.i03.dcm import DCM
|
|
12
|
+
from dodal.devices.mx_phase1.beamstop import Beamstop, BeamstopPositions
|
|
13
13
|
|
|
14
|
-
from mx_bluesky.common.device_setup_plans.check_beamstop import check_beamstop
|
|
15
14
|
from mx_bluesky.common.device_setup_plans.position_detector import (
|
|
16
15
|
set_detector_z_position,
|
|
17
16
|
set_shutter,
|
|
@@ -45,6 +44,9 @@ def start_preparing_data_collection_then_do_plan(
|
|
|
45
44
|
|
|
46
45
|
def wrapped_plan():
|
|
47
46
|
yield from bps.abs_set(eiger.do_arm, 1, group=group) # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
|
|
47
|
+
yield from bps.abs_set(
|
|
48
|
+
beamstop.selected_pos, BeamstopPositions.DATA_COLLECTION, group=group
|
|
49
|
+
)
|
|
48
50
|
if detector_distance_mm:
|
|
49
51
|
yield from set_detector_z_position(
|
|
50
52
|
detector_motion, detector_distance_mm, group
|
|
@@ -52,7 +54,6 @@ def start_preparing_data_collection_then_do_plan(
|
|
|
52
54
|
yield from set_shutter(detector_motion, ShutterState.OPEN, group)
|
|
53
55
|
yield from plan_to_run
|
|
54
56
|
|
|
55
|
-
yield from check_beamstop(beamstop)
|
|
56
57
|
yield from bpp.contingency_wrapper(
|
|
57
58
|
wrapped_plan(),
|
|
58
59
|
except_plan=lambda e: (yield from bps.stop(eiger)), # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
|
|
@@ -13,12 +13,12 @@ from mx_bluesky.hyperion.experiment_plans.pin_centre_then_xray_centre_plan impor
|
|
|
13
13
|
pin_tip_centre_then_xray_centre,
|
|
14
14
|
)
|
|
15
15
|
from mx_bluesky.hyperion.experiment_plans.rotation_scan_plan import (
|
|
16
|
-
|
|
16
|
+
rotation_scan,
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
__all__ = [
|
|
20
20
|
"grid_detect_then_xray_centre",
|
|
21
21
|
"pin_tip_centre_then_xray_centre",
|
|
22
|
-
"
|
|
22
|
+
"rotation_scan",
|
|
23
23
|
"load_centre_collect_full",
|
|
24
24
|
]
|
|
@@ -15,7 +15,7 @@ from mx_bluesky.hyperion.parameters.gridscan import (
|
|
|
15
15
|
PinTipCentreThenXrayCentre,
|
|
16
16
|
)
|
|
17
17
|
from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
|
|
18
|
-
from mx_bluesky.hyperion.parameters.rotation import
|
|
18
|
+
from mx_bluesky.hyperion.parameters.rotation import RotationScan
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def not_implemented():
|
|
@@ -32,7 +32,6 @@ class ExperimentRegistryEntry(TypedDict):
|
|
|
32
32
|
HyperionSpecifiedThreeDGridScan
|
|
33
33
|
| GridScanWithEdgeDetect
|
|
34
34
|
| RotationScan
|
|
35
|
-
| MultiRotationScan
|
|
36
35
|
| PinTipCentreThenXrayCentre
|
|
37
36
|
| LoadCentreCollect
|
|
38
37
|
]
|
|
@@ -47,9 +46,9 @@ PLAN_REGISTRY: dict[str, ExperimentRegistryEntry] = {
|
|
|
47
46
|
"setup": pin_centre_then_xray_centre_plan.create_devices,
|
|
48
47
|
"param_type": PinTipCentreThenXrayCentre,
|
|
49
48
|
},
|
|
50
|
-
"
|
|
49
|
+
"rotation_scan": {
|
|
51
50
|
"setup": rotation_scan_plan.create_devices,
|
|
52
|
-
"param_type":
|
|
51
|
+
"param_type": RotationScan,
|
|
53
52
|
},
|
|
54
53
|
"load_centre_collect_full": {
|
|
55
54
|
"setup": load_centre_collect_full_plan.create_devices,
|
|
@@ -49,6 +49,9 @@ from mx_bluesky.hyperion.device_setup_plans.utils import (
|
|
|
49
49
|
from mx_bluesky.hyperion.experiment_plans.hyperion_flyscan_xray_centre_plan import (
|
|
50
50
|
construct_hyperion_specific_features,
|
|
51
51
|
)
|
|
52
|
+
from mx_bluesky.hyperion.experiment_plans.oav_snapshot_plan import (
|
|
53
|
+
setup_beamline_for_OAV,
|
|
54
|
+
)
|
|
52
55
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
53
56
|
from mx_bluesky.hyperion.parameters.device_composites import (
|
|
54
57
|
GridDetectThenXRayCentreComposite,
|
|
@@ -106,6 +109,13 @@ def detect_grid_and_do_gridscan(
|
|
|
106
109
|
parameters.box_size_um,
|
|
107
110
|
)
|
|
108
111
|
|
|
112
|
+
yield from setup_beamline_for_OAV(
|
|
113
|
+
composite.smargon,
|
|
114
|
+
composite.backlight,
|
|
115
|
+
composite.aperture_scatterguard,
|
|
116
|
+
wait=True,
|
|
117
|
+
)
|
|
118
|
+
|
|
109
119
|
if parameters.selected_aperture:
|
|
110
120
|
# Start moving the aperture/scatterguard into position without moving it in
|
|
111
121
|
yield from bps.prepare(
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from collections.abc import Generator
|
|
4
|
+
|
|
3
5
|
import bluesky.plan_stubs as bps
|
|
4
6
|
import numpy as np
|
|
5
7
|
import pydantic
|
|
@@ -18,12 +20,13 @@ from mx_bluesky.hyperion.experiment_plans.robot_load_then_centre_plan import (
|
|
|
18
20
|
robot_load_then_xray_centre,
|
|
19
21
|
)
|
|
20
22
|
from mx_bluesky.hyperion.experiment_plans.rotation_scan_plan import (
|
|
21
|
-
|
|
23
|
+
RotationScan,
|
|
22
24
|
RotationScanComposite,
|
|
23
|
-
|
|
25
|
+
rotation_scan_internal,
|
|
24
26
|
)
|
|
25
27
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
26
28
|
from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
|
|
29
|
+
from mx_bluesky.hyperion.parameters.rotation import RotationScanPerSweep
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
@@ -48,6 +51,8 @@ def load_centre_collect_full(
|
|
|
48
51
|
* If X-ray centring finds a diffracting centre then move to that centre and
|
|
49
52
|
* do a collection with the specified parameters.
|
|
50
53
|
"""
|
|
54
|
+
parameters.features.update_self_from_server()
|
|
55
|
+
|
|
51
56
|
if not oav_params:
|
|
52
57
|
oav_params = OAVParameters(context="xrayCentring")
|
|
53
58
|
oav_config_file = oav_params.oav_config_json
|
|
@@ -99,21 +104,46 @@ def load_centre_collect_full(
|
|
|
99
104
|
|
|
100
105
|
multi_rotation.rotation_scans.clear()
|
|
101
106
|
|
|
107
|
+
is_alternating = parameters.features.alternate_rotation_direction
|
|
108
|
+
|
|
109
|
+
generator = rotation_scan_generator(is_alternating)
|
|
110
|
+
next(generator)
|
|
102
111
|
for location in locations_to_collect_um:
|
|
103
112
|
for rot in rotation_template:
|
|
104
|
-
combination =
|
|
105
|
-
(
|
|
106
|
-
combination.x_start_um,
|
|
107
|
-
combination.y_start_um,
|
|
108
|
-
combination.z_start_um,
|
|
109
|
-
) = location
|
|
113
|
+
combination = generator.send((rot, location))
|
|
110
114
|
multi_rotation.rotation_scans.append(combination)
|
|
111
|
-
multi_rotation =
|
|
115
|
+
multi_rotation = RotationScan.model_validate(multi_rotation)
|
|
112
116
|
|
|
113
117
|
assert (
|
|
114
118
|
multi_rotation.demand_energy_ev
|
|
115
119
|
== parameters.robot_load_then_centre.demand_energy_ev
|
|
116
120
|
), "Setting a different energy for gridscan and rotation is not supported"
|
|
117
|
-
yield from
|
|
121
|
+
yield from rotation_scan_internal(composite, multi_rotation, oav_params)
|
|
118
122
|
|
|
119
123
|
yield from plan_with_callback_subs()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def rotation_scan_generator(
|
|
127
|
+
is_alternating: bool,
|
|
128
|
+
) -> Generator[RotationScanPerSweep, tuple[RotationScanPerSweep, np.ndarray], None]:
|
|
129
|
+
scan_template, location = yield # type: ignore
|
|
130
|
+
next_rotation_direction = scan_template.rotation_direction
|
|
131
|
+
while True:
|
|
132
|
+
scan = scan_template.model_copy()
|
|
133
|
+
(
|
|
134
|
+
scan.x_start_um,
|
|
135
|
+
scan.y_start_um,
|
|
136
|
+
scan.z_start_um,
|
|
137
|
+
) = location
|
|
138
|
+
if is_alternating:
|
|
139
|
+
if next_rotation_direction != scan.rotation_direction:
|
|
140
|
+
# If originally specified direction of the current scan is different
|
|
141
|
+
# from that required, swap the start and ends.
|
|
142
|
+
start = scan.omega_start_deg
|
|
143
|
+
rotation_sign = scan.rotation_direction.multiplier
|
|
144
|
+
end = start + rotation_sign * scan.scan_width_deg
|
|
145
|
+
scan.omega_start_deg = end
|
|
146
|
+
scan.rotation_direction = next_rotation_direction
|
|
147
|
+
next_rotation_direction = next_rotation_direction.opposite
|
|
148
|
+
|
|
149
|
+
scan_template, location = yield scan
|
|
@@ -29,6 +29,7 @@ def setup_beamline_for_OAV(
|
|
|
29
29
|
backlight: Backlight,
|
|
30
30
|
aperture_scatterguard: ApertureScatterguard,
|
|
31
31
|
group=CONST.WAIT.READY_FOR_OAV,
|
|
32
|
+
wait=False,
|
|
32
33
|
):
|
|
33
34
|
max_vel = yield from bps.rd(smargon.omega.max_velocity)
|
|
34
35
|
yield from bps.abs_set(smargon.omega.velocity, max_vel, group=group)
|
|
@@ -36,6 +37,8 @@ def setup_beamline_for_OAV(
|
|
|
36
37
|
yield from bps.abs_set(
|
|
37
38
|
aperture_scatterguard.selected_aperture, ApertureValue.OUT_OF_BEAM, group=group
|
|
38
39
|
)
|
|
40
|
+
if wait:
|
|
41
|
+
yield from bps.wait(group)
|
|
39
42
|
|
|
40
43
|
|
|
41
44
|
def oav_snapshot_plan(
|
|
@@ -19,7 +19,7 @@ from dodal.devices.i03.undulator_dcm import UndulatorDCM
|
|
|
19
19
|
from dodal.devices.motors import XYZPositioner
|
|
20
20
|
from dodal.devices.oav.oav_detector import OAV
|
|
21
21
|
from dodal.devices.robot import BartRobot, SampleLocation
|
|
22
|
-
from dodal.devices.smargon import Smargon, StubPosition
|
|
22
|
+
from dodal.devices.smargon import CombinedMove, Smargon, StubPosition
|
|
23
23
|
from dodal.devices.thawer import Thawer
|
|
24
24
|
from dodal.devices.webcam import Webcam
|
|
25
25
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
@@ -104,16 +104,7 @@ def prepare_for_robot_load(
|
|
|
104
104
|
|
|
105
105
|
yield from bps.mv(smargon.stub_offsets, StubPosition.RESET_TO_ROBOT_LOAD)
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
yield from bps.mv(
|
|
109
|
-
smargon.x, 0,
|
|
110
|
-
smargon.y, 0,
|
|
111
|
-
smargon.z, 0,
|
|
112
|
-
smargon.omega, 0,
|
|
113
|
-
smargon.chi, 0,
|
|
114
|
-
smargon.phi, 0
|
|
115
|
-
)
|
|
116
|
-
# fmt: on
|
|
107
|
+
yield from bps.mv(smargon, CombinedMove(x=0, y=0, z=0, chi=0, phi=0, omega=0))
|
|
117
108
|
|
|
118
109
|
yield from bps.wait("prepare_robot_load")
|
|
119
110
|
|
|
@@ -19,7 +19,7 @@ from dodal.devices.oav.oav_detector import OAV
|
|
|
19
19
|
from dodal.devices.oav.oav_parameters import OAVParameters
|
|
20
20
|
from dodal.devices.robot import BartRobot
|
|
21
21
|
from dodal.devices.s4_slit_gaps import S4SlitGaps
|
|
22
|
-
from dodal.devices.smargon import Smargon
|
|
22
|
+
from dodal.devices.smargon import CombinedMove, Smargon
|
|
23
23
|
from dodal.devices.synchrotron import Synchrotron
|
|
24
24
|
from dodal.devices.undulator import Undulator
|
|
25
25
|
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
@@ -32,8 +32,6 @@ from dodal.plans.preprocessors.verify_undulator_gap import (
|
|
|
32
32
|
|
|
33
33
|
from mx_bluesky.common.device_setup_plans.manipulate_sample import (
|
|
34
34
|
cleanup_sample_environment,
|
|
35
|
-
move_phi_chi_omega,
|
|
36
|
-
move_x_y_z,
|
|
37
35
|
setup_sample_environment,
|
|
38
36
|
)
|
|
39
37
|
from mx_bluesky.common.parameters.components import WithSnapshot
|
|
@@ -62,8 +60,8 @@ from mx_bluesky.hyperion.experiment_plans.oav_snapshot_plan import (
|
|
|
62
60
|
)
|
|
63
61
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
64
62
|
from mx_bluesky.hyperion.parameters.rotation import (
|
|
65
|
-
MultiRotationScan,
|
|
66
63
|
RotationScan,
|
|
64
|
+
SingleRotationScan,
|
|
67
65
|
)
|
|
68
66
|
|
|
69
67
|
|
|
@@ -118,7 +116,7 @@ class RotationMotionProfile:
|
|
|
118
116
|
|
|
119
117
|
|
|
120
118
|
def calculate_motion_profile(
|
|
121
|
-
params:
|
|
119
|
+
params: SingleRotationScan,
|
|
122
120
|
motor_time_to_speed_s: float,
|
|
123
121
|
max_velocity_deg_s: float,
|
|
124
122
|
) -> RotationMotionProfile:
|
|
@@ -212,7 +210,7 @@ def calculate_motion_profile(
|
|
|
212
210
|
|
|
213
211
|
def rotation_scan_plan(
|
|
214
212
|
composite: RotationScanComposite,
|
|
215
|
-
params:
|
|
213
|
+
params: SingleRotationScan,
|
|
216
214
|
motion_values: RotationMotionProfile,
|
|
217
215
|
):
|
|
218
216
|
"""A stub plan to collect diffraction images from a sample continuously rotating
|
|
@@ -319,7 +317,7 @@ def _cleanup_plan(composite: RotationScanComposite, **kwargs):
|
|
|
319
317
|
|
|
320
318
|
def _move_and_rotation(
|
|
321
319
|
composite: RotationScanComposite,
|
|
322
|
-
params:
|
|
320
|
+
params: SingleRotationScan,
|
|
323
321
|
oav_params: OAVParameters,
|
|
324
322
|
):
|
|
325
323
|
motor_time_to_speed = yield from bps.rd(composite.smargon.omega.acceleration_time)
|
|
@@ -330,19 +328,18 @@ def _move_and_rotation(
|
|
|
330
328
|
return num / 1000 if num else num
|
|
331
329
|
|
|
332
330
|
LOGGER.info("moving to position (if specified)")
|
|
333
|
-
yield from
|
|
331
|
+
yield from bps.abs_set(
|
|
334
332
|
composite.smargon,
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
params.phi_start_deg,
|
|
343
|
-
params.chi_start_deg,
|
|
333
|
+
CombinedMove(
|
|
334
|
+
x=_div_by_1000_if_not_none(params.x_start_um),
|
|
335
|
+
y=_div_by_1000_if_not_none(params.y_start_um),
|
|
336
|
+
z=_div_by_1000_if_not_none(params.z_start_um),
|
|
337
|
+
phi=params.phi_start_deg,
|
|
338
|
+
chi=params.chi_start_deg,
|
|
339
|
+
),
|
|
344
340
|
group=CONST.WAIT.MOVE_GONIO_TO_START,
|
|
345
341
|
)
|
|
342
|
+
|
|
346
343
|
if params.take_snapshots:
|
|
347
344
|
yield from bps.wait(CONST.WAIT.MOVE_GONIO_TO_START)
|
|
348
345
|
yield from setup_beamline_for_OAV(
|
|
@@ -359,9 +356,9 @@ def _move_and_rotation(
|
|
|
359
356
|
yield from rotation_scan_plan(composite, params, motion_values)
|
|
360
357
|
|
|
361
358
|
|
|
362
|
-
def
|
|
359
|
+
def rotation_scan(
|
|
363
360
|
composite: RotationScanComposite,
|
|
364
|
-
parameters:
|
|
361
|
+
parameters: RotationScan,
|
|
365
362
|
oav_params: OAVParameters | None = None,
|
|
366
363
|
) -> MsgGenerator:
|
|
367
364
|
@bpp.set_run_key_decorator(CONST.PLAN.ROTATION_MULTI_OUTER)
|
|
@@ -373,15 +370,15 @@ def multi_rotation_scan(
|
|
|
373
370
|
),
|
|
374
371
|
}
|
|
375
372
|
)
|
|
376
|
-
def
|
|
377
|
-
yield from
|
|
373
|
+
def _wrapped_rotation_scan():
|
|
374
|
+
yield from rotation_scan_internal(composite, parameters, oav_params)
|
|
378
375
|
|
|
379
|
-
yield from
|
|
376
|
+
yield from _wrapped_rotation_scan()
|
|
380
377
|
|
|
381
378
|
|
|
382
|
-
def
|
|
379
|
+
def rotation_scan_internal(
|
|
383
380
|
composite: RotationScanComposite,
|
|
384
|
-
parameters:
|
|
381
|
+
parameters: RotationScan,
|
|
385
382
|
oav_params: OAVParameters | None = None,
|
|
386
383
|
) -> MsgGenerator:
|
|
387
384
|
parameters.features.update_self_from_server()
|
|
@@ -419,7 +416,7 @@ def multi_rotation_scan_internal(
|
|
|
419
416
|
}
|
|
420
417
|
)
|
|
421
418
|
def rotation_scan_core(
|
|
422
|
-
params:
|
|
419
|
+
params: SingleRotationScan,
|
|
423
420
|
):
|
|
424
421
|
yield from _move_and_rotation(composite, params, oav_params)
|
|
425
422
|
|