dls-dodal 1.32.0__tar.gz → 1.33.0__tar.gz

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 (332) hide show
  1. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/PKG-INFO +1 -1
  2. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/reference/device-standards.rst +78 -5
  3. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/pull_request_template.md +1 -1
  4. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dls_dodal.egg-info/PKG-INFO +1 -1
  5. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dls_dodal.egg-info/SOURCES.txt +2 -0
  6. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/_version.py +2 -2
  7. dls_dodal-1.33.0/src/dodal/beamlines/b01_1.py +77 -0
  8. dls_dodal-1.33.0/src/dodal/common/signal_utils.py +53 -0
  9. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/aperturescatterguard.py +12 -15
  10. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/oav_detector.py +1 -15
  11. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/oav/test_oav.py +0 -29
  12. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_aperture_scatterguard.py +45 -20
  13. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_oav.py +0 -22
  14. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_zocalo_results.py +34 -53
  15. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.copier-answers.yml +0 -0
  16. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.devcontainer/devcontainer.json +0 -0
  17. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/CONTRIBUTING.md +0 -0
  18. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/ISSUE_TEMPLATE/issue_template.md +0 -0
  19. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/actions/install_requirements/action.yml +0 -0
  20. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/dependabot.yml +0 -0
  21. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/pages/index.html +0 -0
  22. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/pages/make_switcher.py +0 -0
  23. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/workflows/_check.yml +0 -0
  24. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/workflows/_dist.yml +0 -0
  25. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/workflows/_docs.yml +0 -0
  26. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/workflows/_pypi.yml +0 -0
  27. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/workflows/_release.yml +0 -0
  28. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/workflows/_test.yml +0 -0
  29. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/workflows/_tox.yml +0 -0
  30. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/workflows/ci.yml +0 -0
  31. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.github/workflows/periodic.yml +0 -0
  32. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.gitignore +0 -0
  33. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.pre-commit-config.yaml +0 -0
  34. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.vscode/extensions.json +0 -0
  35. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.vscode/launch.json +0 -0
  36. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.vscode/settings.json +0 -0
  37. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/.vscode/tasks.json +0 -0
  38. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/Dockerfile +0 -0
  39. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/LICENSE +0 -0
  40. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/README.md +0 -0
  41. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/catalog-info.yaml +0 -0
  42. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/_templates/autosummary/class.rst +0 -0
  43. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/_templates/autosummary/module.rst +0 -0
  44. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/assets/zocalo.png +0 -0
  45. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/conf.py +0 -0
  46. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  47. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  48. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/explanations/decisions/COPYME +0 -0
  49. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/explanations/decisions.md +0 -0
  50. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/explanations.md +0 -0
  51. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/genindex.md +0 -0
  52. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/build-docs.md +0 -0
  53. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/contribute.md +0 -0
  54. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/coverage.md +0 -0
  55. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/create-beamline.rst +0 -0
  56. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/dev-install.md +0 -0
  57. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/excalidraw.md +0 -0
  58. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/lint.md +0 -0
  59. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/lock-requirements.md +0 -0
  60. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/make-new-ophyd-async-device.rst +0 -0
  61. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/make-release.md +0 -0
  62. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/move-code.rst +0 -0
  63. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/pypi.md +0 -0
  64. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/run-tests.md +0 -0
  65. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/static-analysis.md +0 -0
  66. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/update-template.md +0 -0
  67. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to/zocalo.rst +0 -0
  68. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/how-to.md +0 -0
  69. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/images/dls-logo.svg +0 -0
  70. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/images/excalidraw-example.svg +0 -0
  71. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/index.md +0 -0
  72. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/reference/api.md +0 -0
  73. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/reference/standards.rst +0 -0
  74. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/reference.md +0 -0
  75. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/tutorials/get_started.rst +0 -0
  76. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/tutorials/installation.md +0 -0
  77. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/docs/tutorials.md +0 -0
  78. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/pyproject.toml +0 -0
  79. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/setup.cfg +0 -0
  80. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/__init__.py +0 -0
  81. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dls_dodal.egg-info/dependency_links.txt +0 -0
  82. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dls_dodal.egg-info/entry_points.txt +0 -0
  83. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dls_dodal.egg-info/requires.txt +0 -0
  84. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dls_dodal.egg-info/top_level.txt +0 -0
  85. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/__init__.py +0 -0
  86. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/__main__.py +0 -0
  87. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/adsim.py +0 -0
  88. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamline_specific_utils/__init__.py +0 -0
  89. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamline_specific_utils/i03.py +0 -0
  90. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/README.md +0 -0
  91. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/__init__.py +0 -0
  92. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/i03.py +0 -0
  93. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/i04.py +0 -0
  94. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/i04_1.py +0 -0
  95. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/i13_1.py +0 -0
  96. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/i20_1.py +0 -0
  97. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/i22.py +0 -0
  98. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/i23.py +0 -0
  99. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/i24.py +0 -0
  100. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/p38.py +0 -0
  101. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/p45.py +0 -0
  102. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/p99.py +0 -0
  103. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/beamlines/training_rig.py +0 -0
  104. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/cli.py +0 -0
  105. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/__init__.py +0 -0
  106. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/beamlines/__init__.py +0 -0
  107. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/beamlines/beamline_parameters.py +0 -0
  108. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/beamlines/beamline_utils.py +0 -0
  109. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/beamlines/device_helpers.py +0 -0
  110. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/coordination.py +0 -0
  111. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/maths.py +0 -0
  112. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/types.py +0 -0
  113. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/udc_directory_provider.py +0 -0
  114. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/common/visit.py +0 -0
  115. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/CTAB.py +0 -0
  116. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/__init__.py +0 -0
  117. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/adsim.py +0 -0
  118. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/aperture.py +0 -0
  119. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/areadetector/__init__.py +0 -0
  120. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/areadetector/adaravis.py +0 -0
  121. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/areadetector/adsim.py +0 -0
  122. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/areadetector/adutils.py +0 -0
  123. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/areadetector/plugins/MJPG.py +0 -0
  124. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/attenuator.py +0 -0
  125. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/backlight.py +0 -0
  126. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/cryostream.py +0 -0
  127. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/dcm.py +0 -0
  128. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/detector/__init__.py +0 -0
  129. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/detector/det_dim_constants.py +0 -0
  130. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/detector/det_dist_to_beam_converter.py +0 -0
  131. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/detector/det_resolution.py +0 -0
  132. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/detector/detector.py +0 -0
  133. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/detector/detector_motion.py +0 -0
  134. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/eiger.py +0 -0
  135. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/eiger_odin.py +0 -0
  136. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/fast_grid_scan.py +0 -0
  137. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/fluorescence_detector_motion.py +0 -0
  138. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/flux.py +0 -0
  139. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/focusing_mirror.py +0 -0
  140. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/hutch_shutter.py +0 -0
  141. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i03/__init__.py +0 -0
  142. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i04/transfocator.py +0 -0
  143. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i20_1/__init__.py +0 -0
  144. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i22/dcm.py +0 -0
  145. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i22/fswitch.py +0 -0
  146. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i22/nxsas.py +0 -0
  147. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i24/__init__.py +0 -0
  148. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i24/aperture.py +0 -0
  149. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i24/beamstop.py +0 -0
  150. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i24/dcm.py +0 -0
  151. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i24/dual_backlight.py +0 -0
  152. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i24/i24_detector_motion.py +0 -0
  153. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i24/i24_vgonio.py +0 -0
  154. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/i24/pmac.py +0 -0
  155. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/ipin.py +0 -0
  156. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/linkam3.py +0 -0
  157. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/logging_ophyd_device.py +0 -0
  158. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/motors.py +0 -0
  159. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/__init__.py +0 -0
  160. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/grid_overlay.py +0 -0
  161. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/microns_for_zoom_levels.json +0 -0
  162. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/oav_calculations.py +0 -0
  163. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/oav_errors.py +0 -0
  164. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/oav_parameters.py +0 -0
  165. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/oav_to_redis_forwarder.py +0 -0
  166. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/pin_image_recognition/__init__.py +0 -0
  167. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/pin_image_recognition/manual_test.py +0 -0
  168. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/pin_image_recognition/utils.py +0 -0
  169. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/oav/utils.py +0 -0
  170. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/p45.py +0 -0
  171. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/p99/__init__.py +0 -0
  172. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/p99/sample_stage.py +0 -0
  173. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/robot.py +0 -0
  174. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/s4_slit_gaps.py +0 -0
  175. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/scatterguard.py +0 -0
  176. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/scintillator.py +0 -0
  177. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/slits.py +0 -0
  178. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/smargon.py +0 -0
  179. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/status.py +0 -0
  180. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/synchrotron.py +0 -0
  181. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/tetramm.py +0 -0
  182. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/thawer.py +0 -0
  183. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/training_rig/__init__.py +0 -0
  184. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/training_rig/sample_stage.py +0 -0
  185. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/turbo_slit.py +0 -0
  186. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/undulator.py +0 -0
  187. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/undulator_dcm.py +0 -0
  188. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/util/__init__.py +0 -0
  189. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/util/adjuster_plans.py +0 -0
  190. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/util/epics_util.py +0 -0
  191. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/util/lookup_tables.py +0 -0
  192. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/util/motor_utils.py +0 -0
  193. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/util/save_panda.py +0 -0
  194. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/util/test_utils.py +0 -0
  195. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/webcam.py +0 -0
  196. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/xbpm_feedback.py +0 -0
  197. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/xspress3/xspress3.py +0 -0
  198. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/xspress3/xspress3_channel.py +0 -0
  199. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/zebra.py +0 -0
  200. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/zebra_controlled_shutter.py +0 -0
  201. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/zocalo/__init__.py +0 -0
  202. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/zocalo/zocalo_interaction.py +0 -0
  203. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/devices/zocalo/zocalo_results.py +0 -0
  204. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/log.py +0 -0
  205. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/parameters/experiment_parameter_base.py +0 -0
  206. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/plans/check_topup.py +0 -0
  207. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/plans/data_session_metadata.py +0 -0
  208. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/plans/motor_util_plans.py +0 -0
  209. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/src/dodal/utils.py +0 -0
  210. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/__init__.py +0 -0
  211. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/beamlines/__init__.py +0 -0
  212. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/beamlines/unit_tests/__init__.py +0 -0
  213. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/beamlines/unit_tests/test_i03.py +0 -0
  214. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/beamlines/unit_tests/test_i24.py +0 -0
  215. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/beamlines/unit_tests/test_mapping.py +0 -0
  216. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/__init__.py +0 -0
  217. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/beamlines/__init__.py +0 -0
  218. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/beamlines/test_beamline_parameters.py +0 -0
  219. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/beamlines/test_beamline_utils.py +0 -0
  220. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/beamlines/test_device_helpers.py +0 -0
  221. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/beamlines/test_device_instantiation.py +0 -0
  222. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/test_coordination.py +0 -0
  223. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/test_maths.py +0 -0
  224. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/test_udc_directory_provider.py +0 -0
  225. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/common/test_visit.py +0 -0
  226. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/conftest.py +0 -0
  227. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/__init__.py +0 -0
  228. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/i04/__init__.py +0 -0
  229. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/i04/test_transfocator.py +0 -0
  230. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/i22/test_dcm.py +0 -0
  231. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/i22/test_fswitch.py +0 -0
  232. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/i22/test_metadataholder.py +0 -0
  233. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/__init__.py +0 -0
  234. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_aperturescatterguard_system.py +0 -0
  235. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_eiger_system.py +0 -0
  236. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_gridscan_system.py +0 -0
  237. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_oav_system.py +0 -0
  238. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_oav_to_redis_system.py +0 -0
  239. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_slit_gaps_system.py +0 -0
  240. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_smargon_system.py +0 -0
  241. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_synchrotron_system.py +0 -0
  242. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_undulator_system.py +0 -0
  243. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_zebra_system.py +0 -0
  244. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/system_tests/test_zocalo_results.py +0 -0
  245. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/training_rig/test_sample_stage.py +0 -0
  246. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/__init__.py +0 -0
  247. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/areadetector/plugins/test_MJPG.py +0 -0
  248. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/conftest.py +0 -0
  249. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/detector/test_det_dim_constants.py +0 -0
  250. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/detector/test_det_resolution.py +0 -0
  251. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/detector/test_detector.py +0 -0
  252. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/i24/__init__.py +0 -0
  253. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/i24/test_dual_backlight.py +0 -0
  254. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/i24/test_pmac.py +0 -0
  255. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/oav/__init__.py +0 -0
  256. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/oav/image_recognition/test_pin_tip_detect.py +0 -0
  257. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/oav/image_recognition/test_pin_tip_detect_utils.py +0 -0
  258. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/oav/test_oav_parameters.py +0 -0
  259. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/oav/test_oav_to_redis_forwarder.py +0 -0
  260. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/p99/test_p99_stage.py +0 -0
  261. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_OAVCentring.json +0 -0
  262. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_aperture.py +0 -0
  263. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_attenuator.py +0 -0
  264. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_backlight.py +0 -0
  265. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_bart_robot.py +0 -0
  266. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_beam_converter.py +0 -0
  267. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_beamline_undulator_to_gap_lookup_table.txt +0 -0
  268. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_daq_configuration/domain/beamlineParameters +0 -0
  269. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_daq_configuration/lookup/BeamLineEnergy_DCM_Pitch_converter.txt +0 -0
  270. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_daq_configuration/lookup/BeamLineEnergy_DCM_Roll_converter.txt +0 -0
  271. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_dcm.py +0 -0
  272. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_display.configuration +0 -0
  273. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_eiger.py +0 -0
  274. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_focusing_mirror.py +0 -0
  275. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_grid_overlay.py +0 -0
  276. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_gridscan.py +0 -0
  277. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_hutch_shutter.py +0 -0
  278. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_jCameraManZoomLevels.xml +0 -0
  279. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_linkam3.py +0 -0
  280. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_lookup_table.txt +0 -0
  281. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_lookup_table_2.txt +0 -0
  282. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_odin.py +0 -0
  283. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_shutter.py +0 -0
  284. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_slits.py +0 -0
  285. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_smargon.py +0 -0
  286. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_status.py +0 -0
  287. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_synchrotron.py +0 -0
  288. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_tetramm.py +0 -0
  289. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_thawer.py +0 -0
  290. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_undulator.py +0 -0
  291. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_undulator_dcm.py +0 -0
  292. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_utils.py +0 -0
  293. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_webcam.py +0 -0
  294. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_xbpm_feedback.py +0 -0
  295. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_xspress3.py +0 -0
  296. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_zebra.py +0 -0
  297. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/test_zocalo_interaction.py +0 -0
  298. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/util/__init__.py +0 -0
  299. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/util/test_adjuster_plans.py +0 -0
  300. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/util/test_beamline_specific_utils.py +0 -0
  301. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/util/test_lookup_tables.py +0 -0
  302. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/devices/unit_tests/util/test_save_panda.py +0 -0
  303. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_beamline.py +0 -0
  304. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_beamline_all_devices_raise_exception.py +0 -0
  305. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_beamline_broken_dependency.py +0 -0
  306. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_beamline_dependencies.py +0 -0
  307. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_beamline_disordered_dependencies.py +0 -0
  308. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_beamline_misbehaving_builtins.py +0 -0
  309. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_beamline_some_devices_working.py +0 -0
  310. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_zocalo/README.rst +0 -0
  311. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_zocalo/__init__.py +0 -0
  312. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_zocalo/__main__.py +0 -0
  313. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/fake_zocalo/dls_start_fake_zocalo.sh +0 -0
  314. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/plans/test_motor_util_plans.py +0 -0
  315. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/plans/test_topup_plan.py +0 -0
  316. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/preprocessors/test_filesystem_metadata.py +0 -0
  317. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_cli.py +0 -0
  318. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/bad_beamlineParameters +0 -0
  319. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/i04_beamlineParameters +0 -0
  320. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/test_beamline_dcm_roll_converter.txt +0 -0
  321. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/test_beamline_dcm_roll_converter_non_monotonic.txt +0 -0
  322. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/test_beamline_dcm_roll_converter_reversed.txt +0 -0
  323. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/test_beamline_parameters.txt +0 -0
  324. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/test_det_dist_converter.txt +0 -0
  325. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/test_images/oav_snapshot_expected.png +0 -0
  326. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/test_images/oav_snapshot_test.png +0 -0
  327. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/topup_long_delay.txt +0 -0
  328. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_data/topup_short_params.txt +0 -0
  329. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/test_utils.py +0 -0
  330. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/unit_tests/__init__.py +0 -0
  331. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/unit_tests/test_cli.py +0 -0
  332. {dls_dodal-1.32.0 → dls_dodal-1.33.0}/tests/unit_tests/test_log.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dls-dodal
