dls-dodal 1.69.0__py3-none-any.whl → 2.0.0__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 (282) hide show
  1. {dls_dodal-1.69.0.dist-info → dls_dodal-2.0.0.dist-info}/METADATA +1 -1
  2. dls_dodal-2.0.0.dist-info/RECORD +354 -0
  3. {dls_dodal-1.69.0.dist-info → dls_dodal-2.0.0.dist-info}/WHEEL +1 -1
  4. dodal/_version.py +2 -2
  5. dodal/beamlines/__init__.py +10 -17
  6. dodal/beamlines/adsim.py +17 -17
  7. dodal/beamlines/b01_1.py +11 -0
  8. dodal/beamlines/b07.py +17 -21
  9. dodal/beamlines/b07_1.py +20 -22
  10. dodal/beamlines/b07_shared.py +12 -0
  11. dodal/beamlines/b16.py +1 -1
  12. dodal/beamlines/b21.py +15 -6
  13. dodal/beamlines/i02_1.py +3 -3
  14. dodal/beamlines/i02_2.py +1 -1
  15. dodal/beamlines/i03.py +4 -4
  16. dodal/beamlines/i04.py +16 -8
  17. dodal/beamlines/i05.py +7 -45
  18. dodal/beamlines/i05_1.py +4 -13
  19. dodal/beamlines/i05_shared.py +51 -0
  20. dodal/beamlines/i06_1.py +7 -5
  21. dodal/beamlines/{i06.py → i06_shared.py} +25 -14
  22. dodal/beamlines/i07.py +14 -16
  23. dodal/beamlines/i09.py +54 -51
  24. dodal/beamlines/i09_1.py +25 -64
  25. dodal/beamlines/i09_1_shared.py +61 -0
  26. dodal/beamlines/i09_2.py +6 -100
  27. dodal/beamlines/i09_2_shared.py +110 -0
  28. dodal/beamlines/i10.py +60 -54
  29. dodal/beamlines/i10_1.py +99 -10
  30. dodal/beamlines/{i10_optics.py → i10_shared.py} +80 -66
  31. dodal/beamlines/i11.py +31 -18
  32. dodal/beamlines/i13_1.py +1 -1
  33. dodal/beamlines/i15.py +6 -6
  34. dodal/beamlines/i15_1.py +6 -6
  35. dodal/beamlines/i17.py +37 -28
  36. dodal/beamlines/i18.py +3 -4
  37. dodal/beamlines/i19_1.py +95 -34
  38. dodal/beamlines/i19_2.py +68 -52
  39. dodal/beamlines/i19_optics.py +26 -13
  40. dodal/beamlines/i20_1.py +6 -14
  41. dodal/beamlines/i21.py +35 -28
  42. dodal/beamlines/i22.py +19 -4
  43. dodal/beamlines/i23.py +1 -2
  44. dodal/beamlines/i24.py +11 -10
  45. dodal/beamlines/k07.py +99 -5
  46. dodal/beamlines/p38.py +3 -3
  47. dodal/beamlines/p60.py +28 -17
  48. dodal/beamlines/p99.py +16 -15
  49. dodal/beamlines/training_rig.py +20 -12
  50. dodal/cli.py +36 -2
  51. dodal/common/beamlines/beamline_parameters.py +2 -1
  52. dodal/common/beamlines/beamline_utils.py +11 -9
  53. dodal/common/beamlines/commissioning_mode.py +6 -3
  54. dodal/common/coordination.py +12 -14
  55. dodal/common/crystal_metadata.py +5 -8
  56. dodal/common/device_utils.py +4 -3
  57. dodal/common/maths.py +28 -40
  58. dodal/common/udc_directory_provider.py +13 -8
  59. dodal/common/visit.py +18 -21
  60. dodal/common/watcher_utils.py +13 -12
  61. dodal/device_manager.py +94 -54
  62. dodal/devices/aperturescatterguard.py +26 -27
  63. dodal/devices/areadetector/plugins/cam.py +1 -3
  64. dodal/devices/areadetector/plugins/mjpg.py +6 -5
  65. dodal/devices/attenuator/attenuator.py +12 -11
  66. dodal/devices/beamlines/b07/__init__.py +3 -0
  67. dodal/devices/{b07_1 → beamlines/b07_1}/__init__.py +2 -2
  68. dodal/devices/{b07_1 → beamlines/b07_1}/ccmc.py +5 -10
  69. dodal/devices/{b16 → beamlines/b16}/detector.py +2 -3
  70. dodal/devices/{i02_1 → beamlines/i02_1}/fast_grid_scan.py +2 -3
  71. dodal/devices/{i02_1 → beamlines/i02_1}/sample_motors.py +1 -1
  72. dodal/devices/{i03 → beamlines/i03}/beamsize.py +11 -7
  73. dodal/devices/{i03 → beamlines/i03}/dcm.py +1 -2
  74. dodal/devices/{i03 → beamlines/i03}/undulator_dcm.py +4 -5
  75. dodal/devices/beamlines/i04/beam_centre.py +151 -0
  76. dodal/devices/{i04 → beamlines/i04}/beamsize.py +11 -7
  77. dodal/devices/{i04 → beamlines/i04}/murko_results.py +5 -5
  78. dodal/devices/{i04 → beamlines/i04}/transfocator.py +10 -15
  79. dodal/devices/beamlines/i05/__init__.py +3 -0
  80. dodal/devices/beamlines/i06_shared/__init__.py +3 -0
  81. dodal/devices/beamlines/i06_shared/i06_enum.py +7 -0
  82. dodal/devices/{i07 → beamlines/i07}/dcm.py +2 -3
  83. dodal/devices/{i07 → beamlines/i07}/id.py +8 -9
  84. dodal/devices/beamlines/i09/__init__.py +3 -0
  85. dodal/devices/{i09_1_shared → beamlines/i09_1_shared}/hard_energy.py +5 -6
  86. dodal/devices/{i09_1_shared → beamlines/i09_1_shared}/hard_undulator_functions.py +19 -16
  87. dodal/devices/{i10 → beamlines/i10}/diagnostics.py +4 -3
  88. dodal/devices/{i10 → beamlines/i10}/i10_apple2.py +31 -45
  89. dodal/devices/{i10 → beamlines/i10}/rasor/rasor_current_amp.py +1 -24
  90. dodal/devices/{i10 → beamlines/i10}/rasor/rasor_motors.py +2 -2
  91. dodal/devices/{i10 → beamlines/i10}/slits.py +5 -3
  92. dodal/devices/beamlines/i10_1/__init__.py +9 -0
  93. dodal/devices/beamlines/i10_1/electromagnet/magnet.py +16 -0
  94. dodal/devices/beamlines/i10_1/electromagnet/stages.py +14 -0
  95. dodal/devices/beamlines/i10_1/scaler_cards.py +13 -0
  96. dodal/devices/{i11 → beamlines/i11}/cyberstar_blower.py +1 -1
  97. dodal/devices/{i11 → beamlines/i11}/diff_stages.py +4 -6
  98. dodal/devices/{i11 → beamlines/i11}/mythen.py +3 -4
  99. dodal/devices/{i11 → beamlines/i11}/nx100robot.py +6 -6
  100. dodal/devices/{i11 → beamlines/i11}/spinner.py +1 -1
  101. dodal/devices/{i13_1 → beamlines/i13_1}/merlin.py +1 -1
  102. dodal/devices/{i15 → beamlines/i15}/dcm.py +1 -2
  103. dodal/devices/{i15 → beamlines/i15}/focussing_mirror.py +5 -5
  104. dodal/devices/{i15 → beamlines/i15}/jack.py +2 -2
  105. dodal/devices/{i15 → beamlines/i15}/multilayer_mirror.py +1 -1
  106. dodal/devices/{i17 → beamlines/i17}/i17_apple2.py +10 -16
  107. dodal/devices/{i18 → beamlines/i18}/diode.py +1 -1
  108. dodal/devices/{i19 → beamlines/i19}/access_controlled/attenuator_motor_squad.py +12 -8
  109. dodal/devices/{i19 → beamlines/i19}/access_controlled/blueapi_device.py +16 -15
  110. dodal/devices/beamlines/i19/access_controlled/piezo_control.py +72 -0
  111. dodal/devices/{i19 → beamlines/i19}/access_controlled/shutter.py +11 -9
  112. dodal/devices/{i19 → beamlines/i19}/backlight.py +3 -1
  113. dodal/devices/{i19 → beamlines/i19}/mapt_configuration.py +2 -1
  114. dodal/devices/{i19 → beamlines/i19}/pin_col_stages.py +11 -8
  115. dodal/devices/beamlines/i19/pin_tip.py +32 -0
  116. dodal/devices/beamlines/i21/__init__.py +3 -0
  117. dodal/devices/{i22 → beamlines/i22}/dcm.py +1 -2
  118. dodal/devices/{i22 → beamlines/i22}/fswitch.py +1 -3
  119. dodal/devices/{i22 → beamlines/i22}/nxsas.py +5 -4
  120. dodal/devices/{i24 → beamlines/i24}/beam_center.py +1 -1
  121. dodal/devices/{i24 → beamlines/i24}/beamstop.py +2 -2
  122. dodal/devices/{i24 → beamlines/i24}/commissioning_jungfrau.py +3 -2
  123. dodal/devices/{i24 → beamlines/i24}/dcm.py +1 -3
  124. dodal/devices/{i24 → beamlines/i24}/dual_backlight.py +3 -3
  125. dodal/devices/{i24 → beamlines/i24}/pmac.py +9 -7
  126. dodal/devices/{p60 → beamlines/p60}/lab_xray_source.py +1 -1
  127. dodal/devices/beamlines/p99/__init__.py +0 -0
  128. dodal/devices/{p99 → beamlines/p99}/andor2_point.py +11 -15
  129. dodal/devices/bimorph_mirror.py +22 -20
  130. dodal/devices/collimation_table.py +3 -2
  131. dodal/devices/common_dcm.py +30 -20
  132. dodal/devices/controllers.py +2 -2
  133. dodal/devices/cryostream.py +8 -0
  134. dodal/devices/current_amplifiers/current_amplifier.py +16 -18
  135. dodal/devices/current_amplifiers/current_amplifier_detector.py +9 -10
  136. dodal/devices/current_amplifiers/femto.py +8 -9
  137. dodal/devices/current_amplifiers/sr570.py +16 -16
  138. dodal/devices/current_amplifiers/struck_scaler_counter.py +5 -5
  139. dodal/devices/detector/det_resolution.py +9 -8
  140. dodal/devices/detector/detector.py +4 -2
  141. dodal/devices/diamond_filter.py +3 -4
  142. dodal/devices/eiger.py +3 -3
  143. dodal/devices/eiger_odin.py +1 -1
  144. dodal/devices/electron_analyser/base/base_controller.py +13 -13
  145. dodal/devices/electron_analyser/base/base_detector.py +15 -20
  146. dodal/devices/electron_analyser/base/base_driver_io.py +39 -46
  147. dodal/devices/electron_analyser/base/base_region.py +27 -30
  148. dodal/devices/electron_analyser/base/base_util.py +18 -16
  149. dodal/devices/electron_analyser/base/energy_sources.py +13 -19
  150. dodal/devices/eurotherm.py +3 -2
  151. dodal/devices/fast_grid_scan.py +31 -34
  152. dodal/devices/fast_shutter.py +24 -21
  153. dodal/devices/flux.py +1 -1
  154. dodal/devices/focusing_mirror.py +29 -11
  155. dodal/devices/hutch_shutter.py +6 -6
  156. dodal/devices/insertion_device/__init__.py +8 -0
  157. dodal/devices/insertion_device/apple2_controller.py +51 -60
  158. dodal/devices/insertion_device/apple2_undulator.py +40 -64
  159. dodal/devices/insertion_device/apple_knot_controller.py +222 -0
  160. dodal/devices/insertion_device/energy.py +100 -27
  161. dodal/devices/insertion_device/energy_motor_lookup.py +20 -27
  162. dodal/devices/insertion_device/lookup_table_models.py +45 -50
  163. dodal/devices/insertion_device/polarisation.py +1 -1
  164. dodal/devices/ipin.py +1 -1
  165. dodal/devices/linkam3.py +7 -5
  166. dodal/devices/motors.py +107 -19
  167. dodal/devices/mx_phase1/beamstop.py +2 -4
  168. dodal/devices/oav/oav_calculations.py +20 -13
  169. dodal/devices/oav/oav_detector.py +28 -23
  170. dodal/devices/oav/oav_parameters.py +4 -9
  171. dodal/devices/oav/oav_to_redis_forwarder.py +22 -18
  172. dodal/devices/oav/pin_image_recognition/__init__.py +4 -6
  173. dodal/devices/oav/pin_image_recognition/manual_test.py +1 -2
  174. dodal/devices/oav/pin_image_recognition/utils.py +30 -32
  175. dodal/devices/oav/snapshots/grid_overlay.py +10 -9
  176. dodal/devices/oav/snapshots/snapshot_image_processing.py +15 -13
  177. dodal/devices/oav/utils.py +9 -12
  178. dodal/devices/p45.py +3 -9
  179. dodal/devices/pgm.py +8 -14
  180. dodal/devices/pressure_jump_cell.py +93 -32
  181. dodal/devices/qbpm.py +1 -3
  182. dodal/devices/robot.py +12 -4
  183. dodal/devices/s4_slit_gaps.py +1 -1
  184. dodal/devices/selectable_source.py +5 -2
  185. dodal/devices/slits.py +2 -5
  186. dodal/devices/smargon.py +2 -3
  187. dodal/devices/temperture_controller/lakeshore/lakeshore.py +38 -64
  188. dodal/devices/temperture_controller/lakeshore/lakeshore_io.py +21 -35
  189. dodal/devices/tetramm.py +7 -7
  190. dodal/devices/turbo_slit.py +8 -7
  191. dodal/devices/undulator.py +42 -56
  192. dodal/devices/util/adjuster_plans.py +2 -3
  193. dodal/devices/util/epics_util.py +10 -10
  194. dodal/devices/util/lookup_tables.py +17 -18
  195. dodal/devices/v2f.py +2 -3
  196. dodal/devices/watsonmarlow323_pump.py +1 -1
  197. dodal/devices/xbpm_feedback.py +3 -2
  198. dodal/devices/xspress3/xspress3.py +8 -11
  199. dodal/devices/xspress3/xspress3_channel.py +3 -6
  200. dodal/devices/zebra/zebra.py +6 -7
  201. dodal/devices/zebra/zebra_constants_mapping.py +11 -7
  202. dodal/devices/zebra/zebra_controlled_shutter.py +2 -1
  203. dodal/devices/zocalo/zocalo_interaction.py +14 -14
  204. dodal/devices/zocalo/zocalo_results.py +33 -33
  205. dodal/log.py +23 -20
  206. dodal/plan_stubs/check_topup.py +15 -15
  207. dodal/plan_stubs/data_session.py +6 -6
  208. dodal/plan_stubs/motor_utils.py +22 -18
  209. dodal/plan_stubs/pressure_jump_cell.py +18 -0
  210. dodal/plan_stubs/wrapped.py +40 -55
  211. dodal/plans/bimorph.py +63 -52
  212. dodal/plans/device_setup_plans/__init__.py +5 -0
  213. dodal/plans/device_setup_plans/setup_pin_tip_params.py +63 -0
  214. dodal/plans/preprocessors/verify_undulator_gap.py +10 -8
  215. dodal/plans/spec_path.py +3 -5
  216. dodal/plans/verify_undulator_gap.py +1 -2
  217. dodal/plans/wrapped.py +4 -3
  218. dodal/testing/electron_analyser/device_factory.py +5 -7
  219. dodal/testing/fixtures/devices/apple2.py +38 -0
  220. dodal/testing/fixtures/run_engine.py +3 -7
  221. dodal/testing/fixtures/utils.py +1 -2
  222. dodal/utils.py +60 -58
  223. dls_dodal-1.69.0.dist-info/RECORD +0 -338
  224. dodal/beamline_specific_utils/i05_shared.py +0 -14
  225. dodal/devices/b07/__init__.py +0 -3
  226. dodal/devices/i04/beam_centre.py +0 -84
  227. dodal/devices/i05/__init__.py +0 -3
  228. dodal/devices/i09/__init__.py +0 -3
  229. dodal/devices/i21/__init__.py +0 -5
  230. {dls_dodal-1.69.0.dist-info → dls_dodal-2.0.0.dist-info}/entry_points.txt +0 -0
  231. {dls_dodal-1.69.0.dist-info → dls_dodal-2.0.0.dist-info}/licenses/LICENSE +0 -0
  232. {dls_dodal-1.69.0.dist-info → dls_dodal-2.0.0.dist-info}/top_level.txt +0 -0
  233. /dodal/{beamline_specific_utils → devices/beamlines}/__init__.py +0 -0
  234. /dodal/devices/{b07 → beamlines/b07}/enums.py +0 -0
  235. /dodal/devices/{b07_1 → beamlines/b07_1}/enums.py +0 -0
  236. /dodal/devices/{b16 → beamlines/b16}/__init__.py +0 -0
  237. /dodal/devices/{i02_1 → beamlines/i02_1}/__init__.py +0 -0
  238. /dodal/devices/{i02_2 → beamlines/i02_2}/__init__.py +0 -0
  239. /dodal/devices/{i03 → beamlines/i03}/__init__.py +0 -0
  240. /dodal/devices/{i03 → beamlines/i03}/constants.py +0 -0
  241. /dodal/devices/{i04 → beamlines/i04}/__init__.py +0 -0
  242. /dodal/devices/{i04 → beamlines/i04}/constants.py +0 -0
  243. /dodal/devices/{i04 → beamlines/i04}/max_pixel.py +0 -0
  244. /dodal/devices/{i05 → beamlines/i05}/enums.py +0 -0
  245. /dodal/devices/{i07 → beamlines/i07}/__init__.py +0 -0
  246. /dodal/devices/{i09 → beamlines/i09}/enums.py +0 -0
  247. /dodal/devices/{i09_1 → beamlines/i09_1}/__init__.py +0 -0
  248. /dodal/devices/{i09_1 → beamlines/i09_1}/enums.py +0 -0
  249. /dodal/devices/{i09_1_shared → beamlines/i09_1_shared}/__init__.py +0 -0
  250. /dodal/devices/{i09_2_shared → beamlines/i09_2_shared}/__init__.py +0 -0
  251. /dodal/devices/{i09_2_shared → beamlines/i09_2_shared}/i09_apple2.py +0 -0
  252. /dodal/devices/{i10 → beamlines/i10}/__init__.py +0 -0
  253. /dodal/devices/{i10 → beamlines/i10}/i10_setting_data.py +0 -0
  254. /dodal/devices/{i10 → beamlines/i10}/mirrors.py +0 -0
  255. /dodal/devices/{i10 → beamlines/i10}/rasor/__init__.py +0 -0
  256. /dodal/devices/{i10 → beamlines/i10}/rasor/rasor_scaler_cards.py +0 -0
  257. /dodal/devices/{i11 → beamlines/i10_1/electromagnet}/__init__.py +0 -0
  258. /dodal/devices/{i13_1 → beamlines/i11}/__init__.py +0 -0
  259. /dodal/devices/{i15 → beamlines/i13_1}/__init__.py +0 -0
  260. /dodal/devices/{i13_1 → beamlines/i13_1}/merlin_controller.py +0 -0
  261. /dodal/devices/{i17 → beamlines/i15}/__init__.py +0 -0
  262. /dodal/devices/{i15 → beamlines/i15}/laue.py +0 -0
  263. /dodal/devices/{i15 → beamlines/i15}/motors.py +0 -0
  264. /dodal/devices/{i15 → beamlines/i15}/rail.py +0 -0
  265. /dodal/devices/{i18 → beamlines/i17}/__init__.py +0 -0
  266. /dodal/devices/{i19 → beamlines/i18}/__init__.py +0 -0
  267. /dodal/devices/{i18 → beamlines/i18}/kb_mirror.py +0 -0
  268. /dodal/devices/{i19/access_controlled → beamlines/i19}/__init__.py +0 -0
  269. /dodal/devices/{i20_1 → beamlines/i19/access_controlled}/__init__.py +0 -0
  270. /dodal/devices/{i19 → beamlines/i19}/access_controlled/hutch_access.py +0 -0
  271. /dodal/devices/{i19 → beamlines/i19}/beamstop.py +0 -0
  272. /dodal/devices/{i19 → beamlines/i19}/diffractometer.py +0 -0
  273. /dodal/devices/{i22 → beamlines/i20_1}/__init__.py +0 -0
  274. /dodal/devices/{i21 → beamlines/i21}/enums.py +0 -0
  275. /dodal/devices/{i24 → beamlines/i22}/__init__.py +0 -0
  276. /dodal/devices/{p99 → beamlines/i24}/__init__.py +0 -0
  277. /dodal/devices/{i24 → beamlines/i24}/aperture.py +0 -0
  278. /dodal/devices/{i24 → beamlines/i24}/focus_mirrors.py +0 -0
  279. /dodal/devices/{i24 → beamlines/i24}/vgonio.py +0 -0
  280. /dodal/devices/{p60 → beamlines/p60}/__init__.py +0 -0
  281. /dodal/devices/{p60 → beamlines/p60}/enums.py +0 -0
  282. /dodal/devices/{p99 → beamlines/p99}/sample_stage.py +0 -0
