mx-bluesky 0.0.2__py3-none-any.whl → 1.1.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/__main__.py +1 -2
- mx_bluesky/_version.py +14 -2
- mx_bluesky/beamlines/i04/__init__.py +3 -0
- mx_bluesky/beamlines/i04/callbacks/murko_callback.py +45 -0
- mx_bluesky/beamlines/i04/thawing_plan.py +85 -0
- mx_bluesky/beamlines/i24/serial/__init__.py +49 -0
- mx_bluesky/beamlines/i24/serial/blueapi_config.yaml +12 -0
- mx_bluesky/{I24 → beamlines/i24}/serial/dcid.py +53 -41
- mx_bluesky/{I24 → beamlines/i24}/serial/extruder/EX-gui-edm/DetStage.edl +3 -4
- mx_bluesky/{I24 → beamlines/i24}/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +28 -32
- mx_bluesky/{I24 → beamlines/i24}/serial/extruder/EX-gui-edm/microdrop_alignment.edl +0 -1
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +516 -0
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/CustomChip_py3v1.edl +3 -4
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/DetStage.edl +3 -4
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +273 -223
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/ME14E-GeneralPurpose.edl +0 -1
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/MappingLite-oxford_py3v1.edl +12 -13
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/PMAC_Command.edl +0 -1
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/Shutter_Control.edl +0 -1
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/microdrop_alignment.edl +0 -1
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/nudgechip.edl +0 -1
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +273 -143
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/short1-laser.png +0 -0
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/short2-laser.png +0 -0
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/ft_utils.py +24 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +808 -0
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +377 -416
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/i24ssx_Chip_Mapping_py3v1.py +34 -40
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +328 -0
- mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/i24ssx_moveonclick.py +66 -48
- mx_bluesky/{I24 → beamlines/i24}/serial/log.py +66 -19
- mx_bluesky/beamlines/i24/serial/parameters/__init__.py +15 -0
- mx_bluesky/beamlines/i24/serial/parameters/constants.py +47 -0
- mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +103 -0
- mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +9 -0
- mx_bluesky/{I24 → beamlines/i24}/serial/parameters/fixed_target/cs/motor_direction.txt +1 -1
- mx_bluesky/{I24 → beamlines/i24}/serial/parameters/fixed_target/pvar_files/minichip-oxford.pvar +1 -1
- mx_bluesky/beamlines/i24/serial/parameters/utils.py +42 -0
- mx_bluesky/beamlines/i24/serial/run_extruder.sh +19 -0
- mx_bluesky/beamlines/i24/serial/run_fixed_target.sh +22 -0
- mx_bluesky/beamlines/i24/serial/run_serial.py +36 -0
- mx_bluesky/{I24 → beamlines/i24}/serial/set_visit_directory.sh +6 -1
- mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/pv.py +1 -62
- mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/pv_abstract.py +6 -7
- mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/setup_beamline.py +90 -269
- mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/setup_detector.py +47 -40
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +459 -0
- mx_bluesky/beamlines/i24/serial/start_blueapi.sh +28 -0
- mx_bluesky/beamlines/i24/serial/write_nexus.py +105 -0
- mx_bluesky/example.py +4 -4
- mx_bluesky/hyperion/__init__.py +1 -0
- mx_bluesky/hyperion/__main__.py +374 -0
- mx_bluesky/hyperion/device_setup_plans/__init__.py +0 -0
- mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +134 -0
- mx_bluesky/hyperion/device_setup_plans/manipulate_sample.py +110 -0
- mx_bluesky/hyperion/device_setup_plans/position_detector.py +16 -0
- mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +60 -0
- mx_bluesky/hyperion/device_setup_plans/setup_oav.py +87 -0
- mx_bluesky/hyperion/device_setup_plans/setup_panda.py +210 -0
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +214 -0
- mx_bluesky/hyperion/device_setup_plans/smargon.py +25 -0
- mx_bluesky/hyperion/device_setup_plans/utils.py +44 -0
- mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +93 -0
- mx_bluesky/hyperion/exceptions.py +47 -0
- mx_bluesky/hyperion/experiment_plans/__init__.py +30 -0
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +84 -0
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +528 -0
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +209 -0
- mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +173 -0
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +81 -0
- mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +463 -0
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +119 -0
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +164 -0
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +322 -0
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +436 -0
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +68 -0
- mx_bluesky/hyperion/external_interaction/__init__.py +9 -0
- mx_bluesky/hyperion/external_interaction/callbacks/__init__.py +10 -0
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +148 -0
- mx_bluesky/hyperion/external_interaction/callbacks/aperture_change_callback.py +22 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/__init__.py +0 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +46 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/ispyb_mapping.py +70 -0
- mx_bluesky/hyperion/external_interaction/callbacks/grid_detection_callback.py +88 -0
- mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py +203 -0
- mx_bluesky/hyperion/external_interaction/callbacks/log_uid_tag_callback.py +20 -0
- mx_bluesky/hyperion/external_interaction/callbacks/logging_callback.py +29 -0
- mx_bluesky/hyperion/external_interaction/callbacks/plan_reactive_callback.py +101 -0
- mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +88 -0
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/__init__.py +0 -0
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +174 -0
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +17 -0
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +102 -0
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/__init__.py +0 -0
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +269 -0
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_mapping.py +53 -0
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py +95 -0
- mx_bluesky/hyperion/external_interaction/callbacks/zocalo_callback.py +92 -0
- mx_bluesky/hyperion/external_interaction/config_server.py +35 -0
- mx_bluesky/hyperion/external_interaction/exceptions.py +13 -0
- mx_bluesky/hyperion/external_interaction/ispyb/__init__.py +0 -0
- mx_bluesky/hyperion/external_interaction/ispyb/data_model.py +95 -0
- mx_bluesky/hyperion/external_interaction/ispyb/exp_eye_store.py +125 -0
- mx_bluesky/hyperion/external_interaction/ispyb/ispyb_store.py +276 -0
- mx_bluesky/hyperion/external_interaction/ispyb/ispyb_utils.py +29 -0
- mx_bluesky/hyperion/external_interaction/nexus/__init__.py +0 -0
- mx_bluesky/hyperion/external_interaction/nexus/nexus_utils.py +148 -0
- mx_bluesky/hyperion/external_interaction/nexus/write_nexus.py +114 -0
- mx_bluesky/hyperion/log.py +99 -0
- mx_bluesky/hyperion/parameters/__init__.py +2 -0
- mx_bluesky/hyperion/parameters/cli.py +68 -0
- mx_bluesky/hyperion/parameters/components.py +253 -0
- mx_bluesky/hyperion/parameters/constants.py +158 -0
- mx_bluesky/hyperion/parameters/gridscan.py +216 -0
- mx_bluesky/hyperion/parameters/rotation.py +160 -0
- mx_bluesky/hyperion/resources/panda/panda-gridscan.yaml +964 -0
- mx_bluesky/hyperion/tracing.py +28 -0
- mx_bluesky/hyperion/utils/context.py +84 -0
- mx_bluesky/hyperion/utils/utils.py +25 -0
- mx_bluesky/hyperion/utils/validation.py +196 -0
- mx_bluesky/jupyter_example.ipynb +3 -2
- {mx_bluesky-0.0.2.dist-info → mx_bluesky-1.1.0.dist-info}/METADATA +53 -32
- mx_bluesky-1.1.0.dist-info/RECORD +136 -0
- {mx_bluesky-0.0.2.dist-info → mx_bluesky-1.1.0.dist-info}/WHEEL +1 -1
- mx_bluesky-1.1.0.dist-info/entry_points.txt +8 -0
- mx_bluesky/I24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +0 -476
- mx_bluesky/I24/serial/fixed_target/FT-gui-edm/ME14E-motors.edl +0 -1874
- mx_bluesky/I24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +0 -706
- mx_bluesky/I24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +0 -463
- mx_bluesky/I24/serial/parameters/__init__.py +0 -5
- mx_bluesky/I24/serial/parameters/constants.py +0 -39
- mx_bluesky/I24/serial/parameters/fixed_target/cs/cs_maker.json +0 -9
- mx_bluesky/I24/serial/parameters/fixed_target/cs/fiducial_1.txt +0 -4
- mx_bluesky/I24/serial/parameters/fixed_target/cs/fiducial_2.txt +0 -4
- mx_bluesky/I24/serial/parameters/fixed_target/litemaps/currentchip.map +0 -81
- mx_bluesky/I24/serial/parameters/fixed_target/parameters.txt +0 -13
- mx_bluesky/I24/serial/run_serial.py +0 -52
- mx_bluesky/I24/serial/write_nexus.py +0 -113
- mx_bluesky-0.0.2.dist-info/RECORD +0 -58
- mx_bluesky-0.0.2.dist-info/entry_points.txt +0 -4
- /mx_bluesky/{I24 → beamlines}/__init__.py +0 -0
- /mx_bluesky/{I24/serial → beamlines/i24}/__init__.py +0 -0
- /mx_bluesky/{I24 → beamlines/i24}/serial/extruder/__init__.py +0 -0
- /mx_bluesky/{I24 → beamlines/i24}/serial/fixed_target/__init__.py +0 -0
- /mx_bluesky/{I24 → beamlines/i24}/serial/parameters/fixed_target/pvar_files/oxford.pvar +0 -0
- /mx_bluesky/{I24 → beamlines/i24}/serial/run_ssx.sh +0 -0
- /mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/__init__.py +0 -0
- /mx_bluesky/{I24 → beamlines/i24}/serial/setup_beamline/ca.py +0 -0
- {mx_bluesky-0.0.2.dist-info → mx_bluesky-1.1.0.dist-info}/LICENSE +0 -0
- {mx_bluesky-0.0.2.dist-info → mx_bluesky-1.1.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,808 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Fixed target data collection
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import shutil
|
|
7
|
+
import time
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from time import sleep
|
|
11
|
+
|
|
12
|
+
import bluesky.plan_stubs as bps
|
|
13
|
+
import bluesky.preprocessors as bpp
|
|
14
|
+
import numpy as np
|
|
15
|
+
from blueapi.core import MsgGenerator
|
|
16
|
+
from dodal.common import inject
|
|
17
|
+
from dodal.devices.hutch_shutter import HutchShutter, ShutterDemand
|
|
18
|
+
from dodal.devices.i24.aperture import Aperture
|
|
19
|
+
from dodal.devices.i24.beamstop import Beamstop
|
|
20
|
+
from dodal.devices.i24.dcm import DCM
|
|
21
|
+
from dodal.devices.i24.dual_backlight import DualBacklight
|
|
22
|
+
from dodal.devices.i24.i24_detector_motion import DetectorMotion
|
|
23
|
+
from dodal.devices.i24.pmac import PMAC
|
|
24
|
+
from dodal.devices.zebra import Zebra
|
|
25
|
+
|
|
26
|
+
from mx_bluesky.beamlines.i24.serial import log
|
|
27
|
+
from mx_bluesky.beamlines.i24.serial.dcid import DCID
|
|
28
|
+
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
|
|
29
|
+
ChipType,
|
|
30
|
+
MappingType,
|
|
31
|
+
PumpProbeSetting,
|
|
32
|
+
)
|
|
33
|
+
from mx_bluesky.beamlines.i24.serial.fixed_target.i24ssx_Chip_Manager_py3v1 import (
|
|
34
|
+
write_parameter_file,
|
|
35
|
+
)
|
|
36
|
+
from mx_bluesky.beamlines.i24.serial.parameters import (
|
|
37
|
+
ChipDescription,
|
|
38
|
+
FixedTargetParameters,
|
|
39
|
+
SSXType,
|
|
40
|
+
)
|
|
41
|
+
from mx_bluesky.beamlines.i24.serial.parameters.constants import (
|
|
42
|
+
LITEMAP_PATH,
|
|
43
|
+
PARAM_FILE_NAME,
|
|
44
|
+
PARAM_FILE_PATH_FT,
|
|
45
|
+
)
|
|
46
|
+
from mx_bluesky.beamlines.i24.serial.setup_beamline import caget, cagetstring, caput, pv
|
|
47
|
+
from mx_bluesky.beamlines.i24.serial.setup_beamline import setup_beamline as sup
|
|
48
|
+
from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_zebra_plans import (
|
|
49
|
+
SHUTTER_OPEN_TIME,
|
|
50
|
+
arm_zebra,
|
|
51
|
+
close_fast_shutter,
|
|
52
|
+
open_fast_shutter,
|
|
53
|
+
open_fast_shutter_at_each_position_plan,
|
|
54
|
+
reset_zebra_when_collection_done_plan,
|
|
55
|
+
setup_zebra_for_fastchip_plan,
|
|
56
|
+
)
|
|
57
|
+
from mx_bluesky.beamlines.i24.serial.write_nexus import call_nexgen
|
|
58
|
+
|
|
59
|
+
ABORTED = False
|
|
60
|
+
|
|
61
|
+
logger = logging.getLogger("I24ssx.fixed_target")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def setup_logging():
|
|
65
|
+
# Log should now change name daily
|
|
66
|
+
logfile = time.strftime("i24fixedtarget_%d%B%y.log").lower()
|
|
67
|
+
log.config(logfile)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def calculate_collection_timeout(parameters: FixedTargetParameters) -> float:
|
|
71
|
+
"""Give an estimation of the time the plan should wait for the data collection \
|
|
72
|
+
to be finished.
|
|
73
|
+
|
|
74
|
+
For non-pump probe collections and collection with short delays, it should be \
|
|
75
|
+
enough to use the collection time plus a genereous 30s buffer.
|
|
76
|
+
For EAVA (Excite and visit again) collections instead, the laser dwell and laser \
|
|
77
|
+
delay times should be included in the calculation. For long dalays between pump \
|
|
78
|
+
and probe, the shutter opening time will also need to be taken into account.
|
|
79
|
+
For more details on the dynamics see
|
|
80
|
+
https://confluence.diamond.ac.uk/display/MXTech/Dynamics+and+fixed+targets.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
parameters (FixedTargerParameters): The collection parameters.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
The estimated collection time, in s.
|
|
87
|
+
"""
|
|
88
|
+
buffer = 30
|
|
89
|
+
pump_setting = parameters.pump_repeat
|
|
90
|
+
collection_time = parameters.total_num_images * parameters.exposure_time_s
|
|
91
|
+
if pump_setting in [
|
|
92
|
+
PumpProbeSetting.NoPP,
|
|
93
|
+
PumpProbeSetting.Short1,
|
|
94
|
+
PumpProbeSetting.Short2,
|
|
95
|
+
]:
|
|
96
|
+
timeout = collection_time + buffer
|
|
97
|
+
else:
|
|
98
|
+
# EAVA: Excite and visit again
|
|
99
|
+
num_windows = parameters.total_num_images / parameters.num_exposures
|
|
100
|
+
timeout = (
|
|
101
|
+
collection_time
|
|
102
|
+
+ parameters.laser_dwell_s * num_windows # type: ignore
|
|
103
|
+
+ parameters.laser_delay_s
|
|
104
|
+
+ buffer
|
|
105
|
+
)
|
|
106
|
+
if pump_setting == PumpProbeSetting.Medium1:
|
|
107
|
+
# Long delay between pump and probe, with fast shutter opening and closing.
|
|
108
|
+
timeout = timeout + SHUTTER_OPEN_TIME
|
|
109
|
+
return timeout
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def copy_files_to_data_location(
|
|
113
|
+
dest_dir: Path | str,
|
|
114
|
+
param_path: Path = PARAM_FILE_PATH_FT,
|
|
115
|
+
map_file: Path = LITEMAP_PATH,
|
|
116
|
+
map_type: MappingType = MappingType.Lite,
|
|
117
|
+
):
|
|
118
|
+
if not isinstance(dest_dir, Path):
|
|
119
|
+
dest_dir = Path(dest_dir)
|
|
120
|
+
shutil.copy2(param_path / "parameters.txt", dest_dir / "parameters.txt")
|
|
121
|
+
if map_type == MappingType.Lite:
|
|
122
|
+
shutil.copy2(map_file / "currentchip.map", dest_dir / "currentchip.map")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def write_userlog(
|
|
126
|
+
parameters: FixedTargetParameters,
|
|
127
|
+
filename: str,
|
|
128
|
+
transmission: float,
|
|
129
|
+
wavelength: float,
|
|
130
|
+
):
|
|
131
|
+
# Write a record of what was collected to the processing directory
|
|
132
|
+
userlog_path = Path(parameters.visit) / f"processing/{parameters.directory}"
|
|
133
|
+
userlog_fid = f"{filename}_parameters.txt"
|
|
134
|
+
logger.debug(f"Write a user log in {userlog_path}")
|
|
135
|
+
|
|
136
|
+
userlog_path.mkdir(parents=True, exist_ok=True)
|
|
137
|
+
|
|
138
|
+
text = f"""
|
|
139
|
+
Fixed Target Data Collection Parameters\n
|
|
140
|
+
Data directory \t{parameters.collection_directory.as_posix()}\n
|
|
141
|
+
Filename \t{filename}\n
|
|
142
|
+
Shots per pos \t{parameters.num_exposures}\n
|
|
143
|
+
Total N images \t{parameters.total_num_images}\n
|
|
144
|
+
Exposure time \t{parameters.exposure_time_s}\n
|
|
145
|
+
Det distance \t{parameters.detector_distance_mm}\n
|
|
146
|
+
Transmission \t{transmission}\n
|
|
147
|
+
Wavelength \t{wavelength}\n
|
|
148
|
+
Detector type \t{parameters.detector_name}\n
|
|
149
|
+
Pump status \t{parameters.pump_repeat}\n
|
|
150
|
+
Pump exp time \t{parameters.laser_dwell_s}\n
|
|
151
|
+
Pump delay \t{parameters.laser_delay_s}\n
|
|
152
|
+
"""
|
|
153
|
+
with open(userlog_path / userlog_fid, "w") as f:
|
|
154
|
+
f.write(text)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@log.log_on_entry
|
|
158
|
+
def get_chip_prog_values(
|
|
159
|
+
parameters: FixedTargetParameters,
|
|
160
|
+
):
|
|
161
|
+
# this is where p variables for fast laser expts will be set
|
|
162
|
+
if parameters.pump_repeat in [
|
|
163
|
+
PumpProbeSetting.NoPP,
|
|
164
|
+
PumpProbeSetting.Short1,
|
|
165
|
+
PumpProbeSetting.Short2,
|
|
166
|
+
PumpProbeSetting.Medium1,
|
|
167
|
+
]:
|
|
168
|
+
pump_repeat_pvar = 0
|
|
169
|
+
elif parameters.pump_repeat == PumpProbeSetting.Repeat1:
|
|
170
|
+
pump_repeat_pvar = 1
|
|
171
|
+
elif parameters.pump_repeat == PumpProbeSetting.Repeat2:
|
|
172
|
+
pump_repeat_pvar = 2
|
|
173
|
+
elif parameters.pump_repeat == PumpProbeSetting.Repeat3:
|
|
174
|
+
pump_repeat_pvar = 3
|
|
175
|
+
elif parameters.pump_repeat == PumpProbeSetting.Repeat5:
|
|
176
|
+
pump_repeat_pvar = 5
|
|
177
|
+
elif parameters.pump_repeat == PumpProbeSetting.Repeat10:
|
|
178
|
+
pump_repeat_pvar = 10
|
|
179
|
+
else:
|
|
180
|
+
raise ValueError(f"Unknown pump_repeat, pump_repeat = {parameters.pump_repeat}")
|
|
181
|
+
|
|
182
|
+
logger.info(
|
|
183
|
+
f"Pump repeat is {str(parameters.pump_repeat)}, PVAR set to {pump_repeat_pvar}"
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
if parameters.pump_repeat == PumpProbeSetting.Short2:
|
|
187
|
+
pump_in_probe = 1
|
|
188
|
+
else:
|
|
189
|
+
pump_in_probe = 0
|
|
190
|
+
|
|
191
|
+
logger.info(f"pump_in_probe set to {pump_in_probe}")
|
|
192
|
+
|
|
193
|
+
chip_dict: dict[str, list] = {
|
|
194
|
+
"X_NUM_STEPS": [11, parameters.chip.x_num_steps],
|
|
195
|
+
"Y_NUM_STEPS": [12, parameters.chip.y_num_steps],
|
|
196
|
+
"X_STEP_SIZE": [13, parameters.chip.x_step_size],
|
|
197
|
+
"Y_STEP_SIZE": [14, parameters.chip.y_step_size],
|
|
198
|
+
"DWELL_TIME": [15, parameters.exposure_time_s],
|
|
199
|
+
"X_START": [16, 0],
|
|
200
|
+
"Y_START": [17, 0],
|
|
201
|
+
"Z_START": [18, 0],
|
|
202
|
+
"X_NUM_BLOCKS": [20, parameters.chip.x_blocks],
|
|
203
|
+
"Y_NUM_BLOCKS": [21, parameters.chip.y_blocks],
|
|
204
|
+
"X_BLOCK_SIZE": [24, parameters.chip.x_block_size],
|
|
205
|
+
"Y_BLOCK_SIZE": [25, parameters.chip.y_block_size],
|
|
206
|
+
"COLTYPE": [26, 41],
|
|
207
|
+
"N_EXPOSURES": [30, parameters.num_exposures],
|
|
208
|
+
"PUMP_REPEAT": [32, pump_repeat_pvar],
|
|
209
|
+
"LASER_DWELL": [34, parameters.laser_dwell_s],
|
|
210
|
+
"LASERTWO_DWELL": [35, parameters.pre_pump_exposure_s],
|
|
211
|
+
"LASER_DELAY": [37, parameters.laser_delay_s],
|
|
212
|
+
"PUMP_IN_PROBE": [38, pump_in_probe],
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
chip_dict["DWELL_TIME"][1] = 1000 * parameters.exposure_time_s
|
|
216
|
+
chip_dict["LASER_DWELL"][1] = (
|
|
217
|
+
1000 * parameters.laser_dwell_s if parameters.laser_dwell_s else 0
|
|
218
|
+
)
|
|
219
|
+
chip_dict["LASERTWO_DWELL"][1] = (
|
|
220
|
+
1000 * parameters.pre_pump_exposure_s if parameters.pre_pump_exposure_s else 0
|
|
221
|
+
)
|
|
222
|
+
chip_dict["LASER_DELAY"][1] = (
|
|
223
|
+
1000 * parameters.laser_delay_s if parameters.laser_delay_s else 0
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
return chip_dict
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@log.log_on_entry
|
|
230
|
+
def load_motion_program_data(
|
|
231
|
+
pmac: PMAC,
|
|
232
|
+
motion_program_dict: dict[str, list],
|
|
233
|
+
map_type: int,
|
|
234
|
+
pump_repeat: int,
|
|
235
|
+
checker_pattern: bool,
|
|
236
|
+
):
|
|
237
|
+
logger.info("Loading motion program data for chip.")
|
|
238
|
+
logger.info(f"Pump_repeat is {PumpProbeSetting(pump_repeat)}")
|
|
239
|
+
if pump_repeat == PumpProbeSetting.NoPP:
|
|
240
|
+
if map_type == MappingType.NoMap:
|
|
241
|
+
prefix = 11
|
|
242
|
+
logger.info(f"Map type is None, setting program prefix to {prefix}")
|
|
243
|
+
elif map_type == MappingType.Lite:
|
|
244
|
+
prefix = 12
|
|
245
|
+
elif map_type == MappingType.Full:
|
|
246
|
+
prefix = 13
|
|
247
|
+
else:
|
|
248
|
+
logger.warning(f"Unknown Map Type, map_type = {map_type}")
|
|
249
|
+
return
|
|
250
|
+
elif pump_repeat in [pp.value for pp in PumpProbeSetting if pp != 0]:
|
|
251
|
+
# Pump setting chosen
|
|
252
|
+
prefix = 14
|
|
253
|
+
logger.info(f"Setting program prefix to {prefix}")
|
|
254
|
+
yield from bps.abs_set(pmac.pmac_string, "P1439=0", wait=True)
|
|
255
|
+
if checker_pattern:
|
|
256
|
+
logger.info("Checker pattern setting enabled.")
|
|
257
|
+
yield from bps.abs_set(pmac.pmac_string, "P1439=1", wait=True)
|
|
258
|
+
if pump_repeat == PumpProbeSetting.Medium1:
|
|
259
|
+
# Medium1 has time delays (Fast shutter opening time in ms)
|
|
260
|
+
yield from bps.abs_set(pmac.pmac_string, "P1441=50", wait=True)
|
|
261
|
+
else:
|
|
262
|
+
yield from bps.abs_set(pmac.pmac_string, "P1441=0", wait=True)
|
|
263
|
+
else:
|
|
264
|
+
logger.warning(f"Unknown Pump repeat, pump_repeat = {pump_repeat}")
|
|
265
|
+
return
|
|
266
|
+
|
|
267
|
+
logger.info("Set PMAC_STRING pv.")
|
|
268
|
+
for key in sorted(motion_program_dict.keys()):
|
|
269
|
+
v = motion_program_dict[key]
|
|
270
|
+
pvar_base = prefix * 100
|
|
271
|
+
pvar = pvar_base + v[0]
|
|
272
|
+
value = str(v[1])
|
|
273
|
+
s = f"P{pvar}={value}"
|
|
274
|
+
logger.info(f"{key} \t {s}")
|
|
275
|
+
yield from bps.abs_set(pmac.pmac_string, s, wait=True)
|
|
276
|
+
yield from bps.sleep(0.02)
|
|
277
|
+
yield from bps.sleep(0.2)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
@log.log_on_entry
|
|
281
|
+
def get_prog_num(
|
|
282
|
+
chip_type: ChipType, map_type: MappingType, pump_repeat: PumpProbeSetting
|
|
283
|
+
) -> int:
|
|
284
|
+
"""Get the motion program number based on the experiment parameters set by \
|
|
285
|
+
the user.
|
|
286
|
+
Any pump probe experiment will return program number 14 (assumes lite mapping).
|
|
287
|
+
For non pump probe experiments, the program number depends on the chip and map type:
|
|
288
|
+
- Custom, Mini and PSI chips, as well as Oxford chips with no map return 11
|
|
289
|
+
- Oxford chips with lite mapping return 12
|
|
290
|
+
- Oxford chips with full mapping should return 13. Currently disabled, will \
|
|
291
|
+
raise an error.
|
|
292
|
+
"""
|
|
293
|
+
logger.info("Get Program Number for the motion program.")
|
|
294
|
+
logger.info(f"Pump_repeat: {str(pump_repeat)} \t Chip Type: {str(chip_type)}")
|
|
295
|
+
if pump_repeat != PumpProbeSetting.NoPP:
|
|
296
|
+
logger.info("Assuming Map type = Mapping Lite.")
|
|
297
|
+
logger.info("Program number: 14")
|
|
298
|
+
return 14
|
|
299
|
+
|
|
300
|
+
if chip_type not in [ChipType.Oxford, ChipType.OxfordInner]:
|
|
301
|
+
logger.info("Program number: 11")
|
|
302
|
+
return 11
|
|
303
|
+
|
|
304
|
+
if map_type == MappingType.NoMap:
|
|
305
|
+
logger.info(f"Map type: {str(map_type)}")
|
|
306
|
+
logger.info("Program number: 11")
|
|
307
|
+
return 11
|
|
308
|
+
if map_type == MappingType.Lite:
|
|
309
|
+
logger.info(f"Map type: {str(map_type)}")
|
|
310
|
+
logger.info("Program number: 12")
|
|
311
|
+
return 12
|
|
312
|
+
if map_type == MappingType.Full:
|
|
313
|
+
# TODO See https://github.com/DiamondLightSource/mx-bluesky/issues/515
|
|
314
|
+
logger.info(f"Map type: {str(map_type)}")
|
|
315
|
+
logger.info("Program number: 13")
|
|
316
|
+
# TODO once reinstated return 13
|
|
317
|
+
msg = "Full mapping is broken and currently disabled."
|
|
318
|
+
logger.error(msg)
|
|
319
|
+
raise ValueError(msg)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
@log.log_on_entry
|
|
323
|
+
def datasetsizei24(
|
|
324
|
+
n_exposures: int,
|
|
325
|
+
chip_params: ChipDescription,
|
|
326
|
+
map_type: MappingType,
|
|
327
|
+
) -> int:
|
|
328
|
+
# Calculates how many images will be collected based on map type and N repeats
|
|
329
|
+
logger.info("Calculate total number of images expected in data collection.")
|
|
330
|
+
|
|
331
|
+
if map_type == MappingType.NoMap:
|
|
332
|
+
if chip_params.chip_type == ChipType.Custom:
|
|
333
|
+
total_numb_imgs = chip_params.x_num_steps * chip_params.y_num_steps
|
|
334
|
+
logger.info(
|
|
335
|
+
f"Map type: None \tCustom chip \tNumber of images {total_numb_imgs}"
|
|
336
|
+
)
|
|
337
|
+
else:
|
|
338
|
+
chip_format = chip_params.chip_format[:4]
|
|
339
|
+
total_numb_imgs = int(np.prod(chip_format))
|
|
340
|
+
logger.info(
|
|
341
|
+
f"""Map type: None \tOxford chip {chip_params.chip_type} \t \
|
|
342
|
+
Number of images {total_numb_imgs}"""
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
elif map_type == MappingType.Lite:
|
|
346
|
+
logger.info(f"Using Mapping Lite on chip type {chip_params.chip_type}")
|
|
347
|
+
chip_format = chip_params.chip_format[2:4]
|
|
348
|
+
block_count = 0
|
|
349
|
+
with open(LITEMAP_PATH / "currentchip.map") as f:
|
|
350
|
+
for line in f.readlines():
|
|
351
|
+
entry = line.split()
|
|
352
|
+
if entry[2] == "1":
|
|
353
|
+
block_count += 1
|
|
354
|
+
|
|
355
|
+
logger.info(f"Block count={block_count}")
|
|
356
|
+
logger.info(f"Chip format={chip_format}")
|
|
357
|
+
|
|
358
|
+
logger.info(f"Number of exposures={n_exposures}")
|
|
359
|
+
|
|
360
|
+
total_numb_imgs = int(np.prod(chip_format) * block_count * n_exposures)
|
|
361
|
+
logger.info(f"Calculated number of images: {total_numb_imgs}")
|
|
362
|
+
|
|
363
|
+
elif map_type == MappingType.Full:
|
|
364
|
+
logger.error("Not Set Up For Full Mapping")
|
|
365
|
+
raise ValueError("The beamline is currently not set for Full Mapping.")
|
|
366
|
+
|
|
367
|
+
else:
|
|
368
|
+
logger.warning(f"Unknown Map Type, map_type = {str(map_type)}")
|
|
369
|
+
raise ValueError("Unknown map type")
|
|
370
|
+
|
|
371
|
+
logger.info("Set PV to calculated number of images.")
|
|
372
|
+
caput(pv.me14e_gp10, int(total_numb_imgs))
|
|
373
|
+
|
|
374
|
+
return int(total_numb_imgs)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
@log.log_on_entry
|
|
378
|
+
def start_i24(
|
|
379
|
+
zebra: Zebra,
|
|
380
|
+
aperture: Aperture,
|
|
381
|
+
backlight: DualBacklight,
|
|
382
|
+
beamstop: Beamstop,
|
|
383
|
+
detector_stage: DetectorMotion,
|
|
384
|
+
shutter: HutchShutter,
|
|
385
|
+
parameters: FixedTargetParameters,
|
|
386
|
+
dcid: DCID,
|
|
387
|
+
):
|
|
388
|
+
"""Set up for I24 fixed target data collection, trigger the detector and open \
|
|
389
|
+
the hutch shutter.
|
|
390
|
+
Returns the start_time.
|
|
391
|
+
"""
|
|
392
|
+
|
|
393
|
+
logger.info("Start I24 data collection.")
|
|
394
|
+
start_time = datetime.now()
|
|
395
|
+
logger.info(f"Collection start time {start_time.ctime()}")
|
|
396
|
+
|
|
397
|
+
logger.debug("Set up beamline")
|
|
398
|
+
yield from sup.setup_beamline_for_collection_plan(
|
|
399
|
+
aperture, backlight, beamstop, wait=True
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
yield from sup.move_detector_stage_to_position_plan(
|
|
403
|
+
detector_stage, parameters.detector_distance_mm
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
logger.debug("Set up beamline DONE")
|
|
407
|
+
|
|
408
|
+
filepath = parameters.collection_directory.as_posix()
|
|
409
|
+
filename = parameters.filename
|
|
410
|
+
|
|
411
|
+
logger.debug("Acquire Region")
|
|
412
|
+
|
|
413
|
+
num_gates = parameters.total_num_images // parameters.num_exposures
|
|
414
|
+
|
|
415
|
+
logger.info(f"Total number of images: {parameters.total_num_images}")
|
|
416
|
+
logger.info(f"Number of exposures: {parameters.num_exposures}")
|
|
417
|
+
logger.info(f"Number of gates (=Total images/N exposures): {num_gates:.4f}")
|
|
418
|
+
|
|
419
|
+
if parameters.detector_name == "pilatus":
|
|
420
|
+
logger.info("Using Pilatus detector")
|
|
421
|
+
logger.info(f"Fastchip Pilatus setup: filepath {filepath}")
|
|
422
|
+
logger.info(f"Fastchip Pilatus setup: filename {filename}")
|
|
423
|
+
logger.info(
|
|
424
|
+
f"Fastchip Pilatus setup: number of images {parameters.total_num_images}"
|
|
425
|
+
)
|
|
426
|
+
logger.info(
|
|
427
|
+
f"Fastchip Pilatus setup: exposure time {parameters.exposure_time_s}"
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
sup.pilatus(
|
|
431
|
+
"fastchip",
|
|
432
|
+
[
|
|
433
|
+
filepath,
|
|
434
|
+
filename,
|
|
435
|
+
parameters.total_num_images,
|
|
436
|
+
parameters.exposure_time_s,
|
|
437
|
+
],
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
# DCID process depends on detector PVs being set up already
|
|
441
|
+
logger.debug("Start DCID process")
|
|
442
|
+
dcid.generate_dcid(
|
|
443
|
+
visit=parameters.visit.name,
|
|
444
|
+
image_dir=filepath,
|
|
445
|
+
start_time=start_time,
|
|
446
|
+
num_images=parameters.total_num_images,
|
|
447
|
+
exposure_time=parameters.exposure_time_s,
|
|
448
|
+
shots_per_position=parameters.num_exposures,
|
|
449
|
+
pump_exposure_time=parameters.laser_dwell_s,
|
|
450
|
+
pump_delay=parameters.laser_delay_s or 0,
|
|
451
|
+
pump_status=parameters.pump_repeat.value,
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
logger.debug("Arm Pilatus. Arm Zebra.")
|
|
455
|
+
shutter_time_offset = SHUTTER_OPEN_TIME if PumpProbeSetting.Medium1 else 0.0
|
|
456
|
+
yield from setup_zebra_for_fastchip_plan(
|
|
457
|
+
zebra,
|
|
458
|
+
parameters.detector_name,
|
|
459
|
+
num_gates,
|
|
460
|
+
parameters.num_exposures,
|
|
461
|
+
parameters.exposure_time_s,
|
|
462
|
+
shutter_time_offset,
|
|
463
|
+
wait=True,
|
|
464
|
+
)
|
|
465
|
+
if parameters.pump_repeat == PumpProbeSetting.Medium1:
|
|
466
|
+
yield from open_fast_shutter_at_each_position_plan(
|
|
467
|
+
zebra, parameters.num_exposures, parameters.exposure_time_s
|
|
468
|
+
)
|
|
469
|
+
caput(pv.pilat_acquire, "1") # Arm pilatus
|
|
470
|
+
yield from arm_zebra(zebra)
|
|
471
|
+
caput(pv.pilat_filename, filename)
|
|
472
|
+
sleep(1.5)
|
|
473
|
+
|
|
474
|
+
elif parameters.detector_name == "eiger":
|
|
475
|
+
logger.info("Using Eiger detector")
|
|
476
|
+
|
|
477
|
+
logger.warning(
|
|
478
|
+
"""TEMPORARY HACK!
|
|
479
|
+
Running a Single image pilatus data collection to create directory."""
|
|
480
|
+
)
|
|
481
|
+
num_imgs = 1
|
|
482
|
+
sup.pilatus(
|
|
483
|
+
"quickshot-internaltrig",
|
|
484
|
+
[filepath, filename, num_imgs, parameters.exposure_time_s],
|
|
485
|
+
)
|
|
486
|
+
logger.debug("Sleep 2s waiting for pilatus to arm")
|
|
487
|
+
sleep(2)
|
|
488
|
+
sleep(0.5)
|
|
489
|
+
caput(pv.pilat_acquire, "0") # Disarm pilatus
|
|
490
|
+
sleep(0.5)
|
|
491
|
+
caput(pv.pilat_acquire, "1") # Arm pilatus
|
|
492
|
+
logger.debug("Pilatus data collection DONE")
|
|
493
|
+
sup.pilatus("return to normal", None)
|
|
494
|
+
logger.info("Pilatus back to normal. Single image pilatus data collection DONE")
|
|
495
|
+
|
|
496
|
+
logger.info(f"Triggered Eiger setup: filepath {filepath}")
|
|
497
|
+
logger.info(f"Triggered Eiger setup: filename {filename}")
|
|
498
|
+
logger.info(
|
|
499
|
+
f"Triggered Eiger setup: number of images {parameters.total_num_images}"
|
|
500
|
+
)
|
|
501
|
+
logger.info(
|
|
502
|
+
f"Triggered Eiger setup: exposure time {parameters.exposure_time_s}"
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
sup.eiger(
|
|
506
|
+
"triggered",
|
|
507
|
+
[
|
|
508
|
+
filepath,
|
|
509
|
+
filename,
|
|
510
|
+
parameters.total_num_images,
|
|
511
|
+
parameters.exposure_time_s,
|
|
512
|
+
],
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
# DCID process depends on detector PVs being set up already
|
|
516
|
+
logger.debug("Start DCID process")
|
|
517
|
+
dcid.generate_dcid(
|
|
518
|
+
visit=parameters.visit.name,
|
|
519
|
+
image_dir=filepath,
|
|
520
|
+
start_time=start_time,
|
|
521
|
+
num_images=parameters.total_num_images,
|
|
522
|
+
exposure_time=parameters.exposure_time_s,
|
|
523
|
+
shots_per_position=parameters.num_exposures,
|
|
524
|
+
pump_exposure_time=parameters.laser_dwell_s,
|
|
525
|
+
pump_delay=parameters.laser_delay_s or 0,
|
|
526
|
+
pump_status=parameters.pump_repeat.value,
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
logger.debug("Arm Zebra.")
|
|
530
|
+
shutter_time_offset = SHUTTER_OPEN_TIME if PumpProbeSetting.Medium1 else 0.0
|
|
531
|
+
yield from setup_zebra_for_fastchip_plan(
|
|
532
|
+
zebra,
|
|
533
|
+
parameters.detector_name,
|
|
534
|
+
num_gates,
|
|
535
|
+
parameters.num_exposures,
|
|
536
|
+
parameters.exposure_time_s,
|
|
537
|
+
shutter_time_offset,
|
|
538
|
+
wait=True,
|
|
539
|
+
)
|
|
540
|
+
if parameters.pump_repeat == PumpProbeSetting.Medium1:
|
|
541
|
+
yield from open_fast_shutter_at_each_position_plan(
|
|
542
|
+
zebra, parameters.num_exposures, parameters.exposure_time_s
|
|
543
|
+
)
|
|
544
|
+
yield from arm_zebra(zebra)
|
|
545
|
+
|
|
546
|
+
sleep(1.5)
|
|
547
|
+
|
|
548
|
+
else:
|
|
549
|
+
msg = f"Unknown Detector Type, det_type = {parameters.detector_name}"
|
|
550
|
+
logger.error(msg)
|
|
551
|
+
raise ValueError(msg)
|
|
552
|
+
|
|
553
|
+
# Open the hutch shutter
|
|
554
|
+
yield from bps.abs_set(shutter, ShutterDemand.OPEN, wait=True)
|
|
555
|
+
|
|
556
|
+
return start_time
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
@log.log_on_entry
|
|
560
|
+
def finish_i24(
|
|
561
|
+
zebra: Zebra,
|
|
562
|
+
pmac: PMAC,
|
|
563
|
+
shutter: HutchShutter,
|
|
564
|
+
dcm: DCM,
|
|
565
|
+
parameters: FixedTargetParameters,
|
|
566
|
+
):
|
|
567
|
+
logger.info(f"Finish I24 data collection with {parameters.detector_name} detector.")
|
|
568
|
+
|
|
569
|
+
complete_filename: str
|
|
570
|
+
transmission = float(caget(pv.pilat_filtertrasm))
|
|
571
|
+
wavelength = yield from bps.rd(dcm.wavelength_in_a)
|
|
572
|
+
|
|
573
|
+
if parameters.detector_name == "pilatus":
|
|
574
|
+
logger.debug("Finish I24 Pilatus")
|
|
575
|
+
complete_filename = f"{parameters.filename}_{caget(pv.pilat_filenum)}"
|
|
576
|
+
yield from reset_zebra_when_collection_done_plan(zebra)
|
|
577
|
+
sup.pilatus("return-to-normal", None)
|
|
578
|
+
sleep(0.2)
|
|
579
|
+
elif parameters.detector_name == "eiger":
|
|
580
|
+
logger.debug("Finish I24 Eiger")
|
|
581
|
+
yield from reset_zebra_when_collection_done_plan(zebra)
|
|
582
|
+
sup.eiger("return-to-normal", None)
|
|
583
|
+
complete_filename = cagetstring(pv.eiger_ODfilenameRBV) # type: ignore
|
|
584
|
+
else:
|
|
585
|
+
raise ValueError(f"{parameters.detector_name=} unrecognised")
|
|
586
|
+
|
|
587
|
+
# Detector independent moves
|
|
588
|
+
logger.info("Move chip back to home position by setting PMAC_STRING pv.")
|
|
589
|
+
yield from bps.trigger(pmac.to_xyz_zero)
|
|
590
|
+
logger.info("Closing shutter")
|
|
591
|
+
yield from bps.abs_set(shutter, ShutterDemand.CLOSE, wait=True)
|
|
592
|
+
|
|
593
|
+
# Write a record of what was collected to the processing directory
|
|
594
|
+
write_userlog(parameters, complete_filename, transmission, wavelength)
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def run_aborted_plan(pmac: PMAC, dcid: DCID):
|
|
598
|
+
"""Plan to send pmac_strings to tell the PMAC when a collection has been aborted, \
|
|
599
|
+
either by pressing the Abort button or because of a timeout, and to reset the \
|
|
600
|
+
P variable.
|
|
601
|
+
"""
|
|
602
|
+
logger.warning("Data Collection Aborted")
|
|
603
|
+
yield from bps.trigger(pmac.abort_program, wait=True)
|
|
604
|
+
|
|
605
|
+
end_time = datetime.now()
|
|
606
|
+
dcid.collection_complete(end_time, aborted=True)
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
@log.log_on_entry
|
|
610
|
+
def main_fixed_target_plan(
|
|
611
|
+
zebra: Zebra,
|
|
612
|
+
pmac: PMAC,
|
|
613
|
+
aperture: Aperture,
|
|
614
|
+
backlight: DualBacklight,
|
|
615
|
+
beamstop: Beamstop,
|
|
616
|
+
detector_stage: DetectorMotion,
|
|
617
|
+
shutter: HutchShutter,
|
|
618
|
+
dcm: DCM,
|
|
619
|
+
parameters: FixedTargetParameters,
|
|
620
|
+
dcid: DCID,
|
|
621
|
+
) -> MsgGenerator:
|
|
622
|
+
logger.info("Running a chip collection on I24")
|
|
623
|
+
|
|
624
|
+
logger.info("Getting Program Dictionary")
|
|
625
|
+
|
|
626
|
+
# If alignment type is Oxford inner it is still an Oxford type chip
|
|
627
|
+
if parameters.chip.chip_type == ChipType.OxfordInner:
|
|
628
|
+
logger.debug("Change chip type Oxford Inner to Oxford.")
|
|
629
|
+
parameters.chip.chip_type = ChipType.Oxford
|
|
630
|
+
|
|
631
|
+
chip_prog_dict = get_chip_prog_values(parameters)
|
|
632
|
+
logger.info("Loading Motion Program Data")
|
|
633
|
+
yield from load_motion_program_data(
|
|
634
|
+
pmac,
|
|
635
|
+
chip_prog_dict,
|
|
636
|
+
parameters.map_type,
|
|
637
|
+
parameters.pump_repeat,
|
|
638
|
+
parameters.checker_pattern,
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
parameters.total_num_images = datasetsizei24(
|
|
642
|
+
parameters.num_exposures, parameters.chip, parameters.map_type
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
start_time = yield from start_i24(
|
|
646
|
+
zebra, aperture, backlight, beamstop, detector_stage, shutter, parameters, dcid
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
logger.info("Moving to Start")
|
|
650
|
+
yield from bps.trigger(pmac.to_xyz_zero)
|
|
651
|
+
sleep(2.0)
|
|
652
|
+
|
|
653
|
+
# Now ready for data collection. Open fast shutter (zebra gate)
|
|
654
|
+
logger.info("Opening fast shutter.")
|
|
655
|
+
yield from open_fast_shutter(zebra)
|
|
656
|
+
|
|
657
|
+
# Kick off the StartOfCollect script
|
|
658
|
+
logger.debug("Notify DCID of the start of the collection.")
|
|
659
|
+
dcid.notify_start()
|
|
660
|
+
|
|
661
|
+
wavelength = yield from bps.rd(dcm.wavelength_in_a)
|
|
662
|
+
if parameters.detector_name == "eiger":
|
|
663
|
+
logger.debug("Start nexus writing service.")
|
|
664
|
+
call_nexgen(
|
|
665
|
+
chip_prog_dict,
|
|
666
|
+
start_time,
|
|
667
|
+
parameters,
|
|
668
|
+
wavelength,
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
yield from kickoff_and_complete_collection(pmac, parameters)
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
def kickoff_and_complete_collection(pmac: PMAC, parameters: FixedTargetParameters):
|
|
675
|
+
prog_num = get_prog_num(
|
|
676
|
+
parameters.chip.chip_type, parameters.map_type, parameters.pump_repeat
|
|
677
|
+
)
|
|
678
|
+
yield from bps.abs_set(pmac.program_number, prog_num, group="setup_pmac")
|
|
679
|
+
# Calculate approx collection time
|
|
680
|
+
total_collection_time = calculate_collection_timeout(parameters)
|
|
681
|
+
logger.info(f"Estimated collection time: {total_collection_time}s.")
|
|
682
|
+
yield from bps.abs_set(
|
|
683
|
+
pmac.collection_time, total_collection_time, group="setup_pmac"
|
|
684
|
+
)
|
|
685
|
+
yield from bps.wait(group="setup_pmac") # Make sure the soft signals are set
|
|
686
|
+
|
|
687
|
+
@bpp.run_decorator(md={"subplan_name": "run_ft_collection"})
|
|
688
|
+
def run_collection():
|
|
689
|
+
logger.info(f"Kick off PMAC with program number {prog_num}.")
|
|
690
|
+
yield from bps.kickoff(pmac.run_program, wait=True)
|
|
691
|
+
yield from bps.complete(pmac.run_program, wait=True)
|
|
692
|
+
logger.info("Collection completed without errors.")
|
|
693
|
+
|
|
694
|
+
yield from run_collection()
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
@log.log_on_entry
|
|
698
|
+
def collection_complete_plan(
|
|
699
|
+
dcid: DCID, collection_directory: Path, map_type: MappingType
|
|
700
|
+
) -> MsgGenerator:
|
|
701
|
+
end_time = datetime.now()
|
|
702
|
+
logger.debug(f"Collection end time {end_time}")
|
|
703
|
+
dcid.collection_complete(end_time, aborted=False)
|
|
704
|
+
|
|
705
|
+
# Copy parameter file and eventual chip map to collection directory
|
|
706
|
+
copy_files_to_data_location(collection_directory, map_type=map_type)
|
|
707
|
+
yield from bps.null()
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
@log.log_on_entry
|
|
711
|
+
def tidy_up_after_collection_plan(
|
|
712
|
+
zebra: Zebra,
|
|
713
|
+
pmac: PMAC,
|
|
714
|
+
shutter: HutchShutter,
|
|
715
|
+
dcm: DCM,
|
|
716
|
+
parameters: FixedTargetParameters,
|
|
717
|
+
dcid: DCID,
|
|
718
|
+
) -> MsgGenerator:
|
|
719
|
+
"""A plan to be run to tidy things up at the end af a fixed target collection, \
|
|
720
|
+
both successful or aborted.
|
|
721
|
+
"""
|
|
722
|
+
logger.info("Closing fast shutter")
|
|
723
|
+
yield from close_fast_shutter(zebra)
|
|
724
|
+
sleep(2.0)
|
|
725
|
+
|
|
726
|
+
# This probably should go in main then
|
|
727
|
+
if parameters.detector_name == "pilatus":
|
|
728
|
+
logger.debug("Pilatus Acquire STOP")
|
|
729
|
+
caput(pv.pilat_acquire, 0)
|
|
730
|
+
elif parameters.detector_name == "eiger":
|
|
731
|
+
logger.debug("Eiger Acquire STOP")
|
|
732
|
+
caput(pv.eiger_acquire, 0)
|
|
733
|
+
caput(pv.eiger_ODcapture, "Done")
|
|
734
|
+
sleep(0.5)
|
|
735
|
+
|
|
736
|
+
yield from finish_i24(zebra, pmac, shutter, dcm, parameters)
|
|
737
|
+
|
|
738
|
+
logger.debug("Notify DCID of end of collection.")
|
|
739
|
+
dcid.notify_end()
|
|
740
|
+
|
|
741
|
+
logger.debug("Quick summary of settings")
|
|
742
|
+
logger.debug(f"Chip name = {parameters.filename} sub_dir = {parameters.directory}")
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
def run_fixed_target_plan(
|
|
746
|
+
zebra: Zebra = inject("zebra"),
|
|
747
|
+
pmac: PMAC = inject("pmac"),
|
|
748
|
+
aperture: Aperture = inject("aperture"),
|
|
749
|
+
backlight: DualBacklight = inject("backlight"),
|
|
750
|
+
beamstop: Beamstop = inject("beamstop"),
|
|
751
|
+
detector_stage: DetectorMotion = inject("detector_motion"),
|
|
752
|
+
shutter: HutchShutter = inject("shutter"),
|
|
753
|
+
dcm: DCM = inject("dcm"),
|
|
754
|
+
) -> MsgGenerator:
|
|
755
|
+
setup_logging()
|
|
756
|
+
|
|
757
|
+
# in the first instance, write params here
|
|
758
|
+
yield from write_parameter_file(detector_stage)
|
|
759
|
+
|
|
760
|
+
logger.info("Getting parameters from file.")
|
|
761
|
+
parameters = FixedTargetParameters.from_file(PARAM_FILE_PATH_FT / PARAM_FILE_NAME)
|
|
762
|
+
|
|
763
|
+
log_msg = f"""
|
|
764
|
+
Parameters for I24 serial collection: \n
|
|
765
|
+
Chip name is {parameters.filename}
|
|
766
|
+
visit = {parameters.visit}
|
|
767
|
+
sub_dir = {parameters.directory}
|
|
768
|
+
n_exposures = {parameters.num_exposures}
|
|
769
|
+
chip_type = {str(parameters.chip.chip_type)}
|
|
770
|
+
map_type = {str(parameters.map_type)}
|
|
771
|
+
dcdetdist = {parameters.detector_distance_mm}
|
|
772
|
+
exptime = {parameters.exposure_time_s}
|
|
773
|
+
det_type = {parameters.detector_name}
|
|
774
|
+
pump_repeat = {str(parameters.pump_repeat)}
|
|
775
|
+
pumpexptime = {parameters.laser_dwell_s}
|
|
776
|
+
pumpdelay = {parameters.laser_delay_s}
|
|
777
|
+
prepumpexptime = {parameters.pre_pump_exposure_s}
|
|
778
|
+
"""
|
|
779
|
+
logger.info(log_msg)
|
|
780
|
+
|
|
781
|
+
# DCID instance - do not create yet
|
|
782
|
+
dcid = DCID(
|
|
783
|
+
emit_errors=False,
|
|
784
|
+
ssx_type=SSXType.FIXED,
|
|
785
|
+
detector=parameters.detector_name,
|
|
786
|
+
)
|
|
787
|
+
|
|
788
|
+
yield from bpp.contingency_wrapper(
|
|
789
|
+
main_fixed_target_plan(
|
|
790
|
+
zebra,
|
|
791
|
+
pmac,
|
|
792
|
+
aperture,
|
|
793
|
+
backlight,
|
|
794
|
+
beamstop,
|
|
795
|
+
detector_stage,
|
|
796
|
+
shutter,
|
|
797
|
+
dcm,
|
|
798
|
+
parameters,
|
|
799
|
+
dcid,
|
|
800
|
+
),
|
|
801
|
+
except_plan=lambda e: (yield from run_aborted_plan(pmac, dcid)),
|
|
802
|
+
final_plan=lambda: (
|
|
803
|
+
yield from tidy_up_after_collection_plan(
|
|
804
|
+
zebra, pmac, shutter, dcm, parameters, dcid
|
|
805
|
+
)
|
|
806
|
+
),
|
|
807
|
+
auto_raise=False,
|
|
808
|
+
)
|