3
- Version: 1.32.0
3
+ Version: 1.33.0
4
4
  Summary: Ophyd devices and other utils that could be used across DLS beamlines
5
5
  Author-email: Dominic Oram <dominic.oram@diamond.ac.uk>
6
6
  License: Apache License
@@ -21,6 +21,17 @@ should think about where to place them in the following order:
21
21
 
22
22
  This is in an effort to avoid duplication across facilities/beamlines.
23
23
 
24
+ Device Best Practices
25
+ ----------------------------
26
+
27
+ Ophyd-async directory contains a flowchart_ for a simplified decision tree about what interfaces
28
+ should a given device implement. In addition to this the following guidelines are strongly recommended:
29
+
30
+ #. Devices should contain only the PV suffixes that are generic for any instance of the device. See `PV Suffixes`_
31
+ #. Anything in a device that is expected to be set externally should be a signal. See `Use of signals`_
32
+ #. Devices should not hold state, when they are read they should read the hardware. See `Holding State`_
33
+
34
+
24
35
  PV Suffixes
25
36
  -----------
26
37
 
@@ -86,16 +97,78 @@ Instead you should make a soft signal:
86
97
 
87
98
  class MyDevice(Device):
88
99
  def __init__(self):
89
- self.param = create_soft_signal(str, "", self.name)
100
+ self.param = soft_signal_rw(str)
90
101
 
