mx-bluesky 1.5.10__py3-none-any.whl → 1.5.12__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 (121) hide show
  1. mx_bluesky/_version.py +2 -2
  2. mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/__init__.py +0 -0
  3. mx_bluesky/beamlines/aithre_lasershaping/experiment_plans/robot_load_plan.py +198 -0
  4. mx_bluesky/beamlines/aithre_lasershaping/goniometer_controls.py +2 -2
  5. mx_bluesky/beamlines/aithre_lasershaping/parameters/__init__.py +0 -0
  6. mx_bluesky/beamlines/aithre_lasershaping/parameters/constants.py +17 -0
  7. mx_bluesky/beamlines/aithre_lasershaping/parameters/robot_load_parameters.py +13 -0
  8. mx_bluesky/beamlines/aithre_lasershaping/pin_tip_centring.py +31 -0
  9. mx_bluesky/beamlines/aithre_lasershaping/robot_load.py +80 -0
  10. mx_bluesky/beamlines/i02_1/parameters/gridscan.py +1 -1
  11. mx_bluesky/beamlines/i04/__init__.py +6 -2
  12. mx_bluesky/beamlines/i04/callbacks/murko_callback.py +27 -12
  13. mx_bluesky/beamlines/i04/experiment_plans/i04_grid_detect_then_xray_centre_plan.py +94 -20
  14. mx_bluesky/beamlines/i04/external_interaction/__init__.py +0 -0
  15. mx_bluesky/beamlines/i04/external_interaction/config_server.py +15 -0
  16. mx_bluesky/beamlines/i04/oav_centering_plans/__init__.py +0 -0
  17. mx_bluesky/beamlines/i04/oav_centering_plans/oav_imaging.py +115 -0
  18. mx_bluesky/beamlines/i04/parameters/__init__.py +0 -0
  19. mx_bluesky/beamlines/i04/parameters/constants.py +21 -0
  20. mx_bluesky/beamlines/i04/redis_to_murko_forwarder.py +24 -1
  21. mx_bluesky/beamlines/i04/thawing_plan.py +149 -154
  22. mx_bluesky/beamlines/i24/jungfrau_commissioning/experiment_plans/do_darks.py +55 -10
  23. mx_bluesky/beamlines/i24/jungfrau_commissioning/plan_stubs/do_external_acquisition.py +1 -1
  24. mx_bluesky/beamlines/i24/jungfrau_commissioning/plan_stubs/plan_utils.py +1 -1
  25. mx_bluesky/beamlines/i24/serial/__init__.py +7 -5
  26. mx_bluesky/beamlines/i24/serial/dcid.py +6 -7
  27. mx_bluesky/beamlines/i24/serial/extruder/{i24ssx_Extruder_Collect_py3v2.py → i24ssx_extruder_collect_py3v2.py} +70 -37
  28. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/CustomChip_py3v1.edl +11 -11
  29. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DetStage.edl +3 -3
  30. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +142 -142
  31. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/MappingLite-oxford_py3v1.edl +135 -135
  32. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/PMAC_Command.edl +8 -8
  33. mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/pumpprobe-py3v1.edl +13 -13
  34. mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_Collect_py3v1.py → i24ssx_chip_collect_py3v1.py} +12 -9
  35. mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_Manager_py3v1.py → i24ssx_chip_manager_py3v1.py} +81 -78
  36. mx_bluesky/beamlines/i24/serial/fixed_target/{i24ssx_Chip_StartUp_py3v1.py → i24ssx_chip_startup_py3v1.py} +3 -3
  37. mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +33 -33
  38. mx_bluesky/beamlines/i24/serial/log.py +11 -11
  39. mx_bluesky/beamlines/i24/serial/parameters/fixed_target/cs/cs_maker.json +3 -3
  40. mx_bluesky/beamlines/i24/serial/parameters/utils.py +5 -5
  41. mx_bluesky/beamlines/i24/serial/setup_beamline/ca.py +0 -12
  42. mx_bluesky/beamlines/i24/serial/setup_beamline/pv.py +122 -334
  43. mx_bluesky/beamlines/i24/serial/setup_beamline/pv_abstract.py +5 -5
  44. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +30 -251
  45. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +3 -3
  46. mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +4 -4
  47. mx_bluesky/beamlines/i24/serial/web_gui_plans/general_plans.py +103 -16
  48. mx_bluesky/beamlines/i24/serial/web_gui_plans/oav_plans.py +64 -0
  49. mx_bluesky/beamlines/i24/serial/write_nexus.py +4 -4
  50. mx_bluesky/common/device_setup_plans/gonio.py +28 -0
  51. mx_bluesky/common/device_setup_plans/manipulate_sample.py +8 -1
  52. mx_bluesky/common/device_setup_plans/robot_load_unload.py +1 -1
  53. mx_bluesky/common/device_setup_plans/setup_oav.py +8 -0
  54. mx_bluesky/common/device_setup_plans/setup_zebra_and_shutter.py +0 -5
  55. mx_bluesky/common/device_setup_plans/xbpm_feedback.py +8 -1
  56. mx_bluesky/common/experiment_plans/beamstop_check.py +229 -0
  57. mx_bluesky/common/experiment_plans/common_flyscan_xray_centre_plan.py +8 -6
  58. mx_bluesky/common/experiment_plans/common_grid_detect_then_xray_centre_plan.py +2 -2
  59. mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py +1 -1
  60. mx_bluesky/common/experiment_plans/inner_plans/read_hardware.py +7 -4
  61. mx_bluesky/common/experiment_plans/inner_plans/write_sample_status.py +2 -2
  62. mx_bluesky/common/experiment_plans/oav_snapshot_plan.py +1 -2
  63. mx_bluesky/{hyperion → common}/experiment_plans/pin_tip_centring_plan.py +23 -24
  64. mx_bluesky/common/external_interaction/callbacks/common/grid_detection_callback.py +5 -0
  65. mx_bluesky/common/external_interaction/callbacks/common/ispyb_callback_base.py +13 -15
  66. mx_bluesky/common/external_interaction/callbacks/common/ispyb_mapping.py +3 -5
  67. mx_bluesky/common/external_interaction/callbacks/common/plan_reactive_callback.py +1 -1
  68. mx_bluesky/common/external_interaction/callbacks/common/zocalo_callback.py +2 -2
  69. mx_bluesky/common/external_interaction/callbacks/sample_handling/sample_handling_callback.py +3 -3
  70. mx_bluesky/common/external_interaction/callbacks/xray_centre/ispyb_callback.py +12 -10
  71. mx_bluesky/common/external_interaction/callbacks/xray_centre/nexus_callback.py +2 -2
  72. mx_bluesky/common/external_interaction/config_server.py +4 -4
  73. mx_bluesky/common/external_interaction/ispyb/data_model.py +11 -4
  74. mx_bluesky/common/external_interaction/ispyb/exp_eye_store.py +163 -4
  75. mx_bluesky/common/external_interaction/ispyb/ispyb_store.py +76 -167
  76. mx_bluesky/common/external_interaction/ispyb/ispyb_utils.py +0 -14
  77. mx_bluesky/common/external_interaction/nexus/nexus_utils.py +2 -2
  78. mx_bluesky/common/external_interaction/nexus/write_nexus.py +3 -3
  79. mx_bluesky/common/parameters/components.py +1 -0
  80. mx_bluesky/common/parameters/constants.py +4 -3
  81. mx_bluesky/common/parameters/device_composites.py +4 -2
  82. mx_bluesky/common/parameters/gridscan.py +2 -2
  83. mx_bluesky/common/utils/exceptions.py +24 -7
  84. mx_bluesky/common/utils/log.py +13 -4
  85. mx_bluesky/common/utils/tracing.py +5 -5
  86. mx_bluesky/common/utils/utils.py +56 -8
  87. mx_bluesky/hyperion/__main__.py +6 -16
  88. mx_bluesky/hyperion/baton_handler.py +38 -14
  89. mx_bluesky/hyperion/device_setup_plans/utils.py +1 -1
  90. mx_bluesky/hyperion/experiment_plans/experiment_registry.py +1 -1
  91. mx_bluesky/hyperion/experiment_plans/hyperion_flyscan_xray_centre_plan.py +15 -13
  92. mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +2 -2
  93. mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +9 -9
  94. mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +7 -8
  95. mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +3 -10
  96. mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +4 -2
  97. mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +10 -4
  98. mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -2
  99. mx_bluesky/hyperion/experiment_plans/udc_default_state.py +160 -0
  100. mx_bluesky/hyperion/external_interaction/agamemnon.py +3 -3
  101. mx_bluesky/hyperion/external_interaction/callbacks/__main__.py +2 -2
  102. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +3 -3
  103. mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +1 -0
  104. mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +3 -6
  105. mx_bluesky/hyperion/external_interaction/config_server.py +5 -5
  106. mx_bluesky/hyperion/parameters/constants.py +11 -4
  107. mx_bluesky/hyperion/parameters/device_composites.py +2 -2
  108. mx_bluesky/hyperion/parameters/gridscan.py +4 -4
  109. mx_bluesky/hyperion/parameters/robot_load.py +1 -9
  110. mx_bluesky/hyperion/plan_runner.py +6 -6
  111. mx_bluesky/hyperion/runner.py +10 -8
  112. mx_bluesky/jupyter_example.ipynb +3 -3
  113. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/METADATA +9 -7
  114. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/RECORD +118 -104
  115. mx_bluesky/common/experiment_plans/inner_plans/udc_default_state.py +0 -65
  116. mx_bluesky/common/external_interaction/callbacks/common/logging_callback.py +0 -29
  117. mx_bluesky/hyperion/device_setup_plans/smargon.py +0 -25
  118. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/WHEEL +0 -0
  119. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/entry_points.txt +0 -0
  120. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/licenses/LICENSE +0 -0
  121. {mx_bluesky-1.5.10.dist-info → mx_bluesky-1.5.12.dist-info}/top_level.txt +0 -0
