From 197037b716af389a9641a8c2655d73c72b13938c Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Mon, 11 May 2026 10:30:50 +0200 Subject: [PATCH 01/53] Bugfix validation --- .../input_data/df_validation/df_parameter_invoer.py | 4 ++-- geoprob_pipe/utils/df_validation/requirements.py | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/geoprob_pipe/input_data/df_validation/df_parameter_invoer.py b/geoprob_pipe/input_data/df_validation/df_parameter_invoer.py index 745809dd..033ea130 100644 --- a/geoprob_pipe/input_data/df_validation/df_parameter_invoer.py +++ b/geoprob_pipe/input_data/df_validation/df_parameter_invoer.py @@ -88,13 +88,13 @@ MINIMUM = ColumnValidation(column_name="minimum", requirements=[ ValidationRequirement( - requirement=requirements.is_null, + requirement=requirements.is_not_null, failure_msg=f"De minimum-kolom is momenteel nog buiten gebruik. Laat deze kolom leeg."), ]) MAXIMUM = ColumnValidation(column_name="maximum", requirements=[ ValidationRequirement( - requirement=requirements.is_null, + requirement=requirements.is_not_null, failure_msg=f"De maximum-kolom is momenteel nog buiten gebruik. Laat deze kolom leeg."), ]) diff --git a/geoprob_pipe/utils/df_validation/requirements.py b/geoprob_pipe/utils/df_validation/requirements.py index 3499ed83..796c741d 100644 --- a/geoprob_pipe/utils/df_validation/requirements.py +++ b/geoprob_pipe/utils/df_validation/requirements.py @@ -34,11 +34,11 @@ def __init__( def is_not_null(s: Series) -> Series: - return s.notna() + return ~(s == "") def is_null(s: Series) -> Series: - return ~s.notna() + return (s == "") def is_in(values: List): @@ -60,8 +60,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() From bd77007040414358e1905cd2d2be6db86afbcfd7 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Mon, 11 May 2026 11:39:52 +0200 Subject: [PATCH 02/53] validation bugfix kolom soms niet numeric gelezen. --- .../input_data/df_validation/df_parameter_invoer.py | 4 ++-- geoprob_pipe/results/assemblage/objects.py | 8 ++++---- geoprob_pipe/utils/df_validation/requirements.py | 6 ++++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/geoprob_pipe/input_data/df_validation/df_parameter_invoer.py b/geoprob_pipe/input_data/df_validation/df_parameter_invoer.py index 033ea130..745809dd 100644 --- a/geoprob_pipe/input_data/df_validation/df_parameter_invoer.py +++ b/geoprob_pipe/input_data/df_validation/df_parameter_invoer.py @@ -88,13 +88,13 @@ MINIMUM = ColumnValidation(column_name="minimum", requirements=[ ValidationRequirement( - requirement=requirements.is_not_null, + requirement=requirements.is_null, failure_msg=f"De minimum-kolom is momenteel nog buiten gebruik. Laat deze kolom leeg."), ]) MAXIMUM = ColumnValidation(column_name="maximum", requirements=[ ValidationRequirement( - requirement=requirements.is_not_null, + requirement=requirements.is_null, failure_msg=f"De maximum-kolom is momenteel nog buiten gebruik. Laat deze kolom leeg."), ]) diff --git a/geoprob_pipe/results/assemblage/objects.py b/geoprob_pipe/results/assemblage/objects.py index cb8f1ad5..ed4616f3 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.") + 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.") + 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)) diff --git a/geoprob_pipe/utils/df_validation/requirements.py b/geoprob_pipe/utils/df_validation/requirements.py index 796c741d..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 == "") + s_num = to_numeric(s, errors="coerce") + return s_num.notna() def is_null(s: Series) -> Series: - return (s == "") + s_num = to_numeric(s, errors="coerce") + return ~s_num.notna() def is_in(values: List): From b0c86a7f64cbf17cb98afbb7a4ce03913c6f6db6 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Mon, 11 May 2026 13:45:33 +0200 Subject: [PATCH 03/53] fix voor extreme waarden van pof en beta --- .../geohydrologische_modellen.rst | 2 +- .../input_parameter_figures.py | 2 +- geoprob_pipe/results/assemblage/functions.py | 12 ++-- geoprob_pipe/results/assemblage/objects.py | 22 +++--- geoprob_pipe/results/construct_dataframes.py | 69 +++++++++++++++---- 5 files changed, 74 insertions(+), 33 deletions(-) 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/cmd_app/parameter_input/input_parameter_figures.py b/geoprob_pipe/cmd_app/parameter_input/input_parameter_figures.py index 547e132a..6a691c9c 100644 --- a/geoprob_pipe/cmd_app/parameter_input/input_parameter_figures.py +++ b/geoprob_pipe/cmd_app/parameter_input/input_parameter_figures.py @@ -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/results/assemblage/functions.py b/geoprob_pipe/results/assemblage/functions.py index c3db7dd3..6c445120 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) @@ -117,7 +117,8 @@ def window_collect(window_size: float, point_list: list[UittredepuntElement], 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,7 +126,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 + if m_tot not in bins_window: + bins_window.append(m_tot) # add end of final window for i in range(len(bins_window)-2): window_elements.append(WindowElement( m_van=bins_window[i], @@ -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 ed4616f3..28c6a8bc 100644 --- a/geoprob_pipe/results/assemblage/objects.py +++ b/geoprob_pipe/results/assemblage/objects.py @@ -27,11 +27,11 @@ def __post_init__(self): if not (0.0 <= self.pf <= 1.0): 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(f"beta moet tussen -38.0 en 38.0 liggen. Huidige waarde is {self.beta}") + # 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)) @@ -58,11 +58,11 @@ def __post_init__(self): if not (0.0 <= self.pf <= 1.0): 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(f"beta moet tussen -38.0 en 38.0 liggen. Huidige waarde is {self.beta}") + # 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) 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) From c20bc26186df5d9e073236a6f0404f15bf87f11c Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 12 May 2026 10:50:12 +0200 Subject: [PATCH 04/53] BaseInquiry class --- geoprob_pipe/cmd_app/questionnaire.py | 109 ++++-- .../cmd_app/spatial_layers/__init__.py | 20 +- .../cmd_app/spatial_layers/base_inquiry.py | 319 ++++++++++++++++++ .../cmd_app/spatial_layers/binnenteenlijn.py | 121 +------ .../cmd_app/spatial_layers/buitenteenlijn.py | 123 +------ .../cmd_app/spatial_layers/dijktraject.py | 28 +- .../cmd_app/spatial_layers/intredelijn.py | 117 +------ .../cmd_app/spatial_layers/polderpeil.py | 2 +- .../cmd_app/spatial_layers/scenarios.py | 63 ++++ 9 files changed, 532 insertions(+), 370 deletions(-) create mode 100644 geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py create mode 100644 geoprob_pipe/cmd_app/spatial_layers/scenarios.py diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 34523218..243c340f 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -1,17 +1,38 @@ 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_polderpeil_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_polderpeil, + added_scenarios, + added_uittredepunten, + added_vakindeling, +) + if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -20,36 +41,62 @@ 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) + 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 + 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_scenarios(app_settings=app_settings): + sys.exit(EARLY_EXIT_MESSAGE) + if not added_intredelijn(app_settings=app_settings): + sys.exit(EARLY_EXIT_MESSAGE) + if not added_polderpeil(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) + 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) + 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) + if not run_calculations(app_settings=app_settings): + sys.exit(EARLY_EXIT_MESSAGE) diff --git a/geoprob_pipe/cmd_app/spatial_layers/__init__.py b/geoprob_pipe/cmd_app/spatial_layers/__init__.py index 629ad723..41cf3b35 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/__init__.py +++ b/geoprob_pipe/cmd_app/spatial_layers/__init__.py @@ -1,9 +1,11 @@ -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 +from .ahn import added_ahn +from .base_inquiry import BaseInquiry +from .binnenteenlijn import added_binnenteenlijn +from .buitenteenlijn import added_buitenteenlijn +from .dijktraject import added_dijktraject +from .hrd.hrd import added_hrd_fragility_curves +from .intredelijn import added_intredelijn +from .polderpeil import added_polderpeil +from .scenarios import added_scenarios +from .uittredepunten.uittredepunten import added_uittredepunten +from .vakindeling import added_vakindeling 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..f24202f7 --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -0,0 +1,319 @@ +""" +Baseclass voor het opvragen van de ruimtelijke invoer voor de parameters. +""" + +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 +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, + ) -> None: + """ + Class om de opvraag van de ruimteljke invoer van de parameters. + + :param app_settings: `ApplicationSettings` object + :param param: Parameter die wordt opgevraagd. + :param scenarios: Lijst met scenarios voor ruimtelike invoer. + :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 + conn = sqlite3.connect(app_settings.geopackage_filepath) + cur = conn.cursor() + cur.execute( + "SELECT values FROM geoprob_pipe_metadata WHERE metadata = ?", + ("ruimtelijke_scenarios",), + ) + self.scenarios = cur.fetchone()[0] + + def request_filepath(self): + """ + Method voor het opvragen van het filepath. + """ + + filepath_is_valid = False + + while filepath_is_valid is False: + 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, + ) + 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, + ) + continue + + filepath_is_valid = True + + # Import data + gdf = self._import_data(filepath) # type:ignore + + # Add data to geopackage + self._add_to_gpkg(gdf) + + def _import_data(self, filepath: str) -> gpd.GeoDataFrame: + """ + Helper method voor het importeren van de data. + + :param filepath: _description_ + :raises NotImplementedError: _description_ + :return: _description_ + """ + 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: _description_ + :return: _description_ + """ + layer_name_is_valid = False + while layer_name_is_valid is False: + 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}" + ) + continue + + layer_name_is_valid = True + + 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 importern vanuit een shapefile. + + :param filepath: _description_ + :return: _description_ + """ + + gdf: gpd.GeoDataFrame = gpd.read_file(filepath) + return gdf + + def _check_shape(self, gdf: gpd.GeoDataFrame): + """ + Helper method voor het checken of de geometry het juiste type is. + + :param gdf: _description_ + :return: _description_ + """ + + 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() + + def _add_to_gpkg(self, gdf: gpd.GeoDataFrame): + """ + Helper method om de data aan de geopackage toe te voegen. + + :param gdf: _description_ + """ + layer_name = self.param + if self.include_value and self.scenarios == "": + column_name_is_valid = False + while column_name_is_valid is False: + column_name: str = prompt.InputPrompt( + message=f""" + Specificeer de kolom waarin {self.param} 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 + 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 == "cancel": + self.request_filepath() + + 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]] # type:ignore + gdf_to_add.to_file( + self.app_settings.geopackage_filepath, + layer=f"{layer_name}", + driver="GPKG", + ) + + elif self.include_value and self.scenarios != "": + gdf_to_add = gdf[["geometry", self.scenarios]] + gdf_to_add.to_file( + self.app_settings.geopackage_filepath, + layer=f"{layer_name}", + driver="GPKG", + ) + + elif not self.include_value and self.scenarios == "": + gdf_to_add = gdf[["geometry"]] + gdf_to_add.to_file( + self.app_settings.geopackage_filepath, + layer=f"{layer_name}", + driver="GPKG", + ) + + elif not self.include_value and self.scenarios != "": + valid_anwser = False + while not valid_anwser: + add_layer_per_scenario = prompt.InputPrompt( + message=f""" + Moeten er lagen per ruimtelijk scenario voor {self.param} worden ingeladen? + Er moet een kolom met de naam 'ondergrondscenario' in de attribute tabel + staan met de naam van het scenario waar de geometrie bijhoort. + (y/n)? O ftype 'cancel' om een ander bestand op te geven. + """ + ) + if add_layer_per_scenario == "y": + # per shape id of naam? + for scenario in self.scenarios: + gdf_to_add: gpd.GeoDataFrame = gdf[ + gdf["ondergrondscenario"] == scenario + ][["geometry"]] + layer_name = f"{self.param}_{scenario}" + gdf_to_add.to_file( + self.app_settings.geopackage_filepath, + layer=f"{layer_name}", + driver="GPKG", + ) + pass + elif add_layer_per_scenario == "n": + gdf_to_add = gdf[["geometry"]] + gdf_to_add.to_file( + self.app_settings.geopackage_filepath, + layer=f"{layer_name}", + driver="GPKG", + ) + valid_anwser = True + elif add_layer_per_scenario == "cancel": + self.request_filepath() + else: + continue + + print(BColors.OKBLUE, f"✅ {self.param} toegevoegd.", BColors.ENDC) diff --git a/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py index 8e43a358..f8ce9fd5 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py @@ -5,14 +5,12 @@ """ 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 +from typing import TYPE_CHECKING + import fiona -import warnings from geoprob_pipe.utils.validation_messages import BColors +from geoprob_pipe.cmd_app.spatial_layers import BaseInquiry + if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -21,7 +19,9 @@ 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) + print( + BColors.OKBLUE, f"✔ Binnenteenlijn al toegevoegd.", BColors.ENDC + ) return True request_binnenteenlijn_filepath(app_settings=app_settings) @@ -29,104 +29,9 @@ def added_binnenteenlijn(app_settings: ApplicationSettings) -> bool: 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 + binnenteenlijn_inquiry = BaseInquiry( + app_settings=app_settings, + param="binnenteenlijn", + specific_shape="lines" + ) + binnenteenlijn_inquiry.request_filepath() diff --git a/geoprob_pipe/cmd_app/spatial_layers/buitenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/buitenteenlijn.py index 3aeaedc0..db35481c 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/buitenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/buitenteenlijn.py @@ -4,14 +4,14 @@ """ 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 + +from typing import TYPE_CHECKING + import fiona + +from geoprob_pipe.cmd_app.spatial_layers import BaseInquiry from geoprob_pipe.utils.validation_messages import BColors + if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -20,7 +20,9 @@ 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) + print( + BColors.OKBLUE, f"✔ Buitenteenlijn al toegevoegd.", BColors.ENDC + ) return True request_buitenteenlijn_filepath(app_settings=app_settings) @@ -28,104 +30,9 @@ def added_buitenteenlijn(app_settings: ApplicationSettings) -> bool: 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 + buitenteenlijn_inquiry = BaseInquiry( + app_settings=app_settings, + param="buitenteenlijn", + specific_shape="lines", + ) + buitenteenlijn_inquiry.request_filepath() diff --git a/geoprob_pipe/cmd_app/spatial_layers/dijktraject.py b/geoprob_pipe/cmd_app/spatial_layers/dijktraject.py index 18cb8a74..a25233ef 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/dijktraject.py +++ b/geoprob_pipe/cmd_app/spatial_layers/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") @@ -84,8 +84,10 @@ def specify_geodatabase_layer(app_settings: ApplicationSettings, filepath: str): layer_name_is_valid = False while layer_name_is_valid is False: 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,6 +96,8 @@ 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) @@ -113,8 +117,10 @@ def specify_geopackage_layer(app_settings: ApplicationSettings, filepath: str): layer_name_is_valid = False while layer_name_is_valid is False: 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,6 +129,8 @@ 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) @@ -140,8 +148,10 @@ def specify_column_with_trajectory_name(app_settings: ApplicationSettings, gdf: column_name_is_valid = False while column_name_is_valid is False: 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,6 +160,8 @@ 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) diff --git a/geoprob_pipe/cmd_app/spatial_layers/intredelijn.py b/geoprob_pipe/cmd_app/spatial_layers/intredelijn.py index 94269593..8fe4053d 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/intredelijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/intredelijn.py @@ -4,14 +4,14 @@ """ 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 + +from typing import TYPE_CHECKING + import fiona + +from geoprob_pipe.cmd_app.spatial_layers import BaseInquiry from geoprob_pipe.utils.validation_messages import BColors + if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -28,102 +28,9 @@ def added_intredelijn(app_settings: ApplicationSettings) -> bool: 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 + 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/polderpeil.py b/geoprob_pipe/cmd_app/spatial_layers/polderpeil.py index ad73a421..0e6c4e24 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/polderpeil.py +++ b/geoprob_pipe/cmd_app/spatial_layers/polderpeil.py @@ -25,7 +25,7 @@ def added_polderpeil(app_settings: ApplicationSettings) -> bool: def request_polderpeil_filepath(app_settings: ApplicationSettings): # Request filepath - filepath: Optional[str] = None + filepath: Optional[str] = None # type:ignore filepath_is_valid = False while filepath_is_valid is False: filepath: str = inquirer.text( diff --git a/geoprob_pipe/cmd_app/spatial_layers/scenarios.py b/geoprob_pipe/cmd_app/spatial_layers/scenarios.py new file mode 100644 index 00000000..bd82eecc --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_layers/scenarios.py @@ -0,0 +1,63 @@ +from __future__ import annotations + +import sqlite3 +from typing import TYPE_CHECKING + +import InquirerPy.prompts.input as prompt + +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: _description_ + :return: _description_ + """ + 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: _description_ + """ + scenario_input_is_valid = False + while scenario_input_is_valid is False: + scenario_input: str = prompt.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: + scenarios = scenario_input.split(",") + + + sql_upsert = """ + INSERT INTO geoprob_pipe_metadata (metadata_type, values) + VALUES (?, ?) + ON CONFLICT(metadata_type) DO UPDATE SET + values = excluded.values + """ + conn = sqlite3.connect(app_settings.geopackage_filepath) + conn.cursor().execute(sql_upsert, ("ruimtelijke_scenarios", scenarios)) + conn.commit() + conn.close() \ No newline at end of file From d65fb93e7fdaf65ae27e6d76c44e28ac70357544 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 13 May 2026 10:52:28 +0200 Subject: [PATCH 05/53] Standaard opvragen lijnen en metadata tabel aanpassing --- .../calculations/systems/single_calc.py | 2 +- geoprob_pipe/cmd_app/cmd.py | 2 +- .../cmd_app/general/geohydrologisch_model.py | 6 +- geoprob_pipe/cmd_app/general/project.py | 6 +- .../cmd_app/general/traject_parameters.py | 4 +- .../parameter_input/expand_input_tables.py | 2 +- .../export_input_parameter_excel.py | 2 +- geoprob_pipe/cmd_app/questionnaire.py | 36 +++-- .../cmd_app/spatial_layers/__init__.py | 1 + .../cmd_app/spatial_layers/base_inquiry.py | 97 +++++++------ .../cmd_app/spatial_layers/binnenteenlijn.py | 2 +- .../cmd_app/spatial_layers/hrd/hrd.py | 2 +- .../spatial_layers/hrd/import_from_hrd.py | 10 +- .../hrd/import_from_other_geopackage.py | 20 +-- .../cmd_app/spatial_layers/parameters.py | 130 ++++++++++++++++++ .../cmd_app/spatial_layers/scenarios.py | 31 +++-- geoprob_pipe/cmd_app/utils/misc.py | 2 +- geoprob_pipe/input_data/input_data_object.py | 2 +- geoprob_pipe/input_data/traject_normering.py | 10 +- geoprob_pipe/utils/update_metadata.py | 20 +-- 20 files changed, 276 insertions(+), 111 deletions(-) create mode 100644 geoprob_pipe/cmd_app/spatial_layers/parameters.py 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/cmd_app/cmd.py b/geoprob_pipe/cmd_app/cmd.py index 8fd5d9e8..9cc31466 100644 --- a/geoprob_pipe/cmd_app/cmd.py +++ b/geoprob_pipe/cmd_app/cmd.py @@ -61,7 +61,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'; """) 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..82c45ab9 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]) @@ -218,7 +218,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..6a36c879 100644 --- a/geoprob_pipe/cmd_app/general/traject_parameters.py +++ b/geoprob_pipe/cmd_app/general/traject_parameters.py @@ -15,7 +15,7 @@ def _append_to_db(app_settings: ApplicationSettings, key: str, value): cursor = conn.cursor() cursor.execute( """ - INSERT INTO geoprob_pipe_metadata (metadata_type, "values") VALUES (?, ?); + INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES (?, ?); """, (key, value)) conn.commit() @@ -111,7 +111,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'; """) 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..f8121f1c 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'; """) 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/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 243c340f..181c2d18 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -22,6 +22,7 @@ ) from geoprob_pipe.cmd_app.spatial_layers import ( added_ahn, + added_parameters, added_binnenteenlijn, added_buitenteenlijn, added_dijktraject, @@ -37,7 +38,7 @@ 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): @@ -47,11 +48,15 @@ def start_questionnaire(app_settings: ApplicationSettings): def questionnaire(app_settings: ApplicationSettings): - print(f"\nALGEMEEN") + 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) - print(f"\nGIS LAGEN") + print("\nGIS LAGEN") if not added_dijktraject(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) if not added_vakindeling(app_settings=app_settings): @@ -66,26 +71,30 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) if not added_buitenteenlijn(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_intredelijn(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) - if not added_polderpeil(app_settings=app_settings): - sys.exit(EARLY_EXIT_MESSAGE) + + print("/nRUIMTELIJKE INPUT") + # TODO Loop met alle ruimtelijke parameters + # TODO maak polderpeil optioneel + + # if not added_polderpeil(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") + print("\nGEOGRAFISCHE KOPPELINGEN") + # TODO maak coupleling for line, polygon, raster 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_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( @@ -93,10 +102,13 @@ def questionnaire(app_settings: ApplicationSettings): ): sys.exit(EARLY_EXIT_MESSAGE) - print(f"\nPARAMETER INVOER") + print("\nPARAMETER INVOER") + # TODO Voeg mogelijkheid om ruimtelijke input aan te passen toe. + # TODO Check validation correct blijft werken. + # TODO Invoer voor koppeling? Validatie daarna? if not added_input_parameter_data(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) - print(f"\nBEREKENINGEN UITVOEREN") + print("\nBEREKENINGEN UITVOEREN") if not run_calculations(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) diff --git a/geoprob_pipe/cmd_app/spatial_layers/__init__.py b/geoprob_pipe/cmd_app/spatial_layers/__init__.py index 41cf3b35..b8943dc4 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/__init__.py +++ b/geoprob_pipe/cmd_app/spatial_layers/__init__.py @@ -5,6 +5,7 @@ from .dijktraject import added_dijktraject from .hrd.hrd import added_hrd_fragility_curves from .intredelijn import added_intredelijn +from .parameters import added_parameters from .polderpeil import added_polderpeil from .scenarios import added_scenarios from .uittredepunten.uittredepunten import added_uittredepunten diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index f24202f7..ab4e5d86 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -1,5 +1,6 @@ """ -Baseclass voor het opvragen van de ruimtelijke invoer voor de parameters. +Class voor het opvragen van de ruimtelijke invoer voor de parameters +vanuit GIS lagen. Shapefiles, geodatabases en geopackages worden ondersteund. """ from __future__ import annotations @@ -29,11 +30,11 @@ def __init__( include_value: bool = False, ) -> None: """ - Class om de opvraag van de ruimteljke invoer van de parameters. + Class voor de opvraag van de ruimteljke invoer van de parameters. - :param app_settings: `ApplicationSettings` object - :param param: Parameter die wordt opgevraagd. - :param scenarios: Lijst met scenarios voor ruimtelike invoer. + :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 @@ -46,10 +47,10 @@ def __init__( conn = sqlite3.connect(app_settings.geopackage_filepath) cur = conn.cursor() cur.execute( - "SELECT values FROM geoprob_pipe_metadata WHERE metadata = ?", + "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?", ("ruimtelijke_scenarios",), ) - self.scenarios = cur.fetchone()[0] + self.scenarios: list[str] = cur.fetchone()[0].split(", ") def request_filepath(self): """ @@ -60,10 +61,12 @@ def request_filepath(self): while filepath_is_valid is False: filepath: str = prompt.InputPrompt( - message=f""" - Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase - met de {self.param} geometrieën. - """ + message=( + f""" +Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase +met de {self.param} geometrieën. + """ + ) ).execute() filepath = filepath.replace('"', "") @@ -95,7 +98,6 @@ def request_filepath(self): # Import data gdf = self._import_data(filepath) # type:ignore - # Add data to geopackage self._add_to_gpkg(gdf) @@ -103,9 +105,10 @@ def _import_data(self, filepath: str) -> gpd.GeoDataFrame: """ Helper method voor het importeren van de data. - :param filepath: _description_ - :raises NotImplementedError: _description_ - :return: _description_ + :param filepath: Bestandspad van de shapfile 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(): @@ -137,17 +140,19 @@ def _import_from_db(self, filepath: str) -> gpd.GeoDataFrame: """ Helper method voor het importeren vanuit een gbd of een geopackage. - :param filepath: _description_ - :return: _description_ + :param filepath: Bestandspad van de database. + :return: GeoDataFrame met de uitgelezen data. """ layer_name_is_valid = False while layer_name_is_valid is False: 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. - """ + 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) @@ -178,19 +183,19 @@ def _import_from_shp(self, filepath: str) -> gpd.GeoDataFrame: """ Helper method voor het importern vanuit een shapefile. - :param filepath: _description_ - :return: _description_ + :param filepath: Bestandspad van de shapfile. + :return: GeoDataFrame met de uitgelezen data. """ gdf: gpd.GeoDataFrame = gpd.read_file(filepath) return gdf - def _check_shape(self, gdf: gpd.GeoDataFrame): + def _check_shape(self, gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame | None: """ Helper method voor het checken of de geometry het juiste type is. :param gdf: _description_ - :return: _description_ + :return: GeoDataFrame of None als check faalt. """ if self.specific_shape == "": @@ -215,21 +220,27 @@ def _check_shape(self, gdf: gpd.GeoDataFrame): ) self.request_filepath() + return gdf + def _add_to_gpkg(self, gdf: gpd.GeoDataFrame): """ 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. - :param gdf: _description_ + :param gdf: GeoDataFrame met de uitgelezen data van de laag. """ layer_name = self.param if self.include_value and self.scenarios == "": column_name_is_valid = False while column_name_is_valid is False: column_name: str = prompt.InputPrompt( - message=f""" - Specificeer de kolom waarin {self.param} staat. Type 'listcolumns' om" - een overzicht te krijgen van de kolommen. Type 'cancel' om een ander bestand op te geven. - """, + message=( + f""" +Specificeer de kolom waarin {self.param} 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 @@ -264,6 +275,7 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame): ) elif self.include_value and self.scenarios != "": + # Scenario waardes per kolom met scenario als naam. gdf_to_add = gdf[["geometry", self.scenarios]] gdf_to_add.to_file( self.app_settings.geopackage_filepath, @@ -281,17 +293,19 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame): elif not self.include_value and self.scenarios != "": valid_anwser = False + while not valid_anwser: add_layer_per_scenario = prompt.InputPrompt( - message=f""" - Moeten er lagen per ruimtelijk scenario voor {self.param} worden ingeladen? - Er moet een kolom met de naam 'ondergrondscenario' in de attribute tabel - staan met de naam van het scenario waar de geometrie bijhoort. - (y/n)? O ftype 'cancel' om een ander bestand op te geven. - """ - ) + message=( + f""" + Moeten er lagen per ruimtelijk scenario voor {self.param} worden ingeladen? + Er moet een kolom met de naam 'ondergrondscenario' in de attribute tabel + staan met de naam van het scenario waar de geometrie bijhoort. + (y/n)? Of type 'cancel' om een ander bestand op te geven. + """ + ) + ).execute() if add_layer_per_scenario == "y": - # per shape id of naam? for scenario in self.scenarios: gdf_to_add: gpd.GeoDataFrame = gdf[ gdf["ondergrondscenario"] == scenario @@ -302,7 +316,8 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame): layer=f"{layer_name}", driver="GPKG", ) - pass + valid_anwser = True + elif add_layer_per_scenario == "n": gdf_to_add = gdf[["geometry"]] gdf_to_add.to_file( @@ -311,8 +326,10 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame): driver="GPKG", ) valid_anwser = True + elif add_layer_per_scenario == "cancel": self.request_filepath() + else: continue diff --git a/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py index f8ce9fd5..8cdcac20 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py @@ -20,7 +20,7 @@ def added_binnenteenlijn(app_settings: ApplicationSettings) -> bool: if "binnenteenlijn" in layers: print( - BColors.OKBLUE, f"✔ Binnenteenlijn al toegevoegd.", BColors.ENDC + BColors.OKBLUE, "✔ Binnenteenlijn al toegevoegd.", BColors.ENDC ) return True 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..3545b31b 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 @@ -202,14 +202,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..f98cfaee 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 @@ -60,23 +60,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/parameters.py b/geoprob_pipe/cmd_app/spatial_layers/parameters.py new file mode 100644 index 00000000..7e45269b --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_layers/parameters.py @@ -0,0 +1,130 @@ +from __future__ import annotations + +import sqlite3 +from typing import TYPE_CHECKING + +import InquirerPy.prompts.input as prompt + +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, +) +from geoprob_pipe.utils.validation_messages import BColors + +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: list[dict] = [ + # Loskoppelen van uitredepunt invoer? + {"name": "mv_exit", "shape": ["raster"]}, + {"name": "polderpeil", "shape": ["line", "polygon", "raster"]}, + {"name": "buitenwaterstand_gemiddeld", "shape": ["line"]}, + {"name": "phi_exit_gemiddeld", "shape": ["line", "polygon", "raster"]}, + {"name": "r_exit", "shape": ["line", "polygon", "raster"]}, + {"name": "k_wvp", "shape": ["line"]}, + {"name": "kD_wvp", "shape": ["line"]}, + {"name": "modelfactor_h", "shape": ["line"]}, + {"name": "modelfactor_ff", "shape": ["line"]}, + {"name": "modelfactor_3d", "shape": ["line"]}, + {"name": "modelfactor_ml", "shape": ["line"]}, + {"name": "i_c_h", "shape": ["line"]}, + {"name": "modelfactor_u", "shape": ["line"]}, + {"name": "modelfactor_p", "shape": ["line"]}, + {"name": "d70", "shape": ["line"]}, + {"name": "c_voorland", "shape": ["line"]}, + {"name": "c_achterland", "shape": ["line"]}, +] + + +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): + 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] + input_list: list[str] = [param["name"] for param in LIST_PARAMS] + match model: + case "model4a": + model_list = [param["name"] for param in MODEL4A_INPUT] + valid_list = [x for x in input_list if x in model_list] + + case "wbi": + model_list = [param["name"] for param in WBI_INPUT] + valid_list = [x for x in input_list if x in model_list] + case "moria": + model_list = [param["name"] for param in MORIA_INPUT] + valid_list = [x for x in input_list if x in model_list] + + scenario_input_is_valid = False + while scenario_input_is_valid is False: + 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 parameters not in valid_list: # type:ignore + print( + BColors.WARNING, + "Een of meerdere van de opgegeven parameters zijn niet geschikt voor ruimtelijke invoer.", + BColors.ENDC, + ) + continue + scenario_input_is_valid = True + + 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, (parameters, "ruimtelijke_parameters")) # type:ignore + if cur.rowcount == 0: + conn.execute(sql_insert, ("ruimtelijke_parameters", parameters)) # type:ignore + + conn.commit() + conn.close() diff --git a/geoprob_pipe/cmd_app/spatial_layers/scenarios.py b/geoprob_pipe/cmd_app/spatial_layers/scenarios.py index bd82eecc..58644845 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/scenarios.py +++ b/geoprob_pipe/cmd_app/spatial_layers/scenarios.py @@ -13,8 +13,8 @@ def added_scenarios(app_settings: ApplicationSettings): """ Check of de scenarios voor ruimtelijke invoer al zijn toegevoegd aan de metadata. - :param app_settings: _description_ - :return: _description_ + :param app_settings: `ApplicationSettings` object. + :return: bool """ conn = sqlite3.connect(app_settings.geopackage_filepath) cur = conn.cursor() @@ -33,7 +33,7 @@ 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: _description_ + :param app_settings: `ApplicationSettings` object. """ scenario_input_is_valid = False while scenario_input_is_valid is False: @@ -49,15 +49,20 @@ def request_scenarios(app_settings: ApplicationSettings): scenarios = "" else: scenarios = scenario_input.split(",") + scenarios = ", ".join(scenarios) + # TODO Check valid input + scenario_input_is_valid = True + + conn = sqlite3.connect(app_settings.geopackage_filepath) - sql_upsert = """ - INSERT INTO geoprob_pipe_metadata (metadata_type, values) - VALUES (?, ?) - ON CONFLICT(metadata_type) DO UPDATE SET - values = excluded.values - """ - conn = sqlite3.connect(app_settings.geopackage_filepath) - conn.cursor().execute(sql_upsert, ("ruimtelijke_scenarios", scenarios)) - conn.commit() - conn.close() \ No newline at end of file + 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")) # type:ignore + if cur.rowcount == 0: + conn.execute(sql_insert, ("ruimtelijke_scenarios", scenarios)) # type:ignore + + conn.commit() + conn.close() \ 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/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() From a82062cceb39b46b5157d3c1aa0d81fbb460d3f0 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 13 May 2026 14:47:24 +0200 Subject: [PATCH 06/53] WIP 13-05 --- .../cmd_app/spatial_joins/line_couple.py | 46 +++ .../cmd_app/spatial_layers/base_inquiry.py | 271 +++++++++++------- .../cmd_app/spatial_layers/parameters.py | 18 +- 3 files changed, 231 insertions(+), 104 deletions(-) create mode 100644 geoprob_pipe/cmd_app/spatial_joins/line_couple.py diff --git a/geoprob_pipe/cmd_app/spatial_joins/line_couple.py b/geoprob_pipe/cmd_app/spatial_joins/line_couple.py new file mode 100644 index 00000000..fd3fa5b2 --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_joins/line_couple.py @@ -0,0 +1,46 @@ +from __future__ import annotations + +import sqlite3 +from typing import TYPE_CHECKING + +import geopandas as gpd + +if TYPE_CHECKING: + from geoprob_pipe.cmd_app.cmd import ApplicationSettings + + +class BaseShapeCouple: + + def __init__(self, app_settings: ApplicationSettings, param: str) -> None: + self.app_settings = app_settings + self.param = param + 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 couple_exit_points(self): + # Read uittredepunten + gdf_exit_points: gpd.GeoDataFrame = gpd.read_file( + self.app_settings.geopackage_filepath, layer="uittredepunten" + ) + + # Read lijn met parameter: + gdf_parameter: gpd.GeoDataFrame = gpd.read_file( + self.app_settings.geopackage_filepath, layer=f"{self.param}" + ) + + # join + gdf_input = gdf_exit_points.sjoin_nearest( + gdf_parameter[["geometry", f"{self.param}"]], how='left', distance_col='distance' + ) + gdf_input = gdf_input[["uitredepunt_id", f"{self.param}"]] + gdf_input = gdf_input.rename({f"{self.param}": "mean"}) + + # Add to gis_join_parameter_invoer + # TODO add all of the parts of a parameter input + pass diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index ab4e5d86..764c1fb2 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -1,6 +1,15 @@ """ 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 onderschijd in invoer met verschillende shapes per scenario +of twee sets met invoer data. """ from __future__ import annotations @@ -13,6 +22,7 @@ import fiona import geopandas as gpd import InquirerPy.prompts.input as prompt +import numpy as np from shapely import LineString, MultiLineString from geoprob_pipe.utils.validation_messages import BColors @@ -51,6 +61,7 @@ def __init__( ("ruimtelijke_scenarios",), ) self.scenarios: list[str] = cur.fetchone()[0].split(", ") + conn.close() def request_filepath(self): """ @@ -94,12 +105,12 @@ def request_filepath(self): ) continue - filepath_is_valid = True + # Import data + gdf = self._import_data(filepath) # type:ignore + # Add data to geopackage - # Import data - gdf = self._import_data(filepath) # type:ignore - # Add data to geopackage - self._add_to_gpkg(gdf) + filepath_is_valid = self._add_to_gpkg(gdf) + print(BColors.OKBLUE, f"✅ {self.param} toegevoegd.", BColors.ENDC) def _import_data(self, filepath: str) -> gpd.GeoDataFrame: """ @@ -194,7 +205,7 @@ def _check_shape(self, gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame | None: """ Helper method voor het checken of de geometry het juiste type is. - :param gdf: _description_ + :param gdf: GeoDataFrame met de uitgelezen data. :return: GeoDataFrame of None als check faalt. """ @@ -222,115 +233,177 @@ def _check_shape(self, gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame | None: return gdf - def _add_to_gpkg(self, gdf: gpd.GeoDataFrame): + 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. + shape of als er meerdere shapes moeten worden toegevoegd. De kolommen + moeten van te voren met de juiste suffix in de shape staan. + + 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. """ - layer_name = self.param + self.suffix_list = ["mean", "dist", "var", "dev", "min", "max"] if self.include_value and self.scenarios == "": - column_name_is_valid = False - while column_name_is_valid is False: - column_name: str = prompt.InputPrompt( - message=( - f""" -Specificeer de kolom waarin {self.param} 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 - 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 == "cancel": - self.request_filepath() - - 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]] # type:ignore - gdf_to_add.to_file( - self.app_settings.geopackage_filepath, - layer=f"{layer_name}", - driver="GPKG", - ) + # Case: Alleen suffix, alle kolomen worden met de geometrie weggeschreven. + return self._add_with_suffix(gdf) elif self.include_value and self.scenarios != "": - # Scenario waardes per kolom met scenario als naam. - gdf_to_add = gdf[["geometry", self.scenarios]] + # Case: beide affixes, per scenario worden alle kolomen met de + # geometrieën weggeschreven. + # Of verschillende geometerieën per scenario + column_list = gdf.columns.to_list() + if True in [len(x.split("_")) == 3 for x in column_list]: + return self._add_with_affixes(gdf) + else: + return self._add_seperate_with_suffix(gdf) + + elif not self.include_value and self.scenarios == "": + # 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"{layer_name}", + layer=f"{self.param}", driver="GPKG", ) + return True + + elif not self.include_value and self.scenarios != "": + # Case: Alleen losse shapes, de geometriën worden per scenario geschreven. + return self._add_with_separate_geometry(gdf) + + 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. + """ + column_list = gdf.columns.to_list() + if "ondegrondscenario" not in column_list: + print( + BColors.WARNING, + "Geen kolom met de naam 'ondergrondscenario' gevonden.", + BColors.ENDC, + ) + + 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, + ) + return False - elif not self.include_value and self.scenarios == "": - gdf_to_add = gdf[["geometry"]] gdf_to_add.to_file( self.app_settings.geopackage_filepath, - layer=f"{layer_name}", + layer=f"{self.param}_{scenario}", driver="GPKG", ) - elif not self.include_value and self.scenarios != "": - valid_anwser = False - - while not valid_anwser: - add_layer_per_scenario = prompt.InputPrompt( - message=( - f""" - Moeten er lagen per ruimtelijk scenario voor {self.param} worden ingeladen? - Er moet een kolom met de naam 'ondergrondscenario' in de attribute tabel - staan met de naam van het scenario waar de geometrie bijhoort. - (y/n)? Of type 'cancel' om een ander bestand op te geven. - """ - ) - ).execute() - if add_layer_per_scenario == "y": - for scenario in self.scenarios: - gdf_to_add: gpd.GeoDataFrame = gdf[ - gdf["ondergrondscenario"] == scenario - ][["geometry"]] - layer_name = f"{self.param}_{scenario}" - gdf_to_add.to_file( - self.app_settings.geopackage_filepath, - layer=f"{layer_name}", - driver="GPKG", - ) - valid_anwser = True - - elif add_layer_per_scenario == "n": - gdf_to_add = gdf[["geometry"]] - gdf_to_add.to_file( - self.app_settings.geopackage_filepath, - layer=f"{layer_name}", - driver="GPKG", - ) - valid_anwser = True - - elif add_layer_per_scenario == "cancel": - self.request_filepath() - - else: - continue - - print(BColors.OKBLUE, f"✅ {self.param} toegevoegd.", BColors.ENDC) + 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. + """ + column_list = gdf.columns.to_list() + add_list = [ + f"{self.param}_{x}" + for x in self.suffix_list + if f"{self.param}_{x}" in column_list + ] + + 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 determinstic. + for _, row in gdf.iterrows(): + if row[f"{self.param}_dist"] == "deterministic": + continue # Overslaan + + if f"{self.param}_var" in add_list: + var_bool = row[f"{self.param}_var"] != np.nan or "" + else: + var_bool = False + + if f"{self.param}_dev" in add_list: + dev_bool = row[f"{self.param}_dev"] != np.nan or "" + 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 + + 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: + """_summary_ + + :param gdf: GeoDataFrame met de uitgelezen data. + :return: bool voor valid_input in while-loop + """ + # Via _add_with_suffix? + return True + + def _add_seperate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: + """_summary_ + + :param gdf: GeoDataFrame met de uitgelezen data. + :return: bool voor valid_input in while-loop + """ + # Via _add_with_suffix? + return True diff --git a/geoprob_pipe/cmd_app/spatial_layers/parameters.py b/geoprob_pipe/cmd_app/spatial_layers/parameters.py index 7e45269b..01f931c2 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/parameters.py @@ -23,7 +23,6 @@ # Polygon of raster alleen beschikbaar als iets per uittredepunt kan verschillen # en afstand tot de keringlijn uitmaakt. LIST_PARAMS: list[dict] = [ - # Loskoppelen van uitredepunt invoer? {"name": "mv_exit", "shape": ["raster"]}, {"name": "polderpeil", "shape": ["line", "polygon", "raster"]}, {"name": "buitenwaterstand_gemiddeld", "shape": ["line"]}, @@ -64,12 +63,21 @@ def added_parameters(app_settings: ApplicationSettings): def request_parameters(app_settings: ApplicationSettings): + """ + Method voor het opvragen van de lijst met parameters waarvoor ruimtelijke + invoer gewenst is. Er wordt gecheckd of deze paramerters ondersteund worden + en of deze in het gekozen model zitten. + + :param app_settings: `ApplicationSettings` object. + """ 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 wordt later gesloten. + input_list: list[str] = [param["name"] for param in LIST_PARAMS] match model: case "model4a": @@ -86,12 +94,14 @@ def request_parameters(app_settings: ApplicationSettings): scenario_input_is_valid = False while scenario_input_is_valid is False: parameter_input: str = prompt.InputPrompt( - message=""" + 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 = "" @@ -116,8 +126,6 @@ def request_parameters(app_settings: ApplicationSettings): continue scenario_input_is_valid = True - 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 (?, ?)" From 2340565f4d66142194790be8efe70f9789ca6b5e Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 19 May 2026 10:29:10 +0200 Subject: [PATCH 07/53] base_inquiry afgerond --- .../cmd_app/spatial_layers/base_inquiry.py | 210 ++++++++++++++---- 1 file changed, 163 insertions(+), 47 deletions(-) diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 764c1fb2..9ce21b99 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -107,9 +107,10 @@ def request_filepath(self): # Import data gdf = self._import_data(filepath) # type:ignore - # Add data to geopackage + # Add data to geopackage filepath_is_valid = self._add_to_gpkg(gdf) + print(BColors.OKBLUE, f"✅ {self.param} toegevoegd.", BColors.ENDC) def _import_data(self, filepath: str) -> gpd.GeoDataFrame: @@ -256,6 +257,7 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: :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 == "": @@ -286,15 +288,20 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: # Case: Alleen losse shapes, de geometriën worden per scenario geschreven. return self._add_with_separate_geometry(gdf) - def _add_with_separate_geometry(self, gdf: gpd.GeoDataFrame) -> bool: + 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]): """ - Method voor het toevoegen van lagen met meerdere shapes voor - verschillende scenarios. + Check of het scenario in de 'ondergrondscenario' kolom voorkomt. - :param gdf: GeoDataFrame met de uitgelezen data. - :return: bool voor valid_input in while-loop. - """ - column_list = gdf.columns.to_list() + :param list[str] column_list: Lijst met kolomnamen uit de GeoDataFrame. + :return: Check of het scenario voorkomt. + :rtype: bool + """ if "ondegrondscenario" not in column_list: print( BColors.WARNING, @@ -303,42 +310,25 @@ def _add_with_separate_geometry(self, gdf: gpd.GeoDataFrame) -> bool: ) return False + else: + return True - 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, - ) - return False - - 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: + def _distribution_check( + self, + column_list: list[str], + add_list: list[str], + 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. + Check of de kolomen 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 """ - column_list = gdf.columns.to_list() - add_list = [ - f"{self.param}_{x}" - for x in self.suffix_list - if f"{self.param}_{x}" in column_list - ] - if len(add_list) == 0: print( BColors.WARNING, @@ -380,6 +370,62 @@ def _add_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: ) 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}_{x}" + for x in self.suffix_list + if f"{self.param}_{x}" 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( @@ -391,19 +437,89 @@ def _add_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: return True def _add_with_affixes(self, gdf: gpd.GeoDataFrame) -> bool: - """_summary_ + """ + 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 - """ - # Via _add_with_suffix? + :rtype: bool + """ + column_list = gdf.columns.to_list() + + for scenario in self.scenarios: + filter_list = [ + x for x in column_list if x.split("_")[0] == scenario + ] + + if len(filter_list) == 0: + print( + BColors.WARNING, + f"Geen geometrieën gevonden met de ondergrondscenarionaam: {scenario}", + BColors.ENDC, + ) + continue + + filter_list = [ + x.split("_")[1:] for x in filter_list + ] # Strip scenario van kolomnaam. + + add_list = [ + f"{self.param}_{x}" + for x in self.suffix_list + if f"{self.param}_{x}" in filter_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}_{scenario}", + driver="GPKG", + ) + return True def _add_seperate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: - """_summary_ + """ + Voeg de lagen toe los van elkaar per scenario. :param gdf: GeoDataFrame met de uitgelezen data. :return: bool voor valid_input in while-loop - """ - # Via _add_with_suffix? + """ + 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_filtered = gdf[mask][["geometry"]] + + if len(gdf_filtered) == 0: + print( + BColors.WARNING, + f"Geen geometrieën gevonden met de ondergrondscenarionaam: {scenario}", + BColors.ENDC, + ) + continue + add_list = [ + f"{self.param}_{x}" + for x in self.suffix_list + if f"{self.param}_{x}" in column_list + ] + + if not self._distribution_check(column_list, add_list, gdf): + return False + + gdf_to_add = gdf_filtered[["geometry", add_list]] + + gdf_to_add.to_file( + self.app_settings.geopackage_filepath, + layer=f"{self.param}_{scenario}", + driver="GPKG", + ) + return True From 5cc46921f43d3a079e171fbf7de44bf375f21b6f Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 19 May 2026 13:40:33 +0200 Subject: [PATCH 08/53] ShapeCouple class --- .../cmd_app/spatial_joins/line_couple.py | 46 --- .../cmd_app/spatial_joins/shape_couple.py | 266 ++++++++++++++++++ .../cmd_app/spatial_layers/parameters.py | 40 +-- 3 files changed, 286 insertions(+), 66 deletions(-) delete mode 100644 geoprob_pipe/cmd_app/spatial_joins/line_couple.py create mode 100644 geoprob_pipe/cmd_app/spatial_joins/shape_couple.py diff --git a/geoprob_pipe/cmd_app/spatial_joins/line_couple.py b/geoprob_pipe/cmd_app/spatial_joins/line_couple.py deleted file mode 100644 index fd3fa5b2..00000000 --- a/geoprob_pipe/cmd_app/spatial_joins/line_couple.py +++ /dev/null @@ -1,46 +0,0 @@ -from __future__ import annotations - -import sqlite3 -from typing import TYPE_CHECKING - -import geopandas as gpd - -if TYPE_CHECKING: - from geoprob_pipe.cmd_app.cmd import ApplicationSettings - - -class BaseShapeCouple: - - def __init__(self, app_settings: ApplicationSettings, param: str) -> None: - self.app_settings = app_settings - self.param = param - 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 couple_exit_points(self): - # Read uittredepunten - gdf_exit_points: gpd.GeoDataFrame = gpd.read_file( - self.app_settings.geopackage_filepath, layer="uittredepunten" - ) - - # Read lijn met parameter: - gdf_parameter: gpd.GeoDataFrame = gpd.read_file( - self.app_settings.geopackage_filepath, layer=f"{self.param}" - ) - - # join - gdf_input = gdf_exit_points.sjoin_nearest( - gdf_parameter[["geometry", f"{self.param}"]], how='left', distance_col='distance' - ) - gdf_input = gdf_input[["uitredepunt_id", f"{self.param}"]] - gdf_input = gdf_input.rename({f"{self.param}": "mean"}) - - # Add to gis_join_parameter_invoer - # TODO add all of the parts of a parameter input - pass diff --git a/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py new file mode 100644 index 00000000..3962ed53 --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py @@ -0,0 +1,266 @@ +from __future__ import annotations + +import sqlite3 +from typing import TYPE_CHECKING + +import geopandas as gpd +import pandas as pd +from shapely.geometry import LineString, MultiLineString, Polygon, MultiPolygon + +from geoprob_pipe.cmd_app.spatial_layers.parameters import LIST_PARAMS + +if TYPE_CHECKING: + from geoprob_pipe.cmd_app.cmd import ApplicationSettings + + +class ShapeCouple: + 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_invoer_parameters'. + + :param app_settings: `ApplicationSettings` object. + :param param: Parameter die gekoppeled 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 koppeleing ,met de uitredepunten 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 scenariois zijn voor + de parameter. + """ + for scenario in self.param_tables: + gdf_parameter: gpd.GeoDataFrame = gpd.read_file( + self.app_settings.geopackage_filepath, + layer=f"{self.param}_{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_types == (LineString or 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_types == (Polygon or 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. + """ + # TODO filter mogelijk dubble waarden + join_df = self.gdf_exit_points.sjoin_nearest(gdf, how="left") + df_to_add = self._create_df(join_df, 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_df = self.gdf_exit_points.sjoin(gdf, how="left") + df_to_add = self._create_df(join_df, scenario) + + self._upsert_to_gpkg(df_to_add) + + # TODO add option for rasters + def _join_to_raster(self): + pass + + def _create_df(self, join_df: pd.DataFrame, scenario: str) -> pd.DataFrame: + """ + Maak de dataframe die moet worden toegevoedg aan de geopackage. + + :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") + df["mean"] = join_df.get(f"{self.param}_mean") + df["variation"] = join_df.get(f"{self.param}_var") + df["deviation"] = join_df.get(f"{self.param}_dev") + df["minimum"] = join_df.get(f"{self.param}_min") + df["maximum"] = join_df.get(f"{self.param}_max") + 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. + + :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(["?"] * len(data)) + # 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, + ) + conn.commit() + conn.close() diff --git a/geoprob_pipe/cmd_app/spatial_layers/parameters.py b/geoprob_pipe/cmd_app/spatial_layers/parameters.py index 01f931c2..65310ff2 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/parameters.py @@ -22,25 +22,25 @@ # 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: list[dict] = [ - {"name": "mv_exit", "shape": ["raster"]}, - {"name": "polderpeil", "shape": ["line", "polygon", "raster"]}, - {"name": "buitenwaterstand_gemiddeld", "shape": ["line"]}, - {"name": "phi_exit_gemiddeld", "shape": ["line", "polygon", "raster"]}, - {"name": "r_exit", "shape": ["line", "polygon", "raster"]}, - {"name": "k_wvp", "shape": ["line"]}, - {"name": "kD_wvp", "shape": ["line"]}, - {"name": "modelfactor_h", "shape": ["line"]}, - {"name": "modelfactor_ff", "shape": ["line"]}, - {"name": "modelfactor_3d", "shape": ["line"]}, - {"name": "modelfactor_ml", "shape": ["line"]}, - {"name": "i_c_h", "shape": ["line"]}, - {"name": "modelfactor_u", "shape": ["line"]}, - {"name": "modelfactor_p", "shape": ["line"]}, - {"name": "d70", "shape": ["line"]}, - {"name": "c_voorland", "shape": ["line"]}, - {"name": "c_achterland", "shape": ["line"]}, -] +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 added_parameters(app_settings: ApplicationSettings): @@ -78,7 +78,7 @@ def request_parameters(app_settings: ApplicationSettings): model = cur.fetchone()[0] # conn wordt later gesloten. - input_list: list[str] = [param["name"] for param in LIST_PARAMS] + input_list: list[str] = [param for param in LIST_PARAMS.keys()] match model: case "model4a": model_list = [param["name"] for param in MODEL4A_INPUT] From cfdcd9d6c304ee687cb21fb04001b00b366d16bc Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 19 May 2026 14:21:31 +0200 Subject: [PATCH 09/53] WIP 19-05 --- geoprob_pipe/cmd_app/questionnaire.py | 13 ++-- .../cmd_app/spatial_layers/__init__.py | 1 + .../spatial_layers/ruimtelijke_invoer.py | 66 +++++++++++++++++++ 3 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 geoprob_pipe/cmd_app/spatial_layers/ruimtelijke_invoer.py diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 181c2d18..5bb0444c 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -16,19 +16,18 @@ coupled_distances_to_uittredepunten, coupled_hrd_to_uittredepunten, coupled_mv_exit_to_gis_parameter_invoer_table, - coupled_polderpeil_to_uittredepunten, coupled_uittredepunten_to_refline, coupled_uittredepunten_to_vakken, ) from geoprob_pipe.cmd_app.spatial_layers import ( added_ahn, - added_parameters, added_binnenteenlijn, added_buitenteenlijn, added_dijktraject, added_hrd_fragility_curves, added_intredelijn, - added_polderpeil, + added_parameters, + added_ruimtelijke_input, added_scenarios, added_uittredepunten, added_vakindeling, @@ -75,12 +74,12 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) print("/nRUIMTELIJKE INPUT") - # TODO Loop met alle ruimtelijke parameters + # Loop voor alle parameters + if not added_ruimtelijke_input(app_settings=app_settings): + sys.exit(EARLY_EXIT_MESSAGE) + # TODO maak polderpeil optioneel - # if not added_polderpeil(app_settings=app_settings): - # sys.exit(EARLY_EXIT_MESSAGE) - added_ahn( app_settings=app_settings, display_added_msg=True ) # AHN may be optional diff --git a/geoprob_pipe/cmd_app/spatial_layers/__init__.py b/geoprob_pipe/cmd_app/spatial_layers/__init__.py index b8943dc4..4f3fcffa 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/__init__.py +++ b/geoprob_pipe/cmd_app/spatial_layers/__init__.py @@ -7,6 +7,7 @@ from .intredelijn import added_intredelijn from .parameters import added_parameters from .polderpeil import added_polderpeil +from .ruimtelijke_invoer import added_ruimtelijke_input from .scenarios import added_scenarios from .uittredepunten.uittredepunten import added_uittredepunten from .vakindeling import added_vakindeling diff --git a/geoprob_pipe/cmd_app/spatial_layers/ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/ruimtelijke_invoer.py new file mode 100644 index 00000000..3ce39eaf --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_layers/ruimtelijke_invoer.py @@ -0,0 +1,66 @@ +from __future__ import annotations + +import sqlite3 +from typing import TYPE_CHECKING + +import fiona + +from geoprob_pipe.cmd_app.spatial_layers import BaseInquiry +from geoprob_pipe.cmd_app.spatial_layers.parameters import LIST_PARAMS +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(", ") + cursor.execute( + "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?", + ("ruimtelijke_scenarios",), + ) + scenarios: list[str] = cursor.fetchone()[0].split(", ") + conn.close() + layers = fiona.listlayers(app_settings.geopackage_filepath) + if parameters == []: + print( + BColors.OKBLUE, + "✔ Geen ruimtelijke parameter invoer.", + BColors.ENDC, + ) + return True + + for parameter in parameters: + if scenarios == []: + if parameter in layers: + print( + BColors.OKBLUE, + f"✔ {parameter} al toegevoegd.", + BColors.ENDC, + ) + return True + + else: + for scenario in scenarios: + if f"{parameter}_{scenario}" in layers: + print( + BColors.OKBLUE, + f"✔ {parameter} al toegevoegd.", + BColors.ENDC, + ) + return True + + inquiry = BaseInquiry( + app_settings=app_settings, + param=f"{parameter}", + specific_shape=LIST_PARAMS[parameter]["shape"], + ) + inquiry.request_filepath() + + return True From 0613d16a266a02f9e58ed5f4c55246d637e8236c Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 20 May 2026 11:05:08 +0200 Subject: [PATCH 10/53] WIP 20-05: totaan rasters --- .../parameter_input/added_input_parameters.py | 131 +++++++------ .../parameter_input/input_parameter_tables.py | 14 +- geoprob_pipe/cmd_app/questionnaire.py | 14 +- .../cmd_app/spatial_joins/__init__.py | 15 +- .../cmd_app/spatial_joins/coupled_hrd.py | 38 +--- .../spatial_joins/coupled_parameters.py | 35 ++++ .../spatial_joins/coupled_polderpeil.py | 92 +++++----- .../cmd_app/spatial_joins/hrd_couple.py | 173 ++++++++++++++++++ .../cmd_app/spatial_joins/shape_couple.py | 53 +++++- .../cmd_app/spatial_layers/__init__.py | 19 +- .../spatial_layers/{ahn.py => added_ahn.py} | 0 ...nenteenlijn.py => added_binnenteenlijn.py} | 0 ...tenteenlijn.py => added_buitenteenlijn.py} | 0 .../{dijktraject.py => added_dijktraject.py} | 0 .../{intredelijn.py => added_intredelijn.py} | 2 +- .../{parameters.py => added_parameters.py} | 0 ..._invoer.py => added_ruimtelijke_invoer.py} | 2 +- .../{scenarios.py => added_scenarios.py} | 0 .../{vakindeling.py => added_vakindeling.py} | 0 .../cmd_app/spatial_layers/base_inquiry.py | 2 +- .../{polderpeil.py => old_polderpeil.py} | 0 .../uittredepunten/alg_walking_circles.py | 2 +- 22 files changed, 412 insertions(+), 180 deletions(-) create mode 100644 geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py create mode 100644 geoprob_pipe/cmd_app/spatial_joins/hrd_couple.py rename geoprob_pipe/cmd_app/spatial_layers/{ahn.py => added_ahn.py} (100%) rename geoprob_pipe/cmd_app/spatial_layers/{binnenteenlijn.py => added_binnenteenlijn.py} (100%) rename geoprob_pipe/cmd_app/spatial_layers/{buitenteenlijn.py => added_buitenteenlijn.py} (100%) rename geoprob_pipe/cmd_app/spatial_layers/{dijktraject.py => added_dijktraject.py} (100%) rename geoprob_pipe/cmd_app/spatial_layers/{intredelijn.py => added_intredelijn.py} (91%) rename geoprob_pipe/cmd_app/spatial_layers/{parameters.py => added_parameters.py} (100%) rename geoprob_pipe/cmd_app/spatial_layers/{ruimtelijke_invoer.py => added_ruimtelijke_invoer.py} (96%) rename geoprob_pipe/cmd_app/spatial_layers/{scenarios.py => added_scenarios.py} (100%) rename geoprob_pipe/cmd_app/spatial_layers/{vakindeling.py => added_vakindeling.py} (100%) rename geoprob_pipe/cmd_app/spatial_layers/{polderpeil.py => old_polderpeil.py} (100%) 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..e2573b40 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,21 @@ 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 + if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -68,7 +73,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 +114,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): @@ -142,6 +148,7 @@ def inquire_to_import_export_tables_and_figures_or_continue( "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"]) @@ -151,55 +158,63 @@ def inquire_to_import_export_tables_and_figures_or_continue( 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) - - 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)": + 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) + + case "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) + + case "Invoer tabellen: Importeren vanuit Excel": + process_import_input(app_settings=app_settings) + + 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) + + case "'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) + + case "Ruimtelijke invoer: Update ingevoerde lagen": + # Nieuw keuze menu voor de volgende: + # TODO herinvoeren van gis lagen. + # TODO toevoegen van nieuwe parameters. + # TODO Toevangen van scenarios. Alles opnieuw inladen en koppelen? + # TODO verwijderen van lagen? Of alleen overschrijven via excel invoer? + pass + + 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. + """) + 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 == "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): @@ -208,7 +223,6 @@ 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: filepath: str = inquirer.text( @@ -222,12 +236,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 - 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 +281,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) @@ -296,10 +310,11 @@ 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) 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/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 5bb0444c..1d40e899 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -18,6 +18,7 @@ coupled_mv_exit_to_gis_parameter_invoer_table, coupled_uittredepunten_to_refline, coupled_uittredepunten_to_vakken, + coupled_parameters_to_uittredepunten ) from geoprob_pipe.cmd_app.spatial_layers import ( added_ahn, @@ -77,25 +78,22 @@ def questionnaire(app_settings: ApplicationSettings): # Loop voor alle parameters if not added_ruimtelijke_input(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) - - # TODO maak polderpeil optioneel - added_ahn( app_settings=app_settings, display_added_msg=True ) # AHN may be optional print("\nGEOGRAFISCHE KOPPELINGEN") - # TODO maak coupleling for line, polygon, raster + # TODO maak coupleling for raster 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_hrd_to_uittredepunten(app_settings=app_settings): + sys.exit(EARLY_EXIT_MESSAGE) + if not coupled_parameters_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 ): diff --git a/geoprob_pipe/cmd_app/spatial_joins/__init__.py b/geoprob_pipe/cmd_app/spatial_joins/__init__.py index 73a4725f..83f27781 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 .coupled_distance_to_exit_points import ( + coupled_distances_to_uittredepunten, +) +from .coupled_exit_points_to_refline import coupled_uittredepunten_to_refline +from .coupled_exit_points_to_vakken import coupled_uittredepunten_to_vakken +from .coupled_hrd import coupled_hrd_to_uittredepunten +from .coupled_mv_exit import coupled_mv_exit_to_gis_parameter_invoer_table +from .coupled_parameters import coupled_parameters_to_uittredepunten diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py index 371f2d16..47843354 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py +++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py @@ -3,12 +3,12 @@ """ 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 + +import fiona +from hrd_couple import HRDCouple + if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -20,30 +20,6 @@ def coupled_hrd_to_uittredepunten(app_settings: ApplicationSettings) -> bool: 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) + HRDCouple(app_settings).couple_exit_points() + return True diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py new file mode 100644 index 00000000..11dde629 --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import sqlite3 +from typing import TYPE_CHECKING + +from shape_couple 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 == []: + 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_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/hrd_couple.py b/geoprob_pipe/cmd_app/spatial_joins/hrd_couple.py new file mode 100644 index 00000000..80a164c7 --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_joins/hrd_couple.py @@ -0,0 +1,173 @@ +""" +Class voor het koppelen van de HRD-locaties aan de uittredepunten. +Versimplende versie van de ShapeCouple class. +""" +# TODO importeer _upsert_to_gpkg vanuit ShapeCouple + +from __future__ import annotations + +import datetime +import sqlite3 +from typing import TYPE_CHECKING + +import geopandas as gpd +import pandas as pd + +from geoprob_pipe.cmd_app.cmd import ApplicationSettings + +if TYPE_CHECKING: + from geoprob_pipe.cmd_app.cmd import ApplicationSettings + + +class HRDCouple: + def __init__(self, app_settings: ApplicationSettings) -> None: + self.app_settings = app_settings + + def couple_exit_points(self): + # 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(join_df) + self._upsert_to_gpkg(df_to_add) + + def _create_df(self, join_df: pd.DataFrame): + 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"] = "" + df["variation"] = "" + df["deviation"] = "" + df["minimum"] = "" + df["maximum"] = "" + df["fragility_values_ref"] = join_df.get("hrd_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 + + 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(["?"] * len(data)) + # 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 + 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 (indentifier) 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/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py index 3962ed53..d338da8b 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py @@ -1,5 +1,6 @@ from __future__ import annotations +import datetime import sqlite3 from typing import TYPE_CHECKING @@ -7,7 +8,7 @@ import pandas as pd from shapely.geometry import LineString, MultiLineString, Polygon, MultiPolygon -from geoprob_pipe.cmd_app.spatial_layers.parameters import LIST_PARAMS +from geoprob_pipe.cmd_app.spatial_layers.added_parameters import LIST_PARAMS if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -73,7 +74,7 @@ def couple_exit_points(self): def _add_single_layer(self): """ - Voeg een laag toe via koppeleing ,met de uitredepunten als er geen + Voeg een laag toe via koppeling, met de uitredepunten als er geen ruimtelijke scenarios zijn voor de parameter. """ gdf_parameter: gpd.GeoDataFrame = gpd.read_file( @@ -83,7 +84,7 @@ def _add_single_layer(self): def _add_multiple_layers(self): """ - Voeg de lagen een voor een toe als er ruimtelijke scenariois zijn voor + Voeg de lagen een voor een toe als er ruimtelijke scenarios zijn voor de parameter. """ for scenario in self.param_tables: @@ -166,12 +167,12 @@ def _create_df(self, join_df: pd.DataFrame, scenario: str) -> pd.DataFrame: df["parameter"] = self.param df["scope"] = "uittredepunt" df["ondergrondscenario_naam"] = scenario - df["distribution_type"] = join_df.get(f"{self.param}_dist") - df["mean"] = join_df.get(f"{self.param}_mean") - df["variation"] = join_df.get(f"{self.param}_var") - df["deviation"] = join_df.get(f"{self.param}_dev") - df["minimum"] = join_df.get(f"{self.param}_min") - df["maximum"] = join_df.get(f"{self.param}_max") + df["distribution_type"] = join_df.get(f"{self.param}_dist", "") + df["mean"] = join_df.get(f"{self.param}_mean", "") + df["variation"] = join_df.get(f"{self.param}_var", "") + df["deviation"] = join_df.get(f"{self.param}_dev", "") + df["minimum"] = join_df.get(f"{self.param}_min", "") + df["maximum"] = join_df.get(f"{self.param}_max", "") df["fragility_values_ref"] = "" df["bronnen"] = "" df["opmerking"] = "" @@ -200,7 +201,10 @@ 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. + 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. """ @@ -262,5 +266,34 @@ def _upsert_to_gpkg(self, df: pd.DataFrame): """, data, ) + # UPSERT naar gpkg_contents + 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 (indentifier) 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() diff --git a/geoprob_pipe/cmd_app/spatial_layers/__init__.py b/geoprob_pipe/cmd_app/spatial_layers/__init__.py index 4f3fcffa..e0bac988 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/__init__.py +++ b/geoprob_pipe/cmd_app/spatial_layers/__init__.py @@ -1,13 +1,12 @@ -from .ahn import added_ahn +from .added_ahn import added_ahn from .base_inquiry import BaseInquiry -from .binnenteenlijn import added_binnenteenlijn -from .buitenteenlijn import added_buitenteenlijn -from .dijktraject import added_dijktraject +from .added_binnenteenlijn import added_binnenteenlijn +from .added_buitenteenlijn import added_buitenteenlijn +from .added_dijktraject import added_dijktraject from .hrd.hrd import added_hrd_fragility_curves -from .intredelijn import added_intredelijn -from .parameters import added_parameters -from .polderpeil import added_polderpeil -from .ruimtelijke_invoer import added_ruimtelijke_input -from .scenarios import added_scenarios +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 .uittredepunten.uittredepunten import added_uittredepunten -from .vakindeling import added_vakindeling +from .added_vakindeling import added_vakindeling 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/binnenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py similarity index 100% rename from geoprob_pipe/cmd_app/spatial_layers/binnenteenlijn.py rename to geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py diff --git a/geoprob_pipe/cmd_app/spatial_layers/buitenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py similarity index 100% rename from geoprob_pipe/cmd_app/spatial_layers/buitenteenlijn.py rename to geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py diff --git a/geoprob_pipe/cmd_app/spatial_layers/dijktraject.py b/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py similarity index 100% rename from geoprob_pipe/cmd_app/spatial_layers/dijktraject.py rename to geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py diff --git a/geoprob_pipe/cmd_app/spatial_layers/intredelijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py similarity index 91% rename from geoprob_pipe/cmd_app/spatial_layers/intredelijn.py rename to geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py index 8fe4053d..3db07052 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/intredelijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py @@ -20,7 +20,7 @@ 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) + print(BColors.OKBLUE, "✔ Intredelijn al toegevoegd.", BColors.ENDC) return True request_intredelijn_filepath(app_settings=app_settings) diff --git a/geoprob_pipe/cmd_app/spatial_layers/parameters.py b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py similarity index 100% rename from geoprob_pipe/cmd_app/spatial_layers/parameters.py rename to geoprob_pipe/cmd_app/spatial_layers/added_parameters.py diff --git a/geoprob_pipe/cmd_app/spatial_layers/ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py similarity index 96% rename from geoprob_pipe/cmd_app/spatial_layers/ruimtelijke_invoer.py rename to geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py index 3ce39eaf..b2cb5934 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py @@ -6,7 +6,7 @@ import fiona from geoprob_pipe.cmd_app.spatial_layers import BaseInquiry -from geoprob_pipe.cmd_app.spatial_layers.parameters import LIST_PARAMS +from geoprob_pipe.cmd_app.spatial_layers.added_parameters import LIST_PARAMS from geoprob_pipe.utils.validation_messages import BColors if TYPE_CHECKING: diff --git a/geoprob_pipe/cmd_app/spatial_layers/scenarios.py b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py similarity index 100% rename from geoprob_pipe/cmd_app/spatial_layers/scenarios.py rename to geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py diff --git a/geoprob_pipe/cmd_app/spatial_layers/vakindeling.py b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py similarity index 100% rename from geoprob_pipe/cmd_app/spatial_layers/vakindeling.py rename to geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 9ce21b99..8cbb7769 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -252,7 +252,7 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: 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 + 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. diff --git a/geoprob_pipe/cmd_app/spatial_layers/polderpeil.py b/geoprob_pipe/cmd_app/spatial_layers/old_polderpeil.py similarity index 100% rename from geoprob_pipe/cmd_app/spatial_layers/polderpeil.py rename to geoprob_pipe/cmd_app/spatial_layers/old_polderpeil.py 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..76977268 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 From 5a8d77baad2d914e727c2a32110c5f5586e3eacb Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 20 May 2026 15:24:08 +0200 Subject: [PATCH 11/53] wip 20-05 begin van aanpassen via parameter invoer keuze menu --- .../parameter_input/added_input_parameters.py | 149 ++++++------- .../update_ruimtelijke_invoer.py | 203 ++++++++++++++++++ geoprob_pipe/cmd_app/questionnaire.py | 8 +- .../cmd_app/spatial_layers/__init__.py | 9 +- .../spatial_layers/added_parameters.py | 31 +-- .../cmd_app/spatial_layers/added_scenarios.py | 38 ++-- .../cmd_app/spatial_layers/base_inquiry.py | 1 + geoprob_pipe/cmd_app/spatial_layers/utils.py | 43 ++++ 8 files changed, 354 insertions(+), 128 deletions(-) create mode 100644 geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py create mode 100644 geoprob_pipe/cmd_app/spatial_layers/utils.py 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 e2573b40..776deb8f 100644 --- a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py +++ b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py @@ -15,6 +15,7 @@ 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 inquire_spatial_update if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -136,84 +137,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", - "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() - 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)": - 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) - - case "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) - - case "Invoer tabellen: Importeren vanuit Excel": - process_import_input(app_settings=app_settings) - - 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) - - case "'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) - - case "Ruimtelijke invoer: Update ingevoerde lagen": - # Nieuw keuze menu voor de volgende: - # TODO herinvoeren van gis lagen. - # TODO toevoegen van nieuwe parameters. - # TODO Toevangen van scenarios. Alles opnieuw inladen en koppelen? - # TODO verwijderen van lagen? Of alleen overschrijven via excel invoer? - pass - - case "Toelichting per keuze optie": - print(""" + 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() + + 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: + inquire_spatial_update( + app_settings=app_settings, + ) + 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. -Ruimtelijke invoer: Update ingevoerde lagen -> Open een keuze menu om de lagen die zijn ingevoerd voor ruimtelijke koppeling van parameters te vervangen. - """) - 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 - case "Applicatie afsluiten": - sys.exit("Applicatie is afgesloten.") + case "Applicatie afsluiten": + sys.exit("Applicatie is afgesloten.") @@ -296,10 +292,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): @@ -318,12 +310,11 @@ def process_import_input(app_settings: ApplicationSettings): 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: 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..ffe31f65 --- /dev/null +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -0,0 +1,203 @@ +from __future__ import annotations + +import sqlite3 +import sys +from typing import TYPE_CHECKING + +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 + +if TYPE_CHECKING: + from geoprob_pipe.cmd_app.cmd import ApplicationSettings + + +# TODO herinvoeren van gis lagen. +# TODO toevoegen van nieuwe parameters. +# TODO Toevangen van scenarios. Alles opnieuw inladen en koppelen? +# TODO verwijderen van lagen? Of alleen overschrijven via excel invoer? +def inquire_spatial_update( + app_settings: ApplicationSettings, +): + choices_list = [ + "Vervang ingevoerde lagen", + "Voeg parameters toe voor ruimtelijke invoer", + "Verwijder parameters voor ruimtlijke invoer", + "Voeg scenarios toe voor ruimtelijke invoer", + "Verwijder scenarios voor ruimtelijke invoer", + "Ga terug naar het parameter invoer menu", + ] + while True: + 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": + inquire_replace_layers(app_settings) + continue + + case "Voeg parameters toe voor ruimtelijke invoer": + add_parameters(app_settings) + continue + + case "Verwijder parameters voor ruimtlijke invoer": + remove_parameters(app_settings) + continue + + case "Voeg scenarios toe voor ruimtelijke invoer": + add_scenarios(app_settings) + continue + + case "Verwijder scenarios voor ruimtelijke invoer": + remove_scenarios(app_settings) + continue + + case "Ga terug naar het parameter invoer menu": + return + + +def inquire_replace_layers(app_settings: ApplicationSettings): + pass + + +def add_parameters(app_settings: ApplicationSettings): + """ + Voeg extra parameters toe voor de ruimtelijke invoer. De aanpassingen + kunnen pas verwerkt worden nadat de applicatie opnieuw is opgestart. + + :param app_settings: `ApplicationSettings` object met alle settings. + """ + + conn = sqlite3.connect(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(app_settings) + + # Vraag gebruiker voor toevoegingen. + while True: + parameter_input: str = InputPrompt( + message=f""" + De volgende parameters zijn nu aangemerkt voor rumtelijke 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 + + try: + parameter_list = parameter_input.split(",") + new_parameters = ", ".join(parameter_list) + + except Exception: + print( + BColors.OKBLUE, + f"Geen parameters toegevoegd. '{parameter_input}' is geen geldige invoer.", + BColors.ENDC, + ) + continue + + valid_input = all(param in valid_list for param in current_parameters) + + if not valid_input: + print( + BColors.OKBLUE, + f"Geen parameterss toegevoegd. '{parameter_input}' bevat een ongeldige parameter.", + BColors.ENDC, + ) + continue + + break + + # Update metadata + + parameters = current_parameters + new_parameters.split(",") + parameters = list(set(parameters)) # Verwijder dubbele waardes + parameters = ", ".join(parameters) + update_metadata_parameters(app_settings, parameters) + completed_update() + + +def remove_parameters(app_settings: ApplicationSettings): + pass + + +def add_scenarios(app_settings: ApplicationSettings): + pass + + +def remove_scenarios(app_settings: ApplicationSettings): + pass + +def update_metadata_parameters(app_settings: ApplicationSettings, parameters: str): + """ + Update de parameters voor ruimtelijke invoer in de metadata. + """ + 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, (parameters, "ruimtelijke_parameters")) # type:ignore + if cur.rowcount == 0: + conn.execute(sql_insert, ("ruimtelijke_parameters", parameters)) # type:ignore + + conn.commit() + conn.close() + +def verwijder_tabellen(): + # Voor vervangen, nieuwe scenarios of verwijderen van parameters. + pass + +def completed_update(): + """ + 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 aanpasingen in een keer te doen." + ), + choices=choices_list, + default=choices_list[0], + ).execute() + + match choice: + case "Andere aanpassing uitvoeren": + return + + case "Applicatie afsluiten": + sys.exit("Applicatie is afgesloten.") \ No newline at end of file diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 1d40e899..182ea8b7 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -55,6 +55,8 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) if not added_parameters(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) + + # TODO batch invoer bestand mogelijk maken print("\nGIS LAGEN") if not added_dijktraject(app_settings=app_settings): @@ -100,9 +102,11 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) print("\nPARAMETER INVOER") - # TODO Voeg mogelijkheid om ruimtelijke input aan te passen toe. + # TODO Optie om GIS invoer te vervangen. # TODO Check validation correct blijft werken. - # TODO Invoer voor koppeling? Validatie daarna? + # TODO verwijder traject waardes als gis_join al waardes heeft. + # Misschien checken of de orde van overschrijven wel logisch is? + # Excel over gis maar wel gis-uittredepunt over excel-traject? if not added_input_parameter_data(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) diff --git a/geoprob_pipe/cmd_app/spatial_layers/__init__.py b/geoprob_pipe/cmd_app/spatial_layers/__init__.py index e0bac988..56ce66db 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/__init__.py +++ b/geoprob_pipe/cmd_app/spatial_layers/__init__.py @@ -1,12 +1,13 @@ from .added_ahn import added_ahn -from .base_inquiry import BaseInquiry from .added_binnenteenlijn import added_binnenteenlijn from .added_buitenteenlijn import added_buitenteenlijn from .added_dijktraject import added_dijktraject -from .hrd.hrd import added_hrd_fragility_curves from .added_intredelijn import added_intredelijn -from .added_parameters import added_parameters +from .added_parameters import LIST_PARAMS, added_parameters from .added_ruimtelijke_invoer import added_ruimtelijke_input from .added_scenarios import added_scenarios -from .uittredepunten.uittredepunten import added_uittredepunten from .added_vakindeling import added_vakindeling +from .base_inquiry import BaseInquiry +from .hrd.hrd import added_hrd_fragility_curves +from .uittredepunten.uittredepunten import added_uittredepunten +from .utils import valid_parameter_list diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py index 65310ff2..b2a16db1 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py @@ -5,15 +5,7 @@ import InquirerPy.prompts.input as prompt -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, -) +from.utils import valid_parameter_list from geoprob_pipe.utils.validation_messages import BColors if TYPE_CHECKING: @@ -71,25 +63,8 @@ def request_parameters(app_settings: ApplicationSettings): :param app_settings: `ApplicationSettings` object. """ 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 wordt later gesloten. - - input_list: list[str] = [param for param in LIST_PARAMS.keys()] - match model: - case "model4a": - model_list = [param["name"] for param in MODEL4A_INPUT] - valid_list = [x for x in input_list if x in model_list] - - case "wbi": - model_list = [param["name"] for param in WBI_INPUT] - valid_list = [x for x in input_list if x in model_list] - case "moria": - model_list = [param["name"] for param in MORIA_INPUT] - valid_list = [x for x in input_list if x in model_list] + + valid_list = valid_parameter_list(app_settings) scenario_input_is_valid = False while scenario_input_is_valid is False: diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py index 58644845..d8849715 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py @@ -3,7 +3,9 @@ import sqlite3 from typing import TYPE_CHECKING -import InquirerPy.prompts.input as prompt +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 @@ -15,13 +17,13 @@ def added_scenarios(app_settings: ApplicationSettings): :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",) - ) + ("ruimtelijke_scenarios",), + ) check = cur.fetchone()[0] == 1 if not check: request_scenarios(app_settings) @@ -34,10 +36,10 @@ def request_scenarios(app_settings: ApplicationSettings): deze toe aan de metadata. :param app_settings: `ApplicationSettings` object. - """ - scenario_input_is_valid = False - while scenario_input_is_valid is False: - scenario_input: str = prompt.InputPrompt( + """ + + 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. @@ -48,14 +50,20 @@ def request_scenarios(app_settings: ApplicationSettings): if scenario_input == "": scenarios = "" else: - scenarios = scenario_input.split(",") - scenarios = ", ".join(scenarios) - # TODO Check valid input - scenario_input_is_valid = True - + 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 (?, ?)" @@ -65,4 +73,4 @@ def request_scenarios(app_settings: ApplicationSettings): conn.execute(sql_insert, ("ruimtelijke_scenarios", scenarios)) # type:ignore conn.commit() - conn.close() \ No newline at end of file + conn.close() diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 8cbb7769..f928f658 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -26,6 +26,7 @@ from shapely import LineString, MultiLineString from geoprob_pipe.utils.validation_messages import BColors +from .added_parameters import LIST_PARAMS if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings diff --git a/geoprob_pipe/cmd_app/spatial_layers/utils.py b/geoprob_pipe/cmd_app/spatial_layers/utils.py new file mode 100644 index 00000000..a9302c73 --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_layers/utils.py @@ -0,0 +1,43 @@ +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, +) +from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS + +if TYPE_CHECKING: + from geoprob_pipe.cmd_app.cmd import ApplicationSettings + +def valid_parameter_list(app_settings: ApplicationSettings): + 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 wordt later gesloten. + + 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 = [x for x in input_list if x in model_list] + + case "wbi": + model_list = [param["name"] for param in WBI_INPUT] + valid_list = [x for x in input_list if x in model_list] + case "moria": + model_list = [param["name"] for param in MORIA_INPUT] + valid_list = [x for x in input_list if x in model_list] + + return valid_list \ No newline at end of file From 309d2ef759ae7f60d7f3fc4374faa5e092546e5e Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 21 May 2026 09:20:30 +0200 Subject: [PATCH 12/53] Bugfixes for test; check imports minder gevoeligheid voor circulaire imports --- .../cmd_app/spatial_joins/coupled_hrd.py | 2 +- .../spatial_joins/coupled_parameters.py | 2 +- .../cmd_app/spatial_joins/hrd_couple.py | 2 -- .../cmd_app/spatial_joins/shape_couple.py | 4 +-- .../cmd_app/spatial_layers/__init__.py | 9 ++++-- .../spatial_layers/added_binnenteenlijn.py | 2 +- .../spatial_layers/added_buitenteenlijn.py | 2 +- .../spatial_layers/added_intredelijn.py | 2 +- .../spatial_layers/added_parameters.py | 28 ++----------------- .../added_ruimtelijke_invoer.py | 3 +- .../cmd_app/spatial_layers/base_inquiry.py | 1 - .../{utils.py => valid_parameters.py} | 26 +++++++++++++++-- geoprob_pipe/results/assemblage/functions.py | 2 +- tests/results/assemblage/test_assemblage.py | 3 +- 14 files changed, 44 insertions(+), 44 deletions(-) rename geoprob_pipe/cmd_app/spatial_layers/{utils.py => valid_parameters.py} (58%) diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py index 47843354..e0209397 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py +++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING import fiona -from hrd_couple import HRDCouple +from .hrd_couple import HRDCouple if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py index 11dde629..919a3d16 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py @@ -3,7 +3,7 @@ import sqlite3 from typing import TYPE_CHECKING -from shape_couple import ShapeCouple +from .shape_couple import ShapeCouple from geoprob_pipe.utils.validation_messages import BColors if TYPE_CHECKING: diff --git a/geoprob_pipe/cmd_app/spatial_joins/hrd_couple.py b/geoprob_pipe/cmd_app/spatial_joins/hrd_couple.py index 80a164c7..fb201b7a 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/hrd_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/hrd_couple.py @@ -13,8 +13,6 @@ import geopandas as gpd import pandas as pd -from geoprob_pipe.cmd_app.cmd import ApplicationSettings - if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings diff --git a/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py index d338da8b..4d4b6cc8 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py @@ -6,9 +6,9 @@ import geopandas as gpd import pandas as pd -from shapely.geometry import LineString, MultiLineString, Polygon, MultiPolygon +from shapely.geometry import LineString, MultiLineString, MultiPolygon, Polygon -from geoprob_pipe.cmd_app.spatial_layers.added_parameters import LIST_PARAMS +from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings diff --git a/geoprob_pipe/cmd_app/spatial_layers/__init__.py b/geoprob_pipe/cmd_app/spatial_layers/__init__.py index 56ce66db..cd71cbe9 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/__init__.py +++ b/geoprob_pipe/cmd_app/spatial_layers/__init__.py @@ -1,13 +1,16 @@ +# 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 LIST_PARAMS, added_parameters +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 .base_inquiry import BaseInquiry from .hrd.hrd import added_hrd_fragility_curves from .uittredepunten.uittredepunten import added_uittredepunten -from .utils import valid_parameter_list + diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py index 8cdcac20..6bbf08a1 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py @@ -9,7 +9,7 @@ import fiona from geoprob_pipe.utils.validation_messages import BColors -from geoprob_pipe.cmd_app.spatial_layers import BaseInquiry +from .base_inquiry import BaseInquiry if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py index db35481c..1f8c7b89 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py @@ -9,7 +9,7 @@ import fiona -from geoprob_pipe.cmd_app.spatial_layers import BaseInquiry +from .base_inquiry import BaseInquiry from geoprob_pipe.utils.validation_messages import BColors if TYPE_CHECKING: diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py index 3db07052..7a58bf60 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py @@ -9,7 +9,7 @@ import fiona -from geoprob_pipe.cmd_app.spatial_layers import BaseInquiry +from .base_inquiry import BaseInquiry from geoprob_pipe.utils.validation_messages import BColors if TYPE_CHECKING: diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py index b2a16db1..5f6c2f77 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py @@ -5,35 +5,13 @@ import InquirerPy.prompts.input as prompt -from.utils import valid_parameter_list 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 -# 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 added_parameters(app_settings: ApplicationSettings): """ @@ -63,7 +41,7 @@ def request_parameters(app_settings: ApplicationSettings): :param app_settings: `ApplicationSettings` object. """ conn = sqlite3.connect(app_settings.geopackage_filepath) - + valid_list = valid_parameter_list(app_settings) scenario_input_is_valid = False diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py index b2cb5934..6524f109 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py @@ -5,8 +5,7 @@ import fiona -from geoprob_pipe.cmd_app.spatial_layers import BaseInquiry -from geoprob_pipe.cmd_app.spatial_layers.added_parameters import LIST_PARAMS +from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS, BaseInquiry from geoprob_pipe.utils.validation_messages import BColors if TYPE_CHECKING: diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index f928f658..8cbb7769 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -26,7 +26,6 @@ from shapely import LineString, MultiLineString from geoprob_pipe.utils.validation_messages import BColors -from .added_parameters import LIST_PARAMS if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings diff --git a/geoprob_pipe/cmd_app/spatial_layers/utils.py b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py similarity index 58% rename from geoprob_pipe/cmd_app/spatial_layers/utils.py rename to geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py index a9302c73..151d069c 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/utils.py +++ b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py @@ -12,10 +12,32 @@ from geoprob_pipe.calculations.systems.wbi.initial_input import ( INITIAL_INPUT as WBI_INPUT, ) -from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS 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): conn = sqlite3.connect(app_settings.geopackage_filepath) @@ -40,4 +62,4 @@ def valid_parameter_list(app_settings: ApplicationSettings): model_list = [param["name"] for param in MORIA_INPUT] valid_list = [x for x in input_list if x in model_list] - return valid_list \ No newline at end of file + return valid_list diff --git a/geoprob_pipe/results/assemblage/functions.py b/geoprob_pipe/results/assemblage/functions.py index 6c445120..3c0f08b6 100644 --- a/geoprob_pipe/results/assemblage/functions.py +++ b/geoprob_pipe/results/assemblage/functions.py @@ -128,7 +128,7 @@ def window_collect(window_size: float, point_list: list[UittredepuntElement], window_elements: List[WindowElement] = [] if m_tot not in bins_window: 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], 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 From 847ebbdb352178d5e6435c87b8a050eff8ed4191 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 21 May 2026 16:06:20 +0200 Subject: [PATCH 13/53] WIP 2105: gpkg import, batch_input, lines per scenario, polderpeil niet ruimtelijk vereist --- .../systems/moria/initial_input.py | 2 +- .../calculations/systems/validation.py | 4 +- geoprob_pipe/cmd_app/cmd.py | 33 +- geoprob_pipe/cmd_app/general/project.py | 4 +- .../initiate_input_excel_tables.py | 2 +- .../update_ruimtelijke_invoer.py | 8 +- geoprob_pipe/cmd_app/questionnaire.py | 22 +- .../spatial_joins/couple_objects/__init__.py | 0 .../base_couple.py} | 67 ++-- .../couple_objects/distance_couple.py | 37 +++ .../couple_objects/hrd_couple.py | 84 +++++ .../{ => couple_objects}/shape_couple.py | 153 +-------- .../coupled_distance_to_exit_points.py | 132 +++++--- .../cmd_app/spatial_joins/coupled_hrd.py | 11 +- .../spatial_joins/coupled_parameters.py | 6 +- .../cmd_app/spatial_layers/__init__.py | 2 + .../spatial_layers/added_binnenteenlijn.py | 3 +- .../spatial_layers/added_buitenteenlijn.py | 3 +- .../spatial_layers/added_intredelijn.py | 12 +- .../spatial_layers/added_parameters.py | 4 +- .../added_ruimtelijke_invoer.py | 4 +- .../cmd_app/spatial_layers/added_scenarios.py | 8 +- .../spatial_layers/added_vakindeling.py | 26 +- .../cmd_app/spatial_layers/base_inquiry.py | 77 +++-- .../spatial_layers/check_batch_input.py | 13 + .../cmd_app/spatial_layers/old_polderpeil.py | 298 +++++++++--------- geoprob_pipe/cmd_app/utils/batch_input.py | 80 +++++ 27 files changed, 636 insertions(+), 459 deletions(-) create mode 100644 geoprob_pipe/cmd_app/spatial_joins/couple_objects/__init__.py rename geoprob_pipe/cmd_app/spatial_joins/{hrd_couple.py => couple_objects/base_couple.py} (76%) create mode 100644 geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance_couple.py create mode 100644 geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py rename geoprob_pipe/cmd_app/spatial_joins/{ => couple_objects}/shape_couple.py (51%) create mode 100644 geoprob_pipe/cmd_app/spatial_layers/check_batch_input.py create mode 100644 geoprob_pipe/cmd_app/utils/batch_input.py diff --git a/geoprob_pipe/calculations/systems/moria/initial_input.py b/geoprob_pipe/calculations/systems/moria/initial_input.py index 877b9178..46e69f93 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", }, { 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/cmd_app/cmd.py b/geoprob_pipe/cmd_app/cmd.py index 9cc31466..8e4508a6 100644 --- a/geoprob_pipe/cmd_app/cmd.py +++ b/geoprob_pipe/cmd_app/cmd.py @@ -1,33 +1,48 @@ -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" + self.batch_input: bool = False # Placeholder 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") @@ -103,7 +118,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/general/project.py b/geoprob_pipe/cmd_app/general/project.py index 82c45ab9..f762315e 100644 --- a/geoprob_pipe/cmd_app/general/project.py +++ b/geoprob_pipe/cmd_app/general/project.py @@ -153,7 +153,7 @@ 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 @@ -182,7 +182,7 @@ def specify_dir_for_new_project(app_settings: ApplicationSettings): workspace_dir_is_valid = True - app_settings.workspace_dir = workspace_dir + app_settings.workspace_dir = Path(workspace_dir) # Continue questionnaire specify_project_filename(app_settings) 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/update_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py index ffe31f65..56471654 100644 --- a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -14,10 +14,10 @@ from geoprob_pipe.cmd_app.cmd import ApplicationSettings -# TODO herinvoeren van gis lagen. -# TODO toevoegen van nieuwe parameters. -# TODO Toevangen van scenarios. Alles opnieuw inladen en koppelen? -# TODO verwijderen van lagen? Of alleen overschrijven via excel invoer? +# TODO Vincent: Herinvoeren van gis lagen. +# TODO Vincent: Toevoegen van nieuwe parameters. +# TODO Vincent: Toevangen van scenarios. Alles opnieuw inladen en koppelen? +# TODO Vincent: Verwijderen van lagen? Of alleen overschrijven via excel invoer? def inquire_spatial_update( app_settings: ApplicationSettings, ): diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 182ea8b7..9546ba4b 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -16,9 +16,9 @@ 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, - coupled_parameters_to_uittredepunten ) from geoprob_pipe.cmd_app.spatial_layers import ( added_ahn, @@ -32,6 +32,7 @@ added_scenarios, added_uittredepunten, added_vakindeling, + check_batch_input, ) if TYPE_CHECKING: @@ -55,8 +56,9 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) if not added_parameters(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) - - # TODO batch invoer bestand mogelijk maken + # TODO Vincent: batch invoer bestand mogelijk maken + 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): @@ -76,7 +78,7 @@ def questionnaire(app_settings: ApplicationSettings): if not added_intredelijn(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) - print("/nRUIMTELIJKE INPUT") + print("\nRUIMTELIJKE INPUT") # Loop voor alle parameters if not added_ruimtelijke_input(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) @@ -85,7 +87,9 @@ def questionnaire(app_settings: ApplicationSettings): ) # AHN may be optional print("\nGEOGRAFISCHE KOPPELINGEN") - # TODO maak coupleling for raster + # TODO Vincent: maak coupleling for raster + if not coupled_parameters_to_uittredepunten(app_settings=app_settings): + sys.exit(EARLY_EXIT_MESSAGE) 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): @@ -94,17 +98,15 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) if not coupled_hrd_to_uittredepunten(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) - if not coupled_parameters_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) print("\nPARAMETER INVOER") - # TODO Optie om GIS invoer te vervangen. - # TODO Check validation correct blijft werken. - # TODO verwijder traject waardes als gis_join al waardes heeft. + # TODO Vincent: Optie om GIS invoer te vervangen. + # TODO Vincent: Check validation correct blijft werken. + # TODO Vincent: verwijder traject waardes als gis_join al waardes heeft. # Misschien checken of de orde van overschrijven wel logisch is? # Excel over gis maar wel gis-uittredepunt over excel-traject? if not added_input_parameter_data(app_settings=app_settings): 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/hrd_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py similarity index 76% rename from geoprob_pipe/cmd_app/spatial_joins/hrd_couple.py rename to geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py index fb201b7a..3d0cdc49 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/hrd_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py @@ -1,51 +1,46 @@ -""" -Class voor het koppelen van de HRD-locaties aan de uittredepunten. -Versimplende versie van de ShapeCouple class. -""" -# TODO importeer _upsert_to_gpkg vanuit ShapeCouple - from __future__ import annotations import datetime import sqlite3 from typing import TYPE_CHECKING -import geopandas as gpd +import numpy as np import pandas as pd if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings -class HRDCouple: - def __init__(self, app_settings: ApplicationSettings) -> None: - self.app_settings = app_settings +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 toegevoedg aan de geopackage. - def couple_exit_points(self): - # 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(join_df) - self._upsert_to_gpkg(df_to_add) - - def _create_df(self, join_df: pd.DataFrame): + :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"] = "buitenwaterstand" + df["parameter"] = self.param df["scope"] = "uittredepunt" - df["ondergrondscenario_naam"] = "" - df["distribution_type"] = "cdf_curve" - df["mean"] = "" - df["variation"] = "" - df["deviation"] = "" - df["minimum"] = "" - df["maximum"] = "" - df["fragility_values_ref"] = join_df.get("hrd_name", "") + df["ondergrondscenario_naam"] = scenario + df["distribution_type"] = join_df.get(f"{self.param}_dist", "") + 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", "") + df["fragility_values_ref"] = "" df["bronnen"] = "" df["opmerking"] = "" @@ -68,7 +63,7 @@ def _create_df(self, join_df: pd.DataFrame): ] ] return df - + def _upsert_to_gpkg(self, df: pd.DataFrame): """ Voeg de dataframe toe aan de tabel. Als de tabel nog niet bestaat @@ -103,7 +98,7 @@ def _upsert_to_gpkg(self, df: pd.DataFrame): """ ) data = [tuple(row) for row in df.to_numpy()] - placeholders = ", ".join(["?"] * len(data)) + placeholders = ", ".join(["?"] * 13) # UPSERT naar tabel cursor.executemany( f""" @@ -120,7 +115,7 @@ def _upsert_to_gpkg(self, df: pd.DataFrame): maximum, fragility_values_ref, bronnen, - opmerking, + opmerking ) VALUES ({placeholders}) ON CONFLICT ( @@ -157,7 +152,7 @@ def _upsert_to_gpkg(self, df: pd.DataFrame): last_change, srs_id ) VALUES (?, ?, ?, ?, ?, ?) - ON CONFLICT (indentifier) DO UPDATE SET + ON CONFLICT (identifier) DO UPDATE SET table_name = excluded.table_name, data_type = excluded.data_type, description = excluded.description, diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance_couple.py new file mode 100644 index 00000000..d14cfbc2 --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance_couple.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +import pandas as pd +from typing import TYPE_CHECKING + +from .base_couple 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_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py new file mode 100644 index 00000000..25b237b9 --- /dev/null +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py @@ -0,0 +1,84 @@ +""" +Class voor het koppelen van de HRD-locaties aan de uittredepunten. +Versimplende versie van de ShapeCouple class. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import geopandas as gpd +import pandas as pd + +from .base_couple 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 uitredepunten. + + :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"] = "" + df["variation"] = "" + df["deviation"] = "" + df["minimum"] = "" + df["maximum"] = "" + 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/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py similarity index 51% rename from geoprob_pipe/cmd_app/spatial_joins/shape_couple.py rename to geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py index 4d4b6cc8..6f0e6cef 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/shape_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py @@ -1,24 +1,23 @@ from __future__ import annotations -import datetime import sqlite3 from typing import TYPE_CHECKING import geopandas as gpd -import pandas as pd from shapely.geometry import LineString, MultiLineString, MultiPolygon, Polygon from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS +from .base_couple import BaseCouple if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings -class ShapeCouple: +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_invoer_parameters'. + De gekoppelde waarden worden weggeschreven in de tabel 'gis_join_parameter_invoer'. :param app_settings: `ApplicationSettings` object. :param param: Parameter die gekoppeled moet worden. @@ -150,150 +149,8 @@ def _join_to_polygon(self, gdf: gpd.GeoDataFrame, scenario: str): self._upsert_to_gpkg(df_to_add) - # TODO add option for rasters + # TODO Vincent: Add option for rasters def _join_to_raster(self): pass - def _create_df(self, join_df: pd.DataFrame, scenario: str) -> pd.DataFrame: - """ - Maak de dataframe die moet worden toegevoedg aan de geopackage. - - :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", "") - df["mean"] = join_df.get(f"{self.param}_mean", "") - df["variation"] = join_df.get(f"{self.param}_var", "") - df["deviation"] = join_df.get(f"{self.param}_dev", "") - df["minimum"] = join_df.get(f"{self.param}_min", "") - df["maximum"] = join_df.get(f"{self.param}_max", "") - 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(["?"] * len(data)) - # 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 - 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 (indentifier) 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() + 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 index 7bcd785b..c05dda1b 100644 --- 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 @@ -3,57 +3,111 @@ """ 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 + +import geopandas as gpd +import fiona + +from geoprob_pipe.cmd_app.spatial_joins.couple_objects.distance_couple import ( + DistCouple, +) +from geoprob_pipe.utils.validation_messages import BColors + if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings +# TODO Vincent: Check of deze al in de tabel staan. +def coupled_distances_to_uittredepunten( + app_settings: ApplicationSettings, +) -> bool: + """ + Bepaal de afstanden tussen de uittredepunten en de intrede, binnenteen en + buitenteenlijen. -def coupled_distances_to_uittredepunten(app_settings: ApplicationSettings) -> bool: + :param app_settings: Object met de insellingen van de applicatie + """ # 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 + gdf_exit_points: gpd.GeoDataFrame = gpd.read_file( + app_settings.geopackage_filepath, layer="uittredepunten" + ) # 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) + layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) + 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: 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)) + 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": "mean"}) - append_to_gis_join_parameter_invoer_table( - df_sjoin=df_l_but, parameter_name="L_but", geopackage_filepath=app_settings.geopackage_filepath) + 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: 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) + 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/coupled_hrd.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py index e0209397..4c7f12c3 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py +++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py @@ -7,13 +7,20 @@ from typing import TYPE_CHECKING import fiona -from .hrd_couple import HRDCouple +from .couple_objects.hrd_couple import HRDCouple if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings - +# TODO Vincent: Check of deze al in de tabel staan. def coupled_hrd_to_uittredepunten(app_settings: ApplicationSettings) -> bool: + """ + Voeg de HRD locaties toe aan de invoer tabel als deze zijn opgegeven. + + :param ApplicationSettings app_settings: Object met de insellingen van de applicatie + :return: _description_ + :rtype: bool + """ layers = fiona.listlayers(app_settings.geopackage_filepath) diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py index 919a3d16..e523d1b6 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py @@ -3,13 +3,13 @@ import sqlite3 from typing import TYPE_CHECKING -from .shape_couple import ShapeCouple +from .couple_objects.shape_couple import ShapeCouple from geoprob_pipe.utils.validation_messages import BColors if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings - +# TODO Vincent: Check of deze al in de tabel staan. def coupled_parameters_to_uittredepunten( app_settings: ApplicationSettings, ) -> bool: @@ -21,7 +21,7 @@ def coupled_parameters_to_uittredepunten( ) parameters: list[str] = cursor.fetchone()[0].split(", ") conn.close() - if parameters == []: + if parameters == ['']: # De split maakt één lege string als de uit de metadata gelezen string leeg is. print( BColors.OKBLUE, "✔ Geen ruimtelijke koppelingen.", diff --git a/geoprob_pipe/cmd_app/spatial_layers/__init__.py b/geoprob_pipe/cmd_app/spatial_layers/__init__.py index cd71cbe9..1c5d7402 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/__init__.py +++ b/geoprob_pipe/cmd_app/spatial_layers/__init__.py @@ -11,6 +11,8 @@ 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/added_binnenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py index 6bbf08a1..2f516724 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py @@ -32,6 +32,7 @@ def request_binnenteenlijn_filepath(app_settings: ApplicationSettings): binnenteenlijn_inquiry = BaseInquiry( app_settings=app_settings, param="binnenteenlijn", - specific_shape="lines" + 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 index 1f8c7b89..fc327d6b 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py @@ -21,7 +21,7 @@ def added_buitenteenlijn(app_settings: ApplicationSettings) -> bool: if "buitenteenlijn" in layers: print( - BColors.OKBLUE, f"✔ Buitenteenlijn al toegevoegd.", BColors.ENDC + BColors.OKBLUE, "✔ Buitenteenlijn al toegevoegd.", BColors.ENDC ) return True @@ -34,5 +34,6 @@ def request_buitenteenlijn_filepath(app_settings: ApplicationSettings): 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/added_intredelijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py index 7a58bf60..b12b9dd7 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py @@ -17,11 +17,11 @@ def added_intredelijn(app_settings: ApplicationSettings) -> bool: - layers = fiona.listlayers(app_settings.geopackage_filepath) - - if "intredelijn" in layers: - print(BColors.OKBLUE, "✔ Intredelijn al toegevoegd.", BColors.ENDC) - return True + 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 @@ -31,6 +31,6 @@ def request_intredelijn_filepath(app_settings: ApplicationSettings): intredelijn_inquiry = BaseInquiry( app_settings=app_settings, param="intredelijn", - specific_shape="lines" + 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 index 5f6c2f77..baf30dd6 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py @@ -48,12 +48,12 @@ def request_parameters(app_settings: ApplicationSettings): while scenario_input_is_valid is False: 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 == "": diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py index 6524f109..47b37409 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py @@ -27,7 +27,7 @@ def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool: scenarios: list[str] = cursor.fetchone()[0].split(", ") conn.close() layers = fiona.listlayers(app_settings.geopackage_filepath) - if parameters == []: + if parameters == ['']: # De split maakt één lege string als de uit de metadata gelezen string leeg is. print( BColors.OKBLUE, "✔ Geen ruimtelijke parameter invoer.", @@ -36,7 +36,7 @@ def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool: return True for parameter in parameters: - if scenarios == []: + if scenarios == ['']: # De split maakt één lege string als de uit de metadata gelezen string leeg is. if parameter in layers: print( BColors.OKBLUE, diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py index d8849715..1b4bfa7f 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py @@ -41,10 +41,10 @@ def request_scenarios(app_settings: ApplicationSettings): 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. +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 == "": diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py index eb40641c..6a1c3c26 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_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,7 +46,7 @@ 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) + print(BColors.OKBLUE, "✔ Vakindeling al toegevoegd.", BColors.ENDC) def import_from_geopackage(filepath: str) -> GeoDataFrame: @@ -77,7 +78,7 @@ def import_from_geopackage(filepath: str) -> GeoDataFrame: def import_from_geodatabase(filepath: str) -> GeoDataFrame: - layer_name: Optional[str] = None + layer_name: str = "" layer_name_is_valid = False while layer_name_is_valid is False: layer_name: str = inquirer.text( @@ -105,13 +106,16 @@ 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 = "" + + while True: + if app_settings.batch_input: + filepath = app_settings.input_config.get("vakindeling", "path") + 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 +124,10 @@ 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) continue - filepath_is_valid = True + break if filepath.endswith(".shp"): with warnings.catch_warnings(): diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 8cbb7769..7e43c02a 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -31,6 +31,7 @@ from geoprob_pipe.cmd_app.cmd import ApplicationSettings +# TODO Vincent: Uitlezen van batch_input.ini als die keuze gemaakt is. class BaseInquiry: def __init__( self, @@ -38,6 +39,7 @@ def __init__( param: str, specific_shape: str = "", include_value: bool = False, + single_geometry: bool = False, ) -> None: """ Class voor de opvraag van de ruimteljke invoer van de parameters. @@ -54,6 +56,7 @@ def __init__( 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( @@ -67,18 +70,21 @@ def request_filepath(self): """ Method voor het opvragen van het filepath. """ - - filepath_is_valid = False - - while filepath_is_valid is False: - filepath: str = prompt.InputPrompt( - message=( - f""" + 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}", "path" + ) + else: + filepath: str = prompt.InputPrompt( + message=( + f""" Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase met de {self.param} geometrieën. - """ - ) - ).execute() + """ + ) + ).execute() filepath = filepath.replace('"', "") @@ -88,6 +94,7 @@ def request_filepath(self): "Het opgegeven bestandspad bestaat niet.", BColors.ENDC, ) + skip_batch = True continue if not ( @@ -103,13 +110,15 @@ def request_filepath(self): """, BColors.ENDC, ) + skip_batch = True continue # Import data gdf = self._import_data(filepath) # type:ignore # Add data to geopackage - filepath_is_valid = self._add_to_gpkg(gdf) + if self._add_to_gpkg(gdf): + break print(BColors.OKBLUE, f"✅ {self.param} toegevoegd.", BColors.ENDC) @@ -155,17 +164,22 @@ def _import_from_db(self, filepath: str) -> gpd.GeoDataFrame: :param filepath: Bestandspad van de database. :return: GeoDataFrame met de uitgelezen data. """ - layer_name_is_valid = False - while layer_name_is_valid is False: - 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. - """ + 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}", "layer" ) - ).execute() + 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() @@ -186,7 +200,7 @@ def _import_from_db(self, filepath: str) -> gpd.GeoDataFrame: ) continue - layer_name_is_valid = True + break gdf: gpd.GeoDataFrame = gpd.read_file(filepath, layer=layer_name) # type:ignore return gdf @@ -274,7 +288,16 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: else: return self._add_seperate_with_suffix(gdf) - elif not self.include_value and self.scenarios == "": + 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( @@ -302,10 +325,12 @@ def _scenario_check(self, column_list: list[str]): :return: Check of het scenario voorkomt. :rtype: bool """ - if "ondegrondscenario" not in column_list: + if "ondergrondscenario" not in column_list: print( BColors.WARNING, - "Geen kolom met de naam 'ondergrondscenario' gevonden.", + "Geen kolom met de naam 'ondergrondscenario' gevonden.\n", + "De volgende kolommen zijn gevonde:\n", + f"{column_list}", BColors.ENDC, ) @@ -388,7 +413,7 @@ def _add_with_separate_geometry(self, gdf: gpd.GeoDataFrame) -> bool: return False for scenario in self.scenarios: - mask = gdf["ondergrondscenario" == scenario] + mask = gdf["ondergrondscenario"] == scenario gdf_to_add = gdf[mask][["geometry"]] if len(gdf_to_add) == 0: 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..603c44f4 --- /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 + +if TYPE_CHECKING: + from geoprob_pipe.cmd_app.cmd import ApplicationSettings + +# TODO Vincent: Voeg een check aan de metadata toe of dit gevraagd moet worden. +# Eerste keer en als de input veranderd moet worden. +def check_batch_input(app_settings: ApplicationSettings): + batch_inquiry(app_settings=app_settings) + return True \ No newline at end of file diff --git a/geoprob_pipe/cmd_app/spatial_layers/old_polderpeil.py b/geoprob_pipe/cmd_app/spatial_layers/old_polderpeil.py index 0e6c4e24..e6fa36bc 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/old_polderpeil.py +++ b/geoprob_pipe/cmd_app/spatial_layers/old_polderpeil.py @@ -1,149 +1,149 @@ -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 # type:ignore - 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) +# 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 # type:ignore +# 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/utils/batch_input.py b/geoprob_pipe/cmd_app/utils/batch_input.py new file mode 100644 index 00000000..dd7500f6 --- /dev/null +++ b/geoprob_pipe/cmd_app/utils/batch_input.py @@ -0,0 +1,80 @@ +from __future__ import annotations + +import configparser +import sqlite3 +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": + 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 + return + + +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() + + datasets = [ + {"name": "vakindeling", "path": "", "layer": "", "column": ""}, + {"name": "uittredepunten", "path": "", "layer": "", "column": ""}, + {"name": "binnenteenlijn", "path": "", "layer": "", "column": ""}, + {"name": "buitenteenlijn", "path": "", "layer": "", "column": ""}, + {"name": "intredelijn", "path": "", "layer": "", "column": ""}, + ] + if not parameters == ['']: + for parameter in parameters: + datasets.append({ + "name": f"{parameter}", "path": "", "layer": "" + }) + + config = configparser.ConfigParser() + + for ds in datasets: + config[ds["name"]] = { + "path": ds["path"], + "layer": ds["layer"], + "column": ds["column"] + } + + with open(f"{app_settings.workspace_dir}/batch_input.ini", "w") as f: + config.write(f) From d70db370728ef535037df53e402c732d1e05b67e Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Fri, 22 May 2026 08:44:59 +0200 Subject: [PATCH 14/53] batch_invoer --- .../spatial_layers/added_parameters.py | 21 ++-- .../spatial_layers/added_vakindeling.py | 113 +++++++++++------- .../cmd_app/spatial_layers/base_inquiry.py | 5 +- .../uittredepunten/uittredepunten.py | 108 ++++++++++------- geoprob_pipe/cmd_app/utils/batch_input.py | 55 +++++---- 5 files changed, 191 insertions(+), 111 deletions(-) diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py index baf30dd6..53f5045c 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py @@ -43,12 +43,13 @@ def request_parameters(app_settings: ApplicationSettings): conn = sqlite3.connect(app_settings.geopackage_filepath) valid_list = valid_parameter_list(app_settings) + + parameters: list[str] = [] - scenario_input_is_valid = False - while scenario_input_is_valid is False: + 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. @@ -57,7 +58,7 @@ def request_parameters(app_settings: ApplicationSettings): ) ).execute() if parameter_input == "": - parameters = "" + parameters = [] elif parameter_input == "list": params_str = ", ".join(valid_list) # type:ignore print( @@ -70,22 +71,26 @@ def request_parameters(app_settings: ApplicationSettings): else: parameters = parameter_input.split(",") - if parameters not in valid_list: # type:ignore + if not all(x in valid_list for x in parameters): # type:ignore print( BColors.WARNING, "Een of meerdere van de opgegeven parameters zijn niet geschikt voor ruimtelijke invoer.", BColors.ENDC, ) continue - scenario_input_is_valid = True + 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, (parameters, "ruimtelijke_parameters")) # type:ignore + cur = conn.execute( + sql_update, (", ".join(parameters), "ruimtelijke_parameters") + ) if cur.rowcount == 0: - conn.execute(sql_insert, ("ruimtelijke_parameters", parameters)) # type:ignore + conn.execute( + sql_insert, ("ruimtelijke_parameters", ", ".join(parameters)) + ) conn.commit() conn.close() diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py index 6a1c3c26..9435d579 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py @@ -49,14 +49,20 @@ def check_validity_vakindeling(app_settings: ApplicationSettings): print(BColors.OKBLUE, "✔ 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() +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() @@ -67,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.*") @@ -77,14 +84,21 @@ def import_from_geopackage(filepath: str) -> GeoDataFrame: return gdf -def import_from_geodatabase(filepath: str) -> GeoDataFrame: +def import_from_geodatabase(app_settings: ApplicationSettings, + filepath: str) -> GeoDataFrame: layer_name: str = "" - 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() + 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() @@ -95,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.*") @@ -107,10 +122,11 @@ def import_from_geodatabase(filepath: str) -> GeoDataFrame: def request_vakindeling_filepath(app_settings: ApplicationSettings): filepath: str = "" + skip_batch = False # Als batch input faalt ga over op handmatig while True: - if app_settings.batch_input: - filepath = app_settings.input_config.get("vakindeling", "path") + 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 " @@ -125,6 +141,7 @@ def request_vakindeling_filepath(app_settings: ApplicationSettings): continue if not os.path.exists(filepath): print(BColors.WARNING, "Het opgegeven bestandspad bestaat niet.", BColors.ENDC) + skip_batch = True continue break @@ -157,14 +174,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) @@ -178,9 +201,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( @@ -197,14 +221,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) @@ -222,6 +252,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 @@ -229,15 +260,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( @@ -254,7 +287,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) @@ -274,7 +307,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"], @@ -294,4 +327,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 index 7e43c02a..90f6b00f 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -31,7 +31,6 @@ from geoprob_pipe.cmd_app.cmd import ApplicationSettings -# TODO Vincent: Uitlezen van batch_input.ini als die keuze gemaakt is. class BaseInquiry: def __init__( self, @@ -74,7 +73,7 @@ def request_filepath(self): while True: if self.app_settings.batch_input and not skip_batch: filepath = self.app_settings.input_config.get( - f"{self.param}", "path" + f"{self.param}", "filepath" ) else: filepath: str = prompt.InputPrompt( @@ -168,7 +167,7 @@ def _import_from_db(self, filepath: str) -> gpd.GeoDataFrame: while True: if self.app_settings.batch_input and not skip_batch: layer_name = self.app_settings.input_config.get( - f"{self.param}", "layer" + f"{self.param}", "database_layer" ) else: layer_name: str = prompt.InputPrompt( 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/utils/batch_input.py b/geoprob_pipe/cmd_app/utils/batch_input.py index dd7500f6..acc3c898 100644 --- a/geoprob_pipe/cmd_app/utils/batch_input.py +++ b/geoprob_pipe/cmd_app/utils/batch_input.py @@ -53,28 +53,43 @@ def batch_config_writer(app_settings: ApplicationSettings): ) parameters: list[str] = cursor.fetchone()[0].split(", ") conn.close() - - datasets = [ - {"name": "vakindeling", "path": "", "layer": "", "column": ""}, - {"name": "uittredepunten", "path": "", "layer": "", "column": ""}, - {"name": "binnenteenlijn", "path": "", "layer": "", "column": ""}, - {"name": "buitenteenlijn", "path": "", "layer": "", "column": ""}, - {"name": "intredelijn", "path": "", "layer": "", "column": ""}, - ] - if not parameters == ['']: - for parameter in parameters: - datasets.append({ - "name": f"{parameter}", "path": "", "layer": "" - }) 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": "", + } - for ds in datasets: - config[ds["name"]] = { - "path": ds["path"], - "layer": ds["layer"], - "column": ds["column"] - } - + 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: config.write(f) From b0369031089a8c6bb59a01f2322d70dd0a93a6c7 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Fri, 22 May 2026 10:43:19 +0200 Subject: [PATCH 15/53] update keuzemenu --- .../update_ruimtelijke_invoer.py | 317 +++++++++++++++--- geoprob_pipe/cmd_app/questionnaire.py | 3 +- .../couple_objects/hrd_couple.py | 11 +- .../couple_objects/shape_couple.py | 2 +- .../cmd_app/spatial_layers/added_scenarios.py | 4 +- geoprob_pipe/cmd_app/utils/batch_input.py | 64 ++-- 6 files changed, 328 insertions(+), 73 deletions(-) diff --git a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py index 56471654..31bdff18 100644 --- a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -4,6 +4,7 @@ import sys from typing import TYPE_CHECKING +import fiona from InquirerPy.prompts.input import InputPrompt from InquirerPy.prompts.list import ListPrompt @@ -14,10 +15,7 @@ from geoprob_pipe.cmd_app.cmd import ApplicationSettings -# TODO Vincent: Herinvoeren van gis lagen. -# TODO Vincent: Toevoegen van nieuwe parameters. -# TODO Vincent: Toevangen van scenarios. Alles opnieuw inladen en koppelen? -# TODO Vincent: Verwijderen van lagen? Of alleen overschrijven via excel invoer? +# TODO Vincent: Testen met invoer. def inquire_spatial_update( app_settings: ApplicationSettings, ): @@ -62,8 +60,61 @@ def inquire_spatial_update( def inquire_replace_layers(app_settings: ApplicationSettings): - pass + """ + Verwijder tabellen die opnieuw moeten worden ingeladen om de geopackage te + updaten. + + :param app_settings: _description_ + """ + conn = sqlite3.connect(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_parameters = valid_parameter_list(app_settings) + + while True: + parameter_input: str = InputPrompt( + message=f""" + De volgende parameters zijn nu aangemerkt voor rumtelijke 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 + + if not all([x for x in parameter_input if x in valid_parameters]): + print( + BColors.OKBLUE, + f"Geen tabellen verwijderd. '{parameter_input}' bevat een ongeldige parameter.", + BColors.ENDC, + ) + continue + + break + + # Verwijder uit geopackage + layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) + table_list = [layer for layer in layers if layer.split("_")[0] in parameter_input] + remove_tables(app_settings, table_list) + completed_update() def add_parameters(app_settings: ApplicationSettings): """ @@ -71,10 +122,10 @@ def add_parameters(app_settings: ApplicationSettings): kunnen pas verwerkt worden nadat de applicatie opnieuw is opgestart. :param app_settings: `ApplicationSettings` object met alle settings. - """ + """ conn = sqlite3.connect(app_settings.geopackage_filepath) - + # Haal ruimtelijke parameters op vanuit de metadata cursor = conn.cursor() cursor.execute( @@ -82,13 +133,13 @@ def add_parameters(app_settings: ApplicationSettings): ("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(app_settings) - + # Vraag gebruiker voor toevoegingen. while True: parameter_input: str = InputPrompt( @@ -110,19 +161,7 @@ def add_parameters(app_settings: ApplicationSettings): ) return - try: - parameter_list = parameter_input.split(",") - new_parameters = ", ".join(parameter_list) - - except Exception: - print( - BColors.OKBLUE, - f"Geen parameters toegevoegd. '{parameter_input}' is geen geldige invoer.", - BColors.ENDC, - ) - continue - - valid_input = all(param in valid_list for param in current_parameters) + valid_input = all(param in valid_list for param in parameter_input) if not valid_input: print( @@ -135,34 +174,187 @@ def add_parameters(app_settings: ApplicationSettings): break # Update metadata - - parameters = current_parameters + new_parameters.split(",") + parameters = current_parameters + parameter_input.split(",") parameters = list(set(parameters)) # Verwijder dubbele waardes parameters = ", ".join(parameters) update_metadata_parameters(app_settings, parameters) + completed_update() def remove_parameters(app_settings: ApplicationSettings): - pass + conn = sqlite3.connect(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_parameters = valid_parameter_list(app_settings) + + while True: + parameter_input: str = InputPrompt( + message=f""" + De volgende parameters zijn nu aangemerkt voor rumtelijke 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 + if not all([x for x in parameter_input if x in valid_parameters]): + print( + BColors.OKBLUE, + f"Geen parameters verwijderd. '{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) + update_metadata_parameters(app_settings, updated_parameters) + # Verwijder uit geopackage + layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) + table_list = [layer for layer in layers if layer.split("_")[0] in updated_parameters] + remove_tables(app_settings, table_list) + completed_update() def add_scenarios(app_settings: ApplicationSettings): - pass + """ + Voeg ondergrondscenarios toe aan de lijst. Dit betekent dat alle + ruimtelijke invoer opnieuw moet worden ingeladen. + """ + # Haal de huidige scenarios op. + conn = sqlite3.connect(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 + update_metadata_scenarios(app_settings, ", ".join(updated_scenarios)) + + # Remove tables to recollect data. + remove_tables(app_settings) def remove_scenarios(app_settings: ApplicationSettings): - pass + """ + Verwijder ondergrondscenarios uit de lijst. Dit betekent dat alle + ruimtelijke invoer opnieuw moet worden ingeladen. + """ + # Haal de huidige scenarios op. + conn = sqlite3.connect(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 -def update_metadata_parameters(app_settings: ApplicationSettings, parameters: str): + # Update metadata + for scenario in scenario_input.split(","): + current_scenarios.remove(scenario) + + update_metadata_scenarios(app_settings, ", ".join(current_scenarios)) + + # Remove tables to recollect data. + remove_tables(app_settings) + + +def update_metadata_scenarios( + app_settings: ApplicationSettings, scenarios: str +): + """ + Update de ondergrondscenarios in de metadata. + """ + conn = sqlite3.connect(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( + app_settings: ApplicationSettings, parameters: str +): """ Update de parameters voor ruimtelijke invoer in de metadata. - """ + """ 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, (parameters, "ruimtelijke_parameters")) # type:ignore if cur.rowcount == 0: @@ -171,33 +363,72 @@ def update_metadata_parameters(app_settings: ApplicationSettings, parameters: st conn.commit() conn.close() -def verwijder_tabellen(): + +def remove_tables( + app_settings: ApplicationSettings, table_list: list[str] = [] +): + """ + Verwijder de tabellen uit de geopackage en de metadata zodat deze oopnieuw + kunnen worden ingeladen. Als de lijst leeg is worden alle tabellen met + ruimtelijke invoer verwijderd. + + :param app_settings: Object met applicatie instellingen. + :param table_list: Lijst met tabellen om te verwijderen, defaults to [] + """ # Voor vervangen, nieuwe scenarios of verwijderen van parameters. - pass + 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(", ") + parameters.append("intredelijn") + layers: list[str] = fiona.listlayers(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(): """ 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" - ] + """ + 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 aanpasingen in een keer te doen." - ), + ), choices=choices_list, default=choices_list[0], ).execute() - + match choice: case "Andere aanpassing uitvoeren": return - + case "Applicatie afsluiten": - sys.exit("Applicatie is afgesloten.") \ No newline at end of file + sys.exit("Applicatie is afgesloten.") diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 9546ba4b..8481e188 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -56,7 +56,6 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) if not added_parameters(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) - # TODO Vincent: batch invoer bestand mogelijk maken if not check_batch_input(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) @@ -104,7 +103,7 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) print("\nPARAMETER INVOER") - # TODO Vincent: Optie om GIS invoer te vervangen. + # TODO Vincent: Optie om GIS invoer te vervangen/aanpassen. # TODO Vincent: Check validation correct blijft werken. # TODO Vincent: verwijder traject waardes als gis_join al waardes heeft. # Misschien checken of de orde van overschrijven wel logisch is? diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py index 25b237b9..36492db1 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py @@ -9,6 +9,7 @@ import geopandas as gpd import pandas as pd +import numpy as np from .base_couple import BaseCouple @@ -54,11 +55,11 @@ def _create_df_hrd(self, join_df: pd.DataFrame) -> pd.DataFrame: df["scope"] = "uittredepunt" df["ondergrondscenario_naam"] = "" df["distribution_type"] = "cdf_curve" - df["mean"] = "" - df["variation"] = "" - df["deviation"] = "" - df["minimum"] = "" - df["maximum"] = "" + 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"] = "" diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py index 6f0e6cef..14b5b2ff 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py @@ -131,7 +131,7 @@ def _join_to_line(self, gdf: gpd.GeoDataFrame, scenario: str): :param gdf: GeoDataFrame met de ruimtelijke invoer. :param scenario: Ondergrondscenario_naam voor in de dataframe. Kan "" zijn. """ - # TODO filter mogelijk dubble waarden + # TODO Vincent: filter mogelijk dubble waarden join_df = self.gdf_exit_points.sjoin_nearest(gdf, how="left") df_to_add = self._create_df(join_df, scenario) diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py index 1b4bfa7f..38bdf8bd 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py @@ -68,9 +68,9 @@ def request_scenarios(app_settings: ApplicationSettings): sql_insert = "INSERT INTO geoprob_pipe_metadata (metadata_type, metadata_value) VALUES (?, ?)" with conn: # transaction - cur = conn.execute(sql_update, (scenarios, "ruimtelijke_scenarios")) # type:ignore + cur = conn.execute(sql_update, (scenarios, "ruimtelijke_scenarios")) if cur.rowcount == 0: - conn.execute(sql_insert, ("ruimtelijke_scenarios", scenarios)) # type:ignore + conn.execute(sql_insert, ("ruimtelijke_scenarios", scenarios)) conn.commit() conn.close() diff --git a/geoprob_pipe/cmd_app/utils/batch_input.py b/geoprob_pipe/cmd_app/utils/batch_input.py index acc3c898..c1aca91b 100644 --- a/geoprob_pipe/cmd_app/utils/batch_input.py +++ b/geoprob_pipe/cmd_app/utils/batch_input.py @@ -2,31 +2,35 @@ 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" + "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?"), + message=( + "Wil je de gis-lagen handmatig invoeren of via een batch_input.ini bestand?" + ), choices=choices_list, - default=choices_list[0] + default=choices_list[0], ).execute() - + match choice: case "Nee, handmatig invoeren": return @@ -36,7 +40,30 @@ def batch_inquiry(app_settings: ApplicationSettings): case "Maak het `batch_input.ini` bestand aan": batch_config_writer(app_settings) app_settings.batch_input = True + ready_inquiry() + return + + +# TODO Vincent: Toelichting voor input optie? +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], + ) + 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): @@ -44,7 +71,7 @@ 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( @@ -55,41 +82,38 @@ def batch_config_writer(app_settings: ApplicationSettings): conn.close() config = configparser.ConfigParser() - + config["vakindeling"] = { "filepath": "", "database_layer": "", "vak_naam_kolom": "", - "vak_id_kolom": "" + "vak_id_kolom": "", } - + config["uittredepunten"] = { "filepath": "", "database_layer": "", - "mv_exit_kolom": "" + "mv_exit_kolom": "", } - + config["binnenteenlijn"] = { "filepath": "", "database_layer": "", } - + config["buitenteenlijn"] = { "filepath": "", "database_layer": "", } - + config["intredelijn"] = { "filepath": "", "database_layer": "", } - if not parameters == ['']: + if not parameters == [""]: for parameter in parameters: - config[parameter] = { - "filepath": "", - "database_layer": "" - } - + config[parameter] = {"filepath": "", "database_layer": ""} + with open(f"{app_settings.workspace_dir}/batch_input.ini", "w") as f: config.write(f) From 2dfdc598e8d33eb1be5c8b567e85f6d010df102c Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Fri, 22 May 2026 12:57:01 +0200 Subject: [PATCH 16/53] clean up while loops and placeholders --- .../cmd_app/comparisons/start_comparison.py | 20 ++--- geoprob_pipe/cmd_app/general/project.py | 41 +++++----- .../cmd_app/general/traject_parameters.py | 80 +++++++++---------- .../parameter_input/added_input_parameters.py | 6 +- .../input_parameter_figures.py | 10 +-- geoprob_pipe/cmd_app/questionnaire.py | 2 - geoprob_pipe/cmd_app/run_calculations/run.py | 10 +-- .../spatial_layers/added_dijktraject.py | 45 +++++------ .../spatial_layers/hrd/import_from_hrd.py | 14 ++-- .../hrd/import_from_other_geopackage.py | 7 +- .../uittredepunten/alg_walking_circles.py | 9 ++- geoprob_pipe/utils/df_validation/dataframe.py | 6 +- 12 files changed, 113 insertions(+), 137 deletions(-) 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/project.py b/geoprob_pipe/cmd_app/general/project.py index f762315e..64b2f4e9 100644 --- a/geoprob_pipe/cmd_app/general/project.py +++ b/geoprob_pipe/cmd_app/general/project.py @@ -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() @@ -156,31 +156,30 @@ def specify_path_to_existing_project(app_settings: ApplicationSettings): 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 = Path(workspace_dir) @@ -189,9 +188,7 @@ def specify_dir_for_new_project(app_settings: ApplicationSettings): 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) diff --git a/geoprob_pipe/cmd_app/general/traject_parameters.py b/geoprob_pipe/cmd_app/general/traject_parameters.py index 6a36c879..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, metadata_value) 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) @@ -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 776deb8f..d2de5825 100644 --- a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py +++ b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py @@ -218,9 +218,7 @@ def export_input_tables_of_db(app_settings: ApplicationSettings, tables: InputPa def import_input_tables(geopackage_filepath: str) -> InputParameterTables: - - 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() @@ -235,7 +233,7 @@ def import_input_tables(geopackage_filepath: str) -> InputParameterTables: 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) # type:ignore print(f"{BColors.UNDERLINE}Tabellen zijn nu geïmporteerd.{BColors.ENDC}") 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 6a691c9c..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 diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 8481e188..040402d7 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -103,8 +103,6 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) print("\nPARAMETER INVOER") - # TODO Vincent: Optie om GIS invoer te vervangen/aanpassen. - # TODO Vincent: Check validation correct blijft werken. # TODO Vincent: verwijder traject waardes als gis_join al waardes heeft. # Misschien checken of de orde van overschrijven wel logisch is? # Excel over gis maar wel gis-uittredepunt over excel-traject? 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_layers/added_dijktraject.py b/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py index a25233ef..af304a8a 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py @@ -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,9 +80,7 @@ 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 @@ -104,7 +102,7 @@ def specify_geodatabase_layer(app_settings: ApplicationSettings, filepath: str): 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.*") @@ -113,9 +111,7 @@ 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 @@ -131,22 +127,22 @@ def specify_geopackage_layer(app_settings: ApplicationSettings, filepath: str): 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 @@ -167,7 +163,7 @@ def specify_column_with_trajectory_name(app_settings: ApplicationSettings, gdf: 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) @@ -184,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": @@ -208,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]] @@ -217,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/hrd/import_from_hrd.py b/geoprob_pipe/cmd_app/spatial_layers/hrd/import_from_hrd.py index 3545b31b..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 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 f98cfaee..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 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 76977268..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 @@ -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/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 = [] From c783c0b57a5dc1acf8e251aba63731f1d2e1b1f4 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 26 May 2026 08:48:16 +0200 Subject: [PATCH 17/53] bug fixes --- .../cmd_app/spatial_joins/couple_objects/base_couple.py | 4 ++-- geoprob_pipe/results/assemblage/functions.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py index 3d0cdc49..982c2e97 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py @@ -34,12 +34,12 @@ def _create_df(self, join_df: pd.DataFrame, scenario: str) -> pd.DataFrame: df["parameter"] = self.param df["scope"] = "uittredepunt" df["ondergrondscenario_naam"] = scenario - df["distribution_type"] = join_df.get(f"{self.param}_dist", "") + 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", "") + df["maximum"] = join_df.get(f"{self.param}_max", np.nan) df["fragility_values_ref"] = "" df["bronnen"] = "" df["opmerking"] = "" diff --git a/geoprob_pipe/results/assemblage/functions.py b/geoprob_pipe/results/assemblage/functions.py index 3c0f08b6..3530c7c8 100644 --- a/geoprob_pipe/results/assemblage/functions.py +++ b/geoprob_pipe/results/assemblage/functions.py @@ -111,7 +111,8 @@ 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, @@ -126,8 +127,7 @@ def window_collect(window_size: float, point_list: list[UittredepuntElement], sum_pf, max_pf = combine_series(df_bin.to_list()) window_elements: List[WindowElement] = [] - if m_tot not in bins_window: - bins_window.append(m_tot) # add end of final window + for i in range(len(bins_window)-1): window_elements.append(WindowElement( m_van=bins_window[i], From dbe02d9860e7a29ffdc0fc8c2d79ebd6801b28ce Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 26 May 2026 11:27:43 +0200 Subject: [PATCH 18/53] bugfix polderpeil en maps --- geoprob_pipe/cmd_app/questionnaire.py | 6 +- .../couple_objects/shape_couple.py | 10 +- .../added_ruimtelijke_invoer.py | 1 + .../cmd_app/spatial_layers/base_inquiry.py | 45 +++++--- geoprob_pipe/visualizations/maps/betamap.py | 101 ++++++++++-------- 5 files changed, 93 insertions(+), 70 deletions(-) diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 040402d7..460a8c48 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -86,9 +86,6 @@ def questionnaire(app_settings: ApplicationSettings): ) # AHN may be optional print("\nGEOGRAFISCHE KOPPELINGEN") - # TODO Vincent: maak coupleling for raster - if not coupled_parameters_to_uittredepunten(app_settings=app_settings): - sys.exit(EARLY_EXIT_MESSAGE) 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): @@ -101,6 +98,9 @@ def questionnaire(app_settings: ApplicationSettings): app_settings=app_settings ): sys.exit(EARLY_EXIT_MESSAGE) + # TODO Vincent: maak coupleling for raster + if not coupled_parameters_to_uittredepunten(app_settings=app_settings): + sys.exit(EARLY_EXIT_MESSAGE) print("\nPARAMETER INVOER") # TODO Vincent: verwijder traject waardes als gis_join al waardes heeft. diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py index 14b5b2ff..a1e847b5 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py @@ -4,7 +4,6 @@ from typing import TYPE_CHECKING import geopandas as gpd -from shapely.geometry import LineString, MultiLineString, MultiPolygon, Polygon from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS from .base_couple import BaseCouple @@ -105,14 +104,15 @@ def _check_shape(self, gdf: gpd.GeoDataFrame, scenario: str = ""): :raises KeyError: Polygon niet geaccepteerd bij deze parameter. :raises ImportError: De laag bestaat uit verschillende geometrie types. """ - if (gdf.geom_types == (LineString or MultiLineString)).all(): + + 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_types == (Polygon or MultiPolygon)).all(): + elif (gdf.geom_type.isin(["Polygon", "MultiPolygon"])).all(): if "polygon" in LIST_PARAMS[self.param]["shape"]: self._join_to_polygon(gdf, scenario) else: @@ -144,8 +144,8 @@ def _join_to_polygon(self, gdf: gpd.GeoDataFrame, scenario: str): :param gdf: GeoDataFrame met de ruimtelijke invoer. :param scenario: Ondergrondscenario_naam voor in de dataframe. Kan "" zijn. """ - join_df = self.gdf_exit_points.sjoin(gdf, how="left") - df_to_add = self._create_df(join_df, scenario) + join_gdf = self.gdf_exit_points.sjoin(gdf, how="left") + df_to_add = self._create_df(join_gdf, scenario) self._upsert_to_gpkg(df_to_add) diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py index 47b37409..08485a49 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py @@ -59,6 +59,7 @@ def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool: app_settings=app_settings, param=f"{parameter}", specific_shape=LIST_PARAMS[parameter]["shape"], + include_value=True ) inquiry.request_filepath() diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 90f6b00f..86035185 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -273,6 +273,7 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: :rtype: bool """ self.suffix_list = ["mean", "dist", "var", "dev", "min", "max"] + if self.include_value and self.scenarios == "": # Case: Alleen suffix, alle kolomen worden met de geometrie weggeschreven. return self._add_with_suffix(gdf) @@ -282,7 +283,10 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: # geometrieën weggeschreven. # Of verschillende geometerieën per scenario column_list = gdf.columns.to_list() - if True in [len(x.split("_")) == 3 for x in column_list]: + if True in [ + len(x.split("_")) == 3 and self.param in x.split("_") + for x in column_list + ]: return self._add_with_affixes(gdf) else: return self._add_seperate_with_suffix(gdf) @@ -515,20 +519,21 @@ def _add_seperate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: :return: bool voor valid_input in while-loop """ 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_filtered = gdf[mask][["geometry"]] + for scenario in self.scenarios + [ + None + ]: # als er geen scenario zijn opgegeven in de kolom + if scenario is None: + mask = gdf["ondergrondscenario"].isna() + else: + mask = gdf["ondergrondscenario"] == scenario - if len(gdf_filtered) == 0: - print( - BColors.WARNING, - f"Geen geometrieën gevonden met de ondergrondscenarionaam: {scenario}", - BColors.ENDC, - ) + if not mask.any(): continue + add_list = [ f"{self.param}_{x}" for x in self.suffix_list @@ -538,12 +543,20 @@ def _add_seperate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: if not self._distribution_check(column_list, add_list, gdf): return False - gdf_to_add = gdf_filtered[["geometry", add_list]] + gdf_to_add = gdf.loc[mask, ["geometry"] + add_list] - gdf_to_add.to_file( - self.app_settings.geopackage_filepath, - layer=f"{self.param}_{scenario}", - driver="GPKG", - ) + 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/visualizations/maps/betamap.py b/geoprob_pipe/visualizations/maps/betamap.py index f5bd9291..1f20a377 100644 --- a/geoprob_pipe/visualizations/maps/betamap.py +++ b/geoprob_pipe/visualizations/maps/betamap.py @@ -1,9 +1,12 @@ 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 @@ -13,50 +16,56 @@ 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 = [x for x in gpkg_layers if x.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 - 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) + else: + print("Skipping unsupported geometry:", geom.geom_type) return fig From 65721a25d903a4bc407833a245819cc59b0d7efc Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 26 May 2026 12:08:08 +0200 Subject: [PATCH 19/53] batch inquiry flag and explanation in .ini --- geoprob_pipe/cmd_app/cmd.py | 3 +- .../parameter_input/added_input_parameters.py | 2 + .../update_ruimtelijke_invoer.py | 56 +++++++++---------- .../spatial_layers/check_batch_input.py | 6 +- geoprob_pipe/cmd_app/utils/batch_input.py | 46 ++++++++++++++- 5 files changed, 80 insertions(+), 33 deletions(-) diff --git a/geoprob_pipe/cmd_app/cmd.py b/geoprob_pipe/cmd_app/cmd.py index 8e4508a6..ec8c7e8b 100644 --- a/geoprob_pipe/cmd_app/cmd.py +++ b/geoprob_pipe/cmd_app/cmd.py @@ -27,7 +27,8 @@ def __init__(self): self.to_run = "all" # -> or vakken:1,2,3,4,5 self.debug: bool = os.getenv("GEOPROB_DEBUG") == "1" - self.batch_input: bool = False # Placeholder for batch input + # Flags + self.batch_input: bool = False # Flag for batch input @property def geopackage_filepath(self) -> str: 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 d2de5825..4c823f94 100644 --- a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py +++ b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py @@ -16,6 +16,7 @@ from .input_parameter_figures import InputParameterFigures from .input_parameter_tables import InputParameterTables from .update_ruimtelijke_invoer import inquire_spatial_update +from geoprob_pipe.cmd_app.utils.batch_input import update_batch_metadata if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -316,5 +317,6 @@ def process_import_input(app_settings: ApplicationSettings): def added_input_parameter_data(app_settings: ApplicationSettings) -> bool: + update_batch_metadata(app_settings=app_settings, value=False) # Batch inquiry process_input_exist_in_db(app_settings=app_settings) 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 index 31bdff18..7f5a1dcb 100644 --- a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -84,12 +84,12 @@ def inquire_replace_layers(app_settings: ApplicationSettings): while True: parameter_input: str = InputPrompt( message=f""" - De volgende parameters zijn nu aangemerkt voor rumtelijke 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. - """ +De volgende parameters zijn nu aangemerkt voor rumtelijke 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 == "": @@ -144,13 +144,13 @@ def add_parameters(app_settings: ApplicationSettings): while True: parameter_input: str = InputPrompt( message=f""" - De volgende parameters zijn nu aangemerkt voor rumtelijke 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. - """ +De volgende parameters zijn nu aangemerkt voor rumtelijke 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 == "": @@ -201,11 +201,11 @@ def remove_parameters(app_settings: ApplicationSettings): while True: parameter_input: str = InputPrompt( message=f""" - De volgende parameters zijn nu aangemerkt voor rumtelijke 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. - """ +De volgende parameters zijn nu aangemerkt voor rumtelijke 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 == "": @@ -258,11 +258,11 @@ def add_scenarios(app_settings: ApplicationSettings): 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. - """ +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 == "": @@ -302,11 +302,11 @@ def remove_scenarios(app_settings: ApplicationSettings): 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. - """ +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 == "": diff --git a/geoprob_pipe/cmd_app/spatial_layers/check_batch_input.py b/geoprob_pipe/cmd_app/spatial_layers/check_batch_input.py index 603c44f4..71eeb430 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/check_batch_input.py +++ b/geoprob_pipe/cmd_app/spatial_layers/check_batch_input.py @@ -1,13 +1,13 @@ from __future__ import annotations from typing import TYPE_CHECKING -from geoprob_pipe.cmd_app.utils.batch_input import batch_inquiry +from geoprob_pipe.cmd_app.utils.batch_input import batch_inquiry, read_metadata if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings -# TODO Vincent: Voeg een check aan de metadata toe of dit gevraagd moet worden. -# Eerste keer en als de input veranderd moet worden. 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/utils/batch_input.py b/geoprob_pipe/cmd_app/utils/batch_input.py index c1aca91b..f215fba3 100644 --- a/geoprob_pipe/cmd_app/utils/batch_input.py +++ b/geoprob_pipe/cmd_app/utils/batch_input.py @@ -33,6 +33,7 @@ def batch_inquiry(app_settings: ApplicationSettings): 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 @@ -58,7 +59,7 @@ def ready_inquiry(): 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 @@ -116,4 +117,47 @@ def batch_config_writer(app_settings: ApplicationSettings): 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(row[0]) \ No newline at end of file From 98b8327c8dd571773efda758cb9f8cbbc2ab3095 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 26 May 2026 14:39:15 +0200 Subject: [PATCH 20/53] shape couple bugfix punten buiten de polygon, geherordend exand_df --- .../parameter_input/added_input_parameters.py | 3 +- .../parameter_input/expand_input_tables.py | 47 +++++++++++++------ .../update_ruimtelijke_invoer.py | 7 +-- geoprob_pipe/cmd_app/questionnaire.py | 2 +- .../couple_objects/base_couple.py | 2 +- .../couple_objects/shape_couple.py | 22 ++++++--- .../coupled_distance_to_exit_points.py | 4 +- .../cmd_app/spatial_joins/coupled_hrd.py | 3 +- .../spatial_joins/coupled_parameters.py | 2 +- .../added_ruimtelijke_invoer.py | 20 +------- .../cmd_app/spatial_layers/base_inquiry.py | 1 + geoprob_pipe/cmd_app/utils/batch_input.py | 4 +- 12 files changed, 65 insertions(+), 52 deletions(-) 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 4c823f94..80167044 100644 --- a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py +++ b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py @@ -317,6 +317,7 @@ def process_import_input(app_settings: ApplicationSettings): def added_input_parameter_data(app_settings: ApplicationSettings) -> bool: - update_batch_metadata(app_settings=app_settings, value=False) # Batch inquiry + # Batch inquiry flag is set to False if input is succesfull. + 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 f8121f1c..50e39902 100644 --- a/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py +++ b/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py @@ -267,21 +267,21 @@ def _gather_required_input_parameters(geopackage_filepath: str) -> List[str]: # return ["mv_exit", "gamma_sat_deklaag"] # TODO # return ["gamma_sat_deklaag"] # TODO - +# TODO Vincent: fix falende overschijving voor polderpeil in expanded excel 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 +291,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 +344,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 +359,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/update_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py index 7f5a1dcb..1bdeb233 100644 --- a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -10,12 +10,12 @@ 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 -# TODO Vincent: Testen met invoer. def inquire_spatial_update( app_settings: ApplicationSettings, ): @@ -368,13 +368,14 @@ def remove_tables( app_settings: ApplicationSettings, table_list: list[str] = [] ): """ - Verwijder de tabellen uit de geopackage en de metadata zodat deze oopnieuw + 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 app_settings: Object met applicatie instellingen. :param table_list: Lijst met tabellen om te verwijderen, defaults to [] - """ + """ + update_batch_metadata(app_settings=app_settings, value=True) # Voor vervangen, nieuwe scenarios of verwijderen van parameters. conn = sqlite3.connect(app_settings.geopackage_filepath) cursor = conn.cursor() diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 460a8c48..196729c0 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -98,7 +98,7 @@ def questionnaire(app_settings: ApplicationSettings): app_settings=app_settings ): sys.exit(EARLY_EXIT_MESSAGE) - # TODO Vincent: maak coupleling for raster + # TODO Later Should: make coupleling for raster if import is added. if not coupled_parameters_to_uittredepunten(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py index 982c2e97..8148e533 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py @@ -34,7 +34,7 @@ def _create_df(self, join_df: pd.DataFrame, scenario: str) -> pd.DataFrame: df["parameter"] = self.param df["scope"] = "uittredepunt" df["ondergrondscenario_naam"] = scenario - df["distribution_type"] = join_df.get(f"{self.param}_dist", "deterministic") + df["distribution_type"] = join_df.get(f"{self.param}_dist", "") 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) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py index a1e847b5..62264df9 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py @@ -6,6 +6,8 @@ import geopandas as gpd from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS +from geoprob_pipe.utils.validation_messages import BColors + from .base_couple import BaseCouple if TYPE_CHECKING: @@ -131,9 +133,8 @@ def _join_to_line(self, gdf: gpd.GeoDataFrame, scenario: str): :param gdf: GeoDataFrame met de ruimtelijke invoer. :param scenario: Ondergrondscenario_naam voor in de dataframe. Kan "" zijn. """ - # TODO Vincent: filter mogelijk dubble waarden - join_df = self.gdf_exit_points.sjoin_nearest(gdf, how="left") - df_to_add = self._create_df(join_df, scenario) + 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) @@ -145,12 +146,19 @@ def _join_to_polygon(self, gdf: gpd.GeoDataFrame, scenario: str): :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()] + print(join_gdf) df_to_add = self._create_df(join_gdf, scenario) self._upsert_to_gpkg(df_to_add) - # TODO Vincent: Add option for rasters + # TODO Later Should: Add option for raster import and coupleling. def _join_to_raster(self): - pass - - + raise NotImplementedError("Toevoegen van parameters via raster is nog niet moegelijk.") 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 index c05dda1b..e60b1177 100644 --- 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 @@ -17,13 +17,13 @@ if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings -# TODO Vincent: Check of deze al in de tabel staan. + def coupled_distances_to_uittredepunten( app_settings: ApplicationSettings, ) -> bool: """ Bepaal de afstanden tussen de uittredepunten en de intrede, binnenteen en - buitenteenlijen. + buitenteenlijnen. Als deze er al in staan worden ze overschreven. :param app_settings: Object met de insellingen van de applicatie """ diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py index 4c7f12c3..e4f63042 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py +++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py @@ -12,10 +12,11 @@ if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings -# TODO Vincent: Check of deze al in de tabel staan. + 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 insellingen van de applicatie :return: _description_ diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py index e523d1b6..572f0542 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py @@ -9,7 +9,7 @@ if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings -# TODO Vincent: Check of deze al in de tabel staan. + def coupled_parameters_to_uittredepunten( app_settings: ApplicationSettings, ) -> bool: diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py index 08485a49..340df599 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py @@ -20,13 +20,8 @@ def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool: ("ruimtelijke_parameters",), ) parameters: list[str] = cursor.fetchone()[0].split(", ") - cursor.execute( - "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type = ?", - ("ruimtelijke_scenarios",), - ) - scenarios: list[str] = cursor.fetchone()[0].split(", ") conn.close() - layers = fiona.listlayers(app_settings.geopackage_filepath) + list_layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) if parameters == ['']: # De split maakt één lege string als de uit de metadata gelezen string leeg is. print( BColors.OKBLUE, @@ -36,18 +31,7 @@ def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool: return True for parameter in parameters: - if scenarios == ['']: # De split maakt één lege string als de uit de metadata gelezen string leeg is. - if parameter in layers: - print( - BColors.OKBLUE, - f"✔ {parameter} al toegevoegd.", - BColors.ENDC, - ) - return True - - else: - for scenario in scenarios: - if f"{parameter}_{scenario}" in layers: + if any(parameter in layer.split("_")[0] for layer in list_layers): print( BColors.OKBLUE, f"✔ {parameter} al toegevoegd.", diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 86035185..8c28ef30 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -197,6 +197,7 @@ def _import_from_db(self, filepath: str) -> gpd.GeoDataFrame: 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 diff --git a/geoprob_pipe/cmd_app/utils/batch_input.py b/geoprob_pipe/cmd_app/utils/batch_input.py index f215fba3..f67712c8 100644 --- a/geoprob_pipe/cmd_app/utils/batch_input.py +++ b/geoprob_pipe/cmd_app/utils/batch_input.py @@ -45,7 +45,6 @@ def batch_inquiry(app_settings: ApplicationSettings): return -# TODO Vincent: Toelichting voor input optie? def ready_inquiry(): """ Keuzemenu als wacht periode voor het invullen van batch_input.ini. @@ -156,8 +155,7 @@ def read_metadata(app_settings: ApplicationSettings): ) row = cursor.fetchone() conn.close() - if row is None: return True - return bool(row[0]) \ No newline at end of file + return bool(int(row[0])) \ No newline at end of file From 7fa8ede86b94b3a24baabfdfc1145ebdb225de02 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 26 May 2026 14:41:04 +0200 Subject: [PATCH 21/53] update todo --- geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py | 1 - geoprob_pipe/cmd_app/questionnaire.py | 4 +--- .../cmd_app/spatial_joins/couple_objects/shape_couple.py | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) 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 50e39902..e3908993 100644 --- a/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py +++ b/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py @@ -267,7 +267,6 @@ def _gather_required_input_parameters(geopackage_filepath: str) -> List[str]: # return ["mv_exit", "gamma_sat_deklaag"] # TODO # return ["gamma_sat_deklaag"] # TODO -# TODO Vincent: fix falende overschijving voor polderpeil in expanded excel def _expand( df_parameter_invoer_combined: DataFrame, df_identifiers: DataFrame, geopackage_filepath: str ) -> Dict[str, DataFrame]: diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 196729c0..012abbc2 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -103,9 +103,7 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) print("\nPARAMETER INVOER") - # TODO Vincent: verwijder traject waardes als gis_join al waardes heeft. - # Misschien checken of de orde van overschrijven wel logisch is? - # Excel over gis maar wel gis-uittredepunt over excel-traject? + # TODO Vincent: Vraag Chris waar de traject defaults automatisch verwijderd worden if not added_input_parameter_data(app_settings=app_settings): sys.exit(EARLY_EXIT_MESSAGE) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py index 62264df9..6fb066e0 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py @@ -154,7 +154,6 @@ def _join_to_polygon(self, gdf: gpd.GeoDataFrame, scenario: str): BColors.ENDC ) join_gdf = join_gdf[join_gdf.index_right.notna()] - print(join_gdf) df_to_add = self._create_df(join_gdf, scenario) self._upsert_to_gpkg(df_to_add) From 2d84cf7635c412a8b4f33bc04b5367587a420e82 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 27 May 2026 08:53:24 +0200 Subject: [PATCH 22/53] spellcheck --- .../parameter_input/added_input_parameters.py | 2 +- .../update_ruimtelijke_invoer.py | 14 +++++----- geoprob_pipe/cmd_app/questionnaire.py | 2 +- .../couple_objects/base_couple.py | 2 +- .../couple_objects/hrd_couple.py | 4 +-- .../couple_objects/shape_couple.py | 8 +++--- .../coupled_distance_to_exit_points.py | 2 +- .../cmd_app/spatial_joins/coupled_hrd.py | 2 +- .../cmd_app/spatial_joins/coupled_mv_exit.py | 2 +- .../spatial_layers/added_parameters.py | 2 +- .../cmd_app/spatial_layers/base_inquiry.py | 28 +++++++++---------- 11 files changed, 34 insertions(+), 34 deletions(-) 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 80167044..b83a9efb 100644 --- a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py +++ b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py @@ -317,7 +317,7 @@ def process_import_input(app_settings: ApplicationSettings): def added_input_parameter_data(app_settings: ApplicationSettings) -> bool: - # Batch inquiry flag is set to False if input is succesfull. + # 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/update_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py index 1bdeb233..b31b10e6 100644 --- a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -22,7 +22,7 @@ def inquire_spatial_update( choices_list = [ "Vervang ingevoerde lagen", "Voeg parameters toe voor ruimtelijke invoer", - "Verwijder parameters voor ruimtlijke invoer", + "Verwijder parameters voor ruimtelijke invoer", "Voeg scenarios toe voor ruimtelijke invoer", "Verwijder scenarios voor ruimtelijke invoer", "Ga terug naar het parameter invoer menu", @@ -43,7 +43,7 @@ def inquire_spatial_update( add_parameters(app_settings) continue - case "Verwijder parameters voor ruimtlijke invoer": + case "Verwijder parameters voor ruimtelijke invoer": remove_parameters(app_settings) continue @@ -84,7 +84,7 @@ def inquire_replace_layers(app_settings: ApplicationSettings): while True: parameter_input: str = InputPrompt( message=f""" -De volgende parameters zijn nu aangemerkt voor rumtelijke invoer: +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. @@ -144,7 +144,7 @@ def add_parameters(app_settings: ApplicationSettings): while True: parameter_input: str = InputPrompt( message=f""" -De volgende parameters zijn nu aangemerkt voor rumtelijke invoer: +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]} @@ -166,7 +166,7 @@ def add_parameters(app_settings: ApplicationSettings): if not valid_input: print( BColors.OKBLUE, - f"Geen parameterss toegevoegd. '{parameter_input}' bevat een ongeldige parameter.", + f"Geen parameters toegevoegd. '{parameter_input}' bevat een ongeldige parameter.", BColors.ENDC, ) continue @@ -201,7 +201,7 @@ def remove_parameters(app_settings: ApplicationSettings): while True: parameter_input: str = InputPrompt( message=f""" -De volgende parameters zijn nu aangemerkt voor rumtelijke invoer: +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. @@ -421,7 +421,7 @@ def completed_update(): choice = ListPrompt( message=( "Om de aanpassingen te verwerken moet de applicatie opnieuw worden gestart. " - "Het is mogelijk om meerdere aanpasingen in een keer te doen." + "Het is mogelijk om meerdere aanpassingen in een keer te doen." ), choices=choices_list, default=choices_list[0], diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index 012abbc2..d4f94828 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -98,7 +98,7 @@ def questionnaire(app_settings: ApplicationSettings): app_settings=app_settings ): sys.exit(EARLY_EXIT_MESSAGE) - # TODO Later Should: make coupleling for raster if import is added. + # 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) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py index 8148e533..fad433f8 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py @@ -23,7 +23,7 @@ class BaseCouple: def _create_df(self, join_df: pd.DataFrame, scenario: str) -> pd.DataFrame: """ - Maak de dataframe die moet worden toegevoedg aan de geopackage. + Maak de dataframe die moet worden toegevoegd aan de geopackage. :param join_df: DataFrame met de data uit de join. :param scenario: Ondergrondscenario_naam voor in de dataframe. Kan "" zijn. diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py index 36492db1..9408b23d 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py @@ -1,6 +1,6 @@ """ Class voor het koppelen van de HRD-locaties aan de uittredepunten. -Versimplende versie van de ShapeCouple class. +Versimpelde versie van de ShapeCouple class. """ from __future__ import annotations @@ -20,7 +20,7 @@ class HRDCouple(BaseCouple): def __init__(self, app_settings: ApplicationSettings) -> None: """ - Class voor het koppelen van de hrd locatie namen aan de uitredepunten. + Class voor het koppelen van de hrd locatie namen aan de uittredepunten. :param app_settings: Object met de settings van de applicatie. """ diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py index 6fb066e0..26fa7427 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py @@ -21,7 +21,7 @@ def __init__(self, app_settings: ApplicationSettings, param: str) -> None: De gekoppelde waarden worden weggeschreven in de tabel 'gis_join_parameter_invoer'. :param app_settings: `ApplicationSettings` object. - :param param: Parameter die gekoppeled moet worden. + :param param: Parameter die gekoppeld moet worden. """ self.app_settings = app_settings self.param = param @@ -74,7 +74,7 @@ def couple_exit_points(self): def _add_single_layer(self): """ - Voeg een laag toe via koppeling, met de uitredepunten als er geen + 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( @@ -158,6 +158,6 @@ def _join_to_polygon(self, gdf: gpd.GeoDataFrame, scenario: str): self._upsert_to_gpkg(df_to_add) - # TODO Later Should: Add option for raster import and coupleling. + # 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 moegelijk.") + 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 index e60b1177..fe0899ae 100644 --- 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 @@ -25,7 +25,7 @@ def coupled_distances_to_uittredepunten( 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 insellingen van de applicatie + :param app_settings: Object met de instellingen van de applicatie """ # Read uittredepunten diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py index e4f63042..1f55a42d 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py +++ b/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py @@ -18,7 +18,7 @@ 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 insellingen van de applicatie + :param ApplicationSettings app_settings: Object met de instellingen van de applicatie :return: _description_ :rtype: bool """ diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_mv_exit.py b/geoprob_pipe/cmd_app/spatial_joins/coupled_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/coupled_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_layers/added_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py index 53f5045c..22171f91 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py @@ -35,7 +35,7 @@ def added_parameters(app_settings: ApplicationSettings): def request_parameters(app_settings: ApplicationSettings): """ Method voor het opvragen van de lijst met parameters waarvoor ruimtelijke - invoer gewenst is. Er wordt gecheckd of deze paramerters ondersteund worden + invoer gewenst is. Er wordt gecheckt of deze parameters ondersteund worden en of deze in het gekozen model zitten. :param app_settings: `ApplicationSettings` object. diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 8c28ef30..236250a2 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -8,7 +8,7 @@ -WEL ruimtelijke scenarios en GEEN ruimtelijke data invoer -WEL ruimtelijke scenarios en WEL ruimtelijke data invoer -Daarnaast is er nog onderschijd in invoer met verschillende shapes per scenario +Daarnaast is er nog onderscheid in invoer met verschillende shapes per scenario of twee sets met invoer data. """ @@ -41,7 +41,7 @@ def __init__( single_geometry: bool = False, ) -> None: """ - Class voor de opvraag van de ruimteljke invoer van de parameters. + 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 @@ -125,7 +125,7 @@ def _import_data(self, filepath: str) -> gpd.GeoDataFrame: """ Helper method voor het importeren van de data. - :param filepath: Bestandspad van de shapfile of database met de GIS lagen. + :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: @@ -207,9 +207,9 @@ def _import_from_db(self, filepath: str) -> gpd.GeoDataFrame: def _import_from_shp(self, filepath: str) -> gpd.GeoDataFrame: """ - Helper method voor het importern vanuit een shapefile. + Helper method voor het importeren vanuit een shapefile. - :param filepath: Bestandspad van de shapfile. + :param filepath: Bestandspad van de shapefile. :return: GeoDataFrame met de uitgelezen data. """ @@ -276,13 +276,13 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: self.suffix_list = ["mean", "dist", "var", "dev", "min", "max"] if self.include_value and self.scenarios == "": - # Case: Alleen suffix, alle kolomen worden met de geometrie weggeschreven. + # 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 kolomen met de + # Case: beide affixes, per scenario worden alle kolommen met de # geometrieën weggeschreven. - # Of verschillende geometerieën per scenario + # Of verschillende geometrieën per scenario column_list = gdf.columns.to_list() if True in [ len(x.split("_")) == 3 and self.param in x.split("_") @@ -290,7 +290,7 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: ]: return self._add_with_affixes(gdf) else: - return self._add_seperate_with_suffix(gdf) + return self._add_separate_with_suffix(gdf) elif ( not self.include_value @@ -312,7 +312,7 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: return True elif not self.include_value and self.scenarios != "": - # Case: Alleen losse shapes, de geometriën worden per scenario geschreven. + # Case: Alleen losse shapes, de geometrieën worden per scenario geschreven. return self._add_with_separate_geometry(gdf) else: @@ -333,7 +333,7 @@ def _scenario_check(self, column_list: list[str]): print( BColors.WARNING, "Geen kolom met de naam 'ondergrondscenario' gevonden.\n", - "De volgende kolommen zijn gevonde:\n", + "De volgende kolommen zijn gevonden:\n", f"{column_list}", BColors.ENDC, ) @@ -349,7 +349,7 @@ def _distribution_check( gdf: gpd.GeoDataFrame, ) -> bool: """ - Check of de kolomen de juiste inputs hebben voor de gekozen distributie. + 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. @@ -368,7 +368,7 @@ def _distribution_check( return False - # Check var or std if not determinstic. + # Check var or std if not deterministic. for _, row in gdf.iterrows(): if row[f"{self.param}_dist"] == "deterministic": continue # Overslaan @@ -512,7 +512,7 @@ def _add_with_affixes(self, gdf: gpd.GeoDataFrame) -> bool: return True - def _add_seperate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: + def _add_separate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: """ Voeg de lagen toe los van elkaar per scenario. From 4054cab8931601962987150d832721a551c6e86d Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 27 May 2026 11:53:29 +0200 Subject: [PATCH 23/53] bugfix --- .../cmd_app/spatial_joins/couple_objects/base_couple.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py index fad433f8..b9067ff6 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py @@ -34,7 +34,7 @@ def _create_df(self, join_df: pd.DataFrame, scenario: str) -> pd.DataFrame: df["parameter"] = self.param df["scope"] = "uittredepunt" df["ondergrondscenario_naam"] = scenario - df["distribution_type"] = join_df.get(f"{self.param}_dist", "") + 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) From cc135c393b0bd30b16f8cd20064dab7f14225908 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 27 May 2026 15:16:24 +0200 Subject: [PATCH 24/53] icicle bugfix --- geoprob_pipe/visualizations/graphs/assemblage_icicle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geoprob_pipe/visualizations/graphs/assemblage_icicle.py b/geoprob_pipe/visualizations/graphs/assemblage_icicle.py index 58c4ba0d..6198f4d4 100644 --- a/geoprob_pipe/visualizations/graphs/assemblage_icicle.py +++ b/geoprob_pipe/visualizations/graphs/assemblage_icicle.py @@ -161,9 +161,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] From b9c6c2894a2e446d47321754abb4786f7a4aff28 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Fri, 29 May 2026 12:25:54 +0200 Subject: [PATCH 25/53] refactor --- .../update_ruimtelijke_invoer.py | 121 +++++++--- geoprob_pipe/cmd_app/questionnaire.py | 2 +- .../cmd_app/spatial_joins/__init__.py | 12 +- .../{base_couple.py => base.py} | 0 .../{distance_couple.py => distance.py} | 2 +- .../couple_objects/{hrd_couple.py => hrd.py} | 2 +- .../{shape_couple.py => shape.py} | 2 +- ...distance_to_exit_points.py => distance.py} | 2 +- .../spatial_joins/{coupled_hrd.py => hrd.py} | 2 +- .../{coupled_mv_exit.py => mv_exit.py} | 0 .../{coupled_parameters.py => parameters.py} | 2 +- ...d_exit_points_to_refline.py => refline.py} | 0 ...led_exit_points_to_vakken.py => vakken.py} | 0 .../spatial_layers/added_parameters.py | 2 +- .../cmd_app/spatial_layers/base_inquiry.py | 26 +- .../cmd_app/spatial_layers/old_polderpeil.py | 149 ------------ .../spatial_layers/valid_parameters.py | 8 +- geoprob_pipe/results/assemblage/functions.py | 2 +- geoprob_pipe/results/assemblage/objects.py | 2 +- .../graphs/assemblage_icicle.py | 15 +- geoprob_pipe/visualizations/graphs/hfreq.py | 6 +- geoprob_pipe/visualizations/maps/betamap.py | 227 +++++++++++------- 22 files changed, 271 insertions(+), 313 deletions(-) rename geoprob_pipe/cmd_app/spatial_joins/couple_objects/{base_couple.py => base.py} (100%) rename geoprob_pipe/cmd_app/spatial_joins/couple_objects/{distance_couple.py => distance.py} (97%) rename geoprob_pipe/cmd_app/spatial_joins/couple_objects/{hrd_couple.py => hrd.py} (98%) rename geoprob_pipe/cmd_app/spatial_joins/couple_objects/{shape_couple.py => shape.py} (99%) rename geoprob_pipe/cmd_app/spatial_joins/{coupled_distance_to_exit_points.py => distance.py} (98%) rename geoprob_pipe/cmd_app/spatial_joins/{coupled_hrd.py => hrd.py} (94%) rename geoprob_pipe/cmd_app/spatial_joins/{coupled_mv_exit.py => mv_exit.py} (100%) rename geoprob_pipe/cmd_app/spatial_joins/{coupled_parameters.py => parameters.py} (95%) rename geoprob_pipe/cmd_app/spatial_joins/{coupled_exit_points_to_refline.py => refline.py} (100%) rename geoprob_pipe/cmd_app/spatial_joins/{coupled_exit_points_to_vakken.py => vakken.py} (100%) delete mode 100644 geoprob_pipe/cmd_app/spatial_layers/old_polderpeil.py diff --git a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py index b31b10e6..70e51faf 100644 --- a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -65,7 +65,7 @@ def inquire_replace_layers(app_settings: ApplicationSettings): updaten. :param app_settings: _description_ - """ + """ conn = sqlite3.connect(app_settings.geopackage_filepath) # Haal ruimtelijke parameters op vanuit de metadata @@ -78,9 +78,9 @@ def inquire_replace_layers(app_settings: ApplicationSettings): conn.commit() conn.close() - - valid_parameters = valid_parameter_list(app_settings) - + + valid_list = valid_parameter_list(app_settings) + while True: parameter_input: str = InputPrompt( message=f""" @@ -91,7 +91,7 @@ def inquire_replace_layers(app_settings: ApplicationSettings): Als er niets wordt opgegeven wordt je terug gestuurd naar het keuzemenu. """ ).execute() - + if parameter_input == "": print( BColors.OKBLUE, @@ -99,23 +99,33 @@ def inquire_replace_layers(app_settings: ApplicationSettings): BColors.ENDC, ) return - - if not all([x for x in parameter_input if x in valid_parameters]): + + valid_input = all( + [ + param + for param in parameter_input.split(",") + if param in valid_list + ] + ) + if not valid_input: print( BColors.OKBLUE, - f"Geen tabellen verwijderd. '{parameter_input}' bevat een ongeldige parameter.", + f"Geen parameters toegevoegd. '{parameter_input}' bevat een ongeldige parameter.", BColors.ENDC, ) continue - + break - + # Verwijder uit geopackage layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) - table_list = [layer for layer in layers if layer.split("_")[0] in parameter_input] + table_list = [ + layer for layer in layers if layer.split("_")[0] in parameter_input + ] remove_tables(app_settings, table_list) completed_update() + def add_parameters(app_settings: ApplicationSettings): """ Voeg extra parameters toe voor de ruimtelijke invoer. De aanpassingen @@ -161,7 +171,13 @@ def add_parameters(app_settings: ApplicationSettings): ) return - valid_input = all(param in valid_list for param in parameter_input) + valid_input = all( + [ + param + for param in parameter_input.split(",") + if param in valid_list + ] + ) if not valid_input: print( @@ -178,7 +194,7 @@ def add_parameters(app_settings: ApplicationSettings): parameters = list(set(parameters)) # Verwijder dubbele waardes parameters = ", ".join(parameters) update_metadata_parameters(app_settings, parameters) - + completed_update() @@ -195,8 +211,8 @@ def remove_parameters(app_settings: ApplicationSettings): conn.commit() conn.close() - - valid_parameters = valid_parameter_list(app_settings) + + valid_list = valid_parameter_list(app_settings) while True: parameter_input: str = InputPrompt( @@ -207,7 +223,7 @@ def remove_parameters(app_settings: ApplicationSettings): Als er niets wordt opgegeven wordt je terug gestuurd naar het keuzemenu. """ ).execute() - + if parameter_input == "": print( BColors.OKBLUE, @@ -215,28 +231,40 @@ def remove_parameters(app_settings: ApplicationSettings): BColors.ENDC, ) return - if not all([x for x in parameter_input if x in valid_parameters]): + + 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 verwijderd. '{parameter_input}' bevat een ongeldige parameter.", + 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) update_metadata_parameters(app_settings, updated_parameters) # Verwijder uit geopackage layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) - table_list = [layer for layer in layers if layer.split("_")[0] in updated_parameters] + table_list = [ + layer for layer in layers if layer.split("_")[0] in updated_parameters + ] remove_tables(app_settings, table_list) completed_update() + def add_scenarios(app_settings: ApplicationSettings): """ Voeg ondergrondscenarios toe aan de lijst. Dit betekent dat alle @@ -319,7 +347,14 @@ def remove_scenarios(app_settings: ApplicationSettings): # Update metadata for scenario in scenario_input.split(","): - current_scenarios.remove(scenario) + if scenario in current_scenarios: + current_scenarios.remove(scenario) + else: + print( + BColors.WARNING, + f"Scenario {scenario} niet gevonden.", + BColors.ENDC, + ) update_metadata_scenarios(app_settings, ", ".join(current_scenarios)) @@ -375,7 +410,7 @@ def remove_tables( :param app_settings: Object met applicatie instellingen. :param table_list: Lijst met tabellen om te verwijderen, defaults to [] """ - update_batch_metadata(app_settings=app_settings, value=True) + update_batch_metadata(app_settings=app_settings, value=True) # Voor vervangen, nieuwe scenarios of verwijderen van parameters. conn = sqlite3.connect(app_settings.geopackage_filepath) cursor = conn.cursor() @@ -392,19 +427,41 @@ def remove_tables( 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,)) + 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,)) + 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() diff --git a/geoprob_pipe/cmd_app/questionnaire.py b/geoprob_pipe/cmd_app/questionnaire.py index d4f94828..573cdfa2 100644 --- a/geoprob_pipe/cmd_app/questionnaire.py +++ b/geoprob_pipe/cmd_app/questionnaire.py @@ -103,7 +103,7 @@ def questionnaire(app_settings: ApplicationSettings): sys.exit(EARLY_EXIT_MESSAGE) print("\nPARAMETER INVOER") - # TODO Vincent: Vraag Chris waar de traject defaults automatisch verwijderd worden + # 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) diff --git a/geoprob_pipe/cmd_app/spatial_joins/__init__.py b/geoprob_pipe/cmd_app/spatial_joins/__init__.py index 83f27781..0527ff01 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/__init__.py +++ b/geoprob_pipe/cmd_app/spatial_joins/__init__.py @@ -1,8 +1,8 @@ -from .coupled_distance_to_exit_points import ( +from .distance import ( coupled_distances_to_uittredepunten, ) -from .coupled_exit_points_to_refline import coupled_uittredepunten_to_refline -from .coupled_exit_points_to_vakken import coupled_uittredepunten_to_vakken -from .coupled_hrd import coupled_hrd_to_uittredepunten -from .coupled_mv_exit import coupled_mv_exit_to_gis_parameter_invoer_table -from .coupled_parameters import coupled_parameters_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/base_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py similarity index 100% rename from geoprob_pipe/cmd_app/spatial_joins/couple_objects/base_couple.py rename to geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance.py similarity index 97% rename from geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance_couple.py rename to geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance.py index d14cfbc2..dfa96ac6 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/distance.py @@ -3,7 +3,7 @@ import pandas as pd from typing import TYPE_CHECKING -from .base_couple import BaseCouple +from .base import BaseCouple if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py similarity index 98% rename from geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py rename to geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py index 9408b23d..10dbd500 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py @@ -11,7 +11,7 @@ import pandas as pd import numpy as np -from .base_couple import BaseCouple +from .base import BaseCouple if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py similarity index 99% rename from geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py rename to geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py index 26fa7427..48f16651 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape_couple.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py @@ -8,7 +8,7 @@ from geoprob_pipe.cmd_app.spatial_layers import LIST_PARAMS from geoprob_pipe.utils.validation_messages import BColors -from .base_couple import BaseCouple +from .base import BaseCouple if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_distance_to_exit_points.py b/geoprob_pipe/cmd_app/spatial_joins/distance.py similarity index 98% rename from geoprob_pipe/cmd_app/spatial_joins/coupled_distance_to_exit_points.py rename to geoprob_pipe/cmd_app/spatial_joins/distance.py index fe0899ae..c8eaca9f 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_distance_to_exit_points.py +++ b/geoprob_pipe/cmd_app/spatial_joins/distance.py @@ -9,7 +9,7 @@ import geopandas as gpd import fiona -from geoprob_pipe.cmd_app.spatial_joins.couple_objects.distance_couple import ( +from geoprob_pipe.cmd_app.spatial_joins.couple_objects.distance import ( DistCouple, ) from geoprob_pipe.utils.validation_messages import BColors diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py b/geoprob_pipe/cmd_app/spatial_joins/hrd.py similarity index 94% rename from geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py rename to geoprob_pipe/cmd_app/spatial_joins/hrd.py index 1f55a42d..f375bbd9 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_hrd.py +++ b/geoprob_pipe/cmd_app/spatial_joins/hrd.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING import fiona -from .couple_objects.hrd_couple import HRDCouple +from .couple_objects.hrd import HRDCouple if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings 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 100% rename from geoprob_pipe/cmd_app/spatial_joins/coupled_mv_exit.py rename to geoprob_pipe/cmd_app/spatial_joins/mv_exit.py diff --git a/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py b/geoprob_pipe/cmd_app/spatial_joins/parameters.py similarity index 95% rename from geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py rename to geoprob_pipe/cmd_app/spatial_joins/parameters.py index 572f0542..9c32b6c9 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/coupled_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_joins/parameters.py @@ -3,7 +3,7 @@ import sqlite3 from typing import TYPE_CHECKING -from .couple_objects.shape_couple import ShapeCouple +from .couple_objects.shape import ShapeCouple from geoprob_pipe.utils.validation_messages import BColors if TYPE_CHECKING: 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/added_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py index 22171f91..bd6df504 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_parameters.py @@ -71,7 +71,7 @@ def request_parameters(app_settings: ApplicationSettings): else: parameters = parameter_input.split(",") - if not all(x in valid_list for x in parameters): # type:ignore + 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.", diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 236250a2..84a980d1 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -285,8 +285,8 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: # Of verschillende geometrieën per scenario column_list = gdf.columns.to_list() if True in [ - len(x.split("_")) == 3 and self.param in x.split("_") - for x in column_list + len(column.split("_")) == 3 and self.param in column.split("_") + for column in column_list ]: return self._add_with_affixes(gdf) else: @@ -447,9 +447,9 @@ def _add_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: """ column_list = gdf.columns.to_list() add_list = [ - f"{self.param}_{x}" - for x in self.suffix_list - if f"{self.param}_{x}" in column_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): @@ -478,7 +478,7 @@ def _add_with_affixes(self, gdf: gpd.GeoDataFrame) -> bool: for scenario in self.scenarios: filter_list = [ - x for x in column_list if x.split("_")[0] == scenario + column for column in column_list if column.split("_")[0] == scenario ] if len(filter_list) == 0: @@ -490,13 +490,13 @@ def _add_with_affixes(self, gdf: gpd.GeoDataFrame) -> bool: continue filter_list = [ - x.split("_")[1:] for x in filter_list + column.split("_")[1:] for column in filter_list ] # Strip scenario van kolomnaam. add_list = [ - f"{self.param}_{x}" - for x in self.suffix_list - if f"{self.param}_{x}" in filter_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): @@ -536,9 +536,9 @@ def _add_separate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: continue add_list = [ - f"{self.param}_{x}" - for x in self.suffix_list - if f"{self.param}_{x}" in column_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): diff --git a/geoprob_pipe/cmd_app/spatial_layers/old_polderpeil.py b/geoprob_pipe/cmd_app/spatial_layers/old_polderpeil.py deleted file mode 100644 index e6fa36bc..00000000 --- a/geoprob_pipe/cmd_app/spatial_layers/old_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 # type:ignore -# 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/valid_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py index 151d069c..78936688 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py @@ -46,20 +46,20 @@ def valid_parameter_list(app_settings: ApplicationSettings): "SELECT metadata_value FROM geoprob_pipe_metadata WHERE metadata_type='geohydrologisch_model'" ) model = cur.fetchone()[0] - # conn wordt later gesloten. + 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 = [x for x in input_list if x in model_list] + 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 = [x for x in input_list if x in model_list] + 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 = [x for x in input_list if x in model_list] + valid_list = [param for param in input_list if param in model_list] return valid_list diff --git a/geoprob_pipe/results/assemblage/functions.py b/geoprob_pipe/results/assemblage/functions.py index 3530c7c8..84f060f2 100644 --- a/geoprob_pipe/results/assemblage/functions.py +++ b/geoprob_pipe/results/assemblage/functions.py @@ -166,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: diff --git a/geoprob_pipe/results/assemblage/objects.py b/geoprob_pipe/results/assemblage/objects.py index 28c6a8bc..37a1917b 100644 --- a/geoprob_pipe/results/assemblage/objects.py +++ b/geoprob_pipe/results/assemblage/objects.py @@ -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/visualizations/graphs/assemblage_icicle.py b/geoprob_pipe/visualizations/graphs/assemblage_icicle.py index 6198f4d4..e14f4924 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: _description_ + :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() 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/maps/betamap.py b/geoprob_pipe/visualizations/maps/betamap.py index 1f20a377..fb333d6f 100644 --- a/geoprob_pipe/visualizations/maps/betamap.py +++ b/geoprob_pipe/visualizations/maps/betamap.py @@ -12,36 +12,43 @@ 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. """ - +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 = [x for x in gpkg_layers if x.split("_")[0] == layer] - + gpkg_layers: list[str] = fiona.listlayers( + geoprob_pipe.input_data.app_settings.geopackage_filepath + ) + list_layers = [ + layer for layer in gpkg_layers if layer.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) + 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 - )) + 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: @@ -69,7 +76,10 @@ def plot_linestring(ls, display): 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] @@ -79,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]), @@ -108,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 @@ -126,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") @@ -176,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( @@ -231,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') From cf5e3a26e00335c4433c51130bc8fb166d6fa143 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Mon, 1 Jun 2026 14:50:43 +0200 Subject: [PATCH 26/53] test en fixes lijn invoer --- .../update_ruimtelijke_invoer.py | 6 +- .../spatial_joins/couple_objects/base.py | 12 +-- .../spatial_joins/couple_objects/shape.py | 14 +-- .../cmd_app/spatial_joins/distance.py | 4 +- .../spatial_layers/added_intredelijn.py | 2 +- .../added_ruimtelijke_invoer.py | 2 +- .../cmd_app/spatial_layers/base_inquiry.py | 89 +++++++++++-------- 7 files changed, 76 insertions(+), 53 deletions(-) diff --git a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py index 70e51faf..19ae2ba7 100644 --- a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -120,7 +120,7 @@ def inquire_replace_layers(app_settings: ApplicationSettings): # Verwijder uit geopackage layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) table_list = [ - layer for layer in layers if layer.split("_")[0] in parameter_input + layer for layer in layers if layer.split("__")[0] in parameter_input ] remove_tables(app_settings, table_list) completed_update() @@ -259,7 +259,7 @@ def remove_parameters(app_settings: ApplicationSettings): # Verwijder uit geopackage layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) table_list = [ - layer for layer in layers if layer.split("_")[0] in updated_parameters + layer for layer in layers if layer.split("__")[0] in updated_parameters ] remove_tables(app_settings, table_list) completed_update() @@ -425,7 +425,7 @@ def remove_tables( if table_list == []: # Remove all spatial input for layer in layers: - if layer.split("_")[0] in parameters: + if layer.split("__")[0] in parameters: cursor.execute(f"DROP TABLE IF EXISTS {layer}") cursor.execute( "DELETE FROM gpkg_contents WHERE table_name = ?", (layer,) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py index b9067ff6..54fd2c89 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py @@ -34,12 +34,12 @@ def _create_df(self, join_df: pd.DataFrame, scenario: str) -> pd.DataFrame: 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["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"] = "" diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py index 48f16651..faa4d382 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py @@ -56,9 +56,9 @@ def couple_exit_points(self): self.param_tables = [ table for table in self.tables_names - if table.split("_")[0] == self.param + 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." @@ -87,11 +87,16 @@ def _add_multiple_layers(self): Voeg de lagen een voor een toe als er ruimtelijke scenarios zijn voor de parameter. """ - for scenario in self.param_tables: + for layer in self.param_tables: gdf_parameter: gpd.GeoDataFrame = gpd.read_file( self.app_settings.geopackage_filepath, - layer=f"{self.param}_{scenario}", + 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 = ""): @@ -106,7 +111,6 @@ def _check_shape(self, gdf: gpd.GeoDataFrame, scenario: str = ""): :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) diff --git a/geoprob_pipe/cmd_app/spatial_joins/distance.py b/geoprob_pipe/cmd_app/spatial_joins/distance.py index c8eaca9f..bb1e8634 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/distance.py +++ b/geoprob_pipe/cmd_app/spatial_joins/distance.py @@ -56,7 +56,7 @@ def coupled_distances_to_uittredepunten( ).couple_exit_points() # Intrede lijn per scenario - if len(layer.split("_")) == 2 and "intredelijn" in layer.split("_")[0]: + if len(layer.split("__")) == 2 and "intredelijn" in layer.split("__")[0]: gdf_intredelijnen: gpd.GeoDataFrame = gpd.read_file( app_settings.geopackage_filepath, layer=layer ) @@ -75,7 +75,7 @@ def coupled_distances_to_uittredepunten( ) DistCouple( app_settings, "L_intrede", df_l_intrede - ).couple_exit_points(scenario=layer.split("_")[1]) + ).couple_exit_points(scenario=layer.split("__")[1]) # Distance to buitenteenlijn gdf_buitenteenlijnen: gpd.GeoDataFrame = gpd.read_file( diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py index b12b9dd7..993bdc33 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py @@ -19,7 +19,7 @@ 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]: + if "intredelijn" in layer.split("__")[0]: print(BColors.OKBLUE, "✔ Intredelijn al toegevoegd.", BColors.ENDC) return True diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py index 340df599..4c55bbd1 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py @@ -31,7 +31,7 @@ def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool: return True for parameter in parameters: - if any(parameter in layer.split("_")[0] for layer in list_layers): + if any(parameter in layer.split("__")[0] for layer in list_layers): print( BColors.OKBLUE, f"✔ {parameter} al toegevoegd.", diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 84a980d1..74c752dc 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -22,7 +22,7 @@ import fiona import geopandas as gpd import InquirerPy.prompts.input as prompt -import numpy as np +import pandas as pd from shapely import LineString, MultiLineString from geoprob_pipe.utils.validation_messages import BColors @@ -119,7 +119,7 @@ def request_filepath(self): if self._add_to_gpkg(gdf): break - print(BColors.OKBLUE, f"✅ {self.param} toegevoegd.", BColors.ENDC) + print(BColors.OKBLUE, f"✅ {self.param} toegevoegd.", BColors.ENDC) def _import_data(self, filepath: str) -> gpd.GeoDataFrame: """ @@ -253,18 +253,19 @@ 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. + 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. + *__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_*. + 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. @@ -285,7 +286,8 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: # 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("_") + len(column.split("__")) == 3 + and self.param in column.split("__") for column in column_list ]: return self._add_with_affixes(gdf) @@ -347,6 +349,7 @@ def _distribution_check( 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. @@ -365,21 +368,29 @@ def _distribution_check( 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(): - if row[f"{self.param}_dist"] == "deterministic": + + # 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: - var_bool = row[f"{self.param}_var"] != np.nan or "" + 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: - dev_bool = row[f"{self.param}_dev"] != np.nan or "" + 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 @@ -430,7 +441,7 @@ def _add_with_separate_geometry(self, gdf: gpd.GeoDataFrame) -> bool: gdf_to_add.to_file( self.app_settings.geopackage_filepath, - layer=f"{self.param}_{scenario}", + layer=f"{self.param}__{scenario}", driver="GPKG", ) @@ -447,9 +458,9 @@ def _add_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: """ column_list = gdf.columns.to_list() add_list = [ - f"{self.param}_{param}" + f"{self.param}__{param}" for param in self.suffix_list - if f"{self.param}_{param}" in column_list + if f"{self.param}__{param}" in column_list ] if not self._distribution_check(column_list, add_list, gdf): @@ -478,7 +489,9 @@ def _add_with_affixes(self, gdf: gpd.GeoDataFrame) -> bool: for scenario in self.scenarios: filter_list = [ - column for column in column_list if column.split("_")[0] == scenario + column + for column in column_list + if column.split("__")[0] == scenario ] if len(filter_list) == 0: @@ -489,24 +502,30 @@ def _add_with_affixes(self, gdf: gpd.GeoDataFrame) -> bool: ) continue - filter_list = [ - column.split("_")[1:] for column in filter_list - ] # Strip scenario van kolomnaam. + # 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}" + f"{self.param}__{suffix}" for suffix in self.suffix_list - if f"{self.param}_{suffix}" in filter_list + if f"{self.param}__{suffix}" in filter_list ] - if not self._distribution_check(column_list, add_list, gdf): - return False - - gdf_to_add = gdf[["geometry", add_list]] + if not self._distribution_check( + column_list, add_list, gdf, scenario=scenario + ): + # Vang parameters niet voor dit scenario. + 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}", + layer=f"{self.param}__{scenario}", driver="GPKG", ) @@ -520,7 +539,7 @@ def _add_separate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: :return: bool voor valid_input in while-loop """ column_list = gdf.columns.to_list() - + if not self._scenario_check(column_list): return False @@ -536,9 +555,9 @@ def _add_separate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: continue add_list = [ - f"{self.param}_{suffix}" + f"{self.param}__{suffix}" for suffix in self.suffix_list - if f"{self.param}_{suffix}" in column_list + if f"{self.param}__{suffix}" in column_list ] if not self._distribution_check(column_list, add_list, gdf): @@ -556,7 +575,7 @@ def _add_separate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: else: gdf_to_add.to_file( self.app_settings.geopackage_filepath, - layer=f"{self.param}_{scenario}", + layer=f"{self.param}__{scenario}", driver="GPKG", ) From a2977623b13e244f22f2b7e3e6469218d3c5a0d1 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Mon, 1 Jun 2026 14:57:56 +0200 Subject: [PATCH 27/53] update database invoer bugfix --- .../added_ruimtelijke_invoer.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py index 4c55bbd1..5245df7e 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py @@ -21,8 +21,11 @@ def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool: ) parameters: list[str] = cursor.fetchone()[0].split(", ") conn.close() + list_layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) - if parameters == ['']: # De split maakt één lege string als de uit de metadata gelezen string leeg is. + + # De split maakt één lege string als de uit de metadata gelezen string leeg is. + if parameters == [""]: print( BColors.OKBLUE, "✔ Geen ruimtelijke parameter invoer.", @@ -32,19 +35,19 @@ def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool: 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, - ) - return True + 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 + include_value=True, ) inquiry.request_filepath() - + return True From 81240143679c2915ecc653fa5cf16d1af44e6528 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 2 Jun 2026 11:22:15 +0200 Subject: [PATCH 28/53] bugfix distance lijnen --- geoprob_pipe/cmd_app/spatial_joins/distance.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/geoprob_pipe/cmd_app/spatial_joins/distance.py b/geoprob_pipe/cmd_app/spatial_joins/distance.py index bb1e8634..afc414b1 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/distance.py +++ b/geoprob_pipe/cmd_app/spatial_joins/distance.py @@ -49,7 +49,7 @@ def coupled_distances_to_uittredepunten( ["uittredepunt_id", "afstand_intredelijn"] ] df_l_intrede = df_l_intrede.rename( - columns={"afstand_intredelijn": "L_intrede_mean"} + columns={"afstand_intredelijn": "L_intrede__mean"} ) DistCouple( app_settings, "L_intrede", df_l_intrede @@ -71,7 +71,7 @@ def coupled_distances_to_uittredepunten( ["uittredepunt_id", "afstand_intredelijn"] ] df_l_intrede = df_l_intrede.rename( - columns={"afstand_intredelijn": "L_intrede_mean"} + columns={"afstand_intredelijn": "L_intrede__mean"} ) DistCouple( app_settings, "L_intrede", df_l_intrede @@ -86,7 +86,7 @@ def coupled_distances_to_uittredepunten( ) df_l_but = gdf_exit_points[["uittredepunt_id", "afstand_buitenteenlijn"]] df_l_but = df_l_but.rename( - columns={"afstand_buitenteenlijn": "L_but_mean"} + columns={"afstand_buitenteenlijn": "L_but__mean"} ) DistCouple(app_settings, "L_but", df_l_but).couple_exit_points() @@ -100,7 +100,7 @@ def coupled_distances_to_uittredepunten( ) df_l_bit = gdf_exit_points[["uittredepunt_id", "afstand_binnenteenlijn"]] df_l_bit = df_l_bit.rename( - columns={"afstand_binnenteenlijn": "L_bit_mean"} + columns={"afstand_binnenteenlijn": "L_bit__mean"} ) DistCouple(app_settings, "L_bit", df_l_bit).couple_exit_points() From e913eb83a1079a7a54475a3b1cc0ce75d733ce01 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 2 Jun 2026 11:52:49 +0200 Subject: [PATCH 29/53] beta map bugfix en comparison fix --- geoprob_pipe/cmd_app/comparisons/beta_map.py | 291 ++++++++++--------- geoprob_pipe/visualizations/maps/betamap.py | 4 +- 2 files changed, 157 insertions(+), 138 deletions(-) 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/visualizations/maps/betamap.py b/geoprob_pipe/visualizations/maps/betamap.py index fb333d6f..aa21210c 100644 --- a/geoprob_pipe/visualizations/maps/betamap.py +++ b/geoprob_pipe/visualizations/maps/betamap.py @@ -22,8 +22,8 @@ def _add_line( gpkg_layers: list[str] = fiona.listlayers( geoprob_pipe.input_data.app_settings.geopackage_filepath ) - list_layers = [ - layer for layer in gpkg_layers if layer.split("_")[0] == layer + list_layers: list[str] = [ + lay for lay in gpkg_layers if lay.split("__")[0] == layer ] for listed_layer in list_layers: From 44787b0e206680039377bd166a87a08bd5fbe600 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 2 Jun 2026 13:11:40 +0200 Subject: [PATCH 30/53] documentatie --- .../spatial_joins/couple_objects/base.py | 4 +++- geoprob_pipe/cmd_app/spatial_joins/distance.py | 5 ++++- .../cmd_app/spatial_joins/parameters.py | 2 +- .../spatial_layers/added_binnenteenlijn.py | 2 +- .../cmd_app/spatial_layers/added_scenarios.py | 2 +- .../cmd_app/spatial_layers/added_vakindeling.py | 6 ++++-- .../cmd_app/spatial_layers/base_inquiry.py | 17 ++++++++--------- .../cmd_app/spatial_layers/valid_parameters.py | 8 ++++++++ 8 files changed, 30 insertions(+), 16 deletions(-) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py index 54fd2c89..ab889d7e 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py @@ -24,6 +24,7 @@ class BaseCouple: 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. @@ -133,7 +134,8 @@ def _upsert_to_gpkg(self, df: pd.DataFrame): """, data, ) - # UPSERT naar gpkg_contents + # UPSERT naar gpkg_contents, vereist in gpkg om leesbaar te zijn + # voor GIS software content = ( "gis_join_parameter_invoer", "attributes", diff --git a/geoprob_pipe/cmd_app/spatial_joins/distance.py b/geoprob_pipe/cmd_app/spatial_joins/distance.py index afc414b1..0a059bb4 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/distance.py +++ b/geoprob_pipe/cmd_app/spatial_joins/distance.py @@ -28,13 +28,16 @@ def coupled_distances_to_uittredepunten( :param app_settings: Object met de instellingen van de applicatie """ - # Read uittredepunten + # 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( diff --git a/geoprob_pipe/cmd_app/spatial_joins/parameters.py b/geoprob_pipe/cmd_app/spatial_joins/parameters.py index 9c32b6c9..9f0c8059 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/parameters.py +++ b/geoprob_pipe/cmd_app/spatial_joins/parameters.py @@ -21,7 +21,7 @@ def coupled_parameters_to_uittredepunten( ) parameters: list[str] = cursor.fetchone()[0].split(", ") conn.close() - if parameters == ['']: # De split maakt één lege string als de uit de metadata gelezen string leeg is. + if parameters == ['']: # De split maakt een lege string, als de uit de metadata gelezen string leeg is. print( BColors.OKBLUE, "✔ Geen ruimtelijke koppelingen.", diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py index 2f516724..4cca0ed4 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py @@ -1,7 +1,7 @@ """ 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. +Maak het toevoegen van deze lijnen afhankelijk van de model keuze. """ from __future__ import annotations diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py index 38bdf8bd..7e622c4d 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_scenarios.py @@ -45,7 +45,7 @@ def request_scenarios(app_settings: ApplicationSettings): 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 = "" diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py index 9435d579..70115312 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py @@ -152,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. " diff --git a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py index 74c752dc..070a9a61 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -81,7 +81,7 @@ def request_filepath(self): f""" Specificeer het volledige bestandspad naar de geopackage/shapefile/geodatabase met de {self.param} geometrieën. - """ +""" ) ).execute() @@ -176,7 +176,7 @@ def _import_from_db(self, filepath: str) -> gpd.GeoDataFrame: 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() @@ -372,13 +372,12 @@ def _distribution_check( # 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 @@ -515,11 +514,12 @@ def _add_with_affixes(self, gdf: gpd.GeoDataFrame) -> bool: if not self._distribution_check( column_list, add_list, gdf, scenario=scenario ): - # Vang parameters niet voor dit 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}) @@ -543,9 +543,8 @@ def _add_separate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: if not self._scenario_check(column_list): return False - for scenario in self.scenarios + [ - None - ]: # als er geen scenario zijn opgegeven in de kolom + # '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: diff --git a/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py index 78936688..f3bf1a98 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py @@ -40,6 +40,13 @@ } 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( @@ -58,6 +65,7 @@ def valid_parameter_list(app_settings: ApplicationSettings): 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] From ee8178526f1ec8339242bd19b39a704fc6362110 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 3 Jun 2026 11:11:50 +0200 Subject: [PATCH 31/53] ruimtelijke invoer keuze menu restart flag --- .../parameter_input/added_input_parameters.py | 7 +- .../update_ruimtelijke_invoer.py | 849 +++++++++--------- 2 files changed, 443 insertions(+), 413 deletions(-) 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 b83a9efb..eb25b74a 100644 --- a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py +++ b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py @@ -15,7 +15,7 @@ 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 inquire_spatial_update +from .update_ruimtelijke_invoer import SpatialUpdateMenu from geoprob_pipe.cmd_app.utils.batch_input import update_batch_metadata if TYPE_CHECKING: @@ -192,9 +192,8 @@ def inquire_to_import_export_tables_and_figures_or_continue( case "Ruimtelijke invoer: Update ingevoerde lagen": # Nieuw keuze menu voor de volgende: - inquire_spatial_update( - app_settings=app_settings, - ) + menu = SpatialUpdateMenu(app_settings) + menu.inquire_spatial_update() continue case "Toelichting per keuze optie": diff --git a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py index 19ae2ba7..62511154 100644 --- a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -16,144 +16,175 @@ from geoprob_pipe.cmd_app.cmd import ApplicationSettings -def inquire_spatial_update( - app_settings: ApplicationSettings, -): - 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", - "Ga terug naar het parameter invoer menu", - ] - while True: - 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": - inquire_replace_layers(app_settings) - continue - - case "Voeg parameters toe voor ruimtelijke invoer": - add_parameters(app_settings) - continue - - case "Verwijder parameters voor ruimtelijke invoer": - remove_parameters(app_settings) - continue - - case "Voeg scenarios toe voor ruimtelijke invoer": - add_scenarios(app_settings) - continue - - case "Verwijder scenarios voor ruimtelijke invoer": - remove_scenarios(app_settings) - continue - - case "Ga terug naar het parameter invoer menu": - return - - -def inquire_replace_layers(app_settings: ApplicationSettings): - """ - Verwijder tabellen die opnieuw moeten worden ingeladen om de geopackage te - updaten. - - :param app_settings: _description_ - """ - conn = sqlite3.connect(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(", ") +class SpatialUpdateMenu: + + 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 + self.restart_flag: bool = False + + def inquire_spatial_update( + self, + ): + """ + Keuzemenu voor het updaten van de ruimtelijke invoer van de .gpkg. + + :param app_settings: _description_ + """ + + + 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): + """ + Verwijder tabellen die opnieuw moeten worden ingeladen om de geopackage te + updaten. + + :param app_settings: _description_ + """ + 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() + conn.commit() + conn.close() - valid_list = valid_parameter_list(app_settings) + valid_list = valid_parameter_list(self.app_settings) - while True: - parameter_input: str = InputPrompt( - message=f""" + 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() + ).execute() - if parameter_input == "": - print( - BColors.OKBLUE, - "Geen tabellen verwijderd.", - BColors.ENDC, - ) - return + 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, + valid_input = all( + [ + param + for param in parameter_input.split(",") + if param in valid_list + ] ) - continue - - break - - # Verwijder uit geopackage - layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) - table_list = [ - layer for layer in layers if layer.split("__")[0] in parameter_input - ] - remove_tables(app_settings, table_list) - completed_update() - - -def add_parameters(app_settings: ApplicationSettings): - """ - Voeg extra parameters toe voor de ruimtelijke invoer. De aanpassingen - kunnen pas verwerkt worden nadat de applicatie opnieuw is opgestart. - - :param app_settings: `ApplicationSettings` object met alle settings. - """ + if not valid_input: + print( + BColors.OKBLUE, + f"Geen parameters toegevoegd. '{parameter_input}' bevat een ongeldige parameter.", + BColors.ENDC, + ) + continue - conn = sqlite3.connect(app_settings.geopackage_filepath) + break - # 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(", ") + # 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): + """ + Voeg extra parameters toe voor de ruimtelijke invoer. De aanpassingen + kunnen pas verwerkt worden nadat de applicatie opnieuw is opgestart. + + :param app_settings: `ApplicationSettings` object met alle settings. + """ + + 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() + conn.commit() + conn.close() - # Haal lijst met geldige parameters op. - valid_list = valid_parameter_list(app_settings) + # 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""" + # 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: @@ -161,332 +192,332 @@ def add_parameters(app_settings: ApplicationSettings): 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 + ).execute() - valid_input = all( - [ - param - for param in parameter_input.split(",") - if param in valid_list - ] - ) + if parameter_input == "": + print( + BColors.OKBLUE, + "Geen nieuwe parameters toegevoegd.", + BColors.ENDC, + ) + return - if not valid_input: - print( - BColors.OKBLUE, - f"Geen parameters toegevoegd. '{parameter_input}' bevat een ongeldige parameter.", - BColors.ENDC, + valid_input = all( + [ + param + for param in parameter_input.split(",") + if param in valid_list + ] ) - continue - break + if not valid_input: + print( + BColors.OKBLUE, + f"Geen parameters toegevoegd. '{parameter_input}' bevat een ongeldige parameter.", + BColors.ENDC, + ) + continue - # Update metadata - parameters = current_parameters + parameter_input.split(",") - parameters = list(set(parameters)) # Verwijder dubbele waardes - parameters = ", ".join(parameters) - update_metadata_parameters(app_settings, parameters) + break - completed_update() + # 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(app_settings: ApplicationSettings): - conn = sqlite3.connect(app_settings.geopackage_filepath) + def remove_parameters(self): + 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(", ") + # 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() + conn.commit() + conn.close() - valid_list = valid_parameter_list(app_settings) + valid_list = valid_parameter_list(self.app_settings) - while True: - parameter_input: str = InputPrompt( - message=f""" + 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() + ).execute() + + if parameter_input == "": + print( + BColors.OKBLUE, + "Geen parameters verwijderd.", + BColors.ENDC, + ) + return - if parameter_input == "": - print( - BColors.OKBLUE, - "Geen parameters verwijderd.", - BColors.ENDC, + valid_input = all( + [ + param + for param in parameter_input.split(",") + if param in valid_list + ] ) - 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): + """ + 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(", ") - 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) - update_metadata_parameters(app_settings, updated_parameters) - # Verwijder uit geopackage - layers: list[str] = fiona.listlayers(app_settings.geopackage_filepath) - table_list = [ - layer for layer in layers if layer.split("__")[0] in updated_parameters - ] - remove_tables(app_settings, table_list) - completed_update() - - -def add_scenarios(app_settings: ApplicationSettings): - """ - Voeg ondergrondscenarios toe aan de lijst. Dit betekent dat alle - ruimtelijke invoer opnieuw moet worden ingeladen. - """ - # Haal de huidige scenarios op. - conn = sqlite3.connect(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""" + 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() + ).execute() - if scenario_input == "": - print( - BColors.OKBLUE, - "Geen nieuwe scenarios toegevoegd.", - BColors.ENDC, - ) - return + if scenario_input == "": + print( + BColors.OKBLUE, + "Geen nieuwe scenarios toegevoegd.", + BColors.ENDC, + ) + return - # Update metadata - updated_scenarios = current_scenarios + scenario_input - update_metadata_scenarios(app_settings, ", ".join(updated_scenarios)) - - # Remove tables to recollect data. - remove_tables(app_settings) - - -def remove_scenarios(app_settings: ApplicationSettings): - """ - Verwijder ondergrondscenarios uit de lijst. Dit betekent dat alle - ruimtelijke invoer opnieuw moet worden ingeladen. - """ - # Haal de huidige scenarios op. - conn = sqlite3.connect(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""" + # 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): + """ + 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() + ).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: + if scenario_input == "": print( - BColors.WARNING, - f"Scenario {scenario} niet gevonden.", + BColors.OKBLUE, + "Geen scenarios verwijderd.", BColors.ENDC, ) + return - update_metadata_scenarios(app_settings, ", ".join(current_scenarios)) - - # Remove tables to recollect data. - remove_tables(app_settings) - - -def update_metadata_scenarios( - app_settings: ApplicationSettings, scenarios: str -): - """ - Update de ondergrondscenarios in de metadata. - """ - conn = sqlite3.connect(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( - app_settings: ApplicationSettings, parameters: str -): - """ - Update de parameters voor ruimtelijke invoer in de metadata. - """ - 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, (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( - app_settings: ApplicationSettings, table_list: list[str] = [] -): - """ - 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 app_settings: Object met applicatie instellingen. - :param table_list: Lijst met tabellen om te verwijderen, defaults to [] - """ - update_batch_metadata(app_settings=app_settings, value=True) - # Voor vervangen, nieuwe scenarios of verwijderen van parameters. - 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(", ") - parameters.append("intredelijn") - layers: list[str] = fiona.listlayers(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,), - ) + # 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): + """ + Update de ondergrondscenarios 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): + """ + Update de parameters voor ruimtelijke invoer 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] = []): + """ + 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 app_settings: Object met applicatie instellingen. + :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",), + ) - conn.commit() - conn.close() - - -def completed_update(): - """ - 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": - return + parameters: list[str] = cursor.fetchone()[0].split(", ") + parameters.append("intredelijn") + layers: list[str] = fiona.listlayers( + self.app_settings.geopackage_filepath + ) - case "Applicatie afsluiten": - sys.exit("Applicatie is afgesloten.") + 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): + """ + 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.") From eef4132d8d17dd756efff97081cbff395e02e98d Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 3 Jun 2026 11:43:01 +0200 Subject: [PATCH 32/53] legenda betrouwbaarheidsindex grafiek buiten de plot geplaatst en wat documentatie --- .../update_ruimtelijke_invoer.py | 36 +++++++++---------- .../graphs/assemblage_icicle.py | 21 +++++++++-- .../graphs/betrouwbaarheidsindex.py | 35 ++++++++++++++++-- 3 files changed, 69 insertions(+), 23 deletions(-) diff --git a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py index 62511154..688e09e0 100644 --- a/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/parameter_input/update_ruimtelijke_invoer.py @@ -17,7 +17,8 @@ class SpatialUpdateMenu: - + restart_flag: bool = False + def __init__( self, app_settings: ApplicationSettings, @@ -25,18 +26,17 @@ def __init__( """ Class voor alle submenus onder het aanpassen vaan de ruimtelijke invoer. - :param app_settings: Object met de instellingen van de applicatie, + :param app_settings: Object met de instellingen van de applicatie """ self.app_settings = app_settings - self.restart_flag: bool = False def inquire_spatial_update( self, - ): + ) -> None: """ Keuzemenu voor het updaten van de ruimtelijke invoer van de .gpkg. - :param app_settings: _description_ + :param app_settings: Object met de instellingen van de applicatie """ @@ -87,12 +87,10 @@ def inquire_spatial_update( case "Ga terug naar het parameter invoer menu": return - def inquire_replace_layers(self): + def inquire_replace_layers(self) -> None: """ Verwijder tabellen die opnieuw moeten worden ingeladen om de geopackage te updaten. - - :param app_settings: _description_ """ conn = sqlite3.connect(self.app_settings.geopackage_filepath) @@ -157,12 +155,10 @@ def inquire_replace_layers(self): self.remove_tables(table_list) self.completed_update() - def add_parameters(self): + 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. - - :param app_settings: `ApplicationSettings` object met alle settings. """ conn = sqlite3.connect(self.app_settings.geopackage_filepath) @@ -228,7 +224,7 @@ def add_parameters(self): self.completed_update() - def remove_parameters(self): + def remove_parameters(self) -> None: conn = sqlite3.connect(self.app_settings.geopackage_filepath) # Haal ruimtelijke parameters op vanuit de metadata @@ -298,7 +294,7 @@ def remove_parameters(self): self.remove_tables(table_list) self.completed_update() - def add_scenarios(self): + def add_scenarios(self) -> None: """ Voeg ondergrondscenarios toe aan de lijst. Dit betekent dat alle ruimtelijke invoer opnieuw moet worden ingeladen. @@ -341,7 +337,7 @@ def add_scenarios(self): # Remove tables to recollect data. self.remove_tables() - def remove_scenarios(self): + def remove_scenarios(self) -> None: """ Verwijder ondergrondscenarios uit de lijst. Dit betekent dat alle ruimtelijke invoer opnieuw moet worden ingeladen. @@ -393,9 +389,10 @@ def remove_scenarios(self): # Remove tables to recollect data. self.remove_tables() - def update_metadata_scenarios(self, scenarios: str): + 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) @@ -407,9 +404,11 @@ def update_metadata_scenarios(self, scenarios: str): conn.commit() conn.close() - def update_metadata_parameters(self, parameters: str): + 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) @@ -428,13 +427,12 @@ def update_metadata_parameters(self, parameters: str): conn.commit() conn.close() - def remove_tables(self, table_list: list[str] = []): + 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 app_settings: Object met applicatie instellingen. :param table_list: Lijst met tabellen om te verwijderen, defaults to [] """ update_batch_metadata(self.app_settings, value=True) @@ -497,7 +495,7 @@ def remove_tables(self, table_list: list[str] = []): conn.commit() conn.close() - def completed_update(self): + 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 diff --git a/geoprob_pipe/visualizations/graphs/assemblage_icicle.py b/geoprob_pipe/visualizations/graphs/assemblage_icicle.py index e14f4924..c3bdcd60 100644 --- a/geoprob_pipe/visualizations/graphs/assemblage_icicle.py +++ b/geoprob_pipe/visualizations/graphs/assemblage_icicle.py @@ -18,8 +18,8 @@ def __init__(self, geoprob_pipe: GeoProbPipe, export: bool = False): Hierin kan worden gezien hoe de faalkansen en beta's tot stand komen vanuit onderliggende elementen. - :param geoprob_pipe: _description_ - :param export: Of het figuur geëxporteerd wordt, defaults to False + :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 @@ -30,6 +30,11 @@ 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 @@ -157,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 = [ @@ -182,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") @@ -229,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..46e2a70e 100644 --- a/geoprob_pipe/visualizations/graphs/betrouwbaarheidsindex.py +++ b/geoprob_pipe/visualizations/graphs/betrouwbaarheidsindex.py @@ -85,6 +85,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 +118,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 +216,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 +290,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 +328,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 +405,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 +427,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 +458,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 From cd4eb9ae08bde78135b44fc1f47ac6508cf5a9c9 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 3 Jun 2026 12:50:31 +0200 Subject: [PATCH 33/53] river_waterlevel documentatie --- .../graphs/betrouwbaarheidsindex.py | 9 ++- .../visualizations/graphs/river_waterlevel.py | 69 +++++++++++++++---- 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/geoprob_pipe/visualizations/graphs/betrouwbaarheidsindex.py b/geoprob_pipe/visualizations/graphs/betrouwbaarheidsindex.py index 46e2a70e..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 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() From f815be2627f12e42bece029981a23f41747f01e3 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 3 Jun 2026 14:15:30 +0200 Subject: [PATCH 34/53] overview_alphas update met sceario namen en clean-up --- .../visualizations/graphs/__init__.py | 6 +- .../visualizations/graphs/overview_alpha.py | 394 +++++++++++------- 2 files changed, 240 insertions(+), 160 deletions(-) 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/overview_alpha.py b/geoprob_pipe/visualizations/graphs/overview_alpha.py index fefb4fd9..669626be 100644 --- a/geoprob_pipe/visualizations/graphs/overview_alpha.py +++ b/geoprob_pipe/visualizations/graphs/overview_alpha.py @@ -1,183 +1,263 @@ 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: + # 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", + ) + + # for scenario in self.scenarios: + # df_case = self.df_alpha[ + # self.df_alpha["ondergrondscenario_id"] == scenario + # ] + # fig_case = make_subplots( + # rows=len(self.parameters), + # cols=1, + # shared_xaxes=False, + # subplot_titles=self.parameters, + # ) + + # for row_idx, param in enumerate(self.parameters, start=1): + # df_param = df_case[df_case["variable"] == param] + # fig_case.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, + # ), + # row=row_idx, + # col=1, + # ) + # fig_case.update_xaxes( + # showgrid=True, tickangle=90, row=row_idx, col=1 + # ) + # fig_case.update_yaxes( + # showgrid=True, + # title_text=f"{param} [{self.param_units[param]}]" + # + f"
({self.dist_types[param]})", + # row=row_idx, + # col=1, + # ) + + # fig_case.update_layout( + # height=300 * len(self.parameters), + # showlegend=False, + # title=f"Overview of parameters for Scenario {self.scenarios[0]}", + # ) + + From baa8cd4e2077a2a6013047b523fd4e8b83b02fa7 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 3 Jun 2026 14:18:25 +0200 Subject: [PATCH 35/53] overview_alphas documentatie --- .../visualizations/graphs/overview_alpha.py | 52 +++---------------- 1 file changed, 8 insertions(+), 44 deletions(-) diff --git a/geoprob_pipe/visualizations/graphs/overview_alpha.py b/geoprob_pipe/visualizations/graphs/overview_alpha.py index 669626be..bcd2e13f 100644 --- a/geoprob_pipe/visualizations/graphs/overview_alpha.py +++ b/geoprob_pipe/visualizations/graphs/overview_alpha.py @@ -124,6 +124,13 @@ def _collect_data(self): ) 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), @@ -211,53 +218,10 @@ def _export(self): 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", ) - - # for scenario in self.scenarios: - # df_case = self.df_alpha[ - # self.df_alpha["ondergrondscenario_id"] == scenario - # ] - # fig_case = make_subplots( - # rows=len(self.parameters), - # cols=1, - # shared_xaxes=False, - # subplot_titles=self.parameters, - # ) - - # for row_idx, param in enumerate(self.parameters, start=1): - # df_param = df_case[df_case["variable"] == param] - # fig_case.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, - # ), - # row=row_idx, - # col=1, - # ) - # fig_case.update_xaxes( - # showgrid=True, tickangle=90, row=row_idx, col=1 - # ) - # fig_case.update_yaxes( - # showgrid=True, - # title_text=f"{param} [{self.param_units[param]}]" - # + f"
({self.dist_types[param]})", - # row=row_idx, - # col=1, - # ) - - # fig_case.update_layout( - # height=300 * len(self.parameters), - # showlegend=False, - # title=f"Overview of parameters for Scenario {self.scenarios[0]}", - # ) - - From 046bfc74525aee936763171ca4ef34012420ca19 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 3 Jun 2026 15:09:37 +0200 Subject: [PATCH 36/53] views vervangen door copies in icicle --- .../visualizations/graphs/assemblage_icicle.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/geoprob_pipe/visualizations/graphs/assemblage_icicle.py b/geoprob_pipe/visualizations/graphs/assemblage_icicle.py index c3bdcd60..653a17cc 100644 --- a/geoprob_pipe/visualizations/graphs/assemblage_icicle.py +++ b/geoprob_pipe/visualizations/graphs/assemblage_icicle.py @@ -36,8 +36,8 @@ def _setup_df(self): 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"}) @@ -45,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" From 4f5e9b1bfc8299df2df0f7878df50671bf2fd8b1 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 4 Jun 2026 09:12:47 +0200 Subject: [PATCH 37/53] a_vak en delta_length aan excel toegevoegd nog niet uitgelzen --- .../systems/model4a/initial_input.py | 18 ++++++++++++++++++ .../systems/moria/initial_input.py | 18 ++++++++++++++++++ .../calculations/systems/wbi/initial_input.py | 18 ++++++++++++++++++ 3 files changed, 54 insertions(+) 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 46e69f93..8adefc59 100644 --- a/geoprob_pipe/calculations/systems/moria/initial_input.py +++ b/geoprob_pipe/calculations/systems/moria/initial_input.py @@ -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/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" + }, ] From e691c4b03b82ac9532069a8296f48caa33dcc0f7 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 4 Jun 2026 10:02:20 +0200 Subject: [PATCH 38/53] databese table hernoemt --- .../systems/base_objects/base_system_build.py | 2 +- geoprob_pipe/cmd_app/comparisons/__init__.py | 22 +++++++++---------- .../parameter_input/added_input_parameters.py | 12 +++++----- .../parameter_input/expand_input_tables.py | 6 ++--- .../export_input_parameter_excel.py | 2 +- .../initiate_input_excel_tables.py | 12 +++++----- .../input_parameter_figures.py | 6 ++--- .../parameter_input/input_parameter_tables.py | 12 +++++----- .../spatial_joins/couple_objects/base.py | 8 +++---- .../spatial_joins/couple_objects/hrd.py | 4 ++-- .../spatial_joins/couple_objects/shape.py | 14 +++++------- .../cmd_app/spatial_joins/distance.py | 14 ++++++------ geoprob_pipe/cmd_app/spatial_joins/hrd.py | 2 +- geoprob_pipe/cmd_app/spatial_joins/mv_exit.py | 4 ++-- geoprob_pipe/cmd_app/spatial_joins/refline.py | 6 ++--- geoprob_pipe/cmd_app/spatial_joins/utils.py | 16 +++++++------- geoprob_pipe/cmd_app/spatial_joins/vakken.py | 6 ++--- .../spatial_layers/added_dijktraject.py | 4 ++-- .../spatial_layers/added_vakindeling.py | 6 ++--- .../cmd_app/spatial_layers/base_inquiry.py | 12 +++++----- .../cmd_app/spatial_layers/hrd/hrd.py | 2 +- .../spatial_layers/hrd/import_from_hrd.py | 6 ++--- .../hrd/import_from_other_geopackage.py | 8 +++---- .../uittredepunten/alg_walking_circles.py | 2 +- .../uittredepunten/uittredepunten.py | 8 +++---- geoprob_pipe/cmd_app/utils/spatial.py | 4 ++-- geoprob_pipe/input_data/input_data_object.py | 10 ++++----- geoprob_pipe/input_data/traject_normering.py | 2 +- geoprob_pipe/spatial/gdf_beta_limit_states.py | 10 ++++----- geoprob_pipe/visualizations/graphs/hfreq.py | 2 +- .../visualizations/graphs/invloedsfactoren.py | 2 +- 31 files changed, 111 insertions(+), 115 deletions(-) diff --git a/geoprob_pipe/calculations/systems/base_objects/base_system_build.py b/geoprob_pipe/calculations/systems/base_objects/base_system_build.py index 0a8c1f8e..ddc9ccb5 100644 --- a/geoprob_pipe/calculations/systems/base_objects/base_system_build.py +++ b/geoprob_pipe/calculations/systems/base_objects/base_system_build.py @@ -23,7 +23,7 @@ def _gather_variable_correlations(geopackage_filepath: str conn = sqlite3.connect(geopackage_filepath) cursor = conn.cursor() cursor.execute(""" -SELECT parameter_a, parameter_b, correlation FROM correlatie_invoer +SELECT parameter_a, parameter_b, correlation FROM data__correlatie_invoer WHERE correlation <> 0.0; """) rows = cursor.fetchall() # This will be a list of tuples diff --git a/geoprob_pipe/cmd_app/comparisons/__init__.py b/geoprob_pipe/cmd_app/comparisons/__init__.py index 953904e7..c9485fb1 100644 --- a/geoprob_pipe/cmd_app/comparisons/__init__.py +++ b/geoprob_pipe/cmd_app/comparisons/__init__.py @@ -54,41 +54,41 @@ def _load_result_data_from_geopackage(self): """Method om de data te verzamelen uit de opgegeven pakketten. Raises: - ValueError: Als de `beta_limit_states` tabellen niet hetzelfde + ValueError: Als de `result__limit_states` tabellen niet hetzelfde formaat hebben. - ValueError: Als de `beta_scenario` tabellen niet hetzelfde + ValueError: Als de `result__scenario` tabellen niet hetzelfde formaat hebben. - ValueError: Als de `beta_uitredepunten` tabellen niet hetzelfde + ValueError: Als de `result__uitredepunten` tabellen niet hetzelfde formaat hebben. """ conn_1 = sqlite3.connect(self.geopackage_filepath_1) conn_2 = sqlite3.connect(self.geopackage_filepath_2) self.df1_beta_limit_states = pd.read_sql( - "SELECT * FROM beta_limit_states;", conn_1 + "SELECT * FROM result__limit_states;", conn_1 ) self.df2_beta_limit_states = pd.read_sql( - "SELECT * FROM beta_limit_states;", conn_2 + "SELECT * FROM result__limit_states;", conn_2 ) if len(self.df1_beta_limit_states) != len(self.df2_beta_limit_states): raise ValueError("De beta_limit_states tables hebben niet " "hetzelfde formaat") self.df1_beta_scenarios = pd.read_sql( - "SELECT * FROM beta_scenarios_final;", conn_1 + "SELECT * FROM result__scenarios_final;", conn_1 ) self.df2_beta_scenarios = pd.read_sql( - "SELECT * FROM beta_scenarios_final;", conn_2 + "SELECT * FROM result__scenarios_final;", conn_2 ) if len(self.df1_beta_scenarios) != len(self.df2_beta_scenarios): raise ValueError("De beta_scenario tables hebben niet hetzelfde " "formaat") self.df1_beta_uittredepunten = pd.read_sql( - "SELECT * FROM beta_uittredepunten;", conn_1 + "SELECT * FROM result__uittredepunten;", conn_1 ) self.df2_beta_uittredepunten = pd.read_sql( - "SELECT * FROM beta_uittredepunten;", conn_2 + "SELECT * FROM result__uittredepunten;", conn_2 ) if len(self.df1_beta_uittredepunten) != len(self.df2_beta_uittredepunten): raise ValueError("De beta_uittredepunten tables hebben niet " @@ -108,11 +108,11 @@ def _load_uittredepunten_gdf(self): """ self.gdf1_uittredepunten = gpd.read_file( self.geopackage_filepath_1, - layer="beta_uittredepunten" + layer="result__uittredepunten" ) self.gdf2_uittredepunten = gpd.read_file( self.geopackage_filepath_2, - layer="beta_uittredepunten" + layer="result__uittredepunten" ) if len(self.gdf1_uittredepunten) != len(self.gdf2_uittredepunten): raise ValueError("De beta_uittredepunten tables hebben niet " 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 eb25b74a..14b504ca 100644 --- a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py +++ b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py @@ -32,8 +32,8 @@ def possibly_initiatie_input_tables_in_db(app_settings: ApplicationSettings): conn.close() # If already exist - if ("parameter_invoer" in tables_names and - "scenario_invoer" in tables_names and "fragility_values_invoer" in tables_names): + if ("data__excel_parameter_invoer" in tables_names and + "data__scenario_invoer" in tables_names and "data__fragility_values_invoer" in tables_names): # print(f"{BColors.UNDERLINE}Tables already exist in geopackage{BColors.ENDC}") return @@ -252,11 +252,11 @@ def inquire_to_store_input_tables_to_db( if choice == "Ja": conn = sqlite3.connect(app_settings.geopackage_filepath) - tables.df_scenario_invoer.to_sql("scenario_invoer", conn, if_exists="replace", index=False) - tables.df_parameter_invoer.to_sql("parameter_invoer", conn, if_exists="replace", index=False) + tables.df_scenario_invoer.to_sql("data__scenario_invoer", conn, if_exists="replace", index=False) + tables.df_parameter_invoer.to_sql("data__excel_parameter_invoer", conn, if_exists="replace", index=False) tables.df_fragility_values_invoer.to_sql( - "fragility_values_invoer", conn, if_exists="replace", index=False) - tables.df_correlatie_invoer.to_sql("correlatie_invoer", conn, if_exists="replace", index=False) + "data__fragility_values_invoer", conn, if_exists="replace", index=False) + tables.df_correlatie_invoer.to_sql("data__correlatie_invoer", conn, if_exists="replace", index=False) conn.close() print(f"{BColors.UNDERLINE}Tabellen zijn nu opgeslagen in het GeoProb-Pipe-file.{BColors.ENDC}") 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 e3908993..2c4bd341 100644 --- a/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py +++ b/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py @@ -33,7 +33,7 @@ def _gather_hrd_frag_line_from_geopackage(ref: str, geopackage_filepath: str): # Read database conn = sqlite3.connect(geopackage_filepath) df_frag_line: DataFrame = read_sql( - sql=f"SELECT * FROM fragility_values_invoer_hrd WHERE fragility_values_ref = '{ref}' AND kans < 1.0;", + sql=f"SELECT * FROM data__fragility_values_invoer_hrd WHERE fragility_values_ref = '{ref}' AND kans < 1.0;", con=conn) conn.close() @@ -61,7 +61,7 @@ def _gather_hrd_frag_line_from_geopackage(ref: str, geopackage_filepath: str): def _gather_other_freq_line(ref: str, tables: InputParameterTables): """ Gather a freq line that is not from the HRD-database, and not from a .csv-file. It originates from the Excel, - either directly from the Excel, or imported into the 'fragility_values_invoer_hrd'-database table. + either directly from the Excel, or imported into the 'data__fragility_values_invoer_hrd'-database table. :param ref: :param tables: @@ -222,7 +222,7 @@ def _construct_df_identifiers(geopackage_filepath: str, tables: InputParameterTa The identifiers table is a table with unique rows (unique uittredepunt, vak and scenario combo). It is used as a base to explode to input per scenario and uittredepunt. """ - gdf_uittredepunten: GeoDataFrame = read_file(geopackage_filepath, layer="uittredepunten") + gdf_uittredepunten: GeoDataFrame = read_file(geopackage_filepath, layer="geom__uittredepunten") df_identifiers: DataFrame = gdf_uittredepunten[["uittredepunt_id", "vak_id"]] df_scenario_invoer: DataFrame = tables.df_scenario_invoer df_identifiers = df_identifiers.merge(df_scenario_invoer, left_on="vak_id", right_on="vak_id") 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 c9e1a8bc..04e39f30 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 @@ -16,7 +16,7 @@ def join_vak_naam(df: DataFrame, app_settings: ApplicationSettings, ) -> DataFrame: - gdf_vakindeling: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="vakindeling") + gdf_vakindeling: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__vakindeling") gdf_vakindeling = gdf_vakindeling.rename(columns={"naam": "vak_naam", "id": "vak_id"}) df = df.merge(gdf_vakindeling[["vak_naam", "vak_id"]], left_on="vak_id", right_on="vak_id") return df[["vak_id", "vak_naam", "naam", "kans"]] 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 8fb602d2..3eff152e 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 @@ -13,7 +13,7 @@ def push_scenario_invoer_tabel(app_settings: ApplicationSettings): # Genereer tabel input (o.b.v. vakindeling) - gdf_vakindeling: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="vakindeling") + gdf_vakindeling: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__vakindeling") gdf_vakindeling = gdf_vakindeling.sort_values(by=["id"]) df_scenarios = gdf_vakindeling[["id"]].copy() df_scenarios.loc[:, 'naam'] = "scenario1" @@ -24,12 +24,12 @@ def push_scenario_invoer_tabel(app_settings: ApplicationSettings): # Push to geopackage conn = sqlite3.connect(app_settings.geopackage_filepath) - df_scenarios.to_sql("scenario_invoer", conn, if_exists="replace", index=False) + df_scenarios.to_sql("data__scenario_invoer", conn, if_exists="replace", index=False) conn.close() def _check_to_exclude_buitenwaterstand(app_settings: ApplicationSettings, df_parameter_invoer: DataFrame): - gdf_uittredepunten: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten") + gdf_uittredepunten: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__uittredepunten") if "hrd_name" in gdf_uittredepunten.columns: return df_parameter_invoer[df_parameter_invoer["name"] != "buitenwaterstand"] return df_parameter_invoer @@ -75,7 +75,7 @@ def push_parameter_invoer_tabel(app_settings: ApplicationSettings): # Push to geopackage conn = sqlite3.connect(app_settings.geopackage_filepath) - df_parameter_invoer.to_sql("parameter_invoer", conn, if_exists="replace", index=False) + df_parameter_invoer.to_sql("data__excel_parameter_invoer", conn, if_exists="replace", index=False) conn.close() @@ -92,7 +92,7 @@ def push_fragility_values_invoer_tabel(app_settings: ApplicationSettings): # Push to geopackage conn = sqlite3.connect(app_settings.geopackage_filepath) - df_fragility_values_invoer.to_sql("fragility_values_invoer", conn, if_exists="replace", index=False) + df_fragility_values_invoer.to_sql("data__fragility_values_invoer", conn, if_exists="replace", index=False) conn.close() @@ -102,7 +102,7 @@ def push_fragility_values_invoer_tabel(app_settings: ApplicationSettings): def push_correlatie_invoer_tabel(app_settings: ApplicationSettings): # Push to geopackage conn = sqlite3.connect(app_settings.geopackage_filepath) - DF_EMPTY_CORRELATIE_INVOER.to_sql("correlatie_invoer", conn, if_exists="replace", index=False) + DF_EMPTY_CORRELATIE_INVOER.to_sql("data__correlatie_invoer", conn, if_exists="replace", index=False) conn.close() 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 ac3e6a2a..796e82f7 100644 --- a/geoprob_pipe/cmd_app/parameter_input/input_parameter_figures.py +++ b/geoprob_pipe/cmd_app/parameter_input/input_parameter_figures.py @@ -86,17 +86,17 @@ def _gather_data(self): # Lengte traject gpkg_file_path = self.app_settings.geopackage_filepath - gdf: GeoDataFrame = read_file(gpkg_file_path, layer="dijktraject") + gdf: GeoDataFrame = read_file(gpkg_file_path, layer="geom__dijktraject") assert gdf.__len__() == 1 self.traject_length = gdf.iloc[0].geometry.length self.x_max = self.traject_length # Vakindeling dictionary - gdf_vakindeling: GeoDataFrame = read_file(self.app_settings.geopackage_filepath, layer="vakindeling") + gdf_vakindeling: GeoDataFrame = read_file(self.app_settings.geopackage_filepath, layer="geom__vakindeling") self.dict_vakindeling = gdf_vakindeling.set_index('id').to_dict(orient='index') # Uittredepunten dictionary - gdf_uittredepunten: GeoDataFrame = read_file(self.app_settings.geopackage_filepath, layer="uittredepunten") + gdf_uittredepunten: GeoDataFrame = read_file(self.app_settings.geopackage_filepath, layer="geom__uittredepunten") self.dict_uittredepunten = gdf_uittredepunten.set_index('uittredepunt_id').to_dict(orient='index') @staticmethod 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 390a7b80..797bb907 100644 --- a/geoprob_pipe/cmd_app/parameter_input/input_parameter_tables.py +++ b/geoprob_pipe/cmd_app/parameter_input/input_parameter_tables.py @@ -25,7 +25,7 @@ def _load_df_correlatie_invoer_from_geopackage(geopackage_filepath: str) -> Data return DF_EMPTY_CORRELATIE_INVOER # Return db table if exists - df_correlatie_invoer = read_sql("SELECT * FROM correlatie_invoer;", conn) + df_correlatie_invoer = read_sql("SELECT * FROM data__correlatie_invoer;", conn) conn.close() return df_correlatie_invoer @@ -82,11 +82,11 @@ def __init__(self, geopackage_filepath: str, path_to_excel: Optional[str] = None def _load_data_from_geopackage(self, geopackage_filepath: str): conn = sqlite3.connect(geopackage_filepath) - df_scenario_invoer = read_sql("SELECT * FROM scenario_invoer;", conn) + df_scenario_invoer = read_sql("SELECT * FROM data__scenario_invoer;", conn) self.df_scenario_invoer = df_scenario_invoer[["vak_id", "naam", "kans"]] - self.df_parameter_invoer = read_sql("SELECT * FROM parameter_invoer;", conn) - self.df_gis_join_parameter_invoer = read_sql("SELECT * FROM gis_join_parameter_invoer;", conn) - self.df_fragility_values_invoer = read_sql("SELECT * FROM fragility_values_invoer;", conn) + self.df_parameter_invoer = read_sql("SELECT * FROM data__excel_parameter_invoer;", conn) + self.df_gis_join_parameter_invoer = read_sql("SELECT * FROM data__gis_parameter_invoer;", conn) + self.df_fragility_values_invoer = read_sql("SELECT * FROM data__fragility_values_invoer;", conn) self.df_correlatie_invoer = _load_df_correlatie_invoer_from_geopackage(geopackage_filepath=geopackage_filepath) conn.close() @@ -94,7 +94,7 @@ def _load_data_from_excel(self, path_to_excel: str, geopackage_filepath: str): self.df_scenario_invoer = read_excel(path_to_excel, sheet_name="Scenario invoer", header=2) self.df_parameter_invoer = read_excel(path_to_excel, sheet_name="Parameter invoer", header=3) conn = sqlite3.connect(geopackage_filepath) - self.df_gis_join_parameter_invoer = read_sql("SELECT * FROM gis_join_parameter_invoer;", conn) + self.df_gis_join_parameter_invoer = read_sql("SELECT * FROM data__gis_parameter_invoer;", conn) conn.close() self.df_fragility_values_invoer = read_excel(path_to_excel, sheet_name="Fragility values", header=3) self.df_correlatie_invoer = read_excel(path_to_excel, sheet_name="Correlatie invoer", header=3) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py index ab889d7e..6d470234 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py @@ -80,7 +80,7 @@ def _upsert_to_gpkg(self, df: pd.DataFrame): cursor = conn.cursor() cursor.execute( """ - CREATE TABLE IF NOT EXISTS gis_join_parameter_invoer ( + CREATE TABLE IF NOT EXISTS data__gis_parameter_invoer ( parameter TEXT, scope TEXT, scope_referentie INTEGER, @@ -103,7 +103,7 @@ def _upsert_to_gpkg(self, df: pd.DataFrame): # UPSERT naar tabel cursor.executemany( f""" - INSERT INTO gis_join_parameter_invoer ( + INSERT INTO data__gis_parameter_invoer ( parameter, scope, scope_referentie, @@ -137,9 +137,9 @@ def _upsert_to_gpkg(self, df: pd.DataFrame): # UPSERT naar gpkg_contents, vereist in gpkg om leesbaar te zijn # voor GIS software content = ( - "gis_join_parameter_invoer", + "data__gis_parameter_invoer", "attributes", - "gis_join_parameter_invoer", + "data__gis_parameter_invoer", "", datetime.datetime.now(), 0, diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py index 10dbd500..f0c4924c 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/hrd.py @@ -33,10 +33,10 @@ def couple_exit_points(self) -> None: """ # Read uittredepunten gdf_exit_points: gpd.GeoDataFrame = gpd.read_file( - self.app_settings.geopackage_filepath, layer="uittredepunten" + self.app_settings.geopackage_filepath, layer="geom__uittredepunten" ) gdf_hrd: gpd.GeoDataFrame = gpd.read_file( - self.app_settings.geopackage_filepath, layer="hrd_locaties" + self.app_settings.geopackage_filepath, layer="geom__hrd_locaties" ) join_df = gdf_exit_points.sjoin_nearest(gdf_hrd, how="left") df_to_add = self._create_df_hrd(join_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 index faa4d382..37cc4bed 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/shape.py @@ -50,13 +50,13 @@ def couple_exit_points(self): """ # Read uittredepunten self.gdf_exit_points: gpd.GeoDataFrame = gpd.read_file( - self.app_settings.geopackage_filepath, layer="uittredepunten" + self.app_settings.geopackage_filepath, layer="geom__uittredepunten" ) self.param_tables = [ table for table in self.tables_names - if table.split("__")[0] == self.param + if table.strip("geom_").split("__")[0] == self.param ] if len(self.param_tables) == 0: @@ -78,7 +78,7 @@ def _add_single_layer(self): ruimtelijke scenarios zijn voor de parameter. """ gdf_parameter: gpd.GeoDataFrame = gpd.read_file( - self.app_settings.geopackage_filepath, layer=f"{self.param}" + self.app_settings.geopackage_filepath, layer=f"geom__{self.param}" ) self._check_shape(gdf_parameter) @@ -90,13 +90,9 @@ def _add_multiple_layers(self): for layer in self.param_tables: gdf_parameter: gpd.GeoDataFrame = gpd.read_file( self.app_settings.geopackage_filepath, - layer=layer, + layer=f"geom__{layer}", ) - if len(layer.split("__")) == 2: - scenario = layer.split("__")[1] - else: - scenario = "" - + scenario = layer.split("__")[1] self._check_shape(gdf_parameter, scenario) def _check_shape(self, gdf: gpd.GeoDataFrame, scenario: str = ""): diff --git a/geoprob_pipe/cmd_app/spatial_joins/distance.py b/geoprob_pipe/cmd_app/spatial_joins/distance.py index 0a059bb4..13cb072f 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/distance.py +++ b/geoprob_pipe/cmd_app/spatial_joins/distance.py @@ -30,7 +30,7 @@ def coupled_distances_to_uittredepunten( # Lees uittredepunten uit gpkg gdf_exit_points: gpd.GeoDataFrame = gpd.read_file( - app_settings.geopackage_filepath, layer="uittredepunten" + app_settings.geopackage_filepath, layer="geom__uittredepunten" ) # Distance to intredelijn @@ -39,9 +39,9 @@ def coupled_distances_to_uittredepunten( # 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 + if "geom__intredelijn" in layers: # Een intredelijn voor alle scenarios gdf_intredelijnen: gpd.GeoDataFrame = gpd.read_file( - app_settings.geopackage_filepath, layer="intredelijn" + app_settings.geopackage_filepath, layer="geom__intredelijn" ) gdf_exit_points["afstand_intredelijn"] = ( gdf_exit_points.geometry.apply( @@ -59,7 +59,7 @@ def coupled_distances_to_uittredepunten( ).couple_exit_points() # Intrede lijn per scenario - if len(layer.split("__")) == 2 and "intredelijn" in layer.split("__")[0]: + if len(layer.split("__")) == 3 and "intredelijn" in layer.split("__"): gdf_intredelijnen: gpd.GeoDataFrame = gpd.read_file( app_settings.geopackage_filepath, layer=layer ) @@ -78,11 +78,11 @@ def coupled_distances_to_uittredepunten( ) DistCouple( app_settings, "L_intrede", df_l_intrede - ).couple_exit_points(scenario=layer.split("__")[1]) + ).couple_exit_points(scenario=layer.split("__")[2]) # Distance to buitenteenlijn gdf_buitenteenlijnen: gpd.GeoDataFrame = gpd.read_file( - app_settings.geopackage_filepath, layer="buitenteenlijn" + app_settings.geopackage_filepath, layer="geom__buitenteenlijn" ) gdf_exit_points["afstand_buitenteenlijn"] = gdf_exit_points.geometry.apply( lambda pnt: round(gdf_buitenteenlijnen.distance(pnt).min(), 1) @@ -96,7 +96,7 @@ def coupled_distances_to_uittredepunten( # Distance to binnenteenlijn gdf_binnenteenlijn: gpd.GeoDataFrame = gpd.read_file( - app_settings.geopackage_filepath, layer="binnenteenlijn" + app_settings.geopackage_filepath, layer="geom__binnenteenlijn" ) gdf_exit_points["afstand_binnenteenlijn"] = gdf_exit_points.geometry.apply( lambda pnt: round(gdf_binnenteenlijn.distance(pnt).min(), 1) diff --git a/geoprob_pipe/cmd_app/spatial_joins/hrd.py b/geoprob_pipe/cmd_app/spatial_joins/hrd.py index f375bbd9..7fd0a8c4 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/hrd.py +++ b/geoprob_pipe/cmd_app/spatial_joins/hrd.py @@ -25,7 +25,7 @@ def coupled_hrd_to_uittredepunten(app_settings: ApplicationSettings) -> bool: layers = fiona.listlayers(app_settings.geopackage_filepath) - if "hrd_locaties" not in layers: + if "geom__hrd_locaties" not in layers: return True # Geen Hydra-locatie geïmporteerd, dan ook niks koppelen. HRDCouple(app_settings).couple_exit_points() diff --git a/geoprob_pipe/cmd_app/spatial_joins/mv_exit.py b/geoprob_pipe/cmd_app/spatial_joins/mv_exit.py index d1508d32..14f827de 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/mv_exit.py +++ b/geoprob_pipe/cmd_app/spatial_joins/mv_exit.py @@ -12,12 +12,12 @@ def coupled_mv_exit_to_gis_parameter_invoer_table(app_settings: ApplicationSetti # Check if already added, if so skip conn = sqlite3.connect(app_settings.geopackage_filepath) - df_existing = read_sql_query("SELECT * FROM gis_join_parameter_invoer;", conn) + df_existing = read_sql_query("SELECT * FROM data__gis_parameter_invoer;", conn) if "mv_exit" in df_existing['parameter'].unique(): return True # Getting necessary GeoDataframes - gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten") + gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__uittredepunten") # Append to new version of geo-spatial storage df_to_append: DataFrame = gdf_exit_points[["mv_exit", "uittredepunt_id"]] diff --git a/geoprob_pipe/cmd_app/spatial_joins/refline.py b/geoprob_pipe/cmd_app/spatial_joins/refline.py index 05dee1eb..dec75581 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/refline.py +++ b/geoprob_pipe/cmd_app/spatial_joins/refline.py @@ -13,14 +13,14 @@ def coupled_uittredepunten_to_refline(app_settings: ApplicationSettings) -> bool functie dat automatisch. """ # Read uittredepunten - gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten") + gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__uittredepunten") # Check if already added if "metrering" in gdf_exit_points.columns and "afstand_reflijn" in gdf_exit_points.columns: print(BColors.OKBLUE, f"✔ Afstand en metrering tot reflijn al gekoppeld aan uittredepunten.", BColors.ENDC) return True # Assuming already added - gdf_dijktraject: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="dijktraject") + gdf_dijktraject: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__dijktraject") gdf_dijktraject_geom = gdf_dijktraject.iloc[0].geometry if isinstance(gdf_dijktraject_geom, MultiLineString): assert gdf_dijktraject_geom.geoms.__len__() == 1 @@ -41,7 +41,7 @@ def coupled_uittredepunten_to_refline(app_settings: ApplicationSettings) -> bool gdf_exit_points['uittredepunt_id'] = range(1, len(gdf_exit_points) + 1) # Store back in geopackage - gdf_exit_points.to_file(Path(app_settings.geopackage_filepath), layer="uittredepunten", driver="GPKG") + gdf_exit_points.to_file(Path(app_settings.geopackage_filepath), layer="geom__uittredepunten", driver="GPKG") print(BColors.OKBLUE, f"✅ Afstand en metrering tot reflijn zijn nu gekoppeld aan de uittredepunten.", BColors.ENDC) return True diff --git a/geoprob_pipe/cmd_app/spatial_joins/utils.py b/geoprob_pipe/cmd_app/spatial_joins/utils.py index e1e2f714..21dc51d8 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/utils.py +++ b/geoprob_pipe/cmd_app/spatial_joins/utils.py @@ -38,13 +38,13 @@ def append_to_gis_join_parameter_invoer_table(df_sjoin: DataFrame, parameter_nam tables_names = [row[0] for row in cursor.fetchall()] # If gis_join-table is non-existent yet - if "gis_join_parameter_invoer" not in tables_names: - df_to_append.to_sql("gis_join_parameter_invoer", conn, if_exists="replace", index=False) + if "data__gis_parameter_invoer" not in tables_names: + df_to_append.to_sql("data__gis_parameter_invoer", conn, if_exists="replace", index=False) return # If polderpeil not yet in gis_join-table - df_existing = read_sql_query("SELECT * FROM gis_join_parameter_invoer;", conn) + df_existing = read_sql_query("SELECT * FROM data__gis_parameter_invoer;", conn) if parameter_name not in df_existing['parameter'].unique(): - df_to_append.to_sql("gis_join_parameter_invoer", conn, if_exists="append", index=False) + df_to_append.to_sql("data__gis_parameter_invoer", conn, if_exists="append", index=False) return raise ValueError # Should not have come here. Parameter should already be supplied, and thus user should not have been able to @@ -86,13 +86,13 @@ def append_hrd_to_gis_join_parameter_invoer_table(df_sjoin: DataFrame, geopackag tables_names = [row[0] for row in cursor.fetchall()] # If gis_join-table is non-existent yet - if "gis_join_parameter_invoer" not in tables_names: - df_to_append.to_sql("gis_join_parameter_invoer", conn, if_exists="replace", index=False) + if "data__gis_parameter_invoer" not in tables_names: + df_to_append.to_sql("data__gis_parameter_invoer", conn, if_exists="replace", index=False) return # If polderpeil not yet in gis_join-table - df_existing = read_sql_query("SELECT * FROM gis_join_parameter_invoer;", conn) + df_existing = read_sql_query("SELECT * FROM data__gis_parameter_invoer;", conn) if "polderpeil" not in df_existing['parameter'].unique(): - df_to_append.to_sql("gis_join_parameter_invoer", conn, if_exists="append", index=False) + df_to_append.to_sql("data__gis_parameter_invoer", conn, if_exists="append", index=False) return raise ValueError # Should not have come here. Parameter should already be supplied, and thus user should not have been able to diff --git a/geoprob_pipe/cmd_app/spatial_joins/vakken.py b/geoprob_pipe/cmd_app/spatial_joins/vakken.py index 4f418e8a..194db135 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/vakken.py +++ b/geoprob_pipe/cmd_app/spatial_joins/vakken.py @@ -10,7 +10,7 @@ def coupled_uittredepunten_to_vakken(app_settings: ApplicationSettings) -> bool: # Read uittredepunten - gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten") + gdf_exit_points: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__uittredepunten") # Check if already added if "vak_id" in gdf_exit_points.columns: @@ -18,7 +18,7 @@ def coupled_uittredepunten_to_vakken(app_settings: ApplicationSettings) -> bool: return True # Assuming already added # Spatial analyses - gdf_vakindeling: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="vakindeling") + gdf_vakindeling: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__vakindeling") gdf_exit_points_with_vakken = gdf_exit_points.sjoin_nearest( gdf_vakindeling[['geometry', 'id']], how='left', distance_col='distance') @@ -29,6 +29,6 @@ def coupled_uittredepunten_to_vakken(app_settings: ApplicationSettings) -> bool: gdf_new_exit_points = gdf_new_exit_points.rename(columns={"id": "vak_id"}) # Store back in geopackage - gdf_new_exit_points.to_file(Path(app_settings.geopackage_filepath), layer="uittredepunten", driver="GPKG") + gdf_new_exit_points.to_file(Path(app_settings.geopackage_filepath), layer="geom__uittredepunten", driver="GPKG") print(BColors.OKBLUE, f"✅ Vakken zijn nu gekoppeld aan de uittredepunten.", BColors.ENDC) return True diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py b/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py index af304a8a..60e4505e 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py @@ -178,7 +178,7 @@ def specify_single_trajectory(app_settings: ApplicationSettings, gdf: GeoDataFra column_name: "traject_naam", gdf.geometry.name: "geometry", }) - gdf.to_file(app_settings.geopackage_filepath, layer="dijktraject", driver="GPKG") + gdf.to_file(app_settings.geopackage_filepath, layer="geom__dijktraject", driver="GPKG") print(BColors.OKBLUE, "✅ Trajectlijn toegevoegd.", BColors.ENDC) return @@ -211,6 +211,6 @@ def specify_single_trajectory(app_settings: ApplicationSettings, gdf: GeoDataFra column_name: "traject_naam", gdf.geometry.name: "geometry", }) - gdf.to_file(app_settings.geopackage_filepath, layer="dijktraject", driver="GPKG") + gdf.to_file(app_settings.geopackage_filepath, layer="geom__dijktraject", driver="GPKG") print(BColors.OKBLUE, "✅ Trajectlijn toegevoegd.", BColors.ENDC) return diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py index 70115312..ed01f371 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py @@ -29,7 +29,7 @@ def added_vakindeling(app_settings: ApplicationSettings) -> bool: def check_validity_vakindeling(app_settings: ApplicationSettings): - gdf_dijktraject: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="dijktraject") + gdf_dijktraject: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__dijktraject") gdf_dijktraject_geom = gdf_dijktraject.iloc[0].geometry if isinstance(gdf_dijktraject_geom, MultiLineString): assert gdf_dijktraject_geom.geoms.__len__() == 1 @@ -41,7 +41,7 @@ def check_validity_vakindeling(app_settings: ApplicationSettings): f"developer.'") dijktraject_length = round(ls_dijktraject.length, 2) - gdf_vakindeling: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="vakindeling") + gdf_vakindeling: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__vakindeling") vakindeling_geometries = gdf_vakindeling.geometry.tolist() vakindeling_total_length = round(sum([geom.length for geom in vakindeling_geometries]), 2) @@ -328,5 +328,5 @@ def align_vak_shp_to_dijktraject( # Add to geopackage gdf_new_vakindeling.to_file( Path(app_settings.geopackage_filepath), - layer="vakindeling", driver="GPKG") + layer="geom__vakindeling", driver="GPKG") 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 index 070a9a61..b3792151 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py +++ b/geoprob_pipe/cmd_app/spatial_layers/base_inquiry.py @@ -308,7 +308,7 @@ def _add_to_gpkg(self, gdf: gpd.GeoDataFrame) -> bool: gdf_to_add = gdf[["geometry"]] gdf_to_add.to_file( self.app_settings.geopackage_filepath, - layer=f"{self.param}", + layer=f"geom__{self.param}", driver="GPKG", ) return True @@ -440,7 +440,7 @@ def _add_with_separate_geometry(self, gdf: gpd.GeoDataFrame) -> bool: gdf_to_add.to_file( self.app_settings.geopackage_filepath, - layer=f"{self.param}__{scenario}", + layer=f"geom__{self.param}__{scenario}", driver="GPKG", ) @@ -469,7 +469,7 @@ def _add_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: gdf_to_add.to_file( self.app_settings.geopackage_filepath, - layer=f"{self.param}", + layer=f"geom__{self.param}", driver="GPKG", ) @@ -525,7 +525,7 @@ def _add_with_affixes(self, gdf: gpd.GeoDataFrame) -> bool: gdf_to_add.to_file( self.app_settings.geopackage_filepath, - layer=f"{self.param}__{scenario}", + layer=f"geom__{self.param}__{scenario}", driver="GPKG", ) @@ -567,14 +567,14 @@ def _add_separate_with_suffix(self, gdf: gpd.GeoDataFrame) -> bool: if scenario is None: gdf_to_add.to_file( self.app_settings.geopackage_filepath, - layer=f"{self.param}", + layer=f"geom__{self.param}", driver="GPKG", ) else: gdf_to_add.to_file( self.app_settings.geopackage_filepath, - layer=f"{self.param}__{scenario}", + layer=f"geom__{self.param}__{scenario}", driver="GPKG", ) diff --git a/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py b/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py index 139aaec5..fc3ae11c 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py +++ b/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py @@ -45,7 +45,7 @@ def _hrd_data_imported(app_settings: ApplicationSettings) -> bool: # Check if locations shape already added layers = fiona.listlayers(app_settings.geopackage_filepath) - if "hrd_locaties" not in layers: + if "geom__hrd_locaties" not in layers: return False # Check overschrijdingsfrequentielijnen already added 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 9e3928f3..109716f1 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 @@ -87,7 +87,7 @@ def _add_hrd_locations_to_database(app_settings: ApplicationSettings, hrd_dir: s }) gdf = GeoDataFrame(hrd_location_rows, columns=['location_name', 'geometry'], crs='EPSG:28992') - gdf.to_file(Path(app_settings.geopackage_filepath), layer="hrd_locaties", driver="GPKG") + gdf.to_file(Path(app_settings.geopackage_filepath), layer="geom__hrd_locaties", driver="GPKG") print(BColors.OKBLUE, f"✅ HRD-locatie punten toegevoegd aan GeoProb-Pipe GeoPackage.", BColors.ENDC) @@ -96,7 +96,7 @@ def _add_hrd_overschrijdingsfrequentielijnen(hrd_dir: str, app_settings: Applica f"GeoPackage.{BColors.ENDC}") hrd = pydra.HRDatabase(hrd_file_path(hrd_dir=hrd_dir)) - gdf_locations: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="hrd_locaties") + gdf_locations: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__hrd_locaties") location_names = gdf_locations['location_name'].unique().tolist() fl = pydra.ExceedanceFrequencyLine("h") dfs: List[DataFrame] = [] @@ -132,7 +132,7 @@ def _add_hrd_overschrijdingsfrequentielijnen(hrd_dir: str, app_settings: Applica if dfs.__len__() > 0: df = concat(dfs, ignore_index=True) conn = sqlite3.connect(app_settings.geopackage_filepath) - df.to_sql("fragility_values_invoer_hrd", conn, if_exists="replace", index=False) + df.to_sql("data__fragility_values_invoer_hrd", conn, if_exists="replace", index=False) conn.close() print(BColors.OKBLUE, f"✅ HRD-overschrijdingsfrequentielijnen toegevoegd aan GeoProb-Pipe " 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 ba260cca..eafdf87f 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 @@ -36,18 +36,18 @@ def _ask_for_other_geopackage_file_path() -> str: def _add_hrd_locations_to_database(other_gpkg_path: str, app_settings: ApplicationSettings): - gdf_locations: GeoDataFrame = read_file(other_gpkg_path, layer="hrd_locaties") - gdf_locations.to_file(Path(app_settings.geopackage_filepath), layer="hrd_locaties", driver="GPKG") + gdf_locations: GeoDataFrame = read_file(other_gpkg_path, layer="geom__hrd_locaties") + gdf_locations.to_file(Path(app_settings.geopackage_filepath), layer="geom__hrd_locaties", driver="GPKG") print(BColors.OKBLUE, f"✅ HRD-locatie punten toegevoegd aan GeoProb-Pipe GeoPackage.", BColors.ENDC) def _add_hrd_overschrijdingsfrequentielijnen(other_gpkg_path: str, app_settings: ApplicationSettings): conn = sqlite3.connect(other_gpkg_path) - df: DataFrame = read_sql_query("SELECT * FROM fragility_values_invoer_hrd;", conn) + df: DataFrame = read_sql_query("SELECT * FROM data__fragility_values_invoer_hrd;", conn) conn.close() conn = sqlite3.connect(app_settings.geopackage_filepath) - df.to_sql("fragility_values_invoer_hrd", conn, if_exists="replace", index=False) + df.to_sql("data__fragility_values_invoer_hrd", conn, if_exists="replace", index=False) conn.close() print(BColors.OKBLUE, f"✅ HRD-overschrijdingsfrequentielijnen toegevoegd aan GeoProb-Pipe " 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 22057cdf..269959f9 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 @@ -196,5 +196,5 @@ def algorithm_walking_circles(app_settings: ApplicationSettings): gdf_to_add = gdf_proposed_uittredepunten[["geometry", "min_val"]] gdf_to_add = gdf_to_add.rename(columns={"min_val": "mv_exit"}) - gdf_to_add.to_file(app_settings.geopackage_filepath, layer="uittredepunten", driver="GPKG") + gdf_to_add.to_file(app_settings.geopackage_filepath, layer="geom__uittredepunten", driver="GPKG") print(BColors.OKBLUE, f"✅ Uittredepunten toegevoegd.", BColors.ENDC) diff --git a/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/uittredepunten.py b/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/uittredepunten.py index c320927a..d1dc7ac5 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/uittredepunten.py +++ b/geoprob_pipe/cmd_app/spatial_layers/uittredepunten/uittredepunten.py @@ -16,11 +16,11 @@ def added_uittredepunten(app_settings: ApplicationSettings) -> bool: layers = fiona.listlayers(app_settings.geopackage_filepath) - if "uittredepunten" not in layers: + if "geom__uittredepunten" not in layers: define_method_of_adding_uittredepunten(app_settings) return True - gdf: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="uittredepunten") + gdf: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__uittredepunten") if gdf.__len__() == 0: define_method_of_adding_uittredepunten(app_settings) return True @@ -239,7 +239,7 @@ def specify_column_with_maaiveld_niveau(app_settings: ApplicationSettings, gdf: elif column_name == "n.a.": gdf_to_add = gdf[["geometry"]] gdf_to_add["mv_exit"] = -999.9 - gdf_to_add.to_file(app_settings.geopackage_filepath, layer="uittredepunten", driver="GPKG") + gdf_to_add.to_file(app_settings.geopackage_filepath, layer="geom__uittredepunten", driver="GPKG") print(BColors.OKBLUE, f"✅ Uittredepunten toegevoegd.", BColors.ENDC) return elif column_name not in column_names: @@ -252,5 +252,5 @@ def specify_column_with_maaiveld_niveau(app_settings: ApplicationSettings, gdf: gdf_to_add = gdf[["geometry", column_name]] # No uittredepunt id yet. This will be set when the metering is determined. gdf_to_add = gdf_to_add.rename(columns={column_name: "mv_exit"}) - gdf_to_add.to_file(app_settings.geopackage_filepath, layer="uittredepunten", driver="GPKG") + gdf_to_add.to_file(app_settings.geopackage_filepath, layer="geom__uittredepunten", driver="GPKG") print(BColors.OKBLUE, f"✅ Uittredepunten toegevoegd.", BColors.ENDC) diff --git a/geoprob_pipe/cmd_app/utils/spatial.py b/geoprob_pipe/cmd_app/utils/spatial.py index 4d1f07a0..09e373c0 100644 --- a/geoprob_pipe/cmd_app/utils/spatial.py +++ b/geoprob_pipe/cmd_app/utils/spatial.py @@ -8,7 +8,7 @@ def load_dijktraject_linestring(app_settings: ApplicationSettings) -> LineString: - gdf_dijktraject: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="dijktraject") + gdf_dijktraject: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__dijktraject") gdf_dijktraject_geom = gdf_dijktraject.iloc[0].geometry if isinstance(gdf_dijktraject_geom, MultiLineString): assert gdf_dijktraject_geom.geoms.__len__() == 1 @@ -22,5 +22,5 @@ def load_dijktraject_linestring(app_settings: ApplicationSettings) -> LineString def load_hydra_nl_as_multipoint(app_settings: ApplicationSettings) -> MultiPoint: - gdf_hrd_locaties: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="hrd_locaties") + gdf_hrd_locaties: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__hrd_locaties") return MultiPoint(gdf_hrd_locaties.geometry.values) diff --git a/geoprob_pipe/input_data/input_data_object.py b/geoprob_pipe/input_data/input_data_object.py index 84ca0ff2..f6558fcd 100644 --- a/geoprob_pipe/input_data/input_data_object.py +++ b/geoprob_pipe/input_data/input_data_object.py @@ -24,7 +24,7 @@ class Uittredepunten: def __init__(self, app_settings: ApplicationSettings): self.app_settings: ApplicationSettings = app_settings self.gdf: GeoDataFrame = read_file(app_settings.geopackage_filepath, - layer="uittredepunten") + layer="geom__uittredepunten") def uittredepunt(self, uittredepunt_id: int): row = self.gdf.loc[ @@ -57,7 +57,7 @@ def __init__(self, app_settings: ApplicationSettings): def _query_scenarios(self) -> DataFrame: conn = sqlite3.connect(self.app_settings.geopackage_filepath) - df_scenario_invoer = read_sql("SELECT * FROM scenario_invoer;", conn) + df_scenario_invoer = read_sql("SELECT * FROM data__scenario_invoer;", conn) df_scenario_invoer = df_scenario_invoer[["vak_id", "naam", "kans"]] conn.close() return df_scenario_invoer @@ -75,14 +75,14 @@ class HydraNLData: def __init__(self, app_settings: ApplicationSettings): self.app_settings: ApplicationSettings = app_settings self.gdf_locations: GeoDataFrame = read_file( - app_settings.geopackage_filepath, layer="hrd_locaties") + app_settings.geopackage_filepath, layer="geom__hrd_locaties") def hrd_fragility_values(self, ref: str) -> List[FragilityValue]: # Read from geopackage conn = sqlite3.connect(self.app_settings.geopackage_filepath) df_frag_line = read_sql( - sql=f"SELECT * FROM fragility_values_invoer_hrd WHERE fragility_values_ref = '{ref}' AND kans < 1.0;", + sql=f"SELECT * FROM data__fragility_values_invoer_hrd WHERE fragility_values_ref = '{ref}' AND kans < 1.0;", con=conn) conn.close() @@ -120,7 +120,7 @@ class Vakken: def __init__(self, app_settings: ApplicationSettings): self.app_settings: ApplicationSettings = app_settings self.gdf: GeoDataFrame = read_file(app_settings.geopackage_filepath, - layer="vakindeling") + layer="geom__vakindeling") class InputData: diff --git a/geoprob_pipe/input_data/traject_normering.py b/geoprob_pipe/input_data/traject_normering.py index 1d43f397..d001122f 100644 --- a/geoprob_pipe/input_data/traject_normering.py +++ b/geoprob_pipe/input_data/traject_normering.py @@ -24,7 +24,7 @@ def _data_from_metadata_table(app_settings: ApplicationSettings) -> Tuple[str, b def _get_traject_length(app_settings: ApplicationSettings) -> float: - gdf_dijktraject: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="dijktraject") + gdf_dijktraject: GeoDataFrame = read_file(app_settings.geopackage_filepath, layer="geom__dijktraject") gdf_dijktraject_geom = gdf_dijktraject.iloc[0].geometry if isinstance(gdf_dijktraject_geom, MultiLineString): assert gdf_dijktraject_geom.geoms.__len__() == 1 diff --git a/geoprob_pipe/spatial/gdf_beta_limit_states.py b/geoprob_pipe/spatial/gdf_beta_limit_states.py index 2638487c..552cf638 100644 --- a/geoprob_pipe/spatial/gdf_beta_limit_states.py +++ b/geoprob_pipe/spatial/gdf_beta_limit_states.py @@ -22,7 +22,7 @@ def get_gdf_beta_limit_states(geoprob_pipe: GeoProbPipe, export: bool = False) - gdf = _get_uittredepunten_gdf_beta_results(geoprob_pipe, geoprob_pipe.results.df_beta_limit_states) if export: gdf.to_file(geoprob_pipe.input_data.app_settings.geopackage_filepath, - layer="beta_limit_states", driver="GPKG", mode="w") + layer="result__limit_states", driver="GPKG", mode="w") return gdf @@ -31,7 +31,7 @@ def get_gdf_beta_scenarios_final(geoprob_pipe: GeoProbPipe, export: bool = False if export: gdf.to_file( geoprob_pipe.input_data.app_settings.geopackage_filepath, - layer="beta_scenarios_final", driver="GPKG", mode="w") + layer="result__scenarios_final", driver="GPKG", mode="w") return gdf @@ -40,7 +40,7 @@ def get_gdf_beta_scenarios_cp(geoprob_pipe: GeoProbPipe, export: bool = False) - if export: gdf.to_file( geoprob_pipe.input_data.app_settings.geopackage_filepath, - layer="beta_scenarios_cp", driver="GPKG", mode="w") + layer="result__scenarios_cp", driver="GPKG", mode="w") return gdf @@ -49,7 +49,7 @@ def get_gdf_beta_scenarios_rp(geoprob_pipe: GeoProbPipe, export: bool = False) - if export: gdf.to_file( geoprob_pipe.input_data.app_settings.geopackage_filepath, - layer="beta_scenarios_rp", driver="GPKG", mode="w") + layer="result__scenarios_rp", driver="GPKG", mode="w") return gdf @@ -58,5 +58,5 @@ def get_gdf_beta_uittredepunten(geoprob_pipe: GeoProbPipe, export: bool = False) if export: gdf.to_file( geoprob_pipe.input_data.app_settings.geopackage_filepath, - layer="beta_uittredepunten", driver="GPKG", mode="w") + layer="result__uittredepunten", driver="GPKG", mode="w") return gdf diff --git a/geoprob_pipe/visualizations/graphs/hfreq.py b/geoprob_pipe/visualizations/graphs/hfreq.py index b323e873..d7d334f1 100644 --- a/geoprob_pipe/visualizations/graphs/hfreq.py +++ b/geoprob_pipe/visualizations/graphs/hfreq.py @@ -21,7 +21,7 @@ def __init__(self, geoprob_pipe: GeoProbPipe, export: bool = False): # Check if there are fragility curves referenced: conn = sqlite3.connect(geoprob_pipe.input_data.app_settings.geopackage_filepath) - df_parameter_invoer = read_sql("SELECT * FROM parameter_invoer;", conn) + df_parameter_invoer = read_sql("SELECT * FROM data__excel_parameter_invoer;", conn) fragility_values_refs = df_parameter_invoer['fragility_values_ref'].unique() conn.close() if (fragility_values_refs.__len__() == 0 or diff --git a/geoprob_pipe/visualizations/graphs/invloedsfactoren.py b/geoprob_pipe/visualizations/graphs/invloedsfactoren.py index 3c012a2d..63cc04a0 100644 --- a/geoprob_pipe/visualizations/graphs/invloedsfactoren.py +++ b/geoprob_pipe/visualizations/graphs/invloedsfactoren.py @@ -125,7 +125,7 @@ def _get_data(geoprob_pipe: GeoProbPipe) -> DataFrame: def _plot_data(geoprob_pipe: GeoProbPipe, df_invloedsfactoren: DataFrame) -> Figure: fig = Figure() gdf_vakindeling: GeoDataFrame = read_file( - geoprob_pipe.input_data.app_settings.geopackage_filepath, layer="vakindeling") + geoprob_pipe.input_data.app_settings.geopackage_filepath, layer="geom__vakindeling") vakken = {row['id']: row["naam"] for index, row in gdf_vakindeling.iterrows()} picked_colors = {} added_to_legend = [] From d46357556eb57d0bad5de8a8fdcfc4523c6525c9 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 4 Jun 2026 10:48:40 +0200 Subject: [PATCH 39/53] database uitgebreidt --- .../parameter_input/added_input_parameters.py | 18 +++-- geoprob_pipe/results/__init__.py | 65 +++++++++++++++---- geoprob_pipe/spatial/__init__.py | 16 +++-- geoprob_pipe/utils/sql_contents.py | 34 ++++++++++ 4 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 geoprob_pipe/utils/sql_contents.py 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 14b504ca..f3cb1899 100644 --- a/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py +++ b/geoprob_pipe/cmd_app/parameter_input/added_input_parameters.py @@ -17,6 +17,7 @@ from .input_parameter_tables import InputParameterTables from .update_ruimtelijke_invoer import SpatialUpdateMenu from geoprob_pipe.cmd_app.utils.batch_input import update_batch_metadata +from geoprob_pipe.utils.sql_contents import write_dfs_to_gpkg if TYPE_CHECKING: from geoprob_pipe.cmd_app.cmd import ApplicationSettings @@ -251,13 +252,20 @@ def inquire_to_store_input_tables_to_db( ).execute() if choice == "Ja": + conn = sqlite3.connect(app_settings.geopackage_filepath) - tables.df_scenario_invoer.to_sql("data__scenario_invoer", conn, if_exists="replace", index=False) - tables.df_parameter_invoer.to_sql("data__excel_parameter_invoer", conn, if_exists="replace", index=False) - tables.df_fragility_values_invoer.to_sql( - "data__fragility_values_invoer", conn, if_exists="replace", index=False) - tables.df_correlatie_invoer.to_sql("data__correlatie_invoer", conn, if_exists="replace", index=False) + + table_dict = { + "data__scenario_invoer": tables.df_scenario_invoer, + "data__excel_parameter_invoer": tables.df_parameter_invoer, + "data__fragility_values_invoer": tables.df_fragility_values_invoer, + "data__correlatie_invoer": tables.df_correlatie_invoer + } + + write_dfs_to_gpkg(conn, tables=table_dict) + conn.close() + print(f"{BColors.UNDERLINE}Tabellen zijn nu opgeslagen in het GeoProb-Pipe-file.{BColors.ENDC}") elif choice == "Nee": diff --git a/geoprob_pipe/results/__init__.py b/geoprob_pipe/results/__init__.py index c76001cd..0db3ce80 100644 --- a/geoprob_pipe/results/__init__.py +++ b/geoprob_pipe/results/__init__.py @@ -1,20 +1,28 @@ from __future__ import annotations + +import os +import sqlite3 +from datetime import datetime +from typing import TYPE_CHECKING + from pandas import DataFrame -from typing import TYPE_CHECKING, Optional + +from geoprob_pipe.results.alphas_and_physical_values import construct_df from geoprob_pipe.results.construct_dataframes import ( + calculate_df_beta_per_uittredepunt, combine_df_beta_per_limit_state, combine_df_beta_per_scenario_cp, - combine_df_beta_per_scenario_rp, combine_df_beta_per_scenario_final, - calculate_df_beta_per_uittredepunt, - construct_df_beta_wbi_vak, - construct_df_beta_window_vak, - construct_df_beta_scaled_vak, + combine_df_beta_per_scenario_rp, construct_df_beta_per_traject, + construct_df_beta_scaled_traject, + construct_df_beta_scaled_vak, + construct_df_beta_wbi_vak, construct_df_beta_window_traject, - construct_df_beta_scaled_traject) -from geoprob_pipe.results.alphas_and_physical_values import construct_df -import os + construct_df_beta_window_vak, +) +from geoprob_pipe.utils.sql_contents import write_dfs_to_gpkg + if TYPE_CHECKING: from geoprob_pipe import GeoProbPipe @@ -31,7 +39,7 @@ def __init__(self, geoprob_pipe: GeoProbPipe): # Scenario calculations as a single Combine Project. self.df_beta_scenarios_final = combine_df_beta_per_scenario_final(geoprob_pipe.calc_results) # Worst result from scenario calculations, either combine project, reliability project or max of limit states. - self._df_alphas_influence_factors_and_physical_values: Optional[DataFrame] = None + self._df_alphas_influence_factors_and_physical_values = DataFrame() self.df_beta_uittredepunten = calculate_df_beta_per_uittredepunt( geoprob_pipe=geoprob_pipe, results=self ) @@ -63,6 +71,8 @@ def __init__(self, geoprob_pipe: GeoProbPipe): self.df_beta_scaled_traject = construct_df_beta_scaled_traject( geoprob_pipe=geoprob_pipe, results=self ) + + self.export_to_gpkg() def df_alphas_influence_factors_and_physical_values( self, @@ -71,7 +81,7 @@ def df_alphas_influence_factors_and_physical_values( ) -> DataFrame: # Generate if not generated yet - if self._df_alphas_influence_factors_and_physical_values is None: + if self._df_alphas_influence_factors_and_physical_values.empty: self._df_alphas_influence_factors_and_physical_values = ( construct_df(self.geoprob_pipe)) @@ -114,6 +124,35 @@ def export_dir_traject(self) -> str: os.makedirs(path, exist_ok=True) return path + def export_to_gpkg(self): + """ + Voeg de overige resultaten toe aan de database voor inzicht en later + gebruik. + """ + conn = sqlite3.connect( + self.geoprob_pipe.input_data.app_settings.geopackage_filepath + ) + + tables = { + "result__physical_values": self._df_alphas_influence_factors_and_physical_values, + "result__vakken_WBI": self.df_beta_WBI_vakken, + "result__vakken_50m": self.df_beta_window50m_vakken, + "result__vakken_100m": self.df_beta_window100m_vakken, + "result__vakken_200m": self.df_beta_window200m_vakken, + "result__vakken_300m": self.df_beta_window300m_vakken, + "result__vakken_scaled": self.df_beta_scaled_vakken, + "result__traject": self.df_beta_traject, + "result__traject_50m": self.df_beta_window50m_traject, + "result__traject_100m": self.df_beta_window100m_traject, + "result__traject_200m": self.df_beta_window200m_traject, + "result__traject_300m": self.df_beta_window300m_traject, + "result__traject_scaled": self.df_beta_scaled_traject, + } + + write_dfs_to_gpkg(conn, tables) + + conn.close() + def export_results( self, bool_beta_limit_states: bool = True, @@ -125,6 +164,9 @@ def export_results( bool_beta_vakken: bool = True, bool_beta_alternative_vakken: bool = False, bool_beta_traject: bool = True): + """ + Exporteer resultaten naar excel op basis van instellingen. + """ # Results of limit state calculations if bool_beta_limit_states: @@ -193,3 +235,4 @@ def export_results( self.df_beta_scaled_traject.to_excel( excel_writer=os.path.join(self.export_dir_traject, "df_beta_scaled_traject.xlsx")) + \ No newline at end of file diff --git a/geoprob_pipe/spatial/__init__.py b/geoprob_pipe/spatial/__init__.py index 421e47aa..5ce6b43f 100644 --- a/geoprob_pipe/spatial/__init__.py +++ b/geoprob_pipe/spatial/__init__.py @@ -1,9 +1,17 @@ from __future__ import annotations + from typing import TYPE_CHECKING -from geoprob_pipe.spatial.gdf_beta_limit_states import ( - get_gdf_beta_limit_states, get_gdf_beta_scenarios_final, get_gdf_beta_scenarios_cp, get_gdf_beta_scenarios_rp, - get_gdf_beta_uittredepunten) + from geopandas import GeoDataFrame + +from geoprob_pipe.spatial.gdf_beta_limit_states import ( + get_gdf_beta_limit_states, + get_gdf_beta_scenarios_cp, + get_gdf_beta_scenarios_final, + get_gdf_beta_scenarios_rp, + get_gdf_beta_uittredepunten, +) + if TYPE_CHECKING: from geoprob_pipe import GeoProbPipe @@ -30,7 +38,7 @@ def get_gdf_beta_uittredepunten(self, export: bool = False) -> GeoDataFrame: @property def export_dir(self) -> str: - return self.geoprob_pipe.input_data.app_settings.workspace_dir + return str(self.geoprob_pipe.input_data.app_settings.workspace_dir) def export_geopackage(self): self.get_gdf_beta_limit_states(export=True) diff --git a/geoprob_pipe/utils/sql_contents.py b/geoprob_pipe/utils/sql_contents.py new file mode 100644 index 00000000..d5c30fd2 --- /dev/null +++ b/geoprob_pipe/utils/sql_contents.py @@ -0,0 +1,34 @@ +import sqlite3 +from datetime import datetime + + +def write_dfs_to_gpkg(conn: sqlite3.Connection, tables: dict): + cursor = conn.cursor() + + for table_name, df in tables.items(): + df.to_sql(table_name, conn, if_exists="replace", index=False) + + cursor.execute( + "DELETE FROM gpkg_contents WHERE table_name = ?", (table_name,) + ) + + # 3. Registreren in gpkg_contents + cursor.execute( + """ + INSERT INTO gpkg_contents ( + table_name, + data_type, + identifier, + description, + last_change + ) + VALUES (?, 'attributes', ?, '', ?) + """, + ( + table_name, + table_name, + datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%fZ"), + ), + ) + + conn.commit() From 8bcb7b03b9b977cd795059eb43d2dc66d9db5459 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 4 Jun 2026 11:51:29 +0200 Subject: [PATCH 40/53] pandas tabellen correct ingevoerd, te openen in arcgis --- .../spatial_layers/added_binnenteenlijn.py | 2 +- .../spatial_layers/added_buitenteenlijn.py | 2 +- .../spatial_layers/added_dijktraject.py | 4 +- .../spatial_layers/added_intredelijn.py | 2 +- .../added_ruimtelijke_invoer.py | 2 +- .../spatial_layers/added_vakindeling.py | 2 +- geoprob_pipe/utils/sql_contents.py | 87 ++++++++++++++++++- 7 files changed, 91 insertions(+), 10 deletions(-) diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py index 4cca0ed4..691c170a 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_binnenteenlijn.py @@ -18,7 +18,7 @@ def added_binnenteenlijn(app_settings: ApplicationSettings) -> bool: layers = fiona.listlayers(app_settings.geopackage_filepath) - if "binnenteenlijn" in layers: + if "geom__binnenteenlijn" in layers: print( BColors.OKBLUE, "✔ Binnenteenlijn al toegevoegd.", BColors.ENDC ) diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py index fc327d6b..835e943b 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_buitenteenlijn.py @@ -19,7 +19,7 @@ def added_buitenteenlijn(app_settings: ApplicationSettings) -> bool: layers = fiona.listlayers(app_settings.geopackage_filepath) - if "buitenteenlijn" in layers: + if "geom__buitenteenlijn" in layers: print( BColors.OKBLUE, "✔ Buitenteenlijn al toegevoegd.", BColors.ENDC ) diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py b/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py index 60e4505e..fe515105 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_dijktraject.py @@ -14,8 +14,8 @@ def added_dijktraject(app_settings: ApplicationSettings) -> bool: layers = fiona.listlayers(app_settings.geopackage_filepath) - if "dijktraject" in layers: - print(BColors.OKBLUE, f"✔ Dijktraject al toegevoegd.", BColors.ENDC) + if "geom__dijktraject" in layers: + print(BColors.OKBLUE, "✔ Dijktraject al toegevoegd.", BColors.ENDC) return True else: question_trajectory_source(app_settings) diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py index 993bdc33..c4745b75 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_intredelijn.py @@ -19,7 +19,7 @@ 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]: + if "intredelijn" in layer.split("__"): print(BColors.OKBLUE, "✔ Intredelijn al toegevoegd.", BColors.ENDC) return True diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py index 5245df7e..1803f7c6 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_ruimtelijke_invoer.py @@ -34,7 +34,7 @@ def added_ruimtelijke_input(app_settings: ApplicationSettings) -> bool: return True for parameter in parameters: - if any(parameter in layer.split("__")[0] for layer in list_layers): + if any(parameter in layer.split("__") for layer in list_layers): print( BColors.OKBLUE, f"✔ {parameter} al toegevoegd.", diff --git a/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py index ed01f371..9a522438 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py +++ b/geoprob_pipe/cmd_app/spatial_layers/added_vakindeling.py @@ -20,7 +20,7 @@ def added_vakindeling(app_settings: ApplicationSettings) -> bool: layers = fiona.listlayers(app_settings.geopackage_filepath) - if "vakindeling" in layers: + if "geom__vakindeling" in layers: check_validity_vakindeling(app_settings=app_settings) return True else: diff --git a/geoprob_pipe/utils/sql_contents.py b/geoprob_pipe/utils/sql_contents.py index d5c30fd2..7b690127 100644 --- a/geoprob_pipe/utils/sql_contents.py +++ b/geoprob_pipe/utils/sql_contents.py @@ -1,18 +1,97 @@ import sqlite3 from datetime import datetime +import pandas as pd -def write_dfs_to_gpkg(conn: sqlite3.Connection, tables: dict): + +def _create_table_with_pk(conn, table_name, df): + cursor = conn.cursor() + + # Verwijder bestaande tabel + cursor.execute(f'DROP TABLE IF EXISTS "{table_name}"') + + # SQLite types bepalen + cols_sql = [] + for col, dtype in df.dtypes.items(): + if "int" in str(dtype): + sql_type = "INTEGER" + elif "float" in str(dtype): + sql_type = "REAL" + else: + sql_type = "TEXT" + + cols_sql.append(f'"{col}" {sql_type}') + + cols_sql = ", ".join(cols_sql) + + # Setup primary key + cursor.execute(f''' + CREATE TABLE "{table_name}" ( + fid INTEGER PRIMARY KEY AUTOINCREMENT, + {cols_sql} + ) + ''') + +def _register_gpkg_data_columns(conn, table_name): + cursor = conn.cursor() + + # Haal kolomnamen op via SQLite pragma + cursor.execute(f"PRAGMA table_info('{table_name}')") + columns = cursor.fetchall() + + for col in columns: + col_name = col[1] # tweede veld = column name + + cursor.execute( + """ + INSERT OR REPLACE INTO gpkg_data_columns ( + table_name, + column_name, + name, + title, + description, + mime_type, + constraint_name + ) + VALUES (?, ?, ?, ?, '', NULL, NULL) + """, + ( + table_name, + col_name, + col_name, + col_name, + ), + ) + +def write_dfs_to_gpkg(conn: sqlite3.Connection, tables: dict[str, pd.DataFrame]): cursor = conn.cursor() + + cursor.execute(""" + CREATE TABLE IF NOT EXISTS gpkg_data_columns ( + table_name TEXT NOT NULL, + column_name TEXT NOT NULL, + name TEXT, + title TEXT, + description TEXT, + mime_type TEXT, + constraint_name TEXT, + PRIMARY KEY (table_name, column_name) + ) + """) for table_name, df in tables.items(): - df.to_sql(table_name, conn, if_exists="replace", index=False) + if df.empty: # Sla lege df over, dit breekt de SQL + continue + + _create_table_with_pk(conn, table_name, df) + + df.to_sql(table_name, conn, if_exists="append", index=False) cursor.execute( "DELETE FROM gpkg_contents WHERE table_name = ?", (table_name,) ) - # 3. Registreren in gpkg_contents + # Registreren in gpkg_contents cursor.execute( """ INSERT INTO gpkg_contents ( @@ -31,4 +110,6 @@ def write_dfs_to_gpkg(conn: sqlite3.Connection, tables: dict): ), ) + _register_gpkg_data_columns(conn, table_name) + conn.commit() From c7f6966f96fe2db252bd410548766dda7fb79efa Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 4 Jun 2026 11:56:12 +0200 Subject: [PATCH 41/53] data__gis_parameter_invoer fix --- geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py index 6d470234..b43faf33 100644 --- a/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py +++ b/geoprob_pipe/cmd_app/spatial_joins/couple_objects/base.py @@ -81,6 +81,7 @@ def _upsert_to_gpkg(self, df: pd.DataFrame): cursor.execute( """ CREATE TABLE IF NOT EXISTS data__gis_parameter_invoer ( + fid INTEGER PRIMARY KEY AUTOINCREMENT, parameter TEXT, scope TEXT, scope_referentie INTEGER, From 5e0fa9afbcc8e3ca21221159bb71e4fbad3306db Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 4 Jun 2026 12:44:53 +0200 Subject: [PATCH 42/53] documentaie en fix voor physical_values --- geoprob_pipe/results/__init__.py | 2 +- geoprob_pipe/utils/sql_contents.py | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/geoprob_pipe/results/__init__.py b/geoprob_pipe/results/__init__.py index 0db3ce80..16b27102 100644 --- a/geoprob_pipe/results/__init__.py +++ b/geoprob_pipe/results/__init__.py @@ -71,7 +71,7 @@ def __init__(self, geoprob_pipe: GeoProbPipe): self.df_beta_scaled_traject = construct_df_beta_scaled_traject( geoprob_pipe=geoprob_pipe, results=self ) - + self.df_alphas_influence_factors_and_physical_values() self.export_to_gpkg() def df_alphas_influence_factors_and_physical_values( diff --git a/geoprob_pipe/utils/sql_contents.py b/geoprob_pipe/utils/sql_contents.py index 7b690127..efc8c95c 100644 --- a/geoprob_pipe/utils/sql_contents.py +++ b/geoprob_pipe/utils/sql_contents.py @@ -5,6 +5,13 @@ def _create_table_with_pk(conn, table_name, df): + """ + Maak de tabel aan met de juiste kollomen en een primary key. + + :param conn: Database connector + :param table_name: Naam van de toe te voegen tabel + :param df: DataFrame die wordt toegevoegd + """ cursor = conn.cursor() # Verwijder bestaande tabel @@ -33,6 +40,12 @@ def _create_table_with_pk(conn, table_name, df): ''') def _register_gpkg_data_columns(conn, table_name): + """ + Voeg de kolommen toe aan de gpkg_data_columns vanuit de ingevoerde tabel. + + :param conn: Database connector + :param table_name: Naam van toegevoegde tabel. + """ cursor = conn.cursor() # Haal kolomnamen op via SQLite pragma @@ -64,8 +77,17 @@ def _register_gpkg_data_columns(conn, table_name): ) def write_dfs_to_gpkg(conn: sqlite3.Connection, tables: dict[str, pd.DataFrame]): + """ + Schrijf de pandas DataFrames naar de databese met een fid primary key en + voeg deze toe aan de gpkg_data_columns zodat deze in gis-software kunnen + worden geopend. + + :param conn: Databse connector + :param tables: dict met de atbelnamen en dataframes + """ cursor = conn.cursor() + # Maak gpkg_data_columns tabel als deze nog niet bestaat. cursor.execute(""" CREATE TABLE IF NOT EXISTS gpkg_data_columns ( table_name TEXT NOT NULL, @@ -85,6 +107,7 @@ def write_dfs_to_gpkg(conn: sqlite3.Connection, tables: dict[str, pd.DataFrame]) _create_table_with_pk(conn, table_name, df) + # Voeg de df toe aan de tabel, met append anders overschijft het de primary key. df.to_sql(table_name, conn, if_exists="append", index=False) cursor.execute( From 8ea7ba9111097104dfa26699068486ddb0f290d9 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 4 Jun 2026 13:57:42 +0200 Subject: [PATCH 43/53] a_vak en delta length uitgelezen --- geoprob_pipe/app_object.py | 15 +- .../parameter_input/expand_input_tables.py | 3 +- geoprob_pipe/results/construct_dataframes.py | 460 ++++++++++++------ 3 files changed, 332 insertions(+), 146 deletions(-) diff --git a/geoprob_pipe/app_object.py b/geoprob_pipe/app_object.py index ba827d89..574f0825 100644 --- a/geoprob_pipe/app_object.py +++ b/geoprob_pipe/app_object.py @@ -1,5 +1,6 @@ from __future__ import annotations import os +import sqlite3 from datetime import datetime from typing import TYPE_CHECKING, Optional, List import pandas as pd @@ -22,6 +23,8 @@ from geoprob_pipe.visualizations import Visualizations from geoprob_pipe.calculations.systems.build_and_run import build_and_run_system_calculations from geoprob_pipe.utils.update_metadata import update_metadata +from geoprob_pipe.utils.sql_contents import write_dfs_to_gpkg + import logging if TYPE_CHECKING: from geoprob_pipe.calculations.systems.build_and_run import CalcResult @@ -51,6 +54,14 @@ def __init__(self, app_settings: ApplicationSettings) -> None: self.time_start = datetime.now() self.input_data = InputData(app_settings=app_settings) # TODO: Alter with new option + + self.df_expanded = run_expand_input_tables(geopackage_filepath=self.input_data.app_settings.geopackage_filepath) + # TODO VJ: vind een betere plaats hiervoor + conn = sqlite3.connect(app_settings.geopackage_filepath) + df_add = self.df_expanded.copy() + df_add["parameter_input"] = df_add["parameter_input"].apply(str) + write_dfs_to_gpkg(conn, {"data__expanded_parameters": df_add}) + conn.close() # Read calculation settings # self._read_calculation_settings() # TODO: Not part of new version @@ -98,10 +109,10 @@ def export_archive(self): self.spatial.export_geopackage() # Parameter invoer als expanded - df_expanded = run_expand_input_tables(geopackage_filepath=self.input_data.app_settings.geopackage_filepath) + input_dir = os.path.join(export_dir, "input") os.makedirs(input_dir, exist_ok=True) - df_expanded.to_excel(excel_writer=os.path.join(input_dir, "df_parameter_invoer_expanded.xlsx"), index=False) + self.df_expanded.to_excel(excel_writer=os.path.join(input_dir, "df_parameter_invoer_expanded.xlsx"), index=False) # Input parameter figures obj = InputParameterFigures.populate( 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 2c4bd341..35bb6330 100644 --- a/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py +++ b/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py @@ -7,6 +7,7 @@ from geopandas import GeoDataFrame, read_file from geoprob_pipe.calculations.systems.mappers.initial_input import INITIAL_INPUT_MAPPER from geoprob_pipe.cmd_app.parameter_input.input_parameter_tables import InputParameterTables +from geoprob_pipe.utils.sql_contents import write_dfs_to_gpkg from probabilistic_library import FragilityValue @@ -404,5 +405,5 @@ def run_expand_input_tables( df_parameter_invoer_combined=df_parameter_invoer_combined3, df_identifiers=df_identifiers, geopackage_filepath=geopackage_filepath) - + return _concat_collection(collection=collection) diff --git a/geoprob_pipe/results/construct_dataframes.py b/geoprob_pipe/results/construct_dataframes.py index a0e566c3..4fb2173c 100644 --- a/geoprob_pipe/results/construct_dataframes.py +++ b/geoprob_pipe/results/construct_dataframes.py @@ -32,7 +32,9 @@ def collect_df_beta_limit_state(calculation: SystemCalculation) -> DataFrame: def create_row(dp: DesignPoint, model_name): return { "uittredepunt_id": calculation.metadata["uittredepunt_id"], - "ondergrondscenario_id": calculation.metadata["ondergrondscenario_naam"], # TODO: id naar naam veranderen? + "ondergrondscenario_id": calculation.metadata[ + "ondergrondscenario_naam" + ], # TODO: id naar naam veranderen? "vak_id": calculation.metadata["vak_id"], "limit_state": model_name, "converged": dp.is_converged, @@ -44,49 +46,74 @@ def create_row(dp: DesignPoint, model_name): } rows = [] - for design_point, model in zip(calculation.results.dps_limit_states, calculation.setup.system_limit_states): + for design_point, model in zip( + calculation.results.dps_limit_states, + calculation.setup.system_limit_states, + ): rows.append(create_row(dp=design_point, model_name=model.__name__)) - df = DataFrame(rows).sort_values(by=["uittredepunt_id", "ondergrondscenario_id", "vak_id"]).reset_index(drop=True) + df = ( + DataFrame(rows) + .sort_values(by=["uittredepunt_id", "ondergrondscenario_id", "vak_id"]) + .reset_index(drop=True) + ) return df -def combine_df_beta_per_limit_state(calc_results: List[CalcResult]) -> DataFrame: +def combine_df_beta_per_limit_state( + calc_results: List[CalcResult], +) -> DataFrame: assert calc_results.__len__() > 0 - df = concat((result.df_limit_state for result in calc_results), ignore_index=True) + df = concat( + (result.df_limit_state for result in calc_results), ignore_index=True + ) return df def collect_df_beta_scenario_rp(calc: SystemCalculation) -> DataFrame: - return DataFrame([{ - "uittredepunt_id": calc.metadata["uittredepunt_id"], - "ondergrondscenario_id": calc.metadata["ondergrondscenario_naam"], # TODO: id naar naam veranderen? - "vak_id": calc.metadata["vak_id"], - "system_calculation": calc, - "converged": calc.results.dp_reliability.is_converged, - "beta": round(calc.results.dp_reliability.reliability_index, 3), - "failure_probability": calc.results.dp_reliability.probability_failure, - "convergence": calc.results.dp_reliability.convergence, - "total_model_runs": calc.results.dp_reliability.total_model_runs, - "total_iterations": calc.results.dp_reliability.total_iterations, - }]) + return DataFrame( + [ + { + "uittredepunt_id": calc.metadata["uittredepunt_id"], + "ondergrondscenario_id": calc.metadata[ + "ondergrondscenario_naam" + ], # TODO: id naar naam veranderen? + "vak_id": calc.metadata["vak_id"], + "system_calculation": calc, + "converged": calc.results.dp_reliability.is_converged, + "beta": round( + calc.results.dp_reliability.reliability_index, 3 + ), + "failure_probability": calc.results.dp_reliability.probability_failure, + "convergence": calc.results.dp_reliability.convergence, + "total_model_runs": calc.results.dp_reliability.total_model_runs, + "total_iterations": calc.results.dp_reliability.total_iterations, + } + ] + ) def collect_df_beta_scenario_cp(calc: SystemCalculation) -> DataFrame: - return DataFrame([{ - "uittredepunt_id": calc.metadata["uittredepunt_id"], - "ondergrondscenario_id": calc.metadata["ondergrondscenario_naam"], # TODO: id naar naam veranderen? - "vak_id": calc.metadata["vak_id"], - "system_calculation": calc, - "converged": calc.results.dp_combine.is_converged, - "beta": round(calc.results.dp_combine.reliability_index, 3), - "failure_probability": calc.results.dp_combine.probability_failure, - "convergence": calc.results.dp_combine.convergence, - "total_model_runs": calc.results.dp_combine.total_model_runs, - }]) + return DataFrame( + [ + { + "uittredepunt_id": calc.metadata["uittredepunt_id"], + "ondergrondscenario_id": calc.metadata[ + "ondergrondscenario_naam" + ], # TODO: id naar naam veranderen? + "vak_id": calc.metadata["vak_id"], + "system_calculation": calc, + "converged": calc.results.dp_combine.is_converged, + "beta": round(calc.results.dp_combine.reliability_index, 3), + "failure_probability": calc.results.dp_combine.probability_failure, + "convergence": calc.results.dp_combine.convergence, + "total_model_runs": calc.results.dp_combine.total_model_runs, + } + ] + ) def collect_df_beta_scenario_final(calc: SystemCalculation) -> DataFrame: - """ Converts a SystemCalculation-object to a single-row DataFrame with the final result of the scenario + """Converts a SystemCalculation-object to a single-row DataFrame with the final result of the scenario calculations. Because there are several calculation methods, and the preferred result also depends on convergence, we use the below flow chart to determine the final result. @@ -103,16 +130,25 @@ def collect_df_beta_scenario_final(calc: SystemCalculation) -> DataFrame: converged1: bool = calc.results.dp_combine.is_converged beta2: float = calc.results.dp_reliability.reliability_index converged2: bool = calc.results.dp_reliability.is_converged - beta3: float = max([dp.reliability_index for dp in calc.results.dps_limit_states]) - converged3: bool = all([dp.is_converged for dp in calc.results.dps_limit_states]) + beta3: float = max( + [dp.reliability_index for dp in calc.results.dps_limit_states] + ) + converged3: bool = all( + [dp.is_converged for dp in calc.results.dps_limit_states] + ) return_dict = { "uittredepunt_id": calc.metadata["uittredepunt_id"], - "ondergrondscenario_id": calc.metadata["ondergrondscenario_naam"], # TODO: id naar naam veranderen? + "ondergrondscenario_id": calc.metadata[ + "ondergrondscenario_naam" + ], # TODO: id naar naam veranderen? "vak_id": calc.metadata["vak_id"], "system_calculation": calc, - "beta1": beta1, "converged1": converged1, - "beta2": beta2, "converged2": converged2, - "beta3": beta3, "converged3": converged3, + "beta1": beta1, + "converged1": converged1, + "beta2": beta2, + "converged2": converged2, + "beta3": beta3, + "converged3": converged3, } # Flow chart step 1: Combine Project converged? @@ -138,20 +174,28 @@ def collect_df_beta_scenario_final(calc: SystemCalculation) -> DataFrame: return DataFrame([return_dict]) # Flow chart step 3: Separate Limit States all converged? - pof3: float = min([dp.probability_failure for dp in calc.results.dps_limit_states]) + pof3: float = min( + [dp.probability_failure for dp in calc.results.dps_limit_states] + ) if converged3: return_dict["method_used"] = "3: Max Limit States" return_dict["flow_chart_number"] = 3 return_dict["failure_probability"] = pof3 return_dict["beta"] = beta3 return_dict["converged"] = converged3 - return_dict["advise"] = ("Result is probably a conservative approximation.You could consider to find " - "convergence for the Combine or Reliability method.") + return_dict["advise"] = ( + "Result is probably a conservative approximation.You could consider to find " + "convergence for the Combine or Reliability method." + ) return DataFrame([return_dict]) # Flow chart step 4: B >= 8.0 (of all methods)? all_pofs: List[float] = [pof3, pof2, pof1] - all_methods: List[str] = ["3: Max Limit States", "2: Reliability Project", "1: Combine Project"] + all_methods: List[str] = [ + "3: Max Limit States", + "2: Reliability Project", + "1: Combine Project", + ] all_betas: List[float] = [beta3, beta2, beta1] index_max_pof = np.argmax(all_pofs) if beta1 >= 8.0 and beta2 >= 8.0 and beta3 >= 8.0: @@ -160,7 +204,9 @@ def collect_df_beta_scenario_final(calc: SystemCalculation) -> DataFrame: return_dict["failure_probability"] = all_pofs[index_max_pof] return_dict["beta"] = all_betas[index_max_pof] return_dict["converged"] = False - return_dict["advise"] = "Result is that positive, no reason to fine tune." + return_dict["advise"] = ( + "Result is that positive, no reason to fine tune." + ) return DataFrame([return_dict]) # No positive result @@ -169,30 +215,53 @@ def collect_df_beta_scenario_final(calc: SystemCalculation) -> DataFrame: return_dict["failure_probability"] = all_pofs[index_max_pof] return_dict["beta"] = all_betas[index_max_pof] return_dict["converged"] = False - return_dict["advise"] = "Consider fine tuning the calculation settings (of e.g. FORM, Importance Sampling, etc)." + return_dict["advise"] = ( + "Consider fine tuning the calculation settings (of e.g. FORM, Importance Sampling, etc)." + ) return DataFrame([return_dict]) -def combine_df_beta_per_scenario_rp(calc_results: List[CalcResult]) -> DataFrame: - df = concat((result.df_scenario_rp for result in calc_results), ignore_index=True) - df = df.sort_values(["uittredepunt_id", "ondergrondscenario_id", "vak_id"]).reset_index(drop=True) +def combine_df_beta_per_scenario_rp( + calc_results: List[CalcResult], +) -> DataFrame: + df = concat( + (result.df_scenario_rp for result in calc_results), ignore_index=True + ) + df = df.sort_values( + ["uittredepunt_id", "ondergrondscenario_id", "vak_id"] + ).reset_index(drop=True) return df -def combine_df_beta_per_scenario_cp(calc_results: List[CalcResult]) -> DataFrame: - df = concat((result.df_scenario_cp for result in calc_results), ignore_index=True) - df = df.sort_values(["uittredepunt_id", "ondergrondscenario_id", "vak_id"]).reset_index(drop=True) +def combine_df_beta_per_scenario_cp( + calc_results: List[CalcResult], +) -> DataFrame: + df = concat( + (result.df_scenario_cp for result in calc_results), ignore_index=True + ) + df = df.sort_values( + ["uittredepunt_id", "ondergrondscenario_id", "vak_id"] + ).reset_index(drop=True) return df -def combine_df_beta_per_scenario_final(calc_results: List[CalcResult]) -> DataFrame: - df = concat((result.df_scenario_final for result in calc_results), ignore_index=True) - df = df.sort_values(["uittredepunt_id", "ondergrondscenario_id", "vak_id"]).reset_index(drop=True) +def combine_df_beta_per_scenario_final( + calc_results: List[CalcResult], +) -> DataFrame: + df = concat( + (result.df_scenario_final for result in calc_results), + ignore_index=True, + ) + df = df.sort_values( + ["uittredepunt_id", "ondergrondscenario_id", "vak_id"] + ).reset_index(drop=True) return df -def calculate_df_beta_per_uittredepunt(geoprob_pipe: GeoProbPipe, results: Results) -> DataFrame: - """ Generates the DataFrame of the final result for the exit points. +def calculate_df_beta_per_uittredepunt( + geoprob_pipe: GeoProbPipe, results: Results +) -> DataFrame: + """Generates the DataFrame of the final result for the exit points. Because there is an automated decision-making in the scenario calculations (see flow chart over there), for the exit points the flow chart is extended below. @@ -241,30 +310,58 @@ def calculate_df_beta_per_uittredepunt(geoprob_pipe: GeoProbPipe, results: Resul ) ) - df["beta"] = df["failure_probability"].apply(lambda failure_prob: convert_failure_probability_to_beta(failure_prob)) + 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) - conv = df_beta_scenarios_final.groupby('uittredepunt_id', as_index=False)["converged"].all() + conv = df_beta_scenarios_final.groupby("uittredepunt_id", as_index=False)[ + "converged" + ].all() df_scen: pd.DataFrame = df.merge(conv, on="uittredepunt_id", how="left") # Determine uittredepunt flow_chart_number - flow_chart_number = df_beta_scenarios_final.groupby('uittredepunt_id', as_index=False)["flow_chart_number"].max() - df_scen = df_scen.merge(flow_chart_number, on="uittredepunt_id", how="left") - df_scen['advise'] = df_scen['flow_chart_number'].map({5: "Consider fine tuning on scenario-level."}).fillna("-") - df_scen['flow_chart_number'] = df_scen['flow_chart_number'].map({5: 11}).fillna(12) + flow_chart_number = df_beta_scenarios_final.groupby( + "uittredepunt_id", as_index=False + )["flow_chart_number"].max() + df_scen = df_scen.merge( + flow_chart_number, on="uittredepunt_id", how="left" + ) + df_scen["advise"] = ( + df_scen["flow_chart_number"] + .map({5: "Consider fine tuning on scenario-level."}) + .fillna("-") + ) + df_scen["flow_chart_number"] = ( + df_scen["flow_chart_number"].map({5: 11}).fillna(12) + ) # Add vak id back to it gdf_uittredepunten = geoprob_pipe.input_data.uittredepunten.gdf df_uittredepunten = gdf_uittredepunten[["uittredepunt_id", "vak_id"]] - df_scen = df_scen.merge(df_uittredepunten, left_on="uittredepunt_id", - right_on="uittredepunt_id") + df_scen = df_scen.merge( + df_uittredepunten, + left_on="uittredepunt_id", + right_on="uittredepunt_id", + ) - return df_scen[["uittredepunt_id", "vak_id", "converged", "beta", - "failure_probability", "advise", "flow_chart_number"]] + return df_scen[ + [ + "uittredepunt_id", + "vak_id", + "converged", + "beta", + "failure_probability", + "advise", + "flow_chart_number", + ] + ] -def _generate_point_list(geoprob_pipe: GeoProbPipe, results: Results) -> List[UittredepuntElement]: - """ Generates a list of all the points as a list `UittredepuntElement` objects. +def _generate_point_list( + geoprob_pipe: GeoProbPipe, results: Results +) -> List[UittredepuntElement]: + """Generates a list of all the points as a list `UittredepuntElement` objects. :param geoprob_pipe: GeoprobPipe object. :param results: @@ -274,11 +371,21 @@ def _generate_point_list(geoprob_pipe: GeoProbPipe, results: Results) -> List[Ui punt_gdf = geoprob_pipe.input_data.uittredepunten.gdf merge_df = pd.merge( - left=punt_df[["uittredepunt_id", "vak_id", "beta", "flow_chart_number", - "failure_probability", "converged", "advise"]], + left=punt_df[ + [ + "uittredepunt_id", + "vak_id", + "beta", + "flow_chart_number", + "failure_probability", + "converged", + "advise", + ] + ], right=punt_gdf[["uittredepunt_id", "metrering"]], - on="uittredepunt_id", how="left" - ) + on="uittredepunt_id", + how="left", + ) vakken_torun: List[int] = [] run_all: bool = False if geoprob_pipe.input_data.app_settings.to_run_vakken_ids: @@ -288,19 +395,31 @@ def _generate_point_list(geoprob_pipe: GeoProbPipe, results: Results) -> List[Ui dsn_list: List[UittredepuntElement] = [] for _, point in merge_df.iterrows(): if point["vak_id"] in vakken_torun or run_all: - dsn_list.append(UittredepuntElement( - pf=point["failure_probability"], - m_value=point["metrering"], - a=0.9, # TODO Haal deze vanuit Input Data via excel - converged=point["converged"], - flow_chart_number=point["flow_chart_number"], - advise=point["advise"] - )) + a_point: float = ( + geoprob_pipe.df_expanded.loc[ + geoprob_pipe.df_expanded["parameter_name"] == "a_vak" + ] + .query("uittredepunt_id == @point.uittredepunt_id")[ + "parameter_input" + ] + .get("mean", 1.0) + ) + dsn_list.append( + UittredepuntElement( + pf=point["failure_probability"], + m_value=point["metrering"], + a=a_point, + converged=point["converged"], + flow_chart_number=point["flow_chart_number"], + advise=point["advise"], + ) + ) return dsn_list -def _generate_element_list(geoprob_pipe: GeoProbPipe, results: Results - ) -> list[VakElement]: +def _generate_element_list( + geoprob_pipe: GeoProbPipe, results: Results +) -> list[VakElement]: """Generates a list of all elements in a traject as `VakElement` objects. :param geoprob_pipe: GeoprobPipe object. @@ -312,12 +431,21 @@ def _generate_element_list(geoprob_pipe: GeoProbPipe, results: Results punt_gdf = geoprob_pipe.input_data.uittredepunten.gdf df = pd.merge( - left=punt_df[["uittredepunt_id", "vak_id", "beta", - "failure_probability", "converged", - "flow_chart_number", "advise"]], + left=punt_df[ + [ + "uittredepunt_id", + "vak_id", + "beta", + "failure_probability", + "converged", + "flow_chart_number", + "advise", + ] + ], right=punt_gdf[["uittredepunt_id", "metrering"]], - on="uittredepunt_id", how="left" - ) + on="uittredepunt_id", + how="left", + ) vakken_torun: List[int] = [] run_all: bool = False if geoprob_pipe.input_data.app_settings.to_run_vakken_ids: @@ -330,39 +458,69 @@ def _generate_element_list(geoprob_pipe: GeoProbPipe, results: Results for _, vak in vakken_gdf.iterrows(): if vak.id in vakken_torun or run_all: df_vak = df.loc[df["vak_id"] == vak["id"]] + a_vak: float = ( + geoprob_pipe.df_expanded.loc[ + geoprob_pipe.df_expanded["parameter_name"] == "a_vak" + ] + .query("vak_id == @vak.id").iloc[0]["parameter_input"] + .get("mean", 1.0) + ) + dl_vak: float =( + geoprob_pipe.df_expanded.loc[ + geoprob_pipe.df_expanded["parameter_name"] == "delta_length" + ] + .query("vak_id == @vak.id").iloc[0]["parameter_input"] + .get("mean", 300.0) + ) dsn_list = [] for _, point in df_vak.iterrows(): - dsn_list.append(UittredepuntElement( - pf=point["failure_probability"], - beta=point["beta"], - m_value=point["metrering"], - a=1.0, # TODO Haal deze vanuit Input Data via excel - converged=point["converged"], - flow_chart_number=point["flow_chart_number"], - advise=point["advise"])) - - element_list.append(VakElement( - id=vak["id"], - m_van=vak["m_start"], - m_tot=vak["m_end"], - a=1.0, # TODO Haal deze vanuit Input Data via excel - delta_length=300, - dsn_list=dsn_list - )) + a_point: float = ( + geoprob_pipe.df_expanded.loc[ + geoprob_pipe.df_expanded["parameter_name"] == "a_vak" + ] + .query("uittredepunt_id == @point.uittredepunt_id")[ + "parameter_input" + ] + .get("mean", 1.0) + ) + dsn_list.append( + UittredepuntElement( + pf=point["failure_probability"], + beta=point["beta"], + m_value=point["metrering"], + a=a_point, + converged=point["converged"], + flow_chart_number=point["flow_chart_number"], + advise=point["advise"], + ) + ) + + element_list.append( + VakElement( + id=vak["id"], + m_van=vak["m_start"], + m_tot=vak["m_end"], + a=a_vak, + delta_length=dl_vak, + dsn_list=dsn_list, + ) + ) return element_list def construct_df_beta_wbi_vak( - geoprob_pipe: GeoProbPipe, results: Results - ) -> pd.DataFrame: - """ Bepaalde de samengestelde faalkans per vak volgens de WBI-methode. + geoprob_pipe: GeoProbPipe, results: Results +) -> pd.DataFrame: + """Bepaalde de samengestelde faalkans per vak volgens de WBI-methode. :param geoprob_pipe: GeoProbPipe object voor data collectie. :param results: Results object voor data collectie. :return DataFrame: """ - element_list: list[VakElement] = _generate_element_list(geoprob_pipe=geoprob_pipe, results=results) + element_list: list[VakElement] = _generate_element_list( + geoprob_pipe=geoprob_pipe, results=results + ) vakken_list = [] for element in element_list: vakken_dict = { @@ -380,23 +538,26 @@ def construct_df_beta_wbi_vak( "beta_vak": element.pf_max_dsn[1].beta, "converged": element.conv_max_dsn, "flow_chart_number": element.flow_chart_number, - "advise": element.advise} + "advise": element.advise, + } vakken_list.append(vakken_dict) return pd.DataFrame(vakken_list) def construct_df_beta_window_vak( - geoprob_pipe: GeoProbPipe, results: Results, window_size: float - ) -> pd.DataFrame: - """ Bepaald de samengestelde faalkans per vak bij een window size. + geoprob_pipe: GeoProbPipe, results: Results, window_size: float +) -> pd.DataFrame: + """Bepaald de samengestelde faalkans per vak bij een window size. :param geoprob_pipe: GeoProbPipe object voor data collectie. :param window_size: :param results: Results object voor data collectie. :return DataFrame: """ - element_list: list[VakElement] = _generate_element_list(geoprob_pipe=geoprob_pipe, results=results) + element_list: list[VakElement] = _generate_element_list( + geoprob_pipe=geoprob_pipe, results=results + ) window_list = [] for element in element_list: for window in element.pf_window(window_size)[2]: @@ -415,24 +576,25 @@ def construct_df_beta_window_vak( "pf_vak": element.pf_window(window_size)[0].pf, "beta_vak": element.pf_window(window_size)[0].beta, "flow_chart_number": element.flow_chart_number, - "advise": element.advise - } + "advise": element.advise, + } window_list.append(window_dict) return pd.DataFrame(window_list) def construct_df_beta_scaled_vak( - geoprob_pipe: GeoProbPipe, results: Results - ) -> pd.DataFrame: - """ Bepaalde de samengestelde faalkans per vak op basis van de afstand tussen de uittredepunten. + geoprob_pipe: GeoProbPipe, results: Results +) -> pd.DataFrame: + """Bepaalde de samengestelde faalkans per vak op basis van de afstand tussen de uittredepunten. :param geoprob_pipe: GeoProbPipe object voor data collectie. :param results: Results object voor data collectie. :return DataFrame: """ - element_list = _generate_element_list(geoprob_pipe=geoprob_pipe, - results=results) + element_list = _generate_element_list( + geoprob_pipe=geoprob_pipe, results=results + ) window_list = [] for element in element_list: for window in element.pf_scaled[2]: @@ -451,16 +613,16 @@ def construct_df_beta_scaled_vak( "pf_vak": element.pf_scaled[0].pf, "beta_vak": element.pf_scaled[0].beta, "flow_chart_number": element.flow_chart_number, - "advise": element.advise - } + "advise": element.advise, + } window_list.append(window_dict) return pd.DataFrame(window_list) def construct_df_beta_per_traject( - geoprob_pipe: GeoProbPipe, results: Results - ) -> pd.DataFrame: + geoprob_pipe: GeoProbPipe, results: Results +) -> pd.DataFrame: """Bepaalde de samengestelde faalkans over het traject volgens de WBI-methode. :param geoprob_pipe: GeoProbPipe object voor data collectie. @@ -469,59 +631,64 @@ def construct_df_beta_per_traject( :return Dataframe: """ dsn_list = _generate_point_list(geoprob_pipe=geoprob_pipe, results=results) - vakken_list = _generate_element_list(geoprob_pipe=geoprob_pipe, results=results) + vakken_list = _generate_element_list( + geoprob_pipe=geoprob_pipe, results=results + ) - traject = TrajectElement(list_vakken=vakken_list, list_dsn=dsn_list, delta_length=300.0) + traject = TrajectElement( + list_vakken=vakken_list, list_dsn=dsn_list, delta_length=300.0 + ) traject_list = [ { "method": "WBI methode over traject", "upper_bound_pof": traject.pf_max_vak[0].pf, "lower_bound_beta": traject.pf_max_vak[0].beta, "lower_bound_pof": traject.pf_max_vak[1].pf, - "upper_bound_beta": traject.pf_max_vak[1].beta}, + "upper_bound_beta": traject.pf_max_vak[1].beta, + }, { "method": "Window 50m over traject", "upper_bound_pof": traject.pf_window(50.0)[0].pf, "lower_bound_beta": traject.pf_window(50.0)[0].beta, "lower_bound_pof": traject.pf_window(50.0)[1].pf, - "upper_bound_beta": traject.pf_window(50.0)[1].beta + "upper_bound_beta": traject.pf_window(50.0)[1].beta, }, { "method": "Window 100m over traject", "upper_bound_pof": traject.pf_window(100.0)[0].pf, "lower_bound_beta": traject.pf_window(100.0)[0].beta, "lower_bound_pof": traject.pf_window(100.0)[1].pf, - "upper_bound_beta": traject.pf_window(100.0)[1].beta + "upper_bound_beta": traject.pf_window(100.0)[1].beta, }, { "method": "Window 200m over traject", "upper_bound_pof": traject.pf_window(200.0)[0].pf, "lower_bound_beta": traject.pf_window(200.0)[0].beta, "lower_bound_pof": traject.pf_window(200.0)[1].pf, - "upper_bound_beta": traject.pf_window(200.0)[1].beta + "upper_bound_beta": traject.pf_window(200.0)[1].beta, }, { "method": "Window 300m over traject", "upper_bound_pof": traject.pf_window(300.0)[0].pf, "lower_bound_beta": traject.pf_window(300.0)[0].beta, "lower_bound_pof": traject.pf_window(300.0)[1].pf, - "upper_bound_beta": traject.pf_window(300.0)[1].beta + "upper_bound_beta": traject.pf_window(300.0)[1].beta, }, { "method": "Scaled over individual sections", "upper_bound_pof": traject.pf_scaled[0].pf, "lower_bound_beta": traject.pf_scaled[0].beta, "lower_bound_pof": traject.pf_scaled[1].pf, - "upper_bound_beta": traject.pf_scaled[1].beta + "upper_bound_beta": traject.pf_scaled[1].beta, }, ] return pd.DataFrame(traject_list) def construct_df_beta_window_traject( - geoprob_pipe: GeoProbPipe, results: Results, window_size: float - ) -> pd.DataFrame: - """ Bepaald de samengestelde faalkans voor het gehele traject bij een window size (i.p.v. vakken). + geoprob_pipe: GeoProbPipe, results: Results, window_size: float +) -> pd.DataFrame: + """Bepaald de samengestelde faalkans voor het gehele traject bij een window size (i.p.v. vakken). :param geoprob_pipe: GeoProbPipe object voor data collectie. :param results: Results object voor data collectie. @@ -529,9 +696,13 @@ def construct_df_beta_window_traject( :return DataFrame: """ dsn_list = _generate_point_list(geoprob_pipe=geoprob_pipe, results=results) - element_list = _generate_element_list(geoprob_pipe=geoprob_pipe, results=results) + element_list = _generate_element_list( + geoprob_pipe=geoprob_pipe, results=results + ) - traject = TrajectElement(list_vakken=element_list, list_dsn=dsn_list, delta_length=window_size) + traject = TrajectElement( + list_vakken=element_list, list_dsn=dsn_list, delta_length=window_size + ) window_list = [] for window in traject.pf_window(window_size=window_size)[2]: window_dict = { @@ -546,20 +717,22 @@ def construct_df_beta_window_traject( "a": 1.0, "delta_L": traject.delta_length, "N_vak": 1.0, - "pf_traject(sum)": traject.pf_window(window_size=window_size)[0].pf, + "pf_traject(sum)": traject.pf_window(window_size=window_size)[ + 0 + ].pf, "beta_traject": traject.pf_window(window_size=window_size)[0].beta, "flow_chart_number": window.flow_chart_number, - "advise": window.advise - } + "advise": window.advise, + } window_list.append(window_dict) return pd.DataFrame(window_list) def construct_df_beta_scaled_traject( - geoprob_pipe: GeoProbPipe, results: Results - ) -> pd.DataFrame: - """ Bepaalde de samengestelde faalkans voor het gehele traject op basis van de afstand tussen de uittredepunten + geoprob_pipe: GeoProbPipe, results: Results +) -> pd.DataFrame: + """Bepaalde de samengestelde faalkans voor het gehele traject op basis van de afstand tussen de uittredepunten i.p.v. de vakken. :param geoprob_pipe: GeoProbPipe object voor data collectie. @@ -567,8 +740,9 @@ def construct_df_beta_scaled_traject( :return DataFrame: """ dsn_list = _generate_point_list(geoprob_pipe=geoprob_pipe, results=results) - element_list = _generate_element_list(geoprob_pipe=geoprob_pipe, - results=results) + element_list = _generate_element_list( + geoprob_pipe=geoprob_pipe, results=results + ) traject = TrajectElement( list_vakken=element_list, list_dsn=dsn_list, delta_length=300.0 @@ -589,8 +763,8 @@ def construct_df_beta_scaled_traject( "pf_traject": traject.pf_scaled[0].pf, "beta_traject": traject.pf_scaled[0].beta, "flow_chart_number": window.flow_chart_number, - "advise": window.advise - } + "advise": window.advise, + } window_list.append(window_dict) return pd.DataFrame(window_list) From e81252b566a7fde7e37ab1bdc25a267f2adeac2c Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 4 Jun 2026 14:13:55 +0200 Subject: [PATCH 44/53] leesbaarheid --- geoprob_pipe/results/construct_dataframes.py | 87 ++++++++++---------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/geoprob_pipe/results/construct_dataframes.py b/geoprob_pipe/results/construct_dataframes.py index 4fb2173c..b5a62ba7 100644 --- a/geoprob_pipe/results/construct_dataframes.py +++ b/geoprob_pipe/results/construct_dataframes.py @@ -281,33 +281,34 @@ def calculate_df_beta_per_uittredepunt( # 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, - ) - ) + + df = df_beta_scenarios_final.copy() + + def bereken_scenario_factor(row): + return geoprob_pipe.input_data.scenarios.scenario_kans( + vak_id=row["vak_id"], + scenario_naam=row["ondergrondscenario_id"], ) - .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["scenario_factor"] = df.apply(bereken_scenario_factor, axis=1) + + df["failure_probability"] = ( + df["failure_probability"] * df["scenario_factor"] + ) + + def combine_probabilities(series): + c_pof = float( + one + - reduce( + operator.mul, + (one - Decimal(str(v)) for v in series), + one, ) ) + return c_pof + + df = df.groupby("uittredepunt_id", as_index=False).agg( + failure_probability=("failure_probability", combine_probabilities) ) df["beta"] = df["failure_probability"].apply( @@ -395,15 +396,12 @@ def _generate_point_list( dsn_list: List[UittredepuntElement] = [] for _, point in merge_df.iterrows(): if point["vak_id"] in vakken_torun or run_all: - a_point: float = ( - geoprob_pipe.df_expanded.loc[ - geoprob_pipe.df_expanded["parameter_name"] == "a_vak" - ] - .query("uittredepunt_id == @point.uittredepunt_id")[ - "parameter_input" - ] - .get("mean", 1.0) - ) + df_point = geoprob_pipe.df_expanded.loc[ + geoprob_pipe.df_expanded["parameter_name"] == "a_vak" + ] + a_point: float = df_point.query( + "uittredepunt_id == @point.uittredepunt_id" + )["parameter_input"].get("mean", 1.0) dsn_list.append( UittredepuntElement( pf=point["failure_probability"], @@ -458,20 +456,25 @@ def _generate_element_list( for _, vak in vakken_gdf.iterrows(): if vak.id in vakken_torun or run_all: df_vak = df.loc[df["vak_id"] == vak["id"]] + + df = geoprob_pipe.df_expanded.loc[ + geoprob_pipe.df_expanded["parameter_name"] == "a_vak" + ] a_vak: float = ( - geoprob_pipe.df_expanded.loc[ - geoprob_pipe.df_expanded["parameter_name"] == "a_vak" - ] - .query("vak_id == @vak.id").iloc[0]["parameter_input"] + df.query("vak_id == @vak.id") + .iloc[0]["parameter_input"] .get("mean", 1.0) ) - dl_vak: float =( - geoprob_pipe.df_expanded.loc[ - geoprob_pipe.df_expanded["parameter_name"] == "delta_length" - ] - .query("vak_id == @vak.id").iloc[0]["parameter_input"] + + df = geoprob_pipe.df_expanded.loc[ + geoprob_pipe.df_expanded["parameter_name"] == "delta_length" + ] + dl_vak: float = ( + df.query("vak_id == @vak.id") + .iloc[0]["parameter_input"] .get("mean", 300.0) ) + dsn_list = [] for _, point in df_vak.iterrows(): From a96961b84d8efc64abb2253239391a1ffb0d6f3a Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Fri, 5 Jun 2026 08:13:32 +0200 Subject: [PATCH 45/53] avak en dl toegevoegd aan valif parameters --- geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py index f3bf1a98..c7fab146 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py +++ b/geoprob_pipe/cmd_app/spatial_layers/valid_parameters.py @@ -37,6 +37,8 @@ "d70": {"shape": ["line"]}, "c_voorland": {"shape": ["line"]}, "c_achterland": {"shape": ["line"]}, + "a_vak": {"shape":["line"]}, + "delta_length": {"shape":["line"]}, } def valid_parameter_list(app_settings: ApplicationSettings): From 15980ff85fae52c30a4e80190d75c56aa63a8d9b Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Fri, 5 Jun 2026 09:23:30 +0200 Subject: [PATCH 46/53] fixme: a_vak in ReliabityProject --- .../calculations/systems/base_objects/system_calculation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geoprob_pipe/calculations/systems/base_objects/system_calculation.py b/geoprob_pipe/calculations/systems/base_objects/system_calculation.py index 112135d0..17e1d71a 100644 --- a/geoprob_pipe/calculations/systems/base_objects/system_calculation.py +++ b/geoprob_pipe/calculations/systems/base_objects/system_calculation.py @@ -148,7 +148,7 @@ def _validate_distributions_are_provided(): def _apply_distributions_on_variables(): for item in system_calculation.setup.distributions: name = item['name'] - + # TODO FIXME a_vak en delta_length geven een validation msg, deze worden niet in dit gebruikt. # Check if variable exists if system_calculation.results.reliability_project.variables[name] is None: system_calculation.validation_messages.add_warning( From ae3528a43e6b4e9ca6f8905b601770379bf42d31 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 9 Jun 2026 10:36:04 +0200 Subject: [PATCH 47/53] test for check expanded parameters table --- .../test_expand_input_tables.py | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 tests/cmd_app/parameter_input/test_expand_input_tables.py diff --git a/tests/cmd_app/parameter_input/test_expand_input_tables.py b/tests/cmd_app/parameter_input/test_expand_input_tables.py new file mode 100644 index 00000000..67227376 --- /dev/null +++ b/tests/cmd_app/parameter_input/test_expand_input_tables.py @@ -0,0 +1,151 @@ +import ast +import sqlite3 + +import numpy as np +import pandas as pd + +# TODO Permanete test gpkg als deze naar de nieuwe standaard is gezet +gpkg_filepath = r"C:\Users\vinji\Python\Libraries\GEOprob-Pipe\Workspace\data_test.geoprob_pipe.gpkg" + + +def _extract_mean(val): + if pd.isna(val): + return np.nan + try: + d = ast.literal_eval(val) # string → dict + return d.get("mean", np.nan) + except Exception: + return np.nan + + +def test_vak( + df_expanded: pd.DataFrame, df_excel_vak: pd.DataFrame, utp_list: list +): + mask = df_expanded["uittredepunt_id"].isin(utp_list) + df_expanded_vak = df_expanded.loc[~mask] + df_expanded_vak = df_expanded_vak.rename( + columns={"parameter_name": "parameter"} + ) + df_expanded_vak["mean_val"] = df_expanded_vak["parameter_input"].apply( + _extract_mean + ) + df_excel_vak = df_excel_vak.rename( + columns={"mean": "mean_val", "scope_referentie": "vak_id"} + ) + # merge + keys = ["parameter", "vak_id", "ondergrondscenario_naam"] + df_compare = df_excel_vak.merge( + df_expanded_vak[keys + ["mean_val"]], + on=keys, + how="outer", + suffixes=("_excel", "_expanded"), + indicator=True, + ) + + tolerance = 1e-6 + + df_compare["verschil"] = np.abs( + df_compare["mean_val_excel"] - df_compare["mean_val_expanded"] + ) + df_errors = df_compare[ + (df_compare["_merge"] != "both") # ontbrekende rijen + | (df_compare["verschil"] > tolerance) + | ( + df_compare["mean_val_excel"].isna() + != df_compare["mean_val_expanded"].isna() + ) + ].dropna(subset=["distribution_type"]) + if len(df_errors) != 0: + print(f"Errors over vak: {len(df_errors)}") + print( + df_errors[ + [ + "parameter", + "vak_id", + "ondergrondscenario_naam", + "mean_val_excel", + "mean_val_expanded", + "verschil", + ] + ].head() + ) + + assert len(df_errors) == 0 + + +def test_utp( + df_expanded: pd.DataFrame, df_excel_utp: pd.DataFrame, utp_list: list +): + mask = df_expanded["uittredepunt_id"].isin(utp_list) + df_expanded_utp = df_expanded.loc[mask] + df_expanded_utp = df_expanded_utp.rename( + columns={"parameter_name": "parameter"} + ) + df_expanded_utp["mean_val"] = df_expanded_utp["parameter_input"].apply( + _extract_mean + ) + df_excel_utp = df_excel_utp.rename( + columns={"mean": "mean_val", "scope_referentie": "uittredepunt_id"} + ) + # merge + keys = ["parameter", "uittredepunt_id", "ondergrondscenario_naam"] + + df_compare = df_excel_utp.merge( + df_expanded_utp[keys + ["mean_val"]], + on=keys, + how="outer", + suffixes=("_excel", "_expanded"), + indicator=True, + ) + + tolerance = 1e-6 + + df_compare["verschil"] = np.abs( + df_compare["mean_val_excel"] - df_compare["mean_val_expanded"] + ) + df_errors = df_compare[ + (df_compare["_merge"] != "both") # ontbrekende rijen + | (df_compare["verschil"] > tolerance) + | ( + df_compare["mean_val_excel"].isna() + != df_compare["mean_val_expanded"].isna() + ) + ].dropna(subset=["distribution_type"]) + if len(df_errors) != 0: + print(f"Errors over utp: {len(df_errors)}") + print( + df_errors[ + [ + "parameter", + "vak_id", + "ondergrondscenario_naam", + "mean_val_excel", + "mean_val_expanded", + "verschil", + ] + ].head() + ) + + assert len(df_errors) == 0 + + +def test_expand(): + conn = sqlite3.connect(gpkg_filepath) + + # Verzamel data + df_excel_vak = pd.read_sql( + "SELECT * FROM data__excel_parameter_invoer WHERE scope == 'vak'", conn + ) + df_excel_utp = pd.read_sql( + "SELECT * FROM data__excel_parameter_invoer WHERE scope == 'uittredepunt'", + conn, + ) + df_expanded = pd.read_sql("SELECT * FROM data__expanded_parameters", conn) + + utp_list = df_excel_utp["scope_referentie"].unique().tolist() + + test_vak(df_expanded, df_excel_vak, utp_list) + test_utp(df_expanded, df_excel_utp, utp_list) + + +test_expand() From 5e301ffe452e549c77615e7354ac34e29637fd9d Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 9 Jun 2026 11:44:57 +0200 Subject: [PATCH 48/53] bugfix expended invoer table --- .../parameter_input/expand_input_tables.py | 213 ++++++++++-------- .../test_expand_input_tables.py | 13 +- 2 files changed, 129 insertions(+), 97 deletions(-) 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 35bb6330..d48a87e4 100644 --- a/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py +++ b/geoprob_pipe/cmd_app/parameter_input/expand_input_tables.py @@ -1,5 +1,5 @@ from typing import Dict, List, Optional -from pandas import DataFrame, isna, notna, concat, read_sql, read_csv, set_option +from pandas import DataFrame, Series, isna, notna, concat, read_sql, read_csv, set_option import sqlite3 import numpy as np import os @@ -9,6 +9,7 @@ from geoprob_pipe.cmd_app.parameter_input.input_parameter_tables import InputParameterTables from geoprob_pipe.utils.sql_contents import write_dfs_to_gpkg from probabilistic_library import FragilityValue +import copy def _combine_parameter_invoer_sources(tables: InputParameterTables) -> DataFrame: @@ -269,99 +270,133 @@ def _gather_required_input_parameters(geopackage_filepath: str) -> List[str]: # return ["gamma_sat_deklaag"] # TODO def _expand( - df_parameter_invoer_combined: DataFrame, df_identifiers: DataFrame, geopackage_filepath: str + 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) + + def merge_into_df(df: DataFrame, df_gather: DataFrame, on_cols: list[str]): + """Veilige merge + combine_first""" + if df_gather.empty: + return df + + df = df.merge( + df_gather, + on=on_cols, + how="left", + suffixes=("", "_new"), + ) + + df["parameter_input"] = df["parameter_input"].combine_first( + df["parameter_input_new"] + ) + df.drop(columns=["parameter_input_new"], inplace=True) + + return df + + 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_gather = df_gather[["scope_referentie", "ondergrondscenario_naam", "parameter_input"]] - df_gather = df_gather.rename(columns={ - "scope_referentie": "uittredepunt_id", - "ondergrondscenario_naam": "naam"}) - df = df_identifiers.copy(deep=True) - df["parameter_input"] = np.nan - 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["parameter_input"] != {}) + df = df_identifiers.copy() + df["parameter_input"] = Series([None] * len(df), dtype="object") + + # 1. excel uittrdepunt en scenario + df_gather = df_parameter_invoer_combined.loc[ + (df_parameter_invoer_combined["parameter"] == parameter_name) + & (df_parameter_invoer_combined["scope"] == "uittredepunt") + & (df_parameter_invoer_combined["ondergrondscenario_naam"].notna()), + ["scope_referentie", "ondergrondscenario_naam", "parameter_input"], + ].rename( + columns={ + "scope_referentie": "uittredepunt_id", + "ondergrondscenario_naam": "naam", + } + ).drop_duplicates(["uittredepunt_id", "naam"]) + + df = merge_into_df(df, df_gather, ["uittredepunt_id", "naam"]) + + # 2. GIS uittredepunt en scenario + df_gather = df_parameter_invoer_combined.loc[ + (df_parameter_invoer_combined["parameter"] == parameter_name) + & (df_parameter_invoer_combined["scope"] == "gis_uittredepunt") + & (df_parameter_invoer_combined["ondergrondscenario_naam"].notna()), + ["scope_referentie", "ondergrondscenario_naam", "parameter_input"], + ].rename( + columns={ + "scope_referentie": "uittredepunt_id", + "ondergrondscenario_naam": "naam", + } + ).drop_duplicates(["uittredepunt_id", "naam"]) + + df = merge_into_df(df, df_gather, ["uittredepunt_id", "naam"]) + + # 3. excel uittrdepunt + df_gather = df_parameter_invoer_combined.loc[ + (df_parameter_invoer_combined["parameter"] == parameter_name) + & (df_parameter_invoer_combined["scope"] == "uittredepunt") + & (df_parameter_invoer_combined["ondergrondscenario_naam"].isna()) + & (df_parameter_invoer_combined["parameter_input"] != {}), + ["scope_referentie", "parameter_input"], + ].rename(columns={"scope_referentie": "uittredepunt_id"}) \ + .drop_duplicates(["uittredepunt_id"]) + + df = merge_into_df(df, df_gather, ["uittredepunt_id"]) + + # 4. GIS uittredepunt + df_gather = df_parameter_invoer_combined.loc[ + (df_parameter_invoer_combined["parameter"] == parameter_name) + & (df_parameter_invoer_combined["scope"] == "gis_uittredepunt") + & (df_parameter_invoer_combined["parameter_input"] != {}), + ["scope_referentie", "parameter_input"], + ].rename(columns={"scope_referentie": "uittredepunt_id"}) \ + .drop_duplicates(["uittredepunt_id"]) + + df = merge_into_df(df, df_gather, ["uittredepunt_id"]) + + # 5. excel vak en scenario + df_gather = df_parameter_invoer_combined.loc[ + (df_parameter_invoer_combined["parameter"] == parameter_name) + & (df_parameter_invoer_combined["scope"] == "vak") + & (df_parameter_invoer_combined["ondergrondscenario_naam"].notna()), + ["scope_referentie", "ondergrondscenario_naam", "parameter_input"], + ].rename( + columns={ + "scope_referentie": "vak_id", + "ondergrondscenario_naam": "naam", + } + ).drop_duplicates(["vak_id", "naam"]) + + df = merge_into_df(df, df_gather, ["vak_id", "naam"]) + + # 6. excel vak + df_gather = df_parameter_invoer_combined.loc[ + (df_parameter_invoer_combined["parameter"] == parameter_name) + & (df_parameter_invoer_combined["scope"] == "vak") + & (df_parameter_invoer_combined["ondergrondscenario_naam"].isna()), + ["scope_referentie", "parameter_input"], + ].rename(columns={"scope_referentie": "vak_id"}) \ + .drop_duplicates(["vak_id"]) + + df = merge_into_df(df, df_gather, ["vak_id"]) + + # 7. excel traject + df_gather = df_parameter_invoer_combined.loc[ + (df_parameter_invoer_combined["parameter"] == parameter_name) + & (df_parameter_invoer_combined["scope"] == "traject") + ] + if not df_gather.empty: + value = df_gather.iloc[0]["parameter_input"] + mask_na = df["parameter_input"].isna() + + df.loc[mask_na, "parameter_input"] = [ + copy.deepcopy(value) for _ in range(mask_na.sum()) ] - 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_gather = df_gather[["scope_referentie", "ondergrondscenario_naam", "parameter_input"]] - df_gather = df_gather.rename(columns={ - "scope_referentie": "vak_id", - "ondergrondscenario_naam": "naam"}) - df['parameter_input'] = df['parameter_input'].combine_first( - df_identifiers.copy(deep=True).merge(df_gather, on=["vak_id", "naam"], how="left")['parameter_input']) - - # Vak 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'].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( - df_identifiers.copy(deep=True).merge(df_gather, on=["vak_id"], how="left")['parameter_input']) - - # Traject niveau - df_gather = df_parameter_invoer_combined[ - (df_parameter_invoer_combined['parameter'] == parameter_name) & - (df_parameter_invoer_combined['scope'] == 'traject')] - if df_gather.__len__() >= 1: - traject_value = df_gather['parameter_input'].values[0] - df['parameter_input'] = df['parameter_input'].apply(lambda x: traject_value if isna(x) else x) - - - - # Add to collection + collection_of_dfs[parameter_name] = df return collection_of_dfs diff --git a/tests/cmd_app/parameter_input/test_expand_input_tables.py b/tests/cmd_app/parameter_input/test_expand_input_tables.py index 67227376..215a38ec 100644 --- a/tests/cmd_app/parameter_input/test_expand_input_tables.py +++ b/tests/cmd_app/parameter_input/test_expand_input_tables.py @@ -5,7 +5,7 @@ import pandas as pd # TODO Permanete test gpkg als deze naar de nieuwe standaard is gezet -gpkg_filepath = r"C:\Users\vinji\Python\Libraries\GEOprob-Pipe\Workspace\data_test.geoprob_pipe.gpkg" +gpkg_filepath = r"C:\Users\vinji\Python\Libraries\GEOprob-Pipe\Workspace\fix.geoprob_pipe.gpkg" def _extract_mean(val): @@ -18,7 +18,7 @@ def _extract_mean(val): return np.nan -def test_vak( +def _vak( df_expanded: pd.DataFrame, df_excel_vak: pd.DataFrame, utp_list: list ): mask = df_expanded["uittredepunt_id"].isin(utp_list) @@ -73,7 +73,7 @@ def test_vak( assert len(df_errors) == 0 -def test_utp( +def _utp( df_expanded: pd.DataFrame, df_excel_utp: pd.DataFrame, utp_list: list ): mask = df_expanded["uittredepunt_id"].isin(utp_list) @@ -144,8 +144,5 @@ def test_expand(): utp_list = df_excel_utp["scope_referentie"].unique().tolist() - test_vak(df_expanded, df_excel_vak, utp_list) - test_utp(df_expanded, df_excel_utp, utp_list) - - -test_expand() + _vak(df_expanded, df_excel_vak, utp_list) + _utp(df_expanded, df_excel_utp, utp_list) From 82b2f68b7ad27532c7985d59f85e1249f9cecadc Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Tue, 9 Jun 2026 14:17:11 +0200 Subject: [PATCH 49/53] WIP test --- .../test_expand_input_tables.py | 81 +++++++++++++++---- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/tests/cmd_app/parameter_input/test_expand_input_tables.py b/tests/cmd_app/parameter_input/test_expand_input_tables.py index 215a38ec..b918bcf2 100644 --- a/tests/cmd_app/parameter_input/test_expand_input_tables.py +++ b/tests/cmd_app/parameter_input/test_expand_input_tables.py @@ -1,3 +1,8 @@ +# TODO fix parameter zowel per vak in excel en per utp in gis +# TODO fix gis parameters niet uit expanded gevonden? + + + import ast import sqlite3 @@ -19,9 +24,13 @@ def _extract_mean(val): def _vak( - df_expanded: pd.DataFrame, df_excel_vak: pd.DataFrame, utp_list: list + df_expanded: pd.DataFrame, + df_excel_vak: pd.DataFrame, + utp_list: list, + parameter: str, ): mask = df_expanded["uittredepunt_id"].isin(utp_list) + df_expanded_vak = df_expanded.loc[~mask] df_expanded_vak = df_expanded_vak.rename( columns={"parameter_name": "parameter"} @@ -42,7 +51,7 @@ def _vak( indicator=True, ) - tolerance = 1e-6 + tolerance = 1e-4 df_compare["verschil"] = np.abs( df_compare["mean_val_excel"] - df_compare["mean_val_expanded"] @@ -56,7 +65,7 @@ def _vak( ) ].dropna(subset=["distribution_type"]) if len(df_errors) != 0: - print(f"Errors over vak: {len(df_errors)}") + print(f"Errors over vak bij {parameter}: {len(df_errors)}") print( df_errors[ [ @@ -70,13 +79,17 @@ def _vak( ].head() ) - assert len(df_errors) == 0 + return df_errors def _utp( - df_expanded: pd.DataFrame, df_excel_utp: pd.DataFrame, utp_list: list + df_expanded: pd.DataFrame, + df_excel_utp: pd.DataFrame, + utp_list: list, + parameter: str, ): mask = df_expanded["uittredepunt_id"].isin(utp_list) + df_expanded_utp = df_expanded.loc[mask] df_expanded_utp = df_expanded_utp.rename( columns={"parameter_name": "parameter"} @@ -98,7 +111,7 @@ def _utp( indicator=True, ) - tolerance = 1e-6 + tolerance = 1e-4 df_compare["verschil"] = np.abs( df_compare["mean_val_excel"] - df_compare["mean_val_expanded"] @@ -112,12 +125,12 @@ def _utp( ) ].dropna(subset=["distribution_type"]) if len(df_errors) != 0: - print(f"Errors over utp: {len(df_errors)}") + print(f"Errors over utp bij {parameter}: {len(df_errors)}") print( df_errors[ [ "parameter", - "vak_id", + "uittredepunt_id", "ondergrondscenario_naam", "mean_val_excel", "mean_val_expanded", @@ -126,7 +139,7 @@ def _utp( ].head() ) - assert len(df_errors) == 0 + return df_errors def test_expand(): @@ -134,15 +147,55 @@ def test_expand(): # Verzamel data df_excel_vak = pd.read_sql( - "SELECT * FROM data__excel_parameter_invoer WHERE scope == 'vak'", conn + "SELECT * FROM data__excel_parameter_invoer WHERE scope = 'vak'", conn ) df_excel_utp = pd.read_sql( - "SELECT * FROM data__excel_parameter_invoer WHERE scope == 'uittredepunt'", + "SELECT * FROM data__excel_parameter_invoer WHERE scope = 'uittredepunt'", conn, ) + df_gis_utp = pd.read_sql( + "SELECT * FROM data__gis_parameter_invoer WHERE scope = 'uittredepunt'", + conn, + ) + if not df_excel_utp.empty: + df_utp = pd.concat( + [df_excel_utp, df_gis_utp], join="outer", ignore_index=True + ) + else: + df_utp = df_gis_utp + df_expanded = pd.read_sql("SELECT * FROM data__expanded_parameters", conn) - utp_list = df_excel_utp["scope_referentie"].unique().tolist() + df_errors = pd.DataFrame() + for param in df_expanded["parameter_name"].unique().tolist(): + mask_utp = df_utp["parameter"] == param + mask_vak = df_excel_vak["parameter"] == param + mask_expanded = df_expanded["parameter_name"] == param + utp_list = df_utp.loc[mask_utp, "scope_referentie"].unique().tolist() # type:ignore + + df_errors = pd.concat( + [ + df_errors, + _vak( + df_expanded=df_expanded[mask_expanded], + df_excel_vak=df_excel_vak[mask_vak], + utp_list=utp_list, + parameter=param, + ), + ] + ) + df_errors = pd.concat( + [ + df_errors, + _utp( + df_expanded=df_expanded[mask_expanded], + df_excel_utp=df_utp[mask_utp], + utp_list=utp_list, + parameter=param, + ), + ] + ) + assert len(df_errors) == 0 + - _vak(df_expanded, df_excel_vak, utp_list) - _utp(df_expanded, df_excel_utp, utp_list) +test_expand() From a8257f6813da1833faae54799808e57bbe6620c8 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Wed, 10 Jun 2026 15:36:50 +0200 Subject: [PATCH 50/53] validator stap 1 wip --- tests/cmd_app/parameter_input/test_expand.py | 191 ++++++++++++++++++ .../test_expand_input_tables.py | 7 +- 2 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 tests/cmd_app/parameter_input/test_expand.py diff --git a/tests/cmd_app/parameter_input/test_expand.py b/tests/cmd_app/parameter_input/test_expand.py new file mode 100644 index 00000000..684b5d76 --- /dev/null +++ b/tests/cmd_app/parameter_input/test_expand.py @@ -0,0 +1,191 @@ +# TODO fix parameter zowel per vak in excel en per utp in gis +# TODO fix gis parameters niet uit expanded gevonden? +""" +Voor idere rij in de excel en gis moet worden gecheckt of deze op de juiste +plaats in de expanded staat. En of er iets is overgeslagen door dubble input. +traject->vak->utp +scenario->wildcard +Mischien naar validation +""" + +import ast +import math +import sqlite3 + +import numpy as np +import pandas as pd + +# TODO Permanete test gpkg als deze naar de nieuwe standaard is gezet +gpkg_filepath = r"C:\Users\vinji\Python\Libraries\GEOprob-Pipe\Workspace\fix.geoprob_pipe.gpkg" + + +def get_mean(x): + if isinstance(x, dict): + return x.get("mean") + elif isinstance(x, str): + d = ast.literal_eval(x) # string → dict + return d.get("mean", np.nan) + return None + + +# --------------------------- +# 1. Prioriteitsfunctie +# --------------------------- + +def scope_priority(row): + if row["scope"] == "uittredepunt": + return 1 + if row["scope"] == "gis_uittredepunt": + return 2 + if row["scope"] == "vak": + return 3 + if row["scope"] == "traject": + return 4 + return 99 + + + +# --------------------------- +# 2. Matching functie +# --------------------------- + +def find_candidates(out_row, df_input): + p = out_row["parameter_name"] + vak = out_row["vak_id"] + uit = out_row["uittredepunt_id"] + scen = out_row["ondergrondscenario_naam"] + + df = df_input[df_input["parameter"] == p] + + candidates = [] + + # uittredepunt niveau (GEEN vak!) + candidates.append(df[ + (df["scope"].isin(["uittredepunt", "gis_uittredepunt"])) & + (df["scope_referentie"] == uit) + ]) + + # vak niveau (GEEN uittredepunt!) + candidates.append(df[ + (df["scope"] == "vak") & + (df["scope_referentie"] == vak) + ]) + + # traject + candidates.append(df[ + df["scope"] == "traject" + ]) + + candidates = pd.concat(candidates, ignore_index=True) + + if candidates.empty: + return candidates + + candidates = candidates.copy() + + candidates["scope_prio"] = candidates.apply(scope_priority, axis=1) + + candidates["is_exact_scenario"] = ( + candidates["ondergrondscenario_naam"] == scen + ) + + # scenario wildcard (fallback) + candidates = candidates[ + candidates["ondergrondscenario_naam"].isna() | + (candidates["ondergrondscenario_naam"] == scen) + ] + candidates = candidates[~candidates["mean"].isna()] + return candidates + + + +# --------------------------- +# 3. Validatie per rij +# --------------------------- + +def validate_row(out_row, df_input): + candidates = find_candidates(out_row, df_input) + + if candidates.empty: + return "NO_CANDIDATE" + + # beste kandidaat volgens regels + best = candidates.sort_values( + ["scope_prio", "is_exact_scenario"], + ascending=[True, False] + ).iloc[0] + + out_mean = get_mean(out_row["parameter_input"]) + + # --------------------------- + # 1. waarde check + # --------------------------- + if not math.isclose(out_mean, best["mean"], rel_tol=1e-6): + return "WRONG_MEAN" + + # --------------------------- + # 2. fallback gebruikt terwijl exact bestaat + # --------------------------- + same_scope = candidates[ + candidates["scope_prio"] == best["scope_prio"] + ] + + exact_exists = same_scope[same_scope["is_exact_scenario"]] + + if not best["is_exact_scenario"] and not exact_exists.empty: + return "FALLBACK_WHILE_EXACT_EXISTS" + + # --------------------------- + # 3. lagere scope gebruikt terwijl hogere bestaat + # --------------------------- + better_scope = candidates[ + candidates["scope_prio"] < best["scope_prio"] + ] + + if not better_scope.empty: + return "HIGHER_SCOPE_AVAILABLE" + + return "OK" + + + +# --------------------------- +# 4. Run validatie +# --------------------------- +def validate(df_out, df_input): + df_out = df_out.copy() + + df_out["validation"] = df_out.apply( + lambda r: validate_row(r, df_input), axis=1 + ) + + errors = df_out[df_out["validation"] != "OK"] + + return df_out, errors + + +# --------------------------- +# 5. Gebruik +# --------------------------- +conn = sqlite3.connect(gpkg_filepath) +df_out = pd.read_sql("SELECT * FROM data__expanded_parameters", conn) +df_excel = pd.read_sql("SELECT * FROM data__excel_parameter_invoer", conn) +df_gis = pd.read_sql("SELECT * FROM data__gis_parameter_invoer", conn) +df_gis["scope"] = "gis_uittredepunt" +df_input = pd.concat([df_excel, df_gis], ignore_index=True) + +df_input["ondergrondscenario_naam"] = ( + df_input["ondergrondscenario_naam"] + .replace("", pd.NA) +) + +df_input["scope_referentie"] = df_input["scope_referentie"].astype("Int64") +df_out["vak_id"] = df_out["vak_id"].astype("Int64") +df_out["uittredepunt_id"] = df_out["uittredepunt_id"].astype("Int64") +conn.close() + + +validated, errors = validate(df_out, df_input) + +print("Aantal fouten:", len(errors)) +print(errors.head()) diff --git a/tests/cmd_app/parameter_input/test_expand_input_tables.py b/tests/cmd_app/parameter_input/test_expand_input_tables.py index b918bcf2..618b3df5 100644 --- a/tests/cmd_app/parameter_input/test_expand_input_tables.py +++ b/tests/cmd_app/parameter_input/test_expand_input_tables.py @@ -1,6 +1,11 @@ # TODO fix parameter zowel per vak in excel en per utp in gis # TODO fix gis parameters niet uit expanded gevonden? - +""" +Voor idere rij in de excel en gis moet worden gecheckt of deze op de juiste +plaats in de expanded staat. En of er iets is overgeslagen door dubble input. +traject->vak->utp +scenario->wildcard +""" import ast From 855ad46a3a83a4b1690339cdd066b49b69087d8c Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 11 Jun 2026 10:42:43 +0200 Subject: [PATCH 51/53] validator voor de expanded-table --- tests/cmd_app/parameter_input/test_expand.py | 191 --------- .../test_expand_input_tables.py | 369 ++++++++++-------- 2 files changed, 197 insertions(+), 363 deletions(-) delete mode 100644 tests/cmd_app/parameter_input/test_expand.py diff --git a/tests/cmd_app/parameter_input/test_expand.py b/tests/cmd_app/parameter_input/test_expand.py deleted file mode 100644 index 684b5d76..00000000 --- a/tests/cmd_app/parameter_input/test_expand.py +++ /dev/null @@ -1,191 +0,0 @@ -# TODO fix parameter zowel per vak in excel en per utp in gis -# TODO fix gis parameters niet uit expanded gevonden? -""" -Voor idere rij in de excel en gis moet worden gecheckt of deze op de juiste -plaats in de expanded staat. En of er iets is overgeslagen door dubble input. -traject->vak->utp -scenario->wildcard -Mischien naar validation -""" - -import ast -import math -import sqlite3 - -import numpy as np -import pandas as pd - -# TODO Permanete test gpkg als deze naar de nieuwe standaard is gezet -gpkg_filepath = r"C:\Users\vinji\Python\Libraries\GEOprob-Pipe\Workspace\fix.geoprob_pipe.gpkg" - - -def get_mean(x): - if isinstance(x, dict): - return x.get("mean") - elif isinstance(x, str): - d = ast.literal_eval(x) # string → dict - return d.get("mean", np.nan) - return None - - -# --------------------------- -# 1. Prioriteitsfunctie -# --------------------------- - -def scope_priority(row): - if row["scope"] == "uittredepunt": - return 1 - if row["scope"] == "gis_uittredepunt": - return 2 - if row["scope"] == "vak": - return 3 - if row["scope"] == "traject": - return 4 - return 99 - - - -# --------------------------- -# 2. Matching functie -# --------------------------- - -def find_candidates(out_row, df_input): - p = out_row["parameter_name"] - vak = out_row["vak_id"] - uit = out_row["uittredepunt_id"] - scen = out_row["ondergrondscenario_naam"] - - df = df_input[df_input["parameter"] == p] - - candidates = [] - - # uittredepunt niveau (GEEN vak!) - candidates.append(df[ - (df["scope"].isin(["uittredepunt", "gis_uittredepunt"])) & - (df["scope_referentie"] == uit) - ]) - - # vak niveau (GEEN uittredepunt!) - candidates.append(df[ - (df["scope"] == "vak") & - (df["scope_referentie"] == vak) - ]) - - # traject - candidates.append(df[ - df["scope"] == "traject" - ]) - - candidates = pd.concat(candidates, ignore_index=True) - - if candidates.empty: - return candidates - - candidates = candidates.copy() - - candidates["scope_prio"] = candidates.apply(scope_priority, axis=1) - - candidates["is_exact_scenario"] = ( - candidates["ondergrondscenario_naam"] == scen - ) - - # scenario wildcard (fallback) - candidates = candidates[ - candidates["ondergrondscenario_naam"].isna() | - (candidates["ondergrondscenario_naam"] == scen) - ] - candidates = candidates[~candidates["mean"].isna()] - return candidates - - - -# --------------------------- -# 3. Validatie per rij -# --------------------------- - -def validate_row(out_row, df_input): - candidates = find_candidates(out_row, df_input) - - if candidates.empty: - return "NO_CANDIDATE" - - # beste kandidaat volgens regels - best = candidates.sort_values( - ["scope_prio", "is_exact_scenario"], - ascending=[True, False] - ).iloc[0] - - out_mean = get_mean(out_row["parameter_input"]) - - # --------------------------- - # 1. waarde check - # --------------------------- - if not math.isclose(out_mean, best["mean"], rel_tol=1e-6): - return "WRONG_MEAN" - - # --------------------------- - # 2. fallback gebruikt terwijl exact bestaat - # --------------------------- - same_scope = candidates[ - candidates["scope_prio"] == best["scope_prio"] - ] - - exact_exists = same_scope[same_scope["is_exact_scenario"]] - - if not best["is_exact_scenario"] and not exact_exists.empty: - return "FALLBACK_WHILE_EXACT_EXISTS" - - # --------------------------- - # 3. lagere scope gebruikt terwijl hogere bestaat - # --------------------------- - better_scope = candidates[ - candidates["scope_prio"] < best["scope_prio"] - ] - - if not better_scope.empty: - return "HIGHER_SCOPE_AVAILABLE" - - return "OK" - - - -# --------------------------- -# 4. Run validatie -# --------------------------- -def validate(df_out, df_input): - df_out = df_out.copy() - - df_out["validation"] = df_out.apply( - lambda r: validate_row(r, df_input), axis=1 - ) - - errors = df_out[df_out["validation"] != "OK"] - - return df_out, errors - - -# --------------------------- -# 5. Gebruik -# --------------------------- -conn = sqlite3.connect(gpkg_filepath) -df_out = pd.read_sql("SELECT * FROM data__expanded_parameters", conn) -df_excel = pd.read_sql("SELECT * FROM data__excel_parameter_invoer", conn) -df_gis = pd.read_sql("SELECT * FROM data__gis_parameter_invoer", conn) -df_gis["scope"] = "gis_uittredepunt" -df_input = pd.concat([df_excel, df_gis], ignore_index=True) - -df_input["ondergrondscenario_naam"] = ( - df_input["ondergrondscenario_naam"] - .replace("", pd.NA) -) - -df_input["scope_referentie"] = df_input["scope_referentie"].astype("Int64") -df_out["vak_id"] = df_out["vak_id"].astype("Int64") -df_out["uittredepunt_id"] = df_out["uittredepunt_id"].astype("Int64") -conn.close() - - -validated, errors = validate(df_out, df_input) - -print("Aantal fouten:", len(errors)) -print(errors.head()) diff --git a/tests/cmd_app/parameter_input/test_expand_input_tables.py b/tests/cmd_app/parameter_input/test_expand_input_tables.py index 618b3df5..c4fa6322 100644 --- a/tests/cmd_app/parameter_input/test_expand_input_tables.py +++ b/tests/cmd_app/parameter_input/test_expand_input_tables.py @@ -1,13 +1,10 @@ -# TODO fix parameter zowel per vak in excel en per utp in gis -# TODO fix gis parameters niet uit expanded gevonden? """ Voor idere rij in de excel en gis moet worden gecheckt of deze op de juiste -plaats in de expanded staat. En of er iets is overgeslagen door dubble input. +plaats in de expanded staat. En of er geen hogere prioriteit aanwezig is. traject->vak->utp scenario->wildcard """ - import ast import sqlite3 @@ -18,189 +15,217 @@ gpkg_filepath = r"C:\Users\vinji\Python\Libraries\GEOprob-Pipe\Workspace\fix.geoprob_pipe.gpkg" -def _extract_mean(val): - if pd.isna(val): - return np.nan - try: - d = ast.literal_eval(val) # string → dict +def get_mean(x): + if isinstance(x, dict): + return x.get("mean") + elif isinstance(x, str): + d = ast.literal_eval(x) # string → dict return d.get("mean", np.nan) - except Exception: - return np.nan + return None -def _vak( - df_expanded: pd.DataFrame, - df_excel_vak: pd.DataFrame, - utp_list: list, - parameter: str, -): - mask = df_expanded["uittredepunt_id"].isin(utp_list) +def _check_match(df_check: pd.DataFrame, df_compare: pd.DataFrame, key: str): + rel_tol = 1e-4 + col = key.replace("mean", "match") + mask_nan = df_compare[key].isna() - df_expanded_vak = df_expanded.loc[~mask] - df_expanded_vak = df_expanded_vak.rename( - columns={"parameter_name": "parameter"} - ) - df_expanded_vak["mean_val"] = df_expanded_vak["parameter_input"].apply( - _extract_mean + df_check[col] = np.isclose( + df_compare["mean"], df_compare[key], rtol=rel_tol ) - df_excel_vak = df_excel_vak.rename( - columns={"mean": "mean_val", "scope_referentie": "vak_id"} + + df_check[col] = df_check[col].mask(mask_nan, None) + + return df_check + + +def validate_expand_tables(): + # --- Verzamel data op uit database + conn = sqlite3.connect(gpkg_filepath) + df_out = pd.read_sql("SELECT * FROM data__expanded_parameters", conn) + df_excel = pd.read_sql("SELECT * FROM data__excel_parameter_invoer", conn) + df_excel["scope_referentie"] = df_excel["scope_referentie"].astype("Int64") + df_gis = pd.read_sql("SELECT * FROM data__gis_parameter_invoer", conn) + df_gis["scope_referentie"] = df_gis["scope_referentie"].astype("Int64") + df_gis["mean"] = df_gis["mean"].astype(float) + conn.close() + + df_gis["scope"] = "gis_uittredepunt" + # Verwijder lege kolommen + df_excel = df_excel.dropna(axis=1, how="all") + df_gis = df_gis.dropna(axis=1, how="all") + df_input = pd.concat([df_excel, df_gis], ignore_index=True) + + # --- Clean dataframes + df_input["ondergrondscenario_naam"] = df_input[ + "ondergrondscenario_naam" + ].replace("", pd.NA) + df_out["ondergrondscenario_naam"] = df_out[ + "ondergrondscenario_naam" + ].replace("", pd.NA) + df_out["uittredepunt_id"] = df_out["uittredepunt_id"].astype("Int64") + df_out = df_out.rename(columns={"parameter_name": "parameter"}) + + # Filter Dataframes + df_out["mean"] = df_out["parameter_input"].apply(get_mean) + df_out = df_out[ + [ + "parameter", + "vak_id", + "uittredepunt_id", + "ondergrondscenario_naam", + "mean", + ] + ] + df_input = df_input[ + [ + "parameter", + "scope", + "scope_referentie", + "ondergrondscenario_naam", + "mean", + ] + ] + + # --- Merge per stap + df_compare = df_out.copy() + + # Traject + df_traject = df_input.loc[df_input["scope"] == "traject"] + df_compare = df_compare.merge( + df_traject[["parameter", "mean"]], + on=["parameter"], + how="left", + suffixes=["", "_traject"], ) - # merge - keys = ["parameter", "vak_id", "ondergrondscenario_naam"] - df_compare = df_excel_vak.merge( - df_expanded_vak[keys + ["mean_val"]], - on=keys, - how="outer", - suffixes=("_excel", "_expanded"), - indicator=True, + + # Vak zonder scenario (Wildcard) + df_vak_wild = df_input.loc[ + (df_input["scope"] == "vak") + & (df_input["ondergrondscenario_naam"].isna()) + ] + df_vak_wild = df_vak_wild.rename(columns={"scope_referentie": "vak_id"}) + df_compare = df_compare.merge( + df_vak_wild[["parameter", "vak_id", "mean"]], + on=["parameter", "vak_id"], + how="left", + suffixes=["", "_vak_wild"], ) - tolerance = 1e-4 + # Vak met scenario + df_vak_scen = df_input.loc[ + (df_input["scope"] == "vak") + & (df_input["ondergrondscenario_naam"].notna()) + ] + df_vak_scen = df_vak_scen.rename(columns={"scope_referentie": "vak_id"}) + df_compare = df_compare.merge( + df_vak_scen[ + ["parameter", "vak_id", "ondergrondscenario_naam", "mean"] + ], + on=["parameter", "vak_id", "ondergrondscenario_naam"], + how="left", + suffixes=["", "_vak_scen"], + ) - df_compare["verschil"] = np.abs( - df_compare["mean_val_excel"] - df_compare["mean_val_expanded"] + # gis_utp zonder scenario (Wildcard) + df_gis_utp_wild = df_input.loc[ + (df_input["scope"] == "gis_uittredepunt") + & (df_input["ondergrondscenario_naam"].isna()) + ] + df_gis_utp_wild = df_gis_utp_wild.rename( + columns={"scope_referentie": "uittredepunt_id"} ) - df_errors = df_compare[ - (df_compare["_merge"] != "both") # ontbrekende rijen - | (df_compare["verschil"] > tolerance) - | ( - df_compare["mean_val_excel"].isna() - != df_compare["mean_val_expanded"].isna() - ) - ].dropna(subset=["distribution_type"]) - if len(df_errors) != 0: - print(f"Errors over vak bij {parameter}: {len(df_errors)}") - print( - df_errors[ - [ - "parameter", - "vak_id", - "ondergrondscenario_naam", - "mean_val_excel", - "mean_val_expanded", - "verschil", - ] - ].head() - ) - - return df_errors - - -def _utp( - df_expanded: pd.DataFrame, - df_excel_utp: pd.DataFrame, - utp_list: list, - parameter: str, -): - mask = df_expanded["uittredepunt_id"].isin(utp_list) - - df_expanded_utp = df_expanded.loc[mask] - df_expanded_utp = df_expanded_utp.rename( - columns={"parameter_name": "parameter"} + df_compare = df_compare.merge( + df_gis_utp_wild[["parameter", "uittredepunt_id", "mean"]], + on=["parameter", "uittredepunt_id"], + how="left", + suffixes=["", "_gis_utp_wild"], ) - df_expanded_utp["mean_val"] = df_expanded_utp["parameter_input"].apply( - _extract_mean + + # excel_upt zonder scenario (Wildcard) + df_excel_utp_wild = df_input.loc[ + (df_input["scope"] == "uittredepunt") + & (df_input["ondergrondscenario_naam"].isna()) + ] + df_excel_utp_wild = df_excel_utp_wild.rename( + columns={"scope_referentie": "uittredepunt_id"} ) - df_excel_utp = df_excel_utp.rename( - columns={"mean": "mean_val", "scope_referentie": "uittredepunt_id"} + df_compare = df_compare.merge( + df_excel_utp_wild[["parameter", "uittredepunt_id", "mean"]], + on=["parameter", "uittredepunt_id"], + how="left", + suffixes=["", "_excel_utp_wild"], ) - # merge - keys = ["parameter", "uittredepunt_id", "ondergrondscenario_naam"] - - df_compare = df_excel_utp.merge( - df_expanded_utp[keys + ["mean_val"]], - on=keys, - how="outer", - suffixes=("_excel", "_expanded"), - indicator=True, + # gis_utp met scenario + df_gis_utp_scen = df_input.loc[ + (df_input["scope"] == "gis_uittredepunt") + & (df_input["ondergrondscenario_naam"].notna()) + ] + df_gis_utp_scen = df_gis_utp_scen.rename( + columns={"scope_referentie": "uittredepunt_id"} ) - - tolerance = 1e-4 - - df_compare["verschil"] = np.abs( - df_compare["mean_val_excel"] - df_compare["mean_val_expanded"] + df_compare = df_compare.merge( + df_gis_utp_scen[ + ["parameter", "uittredepunt_id", "ondergrondscenario_naam", "mean"] + ], + on=["parameter", "uittredepunt_id", "ondergrondscenario_naam"], + how="left", + suffixes=["", "_gis_utp_scen"], ) - df_errors = df_compare[ - (df_compare["_merge"] != "both") # ontbrekende rijen - | (df_compare["verschil"] > tolerance) - | ( - df_compare["mean_val_excel"].isna() - != df_compare["mean_val_expanded"].isna() - ) - ].dropna(subset=["distribution_type"]) - if len(df_errors) != 0: - print(f"Errors over utp bij {parameter}: {len(df_errors)}") - print( - df_errors[ - [ - "parameter", - "uittredepunt_id", - "ondergrondscenario_naam", - "mean_val_excel", - "mean_val_expanded", - "verschil", - ] - ].head() - ) - - return df_errors - - -def test_expand(): - conn = sqlite3.connect(gpkg_filepath) - - # Verzamel data - df_excel_vak = pd.read_sql( - "SELECT * FROM data__excel_parameter_invoer WHERE scope = 'vak'", conn + # excel_utp met scenario + df_excel_utp_scen = df_input.loc[ + (df_input["scope"] == "uittredepunt") + & (df_input["ondergrondscenario_naam"].notna()) + ] + df_excel_utp_scen = df_excel_utp_wild.rename( + columns={"scope_referentie": "uittredepunt_id"} ) - df_excel_utp = pd.read_sql( - "SELECT * FROM data__excel_parameter_invoer WHERE scope = 'uittredepunt'", - conn, + df_compare = df_compare.merge( + df_excel_utp_scen[["parameter", "uittredepunt_id", "mean"]], + on=["parameter", "uittredepunt_id"], + how="left", + suffixes=["", "_excel_utp_scen"], ) - df_gis_utp = pd.read_sql( - "SELECT * FROM data__gis_parameter_invoer WHERE scope = 'uittredepunt'", - conn, + + # --- Check of waardes overeenkomen + + df_check = df_out.copy() + + df_check = _check_match(df_check, df_compare, "mean_traject") + df_check = _check_match(df_check, df_compare, "mean_vak_wild") + df_check = _check_match(df_check, df_compare, "mean_vak_scen") + df_check = _check_match(df_check, df_compare, "mean_gis_utp_wild") + df_check = _check_match(df_check, df_compare, "mean_excel_utp_wild") + df_check = _check_match(df_check, df_compare, "mean_gis_utp_scen") + df_check = _check_match(df_check, df_compare, "mean_excel_utp_scen") + + df_errors = df_out.copy() + cols = [ + "match_traject", + "match_vak_wild", + "match_vak_scen", + "match_gis_utp_wild", + "match_excel_utp_wild", + "match_gis_utp_scen", + "match_excel_utp_scen", + ] + df_errors["match"] = df_check[cols].any(axis=1) + + # Hoogste prioriteit check + df_errors["highest_priority"] = ( + df_check[cols].idxmax(axis=1).where(df_errors["match"], None) ) - if not df_excel_utp.empty: - df_utp = pd.concat( - [df_excel_utp, df_gis_utp], join="outer", ignore_index=True - ) - else: - df_utp = df_gis_utp - - df_expanded = pd.read_sql("SELECT * FROM data__expanded_parameters", conn) - - df_errors = pd.DataFrame() - for param in df_expanded["parameter_name"].unique().tolist(): - mask_utp = df_utp["parameter"] == param - mask_vak = df_excel_vak["parameter"] == param - mask_expanded = df_expanded["parameter_name"] == param - utp_list = df_utp.loc[mask_utp, "scope_referentie"].unique().tolist() # type:ignore - - df_errors = pd.concat( - [ - df_errors, - _vak( - df_expanded=df_expanded[mask_expanded], - df_excel_vak=df_excel_vak[mask_vak], - utp_list=utp_list, - parameter=param, - ), - ] - ) - df_errors = pd.concat( - [ - df_errors, - _utp( - df_expanded=df_expanded[mask_expanded], - df_excel_utp=df_utp[mask_utp], - utp_list=utp_list, - parameter=param, - ), - ] - ) - assert len(df_errors) == 0 - - -test_expand() + + arr = df_check[cols].to_numpy(dtype=object) + + df_errors["priority_error"] = [ + any(v is False for v in row[next((i for i, x in enumerate(row) if x is True), len(row))+1:]) + for row in arr + ] + + # Result + print(df_errors.loc[ + (~df_errors["match"]) | (df_errors["priority_error"]) + ]) + + +validate_expand_tables() From a33b7a4db72d39a7c7a9ee57d1dd067b5401f7fa Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 11 Jun 2026 10:54:15 +0200 Subject: [PATCH 52/53] volgorde fix --- tests/cmd_app/parameter_input/test_expand_input_tables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cmd_app/parameter_input/test_expand_input_tables.py b/tests/cmd_app/parameter_input/test_expand_input_tables.py index c4fa6322..63eae4e1 100644 --- a/tests/cmd_app/parameter_input/test_expand_input_tables.py +++ b/tests/cmd_app/parameter_input/test_expand_input_tables.py @@ -218,7 +218,7 @@ def validate_expand_tables(): arr = df_check[cols].to_numpy(dtype=object) df_errors["priority_error"] = [ - any(v is False for v in row[next((i for i, x in enumerate(row) if x is True), len(row))+1:]) + any(v is False for v in row[(max([i for i, x in enumerate(row) if x is True], default=-1) + 1):]) for row in arr ] From 9f9f56176a290af9b28740482b407432678d7353 Mon Sep 17 00:00:00 2001 From: Vincent Jilesen Date: Thu, 18 Jun 2026 13:00:40 +0200 Subject: [PATCH 53/53] hrd fix en correctie in element_list --- geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py | 3 +-- geoprob_pipe/results/construct_dataframes.py | 12 ++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py b/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py index fc3ae11c..c32f0562 100644 --- a/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py +++ b/geoprob_pipe/cmd_app/spatial_layers/hrd/hrd.py @@ -54,9 +54,8 @@ def _hrd_data_imported(app_settings: ApplicationSettings) -> bool: cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") tables_names = [row[0] for row in cursor.fetchall()] conn.close() - if "fragility_values_invoer_hrd" not in tables_names: + if "data__fragility_values_invoer_hrd" not in tables_names: return False - return True diff --git a/geoprob_pipe/results/construct_dataframes.py b/geoprob_pipe/results/construct_dataframes.py index b5a62ba7..f9598452 100644 --- a/geoprob_pipe/results/construct_dataframes.py +++ b/geoprob_pipe/results/construct_dataframes.py @@ -428,7 +428,7 @@ def _generate_element_list( punt_df = results.df_beta_uittredepunten punt_gdf = geoprob_pipe.input_data.uittredepunten.gdf - df = pd.merge( + df_utp = pd.merge( left=punt_df[ [ "uittredepunt_id", @@ -455,22 +455,22 @@ def _generate_element_list( for _, vak in vakken_gdf.iterrows(): if vak.id in vakken_torun or run_all: - df_vak = df.loc[df["vak_id"] == vak["id"]] + df_vak = df_utp.loc[df_utp["vak_id"] == vak["id"]] - df = geoprob_pipe.df_expanded.loc[ + df_a = geoprob_pipe.df_expanded.loc[ geoprob_pipe.df_expanded["parameter_name"] == "a_vak" ] a_vak: float = ( - df.query("vak_id == @vak.id") + df_a.query("vak_id == @vak.id") .iloc[0]["parameter_input"] .get("mean", 1.0) ) - df = geoprob_pipe.df_expanded.loc[ + df_dl = geoprob_pipe.df_expanded.loc[ geoprob_pipe.df_expanded["parameter_name"] == "delta_length" ] dl_vak: float = ( - df.query("vak_id == @vak.id") + df_dl.query("vak_id == @vak.id") .iloc[0]["parameter_input"] .get("mean", 300.0) )