Public API
This page lists exported symbols of CTBase.Plotting.
From CTBase.Plotting
CTBase.Plotting [Module]
CTBase.Plotting Module
PlottingGeneric, domain-free plotting engine for the Control Toolbox.
It manipulates a backend-agnostic intermediate representation (IR): a weighted tree (CTBase.Plotting.Leaf/CTBase.Plotting.HBox/CTBase.Plotting.VBox) of titled CTBase.Plotting.Axes carrying CTBase.Plotting.Series and CTBase.Plotting.AbstractDecorations. It knows nothing about states, controls, costates, trajectories or optimal control — the case layers (CTModels, CTFlows) build the IR and hand it to a backend via CTBase.Plotting.render.
The IR and all its transforms live here in src (no backend dependency); only the drawing lives in an extension (CTBasePlots for Plots.jl). See the design report in CTModels.jl/.reports/dev/plot_engine_ctbase_report.md.
Public API
IR:
CTBase.Plotting.Series,CTBase.Plotting.AbstractDecoration,CTBase.Plotting.HLine,CTBase.Plotting.VLine,CTBase.Plotting.Annotation,CTBase.Plotting.Axes,CTBase.Plotting.Leaf,CTBase.Plotting.HBox,CTBase.Plotting.VBox,CTBase.Plotting.Figure,CTBase.Plotting.leavescase-layer building blocks:
CTBase.Plotting.Panel,CTBase.Plotting.Stacked,CTBase.Plotting.Paired,CTBase.Plotting.Grid; for trajectories made of phases,CTBase.Plotting.splice_jumps,CTBase.Plotting.switching_vlines,CTBase.Plotting.phase_annotationsbackend contract:
CTBase.Plotting.AbstractPlottingBackend,CTBase.Plotting.PlotsBackend,CTBase.Plotting.MakieBackend,CTBase.Plotting.render,CTBase.Plotting.render!
AbstractDecoration [Abstract Type]
CTBase.Plotting.AbstractDecoration Type
abstract type AbstractDecorationAbstract type of the decorations drawn on an CTBase.Plotting.Axes on top of its series: reference lines (CTBase.Plotting.HLine, CTBase.Plotting.VLine) and texts (CTBase.Plotting.Annotation). Decorations carry no legend entry.
Interface Requirements
A new decoration is a subtype with a drawing method in each backend extension: _draw_decoration!(p, d, sp) in CTBasePlots and _draw_decoration!(axis, d) in CTBaseMakie. A backend without such a method throws a CTBase.Exceptions.NotImplemented when it renders the decoration.
See also: CTBase.Plotting.Axes.
AbstractLayoutNode [Abstract Type]
CTBase.Plotting.AbstractLayoutNode Type
abstract type AbstractLayoutNodeSupertype of the weighted layout tree: CTBase.Plotting.Leaf (a cell), CTBase.Plotting.HBox (columns side by side) and CTBase.Plotting.VBox (rows stacked). This is the backend-agnostic geometry a renderer turns into subplots.
AbstractPlottingBackend [Abstract Type]
CTBase.Plotting.AbstractPlottingBackend Type
abstract type AbstractPlottingBackendSupertype of rendering backends. A backend adds methods to CTBase.Plotting.render / CTBase.Plotting.render! on its concrete type from a weak-dependency extension; the fallback here errors when no backend is loaded.
Annotation [Struct]
CTBase.Plotting.Annotation Type
struct Annotation <: CTBase.Plotting.AbstractDecorationA text placed in a cell (e.g. the label of a phase). Its abscissa x is a data coordinate; its ordinate y is relative to the y-axis range: 0 is the bottom of the axis and 1 its top, so the text keeps its place whatever the data. The backend reads the y-range once the series are drawn.
style uses the neutral vocabulary of CTBase.Plotting.Series where it applies (color, backend_kwargs), plus fontsize and halign (:left, :center, :right) / valign (:bottom, :center, :top). Annotations carry no legend entry.
A cell holding annotations gets some room above its data when its y-limits are automatic (see CTBase.Plotting._ANNOTATION_HEADROOM), so that a text near the top does not cover the curves.
Fields
x::Float64y::Float64text::Stringstyle::NamedTuple
Example
julia> using CTBase: Plotting
julia> a = Plotting.Annotation(0.5, "bang"; y=0.9);
julia> (a.x, a.y, a.text)
(0.5, 0.9, "bang")Axes [Struct]
CTBase.Plotting.Axes Type
struct AxesOne drawable cell: a single axis system holding a list of CTBase.Plotting.Series, optional CTBase.Plotting.AbstractDecorations drawn on top, and its labels/limits. Domain-free — the case layer decides what a cell means.
ylims is one of:
nothing— leave the backend default,(lo, hi)— fixed limits,:auto— backend auto-scaling,:auto_guarded— auto, but widen a (near-)constant series so the axis does not collapse (resolved from the series data, either at lowering or by the backend).
Fields
title::Stringxlabel::Stringylabel::Stringseries::Vector{CTBase.Plotting.Series}decorations::Vector{CTBase.Plotting.AbstractDecoration}legend::Boolylims::Union{Nothing, Tuple{Float64, Float64}, Symbol}
Figure [Struct]
CTBase.Plotting.Figure Type
struct FigureA complete figure: a layout root plus optional overall size and title. size === nothing defers to the engine size heuristic (CTBase.Plotting.default_size); title === nothing draws no overall title.
Fields
root::CTBase.Plotting.AbstractLayoutNodesize::Union{Nothing, Tuple{Int64, Int64}}title::Union{Nothing, String}
Grid [Function]
CTBase.Plotting.Grid Function
Grid(
cells::AbstractMatrix{<:CTBase.Plotting.AbstractLayoutNode};
row_weights,
col_weights
) -> CTBase.Plotting.VBoxArrange a rectangular matrix of nodes into a grid: cells[i, j] is row i, column j (e.g. the :group n×m layout). Each row becomes an CTBase.Plotting.HBox and the rows are stacked in a CTBase.Plotting.VBox. Row and column weights default to equal; pass row_weights / col_weights to override.
HBox [Struct]
CTBase.Plotting.HBox Type
struct HBox <: CTBase.Plotting.AbstractLayoutNodeHorizontal juxtaposition of child nodes (columns placed side by side). weights are relative column widths, one per child (strictly positive). See also CTBase.Plotting.VBox.
Fields
children::Vector{CTBase.Plotting.AbstractLayoutNode}weights::Vector{Float64}
HLine [Struct]
CTBase.Plotting.HLine Type
struct HLine <: CTBase.Plotting.AbstractDecorationA horizontal reference line at height value (e.g. a box bound). style follows the same neutral vocabulary as CTBase.Plotting.Series.
Fields
value::Float64style::NamedTuple
Leaf [Struct]
CTBase.Plotting.Leaf Type
struct Leaf <: CTBase.Plotting.AbstractLayoutNodeA leaf of the layout tree: a single drawable cell wrapping one CTBase.Plotting.Axes.
MakieBackend [Struct]
CTBase.Plotting.MakieBackend Type
struct MakieBackend <: CTBase.Plotting.AbstractPlottingBackendThe Makie.jl backend, at feature parity with CTBase.Plotting.PlotsBackend. The type lives here in src; its CTBase.Plotting.render / CTBase.Plotting.render! methods live in the CTBaseMakie extension, loaded automatically once Makie is available (e.g. via CairoMakie / GLMakie).
Paired [Function]
CTBase.Plotting.Paired Function
Paired(
children::AbstractVector{<:CTBase.Plotting.AbstractLayoutNode};
weights
) -> CTBase.Plotting.HBoxPlace children side by side into an CTBase.Plotting.HBox (e.g. state | costate). With weights=:auto each child's weight is its number of columns (grid_shape(child)[2]), so equal-width columns stay equal; pass an explicit weight vector to override. A two-argument form Paired(left, right) is provided for the common pair.
Panel [Struct]
CTBase.Plotting.Panel Type
struct PanelA titled group of components sharing one time grid — the case layer's convenient input unit (e.g. all state components). It is not part of the rendered IR: the CTBase.Plotting.lower step turns a Panel into CTBase.Plotting.Leaf/CTBase.Plotting.Axes nodes.
Each panel carries its own time grid x (so different groups may live on different grids) and, optionally, a per-component styles vector (finer than the single shared style). data is (n_times, n_components).
Fields
x::Vector{Float64}title::Stringlabels::Vector{String}data::Matrix{Float64}style::NamedTuplestyles::Vector{NamedTuple}
PlotsBackend [Struct]
CTBase.Plotting.PlotsBackend Type
struct PlotsBackend <: CTBase.Plotting.AbstractPlottingBackendThe Plots.jl backend. The type lives here in src; its CTBase.Plotting.render/CTBase.Plotting.render! methods live in the CTBasePlots extension, loaded automatically once Plots is available.
Series [Struct]
CTBase.Plotting.Series Type
struct SeriesOne plotted curve: a set of (x, y) points. Used both for time series (x a time grid) and for phase plots (x, y two state components). An empty label draws no legend entry.
style uses the neutral, backend-agnostic vocabulary — color, linewidth, linestyle, alpha, seriestype (:path, :steppost, :scatter), z_order (:back/:front) — plus backend_kwargs::NamedTuple as an escape hatch for backend-specific attributes (decision D2).
Fields
x::Vector{Float64}y::Vector{Float64}label::Stringstyle::NamedTuple
Stacked [Function]
CTBase.Plotting.Stacked Function
Stacked(
children::AbstractVector{<:CTBase.Plotting.AbstractLayoutNode};
weights
) -> CTBase.Plotting.VBoxStack children vertically into a CTBase.Plotting.VBox. With weights=:auto (default, decision D4) each child's weight is its number of rows (grid_shape(child)[1]), so stacking blocks of different heights keeps every cell the same height — including when a child is itself a paired block; pass an explicit weight vector to override.
VBox [Struct]
CTBase.Plotting.VBox Type
struct VBox <: CTBase.Plotting.AbstractLayoutNodeVertical stacking of child nodes (rows one under another). weights are relative row heights, one per child (strictly positive). See also CTBase.Plotting.HBox.
Fields
children::Vector{CTBase.Plotting.AbstractLayoutNode}weights::Vector{Float64}
VLine [Struct]
CTBase.Plotting.VLine Type
struct VLine <: CTBase.Plotting.AbstractDecorationA vertical reference line at abscissa value (e.g. initial/final time). style follows the same neutral vocabulary as CTBase.Plotting.Series.
Fields
value::Float64style::NamedTuple
leaves [Function]
CTBase.Plotting.leaves Function
leaves(
leaf::CTBase.Plotting.Leaf
) -> Vector{CTBase.Plotting.Leaf}Return the CTBase.Plotting.Leafs of a node in deterministic order: depth-first, children visited in stored order. This order is the contract used to target existing cells by index when overlaying with CTBase.Plotting.render!.
phase_annotations [Function]
CTBase.Plotting.phase_annotations Function
phase_annotations(
x::AbstractVector{<:Real},
times::AbstractVector{<:Real},
labels::AbstractVector{<:AbstractString};
time,
style
) -> Vector{CTBase.Plotting.Annotation}Return the labels of the phases of a trajectory as texts, centred on each phase near the top of the cell, to be passed to CTBase.Plotting.lower as annotations.
The phases are the intervals between the first time of x, the switching times and the last time of x. A phase with an empty label gets no text, so a trajectory with no label gets none.
Arguments
x::AbstractVector{<:Real}: the time grid of the trajectory.times::AbstractVector{<:Real}: the switching times.labels::AbstractVector{<:AbstractString}: one label per phase (""for no label), or none at all.time::Symbol = :default::default,:normalizeor:normalise, as forCTBase.Plotting.lower.style::NamedTuple = NamedTuple(): merged on top of the default style (grey text).
Throws
CTBase.Exceptions.IncorrectArgument: if there is neither no label nor one label per phase, or iftimeis not one of the accepted symbols.
Example
julia> using CTBase: Plotting
julia> a = Plotting.phase_annotations([0.0, 1.0, 2.0], [1.0], ["bang", "singular"]);
julia> [(t.x, t.text) for t in a]
2-element Vector{Tuple{Float64, String}}:
(0.5, "bang")
(1.5, "singular")See also: CTBase.Plotting.switching_vlines, CTBase.Plotting.Annotation.
render [Function]
CTBase.Plotting.render Function
render(
b::CTBase.Plotting.AbstractPlottingBackend,
::CTBase.Plotting.Figure;
kwargs...
) -> Makie.FigureRender fig into a backend figure. Fallback (backend extension not loaded) errors with an ExtensionError; a backend extension overrides this on its concrete type.
render(
::CTBase.Plotting.PlotsBackend,
fig::CTBase.Plotting.Figure;
kwargs...
) -> AnyRender fig into a new Plots.Plot (Plots backend). Series attributes among kwargs (color, linewidth, label, …) are forwarded to every series; the rest (legend, grid, …) are applied to every cell.
Label keywords are resolved on the IR: xlabel replaces the x label of the cells that carry one, title replaces the overall figure title, and ylabel is ignored with a warning (each cell has its own y label). The renderer-owned keys subplot, titlefont and guidefontsize are ignored with a warning.
render(
::CTBase.Plotting.MakieBackend,
fig::CTBase.Plotting.Figure;
kwargs...
) -> Makie.FigureRender fig into a new Makie.Figure (Makie backend). Series attributes among kwargs (color, linewidth, linestyle, alpha, …) are forwarded to every series; axis attributes (legend, ylims, grid/scale/ticks) to every cell. The figure size comes from CTBase.Plotting.default_size.
Label keywords are resolved on the IR: xlabel replaces the x label of the cells that carry one, title replaces the overall figure title, and ylabel is ignored with a warning (each cell has its own y label).
render! [Function]
CTBase.Plotting.render! Function
render!(
b::CTBase.Plotting.AbstractPlottingBackend,
target,
::CTBase.Plotting.Figure;
kwargs...
) -> Makie.FigureOverlay fig onto an existing backend target, targeting existing cells by the deterministic leaf order (see CTBase.Plotting.leaves).
render!(
::CTBase.Plotting.PlotsBackend,
target,
fig::CTBase.Plotting.Figure;
kwargs...
) -> AnyOverlay fig onto an existing Plots plot target, targeting existing subplots by the deterministic leaf order. Series/decorations are added; axes untouched.
The label keywords title, xlabel and ylabel have no effect here, since the axes are untouched: they are ignored with a warning.
render!(
::CTBase.Plotting.MakieBackend,
target::Makie.Figure,
fig::CTBase.Plotting.Figure;
kwargs...
) -> Makie.FigureOverlay fig onto an existing Makie.Figure target, pairing each leaf of the layout tree with the target's Makie.Axis blocks in deterministic CTBase.Plotting.leaves order; only series and decorations are added, the axes are left untouched. An empty target (no axes yet) is filled as if by CTBase.Plotting.render.
The label keywords title, xlabel and ylabel have no effect on an existing axis: they are ignored with a warning (they apply when target is empty).
splice_jumps [Function]
CTBase.Plotting.splice_jumps Function
splice_jumps(
x::AbstractVector{<:Real},
data::AbstractMatrix{<:Real},
times::AbstractVector{<:Real},
left::AbstractMatrix{<:Real},
right::AbstractMatrix{<:Real};
connect
) -> Tuple{Any, Any}Insert the left and right limits at the switching times into the samples of a panel, so that a jump is drawn as a vertical segment.
At every switching time τ = times[i], the rows left[i, :] then right[i, :] are inserted at τ, in time order; a sample already at τ is replaced by these two rows. The samples are returned unchanged when there is no switching time, or when the limits are not known (matrices with no column).
With connect = true (default), the curve goes from the left to the right limit: a jump is drawn as a vertical segment. This makes jumps easy to see, and to compare with a solution whose jump is smoothed (e.g. from a direct method). With connect = false, a row of NaN is inserted between the two limits: both backends break the curve there, so the curve ends at the left limit and starts again at the right limit, with no segment that could be read as values taken by the trajectory.
Arguments
x::AbstractVector{<:Real}: the sample times, increasing.data::AbstractMatrix{<:Real}: the samples, one row per time, one column per component.times::AbstractVector{<:Real}: the switching times, increasing.left,right::AbstractMatrix{<:Real}: the limits before and after each switching time, one row per switching time, one column per component (or no column: not known).connect::Bool = true: draw a jump as a vertical segment (true) or break the curve (false).
Returns
(x, data): the sample times (each switching time twice, three times withconnect = false) and the samples, asVector{Float64}andMatrix{Float64}.
Throws
CTBase.Exceptions.IncorrectArgument: ifleftorrightdoes not have one row per switching time, or its number of columns differs from that ofdata.
Example
julia> using CTBase: Plotting
julia> x, data = Plotting.splice_jumps([0.0, 1.0, 2.0], [0.0; 1.0; 2.0;;], [1.0], [1.0;;], [3.0;;]);
julia> x
4-element Vector{Float64}:
0.0
1.0
1.0
2.0
julia> vec(data)
4-element Vector{Float64}:
0.0
1.0
3.0
2.0See also: CTBase.Plotting.switching_vlines, CTBase.Plotting.phase_annotations.
switching_vlines [Function]
CTBase.Plotting.switching_vlines Function
switching_vlines(
x::AbstractVector{<:Real},
times::AbstractVector{<:Real};
time,
style
) -> Vector{CTBase.Plotting.VLine}Return the vertical lines at the switching times times of a trajectory sampled on x, in plotted time (see time), to be passed to CTBase.Plotting.lower as vlines. Empty when there is no switching time.
Arguments
x::AbstractVector{<:Real}: the time grid of the trajectory (its first and last times give the normalisation).times::AbstractVector{<:Real}: the switching times.time::Symbol = :default::default,:normalizeor:normalise, as forCTBase.Plotting.lower.style::NamedTuple = NamedTuple(): the style of the lines.
Throws
CTBase.Exceptions.IncorrectArgument: iftimeis not one of the accepted symbols.
See also: CTBase.Plotting.phase_annotations.