ophyd-async 0.13.5__py3-none-any.whl → 0.13.7__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 +2 -2
- ophyd_async/core/_mock_signal_backend.py +7 -3
- ophyd_async/core/_signal.py +2 -1
- ophyd_async/epics/motor.py +18 -3
- ophyd_async/epics/pmac/_pmac_io.py +10 -13
- ophyd_async/epics/pmac/_pmac_trajectory.py +9 -10
- ophyd_async/epics/pmac/_pmac_trajectory_generation.py +3 -0
- ophyd_async/epics/pmac/_utils.py +102 -59
- ophyd_async/fastcs/panda/_block.py +10 -9
- ophyd_async/tango/core/__init__.py +0 -2
- ophyd_async/tango/core/_base_device.py +4 -1
- ophyd_async/tango/demo/_counter.py +10 -3
- ophyd_async/tango/demo/_mover.py +4 -3
- ophyd_async/testing/_mock_signal_utils.py +5 -2
- {ophyd_async-0.13.5.dist-info → ophyd_async-0.13.7.dist-info}/METADATA +1 -1
- {ophyd_async-0.13.5.dist-info → ophyd_async-0.13.7.dist-info}/RECORD +19 -20
- ophyd_async/tango/core/_tango_readable.py +0 -15
- {ophyd_async-0.13.5.dist-info → ophyd_async-0.13.7.dist-info}/WHEEL +0 -0
- {ophyd_async-0.13.5.dist-info → ophyd_async-0.13.7.dist-info}/licenses/LICENSE +0 -0
- {ophyd_async-0.13.5.dist-info → ophyd_async-0.13.7.dist-info}/top_level.txt +0 -0
ophyd_async/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.13.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 13,
|
|
31
|
+
__version__ = version = '0.13.7'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 13, 7)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -41,7 +41,9 @@ class MockSignalBackend(SignalBackend[SignalDatatypeT]):
|
|
|
41
41
|
@cached_property
|
|
42
42
|
def put_mock(self) -> AsyncMock:
|
|
43
43
|
"""Return the mock that will track calls to `put()`."""
|
|
44
|
-
put_mock = AsyncMock(
|
|
44
|
+
put_mock = AsyncMock(
|
|
45
|
+
name="put", spec=Callable, side_effect=lambda *_, **__: None
|
|
46
|
+
)
|
|
45
47
|
self.mock().attach_mock(put_mock, "put")
|
|
46
48
|
return put_mock
|
|
47
49
|
|
|
@@ -66,8 +68,10 @@ class MockSignalBackend(SignalBackend[SignalDatatypeT]):
|
|
|
66
68
|
return put_proceeds
|
|
67
69
|
|
|
68
70
|
async def put(self, value: SignalDatatypeT | None, wait: bool):
|
|
69
|
-
await self.put_mock(value, wait=wait)
|
|
70
|
-
|
|
71
|
+
new_value = await self.put_mock(value, wait=wait)
|
|
72
|
+
if new_value is None:
|
|
73
|
+
new_value = value
|
|
74
|
+
await self.soft_backend.put(new_value, wait=wait)
|
|
71
75
|
if wait:
|
|
72
76
|
await self.put_proceeds.wait()
|
|
73
77
|
|
ophyd_async/core/_signal.py
CHANGED
|
@@ -639,9 +639,10 @@ async def set_and_wait_for_other_value(
|
|
|
639
639
|
if wait_for_set_completion:
|
|
640
640
|
await status
|
|
641
641
|
except TimeoutError as exc:
|
|
642
|
+
matcher_name = getattr(matcher, "__name__", f"<{type(matcher).__name__}>")
|
|
642
643
|
raise TimeoutError(
|
|
643
644
|
f"{match_signal.name} value didn't match value from"
|
|
644
|
-
f" {
|
|
645
|
+
f" {matcher_name}() in {timeout}s"
|
|
645
646
|
) from exc
|
|
646
647
|
|
|
647
648
|
return status
|
ophyd_async/epics/motor.py
CHANGED
|
@@ -98,9 +98,12 @@ class Motor(
|
|
|
98
98
|
self.motor_done_move = epics_signal_r(int, prefix + ".DMOV")
|
|
99
99
|
self.low_limit_travel = epics_signal_rw(float, prefix + ".LLM")
|
|
100
100
|
self.high_limit_travel = epics_signal_rw(float, prefix + ".HLM")
|
|
101
|
+
self.dial_low_limit_travel = epics_signal_rw(float, prefix + ".DLLM")
|
|
102
|
+
self.dial_high_limit_travel = epics_signal_rw(float, prefix + ".DHLM")
|
|
101
103
|
self.offset_freeze_switch = epics_signal_rw(OffsetMode, prefix + ".FOFF")
|
|
102
104
|
self.high_limit_switch = epics_signal_r(int, prefix + ".HLS")
|
|
103
105
|
self.low_limit_switch = epics_signal_r(int, prefix + ".LLS")
|
|
106
|
+
self.output_link = epics_signal_r(str, prefix + ".OUT")
|
|
104
107
|
self.set_use_switch = epics_signal_rw(UseSetMode, prefix + ".SET")
|
|
105
108
|
|
|
106
109
|
# Note:cannot use epics_signal_x here, as the motor record specifies that
|
|
@@ -131,16 +134,26 @@ class Motor(
|
|
|
131
134
|
Will raise a MotorLimitsException if the given absolute positions will be
|
|
132
135
|
outside the motor soft limits.
|
|
133
136
|
"""
|
|
134
|
-
|
|
137
|
+
(
|
|
138
|
+
motor_lower_limit,
|
|
139
|
+
motor_upper_limit,
|
|
140
|
+
egu,
|
|
141
|
+
dial_lower_limit,
|
|
142
|
+
dial_upper_limit,
|
|
143
|
+
) = await asyncio.gather(
|
|
135
144
|
self.low_limit_travel.get_value(),
|
|
136
145
|
self.high_limit_travel.get_value(),
|
|
137
146
|
self.motor_egu.get_value(),
|
|
147
|
+
self.dial_low_limit_travel.get_value(),
|
|
148
|
+
self.dial_high_limit_travel.get_value(),
|
|
138
149
|
)
|
|
139
150
|
|
|
140
|
-
# EPICS motor record treats limits of 0, 0 as no limit
|
|
141
|
-
|
|
151
|
+
# EPICS motor record treats dial limits of 0, 0 as no limit
|
|
152
|
+
# Use DLLM and DHLM to check
|
|
153
|
+
if dial_lower_limit == 0 and dial_upper_limit == 0:
|
|
142
154
|
return
|
|
143
155
|
|
|
156
|
+
# Use real motor limit(i.e. HLM and LLM) to check if the move is permissible
|
|
144
157
|
if (
|
|
145
158
|
not motor_upper_limit >= abs_start_pos >= motor_lower_limit
|
|
146
159
|
or not motor_upper_limit >= abs_end_pos >= motor_lower_limit
|
|
@@ -150,6 +163,8 @@ class Motor(
|
|
|
150
163
|
f"{abs_start_pos}{egu} to "
|
|
151
164
|
f"{abs_end_pos}{egu} but motor limits are "
|
|
152
165
|
f"{motor_lower_limit}{egu} <= x <= {motor_upper_limit}{egu} "
|
|
166
|
+
f"dial limits are "
|
|
167
|
+
f"{dial_lower_limit}{egu} <= x <= {dial_upper_limit}"
|
|
153
168
|
)
|
|
154
169
|
|
|
155
170
|
@AsyncStatus.wrap
|
|
@@ -6,7 +6,8 @@ from ophyd_async.core import Array1D, Device, DeviceVector, StandardReadable
|
|
|
6
6
|
from ophyd_async.epics import motor
|
|
7
7
|
from ophyd_async.epics.core import epics_signal_r, epics_signal_rw, epics_signal_x
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
# Map the CS axis letters to their index (1 indexed)
|
|
10
|
+
CS_INDEX = {letter: index + 1 for index, letter in enumerate("ABCUVWXYZ")}
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class PmacTrajectoryIO(StandardReadable):
|
|
@@ -20,24 +21,20 @@ class PmacTrajectoryIO(StandardReadable):
|
|
|
20
21
|
# 1 indexed CS axes so we can index into them from the compound motor input link
|
|
21
22
|
self.positions = DeviceVector(
|
|
22
23
|
{
|
|
23
|
-
i
|
|
24
|
-
|
|
25
|
-
)
|
|
26
|
-
for i, letter in enumerate(CS_LETTERS)
|
|
24
|
+
i: epics_signal_rw(Array1D[np.float64], f"{prefix}{letter}:Positions")
|
|
25
|
+
for letter, i in CS_INDEX.items()
|
|
27
26
|
}
|
|
28
27
|
)
|
|
29
28
|
self.use_axis = DeviceVector(
|
|
30
29
|
{
|
|
31
|
-
i
|
|
32
|
-
for
|
|
30
|
+
i: epics_signal_rw(bool, f"{prefix}{letter}:UseAxis")
|
|
31
|
+
for letter, i in CS_INDEX.items()
|
|
33
32
|
}
|
|
34
33
|
)
|
|
35
34
|
self.velocities = DeviceVector(
|
|
36
35
|
{
|
|
37
|
-
i
|
|
38
|
-
|
|
39
|
-
)
|
|
40
|
-
for i, letter in enumerate(CS_LETTERS)
|
|
36
|
+
i: epics_signal_rw(Array1D[np.float64], f"{prefix}{letter}:Velocities")
|
|
37
|
+
for letter, i in CS_INDEX.items()
|
|
41
38
|
}
|
|
42
39
|
)
|
|
43
40
|
self.total_points = epics_signal_r(int, f"{prefix}TotalPoints_RBV")
|
|
@@ -76,8 +73,8 @@ class PmacCoordIO(Device):
|
|
|
76
73
|
self.cs_port = epics_signal_r(str, f"{prefix}Port")
|
|
77
74
|
self.cs_axis_setpoint = DeviceVector(
|
|
78
75
|
{
|
|
79
|
-
i
|
|
80
|
-
for i in
|
|
76
|
+
i: epics_signal_rw(float, f"{prefix}M{i}:DirectDemand")
|
|
77
|
+
for i in CS_INDEX.values()
|
|
81
78
|
}
|
|
82
79
|
)
|
|
83
80
|
super().__init__(name=name)
|
|
@@ -15,10 +15,10 @@ from ophyd_async.core import (
|
|
|
15
15
|
wait_for_value,
|
|
16
16
|
)
|
|
17
17
|
from ophyd_async.epics.motor import Motor
|
|
18
|
-
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
18
|
+
|
|
19
|
+
from ._pmac_io import CS_INDEX, PmacIO
|
|
20
|
+
from ._pmac_trajectory_generation import PVT, Trajectory
|
|
21
|
+
from ._utils import (
|
|
22
22
|
_PmacMotorInfo,
|
|
23
23
|
calculate_ramp_position_and_duration,
|
|
24
24
|
)
|
|
@@ -131,8 +131,7 @@ class PmacTrajectoryTriggerLogic(FlyerController):
|
|
|
131
131
|
slice, path_length, motor_info, ramp_up_time
|
|
132
132
|
)
|
|
133
133
|
use_axis = {
|
|
134
|
-
|
|
135
|
-
for axis in range(len(CS_LETTERS))
|
|
134
|
+
i: (i in motor_info.motor_cs_index.values()) for i in CS_INDEX.values()
|
|
136
135
|
}
|
|
137
136
|
|
|
138
137
|
coros = [
|
|
@@ -177,14 +176,14 @@ class PmacTrajectoryTriggerLogic(FlyerController):
|
|
|
177
176
|
self, trajectory: Trajectory, motor_info: _PmacMotorInfo
|
|
178
177
|
):
|
|
179
178
|
coros = []
|
|
180
|
-
for motor,
|
|
179
|
+
for motor, cs_index in motor_info.motor_cs_index.items():
|
|
181
180
|
coros.append(
|
|
182
|
-
self.pmac.trajectory.positions[
|
|
181
|
+
self.pmac.trajectory.positions[cs_index].set(
|
|
183
182
|
trajectory.positions[motor]
|
|
184
183
|
)
|
|
185
184
|
)
|
|
186
185
|
coros.append(
|
|
187
|
-
self.pmac.trajectory.velocities[
|
|
186
|
+
self.pmac.trajectory.velocities[cs_index].set(
|
|
188
187
|
trajectory.velocities[motor]
|
|
189
188
|
)
|
|
190
189
|
)
|
|
@@ -206,7 +205,7 @@ class PmacTrajectoryTriggerLogic(FlyerController):
|
|
|
206
205
|
for motor, position in ramp_up_position.items():
|
|
207
206
|
coros.append(
|
|
208
207
|
set_and_wait_for_value(
|
|
209
|
-
coord.cs_axis_setpoint[motor_info.motor_cs_index[motor]
|
|
208
|
+
coord.cs_axis_setpoint[motor_info.motor_cs_index[motor]],
|
|
210
209
|
position,
|
|
211
210
|
set_timeout=10,
|
|
212
211
|
wait_for_set_completion=False,
|
|
@@ -558,6 +558,9 @@ def _get_velocity_profile(
|
|
|
558
558
|
# Check if all profiles have converged on min_time
|
|
559
559
|
if np.isclose(new_min_time, min_time):
|
|
560
560
|
for motor in motors:
|
|
561
|
+
# MIN_INTERVAL should be less than our convergence tolerance
|
|
562
|
+
# such that motors snap to the same point in the time grid
|
|
563
|
+
profiles[motor].quantize()
|
|
561
564
|
time_arrays[motor], velocity_arrays[motor] = profiles[
|
|
562
565
|
motor
|
|
563
566
|
].make_arrays()
|
ophyd_async/epics/pmac/_utils.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import re
|
|
4
5
|
from collections.abc import Sequence
|
|
5
6
|
from dataclasses import dataclass
|
|
6
7
|
|
|
@@ -10,7 +11,7 @@ from scanspec.core import Slice
|
|
|
10
11
|
from ophyd_async.core import gather_dict
|
|
11
12
|
from ophyd_async.epics.motor import Motor
|
|
12
13
|
|
|
13
|
-
from ._pmac_io import
|
|
14
|
+
from ._pmac_io import CS_INDEX, PmacIO
|
|
14
15
|
|
|
15
16
|
# PMAC durations are in milliseconds
|
|
16
17
|
# We must convert from scanspec durations (seconds) to milliseconds
|
|
@@ -21,6 +22,11 @@ TICK_S = 0.000001
|
|
|
21
22
|
MIN_TURNAROUND = 0.002
|
|
22
23
|
MIN_INTERVAL = 0.002
|
|
23
24
|
|
|
25
|
+
# Regex to parse outlink strings of the form "@asyn(PMAC1CS2, 7)"
|
|
26
|
+
# returning PMAC1CS2 and 7
|
|
27
|
+
# https://regex101.com/r/Mu9XpO/1
|
|
28
|
+
OUTLINK_REGEX = re.compile(r"^\@asyn\(([^,]+),\s*(\d+)\)$")
|
|
29
|
+
|
|
24
30
|
|
|
25
31
|
@dataclass
|
|
26
32
|
class _PmacMotorInfo:
|
|
@@ -44,78 +50,115 @@ class _PmacMotorInfo:
|
|
|
44
50
|
dictionaries of motor's to their unique CS index and accelerate rate
|
|
45
51
|
|
|
46
52
|
"""
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
for
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
53
|
+
is_raw_motor = [motor in pmac.motor_assignment_index for motor in motors]
|
|
54
|
+
if all(is_raw_motor):
|
|
55
|
+
# Get the CS port, number and axis letter from the PVs for the raw motor
|
|
56
|
+
assignments = {
|
|
57
|
+
motor: pmac.assignment[pmac.motor_assignment_index[motor]]
|
|
58
|
+
for motor in motors
|
|
59
|
+
}
|
|
60
|
+
cs_ports, cs_numbers, cs_axis_letters = await asyncio.gather(
|
|
61
|
+
gather_dict(
|
|
62
|
+
{motor: assignments[motor].cs_port.get_value() for motor in motors}
|
|
63
|
+
),
|
|
64
|
+
gather_dict(
|
|
65
|
+
{
|
|
66
|
+
motor: assignments[motor].cs_number.get_value()
|
|
67
|
+
for motor in motors
|
|
68
|
+
}
|
|
69
|
+
),
|
|
70
|
+
gather_dict(
|
|
71
|
+
{
|
|
72
|
+
motor: assignments[motor].cs_axis_letter.get_value()
|
|
73
|
+
for motor in motors
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
# Translate axis letters to cs_index and check for duplicates
|
|
78
|
+
motor_cs_index: dict[Motor, int] = {}
|
|
79
|
+
for motor, cs_axis_letter in cs_axis_letters.items():
|
|
80
|
+
if not cs_axis_letter:
|
|
81
|
+
raise ValueError(
|
|
82
|
+
f"Motor {motor.name} does not have an axis assignment."
|
|
83
|
+
)
|
|
84
|
+
try:
|
|
85
|
+
# 1 indexed to match coord
|
|
86
|
+
index = CS_INDEX[cs_axis_letter]
|
|
87
|
+
except KeyError as err:
|
|
88
|
+
raise ValueError(
|
|
89
|
+
f"Motor {motor.name} assigned to '{cs_axis_letter}' "
|
|
90
|
+
f"but must be assigned to one of '{','.join(CS_INDEX)}'"
|
|
91
|
+
) from err
|
|
92
|
+
if index in motor_cs_index.values():
|
|
93
|
+
raise ValueError(
|
|
94
|
+
f"Motor {motor.name} assigned to '{cs_axis_letter}' "
|
|
95
|
+
"but another motor is already assigned to this axis."
|
|
96
|
+
)
|
|
97
|
+
motor_cs_index[motor] = index
|
|
98
|
+
elif not any(is_raw_motor):
|
|
99
|
+
# Get CS numbers from all the cs ports and output links for the CS motors
|
|
100
|
+
output_links, cs_lookup = await asyncio.gather(
|
|
101
|
+
gather_dict({motor: motor.output_link.get_value() for motor in motors}),
|
|
102
|
+
gather_dict(
|
|
103
|
+
{
|
|
104
|
+
cs_number: cs.cs_port.get_value()
|
|
105
|
+
for cs_number, cs in pmac.coord.items()
|
|
106
|
+
}
|
|
107
|
+
),
|
|
108
|
+
)
|
|
109
|
+
# Create a reverse lookup from cs_port to cs_number
|
|
110
|
+
cs_reverse_lookup = {
|
|
111
|
+
cs_port: cs_number for cs_number, cs_port in cs_lookup.items()
|
|
112
|
+
}
|
|
113
|
+
cs_ports: dict[Motor, str] = {}
|
|
114
|
+
cs_numbers: dict[Motor, int] = {}
|
|
115
|
+
motor_cs_index: dict[Motor, int] = {}
|
|
116
|
+
# Populate the cs_ports, cs_numbers and motor_cs_index dicts from outlinks
|
|
117
|
+
for motor, output_link in output_links.items():
|
|
118
|
+
match = OUTLINK_REGEX.match(output_link)
|
|
119
|
+
if not match:
|
|
120
|
+
raise ValueError(
|
|
121
|
+
f"Motor {motor.name} has invalid output link '{output_link}'"
|
|
122
|
+
)
|
|
123
|
+
cs_port, cs_index = match.groups()
|
|
124
|
+
cs_ports[motor] = cs_port
|
|
125
|
+
cs_numbers[motor] = cs_reverse_lookup[cs_port]
|
|
126
|
+
motor_cs_index[motor] = int(cs_index)
|
|
127
|
+
else:
|
|
128
|
+
raise ValueError("Unable to use raw motors and CS motors in the same scan")
|
|
70
129
|
|
|
71
130
|
# check if the values in cs_port and cs_number are the same
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if len(cs_ports) != 1:
|
|
131
|
+
cs_ports_set = set(cs_ports.values())
|
|
132
|
+
if len(cs_ports_set) != 1:
|
|
75
133
|
raise RuntimeError(
|
|
76
134
|
"Failed to fetch common CS port."
|
|
77
135
|
"Motors passed are assigned to multiple CS ports:"
|
|
78
|
-
f"{list(
|
|
136
|
+
f"{list(cs_ports_set)}"
|
|
79
137
|
)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
cs_numbers = set(cs_numbers.values())
|
|
84
|
-
if len(cs_numbers) != 1:
|
|
138
|
+
cs_numbers_set = set(cs_numbers.values())
|
|
139
|
+
if len(cs_numbers_set) != 1:
|
|
85
140
|
raise RuntimeError(
|
|
86
141
|
"Failed to fetch common CS number."
|
|
87
142
|
"Motors passed are assigned to multiple CS numbers:"
|
|
88
|
-
f"{list(
|
|
143
|
+
f"{list(cs_numbers_set)}"
|
|
89
144
|
)
|
|
90
145
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
motor_cs_index[motor] = CS_LETTERS.index(cs_axes[motor])
|
|
99
|
-
except ValueError as err:
|
|
100
|
-
raise ValueError(
|
|
101
|
-
"Failed to get motor CS index. "
|
|
102
|
-
f"Motor {motor.name} assigned to '{cs_axes[motor]}' "
|
|
103
|
-
f"but must be assignmed to '{CS_LETTERS}"
|
|
104
|
-
) from err
|
|
105
|
-
if len(set(motor_cs_index.values())) != len(motor_cs_index.items()):
|
|
106
|
-
raise RuntimeError(
|
|
107
|
-
"Failed to fetch distinct CS Axes."
|
|
108
|
-
"Motors passed are assigned to the same CS Axis"
|
|
109
|
-
f"{list(motor_cs_index)}"
|
|
110
|
-
)
|
|
111
|
-
|
|
146
|
+
# Get the velocities and acceleration rates for each motor
|
|
147
|
+
max_velocity, acceleration_time = await asyncio.gather(
|
|
148
|
+
gather_dict({motor: motor.max_velocity.get_value() for motor in motors}),
|
|
149
|
+
gather_dict(
|
|
150
|
+
{motor: motor.acceleration_time.get_value() for motor in motors}
|
|
151
|
+
),
|
|
152
|
+
)
|
|
112
153
|
motor_acceleration_rate = {
|
|
113
|
-
motor:
|
|
114
|
-
for motor in velocities
|
|
154
|
+
motor: max_velocity[motor] / acceleration_time[motor] for motor in motors
|
|
115
155
|
}
|
|
116
|
-
|
|
117
156
|
return _PmacMotorInfo(
|
|
118
|
-
cs_port,
|
|
157
|
+
cs_port=cs_ports_set.pop(),
|
|
158
|
+
cs_number=cs_numbers_set.pop(),
|
|
159
|
+
motor_cs_index=motor_cs_index,
|
|
160
|
+
motor_acceleration_rate=motor_acceleration_rate,
|
|
161
|
+
motor_max_velocity=max_velocity,
|
|
119
162
|
)
|
|
120
163
|
|
|
121
164
|
|
|
@@ -34,15 +34,6 @@ class DataBlock(Device):
|
|
|
34
34
|
datasets: SignalR[DatasetTable]
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
class PulseBlock(Device):
|
|
38
|
-
"""Used for configuring pulses in the PandA."""
|
|
39
|
-
|
|
40
|
-
delay: SignalRW[float]
|
|
41
|
-
pulses: SignalRW[int]
|
|
42
|
-
step: SignalRW[float]
|
|
43
|
-
width: SignalRW[float]
|
|
44
|
-
|
|
45
|
-
|
|
46
37
|
class PandaPcompDirection(StrictEnum):
|
|
47
38
|
"""Direction options for position compare in the PandA."""
|
|
48
39
|
|
|
@@ -64,6 +55,16 @@ class PandaPosMux(SubsetEnum):
|
|
|
64
55
|
ZERO = "ZERO"
|
|
65
56
|
|
|
66
57
|
|
|
58
|
+
class PulseBlock(Device):
|
|
59
|
+
"""Used for configuring pulses in the PandA."""
|
|
60
|
+
|
|
61
|
+
enable: SignalRW[PandaBitMux]
|
|
62
|
+
delay: SignalRW[float]
|
|
63
|
+
pulses: SignalRW[int]
|
|
64
|
+
step: SignalRW[float]
|
|
65
|
+
width: SignalRW[float]
|
|
66
|
+
|
|
67
|
+
|
|
67
68
|
class PcompBlock(Device):
|
|
68
69
|
"""Position compare block in the PandA."""
|
|
69
70
|
|
|
@@ -8,7 +8,6 @@ from ._signal import (
|
|
|
8
8
|
tango_signal_w,
|
|
9
9
|
tango_signal_x,
|
|
10
10
|
)
|
|
11
|
-
from ._tango_readable import TangoReadable
|
|
12
11
|
from ._tango_transport import (
|
|
13
12
|
AttributeProxy,
|
|
14
13
|
CommandProxy,
|
|
@@ -50,7 +49,6 @@ __all__ = [
|
|
|
50
49
|
"tango_signal_w",
|
|
51
50
|
"tango_signal_x",
|
|
52
51
|
"TangoDevice",
|
|
53
|
-
"TangoReadable",
|
|
54
52
|
"TangoPolling",
|
|
55
53
|
"TangoDeviceConnector",
|
|
56
54
|
"TangoLongStringTable",
|
|
@@ -29,7 +29,7 @@ class TangoDevice(Device):
|
|
|
29
29
|
|
|
30
30
|
def __init__(
|
|
31
31
|
self,
|
|
32
|
-
trl: str
|
|
32
|
+
trl: str = "",
|
|
33
33
|
support_events: bool = False,
|
|
34
34
|
name: str = "",
|
|
35
35
|
auto_fill_signals: bool = True,
|
|
@@ -80,6 +80,9 @@ class TangoDeviceConnector(DeviceConnector):
|
|
|
80
80
|
self._support_events = support_events
|
|
81
81
|
self._auto_fill_signals = auto_fill_signals
|
|
82
82
|
|
|
83
|
+
def set_trl(self, trl: str):
|
|
84
|
+
self.trl = trl
|
|
85
|
+
|
|
83
86
|
def create_children_from_annotations(self, device: Device):
|
|
84
87
|
if not hasattr(self, "filler"):
|
|
85
88
|
self.filler = DeviceFiller(
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
from typing import Annotated as A
|
|
2
2
|
|
|
3
|
-
from ophyd_async.core import
|
|
3
|
+
from ophyd_async.core import (
|
|
4
|
+
DEFAULT_TIMEOUT,
|
|
5
|
+
AsyncStatus,
|
|
6
|
+
SignalR,
|
|
7
|
+
SignalRW,
|
|
8
|
+
SignalX,
|
|
9
|
+
StandardReadable,
|
|
10
|
+
)
|
|
4
11
|
from ophyd_async.core import StandardReadableFormat as Format
|
|
5
|
-
from ophyd_async.tango.core import
|
|
12
|
+
from ophyd_async.tango.core import TangoDevice, TangoPolling
|
|
6
13
|
|
|
7
14
|
|
|
8
|
-
class TangoCounter(
|
|
15
|
+
class TangoCounter(TangoDevice, StandardReadable):
|
|
9
16
|
"""Tango counting device."""
|
|
10
17
|
|
|
11
18
|
# Enter the name and type of the signals you want to use
|
ophyd_async/tango/demo/_mover.py
CHANGED
|
@@ -11,16 +11,17 @@ from ophyd_async.core import (
|
|
|
11
11
|
SignalR,
|
|
12
12
|
SignalRW,
|
|
13
13
|
SignalX,
|
|
14
|
+
StandardReadable,
|
|
14
15
|
WatchableAsyncStatus,
|
|
15
16
|
WatcherUpdate,
|
|
16
17
|
observe_value,
|
|
17
18
|
wait_for_value,
|
|
18
19
|
)
|
|
19
20
|
from ophyd_async.core import StandardReadableFormat as Format
|
|
20
|
-
from ophyd_async.tango.core import DevStateEnum,
|
|
21
|
+
from ophyd_async.tango.core import DevStateEnum, TangoDevice, TangoPolling
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
class TangoMover(
|
|
24
|
+
class TangoMover(TangoDevice, StandardReadable, Movable, Stoppable):
|
|
24
25
|
"""Tango moving device."""
|
|
25
26
|
|
|
26
27
|
# Enter the name and type of the signals you want to use
|
|
@@ -32,7 +33,7 @@ class TangoMover(TangoReadable, Movable, Stoppable):
|
|
|
32
33
|
# If a tango name clashes with a bluesky verb, add a trailing underscore
|
|
33
34
|
stop_: SignalX
|
|
34
35
|
|
|
35
|
-
def __init__(self, trl: str
|
|
36
|
+
def __init__(self, trl: str = "", name=""):
|
|
36
37
|
super().__init__(trl, name=name)
|
|
37
38
|
self.add_readables([self.position], Format.HINTED_SIGNAL)
|
|
38
39
|
self.add_readables([self.velocity], Format.CONFIG_SIGNAL)
|
|
@@ -119,14 +119,17 @@ def _unset_side_effect_cm(put_mock: AsyncMock):
|
|
|
119
119
|
|
|
120
120
|
def callback_on_mock_put(
|
|
121
121
|
signal: Signal[SignalDatatypeT],
|
|
122
|
-
callback: Callable[[SignalDatatypeT, bool], None]
|
|
123
|
-
| Callable[[SignalDatatypeT, bool], Awaitable[None]],
|
|
122
|
+
callback: Callable[[SignalDatatypeT, bool], SignalDatatypeT | None]
|
|
123
|
+
| Callable[[SignalDatatypeT, bool], Awaitable[SignalDatatypeT | None]],
|
|
124
124
|
):
|
|
125
125
|
"""For setting a callback when a backend is put to.
|
|
126
126
|
|
|
127
127
|
Can either be used in a context, with the callback being unset on exit, or
|
|
128
128
|
as an ordinary function.
|
|
129
129
|
|
|
130
|
+
The value that the callback returns (if not None) will be set to the signal
|
|
131
|
+
readback. If None is returned then the readback will be set to the setpoint.
|
|
132
|
+
|
|
130
133
|
:param signal: A signal with a `MockSignalBackend` backend.
|
|
131
134
|
:param callback: The callback to call when the backend is put to during the
|
|
132
135
|
context.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.7
|
|
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,7 +1,7 @@
|
|
|
1
1
|
ophyd_async/__init__.py,sha256=dcAA3qsj1nNIMe5l-v2tlduZ_ypwBmyuHe45Lsq4k4w,206
|
|
2
2
|
ophyd_async/__main__.py,sha256=n_U4O9bgm97OuboUB_9eK7eFiwy8BZSgXJ0OzbE0DqU,481
|
|
3
3
|
ophyd_async/_docs_parser.py,sha256=gPYrigfSbYCF7QoSf2UvE-cpQu4snSssl7ZWN-kKDzI,352
|
|
4
|
-
ophyd_async/_version.py,sha256=
|
|
4
|
+
ophyd_async/_version.py,sha256=JHUU2H4LQG4g5yLVtdeoRqh4fKkn1TUpLvJEVN4qjr4,706
|
|
5
5
|
ophyd_async/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
ophyd_async/core/__init__.py,sha256=yGbkVju5otO8DmA3KyerYB0gLtcX5sdxlq3ajyGha4M,5531
|
|
7
7
|
ophyd_async/core/_derived_signal.py,sha256=TuZza_j3J1Bw4QSqBYB9Ta2FyQP5BycO3nSHVtJ890Q,13015
|
|
@@ -13,12 +13,12 @@ ophyd_async/core/_enums.py,sha256=2vh6x0rZ6SLiw2xxq1xVIn-GpbLDFc8wZoVdA55QiE8,37
|
|
|
13
13
|
ophyd_async/core/_flyer.py,sha256=8zKyU5aQOr_t59GIUwsYeb8NSabdvBp0swwuRe4v5VQ,3457
|
|
14
14
|
ophyd_async/core/_hdf_dataset.py,sha256=0bIX_ZbFSMdXqDwRtEvV-0avHnwXhjPddE5GVNmo7H8,2608
|
|
15
15
|
ophyd_async/core/_log.py,sha256=DxKR4Nz3SgTaTzKBZWqt-w48yT8WUAr_3Qr223TEWRw,3587
|
|
16
|
-
ophyd_async/core/_mock_signal_backend.py,sha256=
|
|
16
|
+
ophyd_async/core/_mock_signal_backend.py,sha256=N6rzwBR3QwHZMcifIZg6sbno6-Ts-1jK0aFVt-3jHAg,3289
|
|
17
17
|
ophyd_async/core/_protocol.py,sha256=wQ_snxhTprHqEjQb1HgFwBljwolMY6A8C3xgV1PXwdU,4051
|
|
18
18
|
ophyd_async/core/_providers.py,sha256=WBht3QCgvGc0stNcwH6z4Zr6hAz3e01-88NjsYI2w6I,9740
|
|
19
19
|
ophyd_async/core/_readable.py,sha256=iBo1YwA5bsAbzLbznvmSnzKDWUuGkLh850Br3BXsgeU,11707
|
|
20
20
|
ophyd_async/core/_settings.py,sha256=_ZccbXKP7j5rG6-bMKk7aaLr8hChdRDAPY_YSR71XXM,4213
|
|
21
|
-
ophyd_async/core/_signal.py,sha256=
|
|
21
|
+
ophyd_async/core/_signal.py,sha256=LVQ38-Txn6lIYFsIbRbZClOy9WXlLDc16FdaE1wVmII,28278
|
|
22
22
|
ophyd_async/core/_signal_backend.py,sha256=F3ma45cIIJ3D702zsVZIqn4Jv7u05YzMQBQND70QCbQ,6987
|
|
23
23
|
ophyd_async/core/_soft_signal_backend.py,sha256=NJUuyaCKtBZjggt8WKi7_lKQRHasToxviuQvl5xbhLU,6222
|
|
24
24
|
ophyd_async/core/_status.py,sha256=a2IDvv_GvUcFuhjQA5bQzWm9ngR6zGc9PR4XcZiaeqk,6557
|
|
@@ -26,7 +26,7 @@ ophyd_async/core/_table.py,sha256=ryJ7AwJBglQUzwP9_aSjR8cu8EKvYXfo1q1byhke3Uc,72
|
|
|
26
26
|
ophyd_async/core/_utils.py,sha256=gUewO4XPrBxsEWzObNumqAB2Q7Hwrd5F_Nc6B2XwQIM,12532
|
|
27
27
|
ophyd_async/core/_yaml_settings.py,sha256=Qojhku9l5kPSkTnEylCRWTe0gpw6S_XP5av5dPpqFgQ,2089
|
|
28
28
|
ophyd_async/epics/__init__.py,sha256=ou4yEaH9VZHz70e8oM614-arLMQvUfQyXhRJsnEpWn8,60
|
|
29
|
-
ophyd_async/epics/motor.py,sha256=
|
|
29
|
+
ophyd_async/epics/motor.py,sha256=RDcyKC_zFR5zLpAcf_yAbuY-1ImE3L3uBAoUXDEiz-s,10224
|
|
30
30
|
ophyd_async/epics/signal.py,sha256=0A-supp9ajr63O6aD7F9oG0-Q26YmRjk-ZGh57-jo1Y,239
|
|
31
31
|
ophyd_async/epics/adandor/__init__.py,sha256=dlitllrAdhvh16PAcVMUSSEytTDNMu6_HuYk8KD1EoY,343
|
|
32
32
|
ophyd_async/epics/adandor/_andor.py,sha256=TijGjNVxuH-P0X7UACPt9eLLQ449DwMyVhbn1kV7Le8,1245
|
|
@@ -83,10 +83,10 @@ ophyd_async/epics/demo/point_detector_channel.db,sha256=FZ9H6HjqplhcF2jgimv_dT1n
|
|
|
83
83
|
ophyd_async/epics/odin/__init__.py,sha256=7kRqVzwoD8PVtp7Nj9iQWlgbLeoWE_8oiq-B0kixwTE,93
|
|
84
84
|
ophyd_async/epics/odin/_odin_io.py,sha256=YDBrS15PnEKe5SHmz397Emh--lZSQEnbR3G7p8pbShY,6533
|
|
85
85
|
ophyd_async/epics/pmac/__init__.py,sha256=GqJTiJudqE9pu050ZNED09F9tKRfazn0wBsojsMH2gg,273
|
|
86
|
-
ophyd_async/epics/pmac/_pmac_io.py,sha256=
|
|
87
|
-
ophyd_async/epics/pmac/_pmac_trajectory.py,sha256=
|
|
88
|
-
ophyd_async/epics/pmac/_pmac_trajectory_generation.py,sha256=
|
|
89
|
-
ophyd_async/epics/pmac/_utils.py,sha256=
|
|
86
|
+
ophyd_async/epics/pmac/_pmac_io.py,sha256=cbChieNrDWRzrr5Mdsqtm2Azp8sG0KHP9rGeJxmbYrA,4332
|
|
87
|
+
ophyd_async/epics/pmac/_pmac_trajectory.py,sha256=hzAcpLNmFoNceubsjk6mjsmg6-PgSjWUu1a8Exyvi6I,7729
|
|
88
|
+
ophyd_async/epics/pmac/_pmac_trajectory_generation.py,sha256=3IIxXa0r6-2uNnILKLGxp3xosOZx8MubKF-F_OM7uaw,27331
|
|
89
|
+
ophyd_async/epics/pmac/_utils.py,sha256=MfuY6NicT7wkwVIWAZkWoCu1ZoSzy6jda1wLK9XAOLA,8614
|
|
90
90
|
ophyd_async/epics/testing/__init__.py,sha256=aTIv4D2DYrpnGco5RQF8QuLG1SfFkIlTyM2uYEKXltA,522
|
|
91
91
|
ophyd_async/epics/testing/_example_ioc.py,sha256=zb4ZEUzuB2MrSw5ETPLIiHhf-2BRU1Bdxco6Kh4iI1I,3880
|
|
92
92
|
ophyd_async/epics/testing/_utils.py,sha256=9gxpwaWX0HGtacu1LTupcw7viXN8G78RmuNciU_-cjs,1702
|
|
@@ -105,7 +105,7 @@ ophyd_async/fastcs/jungfrau/_signals.py,sha256=8seZCkKTb-xJL0IdB2el8VTEbWNaCvZIh
|
|
|
105
105
|
ophyd_async/fastcs/jungfrau/_utils.py,sha256=QpdWbPT_31Jwyi7INFMRq9hncSZIK_4J3l6wpuppzn8,2875
|
|
106
106
|
ophyd_async/fastcs/odin/__init__.py,sha256=da1PTClDMl-IBkrSvq6JC1lnS-K_BASzCvxVhNxN5Ls,13
|
|
107
107
|
ophyd_async/fastcs/panda/__init__.py,sha256=GbnPqH_13wvyPK1CvRHGAViamKVWHY9n-sTmfAdcnMA,1229
|
|
108
|
-
ophyd_async/fastcs/panda/_block.py,sha256=
|
|
108
|
+
ophyd_async/fastcs/panda/_block.py,sha256=Bffta9IkuSq_NSvidDvLyC1YUrfQCwMhppsu1Te7vec,2679
|
|
109
109
|
ophyd_async/fastcs/panda/_control.py,sha256=xtW3dH_MLQoycgP-4vJtYx1M9alHjWo13iu9UFTgwzY,1306
|
|
110
110
|
ophyd_async/fastcs/panda/_hdf_panda.py,sha256=tL_OWHxlMQcMZGq9sxHLSeag6hP9MRIbTPn1W0u0iNI,1237
|
|
111
111
|
ophyd_async/fastcs/panda/_table.py,sha256=maKGoKypEuYqTSVWGgDO6GMEKOtlDm9Dn5YiYdBzu6c,2486
|
|
@@ -131,17 +131,16 @@ ophyd_async/sim/_pattern_generator.py,sha256=kuxvyX2gIxrywhQRhaO1g8YluBT7LBkE20I
|
|
|
131
131
|
ophyd_async/sim/_point_detector.py,sha256=wMG_ncvm99WMCPihlFyuMEf3UknAxCpB1hpk3uKiENE,3024
|
|
132
132
|
ophyd_async/sim/_stage.py,sha256=_SywbmSQwxf7JLx68qwo0RpiB3oIWlbTLmvRKxUoig0,1602
|
|
133
133
|
ophyd_async/tango/__init__.py,sha256=g9xzjlzPpUAP12YI-kYwfAoLSYPAQdL1S11R2c-cius,60
|
|
134
|
-
ophyd_async/tango/core/__init__.py,sha256=
|
|
135
|
-
ophyd_async/tango/core/_base_device.py,sha256=
|
|
134
|
+
ophyd_async/tango/core/__init__.py,sha256=dO2tG_y61zZFQRQh5L37Ps-IqNf-DGOT77Ov5Kobfhs,1349
|
|
135
|
+
ophyd_async/tango/core/_base_device.py,sha256=X5ncxaWKOfRhhqPyT8tmTBJGc3ldGthw1ZCe_j_M2Tg,5088
|
|
136
136
|
ophyd_async/tango/core/_converters.py,sha256=xI_RhMR8dY6IVORUZVVCL9LdYnEE6TA6BBPX_lTu06w,2183
|
|
137
137
|
ophyd_async/tango/core/_signal.py,sha256=8mIxRVEVjhDN33LDbbKZWGMUYn9Gl5ZMEIYw6GSBTUE,5569
|
|
138
|
-
ophyd_async/tango/core/_tango_readable.py,sha256=ctR6YcBGGatW6Jp2kvddA1hVZ2v1CidPsF9FmJK9BYg,406
|
|
139
138
|
ophyd_async/tango/core/_tango_transport.py,sha256=KxjhHqKADrOvzGi9tbOQXUWdsJ0NKGejWxHItxpUsjg,37401
|
|
140
139
|
ophyd_async/tango/core/_utils.py,sha256=pwT7V1DNWSyPOSzvDZ6OsDZTjaV-pAeDLDlmgtHVcNM,1673
|
|
141
140
|
ophyd_async/tango/demo/__init__.py,sha256=_j-UicTnckuIBp8PnieFMOMnLFGivnaKdmo9o0hYtzc,256
|
|
142
|
-
ophyd_async/tango/demo/_counter.py,sha256=
|
|
141
|
+
ophyd_async/tango/demo/_counter.py,sha256=m6zxOJLbHgCEBAapVc1UiOOqKj5lvrlxjA6mXWMRMjo,1200
|
|
143
142
|
ophyd_async/tango/demo/_detector.py,sha256=X5YWHAjukKZ7iYF1fBNle4CBDj1X5rvj0lnPMOcnRCU,1340
|
|
144
|
-
ophyd_async/tango/demo/_mover.py,sha256=
|
|
143
|
+
ophyd_async/tango/demo/_mover.py,sha256=FyG9g1TLaWoqjbLblqWK8inMuDcNVlioq0MIeD5npz4,2913
|
|
145
144
|
ophyd_async/tango/demo/_tango/__init__.py,sha256=FfONT7vM49nNo3a1Lv-LcMZO9EHv6bv91yY-RnxIib4,85
|
|
146
145
|
ophyd_async/tango/demo/_tango/_servers.py,sha256=putvERDyibibaTbhdWyqZB_axj2fURXqzDsZb9oSW14,2991
|
|
147
146
|
ophyd_async/tango/testing/__init__.py,sha256=l52SmX9XuxZUBuLpOYJzHfskkWVYhx3RkSbGL_wUu5Y,199
|
|
@@ -150,13 +149,13 @@ ophyd_async/tango/testing/_test_config.py,sha256=i3t5d4wjUEtAvvSSZNz_bH_r5VEvUph
|
|
|
150
149
|
ophyd_async/testing/__init__.py,sha256=jDBzUAHGDMfkhd-_9u0CJWEq0E0sPrIGGlLmVzEyxY8,1742
|
|
151
150
|
ophyd_async/testing/__pytest_assert_rewrite.py,sha256=_SU2UfChPgEf7CFY7aYH2B7MLp-07_qYnVLyu6QtDL8,129
|
|
152
151
|
ophyd_async/testing/_assert.py,sha256=Ss_XDToi1ymUfr0Z1r45A2Fmg7-9UOv9gYkJEBsZPv8,8795
|
|
153
|
-
ophyd_async/testing/_mock_signal_utils.py,sha256=
|
|
152
|
+
ophyd_async/testing/_mock_signal_utils.py,sha256=GOjELaRFg9zJKcpeLFXjN7ViMT1AK2Hu52lkLMI5XUc,5393
|
|
154
153
|
ophyd_async/testing/_one_of_everything.py,sha256=U9ui7B-iNHDM3H3hIWUuaCb8Gc2eLlUh0sBHUlQldT0,4741
|
|
155
154
|
ophyd_async/testing/_single_derived.py,sha256=5-HOTzgePcZ354NK_ssVpyIbJoJmKyjVQCxSwQXUC-4,2730
|
|
156
155
|
ophyd_async/testing/_utils.py,sha256=zClRo5ve8RGia7wQnby41W-Zprj-slOA5da1LfYnuhw,45
|
|
157
156
|
ophyd_async/testing/_wait_for_pending.py,sha256=YZAR48n-CW0GsPey3zFRzMJ4byDAr3HvMIoawjmTrHw,732
|
|
158
|
-
ophyd_async-0.13.
|
|
159
|
-
ophyd_async-0.13.
|
|
160
|
-
ophyd_async-0.13.
|
|
161
|
-
ophyd_async-0.13.
|
|
162
|
-
ophyd_async-0.13.
|
|
157
|
+
ophyd_async-0.13.7.dist-info/licenses/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
|
|
158
|
+
ophyd_async-0.13.7.dist-info/METADATA,sha256=D28G3xy4fiF7xtLVoy10CqOiI7ZLDs2z1MO6DICwVdA,5703
|
|
159
|
+
ophyd_async-0.13.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
160
|
+
ophyd_async-0.13.7.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
|
|
161
|
+
ophyd_async-0.13.7.dist-info/RECORD,,
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from ophyd_async.core import StandardReadable
|
|
4
|
-
|
|
5
|
-
from ._base_device import TangoDevice
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class TangoReadable(TangoDevice, StandardReadable):
|
|
9
|
-
def __init__(
|
|
10
|
-
self,
|
|
11
|
-
trl: str | None = None,
|
|
12
|
-
name: str = "",
|
|
13
|
-
auto_fill_signals: bool = True,
|
|
14
|
-
) -> None:
|
|
15
|
-
TangoDevice.__init__(self, trl, name=name, auto_fill_signals=auto_fill_signals)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|