From f745dce04ee811fe6adef7b9a25a9c4eb4462112 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Tue, 14 May 2024 15:14:29 +0200 Subject: [PATCH 01/45] debug --- src/View/Geometry/MeshingDialog.py | 14 -------------- src/View/Geometry/Window.py | 2 -- 2 files changed, 16 deletions(-) diff --git a/src/View/Geometry/MeshingDialog.py b/src/View/Geometry/MeshingDialog.py index 974aa187..852c272a 100644 --- a/src/View/Geometry/MeshingDialog.py +++ b/src/View/Geometry/MeshingDialog.py @@ -125,14 +125,6 @@ class MeshingDialog(PamhyrDialog): def lplan(self): return self._lplan - @property - def origin(self): - return self._origin - - @property - def lm(self): - return int(self._lm) - @property def linear(self): return self._linear @@ -165,15 +157,9 @@ class MeshingDialog(PamhyrDialog): self._begin_cs = self.profiles.index(p1) self._end_cs = self.profiles.index(p2) - origin = self.get_combobox_text("comboBox_origin") - self._origin = self.profiles.index(origin) - self._begin_dir = self.get_combobox_text("comboBox_begin_gl") self._end_dir = self.get_combobox_text("comboBox_end_gl") - r_lm_dict = self._trad.get_dict("r_lm_dict") - self._lm = r_lm_dict[self.get_combobox_text("comboBox_lm")] - super().accept() def reject(self): diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 5e13a1dc..bf9079f2 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -298,10 +298,8 @@ class GeometryWindow(PamhyrWindow): data = { "step": dlg.space_step, "limites": [dlg.begin_cs, dlg.end_cs], - "origin": dlg.origin, "directrices": [dlg.begin_dir, dlg.end_dir], "lplan": dlg.lplan, - "lm": dlg.lm, "linear": dlg.linear, } self._edit_meshing(data) From 78e361d48691dcbb11c1eea3ffc3c1da2b5d3a61 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Thu, 16 May 2024 13:01:03 +0200 Subject: [PATCH 02/45] debug issue #57 --- src/View/Geometry/PlotAC.py | 19 +++++++++++++++++++ src/View/Geometry/Window.py | 23 ++++++++++++++--------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/View/Geometry/PlotAC.py b/src/View/Geometry/PlotAC.py index cccffe24..a8892814 100644 --- a/src/View/Geometry/PlotAC.py +++ b/src/View/Geometry/PlotAC.py @@ -82,12 +82,14 @@ class PlotAC(PamhyrPlot): label=self.label_previous_plot_selected, lw=1.5, linestyle='--', color=self.color_plot_previous ) + #self.previous_plot_selected.set_visible(False) self.plot_selected, = self.canvas.axes.plot( station, elevation, label=self.label_plot_selected, color=self.color_plot_current, lw=1.5 ) + #self.plot_selected.set_visible(False) next_id = profile_id + 1 station_next = self.data.profile(next_id).get_station() @@ -98,6 +100,8 @@ class PlotAC(PamhyrPlot): label=self.label_next_plot_selected, color=self.color_plot_next, lw=1.6, linestyle='--' ) + #self.next_plot_selected.set_visible(False) + self.canvas.axes.set_visible(False) def draw_gl(self): if self._current_data_update: @@ -106,6 +110,7 @@ class PlotAC(PamhyrPlot): profile_id = 0 profile = self.data.profile(profile_id) + if profile == None: return station = profile.get_station() elevation = profile.z() gl = profile.names() @@ -160,6 +165,9 @@ class PlotAC(PamhyrPlot): self.draw() return + if self.data is None: + return + self.update_current() self.update_gl() @@ -171,6 +179,10 @@ class PlotAC(PamhyrPlot): previous_id = profile_id - 1 next_id = profile_id + 1 + self.previous_plot_selected.set_visible(False) + self.plot_selected.set_visible(False) + self.next_plot_selected.set_visible(False) + self.previous_plot_selected.set_data([], []) self.plot_selected.set_data([], []) self.next_plot_selected.set_data([], []) @@ -180,18 +192,25 @@ class PlotAC(PamhyrPlot): self.data.profile(previous_id).get_station(), self.data.profile(previous_id).z() ) + self.previous_plot_selected.set_visible(True) + #self.canvas.axes.legend() if 0 <= profile_id < self.data.number_profiles: self.plot_selected.set_data( self.data.profile(profile_id).get_station(), self.data.profile(profile_id).z() ) + self.plot_selected.set_visible(True) + #self.canvas.axes.legend() if 0 <= next_id < self.data.number_profiles: self.next_plot_selected.set_data( self.data.profile(next_id).get_station(), self.data.profile(next_id).z() ) + self.next_plot_selected.set_visible(True) + #self.canvas.axes.legend() + self.canvas.axes.set_visible(True) def update_full(self): self.draw() diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index bf9079f2..b624aa1c 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -157,6 +157,7 @@ class GeometryWindow(PamhyrWindow): def _compute_status_label(self): row = self.index_selected_row() + if row == None: return profile = self._reach.profile(row) name = profile.name + " " + str(profile.kp) @@ -402,7 +403,7 @@ class GeometryWindow(PamhyrWindow): def update_plot_ac(self, ind: int): self.tableView.model().blockSignals(True) - self._plot_ac.current = ind + #self._plot_ac.current = ind self._plot_ac.update() self.tableView.model().blockSignals(False) @@ -446,10 +447,8 @@ class GeometryWindow(PamhyrWindow): def select_current_profile(self): self.tableView.model().blockSignals(True) - - if len(self.tableView.selectedIndexes()) > 0: - row = self.index_selected_row() - + row = self.index_selected_row() + if row != None: self.find(QSlider, "verticalSlider").setValue(row) self.select_plot_xy(row) self.select_plot_kpc(row) @@ -508,10 +507,14 @@ class GeometryWindow(PamhyrWindow): self._table.delete(rows) def index_selected_row(self): - return self.tableView\ - .selectionModel()\ - .selectedRows()[0]\ - .row() + r = self.tableView\ + .selectionModel()\ + .selectedRows() + + if len(r) > 0: + return r[0].row() + else: + return None def sort_ascending(self): self._table.sort_profiles(False) @@ -526,11 +529,13 @@ class GeometryWindow(PamhyrWindow): def move_up(self): row = self.index_selected_row() + if row == None: return self._table.move_up(row) self.select_current_profile() def move_down(self): row = self.index_selected_row() + if row == None: return self._table.move_down(row) self.select_current_profile() From c366a1a4e76700985cfe9f428558450480304144 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Thu, 16 May 2024 18:06:53 +0200 Subject: [PATCH 03/45] increase precision of input sediment diameter --- src/View/ui/Widgets/d50sigma.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/View/ui/Widgets/d50sigma.ui b/src/View/ui/Widgets/d50sigma.ui index d1af908b..5518cbcd 100644 --- a/src/View/ui/Widgets/d50sigma.ui +++ b/src/View/ui/Widgets/d50sigma.ui @@ -22,7 +22,7 @@ Qt::Horizontal - + @@ -37,13 +37,13 @@ - 4 + 8 - + From 783d83e4cc4969c48d39d5ac9db988db643ae24f Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 09:15:37 +0200 Subject: [PATCH 04/45] Trad: Update french translate. --- src/Checker/Mage.py | 8 +- src/Checker/Study.py | 6 +- src/View/BoundaryCondition/translate.py | 2 +- src/View/Frictions/translate.py | 8 +- src/View/Geometry/Profile/Table.py | 20 - src/View/Geometry/Translate.py | 8 +- .../BasicHydraulicStructures/Translate.py | 4 +- .../LateralContribution/Edit/translate.py | 2 +- src/View/LateralContribution/translate.py | 8 +- src/View/Results/CustomPlot/Translate.py | 6 +- src/View/Results/PlotSedReach.py | 2 +- src/View/SolverParameters/translate.py | 8 +- src/View/Stricklers/translate.py | 2 +- src/View/Tools/Plot/PamhyrToolbar.py | 12 +- src/View/Translate.py | 4 +- src/View/ui/BoundaryConditions.ui | 10 +- src/View/ui/ConfigureDialog.ui | 10 +- src/View/ui/DebugRepl.ui | 2 +- src/View/ui/EditBoundaryConditions.ui | 4 +- src/View/ui/EditLateralContribution.ui | 4 +- src/View/ui/Frictions.ui | 5 +- src/View/ui/GeometryCrossSection.ui | 10 +- src/View/ui/GeometryReach.ui | 12 +- src/View/ui/InitialConditions.ui | 2 +- src/View/ui/LateralContributions.ui | 10 +- src/View/ui/MainWindow.ui | 28 +- src/View/ui/MeshingOptions.ui | 12 +- src/View/ui/NewStudy.ui | 2 +- src/View/ui/REPLineDialog.ui | 2 +- src/View/ui/REPLineList.ui | 6 +- src/View/ui/ReachSedimentLayers.ui | 4 +- src/View/ui/Reservoir.ui | 4 +- src/View/ui/ReservoirList.ui | 6 +- src/View/ui/Results.ui | 6 +- src/View/ui/Stricklers.ui | 10 +- src/View/ui/Widgets/MainWindowTabInfo.ui | 2 +- src/lang/fr.ts | 1118 +++++++++-------- 37 files changed, 741 insertions(+), 628 deletions(-) diff --git a/src/Checker/Mage.py b/src/Checker/Mage.py index e7f8352b..acb2ddc8 100644 --- a/src/Checker/Mage.py +++ b/src/Checker/Mage.py @@ -206,11 +206,11 @@ class MageGeometryGuideLineChecker(StudyGeometryChecker): def __init__(self, version="mage8"): super(MageGeometryGuideLineChecker, self).__init__() - self._name = _translate("Checker", "Mage geometry guide line checker") + self._name = _translate("Checker", "Mage geometry guideline checker") self._description = _translate( "Checker", - "Check if exists geometry guide line is correctly defined \ -for each reaches of the study" + "Check if exists geometry guidelines are correctly defined \ +for each reach" ) self._solver = version self._modules = Modules.GEOMETRY @@ -241,7 +241,7 @@ for each reaches of the study" for profile in profiles: if not profile.has_standard_named_points(): self._status = STATUS.WARNING - self._summary = "no_standard_guileline_defined" + self._summary = "no_standard_guideline_defined" return False for gl in gls[1:]: diff --git a/src/Checker/Study.py b/src/Checker/Study.py index f0d69262..b893a507 100644 --- a/src/Checker/Study.py +++ b/src/Checker/Study.py @@ -34,9 +34,9 @@ class StudyNetworkReachChecker(AbstractModelChecker): def __init__(self): super(StudyNetworkReachChecker, self).__init__() - self._name = _translate("Checker", "Study network reach checker") + self._name = _translate("Checker", "Study reach network checker") self._description = _translate( - "Checker", "Check if exists at least one reach for study" + "Checker", "Check if exists at least one reach exists" ) self._modules = Modules.NETWORK @@ -63,7 +63,7 @@ class StudyGeometryChecker(AbstractModelChecker): self._name = _translate("Checker", "Study geometry checker") self._description = _translate( - "Checker", "Check if exists geometry for each reach of study" + "Checker", "Check if the geometry of each reach exists" ) self._modules = Modules.GEOMETRY diff --git a/src/View/BoundaryCondition/translate.py b/src/View/BoundaryCondition/translate.py index 19244076..02903dae 100644 --- a/src/View/BoundaryCondition/translate.py +++ b/src/View/BoundaryCondition/translate.py @@ -48,7 +48,7 @@ class BCTranslate(MainTranslate): self._sub_dict["long_types"] = { "ND": self._dict["not_defined"], - "PC": _translate("BoundaryCondition", "Ponctual contribution"), + "PC": _translate("BoundaryCondition", "Point sources"), "TZ": _translate("BoundaryCondition", "Z(t)"), "TD": _translate("BoundaryCondition", "Q(t)"), "ZD": _translate("BoundaryCondition", "Q(Z)"), diff --git a/src/View/Frictions/translate.py b/src/View/Frictions/translate.py index 57b823a7..3286e2e2 100644 --- a/src/View/Frictions/translate.py +++ b/src/View/Frictions/translate.py @@ -39,8 +39,8 @@ class FrictionsTranslate(MainTranslate): self._sub_dict["table_headers"] = { # "name": self._dict["name"], # "edge": self._dict["reach"], - "begin_kp": _translate("Frictions", "Begin kp (m)"), - "end_kp": _translate("Frictions", "End kp (m)"), - "begin_strickler": _translate("Frictions", "Begin strickler"), - "end_strickler": _translate("Frictions", "End strickler"), + "begin_kp": _translate("Frictions", "Start (m)"), + "end_kp": _translate("Frictions", "End (m)"), + "begin_strickler": _translate("Frictions", "Start coefficient"), + "end_strickler": _translate("Frictions", "End coefficient"), } diff --git a/src/View/Geometry/Profile/Table.py b/src/View/Geometry/Profile/Table.py index 21e202f8..5974eb7c 100644 --- a/src/View/Geometry/Profile/Table.py +++ b/src/View/Geometry/Profile/Table.py @@ -82,16 +82,6 @@ class GeometryProfileTableModel(PamhyrTableModel): elif value == self._data.z_max(): return QColor("blue") - if role == Qt.ToolTipRole: - if value == self._data.z_min(): - return _translate("MainWindowProfile", - "La cote du fond", - "Z minimale") - elif value == self._data.z_max(): - return _translate("MainWindowProfile", - "La cote maximale", - "Z maximale") - if index.column() == 3: value = self._data.point(index.row()).name @@ -104,16 +94,6 @@ class GeometryProfileTableModel(PamhyrTableModel): if role == Qt.ForegroundRole: return QColor("darkRed") - if role == Qt.ToolTipRole: - if value.strip().upper() == "RG": - return _translate( - "MainWindowProfile", "Rive gauche" - ) - else: - return _translate( - "MainWindowProfile", "Rive droite" - ) - return QVariant() def setData(self, index, value, role=Qt.EditRole): diff --git a/src/View/Geometry/Translate.py b/src/View/Geometry/Translate.py index ec8c451a..85348ded 100644 --- a/src/View/Geometry/Translate.py +++ b/src/View/Geometry/Translate.py @@ -33,12 +33,12 @@ class GeometryTranslate(MainTranslate): self._dict["open_file"] = _translate("Geometry", "Open a file") self._dict["file_st"] = _translate( - "Geometry", "File mage geometry (*.ST *.st)") + "Geometry", "Mage geometry file (*.ST *.st)") self._dict["file_m"] = _translate( - "Geometry", "File mage meshed geometry (*.M *.m)") + "Geometry", "Mage meshed geometry file (*.M *.m)") self._dict["file_shp"] = _translate( "Geometry", "Shapefile (*.SHP *.shp)") - self._dict["file_all"] = _translate("Geometry", "All file (*)") + self._dict["file_all"] = _translate("Geometry", "All files (*)") self._dict["cross_section"] = _translate("Geometry", "cross-section") self._dict["cross_sections"] = _translate("Geometry", "cross-sections") @@ -70,7 +70,7 @@ class GeometryTranslate(MainTranslate): "2": _translate("Geometry", "the second guide-line"), "3": _translate( "Geometry", - "the means between the two guide-lines" + "the mean over the two guide-lines" ), } diff --git a/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py b/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py index f55fb2d7..29a12f35 100644 --- a/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py +++ b/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py @@ -28,7 +28,7 @@ class BasicHydraulicStructuresTranslate(MainTranslate): super(BasicHydraulicStructuresTranslate, self).__init__() self._dict["Basic Hydraulic Structures"] = _translate( - "BasicHydraulicStructures", "Basic Hydraulic Structures" + "BasicHydraulicStructures", "Basic Hydraulic Structure" ) self._dict['msg_type_change_title'] = _translate( @@ -138,7 +138,7 @@ hydraulic structure values?" "BasicHydraulicStructures", "Check valve" ), "UD": _translate( - "BasicHydraulicStructures", "User defined" + "BasicHydraulicStructures", "User-defined" ), } diff --git a/src/View/LateralContribution/Edit/translate.py b/src/View/LateralContribution/Edit/translate.py index eeb88930..14b23772 100644 --- a/src/View/LateralContribution/Edit/translate.py +++ b/src/View/LateralContribution/Edit/translate.py @@ -28,7 +28,7 @@ class LCETranslate(LCTranslate): def __init__(self): super(LCETranslate, self).__init__() self._dict["Edit lateral contribution"] = _translate( - "LateralContribution", "Edit lateral contribution" + "LateralContribution", "Edit lateral sources" ) self._sub_dict["table_headers"] = { diff --git a/src/View/LateralContribution/translate.py b/src/View/LateralContribution/translate.py index 145e137f..e6d4225c 100644 --- a/src/View/LateralContribution/translate.py +++ b/src/View/LateralContribution/translate.py @@ -39,12 +39,12 @@ class LCTranslate(MainTranslate): super(LCTranslate, self).__init__() self._dict["Lateral contribution"] = _translate( - "LateralContribution", "Lateral contribution" + "LateralContribution", "Lateral sources" ) self._sub_dict["long_types"] = { "ND": self._dict["not_defined"], - "LC": _translate("LateralContribution", "Lateral contribution"), + "LC": _translate("LateralContribution", "Lateral sources"), "RA": _translate("LateralContribution", "Rain"), "EV": _translate("LateralContribution", "Evaporation"), } @@ -57,6 +57,6 @@ class LCTranslate(MainTranslate): "name": self._dict["name"], "type": self._dict["type"], "edge": self._dict["reach"], - "begin_kp": _translate("LateralContribution", "Begin kp (m)"), - "end_kp": _translate("LateralContribution", "End kp (m)") + "begin_kp": _translate("LateralContribution", "Start (m)"), + "end_kp": _translate("LateralContribution", "End (m)") } diff --git a/src/View/Results/CustomPlot/Translate.py b/src/View/Results/CustomPlot/Translate.py index 6c4236b8..4c4f3815 100644 --- a/src/View/Results/CustomPlot/Translate.py +++ b/src/View/Results/CustomPlot/Translate.py @@ -28,7 +28,7 @@ class CustomPlotTranslate(ResultsTranslate): super(CustomPlotTranslate, self).__init__() self._dict["Custom Plot Selection"] = _translate( - "CustomPlot", "Custom Plot Selection" + "CustomPlot", "Custom plot selection" ) # Value type @@ -38,13 +38,13 @@ class CustomPlotTranslate(ResultsTranslate): self._dict['water_elevation'] = self._dict["unit_water_elevation"] self._dict['discharge'] = self._dict["unit_discharge"] self._dict['elevation'] = _translate( - "CustomPlot", "Bed load elevation (m)" + "CustomPlot", "Bed elevation (m)" ) # Unit corresponding long name (plot axes display) self._dict['0-meter'] = _translate( - "CustomPlot", "Bed load elevation (m)" + "CustomPlot", "Bed elevation (m)" ) self._dict['1-m3s'] = self._dict["unit_discharge"] diff --git a/src/View/Results/PlotSedReach.py b/src/View/Results/PlotSedReach.py index d77339a1..f62c5123 100644 --- a/src/View/Results/PlotSedReach.py +++ b/src/View/Results/PlotSedReach.py @@ -231,7 +231,7 @@ class PlotSedReach(PamhyrPlot): return self.canvas.axes.set_xlabel( - _translate("MainWindow_reach", "Kp (m)"), + _translate("MainWindow_reach", "Position (m)"), color='black', fontsize=10 ) self.canvas.axes.set_ylabel( diff --git a/src/View/SolverParameters/translate.py b/src/View/SolverParameters/translate.py index c1a45d2b..46bae698 100644 --- a/src/View/SolverParameters/translate.py +++ b/src/View/SolverParameters/translate.py @@ -99,7 +99,7 @@ class ParamTranslate(MainTranslate): "Minimum water height (meter)"), "mage_max_niter": _translate("SolverParameters", - "Maximun number of iterations (< 100)"), + "Maximum number of iterations (< 100)"), "mage_timestep_reduction_factor": _translate("SolverParameters", "Timestep reduction factor"), @@ -114,10 +114,10 @@ class ParamTranslate(MainTranslate): "Reduction precision factor of residue"), "mage_niter_max_precision": _translate("SolverParameters", - "Number of iteration at maximum precision"), + "Number of iterations at maximum precision"), "mage_niter_before_switch": _translate("SolverParameters", - "Number of iteration before switch"), + "Number of iterations before switch"), "mage_max_froude": _translate("SolverParameters", "Maximum accepted Froude number"), @@ -152,7 +152,7 @@ class ParamTranslate(MainTranslate): "mage_methode_modification_geometrie": _translate("SolverParameters", "Geometry modification method"), "mage_shields_critique": - _translate("SolverParameters", "Critic shields"), + _translate("SolverParameters", "Critical Shields number"), "mage_shields_correction": _translate("SolverParameters", "Shields correction"), "mage_capacite_solide": diff --git a/src/View/Stricklers/translate.py b/src/View/Stricklers/translate.py index 01275bb1..eb8b5361 100644 --- a/src/View/Stricklers/translate.py +++ b/src/View/Stricklers/translate.py @@ -28,7 +28,7 @@ class StricklersTranslate(MainTranslate): super(StricklersTranslate, self).__init__() self._dict["Stricklers"] = _translate( - "Stricklers", "Stricklers" + "Stricklers", "Strickler coefficients" ) self._sub_dict["table_headers"] = { diff --git a/src/View/Tools/Plot/PamhyrToolbar.py b/src/View/Tools/Plot/PamhyrToolbar.py index 2a851c92..5b4e2927 100644 --- a/src/View/Tools/Plot/PamhyrToolbar.py +++ b/src/View/Tools/Plot/PamhyrToolbar.py @@ -112,7 +112,7 @@ class PamhyrPlotToolbar(NavigationToolbar2QT): self.toolitems.append( ( 'Forward', - _translate("Toolbar", 'Return to next view'), + _translate("Toolbar", 'Back to next view'), 'forward', 'forward' ) ) @@ -121,7 +121,7 @@ class PamhyrPlotToolbar(NavigationToolbar2QT): self.toolitems.append( ( 'Pan', - _translate("Toolbar", 'Axes panoramic'), + _translate("Toolbar", 'Panoramic axes'), 'move', 'pan' ) ) @@ -184,7 +184,7 @@ class PamhyrPlotToolbar(NavigationToolbar2QT): self.toolitems.append( ( 'Save', - _translate("Toolbar", 'Save the figure'), + _translate("Toolbar", 'Save figure'), 'filesave', 'save_figure' ) ) @@ -253,12 +253,12 @@ class PamhyrPlotToolbar(NavigationToolbar2QT): self._actions['back'].setToolTip( _translate("Toolbar", "Back to previous view")) self._actions['forward'].setToolTip( - _translate("Toolbar", "Return to next view")) + _translate("Toolbar", "Back to next view")) self._actions['pan'].setToolTip( - _translate("Toolbar", "Axes panoramic")) + _translate("Toolbar", "Panoramic axes")) self._actions['zoom'].setToolTip(_translate("Toolbar", "Zoom")) self._actions['save_figure'].setToolTip( - _translate("Toolbar", "Save the figure")) + _translate("Toolbar", "Save figure")) self.action_isometric_view.setToolTip( _translate("Toolbar", "Isometric view (Shift+W)")) self.action_auto_global_view.setToolTip( diff --git a/src/View/Translate.py b/src/View/Translate.py index fc91a516..2061d691 100644 --- a/src/View/Translate.py +++ b/src/View/Translate.py @@ -52,7 +52,7 @@ class UnitTranslate(CommonWordTranslate): def __init__(self): super(UnitTranslate, self).__init__() - self._dict["unit_kp"] = _translate("Unit", "KP (m)") + self._dict["unit_kp"] = _translate("Unit", "Position (m)") self._dict["unit_width"] = _translate("Unit", "Width (m)") self._dict["unit_height"] = _translate("Unit", "Height (m)") self._dict["unit_diameter"] = _translate("Unit", "Diameter (m)") @@ -90,5 +90,5 @@ class MainTranslate(UnitTranslate): "MainWindow", "Open SQLite debuging tool ('sqlitebrowser')" ) self._dict["active_window"] = _translate( - "MainWindow", "Activate this window" + "MainWindow", "Enable this window" ) diff --git a/src/View/ui/BoundaryConditions.ui b/src/View/ui/BoundaryConditions.ui index 9f2f1b99..e023eff0 100644 --- a/src/View/ui/BoundaryConditions.ui +++ b/src/View/ui/BoundaryConditions.ui @@ -37,7 +37,7 @@ - 0 + 2 @@ -61,7 +61,7 @@ - Suspenssion + Suspension @@ -114,7 +114,7 @@ Add - Add a new boundary condition or punctual contribution + Add a new boundary condition or point source Ctrl+N @@ -144,7 +144,7 @@ Edit - Edit boundary condition or punctual contribution + Edit boundary condition or point source Ctrl+E @@ -159,7 +159,7 @@ Sort - Sort boundary condition by name + Sort by names diff --git a/src/View/ui/ConfigureDialog.ui b/src/View/ui/ConfigureDialog.ui index 590d0ca2..c6477f86 100644 --- a/src/View/ui/ConfigureDialog.ui +++ b/src/View/ui/ConfigureDialog.ui @@ -25,7 +25,7 @@ true - 0 + 4 false @@ -164,7 +164,7 @@ - Frequence + Frequency @@ -349,7 +349,7 @@ - This value must be used for reading or editing files in speficic case. + This value must be used for reading or editing files in speficic cases. @@ -374,7 +374,7 @@ - - The "@file" keyworkd is replace by the path of file to open. + - The "@file" keyword is replaced by the path of file to open. @@ -382,7 +382,7 @@ - Language + Langue diff --git a/src/View/ui/DebugRepl.ui b/src/View/ui/DebugRepl.ui index db4d069e..39f30ac3 100644 --- a/src/View/ui/DebugRepl.ui +++ b/src/View/ui/DebugRepl.ui @@ -23,7 +23,7 @@ - Eval + Evaluate diff --git a/src/View/ui/EditBoundaryConditions.ui b/src/View/ui/EditBoundaryConditions.ui index bfcf9505..b27232d2 100644 --- a/src/View/ui/EditBoundaryConditions.ui +++ b/src/View/ui/EditBoundaryConditions.ui @@ -86,7 +86,7 @@ Add - Add a new point in boundary condition or punctual contribution + Add a new point Ctrl+N @@ -116,7 +116,7 @@ Sort - Sort boundary condition points + Sort points diff --git a/src/View/ui/EditLateralContribution.ui b/src/View/ui/EditLateralContribution.ui index 02e14bcb..21736a6b 100644 --- a/src/View/ui/EditLateralContribution.ui +++ b/src/View/ui/EditLateralContribution.ui @@ -79,7 +79,7 @@ Add - Add a new point in boundary condition or lateral contribution + Add a new point in boundary condition or lateral source Ctrl+N @@ -109,7 +109,7 @@ Sort - Sort boundary condition point + Sort points diff --git a/src/View/ui/Frictions.ui b/src/View/ui/Frictions.ui index e219bf73..77c32181 100644 --- a/src/View/ui/Frictions.ui +++ b/src/View/ui/Frictions.ui @@ -98,7 +98,10 @@ ressources/edit.pngressources/edit.png - Edit stricklers + Edit Strickler coefficients + + + Edit Strickler coefficients Ctrl+E diff --git a/src/View/ui/GeometryCrossSection.ui b/src/View/ui/GeometryCrossSection.ui index c9c29e61..dfc47bb6 100644 --- a/src/View/ui/GeometryCrossSection.ui +++ b/src/View/ui/GeometryCrossSection.ui @@ -67,10 +67,10 @@ ressources/add.pngressources/add.png - add + Add - Add a point on cross-section + Add a point to cross-section @@ -91,7 +91,7 @@ ressources/up.pngressources/up.png - up + Up Move up selected point(s) @@ -103,10 +103,10 @@ ressources/down.pngressources/down.png - down + Down - Mode down selected point(s) + Move down selected point(s) diff --git a/src/View/ui/GeometryReach.ui b/src/View/ui/GeometryReach.ui index 2ba38650..4624b796 100644 --- a/src/View/ui/GeometryReach.ui +++ b/src/View/ui/GeometryReach.ui @@ -166,7 +166,7 @@ ressources/add.pngressources/add.png - add + Add Add a cross-section @@ -190,7 +190,7 @@ ressources/edit.pngressources/edit.png - edit + Edit Edit selected cross section(s) @@ -205,7 +205,7 @@ sort_asc - Sort cross-sections by ascending KP + Sort cross-sections by ascending position @@ -217,7 +217,7 @@ sort_des - Sort cross-sections by descending KP + Sort cross-sections by descending position @@ -226,7 +226,7 @@ ressources/up.pngressources/up.png - up + Up Move up selected cross-section(s) @@ -238,7 +238,7 @@ ressources/down.pngressources/down.png - down + Down Move down selected cross-section(s) diff --git a/src/View/ui/InitialConditions.ui b/src/View/ui/InitialConditions.ui index 38f96734..403a5fe2 100644 --- a/src/View/ui/InitialConditions.ui +++ b/src/View/ui/InitialConditions.ui @@ -119,7 +119,7 @@ sort - Sort inital condition + Sort inital conditions diff --git a/src/View/ui/LateralContributions.ui b/src/View/ui/LateralContributions.ui index d8d81b79..f1ac5707 100644 --- a/src/View/ui/LateralContributions.ui +++ b/src/View/ui/LateralContributions.ui @@ -37,7 +37,7 @@ - 0 + 2 @@ -61,7 +61,7 @@ - Suspenssion + Suspension @@ -114,7 +114,7 @@ Add - Add a new boundary condition or lateral contribution + Add a new boundary condition or lateral source Ctrl+N @@ -144,7 +144,7 @@ Edit - Edit boundary condition or lateral contribution + Edit boundary condition or lateral source Ctrl+E @@ -159,7 +159,7 @@ Sort - Sort boundary condition by name + Sort by names diff --git a/src/View/ui/MainWindow.ui b/src/View/ui/MainWindow.ui index cb40e142..1156fca9 100644 --- a/src/View/ui/MainWindow.ui +++ b/src/View/ui/MainWindow.ui @@ -115,7 +115,7 @@ - &River Network + &River network @@ -408,7 +408,7 @@ - Pamhyr configuration + Pamhyr2 configuration @@ -446,10 +446,10 @@ - Numerical parameter for solvers + Numerical parameters of solvers - Numerical parameter for solvers + Numerical parameters of solvers @@ -458,7 +458,7 @@ ressources/boundary_condition.pngressources/boundary_condition.png - Boundary conditions and punctual contributions + Boundary conditions and point sources @@ -479,7 +479,7 @@ ressources/friction.pngressources/friction.png - Edit friction + Edit frictions @@ -488,7 +488,7 @@ ressources/lateral_contribution.pngressources/lateral_contribution.png - Edit lateral contributions + Edit lateral sources @@ -597,7 +597,7 @@ Boundary conditions - Edit boundary conditions and punctual contributions + Edit boundary conditions and point sources @@ -609,10 +609,10 @@ ressources/lateral_contribution.pngressources/lateral_contribution.png - Lateral contribution + Lateral sources - Edit lateral contribution + Edit lateral sources @@ -624,7 +624,7 @@ Friction - Edit frictions + Edit friction @@ -669,7 +669,7 @@ Mage - Open mage documentation + Open Mage documentation @@ -717,12 +717,12 @@ ressources/boundary_condition.pngressources/boundary_condition.png - Boundary conditions and punctual contributions + Boundary conditions and point sources - &Additional file + &Additional files diff --git a/src/View/ui/MeshingOptions.ui b/src/View/ui/MeshingOptions.ui index 6ff87a52..49596584 100644 --- a/src/View/ui/MeshingOptions.ui +++ b/src/View/ui/MeshingOptions.ui @@ -33,7 +33,7 @@ - Section space step (m) + Space step (m) @@ -111,7 +111,7 @@ - Distance computation + Guideline used for distance computation @@ -120,7 +120,7 @@ true - Second guide-line + Second guideline @@ -130,7 +130,7 @@ true - First guide-line + First guideline @@ -165,7 +165,7 @@ true - First cross section + First cross-section @@ -186,7 +186,7 @@ true - Last cross section + Last cross-section diff --git a/src/View/ui/NewStudy.ui b/src/View/ui/NewStudy.ui index 47b216c1..e087241c 100644 --- a/src/View/ui/NewStudy.ui +++ b/src/View/ui/NewStudy.ui @@ -127,7 +127,7 @@ false - Staring date + Starting date diff --git a/src/View/ui/REPLineDialog.ui b/src/View/ui/REPLineDialog.ui index 9d5722ae..25902f3f 100644 --- a/src/View/ui/REPLineDialog.ui +++ b/src/View/ui/REPLineDialog.ui @@ -54,7 +54,7 @@ - Comment lines start with '*' char (let see the mage documentation for more details) + <html><head/><body><p>Comment lines start with '*' char (let see Mage documentation for more details)</p></body></html> diff --git a/src/View/ui/REPLineList.ui b/src/View/ui/REPLineList.ui index ea3fe793..b2c71336 100644 --- a/src/View/ui/REPLineList.ui +++ b/src/View/ui/REPLineList.ui @@ -37,13 +37,13 @@ - ressources/add.pngressources/gtk-add.png + ressources/add.pngressources/add.png Add - Add new additional line + Add new line Ctrl+N @@ -52,7 +52,7 @@ - ressources/del.pngressources/gtk-remove.png + ressources/del.pngressources/del.png Delete diff --git a/src/View/ui/ReachSedimentLayers.ui b/src/View/ui/ReachSedimentLayers.ui index dfe39a82..4aaf140d 100644 --- a/src/View/ui/ReachSedimentLayers.ui +++ b/src/View/ui/ReachSedimentLayers.ui @@ -35,7 +35,7 @@ - Apply sediment layers on all reach + Apply sediment layers to all reaches @@ -80,7 +80,7 @@ Edit profile - Edit profile sediment layer + Edit sediment layers of the profile diff --git a/src/View/ui/Reservoir.ui b/src/View/ui/Reservoir.ui index 97e0d7a1..b5f89ff0 100644 --- a/src/View/ui/Reservoir.ui +++ b/src/View/ui/Reservoir.ui @@ -99,7 +99,7 @@ Edit - Edit elevation/surface law + Edit stage-area relation @@ -111,7 +111,7 @@ Sort - Sort points by elevation + Sort points by elevations diff --git a/src/View/ui/ReservoirList.ui b/src/View/ui/ReservoirList.ui index c53a7cd6..aecfc26a 100644 --- a/src/View/ui/ReservoirList.ui +++ b/src/View/ui/ReservoirList.ui @@ -75,7 +75,7 @@ - ressources/add.pngressources/gtk-add.png + ressources/add.pngressources/add.png Add @@ -87,7 +87,7 @@ - ressources/del.pngressources/gtk-remove.png + ressources/del.pngressources/del.png Delete @@ -105,7 +105,7 @@ Edit - Edit reservoir law + Edit reservoir equations diff --git a/src/View/ui/Results.ui b/src/View/ui/Results.ui index c7c319a0..0ff198c6 100644 --- a/src/View/ui/Results.ui +++ b/src/View/ui/Results.ui @@ -145,7 +145,7 @@ - 1 + 2 @@ -198,7 +198,7 @@ - Hydrograph + Discharge time series @@ -251,7 +251,7 @@ Add - Add custom visualization + Add customized visualization diff --git a/src/View/ui/Stricklers.ui b/src/View/ui/Stricklers.ui index a7dbd8e9..437ee782 100644 --- a/src/View/ui/Stricklers.ui +++ b/src/View/ui/Stricklers.ui @@ -25,7 +25,7 @@ - Study stricklers + Strickler coefficients of the study @@ -35,7 +35,7 @@ - Application stricklers + Strickler coefficients of the application @@ -70,7 +70,7 @@ Add - Add new stricklers + Add new Strickler coefficients @@ -82,7 +82,7 @@ Delete - Delete selected stricklers + Delete selected Strickler coefficients @@ -94,7 +94,7 @@ Sort - Sort stricklers + Sort Strickler coefficients diff --git a/src/View/ui/Widgets/MainWindowTabInfo.ui b/src/View/ui/Widgets/MainWindowTabInfo.ui index 9c09579d..8de4e323 100644 --- a/src/View/ui/Widgets/MainWindowTabInfo.ui +++ b/src/View/ui/Widgets/MainWindowTabInfo.ui @@ -182,7 +182,7 @@ - Lateral contributions: + Lateral sources: diff --git a/src/lang/fr.ts b/src/lang/fr.ts index 4b3a4a4d..5c194d35 100644 --- a/src/lang/fr.ts +++ b/src/lang/fr.ts @@ -23,14 +23,14 @@ Edit additional file - Éditer le fichier supplémentaire + Modifier le fichier supplémentaire BasicHydraulicStructures - Basic Hydraulic Structures + Basic Hydraulic Structure Ouvrage hydraulique élémentaire @@ -56,7 +56,7 @@ Half-angle tangent - Tangeante du demi angle + Tangeante du demi-angle @@ -96,7 +96,7 @@ Weir - Seuil + Déversoir @@ -128,20 +128,15 @@ Parameter 5 Paramètre 5 - - - Discharge weir - Seuil déversoir - Trapezoidal weir - Seuil trapézoidal + Déversoir trapézoidal Triangular weir - Seuil triangulaire + Déversoir triangulaire @@ -180,16 +175,21 @@ - User defined + User-defined Défini par l'utilisateur + + + Discharge weir + + BoundaryCondition Edit boundary conditions - Éditer les conditions aux limites + Modifier les conditions aux limites @@ -208,7 +208,7 @@ - Ponctual contribution + Point sources Apports ponctuels @@ -267,49 +267,79 @@ - Mage geometry guide line checker + Mage geometry guideline checker Vérificateur des lignes directrices pour Mage - Check if exists geometry guide line is correctly defined for each reaches of the study - Vérifie si les lignes directrices sont définies pour tous les biefs + Check if geometry guidelines are correctly defined for each reach + Vérifie si les lignes directrices sont définies pour tous les biefs - - Study network reach checker + + Study reach network checker Vérificateur des biefs de l'étude - Check if exists at least one reach for study - Vérifie si il existe au moins un bief dans l'étude + Check if at least one reach exists + Vérifie s'il existe au moins un bief dans l'étude - + Study geometry checker Vérificateur de géometrie de l'étude - - Check if exists geometry for each reach of study - Vérifie si la géométrie existe pour chaque bief de l'étude + + Check if the geometry of each reach exists + Vérifie si la géométrie de chaque bief de l'étude existe - + Dummy ok Dummy ok - + Dummy warning Dummy warning - + Dummy error Dummy error + + + Study initial conditions checker + Vérificateur des conditions initial de l'étude + + + + Check initial conditions for each node of study + Vérifie les conditions initial de l'étude pour chaque nœud + + + + Study boundary conditions checker + Vérificateur des conditions aux limites de l'étude + + + + Check boundary conditions for each node of study + Vérifie les conditions aux limites de l'étude pour chaque nœud + + + + Check if exists geometry guidelines are correctly defined for each reach + Vérifie si il existe des lignes directrices correctement définie pour chaque bief + + + + Check if exists at least one reach exists + Vérificateur si il exists au moins un bief + Checklist @@ -414,12 +444,12 @@ CustomPlot - Custom Plot Selection + Custom plot selection Sélection des graphiques personnalisés - Bed load elevation (m) + Bed elevation (m) Cote du fond (m) @@ -434,9 +464,9 @@ Dialog - + Dialog - Dialog + Dialogue @@ -449,7 +479,7 @@ Type - + Description Description @@ -471,7 +501,7 @@ <html><head/><body><p>Command line format, for input formater (optional), solver execution and output formater (optional). This format can use some replacement values like:</p><p>- <span style=" font-style:italic;">@install_dir</span>: The Pamhyr2 install path</p><p>- <span style=" font-style:italic;">@path</span>: The associate path</p><p>- <span style=" font-style:italic;">@input</span>: Solver input data (depend of solver type)</p><p>-<span style=" font-style:italic;"> @output</span>: Solver output data (depend of solver type)</p><p>- <span style=" font-style:italic;">@dir</span>: The working dir at solver execution</p><p>- <span style=" font-style:italic;">@args</span>: Solver arguments and additional arguments defined on solver parameters</p></body></html> - <html><head/><body><p>Format des lignes de commandes. Ce format peut contenir des valeurs de remplacement, tel que :</p><p>- <span style=" font-style:italic;">@install_dir</span>: Le dossier d'installation de Pamhyr2</p><p>- <span style=" font-style:italic;">@path</span>: Le chemin associé à cette commande</p><p>- <span style=" font-style:italic;">@input</span>: Les données d'entrées du solveur générées par Pamhyr2 (dépend du solveur)</p><p>-<span style=" font-style:italic;"> @output</span>: Les données d'entrées du solveur générées par Pamhyr2 (dépend du solveur)</p><p>- <span style=" font-style:italic;">@dir</span>: Le chemin vers le dossier d'execution du solveur</p><p>- <span style=" font-style:italic;">@args</span>: Arguments du solveur et arguments complémentaires définis dans les paramètres du solveur</p></body></html> + <html><head/><body><p>Format des lignes de commandes. Ce format peut contenir des valeurs de remplacement, telles que :</p><p>- <span style=" font-style:italic;">@install_dir</span>: Le dossier d'installation de Pamhyr2</p><p>- <span style=" font-style:italic;">@path</span>: Le chemin associé à cette commande</p><p>- <span style=" font-style:italic;">@input</span>: Les données d'entrées du solveur générées par Pamhyr2 (dépend du solveur)</p><p>-<span style=" font-style:italic;"> @output</span>: Les données d'entrées du solveur générées par Pamhyr2 (dépend du solveur)</p><p>- <span style=" font-style:italic;">@dir</span>: Le chemin vers le dossier d'execution du solveur</p><p>- <span style=" font-style:italic;">@args</span>: Arguments du solveur et arguments complémentaires définis dans les paramètres du solveur</p></body></html> @@ -506,7 +536,7 @@ Height - Hauteur + Hauteur @@ -514,62 +544,62 @@ Solveurs - + Backup Sauvegarde auto - + Auto save Sauvegarde auto - - Frequence + + Frequency Fréquence - + Enable Activée - + HH:mm:ss HH:mm:ss - Stricklers - Stricklers + Strickler coefficients + Coefficients de Strickler - + Editor Editeur - - This value must be used for reading or editing files in speficic case. + + This value must be used for reading or editing files in speficic cases. Cette valeur peut être utilisée dans des cas spécifiques pour lire ou écrire dans un fichier. - + Editor command - Commande d'édition + Commande d'modification - - - The "@file" keyworkd is replace by the path of file to open. + + - The "@file" keyword is replaced by the path of file to open. - Le mot clef "@file" sera remplacé par le chemin du fichier à ouvrir. - + Language - Langage + Langue - + Please restart application after language modification Un redémarrage de l'application est requis après le changement de langue @@ -590,7 +620,7 @@ - Staring date + Starting date Date de départ @@ -606,7 +636,7 @@ Last modification : - Date de modification : + Dernière modification : @@ -621,45 +651,45 @@ Discharge - Débit + Débit - - First cross section + + First cross-section Première section en travers - - Last cross section + + Last cross-section Dernière section en travers - - First guide line + + First guideline Première ligne directrice - Last guide line - Dernière ligne directrice + Last guideline + Dernière ligne directrice - Section space step + Space step Pas d'espace - - Distance computation guild line - Ligne directrice pour le calcule des distances + + Guideline used for distance computation + Ligne directrice pour le calcul des distances - + Spline Spline - + Linear Linéaire @@ -690,29 +720,94 @@ - Comment lines start with '*' char (let see the mage documentation for more details) - Les lignes de commentaire commence pas un charactère '*' (voir la documentation de mage pour plus de détails) + Comment lines start with '*' char (let see Mage documentation for more details) + Les lignes de commentaire commencent par un caractère '*' (voir la documentation de Mage pour plus de détails) - + Limits Limites Options - Options + Options - - Section space step (m) + + Space step (m) Pas d'espace (m) - + Type of interpolation: Type d'interpolation : + + + Height (m) + Hauteur (m) + + + + Stricklers + Stricklers + + + + Distance computation + Calcule des distances + + + + Second guide-line + Deuxième ligne directrice + + + + First guide-line + Première ligne directrice + + + + Origin + Origine + + + + Origin value + Valeur de l'origine + + + + Discharge (m³/s) + Débit (m³/s) + + + + Parameters + Paramètres + + + + Langue + Langue + + + + <html><head/><body><p>Comment lines start with '*' char (let see Mage documentation for more details)</p></body></html> + Les lignes de commentaire commencent par un caractère '*' (voir la documentation de Mage pour plus de détails) + + + + Second guideline + Seconde ligne directrice + + + + Discharge (m³/s) + + Documentation @@ -725,102 +820,102 @@ Exception - + Generic error message Message d'erreur générique - + Undefined error message Message d'erreur non définie - + Method not implemented Méthode non implémentée - + Method Méthode - + not implemented non implémenté - + for class pour la classe - + Not implemented method Méthode non implémentée - + FileFormatError ErreurFormatDeFichier - + Invalid file format: Format de fichier invalide : - + File format error Erreur de format de fichier - + Invalid file format Format de fichier invalide - + Invalid file Fichier invalide - + format because of format à cause de - + Clipboard format error Erreur de format dans le presse-papier - + without header Sans en-tête - + with header Avec en-tête - + Invalid clipboard data format: Format des données du presse-papier invalide : - + Clipboard format unknown Presse-papier format inconnu - + External file dependence is missing Fichier externe d'une dépendence manquant - + '@file' is missing for module @module: '@path' le fichier '@file' est manquant pour le module @module : '@path' @@ -829,32 +924,32 @@ Form - + Form Formulaire - + About Pamhyr2 À propos de Pamhyr2 - + ... ... - + Version: @version - Version: @version + Version : @version - + License: GPLv3+ - Licence: GPLv3+ + Licence : GPLv3+ - + <a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Source code</a> <a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Code source</a> @@ -906,7 +1001,7 @@ River network - Réseau de la rivière + Réseau hydrographique @@ -985,8 +1080,8 @@ - Lateral contributions: - Contributions latérales : + Lateral sources: + Apports latéraux : @@ -1016,11 +1111,41 @@ Errors summary - Résumer des erreurs + Résumé des erreurs Frictions + + + Strickler coefficients + Coefficients de Strickler + + + + Edit friction coefficients + Modifier les frottements + + + + Start (m) + PK de départ (m) + + + + End (m) + PK de fin (m) + + + + Start coefficient + Coefficient de départ + + + + End coefficient + Coefficient de fin + Stricklers @@ -1029,43 +1154,23 @@ Edit frictions - Éditer les frottements - - - - Begin kp (m) - Pk de départ (m) - - - - End kp (m) - Pk de fin (m) - - - - Begin strickler - Strickler de départ - - - - End strickler - Strickler de fin + Éditer les frotements Geometry - + X (m) X (m) - + Y (m) Y (m) - + Z (m) Z (m) @@ -1081,71 +1186,71 @@ - File mage geometry (*.ST *.st) - Fichier géométrie Mage (*.ST *.st) + Mage geometry file (*.ST *.st) + Fichier Mage de géométrie (*.ST *.st) - File mage meshed geometry (*.M *.m) - Fichier géométrie maillée (*.M *.m) + Mage meshed geometry file (*.M *.m) + Fichier Mage de géométrie maillée (*.M *.m) - - All file (*) + + All files (*) Tous les fichiers (*) - + cross-section section en travers - + cross-sections sections en travers - + Transverse abscissa (m) Abscisse en travers (m) - + Previous cross-section Section en travers précédente - + Cross-section Section en travers - + Next cross-section Section en travers suivante - + Points Points First guideline - Première ligne directrice + Première ligne directrice Second guideline - Seconde ligne directrice + Seconde ligne directrice - Means between the two guideline - Moyenne entre les deux lignes directrices + Mean over the two guidelines + Moyenne sur les deux lignes directrices - + Meshing Maillage @@ -1154,11 +1259,6 @@ Geometry cross-section Géométrie des sections en travers - - - Traversal abs (m) - Absice en travers (m) - upstream @@ -1169,13 +1269,53 @@ downstream aval + + + Shapefile (*.SHP *.shp) + Fichier shape (*.SHP *.shp) + + + + the first guide-line + la première ligne directrice + + + + the second guide-line + la seconde ligne directrice + + + + Width + Largeur + + + + Area + Aire + + + + Perimeter + Périmètre + + + + Traversal abs (m) + Abscisse en travers (m) + + + + the mean over the two guide-lines + la moyenne entre les deux ligne directrice + HydraulicStructures Hydraulic Structures - Structures hydrauliques + Ouvrages hydrauliques @@ -1205,8 +1345,8 @@ LateralContribution - Edit lateral contribution - Éditer les contributions latérales + Edit lateral sources + Modifier les contributions latérales @@ -1220,7 +1360,7 @@ - Lateral contribution + Lateral sources Contributions latérales @@ -1235,44 +1375,44 @@ - Begin kp (m) - Pk de départ (m) + Start (m) + PK de départ (m) - End kp (m) - Pk de fin (m) + End (m) + PK de fin (m) MainWindow - + Open debug window - Ouvrir la fenêtre de dégogage + Ouvrir la fenêtre de débogage - + Open SQLite debuging tool ('sqlitebrowser') - Ouvrir l'outis de dégogage SQLite ('sqlitebrowser') + Ouvrir l'outil de débogage SQLite ('sqlitebrowser') - - Activate this window + + Enable this window Activer cette fenêtre - + MainWindow Fenêtre principale - - toolBar - Barre d'outils + + Toolbar + Barre d'outils - + Add Ajouter @@ -1282,52 +1422,52 @@ Ajouter un casier - + Delete Supprimer Delete reservoirs - Supprimer casier(s) + Supprimer les casier(s) - + Edit - Éditer + modifier - Edit reservoir law - Éditer la loi du(es) casier(s) + Edit reservoir equations + Modifier la loi des casiers - + Add node or edge Ajouter un nœud ou une arête - + Remove node or edge Supprimer un nœud ou une arête Add sediment layer - Ajouter une couche sedimentaire + Ajouter une couche sédimentaire Delete sediment layer - Supprimer une couche sedimentaire + Supprimer une couche sédimentaire Edit sediment layer - Éditer la couche sedimentaire + Modifier la couche sédimentaire - + Ctrl+E Ctrl+E @@ -1337,192 +1477,192 @@ PAMHYR - + &File &Fichier - - &River Network + + &River network &Réseau - + &Geometry &Géometrie - + &Execute &Exécuter - + &Hydraulics &Hydraulique - + &Results &Résultats - + &Help &Aide - + Help Aide - + Pamhyr2 Pamhyr2 - + &Sediment &Sédiment - + &Windows &Fenêtres - + New study Nouvelle étude - + Ctrl+N Ctrl+N - + Open a study Ouvrir une étude - + Ctrl+O Ctrl+O - + Close Fermer - + Close current study Fermer l'étude en cours - + Save Sauvegarder - + Save study Sauvegarder l'étude - + Ctrl+S Ctrl+S - + Save as ... Sauvegarder sous ... - + Save study as ... Sauvegarder l'étude sous ... - + Ctrl+Shift+S Ctrl+Shift+S - - Pamhyr configuration + + Pamhyr2 configuration Configuration de Pamhyr2 - + Quit Quitter - + Quit application Quitter l'application - + Ctrl+F4 Ctrl+F4 - + Edit river network - Éditer le réseau + Modifier le réseau - + Edit geometry - Éditer la géométrie + Modifier la géométrie - + Import geometry Importer une géométrie - + Export geometry Exporter la géométrie - - Numerical parameter for solvers - Paramètres numeriques des solvers + + Numerical parameters of solvers + Paramètres numériques des solveurs - - Boundary conditions and punctual contributions - Condition aux limites et apports ponctuels + + Boundary conditions and point sources + Conditions aux limites et apports ponctuels - + Initial conditions Conditions initiales - + Edit friction - Éditer les frottements + Modifier les frottements - - Edit lateral contributions - Éditer les apports latéraux + + Edit lateral sources + Modifier les contributions latérales - + Run solver - Lancer solveur + Lancer le solveur - + F5 F5 @@ -1532,167 +1672,162 @@ Ouvrir - + Visualize last results Visualisation des derniers résultats - + Visualize the last results - Visualisation des derniers resultats + Visualisation des derniers résultats - + About À propos - + Save current study Sauvegarder l'étude - + Save the study (Ctrl+S) Sauvegarde de l'étude (Ctrl+S) - + Close the study (Ctrl+F) Fermeture de l'étude (Ctrl+F) - + Ctrl+F Ctrl+F - + Run a solver Lancer un solveur - + River network Réseau - + Geometry Géometrie - + Edit reach geometry - Éditer la géométrie du bief actuel + Modifier la géométrie du bief actuel - + Boundary conditions Conditions aux limites - - Edit boundary conditions and punctual contributions - Éditer les conditions aux limites et les apports ponctuels + + Edit boundary conditions and point sources + Modifier les conditions aux limites et les apports ponctuels - - Lateral contribution + + Lateral sources Contributions latérales - - Edit lateral contribution - Éditer les contributions latérales - - - + Friction Frottements - Edit friction frictions - Éditer les frottements + Edit friction coefficients + Modifier les frottements - + Edit study - Éditer l'étude + Modifier l'étude Edit the study metadata - Éditer les informations de l'étude + Modifier les informations de l'étude - + Define initial conditions Définir les conditions initiales - + Sediment layers - Couche sédimentaires + Couches sédimentaires - + Define sediment layers Définition des couches sédimentaires - + Edit reach sediment layers - Éditer les couches sédimentaires + Modifier les couches sédimentaires - + Mage Mage - - Open mage documentation - Ouvrir la domumentation de mage + + Open Mage documentation + Ouvrir la documentation de Mage - + Users (wiki) Utilisateurs (wiki) - + Developers (pdf) - Développeur (pdf) + Développeurs (pdf) - + Developers (html) - Développeur (html) + Développeurs (html) - + Reservoirs Casiers - + Edit reservoirs - Éditer les casiers + Modifier les casiers - + Hydraulic structures - Structures hydraulique + Ouvrages hydrauliques - + Edit hydraulic structures - Éditer les structures hydraulique + Modifier les ouvrages hydrauliques - + Open results from file Ouvrir des résultats depuis un fichier @@ -1708,11 +1843,11 @@ - Eval + Evaluate Évaluer - + Ctrl+Return Ctrl+Return @@ -1724,10 +1859,10 @@ Delete selected sediment layer(s) - Supprimer la(les) couche(s) sédimentaire(s) sélectionnée(s) + Supprimer les couches sédimentaires sélectionnées - + Ctrl+D Ctrl+D @@ -1753,68 +1888,68 @@ - Suspenssion + Suspension Suspension - Add a new boundary condition or lateral contribution - Ajouter une condition aux limites ou un apport ponctuel + Add a new boundary condition or lateral source + Ajouter une condition aux limites ou un apport latéral - + Delete current selected rows Supprimer les lignes selectionnées - Edit boundary condition or lateral contribution - Éditer une condition aux limites ou un apport ponctuel + Edit boundary condition or lateral source + Modifier une condition aux limites ou un apport latéral - + Sort Trier - Sort boundary condition by name + Sort by names Trier par nom - Study stricklers - Stricklers de l'étude + Strickler coefficients of the study + Coefficients de Strickler de l'étude - Application stricklers - Stricklers de l'application + Strickler coefficients of the application + Coefficients de Strickler de l'application - Add new stricklers - Ajouter un Strickler + Add new Strickler coefficients + Ajouter un coefficient de Strickler - Delete selected stricklers - Supprimer les Stricklers selectionnés + Delete selected Strickler coefficients + Supprimer les coefficients de Strickler selectionnés - Sort stricklers - Trier les Stricklers + Sort Strickler coefficients + Trier les coefficients de Strickler - Add a new boundary condition or punctual contribution + Add a new boundary condition or point source Ajouter une condition aux limites ou un apport ponctuel - Edit boundary condition or punctual contribution - Éditer une condition aux limites ou un apport ponctuel + Edit boundary condition or point source + Modifier une condition aux limites ou un apport ponctuel @@ -1828,38 +1963,38 @@ - Hydrograph + Discharge time series Hydrogramme - Add custom visualization + Add customized visualization Ajouter une visualisation personnalisée - + Reload Recharger - + Export Exporter - + Export raw data Exporter les données brutes - + delete supprimer - - Edit stricklers - Éditer des stricklers + + Edit Strickler coefficients + Modifier les coefficients de Strickler @@ -1899,32 +2034,32 @@ Basic hydraulic structures - Ouvrages hydrauliques élémentaire + Ouvrages hydrauliques élémentaires Enable / Disable basic hydraulic structure - Activer/Déactiver l'ouvrage hydraulique élémentaire + Activer/Désactiver l'ouvrage hydraulique élémentaire - + Add a new point - Add a new point + Ajouter un nouveau point Delete points - Supprimer points + Supprimer les points - + Edit selected hydraulic structure - Éditer l'ouvrage hydraulique sélectionné + Modifier l'ouvrage hydraulique sélectionné Stop - Stoper + Arrêter @@ -1944,45 +2079,40 @@ results - resultats - - - - add - Ajouter + résultats - Add a point on cross-section + Add a point to cross-section Ajouter un point à la section en travers Delete selected point(s) - Supprimer le(s) point(s) sélectionné(s) + Supprimer les points sélectionnés - - up + + Up Monter Move up selected point(s) - Déplacer le point sélectionné vers le haut + Déplacer les points sélectionnés vers le haut - - down + + Down Descendre - Mode down selected point(s) - Déplacer le point sélectionné vers le bas + Move down selected point(s) + Déplacer les points sélectionnés vers le bas - + sort_asc sort_asc @@ -1992,49 +2122,49 @@ Trier les points par leurs plus proches voisins - + sort_des sort_des Sort reversed points by nearest neighbor - Trie inverser les points par leurs plus proche voisins + Trier/inverser les points par leurs plus proches voisins Enable / Disable hydraulic structure - Activer/Déactiver l'ouvrage hydraulique + Activer/Désactiver l'ouvrage hydraulique - Edit elevation/surface law - Éditer loi élévation/surface + Edit stage-area relation + Modifier loi cote/surface - Sort points by elevation - Trier les points par leur cote + Sort points by elevations + Trier les points par cote - + Edit sediment layers list - Éditer la liste des couches sédimentaires + Modifier la liste des couches sédimentaires - Apply sediment layers on all reach + Apply sediment layers to all reaches Appliquer une liste de couches sédimentaires Edit profile - Éditer le profil + Modifier le profil - Edit profile sediment layer - Éditer les couches sédimentaires du profil + Edit sediment layers of the profile + Modifier les couches sédimentaires du profil @@ -2044,57 +2174,52 @@ Generate from discharge - Générer pour un débit donnée + Générer pour un débit donné - + Add new initial condition Ajouter une nouvelle condition initiale - + Delete inital condition Supprimer une condition initiale - + sort sort - - Sort inital condition + + Sort inital conditions Trier les conditions initiales - - Add a new point in boundary condition or punctual contribution - Ajouter un nouveau point + + Add a new point in boundary condition or point source + Ajouter un nouveau point Sort boundary condition points - Trier les points des conditions aux limites + Trier les points des conditions aux limites - Add a new point in boundary condition or lateral contribution + Add a new point in boundary condition or lateral source Ajouter un nouveau point - - - Sort boundary condition point - Trier les points des conditions aux limites - Add sediment layers - Ajouter une couche sedimentaire + Ajouter une couche sédimentaire Add specific sediment layers on selected point(s) - Ajouter des couches spécifiques au(x) point(s) sélectionné(s) + Ajouter des couches spécifiques aux points sélectionnés @@ -2104,97 +2229,92 @@ Delete specific sediment layers of selected point(s) - Supprimer les couches sédimentaires au(x) point(s) sélectionné(s) + Supprimer les couches sédimentaires aux points sélectionnés Edit sediment layers - Éditer les couches sédimentaires + Modifier les couches sédimentaires - + Import Importer - + Add a cross-section Ajouter une section en travers - + Delete selected cross-section(s) - Supprimer la(es) section(s) en travers sélectionnée(s) + Supprimer les sections en travers sélectionnées - - edit - éditer - - - + Edit selected cross section(s) - Éditer la(es) section(s) en travers sélectionnée(s) + Modifier les sections en travers sélectionnées - - Sort cross-sections by ascending KP + + Sort cross-sections by ascending position Trier les sections en travers par PK croissant - - Sort cross-sections by descending KP + + Sort cross-sections by descending position Trier les sections en travers par PK décroissant - + Move up selected cross-section(s) - Déplacer la(s) section(s) en travers vers le haut + Déplacer les sections en travers vers le haut - + Move down selected cross-section(s) - Déplacer la(es) section(s) en travers vers le bas + Déplacer les sections en travers vers le bas - + Meshing Maillage - + Summary - Résumer + Résumé - + Checks Vérifications - - &Advansed + + &Advanced &Avancé - - &Additional file - Fichiers &supplémentaire + + &Additional files + Fichiers &supplémentaires - + REP additional lines - Lines REP supplémentaire + Lignes REP supplémentaires - Add new additional line + Add new line Ajouter une nouvelle ligne Delete additional line(s) - Supprimer la(es) ligne(s) supplementaire + Supprimer les lignes supplementaires @@ -2204,7 +2324,7 @@ Edit selected line(s) - Éditer la(es) ligne(s) selectionnée(s) + Modifier les lignes selectionnées @@ -2214,7 +2334,7 @@ File text - Text du fichiers + Texte du fichier @@ -2229,7 +2349,7 @@ The relative file path on executable directory - Le chemin relatif du fichier dans le répertoire d'execution + Le chemin relatif du fichier dans le répertoire d'exécution @@ -2249,84 +2369,84 @@ Delete selected file(s) - Supprimer le(s) fichier(s) selectionné(s) + Supprimer les fichiers sélectionnés Edit file - Éditer fichier + Modifier fichier - + Edit the study information - Éditer les information de l'étude + Modifier les informations de l'étude - - Update KP + + toolBar - - Recompute KP + + toolBar_2 - + + Edit frictions + Éditer les frotements + + + Purge - - - - - Purge cross-sections to keep a given number of points - + Purger Purge the cross-section to keep a given number of points - + Purger les profiles pour garder qu'un nombre donné de points Reverse - + Retourner Reverse the points order - - - - - MainWindowProfile - - - La cote du fond - Z minimale - + Retourner l'ordre des points - - La cote maximale - Z maximale - + + Import from file + Importer depuis un fichier - - Rive gauche - + + Update KP + Mise à jour des PK - - Rive droite - + + Recompute KP + Recalcule des PK + + + + Purge cross-sections to keep a given number of points + Purger les profiles pour garder un nombre fixer de points + + + + Sort points + Trier les points MainWindow_reach - Kp (m) + Position (m) Pk (m) @@ -2340,7 +2460,7 @@ X (m) - + Select destination file Selectionner fichier de destination @@ -2365,7 +2485,7 @@ Edit node reservoir - Éditer le casier du nœud + Modifier le casier du nœud @@ -2380,17 +2500,17 @@ Enable the reach - Activer l'arrête + Activer l'arête Disable the reach - Déactiver l'arrête + Désactiver l'arête Reverse the reach orientation - Inverser l'orientation de l'arrête + Inverser l'orientation de l'arête @@ -2426,7 +2546,7 @@ Edit Mage REP lines - Éditer le lignes REP Mage + Modifier les lignes REP Mage @@ -2444,7 +2564,7 @@ Edit Reservoir - Éditer le casier + Modifier le casier @@ -2545,7 +2665,7 @@ Edit Sediment Layers - Éditer les couches sédimentaires + Modifier les couches sédimentaires @@ -2600,12 +2720,12 @@ Apply sediment layers to reach - Appliquer des couches sédimentaire au bief + Appliquer des couches sédimentaires au bief Sediment Layers List - Liste des ensembles de couches sedimentaires + Liste des ensembles de couches sédimentaires @@ -2623,7 +2743,7 @@ Solver logs - Selection des logs + Sélection des logs @@ -2691,7 +2811,7 @@ Implicitation parameter - Parametre d'implicitation + Paramètre d'implicitation @@ -2730,7 +2850,7 @@ - Maximun number of iterations (< 100) + Maximum number of iterations (< 100) Nombre maximum d'itérations (< 100) @@ -2755,12 +2875,12 @@ - Number of iteration at maximum precision + Number of iterations at maximum precision Nombre d'itérations à la précision maximum - Number of iteration before switch + Number of iterations before switch Nombre d'itérations avant changement @@ -2791,7 +2911,7 @@ Use Mage internal initialization (Y/N) - Utiliser l'initialisation interne de mage (O/N) + Utiliser l'initialisation interne de Mage (O/N) @@ -2830,8 +2950,8 @@ - Critic shields - Shields critique + Critical Shields number + Nombre de Shields critique @@ -2856,10 +2976,15 @@ Stricklers + + + Strickler coefficients + Coefficient de Strickler + Stricklers - Stricklers + Stricklers @@ -2867,7 +2992,7 @@ Edit study - Éditer l'étude + Modifier l'étude @@ -2878,43 +3003,43 @@ Toolbar - + Default view Vue par défaut - + Back to previous view Retour à la vue précédente - - Return to next view + + Back to next view Retour à la vue suivante - - Axes panoramic + + Panoramic axes Axes panoramiques - + Zoom Zoom - + Isometric view (Shift+W) Vue isométrique (Shift+W) - + Auto scale view (Shift+X) Vue automatique (Shift+X) - - Save the figure + + Save figure Sauvegarder la figure @@ -2922,7 +3047,7 @@ Unit - KP (m) + Position (m) PK (m) @@ -2956,27 +3081,27 @@ Cote de l'eau (m) - + Area (hectare) Aire (hectare) - + Time (sec) - Temps (sec) + Temps (s) - + Time (JJJ:HH:MM:SS) Temps (JJJ:HH:MM:SS) - + Date (sec) - Date (sec) + Date (s) - + Date (ISO format) Date (format ISO) @@ -2985,8 +3110,13 @@ Discharge (m³/s) Débit (m³/s) - + + Speed (m/s) + Vitesse (m/s) + + + Discharge (m³/s) From 7de6cc44683074542bfc803431afa3e303b3c830 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 11:50:07 +0200 Subject: [PATCH 05/45] Solver: RubarBE: Disable. --- src/Solver/Solvers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Solver/Solvers.py b/src/Solver/Solvers.py index c173588f..cd336e68 100644 --- a/src/Solver/Solvers.py +++ b/src/Solver/Solvers.py @@ -31,7 +31,7 @@ solver_long_name = { # "mage7": "Mage v7", "mage8": "Mage v8", # "mage_fake7": "Mage fake v7", - "rubarbe": "RubarBE", + # "rubarbe": "RubarBE", } solver_type_list = { @@ -39,5 +39,5 @@ solver_type_list = { # "mage7": Mage7, "mage8": Mage8, # "mage_fake7": MageFake7, - "rubarbe": RubarBE, + # "rubarbe": RubarBE, } From f1a1d084587029c255ec834e3a7564e9f7737db8 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 11:51:23 +0200 Subject: [PATCH 06/45] Pamhyr: Minor change. --- src/View/ui/ConfigureDialog.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/View/ui/ConfigureDialog.ui b/src/View/ui/ConfigureDialog.ui index c6477f86..9c23ce2d 100644 --- a/src/View/ui/ConfigureDialog.ui +++ b/src/View/ui/ConfigureDialog.ui @@ -25,7 +25,7 @@ true - 4 + 0 false From 2013009e8aa5254b3dc87150cdf5187ebd866fa0 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 11:52:07 +0200 Subject: [PATCH 07/45] Mage: Update version. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e8920060..c70caaaa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -29,7 +29,7 @@ stages: ############# variables: - MAGE_8_VERSION: "v8.3.5" + MAGE_8_VERSION: "v8.3.6" dl-mage8-doc: stage: downloads From 507cfb9d536dd973d50c500eea52701973e3f3f6 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 11:55:29 +0200 Subject: [PATCH 08/45] Friction: Fix reach plot. --- src/View/Frictions/Window.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/View/Frictions/Window.py b/src/View/Frictions/Window.py index a1922ddf..c0c7d81b 100644 --- a/src/View/Frictions/Window.py +++ b/src/View/Frictions/Window.py @@ -136,6 +136,7 @@ class FrictionsWindow(PamhyrWindow): self.plot = PlotKPZ( canvas=self.canvas, data=self._reach.reach, + study=self._study, trad=self._trad, toolbar=None, ) From 537612e5e344565015dd76fca02996b0c64c7aae Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 12:22:47 +0200 Subject: [PATCH 09/45] Geometry: Minor change. --- src/View/ui/GeometryReach.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/View/ui/GeometryReach.ui b/src/View/ui/GeometryReach.ui index 4624b796..a124c899 100644 --- a/src/View/ui/GeometryReach.ui +++ b/src/View/ui/GeometryReach.ui @@ -37,7 +37,7 @@ - ressources/go-up2.pngressources/go-up2.png + ressources/up.pngressources/up.png @@ -65,7 +65,7 @@ - ressources/go-down1.pngressources/go-down1.png + ressources/down.pngressources/down.png From cb41520a203efc8ee98a82a093908a060833e4c4 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 12:29:20 +0200 Subject: [PATCH 10/45] pamhyr: Fix Pep8. --- src/View/Geometry/PlotAC.py | 12 +++++------- src/View/Geometry/Window.py | 16 +++++++++++----- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/View/Geometry/PlotAC.py b/src/View/Geometry/PlotAC.py index a8892814..ad43fdf3 100644 --- a/src/View/Geometry/PlotAC.py +++ b/src/View/Geometry/PlotAC.py @@ -82,14 +82,12 @@ class PlotAC(PamhyrPlot): label=self.label_previous_plot_selected, lw=1.5, linestyle='--', color=self.color_plot_previous ) - #self.previous_plot_selected.set_visible(False) self.plot_selected, = self.canvas.axes.plot( station, elevation, label=self.label_plot_selected, color=self.color_plot_current, lw=1.5 ) - #self.plot_selected.set_visible(False) next_id = profile_id + 1 station_next = self.data.profile(next_id).get_station() @@ -100,7 +98,6 @@ class PlotAC(PamhyrPlot): label=self.label_next_plot_selected, color=self.color_plot_next, lw=1.6, linestyle='--' ) - #self.next_plot_selected.set_visible(False) self.canvas.axes.set_visible(False) def draw_gl(self): @@ -110,13 +107,16 @@ class PlotAC(PamhyrPlot): profile_id = 0 profile = self.data.profile(profile_id) - if profile == None: return + if profile is None: + return + station = profile.get_station() elevation = profile.z() gl = profile.names() self.annotation = [] self.complete_gl, self.incomplete_gl = self.data.compute_guidelines() + lcomplete = list(self.complete_gl) lincomplete = list(self.incomplete_gl) @@ -193,7 +193,6 @@ class PlotAC(PamhyrPlot): self.data.profile(previous_id).z() ) self.previous_plot_selected.set_visible(True) - #self.canvas.axes.legend() if 0 <= profile_id < self.data.number_profiles: self.plot_selected.set_data( @@ -201,7 +200,6 @@ class PlotAC(PamhyrPlot): self.data.profile(profile_id).z() ) self.plot_selected.set_visible(True) - #self.canvas.axes.legend() if 0 <= next_id < self.data.number_profiles: self.next_plot_selected.set_data( @@ -209,7 +207,7 @@ class PlotAC(PamhyrPlot): self.data.profile(next_id).z() ) self.next_plot_selected.set_visible(True) - #self.canvas.axes.legend() + self.canvas.axes.set_visible(True) def update_full(self): diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 3e972349..b92ae373 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -157,7 +157,9 @@ class GeometryWindow(PamhyrWindow): def _compute_status_label(self): row = self.index_selected_row() - if row == None: return + if row is None: + return + profile = self._reach.profile(row) name = profile.name + " " + str(profile.kp) @@ -404,7 +406,6 @@ class GeometryWindow(PamhyrWindow): def update_plot_ac(self, ind: int): self.tableView.model().blockSignals(True) - #self._plot_ac.current = ind self._plot_ac.update() self.tableView.model().blockSignals(False) @@ -449,7 +450,8 @@ class GeometryWindow(PamhyrWindow): def select_current_profile(self): self.tableView.model().blockSignals(True) row = self.index_selected_row() - if row != None: + + if row is not None: self.find(QSlider, "verticalSlider").setValue(row) self.select_plot_xy(row) self.select_plot_kpc(row) @@ -530,13 +532,17 @@ class GeometryWindow(PamhyrWindow): def move_up(self): row = self.index_selected_row() - if row == None: return + if row is None: + return + self._table.move_up(row) self.select_current_profile() def move_down(self): row = self.index_selected_row() - if row == None: return + if row is None: + return + self._table.move_down(row) self.select_current_profile() From a5648851f2184aff5bc7e511312c05c5805540bb Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 14:31:34 +0200 Subject: [PATCH 11/45] Friction: Add strickler unit. --- src/View/Frictions/PlotStricklers.py | 2 +- src/View/Frictions/translate.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/View/Frictions/PlotStricklers.py b/src/View/Frictions/PlotStricklers.py index c7f0abc3..40bd9140 100644 --- a/src/View/Frictions/PlotStricklers.py +++ b/src/View/Frictions/PlotStricklers.py @@ -42,7 +42,7 @@ class PlotStricklers(PamhyrPlot): ) self.label_x = self._trad["kp"] - self.label_y = self._trad["stricklers"] + self.label_y = self._trad["strickler_plot"] self.line_kp_elevation = [None, None] diff --git a/src/View/Frictions/translate.py b/src/View/Frictions/translate.py index 3286e2e2..c493ecf7 100644 --- a/src/View/Frictions/translate.py +++ b/src/View/Frictions/translate.py @@ -28,6 +28,9 @@ class FrictionsTranslate(MainTranslate): super(FrictionsTranslate, self).__init__() self._dict["kp"] = self._dict["unit_kp"] + self._dict["strickler_plot"] = _translate( + "Frictions", "Strickler ($m^{1/3}/s$)" + ) self._dict["stricklers"] = _translate( "Frictions", "Stricklers" ) From 5c86e46c7264cf91370940a96d67c2b6db62a896 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 14:51:30 +0200 Subject: [PATCH 12/45] Checker: Bypass study copy to improve performance. --- src/View/CheckList/Worker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/View/CheckList/Worker.py b/src/View/CheckList/Worker.py index f8246fba..58295bee 100644 --- a/src/View/CheckList/Worker.py +++ b/src/View/CheckList/Worker.py @@ -46,7 +46,7 @@ class Worker(QObject): self.signalStatus.emit(checker.name) # Run checker - checker._run(self._study) + checker.run(self._study) self.signalStatus.emit("progress") From 52f2d15280b8fd6b199368e6b43275d436cda0aa Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 15:20:17 +0200 Subject: [PATCH 13/45] Package: Add icon for windows executable file. --- .gitlab-ci.yml | 2 +- src/View/ui/ressources/icon.ico | Bin 0 -> 19518 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/View/ui/ressources/icon.ico diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c70caaaa..245996c6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -333,7 +333,7 @@ build-windows: - python -m pip install -U -r ..\requirements.txt # Run Pyinstaller # - pyinstaller --noconsole -y ..\src\pamhyr.py - - pyinstaller --hide-console hide-early -y ..\src\pamhyr.py + - pyinstaller -i ../src/View/ui/ressources/icon.ico --hide-console hide-early -y ..\src\pamhyr.py # Create directory - mkdir pamhyr - dir diff --git a/src/View/ui/ressources/icon.ico b/src/View/ui/ressources/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8b8894aa4667a5c60f06a3d6e741c4fc35c330e3 GIT binary patch literal 19518 zcmeHO3wTsjlCJLN(FqWZKpyf`K*K|1!K4ELq7rlxlWv%Fc#pc+BsS0qNg#j$1w;^t z;3|rFjA;{Jqfr@%A_jFrf*`NKO#?|feRoF(b(G!xTt-JfzZtix&b_y9zd|~GpYwhD zr7riLbI(1e{;E24>O49C=Q#xDGRp)jG8EJD(4%Meg-}C z>(>wZ8~ehb-o0Q*pWZOc*arsp?*{`14ul~?hCuw_K``RlC>V`(#zY!nT)zky6VV55 z8a5OX2lRt!{Uc#gR9~2J?Esh@a~+HxJsKuVm;kp;nF3R%PKD{WB*1K}mlk~uSfZmK zb6_;wF)S9W*YpQ#^Z;0h?Q-IyAbaq2aPRd4VF{+`(@gL{{9sry=vr7lWH2m?8wAC} z;$g$k7+5+fQQD7f~6C0f``*)z^qxbAS){itX3;5S+WG~wcG=% zvdyq`=~7s^awV*MFc(&@UJV;JZiH2<3Sigpc-Vrnlw-PM)KDlNJq(^0GZG#jKN_}8 zyA8?{M!}mS;^Bqiaq!m2>!Ehka5#A5P&hnh1RP2j0kz}Dz-xHFJ$@7%xp^eKKlVm= z@74sU$NR`_li)n^Y{k@*G6g=J znFP(V65*q}r$Wc<6lhJG3YYFkhR@Qb!O5&ya5CptAZ6VNk~JOL=B0ys;T$-hw-DOa z+y`gYtb_|Cc4*&N1jpB`fX}i1pXc5MpJCmvaWL*UAy3!y?dduvJ&c^ z+zGEbpNHDoTBxh5gF|oD!NG$Ep`oDxI?A?y`{^gZ^Yk{5%J;&F@~7bB@85vq4evtB z{@38E-CN;{y*uDfReRy`^H0Gydmo1@&p!j7)mFgem&@Tw?Q`&{b2ofhR|9{kuY<1- z)xqWW4!~dEsDUf>ufuoyUxdFk9Dx5h)&PG!b_BjXaRiPXI|iptor0E@7U<~cfd4r4 z5&XIB0(^VA34Xx)`{PI9+m=)CgG=1spFaoRcbtdIr<&o%&pP05fAYYW|0%(xOPApC z<;(EjUtEIkzW5w|{QOh+@vBSl_sd_w-@o}UxN_wR{NvmIg@63;9sKmuPdM`a`6TsF zj|F-x&|`s67U*atx^VGAcy#dswQBW*V%x>?Pu|(Idhw#gixw?dq|kgN!)d6u1&bDA zyEU5+wRK+v&xNNJXJ%yFlcAExY6|2p+7fL(Bg0(!Znp*apfuB$nJPyZnXK%m+Pi3M zziJ<>4g)51)lBo#-4fvJ&xOaXBg)J)zub*3@NCIMVg|@VPUW2XMj5lu8@(W9iYA=R z%vktGKht*M^~^$nPtcSTvZ!q3SNud6NSP=Hi$Zy>O<&CTKv}kiZ-95QNe66iHX~m% zI~0Zan_ zfCbyr?MGVmEMtkK?v`K`wM{JxPf4Csc9w`*6)qqn&CaE-3PAN1xV8FUD3ujQBxEEInfJo22Lv5D zd>`TK|LxsFLv2uwHfkR(|VMB3sO4^#6tgMd2qavO==1q5MI#=bEU@> zF4Z)k^fg`;@Pp^vRuq66VqN-YF_#__V>>yN>oW(R{+HUes7kXS%#7Gt%xezI0tDbQ zpN^LWs(6y%TV{}>Kzy@T(jYn6{)%#KTj#MNqzmJ+R$TPpfevmT9AD~qRLCh>;`26+ ztuZ391VI)>KK_SA9d9lW(A@dV%q+ajVtbL-G>mTyaB0tBbWu^C(>wZ-_QvXv$l`;K z|51_W&}vn2SrWn4V#$7*rqpWEOWXf~k<|VO^_@)SSy2RUs89?mR|-f1@FnSkhlmL( z?Mr9|>!wda<4cDh^ft&8Q931f(AP-e>wn_I$xV2QNAOmKA!V{HSi0$~R85Kn(O>c$ zR0Xi!#DOOS*=UNgf=~xWvlxR9Chp1gi#|n?&&IMPQMBX{YhFM z(hZuOgXTs^&6Bcn$AaD&gmE=ny{}O(=KRRG>CR4r53&&Y8)E#(08wcIn(@64p8X&u z9^!(;6)`j_kJdUXQ%x}(C*!L+mq6erHRCxTkxM+AVgY(j%9dfhHpsbyJJ#@gV+70$ zG%o8ehX!|xGnq$fau7kiwv)%7A1_`N=q5kt)thrUW-+X8c=T*47&TLX%ukDtMeZv0 zl}<-NknvBw!mEnUnL-Qa#MnGNODyXm%$NA9;1@Uz^`M z(?7){o!x|bBf5>$&x|H+Fl-Lytt+PJ0ww`5HEHyhI9NbMP-rfcyM^71yA2%YLL8hlWSh&i?_p3&e2OODk>m(4n7VvN?-l2pY@Gi_OI zH}Qr4$pW82C$L#Zs@6yStt`QuNmG5sK!E>APL6~r!88|To!Vcq?!~P(8!vlt-Ho1T zL)}Rtlq2o8N*!V+rbey)sVsD5XnfiJezS?!|3u67y1D(C(=Z$fq&`cLgF-BMUBf%T z|64eY#58H@_+`aNPx1@WE{wkb@~(th{QJ!ekG_wdK0}Pp+O^|-H;_dTpL~NWcs_EmClTC>+Jo1c5)qbYcC|aEuqsQY6 zJ^hxgk4=(S6jh>>4Q`A{s%}T^{PKO>I`9o&gpVIywv5mb zRG^~-BtY)ow(yyCr^Rs+01;6LGyvH^7-RX~U&sO{H!-@vCmBc{w8bwbz_~{mP-xHi z+!wjOm;kMN?IZykU(p}memMa;>g;HBf+Qo5{n;0C!y1O}7MII~H*PvahO%nNaPv-t zAKEEi62%{FS)QB6`1nBh<;!!I)9dm&iUV$yi`dVotkiOH{Hj=@IL#Fs8>22&D`F$W zo-8&|JAJ!Mv0Qv@!aRht6Q&P24x+T>>h826R$)V}Vk@-+t~NO_LQJbPZ6Za+n^M$G zO^ee+9}US)pBV0Gs;%VNNjC;9uaZ}gweL#JF_Fs5*-~4X%o7pL%Sn~BzEdI2Y}LHb zWAupBqskO0q;yZma{rwPeG-d0-DHP7*N*?t3=HoeX_hTpd%O~~TNAf@0zT8n_=+K# z#2Fz@ZmQ*#PZF)3Qq?zaM&L&@zJUTzACM5L1k3HE*W;gqY5Ghoar~DU3OiDgC^pD8 z6}NA}whm%bGeh#cktdWVa0g!W%*{=s8Cau@SYpQd+FpT|&{#~G#h&^N7l%Qb34RfH zu-8%Nu*-zFEQ8%XkN3!NUN|=&g8MJ=6cDGpwwbOJXwynCRB7KiFZLA4G%DMlQ3S{( zXFw6`4ptv@-gcg3Qc(VhA&{GlAFQLL=2-0_ShV$UkI4sM?fV?|<-!DLdWR#|ZW}7> z>0MF_{80Lf9a?ZllcZGdB29&vO-k;!jEEW`xcC-Io zP5G*M34yI|Jy%&>)Acez9oM0!XYRJ z8(i1~H>J}sU;$x@&^we}VZ*r^gMnjE*ZN;$|I>Tc5;w=%eHVq!>XsgDfx*RR6+<cuFIq5j*?S2wHoQyuMkEf!I6~ySM~pRV}1c)BNgQDYr`s)%239!fD|}VoDlK5 z4GxD0y=mAGg)ccxvlk!z2JbXR_u|huT8lx>S@XjE^YZNZ`N#ofC|Gq6tKkAhNXO@U z>Zyp#028$TYrFF0(3{5%^VgoH*^2^I*Yr0S@n;K+Z~9)nqK1x3TOjZYHqc*@q>8g{ zahl8%zZaWwjPFR`*fRl*M+QXuOXx0Wtghj6WA&lyGdwL1|4zN2pbp1jqtQ@}FtrqX zHOE`35Ke>fwT<)pQ0xBl3Q&K%OYo;U96GdqV*6h${zt|oCYel$asA};6VOGa*$WE_ zHlQA;fyqPMki6>(6(04Ec(p`?-f<{$0mA2Rq_KlbrK&FKKhxzV`s3=k69%y#<3Jle z4+W@0KB!=$#0w8Lgcn)l@bhDfIrR3PkLZPkXo52GT%5gd+;z$SWUoHEp{U3{cc^TH z==p_(%4or!@MNi*?#rEu!|-hVeYxe39E3JUjd{H!+Uon2dh$>ZV_H$gT* z^n#*7@&Fuyjl5OSPW-9>PD8JBUiJ2xOW;goHeRimT;b^7QO2zcCdd{TZ7P%*KYSHxUc?+4#K#JB*e=CCS%1$yY+h7YvGeQFxh=Kda6;5Tr%CRT|I7H&dn|oXQM$Y}jkXu9#RFCmCOMw^K=Vtb zY^(u0QamSInmhXF2sWJT6y_&cmi8dtp(@ z$4V_BIL56Ie~6*rEB2Qf){+)Q#dj%2U4d^K-unpMUtI?%%rQN;fBpOcLexoE5mhH4 z&}9^=kvno`a04j#ivCjD69ivWoG#->h3AWe7fJ$abka2`rxPm1EP=y44BN- z_)(_)+skTk#DhmYaRDnA#j&-sddHK*qgcW3ZCCm3e73&f^u>#9Z5KZ|`{8?aW$RHY z`wAr7`>wE4-wP_ysE@OddcGCxKs-=?>D1%MMz#L{)V~-nLF?CV-@aqV_U+qBxI`(& zRLNq!-5pB*Ts;kfFEyZI#gk?KAGAtv=BEsT3FYL(o1+3Au2;uZYAE=s|KSJE{-WYS zUQMA4V+u)oaS2GahWsEvgcRb4bbYFI*VwBlE? z)f6jF7>4+Jw}+#9@w#Wvg#(Upu{KqK$N9k+fm;x{Hvl3`_{-^u-Jt|n7x-aEy?4^< ziX6^({P{H)8T7HqmEzRB_4hl9ixF$xx^^x(J6&A@XHrsX%?OKmmq_(U)i?eRW z?)uZ=xm`B}@wA^hvVV8k4h@w(SO5OGFsAx$B5Rs;v=O!Pv#q^7Oo!Jn>dE$4pvM9| g7Wk)FAlRJWQ`TdF9t-qXpvM9|7U;3S|8EQYAEnly7ytkO literal 0 HcmV?d00001 From b017127b3a95ec439508db48673d5683f6707198 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 15:44:48 +0200 Subject: [PATCH 14/45] Windows: Add nsis icon. --- packages/pamhyr.nsi | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/pamhyr.nsi b/packages/pamhyr.nsi index 7555a618..dd4a8053 100644 --- a/packages/pamhyr.nsi +++ b/packages/pamhyr.nsi @@ -3,6 +3,7 @@ !define LIC_NAME "LICENSE" !define APP_NAME "PAMHYR" +Icon "pamhyr\_internal\View\ui\ressources\icon.ico" Name "Pamhyr2" OutFile "pamhyr-windows.exe" LicenseData "pamhyr\_internal\LICENSE" From 61fd54c4966a495f9dea6d3fdd1596e6add7de54 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 17 May 2024 16:41:05 +0200 Subject: [PATCH 15/45] Geometry, Results: Fix HS display whene not associated. --- src/View/Geometry/PlotKPZ.py | 5 ++++- src/View/Results/PlotKPC.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index 1c80af12..651a6758 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -191,7 +191,10 @@ class PlotKPZ(PamhyrPlot): def draw_profiles_hs(self, reach): lhs = filter( lambda hs: hs._input_reach.reach is reach, - self._study.river.hydraulic_structures.lst + filter( + lambda hs: hs._input_reach is not None, + self._study.river.hydraulic_structures.lst + ) ) for hs in lhs: diff --git a/src/View/Results/PlotKPC.py b/src/View/Results/PlotKPC.py index 77e101dc..74c08059 100644 --- a/src/View/Results/PlotKPC.py +++ b/src/View/Results/PlotKPC.py @@ -109,7 +109,10 @@ class PlotKPC(PamhyrPlot): def draw_profiles_hs(self, reach): lhs = filter( lambda hs: hs._input_reach.reach is reach.geometry, - self.results.study.river.hydraulic_structures.lst + filter( + lambda hs: hs._input_reach is not None, + self.results.study.river.hydraulic_structures.lst + ) ) for hs in lhs: From 8ca21c413f3d27c809eef6ebdaafe235db3069ac Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 21 May 2024 10:51:34 +0200 Subject: [PATCH 16/45] IC: Fix display update and optimized discharge plot update. --- src/View/InitialConditions/PlotDischarge.py | 29 ++++++++++++++++++--- src/View/InitialConditions/Window.py | 7 ++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/View/InitialConditions/PlotDischarge.py b/src/View/InitialConditions/PlotDischarge.py index 7c43c1e5..5ab0b501 100644 --- a/src/View/InitialConditions/PlotDischarge.py +++ b/src/View/InitialConditions/PlotDischarge.py @@ -52,18 +52,41 @@ class PlotDischarge(PamhyrPlot): self._init = True def draw_data(self): - kp = self.data.reach.reach.get_kp() + self.line_discharge = [] if len(self.data) != 0: kp = self.data.get_kp() discharge = self.data.get_discharge() - self.line_kp_zmin = self.canvas.axes.plot( + line, = self.canvas.axes.plot( kp, discharge, color=self.color_plot, **self.plot_default_kargs ) + self.line_discharge.append(line) @timer def update(self, ind=None): - self.draw() + if not self._init: + self.draw() + + self.update_data() + + self.update_idle() + + def update_data(self): + if len(self.data) == len(self.line_discharge): + kp = self.data.get_kp() + discharge = self.data.get_discharge() + + line, = self.canvas.axes.plot( + kp, discharge, + color=self.color_plot, + **self.plot_default_kargs + ) + self.line_discharge.append(line) + else: + for line in self.line_discharge: + line.remove() + + self._draw_data() diff --git a/src/View/InitialConditions/Window.py b/src/View/InitialConditions/Window.py index 82946e84..a9f4c6ad 100644 --- a/src/View/InitialConditions/Window.py +++ b/src/View/InitialConditions/Window.py @@ -194,8 +194,13 @@ class InitialConditionsWindow(PamhyrWindow): return rows[0].row() def update(self): + self.update(propagate=False) + + def _update(self, propagate=True): self._update_plot() - self._propagate_update(key=Modules.INITIAL_CONDITION) + + if propagate: + self._propagate_update(key=Modules.INITIAL_CONDITION) def _update_plot(self): self.plot_1.draw() From a7e43ca6a7ff8024c4b014ece61f9869de885724 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 21 May 2024 11:08:59 +0200 Subject: [PATCH 17/45] MainWindow: Info: Sync update with all modelling modules. --- src/View/MainWindow.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index e1ab44f4..1119e9d8 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -448,8 +448,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): if Modules.CONFIG in keys: self._do_update_config() - if Modules.STUDY in keys: - self._tab_widget_info.update() + self._do_propagate_update_info_tab(keys) logger.debug(f"Propagation of {keys}") for _, window in self.sub_win_list: @@ -458,6 +457,18 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): self._tab_widget_checker.update(modules=keys) + def _do_propagate_update_info_tab(self, keys): + modules = Modules.modelling_list() + modules.append(Modules.STUDY) + + has_info_mod = reduce( + lambda acc, m: acc or (m in keys), + modules, False + ) + + if has_info_mod: + self._tab_widget_info.update() + def _do_propagate_update_rec(self, window, keys): for _, win in window.sub_win_list: win._propagated_update(key=keys) From 14b5b5e3df7c736fb7df727a581e9d29243d77c8 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Tue, 21 May 2024 17:01:54 +0200 Subject: [PATCH 18/45] add purge dialog --- src/View/Geometry/Profile/Table.py | 4 +- src/View/Geometry/Profile/Window.py | 20 ++++++- src/View/Geometry/PurgeDialog.py | 60 ++++++++++++++++++++ src/View/Geometry/Table.py | 4 +- src/View/Geometry/UpdateKPDialog.py | 2 +- src/View/Geometry/Window.py | 13 +++++ src/View/ui/PurgeOptions.ui | 86 +++++++++++++++++++++++++++++ 7 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 src/View/Geometry/PurgeDialog.py create mode 100644 src/View/ui/PurgeOptions.ui diff --git a/src/View/Geometry/Profile/Table.py b/src/View/Geometry/Profile/Table.py index 5974eb7c..141545fa 100644 --- a/src/View/Geometry/Profile/Table.py +++ b/src/View/Geometry/Profile/Table.py @@ -230,11 +230,11 @@ class GeometryProfileTableModel(PamhyrTableModel): self.endMoveRows() self.layoutChanged.emit() - def purge(self): + def purge(self, np_purge): self._undo.push( PurgeCommand( - self._data, 24 + self._data, np_purge ) ) diff --git a/src/View/Geometry/Profile/Window.py b/src/View/Geometry/Profile/Window.py index 655096d7..e93eccff 100644 --- a/src/View/Geometry/Profile/Window.py +++ b/src/View/Geometry/Profile/Window.py @@ -20,8 +20,9 @@ import copy import sys import csv from time import time +import logging -from tools import trace, timer +from tools import trace, timer, logger_exception from Modules import Modules from PyQt5.QtGui import ( @@ -46,9 +47,12 @@ from View.Tools.Plot.PamhyrCanvas import MplCanvas from View.Geometry.Profile.Plot import Plot from View.Geometry.Profile.Table import GeometryProfileTableModel from View.Geometry.Profile.Translate import GeometryProfileTranslate +from View.Geometry.PurgeDialog import PurgeDialog _translate = QCoreApplication.translate +logger = logging.getLogger() + class ProfileWindow(PamhyrWindow): _pamhyr_ui = "GeometryCrossSection" @@ -165,7 +169,6 @@ class ProfileWindow(PamhyrWindow): if Modules.GEOMETRY not in key: return - logger.debug("TOTO") self._tablemodel.layoutChanged.emit() self._update(redraw=True, propagate=False) @@ -258,6 +261,19 @@ class ProfileWindow(PamhyrWindow): self._tablemodel.purge() self.update() + def purge(self): + try: + dlg = PurgeDialog( + trad=self._trad, + parent=self + ) + if dlg.exec(): + self._tablemodel.purge(dlg.np_purge) + self._plot.draw() + except Exception as e: + logger_exception(e) + return + def reverse(self): self._tablemodel.reverse() self.update() diff --git a/src/View/Geometry/PurgeDialog.py b/src/View/Geometry/PurgeDialog.py new file mode 100644 index 00000000..af4fcc34 --- /dev/null +++ b/src/View/Geometry/PurgeDialog.py @@ -0,0 +1,60 @@ +# PurgeDialog.py -- Pamhyr +# Copyright (C) 2023-2024 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- + +from View.Tools.PamhyrWindow import PamhyrDialog + +from PyQt5.QtGui import ( + QKeySequence, +) + +from PyQt5.QtCore import ( + Qt, QVariant, QAbstractTableModel, +) + +from PyQt5.QtWidgets import ( + QUndoStack, QShortcut, QSpinBox, +) + + +class PurgeDialog(PamhyrDialog): + _pamhyr_ui = "PurgeOptions" + _pamhyr_name = "Purge" + + def __init__(self, trad=None, parent=None): + super(PurgeDialog, self).__init__( + title=trad[self._pamhyr_name], + trad=trad, + options=[], + parent=parent + ) + + self._init_default_values() + + def _init_default_values(self): + self._np_purge = 24 + + @property + def np_purge(self): + return self._np_purge + + def accept(self): + self._np_purge = self.get_spin_box("spinBox_np_purge") + super().accept() + + def reject(self): + self.close() diff --git a/src/View/Geometry/Table.py b/src/View/Geometry/Table.py index 3c5db448..4009af87 100644 --- a/src/View/Geometry/Table.py +++ b/src/View/Geometry/Table.py @@ -259,11 +259,11 @@ class GeometryReachTableModel(PamhyrTableModel): self.layoutAboutToBeChanged.emit() self.layoutChanged.emit() - def purge(self): + def purge(self, np_purge): self._undo.push( PurgeCommand( - self._data, 24 + self._data, np_purge ) ) self.layoutChanged.emit() diff --git a/src/View/Geometry/UpdateKPDialog.py b/src/View/Geometry/UpdateKPDialog.py index 87afc977..b1b0b307 100644 --- a/src/View/Geometry/UpdateKPDialog.py +++ b/src/View/Geometry/UpdateKPDialog.py @@ -1,4 +1,4 @@ -# MeshingDialog.py -- Pamhyr +# UpdateKPDialog.py -- Pamhyr # Copyright (C) 2023-2024 INRAE # # This program is free software: you can redistribute it and/or modify diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index b92ae373..055ea8c3 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -57,6 +57,7 @@ from View.Geometry.PlotAC import PlotAC from View.Geometry.PlotKPZ import PlotKPZ from View.Geometry.MeshingDialog import MeshingDialog from View.Geometry.UpdateKPDialog import UpdateKPDialog +from View.Geometry.PurgeDialog import PurgeDialog from View.Geometry.Translate import GeometryTranslate from View.Geometry.Profile.Window import ProfileWindow @@ -550,6 +551,18 @@ class GeometryWindow(PamhyrWindow): self._table.purge() self.update_redraw() + def purge(self): + try: + dlg = PurgeDialog( + trad=self._trad, + parent=self + ) + if dlg.exec(): + self._table.purge(dlg.np_purge) + except Exception as e: + logger_exception(e) + return + def duplicate(self): rows = [ row.row() for row in diff --git a/src/View/ui/PurgeOptions.ui b/src/View/ui/PurgeOptions.ui new file mode 100644 index 00000000..9b027f97 --- /dev/null +++ b/src/View/ui/PurgeOptions.ui @@ -0,0 +1,86 @@ + + + Dialog + + + + 0 + 0 + 194 + 114 + + + + Dialog + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Number of points to keep + + + + + + 3 + + + 999999999 + + + 24 + + + + + + + + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + From dd86b8b461f76b8b08a6f50b3a08989d8b3f21a4 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 21 May 2024 17:19:00 +0200 Subject: [PATCH 19/45] Package: Linux: Add script to force pamhyr running with x11. --- .gitlab-ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 245996c6..21e62270 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -262,6 +262,11 @@ build-linux: - cp -v ../mage8-linux/* pamhyr/mage8/ # Copy Pamhyr - cp -r dist/pamhyr/* pamhyr/ + # Pamhyr script to force x11 + - echo '#!/usr/bin/env bash' > pamhyr-x11 + - echo "" >> pamhyr-x11 + - echo "GDK_BACKEND=x11 ./pamhyr $@" >> pamhyr-x11 + - chmod +x ./pamhyr-x11 # Copy Pamhyr resources - mkdir -p pamhyr/_internal/View - mkdir -p pamhyr/_internal/View/ui From e45eb3fd6931c3ad6f26a8208b3a326759667f69 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 21 May 2024 17:27:27 +0200 Subject: [PATCH 20/45] ci: build-linux: Fix 'pamhyr-x11' path. --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 21e62270..0f0ec0d5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -263,10 +263,10 @@ build-linux: # Copy Pamhyr - cp -r dist/pamhyr/* pamhyr/ # Pamhyr script to force x11 - - echo '#!/usr/bin/env bash' > pamhyr-x11 - - echo "" >> pamhyr-x11 - - echo "GDK_BACKEND=x11 ./pamhyr $@" >> pamhyr-x11 - - chmod +x ./pamhyr-x11 + - echo '#!/usr/bin/env bash' > pamhyr/pamhyr-x11 + - echo "" >> pamhyr/pamhyr-x11 + - echo "GDK_BACKEND=x11 ./pamhyr $@" >> pamhyr/pamhyr-x11 + - chmod +x pamhyr/pamhyr-x11 # Copy Pamhyr resources - mkdir -p pamhyr/_internal/View - mkdir -p pamhyr/_internal/View/ui From 98feca7fca068d4b48be970008c24e0da6abcb95 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Wed, 22 May 2024 11:36:12 +0200 Subject: [PATCH 21/45] add orientation option for update KP --- src/Meshing/Mage.py | 7 +- src/View/Geometry/UpdateKPDialog.py | 25 ++++-- src/View/Geometry/Window.py | 1 + src/View/Tools/ASubWindow.py | 13 ++- src/View/ui/UpdateKPOptions.ui | 126 ++++++++++++++++++++-------- 5 files changed, 122 insertions(+), 50 deletions(-) diff --git a/src/Meshing/Mage.py b/src/Meshing/Mage.py index 1e8f4c2d..4dc75a1d 100644 --- a/src/Meshing/Mage.py +++ b/src/Meshing/Mage.py @@ -371,7 +371,8 @@ class MeshingWithMageMailleurTT(AMeshingTool): lplan: bool = False, lm: int = 3, linear: bool = False, - origin_value=0.0): + origin_value = 0.0, + orientation = 0): if reach is None or len(reach.profiles) == 0: return reach @@ -400,7 +401,7 @@ class MeshingWithMageMailleurTT(AMeshingTool): f"{str(step)} " + f"{limites[0]} {limites[1]} " + f"{directrices[0]} {directrices[1]} " + - f"{lplan} {lm} {linear} " + + f"{orientation} {lm} {linear} " + f"{origin} " ) proc.start( @@ -413,7 +414,7 @@ class MeshingWithMageMailleurTT(AMeshingTool): "update_kp", step, limites[0], limites[1], directrices[0], directrices[1], - lplan, lm, linear, origin, origin_value + orientation, lm, linear, origin, origin_value ] ) ) diff --git a/src/View/Geometry/UpdateKPDialog.py b/src/View/Geometry/UpdateKPDialog.py index b1b0b307..548a87c1 100644 --- a/src/View/Geometry/UpdateKPDialog.py +++ b/src/View/Geometry/UpdateKPDialog.py @@ -28,7 +28,7 @@ from PyQt5.QtCore import ( from PyQt5.QtWidgets import ( QDialogButtonBox, QComboBox, QUndoStack, QShortcut, - QDoubleSpinBox, + QDoubleSpinBox, QButtonGroup, ) @@ -50,12 +50,7 @@ class UpdateKPDialog(PamhyrDialog): self._init_default_values() def _init_default_values(self): - self._space_step = 50.0 - self._lplan = False - self._lm = "3" - self._linear = False - self._begin_cs = -1 - self._end_cs = -1 + self._orientation = 0 self._begin_dir = "un" self._end_dir = "np" self._origin = self._reach.profile(0) @@ -72,6 +67,15 @@ class UpdateKPDialog(PamhyrDialog): self.find(QComboBox, "comboBox_origin").currentIndexChanged.connect( self.changed_profile) + buttonbox = self.find(QButtonGroup, "buttonGroup_orientation") + + i = 0 + for button in buttonbox.buttons(): + if button.objectName() == "radioButton_0": i = 0 + if button.objectName() == "radioButton_1": i = 1 + if button.objectName() == "radioButton_2": i = 2 + buttonbox.setId(button, i) + def changed_profile(self): origin = self.get_combobox_text("comboBox_origin") self.set_double_spin_box( @@ -114,6 +118,10 @@ class UpdateKPDialog(PamhyrDialog): self.set_combobox_text("comboBox_begin_gl", self._begin_dir) self.set_combobox_text("comboBox_end_gl", self._end_dir) + @property + def orientation(self): + return self._orientation + @property def origin(self): return self._origin @@ -133,11 +141,10 @@ class UpdateKPDialog(PamhyrDialog): def accept(self): origin = self.get_combobox_text("comboBox_origin") self._origin = self.profiles.index(origin) - self._origin_value = self.get_double_spin_box("doubleSpinBox_origin") - self._begin_dir = self.get_combobox_text("comboBox_begin_gl") self._end_dir = self.get_combobox_text("comboBox_end_gl") + self._orientation = self.get_checked_id_button_group("buttonGroup_orientation") super().accept() diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 055ea8c3..ad5b0a23 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -336,6 +336,7 @@ class GeometryWindow(PamhyrWindow): "origin": dlg.origin, "directrices": [dlg.begin_dir, dlg.end_dir], "origin_value": dlg.origin_value, + "orientation": dlg.orientation, } self._update_kp(data) except Exception as e: diff --git a/src/View/Tools/ASubWindow.py b/src/View/Tools/ASubWindow.py index 78655358..2bbeca94 100644 --- a/src/View/Tools/ASubWindow.py +++ b/src/View/Tools/ASubWindow.py @@ -35,7 +35,7 @@ from PyQt5.QtWidgets import ( QRadioButton, QComboBox, QFileDialog, QMessageBox, QTableView, QAction, QDateTimeEdit, QWidget, QPlainTextEdit, - QLabel, QDoubleSpinBox, + QLabel, QDoubleSpinBox, QButtonGroup, ) from PyQt5.QtCore import ( QTime, QDateTime, @@ -498,6 +498,17 @@ class ASubWindowFeatures(object): qdate = QDateTime.fromString(date.isoformat(), "yyyy-MM-ddThh:mm:ss") self.find(QDateTimeEdit, name).setDateTime(qdate) + def get_checked_id_button_group(self, name: str): + """Get current checked button id in a buttonGroup + + Args: + name: The buttonGroup component name + + Returns: + Current checked id + """ + return self.find(QButtonGroup, name).checkedId() + # Top level interface diff --git a/src/View/ui/UpdateKPOptions.ui b/src/View/ui/UpdateKPOptions.ui index 881491ba..0f5f1b88 100644 --- a/src/View/ui/UpdateKPOptions.ui +++ b/src/View/ui/UpdateKPOptions.ui @@ -6,37 +6,23 @@ 0 0 - 340 - 204 + 381 + 302 Dialog + + Qt::LeftToRight + - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - Distance computation - - - - true - - - @@ -47,11 +33,17 @@ - - - - true + + + + Upstream to downstream + + false + + + buttonGroup_orientation + @@ -67,20 +59,6 @@ - - - - Origin - - - - - - - Origin value - - - @@ -94,9 +72,80 @@ + + + + Origin + + + + + + + true + + + + + + + Origin value + + + + + + + Downstream to upstream + + + buttonGroup_orientation + + + + + + + true + + + + + + + Orientation + + + + + + + Qt::LeftToRight + + + Keep current + + + true + + + buttonGroup_orientation + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + @@ -134,4 +183,7 @@ + + + From 50686e1b65c31f90ef56caf9619adfc4b04e2b64 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 22 May 2024 15:56:45 +0200 Subject: [PATCH 22/45] Pamhyr: Disable native file dialog. --- src/View/MainWindow.py | 11 +++++++++-- src/View/Tools/ASubWindow.py | 5 ++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 1119e9d8..aef1031d 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -912,7 +912,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Nothing """ if self._study is None: - dialog = QFileDialog(self) + options = QFileDialog.Options() + options |= QFileDialog.DontUseNativeDialog + + dialog = QFileDialog(self, options=options) dialog.setFileMode(QFileDialog.FileMode.ExistingFile) dialog.setDefaultSuffix(".pamhyr") # dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden) @@ -1304,7 +1307,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): if self._study.filename == "": return - dialog = QFileDialog(self) + options = QFileDialog.Options() + options |= QFileDialog.DontUseNativeDialog + + dialog = QFileDialog(self, options=options) + dialog.setFileMode(QFileDialog.FileMode.ExistingFile) dialog.setDefaultSuffix(".BIN") # dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden) diff --git a/src/View/Tools/ASubWindow.py b/src/View/Tools/ASubWindow.py index 78655358..f0658060 100644 --- a/src/View/Tools/ASubWindow.py +++ b/src/View/Tools/ASubWindow.py @@ -102,7 +102,10 @@ class WindowToolKit(object): Returns: The returns of callback """ - dialog = QFileDialog(self) + options = QFileDialog.Options() + options |= QFileDialog.DontUseNativeDialog + + dialog = QFileDialog(self, options=options) if select_file: mode = QFileDialog.FileMode.ExistingFile From 2ee8420b94bf53cf45b4fa842115ff0a0d377e12 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 22 May 2024 17:20:30 +0200 Subject: [PATCH 23/45] Model: Add status versioning and update study version to 0.0.10. --- src/Model/Saved.py | 19 +++++++++++++++++-- src/Model/Study.py | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/Model/Saved.py b/src/Model/Saved.py index 90667a92..6b180b40 100644 --- a/src/Model/Saved.py +++ b/src/Model/Saved.py @@ -22,10 +22,19 @@ logger = logging.getLogger() class SavedStatus(object): - def __init__(self): + def __init__(self, version=0): super(SavedStatus, self).__init__() + self._version = version self._saved = True + @property + def version(self): + return self._version + + @version.setter + def version(self, version): + self._version = version + def is_saved(self): return self._saved @@ -34,5 +43,11 @@ class SavedStatus(object): self._saved = True def modified(self): - # logger.debug("model status set as modified") + if self._saved: + self._version += 1 + + logger.debug( + "STATUS: Model status set as modified " + + f"at version {self._version}" + ) self._saved = False diff --git a/src/Model/Study.py b/src/Model/Study.py index c8ce1dd2..a25241cb 100644 --- a/src/Model/Study.py +++ b/src/Model/Study.py @@ -41,7 +41,7 @@ class Study(SQLModel): def __init__(self, filename=None, init_new=True): # Metadata - self._version = "0.0.9" + self._version = "0.0.10" self.creation_date = datetime.now() self.last_modification_date = datetime.now() self.last_save_date = datetime.now() @@ -209,7 +209,12 @@ class Study(SQLModel): def _create(self): # Info (metadata) self.execute( - "CREATE TABLE info(key TEXT NOT NULL UNIQUE, value TEXT NOT NULL)") + "INSERT INTO info VALUES ('study_release', '0')" + ) + + self.execute( + "CREATE TABLE info(key TEXT NOT NULL UNIQUE, value TEXT NOT NULL)" + ) self.execute( "INSERT INTO info VALUES ('version', " + f"'{self._db_format(self._version)}')", @@ -218,19 +223,20 @@ class Study(SQLModel): self.execute("INSERT INTO info VALUES ('name', '')") self.execute("INSERT INTO info VALUES ('description', '')") self.execute( - f"INSERT INTO info VALUES ('time_system', '{self._time_system}')") + f"INSERT INTO info VALUES ('time_system', '{self._time_system}')" + ) self.execute( - f"INSERT INTO info VALUES ('date', " + - "'{self._date.timestamp()}')" + "INSERT INTO info VALUES ('date', " + + f"'{self._date.timestamp()}')" ) self.execute( - f"INSERT INTO info VALUES ('creation_date', " + - "'{self.creation_time.timestamp()}')" + "INSERT INTO info VALUES ('creation_date', " + + f"'{self.creation_date.timestamp()}')" ) self.execute( - f"INSERT INTO info VALUES ('last_save_date', " + - "'{self.last_save_time.timestamp()}')" + "INSERT INTO info VALUES ('last_save_date', " + + f"'{self.last_save_date.timestamp()}')" ) self._create_submodel() @@ -245,6 +251,12 @@ class Study(SQLModel): logger.debug("Update database") + major, minor, release = version[0].split('.') + if major == "0" and minor == "0" and int(release) < 10: + self.execute( + "INSERT INTO info VALUES ('study_release', '0')" + ) + if self._update_submodel(version[0]): self.execute( f"UPDATE info SET value='{self._version}' WHERE key='version'" @@ -258,6 +270,9 @@ class Study(SQLModel): def _load(cls, filename): new = cls(init_new=False, filename=filename) + version = new.execute("SELECT value FROM info WHERE key='study_release'")[0] + new.status.version = int(version) + # TODO: Load metadata new.name = new.execute("SELECT value FROM info WHERE key='name'")[0] new.description = new.execute( @@ -292,6 +307,11 @@ class Study(SQLModel): def _save(self, progress=None): progress = progress if progress is not None else lambda: None + self.execute( + "INSERT INTO info VALUES ('study_release', "+ + f"'{self.status.version}')" + ) + self.execute( f"UPDATE info SET " + f"value='{self._db_format(self.name)}' WHERE key='name'" From 6c4b67d93ad2cdd18fbff4972e6c869cf595a3bb Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 24 May 2024 11:39:11 +0200 Subject: [PATCH 24/45] pamhyr: Fixing pep8 and use RD and RG by default at update PK (if exists). --- src/Meshing/Mage.py | 4 +-- src/Model/Study.py | 8 +++--- src/View/Geometry/UpdateKPDialog.py | 38 +++++++++++++++++++---------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/Meshing/Mage.py b/src/Meshing/Mage.py index 4dc75a1d..8eb89f8e 100644 --- a/src/Meshing/Mage.py +++ b/src/Meshing/Mage.py @@ -371,8 +371,8 @@ class MeshingWithMageMailleurTT(AMeshingTool): lplan: bool = False, lm: int = 3, linear: bool = False, - origin_value = 0.0, - orientation = 0): + origin_value=0.0, + orientation=0): if reach is None or len(reach.profiles) == 0: return reach diff --git a/src/Model/Study.py b/src/Model/Study.py index a25241cb..46a809bb 100644 --- a/src/Model/Study.py +++ b/src/Model/Study.py @@ -270,8 +270,10 @@ class Study(SQLModel): def _load(cls, filename): new = cls(init_new=False, filename=filename) - version = new.execute("SELECT value FROM info WHERE key='study_release'")[0] - new.status.version = int(version) + version = new.execute( + "SELECT value FROM info WHERE key='study_release'" + ) + new.status.version = int(version[0]) # TODO: Load metadata new.name = new.execute("SELECT value FROM info WHERE key='name'")[0] @@ -308,7 +310,7 @@ class Study(SQLModel): progress = progress if progress is not None else lambda: None self.execute( - "INSERT INTO info VALUES ('study_release', "+ + "INSERT INTO info VALUES ('study_release', " + f"'{self.status.version}')" ) diff --git a/src/View/Geometry/UpdateKPDialog.py b/src/View/Geometry/UpdateKPDialog.py index 548a87c1..1042e37a 100644 --- a/src/View/Geometry/UpdateKPDialog.py +++ b/src/View/Geometry/UpdateKPDialog.py @@ -50,9 +50,20 @@ class UpdateKPDialog(PamhyrDialog): self._init_default_values() def _init_default_values(self): - self._orientation = 0 + gl, _ = self._reach.compute_guidelines() + self._gl = list(gl) + self._begin_dir = "un" self._end_dir = "np" + + lower_gl = list(map(str.lower, self._gl)) + for i, gl in enumerate(lower_gl): + if gl == "rd": + self._begin_dir = self._gl[i] + elif gl == "rg": + self._end_dir = self._gl[i] + + self._orientation = 0 self._origin = self._reach.profile(0) self._origin_value = self._reach.profile(0).kp @@ -64,16 +75,18 @@ class UpdateKPDialog(PamhyrDialog): self.combobox_add_items("comboBox_origin", profiles) - self.find(QComboBox, "comboBox_origin").currentIndexChanged.connect( - self.changed_profile) + self.find(QComboBox, "comboBox_origin")\ + .currentIndexChanged\ + .connect( + self.changed_profile + ) buttonbox = self.find(QButtonGroup, "buttonGroup_orientation") - i = 0 for button in buttonbox.buttons(): - if button.objectName() == "radioButton_0": i = 0 - if button.objectName() == "radioButton_1": i = 1 - if button.objectName() == "radioButton_2": i = 2 + name = button.objectName() + i = int(name.split('_')[-1]) + buttonbox.setId(button, i) def changed_profile(self): @@ -106,11 +119,8 @@ class UpdateKPDialog(PamhyrDialog): return name def _init_default_values_guidelines(self): - gl, _ = self._reach.compute_guidelines() - gl = list(gl) - - bgl = ['un'] + gl + ['np'] - egl = ['un'] + gl + ['np'] + bgl = ['un'] + self._gl + ['np'] + egl = ['un'] + self._gl + ['np'] self.combobox_add_items("comboBox_begin_gl", bgl) self.combobox_add_items("comboBox_end_gl", egl) @@ -144,7 +154,9 @@ class UpdateKPDialog(PamhyrDialog): self._origin_value = self.get_double_spin_box("doubleSpinBox_origin") self._begin_dir = self.get_combobox_text("comboBox_begin_gl") self._end_dir = self.get_combobox_text("comboBox_end_gl") - self._orientation = self.get_checked_id_button_group("buttonGroup_orientation") + self._orientation = self.get_checked_id_button_group( + "buttonGroup_orientation" + ) super().accept() From e4f8bc347d397477f5ee1974f5fcf0bbfd46a1f5 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Thu, 6 Jun 2024 14:29:31 +0200 Subject: [PATCH 25/45] prepare rectangular selection --- src/View/Tools/PamhyrPlot.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/View/Tools/PamhyrPlot.py b/src/View/Tools/PamhyrPlot.py index 843be242..45118fe1 100644 --- a/src/View/Tools/PamhyrPlot.py +++ b/src/View/Tools/PamhyrPlot.py @@ -17,6 +17,7 @@ # -*- coding: utf-8 -*- import matplotlib.colors as mplcolors +from matplotlib.widgets import RectangleSelector from matplotlib import ticker from tools import timestamp_to_old_pamhyr_date @@ -100,6 +101,14 @@ class PamhyrPlot(APlot): self._highlight_data_update = False self._current_data = None #: Current data identifier self._current_data_update = False + self._rect_select = RectangleSelector(ax=self.canvas.axes, + onselect=self.rect_select_callback, + useblit=True, + button=[1, 3], # don't use middle button + minspanx=1.0, + minspany=1.0, + spancoords='pixels', + interactive=False) @property def canvas(self): @@ -231,3 +240,10 @@ class PamhyrPlot(APlot): def onclick(self, event): return + + def rect_select_callback(self, eclick, erelease): + 'eclick and erelease are the press and release events' + x1, y1 = eclick.xdata, eclick.ydata + x2, y2 = erelease.xdata, erelease.ydata + print("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2)) + return From 601ef73b5dd4a8fdbf4877d9e83880500ed5693f Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Thu, 6 Jun 2024 14:30:15 +0200 Subject: [PATCH 26/45] implement rectangular selection in profile window --- src/View/Geometry/Profile/Plot.py | 40 +++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index 5f488592..eb664ea4 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -24,7 +24,7 @@ from tools import timer, trace from View.Tools.PamhyrPlot import PamhyrPlot from PyQt5.QtCore import ( - Qt, QCoreApplication, QItemSelectionModel + Qt, QCoreApplication, QItemSelectionModel, QItemSelection, QItemSelectionRange ) from PyQt5.QtWidgets import QApplication @@ -82,7 +82,7 @@ class Plot(PamhyrPlot): ind, point = self._closer_point(event) self.highlight = ([point], hyd) - self._select_in_table(ind) + self._select_in_table([ind]) self.update() return @@ -135,7 +135,10 @@ class Plot(PamhyrPlot): self._table.setFocus() selection = self._table.selectionModel() - index = self._table.model().index(ind, 0) + index = QItemSelection() + if len(ind) > 0: + for i in ind: + index.append(QItemSelectionRange(self._table.model().index(i, 0))) selection.select( index, QItemSelectionModel.Rows | @@ -143,7 +146,8 @@ class Plot(PamhyrPlot): QItemSelectionModel.Select ) - self._table.scrollTo(index) + if len(ind) > 0: + self._table.scrollTo(self._table.model().index(ind[-1], 0)) self._table.blockSignals(False) def _closer_point(self, event): @@ -181,6 +185,34 @@ class Plot(PamhyrPlot): def _get_z_from_click(self, event): return event.ydata + def rect_select_callback(self, eclick, erelease): + + _, hyd = self.highlight + + x1, y1 = eclick.xdata, eclick.ydata + x2, y2 = erelease.xdata, erelease.ydata + + inds, points = self._points_in_rectangle(x1, y1, x2, y2) + + self.highlight = (points, hyd) + + self._select_in_table(inds) + + self.update() + return + + def _points_in_rectangle(self, x1, y1, x2, y2): + # TODO: use lambdas + listi = [] + listp = [] + station = self.data._get_station(self.data.points) + for i, p in enumerate(self.data.points): + if (min(x1,x2) Date: Thu, 6 Jun 2024 16:29:26 +0200 Subject: [PATCH 27/45] work on interactive profil plot --- src/View/Geometry/Profile/Plot.py | 73 +++++++++++++++++++++-------- src/View/Geometry/Profile/Window.py | 5 +- src/View/Tools/PamhyrPlot.py | 2 +- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index eb664ea4..b6307e00 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -24,7 +24,8 @@ from tools import timer, trace from View.Tools.PamhyrPlot import PamhyrPlot from PyQt5.QtCore import ( - Qt, QCoreApplication, QItemSelectionModel, QItemSelection, QItemSelectionRange + Qt, QCoreApplication, QItemSelectionModel, + QItemSelection, QItemSelectionRange, ) from PyQt5.QtWidgets import QApplication @@ -46,6 +47,7 @@ class Plot(PamhyrPlot): ) self._table = table + self._parent = parent self._z_note = None self._z_line = None self._z_fill_between = None @@ -72,17 +74,24 @@ class Plot(PamhyrPlot): def onpick(self, event): if event.mouseevent.inaxes != self.canvas.axes: return - - modifiers = QApplication.keyboardModifiers() - if modifiers != Qt.ControlModifier: + if event.mouseevent.button.value != 1: return - _, hyd = self.highlight + modifiers = QApplication.keyboardModifiers() + if modifiers not in [Qt.ControlModifier, Qt.NoModifier]: + return + + points, hyd = self.highlight ind, point = self._closer_point(event) - self.highlight = ([point], hyd) - self._select_in_table([ind]) + if modifiers == Qt.ControlModifier: + rows = self._parent.index_selected_rows() + self.highlight = (points+[point], hyd) + self._select_in_table(rows+[ind]) + else: + self.highlight = ([point], hyd) + self._select_in_table([ind]) self.update() return @@ -90,18 +99,22 @@ class Plot(PamhyrPlot): def onclick(self, event): if event.inaxes != self.canvas.axes: return - - modifiers = QApplication.keyboardModifiers() - if modifiers != Qt.ShiftModifier: + if event.button.value == 1: return + #modifiers = QApplication.keyboardModifiers() + #if modifiers not in [Qt.ShiftModifier]: + #return + points, _ = self.highlight z = self._get_z_from_click(event) - if z < self.data.z_min(): + if z < self.data.z_min() or event.button.value == 2: + self.highlight = (points, None) + self.update() return - a, p, w = self._compute_hydrolics(z) + a, p, w = self._compute_hydraulics(z) logger.debug(f"{z, a, p, w}") @@ -110,7 +123,7 @@ class Plot(PamhyrPlot): self.update() return - def select_points_from_indexes(self, indexes): + def select_points_from_indices(self, indexes): data = self.data _, hyd = self.highlight @@ -187,16 +200,27 @@ class Plot(PamhyrPlot): def rect_select_callback(self, eclick, erelease): - _, hyd = self.highlight + x1, y1 = eclick.xdata, eclick.ydata + x2, y2 = erelease.xdata, erelease.ydata + + if(max(abs(x1-x2), abs(y1-y2))<0.001): + return + modifiers = QApplication.keyboardModifiers() + + points, hyd = self.highlight x1, y1 = eclick.xdata, eclick.ydata x2, y2 = erelease.xdata, erelease.ydata - inds, points = self._points_in_rectangle(x1, y1, x2, y2) + inds, points2 = self._points_in_rectangle(x1, y1, x2, y2) - self.highlight = (points, hyd) - - self._select_in_table(inds) + if modifiers == Qt.ControlModifier: + rows = self._parent.index_selected_rows() + self.highlight = (points+points2, hyd) + self._select_in_table(rows+inds) + else: + self.highlight = (points2, hyd) + self._select_in_table(inds) self.update() return @@ -213,7 +237,7 @@ class Plot(PamhyrPlot): return listi, listp - def _compute_hydrolics(self, z): + def _compute_hydraulics(self, z): profile = self.data points = profile.wet_points(z) @@ -242,7 +266,7 @@ class Plot(PamhyrPlot): self.profile_line2D, = self.canvas.axes.plot( x, y, color=self.color_plot, lw=1.5, markersize=7, marker='+', - picker=30 + picker=10 ) self.draw_annotation(x, y) @@ -307,6 +331,11 @@ class Plot(PamhyrPlot): if hyd is not None: self.draw_highligth_z_line(*hyd) + else: + if self._z_note is not None: + self._z_note.set_visible(False) + self._z_line[0].set_visible(False) + self._z_fill_between.set_visible(False) def draw_highligth_z_line(self, z, a, p, w): text = ( @@ -331,6 +360,7 @@ class Plot(PamhyrPlot): xlim, [z, z], color=self.color_plot_river_water ) + self._z_line[0].set_visible(True) self._z_note = self.canvas.axes.annotate( text, pos, @@ -342,12 +372,15 @@ class Plot(PamhyrPlot): fontweight='bold', alpha=0.7 ) + self._z_note.set_visible(True) else: self.draw_highligth_z_line_fill(x, y, z) self._z_line[0].set_data(xlim, [z, z]) self._z_note.set_position(pos) self._z_note.set_text(text) + self._z_line[0].set_visible(True) + self._z_note.set_visible(True) def draw_highligth_z_line_fill(self, x, y, z): if self._z_fill_between is not None: diff --git a/src/View/Geometry/Profile/Window.py b/src/View/Geometry/Profile/Window.py index e93eccff..6e0e5c15 100644 --- a/src/View/Geometry/Profile/Window.py +++ b/src/View/Geometry/Profile/Window.py @@ -115,7 +115,8 @@ class ProfileWindow(PamhyrWindow): data=self._profile, trad=self._trad, toolbar=self._toolbar, - table=self.find(QTableView, "tableView") + table=self.find(QTableView, "tableView"), + parent=self ) self._plot.draw() @@ -146,7 +147,7 @@ class ProfileWindow(PamhyrWindow): def update_points_selection(self): rows = self.index_selected_rows() - self._plot.select_points_from_indexes(rows) + self._plot.select_points_from_indices(rows) def update(self): self.update_plot() diff --git a/src/View/Tools/PamhyrPlot.py b/src/View/Tools/PamhyrPlot.py index 45118fe1..23ae2638 100644 --- a/src/View/Tools/PamhyrPlot.py +++ b/src/View/Tools/PamhyrPlot.py @@ -104,7 +104,7 @@ class PamhyrPlot(APlot): self._rect_select = RectangleSelector(ax=self.canvas.axes, onselect=self.rect_select_callback, useblit=True, - button=[1, 3], # don't use middle button + button=[1], # don't use middle nor right button minspanx=1.0, minspany=1.0, spancoords='pixels', From dfe12c8bcb39f17d7ccbe370a7b8c009ff612662 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Fri, 7 Jun 2024 14:18:56 +0200 Subject: [PATCH 28/45] work on multiple selection in profil plot --- src/View/Geometry/Profile/Plot.py | 34 ++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index b6307e00..43d3c831 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -78,7 +78,7 @@ class Plot(PamhyrPlot): return modifiers = QApplication.keyboardModifiers() - if modifiers not in [Qt.ControlModifier, Qt.NoModifier]: + if modifiers not in [Qt.ControlModifier, Qt.NoModifier, Qt.ShiftModifier]: return points, hyd = self.highlight @@ -89,6 +89,18 @@ class Plot(PamhyrPlot): rows = self._parent.index_selected_rows() self.highlight = (points+[point], hyd) self._select_in_table(rows+[ind]) + elif modifiers == Qt.ShiftModifier: + rows = self._parent.index_selected_rows() + if len(rows)>0: + i1 = min(rows[0], rows[-1], ind) + i2 = max(rows[0], rows[-1], ind) + p = [[self.data.points[i].x,self.data.points[i].y] for i in range(i1, i2)] + else: + i1 = ind + i2 = ind + p = [point] + self.highlight = (p, hyd) + self._select_range_in_table(i1, i2) else: self.highlight = ([point], hyd) self._select_in_table([ind]) @@ -123,7 +135,7 @@ class Plot(PamhyrPlot): self.update() return - def select_points_from_indices(self, indexes): + def select_points_from_indices(self, indices): data = self.data _, hyd = self.highlight @@ -131,7 +143,7 @@ class Plot(PamhyrPlot): map( lambda e: e[1], filter( - lambda e: e[0] in indexes, + lambda e: e[0] in indices, enumerate( zip(data.get_station(), data.z()) ) @@ -163,6 +175,22 @@ class Plot(PamhyrPlot): self._table.scrollTo(self._table.model().index(ind[-1], 0)) self._table.blockSignals(False) + def _select_range_in_table(self, ind1, ind2): + if self._table is not None: + self._table.blockSignals(True) + self._table.setFocus() + selection = self._table.selectionModel() + index = QItemSelection(self._table.model().index(ind1, 0), + self._table.model().index(ind2, 0)) + selection.select( + index, + QItemSelectionModel.Rows | + QItemSelectionModel.ClearAndSelect | + QItemSelectionModel.Select + ) + self._table.scrollTo(self._table.model().index(ind2, 0)) + self._table.blockSignals(False) + def _closer_point(self, event): points_ind = event.ind axes = self.canvas.axes From 31b37a779257a9b319292ed20aacb73d3e236d62 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Fri, 7 Jun 2024 16:23:09 +0200 Subject: [PATCH 29/45] add mouse selection in kpz geometry window --- src/View/Geometry/PlotAC.py | 1 + src/View/Geometry/PlotKPZ.py | 47 ++++++++++++++++++++++++++++++- src/View/Geometry/PlotXY.py | 1 + src/View/Geometry/Profile/Plot.py | 8 +++--- src/View/Geometry/Window.py | 3 +- src/View/Tools/PamhyrPlot.py | 6 +++- 6 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/View/Geometry/PlotAC.py b/src/View/Geometry/PlotAC.py index ad43fdf3..2bdee3d1 100644 --- a/src/View/Geometry/PlotAC.py +++ b/src/View/Geometry/PlotAC.py @@ -50,6 +50,7 @@ class PlotAC(PamhyrPlot): self.previous_plot_selected = None self.plot_selected = None self.next_plot_selected = None + self._rect_select = None @timer def draw(self): diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index 651a6758..7368ceb0 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -20,6 +20,8 @@ import logging from tools import timer from View.Tools.PamhyrPlot import PamhyrPlot +from PyQt5.QtWidgets import QApplication +from PyQt5.QtCore import Qt logger = logging.getLogger() @@ -51,6 +53,48 @@ class PlotKPZ(PamhyrPlot): self.before_plot_selected = None self.plot_selected = None self.after_plot_selected = None + self._rect_select = None + self.parent=parent + + def onpick(self, event): + if event.mouseevent.inaxes != self.canvas.axes: + return + if event.mouseevent.button.value != 1: + return + + modifiers = QApplication.keyboardModifiers() + if modifiers not in [Qt.ControlModifier, Qt.NoModifier, Qt.ShiftModifier]: + return + + ind, point = self._closest_kp(event) + if self.parent._table is not None: + self.parent._table.blockSignals(True) + self.parent.select_row_profile_slider(ind) + self.parent._table.blockSignals(False) + + self.update() + return + + def _closest_kp(self, event): + + s = event.artist.get_segments() + x = [i[0,0] for i in s] + print(x) + mx = event.mouseevent.xdata + points = enumerate(x) + + def dist_mouse(point): + x = point[1] + d = abs(mx - x) + return d + + closest = min( + points, key=dist_mouse + ) + + print("closest = "+str(closest)) + + return closest @timer def draw(self): @@ -91,7 +135,8 @@ class PlotKPZ(PamhyrPlot): self.line_kp_zmin_zmax = self.canvas.axes.vlines( x=kp, ymin=z_min, ymax=z_max, color=self.color_plot, - lw=1. + lw=1., + picker=10 ) def draw_z_line_highlight(self): diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index baa46d26..a60d9a96 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -46,6 +46,7 @@ class PlotXY(PamhyrPlot): self.before_plot_selected = None self.plot_selected = None self.after_plot_selected = None + self._rect_select = None @timer def draw(self): diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index 43d3c831..fdb15303 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -83,7 +83,7 @@ class Plot(PamhyrPlot): points, hyd = self.highlight - ind, point = self._closer_point(event) + ind, point = self._closest_point(event) if modifiers == Qt.ControlModifier: rows = self._parent.index_selected_rows() @@ -191,7 +191,7 @@ class Plot(PamhyrPlot): self._table.scrollTo(self._table.model().index(ind2, 0)) self._table.blockSignals(False) - def _closer_point(self, event): + def _closest_point(self, event): points_ind = event.ind axes = self.canvas.axes bx, by = axes.get_xlim(), axes.get_ylim() @@ -217,11 +217,11 @@ class Plot(PamhyrPlot): ) return d - closer = min( + closest = min( points, key=dist_mouse ) - return closer + return closest def _get_z_from_click(self, event): return event.ydata diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index ad5b0a23..020c29b4 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -382,7 +382,8 @@ class GeometryWindow(PamhyrWindow): study=self._study, data=self._reach, trad=self._trad, - toolbar=self._toolbar_kpc + toolbar=self._toolbar_kpc, + parent=self ) self._plot_kpc.draw() diff --git a/src/View/Tools/PamhyrPlot.py b/src/View/Tools/PamhyrPlot.py index 23ae2638..2be88480 100644 --- a/src/View/Tools/PamhyrPlot.py +++ b/src/View/Tools/PamhyrPlot.py @@ -16,6 +16,8 @@ # -*- coding: utf-8 -*- +import logging + import matplotlib.colors as mplcolors from matplotlib.widgets import RectangleSelector from matplotlib import ticker @@ -26,6 +28,8 @@ from View.Tools.Plot.APlot import APlot from View.Tools.Plot.PamhyrCanvas import MplCanvas from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar +logger = logging.getLogger() + class PamhyrPlot(APlot): color_axes = "black" @@ -245,5 +249,5 @@ class PamhyrPlot(APlot): 'eclick and erelease are the press and release events' x1, y1 = eclick.xdata, eclick.ydata x2, y2 = erelease.xdata, erelease.ydata - print("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2)) + logging.debug("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2)) return From 052faed48dd540eeefcf66c7628043c702cee5d1 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Mon, 10 Jun 2024 14:58:47 +0200 Subject: [PATCH 30/45] PlotXY restructuration --- src/View/Geometry/PlotXY.py | 247 +++++++++++++++++++----------- src/View/Geometry/Profile/Plot.py | 8 +- src/View/Geometry/Window.py | 4 +- 3 files changed, 163 insertions(+), 96 deletions(-) diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index a60d9a96..b4d106e2 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -18,22 +18,27 @@ from tools import timer, trace from View.Tools.PamhyrPlot import PamhyrPlot +from matplotlib import collections +import numpy as np from PyQt5.QtCore import ( - QCoreApplication + QCoreApplication, Qt, QItemSelectionModel, + QItemSelection, QItemSelectionRange, ) +from PyQt5.QtWidgets import QApplication _translate = QCoreApplication.translate class PlotXY(PamhyrPlot): def __init__(self, canvas=None, trad=None, data=None, toolbar=None, - parent=None): + table=None, parent=None): super(PlotXY, self).__init__( canvas=canvas, trad=trad, data=data, toolbar=toolbar, + table=table, parent=parent ) @@ -47,6 +52,112 @@ class PlotXY(PamhyrPlot): self.plot_selected = None self.after_plot_selected = None self._rect_select = None + self.parent=parent + self.line_xy_collection = None + self._table=table + self.colors = [] + + def onpick(self, event): + if event.mouseevent.inaxes != self.canvas.axes: + return + if event.mouseevent.button.value != 1: + return + + modifiers = QApplication.keyboardModifiers() + if modifiers not in [Qt.ControlModifier, Qt.NoModifier, Qt.ShiftModifier]: + return + + ind, point = self._closest_section(event) + print(ind) + if self._table is not None: + self._table.blockSignals(True) + if modifiers == Qt.ControlModifier: + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) + ) + ) + self._select_in_table(rows+[ind]) + elif modifiers == Qt.ShiftModifier: + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) + ) + ) + if len(rows)>0: + i1 = min(rows[0], rows[-1], ind) + i2 = max(rows[0], rows[-1], ind) + else: + i1 = ind + i2 = ind + self._select_range_in_table(i1, i2) + else: + self.parent.select_row_profile_slider(ind) + self._table.blockSignals(False) + + #self.update() + return + + def _closest_section(self, event): + axes = self.canvas.axes + mx = event.mouseevent.xdata + my = event.mouseevent.ydata + bx, by = axes.get_xlim(), axes.get_ylim() + ratio = (bx[0] - bx[1]) / (by[0] - by[1]) + + segments = event.artist.get_segments() + ind = event.ind + + points = [] + for i in ind: + points = points + [[i, j] for j in segments[i]] + + def dist_mouse(point): + x, y = point[1] + d2 = (((mx - x) / ratio) ** 2) + ((my - y) ** 2) + return d2 + + closest = min( + points, key=dist_mouse + ) + + return closest + + def _select_in_table(self, ind): + if self._table is not None: + self._table.blockSignals(True) + self._table.setFocus() + selection = self._table.selectionModel() + index = QItemSelection() + if len(ind) > 0: + for i in ind: + index.append(QItemSelectionRange(self._table.model().index(i, 0))) + selection.select( + index, + QItemSelectionModel.Rows | + QItemSelectionModel.ClearAndSelect | + QItemSelectionModel.Select + ) + + if len(ind) > 0: + self._table.scrollTo(self._table.model().index(ind[-1], 0)) + self._table.blockSignals(False) + + def _select_range_in_table(self, ind1, ind2): + if self._table is not None: + self._table.blockSignals(True) + self._table.setFocus() + selection = self._table.selectionModel() + index = QItemSelection(self._table.model().index(ind1, 0), + self._table.model().index(ind2, 0)) + selection.select( + index, + QItemSelectionModel.Rows | + QItemSelectionModel.ClearAndSelect | + QItemSelectionModel.Select + ) + self._table.scrollTo(self._table.model().index(ind2, 0)) + self._table.blockSignals(False) @timer def draw(self): @@ -64,33 +175,39 @@ class PlotXY(PamhyrPlot): self.draw_xy() self.draw_lr() self.draw_gl() - self.draw_current() + #self.draw_current() self.idle() self._init = True def draw_xy(self): - kp = self.data.get_kp_complete_profiles() - - kp_min, kp_max = (-1, -1) - if self._highlight_data is not None: - kp_min, kp_max = self._highlight_data - - def color_hightlight(kp): - if kp_min <= kp <= kp_max: - return self.color_plot_highlight - return self.color_plot self.line_xy = [] - for x, y, kp in zip(self.data.get_x(), - self.data.get_y(), - kp): - line = self.canvas.axes.plot( - x, y, - color=color_hightlight(kp), - **self.plot_default_kargs + for xy in zip(self.data.get_x(), self.data.get_y()): + self.line_xy.append(np.column_stack(xy)) + + self.colors = self.color_hightlight() + self.line_xy_collection = collections.LineCollection(self.line_xy, + colors = self.colors, + picker=10) + self.canvas.axes.add_collection(self.line_xy_collection) + + def color_hightlight(self): + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) ) - self.line_xy.append(line) + ) + colors = [self.color_plot for row in range(len(self.line_xy))] + if len(rows) >0: + for row in rows: + colors[row] = self.color_plot_current + if rows[0] > 0: + colors[rows[0]-1] = self.color_plot_previous + if rows[-1] < len(self.line_xy)-1: + colors[rows[-1]+1] = self.color_plot_next + return colors + def draw_lr(self): lx = [] @@ -137,33 +254,6 @@ class PlotXY(PamhyrPlot): self.line_gl.append(line) ind += 1 - def draw_current(self): - # Previous profile - self.before_plot_selected, = self.canvas.axes.plot( - self.data.profile(0).x(), - self.data.profile(0).y(), - color=self.color_plot_previous, linestyle="--", - **self.plot_default_kargs - ) - self.before_plot_selected.set_visible(False) - - # Current profile - self.plot_selected, = self.canvas.axes.plot( - self.data.profile(0).x(), - self.data.profile(0).y(), - color=self.color_plot_current, **self.plot_default_kargs - ) - self.plot_selected.set_visible(False) - - # Next profile - self.after_plot_selected, = self.canvas.axes.plot( - self.data.profile(0).x(), - self.data.profile(0).y(), - color=self.color_plot_next, linestyle='--', - **self.plot_default_kargs - ) - self.after_plot_selected.set_visible(False) - @timer def update(self): if not self._init: @@ -184,21 +274,24 @@ class PlotXY(PamhyrPlot): x_complete = list(self.data.get_guidelines_x()) y_complete = list(self.data.get_guidelines_y()) - for i in range(self.data.number_profiles): - if i < len(self.line_xy): - self.line_xy[i][0].set_data( - self.data.profile(i).x(), - self.data.profile(i).y() - ) - else: - self.line_xy.append( - self.canvas.axes.plot( - self.data.profile(i).x(), - self.data.profile(i).y(), - color='r', - **self.plot_default_kargs - ) - ) + # TODO comprendre à quoi sert ce bout de code + # ========> + #for i in range(self.data.number_profiles): + #if i < len(self.line_xy): + #self.line_xy[i][0].set_data( + #self.data.profile(i).x(), + #self.data.profile(i).y() + #) + #else: + #self.line_xy.append( + #self.canvas.axes.plot( + #self.data.profile(i).x(), + #self.data.profile(i).y(), + #color='r', + #**self.plot_default_kargs + #) + #) + # <======== for i in range(len(x_complete)): if i < len(self.line_gl): @@ -216,32 +309,8 @@ class PlotXY(PamhyrPlot): def update_current(self): if self._current_data_update: - ind = self._current_data - before = ind - 1 - after = ind + 1 - - self.before_plot_selected.set_visible(False) - self.plot_selected.set_visible(False) - self.after_plot_selected.set_visible(False) - - if 0 <= before < self.data.number_profiles: - self.before_plot_selected.set_data( - self.data.profile(before).x(), - self.data.profile(before).y() - ) - self.before_plot_selected.set_visible(True) - - if 0 <= ind < self.data.number_profiles: - self.plot_selected.set_data(self.data.profile(ind).x(), - self.data.profile(ind).y()) - self.plot_selected.set_visible(True) - - if 0 <= after < self.data.number_profiles: - self.after_plot_selected.set_data( - self.data.profile(after).x(), - self.data.profile(after).y() - ) - self.after_plot_selected.set_visible(True) + self.colors = self.color_hightlight() + self.line_xy_collection.set_colors(self.colors) def update_lr(self): for line in self.line_lr: diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index fdb15303..7b7815ad 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -158,7 +158,6 @@ class Plot(PamhyrPlot): if self._table is not None: self._table.blockSignals(True) self._table.setFocus() - selection = self._table.selectionModel() index = QItemSelection() if len(ind) > 0: @@ -211,11 +210,8 @@ class Plot(PamhyrPlot): def dist_mouse(point): x, y = point[1] - d = sqrt( - (((mx - x) / ratio) ** 2) + - ((my - y) ** 2) - ) - return d + d2 = ((mx - x) / ratio) ** 2 + ((my - y) ** 2) + return d2 closest = min( points, key=dist_mouse diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 020c29b4..830f1ded 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -363,7 +363,9 @@ class GeometryWindow(PamhyrWindow): canvas=self._canvas_xy, data=self._reach, trad=self._trad, - toolbar=self._toolbar_xy + toolbar=self._toolbar_xy, + table=self.find(QTableView, "tableView"), + parent=self ) self._plot_xy.draw() From 872ff0ef620cce30093153c13e06d5a7a0e7421d Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Mon, 10 Jun 2024 15:59:02 +0200 Subject: [PATCH 31/45] PlotKPZ restructuration --- src/View/Geometry/PlotKPZ.py | 246 +++++++++++++++++++---------------- src/View/Geometry/PlotXY.py | 24 ++-- src/View/Geometry/Window.py | 1 + 3 files changed, 146 insertions(+), 125 deletions(-) diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index 7368ceb0..2e904987 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -21,7 +21,10 @@ import logging from tools import timer from View.Tools.PamhyrPlot import PamhyrPlot from PyQt5.QtWidgets import QApplication -from PyQt5.QtCore import Qt +from PyQt5.QtCore import( + Qt, QItemSelectionModel, + QItemSelection, QItemSelectionRange, +) logger = logging.getLogger() @@ -29,7 +32,7 @@ logger = logging.getLogger() class PlotKPZ(PamhyrPlot): def __init__(self, canvas=None, trad=None, study=None, data=None, toolbar=None, - parent=None): + table=None, parent=None): self._study = study super(PlotKPZ, self).__init__( @@ -37,6 +40,7 @@ class PlotKPZ(PamhyrPlot): trad=trad, data=data, toolbar=toolbar, + table=table, parent=parent ) @@ -55,6 +59,8 @@ class PlotKPZ(PamhyrPlot): self.after_plot_selected = None self._rect_select = None self.parent=parent + self._table=table + self._colors = [] def onpick(self, event): if event.mouseevent.inaxes != self.canvas.axes: @@ -69,7 +75,28 @@ class PlotKPZ(PamhyrPlot): ind, point = self._closest_kp(event) if self.parent._table is not None: self.parent._table.blockSignals(True) - self.parent.select_row_profile_slider(ind) + if modifiers == Qt.ControlModifier: + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) + ) + ) + self._select_in_table(rows+[ind]) + elif modifiers == Qt.ShiftModifier: + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) + ) + ) + if len(rows)>0: + i1 = min(rows[0], rows[-1], ind) + i2 = max(rows[0], rows[-1], ind) + else: + i1 = ind + i2 = ind + self._select_range_in_table(i1, i2) + else: + self.parent.select_row_profile_slider(ind) self.parent._table.blockSignals(False) self.update() @@ -96,6 +123,42 @@ class PlotKPZ(PamhyrPlot): return closest + def _select_in_table(self, ind): + if self._table is not None: + self._table.blockSignals(True) + self._table.setFocus() + selection = self._table.selectionModel() + index = QItemSelection() + if len(ind) > 0: + for i in ind: + index.append(QItemSelectionRange(self._table.model().index(i, 0))) + selection.select( + index, + QItemSelectionModel.Rows | + QItemSelectionModel.ClearAndSelect | + QItemSelectionModel.Select + ) + + if len(ind) > 0: + self._table.scrollTo(self._table.model().index(ind[-1], 0)) + self._table.blockSignals(False) + + def _select_range_in_table(self, ind1, ind2): + if self._table is not None: + self._table.blockSignals(True) + self._table.setFocus() + selection = self._table.selectionModel() + index = QItemSelection(self._table.model().index(ind1, 0), + self._table.model().index(ind2, 0)) + selection.select( + index, + QItemSelectionModel.Rows | + QItemSelectionModel.ClearAndSelect | + QItemSelectionModel.Select + ) + self._table.scrollTo(self._table.model().index(ind2, 0)) + self._table.blockSignals(False) + @timer def draw(self): self.init_axes() @@ -118,8 +181,7 @@ class PlotKPZ(PamhyrPlot): return self.draw_z_line() - self.draw_z_line_highlight() - self.draw_current() + self.draw_lr() self.draw_gl() self.draw_bottom() self.draw_profiles_hs(self._data) @@ -132,77 +194,60 @@ class PlotKPZ(PamhyrPlot): z_min = self.data.get_z_min() z_max = self.data.get_z_max() + self._colors, self._style = self.color_hightlight() + self.line_kp_zmin_zmax = self.canvas.axes.vlines( x=kp, ymin=z_min, ymax=z_max, - color=self.color_plot, + color=self._colors, + linestyle = self._style, lw=1., - picker=10 + picker=10, ) - def draw_z_line_highlight(self): - if self._highlight_data is not None: - kp = self.data.get_kp_complete_profiles() - z_min = self.data.get_z_min() - z_max = self.data.get_z_max() - - kp_min, kp_max = self._highlight_data - - indexes = list( - map( - lambda x: x[0], - filter( - lambda x: kp_min <= x[1] <= kp_max, - enumerate(kp) - ) - ) + def color_hightlight(self): + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) ) + ) + colors = [self.color_plot for row in range(len(self._data))] + style = ["-" for row in range(len(self._data))] + if len(rows) >0: + for row in rows: + colors[row] = self.color_plot_current + if rows[0] > 0: + colors[rows[0]-1] = self.color_plot_previous + style[rows[0]-1] = "--" + if rows[-1] < len(self._data)-1: + colors[rows[-1]+1] = self.color_plot_next + style[rows[-1]+1] = "--" + return colors, style - def indexes_filter(data): return list( - map( - lambda x: x[1], - filter( - lambda x: x[0] in indexes, - enumerate(data) - ) - ) - ) - - ikp = indexes_filter(kp) - imin = indexes_filter(z_min) - imax = indexes_filter(z_max) - - self.line_kp_zmin_zmax_highlight = self.canvas.axes.vlines( - x=ikp, - ymin=imin, ymax=imax, - color=self.color_plot_highlight, - lw=1. - ) - - def draw_current(self): + def draw_lr(self): kp = self.data.get_kp_complete_profiles() - z_min = self.data.get_z_min() - z_max = self.data.get_z_max() + lz = [] + rz = [] - self.plot_selected, = self.canvas.axes.plot( - (kp[0], kp[0]), - (z_min[0], z_max[0]), - color=self.color_plot_current, lw=1.5 - ) - self.plot_selected.set_visible(False) + self.line_lr = [] + for z in self.data.get_z(): + lz.append(z[0]) + rz.append(z[-1]) - self.before_plot_selected, = self.canvas.axes.plot( - (kp[0], kp[0]), - (z_min[0], z_max[0]), - color=self.color_plot_previous, lw=1.5, linestyle='--' + line = self.canvas.axes.plot( + kp, lz, + color=self.color_plot_river_bottom, + linestyle="dotted", + lw=1., ) - self.before_plot_selected.set_visible(False) + self.line_lr.append(line) - self.after_plot_selected, = self.canvas.axes.plot( - (kp[0], kp[0]), - (z_min[0], z_max[0]), - color=self.color_plot_next, lw=1.5, linestyle='--' + line = self.canvas.axes.plot( + kp, rz, + color=self.color_plot_river_bottom, + linestyle="dotted", + lw=1., ) - self.after_plot_selected.set_visible(False) + self.line_lr.append(line) def draw_gl(self): kp = self.data.get_kp_complete_profiles() @@ -270,6 +315,7 @@ class PlotKPZ(PamhyrPlot): self.draw() return + self.update_lr() self.update_gl() self.update_current() @@ -277,52 +323,9 @@ class PlotKPZ(PamhyrPlot): def update_current(self): if self._current_data_update: - ind = self._current_data - before = ind - 1 - after = ind + 1 - - self.before_plot_selected.set_visible(False) - self.plot_selected.set_visible(False) - self.after_plot_selected.set_visible(False) - - if 0 <= before < self.data.number_profiles: - profile = self.data.profile(before) - if len(profile) > 0: - kp_i = profile.kp - z_min_i = profile.z_min() - z_max_i = profile.z_max() - - self.before_plot_selected.set_data( - (kp_i, kp_i), - (z_min_i, z_max_i) - ) - self.before_plot_selected.set_visible(True) - - if 0 <= ind < self.data.number_profiles: - profile = self.data.profile(ind) - if len(profile) > 0: - kp_i = profile.kp - z_min_i = profile.z_min() - z_max_i = profile.z_max() - - self.plot_selected.set_data( - (kp_i, kp_i), - (z_min_i, z_max_i) - ) - self.plot_selected.set_visible(True) - - if 0 <= after < self.data.number_profiles: - profile = self.data.profile(after) - if len(profile) > 0: - kp_i = profile.kp - z_min_i = profile.z_min() - z_max_i = profile.z_max() - - self.after_plot_selected.set_data( - (kp_i, kp_i), - (z_min_i, z_max_i) - ) - self.after_plot_selected.set_visible(True) + self._colors, self._style = self.color_hightlight() + self.line_kp_zmin_zmax.set_colors(self._colors) + self.line_kp_zmin_zmax.set_linestyle(self._style) def update_gl(self): if self._current_data_update: @@ -334,12 +337,19 @@ class PlotKPZ(PamhyrPlot): self.line_kp_zmin.set_data(kp, z_min) - self.line_kp_zmin_zmax.remove() - self.line_kp_zmin_zmax = self.canvas.axes.vlines( - x=kp, - ymin=z_min, ymax=z_max, - color='r', lw=1. - ) + # TODO comprendre à quoi sert ce bout de code + # ========> + #self.line_kp_zmin_zmax.remove() + #self._colors, self._style = self.color_hightlight() + #self.line_kp_zmin_zmax = self.canvas.axes.vlines( + #x=kp, + #ymin=z_min, + #ymax=z_max, + #color=self._colors, + #linestyle = self._style, + #lw=1. + #) + # <======== z_complete = self.data.get_guidelines_z() try: @@ -349,3 +359,9 @@ class PlotKPZ(PamhyrPlot): ) except Exception as e: logger.warning(f"Failed to update graphic KPZ: {e}") + + def update_lr(self): + for line in self.line_lr: + line[0].remove() + + self.draw_lr() diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index b4d106e2..de2c4105 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -55,7 +55,8 @@ class PlotXY(PamhyrPlot): self.parent=parent self.line_xy_collection = None self._table=table - self.colors = [] + self._colors = [] + self._style = [] def onpick(self, event): if event.mouseevent.inaxes != self.canvas.axes: @@ -175,7 +176,6 @@ class PlotXY(PamhyrPlot): self.draw_xy() self.draw_lr() self.draw_gl() - #self.draw_current() self.idle() self._init = True @@ -186,9 +186,10 @@ class PlotXY(PamhyrPlot): for xy in zip(self.data.get_x(), self.data.get_y()): self.line_xy.append(np.column_stack(xy)) - self.colors = self.color_hightlight() + self._colors, self._style = self.color_hightlight() self.line_xy_collection = collections.LineCollection(self.line_xy, - colors = self.colors, + colors = self._colors, + linestyle = self._style, picker=10) self.canvas.axes.add_collection(self.line_xy_collection) @@ -198,16 +199,18 @@ class PlotXY(PamhyrPlot): (i.row() for i in self.parent.tableView.selectedIndexes()) ) ) - colors = [self.color_plot for row in range(len(self.line_xy))] + colors = [self.color_plot for row in range(len(self._data))] + style = ["-" for row in range(len(self._data))] if len(rows) >0: for row in rows: colors[row] = self.color_plot_current if rows[0] > 0: colors[rows[0]-1] = self.color_plot_previous - if rows[-1] < len(self.line_xy)-1: + style[rows[0]-1] = "--" + if rows[-1] < len(self._data)-1: colors[rows[-1]+1] = self.color_plot_next - return colors - + style[rows[-1]+1] = "--" + return colors, style def draw_lr(self): lx = [] @@ -309,8 +312,9 @@ class PlotXY(PamhyrPlot): def update_current(self): if self._current_data_update: - self.colors = self.color_hightlight() - self.line_xy_collection.set_colors(self.colors) + self._colors, self._style = self.color_hightlight() + self.line_xy_collection.set_colors(self._colors) + self.line_xy_collection.set_linestyle(self._style) def update_lr(self): for line in self.line_lr: diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 830f1ded..0f3891ca 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -385,6 +385,7 @@ class GeometryWindow(PamhyrWindow): data=self._reach, trad=self._trad, toolbar=self._toolbar_kpc, + table=self.find(QTableView, "tableView"), parent=self ) self._plot_kpc.draw() From 8cd9ec939b12847efac6b3703dad3763abbab9e1 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Mon, 10 Jun 2024 15:59:32 +0200 Subject: [PATCH 32/45] mend --- src/View/Geometry/PlotKPZ.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index 2e904987..0ecbd558 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -106,7 +106,6 @@ class PlotKPZ(PamhyrPlot): s = event.artist.get_segments() x = [i[0,0] for i in s] - print(x) mx = event.mouseevent.xdata points = enumerate(x) @@ -119,8 +118,6 @@ class PlotKPZ(PamhyrPlot): points, key=dist_mouse ) - print("closest = "+str(closest)) - return closest def _select_in_table(self, ind): From fe57890da421da8b40fd073b2f1c9bdfc2625a2b Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Tue, 11 Jun 2024 10:02:43 +0200 Subject: [PATCH 33/45] work on ctrl+click --- src/View/Geometry/PlotKPZ.py | 12 ++++++------ src/View/Geometry/PlotXY.py | 11 +++++------ src/View/Geometry/Profile/Plot.py | 26 ++++++++++++++++++-------- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index 0ecbd558..142cc7d0 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -81,7 +81,11 @@ class PlotKPZ(PamhyrPlot): (i.row() for i in self.parent.tableView.selectedIndexes()) ) ) - self._select_in_table(rows+[ind]) + if ind in rows: + rows.remove(ind) + self._select_in_table(rows) + else: + self._select_in_table(rows+[ind]) elif modifiers == Qt.ShiftModifier: rows = list( set( @@ -99,7 +103,7 @@ class PlotKPZ(PamhyrPlot): self.parent.select_row_profile_slider(ind) self.parent._table.blockSignals(False) - self.update() + #self.update() return def _closest_kp(self, event): @@ -122,7 +126,6 @@ class PlotKPZ(PamhyrPlot): def _select_in_table(self, ind): if self._table is not None: - self._table.blockSignals(True) self._table.setFocus() selection = self._table.selectionModel() index = QItemSelection() @@ -138,11 +141,9 @@ class PlotKPZ(PamhyrPlot): if len(ind) > 0: self._table.scrollTo(self._table.model().index(ind[-1], 0)) - self._table.blockSignals(False) def _select_range_in_table(self, ind1, ind2): if self._table is not None: - self._table.blockSignals(True) self._table.setFocus() selection = self._table.selectionModel() index = QItemSelection(self._table.model().index(ind1, 0), @@ -154,7 +155,6 @@ class PlotKPZ(PamhyrPlot): QItemSelectionModel.Select ) self._table.scrollTo(self._table.model().index(ind2, 0)) - self._table.blockSignals(False) @timer def draw(self): diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index de2c4105..ea50eff3 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -69,7 +69,6 @@ class PlotXY(PamhyrPlot): return ind, point = self._closest_section(event) - print(ind) if self._table is not None: self._table.blockSignals(True) if modifiers == Qt.ControlModifier: @@ -78,7 +77,11 @@ class PlotXY(PamhyrPlot): (i.row() for i in self.parent.tableView.selectedIndexes()) ) ) - self._select_in_table(rows+[ind]) + if ind in rows: + rows.remove(ind) + self._select_in_table(rows) + else: + self._select_in_table(rows+[ind]) elif modifiers == Qt.ShiftModifier: rows = list( set( @@ -126,7 +129,6 @@ class PlotXY(PamhyrPlot): def _select_in_table(self, ind): if self._table is not None: - self._table.blockSignals(True) self._table.setFocus() selection = self._table.selectionModel() index = QItemSelection() @@ -142,11 +144,9 @@ class PlotXY(PamhyrPlot): if len(ind) > 0: self._table.scrollTo(self._table.model().index(ind[-1], 0)) - self._table.blockSignals(False) def _select_range_in_table(self, ind1, ind2): if self._table is not None: - self._table.blockSignals(True) self._table.setFocus() selection = self._table.selectionModel() index = QItemSelection(self._table.model().index(ind1, 0), @@ -158,7 +158,6 @@ class PlotXY(PamhyrPlot): QItemSelectionModel.Select ) self._table.scrollTo(self._table.model().index(ind2, 0)) - self._table.blockSignals(False) @timer def draw(self): diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index 7b7815ad..8c9fadce 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -70,6 +70,7 @@ class Plot(PamhyrPlot): None # Hydrolic values (z, wet_area, # wet_preimeter, water_width) ) + self.events = [] def onpick(self, event): if event.mouseevent.inaxes != self.canvas.axes: @@ -87,8 +88,14 @@ class Plot(PamhyrPlot): if modifiers == Qt.ControlModifier: rows = self._parent.index_selected_rows() - self.highlight = (points+[point], hyd) - self._select_in_table(rows+[ind]) + if ind in rows: + rows.remove(ind) + del(points[ind]) + self.highlight = (points, hyd) + self._select_in_table(rows) + else: + self.highlight = (points+[point], hyd) + self._select_in_table(rows+[ind]) elif modifiers == Qt.ShiftModifier: rows = self._parent.index_selected_rows() if len(rows)>0: @@ -114,10 +121,6 @@ class Plot(PamhyrPlot): if event.button.value == 1: return - #modifiers = QApplication.keyboardModifiers() - #if modifiers not in [Qt.ShiftModifier]: - #return - points, _ = self.highlight z = self._get_z_from_click(event) @@ -240,8 +243,15 @@ class Plot(PamhyrPlot): if modifiers == Qt.ControlModifier: rows = self._parent.index_selected_rows() - self.highlight = (points+points2, hyd) - self._select_in_table(rows+inds) + if all(i in rows for i in inds): + for ind in sorted(inds, reverse=True): + rows.remove(ind) + del(points[ind]) + self.highlight = (points, hyd) + self._select_in_table(rows) + else: + self.highlight = (points+points2, hyd) + self._select_in_table(rows+inds) else: self.highlight = (points2, hyd) self._select_in_table(inds) From c6b28ba3a0401f57e88f22f6861880153402c8fd Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Tue, 11 Jun 2024 11:55:52 +0200 Subject: [PATCH 34/45] deal with conflicts between onpick and rect select in Profile plot --- src/View/Geometry/PlotKPZ.py | 4 +- src/View/Geometry/PlotXY.py | 4 +- src/View/Geometry/Profile/Plot.py | 77 ++++++++++++++++--------------- src/View/Tools/PamhyrPlot.py | 8 +++- 4 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index 142cc7d0..7d7921a5 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -202,11 +202,11 @@ class PlotKPZ(PamhyrPlot): ) def color_hightlight(self): - rows = list( + rows = sorted(list( set( (i.row() for i in self.parent.tableView.selectedIndexes()) ) - ) + )) colors = [self.color_plot for row in range(len(self._data))] style = ["-" for row in range(len(self._data))] if len(rows) >0: diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index ea50eff3..a96fd45b 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -193,11 +193,11 @@ class PlotXY(PamhyrPlot): self.canvas.axes.add_collection(self.line_xy_collection) def color_hightlight(self): - rows = list( + rows = sorted(list( set( (i.row() for i in self.parent.tableView.selectedIndexes()) ) - ) + )) colors = [self.color_plot for row in range(len(self._data))] style = ["-" for row in range(len(self._data))] if len(rows) >0: diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index 8c9fadce..f8ced64e 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -70,7 +70,41 @@ class Plot(PamhyrPlot): None # Hydrolic values (z, wet_area, # wet_preimeter, water_width) ) - self.events = [] + self._onpickevent = None + + def onrelease(self, event): + # we need to do that to prevent conflicst between onpick and rect_select_callback + modifiers = QApplication.keyboardModifiers() + points, hyd = self.highlight + if self._onpickevent is not None: + ind, point = self._closest_point(self._onpickevent) + if modifiers == Qt.ControlModifier: + rows = self._parent.index_selected_rows() + if ind in rows: + rows.remove(ind) + del(points[ind]) + self.highlight = (points, hyd) + self._select_in_table(rows) + else: + self.highlight = (points+[point], hyd) + self._select_in_table(rows+[ind]) + elif modifiers == Qt.ShiftModifier: + rows = self._parent.index_selected_rows() + if len(rows)>0: + i1 = min(rows[0], rows[-1], ind) + i2 = max(rows[0], rows[-1], ind) + p = [[self.data.points[i].x,self.data.points[i].y] for i in range(i1, i2)] + else: + i1 = ind + i2 = ind + p = [point] + self.highlight = (p, hyd) + self._select_range_in_table(i1, i2) + else: + self.highlight = ([point], hyd) + self._select_in_table([ind]) + + self._onpickevent = None def onpick(self, event): if event.mouseevent.inaxes != self.canvas.axes: @@ -82,37 +116,7 @@ class Plot(PamhyrPlot): if modifiers not in [Qt.ControlModifier, Qt.NoModifier, Qt.ShiftModifier]: return - points, hyd = self.highlight - - ind, point = self._closest_point(event) - - if modifiers == Qt.ControlModifier: - rows = self._parent.index_selected_rows() - if ind in rows: - rows.remove(ind) - del(points[ind]) - self.highlight = (points, hyd) - self._select_in_table(rows) - else: - self.highlight = (points+[point], hyd) - self._select_in_table(rows+[ind]) - elif modifiers == Qt.ShiftModifier: - rows = self._parent.index_selected_rows() - if len(rows)>0: - i1 = min(rows[0], rows[-1], ind) - i2 = max(rows[0], rows[-1], ind) - p = [[self.data.points[i].x,self.data.points[i].y] for i in range(i1, i2)] - else: - i1 = ind - i2 = ind - p = [point] - self.highlight = (p, hyd) - self._select_range_in_table(i1, i2) - else: - self.highlight = ([point], hyd) - self._select_in_table([ind]) - - self.update() + self._onpickevent = event return def onclick(self, event): @@ -227,6 +231,7 @@ class Plot(PamhyrPlot): def rect_select_callback(self, eclick, erelease): + points, hyd = self.highlight x1, y1 = eclick.xdata, eclick.ydata x2, y2 = erelease.xdata, erelease.ydata @@ -234,13 +239,12 @@ class Plot(PamhyrPlot): return modifiers = QApplication.keyboardModifiers() - points, hyd = self.highlight x1, y1 = eclick.xdata, eclick.ydata x2, y2 = erelease.xdata, erelease.ydata inds, points2 = self._points_in_rectangle(x1, y1, x2, y2) - + self._onclickevent = None if modifiers == Qt.ControlModifier: rows = self._parent.index_selected_rows() if all(i in rows for i in inds): @@ -255,8 +259,6 @@ class Plot(PamhyrPlot): else: self.highlight = (points2, hyd) self._select_in_table(inds) - - self.update() return def _points_in_rectangle(self, x1, y1, x2, y2): @@ -267,7 +269,7 @@ class Plot(PamhyrPlot): for i, p in enumerate(self.data.points): if (min(x1,x2) Date: Tue, 11 Jun 2024 14:17:38 +0200 Subject: [PATCH 35/45] interactive profile selection in structures + debug --- src/View/Geometry/PlotAC.py | 1 - src/View/Geometry/PlotKPZ.py | 36 ++++++++--------- src/View/Geometry/PlotXY.py | 1 - src/View/Geometry/Profile/Plot.py | 9 +++++ src/View/HydraulicStructures/PlotKPC.py | 53 +++++++++++++++++++++++-- src/View/HydraulicStructures/Window.py | 3 +- src/View/Tools/PamhyrPlot.py | 11 +---- 7 files changed, 80 insertions(+), 34 deletions(-) diff --git a/src/View/Geometry/PlotAC.py b/src/View/Geometry/PlotAC.py index 2bdee3d1..ad43fdf3 100644 --- a/src/View/Geometry/PlotAC.py +++ b/src/View/Geometry/PlotAC.py @@ -50,7 +50,6 @@ class PlotAC(PamhyrPlot): self.previous_plot_selected = None self.plot_selected = None self.next_plot_selected = None - self._rect_select = None @timer def draw(self): diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index 7d7921a5..36b9beba 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -57,7 +57,6 @@ class PlotKPZ(PamhyrPlot): self.before_plot_selected = None self.plot_selected = None self.after_plot_selected = None - self._rect_select = None self.parent=parent self._table=table self._colors = [] @@ -286,25 +285,26 @@ class PlotKPZ(PamhyrPlot): for hs in lhs: x = hs.input_kp - z_min = reach.get_z_min() - z_max = reach.get_z_max() + if x is not None: + z_min = reach.get_z_min() + z_max = reach.get_z_max() - self.canvas.axes.plot( - [x, x], - [min(z_min), max(z_max)], - linestyle="--", - lw=1., - color=self.color_plot_previous, - ) + self.canvas.axes.plot( + [x, x], + [min(z_min), max(z_max)], + linestyle="--", + lw=1., + color=self.color_plot_previous, + ) - self.canvas.axes.annotate( - " > " + hs.name, - (x, max(z_max)), - horizontalalignment='left', - verticalalignment='top', - annotation_clip=True, - fontsize=9, color=self.color_plot_previous, - ) + self.canvas.axes.annotate( + " > " + hs.name, + (x, max(z_max)), + horizontalalignment='left', + verticalalignment='top', + annotation_clip=True, + fontsize=9, color=self.color_plot_previous, + ) @timer def update(self): diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index a96fd45b..e163e538 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -51,7 +51,6 @@ class PlotXY(PamhyrPlot): self.before_plot_selected = None self.plot_selected = None self.after_plot_selected = None - self._rect_select = None self.parent=parent self.line_xy_collection = None self._table=table diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index f8ced64e..8ebe0aaa 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -29,6 +29,7 @@ from PyQt5.QtCore import ( ) from PyQt5.QtWidgets import QApplication +from matplotlib.widgets import RectangleSelector _translate = QCoreApplication.translate @@ -71,6 +72,14 @@ class Plot(PamhyrPlot): # wet_preimeter, water_width) ) self._onpickevent = None + self._rect_select = RectangleSelector(ax=self.canvas.axes, + onselect=self.rect_select_callback, + useblit=True, + button=[1], # don't use middle nor right button + minspanx=2.0, + minspany=2.0, + spancoords='pixels', + interactive=False) def onrelease(self, event): # we need to do that to prevent conflicst between onpick and rect_select_callback diff --git a/src/View/HydraulicStructures/PlotKPC.py b/src/View/HydraulicStructures/PlotKPC.py index 3327f6e6..209e68a1 100644 --- a/src/View/HydraulicStructures/PlotKPC.py +++ b/src/View/HydraulicStructures/PlotKPC.py @@ -20,8 +20,9 @@ from tools import timer from View.Tools.PamhyrPlot import PamhyrPlot from PyQt5.QtCore import ( - QCoreApplication + QCoreApplication, Qt, ) +from PyQt5.QtWidgets import QApplication from matplotlib.collections import LineCollection @@ -50,6 +51,7 @@ class PlotKPC(PamhyrPlot): self._auto_relim_update = True self._autoscale_update = True + self.parent = parent @property def river(self): @@ -91,7 +93,14 @@ class PlotKPC(PamhyrPlot): self.line_kp_zmin, = self.canvas.axes.plot( kp, z_min, color=self.color_plot_river_bottom, - lw=1. + lw=1., + ) + + self.line_kp_zmax, = self.canvas.axes.plot( + kp, z_max, + color=self.color_plot_river_bottom, + lw=1., + alpha=0.0 ) if len(kp) != 0: @@ -99,7 +108,8 @@ class PlotKPC(PamhyrPlot): x=kp, ymin=z_min, ymax=z_max, color=self.color_plot, - lw=1. + lw=1., + picker=10 ) def draw_current(self): @@ -163,3 +173,40 @@ class PlotKPC(PamhyrPlot): self.profile.set_data([], []) self.canvas.figure.canvas.draw_idle() + + def onpick(self, event): + if event.mouseevent.inaxes != self.canvas.axes: + return + if event.mouseevent.button.value != 1: + return + + modifiers = QApplication.keyboardModifiers() + if modifiers not in [Qt.ControlModifier, Qt.NoModifier, Qt.ShiftModifier]: + return + + closest = self._closest_profile(event) + index = self.parent.tableView.selectedIndexes() + print(index) + if self.parent._table is not None: + self.parent._table.setData(index[2], closest) + + + return + + def _closest_profile(self, event): + + s = event.artist.get_segments() + x = [i[0,0] for i in s] + mx = event.mouseevent.xdata + points = enumerate(x) + + def dist_mouse(point): + x = point[1] + d = abs(mx - x) + return d + + closest = min( + points, key=dist_mouse + ) + + return closest[1] diff --git a/src/View/HydraulicStructures/Window.py b/src/View/HydraulicStructures/Window.py index 1c6af72c..7dee787d 100644 --- a/src/View/HydraulicStructures/Window.py +++ b/src/View/HydraulicStructures/Window.py @@ -141,7 +141,8 @@ class HydraulicStructuresWindow(PamhyrWindow): reach=None, profile=None, trad=self._trad, - toolbar=self.toolbar + toolbar=self.toolbar, + parent=self ) self.plot_kpc.draw() diff --git a/src/View/Tools/PamhyrPlot.py b/src/View/Tools/PamhyrPlot.py index 41b0b87f..76159205 100644 --- a/src/View/Tools/PamhyrPlot.py +++ b/src/View/Tools/PamhyrPlot.py @@ -19,7 +19,6 @@ import logging import matplotlib.colors as mplcolors -from matplotlib.widgets import RectangleSelector from matplotlib import ticker from tools import timestamp_to_old_pamhyr_date @@ -43,7 +42,6 @@ class PamhyrPlot(APlot): color_plot_river_bottom = "grey" color_plot_river_water = "blue" color_plot_river_water_zone = "skyblue" - colors = list(mplcolors.TABLEAU_COLORS) linestyle = ['solid', 'dashed', 'dashdot', 'dotted'] @@ -106,14 +104,7 @@ class PamhyrPlot(APlot): self._highlight_data_update = False self._current_data = None #: Current data identifier self._current_data_update = False - self._rect_select = RectangleSelector(ax=self.canvas.axes, - onselect=self.rect_select_callback, - useblit=True, - button=[1], # don't use middle nor right button - minspanx=2.0, - minspany=2.0, - spancoords='pixels', - interactive=False) + self._rect_select = None @property def canvas(self): From 59fc80a10bf429dc289d93f0c2c3fa2dfee6f790 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Tue, 11 Jun 2024 16:19:52 +0200 Subject: [PATCH 36/45] debug + interactive selection in lateral contrib --- src/View/Frictions/PlotKPZ.py | 50 +++++ src/View/Frictions/Window.py | 7 +- src/View/Geometry/PlotXY.py | 1 - src/View/HydraulicStructures/PlotKPC.py | 2 - src/View/LateralContribution/PlotXY.py | 259 ++++++++++++++++++++++++ src/View/LateralContribution/Window.py | 13 +- 6 files changed, 325 insertions(+), 7 deletions(-) create mode 100644 src/View/Frictions/PlotKPZ.py create mode 100644 src/View/LateralContribution/PlotXY.py diff --git a/src/View/Frictions/PlotKPZ.py b/src/View/Frictions/PlotKPZ.py new file mode 100644 index 00000000..97a80b5b --- /dev/null +++ b/src/View/Frictions/PlotKPZ.py @@ -0,0 +1,50 @@ +# PlotKPC.py -- Pamhyr +# Copyright (C) 2023-2024 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- + +from PyQt5.QtCore import QCoreApplication +from View.HydraulicStructures.PlotKPC import PlotKPC + +_translate = QCoreApplication.translate + + +class PlotKPZ(PlotKPC): + def __init__(self, canvas=None, trad=None, toolbar=None, + river=None, reach=None, profile=None, + parent=None): + super(PlotKPC, self).__init__( + canvas=canvas, + trad=trad, + data=river, + toolbar=toolbar, + parent=parent + ) + + self._current_reach = reach + self._current_profile = profile + + self.label_x = self._trad["unit_kp"] + self.label_y = self._trad["unit_elevation"] + + self._isometric_axis = False + + self._auto_relim_update = True + self._autoscale_update = True + self.parent = parent + + def onpick(self, event): + return diff --git a/src/View/Frictions/Window.py b/src/View/Frictions/Window.py index c0c7d81b..9776ce56 100644 --- a/src/View/Frictions/Window.py +++ b/src/View/Frictions/Window.py @@ -50,7 +50,7 @@ from View.Frictions.Table import ( ) from View.Tools.Plot.PamhyrCanvas import MplCanvas -from View.Geometry.PlotKPZ import PlotKPZ +from View.Frictions.PlotKPZ import PlotKPZ from View.Frictions.PlotStricklers import PlotStricklers from View.Frictions.translate import FrictionsTranslate @@ -135,10 +135,11 @@ class FrictionsWindow(PamhyrWindow): self.plot = PlotKPZ( canvas=self.canvas, - data=self._reach.reach, - study=self._study, + reach=self._reach, + river=self._study.river, trad=self._trad, toolbar=None, + parent=self ) self.plot.draw() diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index e163e538..2793e78b 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -179,7 +179,6 @@ class PlotXY(PamhyrPlot): self._init = True def draw_xy(self): - self.line_xy = [] for xy in zip(self.data.get_x(), self.data.get_y()): self.line_xy.append(np.column_stack(xy)) diff --git a/src/View/HydraulicStructures/PlotKPC.py b/src/View/HydraulicStructures/PlotKPC.py index 209e68a1..2844ab8f 100644 --- a/src/View/HydraulicStructures/PlotKPC.py +++ b/src/View/HydraulicStructures/PlotKPC.py @@ -186,11 +186,9 @@ class PlotKPC(PamhyrPlot): closest = self._closest_profile(event) index = self.parent.tableView.selectedIndexes() - print(index) if self.parent._table is not None: self.parent._table.setData(index[2], closest) - return def _closest_profile(self, event): diff --git a/src/View/LateralContribution/PlotXY.py b/src/View/LateralContribution/PlotXY.py new file mode 100644 index 00000000..91e279ec --- /dev/null +++ b/src/View/LateralContribution/PlotXY.py @@ -0,0 +1,259 @@ +# PlotXY.py -- Pamhyr +# Copyright (C) 2023-2024 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- + +from tools import timer, trace +from View.Tools.PamhyrPlot import PamhyrPlot +from matplotlib import collections +import numpy as np + +from PyQt5.QtCore import ( + QCoreApplication, Qt, QItemSelectionModel, + QItemSelection, QItemSelectionRange, +) +from PyQt5.QtWidgets import QApplication, QTableView + +_translate = QCoreApplication.translate + + +class PlotXY(PamhyrPlot): + def __init__(self, canvas=None, trad=None, data=None, toolbar=None, + table=None, parent=None): + super(PlotXY, self).__init__( + canvas=canvas, + trad=trad, + data=data, + toolbar=toolbar, + table=table, + parent=parent + ) + + self.line_xy = [] + self.line_gl = [] + + self.label_x = self._trad["x"] + self.label_y = self._trad["y"] + + self.before_plot_selected = None + self.plot_selected = None + self.after_plot_selected = None + self.parent=parent + self.line_xy_collection = None + self._table=table + self._colors = [] + self._style = [] + + def onpick(self, event): + if event.mouseevent.inaxes != self.canvas.axes: + return + if event.mouseevent.button.value not in [1,3]: + return + + closest = self._closest_section(event) + t = self.parent.current_tab() + tableView = self.parent.find(QTableView, f"tableView_{t}") + table = self.parent._table[t] + index = tableView.selectedIndexes() + kp = self.data.get_kp() + if self.parent._table is not None: + if event.mouseevent.button.value == 1: + table.setData(index[3], kp[closest[0]]) + if event.mouseevent.button.value == 3: + table.setData(index[4], kp[closest[0]]) + + #self.update() + return + + def _closest_section(self, event): + axes = self.canvas.axes + mx = event.mouseevent.xdata + my = event.mouseevent.ydata + bx, by = axes.get_xlim(), axes.get_ylim() + ratio = (bx[0] - bx[1]) / (by[0] - by[1]) + + segments = event.artist.get_segments() + ind = event.ind + + points = [] + for i in ind: + points = points + [[i, j] for j in segments[i]] + + def dist_mouse(point): + x, y = point[1] + d2 = (((mx - x) / ratio) ** 2) + ((my - y) ** 2) + return d2 + + closest = min( + points, key=dist_mouse + ) + + return closest + + @timer + def draw(self): + self.init_axes() + + if self.data is None: + self.idle() + return + + if self.data.number_profiles == 0: + self._init = False + self.idle() + return + + self.draw_xy() + self.draw_lr() + self.draw_gl() + + self.idle() + self._init = True + + def draw_xy(self): + self.line_xy = [] + for xy in zip(self.data.get_x(), self.data.get_y()): + self.line_xy.append(np.column_stack(xy)) + + self._colors, self._style = self.color_hightlight() + self.line_xy_collection = collections.LineCollection(self.line_xy, + colors = self._colors, + linestyle = self._style, + picker=10) + self.canvas.axes.add_collection(self.line_xy_collection) + + def color_hightlight(self): + kp_min, kp_max = (-1, -1) + if self._highlight_data is not None: + kp_min, kp_max = self._highlight_data + + colors = [self.color_plot for row in range(len(self._data))] + for i, kp in enumerate(self.data.get_kp_complete_profiles()): + if kp_min <= kp <= kp_max: + colors[i] = self.color_plot_current + style = ["-" for row in range(len(self._data))] + + return colors, style + + def draw_lr(self): + lx = [] + ly = [] + rx = [] + ry = [] + + self.line_lr = [] + for x, y in zip(self.data.get_x(), + self.data.get_y()): + lx.append(x[0]) + ly.append(y[0]) + + rx.append(x[-1]) + ry.append(y[-1]) + + line = self.canvas.axes.plot( + lx, ly, + color=self.color_plot_river_bottom, + linestyle="dotted", + lw=1., + ) + self.line_lr.append(line) + + line = self.canvas.axes.plot( + rx, ry, + color=self.color_plot_river_bottom, + linestyle="dotted", + lw=1., + ) + self.line_lr.append(line) + + def draw_gl(self): + x_complete = self.data.get_guidelines_x() + y_complete = self.data.get_guidelines_y() + + ind = 0 + self.line_gl = [] + for x, y in zip(x_complete, y_complete): + line = self.canvas.axes.plot( + x, y, color=self.colors[ind % len(self.colors)], + linestyle=self.linestyle[ind // len(self.colors)] + ) + self.line_gl.append(line) + ind += 1 + + @timer + def update(self): + if not self._init: + self.draw() + return + + if self.data is None: + return + + self.update_lr() + self.update_gl() + self.update_current() + + self.update_idle() + + def update_gl(self): + self.data.compute_guidelines() + x_complete = list(self.data.get_guidelines_x()) + y_complete = list(self.data.get_guidelines_y()) + + # TODO comprendre à quoi sert ce bout de code + # ========> + #for i in range(self.data.number_profiles): + #if i < len(self.line_xy): + #self.line_xy[i][0].set_data( + #self.data.profile(i).x(), + #self.data.profile(i).y() + #) + #else: + #self.line_xy.append( + #self.canvas.axes.plot( + #self.data.profile(i).x(), + #self.data.profile(i).y(), + #color='r', + #**self.plot_default_kargs + #) + #) + # <======== + + for i in range(len(x_complete)): + if i < len(self.line_gl): + self.line_gl[i][0].set_data( + x_complete[i], + y_complete[i] + ) + else: + self.line_gl.append( + self.canvas.axes.plot( + x_complete[i], + y_complete[i] + ) + ) + + def update_current(self): + if self._current_data_update: + self._colors, self._style = self.color_hightlight() + self.line_xy_collection.set_colors(self._colors) + self.line_xy_collection.set_linestyle(self._style) + + def update_lr(self): + for line in self.line_lr: + line[0].remove() + + self.draw_lr() diff --git a/src/View/LateralContribution/Window.py b/src/View/LateralContribution/Window.py index 879955bb..6a91c1cd 100644 --- a/src/View/LateralContribution/Window.py +++ b/src/View/LateralContribution/Window.py @@ -54,7 +54,7 @@ from View.LateralContribution.Table import ( ) from View.Tools.Plot.PamhyrCanvas import MplCanvas -from View.Geometry.PlotXY import PlotXY +from View.LateralContribution.PlotXY import PlotXY from View.LateralContribution.translate import ( LC_types, LCTranslate, ) @@ -83,6 +83,7 @@ class LateralContributionWindow(PamhyrWindow): self.setup_table() self.setup_graph() + self.tabs = self.find(QTabWidget, "tabWidget") self.setup_connections() def setup_table(self): @@ -148,6 +149,7 @@ class LateralContributionWindow(PamhyrWindow): data=None, trad=self._trad, toolbar=None, + parent=self ) def setup_connections(self): @@ -156,6 +158,8 @@ class LateralContributionWindow(PamhyrWindow): self.find(QAction, "action_edit").triggered.connect(self.edit) self.find(QAction, "action_sort").triggered.connect(self.sort) + self.tabs.currentChanged.connect(self._set_current_reach) + for t in ["liquid", "solid", "suspenssion"]: table = self.find(QTableView, f"tableView_{t}") table.selectionModel()\ @@ -216,6 +220,7 @@ class LateralContributionWindow(PamhyrWindow): data=data, trad=self._trad, toolbar=None, + parent=self ) self.plot.highlight = highlight self.plot.update() @@ -292,3 +297,9 @@ class LateralContributionWindow(PamhyrWindow): parent=self ) win.show() + + #@pyqtSlot() + def onChange(self,i): #changed! + QtGui.QMessageBox.information(self, + "Tab Index Changed!", + "Current Tab Index: %d" % i ) #changed! From 7d4091eb24a8c56ce8d724c19cb9ba6e0c4e2126 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Wed, 12 Jun 2024 11:40:52 +0200 Subject: [PATCH 37/45] pep8 --- src/View/Geometry/PlotKPZ.py | 134 ++++++++++++---------- src/View/Geometry/PlotXY.py | 146 ++++++++++++------------ src/View/Geometry/Profile/Plot.py | 47 +++++--- src/View/HydraulicStructures/PlotKPC.py | 6 +- src/View/LateralContribution/PlotXY.py | 55 ++++----- src/View/LateralContribution/Window.py | 6 - 6 files changed, 207 insertions(+), 187 deletions(-) diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index 36b9beba..fb72c5d5 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -21,7 +21,7 @@ import logging from tools import timer from View.Tools.PamhyrPlot import PamhyrPlot from PyQt5.QtWidgets import QApplication -from PyQt5.QtCore import( +from PyQt5.QtCore import ( Qt, QItemSelectionModel, QItemSelection, QItemSelectionRange, ) @@ -57,8 +57,8 @@ class PlotKPZ(PamhyrPlot): self.before_plot_selected = None self.plot_selected = None self.after_plot_selected = None - self.parent=parent - self._table=table + self.parent = parent + self._table = table self._colors = [] def onpick(self, event): @@ -68,47 +68,49 @@ class PlotKPZ(PamhyrPlot): return modifiers = QApplication.keyboardModifiers() - if modifiers not in [Qt.ControlModifier, Qt.NoModifier, Qt.ShiftModifier]: + if modifiers not in [Qt.ControlModifier, + Qt.NoModifier, + Qt.ShiftModifier]: return ind, point = self._closest_kp(event) - if self.parent._table is not None: - self.parent._table.blockSignals(True) - if modifiers == Qt.ControlModifier: - rows = list( - set( - (i.row() for i in self.parent.tableView.selectedIndexes()) - ) + if self.parent._table is None: + return + self.parent._table.blockSignals(True) + if modifiers == Qt.ControlModifier: + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) ) - if ind in rows: - rows.remove(ind) - self._select_in_table(rows) - else: - self._select_in_table(rows+[ind]) - elif modifiers == Qt.ShiftModifier: - rows = list( - set( - (i.row() for i in self.parent.tableView.selectedIndexes()) - ) - ) - if len(rows)>0: - i1 = min(rows[0], rows[-1], ind) - i2 = max(rows[0], rows[-1], ind) - else: - i1 = ind - i2 = ind - self._select_range_in_table(i1, i2) + ) + if ind in rows: + rows.remove(ind) + self._select_in_table(rows) else: - self.parent.select_row_profile_slider(ind) - self.parent._table.blockSignals(False) + self._select_in_table(rows+[ind]) + elif modifiers == Qt.ShiftModifier: + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) + ) + ) + if len(rows) > 0: + i1 = min(rows[0], rows[-1], ind) + i2 = max(rows[0], rows[-1], ind) + else: + i1 = ind + i2 = ind + self._select_range_in_table(i1, i2) + else: + self.parent.select_row_profile_slider(ind) + self.parent._table.blockSignals(False) - #self.update() return def _closest_kp(self, event): s = event.artist.get_segments() - x = [i[0,0] for i in s] + x = [i[0, 0] for i in s] mx = event.mouseevent.xdata points = enumerate(x) @@ -124,22 +126,28 @@ class PlotKPZ(PamhyrPlot): return closest def _select_in_table(self, ind): - if self._table is not None: - self._table.setFocus() - selection = self._table.selectionModel() - index = QItemSelection() - if len(ind) > 0: - for i in ind: - index.append(QItemSelectionRange(self._table.model().index(i, 0))) - selection.select( - index, - QItemSelectionModel.Rows | - QItemSelectionModel.ClearAndSelect | - QItemSelectionModel.Select - ) + if self._table is None: + return - if len(ind) > 0: - self._table.scrollTo(self._table.model().index(ind[-1], 0)) + self._table.setFocus() + selection = self._table.selectionModel() + index = QItemSelection() + + if len(ind) == 0: + return + + for i in ind: + index.append(QItemSelectionRange(self._table.model().index(i, 0))) + + selection.select( + index, + QItemSelectionModel.Rows | + QItemSelectionModel.ClearAndSelect | + QItemSelectionModel.Select + ) + + if len(ind) > 0: + self._table.scrollTo(self._table.model().index(ind[-1], 0)) def _select_range_in_table(self, ind1, ind2): if self._table is not None: @@ -195,7 +203,7 @@ class PlotKPZ(PamhyrPlot): self.line_kp_zmin_zmax = self.canvas.axes.vlines( x=kp, ymin=z_min, ymax=z_max, color=self._colors, - linestyle = self._style, + linestyle=self._style, lw=1., picker=10, ) @@ -208,7 +216,7 @@ class PlotKPZ(PamhyrPlot): )) colors = [self.color_plot for row in range(len(self._data))] style = ["-" for row in range(len(self._data))] - if len(rows) >0: + if len(rows) > 0: for row in rows: colors[row] = self.color_plot_current if rows[0] > 0: @@ -334,19 +342,19 @@ class PlotKPZ(PamhyrPlot): self.line_kp_zmin.set_data(kp, z_min) - # TODO comprendre à quoi sert ce bout de code - # ========> - #self.line_kp_zmin_zmax.remove() - #self._colors, self._style = self.color_hightlight() - #self.line_kp_zmin_zmax = self.canvas.axes.vlines( - #x=kp, - #ymin=z_min, - #ymax=z_max, - #color=self._colors, - #linestyle = self._style, - #lw=1. - #) - # <======== +# TODO comprendre à quoi sert ce bout de code +# ========> +# self.line_kp_zmin_zmax.remove() +# self._colors, self._style = self.color_hightlight() +# self.line_kp_zmin_zmax = self.canvas.axes.vlines( +# x=kp, +# ymin=z_min, +# ymax=z_max, +# color=self._colors, +# linestyle = self._style, +# lw=1. +# ) +# <======== z_complete = self.data.get_guidelines_z() try: diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index 2793e78b..c4a7cde4 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -51,9 +51,9 @@ class PlotXY(PamhyrPlot): self.before_plot_selected = None self.plot_selected = None self.after_plot_selected = None - self.parent=parent + self.parent = parent self.line_xy_collection = None - self._table=table + self._table = table self._colors = [] self._style = [] @@ -64,41 +64,43 @@ class PlotXY(PamhyrPlot): return modifiers = QApplication.keyboardModifiers() - if modifiers not in [Qt.ControlModifier, Qt.NoModifier, Qt.ShiftModifier]: + if modifiers not in [Qt.ControlModifier, + Qt.NoModifier, + Qt.ShiftModifier]: return ind, point = self._closest_section(event) - if self._table is not None: - self._table.blockSignals(True) - if modifiers == Qt.ControlModifier: - rows = list( - set( - (i.row() for i in self.parent.tableView.selectedIndexes()) - ) + if self._table is None: + return + self._table.blockSignals(True) + if modifiers == Qt.ControlModifier: + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) ) - if ind in rows: - rows.remove(ind) - self._select_in_table(rows) - else: - self._select_in_table(rows+[ind]) - elif modifiers == Qt.ShiftModifier: - rows = list( - set( - (i.row() for i in self.parent.tableView.selectedIndexes()) - ) - ) - if len(rows)>0: - i1 = min(rows[0], rows[-1], ind) - i2 = max(rows[0], rows[-1], ind) - else: - i1 = ind - i2 = ind - self._select_range_in_table(i1, i2) + ) + if ind in rows: + rows.remove(ind) + self._select_in_table(rows) else: - self.parent.select_row_profile_slider(ind) - self._table.blockSignals(False) + self._select_in_table(rows + [ind]) + elif modifiers == Qt.ShiftModifier: + rows = list( + set( + (i.row() for i in self.parent.tableView.selectedIndexes()) + ) + ) + if len(rows) > 0: + i1 = min(rows[0], rows[-1], ind) + i2 = max(rows[0], rows[-1], ind) + else: + i1 = ind + i2 = ind + self._select_range_in_table(i1, i2) + else: + self.parent.select_row_profile_slider(ind) + self._table.blockSignals(False) - #self.update() return def _closest_section(self, event): @@ -113,7 +115,7 @@ class PlotXY(PamhyrPlot): points = [] for i in ind: - points = points + [[i, j] for j in segments[i]] + points = points + [[i, j] for j in segments[i]] def dist_mouse(point): x, y = point[1] @@ -127,22 +129,24 @@ class PlotXY(PamhyrPlot): return closest def _select_in_table(self, ind): - if self._table is not None: - self._table.setFocus() - selection = self._table.selectionModel() - index = QItemSelection() - if len(ind) > 0: - for i in ind: - index.append(QItemSelectionRange(self._table.model().index(i, 0))) - selection.select( - index, - QItemSelectionModel.Rows | - QItemSelectionModel.ClearAndSelect | - QItemSelectionModel.Select - ) + if self._table is None: + return + self._table.setFocus() + selection = self._table.selectionModel() + index = QItemSelection() + if len(ind) == 0: + return + for i in ind: + index.append(QItemSelectionRange(self._table.model().index(i, 0))) + selection.select( + index, + QItemSelectionModel.Rows | + QItemSelectionModel.ClearAndSelect | + QItemSelectionModel.Select + ) - if len(ind) > 0: - self._table.scrollTo(self._table.model().index(ind[-1], 0)) + if len(ind) > 0: + self._table.scrollTo(self._table.model().index(ind[-1], 0)) def _select_range_in_table(self, ind1, ind2): if self._table is not None: @@ -184,10 +188,12 @@ class PlotXY(PamhyrPlot): self.line_xy.append(np.column_stack(xy)) self._colors, self._style = self.color_hightlight() - self.line_xy_collection = collections.LineCollection(self.line_xy, - colors = self._colors, - linestyle = self._style, - picker=10) + self.line_xy_collection = collections.LineCollection( + self.line_xy, + colors=self._colors, + linestyle=self._style, + picker=10 + ) self.canvas.axes.add_collection(self.line_xy_collection) def color_hightlight(self): @@ -198,7 +204,7 @@ class PlotXY(PamhyrPlot): )) colors = [self.color_plot for row in range(len(self._data))] style = ["-" for row in range(len(self._data))] - if len(rows) >0: + if len(rows) > 0: for row in rows: colors[row] = self.color_plot_current if rows[0] > 0: @@ -274,24 +280,24 @@ class PlotXY(PamhyrPlot): x_complete = list(self.data.get_guidelines_x()) y_complete = list(self.data.get_guidelines_y()) - # TODO comprendre à quoi sert ce bout de code - # ========> - #for i in range(self.data.number_profiles): - #if i < len(self.line_xy): - #self.line_xy[i][0].set_data( - #self.data.profile(i).x(), - #self.data.profile(i).y() - #) - #else: - #self.line_xy.append( - #self.canvas.axes.plot( - #self.data.profile(i).x(), - #self.data.profile(i).y(), - #color='r', - #**self.plot_default_kargs - #) - #) - # <======== +# TODO comprendre à quoi sert ce bout de code +# ========> +# for i in range(self.data.number_profiles): +# if i < len(self.line_xy): +# self.line_xy[i][0].set_data( +# self.data.profile(i).x(), +# self.data.profile(i).y() +# ) +# else: +# self.line_xy.append( +# self.canvas.axes.plot( +# self.data.profile(i).x(), +# self.data.profile(i).y(), +# color='r', +# **self.plot_default_kargs +# ) +# ) +# <======== for i in range(len(x_complete)): if i < len(self.line_gl): diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index 8ebe0aaa..ee91ca17 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -72,17 +72,20 @@ class Plot(PamhyrPlot): # wet_preimeter, water_width) ) self._onpickevent = None - self._rect_select = RectangleSelector(ax=self.canvas.axes, - onselect=self.rect_select_callback, - useblit=True, - button=[1], # don't use middle nor right button - minspanx=2.0, - minspany=2.0, - spancoords='pixels', - interactive=False) + self._rect_select = RectangleSelector( + ax=self.canvas.axes, + onselect=self.rect_select_callback, + useblit=True, + button=[1], # don't use middle nor right button + minspanx=2.0, + minspany=2.0, + spancoords='pixels', + interactive=False + ) def onrelease(self, event): - # we need to do that to prevent conflicst between onpick and rect_select_callback + # we need to do that to prevent conflicst + # between onpick and rect_select_callback modifiers = QApplication.keyboardModifiers() points, hyd = self.highlight if self._onpickevent is not None: @@ -91,7 +94,7 @@ class Plot(PamhyrPlot): rows = self._parent.index_selected_rows() if ind in rows: rows.remove(ind) - del(points[ind]) + del (points[ind]) self.highlight = (points, hyd) self._select_in_table(rows) else: @@ -99,10 +102,13 @@ class Plot(PamhyrPlot): self._select_in_table(rows+[ind]) elif modifiers == Qt.ShiftModifier: rows = self._parent.index_selected_rows() - if len(rows)>0: + if len(rows) > 0: i1 = min(rows[0], rows[-1], ind) i2 = max(rows[0], rows[-1], ind) - p = [[self.data.points[i].x,self.data.points[i].y] for i in range(i1, i2)] + p = [ + [self.data.points[i].x, self.data.points[i].y] + for i in range(i1, i2) + ] else: i1 = ind i2 = ind @@ -122,7 +128,9 @@ class Plot(PamhyrPlot): return modifiers = QApplication.keyboardModifiers() - if modifiers not in [Qt.ControlModifier, Qt.NoModifier, Qt.ShiftModifier]: + if modifiers not in [Qt.ControlModifier, + Qt.NoModifier, + Qt.ShiftModifier]: return self._onpickevent = event @@ -178,7 +186,9 @@ class Plot(PamhyrPlot): index = QItemSelection() if len(ind) > 0: for i in ind: - index.append(QItemSelectionRange(self._table.model().index(i, 0))) + index.append(QItemSelectionRange( + self._table.model().index(i, 0)) + ) selection.select( index, QItemSelectionModel.Rows | @@ -244,11 +254,10 @@ class Plot(PamhyrPlot): x1, y1 = eclick.xdata, eclick.ydata x2, y2 = erelease.xdata, erelease.ydata - if(max(abs(x1-x2), abs(y1-y2))<0.001): + if (max(abs(x1-x2), abs(y1-y2)) < 0.001): return modifiers = QApplication.keyboardModifiers() - x1, y1 = eclick.xdata, eclick.ydata x2, y2 = erelease.xdata, erelease.ydata @@ -259,7 +268,7 @@ class Plot(PamhyrPlot): if all(i in rows for i in inds): for ind in sorted(inds, reverse=True): rows.remove(ind) - del(points[ind]) + del (points[ind]) self.highlight = (points, hyd) self._select_in_table(rows) else: @@ -276,12 +285,12 @@ class Plot(PamhyrPlot): listp = [] station = self.data._get_station(self.data.points) for i, p in enumerate(self.data.points): - if (min(x1,x2) - #for i in range(self.data.number_profiles): - #if i < len(self.line_xy): - #self.line_xy[i][0].set_data( - #self.data.profile(i).x(), - #self.data.profile(i).y() - #) - #else: - #self.line_xy.append( - #self.canvas.axes.plot( - #self.data.profile(i).x(), - #self.data.profile(i).y(), - #color='r', - #**self.plot_default_kargs - #) - #) - # <======== +# TODO comprendre à quoi sert ce bout de code +# ========> +# for i in range(self.data.number_profiles): +# if i < len(self.line_xy): +# self.line_xy[i][0].set_data( +# self.data.profile(i).x(), +# self.data.profile(i).y() +# ) +# else: +# self.line_xy.append( +# self.canvas.axes.plot( +# self.data.profile(i).x(), +# self.data.profile(i).y(), +# color='r', +# **self.plot_default_kargs +# ) +# ) +# <======== for i in range(len(x_complete)): if i < len(self.line_gl): diff --git a/src/View/LateralContribution/Window.py b/src/View/LateralContribution/Window.py index 6a91c1cd..fab8e289 100644 --- a/src/View/LateralContribution/Window.py +++ b/src/View/LateralContribution/Window.py @@ -297,9 +297,3 @@ class LateralContributionWindow(PamhyrWindow): parent=self ) win.show() - - #@pyqtSlot() - def onChange(self,i): #changed! - QtGui.QMessageBox.information(self, - "Tab Index Changed!", - "Current Tab Index: %d" % i ) #changed! From 88dd9cf15a6c7e7b9b375aabb62784d4f6b52206 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Thu, 13 Jun 2024 11:12:35 +0200 Subject: [PATCH 38/45] remove slider in geometry window --- src/View/Geometry/PlotKPZ.py | 10 +++---- src/View/Geometry/PlotXY.py | 2 +- src/View/Geometry/Window.py | 58 +++--------------------------------- src/View/ui/GeometryReach.ui | 43 -------------------------- 4 files changed, 10 insertions(+), 103 deletions(-) diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index fb72c5d5..eed3542b 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -85,15 +85,15 @@ class PlotKPZ(PamhyrPlot): ) if ind in rows: rows.remove(ind) - self._select_in_table(rows) else: - self._select_in_table(rows+[ind]) + rows.append(ind) + self._select_in_table(rows) elif modifiers == Qt.ShiftModifier: - rows = list( + rows = sorted(list( set( (i.row() for i in self.parent.tableView.selectedIndexes()) ) - ) + )) if len(rows) > 0: i1 = min(rows[0], rows[-1], ind) i2 = max(rows[0], rows[-1], ind) @@ -102,7 +102,7 @@ class PlotKPZ(PamhyrPlot): i2 = ind self._select_range_in_table(i1, i2) else: - self.parent.select_row_profile_slider(ind) + self._select_in_table([ind]) self.parent._table.blockSignals(False) return diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index c4a7cde4..548b7ee0 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -98,7 +98,7 @@ class PlotXY(PamhyrPlot): i2 = ind self._select_range_in_table(i1, i2) else: - self.parent.select_row_profile_slider(ind) + self._select_in_table([ind]) self._table.blockSignals(False) return diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 0f3891ca..dad1a29f 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -36,7 +36,7 @@ from PyQt5.QtCore import ( from PyQt5.QtWidgets import ( QApplication, QMainWindow, QFileDialog, QCheckBox, QUndoStack, QShortcut, QTableView, QHeaderView, - QAction, QSlider, QPushButton, QVBoxLayout, + QAction, QPushButton, QVBoxLayout, QLabel, QAbstractItemView, ) @@ -97,7 +97,7 @@ class GeometryWindow(PamhyrWindow): self.setup_plots() self.setup_statusbar() self.setup_connections() - self.changed_slider_value() + #self.changed_slider_value() def setup_table(self): table_headers = self._trad.get_dict("table_headers") @@ -201,13 +201,6 @@ class GeometryWindow(PamhyrWindow): self.find(QAction, action)\ .triggered.connect(actions[action]) - self.find(QSlider, "verticalSlider").valueChanged.connect( - self.changed_slider_value) - self.find(QPushButton, "pushButton_up").clicked.connect( - self.decrement_value_slider) - self.find(QPushButton, "pushButton_down").clicked.connect( - self.increment_value_slider) - # Profile selection when line change in table self.find(QTableView, "tableView").selectionModel()\ .selectionChanged\ @@ -228,7 +221,6 @@ class GeometryWindow(PamhyrWindow): self._plot_ac.draw() self.select_current_profile() - self.changed_slider_value() if propagate: self._propagate_update(key=Modules.GEOMETRY) @@ -439,26 +431,11 @@ class GeometryWindow(PamhyrWindow): self._plot_ac.update() self.tableView.model().blockSignals(False) - def select_row_profile_slider(self, ind: int = 0): - if self.tableView is not None: - selectionModel = self.tableView.selectionModel() - index = self.tableView.model().index(ind, 0) - - selectionModel.select( - index, - QItemSelectionModel.Rows | - QItemSelectionModel.ClearAndSelect | - QItemSelectionModel.Select - ) - - self.tableView.scrollTo(index) - def select_current_profile(self): self.tableView.model().blockSignals(True) row = self.index_selected_row() if row is not None: - self.find(QSlider, "verticalSlider").setValue(row) self.select_plot_xy(row) self.select_plot_kpc(row) self.select_plot_ac(row) @@ -469,33 +446,6 @@ class GeometryWindow(PamhyrWindow): self.tableView.model().blockSignals(False) - def changed_slider_value(self): - self.tableView.model().blockSignals(True) - - if self._table.rowCount() != 0: - slider = self.find(QSlider, "verticalSlider") - slider.setMaximum(self._table.rowCount() - 1) - - slider_value = slider.value() - kp = self._reach.profile(slider_value).kp - - self.select_plot_xy(slider_value) - self.select_plot_kpc(slider_value) - self.select_row_profile_slider(slider_value) - self.update_statusbar() - - self.tableView.model().blockSignals(False) - - def increment_value_slider(self): - slider = self.find(QSlider, "verticalSlider") - if 0 <= slider.value() < self._table.rowCount() - 1: - slider.setValue(slider.value() + 1) - - def decrement_value_slider(self): - slider = self.find(QSlider, "verticalSlider") - if 0 < slider.value() < self._table.rowCount(): - slider.setValue(slider.value() - 1) - def add(self): if len(self.tableView.selectedIndexes()) == 0: self._table.add(self._table.rowCount()) @@ -528,13 +478,13 @@ class GeometryWindow(PamhyrWindow): def sort_ascending(self): self._table.sort_profiles(False) self.select_current_profile() - self.changed_slider_value() + #self.changed_slider_value() def sort_descending(self): self._table.sort_profiles(True) self.select_current_profile() - self.changed_slider_value() + #self.changed_slider_value() def move_up(self): row = self.index_selected_row() diff --git a/src/View/ui/GeometryReach.ui b/src/View/ui/GeometryReach.ui index a124c899..ceda4450 100644 --- a/src/View/ui/GeometryReach.ui +++ b/src/View/ui/GeometryReach.ui @@ -28,49 +28,6 @@ - - - - - - - - - - ressources/up.pngressources/up.png - - - - - - - - - Qt::Vertical - - - true - - - true - - - - - - - - - - - - - ressources/down.pngressources/down.png - - - - - From 7b8191e2f0068839396cd5e2e5cd4b6a4d504636 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Thu, 13 Jun 2024 18:20:46 +0200 Subject: [PATCH 39/45] interactive selection in results --- src/View/Results/PlotXY.py | 131 +++++++++++++++++++++++++++++++++---- src/View/Results/Window.py | 3 +- 2 files changed, 120 insertions(+), 14 deletions(-) diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index 22a7149f..bbb2e4f4 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -22,10 +22,14 @@ from functools import reduce from tools import timer, trace from View.Tools.PamhyrPlot import PamhyrPlot +import numpy as np +from matplotlib import collections from PyQt5.QtCore import ( - QCoreApplication + QCoreApplication, Qt, QItemSelectionModel, + QItemSelection, QItemSelectionRange ) +from PyQt5.QtWidgets import QApplication, QTableView _translate = QCoreApplication.translate @@ -57,6 +61,74 @@ class PlotXY(PamhyrPlot): self.label_y = _translate("Results", "Y (m)") self._isometric_axis = True + self._tablemodel = parent._table["profile"] + self._table = parent.find(QTableView, f"tableView_profile") + + def onpick(self, event): + print(event.mouseevent.button.value) + if event.mouseevent.inaxes != self.canvas.axes: + return + if event.mouseevent.button.value != 1: + return + + modifiers = QApplication.keyboardModifiers() + if modifiers not in [Qt.ControlModifier, + Qt.NoModifier, + Qt.ShiftModifier]: + return + + ind, point = self._closest_section(event) + if self._table is None: + return + self._select_in_table([ind]) + self._table.blockSignals(False) + + return + + def _closest_section(self, event): + axes = self.canvas.axes + mx = event.mouseevent.xdata + my = event.mouseevent.ydata + bx, by = axes.get_xlim(), axes.get_ylim() + ratio = (bx[0] - bx[1]) / (by[0] - by[1]) + + segments = event.artist.get_segments() + ind = event.ind + + points = [] + for i in ind: + points = points + [[i, j] for j in segments[i]] + + def dist_mouse(point): + x, y = point[1] + d2 = (((mx - x) / ratio) ** 2) + ((my - y) ** 2) + return d2 + + closest = min( + points, key=dist_mouse + ) + + return closest + + def _select_in_table(self, ind): + if self._table is None: + return + self._table.setFocus() + selection = self._table.selectionModel() + index = QItemSelection() + if len(ind) == 0: + return + for i in ind: + index.append(QItemSelectionRange(self._table.model().index(i, 0))) + selection.select( + index, + QItemSelectionModel.Rows | + QItemSelectionModel.ClearAndSelect | + QItemSelectionModel.Select + ) + + if len(ind) > 0: + self._table.scrollTo(self._table.model().index(ind[-1], 0)) @property def results(self): @@ -90,18 +162,51 @@ class PlotXY(PamhyrPlot): self._init = False return - self.line_xy = [ - self.canvas.axes.plot( - x, y, - color=self.color_plot_river_bottom, - **self.plot_default_kargs - ) - for x, y, kp in zip( - reach.geometry.get_x(), - reach.geometry.get_y(), - reach.geometry.get_kp() - ) - ] + #self.line_xy = [ + #self.canvas.axes.plot( + #x, y, + #color=self.color_plot_river_bottom, + #**self.plot_default_kargs + #) + #for x, y, kp in zip( + #reach.geometry.get_x(), + #reach.geometry.get_y(), + #reach.geometry.get_kp() + #) + #] + self.line_xy = [] + for xy in zip(reach.geometry.get_x(), reach.geometry.get_y()): + self.line_xy.append(np.column_stack(xy)) + + self._colors, self._style = self.color_hightlight() + self.line_xy_collection = collections.LineCollection( + self.line_xy, + colors=self._colors, + linestyle=self._style, + picker=10 + ) + self.canvas.axes.add_collection(self.line_xy_collection) + + def color_hightlight(self): + reach = self.results.river.reach(self._current_reach_id) + #rows = sorted(list( + #set( + #(i.row() for i in self._current_profile_id) + #) + #)) + rows=[self._current_profile_id] + colors = [self.color_plot for row in range(reach.geometry.number_profiles)] + style = ["-" for row in range(reach.geometry.number_profiles)] + if len(rows) > 0: + for row in rows: + colors[row] = self.color_plot_current + if rows[0] > 0: + colors[rows[0]-1] = self.color_plot_previous + style[rows[0]-1] = "--" + if rows[-1] < reach.geometry.number_profiles-1: + colors[rows[-1]+1] = self.color_plot_next + style[rows[-1]+1] = "--" + return colors, style def draw_guide_lines(self, reach): x_complete = reach.geometry.get_guidelines_x() diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index 155b971e..d946c088 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -176,7 +176,8 @@ class ResultsWindow(PamhyrWindow): profile_id=0, trad=self._trad, toolbar=self.toolbar, - display_current=True + display_current=True, + parent=self ) self.plot_xy.draw() From 82093bcf95bdb2b339f01b8551863909ad75e619 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Thu, 13 Jun 2024 18:21:09 +0200 Subject: [PATCH 40/45] remove slider in geometry --- src/View/Geometry/Window.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index dad1a29f..bbc4ba12 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -97,7 +97,6 @@ class GeometryWindow(PamhyrWindow): self.setup_plots() self.setup_statusbar() self.setup_connections() - #self.changed_slider_value() def setup_table(self): table_headers = self._trad.get_dict("table_headers") @@ -470,7 +469,7 @@ class GeometryWindow(PamhyrWindow): .selectionModel()\ .selectedRows() - if len(r) > 0: + if len(r) == 1: return r[0].row() else: return None @@ -478,13 +477,11 @@ class GeometryWindow(PamhyrWindow): def sort_ascending(self): self._table.sort_profiles(False) self.select_current_profile() - #self.changed_slider_value() def sort_descending(self): self._table.sort_profiles(True) self.select_current_profile() - #self.changed_slider_value() def move_up(self): row = self.index_selected_row() From 60336c25f1f0369e9db30f901deba558d2960124 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Thu, 13 Jun 2024 18:23:11 +0200 Subject: [PATCH 41/45] pep8 --- src/View/Results/PlotXY.py | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index bbb2e4f4..66d53916 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -162,20 +162,9 @@ class PlotXY(PamhyrPlot): self._init = False return - #self.line_xy = [ - #self.canvas.axes.plot( - #x, y, - #color=self.color_plot_river_bottom, - #**self.plot_default_kargs - #) - #for x, y, kp in zip( - #reach.geometry.get_x(), - #reach.geometry.get_y(), - #reach.geometry.get_kp() - #) - #] self.line_xy = [] - for xy in zip(reach.geometry.get_x(), reach.geometry.get_y()): + for xy in zip(reach.geometry.get_x(), + reach.geometry.get_y()): self.line_xy.append(np.column_stack(xy)) self._colors, self._style = self.color_hightlight() @@ -189,13 +178,9 @@ class PlotXY(PamhyrPlot): def color_hightlight(self): reach = self.results.river.reach(self._current_reach_id) - #rows = sorted(list( - #set( - #(i.row() for i in self._current_profile_id) - #) - #)) - rows=[self._current_profile_id] - colors = [self.color_plot for row in range(reach.geometry.number_profiles)] + rows = [self._current_profile_id] + colors = [self.color_plot + for row in range(reach.geometry.number_profiles)] style = ["-" for row in range(reach.geometry.number_profiles)] if len(rows) > 0: for row in rows: From 460450f524bf748d28043f0c6b138aaa07c349df Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 1 Jul 2024 14:04:18 +0200 Subject: [PATCH 42/45] Pamhyr: Fix save as method and minor change. --- src/Model/Study.py | 3 +++ src/View/MainWindow.py | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Model/Study.py b/src/Model/Study.py index 46a809bb..28384ca4 100644 --- a/src/Model/Study.py +++ b/src/Model/Study.py @@ -117,6 +117,9 @@ class Study(SQLModel): if ".backup" in self.filename: is_new = True + if not os.path.exists(self.filename): + is_new = True + self._init_db_file(self.filename, is_new=is_new) self.commit() diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index aef1031d..1eb655b4 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -579,9 +579,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Nothing """ if self._study.filename is None or self._study.filename == "": + options = QFileDialog.Options() + options |= QFileDialog.DontUseNativeDialog + file_name, _ = QFileDialog.getSaveFileName( self, "Save File", - "", "Pamhyr(*.pamhyr)" + "", "Pamhyr(*.pamhyr)", + options=options, ) if file_name.rsplit(".", 1)[-1] == "pamhyr": @@ -630,9 +634,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ + options = QFileDialog.Options() + options |= QFileDialog.DontUseNativeDialog + file_name, _ = QFileDialog.getSaveFileName( self, "Save File", - "", "Pamhyr(*.pamhyr)" + "", "Pamhyr(*.pamhyr)", + options=options, ) logger.debug(f"Save study as : {repr(file_name)}") From 4deed897ff7b94859843b9eac4295ae598d94cb3 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 1 Jul 2024 14:45:50 +0200 Subject: [PATCH 43/45] BC, LC: Edit: Auto sort values. --- src/View/BoundaryCondition/Edit/Table.py | 19 ++++++++++++++----- src/View/BoundaryCondition/Edit/Window.py | 1 + src/View/LateralContribution/Edit/Table.py | 19 ++++++++++++++----- src/View/LateralContribution/Edit/Window.py | 1 + 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py index 287a8fe4..18fce9e6 100644 --- a/src/View/BoundaryCondition/Edit/Table.py +++ b/src/View/BoundaryCondition/Edit/Table.py @@ -99,7 +99,7 @@ class TableModel(PamhyrTableModel): logger.info(e) logger.debug(traceback.format_exc()) - self.dataChanged.emit(index, index) + self.update() return True def add(self, row, parent=QModelIndex()): @@ -112,7 +112,7 @@ class TableModel(PamhyrTableModel): ) self.endInsertRows() - self.layoutChanged.emit() + self.update() def delete(self, rows, parent=QModelIndex()): self.beginRemoveRows(parent, rows[0], rows[-1]) @@ -135,7 +135,7 @@ class TableModel(PamhyrTableModel): ) self.layoutAboutToBeChanged.emit() - self.layoutChanged.emit() + self.update() def move_up(self, row, parent=QModelIndex()): if row <= 0: @@ -152,7 +152,7 @@ class TableModel(PamhyrTableModel): ) self.endMoveRows() - self.layoutChanged.emit() + self.update() def move_down(self, index, parent=QModelIndex()): if row > len(self._data): @@ -169,7 +169,7 @@ class TableModel(PamhyrTableModel): ) self.endMoveRows() - self.layoutChanged.emit() + self.update() def paste(self, row, header, data): if len(data) == 0: @@ -190,4 +190,13 @@ class TableModel(PamhyrTableModel): ) self.layoutAboutToBeChanged.emit() + self.update() + + def auto_sort(self): + self.layoutAboutToBeChanged.emit() + self._data.sort(key=lambda x: x[0]) + self.layoutAboutToBeChanged.emit() + + def update(self): + self.auto_sort() self.layoutChanged.emit() diff --git a/src/View/BoundaryCondition/Edit/Window.py b/src/View/BoundaryCondition/Edit/Window.py index faf41896..94557ddd 100644 --- a/src/View/BoundaryCondition/Edit/Window.py +++ b/src/View/BoundaryCondition/Edit/Window.py @@ -195,6 +195,7 @@ class EditBoundaryConditionWindow(PamhyrWindow): self.find(QAction, "action_sort").triggered.connect(self.sort) self._table.dataChanged.connect(self.update) + self._table.layoutChanged.connect(self.update) if self._is_solid: self._d50sigma.d50Changed.connect(self.d50_changed) diff --git a/src/View/LateralContribution/Edit/Table.py b/src/View/LateralContribution/Edit/Table.py index c0ab3b44..3e726cc5 100644 --- a/src/View/LateralContribution/Edit/Table.py +++ b/src/View/LateralContribution/Edit/Table.py @@ -99,7 +99,7 @@ class TableModel(PamhyrTableModel): logger.info(e) logger.debug(traceback.format_exc()) - self.dataChanged.emit(index, index) + self.update() return True def add(self, row, parent=QModelIndex()): @@ -112,7 +112,7 @@ class TableModel(PamhyrTableModel): ) self.endInsertRows() - self.layoutChanged.emit() + self.update() def delete(self, rows, parent=QModelIndex()): self.beginRemoveRows(parent, rows[0], rows[-1]) @@ -135,7 +135,7 @@ class TableModel(PamhyrTableModel): ) self.layoutAboutToBeChanged.emit() - self.layoutChanged.emit() + self.update() def move_up(self, row, parent=QModelIndex()): if row <= 0: @@ -152,7 +152,7 @@ class TableModel(PamhyrTableModel): ) self.endMoveRows() - self.layoutChanged.emit() + self.update() def move_down(self, index, parent=QModelIndex()): if row > len(self._data): @@ -169,7 +169,7 @@ class TableModel(PamhyrTableModel): ) self.endMoveRows() - self.layoutChanged.emit() + self.update() def paste(self, row, header, data): if len(data) == 0: @@ -190,4 +190,13 @@ class TableModel(PamhyrTableModel): ) self.layoutAboutToBeChanged.emit() + self.update() + + def auto_sort(self): + self.layoutAboutToBeChanged.emit() + self._data.sort(key=lambda x: x[0]) + self.layoutAboutToBeChanged.emit() + + def update(self): + self.auto_sort() self.layoutChanged.emit() diff --git a/src/View/LateralContribution/Edit/Window.py b/src/View/LateralContribution/Edit/Window.py index 53c774cb..1b5beec7 100644 --- a/src/View/LateralContribution/Edit/Window.py +++ b/src/View/LateralContribution/Edit/Window.py @@ -137,6 +137,7 @@ class EditLateralContributionWindow(PamhyrWindow): self.find(QAction, "action_sort").triggered.connect(self.sort) self._table.dataChanged.connect(self.update) + self._table.layoutChanged.connect(self.update) def update(self): self.plot.update() From c4554d38c1e568835f8fe5bedc48846b1cfe25c5 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 1 Jul 2024 15:52:45 +0200 Subject: [PATCH 44/45] BC, LC: Edit: Disable auto sort. --- src/Model/BoundaryCondition/BoundaryCondition.py | 3 +++ src/View/BoundaryCondition/Edit/Table.py | 2 +- src/View/LateralContribution/Edit/Table.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py index 918af8b3..eddc52b1 100644 --- a/src/Model/BoundaryCondition/BoundaryCondition.py +++ b/src/Model/BoundaryCondition/BoundaryCondition.py @@ -315,6 +315,9 @@ class BoundaryCondition(SQLSubModel): self._data.sort(reverse=_reverse, key=key) self._status.modified() + def index(self, bc): + self._data.index(bc) + def get_i(self, index): return self.data[index] diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py index 18fce9e6..d4a9f8a6 100644 --- a/src/View/BoundaryCondition/Edit/Table.py +++ b/src/View/BoundaryCondition/Edit/Table.py @@ -198,5 +198,5 @@ class TableModel(PamhyrTableModel): self.layoutAboutToBeChanged.emit() def update(self): - self.auto_sort() + # self.auto_sort() self.layoutChanged.emit() diff --git a/src/View/LateralContribution/Edit/Table.py b/src/View/LateralContribution/Edit/Table.py index 3e726cc5..accf7142 100644 --- a/src/View/LateralContribution/Edit/Table.py +++ b/src/View/LateralContribution/Edit/Table.py @@ -198,5 +198,5 @@ class TableModel(PamhyrTableModel): self.layoutAboutToBeChanged.emit() def update(self): - self.auto_sort() + # self.auto_sort() self.layoutChanged.emit() From 70dcb1a6ee139de2d8848bbe2ae1bc2e740d138e Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Tue, 2 Jul 2024 10:47:28 +0200 Subject: [PATCH 45/45] remove print --- src/View/Network/translate.py | 2 ++ src/View/Results/PlotXY.py | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/View/Network/translate.py b/src/View/Network/translate.py index 1b2b8c0c..d6024681 100644 --- a/src/View/Network/translate.py +++ b/src/View/Network/translate.py @@ -54,10 +54,12 @@ class NetworkTranslate(MainTranslate): self._sub_dict["table_headers_node"] = { "name": self._dict['name'], "type": self._dict['type'], + # "id": _translate("Network", "Index"), } self._sub_dict["table_headers_edge"] = { "name": self._dict['name'], "node1": _translate("Network", "Source node"), "node2": _translate("Network", "Destination node"), + # "id": _translate("Network", "Index"), } diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index 66d53916..1621e282 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -65,7 +65,6 @@ class PlotXY(PamhyrPlot): self._table = parent.find(QTableView, f"tableView_profile") def onpick(self, event): - print(event.mouseevent.button.value) if event.mouseevent.inaxes != self.canvas.axes: return if event.mouseevent.button.value != 1: