|
| 1 | +# Plotting |
| 2 | + |
| 3 | +`AbstractVectorOfArray` and `AbstractDiffEqArray` types include |
| 4 | +[Plots.jl](https://github.com/JuliaPlots/Plots.jl) recipes so they can be |
| 5 | +visualised directly with `plot(A)`. |
| 6 | + |
| 7 | +## VectorOfArray |
| 8 | + |
| 9 | +A `VectorOfArray` plots as a matrix where each inner array is a column: |
| 10 | + |
| 11 | +```julia |
| 12 | +using RecursiveArrayTools, Plots |
| 13 | +A = VectorOfArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) |
| 14 | +plot(A) # 3 series (components) vs column index |
| 15 | +``` |
| 16 | + |
| 17 | +## DiffEqArray |
| 18 | + |
| 19 | +A `DiffEqArray` plots as component time series against `A.t`: |
| 20 | + |
| 21 | +```julia |
| 22 | +u = [[sin(t), cos(t)] for t in 0:0.1:2pi] |
| 23 | +t = collect(0:0.1:2pi) |
| 24 | +A = DiffEqArray(u, t) |
| 25 | +plot(A) # plots sin and cos vs t |
| 26 | +``` |
| 27 | + |
| 28 | +If the `DiffEqArray` carries a symbolic system (via `variables` and |
| 29 | +`independent_variables` keyword arguments), the axis labels and series names |
| 30 | +are set automatically from the symbol names. |
| 31 | + |
| 32 | +## Dense (Interpolated) Plotting |
| 33 | + |
| 34 | +When a `DiffEqArray` has an interpolation object in its `interp` field and |
| 35 | +`dense = true`, calling `plot(A)` generates a smooth curve by evaluating the |
| 36 | +interpolation at many points rather than connecting only the saved time steps. |
| 37 | + |
| 38 | +```julia |
| 39 | +using SciMLBase: LinearInterpolation |
| 40 | + |
| 41 | +u = [[1.0, 0.0], [0.0, 1.0], [-1.0, 0.0], [0.0, -1.0]] |
| 42 | +t = [0.0, 1.0, 2.0, 3.0] |
| 43 | +interp = LinearInterpolation(t, u) |
| 44 | +A = DiffEqArray(u, t; interp = interp, dense = true) |
| 45 | +plot(A) # smooth interpolated curve with 1000+ points |
| 46 | +``` |
| 47 | + |
| 48 | +### Plot Recipe Keyword Arguments |
| 49 | + |
| 50 | +The `AbstractDiffEqArray` recipe accepts the following keyword arguments, |
| 51 | +which can be passed directly to `plot`: |
| 52 | + |
| 53 | +| Keyword | Type | Default | Description | |
| 54 | +|---------|------|---------|-------------| |
| 55 | +| `denseplot` | `Bool` | `A.dense && A.interp !== nothing` | Use dense interpolation for smooth curves. Set `false` to show only saved points. | |
| 56 | +| `plotdensity` | `Int` | `max(1000, 10 * length(A.u))` | Number of evenly-spaced points to evaluate when `denseplot = true`. | |
| 57 | +| `tspan` | `Tuple` or `nothing` | `nothing` | Restrict the time window. E.g. `tspan = (0.0, 5.0)`. | |
| 58 | +| `idxs` | varies | `nothing` | Select which components to plot (see below). | |
| 59 | + |
| 60 | +Example: |
| 61 | + |
| 62 | +```julia |
| 63 | +plot(A; denseplot = true, plotdensity = 5000, tspan = (0.0, 2.0)) |
| 64 | +``` |
| 65 | + |
| 66 | +## Selecting Variables with `idxs` |
| 67 | + |
| 68 | +The `idxs` keyword controls which variables appear in the plot. It supports |
| 69 | +several formats: |
| 70 | + |
| 71 | +### Single component |
| 72 | + |
| 73 | +```julia |
| 74 | +plot(A; idxs = 1) # plot component 1 vs time |
| 75 | +plot(A; idxs = 2) # plot component 2 vs time |
| 76 | +``` |
| 77 | + |
| 78 | +### Multiple components |
| 79 | + |
| 80 | +```julia |
| 81 | +plot(A; idxs = [1, 3, 5]) # plot components 1, 3, 5 vs time |
| 82 | +``` |
| 83 | + |
| 84 | +### Phase-space plots (component vs component) |
| 85 | + |
| 86 | +Use a tuple where index `0` represents the independent variable (time): |
| 87 | + |
| 88 | +```julia |
| 89 | +plot(A; idxs = (1, 2)) # component 1 vs component 2 |
| 90 | +plot(A; idxs = (0, 1)) # time vs component 1 (same as default) |
| 91 | +plot(A; idxs = (1, 2, 3)) # 3D plot of components 1, 2, 3 |
| 92 | +``` |
| 93 | + |
| 94 | +### Symbolic indexing |
| 95 | + |
| 96 | +When the `DiffEqArray` carries a symbolic system, variables can be referenced |
| 97 | +by symbol: |
| 98 | + |
| 99 | +```julia |
| 100 | +A = DiffEqArray(u, t; variables = [:x, :y], independent_variables = [:t]) |
| 101 | +plot(A; idxs = :x) # plot x vs time |
| 102 | +plot(A; idxs = [:x, :y]) # plot both |
| 103 | +plot(A; idxs = (:x, :y)) # phase plot of x vs y |
| 104 | +``` |
| 105 | + |
| 106 | +### Custom transformations |
| 107 | + |
| 108 | +A function can be applied to the plotted values: |
| 109 | + |
| 110 | +```julia |
| 111 | +plot(A; idxs = (norm, 0, 1, 2)) # plot norm(u1, u2) vs time |
| 112 | +``` |
| 113 | + |
| 114 | +The tuple format is `(f, xvar, yvar)` or `(f, xvar, yvar, zvar)` where `f` |
| 115 | +is applied element-wise. |
| 116 | + |
| 117 | +## Callable Interface |
| 118 | + |
| 119 | +Any `AbstractDiffEqArray` with an `interp` field supports callable syntax for |
| 120 | +interpolation, independent of plotting: |
| 121 | + |
| 122 | +```julia |
| 123 | +A(0.5) # interpolate all components at t=0.5 |
| 124 | +A(0.5; idxs = 1) # interpolate component 1 at t=0.5 |
| 125 | +A([0.1, 0.5, 0.9]) # interpolate at multiple times (returns DiffEqArray) |
| 126 | +A(0.5, Val{1}) # first derivative at t=0.5 |
| 127 | +A(0.5; continuity = :right) # right-continuity at discontinuities |
| 128 | +``` |
| 129 | + |
| 130 | +The interpolation object must be callable as |
| 131 | +`interp(t, idxs, deriv, p, continuity)`, matching the protocol used by |
| 132 | +SciMLBase's `LinearInterpolation`, `HermiteInterpolation`, and |
| 133 | +`ConstantInterpolation`. |
| 134 | + |
| 135 | +When no interpolation is available (`interp === nothing`), calling `A(t)` |
| 136 | +throws an error. |
| 137 | + |
| 138 | +## ODE Solution Plotting |
| 139 | + |
| 140 | +ODE solutions from DifferentialEquations.jl are subtypes of |
| 141 | +`AbstractDiffEqArray` and inherit all of the above functionality, plus |
| 142 | +additional features: |
| 143 | + |
| 144 | +- **Automatic dense plotting**: `denseplot` defaults to `true` when the solver |
| 145 | + provides dense output. |
| 146 | +- **Analytic solution overlay**: `plot(sol; plot_analytic = true)` overlays the |
| 147 | + exact solution if the problem defines one. |
| 148 | +- **Discrete variables**: Time-varying parameters are plotted as step functions |
| 149 | + with dashed lines and markers. |
| 150 | +- **Symbolic indexing**: Full symbolic indexing through ModelingToolkit is |
| 151 | + supported, including observed (derived) variables. |
| 152 | + |
| 153 | +These advanced features are defined in SciMLBase and activate automatically |
| 154 | +when plotting solution objects. |
0 commit comments