Skip to content

Acquisition Module

Data acquisition functions for logging data from soundcards and National Instruments DAQ devices.

Acquisition Settings

MySettings is the object you pass to every acquisition call — it holds the device, channel, sampling, trigger, voltage-range, IEPE excitation and per-channel calibration configuration. Every constructor argument is keyword-only with a default, and the attributes are plain and mutable. The full per-attribute reference is below; for worked end-to-end recipes (IEPE on a cDAQ, calibration at logging time) see the Data Acquisition user guide.

MySettings

Bases: object

A container for every acquisition setting used by a recording.

A single MySettings instance configures all acquisition entry points — acquisition.log_data, acquisition.signal_generator, the streams recorders and the Logger GUI. All constructor arguments are keyword-only and have defaults, so override only the few you need; attributes are plain and may also be set after construction (settings.fs = 12800). See the Data Acquisition user guide for worked end-to-end examples.

Conventions used throughout:

  • Everything is in volts. Acquired data and generated output are in volts; engineering-unit scaling is applied at display/fit time from channel_sensitivities, never by rescaling the stored data.
  • Per-channel fields take a scalar or a sequence. iepe_excit_current_A and channel_sensitivities accept one value (broadcast to all channels) or a list of length channels, indexed in captured-column order — on a cDAQ chassis that is slot order (see input_channels_spec).
  • The output_* fields configure the generation/AO path and default to their input counterparts when left unset.

Attributes:

  • channels (int) –

    Number of input channels (default 2). On the soundcard backend this is clamped to the device's max_input_channels at start_stream time (with a printed warning) — so the default of 2 becomes 1 on a mono mic rather than failing with PortAudio -9998. The NI backend instead raises ValueError if the count exceeds the device's available AI channels.

  • fs (int) –

    Input sampling frequency in Hz (default 44100). On a DSA module (NI 9234) the driver coerces this to the nearest rate on its discrete divider ladder.

  • nbits (int) –

    Sample bit depth — 8, 16, 24 or 32 (default 16).

  • chunk_size (int) –

    Samples acquired per channel per callback (default 100; values below 10 are raised to 10). Also the upper bound on pretrig_samples.

  • num_chunks (int) –

    Chunks held in the oscilloscope circular buffer (default 6); recomputed from viewed_time when set.

  • viewed_time (float or None) –

    Oscilloscope display window in seconds (default 0.3). When set, overrides num_chunks as ceil(viewed_time * fs / chunk_size). Set to None to size the oscilloscope buffer directly from num_chunks instead.

  • stored_time (float) –

    Duration of the recorded capture in seconds (default 2).

  • pretrig_samples (int or None) –

    Samples retained before the trigger, or None (default) for untriggered recording. Must not exceed chunk_size (the pretrigger buffer holds only one chunk of pre-trigger context).

  • pretrig_threshold (float) –

    Trigger level, in the units the chosen device delivers — volts on NI, ±1-normalised on the soundcard (default 0.05).

  • pretrig_channel (int) –

    Channel index monitored for the trigger (default 0).

  • pretrig_timeout (float) –

    Seconds to wait for a trigger before recording anyway (default 20).

  • device_driver (str) –

    Input backend — 'soundcard' (default), 'nidaq' or 'mock' (the hardware-free test backend).

  • device_index (int or None) –

    Index into the enumerated device list for the chosen driver; None picks a default (the system default input soundcard, or NI device 0). For a cDAQ chassis this indexes the chassis as a whole, not a module — list candidates with dvma.list_available_devices() (its nidaq section is indexed the same way device_index is).

  • input_channels_spec (str or None) –

    Optional raw DAQmx physical-channel string for the AI task, e.g. 'cDAQ1Mod1/ai0:3,cDAQ1Mod3/ai0'. Overrides the auto-built '<dev>/ai0:N-1' string when set — use it for gappy or mixed-module layouts the count-based builder cannot express. nidaqmx backend only.

  • VmaxNI (float) –

    Full-scale input voltage for the NI AI task (default 5); ±VmaxNI is passed as min/max to add_ai_voltage_chan. Pick the smallest range covering the signal for best resolution. Fixed at ±5 V on the 9234 (other values are accepted but ignored by the hardware).

  • VmaxSC (float) –

    Soundcard input calibration (default 1.0) — the jack voltage corresponding to a normalised reading of 1.0. Default 1.0 treats normalised samples as volts at unit scale (no calibration); set it to your measured input sensitivity to calibrate captures in volts.

  • NI_mode (str) –

    NI terminal configuration — 'DAQmx_Val_RSE' (default), 'DAQmx_Val_NRSE', 'DAQmx_Val_Diff' or 'DAQmx_Val_PseudoDiff'. DSA modules (9234) are pseudo-differential only.

  • iepe_excit_current_A (float or sequence of float) –

    Per-channel IEPE / ICP excitation current in amps (default 0.0 = off on every channel). Scalar broadcasts; a sequence must be length channels. Only NI 9234-class DSA modules support it; the legal discrete values on the 9234 are 0.0 and 0.002 (2 mA), validated against the module that actually owns each channel. A channel with current > 0 is switched to AC coupling and the recorder blocks ~2 s after start for the sensor bias to settle through the AC-coupling HPF. Requires device_driver='nidaq' (raises ValueError otherwise). Never enable it on a channel wired to an AO output (e.g. a loopback) — the current drives back into the AO terminal.

  • channel_sensitivities (float or sequence of float) –

    Per-channel sensitivity in volts per engineering unit — V/g for an accelerometer, V/N for a force transducer, V/Pa for a microphone, etc. (default 1.0 = no calibration applied). Scalar broadcasts; a sequence must be length channels and every value must be non-zero. log_data stores the reciprocal as TimeData.channel_cal_factors, which plotting and modal fitting apply automatically, so a 100 mV/g accelerometer (0.1 here) gives a cal factor of 10 and plots read in g. The stored time_data array itself stays in volts.

  • output_device_driver (str) –

    Backend for the output/AO path; defaults to device_driver (same device as the input).

  • output_device_index (int or None) –

    Device index for the output path; None picks the default output soundcard, or NI device 0.

  • output_channels (int) –

    Number of output (AO) channels (default 1).

  • output_channels_spec (str or None) –

    Raw DAQmx physical-channel string for the AO task, e.g. 'cDAQ1Mod2/ao0'; the output analogue of input_channels_spec. nidaqmx backend only.

  • output_fs (int) –

    Output sample rate in Hz; defaults to fs.

  • output_VmaxNI (float or None) –

    Full-scale output voltage for the NI AO task; defaults to VmaxNI. (The NI 9260 is limited to ±4.24 V.)

  • output_VmaxSC (float or None) –

    Full-scale output voltage for the soundcard AO path — the jack voltage corresponding to a ±1 sounddevice sample; defaults to VmaxSC.

  • use_output_as_ch0 (bool) –

    When True and an output array is passed to log_data, the generated drive signal is prepended as channel 0 of the recorded data (default False). Useful for transfer-function tests where the excitation should be the reference channel; the prepended column passes through with a cal factor of 1.

  • init_view_time (bool) –

    Show the time-domain oscilloscope view on launch (default True).

  • init_view_freq (bool) –

    Show the frequency-domain oscilloscope view on launch (default True).

  • init_view_levels (bool) –

    Show the channel-levels oscilloscope view on launch (default True).

