Skip to content

Commit f9e5450

Browse files
committed
attempt screenshot in docs
1 parent 25ece66 commit f9e5450

File tree

5 files changed

+90
-5
lines changed

5 files changed

+90
-5
lines changed

.github/workflows/Documentation.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ jobs:
1919
contents: write
2020
statuses: write
2121
steps:
22+
- name: Install xvfb
23+
run: |
24+
sudo apt update
25+
sudo apt install -y xvfb mesa-utils mesa-vulkan-drivers dbus x11-xserver-utils
2226
- uses: actions/checkout@v4
2327
- uses: julia-actions/setup-julia@v2
2428
with:
@@ -35,6 +39,11 @@ jobs:
3539
env:
3640
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3741
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
42+
LIBGL_ALWAYS_SOFTWARE: "1"
43+
MESA_GL_VERSION_OVERRIDE: "4.5"
44+
MESA_GLSL_VERSION_OVERRIDE: "450"
45+
with:
46+
prefix: xvfb-run --auto-servernum
3847
- name: Run doctests
3948
shell: julia --project=docs --color=yes {0}
4049
run: |

NetworkDynamicsInspector/src/serving.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ function serve_app(display, app)
3434
end
3535
end
3636
close_display(::Nothing; kwargs...) = nothing
37+
close_display() = close_display(CURRENT_DISPLAY[]; strict=true)
3738

3839
####
3940
#### Server Display
@@ -132,8 +133,9 @@ function get_electron_app end
132133
function get_electron_window end
133134

134135
function save_electron_screenshot(path=joinpath(@__DIR__, "screenshot.png"))
136+
path = isabspath(path) ? path : joinpath(pwd(), path)
135137
has_electron_window()|| error("No Electron window exists!")
136-
winid = NDI.get_electron_window().id
138+
winid = get_electron_window().id
137139
js = """
138140
let win = BrowserWindow.fromId($winid)
139141
win.webContents.capturePage().then(image => {
@@ -142,6 +144,7 @@ function save_electron_screenshot(path=joinpath(@__DIR__, "screenshot.png"))
142144
console.log('Screenshot saved to ', screenshotPath);
143145
});
144146
"""
145-
d = run(NDI.get_electron_app(), js)
146-
path
147+
wait_for()
148+
d = run(get_electron_app(), js)
149+
nothing
147150
end

docs/Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
77
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
88
DocumenterInterLinks = "d12716ef-a0f6-4df4-a9f1-a5a34e75c656"
99
DynamicQuantities = "06fc5a27-2a28-4c7c-a15d-362465fb6821"
10+
Electron = "a1bb12fb-d4d1-54b4-b10a-ee7951ef7ad3"
1011
GraphMakie = "1ecd5474-83a3-4783-bb4f-06765db800d2"
1112
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
1213
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
1314
LinearInterpolations = "b20c7882-2490-4592-a606-fbbfe9e745e8"
1415
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
1516
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
1617
NetworkDynamics = "22e9dc34-2a0d-11e9-0de0-8588d035468b"
18+
NetworkDynamicsInspector = "0a4713f2-d58f-43f2-b63b-1b5d5ee4e65a"
1719
OrdinaryDiffEqNonlinearSolve = "127b3ac7-2247-4354-8eb6-78cf4e7c58e8"
1820
OrdinaryDiffEqRosenbrock = "43230ef6-c299-4910-a778-202eb28ce4ce"
1921
OrdinaryDiffEqSDIRK = "2d112036-d095-4a1e-ab9a-08536f3ecdbf"
@@ -30,6 +32,7 @@ SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5"
3032

3133
[sources]
3234
NetworkDynamics = {path = ".."}
35+
NetworkDynamicsInspector = {path = "../NetworkDynamicsInspector"}
3336

3437
[compat]
3538
CairoMakie = "0.13.1"

docs/make.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
ENV["GKSwstype"] = "100" # needed for plotting with GitHub Actions and GR (?)
1+
# ENV["GKSwstype"] = "100" # needed for plotting with GitHub Actions and GR (?)
22

