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).

Activity

  1. added this to the GPEC v2.0.0 milestone on Oct 27, 2026
  2. added
    apiConfig key, output dataset or exported name changed
    on Oct 30, 2026
  3. added theissue type on Oct 30, 2026
  4. logan-nc commented on Nov 2, 2026

    @logan-nc
    Collaborator

    Moving to v2.1.0. We're closing out v2.0 tonight for Matt's release pass tomorrow, and a new public API surface shouldn't land on deadline night without design review. Nothing here blocks v2.0: the existing Analysis plotting entry points ship as they are.

  5. matt-pharr commented on Nov 2, 2026

    @matt-pharr
    CollaboratorAuthor

    Yes this is fine @logan-nc. I think this design is a little bit stale as well but still a good idea. This can be an early 2.1.0 pr.

  6. matt-pharr commented on Nov 4, 2026

    @matt-pharr
    CollaboratorAuthor

    Superseded in shape by #649 and #650. After v2.0.0's typed stage results, a wrapper type would duplicate them, so:

    Not adopted: the GPECResult/GPEC.load wrapper and plot(result, :name). The catalog names the real functions instead. #650 closes this issue when it merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

apiConfig key, output dataset or exported name changed

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions