Compare commits

..

10 Commits

Author SHA1 Message Date
Theophile Terraz 13b4413b36 merge master 2025-09-29 16:08:06 +02:00
Theophile Terraz 706a900c8e work on rubar3 2025-09-29 15:25:35 +02:00
Theophile Terraz da03f39425 debug 2025-09-29 11:23:46 +02:00
Theophile Terraz 7d42c164fc debug 2025-09-25 17:01:01 +02:00
Theophile Terraz 1b2f98494b pep8 2025-09-23 15:53:49 +02:00
Theophile Terraz e7b63fe270 debug 2025-09-23 14:55:31 +02:00
Theophile Terraz 80ae4c36ad import lateral contributions from file 2025-09-23 14:17:59 +02:00
Theophile Terraz 41cffd13e0 debug 2025-09-19 16:33:06 +02:00
Theophile Terraz 9270dd0ff1 add HHLab test case 2025-09-19 16:04:10 +02:00
Theophile Terraz ba8a50e0b9 debug frictions 2025-09-19 16:03:23 +02:00
15 changed files with 230 additions and 75 deletions

View File

@ -426,30 +426,31 @@ class SedimentLayer(SQLSubModel):
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) "
) )
for row in table: if table is not None:
it = iter(row) for row in table:
it = iter(row)
pid = next(it) pid = next(it)
deleted = (next(it) == 1) deleted = (next(it) == 1)
name = next(it) name = next(it)
comment = next(it) comment = next(it)
owner_scenario = next(it) owner_scenario = next(it)
sl = cls( sl = cls(
id=pid, id=pid,
name=name, name=name,
comment=comment, comment=comment,
status=data['status'], status=data['status'],
owner_scenario=owner_scenario owner_scenario=owner_scenario
) )
if deleted: if deleted:
sl.set_as_deleted() sl.set_as_deleted()
data["sl"] = sl data["sl"] = sl
sl._layers = Layer._db_load(execute, data) sl._layers = Layer._db_load(execute, data)
loaded.add(pid) loaded.add(pid)
new.append(sl) new.append(sl)
data["scenario"] = scenario.parent data["scenario"] = scenario.parent
new += cls._db_load(execute, data) new += cls._db_load(execute, data)

View File

@ -74,10 +74,10 @@ class Rubar3(CommandLineSolver):
("rubarbe_tf_5", "y"), ("rubarbe_tf_5", "y"),
("rubarbe_tf_6", "n"), ("rubarbe_tf_6", "n"),
("rubarbe_trased", "y"), ("rubarbe_trased", "y"),
("rubarbe_optfpc", "0"), # ("rubarbe_optfpc", "0"),
("rubarbe_ros", "2650.0"), # ("rubarbe_ros", "2650.0"),
("rubarbe_dm", "0.1"), # ("rubarbe_dm", "0.1"),
("rubarbe_segma", "1.0"), # ("rubarbe_segma", "1.0"),
# Sediment parameters # Sediment parameters
("rubarbe_sediment_ros", "2650.0"), ("rubarbe_sediment_ros", "2650.0"),
("rubarbe_sediment_por", "0.4"), ("rubarbe_sediment_por", "0.4"),
@ -167,7 +167,7 @@ class Rubar3(CommandLineSolver):
it = iter(params) it = iter(params)
line = 0 line = 0
while line < 29: while line < 25:
param = next(it) param = next(it)
name = param.name name = param.name
value = param.value value = param.value
@ -277,19 +277,20 @@ class Rubar3(CommandLineSolver):
f.write(f"{ind:>4} {rk:>11.3f} {n_points:>4}\n") f.write(f"{ind:>4} {rk:>11.3f} {n_points:>4}\n")
for point in profile.points: station = profile.get_station()
for i, point in enumerate(profile.points):
label = point.name.lower() label = point.name.lower()
if label != "": if label != "":
if label[0] == "r": if label[0] == "r":
label = label[1].upper() label = label[1].upper()
else: else:
label = label[1].upper() label = " "
else: else:
label = " " label = " "
y = point.y y = station[i]
z = point.z z = point.z
dcs = 0.001 dcs = 1.0
scs = 1.0 scs = 1.0
tmcs = 0.0 tmcs = 0.0
@ -444,10 +445,10 @@ class Rubar3(CommandLineSolver):
z = data[profile.rk][0] z = data[profile.rk][0]
q = data[profile.rk][1] q = data[profile.rk][1]
# height = z - profile.z_min() height = z - profile.z_min()
speed = profile.speed(q, z) speed = profile.speed(q, z)
return z, speed return height, speed
def _export_hydro(self, study, repertory, qlog, name="0"): def _export_hydro(self, study, repertory, qlog, name="0"):
if qlog is not None: if qlog is not None:
@ -470,7 +471,7 @@ class Rubar3(CommandLineSolver):
for bc in bcs: for bc in bcs:
f.write(f"{len(bc)}\n") f.write(f"{len(bc)}\n")
for d0, d1 in bc.data: for d0, d1 in bc.data:
f.write(f"{d0} {d1}\n") f.write(f"{d1} {d0}\n")
def _export_condav(self, study, repertory, qlog, name="0"): def _export_condav(self, study, repertory, qlog, name="0"):
if qlog is not None: if qlog is not None:
@ -493,7 +494,7 @@ class Rubar3(CommandLineSolver):
for bc in bcs: for bc in bcs:
f.write(f"{len(bc)}\n") f.write(f"{len(bc)}\n")
for d0, d1 in bc.data: for d0, d1 in bc.data:
f.write(f"{d0} {d1}\n") f.write(f"{d1} {d0}\n")
class RubarBE(Rubar3): class RubarBE(Rubar3):

