ophyd-async 0.13.3__tar.gz → 0.13.4__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 (329) hide show
  1. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/PKG-INFO +1 -1
  2. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/_version.py +3 -3
  3. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/__init__.py +2 -1
  4. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_table.py +8 -0
  5. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/_core_logic.py +3 -1
  6. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/pmac/_pmac_io.py +8 -4
  7. ophyd_async-0.13.4/src/ophyd_async/epics/pmac/_pmac_trajectory.py +217 -0
  8. ophyd_async-0.13.4/src/ophyd_async/epics/pmac/_pmac_trajectory_generation.py +692 -0
  9. ophyd_async-0.13.4/src/ophyd_async/epics/pmac/_utils.py +167 -0
  10. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/jungfrau/__init__.py +2 -1
  11. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/jungfrau/_controller.py +29 -11
  12. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/jungfrau/_utils.py +10 -2
  13. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/panda/__init__.py +10 -0
  14. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/panda/_block.py +14 -0
  15. ophyd_async-0.13.4/src/ophyd_async/fastcs/panda/_trigger.py +223 -0
  16. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async.egg-info/PKG-INFO +1 -1
  17. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async.egg-info/SOURCES.txt +3 -0
  18. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_log.py +0 -1
  19. ophyd_async-0.13.4/tests/epics/pmac/conftest.py +34 -0
  20. ophyd_async-0.13.4/tests/epics/pmac/test_pmac_trajectory.py +211 -0
  21. ophyd_async-0.13.3/tests/epics/pmac/test_pmac_utils.py → ophyd_async-0.13.4/tests/epics/pmac/test_pmac_trajectory_generation.py +535 -300
  22. ophyd_async-0.13.4/tests/epics/pmac/test_pmac_utils.py +119 -0
  23. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/jungfrau/test_controller.py +49 -2
  24. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/jungfrau/test_utils.py +4 -2
  25. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/panda/db/panda.db +12 -1
  26. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/panda/test_panda_utils.py +4 -1
  27. ophyd_async-0.13.4/tests/fastcs/panda/test_trigger.py +351 -0
  28. ophyd_async-0.13.3/src/ophyd_async/epics/pmac/_pmac_trajectory.py +0 -114
  29. ophyd_async-0.13.3/src/ophyd_async/epics/pmac/_utils.py +0 -847
  30. ophyd_async-0.13.3/src/ophyd_async/fastcs/panda/_trigger.py +0 -103
  31. ophyd_async-0.13.3/tests/epics/pmac/test_pmac_trajectory.py +0 -170
  32. ophyd_async-0.13.3/tests/fastcs/panda/test_trigger.py +0 -156
  33. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.codecov.yml +0 -0
  34. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.copier-answers.yml +0 -0
  35. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.devcontainer/devcontainer.json +0 -0
  36. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.git-blame-ignore-revs +0 -0
  37. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/CONTRIBUTING.md +0 -0
  38. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  39. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/ISSUE_TEMPLATE/issue.md +0 -0
  40. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
  41. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/actions/install_requirements/action.yml +0 -0
  42. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/codeql/codeql-config.yml +0 -0
  43. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/dependabot.yml +0 -0
  44. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/pages/index.html +0 -0
  45. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/pages/make_switcher.py +0 -0
  46. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/_codeql.yml +0 -0
  47. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/_dist.yml +0 -0
  48. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/_docs.yml +0 -0
  49. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/_import_with_no_extras.yml +0 -0
  50. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/_pypi.yml +0 -0
  51. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/_release.yml +0 -0
  52. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/_system_test.yml +0 -0
  53. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/_test.yml +0 -0
  54. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/_tox.yml +0 -0
  55. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/ci.yml +0 -0
  56. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.github/workflows/periodic.yml +0 -0
  57. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.gitignore +0 -0
  58. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.gitmodules +0 -0
  59. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/.pre-commit-config.yaml +0 -0
  60. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/Dockerfile +0 -0
  61. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/LICENSE +0 -0
  62. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/README.md +0 -0
  63. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/_static/custom.css +0 -0
  64. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/conf.py +0 -0
  65. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  66. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  67. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
  68. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
  69. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
  70. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
  71. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
  72. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0008-signal-types.md +0 -0
  73. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
  74. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0010-docstring-format.md +0 -0
  75. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/0011-buffer-updates-camonitor.md +0 -0
  76. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions/COPYME +0 -0
  77. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/decisions.md +0 -0
  78. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/declarative-vs-procedural.md +0 -0
  79. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/design-goals.md +0 -0
  80. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/device-connection-strategies.md +0 -0
  81. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/devices-signals-backends.md +0 -0
  82. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/fly-scanning.md +0 -0
  83. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/plan-stubs.md +0 -0
  84. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/when-to-extend-movable.md +0 -0
  85. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations/where-device-logic.md +0 -0
  86. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/explanations.md +0 -0
  87. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/genindex.rst +0 -0
  88. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/how-to/choose-right-baseclass.md +0 -0
  89. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/how-to/contribute.md +0 -0
  90. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/how-to/derive-one-signal-from-others.md +0 -0
  91. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/how-to/implement-ad-detector.md +0 -0
  92. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/how-to/interact-with-signals.md +0 -0
  93. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/how-to/put-device-back.md +0 -0
  94. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/how-to/store-and-retrieve.md +0 -0
  95. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/how-to.md +0 -0
  96. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/images/fly_scan_collection_windows_and_frames.svg +0 -0
  97. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/images/ophyd-async-logo.svg +0 -0
  98. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/images/ophyd-favicon.svg +0 -0
  99. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
  100. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/index.md +0 -0
  101. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/reference.md +0 -0
  102. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/tutorials/implementing-detectors.md +0 -0
  103. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/tutorials/implementing-devices.md +0 -0
  104. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/tutorials/installation.md +0 -0
  105. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/tutorials/using-devices.md +0 -0
  106. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/tutorials/writing-tests-for-devices.md +0 -0
  107. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/docs/tutorials.md +0 -0
  108. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/pyproject.toml +0 -0
  109. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/setup.cfg +0 -0
  110. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/__init__.py +0 -0
  111. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/__main__.py +0 -0
  112. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/_docs_parser.py +0 -0
  113. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_derived_signal.py +0 -0
  114. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_derived_signal_backend.py +0 -0
  115. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_detector.py +0 -0
  116. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_device.py +0 -0
  117. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_device_filler.py +0 -0
  118. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_enums.py +0 -0
  119. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_flyer.py +0 -0
  120. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_hdf_dataset.py +0 -0
  121. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_log.py +0 -0
  122. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
  123. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_protocol.py +0 -0
  124. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_providers.py +0 -0
  125. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_readable.py +0 -0
  126. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_settings.py +0 -0
  127. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_signal.py +0 -0
  128. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_signal_backend.py +0 -0
  129. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
  130. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_status.py +0 -0
  131. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_utils.py +0 -0
  132. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/core/_yaml_settings.py +0 -0
  133. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/__init__.py +0 -0
  134. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adandor/__init__.py +0 -0
  135. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adandor/_andor.py +0 -0
  136. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
  137. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
  138. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
  139. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
  140. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
  141. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
  142. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/__init__.py +0 -0
  143. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
  144. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/_core_io.py +0 -0
  145. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/_core_writer.py +0 -0
  146. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/_hdf_writer.py +0 -0
  147. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/_jpeg_writer.py +0 -0
  148. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
  149. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/_tiff_writer.py +0 -0
  150. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adcore/_utils.py +0 -0
  151. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
  152. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
  153. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
  154. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
  155. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
  156. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
  157. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
  158. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
  159. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
  160. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
  161. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
  162. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
  163. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/advimba/__init__.py +0 -0
  164. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
  165. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
  166. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
  167. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/core/__init__.py +0 -0
  168. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/core/_aioca.py +0 -0
  169. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
  170. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/core/_epics_device.py +0 -0
  171. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/core/_p4p.py +0 -0
  172. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
  173. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/core/_signal.py +0 -0
  174. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/core/_util.py +0 -0
  175. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/__init__.py +0 -0
  176. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/__main__.py +0 -0
  177. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/_ioc.py +0 -0
  178. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/_motor.py +0 -0
  179. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
  180. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
  181. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/_stage.py +0 -0
  182. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/motor.db +0 -0
  183. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/point_detector.db +0 -0
  184. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
  185. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/motor.py +0 -0
  186. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/odin/__init__.py +0 -0
  187. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/odin/_odin_io.py +0 -0
  188. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/pmac/__init__.py +0 -0
  189. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/signal.py +0 -0
  190. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/testing/__init__.py +0 -0
  191. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
  192. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/testing/_utils.py +0 -0
  193. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/testing/test_records.db +0 -0
  194. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
  195. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/__init__.py +0 -0
  196. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/core.py +0 -0
  197. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
  198. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/eiger/_eiger.py +0 -0
  199. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
  200. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/eiger/_eiger_io.py +0 -0
  201. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/jungfrau/_jungfrau.py +0 -0
  202. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/jungfrau/_signals.py +0 -0
  203. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
  204. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/panda/_control.py +0 -0
  205. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
  206. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/panda/_table.py +0 -0
  207. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
  208. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/plan_stubs/__init__.py +0 -0
  209. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
  210. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/plan_stubs/_fly.py +0 -0
  211. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
  212. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/plan_stubs/_panda.py +0 -0
  213. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/plan_stubs/_settings.py +0 -0
  214. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/plan_stubs/_utils.py +0 -0
  215. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
  216. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/py.typed +0 -0
  217. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/__init__.py +0 -0
  218. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/__main__.py +0 -0
  219. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/_blob_detector.py +0 -0
  220. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
  221. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/_blob_detector_writer.py +0 -0
  222. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
  223. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
  224. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/_motor.py +0 -0
  225. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/_pattern_generator.py +0 -0
  226. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/_point_detector.py +0 -0
  227. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/sim/_stage.py +0 -0
  228. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/__init__.py +0 -0
  229. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/core/__init__.py +0 -0
  230. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/core/_base_device.py +0 -0
  231. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/core/_converters.py +0 -0
  232. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/core/_signal.py +0 -0
  233. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/core/_tango_readable.py +0 -0
  234. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/core/_tango_transport.py +0 -0
  235. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/core/_utils.py +0 -0
  236. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/demo/__init__.py +0 -0
  237. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/demo/_counter.py +0 -0
  238. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/demo/_detector.py +0 -0
  239. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/demo/_mover.py +0 -0
  240. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
  241. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
  242. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/testing/__init__.py +0 -0
  243. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
  244. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/testing/__init__.py +0 -0
  245. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
  246. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/testing/_assert.py +0 -0
  247. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/testing/_mock_signal_utils.py +0 -0
  248. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/testing/_one_of_everything.py +0 -0
  249. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/testing/_single_derived.py +0 -0
  250. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/testing/_utils.py +0 -0
  251. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
  252. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
  253. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async.egg-info/requires.txt +0 -0
  254. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/src/ophyd_async.egg-info/top_level.txt +0 -0
  255. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/system_tests/conftest.py +0 -0
  256. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/system_tests/epics/adsim/baseline.yaml +0 -0
  257. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/system_tests/epics/adsim/start_iocs.sh +0 -0
  258. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/system_tests/epics/adsim/stop_iocs.sh +0 -0
  259. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/system_tests/epics/adsim/test_adsim_system.py +0 -0
  260. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/system_tests/epics/eiger/README.md +0 -0
  261. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
  262. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/system_tests/epics/eiger/test_eiger_system.py +0 -0
  263. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/conftest.py +0 -0
  264. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_auto_init_devices.py +0 -0
  265. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_detector.py +0 -0
  266. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_device.py +0 -0
  267. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_flyer.py +0 -0
  268. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_mock_signal_backend.py +0 -0
  269. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_multi_derived_signal.py +0 -0
  270. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_observe.py +0 -0
  271. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_protocol.py +0 -0
  272. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_providers.py +0 -0
  273. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_readable.py +0 -0
  274. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_signal.py +0 -0
  275. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_single_derived_signal.py +0 -0
  276. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_soft_signal_backend.py +0 -0
  277. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_status.py +0 -0
  278. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_subset_enum.py +0 -0
  279. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_table.py +0 -0
  280. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_utils.py +0 -0
  281. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/core/test_watchable_async_status.py +0 -0
  282. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adandor/test_andor.py +0 -0
  283. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adaravis/test_aravis.py +0 -0
  284. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adcore/test_cont_acq_detector.py +0 -0
  285. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adcore/test_detectors.py +0 -0
  286. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adcore/test_drivers.py +0 -0
  287. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adcore/test_plugins.py +0 -0
  288. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adcore/test_scans.py +0 -0
  289. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adcore/test_single_trigger.py +0 -0
  290. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adcore/test_writers.py +0 -0
  291. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adkinetix/test_kinetix.py +0 -0
  292. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adpilatus/test_pilatus.py +0 -0
  293. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/adsimdetector/test_sim.py +0 -0
  294. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/advimba/test_vimba.py +0 -0
  295. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/conftest.py +0 -0
  296. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/demo/test_epics_demo.py +0 -0
  297. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/eiger/test_odin_io.py +0 -0
  298. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/pmac/test_pmac_io.py +0 -0
  299. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/pvi/test_pvi.py +0 -0
  300. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/signal/test_common.py +0 -0
  301. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/signal/test_signals.py +0 -0
  302. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/signal/test_yaml_save_ca.yaml +0 -0
  303. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/signal/test_yaml_save_pva.yaml +0 -0
  304. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/test_areadetector_subclass_naming.py +0 -0
  305. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/epics/test_motor.py +0 -0
  306. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/eiger/test_eiger_controller.py +0 -0
  307. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/eiger/test_eiger_detector.py +0 -0
  308. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/jungfrau/__init__.py +0 -0
  309. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/panda/test_hdf_panda.py +0 -0
  310. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/panda/test_panda_connect.py +0 -0
  311. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/panda/test_panda_control.py +0 -0
  312. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/panda/test_seq_table.py +0 -0
  313. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/fastcs/panda/test_writer.py +0 -0
  314. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/plan_stubs/test_ensure_connected.py +0 -0
  315. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/plan_stubs/test_fly.py +0 -0
  316. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/plan_stubs/test_settings.py +0 -0
  317. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/plan_stubs/test_setup.py +0 -0
  318. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/sim/__init__.py +0 -0
  319. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/sim/test_sim_blob_detector.py +0 -0
  320. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/sim/test_sim_motor.py +0 -0
  321. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/tango/conftest.py +0 -0
  322. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/tango/context_subprocess.py +0 -0
  323. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/tango/test_base_device.py +0 -0
  324. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/tango/test_tango_signals.py +0 -0
  325. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/tango/test_tango_transport.py +0 -0
  326. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/test_cli.py +0 -0
  327. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/test_data/test_yaml_config_save.yaml +0 -0
  328. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/test_data/test_yaml_save.yaml +0 -0
  329. {ophyd_async-0.13.3 → ophyd_async-0.13.4}/tests/test_tutorials.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ophyd-async
