mx-bluesky 1.4.5__py3-none-any.whl → 1.4.6__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 (63) hide show
  1. mx_bluesky/_version.py +9 -4
  2. mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +14 -3
  3. mx_bluesky/beamlines/i04/thawing_plan.py +9 -13
  4. mx_bluesky/beamlines/i24/serial/__init__.py +14 -0
  5. mx_bluesky/beamlines/i24/serial/dcid.py +3 -1
  6. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +1 -1
  7. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +6 -3
  8. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +11 -11
  9. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +1 -1
  10. mx_bluesky/beamlines/i24/serial/log.py +0 -1
  11. mx_bluesky/beamlines/i24/serial/parameters/constants.py +1 -1
  12. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +1 -1
  13. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +1 -1
  14. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +2 -2
  15. mx_bluesky/beamlines/i24/serial/web_gui_plans/__init__.py +0 -0
  16. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +109 -0
  17. mx_bluesky/beamlines/i24/serial/write_nexus.py +2 -2
  18. mx_bluesky/common/external_interaction/callbacks/common/plan_reactive_callback.py +2 -2
  19. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +2 -2
  20. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_mapping.py +1 -1
  21. mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +6 -2
  22. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +7 -0
  23. mx_bluesky/common/parameters/constants.py +1 -1
  24. mx_bluesky/common/parameters/gridscan.py +36 -1
  25. mx_bluesky/common/plans/do_fgs.py +4 -6
  26. mx_bluesky/common/plans/read_hardware.py +78 -0
  27. mx_bluesky/common/utils/context.py +68 -0
  28. mx_bluesky/{hyperion/experiment_plans/common → common}/xrc_result.py +16 -0
  29. mx_bluesky/hyperion/__main__.py +4 -0
  30. mx_bluesky/hyperion/device_setup_plans/setup_oav.py +5 -5
  31. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +2 -2
  32. mx_bluesky/hyperion/device_setup_plans/smargon.py +6 -6
  33. mx_bluesky/hyperion/device_setup_plans/utils.py +2 -2
  34. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +4 -4
  35. mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +2 -6
  36. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +33 -87
  37. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +6 -6
  38. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +3 -5
  39. mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +11 -11
  40. mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +4 -4
  41. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +1 -1
  42. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +2 -4
  43. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +10 -10
  44. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +10 -10
  45. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +2 -4
  46. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +7 -9
  47. mx_bluesky/hyperion/external_interaction/agamemnon.py +104 -0
  48. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +1 -1
  49. mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +14 -9
  50. mx_bluesky/hyperion/external_interaction/config_server.py +6 -6
  51. mx_bluesky/hyperion/parameters/device_composites.py +49 -0
  52. mx_bluesky/hyperion/parameters/gridscan.py +1 -1
  53. mx_bluesky/hyperion/utils/__init__.py +1 -0
  54. mx_bluesky/hyperion/utils/context.py +0 -65
  55. mx_bluesky/hyperion/utils/validation.py +3 -3
  56. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.6.dist-info}/METADATA +4 -3
  57. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.6.dist-info}/RECORD +61 -56
  58. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.6.dist-info}/WHEEL +1 -1
  59. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.6.dist-info}/entry_points.txt +1 -0
  60. mx_bluesky/common/device_setup_plans/read_hardware_for_setup.py +0 -14
  61. mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +0 -54
  62. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.6.dist-info}/LICENSE +0 -0
  63. {mx_bluesky-1.4.5.dist-info → mx_bluesky-1.4.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,78 @@
1
+ from __future__ import annotations
2
+
3
+ import bluesky.plan_stubs as bps
4
+ from bluesky.protocols import Readable
5
+ from dodal.devices.aperturescatterguard import ApertureScatterguard
6
+ from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
7
+ from dodal.devices.dcm import DCM
8
+ from dodal.devices.eiger import EigerDetector
9
+ from dodal.devices.flux import Flux
10
+ from dodal.devices.s4_slit_gaps import S4SlitGaps
11
+ from dodal.devices.smargon import Smargon
12
+ from dodal.devices.synchrotron import Synchrotron
13
+ from dodal.devices.undulator import Undulator
14
+
15
+ from mx_bluesky.common.parameters.constants import (
16
+ DocDescriptorNames,
17
+ )
18
+ from mx_bluesky.common.utils.log import LOGGER
19
+
20
+
21
+ def read_hardware_plan(
22
+ signals: list[Readable],
23
+ event_name: str,
24
+ ):
25
+ LOGGER.info(f"Reading status of beamline for event, {event_name}")
26
+ yield from bps.create(name=event_name)
27
+ for signal in signals:
28
+ yield from bps.read(signal)
29
+ yield from bps.save()
30
+
31
+
32
+ def read_hardware_for_zocalo(detector: EigerDetector):
33
+ """ "
34
+ If the RunEngine is subscribed to the ZocaloCallback, this plan will also trigger zocalo.
35
+ """
36
+ yield from read_hardware_plan(
37
+ [detector.odin.file_writer.id], # type: ignore
38
+ DocDescriptorNames.ZOCALO_HW_READ,
39
+ )
40
+
41
+
42
+ def standard_read_hardware_pre_collection(
43
+ undulator: Undulator,
44
+ synchrotron: Synchrotron,
45
+ s4_slit_gaps: S4SlitGaps,
46
+ dcm: DCM,
47
+ smargon: Smargon,
48
+ ):
49
+ LOGGER.info("Reading status of beamline for callbacks, pre collection.")
50
+ signals_to_read_pre_flyscan = [
51
+ undulator.current_gap,
52
+ synchrotron.synchrotron_mode,
53
+ s4_slit_gaps,
54
+ smargon,
55
+ dcm.energy_in_kev,
56
+ ]
57
+ yield from read_hardware_plan(
58
+ signals_to_read_pre_flyscan, DocDescriptorNames.HARDWARE_READ_PRE
59
+ )
60
+
61
+
62
+ def standard_read_hardware_during_collection(
63
+ aperture_scatterguard: ApertureScatterguard,
64
+ attenuator: BinaryFilterAttenuator,
65
+ flux: Flux,
66
+ dcm: DCM,
67
+ detector: EigerDetector,
68
+ ):
69
+ signals_to_read_during_collection = [
70
+ aperture_scatterguard,
71
+ attenuator.actual_transmission,
72
+ flux.flux_reading,
73
+ dcm.energy_in_kev,
74
+ detector.bit_depth,
75
+ ]
76
+ yield from read_hardware_plan(
77
+ signals_to_read_during_collection, DocDescriptorNames.HARDWARE_READ_DURING
78
+ )
@@ -0,0 +1,68 @@
1
+ import dataclasses
2
+ from typing import Any, ClassVar, Protocol, TypeVar, get_type_hints
3
+
4
+ from blueapi.core import BlueskyContext
5
+ from blueapi.core.bluesky_types import Device
6
+
7
+ from mx_bluesky.common.utils.log import LOGGER
8
+
9
+ T = TypeVar("T", bound=Device)
10
+
11
+
12
+ class _IsDataclass(Protocol):
13
+ """Protocol followed by any dataclass"""
14
+
15
+ __dataclass_fields__: ClassVar[dict]
16
+
17
+
18
+ DT = TypeVar("DT", bound=_IsDataclass)
19
+
20
+
21
+ def find_device_in_context(
22
+ context: BlueskyContext,
23
+ name: str,
24
+ # Typing in here is wrong (see https://github.com/microsoft/pyright/issues/7228#issuecomment-1934500232)
25
+ # but this whole thing will go away when we do https://github.com/DiamondLightSource/hyperion/issues/868
26
+ expected_type: type[T] = Device, # type: ignore
27
+ ) -> T:
28
+ LOGGER.debug(f"Looking for device {name} of type {expected_type} in context")
29
+
30
+ device = context.find_device(name)
31
+ if device is None:
32
+ raise ValueError(
33
+ f"Cannot find device named '{name}' in bluesky context {context.devices}."
34
+ )
35
+
36
+ if not isinstance(device, expected_type):
37
+ raise ValueError(
38
+ f"Found device named '{name}' and expected it to be a '{expected_type}' but it was a '{device.__class__.__name__}'"
39
+ )
40
+
41
+ LOGGER.debug(f"Found matching device {device}")
42
+ return device
43
+
44
+
45
+ def device_composite_from_context(context: BlueskyContext, dc: type[DT]) -> DT:
46
+ """
47
+ Initializes all of the devices referenced in a given dataclass from a provided
48
+ context, checking that the types of devices returned by the context are compatible
49
+ with the type annotations of the dataclass.
50
+
51
+ Note that if the context was not created with `wait_for_connection=True` devices may
52
+ still be unconnected.
53
+ """
54
+ LOGGER.debug(
55
+ f"Attempting to initialize devices referenced in dataclass {dc} from blueapi context"
56
+ )
57
+
58
+ devices: dict[str, Any] = {}
59
+ dc_type_hints: dict[str, Any] = get_type_hints(dc)
60
+
61
+ for field in dataclasses.fields(dc):
62
+ device = find_device_in_context(
63
+ context, field.name, expected_type=dc_type_hints.get(field.name, Device)
64
+ )
65
+
66
+ devices[field.name] = device
67
+
68
+ return dc(**devices)
@@ -5,6 +5,8 @@ from collections.abc import Callable, Sequence
5
5
  from functools import partial
6
6
 
7
7
  import numpy as np
8
+ from bluesky.callbacks import CallbackBase
9
+ from event_model import RunStart
8
10
 
9
11
  from mx_bluesky.common.parameters.components import (
10
12
  MultiXtalSelection,
@@ -12,6 +14,20 @@ from mx_bluesky.common.parameters.components import (
12
14
  )
13
15
 
14
16
 
17
+ class XRayCentreEventHandler(CallbackBase):
18
+ def __init__(self):
19
+ super().__init__()
20
+ self.xray_centre_results: Sequence[XRayCentreResult] | None = None
21
+
22
+ def start(self, doc: RunStart) -> RunStart | None:
23
+ if "xray_centre_results" in doc:
24
+ self.xray_centre_results = [
25
+ XRayCentreResult(**result_dict)
26
+ for result_dict in doc["xray_centre_results"] # type: ignore
27
+ ]
28
+ return doc
29
+
30
+
15
31
  @dataclasses.dataclass
16
32
  class XRayCentreResult:
17
33
  """
@@ -38,6 +38,9 @@ from mx_bluesky.hyperion.experiment_plans.experiment_registry import (
38
38
  PLAN_REGISTRY,
39
39
  PlanNotFound,
40
40
  )
41
+ from mx_bluesky.hyperion.external_interaction.agamemnon import (
42
+ update_params_from_agamemnon,
43
+ )
41
44
  from mx_bluesky.hyperion.parameters.cli import parse_cli_args
42
45
  from mx_bluesky.hyperion.parameters.constants import CONST
43
46
  from mx_bluesky.hyperion.utils.context import setup_context
@@ -208,6 +211,7 @@ def compose_start_args(context: BlueskyContext, plan_name: str, action: Actions)
208
211
  )
209
212
  try:
210
213
  parameters = experiment_internal_param_type(**json.loads(request.data))
214
+ parameters = update_params_from_agamemnon(parameters)
211
215
  if parameters.model_extra:
212
216
  raise ValueError(f"Extra fields not allowed {parameters.model_extra}")
213
217
  except Exception as e:
@@ -55,14 +55,14 @@ def setup_pin_tip_detection_params(
55
55
 
56
56
 
57
57
  def setup_general_oav_params(oav: OAV, parameters: OAVParameters):
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
58
+ yield from set_using_group(oav.cam.color_mode, ColorMode.RGB1)
59
+ yield from set_using_group(oav.cam.acquire_period, parameters.acquire_period)
60
+ yield from set_using_group(oav.cam.acquire_time, parameters.exposure)
61
+ yield from set_using_group(oav.cam.gain, parameters.gain)
62
62
 
63
63
  zoom_level_str = f"{float(parameters.zoom)}x"
64
64
  yield from bps.abs_set(
65
- oav.zoom_controller, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
65
+ oav.zoom_controller,
66
66
  zoom_level_str,
67
67
  wait=True,
68
68
  )
@@ -47,7 +47,7 @@ def bluesky_retry(func: Callable):
47
47
 
48
48
 
49
49
  def arm_zebra(zebra: Zebra):
50
- yield from bps.abs_set(zebra.pc.arm, ArmDemand.ARM, wait=True) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
50
+ yield from bps.abs_set(zebra.pc.arm, ArmDemand.ARM, wait=True)
51
51
 
52
52
 
53
53
  def tidy_up_zebra_after_rotation_scan(
@@ -56,7 +56,7 @@ def tidy_up_zebra_after_rotation_scan(
56
56
  group="tidy_up_zebra_after_rotation",
57
57
  wait=True,
58
58
  ):
59
- yield from bps.abs_set(zebra.pc.arm, ArmDemand.DISARM, group=group) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
59
+ yield from bps.abs_set(zebra.pc.arm, ArmDemand.DISARM, group=group)
60
60
  yield from bps.abs_set(
61
61
  zebra_shutter.control_mode, ZebraShutterControl.MANUAL, group=group
62
62
  )
@@ -16,10 +16,10 @@ def move_smargon_warn_on_out_of_range(
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, # 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
19
+ smargon.x,
20
+ position[0],
21
+ smargon.y,
22
+ position[1],
23
+ smargon.z,
24
+ position[2],
25
25
  )
@@ -44,7 +44,7 @@ def start_preparing_data_collection_then_do_plan(
44
44
  """
45
45
 
46
46
  def wrapped_plan():
47
- yield from bps.abs_set(eiger.do_arm, 1, group=group) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
47
+ yield from bps.abs_set(eiger.do_arm, 1, group=group) # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
48
48
  if detector_distance_mm:
49
49
  yield from set_detector_z_position(
50
50
  detector_motion, detector_distance_mm, group
@@ -55,5 +55,5 @@ def start_preparing_data_collection_then_do_plan(
55
55
  yield from check_beamstop(beamstop)
56
56
  yield from bpp.contingency_wrapper(
57
57
  wrapped_plan(),
58
- except_plan=lambda e: (yield from bps.stop(eiger)), # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
58
+ except_plan=lambda e: (yield from bps.stop(eiger)), # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
59
59
  )
@@ -25,14 +25,14 @@ def _check_and_pause_feedback(
25
25
  turning XBPM feedback off.
26
26
 
27
27
  """
28
- yield from bps.mv(attenuator, 1.0) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
28
+ yield from bps.mv(attenuator, 1.0)
29
29
  LOGGER.info("Waiting for XBPM feedback to be stable")
30
30
  yield from bps.trigger(xbpm_feedback, wait=True)
31
31
  LOGGER.info(
32
32
  f"XPBM feedback in position, pausing and setting transmission to {desired_transmission_fraction}"
33
33
  )
34
- yield from bps.mv(xbpm_feedback.pause_feedback, Pause.PAUSE) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
35
- yield from bps.mv(attenuator, desired_transmission_fraction) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
34
+ yield from bps.mv(xbpm_feedback.pause_feedback, Pause.PAUSE)
35
+ yield from bps.mv(attenuator, desired_transmission_fraction)
36
36
 
37
37
 
38
38
  def _unpause_xbpm_feedback_and_set_transmission_to_1(
@@ -46,7 +46,7 @@ def _unpause_xbpm_feedback_and_set_transmission_to_1(
46
46
  the beam in position
47
47
  attenuator (BinaryFilterAttenuator): The attenuator used to set transmission
48
48
  """
49
- yield from bps.mv(xbpm_feedback.pause_feedback, Pause.RUN, attenuator, 1.0) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
49
+ yield from bps.mv(xbpm_feedback.pause_feedback, Pause.RUN, attenuator, 1.0)
50
50
 
51
51
 
52
52
  def transmission_and_xbpm_feedback_for_collection_wrapper(
@@ -6,8 +6,8 @@ from dodal.devices.smargon import Smargon, StubPosition
6
6
 
7
7
  from mx_bluesky.common.utils.log import LOGGER
8
8
  from mx_bluesky.common.utils.tracing import TRACER
9
+ from mx_bluesky.common.xrc_result import XRayCentreResult
9
10
  from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import move_x_y_z
10
- from mx_bluesky.hyperion.experiment_plans.common.xrc_result import XRayCentreResult
11
11
  from mx_bluesky.hyperion.parameters.gridscan import HyperionSpecifiedThreeDGridScan
12
12
 
13
13
 
@@ -43,11 +43,7 @@ def change_aperture_then_move_to_xtal(
43
43
  # https://github.com/DiamondLightSource/mx-bluesky/issues/552
44
44
  if parameters and parameters.FGS_params.set_stub_offsets:
45
45
  LOGGER.info("Recentring smargon co-ordinate system to this point.")
46
- yield from bps.mv(
47
- # See: https://github.com/bluesky/bluesky/issues/1809
48
- smargon.stub_offsets, # type: ignore
49
- StubPosition.CURRENT_AS_CENTER, # type: ignore
50
- )
46
+ yield from bps.mv(smargon.stub_offsets, StubPosition.CURRENT_AS_CENTER)
51
47
 
52
48
 
53
49
  def set_aperture_for_bbox_mm(
@@ -9,59 +9,39 @@ from typing import Protocol
9
9
  import bluesky.plan_stubs as bps
10
10
  import bluesky.preprocessors as bpp
11
11
  import numpy as np
12
- import pydantic
13
12
  from blueapi.core import BlueskyContext
14
- from bluesky.callbacks import CallbackBase
15
13
  from bluesky.utils import MsgGenerator
16
- from dodal.devices.aperturescatterguard import (
17
- ApertureScatterguard,
18
- )
19
- from dodal.devices.attenuator.attenuator import BinaryFilterAttenuator
20
- from dodal.devices.backlight import Backlight
21
- from dodal.devices.dcm import DCM
22
- from dodal.devices.eiger import EigerDetector
23
14
  from dodal.devices.fast_grid_scan import (
24
15
  FastGridScanCommon,
25
- PandAFastGridScan,
26
- ZebraFastGridScan,
27
16
  )
28
17
  from dodal.devices.fast_grid_scan import (
29
18
  set_fast_grid_scan_params as set_flyscan_params,
30
19
  )
31
- from dodal.devices.flux import Flux
32
- from dodal.devices.robot import BartRobot
33
- from dodal.devices.s4_slit_gaps import S4SlitGaps
34
- from dodal.devices.smargon import Smargon
35
- from dodal.devices.synchrotron import Synchrotron
36
- from dodal.devices.undulator import Undulator
37
- from dodal.devices.xbpm_feedback import XBPMFeedback
38
20
  from dodal.devices.zebra.zebra import Zebra
39
- from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
40
21
  from dodal.devices.zocalo.zocalo_results import (
41
22
  ZOCALO_READING_PLAN_NAME,
42
23
  ZOCALO_STAGE_GROUP,
43
24
  XrcResult,
44
- ZocaloResults,
45
25
  get_full_processing_results,
46
26
  )
47
- from event_model import RunStart
48
- from ophyd_async.fastcs.panda import HDFPanda
49
27
 
50
28
  from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback import (
51
29
  ispyb_activation_wrapper,
52
30
  )
53
31
  from mx_bluesky.common.parameters.constants import HardwareConstants
54
32
  from mx_bluesky.common.plans.do_fgs import kickoff_and_complete_gridscan
33
+ from mx_bluesky.common.plans.read_hardware import (
34
+ standard_read_hardware_during_collection,
35
+ standard_read_hardware_pre_collection,
36
+ )
37
+ from mx_bluesky.common.utils.context import device_composite_from_context
55
38
  from mx_bluesky.common.utils.exceptions import (
56
39
  CrystalNotFoundException,
57
40
  SampleException,
58
41
  )
59
42
  from mx_bluesky.common.utils.log import LOGGER
60
43
  from mx_bluesky.common.utils.tracing import TRACER
61
- from mx_bluesky.hyperion.device_setup_plans.read_hardware_for_setup import (
62
- read_hardware_during_collection,
63
- read_hardware_pre_collection,
64
- )
44
+ from mx_bluesky.common.xrc_result import XRayCentreEventHandler, XRayCentreResult
65
45
  from mx_bluesky.hyperion.device_setup_plans.setup_panda import (
66
46
  disarm_panda_for_gridscan,
67
47
  set_panda_directory,
@@ -78,10 +58,11 @@ from mx_bluesky.hyperion.device_setup_plans.xbpm_feedback import (
78
58
  from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import (
79
59
  change_aperture_then_move_to_xtal,
80
60
  )
81
- from mx_bluesky.hyperion.experiment_plans.common.xrc_result import XRayCentreResult
82
61
  from mx_bluesky.hyperion.parameters.constants import CONST
62
+ from mx_bluesky.hyperion.parameters.device_composites import (
63
+ HyperionFlyScanXRayCentreComposite,
64
+ )
83
65
  from mx_bluesky.hyperion.parameters.gridscan import HyperionSpecifiedThreeDGridScan
84
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
85
66
 
86
67
  ZOCALO_MIN_TOTAL_COUNT_THRESHOLD = 3
87
68
 
@@ -90,56 +71,21 @@ class SmargonSpeedException(Exception):
90
71
  pass
91
72
 
92
73
 
93
- @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
94
- class FlyScanXRayCentreComposite:
95
- """All devices which are directly or indirectly required by this plan"""
96
-
97
- aperture_scatterguard: ApertureScatterguard
98
- attenuator: BinaryFilterAttenuator
99
- backlight: Backlight
100
- dcm: DCM
101
- eiger: EigerDetector
102
- zebra_fast_grid_scan: ZebraFastGridScan
103
- flux: Flux
104
- s4_slit_gaps: S4SlitGaps
105
- smargon: Smargon
106
- undulator: Undulator
107
- synchrotron: Synchrotron
108
- xbpm_feedback: XBPMFeedback
109
- zebra: Zebra
110
- zocalo: ZocaloResults
111
- panda: HDFPanda
112
- panda_fast_grid_scan: PandAFastGridScan
113
- robot: BartRobot
114
- sample_shutter: ZebraShutter
115
-
116
-
117
- class XRayCentreEventHandler(CallbackBase):
118
- def __init__(self):
119
- super().__init__()
120
- self.xray_centre_results: Sequence[XRayCentreResult] | None = None
121
-
122
- def start(self, doc: RunStart) -> RunStart | None:
123
- if CONST.PLAN.FLYSCAN_RESULTS in doc:
124
- self.xray_centre_results = [
125
- XRayCentreResult(**result_dict)
126
- for result_dict in doc[CONST.PLAN.FLYSCAN_RESULTS] # type: ignore
127
- ]
128
- return doc
129
-
130
-
131
- def create_devices(context: BlueskyContext) -> FlyScanXRayCentreComposite:
74
+ def create_devices(context: BlueskyContext) -> HyperionFlyScanXRayCentreComposite:
132
75
  """Creates the devices required for the plan and connect to them"""
133
- return device_composite_from_context(context, FlyScanXRayCentreComposite)
76
+ return device_composite_from_context(context, HyperionFlyScanXRayCentreComposite)
134
77
 
135
78
 
136
79
  def flyscan_xray_centre_no_move(
137
- composite: FlyScanXRayCentreComposite, parameters: HyperionSpecifiedThreeDGridScan
80
+ composite: HyperionFlyScanXRayCentreComposite,
81
+ parameters: HyperionSpecifiedThreeDGridScan,
138
82
  ) -> MsgGenerator:
139
83
  """Perform a flyscan and determine the centres of interest"""
140
- parameters.features.update_self_from_server()
84
+
141
85
  composite.eiger.set_detector_parameters(parameters.detector_params)
142
86
  composite.zocalo.zocalo_environment = CONST.ZOCALO_ENV
87
+
88
+ parameters.features.update_self_from_server()
143
89
  composite.zocalo.use_cpu_and_gpu = parameters.features.compare_cpu_and_gpu_zocalo
144
90
  composite.zocalo.use_gpu = parameters.features.use_gpu_results
145
91
 
@@ -164,7 +110,7 @@ def flyscan_xray_centre_no_move(
164
110
  parameters.transmission_frac,
165
111
  )
166
112
  def run_gridscan_and_fetch_and_tidy(
167
- fgs_composite: FlyScanXRayCentreComposite,
113
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
168
114
  params: HyperionSpecifiedThreeDGridScan,
169
115
  feature_controlled: _FeatureControlled,
170
116
  ) -> MsgGenerator:
@@ -178,7 +124,7 @@ def flyscan_xray_centre_no_move(
178
124
 
179
125
 
180
126
  def flyscan_xray_centre(
181
- composite: FlyScanXRayCentreComposite,
127
+ composite: HyperionFlyScanXRayCentreComposite,
182
128
  parameters: HyperionSpecifiedThreeDGridScan,
183
129
  ) -> MsgGenerator:
184
130
  """Create the plan to run the grid scan based on provided parameters.
@@ -217,7 +163,7 @@ def flyscan_xray_centre(
217
163
  @bpp.set_run_key_decorator(CONST.PLAN.GRIDSCAN_AND_MOVE)
218
164
  @bpp.run_decorator(md={"subplan_name": CONST.PLAN.GRIDSCAN_AND_MOVE})
219
165
  def run_gridscan_and_fetch_results(
220
- fgs_composite: FlyScanXRayCentreComposite,
166
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
221
167
  parameters: HyperionSpecifiedThreeDGridScan,
222
168
  feature_controlled: _FeatureControlled,
223
169
  ) -> MsgGenerator:
@@ -265,7 +211,7 @@ def run_gridscan_and_fetch_results(
265
211
  finally:
266
212
  # Turn off dev/shm streaming to avoid filling disk, see https://github.com/DiamondLightSource/hyperion/issues/1395
267
213
  LOGGER.info("Turning off Eiger dev/shm streaming")
268
- yield from bps.abs_set(fgs_composite.eiger.odin.fan.dev_shm_enable, 0) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
214
+ yield from bps.abs_set(fgs_composite.eiger.odin.fan.dev_shm_enable, 0) # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
269
215
 
270
216
  # Wait on everything before returning to GDA (particularly apertures), can be removed
271
217
  # when we do not return to GDA here
@@ -314,7 +260,7 @@ def _fire_xray_centre_result_event(results: Sequence[XRayCentreResult]):
314
260
  @bpp.set_run_key_decorator(CONST.PLAN.GRIDSCAN_MAIN)
315
261
  @bpp.run_decorator(md={"subplan_name": CONST.PLAN.GRIDSCAN_MAIN})
316
262
  def run_gridscan(
317
- fgs_composite: FlyScanXRayCentreComposite,
263
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
318
264
  parameters: HyperionSpecifiedThreeDGridScan,
319
265
  feature_controlled: _FeatureControlled,
320
266
  md={ # noqa
@@ -329,7 +275,7 @@ def run_gridscan(
329
275
  # we should generate an event reading the values which need to be included in the
330
276
  # ispyb deposition
331
277
  with TRACER.start_span("ispyb_hardware_readings"):
332
- yield from read_hardware_pre_collection(
278
+ yield from standard_read_hardware_pre_collection(
333
279
  fgs_composite.undulator,
334
280
  fgs_composite.synchrotron,
335
281
  fgs_composite.s4_slit_gaps,
@@ -338,7 +284,7 @@ def run_gridscan(
338
284
  )
339
285
 
340
286
  read_during_collection = partial(
341
- read_hardware_during_collection,
287
+ standard_read_hardware_during_collection,
342
288
  fgs_composite.aperture_scatterguard,
343
289
  fgs_composite.attenuator,
344
290
  fgs_composite.flux,
@@ -354,7 +300,7 @@ def run_gridscan(
354
300
 
355
301
  LOGGER.info("Waiting for arming to finish")
356
302
  yield from bps.wait(CONST.WAIT.GRID_READY_FOR_DC)
357
- yield from bps.stage(fgs_composite.eiger) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
303
+ yield from bps.stage(fgs_composite.eiger)
358
304
 
359
305
  yield from kickoff_and_complete_gridscan(
360
306
  feature_controlled.fgs_motors,
@@ -394,18 +340,18 @@ class _FeatureControlled:
394
340
  class _ExtraSetup(Protocol):
395
341
  def __call__(
396
342
  self,
397
- fgs_composite: FlyScanXRayCentreComposite,
343
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
398
344
  parameters: HyperionSpecifiedThreeDGridScan,
399
345
  ) -> MsgGenerator: ...
400
346
 
401
347
  setup_trigger: _ExtraSetup
402
- tidy_plan: Callable[[FlyScanXRayCentreComposite], MsgGenerator]
348
+ tidy_plan: Callable[[HyperionFlyScanXRayCentreComposite], MsgGenerator]
403
349
  set_flyscan_params: Callable[[], MsgGenerator]
404
350
  fgs_motors: FastGridScanCommon
405
351
 
406
352
 
407
353
  def _get_feature_controlled(
408
- fgs_composite: FlyScanXRayCentreComposite,
354
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
409
355
  parameters: HyperionSpecifiedThreeDGridScan,
410
356
  ):
411
357
  if parameters.features.use_panda_for_gridscan:
@@ -433,7 +379,7 @@ def _get_feature_controlled(
433
379
 
434
380
 
435
381
  def _generic_tidy(
436
- fgs_composite: FlyScanXRayCentreComposite, group, wait=True
382
+ fgs_composite: HyperionFlyScanXRayCentreComposite, group, wait=True
437
383
  ) -> MsgGenerator:
438
384
  LOGGER.info("Tidying up Zebra")
439
385
  yield from tidy_up_zebra_after_gridscan(
@@ -444,7 +390,7 @@ def _generic_tidy(
444
390
  yield from bps.unstage(fgs_composite.zocalo, group=group, wait=wait)
445
391
 
446
392
 
447
- def _panda_tidy(fgs_composite: FlyScanXRayCentreComposite):
393
+ def _panda_tidy(fgs_composite: HyperionFlyScanXRayCentreComposite):
448
394
  group = "panda_flyscan_tidy"
449
395
  LOGGER.info("Disabling panda blocks")
450
396
  yield from disarm_panda_for_gridscan(fgs_composite.panda, group)
@@ -454,7 +400,7 @@ def _panda_tidy(fgs_composite: FlyScanXRayCentreComposite):
454
400
 
455
401
 
456
402
  def _zebra_triggering_setup(
457
- fgs_composite: FlyScanXRayCentreComposite,
403
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
458
404
  parameters: HyperionSpecifiedThreeDGridScan,
459
405
  ):
460
406
  yield from setup_zebra_for_gridscan(
@@ -463,7 +409,7 @@ def _zebra_triggering_setup(
463
409
 
464
410
 
465
411
  def _panda_triggering_setup(
466
- fgs_composite: FlyScanXRayCentreComposite,
412
+ fgs_composite: HyperionFlyScanXRayCentreComposite,
467
413
  parameters: HyperionSpecifiedThreeDGridScan,
468
414
  ):
469
415
  LOGGER.info("Setting up Panda for flyscan")
@@ -498,8 +444,8 @@ def _panda_triggering_setup(
498
444
  )
499
445
 
500
446
  yield from bps.mv(
501
- fgs_composite.panda_fast_grid_scan.time_between_x_steps_ms, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
502
- time_between_x_steps_ms, # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
447
+ fgs_composite.panda_fast_grid_scan.time_between_x_steps_ms,
448
+ time_between_x_steps_ms,
503
449
  )
504
450
 
505
451
  directory_provider_root = Path(parameters.storage_directory)
@@ -39,7 +39,9 @@ from mx_bluesky.common.external_interaction.callbacks.xray_centre.ispyb_callback
39
39
  ispyb_activation_wrapper,
40
40
  )
41
41
  from mx_bluesky.common.parameters.constants import OavConstants
42
+ from mx_bluesky.common.utils.context import device_composite_from_context
42
43
  from mx_bluesky.common.utils.log import LOGGER
44
+ from mx_bluesky.common.xrc_result import XRayCentreEventHandler
43
45
  from mx_bluesky.hyperion.device_setup_plans.manipulate_sample import (
44
46
  move_aperture_if_required,
45
47
  )
@@ -50,10 +52,6 @@ from mx_bluesky.hyperion.experiment_plans.change_aperture_then_move_plan import
50
52
  change_aperture_then_move_to_xtal,
51
53
  )
52
54
  from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
53
- FlyScanXRayCentreComposite as FlyScanXRayCentreComposite,
54
- )
55
- from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
56
- XRayCentreEventHandler,
57
55
  flyscan_xray_centre_no_move,
58
56
  )
59
57
  from mx_bluesky.hyperion.experiment_plans.oav_grid_detection_plan import (
@@ -61,11 +59,13 @@ from mx_bluesky.hyperion.experiment_plans.oav_grid_detection_plan import (
61
59
  grid_detection_plan,
62
60
  )
63
61
  from mx_bluesky.hyperion.parameters.constants import CONST
62
+ from mx_bluesky.hyperion.parameters.device_composites import (
63
+ HyperionFlyScanXRayCentreComposite,
64
+ )
64
65
  from mx_bluesky.hyperion.parameters.gridscan import (
65
66
  GridScanWithEdgeDetect,
66
67
  HyperionSpecifiedThreeDGridScan,
67
68
  )
68
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
69
69
 
70
70
 
71
71
  @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
@@ -167,7 +167,7 @@ def detect_grid_and_do_gridscan(
167
167
  )
168
168
 
169
169
  yield from flyscan_xray_centre_no_move(
170
- FlyScanXRayCentreComposite(
170
+ HyperionFlyScanXRayCentreComposite(
171
171
  aperture_scatterguard=composite.aperture_scatterguard,
172
172
  attenuator=composite.attenuator,
173
173
  backlight=composite.backlight,
@@ -8,11 +8,10 @@ from bluesky.preprocessors import run_decorator, set_run_key_decorator, subs_wra
8
8
  from bluesky.utils import MsgGenerator
9
9
  from dodal.devices.oav.oav_parameters import OAVParameters
10
10
 
11
- import mx_bluesky.hyperion.experiment_plans.common.xrc_result as flyscan_result
11
+ import mx_bluesky.common.xrc_result as flyscan_result
12
+ from mx_bluesky.common.utils.context import device_composite_from_context
12
13
  from mx_bluesky.common.utils.log import LOGGER
13
- from mx_bluesky.hyperion.experiment_plans.flyscan_xray_centre_plan import (
14
- XRayCentreEventHandler,
15
- )
14
+ from mx_bluesky.common.xrc_result import XRayCentreEventHandler
16
15
  from mx_bluesky.hyperion.experiment_plans.robot_load_then_centre_plan import (
17
16
  RobotLoadThenCentreComposite,
18
17
  robot_load_then_xray_centre,
@@ -24,7 +23,6 @@ from mx_bluesky.hyperion.experiment_plans.rotation_scan_plan import (
24
23
  )
25
24
  from mx_bluesky.hyperion.parameters.constants import CONST
26
25
  from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
27
- from mx_bluesky.hyperion.utils.context import device_composite_from_context
28
26
 
29
27
 
30
28
  @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})