mx-bluesky 1.2.0__py3-none-any.whl → 1.4.1__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/__init__.py +8 -3
- mx_bluesky/__main__.py +12 -7
- mx_bluesky/_version.py +2 -2
- mx_bluesky/beamlines/i04/callbacks/murko_callback.py +14 -4
- mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +178 -0
- mx_bluesky/beamlines/i04/thawing_plan.py +49 -11
- mx_bluesky/beamlines/i24/serial/__init__.py +3 -0
- mx_bluesky/beamlines/i24/serial/dcid.py +143 -171
- mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +1 -1
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +121 -110
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +3 -6
- mx_bluesky/beamlines/i24/serial/fixed_target/ft_utils.py +0 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +164 -169
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +149 -225
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +7 -216
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +18 -17
- mx_bluesky/beamlines/i24/serial/log.py +58 -49
- mx_bluesky/beamlines/i24/serial/parameters/__init__.py +4 -0
- mx_bluesky/beamlines/i24/serial/parameters/constants.py +6 -1
- mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +42 -15
- mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +3 -3
- mx_bluesky/beamlines/i24/serial/run_extruder.sh +30 -5
- mx_bluesky/beamlines/i24/serial/run_fixed_target.sh +30 -5
- mx_bluesky/beamlines/i24/serial/run_serial.py +24 -8
- mx_bluesky/beamlines/i24/serial/setup_beamline/ca.py +0 -2
- mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +2 -0
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +104 -82
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +9 -20
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +26 -28
- mx_bluesky/beamlines/i24/serial/write_nexus.py +74 -72
- mx_bluesky/common/__init__.py +0 -0
- mx_bluesky/common/device_setup_plans/read_hardware_for_setup.py +14 -0
- mx_bluesky/common/external_interaction/config_server.py +46 -0
- mx_bluesky/common/parameters/components.py +258 -0
- mx_bluesky/common/parameters/constants.py +143 -0
- mx_bluesky/common/parameters/gridscan.py +94 -0
- mx_bluesky/common/parameters/robot_load.py +16 -0
- mx_bluesky/common/plans/__init__.py +1 -0
- mx_bluesky/common/plans/do_fgs.py +121 -0
- mx_bluesky/common/utils/log.py +118 -0
- mx_bluesky/{hyperion → common/utils}/tracing.py +2 -2
- mx_bluesky/hyperion/__main__.py +13 -10
- mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +47 -52
- mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +6 -12
- mx_bluesky/hyperion/device_setup_plans/setup_oav.py +6 -12
- mx_bluesky/hyperion/device_setup_plans/setup_panda.py +5 -6
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +49 -18
- mx_bluesky/hyperion/device_setup_plans/smargon.py +9 -9
- mx_bluesky/hyperion/device_setup_plans/utils.py +2 -2
- mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +4 -4
- mx_bluesky/hyperion/exceptions.py +13 -1
- mx_bluesky/hyperion/experiment_plans/__init__.py +4 -0
- mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +83 -0
- mx_bluesky/hyperion/experiment_plans/common/xrc_result.py +47 -0
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -9
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +147 -169
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +48 -22
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +75 -9
- mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +21 -20
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +9 -6
- mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +40 -21
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +22 -22
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +43 -39
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +69 -18
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +17 -7
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +13 -13
- mx_bluesky/hyperion/external_interaction/callbacks/__init__.py +0 -4
- mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +5 -2
- mx_bluesky/hyperion/external_interaction/callbacks/common/abstract_event.py +66 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +5 -0
- mx_bluesky/hyperion/external_interaction/callbacks/common/ispyb_mapping.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/grid_detection_callback.py +30 -25
- mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py +29 -12
- mx_bluesky/hyperion/external_interaction/callbacks/log_uid_tag_callback.py +1 -1
- mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +19 -11
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +7 -4
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +5 -3
- mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/__init__.py +0 -0
- mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +84 -0
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +38 -27
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py +5 -4
- mx_bluesky/hyperion/external_interaction/config_server.py +11 -28
- mx_bluesky/hyperion/external_interaction/exceptions.py +0 -9
- mx_bluesky/hyperion/external_interaction/ispyb/exp_eye_store.py +65 -15
- mx_bluesky/hyperion/external_interaction/ispyb/ispyb_store.py +1 -1
- mx_bluesky/hyperion/external_interaction/nexus/nexus_utils.py +2 -2
- mx_bluesky/hyperion/external_interaction/nexus/write_nexus.py +1 -1
- mx_bluesky/hyperion/log.py +0 -84
- mx_bluesky/hyperion/parameters/components.py +4 -251
- mx_bluesky/hyperion/parameters/constants.py +22 -119
- mx_bluesky/hyperion/parameters/gridscan.py +35 -74
- mx_bluesky/hyperion/parameters/load_centre_collect.py +16 -11
- mx_bluesky/hyperion/parameters/rotation.py +23 -10
- mx_bluesky/hyperion/utils/utils.py +17 -0
- mx_bluesky/hyperion/utils/validation.py +5 -6
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/METADATA +36 -33
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/RECORD +102 -89
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/WHEEL +1 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Mapping_py3v1.py +0 -161
- mx_bluesky/example.py +0 -19
- mx_bluesky/hyperion/parameters/robot_load.py +0 -16
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/LICENSE +0 -0
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from logging.handlers import TimedRotatingFileHandler
|
|
3
|
+
from os import environ
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from dodal.log import (
|
|
7
|
+
ERROR_LOG_BUFFER_LINES,
|
|
8
|
+
CircularMemoryHandler,
|
|
9
|
+
DodalLogHandlers,
|
|
10
|
+
integrate_bluesky_and_ophyd_logging,
|
|
11
|
+
set_up_all_logging_handlers,
|
|
12
|
+
)
|
|
13
|
+
from dodal.log import LOGGER as dodal_logger
|
|
14
|
+
|
|
15
|
+
LOGGER = logging.getLogger("mx-bluesky")
|
|
16
|
+
|
|
17
|
+
__logger_handlers: DodalLogHandlers | None = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ExperimentMetadataTagFilter(logging.Filter):
|
|
21
|
+
"""When an instance of this custom filter is added to a logging handler, dc_group_id
|
|
22
|
+
and run_id will be tagged in that handlers' log messages."""
|
|
23
|
+
|
|
24
|
+
dc_group_id: str | None = None
|
|
25
|
+
run_uid: str | None = None
|
|
26
|
+
|
|
27
|
+
def filter(self, record):
|
|
28
|
+
if self.dc_group_id:
|
|
29
|
+
record.dc_group_id = self.dc_group_id
|
|
30
|
+
if self.run_uid:
|
|
31
|
+
record.run_uid = self.run_uid
|
|
32
|
+
return True
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
tag_filter = ExperimentMetadataTagFilter()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def set_dcgid_tag(dcgid):
|
|
39
|
+
"""Set the datacollection group id as a tag on all subsequent log messages.
|
|
40
|
+
Setting to None will remove the tag."""
|
|
41
|
+
tag_filter.dc_group_id = dcgid
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def set_uid_tag(uid):
|
|
45
|
+
"""Set the unique id as a tag on all subsequent log messages.
|
|
46
|
+
Setting to None will remove the tag."""
|
|
47
|
+
tag_filter.run_uid = uid
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def do_default_logging_setup(
|
|
51
|
+
file_name: str,
|
|
52
|
+
graylog_port: int,
|
|
53
|
+
dev_mode: bool = False,
|
|
54
|
+
integrate_all_logs: bool = True,
|
|
55
|
+
):
|
|
56
|
+
"""Configures dodal logger so that separate debug and info log files are created,
|
|
57
|
+
info logs are sent to Graylog, info logs are streamed to sys.sterr, and logs from ophyd
|
|
58
|
+
and bluesky and ophyd-async are optionally included."""
|
|
59
|
+
|
|
60
|
+
handlers = set_up_all_logging_handlers(
|
|
61
|
+
dodal_logger,
|
|
62
|
+
_get_logging_dir(),
|
|
63
|
+
file_name,
|
|
64
|
+
dev_mode,
|
|
65
|
+
ERROR_LOG_BUFFER_LINES,
|
|
66
|
+
graylog_port,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if integrate_all_logs:
|
|
70
|
+
integrate_bluesky_and_ophyd_logging(dodal_logger)
|
|
71
|
+
|
|
72
|
+
handlers["graylog_handler"].addFilter(tag_filter)
|
|
73
|
+
|
|
74
|
+
global __logger_handlers
|
|
75
|
+
__logger_handlers = handlers
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _get_debug_handler() -> CircularMemoryHandler:
|
|
79
|
+
assert (
|
|
80
|
+
__logger_handlers is not None
|
|
81
|
+
), "You can only use this after running the default logging setup"
|
|
82
|
+
return __logger_handlers["debug_memory_handler"]
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def flush_debug_handler() -> str:
|
|
86
|
+
"""Writes the contents of the circular debug log buffer to disk and returns the written filename"""
|
|
87
|
+
handler = _get_debug_handler()
|
|
88
|
+
assert isinstance(
|
|
89
|
+
handler.target, TimedRotatingFileHandler
|
|
90
|
+
), "Circular memory handler doesn't have an appropriate fileHandler target"
|
|
91
|
+
handler.flush()
|
|
92
|
+
return handler.target.baseFilename
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _get_logging_dir() -> Path:
|
|
96
|
+
"""Get the path to write the mx_bluesky log files to.
|
|
97
|
+
|
|
98
|
+
Log location can be specified in the LOG_DIR environment variable, otherwise MX bluesky logs are written to 'dls_sw/ixx/logs/bluesky'.
|
|
99
|
+
This directory will be created if it is not found
|
|
100
|
+
|
|
101
|
+
Logs are written to ./tmp/logs/bluesky if BEAMLINE environment variable is not found
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
logging_path (Path): Path to the log file for the file handler to write to.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
logging_str = environ.get("LOG_DIR")
|
|
108
|
+
if logging_str:
|
|
109
|
+
logging_path = Path(logging_str)
|
|
110
|
+
else:
|
|
111
|
+
beamline = environ.get("BEAMLINE")
|
|
112
|
+
logging_path = (
|
|
113
|
+
Path(f"/dls_sw/{beamline}/logs/bluesky/")
|
|
114
|
+
if beamline
|
|
115
|
+
else Path("/tmp/logs/bluesky")
|
|
116
|
+
)
|
|
117
|
+
Path.mkdir(logging_path, exist_ok=True, parents=True)
|
|
118
|
+
return logging_path
|
|
@@ -8,8 +8,8 @@ from opentelemetry.sdk.trace import TracerProvider
|
|
|
8
8
|
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def setup_tracing():
|
|
12
|
-
resource = Resource(attributes={SERVICE_NAME:
|
|
11
|
+
def setup_tracing(service_name: str = "Hyperion"):
|
|
12
|
+
resource = Resource(attributes={SERVICE_NAME: service_name})
|
|
13
13
|
|
|
14
14
|
traceProvider = TracerProvider(resource=resource)
|
|
15
15
|
processor = BatchSpanProcessor(
|
mx_bluesky/hyperion/__main__.py
CHANGED
|
@@ -7,13 +7,18 @@ from queue import Queue
|
|
|
7
7
|
from traceback import format_exception
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
|
-
from blueapi.core import BlueskyContext
|
|
10
|
+
from blueapi.core import BlueskyContext
|
|
11
11
|
from bluesky.callbacks.zmq import Publisher
|
|
12
12
|
from bluesky.run_engine import RunEngine
|
|
13
|
+
from bluesky.utils import MsgGenerator
|
|
13
14
|
from flask import Flask, request
|
|
14
15
|
from flask_restful import Api, Resource
|
|
15
16
|
from pydantic.dataclasses import dataclass
|
|
16
17
|
|
|
18
|
+
from mx_bluesky.common.parameters.components import MxBlueskyParameters
|
|
19
|
+
from mx_bluesky.common.parameters.constants import Actions, Status
|
|
20
|
+
from mx_bluesky.common.utils.log import do_default_logging_setup, flush_debug_handler
|
|
21
|
+
from mx_bluesky.common.utils.tracing import TRACER
|
|
17
22
|
from mx_bluesky.hyperion.exceptions import WarningException
|
|
18
23
|
from mx_bluesky.hyperion.experiment_plans.experiment_registry import (
|
|
19
24
|
PLAN_REGISTRY,
|
|
@@ -36,13 +41,9 @@ from mx_bluesky.hyperion.external_interaction.callbacks.logging_callback import
|
|
|
36
41
|
)
|
|
37
42
|
from mx_bluesky.hyperion.log import (
|
|
38
43
|
LOGGER,
|
|
39
|
-
do_default_logging_setup,
|
|
40
|
-
flush_debug_handler,
|
|
41
44
|
)
|
|
42
45
|
from mx_bluesky.hyperion.parameters.cli import parse_cli_args
|
|
43
|
-
from mx_bluesky.hyperion.parameters.
|
|
44
|
-
from mx_bluesky.hyperion.parameters.constants import CONST, Actions, Status
|
|
45
|
-
from mx_bluesky.hyperion.tracing import TRACER
|
|
46
|
+
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
46
47
|
from mx_bluesky.hyperion.utils.context import setup_context
|
|
47
48
|
|
|
48
49
|
VERBOSE_EVENT_LOGGING: bool | None = None
|
|
@@ -53,7 +54,7 @@ class Command:
|
|
|
53
54
|
action: Actions
|
|
54
55
|
devices: Any | None = None
|
|
55
56
|
experiment: Callable[[Any, Any], MsgGenerator] | None = None
|
|
56
|
-
parameters:
|
|
57
|
+
parameters: MxBlueskyParameters | None = None
|
|
57
58
|
callbacks: CallbacksFactory | None = None
|
|
58
59
|
|
|
59
60
|
|
|
@@ -119,7 +120,7 @@ class BlueskyRunner:
|
|
|
119
120
|
def start(
|
|
120
121
|
self,
|
|
121
122
|
experiment: Callable,
|
|
122
|
-
parameters:
|
|
123
|
+
parameters: MxBlueskyParameters,
|
|
123
124
|
plan_name: str,
|
|
124
125
|
callbacks: CallbacksFactory | None,
|
|
125
126
|
) -> StatusAndMessage:
|
|
@@ -239,7 +240,7 @@ def compose_start_args(context: BlueskyContext, plan_name: str, action: Actions)
|
|
|
239
240
|
raise ValueError(f"Extra fields not allowed {parameters.model_extra}")
|
|
240
241
|
except Exception as e:
|
|
241
242
|
raise ValueError(
|
|
242
|
-
f"Supplied parameters don't match the plan for this endpoint {request.data}"
|
|
243
|
+
f"Supplied parameters don't match the plan for this endpoint {request.data}, for plan {plan_name}"
|
|
243
244
|
) from e
|
|
244
245
|
return plan, parameters, plan_name, callback_type
|
|
245
246
|
|
|
@@ -345,7 +346,9 @@ def create_app(
|
|
|
345
346
|
def create_targets():
|
|
346
347
|
hyperion_port = 5005
|
|
347
348
|
args = parse_cli_args()
|
|
348
|
-
do_default_logging_setup(
|
|
349
|
+
do_default_logging_setup(
|
|
350
|
+
CONST.LOG_FILE_NAME, CONST.GRAYLOG_PORT, dev_mode=args.dev_mode
|
|
351
|
+
)
|
|
349
352
|
if not args.use_external_callbacks:
|
|
350
353
|
setup_callback_logging(args.dev_mode)
|
|
351
354
|
app, runner = create_app(
|
|
@@ -4,7 +4,7 @@ import bluesky.plan_stubs as bps
|
|
|
4
4
|
from dodal.devices.focusing_mirror import (
|
|
5
5
|
FocusingMirrorWithStripes,
|
|
6
6
|
MirrorStripe,
|
|
7
|
-
|
|
7
|
+
MirrorVoltages,
|
|
8
8
|
)
|
|
9
9
|
from dodal.devices.undulator_dcm import UndulatorDCM
|
|
10
10
|
from dodal.devices.util.adjuster_plans import lookup_table_adjuster
|
|
@@ -13,79 +13,96 @@ from dodal.devices.util.lookup_tables import (
|
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
from mx_bluesky.hyperion.log import LOGGER
|
|
16
|
+
from mx_bluesky.hyperion.utils.utils import (
|
|
17
|
+
energy_to_bragg_angle,
|
|
18
|
+
)
|
|
16
19
|
|
|
17
20
|
MIRROR_VOLTAGE_GROUP = "MIRROR_VOLTAGE_GROUP"
|
|
18
21
|
DCM_GROUP = "DCM_GROUP"
|
|
22
|
+
YAW_LAT_TIMEOUT_S = 30
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
def _apply_and_wait_for_voltages_to_settle(
|
|
22
26
|
stripe: MirrorStripe,
|
|
23
|
-
|
|
24
|
-
mirror_voltages: VFMMirrorVoltages,
|
|
27
|
+
mirror_voltages: MirrorVoltages,
|
|
25
28
|
):
|
|
26
29
|
with open(mirror_voltages.voltage_lookup_table_path) as lut_file:
|
|
27
30
|
json_obj = json.load(lut_file)
|
|
28
31
|
|
|
29
32
|
# sample mode is the only mode supported
|
|
30
33
|
sample_data = json_obj["sample"]
|
|
31
|
-
mirror_key = mirror.name.lower()
|
|
32
34
|
if stripe == MirrorStripe.BARE:
|
|
33
35
|
stripe_key = "bare"
|
|
34
36
|
elif stripe == MirrorStripe.RHODIUM:
|
|
35
37
|
stripe_key = "rh"
|
|
36
38
|
elif stripe == MirrorStripe.PLATINUM:
|
|
37
39
|
stripe_key = "pt"
|
|
38
|
-
else:
|
|
39
|
-
raise ValueError(f"Unsupported stripe '{stripe}'")
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
mirror_voltages.
|
|
44
|
-
):
|
|
45
|
-
|
|
46
|
-
f"Applying and waiting for voltage {voltage_channel.name} = {required_voltage}"
|
|
47
|
-
)
|
|
48
|
-
yield from bps.abs_set(
|
|
49
|
-
voltage_channel, required_voltage, group=MIRROR_VOLTAGE_GROUP
|
|
50
|
-
)
|
|
41
|
+
for mirror_key, channels in {
|
|
42
|
+
"hfm": mirror_voltages.horizontal_voltages,
|
|
43
|
+
"vfm": mirror_voltages.vertical_voltages,
|
|
44
|
+
}.items():
|
|
45
|
+
required_voltages = sample_data[stripe_key][mirror_key]
|
|
51
46
|
|
|
52
|
-
|
|
47
|
+
for voltage_channel, required_voltage in zip(
|
|
48
|
+
channels.values(), required_voltages, strict=True
|
|
49
|
+
):
|
|
50
|
+
LOGGER.info(
|
|
51
|
+
f"Applying and waiting for voltage {voltage_channel.name} = {required_voltage}"
|
|
52
|
+
)
|
|
53
|
+
yield from bps.abs_set(
|
|
54
|
+
voltage_channel, required_voltage, group=MIRROR_VOLTAGE_GROUP, wait=True
|
|
55
|
+
)
|
|
53
56
|
|
|
54
57
|
|
|
55
58
|
def adjust_mirror_stripe(
|
|
56
|
-
energy_kev, mirror: FocusingMirrorWithStripes, mirror_voltages:
|
|
59
|
+
energy_kev, mirror: FocusingMirrorWithStripes, mirror_voltages: MirrorVoltages
|
|
57
60
|
):
|
|
58
61
|
"""Feedback should be OFF prior to entry, in order to prevent
|
|
59
62
|
feedback from making unnecessary corrections while beam is being adjusted."""
|
|
60
|
-
|
|
63
|
+
mirror_config = mirror.energy_to_stripe(energy_kev)
|
|
61
64
|
|
|
62
65
|
LOGGER.info(
|
|
63
|
-
f"Adjusting mirror stripe for {energy_kev}keV selecting {stripe} stripe"
|
|
66
|
+
f"Adjusting mirror stripe for {energy_kev}keV selecting {mirror_config['stripe']} stripe"
|
|
64
67
|
)
|
|
65
|
-
yield from bps.abs_set(mirror.stripe, stripe, wait=True)
|
|
68
|
+
yield from bps.abs_set(mirror.stripe, mirror_config["stripe"], wait=True)
|
|
66
69
|
yield from bps.trigger(mirror.apply_stripe)
|
|
67
70
|
|
|
71
|
+
# yaw, lat cannot be done simultaneously
|
|
72
|
+
LOGGER.info(f"Adjusting {mirror.name} lat to {mirror_config['lat_mm']}")
|
|
73
|
+
yield from bps.abs_set(
|
|
74
|
+
mirror.x_mm, mirror_config["lat_mm"], wait=True, timeout=YAW_LAT_TIMEOUT_S
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
LOGGER.info(f"Adjusting {mirror.name} yaw to {mirror_config['yaw_mrad']}")
|
|
78
|
+
yield from bps.abs_set(
|
|
79
|
+
mirror.yaw_mrad, mirror_config["yaw_mrad"], wait=True, timeout=YAW_LAT_TIMEOUT_S
|
|
80
|
+
)
|
|
81
|
+
|
|
68
82
|
LOGGER.info("Adjusting mirror voltages...")
|
|
69
|
-
yield from _apply_and_wait_for_voltages_to_settle(
|
|
83
|
+
yield from _apply_and_wait_for_voltages_to_settle(
|
|
84
|
+
mirror_config["stripe"], mirror_voltages
|
|
85
|
+
)
|
|
70
86
|
|
|
71
87
|
|
|
72
88
|
def adjust_dcm_pitch_roll_vfm_from_lut(
|
|
73
89
|
undulator_dcm: UndulatorDCM,
|
|
74
90
|
vfm: FocusingMirrorWithStripes,
|
|
75
|
-
|
|
91
|
+
mirror_voltages: MirrorVoltages,
|
|
76
92
|
energy_kev,
|
|
77
93
|
):
|
|
78
94
|
"""Beamline energy-change post-adjustments : Adjust DCM and VFM directly from lookup tables.
|
|
79
|
-
Lookups are performed against the Bragg angle which
|
|
80
|
-
|
|
95
|
+
Lookups are performed against the Bragg angle which is computed directly from the target energy
|
|
96
|
+
rather than waiting for the EPICS controls PV to reach it.
|
|
81
97
|
Feedback should be OFF prior to entry, in order to prevent
|
|
82
98
|
feedback from making unnecessary corrections while beam is being adjusted."""
|
|
83
99
|
|
|
84
|
-
# DCM Pitch
|
|
100
|
+
# Adjust DCM Pitch
|
|
85
101
|
dcm = undulator_dcm.dcm
|
|
86
102
|
LOGGER.info(f"Adjusting DCM and VFM for {energy_kev} keV")
|
|
87
|
-
|
|
88
|
-
|
|
103
|
+
d_spacing_a: float = yield from bps.rd(undulator_dcm.dcm.crystal_metadata_d_spacing)
|
|
104
|
+
bragg_deg = energy_to_bragg_angle(energy_kev, d_spacing_a)
|
|
105
|
+
LOGGER.info(f"Target Bragg angle = {bragg_deg} degrees")
|
|
89
106
|
dcm_pitch_adjuster = lookup_table_adjuster(
|
|
90
107
|
linear_interpolation_lut(undulator_dcm.pitch_energy_table_path),
|
|
91
108
|
dcm.pitch_in_mrad,
|
|
@@ -104,31 +121,9 @@ def adjust_dcm_pitch_roll_vfm_from_lut(
|
|
|
104
121
|
yield from dcm_roll_adjuster(DCM_GROUP)
|
|
105
122
|
LOGGER.info("Waiting for DCM roll adjust to complete...")
|
|
106
123
|
|
|
107
|
-
# DCM Perp pitch
|
|
108
|
-
offset_mm = undulator_dcm.dcm_fixed_offset_mm
|
|
109
|
-
LOGGER.info(f"Adjusting DCM offset to {offset_mm} mm")
|
|
110
|
-
yield from bps.abs_set(dcm.offset_in_mm, offset_mm, group=DCM_GROUP)
|
|
111
|
-
|
|
112
124
|
#
|
|
113
|
-
# Adjust
|
|
125
|
+
# Adjust vfm mirror stripe and mirror voltages
|
|
114
126
|
#
|
|
115
127
|
|
|
116
|
-
# No need to change HFM
|
|
117
|
-
|
|
118
|
-
# Assumption is focus mode is already set to "sample"
|
|
119
|
-
# not sure how we check this
|
|
120
|
-
|
|
121
128
|
# VFM Stripe selection
|
|
122
|
-
yield from adjust_mirror_stripe(energy_kev, vfm,
|
|
123
|
-
yield from bps.wait(DCM_GROUP)
|
|
124
|
-
|
|
125
|
-
# VFM Adjust - for I03 this table always returns the same value
|
|
126
|
-
vfm_lut = vfm.bragg_to_lat_lookup_table_path
|
|
127
|
-
assert vfm_lut is not None
|
|
128
|
-
vfm_x_adjuster = lookup_table_adjuster(
|
|
129
|
-
linear_interpolation_lut(vfm_lut),
|
|
130
|
-
vfm.x_mm,
|
|
131
|
-
bragg_deg,
|
|
132
|
-
)
|
|
133
|
-
LOGGER.info("Waiting for VFM Lat (Horizontal Translation) to complete...")
|
|
134
|
-
yield from vfm_x_adjuster()
|
|
129
|
+
yield from adjust_mirror_stripe(energy_kev, vfm, mirror_voltages)
|
|
@@ -6,7 +6,6 @@ from dodal.devices.attenuator import Attenuator
|
|
|
6
6
|
from dodal.devices.dcm import DCM
|
|
7
7
|
from dodal.devices.eiger import EigerDetector
|
|
8
8
|
from dodal.devices.flux import Flux
|
|
9
|
-
from dodal.devices.robot import BartRobot
|
|
10
9
|
from dodal.devices.s4_slit_gaps import S4SlitGaps
|
|
11
10
|
from dodal.devices.smargon import Smargon
|
|
12
11
|
from dodal.devices.synchrotron import Synchrotron
|
|
@@ -20,7 +19,7 @@ def read_hardware_pre_collection(
|
|
|
20
19
|
undulator: Undulator,
|
|
21
20
|
synchrotron: Synchrotron,
|
|
22
21
|
s4_slit_gaps: S4SlitGaps,
|
|
23
|
-
|
|
22
|
+
dcm: DCM,
|
|
24
23
|
smargon: Smargon,
|
|
25
24
|
):
|
|
26
25
|
LOGGER.info("Reading status of beamline for callbacks, pre collection.")
|
|
@@ -29,11 +28,12 @@ def read_hardware_pre_collection(
|
|
|
29
28
|
) # gives name to event *descriptor* document
|
|
30
29
|
yield from bps.read(undulator.current_gap)
|
|
31
30
|
yield from bps.read(synchrotron.synchrotron_mode)
|
|
32
|
-
yield from bps.read(s4_slit_gaps.xgap)
|
|
33
|
-
yield from bps.read(s4_slit_gaps.ygap)
|
|
31
|
+
yield from bps.read(s4_slit_gaps.xgap) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
32
|
+
yield from bps.read(s4_slit_gaps.ygap) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
34
33
|
yield from bps.read(smargon.x)
|
|
35
34
|
yield from bps.read(smargon.y)
|
|
36
35
|
yield from bps.read(smargon.z)
|
|
36
|
+
yield from bps.read(dcm.energy_in_kev)
|
|
37
37
|
yield from bps.save()
|
|
38
38
|
|
|
39
39
|
|
|
@@ -48,13 +48,7 @@ def read_hardware_during_collection(
|
|
|
48
48
|
yield from bps.create(name=CONST.DESCRIPTORS.HARDWARE_READ_DURING)
|
|
49
49
|
yield from bps.read(aperture_scatterguard)
|
|
50
50
|
yield from bps.read(attenuator.actual_transmission)
|
|
51
|
-
yield from bps.read(flux.flux_reading)
|
|
51
|
+
yield from bps.read(flux.flux_reading) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
52
52
|
yield from bps.read(dcm.energy_in_kev)
|
|
53
|
-
yield from bps.read(detector.bit_depth)
|
|
54
|
-
yield from bps.save()
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def read_hardware_for_zocalo(detector: EigerDetector):
|
|
58
|
-
yield from bps.create(name=CONST.DESCRIPTORS.ZOCALO_HW_READ)
|
|
59
|
-
yield from bps.read(detector.odin.file_writer.id)
|
|
53
|
+
yield from bps.read(detector.bit_depth) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
60
54
|
yield from bps.save()
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
from functools import partial
|
|
2
2
|
|
|
3
3
|
import bluesky.plan_stubs as bps
|
|
4
|
+
from dodal.devices.areadetector.plugins.CAM import ColorMode
|
|
4
5
|
from dodal.devices.oav.oav_detector import OAV
|
|
5
|
-
from dodal.devices.oav.oav_errors import OAVError_ZoomLevelNotFound
|
|
6
6
|
from dodal.devices.oav.oav_parameters import OAVParameters
|
|
7
7
|
from dodal.devices.oav.pin_image_recognition import PinTipDetection
|
|
8
|
-
from dodal.devices.oav.utils import ColorMode
|
|
9
8
|
|
|
10
9
|
from mx_bluesky.hyperion.parameters.constants import CONST
|
|
11
10
|
|
|
@@ -56,19 +55,14 @@ def setup_pin_tip_detection_params(
|
|
|
56
55
|
|
|
57
56
|
|
|
58
57
|
def setup_general_oav_params(oav: OAV, parameters: OAVParameters):
|
|
59
|
-
yield from set_using_group(oav.cam.color_mode, ColorMode.RGB1)
|
|
60
|
-
yield from set_using_group(oav.cam.acquire_period, parameters.acquire_period)
|
|
61
|
-
yield from set_using_group(oav.cam.acquire_time, parameters.exposure)
|
|
62
|
-
yield from set_using_group(oav.cam.gain, parameters.gain)
|
|
58
|
+
yield from set_using_group(oav.cam.color_mode, ColorMode.RGB1) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
59
|
+
yield from set_using_group(oav.cam.acquire_period, parameters.acquire_period) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
60
|
+
yield from set_using_group(oav.cam.acquire_time, parameters.exposure) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
61
|
+
yield from set_using_group(oav.cam.gain, parameters.gain) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
63
62
|
|
|
64
63
|
zoom_level_str = f"{float(parameters.zoom)}x"
|
|
65
|
-
if zoom_level_str not in oav.zoom_controller.allowed_zoom_levels:
|
|
66
|
-
raise OAVError_ZoomLevelNotFound(
|
|
67
|
-
f"Found {zoom_level_str} as a zoom level but expected one of {oav.zoom_controller.allowed_zoom_levels}"
|
|
68
|
-
)
|
|
69
|
-
|
|
70
64
|
yield from bps.abs_set(
|
|
71
|
-
oav.zoom_controller,
|
|
65
|
+
oav.zoom_controller, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
72
66
|
zoom_level_str,
|
|
73
67
|
wait=True,
|
|
74
68
|
)
|
|
@@ -4,7 +4,7 @@ from importlib import resources
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
6
|
import bluesky.plan_stubs as bps
|
|
7
|
-
from
|
|
7
|
+
from bluesky.utils import MsgGenerator
|
|
8
8
|
from dodal.common.beamlines.beamline_utils import get_path_provider
|
|
9
9
|
from dodal.devices.fast_grid_scan import PandAGridScanParams
|
|
10
10
|
from ophyd_async.core import load_device
|
|
@@ -20,6 +20,7 @@ from mx_bluesky.hyperion.log import LOGGER
|
|
|
20
20
|
MM_TO_ENCODER_COUNTS = 200000
|
|
21
21
|
GENERAL_TIMEOUT = 60
|
|
22
22
|
TICKS_PER_MS = 1000 # Panda sequencer prescaler will be set to us
|
|
23
|
+
PULSE_WIDTH_US = 50
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class Enabled(Enum):
|
|
@@ -62,12 +63,12 @@ def _get_seq_table(
|
|
|
62
63
|
An instance of SeqTable describing the panda sequencer table
|
|
63
64
|
"""
|
|
64
65
|
|
|
65
|
-
start_of_grid_x_counts = int(parameters.
|
|
66
|
+
start_of_grid_x_counts = int(parameters.x_start_mm * MM_TO_ENCODER_COUNTS)
|
|
66
67
|
|
|
67
68
|
# x_start is the first trigger point, so we need to travel to x_steps-1 for the final trigger point
|
|
68
69
|
end_of_grid_x_counts = int(
|
|
69
70
|
start_of_grid_x_counts
|
|
70
|
-
+ (parameters.
|
|
71
|
+
+ (parameters.x_step_size_mm * (parameters.x_steps - 1) * MM_TO_ENCODER_COUNTS)
|
|
71
72
|
)
|
|
72
73
|
|
|
73
74
|
exposure_distance_x_counts = int(exposure_distance_mm * MM_TO_ENCODER_COUNTS)
|
|
@@ -76,8 +77,6 @@ def _get_seq_table(
|
|
|
76
77
|
|
|
77
78
|
delay_between_pulses = time_between_steps_ms * TICKS_PER_MS
|
|
78
79
|
|
|
79
|
-
PULSE_WIDTH_US = 1
|
|
80
|
-
|
|
81
80
|
assert delay_between_pulses > PULSE_WIDTH_US
|
|
82
81
|
|
|
83
82
|
# BITA_1 trigger wired from TTLIN1, this is the trigger input
|
|
@@ -141,7 +140,7 @@ def setup_panda_for_flyscan(
|
|
|
141
140
|
"""
|
|
142
141
|
assert parameters.x_steps > 0
|
|
143
142
|
assert time_between_x_steps_ms * 1000 >= exposure_time_s
|
|
144
|
-
assert sample_velocity_mm_per_s * exposure_time_s < parameters.
|
|
143
|
+
assert sample_velocity_mm_per_s * exposure_time_s < parameters.x_step_size_mm
|
|
145
144
|
|
|
146
145
|
yield from bps.stage(panda, group="panda-config")
|
|
147
146
|
|
|
@@ -3,16 +3,18 @@ from functools import wraps
|
|
|
3
3
|
|
|
4
4
|
import bluesky.plan_stubs as bps
|
|
5
5
|
import bluesky.preprocessors as bpp
|
|
6
|
-
from
|
|
6
|
+
from bluesky.utils import MsgGenerator
|
|
7
7
|
from dodal.devices.zebra import (
|
|
8
8
|
AUTO_SHUTTER_GATE,
|
|
9
|
-
|
|
9
|
+
AUTO_SHUTTER_INPUT_1,
|
|
10
|
+
AUTO_SHUTTER_INPUT_2,
|
|
10
11
|
DISCONNECT,
|
|
11
12
|
IN1_TTL,
|
|
12
13
|
IN3_TTL,
|
|
13
14
|
IN4_TTL,
|
|
14
15
|
PC_GATE,
|
|
15
16
|
PC_PULSE,
|
|
17
|
+
SOFT_IN1,
|
|
16
18
|
TTL_DETECTOR,
|
|
17
19
|
TTL_PANDA,
|
|
18
20
|
TTL_XSPRESS3,
|
|
@@ -55,7 +57,7 @@ def bluesky_retry(func: Callable):
|
|
|
55
57
|
|
|
56
58
|
|
|
57
59
|
def arm_zebra(zebra: Zebra):
|
|
58
|
-
yield from bps.abs_set(zebra.pc.arm, ArmDemand.ARM, wait=True)
|
|
60
|
+
yield from bps.abs_set(zebra.pc.arm, ArmDemand.ARM, wait=True) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
59
61
|
|
|
60
62
|
|
|
61
63
|
def tidy_up_zebra_after_rotation_scan(
|
|
@@ -64,7 +66,7 @@ def tidy_up_zebra_after_rotation_scan(
|
|
|
64
66
|
group="tidy_up_zebra_after_rotation",
|
|
65
67
|
wait=True,
|
|
66
68
|
):
|
|
67
|
-
yield from bps.abs_set(zebra.pc.arm, ArmDemand.DISARM, group=group)
|
|
69
|
+
yield from bps.abs_set(zebra.pc.arm, ArmDemand.DISARM, group=group) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
68
70
|
yield from bps.abs_set(
|
|
69
71
|
zebra_shutter.control_mode, ZebraShutterControl.MANUAL, group=group
|
|
70
72
|
)
|
|
@@ -73,15 +75,45 @@ def tidy_up_zebra_after_rotation_scan(
|
|
|
73
75
|
|
|
74
76
|
|
|
75
77
|
def set_shutter_auto_input(zebra: Zebra, input: int, group="set_shutter_trigger"):
|
|
76
|
-
"""Set the
|
|
78
|
+
"""Set the signal that controls the shutter. We use the second input to the
|
|
79
|
+
Zebra's AND2 gate for this input. ZebraShutter control mode must be in auto for this input to take control
|
|
77
80
|
|
|
78
81
|
For more details see the ZebraShutter device."""
|
|
79
82
|
auto_shutter_control = zebra.logic_gates.and_gates[AUTO_SHUTTER_GATE]
|
|
80
83
|
yield from bps.abs_set(
|
|
81
|
-
auto_shutter_control.sources[
|
|
84
|
+
auto_shutter_control.sources[AUTO_SHUTTER_INPUT_2], input, group
|
|
82
85
|
)
|
|
83
86
|
|
|
84
87
|
|
|
88
|
+
def configure_zebra_and_shutter_for_auto_shutter(
|
|
89
|
+
zebra: Zebra, zebra_shutter: ZebraShutter, input: int, group="use_automatic_shutter"
|
|
90
|
+
):
|
|
91
|
+
"""Set the shutter to auto mode, and configure the zebra to trigger the shutter on
|
|
92
|
+
an input source. For the input, use one of the source constants in zebra.py
|
|
93
|
+
|
|
94
|
+
When the shutter is in auto/manual, logic in EPICS sets the Zebra's
|
|
95
|
+
SOFT_IN1 to low/high respectively. The Zebra's AND2 gate should be used to control the shutter while in auto mode.
|
|
96
|
+
To do this, we need (AND2 = SOFT_IN1 AND input), where input is the zebra signal we want to control the shutter when in auto mode.
|
|
97
|
+
"""
|
|
98
|
+
# See https://github.com/DiamondLightSource/dodal/issues/813 for better typing here.
|
|
99
|
+
|
|
100
|
+
# Set shutter to auto mode
|
|
101
|
+
yield from bps.abs_set(
|
|
102
|
+
zebra_shutter.control_mode, ZebraShutterControl.AUTO, group=group
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Set first input of AND2 gate to SOFT_IN1, which is high when shutter is in auto mode
|
|
106
|
+
# Note the Zebra should ALWAYS be setup this way. See https://github.com/DiamondLightSource/mx-bluesky/issues/551
|
|
107
|
+
yield from bps.abs_set(
|
|
108
|
+
zebra.logic_gates.and_gates[AUTO_SHUTTER_GATE].sources[AUTO_SHUTTER_INPUT_1],
|
|
109
|
+
SOFT_IN1,
|
|
110
|
+
group=group,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Set the second input of AND2 gate to the requested zebra input source
|
|
114
|
+
yield from set_shutter_auto_input(zebra, input, group=group)
|
|
115
|
+
|
|
116
|
+
|
|
85
117
|
@bluesky_retry
|
|
86
118
|
def setup_zebra_for_rotation(
|
|
87
119
|
zebra: Zebra,
|
|
@@ -137,11 +169,10 @@ def setup_zebra_for_rotation(
|
|
|
137
169
|
yield from bps.abs_set(zebra.pc.pulse_start, abs(shutter_opening_s), group=group)
|
|
138
170
|
# Set gate position to be angle of interest
|
|
139
171
|
yield from bps.abs_set(zebra.pc.gate_trigger, axis.value, group=group)
|
|
140
|
-
#
|
|
141
|
-
yield from
|
|
142
|
-
zebra_shutter
|
|
172
|
+
# Set shutter to automatic and to trigger via PC_GATE
|
|
173
|
+
yield from configure_zebra_and_shutter_for_auto_shutter(
|
|
174
|
+
zebra, zebra_shutter, PC_GATE, group=group
|
|
143
175
|
)
|
|
144
|
-
yield from set_shutter_auto_input(zebra, PC_GATE, group=group)
|
|
145
176
|
# Trigger the detector with a pulse
|
|
146
177
|
yield from bps.abs_set(zebra.output.out_pvs[TTL_DETECTOR], PC_PULSE, group=group)
|
|
147
178
|
# Don't use the fluorescence detector
|
|
@@ -159,11 +190,12 @@ def setup_zebra_for_gridscan(
|
|
|
159
190
|
group="setup_zebra_for_gridscan",
|
|
160
191
|
wait=True,
|
|
161
192
|
):
|
|
162
|
-
|
|
163
|
-
yield from
|
|
164
|
-
zebra_shutter
|
|
193
|
+
# Set shutter to automatic and to trigger via motion controller GPIO signal (IN4_TTL)
|
|
194
|
+
yield from configure_zebra_and_shutter_for_auto_shutter(
|
|
195
|
+
zebra, zebra_shutter, IN4_TTL, group=group
|
|
165
196
|
)
|
|
166
|
-
|
|
197
|
+
|
|
198
|
+
yield from bps.abs_set(zebra.output.out_pvs[TTL_DETECTOR], IN3_TTL, group=group)
|
|
167
199
|
yield from bps.abs_set(zebra.output.out_pvs[TTL_XSPRESS3], DISCONNECT, group=group)
|
|
168
200
|
yield from bps.abs_set(zebra.output.pulse_1.input, DISCONNECT, group=group)
|
|
169
201
|
|
|
@@ -198,11 +230,10 @@ def setup_zebra_for_panda_flyscan(
|
|
|
198
230
|
# Forwards eiger trigger signal from panda
|
|
199
231
|
yield from bps.abs_set(zebra.output.out_pvs[TTL_DETECTOR], IN1_TTL, group=group)
|
|
200
232
|
|
|
201
|
-
#
|
|
202
|
-
yield from
|
|
203
|
-
zebra_shutter
|
|
233
|
+
# Set shutter to automatic and to trigger via motion controller GPIO signal (IN4_TTL)
|
|
234
|
+
yield from configure_zebra_and_shutter_for_auto_shutter(
|
|
235
|
+
zebra, zebra_shutter, IN4_TTL, group=group
|
|
204
236
|
)
|
|
205
|
-
yield from set_shutter_auto_input(zebra, IN4_TTL, group=group)
|
|
206
237
|
|
|
207
238
|
yield from bps.abs_set(zebra.output.out_pvs[TTL_XSPRESS3], DISCONNECT, group=group)
|
|
208
239
|
|
|
@@ -2,24 +2,24 @@ import numpy as np
|
|
|
2
2
|
from bluesky import plan_stubs as bps
|
|
3
3
|
from dodal.devices.smargon import Smargon
|
|
4
4
|
|
|
5
|
-
from mx_bluesky.hyperion.exceptions import
|
|
5
|
+
from mx_bluesky.hyperion.exceptions import SampleException
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def move_smargon_warn_on_out_of_range(
|
|
9
9
|
smargon: Smargon, position: np.ndarray | list[float] | tuple[float, float, float]
|
|
10
10
|
):
|
|
11
|
-
"""Throws a
|
|
11
|
+
"""Throws a SampleException if the specified position is out of range for the
|
|
12
12
|
smargon. Otherwise moves to that position."""
|
|
13
13
|
limits = yield from smargon.get_xyz_limits()
|
|
14
14
|
if not limits.position_valid(position):
|
|
15
|
-
raise
|
|
15
|
+
raise SampleException(
|
|
16
16
|
"Pin tip centring failed - pin too long/short/bent and out of range"
|
|
17
17
|
)
|
|
18
18
|
yield from bps.mv(
|
|
19
|
-
smargon.x,
|
|
20
|
-
position[0],
|
|
21
|
-
smargon.y,
|
|
22
|
-
position[1],
|
|
23
|
-
smargon.z,
|
|
24
|
-
position[2],
|
|
19
|
+
smargon.x, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
20
|
+
position[0], # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
21
|
+
smargon.y, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
22
|
+
position[1], # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
23
|
+
smargon.z, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
24
|
+
position[2], # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
|
|
25
25
|
)
|