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_Aandchannel_sensitivitiesaccept one value (broadcast to allchannels) or a list of lengthchannels, indexed in captured-column order — on a cDAQ chassis that is slot order (seeinput_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'smax_input_channelsatstart_streamtime (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 raisesValueErrorif 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 onpretrig_samples. -
num_chunks(int) –Chunks held in the oscilloscope circular buffer (default
6); recomputed fromviewed_timewhen set. -
viewed_time(float or None) –Oscilloscope display window in seconds (default
0.3). When set, overridesnum_chunksasceil(viewed_time * fs / chunk_size). Set to None to size the oscilloscope buffer directly fromnum_chunksinstead. -
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 exceedchunk_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;
Nonepicks 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 withdvma.list_available_devices()(its nidaq section is indexed the same waydevice_indexis). -
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 toadd_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. Default1.0treats 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 lengthchannels. Only NI 9234-class DSA modules support it; the legal discrete values on the 9234 are0.0and0.002(2 mA), validated against the module that actually owns each channel. A channel with current> 0is switched to AC coupling and the recorder blocks ~2 s after start for the sensor bias to settle through the AC-coupling HPF. Requiresdevice_driver='nidaq'(raisesValueErrorotherwise). 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 lengthchannelsand every value must be non-zero.log_datastores the reciprocal asTimeData.channel_cal_factors, which plotting and modal fitting apply automatically, so a100 mV/gaccelerometer (0.1here) gives a cal factor of10and plots read ing. The storedtime_dataarray 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;
Nonepicks 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 ofinput_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
Trueand anoutputarray is passed tolog_data, the generated drive signal is prepended as channel 0 of the recorded data (defaultFalse). 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 fromf1tof2),'gaussian'(band-limited Gaussian noise) or'uniform'(band-limited uniform noise). Maps tosignal_generator'ssig. -
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 asf=[f1, f2]. -
f2(float) –Upper frequency in Hz (default
0). For'sweep'the end frequency; for noise the upper band-pass corner. The GUI rejectsmax(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 ¶
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 forsettings.stored_timeseconds, and returns the most recentstored_time * fssamples from the circular buffer. Ifoutputis supplied it is played in parallel (soundcard play is blocking; NI play is non-blocking and synchronized againststored_timevia WaitUntilTaskDone). - Pretrigger armed (
pretrig_samplesset): waits up tosettings.pretrig_timeoutseconds for the monitored channel to crosssettings.pretrig_threshold. When anoutputstimulus 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 ofstored_time * fssamples straddling the trigger sample so thatpretrig_samplesof 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) withtrigger_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 ¶
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 ¶
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 ¶
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.