mx-bluesky 1.2.0__py3-none-any.whl → 1.4.1a0__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/__init__.py +8 -3
- mx_bluesky/__main__.py +12 -7
- mx_bluesky/_version.py +2 -2
- mx_bluesky/beamlines/i04/callbacks/murko_callback.py +14 -4
- mx_bluesky/beamlines/i04/thawing_plan.py +49 -11
- mx_bluesky/beamlines/i24/serial/__init__.py +3 -0
- mx_bluesky/beamlines/i24/serial/dcid.py +19 -21
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +69 -91
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +2 -5
- mx_bluesky/beamlines/i24/serial/fixed_target/ft_utils.py +0 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +111 -143
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +141 -222
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +7 -216
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +18 -17
- mx_bluesky/beamlines/i24/serial/log.py +58 -49
- mx_bluesky/beamlines/i24/serial/parameters/constants.py +0 -1
- mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +3 -3
- mx_bluesky/beamlines/i24/serial/run_extruder.sh +30 -5
- mx_bluesky/beamlines/i24/serial/run_fixed_target.sh +30 -5
- mx_bluesky/beamlines/i24/serial/run_serial.py +24 -8
- mx_bluesky/beamlines/i24/serial/setup_beamline/ca.py +0 -2
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +79 -81
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +9 -20
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +26 -28
- mx_bluesky/beamlines/i24/serial/write_nexus.py +11 -11
- mx_bluesky/common/__init__.py +0 -0
- mx_bluesky/common/device_setup_plans/read_hardware_for_setup.py +14 -0
- mx_bluesky/common/external_interaction/config_server.py +46 -0
- mx_bluesky/common/parameters/components.py +258 -0
- mx_bluesky/common/parameters/constants.py +138 -0
- mx_bluesky/common/parameters/gridscan.py +94 -0
- mx_bluesky/common/parameters/robot_load.py +16 -0
- mx_bluesky/common/plans/__init__.py +1 -0
- mx_bluesky/common/plans/do_fgs.py +121 -0
- mx_bluesky/common/utils/log.py +118 -0
- mx_bluesky/{hyperion → common/utils}/tracing.py +2 -2
- mx_bluesky/hyperion/__main__.py +13 -10
- mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +31 -26
- mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +6 -12
- mx_bluesky/hyperion/device_setup_plans/setup_oav.py +6 -12
- mx_bluesky/hyperion/device_setup_plans/setup_panda.py +5 -6
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +49 -18
- mx_bluesky/hyperion/device_setup_plans/smargon.py +6 -6
- mx_bluesky/hyperion/device_setup_plans/utils.py +2 -2
- mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +4 -4
- mx_bluesky/hyperion/experiment_plans/__init__.py +4 -0
- mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +83 -0
- mx_bluesky/hyperion/experiment_plans/common/xrc_result.py +47 -0
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -9
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +145 -161
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +56 -22
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +52 -10
- mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +21 -20
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +11 -14
- mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +40 -21
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +19 -19
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +21 -21
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +51 -13
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +24 -7
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +5 -6
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +1 -2
- mx_bluesky/hyperion/external_interaction/callbacks/common/abstract_event.py +66 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/ispyb_mapping.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/grid_detection_callback.py +30 -25
- mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py +29 -12
- mx_bluesky/hyperion/external_interaction/callbacks/log_uid_tag_callback.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +7 -4
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +5 -3
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +28 -20
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py +5 -4
- mx_bluesky/hyperion/external_interaction/config_server.py +11 -28
- mx_bluesky/hyperion/external_interaction/ispyb/exp_eye_store.py +1 -1
- mx_bluesky/hyperion/external_interaction/ispyb/ispyb_store.py +1 -1
- mx_bluesky/hyperion/external_interaction/nexus/nexus_utils.py +2 -2
- mx_bluesky/hyperion/external_interaction/nexus/write_nexus.py +1 -1
- mx_bluesky/hyperion/log.py +0 -84
- mx_bluesky/hyperion/parameters/components.py +4 -251
- mx_bluesky/hyperion/parameters/constants.py +22 -119
- mx_bluesky/hyperion/parameters/gridscan.py +35 -74
- mx_bluesky/hyperion/parameters/load_centre_collect.py +16 -11
- mx_bluesky/hyperion/parameters/rotation.py +23 -10
- mx_bluesky/hyperion/utils/utils.py +17 -0
- mx_bluesky/hyperion/utils/validation.py +5 -6
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/METADATA +36 -33
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/RECORD +91 -81
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/WHEEL +1 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Mapping_py3v1.py +0 -161
- mx_bluesky/example.py +0 -19
- mx_bluesky/hyperion/parameters/robot_load.py +0 -16
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/LICENSE +0 -0
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/top_level.txt +0 -0
|
@@ -1,107 +1,21 @@
|
|
|
1
1
|
import os
|
|
2
|
-
from enum import Enum
|
|
3
2
|
|
|
4
|
-
from dodal.devices.aperturescatterguard import ApertureValue
|
|
5
3
|
from dodal.devices.detector import EIGER2_X_16M_SIZE
|
|
6
4
|
from pydantic.dataclasses import dataclass
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
DEV_ISPYB_DATABASE_CFG = "/dls_sw/dasc/mariadb/credentials/ispyb-hyperion-dev.cfg"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@dataclass(frozen=True)
|
|
23
|
-
class PlanNameConstants:
|
|
24
|
-
# Robot load subplan
|
|
25
|
-
ROBOT_LOAD = "robot_load"
|
|
26
|
-
# Gridscan
|
|
27
|
-
GRID_DETECT_AND_DO_GRIDSCAN = "grid_detect_and_do_gridscan"
|
|
28
|
-
GRID_DETECT_INNER = "grid_detect"
|
|
29
|
-
GRIDSCAN_OUTER = "run_gridscan_move_and_tidy"
|
|
30
|
-
GRIDSCAN_AND_MOVE = "run_gridscan_and_move"
|
|
31
|
-
GRIDSCAN_MAIN = "run_gridscan"
|
|
32
|
-
DO_FGS = "do_fgs"
|
|
33
|
-
# Rotation scan
|
|
34
|
-
ROTATION_MULTI = "multi_rotation_wrapper"
|
|
35
|
-
ROTATION_OUTER = "rotation_scan_with_cleanup"
|
|
36
|
-
ROTATION_MAIN = "rotation_scan_main"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@dataclass(frozen=True)
|
|
40
|
-
class PlanGroupCheckpointConstants:
|
|
41
|
-
# For places to synchronise / stop and wait in plans, use as bluesky group names
|
|
42
|
-
GRID_READY_FOR_DC = "grid_ready_for_data_collection"
|
|
43
|
-
ROTATION_READY_FOR_DC = "rotation_ready_for_data_collection"
|
|
44
|
-
MOVE_GONIO_TO_START = "move_gonio_to_start"
|
|
45
|
-
READY_FOR_OAV = "ready_for_oav"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
@dataclass(frozen=True)
|
|
49
|
-
class DocDescriptorNames:
|
|
50
|
-
# Robot load event descriptor
|
|
51
|
-
ROBOT_LOAD = "robot_load"
|
|
52
|
-
# For callbacks to use
|
|
53
|
-
OAV_ROTATION_SNAPSHOT_TRIGGERED = "rotation_snapshot_triggered"
|
|
54
|
-
OAV_GRID_SNAPSHOT_TRIGGERED = "snapshot_to_ispyb"
|
|
55
|
-
HARDWARE_READ_PRE = "read_hardware_for_callbacks_pre_collection"
|
|
56
|
-
HARDWARE_READ_DURING = "read_hardware_for_callbacks_during_collection"
|
|
57
|
-
ZOCALO_HW_READ = "zocalo_read_hardware_plan"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@dataclass(frozen=True)
|
|
61
|
-
class HardwareConstants:
|
|
62
|
-
OAV_REFRESH_DELAY = 0.3
|
|
63
|
-
PANDA_FGS_RUN_UP_DEFAULT = 0.17
|
|
64
|
-
CRYOJET_MARGIN_MM = 0.2
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@dataclass(frozen=True)
|
|
68
|
-
class TriggerConstants:
|
|
69
|
-
ZOCALO = "trigger_zocalo_on"
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
@dataclass(frozen=True)
|
|
73
|
-
class GridscanParamConstants:
|
|
74
|
-
WIDTH_UM = 600.0
|
|
75
|
-
EXPOSURE_TIME_S = 0.004
|
|
76
|
-
USE_ROI = True
|
|
77
|
-
BOX_WIDTH_UM = 20.0
|
|
78
|
-
OMEGA_1 = 0.0
|
|
79
|
-
OMEGA_2 = 90.0
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
@dataclass(frozen=True)
|
|
83
|
-
class RotationParamConstants:
|
|
84
|
-
DEFAULT_APERTURE_POSITION = ApertureValue.LARGE
|
|
85
|
-
|
|
6
|
+
from mx_bluesky.common.parameters.constants import (
|
|
7
|
+
DocDescriptorNames,
|
|
8
|
+
EnvironmentConstants,
|
|
9
|
+
ExperimentParamConstants,
|
|
10
|
+
HardwareConstants,
|
|
11
|
+
OavConstants,
|
|
12
|
+
PlanGroupCheckpointConstants,
|
|
13
|
+
PlanNameConstants,
|
|
14
|
+
SimConstants,
|
|
15
|
+
TriggerConstants,
|
|
16
|
+
)
|
|
86
17
|
|
|
87
|
-
|
|
88
|
-
class DetectorParamConstants:
|
|
89
|
-
BEAM_XY_LUT_PATH = (
|
|
90
|
-
"tests/test_data/test_det_dist_converter.txt"
|
|
91
|
-
if TEST_MODE
|
|
92
|
-
else "/dls_sw/i03/software/daq_configuration/lookup/DetDistToBeamXYConverter.txt"
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
@dataclass(frozen=True)
|
|
97
|
-
class ExperimentParamConstants:
|
|
98
|
-
DETECTOR = DetectorParamConstants()
|
|
99
|
-
GRIDSCAN = GridscanParamConstants()
|
|
100
|
-
ROTATION = RotationParamConstants()
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
_test_oav_file = "tests/test_data/test_OAVCentring.json"
|
|
104
|
-
_live_oav_file = "/dls_sw/i03/software/daq_configuration/json/OAVCentring_hyperion.json"
|
|
18
|
+
TEST_MODE = os.environ.get("HYPERION_TEST_MODE")
|
|
105
19
|
|
|
106
20
|
|
|
107
21
|
@dataclass(frozen=True)
|
|
@@ -110,16 +24,21 @@ class I03Constants:
|
|
|
110
24
|
BEAMLINE = "BL03S" if TEST_MODE else "BL03I"
|
|
111
25
|
DETECTOR = EIGER2_X_16M_SIZE
|
|
112
26
|
INSERTION_PREFIX = "SR03S" if TEST_MODE else "SR03I"
|
|
113
|
-
OAV_CENTRING_FILE =
|
|
27
|
+
OAV_CENTRING_FILE = OavConstants.OAV_CONFIG_JSON
|
|
114
28
|
SHUTTER_TIME_S = 0.06
|
|
115
29
|
USE_PANDA_FOR_GRIDSCAN = False
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
30
|
+
SET_STUB_OFFSETS = False
|
|
31
|
+
|
|
32
|
+
# Turns on GPU processing for zocalo and logs a comparison between GPU and CPU-
|
|
33
|
+
# processed results. GPU results never used in analysis for now
|
|
34
|
+
COMPARE_CPU_AND_GPU_ZOCALO = False
|
|
119
35
|
|
|
120
36
|
|
|
121
37
|
@dataclass(frozen=True)
|
|
122
38
|
class HyperionConstants:
|
|
39
|
+
DESCRIPTORS = DocDescriptorNames()
|
|
40
|
+
TRIGGER = TriggerConstants()
|
|
41
|
+
ZOCALO_ENV = EnvironmentConstants.ZOCALO_ENV
|
|
123
42
|
HARDWARE = HardwareConstants()
|
|
124
43
|
I03 = I03Constants()
|
|
125
44
|
PARAM = ExperimentParamConstants()
|
|
@@ -136,23 +55,7 @@ class HyperionConstants:
|
|
|
136
55
|
)
|
|
137
56
|
GRAYLOG_PORT = 12232
|
|
138
57
|
PARAMETER_SCHEMA_DIRECTORY = "src/hyperion/parameters/schemas/"
|
|
139
|
-
|
|
58
|
+
LOG_FILE_NAME = "hyperion.log"
|
|
140
59
|
|
|
141
60
|
|
|
142
61
|
CONST = HyperionConstants()
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
class Actions(Enum):
|
|
146
|
-
START = "start"
|
|
147
|
-
STOP = "stop"
|
|
148
|
-
SHUTDOWN = "shutdown"
|
|
149
|
-
STATUS = "status"
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
class Status(Enum):
|
|
153
|
-
WARN = "Warn"
|
|
154
|
-
FAILED = "Failed"
|
|
155
|
-
SUCCESS = "Success"
|
|
156
|
-
BUSY = "Busy"
|
|
157
|
-
ABORTING = "Aborting"
|
|
158
|
-
IDLE = "Idle"
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
from dodal.devices.aperturescatterguard import ApertureValue
|
|
6
3
|
from dodal.devices.detector import (
|
|
7
4
|
DetectorParams,
|
|
8
5
|
)
|
|
@@ -14,36 +11,22 @@ from pydantic import Field, PrivateAttr
|
|
|
14
11
|
from scanspec.core import Path as ScanPath
|
|
15
12
|
from scanspec.specs import Line, Static
|
|
16
13
|
|
|
17
|
-
from mx_bluesky.
|
|
18
|
-
DiffractionExperimentWithSample,
|
|
19
|
-
IspybExperimentType,
|
|
20
|
-
OptionalGonioAngleStarts,
|
|
14
|
+
from mx_bluesky.common.parameters.components import (
|
|
21
15
|
SplitScan,
|
|
22
|
-
WithOavCentring,
|
|
23
16
|
WithOptionalEnergyChange,
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
WithPandaGridScan,
|
|
18
|
+
)
|
|
19
|
+
from mx_bluesky.common.parameters.gridscan import (
|
|
20
|
+
GridCommon,
|
|
21
|
+
SpecifiedGrid,
|
|
26
22
|
)
|
|
23
|
+
from mx_bluesky.hyperion.parameters.components import WithHyperionFeatures
|
|
27
24
|
from mx_bluesky.hyperion.parameters.constants import CONST, I03Constants
|
|
28
|
-
from mx_bluesky.hyperion.parameters.robot_load import RobotLoadAndEnergyChange
|
|
29
25
|
|
|
30
26
|
|
|
31
|
-
class GridCommon
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
grid_width_um: float = Field(default=CONST.PARAM.GRIDSCAN.WIDTH_UM)
|
|
35
|
-
exposure_time_s: float = Field(default=CONST.PARAM.GRIDSCAN.EXPOSURE_TIME_S)
|
|
36
|
-
use_roi_mode: bool = Field(default=CONST.PARAM.GRIDSCAN.USE_ROI)
|
|
37
|
-
panda_runup_distance_mm: float = Field(
|
|
38
|
-
default=CONST.HARDWARE.PANDA_FGS_RUN_UP_DEFAULT
|
|
39
|
-
)
|
|
40
|
-
use_panda: bool = Field(default=CONST.I03.USE_PANDA_FOR_GRIDSCAN)
|
|
41
|
-
use_gpu: bool = Field(default=CONST.I03.USE_GPU_FOR_GRIDSCAN_ANALYSIS)
|
|
42
|
-
use_cpu_and_gpu_zocalo: bool = Field(default=CONST.I03.USE_CPU_AND_GPU_ZOCALO)
|
|
43
|
-
ispyb_experiment_type: IspybExperimentType = Field(
|
|
44
|
-
default=IspybExperimentType.GRIDSCAN_3D
|
|
45
|
-
)
|
|
46
|
-
selected_aperture: ApertureValue | None = Field(default=ApertureValue.SMALL)
|
|
27
|
+
class HyperionGridCommon(GridCommon, WithHyperionFeatures):
|
|
28
|
+
# This class only exists so that we can properly select enable_dev_shm. Remove in
|
|
29
|
+
# https://github.com/DiamondLightSource/hyperion/issues/1395"""
|
|
47
30
|
|
|
48
31
|
@property
|
|
49
32
|
def detector_params(self):
|
|
@@ -57,7 +40,6 @@ class GridCommon(
|
|
|
57
40
|
assert (
|
|
58
41
|
self.detector_distance_mm is not None
|
|
59
42
|
), "Detector distance must be filled before generating DetectorParams"
|
|
60
|
-
os.makedirs(self.storage_directory, exist_ok=True)
|
|
61
43
|
return DetectorParams(
|
|
62
44
|
detector_size_constants=I03Constants.DETECTOR,
|
|
63
45
|
expected_energy_ev=self.demand_energy_ev,
|
|
@@ -72,40 +54,18 @@ class GridCommon(
|
|
|
72
54
|
use_roi_mode=self.use_roi_mode,
|
|
73
55
|
det_dist_to_beam_converter_path=self.det_dist_to_beam_converter_path,
|
|
74
56
|
trigger_mode=self.trigger_mode,
|
|
75
|
-
enable_dev_shm=self.
|
|
57
|
+
enable_dev_shm=self.features.compare_cpu_and_gpu_zocalo,
|
|
76
58
|
**optional_args,
|
|
77
59
|
)
|
|
78
60
|
|
|
79
61
|
|
|
80
|
-
class
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
class RobotLoadThenCentre(GridCommon):
|
|
88
|
-
thawing_time: float = Field(default=CONST.I03.THAWING_TIME)
|
|
89
|
-
|
|
90
|
-
def robot_load_params(self):
|
|
91
|
-
my_params = self.model_dump()
|
|
92
|
-
return RobotLoadAndEnergyChange(**my_params)
|
|
93
|
-
|
|
94
|
-
def pin_centre_then_xray_centre_params(self):
|
|
95
|
-
my_params = self.model_dump()
|
|
96
|
-
del my_params["thawing_time"]
|
|
97
|
-
return PinTipCentreThenXrayCentre(**my_params)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class SpecifiedGridScan(GridCommon, XyzStarts, WithScan):
|
|
101
|
-
"""A specified grid scan is one which has defined values for the start position,
|
|
102
|
-
grid and box sizes, etc., as opposed to parameters for a plan which will create
|
|
103
|
-
those parameters at some point (e.g. through optical pin detection)."""
|
|
104
|
-
|
|
105
|
-
...
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
class ThreeDGridScan(SpecifiedGridScan, SplitScan, WithOptionalEnergyChange):
|
|
62
|
+
class HyperionThreeDGridScan(
|
|
63
|
+
HyperionGridCommon,
|
|
64
|
+
SpecifiedGrid,
|
|
65
|
+
SplitScan,
|
|
66
|
+
WithOptionalEnergyChange,
|
|
67
|
+
WithPandaGridScan,
|
|
68
|
+
):
|
|
109
69
|
"""Parameters representing a so-called 3D grid scan, which consists of doing a
|
|
110
70
|
gridscan in X and Y, followed by one in X and Z."""
|
|
111
71
|
|
|
@@ -127,14 +87,14 @@ class ThreeDGridScan(SpecifiedGridScan, SplitScan, WithOptionalEnergyChange):
|
|
|
127
87
|
x_steps=self.x_steps,
|
|
128
88
|
y_steps=self.y_steps,
|
|
129
89
|
z_steps=self.z_steps,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
90
|
+
x_step_size_mm=self.x_step_size_um / 1000,
|
|
91
|
+
y_step_size_mm=self.y_step_size_um / 1000,
|
|
92
|
+
z_step_size_mm=self.z_step_size_um / 1000,
|
|
93
|
+
x_start_mm=self.x_start_um / 1000,
|
|
94
|
+
y1_start_mm=self.y_start_um / 1000,
|
|
95
|
+
z1_start_mm=self.z_start_um / 1000,
|
|
96
|
+
y2_start_mm=self.y2_start_um / 1000,
|
|
97
|
+
z2_start_mm=self.z2_start_um / 1000,
|
|
138
98
|
set_stub_offsets=self.features.set_stub_offsets,
|
|
139
99
|
dwell_time_ms=self.exposure_time_s * 1000,
|
|
140
100
|
transmission_fraction=self.transmission_frac,
|
|
@@ -143,6 +103,7 @@ class ThreeDGridScan(SpecifiedGridScan, SplitScan, WithOptionalEnergyChange):
|
|
|
143
103
|
@property
|
|
144
104
|
def panda_FGS_params(self) -> PandAGridScanParams:
|
|
145
105
|
if self.y_steps % 2 and self.z_steps > 0:
|
|
106
|
+
# See https://github.com/DiamondLightSource/hyperion/issues/1118 for explanation
|
|
146
107
|
raise OddYStepsException(
|
|
147
108
|
"The number of Y steps must be even for a PandA gridscan"
|
|
148
109
|
)
|
|
@@ -150,14 +111,14 @@ class ThreeDGridScan(SpecifiedGridScan, SplitScan, WithOptionalEnergyChange):
|
|
|
150
111
|
x_steps=self.x_steps,
|
|
151
112
|
y_steps=self.y_steps,
|
|
152
113
|
z_steps=self.z_steps,
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
114
|
+
x_step_size_mm=self.x_step_size_um / 1000,
|
|
115
|
+
y_step_size_mm=self.y_step_size_um / 1000,
|
|
116
|
+
z_step_size_mm=self.z_step_size_um / 1000,
|
|
117
|
+
x_start_mm=self.x_start_um / 1000,
|
|
118
|
+
y1_start_mm=self.y_start_um / 1000,
|
|
119
|
+
z1_start_mm=self.z_start_um / 1000,
|
|
120
|
+
y2_start_mm=self.y2_start_um / 1000,
|
|
121
|
+
z2_start_mm=self.z2_start_um / 1000,
|
|
161
122
|
set_stub_offsets=self.features.set_stub_offsets,
|
|
162
123
|
run_up_distance_mm=self.panda_runup_distance_mm,
|
|
163
124
|
transmission_fraction=self.transmission_frac,
|
|
@@ -2,12 +2,13 @@ from typing import TypeVar
|
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel, model_validator
|
|
4
4
|
|
|
5
|
-
from mx_bluesky.
|
|
6
|
-
|
|
5
|
+
from mx_bluesky.common.parameters.components import (
|
|
6
|
+
MxBlueskyParameters,
|
|
7
|
+
WithCentreSelection,
|
|
7
8
|
WithSample,
|
|
8
9
|
WithVisit,
|
|
9
10
|
)
|
|
10
|
-
from mx_bluesky.
|
|
11
|
+
from mx_bluesky.common.parameters.gridscan import (
|
|
11
12
|
RobotLoadThenCentre,
|
|
12
13
|
)
|
|
13
14
|
from mx_bluesky.hyperion.parameters.rotation import MultiRotationScan
|
|
@@ -15,13 +16,15 @@ from mx_bluesky.hyperion.parameters.rotation import MultiRotationScan
|
|
|
15
16
|
T = TypeVar("T", bound=BaseModel)
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
def construct_from_values(parent_context: dict,
|
|
19
|
-
values =
|
|
20
|
-
values |=
|
|
19
|
+
def construct_from_values(parent_context: dict, child_dict: dict, t: type[T]) -> T:
|
|
20
|
+
values = {k: v for k, v in parent_context.items() if not isinstance(v, dict)}
|
|
21
|
+
values |= child_dict
|
|
21
22
|
return t(**values)
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
class LoadCentreCollect(
|
|
25
|
+
class LoadCentreCollect(
|
|
26
|
+
MxBlueskyParameters, WithVisit, WithSample, WithCentreSelection
|
|
27
|
+
):
|
|
25
28
|
"""Experiment parameters to perform the combined robot load,
|
|
26
29
|
pin-tip centre and rotation scan operations."""
|
|
27
30
|
|
|
@@ -41,10 +44,12 @@ class LoadCentreCollect(HyperionParameters, WithVisit, WithSample):
|
|
|
41
44
|
disallowed_keys == set()
|
|
42
45
|
), f"Unexpected fields found in LoadCentreCollect {disallowed_keys}"
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
values, "robot_load_then_centre", RobotLoadThenCentre
|
|
47
|
+
new_robot_load_then_centre_params = construct_from_values(
|
|
48
|
+
values, values["robot_load_then_centre"], RobotLoadThenCentre
|
|
46
49
|
)
|
|
47
|
-
|
|
48
|
-
values, "multi_rotation_scan", MultiRotationScan
|
|
50
|
+
new_multi_rotation_scan_params = construct_from_values(
|
|
51
|
+
values, values["multi_rotation_scan"], MultiRotationScan
|
|
49
52
|
)
|
|
53
|
+
values["multi_rotation_scan"] = new_multi_rotation_scan_params
|
|
54
|
+
values["robot_load_then_centre"] = new_robot_load_then_centre_params
|
|
50
55
|
return values
|
|
@@ -17,7 +17,7 @@ from scanspec.core import AxesPoints
|
|
|
17
17
|
from scanspec.core import Path as ScanPath
|
|
18
18
|
from scanspec.specs import Line
|
|
19
19
|
|
|
20
|
-
from mx_bluesky.
|
|
20
|
+
from mx_bluesky.common.parameters.components import (
|
|
21
21
|
DiffractionExperimentWithSample,
|
|
22
22
|
IspybExperimentType,
|
|
23
23
|
OptionalGonioAngleStarts,
|
|
@@ -47,7 +47,9 @@ class RotationExperiment(DiffractionExperimentWithSample):
|
|
|
47
47
|
default=IspybExperimentType.ROTATION
|
|
48
48
|
)
|
|
49
49
|
|
|
50
|
-
def
|
|
50
|
+
def _detector_params_impl(
|
|
51
|
+
self, omega_start_deg: float, num_images_per_trigger: int, num_triggers: int
|
|
52
|
+
) -> DetectorParams:
|
|
51
53
|
self.det_dist_to_beam_converter_path = (
|
|
52
54
|
self.det_dist_to_beam_converter_path
|
|
53
55
|
or CONST.PARAM.DETECTOR.BEAM_XY_LUT_PATH
|
|
@@ -66,13 +68,16 @@ class RotationExperiment(DiffractionExperimentWithSample):
|
|
|
66
68
|
detector_distance=self.detector_distance_mm,
|
|
67
69
|
omega_start=omega_start_deg,
|
|
68
70
|
omega_increment=self.rotation_increment_deg,
|
|
69
|
-
num_images_per_trigger=
|
|
70
|
-
num_triggers=
|
|
71
|
+
num_images_per_trigger=num_images_per_trigger,
|
|
72
|
+
num_triggers=num_triggers,
|
|
71
73
|
use_roi_mode=False,
|
|
72
74
|
det_dist_to_beam_converter_path=self.det_dist_to_beam_converter_path,
|
|
73
75
|
**optional_args,
|
|
74
76
|
)
|
|
75
77
|
|
|
78
|
+
def _detector_params(self, omega_start_deg: float) -> DetectorParams:
|
|
79
|
+
return self._detector_params_impl(omega_start_deg, self.num_images, 1)
|
|
80
|
+
|
|
76
81
|
@field_validator("selected_aperture")
|
|
77
82
|
@classmethod
|
|
78
83
|
def _set_default_aperture_position(cls, aperture_position: ApertureValue | None):
|
|
@@ -115,12 +120,16 @@ class MultiRotationScan(RotationExperiment, SplitScan):
|
|
|
115
120
|
|
|
116
121
|
def _single_rotation_scan(self, scan: RotationScanPerSweep) -> RotationScan:
|
|
117
122
|
# self has everything from RotationExperiment
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
allowed_keys = RotationScan.model_fields.keys() # type: ignore # mypy doesn't recognise this as a property...
|
|
124
|
+
params_dump = self.model_dump()
|
|
120
125
|
# provided `scan` has everything from RotationScanPerSweep
|
|
121
|
-
|
|
126
|
+
scan_dump = scan.model_dump()
|
|
127
|
+
rotation_scan_kv_pairs = {
|
|
128
|
+
k: v for k, v in (params_dump | scan_dump).items() if k in allowed_keys
|
|
129
|
+
}
|
|
122
130
|
# together they have everything for RotationScan
|
|
123
|
-
|
|
131
|
+
rotation_scan = RotationScan(**rotation_scan_kv_pairs)
|
|
132
|
+
return rotation_scan
|
|
124
133
|
|
|
125
134
|
@model_validator(mode="after")
|
|
126
135
|
@classmethod
|
|
@@ -152,8 +161,12 @@ class MultiRotationScan(RotationExperiment, SplitScan):
|
|
|
152
161
|
return list(accumulate([0, *self._num_images_per_scan()]))
|
|
153
162
|
|
|
154
163
|
@property
|
|
155
|
-
def detector_params(self):
|
|
156
|
-
return self.
|
|
164
|
+
def detector_params(self) -> DetectorParams:
|
|
165
|
+
return self._detector_params_impl(
|
|
166
|
+
self.rotation_scans[0].omega_start_deg,
|
|
167
|
+
self._num_images_per_scan()[0],
|
|
168
|
+
len(self._num_images_per_scan()),
|
|
169
|
+
)
|
|
157
170
|
|
|
158
171
|
@property
|
|
159
172
|
def ispyb_params(self): # pyright: ignore
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from math import asin
|
|
3
|
+
|
|
1
4
|
from scanspec.core import AxesPoints, Axis
|
|
2
5
|
from scipy.constants import physical_constants
|
|
3
6
|
|
|
@@ -23,3 +26,17 @@ def convert_angstrom_to_eV(wavelength: float) -> float:
|
|
|
23
26
|
def number_of_frames_from_scan_spec(scan_points: AxesPoints[Axis]):
|
|
24
27
|
ax = list(scan_points.keys())[0]
|
|
25
28
|
return len(scan_points[ax])
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def energy_to_bragg_angle(energy_kev: float, d_a: float) -> float:
|
|
32
|
+
"""Compute the bragg angle given the energy in kev.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
energy_kev: The energy in keV
|
|
36
|
+
d_a: The lattice spacing in Angstroms
|
|
37
|
+
Returns:
|
|
38
|
+
The bragg angle in degrees
|
|
39
|
+
"""
|
|
40
|
+
wavelength_a = convert_eV_to_angstrom(energy_kev * 1000)
|
|
41
|
+
d = d_a
|
|
42
|
+
return asin(wavelength_a / (2 * d)) * 180 / math.pi
|
|
@@ -8,7 +8,7 @@ from unittest.mock import patch
|
|
|
8
8
|
import bluesky.preprocessors as bpp
|
|
9
9
|
from bluesky.run_engine import RunEngine
|
|
10
10
|
from dodal.beamlines import i03
|
|
11
|
-
from dodal.devices.oav.oav_parameters import
|
|
11
|
+
from dodal.devices.oav.oav_parameters import OAVConfig
|
|
12
12
|
from ophyd_async.core import set_mock_value
|
|
13
13
|
|
|
14
14
|
from mx_bluesky.hyperion.device_setup_plans.read_hardware_for_setup import (
|
|
@@ -23,8 +23,8 @@ from mx_bluesky.hyperion.external_interaction.callbacks.rotation.nexus_callback
|
|
|
23
23
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
24
24
|
from mx_bluesky.hyperion.parameters.rotation import RotationScan
|
|
25
25
|
|
|
26
|
-
DISPLAY_CONFIGURATION = "tests/
|
|
27
|
-
ZOOM_LEVELS_XML = "tests/
|
|
26
|
+
DISPLAY_CONFIGURATION = "tests/test_data/test_display.configuration"
|
|
27
|
+
ZOOM_LEVELS_XML = "tests/test_data/test_jCameraManZoomLevels.xml"
|
|
28
28
|
TEST_DATA_DIRECTORY = Path("tests/test_data/nexus_files/rotation")
|
|
29
29
|
TEST_METAFILE = "ins_8_5_meta.h5.gz"
|
|
30
30
|
FAKE_DATAFILE = "../fake_data.h5"
|
|
@@ -94,15 +94,14 @@ def fake_create_rotation_devices():
|
|
|
94
94
|
robot = i03.robot(fake_with_ophyd_sim=True)
|
|
95
95
|
oav = i03.oav(
|
|
96
96
|
fake_with_ophyd_sim=True,
|
|
97
|
-
params=
|
|
98
|
-
zoom_params_file=ZOOM_LEVELS_XML,
|
|
97
|
+
params=OAVConfig(
|
|
98
|
+
zoom_params_file=ZOOM_LEVELS_XML, display_config_file=DISPLAY_CONFIGURATION
|
|
99
99
|
),
|
|
100
100
|
)
|
|
101
101
|
xbpm_feedback = i03.xbpm_feedback(fake_with_ophyd_sim=True)
|
|
102
102
|
|
|
103
103
|
set_mock_value(smargon.omega.max_velocity, 131)
|
|
104
104
|
set_mock_value(dcm.energy_in_kev.user_readback, 12700)
|
|
105
|
-
oav.zoom_controller.fvst.sim_put("1.0x") # type: ignore
|
|
106
105
|
|
|
107
106
|
return RotationScanComposite(
|
|
108
107
|
attenuator=attenuator,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mx-bluesky
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1a0
|
|
4
4
|
Summary: Bluesky tools for MX Beamlines at DLS
|
|
5
5
|
Author-email: Dominic Oram <dominic.oram@diamond.ac.uk>
|
|
6
|
-
License:
|
|
6
|
+
License: Apache License
|
|
7
7
|
Version 2.0, January 2004
|
|
8
8
|
http://www.apache.org/licenses/
|
|
9
9
|
|
|
@@ -213,7 +213,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
213
213
|
Requires-Python: >=3.11
|
|
214
214
|
Description-Content-Type: text/x-rst
|
|
215
215
|
License-File: LICENSE
|
|
216
|
-
Requires-Dist:
|
|
216
|
+
Requires-Dist: annotated_types
|
|
217
217
|
Requires-Dist: caproto
|
|
218
218
|
Requires-Dist: fastapi[all]
|
|
219
219
|
Requires-Dist: flask-restful
|
|
@@ -226,43 +226,46 @@ Requires-Dist: opencv-python
|
|
|
226
226
|
Requires-Dist: opentelemetry-distro
|
|
227
227
|
Requires-Dist: opentelemetry-exporter-otlp
|
|
228
228
|
Requires-Dist: pydantic
|
|
229
|
+
Requires-Dist: pydantic-extra-types
|
|
229
230
|
Requires-Dist: pyepics
|
|
230
231
|
Requires-Dist: pyzmq
|
|
231
232
|
Requires-Dist: requests
|
|
232
233
|
Requires-Dist: scanspec
|
|
233
234
|
Requires-Dist: scipy
|
|
234
235
|
Requires-Dist: semver
|
|
235
|
-
Requires-Dist:
|
|
236
|
-
Requires-Dist:
|
|
237
|
-
Requires-Dist:
|
|
238
|
-
Requires-Dist: ophyd
|
|
239
|
-
Requires-Dist:
|
|
240
|
-
Requires-Dist:
|
|
236
|
+
Requires-Dist: matplotlib
|
|
237
|
+
Requires-Dist: blueapi>=0.5.0
|
|
238
|
+
Requires-Dist: daq-config-server>=0.1.1
|
|
239
|
+
Requires-Dist: ophyd==1.9.0
|
|
240
|
+
Requires-Dist: ophyd-async>=0.8a5
|
|
241
|
+
Requires-Dist: bluesky>=1.13.0a4
|
|
242
|
+
Requires-Dist: dls-dodal==1.36.1a
|
|
241
243
|
Provides-Extra: dev
|
|
242
|
-
Requires-Dist: black
|
|
243
|
-
Requires-Dist: build
|
|
244
|
-
Requires-Dist: diff-cover
|
|
245
|
-
Requires-Dist: GitPython
|
|
246
|
-
Requires-Dist:
|
|
247
|
-
Requires-Dist:
|
|
248
|
-
Requires-Dist:
|
|
249
|
-
Requires-Dist:
|
|
250
|
-
Requires-Dist:
|
|
251
|
-
Requires-Dist:
|
|
252
|
-
Requires-Dist:
|
|
253
|
-
Requires-Dist:
|
|
254
|
-
Requires-Dist: pytest-
|
|
255
|
-
Requires-Dist: pytest-
|
|
256
|
-
Requires-Dist: pytest
|
|
257
|
-
Requires-Dist:
|
|
258
|
-
Requires-Dist:
|
|
259
|
-
Requires-Dist: sphinx-
|
|
260
|
-
Requires-Dist:
|
|
261
|
-
Requires-Dist:
|
|
262
|
-
Requires-Dist:
|
|
263
|
-
Requires-Dist: tox
|
|
264
|
-
Requires-Dist:
|
|
265
|
-
Requires-Dist: types-
|
|
244
|
+
Requires-Dist: black; extra == "dev"
|
|
245
|
+
Requires-Dist: build; extra == "dev"
|
|
246
|
+
Requires-Dist: diff-cover; extra == "dev"
|
|
247
|
+
Requires-Dist: GitPython; extra == "dev"
|
|
248
|
+
Requires-Dist: import-linter; extra == "dev"
|
|
249
|
+
Requires-Dist: ipython; extra == "dev"
|
|
250
|
+
Requires-Dist: mypy; extra == "dev"
|
|
251
|
+
Requires-Dist: myst-parser; extra == "dev"
|
|
252
|
+
Requires-Dist: pipdeptree; extra == "dev"
|
|
253
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
254
|
+
Requires-Dist: pydata-sphinx-theme>=0.12; extra == "dev"
|
|
255
|
+
Requires-Dist: pyright; extra == "dev"
|
|
256
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
257
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
258
|
+
Requires-Dist: pytest-random-order; extra == "dev"
|
|
259
|
+
Requires-Dist: pytest; extra == "dev"
|
|
260
|
+
Requires-Dist: ruff; extra == "dev"
|
|
261
|
+
Requires-Dist: sphinx-autobuild; extra == "dev"
|
|
262
|
+
Requires-Dist: sphinx-copybutton; extra == "dev"
|
|
263
|
+
Requires-Dist: sphinxcontrib-plantuml; extra == "dev"
|
|
264
|
+
Requires-Dist: sphinx-design; extra == "dev"
|
|
265
|
+
Requires-Dist: tox-direct; extra == "dev"
|
|
266
|
+
Requires-Dist: tox; extra == "dev"
|
|
267
|
+
Requires-Dist: types-mock; extra == "dev"
|
|
268
|
+
Requires-Dist: types-requests; extra == "dev"
|
|
266
269
|
|
|
267
270
|
mx-bluesky
|
|
268
271
|
===========================
|