mx-bluesky 1.4.2__py3-none-any.whl → 1.4.3__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 (92) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/i24/serial/dcid.py +3 -3
  3. mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +24 -9
  4. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +13 -4
  5. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +1 -1
  6. mx_bluesky/beamlines/i24/serial/parameters/__init__.py +2 -1
  7. mx_bluesky/beamlines/i24/serial/parameters/constants.py +13 -5
  8. mx_bluesky/beamlines/i24/serial/parameters/experiment_parameters.py +20 -4
  9. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +40 -11
  10. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +81 -40
  11. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/aperture_change_callback.py +1 -1
  12. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/grid_detection_callback.py +19 -1
  13. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/ispyb_callback_base.py +40 -34
  14. mx_bluesky/{hyperion → common}/external_interaction/callbacks/common/ispyb_mapping.py +4 -4
  15. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/logging_callback.py +1 -1
  16. mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/zocalo_callback.py +14 -9
  17. mx_bluesky/{hyperion → common}/external_interaction/callbacks/xray_centre/ispyb_callback.py +39 -34
  18. mx_bluesky/{hyperion → common}/external_interaction/callbacks/xray_centre/ispyb_mapping.py +2 -2
  19. mx_bluesky/{hyperion → common}/external_interaction/callbacks/xray_centre/nexus_callback.py +20 -15
  20. mx_bluesky/common/external_interaction/config_server.py +11 -0
  21. mx_bluesky/common/external_interaction/ispyb/__init__.py +0 -0
  22. mx_bluesky/{hyperion → common}/external_interaction/ispyb/data_model.py +2 -0
  23. mx_bluesky/{hyperion → common}/external_interaction/ispyb/exp_eye_store.py +5 -5
  24. mx_bluesky/{hyperion → common}/external_interaction/ispyb/ispyb_store.py +20 -18
  25. mx_bluesky/{hyperion → common}/external_interaction/ispyb/ispyb_utils.py +2 -2
  26. mx_bluesky/common/external_interaction/nexus/__init__.py +0 -0
  27. mx_bluesky/{hyperion → common}/external_interaction/nexus/nexus_utils.py +21 -6
  28. mx_bluesky/{hyperion → common}/external_interaction/nexus/write_nexus.py +5 -5
  29. mx_bluesky/common/external_interaction/test_config_server.py +38 -0
  30. mx_bluesky/common/parameters/components.py +9 -7
  31. mx_bluesky/common/parameters/constants.py +1 -0
  32. mx_bluesky/common/parameters/gridscan.py +102 -53
  33. mx_bluesky/common/plans/do_fgs.py +4 -4
  34. mx_bluesky/{hyperion → common/utils}/exceptions.py +15 -1
  35. mx_bluesky/common/utils/log.py +17 -7
  36. mx_bluesky/hyperion/__main__.py +15 -14
  37. mx_bluesky/hyperion/device_setup_plans/check_beamstop.py +27 -0
  38. mx_bluesky/hyperion/device_setup_plans/dcm_pitch_roll_mirror_adjuster.py +13 -6
  39. mx_bluesky/hyperion/device_setup_plans/manipulate_sample.py +1 -1
  40. mx_bluesky/hyperion/device_setup_plans/position_detector.py +1 -1
  41. mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +3 -3
  42. mx_bluesky/hyperion/device_setup_plans/setup_panda.py +21 -4
  43. mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +62 -36
  44. mx_bluesky/hyperion/device_setup_plans/smargon.py +1 -1
  45. mx_bluesky/hyperion/device_setup_plans/utils.py +4 -0
  46. mx_bluesky/hyperion/device_setup_plans/xbpm_feedback.py +8 -8
  47. mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +28 -17
  48. mx_bluesky/hyperion/experiment_plans/common/xrc_result.py +10 -1
  49. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -9
  50. mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +39 -49
  51. mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +22 -23
  52. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +4 -11
  53. mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +3 -3
  54. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +6 -14
  55. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +12 -11
  56. mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +2 -2
  57. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +9 -4
  58. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +10 -11
  59. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +33 -14
  60. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -2
  61. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +28 -21
  62. mx_bluesky/hyperion/external_interaction/callbacks/common/callback_util.py +43 -32
  63. mx_bluesky/hyperion/external_interaction/callbacks/robot_load/ispyb_callback.py +22 -15
  64. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +25 -24
  65. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +1 -1
  66. mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +13 -9
  67. mx_bluesky/hyperion/external_interaction/callbacks/sample_handling/sample_handling_callback.py +12 -46
  68. mx_bluesky/hyperion/external_interaction/config_server.py +15 -1
  69. mx_bluesky/hyperion/parameters/components.py +3 -2
  70. mx_bluesky/hyperion/parameters/constants.py +1 -0
  71. mx_bluesky/hyperion/parameters/gridscan.py +56 -89
  72. mx_bluesky/hyperion/parameters/load_centre_collect.py +51 -6
  73. mx_bluesky/hyperion/parameters/robot_load.py +40 -0
  74. mx_bluesky/hyperion/parameters/rotation.py +28 -3
  75. mx_bluesky/hyperion/utils/context.py +1 -1
  76. mx_bluesky/hyperion/utils/validation.py +4 -2
  77. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.3.dist-info}/METADATA +6 -6
  78. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.3.dist-info}/RECORD +89 -87
  79. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.3.dist-info}/WHEEL +1 -1
  80. mx_bluesky/common/parameters/robot_load.py +0 -16
  81. mx_bluesky/hyperion/external_interaction/exceptions.py +0 -4
  82. mx_bluesky/hyperion/log.py +0 -15
  83. /mx_bluesky/{hyperion/external_interaction/callbacks/xray_centre → common/external_interaction}/__init__.py +0 -0
  84. /mx_bluesky/{hyperion/external_interaction/ispyb → common/external_interaction/callbacks/common}/__init__.py +0 -0
  85. /mx_bluesky/{hyperion → common}/external_interaction/callbacks/common/abstract_event.py +0 -0
  86. /mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/log_uid_tag_callback.py +0 -0
  87. /mx_bluesky/{hyperion/external_interaction/callbacks → common/external_interaction/callbacks/common}/plan_reactive_callback.py +0 -0
  88. /mx_bluesky/{hyperion/external_interaction/nexus → common/external_interaction/callbacks/xray_centre}/__init__.py +0 -0
  89. /mx_bluesky/{hyperion → common}/utils/utils.py +0 -0
  90. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.3.dist-info}/LICENSE +0 -0
  91. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.3.dist-info}/entry_points.txt +0 -0
  92. {mx_bluesky-1.4.2.dist-info → mx_bluesky-1.4.3.dist-info}/top_level.txt +0 -0
