flowchart LR A[modellen/lhm_coupled] -->|dvc repro run_lhm_coupled| R[runs/lhm_coupled] R -->|dvc repro export_webmap| B[webmap/lhm_coupled] B -->|pixi run publish-webmap| C[MinIO doc-image/webmap/lhm_coupled] C --> D[Model viewer page]
Model viewer
The Model viewer shows the input and results of the coupled LHM model (lhm_coupled) on a web map. It is a static web app: the docs site serves only the JavaScript, and the browser reads the model data directly from MinIO.
All local paths are relative to data/Rijkswaterstaat.
Updating the published data
Run the model with the
run_lhm_coupledDVC stage. It writesruns/lhm_coupled/lhm_coupled.toml, which reads the input ofmodellen/lhm_coupled, and the results next to it. For now this runs 1 year with a looser solver tolerance, seescripts/run_lhm_coupled.py. This takes many hours, so normally pull the cached results instead:pixi run dvc pull run_lhm_coupledExport the model to web-friendly files with the
export_webmapDVC stage, which takes about 10 minutes:pixi run dvc repro --pull --single-item export_webmapThis writes
data/Rijkswaterstaat/webmap/lhm_coupled, seeribasim_nl.webmapfor details:File Content nodes.parquetNode table with all attributes and lon/lat links.parquetLink table with all attributes and simplified geometry basin_area.pmtilesBasin / area polygons as vector tiles waterboards.geojsonSimplified water board boundaries tables/*.parquetAll other input tables, including those in NetCDF, sorted by node_idresults/*_by_id.parquetBasin and flow results sorted by id, for the time series charts results/*_by_time.parquetBasin level and storage, and flow rate, ordered by time step, for coloring the map manifest.jsonList of the files above with their content hash and size, and the color scale of each result variable Results are only exported if the model’s
resultsdirectory exists.Push the outputs and commit the updated
dvc.lock, see DVC:pixi run dvc push run_lhm_coupled export_webmapUpload the files to the anonymously readable
doc-image/webmap/lhm_coupled/prefix on MinIO. This needs credentials with write access in.env.pixi run publish-webmapUnchanged files are skipped, and
manifest.jsonis uploaded last, so visitors never see a manifest pointing to files that are not uploaded yet. Files that are no longer in the manifest are listed but not deleted.
The docs do not need to be rebuilt: the viewer always reads the latest manifest.json.
Viewing local models
The viewer can also show any local model, without publishing it:
pixi run viewer data/Rijkswaterstaat/modellen/hws_2025_10_1/hws.tomlThis exports the model with ribasim_nl.webmap to .cache/viewer, serves it with the viewer on http://localhost:8000, and opens it in a web browser. The export is reused as long as the model, its results and the export code are unchanged, so only the first run takes long; about 10 minutes for the coupled LHM model with results. Results are shown if the model’s results directory exists. Use --port to serve on another port, and --no-browser to not open a browser.
Comparing models
To review a pull request that changes a model, view only the differences from another version of the model. Usually that is the same model at another git revision, like main:
pixi run viewer data/Rijkswaterstaat/runs/lhm_coupled/lhm_coupled.toml --base origin/main--base takes a git revision or the TOML of another model. The model at a revision is read with DVC, from the DVC cache or the DVC remote, into .cache/viewer/revisions. Add --rev to also take the viewed model from a git revision instead of the working tree, for instance --rev HEAD --base origin/main. Fetch first to compare with the latest origin/main.
Nodes are matched by id, and links by their from and to node, since links get renumbered, see ribasim_nl.webmap_diff. A node or link in both models is changed if its geometry, an attribute, its rows in an input table, or its Basin / area differ. The map shows only the added, removed and changed features, in the colors of their status: green, orange and purple, on a grey base map. When zoomed out, the status rings around changed nodes become small dots. Removed and changed Basin / areas of the old model are drawn as dashed outlines. Turn on Unchanged in the layer list to show the other features faintly, for context.
If both models have results, the Basin levels and flow rates are compared too. Basins and flow links whose results differ more than a tolerance are also shown, in shades of grey by the largest difference. Differences of up to 1 mm in level, and of up to 1 L/s plus 1% in flow rate, are ignored as solver noise.
The Differences box counts the differences by status and by what changed, for instance Basin / state or geometry. Uncheck a status or a change to hide those features from the map, for instance to look past the many changed initial states. It also lists the changed TOML settings, all differing features, and the features whose results differ, largest first; click one to zoom to it. The panel of a changed feature lists what changed, shows the old value of changed attributes struck through, and shows both versions of changed tables. The result charts show the old model as dashed lines in a lighter tint.
Developing the viewer
The viewer lives in viewer/ and is written in TypeScript, built with Vite. It uses MapLibre GL JS for the basemap and the Basin / area tiles, deck.gl to draw the nodes and links, and hyparquet to read Parquet files with HTTP range requests.
Start a development server that serves your local export_webmap output, and open http://localhost:5173:
pixi run viewer-devChanges to the TypeScript code reload the page automatically. pixi run viewer-build checks types and builds the viewer into docs/viewer-app. pixi run docs and pixi run docs-render run it before rendering the docs. Add ?data=<url> to the viewer page URL to load the data from another location, for instance ?data=http://localhost:5173/ to use the development server. Only the default MinIO host, the docs site itself and localhost are accepted.