Skip to content

Commit

Permalink
Add update-reset-step button and starting step kwarg to trajectory GUI (
Browse files Browse the repository at this point in the history
#231)

* add update reset step button and starting step kwarg

* bump version
  • Loading branch information
Datseris authored Apr 2, 2024
1 parent 32227e0 commit ed82d34
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 23 deletions.
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.3.5"
version = "3.3.6"

[deps]
Attractors = "f3fd9213-ca85-4dba-9dfd-7fc91308fec7"
Expand Down
23 changes: 18 additions & 5 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,
starting_step = 1,
)

if length(idxs) > dimension(ds)
Expand All @@ -48,7 +49,9 @@ function DynamicalSystems.interactive_trajectory(
)
# Set up layouting and add controls
if add_controls # Notice that `run` and `step` are already observables
reset, run, step, stepslider = _trajectory_plot_controls!(statespacelayout, statespace_axis)
reset, run, step, stepslider = _trajectory_plot_controls!(
statespacelayout, statespace_axis, starting_step
)
else
# So that we can leave the interactive UI code as is
reset = Observable(0); run = Observable(0); step = Observable(0); stepslider = Observable(1)
Expand Down Expand Up @@ -91,16 +94,26 @@ function DynamicalSystems.interactive_trajectory(
ds, paramlayout, parameter_sliders, parameter_names, current_parameters(ds)
)
update = Button(fig, label = "update", tellwidth = false, tellheight = true)
urs = Button(fig, label = "u.r.s.", tellwidth = false, tellheight = true)
resetp = Button(fig, label = "reset p", tellwidth = false, tellheight = true)
gl = paramlayout[2, :] = GridLayout()
gl[1,1] = update
gl[1,2] = resetp
gl[1,2] = urs
gl[1,3] = resetp
# what happens when the update button gets pressed
on(update.clicks) do clicks
for l in keys(slidervals)
v = slidervals[l][]
set_parameter!(dso, l, v)
end
end
# what happens when the u.r.s. button gets pressed
on(urs.clicks) do clicks
update.clicks[] = update.clicks[] + 1 # click update button
reset[] = reset[] + 1 # click reset button
step[] = step[] + 1 # click step button
end
# what happens when the reset p button gets pressed
on(resetp.clicks) do clicks
set_parameters!(pds, p0)
# Also **visually** reset sliders to initial parameters
Expand Down Expand Up @@ -190,15 +203,15 @@ function _init_trajectory_observables(pds, tail)
finalpoints = Observable([x[][end] for x in tailobs])
return tailobs, finalpoints
end
function _trajectory_plot_controls!(gl, statespace_axis)
function _trajectory_plot_controls!(gl, statespace_axis::Bool, starting_step)
position = statespace_axis ? [2,1] : [1,1]
controllayout = setindex!(gl, GridLayout(tellwidth = false, tellheight = statespace_axis), position...)
reset = Button(controllayout[1, 0]; label = "reset")
run = Button(controllayout[1, 1]; label = "run")
step = Button(controllayout[1, 2]; label = "step")
slider_vals = vcat(1:10, 100:100:1000)
slider_vals = unique(round.(Int, 10 .^ (range(0, 4; length = 1001))))
sg = SliderGrid(controllayout[1,3],
(label = "steps =", range = slider_vals, startvalue = 1),
(label = "steps =", range = slider_vals, startvalue = starting_step),
)
return reset.clicks, run.clicks, step.clicks, sg.sliders[1].value
end
Expand Down
43 changes: 26 additions & 17 deletions src/visualizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,53 @@ export interactive_trajectory, interactive_cobweb, interactive_orbitdiagram, sca
"""
interactive_trajectory_timeseries(ds::DynamicalSystem, fs, [, u0s]; kwargs...) → fig, dsobs
Create a Makie `Figure` that to visualize trajectories and timeseries of `ds`.
This `Figure` can also be used as an interactive GUI (requires `GLMakie`) to enable
Create a Makie `Figure` to visualize trajectories and timeseries of observables of `ds`.
This `Figure` can also be used as an interactive GUI to enable
interactive control over parameters and time evolution.
It can also be used to reate videos, as well as customized animations, see below.
It can also be used to create videos, as well as customized animations, see below.
`fs` is a `Vector` of "indices to observe", i.e., anything that can be given
to [`observe_state`](@ref). Each observation index will make a timeseries plot.
`u0s` is a `Vector` of initial conditions. Each is evolved with a unique color and displayed
both as a trajectory in state space and as an observed timeseries.
The given dynamical system is always cast into a `ParallelDynamicalSystem`.
The trajectories from the initial conditions in `u0s` (a vector of vectors)
are all evolved and visualized in parallel. By default
only the current state of the system is used.
## Return
Return the newly created figure `fig`
that may include interactivity-related buttons, and a `dsobs::DynamicalSystemObservable`
that facilities the creation of custom animations and/or interactive
Return `fig, dsobs::DynamicalSystemObservable`. `fig` is the created `Figure`.
`dsobs` facilities the creation of custom animations and/or interactive
applications, see the custom animations section below.
See also [`interactive_trajectory`](@ref).
## Interactivity and time stepping keywords
- `add_controls = true`: If `true`, below the main axis containing the trajectories
some controls for animating the trajectories live are added: run, pause, and how many
steps to evolve for per animation step. The plotted trajectories can always be evolved
_GUI functionality is possible when the plotting backend is `GLMakie`.
Do `using GLMakie; GLMakie.activate!()` to ensure this is the chosen backend._
- `add_controls = true`: If `true`, below the state space axis
some buttons for animating the trajectories live are added:
- `reset`: results the parallel trajectories to their initial conditions
- `run`: when clicked it evolves the trajectories forwards in time indefinitely.
click again to stop the evolution.
- `step`: when clicked it evolves the trajectories forwards in time for the
amount of steps chosen by the slider to its right.
The plotted trajectories can always be evolved
manually using the custom animations etup that we describe below; `add_controls` only
concerns the buttons and interactivity added to the created panel.
concerns the buttons and interactivity added to the created figure.
- `parameter_sliders = nothing`: If given, it must be a dictionary, mapping
parameter indices (any valid index that can be given to [`set_parameter!`](@ref))
to ranges of parameter values. Each combination
of index and range becomes a slider that can be interactively controlled to alter
a system parameter on the fly during time evolution. Note that all system parameters
can also be altered using the custom animation setup that we describe below;
`parameter_sliders` only conserns the buttons and interactivity added to the created panel.
to ranges of parameter values. Each combination of index and range becomes a slider
that can be interactively controlled to alter a system parameter on the fly during time
evolution. Below the parameter sliders, three buttons are added for GUI usage:
- `update`: when clicked the chosen parameter values are propagated into the system
- `u.r.s.`: when clicked it is equivalent with clicking in order: "update", "reset", "step".
- `reset p`: when clicked it resets
Parameters can also be altered using the custom animation setup that we describe below;
`parameter_sliders` only conserns the buttons and interactivity added to the created figure.
- `parameter_names = Dict(keys(ps) .=> string.(keys(ps)))`: Dictionary mapping parameter
keys to labels. Only used if `parameter_sliders` is given.
- `Δt`: Time step of time evolution. Defaults to 1 for discrete time,
Expand All @@ -50,6 +59,7 @@ See also [`interactive_trajectory`](@ref).
- `pause = nothing`: If given, it must be a real number. This number is given to the `sleep`
function, which is called between each plot update. Useful when time integration is
computationally inexpensive and animation proceeds too fast.
- `starting_step = 1`: the starting value of the "step" slider.
## Visualization keywords
Expand Down Expand Up @@ -101,7 +111,6 @@ are triggered by the interactive GUI buttons (the first two when the system is s
time, the last one when the parameters are updated). However, these observables,
and hence the corresponding plotted trajectories that are `map`ed from these observables,
can be updated via the formal API of `DynamicalSystem`:
```
step!(dsobs, n::Int = 1)
```
Expand Down

0 comments on commit ed82d34

Please sign in to comment.