View File

@ -250,7 +250,10 @@ class TableModel(PamhyrTableModel):
line.startswith("*") or line.startswith("*") or
line.startswith("$")): line.startswith("$")):
line = line.split() line = line.split()
data0.append(float(line[0]) * mult) if bctype == "ZD":
data0.append(float(line[0]))
else:
data0.append(old_pamhyr_date_to_timestamp(line[0]))
data1.append(line[1]) data1.append(line[1])
self.replace_data(data0, data1) self.replace_data(data0, data1)

View File

@ -41,7 +41,7 @@ class BCETranslate(BCTranslate):
"BoundaryCondition", "Mage hydrograph file (*.HYD)") "BoundaryCondition", "Mage hydrograph file (*.HYD)")
self._dict["file_lim"] = _translate( self._dict["file_lim"] = _translate(
"BoundaryCondition", "Mage limnigraph file (*.LIM)") "BoundaryCondition", "Mage limnigraph file (*.LIM)")
self._dict["file_lim"] = _translate( self._dict["file_ava"] = _translate(
"BoundaryCondition", "Mage rating curve file (*.AVA)") "BoundaryCondition", "Mage rating curve file (*.AVA)")
self._dict["file_all"] = _translate( self._dict["file_all"] = _translate(
"BoundaryCondition", "All files (*)") "BoundaryCondition", "All files (*)")

View File

@ -153,6 +153,7 @@ class ReplaceDataCommand(QUndoCommand):
self._new_data = new_data self._new_data = new_data
self._old_rows = list(range(len(frictions))) self._old_rows = list(range(len(frictions)))
self._new_rows = list(range(len(new_data))) self._new_rows = list(range(len(new_data)))
self._new = []
self._old_friction = [] self._old_friction = []
for row in self._old_rows: for row in self._old_rows:
@ -164,15 +165,20 @@ class ReplaceDataCommand(QUndoCommand):
self._frictions.insert(row, el) self._frictions.insert(row, el)
def redo(self): def redo(self):
self._frictions.delete_i(self._old_rows) if len(self._new) == 0:
for row in self._new_rows: self._frictions.delete_i(self._old_rows)
new = self._frictions.new(row) for row in self._new_rows:
d = self._new_data[row] new = self._frictions.new(row)
new.edge = d[0] d = self._new_data[row]
new.begin_rk = d[1] new.edge = d[0]
new.end_rk = d[2] new.begin_rk = d[1]
new.begin_strickler = d[3] new.end_rk = d[2]
new.end_strickler = d[4] new.begin_strickler = d[3]
new.end_strickler = d[4]
self._new.append((row, new))
else:
for row, el in self._new:
self._frictions.insert(row, el)
class DelCommand(QUndoCommand): class DelCommand(QUndoCommand):