Examples:

IEPE accelerometers on a cDAQ with per-channel calibration — 100 mV/g ICP accelerometers on the 9234's ai0/ai1 and a 2.3 mV/N force probe on ai2 (channel index 3 unused):

>>> settings = dvma.MySettings(
...     device_driver='nidaq',
...     device_index=0,                  # the cDAQ chassis
...     channels=3,
...     NI_mode='DAQmx_Val_PseudoDiff',  # required by the 9234
...     VmaxNI=5,                        # 9234 fixed at ±5 V
...     fs=12800,
...     iepe_excit_current_A=[0.002, 0.002, 0.0],  # 2 mA accels only
...     channel_sensitivities=[0.1, 0.1, 0.0023],  # V/g, V/g, V/N
... )
>>> dataset = dvma.log_data(settings)

Scalars broadcast to every channel — four identical IEPE-powered 100 mV/g accelerometers:

>>> settings = dvma.MySettings(
...     device_driver='nidaq', channels=4,
...     iepe_excit_current_A=0.002, channel_sensitivities=0.1,
... )
See Also

acquisition.log_data: Run a capture using these settings. list_available_devices: Print soundcard + nidaq devices by index. suggest_ni_settings: Safe NI ranges/rate/mode for a device.

Output_Signal_Settings

Bases: object

Pre-set values for the Logger GUI's "Generate output" panel.

A lightweight holder for the four output-generation fields the Logger GUI exposes. Pass an instance to gui.Logger(..., output_signal_settings=...) to pre-fill that panel; the GUI then feeds the chosen values to acquisition.signal_generator when you preview or play the output. It is only consumed by the GUI — for scripted output, call acquisition.signal_generator / log_data(output=...) directly (see the Data Acquisition user guide).

The signal duration is not stored here — it is a separate field in the GUI panel (and the T= argument of signal_generator when scripting).

Attributes:

  • type (str) –

    Output waveform, matching the panel's drop-down — one of 'None' (output off; the default), 'sweep' (a linear chirp from f1 to f2), 'gaussian' (band-limited Gaussian noise) or 'uniform' (band-limited uniform noise). Maps to signal_generator's sig.

  • amp (float) –

    Peak amplitude in volts (default 0). Clamped to ±settings.output_vmax() at generation time.

  • f1 (float) –

    Lower frequency in Hz (default 0). For 'sweep' the start frequency; for the noise types the lower band-pass corner. Passed through as f=[f1, f2].

  • f2 (float) –

    Upper frequency in Hz (default 0). For 'sweep' the end frequency; for noise the upper band-pass corner. The GUI rejects max(f1, f2) > fs/2 (Nyquist).

