mx-bluesky 1.5.10__py3-none-any.whl → 1.5.11__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 (76) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py +2 -2
  3. mx_bluesky/beamlines/i02_1/parameters/gridscan.py +1 -1
  4. mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +7 -7
  5. mx_bluesky/beamlines/i04/thawing_plan.py +9 -9
  6. mx_bluesky/beamlines/i24/jungfrau_commissioning/experiment_plans/do_darks.py +55 -10
  7. mx_bluesky/beamlines/i24/jungfrau_commissioning/plan_stubs/do_external_acquisition.py +1 -1
  8. mx_bluesky/beamlines/i24/jungfrau_commissioning/plan_stubs/plan_utils.py +1 -1
  9. mx_bluesky/beamlines/i24/serial/__init__.py +7 -5
  10. mx_bluesky/beamlines/i24/serial/dcid.py +3 -3
  11. mx_bluesky/beamlines/i24/serial/extruder/{i24ssx_Extruder_Collect_py3v2.py → i24ssx_extruder_collect_py3v2.py} +65 -35
  12. mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_Collect_py3v1.py → i24ssx_chip_collect_py3v1.py} +5 -5
  13. mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_Manager_py3v1.py → i24ssx_chip_manager_py3v1.py} +46 -46
  14. mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_StartUp_py3v1.py → i24ssx_chip_startup_py3v1.py} +3 -3
  15. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +33 -33
  16. mx_bluesky/beamlines/i24/serial/log.py +11 -11
  17. mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +3 -3
  18. mx_bluesky/beamlines/i24/serial/setup_beamline/ca.py +0 -12
  19. mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +13 -32
  20. mx_bluesky/beamlines/i24/serial/setup_beamline/pv_abstract.py +5 -5
  21. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +22 -249
  22. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +2 -2
  23. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +4 -4
  24. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +102 -15
  25. mx_bluesky/beamlines/i24/serial/write_nexus.py +4 -4
  26. mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py +6 -6
  27. mx_bluesky/common/experiment_plans/common_grid_detect_then_xray_centre_plan.py +2 -2
  28. mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py +1 -1
  29. mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py +2 -2
  30. mx_bluesky/common/experiment_plans/inner_plans/udc_default_state.py +22 -1
  31. mx_bluesky/common/experiment_plans/inner_plans/write_sample_status.py +2 -2
  32. mx_bluesky/common/experiment_plans/oav_snapshot_plan.py +1 -1
  33. mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +3 -3
  34. mx_bluesky/common/external_interaction/callbacks/common/plan_reactive_callback.py +1 -1
  35. mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py +2 -2
  36. mx_bluesky/common/external_interaction/callbacks/sample_handling/sample_handling_callback.py +3 -3
  37. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +7 -5
  38. mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py +2 -2
  39. mx_bluesky/common/external_interaction/config_server.py +2 -2
  40. mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +4 -2
  41. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +0 -1
  42. mx_bluesky/common/external_interaction/nexus/nexus_utils.py +2 -2
  43. mx_bluesky/common/external_interaction/nexus/write_nexus.py +3 -3
  44. mx_bluesky/common/parameters/constants.py +1 -1
  45. mx_bluesky/common/parameters/gridscan.py +2 -2
  46. mx_bluesky/common/utils/exceptions.py +9 -7
  47. mx_bluesky/common/utils/log.py +4 -4
  48. mx_bluesky/common/utils/tracing.py +5 -5
  49. mx_bluesky/common/utils/utils.py +8 -8
  50. mx_bluesky/hyperion/__main__.py +5 -5
  51. mx_bluesky/hyperion/baton_handler.py +15 -8
  52. mx_bluesky/hyperion/device_setup_plans/smargon.py +5 -5
  53. mx_bluesky/hyperion/device_setup_plans/utils.py +1 -1
  54. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +1 -1
  55. mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +15 -13
  56. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +2 -2
  57. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +9 -9
  58. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +2 -2
  59. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +3 -3
  60. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +2 -2
  61. mx_bluesky/hyperion/external_interaction/agamemnon.py +2 -2
  62. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +2 -2
  63. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +1 -1
  64. mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +2 -2
  65. mx_bluesky/hyperion/external_interaction/config_server.py +2 -2
  66. mx_bluesky/hyperion/parameters/constants.py +2 -2
  67. mx_bluesky/hyperion/parameters/gridscan.py +4 -4
  68. mx_bluesky/hyperion/plan_runner.py +6 -6
  69. mx_bluesky/hyperion/runner.py +10 -8
  70. mx_bluesky/jupyter_example.ipynb +3 -3
  71. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.11.dist-info}/METADATA +6 -5
  72. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.11.dist-info}/RECORD +76 -76
  73. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.11.dist-info}/WHEEL +0 -0
  74. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.11.dist-info}/entry_points.txt +0 -0
  75. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.11.dist-info}/licenses/LICENSE +0 -0
  76. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.11.dist-info}/top_level.txt +0 -0
