mx-bluesky 1.4.9__py3-none-any.whl → 1.5.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 (57) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/i24/serial/__init__.py +4 -2
  3. mx_bluesky/beamlines/i24/serial/blueapi_config.yaml +4 -0
  4. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +8 -8
  5. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +36 -4
  6. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +6 -5
  7. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +2 -2
  8. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +5 -5
  9. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +79 -10
  10. mx_bluesky/common/device_setup_plans/manipulate_sample.py +4 -1
  11. mx_bluesky/common/device_setup_plans/robot_load_unload.py +123 -0
  12. mx_bluesky/common/device_setup_plans/utils.py +49 -0
  13. mx_bluesky/common/{plans → experiment_plans}/common_flyscan_xray_centre_plan.py +12 -19
  14. mx_bluesky/{hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py → common/experiment_plans/common_grid_detect_then_xray_centre_plan.py} +108 -136
  15. mx_bluesky/common/{plans → experiment_plans}/inner_plans/do_fgs.py +1 -1
  16. mx_bluesky/common/experiment_plans/oav_grid_detection_plan.py +5 -13
  17. mx_bluesky/{hyperion → common}/experiment_plans/oav_snapshot_plan.py +5 -2
  18. mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +26 -24
  19. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +0 -1
  20. mx_bluesky/common/external_interaction/nexus/write_nexus.py +2 -2
  21. mx_bluesky/common/parameters/components.py +8 -3
  22. mx_bluesky/common/parameters/constants.py +4 -3
  23. mx_bluesky/common/parameters/device_composites.py +65 -0
  24. mx_bluesky/common/utils/__init__.py +0 -0
  25. mx_bluesky/common/xrc_result.py +25 -2
  26. mx_bluesky/hyperion/device_setup_plans/utils.py +0 -48
  27. mx_bluesky/hyperion/experiment_plans/__init__.py +3 -3
  28. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +3 -3
  29. mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +46 -41
  30. mx_bluesky/hyperion/experiment_plans/hyperion_grid_detect_then_xray_centre_plan.py +60 -0
  31. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +26 -8
  32. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +26 -15
  33. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +21 -75
  34. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +10 -8
  35. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +20 -15
  36. mx_bluesky/hyperion/external_interaction/agamemnon.py +4 -4
  37. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +1 -1
  38. mx_bluesky/hyperion/external_interaction/callbacks/{robot_load → robot_actions}/ispyb_callback.py +28 -19
  39. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +1 -1
  40. mx_bluesky/hyperion/external_interaction/callbacks/snapshot_callback.py +3 -0
  41. mx_bluesky/hyperion/external_interaction/config_server.py +0 -11
  42. mx_bluesky/hyperion/parameters/constants.py +1 -6
  43. mx_bluesky/hyperion/parameters/device_composites.py +5 -27
  44. mx_bluesky/hyperion/parameters/gridscan.py +2 -6
  45. mx_bluesky/hyperion/parameters/load_centre_collect.py +15 -0
  46. mx_bluesky/hyperion/parameters/rotation.py +7 -3
  47. {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/METADATA +5 -4
  48. {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/RECORD +56 -52
  49. mx_bluesky/hyperion/utils/validation.py +0 -196
  50. /mx_bluesky/common/{plans → experiment_plans}/__init__.py +0 -0
  51. /mx_bluesky/common/{plans → experiment_plans}/inner_plans/__init__ .py +0 -0
  52. /mx_bluesky/common/{plans → experiment_plans}/read_hardware.py +0 -0
  53. /mx_bluesky/common/{plans → experiment_plans}/write_sample_status.py +0 -0
  54. {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/WHEEL +0 -0
  55. {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/entry_points.txt +0 -0
  56. {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/licenses/LICENSE +0 -0
  57. {mx_bluesky-1.4.9.dist-info → mx_bluesky-1.5.1.dist-info}/top_level.txt +0 -0
mx_bluesky/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '1.4.9'
21
- __version_tuple__ = version_tuple = (1, 4, 9)
20
+ __version__ = version = '1.5.1'
21
+ __version_tuple__ = version_tuple = (1, 5, 1)
@@ -2,7 +2,8 @@ from mx_bluesky.beamlines.i24.serial.web_gui_plans.general_plans import (
2
2
  gui_gonio_move_on_click,
3
3
  gui_move_backlight,
4
4
  gui_move_detector,
5
- gui_set_parameters,
5
+ gui_run_chip_collection,
6
+ gui_set_zoom_level,
6
7
  gui_sleep,
7
8
  gui_stage_move_on_click,
8
9
  )
@@ -57,6 +58,7 @@ __all__ = [
57
58
  "gui_gonio_move_on_click",
58
59
  "gui_sleep",
59
60
  "gui_move_detector",
60
- "gui_set_parameters",
61
+ "gui_run_chip_collection",
61
62
  "gui_move_backlight",
63
+ "gui_set_zoom_level",
62
64
  ]
@@ -8,6 +8,10 @@ env:
8
8
  broadcast_status_events: false
9
9
  api:
10
10
  port: 25565
11
+ cors:
12
+ allow_credentials: True
13
+ origins:
14
+ - "*"
11
15
  stomp:
12
16
  enabled: true
13
17
  host: i24-control.diamond.ac.uk
@@ -23,8 +23,8 @@ from dodal.devices.i24.beamstop import Beamstop
23
23
  from dodal.devices.i24.dcm import DCM
24
24
  from dodal.devices.i24.dual_backlight import DualBacklight
25
25
  from dodal.devices.i24.focus_mirrors import FocusMirrorsMode
26
- from dodal.devices.i24.i24_detector_motion import DetectorMotion
27
26
  from dodal.devices.i24.pilatus_metadata import PilatusMetadata
27
+ from dodal.devices.motors import YZStage
28
28
  from dodal.devices.zebra.zebra import Zebra
29
29
 
30
30
  from mx_bluesky.beamlines.i24.serial.dcid import (
@@ -70,7 +70,7 @@ def flush_print(text):
70
70
 
71
71
  @log_on_entry
72
72
  def initialise_extruder(
73
- detector_stage: DetectorMotion = inject("detector_motion"),
73
+ detector_stage: YZStage = inject("detector_motion"),
74
74
  ) -> MsgGenerator:
75
75
  SSX_LOGGER.info("Initialise Parameters for extruder data collection on I24.")
76
76
 
@@ -98,7 +98,7 @@ def initialise_extruder(
98
98
  def laser_check(
99
99
  mode: str,
100
100
  zebra: Zebra = inject("zebra"),
101
- detector_stage: DetectorMotion = inject("detector_motion"),
101
+ detector_stage: YZStage = inject("detector_motion"),
102
102
  ) -> MsgGenerator:
103
103
  """Plan to open the shutter and check the laser beam from the viewer by pressing \
104
104
  'Laser On' and 'Laser Off' buttons on the edm.
@@ -138,7 +138,7 @@ def laser_check(
138
138
 
139
139
  @log_on_entry
140
140
  def enter_hutch(
141
- detector_stage: DetectorMotion = inject("detector_motion"),
141
+ detector_stage: YZStage = inject("detector_motion"),
142
142
  ) -> MsgGenerator:
143
143
  """Move the detector stage before entering hutch."""
144
144
  yield from bps.mv(detector_stage.z, SAFE_DET_Z)
@@ -146,12 +146,12 @@ def enter_hutch(
146
146
 
147
147
 
148
148
  @log_on_entry
149
- def read_parameters(detector_stage: DetectorMotion, attenuator: ReadOnlyAttenuator):
149
+ def read_parameters(detector_stage: YZStage, attenuator: ReadOnlyAttenuator):
150
150
  """ Read the parameters from user input and create the parameter model for an \
151
151
  extruder collection.
152
152
 
153
153
  Args:
154
- detector_stage (DetectorMotion): The detector stage device.
154
+ detector_stage (YZStage): The detector stage device.
155
155
  attenuator (ReadOnlyAttenuator): A read-only attenuator device to get the \
156
156
  transmission value.
157
157
 
@@ -208,7 +208,7 @@ def main_extruder_plan(
208
208
  aperture: Aperture,
209
209
  backlight: DualBacklight,
210
210
  beamstop: Beamstop,
211
- detector_stage: DetectorMotion,
211
+ detector_stage: YZStage,
212
212
  shutter: HutchShutter,
213
213
  dcm: DCM,
214
214
  mirrors: FocusMirrorsMode,
@@ -500,7 +500,7 @@ def run_extruder_plan(
500
500
  aperture: Aperture = inject("aperture"),
501
501
  backlight: DualBacklight = inject("backlight"),
502
502
  beamstop: Beamstop = inject("beamstop"),
503
- detector_stage: DetectorMotion = inject("detector_motion"),
503
+ detector_stage: YZStage = inject("detector_motion"),
504
504
  shutter: HutchShutter = inject("shutter"),
505
505
  dcm: DCM = inject("dcm"),
506
506
  mirrors: FocusMirrorsMode = inject("focus_mirrors"),
@@ -18,9 +18,9 @@ from dodal.devices.i24.beamstop import Beamstop
18
18
  from dodal.devices.i24.dcm import DCM
19
19
  from dodal.devices.i24.dual_backlight import DualBacklight
20
20
  from dodal.devices.i24.focus_mirrors import FocusMirrorsMode
21
- from dodal.devices.i24.i24_detector_motion import DetectorMotion
22
21
  from dodal.devices.i24.pilatus_metadata import PilatusMetadata
23
22
  from dodal.devices.i24.pmac import PMAC
23
+ from dodal.devices.motors import YZStage
24
24
  from dodal.devices.zebra.zebra import Zebra
25
25
 
26
26
  from mx_bluesky.beamlines.i24.serial.dcid import (
@@ -269,7 +269,7 @@ def start_i24(
269
269
  aperture: Aperture,
270
270
  backlight: DualBacklight,
271
271
  beamstop: Beamstop,
272
- detector_stage: DetectorMotion,
272
+ detector_stage: YZStage,
273
273
  shutter: HutchShutter,
274
274
  parameters: FixedTargetParameters,
275
275
  dcm: DCM,
@@ -504,7 +504,7 @@ def main_fixed_target_plan(
504
504
  aperture: Aperture,
505
505
  backlight: DualBacklight,
506
506
  beamstop: Beamstop,
507
- detector_stage: DetectorMotion,
507
+ detector_stage: YZStage,
508
508
  shutter: HutchShutter,
509
509
  dcm: DCM,
510
510
  mirrors: FocusMirrorsMode,
@@ -655,7 +655,7 @@ def run_fixed_target_plan(
655
655
  aperture: Aperture = inject("aperture"),
656
656
  backlight: DualBacklight = inject("backlight"),
657
657
  beamstop: Beamstop = inject("beamstop"),
658
- detector_stage: DetectorMotion = inject("detector_motion"),
658
+ detector_stage: YZStage = inject("detector_motion"),
659
659
  shutter: HutchShutter = inject("shutter"),
660
660
  dcm: DCM = inject("dcm"),
661
661
  mirrors: FocusMirrorsMode = inject("focus_mirrors"),
@@ -684,6 +684,38 @@ def run_fixed_target_plan(
684
684
  # DCID instance - do not create yet
685
685
  dcid = DCID(emit_errors=False, expt_params=parameters)
686
686
 
687
+ yield from run_plan_in_wrapper(
688
+ zebra,
689
+ pmac,
690
+ aperture,
691
+ backlight,
692
+ beamstop,
693
+ detector_stage,
694
+ shutter,
695
+ dcm,
696
+ mirrors,
697
+ beam_center_device,
698
+ parameters,
699
+ dcid,
700
+ pilatus_metadata,
701
+ )
702
+
703
+
704
+ def run_plan_in_wrapper(
705
+ zebra: Zebra,
706
+ pmac: PMAC,
707
+ aperture: Aperture,
708
+ backlight: DualBacklight,
709
+ beamstop: Beamstop,
710
+ detector_stage: YZStage,
711
+ shutter: HutchShutter,
712
+ dcm: DCM,
713
+ mirrors: FocusMirrorsMode,
714
+ beam_center_device: DetectorBeamCenter,
715
+ parameters: FixedTargetParameters,
716
+ dcid: DCID,
717
+ pilatus_metadata: PilatusMetadata,
718
+ ) -> MsgGenerator:
687
719
  yield from bpp.contingency_wrapper(
688
720
  main_fixed_target_plan(
689
721
  zebra,
@@ -16,8 +16,8 @@ from dodal.common import inject
16
16
  from dodal.devices.attenuator.attenuator import ReadOnlyAttenuator
17
17
  from dodal.devices.i24.beamstop import Beamstop, BeamstopPositions
18
18
  from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
19
- from dodal.devices.i24.i24_detector_motion import DetectorMotion
20
19
  from dodal.devices.i24.pmac import PMAC, EncReset, LaserSettings
20
+ from dodal.devices.motors import YZStage
21
21
 
22
22
  from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
23
23
  ChipType,
@@ -121,14 +121,14 @@ def _is_checker_pattern() -> bool:
121
121
 
122
122
  @log_on_entry
123
123
  def read_parameters(
124
- detector_stage: DetectorMotion,
124
+ detector_stage: YZStage,
125
125
  attenuator: ReadOnlyAttenuator,
126
126
  ) -> MsgGenerator:
127
127
  """ Read the parameters from user input and create the parameter model for a fixed \
128
128
  target collection.
129
129
 
130
130
  Args:
131
- detector_stage (DetectorMotion): The detector stage device.
131
+ detector_stage (YZStage): The detector stage device.
132
132
  attenuator (ReadOnlyAttenuator): A read-only attenuator device to get the \
133
133
  transmission value.
134
134
 
@@ -256,6 +256,7 @@ def upload_chip_map_to_geobrick(pmac: PMAC, chip_map: list[int]) -> MsgGenerator
256
256
  """
257
257
  SSX_LOGGER.info("Uploading Parameters for Oxford Chip to the GeoBrick")
258
258
  SSX_LOGGER.info(f"Chipid {ChipType.Oxford}, width {OXFORD_CHIP_WIDTH}")
259
+ SSX_LOGGER.warning(f"MAP TO UPLOAD: {chip_map}")
259
260
  for block in range(1, 65):
260
261
  value = 1 if block in chip_map else 0
261
262
  pvar = PVAR_TEMPLATE % block
@@ -264,7 +265,7 @@ def upload_chip_map_to_geobrick(pmac: PMAC, chip_map: list[int]) -> MsgGenerator
264
265
  yield from bps.abs_set(pmac.pmac_string, pvar_str, wait=True)
265
266
  # Wait for PMAC to be done processing PVAR string
266
267
  yield from bps.sleep(0.02)
267
- SSX_LOGGER.debug("Upload parameters done.")
268
+ SSX_LOGGER.info("Upload parameters done.")
268
269
 
269
270
 
270
271
  @log_on_entry
@@ -565,7 +566,7 @@ def moveto_preset(
565
566
  pmac: PMAC = inject("pmac"),
566
567
  beamstop: Beamstop = inject("beamstop"),
567
568
  backlight: DualBacklight = inject("backlight"),
568
- det_stage: DetectorMotion = inject("detector_motion"),
569
+ det_stage: YZStage = inject("detector_motion"),
569
570
  ) -> MsgGenerator:
570
571
  # Non Chip Specific Move
571
572
  if place == "zero":
@@ -7,7 +7,7 @@ from dodal.devices.i24.beam_center import DetectorBeamCenter
7
7
  from dodal.devices.i24.beamstop import Beamstop, BeamstopPositions
8
8
  from dodal.devices.i24.dcm import DCM
9
9
  from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
10
- from dodal.devices.i24.i24_detector_motion import DetectorMotion
10
+ from dodal.devices.motors import YZStage
11
11
  from dodal.devices.util.lookup_tables import (
12
12
  linear_interpolation_lut,
13
13
  parse_lookup_table,
@@ -69,7 +69,7 @@ def setup_beamline_for_collection_plan(
69
69
 
70
70
 
71
71
  def move_detector_stage_to_position_plan(
72
- detector_stage: DetectorMotion,
72
+ detector_stage: YZStage,
73
73
  detector_distance: float,
74
74
  ):
75
75
  SSX_LOGGER.debug("Setup beamline: moving detector stage.")
@@ -8,7 +8,7 @@ from enum import IntEnum
8
8
  import bluesky.plan_stubs as bps
9
9
  from bluesky.utils import Msg, MsgGenerator
10
10
  from dodal.common import inject
11
- from dodal.devices.i24.i24_detector_motion import DetectorMotion
11
+ from dodal.devices.motors import YZStage
12
12
 
13
13
  from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER
14
14
  from mx_bluesky.beamlines.i24.serial.parameters import SSXType
@@ -38,9 +38,9 @@ class UnknownDetectorType(Exception):
38
38
  pass
39
39
 
40
40
 
41
- def get_detector_type(detector_stage: DetectorMotion) -> Generator[Msg, None, Detector]:
41
+ def get_detector_type(detector_stage: YZStage) -> Generator[Msg, None, Detector]:
42
42
  det_y = yield from bps.rd(detector_stage.y)
43
- # DetectorMotion should also be used for this.
43
+ # YZStage should also be used for this.
44
44
  # This should be part of https://github.com/DiamondLightSource/mx_bluesky/issues/51
45
45
  if float(det_y) < Eiger.det_y_threshold:
46
46
  SSX_LOGGER.info("Eiger detector in use.")
@@ -53,7 +53,7 @@ def get_detector_type(detector_stage: DetectorMotion) -> Generator[Msg, None, De
53
53
  raise UnknownDetectorType("Detector not found.")
54
54
 
55
55
 
56
- def _move_detector_stage(detector_stage: DetectorMotion, target: float) -> MsgGenerator:
56
+ def _move_detector_stage(detector_stage: YZStage, target: float) -> MsgGenerator:
57
57
  SSX_LOGGER.info(f"Moving detector stage to target position: {target}.")
58
58
  yield from bps.mv(detector_stage.y, target)
59
59
 
@@ -82,7 +82,7 @@ def _get_requested_detector(det_type_pv: str) -> str:
82
82
 
83
83
 
84
84
  def setup_detector_stage(
85
- expt_type: SSXType, detector_stage: DetectorMotion = inject("detector_motion")
85
+ expt_type: SSXType, detector_stage: YZStage = inject("detector_motion")
86
86
  ) -> MsgGenerator:
87
87
  # Grab the correct PV depending on experiment
88
88
  # Its value is set with MUX on edm screen
@@ -3,19 +3,34 @@ from typing import Literal
3
3
 
4
4
  import bluesky.plan_stubs as bps
5
5
  import bluesky.preprocessors as bpp
6
- from blueapi.core import MsgGenerator
6
+ from bluesky.utils import MsgGenerator
7
7
  from dodal.beamlines import i24
8
8
  from dodal.common import inject
9
+ from dodal.devices.hutch_shutter import HutchShutter
10
+ from dodal.devices.i24.aperture import Aperture
11
+ from dodal.devices.i24.beam_center import DetectorBeamCenter
12
+ from dodal.devices.i24.beamstop import Beamstop
13
+ from dodal.devices.i24.dcm import DCM
9
14
  from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
10
- from dodal.devices.i24.i24_detector_motion import DetectorMotion
15
+ from dodal.devices.i24.focus_mirrors import FocusMirrorsMode
16
+ from dodal.devices.i24.pilatus_metadata import PilatusMetadata
11
17
  from dodal.devices.i24.pmac import PMAC
12
- from dodal.devices.oav.oav_detector import OAV
18
+ from dodal.devices.motors import YZStage
19
+ from dodal.devices.oav.oav_detector import OAVBeamCentreFile
20
+ from dodal.devices.zebra.zebra import Zebra
13
21
 
22
+ from mx_bluesky.beamlines.i24.serial.dcid import DCID
14
23
  from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
15
24
  ChipType,
16
25
  MappingType,
17
26
  PumpProbeSetting,
18
27
  )
28
+ from mx_bluesky.beamlines.i24.serial.fixed_target.i24ssx_Chip_Collect_py3v1 import (
29
+ run_plan_in_wrapper,
30
+ )
31
+ from mx_bluesky.beamlines.i24.serial.fixed_target.i24ssx_Chip_Manager_py3v1 import (
32
+ upload_chip_map_to_geobrick,
33
+ )
19
34
  from mx_bluesky.beamlines.i24.serial.fixed_target.i24ssx_moveonclick import (
20
35
  _move_on_mouse_click_plan,
21
36
  )
@@ -24,6 +39,7 @@ from mx_bluesky.beamlines.i24.serial.log import (
24
39
  _read_visit_directory_from_file,
25
40
  )
26
41
  from mx_bluesky.beamlines.i24.serial.parameters import (
42
+ DetectorName,
27
43
  FixedTargetParameters,
28
44
  get_chip_format,
29
45
  )
@@ -46,9 +62,19 @@ def gui_move_backlight(
46
62
  SSX_LOGGER.debug(f"Backlight moved to {bl_pos.value}")
47
63
 
48
64
 
65
+ @bpp.run_decorator()
66
+ def gui_set_zoom_level(
67
+ position: str, oav: OAVBeamCentreFile = inject("oav")
68
+ ) -> MsgGenerator:
69
+ yield from bps.abs_set(oav.zoom_controller, position, wait=True)
70
+ SSX_LOGGER.debug(f"Setting zoom level to {position}")
71
+
72
+
49
73
  @bpp.run_decorator()
50
74
  def gui_stage_move_on_click(
51
- position_px: tuple[int, int], oav: OAV = inject("oav"), pmac: PMAC = inject("pmac")
75
+ position_px: tuple[int, int],
76
+ oav: OAVBeamCentreFile = inject("oav"),
77
+ pmac: PMAC = inject("pmac"),
52
78
  ) -> MsgGenerator:
53
79
  yield from _move_on_mouse_click_plan(oav, pmac, position_px)
54
80
 
@@ -78,7 +104,7 @@ def gui_sleep(sec: int) -> MsgGenerator:
78
104
  @bpp.run_decorator()
79
105
  def gui_move_detector(
80
106
  det: Literal["eiger", "pilatus"],
81
- detector_stage: DetectorMotion = inject("detector_motion"),
107
+ detector_stage: YZStage = inject("detector_motion"),
82
108
  ) -> MsgGenerator:
83
109
  det_y_target = Eiger.det_y_target if det == "eiger" else Pilatus.det_y_target
84
110
  yield from _move_detector_stage(detector_stage, det_y_target)
@@ -88,7 +114,7 @@ def gui_move_detector(
88
114
 
89
115
 
90
116
  @bpp.run_decorator()
91
- def gui_set_parameters(
117
+ def gui_run_chip_collection(
92
118
  sub_dir: str,
93
119
  chip_name: str,
94
120
  exp_time: float,
@@ -103,6 +129,18 @@ def gui_set_parameters(
103
129
  laser_dwell: float,
104
130
  laser_delay: float,
105
131
  pre_pump: float,
132
+ pmac: PMAC = inject("pmac"),
133
+ zebra: Zebra = inject("zebra"),
134
+ aperture: Aperture = inject("aperture"),
135
+ backlight: DualBacklight = inject("backlight"),
136
+ beamstop: Beamstop = inject("beamstop"),
137
+ detector_stage: YZStage = inject("detector_motion"),
138
+ shutter: HutchShutter = inject("shutter"),
139
+ dcm: DCM = inject("dcm"),
140
+ mirrors: FocusMirrorsMode = inject("focus_mirrors"),
141
+ beam_center_pilatus: DetectorBeamCenter = inject("pilatus_bc"),
142
+ beam_center_eiger: DetectorBeamCenter = inject("eiger_bc"),
143
+ pilatus_metadata: PilatusMetadata = inject("pilatus_meta"),
106
144
  ) -> MsgGenerator:
107
145
  """Set the parameter model for the data collection.
108
146
 
@@ -132,7 +170,6 @@ def gui_set_parameters(
132
170
  """
133
171
  # NOTE still a work in progress, adding to it as the ui grows
134
172
  # See progression of https://github.com/DiamondLightSource/mx-daq-ui/issues/3
135
- detector_stage = i24.detector_motion()
136
173
  det_type = yield from get_detector_type(detector_stage)
137
174
  _format = chip_format if ChipType[chip_type] is ChipType.Custom else None
138
175
  chip_params = get_chip_format(ChipType[chip_type], _format)
@@ -164,6 +201,38 @@ def gui_set_parameters(
164
201
  "checker_pattern": checker_pattern,
165
202
  "pre_pump_exposure_s": pre_pump,
166
203
  }
167
- # TODO run the run_fixed_target plan once params are set (GUI not ready yet)
168
- yield from bps.sleep(0.5)
169
- return FixedTargetParameters(**params)
204
+
205
+ parameters = FixedTargetParameters(**params)
206
+
207
+ # Create collection directory
208
+ parameters.collection_directory.mkdir(parents=True, exist_ok=True)
209
+
210
+ if parameters.chip_map:
211
+ yield from upload_chip_map_to_geobrick(pmac, parameters.chip_map)
212
+
213
+ beam_center_device = (
214
+ beam_center_eiger
215
+ if parameters.detector_name is DetectorName.EIGER
216
+ else beam_center_pilatus
217
+ )
218
+ SSX_LOGGER.info("Beam center device ready")
219
+
220
+ # DCID instance - do not create yet
221
+ dcid = DCID(emit_errors=False, expt_params=parameters) # noqa
222
+ SSX_LOGGER.info("DCID created")
223
+
224
+ yield from run_plan_in_wrapper(
225
+ zebra,
226
+ pmac,
227
+ aperture,
228
+ backlight,
229
+ beamstop,
230
+ detector_stage,
231
+ shutter,
232
+ dcm,
233
+ mirrors,
234
+ beam_center_device,
235
+ parameters,
236
+ dcid,
237
+ pilatus_metadata,
238
+ )
@@ -10,6 +10,7 @@ from dodal.devices.detector.detector_motion import DetectorMotion
10
10
  from dodal.devices.smargon import CombinedMove, Smargon
11
11
 
12
12
  from mx_bluesky.common.utils.log import LOGGER
13
+ from mx_bluesky.hyperion.parameters.constants import CONST
13
14
 
14
15
  LOWER_DETECTOR_SHUTTER_AFTER_SCAN = True
15
16
 
@@ -21,6 +22,8 @@ def setup_sample_environment(
21
22
  group="setup_senv",
22
23
  ):
23
24
  """Move the aperture into required position, move out the backlight."""
25
+ yield from bps.abs_set(backlight, BacklightPosition.OUT, group=group)
26
+
24
27
  aperture_value = (
25
28
  None
26
29
  if not aperture_position_gda_name
@@ -29,7 +32,6 @@ def setup_sample_environment(
29
32
  yield from move_aperture_if_required(
30
33
  aperture_scatterguard, aperture_value, group=group
31
34
  )
32
- yield from bps.abs_set(backlight, BacklightPosition.OUT, group=group)
33
35
 
34
36
 
35
37
  def move_aperture_if_required(
@@ -46,6 +48,7 @@ def move_aperture_if_required(
46
48
 
47
49
  else:
48
50
  LOGGER.info(f"Setting aperture position to {aperture_value}")
51
+ yield from bps.wait(CONST.WAIT.PREPARE_APERTURE)
49
52
  yield from bps.abs_set(
50
53
  aperture_scatterguard.selected_aperture,
51
54
  aperture_value,
@@ -0,0 +1,123 @@
1
+ from __future__ import annotations
2
+
3
+ import bluesky.plan_stubs as bps
4
+ import bluesky.preprocessors as bpp
5
+ from bluesky.utils import MsgGenerator
6
+ from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureValue
7
+ from dodal.devices.motors import XYZStage
8
+ from dodal.devices.robot import BartRobot
9
+ from dodal.devices.smargon import CombinedMove, Smargon, StubPosition
10
+ from dodal.plan_stubs.motor_utils import MoveTooLarge, home_and_reset_wrapper
11
+
12
+ from mx_bluesky.common.utils.log import LOGGER
13
+ from mx_bluesky.hyperion.parameters.constants import CONST
14
+
15
+
16
+ def wait_for_smargon_not_disabled(smargon: Smargon, timeout=60):
17
+ """Waits for the smargon disabled flag to go low. The robot hardware is responsible
18
+ for setting this to low when it is safe to move. It does this through a physical
19
+ connection between the robot and the smargon.
20
+ """
21
+ LOGGER.info("Waiting for smargon enabled")
22
+ SLEEP_PER_CHECK = 0.1
23
+ times_to_check = int(timeout / SLEEP_PER_CHECK)
24
+ for _ in range(times_to_check):
25
+ smargon_disabled = yield from bps.rd(smargon.disabled)
26
+ if not smargon_disabled:
27
+ LOGGER.info("Smargon now enabled")
28
+ return
29
+ yield from bps.sleep(SLEEP_PER_CHECK)
30
+ raise TimeoutError(
31
+ "Timed out waiting for smargon to become enabled after robot load"
32
+ )
33
+
34
+
35
+ def _raise_exception_if_moved_out_of_cryojet(exception):
36
+ yield from bps.null()
37
+ if isinstance(exception, MoveTooLarge):
38
+ raise Exception(
39
+ f"Moving {exception.axis} back to {exception.position} after \
40
+ robot load would move it out of the cryojet. The max safe \
41
+ distance is {exception.maximum_move}"
42
+ )
43
+
44
+
45
+ def do_plan_while_lower_gonio_at_home(plan: MsgGenerator, lower_gonio: XYZStage):
46
+ """Moves the lower gonio to home then performs the provided plan and moves it back.
47
+
48
+ The lower gonio must be in the correct position for the robot load and we
49
+ want to put it back afterwards. Note we don't need to wait for the move as the robot
50
+ is interlocked to the lower gonio and the move is quicker than the robot takes to
51
+ get to the load position.
52
+
53
+ Args:
54
+ plan (MsgGenerator): The plan to run while the lower gonio is at home.
55
+ lower_gonio (XYZStage): The lower gonio to home.
56
+ """
57
+ yield from bpp.contingency_wrapper(
58
+ home_and_reset_wrapper(
59
+ plan,
60
+ lower_gonio,
61
+ BartRobot.LOAD_TOLERANCE_MM,
62
+ CONST.HARDWARE.CRYOJET_MARGIN_MM,
63
+ "lower_gonio",
64
+ wait_for_all=False,
65
+ ),
66
+ except_plan=_raise_exception_if_moved_out_of_cryojet,
67
+ )
68
+ return "reset-lower_gonio"
69
+
70
+
71
+ def prepare_for_robot_load(
72
+ aperture_scatterguard: ApertureScatterguard, smargon: Smargon
73
+ ):
74
+ yield from bps.abs_set(
75
+ aperture_scatterguard.selected_aperture,
76
+ ApertureValue.OUT_OF_BEAM,
77
+ group="prepare_robot_load",
78
+ )
79
+
80
+ yield from bps.mv(smargon.stub_offsets, StubPosition.RESET_TO_ROBOT_LOAD)
81
+
82
+ yield from bps.mv(smargon, CombinedMove(x=0, y=0, z=0, chi=0, phi=0, omega=0))
83
+
84
+ yield from bps.wait("prepare_robot_load")
85
+
86
+
87
+ def robot_unload(
88
+ robot: BartRobot,
89
+ smargon: Smargon,
90
+ aperture_scatterguard: ApertureScatterguard,
91
+ lower_gonio: XYZStage,
92
+ visit: str,
93
+ ):
94
+ """Unloads the currently mounted pin into the location that it was loaded from. The
95
+ loaded location is stored on the robot and so need not be provided.
96
+ """
97
+ yield from prepare_for_robot_load(aperture_scatterguard, smargon)
98
+ sample_id = yield from bps.rd(robot.sample_id)
99
+
100
+ @bpp.run_decorator(
101
+ md={
102
+ "subplan_name": CONST.PLAN.ROBOT_UNLOAD,
103
+ "metadata": {"visit": visit, "sample_id": sample_id},
104
+ "activate_callbacks": [
105
+ "RobotLoadISPyBCallback",
106
+ ],
107
+ },
108
+ )
109
+ def do_robot_unload_and_send_to_ispyb():
110
+ yield from bps.create(name=CONST.DESCRIPTORS.ROBOT_UPDATE)
111
+ yield from bps.read(robot)
112
+ yield from bps.save()
113
+
114
+ def _unload():
115
+ yield from bps.trigger(robot.unload, wait=True)
116
+ yield from wait_for_smargon_not_disabled(smargon)
117
+
118
+ gonio_finished = yield from do_plan_while_lower_gonio_at_home(
119
+ _unload(), lower_gonio
120
+ )
121
+ yield from bps.wait(gonio_finished)
122
+
123
+ yield from do_robot_unload_and_send_to_ispyb()
@@ -0,0 +1,49 @@
1
+ from collections.abc import Generator
2
+
3
+ from bluesky import plan_stubs as bps
4
+ from bluesky import preprocessors as bpp
5
+ from bluesky.utils import Msg
6
+ from dodal.devices.detector.detector_motion import DetectorMotion, ShutterState
7
+ from dodal.devices.eiger import EigerDetector
8
+ from dodal.devices.mx_phase1.beamstop import Beamstop, BeamstopPositions
9
+
10
+ from mx_bluesky.common.device_setup_plans.position_detector import (
11
+ set_detector_z_position,
12
+ set_shutter,
13
+ )
14
+
15
+
16
+ def start_preparing_data_collection_then_do_plan(
17
+ beamstop: Beamstop,
18
+ eiger: EigerDetector,
19
+ detector_motion: DetectorMotion,
20
+ detector_distance_mm: float | None,
21
+ plan_to_run: Generator[Msg, None, None],
22
+ group="ready_for_data_collection",
23
+ ) -> Generator[Msg, None, None]:
24
+ """Starts preparing for the next data collection and then runs the
25
+ given plan.
26
+
27
+ Preparation consists of:
28
+ * Arming the Eiger
29
+ * Moving the detector to the specified position
30
+ * Opening the detect shutter
31
+ If the plan fails it will disarm the eiger.
32
+ """
33
+
34
+ def wrapped_plan():
35
+ 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)
36
+ yield from bps.abs_set(
37
+ beamstop.selected_pos, BeamstopPositions.DATA_COLLECTION, group=group
38
+ )
39
+ if detector_distance_mm:
40
+ yield from set_detector_z_position(
41
+ detector_motion, detector_distance_mm, group
42
+ )
43
+ yield from set_shutter(detector_motion, ShutterState.OPEN, group)
44
+ yield from plan_to_run
45
+
46
+ yield from bpp.contingency_wrapper(
47
+ wrapped_plan(),
48
+ except_plan=lambda e: (yield from bps.stop(eiger)), # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
49
+ )