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
|
@@ -2,6 +2,7 @@ import dataclasses
|
|
|
2
2
|
import json
|
|
3
3
|
import re
|
|
4
4
|
import traceback
|
|
5
|
+
from collections.abc import Sequence
|
|
5
6
|
from os import path
|
|
6
7
|
from typing import Any, TypeVar
|
|
7
8
|
|
|
@@ -127,83 +128,88 @@ def get_param_version() -> SemanticVersion:
|
|
|
127
128
|
return SemanticVersion.validate_from_str(str(PARAMETER_VERSION))
|
|
128
129
|
|
|
129
130
|
|
|
130
|
-
def populate_parameters_from_agamemnon(agamemnon_params):
|
|
131
|
+
def populate_parameters_from_agamemnon(agamemnon_params) -> Sequence[LoadCentreCollect]:
|
|
131
132
|
visit, detector_distance = get_withvisit_parameters_from_agamemnon(agamemnon_params)
|
|
132
133
|
with_energy_params = get_withenergy_parameters_from_agamemnon(agamemnon_params)
|
|
133
134
|
pin_type = get_pin_type_from_agamemnon_parameters(agamemnon_params)
|
|
134
|
-
|
|
135
|
+
collections = agamemnon_params["collection"]
|
|
135
136
|
visit_directory, file_name = path.split(agamemnon_params["prefix"])
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
"
|
|
146
|
-
"
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
"
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
"
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
137
|
+
|
|
138
|
+
return [
|
|
139
|
+
LoadCentreCollect.model_validate(
|
|
140
|
+
{
|
|
141
|
+
"parameter_model_version": get_param_version(),
|
|
142
|
+
"visit": visit,
|
|
143
|
+
"detector_distance_mm": detector_distance,
|
|
144
|
+
"sample_id": agamemnon_params["sample"]["id"],
|
|
145
|
+
"sample_puck": agamemnon_params["sample"]["container"],
|
|
146
|
+
"sample_pin": agamemnon_params["sample"]["position"],
|
|
147
|
+
"select_centres": {
|
|
148
|
+
"name": "TopNByMaxCount",
|
|
149
|
+
"n": pin_type.expected_number_of_crystals,
|
|
150
|
+
},
|
|
151
|
+
"robot_load_then_centre": {
|
|
152
|
+
"storage_directory": str(visit_directory) + "/xraycentring",
|
|
153
|
+
"file_name": file_name,
|
|
154
|
+
"tip_offset_um": pin_type.full_width / 2,
|
|
155
|
+
"grid_width_um": pin_type.full_width,
|
|
156
|
+
"omega_start_deg": 0.0,
|
|
157
|
+
"chi_start_deg": collection["chi"],
|
|
158
|
+
"transmission_frac": 1.0,
|
|
159
|
+
"features": {"use_gpu_results": True},
|
|
160
|
+
**with_energy_params,
|
|
161
|
+
},
|
|
162
|
+
"multi_rotation_scan": {
|
|
163
|
+
"comment": collection["comment"],
|
|
164
|
+
"storage_directory": str(visit_directory),
|
|
165
|
+
"exposure_time_s": collection["exposure_time"],
|
|
166
|
+
"file_name": file_name,
|
|
167
|
+
"transmission_frac": collection["transmission"],
|
|
168
|
+
"rotation_increment_deg": collection["omega_increment"],
|
|
169
|
+
"ispyb_experiment_type": collection["experiment_type"],
|
|
170
|
+
"snapshot_omegas_deg": [0.0, 90.0, 180.0, 270.0],
|
|
171
|
+
"rotation_scans": [
|
|
172
|
+
{
|
|
173
|
+
"scan_width_deg": (
|
|
174
|
+
collection["number_of_images"]
|
|
175
|
+
* collection["omega_increment"]
|
|
176
|
+
),
|
|
177
|
+
"omega_start_deg": collection["omega_start"],
|
|
178
|
+
"phi_start_deg": collection["phi_start"],
|
|
179
|
+
"chi_start_deg": collection["chi"],
|
|
180
|
+
"rotation_direction": "Positive",
|
|
181
|
+
}
|
|
182
|
+
],
|
|
183
|
+
**with_energy_params,
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
for collection in collections
|
|
188
|
+
]
|
|
184
189
|
|
|
185
190
|
|
|
186
|
-
def create_parameters_from_agamemnon() -> LoadCentreCollect
|
|
191
|
+
def create_parameters_from_agamemnon() -> Sequence[LoadCentreCollect]:
|
|
187
192
|
beamline_name = get_beamline_name("i03")
|
|
188
193
|
agamemnon_params = get_next_instruction(beamline_name)
|
|
189
194
|
return (
|
|
190
|
-
populate_parameters_from_agamemnon(agamemnon_params)
|
|
191
|
-
if agamemnon_params
|
|
192
|
-
else None
|
|
195
|
+
populate_parameters_from_agamemnon(agamemnon_params) if agamemnon_params else []
|
|
193
196
|
)
|
|
194
197
|
|
|
195
198
|
|
|
196
|
-
def compare_params(load_centre_collect_params):
|
|
199
|
+
def compare_params(load_centre_collect_params: LoadCentreCollect):
|
|
197
200
|
try:
|
|
198
|
-
|
|
201
|
+
lcc_requests = create_parameters_from_agamemnon()
|
|
199
202
|
# Log differences against GDA populated parameters
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
f"Different parameters found when directly reading from Hyperion: {differences}"
|
|
203
|
+
if not lcc_requests:
|
|
204
|
+
LOGGER.info("Agamemnon returned no instructions")
|
|
205
|
+
else:
|
|
206
|
+
differences = DeepDiff(
|
|
207
|
+
lcc_requests[0], load_centre_collect_params, math_epsilon=1e-5
|
|
206
208
|
)
|
|
209
|
+
if differences:
|
|
210
|
+
LOGGER.info(
|
|
211
|
+
f"Different parameters found when directly reading from Hyperion: {differences}"
|
|
212
|
+
)
|
|
207
213
|
except (ValueError, KeyError):
|
|
208
214
|
LOGGER.warning(f"Failed to compare parameters: {traceback.format_exc()}")
|
|
209
215
|
except Exception:
|
|
@@ -93,7 +93,7 @@ def setup_logging(dev_mode: bool):
|
|
|
93
93
|
(ISPYB_ZOCALO_CALLBACK_LOGGER, "hyperion_ispyb_callback.log"),
|
|
94
94
|
(NEXUS_LOGGER, "hyperion_nexus_callback.log"),
|
|
95
95
|
]:
|
|
96
|
-
logging_path, debug_logging_path = _get_logging_dirs()
|
|
96
|
+
logging_path, debug_logging_path = _get_logging_dirs(dev_mode)
|
|
97
97
|
if logger.handlers == []:
|
|
98
98
|
handlers = set_up_all_logging_handlers(
|
|
99
99
|
logger,
|
|
@@ -25,7 +25,7 @@ from mx_bluesky.hyperion.external_interaction.callbacks.rotation.ispyb_mapping i
|
|
|
25
25
|
populate_data_collection_info_for_rotation,
|
|
26
26
|
)
|
|
27
27
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
28
|
-
from mx_bluesky.hyperion.parameters.rotation import
|
|
28
|
+
from mx_bluesky.hyperion.parameters.rotation import SingleRotationScan
|
|
29
29
|
|
|
30
30
|
if TYPE_CHECKING:
|
|
31
31
|
from event_model.documents import Event, RunStart, RunStop
|
|
@@ -62,7 +62,7 @@ class RotationISPyBCallback(BaseISPyBCallback):
|
|
|
62
62
|
)
|
|
63
63
|
hyperion_params = doc.get("mx_bluesky_parameters")
|
|
64
64
|
assert isinstance(hyperion_params, str)
|
|
65
|
-
self.params =
|
|
65
|
+
self.params = SingleRotationScan.model_validate_json(hyperion_params)
|
|
66
66
|
dcgid = (
|
|
67
67
|
self.ispyb_ids.data_collection_group_id
|
|
68
68
|
if (self.params.sample_id == self.last_sample_id)
|
|
@@ -86,7 +86,7 @@ class RotationISPyBCallback(BaseISPyBCallback):
|
|
|
86
86
|
ISPYB_ZOCALO_CALLBACK_LOGGER.info("Beginning ispyb deposition")
|
|
87
87
|
data_collection_group_info = populate_data_collection_group(self.params)
|
|
88
88
|
data_collection_info = populate_data_collection_info_for_rotation(
|
|
89
|
-
cast(
|
|
89
|
+
cast(SingleRotationScan, self.params)
|
|
90
90
|
)
|
|
91
91
|
data_collection_info = populate_remaining_data_collection_info(
|
|
92
92
|
self.params.comment,
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from mx_bluesky.common.external_interaction.ispyb.data_model import DataCollectionInfo
|
|
4
|
-
from mx_bluesky.hyperion.parameters.rotation import
|
|
4
|
+
from mx_bluesky.hyperion.parameters.rotation import SingleRotationScan
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def populate_data_collection_info_for_rotation(params:
|
|
7
|
+
def populate_data_collection_info_for_rotation(params: SingleRotationScan):
|
|
8
8
|
info = DataCollectionInfo(
|
|
9
9
|
omega_start=params.omega_start_deg,
|
|
10
10
|
data_collection_number=params.detector_params.run_number, # type:ignore # the validator always makes this int
|
|
11
11
|
n_images=params.num_images,
|
|
12
12
|
axis_range=params.rotation_increment_deg,
|
|
13
13
|
axis_start=params.omega_start_deg,
|
|
14
|
-
axis_end=(
|
|
14
|
+
axis_end=(
|
|
15
|
+
params.omega_start_deg
|
|
16
|
+
+ params.scan_width_deg * params.rotation_direction.multiplier
|
|
17
|
+
),
|
|
15
18
|
kappa_start=params.kappa_start_deg,
|
|
16
19
|
)
|
|
17
20
|
return info
|
|
@@ -16,7 +16,7 @@ from mx_bluesky.common.external_interaction.nexus.nexus_utils import (
|
|
|
16
16
|
from mx_bluesky.common.external_interaction.nexus.write_nexus import NexusWriter
|
|
17
17
|
from mx_bluesky.common.utils.log import NEXUS_LOGGER
|
|
18
18
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
19
|
-
from mx_bluesky.hyperion.parameters.rotation import
|
|
19
|
+
from mx_bluesky.hyperion.parameters.rotation import SingleRotationScan
|
|
20
20
|
|
|
21
21
|
if TYPE_CHECKING:
|
|
22
22
|
from event_model.documents import Event, EventDescriptor, RunStart
|
|
@@ -85,7 +85,7 @@ class RotationNexusFileCallback(PlanReactiveCallback):
|
|
|
85
85
|
NEXUS_LOGGER.info(
|
|
86
86
|
f"Nexus writer received start document with experiment parameters {hyperion_params}"
|
|
87
87
|
)
|
|
88
|
-
parameters =
|
|
88
|
+
parameters = SingleRotationScan.model_validate_json(hyperion_params)
|
|
89
89
|
NEXUS_LOGGER.info("Setting up nexus file...")
|
|
90
90
|
|
|
91
91
|
det_size = (
|
|
@@ -21,7 +21,9 @@ class HyperionFeatureFlags(FeatureFlags):
|
|
|
21
21
|
set_stub_offsets: If True then set the stub offsets after moving to the crystal (ignored for
|
|
22
22
|
multi-centre)
|
|
23
23
|
omega_flip: If True then invert the smargon omega motor rotation commands with respect to
|
|
24
|
-
the hyperion request.
|
|
24
|
+
the hyperion request. See "Hyperion Coordinate Systems" in the documentation.
|
|
25
|
+
alternate_rotation_direction: If True then the for multi-sample pins the rotation direction of
|
|
26
|
+
successive rotation scans is alternated between positive and negative.
|
|
25
27
|
"""
|
|
26
28
|
|
|
27
29
|
@staticmethod
|
|
@@ -41,3 +43,4 @@ class HyperionFeatureFlags(FeatureFlags):
|
|
|
41
43
|
use_gpu_results: bool = CONST.I03.USE_GPU_RESULTS
|
|
42
44
|
set_stub_offsets: bool = CONST.I03.SET_STUB_OFFSETS
|
|
43
45
|
omega_flip: bool = CONST.I03.OMEGA_FLIP
|
|
46
|
+
alternate_rotation_direction: bool = CONST.I03.ALTERNATE_ROTATION_DIRECTION
|
|
@@ -8,7 +8,6 @@ from mx_bluesky._version import version
|
|
|
8
8
|
@dataclass
|
|
9
9
|
class HyperionArgs:
|
|
10
10
|
dev_mode: bool = False
|
|
11
|
-
verbose_event_logging: bool = False
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
def _add_callback_relevant_args(parser: argparse.ArgumentParser) -> None:
|
|
@@ -29,16 +28,11 @@ def parse_callback_dev_mode_arg() -> bool:
|
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
def parse_cli_args() -> HyperionArgs:
|
|
32
|
-
"""Parses all arguments relevant to hyperion.
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
"""Parses all arguments relevant to hyperion.
|
|
32
|
+
Returns:
|
|
33
|
+
an HyperionArgs dataclass with the fields: (dev_mode: bool)"""
|
|
35
34
|
parser = argparse.ArgumentParser()
|
|
36
35
|
_add_callback_relevant_args(parser)
|
|
37
|
-
parser.add_argument(
|
|
38
|
-
"--verbose-event-logging",
|
|
39
|
-
action="store_true",
|
|
40
|
-
help="Log all bluesky event documents to graylog",
|
|
41
|
-
)
|
|
42
36
|
parser.add_argument(
|
|
43
37
|
"--version",
|
|
44
38
|
help="Print hyperion version string",
|
|
@@ -47,6 +41,5 @@ def parse_cli_args() -> HyperionArgs:
|
|
|
47
41
|
)
|
|
48
42
|
args = parser.parse_args()
|
|
49
43
|
return HyperionArgs(
|
|
50
|
-
verbose_event_logging=args.verbose_event_logging or False,
|
|
51
44
|
dev_mode=args.dev or False,
|
|
52
45
|
)
|
|
@@ -12,7 +12,7 @@ from mx_bluesky.hyperion.parameters.components import WithHyperionUDCFeatures
|
|
|
12
12
|
from mx_bluesky.hyperion.parameters.robot_load import (
|
|
13
13
|
RobotLoadThenCentre,
|
|
14
14
|
)
|
|
15
|
-
from mx_bluesky.hyperion.parameters.rotation import
|
|
15
|
+
from mx_bluesky.hyperion.parameters.rotation import RotationScan
|
|
16
16
|
|
|
17
17
|
T = TypeVar("T", bound=BaseModel)
|
|
18
18
|
|
|
@@ -34,7 +34,7 @@ class LoadCentreCollect(
|
|
|
34
34
|
pin-tip centre and rotation scan operations."""
|
|
35
35
|
|
|
36
36
|
robot_load_then_centre: RobotLoadThenCentre
|
|
37
|
-
multi_rotation_scan:
|
|
37
|
+
multi_rotation_scan: RotationScan
|
|
38
38
|
|
|
39
39
|
@model_validator(mode="before")
|
|
40
40
|
@classmethod
|
|
@@ -42,7 +42,7 @@ class LoadCentreCollect(
|
|
|
42
42
|
allowed_keys = (
|
|
43
43
|
LoadCentreCollect.model_fields.keys()
|
|
44
44
|
| RobotLoadThenCentre.model_fields.keys()
|
|
45
|
-
|
|
|
45
|
+
| RotationScan.model_fields.keys()
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
disallowed_keys = values.keys() - allowed_keys
|
|
@@ -74,7 +74,7 @@ class LoadCentreCollect(
|
|
|
74
74
|
values, values["robot_load_then_centre"], RobotLoadThenCentre
|
|
75
75
|
)
|
|
76
76
|
new_multi_rotation_scan_params = construct_from_values(
|
|
77
|
-
values, values["multi_rotation_scan"],
|
|
77
|
+
values, values["multi_rotation_scan"], RotationScan
|
|
78
78
|
)
|
|
79
79
|
values["multi_rotation_scan"] = new_multi_rotation_scan_params
|
|
80
80
|
values["robot_load_then_centre"] = new_robot_load_then_centre_params
|
|
@@ -42,7 +42,8 @@ class RotationScanPerSweep(OptionalGonioAngleStarts, OptionalXyzStarts):
|
|
|
42
42
|
omega_start_deg: The initial angle of the rotation in degrees (default 0)
|
|
43
43
|
scan_width_deg: The sweep of the rotation in degrees, this must be positive (default 360)
|
|
44
44
|
rotation_direction: Indicates the direction of rotation, if RotationDirection.POSITIVE
|
|
45
|
-
the final angle is obtained by adding scan_width_deg, otherwise by subtraction (default NEGATIVE)
|
|
45
|
+
the final angle is obtained by adding scan_width_deg, otherwise by subtraction (default NEGATIVE).
|
|
46
|
+
See "Hyperion Coordinate Systems" in the documentation.
|
|
46
47
|
nexus_vds_start_img: The frame number of the first frame captured during the rotation
|
|
47
48
|
"""
|
|
48
49
|
|
|
@@ -104,7 +105,7 @@ class RotationExperiment(DiffractionExperimentWithSample, WithHyperionUDCFeature
|
|
|
104
105
|
return aperture_position
|
|
105
106
|
|
|
106
107
|
|
|
107
|
-
class
|
|
108
|
+
class SingleRotationScan(WithScan, RotationScanPerSweep, RotationExperiment):
|
|
108
109
|
@property
|
|
109
110
|
def detector_params(self):
|
|
110
111
|
return self._detector_params(self.omega_start_deg)
|
|
@@ -129,12 +130,12 @@ class RotationScan(WithScan, RotationScanPerSweep, RotationExperiment):
|
|
|
129
130
|
return int(self.scan_width_deg / self.rotation_increment_deg)
|
|
130
131
|
|
|
131
132
|
|
|
132
|
-
class
|
|
133
|
+
class RotationScan(RotationExperiment, SplitScan):
|
|
133
134
|
rotation_scans: Annotated[list[RotationScanPerSweep], Len(min_length=1)]
|
|
134
135
|
|
|
135
|
-
def _single_rotation_scan(self, scan: RotationScanPerSweep) ->
|
|
136
|
+
def _single_rotation_scan(self, scan: RotationScanPerSweep) -> SingleRotationScan:
|
|
136
137
|
# self has everything from RotationExperiment
|
|
137
|
-
allowed_keys =
|
|
138
|
+
allowed_keys = SingleRotationScan.model_fields.keys() # type: ignore # mypy doesn't recognise this as a property...
|
|
138
139
|
params_dump = self.model_dump()
|
|
139
140
|
# provided `scan` has everything from RotationScanPerSweep
|
|
140
141
|
scan_dump = scan.model_dump()
|
|
@@ -142,13 +143,13 @@ class MultiRotationScan(RotationExperiment, SplitScan):
|
|
|
142
143
|
k: v for k, v in (params_dump | scan_dump).items() if k in allowed_keys
|
|
143
144
|
}
|
|
144
145
|
# together they have everything for RotationScan
|
|
145
|
-
rotation_scan =
|
|
146
|
+
rotation_scan = SingleRotationScan(**rotation_scan_kv_pairs)
|
|
146
147
|
return rotation_scan
|
|
147
148
|
|
|
148
149
|
@model_validator(mode="after")
|
|
149
150
|
@classmethod
|
|
150
151
|
def correct_start_vds(cls, values: Any) -> Any:
|
|
151
|
-
assert isinstance(values,
|
|
152
|
+
assert isinstance(values, RotationScan)
|
|
152
153
|
start_img = 0.0
|
|
153
154
|
for scan in values.rotation_scans:
|
|
154
155
|
scan.nexus_vds_start_img = int(start_img)
|
|
@@ -167,7 +168,7 @@ class MultiRotationScan(RotationExperiment, SplitScan):
|
|
|
167
168
|
return self
|
|
168
169
|
|
|
169
170
|
@property
|
|
170
|
-
def single_rotation_scans(self) -> Iterator[
|
|
171
|
+
def single_rotation_scans(self) -> Iterator[SingleRotationScan]:
|
|
171
172
|
for scan in self.rotation_scans:
|
|
172
173
|
yield self._single_rotation_scan(scan)
|
|
173
174
|
|
|
@@ -5,11 +5,14 @@ import mx_bluesky.hyperion.experiment_plans as hyperion_plans
|
|
|
5
5
|
from mx_bluesky.common.utils.log import LOGGER
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def setup_context() -> BlueskyContext:
|
|
8
|
+
def setup_context(dev_mode: bool = False) -> BlueskyContext:
|
|
9
9
|
context = BlueskyContext()
|
|
10
10
|
context.with_plan_module(hyperion_plans)
|
|
11
11
|
|
|
12
|
-
context.with_dodal_module(
|
|
12
|
+
context.with_dodal_module(
|
|
13
|
+
get_beamline_based_on_environment_variable(),
|
|
14
|
+
mock=dev_mode,
|
|
15
|
+
)
|
|
13
16
|
|
|
14
17
|
LOGGER.info(f"Plans found in context: {context.plan_functions.keys()}")
|
|
15
18
|
|
|
@@ -3,12 +3,11 @@ import json
|
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from unittest.mock import patch
|
|
7
6
|
|
|
8
7
|
import bluesky.preprocessors as bpp
|
|
9
8
|
from bluesky.run_engine import RunEngine
|
|
10
9
|
from dodal.beamlines import i03
|
|
11
|
-
from dodal.devices.oav.
|
|
10
|
+
from dodal.devices.oav.oav_detector import OAVConfigBeamCentre
|
|
12
11
|
from ophyd_async.testing import set_mock_value
|
|
13
12
|
|
|
14
13
|
from mx_bluesky.common.plans.read_hardware import (
|
|
@@ -21,7 +20,7 @@ from mx_bluesky.hyperion.external_interaction.callbacks.rotation.nexus_callback
|
|
|
21
20
|
RotationNexusFileCallback,
|
|
22
21
|
)
|
|
23
22
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
24
|
-
from mx_bluesky.hyperion.parameters.rotation import
|
|
23
|
+
from mx_bluesky.hyperion.parameters.rotation import RotationScan
|
|
25
24
|
|
|
26
25
|
DISPLAY_CONFIGURATION = "tests/test_data/test_display.configuration"
|
|
27
26
|
ZOOM_LEVELS_XML = "tests/test_data/test_jCameraManZoomLevels.xml"
|
|
@@ -36,7 +35,7 @@ def test_params(filename_stub, dir):
|
|
|
36
35
|
with open(filename) as f:
|
|
37
36
|
return json.loads(f.read())
|
|
38
37
|
|
|
39
|
-
params =
|
|
38
|
+
params = RotationScan(
|
|
40
39
|
**get_params(
|
|
41
40
|
"tests/test_data/parameter_json_files/good_test_one_multi_rotation_scan_parameters.json"
|
|
42
41
|
)
|
|
@@ -54,7 +53,7 @@ def test_params(filename_stub, dir):
|
|
|
54
53
|
|
|
55
54
|
|
|
56
55
|
def fake_rotation_scan(
|
|
57
|
-
parameters:
|
|
56
|
+
parameters: RotationScan,
|
|
58
57
|
subscription: RotationNexusFileCallback,
|
|
59
58
|
rotation_devices: RotationScanComposite,
|
|
60
59
|
):
|
|
@@ -101,9 +100,7 @@ def fake_create_rotation_devices():
|
|
|
101
100
|
oav = i03.oav(
|
|
102
101
|
connect_immediately=True,
|
|
103
102
|
mock=True,
|
|
104
|
-
params=
|
|
105
|
-
zoom_params_file=ZOOM_LEVELS_XML, display_config_file=DISPLAY_CONFIGURATION
|
|
106
|
-
),
|
|
103
|
+
params=OAVConfigBeamCentre(ZOOM_LEVELS_XML, DISPLAY_CONFIGURATION),
|
|
107
104
|
)
|
|
108
105
|
xbpm_feedback = i03.xbpm_feedback(connect_immediately=True, mock=True)
|
|
109
106
|
|
|
@@ -132,7 +129,7 @@ def fake_create_rotation_devices():
|
|
|
132
129
|
|
|
133
130
|
|
|
134
131
|
def sim_rotation_scan_to_create_nexus(
|
|
135
|
-
test_params:
|
|
132
|
+
test_params: RotationScan,
|
|
136
133
|
fake_create_rotation_devices: RotationScanComposite,
|
|
137
134
|
filename_stub,
|
|
138
135
|
RE,
|
|
@@ -142,15 +139,11 @@ def sim_rotation_scan_to_create_nexus(
|
|
|
142
139
|
|
|
143
140
|
fake_create_rotation_devices.eiger.bit_depth.sim_put(32) # type: ignore
|
|
144
141
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
):
|
|
149
|
-
RE(
|
|
150
|
-
fake_rotation_scan(
|
|
151
|
-
test_params, RotationNexusFileCallback(), fake_create_rotation_devices
|
|
152
|
-
)
|
|
142
|
+
RE(
|
|
143
|
+
fake_rotation_scan(
|
|
144
|
+
test_params, RotationNexusFileCallback(), fake_create_rotation_devices
|
|
153
145
|
)
|
|
146
|
+
)
|
|
154
147
|
|
|
155
148
|
nexus_path = Path(test_params.storage_directory) / nexus_filename
|
|
156
149
|
assert os.path.isfile(nexus_path)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mx-bluesky
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.9
|
|
4
4
|
Summary: Bluesky tools for MX Beamlines at DLS
|
|
5
5
|
Author-email: Dominic Oram <dominic.oram@diamond.ac.uk>
|
|
6
6
|
License: Apache License
|
|
@@ -220,7 +220,7 @@ Requires-Dist: flask-restful
|
|
|
220
220
|
Requires-Dist: ispyb
|
|
221
221
|
Requires-Dist: jupyterlab
|
|
222
222
|
Requires-Dist: matplotlib
|
|
223
|
-
Requires-Dist: nexgen
|
|
223
|
+
Requires-Dist: nexgen>=0.11.0
|
|
224
224
|
Requires-Dist: numpy
|
|
225
225
|
Requires-Dist: opencv-python
|
|
226
226
|
Requires-Dist: opentelemetry-distro
|
|
@@ -235,11 +235,11 @@ Requires-Dist: scipy
|
|
|
235
235
|
Requires-Dist: semver
|
|
236
236
|
Requires-Dist: matplotlib
|
|
237
237
|
Requires-Dist: blueapi>=0.5.0
|
|
238
|
-
Requires-Dist: daq-config-server
|
|
238
|
+
Requires-Dist: daq-config-server==0.1.1
|
|
239
239
|
Requires-Dist: ophyd>=1.10.5
|
|
240
240
|
Requires-Dist: ophyd-async>=0.10.0a2
|
|
241
241
|
Requires-Dist: bluesky>=1.13.1
|
|
242
|
-
Requires-Dist: dls-dodal==1.
|
|
242
|
+
Requires-Dist: dls-dodal==1.48.0
|
|
243
243
|
Provides-Extra: dev
|
|
244
244
|
Requires-Dist: black; extra == "dev"
|
|
245
245
|
Requires-Dist: build; extra == "dev"
|