Skip to content

Analysis UX: introduce a GPECResult object + precondition-aware plot registry #326

Description

@matt-pharr

Motivation

The analysis/plotting experience currently has no in-memory result object. The boundary between "GPEC ran" and "I want to look at the output" is a bag of hardcoded HDF5 string paths — each of the ~30 plot_* functions in src/Analysis/ re-opens the h5 and reaches for its own paths (e.g. perturbed_equilibrium/singular_coupling/resonant_area_weighted_field).

That single missing abstraction produces most of our UX pain:

  • Discovery — you must read the docs to learn which plots exist and what they mean, because nothing in memory can tell you.
  • Preconditions — there is no shared notion of "which stages ran". Functions check ad-hoc (e.g. _has_pe_data in src/Analysis/PerturbedEquilibrium.jl returns a placeholder plot titled "run with perturbed equilibrium enabled"), which is inconsistent and easy to forget.

This issue is the keystone of a small Analysis/UX foundation effort (see related issues). Fixing the abstraction removes the need for a heavyweight GUI.

Proposed design

Introduce a lazy GPECResult type wrapping a gpec.h5 (returned from main() and/or via GPEC.load("gpec.h5")) that:

  1. Knows which stages ran by inspecting the h5 groups (equil/, vacuum/, locstab//integration/, perturbed_equilibrium/, ...). Expose stages(result) / result.available.
  2. Backs a plot registry. Each plot_* declares its required stage/dataset(s). Then plots(result) returns a catalog: plot name, one-line description, and ✓/✗ availability with the reason it is unavailable.
  3. Exposes typed accessors so user code and plot functions stop hardcoding h5 path strings.
  4. Has a good show(io, ::GPECResult) printing a summary: stages run, key scalars (q95, β_N, # singular surfaces, Re(et[1]), ...), and "N plots available, M unavailable (need X)".

Target experience

result = GPEC.load("gpec.h5")
result                            # show() summary: stages, key scalars, plot availability
plots(result)                     # catalog with ✓/✗ + reason
result.singular.island_widths     # typed accessor, no h5 strings
plot(result, :island_widths)      # unavailable -> clear, actionable error (see below)

Precondition errors, not placeholder plots

Replace the current placeholder-plot pattern with a thrown, actionable error. An empty plot titled "no data" is worse than an exception — the user doesn't learn why or what to change. Example message:

plot_island_widths requires the PerturbedEquilibrium stage; this run set force_termination=true. Enable [PerturbedEquilibrium] and re-run.

Scope / suggested first slice

  • Add the GPECResult type, stages(), plots() catalog, and the precondition registry.
  • Wire a handful of existing plot_* functions (e.g. one from each Analysis submodule) into the registry as a proof of concept, rather than converting all 30 at once.
  • Follow-up: migrate the remaining plot functions.

Related

These three together are the real fix; the "do we need a GUI?" question largely answers itself once this object exists (a thin Pluto dashboard becomes plots(result) + a dropdown).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions