From 2d3b6d63d3326b7a699f23d55ee50b87387c9847 Mon Sep 17 00:00:00 2001 From: Martijn Visser Date: Wed, 25 Oct 2023 22:21:40 +0200 Subject: [PATCH] refine edge labels (#683) Fixes #175 Most of the work for this was already done in #658. This changes a few things: - Stop using brackets around the ID to reduce visual clutter: now we use `"Lake IJssel" #10` in printed errors and `Lake IJssel #10` as a QGIS label - Add the edge ID to the label, this is the part that fixed #175 - Stop putting random strings as names in our basic test model - Add some real names to our Dutch waterways test model ![image](https://github.com/Deltares/Ribasim/assets/4471859/9eb4eaf7-51b5-4a21-bcd3-f278681bb6d8) --- core/src/create.jl | 8 +-- core/test/validation.jl | 4 +- python/ribasim/ribasim/utils.py | 7 --- .../ribasim_testmodels/basic.py | 6 +-- .../ribasim_testmodels/dutch_waterways.py | 53 ++++++++++++++++++- qgis/core/nodes.py | 6 ++- 6 files changed, 63 insertions(+), 21 deletions(-) diff --git a/core/src/create.jl b/core/src/create.jl index 6e0c0aa01..2513d0a37 100644 --- a/core/src/create.jl +++ b/core/src/create.jl @@ -154,7 +154,7 @@ function parse_static_and_time( ) if !is_valid errors = true - @error "A $parameter_name time series for $nodetype node $(repr(node_name)) (#$node_id) has repeated times, this can not be interpolated." + @error "A $parameter_name time series for $nodetype node $(repr(node_name)) #$node_id has repeated times, this can not be interpolated." end else # Activity of transient nodes is assumed to be true @@ -168,7 +168,7 @@ function parse_static_and_time( getfield(out, parameter_name)[node_idx] = val end else - @error "$nodetype node $(repr(node_name)) (#$node_id) data not in any table." + @error "$nodetype node $(repr(node_name)) #$node_id data not in any table." errors = true end end @@ -313,11 +313,11 @@ function TabulatedRatingCurve(db::DB, config::Config)::TabulatedRatingCurve push!(interpolations, interpolation) push!(active, true) else - @error "TabulatedRatingCurve node $(repr(node_name)) (#$node_id) data not in any table." + @error "TabulatedRatingCurve node $(repr(node_name)) #$node_id data not in any table." errors = true end if !is_valid - @error "A Q(h) relationship for TabulatedRatingCurve $(repr(node_name)) (#$node_id) from the $source table has repeated levels, this can not be interpolated." + @error "A Q(h) relationship for TabulatedRatingCurve $(repr(node_name)) #$node_id from the $source table has repeated levels, this can not be interpolated." errors = true end end diff --git a/core/test/validation.jl b/core/test/validation.jl index 06ee51832..00eb31a7e 100644 --- a/core/test/validation.jl +++ b/core/test/validation.jl @@ -43,10 +43,10 @@ end @test length(logger.logs) == 2 @test logger.logs[1].level == Error @test logger.logs[1].message == - "A Q(h) relationship for TabulatedRatingCurve \"\" (#1) from the static table has repeated levels, this can not be interpolated." + "A Q(h) relationship for TabulatedRatingCurve \"\" #1 from the static table has repeated levels, this can not be interpolated." @test logger.logs[2].level == Error @test logger.logs[2].message == - "A Q(h) relationship for TabulatedRatingCurve \"\" (#2) from the time table has repeated levels, this can not be interpolated." + "A Q(h) relationship for TabulatedRatingCurve \"\" #2 from the time table has repeated levels, this can not be interpolated." end @testset "Neighbor count validation" begin diff --git a/python/ribasim/ribasim/utils.py b/python/ribasim/ribasim/utils.py index 259bfab87..6a3db761e 100644 --- a/python/ribasim/ribasim/utils.py +++ b/python/ribasim/ribasim/utils.py @@ -1,5 +1,3 @@ -import random -import string from typing import Any, Sequence, Tuple import numpy as np @@ -78,8 +76,3 @@ def connectivity_from_geometry( from_id = node_index[edge_node_id[:, 0]].to_numpy() to_id = node_index[edge_node_id[:, 1]].to_numpy() return from_id, to_id - - -def random_string(length=3): - letters = string.ascii_lowercase - return "".join(random.choice(letters) for i in range(length)) diff --git a/python/ribasim_testmodels/ribasim_testmodels/basic.py b/python/ribasim_testmodels/ribasim_testmodels/basic.py index 710f4bf5b..708a26dd1 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/basic.py +++ b/python/ribasim_testmodels/ribasim_testmodels/basic.py @@ -159,10 +159,7 @@ def basic_model() -> ribasim.Model: # Make sure the feature id starts at 1: explicitly give an index. node = ribasim.Node( static=gpd.GeoDataFrame( - data={ - "type": node_type, - "name": [ribasim.utils.random_string() for _ in range(len(node_id))], - }, + data={"type": node_type}, index=pd.Index(node_id, name="fid"), geometry=node_xy, crs="EPSG:28992", @@ -180,7 +177,6 @@ def basic_model() -> ribasim.Model: edge = ribasim.Edge( static=gpd.GeoDataFrame( data={ - "name": [ribasim.utils.random_string() for _ in range(len(from_id))], "from_node_id": from_id, "to_node_id": to_id, "edge_type": len(from_id) * ["flow"], diff --git a/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py b/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py index a39b76b7b..dc7cfffb3 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py +++ b/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py @@ -233,12 +233,35 @@ def dutch_waterways_model(): ] ) + node_name = [ + "", # 1: LevelBoundary + "IJsselkop", # 2: Basin + "", # 3: LinearResistance + "", # 4: LinearResistance + "IJssel Westervoort", # 5: Basin + "Nederrijn Arnhem", # 6: Basin + "", # 7: LevelBoundary + "Driel open", # 8: TabulatedRatingCurve + "Driel gecontroleerd", # 9: Pump + "", # 10: Basin + "", # 11: LinearResistance + "", # 12: Basin + "Amerongen open", # 13: TabulatedRatingCurve + "Amerongen gecontroleerd", # 14: Pump + "", # 15: Basin + "Kruising ARK", # 16: LevelBoundary + "Controller Driel", # 17: DiscreteControl + "", # 18: LinearResistance + "", # 19: LinearResistance + "Controller Amerongen", # 20: PidControl + ] + node_xy = gpd.points_from_xy(x=xy[:, 0], y=405 - xy[:, 1]) # Make sure the feature id starts at 1: explicitly give an index. node = ribasim.Node( static=gpd.GeoDataFrame( - data={"type": node_type}, + data={"type": node_type, "name": node_name}, index=pd.Index(node_id, name="fid"), geometry=node_xy, crs="EPSG:28992", @@ -261,6 +284,33 @@ def dutch_waterways_model(): from_id = np.concatenate([from_id_flow, from_id_control]) to_id = np.concatenate([to_id_flow, to_id_control]) + edge_name = [ + # flow + "Pannerdensch Kanaal", # 1 -> 2 + "Start IJssel", # 2 -> 3 + "", # 3 -> 5 + "Start Nederrijn", # 2 -> 4 + "", # 4 -> 6 + "", # 6 -> 9 + "", # 9 -> 10 + "", # 10 -> 11 + "", # 11 -> 12 + "", # 12 -> 14 + "", # 14 -> 15 + "", # 6 -> 8 + "", # 8 -> 10 + "", # 12 -> 13 + "", # 13 -> 15 + "", # 5 -> 18 + "", # 18 -> 7 + "", # 15 -> 19 + "", # 19 -> 16 + # control + "", # 20 -> 14 + "", # 17 -> 8 + "", # 17 -> 9 + ] + lines = ribasim.utils.geometry_from_connectivity(node, from_id, to_id) edge = ribasim.Edge( static=gpd.GeoDataFrame( @@ -269,6 +319,7 @@ def dutch_waterways_model(): "to_node_id": to_id, "edge_type": len(from_id_flow) * ["flow"] + len(from_id_control) * ["control"], + "name": edge_name, }, geometry=lines, crs="EPSG:28992", diff --git a/qgis/core/nodes.py b/qgis/core/nodes.py index 93f82a0a9..7812bd095 100644 --- a/qgis/core/nodes.py +++ b/qgis/core/nodes.py @@ -210,7 +210,7 @@ def renderer(self) -> QgsCategorizedSymbolRenderer: @property def labels(self) -> Any: pal_layer = QgsPalLayerSettings() - pal_layer.fieldName = """concat("name", ' (#', "fid", ')')""" + pal_layer.fieldName = """concat("name", ' #', "fid")""" pal_layer.isExpression = True pal_layer.enabled = True pal_layer.dist = 2.0 @@ -290,9 +290,11 @@ def renderer(self) -> QgsCategorizedSymbolRenderer: @property def labels(self) -> Any: pal_layer = QgsPalLayerSettings() - pal_layer.fieldName = "name" + pal_layer.fieldName = """concat("name", ' #', "fid")""" + pal_layer.isExpression = True pal_layer.enabled = True pal_layer.placement = Qgis.LabelPlacement.Line + pal_layer.dist = 1.0 labels = QgsVectorLayerSimpleLabeling(pal_layer) return labels