mx-bluesky 1.4.7__py3-none-any.whl → 1.4.8__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 +4 -4
- mx_bluesky/beamlines/i04/thawing_plan.py +8 -2
- mx_bluesky/beamlines/i23/__init__.py +3 -0
- mx_bluesky/beamlines/i23/serial.py +71 -0
- mx_bluesky/beamlines/i24/serial/__init__.py +2 -0
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +7 -2
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +3 -3
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +6 -56
- mx_bluesky/beamlines/i24/serial/log.py +9 -10
- mx_bluesky/beamlines/i24/serial/parameters/utils.py +36 -7
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +0 -1
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv_abstract.py +4 -4
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +4 -4
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +2 -1
- mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +71 -11
- mx_bluesky/beamlines/i24/serial/write_nexus.py +3 -3
- mx_bluesky/{hyperion → common}/device_setup_plans/check_beamstop.py +1 -1
- mx_bluesky/{hyperion → common}/device_setup_plans/manipulate_sample.py +1 -1
- mx_bluesky/{hyperion → common}/device_setup_plans/setup_oav.py +12 -6
- mx_bluesky/{hyperion → common}/experiment_plans/change_aperture_then_move_plan.py +4 -5
- mx_bluesky/{hyperion → common}/experiment_plans/oav_grid_detection_plan.py +6 -6
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +6 -5
- mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +16 -47
- mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +4 -1
- mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py +4 -4
- mx_bluesky/common/parameters/components.py +22 -2
- mx_bluesky/common/parameters/constants.py +4 -16
- mx_bluesky/common/parameters/gridscan.py +36 -32
- mx_bluesky/common/plans/common_flyscan_xray_centre_plan.py +316 -0
- mx_bluesky/common/plans/inner_plans/__init__ .py +0 -0
- mx_bluesky/common/plans/read_hardware.py +3 -3
- mx_bluesky/common/utils/log.py +15 -12
- mx_bluesky/hyperion/__main__.py +2 -15
- mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +4 -4
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +0 -33
- mx_bluesky/hyperion/device_setup_plans/utils.py +4 -4
- mx_bluesky/hyperion/experiment_plans/__init__.py +0 -6
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +0 -9
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +71 -88
- mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +183 -0
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +12 -7
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +28 -7
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +4 -4
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +1 -1
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +11 -3
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +9 -8
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +18 -56
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -2
- mx_bluesky/hyperion/external_interaction/agamemnon.py +62 -70
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +8 -6
- mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py +183 -31
- mx_bluesky/hyperion/parameters/cli.py +2 -10
- mx_bluesky/hyperion/parameters/constants.py +0 -5
- mx_bluesky/hyperion/parameters/device_composites.py +40 -5
- mx_bluesky/hyperion/parameters/gridscan.py +9 -58
- mx_bluesky/hyperion/parameters/rotation.py +0 -4
- mx_bluesky/hyperion/utils/context.py +2 -5
- mx_bluesky/hyperion/utils/validation.py +13 -10
- {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/METADATA +5 -4
- {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/RECORD +69 -65
- {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/WHEEL +1 -1
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +0 -467
- /mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/{short1-laser.png → s1l.png} +0 -0
- /mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/{short2-laser.png → s2l.png} +0 -0
- /mx_bluesky/{hyperion → common}/device_setup_plans/position_detector.py +0 -0
- /mx_bluesky/common/plans/{do_fgs.py → inner_plans/do_fgs.py} +0 -0
- {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/licenses/LICENSE +0 -0
- {mx_bluesky-1.4.7.dist-info → mx_bluesky-1.4.8.dist-info}/top_level.txt +0 -0
mx_bluesky/_version.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import TypedDict
|
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import zmq
|
|
9
|
-
from dodal.
|
|
9
|
+
from dodal.devices.i04.constants import RedisConstants
|
|
10
10
|
from numpy.typing import NDArray
|
|
11
11
|
from PIL import Image
|
|
12
12
|
from redis import StrictRedis
|
|
@@ -139,9 +139,9 @@ class RedisListener:
|
|
|
139
139
|
|
|
140
140
|
def __init__(
|
|
141
141
|
self,
|
|
142
|
-
redis_host=REDIS_HOST,
|
|
143
|
-
redis_password=REDIS_PASSWORD,
|
|
144
|
-
db=MURKO_REDIS_DB,
|
|
142
|
+
redis_host=RedisConstants.REDIS_HOST,
|
|
143
|
+
redis_password=RedisConstants.REDIS_PASSWORD,
|
|
144
|
+
db=RedisConstants.MURKO_REDIS_DB,
|
|
145
145
|
redis_channel="murko",
|
|
146
146
|
):
|
|
147
147
|
self.redis_client = StrictRedis(
|
|
@@ -4,8 +4,8 @@ import bluesky.plan_stubs as bps
|
|
|
4
4
|
import bluesky.preprocessors as bpp
|
|
5
5
|
from bluesky.preprocessors import run_decorator, subs_decorator
|
|
6
6
|
from bluesky.utils import MsgGenerator
|
|
7
|
-
from dodal.beamlines.i04 import MURKO_REDIS_DB, REDIS_HOST, REDIS_PASSWORD
|
|
8
7
|
from dodal.common import inject
|
|
8
|
+
from dodal.devices.i04.constants import RedisConstants
|
|
9
9
|
from dodal.devices.oav.oav_detector import OAV
|
|
10
10
|
from dodal.devices.oav.oav_to_redis_forwarder import OAVToRedisForwarder, Source
|
|
11
11
|
from dodal.devices.robot import BartRobot
|
|
@@ -42,7 +42,13 @@ def thaw_and_stream_to_redis(
|
|
|
42
42
|
beam_centre_i = yield from bps.rd(oav.beam_centre_i)
|
|
43
43
|
beam_centre_j = yield from bps.rd(oav.beam_centre_j)
|
|
44
44
|
|
|
45
|
-
@subs_decorator(
|
|
45
|
+
@subs_decorator(
|
|
46
|
+
MurkoCallback(
|
|
47
|
+
RedisConstants.REDIS_HOST,
|
|
48
|
+
RedisConstants.REDIS_PASSWORD,
|
|
49
|
+
RedisConstants.MURKO_REDIS_DB,
|
|
50
|
+
)
|
|
51
|
+
)
|
|
46
52
|
@run_decorator(
|
|
47
53
|
md={
|
|
48
54
|
"microns_per_x_pixel": microns_per_pixel_x,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from functools import partial
|
|
2
|
+
|
|
3
|
+
from bluesky import plan_stubs as bps
|
|
4
|
+
from bluesky.plans import rel_grid_scan
|
|
5
|
+
from bluesky.utils import short_uid
|
|
6
|
+
from dodal.beamlines.i23 import I23DetectorPositions
|
|
7
|
+
from dodal.common import inject
|
|
8
|
+
from dodal.devices.motors import SixAxisGonio
|
|
9
|
+
from dodal.devices.positioner import Positioner1D
|
|
10
|
+
from ophyd_async.epics.motor import Motor
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def set_axis_to_max_velocity(axis: Motor):
|
|
14
|
+
max_vel = yield from bps.rd(axis.max_velocity)
|
|
15
|
+
yield from bps.mv(axis.velocity, max_vel)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def one_nd_step(
|
|
19
|
+
detectors,
|
|
20
|
+
step,
|
|
21
|
+
pos_cache,
|
|
22
|
+
omega_axis: Motor,
|
|
23
|
+
omega_rotation: float,
|
|
24
|
+
omega_velocity: float,
|
|
25
|
+
):
|
|
26
|
+
def move():
|
|
27
|
+
yield from bps.checkpoint()
|
|
28
|
+
grp = short_uid("set")
|
|
29
|
+
for motor, pos in step.items():
|
|
30
|
+
yield from bps.abs_set(motor, pos, group=grp)
|
|
31
|
+
yield from set_axis_to_max_velocity(omega_axis)
|
|
32
|
+
yield from bps.abs_set(omega_axis, 0, group=grp)
|
|
33
|
+
yield from bps.wait(group=grp)
|
|
34
|
+
|
|
35
|
+
yield from move()
|
|
36
|
+
yield from bps.mv(omega_axis.velocity, omega_velocity)
|
|
37
|
+
yield from bps.mv(omega_axis, omega_rotation)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def serial_collection(
|
|
41
|
+
x_steps: int,
|
|
42
|
+
y_steps: int,
|
|
43
|
+
x_step_size: float,
|
|
44
|
+
y_step_size: float,
|
|
45
|
+
omega_rotation: float,
|
|
46
|
+
omega_velocity: float,
|
|
47
|
+
detector_motion: Positioner1D = inject("detector_motion"),
|
|
48
|
+
gonio: SixAxisGonio = inject("gonio"),
|
|
49
|
+
):
|
|
50
|
+
"""This plan runs a software controlled serial collection. i.e it moves in a snaked
|
|
51
|
+
grid and does a small rotation collection at each point."""
|
|
52
|
+
|
|
53
|
+
yield from bps.mv(detector_motion.stage_position, I23DetectorPositions.IN)
|
|
54
|
+
yield from rel_grid_scan(
|
|
55
|
+
[],
|
|
56
|
+
gonio.y,
|
|
57
|
+
0,
|
|
58
|
+
y_step_size * (y_steps - 1),
|
|
59
|
+
y_steps,
|
|
60
|
+
gonio.x,
|
|
61
|
+
0,
|
|
62
|
+
x_step_size * (x_steps - 1),
|
|
63
|
+
x_steps,
|
|
64
|
+
per_step=partial( # type: ignore
|
|
65
|
+
one_nd_step,
|
|
66
|
+
omega_axis=gonio.omega,
|
|
67
|
+
omega_rotation=omega_rotation,
|
|
68
|
+
omega_velocity=omega_velocity,
|
|
69
|
+
),
|
|
70
|
+
snake_axes=True,
|
|
71
|
+
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from mx_bluesky.beamlines.i24.serial.web_gui_plans.general_plans import (
|
|
2
2
|
gui_gonio_move_on_click,
|
|
3
|
+
gui_move_backlight,
|
|
3
4
|
gui_move_detector,
|
|
4
5
|
gui_set_parameters,
|
|
5
6
|
gui_sleep,
|
|
@@ -57,4 +58,5 @@ __all__ = [
|
|
|
57
58
|
"gui_sleep",
|
|
58
59
|
"gui_move_detector",
|
|
59
60
|
"gui_set_parameters",
|
|
61
|
+
"gui_move_backlight",
|
|
60
62
|
]
|
|
@@ -317,6 +317,7 @@ def main_extruder_plan(
|
|
|
317
317
|
parameters.num_images,
|
|
318
318
|
parameters.exposure_time_s,
|
|
319
319
|
],
|
|
320
|
+
dcm,
|
|
320
321
|
)
|
|
321
322
|
yield from setup_zebra_for_extruder_with_pump_probe_plan(
|
|
322
323
|
zebra,
|
|
@@ -338,6 +339,7 @@ def main_extruder_plan(
|
|
|
338
339
|
parameters.num_images,
|
|
339
340
|
parameters.exposure_time_s,
|
|
340
341
|
],
|
|
342
|
+
dcm,
|
|
341
343
|
)
|
|
342
344
|
yield from setup_zebra_for_quickshot_plan(
|
|
343
345
|
zebra, parameters.exposure_time_s, parameters.num_images, wait=True
|
|
@@ -441,6 +443,7 @@ def tidy_up_at_collection_end_plan(
|
|
|
441
443
|
shutter: HutchShutter,
|
|
442
444
|
parameters: ExtruderParameters,
|
|
443
445
|
dcid: DCID,
|
|
446
|
+
dcm: DCM,
|
|
444
447
|
) -> MsgGenerator:
|
|
445
448
|
"""A plan to tidy up at the end of a collection, successful or aborted.
|
|
446
449
|
|
|
@@ -455,7 +458,7 @@ def tidy_up_at_collection_end_plan(
|
|
|
455
458
|
if parameters.detector_name == "pilatus":
|
|
456
459
|
yield from sup.pilatus("return-to-normal", None)
|
|
457
460
|
elif parameters.detector_name == "eiger":
|
|
458
|
-
yield from sup.eiger("return-to-normal", None)
|
|
461
|
+
yield from sup.eiger("return-to-normal", None, dcm)
|
|
459
462
|
SSX_LOGGER.debug(f"{parameters.filename}_{caget(pv.eiger_seqID)}")
|
|
460
463
|
SSX_LOGGER.debug("End of Run")
|
|
461
464
|
SSX_LOGGER.info("Close hutch shutter")
|
|
@@ -534,7 +537,9 @@ def run_extruder_plan(
|
|
|
534
537
|
)
|
|
535
538
|
),
|
|
536
539
|
final_plan=lambda: (
|
|
537
|
-
yield from tidy_up_at_collection_end_plan(
|
|
540
|
+
yield from tidy_up_at_collection_end_plan(
|
|
541
|
+
zebra, shutter, parameters, dcid, dcm
|
|
542
|
+
)
|
|
538
543
|
),
|
|
539
544
|
auto_raise=False,
|
|
540
545
|
)
|
|
@@ -1521,7 +1521,7 @@ x 275
|
|
|
1521
1521
|
y 111
|
|
1522
1522
|
w 175
|
|
1523
1523
|
h 139
|
|
1524
|
-
file "SCRIPTS_LOCATION/fixed_target/FT-gui-edm/
|
|
1524
|
+
file "SCRIPTS_LOCATION/fixed_target/FT-gui-edm/s1l.png"
|
|
1525
1525
|
endObjectProperties
|
|
1526
1526
|
|
|
1527
1527
|
# (PNG Image)
|
|
@@ -1534,7 +1534,7 @@ x 486
|
|
|
1534
1534
|
y 111
|
|
1535
1535
|
w 172
|
|
1536
1536
|
h 139
|
|
1537
|
-
file "SCRIPTS_LOCATION/fixed_target/FT-gui-edm/
|
|
1537
|
+
file "SCRIPTS_LOCATION/fixed_target/FT-gui-edm/s2l.png"
|
|
1538
1538
|
endObjectProperties
|
|
1539
1539
|
|
|
1540
1540
|
# (Static Text)
|
|
@@ -1600,7 +1600,7 @@ x 695
|
|
|
1600
1600
|
y 111
|
|
1601
1601
|
w 175
|
|
1602
1602
|
h 139
|
|
1603
|
-
file "SCRIPTS_LOCATION/fixed_target/FT-gui-edm/
|
|
1603
|
+
file "SCRIPTS_LOCATION/fixed_target/FT-gui-edm/s1l.png"
|
|
1604
1604
|
endObjectProperties
|
|
1605
1605
|
|
|
1606
1606
|
# (Static Text)
|
|
@@ -4,6 +4,7 @@ Fixed target data collection
|
|
|
4
4
|
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from pathlib import Path
|
|
7
|
+
from traceback import format_exception
|
|
7
8
|
|
|
8
9
|
import bluesky.plan_stubs as bps
|
|
9
10
|
import bluesky.preprocessors as bpp
|
|
@@ -51,52 +52,6 @@ from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_zebra_plans import (
|
|
|
51
52
|
)
|
|
52
53
|
from mx_bluesky.beamlines.i24.serial.write_nexus import call_nexgen
|
|
53
54
|
|
|
54
|
-
# Move this in common place as part of
|
|
55
|
-
# https://github.com/DiamondLightSource/mx-bluesky/pull/603
|
|
56
|
-
PMAC_MOVE_TIME = 0.008 # Move time between positions on chip ~ 7-8 ms
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def calculate_collection_timeout(parameters: FixedTargetParameters) -> float:
|
|
60
|
-
"""Give an estimation of the time the plan should wait for the data collection \
|
|
61
|
-
to be finished.
|
|
62
|
-
|
|
63
|
-
For non-pump probe collections and collection with short delays, it should be \
|
|
64
|
-
enough to use the collection time plus a genereous 30s buffer.
|
|
65
|
-
For EAVA (Excite and visit again) collections instead, the laser dwell and laser \
|
|
66
|
-
delay times should be included in the calculation. For long dalays between pump \
|
|
67
|
-
and probe, the shutter opening time will also need to be taken into account.
|
|
68
|
-
For more details on the dynamics see
|
|
69
|
-
https://confluence.diamond.ac.uk/display/MXTech/Dynamics+and+fixed+targets.
|
|
70
|
-
|
|
71
|
-
Args:
|
|
72
|
-
parameters (FixedTargerParameters): The collection parameters.
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
The estimated collection time, in s.
|
|
76
|
-
"""
|
|
77
|
-
buffer = PMAC_MOVE_TIME * parameters.total_num_images + 600
|
|
78
|
-
pump_setting = parameters.pump_repeat
|
|
79
|
-
collection_time = parameters.total_num_images * parameters.exposure_time_s
|
|
80
|
-
if pump_setting in [
|
|
81
|
-
PumpProbeSetting.NoPP,
|
|
82
|
-
PumpProbeSetting.Short1,
|
|
83
|
-
PumpProbeSetting.Short2,
|
|
84
|
-
]:
|
|
85
|
-
timeout = collection_time + buffer
|
|
86
|
-
else:
|
|
87
|
-
# EAVA: Excite and visit again
|
|
88
|
-
num_windows = parameters.total_num_images / parameters.num_exposures
|
|
89
|
-
timeout = (
|
|
90
|
-
collection_time
|
|
91
|
-
+ parameters.laser_dwell_s * num_windows # type: ignore
|
|
92
|
-
+ parameters.laser_delay_s
|
|
93
|
-
+ buffer
|
|
94
|
-
)
|
|
95
|
-
if pump_setting == PumpProbeSetting.Medium1:
|
|
96
|
-
# Long delay between pump and probe, with fast shutter opening and closing.
|
|
97
|
-
timeout = timeout + SHUTTER_OPEN_TIME * parameters.total_num_images
|
|
98
|
-
return timeout
|
|
99
|
-
|
|
100
55
|
|
|
101
56
|
def write_userlog(
|
|
102
57
|
parameters: FixedTargetParameters,
|
|
@@ -430,6 +385,7 @@ def start_i24(
|
|
|
430
385
|
parameters.total_num_images,
|
|
431
386
|
parameters.exposure_time_s,
|
|
432
387
|
],
|
|
388
|
+
dcm,
|
|
433
389
|
)
|
|
434
390
|
|
|
435
391
|
# DCID process depends on detector PVs being set up already
|
|
@@ -505,7 +461,7 @@ def finish_i24(
|
|
|
505
461
|
elif parameters.detector_name == "eiger":
|
|
506
462
|
SSX_LOGGER.debug("Finish I24 Eiger")
|
|
507
463
|
yield from reset_zebra_when_collection_done_plan(zebra)
|
|
508
|
-
yield from sup.eiger("return-to-normal", None)
|
|
464
|
+
yield from sup.eiger("return-to-normal", None, dcm)
|
|
509
465
|
complete_filename = cagetstring(pv.eiger_ODfilenameRBV) # type: ignore
|
|
510
466
|
else:
|
|
511
467
|
raise ValueError(f"{parameters.detector_name=} unrecognised")
|
|
@@ -520,12 +476,12 @@ def finish_i24(
|
|
|
520
476
|
write_userlog(parameters, complete_filename, transmission, wavelength)
|
|
521
477
|
|
|
522
478
|
|
|
523
|
-
def run_aborted_plan(pmac: PMAC, dcid: DCID):
|
|
479
|
+
def run_aborted_plan(pmac: PMAC, dcid: DCID, exception: Exception):
|
|
524
480
|
"""Plan to send pmac_strings to tell the PMAC when a collection has been aborted, \
|
|
525
481
|
either by pressing the Abort button or because of a timeout, and to reset the \
|
|
526
482
|
P variable.
|
|
527
483
|
"""
|
|
528
|
-
SSX_LOGGER.warning("Data Collection Aborted")
|
|
484
|
+
SSX_LOGGER.warning(f"Data Collection Aborted: {format_exception(exception)}")
|
|
529
485
|
yield from bps.trigger(pmac.abort_program, wait=True)
|
|
530
486
|
|
|
531
487
|
end_time = datetime.now()
|
|
@@ -621,12 +577,6 @@ def kickoff_and_complete_collection(pmac: PMAC, parameters: FixedTargetParameter
|
|
|
621
577
|
parameters.chip.chip_type, parameters.map_type, parameters.pump_repeat
|
|
622
578
|
)
|
|
623
579
|
yield from bps.abs_set(pmac.program_number, prog_num, group="setup_pmac")
|
|
624
|
-
# Calculate approx collection time
|
|
625
|
-
total_collection_time = calculate_collection_timeout(parameters)
|
|
626
|
-
SSX_LOGGER.info(f"Estimated collection time: {total_collection_time}s.")
|
|
627
|
-
yield from bps.abs_set(
|
|
628
|
-
pmac.collection_time, total_collection_time, group="setup_pmac"
|
|
629
|
-
)
|
|
630
580
|
yield from bps.wait(group="setup_pmac") # Make sure the soft signals are set
|
|
631
581
|
|
|
632
582
|
@bpp.run_decorator(md={"subplan_name": "run_ft_collection"})
|
|
@@ -731,7 +681,7 @@ def run_fixed_target_plan(
|
|
|
731
681
|
parameters,
|
|
732
682
|
dcid,
|
|
733
683
|
),
|
|
734
|
-
except_plan=lambda e: (yield from run_aborted_plan(pmac, dcid)),
|
|
684
|
+
except_plan=lambda e: (yield from run_aborted_plan(pmac, dcid, e)),
|
|
735
685
|
final_plan=lambda: (
|
|
736
686
|
yield from tidy_up_after_collection_plan(
|
|
737
687
|
zebra, pmac, shutter, dcm, parameters, dcid
|
|
@@ -99,16 +99,6 @@ def config(
|
|
|
99
99
|
dev_mode (bool, optional): If true, will log to graylog on localhost instead \
|
|
100
100
|
of production. Defaults to False.
|
|
101
101
|
"""
|
|
102
|
-
do_default_logging_setup(
|
|
103
|
-
"mx-bluesky.log",
|
|
104
|
-
DEFAULT_GRAYLOG_PORT,
|
|
105
|
-
dev_mode=dev_mode,
|
|
106
|
-
integrate_all_logs=False,
|
|
107
|
-
)
|
|
108
|
-
# Remove dodal StreamHandler to avoid duplication of messages above debug
|
|
109
|
-
dodal_logger.removeHandler(dodal_logger.handlers[0])
|
|
110
|
-
_integrate_bluesky_logs(dodal_logger)
|
|
111
|
-
|
|
112
102
|
if logfile:
|
|
113
103
|
logs = _get_logging_file_path() / logfile
|
|
114
104
|
fileFormatter = logging.Formatter(
|
|
@@ -119,6 +109,15 @@ def config(
|
|
|
119
109
|
FH.setLevel(logging.DEBUG)
|
|
120
110
|
FH.setFormatter(fileFormatter)
|
|
121
111
|
SSX_LOGGER.addHandler(FH)
|
|
112
|
+
do_default_logging_setup(
|
|
113
|
+
"mx-bluesky.log",
|
|
114
|
+
DEFAULT_GRAYLOG_PORT,
|
|
115
|
+
dev_mode=dev_mode,
|
|
116
|
+
integrate_all_logs=False,
|
|
117
|
+
)
|
|
118
|
+
# Remove dodal StreamHandler to avoid duplication of messages above debug
|
|
119
|
+
dodal_logger.removeHandler(dodal_logger.handlers[0])
|
|
120
|
+
_integrate_bluesky_logs(dodal_logger)
|
|
122
121
|
|
|
123
122
|
|
|
124
123
|
def log_on_entry(func):
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from typing import Any, Literal
|
|
2
3
|
|
|
3
4
|
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import ChipType
|
|
4
5
|
from mx_bluesky.beamlines.i24.serial.parameters.experiment_parameters import (
|
|
@@ -13,8 +14,27 @@ class EmptyMapError(Exception):
|
|
|
13
14
|
pass
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
def get_chip_format(
|
|
17
|
-
|
|
17
|
+
def get_chip_format(
|
|
18
|
+
chip_type: ChipType,
|
|
19
|
+
format: Sequence[int | float] | None = None,
|
|
20
|
+
origin: Literal["edm", "web"] = "edm",
|
|
21
|
+
) -> ChipDescription:
|
|
22
|
+
"""Get the default parameter values for the requested chip type.
|
|
23
|
+
|
|
24
|
+
For an Oxford-type chip, the default values are hard coded as the dimensions are
|
|
25
|
+
always the same. For a Custom chip instead, the number of steps and step size in
|
|
26
|
+
each direction must be entered through the GUI - web or edm. If the collection is
|
|
27
|
+
run through the edm, the values will be read from the general purpose PVs set on
|
|
28
|
+
there. If instead the plan is run from the web UI, the values will be passed in the
|
|
29
|
+
form of a list/tuple of 4 values.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
chip_type (ChipType): Chip in use
|
|
33
|
+
custom_format (Sequence[int | float], optional): Number and size of steps input
|
|
34
|
+
from the web ui. Format should be: [int, int, float, float].
|
|
35
|
+
Defaults to None.
|
|
36
|
+
origin (str, optional): UI in use, can be either web or edm. Defaults to edm.
|
|
37
|
+
"""
|
|
18
38
|
defaults: dict[str, int | float] = {}
|
|
19
39
|
match chip_type:
|
|
20
40
|
case ChipType.Oxford:
|
|
@@ -33,10 +53,19 @@ def get_chip_format(chip_type: ChipType) -> ChipDescription:
|
|
|
33
53
|
defaults["x_blocks"] = defaults["y_blocks"] = 1
|
|
34
54
|
defaults["b2b_horz"] = defaults["b2b_vert"] = 0.0
|
|
35
55
|
case ChipType.Custom:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
56
|
+
if origin == "edm":
|
|
57
|
+
defaults["x_num_steps"] = int(caget(pv.me14e_gp6))
|
|
58
|
+
defaults["y_num_steps"] = int(caget(pv.me14e_gp7))
|
|
59
|
+
defaults["x_step_size"] = float(caget(pv.me14e_gp8))
|
|
60
|
+
defaults["y_step_size"] = float(caget(pv.me14e_gp99))
|
|
61
|
+
else:
|
|
62
|
+
# NOTE Test for WEB GUI
|
|
63
|
+
if not format:
|
|
64
|
+
raise ValueError("Format for custom chip not passed")
|
|
65
|
+
defaults["x_num_steps"] = format[0]
|
|
66
|
+
defaults["y_num_steps"] = format[1]
|
|
67
|
+
defaults["x_step_size"] = format[2]
|
|
68
|
+
defaults["y_step_size"] = format[3]
|
|
40
69
|
defaults["x_blocks"] = defaults["y_blocks"] = 1
|
|
41
70
|
defaults["b2b_horz"] = defaults["b2b_vert"] = 0.0
|
|
42
71
|
case ChipType.MISP:
|
|
@@ -154,7 +154,6 @@ dcm_gap = "BL24I-MO-DCM-01:GAP"
|
|
|
154
154
|
dcm_roll1 = "BL24I-MO-DCM-01:XTAL1:ROLL"
|
|
155
155
|
dcm_roll2 = "BL24I-MO-DCM-01:XTAL2:ROLL"
|
|
156
156
|
dcm_pitch2 = "BL24I-MO-DCM-01:XTAL2:PITCH"
|
|
157
|
-
dcm_lambda = "BL24I-MO-DCM-01:LAMBDA"
|
|
158
157
|
dcm_energy = "BL24I-MO-DCM-01:ENERGY"
|
|
159
158
|
|
|
160
159
|
# S2
|
|
@@ -19,8 +19,8 @@ class Pilatus:
|
|
|
19
19
|
round(a * b, 3) for a, b in zip(image_size_pixels, pixel_size_mm, strict=False)
|
|
20
20
|
)
|
|
21
21
|
|
|
22
|
-
det_y_threshold =
|
|
23
|
-
det_y_target =
|
|
22
|
+
det_y_threshold = 640.0
|
|
23
|
+
det_y_target = 647.0
|
|
24
24
|
|
|
25
25
|
class pv:
|
|
26
26
|
detector_distance = pv.pilat_detdist
|
|
@@ -48,8 +48,8 @@ class Eiger:
|
|
|
48
48
|
round(a * b, 3) for a, b in zip(image_size_pixels, pixel_size_mm, strict=False)
|
|
49
49
|
)
|
|
50
50
|
|
|
51
|
-
det_y_threshold =
|
|
52
|
-
det_y_target =
|
|
51
|
+
det_y_threshold = 70.0
|
|
52
|
+
det_y_target = 59.0
|
|
53
53
|
|
|
54
54
|
class pv:
|
|
55
55
|
detector_distance = pv.eiger_detdist
|
|
@@ -6,6 +6,7 @@ from dodal.devices.detector.det_dim_constants import DetectorSizeConstants
|
|
|
6
6
|
from dodal.devices.i24.aperture import Aperture, AperturePositions
|
|
7
7
|
from dodal.devices.i24.beam_center import DetectorBeamCenter
|
|
8
8
|
from dodal.devices.i24.beamstop import Beamstop, BeamstopPositions
|
|
9
|
+
from dodal.devices.i24.dcm import DCM
|
|
9
10
|
from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
|
|
10
11
|
from dodal.devices.i24.i24_detector_motion import DetectorMotion
|
|
11
12
|
from dodal.devices.util.lookup_tables import (
|
|
@@ -289,7 +290,6 @@ def pilatus(action, args_list):
|
|
|
289
290
|
for arg in args_list:
|
|
290
291
|
SSX_LOGGER.debug(f"Argument: {arg}")
|
|
291
292
|
|
|
292
|
-
# caput(pv.pilat_wavelength, caget(pv.dcm_lambda))
|
|
293
293
|
caput(pv.pilat_detdist, caget(pv.det_z))
|
|
294
294
|
caput(pv.pilat_filtertrasm, caget(pv.attn_match))
|
|
295
295
|
|
|
@@ -377,15 +377,15 @@ def pilatus(action, args_list):
|
|
|
377
377
|
return 0
|
|
378
378
|
|
|
379
379
|
|
|
380
|
-
def eiger(action, args_list):
|
|
380
|
+
def eiger(action, args_list, dcm: DCM):
|
|
381
381
|
SSX_LOGGER.debug("***** Entering Eiger")
|
|
382
382
|
SSX_LOGGER.info(f"Setup eiger - {action}")
|
|
383
383
|
if args_list:
|
|
384
384
|
for arg in args_list:
|
|
385
385
|
SSX_LOGGER.debug(f"Argument: {arg}")
|
|
386
|
-
# caput(pv.eiger_wavelength, caget(pv.dcm_lambda))
|
|
387
386
|
caput(pv.eiger_detdist, str(float(caget(pv.det_z)) / 1000))
|
|
388
|
-
|
|
387
|
+
dcm_wavelength_a = yield from bps.rd(dcm.wavelength_in_a.user_readback)
|
|
388
|
+
caput(pv.eiger_wavelength, dcm_wavelength_a)
|
|
389
389
|
caput(pv.eiger_omegaincr, 0.0)
|
|
390
390
|
yield from bps.sleep(0.1)
|
|
391
391
|
# Setup common to all collections ###
|
|
@@ -13,7 +13,7 @@ from dodal.devices.i24.i24_detector_motion import DetectorMotion
|
|
|
13
13
|
from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER
|
|
14
14
|
from mx_bluesky.beamlines.i24.serial.parameters import SSXType
|
|
15
15
|
from mx_bluesky.beamlines.i24.serial.setup_beamline import pv
|
|
16
|
-
from mx_bluesky.beamlines.i24.serial.setup_beamline.ca import caget
|
|
16
|
+
from mx_bluesky.beamlines.i24.serial.setup_beamline.ca import caget, caput
|
|
17
17
|
from mx_bluesky.beamlines.i24.serial.setup_beamline.pv_abstract import (
|
|
18
18
|
Detector,
|
|
19
19
|
Eiger,
|
|
@@ -93,4 +93,5 @@ def setup_detector_stage(
|
|
|
93
93
|
Eiger.det_y_target if requested_detector == "eiger" else Pilatus.det_y_target
|
|
94
94
|
)
|
|
95
95
|
yield from _move_detector_stage(detector_stage, det_y_target)
|
|
96
|
+
caput(det_type_pv, requested_detector)
|
|
96
97
|
SSX_LOGGER.info("Detector setup done.")
|
|
@@ -5,6 +5,11 @@ import bluesky.plan_stubs as bps
|
|
|
5
5
|
import bluesky.preprocessors as bpp
|
|
6
6
|
from blueapi.core import MsgGenerator
|
|
7
7
|
from dodal.beamlines import i24
|
|
8
|
+
from dodal.common import inject
|
|
9
|
+
from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
|
|
10
|
+
from dodal.devices.i24.i24_detector_motion import DetectorMotion
|
|
11
|
+
from dodal.devices.i24.pmac import PMAC
|
|
12
|
+
from dodal.devices.oav.oav_detector import OAV
|
|
8
13
|
|
|
9
14
|
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
|
|
10
15
|
ChipType,
|
|
@@ -14,11 +19,15 @@ from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
|
|
|
14
19
|
from mx_bluesky.beamlines.i24.serial.fixed_target.i24ssx_moveonclick import (
|
|
15
20
|
_move_on_mouse_click_plan,
|
|
16
21
|
)
|
|
17
|
-
from mx_bluesky.beamlines.i24.serial.log import
|
|
22
|
+
from mx_bluesky.beamlines.i24.serial.log import (
|
|
23
|
+
SSX_LOGGER,
|
|
24
|
+
_read_visit_directory_from_file,
|
|
25
|
+
)
|
|
18
26
|
from mx_bluesky.beamlines.i24.serial.parameters import (
|
|
19
27
|
FixedTargetParameters,
|
|
20
28
|
get_chip_format,
|
|
21
29
|
)
|
|
30
|
+
from mx_bluesky.beamlines.i24.serial.parameters.utils import EmptyMapError
|
|
22
31
|
from mx_bluesky.beamlines.i24.serial.setup_beamline import pv
|
|
23
32
|
from mx_bluesky.beamlines.i24.serial.setup_beamline.ca import caput
|
|
24
33
|
from mx_bluesky.beamlines.i24.serial.setup_beamline.pv_abstract import Eiger, Pilatus
|
|
@@ -29,9 +38,18 @@ from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_detector import (
|
|
|
29
38
|
|
|
30
39
|
|
|
31
40
|
@bpp.run_decorator()
|
|
32
|
-
def
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
def gui_move_backlight(
|
|
42
|
+
position: str, backlight: DualBacklight = inject("backlight")
|
|
43
|
+
) -> MsgGenerator:
|
|
44
|
+
bl_pos = BacklightPositions(position)
|
|
45
|
+
yield from bps.abs_set(backlight, bl_pos, wait=True)
|
|
46
|
+
SSX_LOGGER.debug(f"Backlight moved to {bl_pos.value}")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@bpp.run_decorator()
|
|
50
|
+
def gui_stage_move_on_click(
|
|
51
|
+
position_px: tuple[int, int], oav: OAV = inject("oav"), pmac: PMAC = inject("pmac")
|
|
52
|
+
) -> MsgGenerator:
|
|
35
53
|
yield from _move_on_mouse_click_plan(oav, pmac, position_px)
|
|
36
54
|
|
|
37
55
|
|
|
@@ -58,11 +76,14 @@ def gui_sleep(sec: int) -> MsgGenerator:
|
|
|
58
76
|
|
|
59
77
|
|
|
60
78
|
@bpp.run_decorator()
|
|
61
|
-
def gui_move_detector(
|
|
62
|
-
|
|
79
|
+
def gui_move_detector(
|
|
80
|
+
det: Literal["eiger", "pilatus"],
|
|
81
|
+
detector_stage: DetectorMotion = inject("detector_motion"),
|
|
82
|
+
) -> MsgGenerator:
|
|
63
83
|
det_y_target = Eiger.det_y_target if det == "eiger" else Pilatus.det_y_target
|
|
64
84
|
yield from _move_detector_stage(detector_stage, det_y_target)
|
|
65
85
|
# Make the output readable
|
|
86
|
+
SSX_LOGGER.debug(f"Detector move done, resetting general PV to {det}")
|
|
66
87
|
caput(pv.me14e_gp101, det)
|
|
67
88
|
|
|
68
89
|
|
|
@@ -75,16 +96,55 @@ def gui_set_parameters(
|
|
|
75
96
|
transmission: float,
|
|
76
97
|
n_shots: int,
|
|
77
98
|
chip_type: str,
|
|
99
|
+
map_type: str,
|
|
100
|
+
chip_format: list[int | float], # for Lite Oxford it's the chipmap
|
|
78
101
|
checker_pattern: bool,
|
|
79
102
|
pump_probe: str,
|
|
80
103
|
laser_dwell: float,
|
|
81
104
|
laser_delay: float,
|
|
82
105
|
pre_pump: float,
|
|
83
106
|
) -> MsgGenerator:
|
|
107
|
+
"""Set the parameter model for the data collection.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
sub_dir (str): subdirectory of the visit to write data in.
|
|
111
|
+
chip_name (str): a name identifying the current chip collection, will be used
|
|
112
|
+
as filename.
|
|
113
|
+
exp_time (float): exposure time of each window shot, in s.
|
|
114
|
+
det_dist (float): sample-detector distance, in mm.
|
|
115
|
+
transmission (float): requested beam intensity transmission, expressed as
|
|
116
|
+
a fraction, e.g. 0.3.
|
|
117
|
+
n_shots (int): number of times each window should be collected.
|
|
118
|
+
chip_type (str): type of chip in use.
|
|
119
|
+
map_type (str): if an Oxford chip is used, define whether it's a full chip
|
|
120
|
+
collection or lite mapping is in use. For all other chip, this will be None.
|
|
121
|
+
chip_format (list[int|float]): for a custom chip, a list of the number of x,y
|
|
122
|
+
steps and the x,y step size. For an Oxford chip, the list should be empty
|
|
123
|
+
if collecting a full chip and a list of the block numbers to scan for a
|
|
124
|
+
lite collection.
|
|
125
|
+
checker_pattern (bool): whether checker_pattern is turned on, ie. only every
|
|
126
|
+
other window in a block gets collected
|
|
127
|
+
pump_probe (str): pump probe setting.
|
|
128
|
+
laser_dwell (float): laser exposure time for pump probe collections, in s.
|
|
129
|
+
laser_delay (float): delay between laser exposure and collection, in s.
|
|
130
|
+
pre_pump (float): pre-pump exposure time for a pump probe short2 collection,
|
|
131
|
+
ie a pump-in-probe where the collection starts during the pump.
|
|
132
|
+
"""
|
|
84
133
|
# NOTE still a work in progress, adding to it as the ui grows
|
|
134
|
+
# See progression of https://github.com/DiamondLightSource/mx-daq-ui/issues/3
|
|
85
135
|
detector_stage = i24.detector_motion()
|
|
86
136
|
det_type = yield from get_detector_type(detector_stage)
|
|
87
|
-
|
|
137
|
+
_format = chip_format if ChipType[chip_type] is ChipType.Custom else None
|
|
138
|
+
chip_params = get_chip_format(ChipType[chip_type], _format)
|
|
139
|
+
if ChipType[chip_type] in [ChipType.Oxford, ChipType.OxfordInner]:
|
|
140
|
+
mapping = MappingType.Lite if map_type == "Lite" else MappingType.NoMap
|
|
141
|
+
if mapping is MappingType.Lite and len(chip_format) == 0:
|
|
142
|
+
# this logic should go in the gui with error message.
|
|
143
|
+
raise EmptyMapError("No blocks chosen")
|
|
144
|
+
chip_map = chip_format
|
|
145
|
+
else:
|
|
146
|
+
mapping = MappingType.NoMap
|
|
147
|
+
chip_map = []
|
|
88
148
|
|
|
89
149
|
params = {
|
|
90
150
|
"visit": _read_visit_directory_from_file().as_posix(), # noqa
|
|
@@ -96,14 +156,14 @@ def gui_set_parameters(
|
|
|
96
156
|
"num_exposures": n_shots,
|
|
97
157
|
"transmission": transmission,
|
|
98
158
|
"chip": chip_params,
|
|
99
|
-
"map_type":
|
|
100
|
-
"chip_map":
|
|
159
|
+
"map_type": mapping,
|
|
160
|
+
"chip_map": chip_map,
|
|
101
161
|
"pump_repeat": PumpProbeSetting[pump_probe], # pump_repeat,
|
|
102
162
|
"laser_dwell_s": laser_dwell,
|
|
103
163
|
"laser_delay_s": laser_delay,
|
|
104
164
|
"checker_pattern": checker_pattern,
|
|
105
165
|
"pre_pump_exposure_s": pre_pump,
|
|
106
166
|
}
|
|
107
|
-
|
|
108
|
-
# This will then run the run_fixed_target plan
|
|
167
|
+
# TODO run the run_fixed_target plan once params are set (GUI not ready yet)
|
|
109
168
|
yield from bps.sleep(0.5)
|
|
169
|
+
return FixedTargetParameters(**params)
|