mirror of
https://gitlab.com/pamhyr/pamhyr2.git
synced 2026-10-30 03:20:41 +01:00
Compare commits
45
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9680202b4c | ||
|
|
ff1bc26d2e | ||
|
|
ebb4c69145 | ||
|
|
29b5c97345 | ||
|
|
b171eb7d32 | ||
|
|
0e18d43496 | ||
|
|
bd4222adfa | ||
|
|
1e4761609d | ||
|
|
de72e2e96b | ||
|
|
95a0dabe68 | ||
|
|
9f53ad685e | ||
|
|
02c597d109 | ||
|
|
510bee115b | ||
|
|
ed250f836d | ||
|
|
a47410a0f1 | ||
|
|
704130966e | ||
|
|
b927aa81b3 | ||
|
|
d154ac96c2 | ||
|
|
6067ba601e | ||
|
|
716d0af96f | ||
|
|
f917dd9284 | ||
|
|
cd68bebf03 | ||
|
|
35cc348f03 | ||
|
|
6f3e1e31f0 | ||
|
|
7df0750c58 | ||
|
|
bcf825a4f7 | ||
|
|
3afd9f5025 | ||
|
|
3cb47ee5c8 | ||
|
|
1535247e1b | ||
|
|
37dd4ebaef | ||
|
|
1e8949067b | ||
|
|
1945e94190 | ||
|
|
1ba971af24 | ||
|
|
0b5357d12a | ||
|
|
3be361b03c | ||
|
|
7681b5d326 | ||
|
|
0a35d387f7 | ||
|
|
b40efc2426 | ||
|
|
59aae7fd40 | ||
|
|
a633e4bccf | ||
|
|
b56b8099ab | ||
|
|
f9fe5c9b6c | ||
|
|
13b954d580 | ||
|
|
f53289ef1b | ||
|
|
1b3ce91582 |
No files matched your search
@@ -9,6 +9,8 @@
|
|||||||
*.class
|
*.class
|
||||||
|
|
||||||
tmp
|
tmp
|
||||||
|
mage8
|
||||||
|
adists
|
||||||
|
|
||||||
*.tar
|
*.tar
|
||||||
*.tar.*
|
*.tar.*
|
||||||
|
|||||||
Generated
+3
@@ -0,0 +1,3 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.10 (pamhyr)" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (pamhyr)" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/pamhyr.iml" filepath="$PROJECT_DIR$/.idea/pamhyr.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+14
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.10 (pamhyr)" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
<component name="PyDocumentationSettings">
|
||||||
|
<option name="format" value="PLAIN" />
|
||||||
|
<option name="myDocStringFormat" value="Plain" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -11,8 +11,7 @@
|
|||||||
\usepackage[absolute]{textpos}
|
\usepackage[absolute]{textpos}
|
||||||
\usepackage{titlesec}
|
\usepackage{titlesec}
|
||||||
\usepackage{amssymb}
|
\usepackage{amssymb}
|
||||||
\usepackage[minted,xparse,breakable]{tcolorbox}
|
\usepackage{tcolorbox}
|
||||||
\usepackage{pmboxdraw}
|
|
||||||
|
|
||||||
\usepackage{enumitem}
|
\usepackage{enumitem}
|
||||||
\setlist[enumerate]{itemsep=-0.5em}
|
\setlist[enumerate]{itemsep=-0.5em}
|
||||||
@@ -141,7 +140,7 @@
|
|||||||
\setminted[llvm]{breaklines,fontsize=\footnotesize,encoding=utf8}
|
\setminted[llvm]{breaklines,fontsize=\footnotesize,encoding=utf8}
|
||||||
|
|
||||||
%% Add box arrond of minted
|
%% Add box arrond of minted
|
||||||
\BeforeBeginEnvironment{minted}{\begin{tcolorbox}[breakable, boxsep=0pt, left=0.1cm, right=0.1cm, arc=0pt, boxrule=0.5pt, colback=white]}%
|
\BeforeBeginEnvironment{minted}{\begin{tcolorbox}[boxsep=0pt, left=0.1cm, right=0.1cm, arc=0pt, boxrule=0.5pt, colback=white]}%
|
||||||
\AfterEndEnvironment{minted}{\end{tcolorbox}}%
|
\AfterEndEnvironment{minted}{\end{tcolorbox}}%
|
||||||
|
|
||||||
\makeatletter
|
\makeatletter
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -0,0 +1,51 @@
|
|||||||
|
# Adists.py -- Pamhyr study checkers
|
||||||
|
# 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 -*-
|
||||||
|
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
from PyQt5.QtCore import QCoreApplication
|
||||||
|
|
||||||
|
from Modules import Modules
|
||||||
|
from Checker.Checker import AbstractModelChecker, STATUS
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class AdistsOutputKpChecker(AbstractModelChecker):
|
||||||
|
def __init__(self):
|
||||||
|
super(AdistsOutputKpChecker, self).__init__()
|
||||||
|
|
||||||
|
self._name = _translate("Checker", "AdisTS output Kp checker")
|
||||||
|
self._description = _translate(
|
||||||
|
"Checker", "Check output Kp"
|
||||||
|
)
|
||||||
|
self._modules = Modules.OUTPUT_KP
|
||||||
|
|
||||||
|
def run(self, study):
|
||||||
|
ok = True
|
||||||
|
nerror = 0
|
||||||
|
self._summary = "ok"
|
||||||
|
self._status = STATUS.OK
|
||||||
|
|
||||||
|
if not self.basic_check(study):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return ok
|
||||||
+3
-3
@@ -363,7 +363,7 @@ class MeshingWithMageMailleurTT(AMeshingTool):
|
|||||||
self.import_m_file(reach, m_file)
|
self.import_m_file(reach, m_file)
|
||||||
return reach
|
return reach
|
||||||
|
|
||||||
def update_rk(self, reach,
|
def update_kp(self, reach,
|
||||||
step: float = 50,
|
step: float = 50,
|
||||||
limites=[-1, -1],
|
limites=[-1, -1],
|
||||||
origin=0,
|
origin=0,
|
||||||
@@ -397,7 +397,7 @@ class MeshingWithMageMailleurTT(AMeshingTool):
|
|||||||
logger.info(
|
logger.info(
|
||||||
f"! {self._exe_path()} " +
|
f"! {self._exe_path()} " +
|
||||||
f"{st_file} {m_file} " +
|
f"{st_file} {m_file} " +
|
||||||
f"update_rk " +
|
f"update_kp " +
|
||||||
f"{str(step)} " +
|
f"{str(step)} " +
|
||||||
f"{limites[0]} {limites[1]} " +
|
f"{limites[0]} {limites[1]} " +
|
||||||
f"{directrices[0]} {directrices[1]} " +
|
f"{directrices[0]} {directrices[1]} " +
|
||||||
@@ -411,7 +411,7 @@ class MeshingWithMageMailleurTT(AMeshingTool):
|
|||||||
str,
|
str,
|
||||||
[
|
[
|
||||||
st_file, m_file,
|
st_file, m_file,
|
||||||
"update_rk", step,
|
"update_kp", step,
|
||||||
limites[0], limites[1],
|
limites[0], limites[1],
|
||||||
directrices[0], directrices[1],
|
directrices[0], directrices[1],
|
||||||
orientation, lm, linear, origin, origin_value
|
orientation, lm, linear, origin, origin_value
|
||||||
|
|||||||
@@ -0,0 +1,221 @@
|
|||||||
|
# BoundaryConditionsAdisTS.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import (
|
||||||
|
trace, timer,
|
||||||
|
old_pamhyr_date_to_timestamp,
|
||||||
|
date_iso_to_timestamp,
|
||||||
|
date_dmy_to_timestamp,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class BoundaryConditionAdisTS(SQLSubModel):
|
||||||
|
_sub_classes = []
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1,
|
||||||
|
pollutant: int = -1, status=None):
|
||||||
|
super(BoundaryConditionAdisTS, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = BoundaryConditionAdisTS._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._type = ""
|
||||||
|
self._node = None
|
||||||
|
self._pollutant = pollutant
|
||||||
|
self._data = []
|
||||||
|
self._header = []
|
||||||
|
self._types = [self.time_convert, float]
|
||||||
|
|
||||||
|
BoundaryConditionAdisTS._id_cnt = max(BoundaryConditionAdisTS._id_cnt + 1, self.id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE boundary_condition_adists(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
pollutant INTEGER NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
node INTEGER,
|
||||||
|
FOREIGN KEY(pollutant) REFERENCES Pollutants(id),
|
||||||
|
FOREIGN KEY(node) REFERENCES river_node(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE boundary_condition_data_adists(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
data0 TEXT NOT NULL,
|
||||||
|
data1 TEXT NOT NULL,
|
||||||
|
bc INTEGER,
|
||||||
|
FOREIGN KEY(bc) REFERENCES boundary_condition_adists(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, pollutant, type, node " +
|
||||||
|
"FROM boundary_condition_adists"
|
||||||
|
)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for row in table:
|
||||||
|
bc = cls(
|
||||||
|
id=row[0],
|
||||||
|
pollutant=row[1],
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
bc.type = row[2]
|
||||||
|
|
||||||
|
bc.node = None
|
||||||
|
if row[3] != -1:
|
||||||
|
bc.node = next(filter(lambda n: n.id == row[3], data["nodes"])).id
|
||||||
|
|
||||||
|
values = execute(
|
||||||
|
"SELECT data0, data1 FROM boundary_condition_data_adists " +
|
||||||
|
f"WHERE bc = '{bc.id}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write data
|
||||||
|
for v in values:
|
||||||
|
data0 = bc._types[0](v[0])
|
||||||
|
data1 = bc._types[1](v[1])
|
||||||
|
# Replace data at pos ind
|
||||||
|
bc._data.append((data0, data1))
|
||||||
|
|
||||||
|
new.append(bc)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
|
||||||
|
execute(f"DELETE FROM boundary_condition_adists WHERE id = {self.id}")
|
||||||
|
execute(f"DELETE FROM boundary_condition_data_adists WHERE bc = {self.id}")
|
||||||
|
|
||||||
|
node = -1
|
||||||
|
if self._node is not None:
|
||||||
|
node = self._node
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"boundary_condition_adists(id, pollutant, type, node) " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, {self._pollutant}, " +
|
||||||
|
f"'{self._db_format(self._type)}', {node}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
for d in self._data:
|
||||||
|
data0 = self._db_format(str(d[0]))
|
||||||
|
data1 = self._db_format(str(d[1]))
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"boundary_condition_data_adists(data0, data1, bc) " +
|
||||||
|
f"VALUES ('{data0}', {data1}, {self.id})"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def time_convert(cls, data):
|
||||||
|
if type(data) is str:
|
||||||
|
if data.count("-") == 2:
|
||||||
|
return date_iso_to_timestamp(data)
|
||||||
|
if data.count("/") == 2:
|
||||||
|
return date_dmy_to_timestamp(data)
|
||||||
|
if data.count(":") == 3:
|
||||||
|
return old_pamhyr_date_to_timestamp(data)
|
||||||
|
if data.count(":") == 2:
|
||||||
|
return old_pamhyr_date_to_timestamp("00:" + data)
|
||||||
|
if data.count(".") == 1:
|
||||||
|
return round(float(data))
|
||||||
|
|
||||||
|
return int(data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def node(self):
|
||||||
|
return self._node
|
||||||
|
|
||||||
|
@node.setter
|
||||||
|
def node(self, node):
|
||||||
|
self._node = node
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def header(self):
|
||||||
|
return self._header.copy()
|
||||||
|
|
||||||
|
@header.setter
|
||||||
|
def header(self, header):
|
||||||
|
self._header = header
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pollutant(self):
|
||||||
|
return self._pollutant
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
@type.setter
|
||||||
|
def type(self, type):
|
||||||
|
self._type = type
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data(self):
|
||||||
|
return self._data.copy()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# BoundaryConditionsAdisTSList.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 copy import copy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrList import PamhyrModelList
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
from Model.BoundaryConditionsAdisTS.BoundaryConditionAdisTS import BoundaryConditionAdisTS
|
||||||
|
|
||||||
|
class BoundaryConditionsAdisTSList(PamhyrModelList):
|
||||||
|
_sub_classes = [
|
||||||
|
BoundaryConditionAdisTS,
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = cls(status=data['status'])
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
new._lst = BoundaryConditionAdisTS._db_load(
|
||||||
|
execute, data
|
||||||
|
)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute("DELETE FROM boundary_condition_adists")
|
||||||
|
execute("DELETE FROM boundary_condition_data_adists")
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
for bc in self._lst:
|
||||||
|
bc._db_save(execute, data=data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def new(self, index, pollutant):
|
||||||
|
n = BoundaryConditionAdisTS(pollutant=pollutant, status=self._status)
|
||||||
|
self._lst.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
@property
|
||||||
|
def BCs_AdisTS_List(self):
|
||||||
|
return self.lst
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
# D90AdisTS.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
from tools import trace, timer, old_pamhyr_date_to_timestamp
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
from Model.D90AdisTS.D90AdisTSSpec import D90AdisTSSpec
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class D90AdisTS(SQLSubModel):
|
||||||
|
_sub_classes = [
|
||||||
|
D90AdisTSSpec,
|
||||||
|
]
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, name: str = "default",
|
||||||
|
status=None):
|
||||||
|
super(D90AdisTS, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = D90AdisTS._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._name = name
|
||||||
|
self._d90 = None
|
||||||
|
self._enabled = True
|
||||||
|
self._data = []
|
||||||
|
|
||||||
|
D90AdisTS._id_cnt = max(
|
||||||
|
D90AdisTS._id_cnt + 1,
|
||||||
|
self.id
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE d90_adists(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
d90 REAL NOT NULL,
|
||||||
|
enabled BOOLEAN NOT NULL
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
if major == minor == "0":
|
||||||
|
if int(release) < 6:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, name, d90, enabled " +
|
||||||
|
"FROM d90_adists"
|
||||||
|
)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for row in table:
|
||||||
|
d90_id = row[0]
|
||||||
|
name = row[1]
|
||||||
|
d90 = row[2]
|
||||||
|
enabled = (row[3] == 1)
|
||||||
|
|
||||||
|
D90 = cls(
|
||||||
|
id=d90_id,
|
||||||
|
name=name,
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
D90.d90 = d90
|
||||||
|
D90.enabled = enabled
|
||||||
|
|
||||||
|
data['d90_default_id'] = d90_id
|
||||||
|
D90._data = D90AdisTSSpec._db_load(execute, data)
|
||||||
|
|
||||||
|
new.append(D90)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute(f"DELETE FROM d90_adists WHERE id = {self.id}")
|
||||||
|
|
||||||
|
d90 = -1.
|
||||||
|
if self.d90 is not None:
|
||||||
|
d90 = self.d90
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"d90_adists(" +
|
||||||
|
"id, name, d90, enabled" +
|
||||||
|
") " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, '{self._db_format(self._name)}', " +
|
||||||
|
f"{d90}, {self._enabled}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
data['d90_default_id'] = self.id
|
||||||
|
execute(
|
||||||
|
"DELETE FROM d90_spec " +
|
||||||
|
f"WHERE d90_default = {self.id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
for d90_spec in self._data:
|
||||||
|
d90_spec._db_save(execute, data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, name):
|
||||||
|
self._name = name
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def d90(self):
|
||||||
|
return self._d90
|
||||||
|
|
||||||
|
@d90.setter
|
||||||
|
def d90(self, d90):
|
||||||
|
self._d90 = d90
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def new(self, index):
|
||||||
|
n = D90AdisTSSpec(status=self._status)
|
||||||
|
self._data.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
def delete(self, data):
|
||||||
|
self._data = list(
|
||||||
|
filter(
|
||||||
|
lambda x: x not in data,
|
||||||
|
self._data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def delete_i(self, indexes):
|
||||||
|
for ind in indexes:
|
||||||
|
del self._data[ind]
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def insert(self, index, data):
|
||||||
|
self._data.insert(index, data)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# D90AdisTSList.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 copy import copy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrList import PamhyrModelList
|
||||||
|
from Model.D90AdisTS.D90AdisTS import D90AdisTS
|
||||||
|
|
||||||
|
class D90AdisTSList(PamhyrModelList):
|
||||||
|
_sub_classes = [
|
||||||
|
D90AdisTS,
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = cls(status=data['status'])
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
new._lst = D90AdisTS._db_load(
|
||||||
|
execute, data
|
||||||
|
)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute("DELETE FROM d90_adists")
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
for d90 in self._lst:
|
||||||
|
d90._db_save(execute, data=data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def new(self, index):
|
||||||
|
n = D90AdisTS(status=self._status)
|
||||||
|
self._lst.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
@property
|
||||||
|
def D90_AdisTS_List(self):
|
||||||
|
return self.lst
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
# D90AdisTSSpec.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class D90AdisTSSpec(SQLSubModel):
|
||||||
|
_sub_classes = [
|
||||||
|
]
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, name: str = "",
|
||||||
|
status=None):
|
||||||
|
super(D90AdisTSSpec, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = D90AdisTSSpec._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._name_section = name
|
||||||
|
self._reach = None
|
||||||
|
self._start_kp = None
|
||||||
|
self._end_kp = None
|
||||||
|
self._d90 = None
|
||||||
|
self._enabled = True
|
||||||
|
|
||||||
|
D90AdisTSSpec._id_cnt = max(D90AdisTSSpec._id_cnt + 1, self.id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE d90_spec(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
d90_default INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
reach INTEGER NOT NULL,
|
||||||
|
start_kp REAL NOT NULL,
|
||||||
|
end_kp REAL NOT NULL,
|
||||||
|
d90 REAL NOT NULL,
|
||||||
|
enabled BOOLEAN NOT NULL,
|
||||||
|
FOREIGN KEY(d90_default) REFERENCES d90_adists(id),
|
||||||
|
FOREIGN KEY(reach) REFERENCES river_reach(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
if major == minor == "0":
|
||||||
|
if int(release) < 6:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, d90_default, name, reach, start_kp, end_kp, " +
|
||||||
|
"d90, enabled " +
|
||||||
|
"FROM d90_spec " +
|
||||||
|
f"WHERE d90_default = {data['d90_default_id']} "
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in table:
|
||||||
|
id = row[0]
|
||||||
|
name = row[2]
|
||||||
|
reach = row[3]
|
||||||
|
start_kp = row[4]
|
||||||
|
end_kp = row[5]
|
||||||
|
d90 = row[6]
|
||||||
|
enabled = (row[7] == 1)
|
||||||
|
|
||||||
|
new_spec = cls(
|
||||||
|
id=id,
|
||||||
|
name=name,
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
new_spec.reach = reach
|
||||||
|
new_spec.start_kp = start_kp
|
||||||
|
new_spec.end_kp = end_kp
|
||||||
|
new_spec.d90 = d90
|
||||||
|
new_spec.enabled = enabled
|
||||||
|
|
||||||
|
new.append(new_spec)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
d90_default = data['d90_default_id']
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"d90_spec(id, d90_default, name, reach, " +
|
||||||
|
"start_kp, end_kp, d90, enabled) " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, " +
|
||||||
|
f"{d90_default}, " +
|
||||||
|
f"'{self._db_format(self._name_section)}', " +
|
||||||
|
f"{self._reach}, " +
|
||||||
|
f"{self._start_kp}, " +
|
||||||
|
f"{self._end_kp}, " +
|
||||||
|
f"{self._d90}, " +
|
||||||
|
f"{self._enabled}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name_section
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, name):
|
||||||
|
self._name_section = name
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reach(self):
|
||||||
|
return self._reach
|
||||||
|
|
||||||
|
@reach.setter
|
||||||
|
def reach(self, reach):
|
||||||
|
self._reach = reach
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start_kp(self):
|
||||||
|
return self._start_kp
|
||||||
|
|
||||||
|
@start_kp.setter
|
||||||
|
def start_kp(self, start_kp):
|
||||||
|
self._start_kp = start_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_kp(self):
|
||||||
|
return self._end_kp
|
||||||
|
|
||||||
|
@end_kp.setter
|
||||||
|
def end_kp(self, end_kp):
|
||||||
|
self._end_kp = end_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def d90(self):
|
||||||
|
return self._d90
|
||||||
|
|
||||||
|
@d90.setter
|
||||||
|
def d90(self, d90):
|
||||||
|
self._d90 = d90
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
# DIFAdisTS.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
from tools import trace, timer, old_pamhyr_date_to_timestamp
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
from Model.DIFAdisTS.DIFAdisTSSpec import DIFAdisTSSpec
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class DIFAdisTS(SQLSubModel):
|
||||||
|
_sub_classes = [
|
||||||
|
DIFAdisTSSpec,
|
||||||
|
]
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, name: str = "default",
|
||||||
|
status=None):
|
||||||
|
super(DIFAdisTS, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = DIFAdisTS._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._name = name
|
||||||
|
self._method = None
|
||||||
|
self._dif = None
|
||||||
|
self._b = None
|
||||||
|
self._c = None
|
||||||
|
self._enabled = True
|
||||||
|
self._types = ["iwasa", "fisher", "elder", "constante", "generique"]
|
||||||
|
self._data = []
|
||||||
|
|
||||||
|
DIFAdisTS._id_cnt = max(
|
||||||
|
DIFAdisTS._id_cnt + 1,
|
||||||
|
self.id
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE dif_adists(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
method TEXT NOT NULL,
|
||||||
|
dif REAL NOT NULL,
|
||||||
|
b REAL,
|
||||||
|
c REAL,
|
||||||
|
enabled BOOLEAN NOT NULL
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
if major == minor == "0":
|
||||||
|
if int(release) < 6:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, name, method, dif, b, c, enabled " +
|
||||||
|
"FROM dif_adists"
|
||||||
|
)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for row in table:
|
||||||
|
dif_id = row[0]
|
||||||
|
name = row[1]
|
||||||
|
method = row[2]
|
||||||
|
dif = row[3]
|
||||||
|
b = row[4]
|
||||||
|
c = row[5]
|
||||||
|
enabled = (row[6] == 1)
|
||||||
|
|
||||||
|
DIF = cls(
|
||||||
|
id=dif_id,
|
||||||
|
name=name,
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
DIF.method = method
|
||||||
|
DIF.dif = dif
|
||||||
|
DIF.b = b
|
||||||
|
DIF.c = c
|
||||||
|
DIF.enabled = enabled
|
||||||
|
|
||||||
|
data['dif_default_id'] = dif_id
|
||||||
|
DIF._data = DIFAdisTSSpec._db_load(execute, data)
|
||||||
|
|
||||||
|
new.append(DIF)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute(f"DELETE FROM dif_adists WHERE id = {self.id}")
|
||||||
|
|
||||||
|
method = ""
|
||||||
|
if self.method is not None:
|
||||||
|
method = self.method
|
||||||
|
|
||||||
|
dif = -1.
|
||||||
|
if self.dif is not None:
|
||||||
|
dif = self.dif
|
||||||
|
|
||||||
|
b = -1.
|
||||||
|
if self.b is not None:
|
||||||
|
b = self.b
|
||||||
|
|
||||||
|
c = -1.
|
||||||
|
if self.dif is not None:
|
||||||
|
c = self.c
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"dif_adists(" +
|
||||||
|
"id, name, method, dif, b, c, enabled" +
|
||||||
|
") " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, '{self._db_format(self._name)}', " +
|
||||||
|
f"'{self._db_format(self._method)}', " +
|
||||||
|
f"{dif}, {b}, {c}, {self._enabled}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
data['dif_default_id'] = self.id
|
||||||
|
execute(
|
||||||
|
"DELETE FROM dif_spec " +
|
||||||
|
f"WHERE dif_default = {self.id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
for dif_spec in self._data:
|
||||||
|
dif_spec._db_save(execute, data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, name):
|
||||||
|
self._name = name
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def method(self):
|
||||||
|
return self._method
|
||||||
|
|
||||||
|
@method.setter
|
||||||
|
def method(self, method):
|
||||||
|
self._method = method
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def types(self):
|
||||||
|
return self._types
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dif(self):
|
||||||
|
return self._dif
|
||||||
|
|
||||||
|
@dif.setter
|
||||||
|
def dif(self, dif):
|
||||||
|
self._dif = dif
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def b(self):
|
||||||
|
return self._b
|
||||||
|
|
||||||
|
@b.setter
|
||||||
|
def b(self, b):
|
||||||
|
self._b = b
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def c(self):
|
||||||
|
return self._c
|
||||||
|
|
||||||
|
@c.setter
|
||||||
|
def c(self, c):
|
||||||
|
self._c = c
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def new(self, index):
|
||||||
|
n = DIFAdisTSSpec(status=self._status)
|
||||||
|
self._data.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
def delete(self, data):
|
||||||
|
self._data = list(
|
||||||
|
filter(
|
||||||
|
lambda x: x not in data,
|
||||||
|
self._data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def delete_i(self, indexes):
|
||||||
|
for ind in indexes:
|
||||||
|
del self._data[ind]
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def insert(self, index, data):
|
||||||
|
self._data.insert(index, data)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# DIFAdisTSList.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 copy import copy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrList import PamhyrModelList
|
||||||
|
from Model.DIFAdisTS.DIFAdisTS import DIFAdisTS
|
||||||
|
|
||||||
|
class DIFAdisTSList(PamhyrModelList):
|
||||||
|
_sub_classes = [
|
||||||
|
DIFAdisTS,
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = cls(status=data['status'])
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
new._lst = DIFAdisTS._db_load(
|
||||||
|
execute, data
|
||||||
|
)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute("DELETE FROM dif_adists")
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
for dif in self._lst:
|
||||||
|
dif._db_save(execute, data=data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def new(self, index):
|
||||||
|
n = DIFAdisTS(status=self._status)
|
||||||
|
self._lst.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
@property
|
||||||
|
def DIF_AdisTS_List(self):
|
||||||
|
return self.lst
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
# DIFAdisTSSpec.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class DIFAdisTSSpec(SQLSubModel):
|
||||||
|
_sub_classes = [
|
||||||
|
]
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, method: str = "",
|
||||||
|
status=None):
|
||||||
|
super(DIFAdisTSSpec, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = DIFAdisTSSpec._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._method = method
|
||||||
|
self._reach = None
|
||||||
|
self._start_kp = None
|
||||||
|
self._end_kp = None
|
||||||
|
self._dif = None
|
||||||
|
self._b = None
|
||||||
|
self._c = None
|
||||||
|
self._enabled = True
|
||||||
|
|
||||||
|
DIFAdisTSSpec._id_cnt = max(DIFAdisTSSpec._id_cnt + 1, self.id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE dif_spec(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
dif_default INTEGER NOT NULL,
|
||||||
|
method TEXT NOT NULL,
|
||||||
|
reach INTEGER NOT NULL,
|
||||||
|
start_kp REAL NOT NULL,
|
||||||
|
end_kp REAL NOT NULL,
|
||||||
|
dif REAL NOT NULL,
|
||||||
|
b REAL,
|
||||||
|
c REAL,
|
||||||
|
enabled BOOLEAN NOT NULL,
|
||||||
|
FOREIGN KEY(dif_default) REFERENCES dif_adists(id),
|
||||||
|
FOREIGN KEY(reach) REFERENCES river_reach(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
if major == minor == "0":
|
||||||
|
if int(release) < 6:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, dif_default, method, reach, start_kp, end_kp, " +
|
||||||
|
"dif, b, c, enabled " +
|
||||||
|
"FROM dif_spec " +
|
||||||
|
f"WHERE dif_default = {data['dif_default_id']} "
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in table:
|
||||||
|
id = row[0]
|
||||||
|
method = row[2]
|
||||||
|
reach = row[3]
|
||||||
|
start_kp = row[4]
|
||||||
|
end_kp = row[5]
|
||||||
|
dif = row[6]
|
||||||
|
b = row[7]
|
||||||
|
c = row[8]
|
||||||
|
enabled = (row[9] == 1)
|
||||||
|
|
||||||
|
new_spec = cls(
|
||||||
|
id=id,
|
||||||
|
method=method,
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
new_spec.reach = reach
|
||||||
|
new_spec.start_kp = start_kp
|
||||||
|
new_spec.end_kp = end_kp
|
||||||
|
new_spec.dif = dif
|
||||||
|
new_spec.b = b
|
||||||
|
new_spec.c = c
|
||||||
|
new_spec.enabled = enabled
|
||||||
|
|
||||||
|
new.append(new_spec)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
dif_default = data['dif_default_id']
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"dif_spec(id, dif_default, method, reach, " +
|
||||||
|
"start_kp, end_kp, dif, b, c, enabled) " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, " +
|
||||||
|
f"{dif_default}, " +
|
||||||
|
f"'{self._db_format(self._method)}', " +
|
||||||
|
f"{self._reach}, " +
|
||||||
|
f"{self._start_kp}, " +
|
||||||
|
f"{self._end_kp}, " +
|
||||||
|
f"{self._dif}, " +
|
||||||
|
f"{self._b}, " +
|
||||||
|
f"{self._c}, " +
|
||||||
|
f"{self._enabled}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def method(self):
|
||||||
|
return self._method
|
||||||
|
|
||||||
|
@method.setter
|
||||||
|
def method(self, method):
|
||||||
|
self._method = method
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reach(self):
|
||||||
|
return self._reach
|
||||||
|
|
||||||
|
@reach.setter
|
||||||
|
def reach(self, reach):
|
||||||
|
self._reach = reach
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start_kp(self):
|
||||||
|
return self._start_kp
|
||||||
|
|
||||||
|
@start_kp.setter
|
||||||
|
def start_kp(self, start_kp):
|
||||||
|
self._start_kp = start_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_kp(self):
|
||||||
|
return self._end_kp
|
||||||
|
|
||||||
|
@end_kp.setter
|
||||||
|
def end_kp(self, end_kp):
|
||||||
|
self._end_kp = end_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dif(self):
|
||||||
|
return self._dif
|
||||||
|
|
||||||
|
@dif.setter
|
||||||
|
def dif(self, dif):
|
||||||
|
self._dif = dif
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def b(self):
|
||||||
|
return self._b
|
||||||
|
|
||||||
|
@b.setter
|
||||||
|
def b(self, b):
|
||||||
|
self._b = b
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def c(self):
|
||||||
|
return self._c
|
||||||
|
|
||||||
|
@c.setter
|
||||||
|
def c(self, c):
|
||||||
|
self._c = c
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -43,8 +43,8 @@ class Friction(SQLSubModel):
|
|||||||
|
|
||||||
self._name = name
|
self._name = name
|
||||||
self._edge = None
|
self._edge = None
|
||||||
self._begin_rk = 0.0
|
self._begin_kp = 0.0
|
||||||
self._end_rk = 0.0
|
self._end_kp = 0.0
|
||||||
self._begin_strickler = None
|
self._begin_strickler = None
|
||||||
self._end_strickler = None
|
self._end_strickler = None
|
||||||
|
|
||||||
@@ -54,8 +54,8 @@ class Friction(SQLSubModel):
|
|||||||
CREATE TABLE friction(
|
CREATE TABLE friction(
|
||||||
id INTEGER NOT NULL PRIMARY KEY,
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
ind INTEGER NOT NULL,
|
ind INTEGER NOT NULL,
|
||||||
begin_rk REAL NOT NULL,
|
begin_kp REAL NOT NULL,
|
||||||
end_rk REAL NOT NULL,
|
end_kp REAL NOT NULL,
|
||||||
reach INTEGER NOT NULL,
|
reach INTEGER NOT NULL,
|
||||||
begin_strickler INTEGER NOT NULL,
|
begin_strickler INTEGER NOT NULL,
|
||||||
end_strickler INTEGER NOT NULL,
|
end_strickler INTEGER NOT NULL,
|
||||||
@@ -69,13 +69,6 @@ class Friction(SQLSubModel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_update(cls, execute, version):
|
def _db_update(cls, execute, version):
|
||||||
major, minor, release = version.strip().split(".")
|
|
||||||
if major == minor == "0":
|
|
||||||
if int(release) < 11:
|
|
||||||
execute("ALTER TABLE friction " +
|
|
||||||
"RENAME COLUMN begin_kp TO begin_rk")
|
|
||||||
execute("ALTER TABLE friction RENAME COLUMN end_kp TO end_rk")
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -87,7 +80,7 @@ class Friction(SQLSubModel):
|
|||||||
stricklers = data["stricklers"].stricklers
|
stricklers = data["stricklers"].stricklers
|
||||||
|
|
||||||
table = execute(
|
table = execute(
|
||||||
"SELECT id, ind, begin_rk, end_rk, " +
|
"SELECT id, ind, begin_kp, end_kp, " +
|
||||||
"begin_strickler, end_strickler " +
|
"begin_strickler, end_strickler " +
|
||||||
f"FROM friction WHERE reach = {reach.id}"
|
f"FROM friction WHERE reach = {reach.id}"
|
||||||
)
|
)
|
||||||
@@ -109,8 +102,8 @@ class Friction(SQLSubModel):
|
|||||||
# Create friction
|
# Create friction
|
||||||
sec = cls(status=status)
|
sec = cls(status=status)
|
||||||
sec.edge = reach
|
sec.edge = reach
|
||||||
sec.begin_rk = row[2]
|
sec.begin_kp = row[2]
|
||||||
sec.end_rk = row[3]
|
sec.end_kp = row[3]
|
||||||
sec.begin_strickler = bs
|
sec.begin_strickler = bs
|
||||||
sec.end_strickler = es
|
sec.end_strickler = es
|
||||||
|
|
||||||
@@ -131,11 +124,11 @@ class Friction(SQLSubModel):
|
|||||||
|
|
||||||
execute(
|
execute(
|
||||||
"INSERT INTO " +
|
"INSERT INTO " +
|
||||||
"friction(id, ind, begin_rk, end_rk, " +
|
"friction(id, ind, begin_kp, end_kp, " +
|
||||||
"reach, begin_strickler, end_strickler) " +
|
"reach, begin_strickler, end_strickler) " +
|
||||||
"VALUES (" +
|
"VALUES (" +
|
||||||
f"{self.id}, {ind}, " +
|
f"{self.id}, {ind}, " +
|
||||||
f"{self._begin_rk}, {self._end_rk}, " +
|
f"{self._begin_kp}, {self._end_kp}, " +
|
||||||
f"{self._edge.id}, " +
|
f"{self._edge.id}, " +
|
||||||
f"{b_s_id}, {e_s_id}" +
|
f"{b_s_id}, {e_s_id}" +
|
||||||
")"
|
")"
|
||||||
@@ -164,10 +157,10 @@ class Friction(SQLSubModel):
|
|||||||
def edge(self, edge):
|
def edge(self, edge):
|
||||||
self._edge = edge
|
self._edge = edge
|
||||||
if (edge is not None and
|
if (edge is not None and
|
||||||
self._begin_rk == 0.0 and
|
self._begin_kp == 0.0 and
|
||||||
self._end_rk == 0.0):
|
self._end_kp == 0.0):
|
||||||
self._begin_rk = self._edge.reach.get_rk_min()
|
self._begin_kp = self._edge.reach.get_kp_min()
|
||||||
self._end_rk = self._edge.reach.get_rk_max()
|
self._end_kp = self._edge.reach.get_kp_max()
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
def has_edge(self):
|
def has_edge(self):
|
||||||
@@ -183,45 +176,45 @@ class Friction(SQLSubModel):
|
|||||||
return self.has_edge() and self.has_coefficient()
|
return self.has_edge() and self.has_coefficient()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def begin_rk(self):
|
def begin_kp(self):
|
||||||
return self._begin_rk
|
return self._begin_kp
|
||||||
|
|
||||||
@begin_rk.setter
|
@begin_kp.setter
|
||||||
def begin_rk(self, begin_rk):
|
def begin_kp(self, begin_kp):
|
||||||
if self._edge is None:
|
if self._edge is None:
|
||||||
self._begin_rk = begin_rk
|
self._begin_kp = begin_kp
|
||||||
else:
|
else:
|
||||||
_min = self._edge.reach.get_rk_min()
|
_min = self._edge.reach.get_kp_min()
|
||||||
_max = self._edge.reach.get_rk_max()
|
_max = self._edge.reach.get_kp_max()
|
||||||
|
|
||||||
if _min <= begin_rk <= _max:
|
if _min <= begin_kp <= _max:
|
||||||
self._begin_rk = begin_rk
|
self._begin_kp = begin_kp
|
||||||
|
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def end_rk(self):
|
def end_kp(self):
|
||||||
return self._end_rk
|
return self._end_kp
|
||||||
|
|
||||||
@end_rk.setter
|
@end_kp.setter
|
||||||
def end_rk(self, end_rk):
|
def end_kp(self, end_kp):
|
||||||
if self._edge is None:
|
if self._edge is None:
|
||||||
self._end_rk = end_rk
|
self._end_kp = end_kp
|
||||||
else:
|
else:
|
||||||
_min = self._edge.reach.get_rk_min()
|
_min = self._edge.reach.get_kp_min()
|
||||||
_max = self._edge.reach.get_rk_max()
|
_max = self._edge.reach.get_kp_max()
|
||||||
|
|
||||||
if _min <= end_rk <= _max:
|
if _min <= end_kp <= _max:
|
||||||
self._end_rk = end_rk
|
self._end_kp = end_kp
|
||||||
|
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
def __contains__(self, rk):
|
def __contains__(self, kp):
|
||||||
return self.contains_rk(rk)
|
return self.contains_kp(kp)
|
||||||
|
|
||||||
def contains_rk(self, rk):
|
def contains_kp(self, kp):
|
||||||
return (
|
return (
|
||||||
self._begin_rk <= rk <= self._end_rk
|
self._begin_kp <= kp <= self._end_kp
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class FrictionList(PamhyrModelList):
|
|||||||
logger.info(f"Update friction TABLE from {version}")
|
logger.info(f"Update friction TABLE from {version}")
|
||||||
cls._db_update_0_0_1(execute, version)
|
cls._db_update_0_0_1(execute, version)
|
||||||
|
|
||||||
return cls._update_submodel(execute, version)
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_load(cls, execute, data=None):
|
def _db_load(cls, execute, data=None):
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class Profile(object):
|
|||||||
_id_cnt = 0
|
_id_cnt = 0
|
||||||
|
|
||||||
def __init__(self, id: int = -1, num: int = 0,
|
def __init__(self, id: int = -1, num: int = 0,
|
||||||
rk: float = 0.0, name: str = "",
|
kp: float = 0.0, name: str = "",
|
||||||
code1: int = 0, code2: int = 0,
|
code1: int = 0, code2: int = 0,
|
||||||
_type: str = "", reach=None,
|
_type: str = "", reach=None,
|
||||||
status=None):
|
status=None):
|
||||||
@@ -49,7 +49,7 @@ class Profile(object):
|
|||||||
self._num = int(num)
|
self._num = int(num)
|
||||||
self._code1 = int(code1)
|
self._code1 = int(code1)
|
||||||
self._code2 = int(code2)
|
self._code2 = int(code2)
|
||||||
self._rk = float(rk)
|
self._kp = float(kp)
|
||||||
self._name = str(name)
|
self._name = str(name)
|
||||||
self._reach = reach
|
self._reach = reach
|
||||||
self._sl = None
|
self._sl = None
|
||||||
@@ -136,16 +136,16 @@ class Profile(object):
|
|||||||
return len(self.points)
|
return len(self.points)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rk(self):
|
def kp(self):
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
Kilometer point.
|
Kilometer point.
|
||||||
"""
|
"""
|
||||||
return self._rk
|
return self._kp
|
||||||
|
|
||||||
@rk.setter
|
@kp.setter
|
||||||
def rk(self, value: float):
|
def kp(self, value: float):
|
||||||
self._rk = float(value)
|
self._kp = float(value)
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
def __init__(self,
|
def __init__(self,
|
||||||
id: int = -1,
|
id: int = -1,
|
||||||
name: str = "",
|
name: str = "",
|
||||||
rk: float = 0.,
|
kp: float = 0.,
|
||||||
reach=None,
|
reach=None,
|
||||||
num=0,
|
num=0,
|
||||||
nb_point: int = 0,
|
nb_point: int = 0,
|
||||||
@@ -53,7 +53,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
num: The number of this profile
|
num: The number of this profile
|
||||||
code1: The interpolation code 1
|
code1: The interpolation code 1
|
||||||
code2: The interpolation code 2
|
code2: The interpolation code 2
|
||||||
rk: Kilometer point
|
kp: Kilometer point
|
||||||
name: The name of profile
|
name: The name of profile
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -63,7 +63,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
id=id,
|
id=id,
|
||||||
num=num,
|
num=num,
|
||||||
name=name,
|
name=name,
|
||||||
rk=rk,
|
kp=kp,
|
||||||
code1=code1, code2=code2,
|
code1=code1, code2=code2,
|
||||||
_type="XYZ",
|
_type="XYZ",
|
||||||
reach=reach,
|
reach=reach,
|
||||||
@@ -78,7 +78,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
ind INTEGER NOT NULL,
|
ind INTEGER NOT NULL,
|
||||||
name TEXT,
|
name TEXT,
|
||||||
reach INTEGER NOT NULL,
|
reach INTEGER NOT NULL,
|
||||||
rk REAL NOT NULL,
|
kp REAL NOT NULL,
|
||||||
num INTEGER NOT NULL,
|
num INTEGER NOT NULL,
|
||||||
code1 INTEGER NOT NULL,
|
code1 INTEGER NOT NULL,
|
||||||
code2 INTEGER NOT NULL,
|
code2 INTEGER NOT NULL,
|
||||||
@@ -94,8 +94,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
def _db_update(cls, execute, version):
|
def _db_update(cls, execute, version):
|
||||||
major, minor, release = version.strip().split(".")
|
major, minor, release = version.strip().split(".")
|
||||||
if major == minor == "0":
|
if major == minor == "0":
|
||||||
rl = int(release)
|
if int(release) < 2:
|
||||||
if rl < 2:
|
|
||||||
execute(
|
execute(
|
||||||
"""
|
"""
|
||||||
ALTER TABLE geometry_profileXYZ
|
ALTER TABLE geometry_profileXYZ
|
||||||
@@ -104,14 +103,6 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
if rl < 11:
|
|
||||||
execute(
|
|
||||||
"""
|
|
||||||
ALTER TABLE geometry_profileXYZ
|
|
||||||
RENAME COLUMN kp TO rk
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
return cls._update_submodel(execute, version)
|
return cls._update_submodel(execute, version)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -121,7 +112,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
reach = data["reach"]
|
reach = data["reach"]
|
||||||
|
|
||||||
table = execute(
|
table = execute(
|
||||||
"SELECT id, ind, name, rk, num, code1, code2, sl " +
|
"SELECT id, ind, name, kp, num, code1, code2, sl " +
|
||||||
"FROM geometry_profileXYZ " +
|
"FROM geometry_profileXYZ " +
|
||||||
f"WHERE reach = {reach.id}"
|
f"WHERE reach = {reach.id}"
|
||||||
)
|
)
|
||||||
@@ -130,7 +121,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
id = row[0]
|
id = row[0]
|
||||||
ind = row[1]
|
ind = row[1]
|
||||||
name = row[2]
|
name = row[2]
|
||||||
rk = row[3]
|
kp = row[3]
|
||||||
num = row[5]
|
num = row[5]
|
||||||
code1 = row[5]
|
code1 = row[5]
|
||||||
code2 = row[6]
|
code2 = row[6]
|
||||||
@@ -138,7 +129,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
|
|
||||||
new = cls(
|
new = cls(
|
||||||
id=id, num=num,
|
id=id, num=num,
|
||||||
name=name, rk=rk,
|
name=name, kp=kp,
|
||||||
code1=code1, code2=code2,
|
code1=code1, code2=code2,
|
||||||
reach=reach,
|
reach=reach,
|
||||||
status=status
|
status=status
|
||||||
@@ -168,10 +159,10 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
sql = (
|
sql = (
|
||||||
"INSERT OR REPLACE INTO " +
|
"INSERT OR REPLACE INTO " +
|
||||||
"geometry_profileXYZ(id, ind, name, reach, " +
|
"geometry_profileXYZ(id, ind, name, reach, " +
|
||||||
"rk, num, code1, code2, sl) " +
|
"kp, num, code1, code2, sl) " +
|
||||||
"VALUES (" +
|
"VALUES (" +
|
||||||
f"{self.id}, {ind}, '{self._db_format(self._name)}', " +
|
f"{self.id}, {ind}, '{self._db_format(self._name)}', " +
|
||||||
f"{self.reach.id}, {self.rk}, {self.num}, " +
|
f"{self.reach.id}, {self.kp}, {self.num}, " +
|
||||||
f"{self.code1}, {self.code1}, {sl}" +
|
f"{self.code1}, {self.code1}, {sl}" +
|
||||||
")"
|
")"
|
||||||
)
|
)
|
||||||
@@ -196,19 +187,19 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
try:
|
try:
|
||||||
if len(header) == 0:
|
if len(header) == 0:
|
||||||
name = data[0]
|
name = data[0]
|
||||||
rk = data[1]
|
kp = data[1]
|
||||||
reach = data[2]
|
reach = data[2]
|
||||||
status = data[3]
|
status = data[3]
|
||||||
|
|
||||||
profile = cls(
|
profile = cls(
|
||||||
id=-1,
|
id=-1,
|
||||||
name=name,
|
name=name,
|
||||||
rk=rk,
|
kp=kp,
|
||||||
reach=reach,
|
reach=reach,
|
||||||
status=status
|
status=status
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
valid_header = {'name', 'reach', 'rk', 'status'}
|
valid_header = {'name', 'reach', 'kp', 'status'}
|
||||||
d = {}
|
d = {}
|
||||||
for i, v in enumerate(data):
|
for i, v in enumerate(data):
|
||||||
h = header[i].strip().lower().split(' ')[0]
|
h = header[i].strip().lower().split(' ')[0]
|
||||||
@@ -332,7 +323,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
logger.debug(f"{e}")
|
logger.debug(f"{e}")
|
||||||
raise IndexError(
|
raise IndexError(
|
||||||
f"Invalid point name: {name} " +
|
f"Invalid point name: {name} " +
|
||||||
f"for profile ({self.id}) rk = {self.rk}"
|
f"for profile ({self.id}) kp = {self.kp}"
|
||||||
)
|
)
|
||||||
|
|
||||||
def has_standard_named_points(self):
|
def has_standard_named_points(self):
|
||||||
|
|||||||
+46
-46
@@ -141,10 +141,10 @@ class Reach(SQLSubModel):
|
|||||||
def profiles(self, profiles):
|
def profiles(self, profiles):
|
||||||
self._profiles = profiles
|
self._profiles = profiles
|
||||||
|
|
||||||
def get_profiles_from_rk(self, rk):
|
def get_profiles_from_kp(self, kp):
|
||||||
return list(
|
return list(
|
||||||
filter(
|
filter(
|
||||||
lambda p: p.rk == rk, self.profiles
|
lambda p: p.kp == kp, self.profiles
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -335,18 +335,18 @@ class Reach(SQLSubModel):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_rk(self):
|
def get_kp(self):
|
||||||
"""List of profiles rk
|
"""List of profiles kp
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of profiles rk
|
List of profiles kp
|
||||||
"""
|
"""
|
||||||
return [profile.rk for profile in self.profiles]
|
return [profile.kp for profile in self.profiles]
|
||||||
|
|
||||||
def get_rk_complete_profiles(self):
|
def get_kp_complete_profiles(self):
|
||||||
return list(
|
return list(
|
||||||
map(
|
map(
|
||||||
lambda profile: profile.rk,
|
lambda profile: profile.kp,
|
||||||
filter(
|
filter(
|
||||||
lambda profile: len(profile) > 0,
|
lambda profile: len(profile) > 0,
|
||||||
self.profiles
|
self.profiles
|
||||||
@@ -354,41 +354,41 @@ class Reach(SQLSubModel):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_rk_min(self):
|
def get_kp_min(self):
|
||||||
if len(self.get_rk()) > 0:
|
if len(self.get_kp()) > 0:
|
||||||
return min(self.get_rk())
|
return min(self.get_kp())
|
||||||
else:
|
else:
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
def get_rk_max(self):
|
def get_kp_max(self):
|
||||||
if len(self.get_rk()) > 0:
|
if len(self.get_kp()) > 0:
|
||||||
return max(self.get_rk())
|
return max(self.get_kp())
|
||||||
else:
|
else:
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
def inter_profiles_rk(self):
|
def inter_profiles_kp(self):
|
||||||
profiles = sorted(self.profiles, key=lambda p: p.rk)
|
profiles = sorted(self.profiles, key=lambda p: p.kp)
|
||||||
first = profiles[0]
|
first = profiles[0]
|
||||||
last = profiles[-1]
|
last = profiles[-1]
|
||||||
|
|
||||||
res_rk = [first.rk]
|
res_kp = [first.kp]
|
||||||
|
|
||||||
profiles = iter(profiles)
|
profiles = iter(profiles)
|
||||||
previous = next(profiles)
|
previous = next(profiles)
|
||||||
|
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
prev = previous.rk
|
prev = previous.kp
|
||||||
curr = profile.rk
|
curr = profile.kp
|
||||||
|
|
||||||
diff = abs(previous.rk - profile.rk)
|
diff = abs(previous.kp - profile.kp)
|
||||||
|
|
||||||
new = previous.rk + (diff / 2.0)
|
new = previous.kp + (diff / 2.0)
|
||||||
res_rk.append(new)
|
res_kp.append(new)
|
||||||
|
|
||||||
previous = profile
|
previous = profile
|
||||||
|
|
||||||
res_rk.append(last.rk)
|
res_kp.append(last.kp)
|
||||||
return res_rk
|
return res_kp
|
||||||
|
|
||||||
# Sediment Layers
|
# Sediment Layers
|
||||||
|
|
||||||
@@ -536,7 +536,7 @@ class Reach(SQLSubModel):
|
|||||||
def sort(self, is_reversed: bool = False):
|
def sort(self, is_reversed: bool = False):
|
||||||
self.profiles = sorted(
|
self.profiles = sorted(
|
||||||
self.profiles,
|
self.profiles,
|
||||||
key=lambda profile: profile.rk,
|
key=lambda profile: profile.kp,
|
||||||
reverse=is_reversed
|
reverse=is_reversed
|
||||||
)
|
)
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
@@ -613,7 +613,7 @@ class Reach(SQLSubModel):
|
|||||||
|
|
||||||
self.profiles = profiles + self.profiles
|
self.profiles = profiles + self.profiles
|
||||||
self._update_profile_numbers()
|
self._update_profile_numbers()
|
||||||
self._recompute_rk()
|
self._recompute_kp()
|
||||||
|
|
||||||
return profiles
|
return profiles
|
||||||
|
|
||||||
@@ -633,7 +633,7 @@ class Reach(SQLSubModel):
|
|||||||
try:
|
try:
|
||||||
list_profile, list_header = self.read_file_st(str(file_path_name))
|
list_profile, list_header = self.read_file_st(str(file_path_name))
|
||||||
profile_header = ["num", "code1",
|
profile_header = ["num", "code1",
|
||||||
"code2", "nb_point", "rk", "name"]
|
"code2", "nb_point", "kp", "name"]
|
||||||
|
|
||||||
if list_profile and list_header:
|
if list_profile and list_header:
|
||||||
for ind, profile in enumerate(list_profile):
|
for ind, profile in enumerate(list_profile):
|
||||||
@@ -721,12 +721,12 @@ class Reach(SQLSubModel):
|
|||||||
c1 = f"{profile.code1:>6}"
|
c1 = f"{profile.code1:>6}"
|
||||||
c2 = f"{profile.code2:>6}"
|
c2 = f"{profile.code2:>6}"
|
||||||
t = f"{len(profile.points):>6}"
|
t = f"{len(profile.points):>6}"
|
||||||
rk = f"{profile.rk:>12f}"[0:12]
|
kp = f"{profile.kp:>12f}"[0:12]
|
||||||
pname = profile.name
|
pname = profile.name
|
||||||
if profile.name == "":
|
if profile.name == "":
|
||||||
pname = f"p{profile.id:>3}".replace(" ", "0")
|
pname = f"p{profile.id:>3}".replace(" ", "0")
|
||||||
|
|
||||||
st.write(f"{num}{c1}{c2}{t} {rk} {pname}\n")
|
st.write(f"{num}{c1}{c2}{t} {kp} {pname}\n")
|
||||||
|
|
||||||
for point in profile.points:
|
for point in profile.points:
|
||||||
x = f"{point.x:<12.4f}"[0:12]
|
x = f"{point.x:<12.4f}"[0:12]
|
||||||
@@ -745,15 +745,15 @@ class Reach(SQLSubModel):
|
|||||||
last = self.profile(len(self) - 1)
|
last = self.profile(len(self) - 1)
|
||||||
|
|
||||||
z_first = first.z_min()
|
z_first = first.z_min()
|
||||||
rk_first = first.rk
|
kp_first = first.kp
|
||||||
|
|
||||||
z_last = last.z_min()
|
z_last = last.z_min()
|
||||||
rk_last = last.rk
|
kp_last = last.kp
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(z_last - z_first)
|
(z_last - z_first)
|
||||||
/
|
/
|
||||||
(rk_last - rk_first)
|
(kp_last - kp_first)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_incline_mean(self):
|
def get_incline_mean(self):
|
||||||
@@ -764,15 +764,15 @@ class Reach(SQLSubModel):
|
|||||||
|
|
||||||
for profile in profiles[1:]:
|
for profile in profiles[1:]:
|
||||||
z_first = previous.z_min()
|
z_first = previous.z_min()
|
||||||
rk_first = previous.rk
|
kp_first = previous.kp
|
||||||
|
|
||||||
z_last = profile.z_min()
|
z_last = profile.z_min()
|
||||||
rk_last = profile.rk
|
kp_last = profile.kp
|
||||||
|
|
||||||
incline_acc += (
|
incline_acc += (
|
||||||
(z_last - z_first)
|
(z_last - z_first)
|
||||||
/
|
/
|
||||||
(rk_last - rk_first)
|
(kp_last - kp_first)
|
||||||
)
|
)
|
||||||
|
|
||||||
previous = profile
|
previous = profile
|
||||||
@@ -787,15 +787,15 @@ class Reach(SQLSubModel):
|
|||||||
|
|
||||||
for profile in profiles[1:]:
|
for profile in profiles[1:]:
|
||||||
z_first = previous.z_min()
|
z_first = previous.z_min()
|
||||||
rk_first = previous.rk
|
kp_first = previous.kp
|
||||||
|
|
||||||
z_last = profile.z_min()
|
z_last = profile.z_min()
|
||||||
rk_last = profile.rk
|
kp_last = profile.kp
|
||||||
|
|
||||||
incline_acc += [
|
incline_acc += [
|
||||||
(z_last - z_first)
|
(z_last - z_first)
|
||||||
/
|
/
|
||||||
(rk_last - rk_first)
|
(kp_last - kp_first)
|
||||||
]
|
]
|
||||||
|
|
||||||
previous = profile
|
previous = profile
|
||||||
@@ -811,15 +811,15 @@ class Reach(SQLSubModel):
|
|||||||
|
|
||||||
for profile in profiles[1:]:
|
for profile in profiles[1:]:
|
||||||
z_first = previous.z_min()
|
z_first = previous.z_min()
|
||||||
rk_first = previous.rk
|
kp_first = previous.kp
|
||||||
|
|
||||||
z_last = profile.z_min()
|
z_last = profile.z_min()
|
||||||
rk_last = profile.rk
|
kp_last = profile.kp
|
||||||
|
|
||||||
incline_acc += [
|
incline_acc += [
|
||||||
(z_last - z_first)
|
(z_last - z_first)
|
||||||
/
|
/
|
||||||
(rk_last - rk_first)
|
(kp_last - kp_first)
|
||||||
]
|
]
|
||||||
|
|
||||||
previous = profile
|
previous = profile
|
||||||
@@ -847,14 +847,14 @@ class Reach(SQLSubModel):
|
|||||||
logger_exception(e)
|
logger_exception(e)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def _recompute_rk(self, offset=0.0):
|
def _recompute_kp(self, offset=0.0):
|
||||||
self._recompute_rk_no_gl(offset=offset)
|
self._recompute_kp_no_gl(offset=offset)
|
||||||
|
|
||||||
def _recompute_rk_no_gl(self, offset=0.0):
|
def _recompute_kp_no_gl(self, offset=0.0):
|
||||||
profiles = iter(self.profiles)
|
profiles = iter(self.profiles)
|
||||||
|
|
||||||
previous = next(profiles)
|
previous = next(profiles)
|
||||||
previous.rk = offset
|
previous.kp = offset
|
||||||
|
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
prev_points = previous.points
|
prev_points = previous.points
|
||||||
@@ -865,5 +865,5 @@ class Reach(SQLSubModel):
|
|||||||
prev_points[-1].dist_2d(curr_points[-1])
|
prev_points[-1].dist_2d(curr_points[-1])
|
||||||
) / 2.0
|
) / 2.0
|
||||||
|
|
||||||
profile.rk = previous.rk + dist
|
profile.kp = previous.kp + dist
|
||||||
previous = profile
|
previous = profile
|
||||||
@@ -50,8 +50,8 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
self.id = id
|
self.id = id
|
||||||
|
|
||||||
self._name = name
|
self._name = name
|
||||||
self._input_rk = None
|
self._input_kp = None
|
||||||
self._output_rk = None
|
self._output_kp = None
|
||||||
self._input_reach = None
|
self._input_reach = None
|
||||||
self._output_reach = None
|
self._output_reach = None
|
||||||
self._enabled = True
|
self._enabled = True
|
||||||
@@ -64,13 +64,14 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|
||||||
execute("""
|
execute("""
|
||||||
CREATE TABLE hydraulic_structures(
|
CREATE TABLE hydraulic_structures(
|
||||||
id INTEGER NOT NULL PRIMARY KEY,
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
enabled BOOLEAN NOT NULL,
|
enabled BOOLEAN NOT NULL,
|
||||||
input_rk REAL NOT NULL,
|
input_kp REAL NOT NULL,
|
||||||
output_rk REAL NOT NULL,
|
output_kp REAL NOT NULL,
|
||||||
input_reach INTEGER,
|
input_reach INTEGER,
|
||||||
output_reach INTEGER,
|
output_reach INTEGER,
|
||||||
FOREIGN KEY(input_reach) REFERENCES river_reach(id),
|
FOREIGN KEY(input_reach) REFERENCES river_reach(id),
|
||||||
@@ -84,25 +85,9 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
def _db_update(cls, execute, version):
|
def _db_update(cls, execute, version):
|
||||||
major, minor, release = version.strip().split(".")
|
major, minor, release = version.strip().split(".")
|
||||||
if major == minor == "0":
|
if major == minor == "0":
|
||||||
rl = int(release)
|
if int(release) < 6:
|
||||||
|
|
||||||
if rl < 6:
|
|
||||||
cls._db_create(execute)
|
cls._db_create(execute)
|
||||||
|
|
||||||
if rl < 11:
|
|
||||||
execute(
|
|
||||||
"""
|
|
||||||
ALTER TABLE hydraulic_structures
|
|
||||||
RENAME COLUMN input_kp TO input_rk
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
execute(
|
|
||||||
"""
|
|
||||||
ALTER TABLE hydraulic_structures
|
|
||||||
RENAME COLUMN output_kp TO output_rk
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -111,7 +96,7 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
|
|
||||||
table = execute(
|
table = execute(
|
||||||
"SELECT id, name, enabled, " +
|
"SELECT id, name, enabled, " +
|
||||||
"input_rk, output_rk, " +
|
"input_kp, output_kp, " +
|
||||||
"input_reach, output_reach " +
|
"input_reach, output_reach " +
|
||||||
"FROM hydraulic_structures "
|
"FROM hydraulic_structures "
|
||||||
)
|
)
|
||||||
@@ -122,8 +107,8 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
hs_id = next(it)
|
hs_id = next(it)
|
||||||
name = next(it)
|
name = next(it)
|
||||||
enabled = (next(it) == 1)
|
enabled = (next(it) == 1)
|
||||||
input_rk = next(it)
|
input_kp = next(it)
|
||||||
output_rk = next(it)
|
output_kp = next(it)
|
||||||
input_reach_id = next(it)
|
input_reach_id = next(it)
|
||||||
output_reach_id = next(it)
|
output_reach_id = next(it)
|
||||||
|
|
||||||
@@ -134,8 +119,8 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
hs.enabled = enabled
|
hs.enabled = enabled
|
||||||
hs.input_rk = input_rk if input_rk != -1 else None
|
hs.input_kp = input_kp if input_kp != -1 else None
|
||||||
hs.output_rk = output_rk if output_rk != -1 else None
|
hs.output_kp = output_kp if output_kp != -1 else None
|
||||||
|
|
||||||
hs.input_reach, hs.output_reach = reduce(
|
hs.input_reach, hs.output_reach = reduce(
|
||||||
lambda acc, n: (
|
lambda acc, n: (
|
||||||
@@ -154,6 +139,7 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
return new
|
return new
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
def _db_save(self, execute, data=None):
|
||||||
|
print("save hs unit")
|
||||||
execute(f"DELETE FROM hydraulic_structures WHERE id = {self.id}")
|
execute(f"DELETE FROM hydraulic_structures WHERE id = {self.id}")
|
||||||
|
|
||||||
input_reach_id = -1
|
input_reach_id = -1
|
||||||
@@ -164,24 +150,24 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
if self._output_reach is not None:
|
if self._output_reach is not None:
|
||||||
output_reach_id = self._output_reach.id
|
output_reach_id = self._output_reach.id
|
||||||
|
|
||||||
input_rk = -1
|
input_kp = -1
|
||||||
if self.input_rk is not None:
|
if self.input_kp is not None:
|
||||||
input_rk = self.input_rk
|
input_kp = self.input_kp
|
||||||
|
|
||||||
output_rk = -1
|
output_kp = -1
|
||||||
if self.output_rk is not None:
|
if self.output_kp is not None:
|
||||||
output_rk = self.output_rk
|
output_kp = self.output_kp
|
||||||
|
|
||||||
sql = (
|
sql = (
|
||||||
"INSERT INTO " +
|
"INSERT INTO " +
|
||||||
"hydraulic_structures(" +
|
"hydraulic_structures(" +
|
||||||
" id, name, enabled, input_rk, output_rk, " +
|
" id, name, enabled, input_kp, output_kp, " +
|
||||||
" input_reach, output_reach" +
|
" input_reach, output_reach" +
|
||||||
") " +
|
") " +
|
||||||
"VALUES (" +
|
"VALUES (" +
|
||||||
f"{self.id}, '{self._db_format(self._name)}', " +
|
f"{self.id}, '{self._db_format(self._name)}', " +
|
||||||
f"{self._db_format(self.enabled)}, " +
|
f"{self._db_format(self.enabled)}, " +
|
||||||
f"{input_rk}, {output_rk}, " +
|
f"{input_kp}, {output_kp}, " +
|
||||||
f"{input_reach_id}, {output_reach_id}" +
|
f"{input_reach_id}, {output_reach_id}" +
|
||||||
")"
|
")"
|
||||||
)
|
)
|
||||||
@@ -214,24 +200,24 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def input_rk(self):
|
def input_kp(self):
|
||||||
return self._input_rk
|
return self._input_kp
|
||||||
|
|
||||||
@input_rk.setter
|
@input_kp.setter
|
||||||
def input_rk(self, input_rk):
|
def input_kp(self, input_kp):
|
||||||
if input_rk is not None:
|
if input_kp is not None:
|
||||||
input_rk = float(input_rk)
|
input_kp = float(input_kp)
|
||||||
|
|
||||||
self._input_rk = input_rk
|
self._input_kp = input_kp
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def output_rk(self):
|
def output_kp(self):
|
||||||
return self._output_rk
|
return self._output_kp
|
||||||
|
|
||||||
@output_rk.setter
|
@output_kp.setter
|
||||||
def output_rk(self, output_rk):
|
def output_kp(self, output_kp):
|
||||||
self._output_rk = output_rk
|
self._output_kp = output_kp
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ logger = logging.getLogger()
|
|||||||
class Data(SQLSubModel):
|
class Data(SQLSubModel):
|
||||||
def __init__(self, name: str = "",
|
def __init__(self, name: str = "",
|
||||||
comment: str = "", reach=None,
|
comment: str = "", reach=None,
|
||||||
rk: float = 0.0, discharge: float = 0.0,
|
kp: float = 0.0, discharge: float = 0.0,
|
||||||
height: float = 0.0,
|
height: float = 0.0,
|
||||||
status=None):
|
status=None):
|
||||||
super(Data, self).__init__()
|
super(Data, self).__init__()
|
||||||
@@ -42,14 +42,14 @@ class Data(SQLSubModel):
|
|||||||
self._name = name
|
self._name = name
|
||||||
self._comment = comment
|
self._comment = comment
|
||||||
|
|
||||||
self._rk = rk
|
self._kp = kp
|
||||||
self._discharge = discharge
|
self._discharge = discharge
|
||||||
self._speed = 0.0
|
self._speed = 0.0
|
||||||
self._elevation = 0.0
|
self._elevation = 0.0
|
||||||
self._height = height
|
self._height = height
|
||||||
|
|
||||||
if self._rk != 0.0:
|
if self._kp != 0.0:
|
||||||
self._update_from_rk()
|
self._update_from_kp()
|
||||||
if self._height != 0.0:
|
if self._height != 0.0:
|
||||||
self._update_from_height()
|
self._update_from_height()
|
||||||
if self._discharge != 0.0:
|
if self._discharge != 0.0:
|
||||||
@@ -64,7 +64,7 @@ class Data(SQLSubModel):
|
|||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
comment TEXT NOT NULL,
|
comment TEXT NOT NULL,
|
||||||
reach INTEGER,
|
reach INTEGER,
|
||||||
rk REAL NOT NULL,
|
kp REAL NOT NULL,
|
||||||
discharge REAL NOT NULL,
|
discharge REAL NOT NULL,
|
||||||
height REAL NOT NULL,
|
height REAL NOT NULL,
|
||||||
FOREIGN KEY(reach) REFERENCES river_reach(id)
|
FOREIGN KEY(reach) REFERENCES river_reach(id)
|
||||||
@@ -75,20 +75,13 @@ class Data(SQLSubModel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_update(cls, execute, version):
|
def _db_update(cls, execute, version):
|
||||||
major, minor, release = version.strip().split(".")
|
|
||||||
if major == minor == "0":
|
|
||||||
if int(release) < 11:
|
|
||||||
execute(
|
|
||||||
"ALTER TABLE initial_conditions RENAME COLUMN kp TO rk"
|
|
||||||
)
|
|
||||||
|
|
||||||
return cls._update_submodel(execute, version)
|
return cls._update_submodel(execute, version)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_load(cls, execute, data=None):
|
def _db_load(cls, execute, data=None):
|
||||||
id = data["reach"].id
|
id = data["reach"].id
|
||||||
table = execute(
|
table = execute(
|
||||||
"SELECT ind, name, comment, rk, discharge, height " +
|
"SELECT ind, name, comment, kp, discharge, height " +
|
||||||
"FROM initial_conditions " +
|
"FROM initial_conditions " +
|
||||||
f"WHERE reach = {id}"
|
f"WHERE reach = {id}"
|
||||||
)
|
)
|
||||||
@@ -102,7 +95,7 @@ class Data(SQLSubModel):
|
|||||||
ind = row[0]
|
ind = row[0]
|
||||||
name = row[1]
|
name = row[1]
|
||||||
comment = row[2]
|
comment = row[2]
|
||||||
rk = row[3]
|
kp = row[3]
|
||||||
discharge = row[4]
|
discharge = row[4]
|
||||||
height = row[5]
|
height = row[5]
|
||||||
|
|
||||||
@@ -111,7 +104,7 @@ class Data(SQLSubModel):
|
|||||||
status=data["status"],
|
status=data["status"],
|
||||||
name=name,
|
name=name,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
rk=rk,
|
kp=kp,
|
||||||
discharge=discharge,
|
discharge=discharge,
|
||||||
height=height,
|
height=height,
|
||||||
)
|
)
|
||||||
@@ -125,12 +118,12 @@ class Data(SQLSubModel):
|
|||||||
|
|
||||||
execute(
|
execute(
|
||||||
"INSERT INTO " +
|
"INSERT INTO " +
|
||||||
"initial_conditions(ind, name, comment, rk, " +
|
"initial_conditions(ind, name, comment, kp, " +
|
||||||
"discharge, height, reach) " +
|
"discharge, height, reach) " +
|
||||||
"VALUES (" +
|
"VALUES (" +
|
||||||
f"{ind}, '{self._db_format(self.name)}', " +
|
f"{ind}, '{self._db_format(self.name)}', " +
|
||||||
f"'{self._db_format(self._comment)}', " +
|
f"'{self._db_format(self._comment)}', " +
|
||||||
f"{self._rk}, {self._discharge}, {self._height}, " +
|
f"{self._kp}, {self._discharge}, {self._height}, " +
|
||||||
f"{self._reach.id}" +
|
f"{self._reach.id}" +
|
||||||
")"
|
")"
|
||||||
)
|
)
|
||||||
@@ -141,12 +134,13 @@ class Data(SQLSubModel):
|
|||||||
new = Data(
|
new = Data(
|
||||||
name=self.name,
|
name=self.name,
|
||||||
comment=self._comment,
|
comment=self._comment,
|
||||||
rk=self._rk,
|
kp=self._kp,
|
||||||
discharge=self._discharge,
|
discharge=self._discharge,
|
||||||
height=self._height,
|
height=self._height,
|
||||||
reach=self._reach,
|
reach=self._reach,
|
||||||
status=self._status,
|
status=self._status,
|
||||||
)
|
)
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -160,8 +154,8 @@ class Data(SQLSubModel):
|
|||||||
val = self._name
|
val = self._name
|
||||||
elif key == "comment":
|
elif key == "comment":
|
||||||
val = self._comment
|
val = self._comment
|
||||||
elif key == "rk":
|
elif key == "kp":
|
||||||
val = self._rk
|
val = self._kp
|
||||||
elif key == "speed":
|
elif key == "speed":
|
||||||
val = self._speed
|
val = self._speed
|
||||||
elif key == "discharge":
|
elif key == "discharge":
|
||||||
@@ -174,7 +168,7 @@ class Data(SQLSubModel):
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
def _update_get_min(self):
|
def _update_get_min(self):
|
||||||
profile = self._reach.reach.get_profiles_from_rk(self._rk)
|
profile = self._reach.reach.get_profiles_from_kp(self._kp)
|
||||||
if len(profile) > 0:
|
if len(profile) > 0:
|
||||||
min = profile[0].z_min()
|
min = profile[0].z_min()
|
||||||
else:
|
else:
|
||||||
@@ -182,7 +176,7 @@ class Data(SQLSubModel):
|
|||||||
|
|
||||||
return min
|
return min
|
||||||
|
|
||||||
def _update_from_rk(self):
|
def _update_from_kp(self):
|
||||||
min = self._update_get_min()
|
min = self._update_get_min()
|
||||||
self._elevation = min + self._height
|
self._elevation = min + self._height
|
||||||
|
|
||||||
@@ -203,9 +197,9 @@ class Data(SQLSubModel):
|
|||||||
self._name = str(value)
|
self._name = str(value)
|
||||||
elif key == "comment":
|
elif key == "comment":
|
||||||
self._comment = str(value)
|
self._comment = str(value)
|
||||||
elif key == "rk":
|
elif key == "kp":
|
||||||
self._rk = float(value)
|
self._kp = float(value)
|
||||||
self._update_from_rk()
|
self._update_from_kp()
|
||||||
elif key == "speed":
|
elif key == "speed":
|
||||||
# Not supposed to be modified
|
# Not supposed to be modified
|
||||||
self._speed = float(value)
|
self._speed = float(value)
|
||||||
@@ -304,10 +298,10 @@ class InitialConditions(SQLSubModel):
|
|||||||
self._data.insert(index, n)
|
self._data.insert(index, n)
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
def new_from_data(self, rk, discharge, elevation):
|
def new_from_data(self, kp, discharge, elevation):
|
||||||
n = Data(reach=self._reach, status=self._status)
|
n = Data(reach=self._reach, status=self._status)
|
||||||
|
|
||||||
n['rk'] = rk
|
n['kp'] = kp
|
||||||
n['discharge'] = discharge
|
n['discharge'] = discharge
|
||||||
n['elevation'] = elevation
|
n['elevation'] = elevation
|
||||||
|
|
||||||
@@ -350,8 +344,8 @@ class InitialConditions(SQLSubModel):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_rk(self):
|
def get_kp(self):
|
||||||
return self._data_get("rk")
|
return self._data_get("kp")
|
||||||
|
|
||||||
def get_elevation(self):
|
def get_elevation(self):
|
||||||
return self._data_get("elevation")
|
return self._data_get("elevation")
|
||||||
@@ -359,10 +353,10 @@ class InitialConditions(SQLSubModel):
|
|||||||
def get_discharge(self):
|
def get_discharge(self):
|
||||||
return self._data_get("discharge")
|
return self._data_get("discharge")
|
||||||
|
|
||||||
def _sort_by_z_and_rk(self, profiles):
|
def _sort_by_z_and_kp(self, profiles):
|
||||||
profiles.sort(
|
profiles.sort(
|
||||||
reverse=False,
|
reverse=False,
|
||||||
key=lambda p: p.rk
|
key=lambda p: p.kp
|
||||||
)
|
)
|
||||||
|
|
||||||
first_z = profiles[0].z()
|
first_z = profiles[0].z()
|
||||||
@@ -371,36 +365,22 @@ class InitialConditions(SQLSubModel):
|
|||||||
if first_z > last_z:
|
if first_z > last_z:
|
||||||
profiles.sort(
|
profiles.sort(
|
||||||
reverse=True,
|
reverse=True,
|
||||||
key=lambda p: p.rk
|
key=lambda p: p.kp
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_growing_constante_height(self, height: float,
|
def generate_growing_constante_height(self, height: float):
|
||||||
compute_discharge: bool):
|
self._data = []
|
||||||
|
|
||||||
profiles = self._reach.reach.profiles.copy()
|
profiles = self._reach.reach.profiles.copy()
|
||||||
self._sort_by_z_and_rk(profiles)
|
self._sort_by_z_and_kp(profiles)
|
||||||
|
|
||||||
previous_elevation = -99999.99
|
|
||||||
|
|
||||||
data_discharge = {}
|
|
||||||
if not compute_discharge:
|
|
||||||
if len(self._data) == 0:
|
|
||||||
for profile in profiles:
|
|
||||||
data_discharge[profile.rk] = 0.0
|
|
||||||
else:
|
|
||||||
for data in self._data:
|
|
||||||
data_discharge[data["rk"]] = data["discharge"]
|
|
||||||
|
|
||||||
incline = self._reach.reach.get_incline_median_mean()
|
incline = self._reach.reach.get_incline_median_mean()
|
||||||
logger.debug(f"incline = {incline}")
|
logger.debug(f"incline = {incline}")
|
||||||
self._data = []
|
|
||||||
|
previous_elevation = -99999.99
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
width = profile.width_approximation()
|
width = profile.width_approximation()
|
||||||
strickler = 25
|
strickler = 25
|
||||||
|
|
||||||
if not compute_discharge:
|
|
||||||
discharge = data_discharge[profile.rk]
|
|
||||||
else:
|
|
||||||
discharge = (
|
discharge = (
|
||||||
((width * 0.8)
|
((width * 0.8)
|
||||||
* strickler
|
* strickler
|
||||||
@@ -413,47 +393,41 @@ class InitialConditions(SQLSubModel):
|
|||||||
previous_elevation
|
previous_elevation
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.debug(f"({profile.rk}):")
|
logger.debug(f"({profile.kp}):")
|
||||||
logger.debug(f" width = {width}")
|
logger.debug(f" width = {width}")
|
||||||
logger.debug(f" strickler = {strickler}")
|
logger.debug(f" strickler = {strickler}")
|
||||||
logger.debug(f" discharge = {discharge}")
|
logger.debug(f" discharge = {discharge}")
|
||||||
|
|
||||||
new = Data(reach=self._reach, status=self._status)
|
new = Data(reach=self._reach, status=self._status)
|
||||||
new["rk"] = profile.rk
|
new["kp"] = profile.kp
|
||||||
new["discharge"] = discharge
|
new["discharge"] = discharge
|
||||||
|
|
||||||
new["elevation"] = elevation
|
new["elevation"] = elevation
|
||||||
|
|
||||||
previous_elevation = elevation
|
|
||||||
self._data.append(new)
|
self._data.append(new)
|
||||||
|
previous_elevation = elevation
|
||||||
|
|
||||||
self._generate_resort_data(profiles)
|
self._generate_resort_data(profiles)
|
||||||
|
|
||||||
def generate_discharge(self, discharge: float, compute_height: bool):
|
def generate_discharge(self, discharge: float):
|
||||||
|
self._data = []
|
||||||
|
|
||||||
|
self._generate_height_estimation_from_discharge(
|
||||||
|
discharge
|
||||||
|
)
|
||||||
|
|
||||||
|
def _generate_height_estimation_from_discharge(self, discharge: float):
|
||||||
profiles = self._reach.reach.profiles.copy()
|
profiles = self._reach.reach.profiles.copy()
|
||||||
self._sort_by_z_and_rk(profiles)
|
self._sort_by_z_and_kp(profiles)
|
||||||
|
|
||||||
previous_elevation = -99999.99
|
previous_elevation = -99999.99
|
||||||
|
|
||||||
data_height = {}
|
|
||||||
if not compute_height:
|
|
||||||
if len(self._data) == 0:
|
|
||||||
for profile in profiles:
|
|
||||||
data_height[profile.rk] = 0.0
|
|
||||||
else:
|
|
||||||
for data in self._data:
|
|
||||||
data_height[data["rk"]] = data["height"]
|
|
||||||
|
|
||||||
incline = self._reach.reach.get_incline_median_mean()
|
incline = self._reach.reach.get_incline_median_mean()
|
||||||
logger.debug(f"incline = {incline}")
|
logger.debug(f"incline = {incline}")
|
||||||
self._data = []
|
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
width = profile.width_approximation()
|
width = profile.width_approximation()
|
||||||
strickler = 25
|
strickler = 25
|
||||||
|
|
||||||
if not compute_height:
|
|
||||||
height = data_height[profile.rk]
|
|
||||||
else:
|
|
||||||
height = (
|
height = (
|
||||||
discharge
|
discharge
|
||||||
/
|
/
|
||||||
@@ -465,13 +439,13 @@ class InitialConditions(SQLSubModel):
|
|||||||
previous_elevation
|
previous_elevation
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.debug(f"({profile.rk}):")
|
logger.debug(f"({profile.kp}):")
|
||||||
logger.debug(f" width = {width}")
|
logger.debug(f" width = {width}")
|
||||||
logger.debug(f" strickler = {strickler}")
|
logger.debug(f" strickler = {strickler}")
|
||||||
logger.debug(f" height = {height}")
|
logger.debug(f" height = {height}")
|
||||||
|
|
||||||
new = Data(reach=self._reach, status=self._status)
|
new = Data(reach=self._reach, status=self._status)
|
||||||
new["rk"] = profile.rk
|
new["kp"] = profile.kp
|
||||||
new["discharge"] = discharge
|
new["discharge"] = discharge
|
||||||
new["elevation"] = elevation
|
new["elevation"] = elevation
|
||||||
|
|
||||||
@@ -482,10 +456,10 @@ class InitialConditions(SQLSubModel):
|
|||||||
|
|
||||||
def _generate_resort_data(self, profiles):
|
def _generate_resort_data(self, profiles):
|
||||||
is_reverse = False
|
is_reverse = False
|
||||||
if profiles[0].rk > profiles[-1].rk:
|
if profiles[0].kp > profiles[-1].kp:
|
||||||
is_reverse = True
|
is_reverse = True
|
||||||
|
|
||||||
self._data.sort(
|
self._data.sort(
|
||||||
reverse=not is_reverse,
|
reverse=not is_reverse,
|
||||||
key=lambda d: d['rk']
|
key=lambda d: d['kp']
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
# InitialConditionsAdisTS.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
from tools import trace, timer, old_pamhyr_date_to_timestamp
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
from Model.InitialConditionsAdisTS.InitialConditionsAdisTSSpec import ICAdisTSSpec
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class InitialConditionsAdisTS(SQLSubModel):
|
||||||
|
_sub_classes = [
|
||||||
|
ICAdisTSSpec,
|
||||||
|
]
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, name: str = "default",
|
||||||
|
pollutant: int = -1, status=None):
|
||||||
|
super(InitialConditionsAdisTS, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = InitialConditionsAdisTS._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._name = name
|
||||||
|
self._pollutant = pollutant
|
||||||
|
self._concentration = None
|
||||||
|
self._eg = None
|
||||||
|
self._em = None
|
||||||
|
self._ed = None
|
||||||
|
self._enabled = True
|
||||||
|
self._data = []
|
||||||
|
|
||||||
|
InitialConditionsAdisTS._id_cnt = max(
|
||||||
|
InitialConditionsAdisTS._id_cnt + 1,
|
||||||
|
self.id
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE initial_conditions_adists(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
pollutant INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
concentration REAL NOT NULL,
|
||||||
|
eg REAL NOT NULL,
|
||||||
|
em REAL NOT NULL,
|
||||||
|
ed REAL NOT NULL,
|
||||||
|
enabled BOOLEAN NOT NULL,
|
||||||
|
FOREIGN KEY(pollutant) REFERENCES Pollutants(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
if major == minor == "0":
|
||||||
|
if int(release) < 6:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, pollutant, name, concentration, eg, em, ed, " +
|
||||||
|
"enabled " +
|
||||||
|
"FROM initial_conditions_adists"
|
||||||
|
)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for row in table:
|
||||||
|
IC_id = row[0]
|
||||||
|
pollutant = row[1]
|
||||||
|
name = row[2]
|
||||||
|
concentration = row[3]
|
||||||
|
eg = row[4]
|
||||||
|
em = row[5]
|
||||||
|
ed = row[6]
|
||||||
|
enabled = (row[7] == 1)
|
||||||
|
|
||||||
|
IC = cls(
|
||||||
|
id=IC_id,
|
||||||
|
name=name,
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
IC.pollutant = pollutant
|
||||||
|
IC.concentration = concentration
|
||||||
|
IC.eg = eg
|
||||||
|
IC.em = em
|
||||||
|
IC.ed = ed
|
||||||
|
IC.enabled = enabled
|
||||||
|
|
||||||
|
data['ic_default_id'] = IC_id
|
||||||
|
IC._data = ICAdisTSSpec._db_load(execute, data)
|
||||||
|
|
||||||
|
new.append(IC)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute(f"DELETE FROM initial_conditions_adists WHERE id = {self.id}")
|
||||||
|
|
||||||
|
pollutant = -1
|
||||||
|
if self.pollutant is not None:
|
||||||
|
pollutant = self.pollutant
|
||||||
|
|
||||||
|
concentration = -1.
|
||||||
|
if self.concentration is not None:
|
||||||
|
concentration = self.concentration
|
||||||
|
|
||||||
|
eg = -1.
|
||||||
|
if self.eg is not None:
|
||||||
|
eg = self.eg
|
||||||
|
|
||||||
|
em = -1.
|
||||||
|
if self.em is not None:
|
||||||
|
em = self.em
|
||||||
|
|
||||||
|
ed = -1.
|
||||||
|
if self.ed is not None:
|
||||||
|
ed = self.ed
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"initial_conditions_adists(" +
|
||||||
|
"id, pollutant, name, concentration, " +
|
||||||
|
"eg, em, ed, enabled" +
|
||||||
|
") " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, {pollutant}, '{self._db_format(self._name)}', " +
|
||||||
|
f"{concentration}, {eg}, {em}, {ed}, {self._enabled}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
data['ic_default_id'] = self.id
|
||||||
|
execute(
|
||||||
|
"DELETE FROM initial_conditions_spec " +
|
||||||
|
f"WHERE ic_default = {self.id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
for ic_spec in self._data:
|
||||||
|
ic_spec._db_save(execute, data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, name):
|
||||||
|
self._name = name
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pollutant(self):
|
||||||
|
return self._pollutant
|
||||||
|
|
||||||
|
@pollutant.setter
|
||||||
|
def pollutant(self, pollutant):
|
||||||
|
self._pollutant = pollutant
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def concentration(self):
|
||||||
|
return self._concentration
|
||||||
|
|
||||||
|
@concentration.setter
|
||||||
|
def concentration(self, concentration):
|
||||||
|
self._concentration = concentration
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def eg(self):
|
||||||
|
return self._eg
|
||||||
|
|
||||||
|
@eg.setter
|
||||||
|
def eg(self, eg):
|
||||||
|
self._eg = eg
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def em(self):
|
||||||
|
return self._em
|
||||||
|
|
||||||
|
@em.setter
|
||||||
|
def em(self, em):
|
||||||
|
self._em = em
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ed(self):
|
||||||
|
return self._ed
|
||||||
|
|
||||||
|
@ed.setter
|
||||||
|
def ed(self, ed):
|
||||||
|
self._ed = ed
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def new(self, index):
|
||||||
|
n = ICAdisTSSpec(status=self._status)
|
||||||
|
self._data.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
def delete(self, data):
|
||||||
|
self._data = list(
|
||||||
|
filter(
|
||||||
|
lambda x: x not in data,
|
||||||
|
self._data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def delete_i(self, indexes):
|
||||||
|
for ind in indexes:
|
||||||
|
del self._data[ind]
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def insert(self, index, data):
|
||||||
|
self._data.insert(index, data)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# InitialConditionsAdisTSList.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 copy import copy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrList import PamhyrModelList
|
||||||
|
from Model.InitialConditionsAdisTS.InitialConditionsAdisTS import InitialConditionsAdisTS
|
||||||
|
|
||||||
|
class InitialConditionsAdisTSList(PamhyrModelList):
|
||||||
|
_sub_classes = [
|
||||||
|
InitialConditionsAdisTS,
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = cls(status=data['status'])
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
new._lst = InitialConditionsAdisTS._db_load(
|
||||||
|
execute, data
|
||||||
|
)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute("DELETE FROM initial_conditions_adists")
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
for ic in self._lst:
|
||||||
|
ic._db_save(execute, data=data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def new(self, index, pollutant):
|
||||||
|
n = InitialConditionsAdisTS(pollutant=pollutant, status=self._status)
|
||||||
|
self._lst.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
@property
|
||||||
|
def Initial_Conditions_List(self):
|
||||||
|
return self.lst
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
# InitialConditionsAdisTSSpec.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class ICAdisTSSpec(SQLSubModel):
|
||||||
|
_sub_classes = [
|
||||||
|
]
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, name: str = "",
|
||||||
|
status=None):
|
||||||
|
super(ICAdisTSSpec, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = ICAdisTSSpec._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._name_section = name
|
||||||
|
self._reach = None
|
||||||
|
self._start_kp = None
|
||||||
|
self._end_kp = None
|
||||||
|
self._concentration = None
|
||||||
|
self._eg = None
|
||||||
|
self._em = None
|
||||||
|
self._ed = None
|
||||||
|
self._rate = None
|
||||||
|
self._enabled = True
|
||||||
|
|
||||||
|
ICAdisTSSpec._id_cnt = max(ICAdisTSSpec._id_cnt + 1, self.id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE initial_conditions_spec(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
ic_default INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
reach INTEGER NOT NULL,
|
||||||
|
start_kp REAL NOT NULL,
|
||||||
|
end_kp REAL NOT NULL,
|
||||||
|
concentration REAL NOT NULL,
|
||||||
|
eg REAL NOT NULL,
|
||||||
|
em REAL NOT NULL,
|
||||||
|
ed REAL NOT NULL,
|
||||||
|
rate REAL NOT NULL,
|
||||||
|
enabled BOOLEAN NOT NULL,
|
||||||
|
FOREIGN KEY(ic_default) REFERENCES initial_conditions_adists(id),
|
||||||
|
FOREIGN KEY(reach) REFERENCES river_reach(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
if major == minor == "0":
|
||||||
|
if int(release) < 6:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, ic_default, name, reach, start_kp, end_kp, " +
|
||||||
|
"concentration, eg, em, ed, rate, enabled " +
|
||||||
|
"FROM initial_conditions_spec " +
|
||||||
|
f"WHERE ic_default = {data['ic_default_id']} "
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in table:
|
||||||
|
id = row[0]
|
||||||
|
name = row[2]
|
||||||
|
reach = row[3]
|
||||||
|
start_kp = row[4]
|
||||||
|
end_kp = row[5]
|
||||||
|
concentration = row[6]
|
||||||
|
eg = row[7]
|
||||||
|
em = row[8]
|
||||||
|
ed = row[9]
|
||||||
|
rate = row[10]
|
||||||
|
enabled = (row[11] == 1)
|
||||||
|
|
||||||
|
#new_spec = [name, reach, start_kp, end_kp, concentration, eg, em, ed, rate, enabled]
|
||||||
|
|
||||||
|
new_spec = cls(
|
||||||
|
id=id,
|
||||||
|
name=name,
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
new_spec.reach = reach
|
||||||
|
new_spec.start_kp = start_kp
|
||||||
|
new_spec.end_kp = end_kp
|
||||||
|
new_spec.concentration = concentration
|
||||||
|
new_spec.eg = eg
|
||||||
|
new_spec.em = em
|
||||||
|
new_spec.ed = ed
|
||||||
|
new_spec.rate = rate
|
||||||
|
new_spec.enabled = enabled
|
||||||
|
|
||||||
|
new.append(new_spec)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
ic_default = data['ic_default_id']
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"initial_conditions_spec(id, ic_default, name, reach, " +
|
||||||
|
"start_kp, end_kp, concentration, eg, em, ed, rate, enabled) " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, " +
|
||||||
|
f"{ic_default}, " +
|
||||||
|
f"'{self._db_format(self._name_section)}', " +
|
||||||
|
f"{self._reach}, " +
|
||||||
|
f"{self._start_kp}, " +
|
||||||
|
f"{self._end_kp}, " +
|
||||||
|
f"{self._concentration}, " +
|
||||||
|
f"{self._eg}, " +
|
||||||
|
f"{self._em}, " +
|
||||||
|
f"{self._ed}, " +
|
||||||
|
f"{self._rate}, " +
|
||||||
|
f"{self._enabled}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name_section
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, name):
|
||||||
|
self._name_section = name
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reach(self):
|
||||||
|
return self._reach
|
||||||
|
|
||||||
|
@reach.setter
|
||||||
|
def reach(self, reach):
|
||||||
|
self._reach = reach
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start_kp(self):
|
||||||
|
return self._start_kp
|
||||||
|
|
||||||
|
@start_kp.setter
|
||||||
|
def start_kp(self, start_kp):
|
||||||
|
self._start_kp = start_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_kp(self):
|
||||||
|
return self._end_kp
|
||||||
|
|
||||||
|
@end_kp.setter
|
||||||
|
def end_kp(self, end_kp):
|
||||||
|
self._end_kp = end_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def concentration(self):
|
||||||
|
return self._concentration
|
||||||
|
|
||||||
|
@concentration.setter
|
||||||
|
def concentration(self, concentration):
|
||||||
|
self._concentration = concentration
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def eg(self):
|
||||||
|
return self._eg
|
||||||
|
|
||||||
|
@eg.setter
|
||||||
|
def eg(self, eg):
|
||||||
|
self._eg = eg
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def em(self):
|
||||||
|
return self._em
|
||||||
|
|
||||||
|
@em.setter
|
||||||
|
def em(self, em):
|
||||||
|
self._em = em
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ed(self):
|
||||||
|
return self._ed
|
||||||
|
|
||||||
|
@ed.setter
|
||||||
|
def ed(self, ed):
|
||||||
|
self._ed = ed
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rate(self):
|
||||||
|
return self._rate
|
||||||
|
|
||||||
|
@rate.setter
|
||||||
|
def rate(self, rate):
|
||||||
|
self._rate = rate
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -48,8 +48,8 @@ class LateralContribution(SQLSubModel):
|
|||||||
self._name = name
|
self._name = name
|
||||||
self._type = ""
|
self._type = ""
|
||||||
self._edge = None
|
self._edge = None
|
||||||
self._begin_rk = 0.0
|
self._begin_kp = 0.0
|
||||||
self._end_rk = 0.0
|
self._end_kp = 0.0
|
||||||
self._data = []
|
self._data = []
|
||||||
self._header = []
|
self._header = []
|
||||||
self._types = [float, float]
|
self._types = [float, float]
|
||||||
@@ -66,8 +66,8 @@ class LateralContribution(SQLSubModel):
|
|||||||
type TEXT NOT NULL,
|
type TEXT NOT NULL,
|
||||||
tab TEXT NOT NULL,
|
tab TEXT NOT NULL,
|
||||||
edge INTEGER,
|
edge INTEGER,
|
||||||
begin_rk REAL NOT NULL,
|
begin_kp REAL NOT NULL,
|
||||||
end_rk REAL NOT NULL,
|
end_kp REAL NOT NULL,
|
||||||
FOREIGN KEY(edge) REFERENCES river_reach(id)
|
FOREIGN KEY(edge) REFERENCES river_reach(id)
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
@@ -87,22 +87,6 @@ class LateralContribution(SQLSubModel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_update(cls, execute, version):
|
def _db_update(cls, execute, version):
|
||||||
major, minor, release = version.strip().split(".")
|
|
||||||
if major == minor == "0":
|
|
||||||
if int(release) < 11:
|
|
||||||
execute(
|
|
||||||
"""
|
|
||||||
ALTER TABLE lateral_contribution
|
|
||||||
RENAME COLUMN begin_kp TO begin_rk
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
execute(
|
|
||||||
"""
|
|
||||||
ALTER TABLE lateral_contribution
|
|
||||||
RENAME COLUMN end_kp TO end_rk
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -126,7 +110,7 @@ class LateralContribution(SQLSubModel):
|
|||||||
tab = data["tab"]
|
tab = data["tab"]
|
||||||
|
|
||||||
table = execute(
|
table = execute(
|
||||||
"SELECT id, name, type, edge, begin_rk, end_rk " +
|
"SELECT id, name, type, edge, begin_kp, end_kp " +
|
||||||
f"FROM lateral_contribution WHERE tab = '{tab}'"
|
f"FROM lateral_contribution WHERE tab = '{tab}'"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -141,8 +125,8 @@ class LateralContribution(SQLSubModel):
|
|||||||
lc.edge = None
|
lc.edge = None
|
||||||
if row[3] != -1:
|
if row[3] != -1:
|
||||||
lc.edge = next(filter(lambda e: e.id == row[3], data["edges"]))
|
lc.edge = next(filter(lambda e: e.id == row[3], data["edges"]))
|
||||||
lc._begin_rk = row[4]
|
lc._begin_kp = row[4]
|
||||||
lc._end_rk = row[5]
|
lc._end_kp = row[5]
|
||||||
|
|
||||||
values = execute(
|
values = execute(
|
||||||
"SELECT ind, data0, data1 FROM lateral_contribution_data " +
|
"SELECT ind, data0, data1 FROM lateral_contribution_data " +
|
||||||
@@ -176,11 +160,11 @@ class LateralContribution(SQLSubModel):
|
|||||||
sql = (
|
sql = (
|
||||||
"INSERT INTO " +
|
"INSERT INTO " +
|
||||||
"lateral_contribution(id, name, type, tab, " +
|
"lateral_contribution(id, name, type, tab, " +
|
||||||
"edge, begin_rk, end_rk) " +
|
"edge, begin_kp, end_kp) " +
|
||||||
"VALUES (" +
|
"VALUES (" +
|
||||||
f"{self.id}, '{self._db_format(self._name)}', " +
|
f"{self.id}, '{self._db_format(self._name)}', " +
|
||||||
f"'{self._db_format(self._type)}', '{tab}', {edge}, " +
|
f"'{self._db_format(self._type)}', '{tab}', {edge}, " +
|
||||||
f"{self._begin_rk}, {self._end_rk}" +
|
f"{self._begin_kp}, {self._end_kp}" +
|
||||||
")"
|
")"
|
||||||
)
|
)
|
||||||
execute(sql)
|
execute(sql)
|
||||||
@@ -247,44 +231,44 @@ class LateralContribution(SQLSubModel):
|
|||||||
def edge(self, edge):
|
def edge(self, edge):
|
||||||
self._edge = edge
|
self._edge = edge
|
||||||
if edge is not None:
|
if edge is not None:
|
||||||
self._begin_rk = self._edge.reach.get_rk_min()
|
self._begin_kp = self._edge.reach.get_kp_min()
|
||||||
self._end_rk = self._edge.reach.get_rk_max()
|
self._end_kp = self._edge.reach.get_kp_max()
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
def has_edge(self):
|
def has_edge(self):
|
||||||
return self._edge is not None
|
return self._edge is not None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def begin_rk(self):
|
def begin_kp(self):
|
||||||
return self._begin_rk
|
return self._begin_kp
|
||||||
|
|
||||||
@begin_rk.setter
|
@begin_kp.setter
|
||||||
def begin_rk(self, begin_rk):
|
def begin_kp(self, begin_kp):
|
||||||
if self._edge is None:
|
if self._edge is None:
|
||||||
self._begin_rk = begin_rk
|
self._begin_kp = begin_kp
|
||||||
else:
|
else:
|
||||||
_min = self._edge.reach.get_rk_min()
|
_min = self._edge.reach.get_kp_min()
|
||||||
_max = self._edge.reach.get_rk_max()
|
_max = self._edge.reach.get_kp_max()
|
||||||
|
|
||||||
if _min <= begin_rk <= _max:
|
if _min <= begin_kp <= _max:
|
||||||
self._begin_rk = begin_rk
|
self._begin_kp = begin_kp
|
||||||
|
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def end_rk(self):
|
def end_kp(self):
|
||||||
return self._end_rk
|
return self._end_kp
|
||||||
|
|
||||||
@end_rk.setter
|
@end_kp.setter
|
||||||
def end_rk(self, end_rk):
|
def end_kp(self, end_kp):
|
||||||
if self._edge is None:
|
if self._edge is None:
|
||||||
self._end_rk = end_rk
|
self._end_kp = end_kp
|
||||||
else:
|
else:
|
||||||
_min = self._edge.reach.get_rk_min()
|
_min = self._edge.reach.get_kp_min()
|
||||||
_max = self._edge.reach.get_rk_max()
|
_max = self._edge.reach.get_kp_max()
|
||||||
|
|
||||||
if _min <= end_rk <= _max:
|
if _min <= end_kp <= _max:
|
||||||
self._end_rk = end_rk
|
self._end_kp = end_kp
|
||||||
|
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
@@ -393,8 +377,8 @@ class LateralContribution(SQLSubModel):
|
|||||||
def convert(self, cls):
|
def convert(self, cls):
|
||||||
new = cls(name=self.name, status=self._status)
|
new = cls(name=self.name, status=self._status)
|
||||||
new.edge = self.edge
|
new.edge = self.edge
|
||||||
new.begin_rk = self.begin_rk
|
new.begin_kp = self.begin_kp
|
||||||
new.end_rk = self.end_rk
|
new.end_kp = self.end_kp
|
||||||
|
|
||||||
for i, _ in enumerate(self.data):
|
for i, _ in enumerate(self.data):
|
||||||
new.add(i)
|
new.add(i)
|
||||||
|
|||||||
@@ -0,0 +1,215 @@
|
|||||||
|
# LateralContributionAdisTS.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import (
|
||||||
|
trace, timer,
|
||||||
|
old_pamhyr_date_to_timestamp,
|
||||||
|
date_iso_to_timestamp,
|
||||||
|
date_dmy_to_timestamp,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class LateralContributionAdisTS(SQLSubModel):
|
||||||
|
_sub_classes = []
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, pollutant: int = -1, name: str = "", status=None):
|
||||||
|
super(LateralContributionAdisTS, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = LateralContributionAdisTS._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._pollutant = pollutant
|
||||||
|
self._edge = None
|
||||||
|
self._begin_kp = 0.0
|
||||||
|
self._end_kp = 0.0
|
||||||
|
self._data = []
|
||||||
|
self._header = ["time", "rate"]
|
||||||
|
self._types = [float, float]
|
||||||
|
|
||||||
|
LateralContributionAdisTS._id_cnt = max(
|
||||||
|
LateralContributionAdisTS._id_cnt + 1, self.id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE lateral_contribution_adists(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
pollutant INTEGER NOT NULL,
|
||||||
|
edge INTEGER NOT NULL,
|
||||||
|
begin_kp REAL NOT NULL,
|
||||||
|
end_kp REAL NOT NULL,
|
||||||
|
FOREIGN KEY(pollutant) REFERENCES Pollutants(id),
|
||||||
|
FOREIGN KEY(edge) REFERENCES river_reach(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE lateral_contribution_data_adists(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
data0 TEXT NOT NULL,
|
||||||
|
data1 TEXT NOT NULL,
|
||||||
|
lc INTEGER,
|
||||||
|
FOREIGN KEY(lc) REFERENCES lateral_contribution(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, pollutant, edge, begin_kp, end_kp " +
|
||||||
|
"FROM lateral_contribution_adists"
|
||||||
|
)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for row in table:
|
||||||
|
lc = cls(
|
||||||
|
id=row[0],
|
||||||
|
pollutant=row[1],
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
lc.edge = row[2]
|
||||||
|
lc.begin_kp = row[3]
|
||||||
|
lc.end_kp = row[4]
|
||||||
|
|
||||||
|
values = execute(
|
||||||
|
"SELECT data0, data1 FROM lateral_contribution_data_adists " +
|
||||||
|
f"WHERE lc = '{lc.id}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write data
|
||||||
|
for v in values:
|
||||||
|
data0 = lc._types[0](v[0])
|
||||||
|
data1 = lc._types[1](v[1])
|
||||||
|
# Replace data at pos ind
|
||||||
|
lc._data.append((data0, data1))
|
||||||
|
|
||||||
|
new.append(lc)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
|
||||||
|
execute(f"DELETE FROM lateral_contribution_adists WHERE id = {self.id}")
|
||||||
|
execute(f"DELETE FROM lateral_contribution_data_adists WHERE lc = {self.id}")
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"lateral_contribution_adists(id, pollutant, edge, begin_kp, end_kp) " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, {self._pollutant}, {self.edge}, " +
|
||||||
|
f"{self._begin_kp}, {self._end_kp}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
for d in self._data:
|
||||||
|
data0 = self._db_format(str(d[0]))
|
||||||
|
data1 = self._db_format(str(d[1]))
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"lateral_contribution_data_adists(data0, data1, lc) " +
|
||||||
|
f"VALUES ('{data0}', {data1}, {self.id})"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def time_convert(cls, data):
|
||||||
|
if type(data) is str:
|
||||||
|
if data.count("-") == 2:
|
||||||
|
return date_iso_to_timestamp(data)
|
||||||
|
if data.count("/") == 2:
|
||||||
|
return date_dmy_to_timestamp(data)
|
||||||
|
if data.count(":") == 3:
|
||||||
|
return old_pamhyr_date_to_timestamp(data)
|
||||||
|
if data.count(":") == 2:
|
||||||
|
return old_pamhyr_date_to_timestamp("00:" + data)
|
||||||
|
if data.count(".") == 1:
|
||||||
|
return round(float(data))
|
||||||
|
|
||||||
|
return int(data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def edge(self):
|
||||||
|
return self._edge
|
||||||
|
|
||||||
|
@edge.setter
|
||||||
|
def edge(self, edge):
|
||||||
|
self._edge = edge
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def header(self):
|
||||||
|
return self._header.copy()
|
||||||
|
|
||||||
|
@header.setter
|
||||||
|
def header(self, header):
|
||||||
|
self._header = header
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pollutant(self):
|
||||||
|
return self._pollutant
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data(self):
|
||||||
|
return self._data.copy()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def begin_kp(self):
|
||||||
|
return self._begin_kp
|
||||||
|
|
||||||
|
@begin_kp.setter
|
||||||
|
def begin_kp(self, begin_kp):
|
||||||
|
self._begin_kp = begin_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_kp(self):
|
||||||
|
return self._end_kp
|
||||||
|
|
||||||
|
@end_kp.setter
|
||||||
|
def end_kp(self, end_kp):
|
||||||
|
self._end_kp = end_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# LateralContributionsAdisTSList.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 copy import copy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrList import PamhyrModelList
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
from Model.LateralContributionsAdisTS.LateralContributionAdisTS import LateralContributionAdisTS
|
||||||
|
|
||||||
|
class LateralContributionsAdisTSList(PamhyrModelList):
|
||||||
|
_sub_classes = [
|
||||||
|
LateralContributionAdisTS,
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = cls(status=data['status'])
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
new._lst = LateralContributionAdisTS._db_load(
|
||||||
|
execute, data
|
||||||
|
)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute("DELETE FROM lateral_contribution_adists")
|
||||||
|
execute("DELETE FROM lateral_condition_data_adists")
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
for lc in self._lst:
|
||||||
|
lc._db_save(execute, data=data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def new(self, index, pollutant):
|
||||||
|
n = LateralContributionAdisTS(pollutant=pollutant, status=self._status)
|
||||||
|
self._lst.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
@property
|
||||||
|
def Lat_Cont_List(self):
|
||||||
|
return self.lst
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
# OutputKpAdists.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import (
|
||||||
|
trace, timer,
|
||||||
|
old_pamhyr_date_to_timestamp,
|
||||||
|
date_iso_to_timestamp,
|
||||||
|
date_dmy_to_timestamp,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class OutputKpAdists(SQLSubModel):
|
||||||
|
_sub_classes = []
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, reach = None, kp = None, title: str = "", status=None):
|
||||||
|
super(OutputKpAdists, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = OutputKpAdists._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._reach = reach
|
||||||
|
self._kp = kp
|
||||||
|
self._title = str(title)
|
||||||
|
self._enabled = True
|
||||||
|
|
||||||
|
OutputKpAdists._id_cnt = max(
|
||||||
|
OutputKpAdists._id_cnt + 1, self.id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reach(self):
|
||||||
|
return self._reach
|
||||||
|
|
||||||
|
@reach.setter
|
||||||
|
def reach(self, reach_id):
|
||||||
|
self._reach = reach_id
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def kp(self):
|
||||||
|
return self._kp
|
||||||
|
|
||||||
|
@kp.setter
|
||||||
|
def kp(self, profile_id):
|
||||||
|
self._kp = profile_id
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def title(self):
|
||||||
|
return self._title
|
||||||
|
|
||||||
|
@title.setter
|
||||||
|
def title(self, title):
|
||||||
|
self._title = title
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"CREATE TABLE OutputKpAdists(" +
|
||||||
|
"id INTEGER NOT NULL PRIMARY KEY, " +
|
||||||
|
"reach INTEGER NOT NULL, " +
|
||||||
|
"kp REAL NOT NULL, " +
|
||||||
|
"title TEXT NOT NULL, " +
|
||||||
|
"FOREIGN KEY(reach) REFERENCES river_reach(id)" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
#reach = data["reach"]
|
||||||
|
#profile = data["profile"]
|
||||||
|
status = data["status"]
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, reach, kp, title " +
|
||||||
|
f"FROM OutputKpAdists"
|
||||||
|
)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for row in table:
|
||||||
|
id = row[0]
|
||||||
|
id_reach = row[1]
|
||||||
|
id_kp = row[2]
|
||||||
|
title = row[3]
|
||||||
|
|
||||||
|
new_output = cls(
|
||||||
|
id=id, reach=id_reach,
|
||||||
|
kp=id_kp, title=title,
|
||||||
|
status=status
|
||||||
|
)
|
||||||
|
|
||||||
|
new.append(new_output)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
|
||||||
|
execute(f"DELETE FROM OutputKpAdists WHERE id = {self.id}")
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"OutputKpAdists(id, reach, kp, title) " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, {self._reach}, {self._kp}, " +
|
||||||
|
f"'{self._db_format(self._title)}'" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# OutputKpListAdists.py -- Pamhyr
|
||||||
|
# Copyright (C) 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 tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
from Model.Tools.PamhyrList import PamhyrModelList
|
||||||
|
from Model.OutputKpAdists.OutputKpAdists import OutputKpAdists
|
||||||
|
|
||||||
|
|
||||||
|
class OutputKpAdistsList(PamhyrModelList):
|
||||||
|
_sub_classes = [OutputKpAdists]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = cls(status=data["status"])
|
||||||
|
|
||||||
|
new._lst = OutputKpAdists._db_load(execute, data)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
ok = True
|
||||||
|
|
||||||
|
# Delete previous data
|
||||||
|
execute("DELETE FROM OutputKpAdists")
|
||||||
|
|
||||||
|
for sl in self._lst:
|
||||||
|
ok &= sl._db_save(execute, data)
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
@property
|
||||||
|
def OutputKp_List(self):
|
||||||
|
return self.lst
|
||||||
|
|
||||||
|
def new(self, lst, index):
|
||||||
|
n = OutputKpAdists(status=self._status)
|
||||||
|
self._lst.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
# Pollutants.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import (
|
||||||
|
trace, timer,
|
||||||
|
old_pamhyr_date_to_timestamp,
|
||||||
|
date_iso_to_timestamp,
|
||||||
|
date_dmy_to_timestamp,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class Pollutants(SQLSubModel):
|
||||||
|
_sub_classes = []
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, name: str = "", status=None):
|
||||||
|
super(Pollutants, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = Pollutants._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._name = str(name)
|
||||||
|
self._enabled = True
|
||||||
|
|
||||||
|
self._data = []
|
||||||
|
|
||||||
|
Pollutants._id_cnt = max(
|
||||||
|
Pollutants._id_cnt + 1, self.id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, name):
|
||||||
|
self._name = name
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data(self):
|
||||||
|
return self._data.copy()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE Pollutants(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL UNIQUE
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE Pollutants_characteristics(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
type INTEGER NOT NULL,
|
||||||
|
diametre REAL NOT NULL,
|
||||||
|
rho REAL NOT NULL,
|
||||||
|
porosity REAL NOT NULL,
|
||||||
|
cdc_riv REAL NOT NULL,
|
||||||
|
cdc_cas REAL NOT NULL,
|
||||||
|
apd REAL NOT NULL,
|
||||||
|
ac REAL NOT NULL,
|
||||||
|
bc REAL NOT NULL,
|
||||||
|
pollutant INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(pollutant) REFERENCES Pollutants(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
status = data["status"]
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, name " +
|
||||||
|
f"FROM Pollutants"
|
||||||
|
)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for row in table:
|
||||||
|
id = row[0]
|
||||||
|
name = row[1]
|
||||||
|
|
||||||
|
new_pollutant = cls(
|
||||||
|
id=id, name=name,
|
||||||
|
status=status
|
||||||
|
)
|
||||||
|
|
||||||
|
new_data = []
|
||||||
|
table = execute(
|
||||||
|
"SELECT * " +
|
||||||
|
"FROM Pollutants_characteristics " +
|
||||||
|
f"WHERE pollutant = {id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for t in table:
|
||||||
|
new_data = t[1:]
|
||||||
|
|
||||||
|
new_pollutant._data.append(new_data)
|
||||||
|
|
||||||
|
new.append(new_pollutant)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
|
||||||
|
execute(f"DELETE FROM Pollutants WHERE id = {self.id}")
|
||||||
|
execute(f"DELETE FROM Pollutants_characteristics WHERE pollutant = {self.id}")
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"Pollutants(id, name) " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, " +
|
||||||
|
f"'{self._db_format(self._name)}'" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
for d in self._data:
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"Pollutants_characteristics(type, diametre, rho, porosity, " +
|
||||||
|
"cdc_riv, cdc_cas, apd, ac, bc, pollutant) " +
|
||||||
|
f"VALUES ({d[0]}, {d[1]}, {d[2]},{d[3]}, {d[4]}, "
|
||||||
|
f"{d[5]}, {d[6]}, {d[7]}, {d[8]}, {self.id})"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def is_define(self):
|
||||||
|
return len(self._data) != 0
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# PollutantsList.py -- Pamhyr
|
||||||
|
# Copyright (C) 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 tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
from Model.Tools.PamhyrList import PamhyrModelList
|
||||||
|
from Model.Pollutants.Pollutants import Pollutants
|
||||||
|
|
||||||
|
|
||||||
|
class PollutantsList(PamhyrModelList):
|
||||||
|
_sub_classes = [Pollutants]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = cls(status=data["status"])
|
||||||
|
|
||||||
|
new._lst = Pollutants._db_load(execute, data)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
ok = True
|
||||||
|
|
||||||
|
# Delete previous data
|
||||||
|
execute("DELETE FROM Pollutants")
|
||||||
|
|
||||||
|
for sl in self._lst:
|
||||||
|
ok &= sl._db_save(execute, data)
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
@property
|
||||||
|
def Pollutants_List(self):
|
||||||
|
return self.lst
|
||||||
|
|
||||||
|
def new(self, lst, index):
|
||||||
|
n = Pollutants(status=self._status)
|
||||||
|
self._lst.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
@@ -35,8 +35,8 @@ class Profile(object):
|
|||||||
return self._profile.name
|
return self._profile.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rk(self):
|
def kp(self):
|
||||||
return self._profile.rk
|
return self._profile.kp
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def geometry(self):
|
def geometry(self):
|
||||||
|
|||||||
@@ -45,6 +45,14 @@ from Model.REPLine.REPLineList import REPLineList
|
|||||||
|
|
||||||
from Solver.Solvers import solver_type_list
|
from Solver.Solvers import solver_type_list
|
||||||
|
|
||||||
|
from Model.OutputKpAdists.OutputKpListAdists import OutputKpAdistsList
|
||||||
|
from Model.Pollutants.PollutantsList import PollutantsList
|
||||||
|
from Model.InitialConditionsAdisTS.InitialConditionsAdisTSList import InitialConditionsAdisTSList
|
||||||
|
from Model.BoundaryConditionsAdisTS.BoundaryConditionsAdisTSList import BoundaryConditionsAdisTSList
|
||||||
|
from Model.LateralContributionsAdisTS.LateralContributionsAdisTSList import LateralContributionsAdisTSList
|
||||||
|
from Model.D90AdisTS.D90AdisTSList import D90AdisTSList
|
||||||
|
from Model.DIFAdisTS.DIFAdisTSList import DIFAdisTSList
|
||||||
|
|
||||||
|
|
||||||
class RiverNode(Node, SQLSubModel):
|
class RiverNode(Node, SQLSubModel):
|
||||||
_sub_classes = []
|
_sub_classes = []
|
||||||
@@ -228,6 +236,13 @@ class River(Graph, SQLSubModel):
|
|||||||
HydraulicStructureList,
|
HydraulicStructureList,
|
||||||
AddFileList,
|
AddFileList,
|
||||||
REPLineList,
|
REPLineList,
|
||||||
|
OutputKpAdistsList,
|
||||||
|
PollutantsList,
|
||||||
|
InitialConditionsAdisTSList,
|
||||||
|
BoundaryConditionsAdisTSList,
|
||||||
|
LateralContributionsAdisTSList,
|
||||||
|
D90AdisTSList,
|
||||||
|
DIFAdisTSList,
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, status=None):
|
def __init__(self, status=None):
|
||||||
@@ -251,6 +266,13 @@ class River(Graph, SQLSubModel):
|
|||||||
)
|
)
|
||||||
self._additional_files = AddFileList(status=self._status)
|
self._additional_files = AddFileList(status=self._status)
|
||||||
self._rep_lines = REPLineList(status=self._status)
|
self._rep_lines = REPLineList(status=self._status)
|
||||||
|
self._Output_kp_adists = OutputKpAdistsList(status=self._status)
|
||||||
|
self._Pollutants = PollutantsList(status=self._status)
|
||||||
|
self._InitialConditionsAdisTS = InitialConditionsAdisTSList(status=self._status)
|
||||||
|
self._BoundaryConditionsAdisTS = BoundaryConditionsAdisTSList(status=self._status)
|
||||||
|
self._LateralContributionsAdisTS = LateralContributionsAdisTSList(status=self._status)
|
||||||
|
self._D90AdisTS = D90AdisTSList(status=self._status)
|
||||||
|
self._DIFAdisTS = DIFAdisTSList(status=self._status)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
@@ -325,6 +347,22 @@ class River(Graph, SQLSubModel):
|
|||||||
)
|
)
|
||||||
new._rep_lines = REPLineList._db_load(execute, data)
|
new._rep_lines = REPLineList._db_load(execute, data)
|
||||||
|
|
||||||
|
new._Output_kp_adists = OutputKpAdistsList._db_load(
|
||||||
|
execute, data
|
||||||
|
)
|
||||||
|
|
||||||
|
new._Pollutants = PollutantsList._db_load(execute, data)
|
||||||
|
|
||||||
|
new._InitialConditionsAdisTS = InitialConditionsAdisTSList._db_load(execute, data)
|
||||||
|
|
||||||
|
new._BoundaryConditionsAdisTS = BoundaryConditionsAdisTSList._db_load(execute, data)
|
||||||
|
|
||||||
|
new._LateralContributionsAdisTS = LateralContributionsAdisTSList._db_load(execute, data)
|
||||||
|
|
||||||
|
new._D90AdisTS = D90AdisTSList._db_load(execute, data)
|
||||||
|
|
||||||
|
new._DIFAdisTS = DIFAdisTSList._db_load(execute, data)
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
def _db_save(self, execute, data=None):
|
||||||
@@ -344,6 +382,14 @@ class River(Graph, SQLSubModel):
|
|||||||
for solver in self._parameters:
|
for solver in self._parameters:
|
||||||
objs.append(self._parameters[solver])
|
objs.append(self._parameters[solver])
|
||||||
|
|
||||||
|
objs.append(self._Output_kp_adists)
|
||||||
|
objs.append(self._Pollutants)
|
||||||
|
objs.append(self._InitialConditionsAdisTS)
|
||||||
|
objs.append(self._BoundaryConditionsAdisTS)
|
||||||
|
objs.append(self._LateralContributionsAdisTS)
|
||||||
|
objs.append(self._D90AdisTS)
|
||||||
|
objs.append(self._DIFAdisTS)
|
||||||
|
|
||||||
self._save_submodel(execute, objs, data)
|
self._save_submodel(execute, objs, data)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -466,6 +512,34 @@ Last export at: @date."""
|
|||||||
def parameters(self):
|
def parameters(self):
|
||||||
return self._parameters
|
return self._parameters
|
||||||
|
|
||||||
|
@property
|
||||||
|
def Output_kp_adists(self):
|
||||||
|
return self._Output_kp_adists
|
||||||
|
|
||||||
|
@property
|
||||||
|
def Pollutants(self):
|
||||||
|
return self._Pollutants
|
||||||
|
|
||||||
|
@property
|
||||||
|
def initial_conditions_adists(self):
|
||||||
|
return self._InitialConditionsAdisTS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def boundary_conditions_adists(self):
|
||||||
|
return self._BoundaryConditionsAdisTS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lateral_contributions_adists(self):
|
||||||
|
return self._LateralContributionsAdisTS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def d90_adists(self):
|
||||||
|
return self._D90AdisTS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dif_adists(self):
|
||||||
|
return self._DIFAdisTS
|
||||||
|
|
||||||
def get_params(self, solver):
|
def get_params(self, solver):
|
||||||
if solver in self._parameters:
|
if solver in self._parameters:
|
||||||
return self._parameters[solver]
|
return self._parameters[solver]
|
||||||
|
|||||||
+5
-5
@@ -41,7 +41,7 @@ class Study(SQLModel):
|
|||||||
|
|
||||||
def __init__(self, filename=None, init_new=True):
|
def __init__(self, filename=None, init_new=True):
|
||||||
# Metadata
|
# Metadata
|
||||||
self._version = "0.0.11"
|
self._version = "0.0.10"
|
||||||
self.creation_date = datetime.now()
|
self.creation_date = datetime.now()
|
||||||
self.last_modification_date = datetime.now()
|
self.last_modification_date = datetime.now()
|
||||||
self.last_save_date = datetime.now()
|
self.last_save_date = datetime.now()
|
||||||
@@ -72,7 +72,7 @@ class Study(SQLModel):
|
|||||||
StudyNetworkReachChecker(),
|
StudyNetworkReachChecker(),
|
||||||
StudyGeometryChecker(),
|
StudyGeometryChecker(),
|
||||||
StudyInitialConditionsChecker(),
|
StudyInitialConditionsChecker(),
|
||||||
StudyBoundaryConditionChecker(),
|
#StudyBoundaryConditionChecker(),
|
||||||
# DummyOK(),
|
# DummyOK(),
|
||||||
# DummyWARNING(),
|
# DummyWARNING(),
|
||||||
# DummyERROR(),
|
# DummyERROR(),
|
||||||
@@ -230,16 +230,16 @@ class Study(SQLModel):
|
|||||||
)
|
)
|
||||||
self.execute(
|
self.execute(
|
||||||
"INSERT INTO info VALUES ('date', " +
|
"INSERT INTO info VALUES ('date', " +
|
||||||
f"'{timestamp(self._date)}')"
|
f"'{self._date.timestamp()}')"
|
||||||
)
|
)
|
||||||
|
|
||||||
self.execute(
|
self.execute(
|
||||||
"INSERT INTO info VALUES ('creation_date', " +
|
"INSERT INTO info VALUES ('creation_date', " +
|
||||||
f"'{timestamp(self.creation_date)}')"
|
f"'{self.creation_date.timestamp()}')"
|
||||||
)
|
)
|
||||||
self.execute(
|
self.execute(
|
||||||
"INSERT INTO info VALUES ('last_save_date', " +
|
"INSERT INTO info VALUES ('last_save_date', " +
|
||||||
f"'{timestamp(self.last_save_date)}')"
|
f"'{self.last_save_date.timestamp()}')"
|
||||||
)
|
)
|
||||||
|
|
||||||
self._create_submodel()
|
self._create_submodel()
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class Modules(IterableFlag):
|
|||||||
RESERVOIR = auto()
|
RESERVOIR = auto()
|
||||||
SEDIMENT_LAYER = auto()
|
SEDIMENT_LAYER = auto()
|
||||||
ADDITIONAL_FILES = auto()
|
ADDITIONAL_FILES = auto()
|
||||||
|
OUTPUT_KP = auto()
|
||||||
|
|
||||||
# Results
|
# Results
|
||||||
RESULTS = auto()
|
RESULTS = auto()
|
||||||
@@ -77,6 +78,7 @@ class Modules(IterableFlag):
|
|||||||
cls.ADDITIONAL_FILES,
|
cls.ADDITIONAL_FILES,
|
||||||
cls.RESULTS,
|
cls.RESULTS,
|
||||||
cls.WINDOW_LIST,
|
cls.WINDOW_LIST,
|
||||||
|
cls.OUTPUT_KP,
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -0,0 +1,494 @@
|
|||||||
|
# AdisTS.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 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from tools import (
|
||||||
|
trace, timer, logger_exception,
|
||||||
|
timestamp_to_old_pamhyr_date,
|
||||||
|
old_pamhyr_date_to_timestamp,
|
||||||
|
timestamp_to_old_pamhyr_date_adists
|
||||||
|
)
|
||||||
|
|
||||||
|
from Solver.CommandLine import CommandLineSolver
|
||||||
|
|
||||||
|
from Model.Results.Results import Results
|
||||||
|
from Model.Results.River.River import River, Reach, Profile
|
||||||
|
|
||||||
|
from Checker.Adists import (
|
||||||
|
AdistsOutputKpChecker,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
def adists_file_open(filepath, mode):
|
||||||
|
f = open(filepath, mode)
|
||||||
|
|
||||||
|
if "w" in mode:
|
||||||
|
# Write header
|
||||||
|
comment = "*"
|
||||||
|
if ".ST" in filepath:
|
||||||
|
comment = "#"
|
||||||
|
|
||||||
|
f.write(
|
||||||
|
f"{comment} " +
|
||||||
|
"This file is generated by PAMHYR, please don't modify\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
return f
|
||||||
|
|
||||||
|
class AdisTS(CommandLineSolver):
|
||||||
|
_type = "adists"
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
super(AdisTS, self).__init__(name)
|
||||||
|
|
||||||
|
self._type = "adists"
|
||||||
|
|
||||||
|
self._cmd_input = ""
|
||||||
|
self._cmd_solver = "@path @input -o @output"
|
||||||
|
self._cmd_output = ""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def default_parameters(cls):
|
||||||
|
lst = super(AdisTS, cls).default_parameters()
|
||||||
|
|
||||||
|
lst += [
|
||||||
|
("adists_implicitation_parameter", "0.5"),
|
||||||
|
("adists_timestep_screen", "60"),
|
||||||
|
("adists_timestep_bin", "60"),
|
||||||
|
("adists_timestep_csv", "60"),
|
||||||
|
("adists_timestep_mage", "60"),
|
||||||
|
("adists_initial_concentration", "60"),
|
||||||
|
]
|
||||||
|
|
||||||
|
return lst
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def checkers(cls):
|
||||||
|
lst = [
|
||||||
|
AdistsOutputKpChecker(),
|
||||||
|
]
|
||||||
|
|
||||||
|
return lst
|
||||||
|
|
||||||
|
def cmd_args(self, study):
|
||||||
|
lst = super(AdisTS, self).cmd_args(study)
|
||||||
|
return lst
|
||||||
|
|
||||||
|
def input_param(self):
|
||||||
|
name = self._study.name
|
||||||
|
return f"{name}.REP"
|
||||||
|
|
||||||
|
def log_file(self):
|
||||||
|
name = self._study.name
|
||||||
|
return f"{name}.TRA"
|
||||||
|
|
||||||
|
def _export_REP_additional_lines(self, study, rep_file):
|
||||||
|
lines = filter(
|
||||||
|
lambda line: line.is_enabled(),
|
||||||
|
study.river.rep_lines.lines
|
||||||
|
)
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
rep_file.write(line.line)
|
||||||
|
|
||||||
|
def _export_REP(self, study, repertory, files, qlog, name="0"):
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export REP file")
|
||||||
|
|
||||||
|
# Write header
|
||||||
|
with adists_file_open(
|
||||||
|
os.path.join(
|
||||||
|
repertory, f"{name}.REP"
|
||||||
|
), "w+"
|
||||||
|
) as f:
|
||||||
|
|
||||||
|
f.write(f"NET ../default-mage/{name}.NET\n")
|
||||||
|
f.write(f"REP ../default-mage/{name}.REP\n")
|
||||||
|
|
||||||
|
for file in files:
|
||||||
|
EXT = file.split('.')[1]
|
||||||
|
f.write(f"{EXT} {file}\n")
|
||||||
|
|
||||||
|
self._export_REP_additional_lines(study, f)
|
||||||
|
|
||||||
|
path_mage_net = os.path.join(os.path.abspath(os.path.join(repertory, os.pardir)), f"default-mage/net")
|
||||||
|
path_adists_net = os.path.join(repertory, "net")
|
||||||
|
|
||||||
|
if os.path.exists(path_mage_net):
|
||||||
|
shutil.copytree(path_mage_net, path_adists_net, dirs_exist_ok=True)
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def export(self, study, repertory, qlog=None):
|
||||||
|
self._study = study
|
||||||
|
name = study.name.replace(" ", "_")
|
||||||
|
|
||||||
|
self.export_additional_files(study, repertory, qlog, name=name)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
###########
|
||||||
|
# RESULTS #
|
||||||
|
###########
|
||||||
|
|
||||||
|
def read_bin(self, study, repertory, results, qlog=None, name="0"):
|
||||||
|
return
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def results(self, study, repertory, qlog=None, name="0"):
|
||||||
|
results = Results(
|
||||||
|
study=study,
|
||||||
|
solver=self,
|
||||||
|
repertory=repertory,
|
||||||
|
name=name,
|
||||||
|
)
|
||||||
|
self.read_bin(study, repertory, results, qlog, name=name)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def output_param(self):
|
||||||
|
name = ""
|
||||||
|
return f"{name}"
|
||||||
|
|
||||||
|
################################
|
||||||
|
# Adis-TS in low coupling mode #
|
||||||
|
################################
|
||||||
|
|
||||||
|
|
||||||
|
class AdisTSlc(AdisTS):
|
||||||
|
_type = "adistslc"
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
super(AdisTSlc, self).__init__(name)
|
||||||
|
|
||||||
|
self._type = "adistslc"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def default_parameters(cls):
|
||||||
|
lst = super(AdisTSlc, cls).default_parameters()
|
||||||
|
|
||||||
|
# Insert new parameters at specific position
|
||||||
|
names = list(map(lambda t: t[0], lst))
|
||||||
|
|
||||||
|
return lst
|
||||||
|
|
||||||
|
##########
|
||||||
|
# Export #
|
||||||
|
##########
|
||||||
|
|
||||||
|
def cmd_args(self, study):
|
||||||
|
lst = super(AdisTSlc, self).cmd_args(study)
|
||||||
|
|
||||||
|
return lst
|
||||||
|
|
||||||
|
def _export_POLs(self, study, repertory, qlog=None, name="0"):
|
||||||
|
|
||||||
|
files = []
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export POLS files")
|
||||||
|
|
||||||
|
pollutants = study.river.Pollutants.Pollutants_List
|
||||||
|
|
||||||
|
for pollutant in pollutants:
|
||||||
|
name = pollutant.name
|
||||||
|
with adists_file_open(os.path.join(repertory, f"{name}.POL"), "w+") as f:
|
||||||
|
files.append(f"{name}.POL")
|
||||||
|
f.write(f"*Polluant A contaminé aux PCB\n")
|
||||||
|
f.write(f"name = {name}\n")
|
||||||
|
|
||||||
|
self._export_POL_Characteristics(study, pollutant._data, f, qlog)
|
||||||
|
|
||||||
|
POL_ICs = next(filter(lambda ic: ic.pollutant == pollutant.id,\
|
||||||
|
study.river.initial_conditions_adists.Initial_Conditions_List))
|
||||||
|
|
||||||
|
if POL_ICs.concentration != None:
|
||||||
|
f.write(f"file_ini = {name}.INI\n")
|
||||||
|
self._export_ICs_AdisTS(study, repertory, POL_ICs, qlog, name)
|
||||||
|
|
||||||
|
POL_BCs = list(filter(lambda bc: bc.pollutant == pollutant.id,\
|
||||||
|
study.river.boundary_conditions_adists.BCs_AdisTS_List))
|
||||||
|
|
||||||
|
if len(POL_BCs) != 0:
|
||||||
|
f.write(f"file_cl = {name}.CDT\n")
|
||||||
|
self._export_BCs_AdisTS(study, repertory, POL_BCs, qlog, name)
|
||||||
|
|
||||||
|
POL_LAT_Cont = list(filter(lambda lc: lc.pollutant == pollutant.id,\
|
||||||
|
study.river.lateral_contributions_adists.Lat_Cont_List))
|
||||||
|
|
||||||
|
if len(POL_LAT_Cont) != 0:
|
||||||
|
f.write(f"file_ald = {name}.ALD\n")
|
||||||
|
f.write(f"*\n")
|
||||||
|
self._export_Lat_AdisTS(study, repertory, POL_LAT_Cont, qlog, name)
|
||||||
|
|
||||||
|
return files
|
||||||
|
|
||||||
|
def _export_Lat_AdisTS(self, study, repertory, POL_LC, qlog, POL_name):
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export POL LCs files")
|
||||||
|
|
||||||
|
with adists_file_open(os.path.join(repertory, f"{POL_name}.ALD"), "w+") as f:
|
||||||
|
for LC in POL_LC:
|
||||||
|
reach_name = next(filter(lambda edge: edge.id == LC.edge, study.river.edges())).name
|
||||||
|
f.write(f"${reach_name} {LC.begin_kp} {LC.end_kp}\n")
|
||||||
|
f.write(f"*temps |débit massique (kg/s)\n")
|
||||||
|
f.write(f"*---------++++++++++\n")
|
||||||
|
|
||||||
|
for LC_data in LC._data:
|
||||||
|
f.write(f"{timestamp_to_old_pamhyr_date_adists(int(LC_data[0]))} {LC_data[1]}\n")
|
||||||
|
f.write(f"*\n")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _export_BCs_AdisTS(self, study, repertory, POL_BC, qlog, POL_name):
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export POL BCs files")
|
||||||
|
|
||||||
|
with adists_file_open(os.path.join(repertory, f"{POL_name}.CDT"), "w+") as f:
|
||||||
|
for BC in POL_BC:
|
||||||
|
node_name = next(filter(lambda x: x.id == BC.node, study.river._nodes)).name
|
||||||
|
f.write(f"${node_name}\n")
|
||||||
|
|
||||||
|
if BC.type == "Concentration":
|
||||||
|
f.write(f"*temps |concentration\n")
|
||||||
|
f.write(f"*JJ:HH:MM | (g/L)\n")
|
||||||
|
f.write(f"*---------++++++++++\n")
|
||||||
|
else:
|
||||||
|
f.write(f"*temps |rate\n")
|
||||||
|
f.write(f"*JJ:HH:MM | (kg/s)\n")
|
||||||
|
f.write(f"*---------++++++++++\n")
|
||||||
|
|
||||||
|
for BC_data in BC._data:
|
||||||
|
f.write(f"{timestamp_to_old_pamhyr_date_adists(int(BC_data[0]))} {BC_data[1]}\n")
|
||||||
|
f.write(f"*\n")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _export_ICs_AdisTS(self, study, repertory, POL_IC_default, qlog, POL_name):
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export POL ICs files")
|
||||||
|
|
||||||
|
with adists_file_open(os.path.join(repertory, f"{POL_name}.INI"), "w+") as f:
|
||||||
|
f.write(f"*État initial pour le polluant {POL_name}\n")
|
||||||
|
f.write(f"{POL_IC_default.name} = {POL_IC_default.concentration} {POL_IC_default.eg} "+
|
||||||
|
f"{POL_IC_default.em} {POL_IC_default.ed}\n")
|
||||||
|
|
||||||
|
if len(POL_IC_default._data) != 0:
|
||||||
|
self._export_ICs_AdisTS_Spec(study, POL_IC_default._data, f, qlog)
|
||||||
|
|
||||||
|
def _export_ICs_AdisTS_Spec(self, study, pol_ics_spec_data, f, qlog, name="0"):
|
||||||
|
|
||||||
|
for ic_spec in pol_ics_spec_data:
|
||||||
|
f.write(f"{ic_spec.name} = {ic_spec.reach} {ic_spec.start_kp} {ic_spec.end_kp} " +
|
||||||
|
f"{ic_spec.concentration} {ic_spec.eg} {ic_spec.em} {ic_spec.ed} {ic_spec.rate}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _export_POL_Characteristics(self, study, pol_data, f, qlog, name="0"):
|
||||||
|
|
||||||
|
list_characteristics = ["type", "diametre", "rho", "porosity", "cdc_riv", "cdc_cas", "apd", "ac", "bc"]
|
||||||
|
|
||||||
|
if len(list_characteristics) == (len(pol_data[0])-1):
|
||||||
|
for l in range(len(list_characteristics)):
|
||||||
|
f.write(f"{list_characteristics[l]} = {pol_data[0][l]}\n")
|
||||||
|
|
||||||
|
def _export_D90(self, study, repertory, qlog=None, name="0"):
|
||||||
|
|
||||||
|
files = []
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export D90 file")
|
||||||
|
|
||||||
|
with adists_file_open(os.path.join(repertory, f"{name}.D90"), "w+") as f:
|
||||||
|
files.append(f"{name}.D90")
|
||||||
|
|
||||||
|
f.write(f"*Diamètres caractéristiques du fond stable\n")
|
||||||
|
|
||||||
|
d90AdisTS = study.river.d90_adists.D90_AdisTS_List
|
||||||
|
|
||||||
|
f.write(f"{d90AdisTS[0].name} = {d90AdisTS[0].d90}\n")
|
||||||
|
|
||||||
|
self._export_d90_spec(study, d90AdisTS[0]._data, f, qlog)
|
||||||
|
|
||||||
|
return files
|
||||||
|
|
||||||
|
def _export_d90_spec(self, study, d90_spec_data, f, qlog, name="0"):
|
||||||
|
|
||||||
|
for d90_spec in d90_spec_data:
|
||||||
|
if (d90_spec.name is None) or (d90_spec.reach is None) or (d90_spec.start_kp is None) or \
|
||||||
|
(d90_spec.end_kp is None) or (d90_spec.d90 is None):
|
||||||
|
return
|
||||||
|
|
||||||
|
edges = study.river.enable_edges()
|
||||||
|
|
||||||
|
id_edges = list(map(lambda x: x.id, edges))
|
||||||
|
|
||||||
|
id_reach = d90_spec.reach
|
||||||
|
|
||||||
|
if id_reach not in id_edges:
|
||||||
|
return
|
||||||
|
|
||||||
|
f.write(f"{d90_spec.name} = {id_reach} {d90_spec.start_kp} {d90_spec.end_kp} {d90_spec.d90}\n")
|
||||||
|
|
||||||
|
def _export_DIF(self, study, repertory, qlog=None, name="0"):
|
||||||
|
|
||||||
|
files = []
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export DIF file")
|
||||||
|
|
||||||
|
with adists_file_open(os.path.join(repertory, f"{name}.DIF"), "w+") as f:
|
||||||
|
files.append(f"{name}.DIF")
|
||||||
|
|
||||||
|
f.write(f"*Définition des paramètres des fonctions de calcul du\n")
|
||||||
|
f.write(f"*coefficient de diffusion\n")
|
||||||
|
|
||||||
|
difAdisTS = study.river.dif_adists.DIF_AdisTS_List
|
||||||
|
|
||||||
|
if difAdisTS[0].method != "generique":
|
||||||
|
f.write(f"defaut = {difAdisTS[0].method} {difAdisTS[0].dif }\n")
|
||||||
|
else:
|
||||||
|
f.write(f"defaut = {difAdisTS[0].method} {difAdisTS[0].dif} {difAdisTS[0].b} {difAdisTS[0].c}\n")
|
||||||
|
|
||||||
|
self._export_dif_spec(study, difAdisTS[0]._data, f, qlog)
|
||||||
|
|
||||||
|
return files
|
||||||
|
|
||||||
|
def _export_dif_spec(self, study, dif_spec_data, f, qlog, name="0"):
|
||||||
|
|
||||||
|
for dif_spec in dif_spec_data:
|
||||||
|
if (dif_spec.reach is None) or (dif_spec.start_kp is None) or \
|
||||||
|
(dif_spec.end_kp is None) or (dif_spec.dif is None) or (dif_spec.b is None) or (dif_spec.c is None):
|
||||||
|
return
|
||||||
|
|
||||||
|
edges = study.river.enable_edges()
|
||||||
|
|
||||||
|
id_edges = list(map(lambda x: x.id, edges))
|
||||||
|
|
||||||
|
id_reach = dif_spec.reach
|
||||||
|
|
||||||
|
if id_reach not in id_edges:
|
||||||
|
return
|
||||||
|
|
||||||
|
if dif_spec.method != "generique":
|
||||||
|
f.write(f"{dif_spec.method} = {id_reach} {dif_spec.start_kp} {dif_spec.end_kp} {dif_spec.dif}\n")
|
||||||
|
else:
|
||||||
|
f.write(f"{dif_spec.method} = {id_reach} {dif_spec.start_kp} {dif_spec.end_kp} {dif_spec.dif}" +
|
||||||
|
f"{dif_spec.b} {dif_spec.c}\n")
|
||||||
|
|
||||||
|
def _export_NUM(self, study, repertory, qlog=None, name="0"):
|
||||||
|
|
||||||
|
dict_names = {"init_time":"start_date",
|
||||||
|
"final_time":"end_date",
|
||||||
|
"timestep":"dt0",
|
||||||
|
"implicitation_parameter":"theta",
|
||||||
|
"timestep_screen":"dtscr",
|
||||||
|
"timestep_bin":"dtbin",
|
||||||
|
"timestep_csv":"dtcsv",
|
||||||
|
"timestep_mage":"dtMage",
|
||||||
|
"initial_concentration":"c_initiale"}
|
||||||
|
files = []
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export NUM file")
|
||||||
|
|
||||||
|
with adists_file_open(os.path.join(repertory, f"{name}.NUM"), "w+") as f:
|
||||||
|
files.append(f"{name}.NUM")
|
||||||
|
|
||||||
|
params = study.river.get_params(self.type).parameters
|
||||||
|
for p in params:
|
||||||
|
name = p.name\
|
||||||
|
.replace("all_", "")\
|
||||||
|
.replace("adists_", "")
|
||||||
|
value = p.value
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
f"export: NUM: {name}: {value} ({p.value})"
|
||||||
|
)
|
||||||
|
|
||||||
|
if name != "command_line_arguments":
|
||||||
|
f.write(f"{dict_names[name]} = {value}\n")
|
||||||
|
|
||||||
|
outputkps = study.river.Output_kp_adists.OutputKp_List
|
||||||
|
|
||||||
|
for outputkp in outputkps:
|
||||||
|
self._export_outputkp(study, outputkp, f, qlog)
|
||||||
|
|
||||||
|
return files
|
||||||
|
|
||||||
|
def _export_outputkp(self, study, outputkp, f, qlog, name="0"):
|
||||||
|
if (outputkp.reach is None) or (outputkp.kp is None) or (outputkp.title is None):
|
||||||
|
return
|
||||||
|
|
||||||
|
edges = study.river.enable_edges()
|
||||||
|
|
||||||
|
id_edges = list(map(lambda x: x.id, edges))
|
||||||
|
|
||||||
|
id_reach = outputkp.reach
|
||||||
|
kp = outputkp.kp
|
||||||
|
title = outputkp.title
|
||||||
|
|
||||||
|
if id_reach not in id_edges:
|
||||||
|
return
|
||||||
|
|
||||||
|
f.write(f"output = {id_reach} {kp} {title}\n")
|
||||||
|
|
||||||
|
def export_func_dict(self):
|
||||||
|
return [
|
||||||
|
self._export_NUM,
|
||||||
|
self._export_DIF,
|
||||||
|
self._export_D90,
|
||||||
|
self._export_POLs,
|
||||||
|
]
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def export(self, study, repertory, qlog=None, name="0"):
|
||||||
|
print("cmd solver adistslc : ", self._cmd_solver)
|
||||||
|
self._study = study
|
||||||
|
name = study.name.replace(" ", "_")
|
||||||
|
|
||||||
|
# Generate files
|
||||||
|
files = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
for func in self.export_func_dict():
|
||||||
|
files = files + func(study, repertory, qlog, name=name)
|
||||||
|
|
||||||
|
self.export_additional_files(study, repertory, qlog, name=name)
|
||||||
|
self._export_REP(study, repertory, files, qlog, name=name)
|
||||||
|
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to export study to {self._type}")
|
||||||
|
logger_exception(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -196,11 +196,17 @@ class CommandLineSolver(AbstractSolver):
|
|||||||
The executable and list of arguments
|
The executable and list of arguments
|
||||||
"""
|
"""
|
||||||
cmd = cmd.replace("@install_dir", self._install_dir())
|
cmd = cmd.replace("@install_dir", self._install_dir())
|
||||||
|
print("format command installDir :", self._install_dir())
|
||||||
cmd = cmd.replace("@path", "\"" + path + "\"")
|
cmd = cmd.replace("@path", "\"" + path + "\"")
|
||||||
|
print("format command path :", path)
|
||||||
cmd = cmd.replace("@input", self.input_param().replace(" ", "_"))
|
cmd = cmd.replace("@input", self.input_param().replace(" ", "_"))
|
||||||
|
print("format command input :", self.input_param().replace(" ", "_"))
|
||||||
cmd = cmd.replace("@output", self.output_param())
|
cmd = cmd.replace("@output", self.output_param())
|
||||||
|
print("format command output :", self.output_param())
|
||||||
cmd = cmd.replace("@dir", self._process.workingDirectory())
|
cmd = cmd.replace("@dir", self._process.workingDirectory())
|
||||||
|
print("format command dir :", self._process.workingDirectory())
|
||||||
cmd = cmd.replace("@args", " ".join(self.cmd_args(study)))
|
cmd = cmd.replace("@args", " ".join(self.cmd_args(study)))
|
||||||
|
print("format command args :", " ".join(self.cmd_args(study)))
|
||||||
|
|
||||||
logger.debug(f"! {cmd}")
|
logger.debug(f"! {cmd}")
|
||||||
|
|
||||||
@@ -237,7 +243,11 @@ class CommandLineSolver(AbstractSolver):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
cmd = self._cmd_solver
|
cmd = self._cmd_solver
|
||||||
|
print("run solver commandline cmd : ", cmd)
|
||||||
|
print("path solver : ", self._path_solver)
|
||||||
exe, args = self._format_command(study, cmd, self._path_solver)
|
exe, args = self._format_command(study, cmd, self._path_solver)
|
||||||
|
print("parsed cmd solver exe : ", exe)
|
||||||
|
print("parsed cmd solver args : ", args)
|
||||||
|
|
||||||
if not os.path.exists(exe):
|
if not os.path.exists(exe):
|
||||||
error = f"[ERROR] Path {exe} do not exists"
|
error = f"[ERROR] Path {exe} do not exists"
|
||||||
@@ -308,6 +318,11 @@ class CommandLineSolver(AbstractSolver):
|
|||||||
self._output.put(res)
|
self._output.put(res)
|
||||||
|
|
||||||
def run(self, study, process=None, output_queue=None):
|
def run(self, study, process=None, output_queue=None):
|
||||||
|
print("Run debug")
|
||||||
|
print("---------")
|
||||||
|
print("cmd input : ", self._cmd_input)
|
||||||
|
print("cmd solver : ", self._cmd_solver)
|
||||||
|
print("cmd output : ", self._cmd_output)
|
||||||
self._study = study
|
self._study = study
|
||||||
|
|
||||||
# Replace old values if needed
|
# Replace old values if needed
|
||||||
|
|||||||
+13
-13
@@ -180,7 +180,7 @@ class Mage(CommandLineSolver):
|
|||||||
c1 = f"{profile.code1:>6}"
|
c1 = f"{profile.code1:>6}"
|
||||||
c2 = f"{profile.code2:>6}"
|
c2 = f"{profile.code2:>6}"
|
||||||
t = f"{len(profile.points):>6}"
|
t = f"{len(profile.points):>6}"
|
||||||
rk = f"{profile.rk:>12f}"[0:12]
|
kp = f"{profile.kp:>12f}"[0:12]
|
||||||
pname = profile.name
|
pname = profile.name
|
||||||
if profile.name == "":
|
if profile.name == "":
|
||||||
# Generate name from profile id prefixed with
|
# Generate name from profile id prefixed with
|
||||||
@@ -207,7 +207,7 @@ class Mage(CommandLineSolver):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Profile header line
|
# Profile header line
|
||||||
wfile.write(f"{num}{c1}{c2}{t} {rk} {pname} {sediment}\n")
|
wfile.write(f"{num}{c1}{c2}{t} {kp} {pname} {sediment}\n")
|
||||||
|
|
||||||
def _export_ST_point_line(self, wfile, files, point):
|
def _export_ST_point_line(self, wfile, files, point):
|
||||||
x = f"{point.x:<12.4f}"[0:12]
|
x = f"{point.x:<12.4f}"[0:12]
|
||||||
@@ -339,7 +339,7 @@ class Mage(CommandLineSolver):
|
|||||||
f.write(f"* {lateral.edge.name} ({name}) {lateral.lctype}\n")
|
f.write(f"* {lateral.edge.name} ({name}) {lateral.lctype}\n")
|
||||||
f.write(
|
f.write(
|
||||||
f"${name} " +
|
f"${name} " +
|
||||||
f"{lateral.begin_rk:>10.4f} {lateral.end_rk:>10.4f}\n"
|
f"{lateral.begin_kp:>10.4f} {lateral.end_kp:>10.4f}\n"
|
||||||
)
|
)
|
||||||
header = lateral.header
|
header = lateral.header
|
||||||
f.write(f"*{header[0]:>9}|{header[1]:>10}\n")
|
f.write(f"*{header[0]:>9}|{header[1]:>10}\n")
|
||||||
@@ -371,17 +371,17 @@ class Mage(CommandLineSolver):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
num = f"{id:>3}"
|
num = f"{id:>3}"
|
||||||
brk = f"{friction.begin_rk:>10.3f}"
|
bkp = f"{friction.begin_kp:>10.3f}"
|
||||||
erk = f"{friction.end_rk:>10.3f}"
|
ekp = f"{friction.end_kp:>10.3f}"
|
||||||
|
|
||||||
# if friction.begin_rk != friction.end_rk:
|
# if friction.begin_kp != friction.end_kp:
|
||||||
# print("TODO")
|
# print("TODO")
|
||||||
|
|
||||||
strickler = friction.begin_strickler
|
strickler = friction.begin_strickler
|
||||||
coef_1 = f"{strickler.minor:>10.3f}"
|
coef_1 = f"{strickler.minor:>10.3f}"
|
||||||
coef_2 = f"{strickler.medium:>10.3f}"
|
coef_2 = f"{strickler.medium:>10.3f}"
|
||||||
|
|
||||||
f.write(f"K{num} {brk}{erk}{coef_1}{coef_2}\n")
|
f.write(f"K{num} {bkp}{ekp}{coef_1}{coef_2}\n")
|
||||||
|
|
||||||
id += 1
|
id += 1
|
||||||
|
|
||||||
@@ -401,7 +401,7 @@ class Mage(CommandLineSolver):
|
|||||||
|
|
||||||
# TODO put real date...
|
# TODO put real date...
|
||||||
f.write(f"$ date en minutes : 0.00\n")
|
f.write(f"$ date en minutes : 0.00\n")
|
||||||
f.write(f"* IB IS discharge elevation rk\n")
|
f.write(f"* IB IS discharge elevation kp\n")
|
||||||
|
|
||||||
id = 1
|
id = 1
|
||||||
for reach in reachs:
|
for reach in reachs:
|
||||||
@@ -418,9 +418,9 @@ class Mage(CommandLineSolver):
|
|||||||
IS = f"{id_sec}"
|
IS = f"{id_sec}"
|
||||||
discharge = f"{d['discharge']:>10.5f}"
|
discharge = f"{d['discharge']:>10.5f}"
|
||||||
elevation = f"{d['elevation']:>11.6f}"
|
elevation = f"{d['elevation']:>11.6f}"
|
||||||
rk = f"{d['rk']:>9.2f}"
|
kp = f"{d['kp']:>9.2f}"
|
||||||
|
|
||||||
f.write(f"{IR} {IS} {discharge} {elevation} {rk}\n")
|
f.write(f"{IR} {IS} {discharge} {elevation} {kp}\n")
|
||||||
id_sec += 1
|
id_sec += 1
|
||||||
|
|
||||||
id += 1
|
id += 1
|
||||||
@@ -495,12 +495,12 @@ class Mage(CommandLineSolver):
|
|||||||
if not hs.enabled:
|
if not hs.enabled:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if hs.input_rk is None:
|
if hs.input_kp is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
f.write(
|
f.write(
|
||||||
'* ouvrage au pk ' +
|
'* ouvrage au pk ' +
|
||||||
f"{float(hs.input_rk):>12.1f}" + ' ' +
|
f"{float(hs.input_kp):>12.1f}" + ' ' +
|
||||||
hs.name + '\n'
|
hs.name + '\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -527,7 +527,7 @@ class Mage(CommandLineSolver):
|
|||||||
|
|
||||||
f.write(
|
f.write(
|
||||||
f"{sin_dict[bhs._type]} " +
|
f"{sin_dict[bhs._type]} " +
|
||||||
f"{reach_id} {float(hs.input_rk):>12.3f} " +
|
f"{reach_id} {float(hs.input_kp):>12.3f} " +
|
||||||
f"{param_str} {name}\n"
|
f"{param_str} {name}\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+13
-13
@@ -265,10 +265,10 @@ class RubarBE(CommandLineSolver):
|
|||||||
|
|
||||||
ind = 1
|
ind = 1
|
||||||
for profile in reach.profiles:
|
for profile in reach.profiles:
|
||||||
rk = profile.rk
|
kp = profile.kp
|
||||||
n_points = len(profile)
|
n_points = len(profile)
|
||||||
|
|
||||||
f.write(f"{ind:>4} {rk:>11.3f} {n_points:>4}\n")
|
f.write(f"{ind:>4} {kp:>11.3f} {n_points:>4}\n")
|
||||||
|
|
||||||
for point in profile.points:
|
for point in profile.points:
|
||||||
label = point.name.lower()
|
label = point.name.lower()
|
||||||
@@ -307,8 +307,8 @@ class RubarBE(CommandLineSolver):
|
|||||||
lm = len(reach) + 1
|
lm = len(reach) + 1
|
||||||
f.write(f"{lm:>13}\n")
|
f.write(f"{lm:>13}\n")
|
||||||
|
|
||||||
for mails in [reach.inter_profiles_rk(),
|
for mails in [reach.inter_profiles_kp(),
|
||||||
reach.get_rk()]:
|
reach.get_kp()]:
|
||||||
ind = 0
|
ind = 0
|
||||||
for mail in mails:
|
for mail in mails:
|
||||||
f.write(f"{mail:15.3f}")
|
f.write(f"{mail:15.3f}")
|
||||||
@@ -338,7 +338,7 @@ class RubarBE(CommandLineSolver):
|
|||||||
lm = len(reach) + 1
|
lm = len(reach) + 1
|
||||||
f.write(f"{lm:>6}\n")
|
f.write(f"{lm:>6}\n")
|
||||||
|
|
||||||
def get_stricklers_from_rk(rk):
|
def get_stricklers_from_kp(kp):
|
||||||
return next(
|
return next(
|
||||||
map(
|
map(
|
||||||
lambda s: (
|
lambda s: (
|
||||||
@@ -346,15 +346,15 @@ class RubarBE(CommandLineSolver):
|
|||||||
else s.begin_strickler.minor
|
else s.begin_strickler.minor
|
||||||
),
|
),
|
||||||
filter(
|
filter(
|
||||||
lambda f: rk in f,
|
lambda f: kp in f,
|
||||||
edge.frictions.lst
|
edge.frictions.lst
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
ind = 1
|
ind = 1
|
||||||
for mail in edge.reach.inter_profiles_rk():
|
for mail in edge.reach.inter_profiles_kp():
|
||||||
coef = get_stricklers_from_rk(mail)
|
coef = get_stricklers_from_kp(mail)
|
||||||
|
|
||||||
f.write(f"{ind:>6} {coef:>12.5f}")
|
f.write(f"{ind:>6} {coef:>12.5f}")
|
||||||
|
|
||||||
@@ -382,7 +382,7 @@ class RubarBE(CommandLineSolver):
|
|||||||
first = profiles[0]
|
first = profiles[0]
|
||||||
last = profiles[-1]
|
last = profiles[-1]
|
||||||
|
|
||||||
if first.rk not in data or last.rk not in data:
|
if first.kp not in data or last.kp not in data:
|
||||||
logger.error(
|
logger.error(
|
||||||
"Study initial condition is not fully defined"
|
"Study initial condition is not fully defined"
|
||||||
)
|
)
|
||||||
@@ -400,7 +400,7 @@ class RubarBE(CommandLineSolver):
|
|||||||
|
|
||||||
prev_h, prev_s = f_h_s
|
prev_h, prev_s = f_h_s
|
||||||
for profile in it:
|
for profile in it:
|
||||||
if profile.rk not in data:
|
if profile.kp not in data:
|
||||||
ind += 1
|
ind += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -424,7 +424,7 @@ class RubarBE(CommandLineSolver):
|
|||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
for d in ics.data:
|
for d in ics.data:
|
||||||
data[d['rk']] = (
|
data[d['kp']] = (
|
||||||
d['elevation'],
|
d['elevation'],
|
||||||
d['discharge'],
|
d['discharge'],
|
||||||
)
|
)
|
||||||
@@ -432,8 +432,8 @@ class RubarBE(CommandLineSolver):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
def _export_tps_profile_height_speed(self, profile, data):
|
def _export_tps_profile_height_speed(self, profile, data):
|
||||||
z = data[profile.rk][0]
|
z = data[profile.kp][0]
|
||||||
q = data[profile.rk][1]
|
q = data[profile.kp][1]
|
||||||
|
|
||||||
height = z - profile.z_min()
|
height = z - profile.z_min()
|
||||||
speed = profile.speed(q, z)
|
speed = profile.speed(q, z)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from Solver.Mage import (
|
|||||||
Mage7, Mage8, MageFake7,
|
Mage7, Mage8, MageFake7,
|
||||||
)
|
)
|
||||||
from Solver.RubarBE import RubarBE
|
from Solver.RubarBE import RubarBE
|
||||||
|
from Solver.AdisTS import AdisTSlc
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ solver_long_name = {
|
|||||||
# "mage7": "Mage v7",
|
# "mage7": "Mage v7",
|
||||||
"mage8": "Mage v8",
|
"mage8": "Mage v8",
|
||||||
# "mage_fake7": "Mage fake v7",
|
# "mage_fake7": "Mage fake v7",
|
||||||
|
"adistslc": "Adis-TS_LC",
|
||||||
# "rubarbe": "RubarBE",
|
# "rubarbe": "RubarBE",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,5 +41,6 @@ solver_type_list = {
|
|||||||
# "mage7": Mage7,
|
# "mage7": Mage7,
|
||||||
"mage8": Mage8,
|
"mage8": Mage8,
|
||||||
# "mage_fake7": MageFake7,
|
# "mage_fake7": MageFake7,
|
||||||
|
"adistslc": AdisTSlc,
|
||||||
# "rubarbe": RubarBE,
|
# "rubarbe": RubarBE,
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
# Plot.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from tools import timer, trace
|
||||||
|
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
QCoreApplication
|
||||||
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class Plot(PamhyrPlot):
|
||||||
|
def __init__(self, mode="time", data=None,
|
||||||
|
trad=None, canvas=None, toolbar=None,
|
||||||
|
parent=None):
|
||||||
|
super(Plot, self).__init__(
|
||||||
|
canvas=canvas,
|
||||||
|
trad=trad,
|
||||||
|
data=data,
|
||||||
|
toolbar=toolbar,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._table_headers = self._trad.get_dict("table_headers")
|
||||||
|
|
||||||
|
header = self.data.header
|
||||||
|
|
||||||
|
self.label_x = self._table_headers[header[0]]
|
||||||
|
self.label_y = self._table_headers[header[1]]
|
||||||
|
|
||||||
|
self._mode = mode
|
||||||
|
self._isometric_axis = False
|
||||||
|
|
||||||
|
self._auto_relim_update = True
|
||||||
|
self._autoscale_update = True
|
||||||
|
|
||||||
|
def custom_ticks(self):
|
||||||
|
if self.data.header[0] != "time":
|
||||||
|
return
|
||||||
|
|
||||||
|
self.set_ticks_time_formater()
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def draw(self):
|
||||||
|
self.init_axes()
|
||||||
|
|
||||||
|
if len(self.data) == 0:
|
||||||
|
self._init = False
|
||||||
|
return
|
||||||
|
|
||||||
|
self.draw_data()
|
||||||
|
self.custom_ticks()
|
||||||
|
|
||||||
|
self.idle()
|
||||||
|
self._init = True
|
||||||
|
|
||||||
|
def draw_data(self):
|
||||||
|
# Plot data
|
||||||
|
x = list(map(lambda v: v[0], self.data.data))
|
||||||
|
y = list(map(lambda v: v[1], self.data.data))
|
||||||
|
|
||||||
|
self._line, = self.canvas.axes.plot(
|
||||||
|
x, y,
|
||||||
|
color=self.color_plot,
|
||||||
|
**self.plot_default_kargs
|
||||||
|
)
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def update(self, ind=None):
|
||||||
|
if not self._init:
|
||||||
|
self.draw()
|
||||||
|
return
|
||||||
|
|
||||||
|
self.update_data()
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
self._line.set_data(x, y)
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
# Table.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from datetime import date, time, datetime, timedelta
|
||||||
|
|
||||||
|
from tools import (
|
||||||
|
trace, timer,
|
||||||
|
timestamp_to_old_pamhyr_date,
|
||||||
|
old_pamhyr_date_to_timestamp
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect, QTime, QDateTime,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QTableView, QAbstractItemView, QSpinBox,
|
||||||
|
QTimeEdit, QDateTimeEdit, QItemDelegate,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.BoundaryConditionsAdisTS.Edit.UndoCommand import (
|
||||||
|
AddCommand, DelCommand, SetDataCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class TableModel(PamhyrTableModel):
|
||||||
|
def data(self, index, role):
|
||||||
|
if role == Qt.TextAlignmentRole:
|
||||||
|
return Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
|
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
value = QVariant()
|
||||||
|
|
||||||
|
if 0 <= column < 2:
|
||||||
|
v = self._data._data[row][column]
|
||||||
|
if self._data._types[column] == float:
|
||||||
|
value = f"{v:.4f}"
|
||||||
|
elif self._data.header[column] == "time":
|
||||||
|
if self._opt_data == "time":
|
||||||
|
value = timestamp_to_old_pamhyr_date(int(v))
|
||||||
|
else:
|
||||||
|
value = str(datetime.fromtimestamp(v))
|
||||||
|
else:
|
||||||
|
value = f"{v}"
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._undo.push(
|
||||||
|
SetDataCommand(
|
||||||
|
self._data, row, column, value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def add(self, row, parent=QModelIndex()):
|
||||||
|
self.beginInsertRows(parent, row, row - 1)
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
AddCommand(
|
||||||
|
self._data, row
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endInsertRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def delete(self, rows, parent=QModelIndex()):
|
||||||
|
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
DelCommand(
|
||||||
|
self._data, rows
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endRemoveRows()
|
||||||
|
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# UndoCommand.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QMessageBox, QUndoCommand, QUndoStack,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.BoundaryConditionsAdisTS.BoundaryConditionAdisTS import BoundaryConditionAdisTS
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class SetDataCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, index, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._index = index
|
||||||
|
self._column = column
|
||||||
|
self._old = self._data._data[self._index][self._column]
|
||||||
|
_type = self._data._types[self._column]
|
||||||
|
self._new = _type(new_value)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._column == 0:
|
||||||
|
self._data._data[self._index] = (self._old,self._data._data[self._index][1])
|
||||||
|
else:
|
||||||
|
self._data._data[self._index] = (self._data._data[self._index][0], self._old)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._column == 0:
|
||||||
|
self._data._data[self._index] = (self._new,self._data._data[self._index][1])
|
||||||
|
else:
|
||||||
|
self._data._data[self._index] = (self._data._data[self._index][0], self._new)
|
||||||
|
|
||||||
|
class AddCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, index):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._index = index
|
||||||
|
self._new = None
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
del self._data._data[self._index]
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._new is None:
|
||||||
|
self._new = self._data._data.insert(self._index, (self._data._types[0](0), self._data._types[1](0.0)))
|
||||||
|
else:
|
||||||
|
self._data._data.insert(self._index, self._new)
|
||||||
|
|
||||||
|
class DelCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, rows):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._rows = rows
|
||||||
|
|
||||||
|
self._bc = []
|
||||||
|
for row in rows:
|
||||||
|
self._bc.append((row, self._data._data[row]))
|
||||||
|
self._bc.sort()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
for row, el in self._bc:
|
||||||
|
self._data._data.insert(row, el)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
for row in self._rows:
|
||||||
|
del self._data._data[row]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
# Window.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import timer, trace
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
from View.Tools.PamhyrWidget import PamhyrWidget
|
||||||
|
from View.Tools.PamhyrDelegate import PamhyrExTimeDelegate
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5 import QtCore
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel, QCoreApplication,
|
||||||
|
pyqtSlot, pyqtSignal,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QHeaderView, QDoubleSpinBox, QVBoxLayout,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||||
|
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||||
|
|
||||||
|
from View.BoundaryConditionsAdisTS.Edit.translate import BCETranslate
|
||||||
|
from View.BoundaryConditionsAdisTS.Edit.Table import TableModel
|
||||||
|
from View.BoundaryConditionsAdisTS.Edit.Plot import Plot
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class EditBoundaryConditionWindow(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "EditBoundaryConditionsAdisTS"
|
||||||
|
_pamhyr_name = "Edit Boundary Conditions AdisTS"
|
||||||
|
|
||||||
|
def __init__(self, data=None, study=None, config=None, parent=None):
|
||||||
|
self._data = data
|
||||||
|
trad = BCETranslate()
|
||||||
|
|
||||||
|
name = trad[self._pamhyr_name]
|
||||||
|
|
||||||
|
super(EditBoundaryConditionWindow, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
if self._data is not None:
|
||||||
|
n = self._data.node
|
||||||
|
node_name = next(filter(lambda x: x.id == n, self._study.river._nodes)).name
|
||||||
|
name += (
|
||||||
|
f" - {study.name} " +
|
||||||
|
f"({node_name})"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._hash_data.append(data)
|
||||||
|
|
||||||
|
self.setup_table()
|
||||||
|
self.setup_plot()
|
||||||
|
self.setup_connections()
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
if self._data.type == "Concentration":
|
||||||
|
self._data.header = ["time", "concentration"]
|
||||||
|
else:
|
||||||
|
self._data.header = ["time", "rate"]
|
||||||
|
|
||||||
|
headers = {}
|
||||||
|
table_headers = self._trad.get_dict("table_headers")
|
||||||
|
for h in self._data.header:
|
||||||
|
headers[h] = table_headers[h]
|
||||||
|
|
||||||
|
self._delegate_time = PamhyrExTimeDelegate(
|
||||||
|
data=self._data,
|
||||||
|
mode=self._study.time_system,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
|
||||||
|
table = self.find(QTableView, "tableView")
|
||||||
|
self._table = TableModel(
|
||||||
|
table_view=table,
|
||||||
|
table_headers=headers,
|
||||||
|
editable_headers=self._data.header,
|
||||||
|
delegates={
|
||||||
|
# "time": self._delegate_time,
|
||||||
|
},
|
||||||
|
data=self._data,
|
||||||
|
undo=self._undo_stack,
|
||||||
|
opt_data=self._study.time_system
|
||||||
|
)
|
||||||
|
|
||||||
|
table.setModel(self._table)
|
||||||
|
table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
table.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
def setup_plot(self):
|
||||||
|
self.canvas = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas.setObjectName("canvas")
|
||||||
|
self.toolbar = PamhyrPlotToolbar(
|
||||||
|
self.canvas, self
|
||||||
|
)
|
||||||
|
self.verticalLayout.addWidget(self.toolbar)
|
||||||
|
self.verticalLayout.addWidget(self.canvas)
|
||||||
|
|
||||||
|
self.plot = Plot(
|
||||||
|
canvas=self.canvas,
|
||||||
|
data=self._data,
|
||||||
|
mode=self._study.time_system,
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar,
|
||||||
|
)
|
||||||
|
self.plot.draw()
|
||||||
|
|
||||||
|
def setup_connections(self):
|
||||||
|
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||||
|
self.find(QAction, "action_del").triggered.connect(self.delete)
|
||||||
|
|
||||||
|
self._table.dataChanged.connect(self.update)
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.plot.update()
|
||||||
|
|
||||||
|
def index_selected_row(self):
|
||||||
|
table = self.find(QTableView, "tableView")
|
||||||
|
return table.selectionModel()\
|
||||||
|
.selectedRows()[0]\
|
||||||
|
.row()
|
||||||
|
|
||||||
|
def index_selected_rows(self):
|
||||||
|
table = self.find(QTableView, "tableView")
|
||||||
|
return list(
|
||||||
|
# Delete duplicate
|
||||||
|
set(
|
||||||
|
map(
|
||||||
|
lambda i: i.row(),
|
||||||
|
table.selectedIndexes()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(self._data) == 0 or len(rows) == 0:
|
||||||
|
self._table.add(0)
|
||||||
|
else:
|
||||||
|
self._table.add(rows[0])
|
||||||
|
|
||||||
|
self.plot.update()
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(rows) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._table.delete(rows)
|
||||||
|
self.plot.update()
|
||||||
|
|
||||||
|
def sort(self):
|
||||||
|
self._table.sort(False)
|
||||||
|
self.plot.update()
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
|
||||||
|
table = []
|
||||||
|
table.append(self._data.header)
|
||||||
|
|
||||||
|
data = self._data.data
|
||||||
|
for row in rows:
|
||||||
|
table.append(list(data[row]))
|
||||||
|
|
||||||
|
self.copyTableIntoClipboard(table)
|
||||||
|
|
||||||
|
def _undo(self):
|
||||||
|
self._table.undo()
|
||||||
|
self.plot.update()
|
||||||
|
|
||||||
|
def _redo(self):
|
||||||
|
self._table.redo()
|
||||||
|
self.plot.update()
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# translate.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 PyQt5.QtCore import QCoreApplication
|
||||||
|
|
||||||
|
from View.Translate import MainTranslate
|
||||||
|
|
||||||
|
from View.BoundaryCondition.translate import BCTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class BCETranslate(BCTranslate):
|
||||||
|
def __init__(self):
|
||||||
|
super(BCETranslate, self).__init__()
|
||||||
|
|
||||||
|
self._dict["Edit Boundary Conditions AdisTS"] = _translate(
|
||||||
|
"BoundaryConditionAdisTS", "Edit boundary conditions AdisTS"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._sub_dict["table_headers"] = {
|
||||||
|
"time": self._dict["time"],
|
||||||
|
"date": self._dict["date"],
|
||||||
|
"rate": _translate("BoundaryConditionAdisTS", "Rate"),
|
||||||
|
"concentration": _translate("BoundaryConditionAdisTS", "Concentration"),
|
||||||
|
}
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
# Table.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.BoundaryCondition.BoundaryConditionTypes import (
|
||||||
|
NotDefined, PonctualContribution,
|
||||||
|
TimeOverZ, TimeOverDischarge, ZOverDischarge
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from View.BoundaryConditionsAdisTS.UndoCommand import (
|
||||||
|
SetNodeCommand, SetTypeCommand,
|
||||||
|
AddCommand, DelCommand,
|
||||||
|
)
|
||||||
|
from View.BoundaryCondition.translate import BC_types
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class ComboBoxDelegate(QItemDelegate):
|
||||||
|
def __init__(self, data=None, mode="type", tab="",
|
||||||
|
trad=None, parent=None):
|
||||||
|
super(ComboBoxDelegate, self).__init__(parent)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._mode = mode
|
||||||
|
self._tab = tab
|
||||||
|
self._trad = trad
|
||||||
|
|
||||||
|
self._long_types = {}
|
||||||
|
if self._trad is not None:
|
||||||
|
self._long_types = self._trad.get_dict("long_types")
|
||||||
|
|
||||||
|
def createEditor(self, parent, option, index):
|
||||||
|
self.editor = QComboBox(parent)
|
||||||
|
|
||||||
|
if self._mode == "type":
|
||||||
|
lst = [self._trad["not_associated"], "Concentration", "Rate"]
|
||||||
|
self.editor.addItems(
|
||||||
|
lst
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.editor.addItems(
|
||||||
|
[self._trad["not_associated"]] +
|
||||||
|
self._data.nodes_names()
|
||||||
|
)
|
||||||
|
|
||||||
|
self.editor.setCurrentText(index.data(Qt.DisplayRole))
|
||||||
|
return self.editor
|
||||||
|
|
||||||
|
def setEditorData(self, editor, index):
|
||||||
|
value = index.data(Qt.DisplayRole)
|
||||||
|
self.editor.currentTextChanged.connect(self.currentItemChanged)
|
||||||
|
|
||||||
|
def setModelData(self, editor, model, index):
|
||||||
|
text = str(editor.currentText())
|
||||||
|
model.setData(index, text)
|
||||||
|
editor.close()
|
||||||
|
editor.deleteLater()
|
||||||
|
|
||||||
|
def updateEditorGeometry(self, editor, option, index):
|
||||||
|
r = QRect(option.rect)
|
||||||
|
if self.editor.windowFlags() & Qt.Popup:
|
||||||
|
if editor.parent() is not None:
|
||||||
|
r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
|
||||||
|
editor.setGeometry(r)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def currentItemChanged(self):
|
||||||
|
self.commitData.emit(self.sender())
|
||||||
|
|
||||||
|
|
||||||
|
class TableModel(PamhyrTableModel):
|
||||||
|
def __init__(self, pollutant=None, bc_list =None, trad=None, **kwargs):
|
||||||
|
self._trad = trad
|
||||||
|
self._bc_list = bc_list
|
||||||
|
self._pollutant = pollutant
|
||||||
|
|
||||||
|
super(TableModel, self).__init__(trad=trad, **kwargs)
|
||||||
|
|
||||||
|
def _setup_lst(self):
|
||||||
|
self._lst = self._bc_list.lst
|
||||||
|
|
||||||
|
def rowCount(self, parent):
|
||||||
|
return len(self._lst)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if len(self._lst) != 0:
|
||||||
|
data = list(filter(lambda x: x.pollutant == self._pollutant,
|
||||||
|
self._lst))
|
||||||
|
else:
|
||||||
|
data = []
|
||||||
|
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._headers[column] == "type":
|
||||||
|
n = data[row].type
|
||||||
|
if n is None or n == "":
|
||||||
|
return self._trad["not_associated"]
|
||||||
|
return n
|
||||||
|
elif self._headers[column] == "node":
|
||||||
|
n = data[row].node
|
||||||
|
if n is None:
|
||||||
|
return self._trad["not_associated"]
|
||||||
|
return next(filter(lambda x: x.id == n, self._data._nodes)).name
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._headers[column] == "type":
|
||||||
|
self._undo.push(
|
||||||
|
SetTypeCommand(
|
||||||
|
self._lst, row, value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif self._headers[column] == "node":
|
||||||
|
self._undo.push(
|
||||||
|
SetNodeCommand(
|
||||||
|
self._lst, row, self._data.node(value)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print(value, self._data.node(value).id)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def add(self, row, parent=QModelIndex()):
|
||||||
|
self.beginInsertRows(parent, row, row - 1)
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
AddCommand(
|
||||||
|
self._pollutant, self._bc_list, self._lst, row
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endInsertRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def delete(self, rows, parent=QModelIndex()):
|
||||||
|
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
DelCommand(
|
||||||
|
self._lst, rows
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endRemoveRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._undo.undo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._undo.redo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# UndoCommand.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 copy import deepcopy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QMessageBox, QUndoCommand, QUndoStack,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.BoundaryConditionsAdisTS.BoundaryConditionAdisTS import BoundaryConditionAdisTS
|
||||||
|
from Model.BoundaryConditionsAdisTS.BoundaryConditionsAdisTSList import BoundaryConditionsAdisTSList
|
||||||
|
|
||||||
|
class SetNodeCommand(QUndoCommand):
|
||||||
|
def __init__(self, bcs, index, node):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._bcs = bcs
|
||||||
|
self._index = index
|
||||||
|
self._old = self._bcs[self._index].node
|
||||||
|
self._new = node.id
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._bcs[self._index].node = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._bcs[self._index].node = self._new
|
||||||
|
|
||||||
|
class SetTypeCommand(QUndoCommand):
|
||||||
|
def __init__(self, bcs, index, _type):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._bcs = bcs
|
||||||
|
self._index = index
|
||||||
|
self._type = _type
|
||||||
|
self._old = self._bcs[self._index].type
|
||||||
|
self._new = self._type
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._bcs[self._index].type = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._bcs[self._index].type = self._new
|
||||||
|
|
||||||
|
class AddCommand(QUndoCommand):
|
||||||
|
def __init__(self, pollutant, bcs_list, bcs, index):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._bcs = bcs
|
||||||
|
self._bc_list = bcs_list
|
||||||
|
self._pollutant = pollutant
|
||||||
|
self._index = index
|
||||||
|
self._new = None
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
del self._bcs[self._index]
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._new is None:
|
||||||
|
self._new = self._bc_list.new(self._index, self._pollutant)
|
||||||
|
else:
|
||||||
|
self._bcs.insert(self._index, self._new)
|
||||||
|
|
||||||
|
|
||||||
|
class DelCommand(QUndoCommand):
|
||||||
|
def __init__(self, bcs, rows):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._bcs = bcs
|
||||||
|
self._rows = rows
|
||||||
|
|
||||||
|
self._bc = []
|
||||||
|
for row in rows:
|
||||||
|
self._bc.append((row, self._bcs[row]))
|
||||||
|
self._bc.sort()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
for row, el in self._bc:
|
||||||
|
self._bcs.insert(row, el)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
for row in self._rows:
|
||||||
|
del self._bcs[row]
|
||||||
|
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
# Window.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import trace, timer, logger_exception
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
|
QWidget,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.BoundaryConditionsAdisTS.Table import (
|
||||||
|
TableModel, ComboBoxDelegate
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Network.GraphWidget import GraphWidget
|
||||||
|
from View.BoundaryConditionsAdisTS.translate import BCAdisTSTranslate
|
||||||
|
from View.BoundaryConditionsAdisTS.Edit.Window import EditBoundaryConditionWindow
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class BoundaryConditionAdisTSWindow(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "BoundaryConditionsAdisTS"
|
||||||
|
_pamhyr_name = "Boundary conditions AdisTS"
|
||||||
|
|
||||||
|
def __init__(self, pollutant=None, study=None, config=None, parent=None):
|
||||||
|
trad = BCAdisTSTranslate()
|
||||||
|
name = (
|
||||||
|
trad[self._pamhyr_name] +
|
||||||
|
" - " + study.name
|
||||||
|
)
|
||||||
|
|
||||||
|
self._pollutant = pollutant
|
||||||
|
|
||||||
|
super(BoundaryConditionAdisTSWindow, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._bcs = self._study.river.boundary_conditions_adists
|
||||||
|
|
||||||
|
self.setup_table()
|
||||||
|
self.setup_graph()
|
||||||
|
self.setup_connections()
|
||||||
|
|
||||||
|
self.ui.setWindowTitle(self._title)
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
self._delegate_type = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
mode="type",
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
self._delegate_node = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
mode="node",
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
|
||||||
|
table = self.find(QTableView, f"tableView")
|
||||||
|
self._table = TableModel(
|
||||||
|
table_view=table,
|
||||||
|
table_headers=self._trad.get_dict("table_headers"),
|
||||||
|
editable_headers=["type", "node"],
|
||||||
|
delegates={
|
||||||
|
"type": self._delegate_type,
|
||||||
|
"node": self._delegate_node,
|
||||||
|
},
|
||||||
|
trad=self._trad,
|
||||||
|
bc_list = self._study.river.boundary_conditions_adists,
|
||||||
|
undo=self._undo_stack,
|
||||||
|
pollutant=self._pollutant,
|
||||||
|
data=self._study.river
|
||||||
|
)
|
||||||
|
table.setModel(self._table)
|
||||||
|
table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
table.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
def setup_graph(self):
|
||||||
|
self.graph_widget = GraphWidget(
|
||||||
|
self._study.river,
|
||||||
|
min_size=None, size=(200, 200),
|
||||||
|
only_display=True,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
self.graph_layout = self.find(QVBoxLayout, "verticalLayout")
|
||||||
|
self.graph_layout.addWidget(self.graph_widget)
|
||||||
|
|
||||||
|
def setup_connections(self):
|
||||||
|
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||||
|
self.find(QAction, "action_del").triggered.connect(self.delete)
|
||||||
|
self.find(QAction, "action_edit").triggered.connect(self.edit)
|
||||||
|
|
||||||
|
def index_selected_row(self):
|
||||||
|
tab = "liquid"
|
||||||
|
table = self.find(QTableView, f"tableView_{tab}")
|
||||||
|
return table.selectionModel()\
|
||||||
|
.selectedRows()[0]\
|
||||||
|
.row()
|
||||||
|
|
||||||
|
def index_selected_rows(self):
|
||||||
|
table = self.find(QTableView, f"tableView")
|
||||||
|
return list(
|
||||||
|
# Delete duplicate
|
||||||
|
set(
|
||||||
|
map(
|
||||||
|
lambda i: i.row(),
|
||||||
|
table.selectedIndexes()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(self._bcs) == 0 or len(rows) == 0:
|
||||||
|
self._table.add(0)
|
||||||
|
else:
|
||||||
|
self._table.add(rows[0])
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(rows) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._table.delete(rows)
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
logger.info("TODO: copy")
|
||||||
|
|
||||||
|
def _paste(self):
|
||||||
|
logger.info("TODO: paste")
|
||||||
|
|
||||||
|
def _undo(self):
|
||||||
|
self._table.undo()
|
||||||
|
|
||||||
|
def _redo(self):
|
||||||
|
self._table.redo()
|
||||||
|
|
||||||
|
def edit(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
for row in rows:
|
||||||
|
data = self._bcs.lst[row]
|
||||||
|
|
||||||
|
if self.sub_window_exists(
|
||||||
|
EditBoundaryConditionWindow,
|
||||||
|
data=[self._study, None, data]
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
win = EditBoundaryConditionWindow(
|
||||||
|
data=data,
|
||||||
|
study=self._study,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
win.show()
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# translate.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 PyQt5.QtCore import QCoreApplication
|
||||||
|
|
||||||
|
from View.Translate import MainTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
class BCAdisTSTranslate(MainTranslate):
|
||||||
|
def __init__(self):
|
||||||
|
super(BCAdisTSTranslate, self).__init__()
|
||||||
|
|
||||||
|
self._dict["Boundary conditions AdisTS"] = _translate(
|
||||||
|
"BoundaryConditionsAdisTS", "Boundary conditions AdisTS"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._sub_dict["table_headers"] = {
|
||||||
|
"type": self._dict["type"],
|
||||||
|
"node": _translate("BoundaryCondition", "Node")
|
||||||
|
}
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
# Table.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from View.D90AdisTS.UndoCommand import (
|
||||||
|
SetCommand, AddCommand, SetCommandSpec,
|
||||||
|
DelCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class ComboBoxDelegate(QItemDelegate):
|
||||||
|
def __init__(self, data=None, ic_spec_lst=None, trad=None, parent=None, mode="reaches"):
|
||||||
|
super(ComboBoxDelegate, self).__init__(parent)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._mode = mode
|
||||||
|
self._trad = trad
|
||||||
|
self._ic_spec_lst = ic_spec_lst
|
||||||
|
|
||||||
|
def createEditor(self, parent, option, index):
|
||||||
|
self.editor = QComboBox(parent)
|
||||||
|
|
||||||
|
val = []
|
||||||
|
if self._mode == "kp":
|
||||||
|
reach_id = self._ic_spec_lst[index.row()].reach
|
||||||
|
|
||||||
|
reach = next(filter(lambda edge: edge.id == reach_id, self._data.edges()))
|
||||||
|
|
||||||
|
if reach_id is not None:
|
||||||
|
val = list(
|
||||||
|
map(
|
||||||
|
lambda kp: str(kp), reach.reach.get_kp()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
val = list(
|
||||||
|
map(
|
||||||
|
lambda n: n.name, self._data.edges()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.editor.addItems(
|
||||||
|
[self._trad['not_associated']] +
|
||||||
|
val
|
||||||
|
)
|
||||||
|
|
||||||
|
self.editor.setCurrentText(str(index.data(Qt.DisplayRole)))
|
||||||
|
return self.editor
|
||||||
|
|
||||||
|
def setEditorData(self, editor, index):
|
||||||
|
value = index.data(Qt.DisplayRole)
|
||||||
|
self.editor.currentTextChanged.connect(self.currentItemChanged)
|
||||||
|
|
||||||
|
def setModelData(self, editor, model, index):
|
||||||
|
text = str(editor.currentText())
|
||||||
|
model.setData(index, text)
|
||||||
|
editor.close()
|
||||||
|
editor.deleteLater()
|
||||||
|
|
||||||
|
def updateEditorGeometry(self, editor, option, index):
|
||||||
|
r = QRect(option.rect)
|
||||||
|
if self.editor.windowFlags() & Qt.Popup:
|
||||||
|
if editor.parent() is not None:
|
||||||
|
r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
|
||||||
|
editor.setGeometry(r)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def currentItemChanged(self):
|
||||||
|
self.commitData.emit(self.sender())
|
||||||
|
|
||||||
|
|
||||||
|
class D90TableModel(PamhyrTableModel):
|
||||||
|
def __init__(self, river=None, data=None, **kwargs):
|
||||||
|
self._river = river
|
||||||
|
|
||||||
|
super(D90TableModel, self).__init__(data=data, **kwargs)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
|
||||||
|
def _setup_lst(self):
|
||||||
|
self._lst = self._data._data
|
||||||
|
|
||||||
|
def rowCount(self, parent):
|
||||||
|
return len(self._lst)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._headers[column] is "name":
|
||||||
|
n = self._lst[row].name
|
||||||
|
if n is None or n == "":
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "reach":
|
||||||
|
n = self._lst[row].reach
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return next(filter(lambda edge: edge.id == n, self._river.edges())).name
|
||||||
|
elif self._headers[column] is "start_kp":
|
||||||
|
n = self._lst[row].start_kp
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "end_kp":
|
||||||
|
n = self._lst[row].end_kp
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "d90":
|
||||||
|
n = self._lst[row].d90
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._headers[column] != "reach":
|
||||||
|
self._undo.push(
|
||||||
|
SetCommandSpec(
|
||||||
|
self._lst, row, self._headers[column], value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif self._headers[column] == "reach":
|
||||||
|
print(self._river.edge(value).id)
|
||||||
|
self._undo.push(
|
||||||
|
SetCommandSpec(
|
||||||
|
self._lst, row, self._headers[column], self._river.edge(value).id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def add(self, row, parent=QModelIndex()):
|
||||||
|
self.beginInsertRows(parent, row, row - 1)
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
AddCommand(
|
||||||
|
self._data, self._lst, row
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endInsertRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def delete(self, rows, parent=QModelIndex()):
|
||||||
|
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
DelCommand(
|
||||||
|
self._data, self._lst, rows
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endRemoveRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._undo.undo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._undo.redo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# Table.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from View.D90AdisTS.UndoCommand import (
|
||||||
|
SetCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
class D90TableDefaultModel(PamhyrTableModel):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(D90TableDefaultModel, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._headers[column] is "name":
|
||||||
|
return self._data[row].name
|
||||||
|
elif self._headers[column] is "d90":
|
||||||
|
n = self._data[row].d90
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._headers[column] is not None:
|
||||||
|
self._undo.push(
|
||||||
|
SetCommand(
|
||||||
|
self._data, row, self._headers[column], value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._undo.undo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._undo.redo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
# UndoCommand.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 copy import deepcopy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QMessageBox, QUndoCommand, QUndoStack,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.D90AdisTS.D90AdisTS import D90AdisTS
|
||||||
|
from Model.D90AdisTS.D90AdisTSList import D90AdisTSList
|
||||||
|
|
||||||
|
|
||||||
|
class SetCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, row, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._column = column
|
||||||
|
|
||||||
|
if self._column == "name":
|
||||||
|
self._old = self._data[self._row].name
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._old = self._data[self._row].d90
|
||||||
|
|
||||||
|
_type = float
|
||||||
|
if column == "name":
|
||||||
|
_type = str
|
||||||
|
|
||||||
|
self._new = _type(new_value)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._old
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._data[self._row].d90 = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._new
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._data[self._row].d90 = self._new
|
||||||
|
|
||||||
|
class SetCommandSpec(QUndoCommand):
|
||||||
|
def __init__(self, data, row, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._column = column
|
||||||
|
|
||||||
|
if self._column == "name":
|
||||||
|
self._old = self._data[self._row].name
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._old = self._data[self._row].reach
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._old = self._data[self._row].start_kp
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._old = self._data[self._row].end_kp
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._old = self._data[self._row].d90
|
||||||
|
|
||||||
|
_type = float
|
||||||
|
if column == "name":
|
||||||
|
_type = str
|
||||||
|
elif column == "reach":
|
||||||
|
_type = int
|
||||||
|
|
||||||
|
self._new = _type(new_value)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._old
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._data[self._row].reach = self._old
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._data[self._row].start_kp = self._old
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._data[self._row].end_kp = self._old
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._data[self._row].d90 = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._new
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._data[self._row].reach = self._new
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._data[self._row].start_kp = self._new
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._data[self._row].end_kp = self._new
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._data[self._row].d90 = self._new
|
||||||
|
|
||||||
|
class AddCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, ics_spec, index):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._ics_spec = ics_spec
|
||||||
|
self._index = index
|
||||||
|
self._new = None
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._data.delete_i([self._index])
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._new is None:
|
||||||
|
self._new = self._data.new(self._index)
|
||||||
|
else:
|
||||||
|
self._data.insert(self._index, self._new)
|
||||||
|
|
||||||
|
class DelCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, ics_spec, rows):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._ics_spec = ics_spec
|
||||||
|
self._rows = rows
|
||||||
|
#self._data = data
|
||||||
|
|
||||||
|
self._ic = []
|
||||||
|
for row in rows:
|
||||||
|
self._ic.append((row, self._ics_spec[row]))
|
||||||
|
self._ic.sort()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
for row, el in self._ic:
|
||||||
|
self._data.insert(row, el)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._data.delete_i(self._rows)
|
||||||
|
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
# Window.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 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import trace, timer, logger_exception
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence, QIcon,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect, QItemSelectionModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
|
QVBoxLayout, QToolBar, QAction, QToolButton,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Modules import Modules
|
||||||
|
|
||||||
|
from View.InitialConditionsAdisTS.UndoCommand import (
|
||||||
|
SetCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.D90AdisTS.TableDefault import (
|
||||||
|
D90TableDefaultModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.D90AdisTS.Table import (
|
||||||
|
D90TableModel, ComboBoxDelegate,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.D90AdisTS.translate import D90AdisTSTranslate
|
||||||
|
|
||||||
|
from Solver.Mage import Mage8
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class D90AdisTSWindow(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "D90AdisTS"
|
||||||
|
_pamhyr_name = "D90 AdisTS"
|
||||||
|
|
||||||
|
def __init__(self, data=None, study=None, config=None, parent=None):
|
||||||
|
self._data = []
|
||||||
|
self._data.append(data)
|
||||||
|
trad = D90AdisTSTranslate()
|
||||||
|
|
||||||
|
name = (
|
||||||
|
trad[self._pamhyr_name] +
|
||||||
|
" - " + study.name +
|
||||||
|
" - " + self._data[0].name
|
||||||
|
)
|
||||||
|
|
||||||
|
super(D90AdisTSWindow, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._hash_data.append(data)
|
||||||
|
|
||||||
|
self._d90_adists_lst = study.river.d90_adists
|
||||||
|
|
||||||
|
self.setup_table()
|
||||||
|
|
||||||
|
self.ui.setWindowTitle(self._title)
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
|
||||||
|
path_icons = os.path.join(self._get_ui_directory(), f"ressources")
|
||||||
|
|
||||||
|
table_default = self.find(QTableView, f"tableView")
|
||||||
|
|
||||||
|
self._table = D90TableDefaultModel(
|
||||||
|
table_view=table_default,
|
||||||
|
table_headers=self._trad.get_dict("table_headers"),
|
||||||
|
editable_headers=["name", "d90"],
|
||||||
|
delegates={},
|
||||||
|
data=self._data,
|
||||||
|
undo=self._undo_stack,
|
||||||
|
trad=self._trad
|
||||||
|
)
|
||||||
|
|
||||||
|
table_default.setModel(self._table)
|
||||||
|
table_default.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
table_default.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
table_default.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
layout = self.find(QVBoxLayout, f"verticalLayout_1")
|
||||||
|
toolBar = QToolBar()
|
||||||
|
layout.addWidget(toolBar)
|
||||||
|
|
||||||
|
action_add = QAction(self)
|
||||||
|
action_add.setIcon(QIcon(os.path.join(path_icons, f"add.png")))
|
||||||
|
action_add.triggered.connect(self.add)
|
||||||
|
action_delete = QAction(self)
|
||||||
|
action_delete.setIcon(QIcon(os.path.join(path_icons, f"del.png")))
|
||||||
|
action_delete.triggered.connect(self.delete)
|
||||||
|
|
||||||
|
toolBar.addAction(action_add)
|
||||||
|
toolBar.addAction(action_delete)
|
||||||
|
|
||||||
|
self.table_spec = QTableView()
|
||||||
|
layout.addWidget(self.table_spec)
|
||||||
|
|
||||||
|
self._delegate_reach = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
ic_spec_lst=self._data[0]._data,
|
||||||
|
parent=self,
|
||||||
|
mode="reaches"
|
||||||
|
)
|
||||||
|
self._delegate_kp = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
ic_spec_lst=self._data[0]._data,
|
||||||
|
parent=self,
|
||||||
|
mode="kp"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._table_spec = D90TableModel(
|
||||||
|
table_view=self.table_spec,
|
||||||
|
table_headers=self._trad.get_dict("table_headers_spec"),
|
||||||
|
editable_headers=["name", "reach", "start_kp", "end_kp", "d90"],
|
||||||
|
delegates={
|
||||||
|
"reach": self._delegate_reach,
|
||||||
|
"start_kp": self._delegate_kp,
|
||||||
|
"end_kp": self._delegate_kp
|
||||||
|
},
|
||||||
|
data=self._data[0],
|
||||||
|
undo=self._undo_stack,
|
||||||
|
trad=self._trad,
|
||||||
|
river=self._study.river
|
||||||
|
)
|
||||||
|
|
||||||
|
self.table_spec.setModel(self._table_spec)
|
||||||
|
self.table_spec.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
self.table_spec.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
self.table_spec.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
selectionModel = self.table_spec.selectionModel()
|
||||||
|
index = self.table_spec.model().index(0, 0)
|
||||||
|
|
||||||
|
selectionModel.select(
|
||||||
|
index,
|
||||||
|
QItemSelectionModel.Rows |
|
||||||
|
QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Select
|
||||||
|
)
|
||||||
|
self.table_spec.scrollTo(index)
|
||||||
|
|
||||||
|
def index_selected_row(self):
|
||||||
|
#table = self.find(QTableView, f"tableView")
|
||||||
|
table = self.table_spec
|
||||||
|
rows = table.selectionModel()\
|
||||||
|
.selectedRows()
|
||||||
|
|
||||||
|
if len(rows) == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return rows[0].row()
|
||||||
|
|
||||||
|
def index_selected_rows(self):
|
||||||
|
#table = self.find(QTableView, f"tableView")
|
||||||
|
table = self.table_spec
|
||||||
|
return list(
|
||||||
|
# Delete duplicate
|
||||||
|
set(
|
||||||
|
map(
|
||||||
|
lambda i: i.row(),
|
||||||
|
table.selectedIndexes()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def move_up(self):
|
||||||
|
row = self.index_selected_row()
|
||||||
|
self._table.move_up(row)
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def move_down(self):
|
||||||
|
row = self.index_selected_row()
|
||||||
|
self._table.move_down(row)
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
rows = list(
|
||||||
|
map(
|
||||||
|
lambda row: row.row(),
|
||||||
|
self.tableView.selectionModel().selectedRows()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
table = list(
|
||||||
|
map(
|
||||||
|
lambda eic: list(
|
||||||
|
map(
|
||||||
|
lambda k: eic[1][k],
|
||||||
|
["kp", "discharge", "elevation"]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
filter(
|
||||||
|
lambda eic: eic[0] in rows,
|
||||||
|
enumerate(self._ics.lst())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.copyTableIntoClipboard(table)
|
||||||
|
|
||||||
|
def _paste(self):
|
||||||
|
header, data = self.parseClipboardTable()
|
||||||
|
|
||||||
|
if len(data) + len(header) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
"D90: Paste: " +
|
||||||
|
f"header = {header}, " +
|
||||||
|
f"data = {data}"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
row = self.index_selected_row()
|
||||||
|
# self._table.paste(row, header, data)
|
||||||
|
self._table.paste(row, [], data)
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _undo(self):
|
||||||
|
self._table.undo()
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _redo(self):
|
||||||
|
self._table.redo()
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(self._data[0]._data) == 0 or len(rows) == 0:
|
||||||
|
self._table_spec.add(0)
|
||||||
|
else:
|
||||||
|
self._table_spec.add(rows[0])
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
print("del")
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(rows) == 0:
|
||||||
|
print("len 0")
|
||||||
|
return
|
||||||
|
self._table_spec.delete(rows)
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# translate.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 PyQt5.QtCore import QCoreApplication
|
||||||
|
|
||||||
|
from View.Translate import MainTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class D90AdisTSTranslate(MainTranslate):
|
||||||
|
def __init__(self):
|
||||||
|
super(D90AdisTSTranslate, self).__init__()
|
||||||
|
|
||||||
|
self._dict["D90 AdisTS"] = _translate(
|
||||||
|
"D90AdisTS", "D90 AdisTS")
|
||||||
|
|
||||||
|
self._dict["kp"] = self._dict["unit_kp"]
|
||||||
|
|
||||||
|
self._sub_dict["table_headers"] = {
|
||||||
|
"name": self._dict["name"],
|
||||||
|
"d90": _translate("Unit", "D90"),
|
||||||
|
}
|
||||||
|
|
||||||
|
self._sub_dict["table_headers_spec"] = {
|
||||||
|
"name": self._dict["name"],
|
||||||
|
"reach": self._dict["reach"],
|
||||||
|
"start_kp": _translate("Unit", "Start_KP (m)"),
|
||||||
|
"end_kp": _translate("Unit", "End_KP (m)"),
|
||||||
|
"d90": _translate("Unit", "D90"),
|
||||||
|
}
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
# Table.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from View.DIFAdisTS.UndoCommand import (
|
||||||
|
SetCommand, AddCommand, SetCommandSpec,
|
||||||
|
DelCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class ComboBoxDelegate(QItemDelegate):
|
||||||
|
def __init__(self, data=None, ic_spec_lst=None, trad=None, parent=None, mode="reaches"):
|
||||||
|
super(ComboBoxDelegate, self).__init__(parent)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._mode = mode
|
||||||
|
self._trad = trad
|
||||||
|
self._ic_spec_lst = ic_spec_lst
|
||||||
|
|
||||||
|
def createEditor(self, parent, option, index):
|
||||||
|
self.editor = QComboBox(parent)
|
||||||
|
|
||||||
|
val = []
|
||||||
|
if self._mode == "kp":
|
||||||
|
reach_id = self._ic_spec_lst[index.row()].reach
|
||||||
|
|
||||||
|
reach = next(filter(lambda edge: edge.id == reach_id, self._data.edges()))
|
||||||
|
|
||||||
|
if reach_id is not None:
|
||||||
|
val = list(
|
||||||
|
map(
|
||||||
|
lambda kp: str(kp), reach.reach.get_kp()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif self._mode == "method":
|
||||||
|
val = self._data.dif_adists.lst[0].types
|
||||||
|
else:
|
||||||
|
val = list(
|
||||||
|
map(
|
||||||
|
lambda n: n.name, self._data.edges()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.editor.addItems(
|
||||||
|
[self._trad['not_associated']] +
|
||||||
|
val
|
||||||
|
)
|
||||||
|
|
||||||
|
self.editor.setCurrentText(str(index.data(Qt.DisplayRole)))
|
||||||
|
return self.editor
|
||||||
|
|
||||||
|
def setEditorData(self, editor, index):
|
||||||
|
value = index.data(Qt.DisplayRole)
|
||||||
|
self.editor.currentTextChanged.connect(self.currentItemChanged)
|
||||||
|
|
||||||
|
def setModelData(self, editor, model, index):
|
||||||
|
text = str(editor.currentText())
|
||||||
|
model.setData(index, text)
|
||||||
|
editor.close()
|
||||||
|
editor.deleteLater()
|
||||||
|
|
||||||
|
def updateEditorGeometry(self, editor, option, index):
|
||||||
|
r = QRect(option.rect)
|
||||||
|
if self.editor.windowFlags() & Qt.Popup:
|
||||||
|
if editor.parent() is not None:
|
||||||
|
r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
|
||||||
|
editor.setGeometry(r)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def currentItemChanged(self):
|
||||||
|
self.commitData.emit(self.sender())
|
||||||
|
|
||||||
|
|
||||||
|
class DIFTableModel(PamhyrTableModel):
|
||||||
|
def __init__(self, river=None, data=None, **kwargs):
|
||||||
|
self._river = river
|
||||||
|
|
||||||
|
super(DIFTableModel, self).__init__(data=data, **kwargs)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
|
||||||
|
def _setup_lst(self):
|
||||||
|
self._lst = self._data._data
|
||||||
|
|
||||||
|
def rowCount(self, parent):
|
||||||
|
return len(self._lst)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._headers[column] is "method":
|
||||||
|
n = self._lst[row].method
|
||||||
|
if n is None or n == "":
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "reach":
|
||||||
|
n = self._lst[row].reach
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return next(filter(lambda edge: edge.id == n, self._river.edges())).name
|
||||||
|
elif self._headers[column] is "start_kp":
|
||||||
|
n = self._lst[row].start_kp
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "end_kp":
|
||||||
|
n = self._lst[row].end_kp
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "dif":
|
||||||
|
n = self._lst[row].dif
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "b":
|
||||||
|
n = self._lst[row].b
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "c":
|
||||||
|
n = self._lst[row].c
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._headers[column] != "reach":
|
||||||
|
self._undo.push(
|
||||||
|
SetCommandSpec(
|
||||||
|
self._lst, row, self._headers[column], value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif self._headers[column] == "reach":
|
||||||
|
print(self._river.edge(value).id)
|
||||||
|
self._undo.push(
|
||||||
|
SetCommandSpec(
|
||||||
|
self._lst, row, self._headers[column], self._river.edge(value).id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def add(self, row, parent=QModelIndex()):
|
||||||
|
self.beginInsertRows(parent, row, row - 1)
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
AddCommand(
|
||||||
|
self._data, self._lst, row
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endInsertRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def delete(self, rows, parent=QModelIndex()):
|
||||||
|
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
DelCommand(
|
||||||
|
self._data, self._lst, rows
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endRemoveRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._undo.undo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._undo.redo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
# Table.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from View.DIFAdisTS.UndoCommand import (
|
||||||
|
SetCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
class DIFTableDefaultModel(PamhyrTableModel):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(DIFTableDefaultModel, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._headers[column] is "method":
|
||||||
|
n = self._data[row].method
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "dif":
|
||||||
|
n = self._data[row].dif
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "b":
|
||||||
|
n = self._data[row].b
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "c":
|
||||||
|
n = self._data[row].c
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._headers[column] is not None:
|
||||||
|
self._undo.push(
|
||||||
|
SetCommand(
|
||||||
|
self._data, row, self._headers[column], value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._undo.undo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._undo.redo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
# UndoCommand.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 copy import deepcopy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QMessageBox, QUndoCommand, QUndoStack,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.DIFAdisTS.DIFAdisTS import DIFAdisTS
|
||||||
|
from Model.DIFAdisTS.DIFAdisTSList import DIFAdisTSList
|
||||||
|
|
||||||
|
|
||||||
|
class SetCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, row, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._column = column
|
||||||
|
|
||||||
|
if self._column == "method":
|
||||||
|
self._old = self._data[self._row].method
|
||||||
|
elif self._column == "dif":
|
||||||
|
self._old = self._data[self._row].dif
|
||||||
|
elif self._column == "b":
|
||||||
|
self._old = self._data[self._row].b
|
||||||
|
elif self._column == "c":
|
||||||
|
self._old = self._data[self._row].c
|
||||||
|
|
||||||
|
_type = float
|
||||||
|
if column == "method":
|
||||||
|
_type = str
|
||||||
|
|
||||||
|
self._new = _type(new_value)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._column == "method":
|
||||||
|
self._data[self._row].method = self._old
|
||||||
|
elif self._column == "dif":
|
||||||
|
self._data[self._row].dif = self._old
|
||||||
|
elif self._column == "b":
|
||||||
|
self._data[self._row].b = self._old
|
||||||
|
elif self._column == "c":
|
||||||
|
self._data[self._row].c = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._column == "method":
|
||||||
|
self._data[self._row].method = self._new
|
||||||
|
elif self._column == "dif":
|
||||||
|
self._data[self._row].dif = self._new
|
||||||
|
elif self._column == "b":
|
||||||
|
self._data[self._row].b = self._new
|
||||||
|
elif self._column == "c":
|
||||||
|
self._data[self._row].c = self._new
|
||||||
|
|
||||||
|
class SetCommandSpec(QUndoCommand):
|
||||||
|
def __init__(self, data, row, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._column = column
|
||||||
|
|
||||||
|
if self._column == "method":
|
||||||
|
self._old = self._data[self._row].method
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._old = self._data[self._row].reach
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._old = self._data[self._row].start_kp
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._old = self._data[self._row].end_kp
|
||||||
|
elif self._column == "dif":
|
||||||
|
self._old = self._data[self._row].dif
|
||||||
|
elif self._column == "b":
|
||||||
|
self._old = self._data[self._row].b
|
||||||
|
elif self._column == "c":
|
||||||
|
self._old = self._data[self._row].c
|
||||||
|
|
||||||
|
_type = float
|
||||||
|
if column == "method":
|
||||||
|
_type = str
|
||||||
|
elif column == "reach":
|
||||||
|
_type = int
|
||||||
|
|
||||||
|
self._new = _type(new_value)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._column == "method":
|
||||||
|
self._data[self._row].method = self._old
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._data[self._row].reach = self._old
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._data[self._row].start_kp = self._old
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._data[self._row].end_kp = self._old
|
||||||
|
elif self._column == "dif":
|
||||||
|
self._data[self._row].dif = self._old
|
||||||
|
elif self._column == "b":
|
||||||
|
self._data[self._row].b = self._old
|
||||||
|
elif self._column == "c":
|
||||||
|
self._data[self._row].c = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._column == "method":
|
||||||
|
self._data[self._row].method = self._new
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._data[self._row].reach = self._new
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._data[self._row].start_kp = self._new
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._data[self._row].end_kp = self._new
|
||||||
|
elif self._column == "dif":
|
||||||
|
self._data[self._row].dif = self._new
|
||||||
|
elif self._column == "b":
|
||||||
|
self._data[self._row].b = self._new
|
||||||
|
elif self._column == "c":
|
||||||
|
self._data[self._row].c = self._new
|
||||||
|
|
||||||
|
class AddCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, ics_spec, index):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._ics_spec = ics_spec
|
||||||
|
self._index = index
|
||||||
|
self._new = None
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._data.delete_i([self._index])
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._new is None:
|
||||||
|
self._new = self._data.new(self._index)
|
||||||
|
else:
|
||||||
|
self._data.insert(self._index, self._new)
|
||||||
|
|
||||||
|
class DelCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, ics_spec, rows):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._ics_spec = ics_spec
|
||||||
|
self._rows = rows
|
||||||
|
#self._data = data
|
||||||
|
|
||||||
|
self._ic = []
|
||||||
|
for row in rows:
|
||||||
|
self._ic.append((row, self._ics_spec[row]))
|
||||||
|
self._ic.sort()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
for row, el in self._ic:
|
||||||
|
self._data.insert(row, el)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._data.delete_i(self._rows)
|
||||||
|
|
||||||
@@ -0,0 +1,290 @@
|
|||||||
|
# Window.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 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import trace, timer, logger_exception
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence, QIcon,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect, QItemSelectionModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
|
QVBoxLayout, QToolBar, QAction, QToolButton,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Modules import Modules
|
||||||
|
|
||||||
|
from View.DIFAdisTS.TableDefault import (
|
||||||
|
DIFTableDefaultModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.DIFAdisTS.Table import (
|
||||||
|
DIFTableModel, ComboBoxDelegate,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.DIFAdisTS.translate import DIFAdisTSTranslate
|
||||||
|
|
||||||
|
from Solver.Mage import Mage8
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class DIFAdisTSWindow(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "DIFAdisTS"
|
||||||
|
_pamhyr_name = "DIF AdisTS"
|
||||||
|
|
||||||
|
def __init__(self, data=None, study=None, config=None, parent=None):
|
||||||
|
self._data = []
|
||||||
|
self._data.append(data)
|
||||||
|
trad = DIFAdisTSTranslate()
|
||||||
|
|
||||||
|
name = (
|
||||||
|
trad[self._pamhyr_name] +
|
||||||
|
" - " + study.name +
|
||||||
|
" - " + self._data[0].name
|
||||||
|
)
|
||||||
|
|
||||||
|
super(DIFAdisTSWindow, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._hash_data.append(data)
|
||||||
|
|
||||||
|
self._dif_adists_lst = study.river.dif_adists
|
||||||
|
|
||||||
|
self.setup_table()
|
||||||
|
|
||||||
|
self.ui.setWindowTitle(self._title)
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
|
||||||
|
path_icons = os.path.join(self._get_ui_directory(), f"ressources")
|
||||||
|
|
||||||
|
table_default = self.find(QTableView, f"tableView")
|
||||||
|
|
||||||
|
self._delegate_method = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
ic_spec_lst=self._data[0]._data,
|
||||||
|
parent=self,
|
||||||
|
mode="method"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._table = DIFTableDefaultModel(
|
||||||
|
table_view=table_default,
|
||||||
|
table_headers=self._trad.get_dict("table_headers"),
|
||||||
|
editable_headers=["method", "dif", "b", "c"],
|
||||||
|
delegates={
|
||||||
|
"method": self._delegate_method
|
||||||
|
},
|
||||||
|
data=self._data,
|
||||||
|
undo=self._undo_stack,
|
||||||
|
trad=self._trad
|
||||||
|
)
|
||||||
|
|
||||||
|
table_default.setModel(self._table)
|
||||||
|
table_default.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
table_default.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
table_default.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
layout = self.find(QVBoxLayout, f"verticalLayout_1")
|
||||||
|
toolBar = QToolBar()
|
||||||
|
layout.addWidget(toolBar)
|
||||||
|
|
||||||
|
action_add = QAction(self)
|
||||||
|
action_add.setIcon(QIcon(os.path.join(path_icons, f"add.png")))
|
||||||
|
action_add.triggered.connect(self.add)
|
||||||
|
action_delete = QAction(self)
|
||||||
|
action_delete.setIcon(QIcon(os.path.join(path_icons, f"del.png")))
|
||||||
|
action_delete.triggered.connect(self.delete)
|
||||||
|
|
||||||
|
toolBar.addAction(action_add)
|
||||||
|
toolBar.addAction(action_delete)
|
||||||
|
|
||||||
|
self.table_spec = QTableView()
|
||||||
|
layout.addWidget(self.table_spec)
|
||||||
|
|
||||||
|
self._delegate_reach = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
ic_spec_lst=self._data[0]._data,
|
||||||
|
parent=self,
|
||||||
|
mode="reaches"
|
||||||
|
)
|
||||||
|
self._delegate_kp = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
ic_spec_lst=self._data[0]._data,
|
||||||
|
parent=self,
|
||||||
|
mode="kp"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._table_spec = DIFTableModel(
|
||||||
|
table_view=self.table_spec,
|
||||||
|
table_headers=self._trad.get_dict("table_headers_spec"),
|
||||||
|
editable_headers=["method", "reach", "start_kp", "end_kp", "dif", "b", "c"],
|
||||||
|
delegates={
|
||||||
|
"method": self._delegate_method,
|
||||||
|
"reach": self._delegate_reach,
|
||||||
|
"start_kp": self._delegate_kp,
|
||||||
|
"end_kp": self._delegate_kp
|
||||||
|
},
|
||||||
|
data=self._data[0],
|
||||||
|
undo=self._undo_stack,
|
||||||
|
trad=self._trad,
|
||||||
|
river=self._study.river
|
||||||
|
)
|
||||||
|
|
||||||
|
self.table_spec.setModel(self._table_spec)
|
||||||
|
self.table_spec.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
self.table_spec.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
self.table_spec.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
selectionModel = self.table_spec.selectionModel()
|
||||||
|
index = self.table_spec.model().index(0, 0)
|
||||||
|
|
||||||
|
selectionModel.select(
|
||||||
|
index,
|
||||||
|
QItemSelectionModel.Rows |
|
||||||
|
QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Select
|
||||||
|
)
|
||||||
|
self.table_spec.scrollTo(index)
|
||||||
|
|
||||||
|
def index_selected_row(self):
|
||||||
|
#table = self.find(QTableView, f"tableView")
|
||||||
|
table = self.table_spec
|
||||||
|
rows = table.selectionModel()\
|
||||||
|
.selectedRows()
|
||||||
|
|
||||||
|
if len(rows) == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return rows[0].row()
|
||||||
|
|
||||||
|
def index_selected_rows(self):
|
||||||
|
#table = self.find(QTableView, f"tableView")
|
||||||
|
table = self.table_spec
|
||||||
|
return list(
|
||||||
|
# Delete duplicate
|
||||||
|
set(
|
||||||
|
map(
|
||||||
|
lambda i: i.row(),
|
||||||
|
table.selectedIndexes()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def move_up(self):
|
||||||
|
row = self.index_selected_row()
|
||||||
|
self._table.move_up(row)
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def move_down(self):
|
||||||
|
row = self.index_selected_row()
|
||||||
|
self._table.move_down(row)
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
rows = list(
|
||||||
|
map(
|
||||||
|
lambda row: row.row(),
|
||||||
|
self.tableView.selectionModel().selectedRows()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
table = list(
|
||||||
|
map(
|
||||||
|
lambda eic: list(
|
||||||
|
map(
|
||||||
|
lambda k: eic[1][k],
|
||||||
|
["kp", "discharge", "elevation"]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
filter(
|
||||||
|
lambda eic: eic[0] in rows,
|
||||||
|
enumerate(self._ics.lst())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.copyTableIntoClipboard(table)
|
||||||
|
|
||||||
|
def _paste(self):
|
||||||
|
header, data = self.parseClipboardTable()
|
||||||
|
|
||||||
|
if len(data) + len(header) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
"DIF: Paste: " +
|
||||||
|
f"header = {header}, " +
|
||||||
|
f"data = {data}"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
row = self.index_selected_row()
|
||||||
|
# self._table.paste(row, header, data)
|
||||||
|
self._table.paste(row, [], data)
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _undo(self):
|
||||||
|
self._table.undo()
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _redo(self):
|
||||||
|
self._table.redo()
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(self._data[0]._data) == 0 or len(rows) == 0:
|
||||||
|
self._table_spec.add(0)
|
||||||
|
else:
|
||||||
|
self._table_spec.add(rows[0])
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
print("del")
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(rows) == 0:
|
||||||
|
print("len 0")
|
||||||
|
return
|
||||||
|
self._table_spec.delete(rows)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# translate.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 PyQt5.QtCore import QCoreApplication
|
||||||
|
|
||||||
|
from View.Translate import MainTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class DIFAdisTSTranslate(MainTranslate):
|
||||||
|
def __init__(self):
|
||||||
|
super(DIFAdisTSTranslate, self).__init__()
|
||||||
|
|
||||||
|
self._dict["DIF AdisTS"] = _translate(
|
||||||
|
"DIFAdisTS", "DIF AdisTS")
|
||||||
|
|
||||||
|
self._dict["kp"] = self._dict["unit_kp"]
|
||||||
|
|
||||||
|
self._sub_dict["table_headers"] = {
|
||||||
|
"method": self._dict["method"],
|
||||||
|
"dif": _translate("Unit", "DIF"),
|
||||||
|
"b": _translate("Unit", "Coeff b"),
|
||||||
|
"c": _translate("Unit", "Coeff c"),
|
||||||
|
}
|
||||||
|
|
||||||
|
self._sub_dict["table_headers_spec"] = {
|
||||||
|
"method": self._dict["method"],
|
||||||
|
"reach": self._dict["reach"],
|
||||||
|
"start_kp": _translate("Unit", "Start_KP (m)"),
|
||||||
|
"end_kp": _translate("Unit", "End_KP (m)"),
|
||||||
|
"dif": _translate("Unit", "DIF"),
|
||||||
|
"b": _translate("Unit", "Coeff b"),
|
||||||
|
"c": _translate("Unit", "Coeff c"),
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# PlotRKC.py -- Pamhyr
|
# PlotKPC.py -- Pamhyr
|
||||||
# Copyright (C) 2023-2024 INRAE
|
# Copyright (C) 2023-2024 INRAE
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
@@ -17,16 +17,16 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication
|
from PyQt5.QtCore import QCoreApplication
|
||||||
from View.HydraulicStructures.PlotRKC import PlotRKC
|
from View.HydraulicStructures.PlotKPC import PlotKPC
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
class PlotRKZ(PlotRKC):
|
class PlotKPZ(PlotKPC):
|
||||||
def __init__(self, canvas=None, trad=None, toolbar=None,
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
river=None, reach=None, profile=None,
|
river=None, reach=None, profile=None,
|
||||||
parent=None):
|
parent=None):
|
||||||
super(PlotRKC, self).__init__(
|
super(PlotKPC, self).__init__(
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
trad=trad,
|
trad=trad,
|
||||||
data=river,
|
data=river,
|
||||||
@@ -37,7 +37,7 @@ class PlotRKZ(PlotRKC):
|
|||||||
self._current_reach = reach
|
self._current_reach = reach
|
||||||
self._current_profile = profile
|
self._current_profile = profile
|
||||||
|
|
||||||
self.label_x = self._trad["unit_rk"]
|
self.label_x = self._trad["unit_kp"]
|
||||||
self.label_y = self._trad["unit_elevation"]
|
self.label_y = self._trad["unit_elevation"]
|
||||||
|
|
||||||
self._isometric_axis = False
|
self._isometric_axis = False
|
||||||
@@ -41,10 +41,10 @@ class PlotStricklers(PamhyrPlot):
|
|||||||
parent=parent
|
parent=parent
|
||||||
)
|
)
|
||||||
|
|
||||||
self.label_x = self._trad["rk"]
|
self.label_x = self._trad["kp"]
|
||||||
self.label_y = self._trad["strickler_plot"]
|
self.label_y = self._trad["strickler_plot"]
|
||||||
|
|
||||||
self.line_rk_elevation = [None, None]
|
self.line_kp_elevation = [None, None]
|
||||||
|
|
||||||
self._isometric_axis = False
|
self._isometric_axis = False
|
||||||
|
|
||||||
@@ -65,9 +65,9 @@ class PlotStricklers(PamhyrPlot):
|
|||||||
self._init = True
|
self._init = True
|
||||||
|
|
||||||
def draw_data(self):
|
def draw_data(self):
|
||||||
rk = self.data.reach.get_rk()
|
kp = self.data.reach.get_kp()
|
||||||
self.canvas.axes.set_xlim(
|
self.canvas.axes.set_xlim(
|
||||||
left=min(rk), right=max(rk)
|
left=min(kp), right=max(kp)
|
||||||
)
|
)
|
||||||
|
|
||||||
frictions = self.data.frictions
|
frictions = self.data.frictions
|
||||||
@@ -76,14 +76,14 @@ class PlotStricklers(PamhyrPlot):
|
|||||||
self.draw_frictions(lst, self.color_plot)
|
self.draw_frictions(lst, self.color_plot)
|
||||||
|
|
||||||
# HightLight
|
# HightLight
|
||||||
rk_min, rk_max = (-1, -1)
|
kp_min, kp_max = (-1, -1)
|
||||||
if self._highlight_data is not None:
|
if self._highlight_data is not None:
|
||||||
rk_min, rk_max = self._highlight_data
|
kp_min, kp_max = self._highlight_data
|
||||||
|
|
||||||
lst = list(
|
lst = list(
|
||||||
filter(
|
filter(
|
||||||
lambda s: (s.begin_rk == rk_min and
|
lambda s: (s.begin_kp == kp_min and
|
||||||
s.end_rk == rk_max),
|
s.end_kp == kp_max),
|
||||||
frictions.frictions
|
frictions.frictions
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -96,7 +96,7 @@ class PlotStricklers(PamhyrPlot):
|
|||||||
lambda f: f.is_full_defined(),
|
lambda f: f.is_full_defined(),
|
||||||
frictions
|
frictions
|
||||||
),
|
),
|
||||||
key=lambda s: s.begin_rk
|
key=lambda s: s.begin_kp
|
||||||
)
|
)
|
||||||
|
|
||||||
coef = flatten(
|
coef = flatten(
|
||||||
@@ -106,9 +106,9 @@ class PlotStricklers(PamhyrPlot):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
rk = flatten(
|
kp = flatten(
|
||||||
map(
|
map(
|
||||||
lambda s: [s.begin_rk, s.end_rk],
|
lambda s: [s.begin_kp, s.end_kp],
|
||||||
lst
|
lst
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -116,13 +116,13 @@ class PlotStricklers(PamhyrPlot):
|
|||||||
coef_minor = list(map(lambda s: s.minor, coef))
|
coef_minor = list(map(lambda s: s.minor, coef))
|
||||||
coef_medium = list(map(lambda s: s.medium, coef))
|
coef_medium = list(map(lambda s: s.medium, coef))
|
||||||
|
|
||||||
self.line_rk_elevation[0] = self.canvas.axes.plot(
|
self.line_kp_elevation[0] = self.canvas.axes.plot(
|
||||||
rk, coef_minor,
|
kp, coef_minor,
|
||||||
color=color, lw=1.
|
color=color, lw=1.
|
||||||
)
|
)
|
||||||
|
|
||||||
self.line_rk_elevation[1] = self.canvas.axes.plot(
|
self.line_kp_elevation[1] = self.canvas.axes.plot(
|
||||||
rk, coef_medium,
|
kp, coef_medium,
|
||||||
color=color, lw=1.
|
color=color, lw=1.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -113,10 +113,10 @@ class TableModel(PamhyrTableModel):
|
|||||||
|
|
||||||
if self._headers[column] == "name":
|
if self._headers[column] == "name":
|
||||||
return self._lst.get(row).name
|
return self._lst.get(row).name
|
||||||
elif self._headers[column] == "begin_rk":
|
elif self._headers[column] == "begin_kp":
|
||||||
return self._lst.get(row).begin_rk
|
return self._lst.get(row).begin_kp
|
||||||
elif self._headers[column] == "end_rk":
|
elif self._headers[column] == "end_kp":
|
||||||
return self._lst.get(row).end_rk
|
return self._lst.get(row).end_kp
|
||||||
elif self._headers[column] == "begin_strickler":
|
elif self._headers[column] == "begin_strickler":
|
||||||
value = self._lst.get(row).begin_strickler
|
value = self._lst.get(row).begin_strickler
|
||||||
if value is None:
|
if value is None:
|
||||||
@@ -144,13 +144,13 @@ class TableModel(PamhyrTableModel):
|
|||||||
self._lst, row, value
|
self._lst, row, value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif self._headers[column] == "begin_rk":
|
elif self._headers[column] == "begin_kp":
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetBeginCommand(
|
SetBeginCommand(
|
||||||
self._lst, row, value
|
self._lst, row, value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif self._headers[column] == "end_rk":
|
elif self._headers[column] == "end_kp":
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetEndCommand(
|
SetEndCommand(
|
||||||
self._lst, row, value
|
self._lst, row, value
|
||||||
|
|||||||
@@ -49,14 +49,14 @@ class SetBeginCommand(QUndoCommand):
|
|||||||
|
|
||||||
self._frictions = frictions
|
self._frictions = frictions
|
||||||
self._index = index
|
self._index = index
|
||||||
self._old = self._frictions.get(self._index).begin_rk
|
self._old = self._frictions.get(self._index).begin_kp
|
||||||
self._new = float(new_value)
|
self._new = float(new_value)
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._frictions.get(self._index).begin_rk = float(self._old)
|
self._frictions.get(self._index).begin_kp = float(self._old)
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
self._frictions.get(self._index).begin_rk = float(self._new)
|
self._frictions.get(self._index).begin_kp = float(self._new)
|
||||||
|
|
||||||
|
|
||||||
class SetEndCommand(QUndoCommand):
|
class SetEndCommand(QUndoCommand):
|
||||||
@@ -65,14 +65,14 @@ class SetEndCommand(QUndoCommand):
|
|||||||
|
|
||||||
self._frictions = frictions
|
self._frictions = frictions
|
||||||
self._index = index
|
self._index = index
|
||||||
self._old = self._frictions.get(self._index).end_rk
|
self._old = self._frictions.get(self._index).end_kp
|
||||||
self._new = float(new_value)
|
self._new = float(new_value)
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._frictions.get(self._index).end_rk = float(self._old)
|
self._frictions.get(self._index).end_kp = float(self._old)
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
self._frictions.get(self._index).end_rk = float(self._new)
|
self._frictions.get(self._index).end_kp = float(self._new)
|
||||||
|
|
||||||
|
|
||||||
class SetBeginStricklerCommand(QUndoCommand):
|
class SetBeginStricklerCommand(QUndoCommand):
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ from View.Frictions.Table import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||||
from View.Frictions.PlotRKZ import PlotRKZ
|
from View.Frictions.PlotKPZ import PlotKPZ
|
||||||
from View.Frictions.PlotStricklers import PlotStricklers
|
from View.Frictions.PlotStricklers import PlotStricklers
|
||||||
from View.Frictions.translate import FrictionsTranslate
|
from View.Frictions.translate import FrictionsTranslate
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ class FrictionsWindow(PamhyrWindow):
|
|||||||
table_view=table,
|
table_view=table,
|
||||||
table_headers=self._trad.get_dict("table_headers"),
|
table_headers=self._trad.get_dict("table_headers"),
|
||||||
editable_headers=[
|
editable_headers=[
|
||||||
"name", "begin_rk", "end_rk",
|
"name", "begin_kp", "end_kp",
|
||||||
"begin_strickler", "end_strickler"
|
"begin_strickler", "end_strickler"
|
||||||
],
|
],
|
||||||
delegates={
|
delegates={
|
||||||
@@ -133,7 +133,7 @@ class FrictionsWindow(PamhyrWindow):
|
|||||||
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
||||||
self.plot_layout.addWidget(self.canvas)
|
self.plot_layout.addWidget(self.canvas)
|
||||||
|
|
||||||
self.plot = PlotRKZ(
|
self.plot = PlotKPZ(
|
||||||
canvas=self.canvas,
|
canvas=self.canvas,
|
||||||
reach=self._reach,
|
reach=self._reach,
|
||||||
river=self._study.river,
|
river=self._study.river,
|
||||||
@@ -204,7 +204,7 @@ class FrictionsWindow(PamhyrWindow):
|
|||||||
data = self._reach
|
data = self._reach
|
||||||
reach = self._reach.reach
|
reach = self._reach.reach
|
||||||
sec = self._frictions.get(rows[0])
|
sec = self._frictions.get(rows[0])
|
||||||
highlight = (sec.begin_rk, sec.end_rk)
|
highlight = (sec.begin_kp, sec.end_kp)
|
||||||
|
|
||||||
self.update_plot(highlight)
|
self.update_plot(highlight)
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class FrictionsTranslate(MainTranslate):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(FrictionsTranslate, self).__init__()
|
super(FrictionsTranslate, self).__init__()
|
||||||
|
|
||||||
self._dict["rk"] = self._dict["unit_rk"]
|
self._dict["kp"] = self._dict["unit_kp"]
|
||||||
self._dict["strickler_plot"] = _translate(
|
self._dict["strickler_plot"] = _translate(
|
||||||
"Frictions", "Strickler ($m^{1/3}/s$)"
|
"Frictions", "Strickler ($m^{1/3}/s$)"
|
||||||
)
|
)
|
||||||
@@ -42,8 +42,8 @@ class FrictionsTranslate(MainTranslate):
|
|||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
# "name": self._dict["name"],
|
# "name": self._dict["name"],
|
||||||
# "edge": self._dict["reach"],
|
# "edge": self._dict["reach"],
|
||||||
"begin_rk": _translate("Frictions", "Start (m)"),
|
"begin_kp": _translate("Frictions", "Start (m)"),
|
||||||
"end_rk": _translate("Frictions", "End (m)"),
|
"end_kp": _translate("Frictions", "End (m)"),
|
||||||
"begin_strickler": _translate("Frictions", "Start coefficient"),
|
"begin_strickler": _translate("Frictions", "Start coefficient"),
|
||||||
"end_strickler": _translate("Frictions", "End coefficient"),
|
"end_strickler": _translate("Frictions", "End coefficient"),
|
||||||
}
|
}
|
||||||
@@ -76,11 +76,11 @@ class MeshingDialog(PamhyrDialog):
|
|||||||
def _init_default_values_profiles(self):
|
def _init_default_values_profiles(self):
|
||||||
profiles = self.profiles
|
profiles = self.profiles
|
||||||
|
|
||||||
self.combobox_add_items("comboBox_begin_rk", profiles)
|
self.combobox_add_items("comboBox_begin_kp", profiles)
|
||||||
self.combobox_add_items("comboBox_end_rk", profiles)
|
self.combobox_add_items("comboBox_end_kp", profiles)
|
||||||
|
|
||||||
self.set_combobox_text("comboBox_begin_rk", profiles[0])
|
self.set_combobox_text("comboBox_begin_kp", profiles[0])
|
||||||
self.set_combobox_text("comboBox_end_rk", profiles[-1])
|
self.set_combobox_text("comboBox_end_kp", profiles[-1])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def profiles(self):
|
def profiles(self):
|
||||||
@@ -98,9 +98,9 @@ class MeshingDialog(PamhyrDialog):
|
|||||||
name = profile.name
|
name = profile.name
|
||||||
|
|
||||||
if name == "":
|
if name == "":
|
||||||
name = f"{profile.rk}"
|
name = f"{profile.kp}"
|
||||||
else:
|
else:
|
||||||
name += f" ({profile.rk})"
|
name += f" ({profile.kp})"
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
@@ -151,8 +151,8 @@ class MeshingDialog(PamhyrDialog):
|
|||||||
)
|
)
|
||||||
self._linear = self.get_radio_button("radioButton_linear")
|
self._linear = self.get_radio_button("radioButton_linear")
|
||||||
|
|
||||||
p1 = self.get_combobox_text("comboBox_begin_rk")
|
p1 = self.get_combobox_text("comboBox_begin_kp")
|
||||||
p2 = self.get_combobox_text("comboBox_end_rk")
|
p2 = self.get_combobox_text("comboBox_end_kp")
|
||||||
|
|
||||||
self._begin_cs = self.profiles.index(p1)
|
self._begin_cs = self.profiles.index(p1)
|
||||||
self._end_cs = self.profiles.index(p2)
|
self._end_cs = self.profiles.index(p2)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# PlotRKC.py -- Pamhyr
|
# PlotKPC.py -- Pamhyr
|
||||||
# Copyright (C) 2023-2024 INRAE
|
# Copyright (C) 2023-2024 INRAE
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
@@ -29,13 +29,13 @@ from PyQt5.QtCore import (
|
|||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
class PlotRKZ(PamhyrPlot):
|
class PlotKPZ(PamhyrPlot):
|
||||||
def __init__(self, canvas=None, trad=None,
|
def __init__(self, canvas=None, trad=None,
|
||||||
study=None, data=None, toolbar=None,
|
study=None, data=None, toolbar=None,
|
||||||
table=None, parent=None):
|
table=None, parent=None):
|
||||||
self._study = study
|
self._study = study
|
||||||
|
|
||||||
super(PlotRKZ, self).__init__(
|
super(PlotKPZ, self).__init__(
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
trad=trad,
|
trad=trad,
|
||||||
data=data,
|
data=data,
|
||||||
@@ -46,12 +46,12 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
|
|
||||||
self._isometric_axis = False
|
self._isometric_axis = False
|
||||||
|
|
||||||
self.line_rk_zgl = []
|
self.line_kp_zgl = []
|
||||||
self.line_rk_zmin = None
|
self.line_kp_zmin = None
|
||||||
self.line_rk_zmin_zmax = None
|
self.line_kp_zmin_zmax = None
|
||||||
self.line_rk_zmin_zmax_highlight = None
|
self.line_kp_zmin_zmax_highlight = None
|
||||||
|
|
||||||
self.label_x = self._trad["unit_rk"]
|
self.label_x = self._trad["unit_kp"]
|
||||||
self.label_y = self._trad["unit_height"]
|
self.label_y = self._trad["unit_height"]
|
||||||
|
|
||||||
self.before_plot_selected = None
|
self.before_plot_selected = None
|
||||||
@@ -73,7 +73,7 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
Qt.ShiftModifier]:
|
Qt.ShiftModifier]:
|
||||||
return
|
return
|
||||||
|
|
||||||
ind, point = self._closest_rk(event)
|
ind, point = self._closest_kp(event)
|
||||||
if self.parent._table is None:
|
if self.parent._table is None:
|
||||||
return
|
return
|
||||||
self.parent._table.blockSignals(True)
|
self.parent._table.blockSignals(True)
|
||||||
@@ -107,7 +107,7 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _closest_rk(self, event):
|
def _closest_kp(self, event):
|
||||||
|
|
||||||
s = event.artist.get_segments()
|
s = event.artist.get_segments()
|
||||||
x = [i[0, 0] for i in s]
|
x = [i[0, 0] for i in s]
|
||||||
@@ -194,14 +194,14 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
self._init = True
|
self._init = True
|
||||||
|
|
||||||
def draw_z_line(self):
|
def draw_z_line(self):
|
||||||
rk = self.data.get_rk_complete_profiles()
|
kp = self.data.get_kp_complete_profiles()
|
||||||
z_min = self.data.get_z_min()
|
z_min = self.data.get_z_min()
|
||||||
z_max = self.data.get_z_max()
|
z_max = self.data.get_z_max()
|
||||||
|
|
||||||
self._colors, self._style = self.color_hightlight()
|
self._colors, self._style = self.color_hightlight()
|
||||||
|
|
||||||
self.line_rk_zmin_zmax = self.canvas.axes.vlines(
|
self.line_kp_zmin_zmax = self.canvas.axes.vlines(
|
||||||
x=rk, ymin=z_min, ymax=z_max,
|
x=kp, ymin=z_min, ymax=z_max,
|
||||||
color=self._colors,
|
color=self._colors,
|
||||||
linestyle=self._style,
|
linestyle=self._style,
|
||||||
lw=1.,
|
lw=1.,
|
||||||
@@ -228,7 +228,7 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
return colors, style
|
return colors, style
|
||||||
|
|
||||||
def draw_lr(self):
|
def draw_lr(self):
|
||||||
rk = self.data.get_rk_complete_profiles()
|
kp = self.data.get_kp_complete_profiles()
|
||||||
lz = []
|
lz = []
|
||||||
rz = []
|
rz = []
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
rz.append(z[-1])
|
rz.append(z[-1])
|
||||||
|
|
||||||
line = self.canvas.axes.plot(
|
line = self.canvas.axes.plot(
|
||||||
rk, lz,
|
kp, lz,
|
||||||
color=self.color_plot_river_bottom,
|
color=self.color_plot_river_bottom,
|
||||||
linestyle="dotted",
|
linestyle="dotted",
|
||||||
lw=1.,
|
lw=1.,
|
||||||
@@ -246,7 +246,7 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
self.line_lr.append(line)
|
self.line_lr.append(line)
|
||||||
|
|
||||||
line = self.canvas.axes.plot(
|
line = self.canvas.axes.plot(
|
||||||
rk, rz,
|
kp, rz,
|
||||||
color=self.color_plot_river_bottom,
|
color=self.color_plot_river_bottom,
|
||||||
linestyle="dotted",
|
linestyle="dotted",
|
||||||
lw=1.,
|
lw=1.,
|
||||||
@@ -254,18 +254,18 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
self.line_lr.append(line)
|
self.line_lr.append(line)
|
||||||
|
|
||||||
def draw_gl(self):
|
def draw_gl(self):
|
||||||
rk = self.data.get_rk_complete_profiles()
|
kp = self.data.get_kp_complete_profiles()
|
||||||
|
|
||||||
ind = 0
|
ind = 0
|
||||||
self.line_rk_zgl = []
|
self.line_kp_zgl = []
|
||||||
for z in self.data.get_guidelines_z():
|
for z in self.data.get_guidelines_z():
|
||||||
# Is incomplete guideline?
|
# Is incomplete guideline?
|
||||||
if len(z) != len(rk):
|
if len(z) != len(kp):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.line_rk_zgl.append(
|
self.line_kp_zgl.append(
|
||||||
self.canvas.axes.plot(
|
self.canvas.axes.plot(
|
||||||
rk, z, lw=1.,
|
kp, z, lw=1.,
|
||||||
color=self.colors[ind % len(self.colors)],
|
color=self.colors[ind % len(self.colors)],
|
||||||
linestyle=self.linestyle[ind // len(self.colors)]
|
linestyle=self.linestyle[ind // len(self.colors)]
|
||||||
)
|
)
|
||||||
@@ -273,11 +273,11 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
ind += 1
|
ind += 1
|
||||||
|
|
||||||
def draw_bottom(self):
|
def draw_bottom(self):
|
||||||
rk = self.data.get_rk_complete_profiles()
|
kp = self.data.get_kp_complete_profiles()
|
||||||
z_min = self.data.get_z_min()
|
z_min = self.data.get_z_min()
|
||||||
|
|
||||||
self.line_rk_zmin, = self.canvas.axes.plot(
|
self.line_kp_zmin, = self.canvas.axes.plot(
|
||||||
rk, z_min,
|
kp, z_min,
|
||||||
linestyle=":", lw=1.5,
|
linestyle=":", lw=1.5,
|
||||||
color='lightgrey'
|
color='lightgrey'
|
||||||
)
|
)
|
||||||
@@ -292,7 +292,7 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for hs in lhs:
|
for hs in lhs:
|
||||||
x = hs.input_rk
|
x = hs.input_kp
|
||||||
if x is not None:
|
if x is not None:
|
||||||
z_min = reach.get_z_min()
|
z_min = reach.get_z_min()
|
||||||
z_max = reach.get_z_max()
|
z_max = reach.get_z_max()
|
||||||
@@ -329,25 +329,25 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
def update_current(self):
|
def update_current(self):
|
||||||
if self._current_data_update:
|
if self._current_data_update:
|
||||||
self._colors, self._style = self.color_hightlight()
|
self._colors, self._style = self.color_hightlight()
|
||||||
self.line_rk_zmin_zmax.set_colors(self._colors)
|
self.line_kp_zmin_zmax.set_colors(self._colors)
|
||||||
self.line_rk_zmin_zmax.set_linestyle(self._style)
|
self.line_kp_zmin_zmax.set_linestyle(self._style)
|
||||||
|
|
||||||
def update_gl(self):
|
def update_gl(self):
|
||||||
if self._current_data_update:
|
if self._current_data_update:
|
||||||
return
|
return
|
||||||
|
|
||||||
rk = self.data.get_rk_complete_profiles()
|
kp = self.data.get_kp_complete_profiles()
|
||||||
z_min = self.data.get_z_min()
|
z_min = self.data.get_z_min()
|
||||||
z_max = self.data.get_z_max()
|
z_max = self.data.get_z_max()
|
||||||
|
|
||||||
self.line_rk_zmin.set_data(rk, z_min)
|
self.line_kp_zmin.set_data(kp, z_min)
|
||||||
|
|
||||||
# TODO comprendre à quoi sert ce bout de code
|
# TODO comprendre à quoi sert ce bout de code
|
||||||
# ========>
|
# ========>
|
||||||
# self.line_rk_zmin_zmax.remove()
|
# self.line_kp_zmin_zmax.remove()
|
||||||
# self._colors, self._style = self.color_hightlight()
|
# self._colors, self._style = self.color_hightlight()
|
||||||
# self.line_rk_zmin_zmax = self.canvas.axes.vlines(
|
# self.line_kp_zmin_zmax = self.canvas.axes.vlines(
|
||||||
# x=rk,
|
# x=kp,
|
||||||
# ymin=z_min,
|
# ymin=z_min,
|
||||||
# ymax=z_max,
|
# ymax=z_max,
|
||||||
# color=self._colors,
|
# color=self._colors,
|
||||||
@@ -358,12 +358,12 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
|
|
||||||
z_complete = self.data.get_guidelines_z()
|
z_complete = self.data.get_guidelines_z()
|
||||||
try:
|
try:
|
||||||
for i in range(len(self.line_rk_zgl)):
|
for i in range(len(self.line_kp_zgl)):
|
||||||
self.line_rk_zgl[i][0].set_data(
|
self.line_kp_zgl[i][0].set_data(
|
||||||
rk, z_complete[i]
|
kp, z_complete[i]
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Failed to update graphic RKZ: {e}")
|
logger.warning(f"Failed to update graphic KPZ: {e}")
|
||||||
|
|
||||||
def update_lr(self):
|
def update_lr(self):
|
||||||
for line in self.line_lr:
|
for line in self.line_lr:
|
||||||
@@ -56,7 +56,7 @@ class Plot(PamhyrPlot):
|
|||||||
self.line_xy = []
|
self.line_xy = []
|
||||||
self.line_gl = []
|
self.line_gl = []
|
||||||
|
|
||||||
self.label_x = self._trad["unit_rk"]
|
self.label_x = self._trad["unit_kp"]
|
||||||
self.label_y = self._trad["unit_height"]
|
self.label_y = self._trad["unit_height"]
|
||||||
|
|
||||||
self.before_plot_selected = None
|
self.before_plot_selected = None
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class ProfileWindow(PamhyrWindow):
|
|||||||
trad = GeometryProfileTranslate()
|
trad = GeometryProfileTranslate()
|
||||||
name = (
|
name = (
|
||||||
trad[self._pamhyr_name] +
|
trad[self._pamhyr_name] +
|
||||||
f" - {self._profile.name} {self._profile.rk}"
|
f" - {self._profile.name} {self._profile.kp}"
|
||||||
)
|
)
|
||||||
|
|
||||||
super(ProfileWindow, self).__init__(
|
super(ProfileWindow, self).__init__(
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ class GeometryReachTableModel(PamhyrTableModel):
|
|||||||
return self._data.profile(index.row()).name
|
return self._data.profile(index.row()).name
|
||||||
|
|
||||||
if role == Qt.DisplayRole and index.column() == 1:
|
if role == Qt.DisplayRole and index.column() == 1:
|
||||||
rk = self._data.profile(index.row()).rk
|
kp = self._data.profile(index.row()).kp
|
||||||
return f"{rk:.4f}"
|
return f"{kp:.4f}"
|
||||||
|
|
||||||
if role == Qt.DisplayRole and index.column() == 2:
|
if role == Qt.DisplayRole and index.column() == 2:
|
||||||
return str(self._data.profile(index.row()).nb_points)
|
return str(self._data.profile(index.row()).nb_points)
|
||||||
@@ -94,9 +94,9 @@ class GeometryReachTableModel(PamhyrTableModel):
|
|||||||
|
|
||||||
if index.column() == 1:
|
if index.column() == 1:
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetRKCommand(
|
SetKPCommand(
|
||||||
self._data, index.row(),
|
self._data, index.row(),
|
||||||
self._data.profile(index.row()).rk,
|
self._data.profile(index.row()).kp,
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -247,12 +247,12 @@ class GeometryReachTableModel(PamhyrTableModel):
|
|||||||
self.layoutAboutToBeChanged.emit()
|
self.layoutAboutToBeChanged.emit()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
def update_rk(self, mesher, data):
|
def update_kp(self, mesher, data):
|
||||||
self.layoutAboutToBeChanged.emit()
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
MeshingCommand(
|
MeshingCommand(
|
||||||
self._data, mesher, data, "update_rk"
|
self._data, mesher, data, "update_kp"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class GeometryTranslate(MainTranslate):
|
|||||||
|
|
||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
"name": self._dict["name"],
|
"name": self._dict["name"],
|
||||||
"rk": self._dict["unit_rk"],
|
"kp": self._dict["unit_kp"],
|
||||||
"poins": _translate("Geometry", "Points"),
|
"poins": _translate("Geometry", "Points"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,16 +56,16 @@ class SetNameCommand(SetDataCommand):
|
|||||||
self._reach.profile(self._index).name = self._new
|
self._reach.profile(self._index).name = self._new
|
||||||
|
|
||||||
|
|
||||||
class SetRKCommand(SetDataCommand):
|
class SetKPCommand(SetDataCommand):
|
||||||
def __init__(self, reach, index, old_value, new_value):
|
def __init__(self, reach, index, old_value, new_value):
|
||||||
self.type = float
|
self.type = float
|
||||||
super(SetRKCommand, self).__init__(reach, index, old_value, new_value)
|
super(SetKPCommand, self).__init__(reach, index, old_value, new_value)
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._reach.profile(self._index).rk = self._old
|
self._reach.profile(self._index).kp = self._old
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
self._reach.profile(self._index).rk = self._new
|
self._reach.profile(self._index).kp = self._new
|
||||||
|
|
||||||
|
|
||||||
class AddCommand(QUndoCommand):
|
class AddCommand(QUndoCommand):
|
||||||
@@ -243,8 +243,8 @@ class MeshingCommand(QUndoCommand):
|
|||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
if self._new_profiles is None:
|
if self._new_profiles is None:
|
||||||
if self._command == "update_rk":
|
if self._command == "update_kp":
|
||||||
self._mesher.update_rk(
|
self._mesher.update_kp(
|
||||||
self._reach,
|
self._reach,
|
||||||
**self._data
|
**self._data
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# UpdateRKDialog.py -- Pamhyr
|
# UpdateKPDialog.py -- Pamhyr
|
||||||
# Copyright (C) 2023-2024 INRAE
|
# Copyright (C) 2023-2024 INRAE
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
@@ -32,12 +32,12 @@ from PyQt5.QtWidgets import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UpdateRKDialog(PamhyrDialog):
|
class UpdateKPDialog(PamhyrDialog):
|
||||||
_pamhyr_ui = "UpdateRKOptions"
|
_pamhyr_ui = "UpdateKPOptions"
|
||||||
_pamhyr_name = "UpdateRK"
|
_pamhyr_name = "UpdateKP"
|
||||||
|
|
||||||
def __init__(self, reach, trad=None, parent=None):
|
def __init__(self, reach, trad=None, parent=None):
|
||||||
super(UpdateRKDialog, self).__init__(
|
super(UpdateKPDialog, self).__init__(
|
||||||
title=trad[self._pamhyr_name],
|
title=trad[self._pamhyr_name],
|
||||||
trad=trad,
|
trad=trad,
|
||||||
options=[],
|
options=[],
|
||||||
@@ -65,7 +65,7 @@ class UpdateRKDialog(PamhyrDialog):
|
|||||||
|
|
||||||
self._orientation = 0
|
self._orientation = 0
|
||||||
self._origin = self._reach.profile(0)
|
self._origin = self._reach.profile(0)
|
||||||
self._origin_value = self._reach.profile(0).rk
|
self._origin_value = self._reach.profile(0).kp
|
||||||
|
|
||||||
self._init_default_values_profiles()
|
self._init_default_values_profiles()
|
||||||
self._init_default_values_guidelines()
|
self._init_default_values_guidelines()
|
||||||
@@ -93,7 +93,7 @@ class UpdateRKDialog(PamhyrDialog):
|
|||||||
origin = self.get_combobox_text("comboBox_origin")
|
origin = self.get_combobox_text("comboBox_origin")
|
||||||
self.set_double_spin_box(
|
self.set_double_spin_box(
|
||||||
"doubleSpinBox_origin",
|
"doubleSpinBox_origin",
|
||||||
self._reach.profile(self.profiles.index(origin)).rk
|
self._reach.profile(self.profiles.index(origin)).kp
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -112,9 +112,9 @@ class UpdateRKDialog(PamhyrDialog):
|
|||||||
name = profile.name
|
name = profile.name
|
||||||
|
|
||||||
if name == "":
|
if name == "":
|
||||||
name = f"{profile.rk}"
|
name = f"{profile.kp}"
|
||||||
else:
|
else:
|
||||||
name += f" ({profile.rk})"
|
name += f" ({profile.kp})"
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
+39
-39
@@ -54,9 +54,9 @@ from Meshing.Mage import (
|
|||||||
from View.Geometry.Table import GeometryReachTableModel
|
from View.Geometry.Table import GeometryReachTableModel
|
||||||
from View.Geometry.PlotXY import PlotXY
|
from View.Geometry.PlotXY import PlotXY
|
||||||
from View.Geometry.PlotAC import PlotAC
|
from View.Geometry.PlotAC import PlotAC
|
||||||
from View.Geometry.PlotRKZ import PlotRKZ
|
from View.Geometry.PlotKPZ import PlotKPZ
|
||||||
from View.Geometry.MeshingDialog import MeshingDialog
|
from View.Geometry.MeshingDialog import MeshingDialog
|
||||||
from View.Geometry.UpdateRKDialog import UpdateRKDialog
|
from View.Geometry.UpdateKPDialog import UpdateKPDialog
|
||||||
from View.Geometry.PurgeDialog import PurgeDialog
|
from View.Geometry.PurgeDialog import PurgeDialog
|
||||||
from View.Geometry.Translate import GeometryTranslate
|
from View.Geometry.Translate import GeometryTranslate
|
||||||
from View.Geometry.Profile.Window import ProfileWindow
|
from View.Geometry.Profile.Window import ProfileWindow
|
||||||
@@ -105,7 +105,7 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
self._table = GeometryReachTableModel(
|
self._table = GeometryReachTableModel(
|
||||||
table_view=table,
|
table_view=table,
|
||||||
table_headers=table_headers,
|
table_headers=table_headers,
|
||||||
editable_headers=["name", "rk"],
|
editable_headers=["name", "kp"],
|
||||||
data=self._reach,
|
data=self._reach,
|
||||||
undo=self._undo_stack
|
undo=self._undo_stack
|
||||||
)
|
)
|
||||||
@@ -116,7 +116,7 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
|
|
||||||
def setup_plots(self):
|
def setup_plots(self):
|
||||||
self.setup_plots_xy()
|
self.setup_plots_xy()
|
||||||
self.setup_plots_rkc()
|
self.setup_plots_kpc()
|
||||||
self.setup_plots_ac()
|
self.setup_plots_ac()
|
||||||
|
|
||||||
def setup_plots_xy(self):
|
def setup_plots_xy(self):
|
||||||
@@ -131,17 +131,17 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
self._plot_layout_xy.addWidget(self._canvas_xy)
|
self._plot_layout_xy.addWidget(self._canvas_xy)
|
||||||
self.plot_xy()
|
self.plot_xy()
|
||||||
|
|
||||||
def setup_plots_rkc(self):
|
def setup_plots_kpc(self):
|
||||||
self._canvas_rkc = MplCanvas(width=6, height=4, dpi=100)
|
self._canvas_kpc = MplCanvas(width=6, height=4, dpi=100)
|
||||||
self._canvas_rkc.setObjectName("canvas_rkc")
|
self._canvas_kpc.setObjectName("canvas_kpc")
|
||||||
self._toolbar_rkc = PamhyrPlotToolbar(
|
self._toolbar_kpc = PamhyrPlotToolbar(
|
||||||
self._canvas_rkc, self,
|
self._canvas_kpc, self,
|
||||||
items=["home", "zoom", "save", "iso", "back/forward", "move"]
|
items=["home", "zoom", "save", "iso", "back/forward", "move"]
|
||||||
)
|
)
|
||||||
self._plot_layout_rkc = self.find(QVBoxLayout, "verticalLayout_2")
|
self._plot_layout_kpc = self.find(QVBoxLayout, "verticalLayout_2")
|
||||||
self._plot_layout_rkc.addWidget(self._toolbar_rkc)
|
self._plot_layout_kpc.addWidget(self._toolbar_kpc)
|
||||||
self._plot_layout_rkc.addWidget(self._canvas_rkc)
|
self._plot_layout_kpc.addWidget(self._canvas_kpc)
|
||||||
self.plot_rkc()
|
self.plot_kpc()
|
||||||
|
|
||||||
def setup_plots_ac(self):
|
def setup_plots_ac(self):
|
||||||
self._canvas_ac = MplCanvas(width=9, height=4, dpi=100)
|
self._canvas_ac = MplCanvas(width=9, height=4, dpi=100)
|
||||||
@@ -162,7 +162,7 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
|
|
||||||
profile = self._reach.profile(row)
|
profile = self._reach.profile(row)
|
||||||
|
|
||||||
name = profile.name + " " + str(profile.rk)
|
name = profile.name + " " + str(profile.kp)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
"<font color=\"Grey\">" +
|
"<font color=\"Grey\">" +
|
||||||
@@ -192,7 +192,7 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
"action_delete": self.delete,
|
"action_delete": self.delete,
|
||||||
"action_edit": self.edit_profile,
|
"action_edit": self.edit_profile,
|
||||||
"action_meshing": self.edit_meshing,
|
"action_meshing": self.edit_meshing,
|
||||||
"action_update_rk": self.update_rk,
|
"action_update_kp": self.update_kp,
|
||||||
"action_purge": self.purge,
|
"action_purge": self.purge,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
def _update(self, redraw=False, propagate=True):
|
def _update(self, redraw=False, propagate=True):
|
||||||
if redraw:
|
if redraw:
|
||||||
self._plot_xy.draw()
|
self._plot_xy.draw()
|
||||||
self._plot_rkc.draw()
|
self._plot_kpc.draw()
|
||||||
self._plot_ac.draw()
|
self._plot_ac.draw()
|
||||||
|
|
||||||
self.select_current_profile()
|
self.select_current_profile()
|
||||||
@@ -315,9 +315,9 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
src_except=e
|
src_except=e
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_rk(self):
|
def update_kp(self):
|
||||||
try:
|
try:
|
||||||
dlg = UpdateRKDialog(
|
dlg = UpdateKPDialog(
|
||||||
reach=self._reach,
|
reach=self._reach,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
parent=self
|
parent=self
|
||||||
@@ -329,15 +329,15 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
"origin_value": dlg.origin_value,
|
"origin_value": dlg.origin_value,
|
||||||
"orientation": dlg.orientation,
|
"orientation": dlg.orientation,
|
||||||
}
|
}
|
||||||
self._update_rk(data)
|
self._update_kp(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger_exception(e)
|
logger_exception(e)
|
||||||
return
|
return
|
||||||
|
|
||||||
def _update_rk(self, data):
|
def _update_kp(self, data):
|
||||||
try:
|
try:
|
||||||
mesher = MeshingWithMageMailleurTT()
|
mesher = MeshingWithMageMailleurTT()
|
||||||
self._table.update_rk(mesher, data)
|
self._table.update_kp(mesher, data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger_exception(e)
|
logger_exception(e)
|
||||||
raise ExternFileMissingError(
|
raise ExternFileMissingError(
|
||||||
@@ -367,25 +367,25 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
self._plot_xy.update()
|
self._plot_xy.update()
|
||||||
self.tableView.model().blockSignals(False)
|
self.tableView.model().blockSignals(False)
|
||||||
|
|
||||||
def plot_rkc(self):
|
def plot_kpc(self):
|
||||||
self.tableView.model().blockSignals(True)
|
self.tableView.model().blockSignals(True)
|
||||||
|
|
||||||
self._plot_rkc = PlotRKZ(
|
self._plot_kpc = PlotKPZ(
|
||||||
canvas=self._canvas_rkc,
|
canvas=self._canvas_kpc,
|
||||||
study=self._study,
|
study=self._study,
|
||||||
data=self._reach,
|
data=self._reach,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
toolbar=self._toolbar_rkc,
|
toolbar=self._toolbar_kpc,
|
||||||
table=self.find(QTableView, "tableView"),
|
table=self.find(QTableView, "tableView"),
|
||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
self._plot_rkc.draw()
|
self._plot_kpc.draw()
|
||||||
|
|
||||||
self.tableView.model().blockSignals(False)
|
self.tableView.model().blockSignals(False)
|
||||||
|
|
||||||
def update_plot_rkc(self):
|
def update_plot_kpc(self):
|
||||||
self.tableView.model().blockSignals(True)
|
self.tableView.model().blockSignals(True)
|
||||||
self._plot_rkc.update()
|
self._plot_kpc.update()
|
||||||
self.tableView.model().blockSignals(False)
|
self.tableView.model().blockSignals(False)
|
||||||
|
|
||||||
def plot_ac(self):
|
def plot_ac(self):
|
||||||
@@ -418,10 +418,10 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
self._plot_xy.update()
|
self._plot_xy.update()
|
||||||
self.tableView.model().blockSignals(False)
|
self.tableView.model().blockSignals(False)
|
||||||
|
|
||||||
def select_plot_rkc(self, ind: int):
|
def select_plot_kpc(self, ind: int):
|
||||||
self.tableView.model().blockSignals(True)
|
self.tableView.model().blockSignals(True)
|
||||||
self._plot_rkc.current = ind
|
self._plot_kpc.current = ind
|
||||||
self._plot_rkc.update()
|
self._plot_kpc.update()
|
||||||
self.tableView.model().blockSignals(False)
|
self.tableView.model().blockSignals(False)
|
||||||
|
|
||||||
def select_plot_ac(self, ind: int):
|
def select_plot_ac(self, ind: int):
|
||||||
@@ -436,11 +436,11 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
|
|
||||||
if row is not None:
|
if row is not None:
|
||||||
self.select_plot_xy(row)
|
self.select_plot_xy(row)
|
||||||
self.select_plot_rkc(row)
|
self.select_plot_kpc(row)
|
||||||
self.select_plot_ac(row)
|
self.select_plot_ac(row)
|
||||||
else:
|
else:
|
||||||
self._plot_xy.draw()
|
self._plot_xy.draw()
|
||||||
self._plot_rkc.draw()
|
self._plot_kpc.draw()
|
||||||
self._plot_ac.draw()
|
self._plot_ac.draw()
|
||||||
|
|
||||||
self.tableView.model().blockSignals(False)
|
self.tableView.model().blockSignals(False)
|
||||||
@@ -539,12 +539,12 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
.selectedRows()
|
.selectedRows()
|
||||||
|
|
||||||
table = []
|
table = []
|
||||||
# table.append(["name", "rk"])
|
# table.append(["name", "kp"])
|
||||||
|
|
||||||
for row in rows:
|
for row in rows:
|
||||||
profile = self._reach.profile(row.row())
|
profile = self._reach.profile(row.row())
|
||||||
table.append(
|
table.append(
|
||||||
[profile.name, profile.rk]
|
[profile.name, profile.kp]
|
||||||
)
|
)
|
||||||
|
|
||||||
self.copyTableIntoClipboard(table)
|
self.copyTableIntoClipboard(table)
|
||||||
@@ -588,14 +588,14 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
self.select_current_profile()
|
self.select_current_profile()
|
||||||
# self.update_plot_ac()
|
# self.update_plot_ac()
|
||||||
# self.update_plot_xy()
|
# self.update_plot_xy()
|
||||||
# self.update_plot_rkc()
|
# self.update_plot_kpc()
|
||||||
|
|
||||||
def _redo(self):
|
def _redo(self):
|
||||||
self._table.redo()
|
self._table.redo()
|
||||||
self.select_current_profile()
|
self.select_current_profile()
|
||||||
# self.update_plot_ac()
|
# self.update_plot_ac()
|
||||||
# self.update_plot_xy()
|
# self.update_plot_xy()
|
||||||
# self.update_plot_rkc()
|
# self.update_plot_kpc()
|
||||||
|
|
||||||
def export_to_file(self):
|
def export_to_file(self):
|
||||||
settings = QSettings(
|
settings = QSettings(
|
||||||
@@ -642,13 +642,13 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
c1 = f"{profile.code1:>6}"
|
c1 = f"{profile.code1:>6}"
|
||||||
c2 = f"{profile.code2:>6}"
|
c2 = f"{profile.code2:>6}"
|
||||||
t = f"{len(profile.points):>6}"
|
t = f"{len(profile.points):>6}"
|
||||||
rk = f"{profile.rk:>12f}"[0:12]
|
kp = f"{profile.kp:>12f}"[0:12]
|
||||||
pname = profile.name
|
pname = profile.name
|
||||||
if profile.name == "":
|
if profile.name == "":
|
||||||
pname = f"p{profile.id:>3}".replace(" ", "0")
|
pname = f"p{profile.id:>3}".replace(" ", "0")
|
||||||
name = f"{pname:<19}"
|
name = f"{pname:<19}"
|
||||||
|
|
||||||
wfile.write(f"{num}{c1}{c2}{t} {rk} {pname}\n")
|
wfile.write(f"{num}{c1}{c2}{t} {kp} {pname}\n")
|
||||||
|
|
||||||
for point in profile.points:
|
for point in profile.points:
|
||||||
self._export_to_file_st_point(wfile, point)
|
self._export_to_file_st_point(wfile, point)
|
||||||
|
|||||||
@@ -150,9 +150,9 @@ class BasicHydraulicStructuresWindow(PamhyrWindow):
|
|||||||
self.plot_layout.addWidget(self.canvas)
|
self.plot_layout.addWidget(self.canvas)
|
||||||
|
|
||||||
reach = self._hs.input_reach
|
reach = self._hs.input_reach
|
||||||
profile_rk = self._hs.input_rk
|
profile_kp = self._hs.input_kp
|
||||||
if profile_rk is not None:
|
if profile_kp is not None:
|
||||||
profiles = reach.reach.get_profiles_from_rk(float(profile_rk))
|
profiles = reach.reach.get_profiles_from_kp(float(profile_kp))
|
||||||
else:
|
else:
|
||||||
profiles = None
|
profiles = None
|
||||||
if profiles is not None:
|
if profiles is not None:
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ class PlotAC(PamhyrPlot):
|
|||||||
self.init_axes()
|
self.init_axes()
|
||||||
|
|
||||||
if self.data is None:
|
if self.data is None:
|
||||||
self.line_rk = None
|
self.line_kp = None
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._current_reach is None:
|
if self._current_reach is None:
|
||||||
self.line_rk = None
|
self.line_kp = None
|
||||||
return
|
return
|
||||||
|
|
||||||
self.draw_data()
|
self.draw_data()
|
||||||
@@ -73,13 +73,13 @@ class PlotAC(PamhyrPlot):
|
|||||||
reach = self._current_reach
|
reach = self._current_reach
|
||||||
|
|
||||||
if self._current_profile is None:
|
if self._current_profile is None:
|
||||||
self.line_rk = None
|
self.line_kp = None
|
||||||
else:
|
else:
|
||||||
profile = self._current_profile
|
profile = self._current_profile
|
||||||
x = profile.get_station()
|
x = profile.get_station()
|
||||||
z = profile.z()
|
z = profile.z()
|
||||||
|
|
||||||
self.line_rk, = self.canvas.axes.plot(
|
self.line_kp, = self.canvas.axes.plot(
|
||||||
x, z,
|
x, z,
|
||||||
color=self.color_plot_river_bottom,
|
color=self.color_plot_river_bottom,
|
||||||
**self.plot_default_kargs
|
**self.plot_default_kargs
|
||||||
@@ -94,7 +94,7 @@ class PlotAC(PamhyrPlot):
|
|||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
if self.line_rk is None:
|
if self.line_kp is None:
|
||||||
self.draw()
|
self.draw()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -110,11 +110,11 @@ class PlotAC(PamhyrPlot):
|
|||||||
x = profile.get_station()
|
x = profile.get_station()
|
||||||
z = profile.z()
|
z = profile.z()
|
||||||
|
|
||||||
self.line_rk.set_data(x, z)
|
self.line_kp.set_data(x, z)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self.update_clear()
|
self.update_clear()
|
||||||
|
|
||||||
def update_clear(self):
|
def update_clear(self):
|
||||||
if self.line_rk is not None:
|
if self.line_kp is not None:
|
||||||
self.line_rk.set_data([], [])
|
self.line_kp.set_data([], [])
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# PlotRKC.py -- Pamhyr
|
# PlotKPC.py -- Pamhyr
|
||||||
# Copyright (C) 2023-2024 INRAE
|
# Copyright (C) 2023-2024 INRAE
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
@@ -29,11 +29,11 @@ from matplotlib.collections import LineCollection
|
|||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
class PlotRKC(PamhyrPlot):
|
class PlotKPC(PamhyrPlot):
|
||||||
def __init__(self, canvas=None, trad=None, toolbar=None,
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
river=None, reach=None, profile=None,
|
river=None, reach=None, profile=None,
|
||||||
parent=None):
|
parent=None):
|
||||||
super(PlotRKC, self).__init__(
|
super(PlotKPC, self).__init__(
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
trad=trad,
|
trad=trad,
|
||||||
data=river,
|
data=river,
|
||||||
@@ -44,7 +44,7 @@ class PlotRKC(PamhyrPlot):
|
|||||||
self._current_reach = reach
|
self._current_reach = reach
|
||||||
self._current_profile = profile
|
self._current_profile = profile
|
||||||
|
|
||||||
self.label_x = self._trad["unit_rk"]
|
self.label_x = self._trad["unit_kp"]
|
||||||
self.label_y = self._trad["unit_elevation"]
|
self.label_y = self._trad["unit_elevation"]
|
||||||
|
|
||||||
self._isometric_axis = False
|
self._isometric_axis = False
|
||||||
@@ -67,14 +67,14 @@ class PlotRKC(PamhyrPlot):
|
|||||||
|
|
||||||
if self.data is None:
|
if self.data is None:
|
||||||
self.profile = None
|
self.profile = None
|
||||||
self.line_rk_zmin_zmax = None
|
self.line_kp_zmin_zmax = None
|
||||||
self.line_rk_zmin = None
|
self.line_kp_zmin = None
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._current_reach is None:
|
if self._current_reach is None:
|
||||||
self.profile = None
|
self.profile = None
|
||||||
self.line_rk_zmin_zmax = None
|
self.line_kp_zmin_zmax = None
|
||||||
self.line_rk_zmin = None
|
self.line_kp_zmin = None
|
||||||
return
|
return
|
||||||
|
|
||||||
self.draw_data()
|
self.draw_data()
|
||||||
@@ -86,26 +86,26 @@ class PlotRKC(PamhyrPlot):
|
|||||||
def draw_data(self):
|
def draw_data(self):
|
||||||
reach = self._current_reach
|
reach = self._current_reach
|
||||||
|
|
||||||
rk = reach.reach.get_rk()
|
kp = reach.reach.get_kp()
|
||||||
z_min = reach.reach.get_z_min()
|
z_min = reach.reach.get_z_min()
|
||||||
z_max = reach.reach.get_z_max()
|
z_max = reach.reach.get_z_max()
|
||||||
|
|
||||||
self.line_rk_zmin, = self.canvas.axes.plot(
|
self.line_kp_zmin, = self.canvas.axes.plot(
|
||||||
rk, z_min,
|
kp, z_min,
|
||||||
color=self.color_plot_river_bottom,
|
color=self.color_plot_river_bottom,
|
||||||
lw=1.,
|
lw=1.,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.line_rk_zmax, = self.canvas.axes.plot(
|
self.line_kp_zmax, = self.canvas.axes.plot(
|
||||||
rk, z_max,
|
kp, z_max,
|
||||||
color=self.color_plot_river_bottom,
|
color=self.color_plot_river_bottom,
|
||||||
lw=1.,
|
lw=1.,
|
||||||
alpha=0.0
|
alpha=0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(rk) != 0:
|
if len(kp) != 0:
|
||||||
self.line_rk_zmin_zmax = self.canvas.axes.vlines(
|
self.line_kp_zmin_zmax = self.canvas.axes.vlines(
|
||||||
x=rk,
|
x=kp,
|
||||||
ymin=z_min, ymax=z_max,
|
ymin=z_min, ymax=z_max,
|
||||||
color=self.color_plot,
|
color=self.color_plot,
|
||||||
lw=1.,
|
lw=1.,
|
||||||
@@ -116,13 +116,13 @@ class PlotRKC(PamhyrPlot):
|
|||||||
if self._current_profile is None:
|
if self._current_profile is None:
|
||||||
self.profile = None
|
self.profile = None
|
||||||
else:
|
else:
|
||||||
rk = [self._current_profile.rk,
|
kp = [self._current_profile.kp,
|
||||||
self._current_profile.rk]
|
self._current_profile.kp]
|
||||||
min_max = [self._current_profile.z_min(),
|
min_max = [self._current_profile.z_min(),
|
||||||
self._current_profile.z_max()]
|
self._current_profile.z_max()]
|
||||||
|
|
||||||
self.profile = self.canvas.axes.plot(
|
self.profile = self.canvas.axes.plot(
|
||||||
rk, min_max,
|
kp, min_max,
|
||||||
color=self.color_plot_current,
|
color=self.color_plot_current,
|
||||||
lw=1.
|
lw=1.
|
||||||
)
|
)
|
||||||
@@ -141,7 +141,7 @@ class PlotRKC(PamhyrPlot):
|
|||||||
|
|
||||||
def update_current_profile(self):
|
def update_current_profile(self):
|
||||||
reach = self._current_reach
|
reach = self._current_reach
|
||||||
rk = reach.reach.get_rk()
|
kp = reach.reach.get_kp()
|
||||||
z_min = reach.reach.get_z_min()
|
z_min = reach.reach.get_z_min()
|
||||||
z_max = reach.reach.get_z_max()
|
z_max = reach.reach.get_z_max()
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ class PlotRKC(PamhyrPlot):
|
|||||||
self.draw()
|
self.draw()
|
||||||
else:
|
else:
|
||||||
self.profile.set_data(
|
self.profile.set_data(
|
||||||
[self._current_profile.rk, self._current_profile.rk],
|
[self._current_profile.kp, self._current_profile.kp],
|
||||||
[self._current_profile.z_min(), self._current_profile.z_max()],
|
[self._current_profile.z_min(), self._current_profile.z_max()],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -159,12 +159,12 @@ class PlotRKC(PamhyrPlot):
|
|||||||
if self.profile is not None:
|
if self.profile is not None:
|
||||||
self.profile[0].set_data([], [])
|
self.profile[0].set_data([], [])
|
||||||
|
|
||||||
if self.line_rk_zmin_zmax is not None:
|
if self.line_kp_zmin_zmax is not None:
|
||||||
self.line_rk_zmin_zmax.remove()
|
self.line_kp_zmin_zmax.remove()
|
||||||
self.line_rk_zmin_zmax = None
|
self.line_kp_zmin_zmax = None
|
||||||
|
|
||||||
if self.line_rk_zmin is not None:
|
if self.line_kp_zmin is not None:
|
||||||
self.line_rk_zmin.set_data([], [])
|
self.line_kp_zmin.set_data([], [])
|
||||||
|
|
||||||
self.canvas.figure.canvas.draw_idle()
|
self.canvas.figure.canvas.draw_idle()
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ from PyQt5.QtWidgets import (
|
|||||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
from View.HydraulicStructures.UndoCommand import (
|
from View.HydraulicStructures.UndoCommand import (
|
||||||
SetNameCommand, SetReachCommand, SetRkCommand,
|
SetNameCommand, SetReachCommand, SetKpCommand,
|
||||||
SetEnabledCommand, AddCommand, DelCommand,
|
SetEnabledCommand, AddCommand, DelCommand,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,14 +58,14 @@ class ComboBoxDelegate(QItemDelegate):
|
|||||||
self.editor = QComboBox(parent)
|
self.editor = QComboBox(parent)
|
||||||
|
|
||||||
val = []
|
val = []
|
||||||
if self._mode == "rk":
|
if self._mode == "kp":
|
||||||
reach = self._data.hydraulic_structures\
|
reach = self._data.hydraulic_structures\
|
||||||
.get(index.row())\
|
.get(index.row())\
|
||||||
.input_reach
|
.input_reach
|
||||||
if reach is not None:
|
if reach is not None:
|
||||||
val = list(
|
val = list(
|
||||||
map(
|
map(
|
||||||
lambda rk: str(rk), reach.reach.get_rk()
|
lambda kp: str(kp), reach.reach.get_kp()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -126,8 +126,8 @@ class TableModel(PamhyrTableModel):
|
|||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n.name
|
return n.name
|
||||||
elif self._headers[column] == "rk":
|
elif self._headers[column] == "kp":
|
||||||
n = self._lst.get(row).input_rk
|
n = self._lst.get(row).input_kp
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
@@ -158,12 +158,12 @@ class TableModel(PamhyrTableModel):
|
|||||||
self._lst, row, self._data.edge(value)
|
self._lst, row, self._data.edge(value)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif self._headers[column] == "rk":
|
elif self._headers[column] == "kp":
|
||||||
if value == na:
|
if value == na:
|
||||||
value = None
|
value = None
|
||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetRkCommand(
|
SetKpCommand(
|
||||||
self._lst, row, value
|
self._lst, row, value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -36,5 +36,5 @@ class HydraulicStructuresTranslate(MainTranslate):
|
|||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
"name": self._dict["name"],
|
"name": self._dict["name"],
|
||||||
"reach": self._dict["reach"],
|
"reach": self._dict["reach"],
|
||||||
"rk": self._dict["unit_rk"],
|
"kp": self._dict["unit_kp"],
|
||||||
}
|
}
|
||||||
@@ -52,34 +52,34 @@ class SetReachCommand(QUndoCommand):
|
|||||||
self._index = index
|
self._index = index
|
||||||
self._old = self._h_s_lst.get(self._index).input_reach
|
self._old = self._h_s_lst.get(self._index).input_reach
|
||||||
self._new = reach
|
self._new = reach
|
||||||
self._old_rk = self._h_s_lst.get(self._index).input_rk
|
self._old_kp = self._h_s_lst.get(self._index).input_kp
|
||||||
self._new_rk = None
|
self._new_kp = None
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
i = self._h_s_lst.get(self._index)
|
i = self._h_s_lst.get(self._index)
|
||||||
i.input_reach = self._old
|
i.input_reach = self._old
|
||||||
i.input_rk = self._old_rk
|
i.input_kp = self._old_kp
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
i = self._h_s_lst.get(self._index)
|
i = self._h_s_lst.get(self._index)
|
||||||
i.input_reach = self._new
|
i.input_reach = self._new
|
||||||
i.input_rk = self._new_rk
|
i.input_kp = self._new_kp
|
||||||
|
|
||||||
|
|
||||||
class SetRkCommand(QUndoCommand):
|
class SetKpCommand(QUndoCommand):
|
||||||
def __init__(self, h_s_lst, index, rk):
|
def __init__(self, h_s_lst, index, kp):
|
||||||
QUndoCommand.__init__(self)
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
self._h_s_lst = h_s_lst
|
self._h_s_lst = h_s_lst
|
||||||
self._index = index
|
self._index = index
|
||||||
self._old = self._h_s_lst.get(self._index).input_rk
|
self._old = self._h_s_lst.get(self._index).input_kp
|
||||||
self._new = rk
|
self._new = kp
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._h_s_lst.get(self._index).input_rk = self._old
|
self._h_s_lst.get(self._index).input_kp = self._old
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
self._h_s_lst.get(self._index).input_rk = self._new
|
self._h_s_lst.get(self._index).input_kp = self._new
|
||||||
|
|
||||||
|
|
||||||
class SetEnabledCommand(QUndoCommand):
|
class SetEnabledCommand(QUndoCommand):
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
|||||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||||
|
|
||||||
from View.HydraulicStructures.PlotAC import PlotAC
|
from View.HydraulicStructures.PlotAC import PlotAC
|
||||||
from View.HydraulicStructures.PlotRKC import PlotRKC
|
from View.HydraulicStructures.PlotKPC import PlotKPC
|
||||||
|
|
||||||
from View.HydraulicStructures.Table import (
|
from View.HydraulicStructures.Table import (
|
||||||
TableModel, ComboBoxDelegate
|
TableModel, ComboBoxDelegate
|
||||||
@@ -89,21 +89,21 @@ class HydraulicStructuresWindow(PamhyrWindow):
|
|||||||
parent=self,
|
parent=self,
|
||||||
mode="reaches"
|
mode="reaches"
|
||||||
)
|
)
|
||||||
self._delegate_rk = ComboBoxDelegate(
|
self._delegate_kp = ComboBoxDelegate(
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
data=self._study.river,
|
data=self._study.river,
|
||||||
parent=self,
|
parent=self,
|
||||||
mode="rk"
|
mode="kp"
|
||||||
)
|
)
|
||||||
|
|
||||||
table = self.find(QTableView, f"tableView")
|
table = self.find(QTableView, f"tableView")
|
||||||
self._table = TableModel(
|
self._table = TableModel(
|
||||||
table_view=table,
|
table_view=table,
|
||||||
table_headers=self._trad.get_dict("table_headers"),
|
table_headers=self._trad.get_dict("table_headers"),
|
||||||
editable_headers=["name", "reach", "rk"],
|
editable_headers=["name", "reach", "kp"],
|
||||||
delegates={
|
delegates={
|
||||||
"reach": self._delegate_reach,
|
"reach": self._delegate_reach,
|
||||||
"rk": self._delegate_rk,
|
"kp": self._delegate_kp,
|
||||||
},
|
},
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
data=self._study.river,
|
data=self._study.river,
|
||||||
@@ -135,7 +135,7 @@ class HydraulicStructuresWindow(PamhyrWindow):
|
|||||||
self.plot_layout.addWidget(self.toolbar)
|
self.plot_layout.addWidget(self.toolbar)
|
||||||
self.plot_layout.addWidget(self.canvas)
|
self.plot_layout.addWidget(self.canvas)
|
||||||
|
|
||||||
self.plot_rkc = PlotRKC(
|
self.plot_kpc = PlotKPC(
|
||||||
canvas=self.canvas,
|
canvas=self.canvas,
|
||||||
river=self._study.river,
|
river=self._study.river,
|
||||||
reach=None,
|
reach=None,
|
||||||
@@ -144,7 +144,7 @@ class HydraulicStructuresWindow(PamhyrWindow):
|
|||||||
toolbar=self.toolbar,
|
toolbar=self.toolbar,
|
||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
self.plot_rkc.draw()
|
self.plot_kpc.draw()
|
||||||
|
|
||||||
self.canvas_2 = MplCanvas(width=5, height=4, dpi=100)
|
self.canvas_2 = MplCanvas(width=5, height=4, dpi=100)
|
||||||
self.canvas_2.setObjectName("canvas_2")
|
self.canvas_2.setObjectName("canvas_2")
|
||||||
@@ -285,20 +285,20 @@ class HydraulicStructuresWindow(PamhyrWindow):
|
|||||||
|
|
||||||
reach = self._hs_lst.get(rows[0]).input_reach
|
reach = self._hs_lst.get(rows[0]).input_reach
|
||||||
if reach is not None:
|
if reach is not None:
|
||||||
self.plot_rkc.set_reach(reach)
|
self.plot_kpc.set_reach(reach)
|
||||||
self.plot_ac.set_reach(reach)
|
self.plot_ac.set_reach(reach)
|
||||||
|
|
||||||
profile_rk = self._hs_lst.get(rows[0]).input_rk
|
profile_kp = self._hs_lst.get(rows[0]).input_kp
|
||||||
if profile_rk is not None:
|
if profile_kp is not None:
|
||||||
profiles = reach.reach\
|
profiles = reach.reach\
|
||||||
.get_profiles_from_rk(
|
.get_profiles_from_kp(
|
||||||
float(profile_rk)
|
float(profile_kp)
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(profiles) != 0 and profiles is not None:
|
if len(profiles) != 0 and profiles is not None:
|
||||||
profile = profiles[0]
|
profile = profiles[0]
|
||||||
|
|
||||||
self.plot_rkc.set_profile(profile)
|
self.plot_kpc.set_profile(profile)
|
||||||
self.plot_ac.set_profile(profile)
|
self.plot_ac.set_profile(profile)
|
||||||
else:
|
else:
|
||||||
self._update_clear_profile()
|
self._update_clear_profile()
|
||||||
@@ -308,9 +308,9 @@ class HydraulicStructuresWindow(PamhyrWindow):
|
|||||||
self._update_clear_all()
|
self._update_clear_all()
|
||||||
|
|
||||||
def _update_clear_all(self):
|
def _update_clear_all(self):
|
||||||
self.plot_rkc.clear()
|
self.plot_kpc.clear()
|
||||||
self.plot_ac.clear()
|
self.plot_ac.clear()
|
||||||
|
|
||||||
def _update_clear_profile(self):
|
def _update_clear_profile(self):
|
||||||
self.plot_ac.clear()
|
self.plot_ac.clear()
|
||||||
self.plot_rkc.clear_profile()
|
self.plot_kpc.clear_profile()
|
||||||
@@ -28,7 +28,7 @@ from PyQt5.QtCore import (
|
|||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
|
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
|
||||||
QDoubleSpinBox, QCheckBox,
|
QDoubleSpinBox,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -45,11 +45,9 @@ class DischargeDialog(PamhyrDialog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.value = None
|
self.value = None
|
||||||
self.option = None
|
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
self.value = self.find(QDoubleSpinBox, "doubleSpinBox").value()
|
self.value = self.find(QDoubleSpinBox, "doubleSpinBox").value()
|
||||||
self.option = self.find(QCheckBox, "checkBox").isChecked()
|
|
||||||
super().accept()
|
super().accept()
|
||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ from PyQt5.QtCore import (
|
|||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
|
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
|
||||||
QDoubleSpinBox, QCheckBox,
|
QDoubleSpinBox,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -45,11 +45,9 @@ class HeightDialog(PamhyrDialog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.value = None
|
self.value = None
|
||||||
self.option = None
|
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
self.value = self.find(QDoubleSpinBox, "doubleSpinBox").value()
|
self.value = self.find(QDoubleSpinBox, "doubleSpinBox").value()
|
||||||
self.option = self.find(QCheckBox, "checkBox").isChecked()
|
|
||||||
super().accept()
|
super().accept()
|
||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# PlotDRK.py -- Pamhyr
|
# PlotDKP.py -- Pamhyr
|
||||||
# Copyright (C) 2023-2024 INRAE
|
# Copyright (C) 2023-2024 INRAE
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
@@ -30,10 +30,10 @@ logger = logging.getLogger()
|
|||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
class PlotDRK(PamhyrPlot):
|
class PlotDKP(PamhyrPlot):
|
||||||
def __init__(self, canvas=None, trad=None, toolbar=None,
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
data=None, parent=None):
|
data=None, parent=None):
|
||||||
super(PlotDRK, self).__init__(
|
super(PlotDKP, self).__init__(
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
trad=trad,
|
trad=trad,
|
||||||
data=data,
|
data=data,
|
||||||
@@ -41,7 +41,7 @@ class PlotDRK(PamhyrPlot):
|
|||||||
parent=parent
|
parent=parent
|
||||||
)
|
)
|
||||||
|
|
||||||
self.label_x = self._trad["rk"]
|
self.label_x = self._trad["kp"]
|
||||||
self.label_y = self._trad["elevation"]
|
self.label_y = self._trad["elevation"]
|
||||||
|
|
||||||
self._isometric_axis = False
|
self._isometric_axis = False
|
||||||
@@ -63,41 +63,41 @@ class PlotDRK(PamhyrPlot):
|
|||||||
self._init = True
|
self._init = True
|
||||||
|
|
||||||
def draw_river_bottom(self):
|
def draw_river_bottom(self):
|
||||||
rk = self.data.reach.reach.get_rk()
|
kp = self.data.reach.reach.get_kp()
|
||||||
z_min = self.data.reach.reach.get_z_min()
|
z_min = self.data.reach.reach.get_z_min()
|
||||||
|
|
||||||
self.line_rk_zmin = self.canvas.axes.plot(
|
self.line_kp_zmin = self.canvas.axes.plot(
|
||||||
rk, z_min,
|
kp, z_min,
|
||||||
color=self.color_plot_river_bottom,
|
color=self.color_plot_river_bottom,
|
||||||
lw=1.
|
lw=1.
|
||||||
)
|
)
|
||||||
|
|
||||||
def draw_water(self):
|
def draw_water(self):
|
||||||
if len(self.data) != 0:
|
if len(self.data) != 0:
|
||||||
rk = self.data.get_rk()
|
kp = self.data.get_kp()
|
||||||
elevation = self.data.get_elevation()
|
elevation = self.data.get_elevation()
|
||||||
|
|
||||||
self.line_rk_elevation = self.canvas.axes.plot(
|
self.line_kp_elevation = self.canvas.axes.plot(
|
||||||
rk, elevation,
|
kp, elevation,
|
||||||
color=self.color_plot_river_water,
|
color=self.color_plot_river_water,
|
||||||
**self.plot_default_kargs
|
**self.plot_default_kargs
|
||||||
)
|
)
|
||||||
|
|
||||||
z_min = self.data.reach.reach.get_z_min()
|
z_min = self.data.reach.reach.get_z_min()
|
||||||
geometry_rk = self.data.reach.reach.get_rk()
|
geometry_kp = self.data.reach.reach.get_kp()
|
||||||
|
|
||||||
filtred_elevation = list(
|
filtred_elevation = list(
|
||||||
map(
|
map(
|
||||||
lambda x: elevation[x[0]],
|
lambda x: elevation[x[0]],
|
||||||
filter(
|
filter(
|
||||||
lambda x: x[1] in geometry_rk,
|
lambda x: x[1] in geometry_kp,
|
||||||
enumerate(rk)
|
enumerate(kp)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.collection = self.canvas.axes.fill_between(
|
self.collection = self.canvas.axes.fill_between(
|
||||||
geometry_rk, z_min, filtred_elevation,
|
geometry_kp, z_min, filtred_elevation,
|
||||||
color=self.color_plot_river_water_zone,
|
color=self.color_plot_river_water_zone,
|
||||||
alpha=0.7, interpolate=True
|
alpha=0.7, interpolate=True
|
||||||
)
|
)
|
||||||
@@ -31,7 +31,7 @@ class PlotDischarge(PamhyrPlot):
|
|||||||
parent=parent
|
parent=parent
|
||||||
)
|
)
|
||||||
|
|
||||||
self.label_x = self._trad["rk"]
|
self.label_x = self._trad["kp"]
|
||||||
self.label_y = self._trad["discharge"]
|
self.label_y = self._trad["discharge"]
|
||||||
|
|
||||||
self._isometric_axis = False
|
self._isometric_axis = False
|
||||||
@@ -55,11 +55,11 @@ class PlotDischarge(PamhyrPlot):
|
|||||||
self.line_discharge = []
|
self.line_discharge = []
|
||||||
|
|
||||||
if len(self.data) != 0:
|
if len(self.data) != 0:
|
||||||
rk = self.data.get_rk()
|
kp = self.data.get_kp()
|
||||||
discharge = self.data.get_discharge()
|
discharge = self.data.get_discharge()
|
||||||
|
|
||||||
line, = self.canvas.axes.plot(
|
line, = self.canvas.axes.plot(
|
||||||
rk, discharge,
|
kp, discharge,
|
||||||
color=self.color_plot,
|
color=self.color_plot,
|
||||||
**self.plot_default_kargs
|
**self.plot_default_kargs
|
||||||
)
|
)
|
||||||
@@ -76,11 +76,11 @@ class PlotDischarge(PamhyrPlot):
|
|||||||
|
|
||||||
def update_data(self):
|
def update_data(self):
|
||||||
if len(self.data) == len(self.line_discharge):
|
if len(self.data) == len(self.line_discharge):
|
||||||
rk = self.data.get_rk()
|
kp = self.data.get_kp()
|
||||||
discharge = self.data.get_discharge()
|
discharge = self.data.get_discharge()
|
||||||
|
|
||||||
line, = self.canvas.axes.plot(
|
line, = self.canvas.axes.plot(
|
||||||
rk, discharge,
|
kp, discharge,
|
||||||
color=self.color_plot,
|
color=self.color_plot,
|
||||||
**self.plot_default_kargs
|
**self.plot_default_kargs
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class ComboBoxDelegate(QItemDelegate):
|
|||||||
list(
|
list(
|
||||||
map(
|
map(
|
||||||
str,
|
str,
|
||||||
self._reach.get_rk()
|
self._reach.get_kp()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -107,8 +107,8 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||||||
if self._headers[column] is "speed":
|
if self._headers[column] is "speed":
|
||||||
z = self._lst.get(row)["elevation"]
|
z = self._lst.get(row)["elevation"]
|
||||||
q = self._lst.get(row)["discharge"]
|
q = self._lst.get(row)["discharge"]
|
||||||
profile = self._reach.reach.get_profiles_from_rk(
|
profile = self._reach.reach.get_profiles_from_kp(
|
||||||
self._lst.get(row)["rk"]
|
self._lst.get(row)["kp"]
|
||||||
)
|
)
|
||||||
if len(profile) >= 1:
|
if len(profile) >= 1:
|
||||||
speed = profile[0].speed(q, z)
|
speed = profile[0].speed(q, z)
|
||||||
@@ -258,7 +258,7 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||||||
data = list(
|
data = list(
|
||||||
map(
|
map(
|
||||||
lambda p: [
|
lambda p: [
|
||||||
p.geometry.rk,
|
p.geometry.kp,
|
||||||
p.get_ts_key(ts, "Q"),
|
p.get_ts_key(ts, "Q"),
|
||||||
p.get_ts_key(ts, "Z"),
|
p.get_ts_key(ts, "Z"),
|
||||||
],
|
],
|
||||||
@@ -289,10 +289,10 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||||||
self._undo.redo()
|
self._undo.redo()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
def generate(self, generator, param, option):
|
def generate(self, generator, param):
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
GenerateCommand(
|
GenerateCommand(
|
||||||
self._lst, generator, param, option
|
self._lst, generator, param
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
@@ -106,7 +106,7 @@ class SortCommand(QUndoCommand):
|
|||||||
def redo(self):
|
def redo(self):
|
||||||
self._ics.sort(
|
self._ics.sort(
|
||||||
reverse=self._reverse,
|
reverse=self._reverse,
|
||||||
key=lambda x: x["rk"]
|
key=lambda x: x["kp"]
|
||||||
)
|
)
|
||||||
if self._indexes is None:
|
if self._indexes is None:
|
||||||
self._indexes = list(
|
self._indexes = list(
|
||||||
@@ -138,7 +138,6 @@ class MoveCommand(QUndoCommand):
|
|||||||
else:
|
else:
|
||||||
self._ics.move_down(self._i)
|
self._ics.move_down(self._i)
|
||||||
|
|
||||||
|
|
||||||
class InsertCommand(QUndoCommand):
|
class InsertCommand(QUndoCommand):
|
||||||
def __init__(self, ics, row, ic):
|
def __init__(self, ics, row, ic):
|
||||||
QUndoCommand.__init__(self)
|
QUndoCommand.__init__(self)
|
||||||
@@ -155,7 +154,6 @@ class InsertCommand(QUndoCommand):
|
|||||||
for ic in self._ic:
|
for ic in self._ic:
|
||||||
self._ics.insert(self._row, ic)
|
self._ics.insert(self._row, ic)
|
||||||
|
|
||||||
|
|
||||||
class DuplicateCommand(QUndoCommand):
|
class DuplicateCommand(QUndoCommand):
|
||||||
def __init__(self, ics, rows, ic):
|
def __init__(self, ics, rows, ic):
|
||||||
QUndoCommand.__init__(self)
|
QUndoCommand.__init__(self)
|
||||||
@@ -174,12 +172,11 @@ class DuplicateCommand(QUndoCommand):
|
|||||||
|
|
||||||
|
|
||||||
class GenerateCommand(QUndoCommand):
|
class GenerateCommand(QUndoCommand):
|
||||||
def __init__(self, ics, generator, param, option):
|
def __init__(self, ics, generator, param):
|
||||||
QUndoCommand.__init__(self)
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
self._ics = ics
|
self._ics = ics
|
||||||
self._param = param
|
self._param = param
|
||||||
self._option = option
|
|
||||||
self._copy = self._ics.data
|
self._copy = self._ics.data
|
||||||
self._generator = generator
|
self._generator = generator
|
||||||
|
|
||||||
@@ -188,8 +185,6 @@ class GenerateCommand(QUndoCommand):
|
|||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
if self._generator == "growing":
|
if self._generator == "growing":
|
||||||
self._ics.generate_growing_constante_height(self._param,
|
self._ics.generate_growing_constante_height(self._param)
|
||||||
self._option)
|
|
||||||
elif self._generator == "discharge":
|
elif self._generator == "discharge":
|
||||||
self._ics.generate_discharge(self._param,
|
self._ics.generate_discharge(self._param)
|
||||||
self._option)
|
|
||||||
@@ -55,7 +55,7 @@ from View.InitialConditions.Table import (
|
|||||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||||
|
|
||||||
from View.InitialConditions.PlotDRK import PlotDRK
|
from View.InitialConditions.PlotDKP import PlotDKP
|
||||||
from View.InitialConditions.PlotDischarge import PlotDischarge
|
from View.InitialConditions.PlotDischarge import PlotDischarge
|
||||||
from View.InitialConditions.translate import ICTranslate
|
from View.InitialConditions.translate import ICTranslate
|
||||||
from View.InitialConditions.DialogHeight import HeightDialog
|
from View.InitialConditions.DialogHeight import HeightDialog
|
||||||
@@ -108,7 +108,7 @@ class InitialConditionsWindow(PamhyrWindow):
|
|||||||
|
|
||||||
def setup_table(self):
|
def setup_table(self):
|
||||||
table = self.find(QTableView, f"tableView")
|
table = self.find(QTableView, f"tableView")
|
||||||
self._delegate_rk = ComboBoxDelegate(
|
self._delegate_kp = ComboBoxDelegate(
|
||||||
reach=self._reach,
|
reach=self._reach,
|
||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
@@ -117,8 +117,8 @@ class InitialConditionsWindow(PamhyrWindow):
|
|||||||
reach=self._reach,
|
reach=self._reach,
|
||||||
table_view=table,
|
table_view=table,
|
||||||
table_headers=self._trad.get_dict("table_headers"),
|
table_headers=self._trad.get_dict("table_headers"),
|
||||||
editable_headers=["rk", "discharge", "elevation", "height"],
|
editable_headers=["kp", "discharge", "elevation", "height"],
|
||||||
delegates={"rk": self._delegate_rk},
|
delegates={"kp": self._delegate_kp},
|
||||||
data=self._study,
|
data=self._study,
|
||||||
undo=self._undo_stack,
|
undo=self._undo_stack,
|
||||||
trad=self._trad
|
trad=self._trad
|
||||||
@@ -139,7 +139,7 @@ class InitialConditionsWindow(PamhyrWindow):
|
|||||||
self.plot_layout_1.addWidget(self.toolbar_1)
|
self.plot_layout_1.addWidget(self.toolbar_1)
|
||||||
self.plot_layout_1.addWidget(self.canvas_1)
|
self.plot_layout_1.addWidget(self.canvas_1)
|
||||||
|
|
||||||
self.plot_1 = PlotDRK(
|
self.plot_1 = PlotDKP(
|
||||||
canvas=self.canvas_1,
|
canvas=self.canvas_1,
|
||||||
data=self._ics,
|
data=self._ics,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
@@ -304,7 +304,7 @@ class InitialConditionsWindow(PamhyrWindow):
|
|||||||
lambda eic: list(
|
lambda eic: list(
|
||||||
map(
|
map(
|
||||||
lambda k: eic[1][k],
|
lambda k: eic[1][k],
|
||||||
["rk", "discharge", "elevation"]
|
["kp", "discharge", "elevation"]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
filter(
|
filter(
|
||||||
@@ -349,14 +349,12 @@ class InitialConditionsWindow(PamhyrWindow):
|
|||||||
dlg = HeightDialog(trad=self._trad, parent=self)
|
dlg = HeightDialog(trad=self._trad, parent=self)
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
value = dlg.value
|
value = dlg.value
|
||||||
compute_discharge = dlg.option
|
self._table.generate("growing", value)
|
||||||
self._table.generate("growing", value, compute_discharge)
|
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
def generate_discharge(self):
|
def generate_discharge(self):
|
||||||
dlg = DischargeDialog(trad=self._trad, parent=self)
|
dlg = DischargeDialog(trad=self._trad, parent=self)
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
value = dlg.value
|
value = dlg.value
|
||||||
compute_height = dlg.option
|
self._table.generate("discharge", value)
|
||||||
self._table.generate("discharge", value, compute_height)
|
|
||||||
self._update()
|
self._update()
|
||||||
@@ -36,11 +36,11 @@ class ICTranslate(MainTranslate):
|
|||||||
|
|
||||||
self._dict["elevation"] = self._dict["unit_elevation"]
|
self._dict["elevation"] = self._dict["unit_elevation"]
|
||||||
self._dict["discharge"] = self._dict["unit_discharge"]
|
self._dict["discharge"] = self._dict["unit_discharge"]
|
||||||
self._dict["rk"] = self._dict["unit_rk"]
|
self._dict["kp"] = self._dict["unit_kp"]
|
||||||
|
|
||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
# "name": _translate("InitialCondition", "Name"),
|
# "name": _translate("InitialCondition", "Name"),
|
||||||
"rk": self._dict["unit_rk"],
|
"kp": self._dict["unit_kp"],
|
||||||
"discharge": self._dict["unit_discharge"],
|
"discharge": self._dict["unit_discharge"],
|
||||||
"elevation": self._dict["unit_elevation"],
|
"elevation": self._dict["unit_elevation"],
|
||||||
"height": self._dict["unit_height"],
|
"height": self._dict["unit_height"],
|
||||||
|
|||||||
@@ -0,0 +1,237 @@
|
|||||||
|
# Table.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from View.InitialConditionsAdisTS.UndoCommand import (
|
||||||
|
SetCommand, AddCommand, SetCommandSpec,
|
||||||
|
DelCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class ComboBoxDelegate(QItemDelegate):
|
||||||
|
def __init__(self, data=None, ic_spec_lst=None, trad=None, parent=None, mode="reaches"):
|
||||||
|
super(ComboBoxDelegate, self).__init__(parent)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._mode = mode
|
||||||
|
self._trad = trad
|
||||||
|
self._ic_spec_lst = ic_spec_lst
|
||||||
|
|
||||||
|
def createEditor(self, parent, option, index):
|
||||||
|
self.editor = QComboBox(parent)
|
||||||
|
|
||||||
|
val = []
|
||||||
|
if self._mode == "kp":
|
||||||
|
reach_id = self._ic_spec_lst[index.row()].reach
|
||||||
|
|
||||||
|
reach = next(filter(lambda edge: edge.id == reach_id, self._data.edges()))
|
||||||
|
|
||||||
|
if reach_id is not None:
|
||||||
|
val = list(
|
||||||
|
map(
|
||||||
|
lambda kp: str(kp), reach.reach.get_kp()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
val = list(
|
||||||
|
map(
|
||||||
|
lambda n: n.name, self._data.edges()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.editor.addItems(
|
||||||
|
[self._trad['not_associated']] +
|
||||||
|
val
|
||||||
|
)
|
||||||
|
|
||||||
|
self.editor.setCurrentText(str(index.data(Qt.DisplayRole)))
|
||||||
|
return self.editor
|
||||||
|
|
||||||
|
def setEditorData(self, editor, index):
|
||||||
|
value = index.data(Qt.DisplayRole)
|
||||||
|
self.editor.currentTextChanged.connect(self.currentItemChanged)
|
||||||
|
|
||||||
|
def setModelData(self, editor, model, index):
|
||||||
|
text = str(editor.currentText())
|
||||||
|
model.setData(index, text)
|
||||||
|
editor.close()
|
||||||
|
editor.deleteLater()
|
||||||
|
|
||||||
|
def updateEditorGeometry(self, editor, option, index):
|
||||||
|
r = QRect(option.rect)
|
||||||
|
if self.editor.windowFlags() & Qt.Popup:
|
||||||
|
if editor.parent() is not None:
|
||||||
|
r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
|
||||||
|
editor.setGeometry(r)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def currentItemChanged(self):
|
||||||
|
self.commitData.emit(self.sender())
|
||||||
|
|
||||||
|
|
||||||
|
class InitialConditionTableModel(PamhyrTableModel):
|
||||||
|
def __init__(self, river=None, data=None, **kwargs):
|
||||||
|
self._river = river
|
||||||
|
|
||||||
|
super(InitialConditionTableModel, self).__init__(data=data, **kwargs)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
|
||||||
|
def _setup_lst(self):
|
||||||
|
self._lst = self._data._data
|
||||||
|
|
||||||
|
def rowCount(self, parent):
|
||||||
|
return len(self._lst)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._headers[column] is "name":
|
||||||
|
n = self._lst[row].name
|
||||||
|
if n is None or n == "":
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "reach":
|
||||||
|
n = self._lst[row].reach
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return next(filter(lambda edge: edge.id == n, self._river.edges())).name
|
||||||
|
elif self._headers[column] is "start_kp":
|
||||||
|
n = self._lst[row].start_kp
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "end_kp":
|
||||||
|
n = self._lst[row].end_kp
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "concentration":
|
||||||
|
n = self._lst[row].concentration
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "eg":
|
||||||
|
n = self._lst[row].eg
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "em":
|
||||||
|
n = self._lst[row].em
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "ed":
|
||||||
|
n = self._lst[row].ed
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "rate":
|
||||||
|
n = self._lst[row].rate
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._headers[column] != "reach":
|
||||||
|
self._undo.push(
|
||||||
|
SetCommandSpec(
|
||||||
|
self._lst, row, self._headers[column], value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif self._headers[column] == "reach":
|
||||||
|
print(self._river.edge(value).id)
|
||||||
|
self._undo.push(
|
||||||
|
SetCommandSpec(
|
||||||
|
self._lst, row, self._headers[column], self._river.edge(value).id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def add(self, row, parent=QModelIndex()):
|
||||||
|
self.beginInsertRows(parent, row, row - 1)
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
AddCommand(
|
||||||
|
self._data, self._lst, row
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endInsertRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def delete(self, rows, parent=QModelIndex()):
|
||||||
|
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
DelCommand(
|
||||||
|
self._data, self._lst, rows
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endRemoveRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._undo.undo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._undo.redo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
# Table.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 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from View.InitialConditionsAdisTS.UndoCommand import (
|
||||||
|
SetCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
class InitialConditionTableDefaultModel(PamhyrTableModel):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(InitialConditionTableDefaultModel, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._headers[column] is "name":
|
||||||
|
return self._data[row].name
|
||||||
|
elif self._headers[column] is "concentration":
|
||||||
|
n = self._data[row].concentration
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "eg":
|
||||||
|
n = self._data[row].eg
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "em":
|
||||||
|
n = self._data[row].em
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "ed":
|
||||||
|
n = self._data[row].ed
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._headers[column] is not None:
|
||||||
|
self._undo.push(
|
||||||
|
SetCommand(
|
||||||
|
self._data, row, self._headers[column], value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._undo.undo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._undo.redo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
# UndoCommand.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 copy import deepcopy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QMessageBox, QUndoCommand, QUndoStack,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.InitialConditionsAdisTS.InitialConditionsAdisTS import InitialConditionsAdisTS
|
||||||
|
from Model.InitialConditionsAdisTS.InitialConditionsAdisTSList import InitialConditionsAdisTSList
|
||||||
|
|
||||||
|
|
||||||
|
class SetCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, row, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._column = column
|
||||||
|
|
||||||
|
if self._column == "name":
|
||||||
|
self._old = self._data[self._row].name
|
||||||
|
elif self._column == "concentration":
|
||||||
|
self._old = self._data[self._row].concentration
|
||||||
|
elif self._column == "eg":
|
||||||
|
self._old = self._data[self._row].eg
|
||||||
|
elif self._column == "em":
|
||||||
|
self._old = self._data[self._row].em
|
||||||
|
elif self._column == "ed":
|
||||||
|
self._old = self._data[self._row].ed
|
||||||
|
|
||||||
|
_type = float
|
||||||
|
if column == "name":
|
||||||
|
_type = str
|
||||||
|
|
||||||
|
self._new = _type(new_value)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._old
|
||||||
|
elif self._column == "concentration":
|
||||||
|
self._data[self._row].concentration = self._old
|
||||||
|
elif self._column == "eg":
|
||||||
|
self._data[self._row].eg = self._old
|
||||||
|
elif self._column == "em":
|
||||||
|
self._data[self._row].em = self._old
|
||||||
|
elif self._column == "ed":
|
||||||
|
self._data[self._row].ed = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._new
|
||||||
|
elif self._column == "concentration":
|
||||||
|
self._data[self._row].concentration = self._new
|
||||||
|
elif self._column == "eg":
|
||||||
|
self._data[self._row].eg = self._new
|
||||||
|
elif self._column == "em":
|
||||||
|
self._data[self._row].em = self._new
|
||||||
|
elif self._column == "ed":
|
||||||
|
self._data[self._row].ed = self._new
|
||||||
|
|
||||||
|
class SetCommandSpec(QUndoCommand):
|
||||||
|
def __init__(self, data, row, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._column = column
|
||||||
|
|
||||||
|
if self._column == "name":
|
||||||
|
self._old = self._data[self._row].name
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._old = self._data[self._row].reach
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._old = self._data[self._row].start_kp
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._old = self._data[self._row].end_kp
|
||||||
|
elif self._column == "concentration":
|
||||||
|
self._old = self._data[self._row].concentration
|
||||||
|
elif self._column == "eg":
|
||||||
|
self._old = self._data[self._row].eg
|
||||||
|
elif self._column == "em":
|
||||||
|
self._old = self._data[self._row].em
|
||||||
|
elif self._column == "ed":
|
||||||
|
self._old = self._data[self._row].ed
|
||||||
|
elif self._column == "rate":
|
||||||
|
self._old = self._data[self._row].rate
|
||||||
|
|
||||||
|
_type = float
|
||||||
|
if column == "name":
|
||||||
|
_type = str
|
||||||
|
elif column == "reach":
|
||||||
|
_type = int
|
||||||
|
|
||||||
|
self._new = _type(new_value)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._old
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._data[self._row].reach = self._old
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._data[self._row].start_kp = self._old
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._data[self._row].end_kp = self._old
|
||||||
|
elif self._column == "concentration":
|
||||||
|
self._data[self._row].concentration = self._old
|
||||||
|
elif self._column == "eg":
|
||||||
|
self._data[self._row].eg = self._old
|
||||||
|
elif self._column == "em":
|
||||||
|
self._data[self._row].em = self._old
|
||||||
|
elif self._column == "ed":
|
||||||
|
self._data[self._row].ed = self._old
|
||||||
|
elif self._column == "rate":
|
||||||
|
self._data[self._row].rate = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._new
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._data[self._row].reach = self._new
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._data[self._row].start_kp = self._new
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._data[self._row].end_kp = self._new
|
||||||
|
elif self._column == "concentration":
|
||||||
|
self._data[self._row].concentration = self._new
|
||||||
|
elif self._column == "eg":
|
||||||
|
self._data[self._row].eg = self._new
|
||||||
|
elif self._column == "em":
|
||||||
|
self._data[self._row].em = self._new
|
||||||
|
elif self._column == "ed":
|
||||||
|
self._data[self._row].ed = self._new
|
||||||
|
elif self._column == "rate":
|
||||||
|
self._data[self._row].rate = self._new
|
||||||
|
|
||||||
|
class AddCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, ics_spec, index):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._ics_spec = ics_spec
|
||||||
|
self._index = index
|
||||||
|
self._new = None
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._data.delete_i([self._index])
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._new is None:
|
||||||
|
self._new = self._data.new(self._index)
|
||||||
|
else:
|
||||||
|
self._data.insert(self._index, self._new)
|
||||||
|
|
||||||
|
class DelCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, ics_spec, rows):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._ics_spec = ics_spec
|
||||||
|
self._rows = rows
|
||||||
|
#self._data = data
|
||||||
|
|
||||||
|
self._ic = []
|
||||||
|
for row in rows:
|
||||||
|
self._ic.append((row, self._ics_spec[row]))
|
||||||
|
self._ic.sort()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
for row, el in self._ic:
|
||||||
|
self._data.insert(row, el)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._data.delete_i(self._rows)
|
||||||
|
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
# Window.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 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import trace, timer, logger_exception
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence, QIcon,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect, QItemSelectionModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
|
QVBoxLayout, QToolBar, QAction, QToolButton,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Modules import Modules
|
||||||
|
|
||||||
|
from View.InitialConditionsAdisTS.UndoCommand import (
|
||||||
|
SetCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.InitialConditionsAdisTS.TableDefault import (
|
||||||
|
InitialConditionTableDefaultModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.InitialConditionsAdisTS.Table import (
|
||||||
|
InitialConditionTableModel, ComboBoxDelegate,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.InitialConditionsAdisTS.translate import IcAdisTSTranslate
|
||||||
|
|
||||||
|
from Solver.Mage import Mage8
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class InitialConditionsAdisTSWindow(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "InitialConditionsAdisTS"
|
||||||
|
_pamhyr_name = "Initial condition AdisTS"
|
||||||
|
|
||||||
|
def __init__(self, data=None, study=None, config=None, parent=None):
|
||||||
|
self._data = []
|
||||||
|
self._data.append(data)
|
||||||
|
trad = IcAdisTSTranslate()
|
||||||
|
|
||||||
|
name = (
|
||||||
|
trad[self._pamhyr_name] +
|
||||||
|
" - " + study.name +
|
||||||
|
" - " + self._data[0].name
|
||||||
|
)
|
||||||
|
|
||||||
|
super(InitialConditionsAdisTSWindow, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._hash_data.append(data)
|
||||||
|
|
||||||
|
self._ics_adists_lst = study.river.initial_conditions_adists
|
||||||
|
|
||||||
|
self.setup_table()
|
||||||
|
|
||||||
|
self.ui.setWindowTitle(self._title)
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
|
||||||
|
path_icons = os.path.join(self._get_ui_directory(), f"ressources")
|
||||||
|
|
||||||
|
table_default = self.find(QTableView, f"tableView")
|
||||||
|
|
||||||
|
self._table = InitialConditionTableDefaultModel(
|
||||||
|
table_view=table_default,
|
||||||
|
table_headers=self._trad.get_dict("table_headers"),
|
||||||
|
editable_headers=["name", "concentration", "eg", "em", "ed"],
|
||||||
|
delegates={},
|
||||||
|
data=self._data,
|
||||||
|
undo=self._undo_stack,
|
||||||
|
trad=self._trad
|
||||||
|
)
|
||||||
|
|
||||||
|
table_default.setModel(self._table)
|
||||||
|
table_default.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
table_default.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
table_default.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
layout = self.find(QVBoxLayout, f"verticalLayout_1")
|
||||||
|
toolBar = QToolBar()
|
||||||
|
layout.addWidget(toolBar)
|
||||||
|
|
||||||
|
action_add = QAction(self)
|
||||||
|
action_add.setIcon(QIcon(os.path.join(path_icons, f"add.png")))
|
||||||
|
action_add.triggered.connect(self.add)
|
||||||
|
action_delete = QAction(self)
|
||||||
|
action_delete.setIcon(QIcon(os.path.join(path_icons, f"del.png")))
|
||||||
|
action_delete.triggered.connect(self.delete)
|
||||||
|
|
||||||
|
toolBar.addAction(action_add)
|
||||||
|
toolBar.addAction(action_delete)
|
||||||
|
|
||||||
|
self.table_spec = QTableView()
|
||||||
|
layout.addWidget(self.table_spec)
|
||||||
|
|
||||||
|
self._delegate_reach = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
ic_spec_lst=self._data[0]._data,
|
||||||
|
parent=self,
|
||||||
|
mode="reaches"
|
||||||
|
)
|
||||||
|
self._delegate_kp = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
ic_spec_lst=self._data[0]._data,
|
||||||
|
parent=self,
|
||||||
|
mode="kp"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._table_spec = InitialConditionTableModel(
|
||||||
|
table_view=self.table_spec,
|
||||||
|
table_headers=self._trad.get_dict("table_headers_spec"),
|
||||||
|
editable_headers=["name", "reach", "start_kp", "end_kp", "concentration", "eg", "em", "ed", "rate"],
|
||||||
|
delegates={
|
||||||
|
"reach": self._delegate_reach,
|
||||||
|
"start_kp": self._delegate_kp,
|
||||||
|
"end_kp": self._delegate_kp
|
||||||
|
},
|
||||||
|
data=self._data[0],
|
||||||
|
undo=self._undo_stack,
|
||||||
|
trad=self._trad,
|
||||||
|
river=self._study.river
|
||||||
|
)
|
||||||
|
|
||||||
|
self.table_spec.setModel(self._table_spec)
|
||||||
|
self.table_spec.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
self.table_spec.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
self.table_spec.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
selectionModel = self.table_spec.selectionModel()
|
||||||
|
index = self.table_spec.model().index(0, 0)
|
||||||
|
|
||||||
|
selectionModel.select(
|
||||||
|
index,
|
||||||
|
QItemSelectionModel.Rows |
|
||||||
|
QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Select
|
||||||
|
)
|
||||||
|
self.table_spec.scrollTo(index)
|
||||||
|
|
||||||
|
def index_selected_row(self):
|
||||||
|
#table = self.find(QTableView, f"tableView")
|
||||||
|
table = self.table_spec
|
||||||
|
rows = table.selectionModel()\
|
||||||
|
.selectedRows()
|
||||||
|
|
||||||
|
if len(rows) == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return rows[0].row()
|
||||||
|
|
||||||
|
def index_selected_rows(self):
|
||||||
|
#table = self.find(QTableView, f"tableView")
|
||||||
|
table = self.table_spec
|
||||||
|
return list(
|
||||||
|
# Delete duplicate
|
||||||
|
set(
|
||||||
|
map(
|
||||||
|
lambda i: i.row(),
|
||||||
|
table.selectedIndexes()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def move_up(self):
|
||||||
|
row = self.index_selected_row()
|
||||||
|
self._table.move_up(row)
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def move_down(self):
|
||||||
|
row = self.index_selected_row()
|
||||||
|
self._table.move_down(row)
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
rows = list(
|
||||||
|
map(
|
||||||
|
lambda row: row.row(),
|
||||||
|
self.tableView.selectionModel().selectedRows()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
table = list(
|
||||||
|
map(
|
||||||
|
lambda eic: list(
|
||||||
|
map(
|
||||||
|
lambda k: eic[1][k],
|
||||||
|
["kp", "discharge", "elevation"]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
filter(
|
||||||
|
lambda eic: eic[0] in rows,
|
||||||
|
enumerate(self._ics.lst())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.copyTableIntoClipboard(table)
|
||||||
|
|
||||||
|
def _paste(self):
|
||||||
|
header, data = self.parseClipboardTable()
|
||||||
|
|
||||||
|
if len(data) + len(header) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
"IC: Paste: " +
|
||||||
|
f"header = {header}, " +
|
||||||
|
f"data = {data}"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
row = self.index_selected_row()
|
||||||
|
# self._table.paste(row, header, data)
|
||||||
|
self._table.paste(row, [], data)
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _undo(self):
|
||||||
|
self._table.undo()
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _redo(self):
|
||||||
|
self._table.redo()
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(self._data[0]._data) == 0 or len(rows) == 0:
|
||||||
|
self._table_spec.add(0)
|
||||||
|
else:
|
||||||
|
self._table_spec.add(rows[0])
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
print("del")
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(rows) == 0:
|
||||||
|
print("len 0")
|
||||||
|
return
|
||||||
|
self._table_spec.delete(rows)
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# translate.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 PyQt5.QtCore import QCoreApplication
|
||||||
|
|
||||||
|
from View.Translate import MainTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class IcAdisTSTranslate(MainTranslate):
|
||||||
|
def __init__(self):
|
||||||
|
super(IcAdisTSTranslate, self).__init__()
|
||||||
|
|
||||||
|
self._dict["Initial condition AdisTS"] = _translate(
|
||||||
|
"InitialConditionAdisTS", "Initial condition AdisTS")
|
||||||
|
|
||||||
|
self._dict["kp"] = self._dict["unit_kp"]
|
||||||
|
|
||||||
|
self._sub_dict["table_headers"] = {
|
||||||
|
"name": self._dict["name"],
|
||||||
|
"concentration": self._dict["unit_concentration"],
|
||||||
|
"eg": _translate("Unit", "EG (m)"),
|
||||||
|
"em": _translate("Unit", "EM (m)"),
|
||||||
|
"ed": _translate("Unit", "ED (m)"),
|
||||||
|
}
|
||||||
|
|
||||||
|
self._sub_dict["table_headers_spec"] = {
|
||||||
|
"name": self._dict["name"],
|
||||||
|
"reach": self._dict["reach"],
|
||||||
|
"start_kp": _translate("Unit", "Start_KP (m)"),
|
||||||
|
"end_kp": _translate("Unit", "End_KP (m)"),
|
||||||
|
"concentration": self._dict["unit_concentration"],
|
||||||
|
"eg": _translate("Unit", "EG (m)"),
|
||||||
|
"em": _translate("Unit", "EM (m)"),
|
||||||
|
"ed": _translate("Unit", "ED (m)"),
|
||||||
|
"rate": _translate("Unit", "Rate"),
|
||||||
|
}
|
||||||
@@ -68,12 +68,12 @@ class PlotXY(PamhyrPlot):
|
|||||||
tableView = self.parent.find(QTableView, f"tableView_{t}")
|
tableView = self.parent.find(QTableView, f"tableView_{t}")
|
||||||
table = self.parent._table[t]
|
table = self.parent._table[t]
|
||||||
index = tableView.selectedIndexes()
|
index = tableView.selectedIndexes()
|
||||||
rk = self.data.get_rk()
|
kp = self.data.get_kp()
|
||||||
if self.parent._table is not None:
|
if self.parent._table is not None:
|
||||||
if event.mouseevent.button.value == 1:
|
if event.mouseevent.button.value == 1:
|
||||||
table.setData(index[3], rk[closest[0]])
|
table.setData(index[3], kp[closest[0]])
|
||||||
if event.mouseevent.button.value == 3:
|
if event.mouseevent.button.value == 3:
|
||||||
table.setData(index[4], rk[closest[0]])
|
table.setData(index[4], kp[closest[0]])
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -137,13 +137,13 @@ class PlotXY(PamhyrPlot):
|
|||||||
self.canvas.axes.add_collection(self.line_xy_collection)
|
self.canvas.axes.add_collection(self.line_xy_collection)
|
||||||
|
|
||||||
def color_hightlight(self):
|
def color_hightlight(self):
|
||||||
rk_min, rk_max = (-1, -1)
|
kp_min, kp_max = (-1, -1)
|
||||||
if self._highlight_data is not None:
|
if self._highlight_data is not None:
|
||||||
rk_min, rk_max = self._highlight_data
|
kp_min, kp_max = self._highlight_data
|
||||||
|
|
||||||
colors = [self.color_plot for row in range(len(self._data))]
|
colors = [self.color_plot for row in range(len(self._data))]
|
||||||
for i, rk in enumerate(self.data.get_rk_complete_profiles()):
|
for i, kp in enumerate(self.data.get_kp_complete_profiles()):
|
||||||
if rk_min <= rk <= rk_max:
|
if kp_min <= kp <= kp_max:
|
||||||
colors[i] = self.color_plot_current
|
colors[i] = self.color_plot_current
|
||||||
style = ["-" for row in range(len(self._data))]
|
style = ["-" for row in range(len(self._data))]
|
||||||
|
|
||||||
|
|||||||
Loaded 100 of 169 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user