102: IQ file readers (sig + raw) #42

Merged
ykp merged 1 commit from feat/102-sig-io-readers into main 2026-10-06 18:01:31 +02:00
Owner

Summary

Implement Step 102 of the testgnss project: self-contained readers for SigV3.1/V3.0 (.sig) and raw IQ files.

What was implemented

  • src/testgnss/io/sig_io.py — new module with:
    • SigReadResult dataclass (frozen, with iq, sample_rate, center_frequency_hz, bandwidth_hz)
    • SigReadError exception (subclass of SigIOError)
    • read_sig(path) — reads SigV3.0 and SigV3.1 files, validates signature, extracts header metadata, handles int16 (normalized by v / 32768) and float32 samples, applies size-consistency rule (warns and truncates)
    • read_raw_iq(path, sample_rate, center_frequency_hz, sample_format="int16") — reads raw interleaved I/Q files (int16 or float32) with operator-supplied metadata
  • src/testgnss/io/__init__.py — exposes SigReadResult, read_sig, read_raw_iq
  • tests/test_testgnss_sig_io.py — comprehensive test suite (24 tests):
    • Round-trip: write SigV3.1 with int16, read back, verify values and metadata
    • Round-trip SigV3.0 detection
    • Round-trip float32 samples
    • Round-trip raw IQ (int16 and float32)
    • Bad signature → SigReadError
    • Real signal (Complexe=0) → SigReadError
    • SIG 3.0 with float32 → SigReadError
    • Invalid sample format enum → SigReadError
    • Truncated header → SigReadError
    • File-not-found → SigReadError
    • Empty raw file → SigReadError
    • Misaligned raw file → SigReadError
    • Non-finite/negative sample_rate → ValueError
    • Non-finite center_frequency → ValueError
    • Unsupported sample_format → ValueError
    • Truncation warning (declared > actual)
    • Trailing bytes warning
    • Correct operator-supplied metadata propagation

Verification

$ pytest tests/test_testgnss_sig_io.py -q -v
........................
24 passed in 0.11s

$ ruff check src/testgnss/io/ tests/test_testgnss_sig_io.py
All checks passed!

All 30 testgnss tests (including existing smoke tests) continue to pass.

Design notes

  • Self-contained — no runtime dependency on the gensig reference implementation
  • Byte-compatible with gengnss.core.sig_writer (same header struct, LP32 semantics, little-endian)
  • Follows the same field grid and endianness conventions as the existing writer
  • Headless-safe: no tkinter or display imports
## Summary Implement Step 102 of the testgnss project: self-contained readers for SigV3.1/V3.0 (.sig) and raw IQ files. ### What was implemented - **`src/testgnss/io/sig_io.py`** — new module with: - `SigReadResult` dataclass (frozen, with `iq`, `sample_rate`, `center_frequency_hz`, `bandwidth_hz`) - `SigReadError` exception (subclass of `SigIOError`) - `read_sig(path)` — reads SigV3.0 and SigV3.1 files, validates signature, extracts header metadata, handles int16 (normalized by `v / 32768`) and float32 samples, applies size-consistency rule (warns and truncates) - `read_raw_iq(path, sample_rate, center_frequency_hz, sample_format="int16")` — reads raw interleaved I/Q files (int16 or float32) with operator-supplied metadata - **`src/testgnss/io/__init__.py`** — exposes `SigReadResult`, `read_sig`, `read_raw_iq` - **`tests/test_testgnss_sig_io.py`** — comprehensive test suite (24 tests): - Round-trip: write SigV3.1 with int16, read back, verify values and metadata - Round-trip SigV3.0 detection - Round-trip float32 samples - Round-trip raw IQ (int16 and float32) - Bad signature → SigReadError - Real signal (Complexe=0) → SigReadError - SIG 3.0 with float32 → SigReadError - Invalid sample format enum → SigReadError - Truncated header → SigReadError - File-not-found → SigReadError - Empty raw file → SigReadError - Misaligned raw file → SigReadError - Non-finite/negative sample_rate → ValueError - Non-finite center_frequency → ValueError - Unsupported sample_format → ValueError - Truncation warning (declared > actual) - Trailing bytes warning - Correct operator-supplied metadata propagation ### Verification ``` $ pytest tests/test_testgnss_sig_io.py -q -v ........................ 24 passed in 0.11s $ ruff check src/testgnss/io/ tests/test_testgnss_sig_io.py All checks passed! ``` All 30 testgnss tests (including existing smoke tests) continue to pass. ### Design notes - Self-contained — no runtime dependency on the `gensig` reference implementation - Byte-compatible with `gengnss.core.sig_writer` (same header struct, LP32 semantics, little-endian) - Follows the same field grid and endianness conventions as the existing writer - Headless-safe: no tkinter or display imports
102: IQ file readers (sig + raw)
Some checks failed
ci / test (3.14) (push) Failing after 1m39s
ci / test (3.12) (push) Failing after 1m48s
ci / testgnss (3.12) (push) Failing after 1m39s
ci / test (3.9) (push) Failing after 2m5s
ci / testgnss (3.14) (push) Failing after 1m41s
ci / testgnss (3.9) (push) Failing after 1m33s
ci / test (3.12) (pull_request) Failing after 2m40s
ci / test (3.14) (pull_request) Failing after 2m37s
ci / testgnss (3.12) (pull_request) Failing after 2m6s
ci / test (3.9) (pull_request) Failing after 2m31s
ci / testgnss (3.14) (pull_request) Failing after 1m58s
ci / testgnss (3.9) (pull_request) Failing after 1m46s
c9aeaac8f6
- Add SigReadResult dataclass, SigReadError exception
- Implement read_sig() for SigV3.0/SigV3.1 .sig files
- Implement read_raw_iq() for raw int16/float32 IQ files
- Add comprehensive test suite (24 tests)
- All tests pass, ruff check clean
ykp merged commit 7c4539a32e into main 2026-10-06 18:01:31 +02:00
ykp deleted branch feat/102-sig-io-readers 2026-10-06 18:01:32 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ykp/gengnss!42
No description provided.