Merge branch 'master' into scenarios.

test_sound
Pierre-Antoine Rouby 2024-09-24 15:54:10 +02:00
commit 40d90424a3
44 changed files with 1445 additions and 562 deletions

View File

@ -381,8 +381,6 @@ class MeshingWithMageMailleurTT(AMeshingTool):
st_file = self.export_reach_to_st(reach, tmp)
m_file = st_file.rsplit(".ST", 1)[0] + ".M"
os.sync()
proc = QProcess()
proc.setWorkingDirectory(tmp)
@ -397,12 +395,13 @@ class MeshingWithMageMailleurTT(AMeshingTool):
logger.info(
f"! {self._exe_path()} " +
f"{st_file} {m_file} " +
f"update_rk " +
f"update_kp " +
f"{str(step)} " +
f"{limites[0]} {limites[1]} " +
f"{directrices[0]} {directrices[1]} " +
f"{orientation} {lm} {linear} " +
f"{origin} "
f"{origin} " +
f"{origin_value} "
)
proc.start(
self._exe_path(),

View File

@ -21,6 +21,7 @@ import logging
from copy import copy, deepcopy
from tools import trace, timer
from functools import reduce
from numpy import interp
from Model.Tools.PamhyrDB import SQLSubModel
from Model.Scenario import Scenario
@ -485,8 +486,23 @@ class InitialConditions(SQLSubModel):
def get_discharge(self):
return self._data_get("discharge")
def generate_growing_constante_height(self, height: float,
compute_discharge: bool):
def _sort_by_z_and_rk(self, profiles):
profiles.sort(
reverse=False,
key=lambda p: p.rk
)
first_z = profiles[0].z()
last_z = profiles[-1].z()
if first_z > last_z:
profiles.sort(
reverse=True,
key=lambda p: p.rk
)
def generate_growing_constant_depth(self, height: float,
compute_discharge: bool):
profiles = self._reach.reach.profiles.copy()
previous_elevation = -99999.99

View File

@ -41,9 +41,9 @@ class Edge(SQLSubModel):
elif name == "id":
ret = self.pamhyr_id
elif name == "node1":
ret = self.node1.name
ret = self.node1
elif name == "node2":
ret = self.node2.name
ret = self.node2
elif name == "enable":
ret = self._enable
@ -69,10 +69,7 @@ class Edge(SQLSubModel):
@property
def name(self):
name = self._name
if self._name == "":
name = f"{self.node1.name} -> {self.node2.name}"
return name
return self._name
def is_enable(self):
return self._enable

View File

@ -26,11 +26,7 @@ class Node(SQLSubModel):
**kwargs):
super(Node, self).__init__(id=id, **kwargs)
if name == "":
self._name = f"Node #{self.pamhyr_id}"
else:
self._name = name
self._name = name
self.pos = Point(x, y)
def __getitem__(self, key):

View File

@ -73,7 +73,7 @@ class PamhyrModelDict(SQLSubModel):
if key in self._dict:
v = self._dict[key]
if type(v) is types.GeneratorType:
if isinstance(v, types.GeneratorType):
return list(v)
return v

View File

