Rotating live wiring#65
Merged
Merged
Conversation
Optional pre-gate 2-D Gaussian blur of the rotating spectrogram so contiguous coherent structure survives aggressive gating: smooth_spectrogram (power + coherence) and smooth_mode_spectrogram (n-map quality + amplitude) in core, run before denoise_spectrogram and applied consistently across the spectrogram / coherence / n-spectrum / n-map nodes. Two fixes make it actually visible: - σ in grid cells, not ms/kHz. Physical widths mapped to sub-bin σ on the coarse STFT grid (2 ms slice → 0.5 kHz bins; time-decimated columns), so the defaults rounded to a near-no-op and moving the sliders did nothing. Cells are one STFT bin, resolution-relative, and can't collapse below a bin. The GUI shows the physical equivalent per live grid (e.g. "3.0 cells ≈ 6.0 ms") via the new pure medianStep helper. Params: smooth_t_cells / smooth_f_cells. - Smooth LINEAR power (arithmetic mean), not log power. A log/geometric mean is dominated by the darkest cell, so a punched-out ridge gap stayed dark and never survived the gate. Linear averaging is pulled toward the bright cells, so a ridge bleeds into and fills its dim neighbours — the whole point of the pass. Contract (CONTRACT.md) + plan docs updated. Tests: core smooth incl. ridge-gap reinforcement, node smoke/no-op, medianStep. Full suite 222 passed / 1 skipped; frontend tsc + 26 vitest green; ruff clean. Co-Authored-By: Claude Opus 4.8 <[email protected]>
Add an `api` entry to .claude/launch.json (uvicorn on :8000, --reload) so the FastAPI backend can be launched alongside the web dev server. Re-resolve uv.lock (drop the stale exclude-newer pin; loosen a pexpect marker). Co-Authored-By: Claude Opus 4.8 <[email protected]>
Follow-up patch to the 2-D Gaussian pre-smoothing in this feature: it blurred *linear* power, which haloed bright ridges and, viewed on the log heatmap, *raised* the visible log-variance instead of lowering it — so the blur was effectively invisible. Smooth log10 power (then map back) so the blur is uniform across the dynamic range and matches both the display and the log-power gate; coherence stays linear. Real-shot log-variance now drops monotonically with sigma. Co-Authored-By: Claude Opus 4.8 <[email protected]>
…ooth test - app.py: drop the raw exception text from the /download 500 body (keep it in logger.exception) so an h5py/OSError message can't leak to the client - contract.ts: type HeatmapNode.z as (number | null)[][] to match the denoise-gated cells the server now emits as null - test_nodes.py: assert the smoothed spectrogram z actually differs from the baseline, so a no-op regression in the smooth-param wiring fails
The contract change typed HeatmapNode.z as (number | null)[][] to match the denoise-gated cells the server emits as null. tsc -b (strict project build) then flagged three RotatingTab consumers that assumed number[][]: - cursor-column power trace: null cell → NaN so the log trace gaps there - live coherence column: coalesce a gated/absent cell to 0 - stripePlot: widen its param to (number | null)[][]; Plotly renders null as gaps
matt-pharr
added a commit
that referenced
this pull request
Jul 1, 2026
…relock) Third develop→kstar_int sync. develop advanced with PR #65 (rotating-live wiring: 2-D Gaussian pre-smoothing, download-500 hardening, heatmap null-cell handling) and PR #46 (gui-sensors: device-agnostic coil overlay, saddle-loop tilt). Only one conflict — uv.lock — since pyproject.toml is identical on both sides; resolved by taking develop's lockfile and regenerating with `uv lock` (135 packages, `uv lock --check` clean). app.py, nodes.py, and test_nodes.py auto-merged. Verified: ruff/ty/pytest (312 passed, 5 skipped)/eslint/tsc/vitest (29)/vite build all green. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds optional 2-D Gaussian pre-smoothing to the rotating spectrogram, applied before
the coherence/power gates so contiguous coherent mode ridges survive aggressive gating.
σ is expressed in grid cells (not ms/kHz, which rounded to a sub-bin no-op on the coarse
STFT grid) with a live physical-units readout, and linear power is smoothed (arithmetic
mean) so a bright ridge fills its dim/dropout neighbours instead of staying dark.
Related issue
N/A
Type of change
src/magnetics/core)src/magnetics/data)src/magnetics/service)gui/web)How I tested it
uv run pytest→ 222 passed, 1 skipped (incl.test_ridge_gap_is_reinforced, which thelinear-power switch turns green; plus node smooth smoke/no-op and
medianSteptests).uv run ruff format --check .+uv run ruff check→ clean.cd gui/web && npx tsc --noEmit→ clean;npx vitest run→ 26 passed.0.518 (off) → 0.024 (σ 3/1.5 cells) → 0.007 (σ 8/5 cells) — strong, monotonic.
(−0.06 log10) under linear smoothing vs staying dark (−0.80) under the old log-power mean.
σ time: 3.0 cells ≈ 6.0 ms,σ freq: 1.5 cells ≈ 0.75 kHz, computed from the live grid viamedianStep.Checklist
ruff+pytest; web:lint+build)core(device-agnostic); none added to service routesdocs/CONTRACT.md+ plan docs)