-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
273 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,67 @@ | ||
Design Goals | ||
============ | ||
# Design goals and differences with ophyd sync | ||
|
||
Ophyd-async was designed to be a library for asynchronously interfacing with hardware. As such it fulfils the same role in the bluesky ecosystem as [ophyd sync](https://github.com/bluesky/ophyd): an abstraction layer that enables experiment orchestration and data acquisition code to operate above the specifics of particular devices and control systems. This document details the design goals and the differences with ophyd sync. | ||
|
||
Parity with Ophyd | ||
----------------- | ||
## Asynchronous Signal access | ||
|
||
It should be possible to migrate applications that use ophyd_ to ophyd-async. Meaning it must support: | ||
A fundamental part of ophyd-async is [](#asyncio). This allows lightweight and deterministic control of multiple signals, making it possible to do the "put 2 PVs in parallel, then get from another PV" logic that is common in flyscanning without the performance and complexity overhead of multiple threads. | ||
|
||
- Definition of devices | ||
- Conformity to the bluesky protocols | ||
- Epics (ChannelAccess) as a backend | ||
For instance, the threaded version of the above looks something like this: | ||
```python | ||
def set_signal_thread(signal, value): | ||
t = Thread(signal.set, value) | ||
t.start() | ||
return | ||
|
||
Ophyd-async should provide built-in support logic for controlling `the same set of devices as ophyd <https://blueskyproject.io/ophyd/user/reference/builtin-devices.html>`_. | ||
def run(): | ||
t1 = set_signal_thread(signal1, value1) | ||
t2 = set_signal_thread(signal2, value2) | ||
t1.join() | ||
t2.join() | ||
value = signal3.get_value() | ||
``` | ||
This gives the overhead of co-ordinating multiple OS threads, which requires events and locking for any more complicated example. | ||
|
||
Compare to the asyncio version: | ||
```python | ||
async def run(): | ||
await asyncio.gather( | ||
signal1.set(value1), | ||
signal2.set(value2) | ||
) | ||
value = await signal3.get_value() | ||
``` | ||
This runs in a single OS thread, but has predictable interrupt behavior, allowing for a much more readable linear flow. | ||
|
||
Clean Device Definition | ||
----------------------- | ||
```{seealso} | ||
[](../how-to/interact-with-signals.md) for examples of the helpers that are easier to write with asyncio. | ||
``` | ||
|
||
It should be easy to define devices with signals that talk to multiple backends and to cleanly organize device logic via composition. | ||
## Support for CA, PVA, Tango | ||
|
||
We need to be able to: | ||
As well as the tradition EPICS Channel Access, ophyd-async was written to allow other Control system protocols, like EPICS PV Access and Tango. An ophyd-async [](#Signal) contains no control system specific logic, but takes a [](#SignalBackend) that it uses whenever it needs to talk to the control system. Likewise at the [](#Device) level, a [](#DeviceConnector) allows control systems to fulfil the type hints of [declarative devices](./declarative-vs-procedural.md). | ||
|
||
- Separate the Device interface from the multiple pieces of logic that might use that Device in a particular way | ||
- Define that Signals of a particular type exist without creating them so backends like Tango or EPICS + PVI can fill them in | ||
```{seealso} | ||
[](./devices-signals-backends.md) for more information on how these fit together, and [](../tutorials/implementing-devices.md) for examples of Devices in different control systems. | ||
``` | ||
|
||
## Clean Device Definition | ||
|
||
Parity with Malcolm | ||
------------------- | ||
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. | ||
|
||
.. seealso:: `./flyscanning` | ||
## Ease the implementation of flyscanning | ||
|
||
Ophyd-async should provide the same building blocks for defining flyscans scans as malcolm_. It should support PandA and Zebra as timing masters by default, but also provide easy helpers for developers to write support for their own devices. | ||
One of the major drivers for ophyd-async was to ease the implementation of flyscanning. A library of flyscanning helpers is being developed to aid such strategies as: | ||
- Definition of scan paths via [ScanSpec](https://github.com/dls-controls/scanspec) | ||
- PVT Trajectory scanning in [Delta Tau motion controllers](https://github.com/dls-controls/pmac) | ||
- Position compare and capture using a [PandABox](https://quantumdetectors.com/products/pandabox) | ||
|
||
It should enable motor trajectory scanning and multiple triggering rates based around a base rate, and pausing/resuming scans. Scans should be modelled using scanspec_, which serves as a universal language for defining trajectory and time-resolved scans, and converted to the underlying format of the given motion controller. It should also be possible to define an outer scan . | ||
These strategies will be ported from DLS's previous flyscanning software [Malcolm](https://github.com/dls-controls/pymalcolm) and improved to take advantage of the flexibility of bluesky's plan definitions. | ||
|
||
```{seealso} | ||
The documents on flyscanning in the [bluesky cookbook](http://blueskyproject.io/bluesky-cookbook/glossary/flyscanning.html) | ||
``` | ||
|
||
Improved Trajectory Calculation | ||
------------------------------- | ||
## Parity and interoperativity with ophyd sync | ||
|
||
Ophyd-async will provide and improve upon the algorithms that malcolm_ uses to calculate trajectories for supported hardware. | ||
|
||
The EPICS pmac_ module supports trajectory scanning, specifying a growing array of positions, velocities and time for axes to move through to perform a scan. | ||
Ophyd-async will provide mechanisms for specifying these scans via a scanspec_, calculating run-ups and turnarounds based on motor parameters, keeping the trajectory scan arrays filled based on the ScanSpec, and allowing this scan to be paused and resumed. | ||
|
||
|
||
Outstanding Design Decisions | ||
---------------------------- | ||
|
||
To view and contribute to discussions on outstanding decisions, please see the design_ label in our Github issues. | ||
|
||
|
||
.. _ophyd: https://github.com/bluesky/ophyd | ||
.. _malcolm: https://github.com/dls-controls/pymalcolm | ||
.. _scanspec: https://github.com/dls-controls/scanspec | ||
.. _design: https://github.com/bluesky/ophyd-async/issues?q=is%3Aissue+is%3Aopen+label%3Adesign | ||
.. _pmac: https://github.com/dls-controls/pmac | ||
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. Eventually ophyd sync will gain feature parity with ophyd sync, supporting [the same set of devices as ophyd](https://blueskyproject.io/ophyd/user/reference/builtin-devices.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Devices, Signals and their Backends | ||
|
||
```{autoclasstree} ophyd_async.core.SignalRW ophyd_async.core.SignalR | ||
``` |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,33 @@ | ||
# Decision Flowchart for Creating a New ophyd_async Device | ||
# How to choose the right base class when implementing a new Device | ||
|
||
This document contains a decision flowchart designed to guide developers through the process of creating a new ophyd_async device in the Ophyd library. It outlines a series of decisions based on the device's capabilities, such as file writing, reading values from process variables (PVs), and mobility within scans. The flowchart helps in determining the appropriate class inheritance and methods to override for optimal device functionality and integration into the system. | ||
When writing a new Device there are several base classes to choose from that will give you certain functionality. This document details how to choose between them, and the next steps to take to implement your Device. | ||
|
||
```{mermaid} | ||
flowchart TD | ||
start([Start]) --> isFileWriting{Is it a File Writing Detector?} | ||
isFileWriting -- Yes --> useStandardDetector[Use StandardDetector] | ||
isFileWriting -- No --> producesPVValue{Does it produce a value from a PV you want to read in a scan?} | ||
producesPVValue -- Yes --> isMovable{Is it something that you move in a scan?} | ||
isMovable -- Yes --> useReadableMovable[Use StandardReadable + AsyncMovable + Override set method] | ||
isMovable -- No --> useReadable[Use StandardReadable] | ||
producesPVValue -- No --> useDevice[Use Device] | ||
```{seealso} | ||
[](../tutorials/implementing-devices.md) gives some examples of how these baseclass might be used | ||
``` | ||
|
||
## Utility baseclasses | ||
|
||
There are some utility baseclasses that allow you to create a Device pre-populated with the right verbs to work in bluesky plans: | ||
|
||
- [](#StandardReadable) allows you to compose the values of child Signals and Devices together so that you can `read()` the Device during a step scan. | ||
- [](#StandardDetector) allows file-writing detectors to be used within both step and flyscans, reporting periodic references to the data that has been written so far. An instance of a [](#DetectorController) and a [](#DetectorWriter) are required to provide this functionality. | ||
- [](#StandardFlyer) allows actuators (like a motor controller) to be used within a flyscan. Implementing a [](#FlyerController) is required to provide this functionality. | ||
|
||
## Adding verbs via protocols | ||
|
||
There are some [bluesky protocols](inv:bluesky#hardware) that show the verbs you can implement to add functionality in standard plans. For example: | ||
|
||
- [](#bluesky.protocols.Movable) to add behavior during `bps.mv` and `bps.abs_set` | ||
- [](#bluesky.protocols.Triggerable) to add behavior before `read()` in `bps.scan` | ||
|
||
It is not strictly required to add the protocol class as a baseclass (the presence of a method with the right signature is all that is required) but generally this is done so that the IDE gives you help when filling in the method, and the type checker knows to check that you have filled it in correctly. | ||
|
||
## Control system specific baseclass | ||
|
||
It is possible to create [procedural devices](../explanations/declarative-vs-procedural.md) using just [](#Device) as a baseclass, but if you wish to make a declarative Device then you need a control system specific baseclass: | ||
|
||
- [](#EpicsDevice) for EPICS CA and PVA devices | ||
- [](#TangoDevice) for Tango devices | ||
|
||
If you are creating a [](#StandardDetector) then multiple inheritance of that and the control system specific baseclass makes initialization order tricky, so you should use [](#TangoConnector), [](#EpicsConnector), [](#PviConnector) or [](#fastcs_connector) and pass it into the `super().__init__` rather than using the control system specific baseclass. An example of this is [](#HDFPanda). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,17 @@ | ||
# How to implement a Device for an EPICS areaDetector | ||
|
||
This document will walk through the steps taken to implement an ophyd-async Device that talks to an EPICS areaDetector | ||
|
||
## Create a module to put the code in | ||
|
||
The first stage is to make a module in the `ophyd-async` repository to put the code in: | ||
|
||
- If you haven't already, `git clone [email protected]:bluesky/ophyd-async.git` and make a new branch to work in | ||
- Create a new directory under `src/ophyd_async/epics/` which is the lowercase version of the epics support module for the detector | ||
- For example, for [`ADSimDetector`](https://github.com/areaDetector/ADSimDetector) make a directory `adsimdetector` | ||
- Make an empty `__init__.py` within that directory | ||
|
||
|
||
.. note:: | ||
|
||
Ophyd async is included on a provisional basis until the v1.0 release and | ||
|
Oops, something went wrong.