Skip to content

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).

name instance-attribute ¤

name = name

legacy_naming instance-attribute ¤

legacy_naming = legacy_naming

publishers instance-attribute ¤

publishers = publishers or []

default_tags instance-attribute ¤

default_tags: dict[str, str] = {}

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 length new 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=True and channel did not appear within timeout.

  • ChannelValueTimeoutError

    wait_for_latest=True and values did not arrive within timeout.

define_background_daemon ¤

define_background_daemon(method: Callable, *args, **kwargs)

Replace all daemon functions with a single method (called with the given args).

open ¤

open()

Open the underlying driver.

close ¤

close()

Close the underlying driver and stop the daemon.

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) –

    INPUT or OUTPUT.

  • 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 Scaler applied 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
)

Configure the hardware sample clock for AI channels.

Parameters:

  • sample_rate ¤

    (float) –

    Sample rate (Hz). Applies to all AI channels.

  • samples_per_channel ¤

    (int | None, default: None ) –

    Samples per channel per read_analog() call; defaults to 10 % of sample_rate (e.g. 100 at 1 kHz).

start ¤

start(**kwargs)

Start hardware-timed acquisition.

Parameters:

  • **kwargs ¤

    channel_type (NI only) selects which DAQmx task to start.

stop ¤

stop(**kwargs)

Stop the DAQ device.

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_analog_value(channel: str, value: float, **kwargs) -> Command

Write value (volts) to AO channel (alias). Raises KeyError if channel isn't configured.

configure_digital_channel ¤

configure_digital_channel(
    direction: Direction,
    physical_channel: str,
    logic: Logic,
    logic_level: float | None = None,
    alias: str | None = None,
    port_width: DigitalPortWidth | None = None,
)

Configure a digital channel.

Parameters:

  • direction ¤

    (Direction) –

    INPUT or OUTPUT.

  • physical_channel ¤

    (str) –

    Vendor-specific id (e.g. "di0" or "port0/line0").

  • logic ¤

    (Logic) –

    Active-HIGH or 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.

  • port_width ¤

    (DigitalPortWidth | None, default: None ) –

    Port width in bits (8/16/32/64) when treating the channel as a port rather than a line.

write_digital_line ¤

write_digital_line(channel: str, data: int, **kwargs) -> Command

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_digital_port(channel: str, data: int, **kwargs) -> Command

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_relay_channel(
    physical_channel: str, alias: str | None = None
)

Configure a relay channel (physical_channel e.g. "3101" = slot 3 / channel 101).

close_relay ¤

close_relay(channel: str, **kwargs) -> Command

Close relay channel (alias) — connects the circuit.

open_relay ¤

open_relay(channel: str, **kwargs) -> Command

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.

DAQVendor ¤

Bases: Enum

NI class-attribute instance-attribute ¤

NI = 'NI DAQmx'

LABJACK_T_SERIES class-attribute instance-attribute ¤

LABJACK_T_SERIES = 'LabJack T-Series'

KEYSIGHT_34980 class-attribute instance-attribute ¤

KEYSIGHT_34980 = 'KEYSIGHT_34980'

MCC class-attribute instance-attribute ¤

MCC = 'MCC DAQ'

ChannelType ¤

Bases: Enum

ANALOG_INPUT class-attribute instance-attribute ¤

ANALOG_INPUT = 'ai'

ANALOG_OUTPUT class-attribute instance-attribute ¤

ANALOG_OUTPUT = 'ao'

DIGITAL_INPUT class-attribute instance-attribute ¤

DIGITAL_INPUT = 'di'

DIGITAL_OUTPUT class-attribute instance-attribute ¤

DIGITAL_OUTPUT = 'do'

Logic ¤

Bases: Enum

HIGH class-attribute instance-attribute ¤

HIGH = 'HIGH'

LOW class-attribute instance-attribute ¤

LOW = 'LOW'

Direction ¤

Bases: Enum

INPUT class-attribute instance-attribute ¤

INPUT = 'INPUT'

OUTPUT class-attribute instance-attribute ¤

OUTPUT = 'OUTPUT'

TerminalConfig ¤

Bases: Enum

DIFF class-attribute instance-attribute ¤

DIFF = 'DIFFERENTIAL'

NRSE class-attribute instance-attribute ¤

NRSE = 'NRSE'

RSE class-attribute instance-attribute ¤

RSE = 'RSE'

HWTimingConfig dataclass ¤

HWTimingConfig(
    sample_rate: float, sample_period: int, samples_per_channel: int
)

sample_rate instance-attribute ¤

sample_rate: float

sample_period instance-attribute ¤

sample_period: int

samples_per_channel instance-attribute ¤

samples_per_channel: int

DAQChannel dataclass ¤

DAQChannel(*, physical_channel: str, alias: str, direction: Direction)

physical_channel instance-attribute ¤

physical_channel: str

alias instance-attribute ¤

alias: str

direction instance-attribute ¤

direction: Direction

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

range_max instance-attribute ¤

