Skip to content

feat(plotting): Makie backend parity with the Plots backend - #540

Merged
ocots merged 3 commits into
mainfrom
feat/makie-backend-parity
Aug 28, 2026
Merged

ocots merged 3 commits into
mainfrom
feat/makie-backend-parity

Conversation

@ocots

@ocots ocots commented Aug 28, 2026 •

Copy link
Copy Markdown
Member

Brings CTBaseMakie (proof of concept, render only) to feature parity with CTBasePlots.

What changed

ext/CTBaseMakie.jl:

  • seriestype dispatch — :steppost → Makie.stairs!(…; step=:post), :scatter → Makie.scatter!, :path → Makie.lines!. Constant-interpolation controls now render as steps.
  • z_order — series drawn back-to-front using the same _z_rank ordering as the Plots backend.
  • Decorations — HLine / VLine drawn via Makie.hlines! / vlines! with style translation (box bounds, t0/tf markers).
  • User kwargs — _partition_user splits into (series_user, axes_user); axis attributes (legend, ylims, grid/scale/ticks) forwarded to every cell, unknown keys dropped. Makie exposes no attributes(:Series) analogue, so the split uses curated whitelists (_SERIES_USER_KEYS / _AXIS_USER_KEYS).
  • render! overlay — real implementation: targets existing Makie.Axis blocks by deterministic leaf order; an empty target figure is filled as if by render (new _render_into! helper, shared with render).

src/Plotting/contract.jl — MakieBackend docstring drops the proof-of-concept caveat.

test/suite/plotting/test_contract_makie.jl — POC assertions replaced by parity assertions mirroring test_contract.jl on the same _figure() IR (overlay keeps axis count, decorations become HLines/VLines, :steppost becomes Stairs, forwarded attributes reach the axes).

Follow-up commits on this branch

  • 1a2624f — :split cells hardcode legend=false; a user label= (or an IR series label) now turns the legend back on, on both backends, so overlaid solutions can be told apart.
  • 1b71e9e — docs: name the Makie backend in the Architecture Overview + the "no backend loaded" note; new "User Attributes: Series vs Axis" section in the plotting guide documenting the per-backend kwarg split.

Docs

  • CairoMakie added to docs/Project.toml; make.jl loads it and registers :CTBaseMakie; the plotting guide gains an executed Makie @example; CTBaseMakie appears on the API reference internals page.
  • make.jl warnonly gains :external_cross_references. The self-referencing InterLinks "CTBase" entry cannot resolve symbols added since the last published inventory (here MakieBackend, latent since feat(plotting): add Makie backend (proof of concept) #539) on a fresh checkout; per the Handbook self-reference pattern the first build completes-with-errors to produce objects.inv, then a second build is clean. Matches CTModels.jl, which already sets this.

Testing

Last full local run 2026-08-28 (1b71e9e):

  • test/suite/plotting — green
  • full suite — 120460 pass
  • docs — clean (2-pass on a fresh checkout, see above)

Part of control-toolbox/CTModels.jl#408.

🤖 Generated with Claude Code

`CTBaseMakie` was a proof of concept (`render` only). Bring it level with
`CTBasePlots` on the whole IR:

- `seriestype` dispatch — `:steppost` → `Makie.stairs!(…; step=:post)`,
  `:scatter` → `Makie.scatter!`, `:path` → `Makie.lines!` (was: everything
  drawn as lines);
- `z_order` — series drawn back-to-front, same `_z_rank` ordering as Plots;
- `HLine` / `VLine` decorations via `Makie.hlines!` / `vlines!` with style
  translation (box bounds, initial/final-time markers);
- user-kwarg partition — `(series_user, axes_user)`; axis attributes
  (`legend`, `ylims`, grid/scale/ticks) forwarded to every cell, unknown keys
  dropped;
- real `render!` overlay — targets existing `Makie.Axis` blocks by
  deterministic leaf order; an empty target figure is filled as if by `render`
  (via the new `_render_into!`).

`test_contract_makie.jl` mirrors `test_contract.jl` on the same IR fixture
(overlay, decorations, stairs, forwarded attributes). Docs: `CairoMakie` docs
dep, executed Makie `@example` in the plotting guide, `CTBaseMakie` on the API
reference internals page. `make.jl` `warnonly` gains
`:external_cross_references` so the self-referencing `InterLinks` bootstrap
(first build produces `objects.inv`, second resolves) is non-fatal — matches
CTModels.jl.

Part of control-toolbox/CTModels.jl#408.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ocots and others added 2 commits August 28, 2026 13:17
`_lower_split` sets `legend=false` on every cell (the component name is the
y-label, not a legend entry). Both backends took that literally, so
`plot(sol; label="s1")` set the series label but never showed it — a
regression from the pre-engine recipe, where Plots auto-revealed the legend
for any labelled series. It also affected the Makie backend, which dropped the
`label` kwarg entirely (not in `_SERIES_USER_KEYS`).

- `CTBaseMakie`: `:label` added to `_SERIES_USER_KEYS`; `_draw_into_axis!`
  shows the legend when a series carries a non-empty label (IR or user `label`).
- `CTBasePlots`: `_draw_axes!` picks `:best` instead of `false` when a series
  is labelled (IR or user `label`).

Default `:split` figures are unchanged (no labels → no legend).

Part of control-toolbox/CTModels.jl#408.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The Backend Contract section and Function Reference already covered
MakieBackend; the Architecture Overview diagram/prose and the "no backend
loaded" note still mentioned only Plots. Bring them level, and add a
"User Attributes: Series vs Axis" subsection explaining how each backend
partitions user kwargs into series vs axis attributes — Plots introspects
Plots.attributes(:Series), Makie uses curated whitelists and drops
unknown keys.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@ocots ocots added run ci Trigger the CI workflow on this PR run documentation Trigger the Documentation workflow on this PR labels Aug 28, 2026
@ocots

ocots commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

Updates since the PR was opened

  • 1a2624f fix(plotting): a user \label=` shows the legend on a :split cell— regression fix affecting **both** backends._lower_splithardcodeslegend=false; a user label=(or an IR series label) now turns the legend back on so overlaid solutions can be told apart. Verified:plot(sol; layout=:split, label="tat")` → legend on every cell (Plots + Makie); no label → no legend. Full suite 120460 pass.
  • 1b71e9e docs: name the Makie backend everywhere the engine's backends are listed — Architecture Overview diagram/prose + the "no backend loaded" note were still Plots-only; brought level. Adds a "User Attributes: Series vs Axis" guide section explaining how each backend partitions user kwargs (Plots introspects Plots.attributes(:Series); Makie uses curated whitelists and drops unknown keys). Docs build clean.

@ocots
ocots merged commit 8db77d0 into main Aug 28, 2026
20 checks passed
@ocots
ocots deleted the feat/makie-backend-parity branch August 28, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run ci Trigger the CI workflow on this PR run documentation Trigger the Documentation workflow on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant