refactor(nidaq): replace placeholder signals with DynamicSignal statistic groups
CI for debye_bec / test (push) Successful in 1m5s

This commit is contained in:
2026-08-05 19:48:02 +02:00
parent eaf6b3ace5
commit c92c40d1ef
2 changed files with 90 additions and 115 deletions
+64 -115
View File
@@ -10,7 +10,7 @@ from ophyd import Device, DeviceStatus, EpicsSignal, EpicsSignalRO, Kind
from ophyd.status import WaitTimeoutError
from ophyd_devices import CompareStatus, ProgressSignal, StatusBase, TransitionStatus
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
from ophyd_devices.sim.sim_signals import SetableSignal
from ophyd_devices.utils.bec_signals import DynamicSignal
from debye_bec.devices.nidaq.nidaq_enums import (
EncoderFactors,
@@ -27,6 +27,27 @@ if TYPE_CHECKING: # pragma: no cover
logger = bec_logger.logger
#: Channels per statistic group. Group sub-signals are emitted as
#: 'nidaq_<group>_<channel>' (e.g. 'nidaq_mean_ai0') in BOTH trigger modes.
NIDAQ_MEAN_CHANNELS = [f"ai{i}" for i in range(8)] + [f"ci{i}" for i in range(18)]
NIDAQ_MAX_CHANNELS = [f"di{i}" for i in range(5)]
NIDAQ_STD_DEV_CHANNELS = [f"ai{i}" for i in range(8)] + [f"ci{i}" for i in range(18)]
NIDAQ_STREAM_CHANNELS = [
"energy",
"enc",
"smpl_abs",
"smpl_fluo",
"ref_abs",
"cisum",
"rle",
"xas_timestamp",
"xrd_timestamp",
"xrd_angle",
"xrd_energy",
"xrd_ai0_mean",
"xrd_ai0_std_dev",
]
class NidaqError(Exception):
"""Nidaq specific error"""
@@ -36,124 +57,43 @@ class NidaqControl(Device):
"""Nidaq control class with all PVs"""
# fmt: off
### Readback PVs for EpicsEmitter ###
energy = Cpt(SetableSignal, value=0, kind=Kind.normal)
ai0 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI0", kind=Kind.omitted, doc="EPICS analog input 0", auto_monitor=True)
ai1 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI1", kind=Kind.omitted, doc="EPICS analog input 1", auto_monitor=True)
ai2 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI2", kind=Kind.omitted, doc="EPICS analog input 2", auto_monitor=True)
ai3 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI3", kind=Kind.omitted, doc="EPICS analog input 3", auto_monitor=True)
ai4 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI4", kind=Kind.omitted, doc="EPICS analog input 4", auto_monitor=True)
ai5 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI5", kind=Kind.omitted, doc="EPICS analog input 5", auto_monitor=True)
ai6 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI6", kind=Kind.omitted, doc="EPICS analog input 6", auto_monitor=True)
ai7 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI7", kind=Kind.omitted, doc="EPICS analog input 7", auto_monitor=True)
smpl_abs = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream sample absorption")
smpl_fluo = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream sample fluorescence")
ref_abs = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream reference absorption")
cisum = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter sum")
ci0 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI0", kind=Kind.omitted, doc="EPICS counter input 0", auto_monitor=True)
ci1 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI1", kind=Kind.omitted, doc="EPICS counter input 1", auto_monitor=True)
ci2 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI2", kind=Kind.omitted, doc="EPICS counter input 2", auto_monitor=True)
ci3 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI3", kind=Kind.omitted, doc="EPICS counter input 3", auto_monitor=True)
ci4 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI4", kind=Kind.omitted, doc="EPICS counter input 4", auto_monitor=True)
ci5 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI5", kind=Kind.omitted, doc="EPICS counter input 5", auto_monitor=True)
ci6 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI6", kind=Kind.omitted, doc="EPICS counter input 6", auto_monitor=True)
ci7 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI7", kind=Kind.omitted, doc="EPICS counter input 7", auto_monitor=True)
ci8 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI8", kind=Kind.omitted, doc="EPICS counter input 8", auto_monitor=True)
ci9 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI9", kind=Kind.omitted, doc="EPICS counter input 9", auto_monitor=True)
ci10 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI10", kind=Kind.omitted, doc="EPICS counter input 0", auto_monitor=True)
ci11 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI11", kind=Kind.omitted, doc="EPICS counter input 1", auto_monitor=True)
ci12 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI12", kind=Kind.omitted, doc="EPICS counter input 2", auto_monitor=True)
ci13 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI13", kind=Kind.omitted, doc="EPICS counter input 3", auto_monitor=True)
ci14 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI14", kind=Kind.omitted, doc="EPICS counter input 4", auto_monitor=True)
ci15 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI15", kind=Kind.omitted, doc="EPICS counter input 5", auto_monitor=True)
ci16 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI16", kind=Kind.omitted, doc="EPICS counter input 6", auto_monitor=True)
ci17 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI17", kind=Kind.omitted, doc="EPICS counter input 7", auto_monitor=True)
ai0_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 0, MEAN")
ai1_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 1, MEAN")
ai2_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 2, MEAN")
ai3_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 3, MEAN")
ai4_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 4, MEAN")
ai5_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 5, MEAN")
ai6_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 6, MEAN")
ai7_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 7, MEAN")
di0 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI0", kind=Kind.omitted, doc="EPICS digital input 0", auto_monitor=True)
di1 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI1", kind=Kind.omitted, doc="EPICS digital input 1", auto_monitor=True)
di2 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI2", kind=Kind.omitted, doc="EPICS digital input 2", auto_monitor=True)
di3 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI3", kind=Kind.omitted, doc="EPICS digital input 3", auto_monitor=True)
di4 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI4", kind=Kind.omitted, doc="EPICS digital input 4", auto_monitor=True)
di0_max = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream digital input 0, MAX")
di1_max = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream digital input 1, MAX")
di2_max = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream digital input 2, MAX")
di3_max = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream digital input 3, MAX")
di4_max = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream digital input 4, MAX")
enc_epics = Cpt(EpicsSignalRO, suffix="NIDAQ-ENC", kind=Kind.omitted, doc="EPICS Encoder reading", auto_monitor=True)
ci0_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 0, MEAN")
ci1_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 1, MEAN")
ci2_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 2, MEAN")
ci3_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 3, MEAN")
ci4_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 4, MEAN")
ci5_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 5, MEAN")
ci6_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 6, MEAN")
ci7_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 7, MEAN")
ci8_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 8, MEAN")
ci9_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 9, MEAN")
ci10_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 10, MEAN")
ci11_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 11, MEAN")
ci12_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 12, MEAN")
ci13_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 13, MEAN")
ci14_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 14, MEAN")
ci15_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 15, MEAN")
ci16_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 16, MEAN")
ci17_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 17, MEAN")
ai0 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI0", kind=Kind.normal, doc="EPICS analog input 0", auto_monitor=True)
ai1 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI1", kind=Kind.normal, doc="EPICS analog input 1", auto_monitor=True)
ai2 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI2", kind=Kind.normal, doc="EPICS analog input 2", auto_monitor=True)
ai3 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI3", kind=Kind.normal, doc="EPICS analog input 3", auto_monitor=True)
ai4 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI4", kind=Kind.normal, doc="EPICS analog input 4", auto_monitor=True)
ai5 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI5", kind=Kind.normal, doc="EPICS analog input 5", auto_monitor=True)
ai6 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI6", kind=Kind.normal, doc="EPICS analog input 6", auto_monitor=True)
ai7 = Cpt(EpicsSignalRO, suffix="NIDAQ-AI7", kind=Kind.normal, doc="EPICS analog input 7", auto_monitor=True)
ci0 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI0", kind=Kind.normal, doc="EPICS counter input 0", auto_monitor=True)
ci1 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI1", kind=Kind.normal, doc="EPICS counter input 1", auto_monitor=True)
ci2 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI2", kind=Kind.normal, doc="EPICS counter input 2", auto_monitor=True)
ci3 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI3", kind=Kind.normal, doc="EPICS counter input 3", auto_monitor=True)
ci4 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI4", kind=Kind.normal, doc="EPICS counter input 4", auto_monitor=True)
ci5 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI5", kind=Kind.normal, doc="EPICS counter input 5", auto_monitor=True)
ci6 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI6", kind=Kind.normal, doc="EPICS counter input 6", auto_monitor=True)
ci7 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI7", kind=Kind.normal, doc="EPICS counter input 7", auto_monitor=True)
ci8 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI8", kind=Kind.normal, doc="EPICS counter input 8", auto_monitor=True)
ci9 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI9", kind=Kind.normal, doc="EPICS counter input 9", auto_monitor=True)
ci10 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI10", kind=Kind.normal, doc="EPICS counter input 0", auto_monitor=True)
ci11 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI11", kind=Kind.normal, doc="EPICS counter input 1", auto_monitor=True)
ci12 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI12", kind=Kind.normal, doc="EPICS counter input 2", auto_monitor=True)
ci13 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI13", kind=Kind.normal, doc="EPICS counter input 3", auto_monitor=True)
ci14 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI14", kind=Kind.normal, doc="EPICS counter input 4", auto_monitor=True)
ci15 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI15", kind=Kind.normal, doc="EPICS counter input 5", auto_monitor=True)
ci16 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI16", kind=Kind.normal, doc="EPICS counter input 6", auto_monitor=True)
ci17 = Cpt(EpicsSignalRO, suffix="NIDAQ-CI17", kind=Kind.normal, doc="EPICS counter input 7", auto_monitor=True)
di0 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI0", kind=Kind.normal, doc="EPICS digital input 0", auto_monitor=True)
di1 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI1", kind=Kind.normal, doc="EPICS digital input 1", auto_monitor=True)
di2 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI2", kind=Kind.normal, doc="EPICS digital input 2", auto_monitor=True)
di3 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI3", kind=Kind.normal, doc="EPICS digital input 3", auto_monitor=True)
di4 = Cpt(EpicsSignalRO, suffix="NIDAQ-DI4", kind=Kind.normal, doc="EPICS digital input 4", auto_monitor=True)
enc_epics = Cpt(EpicsSignalRO, suffix="NIDAQ-ENC", kind=Kind.normal, doc="EPICS Encoder reading", auto_monitor=True)
energy_epics = Cpt(EpicsSignalRO, suffix="NIDAQ-ENERGY", kind=Kind.normal, doc="EPICS Energy reading", auto_monitor=True)
### Readback for BEC emitter ###
ai0_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 0, STD")
ai1_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 1, STD")
ai2_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 2, STD")
ai3_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 3, STD")
ai4_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 4, STD")
ai5_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 5, STD")
ai6_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 6, STD")
ai7_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream analog input 7, STD")
ci0_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 0. STD")
ci1_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 1. STD")
ci2_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 2. STD")
ci3_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 3. STD")
ci4_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 4. STD")
ci5_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 5. STD")
ci6_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 6. STD")
ci7_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 7. STD")
ci8_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 8. STD")
ci9_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 9. STD")
ci10_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 10. STD")
ci11_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 11. STD")
ci12_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 12. STD")
ci13_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 13. STD")
ci14_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 14. STD")
ci15_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 15. STD")
ci16_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 16. STD")
ci17_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream counter input 17. STD")
xas_timestamp = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream XAS timestamp")
xrd_timestamp = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream XRD timestamp")
xrd_angle = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream XRD angle")
xrd_energy = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream XRD energy")
xrd_ai0_mean = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream XRD ai0 mean")
xrd_ai0_std_dev = Cpt(SetableSignal, value=0, kind=Kind.normal, doc="NIDAQ stream XRD ai0 std dev")
enc = Cpt(SetableSignal, value=0, kind=Kind.normal)
rle = Cpt(SetableSignal, value=0, kind=Kind.normal)
energy_epics = Cpt(EpicsSignalRO, suffix="NIDAQ-ENERGY", kind=Kind.omitted, doc="EPICS Energy reading", auto_monitor=True)
### Control PVs ###
@@ -218,6 +158,15 @@ class Nidaq(PSIDeviceBase, NidaqControl):
progress_signal = Cpt(ProgressSignal, name="progress_signal")
# fmt: off
### Statistic groups: emitted as nidaq_<group>_<channel> in both trigger modes ###
#TODO decide on how to group signals, statistic groupd, analog/counter/digital etc.
mean = Cpt(DynamicSignal, name="mean", ndim=1, max_size=1000, signals=NIDAQ_MEAN_CHANNELS, async_update={"type": "add", "max_shape": [None]}, doc="Per-oscillation means (HW) / synchronous readbacks (SW)")
max = Cpt(DynamicSignal, name="max", ndim=1, max_size=1000, signals=NIDAQ_MAX_CHANNELS, async_update={"type": "add", "max_shape": [None]}, doc="Per-oscillation maxima (HW) / synchronous readbacks (SW)")
std_dev = Cpt(DynamicSignal, name="std_dev", ndim=1, max_size=1000, signals=NIDAQ_STD_DEV_CHANNELS, async_update={"type": "add", "max_shape": [None]}, doc="Per-oscillation standard deviations (HW only)")
stream = Cpt(DynamicSignal, name="stream", ndim=1, max_size=1000, signals=NIDAQ_STREAM_CHANNELS, async_update={"type": "add", "max_shape": [None]}, doc="Energy, encoder, derived and XRD channels")
# fmt: on
USER_ACCESS = ["set_config"]
def __init__(self, prefix: str = "", *, name: str, scan_info: ScanInfo = None, **kwargs):
+26
View File
@@ -182,3 +182,29 @@ def test_on_complete(mock_nidaq, scan_info_mock):
dev.stop()
status.wait(timeout=5)
assert status.done is True
########## DynamicSignal statistic groups ##########
from ophyd import Kind
from ophyd_devices.utils.bec_signals import DynamicSignal
def test_statistic_groups_and_omitted_epics(mock_nidaq):
"""Groups own the unified namespace; EPICS scalars are silent data sources.
DynamicSignal is deliberate (per the NIDAQ maintainers, the active channel
set cannot be predicted upfront): channel names are validated, batch
completeness is not.
"""
dev = mock_nidaq
assert isinstance(dev.mean, DynamicSignal)
assert dev.mean.strict_signal_validation is False
assert dev.mean.name == "nidaq_mean"
assert dev.max.name == "nidaq_max"
assert dev.std_dev.name == "nidaq_std_dev"
assert dev.stream.name == "nidaq_stream"
# EPICS scalars demoted: no longer in the readout namespace
assert dev.ai0.kind == Kind.omitted
assert dev.enc_epics.kind == Kind.omitted
assert "nidaq_ai0" not in dev.read()