3
- Version: 0.13.3
3
+ Version: 0.13.4
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
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.13.3'
32
- __version_tuple__ = version_tuple = (0, 13, 3)
31
+ __version__ = version = '0.13.4'
32
+ __version_tuple__ = version_tuple = (0, 13, 4)
33
33
 
34
- __commit_id__ = commit_id = 'gabcdf5983'
34
+ __commit_id__ = commit_id = 'gb42c37bf9'
@@ -78,7 +78,7 @@ from ._signal_backend import (
78
78
  )
79
79
  from ._soft_signal_backend import SoftSignalBackend
80
80
  from ._status import AsyncStatus, WatchableAsyncStatus, completed_status
81
- from ._table import Table
81
+ from ._table import Table, TableSubclass
82
82
  from ._utils import (
83
83
  CALCULATE_TIMEOUT,
84
84
  DEFAULT_TIMEOUT,
@@ -221,4 +221,5 @@ __all__ = [
221
221
  "EnableDisable",
222
222
  "InOut",
223
223
  "OnOff",
224
+ "TableSubclass",
224
225
  ]
@@ -13,6 +13,7 @@ TableSubclass = TypeVar("TableSubclass", bound="Table")
13
13
 
14
14
 
15
15
  def _concat(value1, value2):
16
+ """Concatenate two values, supports both NumPy arrays and generic types."""
16
17
  if isinstance(value1, np.ndarray):
17
18
  return np.concatenate((value1, value2))
18
19
  else:
@@ -20,6 +21,8 @@ def _concat(value1, value2):
20
21
 
21
22
 
22
23
  def _make_default_factory(dtype: np.dtype) -> Callable[[], np.ndarray]:
24
+ """Creates a default factory, returns an empty Numpy array of a specified dtype."""
25
+
23
26
  def numpy_array_default_factory() -> np.ndarray:
24
27
  return np.array([], dtype)
25
28
 
@@ -91,6 +94,11 @@ class Table(ConfinedModel):
91
94
  raise TypeError(f"Cannot use annotation {anno} in a Table")
92
95
  cls.__annotations__[k] = new_anno
93
96
 
97
+ @classmethod
98
+ def empty(cls: type[TableSubclass]) -> TableSubclass:
99
+ """Makes an empty table with zero length columns."""
100
+ return cls() # type: ignore
101
+
94
102
  def __add__(self, right: TableSubclass) -> TableSubclass:
95
103
  """Concatenate the arrays in field values."""
96
104
  cls = type(right)
@@ -34,9 +34,11 @@ class ADBaseController(DetectorController, Generic[ADBaseIOT]):
34
34
  self,
35
35
  driver: ADBaseIOT,
36
36
  good_states: frozenset[ADState] = DEFAULT_GOOD_STATES,
37
+ image_mode: ADImageMode = ADImageMode.MULTIPLE,
37
38
  ) -> None:
