ophyd-async 0.3rc2__tar.gz → 0.3.1a1__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 (199) hide show
  1. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/PKG-INFO +2 -2
  2. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/README.md +1 -1
  3. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/_version.py +2 -2
  4. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/detector.py +15 -10
  5. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/mock_signal_utils.py +16 -2
  6. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/standard_readable.py +2 -0
  7. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/pilatus_controller.py +18 -5
  8. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/pilatus_driver.py +2 -2
  9. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/pilatus.py +21 -4
  10. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_hdf_panda.py +0 -1
  11. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/plan_stubs/fly.py +4 -0
  12. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/sim_pattern_generator.py +0 -2
  13. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/PKG-INFO +2 -2
  14. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_flyer.py +0 -2
  15. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_standard_readable.py +12 -1
  16. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_controllers.py +26 -16
  17. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_pilatus.py +48 -6
  18. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_scans.py +5 -3
  19. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/plan_stubs/test_fly.py +45 -5
  20. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.codecov.yml +0 -0
  21. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.copier-answers.yml +0 -0
  22. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.devcontainer/devcontainer.json +0 -0
  23. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.git-blame-ignore-revs +0 -0
  24. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/CONTRIBUTING.md +0 -0
  25. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/actions/install_requirements/action.yml +0 -0
  26. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/dependabot.yml +0 -0
  27. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/pages/index.html +0 -0
  28. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/pages/make_switcher.py +0 -0
  29. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/workflows/_check.yml +0 -0
  30. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/workflows/_dist.yml +0 -0
  31. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/workflows/_docs.yml +0 -0
  32. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/workflows/_pypi.yml +0 -0
  33. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/workflows/_release.yml +0 -0
  34. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/workflows/_test.yml +0 -0
  35. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/workflows/_tox.yml +0 -0
  36. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/workflows/ci.yml +0 -0
  37. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.github/workflows/periodic.yml +0 -0
  38. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.gitignore +0 -0
  39. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.mailmap +0 -0
  40. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/.pre-commit-config.yaml +0 -0
  41. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/Dockerfile +0 -0
  42. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/LICENSE +0 -0
  43. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/_templates/README +0 -0
  44. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/_templates/custom-class-template.rst +0 -0
  45. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/_templates/custom-module-template.rst +0 -0
  46. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/conf.py +0 -0
  47. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/examples/epics_demo.py +0 -0
  48. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/examples/foo_detector.py +0 -0
  49. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  50. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  51. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
  52. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
  53. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
  54. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
  55. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/decisions/COPYME +0 -0
  56. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/decisions.md +0 -0
  57. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/design-goals.rst +0 -0
  58. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/event-loop-choice.rst +0 -0
  59. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations/flyscanning.rst +0 -0
  60. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/explanations.md +0 -0
  61. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/genindex.rst +0 -0
  62. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/how-to/choose-interfaces-for-devices.md +0 -0
  63. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/how-to/compound-devices.rst +0 -0
  64. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/how-to/contribute.md +0 -0
  65. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/how-to/make-a-simple-device.rst +0 -0
  66. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/how-to/make-a-standard-detector.rst +0 -0
  67. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/how-to/write-tests-for-devices.rst +0 -0
  68. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/how-to.md +0 -0
  69. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/images/bluesky_ophyd_epics_devices_logo.svg +0 -0
  70. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/images/bluesky_ophyd_logo.svg +0 -0
  71. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/images/ophyd_favicon.svg +0 -0
  72. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/index.md +0 -0
  73. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/reference/api.rst +0 -0
  74. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/reference.md +0 -0
  75. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/tutorials/installation.md +0 -0
  76. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/tutorials/using-existing-devices.rst +0 -0
  77. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/docs/tutorials.md +0 -0
  78. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/pyproject.toml +0 -0
  79. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/setup.cfg +0 -0
  80. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/__init__.py +0 -0
  81. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/__main__.py +0 -0
  82. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/__init__.py +0 -0
  83. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/_providers.py +0 -0
  84. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/async_status.py +0 -0
  85. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/device.py +0 -0
  86. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/device_save_loader.py +0 -0
  87. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/flyer.py +0 -0
  88. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/mock_signal_backend.py +0 -0
  89. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/signal.py +0 -0
  90. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/signal_backend.py +0 -0
  91. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/soft_signal_backend.py +0 -0
  92. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/core/utils.py +0 -0
  93. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/__init__.py +0 -0
  94. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/_backend/__init__.py +0 -0
  95. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/_backend/_aioca.py +0 -0
  96. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/_backend/_p4p.py +0 -0
  97. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/_backend/common.py +0 -0
  98. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/__init__.py +0 -0
  99. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/aravis.py +0 -0
  100. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/__init__.py +0 -0
  101. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/ad_sim_controller.py +0 -0
  102. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/aravis_controller.py +0 -0
  103. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/kinetix_controller.py +0 -0
  104. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/vimba_controller.py +0 -0
  105. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/__init__.py +0 -0
  106. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/ad_base.py +0 -0
  107. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/aravis_driver.py +0 -0
  108. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/kinetix_driver.py +0 -0
  109. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/vimba_driver.py +0 -0
  110. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/kinetix.py +0 -0
  111. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/single_trigger_det.py +0 -0
  112. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/utils.py +0 -0
  113. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/vimba.py +0 -0
  114. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/__init__.py +0 -0
  115. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/_hdfdataset.py +0 -0
  116. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/_hdffile.py +0 -0
  117. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/hdf_writer.py +0 -0
  118. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/nd_file_hdf.py +0 -0
  119. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/nd_plugin.py +0 -0
  120. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/demo/__init__.py +0 -0
  121. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/demo/demo_ad_sim_detector.py +0 -0
  122. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/demo/mover.db +0 -0
  123. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/demo/sensor.db +0 -0
  124. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/motion/__init__.py +0 -0
  125. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/motion/motor.py +0 -0
  126. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/pvi/__init__.py +0 -0
  127. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/pvi/pvi.py +0 -0
  128. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/signal/__init__.py +0 -0
  129. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/signal/_epics_transport.py +0 -0
  130. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/signal/signal.py +0 -0
  131. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/log.py +0 -0
  132. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/__init__.py +0 -0
  133. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_common_blocks.py +0 -0
  134. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_panda_controller.py +0 -0
  135. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_table.py +0 -0
  136. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_trigger.py +0 -0
  137. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_utils.py +0 -0
  138. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/writers/__init__.py +0 -0
  139. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/writers/_hdf_writer.py +0 -0
  140. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/writers/_panda_hdf_file.py +0 -0
  141. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/plan_stubs/__init__.py +0 -0
  142. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/plan_stubs/ensure_connected.py +0 -0
  143. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/protocols.py +0 -0
  144. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/__init__.py +0 -0
  145. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/demo/__init__.py +0 -0
  146. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/demo/sim_motor.py +0 -0
  147. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/pattern_generator.py +0 -0
  148. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/sim_pattern_detector_control.py +0 -0
  149. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/sim_pattern_detector_writer.py +0 -0
  150. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/SOURCES.txt +0 -0
  151. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
  152. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/entry_points.txt +0 -0
  153. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/requires.txt +0 -0
  154. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/top_level.txt +0 -0
  155. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/conftest.py +0 -0
  156. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_async_status.py +0 -0
  157. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_device.py +0 -0
  158. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_device_collector.py +0 -0
  159. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_device_save_loader.py +0 -0
  160. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_mock_signal_backend.py +0 -0
  161. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_signal.py +0 -0
  162. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_soft_signal_backend.py +0 -0
  163. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_utils.py +0 -0
  164. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/core/test_watchable_async_status.py +0 -0
  165. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/_backend/test_common.py +0 -0
  166. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/__init__.py +0 -0
  167. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_aravis.py +0 -0
  168. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_drivers.py +0 -0
  169. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_kinetix.py +0 -0
  170. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_single_trigger_det.py +0 -0
  171. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_utils.py +0 -0
  172. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_vimba.py +0 -0
  173. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_writers.py +0 -0
  174. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/demo/test_demo.py +0 -0
  175. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/demo/test_demo_ad_sim_detector.py +0 -0
  176. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/motion/__init__.py +0 -0
  177. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/motion/test_motor.py +0 -0
  178. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/test_pvi.py +0 -0
  179. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/test_records.db +0 -0
  180. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/epics/test_signals.py +0 -0
  181. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/panda/db/panda.db +0 -0
  182. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/panda/test_hdf_panda.py +0 -0
  183. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/panda/test_panda_connect.py +0 -0
  184. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/panda/test_panda_controller.py +0 -0
  185. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/panda/test_panda_utils.py +0 -0
  186. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/panda/test_table.py +0 -0
  187. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/panda/test_trigger.py +0 -0
  188. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/panda/test_writer.py +0 -0
  189. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/protocols/test_protocols.py +0 -0
  190. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/sim/__init__.py +0 -0
  191. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/sim/conftest.py +0 -0
  192. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/sim/demo/__init__.py +0 -0
  193. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/sim/demo/test_sim_motor.py +0 -0
  194. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/sim/test_pattern_generator.py +0 -0
  195. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/sim/test_sim_detector.py +0 -0
  196. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/sim/test_sim_writer.py +0 -0
  197. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/sim/test_streaming_plan.py +0 -0
  198. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/test_cli.py +0 -0
  199. {ophyd_async-0.3rc2 → ophyd_async-0.3.1a1}/tests/test_log.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ophyd-async
