mirror of
https://gitlab.com/pamhyr/pamhyr2.git
synced 2026-10-30 03:20:41 +01:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fecd29666 | ||
|
|
71e1324a0f | ||
|
|
07cae542b0 | ||
|
|
b693f67b99 | ||
|
|
18a3d51d75 | ||
|
|
118a39bd5c | ||
|
|
2009e8223b | ||
|
|
bdaa38ea5c | ||
|
|
713732b1dd | ||
|
|
f053539cdd | ||
|
|
fc6916bb3e | ||
|
|
97c26cb4fb | ||
|
|
10c98bb96e | ||
|
|
7c2d9891d0 | ||
|
|
3c3ac1f1df | ||
|
|
80af278a0f | ||
|
|
f254eaee25 | ||
|
|
5adb0bdee5 | ||
|
|
64c99d46d4 | ||
|
|
0f0defb36f | ||
|
|
1e1ee67d4b | ||
|
|
5bc514c565 | ||
|
|
1da3461dfe | ||
|
|
dd5eecb1e2 | ||
|
|
d93917b081 | ||
|
|
a31e2127e7 | ||
|
|
a29df8f904 | ||
|
|
97ebf9324a | ||
|
|
0112ad63d9 | ||
|
|
bcbb440ad4 | ||
|
|
7ef3184699 | ||
|
|
5f6c823301 | ||
|
|
bc4557e21f | ||
|
|
f6e08f203c | ||
|
|
5dcbc6b4e1 | ||
|
|
ebe906fce0 | ||
|
|
911a2bbbff | ||
|
|
706a900c8e | ||
|
|
da03f39425 | ||
|
|
7d42c164fc | ||
|
|
1b2f98494b | ||
|
|
e7b63fe270 | ||
|
|
80ae4c36ad | ||
|
|
41cffd13e0 | ||
|
|
9270dd0ff1 | ||
|
|
ba8a50e0b9 | ||
|
|
fce034419d | ||
|
|
31fe765e51 | ||
|
|
b582e133a1 | ||
|
|
7c4c772f43 | ||
|
|
5fc4e3903a | ||
|
|
c07a863018 | ||
|
|
243941db51 | ||
|
|
d6c1316178 | ||
|
|
f35048b89f | ||
|
|
24d92b2ac0 | ||
|
|
c702862bc4 | ||
|
|
400f6be9e3 | ||
|
|
5fc6951060 | ||
|
|
5ba38d5cd6 | ||
|
|
3e8132646d | ||
|
|
5aef0bbf3c | ||
|
|
bb3dadc0c7 | ||
|
|
7bb176e7c7 | ||
|
|
8c16e4ed58 | ||
|
|
e9315d9be7 | ||
|
|
46738cec6b | ||
|
|
e576bb15f1 | ||
|
|
26d18d26e9 | ||
|
|
8bac416ab5 | ||
|
|
e6aa840633 | ||
|
|
4b976d3b5f | ||
|
|
e3315c8f81 | ||
|
|
6bcbd006f1 | ||
|
|
c60a0938eb | ||
|
|
4d026afb2c | ||
|
|
4e888d9db0 | ||
|
|
440996b636 | ||
|
|
ed1a1a71ac | ||
|
|
cbe3ad0084 | ||
|
|
46935fde45 | ||
|
|
ca8dc19c83 | ||
|
|
e4a31b3497 | ||
|
|
406dc2bdd4 | ||
|
|
c325f61fce | ||
|
|
d3729cfe77 | ||
|
|
fa8f07b97e | ||
|
|
52c153fa84 | ||
|
|
21bd87f74b | ||
|
|
4d08f3c271 | ||
|
|
e44bbd5a3c | ||
|
|
f827f6bf13 | ||
|
|
4be68ba98d | ||
|
|
e47edea63b | ||
|
|
8daf89d1c4 | ||
|
|
0fa3ca5fad | ||
|
|
e3229c8183 | ||
|
|
c8606cf445 | ||
|
|
09029dc993 | ||
|
|
0a97070b90 | ||
|
|
589b8dcd23 | ||
|
|
4e87135bf4 | ||
|
|
f636236935 | ||
|
|
c3d732b426 | ||
|
|
8913a774ea | ||
|
|
36c3785cde | ||
|
|
5ed905df71 | ||
|
|
ea4fa81cc4 | ||
|
|
8862be991e | ||
|
|
8aea55909e | ||
|
|
1289967abb | ||
|
|
41d1fb9d59 | ||
|
|
8d9a196059 | ||
|
|
558085705f |
No files matched your search
+46
-14
@@ -29,7 +29,9 @@ stages:
|
|||||||
#############
|
#############
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
MAGE_8_VERSION: "v8.3.6"
|
MAGE_8_VERSION: "permalink/latest"
|
||||||
|
ADISTS_VERSION: "permalink/latest"
|
||||||
|
RUBAR_VERSION: "permalink/latest"
|
||||||
|
|
||||||
dl-mage8-doc:
|
dl-mage8-doc:
|
||||||
stage: downloads
|
stage: downloads
|
||||||
@@ -40,7 +42,7 @@ dl-mage8-doc:
|
|||||||
script:
|
script:
|
||||||
- mkdir -p doc
|
- mkdir -p doc
|
||||||
- cd doc
|
- cd doc
|
||||||
- curl -L -o mage8.pdf https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/$MAGE_8_VERSION/downloads/documents/Mage-8_Documentation.pdf
|
- curl -L -o mage8.pdf https://forge.inrae.fr/river-hydraulics/mage/-/releases/$MAGE_8_VERSION/downloads/documents/Mage-8_Documentation.pdf
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- doc/mage8.pdf
|
- doc/mage8.pdf
|
||||||
@@ -52,17 +54,13 @@ dl-mage8-linux:
|
|||||||
rules:
|
rules:
|
||||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||||
script:
|
script:
|
||||||
- curl -L -o mage8.tgz https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/$MAGE_8_VERSION/downloads/packages/mage_linux.tgz
|
- curl -L -o mage8.tgz https://forge.inrae.fr/river-hydraulics/mage/-/releases/$MAGE_8_VERSION/downloads/packages/mage_linux.tgz
|
||||||
- mkdir -p mage8-linux
|
- mkdir -p mage8-linux
|
||||||
- cd mage8-linux
|
- cd mage8-linux
|
||||||
- tar xvf ../mage8.tgz
|
- tar xvf ../mage8.tgz
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- mage8-linux/mage
|
- mage8-linux/mage
|
||||||
- mage8-linux/mage_as7
|
|
||||||
- mage8-linux/mage_extraire
|
|
||||||
- mage8-linux/mailleurTT
|
|
||||||
- mage8-linux/libbief.so
|
|
||||||
|
|
||||||
dl-mage8-windows:
|
dl-mage8-windows:
|
||||||
stage: downloads
|
stage: downloads
|
||||||
@@ -71,17 +69,13 @@ dl-mage8-windows:
|
|||||||
rules:
|
rules:
|
||||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||||
script:
|
script:
|
||||||
- curl -L -o mage8.tgz https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/$MAGE_8_VERSION/downloads/packages/mage_windows.tgz
|
- curl -L -o mage8.tgz https://forge.inrae.fr/river-hydraulics/mage/-/releases/$MAGE_8_VERSION/downloads/packages/mage_windows.tgz
|
||||||
- mkdir -p mage8-windows
|
- mkdir -p mage8-windows
|
||||||
- cd mage8-windows
|
- cd mage8-windows
|
||||||
- tar xvf ../mage8.tgz
|
- tar xvf ../mage8.tgz
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- mage8-windows/mage.exe
|
- mage8-windows/mage.exe
|
||||||
- mage8-windows/mage_as7.exe
|
|
||||||
- mage8-windows/mage_extraire.exe
|
|
||||||
- mage8-windows/mailleurTT.exe
|
|
||||||
- mage8-windows/libbief.dll
|
|
||||||
|
|
||||||
dl-adists-linux:
|
dl-adists-linux:
|
||||||
stage: downloads
|
stage: downloads
|
||||||
@@ -92,7 +86,7 @@ dl-adists-linux:
|
|||||||
script:
|
script:
|
||||||
- mkdir -p adists-linux
|
- mkdir -p adists-linux
|
||||||
- cd adists-linux
|
- cd adists-linux
|
||||||
- curl -L -o adists https://gitlab.irstea.fr/jean-baptiste.faure/adists/-/releases/v1.0.1/downloads/executables/adists
|
- curl -L -o adists https://forge.inrae.fr/river-hydraulics/adists/-/releases/$ADISTS_VERSION/downloads/executables/adists
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- adists-linux/adists
|
- adists-linux/adists
|
||||||
@@ -106,11 +100,42 @@ dl-adists-windows:
|
|||||||
script:
|
script:
|
||||||
- mkdir -p adists-windows
|
- mkdir -p adists-windows
|
||||||
- cd adists-windows
|
- cd adists-windows
|
||||||
- curl -L -o adists.exe https://gitlab.irstea.fr/jean-baptiste.faure/adists/-/releases/v1.0.1/downloads/executables/adists_win64.exe
|
- curl -L -o adists.exe https://forge.inrae.fr/river-hydraulics/adists/-/releases/$ADISTS_VERSION/downloads/executables/adists_win64.exe
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- adists-windows/adists.exe
|
- adists-windows/adists.exe
|
||||||
|
|
||||||
|
dl-rubar-linux:
|
||||||
|
stage: downloads
|
||||||
|
tags:
|
||||||
|
- linux
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||||
|
script:
|
||||||
|
- mkdir -p rubar-linux
|
||||||
|
- cd rubar-linux
|
||||||
|
- curl -L -o rubar.tgz https://forge.inrae.fr/river-hydraulics/rubarbe/-/releases/$RUBAR_VERSION/downloads/packages/rubar_linux.tgz
|
||||||
|
- tar xf rubar.tgz
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- rubar-linux/rubarbe
|
||||||
|
|
||||||
|
dl-rubar-windows:
|
||||||
|
stage: downloads
|
||||||
|
tags:
|
||||||
|
- linux
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||||
|
script:
|
||||||
|
- mkdir -p rubar-windows
|
||||||
|
- cd rubar-windows
|
||||||
|
- curl -L -o rubar.tgz https://forge.inrae.fr/river-hydraulics/rubarbe/-/releases/$RUBAR_VERSION/downloads/packages/rubar_windows.tgz
|
||||||
|
- tar xf rubar.tgz
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- rubar-windows/rubarbe.exe
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# CONFIGURE #
|
# CONFIGURE #
|
||||||
#############
|
#############
|
||||||
@@ -273,6 +298,8 @@ build-linux:
|
|||||||
needs:
|
needs:
|
||||||
- job: dl-adists-linux
|
- job: dl-adists-linux
|
||||||
artifacts: true
|
artifacts: true
|
||||||
|
- job: dl-rubar-linux
|
||||||
|
artifacts: true
|
||||||
- job: dl-mage8-linux
|
- job: dl-mage8-linux
|
||||||
artifacts: true
|
artifacts: true
|
||||||
- job: dl-mage8-doc
|
- job: dl-mage8-doc
|
||||||
@@ -314,6 +341,9 @@ build-linux:
|
|||||||
# Copy adists
|
# Copy adists
|
||||||
- mkdir -p pamhyr/adists
|
- mkdir -p pamhyr/adists
|
||||||
- cp -v ../adists-linux/* pamhyr/adists/
|
- cp -v ../adists-linux/* pamhyr/adists/
|
||||||
|
# Copy rubar
|
||||||
|
- mkdir -p pamhyr/rubar
|
||||||
|
- cp -v ../rubar-linux/* pamhyr/rubar/
|
||||||
# Copy Pamhyr
|
# Copy Pamhyr
|
||||||
- cp -r dist/pamhyr/* pamhyr/
|
- cp -r dist/pamhyr/* pamhyr/
|
||||||
# Pamhyr script to force x11
|
# Pamhyr script to force x11
|
||||||
@@ -379,6 +409,8 @@ build-windows:
|
|||||||
artifacts: true
|
artifacts: true
|
||||||
- job: dl-adists-windows
|
- job: dl-adists-windows
|
||||||
artifacts: true
|
artifacts: true
|
||||||
|
- job: dl-rubar-windows
|
||||||
|
artifacts: true
|
||||||
- job: dl-mage8-doc
|
- job: dl-mage8-doc
|
||||||
artifacts: true
|
artifacts: true
|
||||||
- job: set-version
|
- job: set-version
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Pamhyr is a free and open source graphical user interface for 1D hydro-sedimentary
|
Pamhyr is a free and open source graphical user interface for 1D hydro-sedimentary
|
||||||
modelling of rivers.
|
modelling of rivers.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -20,9 +20,9 @@ modelling of rivers.
|
|||||||
+ Run Mage 8 on a study and visualize results
|
+ Run Mage 8 on a study and visualize results
|
||||||
|
|
||||||
Let see the
|
Let see the
|
||||||
[documentation](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home)
|
[documentation](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home)
|
||||||
([:fr:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home-fr),
|
([:fr:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home-fr),
|
||||||
[:gb:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home-en))
|
[:gb:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home-en))
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
@@ -30,11 +30,11 @@ for more details.
|
|||||||
### GNU/Linux
|
### GNU/Linux
|
||||||
|
|
||||||
See documentation:
|
See documentation:
|
||||||
- [French :fr:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/fr/Install%20on%20GNULinux)
|
- [French :fr:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home/fr/Install%20on%20GNULinux)
|
||||||
- [English :gb:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/en/Install%20on%20GNULinux)
|
- [English :gb:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home/en/Install%20on%20GNULinux)
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
See documentation:
|
See documentation:
|
||||||
- [French :fr:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/fr/Install%20on%20Windows)
|
- [French :fr:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home/fr/Install%20on%20Windows)
|
||||||
- [English :gb:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/en/Install%20on%20Windows)
|
- [English :gb:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home/en/Install%20on%20Windows)
|
||||||
@@ -1375,7 +1375,7 @@ contribution.
|
|||||||
#+INCLUDE: "../../AUTHORS" src text
|
#+INCLUDE: "../../AUTHORS" src text
|
||||||
|
|
||||||
[fn:p2-gitlab] The {{{pamhyr2}}} Gitlab project page:
|
[fn:p2-gitlab] The {{{pamhyr2}}} Gitlab project page:
|
||||||
https://gitlab.irstea.fr/theophile.terraz/pamhyr
|
https://gitlab.com/pamhyr/pamhyr2
|
||||||
[fn:inrae] The INRAE web site: https://www.inrae.fr/
|
[fn:inrae] The INRAE web site: https://www.inrae.fr/
|
||||||
|
|
||||||
** Translate
|
** Translate
|
||||||
|
|||||||
@@ -424,7 +424,7 @@ Create a new version of {{{pamhyr}}} called {{{pamhyr2}}}
|
|||||||
|
|
||||||
** Contribution
|
** Contribution
|
||||||
#+LaTeX: \begin{center}
|
#+LaTeX: \begin{center}
|
||||||
\faIcon{gitlab} https://gitlab.irstea.fr/theophile.terraz/pamhyr/
|
\faIcon{gitlab} https://gitlab.com/pamhyr/pamhyr2/
|
||||||
#+LaTeX: \end{center}
|
#+LaTeX: \end{center}
|
||||||
|
|
||||||
*** For users
|
*** For users
|
||||||
@@ -462,7 +462,7 @@ Create a new version of {{{pamhyr}}} called {{{pamhyr2}}}
|
|||||||
# #+END_EXPORT
|
# #+END_EXPORT
|
||||||
|
|
||||||
#+LaTeX: \begin{center}
|
#+LaTeX: \begin{center}
|
||||||
\faIcon{gitlab} https://gitlab.irstea.fr/theophile.terraz/pamhyr/
|
\faIcon{gitlab} https://gitlab.com/pamhyr/pamhyr2/
|
||||||
#+LaTeX: \end{center}
|
#+LaTeX: \end{center}
|
||||||
|
|
||||||
#+LaTeX: \begin{center}
|
#+LaTeX: \begin{center}
|
||||||
|
|||||||
Binary file not shown.
@@ -112,7 +112,7 @@ Auteurs : & Céline Berni & celine.berni@inrae.fr\tabularnewline
|
|||||||
% \pagebreak{}
|
% \pagebreak{}
|
||||||
|
|
||||||
|
|
||||||
\section{Préambule}
|
\section*{Préambule}
|
||||||
|
|
||||||
Dans ce document, nous expliciterons les fonctionnalités de PamHyr utiles à la modélisation de scénarii d'aménagement de la rivière Hogneau comme décrit dans le document de TP.
|
Dans ce document, nous expliciterons les fonctionnalités de PamHyr utiles à la modélisation de scénarii d'aménagement de la rivière Hogneau comme décrit dans le document de TP.
|
||||||
Il est utile au préalable d'avoir suivi le tutoriel pour la modélisation de la rivière Hogneau fourni avec le logiciel (Tuto1-fr.pdf).
|
Il est utile au préalable d'avoir suivi le tutoriel pour la modélisation de la rivière Hogneau fourni avec le logiciel (Tuto1-fr.pdf).
|
||||||
@@ -121,16 +121,36 @@ Suivre le tutoriel 1 vous permettra de construire le modèle avec le scénario d
|
|||||||
Notez que l'outil PamHyr ne permet pas au stade actuel de comparer plusieurs scenarii.
|
Notez que l'outil PamHyr ne permet pas au stade actuel de comparer plusieurs scenarii.
|
||||||
Vous devrez pour ce faire exporter les vos résultats à partir de la fenêtre \textit{Résultats} qui s'ouvre en cliquant sur \texttt{[Résultats] => [Visualiser les derniers résultats]} à partir de la fenêtre principale.
|
Vous devrez pour ce faire exporter les vos résultats à partir de la fenêtre \textit{Résultats} qui s'ouvre en cliquant sur \texttt{[Résultats] => [Visualiser les derniers résultats]} à partir de la fenêtre principale.
|
||||||
|
|
||||||
Le bouton \includegraphics[width=0.5cm]{../../../src/View/ui/ressources/export.png} vous permet d'exporter les résultats au format CSV pour une utilisation en dehors de Pamhyr2.
|
|
||||||
Vous pouvez soit vous placer en un point kilométrique (PK) donné (celui marqué en rouge sur la visualisation du profil en long ou sélectionné dans le tableau) et exporter la hauteur d'eau, le niveau d'eau le débit ou autre en fonction du temps (sélectionnez alors \texttt{Temps (s)} pour l'axe X), soit vous placer à un instant donné et exporter la grandeur de votre choix pour tous les points kilométriques de votre maillage (sélectionnez alors \texttt{Point Kilométrique (m)} pour l'axe X).
|
|
||||||
Si vous choisissez cette seconde option, cocher \texttt{envelop} vous permettra d'exporter en plus la valeur maximale au cours du temps pour la grandeur choisie.
|
|
||||||
|
|
||||||
Ainsi dans l'exemple ci-dessous, les données exportées le seront au point kilométrique 34000\,m, à l'instant $t=1$ jour et 12h.
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\includegraphics[width=15cm]{img/export_resultats.png}
|
\includegraphics[width=15cm]{img/export_resultats_commentee.png}
|
||||||
\includegraphics[width=12cm]{img/export_resultats2.png}
|
%\includegraphics[width=12cm]{../../../src/View/ui/ressources/export_resultats2.png}
|
||||||
\par\end{center}
|
\par\end{center}
|
||||||
|
|
||||||
|
Le bouton \includegraphics[width=0.5cm]{../../../src/View/ui/ressources/export.png} vous permet d'exporter les résultats au format CSV pour une utilisation en dehors de Pamhyr2.
|
||||||
|
|
||||||
|
Deux options s'offrent à vous :
|
||||||
|
\begin{itemize}
|
||||||
|
\item Vous souhaitez avoir une vue d'ensemble du cours d'eau (et tracer une courbe de remous par exemple). Vous allez exporter une variable en un instant donné tout le long du cours d'eau. Il faut alors vous placer à un instant donné (à l'aide du curseur en bas à gauche) et exporter la grandeur de votre choix pour tous les points kilométriques de votre maillage. Dans la fenêtre d'export, vous devrez sélectionner \texttt{Point Kilométrique (m)} pour l'axe X, et la variable que vous souhaitez exporter pour l'axe Y.
|
||||||
|
|
||||||
|
Cocher \texttt{enveloppe} vous permettra d'exporter en plus les valeurs minimale et maximale au cours du temps pour la grandeur choisie.
|
||||||
|
|
||||||
|
Par exemple, vous choisissez d'exporter la cote du fond et la cote de l'eau et vous cochez \texttt{enveloppe}. Vous obtiendrez un tableau avec les colonnes suivantes :
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{Point Kilométrique (m)} : toutes les valeurs de PK le long de votre bief
|
||||||
|
\item \texttt{Cote du fond (m)} : la cote du fond correspondante à chaque PK
|
||||||
|
\item \texttt{Cote de l'eau (m)} : la cote de l'eau correspondante à chaque PK à l'instant sélectionné (voir figure ci-dessous)
|
||||||
|
\item \texttt{Cote de l'eau min (m)} : la cote de l'eau minimale atteinte correspondante à chaque PK
|
||||||
|
\item \texttt{Cote de l'eau max (m)} : la cote de l'eau maximale atteinte correspondante à chaque PK
|
||||||
|
\end{itemize}
|
||||||
|
ces deux dernières colonnes constituant l'enveloppe de la cote de l'eau.
|
||||||
|
\item Vous souhaitez regarder l'évolution au cours du temps de ce qu'il se passe en un point précis du cours d'eau (regarder l'hydrogramme de crue à l'aval d'un aménagement par exemple). Vous devez alors vous placer au point kilométrique (PK) qui vous intéresse (le PK sélectionné est marqué en rouge sur la visualisation du profil en long ou sélectionné dans le tableau) et exporter la hauteur d'eau, le niveau d'eau, le débit ou autre en fonction du temps. Dans la fenêtre d'export, vous devrez sélectionner \texttt{Temps (s)} pour l'axe X.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Ainsi dans l'exemple ci-dessus, les données exportées le seront au point kilométrique 34000\,m, à l'instant $t=1$ jour et 12h.
|
||||||
|
|
||||||
|
|
||||||
|
\pagebreak{}
|
||||||
|
|
||||||
\section{Premier scénario d'aménagement : abaissement du seuil}
|
\section{Premier scénario d'aménagement : abaissement du seuil}
|
||||||
|
|
||||||
Parmi les 3 options d'aménagement évoquées par la collectivité locale, jouer sur le contrôle aval en abaissant le seuil qui marque la jonction avec le canal de Condé-Pommeroeul peut faire baisser le niveau à l’amont.
|
Parmi les 3 options d'aménagement évoquées par la collectivité locale, jouer sur le contrôle aval en abaissant le seuil qui marque la jonction avec le canal de Condé-Pommeroeul peut faire baisser le niveau à l’amont.
|
||||||
@@ -156,6 +176,8 @@ Sur quelle distance le seuil aval influence-t-il la hauteur d'eau ?
|
|||||||
Est-ce suffisant pour limiter la hauteur d'eau au niveau du pont de l'A2 ($PK \approx 33000$\,m) ?
|
Est-ce suffisant pour limiter la hauteur d'eau au niveau du pont de l'A2 ($PK \approx 33000$\,m) ?
|
||||||
\end{remark}
|
\end{remark}
|
||||||
|
|
||||||
|
\pagebreak{}
|
||||||
|
|
||||||
\section{Second scénario d'aménagement : élargissement du lit moyen}
|
\section{Second scénario d'aménagement : élargissement du lit moyen}
|
||||||
|
|
||||||
Ce scénario d'aménagement consiste à essayer d’augmenter le laminage en créant un lit moyen en rive droite entre les PKs 32 015 et 33 920\,m. Pour rappel, cette localisation est imposée pour des raisons de disponibilité des terrains et on ne peut pas envisager une largeur du lit moyen supérieure à 50 mètres.
|
Ce scénario d'aménagement consiste à essayer d’augmenter le laminage en créant un lit moyen en rive droite entre les PKs 32 015 et 33 920\,m. Pour rappel, cette localisation est imposée pour des raisons de disponibilité des terrains et on ne peut pas envisager une largeur du lit moyen supérieure à 50 mètres.
|
||||||
@@ -166,8 +188,9 @@ Pourquoi élargir le lit moyen peut-il avoir un effet sur le niveau d'eau durant
|
|||||||
|
|
||||||
Pour élargir le lit moyen, la géométrie doit être modifiée.
|
Pour élargir le lit moyen, la géométrie doit être modifiée.
|
||||||
Il est judicieux d'enregistrer votre étude sous un autre nom avant de procéder à ces modifications (cliquez sur \texttt{[Fichier] => [Sauvegarder sous]}).
|
Il est judicieux d'enregistrer votre étude sous un autre nom avant de procéder à ces modifications (cliquez sur \texttt{[Fichier] => [Sauvegarder sous]}).
|
||||||
Le plus simple est de repartir de la géométrie avant maillage avant de modifier les transects.
|
|
||||||
Vous pouvez supprimer les sections interpolées en les sélectionnant dans la fenêtre \textit{Géométrie} et en appuyant sur le bouton \includegraphics[width=0.5cm]{../../../src/View/ui/ressources/del.png}.
|
Vous aurez un certain nombre de sections à modifier. Pour limiter leur nombre, le plus simple est de repartir de la géométrie initiale (avant maillage) avant de modifier les transects et de mailler à nouveau après les modifications.
|
||||||
|
Vous pouvez supprimer les sections interpolées (notées interpol\textit{i}) en les sélectionnant dans la fenêtre \textit{Géométrie} et en appuyant sur le bouton \includegraphics[width=0.5cm]{../../../src/View/ui/ressources/del.png}.
|
||||||
|
|
||||||
Cliquez sur \texttt{[Géométrie] => [Modifier la géométrie]} ou sur l'icône \includegraphics[width=0.5cm]{../../../src/View/ui/ressources/geometry.png} pour définir la géométrie du bief.
|
Cliquez sur \texttt{[Géométrie] => [Modifier la géométrie]} ou sur l'icône \includegraphics[width=0.5cm]{../../../src/View/ui/ressources/geometry.png} pour définir la géométrie du bief.
|
||||||
Sélectionnez la section en travers que vous souhaitez modifier.
|
Sélectionnez la section en travers que vous souhaitez modifier.
|
||||||
@@ -197,6 +220,8 @@ Quel est l'effet de cet aménagement sur l'hydrogramme de crue ?
|
|||||||
Peut-on s'attendre à ce résultat compte tenu du volume qu'il est possible de stocker en lit moyen et du volume total de la crue ?
|
Peut-on s'attendre à ce résultat compte tenu du volume qu'il est possible de stocker en lit moyen et du volume total de la crue ?
|
||||||
\end{remark}
|
\end{remark}
|
||||||
|
|
||||||
|
\pagebreak{}
|
||||||
|
|
||||||
\section{Troisième scénario d'aménagement : casier de stockage}
|
\section{Troisième scénario d'aménagement : casier de stockage}
|
||||||
|
|
||||||
Ce troisième scénario consiste à faire baisser le débit dans la rivière en créant un déversement vers un casier de stockage en rive gauche juste en aval du pont de l'A2.
|
Ce troisième scénario consiste à faire baisser le débit dans la rivière en créant un déversement vers un casier de stockage en rive gauche juste en aval du pont de l'A2.
|
||||||
@@ -216,7 +241,7 @@ Cliquez sur \texttt{[Réseau] => [Modifier le réseau]} ou sur l'icône \include
|
|||||||
Le réseau pour la configuration de référence ne comportait qu'un seul bief entre deux noeuds.
|
Le réseau pour la configuration de référence ne comportait qu'un seul bief entre deux noeuds.
|
||||||
Pour ajouter un casier, il faut ajouter un noeud pour la diffluence, un noeud en amont du casier et un noeud en aval du casier.
|
Pour ajouter un casier, il faut ajouter un noeud pour la diffluence, un noeud en amont du casier et un noeud en aval du casier.
|
||||||
Le casier ne peut en effet pas être en limite aval du modèle ni directement au niveau de la confluence.
|
Le casier ne peut en effet pas être en limite aval du modèle ni directement au niveau de la confluence.
|
||||||
Pour ajouter un noeud, cliquez \includegraphics[width=0.5cm]{../../../src/View/ui/ressources/add.png} pour sélectionner l'outil ``d'addition'' et cliquez ensuite dans la fenêtre grise à l'endroit ou vous souhaitez ajouter un noeud.
|
Pour ajouter un noeud, cliquez sur \includegraphics[width=0.5cm]{../../../src/View/ui/ressources/add.png} pour sélectionner l'outil ``d'addition'' et cliquez ensuite dans la fenêtre grise à l'endroit ou vous souhaitez ajouter un noeud.
|
||||||
De la même façon vous pourrez avec cet outil ajouter un bief entre deux noeuds en cliquant successivement sur l'un puis sur l'autre.
|
De la même façon vous pourrez avec cet outil ajouter un bief entre deux noeuds en cliquant successivement sur l'un puis sur l'autre.
|
||||||
Vous pourrez alors créer un réseau tel que celui ci-dessous où DevLat est le noeud marquant la diffluence.
|
Vous pourrez alors créer un réseau tel que celui ci-dessous où DevLat est le noeud marquant la diffluence.
|
||||||
\begin{center}
|
\begin{center}
|
||||||
@@ -236,6 +261,11 @@ Il vous faudra supprimer les sections dans l'un que vous implémenterez dans l'a
|
|||||||
L'outil d'import de géométrie pourra vous aider.
|
L'outil d'import de géométrie pourra vous aider.
|
||||||
Il faudra le cas échéant réimplémenter également les ouvrages.
|
Il faudra le cas échéant réimplémenter également les ouvrages.
|
||||||
|
|
||||||
|
Vous devrez ensuite implémenter le casier sur le noeud nommé casier. Cliquez sur \texttt{[Hydraulique] => [Casiers]}. Vous pouvez ajouter un casier en cliquant sur \includegraphics[width=0.5cm]{../../../src/View/ui/ressources/add.png}. Vous devrez ensuite configurer le casier en cliquant sur l'icône \includegraphics[width=0.5cm]{"../../../src/View/ui/ressources/edit.png"}. Pour chaque altitude, vous pouvez définir l'aire de stockage (en ha). Vous pourrez ainsi configurer votre casier de la façon suivante :
|
||||||
|
\begin{center}
|
||||||
|
\includegraphics[width=10cm]{img/Casier.png}
|
||||||
|
\par\end{center}
|
||||||
|
|
||||||
Lancez le calcul pour chacune des crues proposées avec ce nouvel aménagement.
|
Lancez le calcul pour chacune des crues proposées avec ce nouvel aménagement.
|
||||||
|
|
||||||
\begin{remark}
|
\begin{remark}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 155 KiB |
@@ -101,7 +101,7 @@ Authors : & Pierre-Antoine Rouby & pierre-antoine.rouby@inrae.fr\tabularnewline
|
|||||||
|
|
||||||
\section{Install Pamhyr2}
|
\section{Install Pamhyr2}
|
||||||
|
|
||||||
Pamhyr2 can be downloaded from \url{https://gitlab.irstea.fr/theophile.terraz/pamhyr}.
|
Pamhyr2 can be downloaded from \url{https://gitlab.com/pamhyr/pamhyr2}.
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\includegraphics[width=15cm]{img/dl.png}
|
\includegraphics[width=15cm]{img/dl.png}
|
||||||
\par\end{center}
|
\par\end{center}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -12,3 +12,5 @@ shapely>=2.0.1
|
|||||||
lxml>=4.9.3
|
lxml>=4.9.3
|
||||||
platformdirs>=4.2.0
|
platformdirs>=4.2.0
|
||||||
pyshp>=2.3.1
|
pyshp>=2.3.1
|
||||||
|
rasterio==1.3.11
|
||||||
|
#fortranformat==2.0.3
|
||||||
@@ -46,6 +46,10 @@ copy /y ..\mage8-windows\mage_extraire.exe pamhyr\mage8\
|
|||||||
copy /y ..\mage8-windows\mailleurTT.exe pamhyr\mage8\
|
copy /y ..\mage8-windows\mailleurTT.exe pamhyr\mage8\
|
||||||
copy /y ..\mage8-windows\libbief.dll pamhyr\mage8\
|
copy /y ..\mage8-windows\libbief.dll pamhyr\mage8\
|
||||||
|
|
||||||
|
rem rubar
|
||||||
|
mkdir pamhyr\rubar
|
||||||
|
copy /y ..\rubar-windows\rubarbe.exe pamhyr\rubar\
|
||||||
|
|
||||||
rem adists
|
rem adists
|
||||||
mkdir pamhyr\adists
|
mkdir pamhyr\adists
|
||||||
copy /y ..\adists-windows\adists.exe pamhyr\adists\
|
copy /y ..\adists-windows\adists.exe pamhyr\adists\
|
||||||
|
|||||||
@@ -12,3 +12,5 @@ shapely>=2.0.1
|
|||||||
lxml>=4.9.3
|
lxml>=4.9.3
|
||||||
platformdirs>=4.2.0
|
platformdirs>=4.2.0
|
||||||
pyshp>=2.3.1
|
pyshp>=2.3.1
|
||||||
|
rasterio==1.3.11
|
||||||
|
#fortranformat==2.0.3
|
||||||
@@ -0,0 +1,317 @@
|
|||||||
|
# Internal.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2025 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from numpy import sign
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
from tools import logger_color_red, logger_color_reset, logger_exception
|
||||||
|
from Meshing.AMeshingTool import AMeshingTool
|
||||||
|
|
||||||
|
from Model.Geometry.ProfileXYZ import ProfileXYZ
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class InternalMeshing(AMeshingTool):
|
||||||
|
def __init__(self):
|
||||||
|
super(InternalMeshing, self).__init__()
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Meshing #
|
||||||
|
###########
|
||||||
|
|
||||||
|
def meshing(self, reach,
|
||||||
|
step: float = 50,
|
||||||
|
limites=[-1, -1],
|
||||||
|
linear: bool = True):
|
||||||
|
if reach is None or len(reach.profiles) == 0:
|
||||||
|
return reach
|
||||||
|
|
||||||
|
if limites[0] > limites[1]:
|
||||||
|
lim = limites[1]
|
||||||
|
limites[1] = limites[0]
|
||||||
|
limites[0] = lim
|
||||||
|
elif limites[0] == limites[1]:
|
||||||
|
return reach
|
||||||
|
|
||||||
|
self.st_to_m(reach, limites)
|
||||||
|
self.interpolate_transversal_step(reach,
|
||||||
|
limites,
|
||||||
|
step)
|
||||||
|
self.purge_aligned_points(reach)
|
||||||
|
|
||||||
|
return reach
|
||||||
|
|
||||||
|
def st_to_m(self, reach, limites):
|
||||||
|
|
||||||
|
gl = reach.compute_guidelines()
|
||||||
|
profiles = reach.profiles[limites[0]:limites[1]+1]
|
||||||
|
|
||||||
|
# we make sure that the lines are in the left-to-right order
|
||||||
|
guide_list = [
|
||||||
|
x.name
|
||||||
|
for x in profiles[0].named_points()
|
||||||
|
if x.name in gl[0]
|
||||||
|
]
|
||||||
|
|
||||||
|
guide_list = ["un"] + guide_list + ["np"]
|
||||||
|
max_values = [0] * (len(guide_list) - 1)
|
||||||
|
max_values_index = [0] * (len(guide_list) - 1)
|
||||||
|
# we work between each couple of guidelines
|
||||||
|
for j, p in enumerate(profiles):
|
||||||
|
for i in range(len(guide_list) - 1):
|
||||||
|
index1 = p.named_point_index(guide_list[i])
|
||||||
|
index2 = p.named_point_index(guide_list[i+1])
|
||||||
|
if index2 - index1 > max_values[i]:
|
||||||
|
max_values[i] = index2 - index1
|
||||||
|
max_values_index[i] = j
|
||||||
|
|
||||||
|
for i in range(len(max_values)):
|
||||||
|
for isect in range(max_values_index[i], len(profiles)-1):
|
||||||
|
self.compl_sect(profiles[isect],
|
||||||
|
profiles[isect+1],
|
||||||
|
guide_list[i],
|
||||||
|
guide_list[i+1])
|
||||||
|
|
||||||
|
for isect in reversed(range(0, max_values_index[i])):
|
||||||
|
self.compl_sect(profiles[isect+1],
|
||||||
|
profiles[isect],
|
||||||
|
guide_list[i],
|
||||||
|
guide_list[i+1])
|
||||||
|
|
||||||
|
def interpolate_transversal_step(self,
|
||||||
|
reach,
|
||||||
|
limites,
|
||||||
|
step):
|
||||||
|
# calcul number of intermediate profiles
|
||||||
|
np = []
|
||||||
|
for i in range(limites[0], limites[1]):
|
||||||
|
np.append(int(abs(reach.profiles[i+1].rk -
|
||||||
|
reach.profiles[i].rk) / step) - 1)
|
||||||
|
if np[-1] < 0:
|
||||||
|
np[-1] = 0
|
||||||
|
|
||||||
|
d = [] # ratios
|
||||||
|
p = [] # new profiles
|
||||||
|
ptr = int(limites[0])
|
||||||
|
for i in range(limites[1] - limites[0]):
|
||||||
|
d = 1.0/float(np[i]+1)
|
||||||
|
ptr0 = ptr
|
||||||
|
for j in range(np[i]):
|
||||||
|
p = ProfileXYZ(reach=reach, status=reach._status)
|
||||||
|
# RATIO entre les deux sections initiales
|
||||||
|
dj = float(j+1)*d
|
||||||
|
ptr += 1 # next profile, original
|
||||||
|
for k in range(len(reach.profiles[ptr0].points)):
|
||||||
|
p.add()
|
||||||
|
p.points[k].name = reach.profiles[ptr0].points[k].name
|
||||||
|
p.points[k].x = reach.profiles[ptr0].points[k].x + \
|
||||||
|
dj*(reach.profiles[ptr].points[k].x -
|
||||||
|
reach.profiles[ptr0].points[k].x)
|
||||||
|
p.points[k].y = reach.profiles[ptr0].points[k].y + \
|
||||||
|
dj*(reach.profiles[ptr].points[k].y -
|
||||||
|
reach.profiles[ptr0].points[k].y)
|
||||||
|
p.points[k].z = reach.profiles[ptr0].points[k].z + \
|
||||||
|
dj*(reach.profiles[ptr].points[k].z -
|
||||||
|
reach.profiles[ptr0].points[k].z)
|
||||||
|
p.rk = reach.profiles[ptr0].rk + \
|
||||||
|
dj*(reach.profiles[ptr].rk -
|
||||||
|
reach.profiles[ptr0].rk)
|
||||||
|
p.name = f'interpol{p.rk}'
|
||||||
|
reach.insert_profile(ptr, p)
|
||||||
|
ptr += 1 # next profile, original
|
||||||
|
|
||||||
|
def compl_sect(self, sect1, sect2, tag1, tag2):
|
||||||
|
# sect1: reference section
|
||||||
|
# sect2: section to complete
|
||||||
|
# start1 and 2: indices of the first point of the bed to complete
|
||||||
|
# end = start + len
|
||||||
|
# len1 and 2: number of intervals
|
||||||
|
# len1: target len
|
||||||
|
|
||||||
|
start1 = sect1.named_point_index(tag1)
|
||||||
|
start2 = sect2.named_point_index(tag1)
|
||||||
|
|
||||||
|
end1 = sect1.named_point_index(tag2)
|
||||||
|
end2 = sect2.named_point_index(tag2)
|
||||||
|
|
||||||
|
len1 = end1 - start1
|
||||||
|
len2 = end2 - start2
|
||||||
|
|
||||||
|
if len1 < len2:
|
||||||
|
self.compl_sect(sect2, sect1, start2, start1,
|
||||||
|
len2, len1, tag1, tag2)
|
||||||
|
return
|
||||||
|
elif len1 == len2:
|
||||||
|
return
|
||||||
|
|
||||||
|
ltot1 = 0.0
|
||||||
|
ltot2 = 0.0
|
||||||
|
alpha = []
|
||||||
|
beta = []
|
||||||
|
# remove names
|
||||||
|
sect2.points[start2].name = ''
|
||||||
|
sect2.points[end2].name = ''
|
||||||
|
for i in range(len1):
|
||||||
|
ltot1 += sect1.point(start1+i).dist(sect1.point(start1+i+1))
|
||||||
|
alpha.append(ltot1)
|
||||||
|
alpha = list(map(lambda x: x/ltot1, alpha)) # target ratios
|
||||||
|
for i in range(len2):
|
||||||
|
ltot2 += sect2.point(start2+i).dist(sect2.point(start2+i+1))
|
||||||
|
beta.append(ltot2)
|
||||||
|
beta = list(map(lambda x: x/ltot2, beta)) # current ratios
|
||||||
|
for i in range(len1 - len2):
|
||||||
|
beta.append(1.0)
|
||||||
|
beta.append(0.0) # beta[-1]
|
||||||
|
if len2 < 1 or ltot2 < 0.0001:
|
||||||
|
# unique point (copy len1 times)
|
||||||
|
# we are at an edge of the profile
|
||||||
|
for i in range(len1-len2):
|
||||||
|
p = sect2.point(start2).copy()
|
||||||
|
sect2.insert_point(start2, p)
|
||||||
|
len2 += 1
|
||||||
|
elif ltot1 < 0.0001:
|
||||||
|
sect2.add_npoints(len1-len2)
|
||||||
|
len2 = len1
|
||||||
|
else: # regular case
|
||||||
|
# loop on the points to insert
|
||||||
|
for k in range(len1-len2):
|
||||||
|
trouve = False
|
||||||
|
for j0 in range(len2):
|
||||||
|
if trouve:
|
||||||
|
break
|
||||||
|
undeplus = True
|
||||||
|
for j1 in range(j0, len2):
|
||||||
|
if undeplus:
|
||||||
|
if beta[j1] <= alpha[j1]:
|
||||||
|
undeplus = False
|
||||||
|
break
|
||||||
|
if undeplus:
|
||||||
|
if j0 == len2:
|
||||||
|
trouve = True
|
||||||
|
else:
|
||||||
|
j1 = j0+1
|
||||||
|
if beta[j0]-alpha[j0] > alpha[j1]-beta[j0]:
|
||||||
|
trouve = True
|
||||||
|
|
||||||
|
if trouve:
|
||||||
|
len2 += 1
|
||||||
|
for i in reversed(range(j0, len2)):
|
||||||
|
beta[i+1] = beta[i]
|
||||||
|
if (beta[j0] == beta[j0-1]):
|
||||||
|
# rien
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
ratio = (alpha[j0] - beta[j0-1]) \
|
||||||
|
/ (beta[j0] - beta[j0-1])
|
||||||
|
if ratio < 0.0:
|
||||||
|
print(f"ratio négatif {ratio}")
|
||||||
|
# on double le point a gauche
|
||||||
|
p = sect2.point(start2+j0-1).copy()
|
||||||
|
sect2.insert_point(start2+j0-1, p)
|
||||||
|
sect2.point(start2+j0-1).name = ''
|
||||||
|
beta[j0] = beta[j0-1]
|
||||||
|
else:
|
||||||
|
p = sect2.point(start2+j0).copy()
|
||||||
|
sect2.insert_point(start2+j0, p)
|
||||||
|
sect2.point(start2+j0+1).name = ''
|
||||||
|
sect2.point(start2+j0+1).x = \
|
||||||
|
(1.0-ratio) * sect2.point(start2+j0).x + \
|
||||||
|
ratio * sect2.point(start2+j0+2).x
|
||||||
|
sect2.point(start2+j0+1).y = \
|
||||||
|
(1.0-ratio) * sect2.point(start2+j0).y + \
|
||||||
|
ratio * sect2.point(start2+j0+2).y
|
||||||
|
sect2.point(start2+j0+1).z = \
|
||||||
|
(1.0-ratio) * sect2.point(start2+j0).z + \
|
||||||
|
ratio * sect2.point(start2+j0+2).z
|
||||||
|
beta[j0] = (1.-ratio)*beta[j0-1] \
|
||||||
|
+ ratio*beta[j0+1]
|
||||||
|
|
||||||
|
if len1 > len2:
|
||||||
|
for i in range(len1 - len2):
|
||||||
|
p = sect2.point(start2+len2).copy()
|
||||||
|
sect2.insert_point(start2+len2, p)
|
||||||
|
sect2.point(start2+len2).name = ''
|
||||||
|
if tag1 != "un":
|
||||||
|
sect2.point(start2).name = tag1
|
||||||
|
if tag2 != "np":
|
||||||
|
sect2.point(start2+len2).name = tag2
|
||||||
|
sect2.modified()
|
||||||
|
|
||||||
|
def update_rk(self, reach,
|
||||||
|
step: float = 50,
|
||||||
|
limites=[-1, -1],
|
||||||
|
origin=0,
|
||||||
|
directrices=['un', 'np'],
|
||||||
|
lplan: bool = False,
|
||||||
|
lm: int = 3,
|
||||||
|
linear: bool = False,
|
||||||
|
origin_value=0.0,
|
||||||
|
orientation=0):
|
||||||
|
if reach is None or len(reach.profiles) == 0:
|
||||||
|
return reach
|
||||||
|
|
||||||
|
nprof = reach.number_profiles
|
||||||
|
if origin >= nprof or origin < 0:
|
||||||
|
logger.warning(
|
||||||
|
f"Origin outside reach"
|
||||||
|
)
|
||||||
|
return reach
|
||||||
|
|
||||||
|
# orientation is the orintation of the bief:
|
||||||
|
# 1: up -> downstream
|
||||||
|
# 2: down -> upstream
|
||||||
|
# else: keep current orientation
|
||||||
|
if orientation == 1:
|
||||||
|
sgn = 1.0
|
||||||
|
elif orientation == 2:
|
||||||
|
sgn = -1.0
|
||||||
|
else:
|
||||||
|
sgn = sign(reach.profiles[-1].rk - reach.profiles[0].rk)
|
||||||
|
if abs(sgn) < 0.5:
|
||||||
|
sgn = 1.0
|
||||||
|
|
||||||
|
reach.profiles[origin].rk = origin_value
|
||||||
|
|
||||||
|
if origin < nprof - 1:
|
||||||
|
for i in range(origin+1, nprof):
|
||||||
|
# 2D
|
||||||
|
d1 = reach.profiles[i-1].named_point(
|
||||||
|
directrices[0]
|
||||||
|
).dist_2d(reach.profiles[i].named_point(directrices[0]))
|
||||||
|
d2 = reach.profiles[i-1].named_point(
|
||||||
|
directrices[1]
|
||||||
|
).dist_2d(reach.profiles[i].named_point(directrices[1]))
|
||||||
|
reach.profiles[i].rk = reach.profiles[i-1].rk \
|
||||||
|
+ (sgn * (d1 + d2) / 2)
|
||||||
|
if origin > 0:
|
||||||
|
for i in reversed(range(0, origin)):
|
||||||
|
# 2D
|
||||||
|
d1 = reach.profiles[i+1].named_point(
|
||||||
|
directrices[0]
|
||||||
|
).dist_2d(reach.profiles[i].named_point(directrices[0]))
|
||||||
|
d2 = reach.profiles[i+1].named_point(
|
||||||
|
directrices[1]
|
||||||
|
).dist_2d(reach.profiles[i].named_point(directrices[1]))
|
||||||
|
reach.profiles[i].rk = reach.profiles[i+1].rk \
|
||||||
|
- (sgn * (d1 + d2) / 2)
|
||||||
|
|
||||||
|
def purge_aligned_points(self, reach):
|
||||||
|
for p in reach.profiles:
|
||||||
|
p.purge_aligned_points()
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from numpy import sign
|
||||||
|
|
||||||
from ctypes import (
|
from ctypes import (
|
||||||
cdll,
|
cdll,
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class AddFile(SQLSubModel):
|
|||||||
self._path = path
|
self._path = path
|
||||||
self._text = text
|
self._text = text
|
||||||
|
|
||||||
AddFile._id_cnt = max(id, AddFile._id_cnt+1)
|
AddFile._id_cnt = max(self.id + 1, AddFile._id_cnt + 1)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
value = None
|
value = None
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ class BoundaryCondition(SQLSubModel):
|
|||||||
self._header = []
|
self._header = []
|
||||||
self._types = [float, float]
|
self._types = [float, float]
|
||||||
|
|
||||||
BoundaryCondition._id_cnt = max(BoundaryCondition._id_cnt + 1, self.id)
|
BoundaryCondition._id_cnt = max(BoundaryCondition._id_cnt + 1,
|
||||||
|
self.id + 1)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class BoundaryConditionAdisTS(SQLSubModel):
|
|||||||
self._types = [self.time_convert, float]
|
self._types = [self.time_convert, float]
|
||||||
|
|
||||||
BoundaryConditionAdisTS._id_cnt = max(
|
BoundaryConditionAdisTS._id_cnt = max(
|
||||||
BoundaryConditionAdisTS._id_cnt + 1, self.id)
|
BoundaryConditionAdisTS._id_cnt + 1, self.id + 1)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
@@ -222,3 +222,82 @@ class BoundaryConditionAdisTS(SQLSubModel):
|
|||||||
@property
|
@property
|
||||||
def data(self):
|
def data(self):
|
||||||
return self._data.copy()
|
return self._data.copy()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _default_0(self):
|
||||||
|
return self._types[0](0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _default_1(self):
|
||||||
|
return self._types[1](0.0)
|
||||||
|
|
||||||
|
def new_from_data(self, header, data):
|
||||||
|
new_0 = self._default_0
|
||||||
|
new_1 = self._default_1
|
||||||
|
|
||||||
|
if len(header) != 0:
|
||||||
|
for i in [0, 1]:
|
||||||
|
for j in range(len(header)):
|
||||||
|
if self._header[i] == header[j]:
|
||||||
|
if i == 0:
|
||||||
|
new_0 = self._types[i](data[j].replace(",", "."))
|
||||||
|
else:
|
||||||
|
new_1 = self._types[i](data[j].replace(",", "."))
|
||||||
|
else:
|
||||||
|
new_0 = self._types[0](data[0].replace(",", "."))
|
||||||
|
new_1 = self._types[1](data[1].replace(",", "."))
|
||||||
|
|
||||||
|
return (new_0, new_1)
|
||||||
|
|
||||||
|
def add(self, index: int):
|
||||||
|
value = (self._default_0, self._default_1)
|
||||||
|
self._data.insert(index, value)
|
||||||
|
self._status.modified()
|
||||||
|
return value
|
||||||
|
|
||||||
|
def insert(self, index: int, value):
|
||||||
|
self._data.insert(index, value)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def delete_i(self, indexes):
|
||||||
|
self._data = list(
|
||||||
|
map(
|
||||||
|
lambda e: e[1],
|
||||||
|
filter(
|
||||||
|
lambda e: e[0] not in indexes,
|
||||||
|
enumerate(self.data)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def sort(self, _reverse=False, key=None):
|
||||||
|
if key is None:
|
||||||
|
self._data.sort(reverse=_reverse)
|
||||||
|
else:
|
||||||
|
self._data.sort(reverse=_reverse, key=key)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def index(self, bc):
|
||||||
|
self._data.index(bc)
|
||||||
|
|
||||||
|
def get_i(self, index):
|
||||||
|
return self.data[index]
|
||||||
|
|
||||||
|
def get_range(self, _range):
|
||||||
|
lst = []
|
||||||
|
for r in _range:
|
||||||
|
lst.append(r)
|
||||||
|
return lst
|
||||||
|
|
||||||
|
def _set_i_c_v(self, index, column, value):
|
||||||
|
v = list(self._data[index])
|
||||||
|
v[column] = self._types[column](value)
|
||||||
|
self._data[index] = tuple(v)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def set_i_0(self, index: int, value):
|
||||||
|
self._set_i_c_v(index, 0, value)
|
||||||
|
|
||||||
|
def set_i_1(self, index: int, value):
|
||||||
|
self._set_i_c_v(index, 1, value)
|
||||||
@@ -53,7 +53,7 @@ class D90AdisTS(SQLSubModel):
|
|||||||
|
|
||||||
D90AdisTS._id_cnt = max(
|
D90AdisTS._id_cnt = max(
|
||||||
D90AdisTS._id_cnt + 1,
|
D90AdisTS._id_cnt + 1,
|
||||||
self.id
|
self.id + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class D90AdisTSSpec(SQLSubModel):
|
|||||||
self._d90 = None
|
self._d90 = None
|
||||||
self._enabled = True
|
self._enabled = True
|
||||||
|
|
||||||
D90AdisTSSpec._id_cnt = max(D90AdisTSSpec._id_cnt + 1, self.id)
|
D90AdisTSSpec._id_cnt = max(D90AdisTSSpec._id_cnt + 1, self.id + 1)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class DIFAdisTS(SQLSubModel):
|
|||||||
|
|
||||||
DIFAdisTS._id_cnt = max(
|
DIFAdisTS._id_cnt = max(
|
||||||
DIFAdisTS._id_cnt + 1,
|
DIFAdisTS._id_cnt + 1,
|
||||||
self.id
|
self.id + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class DIFAdisTSSpec(SQLSubModel):
|
|||||||
self._c = None
|
self._c = None
|
||||||
self._enabled = True
|
self._enabled = True
|
||||||
|
|
||||||
DIFAdisTSSpec._id_cnt = max(DIFAdisTSSpec._id_cnt + 1, self.id)
|
DIFAdisTSSpec._id_cnt = max(DIFAdisTSSpec._id_cnt + 1, self.id + 1)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class Friction(SQLSubModel):
|
|||||||
else:
|
else:
|
||||||
self.id = id
|
self.id = id
|
||||||
|
|
||||||
Friction._id_cnt = max(self.id, Friction._id_cnt+1)
|
Friction._id_cnt = max(self.id + 1, Friction._id_cnt + 1)
|
||||||
|
|
||||||
self._name = name
|
self._name = name
|
||||||
self._edge = None
|
self._edge = None
|
||||||
|
|||||||
@@ -228,3 +228,25 @@ class PointXYZ(Point, SQLSubModel):
|
|||||||
c = PointXYZ.distance(p3, p1)
|
c = PointXYZ.distance(p3, p1)
|
||||||
s = (a + b + c) / 2
|
s = (a + b + c) / 2
|
||||||
return (s*(s-a) * (s-b)*(s-c)) ** 0.5
|
return (s*(s-a) * (s-b)*(s-c)) ** 0.5
|
||||||
|
|
||||||
|
def dist_from_seg(self, p1, p2):
|
||||||
|
a2 = pow(PointXYZ.distance(self, p1), 2)
|
||||||
|
b2 = pow(PointXYZ.distance(self, p2), 2)
|
||||||
|
c2 = pow(PointXYZ.distance(p1, p2), 2)
|
||||||
|
if c2 < 0.00000001:
|
||||||
|
# si les deux points sont confondus
|
||||||
|
d = 0.0
|
||||||
|
else:
|
||||||
|
d = np.sqrt(abs(a2 - pow((c2 - b2 + a2) / (2*np.sqrt(c2)), 2)))
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
p = PointXYZ(self.x,
|
||||||
|
self.y,
|
||||||
|
self.z,
|
||||||
|
self.name,
|
||||||
|
self._profile,
|
||||||
|
self._status)
|
||||||
|
p.sl = self.sl
|
||||||
|
return p
|
||||||
@@ -44,7 +44,7 @@ class Profile(object):
|
|||||||
else:
|
else:
|
||||||
self.id = id
|
self.id = id
|
||||||
|
|
||||||
Profile._id_cnt = max(self.id, Profile._id_cnt+1)
|
Profile._id_cnt = max(self.id + 1, Profile._id_cnt + 1)
|
||||||
|
|
||||||
self._num = int(num)
|
self._num = int(num)
|
||||||
self._code1 = int(code1)
|
self._code1 = int(code1)
|
||||||
@@ -88,6 +88,25 @@ class Profile(object):
|
|||||||
def point(self, index):
|
def point(self, index):
|
||||||
return self.points[index]
|
return self.points[index]
|
||||||
|
|
||||||
|
def named_point(self, name):
|
||||||
|
if name == "un":
|
||||||
|
return self.points[0]
|
||||||
|
elif name == "np":
|
||||||
|
return self.points[-1]
|
||||||
|
else:
|
||||||
|
return next((p for p in self.points if p.name == name), None)
|
||||||
|
|
||||||
|
def named_point_index(self, name):
|
||||||
|
if name == "un":
|
||||||
|
return 0
|
||||||
|
elif name == "np":
|
||||||
|
return len(self.points) - 1
|
||||||
|
else:
|
||||||
|
return next(
|
||||||
|
(p for p in enumerate(self.points) if p[1].name == name),
|
||||||
|
None
|
||||||
|
)[0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def reach(self):
|
def reach(self):
|
||||||
return self._reach
|
return self._reach
|
||||||
@@ -206,7 +225,7 @@ class Profile(object):
|
|||||||
"""Insert point at index.
|
"""Insert point at index.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
index: The index of new profile.
|
index: The index of new point.
|
||||||
point: The point.
|
point: The point.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|||||||
@@ -167,8 +167,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
filter(
|
filter(
|
||||||
lambda s: s.id == sl,
|
lambda s: s.id == sl,
|
||||||
data["sediment_layers_list"].sediment_layers
|
data["sediment_layers_list"].sediment_layers
|
||||||
)
|
), None)
|
||||||
)
|
|
||||||
|
|
||||||
data["profile"] = new
|
data["profile"] = new
|
||||||
new._points = PointXYZ._db_load(execute, data.copy())
|
new._points = PointXYZ._db_load(execute, data.copy())
|
||||||
@@ -883,3 +882,44 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||||||
def modified(self):
|
def modified(self):
|
||||||
self.tab_up_to_date = False
|
self.tab_up_to_date = False
|
||||||
self.station_up_to_date = False
|
self.station_up_to_date = False
|
||||||
|
|
||||||
|
def add_npoints(self, npoints):
|
||||||
|
# add npoints in a profile
|
||||||
|
for k in range(npoints):
|
||||||
|
disti = 0.0
|
||||||
|
i = 1
|
||||||
|
for j in range(len(self.points)-1):
|
||||||
|
distj = self.point(j).dist(self.point(j+1))
|
||||||
|
if distj > disti:
|
||||||
|
disti = distj
|
||||||
|
i = j
|
||||||
|
self.insert_point(i, self.point(i).copy())
|
||||||
|
self.point(i+1).name = ''
|
||||||
|
self.point(i+1).x = 0.5 * self.point(i).x + 0.5 * self.point(i+2).x
|
||||||
|
self.point(i+1).y = 0.5 * self.point(i).y + 0.5 * self.point(i+2).y
|
||||||
|
self.point(i+1).z = 0.5 * self.point(i).z + 0.5 * self.point(i+2).z
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
p = ProfileXYZ(name=self.name,
|
||||||
|
rk=self.rk,
|
||||||
|
reach=self.reach,
|
||||||
|
nb_point=0,
|
||||||
|
code1=0, code2=0,
|
||||||
|
status=self.reach._status)
|
||||||
|
for i, k in enumerate(self.points):
|
||||||
|
p.insert_point(i, k.copy())
|
||||||
|
|
||||||
|
return p
|
||||||
|
|
||||||
|
def purge_aligned_points(self):
|
||||||
|
|
||||||
|
align = True
|
||||||
|
while (align):
|
||||||
|
align = False
|
||||||
|
for i in range(1, self.number_points - 1):
|
||||||
|
d = self.point(i).dist_from_seg(self.point(i-1),
|
||||||
|
self.point(i+1))
|
||||||
|
if d < 0.00001 and self.point(i).name == "":
|
||||||
|
align = True
|
||||||
|
self.delete_i([i])
|
||||||
|
break
|
||||||
@@ -52,7 +52,7 @@ class BasicHS(SQLSubModel):
|
|||||||
self._enabled = True
|
self._enabled = True
|
||||||
self._data = []
|
self._data = []
|
||||||
|
|
||||||
BasicHS._id_cnt = max(BasicHS._id_cnt + 1, self.id)
|
BasicHS._id_cnt = max(BasicHS._id_cnt + 1, self.id + 1)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ class TriangularWeir(BasicHS):
|
|||||||
self._data = [
|
self._data = [
|
||||||
BHSValue("elevation", float, 1.0, status=status),
|
BHSValue("elevation", float, 1.0, status=status),
|
||||||
BHSValue("loading_elevation", float, 9999.999, status=status),
|
BHSValue("loading_elevation", float, 9999.999, status=status),
|
||||||
BHSValue("discharge_coefficient", float, 0.4, status=status),
|
BHSValue("discharge_coefficient", float, 0.31, status=status),
|
||||||
BHSValue("half-angle_tangent", float, 0.0, status=status),
|
BHSValue("half-angle_tangent", float, 1.0, status=status),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class HydraulicStructure(SQLSubModel):
|
|||||||
|
|
||||||
HydraulicStructure._id_cnt = max(
|
HydraulicStructure._id_cnt = max(
|
||||||
HydraulicStructure._id_cnt + 1,
|
HydraulicStructure._id_cnt + 1,
|
||||||
self.id
|
self.id + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -155,7 +155,6 @@ 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
|
||||||
|
|||||||
@@ -382,21 +382,31 @@ class InitialConditions(SQLSubModel):
|
|||||||
self._data = []
|
self._data = []
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
width = profile.wet_width(profile.z_min() + height)
|
width = profile.wet_width(profile.z_min() + height)
|
||||||
|
area = profile.wet_area(profile.z_min() + height)
|
||||||
|
radius = profile.wet_radius(profile.z_min() + height)
|
||||||
frictions = self._reach.frictions.frictions
|
frictions = self._reach.frictions.frictions
|
||||||
strickler = None
|
strickler = None
|
||||||
for f in frictions:
|
if frictions is not None:
|
||||||
if f.contains_rk(profile.rk):
|
if len(frictions) >= 1:
|
||||||
strickler = f.get_friction(profile.rk)[0]
|
for f in frictions:
|
||||||
|
if f.contains_rk(profile.rk):
|
||||||
|
strickler = f.get_friction(profile.rk)[0]
|
||||||
if strickler is None:
|
if strickler is None:
|
||||||
strickler = 25.0
|
strickler = 25.0
|
||||||
|
|
||||||
if not compute_discharge:
|
if not compute_discharge:
|
||||||
discharge = data_discharge[profile.rk]
|
if profile.rk in data_discharge:
|
||||||
|
discharge = data_discharge[profile.rk]
|
||||||
|
else:
|
||||||
|
discharge = 0.0
|
||||||
else:
|
else:
|
||||||
discharge = (
|
discharge = (
|
||||||
((width * 0.8)
|
# ((width * 0.8)
|
||||||
* strickler
|
# * strickler
|
||||||
* (height ** (5/3))
|
# * (height ** (5/3))
|
||||||
|
# * (abs(incline) ** (0.5)))
|
||||||
|
(area * strickler
|
||||||
|
* (radius ** (2/3))
|
||||||
* (abs(incline) ** (0.5)))
|
* (abs(incline) ** (0.5)))
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -423,6 +433,8 @@ class InitialConditions(SQLSubModel):
|
|||||||
def generate_discharge(self, discharge: float, compute_height: bool):
|
def generate_discharge(self, discharge: float, compute_height: bool):
|
||||||
|
|
||||||
profiles = self._reach.reach.profiles.copy()
|
profiles = self._reach.reach.profiles.copy()
|
||||||
|
if profiles is None:
|
||||||
|
return None
|
||||||
profiles.reverse()
|
profiles.reverse()
|
||||||
|
|
||||||
previous_elevation = -99999.99
|
previous_elevation = -99999.99
|
||||||
@@ -443,20 +455,28 @@ class InitialConditions(SQLSubModel):
|
|||||||
width = profile.width_approximation()
|
width = profile.width_approximation()
|
||||||
frictions = self._reach.frictions.frictions
|
frictions = self._reach.frictions.frictions
|
||||||
strickler = None
|
strickler = None
|
||||||
for f in frictions:
|
if frictions is not None:
|
||||||
if f.contains_rk(profile.rk):
|
if len(frictions) >= 1:
|
||||||
strickler = f.get_friction(profile.rk)[0]
|
for f in frictions:
|
||||||
|
if f.contains_rk(profile.rk):
|
||||||
|
strickler = f.get_friction(profile.rk)[0]
|
||||||
if strickler is None:
|
if strickler is None:
|
||||||
strickler = 25.0
|
strickler = 25.0
|
||||||
|
|
||||||
if not compute_height:
|
if not compute_height:
|
||||||
height = data_height[profile.rk]
|
if profile.rk in data_height:
|
||||||
|
height = data_height[profile.rk]
|
||||||
|
else:
|
||||||
|
height = 0.0
|
||||||
else:
|
else:
|
||||||
height = (
|
if abs(incline) <= 0:
|
||||||
discharge
|
height = 0.0
|
||||||
/
|
else:
|
||||||
((width * 0.8) * strickler * (abs(incline) ** (0.5)))
|
height = (
|
||||||
) ** (0.6)
|
discharge
|
||||||
|
/
|
||||||
|
((width * 0.8) * strickler * (abs(incline) ** (0.5)))
|
||||||
|
) ** (0.6)
|
||||||
|
|
||||||
elevation = max(
|
elevation = max(
|
||||||
profile.z_min() + height,
|
profile.z_min() + height,
|
||||||
@@ -499,7 +519,10 @@ class InitialConditions(SQLSubModel):
|
|||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
|
|
||||||
if not compute_discharge:
|
if not compute_discharge:
|
||||||
d = data_discharge[profile.rk]
|
if profile.rk in data_discharge:
|
||||||
|
d = data_discharge[profile.rk]
|
||||||
|
else:
|
||||||
|
d = 0.0
|
||||||
else:
|
else:
|
||||||
d = discharge
|
d = discharge
|
||||||
elevation = interp(profile.rk,
|
elevation = interp(profile.rk,
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class InitialConditionsAdisTS(SQLSubModel):
|
|||||||
|
|
||||||
InitialConditionsAdisTS._id_cnt = max(
|
InitialConditionsAdisTS._id_cnt = max(
|
||||||
InitialConditionsAdisTS._id_cnt + 1,
|
InitialConditionsAdisTS._id_cnt + 1,
|
||||||
self.id
|
self.id + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||||||
self._rate = None
|
self._rate = None
|
||||||
self._enabled = True
|
self._enabled = True
|
||||||
|
|
||||||
ICAdisTSSpec._id_cnt = max(ICAdisTSSpec._id_cnt + 1, self.id)
|
ICAdisTSSpec._id_cnt = max(ICAdisTSSpec._id_cnt + 1, self.id + 1)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class LateralContribution(SQLSubModel):
|
|||||||
self._types = [float, float]
|
self._types = [float, float]
|
||||||
|
|
||||||
LateralContribution._id_cnt = max(
|
LateralContribution._id_cnt = max(
|
||||||
LateralContribution._id_cnt + 1, self.id)
|
LateralContribution._id_cnt + 1, self.id + 1)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|||||||
@@ -31,11 +31,12 @@ class Edge(object):
|
|||||||
self._status = status
|
self._status = status
|
||||||
|
|
||||||
if id == -1:
|
if id == -1:
|
||||||
type(self)._id_cnt += 1
|
|
||||||
self.id = type(self)._id_cnt
|
self.id = type(self)._id_cnt
|
||||||
else:
|
else:
|
||||||
self.id = id
|
self.id = id
|
||||||
|
|
||||||
|
type(self)._id_cnt = max(self.id + 1, type(self)._id_cnt + 1)
|
||||||
|
|
||||||
self._name = name
|
self._name = name
|
||||||
|
|
||||||
self.node1 = node1
|
self.node1 = node1
|
||||||
|
|||||||
@@ -30,11 +30,12 @@ class Node(object):
|
|||||||
self._status = status
|
self._status = status
|
||||||
|
|
||||||
if id == -1:
|
if id == -1:
|
||||||
type(self)._id_cnt += 1
|
|
||||||
self.id = type(self)._id_cnt
|
self.id = type(self)._id_cnt
|
||||||
else:
|
else:
|
||||||
self.id = id
|
self.id = id
|
||||||
|
|
||||||
|
type(self)._id_cnt = max(self.id + 1, type(self)._id_cnt + 1)
|
||||||
|
|
||||||
self._name = name
|
self._name = name
|
||||||
self.pos = Point(x, y)
|
self.pos = Point(x, y)
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class OutputRKAdists(SQLSubModel):
|
|||||||
self._enabled = True
|
self._enabled = True
|
||||||
|
|
||||||
OutputRKAdists._id_cnt = max(
|
OutputRKAdists._id_cnt = max(
|
||||||
OutputRKAdists._id_cnt + 1, self.id)
|
OutputRKAdists._id_cnt + 1, self.id + 1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def reach(self):
|
def reach(self):
|
||||||
|
|||||||
@@ -45,13 +45,16 @@ class Pollutants(SQLSubModel):
|
|||||||
else:
|
else:
|
||||||
self.id = id
|
self.id = id
|
||||||
|
|
||||||
self._name = str(name)
|
if name is None or name == "":
|
||||||
|
self.name = f"pol{self.id}"
|
||||||
|
else:
|
||||||
|
self._name = str(name)
|
||||||
self._enabled = True
|
self._enabled = True
|
||||||
|
|
||||||
self._data = []
|
self._data = []
|
||||||
|
|
||||||
Pollutants._id_cnt = max(
|
Pollutants._id_cnt = max(
|
||||||
Pollutants._id_cnt + 1, self.id)
|
Pollutants._id_cnt + 1, self.id + 1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@@ -179,7 +182,6 @@ class Pollutants(SQLSubModel):
|
|||||||
|
|
||||||
def new_from_data(self, data):
|
def new_from_data(self, data):
|
||||||
|
|
||||||
print("from_data before : ", data)
|
|
||||||
try:
|
try:
|
||||||
new = [int(data[0])]
|
new = [int(data[0])]
|
||||||
new += [float(d) for d in data[1:]]
|
new += [float(d) for d in data[1:]]
|
||||||
@@ -187,8 +189,6 @@ class Pollutants(SQLSubModel):
|
|||||||
logger.error(e)
|
logger.error(e)
|
||||||
new = None
|
new = None
|
||||||
|
|
||||||
print("from_data after : ", new)
|
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class REPLine(SQLSubModel):
|
|||||||
self._line = line
|
self._line = line
|
||||||
self._solvers = solvers
|
self._solvers = solvers
|
||||||
|
|
||||||
REPLine._id_cnt = max(id, REPLine._id_cnt+1)
|
REPLine._id_cnt = max(self.id + 1, REPLine._id_cnt + 1)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
value = None
|
value = None
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class Reservoir(SQLSubModel):
|
|||||||
self._node = None
|
self._node = None
|
||||||
self._data = []
|
self._data = []
|
||||||
|
|
||||||
Reservoir._id_cnt = max(Reservoir._id_cnt + 1, self.id)
|
Reservoir._id_cnt = max(Reservoir._id_cnt + 1, self.id + 1)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
@@ -97,7 +97,7 @@ class Reservoir(SQLSubModel):
|
|||||||
new_reservoir._node = next(
|
new_reservoir._node = next(
|
||||||
filter(
|
filter(
|
||||||
lambda n: n.id == node_id, data["nodes"]
|
lambda n: n.id == node_id, data["nodes"]
|
||||||
)
|
), None
|
||||||
)
|
)
|
||||||
|
|
||||||
new_data = []
|
new_data = []
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ class Results(object):
|
|||||||
def set(self, key, value):
|
def set(self, key, value):
|
||||||
self._meta_data[key] = value
|
self._meta_data[key] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_valid(self):
|
||||||
|
return ("timestamps" in self._meta_data)
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
return self._meta_data[key]
|
return self._meta_data[key]
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,10 @@ class Profile(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_ts_key(self, timestamp, key):
|
def get_ts_key(self, timestamp, key):
|
||||||
return self._data[timestamp][key]
|
if timestamp in self._data:
|
||||||
|
if key in self._data[timestamp]:
|
||||||
|
return self._data[timestamp][key]
|
||||||
|
return None
|
||||||
|
|
||||||
def has_sediment(self):
|
def has_sediment(self):
|
||||||
return any(map(lambda ts: "sl" in self._data[ts], self._data))
|
return any(map(lambda ts: "sl" in self._data[ts], self._data))
|
||||||
@@ -74,6 +77,12 @@ class Reach(object):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._profile_mask = list(
|
||||||
|
map(
|
||||||
|
lambda p: p.name[0:8] != 'interpol', self._profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._profiles)
|
return len(self._profiles)
|
||||||
|
|
||||||
@@ -89,6 +98,10 @@ class Reach(object):
|
|||||||
def profiles(self):
|
def profiles(self):
|
||||||
return self._profiles.copy()
|
return self._profiles.copy()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def profile_mask(self):
|
||||||
|
return self._profile_mask
|
||||||
|
|
||||||
def profile(self, id):
|
def profile(self, id):
|
||||||
return self._profiles[id]
|
return self._profiles[id]
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class Layer(SQLSubModel):
|
|||||||
else:
|
else:
|
||||||
self.id = id
|
self.id = id
|
||||||
|
|
||||||
Layer._id_cnt = max(id, Layer._id_cnt+1)
|
Layer._id_cnt = max(self.id + 1, Layer._id_cnt + 1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@@ -277,18 +277,19 @@ class SedimentLayer(SQLSubModel):
|
|||||||
"FROM sedimentary_layer "
|
"FROM sedimentary_layer "
|
||||||
)
|
)
|
||||||
|
|
||||||
for row in table:
|
if table is not None:
|
||||||
sl = cls(
|
for row in table:
|
||||||
id=row[0],
|
sl = cls(
|
||||||
name=row[1],
|
id=row[0],
|
||||||
comment=row[2],
|
name=row[1],
|
||||||
status=data['status']
|
comment=row[2],
|
||||||
)
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
data["sl"] = sl.id
|
data["sl"] = sl.id
|
||||||
sl._layers = Layer._db_load(execute, data)
|
sl._layers = Layer._db_load(execute, data)
|
||||||
|
|
||||||
new.append(sl)
|
new.append(sl)
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -276,7 +276,8 @@ class Study(SQLModel):
|
|||||||
version = new.execute(
|
version = new.execute(
|
||||||
"SELECT value FROM info WHERE key='study_release'"
|
"SELECT value FROM info WHERE key='study_release'"
|
||||||
)
|
)
|
||||||
new.status.version = int(version[0])
|
if version is not None:
|
||||||
|
new.status.version = int(version[0])
|
||||||
|
|
||||||
# TODO: Load metadata
|
# TODO: Load metadata
|
||||||
new.name = new.execute("SELECT value FROM info WHERE key='name'")[0]
|
new.name = new.execute("SELECT value FROM info WHERE key='name'")[0]
|
||||||
|
|||||||
+206
-13
@@ -108,6 +108,187 @@ class AdisTS(CommandLineSolver):
|
|||||||
name = self._study.name
|
name = self._study.name
|
||||||
return f"{name}.TRA"
|
return f"{name}.TRA"
|
||||||
|
|
||||||
|
def _export_ST(self, study, repertory, qlog, name="0"):
|
||||||
|
files = []
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export ST file")
|
||||||
|
|
||||||
|
os.makedirs(os.path.join(repertory, "net"), exist_ok=True)
|
||||||
|
|
||||||
|
# Write header
|
||||||
|
edges = study.river.enable_edges()
|
||||||
|
for edge in edges:
|
||||||
|
name = f"Reach_{edge.id + 1:>3}".replace(" ", "0")
|
||||||
|
|
||||||
|
with adists_file_open(
|
||||||
|
os.path.join(repertory, "net", f"{name}.ST"),
|
||||||
|
"w+"
|
||||||
|
) as f:
|
||||||
|
files.append(str(os.path.join("net", f"{name}.ST")))
|
||||||
|
|
||||||
|
cnt_num = 1
|
||||||
|
for profile in edge.reach.profiles:
|
||||||
|
self._export_ST_profile_header(
|
||||||
|
f, files, profile, cnt_num
|
||||||
|
)
|
||||||
|
cnt_num += 1
|
||||||
|
|
||||||
|
# Points
|
||||||
|
for point in profile.points:
|
||||||
|
self._export_ST_point_line(
|
||||||
|
f, files, point
|
||||||
|
)
|
||||||
|
|
||||||
|
# Profile last line
|
||||||
|
f.write(f" 999.9990 999.9990 999.9990\n")
|
||||||
|
|
||||||
|
def _export_ST_profile_header(self, wfile, files,
|
||||||
|
profile, cnt):
|
||||||
|
num = f"{cnt:>6}"
|
||||||
|
c1 = f"{profile.code1:>6}"
|
||||||
|
c2 = f"{profile.code2:>6}"
|
||||||
|
t = f"{len(profile.points):>6}"
|
||||||
|
rk = f"{profile.rk:>12f}"[0:12]
|
||||||
|
pname = profile.name
|
||||||
|
if profile.name == "":
|
||||||
|
# Generate name from profile id prefixed with
|
||||||
|
# 'p' (and replace space char with '0' char)
|
||||||
|
pname = f"p{profile.id:>3}".replace(" ", "0")
|
||||||
|
name = f"{pname:<19}"
|
||||||
|
|
||||||
|
# Generate sediment additional data if available
|
||||||
|
sediment = ""
|
||||||
|
if profile.sl is not None:
|
||||||
|
if not any(filter(lambda f: ".GRA" in f, files)):
|
||||||
|
files.append(self._gra_file)
|
||||||
|
|
||||||
|
# Number of layers
|
||||||
|
nl = len(profile.sl)
|
||||||
|
sediment = f" {nl:>3}"
|
||||||
|
|
||||||
|
# Layers data
|
||||||
|
for layer in profile.sl.layers:
|
||||||
|
sediment += (
|
||||||
|
f" {layer.height:>10} {layer.d50:>10} " +
|
||||||
|
f"{layer.sigma:>10} " +
|
||||||
|
f"{layer.critical_constraint:>10}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Profile header line
|
||||||
|
wfile.write(f"{num}{c1}{c2}{t} {rk} {pname} {sediment}\n")
|
||||||
|
|
||||||
|
def _export_ST_point_line(self, wfile, files, point):
|
||||||
|
x = f"{point.x:<12.4f}"[0:12]
|
||||||
|
y = f"{point.y:<12.4f}"[0:12]
|
||||||
|
z = f"{point.z:<12.4f}"[0:12]
|
||||||
|
n = f"{point.name:<3}"
|
||||||
|
|
||||||
|
# Generate sediment additional data if available
|
||||||
|
sediment = ""
|
||||||
|
prev = point.z
|
||||||
|
if point.sl is not None:
|
||||||
|
# Number of layers
|
||||||
|
nl = len(point.sl)
|
||||||
|
sediment = f"{nl:>3}"
|
||||||
|
|
||||||
|
# Layers data
|
||||||
|
for layer in point.sl.layers:
|
||||||
|
prev = round(prev - layer.height, 5)
|
||||||
|
sediment += (
|
||||||
|
f" {prev:>10} {layer.d50:>10} " +
|
||||||
|
f"{layer.sigma:>10} " +
|
||||||
|
f"{layer.critical_constraint:>10}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Point line
|
||||||
|
wfile.write(f"{x} {y} {z} {n} {sediment}\n")
|
||||||
|
|
||||||
|
def _export_NET(self, study, repertory, qlog=None, name="0"):
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export NET file")
|
||||||
|
|
||||||
|
with adists_file_open(
|
||||||
|
os.path.join(repertory, f"{name}.NET"), "w+") as f:
|
||||||
|
edges = study.river.enable_edges()
|
||||||
|
|
||||||
|
for e in edges:
|
||||||
|
name = f"Reach_{e.id + 1:>3}".replace(" ", "0")
|
||||||
|
id = name
|
||||||
|
|
||||||
|
n1 = f"{e.node1.id:3}".replace(" ", "x")
|
||||||
|
n2 = f"{e.node2.id:3}".replace(" ", "x")
|
||||||
|
file = os.path.join("net", name + ".ST")
|
||||||
|
|
||||||
|
f.write(f"{id} {n1} {n2} {file}\n")
|
||||||
|
|
||||||
|
def _export_fake_INI(self, study, repertory, qlog=None, name="0"):
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export fake INI file")
|
||||||
|
|
||||||
|
with adists_file_open(
|
||||||
|
os.path.join(
|
||||||
|
repertory, "Mage_fin.ini"
|
||||||
|
), "w+"
|
||||||
|
) as f:
|
||||||
|
edges = study.river.enable_edges()
|
||||||
|
for i, edge in enumerate(edges):
|
||||||
|
lst = list(filter(
|
||||||
|
lambda f: f.is_full_defined(),
|
||||||
|
edge.frictions.frictions
|
||||||
|
))
|
||||||
|
rk_min = 9999999.9
|
||||||
|
rk_max = -9999999.9
|
||||||
|
coeff_min = -1.0
|
||||||
|
coeff_max = -1.0
|
||||||
|
for s in lst: # TODO optimise ?
|
||||||
|
if s.begin_rk > rk_max:
|
||||||
|
rk_max = s.begin_rk
|
||||||
|
coeff_max = s.begin_strickler
|
||||||
|
if s.begin_rk < rk_min:
|
||||||
|
rk_min = s.begin_rk
|
||||||
|
coeff_min = s.begin_strickler
|
||||||
|
if s.end_rk > rk_max:
|
||||||
|
rk_max = s.end_rk
|
||||||
|
coeff_max = s.end_strickler
|
||||||
|
if s.end_rk < rk_min:
|
||||||
|
rk_min = s.end_rk
|
||||||
|
coeff_min = s.end_strickler
|
||||||
|
|
||||||
|
print("min max", rk_min, rk_max)
|
||||||
|
|
||||||
|
def get_stricklers_from_rk(rk, lst):
|
||||||
|
print("rk", rk)
|
||||||
|
|
||||||
|
coeff = None
|
||||||
|
if rk > rk_max:
|
||||||
|
coeff = coeff_max
|
||||||
|
elif rk < rk_min:
|
||||||
|
coeff = coeff_min
|
||||||
|
else:
|
||||||
|
for s in lst:
|
||||||
|
if (rk >= s.begin_rk and rk <= s.end_rk or
|
||||||
|
rk <= s.begin_rk and rk >= s.end_rk):
|
||||||
|
coeff = s.begin_strickler # TODO: inerpolate
|
||||||
|
break
|
||||||
|
|
||||||
|
# TODO interpolation if rk is not in frictons
|
||||||
|
|
||||||
|
if coeff is None:
|
||||||
|
logger.error(
|
||||||
|
"Study frictions are not fully defined"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
return coeff.minor, coeff.medium
|
||||||
|
|
||||||
|
for j, profile in enumerate(edge.reach.profiles):
|
||||||
|
coef_min, coef_moy = get_stricklers_from_rk(profile.rk,
|
||||||
|
lst)
|
||||||
|
f.write(
|
||||||
|
f" {i+1:3}{j+1:4}{' '*116}{coef_min:9}{coef_moy:9}\n")
|
||||||
|
|
||||||
def _export_REP_additional_lines(self, study, rep_file):
|
def _export_REP_additional_lines(self, study, rep_file):
|
||||||
lines = filter(
|
lines = filter(
|
||||||
lambda line: line.is_enabled(),
|
lambda line: line.is_enabled(),
|
||||||
@@ -128,9 +309,9 @@ class AdisTS(CommandLineSolver):
|
|||||||
repertory, f"{name}.REP"
|
repertory, f"{name}.REP"
|
||||||
), "w+"
|
), "w+"
|
||||||
) as f:
|
) as f:
|
||||||
|
path = os.path.join("..", mage_rep, name)
|
||||||
f.write(f"NET ../{mage_rep}/{name}.NET\n")
|
f.write(f"NET {name}.NET\n")
|
||||||
f.write(f"REP ../{mage_rep}/{name}.REP\n")
|
f.write(f"REP {path}.REP\n")
|
||||||
|
|
||||||
for file in files:
|
for file in files:
|
||||||
EXT = file.split('.')[1]
|
EXT = file.split('.')[1]
|
||||||
@@ -138,13 +319,25 @@ class AdisTS(CommandLineSolver):
|
|||||||
|
|
||||||
self._export_REP_additional_lines(study, f)
|
self._export_REP_additional_lines(study, f)
|
||||||
|
|
||||||
path_mage_net = os.path.join(os.path.abspath(
|
self._export_ST(study, repertory, qlog, name=name)
|
||||||
os.path.join(repertory, os.pardir)
|
self._export_NET(study, repertory, qlog, name=name)
|
||||||
), f"{mage_rep}/net")
|
|
||||||
path_adists_net = os.path.join(repertory, "net")
|
|
||||||
|
|
||||||
if os.path.exists(path_mage_net):
|
# fake mage_fin.ini:
|
||||||
shutil.copytree(path_mage_net, path_adists_net, dirs_exist_ok=True)
|
|
||||||
|
path_mage = os.path.join(os.path.abspath(
|
||||||
|
os.path.join(repertory, os.pardir)), mage_rep)
|
||||||
|
self._export_fake_INI(study, path_mage,
|
||||||
|
qlog, name=name)
|
||||||
|
|
||||||
|
# path_mage_net = os.path.join(os.path.abspath(
|
||||||
|
# os.path.join(repertory, os.pardir)
|
||||||
|
# ), os.path.join(mage_rep, "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
|
@timer
|
||||||
def export(self, study, repertory, qlog=None):
|
def export(self, study, repertory, qlog=None):
|
||||||
@@ -197,7 +390,7 @@ class AdisTS(CommandLineSolver):
|
|||||||
_nodes_views = set()
|
_nodes_views = set()
|
||||||
|
|
||||||
def get_reach_name(self, reach):
|
def get_reach_name(self, reach):
|
||||||
return f"Reach_{reach.id:>3}".replace(" ", "0")
|
return f"Reach_{reach.id + 1:>3}".replace(" ", "0")
|
||||||
|
|
||||||
def get_node_name(self, node):
|
def get_node_name(self, node):
|
||||||
"""Generate a 3 char name for node
|
"""Generate a 3 char name for node
|
||||||
@@ -338,9 +531,9 @@ class AdisTSwc(AdisTS):
|
|||||||
) as f:
|
) as f:
|
||||||
for LC in POL_LC:
|
for LC in POL_LC:
|
||||||
reach = next(filter(
|
reach = next(filter(
|
||||||
lambda edge: edge.id == LC.edge, study.river.edges()
|
lambda edge: edge.id == LC.edge, study.river.enable_edges()
|
||||||
)) # .name
|
)) # .name
|
||||||
reach_name = self.get_reach_name(self, reach)
|
reach_name = self.get_reach_name(reach)
|
||||||
f.write(f"${reach_name} {LC.begin_rk} {LC.end_rk}\n")
|
f.write(f"${reach_name} {LC.begin_rk} {LC.end_rk}\n")
|
||||||
f.write(f"*temps |débit massique (kg/s)\n")
|
f.write(f"*temps |débit massique (kg/s)\n")
|
||||||
f.write(f"*---------++++++++++\n")
|
f.write(f"*---------++++++++++\n")
|
||||||
@@ -729,7 +922,7 @@ class AdisTSwc(AdisTS):
|
|||||||
data_tmp = {}
|
data_tmp = {}
|
||||||
|
|
||||||
for file_bin in path_files:
|
for file_bin in path_files:
|
||||||
key_pol = file_bin.split("/")[-1][0:-4]
|
key_pol = os.path.basename(file_bin)[0:-4]
|
||||||
data_tmp[key_pol] = {}
|
data_tmp[key_pol] = {}
|
||||||
with open(file_bin, 'rb') as f:
|
with open(file_bin, 'rb') as f:
|
||||||
# header
|
# header
|
||||||
|
|||||||
+27
-7
@@ -135,7 +135,7 @@ class Mage(CommandLineSolver):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
rep_file.write(line.line)
|
rep_file.write(line.line+"\n")
|
||||||
|
|
||||||
def _export_ST(self, study, repertory, qlog, name="0"):
|
def _export_ST(self, study, repertory, qlog, name="0"):
|
||||||
files = []
|
files = []
|
||||||
@@ -717,7 +717,7 @@ class Mage(CommandLineSolver):
|
|||||||
# RESULTS #
|
# RESULTS #
|
||||||
###########
|
###########
|
||||||
|
|
||||||
def read_bin(self, study, repertory, results, qlog=None, name="0"):
|
def read_bin(self, study, fname, results, qlog=None, name="0"):
|
||||||
return
|
return
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
@@ -728,7 +728,16 @@ class Mage(CommandLineSolver):
|
|||||||
repertory=repertory,
|
repertory=repertory,
|
||||||
name=name,
|
name=name,
|
||||||
)
|
)
|
||||||
self.read_bin(study, repertory, results, qlog, name=name)
|
fname = os.path.join(repertory, f"{name}.BIN")
|
||||||
|
if not os.path.isfile(fname):
|
||||||
|
logger.info(f"Result file {name}.BIN does not exist")
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
self.read_bin(study, fname, results, qlog, name=name)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to read results")
|
||||||
|
logger_exception(e)
|
||||||
|
return None
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@@ -934,8 +943,7 @@ class Mage8(Mage):
|
|||||||
###########
|
###########
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def read_bin(self, study, repertory, results, qlog=None, name="0"):
|
def read_bin(self, study, fname, results, qlog=None, name="0"):
|
||||||
fname = os.path.join(repertory, f"{name}.BIN")
|
|
||||||
logger.info(f"read_bin: Start reading '{fname}' ...")
|
logger.info(f"read_bin: Start reading '{fname}' ...")
|
||||||
|
|
||||||
with mage_file_open(fname, "r") as f:
|
with mage_file_open(fname, "r") as f:
|
||||||
@@ -986,6 +994,7 @@ class Mage8(Mage):
|
|||||||
|
|
||||||
reachs = []
|
reachs = []
|
||||||
iprofiles = {}
|
iprofiles = {}
|
||||||
|
profile_len = []
|
||||||
reach_offset = {}
|
reach_offset = {}
|
||||||
|
|
||||||
data = read_int(2*nb_reach)
|
data = read_int(2*nb_reach)
|
||||||
@@ -1005,6 +1014,7 @@ class Mage8(Mage):
|
|||||||
|
|
||||||
# Profile ID offset
|
# Profile ID offset
|
||||||
reach_offset[r] = i1
|
reach_offset[r] = i1
|
||||||
|
profile_len.append(i2-i1+1)
|
||||||
|
|
||||||
logger.debug(f"read_bin: iprofiles = {iprofiles}")
|
logger.debug(f"read_bin: iprofiles = {iprofiles}")
|
||||||
|
|
||||||
@@ -1033,6 +1043,15 @@ class Mage8(Mage):
|
|||||||
]
|
]
|
||||||
def ip_to_ri(r, i): return i - reach_offset[r]
|
def ip_to_ri(r, i): return i - reach_offset[r]
|
||||||
|
|
||||||
|
# check results and geometry consistency
|
||||||
|
for i, r in enumerate(reachs):
|
||||||
|
lp = len(r.profiles)
|
||||||
|
pl = profile_len[i]
|
||||||
|
if lp != pl:
|
||||||
|
logger.warning(f"geometry reach {i} has {lp} profiles")
|
||||||
|
logger.warning(f"results reach {i} has {pl} values")
|
||||||
|
return
|
||||||
|
|
||||||
ts = set()
|
ts = set()
|
||||||
end = False
|
end = False
|
||||||
while not end:
|
while not end:
|
||||||
@@ -1042,7 +1061,7 @@ class Mage8(Mage):
|
|||||||
f, dtype=np.byte, count=1)).decode()
|
f, dtype=np.byte, count=1)).decode()
|
||||||
data = read_float(n)
|
data = read_float(n)
|
||||||
|
|
||||||
logger.debug(f"read_bin: timestamp = {timestamp} sec")
|
# logger.debug(f"read_bin: timestamp = {timestamp} sec")
|
||||||
ts.add(timestamp)
|
ts.add(timestamp)
|
||||||
|
|
||||||
if key in ["Z", "Q"]:
|
if key in ["Z", "Q"]:
|
||||||
@@ -1066,7 +1085,6 @@ class Mage8(Mage):
|
|||||||
endline()
|
endline()
|
||||||
end = newline().size <= 0
|
end = newline().size <= 0
|
||||||
|
|
||||||
logger.debug(reachs[0].profiles[0]._data)
|
|
||||||
results.set("timestamps", ts)
|
results.set("timestamps", ts)
|
||||||
ts_list = sorted(ts)
|
ts_list = sorted(ts)
|
||||||
logger.info(f"compute tab...")
|
logger.info(f"compute tab...")
|
||||||
@@ -1265,6 +1283,8 @@ class Mage8(Mage):
|
|||||||
name = study.name.replace(" ", "_")
|
name = study.name.replace(" ", "_")
|
||||||
|
|
||||||
results = super(Mage8, self).results(study, repertory, qlog, name=name)
|
results = super(Mage8, self).results(study, repertory, qlog, name=name)
|
||||||
|
if results is None:
|
||||||
|
return None
|
||||||
if with_gra:
|
if with_gra:
|
||||||
self.read_gra(study, repertory, results, qlog, name=name)
|
self.read_gra(study, repertory, results, qlog, name=name)
|
||||||
|
|
||||||
|
|||||||
+333
-40
@@ -1,5 +1,5 @@
|
|||||||
# RubarBE.py -- Pamhyr
|
# RubarBE.py -- Pamhyr
|
||||||
# Copyright (C) 2024 INRAE
|
# Copyright (C) 2024-2025 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
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,7 +20,7 @@ import os
|
|||||||
import logging
|
import logging
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from tools import timer, trace, old_pamhyr_date_to_timestamp
|
from tools import timer, trace, old_pamhyr_date_to_timestamp, logger_exception
|
||||||
|
|
||||||
from Solver.CommandLine import CommandLineSolver
|
from Solver.CommandLine import CommandLineSolver
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ class Rubar3(CommandLineSolver):
|
|||||||
self._type = "rubar3"
|
self._type = "rubar3"
|
||||||
|
|
||||||
self._cmd_input = ""
|
self._cmd_input = ""
|
||||||
self._cmd_solver = "@path @input -o @output"
|
self._cmd_solver = "@path @args @input"
|
||||||
self._cmd_output = ""
|
self._cmd_output = ""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -58,12 +58,12 @@ class Rubar3(CommandLineSolver):
|
|||||||
("rubarbe_iovis", "n"),
|
("rubarbe_iovis", "n"),
|
||||||
("rubarbe_rep", "n"),
|
("rubarbe_rep", "n"),
|
||||||
("rubarbe_tinit", "000:00:00:00"),
|
("rubarbe_tinit", "000:00:00:00"),
|
||||||
("rubarbe_tmax", "999:99:99:00"),
|
("rubarbe_tmax", "000:01:00:00"), # 1 day
|
||||||
("rubarbe_tiopdt", "000:00:00:00"),
|
("rubarbe_tiopdt", "000:00:00:00"),
|
||||||
("rubarbe_dt", "5.0"),
|
("rubarbe_dt", "5.0"),
|
||||||
("rubarbe_ts", "999:99:99:00"),
|
("rubarbe_ts", "999:99:99:00"),
|
||||||
("rubarbe_dtsauv", "00:00:00:05"),
|
("rubarbe_dtsauv", "00:00:05:00"),
|
||||||
("rubarbe_psave", "00:00:00:05"),
|
("rubarbe_psave", "00:00:05:00"),
|
||||||
("rubarbe_fdeb1", "1"),
|
("rubarbe_fdeb1", "1"),
|
||||||
("rubarbe_fdeb2", "10"),
|
("rubarbe_fdeb2", "10"),
|
||||||
("rubarbe_fdeb3", "100"),
|
("rubarbe_fdeb3", "100"),
|
||||||
@@ -73,8 +73,9 @@ class Rubar3(CommandLineSolver):
|
|||||||
("rubarbe_tf_4", "y"),
|
("rubarbe_tf_4", "y"),
|
||||||
("rubarbe_tf_5", "y"),
|
("rubarbe_tf_5", "y"),
|
||||||
("rubarbe_tf_6", "n"),
|
("rubarbe_tf_6", "n"),
|
||||||
("rubarbe_trased", "y"),
|
("rubarbe_trased", "n"),
|
||||||
("rubarbe_optfpc", "0"),
|
("rubarbe_optfpc", "0"),
|
||||||
|
# trased parameters
|
||||||
("rubarbe_ros", "2650.0"),
|
("rubarbe_ros", "2650.0"),
|
||||||
("rubarbe_dm", "0.1"),
|
("rubarbe_dm", "0.1"),
|
||||||
("rubarbe_segma", "1.0"),
|
("rubarbe_segma", "1.0"),
|
||||||
@@ -129,11 +130,11 @@ class Rubar3(CommandLineSolver):
|
|||||||
|
|
||||||
def output_param(self):
|
def output_param(self):
|
||||||
name = self._study.name
|
name = self._study.name
|
||||||
return f"{name}"
|
return f"profil.{name}"
|
||||||
|
|
||||||
def log_file(self):
|
def log_file(self):
|
||||||
name = self._study.name
|
name = self._study.name
|
||||||
return f"{name}"
|
return f"geomac-i.{name}"
|
||||||
|
|
||||||
def export(self, study, repertory, qlog=None):
|
def export(self, study, repertory, qlog=None):
|
||||||
self._study = study
|
self._study = study
|
||||||
@@ -143,10 +144,12 @@ class Rubar3(CommandLineSolver):
|
|||||||
self._export_ts(study, repertory, qlog, name=name)
|
self._export_ts(study, repertory, qlog, name=name)
|
||||||
self._export_geomac_i(study, repertory, qlog, name=name)
|
self._export_geomac_i(study, repertory, qlog, name=name)
|
||||||
self._export_mail(study, repertory, qlog, name=name)
|
self._export_mail(study, repertory, qlog, name=name)
|
||||||
|
self._export_devers(study, repertory, qlog, name=name)
|
||||||
self._export_condin(study, repertory, qlog, name=name)
|
self._export_condin(study, repertory, qlog, name=name)
|
||||||
self._export_stricklers(study, repertory, qlog, name=name)
|
self._export_stricklers(study, repertory, qlog, name=name)
|
||||||
self._export_hydro(study, repertory, qlog, name=name)
|
self._export_hydro(study, repertory, qlog, name=name)
|
||||||
self._export_condav(study, repertory, qlog, name=name)
|
self._export_condav(study, repertory, qlog, name=name)
|
||||||
|
# self._export_abshyd(study, repertory, qlog, name=name)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -166,9 +169,8 @@ class Rubar3(CommandLineSolver):
|
|||||||
|
|
||||||
it = iter(params)
|
it = iter(params)
|
||||||
|
|
||||||
line = 0
|
param = next(it, None)
|
||||||
while line < 29:
|
while param is not None:
|
||||||
param = next(it)
|
|
||||||
name = param.name
|
name = param.name
|
||||||
value = param.value
|
value = param.value
|
||||||
|
|
||||||
@@ -196,12 +198,12 @@ class Rubar3(CommandLineSolver):
|
|||||||
v2 = next(it).value
|
v2 = next(it).value
|
||||||
v3 = next(it).value
|
v3 = next(it).value
|
||||||
|
|
||||||
f.write(f"{v2}{v3}")
|
# f.write(f"{v2}{v3}")
|
||||||
|
|
||||||
# New line
|
# New line
|
||||||
f.write(f"\n")
|
f.write(f"\n")
|
||||||
|
|
||||||
line += 1
|
param = next(it, None)
|
||||||
|
|
||||||
def _export_ts(self, study, repertory, qlog, name="0"):
|
def _export_ts(self, study, repertory, qlog, name="0"):
|
||||||
if qlog is not None:
|
if qlog is not None:
|
||||||
@@ -277,19 +279,20 @@ class Rubar3(CommandLineSolver):
|
|||||||
|
|
||||||
f.write(f"{ind:>4} {rk:>11.3f} {n_points:>4}\n")
|
f.write(f"{ind:>4} {rk:>11.3f} {n_points:>4}\n")
|
||||||
|
|
||||||
for point in profile.points:
|
station = profile.get_station()
|
||||||
|
for i, point in enumerate(profile.points):
|
||||||
label = point.name.lower()
|
label = point.name.lower()
|
||||||
if label != "":
|
if label != "":
|
||||||
if label[0] == "r":
|
if label[0] == "r":
|
||||||
label = label[1].upper()
|
label = label[1].upper()
|
||||||
else:
|
else:
|
||||||
label = label[1].upper()
|
label = " "
|
||||||
else:
|
else:
|
||||||
label = " "
|
label = " "
|
||||||
|
|
||||||
y = point.y
|
y = station[i]
|
||||||
z = point.z
|
z = point.z
|
||||||
dcs = 0.001
|
dcs = 1.0
|
||||||
scs = 1.0
|
scs = 1.0
|
||||||
tmcs = 0.0
|
tmcs = 0.0
|
||||||
|
|
||||||
@@ -329,6 +332,50 @@ class Rubar3(CommandLineSolver):
|
|||||||
if ind % 3 != 0:
|
if ind % 3 != 0:
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
|
def _export_abshyd(self, study, repertory, qlog, name="0"):
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export ABSHYD file")
|
||||||
|
|
||||||
|
with open(
|
||||||
|
os.path.join(
|
||||||
|
repertory, f"abshyd.{name}"
|
||||||
|
), "w+"
|
||||||
|
) as f:
|
||||||
|
reach_ind = 1
|
||||||
|
for edge in study.river.enable_edges():
|
||||||
|
reach = edge.reach
|
||||||
|
lm = len(reach) + 1
|
||||||
|
f.write(f"{lm:>13}\n")
|
||||||
|
|
||||||
|
ind = 1
|
||||||
|
for mail in reach.inter_profiles_rk():
|
||||||
|
f.write(f"{ind:>4} {mail:15.3f} {reach_ind:>4}\n")
|
||||||
|
ind += 1
|
||||||
|
|
||||||
|
reach_ind += 1
|
||||||
|
|
||||||
|
def _export_devers(self, study, repertory, qlog, name="0"):
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export DEVERS file")
|
||||||
|
|
||||||
|
with open(
|
||||||
|
os.path.join(
|
||||||
|
repertory, f"devers.{name}"
|
||||||
|
), "w+"
|
||||||
|
) as f:
|
||||||
|
reach_ind = 1
|
||||||
|
for edge in study.river.enable_edges():
|
||||||
|
reach = edge.reach
|
||||||
|
lm = len(reach) + 1
|
||||||
|
f.write(f"{lm:>13}\n")
|
||||||
|
|
||||||
|
ind = 1
|
||||||
|
for mail in reach.inter_profiles_rk():
|
||||||
|
f.write(f"{ind:>4} {0.0:15.3f} {0.0:15.3f} {1.0:>15.3f}\n")
|
||||||
|
ind += 1
|
||||||
|
|
||||||
|
reach_ind += 1
|
||||||
|
|
||||||
def _export_stricklers(self, study, repertory, qlog, name="0"):
|
def _export_stricklers(self, study, repertory, qlog, name="0"):
|
||||||
self._export_frot(study, repertory, qlog, name=name, version="")
|
self._export_frot(study, repertory, qlog, name=name, version="")
|
||||||
self._export_frot(study, repertory, qlog, name=name, version="2")
|
self._export_frot(study, repertory, qlog, name=name, version="2")
|
||||||
@@ -347,25 +394,58 @@ class Rubar3(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):
|
lst = list(filter(
|
||||||
return next(
|
lambda f: f.is_full_defined(),
|
||||||
map(
|
edge.frictions.frictions
|
||||||
lambda s: (
|
))
|
||||||
s.begin_strickler.medium if version == "2"
|
|
||||||
else s.begin_strickler.minor
|
rk_min = 9999999.9
|
||||||
),
|
rk_max = -9999999.9
|
||||||
filter(
|
coeff_min = -1.0
|
||||||
lambda f: rk in f,
|
coeff_max = -1.0
|
||||||
edge.frictions.lst
|
for s in lst: # TODO optimise ?
|
||||||
)
|
if s.begin_rk > rk_max:
|
||||||
|
rk_max = s.begin_rk
|
||||||
|
coeff_max = s.begin_strickler
|
||||||
|
if s.begin_rk < rk_min:
|
||||||
|
rk_min = s.begin_rk
|
||||||
|
coeff_min = s.begin_strickler
|
||||||
|
if s.end_rk > rk_max:
|
||||||
|
rk_max = s.end_rk
|
||||||
|
coeff_max = s.end_strickler
|
||||||
|
if s.end_rk < rk_min:
|
||||||
|
rk_min = s.end_rk
|
||||||
|
coeff_min = s.end_strickler
|
||||||
|
|
||||||
|
def get_stricklers_from_rk(rk, lst):
|
||||||
|
|
||||||
|
coeff = None
|
||||||
|
if rk > rk_max:
|
||||||
|
coeff = coeff_max
|
||||||
|
elif rk < rk_min:
|
||||||
|
coeff = coeff_min
|
||||||
|
else:
|
||||||
|
for s in lst:
|
||||||
|
if (rk >= s.begin_rk and rk <= s.end_rk or
|
||||||
|
rk <= s.begin_rk and rk >= s.end_rk):
|
||||||
|
coeff = s.begin_strickler # TODO: inerpolate
|
||||||
|
break
|
||||||
|
|
||||||
|
# TODO interpolation if rk is not in frictons
|
||||||
|
|
||||||
|
if coeff is None:
|
||||||
|
logger.error(
|
||||||
|
"Study frictions are not fully defined"
|
||||||
)
|
)
|
||||||
)
|
return None
|
||||||
|
|
||||||
|
return coeff.medium if version == "2" else coeff.minor
|
||||||
|
|
||||||
ind = 1
|
ind = 1
|
||||||
for mail in edge.reach.inter_profiles_rk():
|
for mail in edge.reach.inter_profiles_rk():
|
||||||
coef = get_stricklers_from_rk(mail)
|
coef = get_stricklers_from_rk(mail, lst)
|
||||||
|
if coef is not None:
|
||||||
f.write(f"{ind:>6} {coef:>12.5f}")
|
f.write(f"{ind:>6} {coef:>12.5f}")
|
||||||
|
|
||||||
ind += 1
|
ind += 1
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
@@ -382,7 +462,7 @@ class Rubar3(CommandLineSolver):
|
|||||||
for edge in study.river.enable_edges():
|
for edge in study.river.enable_edges():
|
||||||
reach = edge.reach
|
reach = edge.reach
|
||||||
|
|
||||||
f.write(f"0.0\n")
|
f.write(f"{0.0}\n")
|
||||||
|
|
||||||
ics = study.river.initial_conditions.get(edge)
|
ics = study.river.initial_conditions.get(edge)
|
||||||
data = self._export_condin_init_data(ics)
|
data = self._export_condin_init_data(ics)
|
||||||
@@ -391,7 +471,9 @@ class Rubar3(CommandLineSolver):
|
|||||||
first = profiles[0]
|
first = profiles[0]
|
||||||
last = profiles[-1]
|
last = profiles[-1]
|
||||||
|
|
||||||
|
# if first not in data or last not in data:
|
||||||
if first.rk not in data or last.rk not in data:
|
if first.rk not in data or last.rk not in data:
|
||||||
|
print(data)
|
||||||
logger.error(
|
logger.error(
|
||||||
"Study initial condition is not fully defined"
|
"Study initial condition is not fully defined"
|
||||||
)
|
)
|
||||||
@@ -444,10 +526,10 @@ class Rubar3(CommandLineSolver):
|
|||||||
z = data[profile.rk][0]
|
z = data[profile.rk][0]
|
||||||
q = data[profile.rk][1]
|
q = data[profile.rk][1]
|
||||||
|
|
||||||
# height = z - profile.z_min()
|
height = z - profile.z_min()
|
||||||
speed = profile.speed(q, z)
|
speed = profile.speed(q, z)
|
||||||
|
|
||||||
return z, speed
|
return height, speed
|
||||||
|
|
||||||
def _export_hydro(self, study, repertory, qlog, name="0"):
|
def _export_hydro(self, study, repertory, qlog, name="0"):
|
||||||
if qlog is not None:
|
if qlog is not None:
|
||||||
@@ -470,7 +552,7 @@ class Rubar3(CommandLineSolver):
|
|||||||
for bc in bcs:
|
for bc in bcs:
|
||||||
f.write(f"{len(bc)}\n")
|
f.write(f"{len(bc)}\n")
|
||||||
for d0, d1 in bc.data:
|
for d0, d1 in bc.data:
|
||||||
f.write(f"{d0} {d1}\n")
|
f.write(f"{d1} {d0}\n")
|
||||||
|
|
||||||
def _export_condav(self, study, repertory, qlog, name="0"):
|
def _export_condav(self, study, repertory, qlog, name="0"):
|
||||||
if qlog is not None:
|
if qlog is not None:
|
||||||
@@ -492,8 +574,219 @@ class Rubar3(CommandLineSolver):
|
|||||||
|
|
||||||
for bc in bcs:
|
for bc in bcs:
|
||||||
f.write(f"{len(bc)}\n")
|
f.write(f"{len(bc)}\n")
|
||||||
for d0, d1 in bc.data:
|
if bc.bctype == "ZD":
|
||||||
f.write(f"{d0} {d1}\n")
|
for d0, d1 in bc.data:
|
||||||
|
f.write(f"{d1} {d0}\n")
|
||||||
|
else:
|
||||||
|
for d0, d1 in bc.data:
|
||||||
|
f.write(f"{d0} {d1}\n")
|
||||||
|
|
||||||
|
def read_profil(self, study, fname, results, qlog=None, name="0"):
|
||||||
|
logger.info(f"read: profil.{name}")
|
||||||
|
with open(fname, "r") as f:
|
||||||
|
reachs = []
|
||||||
|
for i, edge in enumerate(study.river.enable_edges()):
|
||||||
|
reach = edge.reach
|
||||||
|
# Add results reach to reach list
|
||||||
|
res_reach = results.river.add(i)
|
||||||
|
reachs.append((res_reach, len(reach) + 1))
|
||||||
|
|
||||||
|
def read_data_line(f):
|
||||||
|
line = f.readline().split()
|
||||||
|
if len(line) > 3:
|
||||||
|
return tuple(map(float, line))
|
||||||
|
else:
|
||||||
|
return (0.0, 0.0, 0.0, 0.0)
|
||||||
|
|
||||||
|
def set_and_compute_limites(reach, ind, z, q, s):
|
||||||
|
reach.set(ind, timestamp, "Z", z)
|
||||||
|
reach.set(ind, timestamp, "Q", q)
|
||||||
|
reach.set(ind, timestamp, "V", s)
|
||||||
|
|
||||||
|
profile = reach.profile(ind)
|
||||||
|
limits = profile.geometry.get_water_limits(z)
|
||||||
|
reach.set(
|
||||||
|
ind, timestamp, "water_limits", limits
|
||||||
|
)
|
||||||
|
|
||||||
|
ts = set()
|
||||||
|
timestamp = next(filter(
|
||||||
|
lambda p: p.name == 'rubarbe_tinit',
|
||||||
|
study.river.get_params(self._type).parameters
|
||||||
|
)).value
|
||||||
|
if timestamp.count(':') == 3:
|
||||||
|
timestamp = old_pamhyr_date_to_timestamp(timestamp)
|
||||||
|
ts.add(timestamp)
|
||||||
|
|
||||||
|
# add initial condition
|
||||||
|
for r, edge in enumerate(study.river.enable_edges()):
|
||||||
|
reach = edge.reach
|
||||||
|
ics = study.river.initial_conditions.get(edge)
|
||||||
|
q = ics.get_discharge()
|
||||||
|
z = ics.get_elevation()
|
||||||
|
k = 0
|
||||||
|
for i, j in zip(z, q):
|
||||||
|
v = reach.profiles[k].speed(i, j)
|
||||||
|
set_and_compute_limites(reachs[r][0], k, i, j, v)
|
||||||
|
k += 1
|
||||||
|
|
||||||
|
# start read
|
||||||
|
|
||||||
|
end = False
|
||||||
|
while True:
|
||||||
|
line = f.readline()
|
||||||
|
if line == "":
|
||||||
|
results.set("timestamps", ts)
|
||||||
|
return
|
||||||
|
|
||||||
|
timestamp = float(line)
|
||||||
|
ts.add(timestamp)
|
||||||
|
|
||||||
|
logger.info(f"read: profil.{name}: timestamp = {timestamp}")
|
||||||
|
|
||||||
|
for reach, lm in reachs:
|
||||||
|
# First profile
|
||||||
|
h, s, q, z = read_data_line(f)
|
||||||
|
set_and_compute_limites(reach, 0, z+h, q, s)
|
||||||
|
|
||||||
|
# For each profile
|
||||||
|
ind = 1
|
||||||
|
ph, ps, pq, pz = read_data_line(f)
|
||||||
|
while ind < lm - 2:
|
||||||
|
h, s, q, z = read_data_line(f)
|
||||||
|
set_and_compute_limites(
|
||||||
|
reach, ind,
|
||||||
|
(pz + z + ph + h) / 2,
|
||||||
|
(pq + q) / 2,
|
||||||
|
(ps + s) / 2
|
||||||
|
)
|
||||||
|
|
||||||
|
ph = h
|
||||||
|
ps = s
|
||||||
|
pq = q
|
||||||
|
pz = z
|
||||||
|
ind += 1
|
||||||
|
|
||||||
|
# Last profile
|
||||||
|
h, s, q, z = read_data_line(f)
|
||||||
|
set_and_compute_limites(reach, ind, z+h, q, s)
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def write_bin(self, study, fname, results, qlog=None, name="0"):
|
||||||
|
logger.info(f"write_bin: Start writing '{fname}' ...")
|
||||||
|
|
||||||
|
with open(fname, "wb") as f:
|
||||||
|
def newline(j): return np.asarray([j], dtype=np.int32).tofile(f)
|
||||||
|
def endline(j): return np.asarray([j], dtype=np.int32).tofile(f)
|
||||||
|
|
||||||
|
def write_int(i):
|
||||||
|
newline(len(i)*4)
|
||||||
|
np.array(i, dtype=np.int32).tofile(f)
|
||||||
|
endline(len(i)*4)
|
||||||
|
|
||||||
|
def write_float(i):
|
||||||
|
newline(len(i)*4)
|
||||||
|
np.array(i, dtype=np.float32).tofile(f)
|
||||||
|
endline(len(i)*4)
|
||||||
|
|
||||||
|
def write_float64(i):
|
||||||
|
newline(len(i)*8)
|
||||||
|
np.array(i, dtype=np.float64).tofile(f)
|
||||||
|
endline(len(i)*8)
|
||||||
|
|
||||||
|
def write_float64(i):
|
||||||
|
newline(len(i)*8)
|
||||||
|
np.array(i, dtype=np.float64).tofile(f)
|
||||||
|
endline(len(i)*8)
|
||||||
|
|
||||||
|
def write_data(npts, t, a, val):
|
||||||
|
newline(npts*4 + 13)
|
||||||
|
np.array(npts, dtype=np.int32).tofile(f)
|
||||||
|
np.array(t, dtype=np.float64).tofile(f)
|
||||||
|
np.array(bytearray(a.encode()), dtype=np.byte).tofile(f)
|
||||||
|
np.array(val, dtype=np.float32).tofile(f)
|
||||||
|
endline(npts*4 + 13)
|
||||||
|
|
||||||
|
ts_list = sorted(results.get("timestamps"))
|
||||||
|
profiles = []
|
||||||
|
for r in results.river.reachs:
|
||||||
|
profiles += r.profiles
|
||||||
|
|
||||||
|
# Meta data (1st line)
|
||||||
|
nb_reach = len(results.river)
|
||||||
|
nb_profile = len(profiles)
|
||||||
|
write_int([nb_reach, nb_profile, "82"])
|
||||||
|
|
||||||
|
# Reach information (2nd line)
|
||||||
|
is1 = []
|
||||||
|
is2 = []
|
||||||
|
ltmp = []
|
||||||
|
i = 1
|
||||||
|
for r in results.river.reachs:
|
||||||
|
j = i+len(r)-1
|
||||||
|
ltmp += [i, j]
|
||||||
|
is1.append(i)
|
||||||
|
is2.append(j)
|
||||||
|
i += i+len(r)
|
||||||
|
write_int(ltmp)
|
||||||
|
|
||||||
|
# X (3rd line)
|
||||||
|
rk = []
|
||||||
|
for r in results.river.reachs:
|
||||||
|
rk += r.geometry.get_rk()
|
||||||
|
write_float(rk)
|
||||||
|
|
||||||
|
# Z and Y (4th line)
|
||||||
|
# ltmp = []
|
||||||
|
# for r in results.river.reachs:
|
||||||
|
# for p in r.prifiles:
|
||||||
|
# ltpm.append(p.rk)
|
||||||
|
write_float(3*nb_profile*[0.0])
|
||||||
|
|
||||||
|
# Data
|
||||||
|
|
||||||
|
for timestamp in ts_list:
|
||||||
|
q = list(
|
||||||
|
map(
|
||||||
|
lambda p: p.get_ts_key(timestamp, "Q"),
|
||||||
|
profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
write_data(nb_profile, timestamp, "Q", q)
|
||||||
|
z = list(
|
||||||
|
map(
|
||||||
|
lambda p: p.get_ts_key(timestamp, "Z"),
|
||||||
|
profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
write_data(nb_profile, timestamp, "Z", z)
|
||||||
|
logger.info(f"write_bin: ... end with {len(ts_list)} timestamps")
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def results(self, study, repertory, qlog=None, name="0"):
|
||||||
|
results = Results(
|
||||||
|
study=study,
|
||||||
|
solver=self,
|
||||||
|
repertory=repertory,
|
||||||
|
name=name,
|
||||||
|
)
|
||||||
|
results_file = f"profil.{name}"
|
||||||
|
|
||||||
|
fname = os.path.join(repertory, results_file)
|
||||||
|
if not os.path.isfile(fname):
|
||||||
|
logger.warning(f"Result file {results_file} does not exist")
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
self.read_profil(study, fname, results, qlog, name=name)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to read results")
|
||||||
|
logger_exception(e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
fname = os.path.join(repertory, f"{name}.BIN")
|
||||||
|
self.write_bin(study, fname, results, qlog, name)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
class RubarBE(Rubar3):
|
class RubarBE(Rubar3):
|
||||||
@@ -505,5 +798,5 @@ class RubarBE(Rubar3):
|
|||||||
self._type = "rubarbe"
|
self._type = "rubarbe"
|
||||||
|
|
||||||
self._cmd_input = ""
|
self._cmd_input = ""
|
||||||
self._cmd_solver = "@path @input -o @output"
|
self._cmd_solver = "@path @args @input"
|
||||||
self._cmd_output = ""
|
self._cmd_output = ""
|
||||||
@@ -34,7 +34,7 @@ solver_long_name = {
|
|||||||
# "mage_fake7": "Mage fake v7",
|
# "mage_fake7": "Mage fake v7",
|
||||||
"adistswc": "Adis-TS_WC",
|
"adistswc": "Adis-TS_WC",
|
||||||
# "rubarbe": "RubarBE",
|
# "rubarbe": "RubarBE",
|
||||||
# "rubar3": "Rubar3",
|
"rubar3": "Rubar3",
|
||||||
}
|
}
|
||||||
|
|
||||||
solver_type_list = {
|
solver_type_list = {
|
||||||
@@ -44,5 +44,5 @@ solver_type_list = {
|
|||||||
# "mage_fake7": MageFake7,
|
# "mage_fake7": MageFake7,
|
||||||
"adistswc": AdisTSwc,
|
"adistswc": AdisTSwc,
|
||||||
# "rubarbe": RubarBE,
|
# "rubarbe": RubarBE,
|
||||||
# "rubar3": Rubar3,
|
"rubar3": Rubar3,
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ class AboutWindow(PamhyrDialog):
|
|||||||
|
|
||||||
label = self.get_label_text("label_version")
|
label = self.get_label_text("label_version")
|
||||||
label = label.replace("@version", version)
|
label = label.replace("@version", version)
|
||||||
label = label.replace("@codename", "(Adis-TS)")
|
label = label.replace("@codename", "(Claude François)")
|
||||||
self.set_label_text("label_version", label)
|
self.set_label_text("label_version", label)
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|||||||
@@ -211,3 +211,26 @@ class TableModel(PamhyrTableModel):
|
|||||||
)
|
)
|
||||||
self.layoutAboutToBeChanged.emit()
|
self.layoutAboutToBeChanged.emit()
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
def read_from_file(self, file_name, bctype):
|
||||||
|
|
||||||
|
logger.debug(f"Import boundary conditions from {file_name}")
|
||||||
|
data0 = []
|
||||||
|
data1 = []
|
||||||
|
if bctype == "ZD":
|
||||||
|
mult = 1
|
||||||
|
else:
|
||||||
|
mult = 60
|
||||||
|
with open(file_name, encoding="utf-8") as bc_file:
|
||||||
|
for line in bc_file:
|
||||||
|
if not (line.startswith("#") or
|
||||||
|
line.startswith("*") or
|
||||||
|
line.startswith("$")):
|
||||||
|
line = line.split()
|
||||||
|
if bctype == "ZD":
|
||||||
|
data0.append(float(line[0]))
|
||||||
|
else:
|
||||||
|
data0.append(old_pamhyr_date_to_timestamp(line[0]))
|
||||||
|
data1.append(line[1])
|
||||||
|
|
||||||
|
self.replace_data(data0, data1)
|
||||||
@@ -30,10 +30,10 @@ from PyQt5.QtGui import (
|
|||||||
QKeySequence,
|
QKeySequence,
|
||||||
)
|
)
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore, QtWidgets
|
||||||
from PyQt5.QtCore import (
|
from PyQt5.QtCore import (
|
||||||
Qt, QVariant, QAbstractTableModel, QCoreApplication,
|
Qt, QVariant, QAbstractTableModel, QCoreApplication,
|
||||||
pyqtSlot, pyqtSignal,
|
pyqtSlot, pyqtSignal, QSettings,
|
||||||
)
|
)
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
@@ -198,6 +198,8 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
|||||||
self.find(QAction, "action_add").triggered.connect(self.add)
|
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||||
self.find(QAction, "action_del").triggered.connect(self.delete)
|
self.find(QAction, "action_del").triggered.connect(self.delete)
|
||||||
self.find(QAction, "action_sort").triggered.connect(self.sort)
|
self.find(QAction, "action_sort").triggered.connect(self.sort)
|
||||||
|
self.find(QAction, "action_import").triggered\
|
||||||
|
.connect(self.import_from_file)
|
||||||
self.find(QAction, "action_generate_uniform").triggered.connect(
|
self.find(QAction, "action_generate_uniform").triggered.connect(
|
||||||
self.generate_uniform
|
self.generate_uniform
|
||||||
)
|
)
|
||||||
@@ -293,6 +295,31 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
|||||||
self._table.sort(False)
|
self._table.sort(False)
|
||||||
self.plot.update()
|
self.plot.update()
|
||||||
|
|
||||||
|
def import_from_file(self):
|
||||||
|
options = QFileDialog.Options()
|
||||||
|
settings = QSettings(QSettings.IniFormat,
|
||||||
|
QSettings.UserScope, 'MyOrg', )
|
||||||
|
options |= QFileDialog.DontUseNativeDialog
|
||||||
|
|
||||||
|
if self._data.bctype == "TD":
|
||||||
|
file_types = [self._trad["file_hyd"]]
|
||||||
|
if self._data.bctype == "TZ":
|
||||||
|
file_types = [self._trad["file_lim"]]
|
||||||
|
if self._data.bctype == "ZD":
|
||||||
|
file_types = [self._trad["file_ava"]]
|
||||||
|
file_types.append(self._trad["file_all"])
|
||||||
|
|
||||||
|
file_name, _ = QtWidgets.QFileDialog.getOpenFileName(
|
||||||
|
self,
|
||||||
|
self._trad["open_file"],
|
||||||
|
"",
|
||||||
|
";; ".join(file_types),
|
||||||
|
options=options
|
||||||
|
)
|
||||||
|
|
||||||
|
if file_name != "":
|
||||||
|
self._table.read_from_file(file_name, self._data.bctype)
|
||||||
|
|
||||||
def move_up(self):
|
def move_up(self):
|
||||||
row = self.index_selected_row()
|
row = self.index_selected_row()
|
||||||
self._table.move_up(row)
|
self._table.move_up(row)
|
||||||
@@ -372,8 +399,12 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
|||||||
if strickler is None:
|
if strickler is None:
|
||||||
strickler = 25.0
|
strickler = 25.0
|
||||||
height = [(i)*(z_max-z_min)/50 for i in range(51)]
|
height = [(i)*(z_max-z_min)/50 for i in range(51)]
|
||||||
q = [((profile.wet_width(z_min + h) * 0.8) * strickler
|
# q = [((profile.wet_width(z_min + h) * 0.8) * strickler
|
||||||
* (h ** (5/3)) * (abs(self.slope_value) ** (0.5)))
|
# * (h ** (5/3)) * (abs(self.slope_value) ** (0.5)))
|
||||||
|
# for h in height]
|
||||||
|
q = [profile.wet_area(z_min + h) * strickler
|
||||||
|
* (profile.wet_radius(z_min + h) ** (2/3))
|
||||||
|
* (abs(self.slope_value) ** (0.5))
|
||||||
for h in height]
|
for h in height]
|
||||||
for i in range(len(height)):
|
for i in range(len(height)):
|
||||||
height[i] += z_min
|
height[i] += z_min
|
||||||
|
|||||||
@@ -35,6 +35,17 @@ class BCETranslate(BCTranslate):
|
|||||||
self._dict["Boundary Condition Options"] = _translate(
|
self._dict["Boundary Condition Options"] = _translate(
|
||||||
"BoundaryCondition", "Boundary Condition Options")
|
"BoundaryCondition", "Boundary Condition Options")
|
||||||
|
|
||||||
|
self._dict["open_file"] = _translate(
|
||||||
|
"BoundaryCondition", "Open a file")
|
||||||
|
self._dict["file_hyd"] = _translate(
|
||||||
|
"BoundaryCondition", "Mage hydrograph file (*.HYD)")
|
||||||
|
self._dict["file_lim"] = _translate(
|
||||||
|
"BoundaryCondition", "Mage limnigraph file (*.LIM)")
|
||||||
|
self._dict["file_ava"] = _translate(
|
||||||
|
"BoundaryCondition", "Mage rating curve file (*.AVA)")
|
||||||
|
self._dict["file_all"] = _translate(
|
||||||
|
"BoundaryCondition", "All files (*)")
|
||||||
|
|
||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
"x": _translate("BoundaryCondition", "X"),
|
"x": _translate("BoundaryCondition", "X"),
|
||||||
"y": _translate("BoundaryCondition", "Y"),
|
"y": _translate("BoundaryCondition", "Y"),
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ from PyQt5.QtWidgets import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from View.BoundaryConditionsAdisTS.Edit.UndoCommand import (
|
from View.BoundaryConditionsAdisTS.Edit.UndoCommand import (
|
||||||
AddCommand, DelCommand, SetDataCommand,
|
AddCommand, DelCommand, SetDataCommand, PasteCommand, SortCommand,
|
||||||
)
|
)
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
@@ -118,3 +118,40 @@ class TableModel(PamhyrTableModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.endRemoveRows()
|
self.endRemoveRows()
|
||||||
|
|
||||||
|
def sort(self, _reverse, parent=QModelIndex()):
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
SortCommand(
|
||||||
|
self._data, _reverse
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def paste(self, row, header, data):
|
||||||
|
if len(data) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
PasteCommand(
|
||||||
|
self._data, row,
|
||||||
|
list(
|
||||||
|
map(
|
||||||
|
lambda d: self._data.new_from_data(header, d),
|
||||||
|
data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
# self.auto_sort()
|
||||||
|
self.layoutChanged.emit()
|
||||||
@@ -38,29 +38,14 @@ class SetDataCommand(QUndoCommand):
|
|||||||
self._data = data
|
self._data = data
|
||||||
self._index = index
|
self._index = index
|
||||||
self._column = column
|
self._column = column
|
||||||
self._old = self._data._data[self._index][self._column]
|
self._old = self._data.get_i(self._index)[self._column]
|
||||||
_type = self._data._types[self._column]
|
self._new = new_value
|
||||||
self._new = _type(new_value)
|
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
if self._column == 0:
|
self._data._set_i_c_v(self._index, self._column, self._old)
|
||||||
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):
|
def redo(self):
|
||||||
if self._column == 0:
|
self._data._set_i_c_v(self._index, self._column, self._new)
|
||||||
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):
|
class AddCommand(QUndoCommand):
|
||||||
@@ -76,11 +61,11 @@ class AddCommand(QUndoCommand):
|
|||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
if self._new is None:
|
if self._new is None:
|
||||||
self._new = self._data._data.insert(self._index, (
|
self._new = self._data.insert(self._index, (
|
||||||
self._data._types[0](0), self._data._types[1](0.0)
|
self._data._types[0](0), self._data._types[1](0.0)
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
self._data._data.insert(self._index, self._new)
|
self._data.insert(self._index, self._new)
|
||||||
|
|
||||||
|
|
||||||
class DelCommand(QUndoCommand):
|
class DelCommand(QUndoCommand):
|
||||||
@@ -97,8 +82,57 @@ class DelCommand(QUndoCommand):
|
|||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
for row, el in self._bc:
|
for row, el in self._bc:
|
||||||
self._data._data.insert(row, el)
|
self._data.insert(row, el)
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
for row in self._rows:
|
self._data.delete_i(self._rows)
|
||||||
del self._data._data[row]
|
|
||||||
|
|
||||||
|
class PasteCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, row, bcs):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._bcs = bcs
|
||||||
|
self._bcs.reverse()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._data.delete_i(
|
||||||
|
range(self._row, self._row + len(self._bcs))
|
||||||
|
)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
for bc in self._bcs:
|
||||||
|
self._data.insert(self._row, bc)
|
||||||
|
|
||||||
|
|
||||||
|
class SortCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, _reverse):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._reverse = _reverse
|
||||||
|
|
||||||
|
self._old = self._data.data
|
||||||
|
self._indexes = None
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
ll = self._data.data
|
||||||
|
self._data.sort(
|
||||||
|
key=lambda x: self._indexes[ll.index(x)]
|
||||||
|
)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._data.sort(
|
||||||
|
_reverse=self._reverse,
|
||||||
|
key=lambda x: x[0]
|
||||||
|
)
|
||||||
|
if self._indexes is None:
|
||||||
|
self._indexes = list(
|
||||||
|
map(
|
||||||
|
lambda p: self._old.index(p),
|
||||||
|
self._data.data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._old = None
|
||||||
@@ -143,7 +143,7 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
|||||||
def setup_connections(self):
|
def setup_connections(self):
|
||||||
self.find(QAction, "action_add").triggered.connect(self.add)
|
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||||
self.find(QAction, "action_del").triggered.connect(self.delete)
|
self.find(QAction, "action_del").triggered.connect(self.delete)
|
||||||
|
self.find(QAction, "action_sort").triggered.connect(self.sort)
|
||||||
self._table.dataChanged.connect(self.update)
|
self._table.dataChanged.connect(self.update)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
@@ -200,6 +200,22 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
|||||||
|
|
||||||
self.copyTableIntoClipboard(table)
|
self.copyTableIntoClipboard(table)
|
||||||
|
|
||||||
|
def _paste(self):
|
||||||
|
header, data = self.parseClipboardTable()
|
||||||
|
|
||||||
|
logger.debug(f"paste: h:{header}, d:{data}")
|
||||||
|
|
||||||
|
if len(data) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
row = 0
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(rows) != 0:
|
||||||
|
row = rows[0]
|
||||||
|
|
||||||
|
self._table.paste(row, header, data)
|
||||||
|
self.plot.update()
|
||||||
|
|
||||||
def _undo(self):
|
def _undo(self):
|
||||||
self._table.undo()
|
self._table.undo()
|
||||||
self.plot.update()
|
self.plot.update()
|
||||||
|
|||||||
@@ -119,17 +119,10 @@ class TableModel(PamhyrTableModel):
|
|||||||
|
|
||||||
super(TableModel, self).__init__(trad=trad, **kwargs)
|
super(TableModel, self).__init__(trad=trad, **kwargs)
|
||||||
|
|
||||||
def _setup_lst(self):
|
|
||||||
self._lst = self._bc_list.lst
|
|
||||||
|
|
||||||
def rowCount(self, parent):
|
def rowCount(self, parent):
|
||||||
return len(self._lst)
|
return len(self._bc_list)
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if len(self._lst) != 0:
|
|
||||||
data = self._lst
|
|
||||||
else:
|
|
||||||
data = []
|
|
||||||
|
|
||||||
if role != Qt.ItemDataRole.DisplayRole:
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
return QVariant()
|
return QVariant()
|
||||||
@@ -138,12 +131,12 @@ class TableModel(PamhyrTableModel):
|
|||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
if self._headers[column] == "type":
|
if self._headers[column] == "type":
|
||||||
n = data[row].type
|
n = self._bc_list.get(row).type
|
||||||
if n is None or n == "":
|
if n is None or n == "":
|
||||||
return self._trad["not_associated"]
|
return self._trad["not_associated"]
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] == "node":
|
elif self._headers[column] == "node":
|
||||||
n = data[row].node
|
n = self._bc_list.get(row).node
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad["not_associated"]
|
return self._trad["not_associated"]
|
||||||
tmp = next(filter(lambda x: x.id == n, self._data._nodes), None)
|
tmp = next(filter(lambda x: x.id == n, self._data._nodes), None)
|
||||||
@@ -152,7 +145,7 @@ class TableModel(PamhyrTableModel):
|
|||||||
else:
|
else:
|
||||||
return self._trad["not_associated"]
|
return self._trad["not_associated"]
|
||||||
elif self._headers[column] == "pol":
|
elif self._headers[column] == "pol":
|
||||||
n = data[row].pollutant
|
n = self._bc_list.get(row).pollutant
|
||||||
if n is None or n == "not_associated" or n == "":
|
if n is None or n == "not_associated" or n == "":
|
||||||
return self._trad["not_associated"]
|
return self._trad["not_associated"]
|
||||||
tmp = next(filter(lambda x: x.id == n,
|
tmp = next(filter(lambda x: x.id == n,
|
||||||
@@ -177,20 +170,20 @@ class TableModel(PamhyrTableModel):
|
|||||||
if self._headers[column] == "type":
|
if self._headers[column] == "type":
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetTypeCommand(
|
SetTypeCommand(
|
||||||
self._lst, row, value
|
self._bc_list, row, value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif self._headers[column] == "node":
|
elif self._headers[column] == "node":
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetNodeCommand(
|
SetNodeCommand(
|
||||||
self._lst, row, self._data.node(value)
|
self._bc_list, row, self._data.node(value)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif self._headers[column] == "pol":
|
elif self._headers[column] == "pol":
|
||||||
if value == self._trad["not_associated"]:
|
if value == self._trad["not_associated"]:
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetPolCommand(
|
SetPolCommand(
|
||||||
self._lst, row, None
|
self._bc_list, row, None
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -199,7 +192,7 @@ class TableModel(PamhyrTableModel):
|
|||||||
)
|
)
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetPolCommand(
|
SetPolCommand(
|
||||||
self._lst, row, pol.id
|
self._bc_list, row, pol.id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -214,7 +207,7 @@ class TableModel(PamhyrTableModel):
|
|||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
AddCommand(
|
AddCommand(
|
||||||
self._pollutant, self._bc_list, self._lst, row
|
self._pollutant, self._bc_list, row
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -226,7 +219,7 @@ class TableModel(PamhyrTableModel):
|
|||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
DelCommand(
|
DelCommand(
|
||||||
self._lst, rows
|
self._bc_list, rows
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -35,14 +35,14 @@ class SetNodeCommand(QUndoCommand):
|
|||||||
|
|
||||||
self._bcs = bcs
|
self._bcs = bcs
|
||||||
self._index = index
|
self._index = index
|
||||||
self._old = self._bcs[self._index].node
|
self._old = self._bcs.get(self._index).node
|
||||||
self._new = node.id
|
self._new = node.id
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._bcs[self._index].node = self._old
|
self._bcs.get(self._index).node = self._old
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
self._bcs[self._index].node = self._new
|
self._bcs.get(self._index).node = self._new
|
||||||
|
|
||||||
|
|
||||||
class SetTypeCommand(QUndoCommand):
|
class SetTypeCommand(QUndoCommand):
|
||||||
@@ -52,14 +52,14 @@ class SetTypeCommand(QUndoCommand):
|
|||||||
self._bcs = bcs
|
self._bcs = bcs
|
||||||
self._index = index
|
self._index = index
|
||||||
self._type = _type
|
self._type = _type
|
||||||
self._old = self._bcs[self._index].type
|
self._old = self._bcs.get(self._index).type
|
||||||
self._new = self._type
|
self._new = self._type
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._bcs[self._index].type = self._old
|
self._bcs.get(self._index).type = self._old
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
self._bcs[self._index].type = self._new
|
self._bcs.get(self._index).type = self._new
|
||||||
|
|
||||||
|
|
||||||
class SetPolCommand(QUndoCommand):
|
class SetPolCommand(QUndoCommand):
|
||||||
@@ -68,32 +68,31 @@ class SetPolCommand(QUndoCommand):
|
|||||||
|
|
||||||
self._bcs = bcs
|
self._bcs = bcs
|
||||||
self._index = index
|
self._index = index
|
||||||
self._old = self._bcs[self._index].pollutant
|
self._old = self._bcs.get(self._index).pollutant
|
||||||
self._new = pollutant
|
self._new = pollutant
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._bcs[self._index].pollutant = self._old
|
self._bcs.get(self._index).pollutant = self._old
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
self._bcs[self._index].pollutant = self._new
|
self._bcs.get(self._index).pollutant = self._new
|
||||||
|
|
||||||
|
|
||||||
class AddCommand(QUndoCommand):
|
class AddCommand(QUndoCommand):
|
||||||
def __init__(self, pollutant, bcs_list, bcs, index):
|
def __init__(self, pollutant, bcs, index):
|
||||||
QUndoCommand.__init__(self)
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
self._bcs = bcs
|
self._bcs = bcs
|
||||||
self._bc_list = bcs_list
|
|
||||||
self._pollutant = pollutant
|
self._pollutant = pollutant
|
||||||
self._index = index
|
self._index = index
|
||||||
self._new = None
|
self._new = None
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
del self._bcs[self._index]
|
self._bcs.delete_i([self._index])
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
if self._new is None:
|
if self._new is None:
|
||||||
self._new = self._bc_list.new(self._index, self._pollutant)
|
self._new = self._bcs.new(self._index, self._pollutant)
|
||||||
else:
|
else:
|
||||||
self._bcs.insert(self._index, self._new)
|
self._bcs.insert(self._index, self._new)
|
||||||
|
|
||||||
@@ -107,7 +106,7 @@ class DelCommand(QUndoCommand):
|
|||||||
|
|
||||||
self._bc = []
|
self._bc = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
self._bc.append((row, self._bcs[row]))
|
self._bc.append((row, self._bcs.get(row)))
|
||||||
self._bc.sort()
|
self._bc.sort()
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
@@ -115,5 +114,4 @@ class DelCommand(QUndoCommand):
|
|||||||
self._bcs.insert(row, el)
|
self._bcs.insert(row, el)
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
for row in self._rows:
|
self._bcs.delete_i(self._rows)
|
||||||
del self._bcs[row]
|
|
||||||
@@ -180,7 +180,10 @@ class BoundaryConditionAdisTSWindow(PamhyrWindow):
|
|||||||
def edit(self):
|
def edit(self):
|
||||||
rows = self.index_selected_rows()
|
rows = self.index_selected_rows()
|
||||||
for row in rows:
|
for row in rows:
|
||||||
data = self._bcs.lst[row]
|
data = self._bcs.get(row)
|
||||||
|
|
||||||
|
if data.node is None:
|
||||||
|
continue
|
||||||
|
|
||||||
if self.sub_window_exists(
|
if self.sub_window_exists(
|
||||||
EditBoundaryConditionWindow,
|
EditBoundaryConditionWindow,
|
||||||
|
|||||||
@@ -130,29 +130,29 @@ class D90TableModel(PamhyrTableModel):
|
|||||||
row = index.row()
|
row = index.row()
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
if self._headers[column] is "name":
|
if self._headers[column] == "name":
|
||||||
n = self._lst[row].name
|
n = self._lst[row].name
|
||||||
if n is None or n == "":
|
if n is None or n == "":
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "reach":
|
elif self._headers[column] == "reach":
|
||||||
n = self._lst[row].reach
|
n = self._lst[row].reach
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return next(filter(
|
return next(filter(
|
||||||
lambda edge: edge.id == n, self._river.edges()
|
lambda edge: edge.id == n, self._river.edges()
|
||||||
)).name
|
)).name
|
||||||
elif self._headers[column] is "start_rk":
|
elif self._headers[column] == "start_rk":
|
||||||
n = self._lst[row].start_rk
|
n = self._lst[row].start_rk
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "end_rk":
|
elif self._headers[column] == "end_rk":
|
||||||
n = self._lst[row].end_rk
|
n = self._lst[row].end_rk
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "d90":
|
elif self._headers[column] == "d90":
|
||||||
n = self._lst[row].d90
|
n = self._lst[row].d90
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
@@ -175,7 +175,6 @@ class D90TableModel(PamhyrTableModel):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif self._headers[column] == "reach":
|
elif self._headers[column] == "reach":
|
||||||
print(self._river.edge(value).id)
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetCommandSpec(
|
SetCommandSpec(
|
||||||
self._lst, row, self._headers[column],
|
self._lst, row, self._headers[column],
|
||||||
|
|||||||
@@ -279,9 +279,7 @@ class D90AdisTSWindow(PamhyrWindow):
|
|||||||
self._table_spec.add(rows[0])
|
self._table_spec.add(rows[0])
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
print("del")
|
|
||||||
rows = self.index_selected_rows()
|
rows = self.index_selected_rows()
|
||||||
if len(rows) == 0:
|
if len(rows) == 0:
|
||||||
print("len 0")
|
|
||||||
return
|
return
|
||||||
self._table_spec.delete(rows)
|
self._table_spec.delete(rows)
|
||||||
@@ -132,39 +132,39 @@ class DIFTableModel(PamhyrTableModel):
|
|||||||
row = index.row()
|
row = index.row()
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
if self._headers[column] is "method":
|
if self._headers[column] == "method":
|
||||||
n = self._lst[row].method
|
n = self._lst[row].method
|
||||||
if n is None or n == "":
|
if n is None or n == "":
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "reach":
|
elif self._headers[column] == "reach":
|
||||||
n = self._lst[row].reach
|
n = self._lst[row].reach
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return next(filter(
|
return next(filter(
|
||||||
lambda edge: edge.id == n, self._river.edges()
|
lambda edge: edge.id == n, self._river.edges()
|
||||||
)).name
|
)).name
|
||||||
elif self._headers[column] is "start_rk":
|
elif self._headers[column] == "start_rk":
|
||||||
n = self._lst[row].start_rk
|
n = self._lst[row].start_rk
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "end_rk":
|
elif self._headers[column] == "end_rk":
|
||||||
n = self._lst[row].end_rk
|
n = self._lst[row].end_rk
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "dif":
|
elif self._headers[column] == "dif":
|
||||||
n = self._lst[row].dif
|
n = self._lst[row].dif
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "b":
|
elif self._headers[column] == "b":
|
||||||
n = self._lst[row].b
|
n = self._lst[row].b
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "c":
|
elif self._headers[column] == "c":
|
||||||
n = self._lst[row].c
|
n = self._lst[row].c
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
|
|||||||
@@ -55,22 +55,22 @@ class DIFTableDefaultModel(PamhyrTableModel):
|
|||||||
row = index.row()
|
row = index.row()
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
if self._headers[column] is "method":
|
if self._headers[column] == "method":
|
||||||
n = self._data[row].method
|
n = self._data[row].method
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "dif":
|
elif self._headers[column] == "dif":
|
||||||
n = self._data[row].dif
|
n = self._data[row].dif
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "b":
|
elif self._headers[column] == "b":
|
||||||
n = self._data[row].b
|
n = self._data[row].b
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "c":
|
elif self._headers[column] == "c":
|
||||||
n = self._data[row].c
|
n = self._data[row].c
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ from View.Frictions.UndoCommand import (
|
|||||||
SetNameCommand, SetBeginCommand, SetEndCommand,
|
SetNameCommand, SetBeginCommand, SetEndCommand,
|
||||||
SetBeginStricklerCommand, SetEndStricklerCommand,
|
SetBeginStricklerCommand, SetEndStricklerCommand,
|
||||||
AddCommand, DelCommand, SortCommand,
|
AddCommand, DelCommand, SortCommand,
|
||||||
MoveCommand, PasteCommand, DuplicateCommand,
|
MoveCommand, PasteCommand, DuplicateCommand, ReplaceDataCommand,
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
@@ -99,7 +99,7 @@ class ComboBoxDelegate(QItemDelegate):
|
|||||||
self.commitData.emit(self.sender())
|
self.commitData.emit(self.sender())
|
||||||
|
|
||||||
|
|
||||||
class TableModel(PamhyrTableModel):
|
class FrictionTableModel(PamhyrTableModel):
|
||||||
def _setup_lst(self):
|
def _setup_lst(self):
|
||||||
self._lst = self._data.frictions
|
self._lst = self._data.frictions
|
||||||
self._study = self._opt_data
|
self._study = self._opt_data
|
||||||
@@ -199,6 +199,18 @@ class TableModel(PamhyrTableModel):
|
|||||||
self.endRemoveRows()
|
self.endRemoveRows()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def replace_data(self, new_data):
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
ReplaceDataCommand(
|
||||||
|
self._lst, new_data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
def sort(self, _reverse, parent=QModelIndex()):
|
def sort(self, _reverse, parent=QModelIndex()):
|
||||||
self.layoutAboutToBeChanged.emit()
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
|
||||||
@@ -252,3 +264,32 @@ class TableModel(PamhyrTableModel):
|
|||||||
def redo(self):
|
def redo(self):
|
||||||
self._undo.redo()
|
self._undo.redo()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def read_from_file(self, file_name):
|
||||||
|
|
||||||
|
reach_id = self._study.river.enable_edges().index(self._data) + 1
|
||||||
|
|
||||||
|
logger.debug(f"Import frictions from {file_name}")
|
||||||
|
data = []
|
||||||
|
with open(file_name, encoding="utf-8") as rug_file:
|
||||||
|
for line in rug_file:
|
||||||
|
if line.upper().startswith("K"):
|
||||||
|
if int(line[1:4]) == reach_id:
|
||||||
|
data.append(line[4:].split())
|
||||||
|
|
||||||
|
new_data = []
|
||||||
|
for d in data:
|
||||||
|
new = None
|
||||||
|
minor = float(d[2])
|
||||||
|
medium = float(d[3])
|
||||||
|
for s in self._study.river.stricklers.stricklers:
|
||||||
|
if s.minor == minor and s.medium == medium:
|
||||||
|
new = s
|
||||||
|
break
|
||||||
|
if new is None:
|
||||||
|
new = self._study.river.stricklers.new(len(
|
||||||
|
self._study.river.stricklers))
|
||||||
|
new.minor = minor
|
||||||
|
new.medium = medium
|
||||||
|
new_data.append([self._data, float(d[0]), float(d[1]), new, new])
|
||||||
|
self.replace_data(new_data)
|
||||||
@@ -143,6 +143,42 @@ class AddCommand(QUndoCommand):
|
|||||||
self._frictions.insert(self._index, self._new)
|
self._frictions.insert(self._index, self._new)
|
||||||
|
|
||||||
|
|
||||||
|
class ReplaceDataCommand(QUndoCommand):
|
||||||
|
def __init__(self, frictions, new_data):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._frictions = frictions
|
||||||
|
self._new_data = new_data
|
||||||
|
self._old_rows = list(range(len(frictions)))
|
||||||
|
self._new_rows = list(range(len(new_data)))
|
||||||
|
self._new = []
|
||||||
|
|
||||||
|
self._old_friction = []
|
||||||
|
for row in self._old_rows:
|
||||||
|
self._old_friction.append((row, self._frictions.lst[row]))
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._frictions.delete_i(self._new_rows)
|
||||||
|
for row, el in self._old_friction:
|
||||||
|
self._frictions.insert(row, el)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if len(self._new) == 0:
|
||||||
|
self._frictions.delete_i(self._old_rows)
|
||||||
|
for row in self._new_rows:
|
||||||
|
new = self._frictions.new(row)
|
||||||
|
d = self._new_data[row]
|
||||||
|
new.edge = d[0]
|
||||||
|
new.begin_rk = d[1]
|
||||||
|
new.end_rk = d[2]
|
||||||
|
new.begin_strickler = d[3]
|
||||||
|
new.end_strickler = d[4]
|
||||||
|
self._new.append((row, new))
|
||||||
|
else:
|
||||||
|
for row, el in self._new:
|
||||||
|
self._frictions.insert(row, el)
|
||||||
|
|
||||||
|
|
||||||
class DelCommand(QUndoCommand):
|
class DelCommand(QUndoCommand):
|
||||||
def __init__(self, frictions, rows):
|
def __init__(self, frictions, rows):
|
||||||
QUndoCommand.__init__(self)
|
QUndoCommand.__init__(self)
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ from PyQt5.QtGui import (
|
|||||||
QKeySequence,
|
QKeySequence,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from PyQt5 import QtWidgets
|
||||||
from PyQt5.QtCore import (
|
from PyQt5.QtCore import (
|
||||||
Qt, QVariant, QAbstractTableModel,
|
Qt, QVariant, QAbstractTableModel,
|
||||||
QCoreApplication, QModelIndex, pyqtSlot,
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
QRect,
|
QRect, QSettings,
|
||||||
)
|
)
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
@@ -46,7 +47,7 @@ from View.Frictions.UndoCommand import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from View.Frictions.Table import (
|
from View.Frictions.Table import (
|
||||||
TableModel, ComboBoxDelegate
|
FrictionTableModel, ComboBoxDelegate
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||||
@@ -106,7 +107,7 @@ class FrictionsWindow(PamhyrWindow):
|
|||||||
)
|
)
|
||||||
|
|
||||||
table = self.find(QTableView, f"tableView")
|
table = self.find(QTableView, f"tableView")
|
||||||
self._table = TableModel(
|
self._table = FrictionTableModel(
|
||||||
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=[
|
||||||
@@ -157,6 +158,8 @@ class FrictionsWindow(PamhyrWindow):
|
|||||||
self.plot_2.draw()
|
self.plot_2.draw()
|
||||||
|
|
||||||
def setup_connections(self):
|
def setup_connections(self):
|
||||||
|
self.find(QAction, "action_import").triggered\
|
||||||
|
.connect(self.import_from_file)
|
||||||
self.find(QAction, "action_add").triggered.connect(self.add)
|
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||||
self.find(QAction, "action_del").triggered.connect(self.delete)
|
self.find(QAction, "action_del").triggered.connect(self.delete)
|
||||||
self.find(QAction, "action_sort").triggered.connect(self.sort)
|
self.find(QAction, "action_sort").triggered.connect(self.sort)
|
||||||
@@ -265,3 +268,22 @@ class FrictionsWindow(PamhyrWindow):
|
|||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
strick.show()
|
strick.show()
|
||||||
|
|
||||||
|
def import_from_file(self):
|
||||||
|
options = QFileDialog.Options()
|
||||||
|
settings = QSettings(QSettings.IniFormat,
|
||||||
|
QSettings.UserScope, 'MyOrg', )
|
||||||
|
options |= QFileDialog.DontUseNativeDialog
|
||||||
|
|
||||||
|
file_types = [self._trad["file_rug"], self._trad["file_all"]]
|
||||||
|
|
||||||
|
file_name, _ = QtWidgets.QFileDialog.getOpenFileName(
|
||||||
|
self,
|
||||||
|
self._trad["open_file"],
|
||||||
|
"",
|
||||||
|
";; ".join(file_types),
|
||||||
|
options=options
|
||||||
|
)
|
||||||
|
|
||||||
|
if file_name != "":
|
||||||
|
self._table.read_from_file(file_name)
|
||||||
@@ -38,6 +38,10 @@ class FrictionsTranslate(MainTranslate):
|
|||||||
self._dict["Edit frictions"] = _translate(
|
self._dict["Edit frictions"] = _translate(
|
||||||
"Frictions", "Edit frictions"
|
"Frictions", "Edit frictions"
|
||||||
)
|
)
|
||||||
|
self._dict["file_rug"] = _translate(
|
||||||
|
"Frictions", "Mage initial frictions file (*.RUG *.rug)")
|
||||||
|
self._dict["file_all"] = _translate(
|
||||||
|
"Frictions", "All files (*)")
|
||||||
|
|
||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
# "name": self._dict["name"],
|
# "name": self._dict["name"],
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ from PyQt5.QtGui import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from PyQt5.QtCore import (
|
from PyQt5.QtCore import (
|
||||||
Qt, QVariant, QAbstractTableModel,
|
Qt, QVariant, QAbstractTableModel, QItemSelectionModel,
|
||||||
)
|
)
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
|
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
|
||||||
QDoubleSpinBox,
|
QDoubleSpinBox, QRadioButton,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ class MeshingDialog(PamhyrDialog):
|
|||||||
self._space_step = 50.0
|
self._space_step = 50.0
|
||||||
self._lplan = False
|
self._lplan = False
|
||||||
self._lm = "3"
|
self._lm = "3"
|
||||||
self._linear = False
|
self._linear = True
|
||||||
self._begin_cs = -1
|
self._begin_cs = -1
|
||||||
self._end_cs = -1
|
self._end_cs = -1
|
||||||
self._begin_dir = "un"
|
self._begin_dir = "un"
|
||||||
@@ -71,7 +71,7 @@ class MeshingDialog(PamhyrDialog):
|
|||||||
self._origin = self._reach.profile(0)
|
self._origin = self._reach.profile(0)
|
||||||
|
|
||||||
self._init_default_values_profiles()
|
self._init_default_values_profiles()
|
||||||
self._init_default_values_guidelines()
|
# self._init_default_values_guidelines()
|
||||||
|
|
||||||
self.set_double_spin_box(
|
self.set_double_spin_box(
|
||||||
"doubleSpinBox_space_step",
|
"doubleSpinBox_space_step",
|
||||||
@@ -83,14 +83,24 @@ class MeshingDialog(PamhyrDialog):
|
|||||||
else:
|
else:
|
||||||
self.set_radio_button("radioButton_spline", True)
|
self.set_radio_button("radioButton_spline", True)
|
||||||
|
|
||||||
|
self.find(QRadioButton, "radioButton_spline").setEnabled(False)
|
||||||
|
self.find(QRadioButton, "radioButton_linear").setEnabled(False)
|
||||||
|
|
||||||
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_rk", profiles)
|
||||||
self.combobox_add_items("comboBox_end_rk", profiles)
|
self.combobox_add_items("comboBox_end_rk", profiles)
|
||||||
|
|
||||||
self.set_combobox_text("comboBox_begin_rk", profiles[0])
|
r = self.parent.tableView\
|
||||||
self.set_combobox_text("comboBox_end_rk", profiles[-1])
|
.selectionModel()\
|
||||||
|
.selectedRows()
|
||||||
|
if len(r) <= 1:
|
||||||
|
self.set_combobox_text("comboBox_begin_rk", profiles[0])
|
||||||
|
self.set_combobox_text("comboBox_end_rk", profiles[-1])
|
||||||
|
else:
|
||||||
|
self.set_combobox_text("comboBox_begin_rk", profiles[r[0].row()])
|
||||||
|
self.set_combobox_text("comboBox_end_rk", profiles[r[-1].row()])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def profiles(self):
|
def profiles(self):
|
||||||
@@ -167,8 +177,8 @@ class MeshingDialog(PamhyrDialog):
|
|||||||
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)
|
||||||
|
|
||||||
self._begin_dir = self.get_combobox_text("comboBox_begin_gl")
|
# self._begin_dir = self.get_combobox_text("comboBox_begin_gl")
|
||||||
self._end_dir = self.get_combobox_text("comboBox_end_gl")
|
# self._end_dir = self.get_combobox_text("comboBox_end_gl")
|
||||||
|
|
||||||
super().accept()
|
super().accept()
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ class PlotAC(PamhyrPlot):
|
|||||||
self.plot_selected = None
|
self.plot_selected = None
|
||||||
self.next_plot_selected = None
|
self.next_plot_selected = None
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def redraw(self, data):
|
||||||
|
self._data = data
|
||||||
|
self.draw()
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.init_axes()
|
self.init_axes()
|
||||||
|
|||||||
@@ -163,6 +163,11 @@ class PlotRKZ(PamhyrPlot):
|
|||||||
)
|
)
|
||||||
self._table.scrollTo(self._table.model().index(ind2, 0))
|
self._table.scrollTo(self._table.model().index(ind2, 0))
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def redraw(self, data):
|
||||||
|
self._data = data
|
||||||
|
self.draw()
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.init_axes()
|
self.init_axes()
|
||||||
|
|||||||
@@ -162,6 +162,11 @@ class PlotXY(PamhyrPlot):
|
|||||||
)
|
)
|
||||||
self._table.scrollTo(self._table.model().index(ind2, 0))
|
self._table.scrollTo(self._table.model().index(ind2, 0))
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def redraw(self, data):
|
||||||
|
self._data = data
|
||||||
|
self.draw()
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.init_axes()
|
self.init_axes()
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ class GeometryReachTableModel(PamhyrTableModel):
|
|||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
def move_down(self, row, parent=QModelIndex()):
|
def move_down(self, row, parent=QModelIndex()):
|
||||||
if row > self._data.number_profiles:
|
if row >= self._data.number_profiles-1:
|
||||||
return
|
return
|
||||||
|
|
||||||
target = row
|
target = row
|
||||||
@@ -276,3 +276,12 @@ class GeometryReachTableModel(PamhyrTableModel):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def change_reach(self, new_reach, parent):
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
ChangeReachCommand(
|
||||||
|
new_reach,
|
||||||
|
parent
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -22,14 +22,12 @@ from copy import deepcopy
|
|||||||
from tools import trace, timer, logger_exception
|
from tools import trace, timer, logger_exception
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QMessageBox, QUndoCommand, QUndoStack,
|
QMessageBox, QUndoCommand, QUndoStack, QTableView
|
||||||
)
|
)
|
||||||
|
|
||||||
from Model.Geometry import Reach
|
from Model.Geometry import Reach
|
||||||
from Model.Except import exception_message_box
|
from Model.Except import exception_message_box
|
||||||
|
|
||||||
from Meshing.Mage import MeshingWithMage
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
@@ -240,7 +238,7 @@ class MeshingCommand(QUndoCommand):
|
|||||||
self._mesher = mesher
|
self._mesher = mesher
|
||||||
self._command = command
|
self._command = command
|
||||||
|
|
||||||
self._profiles = reach.profiles.copy()
|
self._profiles = [p.copy() for p in reach.profiles]
|
||||||
self._profiles.reverse()
|
self._profiles.reverse()
|
||||||
|
|
||||||
self._new_profiles = None
|
self._new_profiles = None
|
||||||
@@ -264,7 +262,7 @@ class MeshingCommand(QUndoCommand):
|
|||||||
**self._data
|
**self._data
|
||||||
)
|
)
|
||||||
|
|
||||||
self._new_profiles = self._reach.profiles.copy()
|
self._new_profiles = [p.copy() for p in self._reach.profiles]
|
||||||
self._new_profiles.reverse()
|
self._new_profiles.reverse()
|
||||||
else:
|
else:
|
||||||
self._reach.purge()
|
self._reach.purge()
|
||||||
@@ -293,6 +291,35 @@ class PurgeCommand(QUndoCommand):
|
|||||||
profile.purge(self._np_purge)
|
profile.purge(self._np_purge)
|
||||||
|
|
||||||
|
|
||||||
|
class ChangeReachCommand(QUndoCommand):
|
||||||
|
def __init__(self, new_reach, parent):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._old_reach = parent._study.river.current_reach()
|
||||||
|
self._new_reach = new_reach
|
||||||
|
self._parent = parent
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
p = self._parent
|
||||||
|
p._reach = self._old_reach.reach
|
||||||
|
p._study.river.set_current_reach(self._old_reach)
|
||||||
|
p.setup_table()
|
||||||
|
p.update_redraw()
|
||||||
|
p.find(QTableView, "tableView").selectionModel()\
|
||||||
|
.selectionChanged\
|
||||||
|
.connect(p.select_current_profile)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
p = self._parent
|
||||||
|
p._reach = self._new_reach.reach
|
||||||
|
p._study.river.set_current_reach(self._new_reach)
|
||||||
|
p.setup_table()
|
||||||
|
p.update_redraw()
|
||||||
|
p.find(QTableView, "tableView").selectionModel()\
|
||||||
|
.selectionChanged\
|
||||||
|
.connect(p.select_current_profile)
|
||||||
|
|
||||||
|
|
||||||
class ShiftCommand(QUndoCommand):
|
class ShiftCommand(QUndoCommand):
|
||||||
def __init__(self, reach, rows, dx, dy, dz):
|
def __init__(self, reach, rows, dx, dy, dz):
|
||||||
QUndoCommand.__init__(self)
|
QUndoCommand.__init__(self)
|
||||||
|
|||||||
+50
-19
@@ -32,6 +32,7 @@ from PyQt5.QtGui import (
|
|||||||
from PyQt5.QtCore import (
|
from PyQt5.QtCore import (
|
||||||
QModelIndex, Qt, QSettings, pyqtSlot,
|
QModelIndex, Qt, QSettings, pyqtSlot,
|
||||||
QItemSelectionModel, QCoreApplication, QSize,
|
QItemSelectionModel, QCoreApplication, QSize,
|
||||||
|
QItemSelection, QItemSelectionRange,
|
||||||
)
|
)
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QApplication, QMainWindow, QFileDialog, QCheckBox,
|
QApplication, QMainWindow, QFileDialog, QCheckBox,
|
||||||
@@ -47,9 +48,9 @@ from View.Tools.PamhyrWindow import PamhyrWindow
|
|||||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||||
|
|
||||||
from Meshing.Mage import (
|
from View.SelectReach.Window import SelectReachWindow
|
||||||
MeshingWithMage, MeshingWithMageMailleurTT
|
|
||||||
)
|
from Meshing.Internal import InternalMeshing
|
||||||
|
|
||||||
from View.Geometry.Table import GeometryReachTableModel
|
from View.Geometry.Table import GeometryReachTableModel
|
||||||
from View.Geometry.PlotXY import PlotXY
|
from View.Geometry.PlotXY import PlotXY
|
||||||
@@ -196,6 +197,7 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
"action_update_rk": self.update_rk,
|
"action_update_rk": self.update_rk,
|
||||||
"action_purge": self.purge,
|
"action_purge": self.purge,
|
||||||
"action_shift": self.shift,
|
"action_shift": self.shift,
|
||||||
|
"action_select_reach": self.select_reach,
|
||||||
}
|
}
|
||||||
|
|
||||||
for action in actions:
|
for action in actions:
|
||||||
@@ -217,9 +219,9 @@ 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.redraw(data=self._reach)
|
||||||
self._plot_rkc.draw()
|
self._plot_rkc.redraw(data=self._reach)
|
||||||
self._plot_ac.draw()
|
self._plot_ac.redraw(data=self._reach)
|
||||||
|
|
||||||
self.select_current_profile()
|
self.select_current_profile()
|
||||||
|
|
||||||
@@ -285,6 +287,13 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
self.tableView.model().blockSignals(False)
|
self.tableView.model().blockSignals(False)
|
||||||
|
|
||||||
def edit_meshing(self):
|
def edit_meshing(self):
|
||||||
|
|
||||||
|
rows = list(
|
||||||
|
set(
|
||||||
|
(i.row() for i in self.tableView.selectedIndexes())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
selected_rk = [self._reach.profile(r).rk for r in rows]
|
||||||
try:
|
try:
|
||||||
dlg = MeshingDialog(
|
dlg = MeshingDialog(
|
||||||
reach=self._reach,
|
reach=self._reach,
|
||||||
@@ -295,8 +304,6 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
data = {
|
data = {
|
||||||
"step": dlg.space_step,
|
"step": dlg.space_step,
|
||||||
"limites": [dlg.begin_cs, dlg.end_cs],
|
"limites": [dlg.begin_cs, dlg.end_cs],
|
||||||
"directrices": [dlg.begin_dir, dlg.end_dir],
|
|
||||||
"lplan": dlg.lplan,
|
|
||||||
"linear": dlg.linear,
|
"linear": dlg.linear,
|
||||||
}
|
}
|
||||||
self._edit_meshing(data)
|
self._edit_meshing(data)
|
||||||
@@ -304,18 +311,31 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
logger_exception(e)
|
logger_exception(e)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
ind = []
|
||||||
|
for i in range(self._reach.number_profiles):
|
||||||
|
if self._reach.profile(i).rk in selected_rk:
|
||||||
|
ind.append(i)
|
||||||
|
self.tableView.setFocus()
|
||||||
|
selection = self.tableView.selectionModel()
|
||||||
|
index = QItemSelection()
|
||||||
|
if len(ind) > 0:
|
||||||
|
for i in ind:
|
||||||
|
index.append(QItemSelectionRange(
|
||||||
|
self.tableView.model().index(i, 0))
|
||||||
|
)
|
||||||
|
selection.select(
|
||||||
|
index,
|
||||||
|
QItemSelectionModel.Rows |
|
||||||
|
QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Select
|
||||||
|
)
|
||||||
|
|
||||||
def _edit_meshing(self, data):
|
def _edit_meshing(self, data):
|
||||||
try:
|
try:
|
||||||
mesher = MeshingWithMageMailleurTT()
|
mesher = InternalMeshing()
|
||||||
self._table.meshing(mesher, data)
|
self._table.meshing(mesher, data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger_exception(e)
|
logger_exception(e)
|
||||||
raise ExternFileMissingError(
|
|
||||||
module="mage",
|
|
||||||
filename="MailleurTT",
|
|
||||||
path=MeshingWithMageMailleurTT._path(),
|
|
||||||
src_except=e
|
|
||||||
)
|
|
||||||
|
|
||||||
def update_rk(self):
|
def update_rk(self):
|
||||||
try:
|
try:
|
||||||
@@ -338,14 +358,11 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
|
|
||||||
def _update_rk(self, data):
|
def _update_rk(self, data):
|
||||||
try:
|
try:
|
||||||
mesher = MeshingWithMageMailleurTT()
|
mesher = InternalMeshing()
|
||||||
self._table.update_rk(mesher, data)
|
self._table.update_rk(mesher, data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger_exception(e)
|
logger_exception(e)
|
||||||
raise ExternFileMissingError(
|
raise ExternFileMissingError(
|
||||||
module="mage",
|
|
||||||
filename="MailleurTT",
|
|
||||||
path=MeshingWithMageMailleurTT._path(),
|
|
||||||
src_except=e
|
src_except=e
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -535,6 +552,20 @@ class GeometryWindow(PamhyrWindow):
|
|||||||
logger_exception(e)
|
logger_exception(e)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def select_reach(self):
|
||||||
|
try:
|
||||||
|
dlg = SelectReachWindow(
|
||||||
|
study=self._study,
|
||||||
|
trad=self._trad,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
if dlg.exec():
|
||||||
|
self._table.change_reach(dlg.reach, self)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
return
|
||||||
|
|
||||||
def duplicate(self):
|
def duplicate(self):
|
||||||
rows = [
|
rows = [
|
||||||
row.row() for row in
|
row.row() for row in
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||||||
self.layoutAboutToBeChanged.emit()
|
self.layoutAboutToBeChanged.emit()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
def import_from_results(self, index, results):
|
def import_from_results(self, results):
|
||||||
if results is None:
|
if results is None:
|
||||||
logger.error("No results data")
|
logger.error("No results data")
|
||||||
return
|
return
|
||||||
@@ -281,6 +281,51 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||||||
self.layoutAboutToBeChanged.emit()
|
self.layoutAboutToBeChanged.emit()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def read_from_ini(self, file_name):
|
||||||
|
|
||||||
|
reach_id = self._data.river.enable_edges().index(self._reach) + 1
|
||||||
|
|
||||||
|
logger.debug(f"Import initial conditions from {file_name}")
|
||||||
|
data = []
|
||||||
|
with open(file_name, encoding="utf-8") as ini_file:
|
||||||
|
for line in ini_file:
|
||||||
|
if not (line.startswith("#") or
|
||||||
|
line.startswith("*") or
|
||||||
|
line.startswith("$")):
|
||||||
|
line_split = line.split()
|
||||||
|
formated = False
|
||||||
|
if len(line_split[0]) > 3:
|
||||||
|
formated = True
|
||||||
|
elif len(line_split[2]) > 10:
|
||||||
|
formated = True
|
||||||
|
elif len(line_split[3]) > 11:
|
||||||
|
formated = True
|
||||||
|
elif len(line_split[4]) > 9:
|
||||||
|
formated = True
|
||||||
|
|
||||||
|
if formated: # old PamHyr format
|
||||||
|
if int(line[1:4]) == reach_id:
|
||||||
|
data.append([line[31:40],
|
||||||
|
line[10:20],
|
||||||
|
line[20:31]])
|
||||||
|
else:
|
||||||
|
if int(line_split[0]) == reach_id:
|
||||||
|
data.append([line_split[4],
|
||||||
|
line_split[2],
|
||||||
|
line_split[3]])
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
ReplaceDataCommand(
|
||||||
|
self._lst,
|
||||||
|
list(
|
||||||
|
map(
|
||||||
|
lambda d: self._lst.new_from_data(*d),
|
||||||
|
data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._undo.undo()
|
self._undo.undo()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from tools import trace, timer, logger_exception
|
|||||||
|
|
||||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5 import QtWidgets
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
QKeySequence,
|
QKeySequence,
|
||||||
)
|
)
|
||||||
@@ -30,7 +31,7 @@ from PyQt5.QtGui import (
|
|||||||
from PyQt5.QtCore import (
|
from PyQt5.QtCore import (
|
||||||
Qt, QVariant, QAbstractTableModel,
|
Qt, QVariant, QAbstractTableModel,
|
||||||
QCoreApplication, QModelIndex, pyqtSlot,
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
QRect,
|
QRect, QSettings, QItemSelectionModel,
|
||||||
)
|
)
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
@@ -219,6 +220,8 @@ class InitialConditionsWindow(PamhyrWindow):
|
|||||||
def _update_plot(self):
|
def _update_plot(self):
|
||||||
self.plot_1.draw()
|
self.plot_1.draw()
|
||||||
self.plot_2.draw()
|
self.plot_2.draw()
|
||||||
|
self.plot_1.idle()
|
||||||
|
self.plot_2.idle()
|
||||||
|
|
||||||
def _propagated_update(self, key=Modules(0)):
|
def _propagated_update(self, key=Modules(0)):
|
||||||
if Modules.GEOMETRY not in key:
|
if Modules.GEOMETRY not in key:
|
||||||
@@ -260,17 +263,33 @@ class InitialConditionsWindow(PamhyrWindow):
|
|||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
def import_from_file(self):
|
def import_from_file(self):
|
||||||
workdir = os.path.dirname(self._study.filename)
|
options = QFileDialog.Options()
|
||||||
|
settings = QSettings(QSettings.IniFormat,
|
||||||
|
QSettings.UserScope, 'MyOrg', )
|
||||||
|
options |= QFileDialog.DontUseNativeDialog
|
||||||
|
|
||||||
return self.file_dialog(
|
file_types = [
|
||||||
select_file="ExistingFile",
|
self._trad["file_bin"],
|
||||||
callback=lambda d: self._import_from_file(d[0]),
|
self._trad["file_ini"],
|
||||||
directory=workdir,
|
self._trad["file_all"],
|
||||||
default_suffix=".BIN",
|
]
|
||||||
file_filter=["Mage (*.BIN)"],
|
file_name, _ = QtWidgets.QFileDialog.getOpenFileName(
|
||||||
|
self,
|
||||||
|
self._trad["open_file"],
|
||||||
|
"",
|
||||||
|
";; ".join(file_types),
|
||||||
|
options=options
|
||||||
)
|
)
|
||||||
|
|
||||||
def _import_from_file(self, file_name):
|
if file_name != "":
|
||||||
|
size = os.stat(file_name).st_size
|
||||||
|
# self._table.import_geometry(0, file_name)
|
||||||
|
if file_name[-4:] == ".BIN":
|
||||||
|
self._import_from_bin_file(file_name)
|
||||||
|
elif file_name[-4:].upper() == ".INI":
|
||||||
|
self._import_from_ini_file(file_name)
|
||||||
|
|
||||||
|
def _import_from_bin_file(self, file_name):
|
||||||
solver = Mage8("dummy")
|
solver = Mage8("dummy")
|
||||||
name = os.path.basename(file_name)\
|
name = os.path.basename(file_name)\
|
||||||
.replace(".BIN", "")
|
.replace(".BIN", "")
|
||||||
@@ -292,13 +311,18 @@ class InitialConditionsWindow(PamhyrWindow):
|
|||||||
)
|
)
|
||||||
dlg.exec_()
|
dlg.exec_()
|
||||||
results = self._tmp_results
|
results = self._tmp_results
|
||||||
self._import_from_results(results)
|
if results.is_valid:
|
||||||
|
self._import_from_results(results)
|
||||||
|
|
||||||
def _import_from_results(self, results):
|
def _import_from_results(self, results):
|
||||||
logger.debug(f"import from results: {results}")
|
logger.debug(f"import from results: {results}")
|
||||||
row = self.index_selected_row()
|
self._table.import_from_results(results)
|
||||||
|
self._update()
|
||||||
|
|
||||||
self._table.import_from_results(row, results)
|
def _import_from_ini_file(self, file_name):
|
||||||
|
logger.debug(f"import from INI file: {file_name}")
|
||||||
|
self._table.read_from_ini(file_name)
|
||||||
|
self._update()
|
||||||
|
|
||||||
def move_up(self):
|
def move_up(self):
|
||||||
row = self.index_selected_row()
|
row = self.index_selected_row()
|
||||||
|
|||||||
@@ -34,6 +34,15 @@ class ICTranslate(MainTranslate):
|
|||||||
self._dict["discharge"] = self._dict["unit_discharge"]
|
self._dict["discharge"] = self._dict["unit_discharge"]
|
||||||
self._dict["rk"] = self._dict["unit_rk"]
|
self._dict["rk"] = self._dict["unit_rk"]
|
||||||
|
|
||||||
|
self._dict["open_file"] = _translate(
|
||||||
|
"InitialCondition", "Open a file")
|
||||||
|
self._dict["file_bin"] = _translate(
|
||||||
|
"InitialCondition", "Mage results file (*.BIN)")
|
||||||
|
self._dict["file_ini"] = _translate(
|
||||||
|
"InitialCondition", "Mage initial conditions file (*.INI *.ini)")
|
||||||
|
self._dict["file_all"] = _translate(
|
||||||
|
"InitialCondition", "All files (*)")
|
||||||
|
|
||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
# "name": _translate("InitialCondition", "Name"),
|
# "name": _translate("InitialCondition", "Name"),
|
||||||
"rk": self._dict["unit_rk"],
|
"rk": self._dict["unit_rk"],
|
||||||
|
|||||||
@@ -129,49 +129,49 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||||||
row = index.row()
|
row = index.row()
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
if self._headers[column] is "name":
|
if self._headers[column] == "name":
|
||||||
n = self._lst[row].name
|
n = self._lst[row].name
|
||||||
if n is None or n == "":
|
if n is None or n == "":
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "reach":
|
elif self._headers[column] == "reach":
|
||||||
n = self._lst[row].reach
|
n = self._lst[row].reach
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return next(filter(
|
return next(filter(
|
||||||
lambda edge: edge.id == n, self._river.edges()
|
lambda edge: edge.id == n, self._river.edges()
|
||||||
)).name
|
)).name
|
||||||
elif self._headers[column] is "start_rk":
|
elif self._headers[column] == "start_rk":
|
||||||
n = self._lst[row].start_rk
|
n = self._lst[row].start_rk
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "end_rk":
|
elif self._headers[column] == "end_rk":
|
||||||
n = self._lst[row].end_rk
|
n = self._lst[row].end_rk
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "concentration":
|
elif self._headers[column] == "concentration":
|
||||||
n = self._lst[row].concentration
|
n = self._lst[row].concentration
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "eg":
|
elif self._headers[column] == "eg":
|
||||||
n = self._lst[row].eg
|
n = self._lst[row].eg
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "em":
|
elif self._headers[column] == "em":
|
||||||
n = self._lst[row].em
|
n = self._lst[row].em
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "ed":
|
elif self._headers[column] == "ed":
|
||||||
n = self._lst[row].ed
|
n = self._lst[row].ed
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "rate":
|
elif self._headers[column] == "rate":
|
||||||
n = self._lst[row].rate
|
n = self._lst[row].rate
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
@@ -194,7 +194,6 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif self._headers[column] == "reach":
|
elif self._headers[column] == "reach":
|
||||||
print(self._river.edge(value).id)
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetCommandSpec(
|
SetCommandSpec(
|
||||||
self._lst, row, self._headers[column],
|
self._lst, row, self._headers[column],
|
||||||
|
|||||||
@@ -55,24 +55,24 @@ class InitialConditionTableDefaultModel(PamhyrTableModel):
|
|||||||
row = index.row()
|
row = index.row()
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
if self._headers[column] is "name":
|
if self._headers[column] == "name":
|
||||||
return self._data[row].name
|
return self._data[row].name
|
||||||
elif self._headers[column] is "concentration":
|
elif self._headers[column] == "concentration":
|
||||||
n = self._data[row].concentration
|
n = self._data[row].concentration
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "eg":
|
elif self._headers[column] == "eg":
|
||||||
n = self._data[row].eg
|
n = self._data[row].eg
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "em":
|
elif self._headers[column] == "em":
|
||||||
n = self._data[row].em
|
n = self._data[row].em
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
return n
|
return n
|
||||||
elif self._headers[column] is "ed":
|
elif self._headers[column] == "ed":
|
||||||
n = self._data[row].ed
|
n = self._data[row].ed
|
||||||
if n is None:
|
if n is None:
|
||||||
return self._trad['not_associated']
|
return self._trad['not_associated']
|
||||||
|
|||||||
@@ -281,9 +281,7 @@ class InitialConditionsAdisTSWindow(PamhyrWindow):
|
|||||||
self._table_spec.add(rows[0])
|
self._table_spec.add(rows[0])
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
print("del")
|
|
||||||
rows = self.index_selected_rows()
|
rows = self.index_selected_rows()
|
||||||
if len(rows) == 0:
|
if len(rows) == 0:
|
||||||
print("len 0")
|
|
||||||
return
|
return
|
||||||
self._table_spec.delete(rows)
|
self._table_spec.delete(rows)
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from tools import trace, timer
|
from tools import trace, timer, old_pamhyr_date_to_timestamp
|
||||||
|
|
||||||
from PyQt5.QtCore import (
|
from PyQt5.QtCore import (
|
||||||
Qt, QVariant, QAbstractTableModel,
|
Qt, QVariant, QAbstractTableModel,
|
||||||
@@ -38,7 +38,7 @@ from View.LateralContribution.UndoCommand import (
|
|||||||
SetNameCommand, SetEdgeCommand, SetTypeCommand,
|
SetNameCommand, SetEdgeCommand, SetTypeCommand,
|
||||||
SetBeginCommand, SetEndCommand,
|
SetBeginCommand, SetEndCommand,
|
||||||
AddCommand, DelCommand, SortCommand,
|
AddCommand, DelCommand, SortCommand,
|
||||||
MoveCommand, PasteCommand, DuplicateCommand,
|
MoveCommand, PasteCommand, DuplicateCommand, ImportCommand,
|
||||||
)
|
)
|
||||||
|
|
||||||
from Model.LateralContribution.LateralContributionTypes import (
|
from Model.LateralContribution.LateralContributionTypes import (
|
||||||
@@ -116,17 +116,20 @@ class ComboBoxDelegate(QItemDelegate):
|
|||||||
def setModelData(self, editor, model, index):
|
def setModelData(self, editor, model, index):
|
||||||
text = str(editor.currentText())
|
text = str(editor.currentText())
|
||||||
|
|
||||||
if self._mode == "rk":
|
if self._data is None:
|
||||||
profiles = list(
|
|
||||||
filter(
|
|
||||||
lambda p: p.display_name() == text,
|
|
||||||
self._data.reach.profiles
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
value = profiles[0].rk if len(profiles) > 0 else None
|
|
||||||
else:
|
|
||||||
value = text
|
value = text
|
||||||
|
else:
|
||||||
|
if self._mode == "rk" and self._data.reach is not None:
|
||||||
|
profiles = list(
|
||||||
|
filter(
|
||||||
|
lambda p: p.display_name() == text,
|
||||||
|
self._data.reach.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
value = profiles[0].rk if len(profiles) > 0 else None
|
||||||
|
else:
|
||||||
|
value = text
|
||||||
|
|
||||||
model.setData(index, value)
|
model.setData(index, value)
|
||||||
editor.close()
|
editor.close()
|
||||||
@@ -293,3 +296,44 @@ class TableModel(PamhyrTableModel):
|
|||||||
|
|
||||||
self.endMoveRows()
|
self.endMoveRows()
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def read_from_lat(self, file_name):
|
||||||
|
logger.debug(f"Import lateral contributions from {file_name}")
|
||||||
|
data = []
|
||||||
|
current_reach = -1
|
||||||
|
with open(file_name, encoding="utf-8") as lat_file:
|
||||||
|
for line in lat_file:
|
||||||
|
if not (line.startswith("#") or
|
||||||
|
line.startswith("*") or
|
||||||
|
len(line) < 1):
|
||||||
|
line = line.split()
|
||||||
|
if line[0] == "$":
|
||||||
|
current_reach = int(line[1]) - 1
|
||||||
|
if (current_reach <= len(self._data.enable_edges()) and
|
||||||
|
current_reach >= 0):
|
||||||
|
data.append(
|
||||||
|
[self._data.enable_edges()[current_reach],
|
||||||
|
float(line[2]),
|
||||||
|
float(line[3])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if (current_reach <= len(self._data.enable_edges()) and
|
||||||
|
current_reach >= 0):
|
||||||
|
data[-1].append(
|
||||||
|
[
|
||||||
|
old_pamhyr_date_to_timestamp(line[0]),
|
||||||
|
float(line[1])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
ImportCommand(
|
||||||
|
self._lst, self._tab, data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
self.layoutChanged.emit()
|
||||||
@@ -28,6 +28,10 @@ from Model.LateralContribution.LateralContributionList import (
|
|||||||
LateralContributionList
|
LateralContributionList
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from Model.LateralContribution.LateralContributionTypes import (
|
||||||
|
NotDefined, LateralContrib,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SetNameCommand(QUndoCommand):
|
class SetNameCommand(QUndoCommand):
|
||||||
def __init__(self, lcs, tab, index, new_value):
|
def __init__(self, lcs, tab, index, new_value):
|
||||||
@@ -143,13 +147,13 @@ class DelCommand(QUndoCommand):
|
|||||||
self._tab = tab
|
self._tab = tab
|
||||||
self._rows = rows
|
self._rows = rows
|
||||||
|
|
||||||
self._bc = []
|
self._lc = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
self._bc.append((row, self._lcs.get(self._tab, row)))
|
self._lc.append((row, self._lcs.get(self._tab, row)))
|
||||||
self._bc.sort()
|
self._lc.sort()
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
for row, el in self._bc:
|
for row, el in self._lc:
|
||||||
self._lcs.insert(self._tab, row, el)
|
self._lcs.insert(self._tab, row, el)
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
@@ -213,36 +217,73 @@ class MoveCommand(QUndoCommand):
|
|||||||
|
|
||||||
|
|
||||||
class PasteCommand(QUndoCommand):
|
class PasteCommand(QUndoCommand):
|
||||||
def __init__(self, lcs, tab, row, bc):
|
def __init__(self, lcs, tab, row, lc):
|
||||||
QUndoCommand.__init__(self)
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
self._lcs = lcs
|
self._lcs = lcs
|
||||||
self._tab = tab
|
self._tab = tab
|
||||||
self._row = row
|
self._row = row
|
||||||
self._bc = deepcopy(bc)
|
self._lc = deepcopy(lc)
|
||||||
self._bc.reverse()
|
self._lc.reverse()
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._lcs.delete(self._tab, self._bc)
|
self._lcs.delete(self._tab, self._lc)
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
for bc in self._bc:
|
for lc in self._lc:
|
||||||
self._lcs.insert(self._tab, self._row, bc)
|
self._lcs.insert(self._tab, self._row, lc)
|
||||||
|
|
||||||
|
|
||||||
|
class ImportCommand(QUndoCommand):
|
||||||
|
def __init__(self, lcs, tab, data):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._tab = tab
|
||||||
|
self._lcs = lcs
|
||||||
|
self._data = data
|
||||||
|
self._old_rows = list(range(len(self._lcs.get_tab(self._tab))))
|
||||||
|
self._new_rows = list(range(len(self._data)))
|
||||||
|
|
||||||
|
self._new_lc = None
|
||||||
|
self._old_lc = []
|
||||||
|
for row in self._old_rows:
|
||||||
|
self._old_lc.append((row, self._lcs.get(self._tab, row)))
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._lcs.delete_i(self._tab, self._new_rows)
|
||||||
|
for row, el in self._old_lc:
|
||||||
|
self._lcs.insert(self._tab, row, el)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._lcs.delete_i(self._tab, self._old_rows)
|
||||||
|
if self._new_lc is None:
|
||||||
|
self._new_lc = []
|
||||||
|
for row, data in enumerate(self._data):
|
||||||
|
new = LateralContrib(status=self._lcs._status)
|
||||||
|
new.edge = data[0]
|
||||||
|
new.begin_rk = data[1]
|
||||||
|
new.end_rk = data[2]
|
||||||
|
for i, val in enumerate(data[3:]):
|
||||||
|
new.insert(i, val)
|
||||||
|
self._new_lc.append(new)
|
||||||
|
|
||||||
|
for row, el in enumerate(self._new_lc):
|
||||||
|
self._lcs.insert(self._tab, row, el)
|
||||||
|
|
||||||
|
|
||||||
class DuplicateCommand(QUndoCommand):
|
class DuplicateCommand(QUndoCommand):
|
||||||
def __init__(self, lcs, tab, rows, bc):
|
def __init__(self, lcs, tab, rows, lc):
|
||||||
QUndoCommand.__init__(self)
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
self._lcs = lcs
|
self._lcs = lcs
|
||||||
self._tab = tab
|
self._tab = tab
|
||||||
self._rows = rows
|
self._rows = rows
|
||||||
self._bc = deepcopy(bc)
|
self._lc = deepcopy(lc)
|
||||||
self._bc.reverse()
|
self._lc.reverse()
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
self._lcs.delete(self._tab, self._bc)
|
self._lcs.delete(self._tab, self._lc)
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
for bc in self._lcs:
|
for lc in self._lcs:
|
||||||
self._lcs.insert(self._tab, self._rows[0], bc)
|
self._lcs.insert(self._tab, self._rows[0], lc)
|
||||||
@@ -22,6 +22,7 @@ from tools import trace, timer
|
|||||||
|
|
||||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5 import QtWidgets
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
QKeySequence,
|
QKeySequence,
|
||||||
)
|
)
|
||||||
@@ -29,7 +30,7 @@ from PyQt5.QtGui import (
|
|||||||
from PyQt5.QtCore import (
|
from PyQt5.QtCore import (
|
||||||
Qt, QVariant, QAbstractTableModel,
|
Qt, QVariant, QAbstractTableModel,
|
||||||
QCoreApplication, QModelIndex, pyqtSlot,
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
QRect,
|
QRect, QSettings,
|
||||||
)
|
)
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
@@ -153,6 +154,8 @@ class LateralContributionWindow(PamhyrWindow):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def setup_connections(self):
|
def setup_connections(self):
|
||||||
|
self.find(QAction, "action_import").triggered.connect(
|
||||||
|
self.import_from_file)
|
||||||
self.find(QAction, "action_add").triggered.connect(self.add)
|
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||||
self.find(QAction, "action_del").triggered.connect(self.delete)
|
self.find(QAction, "action_del").triggered.connect(self.delete)
|
||||||
self.find(QAction, "action_edit").triggered.connect(self.edit)
|
self.find(QAction, "action_edit").triggered.connect(self.edit)
|
||||||
@@ -297,3 +300,26 @@ class LateralContributionWindow(PamhyrWindow):
|
|||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
win.show()
|
win.show()
|
||||||
|
|
||||||
|
def import_from_file(self):
|
||||||
|
options = QFileDialog.Options()
|
||||||
|
settings = QSettings(QSettings.IniFormat,
|
||||||
|
QSettings.UserScope, 'MyOrg', )
|
||||||
|
options |= QFileDialog.DontUseNativeDialog
|
||||||
|
|
||||||
|
file_types = [
|
||||||
|
self._trad["file_lat"],
|
||||||
|
self._trad["file_all"],
|
||||||
|
]
|
||||||
|
|
||||||
|
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
|
||||||
|
self,
|
||||||
|
self._trad["open_file"],
|
||||||
|
"",
|
||||||
|
";; ".join(file_types),
|
||||||
|
options=options
|
||||||
|
)
|
||||||
|
|
||||||
|
if filename != "":
|
||||||
|
tab = self.current_tab()
|
||||||
|
self._table[tab].read_from_lat(filename)
|
||||||
@@ -52,6 +52,11 @@ class LCTranslate(MainTranslate):
|
|||||||
self._dict["x"] = _translate("Geometry", "X (m)")
|
self._dict["x"] = _translate("Geometry", "X (m)")
|
||||||
self._dict["y"] = _translate("Geometry", "Y (m)")
|
self._dict["y"] = _translate("Geometry", "Y (m)")
|
||||||
self._dict["z"] = _translate("Geometry", "Z (m)")
|
self._dict["z"] = _translate("Geometry", "Z (m)")
|
||||||
|
self._dict["file_lat"] = _translate(
|
||||||
|
"LateralContribution",
|
||||||
|
"Mage lateral contributions file (*.LAT *.lat)")
|
||||||
|
self._dict["file_all"] = _translate(
|
||||||
|
"LateralContribution", "All files (*)")
|
||||||
|
|
||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
"name": self._dict["name"],
|
"name": self._dict["name"],
|
||||||
|
|||||||
+184
-35
@@ -30,6 +30,7 @@ from platformdirs import user_cache_dir
|
|||||||
|
|
||||||
from Solver.AdisTS import AdisTS
|
from Solver.AdisTS import AdisTS
|
||||||
from Solver.Mage import Mage8
|
from Solver.Mage import Mage8
|
||||||
|
from Solver.RubarBE import Rubar3
|
||||||
from tools import logger_exception
|
from tools import logger_exception
|
||||||
|
|
||||||
from PyQt5 import QtGui
|
from PyQt5 import QtGui
|
||||||
@@ -77,14 +78,18 @@ from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
|
|||||||
from View.AdditionalFiles.Window import AddFileListWindow
|
from View.AdditionalFiles.Window import AddFileListWindow
|
||||||
from View.REPLines.Window import REPLineListWindow
|
from View.REPLines.Window import REPLineListWindow
|
||||||
from View.SolverParameters.Window import SolverParametersWindow
|
from View.SolverParameters.Window import SolverParametersWindow
|
||||||
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
|
from View.RunSolver.Window import (
|
||||||
|
SelectSolverWindow,
|
||||||
|
SolverLogWindow,
|
||||||
|
CompareSolversWindow
|
||||||
|
)
|
||||||
|
from View.Results.Window import ResultsWindow
|
||||||
from View.RunSolver.WindowAdisTS import (
|
from View.RunSolver.WindowAdisTS import (
|
||||||
SelectSolverWindowAdisTS,
|
SelectSolverWindowAdisTS,
|
||||||
SolverLogWindowAdisTS
|
SolverLogWindowAdisTS
|
||||||
)
|
)
|
||||||
from View.CheckList.Window import CheckListWindow
|
from View.CheckList.Window import CheckListWindow
|
||||||
from View.CheckList.WindowAdisTS import CheckListWindowAdisTS
|
from View.CheckList.WindowAdisTS import CheckListWindowAdisTS
|
||||||
from View.Results.Window import ResultsWindow
|
|
||||||
from View.Results.WindowAdisTS import ResultsWindowAdisTS
|
from View.Results.WindowAdisTS import ResultsWindowAdisTS
|
||||||
from View.Results.ReadingResultsDialog import ReadingResultsDialog
|
from View.Results.ReadingResultsDialog import ReadingResultsDialog
|
||||||
from View.Debug.Window import ReplWindow
|
from View.Debug.Window import ReplWindow
|
||||||
@@ -93,6 +98,10 @@ from View.Pollutants.Window import PollutantsWindow
|
|||||||
from View.D90AdisTS.Window import D90AdisTSWindow
|
from View.D90AdisTS.Window import D90AdisTSWindow
|
||||||
from View.DIFAdisTS.Window import DIFAdisTSWindow
|
from View.DIFAdisTS.Window import DIFAdisTSWindow
|
||||||
|
|
||||||
|
from Solver.Solvers import GenericSolver
|
||||||
|
|
||||||
|
from Model.Results.Results import Results
|
||||||
|
|
||||||
# Optional internal display of documentation for make the application
|
# Optional internal display of documentation for make the application
|
||||||
# package lighter...
|
# package lighter...
|
||||||
try:
|
try:
|
||||||
@@ -135,7 +144,7 @@ define_model_action = [
|
|||||||
"action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
|
"action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
|
||||||
"action_menu_edit_hydraulic_structures", "action_menu_additional_file",
|
"action_menu_edit_hydraulic_structures", "action_menu_additional_file",
|
||||||
"action_menu_results_last", "action_open_results_from_file",
|
"action_menu_results_last", "action_open_results_from_file",
|
||||||
"action_menu_boundary_conditions_sediment",
|
"action_compare_results", "action_menu_boundary_conditions_sediment",
|
||||||
"action_menu_rep_additional_lines", "action_menu_output_rk",
|
"action_menu_rep_additional_lines", "action_menu_output_rk",
|
||||||
"action_menu_run_adists", "action_menu_pollutants",
|
"action_menu_run_adists", "action_menu_pollutants",
|
||||||
"action_menu_d90", "action_menu_dif",
|
"action_menu_d90", "action_menu_dif",
|
||||||
@@ -186,10 +195,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
title = "(dbg) " if self.conf.debug else ""
|
title = "(dbg) " if self.conf.debug else ""
|
||||||
|
|
||||||
if self._study is not None:
|
if self._study is not None:
|
||||||
title += f"Pamhyr2 - {self._study.name}"
|
title += f"Pamhyr2 (Claude François) - {self._study.name}"
|
||||||
self.setWindowTitle(title)
|
self.setWindowTitle(title)
|
||||||
else:
|
else:
|
||||||
title += "Pamhyr2"
|
title += "Pamhyr2 (Claude François)"
|
||||||
self.setWindowTitle(title)
|
self.setWindowTitle(title)
|
||||||
|
|
||||||
def setup_tab(self):
|
def setup_tab(self):
|
||||||
@@ -280,6 +289,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
"action_menu_close": self.close_model,
|
"action_menu_close": self.close_model,
|
||||||
"action_menu_results_last": self.open_last_results,
|
"action_menu_results_last": self.open_last_results,
|
||||||
"action_open_results_from_file": self.open_results_from_file,
|
"action_open_results_from_file": self.open_results_from_file,
|
||||||
|
"action_compare_results": self.compare_results,
|
||||||
"action_open_results_adists": self.open_results_adists,
|
"action_open_results_adists": self.open_results_adists,
|
||||||
# Help
|
# Help
|
||||||
"action_menu_pamhyr_users_wiki": self.open_doc_user,
|
"action_menu_pamhyr_users_wiki": self.open_doc_user,
|
||||||
@@ -339,10 +349,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
if not self._close_question:
|
if not self._close_question:
|
||||||
if self._study is not None and not self._study.is_saved:
|
if self._study is not None and not self._study.is_saved:
|
||||||
if self.dialog_close(cancel=False):
|
if self.dialog_close():
|
||||||
# PAMHYR is close correctly (no crash)
|
# PAMHYR is close correctly (no crash)
|
||||||
self.conf.set_close_correctly()
|
self.conf.set_close_correctly()
|
||||||
super(ApplicationWindow, self).closeEvent(event)
|
super(ApplicationWindow, self).closeEvent(event)
|
||||||
|
else:
|
||||||
|
event.ignore()
|
||||||
else:
|
else:
|
||||||
super(ApplicationWindow, self).closeEvent(event)
|
super(ApplicationWindow, self).closeEvent(event)
|
||||||
|
|
||||||
@@ -522,7 +534,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def close_model(self):
|
def close_model(self):
|
||||||
if not self.dialog_close(cancel=True):
|
if not self.dialog_close():
|
||||||
return
|
return
|
||||||
|
|
||||||
self._study = None
|
self._study = None
|
||||||
@@ -824,21 +836,19 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
|
|
||||||
return file
|
return file
|
||||||
|
|
||||||
def dialog_close(self, cancel=True):
|
def dialog_close(self):
|
||||||
dlg = QMessageBox(self)
|
dlg = QMessageBox(self)
|
||||||
|
|
||||||
dlg.setWindowTitle(self._trad["mb_close_title"])
|
dlg.setWindowTitle(self._trad["mb_close_title"])
|
||||||
dlg.setText(self._trad["mb_close_msg"])
|
dlg.setText(self._trad["mb_close_msg"])
|
||||||
opt = QMessageBox.Save | QMessageBox.Close
|
opt = QMessageBox.Save | QMessageBox.Close
|
||||||
if cancel:
|
opt |= QMessageBox.Cancel
|
||||||
opt |= QMessageBox.Cancel
|
|
||||||
|
|
||||||
dlg.setStandardButtons(opt)
|
dlg.setStandardButtons(opt)
|
||||||
dlg.setIcon(QMessageBox.Warning)
|
dlg.setIcon(QMessageBox.Warning)
|
||||||
dlg.button(QMessageBox.Save).setText(self._trad["Save"])
|
dlg.button(QMessageBox.Save).setText(self._trad["Save"])
|
||||||
dlg.button(QMessageBox.Close).setText(self._trad["Close"])
|
dlg.button(QMessageBox.Close).setText(self._trad["Close"])
|
||||||
if cancel:
|
dlg.button(QMessageBox.Cancel).setText(self._trad["Cancel"])
|
||||||
dlg.button(QMessageBox.Cancel).setText(self._trad["Cancel"])
|
|
||||||
|
|
||||||
res = dlg.exec()
|
res = dlg.exec()
|
||||||
|
|
||||||
@@ -1310,7 +1320,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
# self.conf.solvers))
|
# self.conf.solvers))
|
||||||
# solver = next(filter(lambda x: x.name == "AdisTS-WC",
|
# solver = next(filter(lambda x: x.name == "AdisTS-WC",
|
||||||
# self.conf.solvers))
|
# self.conf.solvers))
|
||||||
# print(solver._type)
|
|
||||||
# self.run_solver(solver)
|
# self.run_solver(solver)
|
||||||
|
|
||||||
run = SelectSolverWindowAdisTS(
|
run = SelectSolverWindowAdisTS(
|
||||||
@@ -1406,7 +1415,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
if type(results) is str:
|
if type(results) is str:
|
||||||
logger.info(f"Open results from {os.path.dirname(results)}")
|
logger.info(f"Open results from {os.path.dirname(results)}")
|
||||||
|
|
||||||
name = os.path.basename(results).replace(".BIN", "")
|
if ".BIN" in results:
|
||||||
|
name = os.path.basename(results).replace(".BIN", "")
|
||||||
|
elif "profil." in results:
|
||||||
|
name = os.path.basename(results).replace("profil.", "")
|
||||||
|
|
||||||
def reading_fn():
|
def reading_fn():
|
||||||
self._tmp_results = solver.results(
|
self._tmp_results = solver.results(
|
||||||
@@ -1423,22 +1435,25 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
if results is None:
|
if results is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# results does not have values, for example if geometry missmatch
|
||||||
|
if not results.is_valid:
|
||||||
|
return
|
||||||
|
|
||||||
# Windows already opened
|
# Windows already opened
|
||||||
if self.sub_window_exists(
|
if self.sub_window_exists(
|
||||||
ResultsWindow,
|
ResultsWindow,
|
||||||
data=[
|
data=[
|
||||||
self._study,
|
self._study,
|
||||||
None, # No config
|
None, # No config,
|
||||||
solver,
|
results._solver,
|
||||||
results
|
results._repertory,
|
||||||
]
|
results._name]
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
res = ResultsWindow(
|
res = ResultsWindow(
|
||||||
study=self._study,
|
study=self._study,
|
||||||
solver=solver,
|
results=[results],
|
||||||
results=results,
|
|
||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
res.show()
|
res.show()
|
||||||
@@ -1487,7 +1502,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
self._study,
|
self._study,
|
||||||
None, # No config
|
None, # No config
|
||||||
solver,
|
solver,
|
||||||
results
|
results._repertory,
|
||||||
|
results._name,
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
@@ -1525,9 +1541,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
if self._study is None:
|
if self._study is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._study.filename == "":
|
|
||||||
return
|
|
||||||
|
|
||||||
options = QFileDialog.Options()
|
options = QFileDialog.Options()
|
||||||
options |= QFileDialog.DontUseNativeDialog
|
options |= QFileDialog.DontUseNativeDialog
|
||||||
|
|
||||||
@@ -1536,25 +1549,161 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
dialog.setFileMode(QFileDialog.FileMode.ExistingFile)
|
dialog.setFileMode(QFileDialog.FileMode.ExistingFile)
|
||||||
dialog.setDefaultSuffix(".BIN")
|
dialog.setDefaultSuffix(".BIN")
|
||||||
# dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden)
|
# dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden)
|
||||||
dialog.setNameFilters(['Mage (*.BIN)'])
|
dialog.setNameFilters(['Mage (*.BIN)', 'Rubar3 (profil.*)'])
|
||||||
|
|
||||||
if self._last_solver is None:
|
if self._study.filename is not None:
|
||||||
dialog.setDirectory(
|
if self._last_solver is None:
|
||||||
os.path.dirname(self._study.filename)
|
dialog.setDirectory(
|
||||||
)
|
os.path.dirname(self._study.filename)
|
||||||
else:
|
)
|
||||||
dialog.setDirectory(
|
else:
|
||||||
self._solver_workdir(self._last_solver)
|
dialog.setDirectory(
|
||||||
)
|
self._solver_workdir(self._last_solver)
|
||||||
|
)
|
||||||
|
|
||||||
if dialog.exec_():
|
if dialog.exec_():
|
||||||
file_name = dialog.selectedFiles()
|
file_name = dialog.selectedFiles()
|
||||||
logger.info(f"Select results: {file_name}")
|
logger.info(f"Select results: {file_name[0]}")
|
||||||
|
|
||||||
|
solver = None
|
||||||
|
if ".BIN" in file_name[0]:
|
||||||
|
solver = Mage8("Mage8")
|
||||||
|
else:
|
||||||
|
solver = Rubar3("Rubar3")
|
||||||
|
|
||||||
self.open_solver_results(
|
self.open_solver_results(
|
||||||
Mage8("Mage"),
|
solver,
|
||||||
results=file_name[0]
|
results=file_name[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def compare_results(self):
|
||||||
|
if self._study is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
run = CompareSolversWindow(
|
||||||
|
study=self._study,
|
||||||
|
config=self.conf,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
if run.exec():
|
||||||
|
results = self.diff_results(run.solver1,
|
||||||
|
run.solver2)
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
# At least one result not available
|
||||||
|
if results is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Windows already opened
|
||||||
|
if self.sub_window_exists(
|
||||||
|
ResultsWindow,
|
||||||
|
data=[self._study, None] +
|
||||||
|
[r._solver for r in results] +
|
||||||
|
[r._repertory for r in results] +
|
||||||
|
[r._name for r in results]
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
res = ResultsWindow(
|
||||||
|
study=self._study,
|
||||||
|
results=results,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
res.show()
|
||||||
|
|
||||||
|
def diff_results(self, solver1, solver2):
|
||||||
|
if solver1 is None:
|
||||||
|
# TODO message
|
||||||
|
return None
|
||||||
|
if solver2 is None:
|
||||||
|
# TODO message
|
||||||
|
return None
|
||||||
|
|
||||||
|
solver3 = GenericSolver(solver1.name+" - "+solver2.name)
|
||||||
|
solver4 = GenericSolver(solver1.name)
|
||||||
|
solver5 = GenericSolver(solver2.name)
|
||||||
|
|
||||||
|
result1 = solver1.results(
|
||||||
|
self._study,
|
||||||
|
self._solver_workdir(solver1),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result1 is None:
|
||||||
|
# TODO message
|
||||||
|
return None
|
||||||
|
|
||||||
|
result2 = solver2.results(
|
||||||
|
self._study,
|
||||||
|
self._solver_workdir(solver2),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result2 is None:
|
||||||
|
# TODO message
|
||||||
|
return None
|
||||||
|
|
||||||
|
if result2.get("nb_reach") != result1.get("nb_reach"):
|
||||||
|
# TODO message
|
||||||
|
return None
|
||||||
|
|
||||||
|
if result2.get("nb_profile") != result1.get("nb_profile"):
|
||||||
|
# TODO message
|
||||||
|
return None
|
||||||
|
|
||||||
|
# return [result1, result2]
|
||||||
|
|
||||||
|
result3 = Results(self._study, solver3)
|
||||||
|
result4 = Results(self._study, solver1)
|
||||||
|
result5 = Results(self._study, solver2)
|
||||||
|
result3.set("nb_reach", result1.get("nb_reach"))
|
||||||
|
result4.set("nb_reach", result1.get("nb_reach"))
|
||||||
|
result5.set("nb_reach", result1.get("nb_reach"))
|
||||||
|
result3.set("nb_profile", result1.get("nb_profile"))
|
||||||
|
result4.set("nb_profile", result1.get("nb_profile"))
|
||||||
|
result5.set("nb_profile", result1.get("nb_profile"))
|
||||||
|
ts = sorted(list(result1.get("timestamps").intersection(
|
||||||
|
result2.get("timestamps"))))
|
||||||
|
result3.set("timestamps", ts)
|
||||||
|
result4.set("timestamps", ts)
|
||||||
|
result5.set("timestamps", ts)
|
||||||
|
|
||||||
|
for i in range(int(result1.get("nb_reach"))):
|
||||||
|
# Add reach to results reach list
|
||||||
|
r = result3.river.add(i)
|
||||||
|
r = result4.river.add(i)
|
||||||
|
r = result5.river.add(i)
|
||||||
|
|
||||||
|
for timestamp in result3.get("timestamps"):
|
||||||
|
for r in range(int(result1.get("nb_reach"))):
|
||||||
|
reach1 = result1.river.reach(r)
|
||||||
|
reach2 = result2.river.reach(r)
|
||||||
|
reach3 = result3.river.reach(r)
|
||||||
|
reach4 = result4.river.reach(r)
|
||||||
|
reach5 = result5.river.reach(r)
|
||||||
|
for p, (profile1, profile2) in enumerate(zip(
|
||||||
|
reach1.profiles, reach2.profiles)):
|
||||||
|
for key in ["Z", "Q", "V"]:
|
||||||
|
d1 = profile1.get_ts_key(timestamp, key)
|
||||||
|
d2 = profile2.get_ts_key(timestamp, key)
|
||||||
|
d = d1-d2
|
||||||
|
reach3.set(p, timestamp, key, d)
|
||||||
|
reach4.set(p, timestamp, key, d1)
|
||||||
|
reach5.set(p, timestamp, key, d2)
|
||||||
|
limits = reach3.profile(p).geometry.get_water_limits(
|
||||||
|
reach3.profile(p).get_ts_key(timestamp, "Z")
|
||||||
|
)
|
||||||
|
reach3.set(
|
||||||
|
p, timestamp,
|
||||||
|
"water_limits",
|
||||||
|
limits
|
||||||
|
)
|
||||||
|
limits = profile1.get_ts_key(timestamp, "water_limits")
|
||||||
|
reach4.set(p, timestamp, "water_limits", limits)
|
||||||
|
limits = profile2.get_ts_key(timestamp, "water_limits")
|
||||||
|
reach5.set(p, timestamp, "water_limits", limits)
|
||||||
|
|
||||||
|
return [result4, result5, result3]
|
||||||
|
|
||||||
def open_results_adists(self):
|
def open_results_adists(self):
|
||||||
if self._study is None:
|
if self._study is None:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ class GraphWidget(QGraphicsView):
|
|||||||
def setup_scene(self, min_size, max_size, size):
|
def setup_scene(self, min_size, max_size, size):
|
||||||
scene = QGraphicsScene(self)
|
scene = QGraphicsScene(self)
|
||||||
scene.setItemIndexMethod(QGraphicsScene.NoIndex)
|
scene.setItemIndexMethod(QGraphicsScene.NoIndex)
|
||||||
scene.setSceneRect(0, 0, 2000, 2000)
|
scene.setSceneRect(0, 0, 6000, 6000)
|
||||||
|
|
||||||
self.setScene(scene)
|
self.setScene(scene)
|
||||||
self.setCacheMode(QGraphicsView.CacheBackground)
|
self.setCacheMode(QGraphicsView.CacheBackground)
|
||||||
@@ -486,6 +486,7 @@ class GraphWidget(QGraphicsView):
|
|||||||
|
|
||||||
self.scale(1, 1)
|
self.scale(1, 1)
|
||||||
self.previousScale = 1
|
self.previousScale = 1
|
||||||
|
self.centerOn(1000.0, 1000.0)
|
||||||
|
|
||||||
if min_size:
|
if min_size:
|
||||||
self.setMinimumSize(*min_size)
|
self.setMinimumSize(*min_size)
|
||||||
|
|||||||
@@ -35,5 +35,5 @@ class EditReservoirTranslate(ReservoirTranslate):
|
|||||||
|
|
||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
"z": self._dict["unit_elevation"],
|
"z": self._dict["unit_elevation"],
|
||||||
"area": self._dict["unit_area"],
|
"area": self._dict["unit_area_he"],
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
# ShiftDialog.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrDialog
|
||||||
|
from PyQt5.QtWidgets import QDoubleSpinBox, QPushButton
|
||||||
|
|
||||||
|
|
||||||
|
class CoordinatesDialog(PamhyrDialog):
|
||||||
|
_pamhyr_ui = "GeotiffCoordinates"
|
||||||
|
_pamhyr_name = "ImageCoordinates"
|
||||||
|
|
||||||
|
def __init__(self, x, y, trad=None, parent=None):
|
||||||
|
super(CoordinatesDialog, self).__init__(
|
||||||
|
title=trad[self._pamhyr_name],
|
||||||
|
trad=trad,
|
||||||
|
options=[],
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self.spinbox = {}
|
||||||
|
self._init_default_values(x, y)
|
||||||
|
self.setup_connections()
|
||||||
|
|
||||||
|
def _init_default_values(self, x, y):
|
||||||
|
self._x = x
|
||||||
|
self._y = y
|
||||||
|
self._values = {"bottom": x[0],
|
||||||
|
"top": x[1],
|
||||||
|
"left": y[0],
|
||||||
|
"right": y[1]}
|
||||||
|
self.spinbox = {}
|
||||||
|
for t in self._values:
|
||||||
|
self.spinbox[t] = self.find(QDoubleSpinBox, f"doubleSpinBox_{t}")
|
||||||
|
self.reset(t)
|
||||||
|
|
||||||
|
def setup_connections(self):
|
||||||
|
for t in self._values:
|
||||||
|
self.find(QPushButton,
|
||||||
|
f"pushButton_{t}").clicked.connect(
|
||||||
|
lambda state, x=t: self.reset(x))
|
||||||
|
|
||||||
|
def reset(self, t):
|
||||||
|
self.spinbox[t].setValue(self._values[t])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def x(self):
|
||||||
|
return [self._values["bottom"], self._values["top"]]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def y(self):
|
||||||
|
return [self._values["left"], self._values["right"]]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def values(self):
|
||||||
|
return [self._values[t] for t in self._values]
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
for t in self._values:
|
||||||
|
self._values[t] = self.get_double_spin_box(f"doubleSpinBox_{t}")
|
||||||
|
super().accept()
|
||||||
|
|
||||||
|
def reject(self):
|
||||||
|
self.close()
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
# CustomExport.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2025 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrDialog
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QRadioButton, QCheckBox, QVBoxLayout, QLabel, QFrame
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Results.translate import ResultsTranslate
|
||||||
|
|
||||||
|
|
||||||
|
class CustomExportDialog(PamhyrDialog):
|
||||||
|
_pamhyr_ui = "CustomExportAdisDialog"
|
||||||
|
_pamhyr_name = "Custom Plot Selection"
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
trad = ResultsTranslate()
|
||||||
|
super(CustomExportDialog, self).__init__(
|
||||||
|
title=trad[self._pamhyr_name],
|
||||||
|
options=[],
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._available_values_x = self._trad.get_dict("values_x")
|
||||||
|
self._available_values_y = self._trad.get_dict("values_y")
|
||||||
|
|
||||||
|
self.setup_radio_buttons_x()
|
||||||
|
self.setup_radio_buttons_res()
|
||||||
|
self.setup_label()
|
||||||
|
self.setup_envelop_box()
|
||||||
|
self.setup_check_boxes()
|
||||||
|
|
||||||
|
self.value = None
|
||||||
|
|
||||||
|
def setup_radio_buttons_x(self):
|
||||||
|
self._radio = []
|
||||||
|
layout = self.find(QVBoxLayout, "verticalLayout_x")
|
||||||
|
|
||||||
|
for value in self._available_values_x:
|
||||||
|
btn = QRadioButton(
|
||||||
|
self._available_values_x[value],
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
self._radio.append((value, btn))
|
||||||
|
layout.addWidget(btn)
|
||||||
|
|
||||||
|
self._radio[0][1].setChecked(True)
|
||||||
|
layout.addStretch()
|
||||||
|
|
||||||
|
def setup_radio_buttons_res(self):
|
||||||
|
self._radio2 = []
|
||||||
|
layout = self.find(QVBoxLayout, "verticalLayout_pol")
|
||||||
|
label = self.find(QLabel, "label_3")
|
||||||
|
label.setText(self._trad["solver"])
|
||||||
|
|
||||||
|
for solver in self.parent._solvers:
|
||||||
|
btn = QRadioButton(
|
||||||
|
solver.name,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
self._radio2.append((solver.name, btn))
|
||||||
|
layout.addWidget(btn)
|
||||||
|
|
||||||
|
self._radio2[0][1].setChecked(True)
|
||||||
|
if len(self.parent._results) == 1:
|
||||||
|
self._radio2[0][1].setEnabled(False)
|
||||||
|
label.setEnabled(False)
|
||||||
|
else:
|
||||||
|
self._radio2[0][1].setEnabled(True)
|
||||||
|
label.setEnabled(True)
|
||||||
|
|
||||||
|
layout.addStretch()
|
||||||
|
|
||||||
|
def setup_label(self):
|
||||||
|
self._label = self.find(QLabel, "label_4")
|
||||||
|
self._label.setFrameStyle(QFrame.StyledPanel)
|
||||||
|
self._label.setStyleSheet('background-color: white')
|
||||||
|
self.set_label()
|
||||||
|
for r in self._radio:
|
||||||
|
r[1].clicked.connect(self.set_label)
|
||||||
|
|
||||||
|
def set_label(self):
|
||||||
|
if self._radio[0][1].isChecked():
|
||||||
|
self._label.setText(self._parent.text_bief() + "\n" +
|
||||||
|
self._parent.text_time())
|
||||||
|
else:
|
||||||
|
self._label.setText(self._parent.text_bief() + "\n" +
|
||||||
|
self._parent.text_profile())
|
||||||
|
|
||||||
|
def setup_envelop_box(self):
|
||||||
|
layout = self.find(QVBoxLayout, "verticalLayout_x")
|
||||||
|
self._envelop = QCheckBox(
|
||||||
|
self._trad["envelop"],
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
layout.addWidget(self._envelop)
|
||||||
|
self._envelop.setChecked(True)
|
||||||
|
for r in self._radio:
|
||||||
|
r[1].clicked.connect(self.envelop_box_status)
|
||||||
|
|
||||||
|
def envelop_box_status(self):
|
||||||
|
if self._radio[0][1].isChecked():
|
||||||
|
if len(self.parent._results) > 1:
|
||||||
|
self._envelop.setEnabled(False)
|
||||||
|
else:
|
||||||
|
self._envelop.setEnabled(True)
|
||||||
|
else:
|
||||||
|
self._envelop.setEnabled(False)
|
||||||
|
|
||||||
|
def setup_check_boxes(self):
|
||||||
|
self._check = []
|
||||||
|
layout = self.find(QVBoxLayout, "verticalLayout_y")
|
||||||
|
|
||||||
|
for value in self._available_values_y:
|
||||||
|
btn = QCheckBox(
|
||||||
|
self._available_values_y[value],
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
self._check.append((value, btn))
|
||||||
|
layout.addWidget(btn)
|
||||||
|
|
||||||
|
self._check[0][1].setChecked(True)
|
||||||
|
layout.addStretch()
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
x = next(
|
||||||
|
filter(
|
||||||
|
lambda r: r[1].isChecked(),
|
||||||
|
self._radio
|
||||||
|
)
|
||||||
|
)[0]
|
||||||
|
|
||||||
|
y = list(
|
||||||
|
map(
|
||||||
|
lambda b: b[0],
|
||||||
|
filter(
|
||||||
|
lambda b: b[1].isChecked(),
|
||||||
|
self._check
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
res = 0
|
||||||
|
for i, b in enumerate(self._radio2):
|
||||||
|
if b[1].isChecked():
|
||||||
|
res = i
|
||||||
|
break
|
||||||
|
|
||||||
|
self.value = x, y, self._envelop.isChecked(), res
|
||||||
|
|
||||||
|
super().accept()
|
||||||
+20
-3
@@ -1,5 +1,5 @@
|
|||||||
# CustomPlotValuesSelectionDialog.py -- Pamhyr
|
# CustomExportAdis.py -- Pamhyr
|
||||||
# Copyright (C) 2023-2024 INRAE
|
# Copyright (C) 2023-2025 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
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
from View.Tools.PamhyrWindow import PamhyrDialog
|
from View.Tools.PamhyrWindow import PamhyrDialog
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QRadioButton, QCheckBox, QVBoxLayout,
|
QRadioButton, QCheckBox, QVBoxLayout, QLabel, QFrame
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Results.translate import ResultsTranslate
|
from View.Results.translate import ResultsTranslate
|
||||||
@@ -50,6 +50,7 @@ class CustomExportAdisDialog(PamhyrDialog):
|
|||||||
|
|
||||||
self.setup_radio_buttons_x()
|
self.setup_radio_buttons_x()
|
||||||
self.setup_radio_buttons_pol()
|
self.setup_radio_buttons_pol()
|
||||||
|
self.setup_label()
|
||||||
self.setup_check_boxes()
|
self.setup_check_boxes()
|
||||||
|
|
||||||
self.value = None
|
self.value = None
|
||||||
@@ -84,6 +85,22 @@ class CustomExportAdisDialog(PamhyrDialog):
|
|||||||
self._radio2[0][1].setChecked(True)
|
self._radio2[0][1].setChecked(True)
|
||||||
layout.addStretch()
|
layout.addStretch()
|
||||||
|
|
||||||
|
def setup_label(self):
|
||||||
|
self._label = self.find(QLabel, "label_4")
|
||||||
|
self._label.setFrameStyle(QFrame.StyledPanel)
|
||||||
|
self._label.setStyleSheet('background-color: white')
|
||||||
|
self.set_label()
|
||||||
|
for r in self._radio:
|
||||||
|
r[1].clicked.connect(self.set_label)
|
||||||
|
|
||||||
|
def set_label(self):
|
||||||
|
if self._radio[0][1].isChecked():
|
||||||
|
self._label.setText(self._parent.text_bief() + "\n" +
|
||||||
|
self._parent.text_time())
|
||||||
|
else:
|
||||||
|
self._label.setText(self._parent.text_bief() + "\n" +
|
||||||
|
self._parent.text_profile())
|
||||||
|
|
||||||
def setup_check_boxes(self):
|
def setup_check_boxes(self):
|
||||||
self._check = []
|
self._check = []
|
||||||
layout = self.find(QVBoxLayout, "verticalLayout_y")
|
layout = self.find(QVBoxLayout, "verticalLayout_y")
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
from View.Tools.PamhyrWindow import PamhyrDialog
|
from View.Tools.PamhyrWindow import PamhyrDialog
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QRadioButton, QCheckBox, QVBoxLayout,
|
QRadioButton, QCheckBox, QVBoxLayout, QLabel, QFrame
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Results.CustomPlot.Translate import CustomPlotTranslate
|
from View.Results.CustomPlot.Translate import CustomPlotTranslate
|
||||||
@@ -38,10 +38,12 @@ class CustomPlotValuesSelectionDialog(PamhyrDialog):
|
|||||||
parent=parent
|
parent=parent
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._parent = parent
|
||||||
self._available_values_x = self._trad.get_dict("values_x")
|
self._available_values_x = self._trad.get_dict("values_x")
|
||||||
self._available_values_y = self._trad.get_dict("values_y")
|
self._available_values_y = self._trad.get_dict("values_y")
|
||||||
|
|
||||||
self.setup_radio_buttons()
|
self.setup_radio_buttons()
|
||||||
|
self.setup_label()
|
||||||
self.setup_envelop_box()
|
self.setup_envelop_box()
|
||||||
self.setup_check_boxs()
|
self.setup_check_boxs()
|
||||||
|
|
||||||
@@ -62,6 +64,22 @@ class CustomPlotValuesSelectionDialog(PamhyrDialog):
|
|||||||
self._radio[0][1].setChecked(True)
|
self._radio[0][1].setChecked(True)
|
||||||
layout.addStretch()
|
layout.addStretch()
|
||||||
|
|
||||||
|
def setup_label(self):
|
||||||
|
self._label = self.find(QLabel, "label_3")
|
||||||
|
self._label.setFrameStyle(QFrame.StyledPanel)
|
||||||
|
self._label.setStyleSheet('background-color: white')
|
||||||
|
self.set_label()
|
||||||
|
for r in self._radio:
|
||||||
|
r[1].clicked.connect(self.set_label)
|
||||||
|
|
||||||
|
def set_label(self):
|
||||||
|
if self._radio[0][1].isChecked():
|
||||||
|
self._label.setText(self._parent.text_bief() + "\n" +
|
||||||
|
self._parent.text_time())
|
||||||
|
else:
|
||||||
|
self._label.setText(self._parent.text_bief() + "\n" +
|
||||||
|
self._parent.text_profile())
|
||||||
|
|
||||||
def setup_envelop_box(self):
|
def setup_envelop_box(self):
|
||||||
self._envelop = []
|
self._envelop = []
|
||||||
layout = self.find(QVBoxLayout, "verticalLayout_x")
|
layout = self.find(QVBoxLayout, "verticalLayout_x")
|
||||||
|
|||||||
+640
-153
File diff suppressed because it is too large.
Load diff
@@ -29,7 +29,7 @@ _translate = QCoreApplication.translate
|
|||||||
|
|
||||||
class PlotAC(PamhyrPlot):
|
class PlotAC(PamhyrPlot):
|
||||||
def __init__(self, canvas=None, trad=None, toolbar=None,
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
results=None, reach_id=0, profile_id=0,
|
results=None, reach_id=0, profile_id=[0], res_id=[0],
|
||||||
parent=None):
|
parent=None):
|
||||||
super(PlotAC, self).__init__(
|
super(PlotAC, self).__init__(
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
@@ -39,9 +39,11 @@ class PlotAC(PamhyrPlot):
|
|||||||
parent=parent
|
parent=parent
|
||||||
)
|
)
|
||||||
|
|
||||||
self._current_timestamp = max(results.get("timestamps"))
|
|
||||||
self._current_reach_id = reach_id
|
self._current_reach_id = reach_id
|
||||||
self._current_profile_id = profile_id
|
self._current_profile_id = profile_id
|
||||||
|
self._current_res_id = res_id[0]
|
||||||
|
self._timestamps = parent._timestamps
|
||||||
|
self._current_timestamp = max(self._timestamps)
|
||||||
|
|
||||||
self.label_x = self._trad['x']
|
self.label_x = self._trad['x']
|
||||||
self.label_y = self._trad["unit_elevation"]
|
self.label_y = self._trad["unit_elevation"]
|
||||||
@@ -62,7 +64,7 @@ class PlotAC(PamhyrPlot):
|
|||||||
@results.setter
|
@results.setter
|
||||||
def results(self, results):
|
def results(self, results):
|
||||||
self.data = results
|
self.data = results
|
||||||
self._current_timestamp = max(results.get("timestamps"))
|
self._current_timestamp = max(self._timestamps)
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def draw(self, highlight=None):
|
def draw(self, highlight=None):
|
||||||
@@ -71,12 +73,17 @@ class PlotAC(PamhyrPlot):
|
|||||||
if self.results is None:
|
if self.results is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
if self.results[self._current_res_id] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
profile = reach.profile(self._current_profile_id)
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
|
||||||
self.draw_profile(reach, profile)
|
self.draw_profile(reach, profile)
|
||||||
self.draw_water_elevation(reach, profile)
|
self.draw_water_elevation(reach, profile)
|
||||||
self.draw_water_elevation_max(reach, profile)
|
self.draw_water_elevation_max(reach, profile)
|
||||||
|
self.draw_gl()
|
||||||
|
|
||||||
self.enable_legend()
|
self.enable_legend()
|
||||||
|
|
||||||
@@ -109,7 +116,7 @@ class PlotAC(PamhyrPlot):
|
|||||||
|
|
||||||
self.collection = self.canvas.axes.fill_between(
|
self.collection = self.canvas.axes.fill_between(
|
||||||
x, z, water_z,
|
x, z, water_z,
|
||||||
where=z <= water_z,
|
where=list(map(lambda x: x <= water_z, z)),
|
||||||
color=self.color_plot_river_water_zone,
|
color=self.color_plot_river_water_zone,
|
||||||
alpha=0.7, interpolate=True
|
alpha=0.7, interpolate=True
|
||||||
)
|
)
|
||||||
@@ -128,6 +135,72 @@ class PlotAC(PamhyrPlot):
|
|||||||
lw=1., color=self.color_plot_river_water,
|
lw=1., color=self.color_plot_river_water,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def draw_gl(self):
|
||||||
|
|
||||||
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
if profile is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
station = profile.geometry.get_station()
|
||||||
|
elevation = profile.geometry.z()
|
||||||
|
gl = profile.geometry.names()
|
||||||
|
|
||||||
|
self.annotation = []
|
||||||
|
self.cgl, self.igl = reach.geometry.compute_guidelines()
|
||||||
|
|
||||||
|
# we make sure that the lines are in the left-to-right order
|
||||||
|
lcomplete = [
|
||||||
|
x.name
|
||||||
|
for x in profile.geometry.named_points()
|
||||||
|
if x.name in self.cgl
|
||||||
|
]
|
||||||
|
lincomplete = [
|
||||||
|
x.name
|
||||||
|
for x in profile.geometry.named_points()
|
||||||
|
if x.name in self.igl
|
||||||
|
]
|
||||||
|
|
||||||
|
self.color_complete_gl = self.colors
|
||||||
|
self.color_incomplete_gl = 2 * ["grey"]
|
||||||
|
|
||||||
|
x_gl_complete = []
|
||||||
|
y_gl_complete = []
|
||||||
|
x_gl_incomplete = []
|
||||||
|
y_gl_incomplete = []
|
||||||
|
|
||||||
|
for i, txt in enumerate(gl):
|
||||||
|
if txt == "":
|
||||||
|
continue
|
||||||
|
|
||||||
|
if txt.strip() in self.cgl:
|
||||||
|
color = self.color_complete_gl[
|
||||||
|
lcomplete.index(txt) % len(self.color_complete_gl)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
color = self.color_incomplete_gl[
|
||||||
|
lincomplete.index(txt) % len(self.color_incomplete_gl)
|
||||||
|
]
|
||||||
|
|
||||||
|
annotation = self.canvas.axes.annotate(
|
||||||
|
txt, (station[i], elevation[i]),
|
||||||
|
horizontalalignment='left',
|
||||||
|
verticalalignment='top',
|
||||||
|
annotation_clip=True,
|
||||||
|
fontsize=11, color=color
|
||||||
|
)
|
||||||
|
|
||||||
|
annotation.set_position((station[i] + 0., elevation[i] + 0.))
|
||||||
|
self.annotation.append(annotation)
|
||||||
|
|
||||||
|
if txt.strip() in self.cgl:
|
||||||
|
x_gl_complete.append(station[i])
|
||||||
|
y_gl_complete.append(elevation[i])
|
||||||
|
else:
|
||||||
|
x_gl_incomplete.append(station[i])
|
||||||
|
y_gl_incomplete.append(elevation[i])
|
||||||
|
|
||||||
def set_reach(self, reach_id):
|
def set_reach(self, reach_id):
|
||||||
self._current_reach_id = reach_id
|
self._current_reach_id = reach_id
|
||||||
self._current_profile_id = 0
|
self._current_profile_id = 0
|
||||||
@@ -137,10 +210,15 @@ class PlotAC(PamhyrPlot):
|
|||||||
self._current_profile_id = profile_id
|
self._current_profile_id = profile_id
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
def set_result(self, res_id):
|
||||||
|
self._current_res_id = res_id[0]
|
||||||
|
self.update()
|
||||||
|
|
||||||
def set_timestamp(self, timestamp):
|
def set_timestamp(self, timestamp):
|
||||||
self._current_timestamp = timestamp
|
self._current_timestamp = timestamp
|
||||||
|
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
reach = self.results[self._current_res_id].river.reach(
|
||||||
|
self._current_reach_id)
|
||||||
profile = reach.profile(self._current_profile_id)
|
profile = reach.profile(self._current_profile_id)
|
||||||
x = profile.geometry.get_station()
|
x = profile.geometry.get_station()
|
||||||
z = profile.geometry.z()
|
z = profile.geometry.z()
|
||||||
@@ -152,7 +230,8 @@ class PlotAC(PamhyrPlot):
|
|||||||
if not self._init:
|
if not self._init:
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
reach = self.results[self._current_res_id].river.reach(
|
||||||
|
self._current_reach_id)
|
||||||
profile = reach.profile(self._current_profile_id)
|
profile = reach.profile(self._current_profile_id)
|
||||||
x = profile.geometry.get_station()
|
x = profile.geometry.get_station()
|
||||||
z = profile.geometry.z()
|
z = profile.geometry.z()
|
||||||
@@ -160,9 +239,17 @@ class PlotAC(PamhyrPlot):
|
|||||||
self.update_river_bottom(reach, profile, x, z)
|
self.update_river_bottom(reach, profile, x, z)
|
||||||
self.update_water(reach, profile, x, z)
|
self.update_water(reach, profile, x, z)
|
||||||
self.update_water_max(reach, profile, x, z)
|
self.update_water_max(reach, profile, x, z)
|
||||||
|
self.update_gl()
|
||||||
|
|
||||||
self.update_idle()
|
self.update_idle()
|
||||||
|
|
||||||
|
def update_gl(self):
|
||||||
|
for a in self.annotation:
|
||||||
|
a.remove()
|
||||||
|
|
||||||
|
self.annotation[:] = []
|
||||||
|
self.draw_gl()
|
||||||
|
|
||||||
def update_river_bottom(self, reach, profile, x, z):
|
def update_river_bottom(self, reach, profile, x, z):
|
||||||
self.line_rk.set_data(x, z)
|
self.line_rk.set_data(x, z)
|
||||||
|
|
||||||
@@ -176,7 +263,7 @@ class PlotAC(PamhyrPlot):
|
|||||||
self.collection.remove()
|
self.collection.remove()
|
||||||
self.collection = self.canvas.axes.fill_between(
|
self.collection = self.canvas.axes.fill_between(
|
||||||
x, z, water_z,
|
x, z, water_z,
|
||||||
where=z <= water_z,
|
where=list(map(lambda x: x <= water_z, z)),
|
||||||
color=self.color_plot_river_water_zone,
|
color=self.color_plot_river_water_zone,
|
||||||
alpha=0.7, interpolate=True
|
alpha=0.7, interpolate=True
|
||||||
)
|
)
|
||||||
|
|||||||
+100
-46
@@ -35,7 +35,7 @@ logger = logging.getLogger()
|
|||||||
|
|
||||||
class PlotH(PamhyrPlot):
|
class PlotH(PamhyrPlot):
|
||||||
def __init__(self, canvas=None, trad=None, toolbar=None,
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
results=None, reach_id=0, profile_id=0,
|
results=None, reach_id=0, profile_id=[0], res_id=[0],
|
||||||
parent=None):
|
parent=None):
|
||||||
super(PlotH, self).__init__(
|
super(PlotH, self).__init__(
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
@@ -47,9 +47,11 @@ class PlotH(PamhyrPlot):
|
|||||||
|
|
||||||
self._mode = "time"
|
self._mode = "time"
|
||||||
|
|
||||||
self._current_timestamp = max(results.get("timestamps"))
|
|
||||||
self._current_reach_id = reach_id
|
self._current_reach_id = reach_id
|
||||||
self._current_profile_id = profile_id
|
self._current_profile_id = profile_id
|
||||||
|
self._current_res_id = res_id
|
||||||
|
self._timestamps = parent._timestamps
|
||||||
|
self._current_timestamp = max(self._timestamps)
|
||||||
|
|
||||||
self.label_x = self._trad["unit_time_s"]
|
self.label_x = self._trad["unit_time_s"]
|
||||||
self.label_y = self._trad["unit_discharge"]
|
self.label_y = self._trad["unit_discharge"]
|
||||||
@@ -60,8 +62,11 @@ class PlotH(PamhyrPlot):
|
|||||||
|
|
||||||
self._isometric_axis = False
|
self._isometric_axis = False
|
||||||
|
|
||||||
self._auto_relim_update = False
|
# self._auto_relim_update = False
|
||||||
self._autoscale_update = False
|
# self._autoscale_update = False
|
||||||
|
|
||||||
|
self._line_max = []
|
||||||
|
self._line = []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def results(self):
|
def results(self):
|
||||||
@@ -70,47 +75,81 @@ class PlotH(PamhyrPlot):
|
|||||||
@results.setter
|
@results.setter
|
||||||
def results(self, results):
|
def results(self, results):
|
||||||
self.data = results
|
self.data = results
|
||||||
self._current_timestamp = max(results.get("timestamps"))
|
self._current_timestamp = max(self._timestamps)
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def draw(self, highlight=None):
|
def draw(self, highlight=None):
|
||||||
self.init_axes()
|
self.canvas.axes.cla()
|
||||||
|
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||||
|
|
||||||
if self.results is None:
|
if self.results is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
if len(self._current_res_id) < 1:
|
||||||
profile = reach.profile(self._current_profile_id)
|
|
||||||
|
|
||||||
if reach.geometry.number_profiles == 0:
|
|
||||||
self._init = False
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self.draw_max(reach)
|
if len(self._current_res_id) == 1:
|
||||||
self.draw_data(reach, profile)
|
self.draw_max(self._current_res_id[0])
|
||||||
self.draw_current()
|
|
||||||
|
for res_id in self._current_res_id:
|
||||||
|
if self.results[res_id] is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
results = self.results[res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
|
|
||||||
|
if reach.geometry.number_profiles == 0:
|
||||||
|
self._init = False
|
||||||
|
return
|
||||||
|
|
||||||
|
self.draw_data(res_id)
|
||||||
|
|
||||||
|
self.canvas.axes.set_xlabel(
|
||||||
|
self._trad["unit_time_s"],
|
||||||
|
color='black', fontsize=10
|
||||||
|
)
|
||||||
|
|
||||||
|
self.canvas.axes.set_ylabel(
|
||||||
|
self._trad["unit_discharge"],
|
||||||
|
color='black', fontsize=10
|
||||||
|
)
|
||||||
|
|
||||||
self.set_ticks_time_formater()
|
self.set_ticks_time_formater()
|
||||||
|
|
||||||
self.enable_legend()
|
self.enable_legend()
|
||||||
|
|
||||||
self.idle()
|
self.canvas.draw_idle()
|
||||||
self.update_current()
|
self.update_idle
|
||||||
|
self.draw_current()
|
||||||
self._init = True
|
self._init = True
|
||||||
|
|
||||||
def draw_data(self, reach, profile):
|
def draw_data(self, res_id):
|
||||||
self.ts = list(self.results.get("timestamps"))
|
|
||||||
self.ts.sort()
|
|
||||||
|
|
||||||
x = self.ts
|
results = self.results[res_id]
|
||||||
y = profile.get_key("Q")
|
reach = results.river.reach(self._current_reach_id)
|
||||||
|
for i, p in enumerate(self._current_profile_id):
|
||||||
|
profile = reach.profile(p)
|
||||||
|
|
||||||
self._line, = self.canvas.axes.plot(
|
x = self._timestamps
|
||||||
x, y,
|
y = profile.get_key("Q")
|
||||||
label=self.label_discharge,
|
|
||||||
color=self.color_plot,
|
if res_id == 2:
|
||||||
**self.plot_default_kargs
|
label = "Δ " + self.label_discharge + f" {profile.name}"
|
||||||
)
|
else:
|
||||||
|
label = self.label_discharge + f" {profile.name}"
|
||||||
|
|
||||||
|
if len(self._current_res_id) > 1:
|
||||||
|
if res_id != 2:
|
||||||
|
label += f" ({results._solver.name})"
|
||||||
|
|
||||||
|
line, = self.canvas.axes.plot(
|
||||||
|
x, y,
|
||||||
|
label=label,
|
||||||
|
color=self.colors[res_id + 1],
|
||||||
|
linestyle=self.linestyle[i % len(self.linestyle)],
|
||||||
|
**self.plot_default_kargs
|
||||||
|
)
|
||||||
|
self._line.append(line)
|
||||||
|
|
||||||
def draw_current(self):
|
def draw_current(self):
|
||||||
self._current, = self.canvas.axes.plot(
|
self._current, = self.canvas.axes.plot(
|
||||||
@@ -122,12 +161,22 @@ class PlotH(PamhyrPlot):
|
|||||||
lw=1.,
|
lw=1.,
|
||||||
)
|
)
|
||||||
|
|
||||||
def draw_max(self, reach):
|
def draw_max(self, res_id):
|
||||||
self.ts = list(self.results.get("timestamps"))
|
results = self.results[res_id]
|
||||||
self.ts.sort()
|
reach = results.river.reach(self._current_reach_id)
|
||||||
|
|
||||||
x = self.ts
|
if reach.geometry.number_profiles == 0:
|
||||||
|
self._init = False
|
||||||
|
return
|
||||||
|
|
||||||
|
x = self._timestamps
|
||||||
y = []
|
y = []
|
||||||
|
|
||||||
|
if res_id == 2:
|
||||||
|
label = "Δ " + self.label_discharge_max
|
||||||
|
else:
|
||||||
|
label = self.label_discharge_max
|
||||||
|
|
||||||
for ts in x:
|
for ts in x:
|
||||||
ts_y = -9999
|
ts_y = -9999
|
||||||
for profile in reach.profiles:
|
for profile in reach.profiles:
|
||||||
@@ -135,22 +184,28 @@ class PlotH(PamhyrPlot):
|
|||||||
ts_y = max(ts_y, q)
|
ts_y = max(ts_y, q)
|
||||||
y.append(ts_y)
|
y.append(ts_y)
|
||||||
|
|
||||||
self._line_max, = self.canvas.axes.plot(
|
m, = self.canvas.axes.plot(
|
||||||
x, y,
|
x, y,
|
||||||
label=self.label_discharge_max,
|
label=label,
|
||||||
color=self.color_plot_highlight,
|
color=self.color_plot_highlight,
|
||||||
linestyle='dotted',
|
linestyle='dotted',
|
||||||
**self.plot_default_kargs
|
**self.plot_default_kargs
|
||||||
)
|
)
|
||||||
|
self._line_max.append(m)
|
||||||
|
|
||||||
def set_reach(self, reach_id):
|
def set_reach(self, reach_id):
|
||||||
self._current_reach_id = reach_id
|
self._current_reach_id = reach_id
|
||||||
self._current_profile_id = 0
|
self._current_profile_id = [0]
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def set_profile(self, profile_id):
|
def set_profile(self, profile_id):
|
||||||
self._current_profile_id = profile_id
|
self._current_profile_id = profile_id
|
||||||
self.update()
|
# self.update()
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def set_result(self, res_id):
|
||||||
|
self._current_res_id = res_id
|
||||||
|
self.draw()
|
||||||
|
|
||||||
def set_timestamp(self, timestamp):
|
def set_timestamp(self, timestamp):
|
||||||
self._current_timestamp = timestamp
|
self._current_timestamp = timestamp
|
||||||
@@ -162,24 +217,23 @@ class PlotH(PamhyrPlot):
|
|||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
self.update_data()
|
self.update_data()
|
||||||
|
self.update_current()
|
||||||
self.update_idle()
|
self.update_idle()
|
||||||
|
|
||||||
def update_data(self):
|
def update_data(self):
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
for res, res_id in enumerate(self._current_res_id):
|
||||||
profile = reach.profile(self._current_profile_id)
|
results = self.results[res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
|
||||||
x = self.ts
|
x = self._timestamps
|
||||||
y = profile.get_key("Q")
|
y = profile.get_key("Q")
|
||||||
|
|
||||||
self._line.set_data(x, y)
|
self._line[res].set_data(x, y)
|
||||||
|
|
||||||
self._current.set_data(
|
|
||||||
[self._current_timestamp, self._current_timestamp],
|
|
||||||
self.canvas.axes.get_ylim()
|
|
||||||
)
|
|
||||||
|
|
||||||
def update_current(self):
|
def update_current(self):
|
||||||
|
y = self._current.get_ydata()
|
||||||
self._current.set_data(
|
self._current.set_data(
|
||||||
[self._current_timestamp, self._current_timestamp],
|
[self._current_timestamp, self._current_timestamp],
|
||||||
self.canvas.axes.get_ylim()
|
y
|
||||||
)
|
)
|
||||||
+29
-10
@@ -32,7 +32,7 @@ logger = logging.getLogger()
|
|||||||
|
|
||||||
class PlotRKC(PamhyrPlot):
|
class PlotRKC(PamhyrPlot):
|
||||||
def __init__(self, canvas=None, trad=None, toolbar=None,
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
results=None, reach_id=0, profile_id=0,
|
results=None, reach_id=0, profile_id=0, res_id=0,
|
||||||
parent=None):
|
parent=None):
|
||||||
super(PlotRKC, self).__init__(
|
super(PlotRKC, self).__init__(
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
@@ -42,10 +42,11 @@ class PlotRKC(PamhyrPlot):
|
|||||||
parent=parent
|
parent=parent
|
||||||
)
|
)
|
||||||
|
|
||||||
self._timestamps = results.get("timestamps")
|
|
||||||
self._current_timestamp = max(self._timestamps)
|
|
||||||
self._current_reach_id = reach_id
|
self._current_reach_id = reach_id
|
||||||
self._current_profile_id = profile_id
|
self._current_profile_id = profile_id
|
||||||
|
self._current_res_id = res_id[0]
|
||||||
|
self._timestamps = parent._timestamps
|
||||||
|
self._current_timestamp = max(self._timestamps)
|
||||||
|
|
||||||
self.label_x = self._trad["unit_rk"]
|
self.label_x = self._trad["unit_rk"]
|
||||||
self.label_y = self._trad["unit_elevation"]
|
self.label_y = self._trad["unit_elevation"]
|
||||||
@@ -56,6 +57,9 @@ class PlotRKC(PamhyrPlot):
|
|||||||
|
|
||||||
self._isometric_axis = False
|
self._isometric_axis = False
|
||||||
|
|
||||||
|
self._auto_relim_update = True
|
||||||
|
self._autoscale_update = True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def results(self):
|
def results(self):
|
||||||
return self.data
|
return self.data
|
||||||
@@ -63,7 +67,7 @@ class PlotRKC(PamhyrPlot):
|
|||||||
@results.setter
|
@results.setter
|
||||||
def results(self, results):
|
def results(self, results):
|
||||||
self.data = results
|
self.data = results
|
||||||
self._current_timestamp = max(results.get("timestamps"))
|
self._current_timestamp = max(self._timestamps)
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def draw(self, highlight=None):
|
def draw(self, highlight=None):
|
||||||
@@ -72,7 +76,11 @@ class PlotRKC(PamhyrPlot):
|
|||||||
if self.results is None:
|
if self.results is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
if self.results[self._current_res_id] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
|
|
||||||
self.draw_bottom(reach)
|
self.draw_bottom(reach)
|
||||||
self.draw_water_elevation(reach)
|
self.draw_water_elevation(reach)
|
||||||
@@ -107,11 +115,12 @@ class PlotRKC(PamhyrPlot):
|
|||||||
self._river_bottom = z
|
self._river_bottom = z
|
||||||
|
|
||||||
def draw_profiles_hs(self, reach):
|
def draw_profiles_hs(self, reach):
|
||||||
|
results = self.results[self._current_res_id]
|
||||||
lhs = filter(
|
lhs = filter(
|
||||||
lambda hs: hs._input_reach.reach is reach.geometry,
|
lambda hs: hs._input_reach.reach is reach.geometry,
|
||||||
filter(
|
filter(
|
||||||
lambda hs: hs._input_reach is not None,
|
lambda hs: hs._input_reach is not None,
|
||||||
self.results.study.river.hydraulic_structures.lst
|
results.study.river.hydraulic_structures.lst
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -223,6 +232,7 @@ class PlotRKC(PamhyrPlot):
|
|||||||
|
|
||||||
self.water_fill = self.canvas.axes.fill_between(
|
self.water_fill = self.canvas.axes.fill_between(
|
||||||
rk, self._river_bottom, water_z,
|
rk, self._river_bottom, water_z,
|
||||||
|
where=[b <= z for b, z in zip(self._river_bottom, water_z)],
|
||||||
color=self.color_plot_river_water_zone,
|
color=self.color_plot_river_water_zone,
|
||||||
alpha=0.7,
|
alpha=0.7,
|
||||||
interpolate=True
|
interpolate=True
|
||||||
@@ -312,6 +322,10 @@ class PlotRKC(PamhyrPlot):
|
|||||||
self._current_profile_id = profile_id
|
self._current_profile_id = profile_id
|
||||||
self.update_current()
|
self.update_current()
|
||||||
|
|
||||||
|
def set_result(self, res_id):
|
||||||
|
self._current_res_id = res_id[0]
|
||||||
|
self.update()
|
||||||
|
|
||||||
def set_timestamp(self, timestamp):
|
def set_timestamp(self, timestamp):
|
||||||
self._current_timestamp = timestamp
|
self._current_timestamp = timestamp
|
||||||
self.update()
|
self.update()
|
||||||
@@ -320,7 +334,8 @@ class PlotRKC(PamhyrPlot):
|
|||||||
if not self._init:
|
if not self._init:
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
if reach.has_sediment():
|
if reach.has_sediment():
|
||||||
self.update_bottom_with_bedload()
|
self.update_bottom_with_bedload()
|
||||||
|
|
||||||
@@ -329,7 +344,8 @@ class PlotRKC(PamhyrPlot):
|
|||||||
self.update_idle()
|
self.update_idle()
|
||||||
|
|
||||||
def update_water_elevation(self):
|
def update_water_elevation(self):
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
rk = reach.geometry.get_rk()
|
rk = reach.geometry.get_rk()
|
||||||
z_min = reach.geometry.get_z_min()
|
z_min = reach.geometry.get_z_min()
|
||||||
|
|
||||||
@@ -349,12 +365,14 @@ class PlotRKC(PamhyrPlot):
|
|||||||
self.water_fill.remove()
|
self.water_fill.remove()
|
||||||
self.water_fill = self.canvas.axes.fill_between(
|
self.water_fill = self.canvas.axes.fill_between(
|
||||||
rk, self._river_bottom, water_z,
|
rk, self._river_bottom, water_z,
|
||||||
|
where=[rb <= wz for rb, wz in zip(self._river_bottom, water_z)],
|
||||||
color=self.color_plot_river_water_zone,
|
color=self.color_plot_river_water_zone,
|
||||||
alpha=0.7, interpolate=True
|
alpha=0.7, interpolate=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_current(self):
|
def update_current(self):
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
rk = reach.geometry.get_rk()
|
rk = reach.geometry.get_rk()
|
||||||
z_min = reach.geometry.get_z_min()
|
z_min = reach.geometry.get_z_min()
|
||||||
z_max = reach.geometry.get_z_max()
|
z_max = reach.geometry.get_z_max()
|
||||||
@@ -367,7 +385,8 @@ class PlotRKC(PamhyrPlot):
|
|||||||
self.canvas.figure.canvas.draw_idle()
|
self.canvas.figure.canvas.draw_idle()
|
||||||
|
|
||||||
def update_bottom_with_bedload(self):
|
def update_bottom_with_bedload(self):
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
rk = reach.geometry.get_rk()
|
rk = reach.geometry.get_rk()
|
||||||
z = self.sl_compute_current_z(reach)
|
z = self.sl_compute_current_z(reach)
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ logger = logging.getLogger()
|
|||||||
|
|
||||||
class PlotXY(PamhyrPlot):
|
class PlotXY(PamhyrPlot):
|
||||||
def __init__(self, canvas=None, trad=None, toolbar=None,
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
results=None, reach_id=0, profile_id=0,
|
results=None, reach_id=0, profile_id=0, res_id=0,
|
||||||
display_current=True, parent=None):
|
display_current=True, parent=None):
|
||||||
super(PlotXY, self).__init__(
|
super(PlotXY, self).__init__(
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
@@ -52,10 +52,11 @@ class PlotXY(PamhyrPlot):
|
|||||||
self.line_gl = []
|
self.line_gl = []
|
||||||
self.overflow = []
|
self.overflow = []
|
||||||
|
|
||||||
self._timestamps = results.get("timestamps")
|
self._timestamps = parent._timestamps
|
||||||
self._current_timestamp = max(self._timestamps)
|
self._current_timestamp = max(self._timestamps)
|
||||||
self._current_reach_id = reach_id
|
self._current_reach_id = reach_id
|
||||||
self._current_profile_id = profile_id
|
self._current_profile_id = profile_id
|
||||||
|
self._current_res_id = res_id[0]
|
||||||
|
|
||||||
self.label_x = _translate("Results", "X (m)")
|
self.label_x = _translate("Results", "X (m)")
|
||||||
self.label_y = _translate("Results", "Y (m)")
|
self.label_y = _translate("Results", "Y (m)")
|
||||||
@@ -136,7 +137,7 @@ class PlotXY(PamhyrPlot):
|
|||||||
@results.setter
|
@results.setter
|
||||||
def results(self, results):
|
def results(self, results):
|
||||||
self.data = results
|
self.data = results
|
||||||
self._current_timestamp = max(results.get("timestamps"))
|
self._current_timestamp = max(self._timestamps)
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def draw(self, highlight=None):
|
def draw(self, highlight=None):
|
||||||
@@ -145,8 +146,12 @@ class PlotXY(PamhyrPlot):
|
|||||||
if self.results is None:
|
if self.results is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
if self.results[self._current_res_id] is None:
|
||||||
reaches = self.results.river.reachs
|
return
|
||||||
|
|
||||||
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
|
reaches = results.river.reachs
|
||||||
|
|
||||||
self.draw_profiles(reach, reaches)
|
self.draw_profiles(reach, reaches)
|
||||||
self.draw_water_elevation(reach)
|
self.draw_water_elevation(reach)
|
||||||
@@ -161,6 +166,7 @@ class PlotXY(PamhyrPlot):
|
|||||||
if reach.geometry.number_profiles == 0:
|
if reach.geometry.number_profiles == 0:
|
||||||
self._init = False
|
self._init = False
|
||||||
return
|
return
|
||||||
|
self.line_xy = []
|
||||||
# TODO uncomment to draw all the reaches
|
# TODO uncomment to draw all the reaches
|
||||||
# self.draw_other_profiles(reaches)
|
# self.draw_other_profiles(reaches)
|
||||||
for xy in zip(reach.geometry.get_x(),
|
for xy in zip(reach.geometry.get_x(),
|
||||||
@@ -272,7 +278,8 @@ class PlotXY(PamhyrPlot):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def draw_water_elevation(self, reach):
|
def draw_water_elevation(self, reach):
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], []
|
poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], []
|
||||||
|
|
||||||
for profile in reach.profiles:
|
for profile in reach.profiles:
|
||||||
@@ -308,6 +315,10 @@ class PlotXY(PamhyrPlot):
|
|||||||
self.update_profile()
|
self.update_profile()
|
||||||
self.update_idle()
|
self.update_idle()
|
||||||
|
|
||||||
|
def set_result(self, res_id):
|
||||||
|
self._current_res_id = res_id[0]
|
||||||
|
self.update()
|
||||||
|
|
||||||
def set_timestamp(self, timestamp):
|
def set_timestamp(self, timestamp):
|
||||||
self._current_timestamp = timestamp
|
self._current_timestamp = timestamp
|
||||||
self.update()
|
self.update()
|
||||||
@@ -322,7 +333,8 @@ class PlotXY(PamhyrPlot):
|
|||||||
self.update_idle()
|
self.update_idle()
|
||||||
|
|
||||||
def update_profile(self):
|
def update_profile(self):
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
profile = reach.profile(self._current_profile_id)
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
|
||||||
self.plot_selected.set_data(
|
self.plot_selected.set_data(
|
||||||
@@ -331,7 +343,8 @@ class PlotXY(PamhyrPlot):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def update_water_elevation(self):
|
def update_water_elevation(self):
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], []
|
poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], []
|
||||||
|
|
||||||
for profile in reach.profiles:
|
for profile in reach.profiles:
|
||||||
@@ -358,7 +371,8 @@ class PlotXY(PamhyrPlot):
|
|||||||
self.water_fill[0].set_xy(poly)
|
self.water_fill[0].set_xy(poly)
|
||||||
|
|
||||||
def update_water_elevation_overflow(self):
|
def update_water_elevation_overflow(self):
|
||||||
reach = self.results.river.reach(self._current_reach_id)
|
results = self.results[self._current_res_id]
|
||||||
|
reach = results.river.reach(self._current_reach_id)
|
||||||
profile = reach.profile(self._current_profile_id)
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
|
||||||
overflow = []
|
overflow = []
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ from numpy import sqrt
|
|||||||
|
|
||||||
from tools import timer, trace
|
from tools import timer, trace
|
||||||
|
|
||||||
|
from itertools import compress
|
||||||
|
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
QKeySequence, QColor
|
QKeySequence, QColor
|
||||||
)
|
)
|
||||||
@@ -46,13 +48,19 @@ _translate = QCoreApplication.translate
|
|||||||
|
|
||||||
class TableModel(PamhyrTableModel):
|
class TableModel(PamhyrTableModel):
|
||||||
def _setup_lst(self):
|
def _setup_lst(self):
|
||||||
_river = self._data.river
|
_river = self._data[0].river
|
||||||
if self._opt_data == "reach":
|
if self._opt_data == "reach":
|
||||||
self._lst = _river.reachs
|
self._lst = _river.reachs
|
||||||
elif self._opt_data == "profile":
|
elif self._opt_data == "profile":
|
||||||
self._lst = _river.reach(0).profiles
|
self._lst = _river.reach(0).profiles
|
||||||
|
# self._lst = list(filter(lambda x: x.name[0:8] != 'interpol',
|
||||||
|
# _river.reach(0).profiles))
|
||||||
elif self._opt_data == "raw_data":
|
elif self._opt_data == "raw_data":
|
||||||
self._lst = _river.reach(0).profiles
|
self._lst = _river.reach(0).profiles
|
||||||
|
# self._lst = list(filter(lambda x: x.name[0:8] != 'interpol',
|
||||||
|
# _river.reach(0).profiles))
|
||||||
|
elif self._opt_data == "solver":
|
||||||
|
self._lst = self._parent._solvers
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self._timestamp = 0.0
|
self._timestamp = 0.0
|
||||||
@@ -76,6 +84,10 @@ class TableModel(PamhyrTableModel):
|
|||||||
elif self._headers[column] == "rk":
|
elif self._headers[column] == "rk":
|
||||||
v = self._lst[row].rk
|
v = self._lst[row].rk
|
||||||
return f"{v:.4f}"
|
return f"{v:.4f}"
|
||||||
|
elif self._opt_data == "solver":
|
||||||
|
if self._headers[column] == "solver":
|
||||||
|
v = self._lst[row].name
|
||||||
|
return str(v)
|
||||||
elif self._opt_data == "raw_data":
|
elif self._opt_data == "raw_data":
|
||||||
p = self._lst[row]
|
p = self._lst[row]
|
||||||
if self._headers[column] == "name":
|
if self._headers[column] == "name":
|
||||||
@@ -84,14 +96,18 @@ class TableModel(PamhyrTableModel):
|
|||||||
return f"{p.name}"
|
return f"{p.name}"
|
||||||
elif self._headers[column] == "water_elevation":
|
elif self._headers[column] == "water_elevation":
|
||||||
v = self._lst[row].get_ts_key(self._timestamp, "Z")
|
v = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||||
|
if v is None:
|
||||||
|
v = 0.0
|
||||||
return f"{v:.4f}"
|
return f"{v:.4f}"
|
||||||
elif self._headers[column] == "discharge":
|
elif self._headers[column] == "discharge":
|
||||||
v = self._lst[row].get_ts_key(self._timestamp, "Q")
|
v = self._lst[row].get_ts_key(self._timestamp, "Q")
|
||||||
|
if v is None:
|
||||||
|
v = 0.0
|
||||||
return f"{v:.4f}"
|
return f"{v:.4f}"
|
||||||
elif self._headers[column] == "velocity":
|
elif self._headers[column] == "velocity":
|
||||||
q = self._lst[row].get_ts_key(self._timestamp, "Q")
|
|
||||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
|
||||||
v = self._lst[row].get_ts_key(self._timestamp, "V")
|
v = self._lst[row].get_ts_key(self._timestamp, "V")
|
||||||
|
if v is None:
|
||||||
|
v = 0.0
|
||||||
return f"{v:.4f}"
|
return f"{v:.4f}"
|
||||||
elif self._headers[column] == "width":
|
elif self._headers[column] == "width":
|
||||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||||
@@ -123,7 +139,10 @@ class TableModel(PamhyrTableModel):
|
|||||||
v = self._lst[row].get_ts_key(self._timestamp, "V")
|
v = self._lst[row].get_ts_key(self._timestamp, "V")
|
||||||
a = self._lst[row].geometry.wet_area(z)
|
a = self._lst[row].geometry.wet_area(z)
|
||||||
b = self._lst[row].geometry.wet_width(z)
|
b = self._lst[row].geometry.wet_width(z)
|
||||||
froude = v / sqrt(9.81 * (a / b))
|
if b == 0.0 or a == 0.0:
|
||||||
|
froude = 0.0
|
||||||
|
else:
|
||||||
|
froude = v / sqrt(9.81 * (a / b))
|
||||||
return f"{froude:.4f}"
|
return f"{froude:.4f}"
|
||||||
else:
|
else:
|
||||||
v = 0.0
|
v = 0.0
|
||||||
@@ -132,12 +151,14 @@ class TableModel(PamhyrTableModel):
|
|||||||
return QVariant()
|
return QVariant()
|
||||||
|
|
||||||
def update(self, reach):
|
def update(self, reach):
|
||||||
_river = self._data.river
|
_river = self._data[0].river
|
||||||
|
|
||||||
if self._opt_data == "reach":
|
if self._opt_data == "reach":
|
||||||
self._lst = _river.reachs
|
self._lst = _river.reachs
|
||||||
elif self._opt_data == "profile" or self._opt_data == "raw_data":
|
elif self._opt_data == "profile" or self._opt_data == "raw_data":
|
||||||
self._lst = _river.reach(reach).profiles
|
self._lst = _river.reach(reach).profiles
|
||||||
|
elif self._opt_data == "solver":
|
||||||
|
self._lst = self._parent._solvers
|
||||||
|
|
||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ _translate = QCoreApplication.translate
|
|||||||
class TableModel(PamhyrTableModel):
|
class TableModel(PamhyrTableModel):
|
||||||
def _setup_lst(self):
|
def _setup_lst(self):
|
||||||
_river = self._data.river
|
_river = self._data.river
|
||||||
|
self._timestamp = min(list(self._data.get("timestamps")))
|
||||||
if self._opt_data == "reach":
|
if self._opt_data == "reach":
|
||||||
self._lst = _river.reachs
|
self._lst = _river.reachs
|
||||||
elif self._opt_data == "profile":
|
elif self._opt_data == "profile":
|
||||||
@@ -57,7 +58,6 @@ class TableModel(PamhyrTableModel):
|
|||||||
self._lst = tmp_list
|
self._lst = tmp_list
|
||||||
|
|
||||||
def __init__(self, type_pol, **kwargs):
|
def __init__(self, type_pol, **kwargs):
|
||||||
self._timestamp = 0.0
|
|
||||||
self._type_pol = type_pol
|
self._type_pol = type_pol
|
||||||
super(TableModel, self).__init__(**kwargs)
|
super(TableModel, self).__init__(**kwargs)
|
||||||
|
|
||||||
@@ -99,16 +99,18 @@ class TableModel(PamhyrTableModel):
|
|||||||
v = self._lst[row].get_ts_key(
|
v = self._lst[row].get_ts_key(
|
||||||
self._timestamp, "pols")[pol_index][0]
|
self._timestamp, "pols")[pol_index][0]
|
||||||
return f"{v:.4f}"
|
return f"{v:.4f}"
|
||||||
if (self._headers[column] == pol + " Mass"
|
if self._headers[column] == pol + " Mass":
|
||||||
and self._type_pol[pol_index] == 7):
|
if self._type_pol[pol_index] == 7:
|
||||||
m1 = self._lst[row].get_ts_key(
|
m1 = self._lst[row].get_ts_key(
|
||||||
self._timestamp, "pols")[pol_index][1]
|
self._timestamp, "pols")[pol_index][1]
|
||||||
m2 = self._lst[row].get_ts_key(
|
m2 = self._lst[row].get_ts_key(
|
||||||
self._timestamp, "pols")[pol_index][2]
|
self._timestamp, "pols")[pol_index][2]
|
||||||
m3 = self._lst[row].get_ts_key(
|
m3 = self._lst[row].get_ts_key(
|
||||||
self._timestamp, "pols")[pol_index][3]
|
self._timestamp, "pols")[pol_index][3]
|
||||||
v = m1 + m2 + m3
|
v = m1 + m2 + m3
|
||||||
return f"{v:.4f}"
|
return f"{v:.4f}"
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
return QVariant()
|
return QVariant()
|
||||||
|
|
||||||
|
|||||||
+499
-139
@@ -19,6 +19,7 @@
|
|||||||
import os
|
import os
|
||||||
import csv
|
import csv
|
||||||
import logging
|
import logging
|
||||||
|
# import rasterio
|
||||||
|
|
||||||
from numpy import sqrt
|
from numpy import sqrt
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ from PyQt5.QtCore import (
|
|||||||
Qt, QVariant, QAbstractTableModel,
|
Qt, QVariant, QAbstractTableModel,
|
||||||
QCoreApplication, QModelIndex, pyqtSlot,
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
QItemSelectionModel, QTimer,
|
QItemSelectionModel, QTimer,
|
||||||
|
QSettings
|
||||||
)
|
)
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
@@ -59,10 +61,14 @@ from View.Results.CustomPlot.Plot import CustomPlot
|
|||||||
from View.Results.CustomPlot.CustomPlotValuesSelectionDialog import (
|
from View.Results.CustomPlot.CustomPlotValuesSelectionDialog import (
|
||||||
CustomPlotValuesSelectionDialog,
|
CustomPlotValuesSelectionDialog,
|
||||||
)
|
)
|
||||||
|
from View.Results.CustomExport.CustomExport import CustomExportDialog
|
||||||
|
|
||||||
from View.Results.Table import TableModel
|
from View.Results.Table import TableModel
|
||||||
from View.Results.translate import ResultsTranslate
|
from View.Results.translate import (
|
||||||
from View.Stricklers.Window import StricklersWindow
|
ResultsTranslate,
|
||||||
|
CompareResultsTranslate
|
||||||
|
)
|
||||||
|
from View.Results.CoordinatesDialog import CoordinatesDialog
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
@@ -82,16 +88,17 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, study=None, config=None,
|
def __init__(self, study=None, config=None,
|
||||||
solver=None, results=None,
|
results=None, parent=None, trad=None):
|
||||||
parent=None):
|
self._solvers = [r._solver for r in results]
|
||||||
self._solver = solver
|
|
||||||
self._results = results
|
self._results = results
|
||||||
|
self._current_results = [0]
|
||||||
|
|
||||||
trad = ResultsTranslate()
|
if trad is None:
|
||||||
|
trad = ResultsTranslate()
|
||||||
name = (
|
name = (
|
||||||
trad[self._pamhyr_name] + " - "
|
trad[self._pamhyr_name] + " - "
|
||||||
+ study.name + " - "
|
+ study.name + " - "
|
||||||
+ self._solver.name
|
+ " - ".join([s.name for s in self._solvers])
|
||||||
)
|
)
|
||||||
|
|
||||||
super(ResultsWindow, self).__init__(
|
super(ResultsWindow, self).__init__(
|
||||||
@@ -102,14 +109,15 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
parent=parent
|
parent=parent
|
||||||
)
|
)
|
||||||
|
|
||||||
self._hash_data.append(self._solver)
|
for r in results:
|
||||||
self._hash_data.append(self._results)
|
self._hash_data.append(r._solver)
|
||||||
|
self._hash_data.append(r._repertory)
|
||||||
|
self._hash_data.append(r._name)
|
||||||
|
|
||||||
self._additional_plot = {}
|
self._additional_plot = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._timestamps = sorted(list(self._results.get("timestamps")))
|
self.get_timestamps()
|
||||||
|
|
||||||
self.setup_slider()
|
self.setup_slider()
|
||||||
self.setup_table()
|
self.setup_table()
|
||||||
self.setup_plots()
|
self.setup_plots()
|
||||||
@@ -119,22 +127,31 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
logger_exception(e)
|
logger_exception(e)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.update(reach_id=0,
|
||||||
|
profile_id=[0])
|
||||||
|
|
||||||
|
self.update_table_selection_solver(0)
|
||||||
|
|
||||||
def setup_table(self):
|
def setup_table(self):
|
||||||
self._table = {}
|
self._table = {}
|
||||||
for t in ["reach", "profile", "raw_data"]:
|
for t in ["reach", "profile", "raw_data", "solver"]:
|
||||||
table = self.find(QTableView, f"tableView_{t}")
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
self._table[t] = TableModel(
|
self._table[t] = TableModel(
|
||||||
table_view=table,
|
table_view=table,
|
||||||
table_headers=self._trad.get_dict(f"table_headers_{t}"),
|
table_headers=self._trad.get_dict(f"table_headers_{t}"),
|
||||||
data=self._results,
|
data=self._results,
|
||||||
undo=self._undo_stack,
|
undo=self._undo_stack,
|
||||||
opt_data=t
|
opt_data=t,
|
||||||
|
parent=self
|
||||||
)
|
)
|
||||||
self._table[t]._timestamp = self._timestamps[
|
self._table[t]._timestamp = self._timestamps[
|
||||||
self._slider_time.value()]
|
self._slider_time.value()]
|
||||||
|
if len(self._results) <= 1:
|
||||||
|
table = self.find(QTableView, f"tableView_solver")
|
||||||
|
table.hide()
|
||||||
|
|
||||||
def setup_slider(self):
|
def setup_slider(self):
|
||||||
default_reach = self._results.river.reach(0)
|
default_reach = self._results[self._current_results[0]].river.reach(0)
|
||||||
|
|
||||||
self._slider_time = self.find(QSlider, f"horizontalSlider_time")
|
self._slider_time = self.find(QSlider, f"horizontalSlider_time")
|
||||||
self._slider_time.setMaximum(len(self._timestamps) - 1)
|
self._slider_time.setMaximum(len(self._timestamps) - 1)
|
||||||
@@ -181,6 +198,7 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
results=self._results,
|
results=self._results,
|
||||||
reach_id=0,
|
reach_id=0,
|
||||||
profile_id=0,
|
profile_id=0,
|
||||||
|
res_id=self._current_results,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
toolbar=self.toolbar,
|
toolbar=self.toolbar,
|
||||||
display_current=True,
|
display_current=True,
|
||||||
@@ -205,8 +223,10 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
results=self._results,
|
results=self._results,
|
||||||
reach_id=0,
|
reach_id=0,
|
||||||
profile_id=0,
|
profile_id=0,
|
||||||
|
res_id=self._current_results,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
toolbar=self.toolbar_2
|
toolbar=self.toolbar_2,
|
||||||
|
parent=self
|
||||||
)
|
)
|
||||||
self.plot_rkc.draw()
|
self.plot_rkc.draw()
|
||||||
|
|
||||||
@@ -227,8 +247,10 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
results=self._results,
|
results=self._results,
|
||||||
reach_id=0,
|
reach_id=0,
|
||||||
profile_id=0,
|
profile_id=0,
|
||||||
|
res_id=self._current_results,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
toolbar=self.toolbar_3
|
toolbar=self.toolbar_3,
|
||||||
|
parent=self
|
||||||
)
|
)
|
||||||
self.plot_ac.draw()
|
self.plot_ac.draw()
|
||||||
|
|
||||||
@@ -249,9 +271,11 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
canvas=self.canvas_4,
|
canvas=self.canvas_4,
|
||||||
results=self._results,
|
results=self._results,
|
||||||
reach_id=0,
|
reach_id=0,
|
||||||
profile_id=0,
|
profile_id=[0],
|
||||||
|
res_id=self._current_results,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
toolbar=self.toolbar_4
|
toolbar=self.toolbar_4,
|
||||||
|
parent=self
|
||||||
)
|
)
|
||||||
self.plot_h.draw()
|
self.plot_h.draw()
|
||||||
|
|
||||||
@@ -264,16 +288,12 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
super(ResultsWindow, self).closeEvent(event)
|
super(ResultsWindow, self).closeEvent(event)
|
||||||
|
|
||||||
def _compute_status_label(self):
|
def _compute_status_label(self):
|
||||||
# Timestamp
|
|
||||||
ts = self._timestamps[self._slider_time.value()]
|
|
||||||
|
|
||||||
t0 = datetime.fromtimestamp(0)
|
return (self.text_bief() + " | " +
|
||||||
fts = str(
|
self.text_profile() + " | " +
|
||||||
datetime.fromtimestamp(ts) - t0
|
self.text_time())
|
||||||
)
|
|
||||||
fts.replace("days", _translate("Results", "days"))\
|
|
||||||
.replace("day", _translate("Results", "day"))
|
|
||||||
|
|
||||||
|
def text_bief(self):
|
||||||
# Reach
|
# Reach
|
||||||
table = self.find(QTableView, f"tableView_reach")
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
indexes = table.selectedIndexes()
|
indexes = table.selectedIndexes()
|
||||||
@@ -281,7 +301,16 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
reach = self._study.river.enable_edges()[0]
|
reach = self._study.river.enable_edges()[0]
|
||||||
else:
|
else:
|
||||||
reach = self._study.river.enable_edges()[indexes[0].row()]
|
reach = self._study.river.enable_edges()[indexes[0].row()]
|
||||||
|
return f"{self._trad['reach']}: {reach.name}"
|
||||||
|
|
||||||
|
def text_profile(self):
|
||||||
|
# Reach
|
||||||
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
reach = self._study.river.enable_edges()[0]
|
||||||
|
else:
|
||||||
|
reach = self._study.river.enable_edges()[indexes[0].row()]
|
||||||
# Profile
|
# Profile
|
||||||
table = self.find(QTableView, f"tableView_profile")
|
table = self.find(QTableView, f"tableView_profile")
|
||||||
indexes = table.selectedIndexes()
|
indexes = table.selectedIndexes()
|
||||||
@@ -291,10 +320,22 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
profile = reach.reach.profile(indexes[0].row())
|
profile = reach.reach.profile(indexes[0].row())
|
||||||
|
|
||||||
pname = profile.name if profile.name != "" else profile.rk
|
pname = profile.name if profile.name != "" else profile.rk
|
||||||
|
return f"{self._trad['cross_section']}: {pname}"
|
||||||
|
|
||||||
return (f"{self._trad['reach']}: {reach.name} | " +
|
def text_time(self):
|
||||||
f"{self._trad['cross_section']}: {pname} | " +
|
# Timestamp
|
||||||
f"{self._trad['unit_time_s']} : {fts} ({ts} sec)")
|
ts = self._timestamps[self._slider_time.value()]
|
||||||
|
|
||||||
|
t0 = datetime.fromtimestamp(0)
|
||||||
|
fts = str(
|
||||||
|
datetime.fromtimestamp(ts) - t0
|
||||||
|
)
|
||||||
|
fts = str(
|
||||||
|
datetime.fromtimestamp(ts) - t0
|
||||||
|
)
|
||||||
|
fts.replace("days", _translate("Results", "days"))\
|
||||||
|
.replace("day", _translate("Results", "day"))
|
||||||
|
return f"{self._trad['time']} : {fts} ({ts} sec)"
|
||||||
|
|
||||||
def setup_statusbar(self):
|
def setup_statusbar(self):
|
||||||
txt = self._compute_status_label()
|
txt = self._compute_status_label()
|
||||||
@@ -312,7 +353,13 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
"action_add": self._add_custom_plot,
|
"action_add": self._add_custom_plot,
|
||||||
"action_export": self._export,
|
"action_export": self._export,
|
||||||
# "action_export": self.export_current,
|
# "action_export": self.export_current,
|
||||||
|
"action_Geo_tiff": self.import_geotiff
|
||||||
}
|
}
|
||||||
|
self.find(QAction, "action_Geo_tiff").setEnabled(False)
|
||||||
|
self.find(QAction, "action_Geo_tiff").setVisible(False)
|
||||||
|
|
||||||
|
if len(self._results) > 1:
|
||||||
|
self.find(QAction, "action_reload").setEnabled(False)
|
||||||
|
|
||||||
for action in actions:
|
for action in actions:
|
||||||
self.find(QAction, action).triggered.connect(
|
self.find(QAction, action).triggered.connect(
|
||||||
@@ -324,9 +371,10 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
"reach": self._set_current_reach,
|
"reach": self._set_current_reach,
|
||||||
"profile": self._set_current_profile,
|
"profile": self._set_current_profile,
|
||||||
"raw_data": self._set_current_profile_raw_data,
|
"raw_data": self._set_current_profile_raw_data,
|
||||||
|
"solver": self._set_current_results,
|
||||||
}
|
}
|
||||||
|
|
||||||
for t in ["reach", "profile", "raw_data"]:
|
for t in ["reach", "profile", "raw_data", "solver"]:
|
||||||
table = self.find(QTableView, f"tableView_{t}")
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
|
|
||||||
table.selectionModel()\
|
table.selectionModel()\
|
||||||
@@ -344,6 +392,10 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
self._button_last.clicked.connect(self._last)
|
self._button_last.clicked.connect(self._last)
|
||||||
self._timer.timeout.connect(self._update_slider)
|
self._timer.timeout.connect(self._update_slider)
|
||||||
|
|
||||||
|
# tabs
|
||||||
|
tab_widget = self.find(QTabWidget, f"tabWidget")
|
||||||
|
tab_widget.currentChanged.connect(self.tab_changed)
|
||||||
|
|
||||||
def update_table_selection_reach(self, ind):
|
def update_table_selection_reach(self, ind):
|
||||||
table = self.find(QTableView, f"tableView_reach")
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
selectionModel = table.selectionModel()
|
selectionModel = table.selectionModel()
|
||||||
@@ -374,7 +426,25 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
)
|
)
|
||||||
table.scrollTo(index)
|
table.scrollTo(index)
|
||||||
|
|
||||||
def update(self, reach_id=None, profile_id=None, timestamp=None):
|
def update_table_selection_solver(self, ind):
|
||||||
|
table = self.find(QTableView, f"tableView_solver")
|
||||||
|
selectionModel = table.selectionModel()
|
||||||
|
index = table.model().index(ind, 0)
|
||||||
|
|
||||||
|
selectionModel.select(
|
||||||
|
index,
|
||||||
|
QItemSelectionModel.Rows |
|
||||||
|
QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Select
|
||||||
|
)
|
||||||
|
table.scrollTo(index)
|
||||||
|
|
||||||
|
def update(self,
|
||||||
|
reach_id=None,
|
||||||
|
profile_id=None,
|
||||||
|
solver_id=None,
|
||||||
|
timestamp=None):
|
||||||
|
|
||||||
if reach_id is not None:
|
if reach_id is not None:
|
||||||
self.plot_xy.set_reach(reach_id)
|
self.plot_xy.set_reach(reach_id)
|
||||||
self.plot_ac.set_reach(reach_id)
|
self.plot_ac.set_reach(reach_id)
|
||||||
@@ -388,15 +458,27 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
self.update_table_selection_profile(0)
|
self.update_table_selection_profile(0)
|
||||||
|
|
||||||
if profile_id is not None:
|
if profile_id is not None:
|
||||||
self.plot_xy.set_profile(profile_id)
|
self.plot_xy.set_profile(profile_id[0])
|
||||||
self.plot_ac.set_profile(profile_id)
|
self.plot_ac.set_profile(profile_id[0])
|
||||||
self.plot_rkc.set_profile(profile_id)
|
self.plot_rkc.set_profile(profile_id[0])
|
||||||
self.plot_h.set_profile(profile_id)
|
self.plot_h.set_profile(profile_id)
|
||||||
|
|
||||||
for plot in self._additional_plot:
|
for plot in self._additional_plot:
|
||||||
self._additional_plot[plot].set_profile(profile_id)
|
self._additional_plot[plot].set_profile(profile_id[0])
|
||||||
|
|
||||||
self.update_table_selection_profile(profile_id)
|
tab_widget = self.find(QTabWidget, f"tabWidget")
|
||||||
|
if tab_widget.currentIndex() != 2:
|
||||||
|
self.update_table_selection_profile(profile_id[0])
|
||||||
|
|
||||||
|
if solver_id is not None:
|
||||||
|
self._current_results = solver_id
|
||||||
|
self.plot_xy.set_result(solver_id)
|
||||||
|
self.plot_ac.set_result(solver_id)
|
||||||
|
self.plot_rkc.set_result(solver_id)
|
||||||
|
self.plot_h.set_result(solver_id)
|
||||||
|
|
||||||
|
for plot in self._additional_plot:
|
||||||
|
self._additional_plot[plot].set_result(solver_id)
|
||||||
|
|
||||||
if timestamp is not None:
|
if timestamp is not None:
|
||||||
self.plot_xy.set_timestamp(timestamp)
|
self.plot_xy.set_timestamp(timestamp)
|
||||||
@@ -427,6 +509,14 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
|
|
||||||
return indexes[0].row()
|
return indexes[0].row()
|
||||||
|
|
||||||
|
def _get_current_profiles_list(self):
|
||||||
|
table = self.find(QTableView, f"tableView_profile")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return [i.row() for i in indexes]
|
||||||
|
|
||||||
def _get_current_timestamp(self):
|
def _get_current_timestamp(self):
|
||||||
return self._timestamps[
|
return self._timestamps[
|
||||||
self._slider_time.value()
|
self._slider_time.value()
|
||||||
@@ -442,21 +532,22 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
|
|
||||||
def _set_current_profile(self):
|
def _set_current_profile(self):
|
||||||
table = self.find(QTableView, f"tableView_profile")
|
table = self.find(QTableView, f"tableView_profile")
|
||||||
indexes = table.selectedIndexes()
|
indexes = table.selectionModel().selectedRows()
|
||||||
if len(indexes) == 0:
|
if len(indexes) == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
ind = indexes[0].row()
|
self.update(profile_id=[i.row() for i in indexes])
|
||||||
self.update(profile_id=ind)
|
|
||||||
|
|
||||||
def _set_current_profile_raw_data(self):
|
def _set_current_profile_raw_data(self):
|
||||||
table = self.find(QTableView, f"tableView_raw_data")
|
return
|
||||||
|
|
||||||
|
def _set_current_results(self):
|
||||||
|
table = self.find(QTableView, f"tableView_solver")
|
||||||
indexes = table.selectedIndexes()
|
indexes = table.selectedIndexes()
|
||||||
if len(indexes) == 0:
|
if len(indexes) == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
ind = indexes[0].row()
|
self.update(solver_id=[i.row() for i in indexes])
|
||||||
self.update(profile_id=ind)
|
|
||||||
|
|
||||||
def _set_current_timestamp(self):
|
def _set_current_timestamp(self):
|
||||||
timestamp = self._timestamps[self._slider_time.value()]
|
timestamp = self._timestamps[self._slider_time.value()]
|
||||||
@@ -480,14 +571,17 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
|
|
||||||
def _reload(self):
|
def _reload(self):
|
||||||
logger.debug("Reload results...")
|
logger.debug("Reload results...")
|
||||||
self._results = self._results.reload()
|
if len(self._results) == 1:
|
||||||
|
self._results[0] = self._results[0].reload()
|
||||||
|
|
||||||
self._timestamps = sorted(list(self._results.get("timestamps")))
|
self.get_timestamps()
|
||||||
|
|
||||||
self._reload_plots()
|
self._reload_plots()
|
||||||
self._reload_slider()
|
self._reload_slider()
|
||||||
|
|
||||||
def _add_custom_plot(self):
|
def _add_custom_plot(self):
|
||||||
|
profile_id = self._get_current_profile()
|
||||||
|
self.update_table_selection_profile(profile_id)
|
||||||
dlg = CustomPlotValuesSelectionDialog(parent=self)
|
dlg = CustomPlotValuesSelectionDialog(parent=self)
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
x, y, envelop = dlg.value
|
x, y, envelop = dlg.value
|
||||||
@@ -526,6 +620,7 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
self._get_current_timestamp(),
|
self._get_current_timestamp(),
|
||||||
data=self._results,
|
data=self._results,
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
|
res_id=self._current_results,
|
||||||
toolbar=toolbar,
|
toolbar=toolbar,
|
||||||
parent=self,
|
parent=self,
|
||||||
)
|
)
|
||||||
@@ -541,7 +636,26 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
tab_widget.setCurrentWidget(widget)
|
tab_widget.setCurrentWidget(widget)
|
||||||
|
|
||||||
def _copy(self):
|
def _copy(self):
|
||||||
logger.info("TODO: copy")
|
# focus on raw data table
|
||||||
|
if self.find(QTabWidget, f"tabWidget").currentIndex() == 0:
|
||||||
|
table = self.find(QTableView, f"tableView_raw_data")
|
||||||
|
model = self._table["raw_data"]
|
||||||
|
|
||||||
|
coltext = []
|
||||||
|
for index in sorted(table.selectionModel().selectedRows()):
|
||||||
|
row = index.row()
|
||||||
|
rowtext = []
|
||||||
|
for column in range(model.columnCount()):
|
||||||
|
i = model.createIndex(row, column)
|
||||||
|
try:
|
||||||
|
rowtext.append(model.data(i))
|
||||||
|
except AttributeError:
|
||||||
|
rowtext.append("")
|
||||||
|
coltext.append(rowtext)
|
||||||
|
|
||||||
|
self.copyTableIntoClipboard(coltext)
|
||||||
|
else:
|
||||||
|
logger.info("TODO: copy")
|
||||||
|
|
||||||
def _paste(self):
|
def _paste(self):
|
||||||
logger.info("TODO: paste")
|
logger.info("TODO: paste")
|
||||||
@@ -588,10 +702,12 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
self._button_play.setIcon(self._icon_start)
|
self._button_play.setIcon(self._icon_start)
|
||||||
|
|
||||||
def _export(self):
|
def _export(self):
|
||||||
|
profile_id = self._get_current_profile()
|
||||||
|
self.update_table_selection_profile(profile_id)
|
||||||
|
|
||||||
dlg = CustomPlotValuesSelectionDialog(parent=self)
|
dlg = CustomExportDialog(parent=self)
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
x, y, envelop = dlg.value
|
x, y, envelop, solver_id = dlg.value
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -601,41 +717,50 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
)
|
)
|
||||||
self.file_dialog(
|
self.file_dialog(
|
||||||
select_file="AnyFile",
|
select_file="AnyFile",
|
||||||
callback=lambda f: self.export_to(f[0], x, y, envelop),
|
callback=lambda f: self.export_to(f[0], x, y, envelop, solver_id),
|
||||||
default_suffix=".csv",
|
default_suffix=".csv",
|
||||||
file_filter=["CSV (*.csv)"],
|
file_filter=["CSV (*.csv)"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def export_to(self, filename, x, y, envelop):
|
def export_to(self, filename, x, y, envelop, solver_id):
|
||||||
timestamps = sorted(self._results.get("timestamps"))
|
results = self._results[solver_id]
|
||||||
reach = self._results.river.reachs[self._get_current_reach()]
|
reach = results.river.reachs[self._get_current_reach()]
|
||||||
first_line = [f"Study: {self._results.study.name}",
|
first_line = [f"Study: {results.study.name}",
|
||||||
f"Reach: {reach.name}"]
|
f"Reach: {reach.name}"]
|
||||||
if x == "rk":
|
if x == "rk":
|
||||||
timestamp = self._get_current_timestamp()
|
timestamp = self._get_current_timestamp()
|
||||||
first_line.append(f"Time: {timestamp}s")
|
first_line.append(f"Time: {timestamp}s")
|
||||||
val_dict = self._export_rk(timestamp, y, envelop)
|
val_dict = self._export_rk(timestamp, y, envelop, solver_id)
|
||||||
elif x == "time":
|
elif x == "time":
|
||||||
profile_id = self._get_current_profile()
|
profile_id = self._get_current_profile()
|
||||||
profile = reach.profile(profile_id)
|
profile = reach.profile(profile_id)
|
||||||
pname = profile.name if profile.name != "" else profile.rk
|
pname = profile.name if profile.name != "" else profile.rk
|
||||||
first_line.append(f"Profile: {pname}")
|
first_line.append(f"Profile: {pname}")
|
||||||
val_dict = self._export_time(profile_id, y)
|
val_dict = self._export_time(profile_id, y, solver_id)
|
||||||
|
|
||||||
with open(filename, 'w', newline='') as csvfile:
|
try:
|
||||||
writer = csv.writer(csvfile, delimiter=',',
|
with open(filename, 'w', newline='') as csvfile:
|
||||||
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
writer = csv.writer(csvfile, delimiter=',',
|
||||||
dict_x = self._trad.get_dict("values_x")
|
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||||
header = []
|
dict_x = self._trad.get_dict("values_x")
|
||||||
writer.writerow(first_line)
|
header = []
|
||||||
for text in val_dict.keys():
|
writer.writerow(first_line)
|
||||||
header.append(text)
|
for text in val_dict.keys():
|
||||||
writer.writerow(header)
|
header.append(text)
|
||||||
for row in range(len(val_dict[dict_x[x]])):
|
writer.writerow(header)
|
||||||
line = []
|
for row in range(len(val_dict[dict_x[x]])):
|
||||||
for var in val_dict.keys():
|
line = []
|
||||||
line.append(val_dict[var][row])
|
for var in val_dict.keys():
|
||||||
writer.writerow(line)
|
line.append(val_dict[var][row])
|
||||||
|
writer.writerow(line)
|
||||||
|
self._timer.stop()
|
||||||
|
except Exception as e:
|
||||||
|
self.message_box(
|
||||||
|
window_title=self._trad["Warning"],
|
||||||
|
text=self._trad["mb_write_error"],
|
||||||
|
informative_text=self._trad["mb_close_file"]
|
||||||
|
)
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
def export_all(self, reach, directory, timestamps):
|
def export_all(self, reach, directory, timestamps):
|
||||||
name = reach.name
|
name = reach.name
|
||||||
@@ -648,17 +773,25 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
f"reach_{name}.csv"
|
f"reach_{name}.csv"
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(file_name, 'w', newline='') as csvfile:
|
try:
|
||||||
writer = csv.writer(csvfile, delimiter=',',
|
with open(file_name, 'w', newline='') as csvfile:
|
||||||
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
writer = csv.writer(csvfile, delimiter=',',
|
||||||
ts = timestamps[0]
|
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||||
writer.writerow(self._table["raw_data"]._headers)
|
ts = timestamps[0]
|
||||||
for row in range(self._table["raw_data"].rowCount()):
|
writer.writerow(self._table["raw_data"]._headers)
|
||||||
line = []
|
for row in range(self._table["raw_data"].rowCount()):
|
||||||
for column in range(self._table["raw_data"].columnCount()):
|
line = []
|
||||||
index = self._table["raw_data"].index(row, column)
|
for column in range(self._table["raw_data"].columnCount()):
|
||||||
line.append(self._table["raw_data"].data(index))
|
index = self._table["raw_data"].index(row, column)
|
||||||
writer.writerow(line)
|
line.append(self._table["raw_data"].data(index))
|
||||||
|
writer.writerow(line)
|
||||||
|
except Exception as e:
|
||||||
|
self.message_box(
|
||||||
|
window_title=self._trad["Warning"],
|
||||||
|
text=self._trad["mb_write_errore"],
|
||||||
|
informative_text=self._trad["mb_close_file"]
|
||||||
|
)
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
def export_current(self):
|
def export_current(self):
|
||||||
self.file_dialog(
|
self.file_dialog(
|
||||||
@@ -667,7 +800,8 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def export_current_to(self, directory):
|
def export_current_to(self, directory):
|
||||||
reach = self._results.river.reachs[self._get_current_reach()]
|
results = self._results[self._current_results]
|
||||||
|
reach = results.river.reachs[self._get_current_reach()]
|
||||||
self.export_all(reach, directory, [self._get_current_timestamp()])
|
self.export_all(reach, directory, [self._get_current_timestamp()])
|
||||||
|
|
||||||
def delete_tab(self, index):
|
def delete_tab(self, index):
|
||||||
@@ -675,16 +809,32 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
self._additional_plot.pop(tab_widget.tabText(index))
|
self._additional_plot.pop(tab_widget.tabText(index))
|
||||||
tab_widget.removeTab(index)
|
tab_widget.removeTab(index)
|
||||||
|
|
||||||
def _export_rk(self, timestamp, y, envelop):
|
def _export_rk(self, timestamp, y, envelop, solver_id):
|
||||||
reach = self._results.river.reachs[self._get_current_reach()]
|
results = self._results[solver_id]
|
||||||
|
reach = results.river.reachs[self._get_current_reach()]
|
||||||
dict_x = self._trad.get_dict("values_x")
|
dict_x = self._trad.get_dict("values_x")
|
||||||
dict_y = self._trad.get_dict("values_y")
|
dict_y = self._trad.get_dict("values_y")
|
||||||
|
if self._current_results == 2:
|
||||||
|
envelop = False
|
||||||
|
reach1 = results[0].river.reachs[self._get_current_reach()]
|
||||||
|
reach2 = results[1].river.reachs[self._get_current_reach()]
|
||||||
if envelop:
|
if envelop:
|
||||||
dict_y.update(self._trad.get_dict("values_y_envelop"))
|
dict_y.update(self._trad.get_dict("values_y_envelop"))
|
||||||
my_dict = {}
|
my_dict = {}
|
||||||
my_dict[dict_x["rk"]] = reach.geometry.get_rk()
|
my_dict[dict_x["rk"]] = reach.geometry.get_rk()
|
||||||
if "bed_elevation" in y:
|
if "bed_elevation" in y:
|
||||||
my_dict[dict_y["bed_elevation"]] = reach.geometry.get_z_min()
|
if self._current_results != 2:
|
||||||
|
zmin = reach.geometry.get_z_min()
|
||||||
|
else:
|
||||||
|
z_min1 = reach1.geometry.get_z_min()
|
||||||
|
z_min2 = reach2.geometry.get_z_min()
|
||||||
|
zmin = list(
|
||||||
|
map(
|
||||||
|
lambda x, y: x - y,
|
||||||
|
z_min2, z_min2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["bed_elevation"]] = zmin
|
||||||
# if envelop and reach.has_sediment():
|
# if envelop and reach.has_sediment():
|
||||||
if "discharge" in y:
|
if "discharge" in y:
|
||||||
my_dict[dict_y["discharge"]] = list(
|
my_dict[dict_y["discharge"]] = list(
|
||||||
@@ -744,13 +894,36 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
my_dict[dict_y["max_velocity"]] = [max(v) for v in velocities]
|
my_dict[dict_y["max_velocity"]] = [max(v) for v in velocities]
|
||||||
|
|
||||||
if "depth" in y:
|
if "depth" in y:
|
||||||
my_dict[dict_y["depth"]] = list(
|
if self._current_results != 2:
|
||||||
map(
|
d = my_dict[dict_y["depth"]] = list(
|
||||||
lambda p: p.geometry.max_water_depth(
|
map(
|
||||||
p.get_ts_key(timestamp, "Z")),
|
lambda p: p.geometry.max_water_depth(
|
||||||
reach.profiles
|
p.get_ts_key(timestamp, "Z")),
|
||||||
|
reach.profiles
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
else:
|
||||||
|
d1 = list(
|
||||||
|
map(
|
||||||
|
lambda p: p.geometry.max_water_depth(
|
||||||
|
p.get_ts_key(timestamp, "Z")),
|
||||||
|
reach1.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
d2 = list(
|
||||||
|
map(
|
||||||
|
lambda p: p.geometry.max_water_depth(
|
||||||
|
p.get_ts_key(timestamp, "Z")),
|
||||||
|
reach2.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
d = list(
|
||||||
|
map(
|
||||||
|
lambda x, y: x - y,
|
||||||
|
d1, d2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["depth"]] = d
|
||||||
if envelop:
|
if envelop:
|
||||||
my_dict[dict_y["min_depth"]] = list(map(
|
my_dict[dict_y["min_depth"]] = list(map(
|
||||||
lambda p1, p2: p1 - p2, map(
|
lambda p1, p2: p1 - p2, map(
|
||||||
@@ -768,53 +941,157 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if "mean_depth" in y:
|
if "mean_depth" in y:
|
||||||
my_dict[dict_y["mean_depth"]] = list(
|
if self._current_results != 2:
|
||||||
map(
|
d = list(
|
||||||
lambda p: p.geometry.mean_water_depth(
|
map(
|
||||||
p.get_ts_key(timestamp, "Z")),
|
lambda p: p.geometry.mean_water_depth(
|
||||||
reach.profiles
|
p.get_ts_key(timestamp, "Z")),
|
||||||
|
reach.profiles
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
else:
|
||||||
|
d1 = list(
|
||||||
|
map(
|
||||||
|
lambda p: p.geometry.mean_water_depth(
|
||||||
|
p.get_ts_key(timestamp, "Z")),
|
||||||
|
reach1.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
d2 = list(
|
||||||
|
map(
|
||||||
|
lambda p: p.geometry.mean_water_depth(
|
||||||
|
p.get_ts_key(timestamp, "Z")),
|
||||||
|
reach2.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
d = list(
|
||||||
|
map(
|
||||||
|
lambda x, y: x - y,
|
||||||
|
d1, d2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["mean_depth"]] = d
|
||||||
if "froude" in y:
|
if "froude" in y:
|
||||||
my_dict[dict_y["froude"]] = list(
|
if self._current_results != 2:
|
||||||
map(
|
fr = my_dict[dict_y["froude"]] = list(
|
||||||
lambda p:
|
map(
|
||||||
p.get_ts_key(timestamp, "V") /
|
lambda p:
|
||||||
sqrt(9.81 * (
|
p.get_ts_key(timestamp, "V") /
|
||||||
p.geometry.wet_area(
|
sqrt(9.81 * (
|
||||||
p.get_ts_key(timestamp, "Z")) /
|
p.geometry.wet_area(
|
||||||
p.geometry.wet_width(
|
p.get_ts_key(timestamp, "Z")) /
|
||||||
p.get_ts_key(timestamp, "Z"))
|
p.geometry.wet_width(
|
||||||
)),
|
p.get_ts_key(timestamp, "Z"))
|
||||||
reach.profiles
|
)),
|
||||||
|
reach.profiles
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
else:
|
||||||
|
fr1 = list(
|
||||||
|
map(
|
||||||
|
lambda p:
|
||||||
|
p.get_ts_key(timestamp, "V") /
|
||||||
|
sqrt(9.81 * (
|
||||||
|
p.geometry.wet_area(
|
||||||
|
p.get_ts_key(timestamp, "Z")) /
|
||||||
|
p.geometry.wet_width(
|
||||||
|
p.get_ts_key(timestamp, "Z"))
|
||||||
|
)),
|
||||||
|
reach1.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fr2 = list(
|
||||||
|
map(
|
||||||
|
lambda p:
|
||||||
|
p.get_ts_key(timestamp, "V") /
|
||||||
|
sqrt(9.81 * (
|
||||||
|
p.geometry.wet_area(
|
||||||
|
p.get_ts_key(timestamp, "Z")) /
|
||||||
|
p.geometry.wet_width(
|
||||||
|
p.get_ts_key(timestamp, "Z"))
|
||||||
|
)),
|
||||||
|
reach2.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fr = list(
|
||||||
|
map(
|
||||||
|
lambda x, y: x - y,
|
||||||
|
fr1, fr2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["froude"]] = fr
|
||||||
if "wet_area" in y:
|
if "wet_area" in y:
|
||||||
my_dict[dict_y["wet_area"]] = list(
|
if self._current_results != 2:
|
||||||
map(
|
wa = list(
|
||||||
lambda p: p.geometry.wet_area(
|
map(
|
||||||
p.get_ts_key(timestamp, "Z")),
|
lambda p: p.geometry.wet_area(
|
||||||
reach.profiles
|
p.get_ts_key(timestamp, "Z")),
|
||||||
|
reach.profiles
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
else:
|
||||||
|
wa1 = list(
|
||||||
|
map(
|
||||||
|
lambda p: p.geometry.wet_area(
|
||||||
|
p.get_ts_key(timestamp, "Z")),
|
||||||
|
reach1.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
wa2 = list(
|
||||||
|
map(
|
||||||
|
lambda p: p.geometry.wet_area(
|
||||||
|
p.get_ts_key(timestamp, "Z")),
|
||||||
|
reach2.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
wa = list(
|
||||||
|
map(
|
||||||
|
lambda x, y: x - y,
|
||||||
|
wa1, wa2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["wet_area"]] = wa
|
||||||
|
|
||||||
return my_dict
|
return my_dict
|
||||||
|
|
||||||
def _export_time(self, profile, y):
|
def _export_time(self, profile, y, solver_id):
|
||||||
reach = self._results.river.reachs[self._get_current_reach()]
|
results = self._results[solver_id]
|
||||||
|
reach = results.river.reachs[self._get_current_reach()]
|
||||||
profile = reach.profile(profile)
|
profile = reach.profile(profile)
|
||||||
ts = list(self._results.get("timestamps"))
|
|
||||||
ts.sort()
|
|
||||||
dict_x = self._trad.get_dict("values_x")
|
dict_x = self._trad.get_dict("values_x")
|
||||||
dict_y = self._trad.get_dict("values_y")
|
dict_y = self._trad.get_dict("values_y")
|
||||||
my_dict = {}
|
my_dict = {}
|
||||||
my_dict[dict_x["time"]] = ts
|
my_dict[dict_x["time"]] = self._timestamps
|
||||||
z = profile.get_key("Z")
|
z = profile.get_key("Z")
|
||||||
q = profile.get_key("Q")
|
q = profile.get_key("Q")
|
||||||
v = profile.get_key("V")
|
v = profile.get_key("V")
|
||||||
|
if self._current_results == 2:
|
||||||
|
reach1 = self._results[0].river.reach(self._reach)
|
||||||
|
reach2 = self._results[1].river.reach(self._reach)
|
||||||
|
profile1 = reach1.profile(self._profile)
|
||||||
|
profile2 = reach2.profile(self._profile)
|
||||||
|
|
||||||
|
q1 = profile1.get_key("Q")
|
||||||
|
z1 = profile1.get_key("Z")
|
||||||
|
v1 = profile1.get_key("V")
|
||||||
|
|
||||||
|
q2 = profile2.get_key("Q")
|
||||||
|
z2 = profile2.get_key("Z")
|
||||||
|
v2 = profile2.get_key("V")
|
||||||
|
|
||||||
if "bed_elevation" in y:
|
if "bed_elevation" in y:
|
||||||
my_dict[dict_y["bed_elevation"]] = [
|
if self._current_results != 2:
|
||||||
profile.geometry.z_min()] * len(ts)
|
z_min = [profile.geometry.z_min()] * len(self._timestamps)
|
||||||
|
else:
|
||||||
|
z_min1 = profile1.geometry.z_min()
|
||||||
|
z_min2 = profile2.geometry.z_min()
|
||||||
|
z_min = list(
|
||||||
|
map(
|
||||||
|
lambda ts: z_min1 - z_min2,
|
||||||
|
self._timestamps
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["bed_elevation"]] = z_min
|
||||||
if "discharge" in y:
|
if "discharge" in y:
|
||||||
my_dict[dict_y["discharge"]] = q
|
my_dict[dict_y["discharge"]] = q
|
||||||
if "water_elevation" in y:
|
if "water_elevation" in y:
|
||||||
@@ -822,24 +1099,107 @@ class ResultsWindow(PamhyrWindow):
|
|||||||
if "velocity" in y:
|
if "velocity" in y:
|
||||||
my_dict[dict_y["velocity"]] = v
|
my_dict[dict_y["velocity"]] = v
|
||||||
if "depth" in y:
|
if "depth" in y:
|
||||||
my_dict[dict_y["depth"]] = list(
|
if self._current_results != 2:
|
||||||
map(lambda z: profile.geometry.max_water_depth(z), z)
|
d = list(
|
||||||
)
|
map(lambda z: profile.geometry.max_water_depth(z), z)
|
||||||
if "mean_depth" in y:
|
|
||||||
my_dict[dict_y["mean_depth"]] = list(
|
|
||||||
map(lambda z: profile.geometry.mean_water_depth(z), z)
|
|
||||||
)
|
|
||||||
if "froude" in y:
|
|
||||||
my_dict[dict_y["froude"]] = list(
|
|
||||||
map(lambda z, v:
|
|
||||||
v / sqrt(9.81 * (
|
|
||||||
profile.geometry.wet_area(z) /
|
|
||||||
profile.geometry.wet_width(z))
|
|
||||||
), z, v)
|
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
d1 = list(
|
||||||
|
map(lambda z: profile1.geometry.max_water_depth(z), z1)
|
||||||
|
)
|
||||||
|
d2 = list(
|
||||||
|
map(lambda z: profile2.geometry.max_water_depth(z), z2)
|
||||||
|
)
|
||||||
|
d = list(
|
||||||
|
map(
|
||||||
|
lambda x, y: x - y,
|
||||||
|
d1, d2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["depth"]] = d
|
||||||
|
if "mean_depth" in y:
|
||||||
|
if self._current_results != 2:
|
||||||
|
d = list(
|
||||||
|
map(lambda z: profile.geometry.mean_water_depth(z), z)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
d1 = list(
|
||||||
|
map(lambda z: profile1.geometry.mean_water_depth(z), z1)
|
||||||
|
)
|
||||||
|
d2 = list(
|
||||||
|
map(lambda z: profile2.geometry.mean_water_depth(z), z2)
|
||||||
|
)
|
||||||
|
d = list(
|
||||||
|
map(
|
||||||
|
lambda x, y: x - y,
|
||||||
|
d1, d2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["mean_depth"]] = d
|
||||||
|
if "froude" in y:
|
||||||
|
if self._current_results != 2:
|
||||||
|
fr = my_dict[dict_y["froude"]] = list(
|
||||||
|
map(lambda z, v:
|
||||||
|
v / sqrt(9.81 * (
|
||||||
|
profile.geometry.wet_area(z) /
|
||||||
|
profile.geometry.wet_width(z))
|
||||||
|
), z, v)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
fr1 = list(
|
||||||
|
map(lambda z, v:
|
||||||
|
v /
|
||||||
|
sqrt(9.81 * (
|
||||||
|
profile1.geometry.wet_area(z) /
|
||||||
|
profile1.geometry.wet_width(z))
|
||||||
|
), z1, v1)
|
||||||
|
)
|
||||||
|
fr2 = list(
|
||||||
|
map(lambda z, v:
|
||||||
|
v /
|
||||||
|
sqrt(9.81 * (
|
||||||
|
profile2.geometry.wet_area(z) /
|
||||||
|
profile2.geometry.wet_width(z))
|
||||||
|
), z2, v2)
|
||||||
|
)
|
||||||
|
fr = list(
|
||||||
|
map(
|
||||||
|
lambda x, y: x - y,
|
||||||
|
fr1, fr2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["froude"]] = fr
|
||||||
if "wet_area" in y:
|
if "wet_area" in y:
|
||||||
my_dict[dict_y["wet_area"]] = list(
|
if self._current_results != 2:
|
||||||
map(lambda z: profile.geometry.wet_area(z), z)
|
wa = list(
|
||||||
)
|
map(lambda z: profile.geometry.wet_area(z), z)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
wa1 = list(
|
||||||
|
map(lambda z: profile1.geometry.wet_area(z), z1)
|
||||||
|
)
|
||||||
|
wa2 = list(
|
||||||
|
map(lambda z: profile2.geometry.wet_area(z), z2)
|
||||||
|
)
|
||||||
|
wa = list(
|
||||||
|
map(
|
||||||
|
lambda x, y: x - y,
|
||||||
|
wa1, wa2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
my_dict[dict_y["wet_area"]] = wa
|
||||||
|
|
||||||
return my_dict
|
return my_dict
|
||||||
|
|
||||||
|
def get_timestamps(self):
|
||||||
|
self._timestamps = sorted(list(self._results[0].get("timestamps")))
|
||||||
|
|
||||||
|
def tab_changed(self, i):
|
||||||
|
if i != 2:
|
||||||
|
if len(self._get_current_profiles_list()) > 1:
|
||||||
|
# unselect all profiles but the first one
|
||||||
|
profile_id = self._get_current_profile()
|
||||||
|
self.update_table_selection_profile(profile_id)
|
||||||
|
|
||||||
|
def import_geotiff(self):
|
||||||
|
return
|
||||||
@@ -49,7 +49,7 @@ from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
|||||||
from View.Results.PlotSedAdis import PlotAdis_dx, PlotAdis_dt
|
from View.Results.PlotSedAdis import PlotAdis_dx, PlotAdis_dt
|
||||||
|
|
||||||
from View.Results.CustomPlot.Plot import CustomPlot
|
from View.Results.CustomPlot.Plot import CustomPlot
|
||||||
from View.Results.CustomExportAdis import (
|
from View.Results.CustomExport.CustomExportAdis import (
|
||||||
CustomExportAdisDialog,
|
CustomExportAdisDialog,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -98,7 +98,8 @@ class ResultsWindowAdisTS(PamhyrWindow):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self._hash_data.append(self._solver)
|
self._hash_data.append(self._solver)
|
||||||
self._hash_data.append(self._results)
|
self._hash_data.append(self._results._repertory)
|
||||||
|
self._hash_data.append(self._results._name)
|
||||||
|
|
||||||
self._additional_plot = {}
|
self._additional_plot = {}
|
||||||
self._current_pol_id = [1]
|
self._current_pol_id = [1]
|
||||||
@@ -344,24 +345,29 @@ class ResultsWindowAdisTS(PamhyrWindow):
|
|||||||
super(ResultsWindowAdisTS, self).closeEvent(event)
|
super(ResultsWindowAdisTS, self).closeEvent(event)
|
||||||
|
|
||||||
def _compute_status_label(self):
|
def _compute_status_label(self):
|
||||||
# Timestamp
|
return (self.text_bief() + " | " +
|
||||||
ts = self._timestamps[self._slider_time.value()]
|
self.text_profile() + " | " +
|
||||||
|
self.text_pollutant() + " | " +
|
||||||
t0 = datetime.fromtimestamp(0)
|
self.text_time())
|
||||||
fts = str(
|
|
||||||
datetime.fromtimestamp(ts) - t0
|
|
||||||
)
|
|
||||||
fts.replace("days", _translate("Results", "days"))\
|
|
||||||
.replace("day", _translate("Results", "day"))
|
|
||||||
|
|
||||||
|
def text_bief(self):
|
||||||
# Reach
|
# Reach
|
||||||
table = self.find(QTableView, f"tableView_reach")
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
indexes = table.selectedIndexes()
|
indexes = table.selectedIndexes()
|
||||||
if len(indexes) == 0:
|
if len(indexes) == 0:
|
||||||
reach = self._study.river.edges()[0]
|
reach = self._study.river.enable_edges()[0]
|
||||||
else:
|
else:
|
||||||
reach = self._study.river.edges()[indexes[0].row()]
|
reach = self._study.river.enable_edges()[indexes[0].row()]
|
||||||
|
return f"{self._trad['reach']}: {reach.name}"
|
||||||
|
|
||||||
|
def text_profile(self):
|
||||||
|
# Reach
|
||||||
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
reach = self._study.river.enable_edges()[0]
|
||||||
|
else:
|
||||||
|
reach = self._study.river.enable_edges()[indexes[0].row()]
|
||||||
# Profile
|
# Profile
|
||||||
table = self.find(QTableView, f"tableView_profile")
|
table = self.find(QTableView, f"tableView_profile")
|
||||||
indexes = table.selectedIndexes()
|
indexes = table.selectedIndexes()
|
||||||
@@ -371,7 +377,24 @@ class ResultsWindowAdisTS(PamhyrWindow):
|
|||||||
profile = reach.reach.profile(indexes[0].row())
|
profile = reach.reach.profile(indexes[0].row())
|
||||||
|
|
||||||
pname = profile.name if profile.name != "" else profile.rk
|
pname = profile.name if profile.name != "" else profile.rk
|
||||||
|
return f"{self._trad['cross_section']}: {pname}"
|
||||||
|
|
||||||
|
def text_time(self):
|
||||||
|
# Timestamp
|
||||||
|
ts = self._timestamps[self._slider_time.value()]
|
||||||
|
|
||||||
|
t0 = datetime.fromtimestamp(0)
|
||||||
|
fts = str(
|
||||||
|
datetime.fromtimestamp(ts) - t0
|
||||||
|
)
|
||||||
|
fts = str(
|
||||||
|
datetime.fromtimestamp(ts) - t0
|
||||||
|
)
|
||||||
|
fts.replace("days", _translate("Results", "days"))\
|
||||||
|
.replace("day", _translate("Results", "day"))
|
||||||
|
return f"{self._trad['time']} : {fts} ({ts} sec)"
|
||||||
|
|
||||||
|
def text_pollutant(self):
|
||||||
# Pollutant
|
# Pollutant
|
||||||
table = self.find(QTableView, f"tableView_pollutants")
|
table = self.find(QTableView, f"tableView_pollutants")
|
||||||
indexes = table.selectedIndexes()
|
indexes = table.selectedIndexes()
|
||||||
@@ -380,10 +403,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
|
|||||||
self._results.pollutants_list[i.row()+1] for i in indexes
|
self._results.pollutants_list[i.row()+1] for i in indexes
|
||||||
]
|
]
|
||||||
|
|
||||||
return (f"Reach: {reach.name} | " +
|
return (f"Pollutant: {', '.join(self.pollutant_label)}")
|
||||||
f"Profile: {pname} | " +
|
|
||||||
f"Pollutant: {', '.join(self.pollutant_label)} | " +
|
|
||||||
f"{self._trad['unit_time_s']} : {fts} ({ts} sec)")
|
|
||||||
|
|
||||||
def setup_statusbar(self):
|
def setup_statusbar(self):
|
||||||
txt = self._compute_status_label()
|
txt = self._compute_status_label()
|
||||||
@@ -554,14 +574,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
|
|||||||
self.update(pol_id=rows)
|
self.update(pol_id=rows)
|
||||||
|
|
||||||
def _set_current_profile_raw_data(self):
|
def _set_current_profile_raw_data(self):
|
||||||
table = self.find(QTableView, f"tableView_raw_data")
|
return
|
||||||
indexes = table.selectedIndexes()
|
|
||||||
if len(indexes) == 0:
|
|
||||||
return
|
|
||||||
|
|
||||||
ind = indexes[0].row()
|
|
||||||
self.update(profile_id=ind)
|
|
||||||
self._slider_profile.setValue(ind)
|
|
||||||
|
|
||||||
def _set_current_timestamp(self):
|
def _set_current_timestamp(self):
|
||||||
timestamp = self._timestamps[self._slider_time.value()]
|
timestamp = self._timestamps[self._slider_time.value()]
|
||||||
@@ -597,7 +610,26 @@ class ResultsWindowAdisTS(PamhyrWindow):
|
|||||||
self._reload_slider()
|
self._reload_slider()
|
||||||
|
|
||||||
def _copy(self):
|
def _copy(self):
|
||||||
logger.info("TODO: copy")
|
# focus on raw data table
|
||||||
|
if self.find(QTabWidget, f"tabWidget").currentIndex() == 0:
|
||||||
|
table = self.find(QTableView, f"tableView_raw_data")
|
||||||
|
model = self._table["raw_data"]
|
||||||
|
|
||||||
|
coltext = []
|
||||||
|
for index in sorted(table.selectionModel().selectedRows()):
|
||||||
|
row = index.row()
|
||||||
|
rowtext = []
|
||||||
|
for column in range(model.columnCount()):
|
||||||
|
i = model.createIndex(row, column)
|
||||||
|
try:
|
||||||
|
rowtext.append(str(model.data(i)))
|
||||||
|
except AttributeError:
|
||||||
|
rowtext.append("")
|
||||||
|
coltext.append(rowtext)
|
||||||
|
|
||||||
|
self.copyTableIntoClipboard(coltext)
|
||||||
|
else:
|
||||||
|
logger.info("TODO: copy")
|
||||||
|
|
||||||
def _paste(self):
|
def _paste(self):
|
||||||
logger.info("TODO: paste")
|
logger.info("TODO: paste")
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ class ResultsTranslate(MainTranslate):
|
|||||||
self._dict['day'] = _translate("Results", "day")
|
self._dict['day'] = _translate("Results", "day")
|
||||||
self._dict['days'] = _translate("Results", "days")
|
self._dict['days'] = _translate("Results", "days")
|
||||||
|
|
||||||
self._dict['envelop'] = _translate("Results", "envelop")
|
self._dict['envelop'] = _translate("Results", "Envelop")
|
||||||
|
self._dict['solver'] = _translate("Results", "Solver")
|
||||||
|
|
||||||
self._dict['x'] = _translate("Results", "X (m)")
|
self._dict['x'] = _translate("Results", "X (m)")
|
||||||
|
|
||||||
@@ -52,6 +53,19 @@ class ResultsTranslate(MainTranslate):
|
|||||||
"Results",
|
"Results",
|
||||||
"Max water elevation"
|
"Max water elevation"
|
||||||
)
|
)
|
||||||
|
self._dict["file_all"] = _translate("Results", "All files (*)")
|
||||||
|
self._dict["file_geotiff"] = _translate(
|
||||||
|
"Results", "GeoTIFF file (*.tiff *.tif)")
|
||||||
|
self._dict["ImageCoordinates"] = _translate(
|
||||||
|
"Results", "Image coordinates"
|
||||||
|
)
|
||||||
|
self._dict["mb_write_error"] = _translate(
|
||||||
|
"Results", "An error occured when writing to file"
|
||||||
|
)
|
||||||
|
self._dict["mb_close_file"] = _translate(
|
||||||
|
"Results",
|
||||||
|
"If the file is in use, close it and try again"
|
||||||
|
)
|
||||||
|
|
||||||
self._sub_dict["table_headers_reach"] = {
|
self._sub_dict["table_headers_reach"] = {
|
||||||
"name": _translate("Results", "Reach name"),
|
"name": _translate("Results", "Reach name"),
|
||||||
@@ -62,10 +76,14 @@ class ResultsTranslate(MainTranslate):
|
|||||||
}
|
}
|
||||||
|
|
||||||
self._sub_dict["table_headers_profile"] = {
|
self._sub_dict["table_headers_profile"] = {
|
||||||
"name": self._dict["name"],
|
"name": _translate("Results", "Profile name"),
|
||||||
"rk": self._dict["unit_rk"],
|
"rk": self._dict["unit_rk"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self._sub_dict["table_headers_solver"] = {
|
||||||
|
"solver": self._dict['solver'],
|
||||||
|
}
|
||||||
|
|
||||||
self._sub_dict["table_headers_pollutants"] = {
|
self._sub_dict["table_headers_pollutants"] = {
|
||||||
"name": _translate("Results", "Pollutant name"),
|
"name": _translate("Results", "Pollutant name"),
|
||||||
}
|
}
|
||||||
@@ -134,3 +152,38 @@ class ResultsTranslate(MainTranslate):
|
|||||||
"unit_M": self._dict["unit_mass"],
|
"unit_M": self._dict["unit_mass"],
|
||||||
"unit_thickness": self._dict["unit_thickness"],
|
"unit_thickness": self._dict["unit_thickness"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CompareResultsTranslate(ResultsTranslate):
|
||||||
|
def __init__(self):
|
||||||
|
super(CompareResultsTranslate, self).__init__()
|
||||||
|
|
||||||
|
self._dict['label_water'] = u"Δ "+_translate(
|
||||||
|
"Results", "Water elevation"
|
||||||
|
)
|
||||||
|
self._dict['unit_elevation'] = u"Δ "+self._dict["unit_elevation"]
|
||||||
|
|
||||||
|
self._sub_dict["table_headers_raw_data"] = {
|
||||||
|
"name": _translate("Results", "Profile"),
|
||||||
|
"water_elevation": u"Δ "+self._dict["unit_water_elevation"],
|
||||||
|
"discharge": u"Δ "+self._dict["unit_discharge"],
|
||||||
|
"velocity": u"Δ "+self._dict["unit_velocity"],
|
||||||
|
"width": u"Δ "+self._dict["unit_width"],
|
||||||
|
"depth": u"Δ "+self._dict["unit_depth"],
|
||||||
|
"mean_depth": u"Δ "+self._dict["unit_mean_depth"],
|
||||||
|
"wet_area": u"Δ "+self._dict["unit_wet_area"],
|
||||||
|
"wet_perimeter": u"Δ "+self._dict["unit_wet_perimeter"],
|
||||||
|
"hydraulic_radius": u"Δ "+self._dict["unit_hydraulic_radius"],
|
||||||
|
"froude": u"Δ "+self._dict["unit_froude"],
|
||||||
|
}
|
||||||
|
|
||||||
|
self._sub_dict["values_y"] = {
|
||||||
|
"bed_elevation": u"Δ "+self._dict["unit_bed_elevation"],
|
||||||
|
"water_elevation": u"Δ "+self._dict["unit_water_elevation"],
|
||||||
|
"discharge": u"Δ "+self._dict["unit_discharge"],
|
||||||
|
"velocity": u"Δ "+self._dict["unit_velocity"],
|
||||||
|
"depth": u"Δ "+self._dict["unit_depth"],
|
||||||
|
"mean_depth": u"Δ "+self._dict["unit_mean_depth"],
|
||||||
|
"froude": u"Δ "+self._dict["unit_froude"],
|
||||||
|
"wet_area": u"Δ "+self._dict["unit_wet_area"],
|
||||||
|
}
|
||||||
Loaded 100 of 126 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user