mx-bluesky 1.4.1a0__py3-none-any.whl → 1.4.2__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 +66 -36
- 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 +74 -120
- 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 +9 -1
- mx_bluesky/beamlines/i24/serial/parameters/constants.py +6 -0
- mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +75 -16
- 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 +32 -8
- mx_bluesky/beamlines/i24/serial/write_nexus.py +66 -67
- mx_bluesky/common/parameters/components.py +3 -3
- mx_bluesky/common/parameters/constants.py +5 -0
- mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +21 -31
- mx_bluesky/hyperion/device_setup_plans/manipulate_sample.py +6 -6
- mx_bluesky/hyperion/device_setup_plans/smargon.py +3 -3
- mx_bluesky/hyperion/exceptions.py +13 -1
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +16 -10
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +0 -8
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +58 -34
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +8 -2
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +3 -3
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +30 -26
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +26 -7
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +0 -7
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +8 -7
- mx_bluesky/hyperion/external_interaction/callbacks/__init__.py +0 -4
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +4 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +5 -0
- mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +18 -10
- mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/__init__.py +0 -0
- mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +84 -0
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +10 -7
- mx_bluesky/hyperion/external_interaction/exceptions.py +0 -9
- mx_bluesky/hyperion/external_interaction/ispyb/exp_eye_store.py +65 -15
- mx_bluesky/hyperion/utils/validation.py +1 -1
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.2.dist-info}/METADATA +2 -2
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.2.dist-info}/RECORD +49 -46
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.2.dist-info}/LICENSE +0 -0
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.2.dist-info}/WHEEL +0 -0
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.2.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.4.1a0.dist-info → mx_bluesky-1.4.2.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 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,23 @@
|
|
|
1
1
|
from mx_bluesky.beamlines.i24.serial.parameters.constants import 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
|
+
"BeamSettings",
|
|
11
17
|
"ExtruderParameters",
|
|
12
18
|
"ChipDescription",
|
|
13
19
|
"FixedTargetParameters",
|
|
20
|
+
"SerialAndLaserExperiment",
|
|
14
21
|
"get_chip_format",
|
|
22
|
+
"get_chip_map",
|
|
15
23
|
]
|
|
@@ -10,6 +10,12 @@ class SSXType(Enum):
|
|
|
10
10
|
EXTRUDER = "Serial Jet"
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
BEAM_CENTER_POS: dict[str, list] = {
|
|
14
|
+
"eiger": [1600.0, 1697.4],
|
|
15
|
+
"pilatus": [1284.7, 1308.6],
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
13
19
|
OAV_CONFIG_FILES = {
|
|
14
20
|
"zoom_params_file": "/dls_sw/i24/software/gda_versions/gda_9_34/config/xml/jCameraManZoomLevels.xml",
|
|
15
21
|
"oav_config_json": "/dls_sw/i24/software/daq_configuration/json/OAVCentring.json",
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from abc import abstractmethod
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import Literal
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
import numpy as np
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, computed_field, field_validator
|
|
6
8
|
|
|
7
9
|
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
|
|
8
10
|
ChipType,
|
|
9
11
|
MappingType,
|
|
10
12
|
PumpProbeSetting,
|
|
11
13
|
)
|
|
14
|
+
from mx_bluesky.beamlines.i24.serial.parameters.constants import SSXType
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
class SerialExperiment(BaseModel):
|
|
@@ -20,6 +23,7 @@ class SerialExperiment(BaseModel):
|
|
|
20
23
|
exposure_time_s: float
|
|
21
24
|
detector_distance_mm: float
|
|
22
25
|
detector_name: Literal["eiger", "pilatus"]
|
|
26
|
+
transmission: float
|
|
23
27
|
|
|
24
28
|
@field_validator("visit", mode="before")
|
|
25
29
|
@classmethod
|
|
@@ -36,23 +40,43 @@ class SerialExperiment(BaseModel):
|
|
|
36
40
|
class LaserExperiment(BaseModel):
|
|
37
41
|
"""Laser settings for pump probe serial collections."""
|
|
38
42
|
|
|
39
|
-
laser_dwell_s: float
|
|
40
|
-
laser_delay_s: float
|
|
43
|
+
laser_dwell_s: float = 0.0 # pump exposure time
|
|
44
|
+
laser_delay_s: float = 0.0 # pump delay
|
|
41
45
|
pre_pump_exposure_s: float | None = None # Pre illumination, just for chip
|
|
42
46
|
|
|
43
47
|
|
|
44
|
-
class
|
|
45
|
-
"""Extruder parameter model."""
|
|
46
|
-
|
|
47
|
-
num_images: int
|
|
48
|
-
pump_status: bool
|
|
49
|
-
|
|
48
|
+
class SerialAndLaserExperiment(SerialExperiment, LaserExperiment):
|
|
50
49
|
@classmethod
|
|
51
50
|
def from_file(cls, filename: str | Path):
|
|
52
51
|
with open(filename) as fh:
|
|
53
52
|
raw_params = json.load(fh)
|
|
54
53
|
return cls(**raw_params)
|
|
55
54
|
|
|
55
|
+
@property
|
|
56
|
+
@abstractmethod
|
|
57
|
+
def nexgen_experiment_type(self) -> str:
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def ispyb_experiment_type(self) -> SSXType:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ExtruderParameters(SerialAndLaserExperiment):
|
|
67
|
+
"""Extruder parameter model."""
|
|
68
|
+
|
|
69
|
+
num_images: int
|
|
70
|
+
pump_status: bool
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def nexgen_experiment_type(self) -> str:
|
|
74
|
+
return "extruder"
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def ispyb_experiment_type(self) -> SSXType:
|
|
78
|
+
return SSXType.EXTRUDER
|
|
79
|
+
|
|
56
80
|
|
|
57
81
|
class ChipDescription(BaseModel):
|
|
58
82
|
"""Parameters defining the chip in use for FT collection."""
|
|
@@ -85,8 +109,12 @@ class ChipDescription(BaseModel):
|
|
|
85
109
|
else:
|
|
86
110
|
return ((self.y_num_steps - 1) * self.y_step_size) + self.b2b_vert
|
|
87
111
|
|
|
112
|
+
@property
|
|
113
|
+
def tot_num_blocks(self) -> int:
|
|
114
|
+
return self.x_blocks * self.y_blocks
|
|
115
|
+
|
|
88
116
|
|
|
89
|
-
class FixedTargetParameters(
|
|
117
|
+
class FixedTargetParameters(SerialAndLaserExperiment):
|
|
90
118
|
"""Fixed target parameter model."""
|
|
91
119
|
|
|
92
120
|
num_exposures: int
|
|
@@ -94,10 +122,41 @@ class FixedTargetParameters(SerialExperiment, LaserExperiment):
|
|
|
94
122
|
map_type: MappingType
|
|
95
123
|
pump_repeat: PumpProbeSetting
|
|
96
124
|
checker_pattern: bool = False
|
|
97
|
-
|
|
125
|
+
chip_map: list[int]
|
|
98
126
|
|
|
99
|
-
@
|
|
100
|
-
def
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
127
|
+
@property
|
|
128
|
+
def nexgen_experiment_type(self) -> str:
|
|
129
|
+
return "fixed-target"
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def ispyb_experiment_type(self) -> SSXType:
|
|
133
|
+
return SSXType.FIXED
|
|
134
|
+
|
|
135
|
+
@computed_field # type: ignore # Mypy doesn't like it
|
|
136
|
+
@property
|
|
137
|
+
def total_num_images(self) -> int:
|
|
138
|
+
match self.map_type:
|
|
139
|
+
case MappingType.NoMap:
|
|
140
|
+
if self.chip.chip_type is ChipType.Custom:
|
|
141
|
+
num_images = (
|
|
142
|
+
self.chip.x_num_steps
|
|
143
|
+
* self.chip.y_num_steps
|
|
144
|
+
* self.num_exposures
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
chip_format = self.chip.chip_format[:4]
|
|
148
|
+
num_images = int(np.prod(chip_format) * self.num_exposures)
|
|
149
|
+
case MappingType.Lite:
|
|
150
|
+
chip_format = self.chip.chip_format[2:4]
|
|
151
|
+
block_count = len(self.chip_map) # type: ignore
|
|
152
|
+
num_images = int(
|
|
153
|
+
np.prod(chip_format) * block_count * self.num_exposures
|
|
154
|
+
)
|
|
155
|
+
return num_images
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class BeamSettings(BaseModel):
|
|
159
|
+
model_config = ConfigDict(frozen=True)
|
|
160
|
+
wavelength_in_a: float
|
|
161
|
+
beam_size_in_um: tuple[float, float]
|
|
162
|
+
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,26 @@
|
|
|
1
1
|
from time import sleep
|
|
2
2
|
|
|
3
3
|
import bluesky.plan_stubs as bps
|
|
4
|
+
from dodal.beamlines import i24
|
|
4
5
|
from dodal.devices.i24.aperture import Aperture, AperturePositions
|
|
6
|
+
from dodal.devices.i24.beam_center import DetectorBeamCenter
|
|
5
7
|
from dodal.devices.i24.beamstop import Beamstop, BeamstopPositions
|
|
6
8
|
from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
|
|
7
9
|
from dodal.devices.i24.i24_detector_motion import DetectorMotion
|
|
8
10
|
|
|
9
11
|
from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER
|
|
12
|
+
from mx_bluesky.beamlines.i24.serial.parameters.constants import BEAM_CENTER_POS
|
|
10
13
|
from mx_bluesky.beamlines.i24.serial.setup_beamline import pv
|
|
11
14
|
from mx_bluesky.beamlines.i24.serial.setup_beamline.ca import caget, caput
|
|
12
15
|
|
|
13
16
|
|
|
17
|
+
def get_beam_center_device(detector_in_use: str) -> DetectorBeamCenter:
|
|
18
|
+
if detector_in_use == "eiger":
|
|
19
|
+
return i24.eiger_beam_center()
|
|
20
|
+
else:
|
|
21
|
+
return i24.pilatus_beam_center()
|
|
22
|
+
|
|
23
|
+
|
|
14
24
|
def setup_beamline_for_collection_plan(
|
|
15
25
|
aperture: Aperture,
|
|
16
26
|
backlight: DualBacklight,
|
|
@@ -43,6 +53,28 @@ def move_detector_stage_to_position_plan(
|
|
|
43
53
|
yield from bps.mv(detector_stage.z, detector_distance) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
44
54
|
|
|
45
55
|
|
|
56
|
+
def set_detector_beam_center_plan(
|
|
57
|
+
beam_center_device: DetectorBeamCenter,
|
|
58
|
+
detector_name: str,
|
|
59
|
+
group: str = "set_beamcenter",
|
|
60
|
+
wait: bool = True,
|
|
61
|
+
):
|
|
62
|
+
"""A small temporary plan to set up the beam center on the detector in use."""
|
|
63
|
+
# NOTE This will be removed once the detectors are using ophyd_async devices
|
|
64
|
+
# See https://github.com/DiamondLightSource/mx-bluesky/issues/62
|
|
65
|
+
SSX_LOGGER.debug(
|
|
66
|
+
f"Set beam center on {detector_name} detector: {BEAM_CENTER_POS[detector_name]}"
|
|
67
|
+
)
|
|
68
|
+
yield from bps.abs_set(
|
|
69
|
+
beam_center_device.beam_x, BEAM_CENTER_POS[detector_name][0], group=group
|
|
70
|
+
)
|
|
71
|
+
yield from bps.abs_set(
|
|
72
|
+
beam_center_device.beam_y, BEAM_CENTER_POS[detector_name][1], group=group
|
|
73
|
+
)
|
|
74
|
+
if wait:
|
|
75
|
+
yield from bps.wait(group=group)
|
|
76
|
+
|
|
77
|
+
|
|
46
78
|
def modechange(action):
|
|
47
79
|
"""Mode Change"""
|
|
48
80
|
# Pin Hand Mount
|
|
@@ -232,11 +264,6 @@ def pilatus(action, args_list):
|
|
|
232
264
|
# caput(pv.pilat_wavelength, caget(pv.dcm_lambda))
|
|
233
265
|
caput(pv.pilat_detdist, caget(pv.det_z))
|
|
234
266
|
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
267
|
|
|
241
268
|
# Fixed Target stage (very fast start and stop w/ triggering from GeoBrick
|
|
242
269
|
if action == "fastchip":
|
|
@@ -330,11 +357,8 @@ def eiger(action, args_list):
|
|
|
330
357
|
SSX_LOGGER.debug(f"Argument: {arg}")
|
|
331
358
|
# caput(pv.eiger_wavelength, caget(pv.dcm_lambda))
|
|
332
359
|
caput(pv.eiger_detdist, str(float(caget(pv.det_z)) / 1000))
|
|
333
|
-
SSX_LOGGER.warning("WARNING: Have you set header info?")
|
|
334
360
|
caput(pv.eiger_wavelength, caget(pv.dcm_lambda))
|
|
335
361
|
caput(pv.eiger_omegaincr, 0.0)
|
|
336
|
-
caput(pv.eiger_beamx, 1600.0)
|
|
337
|
-
caput(pv.eiger_beamy, 1697.4)
|
|
338
362
|
sleep(0.1)
|
|
339
363
|
# Setup common to all collections ###
|
|
340
364
|
caput(pv.eiger_filewriter, "No")
|