3
- Version: 0.3rc2
3
+ Version: 0.3.1a1
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
@@ -96,7 +96,7 @@ Requires-Dist: types-pyyaml; extra == "dev"
96
96
 
97
97
  # ophyd-async
98
98
 
99
- Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
99
+ Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango.
100
100
 
101
101
  | Source | <https://github.com/bluesky/ophyd-async> |
102
102
  | :-----------: | :-----------------------------------------------: |
@@ -5,7 +5,7 @@
5
5
 
6
6
  # ophyd-async
7
7
 
8
- Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
8
+ Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango.
9
9
 
10
10
  | Source | <https://github.com/bluesky/ophyd-async> |
11
11
  | :-----------: | :-----------------------------------------------: |
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.3rc2'
16
- __version_tuple__ = version_tuple = (0, 3)
15
+ __version__ = version = '0.3.1a1'
16
+ __version_tuple__ = version_tuple = (0, 3, 1)
@@ -63,6 +63,8 @@ class TriggerInfo:
63
63
  deadtime: float
64
64
  #: What is the maximum high time of the triggers
65
65
  livetime: float
66
+ #: What is the maximum timeout on waiting for a frame
67
+ frame_timeout: float | None = None
66
68
 
67
69
 
68
70
  class DetectorControl(ABC):
@@ -162,7 +164,6 @@ class StandardDetector(
162
164
  writer: DetectorWriter,
163
165
  config_sigs: Sequence[AsyncReadable] = (),
164
166
  name: str = "",
165
- writer_timeout: float = DEFAULT_TIMEOUT,
166
167
  ) -> None:
