diff --git a/docs/rekenmethodiek/geohydrologische_modellen.rst b/docs/rekenmethodiek/geohydrologische_modellen.rst
index 4c3cb5c1..741fa121 100644
--- a/docs/rekenmethodiek/geohydrologische_modellen.rst
+++ b/docs/rekenmethodiek/geohydrologische_modellen.rst
@@ -34,7 +34,7 @@ verschilt.
De grondwaterstroming vormt de drijvende kracht achter het proces van terugschrijdende erosie.
Door het analytische grondwatermodel 4A van :cite:`trw_2004` toe te passen,
kan de respons :math:`r_{exit}` in het uittredepunt worden beschreven als functie van de locatie in het
-dwarspofiel :math:`x_{exit}` [m] en de geohydrologische parameters van model 4A.
+dwarsprofiel :math:`x_{exit}` [m] en de geohydrologische parameters van model 4A.
Een uitgebreide toelichting op de onderliggende theorie van dit model is te vinden in :ref:`stationair-model`.
De respons in het uittredepunt wordt bepaald met:
diff --git a/geoprob_pipe/calculations/systems/model4a/initial_input.py b/geoprob_pipe/calculations/systems/model4a/initial_input.py
index a33a0940..44f74063 100644
--- a/geoprob_pipe/calculations/systems/model4a/initial_input.py
+++ b/geoprob_pipe/calculations/systems/model4a/initial_input.py
@@ -293,4 +293,22 @@
"mean": 0.3,
"source": "excel",
},
+ {
+ "name": "a_vak",
+ "description": "De mechanisme gevoelige fractie van het element.",
+ "remark": "",
+ "unit": "-",
+ "distribution_type": DistributionType.deterministic,
+ "mean": 1.0,
+ "source": "excel"
+ },
+ {
+ "name": "delta_length",
+ "description": "De equivalente onafhankelijke lengte voor STPH.",
+ "remark": "",
+ "unit": "m",
+ "distribution_type": DistributionType.deterministic,
+ "mean": 300.0,
+ "source": "excel"
+ },
]
diff --git a/geoprob_pipe/calculations/systems/moria/initial_input.py b/geoprob_pipe/calculations/systems/moria/initial_input.py
index 877b9178..8adefc59 100644
--- a/geoprob_pipe/calculations/systems/moria/initial_input.py
+++ b/geoprob_pipe/calculations/systems/moria/initial_input.py
@@ -276,7 +276,7 @@
"remark": "",
"unit": "kN/m³",
"distribution_type": DistributionType.deterministic,
- "mean": 16.5,
+ "mean": 26.0,
"source": "excel",
},
{
@@ -288,4 +288,22 @@
"mean": 0.3,
"source": "excel",
},
+ {
+ "name": "a_vak",
+ "description": "De mechanisme gevoelige fractie van het element.",
+ "remark": "",
+ "unit": "-",
+ "distribution_type": DistributionType.deterministic,
+ "mean": 1.0,
+ "source": "excel"
+ },
+ {
+ "name": "delta_length",
+ "description": "De equivalente onafhankelijke lengte voor STPH.",
+ "remark": "",
+ "unit": "m",
+ "distribution_type": DistributionType.deterministic,
+ "mean": 300.0,
+ "source": "excel"
+ },
]
diff --git a/geoprob_pipe/calculations/systems/single_calc.py b/geoprob_pipe/calculations/systems/single_calc.py
index 223bd83d..c33d4e74 100644
--- a/geoprob_pipe/calculations/systems/single_calc.py
+++ b/geoprob_pipe/calculations/systems/single_calc.py
@@ -42,7 +42,7 @@ def reproduce_single_calculation(
conn = sqlite3.connect(geopackage_filepath)
cursor = conn.cursor()
cursor.execute(
- 'SELECT "values" FROM geoprob_pipe_metadata WHERE metadata_type = ?',
+ 'SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?',
("geohydrologisch_model",))
geohydrologisch_model: str = cursor.fetchone()[0]
diff --git a/geoprob_pipe/calculations/systems/validation.py b/geoprob_pipe/calculations/systems/validation.py
index 23a13f78..c143590d 100644
--- a/geoprob_pipe/calculations/systems/validation.py
+++ b/geoprob_pipe/calculations/systems/validation.py
@@ -66,8 +66,8 @@
GAMMA_KORREL = ColumnValidation(column_name="mean", requirements=[
ValidationRequirement(
requirement=requirements.is_in_range(left=23.0, right=29.0, inclusive="both"),
- failure_msg=f"De parameter 'gamma_korrel' hoort 26.0 te zijn. "
- f"De applicatie vereist dat deze tussen 23.0 en 29.0 is. ",
+ failure_msg="De parameter 'gamma_korrel' hoort 26.0 te zijn. "
+ "De applicatie vereist dat deze tussen 23.0 en 29.0 is. ",
filters=filters.combine(filters.is_in(column="parameter", values=["gamma_korrel"]),
FILTER_IS_NOT_CDF_CURVE))])
diff --git a/geoprob_pipe/calculations/systems/wbi/initial_input.py b/geoprob_pipe/calculations/systems/wbi/initial_input.py
index d3285ac1..5381d75d 100644
--- a/geoprob_pipe/calculations/systems/wbi/initial_input.py
+++ b/geoprob_pipe/calculations/systems/wbi/initial_input.py
@@ -251,4 +251,22 @@
"mean": 0.3,
"source": "excel",
},
+ {
+ "name": "a_vak",
+ "description": "De mechanisme gevoelige fractie van het element.",
+ "remark": "",
+ "unit": "-",
+ "distribution_type": DistributionType.deterministic,
+ "mean": 1.0,
+ "source": "excel"
+ },
+ {
+ "name": "delta_length",
+ "description": "De equivalente onafhankelijke lengte voor STPH.",
+ "remark": "",
+ "unit": "m",
+ "distribution_type": DistributionType.deterministic,
+ "mean": 300.0,
+ "source": "excel"
+ },
]
diff --git a/geoprob_pipe/cmd_app/cmd.py b/geoprob_pipe/cmd_app/cmd.py
index 8fd5d9e8..ec8c7e8b 100644
--- a/geoprob_pipe/cmd_app/cmd.py
+++ b/geoprob_pipe/cmd_app/cmd.py
@@ -1,33 +1,49 @@
-import typer
-from rich.console import Console
import os
import sqlite3
-from geoprob_pipe.utils import clear_terminal
+from pathlib import Path
+from configparser import ConfigParser
from datetime import datetime
+from importlib.metadata import distributions
+from typing import Dict, List, Optional
+
+import typer
+from rich.console import Console
from rich.panel import Panel
+
from geoprob_pipe.cmd_app.questionnaire import start_questionnaire
-from typing import Optional, List, Dict
from geoprob_pipe.cmd_app.utils.misc import get_geoprob_pipe_version_number
+from geoprob_pipe.utils import clear_terminal
from geoprob_pipe.utils.loggers import setup_base_logging
-from importlib.metadata import distributions
app = typer.Typer(help="GeoProb-Pipe - CLI applicatie voor probabilistische piping berekeningen.", add_completion=False)
class ApplicationSettings:
-
+
def __init__(self):
- self.workspace_dir: Optional[str] = None
- self.geopackage_filename: Optional[str] = None
+ self.workspace_dir: Path = Path()
+ self.geopackage_filename: Path = Path()
self.datetime_stamp: str = datetime.now().strftime("%Y-%m-%d_%H%M%S")
self.to_run = "all"
# -> or vakken:1,2,3,4,5
self.debug: bool = os.getenv("GEOPROB_DEBUG") == "1"
+ # Flags
+ self.batch_input: bool = False # Flag for batch input
@property
def geopackage_filepath(self) -> str:
return os.path.join(self.workspace_dir, self.geopackage_filename)
+
+ @property
+ def batch_input_filepath(self) -> str:
+ return os.path.join(self.workspace_dir, "batch_input.ini")
+ @property
+ def input_config(self):
+ config = ConfigParser()
+ config.read(self.batch_input_filepath)
+ return config
+
@property
def hrd_dir(self):
path_to_hrd_dir = os.path.join(self.workspace_dir, "hrd_files")
@@ -61,7 +77,7 @@ def geohydrologisch_model(self) -> str:
conn = sqlite3.connect(self.geopackage_filepath)
cursor = conn.cursor()
cursor.execute("""
- SELECT geoprob_pipe_metadata."values"
+ SELECT geoprob_pipe_metadata.metadata_value
FROM geoprob_pipe_metadata
WHERE metadata_type='geohydrologisch_model';
""")
@@ -103,7 +119,7 @@ def startup_geoprob_pipe():
debug_label: str = ""
if app_settings.debug:
- debug_label = f", DEBUG=TRUE"
+ debug_label = ", DEBUG=TRUE"
clear_terminal()
console = Console()
diff --git a/geoprob_pipe/cmd_app/comparisons/beta_map.py b/geoprob_pipe/cmd_app/comparisons/beta_map.py
index a153b2b8..d3c6b9db 100644
--- a/geoprob_pipe/cmd_app/comparisons/beta_map.py
+++ b/geoprob_pipe/cmd_app/comparisons/beta_map.py
@@ -1,9 +1,13 @@
from __future__ import annotations
+
import os
-import plotly.graph_objects as go
-import geopandas as gpd
-from shapely.geometry import LineString, MultiLineString, GeometryCollection
from typing import TYPE_CHECKING
+
+import fiona
+import geopandas as gpd
+import plotly.graph_objects as go
+from shapely.geometry import GeometryCollection, LineString, MultiLineString
+
if TYPE_CHECKING:
from geoprob_pipe.cmd_app.comparisons import ComparisonCollector
@@ -35,59 +39,72 @@ def _calculate_zoom(lat_range_val, lon_range_val):
return zoom
-def _add_line(comparison: ComparisonCollector, fig: go.Figure,
- layer: str, color: str):
- gdf_traject = gpd.read_file(comparison.geopackage_filepath_1,
- layer=layer)
- gdf_traject = gdf_traject.to_crs("EPSG:4326")
-
- def plot_linestring(ls, display):
- xs, ys = ls.xy
- xs = list(xs)
- ys = list(ys)
- fig.add_trace(go.Scattermap(
- lon=xs,
- lat=ys,
- mode="lines",
- line=dict(color=color, width=1.5),
- hoverinfo="none",
- name=layer,
- legendgroup=layer,
- showlegend=display
- ))
- show = True
- for geom in gdf_traject.geometry:
- if isinstance(geom, LineString):
- plot_linestring(geom, show)
- show = False
- elif isinstance(geom, MultiLineString):
- for line in geom.geoms:
- plot_linestring(line, show)
+def _add_line(
+ comparison: ComparisonCollector, fig: go.Figure, layer: str, color: str
+):
+ gpkg_layers: list[str] = fiona.listlayers(comparison.geopackage_filepath_1)
+ list_layers: list[str] = [
+ lay for lay in gpkg_layers if lay.split("__")[0] == layer
+ ]
+
+ for listed_layer in list_layers:
+ gdf_traject = gpd.read_file(
+ comparison.geopackage_filepath_1, layer=listed_layer
+ )
+ gdf_traject = gdf_traject.to_crs("EPSG:4326")
+
+ def plot_linestring(ls, display):
+ xs, ys = ls.xy
+ xs = list(xs)
+ ys = list(ys)
+ fig.add_trace(
+ go.Scattermap(
+ lon=xs,
+ lat=ys,
+ mode="lines",
+ line=dict(color=color, width=1.5),
+ hoverinfo="none",
+ name=listed_layer,
+ legendgroup=layer,
+ showlegend=display,
+ )
+ )
+
+ show = True
+ for geom in gdf_traject.geometry:
+ if isinstance(geom, LineString):
+ plot_linestring(geom, show)
show = False
- elif isinstance(geom, GeometryCollection):
- for g in geom.geoms:
- if isinstance(g, LineString):
- plot_linestring(g, show)
+ elif isinstance(geom, MultiLineString):
+ for line in geom.geoms:
+ plot_linestring(line, show)
show = False
- elif isinstance(g, MultiLineString):
- for line in g.geoms:
- plot_linestring(line, show)
+ elif isinstance(geom, GeometryCollection):
+ for g in geom.geoms:
+ if isinstance(g, LineString):
+ plot_linestring(g, show)
show = False
+ elif isinstance(g, MultiLineString):
+ for line in g.geoms:
+ plot_linestring(line, show)
+ show = False
- else:
- print("Skipping unsupported geometry:", geom.geom_type)
+ else:
+ print("Skipping unsupported geometry:", geom.geom_type)
return fig
-def map_delta_beta_comparison(comparison: ComparisonCollector,
- export: bool = False) -> go.Figure:
+def map_delta_beta_comparison(
+ comparison: ComparisonCollector, export: bool = False
+) -> go.Figure:
# load data from class
- gdf_result1 = (comparison.gdf1_uittredepunten[
+ gdf_result1 = comparison.gdf1_uittredepunten[
["uittredepunt_id", "beta", "geometry"]
- ].rename(columns={"beta": "beta1"}))
- gdf_result2 = (comparison.gdf2_uittredepunten[
- ["uittredepunt_id", "beta"]].rename(columns={"beta": "beta2"}))
+ ].rename(columns={"beta": "beta1"})
+ gdf_result2 = comparison.gdf2_uittredepunten[
+ ["uittredepunt_id", "beta"]
+ ].rename(columns={"beta": "beta2"})
gdf = gdf_result1.merge(gdf_result2, on="uittredepunt_id")
gdf["beta_delta"] = gdf["beta2"] - gdf["beta1"]
@@ -95,37 +112,39 @@ def map_delta_beta_comparison(comparison: ComparisonCollector,
gdf_latlon = gdf.to_crs("EPSG:4326")
fig = go.Figure()
- fig.add_trace(go.Scattermap(
- mode="markers",
- lat=gdf_latlon.geometry.y,
- lon=gdf_latlon.geometry.x,
- marker=dict(
- size=9,
- color="black"
- ),
- showlegend=False
- ))
+ fig.add_trace(
+ go.Scattermap(
+ mode="markers",
+ lat=gdf_latlon.geometry.y,
+ lon=gdf_latlon.geometry.x,
+ marker=dict(size=9, color="black"),
+ showlegend=False,
+ )
+ )
hoverdata = ["uittredepunt_id", "beta_delta", "beta1", "beta2"]
- fig.add_trace(go.Scattermap(
- mode="markers",
- lat=gdf_latlon.geometry.y,
- lon=gdf_latlon.geometry.x,
- marker=dict(
- size=8,
- color=gdf_latlon["beta_delta"],
- cmax=3,
- cmin=-3,
- colorscale="RdYlGn",
- colorbar=dict(title="Delta Beta")
- ),
- hoverinfo='text',
- text=gdf_latlon[hoverdata].apply(
- lambda row: '
'.join(
- [f"{col}: {round(row[col], 3)}" for col in hoverdata]
+ fig.add_trace(
+ go.Scattermap(
+ mode="markers",
+ lat=gdf_latlon.geometry.y,
+ lon=gdf_latlon.geometry.x,
+ marker=dict(
+ size=8,
+ color=gdf_latlon["beta_delta"],
+ cmax=3,
+ cmin=-3,
+ colorscale="RdYlGn",
+ colorbar=dict(title="Delta Beta"),
+ ),
+ hoverinfo="text",
+ text=gdf_latlon[hoverdata].apply(
+ lambda row: "
".join(
+ [f"{col}: {round(row[col], 3)}" for col in hoverdata]
),
- axis=1),
- showlegend=False
- ))
+ axis=1,
+ ),
+ showlegend=False,
+ )
+ )
fig = _add_line(comparison, fig, "dijktraject", "black")
fig = _add_line(comparison, fig, "intredelijn", "blue")
@@ -138,24 +157,23 @@ def map_delta_beta_comparison(comparison: ComparisonCollector,
# carto-positron, open-street-map, satellite-streets
map_zoom=zoom,
map_center=dict(
- lat=gdf_latlon.geometry.y.mean(),
- lon=gdf_latlon.geometry.x.mean()
+ lat=gdf_latlon.geometry.y.mean(), lon=gdf_latlon.geometry.x.mean()
),
dragmode="zoom",
- title=f"Delta beta van uittredepunten tussen
" +
- f"Beta1: {comparison.name_1} en Beta2: {comparison.name_2}",
+ title="Delta beta van uittredepunten tussen
"
+ + f"Beta1: {comparison.name_1} en Beta2: {comparison.name_2}",
legend=dict(
- orientation="h",
- yanchor="bottom",
- y=1.02,
- xanchor="right",
- x=1))
+ orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1
+ ),
+ )
if export:
os.makedirs(comparison.export_dir, exist_ok=True)
- fig.write_html(os.path.join(
- comparison.export_dir, "delta_beta_map.html"
- ), include_plotlyjs='cdn', include_mathjax='cdn')
+ fig.write_html(
+ os.path.join(comparison.export_dir, "delta_beta_map.html"),
+ include_plotlyjs="cdn",
+ include_mathjax="cdn",
+ )
# fig.write_image(os.path.join(
# comparison.export_dir, "delta_beta_map.png"
# ), format="png", scale=5, width=1400)
@@ -163,14 +181,16 @@ def map_delta_beta_comparison(comparison: ComparisonCollector,
return fig
-def map_ratio_beta_comparison(comparison: ComparisonCollector,
- export: bool = False) -> go.Figure:
+def map_ratio_beta_comparison(
+ comparison: ComparisonCollector, export: bool = False
+) -> go.Figure:
# load data from class
- gdf_result1 = (comparison.gdf1_uittredepunten[
+ gdf_result1 = comparison.gdf1_uittredepunten[
["uittredepunt_id", "beta", "geometry"]
- ].rename(columns={"beta": "beta1"}))
- gdf_result2 = (comparison.gdf2_uittredepunten[
- ["uittredepunt_id", "beta"]].rename(columns={"beta": "beta2"}))
+ ].rename(columns={"beta": "beta1"})
+ gdf_result2 = comparison.gdf2_uittredepunten[
+ ["uittredepunt_id", "beta"]
+ ].rename(columns={"beta": "beta2"})
gdf = gdf_result1.merge(gdf_result2, on="uittredepunt_id")
gdf["beta_ratio"] = round((gdf["beta1"] / gdf["beta2"]) * 100, 2)
@@ -179,37 +199,39 @@ def map_ratio_beta_comparison(comparison: ComparisonCollector,
gdf_latlon = gdf.to_crs("EPSG:4326")
fig = go.Figure()
- fig.add_trace(go.Scattermap(
- mode="markers",
- lat=gdf_latlon.geometry.y,
- lon=gdf_latlon.geometry.x,
- marker=dict(
- size=9,
- color="black"
- ),
- showlegend=False
- ))
+ fig.add_trace(
+ go.Scattermap(
+ mode="markers",
+ lat=gdf_latlon.geometry.y,
+ lon=gdf_latlon.geometry.x,
+ marker=dict(size=9, color="black"),
+ showlegend=False,
+ )
+ )
hoverdata = ["uittredepunt_id", "beta_ratio", "beta1", "beta2"]
- fig.add_trace(go.Scattermap(
- mode="markers",
- lat=gdf_latlon.geometry.y,
- lon=gdf_latlon.geometry.x,
- marker=dict(
- size=8,
- color=gdf_latlon["beta_ratio"],
- cmax=200,
- cmin=0,
- colorscale="RdYlGn",
- colorbar=dict(title="Beta Ratio - Beta1/Beta2 [%]"),
- ),
- hoverinfo='text',
- text=gdf_latlon[hoverdata].apply(
- lambda row: '
'.join(
- [f"{col}: {round(row[col], 3)}" for col in hoverdata]
+ fig.add_trace(
+ go.Scattermap(
+ mode="markers",
+ lat=gdf_latlon.geometry.y,
+ lon=gdf_latlon.geometry.x,
+ marker=dict(
+ size=8,
+ color=gdf_latlon["beta_ratio"],
+ cmax=200,
+ cmin=0,
+ colorscale="RdYlGn",
+ colorbar=dict(title="Beta Ratio - Beta1/Beta2 [%]"),
+ ),
+ hoverinfo="text",
+ text=gdf_latlon[hoverdata].apply(
+ lambda row: "
".join(
+ [f"{col}: {round(row[col], 3)}" for col in hoverdata]
),
- axis=1),
- showlegend=False
- ))
+ axis=1,
+ ),
+ showlegend=False,
+ )
+ )
fig = _add_line(comparison, fig, "dijktraject", "black")
fig = _add_line(comparison, fig, "intredelijn", "blue")
@@ -222,25 +244,22 @@ def map_ratio_beta_comparison(comparison: ComparisonCollector,
# carto-positron, open-street-map, satellite-streets
map_zoom=zoom,
map_center=dict(
- lat=gdf_latlon.geometry.y.mean(),
- lon=gdf_latlon.geometry.x.mean()
+ lat=gdf_latlon.geometry.y.mean(), lon=gdf_latlon.geometry.x.mean()
),
dragmode="zoom",
- title=f"Beta ratio van uittredepunten tussen
" +
- f"Beta1: {comparison.name_1} en Beta2: {comparison.name_2}",
+ title="Beta ratio van uittredepunten tussen
"
+ + f"Beta1: {comparison.name_1} en Beta2: {comparison.name_2}",
legend=dict(
- orientation="h",
- yanchor="bottom",
- y=1.02,
- xanchor="right",
- x=1
- )
- )
+ orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1
+ ),
+ )
if export:
os.makedirs(comparison.export_dir, exist_ok=True)
- fig.write_html(os.path.join(
- comparison.export_dir, "ratio_beta_map.html"
- ), include_plotlyjs='cdn', include_mathjax='cdn')
+ fig.write_html(
+ os.path.join(comparison.export_dir, "ratio_beta_map.html"),
+ include_plotlyjs="cdn",
+ include_mathjax="cdn",
+ )
# fig.write_image(os.path.join(
# comparison.export_dir, "ratio_beta_map.png"
# ), format="png", scale=5, width=1400)
diff --git a/geoprob_pipe/cmd_app/comparisons/start_comparison.py b/geoprob_pipe/cmd_app/comparisons/start_comparison.py
index bea5b14e..39d4c01b 100644
--- a/geoprob_pipe/cmd_app/comparisons/start_comparison.py
+++ b/geoprob_pipe/cmd_app/comparisons/start_comparison.py
@@ -13,9 +13,7 @@ def specify_dir_for_first_file():
Returns:
filepath:
"""
- filepath: str = ""
- filepath_is_valid = False
- while filepath_is_valid is False:
+ while True:
filepath: str = inq_text(
message=("Specificeer het volledige bestandspad naar het eerste "
".geoprob_pipe.gpkg-bestand."),
@@ -35,7 +33,7 @@ def specify_dir_for_first_file():
BColors.ENDC)
continue
- filepath_is_valid = True
+ break
return filepath
@@ -47,9 +45,7 @@ def specify_dir_for_second_file():
Returns:
filepath:
"""
- filepath: str = ""
- filepath_is_valid = False
- while filepath_is_valid is False:
+ while True:
filepath: str = inq_text(
message=("Specificeer het volledige bestandspad naar het tweede "
".geoprob_pipe.gpkg-bestand."),
@@ -64,12 +60,13 @@ def specify_dir_for_second_file():
"deze extensie.",
BColors.ENDC)
continue
+
if not os.path.exists(filepath):
print(BColors.WARNING, "Het opgegeven bestandspad bestaat niet.",
BColors.ENDC)
continue
- filepath_is_valid = True
+ break
return filepath
@@ -81,9 +78,7 @@ def specify_dir_for_comparison():
Returns:
workspace_dir:
"""
- workspace_dir: str = ""
- workspace_dir_is_valid = False
- while workspace_dir_is_valid is False:
+ while True:
workspace_dir: str = inq_text(
message="Specificeer het volledige pad naar de map waar je"
+ " de export van de vergelijking wilt opslaan.",
@@ -94,12 +89,13 @@ def specify_dir_for_comparison():
print(BColors.WARNING, "De opgegeven map bestaat niet.",
BColors.ENDC)
continue
+
if not os.path.isdir(workspace_dir):
print(BColors.WARNING, "De opgegeven locatie is geen map.",
BColors.ENDC)
continue
- workspace_dir_is_valid = True
+ break
return workspace_dir
diff --git a/geoprob_pipe/cmd_app/general/geohydrologisch_model.py b/geoprob_pipe/cmd_app/general/geohydrologisch_model.py
index 1bcb81e0..6e983a3f 100644
--- a/geoprob_pipe/cmd_app/general/geohydrologisch_model.py
+++ b/geoprob_pipe/cmd_app/general/geohydrologisch_model.py
@@ -20,7 +20,7 @@ def created_model(app_settings: ApplicationSettings) -> bool:
return True
# Check if specified model is legal
- current_specified_model = df[df['metadata_type'] == "geohydrologisch_model"]["values"].iloc[0]
+ current_specified_model = df[df['metadata_type'] == "geohydrologisch_model"]["metadata_value"].iloc[0]
if current_specified_model not in CALCULATION_MAPPER.keys():
specify_model_to_use(app_settings, update_record=True)
return True
@@ -46,11 +46,11 @@ def specify_model_to_use(app_settings: ApplicationSettings, update_record: bool
choice_formatted = choice_formatted.replace(" ", "").lower()
sql_statement = f"""
INSERT INTO geoprob_pipe_metadata
- ('metadata_type', 'values') VALUES ('geohydrologisch_model', '{choice_formatted}')"""
+ (metadata_type, metadata_value) VALUES ('geohydrologisch_model', '{choice_formatted}')"""
if update_record:
sql_statement = f"""
UPDATE geoprob_pipe_metadata
- SET 'values' = '{choice_formatted}'
+ SET metadata_value = '{choice_formatted}'
WHERE metadata_type = 'geohydrologisch_model'"""
cursor.execute(sql_statement)
conn.commit()
diff --git a/geoprob_pipe/cmd_app/general/project.py b/geoprob_pipe/cmd_app/general/project.py
index 68fbe4d0..64b2f4e9 100644
--- a/geoprob_pipe/cmd_app/general/project.py
+++ b/geoprob_pipe/cmd_app/general/project.py
@@ -65,7 +65,7 @@ def created_project(app_settings: ApplicationSettings) -> bool:
console = Console()
console.print(Panel(
EXPLANATION_REPRODUCING_SINGLE_CALCULATION,
- title=f"Inspecteer een enkele berekening".upper(),
+ title="Inspecteer een enkele berekening".upper(),
title_align="left",
border_style="bright_blue",
padding=(0, 2)))
@@ -78,7 +78,7 @@ def created_project(app_settings: ApplicationSettings) -> bool:
def _get_file_geoprob_pipe_version(file_path: str) -> Optional[str]:
conn = sqlite3.connect(file_path)
cursor = conn.cursor()
- cursor.execute(f"SELECT * FROM geoprob_pipe_metadata WHERE metadata_type = 'pip_freeze' LIMIT 1;")
+ cursor.execute("SELECT * FROM geoprob_pipe_metadata WHERE metadata_type = 'pip_freeze' LIMIT 1;")
row = cursor.fetchone()
dict_item = ast.literal_eval(row[2])
@@ -97,10 +97,10 @@ def _compare_versions_and_possibly_warn(installed_version: str, file_version: st
version_diff_msg = (
f"Er is een GeoProb-Pipe versie verschil tussen de installatie ({v_installed}) en het bestand ({v_file}).")
reinstall_msg = (
- f"\n"
- f"Wil je de versies liever gelijk trekken? Dit doe je door eerst de applicatie af te sluiten en vervolgens het \n"
- f"commando `pip install geoprob-pipe==versie_nummer` uit te voeren. Waarbij je `versie_nummer` vervangt met het \n"
- f"nummer van de gewenste versie")
+ "\n"
+ "Wil je de versies liever gelijk trekken? Dit doe je door eerst de applicatie af te sluiten en vervolgens het \n"
+ "commando `pip install geoprob-pipe==versie_nummer` uit te voeren. Waarbij je `versie_nummer` vervangt met het \n"
+ "nummer van de gewenste versie")
if v_installed.major != v_file.major:
print(f"\n{BColors.FAIL}SEVERE WARNING:\n"
@@ -109,6 +109,7 @@ def _compare_versions_and_possibly_warn(installed_version: str, file_version: st
f"compatibel met elkaar zijn. \n"
f"{reinstall_msg}"
f"{BColors.ENDC}\n")
+
elif v_installed.minor != v_file.minor:
print(f"\n{BColors.WARNING}WARNING:\n"
f"{version_diff_msg}\n"
@@ -116,6 +117,7 @@ def _compare_versions_and_possibly_warn(installed_version: str, file_version: st
f"de applicatie. \n"
f"{reinstall_msg}"
f"{BColors.ENDC}\n")
+
elif v_installed.micro != v_file.micro:
print(f"\n{BColors.OKBLUE}"
f"{version_diff_msg}\n"
@@ -139,9 +141,7 @@ def _possibly_warn_if_version_difference(file_path: str):
def specify_path_to_existing_project(app_settings: ApplicationSettings):
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
+ while True:
filepath: str = inquirer.text(
message="Specificeer het volledige bestandspad naar het .geoprob_pipe.gpkg-bestand.",
).execute()
@@ -153,45 +153,42 @@ def specify_path_to_existing_project(app_settings: ApplicationSettings):
f"{os.path.basename(filepath)} eindigt niet op deze extensie.", BColors.ENDC)
continue
if not os.path.exists(filepath):
- print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
+ print(BColors.WARNING, "Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
continue
- filepath_is_valid = True
+ break
- app_settings.workspace_dir = os.path.dirname(filepath)
- app_settings.geopackage_filename = os.path.basename(filepath)
+ app_settings.workspace_dir = Path(os.path.dirname(filepath))
+ app_settings.geopackage_filename = Path(os.path.basename(filepath))
_possibly_warn_if_version_difference(file_path=app_settings.geopackage_filepath)
def specify_dir_for_new_project(app_settings: ApplicationSettings):
- workspace_dir: Optional[str] = None
- workspace_dir_is_valid = False
- while workspace_dir_is_valid is False:
+ while True:
workspace_dir: str = inquirer.text(
message="Specificeer het volledige pad naar de map waar je het GeoProb-Pipe-bestand wilt opslaan.",
).execute()
workspace_dir = workspace_dir.replace('"', '')
if not os.path.exists(workspace_dir):
- print(BColors.WARNING, f"De opgegeven map bestaat niet.", BColors.ENDC)
- continue
+ print(BColors.WARNING, "De opgegeven map bestaat niet.", BColors.ENDC)
+
+
if not os.path.isdir(workspace_dir):
- print(BColors.WARNING, f"De opgegeven locatie is geen map.", BColors.ENDC)
+ print(BColors.WARNING, "De opgegeven locatie is geen map.", BColors.ENDC)
continue
- workspace_dir_is_valid = True
+ break
- app_settings.workspace_dir = workspace_dir
+ app_settings.workspace_dir = Path(workspace_dir)
# Continue questionnaire
specify_project_filename(app_settings)
def specify_project_filename(app_settings: ApplicationSettings):
- filename: Optional[str] = None
- filename_is_valid = False
- while filename_is_valid is False:
+ while True:
project_name: str = inquirer.text(
message="Specificeer een bestandsnaam voor het project. "
"Het bestand wordt opgeslagen met een .geoprob_pipe.gpkg-extensie.",
@@ -207,9 +204,9 @@ def specify_project_filename(app_settings: ApplicationSettings):
f" {filepath}", BColors.ENDC)
continue
- filename_is_valid = True
+ break
- app_settings.geopackage_filename = filename
+ app_settings.geopackage_filename = Path(filename)
create_geopackage_file(app_settings)
@@ -218,7 +215,7 @@ def create_geopackage_file(app_settings: ApplicationSettings):
df = DataFrame({
"metadata_type": ["created_by", "created_datetime", "application_version", "python_version", "pip_freeze"],
- "values": [
+ "metadata_value": [
os.getenv("USERNAME"),
datetime.now(),
get_geoprob_pipe_version_number(),
diff --git a/geoprob_pipe/cmd_app/general/traject_parameters.py b/geoprob_pipe/cmd_app/general/traject_parameters.py
index c51ee9e0..aabafa34 100644
--- a/geoprob_pipe/cmd_app/general/traject_parameters.py
+++ b/geoprob_pipe/cmd_app/general/traject_parameters.py
@@ -1,10 +1,14 @@
from __future__ import annotations
-from geoprob_pipe.utils.validation_messages import BColors
-from InquirerPy import inquirer
-from typing import TYPE_CHECKING, Optional
-from geopandas import read_file
+
import sqlite3
+from typing import TYPE_CHECKING
+
+from geopandas import read_file
+from InquirerPy import inquirer
from pandas import DataFrame
+
+from geoprob_pipe.utils.validation_messages import BColors
+
if TYPE_CHECKING:
from geoprob_pipe.cmd_app.cmd import ApplicationSettings
@@ -13,29 +17,24 @@ def _append_to_db(app_settings: ApplicationSettings, key: str, value):
file_path = app_settings.geopackage_filepath
conn = sqlite3.connect(file_path)
cursor = conn.cursor()
- cursor.execute(
- """
- INSERT INTO geoprob_pipe_metadata (metadata_type, "values") VALUES (?, ?);
- """,
- (key, value))
+ cursor.execute("INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES (?, ?);",
+ (key, value))
conn.commit()
cursor.close()
def _specify_traject_id(app_settings: ApplicationSettings):
- traject_id: Optional[str] = None
- traject_id_is_valid = False
- while traject_id_is_valid is False:
+ while True:
traject_id: str = inquirer.text(
message="Specificeer een tekstuele identificatie van het dijktraject die je graag gebruikt. ",
).execute()
traject_id = traject_id.strip()
- if traject_id is "":
- print(BColors.OKBLUE, f"Je hebt geen traject_id gespecificeerd. Je invoer is leeg. ", BColors.ENDC)
+ if traject_id == "":
+ print(BColors.OKBLUE, "Je hebt geen traject_id gespecificeerd. Je invoer is leeg. ", BColors.ENDC)
continue
- traject_id_is_valid = True
+ break
_append_to_db(app_settings=app_settings, key='traject_id', value=traject_id)
@@ -48,52 +47,49 @@ def is_integer(s: str) -> bool:
def _specify_signaleringswaarde(app_settings: ApplicationSettings):
- signaleringswaarde_int: Optional[int] = None
- signaleringswaarde_is_valid = False
- while signaleringswaarde_is_valid is False:
+ while True:
signaleringswaarde: str = inquirer.text(
message="Specificeer de signaleringswaarde (geheel getal boven 10). ",
).execute()
signaleringswaarde = signaleringswaarde.strip()
- if signaleringswaarde is "":
- print(BColors.OKBLUE, f"Je hebt geen signaleringswaarde gespecificeerd. Je invoer is leeg. ", BColors.ENDC)
+ if signaleringswaarde == "":
+ print(BColors.OKBLUE, "Je hebt geen signaleringswaarde gespecificeerd. Je invoer is leeg. ", BColors.ENDC)
continue
if not is_integer(s=signaleringswaarde):
- print(BColors.OKBLUE, f"Je ingevoerde signaleringswaarde is geen geheel getal.", BColors.ENDC)
+ print(BColors.OKBLUE, "Je ingevoerde signaleringswaarde is geen geheel getal.", BColors.ENDC)
continue
signaleringswaarde_int = int(signaleringswaarde)
if signaleringswaarde_int < 10:
- print(BColors.OKBLUE, f"Je ingevoerde signaleringswaarde is kleiner dan 10. ", BColors.ENDC)
+ print(BColors.OKBLUE, "Je ingevoerde signaleringswaarde is kleiner dan 10. ", BColors.ENDC)
continue
- signaleringswaarde_is_valid = True
+ break
_append_to_db(app_settings=app_settings, key='signaleringswaarde', value=signaleringswaarde_int)
def _specify_ondergrens(app_settings: ApplicationSettings, signaleringswaarde: int):
- ondergrens_int: Optional[int] = None
- ondergrens_is_valid = False
- while ondergrens_is_valid is False:
+ while True:
ondergrens: str = inquirer.text(
message="Specificeer de ondergrens (geheel getal boven 10). ",
).execute()
ondergrens = ondergrens.strip()
- if ondergrens is "":
- print(BColors.OKBLUE, f"Je hebt geen ondergrens gespecificeerd. Je invoer is leeg. ", BColors.ENDC)
+ if ondergrens == "":
+ print(BColors.OKBLUE, "Je hebt geen ondergrens gespecificeerd. Je invoer is leeg. ", BColors.ENDC)
continue
if not is_integer(s=ondergrens):
- print(BColors.OKBLUE, f"Je ingevoerde ondergrens is geen geheel getal.", BColors.ENDC)
+ print(BColors.OKBLUE, "Je ingevoerde ondergrens is geen geheel getal.", BColors.ENDC)
continue
+
ondergrens_int = int(ondergrens)
if ondergrens_int < 10:
- print(BColors.OKBLUE, f"Je ingevoerde ondergrens is kleiner dan 10. ", BColors.ENDC)
+ print(BColors.OKBLUE, "Je ingevoerde ondergrens is kleiner dan 10. ", BColors.ENDC)
continue
if ondergrens_int > signaleringswaarde:
@@ -102,7 +98,7 @@ def _specify_ondergrens(app_settings: ApplicationSettings, signaleringswaarde: i
BColors.ENDC)
continue
- ondergrens_is_valid = True
+ break
_append_to_db(app_settings=app_settings, key='ondergrens', value=ondergrens_int)
@@ -111,7 +107,7 @@ def _get_signaleringswaarde(app_settings: ApplicationSettings) -> int:
conn = sqlite3.connect(app_settings.geopackage_filepath)
cursor = conn.cursor()
cursor.execute("""
- SELECT geoprob_pipe_metadata."values"
+ SELECT geoprob_pipe_metadata.metadata_value
FROM geoprob_pipe_metadata
WHERE metadata_type='signaleringswaarde';
""")
@@ -133,34 +129,33 @@ def is_float(s: str) -> bool:
def _specify_w(app_settings: ApplicationSettings):
- w_float: Optional[float] = None
- w_is_valid = False
- while w_is_valid is False:
+
+ while True:
w: str = inquirer.text(
message="Specificeer de w (decimaal getal tussen 0.0 en 1.0). Gebruikelijke waarde is 0.24.",
).execute()
w = w.strip()
- if w is "":
- print(BColors.OKBLUE, f"Je hebt geen w gespecificeerd. Je invoer is leeg. ", BColors.ENDC)
+ if w == "":
+ print(BColors.OKBLUE, "Je hebt geen w gespecificeerd. Je invoer is leeg. ", BColors.ENDC)
continue
if not is_float(s=w):
- print(BColors.OKBLUE, f"Je ingevoerde w is geen decimaal getal.", BColors.ENDC)
+ print(BColors.OKBLUE, "Je ingevoerde w is geen decimaal getal.", BColors.ENDC)
continue
w_float = float(w)
if w_float > 1.0:
- print(BColors.OKBLUE, f"Je ingevoerde w is groter dan 1.0. Het hoort een getal tussen 0.0 en 1.0 te zijn.",
+ print(BColors.OKBLUE, "Je ingevoerde w is groter dan 1.0. Het hoort een getal tussen 0.0 en 1.0 te zijn.",
BColors.ENDC)
continue
if w_float <= 0.0:
- print(BColors.OKBLUE, f"Je ingevoerde w is kleiner of gelijk aan 0.0. "
- f"Het hoort een getal tussen 0.0 en 1.0 te zijn. ", BColors.ENDC)
+ print(BColors.OKBLUE, "Je ingevoerde w is kleiner of gelijk aan 0.0. "
+ "Het hoort een getal tussen 0.0 en 1.0 te zijn. ", BColors.ENDC)
continue
- w_is_valid = True
+ break
_append_to_db(app_settings=app_settings, key='w', value=w_float)
@@ -168,7 +163,7 @@ def _specify_w(app_settings: ApplicationSettings):
def _specify_is_bovenrivierengebied(app_settings: ApplicationSettings):
choices_list = ["Ja", "Nee"]
choice = inquirer.select(
- message=f"Is dit traject in het bovenrivierengebied?", choices=choices_list, default=choices_list[0]).execute()
+ message="Is dit traject in het bovenrivierengebied?", choices=choices_list, default=choices_list[0]).execute()
choice_bool = False
if choice == "Ja":
choice_bool = True
@@ -186,6 +181,7 @@ def added_traject_parameters(app_settings: ApplicationSettings) -> bool:
_specify_signaleringswaarde(app_settings=app_settings)
signaleringswaarde = _get_signaleringswaarde(app_settings=app_settings)
+
if "ondergrens" not in metadata_types:
_specify_ondergrens(app_settings=app_settings, signaleringswaarde=signaleringswaarde)
diff --git a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py
index f5b556a9..eb25b74a 100644
--- a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py
+++ b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py
@@ -1,16 +1,23 @@
from __future__ import annotations
-from InquirerPy import inquirer
+
+import os
import sqlite3
+import sys
from datetime import datetime
-from geoprob_pipe.cmd_app.parameter_input.expand_input_tables import run_expand_input_tables
-from geoprob_pipe.cmd_app.parameter_input.initiate_input_excel_tables import initiate_input_excel_tables
-from geoprob_pipe.cmd_app.parameter_input.input_parameter_figures import InputParameterFigures
-from geoprob_pipe.cmd_app.parameter_input.export_input_parameter_excel import export_input_parameter_tables
-from geoprob_pipe.cmd_app.parameter_input.input_parameter_tables import InputParameterTables
from typing import TYPE_CHECKING, Optional
-import os
-import sys
+
+from InquirerPy import inquirer
+
from geoprob_pipe.utils.validation_messages import BColors
+
+from .expand_input_tables import run_expand_input_tables
+from .export_input_parameter_excel import export_input_parameter_tables
+from .initiate_input_excel_tables import initiate_input_excel_tables
+from .input_parameter_figures import InputParameterFigures
+from .input_parameter_tables import InputParameterTables
+from .update_ruimtelijke_invoer import SpatialUpdateMenu
+from geoprob_pipe.cmd_app.utils.batch_input import update_batch_metadata
+
if TYPE_CHECKING:
from geoprob_pipe.cmd_app.cmd import ApplicationSettings
@@ -68,7 +75,7 @@ def inquire_if_input_figures_should_be_exported(app_settings: ApplicationSetting
elif choice == choices_list[1]:
pass # Just continue
elif choice == choices_list[2]:
- sys.exit(f"Applicatie is afgesloten.")
+ sys.exit("Applicatie is afgesloten.")
else:
raise ValueError
@@ -109,10 +116,11 @@ def _export_expanded_input(app_settings: ApplicationSettings):
# Copy template to workspace
dst_dir = os.path.join(
- app_settings.workspace_dir,
+ str(app_settings.workspace_dir),
"exports",
app_settings.datetime_stamp,
- "parameter_input_process")
+ "parameter_input_process",
+ )
os.makedirs(dst_dir, exist_ok=True)
dst_path = os.path.join(dst_dir, "expanded_parameter_input.xlsx")
if os.path.exists(dst_path):
@@ -130,76 +138,79 @@ def inquire_to_import_export_tables_and_figures_or_continue(
):
# Determine options
- choices_list = []
- if validity_raw_tables and validity_extended_tables:
- choices_list.append("Zijn de invoer tabellen zijn naar wens? Ga door naar volgende stap")
- else:
- choices_list.append(
- "Zijn de invoer tabellen zijn naar wens? Ga door naar volgende stap (n.v.t. -> invoer niet valide)")
- if validity_raw_tables:
- choices_list.append("Overzichtsfiguren van invoertabellen: Exporteren")
- choices_list.extend([
- "Invoer tabellen: Importeren vanuit Excel",
- "Invoer tabellen: Exporteren naar Excel",
- "'Expanded' parameter invoer per uittredepunt: Exporteren",
- "Toelichting per keuze optie",
- "Applicatie afsluiten"])
-
- # Provide user options
- choice = inquirer.select(
- message="Maak een keuze voor het gereedmaken van de invoertabellen.",
- choices=choices_list,
- default=choices_list[0],
- ).execute()
-
- if choice == "Zijn de invoer tabellen zijn naar wens? Ga door naar volgende stap":
- print(BColors.OKBLUE, f"✔ Parameter invoer afgerond.", BColors.ENDC)
- return
-
- elif choice == "Zijn de invoer tabellen zijn naar wens? Ga door naar volgende stap (n.v.t. -> invoer niet valide)":
- inquire_to_import_export_tables_and_figures_or_continue(
- app_settings=app_settings, tables=tables, validity_raw_tables=validity_raw_tables,
- validity_extended_tables=validity_extended_tables)
+ while True:
+ choices_list = []
+ if validity_raw_tables and validity_extended_tables:
+ choices_list.append("Zijn de invoer tabellen zijn naar wens? Ga door naar volgende stap")
+ else:
+ choices_list.append(
+ "Zijn de invoer tabellen zijn naar wens? Ga door naar volgende stap (n.v.t. -> invoer niet valide)")
+ if validity_raw_tables:
+ choices_list.append("Overzichtsfiguren van invoertabellen: Exporteren")
+ choices_list.extend([
+ "Invoer tabellen: Importeren vanuit Excel",
+ "Invoer tabellen: Exporteren naar Excel",
+ "'Expanded' parameter invoer per uittredepunt: Exporteren",
+ "Ruimtelijke invoer: Update ingevoerde lagen",
+ "Toelichting per keuze optie",
+ "Applicatie afsluiten"])
+
+ # Provide user options
+ choice = inquirer.select(
+ message="Maak een keuze voor het gereedmaken van de invoertabellen.",
+ choices=choices_list,
+ default=choices_list[0],
+ ).execute()
- elif choice == "Overzichtsfiguren van invoertabellen: Exporteren":
- obj = InputParameterFigures.populate(app_settings=app_settings, tables=tables, export=True)
- obj.run()
- inquire_to_import_export_tables_and_figures_or_continue(
- app_settings=app_settings, tables=tables, validity_raw_tables=validity_raw_tables,
- validity_extended_tables=validity_extended_tables)
-
- elif choice == "Invoer tabellen: Importeren vanuit Excel":
- process_import_input(app_settings=app_settings)
-
- elif choice == "Invoer tabellen: Exporteren naar Excel":
- process_export_input_of_db(
- app_settings=app_settings, tables=tables, validity_raw_tables=validity_raw_tables,
- validity_extended_tables=validity_extended_tables)
-
- elif choice == "'Expanded' parameter invoer per uittredepunt: Exporteren":
- _export_expanded_input(app_settings=app_settings)
- inquire_to_import_export_tables_and_figures_or_continue(
- app_settings=app_settings, tables=tables, validity_raw_tables=validity_raw_tables,
- validity_extended_tables=validity_extended_tables)
-
- elif choice == "Toelichting per keuze optie":
- print("""
+ match choice:
+
+ case "Zijn de invoer tabellen zijn naar wens? Ga door naar volgende stap":
+ print(BColors.OKBLUE, "✔ Parameter invoer afgerond.", BColors.ENDC)
+ return
+
+ case "Zijn de invoer tabellen zijn naar wens? Ga door naar volgende stap (n.v.t. -> invoer niet valide)":
+ continue
+
+ case "Overzichtsfiguren van invoertabellen: Exporteren":
+ obj = InputParameterFigures.populate(app_settings=app_settings, tables=tables, export=True)
+ obj.run()
+ continue
+
+ case "Invoer tabellen: Importeren vanuit Excel":
+ process_import_input(app_settings=app_settings)
+ continue
+
+ case "Invoer tabellen: Exporteren naar Excel":
+ process_export_input_of_db(
+ app_settings=app_settings, tables=tables, validity_raw_tables=validity_raw_tables,
+ validity_extended_tables=validity_extended_tables)
+ continue
+
+ case "'Expanded' parameter invoer per uittredepunt: Exporteren":
+ _export_expanded_input(app_settings=app_settings)
+ continue
+
+ case "Ruimtelijke invoer: Update ingevoerde lagen":
+ # Nieuw keuze menu voor de volgende:
+ menu = SpatialUpdateMenu(app_settings)
+ menu.inquire_spatial_update()
+ continue
+
+ case "Toelichting per keuze optie":
+ print("""
Invoer tabellen zijn naar wens, ga door naar volgende stap -> Indien je deze keuzemogelijkheid krijgt zijn de invoertabellen valide en kun je door naar de volgende stap.
Je zegt daarmee eveneens dat de invoertabellen naar wens zijn.
Overzichtsfiguren van invoertabellen: Exporteren -> Deze interactive HTML-figuren geven je per parameter een snel visueel overzicht van de invoer in het GeoProb-Pipe-bestand.
Invoer tabellen: Importeren vanuit Excel -> Importeer vanuit Excel de invoertabellen om ze te laten valideren, visualiseren en/of op te slaan in het GeoProb-Pipe-bestand.
Invoer tabellen: Exporteren naar Excel -> Exporteer vanuit het GeoProb-Pipe-bestand de invoertabellen om ze in Excel te bekijken en/of verder aan te vullen.
'Expanded' parameter invoer: Exporteren -> Exporteert een Excel met de parameter invoer 'expanded' naar per uittredepunt en per scenario. 'Expanded' vanuit de invoer op verschillende niveau's.
- """)
- inquire_to_import_export_tables_and_figures_or_continue(
- app_settings=app_settings, tables=tables, validity_raw_tables=validity_raw_tables,
- validity_extended_tables=validity_extended_tables)
+Ruimtelijke invoer: Update ingevoerde lagen -> Open een keuze menu om de lagen die zijn ingevoerd voor ruimtelijke koppeling van parameters te vervangen, verwijderen of toe te voegen.
+ """)
+ continue
- elif choice == "Applicatie afsluiten":
- sys.exit(f"Applicatie is afgesloten.")
+ case "Applicatie afsluiten":
+ sys.exit("Applicatie is afgesloten.")
- else:
- raise ValueError
def export_input_tables_of_db(app_settings: ApplicationSettings, tables: InputParameterTables):
@@ -207,10 +218,7 @@ def export_input_tables_of_db(app_settings: ApplicationSettings, tables: InputPa
def import_input_tables(geopackage_filepath: str) -> InputParameterTables:
-
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
+ while True:
filepath: str = inquirer.text(
message="Specificeer het volledige bestandspad naar het input parameters Excel.",
).execute()
@@ -222,12 +230,12 @@ def import_input_tables(geopackage_filepath: str) -> InputParameterTables:
f"{os.path.basename(filepath)} eindigt niet op deze extensie.", BColors.ENDC)
continue
if not os.path.exists(filepath):
- print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
+ print(BColors.WARNING, "Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
continue
- filepath_is_valid = True
+ break
- tables = InputParameterTables(path_to_excel=filepath, geopackage_filepath=geopackage_filepath)
+ tables = InputParameterTables(path_to_excel=filepath, geopackage_filepath=geopackage_filepath) # type:ignore
print(f"{BColors.UNDERLINE}Tabellen zijn nu geïmporteerd.{BColors.ENDC}")
return tables
@@ -267,7 +275,7 @@ def process_input_exist_in_db(app_settings: ApplicationSettings):
validity_raw_tables = validate_raw_input_tables(app_settings=app_settings, tables=tables)
# Validate expanded tables
- validity_extended_tables: Optional[bool] = None
+ validity_extended_tables: bool = False
if validity_raw_tables:
validity_extended_tables = validate_expanded_input_tables(app_settings=app_settings, tables=tables)
@@ -282,10 +290,6 @@ def process_export_input_of_db(
app_settings: ApplicationSettings, tables: InputParameterTables,
validity_raw_tables: bool, validity_extended_tables: bool):
export_input_tables_of_db(app_settings=app_settings, tables=tables)
- inquire_to_import_export_tables_and_figures_or_continue(
- app_settings=app_settings, tables=tables, validity_raw_tables=validity_raw_tables,
- validity_extended_tables=validity_extended_tables)
- # -> Redirects also to new process loop
def process_import_input(app_settings: ApplicationSettings):
@@ -296,21 +300,23 @@ def process_import_input(app_settings: ApplicationSettings):
validity_raw_tables = validate_raw_input_tables(app_settings=app_settings, tables=tables)
# Ask to export overview pictures
- if validity_raw_tables: inquire_if_input_figures_should_be_exported(app_settings=app_settings, tables=tables)
+ if validity_raw_tables:
+ inquire_if_input_figures_should_be_exported(app_settings=app_settings, tables=tables)
# Validate expanded tables
- validity_extended_tables: Optional[bool] = None
+ validity_extended_tables: bool = False
if validity_raw_tables:
validity_extended_tables = validate_expanded_input_tables(app_settings=app_settings, tables=tables)
+ if not validity_extended_tables:
+ return
+
# Provide user with follow-up options
inquire_to_store_input_tables_to_db(app_settings=app_settings, tables=tables)
- inquire_to_import_export_tables_and_figures_or_continue(
- app_settings=app_settings, tables=tables, validity_raw_tables=validity_raw_tables,
- validity_extended_tables=validity_extended_tables)
- # -> Redirects also to new process loop
def added_input_parameter_data(app_settings: ApplicationSettings) -> bool:
+ # Batch inquiry flag is set to False if input is successful.
+ update_batch_metadata(app_settings=app_settings, value=False)
process_input_exist_in_db(app_settings=app_settings)
return True
diff --git a/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py b/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py
index a16d32c5..e3908993 100644
--- a/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py
+++ b/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py
@@ -235,7 +235,7 @@ def _gather_required_input_parameters(geopackage_filepath: str) -> List[str]:
conn = sqlite3.connect(geopackage_filepath)
cursor = conn.cursor()
cursor.execute("""
- SELECT geoprob_pipe_metadata."values"
+ SELECT geoprob_pipe_metadata.metadata_value
FROM geoprob_pipe_metadata
WHERE metadata_type='geohydrologisch_model';
""")
@@ -267,21 +267,20 @@ def _gather_required_input_parameters(geopackage_filepath: str) -> List[str]:
# return ["mv_exit", "gamma_sat_deklaag"] # TODO
# return ["gamma_sat_deklaag"] # TODO
-
def _expand(
df_parameter_invoer_combined: DataFrame, df_identifiers: DataFrame, geopackage_filepath: str
) -> Dict[str, DataFrame]:
# Add parameter invoer: op uittredepunten niveau
required_input_parameters = _gather_required_input_parameters(geopackage_filepath=geopackage_filepath)
collection_of_dfs: Dict[str, DataFrame] = {}
-
for parameter_name in required_input_parameters:
# Gather and merge input on uittredepunten / scenario-niveau
df_gather = df_parameter_invoer_combined[
(df_parameter_invoer_combined['parameter'] == parameter_name) &
(df_parameter_invoer_combined['scope'] == 'uittredepunt') &
- (df_parameter_invoer_combined['ondergrondscenario_naam'].notna())]
+ (df_parameter_invoer_combined['ondergrondscenario_naam'].notna())
+ ]
df_gather = df_gather[["scope_referentie", "ondergrondscenario_naam", "parameter_input"]]
df_gather = df_gather.rename(columns={
"scope_referentie": "uittredepunt_id",
@@ -291,23 +290,48 @@ def _expand(
df['parameter_input'] = df['parameter_input'].combine_first(
df_identifiers.copy(deep=True).merge(df_gather, on=["uittredepunt_id", "naam"], how="left")[
'parameter_input'])
+
+ # GIS spatial joins on uittredepunten / scenario-niveau
+ df_gather = df_parameter_invoer_combined[
+ (df_parameter_invoer_combined['parameter'] == parameter_name) &
+ (df_parameter_invoer_combined['scope'] == 'gis_uittredepunt') &
+ (df_parameter_invoer_combined['ondergrondscenario_naam'].notna())
+ ].copy(deep=True)
+ df_gather = df_gather[["scope_referentie", "parameter_input"]]
+ df_gather = df_gather.rename(columns={"scope_referentie": "uittredepunt_id"})
+ df['parameter_input'] = df['parameter_input'].combine_first(
+ df_identifiers.copy(deep=True).merge(df_gather, on=["uittredepunt_id"], how="left")['parameter_input'])
# Uittredepunt niveau
df_gather = df_parameter_invoer_combined[
(df_parameter_invoer_combined['parameter'] == parameter_name) &
(df_parameter_invoer_combined['scope'] == 'uittredepunt') &
- (df_parameter_invoer_combined['ondergrondscenario_naam']).isna()]
+ (df_parameter_invoer_combined['ondergrondscenario_naam']).isna() &
+ (df_parameter_invoer_combined["parameter_input"] != {})
+ ]
df_gather = df_gather[["scope_referentie", "parameter_input"]]
df_gather = df_gather.rename(columns={"scope_referentie": "uittredepunt_id"})
df['parameter_input'] = df['parameter_input'].combine_first(
df_identifiers.copy(deep=True).merge(df_gather, on=["uittredepunt_id"], how="left")['parameter_input'])
+ # GIS spatial joins on uittredepunten
+ df_gather = df_parameter_invoer_combined[
+ (df_parameter_invoer_combined['parameter'] == parameter_name) &
+ (df_parameter_invoer_combined['scope'] == 'gis_uittredepunt') &
+ (df_parameter_invoer_combined["parameter_input"] != {})
+ ].copy(deep=True)
+ df_gather = df_gather[["scope_referentie", "parameter_input"]]
+ df_gather = df_gather.rename(columns={"scope_referentie": "uittredepunt_id"})
+ df['parameter_input'] = df['parameter_input'].combine_first(
+ df_identifiers.copy(deep=True).merge(df_gather, on=["uittredepunt_id"], how="left")['parameter_input'])
+
# Vak / scenario niveau
df_gather = df_parameter_invoer_combined[
(df_parameter_invoer_combined['parameter'] == parameter_name) &
(df_parameter_invoer_combined['scope'] == 'vak') &
- (df_parameter_invoer_combined['ondergrondscenario_naam'].notna())]
+ (df_parameter_invoer_combined['ondergrondscenario_naam'].notna())
+ ]
df_gather = df_gather[["scope_referentie", "ondergrondscenario_naam", "parameter_input"]]
df_gather = df_gather.rename(columns={
"scope_referentie": "vak_id",
@@ -319,7 +343,8 @@ def _expand(
df_gather = df_parameter_invoer_combined[
(df_parameter_invoer_combined['parameter'] == parameter_name) &
(df_parameter_invoer_combined['scope'] == 'vak') &
- (df_parameter_invoer_combined['ondergrondscenario_naam'].isna())]
+ (df_parameter_invoer_combined['ondergrondscenario_naam'].isna())
+ ]
df_gather = df_gather[["scope_referentie", "parameter_input"]]
df_gather = df_gather.rename(columns={"scope_referentie": "vak_id"})
df['parameter_input'] = df['parameter_input'].combine_first(
@@ -333,14 +358,7 @@ def _expand(
traject_value = df_gather['parameter_input'].values[0]
df['parameter_input'] = df['parameter_input'].apply(lambda x: traject_value if isna(x) else x)
- # GIS spatial joins
- df_gather = df_parameter_invoer_combined[
- (df_parameter_invoer_combined['parameter'] == parameter_name) &
- (df_parameter_invoer_combined['scope'] == 'gis_uittredepunt')].copy(deep=True)
- df_gather = df_gather[["scope_referentie", "parameter_input"]]
- df_gather = df_gather.rename(columns={"scope_referentie": "uittredepunt_id"})
- df['parameter_input'] = df['parameter_input'].combine_first(
- df_identifiers.copy(deep=True).merge(df_gather, on=["uittredepunt_id"], how="left")['parameter_input'])
+
# Add to collection
collection_of_dfs[parameter_name] = df
diff --git a/geoprob_pipe/cmd_app/parameter_input/export_input_parameter_excel.py b/geoprob_pipe/cmd_app/parameter_input/export_input_parameter_excel.py
index 600ffc6e..c9e1a8bc 100644
--- a/geoprob_pipe/cmd_app/parameter_input/export_input_parameter_excel.py
+++ b/geoprob_pipe/cmd_app/parameter_input/export_input_parameter_excel.py
@@ -46,7 +46,7 @@ def export_input_parameter_tables(app_settings: ApplicationSettings, tables: Inp
conn = sqlite3.connect(app_settings.geopackage_filepath)
cursor = conn.cursor()
cursor.execute("""
- SELECT geoprob_pipe_metadata."values"
+ SELECT geoprob_pipe_metadata.metadata_value
FROM geoprob_pipe_metadata
WHERE metadata_type='geohydrologisch_model';
""")
diff --git a/geoprob_pipe/cmd_app/parameter_input/initiate_input_excel_tables.py b/geoprob_pipe/cmd_app/parameter_input/initiate_input_excel_tables.py
index ce0266e5..8fb602d2 100644
--- a/geoprob_pipe/cmd_app/parameter_input/initiate_input_excel_tables.py
+++ b/geoprob_pipe/cmd_app/parameter_input/initiate_input_excel_tables.py
@@ -47,7 +47,7 @@ def push_parameter_invoer_tabel(app_settings: ApplicationSettings):
# Exclude parameters that must be geographically added also
df_parameter_invoer = df_parameter_invoer[
- ~df_parameter_invoer["name"].isin(["L_intrede", "L_but", "L_bit", "polderpeil", "mv_exit"])]
+ ~df_parameter_invoer["name"].isin(["L_intrede", "L_but", "L_bit", "mv_exit"])]
df_parameter_invoer = _check_to_exclude_buitenwaterstand(
app_settings=app_settings, df_parameter_invoer=df_parameter_invoer)
diff --git a/geoprob_pipe/cmd_app/parameter_input/input_parameter_figures.py b/geoprob_pipe/cmd_app/parameter_input/input_parameter_figures.py
index 547e132a..ac3e6a2a 100644
--- a/geoprob_pipe/cmd_app/parameter_input/input_parameter_figures.py
+++ b/geoprob_pipe/cmd_app/parameter_input/input_parameter_figures.py
@@ -32,9 +32,9 @@ def __init__(self):
self.export_sub_dir: str = "parameter_input_process"
# Placeholders
- self.df_parameter_invoer: Optional[DataFrame] = None
+ self.df_parameter_invoer: DataFrame = DataFrame()
self.dict_vakindeling: Dict[int, Dict] = {}
- self.traject_length: Optional[float] = None
+ self.traject_length: float = 0.0
self.x_min = 0
self.x_max = 0 # Will be set
self.y_min = 0
@@ -121,7 +121,7 @@ def _get_display_values_from_row(row) -> Tuple[float, Optional[float], Optional[
elif not np.isnan(variation):
deviation_value = mean_value * variation
else:
- ValueError(f"Should have either a variation or deviation. Or maybe a bug and contact the developer.")
+ ValueError("Should have either a variation or deviation. Or maybe a bug and contact the developer.")
# Log normal
if row['distribution_type'] == 'log_normal':
@@ -152,7 +152,7 @@ def _get_display_values_from_df(
kar5pr_values = []
kar95pr_values = []
- for index, row in df.iterrows():
+ for _, row in df.iterrows():
mean_value = row['mean']
mean_values.append(mean_value)
if row['distribution_type'] == 'deterministic':
@@ -165,7 +165,7 @@ def _get_display_values_from_df(
elif not np.isnan(row['variation']):
deviation_value = mean_value * row['variation']
else:
- ValueError(f"Should have either a variation or deviation. Or maybe a bug and contact the developer.")
+ ValueError("Should have either a variation or deviation. Or maybe a bug and contact the developer.")
if row['distribution_type'] == 'log_normal':
kar5pr_values.append(calc_kar_waarde_lognormal(
mean=mean_value, sd=deviation_value, percentiel=0.05)) # TODO: Shift bepalen
@@ -185,7 +185,7 @@ def _add_geospatial_level_data(self, fig: go.Figure, parameter_name: str) -> go.
(self.df_gis_join_parameter_invoer['scope'] == 'uittredepunt')]
show_legend_item_mean = True
- for index, row in df_filter.iterrows():
+ for _, row in df_filter.iterrows():
# Skip cdf curve
if row['distribution_type'] == 'cdf_curve':
diff --git a/geoprob_pipe/cmd_app/parameter_input/input_parameter_tables.py b/geoprob_pipe/cmd_app/parameter_input/input_parameter_tables.py
index 15062cfa..390a7b80 100644
--- a/geoprob_pipe/cmd_app/parameter_input/input_parameter_tables.py
+++ b/geoprob_pipe/cmd_app/parameter_input/input_parameter_tables.py
@@ -17,7 +17,7 @@ def _load_df_correlatie_invoer_from_geopackage(geopackage_filepath: str) -> Data
# Check if table exists in geopackage (older versions don't have this)
conn = sqlite3.connect(geopackage_filepath)
cursor = conn.cursor()
- cursor.execute(f"SELECT name FROM sqlite_master WHERE type='table' AND name='correlatie_invoer';")
+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='correlatie_invoer';")
bool_table_exists = cursor.fetchone() is not None
# Return empty if not exists
@@ -70,10 +70,10 @@ class InputParameterTables:
def __init__(self, geopackage_filepath: str, path_to_excel: Optional[str] = None):
# Placeholders
- self.df_scenario_invoer: Optional[DataFrame] = None
- self.df_parameter_invoer: Optional[DataFrame] = None
- self.df_fragility_values_invoer: Optional[DataFrame] = None
- self.df_correlatie_invoer: Optional[DataFrame] = None
+ # self.df_scenario_invoer: Optional[DataFrame] = None
+ # self.df_parameter_invoer: Optional[DataFrame] = None
+ # self.df_fragility_values_invoer: Optional[DataFrame] = None
+ # self.df_correlatie_invoer: Optional[DataFrame] = None
if path_to_excel is not None:
self._load_data_from_excel(path_to_excel=path_to_excel, geopackage_filepath=geopackage_filepath)
@@ -100,5 +100,7 @@ def _load_data_from_excel(self, path_to_excel: str, geopackage_filepath: str):
self.df_correlatie_invoer = read_excel(path_to_excel, sheet_name="Correlatie invoer", header=3)
def validate_and_report(self, app_settings: ApplicationSettings) -> bool:
- if not _validate_df_parameter_invoer(df=self.df_parameter_invoer, app_settings=app_settings): return False
+ if not _validate_df_parameter_invoer(df=self.df_parameter_invoer, app_settings=app_settings):
+ return False
+
return True
diff --git a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py
new file mode 100644
index 00000000..688e09e0
--- /dev/null
+++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py
@@ -0,0 +1,521 @@
+from __future__ import annotations
+
+import sqlite3
+import sys
+from typing import TYPE_CHECKING
+
+import fiona
+from InquirerPy.prompts.input import InputPrompt
+from InquirerPy.prompts.list import ListPrompt
+
+from geoprob_pipe.cmd_app.spatial_layers import valid_parameter_list
+from geoprob_pipe.utils.validation_messages import BColors
+from geoprob_pipe.cmd_app.utils.batch_input import update_batch_metadata
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+class SpatialUpdateMenu:
+ restart_flag: bool = False
+
+ def __init__(
+ self,
+ app_settings: ApplicationSettings,
+ ) -> None:
+ """
+ Class voor alle submenus onder het aanpassen vaan de ruimtelijke invoer.
+
+ :param app_settings: Object met de instellingen van de applicatie
+ """
+ self.app_settings = app_settings
+
+ def inquire_spatial_update(
+ self,
+ ) -> None:
+ """
+ Keuzemenu voor het updaten van de ruimtelijke invoer van de .gpkg.
+
+ :param app_settings: Object met de instellingen van de applicatie
+ """
+
+
+ while True:
+ choices_list = [
+ "Vervang ingevoerde lagen",
+ "Voeg parameters toe voor ruimtelijke invoer",
+ "Verwijder parameters voor ruimtelijke invoer",
+ "Voeg scenarios toe voor ruimtelijke invoer",
+ "Verwijder scenarios voor ruimtelijke invoer",
+ ]
+
+ if self.restart_flag:
+ choices_list.append("Applicatie afsluiten na aanpassingen")
+ else:
+ choices_list.append("Ga terug naar het parameter invoer menu")
+
+ choice = ListPrompt(
+ message="Maak een keuze voor het aanpassen van de ruimtelijke invoer.",
+ choices=choices_list,
+ default=choices_list[0],
+ ).execute()
+
+ match choice:
+ case "Vervang ingevoerde lagen":
+ self.inquire_replace_layers()
+ continue
+
+ case "Voeg parameters toe voor ruimtelijke invoer":
+ self.add_parameters()
+ continue
+
+ case "Verwijder parameters voor ruimtelijke invoer":
+ self.remove_parameters()
+ continue
+
+ case "Voeg scenarios toe voor ruimtelijke invoer":
+ self.add_scenarios()
+ continue
+
+ case "Verwijder scenarios voor ruimtelijke invoer":
+ self.remove_scenarios()
+ continue
+
+ case "Applicatie afsluiten na aanpassingen":
+ sys.exit("Applicatie is afgesloten.")
+
+ case "Ga terug naar het parameter invoer menu":
+ return
+
+ def inquire_replace_layers(self) -> None:
+ """
+ Verwijder tabellen die opnieuw moeten worden ingeladen om de geopackage te
+ updaten.
+ """
+ conn = sqlite3.connect(self.app_settings.geopackage_filepath)
+
+ # Haal ruimtelijke parameters op vanuit de metadata
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_parameters",),
+ )
+ parameters: list[str] = cursor.fetchone()[0].split(", ")
+
+ conn.commit()
+ conn.close()
+
+ valid_list = valid_parameter_list(self.app_settings)
+
+ while True:
+ parameter_input: str = InputPrompt(
+ message=f"""
+De volgende parameters zijn nu aangemerkt voor ruimtelijke invoer:
+{", ".join(parameters)}
+Welke parameters wil je updaten? Geef deze met comma's gescheiden op.
+De tabellen worden verwijderd uit de geopackage zodat deze opnieuw worden ingelezen.
+Als er niets wordt opgegeven wordt je terug gestuurd naar het keuzemenu.
+"""
+ ).execute()
+
+ if parameter_input == "":
+ print(
+ BColors.OKBLUE,
+ "Geen tabellen verwijderd.",
+ BColors.ENDC,
+ )
+ return
+
+ valid_input = all(
+ [
+ param
+ for param in parameter_input.split(",")
+ if param in valid_list
+ ]
+ )
+ if not valid_input:
+ print(
+ BColors.OKBLUE,
+ f"Geen parameters toegevoegd. '{parameter_input}' bevat een ongeldige parameter.",
+ BColors.ENDC,
+ )
+ continue
+
+ break
+
+ # Verwijder uit geopackage
+ layers: list[str] = fiona.listlayers(
+ self.app_settings.geopackage_filepath
+ )
+ table_list = [
+ layer
+ for layer in layers
+ if layer.split("__")[0] in parameter_input
+ ]
+ self.remove_tables(table_list)
+ self.completed_update()
+
+ def add_parameters(self) -> None:
+ """
+ Voeg extra parameters toe voor de ruimtelijke invoer. De aanpassingen
+ kunnen pas verwerkt worden nadat de applicatie opnieuw is opgestart.
+ """
+
+ conn = sqlite3.connect(self.app_settings.geopackage_filepath)
+
+ # Haal ruimtelijke parameters op vanuit de metadata
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_parameters",),
+ )
+ current_parameters: list[str] = cursor.fetchone()[0].split(", ")
+
+ conn.commit()
+ conn.close()
+
+ # Haal lijst met geldige parameters op.
+ valid_list = valid_parameter_list(self.app_settings)
+
+ # Vraag gebruiker voor toevoegingen.
+ while True:
+ parameter_input: str = InputPrompt(
+ message=f"""
+De volgende parameters zijn nu aangemerkt voor ruimtelijke invoer:
+{", ".join(current_parameters)}
+De volgende parameters kunnen worden toegevoegd:
+{[param for param in valid_list if param not in current_parameters]}
+Welke parameters wil je hieraan toevoegen? Geef deze met comma's gescheiden op.
+Als er niets wordt opgegeven wordt je terug gestuurd naar het keuzemenu.
+"""
+ ).execute()
+
+ if parameter_input == "":
+ print(
+ BColors.OKBLUE,
+ "Geen nieuwe parameters toegevoegd.",
+ BColors.ENDC,
+ )
+ return
+
+ valid_input = all(
+ [
+ param
+ for param in parameter_input.split(",")
+ if param in valid_list
+ ]
+ )
+
+ if not valid_input:
+ print(
+ BColors.OKBLUE,
+ f"Geen parameters toegevoegd. '{parameter_input}' bevat een ongeldige parameter.",
+ BColors.ENDC,
+ )
+ continue
+
+ break
+
+ # Update metadata
+ parameters = current_parameters + parameter_input.split(",")
+ parameters = list(set(parameters)) # Verwijder dubbele waardes
+ parameters = ", ".join(parameters)
+ self.update_metadata_parameters(parameters)
+
+ self.completed_update()
+
+ def remove_parameters(self) -> None:
+ conn = sqlite3.connect(self.app_settings.geopackage_filepath)
+
+ # Haal ruimtelijke parameters op vanuit de metadata
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_parameters",),
+ )
+ parameters: list[str] = cursor.fetchone()[0].split(", ")
+
+ conn.commit()
+ conn.close()
+
+ valid_list = valid_parameter_list(self.app_settings)
+
+ while True:
+ parameter_input: str = InputPrompt(
+ message=f"""
+De volgende parameters zijn nu aangemerkt voor ruimtelijke invoer:
+{", ".join(parameters)}
+Welke parameters wil je verwijderen? Geef deze met comma's gescheiden op.
+Als er niets wordt opgegeven wordt je terug gestuurd naar het keuzemenu.
+"""
+ ).execute()
+
+ if parameter_input == "":
+ print(
+ BColors.OKBLUE,
+ "Geen parameters verwijderd.",
+ BColors.ENDC,
+ )
+ return
+
+ valid_input = all(
+ [
+ param
+ for param in parameter_input.split(",")
+ if param in valid_list
+ ]
+ )
+
+ if not valid_input:
+ print(
+ BColors.OKBLUE,
+ f"Geen parameters toegevoegd. '{parameter_input}' bevat een ongeldige parameter.",
+ BColors.ENDC,
+ )
+ continue
+
+ break
+
+ # Update metadata
+ for parameter in parameter_input.split(","):
+ parameters.remove(parameter)
+
+ updated_parameters = ", ".join(parameters)
+ self.update_metadata_parameters(updated_parameters)
+ # Verwijder uit geopackage
+ layers: list[str] = fiona.listlayers(
+ self.app_settings.geopackage_filepath
+ )
+ table_list = [
+ layer
+ for layer in layers
+ if layer.split("__")[0] in updated_parameters
+ ]
+ self.remove_tables(table_list)
+ self.completed_update()
+
+ def add_scenarios(self) -> None:
+ """
+ Voeg ondergrondscenarios toe aan de lijst. Dit betekent dat alle
+ ruimtelijke invoer opnieuw moet worden ingeladen.
+ """
+ # Haal de huidige scenarios op.
+ conn = sqlite3.connect(self.app_settings.geopackage_filepath)
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_scenarios",),
+ )
+ current_scenarios: list[str] = cursor.fetchone()[0].split(", ")
+
+ conn.commit()
+ conn.close()
+
+ # Vraag gebruiker voor toevoegingen.
+ while True:
+ scenario_input = InputPrompt(
+ message=f"""
+De volgende scenario zijn nu toegevoegd:
+{", ".join(current_scenarios)}
+Welke scenarios wil je hieraan toevoegen? Geef deze met comma's gescheiden op.
+Als er niets wordt opgegeven wordt je terug gestuurd naar het keuzemenu.
+"""
+ ).execute()
+
+ if scenario_input == "":
+ print(
+ BColors.OKBLUE,
+ "Geen nieuwe scenarios toegevoegd.",
+ BColors.ENDC,
+ )
+ return
+
+ # Update metadata
+ updated_scenarios = current_scenarios + scenario_input
+ self.update_metadata_scenarios(", ".join(updated_scenarios))
+
+ # Remove tables to recollect data.
+ self.remove_tables()
+
+ def remove_scenarios(self) -> None:
+ """
+ Verwijder ondergrondscenarios uit de lijst. Dit betekent dat alle
+ ruimtelijke invoer opnieuw moet worden ingeladen.
+ """
+ # Haal de huidige scenarios op.
+ conn = sqlite3.connect(self.app_settings.geopackage_filepath)
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_scenarios",),
+ )
+ current_scenarios: list[str] = cursor.fetchone()[0].split(", ")
+
+ conn.commit()
+ conn.close()
+
+ # Vraag gebruiker voor toevoegingen.
+ while True:
+ scenario_input = InputPrompt(
+ message=f"""
+De volgende scenario zijn nu toegevoegd:
+{", ".join(current_scenarios)}
+Welke scenarios wil je verwijderen? Geef deze met comma's gescheiden op.
+Als er niets wordt opgegeven wordt je terug gestuurd naar het keuzemenu.
+"""
+ ).execute()
+
+ if scenario_input == "":
+ print(
+ BColors.OKBLUE,
+ "Geen scenarios verwijderd.",
+ BColors.ENDC,
+ )
+ return
+
+ # Update metadata
+ for scenario in scenario_input.split(","):
+ if scenario in current_scenarios:
+ current_scenarios.remove(scenario)
+ else:
+ print(
+ BColors.WARNING,
+ f"Scenario {scenario} niet gevonden.",
+ BColors.ENDC,
+ )
+
+ self.update_metadata_scenarios(", ".join(current_scenarios))
+
+ # Remove tables to recollect data.
+ self.remove_tables()
+
+ def update_metadata_scenarios(self, scenarios: str) -> None:
+ """
+ Update de ondergrondscenarios in de metadata.
+ :param scenarios: Nieuwe versie van de scenariios string voor in de metadata.
+ """
+ conn = sqlite3.connect(self.app_settings.geopackage_filepath)
+
+ sql_update = "UPDATE geoprob_pipe_metadata SET metadata_value = ? WHERE metadata_type = ?"
+
+ with conn: # transaction
+ conn.execute(sql_update, (scenarios, "ruimtelijke_scenarios"))
+
+ conn.commit()
+ conn.close()
+
+ def update_metadata_parameters(self, parameters: str) -> None:
+ """
+ Update de parameters voor ruimtelijke invoer in de metadata.
+
+ :param parameters: nieuwe versie van de parameters string voor in de metadata
+ """
+ conn = sqlite3.connect(self.app_settings.geopackage_filepath)
+
+ sql_update = "UPDATE geoprob_pipe_metadata SET metadata_value = ? WHERE metadata_type = ?"
+ sql_insert = "INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES (?, ?)"
+
+ with conn: # transaction
+ cur = conn.execute(
+ sql_update, (parameters, "ruimtelijke_parameters")
+ ) # type:ignore
+ if cur.rowcount == 0:
+ conn.execute(
+ sql_insert, ("ruimtelijke_parameters", parameters)
+ ) # type:ignore
+
+ conn.commit()
+ conn.close()
+
+ def remove_tables(self, table_list: list[str] = []) -> None:
+ """
+ Verwijder de tabellen uit de geopackage en de metadata zodat deze opnieuw
+ kunnen worden ingeladen. Als de lijst leeg is worden alle tabellen met
+ ruimtelijke invoer verwijderd.
+
+ :param table_list: Lijst met tabellen om te verwijderen, defaults to []
+ """
+ update_batch_metadata(self.app_settings, value=True)
+ # Voor vervangen, nieuwe scenarios of verwijderen van parameters.
+ conn = sqlite3.connect(self.app_settings.geopackage_filepath)
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_parameters",),
+ )
+
+ parameters: list[str] = cursor.fetchone()[0].split(", ")
+ parameters.append("intredelijn")
+ layers: list[str] = fiona.listlayers(
+ self.app_settings.geopackage_filepath
+ )
+
+ if table_list == []: # Remove all spatial input
+ for layer in layers:
+ if layer.split("__")[0] in parameters:
+ cursor.execute(f"DROP TABLE IF EXISTS {layer}")
+ cursor.execute(
+ "DELETE FROM gpkg_contents WHERE table_name = ?",
+ (layer,),
+ )
+ cursor.execute(
+ "DELETE FROM gpkg_geometry_columns WHERE table_name = ?",
+ (layer,),
+ )
+ cursor.execute(
+ "DELETE FROM gpkg_tile_matrix_set WHERE table_name = ?",
+ (layer,),
+ )
+ cursor.execute(
+ "DELETE FROM gpkg_tile_matrix WHERE table_name = ?",
+ (layer,),
+ )
+
+ else:
+ for layer in table_list:
+ if layer in layers:
+ cursor.execute(f"DROP TABLE IF EXISTS {layer}")
+ cursor.execute(
+ "DELETE FROM gpkg_contents WHERE table_name = ?",
+ (layer,),
+ )
+ cursor.execute(
+ "DELETE FROM gpkg_geometry_columns WHERE table_name = ?",
+ (layer,),
+ )
+ cursor.execute(
+ "DELETE FROM gpkg_tile_matrix_set WHERE table_name = ?",
+ (layer,),
+ )
+ cursor.execute(
+ "DELETE FROM gpkg_tile_matrix WHERE table_name = ?",
+ (layer,),
+ )
+
+ conn.commit()
+ conn.close()
+
+ def completed_update(self) -> None:
+ """
+ Na aanpassing van de opties moet de applicatie opnieuw opstarten. Bied
+ de optie om meerdere aanpassingen te doen voordat de applicatie wordt
+ afgesloten.
+ """
+ choices_list = ["Andere aanpassing uitvoeren", "Applicatie afsluiten"]
+ while True:
+ choice = ListPrompt(
+ message=(
+ "Om de aanpassingen te verwerken moet de applicatie opnieuw worden gestart. "
+ "Het is mogelijk om meerdere aanpassingen in een keer te doen."
+ ),
+ choices=choices_list,
+ default=choices_list[0],
+ ).execute()
+
+ match choice:
+ case "Andere aanpassing uitvoeren":
+ self.restart_flag = True
+ return
+
+ case "Applicatie afsluiten":
+ sys.exit("Applicatie is afgesloten.")
diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py
index 34523218..573cdfa2 100644
--- a/geoprob_pipe/cmd_app/questionnaire.py
+++ b/geoprob_pipe/cmd_app/questionnaire.py
@@ -1,55 +1,112 @@
from __future__ import annotations
-from geoprob_pipe.cmd_app.general.project import created_project
-from geoprob_pipe.cmd_app.general.geohydrologisch_model import created_model
-from geoprob_pipe.cmd_app.spatial_layers import (
- added_dijktraject, added_vakindeling, added_uittredepunten, added_polderpeil, added_binnenteenlijn,
- added_buitenteenlijn, added_intredelijn, added_ahn, added_hrd_fragility_curves)
-from geoprob_pipe.cmd_app.spatial_joins import (
- coupled_hrd_to_uittredepunten, coupled_distances_to_uittredepunten, coupled_polderpeil_to_uittredepunten,
- coupled_uittredepunten_to_refline, coupled_uittredepunten_to_vakken, coupled_mv_exit_to_gis_parameter_invoer_table)
-from geoprob_pipe.cmd_app.general.traject_parameters import added_traject_parameters
-from geoprob_pipe.cmd_app.parameter_input.added_input_parameters import added_input_parameter_data
+
+import sys
from typing import TYPE_CHECKING
+
+from geoprob_pipe.cmd_app.general.geohydrologisch_model import created_model
+from geoprob_pipe.cmd_app.general.project import created_project
+from geoprob_pipe.cmd_app.general.traject_parameters import (
+ added_traject_parameters,
+)
+from geoprob_pipe.cmd_app.parameter_input.added_input_parameters import (
+ added_input_parameter_data,
+)
from geoprob_pipe.cmd_app.run_calculations.run import run_calculations
-import sys
+from geoprob_pipe.cmd_app.spatial_joins import (
+ coupled_distances_to_uittredepunten,
+ coupled_hrd_to_uittredepunten,
+ coupled_mv_exit_to_gis_parameter_invoer_table,
+ coupled_parameters_to_uittredepunten,
+ coupled_uittredepunten_to_refline,
+ coupled_uittredepunten_to_vakken,
+)
+from geoprob_pipe.cmd_app.spatial_layers import (
+ added_ahn,
+ added_binnenteenlijn,
+ added_buitenteenlijn,
+ added_dijktraject,
+ added_hrd_fragility_curves,
+ added_intredelijn,
+ added_parameters,
+ added_ruimtelijke_input,
+ added_scenarios,
+ added_uittredepunten,
+ added_vakindeling,
+ check_batch_input,
+)
+
if TYPE_CHECKING:
from geoprob_pipe.cmd_app.cmd import ApplicationSettings
-EARLY_EXIT_MESSAGE = f"Applicatie vroegtijdig afgesloten"
+EARLY_EXIT_MESSAGE = "Applicatie vroegtijdig afgesloten"
def start_questionnaire(app_settings: ApplicationSettings):
- if not created_project(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
+ if not created_project(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
questionnaire(app_settings=app_settings)
def questionnaire(app_settings: ApplicationSettings):
- print(f"\nALGEMEEN")
- if not created_model(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
-
- print(f"\nGIS LAGEN")
- if not added_dijktraject(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not added_vakindeling(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not added_hrd_fragility_curves(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not added_traject_parameters(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not added_uittredepunten(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not added_polderpeil(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not added_binnenteenlijn(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not added_buitenteenlijn(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not added_intredelijn(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- added_ahn(app_settings=app_settings, display_added_msg=True) # AHN may be optional
-
- print(f"\nGEOGRAFISCHE KOPPELINGEN")
- if not coupled_uittredepunten_to_refline(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not coupled_hrd_to_uittredepunten(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not coupled_distances_to_uittredepunten(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not coupled_polderpeil_to_uittredepunten(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not coupled_uittredepunten_to_vakken(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
- if not coupled_mv_exit_to_gis_parameter_invoer_table(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
-
- print(f"\nPARAMETER INVOER")
- if not added_input_parameter_data(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
-
- print(f"\nBEREKENINGEN UITVOEREN")
- if not run_calculations(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE)
+ print("\nALGEMEEN")
+ if not created_model(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not added_scenarios(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not added_parameters(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not check_batch_input(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+
+ print("\nGIS LAGEN")
+ if not added_dijktraject(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not added_vakindeling(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not added_hrd_fragility_curves(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not added_traject_parameters(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not added_uittredepunten(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not added_binnenteenlijn(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not added_buitenteenlijn(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not added_intredelijn(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+
+ print("\nRUIMTELIJKE INPUT")
+ # Loop voor alle parameters
+ if not added_ruimtelijke_input(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ added_ahn(
+ app_settings=app_settings, display_added_msg=True
+ ) # AHN may be optional
+
+ print("\nGEOGRAFISCHE KOPPELINGEN")
+ if not coupled_uittredepunten_to_refline(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not coupled_distances_to_uittredepunten(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not coupled_uittredepunten_to_vakken(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not coupled_hrd_to_uittredepunten(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ if not coupled_mv_exit_to_gis_parameter_invoer_table(
+ app_settings=app_settings
+ ):
+ sys.exit(EARLY_EXIT_MESSAGE)
+ # TODO Later Should: make coupling for raster if import is added.
+ if not coupled_parameters_to_uittredepunten(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+
+ print("\nPARAMETER INVOER")
+ # TODO VJ: Vraag CP waar de traject defaults automatisch verwijderd worden
+ if not added_input_parameter_data(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
+
+ print("\nBEREKENINGEN UITVOEREN")
+ if not run_calculations(app_settings=app_settings):
+ sys.exit(EARLY_EXIT_MESSAGE)
diff --git a/geoprob_pipe/cmd_app/run_calculations/run.py b/geoprob_pipe/cmd_app/run_calculations/run.py
index 7c9ae18c..0663988d 100644
--- a/geoprob_pipe/cmd_app/run_calculations/run.py
+++ b/geoprob_pipe/cmd_app/run_calculations/run.py
@@ -40,9 +40,7 @@ def _convert_vak_ids_str_to_ints(input_str: str) -> Tuple[List[int], List[str]]:
return list(set(list_vak_ids_int)), unknown_inputs
def request_vakken_to_run() -> str:
- list_vak_ids_int: List[int] = []
- vakken_input_is_valid = False
- while vakken_input_is_valid is False:
+ while True:
vakken_input: str = inquirer.text(
message="Specificeer welke vakken je wilt doorrekenen. Doe dit door comma-separated de vak nummers (id) "
"op te geven. Bijvoorbeeld '4,5,6,7,10-15'.",
@@ -62,7 +60,7 @@ def request_vakken_to_run() -> str:
f"Probeer opnieuw.{BColors.ENDC}")
continue
- vakken_input_is_valid = True
+ break
return f"vakken:{','.join([str(item) for item in list_vak_ids_int])}"
@@ -82,7 +80,7 @@ def run_calculations(app_settings: ApplicationSettings) -> bool:
if choice == choices_list[0]:
geoprob_pipe = GeoProbPipe(app_settings)
geoprob_pipe.export_archive()
- print(BColors.OKBLUE, f"✅ Berekeningen zijn uitgevoerd.", BColors.ENDC)
+ print(BColors.OKBLUE, "✅ Berekeningen zijn uitgevoerd.", BColors.ENDC)
elif choice == choices_list[1]:
vakken_str: str = request_vakken_to_run()
app_settings.to_run = vakken_str
@@ -91,7 +89,7 @@ def run_calculations(app_settings: ApplicationSettings) -> bool:
print(BColors.OKBLUE, f"✅ Berekeningen zijn uitgevoerd, voor vakken "
f"{app_settings.to_run.replace("vakken:", "")}.", BColors.ENDC)
elif choice == choices_list[2]:
- sys.exit(f"Applicatie is afgesloten.")
+ sys.exit("Applicatie is afgesloten.")
else:
raise ValueError
return True
diff --git a/geoprob_pipe/cmd_app/spatial_joins/__init__.py b/geoprob_pipe/cmd_app/spatial_joins/__init__.py
index 73a4725f..0527ff01 100644
--- a/geoprob_pipe/cmd_app/spatial_joins/__init__.py
+++ b/geoprob_pipe/cmd_app/spatial_joins/__init__.py
@@ -1,7 +1,8 @@
-from geoprob_pipe.cmd_app.spatial_joins.coupled_hrd import coupled_hrd_to_uittredepunten
-from geoprob_pipe.cmd_app.spatial_joins.coupled_distance_to_exit_points import (
- coupled_distances_to_uittredepunten)
-from geoprob_pipe.cmd_app.spatial_joins.coupled_polderpeil import coupled_polderpeil_to_uittredepunten
-from geoprob_pipe.cmd_app.spatial_joins.coupled_exit_points_to_refline import coupled_uittredepunten_to_refline
-from geoprob_pipe.cmd_app.spatial_joins.coupled_exit_points_to_vakken import coupled_uittredepunten_to_vakken
-from geoprob_pipe.cmd_app.spatial_joins.coupled_mv_exit import coupled_mv_exit_to_gis_parameter_invoer_table
+from .distance import (
+ coupled_distances_to_uittredepunten,
+)
+from .refline import coupled_uittredepunten_to_refline
+from .vakken import coupled_uittredepunten_to_vakken
+from .hrd import coupled_hrd_to_uittredepunten
+from .mv_exit import coupled_mv_exit_to_gis_parameter_invoer_table
+from .parameters import coupled_parameters_to_uittredepunten
diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/__init__.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py
new file mode 100644
index 00000000..ab889d7e
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py
@@ -0,0 +1,168 @@
+from __future__ import annotations
+
+import datetime
+import sqlite3
+from typing import TYPE_CHECKING
+
+import numpy as np
+import pandas as pd
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+class BaseCouple:
+ """
+ Base class voor het koppelen van GIS-kagen aan de uittredepunten en deze op
+ de correcte manier toe te voegen aan de geopackage.
+ """
+
+ # Placeholders
+ app_settings: ApplicationSettings
+ param: str
+
+ def _create_df(self, join_df: pd.DataFrame, scenario: str) -> pd.DataFrame:
+ """
+ Maak de dataframe die moet worden toegevoegd aan de geopackage.
+ Als er geen waarde is wordt een default gebruikt.
+
+ :param join_df: DataFrame met de data uit de join.
+ :param scenario: Ondergrondscenario_naam voor in de dataframe. Kan "" zijn.
+ :return: Dataframe met juiste kolommen.
+ """
+ df = join_df[["uittredepunt_id"]].copy()
+ df = df.rename(columns={"uittredepunt_id": "scope_referentie"})
+ df["parameter"] = self.param
+ df["scope"] = "uittredepunt"
+ df["ondergrondscenario_naam"] = scenario
+ df["distribution_type"] = join_df.get(f"{self.param}__dist", "deterministic")
+ df["mean"] = join_df.get(f"{self.param}__mean", np.nan)
+ df["variation"] = join_df.get(f"{self.param}__var", np.nan)
+ df["deviation"] = join_df.get(f"{self.param}__dev", np.nan)
+ df["minimum"] = join_df.get(f"{self.param}__min", np.nan)
+ df["maximum"] = join_df.get(f"{self.param}__max", np.nan)
+ df["fragility_values_ref"] = ""
+ df["bronnen"] = ""
+ df["opmerking"] = ""
+
+ # Sort columns
+ df = df[
+ [
+ "parameter",
+ "scope",
+ "scope_referentie",
+ "ondergrondscenario_naam",
+ "distribution_type",
+ "mean",
+ "variation",
+ "deviation",
+ "minimum",
+ "maximum",
+ "fragility_values_ref",
+ "bronnen",
+ "opmerking",
+ ]
+ ]
+ return df
+
+ def _upsert_to_gpkg(self, df: pd.DataFrame):
+ """
+ Voeg de dataframe toe aan de tabel. Als de tabel nog niet bestaat
+ wordt deze op de correcte manier opgezet. Met een unique verzameling
+ waarden of te kunnen overschrijven. Om te zorgen dat de tabel geschikt
+ is voor een upsert moet er een set van kolommen uniek zijn. Dit is
+ lastiger om automatisch te doen met `.to_sql`. Hier wordt de tabel
+ ook handmatig toegevoegd aan gpkg_contents.
+
+ :param df: DataFrame met juiste kolommen.
+ """
+ conn = sqlite3.connect(self.app_settings.geopackage_filepath)
+ cursor = conn.cursor()
+ cursor.execute(
+ """
+ CREATE TABLE IF NOT EXISTS gis_join_parameter_invoer (
+ parameter TEXT,
+ scope TEXT,
+ scope_referentie INTEGER,
+ ondergrondscenario_naam TEXT,
+ distribution_type TEXT,
+ mean REAL,
+ variation REAL,
+ deviation REAL,
+ minimum REAL,
+ maximum REAL,
+ fragility_values_ref TEXT,
+ bronnen TEXT,
+ opmerking TEXT,
+ UNIQUE(parameter, scope, scope_referentie, ondergrondscenario_naam)
+ )
+ """
+ )
+ data = [tuple(row) for row in df.to_numpy()]
+ placeholders = ", ".join(["?"] * 13)
+ # UPSERT naar tabel
+ cursor.executemany(
+ f"""
+ INSERT INTO gis_join_parameter_invoer (
+ parameter,
+ scope,
+ scope_referentie,
+ ondergrondscenario_naam,
+ distribution_type,
+ mean,
+ variation,
+ deviation,
+ minimum,
+ maximum,
+ fragility_values_ref,
+ bronnen,
+ opmerking
+ )
+ VALUES ({placeholders})
+ ON CONFLICT (
+ parameter, scope, scope_referentie, ondergrondscenario_naam
+ ) DO UPDATE SET
+ distribution_type = excluded.distribution_type,
+ mean = excluded.mean,
+ variation = excluded.variation,
+ deviation = excluded.deviation,
+ minimum = excluded.minimum,
+ maximum = excluded.maximum,
+ fragility_values_ref = excluded.fragility_values_ref,
+ bronnen = excluded.bronnen,
+ opmerking = excluded.opmerking
+ """,
+ data,
+ )
+ # UPSERT naar gpkg_contents, vereist in gpkg om leesbaar te zijn
+ # voor GIS software
+ content = (
+ "gis_join_parameter_invoer",
+ "attributes",
+ "gis_join_parameter_invoer",
+ "",
+ datetime.datetime.now(),
+ 0,
+ )
+ cursor.execute(
+ """
+ INSERT INTO gpkg_contents (
+ table_name,
+ data_type,
+ identifier,
+ description,
+ last_change,
+ srs_id
+ ) VALUES (?, ?, ?, ?, ?, ?)
+ ON CONFLICT (identifier) DO UPDATE SET
+ table_name = excluded.table_name,
+ data_type = excluded.data_type,
+ description = excluded.description,
+ last_change = excluded.last_change,
+ srs_id = excluded.srs_id
+ """,
+ content
+ )
+
+ conn.commit()
+ conn.close()
\ No newline at end of file
diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance.py
new file mode 100644
index 00000000..dfa96ac6
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance.py
@@ -0,0 +1,37 @@
+from __future__ import annotations
+
+import pandas as pd
+from typing import TYPE_CHECKING
+
+from .base import BaseCouple
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+class DistCouple(BaseCouple):
+ def __init__(
+ self, app_settings: ApplicationSettings, param: str, df: pd.DataFrame
+ ) -> None:
+ """
+ Class om de afstand tussen de uittredepunten en de lijnen toe te voegen
+ aan de geopackage.
+
+ :param app_settings: Object met alle settings van de applicatie.
+ :param str param: De parameter die wordt toegevoegd aan de tabel.
+ :param pd.DataFrame df: Dataframe met de waardes per uittredepunt
+ """
+ self.app_settings = app_settings
+ self.param = param
+ self.df = df
+
+ def couple_exit_points(self, scenario: str = ""):
+ """
+ Methode voer het correct opstellen van de dataframe en deze aan de
+ geopackage toe te voegen.
+
+ :param str scenario: Naam van het ondergrondscenario waar deze waardes voor
+ gelden, defaults to ""
+ """
+ df_to_add = self._create_df(self.df, scenario=scenario)
+ self._upsert_to_gpkg(df_to_add)
diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py
new file mode 100644
index 00000000..10dbd500
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py
@@ -0,0 +1,85 @@
+"""
+Class voor het koppelen van de HRD-locaties aan de uittredepunten.
+Versimpelde versie van de ShapeCouple class.
+"""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+import geopandas as gpd
+import pandas as pd
+import numpy as np
+
+from .base import BaseCouple
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+class HRDCouple(BaseCouple):
+ def __init__(self, app_settings: ApplicationSettings) -> None:
+ """
+ Class voor het koppelen van de hrd locatie namen aan de uittredepunten.
+
+ :param app_settings: Object met de settings van de applicatie.
+ """
+ self.app_settings = app_settings
+
+ def couple_exit_points(self) -> None:
+ """
+ Koppel de hrd_locaties aan de uittredepunten. En voeg deze toe aan de
+ geopackage op de juiste manier.
+ """
+ # Read uittredepunten
+ gdf_exit_points: gpd.GeoDataFrame = gpd.read_file(
+ self.app_settings.geopackage_filepath, layer="uittredepunten"
+ )
+ gdf_hrd: gpd.GeoDataFrame = gpd.read_file(
+ self.app_settings.geopackage_filepath, layer="hrd_locaties"
+ )
+ join_df = gdf_exit_points.sjoin_nearest(gdf_hrd, how="left")
+ df_to_add = self._create_df_hrd(join_df)
+ self._upsert_to_gpkg(df_to_add)
+
+ def _create_df_hrd(self, join_df: pd.DataFrame) -> pd.DataFrame:
+ """
+ Methode om de dataframe op te zetten voor de hrd locatie invoer.
+
+ :param join_df: _description_
+ :return: _description_
+ """
+ df = join_df[["uittredepunt_id"]].copy()
+ df = df.rename(columns={"uittredepunt_id": "scope_referentie"})
+ df["parameter"] = "buitenwaterstand"
+ df["scope"] = "uittredepunt"
+ df["ondergrondscenario_naam"] = ""
+ df["distribution_type"] = "cdf_curve"
+ df["mean"] = np.nan
+ df["variation"] = np.nan
+ df["deviation"] = np.nan
+ df["minimum"] = np.nan
+ df["maximum"] = np.nan
+ df["fragility_values_ref"] = join_df.get("location_name", "")
+ df["bronnen"] = ""
+ df["opmerking"] = ""
+
+ # Sort columns
+ df = df[
+ [
+ "parameter",
+ "scope",
+ "scope_referentie",
+ "ondergrondscenario_naam",
+ "distribution_type",
+ "mean",
+ "variation",
+ "deviation",
+ "minimum",
+ "maximum",
+ "fragility_values_ref",
+ "bronnen",
+ "opmerking",
+ ]
+ ]
+ return df
diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py
new file mode 100644
index 00000000..faa4d382
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py
@@ -0,0 +1,167 @@
+from __future__ import annotations
+
+import sqlite3
+from typing import TYPE_CHECKING
+
+import geopandas as gpd
+
+from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS
+from geoprob_pipe.utils.validation_messages import BColors
+
+from .base import BaseCouple
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+class ShapeCouple(BaseCouple):
+ def __init__(self, app_settings: ApplicationSettings, param: str) -> None:
+ """
+ Class om de uittredepunten te koppelen aan een gis-laag vanuit de geopackage.
+ De gekoppelde waarden worden weggeschreven in de tabel 'gis_join_parameter_invoer'.
+
+ :param app_settings: `ApplicationSettings` object.
+ :param param: Parameter die gekoppeld moet worden.
+ """
+ self.app_settings = app_settings
+ self.param = param
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+ cursor = conn.cursor()
+ # Get scenarios to add
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_scenarios",),
+ )
+ self.scenarios: list[str] = cursor.fetchone()[0].split(", ")
+
+ # Get table names
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type=?;", ("table",)
+ )
+ self.tables_names: list[str] = [row[0] for row in cursor.fetchall()]
+ conn.close()
+
+ def couple_exit_points(self):
+ """
+ Lees de uittredepunten uit de geopackage en bepaal of er meerdere scenarios
+ zijn om toe te voegen.
+
+ :raises KeyError: Als de parameter tabel niet wordt gevonden.
+ """
+ # Read uittredepunten
+ self.gdf_exit_points: gpd.GeoDataFrame = gpd.read_file(
+ self.app_settings.geopackage_filepath, layer="uittredepunten"
+ )
+
+ self.param_tables = [
+ table
+ for table in self.tables_names
+ if table.split("__")[0] == self.param
+ ]
+
+ if len(self.param_tables) == 0:
+ raise KeyError(
+ f"{self.param} niet gevonden in de tabellen van de geopackage."
+ )
+
+ elif len(self.param_tables) == 1:
+ # Geen invoer per scenario
+ self._add_single_layer()
+
+ else:
+ # Invoer per scenario
+ self._add_multiple_layers()
+
+ def _add_single_layer(self):
+ """
+ Voeg een laag toe via koppeling, met de uittredepunten als er geen
+ ruimtelijke scenarios zijn voor de parameter.
+ """
+ gdf_parameter: gpd.GeoDataFrame = gpd.read_file(
+ self.app_settings.geopackage_filepath, layer=f"{self.param}"
+ )
+ self._check_shape(gdf_parameter)
+
+ def _add_multiple_layers(self):
+ """
+ Voeg de lagen een voor een toe als er ruimtelijke scenarios zijn voor
+ de parameter.
+ """
+ for layer in self.param_tables:
+ gdf_parameter: gpd.GeoDataFrame = gpd.read_file(
+ self.app_settings.geopackage_filepath,
+ layer=layer,
+ )
+ if len(layer.split("__")) == 2:
+ scenario = layer.split("__")[1]
+ else:
+ scenario = ""
+
+ self._check_shape(gdf_parameter, scenario)
+
+ def _check_shape(self, gdf: gpd.GeoDataFrame, scenario: str = ""):
+ """
+ Bepaal welke shapes er in de laag zitten en of deze een geaccepteerde
+ optie zijn.
+
+ :param gdf: GeoDataFrame met de ruimtelijke invoer.
+ :param scenario: Ondergrondscenario_naam als invoer per scenario voor
+ deze parameters is gekozen, defaults to ""
+ :raises KeyError: Lijn niet geaccepteerd bij deze parameter.
+ :raises KeyError: Polygon niet geaccepteerd bij deze parameter.
+ :raises ImportError: De laag bestaat uit verschillende geometrie types.
+ """
+ if (gdf.geom_type.isin(["LineString", "MultiLineString"])).all():
+ if "line" in LIST_PARAMS[self.param]["shape"]:
+ self._join_to_line(gdf, scenario)
+ else:
+ raise KeyError(
+ "Deze parameter is niet geschikt om aan een lijn gekoppeld te worden."
+ )
+ elif (gdf.geom_type.isin(["Polygon", "MultiPolygon"])).all():
+ if "polygon" in LIST_PARAMS[self.param]["shape"]:
+ self._join_to_polygon(gdf, scenario)
+ else:
+ raise KeyError(
+ "Deze parameter is niet geschikt om aan een polygon gekoppeld te worden."
+ )
+ else:
+ raise ImportError(
+ "De geïmporteerde laag bestaat niet uit alleen lijnen of uit alleen polygonen."
+ )
+
+ def _join_to_line(self, gdf: gpd.GeoDataFrame, scenario: str):
+ """
+ Maak een spatial join van de uittredepunten met een lijn.
+
+ :param gdf: GeoDataFrame met de ruimtelijke invoer.
+ :param scenario: Ondergrondscenario_naam voor in de dataframe. Kan "" zijn.
+ """
+ join_gdf = self.gdf_exit_points.sjoin_nearest(gdf, how="left").drop_duplicates("uittredepunt_id")
+ df_to_add = self._create_df(join_gdf, scenario)
+
+ self._upsert_to_gpkg(df_to_add)
+
+ def _join_to_polygon(self, gdf: gpd.GeoDataFrame, scenario: str):
+ """
+ Maak een spatial join van de uittredepunten met een polygon.
+
+ :param gdf: GeoDataFrame met de ruimtelijke invoer.
+ :param scenario: Ondergrondscenario_naam voor in de dataframe. Kan "" zijn.
+ """
+ join_gdf = self.gdf_exit_points.sjoin(gdf, how="left")
+ outside = join_gdf[join_gdf.index_right.isna()]
+ if len(outside) != 0:
+ print(
+ BColors.WARNING,
+ f"{len(outside)} uittredepunten vallen buiten de polygonen bij {self.param}.",
+ BColors.ENDC
+ )
+ join_gdf = join_gdf[join_gdf.index_right.notna()]
+ df_to_add = self._create_df(join_gdf, scenario)
+
+ self._upsert_to_gpkg(df_to_add)
+
+ # TODO Later Should: Add option for raster import and coupling.
+ def _join_to_raster(self):
+ raise NotImplementedError("Toevoegen van parameters via raster is nog niet mogelijk.")
diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_distance_to_exit_points.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_distance_to_exit_points.py
deleted file mode 100644
index 7bcd785b..00000000
--- a/geoprob_pipe/cmd_app/spatial_joins/coupled_distance_to_exit_points.py
+++ /dev/null
@@ -1,59 +0,0 @@
-"""
-TODO Nu Must Klein: Voeg laag toe aan GeoPackage met visuele koppeling tussen intrede en uittredepunten.
-"""
-
-from __future__ import annotations
-from geopandas import GeoDataFrame, read_file
-from pathlib import Path
-from geoprob_pipe.cmd_app.spatial_joins.utils import append_to_gis_join_parameter_invoer_table
-from geoprob_pipe.utils.validation_messages import BColors
-from typing import TYPE_CHECKING
-if TYPE_CHECKING:
- from geoprob_pipe.cmd_app.cmd import ApplicationSettings
-
-
-def coupled_distances_to_uittredepunten(app_settings: ApplicationSettings) -> bool:
-
- # Read uittredepunten
- gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten")
-
- # Check if already added
- columns = gdf_exit_points.columns
- if "afstand_intredelijn" in columns and "afstand_buitenteenlijn" in columns and "afstand_binnenteenlijn" in columns:
- print(BColors.OKBLUE,
- f"✔ Afstanden intrede, buitenteen en binnenteen al gekoppeld aan uittredepunten.", BColors.ENDC)
- return True # Assuming already added
- # TODO: Uitfaseren dat deze kolommen gekoppeld worden aan de exit_points tabel
-
- # Distance to intredelijn
- gdf_intredelijnen: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="intredelijn")
- gdf_exit_points['afstand_intredelijn'] = gdf_exit_points.geometry.apply(
- lambda pnt: round(gdf_intredelijnen.distance(pnt).min(), 1))
- df_l_intrede = gdf_exit_points[["uittredepunt_id", "afstand_intredelijn"]]
- df_l_intrede = df_l_intrede.rename(columns={"afstand_intredelijn": "mean"})
- append_to_gis_join_parameter_invoer_table(
- df_sjoin=df_l_intrede, parameter_name="L_intrede", geopackage_filepath=app_settings.geopackage_filepath)
-
- # Distance to buitenteenlijn
- gdf_buitenteenlijnen: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="buitenteenlijn")
- gdf_exit_points['afstand_buitenteenlijn'] = gdf_exit_points.geometry.apply(
- lambda pnt: round(gdf_buitenteenlijnen.distance(pnt).min(), 1))
- df_l_but = gdf_exit_points[["uittredepunt_id", "afstand_buitenteenlijn"]]
- df_l_but = df_l_but.rename(columns={"afstand_buitenteenlijn": "mean"})
- append_to_gis_join_parameter_invoer_table(
- df_sjoin=df_l_but, parameter_name="L_but", geopackage_filepath=app_settings.geopackage_filepath)
-
- # Distance to binnenteenlijn
- gdf_binnenteenlijn: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="binnenteenlijn")
- gdf_exit_points['afstand_binnenteenlijn'] = gdf_exit_points.geometry.apply(
- lambda pnt: round(gdf_binnenteenlijn.distance(pnt).min(), 1))
- df_l_intrede = gdf_exit_points[["uittredepunt_id", "afstand_binnenteenlijn"]]
- df_l_intrede = df_l_intrede.rename(columns={"afstand_binnenteenlijn": "mean"})
- append_to_gis_join_parameter_invoer_table(
- df_sjoin=df_l_intrede, parameter_name="L_bit", geopackage_filepath=app_settings.geopackage_filepath)
-
- # Store back in geopackage
- gdf_exit_points.to_file(Path(app_settings.geopackage_filepath), layer="uittredepunten", driver="GPKG")
- print(BColors.OKBLUE,
- f"✅ Afstanden intrede, buitenteen en binnenteen zijn nu gekoppeld aan de uittredepunten.", BColors.ENDC)
- return True
diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py
deleted file mode 100644
index 371f2d16..00000000
--- a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""
-TODO Nu Must Klein: Voeg laag toe aan GeoPackage met visuele koppeling tussen HRD en uittredepunten.
-"""
-
-from __future__ import annotations
-from geopandas import GeoDataFrame, read_file
-import fiona
-from pathlib import Path
-from geoprob_pipe.cmd_app.spatial_joins.utils import append_hrd_to_gis_join_parameter_invoer_table
-from geoprob_pipe.utils.validation_messages import BColors
-from typing import TYPE_CHECKING
-if TYPE_CHECKING:
- from geoprob_pipe.cmd_app.cmd import ApplicationSettings
-
-
-def coupled_hrd_to_uittredepunten(app_settings: ApplicationSettings) -> bool:
-
- layers = fiona.listlayers(app_settings.geopackage_filepath)
-
- if "hrd_locaties" not in layers:
- return True # Geen Hydra-locatie geïmporteerd, dan ook niks koppelen.
-
- # Getting necessary GeoDataframes
- gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten")
- gdf_hrd_locations: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="hrd_locaties")
-
- # Check if already added
- if "hrd_name" in gdf_exit_points.columns:
- print(BColors.OKBLUE, f"✔ HRD-locaties al gekoppeld aan uittredepunten.", BColors.ENDC)
- return True # Assuming already added
-
- # Perform spatial join to find the nearest HRD-location for each Exit Point
- gdf_exit_with_hrd = gdf_exit_points.sjoin_nearest(
- gdf_hrd_locations[['geometry', 'location_name']], how='left', distance_col='distance')
-
- # Define which columns to keep (after spatial join)
- columns_to_keep = list(gdf_exit_points.columns)
- columns_to_keep.append("location_name")
- gdf_new_exit_points = gdf_exit_with_hrd[columns_to_keep]
- gdf_new_exit_points = gdf_new_exit_points.rename(columns={"location_name": "hrd_name"})
- append_hrd_to_gis_join_parameter_invoer_table(
- df_sjoin=gdf_new_exit_points[["uittredepunt_id", "hrd_name"]],
- geopackage_filepath=app_settings.geopackage_filepath)
-
- # Store back in geopackage
- gdf_new_exit_points.to_file(Path(app_settings.geopackage_filepath), layer="uittredepunten", driver="GPKG")
- # TODO: Uitfaseren dat HRD-koppeling middels direct aan de geometrie van het uittredepunt zit.
- print(BColors.OKBLUE, f"✅ HRD-locaties zijn nu gekoppeld aan de uittredepunten.", BColors.ENDC)
- return True
diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_polderpeil.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_polderpeil.py
index acc23c5d..0899cde0 100644
--- a/geoprob_pipe/cmd_app/spatial_joins/coupled_polderpeil.py
+++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_polderpeil.py
@@ -1,49 +1,49 @@
"""
TODO Nu Must Klein: Voeg laag toe aan GeoPackage met visuele koppeling tussen HRD en uittredepunten.
"""
-
-from __future__ import annotations
-from geopandas import GeoDataFrame, read_file
-from pathlib import Path
-from pandas import DataFrame
-from geoprob_pipe.cmd_app.spatial_joins.utils import append_to_gis_join_parameter_invoer_table
-from geoprob_pipe.utils.validation_messages import BColors
-from typing import TYPE_CHECKING
-if TYPE_CHECKING:
- from geoprob_pipe.cmd_app.cmd import ApplicationSettings
-
-
-def coupled_polderpeil_to_uittredepunten(app_settings: ApplicationSettings) -> bool:
-
-
- # Getting necessary GeoDataframes
- gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten")
- gdf_polderpeil: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="polderpeil")
-
- # Check if already added
- if "polderpeil" in gdf_exit_points.columns:
- print(BColors.OKBLUE, f"✔ Polderpeil al gekoppeld aan uittredepunten.", BColors.ENDC)
- return True # Assuming already added
-
- # Perform spatial join to find the nearest HRD-location for each Exit Point
- gdf_exit_with_hrd = gdf_exit_points.sjoin_nearest(
- gdf_polderpeil[['geometry', 'polderpeil']], how='left', distance_col='distance')
-
- # Define which columns to keep (after spatial join)
- columns_to_keep = list(gdf_exit_points.columns)
- columns_to_keep.append("polderpeil")
- gdf_new_exit_points = gdf_exit_with_hrd[columns_to_keep]
-
- # Append to new version of geospatial storage
- df_to_append: DataFrame = gdf_new_exit_points[["polderpeil", "uittredepunt_id"]]
- df_to_append = df_to_append.rename(columns={"polderpeil": "mean"})
- append_to_gis_join_parameter_invoer_table(
- df_sjoin=df_to_append,
- parameter_name="polderpeil",
- geopackage_filepath=app_settings.geopackage_filepath)
-
- # Store back in geopackage
- gdf_new_exit_points.to_file(Path(app_settings.geopackage_filepath), layer="uittredepunten", driver="GPKG")
- # TODO: Uitfaseren deze oude manier van polderpeil opslaan
- print(BColors.OKBLUE, f"✅ Polderpeil is nu gekoppeld aan de uittredepunten.", BColors.ENDC)
- return True
+# Vervallen
+# from __future__ import annotations
+# from geopandas import GeoDataFrame, read_file
+# from pathlib import Path
+# from pandas import DataFrame
+# from geoprob_pipe.cmd_app.spatial_joins.utils import append_to_gis_join_parameter_invoer_table
+# from geoprob_pipe.utils.validation_messages import BColors
+# from typing import TYPE_CHECKING
+# if TYPE_CHECKING:
+# from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+# def coupled_polderpeil_to_uittredepunten(app_settings: ApplicationSettings) -> bool:
+
+
+# # Getting necessary GeoDataframes
+# gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten")
+# gdf_polderpeil: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="polderpeil")
+
+# # Check if already added
+# if "polderpeil" in gdf_exit_points.columns:
+# print(BColors.OKBLUE, f"✔ Polderpeil al gekoppeld aan uittredepunten.", BColors.ENDC)
+# return True # Assuming already added
+
+# # Perform spatial join to find the nearest HRD-location for each Exit Point
+# gdf_exit_with_hrd = gdf_exit_points.sjoin_nearest(
+# gdf_polderpeil[['geometry', 'polderpeil']], how='left', distance_col='distance')
+
+# # Define which columns to keep (after spatial join)
+# columns_to_keep = list(gdf_exit_points.columns)
+# columns_to_keep.append("polderpeil")
+# gdf_new_exit_points = gdf_exit_with_hrd[columns_to_keep]
+
+# # Append to new version of geospatial storage
+# df_to_append: DataFrame = gdf_new_exit_points[["polderpeil", "uittredepunt_id"]]
+# df_to_append = df_to_append.rename(columns={"polderpeil": "mean"})
+# append_to_gis_join_parameter_invoer_table(
+# df_sjoin=df_to_append,
+# parameter_name="polderpeil",
+# geopackage_filepath=app_settings.geopackage_filepath)
+
+# # Store back in geopackage
+# gdf_new_exit_points.to_file(Path(app_settings.geopackage_filepath), layer="uittredepunten", driver="GPKG")
+# # TODO: Uitfaseren deze oude manier van polderpeil opslaan
+# print(BColors.OKBLUE, f"✅ Polderpeil is nu gekoppeld aan de uittredepunten.", BColors.ENDC)
+# return True
diff --git a/geoprob_pipe/cmd_app/spatial_joins/distance.py b/geoprob_pipe/cmd_app/spatial_joins/distance.py
new file mode 100644
index 00000000..0a059bb4
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_joins/distance.py
@@ -0,0 +1,116 @@
+"""
+TODO Nu Must Klein: Voeg laag toe aan GeoPackage met visuele koppeling tussen intrede en uittredepunten.
+"""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+import geopandas as gpd
+import fiona
+
+from geoprob_pipe.cmd_app.spatial_joins.couple_objects.distance import (
+ DistCouple,
+)
+from geoprob_pipe.utils.validation_messages import BColors
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def coupled_distances_to_uittredepunten(
+ app_settings: ApplicationSettings,
+) -> bool:
+ """
+ Bepaal de afstanden tussen de uittredepunten en de intrede, binnenteen en
+ buitenteenlijnen. Als deze er al in staan worden ze overschreven.
+
+ :param app_settings: Object met de instellingen van de applicatie
+ """
+
+ # Lees uittredepunten uit gpkg
+ gdf_exit_points: gpd.GeoDataFrame = gpd.read_file(
+ app_settings.geopackage_filepath, layer="uittredepunten"
+ )
+
+ # Distance to intredelijn
+ layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath)
+ # Lees de intrede lijn(en) uit. Als er meerdere zijn worden deze allemaal
+ # uitgelezen. Er kan zowel een intredelijn zonder scenario als met een scenario
+ # tegelijk zijn.
+ for layer in layers:
+ if "intredelijn" in layers: # Een intredelijn voor alle scenarios
+ gdf_intredelijnen: gpd.GeoDataFrame = gpd.read_file(
+ app_settings.geopackage_filepath, layer="intredelijn"
+ )
+ gdf_exit_points["afstand_intredelijn"] = (
+ gdf_exit_points.geometry.apply(
+ lambda pnt: round(gdf_intredelijnen.distance(pnt).min(), 1)
+ )
+ )
+ df_l_intrede = gdf_exit_points[
+ ["uittredepunt_id", "afstand_intredelijn"]
+ ]
+ df_l_intrede = df_l_intrede.rename(
+ columns={"afstand_intredelijn": "L_intrede__mean"}
+ )
+ DistCouple(
+ app_settings, "L_intrede", df_l_intrede
+ ).couple_exit_points()
+
+ # Intrede lijn per scenario
+ if len(layer.split("__")) == 2 and "intredelijn" in layer.split("__")[0]:
+ gdf_intredelijnen: gpd.GeoDataFrame = gpd.read_file(
+ app_settings.geopackage_filepath, layer=layer
+ )
+ gdf_exit_points["afstand_intredelijn"] = (
+ gdf_exit_points.geometry.apply(
+ lambda pnt: round(
+ gdf_intredelijnen.distance(pnt).min(), 1
+ )
+ )
+ )
+ df_l_intrede = gdf_exit_points[
+ ["uittredepunt_id", "afstand_intredelijn"]
+ ]
+ df_l_intrede = df_l_intrede.rename(
+ columns={"afstand_intredelijn": "L_intrede__mean"}
+ )
+ DistCouple(
+ app_settings, "L_intrede", df_l_intrede
+ ).couple_exit_points(scenario=layer.split("__")[1])
+
+ # Distance to buitenteenlijn
+ gdf_buitenteenlijnen: gpd.GeoDataFrame = gpd.read_file(
+ app_settings.geopackage_filepath, layer="buitenteenlijn"
+ )
+ gdf_exit_points["afstand_buitenteenlijn"] = gdf_exit_points.geometry.apply(
+ lambda pnt: round(gdf_buitenteenlijnen.distance(pnt).min(), 1)
+ )
+ df_l_but = gdf_exit_points[["uittredepunt_id", "afstand_buitenteenlijn"]]
+ df_l_but = df_l_but.rename(
+ columns={"afstand_buitenteenlijn": "L_but__mean"}
+ )
+
+ DistCouple(app_settings, "L_but", df_l_but).couple_exit_points()
+
+ # Distance to binnenteenlijn
+ gdf_binnenteenlijn: gpd.GeoDataFrame = gpd.read_file(
+ app_settings.geopackage_filepath, layer="binnenteenlijn"
+ )
+ gdf_exit_points["afstand_binnenteenlijn"] = gdf_exit_points.geometry.apply(
+ lambda pnt: round(gdf_binnenteenlijn.distance(pnt).min(), 1)
+ )
+ df_l_bit = gdf_exit_points[["uittredepunt_id", "afstand_binnenteenlijn"]]
+ df_l_bit = df_l_bit.rename(
+ columns={"afstand_binnenteenlijn": "L_bit__mean"}
+ )
+
+ DistCouple(app_settings, "L_bit", df_l_bit).couple_exit_points()
+
+ print(
+ BColors.OKBLUE,
+ "✔ Afstanden intrede, buitenteen en binnenteen zijn nu gekoppeld aan de uittredepunten.",
+ BColors.ENDC,
+ )
+ return True
diff --git a/geoprob_pipe/cmd_app/spatial_joins/hrd.py b/geoprob_pipe/cmd_app/spatial_joins/hrd.py
new file mode 100644
index 00000000..f375bbd9
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_joins/hrd.py
@@ -0,0 +1,33 @@
+"""
+TODO Nu Must Klein: Voeg laag toe aan GeoPackage met visuele koppeling tussen HRD en uittredepunten.
+"""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+import fiona
+from .couple_objects.hrd import HRDCouple
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def coupled_hrd_to_uittredepunten(app_settings: ApplicationSettings) -> bool:
+ """
+ Voeg de HRD locaties toe aan de invoer tabel als deze zijn opgegeven.
+ Als deze er al staan worden ze overschreven.
+
+ :param ApplicationSettings app_settings: Object met de instellingen van de applicatie
+ :return: _description_
+ :rtype: bool
+ """
+
+ layers = fiona.listlayers(app_settings.geopackage_filepath)
+
+ if "hrd_locaties" not in layers:
+ return True # Geen Hydra-locatie geïmporteerd, dan ook niks koppelen.
+
+ HRDCouple(app_settings).couple_exit_points()
+
+ return True
diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_mv_exit.py b/geoprob_pipe/cmd_app/spatial_joins/mv_exit.py
similarity index 95%
rename from geoprob_pipe/cmd_app/spatial_joins/coupled_mv_exit.py
rename to geoprob_pipe/cmd_app/spatial_joins/mv_exit.py
index 50b467cf..d1508d32 100644
--- a/geoprob_pipe/cmd_app/spatial_joins/coupled_mv_exit.py
+++ b/geoprob_pipe/cmd_app/spatial_joins/mv_exit.py
@@ -19,7 +19,7 @@ def coupled_mv_exit_to_gis_parameter_invoer_table(app_settings: ApplicationSetti
# Getting necessary GeoDataframes
gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten")
- # Append to new version of geospatial storage
+ # Append to new version of geo-spatial storage
df_to_append: DataFrame = gdf_exit_points[["mv_exit", "uittredepunt_id"]]
df_to_append = df_to_append.rename(columns={"mv_exit": "mean"})
append_to_gis_join_parameter_invoer_table(
diff --git a/geoprob_pipe/cmd_app/spatial_joins/parameters.py b/geoprob_pipe/cmd_app/spatial_joins/parameters.py
new file mode 100644
index 00000000..9f0c8059
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_joins/parameters.py
@@ -0,0 +1,35 @@
+from __future__ import annotations
+
+import sqlite3
+from typing import TYPE_CHECKING
+
+from .couple_objects.shape import ShapeCouple
+from geoprob_pipe.utils.validation_messages import BColors
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def coupled_parameters_to_uittredepunten(
+ app_settings: ApplicationSettings,
+) -> bool:
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_parameters",),
+ )
+ parameters: list[str] = cursor.fetchone()[0].split(", ")
+ conn.close()
+ if parameters == ['']: # De split maakt een lege string, als de uit de metadata gelezen string leeg is.
+ print(
+ BColors.OKBLUE,
+ "✔ Geen ruimtelijke koppelingen.",
+ BColors.ENDC,
+ )
+ return True
+
+ for parameter in parameters:
+ ShapeCouple(app_settings, parameter).couple_exit_points()
+
+ return True
diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_exit_points_to_refline.py b/geoprob_pipe/cmd_app/spatial_joins/refline.py
similarity index 100%
rename from geoprob_pipe/cmd_app/spatial_joins/coupled_exit_points_to_refline.py
rename to geoprob_pipe/cmd_app/spatial_joins/refline.py
diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_exit_points_to_vakken.py b/geoprob_pipe/cmd_app/spatial_joins/vakken.py
similarity index 100%
rename from geoprob_pipe/cmd_app/spatial_joins/coupled_exit_points_to_vakken.py
rename to geoprob_pipe/cmd_app/spatial_joins/vakken.py
diff --git a/geoprob_pipe/cmd_app/spatial_layers/__init__.py b/geoprob_pipe/cmd_app/spatial_layers/__init__.py
index 629ad723..1c5d7402 100644
--- a/geoprob_pipe/cmd_app/spatial_layers/__init__.py
+++ b/geoprob_pipe/cmd_app/spatial_layers/__init__.py
@@ -1,9 +1,18 @@
-from geoprob_pipe.cmd_app.spatial_layers.dijktraject import added_dijktraject
-from geoprob_pipe.cmd_app.spatial_layers.vakindeling import added_vakindeling
-from geoprob_pipe.cmd_app.spatial_layers.uittredepunten.uittredepunten import added_uittredepunten
-from geoprob_pipe.cmd_app.spatial_layers.hrd.hrd import added_hrd_fragility_curves
-from geoprob_pipe.cmd_app.spatial_layers.polderpeil import added_polderpeil
-from geoprob_pipe.cmd_app.spatial_layers.binnenteenlijn import added_binnenteenlijn
-from geoprob_pipe.cmd_app.spatial_layers.buitenteenlijn import added_buitenteenlijn
-from geoprob_pipe.cmd_app.spatial_layers.intredelijn import added_intredelijn
-from geoprob_pipe.cmd_app.spatial_layers.ahn import added_ahn
+# Deze twee moeten eerst om circulaire export te voorkomen.
+from .valid_parameters import valid_parameter_list, LIST_PARAMS
+from .base_inquiry import BaseInquiry
+
+from .added_ahn import added_ahn
+from .added_binnenteenlijn import added_binnenteenlijn
+from .added_buitenteenlijn import added_buitenteenlijn
+from .added_dijktraject import added_dijktraject
+from .added_intredelijn import added_intredelijn
+from .added_parameters import added_parameters
+from .added_ruimtelijke_invoer import added_ruimtelijke_input
+from .added_scenarios import added_scenarios
+from .added_vakindeling import added_vakindeling
+from .check_batch_input import check_batch_input
+from .hrd.hrd import added_hrd_fragility_curves
+from .uittredepunten.uittredepunten import added_uittredepunten
+
+
diff --git a/geoprob_pipe/cmd_app/spatial_layers/ahn.py b/geoprob_pipe/cmd_app/spatial_layers/added_ahn.py
similarity index 100%
rename from geoprob_pipe/cmd_app/spatial_layers/ahn.py
rename to geoprob_pipe/cmd_app/spatial_layers/added_ahn.py
diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py
new file mode 100644
index 00000000..4cca0ed4
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py
@@ -0,0 +1,38 @@
+"""
+TODO Later Should Klein: Controleer of de binnenteenlijn ook echt aan de binnenzijde is.
+TODO Later Should Klein: Niet voor elk geohydrologisch model is de binnen/buiten/intredelijn benodigd.
+Maak het toevoegen van deze lijnen afhankelijk van de model keuze.
+"""
+
+from __future__ import annotations
+from typing import TYPE_CHECKING
+
+import fiona
+from geoprob_pipe.utils.validation_messages import BColors
+from .base_inquiry import BaseInquiry
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def added_binnenteenlijn(app_settings: ApplicationSettings) -> bool:
+ layers = fiona.listlayers(app_settings.geopackage_filepath)
+
+ if "binnenteenlijn" in layers:
+ print(
+ BColors.OKBLUE, "✔ Binnenteenlijn al toegevoegd.", BColors.ENDC
+ )
+ return True
+
+ request_binnenteenlijn_filepath(app_settings=app_settings)
+ return True
+
+
+def request_binnenteenlijn_filepath(app_settings: ApplicationSettings):
+ binnenteenlijn_inquiry = BaseInquiry(
+ app_settings=app_settings,
+ param="binnenteenlijn",
+ specific_shape="lines",
+ single_geometry=True,
+ )
+ binnenteenlijn_inquiry.request_filepath()
diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py
new file mode 100644
index 00000000..fc327d6b
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py
@@ -0,0 +1,39 @@
+"""
+TODO Later Should Klein: Controleer of de buitenteenlijn ook echt aan de buitenzijde is.
+
+"""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+import fiona
+
+from .base_inquiry import BaseInquiry
+from geoprob_pipe.utils.validation_messages import BColors
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def added_buitenteenlijn(app_settings: ApplicationSettings) -> bool:
+ layers = fiona.listlayers(app_settings.geopackage_filepath)
+
+ if "buitenteenlijn" in layers:
+ print(
+ BColors.OKBLUE, "✔ Buitenteenlijn al toegevoegd.", BColors.ENDC
+ )
+ return True
+
+ request_buitenteenlijn_filepath(app_settings=app_settings)
+ return True
+
+
+def request_buitenteenlijn_filepath(app_settings: ApplicationSettings):
+ buitenteenlijn_inquiry = BaseInquiry(
+ app_settings=app_settings,
+ param="buitenteenlijn",
+ specific_shape="lines",
+ single_geometry=True
+ )
+ buitenteenlijn_inquiry.request_filepath()
diff --git a/geoprob_pipe/cmd_app/spatial_layers/dijktraject.py b/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py
similarity index 80%
rename from geoprob_pipe/cmd_app/spatial_layers/dijktraject.py
rename to geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py
index 18cb8a74..af304a8a 100644
--- a/geoprob_pipe/cmd_app/spatial_layers/dijktraject.py
+++ b/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py
@@ -34,8 +34,8 @@ def question_trajectory_source(app_settings: ApplicationSettings):
if choice == choices_list[0]:
with importlib.resources.path(
- package='geoprob_pipe.input_data.dijktrajecten',
- resource='dijktrajecten.shp') as shp_path:
+ 'geoprob_pipe.input_data.dijktrajecten',
+ 'dijktrajecten.shp') as shp_path:
gdf: GeoDataFrame = read_file(shp_path)
specify_single_trajectory(
app_settings, gdf=gdf, column_name="TRAJECT_ID")
@@ -45,9 +45,8 @@ def question_trajectory_source(app_settings: ApplicationSettings):
def request_trajectory_filepath(app_settings: ApplicationSettings):
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
+
+ while True:
filepath: str = inquirer.text(
message="Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase waarin de "
"referentielijn van de dijk zit.",
@@ -58,12 +57,13 @@ def request_trajectory_filepath(app_settings: ApplicationSettings):
if not (filepath.endswith(".gpkg") or filepath.endswith(".shp") or filepath.endswith(".gdb")):
print(BColors.WARNING, f"Het bestand moet of een geopackage, shapefile of geodatabase zijn. Jouw invoer "
f"eindigt op de extensie .{filepath.split(sep='.')[-1]}.", BColors.ENDC)
- continue
+
+
if not os.path.exists(filepath):
- print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
+ print(BColors.WARNING, "Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
continue
- filepath_is_valid = True
+ break
if filepath.endswith(".gdb"):
specify_geodatabase_layer(app_settings, filepath)
@@ -80,12 +80,12 @@ def request_trajectory_filepath(app_settings: ApplicationSettings):
def specify_geodatabase_layer(app_settings: ApplicationSettings, filepath: str):
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
+ while True:
layer_name: str = inquirer.text(
- message="Specificeer de layer waarin met de referentielijn van het dijktraject. Type 'listlayers' om "
- "een overzicht te krijgen van de geodatabase-layers. ",
+ message="""
+ Specificeer de layer waarin met de referentielijn van het dijktraject. Type 'listlayers' om
+ een overzicht te krijgen van de geodatabase-layers. Type 'cancel' om een ander bestand op te geven.
+ """,
).execute()
layer_names = fiona.listlayers(filepath)
@@ -94,13 +94,15 @@ def specify_geodatabase_layer(app_settings: ApplicationSettings, filepath: str):
if layer_name == "listlayers":
print(BColors.OKBLUE, f"De volgende layers zijn beschikbaar in de geodatabase: {layers_str}", BColors.ENDC)
continue
+ if layer_name == "cancel":
+ request_trajectory_filepath(app_settings)
elif layer_name not in layer_names:
print(BColors.OKBLUE, f"De layer name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
f"de geodatabase: {layers_str}", BColors.ENDC)
continue
# TODO Later Must Klein: Check dat een LineString-laag wordt opgegeven.
- layer_name_is_valid = True
+ break
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
@@ -109,12 +111,12 @@ def specify_geodatabase_layer(app_settings: ApplicationSettings, filepath: str):
def specify_geopackage_layer(app_settings: ApplicationSettings, filepath: str):
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
+ while True:
layer_name: str = inquirer.text(
- message="Specificeer de layer waarin met de referentielijn van het dijktraject. Type 'listlayers' om "
- "een overzicht te krijgen van de geopackage-layers. ",
+ message="""
+ Specificeer de layer waarin met de referentielijn van het dijktraject. Type 'listlayers' om
+ een overzicht te krijgen van de geodatabase-layers. Type 'cancel' om een ander bestand op te geven.
+ """,
).execute()
layer_names = fiona.listlayers(filepath)
@@ -123,25 +125,29 @@ def specify_geopackage_layer(app_settings: ApplicationSettings, filepath: str):
if layer_name == "listlayers":
print(BColors.OKBLUE, f"De volgende layers zijn beschikbaar in de geopackage: {layers_str}", BColors.ENDC)
continue
+ if layer_name == "cancel":
+ request_trajectory_filepath(app_settings)
+
elif layer_name not in layer_names:
print(BColors.OKBLUE, f"De layer name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
f"de geopackage: {layers_str}", BColors.ENDC)
continue
# TODO Later Must Klein: Check dat een LineString-laag wordt opgegeven.
- layer_name_is_valid = True
+ break
gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
specify_column_with_trajectory_name(app_settings, gdf)
def specify_column_with_trajectory_name(app_settings: ApplicationSettings, gdf: GeoDataFrame):
- column_name: Optional[str] = None
- column_name_is_valid = False
- while column_name_is_valid is False:
+
+ while True:
column_name: str = inquirer.text(
- message="Specificeer de kolom waarin de naam van het dijktraject staat. Type 'listcolumns' om "
- "een overzicht te krijgen van de kolommen. ",
+ message="""
+ Specificeer de kolom waarin de naam van het dijktraject staat. Type 'listcolumns' om
+ een overzicht te krijgen van de kolommen. Type 'cancel' om een ander bestand op te geven.
+ """,
).execute()
column_names = gdf.columns
@@ -150,12 +156,14 @@ def specify_column_with_trajectory_name(app_settings: ApplicationSettings, gdf:
print(BColors.OKBLUE,
f"De volgende kolommen zijn beschikbaar in de spatial layer: {columns_str}", BColors.ENDC)
continue
+ if column_name == "cancel":
+ request_trajectory_filepath(app_settings)
elif column_name not in column_names:
print(BColors.OKBLUE, f"De kolom naam '{column_name}' bestaat niet. De volgende kolommen zijn beschikbaar "
f"in de spatial layer: {columns_str}", BColors.ENDC)
continue
- column_name_is_valid = True
+ break
column_name: str
specify_single_trajectory(app_settings, gdf, column_name)
@@ -172,19 +180,18 @@ def specify_single_trajectory(app_settings: ApplicationSettings, gdf: GeoDataFra
})
gdf.to_file(app_settings.geopackage_filepath, layer="dijktraject", driver="GPKG")
- print(BColors.OKBLUE, f"✅ Trajectlijn toegevoegd.", BColors.ENDC)
+ print(BColors.OKBLUE, "✅ Trajectlijn toegevoegd.", BColors.ENDC)
return
# Multiple items in gdf? Make user select single one
- trajectory_name: Optional[str] = None
- trajectory_name_is_valid = False
- while trajectory_name_is_valid is False:
+
+ while True:
trajectory_name: str = inquirer.text(
message=f"Er zijn {gdf.__len__()} opties. Type hier welke de juiste referentielijn is. Type "
f"'listoptions' om een overzicht te krijgen van de opties.",
).execute()
- trajectory_names = gdf[column_name].values.tolist()
+ trajectory_names = gdf[column_name].values.astype(str).tolist()
trajectory_names.sort()
trajectories_str = ", ".join(trajectory_names)
if trajectory_name == "listoptions":
@@ -196,7 +203,7 @@ def specify_single_trajectory(app_settings: ApplicationSettings, gdf: GeoDataFra
f"{trajectories_str}", BColors.ENDC)
continue
- trajectory_name_is_valid = True
+ break
gdf = gdf[gdf[column_name] == trajectory_name]
gdf = gdf[[column_name, gdf.geometry.name]]
@@ -205,5 +212,5 @@ def specify_single_trajectory(app_settings: ApplicationSettings, gdf: GeoDataFra
gdf.geometry.name: "geometry",
})
gdf.to_file(app_settings.geopackage_filepath, layer="dijktraject", driver="GPKG")
- print(BColors.OKBLUE, f"✅ Trajectlijn toegevoegd.", BColors.ENDC)
+ print(BColors.OKBLUE, "✅ Trajectlijn toegevoegd.", BColors.ENDC)
return
diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py
new file mode 100644
index 00000000..993bdc33
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py
@@ -0,0 +1,36 @@
+"""
+TODO Later Should Klein: Controleer of de intredelijn ook echt aan de binnenzijde is.
+
+"""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+import fiona
+
+from .base_inquiry import BaseInquiry
+from geoprob_pipe.utils.validation_messages import BColors
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def added_intredelijn(app_settings: ApplicationSettings) -> bool:
+ layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath)
+ for layer in layers:
+ if "intredelijn" in layer.split("__")[0]:
+ print(BColors.OKBLUE, "✔ Intredelijn al toegevoegd.", BColors.ENDC)
+ return True
+
+ request_intredelijn_filepath(app_settings=app_settings)
+ return True
+
+
+def request_intredelijn_filepath(app_settings: ApplicationSettings):
+ intredelijn_inquiry = BaseInquiry(
+ app_settings=app_settings,
+ param="intredelijn",
+ specific_shape="lines",
+ )
+ intredelijn_inquiry.request_filepath()
diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py
new file mode 100644
index 00000000..bd6df504
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+import sqlite3
+from typing import TYPE_CHECKING
+
+import InquirerPy.prompts.input as prompt
+
+from geoprob_pipe.utils.validation_messages import BColors
+
+from .valid_parameters import valid_parameter_list
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def added_parameters(app_settings: ApplicationSettings):
+ """
+ Check of de parameters voor ruimtelijke invoer al zijn toegevoegd aan de metadata.
+
+ :param app_settings: `ApplicationSettings` object.
+ :return: bool
+ """
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+ cur = conn.cursor()
+ cur.execute(
+ "SELECT EXISTS (SELECT 1 FROM geoprob_pipe_metadata WHERE metadata_type = ?)",
+ ("ruimtelijke_parameters",),
+ )
+ check = cur.fetchone()[0] == 1
+ if not check:
+ request_parameters(app_settings)
+ return True
+
+
+def request_parameters(app_settings: ApplicationSettings):
+ """
+ Method voor het opvragen van de lijst met parameters waarvoor ruimtelijke
+ invoer gewenst is. Er wordt gecheckt of deze parameters ondersteund worden
+ en of deze in het gekozen model zitten.
+
+ :param app_settings: `ApplicationSettings` object.
+ """
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+
+ valid_list = valid_parameter_list(app_settings)
+
+ parameters: list[str] = []
+
+ while True:
+ parameter_input: str = prompt.InputPrompt(
+ message=(
+ """
+Specificeer welke parameters je wilt toevoegen als ruimtelijke input.
+Doe dit door de namen gescheiden met comma's op te geven.
+Type 'list' om de lijst te zien met alle parameters die invoerbaar zijn voor dit model.
+Als je geen ruimtelijke input wilt ingeven druk dan op enter zonder iets in te vullen.
+"""
+ )
+ ).execute()
+ if parameter_input == "":
+ parameters = []
+ elif parameter_input == "list":
+ params_str = ", ".join(valid_list) # type:ignore
+ print(
+ BColors.OKBLUE,
+ f"De volgende parameters zijn beschikbaar voor ruimtelijke input: {params_str}",
+ BColors.ENDC,
+ )
+ continue
+
+ else:
+ parameters = parameter_input.split(",")
+
+ if not all(param in valid_list for param in parameters):
+ print(
+ BColors.WARNING,
+ "Een of meerdere van de opgegeven parameters zijn niet geschikt voor ruimtelijke invoer.",
+ BColors.ENDC,
+ )
+ continue
+ break
+
+ sql_update = "UPDATE geoprob_pipe_metadata SET metadata_value = ? WHERE metadata_type = ?"
+ sql_insert = "INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES (?, ?)"
+
+ with conn: # transaction
+ cur = conn.execute(
+ sql_update, (", ".join(parameters), "ruimtelijke_parameters")
+ )
+ if cur.rowcount == 0:
+ conn.execute(
+ sql_insert, ("ruimtelijke_parameters", ", ".join(parameters))
+ )
+
+ conn.commit()
+ conn.close()
diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py
new file mode 100644
index 00000000..5245df7e
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py
@@ -0,0 +1,53 @@
+from __future__ import annotations
+
+import sqlite3
+from typing import TYPE_CHECKING
+
+import fiona
+
+from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS, BaseInquiry
+from geoprob_pipe.utils.validation_messages import BColors
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool:
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_parameters",),
+ )
+ parameters: list[str] = cursor.fetchone()[0].split(", ")
+ conn.close()
+
+ list_layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath)
+
+ # De split maakt één lege string als de uit de metadata gelezen string leeg is.
+ if parameters == [""]:
+ print(
+ BColors.OKBLUE,
+ "✔ Geen ruimtelijke parameter invoer.",
+ BColors.ENDC,
+ )
+ return True
+
+ for parameter in parameters:
+ if any(parameter in layer.split("__")[0] for layer in list_layers):
+ print(
+ BColors.OKBLUE,
+ f"✔ {parameter} al toegevoegd.",
+ BColors.ENDC,
+ )
+ continue
+
+ inquiry = BaseInquiry(
+ app_settings=app_settings,
+ param=f"{parameter}",
+ specific_shape=LIST_PARAMS[parameter]["shape"],
+ include_value=True,
+ )
+ inquiry.request_filepath()
+
+ return True
diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py
new file mode 100644
index 00000000..7e622c4d
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+import sqlite3
+from typing import TYPE_CHECKING
+
+from InquirerPy.prompts.input import InputPrompt
+
+from geoprob_pipe.utils.validation_messages import BColors
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def added_scenarios(app_settings: ApplicationSettings):
+ """
+ Check of de scenarios voor ruimtelijke invoer al zijn toegevoegd aan de metadata.
+
+ :param app_settings: `ApplicationSettings` object.
+ :return: bool
+ """
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+ cur = conn.cursor()
+ cur.execute(
+ "SELECT EXISTS (SELECT 1 FROM geoprob_pipe_metadata WHERE metadata_type = ?)",
+ ("ruimtelijke_scenarios",),
+ )
+ check = cur.fetchone()[0] == 1
+ if not check:
+ request_scenarios(app_settings)
+ return True
+
+
+def request_scenarios(app_settings: ApplicationSettings):
+ """
+ Vraag de mogelijke lijst van scenarios voor de ruimtelijke invoer op en voeg
+ deze toe aan de metadata.
+
+ :param app_settings: `ApplicationSettings` object.
+ """
+
+ while True:
+ scenario_input: str = InputPrompt(
+ message="""
+Specificeer welke scenarios je wilt toevoegen als ruimtelijke input.
+Doe dit door de namen gescheiden met comma's op te geven. Bijvoorbeeld: Scenario1, Scenario2.
+De scenario namen moeten als kolom in de attributes van de laag staan.
+Als je geen ruimtelijke input wilt ingeven druk dan op enter zonder iets in te vullen.
+"""
+ ).execute()
+ if scenario_input == "":
+ scenarios = ""
+ else:
+ try:
+ scenarios = scenario_input.split(",")
+ scenarios = ", ".join(scenarios)
+ except Exception:
+ print(
+ BColors.OKBLUE,
+ f"Geen scenarios toegevoegd. '{scenario_input}' is geen geldige invoer.",
+ BColors.ENDC,
+ )
+ continue
+ break
+
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+
+ sql_update = "UPDATE geoprob_pipe_metadata SET metadata_value = ? WHERE metadata_type = ?"
+ sql_insert = "INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES (?, ?)"
+
+ with conn: # transaction
+ cur = conn.execute(sql_update, (scenarios, "ruimtelijke_scenarios"))
+ if cur.rowcount == 0:
+ conn.execute(sql_insert, ("ruimtelijke_scenarios", scenarios))
+
+ conn.commit()
+ conn.close()
diff --git a/geoprob_pipe/cmd_app/spatial_layers/vakindeling.py b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py
similarity index 71%
rename from geoprob_pipe/cmd_app/spatial_layers/vakindeling.py
rename to geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py
index eb40641c..70115312 100644
--- a/geoprob_pipe/cmd_app/spatial_layers/vakindeling.py
+++ b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py
@@ -13,6 +13,7 @@
from geopandas import GeoDataFrame
import fiona
from geoprob_pipe.utils.validation_messages import BColors
+
if TYPE_CHECKING:
from geoprob_pipe.cmd_app.cmd import ApplicationSettings
@@ -45,17 +46,23 @@ def check_validity_vakindeling(app_settings: ApplicationSettings):
vakindeling_total_length = round(sum([geom.length for geom in vakindeling_geometries]), 2)
assert dijktraject_length == vakindeling_total_length
- print(BColors.OKBLUE, f"✔ Vakindeling al toegevoegd.", BColors.ENDC)
-
-
-def import_from_geopackage(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de laag met de vakindeling. "
- "Type 'listlayers' om een overzicht te krijgen van de geopackage-layers. ",
- ).execute()
+ print(BColors.OKBLUE, "✔ Vakindeling al toegevoegd.", BColors.ENDC)
+
+
+def import_from_geopackage(app_settings: ApplicationSettings,
+ filepath: str) -> GeoDataFrame:
+ layer_name: str = ""
+ skip_batch = False # Als batch input faalt ga over op handmatig
+ while True:
+ if app_settings.batch_input and not skip_batch:
+ layer_name = app_settings.input_config.get(
+ "vakindeling", "database_layer"
+ )
+ else:
+ layer_name: str = inquirer.text(
+ message="Specificeer de laag met de vakindeling. "
+ "Type 'listlayers' om een overzicht te krijgen van de geopackage-layers. ",
+ ).execute()
layer_names = fiona.listlayers(filepath)
layer_names.sort()
@@ -66,9 +73,10 @@ def import_from_geopackage(filepath: str) -> GeoDataFrame:
elif layer_name not in layer_names:
print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
f"de geopackage: {layers_str}", BColors.ENDC)
+ skip_batch = True
continue
- layer_name_is_valid = True
+ break
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
@@ -76,14 +84,21 @@ def import_from_geopackage(filepath: str) -> GeoDataFrame:
return gdf
-def import_from_geodatabase(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de laag met de vakindeling. "
- "Type 'listlayers' om een overzicht te krijgen van de geodatabase-layers. ",
- ).execute()
+def import_from_geodatabase(app_settings: ApplicationSettings,
+ filepath: str) -> GeoDataFrame:
+ layer_name: str = ""
+ skip_batch = False # Als batch input faalt ga over op handmatig
+
+ while True:
+ if app_settings.batch_input and not skip_batch:
+ layer_name = app_settings.input_config.get(
+ "vakindeling", "database_layer"
+ )
+ else:
+ layer_name: str = inquirer.text(
+ message="Specificeer de laag met de vakindeling. "
+ "Type 'listlayers' om een overzicht te krijgen van de geodatabase-layers. ",
+ ).execute()
layer_names = fiona.listlayers(filepath)
layer_names.sort()
@@ -94,9 +109,10 @@ def import_from_geodatabase(filepath: str) -> GeoDataFrame:
elif layer_name not in layer_names:
print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
f"de geodatabase: {layers_str}", BColors.ENDC)
+ skip_batch = True
continue
- layer_name_is_valid = True
+ break
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
@@ -105,13 +121,17 @@ def import_from_geodatabase(filepath: str) -> GeoDataFrame:
def request_vakindeling_filepath(app_settings: ApplicationSettings):
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
- filepath: str = inquirer.text(
- message="Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase waarin de "
- "vakindeling van de dijk zit.",
- ).execute()
+ filepath: str = ""
+ skip_batch = False # Als batch input faalt ga over op handmatig
+
+ while True:
+ if app_settings.batch_input and not skip_batch:
+ filepath = app_settings.input_config.get("vakindeling", "filepath")
+ else:
+ filepath: str = inquirer.text(
+ message="Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase waarin de "
+ "vakindeling van de dijk zit.",
+ ).execute()
filepath = filepath.replace('"', '')
@@ -120,10 +140,11 @@ def request_vakindeling_filepath(app_settings: ApplicationSettings):
f"eindigt op de extensie .{filepath.split(sep='.')[-1]}.", BColors.ENDC)
continue
if not os.path.exists(filepath):
- print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
+ print(BColors.WARNING, "Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
+ skip_batch = True
continue
- filepath_is_valid = True
+ break
if filepath.endswith(".shp"):
with warnings.catch_warnings():
@@ -131,10 +152,12 @@ def request_vakindeling_filepath(app_settings: ApplicationSettings):
gdf: GeoDataFrame = read_file(filepath)
validate_vakindeling(app_settings, gdf=gdf)
elif filepath.endswith(".gpkg"):
- gdf: GeoDataFrame = import_from_geopackage(filepath=filepath)
+ gdf: GeoDataFrame = import_from_geopackage(app_settings=app_settings,
+ filepath=filepath)
validate_vakindeling(app_settings, gdf=gdf)
elif filepath.endswith(".gdb"):
- gdf: GeoDataFrame = import_from_geodatabase(filepath=filepath)
+ gdf: GeoDataFrame = import_from_geodatabase(app_settings=app_settings,
+ filepath=filepath)
validate_vakindeling(app_settings, gdf=gdf)
else:
raise NotImplementedError(f"File with extension {filepath.split(sep='.')[-1]} is not yet supported. "
@@ -153,14 +176,20 @@ def validate_vakindeling(app_settings: ApplicationSettings, gdf: GeoDataFrame):
def specify_column_with_vaknaam(
app_settings: ApplicationSettings, gdf: GeoDataFrame):
- column_name: Optional[str] = None
- column_name_is_valid = False
- while column_name_is_valid is False:
- column_name: str = inquirer.text(
- message="Specificeer de kolom waarin de vaknaam staat. Type "
- "'listcolumns' om een overzicht te krijgen van de "
- "kolommen. ",
- ).execute()
+ column_name: str = ""
+
+ skip_batch = False # Als batch input faalt ga over op handmatig
+ while True:
+ if app_settings.batch_input and not skip_batch:
+ column_name = app_settings.input_config.get(
+ "vakindeling", "vak_naam_kolom"
+ )
+ else:
+ column_name: str = inquirer.text(
+ message="Specificeer de kolom waarin de vaknaam staat. Type "
+ "'listcolumns' om een overzicht te krijgen van de "
+ "kolommen. ",
+ ).execute()
column_names = gdf.columns
columns_str = ", ".join(column_names)
@@ -174,9 +203,10 @@ def specify_column_with_vaknaam(
f"De kolom naam '{column_name}' bestaat niet. De volgende "
f"kolommen zijn beschikbaar in de spatial layer: "
f"{columns_str}", BColors.ENDC)
+ skip_batch = True
continue
- column_name_is_valid = True
+ break
column_name: str
specify_column_with_vak_id(
@@ -193,14 +223,20 @@ def is_numeric_integer(val):
def specify_column_with_vak_id(
app_settings: ApplicationSettings, gdf: GeoDataFrame,
kolom_vak_naam: str):
- kolom_vak_id: Optional[str] = None
- column_name_is_valid = False
- while column_name_is_valid is False:
- kolom_vak_id: str = inquirer.text(
- message="Specificeer de kolom waarin het vak id staat. Indien "
- "onnodig, type 'nvt'. Type 'listcolumns' om een overzicht "
- "te krijgen van de kolommen. ",
- ).execute()
+ kolom_vak_id: str = ""
+ skip_batch = False # Als batch input faalt ga over op handmatig
+
+ while True:
+ if app_settings.batch_input and not skip_batch:
+ kolom_vak_id = app_settings.input_config.get(
+ "vakindeling", "vak_id_kolom"
+ )
+ else:
+ kolom_vak_id: str = inquirer.text(
+ message="Specificeer de kolom waarin het vak id staat. Indien "
+ "onnodig, type 'nvt'. Type 'listcolumns' om een overzicht "
+ "te krijgen van de kolommen. ",
+ ).execute()
column_names = gdf.columns
columns_str = ", ".join(column_names)
@@ -218,6 +254,7 @@ def specify_column_with_vak_id(
print(f"{BColors.OKBLUE}De kolom naam '{kolom_vak_id}' bestaat "
f"niet. De volgende kolommen zijn beschikbaar in de spatial "
f"layer: {columns_str}{BColors.ENDC}")
+ skip_batch = True
continue
# Ensure column values are unique and integers
@@ -225,15 +262,17 @@ def specify_column_with_vak_id(
print(f"{BColors.OKBLUE}De waarden in deze kolom zijn niet uniek. "
f"Corrigeer de dubbelingen, of kies een andere kolom."
f"{BColors.ENDC}")
+ skip_batch = True
continue
elif not gdf[kolom_vak_id].apply(is_numeric_integer).all():
print(f"{BColors.OKBLUE}De waarden in deze kolom zijn niet allen "
f"volledige getallen (integers). Corrigeer de kolom, of "
f"kies een andere.{BColors.ENDC}")
+ skip_batch = True
continue
- column_name_is_valid = True
+ break
kolom_vak_id: str
align_vak_shp_to_dijktraject(
@@ -250,7 +289,7 @@ def align_vak_shp_to_dijktraject(
# Data verzamelen uit provided vak shp
rows = []
- for index, row in gdf_vakindeling.iterrows():
+ for _, row in gdf_vakindeling.iterrows():
pnt1 = row.geometry.boundary.geoms[0]
pnt2 = row.geometry.boundary.geoms[1]
m_pnt1 = round(ls_dijktraject.project(pnt1), 1)
@@ -270,7 +309,7 @@ def align_vak_shp_to_dijktraject(
# Align vak geometry to dijktraject by retrieving substring
rows = []
- for index, row in df.iterrows():
+ for _, row in df.iterrows():
new_row = {
"naam": row["naam"],
"m_start": row["m_start"],
@@ -290,4 +329,4 @@ def align_vak_shp_to_dijktraject(
gdf_new_vakindeling.to_file(
Path(app_settings.geopackage_filepath),
layer="vakindeling", driver="GPKG")
- print(BColors.OKBLUE, f"✅ Vakindeling toegevoegd.", BColors.ENDC)
+ print(BColors.OKBLUE, "✅ Vakindeling toegevoegd.", BColors.ENDC)
diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py
new file mode 100644
index 00000000..070a9a61
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py
@@ -0,0 +1,581 @@
+"""
+Class voor het opvragen van de ruimtelijke invoer voor de parameters
+vanuit GIS lagen. Shapefiles, geodatabases en geopackages worden ondersteund.
+
+Er zijn vier mogelijke invoer situaties:
+-GEEN ruimtelijke scenarios en GEEN ruimtelijke data invoer
+-GEEN ruimtelijke scenarios en WEL ruimtelijke data invoer
+-WEL ruimtelijke scenarios en GEEN ruimtelijke data invoer
+-WEL ruimtelijke scenarios en WEL ruimtelijke data invoer
+
+Daarnaast is er nog onderscheid in invoer met verschillende shapes per scenario
+of twee sets met invoer data.
+"""
+
+from __future__ import annotations
+
+import os
+import sqlite3
+import warnings
+from typing import TYPE_CHECKING
+
+import fiona
+import geopandas as gpd
+import InquirerPy.prompts.input as prompt
+import pandas as pd
+from shapely import LineString, MultiLineString
+
+from geoprob_pipe.utils.validation_messages import BColors
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+class BaseInquiry:
+ def __init__(
+ self,
+ app_settings: ApplicationSettings,
+ param: str,
+ specific_shape: str = "",
+ include_value: bool = False,
+ single_geometry: bool = False,
+ ) -> None:
+ """
+ Class voor de opvraag van de ruimtelijke invoer van de parameters.
+
+ :param app_settings: `ApplicationSettings` object.
+ :param param: Parameter die wordt opgevraagd. Deze wordt ook gebruikt
+ voor de naam van de tabel in de geopackage.
+ :param specific_shape: Welke soort ruimtelijke invoer acceptabel is, defaults to "".
+ Geldige invoer is "lines", "polygons" of "rasters".
+ :param include_value: Of er naast de geometrie zelf ook een bepaalde
+ waarde moet worden toegevoegd aan de geopackage, defaults to False
+ """
+ self.app_settings = app_settings
+ self.param = param
+ self.specific_shape = specific_shape
+ self.include_value = include_value
+ self.single_geometry = single_geometry
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+ cur = conn.cursor()
+ cur.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_scenarios",),
+ )
+ self.scenarios: list[str] = cur.fetchone()[0].split(", ")
+ conn.close()
+
+ def request_filepath(self):
+ """
+ Method voor het opvragen van het filepath.
+ """
+ skip_batch = False # Als batch input faalt ga over op handmatig
+ while True:
+ if self.app_settings.batch_input and not skip_batch:
+ filepath = self.app_settings.input_config.get(
+ f"{self.param}", "filepath"
+ )
+ else:
+ filepath: str = prompt.InputPrompt(
+ message=(
+ f"""
+Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase
+met de {self.param} geometrieën.
+"""
+ )
+ ).execute()
+
+ filepath = filepath.replace('"', "")
+
+ if not os.path.exists(filepath):
+ print(
+ BColors.WARNING,
+ "Het opgegeven bestandspad bestaat niet.",
+ BColors.ENDC,
+ )
+ skip_batch = True
+ continue
+
+ if not (
+ filepath.endswith(".gpkg")
+ or filepath.endswith(".shp")
+ or filepath.endswith(".gdb")
+ ):
+ print(
+ BColors.WARNING,
+ f"""
+ Het bestand moet of een geopackage, shapefile of geodatabase zijn.
+ Jouw invoer eindigt op de extensie .{filepath.split(sep=".")[-1]}.
+ """,
+ BColors.ENDC,
+ )
+ skip_batch = True
+ continue
+
+ # Import data
+ gdf = self._import_data(filepath) # type:ignore
+
+ # Add data to geopackage
+ if self._add_to_gpkg(gdf):
+ break
+
+ print(BColors.OKBLUE, f"✅ {self.param} toegevoegd.", BColors.ENDC)
+
+ def _import_data(self, filepath: str) -> gpd.GeoDataFrame:
+ """
+ Helper method voor het importeren van de data.
+
+ :param filepath: Bestandspad van de shapefile of database met de GIS lagen.
+ :raises NotImplementedError: Wanneer het bestand iets anders is dan wordt ondersteund.
+ :return: GeoDataFrame met de uitgelezen data.
+ :rtype GeoDataFrame:
+ """
+ if filepath.endswith(".shp"):
+ with warnings.catch_warnings():
+ warnings.filterwarnings(
+ "ignore",
+ message="Measured \\(M\\) geometry types are not supported.*",
+ )
+ gdf: gpd.GeoDataFrame = gpd.read_file(filepath)
+
+ elif filepath.endswith(".gpkg"):
+ gdf: gpd.GeoDataFrame = self._import_from_db(filepath)
+
+ elif filepath.endswith(".gdb"):
+ with warnings.catch_warnings():
+ warnings.filterwarnings(
+ "ignore",
+ message="Measured \\(M\\) geometry types are not supported.*",
+ )
+ gdf: gpd.GeoDataFrame = self._import_from_db(filepath)
+
+ else:
+ raise NotImplementedError(
+ f"Applicatie vroegtijdig afgesloten: Een {filepath.split(sep='.')[-1]}-bestand is niet geïmplementeerd."
+ )
+
+ return gdf
+
+ def _import_from_db(self, filepath: str) -> gpd.GeoDataFrame:
+ """
+ Helper method voor het importeren vanuit een gbd of een geopackage.
+
+ :param filepath: Bestandspad van de database.
+ :return: GeoDataFrame met de uitgelezen data.
+ """
+ skip_batch = False # Als batch input faalt ga over op handmatig
+ while True:
+ if self.app_settings.batch_input and not skip_batch:
+ layer_name = self.app_settings.input_config.get(
+ f"{self.param}", "database_layer"
+ )
+ else:
+ layer_name: str = prompt.InputPrompt(
+ message=(
+ f"""
+Specificeer de layer waarin de {self.param} staat. Type 'listlayers' om
+een overzicht te krijgen van de geodatabase-layers. Type 'cancel' om een
+ander bestand op te gaven.
+"""
+ )
+ ).execute()
+
+ layer_names = fiona.listlayers(filepath)
+ layer_names.sort()
+ layers_str = ", ".join(layer_names)
+ if layer_name == "listlayers":
+ print(
+ f"{BColors.OKBLUE}De volgende layers zijn beschikbaar in de geodatabase: {layers_str}{BColors.ENDC}"
+ )
+ continue
+
+ if layer_name == "cancel":
+ self.request_filepath()
+
+ elif layer_name not in layer_names:
+ print(
+ f"{BColors.OKBLUE} De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
+ f"de geodatabase: {layers_str}{BColors.ENDC}"
+ )
+ skip_batch = True
+ continue
+
+ break
+
+ gdf: gpd.GeoDataFrame = gpd.read_file(filepath, layer=layer_name) # type:ignore
+ return gdf
+
+ def _import_from_shp(self, filepath: str) -> gpd.GeoDataFrame:
+ """
+ Helper method voor het importeren vanuit een shapefile.
+
+ :param filepath: Bestandspad van de shapefile.
+ :return: GeoDataFrame met de uitgelezen data.
+ """
+
+ gdf: gpd.GeoDataFrame = gpd.read_file(filepath)
+ return gdf
+
+ def _check_shape(self, gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame | None:
+ """
+ Helper method voor het checken of de geometry het juiste type is.
+
+ :param gdf: GeoDataFrame met de uitgelezen data.
+ :return: GeoDataFrame of None als check faalt.
+ """
+
+ if self.specific_shape == "":
+ return gdf
+
+ if self.specific_shape == "lines":
+ all_lines = gdf.geometry.apply(
+ lambda geom: (
+ isinstance(geom, LineString)
+ or isinstance(geom, MultiLineString)
+ )
+ ).all()
+
+ if not all_lines:
+ print(
+ BColors.WARNING,
+ """
+ Het geïmporteerde bestand bestaat niet (volledig) uit lijnen,
+ maar ook uit andere typen geometrie. Enkel lijnen zijn toegestaan.
+ """,
+ BColors.ENDC,
+ )
+ self.request_filepath()
+
+ return gdf
+
+ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool:
+ """
+ Helper method om de data aan de geopackage toe te voegen.
+ Start een apart inquiry als en waarden moeten worden toegevoegd aan de
+ shape of als er meerdere shapes moeten worden toegevoegd. De kolommen
+ moeten van te voren met de juiste suffix in de shape staan. Als scheiding
+ wordt een dubble underscore gebruikt.
+
+ De mogelijke suffixen zijn:
+ *__mean voor het gemiddelde of deterministische waarde.
+ *__dist voor het distributie type.
+ *__var voor de variatie.
+ *__dev voor de deviatie.
+ *__min voor het minimum.
+ *__max voor het maximum.
+
+ Als er meerdere scenarios zijn moeten deze als aparte kolommen worden
+ toegevoegd met een prefix. Bijvoorbeeld scenario1__*.
+
+ Of als de scenarios als aparte shapes worden ingevoerd, moet er een kolom
+ met de naam "ondergrondscenario" zijn toegevoegd.
+
+ :param gdf: GeoDataFrame met de uitgelezen data van de laag.
+ :return: bool voor valid_input in while-loop.
+ :rtype: bool
+ """
+ self.suffix_list = ["mean", "dist", "var", "dev", "min", "max"]
+
+ if self.include_value and self.scenarios == "":
+ # Case: Alleen suffix, alle kolommen worden met de geometrie weggeschreven.
+ return self._add_with_suffix(gdf)
+
+ elif self.include_value and self.scenarios != "":
+ # Case: beide affixes, per scenario worden alle kolommen met de
+ # geometrieën weggeschreven.
+ # Of verschillende geometrieën per scenario
+ column_list = gdf.columns.to_list()
+ if True in [
+ len(column.split("__")) == 3
+ and self.param in column.split("__")
+ for column in column_list
+ ]:
+ return self._add_with_affixes(gdf)
+ else:
+ return self._add_separate_with_suffix(gdf)
+
+ elif (
+ not self.include_value
+ and (
+ self.scenarios == "" # Geen scenarios opgegeven.
+ or self.single_geometry # Vang hier als scenario's niet relevant zijn.
+ or not self._scenario_check(
+ gdf.columns.to_list()
+ ) # Scenario's niet gekoppeld aan deze laag.
+ )
+ ):
+ # Case: geen affixes alleen de geometrie wordt geschreven.
+ gdf_to_add = gdf[["geometry"]]
+ gdf_to_add.to_file(
+ self.app_settings.geopackage_filepath,
+ layer=f"{self.param}",
+ driver="GPKG",
+ )
+ return True
+
+ elif not self.include_value and self.scenarios != "":
+ # Case: Alleen losse shapes, de geometrieën worden per scenario geschreven.
+ return self._add_with_separate_geometry(gdf)
+
+ else:
+ raise ImportError(
+ "De laag kan niet worden verwerkt. Controleer of de juiste kolommen aanwezig zijn."
+ )
+
+ # Methods voor het controleren van de geodataframes.
+ def _scenario_check(self, column_list: list[str]):
+ """
+ Check of het scenario in de 'ondergrondscenario' kolom voorkomt.
+
+ :param list[str] column_list: Lijst met kolomnamen uit de GeoDataFrame.
+ :return: Check of het scenario voorkomt.
+ :rtype: bool
+ """
+ if "ondergrondscenario" not in column_list:
+ print(
+ BColors.WARNING,
+ "Geen kolom met de naam 'ondergrondscenario' gevonden.\n",
+ "De volgende kolommen zijn gevonden:\n",
+ f"{column_list}",
+ BColors.ENDC,
+ )
+
+ return False
+ else:
+ return True
+
+ def _distribution_check(
+ self,
+ column_list: list[str],
+ add_list: list[str],
+ gdf: gpd.GeoDataFrame,
+ scenario: str = "",
+ ) -> bool:
+ """
+ Check of de kolommen de juiste inputs hebben voor de gekozen distributie.
+ Als een var of std nodig is, deze aanwezig is. En niet beide aanwezig zijn.
+
+ :param list[sts] column_list: Lijst met kolomnamen.
+ :param list[str] add_list: Lijst met geselecteerde kolomnamen voor toe te voegen.
+ :param gpd.GeaDataFrame gdf: GeoDataFrame van uitgelezen data.
+ :return: Check of de kolommen goed zijn.
+ :rtype: bool
+ """
+ if len(add_list) == 0:
+ print(
+ BColors.WARNING,
+ "De parameter is niet gevonden in de attributen van de laag.",
+ f"Alleen deze kolommen zijn gevonden: {', '.join(column_list)}",
+ BColors.ENDC,
+ )
+ return False
+
+ # Check var or std if not deterministic.
+ for _, row in gdf.iterrows():
+ # Als per scenario wordt gecontroleerd is de naam in de gdf anders.
+ if scenario != "":
+ prefix = scenario + "__"
+ else:
+ prefix = ""
+
+ if row[f"{prefix}{self.param}__dist"] == "deterministic":
+ continue # Overslaan
+
+ if f"{self.param}__var" in add_list:
+ value = float(row[f"{prefix}{self.param}__var"])
+ var_bool = pd.notna(value)
+ else:
+ var_bool = False
+
+ if f"{self.param}__dev" in add_list:
+ value = float(row[f"{prefix}{self.param}__dev"])
+ dev_bool = pd.notna(value)
+ else:
+ dev_bool = False
+
+ if var_bool and dev_bool:
+ print(
+ BColors.WARNING,
+ "Er is zowel een waarde voor de variatie als de standaard deviatie.",
+ BColors.ENDC,
+ )
+ return False
+
+ if not var_bool and not dev_bool:
+ print(
+ BColors.WARNING,
+ "Er is geen waarde voor de variatie of de standaard deviatie.",
+ BColors.ENDC,
+ )
+ return False
+
+ return True
+
+ # Methods voor het toevoegen aan de database
+
+ def _add_with_separate_geometry(self, gdf: gpd.GeoDataFrame) -> bool:
+ """
+ Method voor het toevoegen van lagen met meerdere shapes voor
+ verschillende scenarios.
+
+ :param gdf: GeoDataFrame met de uitgelezen data.
+ :return: bool voor valid_input in while-loop.
+ :rtype: bool
+ """
+ column_list = gdf.columns.to_list()
+ if not self._scenario_check(column_list):
+ return False
+
+ for scenario in self.scenarios:
+ mask = gdf["ondergrondscenario"] == scenario
+ gdf_to_add = gdf[mask][["geometry"]]
+
+ if len(gdf_to_add) == 0:
+ print(
+ BColors.WARNING,
+ f"Geen geometrieën gevonden met de ondergrondscenarionaam: {scenario}",
+ BColors.ENDC,
+ )
+ continue
+
+ gdf_to_add.to_file(
+ self.app_settings.geopackage_filepath,
+ layer=f"{self.param}__{scenario}",
+ driver="GPKG",
+ )
+
+ return True
+
+ def _add_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool:
+ """
+ Method voor het schrijven naar de geopackage voor een case met
+ parameter invoer en geen scenarios.
+
+ :param gdf: GeoDataFrame met de uitgelezen data.
+ :return: bool voor valid_input in while-loop.
+ :rtype: bool
+ """
+ column_list = gdf.columns.to_list()
+ add_list = [
+ f"{self.param}__{param}"
+ for param in self.suffix_list
+ if f"{self.param}__{param}" in column_list
+ ]
+
+ if not self._distribution_check(column_list, add_list, gdf):
+ return False
+
+ gdf_to_add = gdf[["geometry", add_list]]
+
+ gdf_to_add.to_file(
+ self.app_settings.geopackage_filepath,
+ layer=f"{self.param}",
+ driver="GPKG",
+ )
+
+ return True
+
+ def _add_with_affixes(self, gdf: gpd.GeoDataFrame) -> bool:
+ """
+ Voeg de data toe apart per scenario als deze als aparte kolommen in de
+ laag staan.
+
+ :param gdf: GeoDataFrame met de uitgelezen data.
+ :return: bool voor valid_input in while-loop
+ :rtype: bool
+ """
+ column_list = gdf.columns.to_list()
+
+ for scenario in self.scenarios:
+ filter_list = [
+ column
+ for column in column_list
+ if column.split("__")[0] == scenario
+ ]
+
+ if len(filter_list) == 0:
+ print(
+ BColors.WARNING,
+ f"Geen geometrieën gevonden met de ondergrondscenarionaam: {scenario}",
+ BColors.ENDC,
+ )
+ continue
+
+ # Strip scenario van kolomnaam.
+ filter_list = [column.split("__")[1:] for column in filter_list]
+ filter_list = ["__".join(item) for item in filter_list]
+
+ add_list = [
+ f"{self.param}__{suffix}"
+ for suffix in self.suffix_list
+ if f"{self.param}__{suffix}" in filter_list
+ ]
+
+ if not self._distribution_check(
+ column_list, add_list, gdf, scenario=scenario
+ ):
+ # parameters niet voor dit scenario of niet correct ingevoerd.
+ continue
+
+ scenario_add_list = [f"{scenario}__{item}" for item in add_list]
+ gdf_to_add = gdf[["geometry"] + scenario_add_list]
+
+ for a, b in zip(scenario_add_list, add_list):
+ gdf_to_add = gdf_to_add.rename(columns={a: b})
+
+ gdf_to_add.to_file(
+ self.app_settings.geopackage_filepath,
+ layer=f"{self.param}__{scenario}",
+ driver="GPKG",
+ )
+
+ return True
+
+ def _add_separate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool:
+ """
+ Voeg de lagen toe los van elkaar per scenario.
+
+ :param gdf: GeoDataFrame met de uitgelezen data.
+ :return: bool voor valid_input in while-loop
+ """
+ column_list = gdf.columns.to_list()
+
+ if not self._scenario_check(column_list):
+ return False
+
+ # 'None' als er geen scenario zijn opgegeven in de kolom
+ for scenario in self.scenarios + [None]:
+ if scenario is None:
+ mask = gdf["ondergrondscenario"].isna()
+ else:
+ mask = gdf["ondergrondscenario"] == scenario
+
+ if not mask.any():
+ continue
+
+ add_list = [
+ f"{self.param}__{suffix}"
+ for suffix in self.suffix_list
+ if f"{self.param}__{suffix}" in column_list
+ ]
+
+ if not self._distribution_check(column_list, add_list, gdf):
+ return False
+
+ gdf_to_add = gdf.loc[mask, ["geometry"] + add_list]
+
+ if scenario is None:
+ gdf_to_add.to_file(
+ self.app_settings.geopackage_filepath,
+ layer=f"{self.param}",
+ driver="GPKG",
+ )
+
+ else:
+ gdf_to_add.to_file(
+ self.app_settings.geopackage_filepath,
+ layer=f"{self.param}__{scenario}",
+ driver="GPKG",
+ )
+
+ return True
diff --git a/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py
deleted file mode 100644
index 8e43a358..00000000
--- a/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py
+++ /dev/null
@@ -1,132 +0,0 @@
-"""
-TODO Later Should Klein: Controleer of de binnenteenlijn ook echt aan de binnenzijde is.
-TODO Later Should Klein: Niet voor elk geohydrologisch model is de binnen/buiten/intredelijn benodigd.
- Maak het toevoegen van deze lijnen afhankelijk van de model keuze.
-"""
-
-from __future__ import annotations
-from InquirerPy import inquirer
-from typing import TYPE_CHECKING, Optional
-import os
-from shapely import LineString, MultiLineString
-from geopandas import GeoDataFrame, read_file
-import fiona
-import warnings
-from geoprob_pipe.utils.validation_messages import BColors
-if TYPE_CHECKING:
- from geoprob_pipe.cmd_app.cmd import ApplicationSettings
-
-
-def added_binnenteenlijn(app_settings: ApplicationSettings) -> bool:
- layers = fiona.listlayers(app_settings.geopackage_filepath)
-
- if "binnenteenlijn" in layers:
- print(BColors.OKBLUE, f"✔ Binnenteenlijn al toegevoegd.", BColors.ENDC)
- return True
-
- request_binnenteenlijn_filepath(app_settings=app_settings)
- return True
-
-
-def request_binnenteenlijn_filepath(app_settings: ApplicationSettings):
-
- # Request filepath
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
- filepath: str = inquirer.text(
- message="Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase waarin de "
- "binnenteen lijnen zitten.",
- ).execute()
-
- filepath = filepath.replace('"', '')
-
- if not (filepath.endswith(".gpkg") or filepath.endswith(".shp") or filepath.endswith(".gdb")):
- print(BColors.WARNING, f"Het bestand moet of een geopackage, shapefile of geodatabase zijn. Jouw invoer "
- f"eindigt op de extensie .{filepath.split(sep='.')[-1]}.", BColors.ENDC)
- continue
- if not os.path.exists(filepath):
- print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
- continue
-
- filepath_is_valid = True
-
- # Import data
- if filepath.endswith(".shp"):
- with warnings.catch_warnings():
- warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
- gdf: GeoDataFrame = read_file(filepath)
- elif filepath.endswith(".gpkg"):
- gdf: GeoDataFrame = import_from_geopackage(filepath=filepath)
- elif filepath.endswith(".gdb"):
- with warnings.catch_warnings():
- warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
- gdf: GeoDataFrame = import_from_geodatabase(filepath=filepath)
- else:
- raise NotImplementedError(
- f"Applicatie vroegtijdig afgesloten: Een {filepath.split(sep='.')[-1]}-bestand is niet geïmplementeerd.")
-
- # Confirm all are points
- all_geometries_are_points = gdf.geometry.apply(
- lambda geom: isinstance(geom, LineString) or isinstance(geom, MultiLineString)).all()
- if not all_geometries_are_points:
- print(BColors.WARNING, f"Het geïmporteerde bestand bestaat niet (volledig) uit lijnen, maar ook uit "
- f"andere typen geometrie. Enkel lijnen zijn toegestaan.", BColors.ENDC)
- request_binnenteenlijn_filepath(app_settings=app_settings)
-
- # Add binnenteenlijn
- gdf_to_add = gdf[["geometry"]]
- gdf_to_add.to_file(app_settings.geopackage_filepath, layer="binnenteenlijn", driver="GPKG")
- print(BColors.OKBLUE, f"✅ Binnenteenlijn toegevoegd.", BColors.ENDC)
-
-
-def import_from_geodatabase(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de layer waarin de binnenteenlijn staat. Type 'listlayers' om "
- "een overzicht te krijgen van de geodatabase-layers. ",
- ).execute()
-
- layer_names = fiona.listlayers(filepath)
- layer_names.sort()
- layers_str = ", ".join(layer_names)
- if layer_name == "listlayers":
- print(f"{BColors.OKBLUE}De volgende layers zijn beschikbaar in de geodatabase: {layers_str}{BColors.ENDC}")
- continue
- elif layer_name not in layer_names:
- print(f"{BColors.OKBLUE} De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
- f"de geodatabase: {layers_str}{BColors.ENDC}")
- continue
-
- layer_name_is_valid = True
-
- gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
- return gdf
-
-
-def import_from_geopackage(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de laag met de binnenteen lijnen. Type 'listlayers' om "
- "een overzicht te krijgen van de geopackage-layers. ",
- ).execute()
-
- layer_names = fiona.listlayers(filepath)
- layer_names.sort()
- layers_str = ", ".join(layer_names)
- if layer_name == "listlayers":
- print(BColors.OKBLUE, f"De volgende layers zijn beschikbaar in de geopackage: {layers_str}", BColors.ENDC)
- continue
- elif layer_name not in layer_names:
- print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
- f"de geopackage: {layers_str}", BColors.ENDC)
- continue
-
- layer_name_is_valid = True
-
- gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
- return gdf
diff --git a/geoprob_pipe/cmd_app/spatial_layers/buitenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/buitenteenlijn.py
deleted file mode 100644
index 3aeaedc0..00000000
--- a/geoprob_pipe/cmd_app/spatial_layers/buitenteenlijn.py
+++ /dev/null
@@ -1,131 +0,0 @@
-"""
-TODO Later Should Klein: Controleer of de buitenteenlijn ook echt aan de buitenzijde is.
-
-"""
-
-from __future__ import annotations
-from InquirerPy import inquirer
-from typing import TYPE_CHECKING, Optional
-import os
-import warnings
-from shapely import LineString, MultiLineString
-from geopandas import GeoDataFrame, read_file
-import fiona
-from geoprob_pipe.utils.validation_messages import BColors
-if TYPE_CHECKING:
- from geoprob_pipe.cmd_app.cmd import ApplicationSettings
-
-
-def added_buitenteenlijn(app_settings: ApplicationSettings) -> bool:
- layers = fiona.listlayers(app_settings.geopackage_filepath)
-
- if "buitenteenlijn" in layers:
- print(BColors.OKBLUE, f"✔ Buitenteenlijn al toegevoegd.", BColors.ENDC)
- return True
-
- request_buitenteenlijn_filepath(app_settings=app_settings)
- return True
-
-
-def request_buitenteenlijn_filepath(app_settings: ApplicationSettings):
-
- # Request filepath
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
- filepath: str = inquirer.text(
- message="Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase waarin de "
- "buitenteen lijnen zitten.",
- ).execute()
-
- filepath = filepath.replace('"', '')
-
- if not (filepath.endswith(".gpkg") or filepath.endswith(".shp") or filepath.endswith(".gdb")):
- print(BColors.WARNING, f"Het bestand moet of een geopackage, shapefile of geodatabase zijn. Jouw invoer "
- f"eindigt op de extensie .{filepath.split(sep='.')[-1]}.", BColors.ENDC)
- continue
- if not os.path.exists(filepath):
- print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
- continue
-
- filepath_is_valid = True
-
- # Import data
- if filepath.endswith(".shp"):
- with warnings.catch_warnings():
- warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
- gdf: GeoDataFrame = read_file(filepath)
- elif filepath.endswith(".gpkg"):
- gdf: GeoDataFrame = import_from_geopackage(filepath=filepath)
- elif filepath.endswith(".gdb"):
- with warnings.catch_warnings():
- warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
- gdf: GeoDataFrame = import_from_geodatabase(filepath=filepath)
- else:
- raise NotImplementedError(
- f"Applicatie vroegtijdig afgesloten: Een {filepath.split(sep='.')[-1]}-bestand is niet geïmplementeerd.")
-
- # Confirm all are points
- all_geometries_are_points = gdf.geometry.apply(
- lambda geom: isinstance(geom, LineString) or isinstance(geom, MultiLineString)).all()
- if not all_geometries_are_points:
- print(BColors.WARNING, f"Het geïmporteerde bestand bestaat niet (volledig) uit lijnen, maar ook uit "
- f"andere typen geometrie. Enkel lijnen zijn toegestaan.", BColors.ENDC)
- request_buitenteenlijn_filepath(app_settings=app_settings)
-
- # Add buitenteenlijn
- gdf_to_add = gdf[["geometry"]]
- gdf_to_add.to_file(app_settings.geopackage_filepath, layer="buitenteenlijn", driver="GPKG")
- print(BColors.OKBLUE, f"✅ Buitenteenlijn toegevoegd.", BColors.ENDC)
-
-
-def import_from_geodatabase(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de layer waarin de buitenteenlijn staat. Type 'listlayers' om "
- "een overzicht te krijgen van de geodatabase-layers. ",
- ).execute()
-
- layer_names = fiona.listlayers(filepath)
- layer_names.sort()
- layers_str = ", ".join(layer_names)
- if layer_name == "listlayers":
- print(BColors.OKBLUE, f"De volgende layers zijn beschikbaar in de geodatabase: {layers_str}", BColors.ENDC)
- continue
- elif layer_name not in layer_names:
- print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
- f"de geodatabase: {layers_str}", BColors.ENDC)
- continue
-
- layer_name_is_valid = True
-
- gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
- return gdf
-
-
-def import_from_geopackage(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de laag met de buitenteen lijnen. Type 'listlayers' om "
- "een overzicht te krijgen van de geopackage-layers. ",
- ).execute()
-
- layer_names = fiona.listlayers(filepath)
- layer_names.sort()
- layers_str = ", ".join(layer_names)
- if layer_name == "listlayers":
- print(BColors.OKBLUE, f"De volgende layers zijn beschikbaar in de geopackage: {layers_str}", BColors.ENDC)
- continue
- elif layer_name not in layer_names:
- print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
- f"de geopackage: {layers_str}", BColors.ENDC)
- continue
-
- layer_name_is_valid = True
-
- gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
- return gdf
diff --git a/geoprob_pipe/cmd_app/spatial_layers/check_batch_input.py b/geoprob_pipe/cmd_app/spatial_layers/check_batch_input.py
new file mode 100644
index 00000000..71eeb430
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_layers/check_batch_input.py
@@ -0,0 +1,13 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+from geoprob_pipe.cmd_app.utils.batch_input import batch_inquiry, read_metadata
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+def check_batch_input(app_settings: ApplicationSettings):
+ if not read_metadata(app_settings=app_settings):
+ return True
+ batch_inquiry(app_settings=app_settings)
+ return True
\ No newline at end of file
diff --git a/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py b/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py
index 22f9939f..139aaec5 100644
--- a/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py
+++ b/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py
@@ -35,7 +35,7 @@ def _hrd_data_requested(app_settings: ApplicationSettings) -> bool:
if choice == "Nee":
keuze = False
cursor.execute(
- f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') VALUES ('extract_hrd_data', {keuze});")
+ f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES ('extract_hrd_data', {keuze});")
conn.commit()
cursor.close()
return keuze
diff --git a/geoprob_pipe/cmd_app/spatial_layers/hrd/import_from_hrd.py b/geoprob_pipe/cmd_app/spatial_layers/hrd/import_from_hrd.py
index 59f5450e..9e3928f3 100644
--- a/geoprob_pipe/cmd_app/spatial_layers/hrd/import_from_hrd.py
+++ b/geoprob_pipe/cmd_app/spatial_layers/hrd/import_from_hrd.py
@@ -40,9 +40,7 @@ def _folder_contains_hrd_db(hrd_dir: str) -> bool:
def _ask_path_to_hrd_dir() -> str:
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
+ while True:
filepath: str = inquirer.text(
message="Specificeer het volledige pad naar de bestandsmap met de Hydra-NL database. "
"Dat zijn de hlcd, config en het database .sqlite-bestand zelf.",
@@ -51,16 +49,16 @@ def _ask_path_to_hrd_dir() -> str:
filepath = filepath.replace('"', '')
if not os.path.isdir(filepath):
- print(BColors.WARNING, f"Het bestandspad moet een directory zijn. Probeer het opnieuw.", BColors.ENDC)
+ print(BColors.WARNING, "Het bestandspad moet een directory zijn. Probeer het opnieuw.", BColors.ENDC)
continue
if not _folder_contains_hrd_db(hrd_dir=filepath):
- print(BColors.WARNING, f"De opgegeven bestandsmap bevat geen of niet alle bestanden van de Hydra-NL "
- f"database. Zorg er voor dat het hlcd-, config.sqlite- en het .sqlite "
- f"database-bestand allen in de map staan. ", BColors.ENDC)
+ print(BColors.WARNING, "De opgegeven bestandsmap bevat geen of niet alle bestanden van de Hydra-NL "
+ "database. Zorg er voor dat het hlcd-, config.sqlite- en het .sqlite "
+ "database-bestand allen in de map staan. ", BColors.ENDC)
continue
- filepath_is_valid = True
+ break
return filepath
@@ -202,14 +200,14 @@ def _add_traject_parameters(app_settings: ApplicationSettings, hrd_dir: str):
conn = sqlite3.connect(file_path)
cursor = conn.cursor()
cursor.execute(
- f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') VALUES ('traject_id', '{traject_id}');")
+ f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES ('traject_id', '{traject_id}');")
cursor.execute(
- f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') "
+ f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) "
f"VALUES ('signaleringswaarde', {signaleringswaarde});")
cursor.execute(
- f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') VALUES ('ondergrens', {ondergrens});")
- cursor.execute(f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') VALUES ('w', {w});")
- cursor.execute(f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') "
+ f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES ('ondergrens', {ondergrens});")
+ cursor.execute(f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES ('w', {w});")
+ cursor.execute(f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) "
f"VALUES ('is_bovenrivierengebied', {is_bovenrivierengebied});")
conn.commit()
cursor.close()
diff --git a/geoprob_pipe/cmd_app/spatial_layers/hrd/import_from_other_geopackage.py b/geoprob_pipe/cmd_app/spatial_layers/hrd/import_from_other_geopackage.py
index 2b704ab0..ba260cca 100644
--- a/geoprob_pipe/cmd_app/spatial_layers/hrd/import_from_other_geopackage.py
+++ b/geoprob_pipe/cmd_app/spatial_layers/hrd/import_from_other_geopackage.py
@@ -14,9 +14,7 @@
def _ask_for_other_geopackage_file_path() -> str:
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
+ while True:
filepath: str = inquirer.text(
message="Specificeer het volledige bestandspad naar het .geoprob_pipe.gpkg-bestand.",
).execute()
@@ -27,11 +25,12 @@ def _ask_for_other_geopackage_file_path() -> str:
print(BColors.WARNING, f"Het bestand moet een .geoprob_pipe.gpkg-bestand zijn. Jouw invoer "
f"{os.path.basename(filepath)} eindigt niet op deze extensie.", BColors.ENDC)
continue
+
if not os.path.exists(filepath):
print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
continue
- filepath_is_valid = True
+ break
return filepath
@@ -60,23 +59,23 @@ def _add_traject_parameters(other_gpkg_path: str, app_settings: ApplicationSetti
df: DataFrame = read_sql_query("SELECT * FROM geoprob_pipe_metadata;", conn)
conn.close()
- traject_id = df[df["metadata_type"] == "traject_id"]["values"].values[0]
- signaleringswaarde = int(df[df["metadata_type"] == "signaleringswaarde"]["values"].values[0])
- ondergrens = int(df[df["metadata_type"] == "ondergrens"]["values"].values[0])
- w = float(df[df["metadata_type"] == "w"]["values"].values[0])
- is_bovenrivierengebied = bool(int(df[df["metadata_type"] == "is_bovenrivierengebied"]["values"].values[0]))
+ traject_id = df[df["metadata_type"] == "traject_id"]["metadata_value"].values[0]
+ signaleringswaarde = int(df[df["metadata_type"] == "signaleringswaarde"]["metadata_value"].values[0])
+ ondergrens = int(df[df["metadata_type"] == "ondergrens"]["metadata_value"].values[0])
+ w = float(df[df["metadata_type"] == "w"]["metadata_value"].values[0])
+ is_bovenrivierengebied = bool(int(df[df["metadata_type"] == "is_bovenrivierengebied"]["metadata_value"].values[0]))
conn = sqlite3.connect(app_settings.geopackage_filepath)
cursor = conn.cursor()
cursor.execute(
- f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') VALUES ('traject_id', '{traject_id}');")
+ f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES ('traject_id', '{traject_id}');")
cursor.execute(
- f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') "
+ f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) "
f"VALUES ('signaleringswaarde', {signaleringswaarde});")
cursor.execute(
- f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') VALUES ('ondergrens', {ondergrens});")
- cursor.execute(f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') VALUES ('w', {w});")
- cursor.execute(f"INSERT INTO geoprob_pipe_metadata (metadata_type, 'values') "
+ f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES ('ondergrens', {ondergrens});")
+ cursor.execute(f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES ('w', {w});")
+ cursor.execute(f"INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) "
f"VALUES ('is_bovenrivierengebied', {is_bovenrivierengebied});")
conn.commit()
cursor.close()
diff --git a/geoprob_pipe/cmd_app/spatial_layers/intredelijn.py b/geoprob_pipe/cmd_app/spatial_layers/intredelijn.py
deleted file mode 100644
index 94269593..00000000
--- a/geoprob_pipe/cmd_app/spatial_layers/intredelijn.py
+++ /dev/null
@@ -1,129 +0,0 @@
-"""
-TODO Later Should Klein: Controleer of de intredelijn ook echt aan de binnenzijde is.
-
-"""
-
-from __future__ import annotations
-from InquirerPy import inquirer
-from typing import TYPE_CHECKING, Optional
-import warnings
-import os
-from shapely import LineString, MultiLineString
-from geopandas import GeoDataFrame, read_file
-import fiona
-from geoprob_pipe.utils.validation_messages import BColors
-if TYPE_CHECKING:
- from geoprob_pipe.cmd_app.cmd import ApplicationSettings
-
-
-def added_intredelijn(app_settings: ApplicationSettings) -> bool:
- layers = fiona.listlayers(app_settings.geopackage_filepath)
-
- if "intredelijn" in layers:
- print(BColors.OKBLUE, f"✔ Intredelijn al toegevoegd.", BColors.ENDC)
- return True
-
- request_intredelijn_filepath(app_settings=app_settings)
- return True
-
-
-def request_intredelijn_filepath(app_settings: ApplicationSettings):
-
- # Request filepath
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
- filepath: str = inquirer.text(
- message="Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase waarin de "
- "intrede lijnen zitten.",
- ).execute()
-
- filepath = filepath.replace('"', '')
-
- if not (filepath.endswith(".gpkg") or filepath.endswith(".shp") or filepath.endswith(".gdb")):
- print(BColors.WARNING, f"Het bestand moet of een geopackage, shapefile of geodatabase zijn. Jouw invoer "
- f"eindigt op de extensie .{filepath.split(sep='.')[-1]}.", BColors.ENDC)
- continue
- if not os.path.exists(filepath):
- print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
- continue
-
- filepath_is_valid = True
-
- # Import data
- if filepath.endswith(".shp"):
- with warnings.catch_warnings():
- warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
- gdf: GeoDataFrame = read_file(filepath)
- elif filepath.endswith(".gpkg"):
- gdf: GeoDataFrame = import_from_geopackage(filepath=filepath)
- elif filepath.endswith(".gdb"):
- gdf: GeoDataFrame = import_from_geodatabase(filepath=filepath)
- else:
- raise NotImplementedError(
- f"Applicatie vroegtijdig afgesloten: Een {filepath.split(sep='.')[-1]}-bestand is niet geïmplementeerd.")
-
- # Confirm all are points
- all_geometries_are_points = gdf.geometry.apply(
- lambda geom: isinstance(geom, LineString) or isinstance(geom, MultiLineString)).all()
- if not all_geometries_are_points:
- print(BColors.WARNING, f"Het geïmporteerde bestand bestaat niet (volledig) uit lijnen, maar ook uit "
- f"andere typen geometrie. Enkel lijnen zijn toegestaan.", BColors.ENDC)
- request_intredelijn_filepath(app_settings=app_settings)
-
- # Add intredelijn
- gdf_to_add = gdf[["geometry"]]
- gdf_to_add.to_file(app_settings.geopackage_filepath, layer="intredelijn", driver="GPKG")
- print(BColors.OKBLUE, f"✅ Intredelijn toegevoegd.", BColors.ENDC)
-
-
-def import_from_geodatabase(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de layer waarin de intredelijn staat. Type 'listlayers' om "
- "een overzicht te krijgen van de geodatabase-layers. ",
- ).execute()
-
- layer_names = fiona.listlayers(filepath)
- layer_names.sort()
- layers_str = ", ".join(layer_names)
- if layer_name == "listlayers":
- print(BColors.OKBLUE, f"De volgende layers zijn beschikbaar in de geodatabase: {layers_str}", BColors.ENDC)
- continue
- elif layer_name not in layer_names:
- print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
- f"de geodatabase: {layers_str}", BColors.ENDC)
- continue
-
- layer_name_is_valid = True
-
- gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
- return gdf
-
-
-def import_from_geopackage(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de laag met de intrede lijnen. Type 'listlayers' om "
- "een overzicht te krijgen van de geopackage-layers. ",
- ).execute()
-
- layer_names = fiona.listlayers(filepath)
- layer_names.sort()
- layers_str = ", ".join(layer_names)
- if layer_name == "listlayers":
- print(BColors.OKBLUE, f"De volgende layers zijn beschikbaar in de geopackage: {layers_str}", BColors.ENDC)
- continue
- elif layer_name not in layer_names:
- print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
- f"de geopackage: {layers_str}", BColors.ENDC)
- continue
-
- layer_name_is_valid = True
-
- gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
- return gdf
diff --git a/geoprob_pipe/cmd_app/spatial_layers/polderpeil.py b/geoprob_pipe/cmd_app/spatial_layers/polderpeil.py
deleted file mode 100644
index ad73a421..00000000
--- a/geoprob_pipe/cmd_app/spatial_layers/polderpeil.py
+++ /dev/null
@@ -1,149 +0,0 @@
-from __future__ import annotations
-from InquirerPy import inquirer
-from typing import TYPE_CHECKING, Optional
-import os
-from shapely import Polygon, MultiPolygon
-from geopandas import GeoDataFrame, read_file
-import fiona
-from geoprob_pipe.utils.validation_messages import BColors
-import warnings
-if TYPE_CHECKING:
- from geoprob_pipe.cmd_app.cmd import ApplicationSettings
-
-
-def added_polderpeil(app_settings: ApplicationSettings) -> bool:
- layers = fiona.listlayers(app_settings.geopackage_filepath)
-
- if "polderpeil" in layers:
- print(BColors.OKBLUE, f"✔ Polderpeil al toegevoegd.", BColors.ENDC)
- return True
-
- request_polderpeil_filepath(app_settings=app_settings)
- return True
-
-
-def request_polderpeil_filepath(app_settings: ApplicationSettings):
-
- # Request filepath
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
- filepath: str = inquirer.text(
- message="Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase waarin de "
- "polderpeilen zitten.",
- ).execute()
-
- filepath = filepath.replace('"', '')
-
- if not (filepath.endswith(".gpkg") or filepath.endswith(".shp") or filepath.endswith(".gdb")):
- print(BColors.WARNING, f"Het bestand moet of een geopackage, shapefile of geodatabase zijn. Jouw invoer "
- f"eindigt op de extensie .{filepath.split(sep='.')[-1]}.", BColors.ENDC)
- continue
- if not os.path.exists(filepath):
- print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
- continue
-
- filepath_is_valid = True
-
- # Import data
- if filepath.endswith(".shp"):
- with warnings.catch_warnings():
- warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
- gdf: GeoDataFrame = read_file(filepath)
- elif filepath.endswith(".gpkg"):
- gdf: GeoDataFrame = import_from_geopackage(filepath=filepath)
- elif filepath.endswith(".gdb"):
- gdf: GeoDataFrame = import_from_geodatabase(filepath=filepath)
- else:
- raise NotImplementedError(
- f"Applicatie vroegtijdig afgesloten: Een {filepath.split(sep='.')[-1]}-bestand is niet geïmplementeerd.")
-
- # Confirm all are points
- all_geometries_are_points = gdf.geometry.apply(
- lambda geom: isinstance(geom, Polygon) or isinstance(geom, MultiPolygon)).all()
- if not all_geometries_are_points:
- print(BColors.WARNING, f"Het geïmporteerde bestand bestaat niet (volledig) uit vlakken/polygonen, maar ook uit "
- f"andere typen geometrie. Enkel vlakken/polygonen zijn toegestaan.", BColors.ENDC)
- request_polderpeil_filepath(app_settings=app_settings)
-
- # Continue questionnaire
- specify_column_with_polderpeil_niveau(app_settings, gdf=gdf)
-
-
-def import_from_geodatabase(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de layer waarin met het polderpeil. Type 'listlayers' om "
- "een overzicht te krijgen van de geodatabase-layers. ",
- ).execute()
-
- layer_names = fiona.listlayers(filepath)
- layer_names.sort()
- layers_str = ", ".join(layer_names)
- if layer_name == "listlayers":
- print(BColors.OKBLUE, f"De volgende layers zijn beschikbaar in de geodatabase: {layers_str}", BColors.ENDC)
- continue
- elif layer_name not in layer_names:
- print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
- f"de geodatabase: {layers_str}", BColors.ENDC)
- continue
-
- layer_name_is_valid = True
-
- gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
- return gdf
-
-
-def import_from_geopackage(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de laag met de polderpeilen. Type 'listlayers' om "
- "een overzicht te krijgen van de geopackage-layers. ",
- ).execute()
-
- layer_names = fiona.listlayers(filepath)
- layer_names.sort()
- layers_str = ", ".join(layer_names)
- if layer_name == "listlayers":
- print(BColors.OKBLUE, f"De volgende layers zijn beschikbaar in de geopackage: {layers_str}", BColors.ENDC)
- continue
- elif layer_name not in layer_names:
- print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
- f"de geopackage: {layers_str}", BColors.ENDC)
- continue
-
- layer_name_is_valid = True
-
- gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
- return gdf
-
-
-def specify_column_with_polderpeil_niveau(app_settings: ApplicationSettings, gdf: GeoDataFrame):
- column_name: Optional[str] = None
- column_name_is_valid = False
- while column_name_is_valid is False:
- column_name: str = inquirer.text(
- message="Specificeer de kolom waarin het polderpeil staat. Type 'listcolumns' om "
- "een overzicht te krijgen van de kolommen.",
- ).execute()
-
- column_names = gdf.columns
- columns_str = ", ".join(column_names)
- if column_name == "listcolumns":
- print(BColors.OKBLUE,
- f"De volgende kolommen zijn beschikbaar in de spatial layer: {columns_str}", BColors.ENDC)
- continue
- elif column_name not in column_names:
- print(BColors.OKBLUE, f"De kolom naam '{column_name}' bestaat niet. De volgende kolommen zijn beschikbaar "
- f"in de spatial layer: {columns_str}", BColors.ENDC)
- continue
- column_name_is_valid = True
-
- gdf_to_add = gdf[["geometry", column_name]]
- gdf_to_add = gdf_to_add.rename(columns={column_name: "polderpeil"})
- gdf_to_add.to_file(app_settings.geopackage_filepath, layer="polderpeil", driver="GPKG")
- print(BColors.OKBLUE, f"✅ Polderpeilen toegevoegd.", BColors.ENDC)
diff --git a/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/alg_walking_circles.py b/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/alg_walking_circles.py
index 7eb99ca4..22057cdf 100644
--- a/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/alg_walking_circles.py
+++ b/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/alg_walking_circles.py
@@ -1,5 +1,5 @@
from __future__ import annotations
-from geoprob_pipe.cmd_app.spatial_layers.ahn import added_ahn, request_ahn
+from geoprob_pipe.cmd_app.spatial_layers.added_ahn import added_ahn, request_ahn
from typing import TYPE_CHECKING, Optional, Tuple, List
from geoprob_pipe.cmd_app.utils.spatial import load_dijktraject_linestring, load_hydra_nl_as_multipoint
from shapely import LineString, MultiPoint, Polygon, MultiPolygon, Point, unary_union
@@ -19,26 +19,27 @@
def request_buffer_distance() -> int:
int_distance = 50
- distance_is_valid = False
- while distance_is_valid is False:
+ while True:
str_distance: str = inquirer.text(
message="Specificeer de afstand (in meters) waarbinnen gezocht moet worden aan binnendijkse zijde.\n"
"Zorg er voor dat deze afstand volledig binnen het toegevoegde raster valt. ",
).execute()
# Validate
- try: int_distance = int(str_distance)
+ try:
+ int_distance = int(str_distance)
except ValueError:
print(f"{BColors.WARNING}Het lukte niet om de invoer om te zetten naar een integer (geheel getal). Weet je "
f"zeker dat de invoer correct is? Probeer het opnieuw.{BColors.ENDC}")
continue
+
if int_distance < 50:
print(f"{BColors.WARNING}De opgegeven afstand moet ten minste 50 meter zijn. "
f"Vul opnieuw een waarde in. {BColors.ENDC}")
continue
# Valid
- distance_is_valid = True
+ break
return int_distance
diff --git a/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/uittredepunten.py b/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/uittredepunten.py
index 2d7a2733..c320927a 100644
--- a/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/uittredepunten.py
+++ b/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/uittredepunten.py
@@ -1,6 +1,6 @@
from __future__ import annotations
from InquirerPy import inquirer
-from typing import TYPE_CHECKING, Optional
+from typing import TYPE_CHECKING
import os
import sys
from geoprob_pipe.cmd_app.spatial_layers.uittredepunten.alg_walking_circles import algorithm_walking_circles
@@ -53,7 +53,7 @@ def define_method_of_adding_uittredepunten(app_settings: ApplicationSettings):
# elif choice == choices_list[2]:
# generate_uittredepunten_suggestions(app_settings=app_settings)
elif choice == choices_list[1]:
- sys.exit(f"Applicatie is afgesloten.")
+ sys.exit("Applicatie is afgesloten.")
else:
raise ValueError
@@ -72,14 +72,19 @@ def import_uittredepunten_gis_file(app_settings: ApplicationSettings):
request_uittredepunten_filepath(app_settings=app_settings)
-def import_from_geodatabase(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de layer waarin met de uittredepunten. Type 'listlayers' om "
- "een overzicht te krijgen van de geodatabase-layers. ",
- ).execute()
+def import_from_geodatabase(app_settings: ApplicationSettings, filepath: str) -> GeoDataFrame:
+ layer_name: str = ""
+ skip_batch = False # Als batch input faalt ga over op handmatig
+ while True:
+ if app_settings.batch_input and not skip_batch:
+ layer_name = app_settings.input_config.get(
+ "uittredepunten", "database_layer"
+ )
+ else:
+ layer_name: str = inquirer.text(
+ message="Specificeer de layer waarin met de uittredepunten. Type 'listlayers' om "
+ "een overzicht te krijgen van de geodatabase-layers. ",
+ ).execute()
layer_names = fiona.listlayers(filepath)
layer_names.sort()
@@ -90,22 +95,29 @@ def import_from_geodatabase(filepath: str) -> GeoDataFrame:
elif layer_name not in layer_names:
print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
f"de geodatabase: {layers_str}", BColors.ENDC)
+ skip_batch = True
continue
- layer_name_is_valid = True
+ break
gdf: GeoDataFrame = read_file(filepath, layer=layer_name)
return gdf
-def import_from_geopackage(filepath: str) -> GeoDataFrame:
- layer_name: Optional[str] = None
- layer_name_is_valid = False
- while layer_name_is_valid is False:
- layer_name: str = inquirer.text(
- message="Specificeer de layer waarin met de uittredepunten. Type 'listlayers' om "
- "een overzicht te krijgen van de geopackage-layers. ",
- ).execute()
+def import_from_geopackage(app_settings: ApplicationSettings, filepath: str) -> GeoDataFrame:
+ layer_name: str = ""
+ skip_batch = False # Als batch input faalt ga over op handmatig
+
+ while True:
+ if app_settings.batch_input and not skip_batch:
+ layer_name = app_settings.input_config.get(
+ "uittredepunten", "database_layer"
+ )
+ else:
+ layer_name: str = inquirer.text(
+ message="Specificeer de layer waarin met de uittredepunten. Type 'listlayers' om "
+ "een overzicht te krijgen van de geopackage-layers. ",
+ ).execute()
layer_names = fiona.listlayers(filepath)
layer_names.sort()
@@ -116,9 +128,10 @@ def import_from_geopackage(filepath: str) -> GeoDataFrame:
elif layer_name not in layer_names:
print(BColors.OKBLUE, f"De laag name '{layer_name}' bestaat niet. De volgende layers zijn beschikbaar in "
f"de geopackage: {layers_str}", BColors.ENDC)
+ skip_batch = True
continue
- layer_name_is_valid = True
+ break
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message="Measured \\(M\\) geometry types are not supported.*")
@@ -150,13 +163,19 @@ def generate_uittredepunten_suggestions(app_settings: ApplicationSettings):
def request_uittredepunten_filepath(app_settings: ApplicationSettings):
# Request filepath
- filepath: Optional[str] = None
- filepath_is_valid = False
- while filepath_is_valid is False:
- filepath: str = inquirer.text(
- message="Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase waarin de "
- "uittredepunten zitten.",
- ).execute()
+ filepath: str = ""
+ skip_batch = False # Als batch input faalt ga over op handmatig
+
+ while True:
+ if app_settings.batch_input and not skip_batch:
+ filepath = app_settings.input_config.get(
+ "uittredepunten", "filepath"
+ )
+ else:
+ filepath: str = inquirer.text(
+ message="Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase waarin de "
+ "uittredepunten zitten.",
+ ).execute()
filepath = filepath.replace('"', '')
@@ -165,18 +184,21 @@ def request_uittredepunten_filepath(app_settings: ApplicationSettings):
f"eindigt op de extensie .{filepath.split(sep='.')[-1]}.", BColors.ENDC)
continue
if not os.path.exists(filepath):
- print(BColors.WARNING, f"Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
+ print(BColors.WARNING, "Het opgegeven bestandspad bestaat niet.", BColors.ENDC)
+ skip_batch = True
continue
- filepath_is_valid = True
+ break
# Import data
if filepath.endswith(".shp"):
gdf: GeoDataFrame = read_file(filepath)
elif filepath.endswith(".gpkg"):
- gdf: GeoDataFrame = import_from_geopackage(filepath=filepath)
+ gdf: GeoDataFrame = import_from_geopackage(app_settings=app_settings,
+ filepath=filepath)
elif filepath.endswith(".gdb"):
- gdf: GeoDataFrame = import_from_geodatabase(filepath=filepath)
+ gdf: GeoDataFrame = import_from_geodatabase(app_settings=app_settings,
+ filepath=filepath)
else:
raise NotImplementedError(
f"Applicatie vroegtijdig afgesloten: Een {filepath.split(sep='.')[-1]}-bestand is nog niet "
@@ -194,14 +216,19 @@ def request_uittredepunten_filepath(app_settings: ApplicationSettings):
def specify_column_with_maaiveld_niveau(app_settings: ApplicationSettings, gdf: GeoDataFrame):
- column_name: Optional[str] = None
- column_name_is_valid = False
- while column_name_is_valid is False:
- column_name: str = inquirer.text(
- message="Specificeer de kolom waarin het maaiveld niveau staat. Type 'listcolumns' om "
- "een overzicht te krijgen van de kolommen. Type 'n.a.' als het maaiveld niveau niet gekoppeld is "
- "aan de punten, dan zal de applicatie in een volgende stap deze voor je downloaden.",
- ).execute()
+ column_name: str = ""
+ skip_batch = False
+ while True:
+ if app_settings.batch_input and not skip_batch:
+ column_name = app_settings.input_config.get(
+ "uittredepunten", "mv_exit_kolom"
+ )
+ else:
+ column_name: str = inquirer.text(
+ message="Specificeer de kolom waarin het maaiveld niveau staat. Type 'listcolumns' om "
+ "een overzicht te krijgen van de kolommen. Type 'n.a.' als het maaiveld niveau niet gekoppeld is "
+ "aan de punten, dan zal de applicatie in een volgende stap deze voor je downloaden.",
+ ).execute()
column_names = gdf.columns
columns_str = ", ".join(column_names)
@@ -218,8 +245,9 @@ def specify_column_with_maaiveld_niveau(app_settings: ApplicationSettings, gdf:
elif column_name not in column_names:
print(BColors.OKBLUE, f"De kolom naam '{column_name}' bestaat niet. De volgende kolommen zijn beschikbaar "
f"in de spatial layer: {columns_str}", BColors.ENDC)
+ skip_batch = True
continue
- column_name_is_valid = True
+ break
gdf_to_add = gdf[["geometry", column_name]]
# No uittredepunt id yet. This will be set when the metering is determined.
diff --git a/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py
new file mode 100644
index 00000000..f3bf1a98
--- /dev/null
+++ b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py
@@ -0,0 +1,73 @@
+from __future__ import annotations
+
+import sqlite3
+from typing import TYPE_CHECKING
+
+from geoprob_pipe.calculations.systems.model4a.initial_input import (
+ INITIAL_INPUT as MODEL4A_INPUT,
+)
+from geoprob_pipe.calculations.systems.moria.initial_input import (
+ INITIAL_INPUT as MORIA_INPUT,
+)
+from geoprob_pipe.calculations.systems.wbi.initial_input import (
+ INITIAL_INPUT as WBI_INPUT,
+)
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+# Lijst van parameters die verwerkt kunnen worden:
+# Polygon of raster alleen beschikbaar als iets per uittredepunt kan verschillen
+# en afstand tot de keringlijn uitmaakt.
+LIST_PARAMS: dict[str, dict] = {
+ "mv_exit": {"shape": ["raster"]},
+ "polderpeil": {"shape": ["line", "polygon", "raster"]},
+ "buitenwaterstand_gemiddeld": {"shape": ["line"]},
+ "phi_exit_gemiddeld": {"shape": ["line", "polygon", "raster"]},
+ "r_exit": {"shape": ["line", "polygon", "raster"]},
+ "k_wvp": {"shape": ["line"]},
+ "kD_wvp": {"shape": ["line"]},
+ "modelfactor_h": {"shape": ["line"]},
+ "modelfactor_ff": {"shape": ["line"]},
+ "modelfactor_3d": {"shape": ["line"]},
+ "modelfactor_ml": {"shape": ["line"]},
+ "i_c_h": {"shape": ["line"]},
+ "modelfactor_u": {"shape": ["line"]},
+ "modelfactor_p": {"shape": ["line"]},
+ "d70": {"shape": ["line"]},
+ "c_voorland": {"shape": ["line"]},
+ "c_achterland": {"shape": ["line"]},
+}
+
+def valid_parameter_list(app_settings: ApplicationSettings):
+ """
+ Bepaal de lijst met parameters op basis van de ingevoerde lijst en de parameters
+ die in het gekozen model gebruikt worden.
+
+ :param app_settings: Object met de instellingen van de app.
+ :return: Lijst met de parameters die ruimtelijk ingevoerd kunnen worden.
+ """
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+ cur = conn.cursor()
+ cur.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type='geohydrologisch_model'"
+ )
+ model = cur.fetchone()[0]
+ conn.close()
+
+ input_list: list[str] = [param for param in LIST_PARAMS.keys()]
+ valid_list = []
+ match model:
+ case "model4a":
+ model_list = [param["name"] for param in MODEL4A_INPUT]
+ valid_list = [param for param in input_list if param in model_list]
+
+ case "wbi":
+ model_list = [param["name"] for param in WBI_INPUT]
+ valid_list = [param for param in input_list if param in model_list]
+
+ case "moria":
+ model_list = [param["name"] for param in MORIA_INPUT]
+ valid_list = [param for param in input_list if param in model_list]
+
+ return valid_list
diff --git a/geoprob_pipe/cmd_app/utils/batch_input.py b/geoprob_pipe/cmd_app/utils/batch_input.py
new file mode 100644
index 00000000..f67712c8
--- /dev/null
+++ b/geoprob_pipe/cmd_app/utils/batch_input.py
@@ -0,0 +1,161 @@
+from __future__ import annotations
+
+import configparser
+import sqlite3
+import sys
+from typing import TYPE_CHECKING
+
+from InquirerPy.prompts.list import ListPrompt
+
+if TYPE_CHECKING:
+ from geoprob_pipe.cmd_app.cmd import ApplicationSettings
+
+
+def batch_inquiry(app_settings: ApplicationSettings):
+ """
+ Keuzemenu voor het gebruik van ee batch input bestand of handmatige invoer.
+
+ :param app_settings: _description_
+ """
+ choices_list = [
+ "Nee, handmatig invoeren",
+ "Ja, invoeren via `batch_input.ini` bestand",
+ "Maak het `batch_input.ini` bestand aan",
+ ]
+ while True:
+ choice = ListPrompt(
+ message=(
+ "Wil je de gis-lagen handmatig invoeren of via een batch_input.ini bestand?"
+ ),
+ choices=choices_list,
+ default=choices_list[0],
+ ).execute()
+
+ match choice:
+ case "Nee, handmatig invoeren":
+ update_batch_metadata(app_settings=app_settings, value=False)
+ return
+ case "Ja, invoeren via `batch_input.ini` bestand":
+ app_settings.batch_input = True
+ return
+ case "Maak het `batch_input.ini` bestand aan":
+ batch_config_writer(app_settings)
+ app_settings.batch_input = True
+ ready_inquiry()
+ return
+
+
+def ready_inquiry():
+ """
+ Keuzemenu als wacht periode voor het invullen van batch_input.ini.
+ """
+ choices_list = [
+ "batch_input.ini is klaar voor uitlezen",
+ "applicatie afsluiten",
+ ]
+ while True:
+ choise = ListPrompt(
+ message="Is het batch_input.ini bestand klaar voor gebruik?",
+ choices=choices_list,
+ default=choices_list[0],
+ ).execute()
+ match choise:
+ case "batch_input.ini is klaar voor uitlezen":
+ return
+ case "applicatie afsluiten":
+ sys.exit("Applicatie is afgesloten.")
+
+
+def batch_config_writer(app_settings: ApplicationSettings):
+ """
+ Functie om het bestand op te zetten voor alle benodigde handelingen.
+
+ :param app_settings: _description_
+ """
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("ruimtelijke_parameters",),
+ )
+ parameters: list[str] = cursor.fetchone()[0].split(", ")
+ conn.close()
+
+ config = configparser.ConfigParser()
+
+ config["vakindeling"] = {
+ "filepath": "",
+ "database_layer": "",
+ "vak_naam_kolom": "",
+ "vak_id_kolom": "",
+ }
+
+ config["uittredepunten"] = {
+ "filepath": "",
+ "database_layer": "",
+ "mv_exit_kolom": "",
+ }
+
+ config["binnenteenlijn"] = {
+ "filepath": "",
+ "database_layer": "",
+ }
+
+ config["buitenteenlijn"] = {
+ "filepath": "",
+ "database_layer": "",
+ }
+
+ config["intredelijn"] = {
+ "filepath": "",
+ "database_layer": "",
+ }
+
+ if not parameters == [""]:
+ for parameter in parameters:
+ config[parameter] = {"filepath": "", "database_layer": ""}
+
+ with open(f"{app_settings.workspace_dir}/batch_input.ini", "w") as f:
+ f.write("""
+# Dit is een bestand om een deel van de invoer van GeoProb-Pipe in
+# een keer in te voeren. Hier moeten dezelfde paden, lagen en kolommen
+# worden ingevoerd als met de handmatige invoer.
+
+# Geef bij 'filepath' het volledige bestandspad op naar het bestand met de invoer.
+# Als het bestand een shapefile is mag je de volgende waarde leeg houden.
+# Deze wordt alleen uitgelezen bij een database(.gdb of .gpkg)
+# Geef bij 'database_layer' de naam op van de laag waarin de invoer staat.
+# Soms moet er ook nog een kolom worden opgegeven:
+# Geef bij '*_kolom' de kolom naam op waarin de opgevraagde parameter in staat.
+
+""")
+ config.write(f)
+
+def update_batch_metadata(app_settings: ApplicationSettings, value: bool):
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+
+ sql_update = "UPDATE geoprob_pipe_metadata SET metadata_value = ? WHERE metadata_type = ?"
+ sql_insert = "INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES (?, ?)"
+
+ with conn: # transaction
+ cur = conn.execute(sql_update, (value, "batch_inquiry")) # type:ignore
+ if cur.rowcount == 0:
+ conn.execute(sql_insert, ("batch_inquiry", value)) # type:ignore
+ conn.execute(sql_update, (value, "batch_inquiry"))
+
+ conn.commit()
+ conn.close()
+
+def read_metadata(app_settings: ApplicationSettings):
+ conn = sqlite3.connect(app_settings.geopackage_filepath)
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?",
+ ("batch_inquiry",),
+ )
+ row = cursor.fetchone()
+ conn.close()
+ if row is None:
+ return True
+
+ return bool(int(row[0]))
\ No newline at end of file
diff --git a/geoprob_pipe/cmd_app/utils/misc.py b/geoprob_pipe/cmd_app/utils/misc.py
index 63ba4716..b5035eb2 100644
--- a/geoprob_pipe/cmd_app/utils/misc.py
+++ b/geoprob_pipe/cmd_app/utils/misc.py
@@ -18,7 +18,7 @@ def get_geohydrological_model(app_settings: ApplicationSettings) -> str:
conn = sqlite3.connect(app_settings.geopackage_filepath)
cursor = conn.cursor()
cursor.execute("""
- SELECT geoprob_pipe_metadata."values"
+ SELECT geoprob_pipe_metadata.metadata_value
FROM geoprob_pipe_metadata
WHERE metadata_type='geohydrologisch_model';
""")
diff --git a/geoprob_pipe/input_data/input_data_object.py b/geoprob_pipe/input_data/input_data_object.py
index 6b917071..84ca0ff2 100644
--- a/geoprob_pipe/input_data/input_data_object.py
+++ b/geoprob_pipe/input_data/input_data_object.py
@@ -150,7 +150,7 @@ def geohydrologisch_model(self) -> str:
conn = sqlite3.connect(self.app_settings.geopackage_filepath)
cursor = conn.cursor()
cursor.execute("""
- SELECT geoprob_pipe_metadata."values"
+ SELECT geoprob_pipe_metadata.metadata_value
FROM geoprob_pipe_metadata
WHERE metadata_type='geohydrologisch_model';
""")
diff --git a/geoprob_pipe/input_data/traject_normering.py b/geoprob_pipe/input_data/traject_normering.py
index 07ef8cdb..1d43f397 100644
--- a/geoprob_pipe/input_data/traject_normering.py
+++ b/geoprob_pipe/input_data/traject_normering.py
@@ -14,11 +14,11 @@ def _data_from_metadata_table(app_settings: ApplicationSettings) -> Tuple[str, b
df: DataFrame = read_sql_query("SELECT * FROM geoprob_pipe_metadata;", conn)
conn.close()
- traject_id = df[df["metadata_type"] == "traject_id"]["values"].values[0]
- signaleringswaarde = int(df[df["metadata_type"] == "signaleringswaarde"]["values"].values[0])
- ondergrens = int(df[df["metadata_type"] == "ondergrens"]["values"].values[0])
- w = float(df[df["metadata_type"] == "w"]["values"].values[0])
- is_bovenrivierengebied = bool(int(df[df["metadata_type"] == "is_bovenrivierengebied"]["values"].values[0]))
+ traject_id = df[df["metadata_type"] == "traject_id"]["metadata_value"].values[0]
+ signaleringswaarde = int(df[df["metadata_type"] == "signaleringswaarde"]["metadata_value"].values[0])
+ ondergrens = int(df[df["metadata_type"] == "ondergrens"]["metadata_value"].values[0])
+ w = float(df[df["metadata_type"] == "w"]["metadata_value"].values[0])
+ is_bovenrivierengebied = bool(int(df[df["metadata_type"] == "is_bovenrivierengebied"]["metadata_value"].values[0]))
return traject_id, is_bovenrivierengebied, signaleringswaarde, ondergrens, w
diff --git a/geoprob_pipe/results/assemblage/functions.py b/geoprob_pipe/results/assemblage/functions.py
index c3db7dd3..84f060f2 100644
--- a/geoprob_pipe/results/assemblage/functions.py
+++ b/geoprob_pipe/results/assemblage/functions.py
@@ -17,7 +17,7 @@ def combine_series(list_pf: list[float]) -> Tuple[float, float]:
doorsneden.
:param list_pf: Lijst met faalkansen van de elementen.
- :return bovengrens en ondergrens
+ :return: bovengrens en ondergrens
"""
# If empty
@@ -28,7 +28,7 @@ def combine_series(list_pf: list[float]) -> Tuple[float, float]:
ondergrens = max(list_pf)
# We have to use Decimal for bovengrens
- getcontext().prec = 30
+ getcontext().prec = 100
# Because with small numbers (e-18 and smaller) it turns out that 1 - e-18 is rounded to one. Therefore, we have to
# use Decimal with a lowered precision (we use up to e-30). We now first convert the necessary values to Decimal:
one = Decimal(1)
@@ -111,13 +111,15 @@ def window_collect(window_size: float, point_list: list[UittredepuntElement],
bins_window = np.arange(
m_van, m_tot, window_size
).tolist()
- bins_window.append(m_tot)
+ if m_tot not in bins_window:
+ bins_window.append(m_tot) # add end of final window
bin_cat: pd.Categorical = cast(pd.Categorical, pd.cut(
list_m_value,
bins=bins_window,
right=False,
- include_lowest=True
+ include_lowest=True,
+ duplicates="drop"
))
df_vak = df_vak.assign(bin=bin_cat)
df_bin = (df_vak.groupby("bin", observed=False)["pf"].max()
@@ -125,8 +127,8 @@ def window_collect(window_size: float, point_list: list[UittredepuntElement],
sum_pf, max_pf = combine_series(df_bin.to_list())
window_elements: List[WindowElement] = []
- bins_window.append(m_tot) # add end of final window
- for i in range(len(bins_window)-2):
+
+ for i in range(len(bins_window)-1):
window_elements.append(WindowElement(
m_van=bins_window[i],
m_tot=bins_window[i+1],
@@ -164,7 +166,7 @@ def scaled_collect(
windows.
"""
from geoprob_pipe.results.assemblage.objects import WindowElement
- if point_list.__len__() == 0: # Leeg element
+ if len(point_list) == 0: # Leeg element
return 0.0, 0.0, []
fcn_list = [p.flow_chart_number for p in point_list]
if min(fcn_list) == 11:
@@ -214,7 +216,7 @@ def scaled_collect(
length = seg_end - seg_start
a = sel.a
N_vak = bepaal_N_vak(length, a, dL)
- pf = cast(float, sel.pf) * N_vak
+ pf = min(1, cast(float, sel.pf) * N_vak) # Limiet als pf zeer hoog is.
pfs.append(pf)
window_elements.append(
WindowElement(
diff --git a/geoprob_pipe/results/assemblage/objects.py b/geoprob_pipe/results/assemblage/objects.py
index cb8f1ad5..37a1917b 100644
--- a/geoprob_pipe/results/assemblage/objects.py
+++ b/geoprob_pipe/results/assemblage/objects.py
@@ -25,13 +25,13 @@ def __post_init__(self):
if self.pf is not None:
if not (0.0 <= self.pf <= 1.0):
- raise ValueError("pof moet tussen 0.0 en 1.0 liggen.")
+ raise ValueError(f"pof moet tussen 0.0 en 1.0 liggen. Huidige waarde is {self.pf}")
- if self.beta is not None:
- if not math.isfinite(self.beta):
- raise ValueError("beta moet een eindige waarde zijn.")
- if (-38.0 <= self.beta <= 38.0) is False:
- raise ValueError("beta moet tussen -38.0 en 38.0 liggen.")
+ # if self.beta is not None:
+ # if not math.isfinite(self.beta):
+ # raise ValueError("beta moet een eindige waarde zijn.")
+ # if (-38.0 <= self.beta <= 38.0) is False:
+ # raise ValueError(f"beta moet tussen -38.0 en 38.0 liggen. Huidige waarde is {self.beta}")
if self.pf is None and self.beta is not None:
self.pf = float(stats.norm.cdf(-1.0 * self.beta))
@@ -56,13 +56,13 @@ def __post_init__(self):
if self.pf is not None:
if not (0.0 <= self.pf <= 1.0):
- raise ValueError("pof moet tussen 0.0 en 1.0 liggen.")
+ raise ValueError(f"pof moet tussen 0.0 en 1.0 liggen. Huidige waarde is {self.pf}")
- if self.beta is not None:
- if not math.isfinite(self.beta):
- raise ValueError("beta moet een eindige waarde zijn.")
- if (-38.0 <= self.beta <= 38.0) is False:
- raise ValueError("beta moet tussen -38.0 en 38.0 liggen.")
+ # if self.beta is not None:
+ # if not math.isfinite(self.beta):
+ # raise ValueError("beta moet een eindige waarde zijn.")
+ # if (-38.0 <= self.beta <= 38.0) is False:
+ # raise ValueError(f"beta moet tussen -38.0 en 38.0 liggen. Huidige waarde is {self.beta}")
if self.pf is None and self.beta is not None:
self.pf = float(stats.norm.cdf(-1.0 * self.beta))
@@ -121,7 +121,7 @@ def pf_max_dsn(self) -> Tuple[KansElement, KansElement]:
pf_dsn = max(list_pf)
# Bereken vak kans
- pf_vak = self.N_vak * pf_dsn
+ pf_vak = min(1, self.N_vak * pf_dsn) # Limit naar 1 bij zeer hoge pof.
return KansElement(pf=pf_dsn), KansElement(pf=pf_vak)
@@ -131,7 +131,7 @@ def conv_max_dsn(self) -> bool:
kansen geconvergeerd zijn, dan True, anders False. Want een niet geconvergeerde kans had de maximale faalkans
kunnen zijn. """
list_conv = [cast(bool, dsn.converged) for dsn in self.dsn_list]
- if False in list_conv:
+ if all(list_conv):
return False
return True
diff --git a/geoprob_pipe/results/construct_dataframes.py b/geoprob_pipe/results/construct_dataframes.py
index 63a0f42d..a0e566c3 100644
--- a/geoprob_pipe/results/construct_dataframes.py
+++ b/geoprob_pipe/results/construct_dataframes.py
@@ -1,18 +1,30 @@
from __future__ import annotations
-from geoprob_pipe.utils.statistics import convert_failure_probability_to_beta
+
+import operator
+from decimal import Decimal, getcontext
+from functools import reduce
+from typing import TYPE_CHECKING, List
+
+import numpy as np
import pandas as pd
-from geoprob_pipe.results.assemblage.objects import (
- UittredepuntElement, VakElement, TrajectElement)
from pandas import DataFrame, concat
-import numpy as np
-from typing import TYPE_CHECKING, List
+
+from geoprob_pipe.results.assemblage.objects import (
+ TrajectElement,
+ UittredepuntElement,
+ VakElement,
+)
+from geoprob_pipe.utils.statistics import convert_failure_probability_to_beta
+
if TYPE_CHECKING:
- from geoprob_pipe.results import Results
- from geoprob_pipe import GeoProbPipe
- from geoprob_pipe.calculations.systems.base_objects.system_calculation import \
- SystemCalculation
from probabilistic_library import DesignPoint
+
+ from geoprob_pipe import GeoProbPipe
+ from geoprob_pipe.calculations.systems.base_objects.system_calculation import (
+ SystemCalculation,
+ )
from geoprob_pipe.calculations.systems.build_and_run import CalcResult
+ from geoprob_pipe.results import Results
def collect_df_beta_limit_state(calculation: SystemCalculation) -> DataFrame:
@@ -196,12 +208,39 @@ def calculate_df_beta_per_uittredepunt(geoprob_pipe: GeoProbPipe, results: Resul
df_beta_scenarios_final = results.df_beta_scenarios_final.copy(deep=True)
- df = df_beta_scenarios_final.assign(
- failure_probability=df_beta_scenarios_final.apply(
- lambda row: row['failure_probability'] * geoprob_pipe.input_data.scenarios.scenario_kans(
- vak_id=row['vak_id'], scenario_naam=row['ondergrondscenario_id']
- ), axis=1)).groupby('uittredepunt_id', as_index=False)[
- 'failure_probability'].sum()
+ # The sum() leads to failure probalilities of larger than 1. Due to very small
+ # values decimal is used.
+ getcontext().prec = 100
+ one = Decimal(1)
+ df = (
+ df_beta_scenarios_final.assign(
+ failure_probability=lambda row: (
+ row["failure_probability"]
+ * row.apply(
+ lambda row: (
+ geoprob_pipe.input_data.scenarios.scenario_kans(
+ vak_id=row["vak_id"],
+ scenario_naam=row["ondergrondscenario_id"],
+ )
+ ),
+ axis=1,
+ )
+ )
+ )
+ .groupby("uittredepunt_id", as_index=False)
+ .agg(
+ failure_probability=(
+ "failure_probability",
+ lambda x: float(
+ one
+ - reduce(
+ operator.mul, (one - Decimal(str(v)) for v in x), one
+ )
+ ),
+ )
+ )
+ )
+
df["beta"] = df["failure_probability"].apply(lambda failure_prob: convert_failure_probability_to_beta(failure_prob))
# Determine when uittredepunt is converged (when all scenarios are converged)
diff --git a/geoprob_pipe/utils/df_validation/dataframe.py b/geoprob_pipe/utils/df_validation/dataframe.py
index 4501d415..ff67a813 100644
--- a/geoprob_pipe/utils/df_validation/dataframe.py
+++ b/geoprob_pipe/utils/df_validation/dataframe.py
@@ -17,15 +17,15 @@ class DataFrameValidation:
def __init__(
self, df: DataFrame, label: str,
- columns_validations: List[ColumnValidation], required_columns: List[str] = None,
+ columns_validations: List[ColumnValidation], required_columns: List[str] = [],
):
self.label: str = label
self.df: DataFrame = df
- self.required_columns: Optional[List[str]] = required_columns
+ self.required_columns: List[str] = required_columns
self.columns_validations: List[ColumnValidation] = columns_validations
# Placeholders
- self.df_failures: Optional[DataFrame] = None
+ self.df_failures: DataFrame = DataFrame()
def _run_required_columns(self) -> DataFrame:
failure_rows = []
diff --git a/geoprob_pipe/utils/df_validation/requirements.py b/geoprob_pipe/utils/df_validation/requirements.py
index 3499ed83..66d0354a 100644
--- a/geoprob_pipe/utils/df_validation/requirements.py
+++ b/geoprob_pipe/utils/df_validation/requirements.py
@@ -34,11 +34,13 @@ def __init__(
def is_not_null(s: Series) -> Series:
- return s.notna()
+ s_num = to_numeric(s, errors="coerce")
+ return s_num.notna()
def is_null(s: Series) -> Series:
- return ~s.notna()
+ s_num = to_numeric(s, errors="coerce")
+ return ~s_num.notna()
def is_in(values: List):
@@ -60,8 +62,10 @@ def is_integer(s: Series) -> Series:
def is_whole_number(s: Series) -> Series:
- return s.notna() & (s % 1 == 0)
+ s_num = to_numeric(s, errors="coerce") # De tweede test breekt als er iets anders dan een getal in staan.
+ return s_num.notna() & (s_num % 1 == 0)
def is_numeric(s: Series) -> Series:
- return to_numeric(s, errors="coerce").notna()
+ s_num = to_numeric(s, errors="coerce")
+ return s_num.notna()
diff --git a/geoprob_pipe/utils/update_metadata.py b/geoprob_pipe/utils/update_metadata.py
index 4626aba4..06dfbb85 100644
--- a/geoprob_pipe/utils/update_metadata.py
+++ b/geoprob_pipe/utils/update_metadata.py
@@ -17,8 +17,8 @@ def _to_text(v):
def _upsert_metadata(conn, table, metadata_type, value):
- sql_update = f'UPDATE {table} SET "values" = ? WHERE metadata_type = ?'
- sql_insert = f'INSERT INTO {table} (metadata_type, "values") VALUES (?, ?)'
+ sql_update = f'UPDATE {table} SET metadata_value = ? WHERE metadata_type = ?'
+ sql_insert = f'INSERT INTO {table} (metadata_type, metadata_value) VALUES (?, ?)'
with conn: # transaction
cur = conn.execute(sql_update, (value, metadata_type))
@@ -43,19 +43,19 @@ def update_metadata(geoprob_pipe: GeoProbPipe):
records = [
{"metadata_type": "last_calculation_run_datetime",
- "values": geoprob_pipe.input_data.app_settings.datetime_stamp},
+ "metadata_value": geoprob_pipe.input_data.app_settings.datetime_stamp},
{"metadata_type": "last_calculation_rub_in_seconds",
- "values": geoprob_pipe.time_diff.total_seconds()},
+ "metadata_value": geoprob_pipe.time_diff.total_seconds()},
{"metadata_type": "last_calculation_run_vakken_to_run",
- "values": ran_vakken_ids},
+ "metadata_value": ran_vakken_ids},
{"metadata_type": "last_calculation_run_nr_of_calculations",
- "values": n_calcs},
+ "metadata_value": n_calcs},
{"metadata_type": "last_calculation_run_nr_of_uittredepunten",
- "values": n_points},
+ "metadata_value": n_points},
{"metadata_type": "last_calculation_run_nr_of_vakken",
- "values": n_vakken},
+ "metadata_value": n_vakken},
{"metadata_type": "last_calculation_run_percentage_of_uittredepunten",
- "values": ratio_points * 100}
+ "metadata_value": ratio_points * 100}
]
conn = sqlite3.connect(gpkg_path)
@@ -63,6 +63,6 @@ def update_metadata(geoprob_pipe: GeoProbPipe):
for r in records:
_upsert_metadata(conn=conn, table=table,
metadata_type=r["metadata_type"],
- value=_to_text(r["values"]))
+ value=_to_text(r["metadata_value"]))
conn.commit()
conn.close()
diff --git a/geoprob_pipe/visualizations/graphs/__init__.py b/geoprob_pipe/visualizations/graphs/__init__.py
index 50b90198..4a98c861 100644
--- a/geoprob_pipe/visualizations/graphs/__init__.py
+++ b/geoprob_pipe/visualizations/graphs/__init__.py
@@ -7,7 +7,7 @@
from geoprob_pipe.visualizations.graphs.physical_values_along_levee import physical_values_buitenwaterstand_and_top_zand
from geoprob_pipe.visualizations.graphs.invloedsfactoren import invloedsfactoren
from geoprob_pipe.visualizations.graphs.phreatic_waterline import phreatic_waterline
-from geoprob_pipe.visualizations.graphs.overview_alpha import overview_alpha
+from geoprob_pipe.visualizations.graphs.overview_alpha import OverviewAlpha
from geoprob_pipe.visualizations.graphs.river_waterlevel import river_waterlevel
from typing import TYPE_CHECKING
from plotly.graph_objects import Figure as PlotlyFigure
@@ -59,7 +59,7 @@ def phreatic_waterline(self) -> PlotlyFigure:
return phreatic_waterline(self.geoprob_pipe, export=False)
def overview_alpha(self) -> PlotlyFigure:
- return overview_alpha(self.geoprob_pipe, export=False)
+ return OverviewAlpha(self.geoprob_pipe, export=False).fig
def river_waterlevel(self) -> PlotlyFigure:
return river_waterlevel(self.geoprob_pipe, export=False)
@@ -71,5 +71,5 @@ def export_graphs(self):
self.physical_values_buitenwaterstand_and_top_zand(export=True)
self.invloedsfactoren(export=True)
phreatic_waterline(self.geoprob_pipe, export=True)
- overview_alpha(self.geoprob_pipe, export=True)
+ OverviewAlpha(self.geoprob_pipe, export=True)
river_waterlevel(self.geoprob_pipe, export=True)
diff --git a/geoprob_pipe/visualizations/graphs/assemblage_icicle.py b/geoprob_pipe/visualizations/graphs/assemblage_icicle.py
index 58c4ba0d..653a17cc 100644
--- a/geoprob_pipe/visualizations/graphs/assemblage_icicle.py
+++ b/geoprob_pipe/visualizations/graphs/assemblage_icicle.py
@@ -1,10 +1,11 @@
from __future__ import annotations
+
import os
-import plotly.graph_objects as go
-import pandas as pd
from typing import TYPE_CHECKING, Dict, List, cast
-from pandas import Series, DataFrame
+import pandas as pd
+import plotly.graph_objects as go
+from pandas import DataFrame, Series
if TYPE_CHECKING:
from geoprob_pipe import GeoProbPipe
@@ -12,6 +13,14 @@
class IciclePlot:
def __init__(self, geoprob_pipe: GeoProbPipe, export: bool = False):
+ """
+ Class voor het maken en exporteren van een Icicle plot van de assemblage.
+ Hierin kan worden gezien hoe de faalkansen en beta's tot stand komen
+ vanuit onderliggende elementen.
+
+ :param geoprob_pipe: Hoofdobject van de applicatie.
+ :param export: Of het figuur geëxporteerd wordt, defaults to False.
+ """
self.geoprob_pipe: GeoProbPipe = geoprob_pipe
self.export: bool = export
self.fig = go.Figure()
@@ -21,9 +30,14 @@ def __init__(self, geoprob_pipe: GeoProbPipe, export: bool = False):
self._optionally_export()
def _setup_df(self):
+ """
+ Set de DataFrame op voor de icicle door de verschillende lagen stap
+ voor stap samen te voegen. De `id` kolom functioneert als key voor het
+ koppelen.
+ """
# Per element parent_name, label, pf, beta
- df_traject = self.geoprob_pipe.results.df_beta_traject
- df_vakken = self.geoprob_pipe.results.df_beta_WBI_vakken
+ df_traject = self.geoprob_pipe.results.df_beta_traject.copy()
+ df_vakken = self.geoprob_pipe.results.df_beta_WBI_vakken.copy()
df_vakken = df_vakken.rename(columns={"beta_dsn": "beta",
"pf_dsn(max)": "pf"})
@@ -31,9 +45,9 @@ def _setup_df(self):
mask_vakken = df_vakken["pf"] != 0
df_vakken = df_vakken[mask_vakken].copy()
- df_utp = self.geoprob_pipe.results.df_beta_uittredepunten
- df_scen = self.geoprob_pipe.results.df_beta_scenarios_final
- df_lim = self.geoprob_pipe.results.df_beta_limit_states
+ df_utp = self.geoprob_pipe.results.df_beta_uittredepunten.copy()
+ df_scen = self.geoprob_pipe.results.df_beta_scenarios_final.copy()
+ df_lim = self.geoprob_pipe.results.df_beta_limit_states.copy()
# traject
mask_traject = df_traject["method"] == "Sum of vakken"
@@ -148,6 +162,12 @@ def _setup_df(self):
self.df_icicle = df_icicle
def _beta_to_color(self, beta: float) -> str:
+ """
+ Vindt de juiste riskeer kleuren bij de betawaardes op basis van de norm.
+
+ :param beta: beta waarde om kleur van te bepalen.
+ :return: rgba waardes van de juiste kleur als string.
+ """
cg: Dict[str, List[float]] = self.geoprob_pipe.input_data.traject_normering.riskeer_categorie_grenzen
# labels = ["+III", "+II", "+I", "0", "-I", "-II", "-III"]
colors = [
@@ -161,9 +181,9 @@ def _beta_to_color(self, beta: float) -> str:
]
# Limit beta to range for colors
if beta < 2:
- return "rgba(30,141,41,0.6)"
- elif beta > 20:
return "rgba(177,33,38,0.6)"
+ elif beta > 20:
+ return "rgba(30,141,41,0.6)"
else:
for i, grens in enumerate(cg):
beta_min, beta_max = cg[grens]
@@ -173,6 +193,9 @@ def _beta_to_color(self, beta: float) -> str:
return "rgba(128,128,128,0.6)"
def _plot(self):
+ """
+ Maak de icicle-plot op basis van de ongezette dataframe.
+ """
df = self.df_icicle
mask_vakken = df["parent_name"].eq("1")
@@ -220,6 +243,9 @@ def _update_layout(self):
)
def _optionally_export(self):
+ """
+ Maak de html van de plot met ingebouwde scroll bar.
+ """
if self.export:
path = self.geoprob_pipe.visualizations.graphs.export_dir
diff --git a/geoprob_pipe/visualizations/graphs/betrouwbaarheidsindex.py b/geoprob_pipe/visualizations/graphs/betrouwbaarheidsindex.py
index a28a4720..bfc1f16e 100644
--- a/geoprob_pipe/visualizations/graphs/betrouwbaarheidsindex.py
+++ b/geoprob_pipe/visualizations/graphs/betrouwbaarheidsindex.py
@@ -1,10 +1,13 @@
from __future__ import annotations
-from pandas import DataFrame, merge, Series
-import numpy as np
+
import os
from datetime import datetime
-import plotly.graph_objects as go
from typing import TYPE_CHECKING
+
+import numpy as np
+import plotly.graph_objects as go
+from pandas import DataFrame, Series, merge
+
if TYPE_CHECKING:
from geoprob_pipe import GeoProbPipe
@@ -85,6 +88,12 @@ def _add_beta_per_uittredepunt_indication_below_plotting_range(
class GraphBetaValuesSingleInteractive:
def __init__(self, geoprob_pipe: GeoProbPipe, export: bool = True):
+ """
+ Class voor het maken van de betrouwbaarheidsindex plot.
+
+ :param geoprob_pipe: Hoofdobject van de applicatie.
+ :param export: Of de figuur geëxporteerd moet worden, defaults to True
+ """
# Logic
self.geoprob_pipe = geoprob_pipe
@@ -112,6 +121,9 @@ def __init__(self, geoprob_pipe: GeoProbPipe, export: bool = True):
self._optionally_export(export=export)
def _add_backgrond(self):
+ """
+ Voeg de achtergrond kleuren toe op basis van de normwaarden.
+ """
# Oude categorie grenzen
# cg = (self.geoprob_pipe.input_data.traject_normering
# .beta_categorie_grenzen)
@@ -207,6 +219,11 @@ def _add_backgrond(self):
))
def _add_beta_per_scenario(self):
+ """
+ Voeg de traces van de scenarios toe aan de plot, inclusief extra
+ symbolen voor punten die buiten de range vallen. En niet geconvergeerde
+ resultaten in een andere kleur.
+ """
df_beta_scenarios_final = self.geoprob_pipe.results.df_beta_scenarios_final
df_for_graph: DataFrame = merge(
left=df_beta_scenarios_final[[
@@ -276,6 +293,11 @@ def _add_beta_per_scenario(self):
"Metrering: %{customdata[2]}")))
def _add_beta_per_uittredepunt(self):
+ """
+ Voeg de traces van de uittredepunten toe aan de plot, inclusief extra
+ symbolen voor punten die buiten de range vallen. En niet geconvergeerde
+ resultaten in een andere kleur.
+ """
# Gather results to plot
df_results_uittredepunten = self.geoprob_pipe.results.df_beta_uittredepunten
@@ -309,6 +331,11 @@ def _add_beta_per_uittredepunt(self):
name=name, color=color, value=value)
def _add_beta_per_vak(self):
+ """
+ Voeg de traces van de vakken toe aan de plot, inclusief extra
+ symbolen voor punten die buiten de range vallen. En niet geconvergeerde
+ resultaten in een andere kleur.
+ """
# Gather data
df_results_vakken = self.geoprob_pipe.results.df_beta_WBI_vakken
df_results_vakken = df_results_vakken.rename(
@@ -381,6 +408,9 @@ def _add_beta_per_vak(self):
first = False
def _add_beta_per_traject(self):
+ """
+ Voeg de trace van het traject toe aan de plot.
+ """
df = self.geoprob_pipe.results.df_beta_traject
df = df[df["method"] == 'WBI methode over traject']
beta_traject: float = df["lower_bound_beta"].iloc[0]
@@ -400,6 +430,10 @@ def _add_beta_per_traject(self):
))
def _update_layout(self):
+ """
+ Voeg de lay-out van de plot toe inclusief knoppen om de lijnen en vak
+ annotaties aan en uit te zetten.
+ """
if self.verder_rekenen_geadviseerd:
self.fig.add_trace(go.Scatter(
x=[0], y=[0], name="Verder rekenen geadviseerd", showlegend=True,
@@ -427,8 +461,8 @@ def _update_layout(self):
legend=dict(
yanchor="top",
y=0.99,
- xanchor="left",
- x=0.01
+ xanchor="right",
+ x=-0.01
),
annotations=annotation,
shapes=self.vak_lines
diff --git a/geoprob_pipe/visualizations/graphs/hfreq.py b/geoprob_pipe/visualizations/graphs/hfreq.py
index b5462860..b323e873 100644
--- a/geoprob_pipe/visualizations/graphs/hfreq.py
+++ b/geoprob_pipe/visualizations/graphs/hfreq.py
@@ -148,7 +148,7 @@ def _add_overschrijdingsfrequentielijnen(self):
for index, fragility_values_ref in enumerate(self.df_fragility_ref_data["fragility_values_ref"].unique()):
# Collect data for the graph
- fragility_values, _, uittredepunten, uittredepunten_multiline = self._get_fragility_values_ref_data(
+ fragility_values, _, _, uittredepunten_multiline = self._get_fragility_values_ref_data(
ref=fragility_values_ref)
levels = [item.x for item in fragility_values]
self.max_level = max(self.max_level, max(levels))
@@ -219,10 +219,10 @@ def _update_layout(self):
title=f"Overschrijdingsfrequentielijnen voor alle HydraNL locaties
"
f"Traject {self.geoprob_pipe.input_data.traject_normering.traject_id}",
xaxis=dict(
- title=f"Waterstand (m+NAP)", type='linear', showgrid=True, gridwidth=0.5, gridcolor="gray",
+ title="Waterstand (m+NAP)", type='linear', showgrid=True, gridwidth=0.5, gridcolor="gray",
range=[self.min_level - xaxis_add, self.max_level + xaxis_add]),
yaxis=dict(
- title=f"Overschrijdingsfrequentie (log-schaal)", type='log', showgrid=True, tickformat=".0e",
+ title="Overschrijdingsfrequentie (log-schaal)", type='log', showgrid=True, tickformat=".0e",
gridwidth=1.0, tickvals=y_ticks, ticktext=y_ticks_text, tickmode='array', gridcolor="gray",
minor=dict(
showgrid=True, dtick="D1", gridwidth=0.5, gridcolor='rgb(199, 197, 193)')))
diff --git a/geoprob_pipe/visualizations/graphs/overview_alpha.py b/geoprob_pipe/visualizations/graphs/overview_alpha.py
index fefb4fd9..bcd2e13f 100644
--- a/geoprob_pipe/visualizations/graphs/overview_alpha.py
+++ b/geoprob_pipe/visualizations/graphs/overview_alpha.py
@@ -1,183 +1,227 @@
from __future__ import annotations
+
import os
-import pandas as pd
+from typing import TYPE_CHECKING
+
import plotly.graph_objects as go
-from plotly.subplots import make_subplots
from pandas import merge
-from geoprob_pipe.calculations.systems.mappers.initial_input import INITIAL_INPUT_MAPPER
-from typing import TYPE_CHECKING
+from plotly.subplots import make_subplots
+from plotly.graph_objects import Figure
+
+from geoprob_pipe.calculations.systems.mappers.initial_input import (
+ INITIAL_INPUT_MAPPER,
+)
from geoprob_pipe.cmd_app.utils.misc import get_geohydrological_model
if TYPE_CHECKING:
from geoprob_pipe import GeoProbPipe
-def overview_alpha(geoprob_pipe: GeoProbPipe, export: bool = False):
-
- model_string = get_geohydrological_model(app_settings=geoprob_pipe.input_data.app_settings)
- initial_input_mapper = INITIAL_INPUT_MAPPER[model_string]['input']
-
- # Get data for graphing
- df = geoprob_pipe.results.df_alphas_influence_factors_and_physical_values(
- filter_deterministic=False, filter_derived=False)
- df = df[["uittredepunt_id", "ondergrondscenario_id", "vak_id", "variable", "distribution_type", "physical_value"]]
-
- gdf_uittredepunten = geoprob_pipe.input_data.uittredepunten.gdf
- df = merge(df, gdf_uittredepunten[["uittredepunt_id", "metrering"]], on="uittredepunt_id", how="left")
-
- # Determine scenario order per uittredepunt_id
- df["scenario_order"] = (
- df.groupby("uittredepunt_id")["ondergrondscenario_id"].transform(lambda x: pd.factorize(x)[0] + 1))
- scenario_orders = sorted(df["scenario_order"].unique())
-
- # List of all alphas that can be shown
- parameters: list[str] = list(df["variable"].unique())
- # Add distribution type
- dist_types = {}
- for param in parameters:
- dist_type = df.loc[
- df["variable"] == param, "distribution_type"].unique()[0]
- dist_types.update({param: dist_type})
- # Add units
- unit_lookup = {item["name"]: item["unit"] for item in initial_input_mapper}
- param_units = {}
- for param in parameters:
- try:
- param_units.update({param: str(unit_lookup[param]).strip("[]")})
- except KeyError:
- param_units.update({param: "?"})
-
- # Add parameter units missing in DUMMY_INPUT by hand.
- param_units.update({
- "L_kwelweg": "m",
- "L_voorland": "m",
- "W_voorland": "s/m",
- "buitenwaterstand_gemiddeld": "m+NAP",
- "d_deklaag": "m",
- "dh_c": "m",
- "dh_red": "m",
- "dphi_c_u": "m+NAP",
- "h_exit": "m+NAP",
- "i_exit": "-",
- "k_wvp": "m/dag",
- "lambda_voorland": "m",
- "phi_exit": "m+NAP",
- "phi_exit_gemiddeld": "m+NAP",
- "r_exit": "-",
- "z_combin": "-",
- "z_h": "-",
- "z_p": "-",
- "z_u": "-"
- })
-
- # Create subplots
- fig = make_subplots(
- rows=len(parameters),
- cols=1,
- shared_xaxes=False,
- subplot_titles=parameters
- )
-
- # Add a button for each ondergrondscenario
- buttons = []
-
- # Add scatter plot per scenario
- for i, scen_order in enumerate(scenario_orders):
- df_case = df[df["scenario_order"] == scen_order]
-
- for row_idx, param in enumerate(parameters, start=1):
- df_param = df_case[df_case["variable"] == param]
- fig.add_trace(
- go.Scatter(
- x=df_param["metrering"],
- y=df_param["physical_value"],
- mode="markers",
- marker=dict(color="black", symbol="x", size=5),
- name=param,
- visible=(i == 0)
- ),
- row=row_idx, col=1
- )
- fig.update_xaxes(showgrid=True, tickangle=90,
- row=row_idx, col=1)
- fig.update_yaxes(showgrid=True,
- title_text=f"{param} [{param_units[param]}]"
- + f"
({dist_types[param]})",
- row=row_idx, col=1)
-
- total_traces = len(scenario_orders) * len(parameters)
-
- # Determine which scenario is visible
- vis = [False] * total_traces
- vis[i*len(parameters):(i+1)*len(parameters)] = [True] * len(parameters)
-
- buttons.append(dict(
- label=f"Scenario {scen_order}",
- method="update",
- args=[
- {"visible": vis},
- {"title": f"Overview of parameters for Scenario {scen_order}"}
+class OverviewAlpha:
+ def __init__(self, geoprob_pipe: GeoProbPipe, export: bool = False):
+ """
+ Verzameling plots van alle alpha's van de vreschillende parameters.
+
+ :param geoprob_pipe: Hoofdopbject van de applicatie.
+ :param export: of de plot als html geëxporteerd moet worden, defaults to False
+ :return: plotly figuur
+ """
+ self.geoprob_pipe = geoprob_pipe
+ self.export = export
+ self.model_string = get_geohydrological_model(
+ app_settings=self.geoprob_pipe.input_data.app_settings
+ )
+ self.initial_input_mapper = INITIAL_INPUT_MAPPER[self.model_string][
+ "input"
+ ]
+
+ self._collect_data()
+ self.fig = self._create_plot()
+ self._export()
+
+ def _collect_data(self):
+ """
+ Verzamelen de data voor de alphas en metrering en voeg de distributies
+ en eenheden toe.
+
+ :return: _description_
+ """
+ # Get data for graphing
+ df_alpha = self.geoprob_pipe.results.df_alphas_influence_factors_and_physical_values(
+ filter_deterministic=False, filter_derived=False
+ )
+ df_alpha = df_alpha[
+ [
+ "uittredepunt_id",
+ "ondergrondscenario_id",
+ "vak_id",
+ "variable",
+ "distribution_type",
+ "physical_value",
]
- ))
-
- # Layout and button
- fig.update_layout(
- height=300*len(parameters),
- showlegend=False,
- title=f"Overview of parameters for Scenario {scenario_orders[0]}",
- updatemenus=[dict(
- active=0,
- buttons=buttons,
- direction="down",
- showactive=True,
- x=1.05, y=1.01
- )],
- )
-
- # Export
- if export:
- export_dir = os.path.join(
- geoprob_pipe.visualizations.graphs.export_dir,
- "grafiek_physical_values"
+ ]
+
+ gdf_uittredepunten = self.geoprob_pipe.input_data.uittredepunten.gdf
+ self.df_alpha = merge(
+ df_alpha,
+ gdf_uittredepunten[["uittredepunt_id", "metrering"]],
+ on="uittredepunt_id",
+ how="left",
)
- os.makedirs(export_dir, exist_ok=True)
- fig.write_html(
- os.path.join(export_dir, "overview_alphas.html"),
- include_plotlyjs='cdn'
+ # List of all alphas that can be shown
+ self.parameters: list[str] = list(df_alpha["variable"].unique())
+
+ # List of scenarios
+ self.scenarios = df_alpha["ondergrondscenario_id"].unique()
+
+ # Add distribution type
+ self.dist_types = {}
+ for param in self.parameters:
+ dist_type = df_alpha.loc[
+ df_alpha["variable"] == param, "distribution_type"
+ ].unique()[0]
+ self.dist_types.update({param: dist_type})
+
+ # Add units
+ unit_lookup = {
+ item["name"]: item["unit"] for item in self.initial_input_mapper
+ }
+ self.param_units = {}
+
+ for param in self.parameters:
+ try:
+ self.param_units.update(
+ {param: str(unit_lookup[param]).strip("[]")}
+ )
+ except KeyError:
+ self.param_units.update({param: "?"})
+
+ # Add parameter units missing in DUMMY_INPUT by hand.
+ self.param_units.update(
+ {
+ "L_kwelweg": "m",
+ "L_voorland": "m",
+ "W_voorland": "s/m",
+ "buitenwaterstand_gemiddeld": "m+NAP",
+ "d_deklaag": "m",
+ "dh_c": "m",
+ "dh_red": "m",
+ "dphi_c_u": "m+NAP",
+ "h_exit": "m+NAP",
+ "i_exit": "-",
+ "k_wvp": "m/dag",
+ "lambda_voorland": "m",
+ "phi_exit": "m+NAP",
+ "phi_exit_gemiddeld": "m+NAP",
+ "r_exit": "-",
+ "z_combin": "-",
+ "z_h": "-",
+ "z_p": "-",
+ "z_u": "-",
+ }
)
- for scen_order in scenario_orders:
- df_case = df[df["scenario_order"] == scen_order]
- fig_case = make_subplots(
- rows=len(parameters), cols=1,
- shared_xaxes=False,
- subplot_titles=parameters
- )
- for row_idx, param in enumerate(parameters, start=1):
+ def _create_plot(self) -> Figure:
+ """
+ Maak de subplots per paramate per scenario. Met maar een scenario zichtbaar.
+ Voegt bij de layout ook een knop toe om te kiezen welke set plots
+ zichtbaar zijn op basis van scenario naam.
+
+ :return: Plotly figuur met de subplots.
+ """
+ # Create subplots
+ fig = make_subplots(
+ rows=len(self.parameters),
+ cols=1,
+ shared_xaxes=False,
+ subplot_titles=self.parameters,
+ )
+
+ # Add a button for each ondergrondscenario
+ buttons = []
+
+ # Add scatter plot per scenario
+ for i, scenario in enumerate(self.scenarios):
+ df_case = self.df_alpha[
+ self.df_alpha["ondergrondscenario_id"] == scenario
+ ]
+
+ for row_idx, param in enumerate(self.parameters, start=1):
df_param = df_case[df_case["variable"] == param]
- fig_case.add_trace(
+ fig.add_trace(
go.Scatter(
x=df_param["metrering"],
y=df_param["physical_value"],
mode="markers",
marker=dict(color="black", symbol="x", size=5),
- name=param
+ name=param,
+ visible=(i == 0),
),
- row=row_idx, col=1
+ row=row_idx,
+ col=1,
+ )
+ fig.update_xaxes(
+ showgrid=True, tickangle=90, row=row_idx, col=1
+ )
+ fig.update_yaxes(
+ showgrid=True,
+ title_text=f"{param} [{self.param_units[param]}]"
+ + f"
({self.dist_types[param]})",
+ row=row_idx,
+ col=1,
+ )
+
+ total_traces = len(self.scenarios) * len(self.parameters)
+
+ # Determine which scenario is visible
+ vis = [False] * total_traces
+ vis[i * len(self.parameters) : (i + 1) * len(self.parameters)] = [
+ True
+ ] * len(self.parameters)
+
+ buttons.append(
+ dict(
+ label=f"{scenario}",
+ method="update",
+ args=[
+ {"visible": vis},
+ {
+ "title": f"Overview of parameters for Scenario {scenario}"
+ },
+ ],
)
- fig_case.update_xaxes(showgrid=True, tickangle=90,
- row=row_idx, col=1)
- fig_case.update_yaxes(showgrid=True,
- title_text=f"{param} [{param_units[param]}]"
- + f"
({dist_types[param]})",
- row=row_idx, col=1)
-
- fig_case.update_layout(
- height=300*len(parameters),
- showlegend=False,
- title=f"Overview of parameters for Scenario {scen_order}"
)
- return fig
+ # Layout and button
+ fig.update_layout(
+ height=300 * len(self.parameters),
+ showlegend=False,
+ title=f"Overview of parameters for Scenario {self.scenarios[0]}",
+ updatemenus=[
+ dict(
+ active=0,
+ buttons=buttons,
+ direction="down",
+ showactive=True,
+ x=1.05,
+ y=1.01,
+ )
+ ],
+ )
+ return fig
+
+ def _export(self):
+ if self.export:
+ export_dir = os.path.join(
+ self.geoprob_pipe.visualizations.graphs.export_dir,
+ "grafiek_physical_values",
+ )
+
+ os.makedirs(export_dir, exist_ok=True)
+
+ self.fig.write_html(
+ os.path.join(export_dir, "overview_alphas.html"),
+ include_plotlyjs="cdn",
+ )
diff --git a/geoprob_pipe/visualizations/graphs/river_waterlevel.py b/geoprob_pipe/visualizations/graphs/river_waterlevel.py
index 51586f3c..dc5bb6d9 100644
--- a/geoprob_pipe/visualizations/graphs/river_waterlevel.py
+++ b/geoprob_pipe/visualizations/graphs/river_waterlevel.py
@@ -1,30 +1,42 @@
from __future__ import annotations
+
import os
+from typing import TYPE_CHECKING, Dict, List, Tuple
+
import numpy as np
-from pandas import DataFrame, concat, Series
-from geopandas import GeoDataFrame
import plotly.colors as pc
+from geopandas import GeoDataFrame
+from pandas import DataFrame, Series, concat
from plotly.graph_objects import Figure, Scatter
-from typing import TYPE_CHECKING, Dict, List, Tuple
-from geoprob_pipe.cmd_app.parameter_input.expand_input_tables import run_expand_input_tables
+
+from geoprob_pipe.cmd_app.parameter_input.expand_input_tables import (
+ run_expand_input_tables,
+)
+
if TYPE_CHECKING:
from geoprob_pipe import GeoProbPipe
-
+# Terugkeertijden om buitenwaterstand bij te plotten
TARGET_FREQS = np.array([
0.1, 0.033333333, 0.01, 0.003333333, 0.001, 0.000333333, 0.0001, 3.33333E-05, 0.00001, 3.33333E-06])
def _collect_data(geoprob_pipe: GeoProbPipe) -> Tuple[DataFrame, GeoDataFrame, DataFrame, DataFrame]:
+ """
+ Verzamel de data voor de plots. Physical values, Metrering, Beta waardes
+ en Hydra curves per uittredepunt.
+ :param geoprob_pipe: Hoofdbestand van de applicatie.
+ :return: Tuple met dataframes van alle onderdelen.
+ """
# Collect uittredepunten
gdf_uittredepunten = geoprob_pipe.input_data.uittredepunten.gdf
# Collect physical values
- df = geoprob_pipe.results.df_alphas_influence_factors_and_physical_values(
+ df_physical = geoprob_pipe.results.df_alphas_influence_factors_and_physical_values(
filter_deterministic=False, filter_derived=False)
- df = df[["uittredepunt_id", "ondergrondscenario_id", "vak_id", "variable", "distribution_type", "physical_value"]]
- df = df.merge(gdf_uittredepunten[["uittredepunt_id", "metrering"]], on="uittredepunt_id", how="left")
+ df_physical = df_physical[["uittredepunt_id", "ondergrondscenario_id", "vak_id", "variable", "distribution_type", "physical_value"]]
+ df_physical = df_physical.merge(gdf_uittredepunten[["uittredepunt_id", "metrering"]], on="uittredepunt_id", how="left")
# Collect Beta results uittredepunten
df_beta = geoprob_pipe.results.df_beta_uittredepunten
@@ -38,14 +50,21 @@ def _collect_data(geoprob_pipe: GeoProbPipe) -> Tuple[DataFrame, GeoDataFrame, D
df_input['parameter_input'].apply(Series)], # Expansion of dict in parameter_input-column
axis=1)
- return df, gdf_uittredepunten, df_beta, df_input
+ return df_physical, gdf_uittredepunten, df_beta, df_input
def _collect_hydra_curves(
- df: DataFrame, gdf_uittredepunten: GeoDataFrame) -> Dict[float, Dict[str, List[float]]]:
+ df_input: DataFrame, gdf_uittredepunten: GeoDataFrame) -> Dict[float, Dict[str, List[float]]]:
+ """
+ Bepaal de hydra curves op de juiste locatie.
+
+ :param df_input: DataFreame met input tabellen voor hrd locaties.
+ :param gdf_uittredepunten: GeoDataFrame met metrering.
+ :return: Hydra curves per locatie als dict.
+ """
hydra_curves = {freq: {"metrering": [], "level": []} for freq in TARGET_FREQS}
- for _, row in df.iterrows():
+ for _, row in df_input.iterrows():
if row["distribution_type"] != "deterministic":
df_subset = gdf_uittredepunten[gdf_uittredepunten["vak_id"] == row["vak_id"]]
if df_subset.empty:
@@ -74,8 +93,16 @@ def _collect_hydra_curves(
def _plot_continuous_exceedance_lines(
fig: Figure, hydra_curves: Dict[float, Dict[str, List[float]]]):
+ """
+ Plot de hydra curves als continue lijnen per herhaaltijd in verschillende
+ kleuren.
- # Blue gradient for lines
+ :param fig: plotly.Figure object met de plots.
+ :param hydra_curves: Dict met Hydra curves per locatie
+ :return: fig
+ """
+
+ # Multicolor gradient for lines
line_colors = pc.sample_colorscale(
colorscale="Jet", samplepoints=np.linspace(start=0.2, stop=0.9, num=len(TARGET_FREQS)))
freq_color_map = {f: c for f, c in zip(TARGET_FREQS, line_colors)}
@@ -95,6 +122,14 @@ def _plot_continuous_exceedance_lines(
def _plot_physical_values(fig: Figure, df: DataFrame) -> Figure:
+ """
+ Plot per uitredepunt de physical value van de buitenwaterstand met een kleur
+ op basis van de beta waarde.
+
+ :param fig: plotly.Figure object met de plots.
+ :param df: Dataframe met de betas.
+ :return: plotly.Figure object met de plots.
+ """
beta_colorscale = "RdYlGn" # Green-to-red scale (low beta = red, high beta = green)
betas = df["beta"].to_numpy()
fig.add_trace(
@@ -129,13 +164,21 @@ def _update_layout(fig: Figure) -> Figure:
def river_waterlevel(geoprob_pipe: GeoProbPipe, export: bool = False):
+ """
+ Maak een plot van de hydra curves voor de buitenwaterstand bij verschillende
+ herhaaltijden samen met de physical value die berekent zijn.
+
+ :param geoprob_pipe: Hoofdbestand van de applicatie.
+ :param export: of het figuur naar html moet worden geëxporteerd, defaults to False
+ :return: plotly.Figure object
+ """
# Prepare base data
df, gdf_uittredepunten, df_beta, df_input = _collect_data(geoprob_pipe=geoprob_pipe)
# Collect Hydra lines (grouped per frequency)
hydra_curves: Dict[float, Dict[str, List[float]]] = _collect_hydra_curves(
- df=df_input, gdf_uittredepunten=gdf_uittredepunten)
+ df_input=df_input, gdf_uittredepunten=gdf_uittredepunten)
# Plot one continuous line per exceedance frequency
fig = Figure()
diff --git a/geoprob_pipe/visualizations/maps/betamap.py b/geoprob_pipe/visualizations/maps/betamap.py
index f5bd9291..aa21210c 100644
--- a/geoprob_pipe/visualizations/maps/betamap.py
+++ b/geoprob_pipe/visualizations/maps/betamap.py
@@ -1,66 +1,85 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Dict, List, Tuple
-import plotly.graph_objects as go
+
import os
+from typing import TYPE_CHECKING, Dict, List, Tuple
+
import geopandas as gpd
-from shapely.geometry import LineString, MultiLineString, GeometryCollection
+import plotly.graph_objects as go
+import fiona
+from shapely.geometry import GeometryCollection, LineString, MultiLineString
if TYPE_CHECKING:
from geoprob_pipe import GeoProbPipe
-def _add_line(geoprob_pipe: GeoProbPipe, fig: go.Figure,
- layer: str, color: str):
- """ Helperfunctie om de lijnen uit de geopackage te vinden en toe te voegen aan de map. Layer is de naam van de
- laag in de geopackage waar de lijn is opgeslagen. Color is de kleur van deze lijn in de map. """
-
- gdf_traject = gpd.read_file(
- geoprob_pipe.input_data.app_settings.geopackage_filepath,
- layer=layer)
- gdf_traject = gdf_traject.to_crs("EPSG:4326")
-
- def plot_linestring(ls, display):
- xs, ys = ls.xy
- xs = list(xs)
- ys = list(ys)
- fig.add_trace(go.Scattermap(
- lon=xs,
- lat=ys,
- mode="lines",
- line=dict(color=color, width=1),
- hoverinfo="none",
- name=layer,
- legendgroup=layer,
- showlegend=display
- ))
-
- show = True
- for geom in gdf_traject.geometry:
- if isinstance(geom, LineString):
- plot_linestring(geom, show)
- show = False
-
- elif isinstance(geom, MultiLineString):
- for line in geom.geoms:
- plot_linestring(line, show)
- show = False
-
- elif isinstance(geom, GeometryCollection):
- for g in geom.geoms:
- if isinstance(g, LineString):
- plot_linestring(g, show)
- show = False
- elif isinstance(g, MultiLineString):
- for line in g.geoms:
- plot_linestring(line, show)
- show = False
-
- else:
- print("Skipping unsupported geometry:", geom.geom_type)
+def _add_line(
+ geoprob_pipe: GeoProbPipe, fig: go.Figure, layer: str, color: str
+):
+ """Helperfunctie om de lijnen uit de geopackage te vinden en toe te voegen aan de map. Layer is de naam van de
+ laag in de geopackage waar de lijn is opgeslagen. Color is de kleur van deze lijn in de map."""
+
+ # Check of er maar een intredelijn of dat er meerdere zijn ingevoerd.
+ gpkg_layers: list[str] = fiona.listlayers(
+ geoprob_pipe.input_data.app_settings.geopackage_filepath
+ )
+ list_layers: list[str] = [
+ lay for lay in gpkg_layers if lay.split("__")[0] == layer
+ ]
+
+ for listed_layer in list_layers:
+ gdf_traject = gpd.read_file(
+ geoprob_pipe.input_data.app_settings.geopackage_filepath,
+ layer=listed_layer,
+ )
+ gdf_traject = gdf_traject.to_crs("EPSG:4326")
+
+ def plot_linestring(ls, display):
+ xs, ys = ls.xy
+ xs = list(xs)
+ ys = list(ys)
+ fig.add_trace(
+ go.Scattermap(
+ lon=xs,
+ lat=ys,
+ mode="lines",
+ line=dict(color=color, width=1),
+ hoverinfo="none",
+ name=listed_layer,
+ legendgroup=layer,
+ showlegend=display,
+ )
+ )
+
+ display = True
+ for geom in gdf_traject.geometry:
+ if isinstance(geom, LineString):
+ plot_linestring(geom, display)
+ display = False
+
+ elif isinstance(geom, MultiLineString):
+ for line in geom.geoms:
+ plot_linestring(line, display)
+ display = False
+
+ elif isinstance(geom, GeometryCollection):
+ for g in geom.geoms:
+ if isinstance(g, LineString):
+ plot_linestring(g, display)
+ display = False
+ elif isinstance(g, MultiLineString):
+ for line in g.geoms:
+ plot_linestring(line, display)
+ display = False
+
+ else:
+ print("Skipping unsupported geometry:", geom.geom_type)
return fig
-def _generate_colorscale(cg: Dict[str, List], labels: List[str]) -> List[Tuple[float, str]]:
+
+def _generate_colorscale(
+ cg: Dict[str, List], labels: List[str]
+) -> List[Tuple[float, str]]:
# cg > category label > [van beta, tot beta]
upper_boundary_beta_graph = cg[labels[0]][1]
lower_boundary_beta_graph = cg[labels[-1]][0]
@@ -70,14 +89,23 @@ def _generate_colorscale(cg: Dict[str, List], labels: List[str]) -> List[Tuple[f
colorscale_intervals: Dict = {}
for index, label in enumerate(labels):
cg_beta_bovengrens = cg[label][1]
- colorscale_intervals[index] = (cg_beta_bovengrens - lower_boundary_beta_graph) / beta_range_graph
+ colorscale_intervals[index] = (
+ cg_beta_bovengrens - lower_boundary_beta_graph
+ ) / beta_range_graph
# Other end boundary value: 0.0
colorscale_intervals[labels.__len__()] = 0.0
# Color scale
- colors = ["rgb(30,141,41)", "rgb(146,206,90)", "rgb(198,226,176)", "rgb(255,255,0)", "rgb(254,165,3)",
- "rgb(255,0,0)", "rgb(177,33,38)"]
+ colors = [
+ "rgb(30,141,41)",
+ "rgb(146,206,90)",
+ "rgb(198,226,176)",
+ "rgb(255,255,0)",
+ "rgb(254,165,3)",
+ "rgb(255,0,0)",
+ "rgb(177,33,38)",
+ ]
colorscale = [
(colorscale_intervals[7], colors[6]),
(colorscale_intervals[6], colors[6]),
@@ -99,7 +127,6 @@ def _generate_colorscale(cg: Dict[str, List], labels: List[str]) -> List[Tuple[f
class BetaMap:
-
def __init__(self, geoprob_pipe: GeoProbPipe, export: bool = False):
self.geoprob_pipe = geoprob_pipe
@@ -117,24 +144,33 @@ def _import_results(self):
# results import
self.inp_point = self.geoprob_pipe.input_data.uittredepunten.gdf
self.res_sc = self.geoprob_pipe.results.df_beta_scenarios_final
- mask = self.inp_point["uittredepunt_id"].isin(self.res_sc["uittredepunt_id"])
+ mask = self.inp_point["uittredepunt_id"].isin(
+ self.res_sc["uittredepunt_id"]
+ )
self.inp_point = self.inp_point[mask]
# Setup of beta category limits
- self.cg: Dict[str, List] = self.geoprob_pipe.input_data.traject_normering.riskeer_categorie_grenzen
+ self.cg: Dict[str, List] = (
+ self.geoprob_pipe.input_data.traject_normering.riskeer_categorie_grenzen
+ )
self.labels: List[str] = list(self.cg.keys())
def _setup_gdf(self):
self.hoverdata = ["uittredepunt_id", "converged", "beta"]
- self.df = self.res_sc.merge(self.inp_point, on="uittredepunt_id", how="inner")
+ self.df = self.res_sc.merge(
+ self.inp_point, on="uittredepunt_id", how="inner"
+ )
idx = self.df.groupby(["uittredepunt_id"])["beta"].idxmin()
self.df = self.df.loc[idx]
self.gdf = gpd.GeoDataFrame(
self.df,
- geometry=gpd.points_from_xy(self.inp_point.geometry.x, self.inp_point.geometry.y),
- crs="EPSG:28992")
+ geometry=gpd.points_from_xy(
+ self.inp_point.geometry.x, self.inp_point.geometry.y
+ ),
+ crs="EPSG:28992",
+ )
# Transformeer naar WGS84 (latitude / longitude)
self.gdf_latlon = self.gdf.to_crs("EPSG:4326")
@@ -167,53 +203,65 @@ def _calculate_zoom(lat_range, lon_range):
def _create_figure(self):
self.fig = go.Figure()
- self.fig.add_trace(go.Scattermap(
- mode="markers",
- lat=self.gdf_latlon.geometry.y,
- lon=self.gdf_latlon.geometry.x,
- marker=dict(size=9, color="black"),
- showlegend=False))
- self.fig.add_trace(go.Scattermap(
- mode='markers',
- lat=self.gdf_latlon.geometry.y, # direct uit geometrie
- lon=self.gdf_latlon.geometry.x, # direct uit geometrie
- marker=dict(
- size=8,
- color=self.gdf_latlon['beta'],
- colorscale=_generate_colorscale(cg=self.cg, labels=self.labels),
- cmin=self.cg[self.labels[6]][0],
- cmax=self.cg[self.labels[0]][1],
- colorbar=dict(
- title="Bèta, WBI cat.",
- tickvals=[
- self.cg[self.labels[6]][0],
- self.cg[self.labels[6]][1],
- self.cg[self.labels[5]][1],
- self.cg[self.labels[4]][1],
- self.cg[self.labels[3]][1],
- self.cg[self.labels[2]][1],
- self.cg[self.labels[1]][1],
- self.cg[self.labels[0]][1]
- ],
- ticktext=[f"{v:.2f}" for v in [
- self.cg[self.labels[6]][0],
- self.cg[self.labels[6]][1],
- self.cg[self.labels[5]][1],
- self.cg[self.labels[4]][1],
- self.cg[self.labels[3]][1],
- self.cg[self.labels[2]][1],
- self.cg[self.labels[1]][1],
- self.cg[self.labels[0]][1]]],
- )
+ self.fig.add_trace(
+ go.Scattermap(
+ mode="markers",
+ lat=self.gdf_latlon.geometry.y,
+ lon=self.gdf_latlon.geometry.x,
+ marker=dict(size=9, color="black"),
+ showlegend=False,
+ )
+ )
+ self.fig.add_trace(
+ go.Scattermap(
+ mode="markers",
+ lat=self.gdf_latlon.geometry.y, # direct uit geometrie
+ lon=self.gdf_latlon.geometry.x, # direct uit geometrie
+ marker=dict(
+ size=8,
+ color=self.gdf_latlon["beta"],
+ colorscale=_generate_colorscale(
+ cg=self.cg, labels=self.labels
+ ),
+ cmin=self.cg[self.labels[6]][0],
+ cmax=self.cg[self.labels[0]][1],
+ colorbar=dict(
+ title="Bèta, WBI cat.",
+ tickvals=[
+ self.cg[self.labels[6]][0],
+ self.cg[self.labels[6]][1],
+ self.cg[self.labels[5]][1],
+ self.cg[self.labels[4]][1],
+ self.cg[self.labels[3]][1],
+ self.cg[self.labels[2]][1],
+ self.cg[self.labels[1]][1],
+ self.cg[self.labels[0]][1],
+ ],
+ ticktext=[
+ f"{v:.2f}"
+ for v in [
+ self.cg[self.labels[6]][0],
+ self.cg[self.labels[6]][1],
+ self.cg[self.labels[5]][1],
+ self.cg[self.labels[4]][1],
+ self.cg[self.labels[3]][1],
+ self.cg[self.labels[2]][1],
+ self.cg[self.labels[1]][1],
+ self.cg[self.labels[0]][1],
+ ]
+ ],
+ ),
),
- hoverinfo='text',
- text=self.gdf_latlon[self.hoverdata].apply(
- lambda row: '
'.join(
- [f"{col}: {row[col]}" for col in self.hoverdata]
+ hoverinfo="text",
+ text=self.gdf_latlon[self.hoverdata].apply(
+ lambda row: "
".join(
+ [f"{col}: {row[col]}" for col in self.hoverdata]
),
- axis=1),
- showlegend=False
- ))
+ axis=1,
+ ),
+ showlegend=False,
+ )
+ )
# Layout
self.fig.update_layout(
@@ -222,33 +270,35 @@ def _create_figure(self):
map_zoom=self.zoom,
map_center=dict(
lat=self.gdf_latlon.geometry.y.mean(),
- lon=self.gdf_latlon.geometry.x.mean()
+ lon=self.gdf_latlon.geometry.x.mean(),
),
legend=dict(
- orientation="h",
- yanchor="bottom",
- y=1.02,
- xanchor="right",
- x=1
+ orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1
),
- dragmode='zoom',
- title='Faalkansberekening STPH'
+ dragmode="zoom",
+ title="Faalkansberekening STPH",
)
def _add_lines(self):
- self.fig = _add_line(self.geoprob_pipe, self.fig,
- "dijktraject", "black")
- self.fig = _add_line(self.geoprob_pipe, self.fig,
- "intredelijn", "blue")
- self.fig = _add_line(self.geoprob_pipe, self.fig,
- "binnenteenlijn", "purple")
- self.fig = _add_line(self.geoprob_pipe, self.fig,
- "buitenteenlijn", "red")
+ self.fig = _add_line(
+ self.geoprob_pipe, self.fig, "dijktraject", "black"
+ )
+ self.fig = _add_line(
+ self.geoprob_pipe, self.fig, "intredelijn", "blue"
+ )
+ self.fig = _add_line(
+ self.geoprob_pipe, self.fig, "binnenteenlijn", "purple"
+ )
+ self.fig = _add_line(
+ self.geoprob_pipe, self.fig, "buitenteenlijn", "red"
+ )
def _optionally_export(self):
if self.export:
path = self.geoprob_pipe.visualizations.maps.export_dir
- self.fig.write_html(os.path.join(
- path, 'Faalkansberekening STPH.html'), include_plotlyjs='cdn')
+ self.fig.write_html(
+ os.path.join(path, "Faalkansberekening STPH.html"),
+ include_plotlyjs="cdn",
+ )
# self.fig.write_image(os.path.join(
# path, 'Faalkansberekening STPH.png'), format='png')
diff --git a/tests/results/assemblage/test_assemblage.py b/tests/results/assemblage/test_assemblage.py
index 976378b1..102c3a79 100644
--- a/tests/results/assemblage/test_assemblage.py
+++ b/tests/results/assemblage/test_assemblage.py
@@ -31,9 +31,10 @@ def test_window():
window_size=10, point_list=list_dsn,
m_van=0, m_tot=40
)
+ print(elements)
assert sum_pf == pytest.approx(1.78e-12)
assert max_pf == pytest.approx(1e-12)
- assert elements.__len__() == 4
+ assert len(elements) == 4
assert elements[0].kans_dsn.pf == 0.0