Skip to content

API reference

Generated directly from the docstrings of the invisensing package (version always matches the wheel you're reading these docs from).

The stable public symbols (those listed in invisensing.__all__) are documented below. Anything not listed there is internal and may change without notice.


File

The unified reader. Auto-detects the on-disk format from the path suffix and exposes the channels each file actually contains.

File

File(path, *, format=None)

Unified reader for Audace DAS acquisition files.

Detects the on-disk format from the path's suffix (.dat, .h5/.hdf5, .tdms, .sgy/.segy) and delegates the bytes-to-numpy work to a format-specific backend. The public API is identical across formats: same properties, same channel extractors, same numpy output shape.

Use it as a context manager so the underlying file handle is closed cleanly even if an exception is raised::

with File("acquisition.dat") as f:
    ...

Parameters

path Path to the file. Suffix is used to pick the backend unless format is supplied explicitly. format Optional override ("dat", "hdf5", "tdms", "segy"). Use when the file has no recognised suffix.

Raises

FileNotFoundError If the path doesn't exist. ValueError If the format can't be auto-detected (and no override was given) or if the file isn't a valid Audace acquisition (zero line_size / sample_size). ImportError If the chosen backend needs an optional third-party library (h5py / npTDMS / segyio) that isn't installed. The message names the right pip install invisensing[<extra>].

path property

path

Path to the source file.

header property

header

Parsed :class:Header (line_size, flags, rates, timestamp…).

mode property

mode

High-level acquisition mode — see :class:Mode.

line_size property

line_size

Wire-side samples per pulse (doubled when is_interleaved).

positions_per_line property

positions_per_line

Spatial fibre positions per pulse — line_size / 2 if INTERLEAVED.

sample_size property

sample_size

Bytes per sample (2 for i16, 4 for i32/f32).

sample_rate property

sample_rate

Wire-side sample rate in Hz.

trig_frequency property

trig_frequency

Trigger pulse repetition rate in Hz.

num_lines property

num_lines

Total trigger pulses recorded in the file.

lines_left property

lines_left

Pulses remaining behind the current read cursor.

timestamp property

timestamp

Acquisition start timestamp (free-form string from the producer).

flags property

flags

Raw header flag bitmask (see FLAG_* constants).

range property

range

Voltage range in volts (header field is mV).

dtype property

dtype

numpy dtype matching (sample_size, FLOAT).

shape property

shape

Total (num_lines, line_size) of the wire payload.

spatial_shape property

spatial_shape

(num_lines, positions_per_line) — shape returned by the channel extractors.

duration property

duration

Total duration of the recording in seconds.

distance property

distance

Round-trip distance (m) the pulse covers in the fibre.

is_demodulated property

is_demodulated

True if the on-board DSP was used (PCIe7821 demod modes).

is_interleaved property

is_interleaved

True if the wire carries 2 samples per spatial position.

is_float property

is_float

True if samples are IEEE-754 floats.

is_phase property

is_phase

True if the file carries unwrapped DAS phase (rad).

is_unsigned property

is_unsigned

True if the odd lane of an INTERLEAVED pair is u16 (magnitude).

is_ac property

is_ac

True if the ADC was AC-coupled during acquisition.

is_hiz property

is_hiz

True if the ADC ran in high-impedance mode.

close

close()

Release the underlying file handle. Safe to call multiple times.

is_acquisition_ac

is_acquisition_ac()

Alias of :attr:is_ac kept for backwards compatibility.

is_acquisition_hiz

is_acquisition_hiz()

Alias of :attr:is_hiz kept for backwards compatibility.

read_lines

read_lines(n=1)

Read up to n consecutive pulses (rows). Returns a (rows, line_size) typed numpy array — dtype is :attr:dtype.

Short-reads are tolerated: when fewer than n pulses remain, returns what's left. Raises :class:OSError only when the reader is already exhausted; raises :class:ValueError if n <= 0.

read_all

read_all()

Read every remaining pulse in one allocation. Use only when the file fits comfortably in RAM (num_lines × line_size × sample_size bytes). For large captures, prefer :meth:read_lines in a loop or iterate the file directly.

rewind

rewind()

Reset the read cursor back to the start of the sample stream.

seek_lines

seek_lines(n)

Move the read cursor to pulse n (0-based) without reading the skipped pulses.

For .dat/.hdf5 this is an O(1) seek; the next :meth:read_lines continues from n. n is clamped to :attr:num_lines. Lets a viewer jump to --start-time on a multi-GB file without streaming past the skipped data.

get_i

get_i(data=None, *, n=1)

Extract the I lane of an INTERLEAVED I/Q file (PCIe7821 :attr:Mode.IQ).

Returns a (rows, positions_per_line) int16 array. Raises :class:ValueError if the file's mode is not :attr:Mode.IQ.

get_q

get_q(data=None, *, n=1)

Extract the Q lane of an INTERLEAVED I/Q file.

get_iq

get_iq(data=None, *, n=1)

Combined complex64 view of an INTERLEAVED I/Q file: result[r, j] = I[r, j] + j·Q[r, j]. Returns (rows, positions_per_line) complex64.

get_arctan

get_arctan(data=None, *, n=1)

Extract the arctan(Q/I) lane of an INTERLEAVED arctan/√ file (PCIe7821 :attr:Mode.ARCTAN_MAGNITUDE). Returns (rows, positions_per_line) int16 — the fixed-point scale is 32767 ↔ +π (vendor convention).

get_magnitude

get_magnitude(data=None, *, n=1)

Extract the √(I²+Q²) magnitude lane of an INTERLEAVED arctan/√ file, reinterpreted as u16 (the wire buffer is typed i16 end-to-end but the vendor sends magnitudes as unsigned). Returns (rows, positions_per_line) uint16.

get_phase

get_phase(data=None, *, n=1)

Phase samples (float32 radians) for PCIe7821 :attr:Mode.PHASE files. One sample per spatial position, no INTERLEAVED pair. Returns (rows, positions_per_line) float32.

For consistency with the other extractors this method exists even though Phase files are already one sample per position — passing data returns it unchanged; passing nothing reads n new pulses.

get_i_volts

get_i_volts(data=None, *, n=1)

Like :meth:get_i but returns the I lane as a float32 numpy array scaled to volts: f32 = i16 × range / 32768. Use this when you want physically-meaningful values without having to remember the ADC scaling.

get_q_volts

get_q_volts(data=None, *, n=1)

Like :meth:get_q but returns the Q lane as float32 volts.

get_iq_volts

get_iq_volts(data=None, *, n=1)

Like :meth:get_iq but returns a complex64 array whose real / imaginary parts are in volts. Convenient for envelope / phase computations that need physical units::

iq = f.get_iq_volts()
envelope_v = np.abs(iq)         # volts
phase_rad  = np.angle(iq)       # radians (wrapped)

get_arctan_radians

get_arctan_radians(data=None, *, n=1)

Like :meth:get_arctan but returns the arctan lane as a float32 numpy array in radians, scaled with the vendor convention 32767 ↔ +π (f32 = i16 × π / 32768). Range is [-π, +π], the raw wrapped output of the FPGA arctan2.

get_magnitude_volts

get_magnitude_volts(data=None, *, n=1)

Like :meth:get_magnitude but returns the magnitude lane as a float32 numpy array in volts: f32 = u16 × range / 32768.

The LSB scaling matches the I/Q lanes (the FPGA computes √(I²+Q²) from the same i16 I/Q codes and keeps the same per-LSB voltage). The output is always ≥ 0.

channels

channels(data=None, *, n=1)

Return all channels of the file in one call, as a dict whose keys depend on the :attr:mode::

Mode.RAW              -> {"samples": ndarray}
Mode.IQ               -> {"i": …, "q": …, "iq": complex64}
Mode.ARCTAN_MAGNITUDE -> {"arctan": …, "magnitude": …}
Mode.PHASE            -> {"phase": …}

Convenience for ad-hoc scripts: pass a pre-read buffer if you already have one, otherwise the method reads n pulses.


Mode

High-level acquisition mode of a file. Use this enum to dispatch on what the file contains:

from invisensing import File, Mode

with File("acquisition.dat") as f:
    match f.mode:
        case Mode.RAW:               ...
        case Mode.IQ:                ...
        case Mode.ARCTAN_MAGNITUDE:  ...
        case Mode.PHASE:             ...

Mode

Bases: Enum

High-level acquisition mode of a file. Derived from the header flags so the user can dispatch with one match statement instead of bit-twiddling::

match file.mode:
    case Mode.RAW:               samples = file.read_lines(n)
    case Mode.IQ:                i, q    = file.get_i(), file.get_q()
    case Mode.ARCTAN_MAGNITUDE:  a, m    = file.get_arctan(), file.get_magnitude()
    case Mode.PHASE:             phase   = file.get_phase()

from_flags classmethod

from_flags(flags)

Decode the high-level mode from a raw header flag mask.


Parsed 128-byte Audace DataHeader. The format-specific backends (HDF5 / TDMS / SEG-Y) reconstruct one of these from their native metadata so the channel extractors take a uniform path regardless of the source file.

You rarely need to instantiate one directly — File.header returns it for you. The constructor is exposed for advanced users (e.g. synthesising files in tests).

Header

128-byte Audace DataHeader parsed into Python-friendly fields.

Exposed as invisensing._core.Header. The HDF5 / TDMS / SEG-Y wrappers reconstruct one of these from format-native metadata so the channel extractors take a single uniform path.

acquisition_ns property

acquisition_ns

Precise acquisition time in i64 nanoseconds (DataHeader timestamp bytes [0..8]). 0 when the file uses the legacy ASCII timestamp string.

content_type property

content_type

content_type descriptor byte (DataHeader byte 64). 0 = Undefined (legacy capture). Use content_type_name for the lowercase tag.

content_type_name property

content_type_name

Lowercase content_type tag (e.g. "interleaved_hw_phase_amplitude", "undefined" for legacy captures).

flags property

flags

is_ac property

is_ac

is_demodulated property

is_demodulated

is_float property

is_float

True if samples are IEEE-754 floats.

is_hiz property

is_hiz

is_interleaved property

is_interleaved

True if the INTERLEAVED bit is set — the wire carries 2 samples per spatial position (I/Q or arctan/√).

is_phase property

is_phase

is_unsigned property

is_unsigned

True if the odd-index lane of an INTERLEAVED pair is unsigned (PCIe7821 ArctanMagnitude mode: √(I²+Q²) as u16).

line_size property

line_size

num_channels property

num_channels

positions_per_line property

positions_per_line

Physical spatial positions per pulse — line_size / 2 when INTERLEAVED, line_size otherwise. Mirrors the Audace positions_per_line helper from the producer.

pulse_width property

pulse_width

range property

range

sample_rate property

sample_rate

sample_size property

sample_size

timestamp property

timestamp

trig_frequency property

trig_frequency

DatReader

Low-level streaming reader for .dat files. The File class wraps this for the common path; use it directly if you need access to the raw cursor (rare).

DatReader

Streaming reader for an Audace .dat file. Holds an open BufReader positioned past the 128-byte header, advanced one chunk per read_lines call so the user can iterate large acquisitions without loading the whole file.

Owns a parsed [Header]; the Python wrapper accesses fields via the header property.

Thread safety: the reader holds a mutable file cursor, so it is not safe to share between Python threads. The Python facade ensures each File has its own DatReader. PyO3 holds the GIL across method calls except during the read_exact itself (where we release it explicitly via Python::allow_threads) — concurrent reads from the same instance are still serialised by the GIL even on a release-build extension, but read_exact runs without it so a second Python thread can make progress while the first is blocked on disk I/O.

header property

header

lines_left property

lines_left

num_lines property

num_lines

path property

path

read_lines method descriptor

read_lines(n=1)

Read up to n pulses of samples and return them as a (rows, line_size) numpy array. The dtype is picked from (sample_size, FLOAT) — matches the FileWriter convention so the numbers come out signed (negative ADC codes stay negative).

The actual read_exact runs with the GIL released so other Python threads can do work while the OS blocks on disk I/O.

  • Raises ValueError if n <= 0.
  • Raises IOError if the file is already exhausted.
  • Caps n at lines_left (does not raise on a short read).

rewind method descriptor

rewind()

Rewind back to the start of the sample stream (just past the header). Useful to make multiple passes over the same reader without re-opening the file.

seek_lines method descriptor

seek_lines(n)

Move the read cursor to pulse n (0-based) without reading the skipped samples — an O(1) seek past the header plus n lines. n is clamped to num_lines; lines_left is updated to match. Subsequent read_lines continues from n.


Functions

parse_header

parse_header builtin

parse_header(bytes)

Parse a 128-byte .dat header. Useful for callers that already hold the bytes (memory-mapped files, in-memory buffers).

export_dat

export_dat

export_dat(
    path,
    data,
    *,
    sample_rate,
    trig_frequency,
    range_v=0.0,
    timestamp="",
    flags=0,
    pulse_width=0,
    num_channels=1
)

Write a 2-D numpy array out as an Audace .dat file (128-byte header + raw samples). The array's shape[1] becomes line_size and its dtype determines sample_size plus the FLOAT flag.

Parameters

path Output file path. Overwritten if it exists. data (num_lines, line_size) 2-D array. Any contiguous-or-not C-order layout is accepted; the data is densified on write. sample_rate Wire-side sample rate in Hz. trig_frequency Trigger pulse rate in Hz. range_v ADC voltage range in volts (stored as mV in the header). timestamp Free-form acquisition timestamp (≤ 32 bytes UTF-8). flags Raw header flag mask. The FLOAT bit is set automatically when data.dtype.kind == 'f'. pulse_width Trigger pulse width in ns. num_channels Number of active socket channels in the original acquisition.

Raises

ValueError If data is not 2-D. OSError If the write fails.


Header-flag constants

The raw flag bits used by the Audace wire-format header. You typically don't need these — File.is_* properties and Mode.from_flags() cover the common cases. They're exposed for callers who need to inspect or build a Header by hand.

Constant Hex Meaning
FLAG_DEMODULATED 0x001 Samples are the output of on-board DSP
FLAG_FLOAT 0x002 Samples are IEEE-754 floats
FLAG_AC 0x004 ADC was AC-coupled
FLAG_HIZ 0x008 ADC ran in high-impedance mode
FLAG_SCHUBERT 0x010 (reserved, internal)
FLAG_SPECTRUM 0x020 (reserved, internal)
FLAG_MOZART 0x040 Software-Mozart pipeline marker
FLAG_PHASE 0x080 Carries unwrapped DAS phase (rad)
FLAG_INTERLEAVED 0x100 Wire carries 2 samples per spatial position
FLAG_UNSIGNED 0x200 Odd lane of an INTERLEAVED pair is u16
HEADER_SIZE 128 Size of the wire header in bytes