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.
- {ophyd_async-0.11 → ophyd_async-0.12.1}/PKG-INFO +3 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/README.md +1 -1
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/conf.py +1 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0007-subpackage-structure.md +1 -1
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/design-goals.md +5 -5
- ophyd_async-0.12.1/docs/explanations/fly-scanning.md +97 -0
- ophyd_async-0.12.1/docs/explanations/plan-stubs.md +336 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/choose-right-baseclass.md +2 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/pyproject.toml +2 -1
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/_version.py +2 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_flyer.py +4 -4
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_hdf_dataset.py +2 -15
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_providers.py +69 -11
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_signal.py +15 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_soft_signal_backend.py +1 -1
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/__init__.py +2 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_core_io.py +15 -5
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_core_writer.py +34 -26
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_hdf_writer.py +4 -3
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_jpeg_writer.py +3 -3
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_tiff_writer.py +3 -3
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_aioca.py +3 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_signal.py +8 -3
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/motor.py +2 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/_utils.py +1 -1
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_trigger.py +4 -4
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_writer.py +1 -3
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/__init__.py +0 -8
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/__main__.py +2 -1
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_blob_detector_writer.py +4 -5
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_pattern_generator.py +3 -3
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/__init__.py +2 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_assert.py +34 -6
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/PKG-INFO +3 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/SOURCES.txt +3 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/requires.txt +1 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/conftest.py +4 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_device.py +2 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_observe.py +8 -8
- ophyd_async-0.12.1/tests/core/test_providers.py +177 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_signal.py +118 -139
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_single_derived_signal.py +4 -3
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_detectors.py +106 -7
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_scans.py +1 -1
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_writers.py +2 -2
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adsimdetector/test_sim.py +10 -7
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/conftest.py +12 -4
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/signal/test_signals.py +67 -24
- ophyd_async-0.12.1/tests/fastcs/panda/test_hdf_panda.py +49 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_panda_connect.py +5 -4
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_writer.py +4 -2
- ophyd_async-0.12.1/tests/plan_stubs/test_fly.py +0 -0
- ophyd_async-0.12.1/tests/sim/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/sim/test_sim_blob_detector.py +1 -1
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/test_tango_signals.py +8 -3
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/test_tutorials.py +7 -0
- ophyd_async-0.11/docs/explanations/flyscanning.md +0 -84
- ophyd_async-0.11/src/ophyd_async/plan_stubs/_fly.py +0 -204
- ophyd_async-0.11/tests/core/test_providers.py +0 -85
- ophyd_async-0.11/tests/fastcs/panda/test_hdf_panda.py +0 -166
- ophyd_async-0.11/tests/plan_stubs/test_fly.py +0 -436
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.codecov.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.copier-answers.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.devcontainer/devcontainer.json +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.git-blame-ignore-revs +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/CONTRIBUTING.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/actions/install_requirements/action.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/codeql/codeql-config.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/dependabot.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/pages/index.html +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/pages/make_switcher.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_check.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_codeql.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_dist.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_docs.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_import_with_no_extras.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_pypi.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_release.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_test.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/_tox.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/ci.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.github/workflows/periodic.yml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.gitignore +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/.pre-commit-config.yaml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/Dockerfile +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/LICENSE +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/_static/custom.css +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0008-signal-types.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0010-docstring-format.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/COPYME +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/declarative-vs-procedural.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/device-connection-strategies.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/devices-signals-backends.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/where-device-logic.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/genindex.rst +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/contribute.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/derive-one-signal-from-others.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/implement-ad-detector.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/interact-with-signals.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/put-device-back.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to/store-and-retrieve.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/how-to.md +0 -0
- /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
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/images/ophyd-async-logo.svg +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/images/ophyd-favicon.svg +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/index.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/reference.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/implementing-detectors.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/implementing-devices.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/installation.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/using-devices.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials/writing-tests-for-devices.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/docs/tutorials.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/setup.cfg +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/__main__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/_docs_parser.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_derived_signal.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_derived_signal_backend.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_detector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_device.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_device_filler.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_log.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_protocol.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_readable.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_settings.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_signal_backend.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_status.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_table.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_utils.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/core/_yaml_settings.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adandor/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adandor/_andor.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_core_logic.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adcore/_utils.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/advimba/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_epics_device.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_p4p.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/core/_util.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/__main__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_ioc.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_motor.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/_stage.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/motor.db +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/point_detector.db +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/eiger/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/eiger/_odin_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/pmac/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/pmac/_pmac_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/signal.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/test_records.db +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/core.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/eiger/_eiger.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/eiger/_eiger_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_block.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_control.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/fastcs/panda/_table.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
- /ophyd_async-0.11/src/ophyd_async/py.typed → /ophyd_async-0.12.1/src/ophyd_async/plan_stubs/_fly.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_panda.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_settings.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_utils.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
- /ophyd_async-0.11/tests/sim/__init__.py → /ophyd_async-0.12.1/src/ophyd_async/py.typed +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_blob_detector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_motor.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_point_detector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/sim/_stage.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_base_device.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_converters.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_signal.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_tango_readable.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_tango_transport.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/core/_utils.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_counter.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_detector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_mover.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/testing/__init__.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_mock_signal_utils.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_single_derived.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_utils.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/src/ophyd_async.egg-info/top_level.txt +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/system_tests/epics/eiger/README.md +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/system_tests/epics/eiger/test_eiger_system.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_auto_init_devices.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_detector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_flyer.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_log.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_mock_signal_backend.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_multi_derived_signal.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_protocol.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_readable.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_soft_signal_backend.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_status.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_subset_enum.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_table.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_utils.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/core/test_watchable_async_status.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adandor/test_andor.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adaravis/test_aravis.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_cont_acq_detector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_drivers.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adcore/test_single_trigger.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adkinetix/test_kinetix.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/adpilatus/test_pilatus.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/advimba/test_vimba.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/demo/test_epics_demo.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/eiger/test_odin_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/pmac/test_pmac_io.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/pvi/test_pvi.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/signal/test_common.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/signal/test_yaml_save_ca.yaml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/signal/test_yaml_save_pva.yaml +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/test_areadetector_subclass_naming.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/epics/test_motor.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/eiger/test_eiger_controller.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/eiger/test_eiger_detector.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/db/panda.db +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_panda_control.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_panda_utils.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_seq_table.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/fastcs/panda/test_trigger.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/plan_stubs/test_ensure_connected.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/plan_stubs/test_settings.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/plan_stubs/test_setup.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/sim/test_sim_motor.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/conftest.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/context_subprocess.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/test_base_device.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/tango/test_tango_transport.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/test_cli.py +0 -0
- {ophyd_async-0.11 → ophyd_async-0.12.1}/tests/test_data/test_yaml_config_save.yaml +0 -0
- {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.
|
|
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
|
|
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
|
|
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),
|
{ophyd_async-0.11 → ophyd_async-0.12.1}/docs/explanations/decisions/0007-subpackage-structure.md
RENAMED
|
@@ -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
|
|
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
|
|
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
|
|
52
|
+
## Ease the implementation of fly scanning
|
|
53
53
|
|
|
54
|
-
One of the major drivers for ophyd-async was to ease the implementation of
|
|
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
|
|
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
|
-
|
|
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
|
+

|
|
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
|
|
15
|
-
- [](#StandardFlyer) allows actuators (like a motor controller) to be used within a
|
|
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.
|
|
105
|
+
timeout = 0.75
|
|
105
106
|
[tool.coverage.run]
|
|
106
107
|
data_file = "/tmp/ophyd_async.coverage"
|
|
107
108
|
|
|
@@ -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
|
|
20
|
+
"""Move to the start of the fly scan."""
|
|
21
21
|
|
|
22
22
|
@abstractmethod
|
|
23
23
|
async def kickoff(self):
|
|
24
|
-
"""Start the
|
|
24
|
+
"""Start the fly scan."""
|
|
25
25
|
|
|
26
26
|
@abstractmethod
|
|
27
27
|
async def complete(self):
|
|
28
|
-
"""Block until the
|
|
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
|
|
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
|
-
|
|
49
|
+
file_uri: str,
|
|
52
50
|
datasets: list[HDFDatasetDescription],
|
|
53
|
-
hostname: str = "localhost",
|
|
54
51
|
) -> None:
|
|
55
52
|
self._last_emitted = 0
|
|
56
|
-
|
|
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(
|