@@ -52,7 +52,7 @@ def standard_read_hardware_pre_collection(
52
52
  synchrotron.synchrotron_mode,
53
53
  s4_slit_gaps,
54
54
  smargon,
55
- dcm.energy_in_kev,
55
+ dcm.energy_in_keV,
56
56
  ]
57
57
  yield from read_hardware_plan(
58
58
  signals_to_read_pre_flyscan, DocDescriptorNames.HARDWARE_READ_PRE
@@ -70,7 +70,7 @@ def standard_read_hardware_during_collection(
70
70
  aperture_scatterguard,
71
71
  attenuator.actual_transmission,
72
72
  flux.flux_reading,
73
- dcm.energy_in_kev,
73
+ dcm.energy_in_keV,
74
74
  detector.bit_depth,
75
75
  ]
76
76
  yield from read_hardware_plan(
@@ -1,13 +1,15 @@
1
1
  import bluesky.plan_stubs as bps
2
2
  import pydantic
3
+ from bluesky.utils import MsgGenerator
3
4
  from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureValue
4
5
  from dodal.devices.collimation_table import CollimationTable
5
- from dodal.devices.cryostream import CryoStream
6
+ from dodal.devices.cryostream import CryoStream, CryoStreamGantry, CryoStreamSelection
6
7
  from dodal.devices.cryostream import InOut as CryoInOut
7
8
  from dodal.devices.fluorescence_detector_motion import (
8
9
  FluorescenceDetector,
9
10
  )
10
11
  from dodal.devices.fluorescence_detector_motion import InOut as FlouInOut
12
+ from dodal.devices.hutch_shutter import HutchShutter, ShutterDemand
11
13
  from dodal.devices.mx_phase1.beamstop import Beamstop, BeamstopPositions
12
14
  from dodal.devices.scintillator import InOut as ScinInOut
13
15
  from dodal.devices.scintillator import Scintillator
@@ -16,15 +18,18 @@ from dodal.devices.scintillator import Scintillator
16
18
  @pydantic.dataclasses.dataclass(config={"arbitrary_types_allowed": True})
17
19
  class UDCDefaultDevices:
18
20
  cryostream: CryoStream
21
+ cryostream_gantry: CryoStreamGantry
19
22
  fluorescence_det_motion: FluorescenceDetector
20
23
  beamstop: Beamstop
21
24
  scintillator: Scintillator
22
25
  aperture_scatterguard: ApertureScatterguard
23
26
  collimation_table: CollimationTable
27
+ hutch_shutter: HutchShutter
24
28
 
25
29
 
26
30
  def move_to_udc_default_state(devices: UDCDefaultDevices):
27
31
  """Moves beamline to known positions prior to UDC start"""
32
+ yield from _verify_correct_cryostream_selected(devices.cryostream_gantry)
28
33
 
29
34
  cryostream_temp = yield from bps.rd(devices.cryostream.temperature_k)
30
35
  cryostream_pressure = yield from bps.rd(devices.cryostream.back_pressure_bar)
@@ -33,6 +38,10 @@ def move_to_udc_default_state(devices: UDCDefaultDevices):
33
38
  if cryostream_pressure > devices.cryostream.MAX_PRESSURE_BAR:
34
39
  raise ValueError("Cryostream back pressure is too high, not starting UDC")
35
40
 
41
+ yield from bps.abs_set(
42
+ devices.hutch_shutter, ShutterDemand.OPEN, group="udc_default"
43
+ )
44
+
36
45
  yield from bps.abs_set(devices.scintillator.selected_pos, ScinInOut.OUT, wait=True)
37
46
 
38
47
  yield from bps.abs_set(
@@ -63,3 +72,15 @@ def move_to_udc_default_state(devices: UDCDefaultDevices):
63
72
  yield from bps.abs_set(devices.cryostream.fine, CryoInOut.IN, group="udc_default")
64
73
 
65
74
  yield from bps.wait("udc_default")
75
+
76
+
77
+ def _verify_correct_cryostream_selected(
78
+ cryostream_gantry: CryoStreamGantry,
79
+ ) -> MsgGenerator:
80
+ cryostream_selection = yield from bps.rd(cryostream_gantry.cryostream_selector)
81
+ cryostream_selected = yield from bps.rd(cryostream_gantry.cryostream_selected)
82
+ if cryostream_selection != CryoStreamSelection.CRYOJET or cryostream_selected != 1:
83
+ raise ValueError(
84
+ f"Cryostream is not selected for use, control PV selection = {cryostream_selection}, "
85
+ f"current status {cryostream_selected}"
86
+ )
@@ -6,7 +6,7 @@ import bluesky.preprocessors as bpp
6
6
  from mx_bluesky.common.external_interaction.callbacks.sample_handling.sample_handling_callback import (
7
7
  SampleHandlingCallback,
8
8
  )
9
- from mx_bluesky.common.utils.exceptions import SampleException
9
+ from mx_bluesky.common.utils.exceptions import SampleError
10
10
 
11
11
 
12
12
  class SampleStatusExceptionType(StrEnum):
@@ -27,7 +27,7 @@ def deposit_sample_error(exception_type: SampleStatusExceptionType, sample_id: i
27
27
  if exception_type == SampleStatusExceptionType.BEAMLINE:
28
28
  raise AssertionError()
29
29
  elif exception_type == SampleStatusExceptionType.SAMPLE:
30
- raise SampleException
30
+ raise SampleError
31
31
 
32
32
  yield from _inner()
33
33
 
@@ -27,7 +27,7 @@ class OavSnapshotComposite(Protocol):
27
27
  backlight: Backlight
28
28
 
29
29
 
30
- def setup_beamline_for_OAV(
30
+ def setup_beamline_for_oav(
31
31
  smargon: Smargon,
32
32
  backlight: Backlight,
33
33
  aperture_scatterguard: ApertureScatterguard,
@@ -29,7 +29,7 @@ from mx_bluesky.common.external_interaction.ispyb.ispyb_utils import get_ispyb_c
29
29
  from mx_bluesky.common.parameters.components import DiffractionExperimentWithSample
30
30
  from mx_bluesky.common.parameters.constants import DocDescriptorNames
31
31
  from mx_bluesky.common.utils.log import ISPYB_ZOCALO_CALLBACK_LOGGER, set_dcgid_tag
32
- from mx_bluesky.common.utils.utils import convert_eV_to_angstrom
32
+ from mx_bluesky.common.utils.utils import convert_ev_to_angstrom
33
33
 
34
34
  D = TypeVar("D")
35
35
  if TYPE_CHECKING:
@@ -43,9 +43,9 @@ def _update_based_on_energy(
43
43
  ):
44
44
  """If energy has been read as part of this reading then add it into the data
45
45
  collection info along with the other fields that depend on it."""
46
- if energy_kev := doc["data"].get("dcm-energy_in_kev", None):
46
+ if energy_kev := doc["data"].get("dcm-energy_in_keV", None):
47
47
  energy_ev = energy_kev * 1000
48
- wavelength_angstroms = convert_eV_to_angstrom(energy_ev)
48
+ wavelength_angstroms = convert_ev_to_angstrom(energy_ev)
49
49
  data_collection_info.wavelength = wavelength_angstroms
50
50
  data_collection_info.resolution = resolution(
51
51
  detector_params,
@@ -40,7 +40,7 @@ class PlanReactiveCallback(CallbackBase):
40
40
  self.log = log
41
41
 
42
42
  def _run_activity_gated(self, name: str, func, doc, override=False):
43
- # Runs `func` if self.active is True or overide is true. Override can be used
43
+ # Runs `func` if self.active is True or override is true. Override can be used
44
44
  # to run the function even after setting self.active to False, i.e. in the last
45
45
  # handler of a run.
46
46
 
@@ -9,7 +9,7 @@ from dodal.devices.zocalo import ZocaloStartInfo, ZocaloTrigger
9
9
  from mx_bluesky.common.parameters.constants import (
10
10
  DocDescriptorNames,
11
11
  )
12
- from mx_bluesky.common.utils.exceptions import ISPyBDepositionNotMade
12
+ from mx_bluesky.common.utils.exceptions import ISPyBDepositionNotMadeError
13
13
  from mx_bluesky.common.utils.log import ISPYB_ZOCALO_CALLBACK_LOGGER
14
14
 
15
15
  if TYPE_CHECKING:
@@ -89,7 +89,7 @@ class ZocaloCallback(CallbackBase):
89
89
  f"Zocalo handler received stop document, for run {doc.get('run_start')}."
90
90
  )
91
91
  if not self._started_zocalo_collections:
92
- raise ISPyBDepositionNotMade(
92
+ raise ISPyBDepositionNotMadeError(
93
93
  f"No ISPyB IDs received by the end of {self.triggering_plan=}"
94
94
  )
95
95
  for info in self._started_zocalo_collections:
@@ -12,7 +12,7 @@ from mx_bluesky.common.external_interaction.ispyb.exp_eye_store import (
12
12
  BLSampleStatus,
13
13
  ExpeyeInteraction,
14
14
  )
15
- from mx_bluesky.common.utils.exceptions import CrystalNotFoundException, SampleException
15
+ from mx_bluesky.common.utils.exceptions import CrystalNotFoundError, SampleError
16
16
  from mx_bluesky.common.utils.log import ISPYB_ZOCALO_CALLBACK_LOGGER
17
17
 
18
18
 
@@ -47,7 +47,7 @@ class SampleHandlingCallback(PlanReactiveCallback):
47
47
  expeye = ExpeyeInteraction()
48
48
  if doc["exit_status"] != "success":
49
49
  reason = doc.get("reason", "")
50
- exception_type, message = SampleException.type_and_message_from_reason(
50
+ exception_type, message = SampleError.type_and_message_from_reason(
51
51
  reason
52
52
  )
53
53
  self.log.info(
@@ -83,7 +83,7 @@ class SampleHandlingCallback(PlanReactiveCallback):
83
83
 
84
84
  def _decode_sample_status(self, exception_type: str) -> BLSampleStatus:
85
85
  match exception_type:
86
- case SampleException.__name__ | CrystalNotFoundException.__name__:
86
+ case SampleError.__name__ | CrystalNotFoundError.__name__:
87
87
  return BLSampleStatus.ERROR_SAMPLE
88
88
  return BLSampleStatus.ERROR_BEAMLINE
89
89
 
@@ -40,8 +40,8 @@ from mx_bluesky.common.parameters.components import DiffractionExperimentWithSam
40
40
  from mx_bluesky.common.parameters.constants import DocDescriptorNames, PlanNameConstants
41
41
  from mx_bluesky.common.parameters.gridscan import GridCommon
42
42
  from mx_bluesky.common.utils.exceptions import (
43
- ISPyBDepositionNotMade,
44
- SampleException,
43
+ ISPyBDepositionNotMadeError,
44
+ SampleError,
45
45
  )
46
46
  from mx_bluesky.common.utils.log import ISPYB_ZOCALO_CALLBACK_LOGGER, set_dcgid_tag
47
47
  from mx_bluesky.common.utils.utils import number_of_frames_from_scan_spec
@@ -87,7 +87,7 @@ class GridscanISPyBCallback(BaseISPyBCallback):
87
87
  To use, subscribe the Bluesky RunEngine to an instance of this class.
88
88
  E.g.:
89
89
  ispyb_handler_callback = FGSISPyBCallback(parameters)
90
- RE.subscribe(ispyb_handler_callback)
90
+ run_engine.subscribe(ispyb_handler_callback)
91
91
  Or decorate a plan using bluesky.preprocessors.subs_decorator.
92
92
 
93
93
  See: https://blueskyproject.io/bluesky/callbacks.html#ways-to-invoke-callbacks
@@ -303,8 +303,10 @@ class GridscanISPyBCallback(BaseISPyBCallback):
303
303
  f"with uid: {self.uid_to_finalize_on}."
304
304
  )
305
305
  if self.ispyb_ids == IspybIds():
306
- raise ISPyBDepositionNotMade("ispyb was not initialised at run start")
307
- exception_type, message = SampleException.type_and_message_from_reason(
306
+ raise ISPyBDepositionNotMadeError(
307
+ "ispyb was not initialised at run start"
308
+ )
309
+ exception_type, message = SampleError.type_and_message_from_reason(
308
310
  doc.get("reason", "")
309
311
  )
310
312
  if exception_type:
@@ -33,7 +33,7 @@ class GridscanNexusFileCallback(PlanReactiveCallback):
33
33
  To use, subscribe the Bluesky RunEngine to an instance of this class.
34
34
  E.g.:
35
35
  nexus_file_handler_callback = NexusFileCallback(parameters)
36
- RE.subscribe(nexus_file_handler_callback)
36
+ run_engine.subscribe(nexus_file_handler_callback)
37
37
  Or decorate a plan using bluesky.preprocessors.subs_decorator.
38
38
 
39
39
  See: https://blueskyproject.io/bluesky/callbacks.html#ways-to-invoke-callbacks
@@ -89,7 +89,7 @@ class GridscanNexusFileCallback(PlanReactiveCallback):
89
89
  nexus_writer.beam,
90
90
  nexus_writer.attenuator,
91
91
  ) = create_beam_and_attenuator_parameters(
92
- data["dcm-energy_in_kev"],
92
+ data["dcm-energy_in_keV"],
93
93
  data["flux-flux_reading"],
94
94
  data["attenuator-actual_transmission"],
95
95
  )
@@ -10,7 +10,7 @@ from pydantic import TypeAdapter
10
10
  from mx_bluesky.common.parameters.constants import (
11
11
  GDA_DOMAIN_PROPERTIES_PATH,
12
12
  FeatureSetting,
13
- FeatureSettingources,
13
+ FeatureSettingSources,
14
14
  OavConstants,
15
15
  )
16
16
  from mx_bluesky.common.utils.log import LOGGER
@@ -25,7 +25,7 @@ T = TypeVar("T", bound=FeatureSetting)
25
25
  class MXConfigClient(ConfigServer, Generic[T]):
26
26
  def __init__(
27
27
  self,
28
- feature_sources: type[FeatureSettingources],
28
+ feature_sources: type[FeatureSettingSources],
29
29
  feature_dc: type[T],
30
30
  url: str = "https://daq-config.diamond.ac.uk",
31
31
  ):
@@ -11,7 +11,7 @@ from mx_bluesky.common.external_interaction.ispyb.ispyb_utils import (
11
11
  get_current_time_string,
12
12
  get_ispyb_config,
13
13
  )
14
- from mx_bluesky.common.utils.exceptions import ISPyBDepositionNotMade
14
+ from mx_bluesky.common.utils.exceptions import ISPyBDepositionNotMadeError
15
15
 
16
16
  RobotActionID = int
17
17
 
@@ -40,7 +40,9 @@ def _send_and_get_response(auth, url, data, send_func) -> dict:
40
40
  resp_txt = str(response.json())
41
41
  except JSONDecodeError:
42
42
  resp_txt = str(response)
43
- raise ISPyBDepositionNotMade(f"Could not write {data} to {url}: {resp_txt}")
43
+ raise ISPyBDepositionNotMadeError(
44
+ f"Could not write {data} to {url}: {resp_txt}"
45
+ )
44
46
  return response.json()
45
47
 
46
48
 
@@ -5,7 +5,6 @@ from dataclasses import asdict
5
5
  from typing import TYPE_CHECKING
6
6
 
7
7
  import ispyb
8
- import ispyb.sqlalchemy
9
8
  import numpy as np
10
9
  from ispyb.connector.mysqlsp.main import ISPyBMySQLSPConnector as Connector
11
10
  from ispyb.sp.mxacquisition import MXAcquisition
@@ -11,7 +11,7 @@ from nexgen.nxs_utils.axes import TransformationType
11
11
  from numpy.typing import DTypeLike
12
12
 
13
13
  from mx_bluesky.common.utils.log import NEXUS_LOGGER
14
- from mx_bluesky.common.utils.utils import convert_eV_to_angstrom
14
+ from mx_bluesky.common.utils.utils import convert_ev_to_angstrom
15
15
 
16
16
 
17
17
  class AxisDirection(Enum):
@@ -158,6 +158,6 @@ def create_beam_and_attenuator_parameters(
158
158
  tuple[Beam, Attenuator]: Descriptions of the beam and attenuator for nexgen.
159
159
  """
160
160
  return (
161
- Beam(wavelength=convert_eV_to_angstrom(energy_kev * 1000), flux=flux),
161
+ Beam(wavelength=convert_ev_to_angstrom(energy_kev * 1000), flux=flux),
162
162
  Attenuator(transmission=transmission_fraction),
163
163
  )
@@ -87,7 +87,7 @@ class NexusWriter:
87
87
  vds_shape = self.data_shape
88
88
 
89
89
  for filename in [self.nexus_file, self.master_file]:
90
- NXmx_Writer = NXmxFileWriter(
90
+ nxmx_writer = NXmxFileWriter(
91
91
  filename,
92
92
  self.goniometer,
93
93
  self.detector,
@@ -96,12 +96,12 @@ class NexusWriter:
96
96
  self.attenuator,
97
97
  self.full_num_of_images,
98
98
  )
99
- NXmx_Writer.write(
99
+ nxmx_writer.write(
100
100
  image_filename=f"{self.data_filename}",
101
101
  start_time=start_time,
102
102
  est_end_time=est_end_time,
103
103
  )
104
- NXmx_Writer.write_vds(
104
+ nxmx_writer.write_vds(
105
105
  vds_offset=self.start_index, vds_shape=vds_shape, vds_dtype=bit_depth
106
106
  )
107
107
 
@@ -166,6 +166,6 @@ class Status(Enum):
166
166
  class FeatureSetting: ... # List of features and their default values. Subclasses must also be a pydantic dataclass
167
167
 
168
168
 
169
- class FeatureSettingources(
169
+ class FeatureSettingSources(
170
170
  StrEnum
171
171
  ): ... # List of features and the name of that property in domain.properties
@@ -109,7 +109,7 @@ class SpecifiedGrid(GridCommon, XyzStarts, WithScan, Generic[GridScanParamType])
109
109
 
110
110
  @property
111
111
  @abstractmethod
112
- def FGS_params(self) -> GridScanParamType: ...
112
+ def fast_gridscan_params(self) -> GridScanParamType: ...
113
113
 
114
114
  def do_set_stub_offsets(self, value: bool):
115
115
  self._set_stub_offsets = value
@@ -167,7 +167,7 @@ class SpecifiedThreeDGridScan(
167
167
  grid2_omega_deg: float = Field(default=GridscanParamConstants.OMEGA_2)
168
168
 
169
169
  @property
170
- def FGS_params(self) -> ZebraGridScanParamsThreeD:
170
+ def fast_gridscan_params(self) -> ZebraGridScanParamsThreeD:
171
171
  return ZebraGridScanParamsThreeD(
172
172
  x_steps=self.x_steps,
173
173
  y_steps=self.y_steps,
@@ -7,20 +7,22 @@ from bluesky.preprocessors import contingency_wrapper
7
7
  from bluesky.utils import Msg
8
8
 
9
9
 
10
- class WarningException(Exception):
10
+ class WarningError(
11
+ Exception
12
+ ): # see https://github.com/DiamondLightSource/mx-bluesky/issues/1394 on naming
11
13
  """An exception used when we want to warn GDA of a
12
14
  problem but continue with UDC anyway"""
13
15
 
14
16
  pass
15
17
 
16
18
 
17
- class ISPyBDepositionNotMade(Exception):
19
+ class ISPyBDepositionNotMadeError(Exception):
18
20
  """Raised when the ISPyB or Zocalo callbacks can't access ISPyB deposition numbers."""
19
21
 
20
22
  pass
21
23
 
22
24
 
23
- class SampleException(WarningException):
25
+ class SampleError(WarningError):
24
26
  """An exception which identifies an issue relating to the sample."""
25
27
 
26
28
  def __str__(self):
@@ -36,7 +38,7 @@ class SampleException(WarningException):
36
38
  T = TypeVar("T")
37
39
 
38
40
 
39
- class CrystalNotFoundException(SampleException):
41
+ class CrystalNotFoundError(SampleError):
40
42
  """Raised if grid detection completed normally but no crystal was found."""
41
43
 
42
44
  def __init__(self, *args):
@@ -49,7 +51,7 @@ def catch_exception_and_warn(
49
51
  *args,
50
52
  **kwargs,
51
53
  ) -> Generator[Msg, None, T]:
52
- """A plan wrapper to catch a specific exception and instead raise a WarningException,
54
+ """A plan wrapper to catch a specific exception and instead raise a WarningError,
53
55
  so that UDC is not halted
54
56
 
55
57
  Example usage:
@@ -58,12 +60,12 @@ def catch_exception_and_warn(
58
60
  ...
59
61
  yield from catch_exception_and_warn(ExceptionA, plan_which_can_raise_exception_a, **args, **kwargs)'
60
62
 
61
- This will catch ExceptionA raised by the plan and instead raise a WarningException
63
+ This will catch ExceptionA raised by the plan and instead raise a WarningError
62
64
  """
63
65
 
64
66
  def warn_if_exception_matches(exception: Exception):
65
67
  if isinstance(exception, exception_to_catch):
66
- raise SampleException(str(exception)) from exception
68
+ raise SampleError(str(exception)) from exception
67
69
  yield from null()
68
70
 
69
71
  return (
@@ -10,11 +10,11 @@ from dodal.log import (
10
10
  integrate_bluesky_and_ophyd_logging,
11
11
  set_up_all_logging_handlers,
12
12
  )
13
- from dodal.log import LOGGER as dodal_logger
13
+ from dodal.log import LOGGER as DODAL_LOGGER
14
14
 
15
15
  LOGGER = logging.getLogger("MX-Bluesky")
16
16
  LOGGER.setLevel("DEBUG")
17
- LOGGER.parent = dodal_logger
17
+ LOGGER.parent = DODAL_LOGGER
18
18
 
19
19
  ISPYB_ZOCALO_CALLBACK_LOGGER = logging.getLogger("ISPyB and Zocalo callbacks")
20
20
  ISPYB_ZOCALO_CALLBACK_LOGGER.setLevel(logging.DEBUG)
@@ -68,7 +68,7 @@ def do_default_logging_setup(
68
68
  and bluesky and ophyd-async are optionally included."""
69
69
  logging_path, debug_logging_path = _get_logging_dirs(dev_mode)
70
70
  handlers = set_up_all_logging_handlers(
71
- dodal_logger,
71
+ DODAL_LOGGER,
72
72
  logging_path,
73
73
  file_name,
74
74
  dev_mode,
@@ -78,7 +78,7 @@ def do_default_logging_setup(
78
78
  )
79
79
 
80
80
  if integrate_all_logs:
81
- integrate_bluesky_and_ophyd_logging(dodal_logger)
81
+ integrate_bluesky_and_ophyd_logging(DODAL_LOGGER)
82
82
 
83
83
  handlers["graylog_handler"].addFilter(tag_filter)
84
84
 
@@ -11,18 +11,18 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor
11
11
  def setup_tracing(service_name: str = "Hyperion"):
12
12
  resource = Resource(attributes={SERVICE_NAME: service_name})
13
13
 
14
- traceProvider = TracerProvider(resource=resource)
14
+ trace_provider = TracerProvider(resource=resource)
15
15
  processor = BatchSpanProcessor(
16
16
  OTLPSpanExporter(endpoint="http://0.0.0.0:4318/v1/traces")
17
17
  )
18
- traceProvider.add_span_processor(processor)
19
- trace.set_tracer_provider(traceProvider)
18
+ trace_provider.add_span_processor(processor)
19
+ trace.set_tracer_provider(trace_provider)
20
20
 
21
21
  reader = PeriodicExportingMetricReader(
22
22
  OTLPMetricExporter(endpoint="http://0.0.0.0:4318/v1/metrics")
23
23
  )
24
- meterProvider = MeterProvider(resource=resource, metric_readers=[reader])
25
- metrics.set_meter_provider(meterProvider)
24
+ meter_provider = MeterProvider(resource=resource, metric_readers=[reader])
25
+ metrics.set_meter_provider(meter_provider)
26
26
 
27
27
 
28
28
  TRACER = trace.get_tracer(__name__)
@@ -4,23 +4,23 @@ from math import asin
4
4
  from scanspec.core import AxesPoints, Axis
5
5
  from scipy.constants import physical_constants
6
6
 
7
- hc_in_eV_and_Angstrom: float = (
7
+ hc_in_ev_and_angstrom: float = (
8
8
  physical_constants["speed of light in vacuum"][0]
9
9
  * physical_constants["Planck constant in eV/Hz"][0]
10
10
  * 1e10 # Angstroms per metre
11
11
  )
12
12
 
13
13
 
14
- def interconvert_eV_Angstrom(wavelength_or_energy: float) -> float:
15
- return hc_in_eV_and_Angstrom / wavelength_or_energy
14
+ def interconvert_ev_angstrom(wavelength_or_energy: float) -> float:
15
+ return hc_in_ev_and_angstrom / wavelength_or_energy
16
16
 
17
17
 
18
- def convert_eV_to_angstrom(hv: float) -> float:
19
- return interconvert_eV_Angstrom(hv)
18
+ def convert_ev_to_angstrom(hv: float) -> float:
19
+ return interconvert_ev_angstrom(hv)
20
20
 
21
21
 
22
- def convert_angstrom_to_eV(wavelength: float) -> float:
23
- return interconvert_eV_Angstrom(wavelength)
22
+ def convert_angstrom_to_ev(wavelength: float) -> float:
23
+ return interconvert_ev_angstrom(wavelength)
24
24
 
25
25
 
26
26
  def number_of_frames_from_scan_spec(scan_points: AxesPoints[Axis]):
@@ -37,6 +37,6 @@ def energy_to_bragg_angle(energy_kev: float, d_a: float) -> float:
37
37
  Returns:
38
38
  The bragg angle in degrees
39
39
  """
40
- wavelength_a = convert_eV_to_angstrom(energy_kev * 1000)
40
+ wavelength_a = convert_ev_to_angstrom(energy_kev * 1000)
41
41
  d = d_a
42
42
  return asin(wavelength_a / (2 * d)) * 180 / math.pi
@@ -22,7 +22,7 @@ from mx_bluesky.common.utils.log import (
22
22
  from mx_bluesky.hyperion.baton_handler import run_forever
23
23
  from mx_bluesky.hyperion.experiment_plans.experiment_registry import (
24
24
  PLAN_REGISTRY,
25
- PlanNotFound,
25
+ PlanNotFoundError,
26
26
  )
27
27
  from mx_bluesky.hyperion.external_interaction.agamemnon import (
28
28
  compare_params,
@@ -48,16 +48,16 @@ from mx_bluesky.hyperion.utils.context import setup_context
48
48
  def compose_start_args(context: BlueskyContext, plan_name: str, action: Actions):
49
49
  experiment_registry_entry = PLAN_REGISTRY.get(plan_name)
50
50
  if experiment_registry_entry is None:
51
- raise PlanNotFound(f"Experiment plan '{plan_name}' not found in registry.")
51
+ raise PlanNotFoundError(f"Experiment plan '{plan_name}' not found in registry.")
52
52
 
53
53
  experiment_internal_param_type = experiment_registry_entry.get("param_type")
54
54
  plan = context.plan_functions.get(plan_name)
55
55
  if experiment_internal_param_type is None:
56
- raise PlanNotFound(
56
+ raise PlanNotFoundError(
57
57
  f"Corresponding internal param type for '{plan_name}' not found in registry."
58
58
  )
59
59
  if plan is None:
60
- raise PlanNotFound(
60
+ raise PlanNotFoundError(
61
61
  f"Experiment plan '{plan_name}' not found in context. Context has {context.plan_functions.keys()}"
62
62
  )
63
63
  try:
@@ -115,7 +115,7 @@ class StopOrStatus(Resource):
115
115
  status_and_message = StatusAndMessage(Status.FAILED, f"{action} not understood")
116
116
  if action == Actions.STATUS.value:
117
117
  LOGGER.debug(
118
- f"Runner received status request - state of the runner object is: {self.runner.__dict__} - state of the RE is: {self.runner.RE.__dict__}"
118
+ f"Runner received status request - state of the runner object is: {self.runner.__dict__} - state of the run_engine is: {self.runner.run_engine.__dict__}"
119
119
  )
120
120
  status_and_message = self.runner.current_status
121
121
  return asdict(status_and_message)
@@ -9,6 +9,7 @@ from bluesky.utils import MsgGenerator, RunEngineInterrupted
9
9
  from dodal.common.beamlines.commissioning_mode import set_commissioning_signal
10
10
  from dodal.devices.aperturescatterguard import ApertureScatterguard
11
11
  from dodal.devices.baton import Baton
12
+ from dodal.devices.detector.detector_motion import DetectorMotion, ShutterState
12
13
  from dodal.devices.motors import XYZStage
13
14
  from dodal.devices.robot import BartRobot
14
15
  from dodal.devices.smargon import Smargon
@@ -38,7 +39,7 @@ from mx_bluesky.hyperion.external_interaction.agamemnon import (
38
39
  from mx_bluesky.hyperion.external_interaction.alerting.constants import Subjects
39
40
  from mx_bluesky.hyperion.parameters.components import Wait
40
41
  from mx_bluesky.hyperion.parameters.load_centre_collect import LoadCentreCollect
41
- from mx_bluesky.hyperion.plan_runner import PlanException, PlanRunner
42
+ from mx_bluesky.hyperion.plan_runner import PlanError, PlanRunner
42
43
  from mx_bluesky.hyperion.utils.context import (
43
44
  clear_all_device_caches,
44
45
  setup_devices,
@@ -53,7 +54,7 @@ def run_forever(runner: PlanRunner):
53
54
  while True:
54
55
  try:
55
56
  run_udc_when_requested(runner.context, runner)
56
- except PlanException as e:
57
+ except PlanError as e:
57
58
  LOGGER.info(
58
59
  "Caught exception during plan execution, stopped and waiting for baton.",
59
60
  exc_info=e,
@@ -64,7 +65,7 @@ def run_forever(runner: PlanRunner):
64
65
  # RunEngine.abort() will have been called and we will get RunEngineInterrupted
65
66
  LOGGER.info(
66
67
  f"RunEngine was interrupted. Runner state is {runner.current_status}, "
67
- f"run engine is {runner.RE.state}"
68
+ f"run engine is {runner.run_engine.state}"
68
69
  )
69
70
 
70
71
 
@@ -93,7 +94,7 @@ def run_udc_when_requested(context: BlueskyContext, runner: PlanRunner):
93
94
  * A user requests the baton away from Hyperion
94
95
  * Hyperion releases the baton when Agamemnon has no more instructions
95
96
  * The RunEngine raises a RequestAbort exception, most likely due to a shutdown command
96
- * A plan raises an exception not of type WarningException (which is then wrapped as a PlanException)
97
+ * A plan raises an exception not of type WarningError (which is then wrapped as a PlanError)
97
98
  Args:
98
99
  baton: The baton device
99
100
  runner: The runner
@@ -109,7 +110,7 @@ def run_udc_when_requested(context: BlueskyContext, runner: PlanRunner):
109
110
  baton, runner, current_visit
110
111
  )
111
112
  if current_visit:
112
- yield from _perform_robot_unload(runner.context, current_visit)
113
+ yield from _clean_up_udc(runner.context, current_visit)
113
114
 
114
115
  def release_baton() -> MsgGenerator:
115
116
  # If hyperion has given up the baton itself we need to also release requested
@@ -145,13 +146,13 @@ def _initialise_udc(context: BlueskyContext, dev_mode: bool):
145
146
 
146
147
  def _wait_for_hyperion_requested(baton: Baton):
147
148
  LOGGER.debug("Hyperion waiting for baton...")
148
- SLEEP_PER_CHECK = 0.1
149
+ sleep_per_check = 0.1
149
150
  while True:
150
151
  requested_user = yield from bps.rd(baton.requested_user)
151
152
  if requested_user == HYPERION_USER:
152
153
  LOGGER.debug("Baton requested for Hyperion")
153
154
  break
154
- yield from bps.sleep(SLEEP_PER_CHECK)
155
+ yield from bps.sleep(sleep_per_check)
155
156
 
156
157
 
157
158
  def _fetch_and_process_agamemnon_instruction(
@@ -239,11 +240,17 @@ def _unrequest_baton(baton: Baton) -> MsgGenerator[str]:
239
240
  return requested_user
240
241
 
241
242
 
242
- def _perform_robot_unload(context: BlueskyContext, visit: str) -> MsgGenerator:
243
+ def _clean_up_udc(context: BlueskyContext, visit: str) -> MsgGenerator:
244
+ cleanup_group = "cleanup"
243
245
  robot = find_device_in_context(context, "robot", BartRobot)
244
246
  smargon = find_device_in_context(context, "smargon", Smargon)
245
247
  aperture_scatterguard = find_device_in_context(
246
248
  context, "aperture_scatterguard", ApertureScatterguard
247
249
  )
248
250
  lower_gonio = find_device_in_context(context, "lower_gonio", XYZStage)
251
+ detector_motion = find_device_in_context(context, "detector_motion", DetectorMotion)
252
+ yield from bps.abs_set(
253
+ detector_motion.shutter, ShutterState.CLOSED, group=cleanup_group
254
+ )
249
255
  yield from robot_unload(robot, smargon, aperture_scatterguard, lower_gonio, visit)
256
+ yield from bps.wait(cleanup_group)