@@ -5,11 +5,14 @@ from pydantic import BaseModel, Field, model_validator
5
5
 
6
6
  class ZebraMappingValidations(BaseModel):
7
7
  """Raises an exception if field set to -1 is accessed, and validate against
8
- multiple fields mapping to the same integer"""
8
+ multiple fields mapping to the same integer.
9
+ """
9
10
 
10
11
  def __getattribute__(self, name: str):
11
- """To protect against mismatch between the Zebra configuration that a plan expects and the Zebra which has
12
- been instantiated, raise exception if a field which has been set to -1 is accessed."""
12
+ """To protect against mismatch between the Zebra configuration that a plan
13
+ expects and the Zebra which has been instantiated, raise exception if a field
14
+ which has been set to -1 is accessed.
15
+ """
13
16
  value = object.__getattribute__(self, name)
14
17
  if not name.startswith("__"):
15
18
  if value == -1:
@@ -20,8 +23,7 @@ class ZebraMappingValidations(BaseModel):
20
23
 
21
24
  @model_validator(mode="after")
22
25
  def ensure_no_duplicate_connections(self):
23
- """Check that TTL outputs and sources are mapped to unique integers"""
24
-
26
+ """Check that TTL outputs and sources are mapped to unique integers."""
25
27
  integer_fields = {
26
28
  key: value
27
29
  for key, value in self.model_dump().items()
@@ -40,7 +42,9 @@ class ZebraMappingValidations(BaseModel):
40
42
 
41
43
  class ZebraTTLOutputs(ZebraMappingValidations):
42
44
  """Maps hardware to the Zebra TTL output (1-4) that they're physically wired to, or
