ophyd-async 0.11__tar.gz → 0.12.1__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 (304) hide show
  1. {ophyd_async-0.11 → ophyd_async-0.12.1}/PKG-INFO +3 -2
  2. {ophyd_async-0.11 → ophyd_async-0.12.1}/README.md +1 -1
  3. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/conf.py +1 -0
  4. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0007-subpackage-structure.md +1 -1
  5. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/design-goals.md +5 -5
  6. ophyd_async-0.12.1/docs/explanations/fly-scanning.md +97 -0
  7. ophyd_async-0.12.1/docs/explanations/plan-stubs.md +336 -0
  8. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/choose-right-baseclass.md +2 -2
  9. {ophyd_async-0.11 → ophyd_async-0.12.1}/pyproject.toml +2 -1
  10. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/_version.py +2 -2
  11. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_flyer.py +4 -4
  12. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_hdf_dataset.py +2 -15
  13. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_providers.py +69 -11
  14. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_signal.py +15 -2
  15. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_soft_signal_backend.py +1 -1
  16. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/__init__.py +2 -0
  17. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_core_io.py +15 -5
  18. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_core_writer.py +34 -26
  19. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_hdf_writer.py +4 -3
  20. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_jpeg_writer.py +3 -3
  21. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_tiff_writer.py +3 -3
  22. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_aioca.py +3 -0
  23. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_signal.py +8 -3
  24. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/motor.py +2 -2
  25. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/_utils.py +1 -1
  26. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_trigger.py +4 -4
  27. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_writer.py +1 -3
  28. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/__init__.py +0 -8
  29. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/__main__.py +2 -1
  30. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_blob_detector_writer.py +4 -5
  31. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_pattern_generator.py +3 -3
  32. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/__init__.py +2 -0
  33. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_assert.py +34 -6
  34. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/PKG-INFO +3 -2
  35. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/SOURCES.txt +3 -2
  36. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/requires.txt +1 -0
  37. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/conftest.py +4 -2
  38. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_device.py +2 -2
  39. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_observe.py +8 -8
  40. ophyd_async-0.12.1/tests/core/test_providers.py +177 -0
  41. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_signal.py +118 -139
  42. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_single_derived_signal.py +4 -3
  43. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_detectors.py +106 -7
  44. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_scans.py +1 -1
  45. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_writers.py +2 -2
  46. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adsimdetector/test_sim.py +10 -7
  47. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/conftest.py +12 -4
  48. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/signal/test_signals.py +67 -24
  49. ophyd_async-0.12.1/tests/fastcs/panda/test_hdf_panda.py +49 -0
  50. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_panda_connect.py +5 -4
  51. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_writer.py +4 -2
  52. ophyd_async-0.12.1/tests/plan_stubs/test_fly.py +0 -0
  53. ophyd_async-0.12.1/tests/sim/__init__.py +0 -0
  54. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/sim/test_sim_blob_detector.py +1 -1
  55. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/test_tango_signals.py +8 -3
  56. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/test_tutorials.py +7 -0
  57. ophyd_async-0.11/docs/explanations/flyscanning.md +0 -84
  58. ophyd_async-0.11/src/ophyd_async/plan_stubs/_fly.py +0 -204
  59. ophyd_async-0.11/tests/core/test_providers.py +0 -85
  60. ophyd_async-0.11/tests/fastcs/panda/test_hdf_panda.py +0 -166
  61. ophyd_async-0.11/tests/plan_stubs/test_fly.py +0 -436
  62. {ophyd_async-0.11 → ophyd_async-0.12.1}/.codecov.yml +0 -0
  63. {ophyd_async-0.11 → ophyd_async-0.12.1}/.copier-answers.yml +0 -0
  64. {ophyd_async-0.11 → ophyd_async-0.12.1}/.devcontainer/devcontainer.json +0 -0
  65. {ophyd_async-0.11 → ophyd_async-0.12.1}/.git-blame-ignore-revs +0 -0
  66. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/CONTRIBUTING.md +0 -0
  67. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  68. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
  69. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
  70. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/actions/install_requirements/action.yml +0 -0
  71. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/codeql/codeql-config.yml +0 -0
  72. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/dependabot.yml +0 -0
  73. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/pages/index.html +0 -0
  74. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/pages/make_switcher.py +0 -0
  75. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_check.yml +0 -0
  76. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_codeql.yml +0 -0
  77. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_dist.yml +0 -0
  78. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_docs.yml +0 -0
  79. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_import_with_no_extras.yml +0 -0
  80. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_pypi.yml +0 -0
  81. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_release.yml +0 -0
  82. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_test.yml +0 -0
  83. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_tox.yml +0 -0
  84. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/ci.yml +0 -0
  85. {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/periodic.yml +0 -0
  86. {ophyd_async-0.11 → ophyd_async-0.12.1}/.gitignore +0 -0
  87. {ophyd_async-0.11 → ophyd_async-0.12.1}/.pre-commit-config.yaml +0 -0
  88. {ophyd_async-0.11 → ophyd_async-0.12.1}/Dockerfile +0 -0
  89. {ophyd_async-0.11 → ophyd_async-0.12.1}/LICENSE +0 -0
  90. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/_static/custom.css +0 -0
  91. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  92. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  93. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
  94. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
  95. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
  96. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
  97. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0008-signal-types.md +0 -0
  98. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
  99. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0010-docstring-format.md +0 -0
  100. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/COPYME +0 -0
  101. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions.md +0 -0
  102. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/declarative-vs-procedural.md +0 -0
  103. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/device-connection-strategies.md +0 -0
  104. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/devices-signals-backends.md +0 -0
  105. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/where-device-logic.md +0 -0
  106. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations.md +0 -0
  107. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/genindex.rst +0 -0
  108. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/contribute.md +0 -0
  109. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/derive-one-signal-from-others.md +0 -0
  110. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/implement-ad-detector.md +0 -0
  111. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/interact-with-signals.md +0 -0
  112. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/put-device-back.md +0 -0
  113. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/store-and-retrieve.md +0 -0
  114. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to.md +0 -0
  115. /ophyd_async-0.11/docs/images/flyscan_collection_windows_and_frames.svg → /ophyd_async-0.12.1/docs/images/fly_scan_collection_windows_and_frames.svg +0 -0
  116. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/images/ophyd-async-logo.svg +0 -0
  117. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/images/ophyd-favicon.svg +0 -0
  118. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
  119. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/index.md +0 -0
  120. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/reference.md +0 -0
  121. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/implementing-detectors.md +0 -0
  122. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/implementing-devices.md +0 -0
  123. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/installation.md +0 -0
  124. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/using-devices.md +0 -0
  125. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/writing-tests-for-devices.md +0 -0
  126. {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials.md +0 -0
  127. {ophyd_async-0.11 → ophyd_async-0.12.1}/setup.cfg +0 -0
  128. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/__init__.py +0 -0
  129. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/__main__.py +0 -0
  130. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/_docs_parser.py +0 -0
  131. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/__init__.py +0 -0
  132. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_derived_signal.py +0 -0
  133. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_derived_signal_backend.py +0 -0
  134. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_detector.py +0 -0
  135. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_device.py +0 -0
  136. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_device_filler.py +0 -0
  137. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_log.py +0 -0
  138. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
  139. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_protocol.py +0 -0
  140. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_readable.py +0 -0
  141. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_settings.py +0 -0
  142. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_signal_backend.py +0 -0
  143. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_status.py +0 -0
  144. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_table.py +0 -0
  145. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_utils.py +0 -0
  146. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_yaml_settings.py +0 -0
  147. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/__init__.py +0 -0
  148. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adandor/__init__.py +0 -0
  149. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adandor/_andor.py +0 -0
  150. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
  151. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
  152. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
  153. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
  154. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
  155. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
  156. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
  157. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_core_logic.py +0 -0
  158. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
  159. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_utils.py +0 -0
  160. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
  161. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
  162. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
  163. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
  164. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
  165. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
  166. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
  167. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
  168. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
  169. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
  170. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
  171. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
  172. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/advimba/__init__.py +0 -0
  173. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
  174. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
  175. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
  176. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/__init__.py +0 -0
  177. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
  178. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_epics_device.py +0 -0
  179. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_p4p.py +0 -0
  180. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
  181. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_util.py +0 -0
  182. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/__init__.py +0 -0
  183. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/__main__.py +0 -0
  184. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_ioc.py +0 -0
  185. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_motor.py +0 -0
  186. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
  187. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
  188. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_stage.py +0 -0
  189. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/motor.db +0 -0
  190. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/point_detector.db +0 -0
  191. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
  192. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/eiger/__init__.py +0 -0
  193. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/eiger/_odin_io.py +0 -0
  194. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/pmac/__init__.py +0 -0
  195. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/pmac/_pmac_io.py +0 -0
  196. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/signal.py +0 -0
  197. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/__init__.py +0 -0
  198. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
  199. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/test_records.db +0 -0
  200. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
  201. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/__init__.py +0 -0
  202. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/core.py +0 -0
  203. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
  204. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/eiger/_eiger.py +0 -0
  205. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
  206. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/eiger/_eiger_io.py +0 -0
  207. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
  208. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
  209. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_block.py +0 -0
  210. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_control.py +0 -0
  211. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
  212. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_table.py +0 -0
  213. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
  214. /ophyd_async-0.11/src/ophyd_async/py.typed → /ophyd_async-0.12.1/src/ophyd_async/plan_stubs/_fly.py +0 -0
  215. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
  216. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_panda.py +0 -0
  217. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_settings.py +0 -0
  218. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_utils.py +0 -0
  219. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
  220. /ophyd_async-0.11/tests/sim/__init__.py → /ophyd_async-0.12.1/src/ophyd_async/py.typed +0 -0
  221. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/__init__.py +0 -0
  222. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_blob_detector.py +0 -0
  223. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
  224. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
  225. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
  226. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_motor.py +0 -0
  227. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_point_detector.py +0 -0
  228. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_stage.py +0 -0
  229. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/__init__.py +0 -0
  230. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/__init__.py +0 -0
  231. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_base_device.py +0 -0
  232. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_converters.py +0 -0
  233. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_signal.py +0 -0
  234. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_tango_readable.py +0 -0
  235. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_tango_transport.py +0 -0
  236. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_utils.py +0 -0
  237. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/__init__.py +0 -0
  238. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_counter.py +0 -0
  239. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_detector.py +0 -0
  240. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_mover.py +0 -0
  241. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
  242. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
  243. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/testing/__init__.py +0 -0
  244. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
  245. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
  246. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_mock_signal_utils.py +0 -0
  247. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_one_of_everything.py +0 -0
  248. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_single_derived.py +0 -0
  249. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_utils.py +0 -0
  250. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
  251. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
  252. {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/top_level.txt +0 -0
  253. {ophyd_async-0.11 → ophyd_async-0.12.1}/system_tests/epics/eiger/README.md +0 -0
  254. {ophyd_async-0.11 → ophyd_async-0.12.1}/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
  255. {ophyd_async-0.11 → ophyd_async-0.12.1}/system_tests/epics/eiger/test_eiger_system.py +0 -0
  256. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_auto_init_devices.py +0 -0
  257. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_detector.py +0 -0
  258. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_flyer.py +0 -0
  259. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_log.py +0 -0
  260. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_mock_signal_backend.py +0 -0
  261. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_multi_derived_signal.py +0 -0
  262. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_protocol.py +0 -0
  263. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_readable.py +0 -0
  264. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_soft_signal_backend.py +0 -0
  265. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_status.py +0 -0
  266. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_subset_enum.py +0 -0
  267. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_table.py +0 -0
  268. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_utils.py +0 -0
  269. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_watchable_async_status.py +0 -0
  270. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adandor/test_andor.py +0 -0
  271. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adaravis/test_aravis.py +0 -0
  272. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_cont_acq_detector.py +0 -0
  273. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_drivers.py +0 -0
  274. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_single_trigger.py +0 -0
  275. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adkinetix/test_kinetix.py +0 -0
  276. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adpilatus/test_pilatus.py +0 -0
  277. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/advimba/test_vimba.py +0 -0
  278. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/demo/test_epics_demo.py +0 -0
  279. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/eiger/test_odin_io.py +0 -0
  280. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/pmac/test_pmac_io.py +0 -0
  281. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/pvi/test_pvi.py +0 -0
  282. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/signal/test_common.py +0 -0
  283. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/signal/test_yaml_save_ca.yaml +0 -0
  284. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/signal/test_yaml_save_pva.yaml +0 -0
  285. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/test_areadetector_subclass_naming.py +0 -0
  286. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/test_motor.py +0 -0
  287. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/eiger/test_eiger_controller.py +0 -0
  288. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/eiger/test_eiger_detector.py +0 -0
  289. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/db/panda.db +0 -0
  290. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_panda_control.py +0 -0
  291. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_panda_utils.py +0 -0
  292. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_seq_table.py +0 -0
  293. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_trigger.py +0 -0
  294. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/plan_stubs/test_ensure_connected.py +0 -0
  295. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/plan_stubs/test_settings.py +0 -0
  296. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/plan_stubs/test_setup.py +0 -0
  297. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/sim/test_sim_motor.py +0 -0
  298. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/conftest.py +0 -0
  299. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/context_subprocess.py +0 -0
  300. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/test_base_device.py +0 -0
  301. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/test_tango_transport.py +0 -0
  302. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/test_cli.py +0 -0
  303. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/test_data/test_yaml_config_save.yaml +0 -0
  304. {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/test_data/test_yaml_save.yaml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ophyd-async
3
- Version: 0.11
3
+ Version: 0.12.1
4
4
  Summary: Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
5
5
  Author-email: Tom Cobb <tom.cobb@diamond.ac.uk>
6
6
  License: BSD 3-Clause License
@@ -48,6 +48,7 @@ Requires-Dist: pyyaml
48
48
  Requires-Dist: colorlog
49
49
  Requires-Dist: pydantic>=2.0
50
50
  Requires-Dist: pydantic-numpy
51
+ Requires-Dist: stamina>=23.1.0
51
52
  Provides-Extra: sim
52
53
  Requires-Dist: h5py; extra == "sim"
53
54
  Provides-Extra: ca
@@ -120,7 +121,7 @@ The main differences from ophyd sync are:
120
121
  - Support for [EPICS][] PVA and [Tango][] as well as the traditional EPICS CA
121
122
  - Better library support for splitting the logic from the hardware interface to avoid complex class heirarchies
122
123
 
123
- It was written with the aim of implementing flyscanning in a generic and extensible way with highly customizable devices like PandABox and the Delta Tau PMAC products. Using async code makes it possible to do the "put 3 PVs in parallel, then get from another PV" logic that is common in flyscanning without the performance and complexity overhead of multiple threads.
124
+ It was written with the aim of implementing fly scanning in a generic and extensible way with highly customizable devices like PandABox and the Delta Tau PMAC products. Using async code makes it possible to do the "put 3 PVs in parallel, then get from another PV" logic that is common in fly scanning without the performance and complexity overhead of multiple threads.
124
125
 
125
126
  Devices from both ophyd sync and ophyd-async can be used in the same RunEngine and even in the same scan. This allows a per-device migration where devices are reimplemented in ophyd-async one by one.
126
127
 
@@ -23,7 +23,7 @@ The main differences from ophyd sync are:
23
23
  - Support for [EPICS][] PVA and [Tango][] as well as the traditional EPICS CA
24
24
  - Better library support for splitting the logic from the hardware interface to avoid complex class heirarchies
25
25
 
26
- It was written with the aim of implementing flyscanning in a generic and extensible way with highly customizable devices like PandABox and the Delta Tau PMAC products. Using async code makes it possible to do the "put 3 PVs in parallel, then get from another PV" logic that is common in flyscanning without the performance and complexity overhead of multiple threads.
26
+ It was written with the aim of implementing fly scanning in a generic and extensible way with highly customizable devices like PandABox and the Delta Tau PMAC products. Using async code makes it possible to do the "put 3 PVs in parallel, then get from another PV" logic that is common in fly scanning without the performance and complexity overhead of multiple threads.
27
27
 
28
28
  Devices from both ophyd sync and ophyd-async can be used in the same RunEngine and even in the same scan. This allows a per-device migration where devices are reimplemented in ophyd-async one by one.
29
29
 
@@ -204,6 +204,7 @@ pygments_style = "sphinx"
204
204
  intersphinx_mapping = {
205
205
  "python": ("https://docs.python.org/3", None),
206
206
  "bluesky": ("https://blueskyproject.io/bluesky/main", None),
207
+ "scanspec": ("https://blueskyproject.io/scanspec/main", None),
207
208
  "numpy": ("https://numpy.org/devdocs/", None),
208
209
  "databroker": ("https://blueskyproject.io/databroker/", None),
209
210
  "event-model": ("https://blueskyproject.io/event-model/main", None),
@@ -14,7 +14,7 @@ Accepted
14
14
  - `ophyd_async.epics`: Epics specific signals and devices
15
15
  - `ophyd_async.tango`: Tango specific signals and devices
16
16
  - `ophyd_async.fastcs`: FastCS (EPICS or Tango) devices like PandA
17
- - `ophyd_async.planstubs`: Plan stubs for various flyscan functionality
17
+ - `ophyd_async.planstubs`: Plan stubs for various fly scan functionality
18
18
  - `ophyd_async.sim`: Simulated devices for demos and tests
19
19
 
20
20
  This ADR proposes a public sub-package structure. The internal private structure should be flat, but can change according to the number of classes in a public package.
@@ -4,7 +4,7 @@ Ophyd-async was designed to be a library for asynchronously interfacing with har
4
4
 
5
5
  ## Asynchronous Signal access
6
6
 
7
- A fundamental part of ophyd-async is [](#asyncio). This allows lightweight and deterministic control of multiple signals, making it possible to do the "put 2 PVs in parallel, then get from another PV" logic that is common in flyscanning without the performance and complexity overhead of multiple threads.
7
+ A fundamental part of ophyd-async is [](#asyncio). This allows lightweight and deterministic control of multiple signals, making it possible to do the "put 2 PVs in parallel, then get from another PV" logic that is common in fly scanning without the performance and complexity overhead of multiple threads.
8
8
 
9
9
  For instance, the threaded version of the above looks something like this:
10
10
  ```python
@@ -49,17 +49,17 @@ As well as the tradition EPICS Channel Access, ophyd-async was written to allow
49
49
 
50
50
  For highly customizable devices like [PandABox](https://quantumdetectors.com/products/pandabox) there are often different pieces of logic that can talk to the same underlying hardware interface. The Devices in ophyd-async are structured so that the logic and interface can be split, and thus can be cleanly organized via composition rather than inheritance.
51
51
 
52
- ## Ease the implementation of flyscanning
52
+ ## Ease the implementation of fly scanning
53
53
 
54
- One of the major drivers for ophyd-async was to ease the implementation of flyscanning. A library of flyscanning helpers is being developed to aid such strategies as:
54
+ One of the major drivers for ophyd-async was to ease the implementation of fly scanning. A library of fly scanning helpers is being developed to aid such strategies as:
55
55
  - Definition of scan paths via [ScanSpec](https://github.com/dls-controls/scanspec)
56
56
  - PVT Trajectory scanning in [Delta Tau motion controllers](https://github.com/dls-controls/pmac)
57
57
  - Position compare and capture using a [PandABox](https://quantumdetectors.com/products/pandabox)
58
58
 
59
- These strategies will be ported from DLS's previous flyscanning software [Malcolm](https://github.com/dls-controls/pymalcolm) and improved to take advantage of the flexibility of bluesky's plan definitions.
59
+ These strategies will be ported from DLS's previous fly scanning software [Malcolm](https://github.com/dls-controls/pymalcolm) and improved to take advantage of the flexibility of bluesky's plan definitions.
60
60
 
61
61
  ```{seealso}
62
- The documents on flyscanning in the [bluesky cookbook](http://blueskyproject.io/bluesky-cookbook/glossary/flyscanning.html)
62
+ [](../explanations/fly-scanning.md)
63
63
  ```
64
64
 
65
65
  ## Parity and interoperativity with ophyd sync
@@ -0,0 +1,97 @@
1
+ # What is the difference between step and fly scanning
2
+
3
+ A scan is defined as actuating some change in zero or more Devices, then collecting data from zero or more detectors to observe that change. Some examples are:
4
+ - moving a motorized stage with a sample on it, and observing its interaction with the X-ray beam on a pair of detectors simultaneously
5
+ - taking a series of time resolved detector frames to observe the degredation of a sample
6
+ - changing the temperature of the sample and observing it with a detector
7
+
8
+ The actuators and detectors in a scan are typically different devices, although many actuators allow the current readback position to be read, so will also be used as a source of data during a scan.
9
+
10
+ We can classify these data collections into two broad categories: step scanning, and fly scanning.
11
+
12
+ * Step scanning: The system performs a sequence of discrete operations: actuate a change, settle, acquire data, repeat. This ensures well-defined data points but may result in longer total acquisition times. Bluesky plans specify this type of measurement through devices' [Movable](#bluesky.protocols.Movable), [Triggerable](#bluesky.protocols.Triggerable) and [Readable](#bluesky.protocols.Readable) protocols.
13
+
14
+ * Fly scanning: Short for "on-the-fly scanning," this method involves kicking off the actuation and detection processes simultaneously, with some form of synchronization that allows the data to be correlated after the scan. This effectively hands over some degree of control to the hardware, with bluesky supervising the progress it is making without being in the loop. The benefits are typically faster scans and smoother coverage of the scanned domain, but it adds complexity in the supervision and synchronization of concurrent processes. Devices capable of this mode implement the [Preparable](#bluesky.protocols.Preparable), [Flyable](#bluesky.protocols.Flyable) and [Collectable](#bluesky.protocols.Collectable) protocols.
15
+
16
+ Filewriting detectors additionally implement [WritesStreamAssets](#bluesky.protocols.WritesStreamAssets) to report the data written to disk during the scan, either at each data point in a step scan, or periodically during a fly scan.
17
+
18
+ ```{seealso}
19
+ [](./plan-stubs.md) for more information on what plan stubs are available that call these protocols
20
+ ```
21
+ ## Scan frames and collection windows
22
+
23
+ Consider some trajectory in 2D space:
24
+
25
+ ![A fly scan trajectory with collection windows containing frames](../images/fly_scan_collection_windows_and_frames.svg)
26
+
27
+ Along the fly scan trajectory we define a discrete sequence of (typically disjoint rather than adjacent) collection windows,
28
+ which are spatial intervals where a coherent block of data is acquired.
29
+ The data collection block is the scan frame, defined as [a vector of lower, mid and upper points in scan space](inv:scanspec#frame_).
30
+ Scan frames map directly to Bluesky [Events](inv:event-model#event), and typically corresponds to a single detector exposure, though they may be composed of multiple detector frames.
31
+
32
+ ## Synchronisation mechanisms
33
+
34
+ A fly scan must define the start of each collection window and a mechanism for the acquisition of frames within those windows.
35
+ Various mechanisms can be used, depending on the available hardware and experimental requirements. Not all combinations of collection window and scan frame triggers provide useful results, so some examples are given below.
36
+
37
+ ### Collection window triggers
38
+
39
+ * Software trigger: The control software signals the start of the next window. For example, a plan kicks off a linear motor move, and starts a free-running detector when it expects the motor to reach a desired constant velocity.
40
+ * Time trigger: A window opens at predefined time intervals (this could be a software or a hardware trigger e.g. from a PandA box).
41
+ * Readback trigger: A hardware trigger sent when a signal from a sensor or encoder value is positively evaluated through some position compare logic.
42
+ * Setpoint trigger: The same control signal sent to some device (e.g. a sample environment controller) also triggering the start of the collection window.
43
+
44
+ ### Scan frame triggers
45
+
46
+ * Internal device trigger: The detector itself generates internal triggers based on its configuration.
47
+ * Time trigger: Hardware triggers sent out at regularly spaced intervals in time.
48
+ * Readback trigger: Same as for collection windows readback triggers.
49
+ * Setpoint trigger: Same as for collection windows setpoint triggers.
50
+
51
+ When a hardware trigger is sent to a detector, it can either be edge triggered (start a frame of a fixed duration on rising edge of trigger) or level triggered (start a frame on rising edge of trigger, stop the frame on falling edge).
52
+
53
+ ## Examples
54
+
55
+ With all this in mind, let us consider typical fly scanning setups given a motor and a detector.
56
+
57
+ ### Software collection window with internal triggers
58
+
59
+ The simplest form of fly scanning uses software synchronisation for opening a collection window, and letting a detector trigger itself internally.
60
+ We effectively tell the devices to "go" at the same time, relying on timestamps to match up the data. The strategy may involve
61
+
62
+ * Calculating the motor run-up distance and move to the start, setting up the detector to take the right number of frames,
63
+ * Starting the motor moving to its end point and waiting for the amount of time it takes to accelerate
64
+ * Starting the detector
65
+ * Waiting until the detector has finished taking frames and the motor has stopped moving
66
+
67
+ This process would produce two data stream: a "monitor" stream of timestamped motor readback positions at the control system update rate;
68
+ and a "primary" stream of detector frames with embedded timestamps when they were received by the control point.
69
+
70
+ ### Software collection window with time triggers
71
+
72
+ If we introduce a PandA box into the system we can trigger the collection window as above, but let the PandA produce time triggers for the detector.
73
+ The strategy is similar:
74
+
75
+ * Calculate motor run-up distance and move to the start, setting the detector into triggered mode and PandA to send the right number of triggers
76
+ * Start the motor moving to its end point and wait for the amount of time it takes to accelerate
77
+ * Start the PandA sending triggers
78
+ * Wait until the PandA, detector and motor have finished
79
+
80
+ The data streams produced are a "monitor" stream of timestamped motor readback positions at the control system update rate;
81
+ and a "primary" stream of PandA captured timestamps and detector frames. If the motor happens to be plugged into the PandA
82
+ then we can dispense with the monitor stream as the motor positions can be captured and produced by the PandA.
83
+
84
+ ### Readback collection window with readback triggers
85
+
86
+ If the motor positions are tracked in the PandA we can use a PCOMP block to trigger both collection windows and frames within.
87
+ This gives the advantage that our detector will trigger at the precise motor positions we expect, but the detector must be able to support level triggering so that it doesn't miss frames if the motor travels faster than expected in a particular frame.
88
+ The strategy and data streams are as in the previous example.
89
+
90
+ ### Readback collection window with time triggers
91
+
92
+ Similar to above, but if the detector is only capable of edge triggering then we need to give it a constant time period so it doesn't miss frames. We do this by sending regularly spaced triggers from a PandA and capturing the positions that the motors were at.
93
+
94
+ ### Setpoint collection window with setpoint triggers
95
+
96
+ It is worth mentioning that the Flyer protocol is also used in hardware-triggered step scanning. Though the collection occurs while the scanned axis is stationary,
97
+ the devices are prepared, kicked off, and completed in a similar way to fly scans.
@@ -0,0 +1,336 @@
1
+ # What plan stubs will do to Devices
2
+
3
+ Plan authors will typically compose [plan stubs](inv:bluesky#stub_plans) together to define the behaviour they expect from their Devices. When the plan is executed, the RunEngine will consume the [`Msg` objects](inv:bluesky:std:doc#msg) `yield from` each plan stub as a series of instructions, many of which call methods on the Device. This document lists some commonly used plan stubs, what Devices will do when they are called, and what order they should be called inside the plan.
4
+
5
+ ```{seealso}
6
+ [](./fly-scanning.md) for more information on the difference between step scans (typically software driven) and flyscans (typically hardware driven)
7
+ ```
8
+
9
+ ## Plan stubs
10
+
11
+ ### [`bps.stage`](#bluesky.plan_stubs.stage) and [`bps.unstage`](#bluesky.plan_stubs.unstage)
12
+
13
+ These are typically the first and last Messages in the plan:
14
+ - `stage` gets the Device into an idle state then makes it ready for data collection:
15
+ - For Devices that read from Signals this will start monitoring those Signals
16
+ - For detectors that write to a resource (e.g. an HDF file) this will indicate that any captured data (e.g. a detector frame) should be stored in a fresh resource
17
+ - `unstage` returns the Device to an idle state:
18
+ - For Devices that read from Signals this will stop monitoring those Signals
19
+ - For detectors that write to a resource this will close that resource
20
+
21
+ It is recommended that the [`bpp.stage_decorator`](#bluesky.preprocessors.stage_decorator) is applied to the plan to yield these Messages as they do the appropriate error handling.
22
+
23
+ ### [`bps.open_run`](#bluesky.plan_stubs.open_run) and [`bps.close_run`](#bluesky.plan_stubs.close_run)
24
+
25
+ These are typically the second and second last Messages in the plan:
26
+ - `open_run` indicates to downstream consumers the start of a data collection
27
+ - For detectors this may be used by specific implentations of `PathProvider` to calculate a new filename to write into
28
+ - `close_run` indicates the end of a data collection
29
+
30
+ It is recommended that the [`bpp.run_decorator`](#bluesky.preprocessors.run_decorator) is applied to the plan to yield these Messages as they do the appropriate error handling. It should be placed after the `stage_decorator`.
31
+
32
+ ### [`bps.prepare`](#bluesky.plan_stubs.prepare)
33
+
34
+ Prepares the device for a `trigger` or `kickoff`, after `stage` and `open_run`:
35
+ - For detectors this will set parameters on the hardware such as exposure time and number of frames. If hardware triggering is requested it will also arm the detector so it is ready to receive those triggers.
36
+ - For motors this will move to the run up position and setup the requested motion velocity or trajectory.
37
+
38
+ ### [`bps.abs_set`](#bluesky.plan_stubs.abs_set) or [`bps.mv`](#bluesky.plan_stubs.mv)
39
+
40
+ Set the device to a target setpoint:
41
+ - For motors, `bps.mv` will move the motor to the desired position, returning when it is complete and erroring if it fails to move. **`bps.abs_set`, however, does not wait for completion by default unless the `wait` option is explicitly set to `True`.**
42
+
43
+ ### [`bps.trigger`](#bluesky.plan_stubs.trigger)
44
+
45
+ Ask the device to trigger a data collection:
46
+ - For detectors this will take a single exposure.
47
+ - For motors this will do nothing as the readback position is always valid.
48
+
49
+ ### [`bps.read`](#bluesky.plan_stubs.read)
50
+
51
+ Collect the data from a device after `trigger`:
52
+ - For detectors that write to a resource this will be a reference to the data written, for other detectors this will be the actual data
53
+ - For motors this is the readback value
54
+
55
+
56
+ ### [`bps.kickoff`](#bluesky.plan_stubs.kickoff)
57
+
58
+ Begin a flyscan:
59
+ - For motors this will start motion and return once the motor has completed its run up and is moving at the desired velocity
60
+ - For detectors prepared for software triggering this will start the acquisition
61
+
62
+ ```{note}
63
+ The plan should ensure that `kickoff` on the motors has finished before `kickoff` on the detectors in started so that software triggered detectors don't start too early. Hardware triggered detectors will already be armed from `prepare`.
64
+ ```
65
+
66
+ ### [`bps.complete`](#bluesky.plan_stubs.collect) and [`bps.collect`](#bluesky.plan_stubs.collect)
67
+
68
+ Wait for flyscanning to be done, collecting data from detectors periodically while that happens:
69
+ - `complete` waits for a flyscan to be done:
70
+ - For motors this will wait until motion including ramp down is complete
71
+ - For detectors this will wait until the requested number of frames has been written
72
+ - `collect` collects the data that has been written so far by a detector during a flyscan.
73
+
74
+ Typically called via [`bps.collect_while_completing`](#bluesky.plan_stubs.collect_while_completing), after `kickoff`.
75
+
76
+ ## Ordering
77
+
78
+ Plan stubs can be mixed together to form arbitrary plans, but there are certain patterns that are common in specific categories of plan. This section lists the ordering of these stubs for step scans (typically software driven), fly scans (typically hardware driven), and scans that nest a fly scan within a step scan.
79
+
80
+ ### Pure step scan
81
+
82
+ After `stage` and `open_run`, `prepare` can be called to set up detectors for a given exposure time if this has been specified in the plan. The inner loop `set`s motors, then `trigger`s and `read`s detectors for each point. Finally `close_run` and `unstage` do the cleanup.
83
+
84
+ ::::{tab-set}
85
+ :sync-group: diagram-code
86
+
87
+ :::{tab-item} Diagram
88
+ :sync: diagram
89
+
90
+ ```{mermaid}
91
+ :config: { "theme": "neutral" }
92
+ :align: center
93
+ flowchart TD
94
+ stage["stage dets, motors"] --> open_run
95
+ open_run --> prepare["(opt) prepare dets"]
96
+ prepare --> set["set motors"]
97
+ set --> trigger["trigger dets"]
98
+ trigger --> read["read dets, motors"]
99
+ read --> set
100
+ read --> close_run
101
+ close_run --> unstage["unstage dets, motors"]
102
+
103
+ ```
104
+ :::
105
+
106
+ :::{tab-item} Code
107
+ :sync: code
108
+
109
+ ```python
110
+ @stage_decorator([detector, motor])
111
+ @run_decorator()
112
+ def pure_step(positions: Sequence[float], exposure_time: float | None) -> MsgGenerator:
113
+ if exposure_time is not None:
114
+ yield from bps.prepare(detector, TriggerInfo(livetime=exposure_time), wait=True)
115
+ for position in positions:
116
+ yield from bps.abs_set(motor, position, wait=True)
117
+ yield from bps.trigger_and_read(detector, motor)
118
+ ```
119
+
120
+ ```{seealso}
121
+ This code is just to aid understanding, normally you would call [](#bluesky.plans.scan) in production
122
+ ```
123
+ :::
124
+
125
+ ::::
126
+
127
+
128
+ (pure-fly-scan)=
129
+ ### Pure fly scan
130
+
131
+ After `stage` and `open_run`, `prepare` sets up detectors for hardware triggering and motors for a trajectory and `kickoff` starts the prepared motion. Then `complete` is called on motors and detectors. While this is in progress the detectors will be `collect`ed repeatedly. Finally `close_run` and `unstage` do the cleanup.
132
+
133
+ ::::{tab-set}
134
+ :sync-group: diagram-code
135
+
136
+ :::{tab-item} Diagram
137
+ :sync: diagram
138
+
139
+ ```{mermaid}
140
+ :config: { "theme": "neutral" }
141
+ :align: center
142
+ flowchart TD
143
+ stage["stage dets, motors"] --> open_run
144
+ open_run --> prepare["prepare dets, motors"]
145
+ prepare --> kickoff["kickoff dets, motors"]
146
+ kickoff --> complete["complete dets, motors"]
147
+ complete --> collect["collect dets"]
148
+ collect --> collect
149
+ collect ----> close_run
150
+ close_run --> unstage["unstage dets, motors"]
151
+ ```
152
+ :::
153
+
154
+ :::{tab-item} Code
155
+ :sync: code
156
+
157
+ ```python
158
+ @stage_decorator([detector, motor])
159
+ @run_decorator()
160
+ def pure_fly(
161
+ start_position: float,
162
+ end_position: float,
163
+ num_exposures: float,
164
+ exposure_time: float,
165
+ readout_time: float,
166
+ ) -> MsgGenerator:
167
+ yield from bps.prepare(
168
+ detector,
169
+ TriggerInfo(
170
+ livetime=exposure_time,
171
+ deadtime=readout_time,
172
+ number_of_events=num_exposures,
173
+ ),
174
+ )
175
+ yield from bps.prepare(
176
+ motor,
177
+ FlyMotorInfo(
178
+ start_position=start_position,
179
+ end_position=end_position,
180
+ time_for_move=(exposure_time + readout_time) * num_exposures,
181
+ ),
182
+ )
183
+ yield from bps.wait()
184
+ yield from bps.kickoff_all(motor)
185
+ yield from bps.kickoff_all(detector)
186
+ yield from bps.collect_while_completing(
187
+ flyers=[motor],
188
+ detectors=[detector],
189
+ flush_period=0.5,
190
+ )
191
+ ```
192
+
193
+ ```{seealso}
194
+ This code is to aid understanding rather than for copying. This will be documented further in <https://github.com/bluesky/ophyd-async/issues/939>
195
+ ```
196
+ :::
197
+
198
+ ::::
199
+
200
+
201
+ ### Fly scan nested within a step scan
202
+
203
+ After `stage` and `open_run` the detectors are `prepare`d for the entire scan. The inner loop `set`s the slow (software) motors to each point, followed by the hardware driven section of the scan. Just like the [](#pure-fly-scan), this consists of `prepare`, then `kickoff`, then `complete` of the fast (hardware) motors, `collect`ing from the detectors repeatedly until they are finished. Finally `close_run` and `unstage` do the cleanup.
204
+
205
+ ::::{tab-set}
206
+ :sync-group: diagram-code
207
+
208
+ :::{tab-item} Diagram
209
+ :sync: diagram
210
+
211
+ ```{mermaid}
212
+ :config: { "theme": "neutral" }
213
+ :align: center
214
+ flowchart TD
215
+ stage["stage dets, motors"] --> open_run
216
+ open_run --> prepare_d["prepare dets"]
217
+ prepare_d --> set["set slow motors"]
218
+ set --> prepare_m["prepare fast motors"]
219
+ prepare_m --> kickoff["kickoff dets, fast motors"]
220
+ kickoff --> complete["complete dets, fast motors"]
221
+ complete --> collect["collect dets"]
222
+ collect --> collect
223
+ collect --> set
224
+ collect ----> close_run
225
+ close_run --> unstage["unstage dets, motors"]
226
+ ```
227
+ :::
228
+
229
+ :::{tab-item} Code
230
+ :sync: code
231
+
232
+ ```python
233
+ @stage_decorator([detector, column_motor, row_motor])
234
+ @run_decorator()
235
+ def fly_inside_step(
236
+ columns: Sequence[float],
237
+ row_start: float,
238
+ row_end: float,
239
+ exposures_per_row: int,
240
+ exposure_time: float,
241
+ readout_time: float,
242
+ ) -> MsgGenerator:
243
+ yield from bps.prepare(
244
+ detector,
245
+ TriggerInfo(
246
+ livetime=exposure_time,
247
+ deadtime=readout_time,
248
+ number_of_events=exposures_per_row * len(columns),
249
+ ),
250
+ )
251
+ for column in columns:
252
+ yield from bps.abs_set(column_motor, column)
253
+ yield from bps.prepare(
254
+ row_motor,
255
+ FlyMotorInfo(
256
+ start_position=row_start,
257
+ end_position=row_end,
258
+ time_for_move=(exposure_time + readout_time) * exposures_per_row,
259
+ ),
260
+ )
261
+ yield from bps.wait()
262
+ yield from bps.kickoff_all(row_motor)
263
+ yield from bps.kickoff_all(detector)
264
+ yield from bps.collect_while_completing(
265
+ flyers=[row_motor],
266
+ detectors=[detector],
267
+ flush_period=0.5,
268
+ )
269
+ ```
270
+
271
+ ```{seealso}
272
+ This code is to aid understanding rather than for copying. This will be documented further in <https://github.com/bluesky/ophyd-async/issues/939>
273
+ ```
274
+ :::
275
+
276
+ ::::
277
+
278
+
279
+
280
+ ## Conclusion
281
+
282
+ The following table summarized what each plan stub does to each class of device:
283
+
284
+
285
+ ```{list-table}
286
+ :header-rows: 1
287
+
288
+ * - Verb
289
+ - Behavior if Motor
290
+ - Behavior if Detector
291
+ - Step / Fly
292
+ * - `stage`
293
+ - Starts monitoring Signals
294
+ - Ensures idle; flags next frame should go in a new resource
295
+ - Both
296
+ * - `unstage`
297
+ - Stops monitoring signals
298
+ - Closes resources
299
+ - Both
300
+ * - `open_run`
301
+ - No effect
302
+ - May compute new resource ID for writing
303
+ - Both
304
+ * - `close_run`
305
+ - No effect
306
+ - Signals the end of data capture
307
+ - Both
308
+ * - `prepare`
309
+ - Moves to run-up position; sets velocity/trajectory
310
+ - Sets acquisition parameters; arms hardware-triggered detectors
311
+ - Both
312
+ * - `abs_set` / `mv`
313
+ - Moves motor to a target position
314
+ - N/A
315
+ - Step
316
+ * - `trigger`
317
+ - N/A
318
+ - Captures a single exposure
319
+ - Step
320
+ * - `read`
321
+ - Reads current position
322
+ - Reads triggered data
323
+ - Step
324
+ * - `kickoff`
325
+ - Starts motion and returns once stable velocity is reached
326
+ - Starts acquisition (software-triggered); hardware-triggered detectors already armed in `prepare`
327
+ - Fly
328
+ * - `complete`
329
+ - Waits for motion (including ramp down) to finish
330
+ - Waits for acquisition to finish (e.g. number of frames)
331
+ - Fly
332
+ * - `collect`
333
+ - N/A
334
+ - Retrieves data already acquired during the scan
335
+ - Fly
336
+ ```
@@ -11,8 +11,8 @@ When writing a new Device there are several base classes to choose from that wil
11
11
  There are some utility baseclasses that allow you to create a Device pre-populated with the right verbs to work in bluesky plans:
12
12
 
13
13
  - [](#StandardReadable) allows you to compose the values of child Signals and Devices together so that you can `read()` the Device during a step scan.
14
- - [](#StandardDetector) allows file-writing detectors to be used within both step and flyscans, reporting periodic references to the data that has been written so far. An instance of a [](#DetectorController) and a [](#DetectorWriter) are required to provide this functionality.
15
- - [](#StandardFlyer) allows actuators (like a motor controller) to be used within a flyscan. Implementing a [](#FlyerController) is required to provide this functionality.
14
+ - [](#StandardDetector) allows file-writing detectors to be used within both step and fly scans, reporting periodic references to the data that has been written so far. An instance of a [](#DetectorController) and a [](#DetectorWriter) are required to provide this functionality.
15
+ - [](#StandardFlyer) allows actuators (like a motor controller) to be used within a fly scan. Implementing a [](#FlyerController) is required to provide this functionality.
16
16
 
17
17
  ## Adding verbs via protocols
18
18
 
@@ -20,6 +20,7 @@ dependencies = [
20
20
  "colorlog",
21
21
  "pydantic>=2.0",
22
22
  "pydantic-numpy",
23
+ "stamina>=23.1.0"
23
24
  ]
24
25
  dynamic = ["version"]
25
26
  license.file = "LICENSE"
@@ -101,7 +102,7 @@ markers = [
101
102
  ]
102
103
  asyncio_mode = "auto"
103
104
  asyncio_default_fixture_loop_scope = "function"
104
- timeout = 0.5
105
+ timeout = 0.75
105
106
  [tool.coverage.run]
106
107
  data_file = "/tmp/ophyd_async.coverage"
107
108
 
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.11'
21
- __version_tuple__ = version_tuple = (0, 11)
20
+ __version__ = version = '0.12.1'
21
+ __version_tuple__ = version_tuple = (0, 12, 1)
@@ -17,15 +17,15 @@ class FlyerController(ABC, Generic[T]):
17
17
 
18
18
  @abstractmethod
19
19
  async def prepare(self, value: T) -> Any:
20
- """Move to the start of the flyscan."""
20
+ """Move to the start of the fly scan."""
21
21
 
22
22
  @abstractmethod
23
23
  async def kickoff(self):
24
- """Start the flyscan."""
24
+ """Start the fly scan."""
25
25
 
26
26
  @abstractmethod
27
27
  async def complete(self):
28
- """Block until the flyscan is done."""
28
+ """Block until the fly scan is done."""
29
29
 
30
30
  @abstractmethod
31
31
  async def stop(self):
@@ -101,7 +101,7 @@ class StandardFlyer(
101
101
  return AsyncStatus(self._prepare(value))
102
102
 
103
103
  async def _prepare(self, value: T) -> None:
104
- # Move to start and setup the flyscan
104
+ # Move to start and setup the fly scan
105
105
  await self._trigger_logic.prepare(value)
106
106
 
107
107
  @AsyncStatus.wrap
@@ -1,6 +1,4 @@
1
1
  from collections.abc import Iterator
2
- from pathlib import Path
3
- from urllib.parse import urlunparse
4
2
 
5
3
  from bluesky.protocols import StreamAsset
6
4
  from event_model import ( # type: ignore
@@ -48,22 +46,11 @@ class HDFDocumentComposer:
48
46
 
49
47
  def __init__(
50
48
  self,
51
- full_file_name: Path,
49
+ file_uri: str,
52
50
  datasets: list[HDFDatasetDescription],
53
- hostname: str = "localhost",
54
51
  ) -> None:
55
52
  self._last_emitted = 0
56
- self._hostname = hostname
57
- uri = urlunparse(
58
- (
59
- "file",
60
- self._hostname,
61
- str(full_file_name.absolute()),
62
- "",
63
- "",
64
- None,
65
- )
66
- )
53
+ uri = file_uri
67
54
  bundler_composer = ComposeStreamResource()
68
55
  self._bundles: list[ComposeStreamResourceBundle] = [
69
56
  bundler_composer(