range_max: float

range_min instance-attribute ¤

range_min: float

scaler instance-attribute ¤

scaler: Scaler | None

terminal_config class-attribute instance-attribute ¤

terminal_config: TerminalConfig | None = None

physical_channel instance-attribute ¤

physical_channel: str

alias instance-attribute ¤

alias: str

direction instance-attribute ¤

direction: Direction

DigitalPortWidth ¤

Bases: IntEnum

WIDTH_8 class-attribute instance-attribute ¤

WIDTH_8 = 8

WIDTH_16 class-attribute instance-attribute ¤

WIDTH_16 = 16

WIDTH_32 class-attribute instance-attribute ¤

WIDTH_32 = 32

WIDTH_64 class-attribute instance-attribute ¤

WIDTH_64 = 64

DigitalChannel dataclass ¤

DigitalChannel(
    logic_level: float | None,
    logic: Logic,
    *,
    physical_channel: str,
    alias: str,
    direction: Direction,
)

Bases: DAQChannel

logic_level instance-attribute ¤

logic_level: float | None

logic instance-attribute ¤

logic: Logic

physical_channel instance-attribute ¤

physical_channel: str

alias instance-attribute ¤

alias: str

direction instance-attribute ¤

direction: Direction

DigitalPortChannel dataclass ¤

DigitalPortChannel(
    logic_level: float | None,
    logic: Logic,
    width: DigitalPortWidth,
    *,
    physical_channel: str,
    alias: str,
    direction: Direction,
)

Bases: DigitalChannel

width instance-attribute ¤

physical_channel instance-attribute ¤

physical_channel: str

alias instance-attribute ¤

alias: str

direction instance-attribute ¤

direction: Direction

logic_level instance-attribute ¤

logic_level: float | None

logic instance-attribute ¤

logic: Logic

DigitalLineChannel dataclass ¤

DigitalLineChannel(
    logic_level: float | None,
    logic: Logic,
    bit_position: int | None = None,
    *,
    physical_channel: str,
    alias: str,
    direction: Direction,
)

Bases: DigitalChannel

bit_position class-attribute instance-attribute ¤

bit_position: int | None = None

physical_channel instance-attribute ¤

physical_channel: str

alias instance-attribute ¤

alias: str

direction instance-attribute ¤

direction: Direction

logic_level instance-attribute ¤

logic_level: float | None

logic instance-attribute ¤

logic: Logic

RelayChannel dataclass ¤

RelayChannel(
    *, physical_channel: str, alias: str, direction: Direction
)

Bases: DAQChannel

A relay channel routed via open/close. direction is always OUTPUT (relay control is a command).

physical_channel instance-attribute ¤

physical_channel: str

alias instance-attribute ¤

alias: str

direction instance-attribute ¤

direction: Direction

Scaling¤

DAQ scaling package.

LinearScaler ¤

LinearScaler(gain: float, offset: float, units: str)

Bases: Scaler

output = raw * gain + offset.

units property ¤

units: str

scale ¤

scale(raw: float) -> float

ReverseLinearScaler ¤

ReverseLinearScaler(gain: float, offset: float, units: str)

Bases: Scaler

output = (raw - offset) / gain — inverse of LinearScaler, e.g. to back out a measurement amplifier.

units property ¤

units: str

scale ¤

scale(raw: float) -> float

Scaler ¤

Bases: ABC

Convert a raw DAQ reading to a physical value and report the resulting units.

Scalers compose via ScalerPipeline (e.g. voltage-divider → thermocouple). The pipeline's reported units come from the last stage.

units abstractmethod property ¤

units: str

Physical units of the scaled output (e.g. "V", "degC", "psi").

scale abstractmethod ¤

scale(raw: float) -> float

Convert a raw DAQ reading to a physical value in :attr:units.

ScalerPipeline ¤

ScalerPipeline(stage: Scaler, *stages: Scaler)

Bases: Scaler

Apply scaler stages sequentially (e.g. voltage divider → thermocouple). Units come from the last stage.

units property ¤

units: str

scale ¤

scale(raw: float) -> float

Thermocouple Scaling¤

Thermocouple scaling for DAQ: voltage → °C with cold-junction compensation.

TC_TYPE ¤

Bases: Enum

B class-attribute instance-attribute ¤
B = 'B'
E class-attribute instance-attribute ¤
E = 'E'
J class-attribute instance-attribute ¤
J = 'J'
K class-attribute instance-attribute ¤
K = 'K'
N class-attribute instance-attribute ¤
N = 'N'
R class-attribute instance-attribute ¤
R = 'R'
S class-attribute instance-attribute ¤
S = 'S'
T class-attribute instance-attribute ¤
T = 'T'

ThermocoupleSensor ¤

ThermocoupleSensor(type: TC_TYPE, cjc_temp: float)

Bases: Scaler

Thermocouple voltage → °C with cold-junction compensation.

ThermocoupleSensor(TC_TYPE.K, cjc_temp=25.0) # Type K, 25 °C reference junction