Examples:

>>> # band-limited noise, 0.1 V, 100-300 Hz, pre-loaded in the GUI
>>> oss = dvma.Output_Signal_Settings(type='gaussian',
...                                   amp=0.1, f1=100, f2=300)
>>> logger = dvma.Logger(settings, output_signal_settings=oss)

Main Acquisition Function

log_data

log_data(settings, test_name=None, rec=None, output=None)

Acquire one block of time-domain data and return it as a DataSet.

Two call modes depending on settings.pretrig_samples:

  • No pretrigger (pretrig_samples is None): starts / reuses a stream, sleeps for settings.stored_time seconds, and returns the most recent stored_time * fs samples from the circular buffer. If output is supplied it is played in parallel (soundcard play is blocking; NI play is non-blocking and synchronized against stored_time via WaitUntilTaskDone).
  • Pretrigger armed (pretrig_samples set): waits up to settings.pretrig_timeout seconds for the monitored channel to cross settings.pretrig_threshold. When an output stimulus is supplied the timeout clock starts once the stimulus is actually playing (the ~1 s settle sleep and AO task setup are not counted against it). On trigger, returns a window of stored_time * fs samples straddling the trigger sample so that pretrig_samples of pre-trigger data appears at the start of the returned buffer. On timeout with no trigger the function does not raise — it falls back to returning the tail of the buffer (same as the no-pretrigger path) with trigger_detected = False.
Parameters

settings : MySettings Acquisition configuration. See pydvma.options.MySettings. test_name : str or None Stored on the returned TimeData for labelling. rec : Recorder-like or None Ignored. Retained for backward compatibility with callers (the GUI's LogDataThread) that still pass a cached recorder. log_data now always rebuilds the stream via streams.start_stream(settings) so that switching device or backend between calls doesn't leave a stale recorder. output : ndarray (N_samples, output_channels) or None Optional playback signal in volts. For NI it's passed through as-is (must stay within ±output_VmaxNI). For soundcard it's divided by output_VmaxSC to recover the ±1 normalised units sounddevice expects.

Returns

DataSet A DataSet containing one TimeData in volts. If settings.use_output_as_ch0 is True and output was supplied, the output signal is prepended as an extra channel.

Notes

A clipping warning is printed when |data| > 0.95 * Vmax anywhere in the capture, where Vmax is VmaxNI on the NI path and VmaxSC on the soundcard path. Both default to behaviour equivalent to the old ±1-normalised check when the user hasn't overridden them.

Pretrigger positioning (both backends, identical logic)

On a successful trigger, the returned buffer is stored_time * fs samples long and the first sample exceeding pretrig_threshold sits at exactly index pretrig_samples — samples [0, pretrig_samples) are pre-trigger context. See streams.Recorder for the state machine that gives this invariant.

pretrig_samples is capped at chunk_size (validated at call-time with a ValueError); the recorder only retains that much pre-trigger context. Larger windows require a larger chunk_size.

On a trigger timeout (pretrig_timeout elapses with nothing above threshold), the function does not raise — it returns the tail of the buffer (same shape as the no-pretrigger path), leaves trigger_detected False, and prints a "not detected" message.

Signal Generation

output_signal

output_signal(settings, output)

Play output (in volts) on the configured AO device.

For soundcard, divides by output_VmaxSC to recover the ±1 normalised float sounddevice expects. For NI, the voltage array is passed straight through to setup_output_NI (the AO task is configured with ±output_VmaxNI rails).

signal_generator

signal_generator(settings, sig='gaussian', T=1, amplitude=0.1, f=None, selected_channels='all')

Create an output-ready waveform.

amplitude is in volts — the generated signal is bounded to ±amplitude and, as a safety ceiling, clipped to ±settings.output_vmax() (i.e. output_VmaxNI on the NI path, output_VmaxSC on the soundcard path). Returns (t, y) where y is shape (N, output_channels) in volts, ready to hand to log_data(..., output=y) or output_signal.

Stream Monitoring

stream_snapshot

stream_snapshot(rec)

Capture the live oscilloscope buffer as a TimeData.

Unlike log_data, which blocks for stored_time seconds and returns a fresh capture, this is a non-blocking snapshot of the oscilloscope-side circular buffer (osc_time_data) — i.e. the most recent num_chunks * chunk_size samples already in memory. Useful for "what is the stream doing right now?" diagnostics from a notebook while a stream is running.

Parameters

rec : Recorder-like Retained for backward compatibility; the actual snapshot is always taken from the module-level streams.REC. Callers can pass any value (typically streams.REC itself).

Returns

TimeData A single TimeData instance with test_name='stream_snapshot', carrying the oscilloscope axis and the live buffer. No channel_cal_factors or units are attached (this is meant as a quick-look tool, not a calibrated capture).

Notes

Requires a live stream: call streams.start_stream(settings) first, or use a function like log_data that does so internally. On the soundcard path the buffer holds voltages scaled by settings.VmaxSC; on the NI path it holds raw volts.