Skip to content

IQ File Reader — iq_reader

P pynasonde.digisonde.raw.iq_reader — streaming reader for time-partitioned one-second IQ binary files.


IQStream

C Mirrors the Julia IQStream object. Manages file handles across second boundaries and exposes a simple read_samples() interface.

pynasonde.digisonde.raw.iq_reader.IQStream dataclass

Direct stream reader mirroring the Julia IQStream object.

Parameters

dir_iq

Root directory that contains the time-partitioned IQ recordings.

epoch

Approximate epoch from which to start the stream. This can be naive (assumed UTC) or timezone-aware.

rx_tag

Channel tag that identifies which stream to use (defaults to "ch0").

read_samples(epoch0, n_samples=None)

Read n_samples complex IQ samples starting near epoch0.

Results are returned as a NumPy array of np.complex64 values. The method reuses internal buffers across calls to minimize allocations. When n_samples is None the entire one-second file that contains epoch0 is returned.

close()

Close the underlying file handle if it is open.


Module-level helpers

M get_frequencies — scan the directory tree and return center / sample frequencies from the first .bin filename found.

pynasonde.digisonde.raw.iq_reader.get_frequencies(dir_iq, epoch, fmt='%H/%M')

Derive center and sampling frequencies based on the closest available file.

The search scans forward in one-minute increments for up to 24 hours, then backwards for another 24 hours, mirroring the Julia implementation.

M get_channels — list the unique channel tags (e.g. ch0, ch1) present in the current minute directory.

pynasonde.digisonde.raw.iq_reader.get_channels(dir_iq, epoch=None, fmt='%H/%M')

Return the unique channel tags available in the current minute directory.

Parameters

dir_iq

Root IQ directory.

epoch

Optional epoch to inspect. Defaults to datetime.now(timezone.utc).


File layout

IQ recordings follow the naming convention:

<root>/YYYY-mm-dd/HH/MM/<timestamp>_<channel>_fc<kHz>kHz_bw<kHz>kHz.bin

Each .bin file contains exactly one second of interleaved 16-bit little-endian I and Q samples (4 bytes per complex sample).

Quick start

import datetime as dt
from pynasonde.digisonde.raw.iq_reader import IQStream, get_channels

epoch = dt.datetime(2023, 10, 14, 16, 0, 0, tzinfo=dt.timezone.utc)
dir_iq = "/media/chakras4/69F9D939661D263B"

# Discover available channels
channels = get_channels(dir_iq, epoch)
print(channels)  # e.g. ['ch0', 'ch1']

# Open a stream and read one second of samples
stream = IQStream(dir_iq, epoch, rx_tag="ch0")
samples = stream.read_samples(epoch)   # np.ndarray of np.complex64
stream.close()