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.
Files changed (121) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/__init__.py +0 -0
  3. mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/robot_load_plan.py +198 -0
  4. mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py +2 -2
  5. mx_bluesky/beamlines/aithre_lasershaping/parameters/__init__.py +0 -0
  6. mx_bluesky/beamlines/aithre_lasershaping/parameters/constants.py +17 -0
  7. mx_bluesky/beamlines/aithre_lasershaping/parameters/robot_load_parameters.py +13 -0
  8. mx_bluesky/beamlines/aithre_lasershaping/pin_tip_centring.py +31 -0
  9. mx_bluesky/beamlines/aithre_lasershaping/robot_load.py +80 -0
  10. mx_bluesky/beamlines/i02_1/parameters/gridscan.py +1 -1
  11. mx_bluesky/beamlines/i04/__init__.py +6 -2
  12. mx_bluesky/beamlines/i04/callbacks/murko_callback.py +27 -12
  13. mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +94 -20
  14. mx_bluesky/beamlines/i04/external_interaction/__init__.py +0 -0
  15. mx_bluesky/beamlines/i04/external_interaction/config_server.py +15 -0
  16. mx_bluesky/beamlines/i04/oav_centering_plans/__init__.py +0 -0
  17. mx_bluesky/beamlines/i04/oav_centering_plans/oav_imaging.py +115 -0
  18. mx_bluesky/beamlines/i04/parameters/__init__.py +0 -0
  19. mx_bluesky/beamlines/i04/parameters/constants.py +21 -0
  20. mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +24 -1
  21. mx_bluesky/beamlines/i04/thawing_plan.py +149 -154
  22. mx_bluesky/beamlines/i24/jungfrau_commissioning/experiment_plans/do_darks.py +55 -10
  23. mx_bluesky/beamlines/i24/jungfrau_commissioning/plan_stubs/do_external_acquisition.py +1 -1
  24. mx_bluesky/beamlines/i24/jungfrau_commissioning/plan_stubs/plan_utils.py +1 -1
  25. mx_bluesky/beamlines/i24/serial/__init__.py +7 -5
  26. mx_bluesky/beamlines/i24/serial/dcid.py +6 -7
  27. mx_bluesky/beamlines/i24/serial/extruder/{i24ssx_Extruder_Collect_py3v2.py → i24ssx_extruder_collect_py3v2.py} +70 -37
  28. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/CustomChip_py3v1.edl +11 -11
  29. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DetStage.edl +3 -3
  30. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +142 -142
  31. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/MappingLite-oxford_py3v1.edl +135 -135
  32. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/PMAC_Command.edl +8 -8
  33. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +13 -13
  34. mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_Collect_py3v1.py → i24ssx_chip_collect_py3v1.py} +12 -9
  35. mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_Manager_py3v1.py → i24ssx_chip_manager_py3v1.py} +81 -78
  36. mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_StartUp_py3v1.py → i24ssx_chip_startup_py3v1.py} +3 -3
  37. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +33 -33
  38. mx_bluesky/beamlines/i24/serial/log.py +11 -11
  39. mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +3 -3
  40. mx_bluesky/beamlines/i24/serial/parameters/utils.py +5 -5
  41. mx_bluesky/beamlines/i24/serial/setup_beamline/ca.py +0 -12
  42. mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +122 -334
  43. mx_bluesky/beamlines/i24/serial/setup_beamline/pv_abstract.py +5 -5
  44. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +30 -251
  45. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +3 -3
  46. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +4 -4
  47. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +103 -16
  48. mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py +64 -0
  49. mx_bluesky/beamlines/i24/serial/write_nexus.py +4 -4
  50. mx_bluesky/common/device_setup_plans/gonio.py +28 -0
  51. mx_bluesky/common/device_setup_plans/manipulate_sample.py +8 -1
  52. mx_bluesky/common/device_setup_plans/robot_load_unload.py +1 -1
  53. mx_bluesky/common/device_setup_plans/setup_oav.py +8 -0
  54. mx_bluesky/common/device_setup_plans/setup_zebra_and_shutter.py +0 -5
  55. mx_bluesky/common/device_setup_plans/xbpm_feedback.py +8 -1
  56. mx_bluesky/common/experiment_plans/beamstop_check.py +229 -0
  57. mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py +8 -6
  58. mx_bluesky/common/experiment_plans/common_grid_detect_then_xray_centre_plan.py +2 -2
  59. mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py +1 -1
  60. mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py +7 -4
  61. mx_bluesky/common/experiment_plans/inner_plans/write_sample_status.py +2 -2
  62. mx_bluesky/common/experiment_plans/oav_snapshot_plan.py +1 -2
  63. mx_bluesky/{hyperion → common}/experiment_plans/pin_tip_centring_plan.py +23 -24
  64. mx_bluesky/common/external_interaction/callbacks/common/grid_detection_callback.py +5 -0
  65. mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +13 -15
  66. mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +3 -5
  67. mx_bluesky/common/external_interaction/callbacks/common/plan_reactive_callback.py +1 -1
  68. mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py +2 -2
  69. mx_bluesky/common/external_interaction/callbacks/sample_handling/sample_handling_callback.py +3 -3
  70. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +12 -10
  71. mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py +2 -2
  72. mx_bluesky/common/external_interaction/config_server.py +4 -4
  73. mx_bluesky/common/external_interaction/ispyb/data_model.py +11 -4
  74. mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +163 -4
  75. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +76 -167
  76. mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py +0 -14
  77. mx_bluesky/common/external_interaction/nexus/nexus_utils.py +2 -2
  78. mx_bluesky/common/external_interaction/nexus/write_nexus.py +3 -3
  79. mx_bluesky/common/parameters/components.py +1 -0
  80. mx_bluesky/common/parameters/constants.py +4 -3
  81. mx_bluesky/common/parameters/device_composites.py +4 -2
  82. mx_bluesky/common/parameters/gridscan.py +2 -2
  83. mx_bluesky/common/utils/exceptions.py +24 -7
  84. mx_bluesky/common/utils/log.py +13 -4
  85. mx_bluesky/common/utils/tracing.py +5 -5
  86. mx_bluesky/common/utils/utils.py +56 -8
  87. mx_bluesky/hyperion/__main__.py +6 -16
  88. mx_bluesky/hyperion/baton_handler.py +38 -14
  89. mx_bluesky/hyperion/device_setup_plans/utils.py +1 -1
  90. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +1 -1
  91. mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +15 -13
  92. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +2 -2
  93. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +9 -9
  94. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +7 -8
  95. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +3 -10
  96. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +4 -2
  97. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +10 -4
  98. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -2
  99. mx_bluesky/hyperion/experiment_plans/udc_default_state.py +160 -0
  100. mx_bluesky/hyperion/external_interaction/agamemnon.py +3 -3
  101. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +2 -2
  102. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +3 -3
  103. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +1 -0
  104. mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +3 -6
  105. mx_bluesky/hyperion/external_interaction/config_server.py +5 -5
  106. mx_bluesky/hyperion/parameters/constants.py +11 -4
  107. mx_bluesky/hyperion/parameters/device_composites.py +2 -2
  108. mx_bluesky/hyperion/parameters/gridscan.py +4 -4
  109. mx_bluesky/hyperion/parameters/robot_load.py +1 -9
  110. mx_bluesky/hyperion/plan_runner.py +6 -6
  111. mx_bluesky/hyperion/runner.py +10 -8
  112. mx_bluesky/jupyter_example.ipynb +3 -3
  113. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/METADATA +9 -7
  114. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/RECORD +118 -104
  115. mx_bluesky/common/experiment_plans/inner_plans/udc_default_state.py +0 -65
  116. mx_bluesky/common/external_interaction/callbacks/common/logging_callback.py +0 -29
  117. mx_bluesky/hyperion/device_setup_plans/smargon.py +0 -25
  118. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/WHEEL +0 -0
  119. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/entry_points.txt +0 -0
  120. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/licenses/LICENSE +0 -0
  121. {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 reponse from server
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.pv.filenameRBV)
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.pv.bit_depth))
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 reponse from server
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.trigger(robot.unload, wait=True)
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, attenuator: BinaryFilterAttenuator
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
- CrystalNotFoundException,
41
- SampleException,
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 construct_beamline_specific_FGS_features(
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 CrystalNotFoundException()
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 SampleException(
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.FGS_params
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
- setup_beamline_for_OAV,
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 setup_beamline_for_OAV(
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 RE is subscribed to ZocaloCallback
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 Undulator
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: 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.energy_in_kev,
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.energy_in_kev,
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 SampleException
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 SampleException
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 setup_beamline_for_OAV(
29
+ def setup_beamline_for_oav(
31
30
  smargon: Smargon,
32
31
  backlight: Backlight,
33
32
  aperture_scatterguard: ApertureScatterguard,