DAQ (Data Acquisition)¤
Interface¤
Bases: Instrument
Parameters:
-
(name¤str) –Channel-name prefix for published data.
-
(driver¤DAQDriverBase) –Concrete DAQ driver; owns its own transport::
daq = InstroDAQ( "myDAQ", driver=Keysight34980A("USB0::0x0957::0x0507::MY44001757::INSTR"), )
-
(publishers¤list[Publisher] | None, default:None) –Publishers that receive emitted Measurement/Command data.
-
–**kwargs¤Default tags applied to every emitted Measurement/Command. Pass
dataset_rid="<rid>"to auto-create a NominalCorePublisher (uses the on-disk 'default' Nominal credential).
driver
property
¤
driver: DAQDriverBase
The underlying vendor driver. Source of truth for all channel/timing state.
channels
property
¤
channels: tuple[DAQChannel, ...]
Frozen snapshot of all configured AI/AO/DI/DO channels (excludes relays).
ai_channels
property
¤
ai_channels: Mapping[str, AnalogChannel]
Frozen snapshot of configured AI channels, keyed by alias.
ao_channels
property
¤
ao_channels: Mapping[str, AnalogChannel]
Frozen snapshot of configured AO channels, keyed by alias.
di_channels
property
¤
di_channels: Mapping[str, DigitalChannel]
Frozen snapshot of configured DI channels, keyed by alias.
do_channels
property
¤
do_channels: Mapping[str, DigitalChannel]
Frozen snapshot of configured DO channels, keyed by alias.
relay_channels
property
¤
relay_channels: Mapping[str, RelayChannel]
Frozen snapshot of configured relay channels, keyed by alias.
background_interval
property
writable
¤
background_interval: float
Always 0 for DAQ: blocking reads implicitly time the daemon loop via samples_per_channel.
background_enable
property
writable
¤
background_enable: bool
Whether the background daemon is enabled.
add_publisher
¤
add_publisher(publisher: Publisher)
Register a publisher to receive this instrument's Measurement/Command data.
publish
¤
publish(data: Measurement | Command, **kwargs)
Fan data out to every configured publisher; kwargs pass through.
add_background_daemon_function
¤
add_background_daemon_function(method: Callable, *args, **kwargs)
Append method to the daemon's call list. Use define_background_daemon to replace instead.
get_channel
¤
get_channel(
channel_name: str,
length: int = 1,
wait_for_latest: bool = False,
timeout: float = 10.0,
) -> Measurement
Return the most recent length samples for channel_name from the in-memory buffer.
Parameters:
-
(channel_name¤str) –Name of the channel to retrieve.
-
(length¤int, default:1) –Number of trailing samples to return.
-
(wait_for_latest¤bool, default:False) –Block until at least
lengthnew values arrive. -
(timeout¤float, default:10.0) –Seconds to wait when
wait_for_latest=True.
Raises:
-
RuntimeError–No background buffer;
start()was not called. -
ChannelNotFoundTimeoutError–wait_for_latest=Trueand channel did not appear withintimeout. -
ChannelValueTimeoutError–wait_for_latest=Trueand values did not arrive withintimeout.
define_background_daemon
¤
define_background_daemon(method: Callable, *args, **kwargs)
Replace all daemon functions with a single method (called with the given args).
configure_analog_channel
¤
configure_analog_channel(
direction: Direction,
physical_channel: str,
alias: str | None = None,
range_min: float = -10.0,
range_max: float = 10.0,
scaler: Scaler | None = None,
terminal_config: TerminalConfig | None = None,
)
Configure an analog channel.
Parameters:
-
(direction¤Direction) –INPUTorOUTPUT. -
(physical_channel¤str) –Vendor-specific channel id (e.g.
"ai0"or"Dev1/ai0"). -
(alias¤str | None, default:None) –Friendly name; defaults to
physical_channel. -
(range_min¤float, default:-10.0) –Lower voltage range (volts).
-
(range_max¤float, default:10.0) –Upper voltage range (volts).
-
(scaler¤Scaler | None, default:None) –Optional
Scalerapplied to AI samples after read. -
(terminal_config¤TerminalConfig | None, default:None) –Terminal wiring (RSE / NRSE / DIFF) for the channel.
configure_ai_sample_rate
¤
configure_ai_sample_rate(
sample_rate: float, samples_per_channel: int | None = None, **kwargs
)
start
¤
start(**kwargs)
Start hardware-timed acquisition.
Parameters:
-
–**kwargs¤channel_type(NI only) selects which DAQmx task to start.
read_analog
¤
read_analog(**kwargs) -> Measurement | list[Measurement]
Dispatch a hardware-timed buffer fetch or a software-timed conversion based on configuration.
Each branch publishes its own Measurements; this dispatcher does not. Hardware-timed with the background daemon running raises — the daemon owns the buffer. Returns a single Measurement when channels share a timebase, otherwise one Measurement per timebase cluster.
write_analog_value
¤
Write value (volts) to AO channel (alias). Raises KeyError if channel isn't configured.
configure_digital_line
¤
configure_digital_line(
direction: Direction,
physical_channel: str,
logic: Logic,
logic_level: float | None = None,
alias: str | None = None,
)
Configure a digital line channel.
Parameters:
-
(direction¤Direction) –INPUTorOUTPUT. -
(physical_channel¤str) –Vendor-specific line id (e.g.
"port0/line3"on NI,"5101/3"on Keysight,"FIO0"on LabJack). -
(logic¤Logic) –Active-
HIGHor active-LOW. -
(logic_level¤float | None, default:None) –Voltage threshold (volts); the driver default is used when
None. -
(alias¤str | None, default:None) –Friendly name; defaults to
physical_channel.
configure_digital_port
¤
configure_digital_port(
direction: Direction,
physical_channel: str,
logic: Logic,
port_width: DigitalPortWidth,
logic_level: float | None = None,
alias: str | None = None,
)
Configure a digital port channel.
Parameters:
-
(direction¤Direction) –INPUTorOUTPUT. -
(physical_channel¤str) –Vendor-specific port id (e.g.
"port0"on NI,"5101"on Keysight,"AUXPORT0"on MCC). -
(logic¤Logic) –Active-
HIGHor active-LOW. -
(port_width¤DigitalPortWidth) –Port width in bits (8/16/32/64).
-
(logic_level¤float | None, default:None) –Voltage threshold (volts); the driver default is used when
None. -
(alias¤str | None, default:None) –Friendly name; defaults to
physical_channel.
write_digital_line
¤
Write 0/1 to DO line channel (alias). Raises KeyError if channel isn't configured.
read_digital_line
¤
read_digital_line(channel: str, **kwargs) -> Measurement
Read DI line channel (alias). Raises KeyError if channel isn't configured.
write_digital_port
¤
Write data to DO port channel (alias). Raises KeyError if channel isn't configured.
read_digital_port
¤
read_digital_port(channel: str, **kwargs) -> Measurement
Read DI port channel (alias). Raises KeyError if channel isn't configured.
configure_relay_channel
¤
Configure a relay channel (physical_channel e.g. "3101" = slot 3 / channel 101).
close_relay
¤
Close relay channel (alias) — connects the circuit.
open_relay
¤
Open relay channel (alias) — disconnects the circuit.
get_actual_sample_rate
¤
get_actual_sample_rate() -> float | None
Hardware's actual sample rate after start(); None if unsupported or not started.
get_points_in_buffer
¤
get_points_in_buffer(**kwargs) -> Measurement
Publish the current DAQ buffer depth on channel {name}.buffer.
Types & Configuration¤
DAQ shared types: vendors, channel types, terminal configs, hardware-timing config.
ChannelType
¤
Logic
¤
Direction
¤
TerminalConfig
¤
HWTimingConfig
dataclass
¤
DAQChannel
dataclass
¤
AnalogChannel
dataclass
¤
AnalogChannel(
range_max: float,
range_min: float,
scaler: Scaler | None,
terminal_config: TerminalConfig | None = None,
*,
physical_channel: str,
alias: str,
direction: Direction,
)
Bases: DAQChannel
DigitalPortWidth
¤
DigitalChannel
dataclass
¤
DigitalPortChannel
dataclass
¤
DigitalPortChannel(
logic_level: float | None,
logic: Logic,
width: DigitalPortWidth,
*,
physical_channel: str,
alias: str,
direction: Direction,
)
Bases: DigitalChannel
DigitalLineChannel
dataclass
¤
DigitalLineChannel(
logic_level: float | None,
logic: Logic,
bit_position: int | None = None,
*,
physical_channel: str,
alias: str,
direction: Direction,
)
Bases: DigitalChannel
RelayChannel
dataclass
¤
Scaling¤
Thermocouple Scaling¤
Driver Interface¤
Bases: ABC
Vendor DAQ driver contract.
The driver is the single source of truth for configured channels and
timing config, held in private dicts/slots that __init__ initializes so
every concrete driver has the same shape; subclasses call
super().__init__() and then populate those privates inside their own
configure_* methods (self._ai_channels[channel.alias] = channel,
self._ai_hw_timing_config = hw_timing_config, etc.). Read-only
@property accessors hand back frozen snapshots so the state can't be
mutated from outside the configure_* path; InstroDAQ exposes the
same snapshots for user introspection — it does not keep its own copies.
channels
property
¤
channels: tuple[DAQChannel, ...]
Frozen snapshot of all configured AI/AO/DI/DO channels (excludes relays).
ai_channels
property
¤
ai_channels: Mapping[str, AnalogChannel]
Frozen snapshot of configured AI channels, keyed by alias.
ao_channels
property
¤
ao_channels: Mapping[str, AnalogChannel]
Frozen snapshot of configured AO channels, keyed by alias.
di_channels
property
¤
di_channels: Mapping[str, DigitalChannel]
Frozen snapshot of configured DI channels, keyed by alias.
do_channels
property
¤
do_channels: Mapping[str, DigitalChannel]
Frozen snapshot of configured DO channels, keyed by alias.
relay_channels
property
¤
relay_channels: Mapping[str, RelayChannel]
Frozen snapshot of configured relay channels, keyed by alias.
open
abstractmethod
¤
open()
Open the underlying transport (or verify the device is present, for handle-less SDKs).
configure_ai_channel
abstractmethod
¤
configure_ai_channel(channel: AnalogChannel)
Register an AI channel with the underlying driver (range, terminal mode, scaler — vendor-specific).
configure_ao_channel
¤
configure_ao_channel(channel: AnalogChannel)
Register an AO channel. Override if the driver supports analog output.
configure_ai_hw_timing
abstractmethod
¤
configure_ai_hw_timing(hw_timing_config: HWTimingConfig)
Configure hardware-timed AI sampling at hw_timing_config.sample_rate.
Called before start() whenever InstroDAQ.configure_ai_sample_rate()
is invoked. The driver should program the sample clock and any
samples_per_channel buffer sizing the underlying SDK requires.
configure_di_line_channel
abstractmethod
¤
configure_di_line_channel(
physical_channel: str,
logic: Logic,
logic_level: float | None = None,
alias: str | None = None,
)
Parse, program, and register a DI line channel.
configure_do_line_channel
abstractmethod
¤
configure_do_line_channel(
physical_channel: str,
logic: Logic,
logic_level: float | None = None,
alias: str | None = None,
)
Parse, program, and register a DO line channel.
configure_di_port_channel
¤
configure_di_port_channel(
physical_channel: str,
logic: Logic,
port_width: DigitalPortWidth,
logic_level: float | None = None,
alias: str | None = None,
)
Parse, program, and register a DI port channel. Override if the driver supports port-mode digital input.
configure_do_port_channel
¤
configure_do_port_channel(
physical_channel: str,
logic: Logic,
port_width: DigitalPortWidth,
logic_level: float | None = None,
alias: str | None = None,
)
Parse, program, and register a DO port channel. Override if the driver supports port-mode digital output.
start
abstractmethod
¤
start(**kwargs)
Start hardware-timed acquisition.
InstroDAQ passes channel_type=<ChannelType> when the user
targets a specific task (e.g. on NI, where AI/AO/DI/DO each have their
own DAQmx task). Drivers without that distinction can ignore it.
stop
abstractmethod
¤
stop(**kwargs)
Stop a running acquisition and release any scan buffers. channel_type mirrors :meth:start.
read_analog
abstractmethod
¤
read_analog() -> Any
Software-timed read of every configured AI channel.
Returns a vendor-specific payload that _read_to_measurements then
unpacks into Measurements. response.dt should be None so
the wrapper timestamps with wall-clock time.
fetch_analog
abstractmethod
¤
fetch_analog() -> Any
Block until samples_per_channel new AI samples are available, then return them.
Drivers should set self.points_in_buffer for buffer-depth
telemetry and return dt (ns per sample) so the wrapper can
build contiguous timestamps via HWTimestamper.
get_actual_sample_rate
¤
get_actual_sample_rate() -> float | None
Actual hardware sample rate achieved after start().
Default returns None (driver doesn't know or hasn't started).
Override on drivers whose SDK reports the effective rate (NI, MCC,
LabJack T-series all do).
write_analog_value
¤
write_analog_value(channel: AnalogChannel, value: float)
Write value to AO channel. Override if the driver supports analog output.
write_digital_line
abstractmethod
¤
write_digital_line(channel: DigitalChannel, data: int)
Drive a single DO line. data is 0 or 1 (active-low channel.logic is handled in the driver).
read_digital_line
abstractmethod
¤
read_digital_line(channel: DigitalChannel) -> int
Sample a single DI line. Returns 0 or 1 after applying channel.logic.
write_digital_port
abstractmethod
¤
write_digital_port(channel: DigitalChannel, data: int)
Drive a multi-line DO port. data is an N-bit integer; bit i controls line i.
read_digital_port
abstractmethod
¤
read_digital_port(channel: DigitalChannel) -> int
Sample a multi-line DI port. Returns an N-bit integer; bit i reflects line i.
define_relay_channel
¤
define_relay_channel(
physical_channel: str, alias: str | None = None
) -> RelayChannel
Build a RelayChannel for physical_channel (e.g. "3101" = slot 3 / channel 101).
Default implementation suits the Keysight 34980A's slot/channel
addressing; override if the driver needs different parsing. Overrides
must also record the resulting channel on self._relay_channels.
close_relay
¤
close_relay(channel: RelayChannel)
Close the relay (connect the circuit). Override if the driver supports relays.
open_relay
¤
open_relay(channel: RelayChannel)
Open the relay (disconnect the circuit). Override if the driver supports relays.
Contiguous nanosecond timestamps for hardware-timed DAQ batches.
Anchors to the wall clock exactly once via seed(), then advances by
sample period on every next_batch() call — eliminates timestamp overlap
when consecutive reads return in rapid succession.
seed
classmethod
¤
Anchor the timeline at t_wall ns (read-return time of the first batch).
Vendor Drivers¤
Keysight 34980A¤
Keysight 34980A Multifunction Switch/Measure Unit DAQ driver.
KeysightData
dataclass
¤
Keysight34980A
¤
Keysight34980A(
visa_resource: str | VisaConfig, *, sync_system_clock: bool = True
)
Bases: DAQDriverBase
Keysight 34980A Multifunction Switch/Measure Unit.
Parameters:
-
(visa_resource¤str | VisaConfig) –VISA resource string or full
VisaConfig. -
(sync_system_clock¤bool, default:True) –Sync the instrument clock to host UTC on
open()so returned timestamps align with the host. Enabled by default.
channels
property
¤
channels: tuple[DAQChannel, ...]
Frozen snapshot of all configured AI/AO/DI/DO channels (excludes relays).
ai_channels
property
¤
ai_channels: Mapping[str, AnalogChannel]
Frozen snapshot of configured AI channels, keyed by alias.
ao_channels
property
¤
ao_channels: Mapping[str, AnalogChannel]
Frozen snapshot of configured AO channels, keyed by alias.
di_channels
property
¤
di_channels: Mapping[str, DigitalChannel]
Frozen snapshot of configured DI channels, keyed by alias.
do_channels
property
¤
do_channels: Mapping[str, DigitalChannel]
Frozen snapshot of configured DO channels, keyed by alias.
relay_channels
property
¤
relay_channels: Mapping[str, RelayChannel]
Frozen snapshot of configured relay channels, keyed by alias.
configure_ai_channel
¤
configure_ai_channel(channel: AnalogChannel)
Configure an AI channel: CONF:VOLT:DC at computed range, then add to ROUT:SCAN and enable timestamps.
configure_ai_hw_timing
¤
configure_ai_hw_timing(hw_timing_config: HWTimingConfig)
Configure TRIG:SOUR TIMER at the configured sample period and infinite count.
fetch_analog
¤
fetch_analog() -> KeysightData
Block until the buffer holds at least one full per-channel batch, then drain a channel-aligned chunk.
configure_di_line_channel
¤
configure_di_line_channel(
physical_channel: str,
logic: Logic,
logic_level: float | None = None,
alias: str | None = None,
)
Parse MNNN/B (slot/channel/bit), program the port for DI, and register the line.
configure_do_line_channel
¤
configure_do_line_channel(
physical_channel: str,
logic: Logic,
logic_level: float | None = None,
alias: str | None = None,
)
Parse MNNN/B (slot/channel/bit), program the port for DO, and register the line.
configure_di_port_channel
¤
configure_di_port_channel(
physical_channel: str,
logic: Logic,
port_width: DigitalPortWidth,
logic_level: float | None = None,
alias: str | None = None,
)
Parse MNNN (slot/channel), program the port for DI, and register the port.
configure_do_port_channel
¤
configure_do_port_channel(
physical_channel: str,
logic: Logic,
port_width: DigitalPortWidth,
logic_level: float | None = None,
alias: str | None = None,
)
Parse MNNN (slot/channel), program the port for DO, and register the port.
write_digital_port
¤
write_digital_port(channel: DigitalChannel, data: int)
Drive a DO port as one N-bit integer. Active-low is applied in hardware via CONF:DIG:POL.
read_digital_port
¤
read_digital_port(channel: DigitalChannel) -> int
Sample a DI port as one N-bit integer. Active-low is applied in hardware via CONF:DIG:POL.
configure_ao_channel
¤
configure_ao_channel(channel: AnalogChannel)
Register an AO channel. Override if the driver supports analog output.
get_actual_sample_rate
¤
get_actual_sample_rate() -> float | None
Actual hardware sample rate achieved after start().
Default returns None (driver doesn't know or hasn't started).
Override on drivers whose SDK reports the effective rate (NI, MCC,
LabJack T-series all do).
write_analog_value
¤
write_analog_value(channel: AnalogChannel, value: float)
Write value to AO channel. Override if the driver supports analog output.
define_relay_channel
¤
define_relay_channel(
physical_channel: str, alias: str | None = None
) -> RelayChannel
Build a RelayChannel for physical_channel (e.g. "3101" = slot 3 / channel 101).
Default implementation suits the Keysight 34980A's slot/channel
addressing; override if the driver needs different parsing. Overrides
must also record the resulting channel on self._relay_channels.
keysight_str_to_ns
¤
Convert a Keysight "YYYY,MM,DD,HH,MM,SS.sss" timestamp (UTC) to ns since the Unix epoch.
parse_datastring
¤
Split a Keysight reading/timestamp data string into (measurements, timestamps_ns).