38
39
  self.driver: ADBaseIOT = driver
39
40
  self.good_states = good_states
41
+ self.image_mode = image_mode
40
42
  self.frame_timeout = DEFAULT_TIMEOUT
41
43
  self._arm_status: AsyncStatus | None = None
42
44
 
@@ -52,7 +54,7 @@ class ADBaseController(DetectorController, Generic[ADBaseIOT]):
52
54
  )
53
55
  await asyncio.gather(
54
56
  self.driver.num_images.set(trigger_info.total_number_of_exposures),
55
- self.driver.image_mode.set(ADImageMode.MULTIPLE),
57
+ self.driver.image_mode.set(self.image_mode),
56
58
  )
57
59
 
58
60
  async def arm(self):
@@ -4,7 +4,7 @@ import numpy as np
4
4
 
5
5
  from ophyd_async.core import Array1D, Device, DeviceVector, StandardReadable
6
6
  from ophyd_async.epics import motor
7
- from ophyd_async.epics.core import epics_signal_r, epics_signal_rw
7
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw, epics_signal_x
8
8
 
9
9
  CS_LETTERS = "ABCUVWXYZ"
10
10
 
@@ -40,11 +40,15 @@ class PmacTrajectoryIO(StandardReadable):
40
40
  for i, letter in enumerate(CS_LETTERS)