167
168
  """
168
169
  Constructor
@@ -173,16 +174,11 @@ class StandardDetector(
173
174
  config_sigs: Signals to read when describe and read
174
175
  configuration are called. Defaults to ().
175
176
  name: Device name. Defaults to "".
176
- writer_timeout: Timeout for frame writing to start, if the
177
- timeout is reached, ophyd-async assumes the detector
178
- has a problem and raises an error.
179
- Defaults to DEFAULT_TIMEOUT.
180
177
  """
181
178
  self._controller = controller
182
179
  self._writer = writer
183
180
  self._describe: Dict[str, DataKey] = {}
184
181
  self._config_sigs = list(config_sigs)
185
- self._frame_writing_timeout = writer_timeout
186
182
  # For prepare
187
183
  self._arm_status: Optional[AsyncStatus] = None
188
184
  self._trigger_info: Optional[TriggerInfo] = None
@@ -245,17 +241,21 @@ class StandardDetector(
245
241
 
246
242
  @AsyncStatus.wrap
247
243
  async def trigger(self) -> None:
244
+ # set default trigger_info
245
+ self._trigger_info = TriggerInfo(
246
+ num=1, trigger=DetectorTrigger.internal, deadtime=0.0, livetime=0.0
247
+ )
248
248
  # Arm the detector and wait for it to finish.
249
249
  indices_written = await self.writer.get_indices_written()
250
250
  written_status = await self.controller.arm(
251
- num=1,
252
- trigger=DetectorTrigger.internal,
251
+ num=self._trigger_info.num,
252
+ trigger=self._trigger_info.trigger,
253
253
  )
254
254
  await written_status
255
255
  end_observation = indices_written + 1
256
256
 
257
257
  async for index in self.writer.observe_indices_written(
258
- self._frame_writing_timeout
258
+ DEFAULT_TIMEOUT + self._trigger_info.livetime + self._trigger_info.deadtime
259
259
  ):
260
260
  if index >= end_observation:
261
261
  break
@@ -309,7 +309,12 @@ class StandardDetector(
309
309
  assert self._arm_status, "Prepare not run"
310
310
  assert self._trigger_info
311
311
  async for index in self.writer.observe_indices_written(
312
- self._frame_writing_timeout
312
+ self._trigger_info.frame_timeout
313
+ or (
314
+ DEFAULT_TIMEOUT
315
+ + self._trigger_info.livetime
316
+ + self._trigger_info.deadtime
317
+ )
313
318
  ):
314
319
  yield WatcherUpdate(
315
320
  name=self.name,
@@ -79,8 +79,22 @@ class _SetValuesIterator:
79
79
  return next_value
80
80
 
81
81
  def __del__(self):
82
- if self.require_all_consumed and self.index != len(list(self.values)):
83
- raise AssertionError("Not all values have been consumed.")
82
+ if self.require_all_consumed:
83
+ # Values is cast to a list here because the user has supplied
84
+ # require_all_consumed=True, we can therefore assume they
85
+ # supplied a finite list.
86
+ # In the case of require_all_consumed=False, an infinite
87
+ # iterble is permitted
88
+ values = list(self.values)
89
+ if self.index != len(values):
90
+ # Report the values consumed and the values yet to be
91
+ # consumed
92
+ consumed = values[0 : self.index]
93
+ to_be_consumed = values[self.index :]
94
+ raise AssertionError(
95
+ f"{self.signal.name}: {consumed} were consumed "
96
+ f"but {to_be_consumed} were not consumed"
97
+ )
84
98
 
85
99
 
86
100
  def set_mock_values(
@@ -254,6 +254,8 @@ class HintedSignal(HasHints, AsyncReadable):
254
254
 
255
255
  @property
256
256
  def hints(self) -> Hints:
257
+ if self.signal.name == "":
258
+ return {"fields": []}
257
259
  return {"fields": [self.signal.name]}
258
260
 
259
261
  @classmethod
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  from typing import Optional
3
3
 
4
+ from ophyd_async.core import DEFAULT_TIMEOUT, wait_for_value
4
5
  from ophyd_async.core.async_status import AsyncStatus
5
6
  from ophyd_async.core.detector import DetectorControl, DetectorTrigger
6
7
  from ophyd_async.epics.areadetector.drivers.ad_base import (
@@ -23,14 +24,13 @@ class PilatusController(DetectorControl):
23
24
  def __init__(
24
25
  self,
25
26
  driver: PilatusDriver,
27
+ readout_time: float,
26
28
  ) -> None:
27
29
  self._drv = driver
30
+ self._readout_time = readout_time
28
31
 
29
32
  def get_deadtime(self, exposure: float) -> float:
30
- # Cite: https://media.dectris.com/User_Manual-PILATUS2-V1_4.pdf
31
- """The required minimum time difference between ExpPeriod and ExpTime
32
- (readout time) is 2.28 ms"""
33
- return 2.28e-3
33
+ return self._readout_time
34
34
 
35
35
  async def arm(
36
36
  self,
@@ -45,7 +45,20 @@ class PilatusController(DetectorControl):
45
45
  self._drv.num_images.set(999_999 if num == 0 else num),
46
46
  self._drv.image_mode.set(ImageMode.multiple),
47
47
  )
48
- return await start_acquiring_driver_and_ensure_status(self._drv)
48
+
49
+ # Standard arm the detector and wait for the acquire PV to be True
50
+ idle_status = await start_acquiring_driver_and_ensure_status(self._drv)
51
+
52
+ # The pilatus has an additional PV that goes True when the camserver
53
+ # is actually ready. Should wait for that too or we risk dropping
54
+ # a frame
55
+ await wait_for_value(
56
+ self._drv.armed_for_triggers,
57
+ True,
58
+ timeout=DEFAULT_TIMEOUT,
59
+ )
60
+
61
+ return idle_status
49
62
 
50
63
  @classmethod
51
64
  def _get_trigger_mode(cls, trigger: DetectorTrigger) -> PilatusTriggerMode:
@@ -1,7 +1,6 @@
1
1
  from enum import Enum
2
2
 
3
- from ophyd_async.epics.signal.signal import epics_signal_rw_rbv
4
-
3
+ from ...signal import epics_signal_r, epics_signal_rw_rbv
5
4
  from .ad_base import ADBase
6
5
 
7
6
 
@@ -18,4 +17,5 @@ class PilatusDriver(ADBase):
18
17
  self.trigger_mode = epics_signal_rw_rbv(
19
18
  PilatusTriggerMode, prefix + "TriggerMode"
20
19
  )
20
+ self.armed_for_triggers = epics_signal_r(bool, prefix + "Armed")
21
21
  super().__init__(prefix, name)
@@ -1,3 +1,5 @@
1
+ from enum import Enum
2
+
1
3
  from bluesky.protocols import Hints
2
4
 
3
5
  from ophyd_async.core import DirectoryProvider
@@ -11,6 +13,20 @@ from ophyd_async.epics.areadetector.writers.hdf_writer import HDFWriter
11
13
  from ophyd_async.epics.areadetector.writers.nd_file_hdf import NDFileHDF
12
14
 
13
15
 
16
+ #: Cite: https://media.dectris.com/User_Manual-PILATUS2-V1_4.pdf
17
+ #: The required minimum time difference between ExpPeriod and ExpTime
18
+ #: (readout time) is 2.28 ms
19
+ #: We provide an option to override for newer Pilatus models
20
+ class PilatusReadoutTime(float, Enum):
21
+ """Pilatus readout time per model in ms"""
22
+
23
+ # Cite: https://media.dectris.com/User_Manual-PILATUS2-V1_4.pdf
24
+ pilatus2 = 2.28e-3
25
+
26
+ # Cite: https://media.dectris.com/user-manual-pilatus3-2020.pdf
27
+ pilatus3 = 0.95e-3
28
+
29
+
14
30
  class PilatusDetector(StandardDetector):
15
31
  """A Pilatus StandardDetector writing HDF files"""
16
32
 
@@ -21,15 +37,16 @@ class PilatusDetector(StandardDetector):
21
37
  self,
22
38
  prefix: str,
23
39
  directory_provider: DirectoryProvider,
24
- drv_suffix="cam1:",
25
- hdf_suffix="HDF1:",
26
- name="",
40
+ readout_time: PilatusReadoutTime = PilatusReadoutTime.pilatus3,
41
+ drv_suffix: str = "cam1:",
42
+ hdf_suffix: str = "HDF1:",
43
+ name: str = "",
27
44
  ):
28
45
  self.drv = PilatusDriver(prefix + drv_suffix)
29
46
  self.hdf = NDFileHDF(prefix + hdf_suffix)
30
47
 
31
48
  super().__init__(
32
- PilatusController(self.drv),
49
+ PilatusController(self.drv, readout_time=readout_time.value),
33
50
  HDFWriter(
34
51
  self.hdf,
35
52
  directory_provider,
@@ -38,7 +38,6 @@ class HDFPanda(CommonPandaBlocks, StandardDetector):
38
38
  writer=writer,
39
39
  config_sigs=config_sigs,
40
40
  name=name,
41
- writer_timeout=DEFAULT_TIMEOUT,
42
41
  )
43
42
 
44
43
  async def connect(
@@ -18,6 +18,7 @@ def prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
18
18
  shutter_time: float,
19
19
  repeats: int = 1,
20
20
  period: float = 0.0,
21
+ frame_timeout: float | None = None,
21
22
  ):
22
23
  """Prepare a hardware triggered flyable and one or more detectors.
23
24
 
@@ -39,6 +40,7 @@ def prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
39
40
  trigger=DetectorTrigger.constant_gate,
40
41
  deadtime=deadtime,
41
42
  livetime=exposure,
43
+ frame_timeout=frame_timeout,
42
44
  )
43
45
  trigger_time = number_of_frames * (exposure + deadtime)
44
46
  pre_delay = max(period - 2 * shutter_time - trigger_time, 0)
@@ -120,6 +122,7 @@ def time_resolved_fly_and_collect_with_static_seq_table(
120
122
  shutter_time: float,
121
123
  repeats: int = 1,
122
124
  period: float = 0.0,
125
+ frame_timeout: float | None = None,
123
126
  ):
124
127
  """Run a scan wth a flyer and multiple detectors.
125
128
 
@@ -144,6 +147,7 @@ def time_resolved_fly_and_collect_with_static_seq_table(
144
147
  shutter_time=shutter_time,
145
148
  repeats=repeats,
146
149
  period=period,
150
+ frame_timeout=frame_timeout,
147
151
  )
148
152
  # Run the fly scan
149
153
  yield from fly_and_collect(stream_name, flyer, detectors)
@@ -16,7 +16,6 @@ class SimPatternDetector(StandardDetector):
16
16
  path: Path,
17
17
  config_sigs: Sequence[AsyncReadable] = [],
18
18
  name: str = "sim_pattern_detector",
19
- writer_timeout: float = 1,
20
19
  ) -> None:
21
20
  self.directory_provider: DirectoryProvider = StaticDirectoryProvider(path)
22
21
  self.pattern_generator = PatternGenerator()
@@ -33,5 +32,4 @@ class SimPatternDetector(StandardDetector):
33
32
  writer=writer,
34
33
  config_sigs=config_sigs,
35
34
  name=name,
36
- writer_timeout=writer_timeout,
37
35
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ophyd-async
3
- Version: 0.3rc2
3
+ Version: 0.3.1a1
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
@@ -96,7 +96,7 @@ Requires-Dist: types-pyyaml; extra == "dev"
96
96
 
97
97
  # ophyd-async
98
98
 
99
- Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
99
+ Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango.
100
100
 
101
101
  | Source | <https://github.com/bluesky/ophyd-async> |
102
102
  | :-----------: | :-----------------------------------------------: |
@@ -124,13 +124,11 @@ async def detectors(RE: RunEngine) -> tuple[StandardDetector, StandardDetector]:
124
124
  Mock(spec=DetectorControl, get_deadtime=lambda num: num, arm=dummy_arm_1),
125
125
  writers[0],
126
126
  name="detector_1",
127
- writer_timeout=3,
128
127
  )
129
128
  detector_2: StandardDetector[Any] = StandardDetector(
130
129
  Mock(spec=DetectorControl, get_deadtime=lambda num: num, arm=dummy_arm_2),
131
130
  writers[1],
132
131
  name="detector_2",
133
- writer_timeout=3,
134
132
  )
135
133
 
136
134
  return (detector_1, detector_2)
@@ -8,7 +8,7 @@ from bluesky.protocols import HasHints
8
8
  from ophyd_async.core import ConfigSignal, HintedSignal, StandardReadable
9
9
  from ophyd_async.core.device import Device, DeviceVector
10
10
  from ophyd_async.core.mock_signal_backend import MockSignalBackend
11
- from ophyd_async.core.signal import SignalR
11
+ from ophyd_async.core.signal import SignalR, soft_signal_r_and_setter
12
12
  from ophyd_async.protocols import AsyncConfigurable, AsyncReadable, AsyncStageable
13
13
 
14
14
 
@@ -219,3 +219,14 @@ def test_standard_readable_set_readable_signals():
219
219
  assert all(isinstance(x, ConfigSignal) for x in sr._configurables)
220
220
  assert len(sr._stageables) == 1
221
221
  assert all(isinstance(x, HintedSignal) for x in sr._stageables)
222
+
223
+
224
+ def test_standard_readable_add_children_multi_nested():
225
+ inner = StandardReadable()
226
+ outer = StandardReadable()
227
+ with inner.add_children_as_readables(HintedSignal):
228
+ inner.a, _ = soft_signal_r_and_setter(float, initial_value=5.0)
229
+ inner.b, _ = soft_signal_r_and_setter(float, initial_value=6.0)
230
+ with outer.add_children_as_readables():
231
+ outer.inner = inner
232
+ assert outer
@@ -2,7 +2,7 @@ from unittest.mock import patch
2
2
 
3
3
  import pytest
4
4
 
5
- from ophyd_async.core import DetectorTrigger, DeviceCollector
5
+ from ophyd_async.core import DetectorTrigger, DeviceCollector, set_mock_value
6
6
  from ophyd_async.epics.areadetector.controllers import (
7
7
  ADSimController,
8
8
  PilatusController,
@@ -13,10 +13,17 @@ from ophyd_async.epics.areadetector.utils import ImageMode
13
13
 
14
14
 
15
15
  @pytest.fixture
16
- async def pilatus(RE) -> PilatusController:
16
+ async def pilatus_driver(RE) -> PilatusDriver:
17
17
  async with DeviceCollector(mock=True):
18
18
  drv = PilatusDriver("DRIVER:")
19
- controller = PilatusController(drv)
19
+
20
+ return drv
21
+
22
+
23
+ @pytest.fixture
24
+ async def pilatus(RE, pilatus_driver: PilatusDriver) -> PilatusController:
25
+ async with DeviceCollector(mock=True):
26
+ controller = PilatusController(pilatus_driver, readout_time=2.28)
20
27
 
21
28
  return controller
22
29
 
@@ -47,19 +54,22 @@ async def test_ad_controller(RE, ad: ADSimController):
47
54
  assert await driver.acquire.get_value() is False
48
55
 
49
56
 
50
- async def test_pilatus_controller(RE, pilatus: PilatusController):
51
- with patch("ophyd_async.core.signal.wait_for_value", return_value=None):
52
- await pilatus.arm(num=1, trigger=DetectorTrigger.constant_gate)
57
+ async def test_pilatus_controller(
58
+ RE,
59
+ pilatus: PilatusController,
60
+ pilatus_driver: PilatusDriver,
61
+ ):
62
+ set_mock_value(pilatus_driver.armed_for_triggers, True)
63
+ status = await pilatus.arm(num=1, trigger=DetectorTrigger.constant_gate)
64
+ await status
53
65
 
54
- driver = pilatus._drv
55
- assert await driver.num_images.get_value() == 1
56
- assert await driver.image_mode.get_value() == ImageMode.multiple
57
- assert await driver.trigger_mode.get_value() == PilatusTriggerMode.ext_enable
58
- assert await driver.acquire.get_value() is True
66
+ assert await pilatus_driver.num_images.get_value() == 1
67
+ assert await pilatus_driver.image_mode.get_value() == ImageMode.multiple
68
+ assert (
69
+ await pilatus_driver.trigger_mode.get_value() == PilatusTriggerMode.ext_enable
70
+ )
71
+ assert await pilatus_driver.acquire.get_value() is True
59
72
 
60
- with patch(
61
- "ophyd_async.epics.areadetector.utils.wait_for_value", return_value=None
62
- ):
63
- await pilatus.disarm()
73
+ await pilatus.disarm()
64
74
 
65
- assert await driver.acquire.get_value() is False
75
+ assert await pilatus_driver.acquire.get_value() is False
@@ -1,3 +1,6 @@
1
+ from typing import Awaitable, Callable
2
+ from unittest.mock import patch
3
+
1
4
  import pytest
2
5
  from bluesky.run_engine import RunEngine
3
6
 
@@ -9,7 +12,7 @@ from ophyd_async.core import (
9
12
  set_mock_value,
10
13
  )
11
14
  from ophyd_async.epics.areadetector.drivers.pilatus_driver import PilatusTriggerMode
12
- from ophyd_async.epics.areadetector.pilatus import PilatusDetector
15
+ from ophyd_async.epics.areadetector.pilatus import PilatusDetector, PilatusReadoutTime
13
16
 
14
17
 
15
18
  @pytest.fixture
@@ -23,13 +26,25 @@ async def pilatus(
23
26
  return adpilatus
24
27
 
25
28
 
29
+ async def test_deadtime_overridable(static_directory_provider: DirectoryProvider):
30
+ async with DeviceCollector(mock=True):
31
+ pilatus = PilatusDetector(
32
+ "PILATUS:",
33
+ static_directory_provider,
34
+ readout_time=PilatusReadoutTime.pilatus2,
35
+ )
36
+ pilatus_controller = pilatus.controller
37
+ # deadtime invariant with exposure time
38
+ assert pilatus_controller.get_deadtime(0) == 2.28e-3
39
+
40
+
26
41
  async def test_deadtime_invariant(
27
42
  pilatus: PilatusDetector,
28
43
  ):
29
44
  pilatus_controller = pilatus.controller
30
45
  # deadtime invariant with exposure time
31
- assert pilatus_controller.get_deadtime(0) == 2.28e-3
32
- assert pilatus_controller.get_deadtime(500) == 2.28e-3
46
+ assert pilatus_controller.get_deadtime(0) == 0.95e-3
47
+ assert pilatus_controller.get_deadtime(500) == 0.95e-3
33
48
 
34
49
 
35
50
  @pytest.mark.parametrize(
@@ -46,10 +61,37 @@ async def test_trigger_mode_set(
46
61
  expected_trigger_mode: PilatusTriggerMode,
47
62
  ):
48
63
  async def trigger_and_complete():
49
- await pilatus.controller.arm(num=1, trigger=detector_trigger)
50
- # Prevent timeouts
51
- set_mock_value(pilatus.controller._drv.acquire, True)
64
+ set_mock_value(pilatus.drv.armed_for_triggers, True)
65
+ status = await pilatus.controller.arm(
66
+ num=1,
67
+ trigger=detector_trigger,
68
+ )
69
+ await status
70
+
71
+ await _trigger(pilatus, expected_trigger_mode, trigger_and_complete)
72
+
73
+
74
+ async def test_trigger_mode_set_without_armed_pv(pilatus: PilatusDetector):
75
+ async def trigger_and_complete():
76
+ status = await pilatus.controller.arm(
77
+ num=1,
78
+ trigger=DetectorTrigger.internal,
79
+ )
80
+ await status
81
+
82
+ with patch(
83
+ "ophyd_async.epics.areadetector.controllers.pilatus_controller.DEFAULT_TIMEOUT",
84
+ 0.1,
85
+ ):
86
+ with pytest.raises(TimeoutError):
87
+ await _trigger(pilatus, PilatusTriggerMode.internal, trigger_and_complete)
52
88
 
89
+
90
+ async def _trigger(
91
+ pilatus: PilatusDetector,
92
+ expected_trigger_mode: PilatusTriggerMode,
93
+ trigger_and_complete: Callable[[], Awaitable],
94
+ ):
53
95
  # Default TriggerMode
54
96
  assert (await pilatus.drv.trigger_mode.get_value()) == PilatusTriggerMode.internal
55
97
 
@@ -1,7 +1,7 @@
1
1
  import asyncio
2
2
  from pathlib import Path
3
3
  from typing import Any, Optional
4
- from unittest.mock import AsyncMock
4
+ from unittest.mock import AsyncMock, patch
5
5
 
6
6
  import bluesky.plan_stubs as bps
7
7
  import bluesky.plans as bp
@@ -76,6 +76,7 @@ def writer(RE, tmp_path: Path) -> HDFWriter:
76
76
  )
77
77
 
78
78
 
79
+ @patch("ophyd_async.core.detector.DEFAULT_TIMEOUT", 0.1)
79
80
  async def test_hdf_writer_fails_on_timeout_with_stepscan(
80
81
  RE: RunEngine,
81
82
  writer: HDFWriter,
@@ -83,7 +84,7 @@ async def test_hdf_writer_fails_on_timeout_with_stepscan(
83
84
  ):
84
85
  set_mock_value(writer.hdf.file_path_exists, True)
85
86
  detector: StandardDetector[Any] = StandardDetector(
86
- controller, writer, name="detector", writer_timeout=0.01
87
+ controller, writer, name="detector"
87
88
  )
88
89
 
89
90
  with pytest.raises(Exception) as exc:
@@ -92,12 +93,13 @@ async def test_hdf_writer_fails_on_timeout_with_stepscan(
92
93
  assert isinstance(exc.value.__cause__, asyncio.TimeoutError)
93
94
 
94
95
 
96
+ @patch("ophyd_async.core.detector.DEFAULT_TIMEOUT", 0.1)
95
97
  def test_hdf_writer_fails_on_timeout_with_flyscan(RE: RunEngine, writer: HDFWriter):
96
98
  controller = DummyController()
97
99
  set_mock_value(writer.hdf.file_path_exists, True)
98
100
 
99
101
  detector: StandardDetector[Optional[TriggerInfo]] = StandardDetector(
100
- controller, writer, writer_timeout=0.01
102
+ controller, writer
101
103
  )
102
104
  trigger_logic = DummyTriggerLogic()
103
105
 
@@ -40,6 +40,7 @@ class DummyWriter(DetectorWriter):
40
40
  self._file: Optional[ComposeStreamResourceBundle] = None
41
41
  self._last_emitted = 0
42
42
  self.index = 0
43
+ self.observe_indices_written_timeout_log = []
43
44
 
44
45
  async def open(self, multiplier: int = 1) -> Dict[str, DataKey]:
45
46
  return {
@@ -54,6 +55,7 @@ class DummyWriter(DetectorWriter):
54
55
  async def observe_indices_written(
55
56
  self, timeout=DEFAULT_TIMEOUT
56
57
  ) -> AsyncGenerator[int, None]:
58
+ self.observe_indices_written_timeout_log.append(timeout)
57
59
  num_captured: int
58
60
  async for num_captured in observe_value(self.dummy_signal, timeout):
59
61
  yield num_captured
@@ -102,9 +104,8 @@ class MockDetector(StandardDetector):
102
104
  writer: DetectorWriter,
103
105
  config_sigs: Sequence[AsyncReadable] = [],
104
106
  name: str = "",
105
- writer_timeout: float = 1,
106
107
  ) -> None:
107
- super().__init__(controller, writer, config_sigs, name, writer_timeout)
108
+ super().__init__(controller, writer, config_sigs, name)
108
109
 
109
110
  @WatchableAsyncStatus.wrap
110
111
  async def complete(self):
@@ -112,7 +113,12 @@ class MockDetector(StandardDetector):
112
113
  assert self._trigger_info
113
114
  self.writer.increment_index()
114
115
  async for index in self.writer.observe_indices_written(
115
- self._frame_writing_timeout
116
+ self._trigger_info.frame_timeout
117
+ or (
118
+ DEFAULT_TIMEOUT
119
+ + self._trigger_info.livetime
120
+ + self._trigger_info.deadtime
121
+ )
116
122
  ):
117
123
  yield WatcherUpdate(
118
124
  name=self.name,
@@ -143,13 +149,11 @@ async def detectors(RE: RunEngine) -> tuple[MockDetector, MockDetector]:
143
149
  Mock(spec=DetectorControl, get_deadtime=lambda num: num, arm=dummy_arm_1),
144
150
  writers[0],
145
151
  name="detector_1",
146
- writer_timeout=3,
147
152
  )
148
153
  detector_2 = MockDetector(
149
154
  Mock(spec=DetectorControl, get_deadtime=lambda num: num, arm=dummy_arm_2),
150
155
  writers[1],
151
156
  name="detector_2",
152
- writer_timeout=3,
153
157
  )
154
158
  return (detector_1, detector_2)
155
159
 
@@ -374,3 +378,39 @@ async def test_at_least_one_detector_in_fly_plan(
374
378
  with pytest.raises(ValueError) as exc:
375
379
  RE(fly())
376
380
  assert str(exc) == "No detectors provided. There must be at least one."
381
+
382
+
383
+ @pytest.mark.parametrize("timeout_setting,expected_timeout", [(None, 12), (5.0, 5.0)])
384
+ async def test_trigger_sets_or_defaults_timeout(
385
+ RE: RunEngine,
386
+ flyer: HardwareTriggeredFlyable,
387
+ detectors: tuple[StandardDetector, ...],
388
+ timeout_setting: float | None,
389
+ expected_timeout: float,
390
+ ):
391
+ detector_list = list(detectors)
392
+
393
+ # Trigger parameters
394
+ number_of_frames = 1
395
+ exposure = 1
396
+ shutter_time = 0.004
397
+
398
+ def fly():
399
+ yield from bps.stage_all(*detector_list, flyer)
400
+ yield from bps.open_run()
401
+ yield from time_resolved_fly_and_collect_with_static_seq_table(
402
+ stream_name="stream1",
403
+ flyer=flyer,
404
+ detectors=detector_list,
405
+ number_of_frames=number_of_frames,
406
+ exposure=exposure,
407
+ shutter_time=shutter_time,
408
+ frame_timeout=timeout_setting,
409
+ )
410
+ yield from bps.close_run()
411
+ yield from bps.unstage_all(flyer, *detector_list)
412
+
413
+ RE(fly())
414
+
415
+ for detector in detectors:
416
+ assert detector.writer.observe_indices_written_timeout_log == [expected_timeout]
File without changes