mx-bluesky 1.4.3__py3-none-any.whl → 1.4.5__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 (38) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +2 -2
  3. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +2 -2
  4. mx_bluesky/common/device_setup_plans/setup_panda.py +9 -0
  5. mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py +4 -15
  6. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +9 -1
  7. mx_bluesky/common/parameters/components.py +0 -1
  8. mx_bluesky/common/parameters/constants.py +16 -0
  9. mx_bluesky/common/parameters/gridscan.py +6 -1
  10. mx_bluesky/common/plans/do_fgs.py +0 -6
  11. mx_bluesky/common/utils/exceptions.py +2 -1
  12. mx_bluesky/definitions.py +4 -0
  13. mx_bluesky/hyperion/__main__.py +8 -43
  14. mx_bluesky/hyperion/device_setup_plans/setup_panda.py +9 -8
  15. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +10 -0
  16. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +0 -15
  17. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +11 -8
  18. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +8 -0
  19. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +23 -16
  20. mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +1 -5
  21. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +1 -8
  22. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +12 -4
  23. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -0
  24. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +24 -5
  25. mx_bluesky/hyperion/external_interaction/config_server.py +13 -2
  26. mx_bluesky/hyperion/parameters/cli.py +1 -9
  27. mx_bluesky/hyperion/parameters/constants.py +6 -1
  28. mx_bluesky/hyperion/parameters/gridscan.py +5 -5
  29. mx_bluesky/hyperion/resources/panda/panda-gridscan.yaml +1006 -964
  30. mx_bluesky/hyperion/utils/validation.py +20 -17
  31. {mx_bluesky-1.4.3.dist-info → mx_bluesky-1.4.5.dist-info}/METADATA +3 -3
  32. {mx_bluesky-1.4.3.dist-info → mx_bluesky-1.4.5.dist-info}/RECORD +36 -36
  33. mx_bluesky/hyperion/external_interaction/callbacks/common/__init__.py +0 -0
  34. mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +0 -80
  35. {mx_bluesky-1.4.3.dist-info → mx_bluesky-1.4.5.dist-info}/LICENSE +0 -0
  36. {mx_bluesky-1.4.3.dist-info → mx_bluesky-1.4.5.dist-info}/WHEEL +0 -0
  37. {mx_bluesky-1.4.3.dist-info → mx_bluesky-1.4.5.dist-info}/entry_points.txt +0 -0
  38. {mx_bluesky-1.4.3.dist-info → mx_bluesky-1.4.5.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Sequence
4
-
3
+ import bluesky.plan_stubs as bps
4
+ import numpy as np
5
5
  import pydantic
6
6
  from blueapi.core import BlueskyContext
7
7
  from bluesky.preprocessors import run_decorator, set_run_key_decorator, subs_wrapper
@@ -66,33 +66,40 @@ def load_centre_collect_full(
66
66
  flyscan_event_handler,
67
67
  )
68
68
 
69
- assert flyscan_event_handler.xray_centre_results, (
70
- "Flyscan result event not received or no crystal found and exception not raised"
71
- )
69
+ locations_to_collect_um: list[np.ndarray] = []
72
70
 
73
- selection_func = flyscan_result.resolve_selection_fn(
74
- parameters.selection_params
75
- )
76
- hits: Sequence[flyscan_result.XRayCentreResult] = selection_func(
77
- flyscan_event_handler.xray_centre_results
78
- )
79
- LOGGER.info(
80
- f"Selected hits {hits} using {selection_func}, args={parameters.selection_params}"
81
- )
71
+ if flyscan_event_handler.xray_centre_results:
72
+ selection_func = flyscan_result.resolve_selection_fn(
73
+ parameters.selection_params
74
+ )
75
+ hits = selection_func(flyscan_event_handler.xray_centre_results)
76
+ locations_to_collect_um = [hit.centre_of_mass_mm * 1000 for hit in hits]
77
+
78
+ LOGGER.info(
79
+ f"Selected hits {hits} using {selection_func}, args={parameters.selection_params}"
80
+ )
81
+ else:
82
+ # If the xray centring hasn't found a result but has not thrown an error it
83
+ # means that we do not need to recentre and can collect where we are
84
+ initial_x = yield from bps.rd(composite.smargon.x.user_readback)
85
+ initial_y = yield from bps.rd(composite.smargon.y.user_readback)
86
+ initial_z = yield from bps.rd(composite.smargon.z.user_readback)
87
+
88
+ locations_to_collect_um = [np.array([initial_x, initial_y, initial_z])]
82
89
 
83
90
  multi_rotation = parameters.multi_rotation_scan
84
91
  rotation_template = multi_rotation.rotation_scans.copy()
85
92
 
86
93
  multi_rotation.rotation_scans.clear()
87
94
 
88
- for hit in hits:
95
+ for location in locations_to_collect_um:
89
96
  for rot in rotation_template:
90
97
  combination = rot.model_copy()
91
98
  (
92
99
  combination.x_start_um,
93
100
  combination.y_start_um,
94
101
  combination.z_start_um,
95
- ) = (axis * 1000 for axis in hit.centre_of_mass_mm)
102
+ ) = location
96
103
  multi_rotation.rotation_scans.append(combination)
