Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ DataAPI = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
FLoops = "cc61a311-1640-44b5-9fba-1b764f453329"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
MultiScaleTreeGraph = "dd4a991b-8a45-4075-bede-262ee62d5583"
PlantMeteo = "4630fe09-e0fb-4da5-a846-781cb73437b6"
Expand All @@ -18,13 +20,22 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
Term = "22787eb5-b846-44ae-b979-8e399b8463ab"

[weakdeps]
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"

[extensions]
PlantSimEngineGraphEditorExt = "HTTP"

[compat]
AbstractTrees = "0.4"
CSV = "0.10"
DataAPI = "1.15"
DataFrames = "1"
Dates = "1.10"
FLoops = "0.2"
HTTP = "1"
InteractiveUtils = "1.10"
JSON = "1"
Markdown = "1.10"
MultiScaleTreeGraph = "0.15.1"
PlantMeteo = "0.8.2"
Expand Down
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ makedocs(;
"Detailed first simulation" => "./step_by_step/detailed_first_example.md",
"Coupling" => "./step_by_step/simple_model_coupling.md",
"Model Switching" => "./step_by_step/model_switching.md",
"Graph visualization and editing" => "./step_by_step/graph_visualization_editor.md",
"Quick examples" => "./step_by_step/quick_and_dirty_examples.md",
"Implementing a process" => "./step_by_step/implement_a_process.md",
"Implementing a model" => "./step_by_step/implement_a_model.md",
Expand Down
86 changes: 86 additions & 0 deletions docs/src/step_by_step/graph_visualization_editor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Graph visualization and editing

`PlantSimEngine` can export a dependency graph view from a [`ModelMapping`](@ref). The static viewer is available from the core package and does not require any web server dependency.

```julia
using PlantSimEngine
using PlantSimEngine.Examples

mapping = ModelMapping(
ToyLAIModel(),
Beer(0.5);
status=(TT_cu=1.0:200.0,),
)

write_graph_view("dependency_graph.html", mapping)
```

The same serialization path is used by the interactive editor. The editor is implemented as a Julia package extension, so the HTTP/WebSocket stack is loaded only when [`HTTP.jl`](https://github.com/JuliaWeb/HTTP.jl) is available and loaded in the active session.

```julia
using PlantSimEngine
using PlantSimEngine.Examples
using HTTP

mapping = ModelMapping(
ToyLAIModel(),
Beer(0.5);
status=(TT_cu=1.0:200.0,),
)

session = edit_graph(mapping)
session.url
session
```

To start from a blank graph and build a mapping from scratch, omit the mapping:

```julia
session = edit_graph()
```

By default, `edit_graph` opens `session.url` in the system default browser. Pass `open_browser=false` to keep the session headless, for example in scripts or tests:

```julia
session = edit_graph(mapping; open_browser=false)
```

The browser sends edit commands to Julia over a WebSocket. Julia remains the source of truth: it applies the edit, rebuilds the [`ModelMapping`](@ref), recompiles graph diagnostics, and sends the updated graph back to the browser.

To stop the HTTP/WebSocket session, run:

```julia
close(session)
```

Use [`current_mapping`](@ref) to recover the latest mapping from the session:

```julia
edited_mapping = current_mapping(session)
close(session)
```

The web editor also exposes a dedicated "Mapping code" panel. It shows the current [`ModelMapping`](@ref) as Julia code, and can write that code to a `.jl` file so it can be copied/pasted or reused in scripts. The generated file is intentionally plain Julia: it imports the packages needed by the selected models and defines a top-level `mapping` variable:

```julia
using PlantSimEngine
using PlantSimEngine.Examples

mapping = ModelMapping(
# ...
)
```

After writing a file once, every successful edit, undo, redo, or recent-file load automatically rewrites that same file. The session also keeps a recovery autosave in the temporary directory. The top-left "Open" button can reopen a mapping script from a file path or from the recent mapping list. Use git or another version-control system for mapping scripts that matter for a simulation workflow.

The editor extension currently supports the same edit operations as the Julia API:

- add, remove, and replace a model at a scale;
- update an existing model's parameter values, scale, or rate from the inspector;
- keep the model default rate, or set a custom `ClockSpec(dt, phase)` when adding a model;
- set a mapped input variable, either from the inspector or by drawing a connection from an output port to an input port;
- map a scalar source value or a vector of values from one or several source scales;
- mark or unmark a variable as [`PreviousTimeStep`](@ref);
- undo and redo edits inside the live session.

If `HTTP` is not loaded, `edit_graph(mapping)` throws an error explaining that the interactive editor requires `using HTTP`. Static graph visualization through [`write_graph_view`](@ref), `graph_view`, and [`graph_view_json`](@ref) remains available without loading `HTTP`.
Loading
Loading