diff --git a/doc/users/Tuto1/data/Hogneau.var b/doc/users/Tuto1/data/Hogneau.var deleted file mode 100644 index 33b537e6..00000000 --- a/doc/users/Tuto1/data/Hogneau.var +++ /dev/null @@ -1 +0,0 @@ -$Clapet_001 clapet \ No newline at end of file diff --git a/doc/users/Tuto1/step3.pamhyr b/doc/users/Tuto1/step3.pamhyr index 00a39e3a..49eb6bee 100644 Binary files a/doc/users/Tuto1/step3.pamhyr and b/doc/users/Tuto1/step3.pamhyr differ diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py index 87cae1dc..62a906b7 100644 --- a/src/Solver/Mage.py +++ b/src/Solver/Mage.py @@ -599,29 +599,50 @@ class Mage(CommandLineSolver): if qlog is not None: qlog.put("Export VAR file") - with mage_file_open(os.path.join(repertory, f"{name}.VAR"), "w+") as f: - files.append(f"{name}.VAR") + nb_cv = 0 + for hs in hydraulic_structures: + if hs.input_reach is None: + continue - for hs in hydraulic_structures: - if hs.input_reach is None: - continue + if not hs.input_reach.is_enable(): + continue - if not hs.input_reach.is_enable(): - continue + if not hs.enabled: + continue - for bhs in hs.basic_structures: + for bhs in hs.basic_structures: + if bhs.enabled: logger.info(bhs._type) - if bhs._type != "CV": + if bhs._type == "CV": + nb_cv += 1 + + if nb_cv != 0: + with mage_file_open(os.path.join( + repertory, f"{name}.VAR"), "w+") as f: + files.append(f"{name}.VAR") + + for hs in hydraulic_structures: + if hs.input_reach is None: continue - name = bhs.name - if name == "": - name = f"HS_{bhs.id:>3}".replace(" ", "0") + if not hs.input_reach.is_enable(): + continue - f.write( - f"${name} clapet" - ) + if not hs.enabled: + continue + for bhs in hs.basic_structures: + logger.info(bhs._type) + if bhs._type != "CV": + continue + + name = bhs.name + if name == "": + name = f"HS_{bhs.id:>3}".replace(" ", "0") + + f.write( + f"${name} clapet" + ) return files def _export_DEV(self, study, repertory, qlog, name="0"): diff --git a/src/View/InitialConditions/Window.py b/src/View/InitialConditions/Window.py index add3f1a7..573dd4b6 100644 --- a/src/View/InitialConditions/Window.py +++ b/src/View/InitialConditions/Window.py @@ -365,40 +365,43 @@ class InitialConditionsWindow(PamhyrWindow): self._update() def generate_growing_constant_depth(self): - dlg = DepthDialog(self.depth_value, - self.depth_option, - trad=self._trad, - parent=self) - if dlg.exec(): - self.depth_value = dlg.value - self.depth_option = dlg.option - self._table.generate("growing", - self.depth_value, - self.depth_option) - self._update() - - def generate_discharge(self): - dlg = DischargeDialog(self.discharge_value, - self.discharge_option, + if self._reach.reach.number_profiles > 0: + dlg = DepthDialog(self.depth_value, + self.depth_option, trad=self._trad, parent=self) - if dlg.exec(): - self.discharge_value = dlg.value - self.discharge_option = dlg.option - self._table.generate("discharge", - self.discharge_value, - self.discharge_option) - self._update() + if dlg.exec(): + self.depth_value = dlg.value + self.depth_option = dlg.option + self._table.generate("growing", + self.depth_value, + self.depth_option) + self._update() + + def generate_discharge(self): + if self._reach.reach.number_profiles > 1: + dlg = DischargeDialog(self.discharge_value, + self.discharge_option, + trad=self._trad, + parent=self) + if dlg.exec(): + self.discharge_value = dlg.value + self.discharge_option = dlg.option + self._table.generate("discharge", + self.discharge_value, + self.discharge_option) + self._update() def generate_height(self): - dlg = HeightDialog(self.height_values, - self.height_option, - trad=self._trad, - parent=self) - if dlg.exec(): - self.height_values = dlg.values - self.height_option = dlg.option - self._table.generate("height", - self.height_values, - self.height_option) - self._update() + if self._reach.reach.number_profiles > 0: + dlg = HeightDialog(self.height_values, + self.height_option, + trad=self._trad, + parent=self) + if dlg.exec(): + self.height_values = dlg.values + self.height_option = dlg.option + self._table.generate("height", + self.height_values, + self.height_option) + self._update() diff --git a/src/View/MainWindowTabInfo.py b/src/View/MainWindowTabInfo.py index f655d799..2dd9881a 100644 --- a/src/View/MainWindowTabInfo.py +++ b/src/View/MainWindowTabInfo.py @@ -20,8 +20,13 @@ import logging from tools import timer, trace +from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar +from View.Tools.Plot.PamhyrCanvas import MplCanvas +from View.PlotXY import PlotXY from View.Tools.PamhyrWidget import PamhyrWidget +from PyQt5.QtWidgets import QVBoxLayout + logger = logging.getLogger() @@ -38,7 +43,9 @@ class WidgetInfo(PamhyrWidget): parent=parent ) + self.parent = parent self.set_initial_values() + self.setup_graph() @property def study(self): @@ -64,6 +71,25 @@ class WidgetInfo(PamhyrWidget): self.set_label_text("label_lc", "-") self.set_label_text("label_hs", "-") + def setup_graph(self): + self.canvas = MplCanvas(width=5, height=4, dpi=100) + self.canvas.setObjectName("canvas") + self.plot_layout_xy = self.find(QVBoxLayout, "verticalLayout") + self._toolbar_xy = PamhyrPlotToolbar( + self.canvas, self, + items=["home", "zoom", "save", "iso", "back/forward", "move"] + ) + self.plot_layout_xy.addWidget(self._toolbar_xy) + self.plot_layout_xy.addWidget(self.canvas) + + self.plot = PlotXY( + canvas=self.canvas, + data=None, + trad=self.parent._trad, + toolbar=self._toolbar_xy, + parent=self + ) + def update(self): if self._study is None: self.set_initial_values() @@ -75,6 +101,15 @@ class WidgetInfo(PamhyrWidget): self.set_network_values() self.set_geometry_values() + self.plot = PlotXY( + canvas=self.canvas, + data=self._study.river.enable_edges(), + trad=self.parent._trad, + toolbar=self._toolbar_xy, + parent=self + ) + self.plot.update() + def set_network_values(self): river = self._study.river diff --git a/src/View/PlotXY.py b/src/View/PlotXY.py new file mode 100644 index 00000000..07ae3fad --- /dev/null +++ b/src/View/PlotXY.py @@ -0,0 +1,119 @@ +# 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._data = data + self.label_x = self._trad["x"] + self.label_y = self._trad["y"] + self.parent = parent + + self._isometric_axis = True + + self._auto_relim_update = True + self._autoscale_update = True + + @timer + def draw(self): + self.init_axes() + + if self._data is None: + self.idle() + return + + if len(self._data) < 1: + self.idle() + return + + self.line_lr = [] + for data in self._data: + if data.reach.number_profiles != 0: + self.draw_xy(data.reach) + self.draw_lr(data.reach) + self.idle() + return + + def draw_xy(self, reach): + line_xy = [] + for xy in zip(reach.get_x(), reach.get_y()): + line_xy.append(np.column_stack(xy)) + + line_xy_collection = collections.LineCollection( + line_xy, + colors=self.color_plot_river_bottom + ) + self.canvas.axes.add_collection(line_xy_collection) + + def draw_lr(self, reach): + lx = [] + ly = [] + rx = [] + ry = [] + + for x, y in zip(reach.get_x(), + reach.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) + + @timer + def update(self): + self.draw() + self.update_idle() diff --git a/src/View/Reservoir/Edit/Plot.py b/src/View/Reservoir/Edit/Plot.py index ac1859a1..e7cc70ad 100644 --- a/src/View/Reservoir/Edit/Plot.py +++ b/src/View/Reservoir/Edit/Plot.py @@ -49,8 +49,8 @@ class Plot(PamhyrPlot): self._mode = mode self._table_headers = self._trad.get_dict("table_headers") - self.label_x = self._table_headers["z"] - self.label_y = self._table_headers["area"] + self.label_x = self._table_headers["area"] + self.label_y = self._table_headers["z"] self._isometric_axis = False @@ -71,8 +71,8 @@ class Plot(PamhyrPlot): self._init = True def draw_data(self): - x = list(map(lambda v: v[0], self.data.data)) - y = list(map(lambda v: v[1], self.data.data)) + x = list(map(lambda v: v[1], self.data.data)) + y = list(map(lambda v: v[0], self.data.data)) self._line, = self.canvas.axes.plot( x, y, color=self.color_plot, @@ -89,7 +89,7 @@ class Plot(PamhyrPlot): self.update_idle() def update_data(self): - x = list(map(lambda v: v[0], self.data.data)) - y = list(map(lambda v: v[1], self.data.data)) + x = list(map(lambda v: v[1], self.data.data)) + y = list(map(lambda v: v[0], self.data.data)) self._line.set_data(x, y) diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index 8ae76c04..290259f0 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -146,8 +146,9 @@ class PlotXY(PamhyrPlot): return reach = self.results.river.reach(self._current_reach_id) + reaches = self.results.river.reachs - self.draw_profiles(reach) + self.draw_profiles(reach, reaches) self.draw_water_elevation(reach) self.draw_water_elevation_max(reach) self.draw_guide_lines(reach) @@ -156,12 +157,12 @@ class PlotXY(PamhyrPlot): self.idle() self._init = True - def draw_profiles(self, reach): + def draw_profiles(self, reach, reaches): if reach.geometry.number_profiles == 0: self._init = False return - - self.line_xy = [] + # TODO uncomment to draw all the reaches + # self.draw_other_profiles(reaches) for xy in zip(reach.geometry.get_x(), reach.geometry.get_y()): self.line_xy.append(np.column_stack(xy)) @@ -176,6 +177,19 @@ class PlotXY(PamhyrPlot): ) self.canvas.axes.add_collection(self.line_xy_collection) + def draw_other_profiles(self, reaches): + + for reach in reaches: + for xy in zip(reach.geometry.get_x(), + reach.geometry.get_y()): + self.line_xy.append(np.column_stack(xy)) + + self.line_xy_collection = collections.LineCollection( + self.line_xy, + colors=self.color_plot_river_bottom, + ) + self.canvas.axes.add_collection(self.line_xy_collection) + def draw_guide_lines(self, reach): x_complete = reach.geometry.get_guidelines_x() y_complete = reach.geometry.get_guidelines_y() diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index eb4684cf..661d25d6 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -606,11 +606,17 @@ class ResultsWindow(PamhyrWindow): def export_to(self, filename, x, y): timestamps = sorted(self._results.get("timestamps")) + reach = self._results.river.reachs[self._get_current_reach()] + first_line = [f"Study: {self._results.study.name}", + f"Reach: {reach.name}"] if x == "rk": timestamp = self._get_current_timestamp() + first_line.append(f"Time: {timestamp}s") val_dict = self._export_rk(timestamp, y, filename) elif x == "time": profile = self._get_current_profile() + pname = profile.name if profile.name != "" else profile.rk + first_line.append(f"Profile: {pname}") val_dict = self._export_time(profile, y, filename) with open(filename, 'w', newline='') as csvfile: @@ -619,6 +625,7 @@ class ResultsWindow(PamhyrWindow): dict_x = self._trad.get_dict("values_x") dict_y = self._trad.get_dict("values_y") header = [dict_x[x]] + writer.writerow(first_line) for text in y: header.append(dict_y[text]) writer.writerow(header) diff --git a/src/View/Translate.py b/src/View/Translate.py index 948160e0..0532be2d 100644 --- a/src/View/Translate.py +++ b/src/View/Translate.py @@ -146,3 +146,5 @@ class MainTranslate(UnitTranslate): "MainWindow", "Do you want to save current study before closing it?" ) + self._dict["x"] = _translate("MainWindow", "X (m)") + self._dict["y"] = _translate("MainWindow", "Y (m)") diff --git a/src/lang/fr.ts b/src/lang/fr.ts index 6abba31a..f358e6d6 100644 --- a/src/lang/fr.ts +++ b/src/lang/fr.ts @@ -1,5 +1,6 @@ - + + About @@ -1167,7 +1168,7 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie. - Copyright © 2022-2024 INRAE + Copyright © 2022-2024 INRAE Copyright © 2022-2024 INRAE @@ -1175,11 +1176,6 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie.Version: @version @codename Version : @version @codename - - - Copyright © 2022-2024 INRAE - - Frictions @@ -1456,17 +1452,17 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie. MainWindow - + Open debug window Ouvrir la fenêtre de débogage - + Open SQLite debuging tool ('sqlitebrowser') Ouvrir l'outil de débogage SQLite ('sqlitebrowser') - + Enable this window Activer cette fenêtre @@ -2311,12 +2307,12 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie.Maillage - + Summary Résumé - + Checks Vérifications @@ -2536,7 +2532,7 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie.Données - + Please select a reach Veuillez sélectionner un bief @@ -2546,35 +2542,45 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie.L'édition de la géométrie nécessite un bief sélectionné dans le réseau fluvial pour pouvoir travailler dessus - + Last open study Dernière étude ouverte - + Do you want to open again the last open study? Voulez-vous rouvrir la dernière étude ? - + This edition window need a reach selected into the river network to work on it Cette fenêtre d'édition a besoin d'un bief sélectionné dans le réseau pour travailler dessus - + Close without saving study Fermer sans sauvegarder l'étude - + Do you want to save current study before closing it? Souhaitez-vous sauvegarder l'étude en cours avant de la fermer ? - + Warning Avertissement + + + X (m) + X (m) + + + + Y (m) + Y (m) + MainWindow_reach @@ -3255,17 +3261,17 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie.Vitesse (m/s) - + Wet Perimeter (m) Périmètre mouillé (m) - + Hydraulic Radius (m) Rayon hydraulique (m) - + Froude number Nombre de Froude @@ -3277,6 +3283,11 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie. Wet Area (m^2) + Aire mouillée (m²) + + + + Wet Area (m²) Aire mouillée (m²)