ophyd-async 0.12.2__tar.gz → 0.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/PKG-INFO +3 -2
- ophyd_async-0.13.0/docs/explanations/decisions/0011-buffer-updates-camonitor.md +33 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/pyproject.toml +3 -2
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/_version.py +2 -2
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/__init__.py +11 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_detector.py +6 -9
- ophyd_async-0.13.0/src/ophyd_async/core/_enums.py +21 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adaravis/__init__.py +1 -2
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adaravis/_aravis_controller.py +4 -4
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adaravis/_aravis_io.py +2 -12
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/__init__.py +4 -4
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/_core_io.py +59 -7
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/_core_logic.py +4 -3
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/_core_writer.py +4 -5
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/_utils.py +36 -11
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/advimba/__init__.py +0 -2
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/advimba/_vimba_controller.py +6 -9
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/advimba/_vimba_io.py +3 -10
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/core/__init__.py +2 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/core/_aioca.py +6 -2
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/core/_util.py +12 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/eiger/_odin_io.py +25 -7
- ophyd_async-0.13.0/src/ophyd_async/epics/pmac/__init__.py +8 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/pmac/_pmac_io.py +34 -23
- ophyd_async-0.13.0/src/ophyd_async/epics/pmac/_utils.py +231 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/eiger/_eiger.py +1 -1
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/eiger/_eiger_io.py +2 -1
- ophyd_async-0.13.0/src/ophyd_async/plan_stubs/_nd_attributes.py +48 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async.egg-info/PKG-INFO +3 -2
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async.egg-info/SOURCES.txt +5 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async.egg-info/requires.txt +2 -1
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_detector.py +0 -17
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_device.py +1 -0
- ophyd_async-0.13.0/tests/epics/adcore/test_plugins.py +9 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adcore/test_writers.py +46 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/advimba/test_vimba.py +17 -21
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/eiger/test_odin_io.py +53 -29
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/pmac/test_pmac_io.py +31 -9
- ophyd_async-0.13.0/tests/epics/pmac/test_pmac_utils.py +324 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/signal/test_signals.py +45 -2
- ophyd_async-0.13.0/tests/epics/test_areadetector_subclass_naming.py +66 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/test_motor.py +1 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/eiger/test_eiger_detector.py +11 -2
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/sim/test_sim_motor.py +1 -0
- ophyd_async-0.12.2/src/ophyd_async/epics/pmac/__init__.py +0 -3
- ophyd_async-0.12.2/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -74
- ophyd_async-0.12.2/tests/epics/test_areadetector_subclass_naming.py +0 -32
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.codecov.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.copier-answers.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.devcontainer/devcontainer.json +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.git-blame-ignore-revs +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/CONTRIBUTING.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/ISSUE_TEMPLATE/issue.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/actions/install_requirements/action.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/codeql/codeql-config.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/dependabot.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/pages/index.html +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/pages/make_switcher.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/_check.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/_codeql.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/_dist.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/_docs.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/_import_with_no_extras.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/_pypi.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/_release.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/_test.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/_tox.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/ci.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.github/workflows/periodic.yml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.gitignore +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/.pre-commit-config.yaml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/Dockerfile +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/LICENSE +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/README.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/_static/custom.css +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/conf.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0008-signal-types.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/0010-docstring-format.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions/COPYME +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/decisions.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/declarative-vs-procedural.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/design-goals.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/device-connection-strategies.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/devices-signals-backends.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/fly-scanning.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/plan-stubs.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations/where-device-logic.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/explanations.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/genindex.rst +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/how-to/choose-right-baseclass.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/how-to/contribute.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/how-to/derive-one-signal-from-others.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/how-to/implement-ad-detector.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/how-to/interact-with-signals.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/how-to/put-device-back.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/how-to/store-and-retrieve.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/how-to.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/images/fly_scan_collection_windows_and_frames.svg +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/images/ophyd-async-logo.svg +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/images/ophyd-favicon.svg +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/index.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/reference.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/tutorials/implementing-detectors.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/tutorials/implementing-devices.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/tutorials/installation.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/tutorials/using-devices.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/tutorials/writing-tests-for-devices.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/docs/tutorials.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/setup.cfg +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/__main__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/_docs_parser.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_derived_signal.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_derived_signal_backend.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_device.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_device_filler.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_flyer.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_hdf_dataset.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_log.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_protocol.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_providers.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_readable.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_settings.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_signal.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_signal_backend.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_status.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_table.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_utils.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/core/_yaml_settings.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adandor/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adandor/_andor.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/_hdf_writer.py +6 -6
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/_jpeg_writer.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adcore/_tiff_writer.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/core/_epics_device.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/core/_p4p.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/core/_signal.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/__main__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/_ioc.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/_motor.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/_stage.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/motor.db +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/point_detector.db +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/eiger/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/motor.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/signal.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/testing/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/testing/_utils.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/testing/test_records.db +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/core.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/panda/_block.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/panda/_control.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/panda/_table.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/panda/_trigger.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/plan_stubs/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/plan_stubs/_fly.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/plan_stubs/_panda.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/plan_stubs/_settings.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/plan_stubs/_utils.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/py.typed +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/__main__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/_blob_detector.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/_blob_detector_writer.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/_motor.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/_pattern_generator.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/_point_detector.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/sim/_stage.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/core/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/core/_base_device.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/core/_converters.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/core/_signal.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/core/_tango_readable.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/core/_tango_transport.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/core/_utils.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/demo/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/demo/_counter.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/demo/_detector.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/demo/_mover.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/testing/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/testing/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/testing/_assert.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/testing/_mock_signal_utils.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/testing/_single_derived.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/testing/_utils.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async.egg-info/top_level.txt +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/system_tests/epics/eiger/README.md +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/system_tests/epics/eiger/test_eiger_system.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/conftest.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_auto_init_devices.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_flyer.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_log.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_mock_signal_backend.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_multi_derived_signal.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_observe.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_protocol.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_providers.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_readable.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_signal.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_single_derived_signal.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_soft_signal_backend.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_status.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_subset_enum.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_table.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_utils.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/core/test_watchable_async_status.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adandor/test_andor.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adaravis/test_aravis.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adcore/test_cont_acq_detector.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adcore/test_detectors.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adcore/test_drivers.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adcore/test_scans.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adcore/test_single_trigger.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adkinetix/test_kinetix.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adpilatus/test_pilatus.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/adsimdetector/test_sim.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/conftest.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/demo/test_epics_demo.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/pvi/test_pvi.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/signal/test_common.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/signal/test_yaml_save_ca.yaml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/epics/signal/test_yaml_save_pva.yaml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/eiger/test_eiger_controller.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/panda/db/panda.db +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/panda/test_hdf_panda.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/panda/test_panda_connect.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/panda/test_panda_control.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/panda/test_panda_utils.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/panda/test_seq_table.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/panda/test_trigger.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/fastcs/panda/test_writer.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/plan_stubs/test_ensure_connected.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/plan_stubs/test_fly.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/plan_stubs/test_settings.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/plan_stubs/test_setup.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/sim/__init__.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/sim/test_sim_blob_detector.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/tango/conftest.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/tango/context_subprocess.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/tango/test_base_device.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/tango/test_tango_signals.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/tango/test_tango_transport.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/test_cli.py +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/test_data/test_yaml_config_save.yaml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/test_data/test_yaml_save.yaml +0 -0
- {ophyd_async-0.12.2 → ophyd_async-0.13.0}/tests/test_tutorials.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.0
|
|
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
|
|
@@ -49,10 +49,11 @@ Requires-Dist: colorlog
|
|
|
49
49
|
Requires-Dist: pydantic>=2.0
|
|
50
50
|
Requires-Dist: pydantic-numpy
|
|
51
51
|
Requires-Dist: stamina>=23.1.0
|
|
52
|
+
Requires-Dist: scanspec>=1.0a1
|
|
52
53
|
Provides-Extra: sim
|
|
53
54
|
Requires-Dist: h5py; extra == "sim"
|
|
54
55
|
Provides-Extra: ca
|
|
55
|
-
Requires-Dist: aioca>=
|
|
56
|
+
Requires-Dist: aioca>=2.0a4; extra == "ca"
|
|
56
57
|
Provides-Extra: pva
|
|
57
58
|
Requires-Dist: p4p>=4.2.0; extra == "pva"
|
|
58
59
|
Provides-Extra: tango
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# 11. Buffer updates when using `camonitor`
|
|
2
|
+
|
|
3
|
+
Date: 2025-07-30
|
|
4
|
+
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
Accepted
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
The ChannelAccess signal backend uses aioca.camonitor to subscribe to changes in PV values. By default it deals with backpressure by dropping excessive updates that it is too slow to handle. It also has a mode whereby it will buffer the updates, lagging behind if there are too many.
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
# The following will buffer every update to the PV
|
|
15
|
+
aioca.camonitor(my_pv, all_updates=True)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Decision
|
|
19
|
+
|
|
20
|
+
Default `all_updates` to `True` in the ChannelAccess backend, but provide a feature flag via an environment variable so it can be reverted at runtime if necessary.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# The following should restore the old behavior
|
|
24
|
+
export OPHYD_ASYNC_EPICS_CA_KEEP_ALL_UPDATES=False
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Consequences
|
|
28
|
+
|
|
29
|
+
If backpressure is causing a problem, ophyd-async will slow down and lag behind. This is deemed to be an easier problem to spot and debug than updates being silently dropped.
|
|
30
|
+
|
|
31
|
+
It is the responsibility of IOCs to not push updates too quickly (<=10Hz) rather than the responsibility of ophyd-async to handle them. If an IOC is pushing updates too quickly, it should be fixed.
|
|
32
|
+
|
|
33
|
+
There may be unknown bugs and race conditions exposed by this change, they can be temporarily remedied by disabling the feature (see above).
|
|
@@ -20,7 +20,8 @@ dependencies = [
|
|
|
20
20
|
"colorlog",
|
|
21
21
|
"pydantic>=2.0",
|
|
22
22
|
"pydantic-numpy",
|
|
23
|
-
"stamina>=23.1.0"
|
|
23
|
+
"stamina>=23.1.0",
|
|
24
|
+
"scanspec>=1.0a1",
|
|
24
25
|
]
|
|
25
26
|
dynamic = ["version"]
|
|
26
27
|
license.file = "LICENSE"
|
|
@@ -29,7 +30,7 @@ requires-python = ">=3.10"
|
|
|
29
30
|
|
|
30
31
|
[project.optional-dependencies]
|
|
31
32
|
sim = ["h5py"]
|
|
32
|
-
ca = ["aioca>=
|
|
33
|
+
ca = ["aioca>=2.0a4"]
|
|
33
34
|
pva = ["p4p>=4.2.0"]
|
|
34
35
|
tango = ["pytango==10.0.0"]
|
|
35
36
|
demo = ["ipython", "matplotlib", "pyqt6"]
|
|
@@ -16,6 +16,12 @@ from ._detector import (
|
|
|
16
16
|
)
|
|
17
17
|
from ._device import Device, DeviceConnector, DeviceVector, init_devices
|
|
18
18
|
from ._device_filler import DeviceFiller
|
|
19
|
+
from ._enums import (
|
|
20
|
+
EnabledDisabled,
|
|
21
|
+
EnableDisable,
|
|
22
|
+
InOut,
|
|
23
|
+
OnOff,
|
|
24
|
+
)
|
|
19
25
|
from ._flyer import FlyerController, FlyMotorInfo, StandardFlyer
|
|
20
26
|
from ._hdf_dataset import HDFDatasetDescription, HDFDocumentComposer
|
|
21
27
|
from ._log import config_ophyd_async_logging
|
|
@@ -209,4 +215,9 @@ __all__ = [
|
|
|
209
215
|
# Back compat - delete before 1.0
|
|
210
216
|
"ConfigSignal",
|
|
211
217
|
"HintedSignal",
|
|
218
|
+
# Standard enums
|
|
219
|
+
"EnabledDisabled",
|
|
220
|
+
"EnableDisable",
|
|
221
|
+
"InOut",
|
|
222
|
+
"OnOff",
|
|
212
223
|
]
|
|
@@ -104,7 +104,11 @@ class DetectorController(ABC):
|
|
|
104
104
|
|
|
105
105
|
@abstractmethod
|
|
106
106
|
def get_deadtime(self, exposure: float | None) -> float:
|
|
107
|
-
"""
|
|
107
|
+
"""Get state-independent deadtime.
|
|
108
|
+
|
|
109
|
+
For a given exposure, what is the safest minimum time between exposures that
|
|
110
|
+
can be determined without reading signals.
|
|
111
|
+
"""
|
|
108
112
|
|
|
109
113
|
@abstractmethod
|
|
110
114
|
async def prepare(self, trigger_info: TriggerInfo) -> None:
|
|
@@ -313,14 +317,7 @@ class StandardDetector(
|
|
|
313
317
|
if value.trigger != DetectorTrigger.INTERNAL and not value.deadtime:
|
|
314
318
|
msg = "Deadtime must be supplied when in externally triggered mode"
|
|
315
319
|
raise ValueError(msg)
|
|
316
|
-
|
|
317
|
-
if value.deadtime and required_deadtime > value.deadtime:
|
|
318
|
-
msg = (
|
|
319
|
-
f"Detector {self._controller} needs at least {required_deadtime}s "
|
|
320
|
-
f"deadtime, but trigger logic provides only {value.deadtime}s"
|
|
321
|
-
)
|
|
322
|
-
raise ValueError(msg)
|
|
323
|
-
elif not value.deadtime:
|
|
320
|
+
if not value.deadtime:
|
|
324
321
|
value.deadtime = self._controller.get_deadtime(value.livetime)
|
|
325
322
|
self._trigger_info = value
|
|
326
323
|
self._number_of_events_iter = iter(
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from ._utils import StrictEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class OnOff(StrictEnum):
|
|
5
|
+
ON = "On"
|
|
6
|
+
OFF = "Off"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class EnableDisable(StrictEnum):
|
|
10
|
+
ENABLE = "Enable"
|
|
11
|
+
DISABLE = "Disable"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EnabledDisabled(StrictEnum):
|
|
15
|
+
ENABLED = "Enabled"
|
|
16
|
+
DISABLED = "Disabled"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class InOut(StrictEnum):
|
|
20
|
+
IN = "In"
|
|
21
|
+
OUT = "Out"
|
|
@@ -5,12 +5,11 @@ https://github.com/areaDetector/ADAravis
|
|
|
5
5
|
|
|
6
6
|
from ._aravis import AravisDetector
|
|
7
7
|
from ._aravis_controller import AravisController
|
|
8
|
-
from ._aravis_io import AravisDriverIO,
|
|
8
|
+
from ._aravis_io import AravisDriverIO, AravisTriggerSource
|
|
9
9
|
|
|
10
10
|
__all__ = [
|
|
11
11
|
"AravisDetector",
|
|
12
12
|
"AravisController",
|
|
13
13
|
"AravisDriverIO",
|
|
14
|
-
"AravisTriggerMode",
|
|
15
14
|
"AravisTriggerSource",
|
|
16
15
|
]
|
{ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/adaravis/_aravis_controller.py
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
|
|
3
|
-
from ophyd_async.core import DetectorTrigger, TriggerInfo
|
|
3
|
+
from ophyd_async.core import DetectorTrigger, OnOff, TriggerInfo
|
|
4
4
|
from ophyd_async.epics import adcore
|
|
5
5
|
|
|
6
|
-
from ._aravis_io import AravisDriverIO,
|
|
6
|
+
from ._aravis_io import AravisDriverIO, AravisTriggerSource
|
|
7
7
|
|
|
8
8
|
# The deadtime of an ADaravis controller varies depending on the exact model of camera.
|
|
9
9
|
# Ideally we would maximize performance by dynamically retrieving the deadtime at
|
|
@@ -23,14 +23,14 @@ class AravisController(adcore.ADBaseController[AravisDriverIO]):
|
|
|
23
23
|
|
|
24
24
|
if trigger_info.trigger is DetectorTrigger.INTERNAL:
|
|
25
25
|
# Set trigger mode off to ignore the trigger source
|
|
26
|
-
await self.driver.trigger_mode.set(
|
|
26
|
+
await self.driver.trigger_mode.set(OnOff.OFF)
|
|
27
27
|
elif trigger_info.trigger in {
|
|
28
28
|
DetectorTrigger.CONSTANT_GATE,
|
|
29
29
|
DetectorTrigger.EDGE_TRIGGER,
|
|
30
30
|
}:
|
|
31
31
|
# Trigger on the rising edge of Line1
|
|
32
32
|
# trigger mode must be set first and on it's own!
|
|
33
|
-
await self.driver.trigger_mode.set(
|
|
33
|
+
await self.driver.trigger_mode.set(OnOff.ON)
|
|
34
34
|
await self.driver.trigger_source.set(AravisTriggerSource.LINE1)
|
|
35
35
|
else:
|
|
36
36
|
raise ValueError(f"ADAravis does not support {trigger_info.trigger}")
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
from typing import Annotated as A
|
|
2
2
|
|
|
3
|
-
from ophyd_async.core import
|
|
3
|
+
from ophyd_async.core import OnOff, SignalRW, SubsetEnum
|
|
4
4
|
from ophyd_async.epics import adcore
|
|
5
5
|
from ophyd_async.epics.core import PvSuffix
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class AravisTriggerMode(StrictEnum):
|
|
9
|
-
"""GigEVision GenICAM standard TriggerMode."""
|
|
10
|
-
|
|
11
|
-
ON = "On"
|
|
12
|
-
"""Use TriggerSource to trigger each frame"""
|
|
13
|
-
|
|
14
|
-
OFF = "Off"
|
|
15
|
-
"""Just trigger as fast as you can"""
|
|
16
|
-
|
|
17
|
-
|
|
18
8
|
class AravisTriggerSource(SubsetEnum):
|
|
19
9
|
"""Which trigger source to use when TriggerMode=On."""
|
|
20
10
|
|
|
@@ -27,5 +17,5 @@ class AravisDriverIO(adcore.ADBaseIO):
|
|
|
27
17
|
This mirrors the interface provided by ADAravis/db/aravisCamera.template.
|
|
28
18
|
"""
|
|
29
19
|
|
|
30
|
-
trigger_mode: A[SignalRW[
|
|
20
|
+
trigger_mode: A[SignalRW[OnOff], PvSuffix.rbv("TriggerMode")]
|
|
31
21
|
trigger_source: A[SignalRW[AravisTriggerSource], PvSuffix.rbv("TriggerSource")]
|
|
@@ -7,7 +7,6 @@ from ._core_detector import AreaDetector, ContAcqAreaDetector
|
|
|
7
7
|
from ._core_io import (
|
|
8
8
|
ADBaseDatasetDescriber,
|
|
9
9
|
ADBaseIO,
|
|
10
|
-
ADCallbacks,
|
|
11
10
|
ADCompression,
|
|
12
11
|
ADState,
|
|
13
12
|
NDArrayBaseIO,
|
|
@@ -18,6 +17,7 @@ from ._core_io import (
|
|
|
18
17
|
NDPluginBaseIO,
|
|
19
18
|
NDPluginCBIO,
|
|
20
19
|
NDPluginStatsIO,
|
|
20
|
+
NDROIStatIO,
|
|
21
21
|
)
|
|
22
22
|
from ._core_logic import DEFAULT_GOOD_STATES, ADBaseContAcqController, ADBaseController
|
|
23
23
|
from ._core_writer import ADWriter
|
|
@@ -33,12 +33,11 @@ from ._utils import (
|
|
|
33
33
|
NDAttributeParam,
|
|
34
34
|
NDAttributePv,
|
|
35
35
|
NDAttributePvDbrType,
|
|
36
|
-
|
|
36
|
+
ndattributes_to_xml,
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
__all__ = [
|
|
40
40
|
"ADBaseIO",
|
|
41
|
-
"ADCallbacks",
|
|
42
41
|
"ADCompression",
|
|
43
42
|
"ADBaseContAcqController",
|
|
44
43
|
"AreaDetector",
|
|
@@ -50,6 +49,7 @@ __all__ = [
|
|
|
50
49
|
"NDFileHDFIO",
|
|
51
50
|
"NDPluginBaseIO",
|
|
52
51
|
"NDPluginStatsIO",
|
|
52
|
+
"NDROIStatIO",
|
|
53
53
|
"DEFAULT_GOOD_STATES",
|
|
54
54
|
"ADBaseDatasetDescriber",
|
|
55
55
|
"ADBaseController",
|
|
@@ -64,8 +64,8 @@ __all__ = [
|
|
|
64
64
|
"NDAttributePv",
|
|
65
65
|
"NDAttributeParam",
|
|
66
66
|
"NDAttributeDataType",
|
|
67
|
-
"stop_busy_record",
|
|
68
67
|
"NDAttributePvDbrType",
|
|
69
68
|
"NDCBFlushOnSoftTrgMode",
|
|
70
69
|
"NDPluginCBIO",
|
|
70
|
+
"ndattributes_to_xml",
|
|
71
71
|
]
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from typing import Annotated as A
|
|
3
3
|
|
|
4
|
-
from ophyd_async.core import
|
|
4
|
+
from ophyd_async.core import (
|
|
5
|
+
DatasetDescriber,
|
|
6
|
+
DeviceVector,
|
|
7
|
+
EnableDisable,
|
|
8
|
+
SignalR,
|
|
9
|
+
SignalRW,
|
|
10
|
+
StrictEnum,
|
|
11
|
+
)
|
|
5
12
|
from ophyd_async.epics.core import EpicsDevice, PvSuffix
|
|
6
13
|
|
|
7
14
|
from ._utils import ADBaseDataType, ADFileWriteMode, ADImageMode, convert_ad_dtype_to_np
|
|
8
15
|
|
|
9
16
|
|
|
10
|
-
class ADCallbacks(StrictEnum):
|
|
11
|
-
ENABLE = "Enable"
|
|
12
|
-
DISABLE = "Disable"
|
|
13
|
-
|
|
14
|
-
|
|
15
17
|
class NDArrayBaseIO(EpicsDevice):
|
|
16
18
|
"""Class responsible for passing detector data from drivers to pluglins.
|
|
17
19
|
|
|
@@ -53,7 +55,7 @@ class NDPluginBaseIO(NDArrayBaseIO):
|
|
|
53
55
|
"""
|
|
54
56
|
|
|
55
57
|
nd_array_port: A[SignalRW[str], PvSuffix.rbv("NDArrayPort")]
|
|
56
|
-
enable_callbacks: A[SignalRW[
|
|
58
|
+
enable_callbacks: A[SignalRW[EnableDisable], PvSuffix.rbv("EnableCallbacks")]
|
|
57
59
|
nd_array_address: A[SignalRW[int], PvSuffix.rbv("NDArrayAddress")]
|
|
58
60
|
array_size0: A[SignalR[int], PvSuffix("ArraySize0_RBV")]
|
|
59
61
|
array_size1: A[SignalR[int], PvSuffix("ArraySize1_RBV")]
|
|
@@ -87,6 +89,56 @@ class NDPluginStatsIO(NDPluginBaseIO):
|
|
|
87
89
|
hist_max: A[SignalRW[float], PvSuffix.rbv("HistMax")]
|
|
88
90
|
|
|
89
91
|
|
|
92
|
+
class NDROIStatIO(NDPluginBaseIO):
|
|
93
|
+
"""Plugin for calculating basic statistics for multiple ROIs.
|
|
94
|
+
|
|
95
|
+
Each ROI is implemented as an instance of NDROIStatNIO,
|
|
96
|
+
and the collection of ROIs is held as a DeviceVector.
|
|
97
|
+
|
|
98
|
+
See HTML docs at https://areadetector.github.io/areaDetector/ADCore/NDPluginROIStat.html
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def __init__(self, prefix, num_channels=8, with_pvi=False, name=""):
|
|
102
|
+
self.channels = DeviceVector(
|
|
103
|
+
{i: NDROIStatNIO(f"{prefix}{i}:") for i in range(1, num_channels + 1)}
|
|
104
|
+
)
|
|
105
|
+
super().__init__(prefix, with_pvi, name)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class NDROIStatNIO(EpicsDevice):
|
|
109
|
+
"""Defines the parameters for a single ROI used for statistics calculation.
|
|
110
|
+
|
|
111
|
+
Each instance represents a single ROI, with attributes for its position
|
|
112
|
+
(min_x, min_y) and size (size_x, size_y), as well as a name and use status.
|
|
113
|
+
|
|
114
|
+
See definition in ADApp/pluginSrc/NDPluginROIStat.h in https://github.com/areaDetector/ADCore.
|
|
115
|
+
|
|
116
|
+
Attributes:
|
|
117
|
+
name: The name of the ROI.
|
|
118
|
+
use: Flag indicating whether the ROI is used.
|
|
119
|
+
min_x: The start X-coordinate of the ROI.
|
|
120
|
+
min_y: The start Y-coordinate of the ROI.
|
|
121
|
+
size_x: The width of the ROI.
|
|
122
|
+
size_y: The height of the ROI.
|
|
123
|
+
min_value: Minimum count value in the ROI.
|
|
124
|
+
max_value: Maximum count value in the ROI.
|
|
125
|
+
mean_value: Mean counts value in the ROI.
|
|
126
|
+
total: Total counts in the ROI.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
name_: A[SignalRW[str], PvSuffix("Name")]
|
|
130
|
+
use: A[SignalRW[bool], PvSuffix.rbv("Use")]
|
|
131
|
+
min_x: A[SignalRW[int], PvSuffix.rbv("MinX")]
|
|
132
|
+
min_y: A[SignalRW[int], PvSuffix.rbv("MinY")]
|
|
133
|
+
size_x: A[SignalRW[int], PvSuffix.rbv("SizeX")]
|
|
134
|
+
size_y: A[SignalRW[int], PvSuffix.rbv("SizeY")]
|
|
135
|
+
# stats
|
|
136
|
+
min_value: A[SignalR[float], PvSuffix("MinValue_RBV")]
|
|
137
|
+
max_value: A[SignalR[float], PvSuffix("MaxValue_RBV")]
|
|
138
|
+
mean_value: A[SignalR[float], PvSuffix("MeanValue_RBV")]
|
|
139
|
+
total: A[SignalR[float], PvSuffix("Total_RBV")]
|
|
140
|
+
|
|
141
|
+
|
|
90
142
|
class ADState(StrictEnum):
|
|
91
143
|
"""Default set of states of an AreaDetector driver.
|
|
92
144
|
|
|
@@ -6,19 +6,20 @@ from ophyd_async.core import (
|
|
|
6
6
|
AsyncStatus,
|
|
7
7
|
DetectorController,
|
|
8
8
|
DetectorTrigger,
|
|
9
|
+
EnableDisable,
|
|
9
10
|
TriggerInfo,
|
|
10
11
|
observe_value,
|
|
11
12
|
set_and_wait_for_value,
|
|
12
13
|
)
|
|
14
|
+
from ophyd_async.epics.core import stop_busy_record
|
|
13
15
|
|
|
14
16
|
from ._core_io import (
|
|
15
17
|
ADBaseIO,
|
|
16
|
-
ADCallbacks,
|
|
17
18
|
ADState,
|
|
18
19
|
NDCBFlushOnSoftTrgMode,
|
|
19
20
|
NDPluginCBIO,
|
|
20
21
|
)
|
|
21
|
-
from ._utils import ADImageMode
|
|
22
|
+
from ._utils import ADImageMode
|
|
22
23
|
|
|
23
24
|
# Default set of states that we should consider "good" i.e. the acquisition
|
|
24
25
|
# is complete and went well
|
|
@@ -198,7 +199,7 @@ class ADBaseContAcqController(ADBaseController[ADBaseIO]):
|
|
|
198
199
|
|
|
199
200
|
# Configure the CB plugin to collect the correct number of triggers
|
|
200
201
|
await asyncio.gather(
|
|
201
|
-
self.cb_plugin.enable_callbacks.set(
|
|
202
|
+
self.cb_plugin.enable_callbacks.set(EnableDisable.ENABLE),
|
|
202
203
|
self.cb_plugin.pre_count.set(0),
|
|
203
204
|
self.cb_plugin.post_count.set(trigger_info.total_number_of_exposures),
|
|
204
205
|
self.cb_plugin.preset_trigger_count.set(1),
|
|
@@ -12,19 +12,19 @@ from event_model import ( # type: ignore
|
|
|
12
12
|
from pydantic import PositiveInt
|
|
13
13
|
|
|
14
14
|
from ophyd_async.core._detector import DetectorWriter
|
|
15
|
+
from ophyd_async.core._enums import EnableDisable
|
|
15
16
|
from ophyd_async.core._providers import DatasetDescriber, PathInfo, PathProvider
|
|
16
17
|
from ophyd_async.core._signal import (
|
|
17
18
|
observe_value,
|
|
18
19
|
set_and_wait_for_value,
|
|
19
|
-
wait_for_value,
|
|
20
20
|
)
|
|
21
21
|
from ophyd_async.core._status import AsyncStatus
|
|
22
22
|
from ophyd_async.core._utils import DEFAULT_TIMEOUT, error_if_none
|
|
23
|
+
from ophyd_async.epics.core import stop_busy_record
|
|
23
24
|
|
|
24
25
|
# from ophyd_async.epics.adcore._core_logic import ADBaseDatasetDescriber
|
|
25
26
|
from ._core_io import (
|
|
26
27
|
ADBaseDatasetDescriber,
|
|
27
|
-
ADCallbacks,
|
|
28
28
|
NDArrayBaseIO,
|
|
29
29
|
NDFileIO,
|
|
30
30
|
NDFilePluginIO,
|
|
@@ -89,7 +89,7 @@ class ADWriter(DetectorWriter, Generic[NDFileIOT]):
|
|
|
89
89
|
)
|
|
90
90
|
|
|
91
91
|
if isinstance(self.fileio, NDFilePluginIO):
|
|
92
|
-
await self.fileio.enable_callbacks.set(
|
|
92
|
+
await self.fileio.enable_callbacks.set(EnableDisable.ENABLE)
|
|
93
93
|
|
|
94
94
|
# Set the directory creation depth first, since dir creation callback happens
|
|
95
95
|
# when directory path PV is processed.
|
|
@@ -213,8 +213,7 @@ class ADWriter(DetectorWriter, Generic[NDFileIOT]):
|
|
|
213
213
|
|
|
214
214
|
async def close(self):
|
|
215
215
|
# Already done a caput callback in _capture_status, so can't do one here
|
|
216
|
-
await self.fileio.capture
|
|
217
|
-
await wait_for_value(self.fileio.capture, False, DEFAULT_TIMEOUT)
|
|
216
|
+
await stop_busy_record(self.fileio.capture, False, timeout=DEFAULT_TIMEOUT)
|
|
218
217
|
if self._capture_status and not self._capture_status.done:
|
|
219
218
|
# We kicked off an open, so wait for it to return
|
|
220
219
|
await self._capture_status
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
1
2
|
from dataclasses import dataclass
|
|
3
|
+
from xml.etree import ElementTree as ET
|
|
2
4
|
|
|
3
5
|
from ophyd_async.core import (
|
|
4
|
-
DEFAULT_TIMEOUT,
|
|
5
|
-
SignalDatatypeT,
|
|
6
6
|
SignalR,
|
|
7
|
-
SignalRW,
|
|
8
7
|
StrictEnum,
|
|
9
8
|
SubsetEnum,
|
|
10
9
|
SupersetEnum,
|
|
11
|
-
wait_for_value,
|
|
12
10
|
)
|
|
13
11
|
|
|
14
12
|
|
|
@@ -136,10 +134,37 @@ class NDAttributeParam:
|
|
|
136
134
|
description: str = "" # A description that appears in the HDF file as an attribute
|
|
137
135
|
|
|
138
136
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
def ndattributes_to_xml(
|
|
138
|
+
ndattributes: Sequence[NDAttributeParam | NDAttributePv],
|
|
139
|
+
) -> str:
|
|
140
|
+
"""Convert a set of NDAttribute params to XML."""
|
|
141
|
+
root = ET.Element("Attributes")
|
|
142
|
+
for ndattribute in ndattributes:
|
|
143
|
+
if isinstance(ndattribute, NDAttributeParam):
|
|
144
|
+
ET.SubElement(
|
|
145
|
+
root,
|
|
146
|
+
"Attribute",
|
|
147
|
+
name=ndattribute.name,
|
|
148
|
+
type="PARAM",
|
|
149
|
+
source=ndattribute.param,
|
|
150
|
+
addr=str(ndattribute.addr),
|
|
151
|
+
datatype=ndattribute.datatype.value,
|
|
152
|
+
description=ndattribute.description,
|
|
153
|
+
)
|
|
154
|
+
elif isinstance(ndattribute, NDAttributePv):
|
|
155
|
+
ET.SubElement(
|
|
156
|
+
root,
|
|
157
|
+
"Attribute",
|
|
158
|
+
name=ndattribute.name,
|
|
159
|
+
type="EPICS_PV",
|
|
160
|
+
source=ndattribute.signal.source.split("ca://")[-1],
|
|
161
|
+
dbrtype=ndattribute.dbrtype.value,
|
|
162
|
+
description=ndattribute.description,
|
|
163
|
+
)
|
|
164
|
+
else:
|
|
165
|
+
raise ValueError(
|
|
166
|
+
f"Invalid type for ndattributes: {type(ndattribute)}. "
|
|
167
|
+
"Expected NDAttributePv or NDAttributeParam."
|
|
168
|
+
)
|
|
169
|
+
xml_text = ET.tostring(root, encoding="unicode")
|
|
170
|
+
return xml_text
|
|
@@ -4,7 +4,6 @@ from ._vimba_io import (
|
|
|
4
4
|
VimbaConvertFormat,
|
|
5
5
|
VimbaDriverIO,
|
|
6
6
|
VimbaExposeOutMode,
|
|
7
|
-
VimbaOnOff,
|
|
8
7
|
VimbaOverlap,
|
|
9
8
|
VimbaTriggerSource,
|
|
10
9
|
)
|
|
@@ -14,7 +13,6 @@ __all__ = [
|
|
|
14
13
|
"VimbaController",
|
|
15
14
|
"VimbaDriverIO",
|
|
16
15
|
"VimbaExposeOutMode",
|
|
17
|
-
"VimbaOnOff",
|
|
18
16
|
"VimbaTriggerSource",
|
|
19
17
|
"VimbaOverlap",
|
|
20
18
|
"VimbaConvertFormat",
|
{ophyd_async-0.12.2 → ophyd_async-0.13.0}/src/ophyd_async/epics/advimba/_vimba_controller.py
RENAMED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
|
|
3
|
-
from ophyd_async.core import
|
|
4
|
-
DetectorTrigger,
|
|
5
|
-
TriggerInfo,
|
|
6
|
-
)
|
|
3
|
+
from ophyd_async.core import DetectorTrigger, OnOff, TriggerInfo
|
|
7
4
|
from ophyd_async.epics import adcore
|
|
8
5
|
|
|
9
|
-
from ._vimba_io import VimbaDriverIO, VimbaExposeOutMode,
|
|
6
|
+
from ._vimba_io import VimbaDriverIO, VimbaExposeOutMode, VimbaTriggerSource
|
|
10
7
|
|
|
11
8
|
TRIGGER_MODE = {
|
|
12
|
-
DetectorTrigger.INTERNAL:
|
|
13
|
-
DetectorTrigger.CONSTANT_GATE:
|
|
14
|
-
DetectorTrigger.VARIABLE_GATE:
|
|
15
|
-
DetectorTrigger.EDGE_TRIGGER:
|
|
9
|
+
DetectorTrigger.INTERNAL: OnOff.OFF,
|
|
10
|
+
DetectorTrigger.CONSTANT_GATE: OnOff.ON,
|
|
11
|
+
DetectorTrigger.VARIABLE_GATE: OnOff.ON,
|
|
12
|
+
DetectorTrigger.EDGE_TRIGGER: OnOff.ON,
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
EXPOSE_OUT_MODE = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Annotated as A
|
|
2
2
|
|
|
3
|
-
from ophyd_async.core import SignalRW, StrictEnum
|
|
3
|
+
from ophyd_async.core import OnOff, SignalRW, StrictEnum
|
|
4
4
|
from ophyd_async.epics import adcore
|
|
5
5
|
from ophyd_async.epics.core import PvSuffix
|
|
6
6
|
|
|
@@ -30,17 +30,10 @@ class VimbaTriggerSource(StrictEnum):
|
|
|
30
30
|
class VimbaOverlap(StrictEnum):
|
|
31
31
|
"""Overlap modes for the Vimba detector."""
|
|
32
32
|
|
|
33
|
-
OFF =
|
|
33
|
+
OFF = OnOff.OFF
|
|
34
34
|
PREV_FRAME = "PreviousFrame"
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
class VimbaOnOff(StrictEnum):
|
|
38
|
-
"""On/Off modes on the Vimba detector."""
|
|
39
|
-
|
|
40
|
-
ON = "On"
|
|
41
|
-
OFF = "Off"
|
|
42
|
-
|
|
43
|
-
|
|
44
37
|
class VimbaExposeOutMode(StrictEnum):
|
|
45
38
|
"""Exposure control modes for Vimba detectors."""
|
|
46
39
|
|
|
@@ -55,6 +48,6 @@ class VimbaDriverIO(adcore.ADBaseIO):
|
|
|
55
48
|
SignalRW[VimbaConvertFormat], PvSuffix("ConvertPixelFormat")
|
|
56
49
|
]
|
|
57
50
|
trigger_source: A[SignalRW[VimbaTriggerSource], PvSuffix("TriggerSource")]
|
|
58
|
-
trigger_mode: A[SignalRW[
|
|
51
|
+
trigger_mode: A[SignalRW[OnOff], PvSuffix("TriggerMode")]
|
|
59
52
|
trigger_overlap: A[SignalRW[VimbaOverlap], PvSuffix("TriggerOverlap")]
|
|
60
53
|
exposure_mode: A[SignalRW[VimbaExposeOutMode], PvSuffix("ExposureMode")]
|
|
@@ -10,6 +10,7 @@ from ._signal import (
|
|
|
10
10
|
epics_signal_w,
|
|
11
11
|
epics_signal_x,
|
|
12
12
|
)
|
|
13
|
+
from ._util import stop_busy_record
|
|
13
14
|
|
|
14
15
|
__all__ = [
|
|
15
16
|
"PviDeviceConnector",
|
|
@@ -23,4 +24,5 @@ __all__ = [
|
|
|
23
24
|
"epics_signal_rw_rbv",
|
|
24
25
|
"epics_signal_w",
|
|
25
26
|
"epics_signal_x",
|
|
27
|
+
"stop_busy_record",
|
|
26
28
|
]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import os
|
|
2
3
|
import sys
|
|
3
4
|
import typing
|
|
4
5
|
from collections.abc import Mapping, Sequence
|
|
@@ -40,6 +41,10 @@ from ._util import EpicsSignalBackend, format_datatype, get_supported_values
|
|
|
40
41
|
logger = logging.getLogger("ophyd_async")
|
|
41
42
|
|
|
42
43
|
|
|
44
|
+
def _all_updates() -> bool:
|
|
45
|
+
return os.environ.get("OPHYD_ASYNC_EPICS_CA_KEEP_ALL_UPDATES", "True") == "True"
|
|
46
|
+
|
|
47
|
+
|
|
43
48
|
def _limits_from_augmented_value(value: AugmentedValue) -> Limits:
|
|
44
49
|
def get_limits(limit: str) -> LimitsRange | None:
|
|
45
50
|
low = getattr(value, f"lower_{limit}_limit", nan)
|
|
@@ -250,12 +255,11 @@ class CaSignalBackend(EpicsSignalBackend[SignalDatatypeT]):
|
|
|
250
255
|
datatype: type[SignalDatatypeT] | None,
|
|
251
256
|
read_pv: str = "",
|
|
252
257
|
write_pv: str = "",
|
|
253
|
-
all_updates: bool = True,
|
|
254
258
|
):
|
|
255
259
|
self.converter: CaConverter = DisconnectedCaConverter(float, dbr.DBR_DOUBLE)
|
|
256
260
|
self.initial_values: dict[str, AugmentedValue] = {}
|
|
257
261
|
self.subscription: Subscription | None = None
|
|
258
|
-
self._all_updates =
|
|
262
|
+
self._all_updates = _all_updates()
|
|
259
263
|
super().__init__(datatype, read_pv, write_pv)
|
|
260
264
|
|
|
261
265
|
def source(self, name: str, read: bool):
|
|
@@ -4,13 +4,16 @@ from typing import Any, TypeVar, get_args, get_origin
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
|
|
6
6
|
from ophyd_async.core import (
|
|
7
|
+
DEFAULT_TIMEOUT,
|
|
7
8
|
SignalBackend,
|
|
8
9
|
SignalDatatypeT,
|
|
10
|
+
SignalRW,
|
|
9
11
|
StrictEnum,
|
|
10
12
|
SubsetEnum,
|
|
11
13
|
SupersetEnum,
|
|
12
14
|
get_dtype,
|
|
13
15
|
get_enum_cls,
|
|
16
|
+
wait_for_value,
|
|
14
17
|
)
|
|
15
18
|
|
|
16
19
|
T = TypeVar("T")
|
|
@@ -76,3 +79,12 @@ class EpicsSignalBackend(SignalBackend[SignalDatatypeT]):
|
|
|
76
79
|
self.read_pv = read_pv
|
|
77
80
|
self.write_pv = write_pv
|
|
78
81
|
super().__init__(datatype)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
async def stop_busy_record(
|
|
85
|
+
signal: SignalRW[SignalDatatypeT],
|
|
86
|
+
value: SignalDatatypeT,
|
|
87
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
88
|
+
) -> None:
|
|
89
|
+
await signal.set(value, wait=False)
|
|
90
|
+
await wait_for_value(signal, value, timeout=timeout)
|