Skip to content

Commit 23fd287

Browse files
committed
add methods for manipulating appstate
1 parent 91f67c5 commit 23fd287

File tree

1 file changed

+137
-2
lines changed

1 file changed

+137
-2
lines changed

NetworkDynamicsInspector/src/NetworkDynamicsInspector.jl

Lines changed: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ using ColorSchemes: ColorSchemes, ColorScheme
2525
using SciMLBase: SciMLBase
2626

2727
# defined based on the julia version
28-
using NetworkDynamics: AnnotatedIOBuffer, AnnotatedString
28+
using NetworkDynamics: AnnotatedIOBuffer, AnnotatedString, @styled_str
2929

3030
include("utils.jl")
3131

@@ -43,7 +43,8 @@ include("timeseries.jl")
4343

4444
const SymbolicCompIndex = Union{VIndex{Int,Nothing}, EIndex{Int,Nothing}}
4545

46-
export inspect
46+
export inspect, dump_app_state
47+
export set_sol!, set_state!, set_graphplot!, set_timeseries!, define_timeseries!
4748

4849
@kwdef struct GraphPlot
4950
nstate::Observable{Vector{Symbol}} = [:nothing]
@@ -243,6 +244,140 @@ function inspect(sol; restart=false, reset=false)
243244
nothing
244245
end
245246

247+
function appstate()
248+
isnothing(APPSTATE[]) && error("Uninitialized appstate. To initialize call `set_sol!(sol)` or `inspect(sol)`!")
249+
APPSTATE[]
250+
end
251+
252+
# helper constrcut to mark undefined keyword arguments
253+
struct NotSpecified end
254+
function set_maybe!(obs::Observable, val)
255+
if obs[] != val
256+
obs[] = val
257+
end
258+
end
259+
set_maybe!(obs::Observable, ::NotSpecified) = nothing
260+
261+
"""
262+
set_sol!(sol)
263+
264+
Set the solution of the current appstate to `sol`.
265+
"""
266+
function set_sol!(sol)
267+
if isnothing(APPSTATE[])
268+
APPSTATE[] = AppState(sol)
269+
else
270+
APPSTATE[].sol[] = sol
271+
end
272+
nothing
273+
end
274+
275+
"""
276+
set_state!(; sol, t, tmin, tmax)
277+
278+
Set the solution, current time and time limits of the current appstate.
279+
280+
To automaticially create commands see [`dump_app_state()`](@ref).
281+
"""
282+
function set_state!(; sol = NotSpecified(),
283+
t = NotSpecified(),
284+
tmin = NotSpecified(),
285+
tmax = NotSpecified())
286+
sol != NotSpecified() && set_sol!(sol)
287+
set_maybe!(appstate().t, t)
288+
set_maybe!(appstate().tmin, tmin)
289+
set_maybe!(appstate().tmax, tmax)
290+
nothing
291+
end
292+
293+
"""
294+
set_graphplot!(; nstate, estate, nstate_rel, estate_rel, ncolorrange, ecolorrange)
295+
296+
Set the properties of the graphplot of the current appstate.
297+
298+
To automaticially create commands see [`dump_app_state()`](@ref).
299+
"""
300+
function set_graphplot!(; nstate = NotSpecified(),
301+
estate = NotSpecified(),
302+
nstate_rel = NotSpecified(),
303+
estate_rel = NotSpecified(),
304+
ncolorrange = NotSpecified(),
305+
ecolorrange = NotSpecified())
306+
gp = appstate().graphplot
307+
set_maybe!(gp.nstate, nstate)
308+
set_maybe!(gp.estate, estate)
309+
set_maybe!(gp.nstate_rel, nstate_rel)
310+
set_maybe!(gp.estate_rel, estate_rel)
311+
set_maybe!(gp.ncolorrange, ncolorrange)
312+
set_maybe!(gp.ecolorrange, ecolorrange)
313+
nothing
314+
end
315+
316+
"""
317+
set_timeseries!(key; selcomp, states, rel)
318+
319+
Set properties of the timeseries plot with key `key`. See also [`define_timeseries!`](@ref).
320+
321+
To automaticially create commands see [`dump_app_state()`](@ref).
322+
"""
323+
function set_timeseries!(key; selcomp = NotSpecified(),
324+
states = NotSpecified(),
325+
rel = NotSpecified())
326+
if !haskey(appstate().tsplots, key)
327+
appstate().tsplots[key] = TimeseriesPlot()
328+
end
329+
tsplot = appstate().tsplots[key]
330+
set_maybe!(tsplot.selcomp, selcomp)
331+
set_maybe!(tsplot.states, states)
332+
set_maybe!(tsplot.rel, rel)
333+
nothing
334+
end
335+
336+
"""
337+
define_timeseries!(tsarray)
338+
339+
Defines timeseries, where `tsarray` is an array of timeseries keyword arguments
340+
(see [`set_timeseries!`](@ref)).
341+
342+
To automaticially create commands see [`dump_app_state()`](@ref).
343+
"""
344+
function define_timeseries!(tsarray)
345+
if length(tsarray) != length(appstate().tsplots[])
346+
@warn "Due to current limitations, you need to reload the page if the number of timeseries plots changes"
347+
empty!(appstate().tsplots[])
348+
tskeys = [gendomid("ts") for _ in tsarray]
349+
else
350+
tskeys = keys(appstate().tsplots[])
351+
end
352+
for (key, ts) in zip(tskeys, tsarray)
353+
set_timeseries!(key; pop!(tsargs)...)
354+
end
355+
nothing
356+
end
357+
358+
"""
359+
dump_app_state()
360+
361+
Generate a list of [`set_sol!`](@ref), [`set_state!`](@ref), [`set_graphplot!`](@ref) and [`define_timeseries!`](@ref)
362+
commands to recreate the current appstate.
363+
The intended usecase is to quickly recreate "starting points" for interactive exploration.
364+
"""
365+
function dump_app_state()
366+
appstate()
367+
println("To recreate the current state, run the following commands:\n")
368+
println(styled"set_sol!({red:sol}) # optional if after inspect(sol)")
369+
println("set_state!(; t=$(appstate().t[]), tmin=$(appstate().tmin[]), tmax=$(appstate().tmax[]))")
370+
gp = appstate().graphplot
371+
println("set_graphplot!(; nstate=$(gp.nstate[]), estate=$(gp.estate[]), nstate_rel=$(gp.nstate_rel[]), estate_rel=$(gp.estate_rel[]), ncolorrange=$(gp.ncolorrange[]), ecolorrange=$(gp.ecolorrange[]))")
372+
println("define_timeseries!([")
373+
for ts in values(appstate().tsplots[])
374+
selstr = replace(repr(ts.selcomp[]), r"^.*\["=>"[")
375+
println(" (; selcomp=$(selstr), states=$(ts.states[]), rel=$(ts.rel[])),")
376+
end
377+
println("])")
378+
nothing
379+
end
380+
246381
function apptheme()
247382
Theme(
248383
fontsize=10,

0 commit comments

Comments
 (0)