43
- None if that hardware is not connected. A value of -1 means this hardware is not connected."""
45
+ None if that hardware is not connected. A value of -1 means this hardware is not
46
+ connected.
47
+ """
44
48
 
45
49
  TTL_EIGER: int = Field(default=-1, ge=-1, le=4)
46
50
  TTL_PILATUS: int = Field(default=-1, ge=-1, le=4)
@@ -53,7 +57,7 @@ class ZebraTTLOutputs(ZebraMappingValidations):
53
57
 
54
58
 
55
59
  class ZebraSources(ZebraMappingValidations):
56
- """Maps internal Zebra signal source to their integer PV value"""
60
+ """Maps internal Zebra signal source to their integer PV value."""
57
61
 
58
62
  DISCONNECT: int = Field(default=0, ge=0, le=63)
59
63
  IN1_TTL: int = Field(default=1, ge=0, le=63)
@@ -26,7 +26,8 @@ class ZebraShutter(StandardReadable, Movable[ZebraShutterState]):
26
26
  automatic control. A soft input (aliased to control_mode) will switch between
27
27
  which of these AND gates to use. For the manual gate the shutter is then controlled
28
28
  by a different soft input (aliased to manual_position_setpoint). Both these AND
29
- gates then feed into an OR gate, which then feeds to the shutter."""
29
+ gates then feed into an OR gate, which then feeds to the shutter.
30
+ """
30
31
 
