We could definitely use better docs for streamplot
But to solve your question: there are four parameters (provided as keyword arguments) in streamplot
which control how the output looks. These are:
gridsize
: controls the number of “cells” in the grid, i.e., where a streamplot trajectory can start
maxsteps
: what it says on the tin, the max number of steps that a simulation can go forward
density
: the density of trajectories in the streamplot
stepsize
: the size of each simulation step when simulating the trajectory
For our purposes here, we’ll ignore stepsize
since it seems to be at least correct.
The beauty of Makie is that all these attributes are actually Observables, meaning that we can update them on the fly and Makie will automatically re-compute! You can use Makie’s UI functionality (sliders in this case) to allow you to interactively explore and understand what these parameters do (though we should document that as well!)
I made a small example to show how you can interactively manipulate these, and it ends at something which looks close to what you want. If you’d like to contribute to the streamplot docs / examples in Makie (after cleaning up the explanation a bit :D) please feel free!
using GLMakie
# GLMakie is the interactive backend, you could use WGLMakie as well, but not CairoMakie since we want to interact with the plot!
# First, your code - this is a direct copy + paste
x_lim = (-3,3)
y_lim = (-3,3)
stableVanDerPaul(x, y) = Point2f(y, (1 - x^2) * y - x)
semiStable(x, y) = Point2f(y, y - x)
titles = ["non-stable", "stable", "semi-stable"]
functions = [stableVanDerPaul, semiStable]
n = length(functions)
cmaps = [:gnuplot2, :gnuplot2, :gnuplot2]
fig = Figure(size = (800, 600), fontsize = 24)
axs = [Axis(fig[1, i], xlabel = "x", ylabel = "y", title = titles[i],
aspect = 1, backgroundcolor = :white) for i in 1:n]
plts = [streamplot!(axs[i], functions[i], -4 .. 4, -4 .. 4, colormap = [:red,:orange,:brown],
gridsize = (32, 32), arrow_size = 10) for i in 1:n, density = 0.1]
[hideydecorations!(axs[2], grid = false, ticks = false) for i in 2:n]
[limits!(axs[i], x_lim...,y_lim...) for i in 1:n]
fig
# now, we initialize a grid of sliders which allow us to control the parameters
sg = SliderGrid(
fig[2, :],
(label = "Quality", range = 5:40, startvalue = 16),
(label = "Density", range = LinRange(0, 2, 40), startvalue = 1),
(label = "Max steps", range = round.(Int, LinRange(250, 2000, 20)), startvalue = 500),
(label = "Grid size", range = round.(Int, LinRange(16, 100, 20)), startvalue = 32),
)
# each slider has an observable called `value`, which updates whenever the slider is moved
# we pass these updates on to the plots!
on(sg.sliders[1].value) do quality
plts[1].quality[] = quality
plts[2].quality[] = quality
end
on(sg.sliders[2].value) do density
plts[1].density[] = density
plts[2].density[] = density
end
on(sg.sliders[3].value) do maxsteps
plts[1].maxsteps[] = maxsteps
plts[2].maxsteps[] = maxsteps
end
on(sg.sliders[4].value) do gridsize
plts[1].gridsize[] = (gridsize, gridsize, gridsize)
plts[2].gridsize[] = (gridsize, gridsize, gridsize)
end
fig