Skip to content

Commit 2883a6b

Browse files
committed
update docs
1 parent 5b38d52 commit 2883a6b

File tree

2 files changed

+94
-67
lines changed

2 files changed

+94
-67
lines changed

docs/src/API.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,14 @@ save_parameters!
191191
ff_to_constraint
192192
Base.copy(::NetworkDynamics.ComponentModel)
193193
```
194+
195+
## NetworkDynamicsInspector API
196+
```@docs
197+
inspect
198+
dump_app_state
199+
set_sol!
200+
set_state!
201+
set_graphplot!
202+
set_timeseries!
203+
define_timeseries!
204+
```

docs/src/inspector.md

Lines changed: 83 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,99 +2,115 @@
22

33
Interactive solution inspection tool based on [WGLMakie](https://makie.org/website/) and [Bonito](https://github.com/SimonDanisch/Bonito.jl) are provided through the helper package `NetworkDynamicsInspector`.
44

5+
Firstoff, we need to define the system we want to interactively inspect.
56

6-
```@example ndi
7-
using NetworkDynamics
8-
using NetworkDynamicsInspector
9-
using NetworkDynamicsInspector: NetworkDynamicsInspector as NDI #hide
10-
using Electron # hide
11-
using OrdinaryDiffEqTsit5
12-
using Graphs
13-
14-
include(joinpath(pkgdir(NetworkDynamics), "test", "ComponentLibrary.jl"))
15-
function get_sol(;limit=1.0)
16-
g = SimpleGraph([0 1 1 0 1;
17-
1 0 1 1 0;
18-
1 1 0 1 0;
19-
0 1 1 0 1;
20-
1 0 0 1 0])
21-
vs = [Lib.swing_mtk() for _ in 1:5];
22-
set_default!(vs[1], :Pmech, -1)
23-
set_default!(vs[2], :Pmech, 1.5)
24-
set_default!(vs[3], :Pmech, -1)
25-
set_default!(vs[4], :Pmech, -1)
26-
set_default!(vs[5], :Pmech, 1.5)
27-
ls = [Lib.line_mtk() for _ in 1:7];
28-
nw = Network(g, vs, ls)
29-
sinit = NWState(nw)
30-
s0 = find_fixpoint(nw)
31-
set_defaults!(nw, s0)
32-
33-
# set_position!(vs[1], (0.0, 0.0))
34-
set_marker!(vs[1], :dtriangle)
35-
set_marker!(vs[2], :utriangle)
36-
set_marker!(vs[3], :dtriangle)
37-
set_marker!(vs[4], :dtriangle)
38-
set_marker!(vs[5], :utriangle)
39-
40-
cond = ComponentCondition([:P, :₋P, :srcθ], [:limit, :K]) do u, p, t
41-
abs(u[:P]) - p[:limit]
42-
end
43-
affect = ComponentAffect([],[:active]) do u, p, ctx
44-
@info "Trip line $(ctx.eidx) between $(ctx.src) and $(ctx.dst) at t=$(ctx.t)"
45-
p[:active] = 0
46-
end
47-
cb = ContinousComponentCallback(cond, affect)
48-
set_callback!.(ls, Ref(cb))
7+
!!! details "Define some network, simulate it and get a solution object"
8+
```@example ndi
9+
using NetworkDynamics
10+
using NetworkDynamicsInspector
11+
using NetworkDynamicsInspector: NetworkDynamicsInspector as NDI #hide
12+
using Electron # hide
13+
using OrdinaryDiffEqTsit5
14+
using Graphs
4915

50-
tripfirst = PresetTimeComponentCallback(1.0, affect) # reuse the same affect
51-
add_callback!(nw[EIndex(5)], tripfirst)
16+
include(joinpath(pkgdir(NetworkDynamics), "test", "ComponentLibrary.jl"))
17+
function get_sol(;limit=1.0)
18+
g = SimpleGraph([0 1 1 0 1;
19+
1 0 1 1 0;
20+
1 1 0 1 0;
21+
0 1 1 0 1;
22+
1 0 0 1 0])
23+
vs = [Lib.swing_mtk() for _ in 1:5];
24+
set_default!(vs[1], :Pmech, -1)
25+
set_default!(vs[2], :Pmech, 1.5)
26+
set_default!(vs[3], :Pmech, -1)
27+
set_default!(vs[4], :Pmech, -1)
28+
set_default!(vs[5], :Pmech, 1.5)
29+
ls = [Lib.line_mtk() for _ in 1:7];
30+
nw = Network(g, vs, ls)
31+
sinit = NWState(nw)
32+
s0 = find_fixpoint(nw)
33+
set_defaults!(nw, s0)
5234

53-
nwcb = NetworkDynamics.get_callbacks(nw);
54-
s0 = NWState(nw)
55-
s0.p.e[:, :limit] .= limit
35+
# set_position!(vs[1], (0.0, 0.0))
36+
set_marker!(vs[1], :dtriangle)
37+
set_marker!(vs[2], :utriangle)
38+
set_marker!(vs[3], :dtriangle)
39+
set_marker!(vs[4], :dtriangle)
40+
set_marker!(vs[5], :utriangle)
5641

57-
prob = ODEProblem(nw, uflat(s0), (0,6), copy(pflat(s0)), callback=nwcb)
58-
sol = solve(prob, Tsit5())
59-
end
42+
cond = ComponentCondition([:P, :₋P, :srcθ], [:limit, :K]) do u, p, t
43+
abs(u[:P]) - p[:limit]
44+
end
45+
affect = ComponentAffect([],[:active]) do u, p, ctx
46+
@info "Trip line $(ctx.eidx) between $(ctx.src) and $(ctx.dst) at t=$(ctx.t)"
47+
p[:active] = 0
48+
end
49+
cb = ContinousComponentCallback(cond, affect)
50+
set_callback!.(ls, Ref(cb))
6051

61-
sol = get_sol()
62-
sleep(1) # hide
63-
inspect(sol; restart=false, reset=true)
52+
tripfirst = PresetTimeComponentCallback(1.0, affect) # reuse the same affect
53+
add_callback!(nw[EIndex(5)], tripfirst)
54+
55+
nwcb = NetworkDynamics.get_callbacks(nw);
56+
s0 = NWState(nw)
57+
s0.p.e[:, :limit] .= limit
58+
59+
prob = ODEProblem(nw, uflat(s0), (0,6), copy(pflat(s0)), callback=nwcb)
60+
sol = solve(prob, Tsit5())
61+
end
62+
63+
sol = get_sol()
64+
```
65+
66+
No that we have and `ODESolution` `sol`, we can call [`inspect`](@ref) to open the inspector gui. In the docstring you can find several options to chose how the app is displayed.
67+
68+
```@example ndi
69+
inspect(sol; reset=true)
6470
sleep(1) # hide
65-
define_timeseries!([
66-
(; selcomp=[EIndex(i) for i in 1:7], states=[:P])
67-
])
71+
define_timeseries!([ # hide
72+
(; selcomp=[EIndex(i) for i in 1:7], states=[:P]) # hide
73+
]) # hide
74+
sleep(3) # hide
6875
NDI.save_electron_screenshot("screenshot.png") #hide
76+
```
77+
![screenshot](screenshot.png)
6978