91
102
  my_device = MyDevice()
92
103
  def my_plan():
93
104
  yield from bps.mv(my_device.param, "new_value")
94
105
 
95
- Ophyd Devices best practices
96
- ----------------------------
97
106
 
98
- Ophyd-async directory contains a flowchart_ for a simplified decision tree about what interfaces
99
- should a given device implement.
107
+ Holding State
108
+ -------------
109
+
110
+ Devices should avoid holding state as much as possible. Ophyd devices are mostly trying to reflect the state of hardware and so when the device is read that hardware should be read.
111
+
112
+ If the device holds the state itself it is likely to not reflect the real hardware if:
113
+ * The device has just been initialised
114
+ * The hardware has changed independently e.g. via EPICS directly
115
+ * The hardware has failed to do what the device expected
116
+
117
+ For example, if I have a device that I would like to treat as moving in/out based on an underlying axis then it would be incorrect to implement it like this:
118
+
119
+ .. code-block:: python
120
+
121
+ class InOut(Enum):
122
+ IN = 0
123
+ OUT = 0
124
+
125
+ class MyDevice(Device):
126
+ def __init__(self):
127
+ self.underlying_motor = Motor("MOTOR")
128
+ with self.add_children_as_readables():
129
+ self.in_out, self._in_out_setter = soft_signal_r_and_setter(InOut)
130
+
131
+
132
+ @AsyncStatus.wrap
133
+ async def set(self, value: InOut):
134
+ if value == InOut.IN:
135
+ await self.underlying_motor.set(100)
136
+ else:
137
+ await self.underlying_motor.set(0)
138
+ self._in_out_setter(value)
139
+
140
+ While this may appear to work fine during normal operation the state of in_out is only ever updated if the ophyd device is set. It is incorrect to assume that underlying_motor only changes
141
+ based on this and so this has the issues listed above. Instead you should make sure to update in_out whenever the device is read e.g.
142
+
143
+ .. code-block:: python
144
+
145
+ class InOut(Enum):
146
+ IN = 0
147
+ OUT = 0
148
+
149
+ class MyDevice(Device):
150
+ def __init__(self):
151
+ self.underlying_motor = Motor("MOTOR")
152
+ with self.add_children_as_readables():
153
+ self.in_out = create_hardware_backed_soft_signal(InOut, self._get_in_out_from_hardware)
154
+
155
+ async def _get_in_out_from_hardware(self):
156
+ current_position = await self.underlying_motor.get_value()
157
+ if isclose(current_position, 0):
158
+ return InOut.IN
159
+ elif isclose(current_position, 100):
160
+ return InOut.OUT
161
+ else:
162
+ raise ValueError()
163
+
164
+
165
+ @AsyncStatus.wrap
166
+ async def set(self, value: InOut):
167
+ if value == InOut.IN:
168
+ await self.underlying_motor.set(100)
169
+ else:
170
+ await self.underlying_motor.set(0)
171
+
172
+ This will be simplified by https://github.com/bluesky/ophyd-async/issues/525
100
173
 
