Skip to content

Add temporal Flow and Basin results to QGIS.#2208

Merged
evetion merged 5 commits into
mainfrom
feat/temporal-qgis
Apr 7, 2025
Merged

Add temporal Flow and Basin results to QGIS.#2208
evetion merged 5 commits into
mainfrom
feat/temporal-qgis

Conversation

@evetion

@evetion evetion commented Apr 4, 2025

Copy link
Copy Markdown
Member

And adds "show topology" button on the layer context menu.

Fixes #2178
Fixes #2171

This creates a new Results group in QGIS for each loaded model, and adds a BasinNode and FlowLink layer to it. These are duplicates of the Node and Link layer for the result data (and thus only keeping node_type=Basin, and link_type=flow).

Result arrow files (basin, flow and concentration) are read with pandas and indexed on time (concentration is widened first) and saved on the widget. Fields on the BasinNode and FlowLink are created to store the result variables. A specific time slice, by default the last, or by a signal from the temporal manager is then used to update these fields. The temporal manager is initialized based on the start/endtime and timestep from .toml file.

In effect you now have Node and Link tables with all result variables for a given timestep, meaning you're free to add symbology/labels as you would for any (static) layer.

The layer context menu is expanded to show a "Show topology" checkmark, which sets a layer variable, which in turn is used by the layer symbology to either show @geometry or make_line(start_point(@geometry), end_point( @geometry)).


For @Huite and @JoerivanEngelen, updating the (memory) layers on the fly, and not using QGIS to read arrow files is essential for performance. Further performance was gained by not iterating over the layer features and updating them, but by setting them directly based on the fid (order). Note that the memory copy does not use the same fids as our geopackage layers, and you can't control them. The last factor of performance was disabling the automatic undo functionality (or rather creating 1 undo, instead of one for each feature) when updating the layer.

@visr

visr commented Apr 4, 2025

Copy link
Copy Markdown
Member

This is very very nice. I like how it dynamically fills in the tables and things I tried like adding a label with the flow rate just seem to work:
image

Here I used format_number("flow_rate", 2) to avoid getting the full Float64 printed. Perhaps we should add something like this in the default style?

If I remove a model and load it in in the same QGIS session it seems the show topology context is getting added another time:

image

Also it seemed to only work for me on the results but not the Link layer?

Further the BasinNode symbology uses relative_error by default(last column); can that be level (first column)?

These other things are perhaps better as follow ups:

@visr

visr commented Apr 4, 2025

Copy link
Copy Markdown
Member

If I do "remove group" on the HWS model and then open it again I consistently get:

