Skip to content

Added Advanced Options to Quasistatic GUI#57

Open
mfairborn23 wants to merge 17 commits into
developfrom
qs-gui-improvement
Open

Added Advanced Options to Quasistatic GUI#57
mfairborn23 wants to merge 17 commits into
developfrom
qs-gui-improvement

Conversation

@mfairborn23

@mfairborn23 mfairborn23 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Improves the quasi-stationary (QS) GUI tab and merges in refactor-quasistationary's SLCONTOUR
restructuring, reconciling the overlap between the two.

  • Array dropdown parity: the QS tab's "Array" selector used a hardcoded 9-item list that had
    drifted from the left sidebar's device-driven sensor-set list (28 entries). It now reads from
    the same device.sensor_sets source as the sidebar, falling back to the old curated list
    offline/in mock mode.
  • New "Advanced options" panel in the QS tab, toggled by a button styled to match the
    settings bar (not the collapsible plot sections below it):
    • Uncertainty (σ) — measurement uncertainty applied uniformly to every channel (default
      2e-5), now a real, overridable fit parameter instead of a hardcoded constant.
    • Fraction of energy included — the SVD energy-retention filter (already wired backend-side;
      this adds the missing UI control).
    • Basis functionsinusoidal-integral / sinusoidal-point / gaussian-integral /
      gaussian-point, all of which already existed in the fit but were never exposed through the
      API.
    • Fit condition — the lstsq condition-number cutoff, same story (existing physics, newly
      wired).
  • Fixed a silent regression: the tokamak wall outline had disappeared from the QS tab's Sensor
    Map cross-section plot. load_wall() was still reading the device JSON's wall key with the
    old flat schema after it was migrated to a shot-segmented one — it always returned (None, None) with no error. Superseded by refactor-quasistationary's independent fix, which resolves
    the newer first_wall key via the same shot-aware resolver the Sensors tab already uses.
  • Merged in refactor-quasistationary: promotes the SLCONTOUR reference pipeline out of the
    _slcontour/ OMFIT-shim layout into shim-free core/qs_* modules (qs_fit, qs_prep,
    qs_io_data, qs_plots, qs_run, qs_device), deleting the old omfit_compat.py shim and the
    unused pure-numpy core/quasistationary.py port. Where the two branches touched the same code,
    the incoming restructuring was prioritized; this branch's additive work (the sigma/fit_basis/
    fit_cond wiring, the Advanced Options UI) was re-pointed at the new module layout rather than
    dropped.

