Skip to content

ANALYSIS - Add equilibrium, stability, and PE visualization toolkit#198

Merged
logan-nc merged 12 commits into
developfrom
feature/analysis-plots
Mar 27, 2026
Merged

ANALYSIS - Add equilibrium, stability, and PE visualization toolkit#198
logan-nc merged 12 commits into
developfrom
feature/analysis-plots

Conversation

@logan-nc
Copy link
Copy Markdown
Collaborator

Summary

  • Adds 17 new plot functions across three Analysis submodules, each implemented as a standalone component callable independently or composed into summary plots
  • Adds a new Analysis.PerturbedEquilibrium submodule for resonant coupling and island visualization
  • Fixes PerturbedEquilibrium/Utils.jl to write full singular coupling matrices to HDF5 (previously only scalars were written)
  • Updates all analyze_example.jl scripts to demonstrate the new functions

New functions

Analysis.ForceFreeStates (component → summary pattern):

  • plot_energy_eigenvectors(h5path; matrix_type=:total) — heatmap of |Wₜ| eigenvectors
  • plot_eigenvalue_spectrum(h5path; matrix_type=:total/:plasma/:vacuum) — eigenvalue scatter colored by stability
  • plot_delta_prime(h5path) — |Δ'| bar chart from FFS asymptotic coefficients
  • plot_dcon_summary(h5path) — 4-panel composer (eigenvectors, criterion, spectrum, Δ')
  • plot_singular_surfaces(h5path) — 2-panel composer (q-profile with surface markers, Δ')

Analysis.Equilibrium:

  • plot_qprofile(h5path; show_singular=true) — q(ψ) with optional rational surface overlays
  • plot_pressure_profile(h5path) — μ₀p(ψ)
  • plot_f_profile(h5path) — 2πF(ψ)
  • plot_equilibrium_summary(h5path) — 3-panel composer

Analysis.PerturbedEquilibrium (new submodule):

  • plot_resonant_flux, plot_island_widths, plot_chirikov_parameter, plot_pe_delta_prime
  • plot_resonant_field(h5path) — 5-panel composer of resonant coupling quantities
  • plot_mode_spectrogram(h5path; component=:xi_psi/:b_psi/:b_theta/:b_zeta) — line + heatmap spectrogram
  • plot_perturbed_equilibrium_summary(h5path) — 3-panel composer (islands, energies, spectrogram)

OMFIT plots ported and not ported

Ported

OMFIT function Julia function Module
plot_dcon_summary.py plot_dcon_summary + component functions Analysis.ForceFreeStates
plot_equil_summary.py (profiles) plot_equilibrium_summary + component functions Analysis.Equilibrium
plot_resonant_field.py plot_resonant_field + component functions Analysis.PerturbedEquilibrium
plot_spectrograms.py plot_mode_spectrogram Analysis.PerturbedEquilibrium
(new — no OMFIT equivalent) plot_singular_surfaces, plot_perturbed_equilibrium_summary ForceFreeStates / PerturbedEquilibrium

Not ported

PENTRC/NTV not implemented in Julia:

  • plot_torque.py, plot_torque_summary.py, plot_torque_matrices.py, plot_torque_by_coil.py — require NTV torque output (T_xe, T_coil) not computed in Julia GPEC

Requires outputs not yet in Julia:

  • plot_resonant_coupling.py, plot_resonant_coupling_matrix.py — require control surface coupling matrix C_xe
  • plot_control_1d/2d.py, plot_control_mode_coil_summary.py — require coil decomposition matrices
  • plot_field_at_wall.py — requires cylindrical (wall-projected) output
  • plot_reluctance_matrix.py — requires reluctance matrix R_xe
  • plot_stride_summary.py — requires full STRIDE Δ' matrix (available in edge_jacobian branch, not yet merged)

3D visualization (Mayavi-based, no Plots.jl equivalent):

  • plot_3d_basics.py, plot_gpec_wall.py, plot_gpec_coils.py, plot_control_modes_3d.py, plot_control_3d.py

Input profiles (not GPEC output):

  • plot_profiles.py — kinetic input profiles (n_e, T_i, T_e, ω_E), not from gpec.h5

Already covered:

  • plot_equilibrium.py — flux surfaces covered by existing Analysis.Equilibrium.plot_flux_surfaces

Test plan

  • Run julia --project=. examples/Solovev_ideal_example/analyze_example.jl — verify all new plot calls execute without error
  • Run julia --project=. examples/DIIID-like_ideal_example/analyze_example.jl — verify FFS summary plots render; PE plots should gracefully return "no data" plots if PE not enabled
  • Run existing test suite: julia --project=. -e 'using Test; using GeneralizedPerturbedEquilibrium; include("test/runtests_fullruns.jl")'

🤖 Generated with Claude Code

…tion toolkit

New component and summary plot functions across three Analysis submodules:

ForceFreeStates (src/Analysis/ForceFreeStates.jl):
- plot_energy_eigenvectors: heatmap of |Wt| eigenvectors vs (m, mode index)
- plot_eigenvalue_spectrum: eigenvalue scatter colored by stability (red/green)
- plot_delta_prime: |Δ'| bar chart from FFS asymptotic coefficients (ca_left/ca_right)
- plot_dcon_summary: 4-panel composer (eigenvectors, criterion, spectrum, Δ')
- plot_singular_surfaces: 2-panel composer (q-profile with surface markers, Δ')

Equilibrium (src/Analysis/Equilibrium.jl):
- plot_qprofile: q(ψ) with rational surface overlays
- plot_pressure_profile: μ₀p(ψ)
- plot_f_profile: 2πF(ψ)
- plot_equilibrium_summary: 3-panel composer (q, pressure, F profiles)

PerturbedEquilibrium (src/Analysis/PerturbedEquilibrium.jl, new file):
- plot_resonant_flux, plot_island_widths, plot_chirikov_parameter, plot_pe_delta_prime
- plot_resonant_field: 5-panel composer of resonant coupling quantities
- plot_mode_spectrogram: 2-panel line+heatmap spectrogram (xi_psi/b_psi/b_theta/b_zeta)
- plot_perturbed_equilibrium_summary: 3-panel composer (islands, energies, spectrogram)

PE HDF5 output (src/PerturbedEquilibrium/Utils.jl):
- Write resonant_flux, resonant_current, island_width_sq, penetrated_field, delta_prime
  (ComplexF64), island_half_width and chirikov_parameter (Float64) to singular_coupling group

Updated all analyze_example.jl scripts to demonstrate the new functions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@logan-nc logan-nc self-assigned this Mar 23, 2026
@logan-nc logan-nc added the enhancement New feature or request label Mar 23, 2026
logan-nc and others added 11 commits March 23, 2026 10:24
…x, response shape

- ForceFreeStates: Replace hline! with vline! in plot_eigenvalue_spectrum
  (stability boundary is Re(eigenvalue)=0, a vertical line, not horizontal)
- ForceFreeStates: Replace invalid annotate!(p, :center, :top, ...) with title!
  in plot_dcon_summary (no-vacuum-data branch); :center/:top are not data coords
- ForceFreeStates: Add inline note explaining imag(xi_psi) phase convention
- PerturbedEquilibrium: Fix plot_resonant_flux, plot_pe_delta_prime,
  _plot_resonant_current to read PE forcing mode n from
  perturbed_equilibrium/forcing_modes/n instead of info/mn_index (FFS).
  PE coupling matrices are (num_forcing_modes, msing), not (numpert_total_FFS, msing)
- PerturbedEquilibrium: Fix plot_mode_spectrogram data layout and psi axis.
  Response data is (npsi, numpert_total) not (numpert_total, npsi); psi axis
  is integration/psi (737 pts), not splines/profiles/xs (183 pts)
- PerturbedEquilibrium: Fix plot_perturbed_equilibrium_summary docstring to
  match implementation (no Chirikov overlay on island-width panel)
- Add examples/DIIID-like_ideal_example/make_plots.jl: saves all 20 plots
  to examples/DIIID-like_ideal_example/plots/ using GR backend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, and spacing fixes

- plot_mode_spectrogram: flip heatmap to (m, ψ_N) with psi on vertical axis
  (conventional spectrogram orientation); rational surface overlays use hline!
- plot_mode_spectrogram: trim line plot legend to m ∈ [0, nhigh·q95) to avoid
  unwieldy legend from negative/high-m modes outside the resonant range
- All plots: add left_margin, bottom_margin, right_margin (Plots.mm) throughout
  to prevent axis labels, rotated xtick text, and colorbar titles from clipping
- plot_equilibrium_summary: increase size to (1300, 450), add top_margin for
  plot_title clearance; reduce plot_titlefontsize to avoid overlap
- Summary plots: adjust sizes to give subpanels more breathing room

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…coloring

- plot_eigenmode_summary: align top eigenvector bar with heatmap x-axis using
  @layout [a{0.25h} _{0.25w}; b c{0.25w}] (blank cell preserves column widths)
- plot_eigenmode_summary: color scatter by sign (red=negative, blue=positive)
  and add markerstrokewidth=0 to remove black rings from dots
- plot_eigenvalue_spectrum: apply same color convention (red=negative/unstable,
  blue=positive/stable) instead of previous red/green

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…onversions, new equilibrium panels

- Eigenmode summary (ffs_eigenmode_summary): removed from make_plots (redundant with ffs_summary)
- ffs_dcon_summary → ffs_summary; eigenvalue plot replaced with mode displacement (|ξ_ψ| vs ψ_N)
- All bar charts (Δ', resonant flux/current, island widths, Chirikov) converted to scatter plots on ψ_N axis with integer-q annotations
- plot_delta_prime: shows Re(Δ') with sign coloring and zero reference line
- Equilibrium summary: tall RZ panel (left column), profiles stacked right; x-axes share [0,1] range; upper panels suppress redundant x-axis labels
- plot_flux_surfaces_h5: rational surfaces drawn as red closed contours with q labels
- plot_f_profile: rational surface vlines added (consistent with q and P plots)
- GSE panels: log-scale y-axis; integrated error overplotted on theta-slice panel; single legend entry
- All ψ_N labels use LaTeXStrings (L"\psi_N"); |ξ_ψ| and |D_c| similarly subscripted
- Profile plot titles removed (y-axis labels carry the information)
- Stability criterion: ylabel/title updated to |D_c|, zero reference line added
- PlotlyJS and LaTeXStrings added to Project.toml
- CLAUDE.md: note added to never remove packages from Project.toml

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nd alignment

Remove titles from all 5 subplots in plot_resonant_field (ylabels carry the same
information). Move outertopright legends inside (:topright) for the top 3 panels so
all 5 panels share the same right margin and x-axes align. Suppress x-axis labels
and ticks on the top 4 panels; only the bottom (Chirikov) panel shows the x-axis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…o analyze scripts, increase margins and fix colorbar overlap

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documenter was failing with missing_docs error because all PerturbedEquilibrium
analysis functions had docstrings but no @autodocs block in analysis.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@logan-nc
Copy link
Copy Markdown
Collaborator Author

No main src changes here - anything is an improvement over what we had before and everyone should feel empowered to improve any/all plots as we go. API is bound to change for PE stuff, so I am not going to waste anyone's time asking for reviews now.

@logan-nc logan-nc merged commit 4396444 into develop Mar 27, 2026
4 checks passed
@logan-nc logan-nc deleted the feature/analysis-plots branch March 27, 2026 13:59
logan-nc added a commit that referenced this pull request Apr 2, 2026
Incorporates:
- PR #207: FastInterpolations v0.4 API (Series() wrappers, ZeroCurvBC, remove explicit defaults)
- PR #208: Separatrix finder Brent method fix
- PR #198: Analysis module improvements (plot_eigenvalues, plot_delta_prime, plot_ffs_summary)
- AdaptiveArrayPools v0.3.5, FastInterpolations v0.4.7

Conflict resolved in src/Analysis/ForceFreeStates.jl: retained our
plot_edge_stability_scan alongside develop's new plot_eigenvalues,
plot_delta_prime, and plot_ffs_summary functions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant