mx-bluesky 1.1.0__py3-none-any.whl → 1.4.0__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 +48 -10
- mx_bluesky/beamlines/i24/serial/__init__.py +3 -0
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +68 -90
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +1 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +104 -126
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +139 -162
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Mapping_py3v1.py +25 -36
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +24 -34
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +14 -11
- mx_bluesky/beamlines/i24/serial/log.py +58 -49
- 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 +31 -7
- 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 +1 -1
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +8 -18
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +2 -2
- mx_bluesky/common/__init__.py +0 -0
- mx_bluesky/common/device_setup_plans/read_hardware_for_setup.py +14 -0
- mx_bluesky/common/parameters/components.py +221 -0
- mx_bluesky/common/parameters/constants.py +133 -0
- mx_bluesky/common/plans/__init__.py +1 -0
- mx_bluesky/common/plans/do_fgs.py +121 -0
- mx_bluesky/common/utils/log.py +116 -0
- mx_bluesky/{hyperion → common/utils}/tracing.py +2 -2
- mx_bluesky/hyperion/__main__.py +11 -9
- 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 +1 -2
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +48 -17
- mx_bluesky/hyperion/device_setup_plans/smargon.py +6 -6
- mx_bluesky/hyperion/device_setup_plans/utils.py +13 -2
- mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +4 -4
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -0
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +59 -108
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +7 -5
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +46 -0
- mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +19 -18
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +8 -5
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +4 -4
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +17 -17
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +241 -0
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +24 -181
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +6 -4
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +3 -11
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +1 -2
- mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +18 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/ispyb_mapping.py +1 -9
- mx_bluesky/hyperion/external_interaction/callbacks/grid_detection_callback.py +18 -13
- mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py +32 -15
- mx_bluesky/hyperion/external_interaction/callbacks/log_uid_tag_callback.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +3 -5
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +4 -3
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +23 -18
- mx_bluesky/hyperion/external_interaction/config_server.py +22 -10
- mx_bluesky/hyperion/external_interaction/ispyb/ispyb_store.py +1 -1
- mx_bluesky/hyperion/external_interaction/ispyb/ispyb_utils.py +0 -2
- 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 +1 -242
- mx_bluesky/hyperion/parameters/constants.py +22 -118
- mx_bluesky/hyperion/parameters/gridscan.py +20 -11
- mx_bluesky/hyperion/parameters/load_centre_collect.py +50 -0
- mx_bluesky/hyperion/parameters/robot_load.py +16 -0
- mx_bluesky/hyperion/parameters/rotation.py +9 -5
- mx_bluesky/hyperion/utils/utils.py +17 -0
- mx_bluesky/hyperion/utils/validation.py +5 -6
- {mx_bluesky-1.1.0.dist-info → mx_bluesky-1.4.0.dist-info}/METADATA +4 -2
- {mx_bluesky-1.1.0.dist-info → mx_bluesky-1.4.0.dist-info}/RECORD +80 -70
- {mx_bluesky-1.1.0.dist-info → mx_bluesky-1.4.0.dist-info}/WHEEL +1 -1
- mx_bluesky/example.py +0 -19
- {mx_bluesky-1.1.0.dist-info → mx_bluesky-1.4.0.dist-info}/LICENSE +0 -0
- {mx_bluesky-1.1.0.dist-info → mx_bluesky-1.4.0.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.1.0.dist-info → mx_bluesky-1.4.0.dist-info}/top_level.txt +0 -0
|
@@ -2,7 +2,6 @@ from typing import TypedDict
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
from bluesky.callbacks import CallbackBase
|
|
5
|
-
from dodal.devices.oav.oav_detector import OAVConfigParams
|
|
6
5
|
from dodal.devices.oav.utils import calculate_x_y_z_of_pixel
|
|
7
6
|
from event_model.documents import Event
|
|
8
7
|
|
|
@@ -26,21 +25,19 @@ class GridParamUpdate(TypedDict):
|
|
|
26
25
|
class GridDetectionCallback(CallbackBase):
|
|
27
26
|
def __init__(
|
|
28
27
|
self,
|
|
29
|
-
oav_params: OAVConfigParams,
|
|
30
28
|
*args,
|
|
31
29
|
) -> None:
|
|
32
30
|
super().__init__(*args)
|
|
33
|
-
self.oav_params = oav_params
|
|
34
31
|
self.start_positions: list = []
|
|
35
32
|
self.box_numbers: list = []
|
|
36
33
|
|
|
37
34
|
def event(self, doc: Event):
|
|
38
35
|
data = doc.get("data")
|
|
39
|
-
top_left_x_px = data["
|
|
40
|
-
box_width_px = data["
|
|
36
|
+
top_left_x_px = data["oav-grid_snapshot-top_left_x"]
|
|
37
|
+
box_width_px = data["oav-grid_snapshot-box_width"]
|
|
41
38
|
x_of_centre_of_first_box_px = top_left_x_px + box_width_px / 2
|
|
42
39
|
|
|
43
|
-
top_left_y_px = data["
|
|
40
|
+
top_left_y_px = data["oav-grid_snapshot-top_left_y"]
|
|
44
41
|
y_of_centre_of_first_box_px = top_left_y_px + box_width_px / 2
|
|
45
42
|
|
|
46
43
|
smargon_omega = data["smargon-omega"]
|
|
@@ -53,23 +50,31 @@ class GridDetectionCallback(CallbackBase):
|
|
|
53
50
|
y_of_centre_of_first_box_px,
|
|
54
51
|
)
|
|
55
52
|
|
|
53
|
+
microns_per_pixel_x = data["oav-microns_per_pixel_x"]
|
|
54
|
+
microns_per_pixel_y = data["oav-microns_per_pixel_y"]
|
|
55
|
+
beam_x = data["oav-beam_centre_i"]
|
|
56
|
+
beam_y = data["oav-beam_centre_j"]
|
|
57
|
+
|
|
56
58
|
position_grid_start = calculate_x_y_z_of_pixel(
|
|
57
|
-
current_xyz,
|
|
59
|
+
current_xyz,
|
|
60
|
+
smargon_omega,
|
|
61
|
+
centre_of_first_box,
|
|
62
|
+
(beam_x, beam_y),
|
|
63
|
+
(microns_per_pixel_x, microns_per_pixel_y),
|
|
58
64
|
)
|
|
59
|
-
|
|
60
65
|
LOGGER.info(f"Calculated start position {position_grid_start}")
|
|
61
66
|
|
|
62
67
|
self.start_positions.append(position_grid_start)
|
|
63
68
|
self.box_numbers.append(
|
|
64
69
|
(
|
|
65
|
-
data["
|
|
66
|
-
data["
|
|
70
|
+
data["oav-grid_snapshot-num_boxes_x"],
|
|
71
|
+
data["oav-grid_snapshot-num_boxes_y"],
|
|
67
72
|
)
|
|
68
73
|
)
|
|
69
74
|
|
|
70
|
-
self.x_step_size_mm = box_width_px *
|
|
71
|
-
self.y_step_size_mm = box_width_px *
|
|
72
|
-
self.z_step_size_mm = box_width_px *
|
|
75
|
+
self.x_step_size_mm = box_width_px * microns_per_pixel_x / 1000
|
|
76
|
+
self.y_step_size_mm = box_width_px * microns_per_pixel_y / 1000
|
|
77
|
+
self.z_step_size_mm = box_width_px * microns_per_pixel_y / 1000
|
|
73
78
|
return doc
|
|
74
79
|
|
|
75
80
|
def get_grid_parameters(self) -> GridParamUpdate:
|
|
@@ -5,9 +5,12 @@ from collections.abc import Callable, Sequence
|
|
|
5
5
|
from typing import TYPE_CHECKING, Any, TypeVar, cast
|
|
6
6
|
|
|
7
7
|
from dodal.beamline_specific_utils.i03 import beam_size_from_aperture
|
|
8
|
+
from dodal.devices.detector import DetectorParams
|
|
8
9
|
from dodal.devices.detector.det_resolution import resolution
|
|
9
10
|
from dodal.devices.synchrotron import SynchrotronMode
|
|
10
11
|
|
|
12
|
+
from mx_bluesky.common.parameters.components import DiffractionExperimentWithSample
|
|
13
|
+
from mx_bluesky.common.utils.log import set_dcgid_tag
|
|
11
14
|
from mx_bluesky.hyperion.external_interaction.callbacks.plan_reactive_callback import (
|
|
12
15
|
PlanReactiveCallback,
|
|
13
16
|
)
|
|
@@ -21,8 +24,7 @@ from mx_bluesky.hyperion.external_interaction.ispyb.ispyb_store import (
|
|
|
21
24
|
StoreInIspyb,
|
|
22
25
|
)
|
|
23
26
|
from mx_bluesky.hyperion.external_interaction.ispyb.ispyb_utils import get_ispyb_config
|
|
24
|
-
from mx_bluesky.hyperion.log import ISPYB_LOGGER
|
|
25
|
-
from mx_bluesky.hyperion.parameters.components import DiffractionExperimentWithSample
|
|
27
|
+
from mx_bluesky.hyperion.log import ISPYB_LOGGER
|
|
26
28
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
27
29
|
from mx_bluesky.hyperion.utils.utils import convert_eV_to_angstrom
|
|
28
30
|
|
|
@@ -33,6 +35,25 @@ if TYPE_CHECKING:
|
|
|
33
35
|
from event_model.documents import Event, EventDescriptor, RunStart, RunStop
|
|
34
36
|
|
|
35
37
|
|
|
38
|
+
def _update_based_on_energy(
|
|
39
|
+
doc: Event,
|
|
40
|
+
detector_params: DetectorParams,
|
|
41
|
+
data_collection_info: DataCollectionInfo,
|
|
42
|
+
):
|
|
43
|
+
"""If energy has been read as part of this reading then add it into the data
|
|
44
|
+
collection info along with the other fields that depend on it."""
|
|
45
|
+
if energy_kev := doc["data"].get("dcm-energy_in_kev", None):
|
|
46
|
+
energy_ev = energy_kev * 1000
|
|
47
|
+
wavelength_angstroms = convert_eV_to_angstrom(energy_ev)
|
|
48
|
+
data_collection_info.wavelength = wavelength_angstroms
|
|
49
|
+
data_collection_info.resolution = resolution(
|
|
50
|
+
detector_params,
|
|
51
|
+
wavelength_angstroms,
|
|
52
|
+
detector_params.detector_distance,
|
|
53
|
+
)
|
|
54
|
+
return data_collection_info
|
|
55
|
+
|
|
56
|
+
|
|
36
57
|
class BaseISPyBCallback(PlanReactiveCallback):
|
|
37
58
|
def __init__(
|
|
38
59
|
self,
|
|
@@ -109,10 +130,13 @@ class BaseISPyBCallback(PlanReactiveCallback):
|
|
|
109
130
|
slitgap_horizontal=doc["data"]["s4_slit_gaps_xgap"],
|
|
110
131
|
slitgap_vertical=doc["data"]["s4_slit_gaps_ygap"],
|
|
111
132
|
)
|
|
133
|
+
hwscan_data_collection_info = _update_based_on_energy(
|
|
134
|
+
doc, self.params.detector_params, hwscan_data_collection_info
|
|
135
|
+
)
|
|
112
136
|
hwscan_position_info = DataCollectionPositionInfo(
|
|
113
|
-
pos_x=doc["data"]["smargon-x"],
|
|
114
|
-
pos_y=doc["data"]["smargon-y"],
|
|
115
|
-
pos_z=doc["data"]["smargon-z"],
|
|
137
|
+
pos_x=float(doc["data"]["smargon-x"]),
|
|
138
|
+
pos_y=float(doc["data"]["smargon-y"]),
|
|
139
|
+
pos_z=float(doc["data"]["smargon-z"]),
|
|
116
140
|
)
|
|
117
141
|
scan_data_infos = self.populate_info_for_update(
|
|
118
142
|
hwscan_data_collection_info, hwscan_position_info, self.params
|
|
@@ -137,16 +161,9 @@ class BaseISPyBCallback(PlanReactiveCallback):
|
|
|
137
161
|
if transmission := doc["data"]["attenuator-actual_transmission"]:
|
|
138
162
|
# Ispyb wants the transmission in a percentage, we use fractions
|
|
139
163
|
hwscan_data_collection_info.transmission = transmission * 100
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
wavelength_angstroms = convert_eV_to_angstrom(energy_ev)
|
|
144
|
-
hwscan_data_collection_info.wavelength = wavelength_angstroms
|
|
145
|
-
hwscan_data_collection_info.resolution = resolution(
|
|
146
|
-
self.params.detector_params,
|
|
147
|
-
wavelength_angstroms,
|
|
148
|
-
self.params.detector_params.detector_distance,
|
|
149
|
-
)
|
|
164
|
+
hwscan_data_collection_info = _update_based_on_energy(
|
|
165
|
+
doc, self.params.detector_params, hwscan_data_collection_info
|
|
166
|
+
)
|
|
150
167
|
scan_data_infos = self.populate_info_for_update(
|
|
151
168
|
hwscan_data_collection_info, None, self.params
|
|
152
169
|
)
|
|
@@ -6,7 +6,6 @@ from event_model.documents import EventDescriptor
|
|
|
6
6
|
|
|
7
7
|
from mx_bluesky.hyperion.external_interaction.callbacks.common.ispyb_mapping import (
|
|
8
8
|
get_proposal_and_session_from_visit_string,
|
|
9
|
-
get_visit_string_from_path,
|
|
10
9
|
)
|
|
11
10
|
from mx_bluesky.hyperion.external_interaction.callbacks.plan_reactive_callback import (
|
|
12
11
|
PlanReactiveCallback,
|
|
@@ -37,10 +36,9 @@ class RobotLoadISPyBCallback(PlanReactiveCallback):
|
|
|
37
36
|
ISPYB_LOGGER.debug(f"ISPyB robot load callback received: {doc}")
|
|
38
37
|
self.run_uid = doc.get("uid")
|
|
39
38
|
assert isinstance(metadata := doc.get("metadata"), dict)
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
proposal, session = get_proposal_and_session_from_visit_string(
|
|
40
|
+
metadata["visit"]
|
|
42
41
|
)
|
|
43
|
-
proposal, session = get_proposal_and_session_from_visit_string(visit)
|
|
44
42
|
self.action_id = self.expeye.start_load(
|
|
45
43
|
proposal,
|
|
46
44
|
session,
|
|
@@ -64,7 +62,7 @@ class RobotLoadISPyBCallback(PlanReactiveCallback):
|
|
|
64
62
|
self.action_id is not None
|
|
65
63
|
), "ISPyB Robot load callback event called unexpectedly"
|
|
66
64
|
barcode = doc["data"]["robot-barcode"]
|
|
67
|
-
oav_snapshot = doc["data"]["
|
|
65
|
+
oav_snapshot = doc["data"]["oav-snapshot-last_saved_path"]
|
|
68
66
|
webcam_snapshot = doc["data"]["webcam-last_saved_path"]
|
|
69
67
|
# I03 uses webcam/oav snapshots in place of before/after snapshots
|
|
70
68
|
self.expeye.update_barcode_and_snapshots(
|
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
from collections.abc import Callable, Sequence
|
|
4
4
|
from typing import TYPE_CHECKING, Any, cast
|
|
5
5
|
|
|
6
|
+
from mx_bluesky.common.parameters.components import IspybExperimentType
|
|
7
|
+
from mx_bluesky.common.utils.log import set_dcgid_tag
|
|
6
8
|
from mx_bluesky.hyperion.external_interaction.callbacks.common.ispyb_mapping import (
|
|
7
9
|
populate_data_collection_group,
|
|
8
10
|
populate_remaining_data_collection_info,
|
|
@@ -22,8 +24,7 @@ from mx_bluesky.hyperion.external_interaction.ispyb.ispyb_store import (
|
|
|
22
24
|
IspybIds,
|
|
23
25
|
StoreInIspyb,
|
|
24
26
|
)
|
|
25
|
-
from mx_bluesky.hyperion.log import ISPYB_LOGGER
|
|
26
|
-
from mx_bluesky.hyperion.parameters.components import IspybExperimentType
|
|
27
|
+
from mx_bluesky.hyperion.log import ISPYB_LOGGER
|
|
27
28
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
28
29
|
from mx_bluesky.hyperion.parameters.rotation import RotationScan
|
|
29
30
|
|
|
@@ -157,7 +158,7 @@ class RotationISPyBCallback(BaseISPyBCallback):
|
|
|
157
158
|
data_collection_info = DataCollectionInfo(
|
|
158
159
|
**{
|
|
159
160
|
f"xtal_snapshot{self._oav_snapshot_event_idx}": data.get(
|
|
160
|
-
"
|
|
161
|
+
"oav-snapshot-last_saved_path"
|
|
161
162
|
)
|
|
162
163
|
}
|
|
163
164
|
)
|
|
@@ -7,8 +7,14 @@ from typing import TYPE_CHECKING, Any
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
from blueapi.core import MsgGenerator
|
|
9
9
|
from bluesky import preprocessors as bpp
|
|
10
|
-
from dodal.devices.zocalo.zocalo_results import
|
|
10
|
+
from dodal.devices.zocalo.zocalo_results import (
|
|
11
|
+
ZOCALO_READING_PLAN_NAME,
|
|
12
|
+
get_processing_results_from_event,
|
|
13
|
+
)
|
|
11
14
|
|
|
15
|
+
from mx_bluesky.common.parameters.components import DiffractionExperimentWithSample
|
|
16
|
+
from mx_bluesky.common.parameters.constants import PlanNameConstants
|
|
17
|
+
from mx_bluesky.common.utils.log import set_dcgid_tag
|
|
12
18
|
from mx_bluesky.hyperion.external_interaction.callbacks.common.ispyb_mapping import (
|
|
13
19
|
populate_data_collection_group,
|
|
14
20
|
populate_remaining_data_collection_info,
|
|
@@ -36,8 +42,7 @@ from mx_bluesky.hyperion.external_interaction.ispyb.ispyb_store import (
|
|
|
36
42
|
IspybIds,
|
|
37
43
|
StoreInIspyb,
|
|
38
44
|
)
|
|
39
|
-
from mx_bluesky.hyperion.log import ISPYB_LOGGER
|
|
40
|
-
from mx_bluesky.hyperion.parameters.components import DiffractionExperimentWithSample
|
|
45
|
+
from mx_bluesky.hyperion.log import ISPYB_LOGGER
|
|
41
46
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
42
47
|
from mx_bluesky.hyperion.parameters.gridscan import (
|
|
43
48
|
GridCommon,
|
|
@@ -85,7 +90,7 @@ class GridscanISPyBCallback(BaseISPyBCallback):
|
|
|
85
90
|
self._processing_start_time: float | None = None
|
|
86
91
|
|
|
87
92
|
def activity_gated_start(self, doc: RunStart):
|
|
88
|
-
if doc.get("subplan_name") ==
|
|
93
|
+
if doc.get("subplan_name") == PlanNameConstants.DO_FGS:
|
|
89
94
|
self._start_of_fgs_uid = doc.get("uid")
|
|
90
95
|
if doc.get("subplan_name") == CONST.PLAN.GRID_DETECT_AND_DO_GRIDSCAN:
|
|
91
96
|
self.uid_to_finalize_on = doc.get("uid")
|
|
@@ -147,7 +152,7 @@ class GridscanISPyBCallback(BaseISPyBCallback):
|
|
|
147
152
|
ISPYB_LOGGER.info(
|
|
148
153
|
f"Amending comment based on Zocalo reading doc: {format_doc_for_log(doc)}"
|
|
149
154
|
)
|
|
150
|
-
raw_results =
|
|
155
|
+
raw_results = get_processing_results_from_event("zocalo", doc)
|
|
151
156
|
if len(raw_results) > 0:
|
|
152
157
|
for n, res in enumerate(raw_results):
|
|
153
158
|
bb = res["bounding_box"]
|
|
@@ -178,25 +183,25 @@ class GridscanISPyBCallback(BaseISPyBCallback):
|
|
|
178
183
|
data = doc["data"]
|
|
179
184
|
data_collection_id = None
|
|
180
185
|
data_collection_info = DataCollectionInfo(
|
|
181
|
-
xtal_snapshot1=data.get("
|
|
182
|
-
xtal_snapshot2=data.get("
|
|
183
|
-
xtal_snapshot3=data.get("
|
|
186
|
+
xtal_snapshot1=data.get("oav-grid_snapshot-last_path_full_overlay"),
|
|
187
|
+
xtal_snapshot2=data.get("oav-grid_snapshot-last_path_outer"),
|
|
188
|
+
xtal_snapshot3=data.get("oav-grid_snapshot-last_saved_path"),
|
|
184
189
|
n_images=(
|
|
185
|
-
data["
|
|
186
|
-
* data["
|
|
190
|
+
data["oav-grid_snapshot-num_boxes_x"]
|
|
191
|
+
* data["oav-grid_snapshot-num_boxes_y"]
|
|
187
192
|
),
|
|
188
193
|
)
|
|
189
|
-
microns_per_pixel_x = data["
|
|
190
|
-
microns_per_pixel_y = data["
|
|
194
|
+
microns_per_pixel_x = data["oav-microns_per_pixel_x"]
|
|
195
|
+
microns_per_pixel_y = data["oav-microns_per_pixel_y"]
|
|
191
196
|
data_collection_grid_info = DataCollectionGridInfo(
|
|
192
|
-
dx_in_mm=data["
|
|
193
|
-
dy_in_mm=data["
|
|
194
|
-
steps_x=data["
|
|
195
|
-
steps_y=data["
|
|
197
|
+
dx_in_mm=data["oav-grid_snapshot-box_width"] * microns_per_pixel_x / 1000,
|
|
198
|
+
dy_in_mm=data["oav-grid_snapshot-box_width"] * microns_per_pixel_y / 1000,
|
|
199
|
+
steps_x=data["oav-grid_snapshot-num_boxes_x"],
|
|
200
|
+
steps_y=data["oav-grid_snapshot-num_boxes_y"],
|
|
196
201
|
microns_per_pixel_x=microns_per_pixel_x,
|
|
197
202
|
microns_per_pixel_y=microns_per_pixel_y,
|
|
198
|
-
snapshot_offset_x_pixel=int(data["
|
|
199
|
-
snapshot_offset_y_pixel=int(data["
|
|
203
|
+
snapshot_offset_x_pixel=int(data["oav-grid_snapshot-top_left_x"]),
|
|
204
|
+
snapshot_offset_y_pixel=int(data["oav-grid_snapshot-top_left_y"]),
|
|
200
205
|
orientation=Orientation.HORIZONTAL,
|
|
201
206
|
snaked=True,
|
|
202
207
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from daq_config_server.client import ConfigServer
|
|
2
|
-
from pydantic import BaseModel
|
|
2
|
+
from pydantic import BaseModel, Field, model_validator
|
|
3
3
|
|
|
4
4
|
from mx_bluesky.hyperion.log import LOGGER
|
|
5
5
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
@@ -17,19 +17,31 @@ def config_server() -> ConfigServer:
|
|
|
17
17
|
class FeatureFlags(BaseModel):
|
|
18
18
|
# The default value will be used as the fallback when doing a best-effort fetch
|
|
19
19
|
# from the service
|
|
20
|
-
use_panda_for_gridscan: bool =
|
|
21
|
-
|
|
22
|
-
set_stub_offsets: bool =
|
|
20
|
+
use_panda_for_gridscan: bool = CONST.I03.USE_PANDA_FOR_GRIDSCAN
|
|
21
|
+
compare_cpu_and_gpu_zocalo: bool = CONST.I03.COMPARE_CPU_AND_GPU_ZOCALO
|
|
22
|
+
set_stub_offsets: bool = CONST.I03.SET_STUB_OFFSETS
|
|
23
23
|
|
|
24
|
+
# Feature values supplied at construction will override values from the config server
|
|
25
|
+
overriden_features: dict = Field(default_factory=dict, exclude=True)
|
|
26
|
+
|
|
27
|
+
@model_validator(mode="before")
|
|
24
28
|
@classmethod
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
def mark_overridden_features(cls, values):
|
|
30
|
+
assert isinstance(values, dict)
|
|
31
|
+
values["overriden_features"] = values.copy()
|
|
32
|
+
return values
|
|
28
33
|
|
|
29
34
|
@classmethod
|
|
30
|
-
def
|
|
31
|
-
|
|
35
|
+
def _get_flags(cls):
|
|
36
|
+
flags = config_server().best_effort_get_all_feature_flags()
|
|
37
|
+
return {f: flags[f] for f in flags if f in cls.model_fields.keys()}
|
|
32
38
|
|
|
33
39
|
def update_self_from_server(self):
|
|
40
|
+
"""Used to update the feature flags from the server during a plan. Where there are flags which were explicitly set from externally supplied parameters, these values will be used instead."""
|
|
34
41
|
for flag, value in self._get_flags().items():
|
|
35
|
-
|
|
42
|
+
updated_value = (
|
|
43
|
+
value
|
|
44
|
+
if flag not in self.overriden_features.keys()
|
|
45
|
+
else self.overriden_features[flag]
|
|
46
|
+
)
|
|
47
|
+
setattr(self, flag, updated_value)
|
|
@@ -11,6 +11,7 @@ from ispyb.sp.mxacquisition import MXAcquisition
|
|
|
11
11
|
from ispyb.strictordereddict import StrictOrderedDict
|
|
12
12
|
from pydantic import BaseModel
|
|
13
13
|
|
|
14
|
+
from mx_bluesky.common.utils.tracing import TRACER
|
|
14
15
|
from mx_bluesky.hyperion.external_interaction.ispyb.data_model import (
|
|
15
16
|
DataCollectionGridInfo,
|
|
16
17
|
DataCollectionGroupInfo,
|
|
@@ -22,7 +23,6 @@ from mx_bluesky.hyperion.external_interaction.ispyb.ispyb_utils import (
|
|
|
22
23
|
get_session_id_from_visit,
|
|
23
24
|
)
|
|
24
25
|
from mx_bluesky.hyperion.log import ISPYB_LOGGER
|
|
25
|
-
from mx_bluesky.hyperion.tracing import TRACER
|
|
26
26
|
|
|
27
27
|
if TYPE_CHECKING:
|
|
28
28
|
pass
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import time
|
|
4
|
-
from datetime import datetime, timedelta
|
|
4
|
+
from datetime import UTC, datetime, timedelta
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
from dodal.devices.detector import DetectorParams
|
|
@@ -93,7 +93,7 @@ def create_goniometer_axes(
|
|
|
93
93
|
|
|
94
94
|
def get_start_and_predicted_end_time(time_expected: float) -> tuple[str, str]:
|
|
95
95
|
time_format = r"%Y-%m-%dT%H:%M:%SZ"
|
|
96
|
-
start = datetime.
|
|
96
|
+
start = datetime.fromtimestamp(time.time(), tz=UTC)
|
|
97
97
|
end_est = start + timedelta(seconds=time_expected)
|
|
98
98
|
return start.strftime(time_format), end_est.strftime(time_format)
|
|
99
99
|
|
|
@@ -15,12 +15,12 @@ from nexgen.nxs_write.nxmx_writer import NXmxFileWriter
|
|
|
15
15
|
from numpy.typing import DTypeLike
|
|
16
16
|
from scanspec.core import AxesPoints
|
|
17
17
|
|
|
18
|
+
from mx_bluesky.common.parameters.components import DiffractionExperimentWithSample
|
|
18
19
|
from mx_bluesky.hyperion.external_interaction.nexus.nexus_utils import (
|
|
19
20
|
create_detector_parameters,
|
|
20
21
|
create_goniometer_axes,
|
|
21
22
|
get_start_and_predicted_end_time,
|
|
22
23
|
)
|
|
23
|
-
from mx_bluesky.hyperion.parameters.components import DiffractionExperimentWithSample
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class NexusWriter:
|
mx_bluesky/hyperion/log.py
CHANGED
|
@@ -1,23 +1,10 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from logging.handlers import TimedRotatingFileHandler
|
|
3
|
-
from os import environ
|
|
4
|
-
from pathlib import Path
|
|
5
2
|
|
|
6
|
-
from dodal.log import (
|
|
7
|
-
ERROR_LOG_BUFFER_LINES,
|
|
8
|
-
CircularMemoryHandler,
|
|
9
|
-
DodalLogHandlers,
|
|
10
|
-
integrate_bluesky_and_ophyd_logging,
|
|
11
|
-
set_up_all_logging_handlers,
|
|
12
|
-
)
|
|
13
3
|
from dodal.log import LOGGER as dodal_logger
|
|
14
4
|
|
|
15
|
-
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
16
|
-
|
|
17
5
|
LOGGER = logging.getLogger("Hyperion")
|
|
18
6
|
LOGGER.setLevel("DEBUG")
|
|
19
7
|
LOGGER.parent = dodal_logger
|
|
20
|
-
__logger_handlers: DodalLogHandlers | None = None
|
|
21
8
|
|
|
22
9
|
ISPYB_LOGGER = logging.getLogger("Hyperion ISPyB and Zocalo callbacks")
|
|
23
10
|
ISPYB_LOGGER.setLevel(logging.DEBUG)
|
|
@@ -26,74 +13,3 @@ NEXUS_LOGGER = logging.getLogger("Hyperion NeXus callbacks")
|
|
|
26
13
|
NEXUS_LOGGER.setLevel(logging.DEBUG)
|
|
27
14
|
|
|
28
15
|
ALL_LOGGERS = [LOGGER, ISPYB_LOGGER, NEXUS_LOGGER]
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class ExperimentMetadataTagFilter(logging.Filter):
|
|
32
|
-
dc_group_id: str | None = None
|
|
33
|
-
run_uid: str | None = None
|
|
34
|
-
|
|
35
|
-
def filter(self, record):
|
|
36
|
-
if self.dc_group_id:
|
|
37
|
-
record.dc_group_id = self.dc_group_id
|
|
38
|
-
if self.run_uid:
|
|
39
|
-
record.run_uid = self.run_uid
|
|
40
|
-
return True
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
tag_filter = ExperimentMetadataTagFilter()
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def set_dcgid_tag(dcgid):
|
|
47
|
-
"""Set the datacollection group id as a tag on all subsequent log messages.
|
|
48
|
-
Setting to None will remove the tag."""
|
|
49
|
-
tag_filter.dc_group_id = dcgid
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def set_uid_tag(uid):
|
|
53
|
-
tag_filter.run_uid = uid
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def do_default_logging_setup(dev_mode=False):
|
|
57
|
-
handlers = set_up_all_logging_handlers(
|
|
58
|
-
dodal_logger,
|
|
59
|
-
_get_logging_dir(),
|
|
60
|
-
"hyperion.log",
|
|
61
|
-
dev_mode,
|
|
62
|
-
ERROR_LOG_BUFFER_LINES,
|
|
63
|
-
CONST.GRAYLOG_PORT,
|
|
64
|
-
)
|
|
65
|
-
integrate_bluesky_and_ophyd_logging(dodal_logger)
|
|
66
|
-
handlers["graylog_handler"].addFilter(tag_filter)
|
|
67
|
-
|
|
68
|
-
global __logger_handlers
|
|
69
|
-
__logger_handlers = handlers
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def _get_debug_handler() -> CircularMemoryHandler:
|
|
73
|
-
assert (
|
|
74
|
-
__logger_handlers is not None
|
|
75
|
-
), "You can only use this after running the default logging setup"
|
|
76
|
-
return __logger_handlers["debug_memory_handler"]
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def flush_debug_handler() -> str:
|
|
80
|
-
"""Writes the contents of the circular debug log buffer to disk and returns the written filename"""
|
|
81
|
-
handler = _get_debug_handler()
|
|
82
|
-
assert isinstance(
|
|
83
|
-
handler.target, TimedRotatingFileHandler
|
|
84
|
-
), "Circular memory handler doesn't have an appropriate fileHandler target"
|
|
85
|
-
handler.flush()
|
|
86
|
-
return handler.target.baseFilename
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def _get_logging_dir() -> Path:
|
|
90
|
-
"""Get the path to write the hyperion log files to.
|
|
91
|
-
|
|
92
|
-
If the HYPERION_LOG_DIR environment variable exists then logs will be put in here.
|
|
93
|
-
If no environment variable is found it will default it to the ./tmp/dev directory.
|
|
94
|
-
|
|
95
|
-
Returns:
|
|
96
|
-
logging_path (Path): Path to the log file for the file handler to write to.
|
|
97
|
-
"""
|
|
98
|
-
logging_path = Path(environ.get("HYPERION_LOG_DIR") or "./tmp/dev/")
|
|
99
|
-
return logging_path
|