46 lines
2.0 KiB
Python
46 lines
2.0 KiB
Python
"""One-off exporter: PLFM GUI I/Q CSV -> compact XZ binary replay artifact.
|
|
|
|
Run from the repository root:
|
|
.venv/bin/python tools/export_replay_iq.py
|
|
|
|
Reads `src/defense_sim/radar/data/plfm_gui_samples.csv` (bundled copy of the
|
|
upstream GUI `test_radar_data.csv`) and writes
|
|
`src/defense_sim/radar/data/plfm_gui_samples.iq.xz`: four int16 planes
|
|
(LONG I, SHORT I, LONG Q, SHORT Q), chirp-major x sample-index-minor, XZ
|
|
preset 9. Row metadata is not stored because the grid is dense and ordered
|
|
(timestamp_ns = 2 * (chirp*512 + sample)); `magnitude_squared` is not stored
|
|
because it does not equal I^2 + Q^2 in most rows of the source file
|
|
(15,515 of 16,384 mismatch; verified at export time).
|
|
"""
|
|
import lzma
|
|
import numpy as np
|
|
|
|
|
|
def main():
|
|
path = "src/defense_sim/radar/data/plfm_gui_samples.csv"
|
|
rows = [line.strip().split(",") for line in open(path)][1:]
|
|
groups = []
|
|
for kind in ("LONG", "SHORT"):
|
|
selected = [r for r in rows if r[2] == kind]
|
|
chirps = sorted({int(r[1]) for r in selected})
|
|
size = max(int(r[3]) for r in selected) + 1
|
|
plane = np.zeros((len(chirps), size), np.complex128)
|
|
index = {c: i for i, c in enumerate(chirps)}
|
|
for r in selected:
|
|
plane[index[int(r[1])], int(r[3])] = complex(float(r[4]), float(r[5]))
|
|
groups.append(plane)
|
|
# magnitude_squared integrity check: the source file's column is not I^2+Q^2.
|
|
bad = sum(1 for r in rows if float(r[6]) != (float(r[4])**2 + float(r[5])**2))
|
|
print(f"magnitude_squared mismatches: {bad} of {len(rows)}")
|
|
planes = [np.round(plane.real).astype(np.int16) for plane in groups]
|
|
planes += [np.round(plane.imag).astype(np.int16) for plane in groups]
|
|
blob = b"".join(p.tobytes() for p in planes)
|
|
out = "src/defense_sim/radar/data/plfm_gui_samples.iq.xz"
|
|
with open(out, "wb") as stream:
|
|
stream.write(lzma.compress(blob, preset=9))
|
|
print(f"wrote {out}: {len(lzma.compress(blob, preset=9))} bytes from {len(blob)} raw")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|