Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The changelogs of individual sub-packages are self-contained for each package.
# v3.6

- New interactive GUI function: `interactive_2d_clicker`.
- New keyword `statespace_names` for `interactive_trajectory`.

# v3.5

Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "DynamicalSystems"
uuid = "61744808-ddfa-5f27-97ff-6e42cc95d634"
repo = "https://github.com/JuliaDynamics/DynamicalSystems.jl.git"
version = "3.6.0"
version = "3.6.1"

[deps]
Attractors = "f3fd9213-ca85-4dba-9dfd-7fc91308fec7"
Expand Down
40 changes: 11 additions & 29 deletions docs/src/visualizations.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,25 +240,32 @@ oddata = interactive_orbitdiagram(ds, p_index, p_min, p_max, i;
ps, us = scaleod(oddata)
```

## Interactive 2D clicker
## Interactive 2D dynamical system

```@docs
interactive_2d_clicker
```

Example:
The `interactive_2d_clicker` function can be used to spin up a GUI
for interactively exploring the state space of a 2D dynamical system.

For example, the following code show how to interactively explore a
[`ProjectedDynamicalSystem`](@ref):

```julia
using GLMakie, DynamicalSystems

# This is the 3D Lorenz model
lorenz = Systems.lorenz()

projection = [1, 2]
complete_state = [12.0]
complete_state = [0.0]
projected_ds = ProjectedDynamicalSystem(lorenz, projection, complete_state)

interactive_2d_clicker(projected_ds; Δt = 0.01, times = 10:100)
interactive_2d_clicker(projected_ds; tfinal = (10.0, 150.0))
```


## Interactive Poincaré Surface of Section

```@raw html
Expand Down Expand Up @@ -340,28 +347,3 @@ j = 2 # the dimension of the plane

interactive_poincaresos_scan(trs, j; linekw = (transparency = true,))
```

## Interactive 2D dynamical system

```@docs
interactive_clicker
```

The `interactive_clicker` function can be used to spin up a GUI
for interactively exploring the state space of a 2D dynamical system.

For example, the following code show how to interactively explore a
[`ProjectedDynamicalSystem`](@ref):

```julia
using GLMakie, DynamicalSystems

# This is the 3D Lorenz model
lorenz = Systems.lorenz()

projection = [1, 2]
complete_state = [0.0]
projected_ds = ProjectedDynamicalSystem(lorenz, projection, complete_state)

interactive_clicker(projected_ds; tfinal = (10.0, 150.0))
```
32 changes: 17 additions & 15 deletions ext/src/interactive_trajectory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function DynamicalSystems.interactive_trajectory(
axis = NamedTuple(),
lims = nothing,
statespace_axis = true,
statespace_names = state_name.(idxs),
starting_step = 1,
)

Expand All @@ -40,7 +41,7 @@ function DynamicalSystems.interactive_trajectory(
statespacelayout = fig[1,1] = GridLayout()
lims = isnothing(lims) ? _traj_lim_estimator(ds, u0s, idxs, [1], Δt)[1] : lims
tailobs, finalpoints = _init_statespace_plot!(statespacelayout, ds, idxs,
lims, pds, colors, plotkwargs, markersize, tail, axis, fade, statespace_axis,
lims, pds, colors, plotkwargs, markersize, tail, axis, fade, statespace_names, statespace_axis,
)
# Set up layouting and add controls
if add_controls # Notice that `run` and `step` are already observables
Expand Down Expand Up @@ -130,15 +131,15 @@ vector_idx_observe(ds, u, idxs) = [observe_state(ds, i, u) for i in idxs]
"Create the state space axis and evolution controls. Return the axis."
function _init_statespace_plot!(
layout, ds, idxs, lims, pds, colors, plotkwargs, markersize, tail, axis, fade,
statespace_axis # whether to show the statespace axis
statespace_names, statespace_axis # whether to show the statespace axis
)
tailobs, finalpoints = _init_trajectory_observables(pds, tail)
is3D = length(idxs) == 3
axisposition = statespace_axis ? layout[1,1] : Figure()[1,1]
xlabel = state_name(idxs[1])
ylabel = state_name(idxs[2])
xlabel = statespace_names[1]
ylabel = statespace_names[2]
statespaceax = if is3D
zlabel = state_name(idxs[3])
zlabel = statespace_names[3]
Axis3(axisposition; xlabel, ylabel, zlabel, axis...)
else
Axis(axisposition; xlabel, ylabel, axis...)
Expand Down Expand Up @@ -272,16 +273,17 @@ end
# Timeseries extension
###########################################################################################
function DynamicalSystems.interactive_trajectory_timeseries(
ds::DynamicalSystem, fs::Vector, u0s = [current_state(ds)];
linekwargs = isdiscretetime(ds) ? (linewidth = 1,) : (linewidth = 3,),
timeseries_names = [state_name(f) for f in fs],
colors = collect(cgrad(COLORSCHEME, length(u0s); categorical = true)),
timeseries_ylims = nothing,
timelabel = "time", timeunit = 1,
Δt = DynamicalSystems.isdiscretetime(ds) ? 1 : 0.01,
idxs = 1:min(length(u0s[1]), 3),
lims = nothing,
kwargs...)
ds::DynamicalSystem, fs::Vector, u0s = [current_state(ds)];
linekwargs = isdiscretetime(ds) ? (linewidth = 1,) : (linewidth = 3,),
timeseries_names = state_name.(fs),
colors = collect(cgrad(COLORSCHEME, length(u0s); categorical = true)),
timeseries_ylims = nothing,
timelabel = "time", timeunit = 1,
Δt = DynamicalSystems.isdiscretetime(ds) ? 1 : 0.01,
idxs = 1:min(length(u0s[1]), 3),
lims = nothing,
kwargs...
)

# automatic limits
if isnothing(timeseries_ylims) || isnothing(lims)
Expand Down
3 changes: 2 additions & 1 deletion src/visualizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ See also [`interactive_trajectory`](@ref).

- `idxs = 1:min(length(u0s[1]), 3)`: Which variables to plot in a state space trajectory.
Any index that can be given to [`observe_state`](@ref) can be given here.
- `statespace_names = state_name.(idxs)`: Names for the state space axis.
- `statespace_axis = true`: Whether to create and display an axis for the trajectory plot.
- `idxs = 1:min(length(u0s[1]), 3)`: Which variables to plot in a state space trajectory.
Any index that can be given to [`observe_state`](@ref) can be given here.
Expand All @@ -108,7 +109,7 @@ See also [`interactive_trajectory`](@ref).

- `linekwargs = NamedTuple()`: Extra keywords propagated to the timeseries plots.
Can also be a vector of named tuples, each one for each unique initial condition.
- `timeseries_names`: A vector of strings with length equal to `fs` giving names to
- `timeseries_names = state_name.(fs)`: A vector of strings with length equal to `fs` giving names to
the y-labels of the timeseries plots.
- `timeseries_ylims`: A vector of 2-tuples for the lower and upper limits of the
y-axis of each timeseries plot. If not given it is deduced automatically similarly to `lims`.
Expand Down