View File

@ -319,9 +319,10 @@ class InitialConditionsWindow(PamhyrWindow):
def _import_from_results(self, results): def _import_from_results(self, results):
logger.debug(f"import from results: {results}") logger.debug(f"import from results: {results}")
self._table.import_from_results(row, results) self._table.import_from_results(results)
def _import_from_ini_file(self, file_name): def _import_from_ini_file(self, file_name):
logger.debug(f"import from INI file: {file_name}")
self._table.read_from_ini(file_name) self._table.read_from_ini(file_name)
def move_up(self): def move_up(self):

View File

@ -19,7 +19,7 @@
import logging import logging
import traceback import traceback
from tools import trace, timer from tools import trace, timer, old_pamhyr_date_to_timestamp
from PyQt5.QtCore import ( from PyQt5.QtCore import (
Qt, QVariant, QAbstractTableModel, Qt, QVariant, QAbstractTableModel,
@ -38,7 +38,7 @@ from View.LateralContribution.UndoCommand import (
SetNameCommand, SetEdgeCommand, SetTypeCommand, SetNameCommand, SetEdgeCommand, SetTypeCommand,
SetBeginCommand, SetEndCommand, SetBeginCommand, SetEndCommand,
AddCommand, DelCommand, SortCommand, AddCommand, DelCommand, SortCommand,
MoveCommand, PasteCommand, DuplicateCommand, MoveCommand, PasteCommand, DuplicateCommand, ImportCommand,
) )
from Model.LateralContribution.LateralContributionTypes import ( from Model.LateralContribution.LateralContributionTypes import (
@ -116,17 +116,20 @@ class ComboBoxDelegate(QItemDelegate):
def setModelData(self, editor, model, index): def setModelData(self, editor, model, index):
text = str(editor.currentText()) text = str(editor.currentText())
if self._mode == "rk": if self._data is None:
profiles = list(
filter(
lambda p: p.display_name() == text,
self._data.reach.profiles
)
)
value = profiles[0].rk if len(profiles) > 0 else None
else:
value = text value = text
else:
if self._mode == "rk" and self._data.reach is not None:
profiles = list(
filter(
lambda p: p.display_name() == text,
self._data.reach.profiles
)
)
value = profiles[0].rk if len(profiles) > 0 else None
else:
value = text
model.setData(index, value) model.setData(index, value)
editor.close() editor.close()
@ -319,3 +322,44 @@ class TableModel(PamhyrTableModel):
self.endMoveRows() self.endMoveRows()
self.layoutChanged.emit() self.layoutChanged.emit()
def read_from_lat(self, file_name):
logger.debug(f"Import lateral contributions from {file_name}")
data = []
current_reach = -1
with open(file_name, encoding="utf-8") as lat_file:
for line in lat_file:
if not (line.startswith("#") or
line.startswith("*") or
len(line) < 1):
line = line.split()
if line[0] == "$":
current_reach = int(line[1]) - 1
if (current_reach <= len(self._data.enable_edges()) and
current_reach >= 0):
data.append(
[self._data.enable_edges()[current_reach],
float(line[2]),
float(line[3])
]
)
else:
if (current_reach <= len(self._data.enable_edges()) and
current_reach >= 0):
data[-1].append(
[
old_pamhyr_date_to_timestamp(line[0]),
float(line[1])
]
)
self.layoutAboutToBeChanged.emit()
self._undo.push(
ImportCommand(
self._lst, self._tab, data
)
)
self.layoutAboutToBeChanged.emit()
self.layoutChanged.emit()

View File

@ -28,6 +28,10 @@ from Model.LateralContribution.LateralContributionList import (
LateralContributionList LateralContributionList
) )
from Model.LateralContribution.LateralContributionTypes import (
NotDefined, LateralContrib,
)
class SetNameCommand(QUndoCommand): class SetNameCommand(QUndoCommand):
def __init__(self, lcs, tab, index, new_value): def __init__(self, lcs, tab, index, new_value):
@ -143,12 +147,12 @@ class DelCommand(QUndoCommand):
self._tab = tab self._tab = tab
self._rows = rows self._rows = rows
self._bc = [] self._lc = []
for row in rows: for row in rows:
self._bc.append(self._lcs.get_tab(self._tab)[row]) self._lc.append(self._lcs.get_tab(self._tab)[row])
def undo(self): def undo(self):
for el in self._bc: for el in self._lc:
el.set_as_not_deleted() el.set_as_not_deleted()
def redo(self): def redo(self):
@ -214,36 +218,73 @@ class MoveCommand(QUndoCommand):
class PasteCommand(QUndoCommand): class PasteCommand(QUndoCommand):
def __init__(self, lcs, tab, row, bc): def __init__(self, lcs, tab, row, lc):
QUndoCommand.__init__(self) QUndoCommand.__init__(self)
self._lcs = lcs self._lcs = lcs
self._tab = tab self._tab = tab
self._row = row self._row = row
self._bc = deepcopy(bc) self._lc = deepcopy(lc)
self._bc.reverse() self._lc.reverse()
def undo(self): def undo(self):
self._lcs.delete(self._tab, self._bc) self._lcs.delete(self._tab, self._lc)
def redo(self): def redo(self):
for bc in self._bc: for lc in self._lc:
self._lcs.insert(self._tab, self._row, bc) self._lcs.insert(self._tab, self._row, lc)
class ImportCommand(QUndoCommand):
def __init__(self, lcs, tab, data):
QUndoCommand.__init__(self)
self._tab = tab
self._lcs = lcs
self._data = data
self._old_rows = list(range(len(self._lcs.get_tab(self._tab))))
self._new_rows = list(range(len(self._data)))
self._new_lc = None
self._old_lc = []
for row in self._old_rows:
self._old_lc.append((row, self._lcs.get(self._tab, row)))
def undo(self):
self._lcs.delete_i(self._tab, self._new_rows)
for row, el in self._old_lc:
self._lcs.insert(self._tab, row, el)
def redo(self):
self._lcs.delete_i(self._tab, self._old_rows)
if self._new_lc is None:
self._new_lc = []
for row, data in enumerate(self._data):
new = LateralContrib(status=self._lcs._status)
new.edge = data[0]
new.begin_rk = data[1]
new.end_rk = data[2]
for i, val in enumerate(data[3:]):
new.insert(i, val)
self._new_lc.append(new)
for row, el in enumerate(self._new_lc):
self._lcs.insert(self._tab, row, el)
class DuplicateCommand(QUndoCommand): class DuplicateCommand(QUndoCommand):
def __init__(self, lcs, tab, rows, bc): def __init__(self, lcs, tab, rows, lc):
QUndoCommand.__init__(self) QUndoCommand.__init__(self)
self._lcs = lcs self._lcs = lcs
self._tab = tab self._tab = tab
self._rows = rows self._rows = rows
self._bc = deepcopy(bc) self._lc = deepcopy(lc)
self._bc.reverse() self._lc.reverse()
def undo(self): def undo(self):
self._lcs.delete(self._tab, self._bc) self._lcs.delete(self._tab, self._lc)
def redo(self): def redo(self):
for bc in self._lcs: for lc in self._lcs:
self._lcs.insert(self._tab, self._rows[0], bc) self._lcs.insert(self._tab, self._rows[0], lc)

View File

@ -22,6 +22,7 @@ from tools import trace, timer
from View.Tools.PamhyrWindow import PamhyrWindow from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5 import QtWidgets
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
) )
@ -29,7 +30,7 @@ from PyQt5.QtGui import (
from PyQt5.QtCore import ( from PyQt5.QtCore import (
Qt, QVariant, QAbstractTableModel, Qt, QVariant, QAbstractTableModel,
QCoreApplication, QModelIndex, pyqtSlot, QCoreApplication, QModelIndex, pyqtSlot,
QRect, QRect, QSettings,
) )
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
@ -158,6 +159,8 @@ class LateralContributionWindow(PamhyrWindow):
def setup_connections(self): def setup_connections(self):
if self._study.is_editable(): if self._study.is_editable():
self.find(QAction, "action_import").triggered.connect(
self.import_from_file)
self.find(QAction, "action_add").triggered.connect(self.add) self.find(QAction, "action_add").triggered.connect(self.add)
self.find(QAction, "action_del").triggered.connect(self.delete) self.find(QAction, "action_del").triggered.connect(self.delete)
self.find(QAction, "action_sort").triggered.connect(self.sort) self.find(QAction, "action_sort").triggered.connect(self.sort)
@ -302,3 +305,26 @@ class LateralContributionWindow(PamhyrWindow):
parent=self parent=self
) )
win.show() win.show()
def import_from_file(self):
options = QFileDialog.Options()
settings = QSettings(QSettings.IniFormat,
QSettings.UserScope, 'MyOrg', )
options |= QFileDialog.DontUseNativeDialog
file_types = [
self._trad["file_lat"],
self._trad["file_all"],
]
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self,
self._trad["open_file"],
"",
";; ".join(file_types),
options=options
)
if filename != "":
tab = self.current_tab()
self._table[tab].read_from_lat(filename)