101
174
  .. _flowchart: https://blueskyproject.io/ophyd-async/main/how-to/choose-interfaces-for-devices.html
@@ -6,6 +6,6 @@ Fixes #ISSUE
6
6
 
7
7
  ### Checks for reviewer
8
8
  - [ ] Would the PR title make sense to a scientist on a set of release notes
9
- - [ ] If a new device has been added does it follow the [standards](https://github.com/DiamondLightSource/dodal/wiki/Device-Standards)
9
+ - [ ] If a new device has been added does it follow the [standards](https://diamondlightsource.github.io/dodal/main/reference/device-standards.html)
10
10
  - [ ] If changing the API for a pre-existing device, ensure that any beamlines using this device have updated their Bluesky plans accordingly
11
11
  - [ ] Have the connection tests for the relevant beamline(s) been run via `dodal connect ${BEAMLINE}`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dls-dodal
3
- Version: 1.32.0
3
+ Version: 1.33.0
4
4
  Summary: Ophyd devices and other utils that could be used across DLS beamlines
5
5
  Author-email: Dominic Oram <dominic.oram@diamond.ac.uk>
6
6
  License: Apache License
@@ -82,6 +82,7 @@ src/dodal/beamline_specific_utils/__init__.py
82
82
  src/dodal/beamline_specific_utils/i03.py
83
83
  src/dodal/beamlines/README.md
84
84
  src/dodal/beamlines/__init__.py
85
+ src/dodal/beamlines/b01_1.py
85
86
  src/dodal/beamlines/i03.py
86
87
  src/dodal/beamlines/i04.py
87
88
  src/dodal/beamlines/i04_1.py
@@ -97,6 +98,7 @@ src/dodal/beamlines/training_rig.py
97
98
  src/dodal/common/__init__.py
98
99
  src/dodal/common/coordination.py
99
100
  src/dodal/common/maths.py
101
+ src/dodal/common/signal_utils.py
100
102
  src/dodal/common/types.py
101
103
  src/dodal/common/udc_directory_provider.py
102
104
  src/dodal/common/visit.py
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.32.0'
16
- __version_tuple__ = version_tuple = (1, 32, 0)
15
+ __version__ = version = '1.33.0'
16
+ __version_tuple__ = version_tuple = (1, 33, 0)
@@ -0,0 +1,77 @@
1
+ from pathlib import Path
2
+
3
+ from ophyd_async.epics.adaravis import AravisDetector
4
+ from ophyd_async.fastcs.panda import HDFPanda
5
+
6
+ from dodal.common.beamlines.beamline_utils import (
7
+ device_instantiation,
8
+ get_path_provider,
9
+ set_path_provider,
10
+ )
11
+ from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
12
+ from dodal.common.visit import LocalDirectoryServiceClient, StaticVisitPathProvider
13
+ from dodal.devices.synchrotron import Synchrotron
14
+ from dodal.log import set_beamline as set_log_beamline
15
+
16
+ BL = "c01"
17
+ set_log_beamline(BL)
18
+ set_utils_beamline(BL)
19
+
20
+ set_path_provider(
21
+ StaticVisitPathProvider(
22
+ BL,
23
+ Path("/dls/b01-1/data/"),
24
+ client=LocalDirectoryServiceClient(),
25
+ )
26
+ )
27
+
28
+ """
29
+ NOTE: Due to ArgoCD and the k8s cluster configuration those PVs are not available remotely.
30
+ You need to be on the beamline-local network to access them.
31
+ The simplest way to do this is to `ssh b01-1-ws001` and run `dodal connect b01_1` from there.
32
+ remember about the underscore in the beamline name.
33
+
34
+ See the IOC status here:
35
+ https://argocd.diamond.ac.uk/applications?showFavorites=false&proj=&sync=&autoSync=&health=&namespace=&cluster=&labels=
36
+ """
37
+
38
+
39
+ def panda(
40
+ wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
41
+ ) -> HDFPanda:
42
+ return device_instantiation(
43
+ device_factory=HDFPanda,
44
+ name="panda",
45
+ prefix="-EA-PANDA-01:",
46
+ wait=wait_for_connection,
47
+ fake=fake_with_ophyd_sim,
48
+ path_provider=get_path_provider(),
49
+ )
50
+
51
+
52
+ def synchrotron(
53
+ wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
54
+ ) -> Synchrotron:
55
+ return device_instantiation(
56
+ Synchrotron,
57
+ "synchrotron",
58
+ "",
59
+ wait_for_connection,
60
+ fake_with_ophyd_sim,
61
+ bl_prefix=False,
62
+ )
63
+
64
+
65
+ def manta(
66
+ wait_for_connection: bool = True, fake_with_ophyd_sim: bool = False
67
+ ) -> AravisDetector:
68
+ return device_instantiation(
69
+ AravisDetector,
70
+ "manta",
71
+ "-DI-DCAM-02:",
72
+ wait_for_connection,
73
+ fake_with_ophyd_sim,
74
+ path_provider=get_path_provider(),
75
+ drv_suffix="CAM:",
76
+ hdf_suffix="HDF5:",
77
+ )
@@ -0,0 +1,53 @@
1
+ from collections.abc import Callable, Coroutine
2
+ from typing import Any, TypeVar
3
+
4
+ from bluesky.protocols import Reading
5
+ from ophyd_async.core import SignalR, SoftSignalBackend
6
+ from ophyd_async.core._soft_signal_backend import SignalMetadata
7
+
8
+ T = TypeVar("T")
9
+
10
+
11
+ class HarwareBackedSoftSignalBackend(SoftSignalBackend[T]):
12
+ def __init__(
13
+ self,
14
+ get_from_hardware_func: Callable[[], Coroutine[Any, Any, T]],
15
+ *args,
16
+ **kwargs,
17
+ ) -> None:
18
+ self.get_from_hardware_func = get_from_hardware_func
19
+ super().__init__(*args, **kwargs)
20
+
21
+ async def _update_value(self):
22
+ new_value = await self.get_from_hardware_func()
23
+ await self.put(new_value)
24
+
25
+ async def get_reading(self) -> Reading:
26
+ await self._update_value()
27
+ return await super().get_reading()
28
+
29
+ async def get_value(self) -> T:
30
+ await self._update_value()
31
+ return await super().get_value()
32
+
33
+
34
+ def create_hardware_backed_soft_signal(
35
+ datatype: type[T],
36
+ get_from_hardware_func: Callable[[], Coroutine[Any, Any, T]],
37
+ units: str | None = None,
38
+ precision: int | None = None,
39
+ ):
40
+ """Creates a soft signal that, when read will call the function passed into
41
+ `get_from_hardware_func` and return this.
42
+
43
+ This will allow you to make soft signals derived from arbitrary hardware signals.
44
+ However, calling subscribe on this signal does not give you a sensible value and
45
+ the signal is currently read only. See https://github.com/bluesky/ophyd-async/issues/525
46
+ for a more full solution.
47
+ """
48
+ metadata = SignalMetadata(units=units, precision=precision)
49
+ return SignalR(
50
+ backend=HarwareBackedSoftSignalBackend(
51
+ get_from_hardware_func, datatype, metadata=metadata
52
+ )
53
+ )
@@ -8,11 +8,11 @@ from ophyd_async.core import (
8
8
  AsyncStatus,
9
9
  HintedSignal,
10
10
  StandardReadable,
11
- soft_signal_rw,
12
11
  )
13
12
  from pydantic import BaseModel, Field
14
13
 
15
14
  from dodal.common.beamlines.beamline_parameters import GDABeamlineParameters
15
+ from dodal.common.signal_utils import create_hardware_backed_soft_signal
16
16
  from dodal.devices.aperture import Aperture
17
17
  from dodal.devices.scatterguard import Scatterguard
18
18
 
@@ -105,7 +105,9 @@ class ApertureScatterguard(StandardReadable, Movable):
105
105
  ) -> None:
106
106
  self.aperture = Aperture(prefix + "-MO-MAPT-01:")
107
107
  self.scatterguard = Scatterguard(prefix + "-MO-SCAT-01:")
108
- self.radius = soft_signal_rw(float, units="µm")
108
+ self.radius = create_hardware_backed_soft_signal(
109
+ float, self._get_current_radius, units="µm"
110
+ )
109
111
  self._loaded_positions = loaded_positions
110
112
  self._tolerances = tolerances
111
113
  self.add_readables(
@@ -119,7 +121,9 @@ class ApertureScatterguard(StandardReadable, Movable):
119
121
  ],
120
122
  )