mx_bluesky/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.4.2'
16
- __version_tuple__ = version_tuple = (1, 4, 2)
15
+ __version__ = version = '1.4.3'
16
+ __version_tuple__ = version_tuple = (1, 4, 3)
@@ -4,7 +4,6 @@ import math
4
4
  import os
5
5
  import subprocess
6
6
  from functools import lru_cache
7
- from typing import Literal
8
7
 
9
8
  import bluesky.plan_stubs as bps
10
9
  import requests
@@ -18,6 +17,7 @@ from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import PumpProbeSetti
18
17
  from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER
19
18
  from mx_bluesky.beamlines.i24.serial.parameters import (
20
19
  BeamSettings,
20
+ DetectorName,
21
21
  ExtruderParameters,
22
22
  FixedTargetParameters,
23
23
  )
@@ -50,7 +50,7 @@ def read_beam_info_from_hardware(
50
50
  dcm: DCM,
51
51
  mirrors: FocusMirrorsMode,
52
52
  beam_center: DetectorBeamCenter,
53
- detector_name: Literal["eiger", "pilatus"],
53
+ detector_name: DetectorName,
54
54
  ):
55
55
  """ Read the beam information from hardware.
56
56
 
@@ -59,7 +59,7 @@ def read_beam_info_from_hardware(
59
59
  mirrors (FocusMirrorMode): The device describing the focus mirror mode settings.
60
60
  beam_center (DetectorBeamCenter): A device to set and read the beam center on \
61
61
  the detector.
62
- detector_name (Literal["eiger", "pilatus"]): The detector currently in use.
62
+ detector_name (DetectorName): The detector currently in use.
63
63
 
64
64
  Returns:
65
65
  BeamSettings parameter model.
@@ -16,7 +16,7 @@ import bluesky.plan_stubs as bps
16
16
  import bluesky.preprocessors as bpp
17
17
  from bluesky.utils import MsgGenerator
18
18
  from dodal.common import inject
19
- from dodal.devices.attenuator import ReadOnlyAttenuator
19
+ from dodal.devices.attenuator.attenuator import ReadOnlyAttenuator
20
20
  from dodal.devices.hutch_shutter import HutchShutter, ShutterDemand
21
21
  from dodal.devices.i24.aperture import Aperture
22
22
  from dodal.devices.i24.beam_center import DetectorBeamCenter
@@ -25,7 +25,7 @@ from dodal.devices.i24.dcm import DCM
25
25
  from dodal.devices.i24.dual_backlight import DualBacklight
26
26
  from dodal.devices.i24.focus_mirrors import FocusMirrorsMode
27
27
  from dodal.devices.i24.i24_detector_motion import DetectorMotion
28
- from dodal.devices.zebra import DISCONNECT, SOFT_IN3, Zebra
28
+ from dodal.devices.zebra.zebra import Zebra
29
29
 
30
30
  from mx_bluesky.beamlines.i24.serial.dcid import (
31
31
  DCID,
@@ -38,6 +38,7 @@ from mx_bluesky.beamlines.i24.serial.log import (
38
38
  log_on_entry,
39
39
  )
40
40
  from mx_bluesky.beamlines.i24.serial.parameters import ExtruderParameters
41
+ from mx_bluesky.beamlines.i24.serial.parameters.constants import BEAM_CENTER_LUT_FILES
41
42
  from mx_bluesky.beamlines.i24.serial.setup_beamline import Pilatus, caget, caput, pv
42
43
  from mx_bluesky.beamlines.i24.serial.setup_beamline import setup_beamline as sup
43
44
  from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_detector import (
@@ -46,8 +47,6 @@ from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_detector import (
46
47
  )
47
48
  from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_zebra_plans import (
48
49
  GATE_START,
49
- TTL_EIGER,
50
- TTL_PILATUS,
51
50
  arm_zebra,
52
51
  disarm_zebra,
53
52
  open_fast_shutter,
@@ -115,13 +114,22 @@ def laser_check(
115
114
 
116
115
  det_type = yield from get_detector_type(detector_stage)
117
116
 
118
- LASER_TTL = TTL_EIGER if isinstance(det_type, Pilatus) else TTL_PILATUS
117
+ LASER_TTL = (
118
+ zebra.mapping.outputs.TTL_EIGER
119
+ if isinstance(det_type, Pilatus)
120
+ else zebra.mapping.outputs.TTL_PILATUS
121
+ )
122
+
119
123
  if mode == "laseron":
120
- yield from bps.abs_set(zebra.output.out_pvs[LASER_TTL], SOFT_IN3)
124
+ yield from bps.abs_set(
125
+ zebra.output.out_pvs[LASER_TTL], zebra.mapping.sources.SOFT_IN3
126
+ )
121
127
  yield from set_shutter_mode(zebra, "auto")
122
128
 
123
129
  if mode == "laseroff":
124
- yield from bps.abs_set(zebra.output.out_pvs[LASER_TTL], DISCONNECT)
130
+ yield from bps.abs_set(
131
+ zebra.output.out_pvs[LASER_TTL], zebra.mapping.sources.DISCONNECT
132
+ )
125
133
  yield from set_shutter_mode(zebra, "manual")
126
134
 
127
135
 
@@ -206,8 +214,14 @@ def main_extruder_plan(
206
214
  dcid: DCID,
207
215
  start_time: datetime,
208
216
  ) -> MsgGenerator:
217
+ beam_center_pixels = sup.compute_beam_center_position_from_lut(
218
+ BEAM_CENTER_LUT_FILES[parameters.detector_name],
219
+ parameters.detector_distance_mm,
220
+ parameters.detector_size_constants,
221
+ )
209
222
  yield from sup.set_detector_beam_center_plan(
210
- beam_center_device, parameters.detector_name
223
+ beam_center_device,
224
+ beam_center_pixels,
211
225
  )
212
226
 
213
227
  # Setting up the beamline
@@ -281,7 +295,6 @@ def main_extruder_plan(
281
295
  SSX_LOGGER.info("Using Eiger detector")
282
296
 
283
297
  SSX_LOGGER.debug(f"Creating the directory for the collection in {filepath}.")
284
- Path(filepath).mkdir(parents=True, exist_ok=True)
285
298
 
286
299
  caput(pv.eiger_seqID, int(caget(pv.eiger_seqID)) + 1)
287
300
  SSX_LOGGER.info(f"Eiger quickshot setup: filepath {filepath}")
@@ -488,6 +501,8 @@ def run_extruder_plan(
488
501
  parameters: ExtruderParameters = yield from read_parameters(
489
502
  detector_stage, attenuator
490
503
  )
504
+ # Create collection directory
505
+ parameters.collection_directory.mkdir(parents=True, exist_ok=True)
491
506
 
492
507
  beam_center_device = sup.get_beam_center_device(parameters.detector_name)
493
508
 
@@ -10,7 +10,7 @@ import bluesky.plan_stubs as bps
10
10
  import bluesky.preprocessors as bpp
11
11
  from bluesky.utils import MsgGenerator
12
12
  from dodal.common import inject
13
- from dodal.devices.attenuator import ReadOnlyAttenuator
13
+ from dodal.devices.attenuator.attenuator import ReadOnlyAttenuator
14
14
  from dodal.devices.hutch_shutter import HutchShutter, ShutterDemand
15
15
  from dodal.devices.i24.aperture import Aperture
16
16
  from dodal.devices.i24.beam_center import DetectorBeamCenter
@@ -20,7 +20,7 @@ from dodal.devices.i24.dual_backlight import DualBacklight
20
20
  from dodal.devices.i24.focus_mirrors import FocusMirrorsMode
21
21
  from dodal.devices.i24.i24_detector_motion import DetectorMotion
22
22
  from dodal.devices.i24.pmac import PMAC
23
- from dodal.devices.zebra import Zebra
23
+ from dodal.devices.zebra.zebra import Zebra
24
24
 
25
25
  from mx_bluesky.beamlines.i24.serial.dcid import (
26
26
  DCID,
@@ -38,6 +38,7 @@ from mx_bluesky.beamlines.i24.serial.fixed_target.i24ssx_Chip_Manager_py3v1 impo
38
38
  )
39
39
  from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER, log_on_entry
40
40
  from mx_bluesky.beamlines.i24.serial.parameters import FixedTargetParameters
41
+ from mx_bluesky.beamlines.i24.serial.parameters.constants import BEAM_CENTER_LUT_FILES
41
42
  from mx_bluesky.beamlines.i24.serial.setup_beamline import caget, cagetstring, caput, pv
42
43
  from mx_bluesky.beamlines.i24.serial.setup_beamline import setup_beamline as sup
43
44
  from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_zebra_plans import (
@@ -410,7 +411,6 @@ def start_i24(
410
411
  SSX_LOGGER.info("Using Eiger detector")
411
412
 
412
413
  SSX_LOGGER.debug(f"Creating the directory for the collection in {filepath}.")
413
- Path(filepath).mkdir(parents=True, exist_ok=True)
414
414
 
415
415
  SSX_LOGGER.info(f"Triggered Eiger setup: filepath {filepath}")
416
416
  SSX_LOGGER.info(f"Triggered Eiger setup: filename {filename}")
@@ -547,8 +547,14 @@ def main_fixed_target_plan(
547
547
  ) -> MsgGenerator:
548
548
  SSX_LOGGER.info("Running a chip collection on I24")
549
549
 
550
+ beam_center_pixels = sup.compute_beam_center_position_from_lut(
551
+ BEAM_CENTER_LUT_FILES[parameters.detector_name],
552
+ parameters.detector_distance_mm,
553
+ parameters.detector_size_constants,
554
+ )
550
555
  yield from sup.set_detector_beam_center_plan(
551
- beam_center_device, parameters.detector_name
556
+ beam_center_device,
557
+ beam_center_pixels,
552
558
  )
553
559
 
554
560
  SSX_LOGGER.info("Getting Program Dictionary")
@@ -697,6 +703,9 @@ def run_fixed_target_plan(
697
703
  detector_stage, attenuator
698
704
  )
699
705
 
706
+ # Create collection directory
707
+ parameters.collection_directory.mkdir(parents=True, exist_ok=True)
708
+
700
709
  if parameters.chip_map:
701
710
  upload_chip_map_to_geobrick(pmac, parameters.chip_map)
702
711
 
@@ -15,7 +15,7 @@ import bluesky.plan_stubs as bps
15
15
  import numpy as np
16
16
  from bluesky.utils import MsgGenerator
17
17
  from dodal.common import inject
18
- from dodal.devices.attenuator import ReadOnlyAttenuator
18
+ from dodal.devices.attenuator.attenuator import ReadOnlyAttenuator
19
19
  from dodal.devices.i24.beamstop import Beamstop, BeamstopPositions
20
20
  from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
21
21
  from dodal.devices.i24.i24_detector_motion import DetectorMotion
@@ -1,4 +1,4 @@
1
- from mx_bluesky.beamlines.i24.serial.parameters.constants import SSXType
1
+ from mx_bluesky.beamlines.i24.serial.parameters.constants import DetectorName, SSXType
2
2
  from mx_bluesky.beamlines.i24.serial.parameters.experiment_parameters import (
3
3
  BeamSettings,
4
4
  ChipDescription,
@@ -13,6 +13,7 @@ from mx_bluesky.beamlines.i24.serial.parameters.utils import (
13
13
 
14
14
  __all__ = [
15
15
  "SSXType",
16
+ "DetectorName",
16
17
  "BeamSettings",
17
18
  "ExtruderParameters",
18
19
  "ChipDescription",
@@ -1,18 +1,26 @@
1
- from enum import Enum
1
+ from enum import StrEnum
2
2
  from os import environ
3
3
  from pathlib import Path
4
4
 
5
5
  from mx_bluesky.beamlines.i24.serial.log import _read_visit_directory_from_file
6
6
 
7
7
 
8
- class SSXType(Enum):
8
+ class SSXType(StrEnum):
9
9
  FIXED = "Serial Fixed"
10
10
  EXTRUDER = "Serial Jet"
11
11
 
12
12
 
13
- BEAM_CENTER_POS: dict[str, list] = {
14
- "eiger": [1600.0, 1697.4],
15
- "pilatus": [1284.7, 1308.6],
13
+ class DetectorName(StrEnum):
14
+ EIGER = "eiger"
15
+ PILATUS = "pilatus"
16
+
17
+
18
+ # TODO figue sth out for tests
19
+ LUT_FILES_PATH = Path("/dls_sw/i24/software/daq_configuration/lookup")
20
+
21
+ BEAM_CENTER_LUT_FILES = {
22
+ DetectorName.EIGER: LUT_FILES_PATH / "DetDistToBeamXYConverterE9M.txt",
23
+ DetectorName.PILATUS: LUT_FILES_PATH / "DetDistToBeamXYConverterP6M.txt",
16
24
  }
17
25
 
18
26
 
@@ -1,9 +1,13 @@
1
1
  import json
2
2
  from abc import abstractmethod
3
3
  from pathlib import Path
4
- from typing import Literal
5
4
 
6
5
  import numpy as np
6
+ from dodal.devices.detector.det_dim_constants import (
7
+ EIGER2_X_9M_SIZE,
8
+ PILATUS_6M_SIZE,
9
+ DetectorSizeConstants,
10
+ )
7
11
  from pydantic import BaseModel, ConfigDict, computed_field, field_validator
8
12
 
9
13
  from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
@@ -11,7 +15,10 @@ from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
11
15
  MappingType,
12
16
  PumpProbeSetting,
13
17
  )
14
- from mx_bluesky.beamlines.i24.serial.parameters.constants import SSXType
18
+ from mx_bluesky.beamlines.i24.serial.parameters.constants import (
19
+ DetectorName,
20
+ SSXType,
21
+ )
15
22
 
16
23
 
17
24
  class SerialExperiment(BaseModel):
@@ -22,7 +29,7 @@ class SerialExperiment(BaseModel):
22
29
  filename: str
23
30
  exposure_time_s: float
24
31
  detector_distance_mm: float
25
- detector_name: Literal["eiger", "pilatus"]
32
+ detector_name: DetectorName
26
33
  transmission: float
27
34
 
28
35
  @field_validator("visit", mode="before")
@@ -34,7 +41,16 @@ class SerialExperiment(BaseModel):
34
41
 
35
42
  @property
36
43
  def collection_directory(self) -> Path:
37
- return Path(self.visit) / self.directory
44
+ directory = Path(self.visit) / self.directory
45
+ return directory
46
+
47
+ @property
48
+ def detector_size_constants(self) -> DetectorSizeConstants:
49
+ return (
50
+ EIGER2_X_9M_SIZE
51
+ if self.detector_name is DetectorName.EIGER
52
+ else PILATUS_6M_SIZE
53
+ )
38
54
 
39
55
 
40
56
  class LaserExperiment(BaseModel):
@@ -1,15 +1,20 @@
1
+ from pathlib import Path
1
2
  from time import sleep
2
3
 
3
4
  import bluesky.plan_stubs as bps
4
5
  from dodal.beamlines import i24
6
+ from dodal.devices.detector.det_dim_constants import DetectorSizeConstants
5
7
  from dodal.devices.i24.aperture import Aperture, AperturePositions
6
8
  from dodal.devices.i24.beam_center import DetectorBeamCenter
7
9
  from dodal.devices.i24.beamstop import Beamstop, BeamstopPositions
8
10
  from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
9
11
  from dodal.devices.i24.i24_detector_motion import DetectorMotion
12
+ from dodal.devices.util.lookup_tables import (
13
+ linear_interpolation_lut,
14
+ parse_lookup_table,
15
+ )
10
16
 
11
17
  from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER
12
- from mx_bluesky.beamlines.i24.serial.parameters.constants import BEAM_CENTER_POS
13
18
  from mx_bluesky.beamlines.i24.serial.setup_beamline import pv
14
19
  from mx_bluesky.beamlines.i24.serial.setup_beamline.ca import caget, caput
15
20
 
@@ -21,6 +26,35 @@ def get_beam_center_device(detector_in_use: str) -> DetectorBeamCenter:
21
26
  return i24.pilatus_beam_center()
22
27
 
23
28
 
29
+ def compute_beam_center_position_from_lut(
30
+ lut_path: Path,
31
+ detector_distance_mm: float,
32
+ det_size_constants: DetectorSizeConstants,
33
+ ) -> tuple[float, float]:
34
+ """Calculate the beam center position for the detector distance \
35
+ using the values in the lookup table for the conversion.
36
+ """
37
+ lut_values = parse_lookup_table(lut_path.as_posix())
38
+
39
+ calc_x = linear_interpolation_lut(lut_values[0], lut_values[1])
40
+ beam_x_mm = calc_x(detector_distance_mm)
41
+ beam_x = (
42
+ beam_x_mm
43
+ * det_size_constants.det_size_pixels.width
44
+ / det_size_constants.det_dimension.width
45
+ )
46
+
47
+ calc_y = linear_interpolation_lut(lut_values[0], lut_values[2])
48
+ beam_y_mm = calc_y(detector_distance_mm)
49
+ beam_y = (
50
+ beam_y_mm
51
+ * det_size_constants.det_size_pixels.height
52
+ / det_size_constants.det_dimension.height
53
+ )
54
+
55
+ return beam_x, beam_y
56
+
57
+
24
58
  def setup_beamline_for_collection_plan(
25
59
  aperture: Aperture,
26
60
  backlight: DualBacklight,
@@ -55,22 +89,17 @@ def move_detector_stage_to_position_plan(
55
89
 
56
90
  def set_detector_beam_center_plan(
57
91
  beam_center_device: DetectorBeamCenter,
58
- detector_name: str,
92
+ beam_center_pixels: tuple[float, float],
59
93
  group: str = "set_beamcenter",
60
94
  wait: bool = True,
61
95
  ):
62
96
  """A small temporary plan to set up the beam center on the detector in use."""
63
97
  # NOTE This will be removed once the detectors are using ophyd_async devices
64
98
  # See https://github.com/DiamondLightSource/mx-bluesky/issues/62
65
- SSX_LOGGER.debug(
66
- f"Set beam center on {detector_name} detector: {BEAM_CENTER_POS[detector_name]}"
67
- )
68
- yield from bps.abs_set(
69
- beam_center_device.beam_x, BEAM_CENTER_POS[detector_name][0], group=group
70
- )
71
- yield from bps.abs_set(
72
- beam_center_device.beam_y, BEAM_CENTER_POS[detector_name][1], group=group
73
- )
99
+ beam_position_x, beam_position_y = beam_center_pixels
100
+ SSX_LOGGER.info(f"Setting beam center to: {beam_position_x}, {beam_position_y}")
101
+ yield from bps.abs_set(beam_center_device.beam_x, beam_position_x, group=group)
102
+ yield from bps.abs_set(beam_center_device.beam_y, beam_position_y, group=group)
74
103
  if wait:
75
104
  yield from bps.wait(group=group)
76
105
 
@@ -10,20 +10,7 @@ schematics corresponds to soft_in_2 in the code.
10
10
  """