Traceback (most recent call last):
  File "C:\Users/visser_mn/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\ribasim_qgis\widgets\dataset_widget.py", line 620, in _update_arrow_layers
    self._update_arrow_layer(
  File "C:\Users/visser_mn/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\ribasim_qgis\widgets\dataset_widget.py", line 593, in _update_arrow_layer
    layer.startEditing()
RuntimeError: wrapped C/C++ object of type QgsVectorLayer has been deleted

@evetion

evetion commented Apr 4, 2025

Copy link
Copy Markdown
Member Author

Traceback (most recent call last):
File "C:\Users/visser_mn/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\ribasim_qgis\widgets\dataset_widget.py", line 620, in _update_arrow_layers
self._update_arrow_layer(
File "C:\Users/visser_mn/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\ribasim_qgis\widgets\dataset_widget.py", line 593, in _update_arrow_layer
layer.startEditing()
RuntimeError: wrapped C/C++ object of type QgsVectorLayer has been deleted

I've seen this before and refactored a large part of the signals because of it, but I think it only triggers once you got another error first?

Here I used format_number("flow_rate", 2) to avoid getting the full Float64 printed. Perhaps we should add something like this in the default style?

Sure, will add it. What do you suggest for Basin labels?

Also it seemed to only work for me on the results but not the Link layer?

Yes, it only sets a variable on the layer, the style has to use that variable. Will update the default style to do so as well.

If I remove a model and load it in in the same QGIS session it seems the show topology context is getting added another time:

Ouch, nice find. It's hijacking of the contextmenu signal, and it does so for the DatasetWidget (repeated for each dataset), that should probably be the Ribasim widget, or check for an existing widget.

Further the BasinNode symbology uses relative_error by default(last column); can that be level (first column)?

Sure, but that's hard to style consistently, would have to make an update symbology after arrow load for it, based on min/max or so.

@Huite

Huite commented Apr 4, 2025

Copy link
Copy Markdown
Contributor

Traceback (most recent call last):
File "C:\Users/visser_mn/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\ribasim_qgis\widgets\dataset_widget.py", line 620, in _update_arrow_layers
self._update_arrow_layer(
File "C:\Users/visser_mn/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\ribasim_qgis\widgets\dataset_widget.py", line 593, in _update_arrow_layer
layer.startEditing()
RuntimeError: wrapped C/C++ object of type QgsVectorLayer has been deleted

I've seen this before and refactored a large part of the signals because of it, but I think it only triggers once you got another error first?

My guess here is that arrow layer in Python hasn't been updated after group deletion?
If you delete the group, the Qt memory manager will delete the group, but Python won't. So if you then to try access the Python object, it'll obviously try to look at something that's been deleted.
You could try connecting to the group deleted signal (or something). But this signal might not exist, or there might be a bunch of ways in which the group can get up deleted.

Alternatively, you just catch the exception and update the Python state then? Might be the most robust and simple.

@visr

visr commented Apr 4, 2025

Copy link
Copy Markdown
Member

What do you suggest for Basin labels?

Hmm by default nothing I guess so it doesn't get confused with flow rates? Otherwise level, would be nice if that is already prepared and folks just have to enable it.

would have to make an update symbology after arrow load for it, based on min/max or so

You wanted that for flow_rate as well right? Also fine with me as a follow up.

@visr

visr commented Apr 4, 2025

Copy link
Copy Markdown
Member

Another follow up, since I see you already add concentration data, would be to add allocation results, see also #2196.

@evetion

evetion commented Apr 4, 2025

Copy link
Copy Markdown
Member Author

Ok, this is good for review/merge.

Fixed:

  • Remove our Python reference (used in the update arrow layers) to our layers when layers are about to be removed. Should fix the C++ Wrapper errors.
  • Hide the Results group by default
  • Link layer now also supports topology view
  • FlowLink layer has labels by default
  • BasinNode layer now visualizes level (range will be useless for most cases though) and has labels by default.
  • Show topology button will only show up once now
  • Layers are now temporal enabled, enabling resetting of temporal ranges after manual changes:
Screenshot 2025-04-04 at 19 15 17

@evetion evetion merged commit 7be9b61 into main Apr 7, 2025
@evetion evetion deleted the feat/temporal-qgis branch April 7, 2025 09:14
@visr visr mentioned this pull request Apr 14, 2025
visr added a commit that referenced this pull request Apr 15, 2025
## [v2025.3.0] - 2025-04-14

The only breaking change in this release is to disallow connecting a
single FlowBoundary to multiple Basins.
There are large improvements in the ability to visualize results on the
map in QGIS.
We also welcome the Junction node to the family, which will help laying
out networks in a recognizable manner.

### Added
- Add spatio-temporal results layers to QGIS.
[#2208](#2208)
- Add topological (straight line) link view toggle to QGIS.
[#2208](#2208)
- Added [Junction](https://ribasim.org/reference/node/junction.html)
node type. [#2175](#2175)
- Write results and log bottlenecks also on an interrupt or crash.
[#2191](#2191)
[#2200](#2200)
- Log computation time and save it to `solver_stats.arrow`.
[#2209](https://github.com/Deltares/Ribasim/pull/)
- Experimental support for writing the model network and results into
files used by Delft-FEWS,
[`model.to_fews`](`https://ribasim.org/reference/python/Model.html#ribasim.Model.to_fews`).
[#2161](#2161)
- Document
[`results/concentration.arrow`](https://ribasim.org/reference/usage.html#concentration---concentration.arrow).
[#2165](#2165)

### Changed
- Allow max 1 outflow neighbour for FlowBoundary.
[#2192](#2192)
- Automatic differentiation is enabled by default again, `autodiff =
true`, leading to better performance.
[#2137](#2137)
[#2183](#2183)
visr added a commit that referenced this pull request Feb 20, 2026
Fixes #2618

This updates the QGIS temporal controller / spatial view from
#2208 to netCDF, and **replaces
our use of the iMOD timeseries widget with a new widget with a Plotly
plot**.

Plotly comes with QGIS. I considered using DataPlotly at first, but it
wouldn't help us much versus using plotly directly, and as noted in
#790 (comment)
wflow-qgis follows a similar approach. This is just line plots, but if
we want we can also consider supporting fancier stacked histogram water
balance plots for Basins, and fraction plots for water quality for
instance.

- [x] Docs (update guide, also update old screenshots)
- [x] Tests (at least in the manual test plan)
- [x] Trying it out on large models (seems reasonable, takes a few secs
to plot timeseries of a hundred nodes, but you don't want to plot so
many, spatial results feel similar as before)
- [x] Go over the code (used AI)

I didn't want to have more than one Ribasim button, so I made the
current one a dropdown, and moved the other options that were previously
in the context menu there.

<img width="1353" height="983" alt="Screenshot 2026-02-16 212052"
src="https://github.com/user-attachments/assets/7d39eab3-7320-431f-b5d6-c0b710f5a1a1"
/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show topology in QGIS Visualize flows in QGIS

3 participants