Parameters:

  • type ¤
    (TC_TYPE) –

    Thermocouple type (B/E/J/K/N/R/S/T).

  • cjc_temp ¤
    (float) –

    Cold-junction reference temperature in °C.

units property ¤
units: str
scale ¤
scale(raw: float | int) -> float

Voltage (volts or millivolts per the thermocouples library) → temperature (°C).

Driver Interface¤

Bases: ABC

Vendor DAQ driver contract. Concrete drivers own their transport and lifecycle.

The composed InstroDAQ installs an InstroDAQFacade (implements APIInstroDAQ) onto self.hal so drivers can read back configured channels and timing without coupling to the instrument's internal state.

points_in_buffer instance-attribute ¤

points_in_buffer: int

hal instance-attribute ¤

hal: APIInstroDAQ

open abstractmethod ¤

open()

Open the underlying transport (or verify the device is present, for handle-less SDKs).

close abstractmethod ¤

close()

Close every task/handle owned by the driver. Idempotent.

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. Default is a no-op; 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.

define_digital_channel abstractmethod ¤

define_digital_channel(
    direction: Direction,
    physical_channel: str,
    logic: Logic,
    logic_level: float | None = None,
    alias: str | None = None,
    port_width: DigitalPortWidth | None = None,
) -> DigitalChannel

Parse a vendor-specific physical_channel string into a DigitalLineChannel or DigitalPortChannel.

port_width is supplied for port-mode channels; line-mode channels encode their bit position in physical_channel per vendor convention (e.g. "port0/line3" on NI, "5101/3" on Keysight 34980A, "AUXPORT0/1" on MCC).

configure_do_channel abstractmethod ¤

configure_do_channel(channel: DigitalChannel)

Register a DO channel (line or port) with the underlying driver.

configure_di_channel abstractmethod ¤

configure_di_channel(channel: DigitalChannel)

Register a DI channel (line or port) with the underlying driver.

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.

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 ¤

seed(
    t_wall: int, dt: int, length: int
) -> tuple[HWTimestamper, list[int]]

Anchor the timeline at t_wall ns (read-return time of the first batch).

next_batch ¤

next_batch(dt: int, length: int) -> list[int]

Return length ns timestamps at dt spacing, continuing from the previous batch.

Vendor Drivers¤

Keysight 34980A¤

Keysight 34980A Multifunction Switch/Measure Unit DAQ driver.

KeysightData dataclass ¤

KeysightData(
    data: str, timestamp: int | None = None, dt: int | None = None
)
data instance-attribute ¤
data: str
timestamp class-attribute instance-attribute ¤
timestamp: int | None = None
dt class-attribute instance-attribute ¤
dt: int | None = None

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.

points_in_buffer instance-attribute ¤
points_in_buffer: int = 0
hal instance-attribute ¤
hal: APIInstroDAQ
open ¤
open()
close ¤
close()
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.

start ¤
start(**kwargs)

Enable timestamps and INIT the scan.

stop ¤
stop(**kwargs)

ABORt any pending scan.

read_analog ¤
read_analog() -> KeysightData
fetch_analog ¤
fetch_analog() -> KeysightData

Block until the buffer holds at least one full per-channel batch, then drain a channel-aligned chunk.

define_digital_channel ¤
define_digital_channel(
    direction: Direction,
    physical_channel: str,
    logic: Logic,
    logic_level: float | None = None,
    alias: str | None = None,
    port_width: DigitalPortWidth | None = None,
) -> DigitalChannel
configure_do_channel ¤
configure_do_channel(channel: DigitalChannel)

Configure DO width/direction/polarity/drive/level for channel.

configure_di_channel ¤
configure_di_channel(channel: DigitalChannel)

Configure DI width/direction/polarity/drive/level for channel.

write_digital_line ¤
write_digital_line(channel: DigitalChannel, data: int) -> None
read_digital_line ¤
read_digital_line(channel: DigitalChannel) -> int
write_digital_port ¤
write_digital_port(channel: DigitalChannel, data: int)
read_digital_port ¤
read_digital_port(channel: DigitalChannel) -> int
close_relay ¤
close_relay(channel: RelayChannel)

ROUTe:CLOSe the relay.

open_relay ¤
open_relay(channel: RelayChannel)

ROUTe:OPEN the relay.

configure_ao_channel ¤
configure_ao_channel(channel: AnalogChannel)

Register an AO channel. Default is a no-op; 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.

keysight_str_to_ns ¤

keysight_str_to_ns(ts_str: str) -> int

Convert a Keysight "YYYY,MM,DD,HH,MM,SS.sss" timestamp (UTC) to ns since the Unix epoch.

parse_datastring ¤

parse_datastring(data: str) -> tuple[list[float], list[int]]

Split a Keysight reading/timestamp data string into (measurements, timestamps_ns).

get_scanlist ¤

get_scanlist(channels: list[DAQChannel]) -> list[DAQChannel]