Changes

  • gui/web/src/components/tabs/QuasiStationaryTab.tsx — array-dropdown parity + Advanced Options
    panel.
  • src/magnetics/service/nodes.py_qs_run/_prep_qs_ds parse and forward sigma,
    fit_basis, fit_cond; _sensor_map_rz now resolves the wall outline shot-aware.
  • src/magnetics/core/qs_fit.py (renamed from _slcontour/fit.py) — new sigma_override
    parameter; uniform-σ override path.
  • src/magnetics/core/qs_device.py (new, replaces _slcontour/omfit_compat.py) — device/geometry
    adapter, including the first_wall-based load_wall fix.
  • src/magnetics/core/{qs_prep,qs_io_data,qs_plots,qs_run}.py (renamed from _slcontour/*),
    qs_bridge.py — carried over from refactor-quasistationary with no functional changes beyond
    the rename/import-path updates.
  • src/magnetics/core/quasistationary.py, src/magnetics/_slcontour/* — deleted (superseded by
    core/qs_*).
  • tests/test_qs_bridge.py, tests/test_slcontour_geometry.py — new coverage from both branches
    kept: sigma/fit_basis/fit_cond wiring tests, load_wall regression tests, and the
    mode-reconstruction sign-convention test.
  • docs/specs/quasistationary-mode-analysis.md, examples/example_magnetics.ipynb — carried over
    from refactor-quasistationary (relocated/modernized QS reference notebook + a new spec doc).

Test plan

  • uv run pytest — 216 passed, 1 skipped
  • npm test (gui/web) — 24 passed
  • npx tsc --noEmit / npm run build / npm run lint — clean
  • uv run ty check — no new diagnostics (pre-existing, unrelated issues only, in
    tests/test_spectral.py)
  • End-to-end manual check against a real fetched shot (184927): wall outline present, and
    sigma/fit_basis/fit_cond query params confirmed to reach and change the fit output
    (not just recorded as labels)

🤖 Generated with Claude Code

priyanshlunia and others added 12 commits July 1, 2026 12:12
Retire the dead core/quasistationary.py (a partial, unwired port whose
reconstruct_grid used exp(+i(nφ+mθ)) — wrong for any phased mode) plus its
falsely-certifying test, and promote the *active* SLCONTOUR pipeline into core
under unified qs_ naming, deleting the omfit_compat OMFIT shim.

- Move _slcontour/{fit,prep,io_data,run,plots}.py -> core/qs_*.py.
- Delete omfit_compat.py, folding each symbol to its owner: printv/w/e -> logging;
  OMFITexception -> ValueError; delta_degrees -> qs_fit; cornernote/uband ->
  qs_plots; device readers -> new core/qs_device.py, which delegates to the data
  layer (data.devices / data.diiid_geometry) and keeps only the QS-specific extras
  (derived theta/end-coord sensor_geometry, resolve_channel_filter semantics).
- qs_device.load_wall now delegates to devices.feature_at, fixing the segmented-
  schema bug (the shim read a nonexistent top-level `wall` key -> (None, None)).
- Lock the -i reconstruction convention: invariant comments at the three sites
  + a discriminating δ≠0 regression test the old zero-phase test missed.
- qs_plots docstring clarified as standalone matplotlib (not GUI/service wired).
- Rewire service/nodes.py + tests; pyproject drops the ruff exclude and retargets
  a deferred ty exclude onto the qs_* files. Relocate the reference notebook/README
  to docs/qs_slcontour/.

ruff format/check + ty (with service extra) clean; 209 passed, 1 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Finish the core/qs_* promotion by cleaning up its reference material, which was
still written for the old OMFIT `magnetics-code` layout.

- Move example_magnetics.ipynb into examples/ and rewire it onto the new
  infrastructure: imports become magnetics.core.qs_{io_data,device,run} plus
  `qs_plots as plots` (so the plot cells are unchanged); drop the sys.path hack
  and the OMFIT-script mapping / "ported OMFIT scripts" framing.
- Replace docs/qs_slcontour/README.md with docs/quasistationary-mode-analysis.md:
  no OMFIT-magnetics plumbing (module↔OMFIT-script table, omfit_compat, cd
  analysis), instead a walkthrough of the qs_* pipeline (io_data → prep → fit →
  run, plus qs_bridge→service and standalone qs_plots), data inputs, quick start,
  and the -i reconstruction sign convention. Physics provenance (SLCONTOUR,
  VISION §4.1) kept.
- Remove the now-empty docs/qs_slcontour/.

Docs-only; no src/ behavior change. ruff format --check clean.
(docs/magnetics-code-architecture.md is also OMFIT-era — left for a later sweep.)

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…ond), wall-outline fix

- QS tab's Array dropdown now uses the same device sensor_sets list as the
  left sidebar instead of a hardcoded 9-item subset.
- New Advanced Options controls in the QS tab: uncertainty (sigma), fraction
  of energy included, basis function, fit condition - wired through to the
  SLCONTOUR fit via new sigma_override/fit_basis/fit_cond query params.
- Fix load_wall() reading the device JSON's legacy flat wall schema; it's
  been shot-segmented since 28c75c6, so the wall outline silently stopped
  rendering in the QS Sensor Map cross-section plot.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Prioritizes the incoming SLCONTOUR restructuring (_slcontour/* -> core/qs_*,
qs_device.py replacing omfit_compat.py) over this branch's prior fixes where
they overlapped:
- Dropped this branch's _segment_fields-based load_wall fix on the legacy
  `wall` key in favor of the incoming qs_device.load_wall, which resolves
  the newer, canonical `first_wall` key via devices.feature_at.
- Kept this branch's additive work with no incoming equivalent: the QS tab's
  Advanced Options UI, and the sigma_override/fit_basis/fit_cond query-param
  wiring in _qs_run/_prep_qs_ds (now pointed at core.qs_run/core.qs_device
  instead of the deleted _slcontour module).
- Merged both branches' new tests in test_qs_bridge.py and
  test_slcontour_geometry.py rather than dropping either side's coverage.
Pulls in the cluster-network-config work that landed on develop while this
branch was in progress (device-file network blocks, explicit cluster
address + per-channel mdsthin default, auto hop-count resolution) plus new
QS-correctness test coverage (PR #47). No conflicts with this branch's QS
GUI/backend work.
Mirrors qs_plots.plot_svds's two diagnostic panels as GUI-servable
LineNodes: data-matrix SVD cumulative energy fraction and design-matrix
per-singular-value condition number, each carrying the relevant
threshold (energy_limit / fit_condition) as a reference line.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
…lots

- Add hover title= tooltips (sourced from OMFIT's magnetics_gui.py help
  text) to Array, n/m modes, Detrend, band, t trim, and basis function
  - the last gaps among the QS settings-bar and Advanced Options controls.
- Surface svd_energy/svd_condition fetch errors instead of silently
  leaving the panels stuck on a generic "loading..." placeholder forever.
- Move the SVD energy/condition plots into their own default-open
  section instead of nesting them inside the closed-by-default "fit
  quality" panel, so they're visible without extra clicks.
- Fix SVD condition-number axis rendering: use a linear y-axis to match
  the qs_plots.plot_svds reference (was hardcoded log, which let an
  off-screen threshold line stretch the autorange and squash the data),
  add dtick=1 to both SVD x-axes (small-integer singular-value index),
  and give both legends more top margin so they don't crowd the header.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
- SVD conditioning: default the section closed like the other
  collapsible panels, and double both plots' height (150 -> 300).
- Reorder the settings bar: move "t trim (ms)" next to "Array".
- Shorten the Array tooltip to plain dropdown guidance.
- Rename "band (ms)" to "detrend band (ms)" for clarity.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Main-series points 4 -> 8, "removed" x-markers 7 -> 12.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
@mfairborn23 mfairborn23 requested a review from matt-pharr July 1, 2026 20:15
@mfairborn23

Copy link
Copy Markdown
Collaborator Author

Ready to merge I think

# Conflicts:
#	gui/web/src/components/tabs/QuasiStationaryTab.tsx
@logan-nc

logan-nc commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

@mfairborn23 can you post a screenshot of the new GUI layout?

One thing I noticed yesterday was there was something called "band" that you guys said was actually the baselining window... I found that confusing and am interested to see how it's been clarified if you've added band-pass filtering as another entry as claimed in #81. None of the description above says anything about band pass filtering?

…l when you click the button to adjust text size
@mfairborn23

Copy link
Copy Markdown
Collaborator Author

Okay- I'll look into this and see if I missed something!

@mfairborn23

Copy link
Copy Markdown
Collaborator Author
image I think it's just hidden in the "Advanced" tab. Sounds like I should move it out?

@mfairborn23

Copy link
Copy Markdown
Collaborator Author

Sorry that last screen shot isnt very visible. I think it can be seen more clearly here
image

@logan-nc

logan-nc commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Yeah, smoothing (i.e. filtering) is a top level thing - ESPECIALLY if it defaults to some value other than (0, inf). We should tell users if we are doing something to the data.

Minor: Some of these are capitalized and others are not → standardize.

Do you think the number of entries is too intimidating to just have all there? Lets group them more logically:
Line 1 (Basics): Array, time
Line 2 (Data): detrend opts, bandpass filtering, svd filtering, uncertainty
Line 3 (Fitting): basis functions, conditioning

I suppose you could collapse some, but I think if organized like this it would be pretty clean to just always have showing

@mfairborn23

Copy link
Copy Markdown
Collaborator Author

Alright- sounds good! I will reorganize the options!

Replace the primary-bar + Advanced-toggle split with three always-visible
rows grouped by function: Basics (array, time trim, mode numbers), Data
(detrend, bandpass, SVD filtering, uncertainty), and Fitting (basis
function, condition number). Removes the advancedOpen toggle so nothing
is hidden by default.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
@mfairborn23

mfairborn23 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

New version in the most recent commit (except I am renaming t trim "time")
image

@mfairborn23 mfairborn23 mentioned this pull request Jul 2, 2026
5 tasks
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.

3 participants