# Table.py -- Pamhyr # Copyright (C) 2023-2025 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 -*- import logging import traceback from numpy import sqrt from tools import timer, trace from itertools import compress from PyQt5.QtGui import ( QKeySequence, QColor ) from PyQt5.QtCore import ( Qt, QAbstractTableModel, QModelIndex, QVariant, pyqtSlot, QCoreApplication, ) from PyQt5.QtWidgets import ( QMessageBox, QUndoCommand, QUndoStack, QStyledItemDelegate, QLineEdit, QAbstractItemView, QComboBox, ) from View.Tools.PamhyrTable import PamhyrTableModel from View.Results.translate import * logger = logging.getLogger() _translate = QCoreApplication.translate class TableModel(PamhyrTableModel): def _setup_lst(self): _river = self._data[0].river if self._opt_data == "reach": self._lst = _river.reachs elif self._opt_data == "profile": self._lst = _river.reach(0).profiles # self._lst = list(filter(lambda x: x.name[0:8] != 'interpol', # _river.reach(0).profiles)) elif self._opt_data == "raw_data": self._lst = _river.reach(0).profiles # self._lst = list(filter(lambda x: x.name[0:8] != 'interpol', # _river.reach(0).profiles)) elif self._opt_data == "solver": self._lst = self._parent._solvers def __init__(self, **kwargs): self._timestamp = max(kwargs["parent"]._timestamps) super(TableModel, self).__init__(**kwargs) def data(self, index, role=Qt.DisplayRole): if role != Qt.ItemDataRole.DisplayRole: return QVariant() row = index.row() column = index.column() if self._opt_data == "reach": if self._headers[column] == "name": v = self._lst[row].name return str(v) elif self._opt_data == "profile": if self._headers[column] == "name": v = self._lst[row].name return str(v) elif self._headers[column] == "rk": v = self._lst[row].rk return f"{v:.4f}" elif self._opt_data == "solver": if self._headers[column] == "solver": v = self._lst[row] if v is None: v = self._data[0].solver_name return str(v) elif self._opt_data == "raw_data": p = self._lst[row] if self._headers[column] == "name": if p.name == "": return f"{p.rk:.4f}" return f"{p.name}" elif self._headers[column] == "water_elevation": v = self._lst[row].get_ts_key(self._timestamp, "Z") if v is None: v = 0.0 return f"{v:.4f}" elif self._headers[column] == "discharge": v = self._lst[row].get_ts_key(self._timestamp, "Q") if v is None: v = 0.0 return f"{v:.4f}" elif self._headers[column] == "velocity": v = self._lst[row].get_ts_key(self._timestamp, "V") if v is None: v = 0.0 return f"{v:.4f}" elif self._headers[column] == "width": z = self._lst[row].get_ts_key(self._timestamp, "Z") v = self._lst[row].geometry.wet_width(z) return f"{v:.4f}" elif self._headers[column] == "depth": z = self._lst[row].get_ts_key(self._timestamp, "Z") v = self._lst[row].geometry.max_water_depth(z) return f"{v:.4f}" elif self._headers[column] == "mean_depth": z = self._lst[row].get_ts_key(self._timestamp, "Z") v = self._lst[row].geometry.mean_water_depth(z) return f"{v:.4f}" elif self._headers[column] == "wet_area": z = self._lst[row].get_ts_key(self._timestamp, "Z") v = self._lst[row].geometry.wet_area(z) return f"{v:.4f}" elif self._headers[column] == "wet_perimeter": z = self._lst[row].get_ts_key(self._timestamp, "Z") v = self._lst[row].geometry.wet_perimeter(z) return f"{v:.4f}" elif self._headers[column] == "hydraulic_radius": z = self._lst[row].get_ts_key(self._timestamp, "Z") v = self._lst[row].geometry.wet_radius(z) return f"{v:.4f}" elif self._headers[column] == "froude": q = self._lst[row].get_ts_key(self._timestamp, "Q") z = self._lst[row].get_ts_key(self._timestamp, "Z") v = self._lst[row].get_ts_key(self._timestamp, "V") a = self._lst[row].geometry.wet_area(z) b = self._lst[row].geometry.wet_width(z) if b == 0.0 or a == 0.0: froude = 0.0 else: froude = v / sqrt(9.81 * (a / b)) return f"{froude:.4f}" else: v = 0.0 return f"{v:.4f}" return QVariant() def update(self, reach): _river = self._data[0].river if self._opt_data == "reach": self._lst = _river.reachs elif self._opt_data == "profile" or self._opt_data == "raw_data": self._lst = _river.reach(reach).profiles elif self._opt_data == "solver": self._lst = self._parent._solvers self.layoutChanged.emit() @property def timestamp(self): return self._timestamp @timestamp.setter def timestamp(self, timestamp): self._timestamp = timestamp self.layoutChanged.emit()