mirror of
https://gitlab.com/pamhyr/pamhyr2.git
synced 2026-10-30 03:20:41 +01:00
Compare commits
25
Commits
adists_num
...
adists_new
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ae16ca6ec | ||
|
|
c7406d3bce | ||
|
|
cb8ecc752b | ||
|
|
4c522ae050 | ||
|
|
689d5a7592 | ||
|
|
c118d4fae8 | ||
|
|
1baf2e8dd5 | ||
|
|
1fcdaa8b81 | ||
|
|
71729578dd | ||
|
|
abe7bf969a | ||
|
|
673ae3908c | ||
|
|
1a31c9122e | ||
|
|
c53d7d9c25 | ||
|
|
02f14ffdf1 | ||
|
|
84fd841f86 | ||
|
|
629b856788 | ||
|
|
f3007e2fe2 | ||
|
|
a7a1a4ddd1 | ||
|
|
0719db17ed | ||
|
|
018192714c | ||
|
|
501000fa6b | ||
|
|
75149000db | ||
|
|
3c82148f44 | ||
|
|
7f2ff9d341 | ||
|
|
57be80bcd4 |
No files matched your search
@@ -9,6 +9,8 @@
|
|||||||
*.class
|
*.class
|
||||||
|
|
||||||
tmp
|
tmp
|
||||||
|
mage8
|
||||||
|
adists
|
||||||
|
|
||||||
*.tar
|
*.tar
|
||||||
*.tar.*
|
*.tar.*
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class LateralContributionAdisTS(SQLSubModel):
|
|||||||
self._end_kp = 0.0
|
self._end_kp = 0.0
|
||||||
self._data = []
|
self._data = []
|
||||||
self._header = ["time", "rate"]
|
self._header = ["time", "rate"]
|
||||||
self._types = [float, float]
|
self._types = [self.time_convert, float]
|
||||||
|
|
||||||
LateralContributionAdisTS._id_cnt = max(
|
LateralContributionAdisTS._id_cnt = max(
|
||||||
LateralContributionAdisTS._id_cnt + 1, self.id)
|
LateralContributionAdisTS._id_cnt + 1, self.id)
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# Results.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/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import numpy as np
|
||||||
|
import os, glob
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from Model.Results.River.RiverAdisTS import River
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class Results(object):
|
||||||
|
def __init__(self, study=None, solver=None,
|
||||||
|
repertory="", name="0"):
|
||||||
|
self._study = study
|
||||||
|
self._solver = solver
|
||||||
|
self._repertory = repertory
|
||||||
|
self._name = name
|
||||||
|
|
||||||
|
self._river = River(self._study)
|
||||||
|
|
||||||
|
self._meta_data = {
|
||||||
|
# Keep results creation date
|
||||||
|
"creation_date": datetime.now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
repertory_results = os.path.join(repertory, "resultats")
|
||||||
|
self._pollutants_list = [el.split("/")[-1][0:-4] for el in glob.glob(repertory_results + "/*.bin")]
|
||||||
|
|
||||||
|
self._phys_var_list = ["C", "G", "M", "D", "L", "N", "R"]
|
||||||
|
|
||||||
|
print("*********files names resultats from Results Object: ", self._pollutants_list)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def date(self):
|
||||||
|
date = self._meta_data["creation_date"]
|
||||||
|
return f"{date.isoformat(sep=' ')}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def river(self):
|
||||||
|
return self._river
|
||||||
|
|
||||||
|
@property
|
||||||
|
def study(self):
|
||||||
|
return self._study
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pollutants_list(self):
|
||||||
|
return self._pollutants_list
|
||||||
|
|
||||||
|
@property
|
||||||
|
def phys_var_list(self):
|
||||||
|
return self._phys_var_list
|
||||||
|
|
||||||
|
def set(self, key, value):
|
||||||
|
self._meta_data[key] = value
|
||||||
|
|
||||||
|
def get(self, key):
|
||||||
|
return self._meta_data[key]
|
||||||
|
|
||||||
|
def reload(self):
|
||||||
|
return self._solver.results(
|
||||||
|
self._study,
|
||||||
|
self._repertory,
|
||||||
|
qlog=None,
|
||||||
|
)
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
# River.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/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class Profile(object):
|
||||||
|
def __init__(self, profile, study):
|
||||||
|
self._study = study
|
||||||
|
self._profile = profile # Source profile in the study
|
||||||
|
self._data = {} # Dict of dict {<ts>: {<key>: <value>, ...}, ...}
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._profile.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def kp(self):
|
||||||
|
return self._profile.kp
|
||||||
|
|
||||||
|
@property
|
||||||
|
def geometry(self):
|
||||||
|
return self._profile
|
||||||
|
|
||||||
|
def set(self, timestamp, key, data):
|
||||||
|
if timestamp not in self._data:
|
||||||
|
self._data[timestamp] = {}
|
||||||
|
|
||||||
|
self._data[timestamp][key] = data
|
||||||
|
|
||||||
|
def get_ts(self, timestamp):
|
||||||
|
return self._data[timestamp]
|
||||||
|
|
||||||
|
def get_key(self, key):
|
||||||
|
return list(
|
||||||
|
map(lambda ts: self._data[ts][key], self._data)
|
||||||
|
)
|
||||||
|
|
||||||
|
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):
|
||||||
|
self._study = study
|
||||||
|
self._reach = reach # Source reach in the study
|
||||||
|
self._profiles = list(
|
||||||
|
map(
|
||||||
|
lambda p: Profile(p, self._study),
|
||||||
|
reach.profiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._profiles)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._reach.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def geometry(self):
|
||||||
|
return self._reach
|
||||||
|
|
||||||
|
@property
|
||||||
|
def profiles(self):
|
||||||
|
return self._profiles.copy()
|
||||||
|
|
||||||
|
def profile(self, id):
|
||||||
|
return self._profiles[id]
|
||||||
|
|
||||||
|
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):
|
||||||
|
self._study = study
|
||||||
|
|
||||||
|
# Dict with timestamps as key
|
||||||
|
self._reachs = []
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._reachs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reachs(self):
|
||||||
|
return self._reachs.copy()
|
||||||
|
|
||||||
|
def reach(self, id):
|
||||||
|
return self._reachs[id]
|
||||||
|
|
||||||
|
def has_reach(self, id):
|
||||||
|
return 0 <= id < len(self._reachs)
|
||||||
|
|
||||||
|
def add(self, reach_id):
|
||||||
|
reachs = self._study.river.enable_edges()
|
||||||
|
|
||||||
|
new = Reach(reachs[reach_id].reach, self._study)
|
||||||
|
|
||||||
|
self._reachs.append(new)
|
||||||
|
return new
|
||||||
|
|
||||||
|
def get_reach_by_geometry(self, geometry_reach):
|
||||||
|
return next(
|
||||||
|
filter(
|
||||||
|
lambda r: r.geometry is geometry_reach,
|
||||||
|
self._reachs
|
||||||
|
)
|
||||||
|
)
|
||||||
+252
-7
@@ -16,10 +16,14 @@
|
|||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import os
|
import os, glob
|
||||||
import logging
|
import logging
|
||||||
|
from http.cookiejar import reach
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
|
||||||
from tools import (
|
from tools import (
|
||||||
trace, timer, logger_exception,
|
trace, timer, logger_exception,
|
||||||
timestamp_to_old_pamhyr_date,
|
timestamp_to_old_pamhyr_date,
|
||||||
@@ -29,7 +33,7 @@ from tools import (
|
|||||||
|
|
||||||
from Solver.CommandLine import CommandLineSolver
|
from Solver.CommandLine import CommandLineSolver
|
||||||
|
|
||||||
from Model.Results.Results import Results
|
from Model.Results.ResultsAdisTS import Results
|
||||||
from Model.Results.River.River import River, Reach, Profile
|
from Model.Results.River.River import River, Reach, Profile
|
||||||
|
|
||||||
from Checker.Adists import (
|
from Checker.Adists import (
|
||||||
@@ -110,7 +114,7 @@ class AdisTS(CommandLineSolver):
|
|||||||
for line in lines:
|
for line in lines:
|
||||||
rep_file.write(line.line)
|
rep_file.write(line.line)
|
||||||
|
|
||||||
def _export_REP(self, study, repertory, files, qlog, name="0"):
|
def _export_REP(self, study, repertory, mage_rep, files, qlog, name="0"):
|
||||||
|
|
||||||
if qlog is not None:
|
if qlog is not None:
|
||||||
qlog.put("Export REP file")
|
qlog.put("Export REP file")
|
||||||
@@ -122,8 +126,8 @@ class AdisTS(CommandLineSolver):
|
|||||||
), "w+"
|
), "w+"
|
||||||
) as f:
|
) as f:
|
||||||
|
|
||||||
f.write(f"NET ../default-mage/{name}.NET\n")
|
f.write(f"NET ../{mage_rep}/{name}.NET\n")
|
||||||
f.write(f"REP ../default-mage/{name}.REP\n")
|
f.write(f"REP ../{mage_rep}/{name}.REP\n")
|
||||||
|
|
||||||
for file in files:
|
for file in files:
|
||||||
EXT = file.split('.')[1]
|
EXT = file.split('.')[1]
|
||||||
@@ -131,6 +135,12 @@ class AdisTS(CommandLineSolver):
|
|||||||
|
|
||||||
self._export_REP_additional_lines(study, f)
|
self._export_REP_additional_lines(study, f)
|
||||||
|
|
||||||
|
path_mage_net = os.path.join(os.path.abspath(os.path.join(repertory, os.pardir)), f"{mage_rep}/net")
|
||||||
|
path_adists_net = os.path.join(repertory, "net")
|
||||||
|
|
||||||
|
if os.path.exists(path_mage_net):
|
||||||
|
shutil.copytree(path_mage_net, path_adists_net, dirs_exist_ok=True)
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def export(self, study, repertory, qlog=None):
|
def export(self, study, repertory, qlog=None):
|
||||||
self._study = study
|
self._study = study
|
||||||
@@ -449,6 +459,241 @@ class AdisTSlc(AdisTS):
|
|||||||
|
|
||||||
f.write(f"output = {id_reach} {kp} {title}\n")
|
f.write(f"output = {id_reach} {kp} {title}\n")
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def read_bin(self, study, repertory, results, qlog=None, name="0"):
|
||||||
|
repertory_results = os.path.join(repertory, "resultats")
|
||||||
|
|
||||||
|
files_bin_names = [el.split("/")[-1] for el in glob.glob(repertory_results+"/*.bin")]
|
||||||
|
print("files names resultats: ", files_bin_names)
|
||||||
|
|
||||||
|
ifilename = os.path.join(repertory_results, files_bin_names[0])
|
||||||
|
|
||||||
|
logger.info(f"read_bin: Start reading '{ifilename}' ...")
|
||||||
|
|
||||||
|
print("reading ", ifilename)
|
||||||
|
with open(ifilename, 'rb') as f:
|
||||||
|
# header
|
||||||
|
# first line
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=3)
|
||||||
|
ibmax = data[0] # number of reaches
|
||||||
|
ismax = data[1] # total number of cross sections
|
||||||
|
kbl = data[2] * -1 # block size for .BIN header
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# second line
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
ibu = np.fromfile(f, dtype=np.int32, count=ibmax)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# third line
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=2 * ibmax)
|
||||||
|
is1 = np.zeros(ibmax, dtype=np.int32)
|
||||||
|
is2 = np.zeros(ibmax, dtype=np.int32)
|
||||||
|
print("nombre de biefs : ", ibmax)
|
||||||
|
|
||||||
|
logger.debug(f"read_bin: nb_reach = {ibmax}")
|
||||||
|
logger.debug(f"read_bin: nb_profile = {ismax}")
|
||||||
|
|
||||||
|
results.set("nb_reach", f"{ibmax}")
|
||||||
|
results.set("nb_profile", f"{ismax}")
|
||||||
|
|
||||||
|
reachs = []
|
||||||
|
iprofiles = {}
|
||||||
|
reach_offset = {}
|
||||||
|
|
||||||
|
for i in range(ibmax):
|
||||||
|
# Add results reach to reach list
|
||||||
|
r = results.river.add(i)
|
||||||
|
reachs.append(r)
|
||||||
|
|
||||||
|
is1[i] = data[2 * i] - 1 # first section of reach i (FORTRAN numbering)
|
||||||
|
is2[i] = data[2 * i + 1] - 1 # last section of reach i (FORTRAN numbering)
|
||||||
|
|
||||||
|
key = (is1[i], is2[i])
|
||||||
|
iprofiles[key] = r
|
||||||
|
|
||||||
|
reach_offset[r] = is1[i]
|
||||||
|
|
||||||
|
logger.debug(f"read_bin: iprofiles = {iprofiles}")
|
||||||
|
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# fourth line
|
||||||
|
pk = np.zeros(ismax, dtype=np.float32)
|
||||||
|
for k in range(0, ismax, kbl):
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
pk[k:min(k + kbl, ismax)] = np.fromfile(f, dtype=np.float32, count=min(k + kbl, ismax) - k)
|
||||||
|
print("pk : ", pk)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
|
||||||
|
# fifth line (useless)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
zmin_OLD = np.fromfile(f, dtype=np.float32, count=1)[0]
|
||||||
|
print("zmin_OLD : ", zmin_OLD)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# sixth line
|
||||||
|
zf = np.zeros(ismax, dtype=np.float32)
|
||||||
|
z = np.zeros(ismax * 3, dtype=np.float32)
|
||||||
|
for k in range(0, ismax, kbl):
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
z[3 * k:3 * min(k + kbl, ismax)] = np.fromfile(f, dtype=np.float32,
|
||||||
|
count=3 * (min(k + kbl, ismax) - k))
|
||||||
|
# z[i*3+1] and z[i*3+2] are useless
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
zf = [z[i * 3] for i in range(ismax)]
|
||||||
|
print("zf : ", zf)
|
||||||
|
# seventh line (useless)
|
||||||
|
for k in range(0, ismax, kbl):
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
zero = np.fromfile(f, dtype=np.int32, count=ismax)
|
||||||
|
print("zero : ", zero)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# end header
|
||||||
|
|
||||||
|
def ip_to_r(i): return iprofiles[
|
||||||
|
next(
|
||||||
|
filter(
|
||||||
|
lambda k: k[0] <= i <= k[1],
|
||||||
|
iprofiles
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
def ip_to_ri(r, i): return i - reach_offset[r]
|
||||||
|
|
||||||
|
path_files = map(lambda file: os.path.join(repertory_results, file), files_bin_names)
|
||||||
|
|
||||||
|
data_tmp = {}
|
||||||
|
|
||||||
|
for file_bin in path_files:
|
||||||
|
key_pol = file_bin.split("/")[-1][0:-4]
|
||||||
|
data_tmp[key_pol] = {}
|
||||||
|
with open(file_bin, 'rb') as f:
|
||||||
|
# header
|
||||||
|
# first line
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=3)
|
||||||
|
ibmax = data[0] # number of reaches
|
||||||
|
ismax = data[1] # total number of cross sections
|
||||||
|
kbl = data[2] * -1 # block size for .BIN header
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# second line
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
ibu = np.fromfile(f, dtype=np.int32, count=ibmax)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# third line
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=2 * ibmax)
|
||||||
|
is1 = np.zeros(ibmax, dtype=np.int32)
|
||||||
|
is2 = np.zeros(ibmax, dtype=np.int32)
|
||||||
|
for i in range(ibmax):
|
||||||
|
is1[i] = data[2 * i] # first section of reach i (FORTRAN numbering)
|
||||||
|
is2[i] = data[2 * i + 1] # last section of reach i (FORTRAN numbering)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# fourth line
|
||||||
|
pk = np.zeros(ismax, dtype=np.float32)
|
||||||
|
for k in range(0, ismax, kbl):
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
pk[k:min(k + kbl, ismax)] = np.fromfile(f, dtype=np.float32, count=min(k + kbl, ismax) - k)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# fifth line (useless)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
zmin_OLD = np.fromfile(f, dtype=np.float32, count=1)[0]
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# sixth line
|
||||||
|
zf = np.zeros(ismax, dtype=np.float32)
|
||||||
|
z = np.zeros(ismax * 3, dtype=np.float32)
|
||||||
|
for k in range(0, ismax, kbl):
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
z[3 * k:3 * min(k + kbl, ismax)] = np.fromfile(f, dtype=np.float32,
|
||||||
|
count=3 * (min(k + kbl, ismax) - k))
|
||||||
|
# z[i*3+1] and z[i*3+2] are useless
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
zf = [z[i * 3] for i in range(ismax)]
|
||||||
|
# seventh line (useless)
|
||||||
|
for k in range(0, ismax, kbl):
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
zero = np.fromfile(f, dtype=np.int32, count=ismax)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
# end header
|
||||||
|
# data
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
while data.size > 0:
|
||||||
|
ismax = np.fromfile(f, dtype=np.int32, count=1)[0]
|
||||||
|
t = np.fromfile(f, dtype=np.float64, count=1)[0]
|
||||||
|
if not t in data_tmp[key_pol]:
|
||||||
|
data_tmp[key_pol][t] = {}
|
||||||
|
c = np.fromfile(f, dtype=np.byte, count=1)
|
||||||
|
# possible values :
|
||||||
|
# sediment : C, G, M, D, L, N, R
|
||||||
|
# polutant : C, G, M, D
|
||||||
|
phys_var = bytearray(c).decode()
|
||||||
|
data_tmp[key_pol][t][phys_var] = {}
|
||||||
|
real_data = np.fromfile(f, dtype=np.float32, count=ismax)
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (end)
|
||||||
|
data_tmp[key_pol][t][phys_var] = real_data
|
||||||
|
data = np.fromfile(f, dtype=np.int32, count=1) # line length (bytes) (start)
|
||||||
|
# end data
|
||||||
|
|
||||||
|
###print("dta tmp AAA")
|
||||||
|
###print("-----------")
|
||||||
|
###print(data_tmp["AAA-silt"])
|
||||||
|
|
||||||
|
pollutants_keys = list(data_tmp.keys())
|
||||||
|
timestamps_keys = list(data_tmp[pollutants_keys[0]].keys())
|
||||||
|
phys_data_names = list(data_tmp[pollutants_keys[0]][timestamps_keys[0]].keys())
|
||||||
|
|
||||||
|
###print("pol keys: ", pollutants_keys)
|
||||||
|
###print("t keys: ", timestamps_keys)
|
||||||
|
###print("phys var: ", phys_data_names)
|
||||||
|
#print("set timestamps keys: ", set(timestamps_keys))
|
||||||
|
#print("isma")
|
||||||
|
###print("iprofiles: ", iprofiles)
|
||||||
|
|
||||||
|
pi_tmp = []
|
||||||
|
reach_tmp = []
|
||||||
|
|
||||||
|
for i in range(ismax-1):
|
||||||
|
#print("first i: ", i)
|
||||||
|
reach = ip_to_r(i)
|
||||||
|
reach_tmp.append(reach)
|
||||||
|
#print("reach i:", reach)
|
||||||
|
#print("second i: ", i)
|
||||||
|
p_i = ip_to_ri(reach, i)
|
||||||
|
pi_tmp.append(p_i)
|
||||||
|
|
||||||
|
for t_data in timestamps_keys:
|
||||||
|
pol_view = []
|
||||||
|
for pol in pollutants_keys:
|
||||||
|
#print("pol results: ", type(list(data_tmp[pol][t_data].values())))
|
||||||
|
pol_view.append(tuple( list(map(lambda data_el: data_el[p_i], list(data_tmp[pol][t_data].values()))) ))
|
||||||
|
|
||||||
|
reach.set(p_i, t_data, "pols", pol_view)
|
||||||
|
|
||||||
|
###print("pi_tmp: ", pi_tmp)
|
||||||
|
###print("pol view: ", pol_view)
|
||||||
|
###print("reach from i: ", reach_tmp)
|
||||||
|
#print("pol view: ", pol_view)
|
||||||
|
#print("results: ", results)
|
||||||
|
results.set("timestamps", set(timestamps_keys))
|
||||||
|
#print("------------------------set timestamps results meta data: ", set(timestamps_keys))
|
||||||
|
|
||||||
|
###print("debug profiles for draw:")
|
||||||
|
###print("------------------------")
|
||||||
|
###print(data_tmp["AAA-silt"][0.0]["C"][0])
|
||||||
|
###print(data_tmp["AAA-silt"][600.0]["C"][0])
|
||||||
|
###print(data_tmp["AAA-silt"][1205.7208829578194]["C"][0])
|
||||||
|
###print("========================")
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def results(self, study, repertory, qlog=None, name=None):
|
||||||
|
self._study = study
|
||||||
|
if name is None:
|
||||||
|
name = study.name.replace(" ", "_")
|
||||||
|
|
||||||
|
results = super(AdisTSlc, self).results(study, repertory, qlog, name=name)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
def export_func_dict(self):
|
def export_func_dict(self):
|
||||||
return [
|
return [
|
||||||
self._export_NUM,
|
self._export_NUM,
|
||||||
@@ -458,7 +703,7 @@ class AdisTSlc(AdisTS):
|
|||||||
]
|
]
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def export(self, study, repertory, qlog=None, name="0"):
|
def export(self, study, repertory, mage_rep, qlog=None, name="0"):
|
||||||
print("cmd solver adistslc : ", self._cmd_solver)
|
print("cmd solver adistslc : ", self._cmd_solver)
|
||||||
self._study = study
|
self._study = study
|
||||||
name = study.name.replace(" ", "_")
|
name = study.name.replace(" ", "_")
|
||||||
@@ -471,7 +716,7 @@ class AdisTSlc(AdisTS):
|
|||||||
files = files + func(study, repertory, qlog, name=name)
|
files = files + func(study, repertory, qlog, name=name)
|
||||||
|
|
||||||
self.export_additional_files(study, repertory, qlog, name=name)
|
self.export_additional_files(study, repertory, qlog, name=name)
|
||||||
self._export_REP(study, repertory, files, qlog, name=name)
|
self._export_REP(study, repertory, mage_rep, files, qlog, name=name)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -196,17 +196,11 @@ class CommandLineSolver(AbstractSolver):
|
|||||||
The executable and list of arguments
|
The executable and list of arguments
|
||||||
"""
|
"""
|
||||||
cmd = cmd.replace("@install_dir", self._install_dir())
|
cmd = cmd.replace("@install_dir", self._install_dir())
|
||||||
print("format command installDir :", self._install_dir())
|
|
||||||
cmd = cmd.replace("@path", "\"" + path + "\"")
|
cmd = cmd.replace("@path", "\"" + path + "\"")
|
||||||
print("format command path :", path)
|
|
||||||
cmd = cmd.replace("@input", self.input_param().replace(" ", "_"))
|
cmd = cmd.replace("@input", self.input_param().replace(" ", "_"))
|
||||||
print("format command input :", self.input_param().replace(" ", "_"))
|
|
||||||
cmd = cmd.replace("@output", self.output_param())
|
cmd = cmd.replace("@output", self.output_param())
|
||||||
print("format command output :", self.output_param())
|
|
||||||
cmd = cmd.replace("@dir", self._process.workingDirectory())
|
cmd = cmd.replace("@dir", self._process.workingDirectory())
|
||||||
print("format command dir :", self._process.workingDirectory())
|
|
||||||
cmd = cmd.replace("@args", " ".join(self.cmd_args(study)))
|
cmd = cmd.replace("@args", " ".join(self.cmd_args(study)))
|
||||||
print("format command args :", " ".join(self.cmd_args(study)))
|
|
||||||
|
|
||||||
logger.debug(f"! {cmd}")
|
logger.debug(f"! {cmd}")
|
||||||
|
|
||||||
@@ -243,11 +237,7 @@ class CommandLineSolver(AbstractSolver):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
cmd = self._cmd_solver
|
cmd = self._cmd_solver
|
||||||
print("run solver commandline cmd : ", cmd)
|
|
||||||
print("path solver : ", self._path_solver)
|
|
||||||
exe, args = self._format_command(study, cmd, self._path_solver)
|
exe, args = self._format_command(study, cmd, self._path_solver)
|
||||||
print("parsed cmd solver exe : ", exe)
|
|
||||||
print("parsed cmd solver args : ", args)
|
|
||||||
|
|
||||||
if not os.path.exists(exe):
|
if not os.path.exists(exe):
|
||||||
error = f"[ERROR] Path {exe} do not exists"
|
error = f"[ERROR] Path {exe} do not exists"
|
||||||
@@ -318,11 +308,6 @@ class CommandLineSolver(AbstractSolver):
|
|||||||
self._output.put(res)
|
self._output.put(res)
|
||||||
|
|
||||||
def run(self, study, process=None, output_queue=None):
|
def run(self, study, process=None, output_queue=None):
|
||||||
print("Run debug")
|
|
||||||
print("---------")
|
|
||||||
print("cmd input : ", self._cmd_input)
|
|
||||||
print("cmd solver : ", self._cmd_solver)
|
|
||||||
print("cmd output : ", self._cmd_output)
|
|
||||||
self._study = study
|
self._study = study
|
||||||
|
|
||||||
# Replace old values if needed
|
# Replace old values if needed
|
||||||
|
|||||||
@@ -980,6 +980,7 @@ class Mage8(Mage):
|
|||||||
|
|
||||||
# Add profile id correspondance to reach
|
# Add profile id correspondance to reach
|
||||||
key = (i1, i2)
|
key = (i1, i2)
|
||||||
|
print("mage keys reachs: ", key)
|
||||||
iprofiles[key] = r
|
iprofiles[key] = r
|
||||||
|
|
||||||
# Profile ID offset
|
# Profile ID offset
|
||||||
@@ -1012,6 +1013,8 @@ class Mage8(Mage):
|
|||||||
]
|
]
|
||||||
def ip_to_ri(r, i): return i - reach_offset[r]
|
def ip_to_ri(r, i): return i - reach_offset[r]
|
||||||
|
|
||||||
|
print("mage iprofiles: ", iprofiles)
|
||||||
|
|
||||||
ts = set()
|
ts = set()
|
||||||
end = False
|
end = False
|
||||||
while not end:
|
while not end:
|
||||||
@@ -1047,6 +1050,7 @@ class Mage8(Mage):
|
|||||||
|
|
||||||
logger.debug(reachs[0].profiles[0]._data)
|
logger.debug(reachs[0].profiles[0]._data)
|
||||||
results.set("timestamps", ts)
|
results.set("timestamps", ts)
|
||||||
|
print("set timestamps mage: ", ts)
|
||||||
logger.info(f"read_bin: ... end with {len(ts)} timestamp read")
|
logger.info(f"read_bin: ... end with {len(ts)} timestamp read")
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
|
|||||||
@@ -0,0 +1,200 @@
|
|||||||
|
# WindowAdisTS.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, QRect, QThread,
|
||||||
|
pyqtSlot, pyqtSignal,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
|
QProgressBar, QLabel,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.CheckList.Table import TableModel
|
||||||
|
from View.CheckList.Worker import Worker
|
||||||
|
from View.CheckList.Translate import CheckListTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class CheckListWindowAdisTS(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "CheckList"
|
||||||
|
_pamhyr_name = "Check list"
|
||||||
|
|
||||||
|
signalStatus = pyqtSignal(str)
|
||||||
|
|
||||||
|
def __init__(self, autorun: bool = True,
|
||||||
|
study=None, config=None,
|
||||||
|
solver=None, parent=None, mage_rep=None):
|
||||||
|
trad = CheckListTranslate()
|
||||||
|
|
||||||
|
self._autorun = autorun
|
||||||
|
self._solver = solver
|
||||||
|
self._mage_rep = mage_rep
|
||||||
|
|
||||||
|
name = trad[self._pamhyr_name] + " - " + study.name
|
||||||
|
|
||||||
|
super(CheckListWindowAdisTS, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
options=[],
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add solver to hash computation data
|
||||||
|
self._hash_data.append(self._solver)
|
||||||
|
|
||||||
|
self._checker_list = (
|
||||||
|
self._study.checkers() +
|
||||||
|
self._solver.checkers()
|
||||||
|
)
|
||||||
|
|
||||||
|
self.setup_table()
|
||||||
|
self.setup_progress_bar()
|
||||||
|
self.setup_connections()
|
||||||
|
self.setup_thread()
|
||||||
|
self.setup_statusbar()
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
table = self.find(QTableView, f"tableView")
|
||||||
|
self._table = TableModel(
|
||||||
|
table_view=table,
|
||||||
|
table_headers=self._trad.get_dict("table_headers"),
|
||||||
|
data=self._checker_list,
|
||||||
|
)
|
||||||
|
|
||||||
|
def setup_progress_bar(self):
|
||||||
|
self._progress = self.find(QProgressBar, f"progressBar")
|
||||||
|
self._p = 0 # Progress current step
|
||||||
|
|
||||||
|
self._progress.setRange(0, len(self._checker_list))
|
||||||
|
self._progress.setValue(self._p)
|
||||||
|
|
||||||
|
def setup_connections(self):
|
||||||
|
self.find(QPushButton, "pushButton_ok").clicked.connect(self.accept)
|
||||||
|
self.find(QPushButton, "pushButton_retry").clicked.connect(self.retry)
|
||||||
|
self.find(QPushButton, "pushButton_cancel")\
|
||||||
|
.clicked.connect(self.reject)
|
||||||
|
|
||||||
|
def setup_thread(self):
|
||||||
|
self._worker = Worker(self._study, self._checker_list)
|
||||||
|
self._worker_thread = QThread()
|
||||||
|
self._worker.moveToThread(self._worker_thread)
|
||||||
|
|
||||||
|
# Connect any worker signals
|
||||||
|
self._worker.signalStatus.connect(self.update)
|
||||||
|
self._worker_thread.started.connect(self._worker.process)
|
||||||
|
|
||||||
|
self._worker_thread.start()
|
||||||
|
|
||||||
|
def retry(self):
|
||||||
|
self._worker_thread.terminate()
|
||||||
|
self._worker_thread.wait()
|
||||||
|
|
||||||
|
self.find(QPushButton, "pushButton_retry").setEnabled(False)
|
||||||
|
self.find(QPushButton, "pushButton_ok").setEnabled(False)
|
||||||
|
|
||||||
|
self.setup_thread()
|
||||||
|
|
||||||
|
def _compute_status(self):
|
||||||
|
ok = len(list(filter(lambda c: c.is_ok(), self._checker_list)))
|
||||||
|
warning = len(
|
||||||
|
list(filter(lambda c: c.is_warning(), self._checker_list)))
|
||||||
|
error = len(list(filter(lambda c: c.is_error(), self._checker_list)))
|
||||||
|
|
||||||
|
return ok, warning, error
|
||||||
|
|
||||||
|
def _compute_status_label(self):
|
||||||
|
ok, warning, error = self._compute_status()
|
||||||
|
return (f"<font color=\"Green\">Ok: {ok} </font> |" +
|
||||||
|
f"<font color=\"Orange\">Warning: {warning} </font> |" +
|
||||||
|
f"<font color=\"Red\">Error: {error}</font>")
|
||||||
|
|
||||||
|
def setup_statusbar(self):
|
||||||
|
txt = self._compute_status_label()
|
||||||
|
self._status_label = QLabel(txt)
|
||||||
|
self.statusbar.addPermanentWidget(self._status_label)
|
||||||
|
|
||||||
|
def update_statusbar(self):
|
||||||
|
txt = self._compute_status_label()
|
||||||
|
self._status_label.setText(txt)
|
||||||
|
|
||||||
|
def progress(self):
|
||||||
|
self._p += 1
|
||||||
|
self._progress.setValue(self._p)
|
||||||
|
self._table.update()
|
||||||
|
|
||||||
|
def start_compute(self):
|
||||||
|
self._p = 0
|
||||||
|
self._progress.setValue(self._p)
|
||||||
|
|
||||||
|
def info_compute(self, str):
|
||||||
|
self.statusbar.showMessage(str, 3000)
|
||||||
|
|
||||||
|
def end_compute(self):
|
||||||
|
self._table.layoutChanged.emit()
|
||||||
|
self.find(QPushButton, "pushButton_retry").setEnabled(True)
|
||||||
|
|
||||||
|
errors = any(filter(lambda c: c.is_error(), self._checker_list))
|
||||||
|
if not errors:
|
||||||
|
self.find(QPushButton, "pushButton_ok").setEnabled(True)
|
||||||
|
if self._autorun:
|
||||||
|
self._parent.solver_log_adists(self._solver, self._mage_rep)
|
||||||
|
self.end()
|
||||||
|
|
||||||
|
self.update_statusbar()
|
||||||
|
|
||||||
|
def update(self, key: str):
|
||||||
|
if key == "start":
|
||||||
|
self.start_compute()
|
||||||
|
self.info_compute("Starting ...")
|
||||||
|
elif key == "end":
|
||||||
|
self.info_compute("Finish")
|
||||||
|
self.end_compute()
|
||||||
|
elif key == "progress":
|
||||||
|
self.progress()
|
||||||
|
else:
|
||||||
|
self.info_compute(key)
|
||||||
|
|
||||||
|
self.update_statusbar()
|
||||||
|
|
||||||
|
def end(self):
|
||||||
|
# self._worker.join()b
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def reject(self):
|
||||||
|
self.end()
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
self._parent.solver_log_adists(self._solver, self._mage_rep)
|
||||||
|
# self.end()
|
||||||
@@ -23,7 +23,8 @@ from datetime import date, time, datetime, timedelta
|
|||||||
from tools import (
|
from tools import (
|
||||||
trace, timer,
|
trace, timer,
|
||||||
timestamp_to_old_pamhyr_date,
|
timestamp_to_old_pamhyr_date,
|
||||||
old_pamhyr_date_to_timestamp
|
old_pamhyr_date_to_timestamp,
|
||||||
|
timestamp_to_old_pamhyr_date_adists
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
@@ -69,7 +70,7 @@ class TableModel(PamhyrTableModel):
|
|||||||
value = f"{v:.4f}"
|
value = f"{v:.4f}"
|
||||||
elif self._data.header[column] == "time":
|
elif self._data.header[column] == "time":
|
||||||
if self._opt_data == "time":
|
if self._opt_data == "time":
|
||||||
value = timestamp_to_old_pamhyr_date(int(v))
|
value = timestamp_to_old_pamhyr_date_adists(int(v))
|
||||||
else:
|
else:
|
||||||
value = str(datetime.fromtimestamp(v))
|
value = str(datetime.fromtimestamp(v))
|
||||||
else:
|
else:
|
||||||
|
|||||||
+109
-4
@@ -24,6 +24,8 @@ import subprocess
|
|||||||
from queue import Queue
|
from queue import Queue
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from platformdirs import user_cache_dir
|
from platformdirs import user_cache_dir
|
||||||
|
|
||||||
|
from Solver.AdisTS import AdisTS
|
||||||
from tools import logger_exception
|
from tools import logger_exception
|
||||||
|
|
||||||
from PyQt5 import QtGui
|
from PyQt5 import QtGui
|
||||||
@@ -71,8 +73,11 @@ from View.AdditionalFiles.Window import AddFileListWindow
|
|||||||
from View.REPLines.Window import REPLineListWindow
|
from View.REPLines.Window import REPLineListWindow
|
||||||
from View.SolverParameters.Window import SolverParametersWindow
|
from View.SolverParameters.Window import SolverParametersWindow
|
||||||
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
|
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
|
||||||
|
from View.RunSolver.WindowAdisTS import SelectSolverWindowAdisTS, SolverLogWindowAdisTS
|
||||||
from View.CheckList.Window import CheckListWindow
|
from View.CheckList.Window import CheckListWindow
|
||||||
|
from View.CheckList.WindowAdisTS import CheckListWindowAdisTS
|
||||||
from View.Results.Window import ResultsWindow
|
from View.Results.Window import ResultsWindow
|
||||||
|
from View.Results.WindowAdisTS import ResultsWindowAdisTS
|
||||||
from View.Results.ReadingResultsDialog import ReadingResultsDialog
|
from View.Results.ReadingResultsDialog import ReadingResultsDialog
|
||||||
from View.Debug.Window import ReplWindow
|
from View.Debug.Window import ReplWindow
|
||||||
from View.OutputKpAdisTS.Window import OutputKpAdisTSWindow
|
from View.OutputKpAdisTS.Window import OutputKpAdisTSWindow
|
||||||
@@ -241,7 +246,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
"action_menu_dif": self.open_dif,
|
"action_menu_dif": self.open_dif,
|
||||||
"action_menu_d90": self.open_d90,
|
"action_menu_d90": self.open_d90,
|
||||||
"action_menu_pollutants": self.open_pollutants,
|
"action_menu_pollutants": self.open_pollutants,
|
||||||
"action_menu_run_adists":self.run_solver_adists,
|
"action_menu_run_adists":self.select_run_solver_adists,
|
||||||
"action_menu_output_kp": self.open_output_kp_adists,
|
"action_menu_output_kp": self.open_output_kp_adists,
|
||||||
"action_menu_config": self.open_configure,
|
"action_menu_config": self.open_configure,
|
||||||
"action_menu_new": self.open_new_study,
|
"action_menu_new": self.open_new_study,
|
||||||
@@ -1257,13 +1262,46 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
if run.exec():
|
if run.exec():
|
||||||
self.run_solver(run.solver)
|
self.run_solver(run.solver)
|
||||||
|
|
||||||
def run_solver_adists(self):
|
def select_run_solver_adists(self):
|
||||||
if self._study is None:
|
if self._study is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
#solver = next(filter(lambda x: x._type == "adistslc", self.conf.solvers))
|
#solver = next(filter(lambda x: x._type == "adistslc", self.conf.solvers))
|
||||||
solver = next(filter(lambda x: x.name == "AdisTS-LC", self.conf.solvers))
|
#solver = next(filter(lambda x: x.name == "AdisTS-LC", self.conf.solvers))
|
||||||
self.run_solver(solver)
|
#print(solver._type)
|
||||||
|
#self.run_solver(solver)
|
||||||
|
|
||||||
|
run = SelectSolverWindowAdisTS(
|
||||||
|
study=self._study,
|
||||||
|
config=self.conf,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
if run.exec():
|
||||||
|
self.run_solver_adists(run.solver, run.mage_rep)
|
||||||
|
|
||||||
|
def run_solver_adists(self, solver, mage_rep):
|
||||||
|
if self._study is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.sub_window_exists(
|
||||||
|
CheckListWindowAdisTS,
|
||||||
|
data=[
|
||||||
|
self._study,
|
||||||
|
self.conf,
|
||||||
|
solver,
|
||||||
|
mage_rep
|
||||||
|
]
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
check = CheckListWindowAdisTS(
|
||||||
|
study=self._study,
|
||||||
|
config=self.conf,
|
||||||
|
solver=solver,
|
||||||
|
parent=self,
|
||||||
|
mage_rep=mage_rep,
|
||||||
|
)
|
||||||
|
check.show()
|
||||||
|
|
||||||
def run_solver(self, solver):
|
def run_solver(self, solver):
|
||||||
if self._study is None:
|
if self._study is None:
|
||||||
@@ -1287,6 +1325,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
)
|
)
|
||||||
check.show()
|
check.show()
|
||||||
|
|
||||||
|
def solver_log_adists(self, solver, mage_rep):
|
||||||
|
sol = SolverLogWindowAdisTS(
|
||||||
|
study=self._study,
|
||||||
|
config=self.conf,
|
||||||
|
solver=solver,
|
||||||
|
parent=self,
|
||||||
|
mage_rep=mage_rep,
|
||||||
|
)
|
||||||
|
sol.show()
|
||||||
|
|
||||||
def solver_log(self, solver):
|
def solver_log(self, solver):
|
||||||
sol = SolverLogWindow(
|
sol = SolverLogWindow(
|
||||||
study=self._study,
|
study=self._study,
|
||||||
@@ -1353,6 +1401,63 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||||||
)
|
)
|
||||||
res.show()
|
res.show()
|
||||||
|
|
||||||
|
def open_solver_results_adists(self, solver, results=None):
|
||||||
|
def reading_fn():
|
||||||
|
self._tmp_results = results
|
||||||
|
|
||||||
|
# If no specific results, get last results
|
||||||
|
if results is None:
|
||||||
|
def reading_fn():
|
||||||
|
self._tmp_results = self._last_results
|
||||||
|
|
||||||
|
if self._last_results is None:
|
||||||
|
def reading_fn():
|
||||||
|
self._tmp_results = solver.results(
|
||||||
|
self._study,
|
||||||
|
self._solver_workdir(solver),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Open from file
|
||||||
|
if type(results) is str:
|
||||||
|
logger.info(f"Open results from {os.path.dirname(results)}")
|
||||||
|
|
||||||
|
name = os.path.basename(results).replace(".BIN", "")
|
||||||
|
|
||||||
|
def reading_fn():
|
||||||
|
self._tmp_results = solver.results(
|
||||||
|
self._study,
|
||||||
|
os.path.dirname(results),
|
||||||
|
name=name
|
||||||
|
)
|
||||||
|
|
||||||
|
dlg = ReadingResultsDialog(reading_fn=reading_fn, parent=self)
|
||||||
|
dlg.exec_()
|
||||||
|
results = self._tmp_results
|
||||||
|
|
||||||
|
# No results available
|
||||||
|
if results is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Windows already opened
|
||||||
|
if self.sub_window_exists(
|
||||||
|
ResultsWindowAdisTS,
|
||||||
|
data=[
|
||||||
|
self._study,
|
||||||
|
None, # No config
|
||||||
|
solver,
|
||||||
|
results
|
||||||
|
]
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
res = ResultsWindowAdisTS(
|
||||||
|
study=self._study,
|
||||||
|
solver=solver,
|
||||||
|
results=results,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
res.show()
|
||||||
|
|
||||||
def _solver_workdir(self, solver):
|
def _solver_workdir(self, solver):
|
||||||
workdir = os.path.join(
|
workdir = os.path.join(
|
||||||
os.path.dirname(self._study.filename),
|
os.path.dirname(self._study.filename),
|
||||||
|
|||||||
@@ -0,0 +1,162 @@
|
|||||||
|
# PlotCAdisTS.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from tools import timer, trace
|
||||||
|
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
QCoreApplication
|
||||||
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class PlotC(PamhyrPlot):
|
||||||
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
|
results=None, reach_id=0, profile_id=0, pol_id=0,
|
||||||
|
parent=None):
|
||||||
|
super(PlotC, self).__init__(
|
||||||
|
canvas=canvas,
|
||||||
|
trad=trad,
|
||||||
|
data=results,
|
||||||
|
toolbar=toolbar,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._mode = "time"
|
||||||
|
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self._current_pol_id = pol_id
|
||||||
|
|
||||||
|
self.label_x = _translate("Results", "Time (s)")
|
||||||
|
self.label_y = _translate("Results", "Discharge (m³/s)")
|
||||||
|
|
||||||
|
self.label_discharge = _translate("Results", "Cross-section discharge")
|
||||||
|
self.label_discharge_max = _translate("Results", "Max discharge")
|
||||||
|
self.label_timestamp = _translate("Results", "Current timestamp")
|
||||||
|
|
||||||
|
self._isometric_axis = False
|
||||||
|
|
||||||
|
self._auto_relim_update = False
|
||||||
|
self._autoscale_update = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def results(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
@results.setter
|
||||||
|
def results(self, results):
|
||||||
|
self.data = results
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def draw(self, highlight=None):
|
||||||
|
self.init_axes()
|
||||||
|
|
||||||
|
if self.results is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
if reach.geometry.number_profiles == 0:
|
||||||
|
self._init = False
|
||||||
|
return
|
||||||
|
|
||||||
|
self.draw_data(reach, profile, pollutant)
|
||||||
|
|
||||||
|
self.set_ticks_time_formater()
|
||||||
|
|
||||||
|
self.enable_legend()
|
||||||
|
|
||||||
|
self.idle()
|
||||||
|
self._init = True
|
||||||
|
|
||||||
|
def draw_data(self, reach, profile, pollutant):
|
||||||
|
self.ts = list(self.results.get("timestamps"))
|
||||||
|
self.ts.sort()
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
#First 0 for pol and second 0 for phys var
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][0], profile.get_key("pols")))
|
||||||
|
|
||||||
|
###print("************//////////////////")
|
||||||
|
###print("profile: ", self._current_profile_id)
|
||||||
|
###print("reach: ", self._current_reach_id)
|
||||||
|
###print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
###print("*****************draw data: ", len(x),len(y))
|
||||||
|
###print("x: ", x)
|
||||||
|
###print("y: ", y)
|
||||||
|
###print("reach: ", reach)
|
||||||
|
###print("profile: ", profile)
|
||||||
|
###print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
self._line, = self.canvas.axes.plot(
|
||||||
|
x, y,
|
||||||
|
label=self.label_discharge,
|
||||||
|
color=self.color_plot,
|
||||||
|
**self.plot_default_kargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_reach(self, reach_id):
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = 0
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def set_profile(self, profile_id):
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def set_pollutant(self, pol_id):
|
||||||
|
self._current_pol_id = pol_id
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def set_timestamp(self, timestamp):
|
||||||
|
self._current_timestamp = timestamp
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if not self._init:
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
self.update_data()
|
||||||
|
|
||||||
|
self.update_idle()
|
||||||
|
|
||||||
|
def update_data(self):
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][0], profile.get_key("pols")))
|
||||||
|
|
||||||
|
self._line.set_data(x, y)
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
# PlotMAdisTS.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from tools import timer, trace
|
||||||
|
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
QCoreApplication
|
||||||
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class PlotM(PamhyrPlot):
|
||||||
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
|
results=None, reach_id=0, profile_id=0, pol_id=0,
|
||||||
|
parent=None):
|
||||||
|
super(PlotM, self).__init__(
|
||||||
|
canvas=canvas,
|
||||||
|
trad=trad,
|
||||||
|
data=results,
|
||||||
|
toolbar=toolbar,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._mode = "time"
|
||||||
|
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self._current_pol_id = pol_id
|
||||||
|
|
||||||
|
self.label_x = _translate("Results", "Time (s)")
|
||||||
|
self.label_y = _translate("Results", "Discharge (m³/s)")
|
||||||
|
|
||||||
|
self.label_discharge = _translate("Results", "Cross-section discharge")
|
||||||
|
self.label_discharge_max = _translate("Results", "Max discharge")
|
||||||
|
self.label_timestamp = _translate("Results", "Current timestamp")
|
||||||
|
|
||||||
|
self._isometric_axis = False
|
||||||
|
|
||||||
|
self._auto_relim_update = False
|
||||||
|
self._autoscale_update = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def results(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
@results.setter
|
||||||
|
def results(self, results):
|
||||||
|
self.data = results
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def draw(self, highlight=None):
|
||||||
|
self.init_axes()
|
||||||
|
|
||||||
|
if self.results is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
if reach.geometry.number_profiles == 0:
|
||||||
|
self._init = False
|
||||||
|
return
|
||||||
|
|
||||||
|
self.draw_data(reach, profile, pollutant)
|
||||||
|
|
||||||
|
self.set_ticks_time_formater()
|
||||||
|
|
||||||
|
self.enable_legend()
|
||||||
|
|
||||||
|
self.idle()
|
||||||
|
self._init = True
|
||||||
|
|
||||||
|
def draw_data(self, reach, profile, pollutant):
|
||||||
|
self.ts = list(self.results.get("timestamps"))
|
||||||
|
self.ts.sort()
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
#First 0 for pol and second 0 for phys var
|
||||||
|
y1 = list(map(lambda data_el: data_el[pollutant][1], profile.get_key("pols")))
|
||||||
|
y2 = list(map(lambda data_el: data_el[pollutant][2], profile.get_key("pols")))
|
||||||
|
y3 = list(map(lambda data_el: data_el[pollutant][3], profile.get_key("pols")))
|
||||||
|
|
||||||
|
y = (np.array(y1) + np.array(y2) + np.array(y3)).tolist()
|
||||||
|
|
||||||
|
###print("************//////////////////")
|
||||||
|
###print("profile: ", self._current_profile_id)
|
||||||
|
###print("reach: ", self._current_reach_id)
|
||||||
|
###print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
###print("*****************draw data: ", len(x),len(y))
|
||||||
|
###print("x: ", x)
|
||||||
|
###print("y: ", y)
|
||||||
|
###print("reach: ", reach)
|
||||||
|
###print("profile: ", profile)
|
||||||
|
###print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
self._line, = self.canvas.axes.plot(
|
||||||
|
x, y,
|
||||||
|
label=self.label_discharge,
|
||||||
|
color=self.color_plot,
|
||||||
|
**self.plot_default_kargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_reach(self, reach_id):
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = 0
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def set_profile(self, profile_id):
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def set_pollutant(self, pol_id):
|
||||||
|
self._current_pol_id = pol_id
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def set_timestamp(self, timestamp):
|
||||||
|
self._current_timestamp = timestamp
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if not self._init:
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
self.update_data()
|
||||||
|
|
||||||
|
self.update_idle()
|
||||||
|
|
||||||
|
def update_data(self):
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
|
||||||
|
y1 = list(map(lambda data_el: data_el[pollutant][1], profile.get_key("pols")))
|
||||||
|
y2 = list(map(lambda data_el: data_el[pollutant][2], profile.get_key("pols")))
|
||||||
|
y3 = list(map(lambda data_el: data_el[pollutant][3], profile.get_key("pols")))
|
||||||
|
|
||||||
|
y = (np.array(y1) + np.array(y2) + np.array(y3)).tolist()
|
||||||
|
|
||||||
|
self._line.set_data(x, y)
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
# PlotTotSedCAdisTS.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from tools import timer, trace
|
||||||
|
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
QCoreApplication
|
||||||
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class PlotTotSedC(PamhyrPlot):
|
||||||
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
|
results=None, reach_id=0, profile_id=0, pol_id=0,
|
||||||
|
parent=None):
|
||||||
|
super(PlotTotSedC, self).__init__(
|
||||||
|
canvas=canvas,
|
||||||
|
trad=trad,
|
||||||
|
data=results,
|
||||||
|
toolbar=toolbar,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._mode = "time"
|
||||||
|
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self._current_pol_id = pol_id
|
||||||
|
|
||||||
|
self.label_x = _translate("Results", "Time (s)")
|
||||||
|
self.label_y = _translate("Results", "Discharge (m³/s)")
|
||||||
|
|
||||||
|
self.label_discharge = _translate("Results", "Cross-section discharge")
|
||||||
|
self.label_discharge_max = _translate("Results", "Max discharge")
|
||||||
|
self.label_timestamp = _translate("Results", "Current timestamp")
|
||||||
|
|
||||||
|
self._isometric_axis = False
|
||||||
|
|
||||||
|
self._auto_relim_update = False
|
||||||
|
self._autoscale_update = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def results(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
@results.setter
|
||||||
|
def results(self, results):
|
||||||
|
self.data = results
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def draw(self, highlight=None):
|
||||||
|
self.init_axes()
|
||||||
|
|
||||||
|
if self.results is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
if reach.geometry.number_profiles == 0:
|
||||||
|
self._init = False
|
||||||
|
return
|
||||||
|
|
||||||
|
self.draw_data(reach, profile, pollutant)
|
||||||
|
|
||||||
|
self.set_ticks_time_formater()
|
||||||
|
|
||||||
|
self.enable_legend()
|
||||||
|
|
||||||
|
self.idle()
|
||||||
|
self._init = True
|
||||||
|
|
||||||
|
def draw_data(self, reach, profile, pollutant):
|
||||||
|
self.ts = list(self.results.get("timestamps"))
|
||||||
|
self.ts.sort()
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
#First 0 for pol and second 0 for phys var
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][0], profile.get_key("pols")))
|
||||||
|
|
||||||
|
print("Total Sed C************//////////////////")
|
||||||
|
print("profile: ", self._current_profile_id)
|
||||||
|
print("reach: ", self._current_reach_id)
|
||||||
|
print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
###print("*****************draw data: ", len(x),len(y))
|
||||||
|
###print("x: ", x)
|
||||||
|
###print("y: ", y)
|
||||||
|
###print("reach: ", reach)
|
||||||
|
###print("profile: ", profile)
|
||||||
|
###print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
self._line, = self.canvas.axes.plot(
|
||||||
|
x, y,
|
||||||
|
label=self.label_discharge,
|
||||||
|
color=self.color_plot,
|
||||||
|
**self.plot_default_kargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_reach(self, reach_id):
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = 0
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def set_profile(self, profile_id):
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def set_timestamp(self, timestamp):
|
||||||
|
self._current_timestamp = timestamp
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if not self._init:
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
self.update_data()
|
||||||
|
|
||||||
|
self.update_idle()
|
||||||
|
|
||||||
|
def update_data(self):
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][0], profile.get_key("pols")))
|
||||||
|
|
||||||
|
self._line.set_data(x, y)
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
# PlotTotSedEDAdisTS.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from tools import timer, trace
|
||||||
|
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
QCoreApplication
|
||||||
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class PlotTotSedED(PamhyrPlot):
|
||||||
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
|
results=None, reach_id=0, profile_id=0, pol_id=0,
|
||||||
|
parent=None):
|
||||||
|
super(PlotTotSedED, self).__init__(
|
||||||
|
canvas=canvas,
|
||||||
|
trad=trad,
|
||||||
|
data=results,
|
||||||
|
toolbar=toolbar,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._mode = "time"
|
||||||
|
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self._current_pol_id = pol_id
|
||||||
|
|
||||||
|
self.label_x = _translate("Results", "Time (s)")
|
||||||
|
self.label_y = _translate("Results", "Discharge (m³/s)")
|
||||||
|
|
||||||
|
self.label_discharge = _translate("Results", "Cross-section discharge")
|
||||||
|
self.label_discharge_max = _translate("Results", "Max discharge")
|
||||||
|
self.label_timestamp = _translate("Results", "Current timestamp")
|
||||||
|
|
||||||
|
self._isometric_axis = False
|
||||||
|
|
||||||
|
self._auto_relim_update = False
|
||||||
|
self._autoscale_update = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def results(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
@results.setter
|
||||||
|
def results(self, results):
|
||||||
|
self.data = results
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def draw(self, highlight=None):
|
||||||
|
self.init_axes()
|
||||||
|
|
||||||
|
if self.results is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
if reach.geometry.number_profiles == 0:
|
||||||
|
self._init = False
|
||||||
|
return
|
||||||
|
|
||||||
|
self.draw_data(reach, profile, pollutant)
|
||||||
|
|
||||||
|
self.set_ticks_time_formater()
|
||||||
|
|
||||||
|
self.enable_legend()
|
||||||
|
|
||||||
|
self.idle()
|
||||||
|
self._init = True
|
||||||
|
|
||||||
|
def draw_data(self, reach, profile, pollutant):
|
||||||
|
self.ts = list(self.results.get("timestamps"))
|
||||||
|
self.ts.sort()
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
#First 0 for pol and second 0 for phys var
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][3], profile.get_key("pols")))
|
||||||
|
|
||||||
|
print("Total Sed ED ************//////////////////")
|
||||||
|
print("profile: ", self._current_profile_id)
|
||||||
|
print("reach: ", self._current_reach_id)
|
||||||
|
print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
###print("*****************draw data: ", len(x),len(y))
|
||||||
|
###print("x: ", x)
|
||||||
|
###print("y: ", y)
|
||||||
|
###print("reach: ", reach)
|
||||||
|
###print("profile: ", profile)
|
||||||
|
###print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
self._line, = self.canvas.axes.plot(
|
||||||
|
x, y,
|
||||||
|
label=self.label_discharge,
|
||||||
|
color=self.color_plot,
|
||||||
|
**self.plot_default_kargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_reach(self, reach_id):
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = 0
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def set_profile(self, profile_id):
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def set_timestamp(self, timestamp):
|
||||||
|
self._current_timestamp = timestamp
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if not self._init:
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
self.update_data()
|
||||||
|
|
||||||
|
self.update_idle()
|
||||||
|
|
||||||
|
def update_data(self):
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][3], profile.get_key("pols")))
|
||||||
|
|
||||||
|
self._line.set_data(x, y)
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
# PlotTotSedEGAdisTS.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from tools import timer, trace
|
||||||
|
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
QCoreApplication
|
||||||
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class PlotTotSedEG(PamhyrPlot):
|
||||||
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
|
results=None, reach_id=0, profile_id=0, pol_id=0,
|
||||||
|
parent=None):
|
||||||
|
super(PlotTotSedEG, self).__init__(
|
||||||
|
canvas=canvas,
|
||||||
|
trad=trad,
|
||||||
|
data=results,
|
||||||
|
toolbar=toolbar,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._mode = "time"
|
||||||
|
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self._current_pol_id = pol_id
|
||||||
|
|
||||||
|
self.label_x = _translate("Results", "Time (s)")
|
||||||
|
self.label_y = _translate("Results", "Discharge (m³/s)")
|
||||||
|
|
||||||
|
self.label_discharge = _translate("Results", "Cross-section discharge")
|
||||||
|
self.label_discharge_max = _translate("Results", "Max discharge")
|
||||||
|
self.label_timestamp = _translate("Results", "Current timestamp")
|
||||||
|
|
||||||
|
self._isometric_axis = False
|
||||||
|
|
||||||
|
self._auto_relim_update = False
|
||||||
|
self._autoscale_update = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def results(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
@results.setter
|
||||||
|
def results(self, results):
|
||||||
|
self.data = results
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def draw(self, highlight=None):
|
||||||
|
self.init_axes()
|
||||||
|
|
||||||
|
if self.results is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
if reach.geometry.number_profiles == 0:
|
||||||
|
self._init = False
|
||||||
|
return
|
||||||
|
|
||||||
|
self.draw_data(reach, profile, pollutant)
|
||||||
|
|
||||||
|
self.set_ticks_time_formater()
|
||||||
|
|
||||||
|
self.enable_legend()
|
||||||
|
|
||||||
|
self.idle()
|
||||||
|
self._init = True
|
||||||
|
|
||||||
|
def draw_data(self, reach, profile, pollutant):
|
||||||
|
self.ts = list(self.results.get("timestamps"))
|
||||||
|
self.ts.sort()
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
#First 0 for pol and second 0 for phys var
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][1], profile.get_key("pols")))
|
||||||
|
|
||||||
|
print("Total Sed EG ************//////////////////")
|
||||||
|
print("profile: ", self._current_profile_id)
|
||||||
|
print("reach: ", self._current_reach_id)
|
||||||
|
print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
###print("*****************draw data: ", len(x),len(y))
|
||||||
|
###print("x: ", x)
|
||||||
|
###print("y: ", y)
|
||||||
|
###print("reach: ", reach)
|
||||||
|
###print("profile: ", profile)
|
||||||
|
###print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
self._line, = self.canvas.axes.plot(
|
||||||
|
x, y,
|
||||||
|
label=self.label_discharge,
|
||||||
|
color=self.color_plot,
|
||||||
|
**self.plot_default_kargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_reach(self, reach_id):
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = 0
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def set_profile(self, profile_id):
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def set_timestamp(self, timestamp):
|
||||||
|
self._current_timestamp = timestamp
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if not self._init:
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
self.update_data()
|
||||||
|
|
||||||
|
self.update_idle()
|
||||||
|
|
||||||
|
def update_data(self):
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][1], profile.get_key("pols")))
|
||||||
|
|
||||||
|
self._line.set_data(x, y)
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
# PlotTotSedEMAdisTS.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from tools import timer, trace
|
||||||
|
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
QCoreApplication
|
||||||
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class PlotTotSedEM(PamhyrPlot):
|
||||||
|
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||||
|
results=None, reach_id=0, profile_id=0, pol_id=0,
|
||||||
|
parent=None):
|
||||||
|
super(PlotTotSedEM, self).__init__(
|
||||||
|
canvas=canvas,
|
||||||
|
trad=trad,
|
||||||
|
data=results,
|
||||||
|
toolbar=toolbar,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._mode = "time"
|
||||||
|
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self._current_pol_id = pol_id
|
||||||
|
|
||||||
|
self.label_x = _translate("Results", "Time (s)")
|
||||||
|
self.label_y = _translate("Results", "Discharge (m³/s)")
|
||||||
|
|
||||||
|
self.label_discharge = _translate("Results", "Cross-section discharge")
|
||||||
|
self.label_discharge_max = _translate("Results", "Max discharge")
|
||||||
|
self.label_timestamp = _translate("Results", "Current timestamp")
|
||||||
|
|
||||||
|
self._isometric_axis = False
|
||||||
|
|
||||||
|
self._auto_relim_update = False
|
||||||
|
self._autoscale_update = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def results(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
@results.setter
|
||||||
|
def results(self, results):
|
||||||
|
self.data = results
|
||||||
|
self._current_timestamp = max(results.get("timestamps"))
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def draw(self, highlight=None):
|
||||||
|
self.init_axes()
|
||||||
|
|
||||||
|
if self.results is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
if reach.geometry.number_profiles == 0:
|
||||||
|
self._init = False
|
||||||
|
return
|
||||||
|
|
||||||
|
self.draw_data(reach, profile, pollutant)
|
||||||
|
|
||||||
|
self.set_ticks_time_formater()
|
||||||
|
|
||||||
|
self.enable_legend()
|
||||||
|
|
||||||
|
self.idle()
|
||||||
|
self._init = True
|
||||||
|
|
||||||
|
def draw_data(self, reach, profile, pollutant):
|
||||||
|
self.ts = list(self.results.get("timestamps"))
|
||||||
|
self.ts.sort()
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
#First 0 for pol and second 0 for phys var
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][2], profile.get_key("pols")))
|
||||||
|
|
||||||
|
print("Total Sed EM ************//////////////////")
|
||||||
|
print("profile: ", self._current_profile_id)
|
||||||
|
print("reach: ", self._current_reach_id)
|
||||||
|
print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
###print("*****************draw data: ", len(x),len(y))
|
||||||
|
###print("x: ", x)
|
||||||
|
###print("y: ", y)
|
||||||
|
###print("reach: ", reach)
|
||||||
|
###print("profile: ", profile)
|
||||||
|
###print("pollutant: ", pollutant)
|
||||||
|
|
||||||
|
self._line, = self.canvas.axes.plot(
|
||||||
|
x, y,
|
||||||
|
label=self.label_discharge,
|
||||||
|
color=self.color_plot,
|
||||||
|
**self.plot_default_kargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_reach(self, reach_id):
|
||||||
|
self._current_reach_id = reach_id
|
||||||
|
self._current_profile_id = 0
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def set_profile(self, profile_id):
|
||||||
|
self._current_profile_id = profile_id
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def set_timestamp(self, timestamp):
|
||||||
|
self._current_timestamp = timestamp
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if not self._init:
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
self.update_data()
|
||||||
|
|
||||||
|
self.update_idle()
|
||||||
|
|
||||||
|
def update_data(self):
|
||||||
|
reach = self.results.river.reach(self._current_reach_id)
|
||||||
|
profile = reach.profile(self._current_profile_id)
|
||||||
|
pollutant = self._current_pol_id
|
||||||
|
|
||||||
|
x = self.ts
|
||||||
|
#y = profile.get_key("Q")
|
||||||
|
y = list(map(lambda data_el: data_el[pollutant][2], profile.get_key("pols")))
|
||||||
|
|
||||||
|
self._line.set_data(x, y)
|
||||||
@@ -45,8 +45,12 @@ _translate = QCoreApplication.translate
|
|||||||
class TableModel(PamhyrTableModel):
|
class TableModel(PamhyrTableModel):
|
||||||
def _setup_lst(self):
|
def _setup_lst(self):
|
||||||
_river = self._data.river
|
_river = self._data.river
|
||||||
|
print("data: ", self._data)
|
||||||
|
print("river: ", _river)
|
||||||
|
print("reaches: ", _river.reachs)
|
||||||
if self._opt_data == "reach":
|
if self._opt_data == "reach":
|
||||||
self._lst = _river.reachs
|
self._lst = _river.reachs
|
||||||
|
print("optreach: ", self._lst)
|
||||||
elif self._opt_data == "profile":
|
elif self._opt_data == "profile":
|
||||||
self._lst = _river.reach(0).profiles
|
self._lst = _river.reach(0).profiles
|
||||||
elif self._opt_data == "raw_data":
|
elif self._opt_data == "raw_data":
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
# TableAdisTS.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2024 INRAE
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from tools import timer, trace
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence, QColor
|
||||||
|
)
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QAbstractTableModel, QModelIndex,
|
||||||
|
QVariant, pyqtSlot, QCoreApplication,
|
||||||
|
)
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QMessageBox, QUndoCommand, QUndoStack,
|
||||||
|
QStyledItemDelegate, QLineEdit, QAbstractItemView,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
from View.Results.translate import *
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class TableModel(PamhyrTableModel):
|
||||||
|
def _setup_lst(self):
|
||||||
|
_river = self._data.river
|
||||||
|
###print("//////////////////opt_data: ", self._opt_data)
|
||||||
|
###print("data: ", self._data)
|
||||||
|
###print("river: ", _river)
|
||||||
|
###print("reaches: ", _river.reachs)
|
||||||
|
if self._opt_data == "reach":
|
||||||
|
self._lst = _river.reachs
|
||||||
|
###print("optreach: ", self._lst)
|
||||||
|
elif self._opt_data == "profile":
|
||||||
|
self._lst = _river.reach(0).profiles
|
||||||
|
elif self._opt_data == "raw_data":
|
||||||
|
self._lst = _river.reach(0).profiles
|
||||||
|
elif self._opt_data == "pollutants":
|
||||||
|
tmp_list = self._data.pollutants_list.copy()
|
||||||
|
tmp_list.remove("total_sediment")
|
||||||
|
###print(type(tmp_list))
|
||||||
|
#tmp_list.insert(len(tmp_list), "total_sediment")
|
||||||
|
self._lst = tmp_list
|
||||||
|
###print("=====table pollutants: ", self._lst)
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self._timestamp = 0.0
|
||||||
|
super(TableModel, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def data(self, index, role=Qt.DisplayRole):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._opt_data == "reach":
|
||||||
|
if self._headers[column] == "name":
|
||||||
|
v = self._lst[row].name
|
||||||
|
return str(v)
|
||||||
|
elif self._opt_data == "pollutants":
|
||||||
|
if self._headers[column] == "name":
|
||||||
|
v = self._lst[row]
|
||||||
|
return str(v)
|
||||||
|
elif self._opt_data == "profile":
|
||||||
|
if self._headers[column] == "name":
|
||||||
|
v = self._lst[row].name
|
||||||
|
return str(v)
|
||||||
|
elif self._headers[column] == "kp":
|
||||||
|
v = self._lst[row].kp
|
||||||
|
return f"{v:.4f}"
|
||||||
|
elif self._opt_data == "raw_data":
|
||||||
|
p = self._lst[row]
|
||||||
|
if self._headers[column] == "name":
|
||||||
|
if p.name == "":
|
||||||
|
return f"{p.kp:.4f}"
|
||||||
|
return f"{p.name}"
|
||||||
|
tmp_list = self._data.pollutants_list.copy()
|
||||||
|
tmp_list.remove("total_sediment")
|
||||||
|
tmp_list2 = self._data.pollutants_list.copy()
|
||||||
|
print("=============================list polutants table raw: ", tmp_list)
|
||||||
|
print("=============================list polutants table raw: ", tmp_list2)
|
||||||
|
for pol in tmp_list:
|
||||||
|
pol_index = tmp_list2.index(pol)
|
||||||
|
print("=============================pol index: ", pol_index)
|
||||||
|
header_name = pol + " Concentration"
|
||||||
|
print("=============================Headers: ", self._headers[column])
|
||||||
|
print("=============================Headers: ", header_name)
|
||||||
|
if self._headers[column] == header_name:
|
||||||
|
print("=============================Headers: ", self._headers[column])
|
||||||
|
print("=============================Headers: ", header_name)
|
||||||
|
v = self._lst[row].get_ts_key(self._timestamp, "pols")[pol_index][0]
|
||||||
|
return f"{v:.4f}"
|
||||||
|
elif self._headers[column] == pol + " Mass":
|
||||||
|
m1 = self._lst[row].get_ts_key(self._timestamp, "pols")[pol_index][1]
|
||||||
|
m2 = self._lst[row].get_ts_key(self._timestamp, "pols")[pol_index][2]
|
||||||
|
m3 = self._lst[row].get_ts_key(self._timestamp, "pols")[pol_index][3]
|
||||||
|
v = m1 + m2 + m3
|
||||||
|
return f"{v:.4f}"
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def update(self, reach):
|
||||||
|
_river = self._data.river
|
||||||
|
|
||||||
|
if self._opt_data == "reach":
|
||||||
|
self._lst = _river.reachs
|
||||||
|
elif self._opt_data == "profile" or self._opt_data == "raw_data":
|
||||||
|
self._lst = _river.reach(reach).profiles
|
||||||
|
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timestamp(self):
|
||||||
|
return self._timestamp
|
||||||
|
|
||||||
|
@timestamp.setter
|
||||||
|
def timestamp(self, timestamp):
|
||||||
|
self._timestamp = timestamp
|
||||||
|
self.layoutChanged.emit()
|
||||||
@@ -0,0 +1,643 @@
|
|||||||
|
# WindowAdisTS.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 csv
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from tools import trace, timer, logger_exception
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence, QIcon, QPixmap,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QItemSelectionModel, QTimer,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
|
QSlider, QLabel, QWidget, QGridLayout,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||||
|
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||||
|
|
||||||
|
from View.Results.PlotCAdisTS import PlotC
|
||||||
|
from View.Results.PlotMAdisTS import PlotM
|
||||||
|
from View.Results.PlotTotSedCAdisTS import PlotTotSedC
|
||||||
|
from View.Results.PlotTotSedEGAdisTS import PlotTotSedEG
|
||||||
|
from View.Results.PlotTotSedEMAdisTS import PlotTotSedEM
|
||||||
|
from View.Results.PlotTotSedEDAdisTS import PlotTotSedED
|
||||||
|
|
||||||
|
from View.Results.CustomPlot.Plot import CustomPlot
|
||||||
|
from View.Results.CustomPlot.CustomPlotValuesSelectionDialog import (
|
||||||
|
CustomPlotValuesSelectionDialog,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Results.TableAdisTS import TableModel
|
||||||
|
from View.Results.translate import ResultsTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class ResultsWindowAdisTS(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "ResultsAdisTS"
|
||||||
|
_pamhyr_name = "Results"
|
||||||
|
|
||||||
|
def _path_file(self, filename):
|
||||||
|
return os.path.abspath(
|
||||||
|
os.path.join(
|
||||||
|
os.path.dirname(__file__),
|
||||||
|
"..", "ui", "ressources", filename
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, study=None, config=None,
|
||||||
|
solver=None, results=None,
|
||||||
|
parent=None):
|
||||||
|
self._solver = solver
|
||||||
|
self._results = results
|
||||||
|
|
||||||
|
pollutants_headers = self._results.pollutants_list.copy()
|
||||||
|
print("***///---+++///***---+++pollutants translate: ", pollutants_headers)
|
||||||
|
|
||||||
|
trad = ResultsTranslate(pollutants_headers)
|
||||||
|
name = (
|
||||||
|
trad[self._pamhyr_name] + " - "
|
||||||
|
+ study.name + " - "
|
||||||
|
+ self._solver.name
|
||||||
|
)
|
||||||
|
|
||||||
|
super(ResultsWindowAdisTS, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._hash_data.append(self._solver)
|
||||||
|
self._hash_data.append(self._results)
|
||||||
|
|
||||||
|
self._additional_plot = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
#print("timestamps results: ", self._results)
|
||||||
|
self._timestamps = sorted(list(self._results.get("timestamps")))
|
||||||
|
|
||||||
|
print("setup table adists results")
|
||||||
|
|
||||||
|
self.setup_table()
|
||||||
|
self.setup_plots()
|
||||||
|
self.setup_slider()
|
||||||
|
print("///setup slider correct")
|
||||||
|
self.setup_statusbar()
|
||||||
|
print("///setup status bar correct")
|
||||||
|
self.setup_connections()
|
||||||
|
print("///setup connections correct")
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
print("setup table adists results")
|
||||||
|
print("results study name: ", self._results.study.name)
|
||||||
|
print("results study river: ", self._results.study.river)
|
||||||
|
print("*********files names resultats from Results Window: ", self._results.pollutants_list)
|
||||||
|
self._table = {}
|
||||||
|
for t in ["reach", "profile", "pollutants", "raw_data"]:
|
||||||
|
print("t: ", t)
|
||||||
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
|
self._table[t] = TableModel(
|
||||||
|
table_view=table,
|
||||||
|
table_headers=self._trad.get_dict(f"table_headers_{t}"),
|
||||||
|
data=self._results,
|
||||||
|
undo=self._undo_stack,
|
||||||
|
opt_data=t
|
||||||
|
)
|
||||||
|
|
||||||
|
def setup_slider(self):
|
||||||
|
self._timer = QTimer(self)
|
||||||
|
|
||||||
|
def setup_plots(self):
|
||||||
|
self.canvas_4 = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_4.setObjectName("canvas_4")
|
||||||
|
self.toolbar_4 = PamhyrPlotToolbar(
|
||||||
|
self.canvas_4, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_4 = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_concentration")
|
||||||
|
self.plot_layout_4.addWidget(self.toolbar_4)
|
||||||
|
self.plot_layout_4.addWidget(self.canvas_4)
|
||||||
|
|
||||||
|
self.plot_c = PlotC(
|
||||||
|
canvas=self.canvas_4,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=0,
|
||||||
|
profile_id=0,
|
||||||
|
pol_id=0,
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_4
|
||||||
|
)
|
||||||
|
self.plot_c.draw()
|
||||||
|
|
||||||
|
print("///plot c adists correct")
|
||||||
|
|
||||||
|
self.canvas_3 = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_3.setObjectName("canvas_3")
|
||||||
|
self.toolbar_3 = PamhyrPlotToolbar(
|
||||||
|
self.canvas_3, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_3 = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_mass")
|
||||||
|
self.plot_layout_3.addWidget(self.toolbar_3)
|
||||||
|
self.plot_layout_3.addWidget(self.canvas_3)
|
||||||
|
|
||||||
|
self.plot_m = PlotM(
|
||||||
|
canvas=self.canvas_3,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=0,
|
||||||
|
profile_id=0,
|
||||||
|
pol_id=0,
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_3
|
||||||
|
)
|
||||||
|
self.plot_m.draw()
|
||||||
|
|
||||||
|
print("///plot m adists correct")
|
||||||
|
|
||||||
|
self.canvas_2 = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_2.setObjectName("canvas_2")
|
||||||
|
self.toolbar_2 = PamhyrPlotToolbar(
|
||||||
|
self.canvas_2, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_2 = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_tot_c")
|
||||||
|
self.plot_layout_2.addWidget(self.toolbar_2)
|
||||||
|
self.plot_layout_2.addWidget(self.canvas_2)
|
||||||
|
|
||||||
|
self.plot_tot_c = PlotTotSedC(
|
||||||
|
canvas=self.canvas_2,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=0,
|
||||||
|
profile_id=0,
|
||||||
|
pol_id=self._results.pollutants_list.index("total_sediment"),
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_2
|
||||||
|
)
|
||||||
|
|
||||||
|
self.plot_tot_c.draw()
|
||||||
|
|
||||||
|
self.canvas_1 = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_1.setObjectName("canvas_1")
|
||||||
|
self.toolbar_1 = PamhyrPlotToolbar(
|
||||||
|
self.canvas_1, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_1 = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_tot_left_2")
|
||||||
|
self.plot_layout_1.addWidget(self.toolbar_1)
|
||||||
|
self.plot_layout_1.addWidget(self.canvas_1)
|
||||||
|
|
||||||
|
self.plot_tot_eg = PlotTotSedEG(
|
||||||
|
canvas=self.canvas_1,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=0,
|
||||||
|
profile_id=0,
|
||||||
|
pol_id=self._results.pollutants_list.index("total_sediment"),
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_1
|
||||||
|
)
|
||||||
|
|
||||||
|
self.plot_tot_eg.draw()
|
||||||
|
|
||||||
|
self.canvas_0 = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_0.setObjectName("canvas_0")
|
||||||
|
self.toolbar_0 = PamhyrPlotToolbar(
|
||||||
|
self.canvas_0, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_0 = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_tot_minor")
|
||||||
|
self.plot_layout_0.addWidget(self.toolbar_0)
|
||||||
|
self.plot_layout_0.addWidget(self.canvas_0)
|
||||||
|
|
||||||
|
self.plot_tot_em = PlotTotSedEM(
|
||||||
|
canvas=self.canvas_0,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=0,
|
||||||
|
profile_id=0,
|
||||||
|
pol_id=self._results.pollutants_list.index("total_sediment"),
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_0
|
||||||
|
)
|
||||||
|
|
||||||
|
self.plot_tot_em.draw()
|
||||||
|
|
||||||
|
self.canvas_5 = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_5.setObjectName("canvas_5")
|
||||||
|
self.toolbar_5 = PamhyrPlotToolbar(
|
||||||
|
self.canvas_5, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_5 = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_tot_right")
|
||||||
|
self.plot_layout_5.addWidget(self.toolbar_5)
|
||||||
|
print("///***---+++///+++add toolbar correct")
|
||||||
|
self.plot_layout_5.addWidget(self.canvas_5)
|
||||||
|
print("///***---+++///+++add canvas correct")
|
||||||
|
|
||||||
|
self.plot_tot_ed = PlotTotSedED(
|
||||||
|
canvas=self.canvas_5,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=0,
|
||||||
|
profile_id=0,
|
||||||
|
pol_id=self._results.pollutants_list.index("total_sediment"),
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_5
|
||||||
|
)
|
||||||
|
|
||||||
|
self.plot_tot_ed.draw()
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
try:
|
||||||
|
self._timer.stop()
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
|
super(ResultsWindowAdisTS, self).closeEvent(event)
|
||||||
|
|
||||||
|
def _compute_status_label(self):
|
||||||
|
# Reach
|
||||||
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
reach = self._study.river.edges()[0]
|
||||||
|
else:
|
||||||
|
reach = self._study.river.edges()[indexes[0].row()]
|
||||||
|
|
||||||
|
# Profile
|
||||||
|
table = self.find(QTableView, f"tableView_profile")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
profile = reach.reach.profile(0)
|
||||||
|
else:
|
||||||
|
profile = reach.reach.profile(indexes[0].row())
|
||||||
|
|
||||||
|
pname = profile.name if profile.name != "" else profile.kp
|
||||||
|
|
||||||
|
# Pollutant
|
||||||
|
table = self.find(QTableView, f"tableView_pollutants")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
pollutant = self._results.pollutants_list[0]
|
||||||
|
else:
|
||||||
|
pollutant = self._results.pollutants_list[indexes[0].row()]
|
||||||
|
|
||||||
|
return (f"Reach: {reach.name} | " +
|
||||||
|
f"Profile: {pname} | " +
|
||||||
|
f"Pollutant: {pollutant}")
|
||||||
|
|
||||||
|
def setup_statusbar(self):
|
||||||
|
txt = self._compute_status_label()
|
||||||
|
self._status_label = QLabel(txt)
|
||||||
|
self.statusbar.addPermanentWidget(self._status_label)
|
||||||
|
|
||||||
|
def update_statusbar(self):
|
||||||
|
txt = self._compute_status_label()
|
||||||
|
self._status_label.setText(txt)
|
||||||
|
|
||||||
|
def setup_connections(self):
|
||||||
|
# Action
|
||||||
|
actions = {
|
||||||
|
"action_reload": self._reload,
|
||||||
|
###"action_add": self._add_custom_plot,
|
||||||
|
"action_export": self.export,
|
||||||
|
}
|
||||||
|
|
||||||
|
for action in actions:
|
||||||
|
self.find(QAction, action).triggered.connect(
|
||||||
|
actions[action]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Table and Plot
|
||||||
|
fun = {
|
||||||
|
"reach": self._set_current_reach,
|
||||||
|
"profile": self._set_current_profile,
|
||||||
|
"pollutants": self._set_current_pol,
|
||||||
|
"raw_data": self._set_current_profile_raw_data,
|
||||||
|
}
|
||||||
|
|
||||||
|
for t in ["reach", "profile", "pollutants"]:###, "raw_data"]:
|
||||||
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
|
|
||||||
|
table.selectionModel()\
|
||||||
|
.selectionChanged\
|
||||||
|
.connect(fun[t])
|
||||||
|
|
||||||
|
self._table[t].dataChanged.connect(fun[t])
|
||||||
|
|
||||||
|
self._timer.timeout.connect(self._update_slider)
|
||||||
|
|
||||||
|
def update_table_selection_reach(self, ind):
|
||||||
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
|
selectionModel = table.selectionModel()
|
||||||
|
index = table.model().index(ind, 0)
|
||||||
|
|
||||||
|
selectionModel.select(
|
||||||
|
index,
|
||||||
|
QItemSelectionModel.Rows |
|
||||||
|
QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Select
|
||||||
|
)
|
||||||
|
table.scrollTo(index)
|
||||||
|
|
||||||
|
self._table["profile"].update(ind)
|
||||||
|
###self._table["raw_data"].update(ind)
|
||||||
|
|
||||||
|
def update_table_selection_profile(self, ind):
|
||||||
|
for t in ["profile"]:###, "raw_data"]:
|
||||||
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
|
selectionModel = table.selectionModel()
|
||||||
|
index = table.model().index(ind, 0)
|
||||||
|
|
||||||
|
selectionModel.select(
|
||||||
|
index,
|
||||||
|
QItemSelectionModel.Rows |
|
||||||
|
QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Select
|
||||||
|
)
|
||||||
|
table.scrollTo(index)
|
||||||
|
|
||||||
|
def update_table_selection_pol(self, ind):
|
||||||
|
for t in ["pollutants"]:###, "raw_data"]:
|
||||||
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
|
selectionModel = table.selectionModel()
|
||||||
|
index = table.model().index(ind, 0)
|
||||||
|
|
||||||
|
selectionModel.select(
|
||||||
|
index,
|
||||||
|
QItemSelectionModel.Rows |
|
||||||
|
QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Select
|
||||||
|
)
|
||||||
|
table.scrollTo(index)
|
||||||
|
|
||||||
|
def update(self, reach_id=None, profile_id=None, pol_id=None, timestamp=None):
|
||||||
|
if reach_id is not None:
|
||||||
|
self.plot_c.set_reach(reach_id)
|
||||||
|
self.plot_m.set_reach(reach_id)
|
||||||
|
self.plot_tot_c.set_reach(reach_id)
|
||||||
|
self.plot_tot_eg.set_reach(reach_id)
|
||||||
|
self.plot_tot_em.set_reach(reach_id)
|
||||||
|
self.plot_tot_ed.set_reach(reach_id)
|
||||||
|
|
||||||
|
self.update_table_selection_reach(reach_id)
|
||||||
|
self.update_table_selection_profile(0)
|
||||||
|
self.update_table_selection_pol(0)
|
||||||
|
|
||||||
|
if profile_id is not None:
|
||||||
|
self.plot_c.set_profile(profile_id)
|
||||||
|
self.plot_m.set_profile(profile_id)
|
||||||
|
self.plot_tot_c.set_profile(profile_id)
|
||||||
|
self.plot_tot_eg.set_profile(profile_id)
|
||||||
|
self.plot_tot_em.set_profile(profile_id)
|
||||||
|
self.plot_tot_ed.set_profile(profile_id)
|
||||||
|
|
||||||
|
self.update_table_selection_profile(profile_id)
|
||||||
|
|
||||||
|
print("--**//++update pol_id before None: ", pol_id)
|
||||||
|
|
||||||
|
if pol_id is not None:
|
||||||
|
print("--**//++//**//** update pol_id: ", pol_id)
|
||||||
|
self.plot_c.set_pollutant(pol_id)
|
||||||
|
self.plot_m.set_pollutant(pol_id)
|
||||||
|
|
||||||
|
self.update_table_selection_pol(pol_id)
|
||||||
|
|
||||||
|
if timestamp is not None:
|
||||||
|
self.plot_c.set_timestamp(timestamp)
|
||||||
|
self.plot_m.set_timestamp(timestamp)
|
||||||
|
self.plot_tot_c.set_timestamp(timestamp)
|
||||||
|
self.plot_tot_eg.set_timestamp(timestamp)
|
||||||
|
self.plot_tot_em.set_timestamp(timestamp)
|
||||||
|
self.plot_tot_ed.set_timestamp(timestamp)
|
||||||
|
|
||||||
|
self._table["raw_data"].timestamp = timestamp
|
||||||
|
|
||||||
|
self.update_statusbar()
|
||||||
|
|
||||||
|
def _set_current_reach(self):
|
||||||
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.update(reach_id=indexes[0].row())
|
||||||
|
|
||||||
|
def _set_current_profile(self):
|
||||||
|
table = self.find(QTableView, f"tableView_profile")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
ind = indexes[0].row()
|
||||||
|
self.update(profile_id=ind)
|
||||||
|
###self._slider_profile.setValue(ind)
|
||||||
|
|
||||||
|
def _set_current_pol(self):
|
||||||
|
table = self.find(QTableView, f"tableView_pollutants")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
ind = indexes[0].row()
|
||||||
|
print("set pol id: ", ind)
|
||||||
|
self.update(pol_id=ind)
|
||||||
|
|
||||||
|
def _set_current_profile_raw_data(self):
|
||||||
|
table = self.find(QTableView, f"tableView_raw_data")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
ind = indexes[0].row()
|
||||||
|
self.update(profile_id=ind)
|
||||||
|
self._slider_profile.setValue(ind)
|
||||||
|
|
||||||
|
def _set_current_profile_slider(self):
|
||||||
|
pid = self._slider_profile.value()
|
||||||
|
self.update(profile_id=pid)
|
||||||
|
|
||||||
|
def _set_current_timestamp(self):
|
||||||
|
timestamp = self._timestamps[self._slider_time.value()]
|
||||||
|
self.update(timestamp=timestamp)
|
||||||
|
|
||||||
|
def _reload_plots(self):
|
||||||
|
self.plot_c.results = self._results
|
||||||
|
self.plot_m.results = self._results
|
||||||
|
self.plot_tot_c.results = self._results
|
||||||
|
self.plot_tot_eg.results = self._results
|
||||||
|
self.plot_tot_em.results = self._results
|
||||||
|
self.plot_tot_ed.results = self._results
|
||||||
|
|
||||||
|
self.plot_c.draw()
|
||||||
|
self.plot_m.draw()
|
||||||
|
self.plot_tot_c.draw()
|
||||||
|
self.plot_tot_eg.draw()
|
||||||
|
self.plot_tot_em.draw()
|
||||||
|
self.plot_tot_ed.draw()
|
||||||
|
|
||||||
|
def _reload_slider(self):
|
||||||
|
self._slider_time = self.find(QSlider, f"horizontalSlider_time")
|
||||||
|
self._slider_time.setMaximum(len(self._timestamps) - 1)
|
||||||
|
self._slider_time.setValue(len(self._timestamps) - 1)
|
||||||
|
|
||||||
|
def _reload(self):
|
||||||
|
logger.debug("Reload results...")
|
||||||
|
self._results = self._results.reload()
|
||||||
|
|
||||||
|
self._timestamps = sorted(list(self._results.get("timestamps")))
|
||||||
|
|
||||||
|
self._reload_plots()
|
||||||
|
###self._reload_slider()
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
logger.info("TODO: copy")
|
||||||
|
|
||||||
|
def _paste(self):
|
||||||
|
logger.info("TODO: paste")
|
||||||
|
|
||||||
|
def _undo(self):
|
||||||
|
self._table.undo()
|
||||||
|
|
||||||
|
def _redo(self):
|
||||||
|
self._table.redo()
|
||||||
|
|
||||||
|
# play / pause buttons
|
||||||
|
def _update_slider(self):
|
||||||
|
if self._slider_time.value() == self._slider_time.maximum():
|
||||||
|
self._slider_time.setValue(self._slider_time.minimum())
|
||||||
|
else:
|
||||||
|
self._slider_time.setValue(self._slider_time.value()+1)
|
||||||
|
|
||||||
|
def _next(self):
|
||||||
|
self._slider_time.setValue(self._slider_time.value()+1)
|
||||||
|
|
||||||
|
def _back(self):
|
||||||
|
self._slider_time.setValue(self._slider_time.value()-1)
|
||||||
|
|
||||||
|
def _first(self):
|
||||||
|
self._slider_time.setValue(self._slider_time.minimum())
|
||||||
|
|
||||||
|
def _last(self):
|
||||||
|
self._slider_time.setValue(self._slider_time.maximum())
|
||||||
|
|
||||||
|
def _pause(self):
|
||||||
|
if self._button_play.isChecked():
|
||||||
|
self._button_next.setEnabled(False)
|
||||||
|
self._button_back.setEnabled(False)
|
||||||
|
self._button_first.setEnabled(False)
|
||||||
|
self._button_last.setEnabled(False)
|
||||||
|
self._timer.start(100)
|
||||||
|
self._button_play.setIcon(self._icon_pause)
|
||||||
|
else:
|
||||||
|
self._timer.stop()
|
||||||
|
self._button_next.setEnabled(True)
|
||||||
|
self._button_back.setEnabled(True)
|
||||||
|
self._button_first.setEnabled(True)
|
||||||
|
self._button_last.setEnabled(True)
|
||||||
|
self._button_play.setIcon(self._icon_start)
|
||||||
|
|
||||||
|
def export(self):
|
||||||
|
self.file_dialog(
|
||||||
|
select_file=False,
|
||||||
|
callback=lambda d: self.export_to(d[0])
|
||||||
|
)
|
||||||
|
|
||||||
|
def export_to(self, directory):
|
||||||
|
for reach in self._results.river.reachs:
|
||||||
|
self.export_reach(reach, directory)
|
||||||
|
|
||||||
|
def export_reach(self, reach, directory):
|
||||||
|
name = reach.name
|
||||||
|
name = name.replace(" ", "-")
|
||||||
|
|
||||||
|
file_name = os.path.join(
|
||||||
|
directory,
|
||||||
|
f"reach_{name}.csv"
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(file_name, 'w', newline='') as csvfile:
|
||||||
|
writer = csv.writer(csvfile, delimiter=',',
|
||||||
|
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||||
|
writer.writerow(["name", "kp", "data-file"])
|
||||||
|
for profile in reach.profiles:
|
||||||
|
p_file_name = os.path.join(
|
||||||
|
directory,
|
||||||
|
f"cs_{profile.geometry.id}.csv"
|
||||||
|
)
|
||||||
|
|
||||||
|
writer.writerow([
|
||||||
|
profile.name,
|
||||||
|
profile.kp,
|
||||||
|
p_file_name
|
||||||
|
])
|
||||||
|
|
||||||
|
self.export_profile(reach, profile, p_file_name)
|
||||||
|
|
||||||
|
def export_profile(self, reach, profile, file_name):
|
||||||
|
with open(file_name, 'w', newline='') as csvfile:
|
||||||
|
writer = csv.writer(csvfile, delimiter=',',
|
||||||
|
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||||
|
|
||||||
|
writer.writerow(["timestamp", "z", "q"])
|
||||||
|
timestamps = sorted(self._results.get("timestamps"))
|
||||||
|
|
||||||
|
for ts in timestamps:
|
||||||
|
writer.writerow([
|
||||||
|
ts,
|
||||||
|
profile.get_ts_key(ts, "Z"),
|
||||||
|
profile.get_ts_key(ts, "Q"),
|
||||||
|
])
|
||||||
@@ -24,7 +24,13 @@ _translate = QCoreApplication.translate
|
|||||||
|
|
||||||
|
|
||||||
class ResultsTranslate(MainTranslate):
|
class ResultsTranslate(MainTranslate):
|
||||||
def __init__(self):
|
def __init__(self, pollutants=None):
|
||||||
|
if pollutants is not None:
|
||||||
|
self.pollutants = pollutants
|
||||||
|
self.pollutants.remove("total_sediment")
|
||||||
|
else:
|
||||||
|
self.pollutants = pollutants
|
||||||
|
|
||||||
super(ResultsTranslate, self).__init__()
|
super(ResultsTranslate, self).__init__()
|
||||||
|
|
||||||
self._dict["Results"] = _translate("Results", "Results")
|
self._dict["Results"] = _translate("Results", "Results")
|
||||||
@@ -48,14 +54,31 @@ class ResultsTranslate(MainTranslate):
|
|||||||
"name": _translate("Results", "Reach name"),
|
"name": _translate("Results", "Reach name"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self._sub_dict["table_headers_phys_var"] = {
|
||||||
|
"name": _translate("Results", "Variables names"),
|
||||||
|
}
|
||||||
|
|
||||||
self._sub_dict["table_headers_profile"] = {
|
self._sub_dict["table_headers_profile"] = {
|
||||||
"name": self._dict["name"],
|
"name": self._dict["name"],
|
||||||
"kp": self._dict["unit_kp"],
|
"kp": self._dict["unit_kp"],
|
||||||
}
|
}
|
||||||
|
|
||||||
self._sub_dict["table_headers_raw_data"] = {
|
self._sub_dict["table_headers_pollutants"] = {
|
||||||
"name": _translate("Results", "Profile"),
|
"name": _translate("Results", "Pollutant name"),
|
||||||
"water_elevation": self._dict["unit_water_elevation"],
|
|
||||||
"discharge": self._dict["unit_discharge"],
|
|
||||||
"speed": self._dict["unit_speed"],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.pollutants is not None:
|
||||||
|
self._sub_dict["table_headers_raw_data"] = {
|
||||||
|
"name": _translate("Results", "Profile"),
|
||||||
|
}
|
||||||
|
for pol in self.pollutants:
|
||||||
|
self._sub_dict["table_headers_raw_data"][pol + " Concentration"] = pol + "\n Concentration"
|
||||||
|
self._sub_dict["table_headers_raw_data"][pol + " Mass"] = pol + "\n Mass"
|
||||||
|
else:
|
||||||
|
self._sub_dict["table_headers_raw_data"] = {
|
||||||
|
"name": _translate("Results", "Profile"),
|
||||||
|
"water_elevation": self._dict["unit_water_elevation"],
|
||||||
|
"discharge": self._dict["unit_discharge"],
|
||||||
|
"speed": self._dict["unit_speed"],
|
||||||
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,9 @@ class SelectSolverWindow(PamhyrDialog):
|
|||||||
self.select_last_solver()
|
self.select_last_solver()
|
||||||
|
|
||||||
def setup_combobox(self):
|
def setup_combobox(self):
|
||||||
solvers = self._config.solvers
|
#solvers = self._config.solvers
|
||||||
|
#solvers mage
|
||||||
|
solvers = list(filter(lambda x: "adists" not in x._type, self._config.solvers))
|
||||||
solvers_name = list(
|
solvers_name = list(
|
||||||
map(
|
map(
|
||||||
self._format_solver_name,
|
self._format_solver_name,
|
||||||
|
|||||||
@@ -0,0 +1,451 @@
|
|||||||
|
# WindowAdisTS.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 tempfile
|
||||||
|
|
||||||
|
from queue import Queue
|
||||||
|
from tools import trace, timer, logger_exception
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrDialog, PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect, QTimer, QProcess,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
|
QTextEdit,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.RunSolver.Log.Window import SolverLogFileWindow
|
||||||
|
from View.Results.ReadingResultsDialog import ReadingResultsDialog
|
||||||
|
|
||||||
|
try:
|
||||||
|
from signal import SIGTERM, SIGSTOP, SIGCONT
|
||||||
|
_signal = True
|
||||||
|
except Exception:
|
||||||
|
_signal = False
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class SelectSolverWindowAdisTS(PamhyrDialog):
|
||||||
|
_pamhyr_ui = "SelectSolverAdisTS"
|
||||||
|
_pamhyr_name = "Select solver"
|
||||||
|
|
||||||
|
def __init__(self, study=None, config=None,
|
||||||
|
parent=None):
|
||||||
|
self._solver = None
|
||||||
|
|
||||||
|
name = _translate("Solver", "Select solver")
|
||||||
|
super(SelectSolverWindowAdisTS, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
options=[],
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self.setup_combobox()
|
||||||
|
self.setup_connections()
|
||||||
|
self.select_last_solver()
|
||||||
|
|
||||||
|
def setup_combobox(self):
|
||||||
|
#solvers = self._config.solvers
|
||||||
|
#solvers mage
|
||||||
|
solvers = list(filter(lambda x: "mage" not in x._type, self._config.solvers))
|
||||||
|
solvers_name = list(
|
||||||
|
map(
|
||||||
|
self._format_solver_name,
|
||||||
|
solvers
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
solvers_mage = list(filter(lambda x: "mage" in x._type.lower(), self._config.solvers))
|
||||||
|
solvers_mage_names = list(map(lambda x: x._name, solvers_mage))
|
||||||
|
|
||||||
|
solvers_dir = os.path.join(
|
||||||
|
os.path.dirname(self._study.filename),
|
||||||
|
"_PAMHYR_",
|
||||||
|
self._study.name.replace(" ", "_"),
|
||||||
|
)
|
||||||
|
|
||||||
|
dir_solvers_List = os.listdir(solvers_dir)
|
||||||
|
|
||||||
|
display_mage_names = list(filter(lambda x: x in solvers_mage_names, dir_solvers_List))
|
||||||
|
|
||||||
|
self.combobox_add_items("comboBox", solvers_name)
|
||||||
|
self.combobox_add_items("comboBoxRepMage", display_mage_names)
|
||||||
|
|
||||||
|
def setup_connections(self):
|
||||||
|
self.find(QPushButton, "pushButton_run").clicked.connect(self.accept)
|
||||||
|
self.find(QPushButton, "pushButton_cancel")\
|
||||||
|
.clicked.connect(self.reject)
|
||||||
|
|
||||||
|
def select_last_solver(self):
|
||||||
|
solvers = self._config.solvers
|
||||||
|
last = self._config.last_solver_name
|
||||||
|
|
||||||
|
solver = list(
|
||||||
|
filter(
|
||||||
|
lambda s: s.name == last,
|
||||||
|
solvers
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(solver) != 0:
|
||||||
|
self.set_combobox_text(
|
||||||
|
"comboBox",
|
||||||
|
self._format_solver_name(solver[0])
|
||||||
|
)
|
||||||
|
|
||||||
|
def _format_solver_name(self, solver):
|
||||||
|
return f"{solver.name} - ({solver._type})"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def solver(self):
|
||||||
|
return self._solver
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mage_rep(self):
|
||||||
|
return self._mage_result_rep
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
solver_name = self.get_combobox_text("comboBox")
|
||||||
|
solver_name = solver_name.rsplit(" - ", 1)[0]
|
||||||
|
|
||||||
|
self._mage_result_rep = self.get_combobox_text("comboBoxRepMage")
|
||||||
|
|
||||||
|
self._config.update_last_solver_used(solver_name)
|
||||||
|
|
||||||
|
self._solver = next(
|
||||||
|
filter(
|
||||||
|
lambda s: s.name == solver_name,
|
||||||
|
self._config.solvers
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
super(SelectSolverWindowAdisTS, self).accept()
|
||||||
|
|
||||||
|
class SolverLogWindowAdisTS(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "SolverLogAdisTS"
|
||||||
|
_pamhyr_name = "Solver Log"
|
||||||
|
|
||||||
|
def __init__(self, study=None, config=None,
|
||||||
|
solver=None, parent=None, mage_rep=None):
|
||||||
|
self._solver = solver
|
||||||
|
self._results = None
|
||||||
|
self._results_mage = None
|
||||||
|
self._mage_rep = mage_rep
|
||||||
|
|
||||||
|
name = _translate("Solver", "Select log")
|
||||||
|
super(SolverLogWindowAdisTS, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
options=[],
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self.setup_action()
|
||||||
|
self.setup_alarm()
|
||||||
|
self.setup_connections()
|
||||||
|
self.setup_workdir()
|
||||||
|
self.setup_process()
|
||||||
|
|
||||||
|
ok = self.export()
|
||||||
|
if ok:
|
||||||
|
self.run()
|
||||||
|
else:
|
||||||
|
self._log(
|
||||||
|
f" *** Failed to export study to {self._solver._type}",
|
||||||
|
color="red"
|
||||||
|
)
|
||||||
|
|
||||||
|
def setup_action(self):
|
||||||
|
self.find(QAction, "action_start").setEnabled(False)
|
||||||
|
if _signal:
|
||||||
|
self.find(QAction, "action_pause").setEnabled(True)
|
||||||
|
else:
|
||||||
|
self.find(QAction, "action_pause").setEnabled(False)
|
||||||
|
|
||||||
|
self.find(QAction, "action_stop").setEnabled(True)
|
||||||
|
self.find(QAction, "action_log_file").setEnabled(False)
|
||||||
|
self.find(QAction, "action_results").setEnabled(False)
|
||||||
|
|
||||||
|
def setup_alarm(self):
|
||||||
|
self._alarm = QTimer()
|
||||||
|
|
||||||
|
def setup_connections(self):
|
||||||
|
self.find(QAction, "action_start").triggered.connect(self.start)
|
||||||
|
self.find(QAction, "action_pause").triggered.connect(self.pause)
|
||||||
|
self.find(QAction, "action_stop").triggered.connect(self.stop)
|
||||||
|
self.find(QAction, "action_log_file").triggered.connect(self.log_file)
|
||||||
|
self.find(QAction, "action_results").triggered.connect(self.results)
|
||||||
|
self.find(QAction, "action_results_Mage").triggered.connect(self.resultsMage)
|
||||||
|
|
||||||
|
self._alarm.timeout.connect(self.update)
|
||||||
|
|
||||||
|
def setup_workdir(self):
|
||||||
|
self._workdir = ""
|
||||||
|
if self._study.filename == "":
|
||||||
|
self._workdir = tempfile.TemporaryDirectory()
|
||||||
|
else:
|
||||||
|
self._workdir = os.path.join(
|
||||||
|
os.path.dirname(self._study.filename),
|
||||||
|
"_PAMHYR_",
|
||||||
|
self._study.name.replace(" ", "_"),
|
||||||
|
self._solver.name.replace(" ", "_"),
|
||||||
|
)
|
||||||
|
os.makedirs(self._workdir, exist_ok=True)
|
||||||
|
|
||||||
|
def setup_process(self):
|
||||||
|
self._alarm.start(100)
|
||||||
|
self._output = Queue()
|
||||||
|
self._process = self.new_process(self._parent)
|
||||||
|
|
||||||
|
def new_process(self, parent):
|
||||||
|
new = QProcess(parent)
|
||||||
|
new.setWorkingDirectory(self._workdir)
|
||||||
|
new.setProcessChannelMode(QProcess.MergedChannels)
|
||||||
|
return new
|
||||||
|
|
||||||
|
def export(self):
|
||||||
|
self._log(f" *** Export study {self._solver.name}", color="blue")
|
||||||
|
ok = self._solver.export(self._study, self._workdir, self._mage_rep, qlog=self._output)
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
self._alarm.stop()
|
||||||
|
super(SolverLogWindowAdisTS, self).closeEvent(event)
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
self.find(QTextEdit, "textEdit").copy()
|
||||||
|
|
||||||
|
#######
|
||||||
|
# LOG #
|
||||||
|
#######
|
||||||
|
|
||||||
|
def _log(self, msg, color=None):
|
||||||
|
if type(msg) is str:
|
||||||
|
self._log_str(msg, color)
|
||||||
|
elif type(msg) is int:
|
||||||
|
self._log_int(msg, color)
|
||||||
|
|
||||||
|
def _log_str(self, msg, color=None):
|
||||||
|
if msg == "":
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info(f"solver: {msg}")
|
||||||
|
msg = msg.rsplit('\n', 1)[0]
|
||||||
|
|
||||||
|
if color is not None:
|
||||||
|
msg = f"<font color=\"{color}\">" + msg + "</font>"
|
||||||
|
|
||||||
|
self.find(QTextEdit, "textEdit").append(msg)
|
||||||
|
|
||||||
|
def _log_int(self, int_code, color=None):
|
||||||
|
logger.info(f"solver: Returns {int_code}")
|
||||||
|
color = "blue" if int_code == 0 else "red"
|
||||||
|
|
||||||
|
self.find(QTextEdit, "textEdit")\
|
||||||
|
.append(
|
||||||
|
f"<font color=\"{color}\">" +
|
||||||
|
f" *** Finished with code {int_code}" +
|
||||||
|
"</font>"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.statusbar.showMessage(
|
||||||
|
"Done" if int_code == 0 else "Failed",
|
||||||
|
3000
|
||||||
|
)
|
||||||
|
|
||||||
|
##########
|
||||||
|
# UPDATE #
|
||||||
|
##########
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if self._solver.is_stoped():
|
||||||
|
self.find(QAction, "action_start").setEnabled(True)
|
||||||
|
self.find(QAction, "action_pause").setEnabled(False)
|
||||||
|
self.find(QAction, "action_stop").setEnabled(False)
|
||||||
|
self.find(QAction, "action_results").setEnabled(True)
|
||||||
|
|
||||||
|
if self._solver.log_file() != "":
|
||||||
|
self.find(QAction, "action_log_file").setEnabled(True)
|
||||||
|
|
||||||
|
self._update_logs_all()
|
||||||
|
# self._update_get_results()
|
||||||
|
|
||||||
|
self._update_logs_all()
|
||||||
|
|
||||||
|
def _update_get_results(self):
|
||||||
|
if self._results is None:
|
||||||
|
def reading_fn():
|
||||||
|
try:
|
||||||
|
self._results = self._solver.results(
|
||||||
|
self._study, self._workdir, qlog=self._output
|
||||||
|
)
|
||||||
|
self._parent.set_results(self._solver, self._results)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to open results")
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
|
dlg = ReadingResultsDialog(reading_fn=reading_fn, parent=self)
|
||||||
|
dlg.exec_()
|
||||||
|
|
||||||
|
def _update_logs_all(self):
|
||||||
|
while self._output.qsize() != 0:
|
||||||
|
s = self._output.get()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if type(s) is str and "[ERROR]" in s:
|
||||||
|
self._log(s.encode("utf-8"), color="red")
|
||||||
|
else:
|
||||||
|
self._log(s)
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Process controle #
|
||||||
|
####################
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self._log(f" *** Run solver {self._solver.name}", color="blue")
|
||||||
|
self._solver.run(
|
||||||
|
self._study,
|
||||||
|
process=self._process,
|
||||||
|
output_queue=self._output
|
||||||
|
)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
if self._solver.is_stoped():
|
||||||
|
self._log(f" *** Export study {self._solver.name}", color="blue")
|
||||||
|
|
||||||
|
ok = self._solver.export(
|
||||||
|
self._study, self._workdir, self._mage_rep, qlog=self._output
|
||||||
|
)
|
||||||
|
|
||||||
|
if not ok:
|
||||||
|
self._log(f" *** Failed to export", color="red")
|
||||||
|
self.update()
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.update()
|
||||||
|
self._process = self.new_process(self._parent)
|
||||||
|
|
||||||
|
self._log(" *** Start", color="blue")
|
||||||
|
self._results = None
|
||||||
|
self._solver.start(self._study, process=self._process)
|
||||||
|
|
||||||
|
self.find(QAction, "action_start").setEnabled(False)
|
||||||
|
if _signal:
|
||||||
|
self.find(QAction, "action_pause").setEnabled(True)
|
||||||
|
else:
|
||||||
|
self.find(QAction, "action_pause").setEnabled(False)
|
||||||
|
self.find(QAction, "action_stop").setEnabled(True)
|
||||||
|
self.find(QAction, "action_log_file").setEnabled(False)
|
||||||
|
self.find(QAction, "action_results").setEnabled(False)
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
self._log(" *** Pause", color="blue")
|
||||||
|
self._solver.pause()
|
||||||
|
|
||||||
|
self.find(QAction, "action_start").setEnabled(True)
|
||||||
|
self.find(QAction, "action_pause").setEnabled(False)
|
||||||
|
self.find(QAction, "action_stop").setEnabled(True)
|
||||||
|
self.find(QAction, "action_results").setEnabled(False)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._log(" *** Stop", color="blue")
|
||||||
|
self._solver.kill()
|
||||||
|
|
||||||
|
self.find(QAction, "action_start").setEnabled(True)
|
||||||
|
self.find(QAction, "action_pause").setEnabled(False)
|
||||||
|
self.find(QAction, "action_stop").setEnabled(False)
|
||||||
|
self.find(QAction, "action_results").setEnabled(True)
|
||||||
|
if self._solver.log_file() != "":
|
||||||
|
self.find(QAction, "action_log_file").setEnabled(True)
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Results #
|
||||||
|
###########
|
||||||
|
|
||||||
|
def results(self):
|
||||||
|
if self._results is None:
|
||||||
|
def reading_fn():
|
||||||
|
self._results = self._solver.results(
|
||||||
|
self._study, self._workdir, qlog=self._output
|
||||||
|
)
|
||||||
|
|
||||||
|
dlg = ReadingResultsDialog(reading_fn=reading_fn, parent=self)
|
||||||
|
dlg.exec_()
|
||||||
|
|
||||||
|
self._parent.set_results(self._solver, self._results)
|
||||||
|
self._parent.open_solver_results_adists(self._solver, self._results)
|
||||||
|
|
||||||
|
self._solver.has_results_loaded()
|
||||||
|
|
||||||
|
def resultsMage(self):
|
||||||
|
if self._results_mage is None:
|
||||||
|
mage_solver = next(filter(lambda x: x._name == self._mage_rep, self._config.solvers))
|
||||||
|
workdir_mage = os.path.join(
|
||||||
|
os.path.dirname(self._study.filename),
|
||||||
|
"_PAMHYR_",
|
||||||
|
self._study.name.replace(" ", "_"),
|
||||||
|
mage_solver.name.replace(" ", "_"),
|
||||||
|
)
|
||||||
|
def reading_fn():
|
||||||
|
self._results_mage = mage_solver.results(
|
||||||
|
self._study, workdir_mage, qlog=self._output
|
||||||
|
)
|
||||||
|
|
||||||
|
dlg = ReadingResultsDialog(reading_fn=reading_fn, parent=self)
|
||||||
|
dlg.exec_()
|
||||||
|
|
||||||
|
self._parent.set_results(mage_solver, self._results_mage)
|
||||||
|
self._parent.open_solver_results(mage_solver, self._results_mage)
|
||||||
|
|
||||||
|
mage_solver.has_results_loaded()
|
||||||
|
|
||||||
|
def log_file(self):
|
||||||
|
file_name = os.path.join(self._workdir, self._solver.log_file())
|
||||||
|
log = SolverLogFileWindow(
|
||||||
|
file_name=file_name,
|
||||||
|
study=self._study,
|
||||||
|
config=self._config,
|
||||||
|
solver=self._solver,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
log.show()
|
||||||
|
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1280</width>
|
||||||
|
<height>720</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="Europe"/>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>874</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QSplitter" name="splitter_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QSplitter" name="splitter_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QTableView" name="tableView_reach"/>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="tableView_profile"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="tableView_pollutants"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_tot_left"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab_4">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Raw data</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_5">
|
||||||
|
<item row="0" column="1">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="tableView_raw_data"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_2">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Concentration</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_concentration"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_3">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Mass</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_mass"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_5">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Total Sediments</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_6">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_tot">
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabWidget_2">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Concentration</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_7">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_tot_c"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_6">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Left thickness</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_8">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_tot_left_2"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_7">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Minor thickness</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_9">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_tot_minor"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_8">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Right thickness</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_10">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_tot_right"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menubar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1280</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
<widget class="QToolBar" name="toolBar">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>toolBar</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<addaction name="action_add"/>
|
||||||
|
<addaction name="action_export"/>
|
||||||
|
<addaction name="action_reload"/>
|
||||||
|
</widget>
|
||||||
|
<action name="action_add">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/add.png</normaloff>ressources/add.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Add custom visualization</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_reload">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/reload.png</normaloff>ressources/reload.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Reload</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_export">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/export.png</normaloff>ressources/export.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Export</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Export raw data</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+E</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Dialog</class>
|
||||||
|
<widget class="QDialog" name="Dialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>384</width>
|
||||||
|
<height>107</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="Europe"/>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>AdisTS Solver:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QComboBox" name="comboBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton_run">
|
||||||
|
<property name="text">
|
||||||
|
<string>Run</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/run.png</normaloff>ressources/run.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton_cancel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QComboBox" name="comboBoxRepMage"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Mage Repertory:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1152</width>
|
||||||
|
<height>648</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QTextEdit" name="textEdit">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Monospace</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="Europe"/>
|
||||||
|
</property>
|
||||||
|
<property name="documentTitle">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="undoRedoEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menubar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1152</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
<widget class="QToolBar" name="toolBar">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>toolBar</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<addaction name="action_start"/>
|
||||||
|
<addaction name="action_pause"/>
|
||||||
|
<addaction name="action_stop"/>
|
||||||
|
<addaction name="action_log_file"/>
|
||||||
|
<addaction name="action_results"/>
|
||||||
|
<addaction name="action_results_Mage"/>
|
||||||
|
</widget>
|
||||||
|
<action name="action_stop">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/close.png</normaloff>ressources/close.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Stop</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_start">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/run.png</normaloff>ressources/run.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Start</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_pause">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/player_pause.png</normaloff>ressources/player_pause.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pause</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_log_file">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/zoom.png</normaloff>ressources/zoom.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>LogFile</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_results">
|
||||||
|
<property name="text">
|
||||||
|
<string>results</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_results_Mage">
|
||||||
|
<property name="text">
|
||||||
|
<string>results_Mage</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
Binary file not shown.
Reference in new issue
Block a user