feat(round-11): |IQ| in the preview time plot + full-scale final normalization + per-tone LFM comb scaling #52
No reviewers
Labels
No labels
accessibility
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
ykp/gensig!52
Loading…
Reference in a new issue
No description provided.
Delete branch "round-11-features"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Three operator-confirmed features (round 11, decisions locked via explicit Q&A):
|IQ| in the preview time series — the result-graph time subplot now draws three traces: I (orange), Q (blue) and the new |IQ| magnitude (teal), title "Time (I/Q/|IQ|)". The hover annotation's nearest-trace logic picks up the third trace unchanged (readout reports magnitude samples too). Display decimation applies to all traces; no new settings.
Final normalization: full-scale target (gain allowed) —
pipeline.apply_post_chainends with_normalize_full_scale: any peak differing from full scale is scaled by1/peak— up OR down — under the operator's exact condition (peak > 1e-6 and abs(1 − peak) > 1e-6). Guards: near-zero signals (peak ≤ 1e-6) stay untouched (a1/peakgain would amplify numerical noise); 1-ulp float-noise overshoots (|1−peak| ≤ 1e-6) are not renormalized. The retired scale-down-only contract (Level = % of full scale preserved in the OUTPUT) is gone by confirmed decision: per-band Level ratios still shape the INTERNAL signal, but everything written/displayed peaks at exactly 1.0. Spec §5.3.5 rewritten, §3.2 carries the caveat; the rule lives in one place (pipeline._normalize_full_scale) that the tests pin against.create_lfm_tones(k=0 periodic chirp): exactcreate_multi_tonestone/scale handling — the builder no longer generates the full-union uniform comb. It now synthesizes only the requested per-band tones (Fmin:spacing:Fmaxper band), each nearest-snapped onto the exactfe/Pperiod grid — no in-gap lines (empty by construction; BandIsolation no longer needed to carve k=0 gaps) — with per-band Level scales per line (Q20 ratios preserved, peak normalized tomax(|scales|)), duplicates keeping the last tone's scale (fancy-assignment semantics, per the operator's overwrite choice), and the −π/4 quadratic chirp phase law in the grid position across the union span (the sweep rate is unchanged and requested-tone gaps do not distort it). Still strictly P-periodic (exactfe/Pgrid, length-P inverse DFT — no 2^N quantization anywhere). Spec §5.2.2 k=0 bullet rewritten.Tests
test_multi_tones.py: k=0 section rewritten — requested-tones-only (inter-band gap EMPTY), per-band Level line ratios (scales 1.0/0.25 → 4× magnitude ratio), duplicate-overwrite (last scale wins), chirp-phase assertion (unit-circle-wrapped comparison againstπ(m̃²/N − 0.25)); period/guards/dispatch tests unchanged.test_pipeline.py: pass-through pinned at peak == 1.0 (same-object contract), new boost test (0.9 → 1.0) and near-zero untouched test; all bitwise stage pins wrapped withpipeline._normalize_full_scale; CFR RMS bound widened for the boost factor.test_generate.py+ chirp/comb-IQ integration: "all post off" compares the file against the normalized raw output, with the no-clip bound relaxed to one int16 LSB (the peak legitimately lands at full scale).test_protected_notch.py: passthrough vs the normalization rule.Gate: 1296 passed / 64 skipped (headless UI tier),
ruff checkclean,mypyclean.