31
32
  def __init__(self, prefix: str, name: str = ""):
32
33
  self._manual_position_setpoint = epics_signal_w(
@@ -22,14 +22,14 @@ def _get_zocalo_connection(environment):
22
22
 
23
23
  @dataclass
24
24
  class ZocaloStartInfo:
25
- """
26
- ispyb_dcid (int): The ID of the data collection in ISPyB
27
- filename (str): The name of the file that the detector will store into dev/shm
28
- start_frame_index (int): The index of the first image of this collection within the file
29
- written by the detector
30
- number_of_frames (int): The number of frames in this collection
31
- message_index (int): Which trigger this is in the detector collection e.g. 0 for the
32
- first collection after a single arm, 1 for the next...
25
+ """Attributes:
26
+ ispyb_dcid (int): The ID of the data collection in ISPyB.
27
+ filename (str): The name of the file that the detector will store into dev/shm.
28
+ start_frame_index (int): The index of the first image of this collection within
29
+ the file written by the detector.
30
+ number_of_frames (int): The number of frames in this collection.
31
+ message_index (int): Which trigger this is in the detector collection e.g. 0 for
32
+ the first collection after a single arm, 1 for the next...
33
33
  """
34
34
 
35
35
  ispyb_dcid: int
@@ -56,7 +56,8 @@ class ZocaloTrigger:
56
56
  into a plan, use the ZocaloResults ophyd device.
57
57
 
58
58
  see https://diamondlightsource.github.io/dodal/main/how-to/zocalo.html for
59
- more information about zocalo."""
59
+ more information about zocalo.
60
+ """
60
61
 
61
62
  def __init__(self, environment: str = ZOCALO_ENV):
62
63
  self.zocalo_environment: str = environment
@@ -83,10 +84,10 @@ class ZocaloTrigger:
83
84
  start_data: ZocaloStartInfo,
84
85
  ):
85
86
  """Tells the data analysis pipeline we have started a run.
86
- Assumes that appropriate data has already been put into ISPyB
87
+ Assumes that appropriate data has already been put into ISPyB.
87
88
 
88
89
  Args:
89
- start_data (ZocaloStartInfo): Data about the collection to send to zocalo
90
+ start_data (ZocaloStartInfo): Data about the collection to send to zocalo.
90
91
  """
91
92
  LOGGER.info(f"Starting Zocalo job {start_data}")
92
93
  data = dataclasses.asdict(start_data)
@@ -95,12 +96,11 @@ class ZocaloTrigger:
95
96
 
96
97
  def run_end(self, data_collection_id: int):
97
98
  """Tells the data analysis pipeline we have finished a run.
98
- Assumes that appropriate data has already been put into ISPyB
99
+ Assumes that appropriate data has already been put into ISPyB.
99
100
 
100
101
  Args:
101
102
  data_collection_id (int): The ID of the data collection representing the
102
- gridscan in ISPyB
103
-
103
+ gridscan in ISPyB.
104
104
  """
105
105
  LOGGER.info(f"Ending Zocalo job with ispyb id {data_collection_id}")
106
106
  self._send_to_zocalo(
@@ -53,25 +53,27 @@ _NO_SAMPLE_ID = -1
53
53
 
54
54
 
55
55
  class XrcResult(TypedDict):
56
- """
57
- Information about a diffracting centre.
56
+ """Information about a diffracting centre.
58
57
 
59
58
  NOTE: the coordinate systems of centre_of_mass and max_voxel/bounding_box are not
60
- the same; centre_of_mass coordinates are continuous whereas max_voxel and bounding_box
61
- coordinates are discrete.
59
+ the same; centre_of_mass coordinates are continuous whereas max_voxel and
60
+ bounding_box coordinates are discrete.
61
+
62
62
  Attributes:
63
- centre_of_mass: The position of the centre of mass of the crystal, adjusted so that
64
- grid box centres lie on integer grid coordinates, such that a 1x1x1 crystal detected in
65
- a single grid box at 0, 0, 0, has c.o.m. of 0, 0, 0, not 0.5, 0.5, 0.5
66
- max_voxel: Position of the voxel with the maximum count, in integer coordinates
67
- max_count: max count achieved in a single voxel for the crystal
68
- n_voxels: Number of voxels (aka grid boxes) in the diffracting centre
69
- total_count: Total of above-threshold spot counts in the labelled voxels
70
- bounding_box: The rectangular prism that bounds the crystal, expressed
71
- as the volume of whole boxes as a half-open range i.e such that
63
+ centre_of_mass (list[float]): The position of the centre of mass of the
64
+ crystal, adjusted so that grid box centres lie on integer grid coordinates,
65
+ such that a 1x1x1 crystal detected in a single grid box at 0, 0, 0, has
66
+ c.o.m. of 0, 0, 0, not 0.5, 0.5, 0.5.
67
+ max_voxel (list[int]): Position of the voxel with the maximum count, in integer
68
+ coordinates.
69
+ max_count (int): Max count achieved in a single voxel for the crystal.
70
+ n_voxels (int): Number of voxels (aka grid boxes) in the diffracting centre.
71
+ total_count (int): Total of above-threshold spot counts in the labelled voxels.
72
+ bounding_box (list[list[int]]): The rectangular prism that bounds the crystal,
73
+ expressed as the volume of whole boxes as a half-open range i.e such that
72
74
  p1 = (x1, y1, z1) <= p < p2 = (x2, y2, z2) and
73
75
  p2 - p1 gives the dimensions in whole voxels.
74
- sample_id: The sample id associated with the centre.
76
+ sample_id (int): The sample id associated with the centre.
75
77
  """
76
78
 
77
79
  centre_of_mass: list[float]
@@ -106,21 +108,17 @@ class ZocaloResults(StandardReadable, Triggerable):
106
108
  See https://diamondlightsource.github.io/dodal/main/how-to/zocalo.html
107
109
 
108
110
  Args:
109
- name (str): Name of the device
110
-
111
- zocalo_environment (str): How zocalo is configured. Defaults to i03's development configuration
112
-
113
- channel (str): Name for the results Queue
114
-
115
- sort_key (str): How results are ranked. Defaults to sorting by highest counts
116
-
117
- timeout_s (float): Maximum time to wait for the Queue to be filled by an object, starting
118
- from when the ZocaloResults device is triggered
119
-
120
- prefix (str): EPICS PV prefix for the device
121
-
122
- results_source (ZocaloSource): Where to get results from, GPU or CPU analysis
123
-
111
+ name (str, optional): Name of the device.
112
+ zocalo_environment (str, optional): How zocalo is configured. Defaults to i03's
113
+ development configuration.
114
+ channel (str, optional): Name for the results Queue.
115
+ sort_key (str, optional): How results are ranked. Defaults to sorting by highest
116
+ counts.
117
+ timeout_s (float, optional): Maximum time to wait for the Queue to be filled by
118
+ an object, starting from when the ZocaloResults device is triggered.
119
+ prefix (str): EPICS PV prefix for the device.
120
+ results_source (ZocaloSource, optional): Where to get results from, GPU or CPU
121
+ analysis.
124
122
  """
125
123
 
126
124
  def __init__(
@@ -205,8 +203,8 @@ class ZocaloResults(StandardReadable, Triggerable):
205
203
  """Stages the Zocalo device by: subscribing to the queue, doing a background
206
204
  sleep for a few seconds to wait for any stale messages to be received, then
207
205
  clearing the queue. Plans using this device should wait on ZOCALO_STAGE_GROUP
208
- before triggering processing for the experiment"""
209
-
206
+ before triggering processing for the experiment.
207
+ """
210
208
  LOGGER.info("Subscribing to results queue")
211
209
  try:
212
210
  self._subscribe_to_results()
@@ -312,8 +310,10 @@ def _corrected_xrc_result(uncorrected: XrcResult) -> XrcResult:
312
310
  def get_full_processing_results(
313
311
  zocalo: ZocaloResults,
314
312
  ) -> Generator[Msg, Any, Sequence[XrcResult]]:
315
- """A plan that will return the raw zocalo results, ranked in descending order according to the sort key.
316
- Returns empty list in the event no results found."""
313
+ """A plan that will return the raw zocalo results, ranked in descending order
314
+ according to the sort key.
315
+ Returns empty list in the event no results found.
316
+ """
317
317
  LOGGER.info("Retrieving raw zocalo processing results")
318
318
  com = yield from bps.rd(zocalo.centre_of_mass, default_value=[])
319
319
  max_voxel = yield from bps.rd(zocalo.max_voxel, default_value=[])
dodal/log.py CHANGED
@@ -57,11 +57,11 @@ class CircularMemoryHandler(logging.Handler):
57
57
  """Loosely based on the MemoryHandler, which keeps a buffer and writes it when full
58
58
  or when there is a record of specific level. This instead keeps a circular buffer
59
59
  that always contains the last {capacity} number of messages, this is only flushed
60
- when a log of specific {flush_level} comes in. On flush this buffer is then passed to
61
- the {target} handler.
60
+ when a log of specific {flush_level} comes in. On flush this buffer is then passed
61
+ to the {target} handler.
62
62
 
63
- The CircularMemoryHandler becomes the owner of the target handler which will be closed
64
- on close of this handler.
63
+ The CircularMemoryHandler becomes the owner of the target handler which will be
64
+ closed on close of this handler.
65
65
  """
66
66
 
67
67
  def __init__(self, capacity, flush_level=logging.ERROR, target=None):
@@ -76,9 +76,7 @@ class CircularMemoryHandler(logging.Handler):
76
76
  self.flush()
77
77
 
78
78
  def flush(self):
79
- """
80
- Pass the contents of the buffer forward to the target.
81
- """
79
+ """Pass the contents of the buffer forward to the target."""
82
80
  self.acquire()
83
81
  try:
84
82
  if self.target:
@@ -151,7 +149,8 @@ def set_up_graylog_handler(logger: Logger, host: str, port: int):
151
149
 
152
150
  def set_up_info_file_handler(logger, path: Path, filename: str):
153
151
  """Set up a file handler for the logger, at INFO level, which will keep 30 days
154
- of logs, rotating once per day. Creates the directory if necessary."""
152
+ of logs, rotating once per day. Creates the directory if necessary.
153
+ """
155
154
  print(f"Logging to INFO file handler {path / filename}")
156
155
  path.mkdir(parents=True, exist_ok=True)
157
156
  file_handler = TimedRotatingFileHandler(
@@ -167,7 +166,8 @@ def set_up_debug_memory_handler(
167
166
  ):
168
167
  """Set up a Memory handler which holds 200k lines, and writes them to an hourly
169
168
  log file when it sees a message of severity ERROR. Creates the directory if
170
- necessary"""
169
+ necessary.
170
+ """
171
171
  debug_path = path / "debug"
172
172
  print(f"Logging to DEBUG handler {debug_path / filename}")
173
173
  debug_path.mkdir(parents=True, exist_ok=True)
@@ -204,17 +204,20 @@ def set_up_all_logging_handlers(
204
204
  debug_logging_path: Path | None = None,
205
205
  ) -> DodalLogHandlers:
206
206
  """Set up the default logging environment.
207
+
207
208
  Args:
208
- logger: the logging.Logger object to apply all the handlers to.
209
- logging_path: The location to store log files.
210
- filename: The log filename.
211
- dev_mode: If true, will log to graylog on localhost instead of
212
- production. Defaults to False.
213
- error_log_buffer_lines: Number of lines for the CircularMemoryHandler to keep in
214
- buffer and write to file when encountering an error message.
215
- graylog_port: The port to send graylog messages to, if None uses the
216
- default dodal port
217
- debug_logging_path: The location to store debug log files, if None uses `logging_path`
209
+ logger (Logger): The logging.Logger object to apply all the handlers to.
210
+ logging_path (Path): The location to store log files.
211
+ filename (str): The log filename.
212
+ dev_mode (bool): If true, will log to graylog on localhost instead of
213
+ production. Defaults to False.
214
+ error_log_buffer_lines (int): Number of lines for the CircularMemoryHandler to
215
+ keep in buffer and write to file when encountering an error message.
216
+ graylog_port (int, optional): The port to send graylog messages to, if None uses
217
+ the default dodal port
218
+ debug_logging_path (Path, optional): The location to store debug log files, if
219
+ None uses `logging_path`
220
+
218
221
  Returns:
219
222
  A DodaLogHandlers TypedDict with the created handlers.
220
223
  """
@@ -261,7 +264,7 @@ def get_logging_file_paths() -> tuple[Path, Path]:
261
264
 
262
265
  Returns:
263
266
  tuple[Path, Path]: Paths to the standard log file and to the debug log file,
264
- for the file handlers to write to
267
+ for the file handlers to write to
265
268
  """
266
269
  beamline: str | None = environ.get("BEAMLINE")
267
270
 
@@ -49,15 +49,17 @@ def _delay_to_avoid_topup(
49
49
  total_exposure_time_s: float,
50
50
  ) -> bool:
51
51
  """Determine whether we should delay collection until after a topup. Generally
52
- if a topup is due to occur during the collection we will delay collection until after the topup.
53
- However for long-running collections, impact of the topup is potentially less and collection-duration may be
54
- a significant fraction of the topup-interval, therefore we may wish to collect during a topup.
52
+ if a topup is due to occur during the collection we will delay collection until
53
+ after the topup. However for long-running collections, impact of the topup is
54
+ potentially less and collection-duration may be a significant fraction of the
55
+ topup-interval, therefore we may wish to collect during a topup.
55
56
 
56
57
  Args:
57
- total_run_time_s: Anticipated time until end of the collection in seconds
58
- time_to_topup_s: Time to the start of the topup as measured from the PV
59
- topup_configuration: configuration dictionary
60
- total_exposure_time_s: Total exposure time of the sample in s"""
58
+ total_run_time_s (float): Anticipated time until end of the collection in seconds.
59
+ time_to_topup_s (float): Time to the start of the topup as measured from the PV.
60
+ topup_configuration (dict): Configuration dictionary.
61
+ total_exposure_time_s (float): Total exposure time of the sample in s.
62
+ """
61
63
  if total_run_time_s > time_to_topup_s:
62
64
  limit_s = topup_configuration.get(
63
65
  TopupConfig.THRESHOLD_EXPOSURE_S, DEFAULT_THRESHOLD_EXPOSURE_S
@@ -75,9 +77,7 @@ def _delay_to_avoid_topup(
75
77
  """)
76
78
  return gate
77
79
  LOGGER.info(
78
- """
79
- Total run time less than time to next topup. Proceeding with collection.
80
- """
80
+ """Total run time less than time to next topup. Proceeding with collection."""
81
81
  )
82
82
  return False
83
83
 
@@ -95,15 +95,15 @@ def check_topup_and_wait_if_necessary(
95
95
  total_exposure_time: float,
96
96
  ops_time: float, # Account for xray centering, rotation speed, etc
97
97
  ): # See https://github.com/DiamondLightSource/hyperion/issues/932
98
- """A small plan to check if topup gating is permitted and sleep until the topup\
98
+ """A small plan to check if topup gating is permitted and sleep until the topup
99
99
  is over if it starts before the end of collection.
100
100
 
101
101
  Args:
102
102
  synchrotron (Synchrotron): Synchrotron device.
103
- total_exposure_time (float): Expected total exposure time for \
104
- collection, in seconds.
105
- ops_time (float): Additional time to account for various operations,\
106
- eg. x-ray centering, in seconds. Defaults to 30.0.
103
+ total_exposure_time (float): Expected total exposure time for collection, in
104
+ seconds.
105
+ ops_time (float): Additional time to account for various operations, eg. x-ray
106
+ centering, in seconds. Defaults to 30.0.
107
107
  """
108
108
  machine_mode = yield from bps.rd(synchrotron.synchrotron_mode)
109
109
  assert isinstance(machine_mode, SynchrotronMode)
@@ -15,8 +15,7 @@ DATA_GROUPS = "data_groups"
15
15
  def attach_data_session_metadata_wrapper(
16
16
  plan: MsgGenerator, provider: PathProvider | None = None
17
17
  ) -> MsgGenerator:
18
- """
19
- Attach data session metadata to the runs within a plan and make it correlate
18
+ """Attach data session metadata to the runs within a plan and make it correlate
20
19
  with an ophyd-async PathProvider.
21
20
 
22
21
  This updates the path provider (which in turn makes a call to to a service
@@ -24,14 +23,15 @@ def attach_data_session_metadata_wrapper(
24
23
  start document contains the correct data session.
25
24
 
26
25
  Args:
27
- plan: The plan to preprocess
28
- provider: The path provider that participating detectors are aware of.
26
+ plan (MsgGenerator): The plan to preprocess.
27
+ provider (PathProvider): The path provider that participating detectors are
28
+ aware of.
29
29
 
30
30
  Returns:
31
- MsgGenerator: A plan
31
+ MsgGenerator: A plan.
32
32
 
33
33
  Yields:
34
- Iterator[Msg]: Plan messages
34
+ Iterator[Msg]: Plan messages.
35
35
  """
36
36
  try:
37
37
  provider = provider or get_path_provider()
@@ -29,8 +29,8 @@ def check_and_cache_values(
29
29
  maximum_move: float,
30
30
  ) -> Generator[Msg, Any, dict[Motor, float]]:
31
31
  """Caches the positions of all Motors on specified device if they are within
32
- smallest_move of home_position. Throws MoveTooLargeError if they are outside maximum_move
33
- of the home_position
32
+ smallest_move of home_position. Throws MoveTooLargeError if they are outside
33
+ maximum_move of the home_position.
34
34
  """
35
35
  positions = {}
36
36
  for axis, new_position in devices_and_positions.items():
@@ -68,25 +68,29 @@ def move_and_reset_wrapper(
68
68
  ) -> MsgGenerator:
69
69
  """Wrapper that does the following:
70
70
  1. Caches the positions of all Motors on device
71
- 2. Throws a MoveTooLargeError exception if any positions are maximum_move away from home_position
72
- 2. Moves any motor that is more than smallest_move away from the home_position to home_position
73
- 3. Runs the specified plan
74
- 4. Moves all motors back to their cached positions
71
+ 2. Throws a MoveTooLargeError exception if any positions are maximum_move away
72
+ from home_position
73
+ 3. Moves any motor that is more than smallest_move away from the home_position to
74
+ home_position
75
+ 4. Runs the specified plan
76
+ 5. Moves all motors back to their cached positions
75
77
 
76
78
  Args:
77
- plan (Callable[[], MsgGenerator]): The plan to move between homing and returning to the cache
78
- device (Device): The device to move. All Motors in the device will be cached and moved
79
- smallest_move (float): The smallest move that we care about doing the home and cache for.
80
- Useful for not wearing out motors if you have large tolerances
81
- maximum_move (float): If any Motor starts this far from the home an exception is raised
82
- and no moves occur
83
- home_position (float): The position to move every motor to after caching
79
+ plan (Callable[[], MsgGenerator]): The plan to move between homing and returning
80
+ to the cache.
81
+ device_and_positions (dict[Motor, float]): The device to move and position to
82
+ move it to. All Motors in the device will be cached and moved.
83
+ smallest_move (float): The smallest move that we care about doing the home and
84
+ cache for. Useful for not wearing out motors if you have large tolerances.
85
+ maximum_move (float): If any Motor starts this far from the home an exception is
86
+ raised and no moves occur.
87
+ home_position (float): The position to move every motor to after caching.
84
88
  group (str, optional): If set the home move will be done using the home-{group}
85
- group and the reset to cache done using reset-{group}
86
- wait_for_all (bool, optional): If true the home and reset to cache will be waited
87
- on. If false it is left up to the caller to wait on
88
- them. Defaults to True.
89
- """
89
+ group and the reset to cache done using reset-{group}.
90
+ wait_for_all (bool, optional): If true the home and reset to cache will be
91
+ waited on. If false it is left up to the caller to wait on them. Defaults to
92
+ True.
93
+ """ # noqa D415
90
94
  initial_positions = yield from check_and_cache_values(
91
95
  device_and_positions, smallest_move, maximum_move
92
96
  )
@@ -0,0 +1,18 @@
1
+ import bluesky.plan_stubs as bps
2
+
3
+ from dodal.devices.pressure_jump_cell import PressureJumpCell
4
+
5
+
6
+ def set_pressure_jump(
7
+ pressure_cell: PressureJumpCell, pressure_from: int, pressure_to: int
8
+ ):
9
+ """Sets the desired pressures for a jump waiting for the device to complete the
10
+ operation.
11
+ """
12
+ yield from bps.mv(
13
+ pressure_cell.control.from_pressure,
14
+ pressure_from,
15
+ pressure_cell.control.to_pressure,
16
+ pressure_to,
17
+ )
18
+ yield from bps.trigger(pressure_cell.control.do_jump, wait=True)
@@ -6,9 +6,7 @@ import bluesky.plan_stubs as bps
6
6
  from bluesky.protocols import Movable
7
7
  from bluesky.utils import MsgGenerator
8
8
 
9
- """
10
- Wrappers for Bluesky built-in plan stubs with type hinting
11
- """
9
+ """Wrappers for Bluesky built-in plan stubs with type hinting."""
12
10
 
13
11
  Group = Annotated[str, "String identifier used by 'wait' or stubs that await"]
14
12
 
@@ -18,22 +16,21 @@ T = TypeVar("T")
18
16
  def set_absolute(
19
17
  movable: Movable[T], value: T, group: Group | None = None, wait: bool = False
20
18
  ) -> MsgGenerator:
21
- """
22
- Set a device, wrapper for `bp.abs_set`.
19
+ """Set a device, wrapper for `bp.abs_set`.
23
20
 
24
21
  Args:
25
- movable (Movable[T]): The device to set
26
- value (T): The new value
27
- group (Group | None, optional): The message group to associate with the
28
- setting, for sequencing. Defaults to None.
29
- wait (bool, optional): The group should wait until all setting is complete
30
- (e.g. a motor has finished moving). Defaults to False.
22
+ movable (Movable[T]): The device to set.
23
+ value (T): The new value.
24
+ group (Group | None, optional): The message group to associate with the setting,
25
+ for sequencing. Defaults to None.
26
+ wait (bool, optional): The group should wait until all setting is complete (e.g.
27
+ a motor has finished moving). Defaults to False.
31
28
 
32
29
  Returns:
33
- MsgGenerator: Plan
30
+ MsgGenerator: Plan.
34
31
 
35
32
  Yields:
36
- Iterator[MsgGenerator]: Bluesky messages
33
+ Iterator[MsgGenerator]: Bluesky messages.
37
34
  """
38
35
  return (yield from bps.abs_set(movable, value, group=group, wait=wait))
39
36
 
@@ -41,43 +38,39 @@ def set_absolute(
41
38
  def set_relative(
42
39
  movable: Movable[T], value: T, group: Group | None = None, wait: bool = False
43
40
  ) -> MsgGenerator:
44
- """
45
- Change a device, wrapper for `bp.rel_set`.
41
+ """Change a device, wrapper for `bp.rel_set`.
46
42
 
47
43
  Args:
48
- movable (Movable): The device to set
49
- value (T): The new value
50
- group (Group | None, optional): The message group to associate with the
51
- setting, for sequencing. Defaults to None.
52
- wait (bool, optional): The group should wait until all setting is complete
53
- (e.g. a motor has finished moving). Defaults to False.
44
+ movable (Movable): The device to set.
45
+ value (T): The new value.
46
+ group (Group | None, optional): The message group to associate with the setting,
47
+ for sequencing. Defaults to None.
48
+ wait (bool, optional): The group should wait until all setting is complete (e.g.
49
+ a motor has finished moving). Defaults to False.
54
50
 
55
51
  Returns:
56
- MsgGenerator: Plan
52
+ MsgGenerator: Plan.
57
53
 
58
54
  Yields:
59
- Iterator[MsgGenerator]: Bluesky messages
55
+ Iterator[MsgGenerator]: Bluesky messages.
60
56
  """
61
-
62
57
  return (yield from bps.rel_set(movable, value, group=group, wait=wait))
63
58
 
64
59
 
65
60
  def move(moves: Mapping[Movable[T], T], group: Group | None = None) -> MsgGenerator:
66
- """
67
- Move a device, wrapper for `bp.mv`.
61
+ """Move a device, wrapper for `bp.mv`.
68
62
 
69
63
  Args:
70
- moves (Mapping[Movable, T]): Mapping of Movables to target positions
71
- group (Group | None, optional): The message group to associate with the
72
- setting, for sequencing. Defaults to None.
64
+ moves (Mapping[Movable, T]): Mapping of Movables to target positions.
65
+ group (Group | None, optional): The message group to associate with the setting,
66
+ for sequencing. Defaults to None.
73
67
 
74
68
  Returns:
75
- MsgGenerator: Plan
69
+ MsgGenerator: Plan.
76
70
 
77
71
  Yields:
78
- Iterator[MsgGenerator]: Bluesky messages
72
+ Iterator[MsgGenerator]: Bluesky messages.
79
73
  """
80
-
81
74
  return (
82
75
  yield from bps.mv(*itertools.chain.from_iterable(moves.items()), group=group)
83
76
  )
@@ -86,40 +79,36 @@ def move(moves: Mapping[Movable[T], T], group: Group | None = None) -> MsgGenera
86
79
  def move_relative(
87
80
  moves: Mapping[Movable[T], T], group: Group | None = None
88
81
  ) -> MsgGenerator:
89
- """
90
- Move a device relative to its current position, wrapper for `bp.mvr`.
82
+ """Move a device relative to its current position, wrapper for `bp.mvr`.
91
83
 
92
84
  Args:
93
- moves (Mapping[Movable, T]): Mapping of Movables to target deltas
85
+ moves (Mapping[Movable, T]): Mapping of Movables to target deltas.
94
86
  group (Group | None, optional): The message group to associate with the
95
- setting, for sequencing. Defaults to None.
87
+ setting, for sequencing. Defaults to None.
96
88
 
97
89
  Returns:
98
- MsgGenerator: Plan
90
+ MsgGenerator: Plan.
99
91
 
100
92
  Yields:
101
- Iterator[MsgGenerator]: Bluesky messages
93
+ Iterator[MsgGenerator]: Bluesky messages.
102
94
  """
103
-
104
95
  return (
105
96
  yield from bps.mvr(*itertools.chain.from_iterable(moves.items()), group=group)
106
97
  )
107
98
 
108
99
 
109
100
  def sleep(time: float) -> MsgGenerator:
110
- """
111
- Suspend all action for a given time, wrapper for `bp.sleep`
101
+ """Suspend all action for a given time, wrapper for `bp.sleep`.
112
102
 
113
103
  Args:
114
- time (float): Time to wait in seconds
104
+ time (float): Time to wait in seconds.
115
105
 
116
106
  Returns:
117
- MsgGenerator: Plan
107
+ MsgGenerator: Plan.
118
108
 
119
109
  Yields:
120
- Iterator[MsgGenerator]: Bluesky messages
110
+ Iterator[MsgGenerator]: Bluesky messages.
121
111
  """
122
-
123
112
  return (yield from bps.sleep(time))
124
113
 
125
114
 
@@ -127,22 +116,18 @@ def wait(
127
116
  group: Group | None = None,
128
117
  timeout: float | None = None,
129
118
  ) -> MsgGenerator:
130
- """
131
- Wait for a group status to complete, wrapper for `bp.wait`.
119
+ """Wait for a group status to complete, wrapper for `bp.wait`.
132
120
  Does not expose move_on, as when used as a stub will not fail on Timeout.
133
121
 
134
122
  Args:
135
- group (Group | None, optional): The name of the group to wait for, defaults
136
- to None, in which case waits for all
137
- groups that have not yet been awaited.
138
- timeout (float | None, default=None): a timeout in seconds
139
-
123
+ group (Group | None, optional): The name of the group to wait for, defaults to
124
+ None, in which case waits for all groups that have not yet been awaited.
125
+ timeout (float | None, default=None): a timeout in seconds.
140
126
 
141
127
  Returns:
142
- MsgGenerator: Plan
128
+ MsgGenerator: Plan.
143
129
 
144
130
  Yields:
145
- Iterator[MsgGenerator]: Bluesky messages
131
+ Iterator[MsgGenerator]: Bluesky messages.
146
132
  """
147
-
148
133
  return (yield from bps.wait(group, timeout=timeout))