| name | plotting-basics |
| description | How to plot with plot_julia: native plotters, live windows, and seeing your own plots |
Plotting basics
When to use
Use this skill whenever the user asks for a plot, chart, figure, or visualization,
or when a plot would make simulation results easier to understand.
The model: plot_julia captures whatever you draw
Use plot_julia for anything that produces a figure — never build a Figure
in run_julia (that saves no artifact and the user can't see it). plot_julia:
- activates the right Makie backend for this session (you don't manage backends),
- evaluates your code, and
- captures the resulting figure to an image file — whether your code returns a
Figure, returns a (fig, ax, plot) tuple, or calls a native plotter that opens
a window / calls display internally.
So you do not need to end on fig, and you do not need to avoid display.
Just call the plotter.
Prefer native plotters
Call your simulator's own documented plotters first — they are the canonical,
best-looking views, they run on GLMakie, and plot_julia captures them
automatically. The <sim>-overview skill lists the plotters for your simulator.
Build a Figure inline when no native plotter fits, or when you want a specific
custom view:
fig = Figure(size = (600, 400))
ax = Axis(fig[1, 1], title = "History match", xlabel = "t", ylabel = "rate")
lines!(ax, t, sim); scatter!(ax, t, obs)
fig
Seeing your own plot: view=true
Pass view=true to get the (downscaled) image back so you can look at it —
to verify a curve overlays the data, spot an anomaly, or check a 3D view. Use it
deliberately, not on every plot (each image costs tokens). The user always sees
the saved artifact regardless of view.
plot_julia(code="<your plot code>", view=true) # then reason about what you see
How the user sees a plot
plot_julia shows the figure to the user and saves a PNG record. How it is shown
depends on the interface you are driving (your interface note states it): a live
Makie window on the desktop they can rotate, zoom, and step; an interactive figure
pinned in a side panel on the web; or just the saved PNG on a headless/one-shot
run. You always just call plot_julia — you don't manage that difference, and
there's no separate "interactive" mode.
view is for you, not the user — it returns the image to you; it shows
them nothing extra.
- Pass
window=false only to compute/inspect a plot without surfacing it.
- Don't force a backend or window from a plotter's own kwargs (e.g.
gui=true):
that opens a separate desktop window outside plot_julia. Just call the plotter
normally — the tool already shows the figure the right way for the interface.
- If the user says they can't see a plot, you probably built it in
run_julia
(use plot_julia) or set window=false — fix that, don't just re-describe it.
Slots, recapture, close
Each plot is keyed by its slot — the same slot refreshes that view in place
(reuse it when iterating so you don't spawn a new view per attempt), and distinct
plots get distinct slots (slot="reservoir", slot="wells") so they stay
addressable as separate views. This applies on every interface (a desktop window,
or a tab in the web side panel).
Recapture and close act on desktop plot windows (they don't apply on the web,
where the figure stays live in the browser):
- Recapture after the user rotates/zooms/steps a window:
recapture_plot(slot="reservoir") re-renders that plot's figure at its current
state and returns the image. Omit slot for the most recent. It renders the
figure jutul-agent still holds, so it works even if the user closed the window
(you get its last state); only close_plots discards it. You can't advance the
timestep yourself — ask the user to step the window, then recapture.
- Close windows with
close_plots(slot="reservoir") (one) or close_plots() (all).
Diagnostics & model structure
Sizing and slots
- Output is PNG.
size=(width, height) sets a specific resolution.
slot="name" overwrites the same artifact path when refreshing a comparison
during calibration (e.g. slot="saturation_final").
Loading tabular data
using CSV, DataFrames
obs = CSV.read("experiments/observations/data.csv", DataFrame) # workspace-relative, no leading slash
Performance
- Do not re-run a full simulation inside
plot_julia if the REPL already holds
the result/arrays from a recent run_julia — plot from the cached objects.
Plotting should take seconds, not minutes.
- Reuse
slot= for comparison plots you refresh during calibration.