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.
Files changed (105) hide show
  1. mx_bluesky/__init__.py +8 -3
  2. mx_bluesky/__main__.py +12 -7
  3. mx_bluesky/_version.py +2 -2
  4. mx_bluesky/beamlines/i04/callbacks/murko_callback.py +14 -4
  5. mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +178 -0
  6. mx_bluesky/beamlines/i04/thawing_plan.py +49 -11
  7. mx_bluesky/beamlines/i24/serial/__init__.py +3 -0
  8. mx_bluesky/beamlines/i24/serial/dcid.py +143 -171
  9. mx_bluesky/beamlines/i24/serial/extruder/EX-gui-edm/DiamondExtruder-I24-py3v1.edl +1 -1
  10. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +121 -110
  11. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +3 -6
  12. mx_bluesky/beamlines/i24/serial/fixed_target/ft_utils.py +0 -1
  13. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +164 -169
  14. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +149 -225
  15. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +7 -216
  16. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +18 -17
  17. mx_bluesky/beamlines/i24/serial/log.py +58 -49
  18. mx_bluesky/beamlines/i24/serial/parameters/__init__.py +4 -0
  19. mx_bluesky/beamlines/i24/serial/parameters/constants.py +6 -1
  20. mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +42 -15
  21. mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +3 -3
  22. mx_bluesky/beamlines/i24/serial/run_extruder.sh +30 -5
  23. mx_bluesky/beamlines/i24/serial/run_fixed_target.sh +30 -5
  24. mx_bluesky/beamlines/i24/serial/run_serial.py +24 -8
  25. mx_bluesky/beamlines/i24/serial/setup_beamline/ca.py +0 -2
  26. mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +2 -0
  27. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +104 -82
  28. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +9 -20
  29. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +26 -28
  30. mx_bluesky/beamlines/i24/serial/write_nexus.py +74 -72
  31. mx_bluesky/common/__init__.py +0 -0
  32. mx_bluesky/common/device_setup_plans/read_hardware_for_setup.py +14 -0
  33. mx_bluesky/common/external_interaction/config_server.py +46 -0
  34. mx_bluesky/common/parameters/components.py +258 -0
  35. mx_bluesky/common/parameters/constants.py +143 -0
  36. mx_bluesky/common/parameters/gridscan.py +94 -0
  37. mx_bluesky/common/parameters/robot_load.py +16 -0
  38. mx_bluesky/common/plans/__init__.py +1 -0
  39. mx_bluesky/common/plans/do_fgs.py +121 -0
  40. mx_bluesky/common/utils/log.py +118 -0
  41. mx_bluesky/{hyperion → common/utils}/tracing.py +2 -2
  42. mx_bluesky/hyperion/__main__.py +13 -10
  43. mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +47 -52
  44. mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +6 -12
  45. mx_bluesky/hyperion/device_setup_plans/setup_oav.py +6 -12
  46. mx_bluesky/hyperion/device_setup_plans/setup_panda.py +5 -6
  47. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +49 -18
  48. mx_bluesky/hyperion/device_setup_plans/smargon.py +9 -9
  49. mx_bluesky/hyperion/device_setup_plans/utils.py +2 -2
  50. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +4 -4
  51. mx_bluesky/hyperion/exceptions.py +13 -1
  52. mx_bluesky/hyperion/experiment_plans/__init__.py +4 -0
  53. mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +83 -0
  54. mx_bluesky/hyperion/experiment_plans/common/xrc_result.py +47 -0
  55. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -9
  56. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +147 -169
  57. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +48 -22
  58. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +75 -9
  59. mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +21 -20
  60. mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +9 -6
  61. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +2 -2
  62. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +40 -21
  63. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +22 -22
  64. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +43 -39
  65. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +69 -18
  66. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +17 -7
  67. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +13 -13
  68. mx_bluesky/hyperion/external_interaction/callbacks/__init__.py +0 -4
  69. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +5 -2
  70. mx_bluesky/hyperion/external_interaction/callbacks/common/abstract_event.py +66 -0
  71. mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +5 -0
  72. mx_bluesky/hyperion/external_interaction/callbacks/common/ispyb_mapping.py +1 -1
  73. mx_bluesky/hyperion/external_interaction/callbacks/grid_detection_callback.py +30 -25
  74. mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py +29 -12
  75. mx_bluesky/hyperion/external_interaction/callbacks/log_uid_tag_callback.py +1 -1
  76. mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +19 -11
  77. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +7 -4
  78. mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +5 -3
  79. mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/__init__.py +0 -0
  80. mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +84 -0
  81. mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +38 -27
  82. mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py +5 -4
  83. mx_bluesky/hyperion/external_interaction/config_server.py +11 -28
  84. mx_bluesky/hyperion/external_interaction/exceptions.py +0 -9
  85. mx_bluesky/hyperion/external_interaction/ispyb/exp_eye_store.py +65 -15
  86. mx_bluesky/hyperion/external_interaction/ispyb/ispyb_store.py +1 -1
  87. mx_bluesky/hyperion/external_interaction/nexus/nexus_utils.py +2 -2
  88. mx_bluesky/hyperion/external_interaction/nexus/write_nexus.py +1 -1
  89. mx_bluesky/hyperion/log.py +0 -84
  90. mx_bluesky/hyperion/parameters/components.py +4 -251
  91. mx_bluesky/hyperion/parameters/constants.py +22 -119
  92. mx_bluesky/hyperion/parameters/gridscan.py +35 -74
  93. mx_bluesky/hyperion/parameters/load_centre_collect.py +16 -11
  94. mx_bluesky/hyperion/parameters/rotation.py +23 -10
  95. mx_bluesky/hyperion/utils/utils.py +17 -0
  96. mx_bluesky/hyperion/utils/validation.py +5 -6
  97. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/METADATA +36 -33
  98. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/RECORD +102 -89
  99. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/WHEEL +1 -1
  100. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Mapping_py3v1.py +0 -161
  101. mx_bluesky/example.py +0 -19
  102. mx_bluesky/hyperion/parameters/robot_load.py +0 -16
  103. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/LICENSE +0 -0
  104. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/entry_points.txt +0 -0
  105. {mx_bluesky-1.2.0.dist-info → mx_bluesky-1.4.1.dist-info}/top_level.txt +0 -0
@@ -41,7 +41,7 @@ def start_preparing_data_collection_then_do_plan(
41
41
  """
42
42
 
43
43
  def wrapped_plan():
44
- yield from bps.abs_set(eiger.do_arm, 1, group=group)
44
+ yield from bps.abs_set(eiger.do_arm, 1, group=group) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
45
45
  if detector_distance_mm:
46
46
  yield from set_detector_z_position(
47
47
  detector_motion, detector_distance_mm, group
@@ -51,5 +51,5 @@ def start_preparing_data_collection_then_do_plan(
51
51
 
52
52
  yield from bpp.contingency_wrapper(
53
53
  wrapped_plan(),
54
- except_plan=lambda e: (yield from bps.stop(eiger)),
54
+ except_plan=lambda e: (yield from bps.stop(eiger)), # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
55
55
  )
@@ -23,14 +23,14 @@ def _check_and_pause_feedback(
23
23
  turning XBPM feedback off.
24
24
 
25
25
  """
26
- yield from bps.mv(attenuator, 1.0)
26
+ yield from bps.mv(attenuator, 1.0) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
27
27
  LOGGER.info("Waiting for XBPM feedback to be stable")
28
28
  yield from bps.trigger(xbpm_feedback, wait=True)
29
29
  LOGGER.info(
30
30
  f"XPBM feedback in position, pausing and setting transmission to {desired_transmission_fraction}"
31
31
  )
32
- yield from bps.mv(xbpm_feedback.pause_feedback, Pause.PAUSE)
33
- yield from bps.mv(attenuator, desired_transmission_fraction)
32
+ yield from bps.mv(xbpm_feedback.pause_feedback, Pause.PAUSE) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
33
+ yield from bps.mv(attenuator, desired_transmission_fraction) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
34
34
 
35
35
 
36
36
  def _unpause_xbpm_feedback_and_set_transmission_to_1(
@@ -44,7 +44,7 @@ def _unpause_xbpm_feedback_and_set_transmission_to_1(
44
44
  the beam in position
45
45
  attenuator (Attenuator): The attenuator used to set transmission
46
46
  """
47
- yield from bps.mv(xbpm_feedback.pause_feedback, Pause.RUN, attenuator, 1.0)
47
+ yield from bps.mv(xbpm_feedback.pause_feedback, Pause.RUN, attenuator, 1.0) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
48
48
 
49
49
 
50
50
  def transmission_and_xbpm_feedback_for_collection_wrapper(
@@ -13,9 +13,21 @@ class WarningException(Exception):
13
13
  pass
14
14
 
15
15
 
16
+ class SampleException(WarningException):
17
+ """An exception which identifies an issue relating to the sample."""
18
+
19
+ pass
20
+
21
+
16
22
  T = TypeVar("T")
17
23
 
18
24
 
25
+ class CrystalNotFoundException(SampleException):
26
+ """Raised if grid detection completed normally but no crystal was found."""
27
+
28
+ pass
29
+
30
+
19
31
  def catch_exception_and_warn(
20
32
  exception_to_catch: type[Exception],
21
33
  func: Callable[..., Generator[Msg, None, T]],
@@ -36,7 +48,7 @@ def catch_exception_and_warn(
36
48
 
37
49
  def warn_if_exception_matches(exception: Exception):
38
50
  if isinstance(exception, exception_to_catch):
39
- raise WarningException(str(exception))
51
+ raise SampleException(str(exception)) from exception
40
52
  yield from null()
41
53
 
42
54
  return (
@@ -9,6 +9,9 @@ from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
9
9
  from mx_bluesky.hyperion.experiment_plans.grid_detect_then_xray_centre_plan import (
10
10
  grid_detect_then_xray_centre,
11
11
  )
12
+ from mx_bluesky.hyperion.experiment_plans.load_centre_collect_full_plan import (
13
+ load_centre_collect_full,
14
+ )
12
15
  from mx_bluesky.hyperion.experiment_plans.pin_centre_then_xray_centre_plan import (
13
16
  pin_tip_centre_then_xray_centre,
14
17
  )
@@ -27,4 +30,5 @@ __all__ = [
27
30
  "pin_tip_centre_then_xray_centre",
28
31
  "multi_rotation_scan",
29
32
  "robot_load_then_centre",
33
+ "load_centre_collect_full",
30
34
  ]
@@ -0,0 +1,83 @@
1
+ import bluesky.plan_stubs as bps
2
+ import bluesky.preprocessors as bpp
3
+ import numpy
4
+ from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureValue
5
+ from dodal.devices.smargon import Smargon, StubPosition
6
+
7
+ from mx_bluesky.common.utils.tracing import TRACER
8
+ from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import move_x_y_z
9
+ from mx_bluesky.hyperion.experiment_plans.common.xrc_result import XRayCentreResult
10
+ from mx_bluesky.hyperion.log import LOGGER
11
+ from mx_bluesky.hyperion.parameters.gridscan import HyperionThreeDGridScan
12
+
13
+
14
+ def change_aperture_then_move_to_xtal(
15
+ best_hit: XRayCentreResult,
16
+ smargon: Smargon,
17
+ aperture_scatterguard: ApertureScatterguard,
18
+ parameters: HyperionThreeDGridScan | None = None,
19
+ ):
20
+ """For the given x-ray centring result,
21
+ * Change the aperture so that the beam size is comparable to the crystal size
22
+ * Centre on the centre-of-mass
23
+ * Reset the stub offsets if specified by params"""
24
+ if best_hit.bounding_box_mm is not None:
25
+ bounding_box_size = numpy.abs(
26
+ best_hit.bounding_box_mm[1] - best_hit.bounding_box_mm[0]
27
+ )
28
+ with TRACER.start_span("change_aperture"):
29
+ yield from _set_aperture_for_bbox_mm(
30
+ aperture_scatterguard, bounding_box_size
31
+ )
32
+ else:
33
+ LOGGER.warning("No bounding box size received")
34
+
35
+ # once we have the results, go to the appropriate position
36
+ LOGGER.info("Moving to centre of mass.")
37
+ with TRACER.start_span("move_to_result"):
38
+ x, y, z = best_hit.centre_of_mass_mm
39
+ yield from move_x_y_z(smargon, x, y, z, wait=True)
40
+
41
+ # TODO support for setting stub offsets in multipin
42
+ # https://github.com/DiamondLightSource/mx-bluesky/issues/552
43
+ if parameters and parameters.FGS_params.set_stub_offsets:
44
+ LOGGER.info("Recentring smargon co-ordinate system to this point.")
45
+ yield from bps.mv(
46
+ # See: https://github.com/bluesky/bluesky/issues/1809
47
+ smargon.stub_offsets, # type: ignore
48
+ StubPosition.CURRENT_AS_CENTER, # type: ignore
49
+ )
50
+
51
+
52
+ def _set_aperture_for_bbox_mm(
53
+ aperture_device: ApertureScatterguard, bbox_size_mm: list[float] | numpy.ndarray
54
+ ):
55
+ # TODO confirm correction factor see https://github.com/DiamondLightSource/mx-bluesky/issues/618
56
+ ASSUMED_BOX_SIZE_MM = 0.020
57
+ bbox_size_boxes = [round(mm / ASSUMED_BOX_SIZE_MM) for mm in bbox_size_mm]
58
+ yield from set_aperture_for_bbox_size(aperture_device, bbox_size_boxes)
59
+
60
+
61
+ def set_aperture_for_bbox_size(
62
+ aperture_device: ApertureScatterguard,
63
+ bbox_size: list[int] | numpy.ndarray,
64
+ ):
65
+ # bbox_size is [x,y,z], for i03 we only care about x
66
+ new_selected_aperture = (
67
+ ApertureValue.MEDIUM if bbox_size[0] < 2 else ApertureValue.LARGE
68
+ )
69
+ LOGGER.info(
70
+ f"Setting aperture to {new_selected_aperture} based on bounding box size {bbox_size}."
71
+ )
72
+
73
+ @bpp.set_run_key_decorator("change_aperture")
74
+ @bpp.run_decorator(
75
+ md={
76
+ "subplan_name": "change_aperture",
77
+ "aperture_size": new_selected_aperture.value,
78
+ }
79
+ )
80
+ def set_aperture():
81
+ yield from bps.abs_set(aperture_device, new_selected_aperture)
82
+
83
+ yield from set_aperture()
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ from collections.abc import Callable, Sequence
5
+ from functools import partial
6
+
7
+ import numpy as np
8
+
9
+ from mx_bluesky.common.parameters.components import (
10
+ MultiXtalSelection,
11
+ TopNByMaxCountSelection,
12
+ )
13
+
14
+
15
+ @dataclasses.dataclass
16
+ class XRayCentreResult:
17
+ """Represents information about a hit from an X-ray centring."""
18
+
19
+ centre_of_mass_mm: np.ndarray
20
+ bounding_box_mm: tuple[np.ndarray, np.ndarray]
21
+ max_count: int
22
+ total_count: int
23
+
24
+ def __eq__(self, o):
25
+ return (
26
+ isinstance(o, XRayCentreResult)
27
+ and o.max_count == self.max_count
28
+ and o.total_count == self.total_count
29
+ and all(o.centre_of_mass_mm == self.centre_of_mass_mm)
30
+ and all(o.bounding_box_mm[0] == self.bounding_box_mm[0])
31
+ and all(o.bounding_box_mm[1] == self.bounding_box_mm[1])
32
+ )
33
+
34
+
35
+ def top_n_by_max_count(
36
+ unfiltered: Sequence[XRayCentreResult], n: int
37
+ ) -> Sequence[XRayCentreResult]:
38
+ sorted_hits = sorted(unfiltered, key=lambda result: result.max_count, reverse=True)
39
+ return sorted_hits[:n]
40
+
41
+
42
+ def resolve_selection_fn(
43
+ params: MultiXtalSelection,
44
+ ) -> Callable[[Sequence[XRayCentreResult]], Sequence[XRayCentreResult]]:
45
+ if isinstance(params, TopNByMaxCountSelection):
46
+ return partial(top_n_by_max_count, n=params.n)
47
+ raise ValueError(f"Invalid selection function {params.name}")
@@ -5,6 +5,11 @@ from typing import TypedDict
5
5
 
6
6
  import mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan as flyscan_xray_centre_plan
7
7
  import mx_bluesky.hyperion.experiment_plans.rotation_scan_plan as rotation_scan_plan
8
+ from mx_bluesky.common.parameters.gridscan import (
9
+ GridScanWithEdgeDetect,
10
+ PinTipCentreThenXrayCentre,
11
+ RobotLoadThenCentre,
12
+ )
8
13
  from mx_bluesky.hyperion.experiment_plans import (
9
14
  grid_detect_then_xray_centre_plan,
10
15
  load_centre_collect_full_plan,
@@ -18,12 +23,7 @@ from mx_bluesky.hyperion.external_interaction.callbacks.common.callback_util imp
18
23
  create_robot_load_and_centre_callbacks,
19
24
  create_rotation_callbacks,
20
25
  )
21
- from mx_bluesky.hyperion.parameters.gridscan import (
22
- GridScanWithEdgeDetect,
23
- PinTipCentreThenXrayCentre,
24
- RobotLoadThenCentre,
25
- ThreeDGridScan,
26
- )
26
+ from mx_bluesky.hyperion.parameters.gridscan import HyperionThreeDGridScan
27
27
  from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
28
28
  from mx_bluesky.hyperion.parameters.rotation import MultiRotationScan, RotationScan
29
29
 
@@ -39,7 +39,7 @@ def do_nothing():
39
39
  class ExperimentRegistryEntry(TypedDict):
40
40
  setup: Callable
41
41
  param_type: type[
42
- ThreeDGridScan
42
+ HyperionThreeDGridScan
43
43
  | GridScanWithEdgeDetect
44
44
  | RotationScan
45
45
  | MultiRotationScan
@@ -53,7 +53,7 @@ class ExperimentRegistryEntry(TypedDict):
53
53
  PLAN_REGISTRY: dict[str, ExperimentRegistryEntry] = {
54
54
  "flyscan_xray_centre": {
55
55
  "setup": flyscan_xray_centre_plan.create_devices,
56
- "param_type": ThreeDGridScan,
56
+ "param_type": HyperionThreeDGridScan,
57
57
  "callbacks_factory": create_gridscan_callbacks,
58
58
  },
59
59
  "grid_detect_then_xray_centre": {
@@ -81,7 +81,7 @@ PLAN_REGISTRY: dict[str, ExperimentRegistryEntry] = {
81
81
  "param_type": MultiRotationScan,
82
82
  "callbacks_factory": create_rotation_callbacks,
83
83
  },
84
- "load_centre_collect_full_plan": {
84
+ "load_centre_collect_full": {
85
85
  "setup": load_centre_collect_full_plan.create_devices,
86
86
  "param_type": LoadCentreCollect,
87
87
  "callbacks_factory": create_load_centre_collect_callbacks,