ophyd-async 0.3a5__py3-none-any.whl → 0.3rc2__py3-none-any.whl
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/_version.py +1 -1
- ophyd_async/core/__init__.py +7 -5
- ophyd_async/core/async_status.py +11 -28
- ophyd_async/core/detector.py +1 -1
- ophyd_async/core/device.py +2 -4
- ophyd_async/core/flyer.py +1 -1
- ophyd_async/core/mock_signal_backend.py +5 -8
- ophyd_async/core/mock_signal_utils.py +10 -14
- ophyd_async/core/signal.py +23 -17
- ophyd_async/core/signal_backend.py +1 -1
- ophyd_async/core/utils.py +11 -0
- ophyd_async/epics/areadetector/drivers/ad_base.py +1 -7
- ophyd_async/epics/areadetector/writers/hdf_writer.py +3 -2
- ophyd_async/epics/areadetector/writers/nd_file_hdf.py +0 -2
- ophyd_async/epics/areadetector/writers/nd_plugin.py +9 -0
- ophyd_async/epics/demo/__init__.py +30 -26
- ophyd_async/epics/motion/motor.py +35 -29
- ophyd_async/panda/__init__.py +2 -0
- ophyd_async/panda/writers/_hdf_writer.py +4 -4
- ophyd_async/{planstubs → plan_stubs}/__init__.py +5 -1
- ophyd_async/plan_stubs/fly.py +149 -0
- ophyd_async/sim/demo/sim_motor.py +56 -86
- {ophyd_async-0.3a5.dist-info → ophyd_async-0.3rc2.dist-info}/METADATA +1 -1
- {ophyd_async-0.3a5.dist-info → ophyd_async-0.3rc2.dist-info}/RECORD +29 -29
- ophyd_async/planstubs/prepare_trigger_and_dets.py +0 -57
- /ophyd_async/{planstubs → plan_stubs}/ensure_connected.py +0 -0
- {ophyd_async-0.3a5.dist-info → ophyd_async-0.3rc2.dist-info}/LICENSE +0 -0
- {ophyd_async-0.3a5.dist-info → ophyd_async-0.3rc2.dist-info}/WHEEL +0 -0
- {ophyd_async-0.3a5.dist-info → ophyd_async-0.3rc2.dist-info}/entry_points.txt +0 -0
- {ophyd_async-0.3a5.dist-info → ophyd_async-0.3rc2.dist-info}/top_level.txt +0 -0
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from dataclasses import replace
|
|
3
2
|
|
|
4
3
|
from bluesky.protocols import Movable, Stoppable
|
|
5
4
|
|
|
6
5
|
from ophyd_async.core import (
|
|
7
|
-
AsyncStatus,
|
|
8
6
|
ConfigSignal,
|
|
9
7
|
HintedSignal,
|
|
10
8
|
StandardReadable,
|
|
11
9
|
WatchableAsyncStatus,
|
|
12
10
|
)
|
|
13
11
|
from ophyd_async.core.signal import observe_value
|
|
14
|
-
from ophyd_async.core.utils import
|
|
12
|
+
from ophyd_async.core.utils import (
|
|
13
|
+
DEFAULT_TIMEOUT,
|
|
14
|
+
CalculatableTimeout,
|
|
15
|
+
CalculateTimeout,
|
|
16
|
+
WatcherUpdate,
|
|
17
|
+
)
|
|
15
18
|
|
|
16
19
|
from ..signal.signal import epics_signal_r, epics_signal_rw, epics_signal_x
|
|
17
20
|
|
|
@@ -47,42 +50,45 @@ class Motor(StandardReadable, Movable, Stoppable):
|
|
|
47
50
|
# Readback should be named the same as its parent in read()
|
|
48
51
|
self.user_readback.set_name(name)
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
@WatchableAsyncStatus.wrap
|
|
54
|
+
async def set(
|
|
55
|
+
self, new_position: float, timeout: CalculatableTimeout = CalculateTimeout
|
|
56
|
+
):
|
|
53
57
|
self._set_success = True
|
|
54
|
-
|
|
58
|
+
(
|
|
59
|
+
old_position,
|
|
60
|
+
units,
|
|
61
|
+
precision,
|
|
62
|
+
velocity,
|
|
63
|
+
acceleration_time,
|
|
64
|
+
) = await asyncio.gather(
|
|
55
65
|
self.user_setpoint.get_value(),
|
|
56
66
|
self.motor_egu.get_value(),
|
|
57
67
|
self.precision.get_value(),
|
|
68
|
+
self.velocity.get_value(),
|
|
69
|
+
self.acceleration_time.get_value(),
|
|
58
70
|
)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
unit=units,
|
|
68
|
-
precision=precision,
|
|
69
|
-
),
|
|
70
|
-
move_status,
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
@WatchableAsyncStatus.wrap
|
|
74
|
-
async def set(self, new_position: float, timeout: float | None = None):
|
|
75
|
-
update, move_status = await self._move(new_position)
|
|
71
|
+
if timeout is CalculateTimeout:
|
|
72
|
+
assert velocity > 0, "Motor has zero velocity"
|
|
73
|
+
timeout = (
|
|
74
|
+
abs(new_position - old_position) / velocity
|
|
75
|
+
+ 2 * acceleration_time
|
|
76
|
+
+ DEFAULT_TIMEOUT
|
|
77
|
+
)
|
|
78
|
+
move_status = self.user_setpoint.set(new_position, wait=True, timeout=timeout)
|
|
76
79
|
async for current_position in observe_value(
|
|
77
80
|
self.user_readback, done_status=move_status
|
|
78
81
|
):
|
|
79
|
-
|
|
80
|
-
raise RuntimeError("Motor was stopped")
|
|
81
|
-
yield replace(
|
|
82
|
-
update,
|
|
83
|
-
name=self.name,
|
|
82
|
+
yield WatcherUpdate(
|
|
84
83
|
current=current_position,
|
|
84
|
+
initial=old_position,
|
|
85
|
+
target=new_position,
|
|
86
|
+
name=self.name,
|
|
87
|
+
unit=units,
|
|
88
|
+
precision=precision,
|
|
85
89
|
)
|
|
90
|
+
if not self._set_success:
|
|
91
|
+
raise RuntimeError("Motor was stopped")
|
|
86
92
|
|
|
87
93
|
async def stop(self, success=False):
|
|
88
94
|
self._set_success = success
|
ophyd_async/panda/__init__.py
CHANGED
|
@@ -15,6 +15,7 @@ from ._table import (
|
|
|
15
15
|
seq_table_from_arrays,
|
|
16
16
|
seq_table_from_rows,
|
|
17
17
|
)
|
|
18
|
+
from ._trigger import StaticSeqTableTriggerLogic
|
|
18
19
|
from ._utils import phase_sorter
|
|
19
20
|
|
|
20
21
|
__all__ = [
|
|
@@ -33,4 +34,5 @@ __all__ = [
|
|
|
33
34
|
"TimeUnits",
|
|
34
35
|
"DataBlock",
|
|
35
36
|
"CommonPandABlocks",
|
|
37
|
+
"StaticSeqTableTriggerLogic",
|
|
36
38
|
]
|
|
@@ -79,10 +79,10 @@ async def get_signals_marked_for_capture(
|
|
|
79
79
|
capture_signals.keys(), capture_signals.values(), signal_values
|
|
80
80
|
):
|
|
81
81
|
signal_path = signal_path.replace("_capture", "")
|
|
82
|
-
if (signal_value
|
|
82
|
+
if (signal_value in iter(Capture)) and (signal_value != Capture.No):
|
|
83
83
|
signals_to_capture[signal_path] = CaptureSignalWrapper(
|
|
84
84
|
signal_object,
|
|
85
|
-
signal_value
|
|
85
|
+
signal_value,
|
|
86
86
|
)
|
|
87
87
|
|
|
88
88
|
return signals_to_capture
|
|
@@ -126,7 +126,7 @@ class PandaHDFWriter(DetectorWriter):
|
|
|
126
126
|
str(info.root / info.resource_dir)
|
|
127
127
|
),
|
|
128
128
|
self.panda_device.data.hdf_file_name.set(
|
|
129
|
-
f"{info.prefix}{self.panda_device.name}{info.suffix}",
|
|
129
|
+
f"{info.prefix}{self.panda_device.name}{info.suffix}.h5",
|
|
130
130
|
),
|
|
131
131
|
self.panda_device.data.num_capture.set(0),
|
|
132
132
|
)
|
|
@@ -149,7 +149,7 @@ class PandaHDFWriter(DetectorWriter):
|
|
|
149
149
|
else split_path[-2]
|
|
150
150
|
)
|
|
151
151
|
|
|
152
|
-
for suffix in
|
|
152
|
+
for suffix in capture_signal.capture_type.split(" "):
|
|
153
153
|
self._datasets.append(
|
|
154
154
|
_HDFDataset(
|
|
155
155
|
name,
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
from .ensure_connected import ensure_connected
|
|
2
|
-
from .
|
|
2
|
+
from .fly import (
|
|
3
|
+
fly_and_collect,
|
|
3
4
|
prepare_static_seq_table_flyer_and_detectors_with_same_trigger,
|
|
5
|
+
time_resolved_fly_and_collect_with_static_seq_table,
|
|
4
6
|
)
|
|
5
7
|
|
|
6
8
|
__all__ = [
|
|
9
|
+
"fly_and_collect",
|
|
7
10
|
"prepare_static_seq_table_flyer_and_detectors_with_same_trigger",
|
|
11
|
+
"time_resolved_fly_and_collect_with_static_seq_table",
|
|
8
12
|
"ensure_connected",
|
|
9
13
|
]
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
import bluesky.plan_stubs as bps
|
|
4
|
+
from bluesky.utils import short_uid
|
|
5
|
+
|
|
6
|
+
from ophyd_async.core.detector import DetectorTrigger, StandardDetector, TriggerInfo
|
|
7
|
+
from ophyd_async.core.flyer import HardwareTriggeredFlyable
|
|
8
|
+
from ophyd_async.core.utils import in_micros
|
|
9
|
+
from ophyd_async.panda._table import SeqTable, SeqTableRow, seq_table_from_rows
|
|
10
|
+
from ophyd_async.panda._trigger import SeqTableInfo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
|
|
14
|
+
flyer: HardwareTriggeredFlyable[SeqTableInfo],
|
|
15
|
+
detectors: List[StandardDetector],
|
|
16
|
+
number_of_frames: int,
|
|
17
|
+
exposure: float,
|
|
18
|
+
shutter_time: float,
|
|
19
|
+
repeats: int = 1,
|
|
20
|
+
period: float = 0.0,
|
|
21
|
+
):
|
|
22
|
+
"""Prepare a hardware triggered flyable and one or more detectors.
|
|
23
|
+
|
|
24
|
+
Prepare a hardware triggered flyable and one or more detectors with the
|
|
25
|
+
same trigger. This method constructs TriggerInfo and a static sequence
|
|
26
|
+
table from required parameters. The table is required to prepare the flyer,
|
|
27
|
+
and the TriggerInfo is required to prepare the detector(s).
|
|
28
|
+
|
|
29
|
+
This prepares all supplied detectors with the same trigger.
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
if not detectors:
|
|
33
|
+
raise ValueError("No detectors provided. There must be at least one.")
|
|
34
|
+
|
|
35
|
+
deadtime = max(det.controller.get_deadtime(exposure) for det in detectors)
|
|
36
|
+
|
|
37
|
+
trigger_info = TriggerInfo(
|
|
38
|
+
num=number_of_frames * repeats,
|
|
39
|
+
trigger=DetectorTrigger.constant_gate,
|
|
40
|
+
deadtime=deadtime,
|
|
41
|
+
livetime=exposure,
|
|
42
|
+
)
|
|
43
|
+
trigger_time = number_of_frames * (exposure + deadtime)
|
|
44
|
+
pre_delay = max(period - 2 * shutter_time - trigger_time, 0)
|
|
45
|
+
|
|
46
|
+
table: SeqTable = seq_table_from_rows(
|
|
47
|
+
# Wait for pre-delay then open shutter
|
|
48
|
+
SeqTableRow(
|
|
49
|
+
time1=in_micros(pre_delay),
|
|
50
|
+
time2=in_micros(shutter_time),
|
|
51
|
+
outa2=True,
|
|
52
|
+
),
|
|
53
|
+
# Keeping shutter open, do N triggers
|
|
54
|
+
SeqTableRow(
|
|
55
|
+
repeats=number_of_frames,
|
|
56
|
+
time1=in_micros(exposure),
|
|
57
|
+
outa1=True,
|
|
58
|
+
outb1=True,
|
|
59
|
+
time2=in_micros(deadtime),
|
|
60
|
+
outa2=True,
|
|
61
|
+
),
|
|
62
|
+
# Add the shutter close
|
|
63
|
+
SeqTableRow(time2=in_micros(shutter_time)),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
table_info = SeqTableInfo(table, repeats)
|
|
67
|
+
|
|
68
|
+
for det in detectors:
|
|
69
|
+
yield from bps.prepare(det, trigger_info, wait=False, group="prep")
|
|
70
|
+
yield from bps.prepare(flyer, table_info, wait=False, group="prep")
|
|
71
|
+
yield from bps.wait(group="prep")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def fly_and_collect(
|
|
75
|
+
stream_name: str,
|
|
76
|
+
flyer: HardwareTriggeredFlyable[SeqTableInfo],
|
|
77
|
+
detectors: List[StandardDetector],
|
|
78
|
+
):
|
|
79
|
+
"""Kickoff, complete and collect with a flyer and multiple detectors.
|
|
80
|
+
|
|
81
|
+
This stub takes a flyer and one or more detectors that have been prepared. It
|
|
82
|
+
declares a stream for the detectors, then kicks off the detectors and the flyer.
|
|
83
|
+
The detectors are collected until the flyer and detectors have completed.
|
|
84
|
+
|
|
85
|
+
"""
|
|
86
|
+
yield from bps.declare_stream(*detectors, name=stream_name, collect=True)
|
|
87
|
+
yield from bps.kickoff(flyer, wait=True)
|
|
88
|
+
for detector in detectors:
|
|
89
|
+
yield from bps.kickoff(detector)
|
|
90
|
+
|
|
91
|
+
# collect_while_completing
|
|
92
|
+
group = short_uid(label="complete")
|
|
93
|
+
|
|
94
|
+
yield from bps.complete(flyer, wait=False, group=group)
|
|
95
|
+
for detector in detectors:
|
|
96
|
+
yield from bps.complete(detector, wait=False, group=group)
|
|
97
|
+
|
|
98
|
+
done = False
|
|
99
|
+
while not done:
|
|
100
|
+
try:
|
|
101
|
+
yield from bps.wait(group=group, timeout=0.5)
|
|
102
|
+
except TimeoutError:
|
|
103
|
+
pass
|
|
104
|
+
else:
|
|
105
|
+
done = True
|
|
106
|
+
yield from bps.collect(
|
|
107
|
+
*detectors,
|
|
108
|
+
return_payload=False,
|
|
109
|
+
name=stream_name,
|
|
110
|
+
)
|
|
111
|
+
yield from bps.wait(group=group)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def time_resolved_fly_and_collect_with_static_seq_table(
|
|
115
|
+
stream_name: str,
|
|
116
|
+
flyer: HardwareTriggeredFlyable[SeqTableInfo],
|
|
117
|
+
detectors: List[StandardDetector],
|
|
118
|
+
number_of_frames: int,
|
|
119
|
+
exposure: float,
|
|
120
|
+
shutter_time: float,
|
|
121
|
+
repeats: int = 1,
|
|
122
|
+
period: float = 0.0,
|
|
123
|
+
):
|
|
124
|
+
"""Run a scan wth a flyer and multiple detectors.
|
|
125
|
+
|
|
126
|
+
The stub demonstrates the standard basic flow for a flyscan:
|
|
127
|
+
|
|
128
|
+
- Prepare the flyer and detectors with a trigger
|
|
129
|
+
- Fly and collect:
|
|
130
|
+
- Declare the stream and kickoff the scan
|
|
131
|
+
- Collect while completing
|
|
132
|
+
|
|
133
|
+
This needs to be used in a plan that instantates detectors and a flyer,
|
|
134
|
+
stages/unstages the devices, and opens and closes the run.
|
|
135
|
+
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
# Set up scan and prepare trigger
|
|
139
|
+
yield from prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
|
|
140
|
+
flyer,
|
|
141
|
+
detectors,
|
|
142
|
+
number_of_frames=number_of_frames,
|
|
143
|
+
exposure=exposure,
|
|
144
|
+
shutter_time=shutter_time,
|
|
145
|
+
repeats=repeats,
|
|
146
|
+
period=period,
|
|
147
|
+
)
|
|
148
|
+
# Run the fly scan
|
|
149
|
+
yield from fly_and_collect(stream_name, flyer, detectors)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import contextlib
|
|
2
3
|
import time
|
|
3
|
-
from dataclasses import replace
|
|
4
4
|
|
|
5
5
|
from bluesky.protocols import Movable, Stoppable
|
|
6
6
|
|
|
@@ -25,109 +25,79 @@ class SimMotor(StandardReadable, Movable, Stoppable):
|
|
|
25
25
|
- name: str: name of device
|
|
26
26
|
- instant: bool: whether to move instantly, or with a delay
|
|
27
27
|
"""
|
|
28
|
+
# Define some signals
|
|
28
29
|
with self.add_children_as_readables(HintedSignal):
|
|
29
30
|
self.user_readback, self._user_readback_set = soft_signal_r_and_setter(
|
|
30
31
|
float, 0
|
|
31
32
|
)
|
|
32
|
-
|
|
33
33
|
with self.add_children_as_readables(ConfigSignal):
|
|
34
|
-
self.velocity = soft_signal_rw(float, 1.0)
|
|
35
|
-
self.
|
|
36
|
-
|
|
37
|
-
self._instant = instant
|
|
38
|
-
self._move_status: AsyncStatus | None = None
|
|
39
|
-
|
|
40
|
-
# Define some signals
|
|
34
|
+
self.velocity = soft_signal_rw(float, 0 if instant else 1.0)
|
|
35
|
+
self.units = soft_signal_rw(str, "mm")
|
|
41
36
|
self.user_setpoint = soft_signal_rw(float, 0)
|
|
42
37
|
|
|
43
|
-
super().__init__(name=name)
|
|
44
|
-
|
|
45
38
|
# Whether set() should complete successfully or not
|
|
46
39
|
self._set_success = True
|
|
40
|
+
self._move_status: AsyncStatus | None = None
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
"""
|
|
50
|
-
Stop the motor if it is moving
|
|
51
|
-
"""
|
|
52
|
-
if self._move_status:
|
|
53
|
-
self._move_status.task.cancel()
|
|
54
|
-
self._move_status = None
|
|
42
|
+
super().__init__(name=name)
|
|
55
43
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
44
|
+
async def _move(self, old_position: float, new_position: float, move_time: float):
|
|
45
|
+
start = time.monotonic()
|
|
46
|
+
distance = abs(new_position - old_position)
|
|
47
|
+
while True:
|
|
48
|
+
time_elapsed = round(time.monotonic() - start, 2)
|
|
60
49
|
|
|
61
|
-
|
|
50
|
+
# update position based on time elapsed
|
|
51
|
+
if time_elapsed >= move_time:
|
|
52
|
+
# successfully reached our target position
|
|
53
|
+
self._user_readback_set(new_position)
|
|
54
|
+
break
|
|
55
|
+
else:
|
|
56
|
+
current_position = old_position + distance * time_elapsed / move_time
|
|
62
57
|
|
|
63
|
-
|
|
58
|
+
self._user_readback_set(current_position)
|
|
59
|
+
|
|
60
|
+
# 10hz update loop
|
|
61
|
+
await asyncio.sleep(0.1)
|
|
64
62
|
|
|
65
63
|
@WatchableAsyncStatus.wrap
|
|
66
|
-
async def set(self, new_position: float
|
|
64
|
+
async def set(self, new_position: float):
|
|
67
65
|
"""
|
|
68
66
|
Asynchronously move the motor to a new position.
|
|
69
67
|
"""
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
):
|
|
74
|
-
if not self._set_success:
|
|
75
|
-
raise RuntimeError("Motor was stopped")
|
|
76
|
-
yield replace(
|
|
77
|
-
update,
|
|
78
|
-
name=self.name,
|
|
79
|
-
current=current_position,
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
async def _move(self, new_position: float, timeout: float | None = None):
|
|
83
|
-
"""
|
|
84
|
-
Start the motor moving to a new position.
|
|
85
|
-
|
|
86
|
-
If the motor is already moving, it will stop first.
|
|
87
|
-
If this is an instant motor the move will be instantaneous.
|
|
88
|
-
"""
|
|
89
|
-
self.stop()
|
|
90
|
-
start = time.monotonic()
|
|
91
|
-
self._set_success = True
|
|
92
|
-
|
|
93
|
-
current_position = await self.user_readback.get_value()
|
|
94
|
-
distance = abs(new_position - current_position)
|
|
95
|
-
travel_time = 0 if self._instant else distance / await self.velocity.get_value()
|
|
96
|
-
|
|
97
|
-
old_position, units = await asyncio.gather(
|
|
68
|
+
# Make sure any existing move tasks are stopped
|
|
69
|
+
await self.stop()
|
|
70
|
+
old_position, units, velocity = await asyncio.gather(
|
|
98
71
|
self.user_setpoint.get_value(),
|
|
99
|
-
self.
|
|
72
|
+
self.units.get_value(),
|
|
73
|
+
self.velocity.get_value(),
|
|
100
74
|
)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
# update position based on time elapsed
|
|
107
|
-
if time_elapsed >= travel_time:
|
|
108
|
-
# successfully reached our target position
|
|
109
|
-
self._user_readback_set(new_position)
|
|
110
|
-
self._set_success = True
|
|
111
|
-
break
|
|
112
|
-
else:
|
|
113
|
-
current_position = (
|
|
114
|
-
old_position + distance * time_elapsed / travel_time
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
self._user_readback_set(current_position)
|
|
118
|
-
|
|
119
|
-
# 10hz update loop
|
|
120
|
-
await asyncio.sleep(0.1)
|
|
121
|
-
|
|
122
|
-
# set up a task that updates the motor position at ~10hz
|
|
123
|
-
self._move_status = AsyncStatus(asyncio.wait_for(update_position(), timeout))
|
|
124
|
-
|
|
125
|
-
return (
|
|
126
|
-
WatcherUpdate(
|
|
127
|
-
initial=old_position,
|
|
128
|
-
current=old_position,
|
|
129
|
-
target=new_position,
|
|
130
|
-
unit=units,
|
|
131
|
-
),
|
|
132
|
-
self._move_status,
|
|
75
|
+
# If zero velocity, do instant move
|
|
76
|
+
move_time = abs(new_position - old_position) / velocity if velocity else 0
|
|
77
|
+
self._move_status = AsyncStatus(
|
|
78
|
+
self._move(old_position, new_position, move_time)
|
|
133
79
|
)
|
|
80
|
+
# If stop is called then this will raise a CancelledError, ignore it
|
|
81
|
+
with contextlib.suppress(asyncio.CancelledError):
|
|
82
|
+
async for current_position in observe_value(
|
|
83
|
+
self.user_readback, done_status=self._move_status
|
|
84
|
+
):
|
|
85
|
+
yield WatcherUpdate(
|
|
86
|
+
current=current_position,
|
|
87
|
+
initial=old_position,
|
|
88
|
+
target=new_position,
|
|
89
|
+
name=self.name,
|
|
90
|
+
unit=units,
|
|
91
|
+
)
|
|
92
|
+
if not self._set_success:
|
|
93
|
+
raise RuntimeError("Motor was stopped")
|
|
94
|
+
|
|
95
|
+
async def stop(self, success=True):
|
|
96
|
+
"""
|
|
97
|
+
Stop the motor if it is moving
|
|
98
|
+
"""
|
|
99
|
+
self._set_success = success
|
|
100
|
+
if self._move_status:
|
|
101
|
+
self._move_status.task.cancel()
|
|
102
|
+
self._move_status = None
|
|
103
|
+
await self.user_setpoint.set(await self.user_readback.get_value())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3rc2
|
|
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
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
ophyd_async/__init__.py,sha256=v-rRiDOgZ3sQSMQKq0vgUQZvpeOkoHFXissAx6Ktg84,61
|
|
2
2
|
ophyd_async/__main__.py,sha256=G-Zcv_G9zK7Nhx6o5L5w-wyhMxdl_WgyMELu8IMFqAE,328
|
|
3
|
-
ophyd_async/_version.py,sha256=
|
|
3
|
+
ophyd_async/_version.py,sha256=Q6NCoABIZDCaoLXsuU8odM9VJngCLNAvP46RIhMvPN0,409
|
|
4
4
|
ophyd_async/log.py,sha256=DbMjt0bkfUOLHIinZYt0Q0FHZmCXXi5x8y0uFiEmqoQ,3587
|
|
5
5
|
ophyd_async/protocols.py,sha256=EF2W9nfElV-0QNMYrX1zusL1PqDJR3kNsjlalR29j0I,3412
|
|
6
|
-
ophyd_async/core/__init__.py,sha256=
|
|
6
|
+
ophyd_async/core/__init__.py,sha256=znjVeRfrDVJbGLEkUczeKMW46kV6HDrlE4lV0SqvZt4,2952
|
|
7
7
|
ophyd_async/core/_providers.py,sha256=LrlTMPHKXWOPVkpAOw-pqBq0kip-c3C9ZZPoFfiaV4M,2212
|
|
8
|
-
ophyd_async/core/async_status.py,sha256=
|
|
9
|
-
ophyd_async/core/detector.py,sha256=
|
|
10
|
-
ophyd_async/core/device.py,sha256=
|
|
8
|
+
ophyd_async/core/async_status.py,sha256=9TOgOXIAuH62RDo5t-Y5GdjrJ76d_6TFlBxYv-5_a88,4367
|
|
9
|
+
ophyd_async/core/detector.py,sha256=8mdLKphirgit5CVCklJI9eHqKKiCz4CYs9BElo10-lc,11007
|
|
10
|
+
ophyd_async/core/device.py,sha256=280zFnLCoiMZAA-Dh1_AjUSnhxUfKYGgj4H_2S1njOA,7086
|
|
11
11
|
ophyd_async/core/device_save_loader.py,sha256=RXA3dPUPihAR2ZGDStlGiA-TAsr_xqL0snsCjMsMnfA,9138
|
|
12
|
-
ophyd_async/core/flyer.py,sha256=
|
|
13
|
-
ophyd_async/core/mock_signal_backend.py,sha256=
|
|
14
|
-
ophyd_async/core/mock_signal_utils.py,sha256=
|
|
15
|
-
ophyd_async/core/signal.py,sha256=
|
|
16
|
-
ophyd_async/core/signal_backend.py,sha256=
|
|
12
|
+
ophyd_async/core/flyer.py,sha256=bIjzBkrl8HVAlKgsZ_FF0WL69Qvksyzp9ZWmTLl8Yrw,2304
|
|
13
|
+
ophyd_async/core/mock_signal_backend.py,sha256=Ug6jK72wm9vM6EueoUrYgcXtiFzdPUEISRe86LdyYKc,2844
|
|
14
|
+
ophyd_async/core/mock_signal_utils.py,sha256=bF8MVZA1j9zCmS2tBbgUdfwNmcHniHixnmotjd0g7hs,4083
|
|
15
|
+
ophyd_async/core/signal.py,sha256=FbTb5qDPLhVxEbh6gimqXfkZwcqB4ymHTEYVXZVZYrk,16456
|
|
16
|
+
ophyd_async/core/signal_backend.py,sha256=fT3q0WED3JHmNKYCs7PzDLCK4cUPVin3wQjDNPdHqAY,1525
|
|
17
17
|
ophyd_async/core/soft_signal_backend.py,sha256=56zvcEi4c8n1yYbafTbp7X0VhSkhoehm3L8RBhu2fik,5596
|
|
18
18
|
ophyd_async/core/standard_readable.py,sha256=uVG3vs3s7-Kzg5dRCtT4I2mhZPqwVGYy2dxNmaOpDVU,8980
|
|
19
|
-
ophyd_async/core/utils.py,sha256=
|
|
19
|
+
ophyd_async/core/utils.py,sha256=3oZcXNqAUHX4ZWMBH5gSuK6cFWEhSkZ9GSDYv0pf8jc,5783
|
|
20
20
|
ophyd_async/epics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
ophyd_async/epics/_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
ophyd_async/epics/_backend/_aioca.py,sha256=cpPNZmRMi7FnAh2-3ec5uklLVFOqsmEmpI1nh5Ud1Ls,8794
|
|
@@ -36,7 +36,7 @@ ophyd_async/epics/areadetector/controllers/kinetix_controller.py,sha256=9QmydX85
|
|
|
36
36
|
ophyd_async/epics/areadetector/controllers/pilatus_controller.py,sha256=cd1CKkaXlwkpQ0I1VL7nN0U8R4VweTsa08WhvHYI4nY,2243
|
|
37
37
|
ophyd_async/epics/areadetector/controllers/vimba_controller.py,sha256=Eh4Hr9rWgq1mKvE93JzgixntjPHxF3_07GTFqiOdZqE,2123
|
|
38
38
|
ophyd_async/epics/areadetector/drivers/__init__.py,sha256=-Ib0Lz4fFQQmB7K0uFxMDvAerkLxadMQERH7lNAvrs4,495
|
|
39
|
-
ophyd_async/epics/areadetector/drivers/ad_base.py,sha256=
|
|
39
|
+
ophyd_async/epics/areadetector/drivers/ad_base.py,sha256=18WFAiWEUg0H2LcvTQHrKYj2wThGafQzDpiyAWki6vo,3411
|
|
40
40
|
ophyd_async/epics/areadetector/drivers/aravis_driver.py,sha256=PmIygsVNoxxYHvZZzFAbAm2DXmXFc13nAzL_DJB6YSU,1464
|
|
41
41
|
ophyd_async/epics/areadetector/drivers/kinetix_driver.py,sha256=yIV23BkGBJ4i0VskLiLL7AFbadCCR6Ch1UwUDJ9r2YM,743
|
|
42
42
|
ophyd_async/epics/areadetector/drivers/pilatus_driver.py,sha256=0DsUu9vAPXDa2v8_V0f_kPjBtLu3y4_EkmFfFjYO4Gk,553
|
|
@@ -44,21 +44,21 @@ ophyd_async/epics/areadetector/drivers/vimba_driver.py,sha256=J54VtWkOklfbSqZYxG
|
|
|
44
44
|
ophyd_async/epics/areadetector/writers/__init__.py,sha256=tpPcrYd1hs8WS7C0gmCnR2EBwjE5RzCljI7WwZ2V_LM,191
|
|
45
45
|
ophyd_async/epics/areadetector/writers/_hdfdataset.py,sha256=E0C9VgsPyY35h7k0mvcIhjsIVNavApLxizqNWlM388w,167
|
|
46
46
|
ophyd_async/epics/areadetector/writers/_hdffile.py,sha256=YtUgOKX53m0TaFEGBW671qXqNuuEKxEyLV5Ein1fjvo,1799
|
|
47
|
-
ophyd_async/epics/areadetector/writers/hdf_writer.py,sha256=
|
|
48
|
-
ophyd_async/epics/areadetector/writers/nd_file_hdf.py,sha256=
|
|
49
|
-
ophyd_async/epics/areadetector/writers/nd_plugin.py,sha256=
|
|
50
|
-
ophyd_async/epics/demo/__init__.py,sha256=
|
|
47
|
+
ophyd_async/epics/areadetector/writers/hdf_writer.py,sha256=ZpbVilNVv81OpbCrqaeZUoHLarrjzRWEGe-zI1Wxyyw,5436
|
|
48
|
+
ophyd_async/epics/areadetector/writers/nd_file_hdf.py,sha256=EkiaEh_0U6Iz17jFi2IIsRPsVQTQIJRG8EPNCiAHkkU,1762
|
|
49
|
+
ophyd_async/epics/areadetector/writers/nd_plugin.py,sha256=GUzaeTMdG07Rb1x0WzBBxMEltBhr10jb5dL29tEWXEQ,1547
|
|
50
|
+
ophyd_async/epics/demo/__init__.py,sha256=ZcuZ66aIQ58WSydLOSKnk-h_W-aWjhDRZkWQA6f3sig,5790
|
|
51
51
|
ophyd_async/epics/demo/demo_ad_sim_detector.py,sha256=06y65yvaqXvL2rDocjYyLz9kTVzuwV-LeuPhEfExdOA,944
|
|
52
52
|
ophyd_async/epics/demo/mover.db,sha256=RFz0rxZue689Wh1sWTZwWeFMUrH04ttPq2u5xJH_Fp4,998
|
|
53
53
|
ophyd_async/epics/demo/sensor.db,sha256=AVtiydrdtwAz2EFurO2Ult9SSRtre3r0akOBbL98LT0,554
|
|
54
54
|
ophyd_async/epics/motion/__init__.py,sha256=tnmVRIwKa9PdN_xonJdAUD04UpEceh-hoD7XI62yDB0,46
|
|
55
|
-
ophyd_async/epics/motion/motor.py,sha256=
|
|
55
|
+
ophyd_async/epics/motion/motor.py,sha256=G8cc-okSXJ6s2fGxRO155xm7PrBbVImBmBMRWts895k,3630
|
|
56
56
|
ophyd_async/epics/pvi/__init__.py,sha256=TbOQNY4enQWgtr1T7x129vpo2p7FIFlr8cyZqqv5Lk4,158
|
|
57
57
|
ophyd_async/epics/pvi/pvi.py,sha256=PJdY3rCRyIQbsbHDru-TJ-IVOItyaQwCQKAC0Widu6A,11363
|
|
58
58
|
ophyd_async/epics/signal/__init__.py,sha256=JXKBSGpRL9y3auh27JRxsqDn_rBOXpJjtd4nCuDOX2g,261
|
|
59
59
|
ophyd_async/epics/signal/_epics_transport.py,sha256=DEIL0iYUAWssysVEgWGu1fHSM1l-ATV2kjUgPtDN9LY,858
|
|
60
60
|
ophyd_async/epics/signal/signal.py,sha256=M8ZVG_zLdYJfroCRX-u_w8c3yIhswSRw8e3RkW2szio,3166
|
|
61
|
-
ophyd_async/panda/__init__.py,sha256=
|
|
61
|
+
ophyd_async/panda/__init__.py,sha256=FuSnvp-RtdA0X4RcHEF0nTiXymRts2MNdFmF_1_i41w,775
|
|
62
62
|
ophyd_async/panda/_common_blocks.py,sha256=n0PPc1rar43oDSIA-yNubTc8fR5YCW1tyjQU58whsg0,1038
|
|
63
63
|
ophyd_async/panda/_hdf_panda.py,sha256=QjfZyYos0ZBlIqBiZ5UbyEd_wuh_cGzwV8QE9jvLiIY,1419
|
|
64
64
|
ophyd_async/panda/_panda_controller.py,sha256=dIqcjmaIHVrki8UXSoDx46kk6I2Lhpe2o3sXNg5f-RQ,1238
|
|
@@ -66,21 +66,21 @@ ophyd_async/panda/_table.py,sha256=dLoRP4zYNOkD_s0Vkp2wVYAwkjVG8nNdf8-FaXOTfPo,5
|
|
|
66
66
|
ophyd_async/panda/_trigger.py,sha256=tBH8uq_4o1ASG9yofVxq3tjf5v8LPzniDTRL4yjramI,1195
|
|
67
67
|
ophyd_async/panda/_utils.py,sha256=VHW5kPVISyEkmse_qQcyisBkkEwMO6GG2Ago-CH1AFA,487
|
|
68
68
|
ophyd_async/panda/writers/__init__.py,sha256=xy7BguVQG4HNIDBfKPjMj0KQo1tptC9LbCpEuMcVGaM,70
|
|
69
|
-
ophyd_async/panda/writers/_hdf_writer.py,sha256=
|
|
69
|
+
ophyd_async/panda/writers/_hdf_writer.py,sha256=vnyIg3JmlzMIIq75o0IDMfGzBm_GJAhOUisAZE_0cyg,7597
|
|
70
70
|
ophyd_async/panda/writers/_panda_hdf_file.py,sha256=42iHaTax4JjOBpNC7d4nkNL9SM14OTnFPTIcXv2jg-4,1759
|
|
71
|
-
ophyd_async/
|
|
72
|
-
ophyd_async/
|
|
73
|
-
ophyd_async/
|
|
71
|
+
ophyd_async/plan_stubs/__init__.py,sha256=nO9ELG9J7fYwfVTVRWVorz4kffeszYpwk1ROh6Ha--w,405
|
|
72
|
+
ophyd_async/plan_stubs/ensure_connected.py,sha256=1MkDu8UqVRPHLnW9IXRn-QvKiG8-rCV8T4KDbjf9K6w,557
|
|
73
|
+
ophyd_async/plan_stubs/fly.py,sha256=nl8XLoY7hvlam6H3zl4NcPRUiEJ3xIjopHEfA0ehTDg,4845
|
|
74
74
|
ophyd_async/sim/__init__.py,sha256=ScjH1g7FMo5yPACfJRZE6xGBWCHU4bKDzNQk1tqObnA,366
|
|
75
75
|
ophyd_async/sim/pattern_generator.py,sha256=pvSk2zb82D08j2jiKAMqMAfRohGnYd_rpjUraLrCD6c,10640
|
|
76
76
|
ophyd_async/sim/sim_pattern_detector_control.py,sha256=Ypz8IuRYAY2J243IhVbNyGr_Z-XtpJZ1qxma6NR3TgM,1838
|
|
77
77
|
ophyd_async/sim/sim_pattern_detector_writer.py,sha256=ESpcVyHd1TP7Cojznv2hJAwLinu3XbgAiVKfX12FCII,1237
|
|
78
78
|
ophyd_async/sim/sim_pattern_generator.py,sha256=fbcwWxTPYKLK33OzIY15vGylnonOO8HIudz1y_56GZU,1336
|
|
79
79
|
ophyd_async/sim/demo/__init__.py,sha256=9mxKpslrL89cfSj4g3og8Br3O--pMj3hhWZS-Xu6kyA,56
|
|
80
|
-
ophyd_async/sim/demo/sim_motor.py,sha256=
|
|
81
|
-
ophyd_async-0.
|
|
82
|
-
ophyd_async-0.
|
|
83
|
-
ophyd_async-0.
|
|
84
|
-
ophyd_async-0.
|
|
85
|
-
ophyd_async-0.
|
|
86
|
-
ophyd_async-0.
|
|
80
|
+
ophyd_async/sim/demo/sim_motor.py,sha256=a2p5wnHXjF-V5zOFai7jnszk4kbGmrZRnUqBtkOgEfQ,3733
|
|
81
|
+
ophyd_async-0.3rc2.dist-info/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
|
|
82
|
+
ophyd_async-0.3rc2.dist-info/METADATA,sha256=TRb7FrOHb4YrISGe-fkGY_W3kkrnBvioFJsgErNLmo8,6285
|
|
83
|
+
ophyd_async-0.3rc2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
84
|
+
ophyd_async-0.3rc2.dist-info/entry_points.txt,sha256=O0YNJTEufO0w9BozXi-JurTy2U1_o0ypeCgJLQ727Jk,58
|
|
85
|
+
ophyd_async-0.3rc2.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
|
|
86
|
+
ophyd_async-0.3rc2.dist-info/RECORD,,
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
|
-
import bluesky.plan_stubs as bps
|
|
4
|
-
|
|
5
|
-
from ophyd_async.core.detector import DetectorTrigger, StandardDetector, TriggerInfo
|
|
6
|
-
from ophyd_async.core.flyer import HardwareTriggeredFlyable
|
|
7
|
-
from ophyd_async.core.utils import in_micros
|
|
8
|
-
from ophyd_async.panda._table import SeqTable, SeqTableRow, seq_table_from_rows
|
|
9
|
-
from ophyd_async.panda._trigger import SeqTableInfo
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
|
|
13
|
-
flyer: HardwareTriggeredFlyable[SeqTableInfo],
|
|
14
|
-
detectors: List[StandardDetector],
|
|
15
|
-
num: int,
|
|
16
|
-
width: float,
|
|
17
|
-
deadtime: float,
|
|
18
|
-
shutter_time: float,
|
|
19
|
-
repeats: int = 1,
|
|
20
|
-
period: float = 0.0,
|
|
21
|
-
):
|
|
22
|
-
trigger_info = TriggerInfo(
|
|
23
|
-
num=num * repeats,
|
|
24
|
-
trigger=DetectorTrigger.constant_gate,
|
|
25
|
-
deadtime=deadtime,
|
|
26
|
-
livetime=width,
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
trigger_time = num * (width + deadtime)
|
|
30
|
-
pre_delay = max(period - 2 * shutter_time - trigger_time, 0)
|
|
31
|
-
|
|
32
|
-
table: SeqTable = seq_table_from_rows(
|
|
33
|
-
# Wait for pre-delay then open shutter
|
|
34
|
-
SeqTableRow(
|
|
35
|
-
time1=in_micros(pre_delay),
|
|
36
|
-
time2=in_micros(shutter_time),
|
|
37
|
-
outa2=True,
|
|
38
|
-
),
|
|
39
|
-
# Keeping shutter open, do N triggers
|
|
40
|
-
SeqTableRow(
|
|
41
|
-
repeats=num,
|
|
42
|
-
time1=in_micros(width),
|
|
43
|
-
outa1=True,
|
|
44
|
-
outb1=True,
|
|
45
|
-
time2=in_micros(deadtime),
|
|
46
|
-
outa2=True,
|
|
47
|
-
),
|
|
48
|
-
# Add the shutter close
|
|
49
|
-
SeqTableRow(time2=in_micros(shutter_time)),
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
table_info = SeqTableInfo(table, repeats)
|
|
53
|
-
|
|
54
|
-
for det in detectors:
|
|
55
|
-
yield from bps.prepare(det, trigger_info, wait=False, group="prep")
|
|
56
|
-
yield from bps.prepare(flyer, table_info, wait=False, group="prep")
|
|
57
|
-
yield from bps.wait(group="prep")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|