97
104
  multi_rotation = MultiRotationScan.model_validate(multi_rotation)
98
105
 
@@ -34,9 +34,7 @@ def setup_beamline_for_OAV(
34
34
  yield from bps.abs_set(smargon.omega.velocity, max_vel, group=group)
35
35
  yield from bps.abs_set(backlight, BacklightPosition.IN, group=group)
36
36
  yield from bps.abs_set(
37
- aperture_scatterguard,
38
- ApertureValue.ROBOT_LOAD,
39
- group=group,
37
+ aperture_scatterguard, ApertureValue.OUT_OF_BEAM, group=group
40
38
  )
41
39
 
42
40
 
@@ -44,11 +42,9 @@ def oav_snapshot_plan(
44
42
  composite: OavSnapshotComposite,
45
43
  parameters: WithSnapshot,
46
44
  oav_parameters: OAVParameters,
47
- wait: bool = True,
48
45
  ) -> MsgGenerator:
49
46
  if not parameters.take_snapshots:
50
47
  return
51
- yield from bps.wait(group=CONST.WAIT.READY_FOR_OAV)
52
48
  yield from _setup_oav(composite, parameters, oav_parameters)
53
49
  for omega in parameters.snapshot_omegas_deg or []:
54
50
  yield from _take_oav_snapshot(composite, omega)
@@ -95,9 +95,7 @@ def prepare_for_robot_load(
95
95
  aperture_scatterguard: ApertureScatterguard, smargon: Smargon
96
96
  ):
97
97
  yield from bps.abs_set(
98
- aperture_scatterguard,
99
- ApertureValue.ROBOT_LOAD,
100
- group="prepare_robot_load",
98
+ aperture_scatterguard, ApertureValue.OUT_OF_BEAM, group="prepare_robot_load"
101
99
  )
102
100
 
103
101
  yield from bps.mv(smargon.stub_offsets, StubPosition.RESET_TO_ROBOT_LOAD) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809
@@ -122,11 +120,6 @@ def do_robot_load(
122
120
  demand_energy_ev: float | None,
123
121
  thawing_time: float,
124
122
  ):
125
- error_code = yield from bps.rd(composite.robot.error_code)
126
- # Reset robot if light curtains were tripped
127
- if error_code == 40:
128
- yield from bps.trigger(composite.robot.reset, wait=True)
129
-
130
123
  yield from bps.abs_set(
131
124
  composite.robot,
132
125
  sample_location,
@@ -346,6 +346,13 @@ def _move_and_rotation(
346
346
  yield from setup_beamline_for_OAV(
347
347
  composite.smargon, composite.backlight, composite.aperture_scatterguard
348
348
  )
349
+ yield from bps.wait(group=CONST.WAIT.READY_FOR_OAV)
350
+ if params.selected_aperture:
351
+ yield from bps.prepare(
352
+ composite.aperture_scatterguard,
353
+ params.selected_aperture,
354
+ group=CONST.WAIT.ROTATION_READY_FOR_DC,
355
+ )
349
356
  yield from oav_snapshot_plan(composite, params, oav_params)
350
357
  yield from rotation_scan_plan(
351
358
  composite,
@@ -368,8 +375,6 @@ def rotation_scan(
368
375
  @bpp.run_decorator( # attach experiment metadata to the start document
369
376
  md={
370
377
  "subplan_name": CONST.PLAN.ROTATION_OUTER,
371
- CONST.TRIGGER.ZOCALO: CONST.PLAN.ROTATION_MAIN,
372
- "zocalo_environment": CONST.ZOCALO_ENV,
373
378
  "mx_bluesky_parameters": parameters.model_dump_json(),
374
379
  "activate_callbacks": [
375
380
  "RotationISPyBCallback",
@@ -378,8 +383,10 @@ def rotation_scan(
378
383
  }
379
384
  )
380
385
  @transmission_and_xbpm_feedback_for_collection_decorator(
386
+ composite.undulator,
381
387
  composite.xbpm_feedback,
382
388
  composite.attenuator,
389
+ composite.dcm,
383
390
  parameters.transmission_frac,
384
391
  )
385
392
  def rotation_scan_plan_with_stage_and_cleanup(
@@ -429,10 +436,11 @@ def multi_rotation_scan(
429
436
  ],
430
437
  }
431
438
  )
432
- @bpp.stage_decorator([eiger])
433
439
  @transmission_and_xbpm_feedback_for_collection_decorator(
440
+ composite.undulator,
434
441
  composite.xbpm_feedback,
435
442
  composite.attenuator,
443
+ composite.dcm,
436
444
  parameters.transmission_frac,
437
445
  )
438
446
  @bpp.finalize_decorator(lambda: _cleanup_plan(composite))
@@ -443,7 +451,6 @@ def multi_rotation_scan(
443
451
  @bpp.run_decorator( # attach experiment metadata to the start document
444
452
  md={
445
453
  "subplan_name": CONST.PLAN.ROTATION_OUTER,
446
- CONST.TRIGGER.ZOCALO: CONST.PLAN.ROTATION_MAIN,
447
454
  "mx_bluesky_parameters": single_scan.model_dump_json(),
448
455
  }
449
456
  )
@@ -463,3 +470,4 @@ def multi_rotation_scan(
463
470
  _multi_rotation_scan(),
464
471
  group=CONST.WAIT.ROTATION_READY_FOR_DC,
465
472
  )
473
+ yield from bps.unstage(eiger)
@@ -54,7 +54,9 @@ def set_energy_plan(
54
54
  if energy_ev:
55
55
  yield from transmission_and_xbpm_feedback_for_collection_wrapper(
56
56
  _set_energy_plan(energy_ev / 1000, composite),
57
+ composite.undulator_dcm.undulator_ref(),
57
58
  composite.xbpm_feedback,
58
59
  composite.attenuator,
60
+ composite.dcm,
59
61
  DESIRED_TRANSMISSION_FRACTION,
60
62
  )
@@ -3,6 +3,7 @@ from collections.abc import Callable, Sequence
3
3
  from threading import Thread
4
4
  from time import sleep
5
5
 
6
+ from bluesky.callbacks import CallbackBase
6
7
  from bluesky.callbacks.zmq import Proxy, RemoteDispatcher
7
8
  from dodal.log import LOGGER as dodal_logger
8
9
  from dodal.log import set_up_all_logging_handlers
@@ -48,15 +49,33 @@ LIVENESS_POLL_SECONDS = 1
48
49
  ERROR_LOG_BUFFER_LINES = 5000
49
50
 
50
51
 
51
- def setup_callbacks():
52
- zocalo = ZocaloCallback()
53
- return [
52
+ def create_gridscan_callbacks() -> tuple[
53
+ GridscanNexusFileCallback, GridscanISPyBCallback
54
+ ]:
55
+ return (
54
56
  GridscanNexusFileCallback(param_type=HyperionSpecifiedThreeDGridScan),
55
57
  GridscanISPyBCallback(
56
- param_type=GridCommonWithHyperionDetectorParams, emit=zocalo
58
+ param_type=GridCommonWithHyperionDetectorParams,
59
+ emit=ZocaloCallback(CONST.PLAN.DO_FGS, CONST.ZOCALO_ENV),
57
60
  ),
61
+ )
62
+
63
+
64
+ def create_rotation_callbacks() -> tuple[
65
+ RotationNexusFileCallback, RotationISPyBCallback
66
+ ]:
67
+ return (
58
68
  RotationNexusFileCallback(),
59
- RotationISPyBCallback(emit=zocalo),
69
+ RotationISPyBCallback(
70
+ emit=ZocaloCallback(CONST.PLAN.ROTATION_MAIN, CONST.ZOCALO_ENV)
71
+ ),
72
+ )
73
+
74
+
75
+ def setup_callbacks() -> list[CallbackBase]:
76
+ return [
77
+ *create_gridscan_callbacks(),
78
+ *create_rotation_callbacks(),
60
79
  LogUidTaggingCallback(),
61
80
  RobotLoadISPyBCallback(),
62
81
  SampleHandlingCallback(),
@@ -1,6 +1,7 @@
1
1
  from functools import cache
2
2
 
3
3
  from daq_config_server.client import ConfigServer
4
+ from pydantic import model_validator
4
5
 
5
6
  from mx_bluesky.common.external_interaction.config_server import FeatureFlags
6
7
  from mx_bluesky.common.utils.log import LOGGER
@@ -13,8 +14,10 @@ class HyperionFeatureFlags(FeatureFlags):
13
14
 
14
15
  Attributes:
15
16
  use_panda_for_gridscan: If True then the PandA is used for gridscans, otherwise the zebra is used
16
- compare_cpu_and_gpu_zocalo: If True then GPU result processing is enabled alongside CPU, if False then
17
- CPU only is used.
17
+ compare_cpu_and_gpu_zocalo: If True then GPU result processing is enabled
18
+ alongside CPU and the results are compared. The CPU result is still take.n
19
+ use_gpu_results: If True then GPU result processing is enabled
20
+ and the GPU result is taken.
18
21
  set_stub_offsets: If True then set the stub offsets after moving to the crystal (ignored for
19
22
  multi-centre)
20
23
  omega_flip: If True then invert the smargon omega motor rotation commands with respect to
@@ -28,5 +31,13 @@ class HyperionFeatureFlags(FeatureFlags):
28
31
 
29
32
  use_panda_for_gridscan: bool = CONST.I03.USE_PANDA_FOR_GRIDSCAN
30
33
  compare_cpu_and_gpu_zocalo: bool = CONST.I03.COMPARE_CPU_AND_GPU_ZOCALO
34
+ use_gpu_results: bool = CONST.I03.USE_GPU_RESULTS
31
35
  set_stub_offsets: bool = CONST.I03.SET_STUB_OFFSETS
32
36
  omega_flip: bool = CONST.I03.OMEGA_FLIP
37
+
38
+ @model_validator(mode="after")
39
+ def use_gpu_and_compare_cannot_both_be_true(self):
40
+ assert not (self.use_gpu_results and self.compare_cpu_and_gpu_zocalo), (
41
+ "Cannot both use GPU results and compare them to CPU"
42
+ )
43
+ return self
@@ -8,7 +8,6 @@ from mx_bluesky._version import version
8
8
  @dataclass
9
9
  class HyperionArgs:
10
10
  dev_mode: bool = False
11
- use_external_callbacks: bool = False
12
11
  verbose_event_logging: bool = False
13
12
  skip_startup_connection: bool = False
14
13
 
@@ -34,8 +33,7 @@ def parse_cli_args() -> HyperionArgs:
34
33
  """Parses all arguments relevant to hyperion. Returns an HyperionArgs dataclass with
35
34
  the fields: (verbose_event_logging: bool,
36
35
  dev_mode: bool,
37
- skip_startup_connection: bool,
38
- external_callbacks: bool)"""
36
+ skip_startup_connection: bool)"""
39
37
  parser = argparse.ArgumentParser()
40
38
  _add_callback_relevant_args(parser)
41
39
  parser.add_argument(
@@ -48,11 +46,6 @@ def parse_cli_args() -> HyperionArgs:
48
46
  action="store_true",
49
47
  help="Skip connecting to EPICS PVs on startup",
50
48
  )
51
- parser.add_argument(
52
- "--external-callbacks",
53
- action="store_true",
54
- help="Run the external hyperion-callbacks service and publish events over ZMQ",
55
- )
56
49
  parser.add_argument(
57
50
  "--version",
58
51
  help="Print hyperion version string",
@@ -64,5 +57,4 @@ def parse_cli_args() -> HyperionArgs:
64
57
  verbose_event_logging=args.verbose_event_logging or False,
65
58
  dev_mode=args.dev or False,
66
59
  skip_startup_connection=args.skip_startup_connection or False,
67
- use_external_callbacks=args.external_callbacks or False,
68
60
  )
@@ -4,6 +4,7 @@ from dodal.devices.detector import EIGER2_X_16M_SIZE
4
4
  from pydantic.dataclasses import dataclass
5
5
 
6
6
  from mx_bluesky.common.parameters.constants import (
7
+ DeviceSettingsConstants,
7
8
  DocDescriptorNames,
8
9
  EnvironmentConstants,
9
10
  ExperimentParamConstants,
@@ -31,9 +32,12 @@ class I03Constants:
31
32
  OMEGA_FLIP = True
32
33
 
33
34
  # Turns on GPU processing for zocalo and logs a comparison between GPU and CPU-
34
- # processed results. GPU results never used in analysis for now
35
+ # processed results.
35
36
  COMPARE_CPU_AND_GPU_ZOCALO = False
36
37
 
38
+ # Turns on GPU processing for zocalo and uses the results that come back
39
+ USE_GPU_RESULTS = False
40
+
37
41
 
38
42
  @dataclass(frozen=True)
39
43
  class HyperionConstants:
@@ -57,6 +61,7 @@ class HyperionConstants:
57
61
  GRAYLOG_PORT = 12232
58
62
  PARAMETER_SCHEMA_DIRECTORY = "src/hyperion/parameters/schemas/"
59
63
  LOG_FILE_NAME = "hyperion.log"
64
+ DEVICE_SETTINGS_CONSTANTS = DeviceSettingsConstants()
60
65
 
61
66
 
62
67
  CONST = HyperionConstants()
@@ -7,9 +7,7 @@ from dodal.devices.fast_grid_scan import (
7
7
  PandAGridScanParams,
8
8
  ZebraGridScanParams,
9
9
  )
10
- from pydantic import Field
11
10
 
12
- from mx_bluesky.common.parameters.constants import GridscanParamConstants
13
11
  from mx_bluesky.common.parameters.gridscan import (
14
12
  GridCommon,
15
13
  SpecifiedThreeDGridScan,
@@ -49,7 +47,8 @@ class GridCommonWithHyperionDetectorParams(GridCommon, WithHyperionUDCFeatures):
49
47
  use_roi_mode=self.use_roi_mode,
50
48
  det_dist_to_beam_converter_path=self.det_dist_to_beam_converter_path,
51
49
  trigger_mode=self.trigger_mode,
52
- enable_dev_shm=self.features.compare_cpu_and_gpu_zocalo,
50
+ enable_dev_shm=self.features.compare_cpu_and_gpu_zocalo
51
+ or self.features.use_gpu_results,
53
52
  **optional_args,
54
53
  )
55
54
 
@@ -85,7 +84,8 @@ class HyperionSpecifiedThreeDGridScan(SpecifiedThreeDGridScan, WithHyperionUDCFe
85
84
  use_roi_mode=self.use_roi_mode,
86
85
  det_dist_to_beam_converter_path=self.det_dist_to_beam_converter_path,
87
86
  trigger_mode=self.trigger_mode,
88
- enable_dev_shm=self.features.compare_cpu_and_gpu_zocalo,
87
+ enable_dev_shm=self.features.compare_cpu_and_gpu_zocalo
88
+ or self.features.use_gpu_results,
89
89
  **optional_args,
90
90
  )
91
91
 
@@ -146,4 +146,4 @@ class PinTipCentreThenXrayCentre(
146
146
  class GridScanWithEdgeDetect(
147
147
  GridCommonWithHyperionDetectorParams, WithHyperionUDCFeatures
148
148
  ):
149
- box_size_um: float = Field(default=GridscanParamConstants.BOX_WIDTH_UM)
149
+ pass