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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions