From ec6d2c27dde3f9e21a404bd5112c799d0132c087 Mon Sep 17 00:00:00 2001 From: Datseris Date: Fri, 19 Sep 2025 11:21:32 +0100 Subject: [PATCH 1/3] add keyword `statespace_names` in interactive trajecotry --- CHANGELOG.md | 1 + Project.toml | 2 +- ext/src/interactive_trajectory.jl | 32 ++++++++++++++++--------------- src/visualizations.jl | 3 ++- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3020753b..16879dfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/Project.toml b/Project.toml index a6abc82d..eacfbd8a 100644 --- a/Project.toml +++ b/Project.toml @@ -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" diff --git a/ext/src/interactive_trajectory.jl b/ext/src/interactive_trajectory.jl index 0fc0fef2..cc248735 100644 --- a/ext/src/interactive_trajectory.jl +++ b/ext/src/interactive_trajectory.jl @@ -23,6 +23,7 @@ function DynamicalSystems.interactive_trajectory( axis = NamedTuple(), lims = nothing, statespace_axis = true, + statespace_names = state_name.(idxs), starting_step = 1, ) @@ -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 @@ -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...) @@ -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) diff --git a/src/visualizations.jl b/src/visualizations.jl index 33f9c073..70b445eb 100644 --- a/src/visualizations.jl +++ b/src/visualizations.jl @@ -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. @@ -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`. From 2cce06e0eb0876a90a8d4b34275fa15e0ecf5fd6 Mon Sep 17 00:00:00 2001 From: Datseris Date: Fri, 19 Sep 2025 13:45:35 +0100 Subject: [PATCH 2/3] fix name of interactive clicker --- docs/src/visualizations.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/visualizations.md b/docs/src/visualizations.md index 51fbdf2f..e7c95c35 100644 --- a/docs/src/visualizations.md +++ b/docs/src/visualizations.md @@ -344,10 +344,10 @@ interactive_poincaresos_scan(trs, j; linekw = (transparency = true,)) ## Interactive 2D dynamical system ```@docs -interactive_clicker +interactive_2d_clicker ``` -The `interactive_clicker` function can be used to spin up a GUI +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 @@ -363,5 +363,5 @@ projection = [1, 2] complete_state = [0.0] projected_ds = ProjectedDynamicalSystem(lorenz, projection, complete_state) -interactive_clicker(projected_ds; tfinal = (10.0, 150.0)) +interactive_2d_clicker(projected_ds; tfinal = (10.0, 150.0)) ``` From ae980bab2f0ee862a3da25bfebdd49e934cb223c Mon Sep 17 00:00:00 2001 From: Datseris Date: Fri, 19 Sep 2025 16:21:54 +0100 Subject: [PATCH 3/3] fix duplicate reference --- docs/src/visualizations.md | 40 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/docs/src/visualizations.md b/docs/src/visualizations.md index e7c95c35..d2069991 100644 --- a/docs/src/visualizations.md +++ b/docs/src/visualizations.md @@ -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 @@ -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_2d_clicker -``` - -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 = [0.0] -projected_ds = ProjectedDynamicalSystem(lorenz, projection, complete_state) - -interactive_2d_clicker(projected_ds; tfinal = (10.0, 150.0)) -```