mx-bluesky 1.4.1a0__py3-none-any.whl → 1.4.3__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/i04/redis_to_murko_forwarder.py +178 -0
- mx_bluesky/beamlines/i24/serial/__init__.py +0 -6
- mx_bluesky/beamlines/i24/serial/dcid.py +125 -151
- mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +1 -1
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +88 -43
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +1 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/MappingLite-oxford_py3v1.edl +2 -46
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +85 -122
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +58 -66
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +1 -19
- mx_bluesky/beamlines/i24/serial/parameters/__init__.py +11 -2
- mx_bluesky/beamlines/i24/serial/parameters/constants.py +16 -2
- mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +94 -19
- mx_bluesky/beamlines/i24/serial/parameters/utils.py +19 -0
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +2 -0
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +61 -8
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +81 -40
- mx_bluesky/beamlines/i24/serial/write_nexus.py +66 -67
- mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/aperture_change_callback.py +1 -1
- mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/grid_detection_callback.py +19 -1
- mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/ispyb_callback_base.py +40 -34
- mx_bluesky/{hyperion → common}/external_interaction/callbacks/common/ispyb_mapping.py +4 -4
- mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/logging_callback.py +1 -1
- mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/zocalo_callback.py +14 -9
- mx_bluesky/{hyperion → common}/external_interaction/callbacks/xray_centre/ispyb_callback.py +46 -38
- mx_bluesky/{hyperion → common}/external_interaction/callbacks/xray_centre/ispyb_mapping.py +2 -2
- mx_bluesky/{hyperion → common}/external_interaction/callbacks/xray_centre/nexus_callback.py +20 -15
- mx_bluesky/common/external_interaction/config_server.py +11 -0
- mx_bluesky/common/external_interaction/ispyb/__init__.py +0 -0
- mx_bluesky/{hyperion → common}/external_interaction/ispyb/data_model.py +2 -0
- mx_bluesky/{hyperion → common}/external_interaction/ispyb/exp_eye_store.py +67 -17
- mx_bluesky/{hyperion → common}/external_interaction/ispyb/ispyb_store.py +20 -18
- mx_bluesky/{hyperion → common}/external_interaction/ispyb/ispyb_utils.py +2 -2
- mx_bluesky/common/external_interaction/nexus/__init__.py +0 -0
- mx_bluesky/{hyperion → common}/external_interaction/nexus/nexus_utils.py +21 -6
- mx_bluesky/{hyperion → common}/external_interaction/nexus/write_nexus.py +5 -5
- mx_bluesky/common/external_interaction/test_config_server.py +38 -0
- mx_bluesky/common/parameters/components.py +10 -8
- mx_bluesky/common/parameters/constants.py +6 -0
- mx_bluesky/common/parameters/gridscan.py +102 -53
- mx_bluesky/common/plans/do_fgs.py +4 -4
- mx_bluesky/{hyperion → common/utils}/exceptions.py +27 -1
- mx_bluesky/common/utils/log.py +17 -7
- mx_bluesky/hyperion/__main__.py +15 -14
- mx_bluesky/hyperion/device_setup_plans/check_beamstop.py +27 -0
- mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +34 -37
- mx_bluesky/hyperion/device_setup_plans/manipulate_sample.py +7 -7
- mx_bluesky/hyperion/device_setup_plans/position_detector.py +1 -1
- mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +3 -3
- mx_bluesky/hyperion/device_setup_plans/setup_panda.py +21 -4
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +62 -36
- mx_bluesky/hyperion/device_setup_plans/smargon.py +3 -3
- mx_bluesky/hyperion/device_setup_plans/utils.py +4 -0
- mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +8 -8
- mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +28 -17
- mx_bluesky/hyperion/experiment_plans/common/xrc_result.py +10 -1
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -9
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +54 -58
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +22 -31
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +57 -40
- mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +3 -3
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +8 -2
- mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +6 -14
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +12 -11
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +4 -4
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +39 -30
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +36 -18
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +33 -21
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +10 -9
- mx_bluesky/hyperion/external_interaction/callbacks/__init__.py +0 -4
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +31 -20
- mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +46 -30
- mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +39 -24
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +25 -24
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +13 -9
- mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/__init__.py +0 -0
- mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +50 -0
- mx_bluesky/hyperion/external_interaction/config_server.py +15 -1
- mx_bluesky/hyperion/parameters/components.py +3 -2
- mx_bluesky/hyperion/parameters/constants.py +1 -0
- mx_bluesky/hyperion/parameters/gridscan.py +56 -89
- mx_bluesky/hyperion/parameters/load_centre_collect.py +51 -6
- mx_bluesky/hyperion/parameters/robot_load.py +40 -0
- mx_bluesky/hyperion/parameters/rotation.py +28 -3
- mx_bluesky/hyperion/utils/context.py +1 -1
- mx_bluesky/hyperion/utils/validation.py +5 -3
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.3.dist-info}/METADATA +6 -6
- mx_bluesky-1.4.3.dist-info/RECORD +155 -0
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.3.dist-info}/WHEEL +1 -1
- mx_bluesky/common/parameters/robot_load.py +0 -16
- mx_bluesky/hyperion/external_interaction/exceptions.py +0 -13
- mx_bluesky/hyperion/log.py +0 -15
- mx_bluesky-1.4.1a0.dist-info/RECORD +0 -150
- /mx_bluesky/{hyperion/external_interaction/callbacks/xray_centre → common/external_interaction}/__init__.py +0 -0
- /mx_bluesky/{hyperion/external_interaction/ispyb → common/external_interaction/callbacks/common}/__init__.py +0 -0
- /mx_bluesky/{hyperion → common}/external_interaction/callbacks/common/abstract_event.py +0 -0
- /mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/log_uid_tag_callback.py +0 -0
- /mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/plan_reactive_callback.py +0 -0
- /mx_bluesky/{hyperion/external_interaction/nexus → common/external_interaction/callbacks/xray_centre}/__init__.py +0 -0
- /mx_bluesky/{hyperion → common}/utils/utils.py +0 -0
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.3.dist-info}/LICENSE +0 -0
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.3.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.3.dist-info}/top_level.txt +0 -0
|
@@ -15,22 +15,30 @@ import bluesky.plan_stubs as bps
|
|
|
15
15
|
import numpy as np
|
|
16
16
|
from bluesky.utils import MsgGenerator
|
|
17
17
|
from dodal.common import inject
|
|
18
|
+
from dodal.devices.attenuator.attenuator import ReadOnlyAttenuator
|
|
18
19
|
from dodal.devices.i24.beamstop import Beamstop, BeamstopPositions
|
|
19
20
|
from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
|
|
20
21
|
from dodal.devices.i24.i24_detector_motion import DetectorMotion
|
|
21
22
|
from dodal.devices.i24.pmac import PMAC, EncReset, LaserSettings
|
|
22
23
|
|
|
23
|
-
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import
|
|
24
|
+
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
|
|
25
|
+
ChipType,
|
|
26
|
+
Fiducials,
|
|
27
|
+
MappingType,
|
|
28
|
+
)
|
|
24
29
|
from mx_bluesky.beamlines.i24.serial.log import (
|
|
25
30
|
SSX_LOGGER,
|
|
26
31
|
_read_visit_directory_from_file,
|
|
27
32
|
log_on_entry,
|
|
28
33
|
)
|
|
29
|
-
from mx_bluesky.beamlines.i24.serial.parameters import
|
|
34
|
+
from mx_bluesky.beamlines.i24.serial.parameters import (
|
|
35
|
+
FixedTargetParameters,
|
|
36
|
+
get_chip_format,
|
|
37
|
+
get_chip_map,
|
|
38
|
+
)
|
|
30
39
|
from mx_bluesky.beamlines.i24.serial.parameters.constants import (
|
|
31
40
|
CS_FILES_PATH,
|
|
32
41
|
LITEMAP_PATH,
|
|
33
|
-
PARAM_FILE_NAME,
|
|
34
42
|
PARAM_FILE_PATH_FT,
|
|
35
43
|
PVAR_FILE_PATH,
|
|
36
44
|
)
|
|
@@ -46,6 +54,8 @@ CHIP_MOVES = {
|
|
|
46
54
|
ChipType.Custom: 25.40,
|
|
47
55
|
ChipType.Minichip: 25.40,
|
|
48
56
|
}
|
|
57
|
+
OXFORD_CHIP_WIDTH = 8
|
|
58
|
+
PVAR_TEMPLATE = f"P3%0{2}d1"
|
|
49
59
|
CHIPTYPE_PV = pv.me14e_gp1
|
|
50
60
|
MAPTYPE_PV = pv.me14e_gp2
|
|
51
61
|
NUM_EXPOSURES_PV = pv.me14e_gp3
|
|
@@ -106,21 +116,35 @@ def initialise_stages(
|
|
|
106
116
|
|
|
107
117
|
|
|
108
118
|
@log_on_entry
|
|
109
|
-
def
|
|
119
|
+
def read_parameters(
|
|
110
120
|
detector_stage: DetectorMotion,
|
|
121
|
+
attenuator: ReadOnlyAttenuator,
|
|
111
122
|
) -> MsgGenerator:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
param_path.mkdir(parents=True, exist_ok=True)
|
|
123
|
+
""" Read the parameters from user input and create the parameter model for a fixed \
|
|
124
|
+
target collection.
|
|
115
125
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
126
|
+
Args:
|
|
127
|
+
detector_stage (DetectorMotion): The detector stage device.
|
|
128
|
+
attenuator (ReadOnlyAttenuator): A read-only attenuator device to get the \
|
|
129
|
+
transmission value.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
FixedTargetParameters: Parameter model for fixed target collections
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
SSX_LOGGER.info("Creating parameter model from input.")
|
|
119
136
|
|
|
120
137
|
filename = caget(pv.me14e_chip_name)
|
|
121
138
|
det_type = yield from get_detector_type(detector_stage)
|
|
122
139
|
chip_params = get_chip_format(ChipType(int(caget(CHIPTYPE_PV))))
|
|
123
140
|
map_type = int(caget(MAPTYPE_PV))
|
|
141
|
+
if map_type == MappingType.Lite and chip_params.chip_type in [
|
|
142
|
+
ChipType.Oxford,
|
|
143
|
+
ChipType.OxfordInner,
|
|
144
|
+
]:
|
|
145
|
+
chip_map = get_chip_map()
|
|
146
|
+
else:
|
|
147
|
+
chip_map = []
|
|
124
148
|
pump_repeat = int(caget(PUMP_REPEAT_PV))
|
|
125
149
|
|
|
126
150
|
# If file name ends in a digit this causes processing/pilatus pain.
|
|
@@ -136,6 +160,8 @@ def write_parameter_file(
|
|
|
136
160
|
f"Requested filename ends in a number. Appended dash: {filename}"
|
|
137
161
|
)
|
|
138
162
|
|
|
163
|
+
transmission = yield from bps.rd(attenuator.actual_transmission)
|
|
164
|
+
|
|
139
165
|
params_dict = {
|
|
140
166
|
"visit": _read_visit_directory_from_file().as_posix(), # noqa
|
|
141
167
|
"directory": caget(pv.me14e_filepath),
|
|
@@ -144,24 +170,24 @@ def write_parameter_file(
|
|
|
144
170
|
"detector_distance_mm": caget(pv.me14e_dcdetdist),
|
|
145
171
|
"detector_name": str(det_type),
|
|
146
172
|
"num_exposures": int(caget(NUM_EXPOSURES_PV)),
|
|
147
|
-
"
|
|
173
|
+
"transmission": transmission,
|
|
174
|
+
"chip": chip_params.model_dump(),
|
|
148
175
|
"map_type": map_type,
|
|
149
176
|
"pump_repeat": pump_repeat,
|
|
150
177
|
"checker_pattern": bool(caget(pv.me14e_gp111)),
|
|
151
|
-
"
|
|
152
|
-
"
|
|
178
|
+
"chip_map": chip_map,
|
|
179
|
+
"laser_dwell_s": float(caget(pv.me14e_gp103)) if pump_repeat != 0 else 0.0,
|
|
180
|
+
"laser_delay_s": float(caget(pv.me14e_gp110)) if pump_repeat != 0 else 0.0,
|
|
153
181
|
"pre_pump_exposure_s": float(caget(pv.me14e_gp109))
|
|
154
182
|
if pump_repeat != 0
|
|
155
183
|
else None,
|
|
156
184
|
}
|
|
157
185
|
|
|
158
|
-
|
|
159
|
-
json.dump(params_dict, f, indent=4)
|
|
160
|
-
|
|
161
|
-
SSX_LOGGER.info("Information written to file \n")
|
|
186
|
+
SSX_LOGGER.info("Parameters for I24 serial collection: \n")
|
|
162
187
|
SSX_LOGGER.info(pformat(params_dict))
|
|
163
188
|
|
|
164
189
|
yield from bps.null()
|
|
190
|
+
return FixedTargetParameters(**params_dict)
|
|
165
191
|
|
|
166
192
|
|
|
167
193
|
def scrape_pvar_file(fid: str, pvar_dir: Path = PVAR_FILE_PATH):
|
|
@@ -216,59 +242,25 @@ def define_current_chip(
|
|
|
216
242
|
|
|
217
243
|
|
|
218
244
|
@log_on_entry
|
|
219
|
-
def
|
|
220
|
-
|
|
221
|
-
litemap_path.mkdir(parents=True, exist_ok=True)
|
|
222
|
-
|
|
223
|
-
SSX_LOGGER.info(f"Saving {litemap_path.as_posix()} currentchip.map")
|
|
224
|
-
with open(litemap_path / "currentchip.map", "w") as f:
|
|
225
|
-
SSX_LOGGER.debug("Printing only blocks with block_val == 1")
|
|
226
|
-
for x in range(1, 82):
|
|
227
|
-
block_str = f"ME14E-MO-IOC-01:GP{x + 10:d}"
|
|
228
|
-
block_val = int(caget(block_str))
|
|
229
|
-
if block_val == 1:
|
|
230
|
-
SSX_LOGGER.info(f"{block_str} {block_val:d}")
|
|
231
|
-
line = f"{x:02d}status P3{x:02d}1 \t{block_val}\n"
|
|
232
|
-
f.write(line)
|
|
233
|
-
yield from bps.null()
|
|
245
|
+
def upload_chip_map_to_geobrick(pmac: PMAC, chip_map: list[int]) -> MsgGenerator:
|
|
246
|
+
"""Upload the map parameters for an Oxford-type chip (width=8) to the geobrick.
|
|
234
247
|
|
|
248
|
+
Args:
|
|
249
|
+
pmac (PMAC): The PMAC device.
|
|
250
|
+
chip_map (list[int]): A list of selected blocks to be collected.
|
|
235
251
|
|
|
236
|
-
|
|
237
|
-
def upload_parameters(pmac: PMAC = inject("pmac")) -> MsgGenerator:
|
|
252
|
+
"""
|
|
238
253
|
SSX_LOGGER.info("Uploading Parameters for Oxford Chip to the GeoBrick")
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
SSX_LOGGER.info(f"width {width}")
|
|
249
|
-
x = 1
|
|
250
|
-
for line in f.readlines()[: width**2]:
|
|
251
|
-
cols = line.split()
|
|
252
|
-
pvar = cols[1]
|
|
253
|
-
value = cols[2]
|
|
254
|
-
s = pvar + "=" + value
|
|
255
|
-
if value != "1":
|
|
256
|
-
s2 = pvar + " "
|
|
257
|
-
sys.stdout.write(s2)
|
|
258
|
-
else:
|
|
259
|
-
sys.stdout.write(s + " ")
|
|
260
|
-
sys.stdout.flush()
|
|
261
|
-
if x == width:
|
|
262
|
-
print()
|
|
263
|
-
x = 1
|
|
264
|
-
else:
|
|
265
|
-
x += 1
|
|
266
|
-
yield from bps.abs_set(pmac.pmac_string, s, wait=True)
|
|
267
|
-
sleep(0.02)
|
|
268
|
-
|
|
269
|
-
SSX_LOGGER.warning("Automatic Setting Mapping Type to Lite has been disabled")
|
|
254
|
+
SSX_LOGGER.info(f"Chipid {ChipType.Oxford}, width {OXFORD_CHIP_WIDTH}")
|
|
255
|
+
for block in range(1, 65):
|
|
256
|
+
value = 1 if block in chip_map else 0
|
|
257
|
+
pvar = PVAR_TEMPLATE % block
|
|
258
|
+
pvar_str = f"{pvar}={value}"
|
|
259
|
+
SSX_LOGGER.debug(f"Set {pvar_str} for block {block}")
|
|
260
|
+
yield from bps.abs_set(pmac.pmac_string, pvar_str, wait=True)
|
|
261
|
+
# Wait for PMAC to be done processing PVAR string
|
|
262
|
+
sleep(0.02)
|
|
270
263
|
SSX_LOGGER.debug("Upload parameters done.")
|
|
271
|
-
yield from bps.null()
|
|
272
264
|
|
|
273
265
|
|
|
274
266
|
@log_on_entry
|
|
@@ -3,28 +3,10 @@ Startup utilities for chip
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import string
|
|
6
|
-
from pathlib import Path
|
|
7
6
|
|
|
8
7
|
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import ChipType
|
|
9
8
|
from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER, log_on_entry
|
|
10
|
-
from mx_bluesky.beamlines.i24.serial.parameters import
|
|
11
|
-
FixedTargetParameters,
|
|
12
|
-
get_chip_format,
|
|
13
|
-
)
|
|
14
|
-
from mx_bluesky.beamlines.i24.serial.parameters.constants import (
|
|
15
|
-
PARAM_FILE_NAME,
|
|
16
|
-
PARAM_FILE_PATH_FT,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def read_parameter_file(
|
|
21
|
-
param_path: Path | str = PARAM_FILE_PATH_FT,
|
|
22
|
-
) -> FixedTargetParameters:
|
|
23
|
-
if not isinstance(param_path, Path):
|
|
24
|
-
param_path = Path(param_path)
|
|
25
|
-
params_file = param_path / PARAM_FILE_NAME
|
|
26
|
-
params = FixedTargetParameters.from_file(params_file)
|
|
27
|
-
return params
|
|
9
|
+
from mx_bluesky.beamlines.i24.serial.parameters import get_chip_format
|
|
28
10
|
|
|
29
11
|
|
|
30
12
|
@log_on_entry
|
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
from mx_bluesky.beamlines.i24.serial.parameters.constants import SSXType
|
|
1
|
+
from mx_bluesky.beamlines.i24.serial.parameters.constants import DetectorName, SSXType
|
|
2
2
|
from mx_bluesky.beamlines.i24.serial.parameters.experiment_parameters import (
|
|
3
|
+
BeamSettings,
|
|
3
4
|
ChipDescription,
|
|
4
5
|
ExtruderParameters,
|
|
5
6
|
FixedTargetParameters,
|
|
7
|
+
SerialAndLaserExperiment,
|
|
8
|
+
)
|
|
9
|
+
from mx_bluesky.beamlines.i24.serial.parameters.utils import (
|
|
10
|
+
get_chip_format,
|
|
11
|
+
get_chip_map,
|
|
6
12
|
)
|
|
7
|
-
from mx_bluesky.beamlines.i24.serial.parameters.utils import get_chip_format
|
|
8
13
|
|
|
9
14
|
__all__ = [
|
|
10
15
|
"SSXType",
|
|
16
|
+
"DetectorName",
|
|
17
|
+
"BeamSettings",
|
|
11
18
|
"ExtruderParameters",
|
|
12
19
|
"ChipDescription",
|
|
13
20
|
"FixedTargetParameters",
|
|
21
|
+
"SerialAndLaserExperiment",
|
|
14
22
|
"get_chip_format",
|
|
23
|
+
"get_chip_map",
|
|
15
24
|
]
|
|
@@ -1,15 +1,29 @@
|
|
|
1
|
-
from enum import
|
|
1
|
+
from enum import StrEnum
|
|
2
2
|
from os import environ
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
from mx_bluesky.beamlines.i24.serial.log import _read_visit_directory_from_file
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class SSXType(
|
|
8
|
+
class SSXType(StrEnum):
|
|
9
9
|
FIXED = "Serial Fixed"
|
|
10
10
|
EXTRUDER = "Serial Jet"
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
class DetectorName(StrEnum):
|
|
14
|
+
EIGER = "eiger"
|
|
15
|
+
PILATUS = "pilatus"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# TODO figue sth out for tests
|
|
19
|
+
LUT_FILES_PATH = Path("/dls_sw/i24/software/daq_configuration/lookup")
|
|
20
|
+
|
|
21
|
+
BEAM_CENTER_LUT_FILES = {
|
|
22
|
+
DetectorName.EIGER: LUT_FILES_PATH / "DetDistToBeamXYConverterE9M.txt",
|
|
23
|
+
DetectorName.PILATUS: LUT_FILES_PATH / "DetDistToBeamXYConverterP6M.txt",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
13
27
|
OAV_CONFIG_FILES = {
|
|
14
28
|
"zoom_params_file": "/dls_sw/i24/software/gda_versions/gda_9_34/config/xml/jCameraManZoomLevels.xml",
|
|
15
29
|
"oav_config_json": "/dls_sw/i24/software/daq_configuration/json/OAVCentring.json",
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from abc import abstractmethod
|
|
2
3
|
from pathlib import Path
|
|
3
|
-
from typing import Literal
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import numpy as np
|
|
6
|
+
from dodal.devices.detector.det_dim_constants import (
|
|
7
|
+
EIGER2_X_9M_SIZE,
|
|
8
|
+
PILATUS_6M_SIZE,
|
|
9
|
+
DetectorSizeConstants,
|
|
10
|
+
)
|
|
11
|
+
from pydantic import BaseModel, ConfigDict, computed_field, field_validator
|
|
6
12
|
|
|
7
13
|
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
|
|
8
14
|
ChipType,
|
|
9
15
|
MappingType,
|
|
10
16
|
PumpProbeSetting,
|
|
11
17
|
)
|
|
18
|
+
from mx_bluesky.beamlines.i24.serial.parameters.constants import (
|
|
19
|
+
DetectorName,
|
|
20
|
+
SSXType,
|
|
21
|
+
)
|
|
12
22
|
|
|
13
23
|
|
|
14
24
|
class SerialExperiment(BaseModel):
|
|
@@ -19,7 +29,8 @@ class SerialExperiment(BaseModel):
|
|
|
19
29
|
filename: str
|
|
20
30
|
exposure_time_s: float
|
|
21
31
|
detector_distance_mm: float
|
|
22
|
-
detector_name:
|
|
32
|
+
detector_name: DetectorName
|
|
33
|
+
transmission: float
|
|
23
34
|
|
|
24
35
|
@field_validator("visit", mode="before")
|
|
25
36
|
@classmethod
|
|
@@ -30,29 +41,58 @@ class SerialExperiment(BaseModel):
|
|
|
30
41
|
|
|
31
42
|
@property
|
|
32
43
|
def collection_directory(self) -> Path:
|
|
33
|
-
|
|
44
|
+
directory = Path(self.visit) / self.directory
|
|
45
|
+
return directory
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def detector_size_constants(self) -> DetectorSizeConstants:
|
|
49
|
+
return (
|
|
50
|
+
EIGER2_X_9M_SIZE
|
|
51
|
+
if self.detector_name is DetectorName.EIGER
|
|
52
|
+
else PILATUS_6M_SIZE
|
|
53
|
+
)
|
|
34
54
|
|
|
35
55
|
|
|
36
56
|
class LaserExperiment(BaseModel):
|
|
37
57
|
"""Laser settings for pump probe serial collections."""
|
|
38
58
|
|
|
39
|
-
laser_dwell_s: float
|
|
40
|
-
laser_delay_s: float
|
|
59
|
+
laser_dwell_s: float = 0.0 # pump exposure time
|
|
60
|
+
laser_delay_s: float = 0.0 # pump delay
|
|
41
61
|
pre_pump_exposure_s: float | None = None # Pre illumination, just for chip
|
|
42
62
|
|
|
43
63
|
|
|
44
|
-
class
|
|
45
|
-
"""Extruder parameter model."""
|
|
46
|
-
|
|
47
|
-
num_images: int
|
|
48
|
-
pump_status: bool
|
|
49
|
-
|
|
64
|
+
class SerialAndLaserExperiment(SerialExperiment, LaserExperiment):
|
|
50
65
|
@classmethod
|
|
51
66
|
def from_file(cls, filename: str | Path):
|
|
52
67
|
with open(filename) as fh:
|
|
53
68
|
raw_params = json.load(fh)
|
|
54
69
|
return cls(**raw_params)
|
|
55
70
|
|
|
71
|
+
@property
|
|
72
|
+
@abstractmethod
|
|
73
|
+
def nexgen_experiment_type(self) -> str:
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
@abstractmethod
|
|
78
|
+
def ispyb_experiment_type(self) -> SSXType:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class ExtruderParameters(SerialAndLaserExperiment):
|
|
83
|
+
"""Extruder parameter model."""
|
|
84
|
+
|
|
85
|
+
num_images: int
|
|
86
|
+
pump_status: bool
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def nexgen_experiment_type(self) -> str:
|
|
90
|
+
return "extruder"
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def ispyb_experiment_type(self) -> SSXType:
|
|
94
|
+
return SSXType.EXTRUDER
|
|
95
|
+
|
|
56
96
|
|
|
57
97
|
class ChipDescription(BaseModel):
|
|
58
98
|
"""Parameters defining the chip in use for FT collection."""
|
|
@@ -85,8 +125,12 @@ class ChipDescription(BaseModel):
|
|
|
85
125
|
else:
|
|
86
126
|
return ((self.y_num_steps - 1) * self.y_step_size) + self.b2b_vert
|
|
87
127
|
|
|
128
|
+
@property
|
|
129
|
+
def tot_num_blocks(self) -> int:
|
|
130
|
+
return self.x_blocks * self.y_blocks
|
|
131
|
+
|
|
88
132
|
|
|
89
|
-
class FixedTargetParameters(
|
|
133
|
+
class FixedTargetParameters(SerialAndLaserExperiment):
|
|
90
134
|
"""Fixed target parameter model."""
|
|
91
135
|
|
|
92
136
|
num_exposures: int
|
|
@@ -94,10 +138,41 @@ class FixedTargetParameters(SerialExperiment, LaserExperiment):
|
|
|
94
138
|
map_type: MappingType
|
|
95
139
|
pump_repeat: PumpProbeSetting
|
|
96
140
|
checker_pattern: bool = False
|
|
97
|
-
|
|
141
|
+
chip_map: list[int]
|
|
98
142
|
|
|
99
|
-
@
|
|
100
|
-
def
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
143
|
+
@property
|
|
144
|
+
def nexgen_experiment_type(self) -> str:
|
|
145
|
+
return "fixed-target"
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def ispyb_experiment_type(self) -> SSXType:
|
|
149
|
+
return SSXType.FIXED
|
|
150
|
+
|
|
151
|
+
@computed_field # type: ignore # Mypy doesn't like it
|
|
152
|
+
@property
|
|
153
|
+
def total_num_images(self) -> int:
|
|
154
|
+
match self.map_type:
|
|
155
|
+
case MappingType.NoMap:
|
|
156
|
+
if self.chip.chip_type is ChipType.Custom:
|
|
157
|
+
num_images = (
|
|
158
|
+
self.chip.x_num_steps
|
|
159
|
+
* self.chip.y_num_steps
|
|
160
|
+
* self.num_exposures
|
|
161
|
+
)
|
|
162
|
+
else:
|
|
163
|
+
chip_format = self.chip.chip_format[:4]
|
|
164
|
+
num_images = int(np.prod(chip_format) * self.num_exposures)
|
|
165
|
+
case MappingType.Lite:
|
|
166
|
+
chip_format = self.chip.chip_format[2:4]
|
|
167
|
+
block_count = len(self.chip_map) # type: ignore
|
|
168
|
+
num_images = int(
|
|
169
|
+
np.prod(chip_format) * block_count * self.num_exposures
|
|
170
|
+
)
|
|
171
|
+
return num_images
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class BeamSettings(BaseModel):
|
|
175
|
+
model_config = ConfigDict(frozen=True)
|
|
176
|
+
wavelength_in_a: float
|
|
177
|
+
beam_size_in_um: tuple[float, float]
|
|
178
|
+
beam_center_in_mm: tuple[float, float]
|
|
@@ -6,6 +6,12 @@ from mx_bluesky.beamlines.i24.serial.parameters.experiment_parameters import (
|
|
|
6
6
|
)
|
|
7
7
|
from mx_bluesky.beamlines.i24.serial.setup_beamline import caget, pv
|
|
8
8
|
|
|
9
|
+
OXFORD_BLOCKS_PVS = [f"ME14E-MO-IOC-01:GP{i}" for i in range(11, 75)]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class EmptyMapError(Exception):
|
|
13
|
+
pass
|
|
14
|
+
|
|
9
15
|
|
|
10
16
|
def get_chip_format(chip_type: ChipType) -> ChipDescription:
|
|
11
17
|
"""Default parameter values."""
|
|
@@ -40,3 +46,16 @@ def get_chip_format(chip_type: ChipType) -> ChipDescription:
|
|
|
40
46
|
defaults["b2b_horz"] = defaults["b2b_vert"] = 0.0
|
|
41
47
|
chip_params: dict[str, Any] = {"chip_type": chip_type, **defaults}
|
|
42
48
|
return ChipDescription(**chip_params)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_chip_map() -> list[int]:
|
|
52
|
+
"""Return a list of blocks (the 'chip map') to be collected on an Oxford type chip \
|
|
53
|
+
when using lite mapping."""
|
|
54
|
+
chipmap = []
|
|
55
|
+
for n, block_pv in enumerate(OXFORD_BLOCKS_PVS):
|
|
56
|
+
block_val = int(caget(block_pv))
|
|
57
|
+
if block_val == 1:
|
|
58
|
+
chipmap.append(n + 1)
|
|
59
|
+
if len(chipmap) == 0:
|
|
60
|
+
raise EmptyMapError("No blocks selected for Lite map.")
|
|
61
|
+
return chipmap
|
|
@@ -1,16 +1,60 @@
|
|
|
1
|
+
from pathlib import Path
|
|
1
2
|
from time import sleep
|
|
2
3
|
|
|
3
4
|
import bluesky.plan_stubs as bps
|
|
5
|
+
from dodal.beamlines import i24
|
|
6
|
+
from dodal.devices.detector.det_dim_constants import DetectorSizeConstants
|
|
4
7
|
from dodal.devices.i24.aperture import Aperture, AperturePositions
|
|
8
|
+
from dodal.devices.i24.beam_center import DetectorBeamCenter
|
|
5
9
|
from dodal.devices.i24.beamstop import Beamstop, BeamstopPositions
|
|
6
10
|
from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
|
|
7
11
|
from dodal.devices.i24.i24_detector_motion import DetectorMotion
|
|
12
|
+
from dodal.devices.util.lookup_tables import (
|
|
13
|
+
linear_interpolation_lut,
|
|
14
|
+
parse_lookup_table,
|
|
15
|
+
)
|
|
8
16
|
|
|
9
17
|
from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER
|
|
10
18
|
from mx_bluesky.beamlines.i24.serial.setup_beamline import pv
|
|
11
19
|
from mx_bluesky.beamlines.i24.serial.setup_beamline.ca import caget, caput
|
|
12
20
|
|
|
13
21
|
|
|
22
|
+
def get_beam_center_device(detector_in_use: str) -> DetectorBeamCenter:
|
|
23
|
+
if detector_in_use == "eiger":
|
|
24
|
+
return i24.eiger_beam_center()
|
|
25
|
+
else:
|
|
26
|
+
return i24.pilatus_beam_center()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def compute_beam_center_position_from_lut(
|
|
30
|
+
lut_path: Path,
|
|
31
|
+
detector_distance_mm: float,
|
|
32
|
+
det_size_constants: DetectorSizeConstants,
|
|
33
|
+
) -> tuple[float, float]:
|
|
34
|
+
"""Calculate the beam center position for the detector distance \
|
|
35
|
+
using the values in the lookup table for the conversion.
|
|
36
|
+
"""
|
|
37
|
+
lut_values = parse_lookup_table(lut_path.as_posix())
|
|
38
|
+
|
|
39
|
+
calc_x = linear_interpolation_lut(lut_values[0], lut_values[1])
|
|
40
|
+
beam_x_mm = calc_x(detector_distance_mm)
|
|
41
|
+
beam_x = (
|
|
42
|
+
beam_x_mm
|
|
43
|
+
* det_size_constants.det_size_pixels.width
|
|
44
|
+
/ det_size_constants.det_dimension.width
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
calc_y = linear_interpolation_lut(lut_values[0], lut_values[2])
|
|
48
|
+
beam_y_mm = calc_y(detector_distance_mm)
|
|
49
|
+
beam_y = (
|
|
50
|
+
beam_y_mm
|
|
51
|
+
* det_size_constants.det_size_pixels.height
|
|
52
|
+
/ det_size_constants.det_dimension.height
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return beam_x, beam_y
|
|
56
|
+
|
|
57
|
+
|
|
14
58
|
def setup_beamline_for_collection_plan(
|
|
15
59
|
aperture: Aperture,
|
|
16
60
|
backlight: DualBacklight,
|
|
@@ -43,6 +87,23 @@ def move_detector_stage_to_position_plan(
|
|
|
43
87
|
yield from bps.mv(detector_stage.z, detector_distance) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
44
88
|
|
|
45
89
|
|
|
90
|
+
def set_detector_beam_center_plan(
|
|
91
|
+
beam_center_device: DetectorBeamCenter,
|
|
92
|
+
beam_center_pixels: tuple[float, float],
|
|
93
|
+
group: str = "set_beamcenter",
|
|
94
|
+
wait: bool = True,
|
|
95
|
+
):
|
|
96
|
+
"""A small temporary plan to set up the beam center on the detector in use."""
|
|
97
|
+
# NOTE This will be removed once the detectors are using ophyd_async devices
|
|
98
|
+
# See https://github.com/DiamondLightSource/mx-bluesky/issues/62
|
|
99
|
+
beam_position_x, beam_position_y = beam_center_pixels
|
|
100
|
+
SSX_LOGGER.info(f"Setting beam center to: {beam_position_x}, {beam_position_y}")
|
|
101
|
+
yield from bps.abs_set(beam_center_device.beam_x, beam_position_x, group=group)
|
|
102
|
+
yield from bps.abs_set(beam_center_device.beam_y, beam_position_y, group=group)
|
|
103
|
+
if wait:
|
|
104
|
+
yield from bps.wait(group=group)
|
|
105
|
+
|
|
106
|
+
|
|
46
107
|
def modechange(action):
|
|
47
108
|
"""Mode Change"""
|
|
48
109
|
# Pin Hand Mount
|
|
@@ -232,11 +293,6 @@ def pilatus(action, args_list):
|
|
|
232
293
|
# caput(pv.pilat_wavelength, caget(pv.dcm_lambda))
|
|
233
294
|
caput(pv.pilat_detdist, caget(pv.det_z))
|
|
234
295
|
caput(pv.pilat_filtertrasm, caget(pv.attn_match))
|
|
235
|
-
SSX_LOGGER.warning("WARNING: Have you set beam X and Y?")
|
|
236
|
-
# 16 Fed 2022 last change DA
|
|
237
|
-
caput(pv.pilat_beamx, 1284.7)
|
|
238
|
-
caput(pv.pilat_beamy, 1308.6)
|
|
239
|
-
sleep(0.1)
|
|
240
296
|
|
|
241
297
|
# Fixed Target stage (very fast start and stop w/ triggering from GeoBrick
|
|
242
298
|
if action == "fastchip":
|
|
@@ -330,11 +386,8 @@ def eiger(action, args_list):
|
|
|
330
386
|
SSX_LOGGER.debug(f"Argument: {arg}")
|
|
331
387
|
# caput(pv.eiger_wavelength, caget(pv.dcm_lambda))
|
|
332
388
|
caput(pv.eiger_detdist, str(float(caget(pv.det_z)) / 1000))
|
|
333
|
-
SSX_LOGGER.warning("WARNING: Have you set header info?")
|
|
334
389
|
caput(pv.eiger_wavelength, caget(pv.dcm_lambda))
|
|
335
390
|
caput(pv.eiger_omegaincr, 0.0)
|
|
336
|
-
caput(pv.eiger_beamx, 1600.0)
|
|
337
|
-
caput(pv.eiger_beamy, 1697.4)
|
|
338
391
|
sleep(0.1)
|
|
339
392
|
# Setup common to all collections ###
|
|
340
393
|
caput(pv.eiger_filewriter, "No")
|