Skip to content

feat(train): TrainingConfig subcarrier-layout presets + real MmFiDataset loader test (audit #4/#6/#7)#537

Merged
ruvnet merged 1 commit into
mainfrom
fix/training-config-mesh-and-loader-test
May 12, 2026
Merged

feat(train): TrainingConfig subcarrier-layout presets + real MmFiDataset loader test (audit #4/#6/#7)#537
ruvnet merged 1 commit into
mainfrom
fix/training-config-mesh-and-loader-test

Conversation

@ruvnet

@ruvnet ruvnet commented May 12, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the remaining doable findings from the 2026-05-11 training-pipeline audit (after #535 fixed #5 and #536 fixed #1-extract/#2/#3):

# Finding This PR
6 CSI format default = 56-sc / 1 NIC — non-MM-Fi shapes require hand-overriding two fields TrainingConfig::for_subcarriers + named presets + docs
7 Multi-band 168-sc mesh (ADR-078) not reflected in the training config TrainingConfig::multiband_168() preset + multi-NIC mapping documented
4 proof.rs uses SyntheticCsiDataset not real data ✅ reframed + tests/test_real_loader.rs covers the real on-disk path

#6 / #7TrainingConfig subcarrier-layout presets

num_subcarriers: 56 / native_subcarriers: 114 were the only documented shape; using any other CSI source meant overriding both fields by hand. New, in config.rs:

  • TrainingConfig::for_subcarriers(native, target) — explicit native→model resample.
  • TrainingConfig::mmfi() (114→56, == default()), ht40_192() (≈192-sc ESP32 HT40 → 56), multiband_168() (168-sc ADR-078 multi-band mesh → 56).
  • Field docs now list the common native counts (MM-Fi 114, HT20 56, HT40 ≈192/114, multi-band mesh 168) and point at the presets, plus a note that a 2–3-node CSI mesh currently maps onto [T, n_tx, n_rx, n_sc] via extra n_rx until a dedicated node dimension lands.
  • The model's input width stays num_subcarriers — the presets only change the resampling input, not the architecture.

#4 — real on-disk loader test

A deterministic proof must use a reproducible source, so verify-training correctly stays on SyntheticCsiDataset — the real gap was that nothing exercised MmFiDataset's .npy disk-loading path. New tests/test_real_loader.rs:

  • writes synthetic CSI (deterministic, no RNG) to .npy files in the MmFiDataset::discover layout (<root>/S01/A01/{wifi_csi.npy, wifi_csi_phase.npy, gt_keypoints.npy}),
  • loads it back via discover + get, asserting CsiSample shapes ([T,n_tx,n_rx,n_sc], keypoints [17,2], visibility [17]) and finiteness,
  • covers the subcarrier-interpolation branch (target 28 < native 56 → resampled output shape) and the empty-root case.
  • Adds ndarray / ndarray-npy as [dev-dependencies] for fixture writing.

Tests

cargo check -p wifi-densepose-train --no-default-features — clean (only pre-existing ruvector-* / wifi-densepose-nn warnings). cargo test -p wifi-densepose-train --no-default-features — all existing tests green, plus the 3 new test_real_loader.rs tests and the updated config.rs doctest (now exercises ht40_192() / for_subcarriers) pass. Purely additive — no model-shape change, no tch-module change, deterministic proof untouched. (An unrelated 109-line Cargo.lock drift a cargo check introduced was reverted, so the diff is clean.)

Audit scoreboard

#1 (extract) ✅ #2#3 ✅ (#536) · #4#6#7 ✅ (this PR) · #5 ✅ (#535). The one not closed: #1's training-target half — wiring the extracted signal_features into a vitals/multi-task supervision head — is blocked on a vitals-labeled dataset (MM-Fi/Wi-Pose carry no vitals labels; an ESP32 paired capture would). The end-to-end path is in the training-guide.md delivered to the pulse-seed handoff. So all 7 findings are addressed/reframed; one has a remaining follow-up gated on data.

🤖 Generated with claude-flow

…set loader test

Closes the remaining doable items from the 2026-05-11 training-pipeline audit:

#6 (CSI format default = 56-sc / 1 NIC) + #7 (multi-band 168-sc mesh not in
config): new `TrainingConfig::for_subcarriers(native, target)` plus named
presets `mmfi()` (114→56), `ht40_192()` (≈192-sc ESP32 HT40 → 56) and
`multiband_168()` (168-sc ADR-078 multi-band mesh → 56). Non-MM-Fi CSI shapes
are now first-class instead of requiring manual `native_subcarriers` /
`num_subcarriers` overrides; the field docs list the supported source counts
and the multi-NIC mapping (a 2–3-node mesh currently rides on `n_rx` until a
dedicated node dimension lands). Model input width stays `num_subcarriers`; the
presets only vary the resampling input.

#4 (proof.rs uses synthetic data): reframed — a deterministic proof *must* use
a reproducible source, so `verify-training` correctly stays on
`SyntheticCsiDataset`. The real gap was that nothing exercised the on-disk
`MmFiDataset` path. New `tests/test_real_loader.rs` writes synthetic CSI to
`.npy` files in the `MmFiDataset::discover` layout, loads it back, and checks
the resulting `CsiSample` — covering the no-interp case, the
subcarrier-interpolation branch, and the empty-root case. Adds `ndarray` /
`ndarray-npy` as dev-deps for the fixture writing.

cargo check + cargo test -p wifi-densepose-train --no-default-features: clean,
all existing tests green, 3 new loader tests + the updated config doctest pass.
Purely additive — no model-shape change, no tch-module change.

Co-Authored-By: claude-flow <ruv@ruv.net>
@ruvnet
ruvnet merged commit c604ca1 into main May 12, 2026
4 of 13 checks passed
@ruvnet
ruvnet deleted the fix/training-config-mesh-and-loader-test branch May 12, 2026 03:49
ruvnet added a commit that referenced this pull request May 12, 2026
Publishing the additive changes from PRs #536/#537 to crates.io:
- `signal_features` module — wires `wifi-densepose-signal` into the pipeline
  (audit #1/#2)
- `TrainingConfig::for_subcarriers` / `ht40_192()` / `multiband_168()` presets
  + the real `MmFiDataset` loader integration test (audit #4/#6/#7)

No public API removals or changes — additive only, so 0.3.0 -> 0.3.1 is
semver-correct. No other workspace crate depends on `wifi-densepose-train`,
so this is a standalone bump.

Co-Authored-By: claude-flow <ruv@ruv.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1011 Best Way to Block

1 participant