7079

71-
set_state!(; t=2.0) #hide
72-
sleep(1) # hide
80+
## Programmatric Acces and GUI State manipulation
81+
Internally, the `NetworkDynamicsInspector` holds a global reference to an object `AppState`. This AppState reflects the changes the user made to the GUI and can be also altered programmaticially.
82+
83+
See [NetworkDynamicsInspector API](@ref) for a list of all available function.
84+
As a good starting point, there is a function [`dump_app_state`](@ref)
85+
which helps you to recreate the GUI state which was previously adjusted by hand.
86+
87+
Lets say we've adjuste the appstate to include another timeseries plot for the node states.
88+
89+
```@example ndi
90+
set_state!(; t=1.75) #hide
7391
define_timeseries!([ #hide
7492
(; selcomp=[VIndex(i) for i in 1:5], states=[:θ, :ω]) #hide
7593
(; selcomp=[EIndex(i) for i in 1:7], states=[:P]) #hide
7694
]) #hide
77-
sleep(1) #hide
78-
95+
sleep(3) #hide
7996
nothing #hide
8097
```
81-
![screenshot](screenshot.png)
8298

83-
## Programmatric Acces and GUI State manipulation
99+
We can dump the code which helps us to recreate the app state:
84100
```@example ndi
85101
dump_app_state()
86102
```
87103

104+
Now we can use this code to recreate the app state even though we've reseted it.
88105
```@example ndi
89106
buf = IOBuffer() #hide
90107
dump_app_state(buf) #hide
91108
code = String(take!(buf)) #hide
92-
sleep(1) #hide
93-
inspect(sol; reset=true) #hide
109+
inspect(sol; reset=true)
94110
sleep(1) #hide
95111
eval(Meta.parse("begin;"*code*"end;")) #hide
96-
sleep(1) #hide
112+
sleep(3) #hide
97113
NDI.save_electron_screenshot("screenshot2.png") #hide
98-
nothing #hide
114+
"copy-paste and execute code returned by `dump_app_state` here"
99115
```
100116
![screenshot](screenshot2.png)

0 commit comments

Comments
 (0)