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
@@ -12,17 +12,16 @@ from ophyd_async.core import (
12
12
  soft_signal_rw,
13
13
  )
14
14
 
15
- from dodal.devices.common_dcm import DoubleCrystalMonochromatorBase
16
- from dodal.devices.i09_1_shared.hard_undulator_functions import (
15
+ from dodal.devices.beamlines.i09_1_shared.hard_undulator_functions import (
17
16
  MAX_ENERGY_COLUMN,
18
17
  MIN_ENERGY_COLUMN,
19
18
  )
19
+ from dodal.devices.common_dcm import DoubleCrystalMonochromatorBase
20
20
  from dodal.devices.undulator import UndulatorInMm, UndulatorOrder
21
21
 
22
22
 
23
23
  class HardInsertionDeviceEnergy(StandardReadable, Movable[float]):
24
- """
25
- Compound device to link hard x-ray undulator gap and order to photon energy.
24
+ """Compound device to link hard x-ray undulator gap and order to photon energy.
26
25
  Setting the energy adjusts the undulator gap accordingly.
27
26
  """
28
27
 
@@ -83,8 +82,8 @@ class HardInsertionDeviceEnergy(StandardReadable, Movable[float]):
83
82
 
84
83
 
85
84
  class HardEnergy(StandardReadable, Locatable[float]):
86
- """
87
- Energy compound device that provides combined change of both DCM energy and undulator gap accordingly.
85
+ """Energy compound device that provides combined change of both DCM energy and
86
+ undulator gap accordingly.
88
87
  """
89
88
 
90
89
  def __init__(
@@ -49,9 +49,7 @@ def _calculate_gamma(look_up_table: dict[int, "np.ndarray"], order: int) -> floa
49
49
  def _calculate_undulator_parameter_max(
50
50
  magnet_field: float, undulator_period_mm: int
51
51
  ) -> float:
52
- """
53
- Calculate the maximum undulator parameter.
54
- """
52
+ """Calculate the maximum undulator parameter."""
55
53
  return (
56
54
  (
57
55
  2
@@ -73,22 +71,25 @@ def calculate_gap_i09_hu(
73
71
  gap_offset: float = 0.0,
74
72
  undulator_period_mm: int = 27,
75
73
  ) -> float:
76
- """
77
- Calculate the undulator gap required to produce a given energy at a given harmonic order.
78
- This algorithm was provided by the I09 beamline scientists, and is based on the physics of undulator radiation.
74
+ """Calculate the undulator gap required to produce a given energy at a given
75
+ harmonic order. This algorithm was provided by the I09 beamline scientists, and is
76
+ based on the physics of undulator radiation.
77
+
79
78
  https://cxro.lbl.gov//PDF/X-Ray-Data-Booklet.pdf
80
79
 
81
80
  Args:
82
81
  photon_energy_kev (float): Requested photon energy in keV.
83
- look_up_table (dict[int, np.ndarray]): Lookup table containing undulator and beamline parameters for each harmonic order.
84
- order (int, optional): Harmonic order for which to calculate the gap. Defaults to 1.
85
- gap_offset (float, optional): Additional gap offset to apply (in mm). Defaults to 0.0.
82
+ look_up_table (dict[int, np.ndarray]): Lookup table containing undulator and
83
+ beamline parameters for each harmonic order.
84
+ order (int, optional): Harmonic order for which to calculate the gap. Defaults
85
+ to 1.
86
+ gap_offset (float, optional): Additional gap offset to apply (in mm). Defaults
87
+ to 0.0.
86
88
  undulator_period_mm (int, optional): Undulator period in mm. Defaults to 27.
87
89
 
88
90
  Returns:
89
91
  float: Calculated undulator gap in millimeters.
90
92
  """
91
-
92
93
  _validate_order(order, look_up_table)
93
94
  gamma = _calculate_gamma(look_up_table, order)
94
95
 
@@ -141,15 +142,17 @@ def calculate_energy_i09_hu(
141
142
  gap_offset: float = 0.0,
142
143
  undulator_period_mm: int = 27,
143
144
  ) -> float:
144
- """
145
- Calculate the photon energy produced by the undulator at a given gap and harmonic order.
146
- Reverse of the calculate_gap_i09_hu function.
145
+ """Calculate the photon energy produced by the undulator at a given gap and harmonic
146
+ order. Reverse of the calculate_gap_i09_hu function.
147
147
 
148
148
  Args:
149
149
  gap (float): Undulator gap in millimeters.
150
- look_up_table (dict[int, np.ndarray]): Lookup table containing undulator and beamline parameters for each harmonic order.
151
- order (int, optional): Harmonic order for which to calculate the energy. Defaults to 1.
152
- gap_offset (float, optional): Additional gap offset to apply (in mm). Defaults to 0.0.
150
+ look_up_table (dict[int, np.ndarray]): Lookup table containing undulator and
151
+ beamline parameters for each harmonic order.
152
+ order (int, optional): Harmonic order for which to calculate the energy.
153
+ Defaults to 1.
154
+ gap_offset (float, optional): Additional gap offset to apply (in mm). Defaults
155
+ to 0.0.
153
156
  undulator_period_mm (int, optional): Undulator period in mm. Defaults to 27.
154
157
 
155
158
  Returns:
@@ -86,7 +86,8 @@ class D3jPosition(StrictEnum):
86
86
  class I10PneumaticStage(StandardReadable):
87
87
  """Pneumatic stage only has two real positions in or out.
88
88
  Use for fluorescent screen which can be insert into the x-ray beam.
89
- Most often use in conjunction with a webcam to locate the x-ray beam."""
89
+ Most often use in conjunction with a webcam to locate the x-ray beam.
90
+ """
90
91
 
91
92
  def __init__(
92
93
  self,
@@ -106,7 +107,7 @@ class I10PneumaticStage(StandardReadable):
106
107
 
107
108
 
108
109
  class ScreenCam(Device):
109
- """Compound device of pneumatic stage(fluorescent screen) and webcam"""
110
+ """Compound device of pneumatic stage(fluorescent screen) and webcam."""
110
111
 
111
112
  def __init__(
112
113
  self,
@@ -191,7 +192,7 @@ class I10JDiagnostic(Device):
191
192
 
192
193
 
193
194
  class I10Diagnostic5ADet(Device):
194
- """Diagnostic 5a detection with drain current and photo diode"""
195
+ """Diagnostic 5a detection with drain current and photo diode."""
195
196
 
196
197
  def __init__(
197
198
  self, prefix: str, name: str = "", connector: DeviceConnector | None = None
@@ -32,7 +32,14 @@ ALPHA_OFFSET = 180
32
32
 
33
33
 
34
34
  class I10Apple2(Apple2[UndulatorPhaseAxes]):
35
- """I10Apple2 device is an apple2 with extra jaw phase motor."""
35
+ """I10Apple2 device is an apple2 with extra jaw phase motor.
36
+
37
+ Args:
38
+ id_gap (UndulatorJawPhase): The gap motor of the undulator.
39
+ id_phase (UndulatorJawPhase): The phase motors of the undulator.
40
+ id_jaw_phase (UndulatorJawPhase): The jaw phase motor of the undulator.
41
+ name (str, optional): The name of the device, by default "".
42
+ """
36
43
 
37
44
  def __init__(
38
45
  self,
@@ -41,27 +48,29 @@ class I10Apple2(Apple2[UndulatorPhaseAxes]):
41
48
  id_jaw_phase: UndulatorJawPhase,
42
49
  name: str = "",
43
50
  ) -> None:
44
- """
45
- Parameters:
46
- ------------
47
- id_gap : UndulatorJawPhase
48
- The gap motor of the undulator.
49
- id_phase : UndulatorJawPhase
50
- The phase motors of the undulator.
51
- id_jaw_phase : UndulatorJawPhase
52
- The jaw phase motor of the undulator.
53
- name : str, optional
54
- The name of the device, by default "".
55
- """
56
51
  with self.add_children_as_readables():
57
52
  self.jaw_phase = Reference(id_jaw_phase)
58
53
  super().__init__(id_gap=id_gap, id_phase=id_phase, name=name)
59
54
 
60
55
 
61
56
  class I10Apple2Controller(Apple2Controller[I10Apple2]):
62
- """
63
- I10Apple2Controller is a extension of Apple2Controller which provide linear
57
+ """I10Apple2Controller is a extension of Apple2Controller which provide linear
64
58
  arbitrary angle control.
59
+
60
+ Args:
61
+ apple2 (I10Apple2): An I10Apple2 device.
62
+ gap_energy_motor_lut (EnergyMotorLookup): The class that handles the gap
63
+ look up table logic for the insertion device.
64
+ phase_energy_motor_lut (EnergyMotorLookup): The class that handles the phase
65
+ look up table logic for the insertion device.
66
+ jaw_phase_limit (float, optional): The maximum allowed jaw_phase movement.
67
+ The default is 12.0
68
+ jaw_phase_poly_param (list[float], optional): polynomial parameters highest
69
+ power first. The default is DEFAULT_JAW_PHASE_POLY_PARAMS
70
+ angle_threshold_deg (float, optional): The angle threshold to switch between
71
+ 0-180 and 180-360 range. The default is 30.0
72
+ units (str, optional): the units of this device. Defaults to eV.
73
+ name (str, optional): New device name.
65
74
  """
66
75
 
67
76
  def __init__(
@@ -75,26 +84,6 @@ class I10Apple2Controller(Apple2Controller[I10Apple2]):
75
84
  units: str = "eV",
76
85
  name: str = "",
77
86
  ) -> None:
78
- """
79
- Parameters:
80
- -----------
81
- apple2 : I10Apple2
82
- An I10Apple2 device.
83
- gap_energy_motor_lut: EnergyMotorLookup
84
- The class that handles the gap look up table logic for the insertion device.
85
- phase_energy_motor_lut: EnergyMotorLookup
86
- The class that handles the phase look up table logic for the insertion device.
87
- jaw_phase_limit : float, optional
88
- The maximum allowed jaw_phase movement., by default 12.0
89
- jaw_phase_poly_param : list[float], optional
90
- polynomial parameters highest power first., by default DEFAULT_JAW_PHASE_POLY_PARAMS
91
- angle_threshold_deg : float, optional
92
- The angle threshold to switch between 0-180 and 180-360 range., by default 30.0
93
- units:
94
- the units of this device. Defaults to eV.
95
- name : str, optional
96
- New device name.
97
- """
98
87
  self.gap_energy_motor_lut = gap_energy_motor_lut
99
88
  self.phase_energy_motor_lut = phase_energy_motor_lut
100
89
  super().__init__(
@@ -167,8 +156,13 @@ class I10Apple2Controller(Apple2Controller[I10Apple2]):
167
156
 
168
157
 
169
158
  class LinearArbitraryAngle(StandardReadable, Movable[SupportsFloat]):
170
- """
171
- Device to set the polarisation angle of the Apple2 undulator in Linear Arbitrary (LA) mode.
159
+ """Device to set the polarisation angle of the Apple2 undulator in Linear Arbitrary
160
+ (LA) mode.
161
+
162
+ Args:
163
+ id_controller (I10Apple2Controller): The I10Apple2Controller which control
164
+ the ID.
165
+ name (str, optional): New device name.
172
166
  """
173
167
 
174
168
  def __init__(
@@ -176,14 +170,6 @@ class LinearArbitraryAngle(StandardReadable, Movable[SupportsFloat]):
176
170
  id_controller: I10Apple2Controller,
177
171
  name: str = "",
178
172
  ) -> None:
179
- """
180
- Parameters
181
- ----------
182
- id_controller : I10Apple2Controller
183
- The I10Apple2Controller which control the ID.
184
- name : str, optional
185
- New device name.
186
- """
187
173
  super().__init__(name=name)
188
174
  self.linear_arbitrary_angle = Reference(id_controller.linear_arbitrary_angle)
189
175
 
@@ -6,11 +6,6 @@ from dodal.devices.current_amplifiers import (
6
6
  Femto3xxGainToCurrentTable,
7
7
  Femto3xxRaiseTime,
8
8
  FemtoDDPCA,
9
- SR570FineGainTable,
10
- SR570FullGainTable,
11
- SR570GainTable,
12
- SR570GainToCurrentTable,
13
- SR570RaiseTimeTable,
14
9
  )
15
10
 
16
11
 
@@ -41,32 +36,14 @@ class RasorFemto(Device):
41
36
 
42
37
 
43
38
  class RasorSR570(Device):
44
- def __init__(self, prefix: str, suffix: str = "SENS:SEL", name: str = "") -> None:
39
+ def __init__(self, prefix: str, name: str = "") -> None:
45
40
  self.ca1 = SR570(
46
41
  prefix + "-04:",
47
- suffix=suffix,
48
- fine_gain_table=SR570FineGainTable,
49
- coarse_gain_table=SR570GainTable,
50
- combined_table=SR570FullGainTable,
51
- gain_to_current_table=SR570GainToCurrentTable,
52
- raise_timetable=SR570RaiseTimeTable,
53
42
  )
54
43
  self.ca2 = SR570(
55
44
  prefix + "-05:",
56
- suffix=suffix,
57
- fine_gain_table=SR570FineGainTable,
58
- coarse_gain_table=SR570GainTable,
59
- combined_table=SR570FullGainTable,
60
- gain_to_current_table=SR570GainToCurrentTable,
61
- raise_timetable=SR570RaiseTimeTable,
62
45
  )
63
46
  self.ca3 = SR570(
64
47
  prefix + "-06:",
65
- suffix=suffix,
66
- fine_gain_table=SR570FineGainTable,
67
- coarse_gain_table=SR570GainTable,
68
- combined_table=SR570FullGainTable,
69
- gain_to_current_table=SR570GainToCurrentTable,
70
- raise_timetable=SR570RaiseTimeTable,
71
48
  )
72
49
  super().__init__(name)
@@ -18,7 +18,7 @@ class Diffractometer(StandardReadable):
18
18
 
19
19
 
20
20
  class DetSlits(StandardReadable):
21
- "Detector slits"
21
+ """Detector slits."""
22
22
 
23
23
  def __init__(
24
24
  self,
@@ -32,7 +32,7 @@ class DetSlits(StandardReadable):
32
32
 
33
33
 
34
34
  class PaStage(StandardReadable):
35
- "Rasor detector stage"
35
+ """Rasor detector stage."""
36
36
 
37
37
  def __init__(
38
38
  self,
@@ -27,9 +27,10 @@ class I10SlitsBlades(Slits):
27
27
 
28
28
 
29
29
  class BladeDrainCurrents(Device):
30
- """ "The drain current measurements on each blade. The drain current are due to
30
+ """The drain current measurements on each blade. The drain current are due to
31
31
  photoelectric effect (https://en.wikipedia.org/wiki/Photoelectric_effect).
32
- Note the readings are in voltage as it is the output of a current amplifier."""
32
+ Note the readings are in voltage as it is the output of a current amplifier.
33
+ """
33
34
 
34
35
  def __init__(
35
36
  self,
@@ -59,7 +60,8 @@ class BladeDrainCurrents(Device):
59
60
 
60
61
  class I10PrimarySlits(Slits):
61
62
  """First slits of the beamline with very high power load, they are two square water
62
- cooled blocks(aperture/aptr) that overlap to produce slit like behavior."""
63
+ cooled blocks(aperture/aptr) that overlap to produce slit like behavior.
64
+ """
63
65
 
64
66
  def __init__(self, prefix: str, name: str = "") -> None:
65
67
  with self.add_children_as_readables():
@@ -0,0 +1,9 @@
1
+ from .electromagnet.magnet import ElectromagnetMagnetField
2
+ from .electromagnet.stages import ElectromagnetStage
3
+ from .scaler_cards import I10JScalerCard
4
+
5
+ __all__ = [
6
+ "ElectromagnetMagnetField",
7
+ "I10JScalerCard",
8
+ "ElectromagnetStage",
9
+ ]
@@ -0,0 +1,16 @@
1
+ from ophyd_async.core import StandardReadable
2
+ from ophyd_async.epics.core import epics_signal_rw
3
+
4
+
5
+ class ElectromagnetMagnetField(StandardReadable):
6
+ def __init__(
7
+ self,
8
+ prefix: str,
9
+ name: str = "",
10
+ ):
11
+ with self.add_children_as_readables():
12
+ self.field = epics_signal_rw(
13
+ float, write_pv=prefix + "FIELD", read_pv=prefix + "FIELD:RBV"
14
+ )
15
+ self.current = epics_signal_rw(float, prefix + "DMD")
16
+ super().__init__(name=name)
@@ -0,0 +1,14 @@
1
+ from ophyd_async.core import StandardReadable
2
+ from ophyd_async.epics.motor import Motor
3
+
4
+
5
+ class ElectromagnetStage(StandardReadable):
6
+ def __init__(
7
+ self,
8
+ prefix: str,
9
+ name: str = "",
10
+ ):
11
+ with self.add_children_as_readables():
12
+ self.y = Motor(prefix + "Y")
13
+ self.pitch = Motor(prefix + "PITCH")
14
+ super().__init__(name=name)
@@ -0,0 +1,13 @@
1
+ from ophyd_async.core import StandardReadable
2
+
3
+ from dodal.devices.current_amplifiers import StruckScaler
4
+
5
+
6
+ class I10JScalerCard(StandardReadable):
7
+ def __init__(self, prefix, name: str = "") -> None:
8
+ with self.add_children_as_readables():
9
+ self.mon = StruckScaler(prefix=prefix, suffix=".S17")
10
+ self.tey = StruckScaler(prefix=prefix, suffix=".S18")
11
+ self.fy = StruckScaler(prefix=prefix, suffix=".S19")
12
+ self.fy2 = StruckScaler(prefix=prefix, suffix=".S20")
13
+ super().__init__(name)
@@ -9,7 +9,7 @@ EU = TypeVar("EU", bound=EurothermGeneral)
9
9
 
10
10
 
11
11
  class CyberstarBlower(StandardReadable, Generic[EU]):
12
- """This is a specific device that uses a Eurotherm controller"""
12
+ """This is a specific device that uses a Eurotherm controller."""
13
13
 
14
14
  def __init__(
15
15
  self,
@@ -4,10 +4,9 @@ from dodal.devices.motors import Stage
4
4
 
5
5
 
6
6
  class DiffractometerStage(Stage):
7
- """
8
- This is the diffractometer stage which contains both detectors,
7
+ """This is the diffractometer stage which contains both detectors,
9
8
  it allows for rotations and also sample position. Contains:
10
- theta, delta, two_theta, sample_position
9
+ theta, delta, two_theta, sample_position.
11
10
  """
12
11
 
13
12
  def __init__(
@@ -29,10 +28,9 @@ class DiffractometerStage(Stage):
29
28
 
30
29
 
31
30
  class DiffractometerBase(Stage):
32
- """
33
- This is the diffractometer stage which contains both detectors,
31
+ """This is the diffractometer stage which contains both detectors,
34
32
  it allows for translation about x and y and also sample position. Contains:
35
- x1, x2, y1, y2, y3. Used for aligning the detector to the beam/sample
33
+ x1, x2, y1, y2, y3. Used for aligning the detector to the beam/sample.
36
34
  """
37
35
 
38
36
  def __init__(
@@ -99,7 +99,7 @@ _BIT_DEPTH = 24
99
99
 
100
100
 
101
101
  class Mythen3Controller(ADBaseController):
102
- """ADBaseController` for a Mythen3"""
102
+ """ADBaseController` for a Mythen3."""
103
103
 
104
104
  def __init__(self, driver: Mythen3Driver):
105
105
  self._driver = driver
@@ -134,9 +134,8 @@ class Mythen3Controller(ADBaseController):
134
134
 
135
135
 
136
136
  class Mythen3(AreaDetector[Mythen3Controller]):
137
- """
138
- The detector may be configured for an external trigger on a GPIO port,
139
- which must be done prior to preparing the detector
137
+ """The detector may be configured for an external trigger on a GPIO port,
138
+ which must be done prior to preparing the detector.
140
139
  """
141
140
 
142
141
  def __init__(
@@ -34,9 +34,8 @@ class RobotSampleState(float, Enum):
34
34
 
35
35
 
36
36
  class NX100Robot(StandardReadable, Locatable[int], Stoppable, Pausable):
37
- """
38
- This is a Yaskawa Motoman that uses an NX100 controller. It consists of a robot arm
39
- with a gripper and a carousel for sample handling. It can pick and place samples
37
+ """This is a Yaskawa Motoman that uses an NX100 controller. It consists of a robot
38
+ arm with a gripper and a carousel for sample handling. It can pick and place samples
40
39
  from the carousel to the diffractometer and vice versa.
41
40
 
42
41
  Has set, pause, resume, stop, locate, stage methods.
@@ -71,9 +70,10 @@ class NX100Robot(StandardReadable, Locatable[int], Stoppable, Pausable):
71
70
  )
72
71
 
73
72
  async def clear_sample(self, table_in: bool = True):
74
- """clears the sample from the diffractometer and places it on the carousel.
75
- if table_in is True, it will also move the sample holder to the table in position."""
76
-
73
+ """Clears the sample from the diffractometer and places it on the carousel.
74
+ if table_in is True, it will also move the sample holder to the table in
75
+ position.
76
+ """
77
77
  sample_state = await self.robot_sample_state.get_value()
78
78
  if sample_state == RobotSampleState.DIFFRACTOMETER:
79
79
  await asyncio.gather(
@@ -8,7 +8,7 @@ from ophyd_async.epics.core import epics_signal_rw
8
8
 
9
9
 
10
10
  class Spinner(StandardReadable, Pausable):
11
- """This is a simple sample spinner, that has enable and speed (%)"""
11
+ """This is a simple sample spinner, that has enable and speed (%)."""
12
12
 
13
13
  def __init__(
14
14
  self,
@@ -2,7 +2,7 @@ from ophyd_async.core import PathProvider, StandardDetector
2
2
  from ophyd_async.epics import adcore
3
3
 
4
4
  from dodal.common.beamlines.device_helpers import CAM_SUFFIX, HDF5_SUFFIX
5
- from dodal.devices.i13_1.merlin_controller import MerlinController
5
+ from dodal.devices.beamlines.i13_1.merlin_controller import MerlinController
6
6
 
7
7
 
8
8
  class Merlin(StandardDetector):
@@ -23,8 +23,7 @@ class ThetaRollYZCrystal(ThetaYCrystal):
23
23
 
24
24
 
25
25
  class DCM(DoubleCrystalMonochromatorBase[ThetaRollYZCrystal, ThetaYCrystal]):
26
- """
27
- A double crystal monochromator device, used to select the beam energy.
26
+ """A double crystal monochromator device, used to select the beam energy.
28
27
 
29
28
  Once the i15 DCM supports all of the PVs required by DoubleCrystalMonochromator or
30
29
  DoubleCrystalMonochromatorWithDSpacing this class can be changed to inherit from it,
@@ -3,7 +3,7 @@ from ophyd_async.epics.motor import Motor
3
3
 
4
4
 
5
5
  class FocusingMirrorBase(StandardReadable):
6
- """Focusing Mirror with curve, ellip & pitch"""
6
+ """Focusing Mirror with curve, ellip & pitch."""
7
7
 
8
8
  def __init__(self, prefix: str, name: str = ""):
9
9
  with self.add_children_as_readables():
@@ -15,7 +15,7 @@ class FocusingMirrorBase(StandardReadable):
15
15
 
16
16
 
17
17
  class FocusingMirrorHorizontal(FocusingMirrorBase):
18
- """Focusing Mirror with curve, ellip, pitch & X"""
18
+ """Focusing Mirror with curve, ellip, pitch & X."""
19
19
 
20
20
  def __init__(self, prefix: str, name: str = ""):
21
21
  with self.add_children_as_readables():
@@ -25,7 +25,7 @@ class FocusingMirrorHorizontal(FocusingMirrorBase):
25
25
 
26
26
 
27
27
  class FocusingMirrorVertical(FocusingMirrorBase):
28
- """Focusing Mirror with curve, ellip, pitch & Y"""
28
+ """Focusing Mirror with curve, ellip, pitch & Y."""
29
29
 
30
30
  def __init__(self, prefix: str, name: str = ""):
31
31
  with self.add_children_as_readables():
@@ -35,7 +35,7 @@ class FocusingMirrorVertical(FocusingMirrorBase):
35
35
 
36
36
 
37
37
  class FocusingMirror(FocusingMirrorBase):
38
- """Focusing Mirror with curve, ellip, pitch, yaw, X & Y"""
38
+ """Focusing Mirror with curve, ellip, pitch, yaw, X & Y."""
39
39
 
40
40
  def __init__(self, prefix: str, name: str = ""):
41
41
  with self.add_children_as_readables():
@@ -47,7 +47,7 @@ class FocusingMirror(FocusingMirrorBase):
47
47
 
48
48
 
49
49
  class FocusingMirrorWithRoll(FocusingMirror):
50
- """Focusing Mirror with curve, ellip, pitch, roll, yaw, X & Y"""
50
+ """Focusing Mirror with curve, ellip, pitch, roll, yaw, X & Y."""
51
51
 
52
52
  def __init__(self, prefix: str, name: str = "") -> None:
53
53
  with self.add_children_as_readables():
@@ -3,7 +3,7 @@ from ophyd_async.epics.motor import Motor
3
3
 
4
4
 
5
5
  class JackX(StandardReadable):
6
- """Focusing Mirror"""
6
+ """Focusing Mirror."""
7
7
 
8
8
  def __init__(self, prefix: str, name: str = ""):
9
9
  with self.add_children_as_readables():
@@ -17,7 +17,7 @@ class JackX(StandardReadable):
17
17
 
18
18
 
19
19
  class JackY(StandardReadable):
20
- """Focusing Mirror"""
20
+ """Focusing Mirror."""
21
21
 
22
22
  def __init__(self, prefix: str, name: str = ""):
23
23
  with self.add_children_as_readables():
@@ -3,7 +3,7 @@ from ophyd_async.epics.motor import Motor
3
3
 
4
4
 
5
5
  class MultiLayerMirror(StandardReadable):
6
- """Multilayer Mirror"""
6
+ """Multilayer Mirror."""
7
7
 
8
8
  def __init__(self, prefix: str, name: str = ""):
9
9
  with self.add_children_as_readables():
@@ -17,9 +17,17 @@ MAXIMUM_MOVE_TIME = 550 # There is no useful movements take longer than this.
17
17
 
18
18
 
19
19
  class I17Apple2Controller(Apple2Controller[Apple2[UndulatorPhaseAxes]]):
20
- """
21
- I10Apple2Controller is a extension of Apple2Controller which provide linear
20
+ """I17Apple2Controller is a extension of Apple2Controller which provide linear
22
21
  arbitrary angle control.
22
+
23
+ Args:
24
+ apple2 (Apple2): An Apple2 device.
25
+ gap_energy_motor_lut (EnergyMotorLookup): The class that handles the gap
26
+ look up table logic for the insertion device.
27
+ phase_energy_motor_lut (EnergyMotorLookup): The class that handles the phase
28
+ look up table logic for the insertion device.
29
+ units (str, optional): The units of this device. Defaults to eV.
30
+ name (str, optional): New device name.
23
31
  """
24
32
 
25
33
  def __init__(
@@ -30,20 +38,6 @@ class I17Apple2Controller(Apple2Controller[Apple2[UndulatorPhaseAxes]]):
30
38
  units: str = "eV",
31
39
  name: str = "",
32
40
  ) -> None:
33
- """
34
- Parameters:
35
- -----------
36
- apple2 : Apple2
37
- An Apple2 device.
38
- gap_energy_motor_lut: EnergyMotorLookup
39
- The class that handles the gap look up table logic for the insertion device.
40
- phase_energy_motor_lut: EnergyMotorLookup
41
- The class that handles the phase look up table logic for the insertion device.
42
- units:
43
- the units of this device. Defaults to eV.
44
- name : str, optional
45
- New device name.
46
- """
47
41
  self.gap_energy_motor_lut = gap_energy_motor_lut
48
42
  self.phase_energy_motor_lut = phase_energy_motor_lut
49
43
  super().__init__(
@@ -5,7 +5,7 @@ from dodal.devices.positioner import create_positioner
5
5
 
6
6
 
7
7
  class FilterAValues(StrictEnum):
8
- """Maps from a short usable name to the string name in EPICS"""
8
+ """Maps from a short usable name to the string name in EPICS."""
9
9
 
10
10
  AL_2MM = "2 mm Al"
11
11
  AL_1_5MM = "1.5 mm Al"