mirror of
https://gitlab.com/pamhyr/pamhyr2.git
synced 2026-10-29 19:10:42 +01:00
Compare commits
198
Commits
No files matched your search
+195
-77
@@ -1,5 +1,5 @@
|
||||
# .gitlab-ci.yml -- Pamhyr gitlab-ci
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -20,6 +20,8 @@ stages:
|
||||
- test
|
||||
- build
|
||||
- package
|
||||
- hash
|
||||
- antivirus
|
||||
- release
|
||||
|
||||
#############
|
||||
@@ -27,9 +29,9 @@ stages:
|
||||
#############
|
||||
|
||||
variables:
|
||||
MAGE_VERSION: "v8.3.3"
|
||||
MAGE_8_VERSION: "v8.3.5"
|
||||
|
||||
dl-mage-doc:
|
||||
dl-mage8-doc:
|
||||
stage: downloads
|
||||
tags:
|
||||
- linux
|
||||
@@ -38,46 +40,48 @@ dl-mage-doc:
|
||||
script:
|
||||
- mkdir -p doc
|
||||
- cd doc
|
||||
- curl -L -o mage8.pdf https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/$MAGE_VERSION/downloads/documents/Mage-8_Documentation.pdf
|
||||
- curl -L -o mage8.pdf https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/$MAGE_8_VERSION/downloads/documents/Mage-8_Documentation.pdf
|
||||
artifacts:
|
||||
paths:
|
||||
- doc/mage8.pdf
|
||||
|
||||
dl-mage-linux:
|
||||
dl-mage8-linux:
|
||||
stage: downloads
|
||||
tags:
|
||||
- linux
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||
script:
|
||||
- curl -L -o mage.tgz https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/$MAGE_VERSION/downloads/packages/mage_linux.tgz
|
||||
- mkdir -p mage-linux
|
||||
- cd mage-linux
|
||||
- tar xvf ../mage.tgz
|
||||
- curl -L -o mage8.tgz https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/$MAGE_8_VERSION/downloads/packages/mage_linux.tgz
|
||||
- mkdir -p mage8-linux
|
||||
- cd mage8-linux
|
||||
- tar xvf ../mage8.tgz
|
||||
artifacts:
|
||||
paths:
|
||||
- mage-linux/mage
|
||||
- mage-linux/mage_extraire
|
||||
- mage-linux/mailleurTT
|
||||
- mage-linux/libbief.so
|
||||
- mage8-linux/mage
|
||||
- mage8-linux/mage_as7
|
||||
- mage8-linux/mage_extraire
|
||||
- mage8-linux/mailleurTT
|
||||
- mage8-linux/libbief.so
|
||||
|
||||
dl-mage-windows:
|
||||
dl-mage8-windows:
|
||||
stage: downloads
|
||||
tags:
|
||||
- linux
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||
script:
|
||||
- curl -L -o mage.tgz https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/$MAGE_VERSION/downloads/packages/mage_windows.tgz
|
||||
- mkdir -p mage-windows
|
||||
- cd mage-windows
|
||||
- tar xvf ../mage.tgz
|
||||
- curl -L -o mage8.tgz https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/$MAGE_8_VERSION/downloads/packages/mage_windows.tgz
|
||||
- mkdir -p mage8-windows
|
||||
- cd mage8-windows
|
||||
- tar xvf ../mage8.tgz
|
||||
artifacts:
|
||||
paths:
|
||||
- mage-windows/mage.exe
|
||||
- mage-windows/mage_extraire.exe
|
||||
- mage-windows/mailleurTT.exe
|
||||
- mage-windows/libbief.dll
|
||||
- mage8-windows/mage.exe
|
||||
- mage8-windows/mage_as7.exe
|
||||
- mage8-windows/mage_extraire.exe
|
||||
- mage8-windows/mailleurTT.exe
|
||||
- mage8-windows/libbief.dll
|
||||
|
||||
#############
|
||||
# CONFIGURE #
|
||||
@@ -148,23 +152,22 @@ test-pep8:
|
||||
# BUILD #
|
||||
#########
|
||||
|
||||
build-users-doc:
|
||||
stage: build
|
||||
tags:
|
||||
- linux
|
||||
needs:
|
||||
- job: set-version
|
||||
artifacts: true
|
||||
script:
|
||||
- cd ./doc/users/
|
||||
- ./build.sh
|
||||
artifacts:
|
||||
paths:
|
||||
- doc/users/documentation.pdf
|
||||
- doc/users/documentation.html
|
||||
- doc/users/images/
|
||||
allow_failure: true
|
||||
|
||||
# build-users-doc:
|
||||
# stage: build
|
||||
# tags:
|
||||
# - linux
|
||||
# needs:
|
||||
# - job: set-version
|
||||
# artifacts: true
|
||||
# script:
|
||||
# - cd ./doc/users/
|
||||
# - ./build.sh
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - doc/users/documentation.pdf
|
||||
# - doc/users/documentation.html
|
||||
# - doc/users/images/
|
||||
# allow_failure: true
|
||||
|
||||
build-td:
|
||||
stage: build
|
||||
@@ -221,9 +224,9 @@ build-linux:
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||
needs:
|
||||
- job: dl-mage-linux
|
||||
- job: dl-mage8-linux
|
||||
artifacts: true
|
||||
- job: dl-mage-doc
|
||||
- job: dl-mage8-doc
|
||||
artifacts: true
|
||||
- job: set-version
|
||||
artifacts: true
|
||||
@@ -231,8 +234,8 @@ build-linux:
|
||||
artifacts: true
|
||||
- job: build-developers-doc
|
||||
artifacts: true
|
||||
- job: build-users-doc
|
||||
artifacts: true
|
||||
# - job: build-users-doc
|
||||
# artifacts: true
|
||||
- job: build-td
|
||||
artifacts: true
|
||||
script:
|
||||
@@ -248,28 +251,27 @@ build-linux:
|
||||
- pyinstaller -y --paths linux-venv/lib/python3.8/site-packages ../src/pamhyr.py
|
||||
# Create directory
|
||||
- mkdir -p pamhyr
|
||||
- mkdir -p pamhyr/pamhyr
|
||||
- mkdir -p pamhyr/pamhyr/_internal
|
||||
- mkdir -p pamhyr/_internal
|
||||
# Copy Pamhyr info
|
||||
- cp -v ../VERSION pamhyr/pamhyr/_internal/
|
||||
- cp -v ../AUTHORS pamhyr/pamhyr/_internal/
|
||||
- cp -v ../LICENSE pamhyr/pamhyr/_internal/
|
||||
- cp -v ../src/motd.txt pamhyr/pamhyr/_internal/
|
||||
- cp -v ../VERSION pamhyr/_internal/
|
||||
- cp -v ../AUTHORS pamhyr/_internal/
|
||||
- cp -v ../LICENSE pamhyr/_internal/
|
||||
- cp -v ../src/motd.txt pamhyr/_internal/
|
||||
# Copy mage
|
||||
- mkdir -p pamhyr/mage
|
||||
- cp -v ../mage-linux/* pamhyr/mage/
|
||||
- mkdir -p pamhyr/mage8
|
||||
- cp -v ../mage8-linux/* pamhyr/mage8/
|
||||
# Copy Pamhyr
|
||||
- cp -r dist/pamhyr pamhyr/
|
||||
- cp -r dist/pamhyr/* pamhyr/
|
||||
# Copy Pamhyr resources
|
||||
- mkdir -p pamhyr/pamhyr/_internal/View
|
||||
- mkdir -p pamhyr/pamhyr/_internal/View/ui
|
||||
- mkdir -p pamhyr/pamhyr/_internal/View/ui/Widgets
|
||||
- cp -r ../src/View/ui/*.ui pamhyr/pamhyr/_internal/View/ui/
|
||||
- cp -r ../src/View/ui/ressources/ pamhyr/pamhyr/_internal/View/ui
|
||||
- cp -r ../src/View/ui/Widgets/*.ui pamhyr/pamhyr/_internal/View/ui/Widgets
|
||||
- mkdir -p pamhyr/_internal/View
|
||||
- mkdir -p pamhyr/_internal/View/ui
|
||||
- mkdir -p pamhyr/_internal/View/ui/Widgets
|
||||
- cp -r ../src/View/ui/*.ui pamhyr/_internal/View/ui/
|
||||
- cp -r ../src/View/ui/ressources/ pamhyr/_internal/View/ui
|
||||
- cp -r ../src/View/ui/Widgets/*.ui pamhyr/_internal/View/ui/Widgets
|
||||
# Copy lang
|
||||
- mkdir -p pamhyr/pamhyr/_internal/lang
|
||||
- cp -r ../src/lang/*.qm pamhyr/pamhyr/_internal/lang
|
||||
- mkdir -p pamhyr/_internal/lang
|
||||
- cp -r ../src/lang/*.qm pamhyr/_internal/lang
|
||||
# Copy tests cases
|
||||
- mkdir -p pamhyr/tests_cases/
|
||||
- mkdir -p pamhyr/tests_cases/Saar
|
||||
@@ -297,10 +299,6 @@ build-linux:
|
||||
# Copy TP charriage
|
||||
- mkdir -p pamhyr/doc/TP_charriage/
|
||||
- cp ../doc/users/TP_charriage/* pamhyr/doc/TP_charriage
|
||||
# Create running script
|
||||
- echo "#!/bin/sh" > pamhyr/Pamhyr2
|
||||
- echo "./pamhyr/pamhyr $@" >> pamhyr/Pamhyr2
|
||||
- chmod u+x pamhyr/Pamhyr2
|
||||
artifacts:
|
||||
paths:
|
||||
- linux/pamhyr
|
||||
@@ -312,9 +310,9 @@ build-windows:
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||
needs:
|
||||
- job: dl-mage-windows
|
||||
- job: dl-mage8-windows
|
||||
artifacts: true
|
||||
- job: dl-mage-doc
|
||||
- job: dl-mage8-doc
|
||||
artifacts: true
|
||||
- job: set-version
|
||||
artifacts: true
|
||||
@@ -322,18 +320,20 @@ build-windows:
|
||||
artifacts: true
|
||||
- job: build-developers-doc
|
||||
artifacts: true
|
||||
- job: build-users-doc
|
||||
artifacts: true
|
||||
# - job: build-users-doc
|
||||
# artifacts: true
|
||||
- job: build-td
|
||||
artifacts: true
|
||||
script:
|
||||
- mkdir windows
|
||||
- cd windows
|
||||
# Setup env
|
||||
- python -m pip install -U pip
|
||||
- python -m pip install -r ..\requirements.txt
|
||||
- python -m pip install -U -r ..\requirements.txt
|
||||
# Run Pyinstaller
|
||||
- pyinstaller -y ..\src\pamhyr.py
|
||||
# - pyinstaller --noconsole -y ..\src\pamhyr.py
|
||||
- pyinstaller --hide-console hide-early -y ..\src\pamhyr.py
|
||||
# Create directory
|
||||
- mkdir pamhyr
|
||||
- dir
|
||||
@@ -403,6 +403,111 @@ windows-package-exe:
|
||||
- copy ..\packages\pamhyr.nsi pamhyr.nsi
|
||||
- .\make-windows-exe.bat
|
||||
|
||||
########
|
||||
# HASH #
|
||||
########
|
||||
|
||||
linux-build-hash:
|
||||
stage: hash
|
||||
tags:
|
||||
- release
|
||||
- linux
|
||||
needs:
|
||||
- job: build-linux
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||
script:
|
||||
- cd linux
|
||||
- sha256sum -b pamhyr/pamhyr > pamhyr/pamhyr.sha256
|
||||
artifacts:
|
||||
paths:
|
||||
- linux/pamhyr/pamhyr.sha256
|
||||
|
||||
windows-build-hash:
|
||||
stage: hash
|
||||
tags:
|
||||
- release
|
||||
- linux
|
||||
needs:
|
||||
- job: build-windows
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||
script:
|
||||
- cd windows
|
||||
- sha256sum -b pamhyr/pamhyr.exe > pamhyr/pamhyr.exe.sha256
|
||||
artifacts:
|
||||
paths:
|
||||
- windows/pamhyr/pamhyr.exe.sha256
|
||||
|
||||
pkg-hash:
|
||||
stage: hash
|
||||
tags:
|
||||
- release
|
||||
- linux
|
||||
needs:
|
||||
- job: linux-package-tar
|
||||
artifacts: true
|
||||
- job: windows-package-zip
|
||||
artifacts: true
|
||||
- job: windows-package-exe
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_TAG
|
||||
script:
|
||||
- cd windows
|
||||
- sha256sum -b pamhyr-windows.exe > pamhyr-windows.exe.sha256
|
||||
- sha256sum -b pamhyr-windows.zip > pamhyr-windows.zip.sha256
|
||||
- cd ..
|
||||
- cd linux
|
||||
- sha256sum -b pamhyr-gnulinux.tar.xz > pamhyr-gnulinux.tar.xz.sha256
|
||||
artifacts:
|
||||
paths:
|
||||
- windows/pamhyr-windows.exe.sha256
|
||||
- windows/pamhyr-windows.zip.sha256
|
||||
- linux/pamhyr-gnulinux.tar.xz.sha256
|
||||
|
||||
#############
|
||||
# ANTIVIRUS #
|
||||
#############
|
||||
|
||||
build-check-clamav:
|
||||
stage: antivirus
|
||||
tags:
|
||||
- release
|
||||
- linux
|
||||
needs:
|
||||
- job: build-linux
|
||||
artifacts: true
|
||||
- job: build-windows
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG
|
||||
script:
|
||||
- cd packages
|
||||
- ./clamav-scan.sh builds
|
||||
allow_failure: true
|
||||
|
||||
pkg-check-clamav:
|
||||
stage: antivirus
|
||||
tags:
|
||||
- release
|
||||
- linux
|
||||
needs:
|
||||
- job: linux-package-tar
|
||||
artifacts: true
|
||||
- job: windows-package-zip
|
||||
artifacts: true
|
||||
- job: windows-package-exe
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_TAG
|
||||
script:
|
||||
- cd packages
|
||||
- ./clamav-scan.sh packages
|
||||
allow_failure: true
|
||||
|
||||
###########
|
||||
# RELEASE #
|
||||
###########
|
||||
@@ -419,10 +524,12 @@ tag-release:
|
||||
artifacts: true
|
||||
- job: windows-package-exe
|
||||
artifacts: true
|
||||
- job: build-users-doc
|
||||
artifacts: true
|
||||
# - job: build-users-doc
|
||||
# artifacts: true
|
||||
- job: build-developers-doc
|
||||
artifacts: true
|
||||
- job: pkg-hash
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG
|
||||
artifacts:
|
||||
@@ -430,33 +537,44 @@ tag-release:
|
||||
- linux/pamhyr-gnulinux.tar.xz
|
||||
- windows/pamhyr-windows.zip
|
||||
- windows/pamhyr-windows.exe
|
||||
- linux/pamhyr-gnulinux.tar.xz.sha256
|
||||
- windows/pamhyr-windows.zip.sha256
|
||||
- windows/pamhyr-windows.exe.sha256
|
||||
- doc/dev/documentation.pdf
|
||||
- doc/users/documentation.pdf
|
||||
# - doc/users/documentation.pdf
|
||||
script:
|
||||
- cd packages
|
||||
release:
|
||||
name: '$CI_COMMIT_TAG'
|
||||
description: 'Automatic release from tag $CI_COMMIT_TAG'
|
||||
description: '$CI_COMMIT_TAG_MESSAGE'
|
||||
tag_name: '$CI_COMMIT_TAG'
|
||||
ref: '$CI_COMMIT_SHA'
|
||||
assets:
|
||||
links:
|
||||
- name: 'GNU/Linux CHECKSUM SHA256 (tar.xz)'
|
||||
url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/linux/pamhyr-gnulinux.tar.xz.sha256'
|
||||
filepath: '/linux/pamhyr-gnulinux.tar.xz.sha256'
|
||||
link_type: 'package'
|
||||
- name: 'GNU/Linux (tar.xz)'
|
||||
url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/linux/pamhyr-gnulinux.tar.xz'
|
||||
filepath: '/linux/pamhyr-gnulinux.tar.xz'
|
||||
link_type: 'package'
|
||||
- name: 'Windows CHECKSUM SHA256 (exe)'
|
||||
url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/windows/pamhyr-windows.exe.sha256'
|
||||
filepath: '/windows/pamhyr-windows.exe.sha256'
|
||||
link_type: 'package'
|
||||
- name: 'Windows (exe)'
|
||||
url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/windows/pamhyr-windows.exe'
|
||||
filepath: '/windows/pamhyr-windows.exe'
|
||||
link_type: 'package'
|
||||
- name: 'Windows CHECKSUM SHA256 (zip)'
|
||||
url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/windows/pamhyr-windows.zip.sha256'
|
||||
filepath: '/windows/pamhyr-windows.zip.sha256'
|
||||
link_type: 'package'
|
||||
- name: 'Windows (zip)'
|
||||
url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/windows/pamhyr-windows.zip'
|
||||
filepath: '/windows/pamhyr-windows.zip'
|
||||
link_type: 'package'
|
||||
- name: 'User documentations (pdf)'
|
||||
url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/doc/users/documentation.pdf'
|
||||
filepath: '/doc/users/documentation.pdf'
|
||||
link_type: 'other'
|
||||
- name: 'Dev documentations (pdf)'
|
||||
url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/doc/dev/documentation.pdf'
|
||||
filepath: '/doc/dev/documentation.pdf'
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Sylvain COULIBALY, INRAE, 2020 - 2022
|
||||
Théophile TERRAZ, INRAE, 2022 - 2023
|
||||
Pierre-Antoine ROUBY, INRAE, 2023
|
||||
Théophile TERRAZ, INRAE, 2022 - 2024
|
||||
Pierre-Antoine ROUBY, INRAE, 2023 - 2024
|
||||
@@ -25,21 +25,11 @@ for more details.
|
||||
|
||||
### GNU/Linux
|
||||
|
||||
Downloads the [last
|
||||
realease](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/releases/permalink/latest)
|
||||
GNU/Linux binary archive.
|
||||
|
||||
```shell
|
||||
tar xf pamhyr-gnulinux.tar.xz
|
||||
cd pamhyr
|
||||
./Pamhyr2
|
||||
```
|
||||
[See documentation](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/en/Install%20on%20GNULinux)
|
||||
|
||||
### Windows
|
||||
|
||||
Downloads the [last
|
||||
realease](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/releases/permalink/latest)
|
||||
Windows installer or ZIP archive.
|
||||
[See documentation](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/en/Install%20on%20Windows)
|
||||
|
||||
### From source code
|
||||
|
||||
|
||||
+82
-45
@@ -1,5 +1,5 @@
|
||||
# documentation.org -- Pamhyr developers documentation
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -369,6 +369,7 @@ of Bar (Listing [[sql-bar]] and [[sql-foo]]).
|
||||
CREATE TABLE bar (
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
x INTEGER NOT NULL,
|
||||
y INTEGER NOT NULL,
|
||||
foo_id INTEGER NOT NULL,
|
||||
FOREIGN KEY(foo_id) REFERENCES foo(id),
|
||||
)""")
|
||||
@@ -455,6 +456,15 @@ of Bar (Listing [[sql-bar]] and [[sql-foo]]).
|
||||
bar._sql_save(execute, data=data)
|
||||
#+end_src
|
||||
|
||||
Let see the results database scheme for Pamhyr2 at version v0.0.7 in
|
||||
Figure [[sql_schema]].
|
||||
|
||||
#+NAME: sql_schema
|
||||
#+ATTR_LATEX: :width 16cm
|
||||
#+CAPTION: SQLite database scheme at Pamhyr2 version v0.0.7 (generate with [[https://gitlab.com/Screwtapello/sqlite-schema-diagram]])
|
||||
[[./images/schema_v0.0.7.png]]
|
||||
|
||||
|
||||
[fn:sqlite] The SQLite web site: https://www.sqlite.org/index.html
|
||||
(last access 2023-09-20)
|
||||
|
||||
@@ -538,44 +548,44 @@ generic value from optional parameters, for examples:
|
||||
#+NAME: window
|
||||
#+CAPTION: Example of Pamhyr2 window
|
||||
#+begin_src python :python python3 :results output :noweb yes
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
from View.My.Translate import MyTranslate
|
||||
from View.My.Table import MyTableModel
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
from View.My.Translate import MyTranslate
|
||||
from View.My.Table import MyTableModel
|
||||
|
||||
class MyWindow(PamhyrWindow):
|
||||
_pamhyr_ui = "MyUI"
|
||||
_pamhyr_name = "My window"
|
||||
class MyWindow(PamhyrWindow):
|
||||
_pamhyr_ui = "MyUI"
|
||||
_pamhyr_name = "My window"
|
||||
|
||||
def __init__(self, my_data=None,
|
||||
study=None, config=None,
|
||||
parent=None):
|
||||
self._my_data = my_data
|
||||
def __init__(self, study=None, config=None,
|
||||
my_data=None,
|
||||
parent=None):
|
||||
self._my_data = my_data
|
||||
|
||||
super(MyWindow, self).__init__(
|
||||
# Window title
|
||||
title = self._pamhyr_name + " - " + study.name,
|
||||
# Window standard data
|
||||
study = study, config = config,
|
||||
trad = MyTranslate(),
|
||||
parent = parent,
|
||||
# Activate undo/redo and copy/paste shortcut
|
||||
options = ["undo", "copy"]
|
||||
)
|
||||
super(MyWindow, self).__init__(
|
||||
# Window title
|
||||
title = self._pamhyr_name + " - " + study.name,
|
||||
# Window standard data
|
||||
study = study, config = config,
|
||||
trad = MyTranslate(),
|
||||
parent = parent,
|
||||
# Activate undo/redo and copy/paste shortcut
|
||||
options = ["undo", "copy"]
|
||||
)
|
||||
|
||||
# Add custom data to hash window computation
|
||||
self._hash_data.append(self._my_data)
|
||||
# Add custom data to hash window computation
|
||||
self._hash_data.append(self._my_data)
|
||||
|
||||
# Setup custom window components
|
||||
self.setup_table()
|
||||
self.setup_connections()
|
||||
# Setup custom window components
|
||||
self.setup_table()
|
||||
self.setup_connections()
|
||||
|
||||
def setup_table(self):
|
||||
# Init table(s)...
|
||||
def setup_table(self):
|
||||
# Init table(s)...
|
||||
|
||||
def setup_connections(self):
|
||||
# Init action connection(s)...
|
||||
def setup_connections(self):
|
||||
# Init action connection(s)...
|
||||
|
||||
# ...
|
||||
# ...
|
||||
#+end_src
|
||||
|
||||
Typically we called method =setup_*=, the method to initialize some
|
||||
@@ -661,11 +671,13 @@ creation, this stack is accessible at =self._undo_stack=.
|
||||
|
||||
*** Plot
|
||||
|
||||
To define a new plot you can create a class who inherit to APlot. The
|
||||
creator need threee argument:
|
||||
To define a new plot you can create a class who inherit to
|
||||
PamhyrPlot. The creator need at leaste five argument:
|
||||
- A =canvas= of type =MplCanvas=
|
||||
- A (optional) =trad= of type =PamhyrTranslate=
|
||||
- A =data= used in =draw= and =update= to create and update the plot
|
||||
- A optional =toolbar= of type =PamhyrToolbar=
|
||||
- A =parent= window
|
||||
This class must implement two method =draw= and =update=, the first
|
||||
method to draw the plot from scratch, the second to update the plot if
|
||||
data has changed.
|
||||
@@ -673,19 +685,36 @@ data has changed.
|
||||
#+begin_src python :python python3 :results output :noweb yes
|
||||
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||
|
||||
class MyPlot(APlot):
|
||||
def __init__(self, canvas=None, data=None, toolbar=None):
|
||||
class MyPlot(PamhyrPlot):
|
||||
def __init__(self, canvas=None, trad=None, toolbar=None
|
||||
data=None, parent=None):
|
||||
super(MyPlot, self).__init__(
|
||||
canvas=canvas,
|
||||
trad=trad,
|
||||
data=data,
|
||||
toolbar=toolbar
|
||||
toolbar=toolbar,
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self.label_x = self._trad["x"]
|
||||
self.label_y = self._trad["y"]
|
||||
|
||||
# Optional configuration
|
||||
self._isometric_axis = False
|
||||
|
||||
self._auto_relim_update = True
|
||||
self._autoscale_update = True
|
||||
|
||||
def draw(self):
|
||||
# Draw function code...
|
||||
|
||||
def update(self, ind = None):
|
||||
def update(self):
|
||||
# Update function code...
|
||||
|
||||
def clear(self):
|
||||
# Clear plot values...
|
||||
|
||||
# ...
|
||||
#+end_src
|
||||
|
||||
** Solver
|
||||
@@ -745,7 +774,7 @@ execute a code on distant computer, for example, over ssh.
|
||||
style=dashed;
|
||||
subgraph cluster021 {
|
||||
label="Solver Classes";
|
||||
classSolverM7[label="Mage7", fillcolor=6];
|
||||
//classSolverM7[label="Mage7", fillcolor=6];
|
||||
classSolverM8[label="Mage8", fillcolor=6];
|
||||
classSolverR[label="RubarBE", fillcolor=6];
|
||||
}
|
||||
@@ -828,7 +857,7 @@ solver and get results:
|
||||
- (2.1) The solver read the input file(s)
|
||||
- (2.2) The solver compute results and write it to solver output
|
||||
file(s)
|
||||
- (3) Pamhyr2 create a Reuslts
|
||||
- (3) Pamhyr2 create a =Results= object
|
||||
- (3.1) The Pamhyr2 solver class read solver output file(s) and
|
||||
complete Results with readed data
|
||||
|
||||
@@ -958,8 +987,16 @@ different methods:
|
||||
|
||||
** Unit tests
|
||||
|
||||
The unit tests is actually not implemented in Pamhyr2, it is a *work
|
||||
in progress*.
|
||||
A very small part of Pamhyr2 has unit test. This part is limited to the Model.
|
||||
|
||||
#+begin_src shell
|
||||
python3 -m venv test
|
||||
. test test/bin/activate
|
||||
pip3 install -U -r ./full-requirements.txt
|
||||
|
||||
cd src/
|
||||
python3 -Walways -m unittest discovert -v -t .
|
||||
#+end_src
|
||||
|
||||
** The debug mode
|
||||
|
||||
@@ -970,14 +1007,14 @@ line:
|
||||
./Pamhyr2 debug
|
||||
#+end_src
|
||||
|
||||
This mode add some log and add two action in main window menu:
|
||||
"About/Debug" open a window with Python Repl in current Python
|
||||
environement, and "About/Debug SQLite" who open the application
|
||||
This mode add some log and add two action in main window menu: "About
|
||||
> Debug" open a window with Python Repl in current Python
|
||||
environement, and "About > Debug SQLite" who open the application
|
||||
SQLiteBrowser (if installed) on current Study to explore the study
|
||||
data base file.
|
||||
|
||||
#+NAME: debug-repl
|
||||
#+ATTR_LATEX: :width 12cm
|
||||
#+ATTR_LATEX: :width 14cm
|
||||
#+CAPTION: Pamhyr2 debug Python REPL
|
||||
[[./images/python-debug-repl.png]]
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 51 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 224 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -4,9 +4,10 @@ PyQt5-sip==12.12.2
|
||||
PyQtWebEngine==5.15.6
|
||||
QScintilla>=2.14.1
|
||||
pyqtgraph>=0.12.1
|
||||
matplotlib>=3.4.1
|
||||
matplotlib>=3.7.1
|
||||
numpy>=1.24.2
|
||||
colorama>=0.4.3
|
||||
pyinstaller>=5.11.0
|
||||
shapely>=2.0.1
|
||||
lxml>=4.9.3
|
||||
platformdirs>=4.2.0
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#! /bin/bash
|
||||
set +x
|
||||
|
||||
OPTS="-r -a -i"
|
||||
|
||||
if [ "$1" == "builds" ]; then
|
||||
FILES="../windows/ ../linux/"
|
||||
else
|
||||
FILES="../windows/pamhyr-windows.exe ../windows/pamhyr-windows.zip ../linux/pamhyr-gnulinux.tar.xz"
|
||||
fi
|
||||
|
||||
clamscan $OPTS $FILES | tee clamav.log
|
||||
|
||||
RES=$(cat clamav.log | grep "Infected files: 0")
|
||||
if [ -z "$RES" ]; then
|
||||
echo "Infected files"
|
||||
exit -1
|
||||
else
|
||||
echo "OK"
|
||||
exit 0
|
||||
fi
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
|
||||
start cmd /c pamhyr.exe debug
|
||||
@@ -0,0 +1,3 @@
|
||||
#! /bin/sh
|
||||
|
||||
./pamhyr debug
|
||||
@@ -16,34 +16,35 @@ rem along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
@ECHO ON
|
||||
|
||||
mkdir pamhyr\pamhyr\_internal
|
||||
xcopy /s /e /y dist\pamhyr pamhyr\pamhyr
|
||||
mkdir pamhyr\_internal
|
||||
xcopy /s /e /y dist\pamhyr pamhyr
|
||||
|
||||
rem Copy data
|
||||
mkdir pamhyr\pamhyr\_internal\lang
|
||||
mkdir pamhyr\pamhyr\_internal\View\ui\ressources
|
||||
mkdir pamhyr\pamhyr\_internal\View\ui\Widgets
|
||||
mkdir pamhyr\_internal\lang
|
||||
mkdir pamhyr\_internal\View\ui\ressources
|
||||
mkdir pamhyr\_internal\View\ui\Widgets
|
||||
|
||||
rem UI
|
||||
copy /y ..\src\View\ui\ressources\ pamhyr\pamhyr\_internal\View\ui\ressources
|
||||
copy /y ..\src\View\ui\Widgets\*.ui pamhyr\pamhyr\_internal\View\ui\Widgets
|
||||
copy /y ..\src\View\ui\*.ui pamhyr\pamhyr\_internal\View\ui\
|
||||
copy /y ..\src\View\ui\ressources\ pamhyr\_internal\View\ui\ressources
|
||||
copy /y ..\src\View\ui\Widgets\*.ui pamhyr\_internal\View\ui\Widgets
|
||||
copy /y ..\src\View\ui\*.ui pamhyr\_internal\View\ui\
|
||||
|
||||
rem Lang
|
||||
copy /y ..\src\lang\*.qm pamhyr\pamhyr\_internal\lang\
|
||||
copy /y ..\src\lang\*.qm pamhyr\_internal\lang\
|
||||
|
||||
rem Information
|
||||
copy /y ..\VERSION pamhyr\pamhyr\_internal
|
||||
copy /y ..\AUTHORS pamhyr\pamhyr\_internal
|
||||
copy /y ..\LICENSE pamhyr\pamhyr\_internal
|
||||
copy /y ..\src\motd.txt pamhyr\pamhyr\_internal
|
||||
copy /y ..\VERSION pamhyr\_internal
|
||||
copy /y ..\AUTHORS pamhyr\_internal
|
||||
copy /y ..\LICENSE pamhyr\_internal
|
||||
copy /y ..\src\motd.txt pamhyr\_internal
|
||||
|
||||
rem MAGE
|
||||
mkdir pamhyr\mage
|
||||
copy /y ..\mage-windows\mage.exe pamhyr\mage\
|
||||
copy /y ..\mage-windows\mage_extraire.exe pamhyr\mage\
|
||||
copy /y ..\mage-windows\mailleurTT.exe pamhyr\mage\
|
||||
copy /y ..\mage-windows\libbief.dll pamhyr\mage\
|
||||
mkdir pamhyr\mage8
|
||||
copy /y ..\mage8-windows\mage.exe pamhyr\mage8\
|
||||
copy /y ..\mage8-windows\mage_as7.exe pamhyr\mage8\
|
||||
copy /y ..\mage8-windows\mage_extraire.exe pamhyr\mage8\
|
||||
copy /y ..\mage8-windows\mailleurTT.exe pamhyr\mage8\
|
||||
copy /y ..\mage8-windows\libbief.dll pamhyr\mage8\
|
||||
|
||||
rem Copy tests_cases
|
||||
mkdir pamhyr\tests_cases
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@
|
||||
|
||||
Name "Pamhyr2"
|
||||
OutFile "pamhyr-windows.exe"
|
||||
LicenseData "pamhyr\pamhyr\_internal\LICENSE"
|
||||
LicenseData "pamhyr\_internal\LICENSE"
|
||||
LicenseText "I Agree"
|
||||
|
||||
RequestExecutionLevel admin
|
||||
@@ -41,12 +41,12 @@ SectionEnd
|
||||
Section "Start Menu Shortcuts"
|
||||
CreateDirectory "$SMPROGRAMS\Pamhyr2"
|
||||
CreateShortcut "$SMPROGRAMS\Pamhyr2\Uninstall.lnk" "$INSTDIR\uninstall.exe"
|
||||
CreateShortcut "$SMPROGRAMS\Pamhyr2\Pamhyr2.lnk" "$INSTDIR\pamhyr\pamhyr.exe"
|
||||
CreateShortcut "$SMPROGRAMS\Pamhyr2\Pamhyr2.lnk" "$INSTDIR\pamhyr.exe"
|
||||
SectionEnd
|
||||
|
||||
Section "Desktop Shortcuts"
|
||||
SetShellVarContext all
|
||||
CreateShortcut "$desktop\Pamhyr2.lnk" "$instdir\pamhyr\pamhyr.exe"
|
||||
CreateShortcut "$desktop\Pamhyr2.lnk" "$instdir\pamhyr.exe"
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
|
||||
+2
-1
@@ -4,9 +4,10 @@ PyQt5-sip==12.12.2
|
||||
#PyQtWebEngine==5.15.6
|
||||
QScintilla>=2.14.1
|
||||
pyqtgraph>=0.12.1
|
||||
matplotlib>=3.4.1
|
||||
matplotlib>=3.7.1
|
||||
numpy>=1.24.2
|
||||
colorama>=0.4.3
|
||||
pyinstaller>=5.11.0
|
||||
shapely>=2.0.1
|
||||
lxml>=4.9.3
|
||||
platformdirs>=4.2.0
|
||||
+32
-2
@@ -1,5 +1,5 @@
|
||||
# Checker.py -- Pamhyr abstract checker class
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -16,23 +16,53 @@
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from Modules import Modules
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class STATUS(Enum):
|
||||
UNKNOWN = -1
|
||||
OK = 0
|
||||
WARNING = 1
|
||||
ERROR = 2
|
||||
UNKNOWN = 999
|
||||
|
||||
def __eq__(self, y):
|
||||
return self.value == y.value
|
||||
|
||||
def __gt__(self, y):
|
||||
return self.value > y.value
|
||||
|
||||
def __or__(self, y):
|
||||
v = [self, y]
|
||||
r = self.OK
|
||||
|
||||
if self.UNKNOWN in v:
|
||||
r = self.UNKNOWN
|
||||
if self.ERROR in v:
|
||||
r = self.ERROR
|
||||
if self.WARNING in v:
|
||||
r = self.WARNING
|
||||
|
||||
logger.debug(f"CHECKER: STATUS: {self} | {y} = {r}")
|
||||
return r
|
||||
|
||||
|
||||
class AbstractModelChecker(object):
|
||||
def __init__(self):
|
||||
self._name = ""
|
||||
self._description = ""
|
||||
self._solver = "study"
|
||||
self._modules = Modules.NONE
|
||||
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self._status = STATUS.UNKNOWN
|
||||
self._summary = "Unknown"
|
||||
|
||||
|
||||
+10
-3
@@ -1,5 +1,5 @@
|
||||
# Mage.py -- Pamhyr MAGE checkers
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -23,6 +23,8 @@ from tools import flatten, timer
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
|
||||
from Modules import Modules
|
||||
|
||||
from Checker.Checker import AbstractModelChecker, STATUS
|
||||
from Checker.Study import StudyGeometryChecker
|
||||
|
||||
@@ -30,7 +32,7 @@ _translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class MageNetworkGraphChecker(AbstractModelChecker):
|
||||
def __init__(self, connectivity=True):
|
||||
def __init__(self, connectivity=True, version="mage8"):
|
||||
super(MageNetworkGraphChecker, self).__init__()
|
||||
|
||||
self._mode_conn = connectivity
|
||||
@@ -44,6 +46,8 @@ class MageNetworkGraphChecker(AbstractModelChecker):
|
||||
"Checker", f"Mage network graph {mode} checker")
|
||||
self._description = _translate(
|
||||
"Checker", "Check if the network graph is valid")
|
||||
self._solver = version
|
||||
self._modules = Modules.NETWORK
|
||||
|
||||
@timer
|
||||
def _connectivity(self, summary, status, graph):
|
||||
@@ -199,7 +203,7 @@ class MageNetworkGraphChecker(AbstractModelChecker):
|
||||
|
||||
|
||||
class MageGeometryGuideLineChecker(StudyGeometryChecker):
|
||||
def __init__(self):
|
||||
def __init__(self, version="mage8"):
|
||||
super(MageGeometryGuideLineChecker, self).__init__()
|
||||
|
||||
self._name = _translate("Checker", "Mage geometry guide line checker")
|
||||
@@ -208,6 +212,9 @@ class MageGeometryGuideLineChecker(StudyGeometryChecker):
|
||||
"Check if exists geometry guide line is correctly defined \
|
||||
for each reaches of the study"
|
||||
)
|
||||
self._solver = version
|
||||
self._modules = Modules.GEOMETRY
|
||||
|
||||
self._reachs = []
|
||||
|
||||
def run(self, study):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Study.py -- Pamhyr study checkers
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -20,6 +20,7 @@ import time
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
|
||||
from Modules import Modules
|
||||
from Checker.Checker import AbstractModelChecker, STATUS
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
@@ -31,7 +32,9 @@ class StudyNetworkReachChecker(AbstractModelChecker):
|
||||
|
||||
self._name = _translate("Checker", "Study network reach checker")
|
||||
self._description = _translate(
|
||||
"Checker", "Check if exists at least one reach for study")
|
||||
"Checker", "Check if exists at least one reach for study"
|
||||
)
|
||||
self._modules = Modules.NETWORK
|
||||
|
||||
def run(self, study):
|
||||
if study is None:
|
||||
@@ -62,7 +65,10 @@ class StudyGeometryChecker(AbstractModelChecker):
|
||||
|
||||
self._name = _translate("Checker", "Study geometry checker")
|
||||
self._description = _translate(
|
||||
"Checker", "Check if exists geometry for each reach of study")
|
||||
"Checker", "Check if exists geometry for each reach of study"
|
||||
)
|
||||
self._modules = Modules.GEOMETRY
|
||||
|
||||
self._reachs = []
|
||||
|
||||
def run(self, study):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# AMeshingTool.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
+57
-12
@@ -1,5 +1,5 @@
|
||||
# Mage.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -30,7 +30,7 @@ from ctypes import (
|
||||
)
|
||||
from PyQt5.QtCore import QProcess
|
||||
|
||||
from tools import logger_color_red, logger_color_reset
|
||||
from tools import logger_color_red, logger_color_reset, logger_exception
|
||||
from Meshing.AMeshingTool import AMeshingTool
|
||||
|
||||
logger = logging.getLogger()
|
||||
@@ -65,6 +65,10 @@ class MeshingWithMage(AMeshingTool):
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _path(cls):
|
||||
return cls._exe_path()
|
||||
|
||||
def _init_c_init_bief_from_geo_file(self):
|
||||
self._c_init_bief_from_geo_file = getattr(
|
||||
self._bief_lib, 'c_init_bief_from_geo_file'
|
||||
@@ -274,15 +278,25 @@ class MeshingWithMageMailleurTT(AMeshingTool):
|
||||
return os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"..", "..", "..", "mage", f"mailleurTT{ext}"
|
||||
"..", "..", "mage8", f"mailleurTT{ext}"
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _path(cls):
|
||||
return cls._exe_path()
|
||||
|
||||
###########
|
||||
# Meshing #
|
||||
###########
|
||||
|
||||
def meshing(self, reach, step: float = 50):
|
||||
def meshing(self, reach,
|
||||
step: float = 50,
|
||||
limites=[-1, -1],
|
||||
directrices=['un', 'np'],
|
||||
lplan: bool = False,
|
||||
lm: int = 3,
|
||||
linear: bool = False):
|
||||
if reach is None or len(reach.profiles) == 0:
|
||||
return reach
|
||||
|
||||
@@ -291,22 +305,51 @@ class MeshingWithMageMailleurTT(AMeshingTool):
|
||||
st_file = self.export_reach_to_st(reach, tmp)
|
||||
m_file = st_file.rsplit(".ST", 1)[0] + ".M"
|
||||
|
||||
os.sync()
|
||||
|
||||
proc = QProcess()
|
||||
proc.setWorkingDirectory(tmp)
|
||||
|
||||
logger.debug(f"! mailleurTT {st_file} {m_file} {str(step)}")
|
||||
lplan = 1 if lplan else 0
|
||||
linear = 1 if linear else 0
|
||||
|
||||
logger.info(
|
||||
f"! {self._exe_path()} {st_file} {m_file} " +
|
||||
f"{str(step)} " +
|
||||
f"{limites[0]} {limites[1]} " +
|
||||
f"{directrices[0]} {directrices[1]} " +
|
||||
f"{lplan} {lm} {linear}"
|
||||
)
|
||||
proc.start(
|
||||
self._exe_path(), [st_file, m_file, str(step)]
|
||||
self._exe_path(),
|
||||
list(map(
|
||||
str,
|
||||
[
|
||||
st_file, m_file, step,
|
||||
limites[0], limites[1],
|
||||
directrices[0], directrices[1],
|
||||
lplan, lm, linear
|
||||
]
|
||||
))
|
||||
)
|
||||
proc.waitForFinished()
|
||||
|
||||
errors = proc.readAllStandardError()
|
||||
if len(errors) != 0:
|
||||
if proc.exitCode() != 0:
|
||||
logger.error(
|
||||
f"{logger_color_red()}" +
|
||||
f"MailleurTT error: {proc.exitCode()}" +
|
||||
f"{logger_color_reset()}"
|
||||
)
|
||||
outputs = proc.readAllStandardOutput()
|
||||
logger.debug(outputs)
|
||||
|
||||
errors = proc.readAllStandardError()
|
||||
logger.error(
|
||||
f"{logger_color_red()}{errors}{logger_color_reset()}"
|
||||
)
|
||||
else:
|
||||
self.import_m_file(reach, m_file)
|
||||
|
||||
return reach
|
||||
|
||||
def export_reach_to_st(self, reach, tmp):
|
||||
@@ -318,7 +361,9 @@ class MeshingWithMageMailleurTT(AMeshingTool):
|
||||
return tmp_st
|
||||
|
||||
def import_m_file(self, reach, m):
|
||||
reach.purge()
|
||||
|
||||
logger.debug(f"meshing: Import geometry from {m}")
|
||||
reach.import_geometry(m)
|
||||
if os.path.exists(m):
|
||||
reach.purge()
|
||||
logger.debug(f"meshing: Import geometry from {m}")
|
||||
reach.import_geometry(m)
|
||||
else:
|
||||
logger.error(f"meshing: Meshed geometry file {m} do not exists")
|
||||
@@ -1,5 +1,5 @@
|
||||
# __init__.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# test_Model.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -25,9 +25,10 @@ from Model.Saved import SavedStatus
|
||||
from Model.Study import Study
|
||||
from Model.River import River
|
||||
|
||||
from Meshing.Mage import MeshingWithMage
|
||||
from Meshing.Mage import MeshingWithMage, MeshingWithMageMailleurTT
|
||||
|
||||
mage_mesher = os.path.exists(MeshingWithMage._lib_path())
|
||||
mage_mesher_TT = os.path.exists(MeshingWithMageMailleurTT._exe_path())
|
||||
|
||||
|
||||
class MeshingTestCase(unittest.TestCase):
|
||||
@@ -35,3 +36,8 @@ class MeshingTestCase(unittest.TestCase):
|
||||
def test_create_meshingtool_mage(self):
|
||||
mesher = MeshingWithMage()
|
||||
self.assertNotEqual(mesher, None)
|
||||
|
||||
@unittest.skipIf(not mage_mesher_TT, "mailleurTT is not available")
|
||||
def test_create_meshingtool_mageTT(self):
|
||||
mesher = MeshingWithMageMailleurTT()
|
||||
self.assertNotEqual(mesher, None)
|
||||
@@ -0,0 +1,178 @@
|
||||
# AddFile.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from functools import reduce
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
from Model.Tools.PamhyrDB import SQLSubModel
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
|
||||
|
||||
class AddFile(SQLSubModel):
|
||||
_sub_classes = []
|
||||
_id_cnt = 0
|
||||
|
||||
def __init__(self, id: int = -1, enabled=True,
|
||||
name="", path="", text="",
|
||||
status=None):
|
||||
super(AddFile, self).__init__()
|
||||
|
||||
if id == -1:
|
||||
self.id = AddFile._id_cnt
|
||||
else:
|
||||
self.id = id
|
||||
|
||||
self._status = status
|
||||
|
||||
self._enabled = enabled
|
||||
self._name = f"File {self.id}" if name == "" else name
|
||||
self._path = path
|
||||
self._text = text
|
||||
|
||||
AddFile._id_cnt = max(id, AddFile._id_cnt+1)
|
||||
|
||||
def __getitem__(self, key):
|
||||
value = None
|
||||
|
||||
if key == "enabled":
|
||||
value = self._enabled
|
||||
elif key == "name":
|
||||
value = self._name
|
||||
elif key == "path":
|
||||
value = self._path
|
||||
elif key == "text":
|
||||
value = self._text
|
||||
|
||||
return value
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key == "enabled":
|
||||
self._enabled = value
|
||||
elif key == "name":
|
||||
self._name = value
|
||||
elif key == "path":
|
||||
self._path = value
|
||||
elif key == "text":
|
||||
self._text = value
|
||||
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
return self._enabled
|
||||
|
||||
@enabled.setter
|
||||
def enabled(self, enabled):
|
||||
self._enabled = enabled
|
||||
self._status.modified()
|
||||
|
||||
def is_enabled(self):
|
||||
return self._enabled
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
self._name = name
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return self._path
|
||||
|
||||
@path.setter
|
||||
def path(self, path):
|
||||
self._path = path
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
return self._text
|
||||
|
||||
@text.setter
|
||||
def text(self, text):
|
||||
self._text = text
|
||||
self._status.modified()
|
||||
|
||||
@classmethod
|
||||
def _db_create(cls, execute):
|
||||
execute("""
|
||||
CREATE TABLE additional_files(
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
enabled BOOLEAN NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
text TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
|
||||
return cls._create_submodel(execute)
|
||||
|
||||
@classmethod
|
||||
def _db_update(cls, execute, version):
|
||||
major, minor, release = version.strip().split(".")
|
||||
if major == minor == "0":
|
||||
if int(release) < 8:
|
||||
cls._db_create(execute)
|
||||
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
new = []
|
||||
|
||||
table = execute(
|
||||
"SELECT id, enabled, name, path, text " +
|
||||
"FROM additional_files"
|
||||
)
|
||||
|
||||
for row in table:
|
||||
it = iter(row)
|
||||
|
||||
id = next(it)
|
||||
enabled = (next(it) == 1)
|
||||
name = next(it)
|
||||
path = next(it)
|
||||
text = next(it)
|
||||
|
||||
f = cls(
|
||||
id=id, enabled=enabled, name=name, path=path, text=text,
|
||||
status=data['status']
|
||||
)
|
||||
|
||||
new.append(f)
|
||||
|
||||
return new
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
sql = (
|
||||
"INSERT INTO " +
|
||||
"additional_files(id, enabled, name, path, text) " +
|
||||
"VALUES (" +
|
||||
f"{self.id}, {self._enabled}, " +
|
||||
f"'{self._db_format(self._name)}', " +
|
||||
f"'{self._db_format(self._path)}', " +
|
||||
f"'{self._db_format(self._text)}'" +
|
||||
")"
|
||||
)
|
||||
execute(sql)
|
||||
|
||||
return True
|
||||
@@ -0,0 +1,56 @@
|
||||
# AddFileList.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
from Model.Tools.PamhyrList import PamhyrModelList
|
||||
from Model.AdditionalFile.AddFile import AddFile
|
||||
|
||||
|
||||
class AddFileList(PamhyrModelList):
|
||||
_sub_classes = [AddFile]
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
new = cls(status=data["status"])
|
||||
|
||||
new._lst = AddFile._db_load(execute, data)
|
||||
|
||||
return new
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
ok = True
|
||||
|
||||
# Delete previous data
|
||||
execute("DELETE FROM additional_files")
|
||||
|
||||
for af in self._lst:
|
||||
ok &= af._db_save(execute, data)
|
||||
|
||||
return ok
|
||||
|
||||
@property
|
||||
def files(self):
|
||||
return self.lst
|
||||
|
||||
def new(self, index):
|
||||
n = AddFile(status=self._status)
|
||||
self.insert(index, n)
|
||||
self._status.modified()
|
||||
return n
|
||||
@@ -1,5 +1,5 @@
|
||||
# BoundaryCondition.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
import logging
|
||||
|
||||
from tools import trace, timer, old_pamhyr_date_to_timestamp
|
||||
from tools import (
|
||||
trace, timer,
|
||||
old_pamhyr_date_to_timestamp,
|
||||
date_iso_to_timestamp,
|
||||
date_dmy_to_timestamp,
|
||||
)
|
||||
|
||||
from Model.Tools.PamhyrDB import SQLSubModel
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
@@ -189,6 +194,10 @@ class BoundaryCondition(SQLSubModel):
|
||||
@classmethod
|
||||
def time_convert(cls, data):
|
||||
if type(data) is str:
|
||||
if data.count("-") == 2:
|
||||
return date_iso_to_timestamp(data)
|
||||
if data.count("/") == 2:
|
||||
return date_dmy_to_timestamp(data)
|
||||
if data.count(":") == 3:
|
||||
return old_pamhyr_date_to_timestamp(data)
|
||||
if data.count(":") == 2:
|
||||
@@ -200,6 +209,9 @@ class BoundaryCondition(SQLSubModel):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._name == "":
|
||||
return f"B{self.id + 1}"
|
||||
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# BoundaryConditionList.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# BoundaryConditionTypes.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Except.py -- Pamhyr model exceptions
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Friction.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -26,11 +26,21 @@ logger = logging.getLogger()
|
||||
|
||||
|
||||
class Friction(SQLSubModel):
|
||||
def __init__(self, name: str = "", status=None):
|
||||
_id_cnt = 0
|
||||
|
||||
def __init__(self, id: int = -1, name: str = "",
|
||||
status=None):
|
||||
super(Friction, self).__init__()
|
||||
|
||||
self._status = status
|
||||
|
||||
if id == -1:
|
||||
self.id = Friction._id_cnt
|
||||
else:
|
||||
self.id = id
|
||||
|
||||
Friction._id_cnt = max(self.id, Friction._id_cnt+1)
|
||||
|
||||
self._name = name
|
||||
self._edge = None
|
||||
self._begin_kp = 0.0
|
||||
@@ -42,7 +52,7 @@ class Friction(SQLSubModel):
|
||||
def _db_create(cls, execute):
|
||||
execute("""
|
||||
CREATE TABLE friction(
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
ind INTEGER NOT NULL,
|
||||
begin_kp REAL NOT NULL,
|
||||
end_kp REAL NOT NULL,
|
||||
@@ -70,28 +80,30 @@ class Friction(SQLSubModel):
|
||||
stricklers = data["stricklers"].stricklers
|
||||
|
||||
table = execute(
|
||||
"SELECT ind, begin_kp, end_kp, begin_strickler, end_strickler " +
|
||||
"SELECT id, ind, begin_kp, end_kp, " +
|
||||
"begin_strickler, end_strickler " +
|
||||
f"FROM friction WHERE reach = {reach.id}"
|
||||
)
|
||||
|
||||
for row in table:
|
||||
ind = row[0]
|
||||
id = row[0]
|
||||
ind = row[1]
|
||||
# Get stricklers
|
||||
if int(row[3]) == -1:
|
||||
if int(row[4]) == -1:
|
||||
bs = None
|
||||
else:
|
||||
bs = next(filter(lambda s: s.id == row[3], stricklers))
|
||||
bs = next(filter(lambda s: s.id == row[4], stricklers))
|
||||
|
||||
if int(row[4]) == -1:
|
||||
if int(row[5]) == -1:
|
||||
es = None
|
||||
else:
|
||||
es = next(filter(lambda s: s.id == row[4], stricklers))
|
||||
es = next(filter(lambda s: s.id == row[5], stricklers))
|
||||
|
||||
# Create friction
|
||||
sec = cls(status=status)
|
||||
sec.edge = reach
|
||||
sec.begin_kp = row[1]
|
||||
sec.end_kp = row[2]
|
||||
sec.begin_kp = row[2]
|
||||
sec.end_kp = row[3]
|
||||
sec.begin_strickler = bs
|
||||
sec.end_strickler = es
|
||||
|
||||
@@ -112,10 +124,11 @@ class Friction(SQLSubModel):
|
||||
|
||||
execute(
|
||||
"INSERT INTO " +
|
||||
"friction(ind, begin_kp, end_kp, " +
|
||||
"friction(id, ind, begin_kp, end_kp, " +
|
||||
"reach, begin_strickler, end_strickler) " +
|
||||
"VALUES (" +
|
||||
f"{ind}, {self._begin_kp}, {self._end_kp}, " +
|
||||
f"{self.id}, {ind}, " +
|
||||
f"{self._begin_kp}, {self._end_kp}, " +
|
||||
f"{self._edge.id}, " +
|
||||
f"{b_s_id}, {e_s_id}" +
|
||||
")"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# FrictionList.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Point.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# PointXY.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# PointXYZ.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -47,7 +47,7 @@ class PointXYZ(Point, SQLSubModel):
|
||||
z INTEGER NOT NULL,
|
||||
profile INTEGER NOT NULL,
|
||||
sl INTEGER,
|
||||
FOREIGN KEY(profile) REFERENCES profileXYZ(id),
|
||||
FOREIGN KEY(profile) REFERENCES geometry_profileXYZ(id),
|
||||
FOREIGN KEY(sl) REFERENCES sedimentary_layer(id)
|
||||
)
|
||||
""")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Profile.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ProfileXYZ.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -478,57 +478,55 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
return abs(rg.dist(rd))
|
||||
|
||||
def get_water_limits(self, z):
|
||||
# ====================================================================
|
||||
# détermination des points limites RG et RD pour un niveau
|
||||
# d'eau donné
|
||||
#
|
||||
# irg et ird sont les premiers indices en partant des rives
|
||||
# gauche et droite qui correspondent à des points sous la
|
||||
# surface de l'eau ptX et ptY sont les points interpolés où
|
||||
# le plan d'eau intersecte le profil known_level est le
|
||||
# niveau d'eau pour lequel on a obtenu irg, ird, ptX et ptY
|
||||
# ====================================================================
|
||||
"""
|
||||
Determine left and right limits of water elevation.
|
||||
"""
|
||||
|
||||
# initialisation
|
||||
irg = -1
|
||||
ird = -1
|
||||
# Get the index of first point with elevation lesser than water
|
||||
# elevation (for the right and left river side)
|
||||
i_left = -1
|
||||
i_right = -1
|
||||
|
||||
for i in range(self.number_points):
|
||||
if self.point(i).z <= z:
|
||||
irg = i
|
||||
i_left = i
|
||||
break
|
||||
|
||||
for i in reversed(range(self.number_points)):
|
||||
if self.point(i).z <= z:
|
||||
ird = i
|
||||
i_right = i
|
||||
break
|
||||
|
||||
# interpolation des points ptX et ptY
|
||||
if (irg < self.number_points - 1):
|
||||
# Interpolate points at river left side
|
||||
if (i_left > 0):
|
||||
x = np.interp(
|
||||
z,
|
||||
[self.point(irg).z, self.point(irg + 1).z],
|
||||
[self.point(irg).x, self.point(irg + 1).x]
|
||||
[self.point(i_left).z, self.point(i_left - 1).z],
|
||||
[self.point(i_left).x, self.point(i_left - 1).x]
|
||||
)
|
||||
y = np.interp(
|
||||
z,
|
||||
[self.point(irg).z, self.point(irg + 1).z],
|
||||
[self.point(irg).y, self.point(irg + 1).y]
|
||||
[self.point(i_left).z, self.point(i_left - 1).z],
|
||||
[self.point(i_left).y, self.point(i_left - 1).y]
|
||||
)
|
||||
ptX = PointXYZ(x, y, z)
|
||||
pt_left = PointXYZ(x, y, z)
|
||||
else:
|
||||
ptX = self.point(0)
|
||||
if (ird > 0):
|
||||
pt_left = self.point(0)
|
||||
|
||||
# Interpolate points at river right side
|
||||
if (i_right < self.number_points - 1):
|
||||
x = np.interp(
|
||||
z,
|
||||
[self.point(ird-1).z, self.point(ird).z],
|
||||
[self.point(ird-1).x, self.point(ird).x]
|
||||
[self.point(i_right).z, self.point(i_right + 1).z],
|
||||
[self.point(i_right).x, self.point(i_right + 1).x]
|
||||
)
|
||||
y = np.interp(
|
||||
z,
|
||||
[self.point(ird).z, self.point(ird - 1).z],
|
||||
[self.point(ird).y, self.point(ird - 1).y]
|
||||
[self.point(i_right).z, self.point(i_right + 1).z],
|
||||
[self.point(i_right).y, self.point(i_right + 1).y]
|
||||
)
|
||||
ptY = PointXYZ(x, y, z)
|
||||
pt_right = PointXYZ(x, y, z)
|
||||
else:
|
||||
ptY = self.point(self.number_points - 1)
|
||||
pt_right = self.point(self.number_points - 1)
|
||||
|
||||
return ptX, ptY
|
||||
return pt_left, pt_right
|
||||
@@ -1,5 +1,5 @@
|
||||
# Reach.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -65,7 +65,7 @@ class Reach(SQLSubModel):
|
||||
|
||||
new._profiles = ProfileXYZ._db_load(
|
||||
execute,
|
||||
data=data
|
||||
data=data.copy()
|
||||
)
|
||||
|
||||
return new
|
||||
@@ -111,7 +111,7 @@ class Reach(SQLSubModel):
|
||||
def _get_profiles_list(self):
|
||||
# Profiles list generator is type (int, Point) with the first
|
||||
# element the index of the Point in list
|
||||
logger.info(f"Load profiles from reach {self.name}")
|
||||
logger.debug(f"Load profiles from reach {self.name}")
|
||||
return list(
|
||||
map(
|
||||
lambda p: p[1],
|
||||
@@ -743,7 +743,10 @@ class Reach(SQLSubModel):
|
||||
incline_acc.sort()
|
||||
|
||||
marge = round(len(incline_acc) * 0.1)
|
||||
incline_set = incline_acc[marge:-marge]
|
||||
if marge > 0:
|
||||
incline_set = incline_acc[marge:-marge]
|
||||
else:
|
||||
incline_set = incline_acc
|
||||
|
||||
logger.debug(f"+{incline_acc}")
|
||||
logger.debug(f"-{incline_set}")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Vector_1d.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# HydraulicStructures.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -158,6 +158,9 @@ class BasicHS(SQLSubModel):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._name == "":
|
||||
return f"{self._type}{self.id + 1}"
|
||||
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Types.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Value.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# HydraulicStructures.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -187,6 +187,9 @@ class HydraulicStructure(SQLSubModel):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._name == "":
|
||||
return f"HS{self.id + 1}"
|
||||
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# HydraulicStructuresList.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# InitialConditions.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -430,7 +430,7 @@ class InitialConditions(SQLSubModel):
|
||||
logger.debug(f"({profile.kp}):")
|
||||
logger.debug(f" width = {width}")
|
||||
logger.debug(f" strickler = {strickler}")
|
||||
logger.debug(f" hieght = {height}")
|
||||
logger.debug(f" height = {height}")
|
||||
|
||||
new = Data(reach=self._reach, status=self._status)
|
||||
new["kp"] = profile.kp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# InitialConditionsDict.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# LateralContribution.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
import logging
|
||||
|
||||
from tools import trace, timer, old_pamhyr_date_to_timestamp
|
||||
from tools import (
|
||||
trace, timer,
|
||||
old_pamhyr_date_to_timestamp,
|
||||
date_iso_to_timestamp,
|
||||
date_dmy_to_timestamp,
|
||||
)
|
||||
|
||||
from Model.Tools.PamhyrDB import SQLSubModel
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
@@ -189,6 +194,10 @@ class LateralContribution(SQLSubModel):
|
||||
@classmethod
|
||||
def time_convert(cls, data):
|
||||
if type(data) is str:
|
||||
if data.count("-") == 2:
|
||||
return date_iso_to_timestamp(data)
|
||||
if data.count("/") == 2:
|
||||
return date_dmy_to_timestamp(data)
|
||||
if data.count(":") == 3:
|
||||
return old_pamhyr_date_to_timestamp(data)
|
||||
if data.count(":") == 2:
|
||||
@@ -200,6 +209,9 @@ class LateralContribution(SQLSubModel):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._name == "":
|
||||
return f"L{self.id + 1}"
|
||||
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# LateralContributionList.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# LateralContributionTypes.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Edge.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Graph.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -67,6 +67,13 @@ class Graph(object):
|
||||
def edges_counts(self):
|
||||
return len(self._edges)
|
||||
|
||||
def enable_nodes_counts(self):
|
||||
return reduce(
|
||||
lambda acc, n: acc + 1 if self.is_enable_node(n) else acc,
|
||||
self._nodes,
|
||||
0
|
||||
)
|
||||
|
||||
def enable_edges_counts(self):
|
||||
return reduce(
|
||||
lambda acc, e: acc + 1 if e.is_enable() else acc,
|
||||
@@ -213,6 +220,12 @@ class Graph(object):
|
||||
True
|
||||
)
|
||||
|
||||
def is_internal_node(self, node):
|
||||
return not (
|
||||
self.is_upstream_node(node) or
|
||||
self.is_downstream_node(node)
|
||||
)
|
||||
|
||||
def is_enable_node(self, node):
|
||||
return reduce(
|
||||
lambda acc, e: (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Node.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Point.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# __init__.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# test_Network.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
# REPLine.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from functools import reduce
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
from Model.Tools.PamhyrDB import SQLSubModel
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
|
||||
|
||||
class REPLine(SQLSubModel):
|
||||
_sub_classes = []
|
||||
_id_cnt = 0
|
||||
|
||||
def __init__(self, id: int = -1, enabled=True,
|
||||
name="", line="", solvers=set(),
|
||||
status=None):
|
||||
super(REPLine, self).__init__()
|
||||
|
||||
if id == -1:
|
||||
self.id = REPLine._id_cnt
|
||||
else:
|
||||
self.id = id
|
||||
|
||||
self._status = status
|
||||
|
||||
self._enabled = enabled
|
||||
self._name = f"Line{self.id}" if name == "" else name
|
||||
self._line = line
|
||||
self._solvers = solvers
|
||||
|
||||
REPLine._id_cnt = max(id, REPLine._id_cnt+1)
|
||||
|
||||
def __getitem__(self, key):
|
||||
value = None
|
||||
|
||||
if key == "enabled":
|
||||
value = self._enabled
|
||||
elif key == "name":
|
||||
value = self._name
|
||||
elif key == "line":
|
||||
value = self._line
|
||||
elif key == "solvers":
|
||||
value = self._solvers
|
||||
|
||||
return value
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key == "enabled":
|
||||
self._enabled = value
|
||||
elif key == "name":
|
||||
self._name = value
|
||||
elif key == "line":
|
||||
self._line = value
|
||||
elif key == "solvers":
|
||||
self._solvers = value
|
||||
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
return self._enabled
|
||||
|
||||
@enabled.setter
|
||||
def enabled(self, enabled):
|
||||
self._enabled = enabled
|
||||
self._status.modified()
|
||||
|
||||
def is_enabled(self):
|
||||
return self._enabled
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
self._name = name
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def line(self):
|
||||
return self._line
|
||||
|
||||
@line.setter
|
||||
def line(self, line):
|
||||
self._line = line
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def solvers(self):
|
||||
return self._solvers
|
||||
|
||||
@solvers.setter
|
||||
def solvers(self, solvers):
|
||||
self._solvers = solvers
|
||||
self._status.modified()
|
||||
|
||||
@classmethod
|
||||
def _db_create(cls, execute):
|
||||
execute("""
|
||||
CREATE TABLE rep_lines(
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
enabled BOOLEAN NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
line TEXT NOT NULL,
|
||||
solvers TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
|
||||
return cls._create_submodel(execute)
|
||||
|
||||
@classmethod
|
||||
def _db_update(cls, execute, version):
|
||||
major, minor, release = version.strip().split(".")
|
||||
if major == minor == "0":
|
||||
if int(release) < 9:
|
||||
cls._db_create(execute)
|
||||
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
new = []
|
||||
|
||||
table = execute(
|
||||
"SELECT id, enabled, name, line, solvers " +
|
||||
"FROM rep_lines"
|
||||
)
|
||||
|
||||
for row in table:
|
||||
it = iter(row)
|
||||
|
||||
id = next(it)
|
||||
enabled = (next(it) == 1)
|
||||
name = next(it)
|
||||
line = next(it)
|
||||
solvers = set(next(it).split(";;"))
|
||||
|
||||
f = cls(
|
||||
id=id, enabled=enabled, name=name, line=line,
|
||||
solvers=solvers, status=data['status']
|
||||
)
|
||||
|
||||
new.append(f)
|
||||
|
||||
return new
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
solvers = ";;".join(self._solvers)
|
||||
|
||||
sql = (
|
||||
"INSERT INTO " +
|
||||
"rep_lines(id, enabled, name, line, solvers) " +
|
||||
"VALUES (" +
|
||||
f"{self.id}, {self._enabled}, " +
|
||||
f"'{self._db_format(self._name)}', " +
|
||||
f"'{self._db_format(self._line)}', " +
|
||||
f"'{self._db_format(solvers)}'" +
|
||||
")"
|
||||
)
|
||||
execute(sql)
|
||||
|
||||
return True
|
||||
@@ -0,0 +1,56 @@
|
||||
# REPLineList.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
from Model.Tools.PamhyrList import PamhyrModelList
|
||||
from Model.REPLine.REPLine import REPLine
|
||||
|
||||
|
||||
class REPLineList(PamhyrModelList):
|
||||
_sub_classes = [REPLine]
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
new = cls(status=data["status"])
|
||||
|
||||
new._lst = REPLine._db_load(execute, data)
|
||||
|
||||
return new
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
ok = True
|
||||
|
||||
# Delete previous data
|
||||
execute("DELETE FROM rep_lines")
|
||||
|
||||
for af in self._lst:
|
||||
ok &= af._db_save(execute, data)
|
||||
|
||||
return ok
|
||||
|
||||
@property
|
||||
def lines(self):
|
||||
return self.lst
|
||||
|
||||
def new(self, index):
|
||||
n = REPLine(status=self._status)
|
||||
self.insert(index, n)
|
||||
self._status.modified()
|
||||
return n
|
||||
@@ -1,5 +1,5 @@
|
||||
# Reservoir.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -152,6 +152,9 @@ class Reservoir(SQLSubModel):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._name == "":
|
||||
return f"R{self.id + 1}"
|
||||
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ReservoirList.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Results.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# River.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -59,6 +59,9 @@ class Profile(object):
|
||||
def get_ts_key(self, timestamp, key):
|
||||
return self._data[timestamp][key]
|
||||
|
||||
def has_sediment(self):
|
||||
return any(map(lambda ts: "sl" in self._data[ts], self._data))
|
||||
|
||||
|
||||
class Reach(object):
|
||||
def __init__(self, reach, study):
|
||||
@@ -92,6 +95,9 @@ class Reach(object):
|
||||
def set(self, profile_id, timestamp, key, data):
|
||||
self._profiles[profile_id].set(timestamp, key, data)
|
||||
|
||||
def has_sediment(self):
|
||||
return any(map(lambda profile: profile.has_sediment(), self._profiles))
|
||||
|
||||
|
||||
class River(object):
|
||||
def __init__(self, study):
|
||||
|
||||
+55
-21
@@ -1,5 +1,5 @@
|
||||
# River.py -- Pamhyr river model
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -40,6 +40,8 @@ from Model.Reservoir.ReservoirList import ReservoirList
|
||||
from Model.HydraulicStructures.HydraulicStructuresList import (
|
||||
HydraulicStructureList,
|
||||
)
|
||||
from Model.AdditionalFile.AddFileList import AddFileList
|
||||
from Model.REPLine.REPLineList import REPLineList
|
||||
|
||||
from Solver.Solvers import solver_type_list
|
||||
|
||||
@@ -224,6 +226,8 @@ class River(Graph, SQLSubModel):
|
||||
SedimentLayerList,
|
||||
ReservoirList,
|
||||
HydraulicStructureList,
|
||||
AddFileList,
|
||||
REPLineList,
|
||||
]
|
||||
|
||||
def __init__(self, status=None):
|
||||
@@ -245,6 +249,8 @@ class River(Graph, SQLSubModel):
|
||||
self._hydraulic_structures = HydraulicStructureList(
|
||||
status=self._status
|
||||
)
|
||||
self._additional_files = AddFileList(status=self._status)
|
||||
self._rep_lines = REPLineList(status=self._status)
|
||||
|
||||
@classmethod
|
||||
def _db_create(cls, execute):
|
||||
@@ -263,66 +269,62 @@ class River(Graph, SQLSubModel):
|
||||
# Stricklers (Stricklers is load in first because it's needed
|
||||
# for reachs)
|
||||
new._stricklers = StricklersList._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
data["stricklers"] = new._stricklers
|
||||
|
||||
# Initial conditions
|
||||
new._sediment_layers = SedimentLayerList._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
data["sediment_layers_list"] = new._sediment_layers
|
||||
|
||||
# Network
|
||||
new._nodes = RiverNode._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
data["nodes"] = new.nodes()
|
||||
|
||||
new._edges = RiverReach._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
data["edges"] = new.edges()
|
||||
|
||||
# Boundary Condition
|
||||
new._boundary_condition = BoundaryConditionList._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
# Lateral Contribution
|
||||
new._lateral_contribution = LateralContributionList._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
|
||||
# Initial conditions
|
||||
new._initial_conditions = InitialConditionsDict._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
|
||||
# Reservoir
|
||||
new._reservoir = ReservoirList._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
|
||||
# Hydraulic Structures
|
||||
new._hydraulic_structures = HydraulicStructureList._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
|
||||
# Parameters
|
||||
new._parameters = SolverParametersList._db_load(
|
||||
execute,
|
||||
data
|
||||
execute, data
|
||||
)
|
||||
|
||||
# Additional Files
|
||||
new._additional_files = AddFileList._db_load(
|
||||
execute, data
|
||||
)
|
||||
new._rep_lines = REPLineList._db_load(execute, data)
|
||||
|
||||
return new
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
@@ -336,6 +338,8 @@ class River(Graph, SQLSubModel):
|
||||
objs.append(self._stricklers)
|
||||
objs.append(self._reservoir)
|
||||
objs.append(self._hydraulic_structures)
|
||||
objs.append(self._additional_files)
|
||||
objs.append(self._rep_lines)
|
||||
|
||||
for solver in self._parameters:
|
||||
objs.append(self._parameters[solver])
|
||||
@@ -372,6 +376,28 @@ class River(Graph, SQLSubModel):
|
||||
except Exception as e:
|
||||
logger_exception(e)
|
||||
|
||||
def init_default(self):
|
||||
self.init_default_network()
|
||||
self.init_default_additional_files()
|
||||
|
||||
def init_default_network(self):
|
||||
n1 = self.add_node(880.0, 950.0)
|
||||
n2 = self.add_node(1120.0, 1020.0)
|
||||
|
||||
e = self.add_edge(n1, n2)
|
||||
|
||||
def init_default_additional_files(self):
|
||||
add_file = self._additional_files.new(0)
|
||||
add_file.name = "Pamhyr2 stamp file"
|
||||
add_file.path = "Pamhyr2.txt"
|
||||
add_file.text = """This repository has been generated by Pamhyr2 \
|
||||
version "@version" !
|
||||
|
||||
All hand made file modification could be erased by the next solver
|
||||
execution...
|
||||
|
||||
Last export at: @date."""
|
||||
|
||||
@property
|
||||
def boundary_condition(self):
|
||||
return self._boundary_condition
|
||||
@@ -413,6 +439,14 @@ class River(Graph, SQLSubModel):
|
||||
def hydraulic_structures(self):
|
||||
return self._hydraulic_structures
|
||||
|
||||
@property
|
||||
def additional_files(self):
|
||||
return self._additional_files
|
||||
|
||||
@property
|
||||
def rep_lines(self):
|
||||
return self._rep_lines
|
||||
|
||||
@property
|
||||
def parameters(self):
|
||||
return self._parameters
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Saved.py -- Pamhyr model status class
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# SedimentLayer.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from functools import reduce
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
from Model.Tools.PamhyrDB import SQLSubModel
|
||||
@@ -37,6 +55,9 @@ class Layer(SQLSubModel):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._name == "":
|
||||
return f"Layer{self.id + 1}"
|
||||
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
@@ -204,6 +225,9 @@ class SedimentLayer(SQLSubModel):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._name == "":
|
||||
return f"SL{self.id + 1}"
|
||||
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
@@ -340,3 +364,29 @@ class SedimentLayer(SQLSubModel):
|
||||
lst[index], lst[prev] = lst[prev], lst[index]
|
||||
|
||||
self._status.modified()
|
||||
|
||||
def compute_height_from_bottom(self, bottom_elevation: list):
|
||||
sl_height = self.height()
|
||||
|
||||
sl_height_by_profile = []
|
||||
for i in range(len(sl_height)):
|
||||
cur_profile = []
|
||||
for _ in bottom_elevation:
|
||||
cur_profile.append(sl_height[i])
|
||||
|
||||
sl_height_by_profile.append(cur_profile)
|
||||
|
||||
z_sl = reduce(
|
||||
lambda acc, current_sl: acc + [
|
||||
list(
|
||||
map(
|
||||
lambda cur_sl_h, prev_sl_h: prev_sl_h - cur_sl_h,
|
||||
current_sl, acc[-1]
|
||||
)
|
||||
)
|
||||
],
|
||||
sl_height_by_profile,
|
||||
[bottom_elevation]
|
||||
)
|
||||
|
||||
return z_sl
|
||||
@@ -1,3 +1,19 @@
|
||||
# SedimentLayerList.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Serializable.py -- Pamhyr pickle abstract class
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SolverParametersList.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Stricklers.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -120,6 +120,8 @@ class Stricklers(SQLSubModel):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._name == "":
|
||||
return f"K{self.id + 1}"
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# StricklersList.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
+26
-6
@@ -1,5 +1,5 @@
|
||||
# Study.py -- Pamhyr Study class
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -41,7 +41,7 @@ class Study(SQLModel):
|
||||
|
||||
def __init__(self, filename=None, init_new=True):
|
||||
# Metadata
|
||||
self._version = "0.0.7"
|
||||
self._version = "0.0.9"
|
||||
self.creation_date = datetime.now()
|
||||
self.last_modification_date = datetime.now()
|
||||
self.last_save_date = datetime.now()
|
||||
@@ -103,10 +103,20 @@ class Study(SQLModel):
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
is_new = False
|
||||
fname = fname + "." + str(self._old_save_id)
|
||||
filename = os.path.join(fdir, "_PAMHYR_", "__old__", fname)
|
||||
shutil.copy(self.filename, filename)
|
||||
self._old_save_id += 1
|
||||
if os.path.exists(self.filename) and ".backup" not in self.filename:
|
||||
filename = os.path.join(fdir, "_PAMHYR_", "__old__", fname)
|
||||
logger.debug(f"Backup previous version copy: {filename}")
|
||||
shutil.copy(self.filename, filename)
|
||||
self._old_save_id += 1
|
||||
is_new = True
|
||||
|
||||
if ".backup" in self.filename:
|
||||
is_new = True
|
||||
|
||||
self._init_db_file(self.filename, is_new=is_new)
|
||||
self.commit()
|
||||
|
||||
# Save
|
||||
self.last_save_date = datetime.now()
|
||||
@@ -128,6 +138,16 @@ class Study(SQLModel):
|
||||
|
||||
@filename.setter
|
||||
def filename(self, filename):
|
||||
if filename is None:
|
||||
self._filename = None
|
||||
self.status.modified()
|
||||
return
|
||||
|
||||
if self._filename is not None and self._filename != "":
|
||||
self._filename = str(filename)
|
||||
self.status.modified()
|
||||
return
|
||||
|
||||
self._filename = str(filename)
|
||||
self._init_db_file(filename, is_new=True)
|
||||
self.status.modified()
|
||||
@@ -221,7 +241,7 @@ class Study(SQLModel):
|
||||
if version[0] == self._version:
|
||||
return True
|
||||
|
||||
logger.info("Update database")
|
||||
logger.debug("Update database")
|
||||
|
||||
if self._update_submodel(version[0]):
|
||||
self.execute(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# PamhyrDB.py -- Pamhyr abstract model database classes
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -23,7 +23,7 @@ import logging
|
||||
from pathlib import Path
|
||||
from functools import reduce
|
||||
|
||||
from tools import SQL
|
||||
from SQL import SQL
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
|
||||
logger = logging.getLogger()
|
||||
@@ -35,8 +35,10 @@ class SQLModel(SQL):
|
||||
_sub_classes = []
|
||||
|
||||
def _init_db_file(self, db, is_new=True):
|
||||
exists = Path(db).exists()
|
||||
if self._db is not None:
|
||||
self._db.close()
|
||||
|
||||
exists = Path(db).exists()
|
||||
if exists and is_new:
|
||||
os.remove(db)
|
||||
|
||||
@@ -68,6 +70,7 @@ class SQLModel(SQL):
|
||||
return True
|
||||
|
||||
def _create(self):
|
||||
|
||||
raise NotImplementedMethodeError(self, self._create)
|
||||
|
||||
def _update_submodel(self, version):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# PamhyrDict.py -- Pamhyr abstract dict for model classes
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -56,7 +56,7 @@ class PamhyrModelDict(SQLSubModel):
|
||||
def __len__(self):
|
||||
return len(self._dict)
|
||||
|
||||
def is_defined(self, key):
|
||||
def __contains__(self, key):
|
||||
return key in self._dict
|
||||
|
||||
def set(self, key, new):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# PamhyrList.py -- Pamhyr Abstract List object for the Model
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -62,16 +62,27 @@ class PamhyrModelList(SQLSubModel):
|
||||
|
||||
@property
|
||||
def lst(self):
|
||||
"""Return the PamhyrList as a Python list
|
||||
|
||||
Return the PamhyrList as a Python list. This list is the
|
||||
current list used in the PamhyrList object. **If you need to
|
||||
modify it, please make a copy.**
|
||||
|
||||
Returns: The Python list
|
||||
"""
|
||||
return self._lst
|
||||
|
||||
def __len__(self):
|
||||
return len(self.lst)
|
||||
|
||||
def get(self, row):
|
||||
return self._lst[row]
|
||||
def index(self, el):
|
||||
return self._lst.index(el)
|
||||
|
||||
def set(self, row, new):
|
||||
self._lst[row] = new
|
||||
def get(self, index):
|
||||
return self._lst[index]
|
||||
|
||||
def set(self, index, new):
|
||||
self._lst[index] = new
|
||||
if self._status is not None:
|
||||
self._status.modified()
|
||||
|
||||
@@ -93,6 +104,14 @@ class PamhyrModelList(SQLSubModel):
|
||||
self._status.modified()
|
||||
|
||||
def delete(self, lst):
|
||||
"""Delete a list of elements
|
||||
|
||||
Args:
|
||||
lst: The list of elements
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
for el in lst:
|
||||
self._lst.remove(el)
|
||||
|
||||
@@ -100,6 +119,14 @@ class PamhyrModelList(SQLSubModel):
|
||||
self._status.modified()
|
||||
|
||||
def delete_i(self, indexes):
|
||||
"""Delete elements from list of indexes
|
||||
|
||||
Args:
|
||||
indexes: The elements indexes
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
lst = list(
|
||||
map(
|
||||
lambda x: x[1],
|
||||
@@ -175,16 +202,32 @@ class PamhyrModelListWithTab(SQLSubModel):
|
||||
################
|
||||
|
||||
def len(self, lst):
|
||||
"""Size of tab list
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
|
||||
Returns:
|
||||
The size of the tab list
|
||||
"""
|
||||
return len(self._tabs[lst])
|
||||
|
||||
def get_tab(self, lst):
|
||||
"""Get tab list (copy) from name
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
return self._tabs[lst].copy()
|
||||
|
||||
def get(self, lst, row):
|
||||
return self._tabs[lst][row]
|
||||
def get(self, lst, index):
|
||||
return self._tabs[lst][index]
|
||||
|
||||
def set(self, lst, row, new):
|
||||
self._tabs[lst][row] = new
|
||||
def set(self, lst, index, new):
|
||||
self._tabs[lst][index] = new
|
||||
self._status.modified()
|
||||
|
||||
def new(self, lst, index):
|
||||
@@ -200,15 +243,43 @@ class PamhyrModelListWithTab(SQLSubModel):
|
||||
raise NotImplementedMethodeError(self, self.new)
|
||||
|
||||
def insert(self, lst, index, new):
|
||||
"""Insert element in tab
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
index: The index of new element
|
||||
new: The new elements
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
self._tabs[lst].insert(index, new)
|
||||
self._status.modified()
|
||||
|
||||
def delete(self, lst, els):
|
||||
"""Delete elements from specific tab
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
els: The elements list
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
for el in els:
|
||||
self._tabs[lst].remove(el)
|
||||
self._status.modified()
|
||||
|
||||
def delete_i(self, lst, indexes):
|
||||
"""Delete elements from specific tab
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
indexes: The elements indexes
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
els = list(
|
||||
map(
|
||||
lambda x: x[1],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# __init__.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# test_Model.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# Modules.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from enum import Flag, auto
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class Modules(Flag):
|
||||
NONE = 0
|
||||
|
||||
# General
|
||||
STUDY = auto()
|
||||
CONFIG = auto()
|
||||
|
||||
# Modelling
|
||||
NETWORK = auto()
|
||||
GEOMETRY = auto()
|
||||
BOUNDARY_CONDITION = auto()
|
||||
LATERAL_CONTRIBUTION = auto()
|
||||
FRICTION = auto()
|
||||
INITIAL_CONDITION = auto()
|
||||
HYDRAULIC_STRUCTURES = auto()
|
||||
RESERVOIR = auto()
|
||||
SEDIMENT_LAYER = auto()
|
||||
ADDITIONAL_FILES = auto()
|
||||
|
||||
# Results
|
||||
RESULTS = auto()
|
||||
|
||||
# Display
|
||||
WINDOW_LIST = auto()
|
||||
|
||||
@classmethod
|
||||
def all(cls):
|
||||
return ~cls.NONE
|
||||
|
||||
@classmethod
|
||||
def modelling(cls):
|
||||
return (
|
||||
cls.NETWORK
|
||||
| cls.GEOMETRY
|
||||
| cls.BOUNDARY_CONDITION
|
||||
| cls.LATERAL_CONTRIBUTION
|
||||
| cls.FRICTION
|
||||
| cls.INITIAL_CONDITION
|
||||
| cls.HYDRAULIC_STRUCTURES
|
||||
| cls.RESERVOIR
|
||||
| cls.SEDIMENT_LAYER
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def modelling_list(cls):
|
||||
return [
|
||||
cls.NETWORK,
|
||||
cls.GEOMETRY,
|
||||
cls.BOUNDARY_CONDITION,
|
||||
cls.LATERAL_CONTRIBUTION,
|
||||
cls.FRICTION,
|
||||
cls.INITIAL_CONDITION,
|
||||
cls.HYDRAULIC_STRUCTURES,
|
||||
cls.RESERVOIR,
|
||||
cls.SEDIMENT_LAYER,
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def modelling_display_name(cls):
|
||||
return {
|
||||
cls.NETWORK: "Network",
|
||||
cls.GEOMETRY: "Geometry",
|
||||
cls.BOUNDARY_CONDITION: "Boundary condition",
|
||||
cls.LATERAL_CONTRIBUTION: "Lateral contribution",
|
||||
cls.FRICTION: "Friction",
|
||||
cls.INITIAL_CONDITION: "Initial condition",
|
||||
cls.HYDRAULIC_STRUCTURES: "Hydraulic structures",
|
||||
cls.RESERVOIR: "Reservoir",
|
||||
cls.SEDIMENT_LAYER: "Sediment layer",
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
# SQL.py -- Pamhyr
|
||||
# Copyright (C) 2023-2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import logging
|
||||
import sqlite3
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from tools import timer
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class SQL(object):
|
||||
def _init_db_file(self, db):
|
||||
exists = Path(db).exists()
|
||||
|
||||
os.makedirs(
|
||||
os.path.dirname(db),
|
||||
exist_ok=True
|
||||
)
|
||||
|
||||
self._db = sqlite3.connect(db)
|
||||
self._cur = self._db.cursor()
|
||||
|
||||
if not exists:
|
||||
self._create() # Create db
|
||||
self._save() # Save
|
||||
else:
|
||||
self._update() # Update db scheme if necessary
|
||||
self._load() # Load data
|
||||
|
||||
def __init__(self, filename=None):
|
||||
self._db = None
|
||||
|
||||
if filename is not None:
|
||||
self._init_db_file(filename)
|
||||
|
||||
def commit(self):
|
||||
logger.debug("SQL - commit")
|
||||
self._db.commit()
|
||||
|
||||
def _close(self):
|
||||
self.commit()
|
||||
self._db.close()
|
||||
|
||||
def _fetch_string(self, s):
|
||||
return s.replace("'", "'")
|
||||
|
||||
def _fetch_tuple(self, tup):
|
||||
res = []
|
||||
for v in tup:
|
||||
if type(v) is str:
|
||||
v = self._fetch_string(v)
|
||||
res.append(v)
|
||||
|
||||
return res
|
||||
|
||||
def _fetch_list(self, lst):
|
||||
res = []
|
||||
for v in lst:
|
||||
if type(v) is str:
|
||||
v = self._fetch_string(v)
|
||||
elif type(v) is tuple:
|
||||
v = self._fetch_tuple(v)
|
||||
res.append(v)
|
||||
|
||||
return res
|
||||
|
||||
def _fetch(self, res, one):
|
||||
if one:
|
||||
value = res.fetchone()
|
||||
else:
|
||||
value = res.fetchall()
|
||||
res = value
|
||||
|
||||
if type(value) is list:
|
||||
res = self._fetch_list(value)
|
||||
elif type(value) is tuple:
|
||||
res = self._fetch_tuple(value)
|
||||
|
||||
return res
|
||||
|
||||
def _db_format(self, value):
|
||||
# Replace ''' by ''' to preserve SQL injection
|
||||
if type(value) is str:
|
||||
value = value.replace("'", "'")
|
||||
return value
|
||||
|
||||
@timer
|
||||
def execute(self, cmd, fetch_one=True, commit=False):
|
||||
logger.debug(f"SQL - {cmd}")
|
||||
|
||||
value = None
|
||||
try:
|
||||
res = self._cur.execute(cmd)
|
||||
|
||||
if commit:
|
||||
self._db.commit()
|
||||
|
||||
value = self._fetch(res, fetch_one)
|
||||
except Exception as e:
|
||||
logger_exception(e)
|
||||
finally:
|
||||
return value
|
||||
|
||||
def _create(self):
|
||||
logger.warning("TODO: Create")
|
||||
|
||||
def _update(self):
|
||||
logger.warning("TODO: Update")
|
||||
|
||||
def _save(self):
|
||||
logger.warning("TODO: Save")
|
||||
|
||||
def _load(self):
|
||||
logger.warning("TODO: LOAD")
|
||||
@@ -1,5 +1,5 @@
|
||||
# AScript.py -- Pamhyr abstract script class
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Hello.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ListSolver.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# MageMesh.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# P3DST.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Run.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ASolver.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# CommandLine.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -19,7 +19,8 @@
|
||||
import os
|
||||
import logging
|
||||
|
||||
from tools import timer, parse_command_line
|
||||
from datetime import datetime
|
||||
from tools import timer, parse_command_line, get_version, logger_exception
|
||||
|
||||
try:
|
||||
# Installation allow Unix-like signal
|
||||
@@ -124,6 +125,54 @@ class CommandLineSolver(AbstractSolver):
|
||||
"""
|
||||
raise NotImplementedMethodeError(self, self.log_file)
|
||||
|
||||
def export_additional_files(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
if qlog is not None:
|
||||
qlog.put("Export additional files")
|
||||
|
||||
add_files = study.river.additional_files.files
|
||||
for add_file in add_files:
|
||||
self.export_additional_file(
|
||||
study, add_file, repertory, files
|
||||
)
|
||||
|
||||
return files
|
||||
|
||||
def export_additional_file(self, study, add_file, repertory, files):
|
||||
if add_file.path == "" or not add_file.is_enabled():
|
||||
return files
|
||||
|
||||
path = os.path.join(repertory, add_file.path)
|
||||
os.makedirs(
|
||||
os.path.dirname(path),
|
||||
exist_ok=True
|
||||
)
|
||||
|
||||
with open(path, "w+") as f:
|
||||
files.append(add_file.path)
|
||||
|
||||
txt = add_file.text
|
||||
txt = txt.replace("@version", get_version())
|
||||
txt = txt.replace("@date", datetime.now().isoformat(sep=" "))
|
||||
|
||||
f.write(txt)
|
||||
|
||||
return files
|
||||
|
||||
def export_study_description(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
path = os.path.join(
|
||||
repertory, "pamhyr-study-description.txt"
|
||||
)
|
||||
|
||||
with open(path, "w+", encoding='utf-8') as f:
|
||||
txt = study.description\
|
||||
.encode()\
|
||||
.decode('utf-8', 'replace')
|
||||
f.write(txt)
|
||||
|
||||
#######
|
||||
# Run #
|
||||
#######
|
||||
@@ -132,7 +181,7 @@ class CommandLineSolver(AbstractSolver):
|
||||
return os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"..", "..", ".."
|
||||
"..", ".."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -224,12 +273,15 @@ class CommandLineSolver(AbstractSolver):
|
||||
return True
|
||||
|
||||
def _data_ready(self):
|
||||
# Read process output and put lines in queue
|
||||
s = self._process.readAll().data().decode()
|
||||
try:
|
||||
# Read process output and put lines in queue
|
||||
s = self._process.readAll().data().decode('utf-8', "replace")
|
||||
|
||||
if self._output is not None:
|
||||
for x in s.split('\n'):
|
||||
self._output.put(x)
|
||||
if self._output is not None:
|
||||
for x in s.split(os.linesep):
|
||||
self._output.put(x)
|
||||
except Exception as e:
|
||||
logger_exception(e)
|
||||
|
||||
def _finished(self, study, exit_code, exit_status):
|
||||
if self._output is not None:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# GenericSolver.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
+151
-114
@@ -1,5 +1,5 @@
|
||||
# Mage.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -20,7 +20,7 @@ import os
|
||||
import logging
|
||||
import numpy as np
|
||||
|
||||
from tools import timer, trace
|
||||
from tools import timer, trace, logger_exception
|
||||
|
||||
from Solver.CommandLine import CommandLineSolver
|
||||
from Checker.Mage import (
|
||||
@@ -90,7 +90,7 @@ class Mage(CommandLineSolver):
|
||||
("mage_compute_reach_volume_balance", "y"),
|
||||
("mage_max_reach_volume_balance", "0.001"),
|
||||
("mage_min_reach_volume_to_check", "1000.0"),
|
||||
("mage_init_internal", " "),
|
||||
("mage_init_internal", "n"),
|
||||
]
|
||||
|
||||
return lst
|
||||
@@ -98,10 +98,9 @@ class Mage(CommandLineSolver):
|
||||
@classmethod
|
||||
def checkers(cls):
|
||||
lst = [
|
||||
MageNetworkGraphChecker(connectivity=True),
|
||||
MageNetworkGraphChecker(connectivity=False),
|
||||
MageGeometryGuideLineChecker(),
|
||||
|
||||
MageNetworkGraphChecker(connectivity=True, version=cls._type),
|
||||
MageNetworkGraphChecker(connectivity=False, version=cls._type),
|
||||
MageGeometryGuideLineChecker(version=cls._type),
|
||||
]
|
||||
|
||||
return lst
|
||||
@@ -129,7 +128,15 @@ class Mage(CommandLineSolver):
|
||||
name = self._study.name
|
||||
return f"{name}.TRA"
|
||||
|
||||
@timer
|
||||
def _export_REP_additional_lines(self, study, rep_file):
|
||||
lines = filter(
|
||||
lambda line: line.is_enabled(),
|
||||
study.river.rep_lines.lines
|
||||
)
|
||||
|
||||
for line in lines:
|
||||
rep_file.write(line.line)
|
||||
|
||||
def _export_ST(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -139,18 +146,9 @@ class Mage(CommandLineSolver):
|
||||
os.makedirs(os.path.join(repertory, "net"), exist_ok=True)
|
||||
|
||||
# Write header
|
||||
edges = study.river.edges()
|
||||
edges = list(
|
||||
filter(
|
||||
lambda e: e.is_enable(),
|
||||
edges
|
||||
)
|
||||
)
|
||||
|
||||
edges = study.river.enable_edges()
|
||||
for edge in edges:
|
||||
name = edge.name.replace(" ", "_")
|
||||
if edge._name == "":
|
||||
name = f"Reach_{edge.id}"
|
||||
name = f"Reach_{edge.id + 1:>3}".replace(" ", "0")
|
||||
|
||||
with mage_file_open(
|
||||
os.path.join(repertory, "net", f"{name}.ST"),
|
||||
@@ -237,7 +235,6 @@ class Mage(CommandLineSolver):
|
||||
# Point line
|
||||
wfile.write(f"{x} {y} {z} {n} {sediment}\n")
|
||||
|
||||
@timer
|
||||
def _export_BC(self, t, bounds, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -271,7 +268,6 @@ class Mage(CommandLineSolver):
|
||||
|
||||
return files
|
||||
|
||||
@timer
|
||||
def _export_bound_cond(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
lst = study.river.boundary_condition
|
||||
@@ -286,6 +282,9 @@ class Mage(CommandLineSolver):
|
||||
if bound.node is None:
|
||||
continue
|
||||
|
||||
if not study.river.is_enable_node(bound.node):
|
||||
continue
|
||||
|
||||
if bound.bctype == "ZD":
|
||||
AVA.append(bound)
|
||||
elif bound.bctype == "TD" or bound.bctype == "PC":
|
||||
@@ -302,42 +301,55 @@ class Mage(CommandLineSolver):
|
||||
|
||||
return files
|
||||
|
||||
# @timer
|
||||
# def _export_LC(self, lateral, repertory, qlog, name="0"):
|
||||
# files = []
|
||||
def _export_lateral_contrib(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
lst = study.river.lateral_contribution
|
||||
|
||||
# if qlog is not None:
|
||||
# qlog.put(f"Export LAT file")
|
||||
with mage_file_open(
|
||||
os.path.join(repertory, f"{name}.LAT"),
|
||||
"w+"
|
||||
) as f:
|
||||
if qlog is not None:
|
||||
qlog.put(f"Export LAT file")
|
||||
files.append(f"{name}.LAT")
|
||||
|
||||
# with mage_file_open(
|
||||
# os.path.join(repertory, f"{name}.LAT"),
|
||||
# "w+"
|
||||
# ) as f:
|
||||
# files.append(f"{name}.LAT")
|
||||
for tab in ["liquid", "solid", "suspenssion"]:
|
||||
for lateral in lst.get_tab(tab):
|
||||
self._export_LC(study, lateral, f, qlog)
|
||||
|
||||
# name = f"{lateral.node.id:3}".replace(" ", "x")
|
||||
# f.write(f"* {lateral.node.name} ({name}) {lateral.bctype}\n")
|
||||
# f.write(f"${name}\n")
|
||||
# header = lateral.header
|
||||
# f.write(f"*{header[0]:>9}|{header[1]:>10}\n")
|
||||
return files
|
||||
|
||||
# for d in lateral.data:
|
||||
# f.write(f"{d[0]:1{name}.3f}{d[1]:10.3f}\n")
|
||||
def _export_LC(self, study, lateral, f, qlog, name="0"):
|
||||
if lateral.edge is None:
|
||||
return
|
||||
|
||||
# return files
|
||||
edges = study.river.enable_edges()
|
||||
if lateral.edge not in edges:
|
||||
return
|
||||
|
||||
# @timer
|
||||
# def _export_lateral_contrib(self, study, repertory, qlog, name="0"):
|
||||
# files = []
|
||||
# lst = study.river.lateral_contribution
|
||||
eid, _ = next(
|
||||
filter(
|
||||
lambda e: e[1] == lateral.edge,
|
||||
enumerate(edges)
|
||||
)
|
||||
)
|
||||
|
||||
# for tab in ["liquid", "solid", "suspenssion"]:
|
||||
# for lateral in lst.get_tab(tab):
|
||||
# files = files + self._export_LC(lateral, repertory, qlog)
|
||||
name = f"{eid+1:>3}"
|
||||
# name = f"Reach_{lateral.edge.id + 1:>3}".replace(" ", "0")
|
||||
f.write(f"* {lateral.edge.name} ({name}) {lateral.lctype}\n")
|
||||
f.write(
|
||||
f"${name} " +
|
||||
f"{lateral.begin_kp:>10.4f} {lateral.end_kp:>10.4f}\n"
|
||||
)
|
||||
header = lateral.header
|
||||
f.write(f"*{header[0]:>9}|{header[1]:>10}\n")
|
||||
|
||||
# return files
|
||||
for d in lateral.data:
|
||||
if lateral.lctype in ["EV"]:
|
||||
f.write(f"{d[0]:10.3f}{-d[1]:10.3f}\n")
|
||||
else:
|
||||
f.write(f"{d[0]:10.3f}{d[1]:10.3f}\n")
|
||||
|
||||
@timer
|
||||
def _export_RUG(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -348,13 +360,7 @@ class Mage(CommandLineSolver):
|
||||
with mage_file_open(os.path.join(repertory, f"{name}.RUG"), "w+") as f:
|
||||
files.append(f"{name}.RUG")
|
||||
|
||||
edges = study.river.edges()
|
||||
edges = list(
|
||||
filter(
|
||||
lambda e: e.is_enable(),
|
||||
edges
|
||||
)
|
||||
)
|
||||
edges = study.river.enable_edges()
|
||||
|
||||
id = 1
|
||||
for edge in edges:
|
||||
@@ -381,7 +387,6 @@ class Mage(CommandLineSolver):
|
||||
|
||||
return files
|
||||
|
||||
@timer
|
||||
def _export_INI(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -424,7 +429,6 @@ class Mage(CommandLineSolver):
|
||||
files.append(f"{name}.INI")
|
||||
return files
|
||||
|
||||
@timer
|
||||
def _export_CAS(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -457,7 +461,6 @@ class Mage(CommandLineSolver):
|
||||
|
||||
return files
|
||||
|
||||
@timer
|
||||
def _export_SIN(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -489,35 +492,41 @@ class Mage(CommandLineSolver):
|
||||
if not hs.input_reach.is_enable():
|
||||
continue
|
||||
|
||||
if hs.input_kp is None:
|
||||
continue
|
||||
|
||||
f.write(
|
||||
'* ouvrage au pk ' +
|
||||
f"{float(hs.input_kp):>12.1f}" + ' ' +
|
||||
hs.name + '\n'
|
||||
)
|
||||
|
||||
for bhs in hs.basic_structures:
|
||||
reach_id = study.river.get_edge_id(hs.input_reach) + 1
|
||||
param_str = ' '.join(
|
||||
[
|
||||
f'{p:>10.3f}'
|
||||
for p in self._export_SIN_parameters(bhs)
|
||||
]
|
||||
)
|
||||
|
||||
name = bhs.name
|
||||
if name == "":
|
||||
name = f"HS_{bhs.id:>3}".replace(" ", "0")
|
||||
else:
|
||||
name = name.replace(" ", "_")
|
||||
|
||||
f.write(
|
||||
f"{sin_dict[bhs._type]} " +
|
||||
f"{reach_id} {float(hs.input_kp):>12.3f} " +
|
||||
f"{param_str} {name}\n"
|
||||
)
|
||||
self._export_SIN_bhs(study, sin_dict, hs, f)
|
||||
|
||||
return files
|
||||
|
||||
def _export_SIN_bhs(self, study, sin_dict, hs, f):
|
||||
for bhs in hs.basic_structures:
|
||||
reach_id = study.river.get_edge_id(hs.input_reach) + 1
|
||||
param_str = ' '.join(
|
||||
[
|
||||
f'{p:>10.3f}'
|
||||
for p in self._export_SIN_parameters(bhs)
|
||||
]
|
||||
)
|
||||
|
||||
name = bhs.name
|
||||
if name == "":
|
||||
name = f"HS_{bhs.id:>3}".replace(" ", "0")
|
||||
else:
|
||||
name = name.replace(" ", "_")
|
||||
|
||||
f.write(
|
||||
f"{sin_dict[bhs._type]} " +
|
||||
f"{reach_id} {float(hs.input_kp):>12.3f} " +
|
||||
f"{param_str} {name}\n"
|
||||
)
|
||||
|
||||
def _export_SIN_parameters(self, bhs):
|
||||
res = [9999.999] * 5
|
||||
|
||||
@@ -576,7 +585,6 @@ class Mage(CommandLineSolver):
|
||||
|
||||
return res
|
||||
|
||||
@timer
|
||||
def _export_VAR(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -612,7 +620,6 @@ class Mage(CommandLineSolver):
|
||||
|
||||
return files
|
||||
|
||||
@timer
|
||||
def _export_DEV(self, study, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -635,7 +642,6 @@ class Mage(CommandLineSolver):
|
||||
|
||||
return files
|
||||
|
||||
@timer
|
||||
def _export_REP(self, study, repertory, files, qlog, name="0"):
|
||||
if qlog is not None:
|
||||
qlog.put("Export REP file")
|
||||
@@ -657,6 +663,7 @@ class Mage(CommandLineSolver):
|
||||
f.write("* OUTPUT\n")
|
||||
f.write(f"TRA {name}.TRA\n")
|
||||
f.write(f"BIN {name}.BIN\n")
|
||||
f.write(f"ERR {name}.ERR\n")
|
||||
|
||||
for file in files:
|
||||
EXT = file.split('.')[1]
|
||||
@@ -664,6 +671,8 @@ class Mage(CommandLineSolver):
|
||||
if EXT in ["GRA"]:
|
||||
f.write(f"{EXT} {file}\n")
|
||||
|
||||
self._export_REP_additional_lines(study, f)
|
||||
|
||||
@timer
|
||||
def export(self, study, repertory, qlog=None):
|
||||
self._study = study
|
||||
@@ -674,6 +683,8 @@ class Mage(CommandLineSolver):
|
||||
self._bin_file = f"{name}.BIN"
|
||||
|
||||
self._export_ST(study, repertory, qlog, name=name)
|
||||
self.export_additional_files(study, repertory, qlog, name=name)
|
||||
self.export_study_description(study, repertory, qlog, name=name)
|
||||
|
||||
return True
|
||||
|
||||
@@ -765,7 +776,6 @@ class Mage8(Mage):
|
||||
|
||||
return lst
|
||||
|
||||
@timer
|
||||
def _export_PAR(self, study, repertory, qlog=None, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -792,11 +802,14 @@ class Mage8(Mage):
|
||||
value = ("p" if value.lower() in ["y", "yes", "true"]
|
||||
else "")
|
||||
|
||||
logger.debug(
|
||||
f"export: PAR: {name}: {value} ({p.value})"
|
||||
)
|
||||
|
||||
f.write(f"{name} {value}\n")
|
||||
|
||||
return files
|
||||
|
||||
@timer
|
||||
def _export_NET(self, study, repertory, qlog=None, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -806,20 +819,11 @@ class Mage8(Mage):
|
||||
with mage_file_open(os.path.join(repertory, f"{name}.NET"), "w+") as f:
|
||||
files.append(f"{name}.NET")
|
||||
|
||||
edges = study.river.edges()
|
||||
edges = list(
|
||||
filter(
|
||||
lambda e: e.is_enable(),
|
||||
edges
|
||||
)
|
||||
)
|
||||
edges = study.river.enable_edges()
|
||||
|
||||
for e in edges:
|
||||
name = e.name.replace(" ", "_")
|
||||
if e._name == "":
|
||||
name = f"Reach_{e.id}"
|
||||
|
||||
id = f"Bief_{e.id+1}"
|
||||
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")
|
||||
@@ -829,7 +833,6 @@ class Mage8(Mage):
|
||||
|
||||
return files
|
||||
|
||||
@timer
|
||||
def _export_QSO(self, bounds, repertory, qlog, name="0"):
|
||||
files = []
|
||||
|
||||
@@ -865,6 +868,16 @@ class Mage8(Mage):
|
||||
|
||||
return files
|
||||
|
||||
def export_func_dict(self):
|
||||
return [
|
||||
self._export_ST, self._export_PAR,
|
||||
self._export_NET, self._export_bound_cond,
|
||||
self._export_RUG, self._export_INI,
|
||||
self._export_SIN, self._export_VAR,
|
||||
self._export_CAS, self._export_DEV,
|
||||
self._export_lateral_contrib,
|
||||
]
|
||||
|
||||
@timer
|
||||
def export(self, study, repertory, qlog=None, name="0"):
|
||||
self._study = study
|
||||
@@ -877,20 +890,19 @@ class Mage8(Mage):
|
||||
# Generate files
|
||||
files = []
|
||||
|
||||
files = self._export_ST(study, repertory, qlog, name=name)
|
||||
files = files + self._export_PAR(study, repertory, qlog, name=name)
|
||||
files = files + self._export_NET(study, repertory, qlog, name=name)
|
||||
files = files + \
|
||||
self._export_bound_cond(study, repertory, qlog, name=name)
|
||||
files = files + self._export_RUG(study, repertory, qlog, name=name)
|
||||
files = files + self._export_INI(study, repertory, qlog, name=name)
|
||||
files = files + self._export_SIN(study, repertory, qlog, name=name)
|
||||
files = files + self._export_VAR(study, repertory, qlog, name=name)
|
||||
files = files + self._export_CAS(study, repertory, qlog, name=name)
|
||||
files = files + self._export_DEV(study, repertory, qlog, name=name)
|
||||
self._export_REP(study, repertory, files, qlog, name=name)
|
||||
try:
|
||||
for func in self.export_func_dict():
|
||||
files = files + func(study, repertory, qlog, name=name)
|
||||
|
||||
return True
|
||||
self.export_additional_files(study, repertory, qlog, name=name)
|
||||
self.export_study_description(study, repertory, qlog, name=name)
|
||||
self._export_REP(study, repertory, files, qlog, name=name)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to export study to {self._type}")
|
||||
logger_exception(e)
|
||||
return False
|
||||
|
||||
###########
|
||||
# RESULTS #
|
||||
@@ -1019,9 +1031,12 @@ class Mage8(Mage):
|
||||
reach.set(ri, timestamp, key, d)
|
||||
if key == "Z":
|
||||
profile = reach.profile(ri)
|
||||
ptX, ptY = profile.geometry.get_water_limits(d)
|
||||
reach.set(ri, timestamp, "ptX", ptX)
|
||||
reach.set(ri, timestamp, "ptY", ptY)
|
||||
limits = profile.geometry.get_water_limits(d)
|
||||
reach.set(
|
||||
ri, timestamp,
|
||||
"water_limits",
|
||||
limits
|
||||
)
|
||||
|
||||
endline()
|
||||
end = newline().size <= 0
|
||||
@@ -1200,12 +1215,34 @@ class Mage8(Mage):
|
||||
logger.info(f"read_gra: ... end with {len(ts)} timestamp read")
|
||||
|
||||
@timer
|
||||
def results(self, study, repertory, qlog=None, name=None):
|
||||
def results(self, study, repertory,
|
||||
qlog=None, name=None,
|
||||
with_gra=True):
|
||||
self._study = study
|
||||
if name is None:
|
||||
name = study.name.replace(" ", "_")
|
||||
|
||||
results = super(Mage8, self).results(study, repertory, qlog, name=name)
|
||||
self.read_gra(study, repertory, results, qlog, name=name)
|
||||
if with_gra:
|
||||
self.read_gra(study, repertory, results, qlog, name=name)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
class MageFake7(Mage8):
|
||||
_type = "mage_fake7"
|
||||
|
||||
def __init__(self, name):
|
||||
super(MageFake7, self).__init__(name)
|
||||
|
||||
self._type = "mage_fake7"
|
||||
|
||||
@timer
|
||||
def results(self, study, repertory,
|
||||
qlog=None, name=None,
|
||||
with_gra=False):
|
||||
results = super(MageFake7, self).results(
|
||||
study, repertory,
|
||||
qlog, name=name, with_gra=with_gra
|
||||
)
|
||||
return results
|
||||
@@ -1,5 +1,5 @@
|
||||
# Solvers.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -19,18 +19,22 @@
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
|
||||
from Solver.GenericSolver import GenericSolver
|
||||
from Solver.Mage import Mage7, Mage8
|
||||
from Solver.Mage import (
|
||||
Mage7, Mage8, MageFake7,
|
||||
)
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
solver_long_name = {
|
||||
"generic": "Generic",
|
||||
# "generic": "Generic",
|
||||
# "mage7": "Mage v7",
|
||||
"mage8": "Mage v8",
|
||||
# "mage_fake7": "Mage fake v7",
|
||||
}
|
||||
|
||||
solver_type_list = {
|
||||
"generic": GenericSolver,
|
||||
# "generic": GenericSolver,
|
||||
# "mage7": Mage7,
|
||||
"mage8": Mage8,
|
||||
# "mage_fake7": MageFake7,
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -67,5 +67,5 @@ class AboutWindow(PamhyrDialog):
|
||||
label = f"\n - {author}" + label
|
||||
except StopIteration:
|
||||
label = _translate("About", "Contributors: ") + label
|
||||
label = "Copyright © 2023 INRAE\n" + label
|
||||
label = "Copyright © 2023-2024 INRAE\n" + label
|
||||
self.set_label_text("label_copyright", label)
|
||||
@@ -0,0 +1,90 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from Modules import Modules
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QLabel, QPlainTextEdit, QPushButton,
|
||||
QCheckBox,
|
||||
)
|
||||
|
||||
from View.AdditionalFiles.Translate import AddFileTranslate
|
||||
from View.AdditionalFiles.UndoCommand import (
|
||||
SetCommand
|
||||
)
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class EditAddFileWindow(PamhyrWindow):
|
||||
_pamhyr_ui = "AdditionalFile"
|
||||
_pamhyr_name = "Edit additional file"
|
||||
|
||||
def __init__(self, study=None, config=None, add_file=None,
|
||||
trad=None, undo=None, parent=None):
|
||||
|
||||
name = trad[self._pamhyr_name] + " - " + study.name
|
||||
super(EditAddFileWindow, self).__init__(
|
||||
title=name,
|
||||
study=study,
|
||||
config=config,
|
||||
options=[],
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self._add_file = add_file
|
||||
self._hash_data.append(self._add_file)
|
||||
|
||||
self._undo = undo
|
||||
|
||||
self.setup_values()
|
||||
self.setup_connection()
|
||||
|
||||
def setup_values(self):
|
||||
self.set_check_box("checkBox", self._add_file.enabled)
|
||||
self.set_line_edit_text("lineEdit_name", self._add_file.name)
|
||||
self.set_line_edit_text("lineEdit_path", self._add_file.path)
|
||||
self.set_plaintext_edit_text("plainTextEdit", self._add_file.text)
|
||||
|
||||
def setup_connection(self):
|
||||
self.find(QPushButton, "pushButton_cancel")\
|
||||
.clicked.connect(self.close)
|
||||
self.find(QPushButton, "pushButton_ok")\
|
||||
.clicked.connect(self.accept)
|
||||
|
||||
def accept(self):
|
||||
is_enabled = self.get_check_box("checkBox")
|
||||
name = self.get_line_edit_text("lineEdit_name")
|
||||
path = self.get_line_edit_text("lineEdit_path")
|
||||
text = self.get_plaintext_edit_text("plainTextEdit")
|
||||
|
||||
self._undo.push(
|
||||
SetCommand(
|
||||
self._add_file,
|
||||
enabled=is_enabled,
|
||||
name=name,
|
||||
path=path,
|
||||
text=text,
|
||||
)
|
||||
)
|
||||
|
||||
self._propagate_update(key=Modules.ADDITIONAL_FILES)
|
||||
self.close()
|
||||
@@ -0,0 +1,81 @@
|
||||
# List.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from functools import reduce
|
||||
from tools import trace, timer
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
Qt, QVariant,
|
||||
)
|
||||
|
||||
from PyQt5.QtGui import (
|
||||
QColor, QBrush,
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrList import PamhyrListModel
|
||||
from View.AdditionalFiles.UndoCommand import (
|
||||
AddCommand, DelCommand
|
||||
)
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class ListModel(PamhyrListModel):
|
||||
def data(self, index, role):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
file = self._data.files[row]
|
||||
|
||||
if role == Qt.ForegroundRole:
|
||||
color = Qt.gray
|
||||
|
||||
if file.is_enabled():
|
||||
color = QColor("black")
|
||||
else:
|
||||
color = QColor("grey")
|
||||
|
||||
return QBrush(color)
|
||||
|
||||
if role == Qt.ItemDataRole.DisplayRole:
|
||||
text = f"{file.name}: '{file.path}'"
|
||||
|
||||
if not file.is_enabled():
|
||||
text += " (disabled)"
|
||||
|
||||
return text
|
||||
|
||||
return QVariant()
|
||||
|
||||
def add(self, row):
|
||||
self._undo.push(
|
||||
AddCommand(
|
||||
self._data, row
|
||||
)
|
||||
)
|
||||
self.update()
|
||||
|
||||
def delete(self, row):
|
||||
self._undo.push(
|
||||
DelCommand(
|
||||
self._data, row
|
||||
)
|
||||
)
|
||||
self.update()
|
||||
@@ -0,0 +1,35 @@
|
||||
# Translate.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
from View.Translate import MainTranslate
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class AddFileTranslate(MainTranslate):
|
||||
def __init__(self):
|
||||
super(AddFileTranslate, self).__init__()
|
||||
|
||||
self._dict["Additional files"] = _translate(
|
||||
"AdditionalFiles", "Additional files"
|
||||
)
|
||||
|
||||
self._dict["Edit additional file"] = _translate(
|
||||
"AdditionalFiles", "Edit additional file"
|
||||
)
|
||||
@@ -0,0 +1,82 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QMessageBox, QUndoCommand, QUndoStack,
|
||||
)
|
||||
|
||||
|
||||
class SetCommand(QUndoCommand):
|
||||
def __init__(self, add_file, **kwargs):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._add_file = add_file
|
||||
self._new = kwargs
|
||||
self._old = None
|
||||
|
||||
def undo(self):
|
||||
f = self._add_file
|
||||
|
||||
for key in self._old:
|
||||
f[key] = self._old[key]
|
||||
|
||||
def redo(self):
|
||||
f = self._add_file
|
||||
|
||||
if self._old is None:
|
||||
self._old = {}
|
||||
for key in self._new:
|
||||
self._old[key] = f[key]
|
||||
|
||||
for key in self._new:
|
||||
f[key] = self._new[key]
|
||||
|
||||
|
||||
class AddCommand(QUndoCommand):
|
||||
def __init__(self, files, row):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._files = files
|
||||
self._row = row
|
||||
self._new = None
|
||||
|
||||
def undo(self):
|
||||
self._files.delete([self._new])
|
||||
|
||||
def redo(self):
|
||||
if self._new is None:
|
||||
self._new = self._files.new(self._row)
|
||||
else:
|
||||
self._files.insert(self._row, self._new)
|
||||
|
||||
|
||||
class DelCommand(QUndoCommand):
|
||||
def __init__(self, files, row):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._files = files
|
||||
self._row = row
|
||||
self._old = self._files.get(row)
|
||||
|
||||
def undo(self):
|
||||
self._files.insert(self._row, self._old)
|
||||
|
||||
def redo(self):
|
||||
self._files.delete_i([self._row])
|
||||
@@ -0,0 +1,118 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QAction, QListView,
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
|
||||
from View.AdditionalFiles.List import ListModel
|
||||
from View.AdditionalFiles.Translate import AddFileTranslate
|
||||
from View.AdditionalFiles.Edit.Window import EditAddFileWindow
|
||||
|
||||
|
||||
class AddFileListWindow(PamhyrWindow):
|
||||
_pamhyr_ui = "AdditionalFileList"
|
||||
_pamhyr_name = "Additional files"
|
||||
|
||||
def __init__(self, study=None, config=None,
|
||||
parent=None):
|
||||
trad = AddFileTranslate()
|
||||
name = trad[self._pamhyr_name] + " - " + study.name
|
||||
|
||||
super(AddFileListWindow, self).__init__(
|
||||
title=name,
|
||||
study=study,
|
||||
config=config,
|
||||
trad=trad,
|
||||
options=[],
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self.setup_list()
|
||||
self.setup_connections()
|
||||
|
||||
def setup_list(self):
|
||||
lst = self.find(QListView, f"listView")
|
||||
self._list = ListModel(
|
||||
list_view=lst,
|
||||
data=self._study.river.additional_files,
|
||||
undo=self._undo_stack,
|
||||
trad=self._trad,
|
||||
)
|
||||
|
||||
def setup_connections(self):
|
||||
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||
self.find(QAction, "action_delete").triggered.connect(self.delete)
|
||||
self.find(QAction, "action_edit").triggered.connect(self.edit)
|
||||
|
||||
def update(self):
|
||||
self._list.update()
|
||||
|
||||
def selected_rows(self):
|
||||
lst = self.find(QListView, f"listView")
|
||||
return list(map(lambda i: i.row(), lst.selectedIndexes()))
|
||||
|
||||
def add(self):
|
||||
rows = self.selected_rows()
|
||||
if len(rows) > 0:
|
||||
row = rows[0]
|
||||
else:
|
||||
row = 0
|
||||
|
||||
self._list.add(row)
|
||||
|
||||
def delete(self):
|
||||
rows = self.selected_rows()
|
||||
if len(rows) == 0:
|
||||
return
|
||||
|
||||
self._list.delete(rows[0])
|
||||
|
||||
def edit(self):
|
||||
rows = self.selected_rows()
|
||||
|
||||
for row in rows:
|
||||
add_file = self._study.river.additional_files.files[row]
|
||||
|
||||
if self.sub_window_exists(
|
||||
EditAddFileWindow,
|
||||
data=[self._study, self._config, add_file]
|
||||
):
|
||||
continue
|
||||
|
||||
win = EditAddFileWindow(
|
||||
study=self._study,
|
||||
config=self._config,
|
||||
add_file=add_file,
|
||||
trad=self._trad,
|
||||
undo=self._undo_stack,
|
||||
parent=self,
|
||||
)
|
||||
win.show()
|
||||
|
||||
def _undo(self):
|
||||
self._undo_stack.undo()
|
||||
self.update()
|
||||
|
||||
def _redo(self):
|
||||
self._undo_stack.redo()
|
||||
self.update()
|
||||
@@ -1,5 +1,5 @@
|
||||
# Plot.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -27,8 +27,6 @@ from PyQt5.QtCore import (
|
||||
QCoreApplication
|
||||
)
|
||||
|
||||
from View.BoundaryCondition.Edit.translate import BCETranslate
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
logger = logging.getLogger()
|
||||
@@ -47,99 +45,60 @@ class Plot(PamhyrPlot):
|
||||
)
|
||||
|
||||
self._table_headers = self._trad.get_dict("table_headers")
|
||||
|
||||
header = self.data.header
|
||||
self.label_x = self._table_headers[header[0]]
|
||||
self.label_y = self._table_headers[header[1]]
|
||||
|
||||
self._mode = mode
|
||||
self._isometric_axis = False
|
||||
|
||||
self._auto_relim_update = True
|
||||
self._autoscale_update = True
|
||||
|
||||
def custom_ticks(self):
|
||||
if self.data.header[0] != "time":
|
||||
return
|
||||
|
||||
t0 = datetime.fromtimestamp(0)
|
||||
nb = len(self.data.data)
|
||||
mod = int(nb / 5)
|
||||
mod = mod if mod > 0 else nb
|
||||
|
||||
fx = list(
|
||||
map(
|
||||
lambda x: x[1],
|
||||
filter(
|
||||
lambda x: x[0] % mod == 0,
|
||||
enumerate(self.data.data)
|
||||
)
|
||||
)
|
||||
)
|
||||
xx = list(map(lambda v: v[0], fx))
|
||||
if self._mode == "time":
|
||||
xt = list(
|
||||
map(
|
||||
lambda v: str(
|
||||
datetime.fromtimestamp(v[0]) - t0
|
||||
).split(",")[0]
|
||||
.replace("days", _translate("BoundaryCondition", "days"))
|
||||
.replace("day", _translate("BoundaryCondition", "day")),
|
||||
fx
|
||||
)
|
||||
)
|
||||
else:
|
||||
xt = list(
|
||||
map(
|
||||
lambda v: str(datetime.fromtimestamp(v[0]).date()),
|
||||
fx
|
||||
)
|
||||
)
|
||||
|
||||
self.canvas.axes.set_xticks(ticks=xx, labels=xt, rotation=45)
|
||||
self.set_ticks_time_formater()
|
||||
|
||||
@timer
|
||||
def draw(self):
|
||||
self.canvas.axes.cla()
|
||||
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
self.init_axes()
|
||||
|
||||
if len(self.data) == 0:
|
||||
self._init = False
|
||||
return
|
||||
|
||||
self.draw_data()
|
||||
self.custom_ticks()
|
||||
|
||||
self.idle()
|
||||
self._init = True
|
||||
|
||||
def draw_data(self):
|
||||
# Plot data
|
||||
x = list(map(lambda v: v[0], self.data.data))
|
||||
y = list(map(lambda v: v[1], self.data.data))
|
||||
|
||||
self._line, = self.canvas.axes.plot(
|
||||
x, y,
|
||||
color='r', lw=1.,
|
||||
markersize=5, marker='+',
|
||||
picker=30,
|
||||
color=self.color_plot,
|
||||
**self.plot_default_kargs
|
||||
)
|
||||
|
||||
self.custom_ticks()
|
||||
|
||||
# Plot label
|
||||
header = self.data.header
|
||||
self.canvas.axes.set_xlabel(
|
||||
self._table_headers[header[0]], color='black', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
self._table_headers[header[1]], color='black', fontsize=10
|
||||
)
|
||||
|
||||
self.canvas.axes.autoscale_view(True, True, True)
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
# self.toolbar.update()
|
||||
|
||||
self._init = True
|
||||
|
||||
@timer
|
||||
def update(self, ind=None):
|
||||
if not self._init:
|
||||
self.draw()
|
||||
return
|
||||
|
||||
self.update_data()
|
||||
|
||||
self.update_idle()
|
||||
|
||||
def update_data(self):
|
||||
x = list(map(lambda v: v[0], self.data.data))
|
||||
y = list(map(lambda v: v[1], self.data.data))
|
||||
|
||||
self._line.set_data(x, y)
|
||||
|
||||
self.custom_ticks()
|
||||
|
||||
self.canvas.axes.relim()
|
||||
self.canvas.axes.autoscale()
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
@@ -1,5 +1,5 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -21,7 +21,11 @@ import traceback
|
||||
|
||||
from datetime import date, time, datetime, timedelta
|
||||
|
||||
from tools import trace, timer
|
||||
from tools import (
|
||||
trace, timer,
|
||||
timestamp_to_old_pamhyr_date,
|
||||
old_pamhyr_date_to_timestamp
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
||||
@@ -70,9 +74,7 @@ class TableModel(PamhyrTableModel):
|
||||
value = f"{v:.4f}"
|
||||
elif self._data.header[column] == "time":
|
||||
if self._opt_data == "time":
|
||||
t0 = datetime.fromtimestamp(0)
|
||||
t = datetime.fromtimestamp(v)
|
||||
value = str(t - t0)
|
||||
value = timestamp_to_old_pamhyr_date(int(v))
|
||||
else:
|
||||
value = str(datetime.fromtimestamp(v))
|
||||
else:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -105,12 +105,11 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
||||
trad = BCETranslate()
|
||||
self._long_types = trad.get_dict("long_types")
|
||||
|
||||
name = self._pamhyr_name
|
||||
name = trad[self._pamhyr_name]
|
||||
if self._data is not None:
|
||||
node_name = (self._data.node.name if self._data.node is not None
|
||||
else _translate("BoundaryCondition", "Not associate"))
|
||||
name = (
|
||||
_translate("Edit boundary condition", self._pamhyr_name) +
|
||||
else trad['not_associated'])
|
||||
name += (
|
||||
f" - {study.name} " +
|
||||
f" - {self._data.name} ({self._data.id}) " +
|
||||
f"({self._long_types[self._data.bctype]} - {node_name})"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
|
||||
from View.Tools.PamhyrTranslate import PamhyrTranslate
|
||||
from View.Translate import MainTranslate
|
||||
|
||||
from View.BoundaryCondition.translate import BCTranslate
|
||||
|
||||
@@ -29,12 +29,16 @@ class BCETranslate(BCTranslate):
|
||||
def __init__(self):
|
||||
super(BCETranslate, self).__init__()
|
||||
|
||||
self._dict["Edit Boundary Conditions"] = _translate(
|
||||
"BoundaryCondition", "Edit boundary conditions"
|
||||
)
|
||||
|
||||
self._sub_dict["table_headers"] = {
|
||||
"x": _translate("BoundaryCondition", "X"),
|
||||
"y": _translate("BoundaryCondition", "Y"),
|
||||
"time": _translate("BoundaryCondition", "Time"),
|
||||
"date": _translate("BoundaryCondition", "Date"),
|
||||
"discharge": _translate("BoundaryCondition", "Discharge (m³/s)"),
|
||||
"z": _translate("BoundaryCondition", "Z (m)"),
|
||||
"time": self._dict["time"],
|
||||
"date": self._dict["date"],
|
||||
"discharge": self._dict["unit_discharge"],
|
||||
"z": self._dict["unit_elevation"],
|
||||
"solid": _translate("BoundaryCondition", "Solid (kg/s)"),
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -85,7 +85,7 @@ class ComboBoxDelegate(QItemDelegate):
|
||||
)
|
||||
else:
|
||||
self.editor.addItems(
|
||||
[_translate("BoundaryCondition", "Not associate")] +
|
||||
[self._trad["not_associated"]] +
|
||||
self._data.nodes_names()
|
||||
)
|
||||
|
||||
@@ -145,7 +145,7 @@ class TableModel(PamhyrTableModel):
|
||||
elif self._headers[column] == "node":
|
||||
n = self._lst.get(self._tab, row).node
|
||||
if n is None:
|
||||
return _translate("BoundaryCondition", "Not associate")
|
||||
return self._trad["not_associated"]
|
||||
return n.name
|
||||
|
||||
return QVariant()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
# 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
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
import logging
|
||||
|
||||
from tools import trace, timer
|
||||
from tools import trace, timer, logger_exception
|
||||
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
|
||||
@@ -37,6 +37,7 @@ from PyQt5.QtWidgets import (
|
||||
QFileDialog, QTableView, QAbstractItemView,
|
||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from Model.BoundaryCondition.BoundaryConditionTypes import (
|
||||
@@ -68,13 +69,17 @@ class BoundaryConditionWindow(PamhyrWindow):
|
||||
_pamhyr_name = "Boundary conditions"
|
||||
|
||||
def __init__(self, study=None, config=None, parent=None):
|
||||
name = self._pamhyr_name + " - " + study.name
|
||||
trad = BCTranslate()
|
||||
name = (
|
||||
trad[self._pamhyr_name] +
|
||||
" - " + study.name
|
||||
)
|
||||
|
||||
super(BoundaryConditionWindow, self).__init__(
|
||||
title=name,
|
||||
study=study,
|
||||
config=config,
|
||||
trad=BCTranslate(),
|
||||
trad=trad,
|
||||
parent=parent
|
||||
)
|
||||
|
||||
@@ -166,6 +171,13 @@ class BoundaryConditionWindow(PamhyrWindow):
|
||||
)
|
||||
)
|
||||
|
||||
def set_active_tab(self, tab_id=0):
|
||||
try:
|
||||
tab_widget = self.find(QTabWidget, "tabWidget")
|
||||
tab_widget.setCurrentIndex(tab_id)
|
||||
except Exception as e:
|
||||
logger_exception(e)
|
||||
|
||||
def add(self):
|
||||
tab = self.current_tab()
|
||||
rows = self.index_selected_rows()
|
||||
|
||||
Loaded 100 of 265 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user