Skip to content

Commit eaedbb2

Browse files
authored
Merge pull request #192 from VirtualPlantLab/graph-visualization
Add dependency graph visualizer and editor
2 parents 8e601d5 + 17f4737 commit eaedbb2

48 files changed

Lines changed: 13111 additions & 18 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/Benchmarks.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ permissions:
77
pull-requests: write
88
jobs:
99
bench:
10-
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{
11-
github.event_name }}
10+
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ github.event_name }}
1211
runs-on: ${{ matrix.os }}
1312
timeout-minutes: 60
1413
strategy:
@@ -18,11 +17,9 @@ jobs:
1817
- "1"
1918
os:
2019
- ubuntu-latest
21-
arch:
22-
- x64
2320
steps:
2421
- uses: MilesCranmer/AirspeedVelocity.jl@action-v1
2522
with:
2623
julia-version: ${{ matrix.version }}
2724
bench-on: ${{ github.event.pull_request.head.sha }}
28-
extra-pkgs: https://github.com/PalmStudio/XPalm.jl,https://github.com/VEZY/PlantBiophysics.jl
25+
extra-pkgs: https://github.com/PalmStudio/XPalm.jl,https://github.com/VEZY/PlantBiophysics.jl

.github/workflows/CI.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,59 @@ jobs:
7575
using PlantSimEngine
7676
DocMeta.setdocmeta!(PlantSimEngine, :DocTestSetup, :(using PlantSimEngine); recursive=true)
7777
doctest(PlantSimEngine)
78+
graph-editor-e2e:
79+
name: Graph editor E2E
80+
runs-on: ubuntu-latest
81+
timeout-minutes: 30
82+
permissions:
83+
actions: write
84+
contents: read
85+
steps:
86+
- uses: actions/checkout@v6
87+
- uses: julia-actions/setup-julia@v3
88+
with:
89+
version: "1"
90+
- uses: julia-actions/cache@v3
91+
- name: Configure test environment
92+
shell: julia --project=test --color=yes {0}
93+
run: |
94+
using Pkg
95+
Pkg.develop(PackageSpec(path=pwd()))
96+
Pkg.instantiate()
97+
- uses: actions/setup-node@v4
98+
with:
99+
node-version: "22"
100+
cache: npm
101+
cache-dependency-path: frontend/package-lock.json
102+
- name: Install frontend dependencies
103+
working-directory: frontend
104+
run: npm ci
105+
- name: Run frontend unit tests
106+
working-directory: frontend
107+
run: npm test
108+
- name: Typecheck graph editor frontend
109+
working-directory: frontend
110+
run: npm run typecheck
111+
- name: Build graph editor frontend
112+
working-directory: frontend
113+
run: npm run build
114+
- name: Check committed graph editor assets
115+
run: |
116+
git diff --exit-code -- frontend/dist || {
117+
echo "frontend/dist is stale. Run npm run build in frontend/ and commit the rebuilt assets.";
118+
exit 1;
119+
}
120+
- name: Install Playwright browser
121+
working-directory: frontend
122+
run: npx playwright install --with-deps chromium
123+
- name: Run graph editor E2E tests
124+
working-directory: frontend
125+
run: npm run test:e2e
126+
- name: Upload Playwright artifacts
127+
if: failure()
128+
uses: actions/upload-artifact@v4
129+
with:
130+
name: graph-editor-playwright-artifacts
131+
path: |
132+
frontend/playwright-report/
133+
frontend/test-results/

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ docs/Manifest.toml
77
test/Manifest.toml
88
docs/build/
99
benchmark/Manifest.toml
10-
frontend
10+
frontend/node_modules/
11+
docs/src/www/simple_dependency_graph.html

Project.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,37 @@ DataAPI = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
1010
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
1111
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
1212
FLoops = "cc61a311-1640-44b5-9fba-1b764f453329"
13+
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
14+
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
1315
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
1416
MultiScaleTreeGraph = "dd4a991b-8a45-4075-bede-262ee62d5583"
1517
PlantMeteo = "4630fe09-e0fb-4da5-a846-781cb73437b6"
18+
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1619
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
1720
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
1821
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
1922
Term = "22787eb5-b846-44ae-b979-8e399b8463ab"
2023

24+
[weakdeps]
25+
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
26+
27+
[extensions]
28+
PlantSimEngineGraphEditorExt = "HTTP"
29+
2130
[compat]
2231
AbstractTrees = "0.4"
2332
CSV = "0.10"
2433
DataAPI = "1.15"
2534
DataFrames = "1"
2635
Dates = "1.10"
2736
FLoops = "0.2"
37+
HTTP = "1"
38+
InteractiveUtils = "1.10"
39+
JSON = "1"
2840
Markdown = "1.10"
2941
MultiScaleTreeGraph = "0.15.1"
3042
PlantMeteo = "0.8.2"
43+
Random = "1.10"
3144
SHA = "0.7.0"
3245
Statistics = "1.10"
3346
Tables = "1"

docs/make.jl

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
#using Pkg
22
#Pkg.develop("PlantSimEngine")
33
using PlantSimEngine
4+
using PlantSimEngine.Examples
45
using PlantMeteo
56
using DataFrames, CSV
67
using Documenter
78
using CairoMakie
89

910
DocMeta.setdocmeta!(PlantSimEngine, :DocTestSetup, :(using PlantSimEngine, PlantMeteo, DataFrames, CSV, CairoMakie); recursive=true)
1011

