mx-bluesky 1.5.10__py3-none-any.whl → 1.5.12__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/experiment_plans/__init__.py +0 -0
- mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/robot_load_plan.py +198 -0
- mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py +2 -2
- mx_bluesky/beamlines/aithre_lasershaping/parameters/__init__.py +0 -0
- mx_bluesky/beamlines/aithre_lasershaping/parameters/constants.py +17 -0
- mx_bluesky/beamlines/aithre_lasershaping/parameters/robot_load_parameters.py +13 -0
- mx_bluesky/beamlines/aithre_lasershaping/pin_tip_centring.py +31 -0
- mx_bluesky/beamlines/aithre_lasershaping/robot_load.py +80 -0
- mx_bluesky/beamlines/i02_1/parameters/gridscan.py +1 -1
- mx_bluesky/beamlines/i04/__init__.py +6 -2
- mx_bluesky/beamlines/i04/callbacks/murko_callback.py +27 -12
- mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +94 -20
- mx_bluesky/beamlines/i04/external_interaction/__init__.py +0 -0
- mx_bluesky/beamlines/i04/external_interaction/config_server.py +15 -0
- mx_bluesky/beamlines/i04/oav_centering_plans/__init__.py +0 -0
- mx_bluesky/beamlines/i04/oav_centering_plans/oav_imaging.py +115 -0
- mx_bluesky/beamlines/i04/parameters/__init__.py +0 -0
- mx_bluesky/beamlines/i04/parameters/constants.py +21 -0
- mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +24 -1
- mx_bluesky/beamlines/i04/thawing_plan.py +149 -154
- mx_bluesky/beamlines/i24/jungfrau_commissioning/experiment_plans/do_darks.py +55 -10
- mx_bluesky/beamlines/i24/jungfrau_commissioning/plan_stubs/do_external_acquisition.py +1 -1
- mx_bluesky/beamlines/i24/jungfrau_commissioning/plan_stubs/plan_utils.py +1 -1
- mx_bluesky/beamlines/i24/serial/__init__.py +7 -5
- mx_bluesky/beamlines/i24/serial/dcid.py +6 -7
- mx_bluesky/beamlines/i24/serial/extruder/{i24ssx_Extruder_Collect_py3v2.py → i24ssx_extruder_collect_py3v2.py} +70 -37
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/CustomChip_py3v1.edl +11 -11
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DetStage.edl +3 -3
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +142 -142
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/MappingLite-oxford_py3v1.edl +135 -135
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/PMAC_Command.edl +8 -8
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +13 -13
- mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_Collect_py3v1.py → i24ssx_chip_collect_py3v1.py} +12 -9
- mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_Manager_py3v1.py → i24ssx_chip_manager_py3v1.py} +81 -78
- mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_StartUp_py3v1.py → i24ssx_chip_startup_py3v1.py} +3 -3
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +33 -33
- mx_bluesky/beamlines/i24/serial/log.py +11 -11
- mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +3 -3
- mx_bluesky/beamlines/i24/serial/parameters/utils.py +5 -5
- mx_bluesky/beamlines/i24/serial/setup_beamline/ca.py +0 -12
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +122 -334
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv_abstract.py +5 -5
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +30 -251
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +3 -3
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +4 -4
- mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +103 -16
- mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py +64 -0
- mx_bluesky/beamlines/i24/serial/write_nexus.py +4 -4
- mx_bluesky/common/device_setup_plans/gonio.py +28 -0
- mx_bluesky/common/device_setup_plans/manipulate_sample.py +8 -1
- mx_bluesky/common/device_setup_plans/robot_load_unload.py +1 -1
- mx_bluesky/common/device_setup_plans/setup_oav.py +8 -0
- mx_bluesky/common/device_setup_plans/setup_zebra_and_shutter.py +0 -5
- mx_bluesky/common/device_setup_plans/xbpm_feedback.py +8 -1
- mx_bluesky/common/experiment_plans/beamstop_check.py +229 -0
- mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py +8 -6
- mx_bluesky/common/experiment_plans/common_grid_detect_then_xray_centre_plan.py +2 -2
- mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py +1 -1
- mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py +7 -4
- mx_bluesky/common/experiment_plans/inner_plans/write_sample_status.py +2 -2
- mx_bluesky/common/experiment_plans/oav_snapshot_plan.py +1 -2
- mx_bluesky/{hyperion → common}/experiment_plans/pin_tip_centring_plan.py +23 -24
- mx_bluesky/common/external_interaction/callbacks/common/grid_detection_callback.py +5 -0
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +13 -15
- mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +3 -5
- mx_bluesky/common/external_interaction/callbacks/common/plan_reactive_callback.py +1 -1
- mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py +2 -2
- mx_bluesky/common/external_interaction/callbacks/sample_handling/sample_handling_callback.py +3 -3
- mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +12 -10
- mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py +2 -2
- mx_bluesky/common/external_interaction/config_server.py +4 -4
- mx_bluesky/common/external_interaction/ispyb/data_model.py +11 -4
- mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +163 -4
- mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +76 -167
- mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py +0 -14
- mx_bluesky/common/external_interaction/nexus/nexus_utils.py +2 -2
- mx_bluesky/common/external_interaction/nexus/write_nexus.py +3 -3
- mx_bluesky/common/parameters/components.py +1 -0
- mx_bluesky/common/parameters/constants.py +4 -3
- mx_bluesky/common/parameters/device_composites.py +4 -2
- mx_bluesky/common/parameters/gridscan.py +2 -2
- mx_bluesky/common/utils/exceptions.py +24 -7
- mx_bluesky/common/utils/log.py +13 -4
- mx_bluesky/common/utils/tracing.py +5 -5
- mx_bluesky/common/utils/utils.py +56 -8
- mx_bluesky/hyperion/__main__.py +6 -16
- mx_bluesky/hyperion/baton_handler.py +38 -14
- mx_bluesky/hyperion/device_setup_plans/utils.py +1 -1
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +1 -1
- mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +15 -13
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +9 -9
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +7 -8
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +3 -10
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +4 -2
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +10 -4
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/udc_default_state.py +160 -0
- mx_bluesky/hyperion/external_interaction/agamemnon.py +3 -3
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +2 -2
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +3 -3
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +1 -0
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +3 -6
- mx_bluesky/hyperion/external_interaction/config_server.py +5 -5
- mx_bluesky/hyperion/parameters/constants.py +11 -4
- mx_bluesky/hyperion/parameters/device_composites.py +2 -2
- mx_bluesky/hyperion/parameters/gridscan.py +4 -4
- mx_bluesky/hyperion/parameters/robot_load.py +1 -9
- mx_bluesky/hyperion/plan_runner.py +6 -6
- mx_bluesky/hyperion/runner.py +10 -8
- mx_bluesky/jupyter_example.ipynb +3 -3
- {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/METADATA +9 -7
- {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/RECORD +118 -104
- mx_bluesky/common/experiment_plans/inner_plans/udc_default_state.py +0 -65
- mx_bluesky/common/external_interaction/callbacks/common/logging_callback.py +0 -29
- mx_bluesky/hyperion/device_setup_plans/smargon.py +0 -25
- {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/WHEEL +0 -0
- {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/licenses/LICENSE +0 -0
- {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/top_level.txt +0 -0
|
@@ -37,7 +37,7 @@ def call_nexgen(
|
|
|
37
37
|
Raises:
|
|
38
38
|
ValueError: For a wrong experiment type passed (either unknown or not matched \
|
|
39
39
|
to parameter model).
|
|
40
|
-
HTTPError: For a problem with
|
|
40
|
+
HTTPError: For a problem with response from server
|
|
41
41
|
|
|
42
42
|
"""
|
|
43
43
|
current_chip_map = None
|
|
@@ -55,7 +55,7 @@ def call_nexgen(
|
|
|
55
55
|
total_numb_imgs = parameters.num_images
|
|
56
56
|
pump_status = parameters.pump_status
|
|
57
57
|
|
|
58
|
-
filename_prefix = cagetstring(Eiger.
|
|
58
|
+
filename_prefix = cagetstring(Eiger.PV.filename_rbv)
|
|
59
59
|
meta_h5 = parameters.visit / parameters.directory / f"{filename_prefix}_meta.h5"
|
|
60
60
|
t0 = time.time()
|
|
61
61
|
max_wait = 60 # seconds
|
|
@@ -71,7 +71,7 @@ def call_nexgen(
|
|
|
71
71
|
SSX_LOGGER.warning(f"Giving up waiting for {meta_h5} after {max_wait} seconds")
|
|
72
72
|
return
|
|
73
73
|
|
|
74
|
-
bit_depth = int(caget(Eiger.
|
|
74
|
+
bit_depth = int(caget(Eiger.PV.bit_depth))
|
|
75
75
|
SSX_LOGGER.debug(
|
|
76
76
|
f"Call to nexgen server with the following chip definition: \n{chip_prog_dict}"
|
|
77
77
|
)
|
|
@@ -109,7 +109,7 @@ def submit_to_server(
|
|
|
109
109
|
Raises:
|
|
110
110
|
ValueError: For a wrong experiment type passed (either unknown or not matched \
|
|
111
111
|
to parameter model).
|
|
112
|
-
HTTPError: For a problem with
|
|
112
|
+
HTTPError: For a problem with response from server
|
|
113
113
|
|
|
114
114
|
"""
|
|
115
115
|
access_token = pathlib.Path("/scratch/ssx_nexgen.key").read_text().strip()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from bluesky import plan_stubs as bps
|
|
3
|
+
from bluesky.utils import FailedStatus
|
|
4
|
+
from dodal.devices.motors import XYZOmegaStage
|
|
5
|
+
from ophyd_async.epics.motor import MotorLimitsError
|
|
6
|
+
|
|
7
|
+
from mx_bluesky.common.utils.exceptions import SampleError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def move_gonio_warn_on_out_of_range(
|
|
11
|
+
gonio: XYZOmegaStage,
|
|
12
|
+
position: np.ndarray | list[float] | tuple[float, float, float],
|
|
13
|
+
):
|
|
14
|
+
"""
|
|
15
|
+
Throws a SampleException if the specified position is out of range for the
|
|
16
|
+
gonio. Otherwise moves to that position. The check is from ophyd-async
|
|
17
|
+
"""
|
|
18
|
+
try:
|
|
19
|
+
yield from bps.mv(
|
|
20
|
+
gonio.x, position[0], gonio.y, position[1], gonio.z, position[2]
|
|
21
|
+
)
|
|
22
|
+
except FailedStatus as fs:
|
|
23
|
+
if isinstance(fs.__cause__, MotorLimitsError):
|
|
24
|
+
raise SampleError(
|
|
25
|
+
"Pin tip centring failed - pin too long/short/bent and out of range"
|
|
26
|
+
) from fs.__cause__
|
|
27
|
+
else:
|
|
28
|
+
raise fs
|
|
@@ -8,6 +8,7 @@ from dodal.devices.aperturescatterguard import (
|
|
|
8
8
|
from dodal.devices.backlight import Backlight, InOut
|
|
9
9
|
from dodal.devices.detector.detector_motion import DetectorMotion
|
|
10
10
|
from dodal.devices.smargon import CombinedMove, Smargon
|
|
11
|
+
from dodal.devices.thawer import OnOff, Thawer
|
|
11
12
|
|
|
12
13
|
from mx_bluesky.common.parameters.constants import PlanGroupCheckpointConstants
|
|
13
14
|
from mx_bluesky.common.utils.log import LOGGER
|
|
@@ -19,9 +20,13 @@ def setup_sample_environment(
|
|
|
19
20
|
aperture_scatterguard: ApertureScatterguard,
|
|
20
21
|
aperture_position_gda_name: str | None,
|
|
21
22
|
backlight: Backlight,
|
|
23
|
+
thawer: Thawer,
|
|
22
24
|
group="setup_senv",
|
|
23
25
|
):
|
|
24
|
-
"""Move the aperture into required position, move out the backlight
|
|
26
|
+
"""Move the aperture into required position, move out the backlight so that it
|
|
27
|
+
doesn't cause a shadow on the detector and turn off thawing so it doesn't vibrate
|
|
28
|
+
the pin."""
|
|
29
|
+
|
|
25
30
|
yield from bps.abs_set(backlight, InOut.OUT, group=group)
|
|
26
31
|
|
|
27
32
|
aperture_value = (
|
|
@@ -33,6 +38,8 @@ def setup_sample_environment(
|
|
|
33
38
|
aperture_scatterguard, aperture_value, group=group
|
|
34
39
|
)
|
|
35
40
|
|
|
41
|
+
yield from bps.abs_set(thawer, OnOff.OFF, group=group)
|
|
42
|
+
|
|
36
43
|
|
|
37
44
|
def move_aperture_if_required(
|
|
38
45
|
aperture_scatterguard: ApertureScatterguard,
|
|
@@ -117,7 +117,7 @@ def robot_unload(
|
|
|
117
117
|
yield from bps.save()
|
|
118
118
|
|
|
119
119
|
def _unload():
|
|
120
|
-
yield from bps.
|
|
120
|
+
yield from bps.abs_set(robot, None, wait=True)
|
|
121
121
|
yield from wait_for_smargon_not_disabled(smargon)
|
|
122
122
|
|
|
123
123
|
gonio_finished = yield from do_plan_while_lower_gonio_at_home(
|
|
@@ -28,6 +28,11 @@ def setup_pin_tip_detection_params(
|
|
|
28
28
|
pin_tip_detect_device.preprocess_ksize, parameters.preprocess_K_size
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
+
# sets iteration for blur
|
|
32
|
+
yield from set_using_group(
|
|
33
|
+
pin_tip_detect_device.preprocess_iterations, parameters.preprocess_iter
|
|
34
|
+
)
|
|
35
|
+
|
|
31
36
|
# Canny edge detect - lower
|
|
32
37
|
yield from set_using_group(
|
|
33
38
|
pin_tip_detect_device.canny_lower_threshold,
|
|
@@ -40,6 +45,9 @@ def setup_pin_tip_detection_params(
|
|
|
40
45
|
parameters.canny_edge_upper_threshold,
|
|
41
46
|
)
|
|
42
47
|
|
|
48
|
+
# "Open" morphological operation
|
|
49
|
+
yield from set_using_group(pin_tip_detect_device.open_ksize, parameters.open_ksize)
|
|
50
|
+
|
|
43
51
|
# "Close" morphological operation
|
|
44
52
|
yield from set_using_group(
|
|
45
53
|
pin_tip_detect_device.close_ksize, parameters.close_ksize
|
|
@@ -183,11 +183,6 @@ def setup_zebra_for_rotation(
|
|
|
183
183
|
|
|
184
184
|
ttl_detector = ttl_input_for_detector_to_use or zebra.mapping.outputs.TTL_DETECTOR
|
|
185
185
|
|
|
186
|
-
if not isinstance(direction, RotationDirection):
|
|
187
|
-
raise ValueError(
|
|
188
|
-
"Disallowed rotation direction provided to Zebra setup plan. "
|
|
189
|
-
"Use RotationDirection.POSITIVE or RotationDirection.NEGATIVE."
|
|
190
|
-
)
|
|
191
186
|
yield from bps.abs_set(zebra.pc.dir, direction.value, group=group)
|
|
192
187
|
LOGGER.info("ZEBRA SETUP: START")
|
|
193
188
|
# Set gate start, adjust for shutter opening time if necessary
|
|
@@ -6,7 +6,9 @@ from mx_bluesky.common.utils.log import LOGGER
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def unpause_xbpm_feedback_and_set_transmission_to_1(
|
|
9
|
-
xbpm_feedback: XBPMFeedback,
|
|
9
|
+
xbpm_feedback: XBPMFeedback,
|
|
10
|
+
attenuator: BinaryFilterAttenuator,
|
|
11
|
+
timeout_for_stable: float = 0,
|
|
10
12
|
):
|
|
11
13
|
"""Turns the XBPM feedback back on and sets transmission to 1 so that it keeps the
|
|
12
14
|
beam aligned whilst not collecting.
|
|
@@ -15,8 +17,13 @@ def unpause_xbpm_feedback_and_set_transmission_to_1(
|
|
|
15
17
|
xbpm_feedback (XBPMFeedback): The XBPM device that is responsible for keeping
|
|
16
18
|
the beam in position
|
|
17
19
|
attenuator (BinaryFilterAttenuator): The attenuator used to set transmission
|
|
20
|
+
timeout_for_stable: If specified and non-zero, specifies the time in seconds to wait for
|
|
21
|
+
feedback to stabilise, otherwise we do not wait.
|
|
18
22
|
"""
|
|
19
23
|
yield from bps.mv(xbpm_feedback.pause_feedback, Pause.RUN, attenuator, 1.0)
|
|
24
|
+
if timeout_for_stable:
|
|
25
|
+
yield from bps.trigger(xbpm_feedback, group="feedback")
|
|
26
|
+
yield from bps.wait(group="feedback", timeout=timeout_for_stable)
|
|
20
27
|
|
|
21
28
|
|
|
22
29
|
def check_and_pause_feedback(
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import pydantic
|
|
2
|
+
from bluesky import plan_stubs as bps
|
|
3
|
+
from bluesky.utils import MsgGenerator
|
|
4
|
+
from dodal.common.beamlines.beamline_parameters import GDABeamlineParameters
|
|
5
|
+
from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureValue
|
|
6
|
+
from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
|
|
7
|
+
from dodal.devices.backlight import Backlight
|
|
8
|
+
from dodal.devices.baton import Baton
|
|
9
|
+
from dodal.devices.detector.detector_motion import DetectorMotion, ShutterState
|
|
10
|
+
from dodal.devices.ipin import IPin, IPinGain
|
|
11
|
+
from dodal.devices.mx_phase1.beamstop import Beamstop, BeamstopPositions
|
|
12
|
+
from dodal.devices.xbpm_feedback import XBPMFeedback
|
|
13
|
+
from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter, ZebraShutterState
|
|
14
|
+
from ophyd_async.core import InOut
|
|
15
|
+
|
|
16
|
+
from mx_bluesky.common.device_setup_plans.xbpm_feedback import (
|
|
17
|
+
unpause_xbpm_feedback_and_set_transmission_to_1,
|
|
18
|
+
)
|
|
19
|
+
from mx_bluesky.common.utils.exceptions import BeamlineCheckFailureError
|
|
20
|
+
from mx_bluesky.common.utils.log import LOGGER
|
|
21
|
+
|
|
22
|
+
_GROUP_PRE_BEAMSTOP_OUT_CHECK = "pre_background_check"
|
|
23
|
+
_GROUP_POST_BEAMSTOP_OUT_CHECK = "post_background_check"
|
|
24
|
+
_PARAM_IPIN_THRESHOLD = "ipin_threshold"
|
|
25
|
+
|
|
26
|
+
_FEEDBACK_TIMEOUT_S = 10
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
|
|
30
|
+
class BeamstopCheckDevices:
|
|
31
|
+
aperture_scatterguard: ApertureScatterguard
|
|
32
|
+
attenuator: BinaryFilterAttenuator
|
|
33
|
+
backlight: Backlight
|
|
34
|
+
baton: Baton
|
|
35
|
+
beamstop: Beamstop
|
|
36
|
+
detector_motion: DetectorMotion
|
|
37
|
+
ipin: IPin
|
|
38
|
+
sample_shutter: ZebraShutter
|
|
39
|
+
xbpm_feedback: XBPMFeedback
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SampleCurrentBelowThresholdError(BeamlineCheckFailureError): ...
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class BeamstopNotInPositionError(BeamlineCheckFailureError): ...
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class BeamObstructedError(BeamlineCheckFailureError): ...
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def move_beamstop_in_and_verify_using_diode(
|
|
52
|
+
devices: BeamstopCheckDevices,
|
|
53
|
+
beamline_parameters: GDABeamlineParameters,
|
|
54
|
+
detector_min_z_mm: float,
|
|
55
|
+
detector_max_z_mm: float,
|
|
56
|
+
) -> MsgGenerator:
|
|
57
|
+
"""
|
|
58
|
+
Move the beamstop into the data collection position, checking the beam current
|
|
59
|
+
via the diode on the detector shutter, first with the beamstop out and then with
|
|
60
|
+
the beamstop in.
|
|
61
|
+
These checks aim to ensure that
|
|
62
|
+
* The beam is not obstructed by something other than the beamstop
|
|
63
|
+
* The beamstop has been successfully moved and is intercepting the beam
|
|
64
|
+
|
|
65
|
+
As a side-effect, this plan also does the following things:
|
|
66
|
+
* Move the detector z-axis in range
|
|
67
|
+
* Move the backlight out
|
|
68
|
+
* Unpauses feedback
|
|
69
|
+
* Sets xmission to 100%
|
|
70
|
+
* Sets IPin gain to 10^4 low noise
|
|
71
|
+
* Moves aperture scatterguard to OUT_OF_BEAM if it is currently in beam
|
|
72
|
+
|
|
73
|
+
Implementation note:
|
|
74
|
+
Some checks are repeated here such as closing the sample shutter, so that at a
|
|
75
|
+
future point this plan may be run independently of the udc default state script
|
|
76
|
+
if desired.
|
|
77
|
+
Note on commissioning mode:
|
|
78
|
+
When commissioning mode is enabled, the beamstop check will execute normally except
|
|
79
|
+
where it expects beam to be present, the absence of beam will be ignored.
|
|
80
|
+
Args:
|
|
81
|
+
devices: The device composite containing the necessary devices
|
|
82
|
+
beamline_parameters: A mapping containing the beamlineParameters
|
|
83
|
+
detector_min_z_mm: Detector minimum distance at which beamstop is effective
|
|
84
|
+
detector_max_z_mm: Detector maximum distance at which beamstop is effective
|
|
85
|
+
Raises:
|
|
86
|
+
SampleCurrentBelowThresholdError: If we do not have sufficient sample current to perform
|
|
87
|
+
the check.
|
|
88
|
+
BeamstopNotInPositionError: If the ipin current is too high, indicating that the
|
|
89
|
+
beamstop is not in the correct position.
|
|
90
|
+
BeamObstructedError: If the ipin current is too low after the first check
|
|
91
|
+
with the beamstop out, indicating a likely obstruction.
|
|
92
|
+
"""
|
|
93
|
+
LOGGER.info("Performing beamstop check...")
|
|
94
|
+
commissioning_mode_enabled = yield from bps.rd(devices.baton.commissioning)
|
|
95
|
+
beamstop_threshold_uA = beamline_parameters[_PARAM_IPIN_THRESHOLD] # noqa: N806
|
|
96
|
+
|
|
97
|
+
yield from _start_moving_detector_if_needed(
|
|
98
|
+
devices, detector_min_z_mm, detector_max_z_mm, _GROUP_POST_BEAMSTOP_OUT_CHECK
|
|
99
|
+
)
|
|
100
|
+
yield from _pre_beamstop_out_check_actions(devices)
|
|
101
|
+
yield from _beamstop_out_check(
|
|
102
|
+
devices, beamstop_threshold_uA, commissioning_mode_enabled
|
|
103
|
+
)
|
|
104
|
+
yield from _post_beamstop_out_check_actions(devices, _GROUP_POST_BEAMSTOP_OUT_CHECK)
|
|
105
|
+
yield from _beamstop_in_check(devices, beamstop_threshold_uA)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _pre_beamstop_out_check_actions(devices: BeamstopCheckDevices):
|
|
109
|
+
# Re-verify that the sample shutter is closed
|
|
110
|
+
yield from bps.abs_set(devices.sample_shutter, ZebraShutterState.CLOSE, wait=True)
|
|
111
|
+
LOGGER.info("Unpausing feedback, transmission to 100%, wait for feedback stable...")
|
|
112
|
+
try:
|
|
113
|
+
yield from unpause_xbpm_feedback_and_set_transmission_to_1(
|
|
114
|
+
devices.xbpm_feedback,
|
|
115
|
+
devices.attenuator,
|
|
116
|
+
_FEEDBACK_TIMEOUT_S,
|
|
117
|
+
)
|
|
118
|
+
except TimeoutError as e:
|
|
119
|
+
raise SampleCurrentBelowThresholdError(
|
|
120
|
+
"Unable to perform beamstop check - xbpm feedback did not become stable "
|
|
121
|
+
" - check if beam present?"
|
|
122
|
+
) from e
|
|
123
|
+
|
|
124
|
+
yield from bps.abs_set(
|
|
125
|
+
devices.backlight, InOut.OUT, group=_GROUP_PRE_BEAMSTOP_OUT_CHECK
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
yield from bps.abs_set(
|
|
129
|
+
devices.aperture_scatterguard.selected_aperture,
|
|
130
|
+
ApertureValue.OUT_OF_BEAM,
|
|
131
|
+
group=_GROUP_PRE_BEAMSTOP_OUT_CHECK,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
yield from bps.abs_set(
|
|
135
|
+
devices.ipin.gain,
|
|
136
|
+
IPinGain.GAIN_10E4_LOW_NOISE,
|
|
137
|
+
group=_GROUP_PRE_BEAMSTOP_OUT_CHECK,
|
|
138
|
+
)
|
|
139
|
+
yield from bps.abs_set(
|
|
140
|
+
devices.detector_motion.shutter,
|
|
141
|
+
ShutterState.CLOSED,
|
|
142
|
+
group=_GROUP_PRE_BEAMSTOP_OUT_CHECK,
|
|
143
|
+
)
|
|
144
|
+
yield from bps.abs_set(
|
|
145
|
+
devices.beamstop.selected_pos,
|
|
146
|
+
BeamstopPositions.OUT_OF_BEAM,
|
|
147
|
+
group=_GROUP_PRE_BEAMSTOP_OUT_CHECK,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
LOGGER.info("Waiting for pre-background-check motions to complete...")
|
|
151
|
+
yield from bps.wait(group=_GROUP_PRE_BEAMSTOP_OUT_CHECK)
|
|
152
|
+
|
|
153
|
+
# Check detector shutter is closed
|
|
154
|
+
detector_shutter_state = yield from bps.rd(devices.detector_motion.shutter)
|
|
155
|
+
detector_shutter_is_closed = detector_shutter_state == ShutterState.CLOSED
|
|
156
|
+
if not detector_shutter_is_closed:
|
|
157
|
+
raise RuntimeError(
|
|
158
|
+
"Unable to proceed with beamstop background check, detector shutter did not close"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _start_moving_detector_if_needed(
|
|
163
|
+
devices: BeamstopCheckDevices,
|
|
164
|
+
detector_min_z_mm: float,
|
|
165
|
+
detector_max_z_mm: float,
|
|
166
|
+
group: str = None,
|
|
167
|
+
):
|
|
168
|
+
detector_current_z = yield from bps.rd(devices.detector_motion.z)
|
|
169
|
+
target_z = max(min(detector_current_z, detector_max_z_mm), detector_min_z_mm)
|
|
170
|
+
if detector_current_z != target_z:
|
|
171
|
+
LOGGER.info(
|
|
172
|
+
f"Detector distance {detector_current_z}mm outside acceptable range for diode "
|
|
173
|
+
f"check {detector_min_z_mm} <= z <= {detector_max_z_mm}, moving it."
|
|
174
|
+
)
|
|
175
|
+
yield from bps.abs_set(devices.detector_motion.z, target_z, group=group)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _post_beamstop_out_check_actions(devices: BeamstopCheckDevices, group: str):
|
|
179
|
+
yield from bps.abs_set(
|
|
180
|
+
devices.beamstop.selected_pos,
|
|
181
|
+
BeamstopPositions.DATA_COLLECTION,
|
|
182
|
+
group=group,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
LOGGER.info("Waiting for detector motion to complete...")
|
|
186
|
+
yield from bps.wait(group=group)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _beamstop_out_check(
|
|
190
|
+
devices: BeamstopCheckDevices,
|
|
191
|
+
beamstop_threshold_uA: float, # noqa: N803
|
|
192
|
+
commissioning_mode_enabled: bool,
|
|
193
|
+
):
|
|
194
|
+
ipin_beamstop_out_uA = yield from _check_ipin(devices) # noqa: N806
|
|
195
|
+
|
|
196
|
+
LOGGER.info(f"Beamstop out ipin = {ipin_beamstop_out_uA}uA")
|
|
197
|
+
if ipin_beamstop_out_uA < beamstop_threshold_uA:
|
|
198
|
+
msg = (
|
|
199
|
+
f"IPin current {ipin_beamstop_out_uA}uA below threshold "
|
|
200
|
+
f"{beamstop_threshold_uA} with beamstop out - check "
|
|
201
|
+
f"that beam is not obstructed."
|
|
202
|
+
)
|
|
203
|
+
if commissioning_mode_enabled:
|
|
204
|
+
LOGGER.warning(msg + " - commissioning mode enabled - ignoring this")
|
|
205
|
+
else:
|
|
206
|
+
raise BeamObstructedError(msg)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _beamstop_in_check(devices: BeamstopCheckDevices, beamstop_threshold_uA: float): # noqa: N803
|
|
210
|
+
ipin_in_beam_uA = yield from _check_ipin(devices) # noqa: N806
|
|
211
|
+
if ipin_in_beam_uA > beamstop_threshold_uA:
|
|
212
|
+
raise BeamstopNotInPositionError(
|
|
213
|
+
f"Ipin is too high at {ipin_in_beam_uA} - check that beamstop is "
|
|
214
|
+
f"in the correct position."
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _check_ipin(devices: BeamstopCheckDevices):
|
|
219
|
+
try:
|
|
220
|
+
yield from bps.abs_set(
|
|
221
|
+
devices.sample_shutter, ZebraShutterState.OPEN, wait=True
|
|
222
|
+
)
|
|
223
|
+
yield from bps.sleep(1) # wait for reading to settle
|
|
224
|
+
|
|
225
|
+
return (yield from bps.rd(devices.ipin.pin_readback)) # noqa: N806
|
|
226
|
+
finally:
|
|
227
|
+
yield from bps.abs_set(
|
|
228
|
+
devices.sample_shutter, ZebraShutterState.CLOSE, wait=True
|
|
229
|
+
)
|
|
@@ -37,8 +37,8 @@ from mx_bluesky.common.parameters.constants import (
|
|
|
37
37
|
from mx_bluesky.common.parameters.device_composites import FlyScanEssentialDevices
|
|
38
38
|
from mx_bluesky.common.parameters.gridscan import SpecifiedThreeDGridScan
|
|
39
39
|
from mx_bluesky.common.utils.exceptions import (
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
CrystalNotFoundError,
|
|
41
|
+
SampleError,
|
|
42
42
|
)
|
|
43
43
|
from mx_bluesky.common.utils.log import LOGGER
|
|
44
44
|
from mx_bluesky.common.utils.tracing import TRACER
|
|
@@ -77,7 +77,7 @@ def generic_tidy(xrc_composite: FlyScanEssentialDevices, wait=True) -> MsgGenera
|
|
|
77
77
|
yield from bps.wait(group)
|
|
78
78
|
|
|
79
79
|
|
|
80
|
-
def
|
|
80
|
+
def construct_beamline_specific_fast_gridscan_features(
|
|
81
81
|
setup_trigger_plan: Callable[..., MsgGenerator],
|
|
82
82
|
tidy_plan: Callable[..., MsgGenerator],
|
|
83
83
|
set_flyscan_params_plan: Callable[..., MsgGenerator],
|
|
@@ -235,7 +235,7 @@ def _fetch_xrc_results_from_zocalo(
|
|
|
235
235
|
flyscan_results = [_generate_dummy_xrc_result(parameters)]
|
|
236
236
|
else:
|
|
237
237
|
LOGGER.warning("No X-ray centre received")
|
|
238
|
-
raise
|
|
238
|
+
raise CrystalNotFoundError()
|
|
239
239
|
yield from _fire_xray_centre_result_event(flyscan_results)
|
|
240
240
|
|
|
241
241
|
|
|
@@ -276,9 +276,11 @@ def run_gridscan(
|
|
|
276
276
|
yield from beamline_specific.set_flyscan_params_plan()
|
|
277
277
|
except FailedStatus as e:
|
|
278
278
|
if isinstance(e.__cause__, GridScanInvalidError):
|
|
279
|
-
raise
|
|
279
|
+
raise SampleError(
|
|
280
280
|
"Scan invalid - gridscan not valid for detected pin position"
|
|
281
281
|
) from e
|
|
282
|
+
else:
|
|
283
|
+
raise e
|
|
282
284
|
|
|
283
285
|
LOGGER.info("Waiting for arming to finish")
|
|
284
286
|
yield from bps.wait(PlanGroupCheckpointConstants.GRID_READY_FOR_DC)
|
|
@@ -301,7 +303,7 @@ def run_gridscan(
|
|
|
301
303
|
def _xrc_result_in_boxes_to_result_in_mm(
|
|
302
304
|
xrc_result: XrcResult, parameters: SpecifiedThreeDGridScan
|
|
303
305
|
) -> XRayCentreResult:
|
|
304
|
-
fgs_params = parameters.
|
|
306
|
+
fgs_params = parameters.fast_gridscan_params
|
|
305
307
|
xray_centre = fgs_params.grid_position_to_motor_position(
|
|
306
308
|
np.array(xrc_result["centre_of_mass"])
|
|
307
309
|
)
|
|
@@ -29,7 +29,7 @@ from mx_bluesky.common.experiment_plans.oav_grid_detection_plan import (
|
|
|
29
29
|
grid_detection_plan,
|
|
30
30
|
)
|
|
31
31
|
from mx_bluesky.common.experiment_plans.oav_snapshot_plan import (
|
|
32
|
-
|
|
32
|
+
setup_beamline_for_oav,
|
|
33
33
|
)
|
|
34
34
|
from mx_bluesky.common.external_interaction.callbacks.common.grid_detection_callback import (
|
|
35
35
|
GridDetectionCallback,
|
|
@@ -123,7 +123,7 @@ def detect_grid_and_do_gridscan(
|
|
|
123
123
|
|
|
124
124
|
grid_params_callback = GridDetectionCallback()
|
|
125
125
|
|
|
126
|
-
yield from
|
|
126
|
+
yield from setup_beamline_for_oav(
|
|
127
127
|
composite.smargon,
|
|
128
128
|
composite.backlight,
|
|
129
129
|
composite.aperture_scatterguard,
|
|
@@ -46,7 +46,7 @@ def _wait_for_zocalo_to_stage_then_do_fgs(
|
|
|
46
46
|
LOGGER.info("Waiting for Zocalo device queue to have been cleared...")
|
|
47
47
|
yield from bps.wait(ZOCALO_STAGE_GROUP)
|
|
48
48
|
|
|
49
|
-
# Triggers Zocalo if
|
|
49
|
+
# Triggers Zocalo if run_engine is subscribed to ZocaloCallback
|
|
50
50
|
yield from read_hardware_for_zocalo(detector)
|
|
51
51
|
LOGGER.info("Wait for all moves with no assigned group")
|
|
52
52
|
yield from bps.wait()
|
|
@@ -4,13 +4,14 @@ import bluesky.plan_stubs as bps
|
|
|
4
4
|
from bluesky.protocols import Readable
|
|
5
5
|
from dodal.devices.aperturescatterguard import ApertureScatterguard
|
|
6
6
|
from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
|
|
7
|
+
from dodal.devices.beamsize.beamsize import BeamsizeBase
|
|
7
8
|
from dodal.devices.common_dcm import DoubleCrystalMonochromator
|
|
8
9
|
from dodal.devices.eiger import EigerDetector
|
|
9
10
|
from dodal.devices.flux import Flux
|
|
10
11
|
from dodal.devices.s4_slit_gaps import S4SlitGaps
|
|
11
12
|
from dodal.devices.smargon import Smargon
|
|
12
13
|
from dodal.devices.synchrotron import Synchrotron
|
|
13
|
-
from dodal.devices.undulator import
|
|
14
|
+
from dodal.devices.undulator import UndulatorInKeV
|
|
14
15
|
|
|
15
16
|
from mx_bluesky.common.parameters.constants import (
|
|
16
17
|
DocDescriptorNames,
|
|
@@ -40,7 +41,7 @@ def read_hardware_for_zocalo(detector: EigerDetector):
|
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
def standard_read_hardware_pre_collection(
|
|
43
|
-
undulator:
|
|
44
|
+
undulator: UndulatorInKeV,
|
|
44
45
|
synchrotron: Synchrotron,
|
|
45
46
|
s4_slit_gaps: S4SlitGaps,
|
|
46
47
|
dcm: DoubleCrystalMonochromator,
|
|
@@ -52,7 +53,7 @@ def standard_read_hardware_pre_collection(
|
|
|
52
53
|
synchrotron.synchrotron_mode,
|
|
53
54
|
s4_slit_gaps,
|
|
54
55
|
smargon,
|
|
55
|
-
dcm.
|
|
56
|
+
dcm.energy_in_keV,
|
|
56
57
|
]
|
|
57
58
|
yield from read_hardware_plan(
|
|
58
59
|
signals_to_read_pre_flyscan, DocDescriptorNames.HARDWARE_READ_PRE
|
|
@@ -65,13 +66,15 @@ def standard_read_hardware_during_collection(
|
|
|
65
66
|
flux: Flux,
|
|
66
67
|
dcm: DoubleCrystalMonochromator,
|
|
67
68
|
detector: EigerDetector,
|
|
69
|
+
beamsize: BeamsizeBase,
|
|
68
70
|
):
|
|
69
71
|
signals_to_read_during_collection = [
|
|
70
72
|
aperture_scatterguard,
|
|
71
73
|
attenuator.actual_transmission,
|
|
72
74
|
flux.flux_reading,
|
|
73
|
-
dcm.
|
|
75
|
+
dcm.energy_in_keV,
|
|
74
76
|
detector.bit_depth,
|
|
77
|
+
beamsize,
|
|
75
78
|
]
|
|
76
79
|
yield from read_hardware_plan(
|
|
77
80
|
signals_to_read_during_collection, DocDescriptorNames.HARDWARE_READ_DURING
|
|
@@ -6,7 +6,7 @@ import bluesky.preprocessors as bpp
|
|
|
6
6
|
from mx_bluesky.common.external_interaction.callbacks.sample_handling.sample_handling_callback import (
|
|
7
7
|
SampleHandlingCallback,
|
|
8
8
|
)
|
|
9
|
-
from mx_bluesky.common.utils.exceptions import
|
|
9
|
+
from mx_bluesky.common.utils.exceptions import SampleError
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class SampleStatusExceptionType(StrEnum):
|
|
@@ -27,7 +27,7 @@ def deposit_sample_error(exception_type: SampleStatusExceptionType, sample_id: i
|
|
|
27
27
|
if exception_type == SampleStatusExceptionType.BEAMLINE:
|
|
28
28
|
raise AssertionError()
|
|
29
29
|
elif exception_type == SampleStatusExceptionType.SAMPLE:
|
|
30
|
-
raise
|
|
30
|
+
raise SampleError
|
|
31
31
|
|
|
32
32
|
yield from _inner()
|
|
33
33
|
|
|
@@ -24,10 +24,9 @@ class OavSnapshotComposite(Protocol):
|
|
|
24
24
|
smargon: Smargon
|
|
25
25
|
oav: OAV
|
|
26
26
|
aperture_scatterguard: ApertureScatterguard
|
|
27
|
-
backlight: Backlight
|
|
28
27
|
|
|
29
28
|
|
|
30
|
-
def
|
|
29
|
+
def setup_beamline_for_oav(
|
|
31
30
|
smargon: Smargon,
|
|
32
31
|
backlight: Backlight,
|
|
33
32
|
aperture_scatterguard: ApertureScatterguard,
|