View File

@ -52,6 +52,10 @@ class LCTranslate(MainTranslate):
self._dict["x"] = _translate("Geometry", "X (m)") self._dict["x"] = _translate("Geometry", "X (m)")
self._dict["y"] = _translate("Geometry", "Y (m)") self._dict["y"] = _translate("Geometry", "Y (m)")
self._dict["z"] = _translate("Geometry", "Z (m)") self._dict["z"] = _translate("Geometry", "Z (m)")
self._dict["file_lat"] = _translate(
"LateralContribution", "Shapefile (*.LAT *.lat)")
self._dict["file_all"] = _translate(
"LateralContribution", "All files (*)")
self._sub_dict["table_headers"] = { self._sub_dict["table_headers"] = {
"name": self._dict["name"], "name": self._dict["name"],

View File

@ -495,7 +495,7 @@ class ResultsWindow(PamhyrWindow):
table = self.find(QTableView, f"tableView_profile") table = self.find(QTableView, f"tableView_profile")
indexes = table.selectedIndexes() indexes = table.selectedIndexes()
if len(indexes) == 0: if len(indexes) == 0:
return 0 return []
return [i.row() for i in indexes] return [i.row() for i in indexes]

View File

@ -112,6 +112,18 @@
<string>Sort points</string> <string>Sort points</string>
</property> </property>
</action> </action>
<action name="action_import">
<property name="icon">
<iconset>
<normaloff>ressources/import.png</normaloff>ressources/import.png</iconset>
</property>
<property name="text">
<string>Import</string>
</property>
<property name="toolTip">
<string>Import from file</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -97,6 +97,7 @@
<attribute name="toolBarBreak"> <attribute name="toolBarBreak">
<bool>false</bool> <bool>false</bool>
</attribute> </attribute>
<addaction name="action_import"/>
<addaction name="action_add"/> <addaction name="action_add"/>
<addaction name="action_del"/> <addaction name="action_del"/>
<addaction name="action_edit"/> <addaction name="action_edit"/>
@ -162,6 +163,18 @@
<string>Sort by names</string> <string>Sort by names</string>
</property> </property>
</action> </action>
<action name="action_import">
<property name="icon">
<iconset>
<normaloff>ressources/import.png</normaloff>ressources/import.png</iconset>
</property>
<property name="text">
<string>Import</string>
</property>
<property name="toolTip">
<string>Import from file</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -264,7 +264,10 @@ def date_dmy_to_timestamp(date: str):
def old_pamhyr_date_to_timestamp(date: str): def old_pamhyr_date_to_timestamp(date: str):
v = date.split(":") v = date.split(":")
if len(v) != 4: if len(v) != 4:
return 0 if len(v) == 1: # minutes
return int(float(v[0]) * 60) # Minute to sec
else:
return 0
m = [ m = [
(24 * 60 * 60), # Day to sec (24 * 60 * 60), # Day to sec

Binary file not shown.