12+
function build_graph_viewer_example()
13+
mapping = ModelMapping(
14+
ToyDegreeDaysCumulModel(),
15+
ToyLAIModel(),
16+
Beer(0.5),
17+
)
18+
path = joinpath(@__DIR__, "src", "www", "simple_dependency_graph.html")
19+
write_graph_view(path, mapping)
20+
return nothing
21+
end
22+
23+
build_graph_viewer_example()
24+
1125
makedocs(;
1226
modules=[PlantSimEngine],
1327
authors="Rémi Vezy <VEZY@users.noreply.github.com> and contributors",
@@ -30,10 +44,11 @@ makedocs(;
3044
"Key Concepts" => "./prerequisites/key_concepts.md",
3145
"Julia language basics" => "./prerequisites/julia_basics.md",
3246
],
33-
"Step by step - Single-scale simulations" => [
34-
"Detailed first simulation" => "./step_by_step/detailed_first_example.md",
35-
"Coupling" => "./step_by_step/simple_model_coupling.md",
47+
"Getting Started" => [
48+
"First simulation" => "./step_by_step/detailed_first_example.md",
49+
"Model Coupling" => "./step_by_step/simple_model_coupling.md",
3650
"Model Switching" => "./step_by_step/model_switching.md",
51+
"Graph visualization and editing" => "./step_by_step/graph_visualization_editor.md",
3752
"Quick examples" => "./step_by_step/quick_and_dirty_examples.md",
3853
"Implementing a process" => "./step_by_step/implement_a_process.md",
3954
"Implementing a model" => "./step_by_step/implement_a_model.md",

docs/src/developers.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ PlantSimEngine currently has three main local environments:
2626
- `docs/` for the Documenter build;
2727
- `benchmark/` for benchmark scripts used to compare performance locally.
2828

29+
The graph viewer/editor also has a small frontend workspace in `frontend/`. It
30+
is a Vite/React application that is compiled into `frontend/dist/` and then
31+
embedded by the Julia static viewer and graph editor extension.
32+
2933
## Running checks locally
3034

3135
### Main test suite
@@ -51,6 +55,66 @@ The docs environment includes the extra packages needed for examples and API
5155
documentation, such as `Documenter`, `CairoMakie`, `PlantMeteo`, and
5256
`MultiScaleTreeGraph`.
5357

58+
### Graph viewer frontend
59+
60+
The graph viewer and editor UI lives in `frontend/`. Use Node 22 or newer, then
61+
install the JavaScript dependencies from the repository root with:
62+
63+
```bash
64+
cd frontend
65+
npm ci
66+
```
67+
68+
For local development, run the Vite server:
69+
70+
```bash
71+
npm run dev
72+
```
73+
74+
This is useful for frontend-only iteration. The Julia package, however, serves
75+
the compiled assets from `frontend/dist/`, so rebuild the bundle before testing
76+
the Julia viewer/editor or before committing frontend changes:
77+
78+
```bash
79+
npm run build
80+
```
81+
82+
`frontend/dist/` is intentionally committed because registered Julia packages
83+
need the browser assets without requiring users to run a Node build step.
84+
85+
Run the lightweight frontend checks with:
86+
87+
```bash
88+
npm run typecheck
89+
npm test
90+
```
91+
92+
The end-to-end tests use Playwright and start a real Julia graph editor session.
93+
Install the Chromium browser once, then run the suite:
94+
95+
```bash
96+
npx playwright install --with-deps chromium
97+
npm run test:e2e
98+
```
99+
100+
The E2E helper starts Julia with `julia --project=test --startup-file=no`, loads
101+
`PlantSimEngine`, `PlantSimEngine.Examples`, and `HTTP`, then drives the browser
102+
against the local editor URL. If you already have an editor session running and
103+
want Playwright to use it, set `PSE_GRAPH_EDITOR_URL` to the full session URL,
104+
including the `token` query parameter.
105+
106+
After changing the viewer UI, rebuild the docs to verify the static embedded
107+
viewer too:
108+
109+
```bash
110+
cd ..
111+
julia --project=docs docs/make.jl
112+
```
113+
114+
The docs build writes `docs/src/www/simple_dependency_graph.html` as an
115+
intermediate generated asset and copies it into `docs/build/`; that source-side
116+
HTML file is ignored by git.
117+
54118
### Benchmarks
55119

56120
Benchmark scripts live in `benchmark/`. They are useful when a change may alter

docs/src/index.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ Depth = 5
6262

6363
**Intuitive Multi-Scale Support:** The framework naturally handles models operating at different scales—from organelle to ecosystem—connecting them with minimal effort and maintaining consistency across scales.
6464

65+
Model coupling can be done in Julia scripts or interactively in the graph view (or both):
66+
67+
```@raw html
68+
<iframe
69+
src="www/simple_dependency_graph.html"
70+
style="width: 100%; height: 500px; border: 1px solid #d8cfc2; border-radius: 8px; background: #f7f0e7;"
71+
title="PlantSimEngine dependency graph example"
72+
></iframe>
73+
```
74+
6575
### Flexibility with Precision Control
6676

6777
**Effortless Model Switching:** Researchers can switch between different component models using a simple syntax without rewriting the underlying model code. This enables rapid comparison between different hypotheses and model versions, accelerating the scientific discovery process.
@@ -74,6 +84,7 @@ Depth = 5
7484

7585
## Batteries included
7686

87+
- **Interactive graph editor**: Compose your model by interactively adding sub-models in a graph editor, and let the framework handle the coupling and execution.
7788
- **Automated Management**: Seamlessly handle inputs, outputs, time-steps, objects, and dependency resolution.
7889
- **Iterative Development**: Fast and interactive prototyping of models with built-in constraints to avoid errors and sensible defaults to streamline the model writing process.
7990
- **Control Your Degrees of Freedom**: Fix variables to constant values or force to observations, use simpler models for specific processes to reduce complexity.

0 commit comments

Comments
 (0)