@ -30,13 +30,13 @@ from Model.Results.River.River import River, Reach, Profile
logger = logging.getLogger()
class RubarBE(CommandLineSolver):
_type = "rubarbe"
class Rubar3(CommandLineSolver):
_type = "rubar3"
def __init__(self, name):
super(RubarBE, self).__init__(name)
super(Rubar3, self).__init__(name)
self._type = "rubarbe"
self._type = "rubar3"
self._cmd_input = ""
self._cmd_solver = "@path @input -o @output"
@ -44,9 +44,9 @@ class RubarBE(CommandLineSolver):
@classmethod
def default_parameters(cls):
lst = super(RubarBE, cls).default_parameters()
# lst = super(Rubar3, cls).default_parameters()
lst += [
lst = [
("rubarbe_cfl", "0.50000E+00"),
("rubarbe_condam", "1"),
("rubarbe_condav", "3"),
@ -60,10 +60,10 @@ class RubarBE(CommandLineSolver):
("rubarbe_tinit", "000:00:00:00"),
("rubarbe_tmax", "999:99:99:00"),
("rubarbe_tiopdt", "000:00:00:00"),
("rubarbe_dt", "3000.0"),
("rubarbe_dt", "5.0"),
("rubarbe_ts", "999:99:99:00"),
("rubarbe_dtsauv", "999:99:99:00"),
("rubarbe_psave", "999:99:99:00"),
("rubarbe_dtsauv", "00:00:00:05"),
("rubarbe_psave", "00:00:00:05"),
("rubarbe_fdeb1", "1"),
("rubarbe_fdeb2", "10"),
("rubarbe_fdeb3", "100"),
@ -119,21 +119,21 @@ class RubarBE(CommandLineSolver):
##########
def cmd_args(self, study):
lst = super(RubarBE, self).cmd_args(study)
lst = super(Rubar3, self).cmd_args(study)
return lst
def input_param(self):
name = self._study.name
return f"{name}.REP"
return f"{name}"
def output_param(self):
name = self._study.name
return f"{name}.BIN"
return f"{name}"
def log_file(self):
name = self._study.name
return f"{name}.TRA"
return f"{name}"
def export(self, study, repertory, qlog=None):
self._study = study
@ -143,8 +143,12 @@ class RubarBE(CommandLineSolver):
self._export_ts(study, repertory, qlog, name=name)
self._export_geomac_i(study, repertory, qlog, name=name)
self._export_mail(study, repertory, qlog, name=name)
self._export_tps(study, repertory, qlog, name=name)
self._export_condin(study, repertory, qlog, name=name)
self._export_stricklers(study, repertory, qlog, name=name)
self._export_hydro(study, repertory, qlog, name=name)
self._export_condav(study, repertory, qlog, name=name)
return True
def _export_donnee(self, study, repertory, qlog, name="0"):
if qlog is not None:
@ -168,6 +172,9 @@ class RubarBE(CommandLineSolver):
name = param.name
value = param.value
if "all_" in name:
continue
if value != "":
# Value format
if value.count(':') == 3:
@ -276,7 +283,9 @@ class RubarBE(CommandLineSolver):
if label[0] == "r":
label = label[1].upper()
else:
label = lable[0]
label = label[1].upper()
else:
label = " "
y = point.y
z = point.z
@ -361,13 +370,13 @@ class RubarBE(CommandLineSolver):
ind += 1
f.write("\n")
def _export_tps(self, study, repertory, qlog, name="0"):
def _export_condin(self, study, repertory, qlog, name="0"):
if qlog is not None:
qlog.put("Export TPS file")
qlog.put("Export CONDIN file")
with open(
os.path.join(
repertory, f"tps.{name}"
repertory, f"condin.{name}"
), "w+"
) as f:
for edge in study.river.enable_edges():
@ -376,7 +385,7 @@ class RubarBE(CommandLineSolver):
f.write(f"0.0\n")
ics = study.river.initial_conditions.get(edge)
data = self._export_tps_init_data(ics)
data = self._export_condin_init_data(ics)
profiles = reach.profiles
first = profiles[0]
@ -388,11 +397,11 @@ class RubarBE(CommandLineSolver):
)
return
f_h_s = self._export_tps_profile_height_speed(first, data)
l_h_s = self._export_tps_profile_height_speed(last, data)
f_h_s = self._export_condin_profile_height_speed(first, data)
l_h_s = self._export_condin_profile_height_speed(last, data)
# First mail
f.write(f"{1:>5} {f_h_s[0]} {f_h_s[1]}")
f.write(f"{1:>5} {f_h_s[0]} {f_h_s[1]}\n")
ind = 2
it = iter(profiles)
@ -404,7 +413,7 @@ class RubarBE(CommandLineSolver):
ind += 1
continue
cur_h, cur_s = self._export_tps_profile_height_speed(
cur_h, cur_s = self._export_condin_profile_height_speed(
profile, data
)
@ -418,9 +427,9 @@ class RubarBE(CommandLineSolver):
ind += 1
# Last mail
f.write(f"{ind:>5} {f_h_s[0]} {f_h_s[1]}")
f.write(f"{ind:>5} {f_h_s[0]} {f_h_s[1]}\n")
def _export_tps_init_data(self, ics):
def _export_condin_init_data(self, ics):
data = {}
for d in ics.data:
@ -431,11 +440,70 @@ class RubarBE(CommandLineSolver):
return data
def _export_tps_profile_height_speed(self, profile, data):
def _export_condin_profile_height_speed(self, profile, data):
z = data[profile.rk][0]
q = data[profile.rk][1]
height = z - profile.z_min()
# height = z - profile.z_min()
speed = profile.speed(q, z)
return height, speed
return z, speed
def _export_hydro(self, study, repertory, qlog, name="0"):
if qlog is not None:
qlog.put("Export HYDRO file")
with open(
os.path.join(
repertory, f"hydro.{name}"
), "w+"
) as f:
bcs = []
for edge in study.river.enable_edges():
for bound in study.river.boundary_condition.get_tab("liquid"):
# BC is an hydrogramme
if bound.bctype == "TD" or bound.bctype == "PC":
# BC is on input node of this reach
if bound.node == edge.node1:
bcs.append(bound)
for bc in bcs:
f.write(f"{len(bc)}\n")
for d0, d1 in bc.data:
f.write(f"{d0} {d1}\n")
def _export_condav(self, study, repertory, qlog, name="0"):
if qlog is not None:
qlog.put("Export CONDAV file")
with open(
os.path.join(
repertory, f"condav.{name}"
), "w+"
) as f:
bcs = []
for edge in study.river.enable_edges():
for bound in study.river.boundary_condition.get_tab("liquid"):
# BC is an hydrogramme
if bound.bctype == "ZD" or bound.bctype == "TZ":
# BC is on input node of this reach
if bound.node == edge.node2:
bcs.append(bound)
for bc in bcs:
f.write(f"{len(bc)}\n")
for d0, d1 in bc.data:
f.write(f"{d0} {d1}\n")
class RubarBE(Rubar3):
_type = "rubarbe"
def __init__(self, name):
super(RubarBE, self).__init__(name)
self._type = "rubarbe"
self._cmd_input = ""
self._cmd_solver = "@path @input -o @output"
self._cmd_output = ""

View File

@ -22,7 +22,7 @@ from Solver.GenericSolver import GenericSolver
from Solver.Mage import (
Mage7, Mage8, MageFake7,
)
from Solver.RubarBE import RubarBE
from Solver.RubarBE import Rubar3, RubarBE
_translate = QCoreApplication.translate
@ -32,6 +32,7 @@ solver_long_name = {
"mage8": "Mage v8",
# "mage_fake7": "Mage fake v7",
# "rubarbe": "RubarBE",
# "rubar3": "Rubar3",
}
solver_type_list = {
@ -40,4 +41,5 @@ solver_type_list = {
"mage8": Mage8,
# "mage_fake7": MageFake7,
# "rubarbe": RubarBE,
# "rubar3": Rubar3,
}

View File

@ -67,5 +67,5 @@ class AboutWindow(PamhyrDialog):
label = f"\n - {author}" + label
except StopIteration:
label = _translate("About", "Contributors: ") + label
label = "Copyright © 2022-2024 INRAE\n" + label
# label = "Copyright © 2022-2024 INRAE\n" + label
self.set_label_text("label_copyright", label)

View File

@ -133,6 +133,7 @@ class EditBoundaryConditionWindow(PamhyrWindow):
self.setup_plot()
self.setup_data()
self.setup_connections()
self.setup_dialog()
def setup_data(self):
self._is_solid = self._data.bctype == "SL"
@ -208,13 +209,17 @@ class EditBoundaryConditionWindow(PamhyrWindow):
.triggered.connect(self.generate_uniform)
self.find(QAction, "action_generate_critical")\
.triggered.connect(self.generate_critical)
self.find(QAction, "action_increasing")\
.triggered.connect(self.make_increasing)
if self._data.bctype != "ZD" or not self._data.has_node:
self.find(QAction, "action_generate_uniform").setVisible(False)
self.find(QAction, "action_generate_critical").setVisible(False)
self.find(QAction, "action_increasing").setVisible(False)
else:
self.find(QAction, "action_generate_uniform").setVisible(True)
self.find(QAction, "action_generate_critical").setVisible(True)
self.find(QAction, "action_increasing").setVisible(True)
self._table.dataChanged.connect(self.update)
self._table.layoutChanged.connect(self.update)
@ -226,6 +231,10 @@ class EditBoundaryConditionWindow(PamhyrWindow):
else:
self._d50sigma.setEnabled(False)
def setup_dialog(self):
reach = self._data.reach(self._study.river)[0]
self.slope_value = abs(reach.get_incline_median_mean())
def d50_changed(self, value):
self._undo_stack.push(
SetMetaDataCommand(
@ -340,15 +349,16 @@ class EditBoundaryConditionWindow(PamhyrWindow):
def generate_uniform(self):
if self._data.has_node:
node = self._data.node
if node is None:
return
reach = self._data.reach(self._study.river)[0]
profile = reach.profiles[-1]
incline = abs(reach.get_incline_median_mean())
dlg = GenerateDialog(incline,
dlg = GenerateDialog(self.slope_value,
reach,
trad=self._trad,
parent=self)
if dlg.exec():
incline = dlg.value
self.slope_value = dlg.value
frictions = reach._parent.frictions.frictions
z_min = profile.z_min()
z_max = profile.z_max()
@ -360,8 +370,10 @@ class EditBoundaryConditionWindow(PamhyrWindow):
strickler = 25.0
height = [(i)*(z_max-z_min)/50 for i in range(51)]
q = [((profile.wet_width(z_min + h) * 0.8) * strickler
* (h ** (5/3)) * (abs(incline) ** (0.5)))
* (h ** (5/3)) * (abs(self.slope_value) ** (0.5)))
for h in height]
for i in range(len(height)):
height[i] += z_min
self._table.replace_data(height, q)
return
@ -369,6 +381,8 @@ class EditBoundaryConditionWindow(PamhyrWindow):
def generate_critical(self):
if self._data.has_node:
node = self._data.node
if node is None:
return
reach = self._data.reach(self._study.river)[0]
profile = reach.profiles[-1]
z_min = profile.z_min()
@ -377,5 +391,25 @@ class EditBoundaryConditionWindow(PamhyrWindow):
q = [sqrt(9.81 * (profile.wet_area(z_min + h) ** 3)
/ profile.wet_width(z_min + h))
for h in height]
for i in range(len(height)):
height[i] += z_min
self._table.replace_data(height, q)
return
def make_increasing(self):
if self._data.has_node:
node = self._data.node
if node is None:
return
if len(self._table._data) < 2:
return
h = [self._data.get_i(0)[0]]
q = [self._data.get_i(0)[1]]
for i in range(len(self._table._data)):
if i == 0:
continue
row = self._data.get_i(i)
if row[1] > q[-1]:
h.append(row[0])
q.append(row[1])
self._table.replace_data(h, q)

View File

@ -74,17 +74,17 @@ class ConfigureSolverWindow(PamhyrDialog):
# File button
buttons = {
"pushButton_input": (lambda: self.file_dialog(
select_file=True,
select_file="ExistingFile",
callback=lambda f: self.set_line_edit_text(
"lineEdit_input", f[0])
)),
"pushButton_solver": (lambda: self.file_dialog(
select_file=True,
select_file="ExistingFile",
callback=lambda f: self.set_line_edit_text(
"lineEdit_solver", f[0])
)),
"pushButton_output": (lambda: self.file_dialog(
select_file=True,
select_file="ExistingFile",
callback=lambda f: self.set_line_edit_text(
"lineEdit_output", f[0])
)),

View File

@ -157,7 +157,7 @@ class ConfigureWindow(PamhyrDialog):
"pushButton_stricklers_sort": self.sort_stricklers,
# Others
# "pushButton_backup_path": lambda: self.file_dialog(
# select_file=False,
# select_file="Directory",
# callback=lambda f: self.set_line_edit_text(
# "lineEdit_backup_path", f[0]
# )

View File

@ -41,7 +41,7 @@ class PlotAC(PamhyrPlot):
self._autoscale_update = True
self.label_x = self._trad["transverse_abscissa"]
self.label_y = self._trad["unit_height"]
self.label_y = self._trad["unit_elevation"]
self.label_previous_plot_selected = self._trad["prev_cs"]
self.label_plot_selected = self._trad["cs"]

View File

@ -56,8 +56,8 @@ class Plot(PamhyrPlot):
self.line_xy = []
self.line_gl = []
self.label_x = self._trad["unit_rk"]
self.label_y = self._trad["unit_height"]
self.label_x = self._trad["transverse_abscissa"]
self.label_y = self._trad["unit_elevation"]
self.before_plot_selected = None
self.plot_selected = None

View File

@ -108,7 +108,7 @@ hydraulic structure values?"
self._sub_dict["long_types"] = {
"ND": self._dict["not_defined"],
"S1": _translate(
"BasicHydraulicStructures", "Discharge weir"
"BasicHydraulicStructures", "Rectangular weir"
),
"S2": _translate(
"BasicHydraulicStructures", "Trapezoidal weir"

View File

@ -0,0 +1,60 @@
# DialogDepth.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 <https://www.gnu.org/licenses/>.
# -*- 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 (
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
QDoubleSpinBox, QCheckBox,
)
class DepthDialog(PamhyrDialog):
_pamhyr_ui = "InitialConditions_Dialog_Generator_Depth"
_pamhyr_name = "Depth"
def __init__(self, value, option, trad=None, parent=None):
super(DepthDialog, self).__init__(
title=trad[self._pamhyr_name],
options=[],
trad=trad,
parent=parent
)
self.value = value
self.option = option
self.sb = self.find(QDoubleSpinBox, "doubleSpinBox")
self.sb.setValue(self.value)
self.cb = self.find(QCheckBox, "checkBox")
self.cb.setChecked(self.option)
def accept(self):
self.value = self.sb.value()
self.option = self.cb.isChecked()
super().accept()
def reject(self):
self.close()

View File

@ -36,7 +36,12 @@ class DischargeDialog(PamhyrDialog):
_pamhyr_ui = "InitialConditions_Dialog_Generator_Discharge"
_pamhyr_name = "Discharge"
def __init__(self, title="Discharge", trad=None, parent=None):
def __init__(self,
value,
option,
title="Discharge",
trad=None,
parent=None):
super(DischargeDialog, self).__init__(
title=trad[self._pamhyr_name],
options=[],
@ -44,12 +49,16 @@ class DischargeDialog(PamhyrDialog):
parent=parent
)
self.value = None
self.option = None
self.value = value
self.option = option
self.sb = self.find(QDoubleSpinBox, "doubleSpinBox")
self.sb.setValue(self.value)
self.cb = self.find(QCheckBox, "checkBox")
self.cb.setChecked(self.option)
def accept(self):
self.value = self.find(QDoubleSpinBox, "doubleSpinBox").value()
self.option = self.find(QCheckBox, "checkBox").isChecked()
self.value = self.sb.value()
self.option = self.cb.isChecked()
super().accept()
def reject(self):

View File

@ -28,7 +28,7 @@ from PyQt5.QtCore import (
from PyQt5.QtWidgets import (
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
QDoubleSpinBox, QCheckBox,
QDoubleSpinBox, QCheckBox, QLabel
)
@ -36,7 +36,7 @@ class HeightDialog(PamhyrDialog):
_pamhyr_ui = "InitialConditions_Dialog_Generator_Height"
_pamhyr_name = "Height"
def __init__(self, trad=None, parent=None):
def __init__(self, values, option, trad=None, parent=None):
super(HeightDialog, self).__init__(
title=trad[self._pamhyr_name],
options=[],
@ -44,12 +44,29 @@ class HeightDialog(PamhyrDialog):
parent=parent
)
self.value = None
self.option = None
self.values = values
self.option = option
self.sb1 = self.find(QDoubleSpinBox, "doubleSpinBox_1")
self.sb1.setValue(self.values[0])
self.sb2 = self.find(QDoubleSpinBox, "doubleSpinBox_2")
self.sb2.setValue(self.values[1])
self.sb3 = self.find(QDoubleSpinBox, "doubleSpinBox_3")
self.sb3.setValue(self.values[2])
self.cb = self.find(QCheckBox, "checkBox")
self.cb.setChecked(self.option)
self.enable_discharge()
self.cb.clicked.connect(self.enable_discharge)
def enable_discharge(self):
label = self.find(QLabel, "label_3")
self.sb3.setEnabled(self.cb.isChecked())
label.setEnabled(self.cb.isChecked())
def accept(self):
self.value = self.find(QDoubleSpinBox, "doubleSpinBox").value()
self.option = self.find(QCheckBox, "checkBox").isChecked()
self.values[0] = self.sb1.value()
self.values[1] = self.sb2.value()
self.values[2] = self.sb3.value()
self.option = self.cb.isChecked()
super().accept()
def reject(self):

View File

@ -195,8 +195,13 @@ class GenerateCommand(QUndoCommand):
def redo(self):
if self._generator == "growing":
self._ics.generate_growing_constante_height(self._param,
self._option)
self._ics.generate_growing_constant_depth(self._param,
self._option)
elif self._generator == "discharge":
self._ics.generate_discharge(self._param,
self._option)
elif self._generator == "height":
self._ics.generate_height(self._param[0],
self._param[1],
self._option,
self._param[2])

View File

@ -58,6 +58,7 @@ from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.InitialConditions.PlotDRK import PlotDRK
from View.InitialConditions.PlotDischarge import PlotDischarge
from View.InitialConditions.translate import ICTranslate
from View.InitialConditions.DialogDepth import DepthDialog
from View.InitialConditions.DialogHeight import HeightDialog
from View.InitialConditions.DialogDischarge import DischargeDialog
from View.WaitingDialog import WaitingDialog
@ -103,6 +104,7 @@ class InitialConditionsWindow(PamhyrWindow):
self.setup_table()
self.setup_plot()
self.setup_connections()
self.setub_dialogs()
self.ui.setWindowTitle(self._title)
@ -179,16 +181,27 @@ class InitialConditionsWindow(PamhyrWindow):
self.find(QAction, "action_import").triggered\
.connect(self.import_from_file)
self.find(QPushButton, "pushButton_generate_1").clicked.connect(
self.generate_growing_constante_height
)
self.find(QPushButton, "pushButton_generate_1").clicked.connect(
self.generate_growing_constant_depth
)
self.find(QPushButton, "pushButton_generate_2").clicked.connect(
self.generate_discharge
)
self.find(QPushButton, "pushButton_generate_3").clicked.connect(
self.generate_height
)
self._table.dataChanged.connect(self._update_plot)
def setub_dialogs(self):
self.height_values = [0.0, 0.0, 0.0]
self.height_option = True
self.discharge_value = 0.0
self.discharge_option = True
self.depth_value = 0.0
self.depth_option = True
def index_selected_row(self):
table = self.find(QTableView, f"tableView")
rows = table.selectionModel()\
@ -255,6 +268,7 @@ class InitialConditionsWindow(PamhyrWindow):
workdir = os.path.dirname(self._study.filename)
return self.file_dialog(
select_file="ExistingFile",
callback=lambda d: self._import_from_file(d[0]),
directory=workdir,
default_suffix=".BIN",
@ -352,18 +366,41 @@ class InitialConditionsWindow(PamhyrWindow):
self._table.redo()
self._update()
def generate_growing_constante_height(self):
dlg = HeightDialog(trad=self._trad, parent=self)
def generate_growing_constant_depth(self):
dlg = DepthDialog(self.depth_value,
self.depth_option,
trad=self._trad,
parent=self)
if dlg.exec():
value = dlg.value
compute_discharge = dlg.option
self._table.generate("growing", value, compute_discharge)
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(trad=self._trad, parent=self)
dlg = DischargeDialog(self.discharge_value,
self.discharge_option,
trad=self._trad,
parent=self)
if dlg.exec():
value = dlg.value
compute_height = dlg.option
self._table.generate("discharge", value, compute_height)
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()

View File

@ -28,11 +28,7 @@ class ICTranslate(MainTranslate):
super(ICTranslate, self).__init__()
self._dict["Initial condition"] = _translate(
"InitialCondition", "Initial condition")
self._dict["Discharge"] = _translate(
"InitialCondition", "Discharge")
self._dict["Height"] = _translate(
"InitialCondition", "Height")
"InitialCondition", "Initial conditions")
self._dict["elevation"] = self._dict["unit_elevation"]
self._dict["discharge"] = self._dict["unit_discharge"]

View File

@ -499,6 +499,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self.update()
def close_model(self):
if not self.dialog_close(cancel=True):
return
self._study = None
self.update_enable_action()
self.conf.set_close_correctly()
@ -748,15 +751,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
##################
def msg_select_reach(self):
self.message_box("Please select a reach",
"Geometry edition need a reach selected "
"into river network window to work on it")
self.message_box(
self._trad["mb_select_reach_title"],
self._trad["mb_select_reach_msg"]
)
def dialog_reopen_study(self):
dlg = QMessageBox(self)
dlg.setWindowTitle("Last open study")
dlg.setText("Do you want to open again the last open study?")
dlg.setWindowTitle(self._trad["mb_last_open_title"])
dlg.setText(self._trad["mb_last_open_msg"])
opt = QMessageBox.Cancel | QMessageBox.Ok # | QMessageBox.Open
dlg.setStandardButtons(opt)
@ -796,9 +800,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def dialog_close(self, cancel=True):
dlg = QMessageBox(self)
dlg.setWindowTitle("Close PAMHYR without saving study")
dlg.setText("Do you want to save current study before PAMHYR close ?")
opt = QMessageBox.Save | QMessageBox.Ignore
dlg.setWindowTitle(self._trad["mb_close_title"])
dlg.setText(self._trad["mb_close_msg"])
opt = QMessageBox.Save | QMessageBox.Close
if cancel:
opt |= QMessageBox.Cancel
@ -810,7 +814,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if res == QMessageBox.Save:
self.save_study()
return True
elif res == QMessageBox.Ignore:
elif res == QMessageBox.Close:
return True
elif res == QMessageBox.Cancel:
return False
@ -1446,15 +1450,3 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
f"sqlitebrowser {file}",
shell=True
)
# TODO: Delete me !
###############
# DUMMY STUFF #
###############
def open_dummy(self, title="Dummy"):
self.dummy = DummyWindow(
title=title if type(title) is str else "Dummy",
parent=self
)
self.dummy.show()

View File

@ -368,11 +368,18 @@ class EdgeItem(QGraphicsItem):
class NodeText(QGraphicsTextItem):
def __init__(self, node_item):
def __init__(self, node_item, graph):
super(NodeText, self).__init__()
self.item = node_item
self.setPlainText(self.item.node.name)
self.graph = graph
name = self.item.node.name
if name == "":
name = self.graph._trad.node_name(self.item.node)
self.setPlainText(name)
self.setDefaultTextColor(Qt.black)
self.set_custom_pos(self.item.pos())
self.setZValue(2)
@ -502,7 +509,7 @@ class GraphWidget(QGraphicsView):
for node in self.graph.nodes():
inode = NodeItem(node, self)
self.texts[inode] = NodeText(inode)
self.texts[inode] = NodeText(inode, self)
self.scene().addItem(self.texts[inode])
self.scene().addItem(inode)
self.node_items.append(inode)
@ -578,7 +585,7 @@ class GraphWidget(QGraphicsView):
inode = NodeItem(node, self)
self.scene().addItem(inode)
self.node_items.append(inode)
self.texts[inode] = NodeText(inode)
self.texts[inode] = NodeText(inode, self)
self.scene().addItem(self.texts[inode])
self.changeNode.emit(self.sender())

View File

@ -94,6 +94,9 @@ class NodeTableModel(PamhyrTableModel):
return ret
if self._headers[index.column()] == "name":
return self._trad.node_name(self._lst[index.row()])
return self._lst[index.row()][self._headers[index.column()]]
@pyqtSlot()
@ -133,6 +136,15 @@ class EdgeTableModel(PamhyrTableModel):
if role != Qt.ItemDataRole.DisplayRole:
return QVariant()
if (self._headers[index.column()] == "node1" or
self._headers[index.column()] == "node2"):
return self._trad.node_name(
self._lst[index.row()][self._headers[index.column()]]
)
if self._headers[index.column()] == "name":
return self._trad.edge_name(self._lst[index.row()])
return self._lst[index.row()][self._headers[index.column()]]
@pyqtSlot()

View File

@ -97,6 +97,7 @@ class NetworkWindow(PamhyrWindow):
table_view=table,
table_headers=self._table_headers_node,
editable_headers=node_editable_headers,
trad=self._trad,
data=self._graph,
undo=self._undo_stack,
)
@ -116,6 +117,7 @@ class NetworkWindow(PamhyrWindow):
table_view=table,
table_headers=self._table_headers_edge,
editable_headers=edge_editable_headers,
trad=self._trad,
delegates={
"node1": self.delegate_combobox,
"node2": self.delegate_combobox,

View File

@ -31,6 +31,9 @@ class NetworkTranslate(MainTranslate):
"Network", "River network"
)
self._dict["node"] = _translate("Network", "Node")
self._dict["edge"] = _translate("Network", "Reach")
self._dict["menu_add_node"] = _translate("Network", "Add node")
self._dict["menu_del_node"] = _translate("Network", "Delete the node")
self._dict["menu_edit_res_node"] = _translate(
@ -63,3 +66,15 @@ class NetworkTranslate(MainTranslate):
"node2": _translate("Network", "Destination node"),
"id": _translate("Network", "Index"),
}
def node_name(self, node):
if node.name == "":
return f"{self['node']} #{node.id}"
return node.name
def edge_name(self, edge):
if edge.name == "":
return f"{self['edge']} #{edge.id}"
return edge.name

View File

@ -95,4 +95,5 @@ class CustomPlotValuesSelectionDialog(PamhyrDialog):
)
self.value = x, y
super().accept()

View File

@ -34,7 +34,7 @@ unit = {
"water_elevation": "0-meter",
"discharge": "1-m3s",
"velocity": "2-ms",
"depth": "3-meter",
"max_depth": "3-meter",
"mean_depth": "3-meter",
"froude": "4-dimensionless",
"wet_area": "5-m2",
@ -157,9 +157,9 @@ class CustomPlot(PamhyrPlot):
)
lines["velocity"] = line
if "depth" in self._y:
if "max_depth" in self._y:
ax = self._axes[unit["depth"]]
ax = self._axes[unit["max_depth"]]
d = list(
map(
lambda p: p.geometry.max_water_depth(
@ -171,7 +171,7 @@ class CustomPlot(PamhyrPlot):
rk, d,
color='brown', lw=1.,
)
lines["depth"] = line
lines["max_depth"] = line
if "mean_depth" in self._y:
@ -361,9 +361,9 @@ class CustomPlot(PamhyrPlot):
)
lines["velocity"] = line
if "depth" in self._y:
if "max_depth" in self._y:
ax = self._axes[unit["depth"]]
ax = self._axes[unit["max_depth"]]
d = list(
map(lambda z: profile.geometry.max_water_depth(z), z)
)
@ -372,7 +372,7 @@ class CustomPlot(PamhyrPlot):
ts, d,
color='brown', lw=1.,
)
lines["depth"] = line
lines["max_depth"] = line
if "mean_depth" in self._y:
@ -385,7 +385,7 @@ class CustomPlot(PamhyrPlot):
ts, d,
color='orange', lw=1.,
)
lines["depth"] = line
lines["mean_depth"] = line
if "froude" in self._y:

View File

@ -59,20 +59,3 @@ class CustomPlotTranslate(ResultsTranslate):
self._dict['3-meter'] = self._dict["unit_height"]
self._dict['4-dimensionless'] = self._dict["unit_froude"]
self._dict['5-m2'] = self._dict["wet_area"]
# SubDict
self._sub_dict["values_x"] = {
"rk": self._dict["rk"],
"time": self._dict["time"],
}
self._sub_dict["values_y"] = {
"elevation": self._dict["elevation"],
"water_elevation": self._dict["water_elevation"],
"discharge": self._dict["discharge"],
"velocity": self._dict["velocity"],
"depth": self._dict["max_depth"],
"mean_depth": self._dict["mean_depth"],
"froude": self._dict["froude"],
"wet_area": self._dict["wet_area"],
}

View File

@ -51,8 +51,8 @@ class PlotH(PamhyrPlot):
self._current_reach_id = reach_id
self._current_profile_id = profile_id
self.label_x = _translate("Results", "Time (s)")
self.label_y = _translate("Results", "Discharge (m³/s)")
self.label_x = self._trad["unit_time_s"]
self.label_y = self._trad["unit_discharge"]
self.label_discharge = _translate("Results", "Cross-section discharge")
self.label_discharge_max = _translate("Results", "Max discharge")
@ -174,12 +174,12 @@ class PlotH(PamhyrPlot):
self._line.set_data(x, y)
self._current.set_data(
self._current_timestamp,
[self._current_timestamp, self._current_timestamp],
self.canvas.axes.get_ylim()
)
def update_current(self):
self._current.set_data(
self._current_timestamp,
[self._current_timestamp, self._current_timestamp],
self.canvas.axes.get_ylim()
)

View File

@ -20,6 +20,8 @@ import os
import csv
import logging
from numpy import sqrt
from datetime import datetime
from tools import trace, timer, logger_exception
@ -290,9 +292,9 @@ class ResultsWindow(PamhyrWindow):
pname = profile.name if profile.name != "" else profile.rk
return (f"Reach: {reach.name} | " +
f"Profile: {pname} | " +
f"Timestamp : {fts} ({ts} sec)")
return (f"{self._trad['reach']}: {reach.name} | " +
f"{self._trad['cross_section']}: {pname} | " +
f"{self._trad['unit_time_s']} : {fts} ({ts} sec)")
def setup_statusbar(self):
txt = self._compute_status_label()
@ -308,8 +310,8 @@ class ResultsWindow(PamhyrWindow):
actions = {
"action_reload": self._reload,
"action_add": self._add_custom_plot,
# "action_export": self.export,
"action_export": self.export_current,
"action_export": self._export,
# "action_export": self.export_current,
}
for action in actions:
@ -534,6 +536,7 @@ class ResultsWindow(PamhyrWindow):
grid.addWidget(canvas, 1, 0)
widget.setLayout(grid)
tab_widget.addTab(widget, name)
tab_widget.setCurrentWidget(widget)
def _copy(self):
logger.info("TODO: copy")
@ -582,18 +585,50 @@ class ResultsWindow(PamhyrWindow):
self._button_last.setEnabled(True)
self._button_play.setIcon(self._icon_start)
def export(self):
def _export(self):
dlg = CustomPlotValuesSelectionDialog(parent=self)
if dlg.exec():
x, y = dlg.value
else:
return
logger.debug(
"Export custom plot for: " +
f"{x} -> {','.join(y)}"
)
self.file_dialog(
select_file=False,
callback=lambda d: self.export_to(d[0])
select_file="AnyFile",
callback=lambda f: self.export_to(f[0], x, y),
default_suffix=".csv",
file_filter=["CSV (*.csv)"],
)
def export_to(self, directory):
def export_to(self, filename, x, y):
timestamps = sorted(self._results.get("timestamps"))
for reach in self._results.river.reachs:
self.export_reach(reach, directory, timestamps)
if x == "rk":
timestamp = self._get_current_timestamp()
val_dict = self._export_rk(timestamp, y, filename)
elif x == "time":
profile = self._get_current_profile()
val_dict = self._export_time(profile, y, filename)
def export_reach(self, reach, directory, timestamps):
with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL)
dict_x = self._trad.get_dict("values_x")
dict_y = self._trad.get_dict("values_y")
header = [dict_x[x]]
for text in y:
header.append(dict_y[text])
writer.writerow(header)
for row in range(len(val_dict[x])):
line = [val_dict[x][row]]
for var in y:
line.append(val_dict[var][row])
writer.writerow(line)
def export_all(self, reach, directory, timestamps):
name = reach.name
name = name.replace(" ", "-")
if len(timestamps) == 1:
@ -607,59 +642,144 @@ class ResultsWindow(PamhyrWindow):
with open(file_name, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL)
if len(timestamps) > 1:
writer.writerow(["name", "rk", "data-file"])
for profile in reach.profiles:
p_file_name = os.path.join(
directory,
f"cs_{profile.geometry.id}.csv"
)
writer.writerow([
profile.name,
profile.rk,
p_file_name
])
self.export_profile(reach,
profile,
p_file_name,
timestamps)
else:
ts = timestamps[0]
writer.writerow(self._table["raw_data"]._headers)
for row in range(self._table["raw_data"].rowCount()):
line = []
for column in range(self._table["raw_data"].columnCount()):
index = self._table["raw_data"].index(row, column)
line.append(self._table["raw_data"].data(index))
writer.writerow(line)
def export_profile(self, reach, profile, file_name, timestamps):
with open(file_name, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL)
writer.writerow(["timestamp", "z", "q"])
for ts in timestamps:
writer.writerow([
ts,
profile.get_ts_key(ts, "Z"),
profile.get_ts_key(ts, "Q"),
])
ts = timestamps[0]
writer.writerow(self._table["raw_data"]._headers)
for row in range(self._table["raw_data"].rowCount()):
line = []
for column in range(self._table["raw_data"].columnCount()):
index = self._table["raw_data"].index(row, column)
line.append(self._table["raw_data"].data(index))
writer.writerow(line)
def export_current(self):
self.file_dialog(
select_file=False,
select_file="Directory",
callback=lambda d: self.export_current_to(d[0])
)
def export_current_to(self, directory):
reach = self._results.river.reachs[self._get_current_reach()]
self.export_reach(reach, directory, [self._get_current_timestamp()])
self.export_all(reach, directory, [self._get_current_timestamp()])
def delete_tab(self, index):
tab_widget = self.find(QTabWidget, f"tabWidget")
self._additional_plot.pop(tab_widget.tabText(index))
tab_widget.removeTab(index)
def _export_rk(self, timestamp, y, filename):
reach = self._results.river.reachs[self._get_current_reach()]
my_dict = {}
my_dict["rk"] = reach.geometry.get_rk()
if "elevation" in y:
my_dict["elevation"] = reach.geometry.get_z_min()
if "discharge" in y:
my_dict["discharge"] = list(
map(
lambda p: p.get_ts_key(timestamp, "Q"),
reach.profiles
)
)
if "water_elevation" in y:
my_dict["water_elevation"] = list(
map(
lambda p: p.get_ts_key(timestamp, "Z"),
reach.profiles
)
)
if "velocity" in y:
my_dict["velocity"] = list(
map(
lambda p: p.geometry.speed(
p.get_ts_key(timestamp, "Q"),
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
if "max_depth" in y:
my_dict["max_depth"] = list(
map(
lambda p: p.geometry.max_water_depth(
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
if "mean_depth" in y:
my_dict["mean_depth"] = list(
map(
lambda p: p.geometry.mean_water_depth(
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
if "froude" in y:
my_dict["froude"] = list(
map(
lambda p:
p.geometry.speed(
p.get_ts_key(timestamp, "Q"),
p.get_ts_key(timestamp, "Z")) /
sqrt(9.81 * (
p.geometry.wet_area(
p.get_ts_key(timestamp, "Z")) /
p.geometry.wet_width(
p.get_ts_key(timestamp, "Z"))
)),
reach.profiles
)
)
if "wet_area" in y:
my_dict["wet_area"] = list(
map(
lambda p: p.geometry.wet_area(
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
return my_dict
def _export_time(self, profile, y, filename):
reach = self._results.river.reachs[self._get_current_reach()]
profile = reach.profile(profile)
ts = list(self._results.get("timestamps"))
ts.sort()
my_dict = {}
my_dict["time"] = ts
z = profile.get_key("Z")
q = profile.get_key("Q")
if "elevation" in y:
my_dict["elevation"] = [profile.geometry.z_min()] * len(ts)
if "discharge" in y:
my_dict["discharge"] = q
if "water_elevation" in y:
my_dict["water_elevation"] = z
if "velocity" in y:
my_dict["velocity"] = list(
map(
lambda q, z: profile.geometry.speed(q, z),
q, z
)
)
if "max_depth" in y:
my_dict["max_depth"] = list(
map(lambda z: profile.geometry.max_water_depth(z), z)
)
if "mean_depth" in y:
my_dict["mean_depth"] = list(
map(lambda z: profile.geometry.mean_water_depth(z), z)
)
if "froude" in y:
my_dict["froude"] = list(
map(lambda z, q:
profile.geometry.speed(q, z) /
sqrt(9.81 * (
profile.geometry.wet_area(z) /
profile.geometry.wet_width(z))
), z, q)
)
if "wet_area" in y:
my_dict["wet_area"] = list(
map(lambda z: profile.geometry.wet_area(z), z)
)
return my_dict

View File

@ -37,7 +37,7 @@ class ResultsTranslate(MainTranslate):
self._dict['x'] = _translate("Results", "X (m)")
self._dict['label_bottom'] = _translate("Results", "River bottom")
self._dict['label_bottom'] = _translate("Results", "Bottom")
self._dict['label_water'] = _translate("Results", "Water elevation")
self._dict['label_water_max'] = _translate(
"Results",
@ -66,3 +66,19 @@ class ResultsTranslate(MainTranslate):
"hydraulic_radius": self._dict["unit_hydraulic_radius"],
"froude": self._dict["unit_froude"],
}
self._sub_dict["values_x"] = {
"rk": self._dict["unit_rk"],
"time": self._dict["unit_time_s"],
}
self._sub_dict["values_y"] = {
"elevation": self._dict["unit_elevation"],
"water_elevation": self._dict["unit_water_elevation"],
"discharge": self._dict["unit_discharge"],
"velocity": self._dict["unit_speed"],
"max_depth": self._dict["unit_max_height"],
"mean_depth": self._dict["unit_mean_height"],
"froude": self._dict["unit_froude"],
"wet_area": self._dict["unit_wet_area"],
}

View File

@ -85,7 +85,7 @@ class WindowToolKit(object):
return header, values
def file_dialog(self, select_file=True,
def file_dialog(self, select_file="ExistingFile",
callback=lambda x: None,
directory=None,
default_suffix=None,
@ -107,16 +107,18 @@ class WindowToolKit(object):
dialog = QFileDialog(self, options=options)
if select_file:
if select_file == "Existing_file":
mode = QFileDialog.FileMode.ExistingFile
else:
elif select_file == "Directory":
mode = QFileDialog.FileMode.Directory
else:
mode = QFileDialog.FileMode.AnyFile
dialog.setFileMode(mode)
if directory is not None:
dialog.setDirectory(directory)
if select_file:
if select_file != "Directory":
if default_suffix is not None:
dialog.setDefaultSuffix(default_suffix)
@ -147,6 +149,9 @@ class WindowToolKit(object):
msg.setInformativeText(informative_text)
msg.setWindowTitle(window_title)
msg.findChild(QLabel, "qt_msgbox_label")\
.setFixedWidth(384)
msg.exec_()

View File

@ -66,8 +66,9 @@ class UnitTranslate(CommonWordTranslate):
self._dict["unit_water_elevation"] = _translate(
"Unit", "Water elevation (m)"
)
self._dict["unit_speed"] = _translate("Unit", "Velocity (m/s)")
self._dict["unit_discharge"] = _translate("Unit", "Discharge (m³/s)")
self._dict["unit_discharge"] = _translate("Unit", "Discharge (m^3/s)")
self._dict["unit_area"] = _translate("Unit", "Area (hectare)")
self._dict["unit_time_s"] = _translate("Unit", "Time (sec)")
@ -76,7 +77,7 @@ class UnitTranslate(CommonWordTranslate):
self._dict["unit_date_s"] = _translate("Unit", "Date (sec)")
self._dict["unit_date_iso"] = _translate("Unit", "Date (ISO format)")
self._dict["unit_wet_area"] = _translate("Unit", "Wet Area (m²)")
self._dict["unit_wet_area"] = _translate("Unit", "Wet Area (m^2)")
self._dict["unit_wet_perimeter"] = _translate(
"Unit", "Wet Perimeter (m)"
)
@ -113,3 +114,29 @@ class MainTranslate(UnitTranslate):
self._dict["waiting_result"] = _translate(
"MainWindow", "Reading results ..."
)
# Message box
self._dict["mb_select_reach_title"] = _translate(
"MainWindow", "Please select a reach"
)
self._dict["mb_select_reach_msg"] = _translate(
"MainWindow",
"This edition window need a reach selected "
"into the river network to work on it"
)
self._dict["mb_last_open_title"] = _translate(
"MainWindow", "Last open study"
)
self._dict["mb_last_open_msg"] = _translate(
"MainWindow",
"Do you want to open again the last open study?"
)
self._dict["mb_close_title"] = _translate(
"MainWindow", "Close without saving study"
)
self._dict["mb_close_msg"] = _translate(
"MainWindow",
"Do you want to save current study before closing it?"
)

View File

@ -382,7 +382,7 @@
</widget>
<widget class="QWidget" name="tab_language">
<attribute name="title">
<string>Langue</string>
<string>Language</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>414</width>
<height>482</height>
<height>70</height>
</rect>
</property>
<property name="windowTitle">
@ -57,22 +57,6 @@
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
@ -89,5 +73,21 @@
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -75,6 +75,7 @@
<addaction name="action_sort"/>
<addaction name="action_generate_uniform"/>
<addaction name="action_generate_critical"/>
<addaction name="action_increasing"/>
</widget>
<action name="action_add">
<property name="checkable">
@ -140,6 +141,14 @@
<string>Generate rating curve as Q(z) = Sqrt(g*S(z)^3/L(z))</string>
</property>
</action>
<action name="action_increasing">
<property name="text">
<string>Make increasing</string>
</property>
<property name="toolTip">
<string>Remove points to make the curve increasing</string>
</property>
</action>
</widget>
<resources/>
<connections/>

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>1024</width>
<width>849</width>
<height>576</height>
</rect>
</property>
@ -27,14 +27,21 @@
<item>
<widget class="QPushButton" name="pushButton_generate_1">
<property name="text">
<string>Generate height</string>
<string>Generate uniform depth</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_generate_2">
<property name="text">
<string>Generate discharge</string>
<string>Generate uniform discharge</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_generate_3">
<property name="text">
<string>Generate uniform elevation</string>
</property>
</widget>
</item>
@ -65,7 +72,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>1024</width>
<width>849</width>
<height>22</height>
</rect>
</property>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>284</width>
<height>107</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="locale">
<locale language="English" country="Europe"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Depth (m)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox">
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Generate discharge</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -32,7 +32,7 @@
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Discharge (m³/s)</string>
<string>Discharge (m^3/s)</string>
</property>
</widget>
</item>

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>284</width>
<height>80</height>
<width>396</width>
<height>182</height>
</rect>
</property>
<property name="windowTitle">
@ -17,7 +17,79 @@
<locale language="English" country="Europe"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Upstream height (m)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox_1">
<property name="minimum">
<double>-1000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Discharge</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox_3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<double>-1000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Downstream height (m)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox_2">
<property name="minimum">
<double>-1000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -27,34 +99,17 @@
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Height (m)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox">
<property name="maximum">
<double>1000000.000000000000000</double>
<string>Generate constant discharge</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Generate discharge</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>194</width>
<width>251</width>
<height>114</height>
</rect>
</property>
@ -27,7 +27,7 @@
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Number of points to keep</string>
<string>Maximum number of points to keep</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">

View File

@ -132,14 +132,14 @@
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<property name="tabsClosable">
<bool>true</bool>
</property>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Raw data</string>
<string>Data</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="1">
@ -262,7 +262,7 @@
<string>Export</string>
</property>
<property name="toolTip">
<string>Export raw data</string>
<string>Export data as CSV</string>
</property>
<property name="shortcut">
<string>Ctrl+E</string>

View File

@ -17,8 +17,35 @@
<locale language="English" country="Europe"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_logo_pamhyr2">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>ressources/Pamhyr2_logo.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_logo_inrae">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>ressources/Logo-INRAE.png</pixmap>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_title">
<property name="font">
@ -33,34 +60,213 @@
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Copyright © 2022-2024 INRAE</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_version">
<property name="text">
<string>Version: @version</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_license">
<property name="text">
<string>License: GPLv3+</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_logo_gpl">
<property name="maximumSize">
<size>
<width>100</width>
<height>50</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>ressources/GPLv3_Logo.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;a href=&quot;https://gitlab.irstea.fr/theophile.terraz/pamhyr&quot;&gt;Source code&lt;/a&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_copyright">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_version">
<property name="text">
<string>Version: @version</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_license">
<property name="text">
<string>License: GPLv3+</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;a href=&quot;https://gitlab.irstea.fr/theophile.terraz/pamhyr&quot;&gt;Source code&lt;/a&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
@ -79,16 +285,6 @@
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_logo_pamhyr2">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>ressources/Pamhyr2_logo.png</pixmap>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

File diff suppressed because it is too large Load Diff