121
123
  with self.add_children_as_readables(HintedSignal):
122
- self.selected_aperture = soft_signal_rw(ApertureValue)
124
+ self.selected_aperture = create_hardware_backed_soft_signal(
125
+ ApertureValue, self._get_current_aperture_position
126
+ )
123
127
 
124
128
  super().__init__(name)
125
129
 
@@ -136,9 +140,6 @@ class ApertureScatterguard(StandardReadable, Movable):
136
140
  @AsyncStatus.wrap
137
141
  async def _set_raw_unsafe(self, position: AperturePosition):
138
142
  """Accept the risks and move in an unsafe way. Collisions possible."""
139
- if position.radius is not None:
140
- await self.radius.set(position.radius)
141
-
142
143
  aperture_x, aperture_y, aperture_z, scatterguard_x, scatterguard_y = (
143
144
  position.values
144
145
  )
@@ -150,13 +151,8 @@ class ApertureScatterguard(StandardReadable, Movable):
150
151
  self.scatterguard.x.set(scatterguard_x),
151
152
  self.scatterguard.y.set(scatterguard_y),
152
153
  )
153
- try:
154
- value = await self.get_current_aperture_position()
155
- self.selected_aperture.set(value)
156
- except InvalidApertureMove:
157
- self.selected_aperture.set(None) # type: ignore
158
154
 