11
11
 
12
12
  import bluesky.plan_stubs as bps
13
- from dodal.devices.zebra import (
14
- AND3,
15
- AND4,
16
- DISCONNECT,
17
- IN1_TTL,
18
- IN3_TTL,
19
- OR1,
20
- PC_ARM,
21
- PC_GATE,
22
- PC_PULSE,
23
- PULSE1,
24
- PULSE2,
25
- SOFT_IN2,
26
- SOFT_IN3,
13
+ from dodal.devices.zebra.zebra import (
27
14
  ArmDemand,
28
15
  ArmSource,
29
16
  I24Axes,
@@ -131,7 +118,9 @@ def setup_zebra_for_quickshot_plan(
131
118
  yield from bps.abs_set(zebra.pc.gate_start, GATE_START, group=group)
132
119
  yield from bps.abs_set(zebra.pc.gate_width, gate_width, group=group)
133
120
 
134
- yield from bps.abs_set(zebra.pc.gate_input, SOFT_IN2, group=group)
121
+ yield from bps.abs_set(
122
+ zebra.pc.gate_input, zebra.mapping.sources.SOFT_IN2, group=group
123
+ )
135
124
  yield from bps.sleep(0.1)
136
125
 
137
126
  if wait:
@@ -144,17 +133,25 @@ def set_logic_gates_for_porto_triggering(
144
133
  ):
145
134
  # To OUT2_TTL
146
135
  yield from bps.abs_set(
147
- zebra.logic_gates.and_gates[3].sources[1], SOFT_IN2, group=group
136
+ zebra.logic_gates.and_gates[3].sources[1],
137
+ zebra.mapping.sources.SOFT_IN2,
138
+ group=group,
148
139
  )
149
140
  yield from bps.abs_set(
150
- zebra.logic_gates.and_gates[3].sources[2], PULSE1, group=group
141
+ zebra.logic_gates.and_gates[3].sources[2],
142
+ zebra.mapping.sources.PULSE1,
143
+ group=group,
151
144
  )
152
145
  # To OUT1_TTL
153
146
  yield from bps.abs_set(
154
- zebra.logic_gates.and_gates[4].sources[1], SOFT_IN2, group=group
147
+ zebra.logic_gates.and_gates[4].sources[1],
148
+ zebra.mapping.sources.SOFT_IN2,
149
+ group=group,
155
150
  )
156
151
  yield from bps.abs_set(
157
- zebra.logic_gates.and_gates[4].sources[2], PULSE2, group=group
152
+ zebra.logic_gates.and_gates[4].sources[2],
153
+ zebra.mapping.sources.PULSE2,
154
+ group=group,
158
155
  )
159
156
  yield from bps.wait(group=group)
160
157
 
@@ -215,10 +212,16 @@ def setup_zebra_for_extruder_with_pump_probe_plan(
215
212
  # Set TTL out depending on detector type
216
213
  DET_TTL = TTL_EIGER if det_type == "eiger" else TTL_PILATUS
217
214
  LASER_TTL = TTL_PILATUS if det_type == "eiger" else TTL_EIGER
218
- yield from bps.abs_set(zebra.output.out_pvs[DET_TTL], AND4, group=group)
219
- yield from bps.abs_set(zebra.output.out_pvs[LASER_TTL], AND3, group=group)
215
+ yield from bps.abs_set(
216
+ zebra.output.out_pvs[DET_TTL], zebra.mapping.sources.AND4, group=group
217
+ )
218
+ yield from bps.abs_set(
219
+ zebra.output.out_pvs[LASER_TTL], zebra.mapping.sources.AND3, group=group
220
+ )
220
221
 
221
- yield from bps.abs_set(zebra.pc.gate_input, SOFT_IN2, group=group)
222
+ yield from bps.abs_set(
223
+ zebra.pc.gate_input, zebra.mapping.sources.SOFT_IN2, group=group
224
+ )
222
225
 
223
226
  assert pump_exp and pump_delay, "Must supply pump_exp and pump_delay!"
224
227
  gate_width, gate_step = get_zebra_settings_for_extruder(
@@ -242,7 +245,9 @@ def setup_zebra_for_extruder_with_pump_probe_plan(
242
245
  SSX_LOGGER.info(
243
246
  f"Pulse1 starting at {pulse1_delay} with width set to laser dwell {pump_exp}."
244
247
  )
245
- yield from bps.abs_set(zebra.output.pulse_1.input, PC_GATE, group=group)
248
+ yield from bps.abs_set(
249
+ zebra.output.pulse_1.input, zebra.mapping.sources.PC_GATE, group=group
250
+ )
246
251
  yield from bps.abs_set(zebra.output.pulse_1.delay, pulse1_delay, group=group)
247
252
  yield from bps.abs_set(zebra.output.pulse_1.width, pump_exp, group=group)
248
253
  SSX_LOGGER.info(
@@ -251,7 +256,9 @@ def setup_zebra_for_extruder_with_pump_probe_plan(
251
256
  exposure time {exp_time}.
252
257
  """
253
258
  )
254
- yield from bps.abs_set(zebra.output.pulse_2.input, PC_GATE, group=group)
259
+ yield from bps.abs_set(
260
+ zebra.output.pulse_2.input, zebra.mapping.sources.PC_GATE, group=group
261
+ )
255
262
  yield from bps.abs_set(zebra.output.pulse_2.delay, pump_delay, group=group)
256
263
  yield from bps.abs_set(zebra.output.pulse_2.width, exp_time, group=group)
257
264
 
@@ -308,20 +315,30 @@ def setup_zebra_for_fastchip_plan(
308
315
 
309
316
  # Logic Gates
310
317
  yield from bps.abs_set(
311
- zebra.logic_gates.and_gates[3].sources[1], SOFT_IN2, group=group
318
+ zebra.logic_gates.and_gates[3].sources[1],
319
+ zebra.mapping.sources.SOFT_IN2,
320
+ group=group,
312
321
  )
313
322
  yield from bps.abs_set(
314
- zebra.logic_gates.and_gates[3].sources[2], PC_PULSE, group=group
323
+ zebra.logic_gates.and_gates[3].sources[2],
324
+ zebra.mapping.sources.PC_PULSE,
325
+ group=group,
315
326
  )
316
327
 
317
- yield from bps.abs_set(zebra.pc.gate_input, IN3_TTL, group=group)
328
+ yield from bps.abs_set(
329
+ zebra.pc.gate_input, zebra.mapping.sources.IN3_TTL, group=group
330
+ )
318
331
 
319
332
  # Set TTL out depending on detector type
320
333
  # And calculate some of the other settings
321
334
  if det_type == "eiger":
322
- yield from bps.abs_set(zebra.output.out_pvs[TTL_EIGER], AND3, group=group)
335
+ yield from bps.abs_set(
336
+ zebra.output.out_pvs[TTL_EIGER], zebra.mapping.sources.AND3, group=group
337
+ )
323
338
  if det_type == "pilatus":
324
- yield from bps.abs_set(zebra.output.out_pvs[TTL_PILATUS], AND3, group=group)
339
+ yield from bps.abs_set(
340
+ zebra.output.out_pvs[TTL_PILATUS], zebra.mapping.sources.AND3, group=group
341
+ )
325
342
 
326
343
  # Square wave - needs a small drop to make it work for eiger
327
344
  pulse_width = exposure_time - 0.0001 if det_type == "eiger" else exposure_time / 2
@@ -374,13 +391,19 @@ def open_fast_shutter_at_each_position_plan(
374
391
  )
375
392
  SSX_LOGGER.debug("Controlling the fast shutter on PULSE2.")
376
393
  # Output panel pulse_2 settings
377
- yield from bps.abs_set(zebra.output.pulse_2.input, PC_GATE, group=group)
394
+ yield from bps.abs_set(
395
+ zebra.output.pulse_2.input, zebra.mapping.sources.PC_GATE, group=group
396
+ )
378
397
  yield from bps.abs_set(zebra.output.pulse_2.delay, 0.0, group=group)
379
398
  pulse2_width = num_exposures * exposure_time + SHUTTER_OPEN_TIME
380
399
  yield from bps.abs_set(zebra.output.pulse_2.width, pulse2_width, group=group)
381
400
 
382
401
  # Fast shutter
383
- yield from bps.abs_set(zebra.output.out_pvs[TTL_FAST_SHUTTER], PULSE2, group=group)
402
+ yield from bps.abs_set(
403
+ zebra.output.out_pvs[TTL_FAST_SHUTTER],
404
+ zebra.mapping.sources.PULSE2,
405
+ group=group,
406
+ )
384
407
 
385
408
  if wait:
386
409
  yield from bps.wait(group=group)
@@ -396,12 +419,22 @@ def reset_pc_gate_and_pulse(zebra: Zebra, group: str = "reset_pc"):
396
419
 
397
420
  def reset_output_panel(zebra: Zebra, group: str = "reset_zebra_outputs"):
398
421
  # Reset TTL out
399
- yield from bps.abs_set(zebra.output.out_pvs[2], PC_GATE, group=group)
400
- yield from bps.abs_set(zebra.output.out_pvs[3], DISCONNECT, group=group)
401
- yield from bps.abs_set(zebra.output.out_pvs[4], OR1, group=group)
422
+ yield from bps.abs_set(
423
+ zebra.output.out_pvs[2], zebra.mapping.sources.PC_GATE, group=group
424
+ )
425
+ yield from bps.abs_set(
426
+ zebra.output.out_pvs[3], zebra.mapping.sources.DISCONNECT, group=group
427
+ )
428
+ yield from bps.abs_set(
429
+ zebra.output.out_pvs[4], zebra.mapping.sources.OR1, group=group
430
+ )
402
431
 
403
- yield from bps.abs_set(zebra.output.pulse_1.input, DISCONNECT, group=group)
404
- yield from bps.abs_set(zebra.output.pulse_2.input, DISCONNECT, group=group)
432
+ yield from bps.abs_set(
433
+ zebra.output.pulse_1.input, zebra.mapping.sources.DISCONNECT, group=group
434
+ )
435
+ yield from bps.abs_set(
436
+ zebra.output.pulse_2.input, zebra.mapping.sources.DISCONNECT, group=group
437
+ )
405
438
 
406
439
  yield from bps.wait(group=group)
407
440
 
@@ -418,16 +451,24 @@ def zebra_return_to_normal_plan(
418
451
  # Reset PC_GATE and PC_SOURCE to "Position"
419
452
  yield from setup_pc_sources(zebra, TrigSource.POSITION, TrigSource.POSITION)
420
453
 
421
- yield from bps.abs_set(zebra.pc.gate_input, SOFT_IN3, group=group)
454
+ yield from bps.abs_set(
455
+ zebra.pc.gate_input, zebra.mapping.sources.SOFT_IN3, group=group
456
+ )
422
457
  yield from bps.abs_set(zebra.pc.num_gates, 1, group=group)
423
- yield from bps.abs_set(zebra.pc.pulse_input, DISCONNECT, group=group)
458
+ yield from bps.abs_set(
459
+ zebra.pc.pulse_input, zebra.mapping.sources.DISCONNECT, group=group
460
+ )
424
461
 
425
462
  # Logic Gates
426
463
  yield from bps.abs_set(
427
- zebra.logic_gates.and_gates[3].sources[1], PC_ARM, group=group
464
+ zebra.logic_gates.and_gates[3].sources[1],
465
+ zebra.mapping.sources.PC_ARM,
466
+ group=group,
428
467
  )
429
468
  yield from bps.abs_set(
430
- zebra.logic_gates.and_gates[3].sources[2], IN1_TTL, group=group
469
+ zebra.logic_gates.and_gates[3].sources[2],
470
+ zebra.mapping.sources.IN1_TTL,
471
+ group=group,
431
472
  )
432
473
 
433
474
  # Reset TTL out
@@ -1,7 +1,7 @@
1
1
  from bluesky.callbacks import CallbackBase
2
2
  from event_model.documents.run_start import RunStart
3
3
 
4
- from mx_bluesky.hyperion.log import LOGGER
4
+ from mx_bluesky.common.utils.log import LOGGER
5
5
 
6
6
  from .logging_callback import format_doc_for_log
7
7
 
@@ -5,10 +5,28 @@ from bluesky.callbacks import CallbackBase
5
5
  from dodal.devices.oav.utils import calculate_x_y_z_of_pixel
6
6
  from event_model.documents import Event
7
7
 
8
- from mx_bluesky.hyperion.log import LOGGER
8
+ from mx_bluesky.common.utils.log import LOGGER
9
9
 
10
10
 
11
11
  class GridParamUpdate(TypedDict):
12
+ """
13
+ Grid parameters extracted from the grid detection.
14
+ Positions are in motor-space.
15
+
16
+ Attributes:
17
+ x_start_um: x position of the centre of the first xy-gridscan box in microns
18
+ y_start_um: y position of the centre of the first xy-gridscan box in microns
19
+ y2_start_um: y position of the centre of the first xz-gridscan box in microns
20
+ z_start_um: z position of the centre of the first xy-gridscan box in microns
21
+ z2_start_um: z position of the centre of the first xz-gridscan box in microns
22
+ x_steps: Number of grid boxes in x-direction for xy- and xz- gridscans
23
+ y_steps: Number of grid boxes in y-direction for xy-gridscan
24
+ z_steps: Number of grid boxes in z-direction for xz-gridscan
25
+ x_step_size_um: x-dimension of the grid box
26
+ y_step_size_um: y-dimension of the grid box
27
+ z_step_size_um: z-dimension of the grid box
28
+ """
29
+
12
30
  x_start_um: float
13
31
  y_start_um: float
14
32
  y2_start_um: float