mx-bluesky 1.4.6__py3-none-any.whl → 1.4.7__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/aithre_lasershaping/__init__.py +13 -0
- mx_bluesky/beamlines/aithre_lasershaping/check_goniometer_performance.py +29 -0
- mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py +18 -0
- mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +31 -25
- mx_bluesky/beamlines/i04/thawing_plan.py +10 -1
- mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +12 -12
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +30 -29
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +10 -11
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +8 -10
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +10 -3
- mx_bluesky/beamlines/i24/serial/log.py +1 -0
- mx_bluesky/beamlines/i24/serial/set_visit_directory.sh +1 -1
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +16 -16
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +47 -48
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +1 -1
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +9 -7
- mx_bluesky/beamlines/i24/serial/write_nexus.py +3 -2
- mx_bluesky/common/device_setup_plans/xbpm_feedback.py +45 -0
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +2 -4
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +1 -1
- mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py +18 -15
- mx_bluesky/{hyperion → common}/external_interaction/callbacks/sample_handling/sample_handling_callback.py +16 -4
- mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +41 -5
- mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py +2 -1
- mx_bluesky/common/external_interaction/ispyb/data_model.py +1 -0
- mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +14 -1
- mx_bluesky/common/external_interaction/nexus/nexus_utils.py +1 -1
- mx_bluesky/common/parameters/constants.py +2 -0
- mx_bluesky/common/parameters/gridscan.py +1 -1
- mx_bluesky/common/plans/write_sample_status.py +46 -0
- mx_bluesky/common/preprocessors/__init__.py +0 -0
- mx_bluesky/common/preprocessors/preprocessors.py +105 -0
- mx_bluesky/common/protocols/__init__.py +0 -0
- mx_bluesky/common/protocols/protocols.py +10 -0
- mx_bluesky/hyperion/__main__.py +3 -9
- mx_bluesky/hyperion/baton_handler.py +84 -0
- mx_bluesky/hyperion/device_setup_plans/setup_panda.py +5 -1
- mx_bluesky/hyperion/experiment_plans/__init__.py +0 -4
- mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +10 -25
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +0 -7
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +11 -10
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +5 -1
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +5 -3
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +0 -26
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +23 -18
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +25 -6
- mx_bluesky/hyperion/external_interaction/agamemnon.py +148 -10
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +12 -6
- mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py +107 -0
- mx_bluesky/hyperion/parameters/gridscan.py +2 -2
- mx_bluesky/hyperion/parameters/rotation.py +1 -1
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.7.dist-info}/METADATA +7 -7
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.7.dist-info}/RECORD +60 -51
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.7.dist-info}/WHEEL +1 -1
- mx_bluesky/common/external_interaction/callbacks/common/aperture_change_callback.py +0 -22
- mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +0 -103
- /mx_bluesky/{hyperion → common}/external_interaction/callbacks/sample_handling/__init__.py +0 -0
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.7.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.7.dist-info/licenses}/LICENSE +0 -0
- {mx_bluesky-1.4.6.dist-info → mx_bluesky-1.4.7.dist-info}/top_level.txt +0 -0
|
@@ -258,22 +258,22 @@ step09_pmac_response = "BL24I-MO-IOC-09:ASYN9.AINP"
|
|
|
258
258
|
step10_pmac_response = "BL24I-MO-IOC-10:ASYN10.AINP"
|
|
259
259
|
step11_pmac_response = "BL24I-MO-IOC-11:ASYN11.AINP"
|
|
260
260
|
step12_pmac_response = "BL24I-MO-IOC-12:ASYN12.AINP"
|
|
261
|
-
# General Purpose PV
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
261
|
+
# General Purpose PV. Now use STEP13
|
|
262
|
+
ioc13_gp1 = "BL24I-MO-IOC-13:GP1"
|
|
263
|
+
ioc13_gp2 = "BL24I-MO-IOC-13:GP2"
|
|
264
|
+
ioc13_gp3 = "BL24I-MO-IOC-13:GP3"
|
|
265
|
+
ioc13_gp4 = "BL24I-MO-IOC-13:GP4"
|
|
266
|
+
ioc13_gp5 = "BL24I-MO-IOC-13:GP5"
|
|
267
|
+
ioc13_gp6 = "BL24I-MO-IOC-13:GP6"
|
|
268
|
+
ioc13_gp7 = "BL24I-MO-IOC-13:GP7"
|
|
269
|
+
ioc13_gp8 = "BL24I-MO-IOC-13:GP8"
|
|
270
|
+
ioc13_gp9 = "BL24I-MO-IOC-13:GP9"
|
|
271
|
+
ioc13_gp10 = "BL24I-MO-IOC-13:GP10"
|
|
272
|
+
ioc13_gp11 = "BL24I-MO-IOC-13:GP11"
|
|
273
|
+
ioc13_gp12 = "BL24I-MO-IOC-13:GP12"
|
|
274
|
+
ioc13_gp13 = "BL24I-MO-IOC-13:GP13"
|
|
275
|
+
ioc13_gp14 = "BL24I-MO-IOC-13:GP14"
|
|
276
|
+
ioc13_gp15 = "BL24I-MO-IOC-13:GP15"
|
|
277
277
|
# ME14E
|
|
278
278
|
me14e_pmac_str = "ME14E-MO-CHIP-01:PMAC_STRING"
|
|
279
279
|
me14e_stage_x = "ME14E-MO-CHIP-01:X"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from time import sleep
|
|
3
2
|
|
|
4
3
|
import bluesky.plan_stubs as bps
|
|
5
4
|
from dodal.beamlines import i24
|
|
@@ -149,9 +148,9 @@ def modechange(action):
|
|
|
149
148
|
caput(pv.vgon_pinzs, 0)
|
|
150
149
|
caput(pv.fluo_trans, "OUT")
|
|
151
150
|
caput(pv.bs_roty, 0)
|
|
152
|
-
sleep(0.5)
|
|
151
|
+
yield from bps.sleep(0.5)
|
|
153
152
|
caput(pv.bs_mp_select, "Data Collection")
|
|
154
|
-
sleep(2.3)
|
|
153
|
+
yield from bps.sleep(2.3)
|
|
155
154
|
caput(pv.bl_mp_select, "In")
|
|
156
155
|
SSX_LOGGER.debug("Pin Data Collection Done")
|
|
157
156
|
|
|
@@ -168,9 +167,9 @@ def modechange(action):
|
|
|
168
167
|
caput(pv.vgon_pinyh, 0)
|
|
169
168
|
caput(pv.vgon_pinzs, 0)
|
|
170
169
|
caput(pv.fluo_trans, "OUT")
|
|
171
|
-
sleep(0.1)
|
|
170
|
+
yield from bps.sleep(0.1)
|
|
172
171
|
caput(pv.bs_roty, 0)
|
|
173
|
-
sleep(2.6)
|
|
172
|
+
yield from bps.sleep(2.6)
|
|
174
173
|
caput(pv.bl_mp_select, "In")
|
|
175
174
|
caput(pv.bs_mp_select, "Data Collection")
|
|
176
175
|
SSX_LOGGER.debug("RT Data Collection Done")
|
|
@@ -182,11 +181,11 @@ def modechange(action):
|
|
|
182
181
|
caput(pv.hgon_omega, 0.0)
|
|
183
182
|
caput(pv.fluo_trans, "OUT")
|
|
184
183
|
caput(pv.bl_mp_select, "Out")
|
|
185
|
-
sleep(1)
|
|
184
|
+
yield from bps.sleep(1)
|
|
186
185
|
caput(pv.aptr1_mp_select, "Manual Mounting")
|
|
187
186
|
caput(pv.bs_mp_select, "Tray Mount")
|
|
188
187
|
while float(caget(pv.ttab_x + ".RBV")) > 3:
|
|
189
|
-
sleep(1)
|
|
188
|
+
yield from bps.sleep(1)
|
|
190
189
|
SSX_LOGGER.debug("Tray Hand Mount Done")
|
|
191
190
|
|
|
192
191
|
# Tray Robot Load. This action needs to be reviewed and revised
|
|
@@ -199,15 +198,15 @@ def modechange(action):
|
|
|
199
198
|
caput(pv.fluo_trans, "OUT")
|
|
200
199
|
caput(pv.aptr1_mp_select, "In")
|
|
201
200
|
caput(pv.bl_mp_select, "Out")
|
|
202
|
-
sleep(1)
|
|
201
|
+
yield from bps.sleep(1)
|
|
203
202
|
caput(pv.bs_roty, 0)
|
|
204
|
-
sleep(1)
|
|
203
|
+
yield from bps.sleep(1)
|
|
205
204
|
caput(pv.bs_mp_select, "Robot")
|
|
206
|
-
sleep(1)
|
|
205
|
+
yield from bps.sleep(1)
|
|
207
206
|
caput(pv.bs_mp_select, "Data Collection Far")
|
|
208
|
-
sleep(1)
|
|
207
|
+
yield from bps.sleep(1)
|
|
209
208
|
caput(pv.bs_roty, 0)
|
|
210
|
-
sleep(4)
|
|
209
|
+
yield from bps.sleep(4)
|
|
211
210
|
caput(pv.bl_mp_select, "In")
|
|
212
211
|
SSX_LOGGER.debug("Tray Robot Mount Done")
|
|
213
212
|
|
|
@@ -220,15 +219,15 @@ def modechange(action):
|
|
|
220
219
|
caput(pv.aptr1_mp_select, "In")
|
|
221
220
|
caput(pv.fluo_trans, "OUT")
|
|
222
221
|
caput(pv.bl_mp_select, "Out")
|
|
223
|
-
sleep(1)
|
|
222
|
+
yield from bps.sleep(1)
|
|
224
223
|
caput(pv.bs_roty, 0)
|
|
225
|
-
sleep(1)
|
|
224
|
+
yield from bps.sleep(1)
|
|
226
225
|
caput(pv.bs_mp_select, "Robot")
|
|
227
|
-
sleep(1)
|
|
226
|
+
yield from bps.sleep(1)
|
|
228
227
|
caput(pv.bs_mp_select, "Data Collection")
|
|
229
|
-
sleep(1)
|
|
228
|
+
yield from bps.sleep(1)
|
|
230
229
|
caput(pv.bs_roty, 0)
|
|
231
|
-
sleep(4)
|
|
230
|
+
yield from bps.sleep(4)
|
|
232
231
|
caput(pv.bl_mp_select, "In")
|
|
233
232
|
SSX_LOGGER.debug("Tray Data Collection Done")
|
|
234
233
|
|
|
@@ -252,17 +251,17 @@ def modechange(action):
|
|
|
252
251
|
caput(pv.vgon_pinzs, 0)
|
|
253
252
|
while float(caget(pv.ttab_x + ".RBV")) > 1:
|
|
254
253
|
SSX_LOGGER.debug(f"moving ttab_x {caget(pv.ttab_x)}")
|
|
255
|
-
sleep(0.1)
|
|
254
|
+
yield from bps.sleep(0.1)
|
|
256
255
|
while caget(pv.fluo_out_limit) == "OFF":
|
|
257
256
|
SSX_LOGGER.debug("waiting on fluorescence detector")
|
|
258
|
-
sleep(0.1)
|
|
257
|
+
yield from bps.sleep(0.1)
|
|
259
258
|
while caget(pv.bl_mp_select) != "Out":
|
|
260
259
|
SSX_LOGGER.debug("waiting on back light to move to out")
|
|
261
|
-
sleep(0.1)
|
|
260
|
+
yield from bps.sleep(0.1)
|
|
262
261
|
caput(pv.bs_mp_select, "Robot")
|
|
263
262
|
caput(pv.bs_roty, 0)
|
|
264
263
|
while float(caget(pv.ptab_y + ".RBV")) > -89.0:
|
|
265
|
-
sleep(1)
|
|
264
|
+
yield from bps.sleep(1)
|
|
266
265
|
SSX_LOGGER.debug("Switch To Tray Done")
|
|
267
266
|
|
|
268
267
|
# Tray Switch to Pin
|
|
@@ -272,11 +271,11 @@ def modechange(action):
|
|
|
272
271
|
caput(pv.hgon_trayys, 0.0)
|
|
273
272
|
caput(pv.hgon_trayzs, 0.0)
|
|
274
273
|
while float(caget(pv.ttab_x + ".RBV")) > 1.0:
|
|
275
|
-
sleep(1)
|
|
274
|
+
yield from bps.sleep(1)
|
|
276
275
|
caput(pv.ptab_y, 0)
|
|
277
276
|
while float(caget(pv.ptab_y + ".RBV")) < -1.0:
|
|
278
|
-
sleep(1)
|
|
279
|
-
modechange("Pin_data_collection")
|
|
277
|
+
yield from bps.sleep(1)
|
|
278
|
+
yield from modechange("Pin_data_collection")
|
|
280
279
|
SSX_LOGGER.debug("Switch To Pin Done")
|
|
281
280
|
else:
|
|
282
281
|
SSX_LOGGER.debug(f"Unknown action: {action}")
|
|
@@ -323,9 +322,9 @@ def pilatus(action, args_list):
|
|
|
323
322
|
[filepath, filename, num_imgs, exptime] = args_list
|
|
324
323
|
rampath = filepath.replace("dls/i24/data", "ramdisk")
|
|
325
324
|
caput(pv.pilat_filepath, rampath)
|
|
326
|
-
sleep(0.1)
|
|
325
|
+
yield from bps.sleep(0.1)
|
|
327
326
|
caput(pv.pilat_filename, filename)
|
|
328
|
-
sleep(0.1)
|
|
327
|
+
yield from bps.sleep(0.1)
|
|
329
328
|
acqtime = float(exptime) - 0.001
|
|
330
329
|
caput(pv.pilat_acquiretime, str(acqtime))
|
|
331
330
|
caput(pv.pilat_acquireperiod, str(exptime))
|
|
@@ -336,21 +335,21 @@ def pilatus(action, args_list):
|
|
|
336
335
|
SSX_LOGGER.debug(f"Exposure time set as {exptime} s")
|
|
337
336
|
SSX_LOGGER.debug(f"Acquire time set as {acqtime} s")
|
|
338
337
|
SSX_LOGGER.debug("Pilatus takes time apprx 2sec")
|
|
339
|
-
sleep(2)
|
|
338
|
+
yield from bps.sleep(2)
|
|
340
339
|
caput(pv.pilat_delaytime, 0.00)
|
|
341
340
|
caput(pv.pilat_numimages, str(num_imgs))
|
|
342
341
|
caput(pv.pilat_imagemode, "Continuous")
|
|
343
342
|
caput(pv.pilat_triggermode, "Ext. Trigger")
|
|
344
|
-
sleep(0.2)
|
|
343
|
+
yield from bps.sleep(0.2)
|
|
345
344
|
|
|
346
345
|
elif action == "quickshot-internaltrig":
|
|
347
346
|
SSX_LOGGER.debug("quickshot-internaltrig")
|
|
348
347
|
[filepath, filename, num_imgs, exptime] = args_list
|
|
349
348
|
rampath = filepath.replace("dls/i24/data", "ramdisk")
|
|
350
349
|
caput(pv.pilat_filepath, rampath)
|
|
351
|
-
sleep(0.1)
|
|
350
|
+
yield from bps.sleep(0.1)
|
|
352
351
|
caput(pv.pilat_filename, filename)
|
|
353
|
-
sleep(0.1)
|
|
352
|
+
yield from bps.sleep(0.1)
|
|
354
353
|
acqtime = float(exptime) - 0.001
|
|
355
354
|
caput(pv.pilat_acquiretime, str(acqtime))
|
|
356
355
|
caput(pv.pilat_acquireperiod, str(exptime))
|
|
@@ -361,12 +360,12 @@ def pilatus(action, args_list):
|
|
|
361
360
|
SSX_LOGGER.debug(f"Exposure time set as {exptime} s")
|
|
362
361
|
SSX_LOGGER.debug(f"Acquire time set as {acqtime} s")
|
|
363
362
|
SSX_LOGGER.debug("Pilatus takes time apprx 2sec")
|
|
364
|
-
sleep(2)
|
|
363
|
+
yield from bps.sleep(2)
|
|
365
364
|
caput(pv.pilat_delaytime, 0.00)
|
|
366
365
|
caput(pv.pilat_numimages, str(num_imgs))
|
|
367
366
|
caput(pv.pilat_imagemode, "Continuous")
|
|
368
367
|
caput(pv.pilat_triggermode, "Internal")
|
|
369
|
-
sleep(0.2)
|
|
368
|
+
yield from bps.sleep(0.2)
|
|
370
369
|
|
|
371
370
|
# Put it all back to GDA acceptable defaults
|
|
372
371
|
elif action == "return to normal":
|
|
@@ -374,7 +373,7 @@ def pilatus(action, args_list):
|
|
|
374
373
|
caput(pv.pilat_triggermode, "Ext. Trigger")
|
|
375
374
|
caput(pv.pilat_numexpimage, 1)
|
|
376
375
|
SSX_LOGGER.debug("***** leaving pilatus")
|
|
377
|
-
sleep(0.1)
|
|
376
|
+
yield from bps.sleep(0.1)
|
|
378
377
|
return 0
|
|
379
378
|
|
|
380
379
|
|
|
@@ -388,7 +387,7 @@ def eiger(action, args_list):
|
|
|
388
387
|
caput(pv.eiger_detdist, str(float(caget(pv.det_z)) / 1000))
|
|
389
388
|
caput(pv.eiger_wavelength, caget(pv.dcm_lambda))
|
|
390
389
|
caput(pv.eiger_omegaincr, 0.0)
|
|
391
|
-
sleep(0.1)
|
|
390
|
+
yield from bps.sleep(0.1)
|
|
392
391
|
# Setup common to all collections ###
|
|
393
392
|
caput(pv.eiger_filewriter, "No")
|
|
394
393
|
caput(pv.eiger_stream, "Yes")
|
|
@@ -409,9 +408,9 @@ def eiger(action, args_list):
|
|
|
409
408
|
[filepath, filename, num_imgs, exptime] = args_list
|
|
410
409
|
filename = filename + "_" + str(caget(pv.eiger_seqID))
|
|
411
410
|
caput(pv.eiger_ODfilepath, filepath)
|
|
412
|
-
sleep(0.1)
|
|
411
|
+
yield from bps.sleep(0.1)
|
|
413
412
|
caput(pv.eiger_ODfilename, filename)
|
|
414
|
-
sleep(0.1)
|
|
413
|
+
yield from bps.sleep(0.1)
|
|
415
414
|
acqtime = float(exptime) - 0.0000001
|
|
416
415
|
caput(pv.eiger_acquiretime, str(acqtime))
|
|
417
416
|
SSX_LOGGER.debug(f"Filepath was set as {filepath}")
|
|
@@ -425,7 +424,7 @@ def eiger(action, args_list):
|
|
|
425
424
|
caput(pv.eiger_triggermode, "Internal Series")
|
|
426
425
|
caput(pv.eiger_numtriggers, 1)
|
|
427
426
|
caput(pv.eiger_manualtrigger, "Yes")
|
|
428
|
-
sleep(1.0)
|
|
427
|
+
yield from bps.sleep(1.0)
|
|
429
428
|
# ODIN setup
|
|
430
429
|
SSX_LOGGER.info("Setting up Odin")
|
|
431
430
|
caput(pv.eiger_ODfilename, filename)
|
|
@@ -435,7 +434,7 @@ def eiger(action, args_list):
|
|
|
435
434
|
eigerbdrbv = "UInt" + str(caget(pv.eiger_bitdepthrbv))
|
|
436
435
|
caput(pv.eiger_ODdatatype, eigerbdrbv)
|
|
437
436
|
caput(pv.eiger_ODcompress, "BSL24")
|
|
438
|
-
sleep(1.0)
|
|
437
|
+
yield from bps.sleep(1.0)
|
|
439
438
|
# All done. Now get Odin to wait for data and start Eiger
|
|
440
439
|
SSX_LOGGER.info("Done: Odin waiting for data")
|
|
441
440
|
caput(pv.eiger_ODcapture, "Capture")
|
|
@@ -451,9 +450,9 @@ def eiger(action, args_list):
|
|
|
451
450
|
[filepath, filename, num_imgs, exptime] = args_list
|
|
452
451
|
filename = filename + "_" + str(caget(pv.eiger_seqID))
|
|
453
452
|
caput(pv.eiger_ODfilepath, filepath)
|
|
454
|
-
sleep(0.1)
|
|
453
|
+
yield from bps.sleep(0.1)
|
|
455
454
|
caput(pv.eiger_ODfilename, filename)
|
|
456
|
-
sleep(0.1)
|
|
455
|
+
yield from bps.sleep(0.1)
|
|
457
456
|
acqtime = float(exptime) - 0.0000001
|
|
458
457
|
caput(pv.eiger_acquiretime, str(acqtime))
|
|
459
458
|
SSX_LOGGER.debug(f"Filepath was set as {filepath}")
|
|
@@ -467,7 +466,7 @@ def eiger(action, args_list):
|
|
|
467
466
|
caput(pv.eiger_triggermode, "External Enable")
|
|
468
467
|
caput(pv.eiger_numtriggers, str(num_imgs))
|
|
469
468
|
caput(pv.eiger_manualtrigger, "Yes")
|
|
470
|
-
sleep(1.0)
|
|
469
|
+
yield from bps.sleep(1.0)
|
|
471
470
|
# ODIN setup #
|
|
472
471
|
SSX_LOGGER.info("Setting up Odin")
|
|
473
472
|
caput(pv.eiger_ODfilename, filename)
|
|
@@ -477,7 +476,7 @@ def eiger(action, args_list):
|
|
|
477
476
|
eigerbdrbv = "UInt" + str(caget(pv.eiger_bitdepthrbv))
|
|
478
477
|
caput(pv.eiger_ODdatatype, eigerbdrbv)
|
|
479
478
|
caput(pv.eiger_ODcompress, "BSL24")
|
|
480
|
-
sleep(1.0)
|
|
479
|
+
yield from bps.sleep(1.0)
|
|
481
480
|
# All done. Now get Odin to wait for data and start Eiger
|
|
482
481
|
SSX_LOGGER.info("Done: Odin waiting for data")
|
|
483
482
|
caput(pv.eiger_ODcapture, "Capture")
|
|
@@ -492,7 +491,7 @@ def eiger(action, args_list):
|
|
|
492
491
|
caput(pv.eiger_manualtrigger, "No")
|
|
493
492
|
# caput(pv.eiger_seqID, int(caget(pv.eiger_seqID))+1)
|
|
494
493
|
SSX_LOGGER.debug("***** leaving Eiger")
|
|
495
|
-
sleep(0.1)
|
|
494
|
+
yield from bps.sleep(0.1)
|
|
496
495
|
return 0
|
|
497
496
|
|
|
498
497
|
|
|
@@ -510,10 +509,10 @@ def xspress3(action, args_list):
|
|
|
510
509
|
caput(pv.xsp3_acquiretime, exp_time)
|
|
511
510
|
caput(pv.xsp3_c1_mca_roi1_llm, lo)
|
|
512
511
|
caput(pv.xsp3_c1_mca_roi1_hlm, hi)
|
|
513
|
-
sleep(0.2)
|
|
512
|
+
yield from bps.sleep(0.2)
|
|
514
513
|
caput(pv.xsp3_c1_mca_roi1_llm, lo)
|
|
515
514
|
caput(pv.xsp3_c1_mca_roi1_hlm, hi)
|
|
516
|
-
sleep(0.2)
|
|
515
|
+
yield from bps.sleep(0.2)
|
|
517
516
|
caput(pv.xsp3_erase, 0)
|
|
518
517
|
|
|
519
518
|
elif action == "on-the-fly":
|
|
@@ -522,10 +521,10 @@ def xspress3(action, args_list):
|
|
|
522
521
|
caput(pv.xsp3_numimages, num_frms)
|
|
523
522
|
caput(pv.xsp3_c1_mca_roi1_llm, lo)
|
|
524
523
|
caput(pv.xsp3_c1_mca_roi1_hlm, hi)
|
|
525
|
-
sleep(0.2)
|
|
524
|
+
yield from bps.sleep(0.2)
|
|
526
525
|
caput(pv.xsp3_c1_mca_roi1_llm, lo)
|
|
527
526
|
caput(pv.xsp3_c1_mca_roi1_hlm, hi)
|
|
528
|
-
sleep(0.2)
|
|
527
|
+
yield from bps.sleep(0.2)
|
|
529
528
|
caput(pv.xsp3_erase, 0)
|
|
530
529
|
|
|
531
530
|
elif action == "return-to-normal":
|
|
@@ -539,6 +538,6 @@ def xspress3(action, args_list):
|
|
|
539
538
|
else:
|
|
540
539
|
SSX_LOGGER.error("Unknown action for xspress3 method:", action)
|
|
541
540
|
|
|
542
|
-
sleep(0.1)
|
|
541
|
+
yield from bps.sleep(0.1)
|
|
543
542
|
SSX_LOGGER.debug("***** leaving xspress3")
|
|
544
543
|
return 1
|
|
@@ -272,7 +272,7 @@ def setup_zebra_for_fastchip_plan(
|
|
|
272
272
|
det_type: str,
|
|
273
273
|
num_gates: int,
|
|
274
274
|
num_exposures: int,
|
|
275
|
-
|
|
275
|
+
exposure_time_s: float,
|
|
276
276
|
start_time_offset: float = 0.0,
|
|
277
277
|
group: str = "setup_zebra_for_fastchip",
|
|
278
278
|
wait: bool = True,
|
|
@@ -303,7 +303,7 @@ def setup_zebra_for_fastchip_plan(
|
|
|
303
303
|
det_type (str): Detector in use, current choices are Eiger or Pilatus.
|
|
304
304
|
num_gates (int): Number of apertures to visit in a chip.
|
|
305
305
|
num_exposures (int): Number of times data is collected in each aperture.
|
|
306
|
-
|
|
306
|
+
exposure_time_s (float): Exposure time for each shot.
|
|
307
307
|
start_time_offset (float): Delay on the start of the position compare. \
|
|
308
308
|
Defaults to 0.0 (standard chip collection).
|
|
309
309
|
"""
|
|
@@ -341,10 +341,12 @@ def setup_zebra_for_fastchip_plan(
|
|
|
341
341
|
)
|
|
342
342
|
|
|
343
343
|
# Square wave - needs a small drop to make it work for eiger
|
|
344
|
-
pulse_width =
|
|
344
|
+
pulse_width = (
|
|
345
|
+
exposure_time_s - 0.0001 if det_type == "eiger" else exposure_time_s / 2
|
|
346
|
+
)
|
|
345
347
|
|
|
346
348
|
# 100us buffer needed to avoid missing some of the triggers
|
|
347
|
-
exptime_buffer =
|
|
349
|
+
exptime_buffer = exposure_time_s + 0.0001
|
|
348
350
|
|
|
349
351
|
# Number of gates is the number of windows collected
|
|
350
352
|
yield from bps.abs_set(zebra.pc.num_gates, num_gates, group=group)
|
|
@@ -362,7 +364,7 @@ def setup_zebra_for_fastchip_plan(
|
|
|
362
364
|
def open_fast_shutter_at_each_position_plan(
|
|
363
365
|
zebra: Zebra,
|
|
364
366
|
num_exposures: int,
|
|
365
|
-
|
|
367
|
+
exposure_time_s: float,
|
|
366
368
|
group: str = "fast_shutter_control",
|
|
367
369
|
wait: bool = True,
|
|
368
370
|
):
|
|
@@ -384,7 +386,7 @@ def open_fast_shutter_at_each_position_plan(
|
|
|
384
386
|
Args:
|
|
385
387
|
zebra (Zebra): The zebra ophyd device.
|
|
386
388
|
num_exposures (int): Number of times data is collected in each aperture.
|
|
387
|
-
|
|
389
|
+
exposure_time_s (float): Exposure time for each shot.
|
|
388
390
|
"""
|
|
389
391
|
SSX_LOGGER.info(
|
|
390
392
|
"ZEBRA setup for fastchip collection with long delays between exposures."
|
|
@@ -395,7 +397,7 @@ def open_fast_shutter_at_each_position_plan(
|
|
|
395
397
|
zebra.output.pulse_2.input, zebra.mapping.sources.PC_GATE, group=group
|
|
396
398
|
)
|
|
397
399
|
yield from bps.abs_set(zebra.output.pulse_2.delay, 0.0, group=group)
|
|
398
|
-
pulse2_width = num_exposures *
|
|
400
|
+
pulse2_width = num_exposures * exposure_time_s + SHUTTER_OPEN_TIME
|
|
399
401
|
yield from bps.abs_set(zebra.output.pulse_2.width, pulse2_width, group=group)
|
|
400
402
|
|
|
401
403
|
# Fast shutter
|
|
@@ -4,6 +4,7 @@ import pprint
|
|
|
4
4
|
import time
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
|
|
7
|
+
import bluesky.plan_stubs as bps
|
|
7
8
|
import requests
|
|
8
9
|
|
|
9
10
|
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import ChipType, MappingType
|
|
@@ -61,10 +62,10 @@ def call_nexgen(
|
|
|
61
62
|
while time.time() - t0 < max_wait:
|
|
62
63
|
if meta_h5.exists():
|
|
63
64
|
SSX_LOGGER.info(f"Found {meta_h5} after {time.time() - t0:.1f} seconds")
|
|
64
|
-
|
|
65
|
+
yield from bps.sleep(5)
|
|
65
66
|
break
|
|
66
67
|
SSX_LOGGER.debug(f"Waiting for {meta_h5}")
|
|
67
|
-
|
|
68
|
+
yield from bps.sleep(1)
|
|
68
69
|
if not meta_h5.exists():
|
|
69
70
|
SSX_LOGGER.warning(f"Giving up waiting for {meta_h5} after {max_wait} seconds")
|
|
70
71
|
return
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from bluesky import plan_stubs as bps
|
|
2
|
+
from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
|
|
3
|
+
from dodal.devices.xbpm_feedback import Pause, XBPMFeedback
|
|
4
|
+
|
|
5
|
+
from mx_bluesky.common.utils.log import LOGGER
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def unpause_xbpm_feedback_and_set_transmission_to_1(
|
|
9
|
+
xbpm_feedback: XBPMFeedback, attenuator: BinaryFilterAttenuator
|
|
10
|
+
):
|
|
11
|
+
"""Turns the XBPM feedback back on and sets transmission to 1 so that it keeps the
|
|
12
|
+
beam aligned whilst not collecting.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
xbpm_feedback (XBPMFeedback): The XBPM device that is responsible for keeping
|
|
16
|
+
the beam in position
|
|
17
|
+
attenuator (BinaryFilterAttenuator): The attenuator used to set transmission
|
|
18
|
+
"""
|
|
19
|
+
yield from bps.mv(xbpm_feedback.pause_feedback, Pause.RUN, attenuator, 1.0) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def check_and_pause_feedback(
|
|
23
|
+
xbpm_feedback: XBPMFeedback,
|
|
24
|
+
attenuator: BinaryFilterAttenuator,
|
|
25
|
+
desired_transmission_fraction: float,
|
|
26
|
+
):
|
|
27
|
+
"""Checks that the xbpm is in position before then turning it off and setting a new
|
|
28
|
+
transmission.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
xbpm_feedback (XBPMFeedback): The XBPM device that is responsible for keeping
|
|
32
|
+
the beam in position
|
|
33
|
+
attenuator (BinaryFilterAttenuator): The attenuator used to set transmission
|
|
34
|
+
desired_transmission_fraction (float): The desired transmission to set after
|
|
35
|
+
turning XBPM feedback off.
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
yield from bps.mv(attenuator, 1.0) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
39
|
+
LOGGER.info("Waiting for XBPM feedback to be stable")
|
|
40
|
+
yield from bps.trigger(xbpm_feedback, wait=True)
|
|
41
|
+
LOGGER.info(
|
|
42
|
+
f"XPBM feedback in position, pausing and setting transmission to {desired_transmission_fraction}"
|
|
43
|
+
)
|
|
44
|
+
yield from bps.mv(xbpm_feedback.pause_feedback, Pause.PAUSE) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
45
|
+
yield from bps.mv(attenuator, desired_transmission_fraction) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
@@ -121,10 +121,8 @@ class BaseISPyBCallback(PlanReactiveCallback):
|
|
|
121
121
|
ISPYB_ZOCALO_CALLBACK_LOGGER.info(
|
|
122
122
|
"ISPyB handler received event from read hardware"
|
|
123
123
|
)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
SynchrotronMode,
|
|
127
|
-
)
|
|
124
|
+
synchrotron_mode = doc["data"]["synchrotron-synchrotron_mode"]
|
|
125
|
+
assert isinstance(synchrotron_mode, SynchrotronMode)
|
|
128
126
|
|
|
129
127
|
hwscan_data_collection_info = DataCollectionInfo(
|
|
130
128
|
undulator_gap1=doc["data"]["undulator-current_gap"],
|
|
@@ -35,7 +35,7 @@ def populate_remaining_data_collection_info(
|
|
|
35
35
|
data_collection_info.detector_id = I03_EIGER_DETECTOR
|
|
36
36
|
data_collection_info.comments = comment
|
|
37
37
|
data_collection_info.detector_distance = params.detector_params.detector_distance
|
|
38
|
-
data_collection_info.exp_time = params.detector_params.
|
|
38
|
+
data_collection_info.exp_time = params.detector_params.exposure_time_s
|
|
39
39
|
data_collection_info.imgdir = params.detector_params.directory
|
|
40
40
|
data_collection_info.imgprefix = params.detector_params.prefix
|
|
41
41
|
data_collection_info.imgsuffix = EIGER_FILE_SUFFIX
|
|
@@ -18,10 +18,11 @@ if TYPE_CHECKING:
|
|
|
18
18
|
|
|
19
19
|
class ZocaloCallback(CallbackBase):
|
|
20
20
|
"""Callback class to handle the triggering of Zocalo processing.
|
|
21
|
-
|
|
22
|
-
sub-plan, and sends a run_end signal on receiving a stop document for the same plan.
|
|
21
|
+
Will start listening for collections when {triggering_plan} has been started.
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
For every ispyb deposition that occurs inside this run the callback will send zocalo
|
|
24
|
+
a run_start signal. Once the {triggering_plan} has ended the callback will send a
|
|
25
|
+
run_end signal for all collections.
|
|
25
26
|
|
|
26
27
|
Shouldn't be subscribed directly to the RunEngine, instead should be passed to the
|
|
27
28
|
`emit` argument of an ISPyB callback which appends DCIDs to the relevant start doc.
|
|
@@ -30,7 +31,9 @@ class ZocaloCallback(CallbackBase):
|
|
|
30
31
|
def _reset_state(self):
|
|
31
32
|
self.run_uid: str | None = None
|
|
32
33
|
self.zocalo_info: list[ZocaloStartInfo] = []
|
|
34
|
+
self._started_zocalo_collections: list[ZocaloStartInfo] = []
|
|
33
35
|
self.descriptors: dict[str, EventDescriptor] = {}
|
|
36
|
+
self.start_frame = 0
|
|
34
37
|
|
|
35
38
|
def __init__(self, triggering_plan: str, zocalo_environment: str):
|
|
36
39
|
super().__init__()
|
|
@@ -42,26 +45,21 @@ class ZocaloCallback(CallbackBase):
|
|
|
42
45
|
ISPYB_ZOCALO_CALLBACK_LOGGER.info("Zocalo handler received start document.")
|
|
43
46
|
if self.triggering_plan and doc.get("subplan_name") == self.triggering_plan:
|
|
44
47
|
self.run_uid = doc.get("uid")
|
|
45
|
-
|
|
48
|
+
if self.run_uid:
|
|
46
49
|
if (
|
|
47
|
-
isinstance(
|
|
50
|
+
isinstance(scan_points := doc.get("scan_points"), list)
|
|
51
|
+
and isinstance(ispyb_ids := doc.get("ispyb_dcids"), tuple)
|
|
48
52
|
and len(ispyb_ids) > 0
|
|
49
53
|
):
|
|
50
54
|
ISPYB_ZOCALO_CALLBACK_LOGGER.info(f"Zocalo triggering for {ispyb_ids}")
|
|
51
55
|
ids_and_shape = list(zip(ispyb_ids, scan_points, strict=False))
|
|
52
|
-
start_frame = 0
|
|
53
|
-
self.zocalo_info = []
|
|
54
56
|
for idx, id_and_shape in enumerate(ids_and_shape):
|
|
55
57
|
id, shape = id_and_shape
|
|
56
58
|
num_frames = number_of_frames_from_scan_spec(shape)
|
|
57
59
|
self.zocalo_info.append(
|
|
58
|
-
ZocaloStartInfo(id, None, start_frame, num_frames, idx)
|
|
60
|
+
ZocaloStartInfo(id, None, self.start_frame, num_frames, idx)
|
|
59
61
|
)
|
|
60
|
-
start_frame += num_frames
|
|
61
|
-
else:
|
|
62
|
-
raise ISPyBDepositionNotMade(
|
|
63
|
-
f"No ISPyB IDs received by the start of {self.triggering_plan=}"
|
|
64
|
-
)
|
|
62
|
+
self.start_frame += num_frames
|
|
65
63
|
|
|
66
64
|
def descriptor(self, doc: EventDescriptor):
|
|
67
65
|
self.descriptors[doc["uid"]] = doc
|
|
@@ -73,6 +71,8 @@ class ZocaloCallback(CallbackBase):
|
|
|
73
71
|
for start_info in self.zocalo_info:
|
|
74
72
|
start_info.filename = filename
|
|
75
73
|
self.zocalo_interactor.run_start(start_info)
|
|
74
|
+
self._started_zocalo_collections.append(start_info)
|
|
75
|
+
self.zocalo_info = []
|
|
76
76
|
return doc
|
|
77
77
|
|
|
78
78
|
def stop(self, doc: RunStop):
|
|
@@ -80,7 +80,10 @@ class ZocaloCallback(CallbackBase):
|
|
|
80
80
|
ISPYB_ZOCALO_CALLBACK_LOGGER.info(
|
|
81
81
|
f"Zocalo handler received stop document, for run {doc.get('run_start')}."
|
|
82
82
|
)
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
if not self._started_zocalo_collections:
|
|
84
|
+
raise ISPyBDepositionNotMade(
|
|
85
|
+
f"No ISPyB IDs received by the end of {self.triggering_plan=}"
|
|
86
|
+
)
|
|
87
|
+
for info in self._started_zocalo_collections:
|
|
85
88
|
self.zocalo_interactor.run_end(info.ispyb_dcid)
|
|
86
89
|
self._reset_state()
|
|
@@ -15,12 +15,15 @@ class SampleHandlingCallback(PlanReactiveCallback):
|
|
|
15
15
|
"""Intercepts exceptions from experiment plans and updates the ISPyB BLSampleStatus
|
|
16
16
|
field according to the type of exception raised."""
|
|
17
17
|
|
|
18
|
-
def __init__(self):
|
|
18
|
+
def __init__(self, record_loaded_on_success=False):
|
|
19
19
|
super().__init__(log=ISPYB_ZOCALO_CALLBACK_LOGGER)
|
|
20
20
|
self._sample_id: int | None = None
|
|
21
21
|
self._descriptor: str | None = None
|
|
22
22
|
self._run_id: str | None = None
|
|
23
23
|
|
|
24
|
+
# Record 'sample loaded' if document successfully stops
|
|
25
|
+
self.record_loaded_on_success = record_loaded_on_success
|
|
26
|
+
|
|
24
27
|
def activity_gated_start(self, doc: RunStart):
|
|
25
28
|
if not self._sample_id and self.active:
|
|
26
29
|
sample_id = doc.get("metadata", {}).get("sample_id")
|
|
@@ -30,6 +33,7 @@ class SampleHandlingCallback(PlanReactiveCallback):
|
|
|
30
33
|
|
|
31
34
|
def activity_gated_stop(self, doc: RunStop) -> RunStop:
|
|
32
35
|
if self._run_id == doc.get("run_start"):
|
|
36
|
+
expeye = ExpeyeInteraction()
|
|
33
37
|
if doc["exit_status"] != "success":
|
|
34
38
|
exception_type, message = SampleException.type_and_message_from_reason(
|
|
35
39
|
doc.get("reason", "")
|
|
@@ -37,13 +41,17 @@ class SampleHandlingCallback(PlanReactiveCallback):
|
|
|
37
41
|
self.log.info(
|
|
38
42
|
f"Sample handling callback intercepted exception of type {exception_type}: {message}"
|
|
39
43
|
)
|
|
40
|
-
self._record_exception(exception_type)
|
|
44
|
+
self._record_exception(exception_type, expeye)
|
|
45
|
+
|
|
46
|
+
elif self.record_loaded_on_success:
|
|
47
|
+
self._record_loaded(expeye)
|
|
48
|
+
|
|
41
49
|
self._sample_id = None
|
|
42
50
|
self._run_id = None
|
|
51
|
+
|
|
43
52
|
return doc
|
|
44
53
|
|
|
45
|
-
def _record_exception(self, exception_type: str):
|
|
46
|
-
expeye = ExpeyeInteraction()
|
|
54
|
+
def _record_exception(self, exception_type: str, expeye: ExpeyeInteraction):
|
|
47
55
|
assert self._sample_id, "Unable to record exception due to no sample ID"
|
|
48
56
|
sample_status = self._decode_sample_status(exception_type)
|
|
49
57
|
expeye.update_sample_status(self._sample_id, sample_status)
|
|
@@ -53,3 +61,7 @@ class SampleHandlingCallback(PlanReactiveCallback):
|
|
|
53
61
|
case SampleException.__name__ | CrystalNotFoundException.__name__:
|
|
54
62
|
return BLSampleStatus.ERROR_SAMPLE
|
|
55
63
|
return BLSampleStatus.ERROR_BEAMLINE
|
|
64
|
+
|
|
65
|
+
def _record_loaded(self, expeye: ExpeyeInteraction):
|
|
66
|
+
assert self._sample_id, "Unable to record loaded state due to no sample ID"
|
|
67
|
+
expeye.update_sample_status(self._sample_id, BLSampleStatus.LOADED)
|