159
- async def get_current_aperture_position(self) -> ApertureValue:
155
+ async def _get_current_aperture_position(self) -> ApertureValue:
160
156
  """
161
157
  Returns the current aperture position using readback values
162
158
  for SMALL, MEDIUM, LARGE. ROBOT_LOAD position defined when
@@ -176,6 +172,10 @@ class ApertureScatterguard(StandardReadable, Movable):
176
172
 
177
173
  raise InvalidApertureMove("Current aperture/scatterguard state unrecognised")
178
174
 
175
+ async def _get_current_radius(self) -> float | None:
176
+ current_value = await self._get_current_aperture_position()
177
+ return self._loaded_positions[current_value].radius
178
+
179
179
  async def _safe_move_within_datacollection_range(
180
180
  self, position: AperturePosition, value: ApertureValue
181
181
  ):
@@ -203,8 +203,6 @@ class ApertureScatterguard(StandardReadable, Movable):
203
203
  )
204
204
 
205
205
  current_ap_y = await self.aperture.y.user_readback.get_value()
206
- if position.radius is not None:
207
- await self.radius.set(position.radius)
208
206
 
209
207
  aperture_x, aperture_y, aperture_z, scatterguard_x, scatterguard_y = (
210
208
  position.values
@@ -231,4 +229,3 @@ class ApertureScatterguard(StandardReadable, Movable):
231
229
  self.scatterguard.x.set(scatterguard_x),
232
230
  self.scatterguard.y.set(scatterguard_y),
233
231
  )
234
- await self.selected_aperture.set(value)
@@ -12,7 +12,6 @@ from ophyd import (
12
12
  OverlayPlugin,
13
13
  ProcessPlugin,
14
14
  ROIPlugin,
15
- Signal,
16
15
  StatusBase,
17
16
  )
18
17
 
@@ -35,8 +34,6 @@ class ZoomController(Device):
35
34
 
36
35
  # Level is the string description of the zoom level e.g. "1.0x"
37
36
  level = Component(EpicsSignal, "MP:SELECT", string=True)
38
- # Used by OAV to work out if we're changing the setpoint
39
- _level_sp = Component(Signal)
40
37
 
41
38
  zrst = Component(EpicsSignal, "MP:SELECT.ZRST")
42
39
  onst = Component(EpicsSignal, "MP:SELECT.ONST")
@@ -46,14 +43,6 @@ class ZoomController(Device):
46
43
  fvst = Component(EpicsSignal, "MP:SELECT.FVST")
47
44
  sxst = Component(EpicsSignal, "MP:SELECT.SXST")
48
45
 
49
- def set_flatfield_on_zoom_level_one(self, value):
50
- self.parent: OAV
51
- flat_applied = self.parent.proc.port_name.get()
52
- no_flat_applied = self.parent.cam.port_name.get()
53
- return self.parent.grid_snapshot.input_plugin.set(
54
- flat_applied if value == "1.0x" else no_flat_applied
55
- )
56
-
57
46
  @property
58
47
  def allowed_zoom_levels(self):
59
48
  return [
@@ -67,10 +56,7 @@ class ZoomController(Device):
67
56
  ]
68
57
 
69
58
  def set(self, level_to_set: str) -> StatusBase:
70
- return_status = self._level_sp.set(level_to_set)
71
- return_status &= self.level.set(level_to_set)
72
- return_status &= self.set_flatfield_on_zoom_level_one(level_to_set)
73
- return return_status
59
+ return self.level.set(level_to_set)
74
60
 
75
61
 
76
62
  class OAV(AreaDetector):
@@ -1,8 +1,5 @@
1
- from unittest.mock import MagicMock
2
-
3
1
  import pytest
4
2
  from ophyd.sim import instantiate_fake_device
5
- from ophyd.status import AndStatus, Status
6
3
 
7
4
  from dodal.devices.oav.oav_detector import OAV, OAVConfigParams
8
5
  from dodal.devices.oav.oav_errors import (
@@ -36,32 +33,6 @@ def oav() -> OAV:
36
33
  return oav
37
34
 
38
35
 
39
- @pytest.mark.parametrize(
40
- "zoom, expected_plugin",
41
- [
42
- ("1.0x", "proc"),
43
- ("7.0x", "CAM"),
44
- ],
45
- )
46
- def test_when_zoom_level_changed_then_oav_rewired(zoom, expected_plugin, oav: OAV):
47
- oav.zoom_controller.set(zoom).wait()
48
-
49
- assert oav.grid_snapshot.input_plugin.get() == expected_plugin
50
-
51
-
52
- def test_when_zoom_level_changed_then_status_waits_for_all_plugins_to_be_updated(
53
- oav: OAV,
54
- ):
55
- mjpg_status = Status("mjpg - test_when_zoom_level...")
56
- oav.grid_snapshot.input_plugin.set = MagicMock(return_value=mjpg_status)
57
-
58
- assert isinstance(full_status := oav.zoom_controller.set("1.0x"), AndStatus)
59
- assert mjpg_status in full_status
60
-
61
- mjpg_status.set_finished()
62
- full_status.wait()
63
-
64
-
65
36
  def test_load_microns_per_pixel_entry_not_found(oav: OAV):
66
37
  with pytest.raises(OAVError_ZoomLevelNotFound):
67
38
  oav.parameters.load_microns_per_pixel(0.000001, 0, 0)
@@ -8,6 +8,7 @@ import pytest
8
8
  from bluesky.run_engine import RunEngine
9
9
  from ophyd_async.core import (
10
10
  DeviceCollector,
11
+ callback_on_mock_put,
11
12
  get_mock_put,
12
13
  set_mock_value,
13
14
  )
@@ -115,6 +116,7 @@ async def aperture_in_medium_pos_w_call_log(
115
116
  await ap_sg._set_raw_unsafe(aperture_positions[ApertureValue.MEDIUM])
116
117
 
117
118
  set_mock_value(ap_sg.aperture.medium, 1)
119
+
118
120
  yield ap_sg, call_log
119
121
 
120
122
 
@@ -144,9 +146,6 @@ def _assert_position_in_reading(
144
146
  position: AperturePosition,
145
147
  device_name: str,
146
148
  ):
147
- if position.radius is not None:
148
- assert reading[f"{device_name}-radius"]["value"] == position.radius
149
- assert reading[f"{device_name}-selected_aperture"]["value"] == aperture
150
149
  assert reading[f"{device_name}-aperture-x"]["value"] == position.aperture_x
151
150
  assert reading[f"{device_name}-aperture-y"]["value"] == position.aperture_y
152
151
  assert reading[f"{device_name}-aperture-z"]["value"] == position.aperture_z
@@ -244,19 +243,27 @@ def set_underlying_motors(ap_sg: ApertureScatterguard, position: AperturePositio
244
243
  motor.set(pos)
245
244
 
246
245
 
247
- async def test_aperture_positions_large(ap_sg: ApertureScatterguard):
248
- set_mock_value(ap_sg.aperture.large, 1)
249
- assert await ap_sg.get_current_aperture_position() == ApertureValue.LARGE
250
-
251
-
252
- async def test_aperture_positions_medium(ap_sg: ApertureScatterguard):
253
- set_mock_value(ap_sg.aperture.medium, 1)
254
- assert await ap_sg.get_current_aperture_position() == ApertureValue.MEDIUM
255
-
256
-
257
- async def test_aperture_positions_small(ap_sg: ApertureScatterguard):
258
- set_mock_value(ap_sg.aperture.small, 1)
259
- assert await ap_sg.get_current_aperture_position() == ApertureValue.SMALL
246
+ @pytest.mark.parametrize(
247
+ "read_pv, aperture",
248
+ [
249
+ ("large", ApertureValue.LARGE),
250
+ ("medium", ApertureValue.MEDIUM),
251
+ ("small", ApertureValue.SMALL),
252
+ ],
253
+ )
254
+ async def test_aperture_positions(
255
+ ap_sg: ApertureScatterguard,
256
+ aperture_positions: dict[ApertureValue, AperturePosition],
257
+ read_pv: str,
258
+ aperture: ApertureValue,
259
+ ):
260
+ set_mock_value(getattr(ap_sg.aperture, read_pv), 1)
261
+ reading = await ap_sg.read()
262
+ assert isinstance(reading, dict)
263
+ assert (
264
+ reading[f"{ap_sg.name}-radius"]["value"] == aperture_positions[aperture].radius
265
+ )
266
+ assert reading[f"{ap_sg.name}-selected_aperture"]["value"] == aperture
260
267
 
261
268
 
262
269
  async def test_aperture_positions_robot_load(
@@ -268,7 +275,12 @@ async def test_aperture_positions_robot_load(
268
275
  set_mock_value(ap_sg.aperture.small, 0)
269
276
  robot_load = aperture_positions[ApertureValue.ROBOT_LOAD]
270
277
  await ap_sg.aperture.y.set(robot_load.aperture_y)
271
- assert await ap_sg.get_current_aperture_position() == ApertureValue.ROBOT_LOAD
278
+ reading = await ap_sg.read()
279
+ assert isinstance(reading, dict)
280
+ assert reading[f"{ap_sg.name}-radius"]["value"] == 0.0
281
+ assert (
282
+ reading[f"{ap_sg.name}-selected_aperture"]["value"] == ApertureValue.ROBOT_LOAD
283
+ )
272
284
 
273
285
 
274
286
  async def test_aperture_positions_robot_load_within_tolerance(
@@ -282,7 +294,12 @@ async def test_aperture_positions_robot_load_within_tolerance(
282
294
  set_mock_value(ap_sg.aperture.medium, 0)
283
295
  set_mock_value(ap_sg.aperture.small, 0)
284
296
  await ap_sg.aperture.y.set(robot_load_ap_y + tolerance)
285
- assert await ap_sg.get_current_aperture_position() == ApertureValue.ROBOT_LOAD
297
+ reading = await ap_sg.read()
298
+ assert isinstance(reading, dict)
299
+ assert reading[f"{ap_sg.name}-radius"]["value"] == 0.0
300
+ assert (
301
+ reading[f"{ap_sg.name}-selected_aperture"]["value"] == ApertureValue.ROBOT_LOAD
302
+ )
286
303
 
287
304
 
288
305
  async def test_aperture_positions_robot_load_outside_tolerance(
@@ -297,7 +314,7 @@ async def test_aperture_positions_robot_load_outside_tolerance(
297
314
  set_mock_value(ap_sg.aperture.small, 0)
298
315
  await ap_sg.aperture.y.set(robot_load_ap_y + tolerance)
299
316
  with pytest.raises(InvalidApertureMove):
300
- await ap_sg.get_current_aperture_position()
317
+ await ap_sg.read()
301
318
 
302
319
 
303
320
  async def test_aperture_positions_robot_load_unsafe(
@@ -308,7 +325,7 @@ async def test_aperture_positions_robot_load_unsafe(
308
325
  set_mock_value(ap_sg.aperture.small, 0)
309
326
  await ap_sg.aperture.y.set(50.0)
310
327
  with pytest.raises(InvalidApertureMove):
311
- await ap_sg.get_current_aperture_position()
328
+ await ap_sg.read()
312
329
 
313
330
 
314
331
  @pytest.mark.skip(
@@ -360,6 +377,14 @@ async def test_ap_sg_in_runengine(
360
377
  ap = aperture_in_medium_pos.aperture
361
378
  sg = aperture_in_medium_pos.scatterguard
362
379
  test_loc = aperture_positions[ApertureValue.SMALL]
380
+
381
+ def set_small_readback_pv(value, *args, **kwargs):
382
+ set_mock_value(ap.small, 1)
383
+ set_mock_value(ap.medium, 0)
384
+ set_mock_value(ap.y.user_readback, value)
385
+
386
+ callback_on_mock_put(ap.y.user_setpoint, set_small_readback_pv)
387
+
363
388
  RE(bps.abs_set(aperture_in_medium_pos, ApertureValue.SMALL, wait=True))
364
389
  assert await ap.x.user_readback.get_value() == test_loc.aperture_x
365
390
  assert await ap.y.user_readback.get_value() == test_loc.aperture_y
@@ -2,7 +2,6 @@ from unittest.mock import AsyncMock, MagicMock, call, patch
2
2
 
3
3
  import numpy as np
4
4
  import pytest
5
- from bluesky import plan_stubs as bps
6
5
  from bluesky.run_engine import RunEngine
7
6
  from ophyd.sim import instantiate_fake_device, make_fake_device
8
7
  from ophyd_async.core import set_mock_value
@@ -165,27 +164,6 @@ def test_bottom_right_from_top_left():
165
164
  assert bottom_right[0] == 198 and bottom_right[1] == 263
166
165
 
167
166
 
168
- def test_when_zoom_1_then_flat_field_applied(fake_oav: OAV, RE: RunEngine):
169
- RE(bps.abs_set(fake_oav.zoom_controller, "1.0x"))
170
- assert fake_oav.grid_snapshot.input_plugin.get() == "PROC"
171
-
172
-
173
- def test_when_zoom_not_1_then_flat_field_removed(fake_oav: OAV, RE: RunEngine):
174
- RE(bps.abs_set(fake_oav.zoom_controller, "10.0x"))
175
- assert fake_oav.grid_snapshot.input_plugin.get() == "CAM"
176
-
177
-
178
- def test_when_zoom_is_externally_changed_to_1_then_flat_field_not_changed(
179
- fake_oav: OAV,
180
- ):
181
- """This test is required to ensure that Hyperion doesn't cause unexpected behaviour
182
- e.g. change the flatfield when the zoom level is changed through the synoptic"""
183
- fake_oav.grid_snapshot.input_plugin.sim_put("CAM") # type: ignore
184
-
185
- fake_oav.zoom_controller.level.sim_put("1.0x") # type: ignore
186
- assert fake_oav.grid_snapshot.input_plugin.get() == "CAM"
187
-
188
-
189
167
  def test_get_beam_position_from_zoom_only_called_once_on_multiple_connects(
190
168
  fake_oav: OAV,
191
169
  ):