41
41
  }
42
42
  )
43
+ self.total_points = epics_signal_r(int, f"{prefix}TotalPoints_RBV")
43
44
  self.points_to_build = epics_signal_rw(int, prefix + "ProfilePointsToBuild")
44
- self.build_profile = epics_signal_rw(bool, prefix + "ProfileBuild")
45
+ self.build_profile = epics_signal_x(prefix + "ProfileBuild")
46
+ self.append_profile = epics_signal_x(prefix + "ProfileAppend")
47
+ # This should be a SignalX, but because it is a Busy record, must
48
+ # be a SignalRW to be waited on in PmacTrajectoryTriggerLogic.
49
+ # TODO: Change record type to bo from busy (https://github.com/DiamondLightSource/pmac/issues/154)
45
50
  self.execute_profile = epics_signal_rw(bool, prefix + "ProfileExecute")
46
- self.scan_percent = epics_signal_r(float, prefix + "TscanPercent_RBV")
47
- self.abort_profile = epics_signal_rw(bool, prefix + "ProfileAbort")
51
+ self.abort_profile = epics_signal_x(prefix + "ProfileAbort")
48
52
  self.profile_cs_name = epics_signal_rw(str, prefix + "ProfileCsName")
49
53
  self.calculate_velocities = epics_signal_rw(bool, prefix + "ProfileCalcVel")