33
using Documenter
44
using NetworkDynamics
5+
using NetworkDynamicsInspector
56
using SciMLBase
67
using Literate
78
using ModelingToolkit
@@ -29,7 +30,7 @@ mtkext = Base.get_extension(NetworkDynamics, :MTKExt)
2930
kwargs = (;
3031
root=joinpath(pkgdir(NetworkDynamics), "docs"),
3132
sitename="NetworkDynamics",
32-
modules=[NetworkDynamics, mtkext],
33+
modules=[NetworkDynamics, mtkext, NetworkDynamicsInspector],
3334
linkcheck=true, # checks if external links resolve
3435
pagesonly=true,
3536
plugins=[links],
@@ -44,6 +45,7 @@ kwargs = (;
4445
"callbacks.md",
4546
"mtk_integration.md",
4647
"external_inputs.md",
48+
"inspector.md",
4749
],
4850
"API.md",
4951
"Tutorials" => [

docs/src/inspector.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# NetworkDynamicsInspector
2+
3+
```@example ndi
4+
using NetworkDynamics
5+
using NetworkDynamicsInspector
6+
using NetworkDynamicsInspector: NetworkDynamicsInspector as NDI #hide
7+
using Electron # hide
8+
using OrdinaryDiffEqTsit5
9+
using Graphs
10+
11+
include(joinpath(pkgdir(NetworkDynamics), "test", "ComponentLibrary.jl"))
12+
function get_sol(;limit=1.0)
13+
g = SimpleGraph([0 1 1 0 1;
14+
1 0 1 1 0;
15+
1 1 0 1 0;
16+
0 1 1 0 1;
17+
1 0 0 1 0])
18+
vs = [Lib.swing_mtk() for _ in 1:5];
19+
set_default!(vs[1], :Pmech, -1)
20+
set_default!(vs[2], :Pmech, 1.5)
21+
set_default!(vs[3], :Pmech, -1)
22+
set_default!(vs[4], :Pmech, -1)
23+
set_default!(vs[5], :Pmech, 1.5)
24+
ls = [Lib.line_mtk() for _ in 1:7];
25+
nw = Network(g, vs, ls)
26+
sinit = NWState(nw)
27+
s0 = find_fixpoint(nw)
28+
set_defaults!(nw, s0)
29+
30+
# set_position!(vs[1], (0.0, 0.0))
31+
set_marker!(vs[1], :dtriangle)
32+
set_marker!(vs[2], :utriangle)
33+
set_marker!(vs[3], :dtriangle)
34+
set_marker!(vs[4], :dtriangle)
35+
set_marker!(vs[5], :utriangle)
36+
37+
cond = ComponentCondition([:P, :₋P, :srcθ], [:limit, :K]) do u, p, t
38+
abs(u[:P]) - p[:limit]
39+
end
40+
affect = ComponentAffect([],[:active]) do u, p, ctx
41+
@info "Trip line $(ctx.eidx) between $(ctx.src) and $(ctx.dst) at t=$(ctx.t)"
42+
p[:active] = 0
43+
end
44+
cb = ContinousComponentCallback(cond, affect)
45+
set_callback!.(ls, Ref(cb))
46+
47+
tripfirst = PresetTimeComponentCallback(1.0, affect) # reuse the same affect
48+
add_callback!(nw[EIndex(5)], tripfirst)
49+
50+
nwcb = NetworkDynamics.get_callbacks(nw);
51+
s0 = NWState(nw)
52+
s0.p.e[:, :limit] .= limit
53+
54+
prob = ODEProblem(nw, uflat(s0), (0,6), copy(pflat(s0)), callback=nwcb)
55+
sol = solve(prob, Tsit5())
56+
end
57+
58+
sol = get_sol()
59+
60+
61+
62+
NDI.CURRENT_DISPLAY[] = ElectronDisp(resolution=(1000,1000)) # hide
63+
@info "open gui"
64+
inspect(sol)
65+
NDI.save_electron_screenshot("screenshot.png")
66+
NDI.close_display()
67+
```
68+
![screenshot](screenshot.png)

0 commit comments

Comments
 (0)