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
@@ -4,10 +4,12 @@ from ophyd_async.core import AsyncStatus
4
4
  from pydantic import BaseModel, model_validator
5
5
  from pydantic.types import PositiveInt, StringConstraints
6
6
 
7
- from dodal.devices.i19.access_controlled.blueapi_device import (
7
+ from dodal.devices.beamlines.i19.access_controlled.blueapi_device import (
8
8
  OpticsBlueAPIDevice,
9
9
  )
10
- from dodal.devices.i19.access_controlled.hutch_access import ACCESS_DEVICE_NAME
10
+ from dodal.devices.beamlines.i19.access_controlled.hutch_access import (
11
+ ACCESS_DEVICE_NAME,
12
+ )
11
13
 
12
14
  PermittedKeyStr = Annotated[str, StringConstraints(pattern="^[A-Za-z0-9-_]*$")]
13
15
 
@@ -32,18 +34,20 @@ class AttenuatorMotorPositionDemands(BaseModel):
32
34
 
33
35
 
34
36
  class AttenuatorMotorSquad(OpticsBlueAPIDevice):
35
- """ I19-specific proxy device which requests absorber position changes in the x-ray attenuator.
37
+ """I19-specific proxy device which requests absorber position changes in the
38
+ x-ray attenuator.
36
39
 
37
40
  Sends REST call to blueapi controlling optics on the I19 cluster.
38
- The hutch in use is compared against the hutch which sent the REST call.
41
+ The hutch in use is compared against the hutch which sent the REST call.
39
42
  Only the hutch in use will be permitted to execute a plan (requesting motor moves).
40
- As the two hutches are located in series, checking the hutch in use is necessary to \
41
- avoid accidentally operating optics devices from one hutch while the other has beam time.
43
+ As the two hutches are located in series, checking the hutch in use is necessary to
44
+ avoid accidentally operating optics devices from one hutch while the other has beam
45
+ time.
42
46
 
43
- The name of the hutch that wants to operate the optics device is passed to the \
47
+ The name of the hutch that wants to operate the optics device is passed to the
44
48
  access controlled device upon instantiation of the latter.
45
49
 
46
- For details see the architecture described in \
50
+ For details see the architecture described in
47
51
  https://github.com/DiamondLightSource/i19-bluesky/issues/30.
48
52
  """
49
53
 
@@ -21,11 +21,11 @@ class HutchState(str, Enum):
21
21
 
22
22
 
23
23
  class OpticsBlueAPIDevice(StandardReadable, Movable[D]):
24
- """General device that a REST call to the blueapi instance controlling the optics \
25
- hutch running on the I19 cluster, which will evaluate the current hutch in use vs \
24
+ """General device that a REST call to the blueapi instance controlling the optics
25
+ hutch running on the I19 cluster, which will evaluate the current hutch in use vs
26
26
  the hutch sending the request and decide if the plan will be run or not.
27
27
 
28
- For details see the architecture described in \
28
+ For details see the architecture described in
29
29
  https://github.com/DiamondLightSource/i19-bluesky/issues/30.
30
30
  """
31
31
 
@@ -44,22 +44,23 @@ class OpticsBlueAPIDevice(StandardReadable, Movable[D]):
44
44
 
45
45
  @AsyncStatus.wrap
46
46
  async def set(self, value: D):
47
- """ On set send a POST request to the optics blueapi with the name and \
48
- parameters, gets the generated task_id and then sends a PUT request that runs \
47
+ """On set send a POST request to the optics blueapi with the name and
48
+ parameters, gets the generated task_id and then sends a PUT request that runs
49
49
  the plan.
50
50
 
51
51
  Args:
52
- value (dict): The value passed here should be the parameters for the POST \
53
- request, taking the form:
54
- {
55
- "name": "plan_name",
56
- "params": {
57
- "experiment_hutch": f"{hutch_name}",
58
- "access_device": "access_control",
59
- "other_params": "...",
60
- ...
52
+ value (dict): The value passed here should be the parameters for the POST
53
+ request, taking the form::
54
+
55
+ {
56
+ "name": "plan_name",
57
+ "params": {
58
+ "experiment_hutch": f"{hutch_name}",
59
+ "access_device": "access_control",
60
+ "other_params": "...",
61
+ ...
62
+ }
61
63
  }
62
- }
63
64
  """
64
65
  # Value here vould be request params dictionary.
65
66
  request_params = json.dumps(value)
@@ -0,0 +1,72 @@
1
+ from enum import StrEnum
2
+
3
+ from ophyd_async.core import AsyncStatus, StandardReadableFormat
4
+ from ophyd_async.epics.core import epics_signal_r
5
+
6
+ from dodal.devices.beamlines.i19.access_controlled.blueapi_device import (
7
+ HutchState,
8
+ OpticsBlueAPIDevice,
9
+ )
10
+ from dodal.devices.beamlines.i19.access_controlled.hutch_access import (
11
+ ACCESS_DEVICE_NAME,
12
+ )
13
+
14
+
15
+ class FocusingMirrorName(StrEnum):
16
+ VFM = "vfm"
17
+ HFM = "hfm"
18
+
19
+
20
+ PIEZO_CONTROL_PLAN_NAME = "apply_voltage_to_piezo"
21
+
22
+
23
+ # NOTE This device is only meant to control the piezo. There should be a separate device
24
+ # to control the actual focusing mirror motors, as the two operations are often done
25
+ # independently.
26
+ class AccessControlledPiezoActuator(OpticsBlueAPIDevice):
27
+ """I19-specific device to set a voltage on the focusing mirror piezoelectric
28
+ actuator.
29
+
30
+ This device will send a REST call to the blueapi instance controlling the optics
31
+ hutch running on the I19 cluster, which will evaluate the current hutch in use vs
32
+ the hutch sending the request and decide if the plan will be run or not.
33
+ As the two hutches are located in series, checking the hutch in use is necessary to
34
+ avoid accidentally operating the shutter from one hutch while the other has beamtime.
35
+
36
+ The name of the hutch that wants to operate the shutter, as well as a commissioning
37
+ directory to act as a placehlder for the instrument_session,should be passed to the
38
+ device upon instantiation.
39
+
40
+ A mirror type (vfm or hfm) also needs to be set upon instantiation so that the
41
+ correct plan can be run and the correct optics device is injected.
42
+
43
+ For details see the architecture described in
44
+ https://diamondlightsource.github.io/i19-bluesky/main/explanations/decisions/0004-optics-blueapi-architecture.html
45
+ """
46
+
47
+ def __init__(
48
+ self,
49
+ prefix: str,
50
+ mirror_type: FocusingMirrorName,
51
+ hutch: HutchState,
52
+ instrument_session: str = "",
53
+ name: str = "",
54
+ ):
55
+ with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
56
+ self.readback = epics_signal_r(float, f"{prefix}AOFPITCH:RBV")
57
+ self.mirror = mirror_type
58
+ super().__init__(hutch=hutch, instrument_session=instrument_session, name=name)
59
+
60
+ @AsyncStatus.wrap
61
+ async def set(self, value: float):
62
+ request_params = {
63
+ "name": PIEZO_CONTROL_PLAN_NAME,
64
+ "params": {
65
+ "experiment_hutch": self._invoking_hutch,
66
+ "access_device": ACCESS_DEVICE_NAME,
67
+ "voltage_demand": value,
68
+ "focus_mirror": self.mirror.value,
69
+ },
70
+ "instrument_session": self.instrument_session,
71
+ }
72
+ await super().set(request_params)
@@ -1,27 +1,29 @@
1
1
  from ophyd_async.core import AsyncStatus, StandardReadableFormat
2
2
  from ophyd_async.epics.core import epics_signal_r
3
3
 
4
- from dodal.devices.hutch_shutter import ShutterDemand, ShutterState
5
- from dodal.devices.i19.access_controlled.blueapi_device import (
4
+ from dodal.devices.beamlines.i19.access_controlled.blueapi_device import (
6
5
  HutchState,
7
6
  OpticsBlueAPIDevice,
8
7
  )
9
- from dodal.devices.i19.access_controlled.hutch_access import ACCESS_DEVICE_NAME
8
+ from dodal.devices.beamlines.i19.access_controlled.hutch_access import (
9
+ ACCESS_DEVICE_NAME,
10
+ )
11
+ from dodal.devices.hutch_shutter import ShutterDemand, ShutterState
10
12
 
11
13
 
12
14
  class AccessControlledShutter(OpticsBlueAPIDevice):
13
- """ I19-specific device to operate the hutch shutter.
15
+ """I19-specific device to operate the hutch shutter.
14
16
 
15
- This device will send a REST call to the blueapi instance controlling the optics \
16
- hutch running on the I19 cluster, which will evaluate the current hutch in use vs \
17
+ This device will send a REST call to the blueapi instance controlling the optics
18
+ hutch running on the I19 cluster, which will evaluate the current hutch in use vs
17
19
  the hutch sending the request and decide if the plan will be run or not.
18
- As the two hutches are located in series, checking the hutch in use is necessary to \
20
+ As the two hutches are located in series, checking the hutch in use is necessary to
19
21
  avoid accidentally operating the shutter from one hutch while the other has beamtime.
20
22
 
21
- The name of the hutch that wants to operate the shutter should be passed to the \
23
+ The name of the hutch that wants to operate the shutter should be passed to the
22
24
  device upon instantiation.
23
25
 
24
- For details see the architecture described in \
26
+ For details see the architecture described in
25
27
  https://github.com/DiamondLightSource/i19-bluesky/issues/30.
26
28
  """
27
29
 
@@ -6,7 +6,9 @@ from dodal.common.enums import InOutUpper
6
6
 
7
7
 
8
8
  class BacklightPosition(StandardReadable, Movable[InOutUpper]):
9
- """Device moves backlight to the IN or OUT position since controls side manages switching the light on/off"""
9
+ """Device moves backlight to the IN or OUT position since controls side manages
10
+ switching the light on/off.
11
+ """
10
12
 
11
13
  def __init__(self, prefix: str, name: str = "") -> None:
12
14
  self.position = epics_signal_rw(InOutUpper, f"{prefix}AD1:choiceButton")
@@ -27,7 +27,8 @@ class MAPTConfigurationTable(StandardReadable):
27
27
  class MAPTConfigurationControl(StandardReadable):
28
28
  """A device to control the MAPT (Mini Aperture) configuration. It provides a signal
29
29
  to set the configuration PV to the requested value and a triggerable signal that
30
- will move all the motors to the correct position."""
30
+ will move all the motors to the correct position.
31
+ """
31
32
 
32
33
  def __init__(
33
34
  self, prefix: str, aperture_request: type[SubsetEnum], name: str = ""
@@ -6,7 +6,7 @@ from ophyd_async.core import AsyncStatus, StandardReadable, SubsetEnum
6
6
  from ophyd_async.epics.core import epics_signal_r
7
7
  from pydantic import BaseModel
8
8
 
9
- from dodal.devices.i19.mapt_configuration import (
9
+ from dodal.devices.beamlines.i19.mapt_configuration import (
10
10
  MAPTConfigurationControl,
11
11
  MAPTConfigurationTable,
12
12
  )
@@ -45,10 +45,10 @@ class AperturePosition(BaseModel):
45
45
  one of the available apertures.
46
46
 
47
47
  Attributes:
48
- pinhole_x: The position of the x motor on the pinhole stage
49
- pinhole_y: The position of the y motor on the pinhole stage
50
- collimator_x: The position of the x motor on the collimator stage
51
- collimator_y: The position of the y motor on the collimator stage
48
+ pinhole_x (float): The position of the x motor on the pinhole stage.
49
+ pinhole_y (float): The position of the y motor on the pinhole stage.
50
+ collimator_x (float): The position of the x motor on the collimator stage.
51
+ collimator_y (float): The position of the y motor on the collimator stage.
52
52
  """
53
53
 
54
54
  pinhole_x: float
@@ -59,7 +59,8 @@ class AperturePosition(BaseModel):
59
59
 
60
60
  class PinColConfiguration(StandardReadable):
61
61
  """Full MAPT configuration table, including out positions and selection for the
62
- Pinhole and Collimator control."""
62
+ Pinhole and Collimator control.
63
+ """
63
64
 
64
65
  def __init__(self, prefix: str, apertures: list[int], name: str = "") -> None:
65
66
  with self.add_children_as_readables():
@@ -75,7 +76,8 @@ class PinColConfiguration(StandardReadable):
75
76
 
76
77
  class PinholeCollimatorControl(StandardReadable, Movable[str]):
77
78
  """Device to control the Pinhole and Collimator stages moves on I19-2, using the
78
- MAPT configuration table to look up the positions."""
79
+ MAPT configuration table to look up the positions.
80
+ """
79
81
 
80
82
  def __init__(
81
83
  self,
@@ -130,7 +132,8 @@ class PinholeCollimatorControl(StandardReadable, Movable[str]):
130
132
  async def _safe_move_in(self, value: _PinColPosition):
131
133
  """Move the pinhole and collimator stages safely to the in position.
132
134
  In order to avoid a collision, we have to make sure that the pinhole stage is
133
- always moved in before the collimator stage."""
135
+ always moved in before the collimator stage.
136
+ """
134
137
  LOGGER.info(
135
138
  f"Moving pinhole and collimator stages to in position: {value.value}"
136
139
  )
@@ -0,0 +1,32 @@
1
+ from ophyd_async.core import StandardReadable
2
+ from ophyd_async.epics.core import epics_signal_rw
3
+
4
+
5
+ class PinTipCentreHolder(StandardReadable):
6
+ """Temporary device to hold the pin tip x,y positions for centring.
7
+ It uses the CenterX and CenterY PVs in the overlay plugin for the OAV device to
8
+ save and read the pit tip location.
9
+
10
+ Attributes:
11
+ pin_tip_i (SignalRW): x position of the pin tip, in pixels.
12
+ pin_tip_j (SignalRW): y position of the pin tip, in pixels.
13
+
14
+ This workaround is necessary because it's not yet possible to get these values back
15
+ from a plan in blueapi. It will be removed once this is completed
16
+ https://github.com/DiamondLightSource/blueapi/issues/1349
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ prefix: str,
22
+ name: str = "",
23
+ overlay_channel: int = 1,
24
+ ):
25
+ with self.add_children_as_readables():
26
+ self.pin_tip_i = epics_signal_rw(
27
+ int, prefix + f"OVER:{overlay_channel}:CenterX"
28
+ )
29
+ self.pin_tip_j = epics_signal_rw(
30
+ int, prefix + f"OVER:{overlay_channel}:CenterY"
31
+ )
32
+ super().__init__(name)
@@ -0,0 +1,3 @@
1
+ from .enums import Grating
2
+
3
+ __all__ = ["Grating"]
@@ -24,8 +24,7 @@ _CONVERSION_CONSTANT = 12.3984
24
24
 
25
25
 
26
26
  class DCM(DoubleCrystalMonochromatorWithDSpacing[RollCrystal, PitchAndRollCrystal]):
27
- """
28
- A double crystal monochromator (DCM), used to select the energy of the beam.
27
+ """A double crystal monochromator (DCM), used to select the energy of the beam.
29
28
 
30
29
  perp describes the gap between the 2 DCM crystals which has to change as you alter
31
30
  the angle to select the requested energy.
@@ -15,8 +15,7 @@ from dodal.common.enums import InOutUpper
15
15
 
16
16
 
17
17
  class FSwitch(StandardReadable):
18
- """
19
- Device for i22's fswitch. A filter switch for manipulating
18
+ """Device for i22's fswitch. A filter switch for manipulating
20
19
  compound refractive lenses. Also referred to as a transfocator.
21
20
 
22
21
  This currently only implements the minimum
@@ -25,7 +24,6 @@ class FSwitch(StandardReadable):
25
24
  Eventually this should be combined with the transfocator device in the i04
26
25
  module but is currently incompatible as the Epics interfaces are different.
27
26
  See https://github.com/DiamondLightSource/dodal/issues/399
28
-
29
27
  """
30
28
 
31
29
  NUM_FILTERS = 128
@@ -57,8 +57,7 @@ class MetadataHolder:
57
57
 
58
58
  @dataclass
59
59
  class NXSasMetadataHolder(MetadataHolder):
60
- """
61
- Required fields for NXDetectors that are used in an NXsas application definition.
60
+ """Required fields for NXDetectors that are used in an NXsas application definition.
62
61
  All fields are Configuration and read once per run only.
63
62
  """
64
63
 
@@ -94,7 +93,8 @@ class NXSasPilatus(PilatusDetector):
94
93
  to comply with the NXsas application definition.
95
94
  Adds all values in the NXSasMetadataHolder's configuration fields
96
95
  to the configuration of the parent device.
97
- Writes hdf5 files."""
96
+ Writes hdf5 files.
97
+ """
98
98
  super().__init__(
99
99
  prefix,
100
100
  path_provider,
@@ -137,7 +137,8 @@ class NXSasOAV(AravisDetector):
137
137
  to comply with the NXsas application definition.
138
138
  Adds all values in the NXSasMetadataHolder's configuration fields
139
139
  to the configuration of the parent device.
140
- Writes hdf5 files."""
140
+ Writes hdf5 files.
141
+ """
141
142
  super().__init__(
142
143
  prefix,
143
144
  path_provider,
@@ -1,4 +1,4 @@
1
- """A small temporary device to get the beam center positions on i24"""
1
+ """A small temporary device to get the beam center positions on i24."""
2
2
 
3
3
  from ophyd_async.core import StandardReadable
4
4
  from ophyd_async.epics.core import epics_signal_rw
@@ -21,8 +21,8 @@ class Beamstop(XYZStage):
21
21
  The additional y_rotation motor is independent of the positioner and can to be moved
22
22
  on its own as needed.
23
23
 
24
- WARNING. Before moving the y_rotation motor away from 0, it is important to make sure
25
- that the backlight is in the "OUT" position to avoid a collision.
24
+ WARNING. Before moving the y_rotation motor away from 0, it is important to make
25
+ sure that the backlight is in the "OUT" position to avoid a collision.
26
26
  See also https://github.com/DiamondLightSource/dodal/issues/646.
27
27
  """
28
28
 
@@ -26,7 +26,7 @@ class JungfrauCommissioningWriter(DetectorWriter, StandardReadable):
26
26
 
27
27
  The PVs on this device are responsible for writing files of a specified name
28
28
  to a specified path, marking itself as "ready to write", and having a counter of
29
- frames written, which must be zero'd at the ophyd level
29
+ frames written, which must be zero'd at the ophyd level.
30
30
  """
31
31
 
32
32
  def __init__(
@@ -101,7 +101,8 @@ class CommissioningJungfrau(
101
101
  StandardDetector[JungfrauController, JungfrauCommissioningWriter]
102
102
  ):
103
103
  """Ophyd-async implementation of a Jungfrau 9M Detector, using a temporary
104
- filewriter in place of Odin"""
104
+ filewriter in place of Odin.
105
+ """
105
106
 
106
107
  def __init__(
107
108
  self,
@@ -8,9 +8,7 @@ from dodal.devices.common_dcm import (
8
8
 
9
9
 
10
10
  class DCM(DoubleCrystalMonochromatorWithDSpacing[RollCrystal, PitchAndRollCrystal]):
11
- """
12
- A double crystal monocromator device, used to select the beam energy.
13
- """
11
+ """A double crystal monocromator device, used to select the beam energy."""
14
12
 
15
13
  def __init__(self, prefix: str, motion_prefix: str, name: str = "") -> None:
16
14
  with self.add_children_as_readables():
@@ -27,13 +27,13 @@ class BacklightPositioner(StandardReadable):
27
27
 
28
28
 
29
29
  class DualBacklight(StandardReadable):
30
- """
31
- Device to trigger the dual backlight on I24.
30
+ """Device to trigger the dual backlight on I24.
32
31
  This device is made up by two LEDs:
33
32
  - LED1 is the "backlight", can be moved to 5 different positions.
34
33
  - LED2 is a "frontlight", it does not move, just switches on and off.
35
34
 
36
- To set the position for LED1:
35
+ To set the position for LED1::
36
+
37
37
  b = DualBacklight(name="backlight)
38
38
  b.backlight_position.set("OAV2")
39
39
 
@@ -45,9 +45,11 @@ class LaserSettings(str, Enum):
45
45
  class EncReset(str, Enum):
46
46
  """PMAC strings for position compare on encoder channels in the controller.
47
47
 
48
- For example, for ENC5:
48
+ For example, for ENC5::
49
+
49
50
  m508 sets position A to be compared with value in Channel5 in the controller.
50
51
  m509 sets position B to be compared with value in Channel5 in the controller.
52
+
51
53
  Note. These settings are usually used for initialisation.
52
54
  """
53
55
 
@@ -141,8 +143,8 @@ class ProgramRunner(Device, Flyable):
141
143
 
142
144
  @AsyncStatus.wrap
143
145
  async def kickoff(self):
144
- """Kick off the collection by sending a program number to the pmac_string and \
145
- wait for the scan status PV to go to 1.
146
+ """Kick off the collection by sending a program number to the pmac_string and
147
+ wait for the scan status PV to go to 1.
146
148
  """
147
149
  prog_num_str = await self._get_prog_number_string()
148
150
  await self._signal_ref().set(prog_num_str, wait=True)
@@ -154,8 +156,8 @@ class ProgramRunner(Device, Flyable):
154
156
 
155
157
  @AsyncStatus.wrap
156
158
  async def complete(self):
157
- """Stop collecting when the scan status PV goes to 0 or when counter PV hasn't \
158
- updated for 30 seconds.
159
+ """Stop collecting when the scan status PV goes to 0 or when counter PV hasn't
160
+ updated for 30 seconds.
159
161
  """
160
162
  counter_time = await self._counter_time_ref().get_value()
161
163
  async for signal, value in observe_signals_value(
@@ -169,8 +171,8 @@ class ProgramRunner(Device, Flyable):
169
171
 
170
172
 
171
173
  class ProgramAbort(Triggerable):
172
- """Abort a data collection by setting the PMAC string and then wait for the \
173
- status value to go back to 0.
174
+ """Abort a data collection by setting the PMAC string and then wait for the
175
+ status value to go back to 0.
174
176
  """
175
177
 
176
178
  def __init__(
@@ -12,7 +12,7 @@ class LabXraySource(float, Enum):
12
12
 
13
13
 
14
14
  class LabXraySourceReadable(StandardReadable):
15
- """Simple device to get the laboratory x-ray tube energy reading"""
15
+ """Simple device to get the laboratory x-ray tube energy reading."""
16
16
 
17
17
  def __init__(self, xraysource: LabXraySource, name: str = "") -> None:
18
18
  with self.add_children_as_readables():
File without changes
@@ -8,7 +8,17 @@ from ophyd_async.epics.core import epics_signal_r
8
8
 
9
9
  class Andor2Point(SingleTriggerDetector):
10
10
  """Using the andor2 as if it is a massive point detector, read the read uncached
11
- value after a picture is taken."""
11
+ value after a picture is taken.
12
+
13
+ Args:
14
+ prefix (str): Beamline camera PV.
15
+ drv_suffix (str): Camera PV suffix.
16
+ read_uncached (dict[str,str]): A dictionary contains the name and the PV
17
+ suffix for the statistic plugin.
18
+ name (str): Name of the device.
19
+ plugins ([dict[str, NDPluginBaseIO], optional): Dictionary containing
20
+ plugin that are forward to the base class.
21
+ """
12
22
 
13
23
  def __init__(
14
24
  self,
@@ -18,20 +28,6 @@ class Andor2Point(SingleTriggerDetector):
18
28
  name: str = "",
19
29
  plugins: dict[str, NDPluginBaseIO] | None = None,
20
30
  ) -> None:
21
- """
22
- Parameters
23
- ----------
24
- prefix: str,
25
- Beamline camera pv
26
- drv_suffix : str,
27
- Camera pv suffix
28
- read_uncached: dict[str,str]
29
- A dictionary contains the name and the pv suffix for the statistic plugin.
30
- name: str:
31
- Name of the device.
32
- plugins:: Optional[dict[str, NDPluginBaseIO] | None
33
- Dictionary containing plugin that are forward to the base class.
34
- """
35
31
  with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
36
32
  for k, v in read_uncached.items():
37
33
  setattr(self, k, epics_signal_r(float, prefix + v))
@@ -43,10 +43,19 @@ class BimorphMirrorChannel(StandardReadable, EpicsDevice):
43
43
  """Collection of PVs comprising a single bimorph channel.
44
44
 
45
45
  Attributes:
46
- target_voltage: Float RW_RBV for target voltage, which can be set using parent mirror's all target proc
47
- output_voltage: Float RW_RBV for current voltage on bimorph
48
- status: BimorphMirrorOnOff readable for ON/OFF status of channel
49
- shift: Float writeable shifting channel voltage
46
+ target_voltage (SignalRW): Float RW_RBV for target voltage, which can be set
47
+ using parent mirror's all target proc.
48
+ output_voltage (SignalRW): Float RW_RBV for current voltage on bimorph.
49
+ status (SignalR): BimorphMirrorOnOff readable for ON/OFF status of channel.
50
+ shift (SignalW): Float writeable shifting channel voltage.
51
+
52
+ Args:
53
+ prefix (str): PV prefix.
54
+ number_of_channels (int): Number of channels on bimorph mirror (can be zero).
55
+ name (str, optional): Name of device.
56
+
57
+ Raises:
58
+ ValueError: number_of_channels is less than zero.
50
59
  """
51
60
 
52
61
  target_voltage: A[SignalRW[float], PvSuffix.rbv("VTRGT"), Format.CONFIG_SIGNAL]
@@ -59,21 +68,14 @@ class BimorphMirror(StandardReadable, Movable[list[float]]):
59
68
  """Class to represent CAENels Bimorph Mirrors.
60
69
 
61
70
  Attributes:
62
- channels: DeviceVector of BimorphMirrorChannel, indexed from 1, for each channel
63
- enabled: Writeable BimorphOnOff
64
- status: Readable BimorphMirrorStatus Busy/Idle status
65
- err: Alarm status"""
71
+ channels (DeviceVector): DeviceVector of BimorphMirrorChannel, indexed from 1,
72
+ for each channel.
73
+ enabled (SignalW): Writeable BimorphOnOff.
74
+ status (SignalR): Readable BimorphMirrorStatus Busy/Idle status.
75
+ err (SignalR): Alarm status.
76
+ """
66
77
 
67
78
  def __init__(self, prefix: str, number_of_channels: int, name=""):
68
- """
69
- Args:
70
- prefix: str PV prefix
71
- number_of_channels: int number of channels on bimorph mirror (can be zero)
72
- name: str name of device
73
-
74
- Raises:
75
- ValueError: number_of_channels is less than zero"""
76
-
77
79
  if number_of_channels < 0:
78
80
  raise ValueError(f"Number of channels is below zero: {number_of_channels}")
79
81
 
@@ -95,11 +97,11 @@ class BimorphMirror(StandardReadable, Movable[list[float]]):
95
97
  """Sets bimorph voltages in parallel via target voltage and all proc.
96
98
 
97
99
  Args:
98
- value: List of float target voltages
100
+ value (list[float]): List of float target voltages.
99
101
 
100
102
  Raises:
101
- ValueError: On set to non-existent channel"""
102
-
103
+ ValueError: On set to non-existent channel.
104
+ """
103
105
  if len(value) != len(self.channels):
104
106
  raise ValueError(
105
107
  f"Length of value input array does not match number of \
@@ -13,8 +13,9 @@ class CollimationTable(StandardReadable):
13
13
  There are 2 physical horizontal motors 1 upstream, 1 downstream. These provide yaw.
14
14
 
15
15
  Table motion is disabled by an object being within the laser curtain area and can be
16
- overridden by use of the dead man's handle device or locking the hutch. The effect of
17
- these disabling systems is to cut power to the motors - signal for this is crate_power
16
+ overridden by use of the dead man's handle device or locking the hutch. The effect
17
+ of these disabling systems is to cut power to the motors - signal for this is
18
+ `crate_power`.
18
19
  """
19
20
 
20
21
  def __init__(self, prefix: str, name: str = ""):