50
54
 
@@ -0,0 +1,217 @@
1
+ import asyncio
2
+ from dataclasses import dataclass
3
+
4
+ import numpy as np
5
+ from scanspec.core import Path, Slice
6
+ from scanspec.specs import Spec
7
+
8
+ from ophyd_async.core import (
9
+ DEFAULT_TIMEOUT,
10
+ AsyncStatus,
11
+ FlyerController,
12
+ error_if_none,
13
+ observe_value,
14
+ set_and_wait_for_value,
15
+ wait_for_value,
16
+ )
17
+ from ophyd_async.epics.motor import Motor
18
+ from ophyd_async.epics.pmac import PmacIO
19
+ from ophyd_async.epics.pmac._pmac_io import CS_LETTERS
20
+ from ophyd_async.epics.pmac._pmac_trajectory_generation import PVT, Trajectory
21
+ from ophyd_async.epics.pmac._utils import (
22
+ _PmacMotorInfo,
23
+ calculate_ramp_position_and_duration,
24
+ )
25
+
26
+ # PMAC durations are in milliseconds
27
+ # We must convert from scanspec durations (seconds) to milliseconds
28
+ # PMAC motion program multiples durations by 0.001
29
+ # (see https://github.com/DiamondLightSource/pmac/blob/afe81f8bb9179c3a20eff351f30bc6cfd1539ad9/pmacApp/pmc/trajectory_scan_code_ppmac.pmc#L241)
30
+ # Therefore, we must divide scanspec durations by 10e-6
31
+ TICK_S = 0.000001
32
+ SLICE_SIZE = 4000
33
+
34
+
35
+ @dataclass
36
+ class PmacPrepareContext:
37
+ path: Path
38
+ motor_info: _PmacMotorInfo
39
+ ramp_up_time: float
40
+
41
+
42
+ class PmacTrajectoryTriggerLogic(FlyerController):
43
+ def __init__(self, pmac: PmacIO) -> None:
44
+ self.pmac = pmac
45
+ self._next_pvt: PVT | None
46
+ self._loaded: int = 0
47
+ self._trajectory_status: AsyncStatus | None = None
48
+ self._prepare_context: PmacPrepareContext | None = None
49
+
50
+ async def prepare(self, value: Spec[Motor]):
51
+ path = Path(value.calculate())
52
+ slice = path.consume(SLICE_SIZE)
53
+ path_length = len(path)
54
+ motors = slice.axes()
55
+ motor_info = await _PmacMotorInfo.from_motors(self.pmac, motors)
56
+ ramp_up_pos, ramp_up_time = calculate_ramp_position_and_duration(
57
+ slice, motor_info, True
58
+ )
59
+ self._prepare_context = PmacPrepareContext(
60
+ path=path, motor_info=motor_info, ramp_up_time=ramp_up_time
61
+ )
62
+ await asyncio.gather(
63
+ self._build_trajectory(motor_info, slice, path_length, ramp_up_time),
64
+ self._move_to_start(motor_info, ramp_up_pos),
65
+ )
66
+
67
+ async def kickoff(self):
68
+ prepare_context = error_if_none(
69
+ self._prepare_context, "Cannot kickoff. Must call prepare first."
70
+ )
71
+ self._prepare_context = None
72
+ self._trajectory_status = self._execute_trajectory(
73
+ prepare_context.path, prepare_context.motor_info
74
+ )
75
+ # Wait for the ramp up to happen
76
+ await wait_for_value(
77
+ self.pmac.trajectory.total_points,
78
+ lambda v: v >= 1,
79
+ prepare_context.ramp_up_time + DEFAULT_TIMEOUT,
80
+ )
81
+
82
+ async def complete(self):
83
+ trajectory_status = error_if_none(
84
+ self._trajectory_status, "Cannot complete. Must call kickoff first."
85
+ )
86
+ await trajectory_status
87
+ # Reset trajectory status and number of loaded points
88
+ self._trajectory_status = None
89
+ self._loaded = 0
90
+
91
+ async def stop(self):
92
+ await self.pmac.trajectory.abort_profile.trigger()
93
+
94
+ @AsyncStatus.wrap
95
+ async def _execute_trajectory(self, path: Path, motor_info: _PmacMotorInfo):
96
+ execute_status = self.pmac.trajectory.execute_profile.set(
97
+ True, wait=True, timeout=None
98
+ )
99
+ # We consume SLICE_SIZE from self.path and parse a trajectory
100
+ # containing at least 2 * SLICE_SIZE, as a gapless trajectory
101
+ # will contain 2 points per slice frame. If gaps are present,
102
+ # additional points are inserted, overfilling the buffer.
103
+ min_buffer_size = SLICE_SIZE * 2
104
+ async for current_point in observe_value(
105
+ self.pmac.trajectory.total_points,
106
+ done_status=execute_status,
107
+ timeout=DEFAULT_TIMEOUT,
108
+ ):
109
+ # Ensure we maintain a minimum buffer size, if we have more points to append
110
+ if len(path) != 0 and self._loaded - current_point < min_buffer_size:
111
+ # We have less than SLICE_SIZE * 2 points in the buffer, so refill
112
+ next_slice = path.consume(SLICE_SIZE)
113
+ path_length = len(path)
114
+ await self._append_trajectory(next_slice, path_length, motor_info)
115
+
116
+ async def _append_trajectory(
117
+ self, slice: Slice, path_length: int, motor_info: _PmacMotorInfo
118
+ ):
119
+ trajectory = await self._parse_trajectory(slice, path_length, motor_info)
120
+ await self._set_trajectory_arrays(trajectory, motor_info)
121
+ await self.pmac.trajectory.append_profile.trigger()
122
+
123
+ async def _build_trajectory(
124
+ self,
125
+ motor_info: _PmacMotorInfo,
126
+ slice: Slice,
127
+ path_length: int,
128
+ ramp_up_time: float,
129
+ ):
130
+ trajectory = await self._parse_trajectory(
131
+ slice, path_length, motor_info, ramp_up_time
132
+ )
133
+ use_axis = {
134
+ axis + 1: (axis in motor_info.motor_cs_index.values())
135
+ for axis in range(len(CS_LETTERS))
136
+ }
137
+
138
+ coros = [
139
+ self.pmac.trajectory.profile_cs_name.set(motor_info.cs_port),
140
+ self.pmac.trajectory.calculate_velocities.set(False),
141
+ self._set_trajectory_arrays(trajectory, motor_info),
142
+ ] + [
143
+ self.pmac.trajectory.use_axis[number].set(use)
144
+ for number, use in use_axis.items()
145
+ ]
146
+
147
+ await asyncio.gather(*coros)
148
+ await self.pmac.trajectory.build_profile.trigger()
149
+
150
+ async def _parse_trajectory(
151
+ self,
152
+ slice: Slice,
153
+ path_length: int,
154
+ motor_info: _PmacMotorInfo,
155
+ ramp_up_time: float | None = None,
156
+ ) -> Trajectory:
157
+ trajectory, exit_pvt = Trajectory.from_slice(
158
+ slice,
159
+ motor_info,
160
+ None if ramp_up_time else self._next_pvt,
161
+ ramp_up_time=ramp_up_time,
162
+ )
163
+
164
+ if path_length == 0:
165
+ ramp_down_pos, ramp_down_time = calculate_ramp_position_and_duration(
166
+ slice, motor_info, False
167
+ )
168
+ trajectory = trajectory.with_ramp_down(
169
+ exit_pvt, ramp_down_pos, ramp_down_time, 0
170
+ )
171
+ self._next_pvt = exit_pvt
172
+ self._loaded += len(trajectory)
173
+
174
+ return trajectory
175
+
176
+ async def _set_trajectory_arrays(
177
+ self, trajectory: Trajectory, motor_info: _PmacMotorInfo
178
+ ):
179
+ coros = []
180
+ for motor, number in motor_info.motor_cs_index.items():
181
+ coros.append(
182
+ self.pmac.trajectory.positions[number + 1].set(
183
+ trajectory.positions[motor]
184
+ )
185
+ )
186
+ coros.append(
187
+ self.pmac.trajectory.velocities[number + 1].set(
188
+ trajectory.velocities[motor]
189
+ )
190
+ )
191
+ coros.extend(
192
+ [
193
+ self.pmac.trajectory.time_array.set(trajectory.durations / TICK_S),
194
+ self.pmac.trajectory.user_array.set(trajectory.user_programs),
195
+ self.pmac.trajectory.points_to_build.set(len(trajectory.durations)),
196
+ ]
197
+ )
198
+ await asyncio.gather(*coros)
199
+
200
+ async def _move_to_start(
201
+ self, motor_info: _PmacMotorInfo, ramp_up_position: dict[Motor, np.float64]
202
+ ):
203
+ coord = self.pmac.coord[motor_info.cs_number]
204
+ coros = []
205
+ await coord.defer_moves.set(True)
206
+ for motor, position in ramp_up_position.items():
207
+ coros.append(
208
+ set_and_wait_for_value(
209
+ coord.cs_axis_setpoint[motor_info.motor_cs_index[motor] + 1],
210
+ position,
211
+ set_timeout=10,
212
+ wait_for_set_completion=False,
213
+ )
214
+ )
215
+ statuses = await asyncio.gather(*coros)
216
+ await coord.defer_moves.set(False)
217
+ await asyncio.gather(*statuses)