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
¶
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>].
positions_per_line
property
¶
Spatial fibre positions per pulse — line_size / 2 if INTERLEAVED.
spatial_shape
property
¶
(num_lines, positions_per_line) — shape returned by the channel extractors.
read_lines
¶
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 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.
seek_lines
¶
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
¶
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_iq
¶
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
¶
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
¶
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
¶
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
¶
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
¶
Like :meth:get_q but returns the Q lane as float32 volts.
get_iq_volts
¶
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
¶
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
¶
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
¶
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()
Header¶
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
¶
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 descriptor byte (DataHeader byte 64). 0 = Undefined
(legacy capture). Use content_type_name for the lowercase tag.
content_type_name
property
¶
Lowercase content_type tag (e.g. "interleaved_hw_phase_amplitude",
"undefined" for legacy captures).
is_interleaved
property
¶
True if the INTERLEAVED bit is set — the wire carries 2 samples
per spatial position (I/Q or arctan/√).
is_unsigned
property
¶
True if the odd-index lane of an INTERLEAVED pair is unsigned
(PCIe7821 ArctanMagnitude mode: √(I²+Q²) as u16).
positions_per_line
property
¶
Physical spatial positions per pulse — line_size / 2 when
INTERLEAVED, line_size otherwise. Mirrors
the Audace positions_per_line helper from the producer.
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.
read_lines
method descriptor
¶
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
ValueErrorifn <= 0. - Raises
IOErrorif the file is already exhausted. - Caps
natlines_left(does not raise on a short read).
rewind
method descriptor
¶
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
¶
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 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 |