@@ -1,18 +1,15 @@
1
- from collections.abc import Callable
2
- from functools import partial
3
-
4
1
  import bluesky.plan_stubs as bps
5
2
  import bluesky.preprocessors as bpp
6
- from bluesky.preprocessors import run_decorator, subs_decorator
3
+ from bluesky.preprocessors import contingency_decorator, run_decorator, subs_decorator
7
4
  from bluesky.utils import MsgGenerator
8
5
  from dodal.common import inject
9
6
  from dodal.devices.i04.constants import RedisConstants
10
7
  from dodal.devices.i04.murko_results import MurkoResultsDevice
11
- from dodal.devices.oav.oav_detector import OAV
12
8
  from dodal.devices.oav.oav_to_redis_forwarder import OAVToRedisForwarder, Source
13
9
  from dodal.devices.robot import BartRobot
14
10
  from dodal.devices.smargon import Smargon
15
11
  from dodal.devices.thawer import OnOff, Thawer
12
+ from dodal.log import LOGGER
16
13
 
17
14
  from mx_bluesky.beamlines.i04.callbacks.murko_callback import MurkoCallback
18
15
 
@@ -29,53 +26,26 @@ def thaw(
29
26
 
30
27
  Args:
31
28
  time_to_thaw (float): Time to thaw for, in seconds.
32
- rotation (float, optional): How much to rotate by whilst thawing, in degrees.
33
- Defaults to 360.
34
- ... devices: These are the specific ophyd-devices used for the plan, the
35
- defaults are always correct.
29
+ rotation (float): How much to rotate by whilst thawing, in degrees.
30
+ thawer (Thawer): The thawing device.
31
+ smargon (Smargon): The smargon used to rotate.
36
32
  """
37
- yield from _thaw(time_to_thaw, rotation, thawer, smargon)
38
-
39
-
40
- def thaw_and_stream_to_redis(
41
- time_to_thaw: float,
42
- rotation: float = 360,
43
- robot: BartRobot = inject("robot"),
44
- thawer: Thawer = inject("thawer"),
45
- smargon: Smargon = inject("smargon"),
46
- oav: OAV = inject("oav_full_screen"),
47
- oav_to_redis_forwarder: OAVToRedisForwarder = inject("oav_to_redis_forwarder"),
48
- ) -> MsgGenerator:
49
- """Turns on the thawer and rotates the sample by {rotation} degrees to thaw it, then
50
- rotates {rotation} degrees back and turns the thawer off. The speed of the goniometer
51
- is set such that the process takes whole process will take {time_to_thaw} time.
33
+ initial_velocity = yield from bps.rd(smargon.omega.velocity)
34
+ new_velocity = abs(rotation / time_to_thaw) * 2.0
52
35
 
53
- At the same time streams OAV images to redis for later processing (e.g. by murko).
54
- On the first rotation the images from the large ROI are streamed, on the second the
55
- smaller ROI is used.
36
+ def do_thaw():
37
+ yield from bps.abs_set(smargon.omega.velocity, new_velocity, wait=True)
38
+ yield from bps.abs_set(thawer, OnOff.ON, wait=True)
39
+ yield from bps.rel_set(smargon.omega, rotation, wait=True)
40
+ yield from bps.rel_set(smargon.omega, -rotation, wait=True)
56
41
 
57
- Args:
58
- time_to_thaw (float): Time to thaw for, in seconds.
59
- rotation (float, optional): How much to rotate by whilst thawing, in degrees.
60
- Defaults to 360.
61
- ... devices: These are the specific ophyd-devices used for the plan, the
62
- defaults are always correct
63
- """
42
+ def cleanup():
43
+ yield from bps.abs_set(smargon.omega.velocity, initial_velocity, wait=True)
44
+ yield from bps.abs_set(thawer, OnOff.OFF, wait=True)
64
45
 
65
- def switch_forwarder_to_ROI() -> MsgGenerator:
66
- yield from bps.complete(oav_to_redis_forwarder, wait=True)
67
- yield from bps.mv(oav_to_redis_forwarder.selected_source, Source.ROI.value)
68
- yield from bps.kickoff(oav_to_redis_forwarder, wait=True)
69
-
70
- yield from _thaw_and_stream_to_redis(
71
- time_to_thaw,
72
- rotation,
73
- robot,
74
- thawer,
75
- smargon,
76
- oav,
77
- oav_to_redis_forwarder,
78
- switch_forwarder_to_ROI,
46
+ yield from bpp.contingency_wrapper(
47
+ do_thaw(),
48
+ final_plan=cleanup,
79
49
  )
80
50
 
81
51
 
@@ -85,14 +55,13 @@ def thaw_and_murko_centre(
85
55
  robot: BartRobot = inject("robot"),
86
56
  thawer: Thawer = inject("thawer"),
87
57
  smargon: Smargon = inject("smargon"),
88
- oav: OAV = inject("oav_full_screen"),
89
58
  murko_results: MurkoResultsDevice = inject("murko_results"),
90
59
  oav_to_redis_forwarder: OAVToRedisForwarder = inject("oav_to_redis_forwarder"),
91
60
  ) -> MsgGenerator:
92
61
  """Thaws the sample and centres it using murko by:
93
62
  1. Turns on the thawer
94
63
  2. Rotates the sample by {rotation} degrees, whilst this is happening images from
95
- the large ROI of the OAV are being fed to murko
64
+ the full screen OAV are being fed to murko
96
65
  3. After the rotation has completed moves to the average centre returned by murko
97
66
  from these images
98
67
  4. Rotate {rotation} degrees back to the start, whilst this is happening images
@@ -109,147 +78,173 @@ def thaw_and_murko_centre(
109
78
  ... devices: These are the specific ophyd-devices used for the plan, the
110
79
  defaults are always correct
111
80
  """
81
+ murko_results_group = "get_results"
112
82
 
113
- MURKO_RESULTS_GROUP = "get_results"
83
+ sample_id = yield from bps.rd(robot.sample_id)
84
+ sample_id = int(sample_id)
114
85
 
115
- def centre_then_switch_forwarder_to_ROI() -> MsgGenerator:
116
- yield from bps.complete(oav_to_redis_forwarder, wait=True)
86
+ oav_fs = oav_to_redis_forwarder.sources[Source.FULL_SCREEN].oav_ref()
117
87
 
118
- yield from bps.mv(oav_to_redis_forwarder.selected_source, Source.ROI.value)
88
+ initial_zoom_level = yield from bps.rd(oav_fs.zoom_controller.level)
89
+ initial_velocity = yield from bps.rd(smargon.omega.velocity)
90
+ new_velocity = abs(rotation / time_to_thaw) * 2.0
91
+ murko_callback = MurkoCallback(
92
+ RedisConstants.REDIS_HOST,
93
+ RedisConstants.REDIS_PASSWORD,
94
+ RedisConstants.MURKO_REDIS_DB,
95
+ )
96
+
97
+ def cleanup():
98
+ yield from bps.mv(oav_fs.zoom_controller.level, initial_zoom_level)
99
+ yield from bps.abs_set(smargon.omega.velocity, initial_velocity, wait=True)
100
+ yield from bps.abs_set(thawer, OnOff.OFF, wait=True)
101
+
102
+ def centre_from_murko():
103
+ yield from bps.wait(murko_results_group)
119
104
 
120
- yield from bps.wait(MURKO_RESULTS_GROUP)
121
105
  x_predict = yield from bps.rd(murko_results.x_mm)
122
106
  y_predict = yield from bps.rd(murko_results.y_mm)
123
107
  z_predict = yield from bps.rd(murko_results.z_mm)
124
108
 
109
+ LOGGER.info(f"Got results: {x_predict, y_predict, z_predict}")
110
+
125
111
  yield from bps.rel_set(smargon.x, x_predict)
126
112
  yield from bps.rel_set(smargon.y, y_predict)
127
113
  yield from bps.rel_set(smargon.z, z_predict)
128
114
 
129
- yield from bps.kickoff(oav_to_redis_forwarder, wait=True)
115
+ @subs_decorator(murko_callback)
116
+ @contingency_decorator(final_plan=cleanup)
117
+ def do_thaw_and_murko_centre():
118
+ yield from bps.mv(
119
+ murko_results.sample_id,
120
+ str(sample_id),
121
+ oav_to_redis_forwarder.sample_id,
122
+ sample_id,
123
+ oav_fs.zoom_controller.level,
124
+ "1.0x",
125
+ )
126
+ yield from bps.abs_set(smargon.omega.velocity, new_velocity, wait=True)
127
+ yield from bps.abs_set(thawer, OnOff.ON, wait=True)
128
+
129
+ def rotate_in_one_direction_then_murko_centre(
130
+ rotation: float, oav_mode: Source
131
+ ):
132
+ @run_decorator(md={"sample_id": sample_id})
133
+ def rotate_in_one_direction_and_start_murko_and_stream_to_redis():
134
+ yield from bps.stage(murko_results, wait=True)
135
+ yield from bps.trigger(murko_results, group=murko_results_group)
130
136
 
131
- sample_id = yield from bps.rd(robot.sample_id)
132
- yield from bps.mv(murko_results.sample_id, str(sample_id))
137
+ yield from _rotate_in_one_direction_and_stream_to_redis(
138
+ smargon, oav_to_redis_forwarder, oav_mode, rotation
139
+ )
133
140
 
134
- yield from bps.stage(murko_results, wait=True)
135
- yield from bps.trigger(murko_results, group=MURKO_RESULTS_GROUP)
141
+ yield from rotate_in_one_direction_and_start_murko_and_stream_to_redis()
136
142
 
137
- yield from bpp.contingency_wrapper(
138
- _thaw_and_stream_to_redis(
139
- time_to_thaw,
140
- rotation,
141
- robot,
142
- thawer,
143
- smargon,
144
- oav,
145
- oav_to_redis_forwarder,
146
- centre_then_switch_forwarder_to_ROI,
147
- ),
148
- final_plan=partial(bps.unstage, murko_results, wait=True),
149
- )
143
+ yield from centre_from_murko()
144
+ yield from bps.unstage(murko_results, wait=True)
145
+
146
+ yield from rotate_in_one_direction_then_murko_centre(
147
+ rotation, Source.FULL_SCREEN
148
+ )
149
+ yield from rotate_in_one_direction_then_murko_centre(-rotation, Source.ROI)
150
150
 
151
+ yield from do_thaw_and_murko_centre()
151
152
 
152
- def _thaw(
153
+
154
+ def thaw_and_stream_to_redis(
153
155
  time_to_thaw: float,
154
- rotation: float,
155
- thawer: Thawer,
156
- smargon: Smargon,
157
- plan_between_rotations: Callable[[], MsgGenerator] | None = None,
156
+ rotation: float = 360,
157
+ robot: BartRobot = inject("robot"),
158
+ thawer: Thawer = inject("thawer"),
159
+ smargon: Smargon = inject("smargon"),
160
+ oav_to_redis_forwarder: OAVToRedisForwarder = inject("oav_to_redis_forwarder"),
158
161
  ) -> MsgGenerator:
159
162
  """Turns on the thawer and rotates the sample by {rotation} degrees to thaw it, then
160
163
  rotates {rotation} degrees back and turns the thawer off. The speed of the goniometer
161
164
  is set such that the process takes whole process will take {time_to_thaw} time.
162
165
 
166
+ At the same time streams OAV images to redis for later processing (e.g. by murko).
167
+ On the first rotation the images from the large ROI are streamed, on the second the
168
+ smaller ROI is used.
169
+
163
170
  Args:
164
171
  time_to_thaw (float): Time to thaw for, in seconds.
165
- rotation (float): How much to rotate by whilst thawing, in degrees.
166
- thawer (Thawer): The thawing device.
167
- smargon (Smargon): The smargon used to rotate.
168
- plan_between_rotations (MsgGenerator, optional): A plan to run between rotations
169
- of the smargon. Defaults to no plan.
172
+ rotation (float, optional): How much to rotate by whilst thawing, in degrees.
173
+ Defaults to 360.
174
+ ... devices: These are the specific ophyd-devices used for the plan, the
175
+ defaults are always correct
170
176
  """
171
- inital_velocity = yield from bps.rd(smargon.omega.velocity)
172
- new_velocity = abs(rotation / time_to_thaw) * 2.0
173
-
174
- def do_thaw():
175
- yield from bps.abs_set(smargon.omega.velocity, new_velocity, wait=True)
176
- yield from bps.abs_set(thawer.control, OnOff.ON, wait=True)
177
- yield from bps.rel_set(smargon.omega, rotation, wait=True)
178
- if plan_between_rotations:
179
- yield from plan_between_rotations()
180
- yield from bps.rel_set(smargon.omega, -rotation, wait=True)
181
-
182
- def cleanup():
183
- yield from bps.abs_set(smargon.omega.velocity, inital_velocity, wait=True)
184
- yield from bps.abs_set(thawer.control, OnOff.OFF, wait=True)
185
-
186
- # Always cleanup even if there is a failure
187
- yield from bpp.contingency_wrapper(
188
- do_thaw(),
189
- final_plan=cleanup,
190
- )
191
-
192
-
193
- def _thaw_and_stream_to_redis(
194
- time_to_thaw: float,
195
- rotation: float,
196
- robot: BartRobot,
197
- thawer: Thawer,
198
- smargon: Smargon,
199
- oav: OAV,
200
- oav_to_redis_forwarder: OAVToRedisForwarder,
201
- plan_between_rotations: Callable[[], MsgGenerator],
202
- ) -> MsgGenerator:
203
- zoom_percentage = yield from bps.rd(oav.zoom_controller.percentage)
204
177
  sample_id = yield from bps.rd(robot.sample_id)
205
-
206
178
  sample_id = int(sample_id)
207
- zoom_level_before_thawing = yield from bps.rd(oav.zoom_controller.level)
208
179
 
209
- yield from bps.mv(oav.zoom_controller.level, "1.0x")
180
+ oav_fs = oav_to_redis_forwarder.sources[Source.FULL_SCREEN].oav_ref()
210
181
 
211
- microns_per_pixel_x = yield from bps.rd(oav.microns_per_pixel_x)
212
- microns_per_pixel_y = yield from bps.rd(oav.microns_per_pixel_y)
213
- beam_centre_i = yield from bps.rd(oav.beam_centre_i)
214
- beam_centre_j = yield from bps.rd(oav.beam_centre_j)
182
+ initial_zoom_level = yield from bps.rd(oav_fs.zoom_controller.level)
183
+ initial_velocity = yield from bps.rd(smargon.omega.velocity)
184
+ new_velocity = abs(rotation / time_to_thaw) * 2.0
215
185
 
216
- @subs_decorator(
217
- MurkoCallback(
218
- RedisConstants.REDIS_HOST,
219
- RedisConstants.REDIS_PASSWORD,
220
- RedisConstants.MURKO_REDIS_DB,
221
- )
222
- )
223
- @run_decorator(
224
- md={
225
- "microns_per_x_pixel": microns_per_pixel_x,
226
- "microns_per_y_pixel": microns_per_pixel_y,
227
- "beam_centre_i": beam_centre_i,
228
- "beam_centre_j": beam_centre_j,
229
- "zoom_percentage": zoom_percentage,
230
- "sample_id": sample_id,
231
- }
186
+ murko_callback = MurkoCallback(
187
+ RedisConstants.REDIS_HOST,
188
+ RedisConstants.REDIS_PASSWORD,
189
+ RedisConstants.MURKO_REDIS_DB,
232
190
  )
233
- def _main_plan():
191
+
192
+ def cleanup():
193
+ yield from bps.mv(oav_fs.zoom_controller.level, initial_zoom_level)
194
+ yield from bps.abs_set(smargon.omega.velocity, initial_velocity, wait=True)
195
+ yield from bps.abs_set(thawer, OnOff.OFF, wait=True)
196
+
197
+ @subs_decorator(murko_callback)
198
+ @contingency_decorator(final_plan=cleanup)
199
+ def do_thaw_and_stream_to_redis():
234
200
  yield from bps.mv(
235
201
  oav_to_redis_forwarder.sample_id,
236
202
  sample_id,
237
- oav_to_redis_forwarder.selected_source,
238
- Source.FULL_SCREEN.value,
203
+ oav_fs.zoom_controller.level,
204
+ "1.0x",
239
205
  )
240
-
241
- yield from bps.kickoff(oav_to_redis_forwarder, wait=True)
242
- yield from bps.monitor(smargon.omega.user_readback, name="smargon")
243
- yield from bps.monitor(oav_to_redis_forwarder.uuid, name="oav")
244
- yield from _thaw(
245
- time_to_thaw, rotation, thawer, smargon, plan_between_rotations
206
+ yield from bps.abs_set(smargon.omega.velocity, new_velocity, wait=True)
207
+ yield from bps.abs_set(thawer, OnOff.ON, wait=True)
208
+
209
+ @run_decorator(md={"sample_id": sample_id})
210
+ def rotate_in_one_direction_and_stream_to_redis(
211
+ rotation: float, oav_mode: Source
212
+ ):
213
+ yield from _rotate_in_one_direction_and_stream_to_redis(
214
+ smargon, oav_to_redis_forwarder, oav_mode, rotation
215
+ )
216
+
217
+ yield from rotate_in_one_direction_and_stream_to_redis(
218
+ rotation, Source.FULL_SCREEN
246
219
  )
247
- yield from bps.complete(oav_to_redis_forwarder)
220
+ yield from rotate_in_one_direction_and_stream_to_redis(-rotation, Source.ROI)
248
221
 
249
- def cleanup():
250
- yield from bps.mv(oav.zoom_controller.level, zoom_level_before_thawing)
222
+ yield from do_thaw_and_stream_to_redis()
251
223
 
252
- yield from bpp.contingency_wrapper(
253
- _main_plan(),
254
- final_plan=cleanup,
224
+
225
+ def _rotate_in_one_direction_and_stream_to_redis(
226
+ smargon: Smargon,
227
+ oav_to_redis_forwarder: OAVToRedisForwarder,
228
+ oav_mode: Source,
229
+ rotation: float,
230
+ ):
231
+ def get_metadata_from_current_oav():
232
+ current_source_idx = yield from bps.rd(oav_to_redis_forwarder.selected_source)
233
+ oav = oav_to_redis_forwarder.sources[current_source_idx].oav_ref()
234
+ yield from bps.create()
235
+ oav_info = yield from bps.read(oav)
236
+ LOGGER.info(f"Got oav information: {oav_info}")
237
+ yield from bps.save()
238
+
239
+ yield from bps.mv(
240
+ oav_to_redis_forwarder.selected_source,
241
+ oav_mode.value,
255
242
  )
243
+
244
+ yield from get_metadata_from_current_oav()
245
+ yield from bps.monitor(smargon.omega.user_readback, name="smargon")
246
+ yield from bps.monitor(oav_to_redis_forwarder.uuid, name="oav")
247
+
248
+ yield from bps.kickoff(oav_to_redis_forwarder, wait=True)
249
+ yield from bps.rel_set(smargon.omega, rotation, wait=True)
250
+ yield from bps.complete(oav_to_redis_forwarder, wait=True)
@@ -3,10 +3,10 @@ from bluesky import plan_stubs as bps
3
3
  from bluesky.utils import MsgGenerator
4
4
  from dodal.common import inject
5
5
  from dodal.devices.i24.commissioning_jungfrau import CommissioningJungfrau
6
- from ophyd_async.core import WatchableAsyncStatus
7
6
  from ophyd_async.fastcs.jungfrau import (
8
7
  AcquisitionType,
9
8
  GainMode,
9
+ create_jungfrau_internal_triggering_info,
10
10
  create_jungfrau_pedestal_triggering_info,
11
11
  )
12
12
  from pydantic import PositiveInt
@@ -18,6 +18,7 @@ from mx_bluesky.beamlines.i24.jungfrau_commissioning.plan_stubs.plan_utils impor
18
18
  from mx_bluesky.common.utils.log import LOGGER
19
19
 
20
20
  PEDESTAL_DARKS_RUN = "PEDESTAL DARKS RUN"
21
+ STANDARD_DARKS_RUN = "STANDARD DARKS RUN"
21
22
 
22
23
 
23
24
  def do_pedestal_darks(
@@ -26,7 +27,7 @@ def do_pedestal_darks(
26
27
  pedestal_loops: PositiveInt = 200,
27
28
  jungfrau: CommissioningJungfrau = inject("jungfrau"),
28
29
  path_of_output_file: str | None = None,
29
- ) -> MsgGenerator[WatchableAsyncStatus]:
30
+ ) -> MsgGenerator:
30
31
  """Acquire darks in pedestal mode, using dynamic gain mode. This calibrates the offsets
31
32
  for the jungfrau, and must be performed before acquiring real data in dynamic gain mode.
32
33
 
@@ -38,6 +39,9 @@ def do_pedestal_darks(
38
39
  4. Do the first three steps a second time, except use ForceSwitchG2 instead of ForceSwitchG1
39
40
  during step 2.
40
41
 
42
+ A pedestal scan should be acquired when detector configuration and environmental conditions change, but due to small
43
+ in instabilities in beamline conditions, it is recommended to run a pedestal scan on roughly an hourly basis.
44
+
41
45
  Args:
42
46
  exp_time_s: Length of detector exposure for each frame.
43
47
  pedestal_frames: Number of frames acquired per pedestal loop.
@@ -66,13 +70,54 @@ def do_pedestal_darks(
66
70
  jungfrau.drv.gain_mode,
67
71
  GainMode.DYNAMIC,
68
72
  )
69
- return (
70
- yield from fly_jungfrau(
71
- jungfrau,
72
- trigger_info,
73
- wait=True,
74
- log_on_percentage_prefix="Jungfrau pedestal dynamic gain mode darks triggers recieved",
75
- )
73
+ yield from fly_jungfrau(
74
+ jungfrau,
75
+ trigger_info,
76
+ wait=True,
77
+ log_on_percentage_prefix="Jungfrau pedestal dynamic gain mode darks triggers received",
78
+ )
79
+
80
+ yield from _do_decorated_plan()
81
+
82
+
83
+ def do_non_pedestal_darks(
84
+ gain_mode: GainMode,
85
+ exp_time_s: float = 0.001,
86
+ total_triggers: PositiveInt = 1000,
87
+ jungfrau: CommissioningJungfrau = inject("jungfrau"),
88
+ path_of_output_file: str | None = None,
89
+ ) -> MsgGenerator:
90
+ """Internally take a set of images at a given gain mode.
91
+
92
+ Non-pedestal darks are useful for detector panel cross-checks and for calculating masks.
93
+
94
+ Args:
95
+ gain_mode: Which gain mode to put the Jungfrau into before starting the acquisition.
96
+ exp_time_s: Length of detector exposure for each trigger.
97
+ total_triggers: Total triggers for the dark scan.
98
+ jungfrau: Jungfrau device
99
+ path_of_output_file: Absolute path of the detector file output, including file name. If None, then use the PathProvider
100
+ set during Jungfrau device instantiation
101
+ """
102
+
103
+ @bpp.set_run_key_decorator(STANDARD_DARKS_RUN)
104
+ @bpp.run_decorator(md={"subplan_name": STANDARD_DARKS_RUN})
105
+ @bpp.stage_decorator([jungfrau])
106
+ def _do_decorated_plan():
107
+ if path_of_output_file:
108
+ override_file_path(jungfrau, path_of_output_file)
109
+
110
+ trigger_info = create_jungfrau_internal_triggering_info(
111
+ total_triggers, exp_time_s
112
+ )
113
+
114
+ yield from bps.mv(jungfrau.drv.gain_mode, gain_mode)
115
+
116
+ yield from fly_jungfrau(
117
+ jungfrau,
118
+ trigger_info,
119
+ wait=True,
120
+ log_on_percentage_prefix=f"Jungfrau {gain_mode} gain mode darks triggers received",
76
121
  )
77
122
 
78
- return (yield from _do_decorated_plan())
123
+ yield from _do_decorated_plan()
@@ -30,7 +30,7 @@ def do_external_acquisition(
30
30
 
31
31
  Args:
32
32
  exp_time_s: Length of detector exposure for each frame.
33
- total_triggers: Number of external triggers recieved before acquisition is marked as complete.
33
+ total_triggers: Number of external triggers received before acquisition is marked as complete.
34
34
  jungfrau: Jungfrau device
35
35
  output_file_name: Absolute path of the detector file output, including file name. If None, then use the PathProvider
36
36
  set during jungfrau device instantiation
@@ -21,7 +21,7 @@ def fly_jungfrau(
21
21
  jungfrau: CommissioningJungfrau,
22
22
  trigger_info: TriggerInfo,
23
23
  wait: bool = False,
24
- log_on_percentage_prefix="Jungfrau data collection triggers recieved",
24
+ log_on_percentage_prefix="Jungfrau data collection triggers received",
25
25
  ) -> MsgGenerator[WatchableAsyncStatus]:
26
26
  """Stage, prepare, and kickoff Jungfrau with a configured TriggerInfo. Optionally wait
27
27
  for completion.
@@ -3,19 +3,20 @@ from mx_bluesky.beamlines.i24.serial.web_gui_plans.general_plans import (
3
3
  gui_move_backlight,
4
4
  gui_move_detector,
5
5
  gui_run_chip_collection,
6
+ gui_run_extruder_collection,
7
+ gui_set_fiducial_0,
6
8
  gui_set_zoom_level,
7
- gui_sleep,
8
9
  gui_stage_move_on_click,
9
10
  )
10
11
 
11
- from .extruder.i24ssx_Extruder_Collect_py3v2 import (
12
+ from .extruder.i24ssx_extruder_collect_py3v2 import (
12
13
  enter_hutch,
13
14
  initialise_extruder,
14
15
  laser_check,
15
16
  run_extruder_plan,
16
17
  )
17
- from .fixed_target.i24ssx_Chip_Collect_py3v1 import run_fixed_target_plan
18
- from .fixed_target.i24ssx_Chip_Manager_py3v1 import (
18
+ from .fixed_target.i24ssx_chip_collect_py3v1 import run_fixed_target_plan
19
+ from .fixed_target.i24ssx_chip_manager_py3v1 import (
19
20
  block_check,
20
21
  cs_maker,
21
22
  cs_reset,
@@ -56,9 +57,10 @@ __all__ = [
56
57
  # GUI plans
57
58
  "gui_stage_move_on_click",
58
59
  "gui_gonio_move_on_click",
59
- "gui_sleep",
60
60
  "gui_move_detector",
61
61
  "gui_run_chip_collection",
62
62
  "gui_move_backlight",
63
63
  "gui_set_zoom_level",
64
+ "gui_set_fiducial_0",
65
+ "gui_run_extruder_collection",
64
66
  ]
@@ -95,7 +95,7 @@ class DCID:
95
95
 
96
96
  Attributes:
97
97
  error:
98
- If an error has occured. This will be set, even if emit_errors = True
98
+ If an error has occurred. This will be set, even if emit_errors = True
99
99
  """
100
100
 
101
101
  def __init__(
@@ -112,6 +112,8 @@ class DCID:
112
112
  match expt_params.detector_name:
113
113
  case "eiger":
114
114
  self.detector = Eiger()
115
+ case _:
116
+ raise ValueError("Unknown detector:", expt_params.detector_name)
115
117
 
116
118
  self.server = server or DEFAULT_ISPYB_SERVER
117
119
  self.emit_errors = emit_errors
@@ -144,7 +146,7 @@ class DCID:
144
146
  try:
145
147
  if not start_time:
146
148
  start_time = datetime.datetime.now().astimezone()
147
- elif not start_time.timetz:
149
+ else:
148
150
  start_time = start_time.astimezone()
149
151
 
150
152
  resolution = get_resolution(
@@ -156,10 +158,7 @@ class DCID:
156
158
  transmission = self.parameters.transmission * 100
157
159
  xbeam, ybeam = beam_settings.beam_center_in_mm
158
160
 
159
- if isinstance(self.detector, Eiger):
160
- startImageNumber = 1
161
- else:
162
- raise ValueError("Unknown detector:", self.detector)
161
+ start_image_number = 1
163
162
 
164
163
  events = [
165
164
  {
@@ -201,7 +200,7 @@ class DCID:
201
200
  "imageDirectory": image_dir,
202
201
  "numberOfImages": num_images,
203
202
  "resolution": resolution,
204
- "startImageNumber": startImageNumber,
203
+ "startImageNumber": start_image_number,
205
204
  "startTime": start_time.isoformat(),
206
205
  "transmission": transmission,
207
206
  "visit": self.parameters.visit.name,