mirror of https://gitlab.com/pamhyr/pamhyr2
Compare commits
9 Commits
36c93a0c93
...
ae39f33131
| Author | SHA1 | Date |
|---|---|---|
|
|
ae39f33131 | |
|
|
291f80e904 | |
|
|
61baaeeffb | |
|
|
68aabb343d | |
|
|
f2d6e07931 | |
|
|
123259c2ef | |
|
|
816d7663b5 | |
|
|
9b9202c739 | |
|
|
57f82415bd |
|
|
@ -352,11 +352,8 @@ class Scenario(SQLSubModel):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def workdir(self):
|
def workdir(self):
|
||||||
srep = ""
|
current = "scenario_" + str(self.id)
|
||||||
if self.id != 0:
|
if self.parent is None or self.parent.id == 0:
|
||||||
srep = os.path.join(
|
return current
|
||||||
self.parent.workdir(),
|
|
||||||
"scenario_" + str(self.id)
|
|
||||||
)
|
|
||||||
|
|
||||||
return srep
|
return os.path.join(self.parent.workdir(), current)
|
||||||
|
|
|
||||||
|
|
@ -613,17 +613,24 @@ class WeatherParameters(SQLSubModel):
|
||||||
new_0 = self._default_0
|
new_0 = self._default_0
|
||||||
new_1 = self._default_1
|
new_1 = self._default_1
|
||||||
|
|
||||||
|
def convert(column, value, default):
|
||||||
|
if value.strip() == "":
|
||||||
|
return default
|
||||||
|
return self._types[column](value.replace(",", "."))
|
||||||
|
|
||||||
if len(header) != 0:
|
if len(header) != 0:
|
||||||
for i in [0, 1]:
|
for i in [0, 1]:
|
||||||
for j in range(len(header)):
|
for j in range(len(header)):
|
||||||
if self._header[i] == header[j]:
|
if self._header[i] == header[j] and j < len(data):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
new_0 = self._types[i](data[j].replace(",", "."))
|
new_0 = convert(i, data[j], new_0)
|
||||||
else:
|
else:
|
||||||
new_1 = self._types[i](data[j].replace(",", "."))
|
new_1 = convert(i, data[j], new_1)
|
||||||
else:
|
else:
|
||||||
new_0 = self._types[0](data[0].replace(",", "."))
|
if len(data) > 0:
|
||||||
new_1 = self._types[1](data[1].replace(",", "."))
|
new_0 = convert(0, data[0], new_0)
|
||||||
|
if len(data) > 1:
|
||||||
|
new_1 = convert(1, data[1], new_1)
|
||||||
|
|
||||||
return Data(new_0, new_1, status=self._status)
|
return Data(new_0, new_1, status=self._status)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,17 @@ class WeatherParametersList(PamhyrModelList):
|
||||||
_default_types = [
|
_default_types = [
|
||||||
"AT", "SH", "GR", "RWS", "GT", "GFR", "ALB", "SC", "CCF"
|
"AT", "SH", "GR", "RWS", "GT", "GFR", "ALB", "SC", "CCF"
|
||||||
]
|
]
|
||||||
|
_default_values = {
|
||||||
|
"AT": 20.0,
|
||||||
|
"SH": 0.001,
|
||||||
|
"GR": 10.0,
|
||||||
|
"RWS": 1.0,
|
||||||
|
"GT": 0.0,
|
||||||
|
"GFR": 0.0,
|
||||||
|
"ALB": 0.06,
|
||||||
|
"SC": 0.15,
|
||||||
|
"CCF": 0.5,
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, status=None):
|
def __init__(self, status=None):
|
||||||
super(WeatherParametersList, self).__init__(status=status)
|
super(WeatherParametersList, self).__init__(status=status)
|
||||||
|
|
@ -109,7 +120,11 @@ class WeatherParametersList(PamhyrModelList):
|
||||||
for type in self._default_types:
|
for type in self._default_types:
|
||||||
if type not in existing:
|
if type not in existing:
|
||||||
self._default.append(
|
self._default.append(
|
||||||
WeatherParametersDefault(type=type, status=self._status)
|
WeatherParametersDefault(
|
||||||
|
type=type,
|
||||||
|
value=self._default_values[type],
|
||||||
|
status=self._status,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self._sort_default_values()
|
self._sort_default_values()
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,10 @@ class StudyTestCase(unittest.TestCase):
|
||||||
defaults = study.river.weather_parameters.default
|
defaults = study.river.weather_parameters.default
|
||||||
|
|
||||||
self.assertEqual(len(defaults), 9)
|
self.assertEqual(len(defaults), 9)
|
||||||
|
self.assertEqual(
|
||||||
|
[default.value for default in defaults],
|
||||||
|
[20.0, 0.001, 10.0, 1.0, 0.0, 0.0, 0.06, 0.15, 0.5]
|
||||||
|
)
|
||||||
defaults[0].value = 12.5
|
defaults[0].value = 12.5
|
||||||
|
|
||||||
dir = tempfile.mkdtemp()
|
dir = tempfile.mkdtemp()
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,8 @@ class ScriptRun(AScript):
|
||||||
os.path.dirname(study.filename),
|
os.path.dirname(study.filename),
|
||||||
"_PAMHYR_",
|
"_PAMHYR_",
|
||||||
study.name.replace(" ", "_"),
|
study.name.replace(" ", "_"),
|
||||||
solver.name.replace(" ", "_")
|
solver.name.replace(" ", "_"),
|
||||||
|
study.status.scenario.workdir(),
|
||||||
)
|
)
|
||||||
os.makedirs(workdir, exist_ok=True)
|
os.makedirs(workdir, exist_ok=True)
|
||||||
logger.info(f"Set working dir to {workdir}")
|
logger.info(f"Set working dir to {workdir}")
|
||||||
|
|
|
||||||
|
|
@ -363,13 +363,19 @@ class AdisTS(CommandLineSolver):
|
||||||
if qlog is not None:
|
if qlog is not None:
|
||||||
qlog.put("Export REP file")
|
qlog.put("Export REP file")
|
||||||
|
|
||||||
|
mage_path = (mage_rep if os.path.isabs(mage_rep) else os.path.join(
|
||||||
|
os.path.abspath(os.path.join(repertory, os.pardir)),
|
||||||
|
mage_rep,
|
||||||
|
))
|
||||||
|
relative_mage_path = os.path.relpath(mage_path, repertory)
|
||||||
|
|
||||||
# Write header
|
# Write header
|
||||||
with adists_file_open(
|
with adists_file_open(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
repertory, f"{name}.REP"
|
repertory, f"{name}.REP"
|
||||||
), "w+"
|
), "w+"
|
||||||
) as f:
|
) as f:
|
||||||
path = os.path.join("..", mage_rep, name)
|
path = os.path.join(relative_mage_path, name)
|
||||||
f.write(f"NET {name}.NET\n")
|
f.write(f"NET {name}.NET\n")
|
||||||
f.write(f"REP {path}.REP\n")
|
f.write(f"REP {path}.REP\n")
|
||||||
|
|
||||||
|
|
@ -384,9 +390,7 @@ class AdisTS(CommandLineSolver):
|
||||||
|
|
||||||
# fake mage_fin.ini:
|
# fake mage_fin.ini:
|
||||||
|
|
||||||
path_mage = os.path.join(os.path.abspath(
|
self._export_fake_INI(study, mage_path,
|
||||||
os.path.join(repertory, os.pardir)), mage_rep)
|
|
||||||
self._export_fake_INI(study, path_mage,
|
|
||||||
qlog, name=name)
|
qlog, name=name)
|
||||||
|
|
||||||
# path_mage_net = os.path.join(os.path.abspath(
|
# path_mage_net = os.path.join(os.path.abspath(
|
||||||
|
|
|
||||||
|
|
@ -330,13 +330,19 @@ class AdisTT(CommandLineSolver):
|
||||||
if qlog is not None:
|
if qlog is not None:
|
||||||
qlog.put("Export REP file")
|
qlog.put("Export REP file")
|
||||||
|
|
||||||
|
mage_path = (mage_rep if os.path.isabs(mage_rep) else os.path.join(
|
||||||
|
os.path.abspath(os.path.join(repertory, os.pardir)),
|
||||||
|
mage_rep,
|
||||||
|
))
|
||||||
|
relative_mage_path = os.path.relpath(mage_path, repertory)
|
||||||
|
|
||||||
# Write header
|
# Write header
|
||||||
with adistt_file_open(
|
with adistt_file_open(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
repertory, f"{name}.REP"
|
repertory, f"{name}.REP"
|
||||||
), "w+"
|
), "w+"
|
||||||
) as f:
|
) as f:
|
||||||
path = os.path.join("..", mage_rep, name)
|
path = os.path.join(relative_mage_path, name)
|
||||||
f.write(f"NET {path}.NET\n")
|
f.write(f"NET {path}.NET\n")
|
||||||
f.write(f"REP {path}.REP\n")
|
f.write(f"REP {path}.REP\n")
|
||||||
|
|
||||||
|
|
@ -348,9 +354,7 @@ class AdisTT(CommandLineSolver):
|
||||||
|
|
||||||
# fake mage_fin.ini:
|
# fake mage_fin.ini:
|
||||||
|
|
||||||
path_mage = os.path.join(os.path.abspath(
|
self._export_fake_INI(study, mage_path,
|
||||||
os.path.join(repertory, os.pardir)), mage_rep)
|
|
||||||
self._export_fake_INI(study, path_mage,
|
|
||||||
qlog, name=name)
|
qlog, name=name)
|
||||||
|
|
||||||
# path_mage_net = os.path.join(os.path.abspath(
|
# path_mage_net = os.path.join(os.path.abspath(
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,13 @@ class CheckListWindowAdisTS(PamhyrWindow):
|
||||||
|
|
||||||
def __init__(self, autorun: bool = True,
|
def __init__(self, autorun: bool = True,
|
||||||
study=None, config=None,
|
study=None, config=None,
|
||||||
solver=None, parent=None, mage_rep=None):
|
solver=None, parent=None, mage_rep=None, mode="adists"):
|
||||||
trad = CheckListTranslate()
|
trad = CheckListTranslate()
|
||||||
|
|
||||||
self._autorun = autorun
|
self._autorun = autorun
|
||||||
self._solver = solver
|
self._solver = solver
|
||||||
self._mage_rep = mage_rep
|
self._mage_rep = mage_rep
|
||||||
|
self._mode = mode
|
||||||
|
|
||||||
name = trad[self._pamhyr_name] + " - " + study.name
|
name = trad[self._pamhyr_name] + " - " + study.name
|
||||||
|
|
||||||
|
|
@ -73,6 +74,8 @@ class CheckListWindowAdisTS(PamhyrWindow):
|
||||||
|
|
||||||
# Add solver to hash computation data
|
# Add solver to hash computation data
|
||||||
self._hash_data.append(self._solver)
|
self._hash_data.append(self._solver)
|
||||||
|
self._hash_data.append(self._mage_rep)
|
||||||
|
self._hash_data.append(self._mode)
|
||||||
|
|
||||||
self._checker_list = (
|
self._checker_list = (
|
||||||
self._study.checkers() +
|
self._study.checkers() +
|
||||||
|
|
@ -169,7 +172,7 @@ class CheckListWindowAdisTS(PamhyrWindow):
|
||||||
if not errors:
|
if not errors:
|
||||||
self.find(QPushButton, "pushButton_ok").setEnabled(True)
|
self.find(QPushButton, "pushButton_ok").setEnabled(True)
|
||||||
if self._autorun:
|
if self._autorun:
|
||||||
self._parent.solver_log_adists(self._solver, self._mage_rep)
|
self.open_solver_log()
|
||||||
self.end()
|
self.end()
|
||||||
|
|
||||||
self.update_statusbar()
|
self.update_statusbar()
|
||||||
|
|
@ -196,5 +199,11 @@ class CheckListWindowAdisTS(PamhyrWindow):
|
||||||
self.end()
|
self.end()
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
self._parent.solver_log_adists(self._solver, self._mage_rep)
|
self.open_solver_log()
|
||||||
# self.end()
|
# self.end()
|
||||||
|
|
||||||
|
def open_solver_log(self):
|
||||||
|
if self._mode == "adistt":
|
||||||
|
self._parent.solver_log_adistt(self._solver, self._mage_rep)
|
||||||
|
else:
|
||||||
|
self._parent.solver_log_adists(self._solver, self._mage_rep)
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ from View.RunSolver.WindowAdisTS import (
|
||||||
from View.CheckList.Window import CheckListWindow
|
from View.CheckList.Window import CheckListWindow
|
||||||
from View.CheckList.WindowAdisTS import CheckListWindowAdisTS
|
from View.CheckList.WindowAdisTS import CheckListWindowAdisTS
|
||||||
from View.Results.WindowAdisTS import ResultsWindowAdisTS
|
from View.Results.WindowAdisTS import ResultsWindowAdisTS
|
||||||
|
from View.Results.WindowAdisTT import ResultsWindowAdisTT
|
||||||
from View.Results.ReadingResultsDialog import ReadingResultsDialog
|
from View.Results.ReadingResultsDialog import ReadingResultsDialog
|
||||||
|
|
||||||
from View.Debug.Window import ReplWindow, TimerWindow
|
from View.Debug.Window import ReplWindow, TimerWindow
|
||||||
|
|
@ -148,7 +149,7 @@ model_action = [
|
||||||
"action_menu_close", "action_menu_edit", "action_menu_save",
|
"action_menu_close", "action_menu_edit", "action_menu_save",
|
||||||
"action_menu_save_as", "action_toolBar_close", "action_toolBar_save",
|
"action_menu_save_as", "action_toolBar_close", "action_toolBar_save",
|
||||||
"action_menu_numerical_parameter", "action_menu_open_results_from_file",
|
"action_menu_numerical_parameter", "action_menu_open_results_from_file",
|
||||||
"action_menu_open_results_adists",
|
"action_menu_open_results_adists", "action_menu_open_results_adistt",
|
||||||
]
|
]
|
||||||
|
|
||||||
other_model_action = [
|
other_model_action = [
|
||||||
|
|
@ -297,9 +298,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
"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":
|
"action_menu_run_adists":
|
||||||
lambda: self.select_run_solver_adists(mode="adists"),
|
self.select_run_solver_adists,
|
||||||
"action_menu_run_adistt":
|
"action_menu_run_adistt":
|
||||||
lambda: self.select_run_solver_adists(mode="adistt"),
|
self.select_run_solver_adistt,
|
||||||
"action_menu_output_rk": self.open_output_rk_adists,
|
"action_menu_output_rk": self.open_output_rk_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,
|
||||||
|
|
@ -334,6 +335,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
"action_menu_compare_scenarios_results":
|
"action_menu_compare_scenarios_results":
|
||||||
self.compare_results_scenarios,
|
self.compare_results_scenarios,
|
||||||
"action_menu_open_results_adists": self.open_results_adists,
|
"action_menu_open_results_adists": self.open_results_adists,
|
||||||
|
"action_menu_open_results_adistt":
|
||||||
|
lambda: self.open_results_adists(mode="adistt"),
|
||||||
# Help
|
# Help
|
||||||
"action_menu_pamhyr_users_wiki": self.open_doc_user,
|
"action_menu_pamhyr_users_wiki": self.open_doc_user,
|
||||||
"action_menu_pamhyr_developers_pdf":
|
"action_menu_pamhyr_developers_pdf":
|
||||||
|
|
@ -1081,7 +1084,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
|
|
||||||
if self.sub_window_exists(
|
if self.sub_window_exists(
|
||||||
BoundaryConditionsTemperatureWindow,
|
BoundaryConditionsTemperatureWindow,
|
||||||
data=[self._study, None, bclist]
|
data=[self._study, None]
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -1101,7 +1104,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
|
|
||||||
if self.sub_window_exists(
|
if self.sub_window_exists(
|
||||||
InitialConditionsTemperatureWindow,
|
InitialConditionsTemperatureWindow,
|
||||||
data=[self._study, None, ic_default]
|
data=[self._study, None]
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -1570,7 +1573,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
if run.exec():
|
if run.exec():
|
||||||
self.run_solver(run.solver)
|
self.run_solver(run.solver)
|
||||||
|
|
||||||
def select_run_solver_adists(self, mode="adists"):
|
def select_run_solver_adists(self):
|
||||||
if self._study is None:
|
if self._study is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -1586,9 +1589,27 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
if run.exec():
|
if run.exec():
|
||||||
self.run_solver_adists(run.solver, run.mage_rep, mode=mode)
|
self.run_solver_adists(run.solver, run.mage_rep)
|
||||||
|
|
||||||
def run_solver_adists(self, solver, mage_rep, mode="adists"):
|
def select_run_solver_adistt(self):
|
||||||
|
if self._study is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
run = SelectSolverWindowAdisTT(
|
||||||
|
study=self._study,
|
||||||
|
config=self.conf,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
if run.exec():
|
||||||
|
self.run_solver_adistt(run.solver, run.mage_rep)
|
||||||
|
|
||||||
|
def run_solver_adists(self, solver, mage_rep):
|
||||||
|
self._run_solver_adis(solver, mage_rep, mode="adists")
|
||||||
|
|
||||||
|
def run_solver_adistt(self, solver, mage_rep):
|
||||||
|
self._run_solver_adis(solver, mage_rep, mode="adistt")
|
||||||
|
|
||||||
|
def _run_solver_adis(self, solver, mage_rep, mode):
|
||||||
if self._study is None:
|
if self._study is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -1598,7 +1619,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
self._study,
|
self._study,
|
||||||
self.conf,
|
self.conf,
|
||||||
solver,
|
solver,
|
||||||
mage_rep
|
mage_rep,
|
||||||
|
mode,
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
@ -1609,6 +1631,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
solver=solver,
|
solver=solver,
|
||||||
parent=self,
|
parent=self,
|
||||||
mage_rep=mage_rep,
|
mage_rep=mage_rep,
|
||||||
|
mode=mode,
|
||||||
)
|
)
|
||||||
check.show()
|
check.show()
|
||||||
|
|
||||||
|
|
@ -1644,6 +1667,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
)
|
)
|
||||||
sol.show()
|
sol.show()
|
||||||
|
|
||||||
|
def solver_log_adistt(self, solver, mage_rep):
|
||||||
|
sol = SolverLogWindowAdisTT(
|
||||||
|
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,
|
||||||
|
|
@ -1763,6 +1796,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
)
|
)
|
||||||
|
|
||||||
def open_solver_results_adists(self, solver, results=None):
|
def open_solver_results_adists(self, solver, results=None):
|
||||||
|
self._open_solver_results_adis(
|
||||||
|
solver, ResultsWindowAdisTS, results=results
|
||||||
|
)
|
||||||
|
|
||||||
|
def open_solver_results_adistt(self, solver, results=None):
|
||||||
|
self._open_solver_results_adis(
|
||||||
|
solver, ResultsWindowAdisTT, results=results
|
||||||
|
)
|
||||||
|
|
||||||
|
def _open_solver_results_adis(self, solver, window_class, results=None):
|
||||||
def reading_fn():
|
def reading_fn():
|
||||||
self._tmp_results = results
|
self._tmp_results = results
|
||||||
|
|
||||||
|
|
@ -1804,7 +1847,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
|
|
||||||
# Windows already opened
|
# Windows already opened
|
||||||
if self.sub_window_exists(
|
if self.sub_window_exists(
|
||||||
ResultsWindowAdisTS,
|
window_class,
|
||||||
data=[
|
data=[
|
||||||
self._study,
|
self._study,
|
||||||
None, # No config
|
None, # No config
|
||||||
|
|
@ -1815,7 +1858,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
res = ResultsWindowAdisTS(
|
res = window_class(
|
||||||
study=self._study,
|
study=self._study,
|
||||||
solver=solver,
|
solver=solver,
|
||||||
results=results,
|
results=results,
|
||||||
|
|
@ -1842,6 +1885,23 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
self._solver_workdir(solver, scenario)
|
self._solver_workdir(solver, scenario)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _solver_from_results_path(self, results_path):
|
||||||
|
solvers_by_directory = {
|
||||||
|
solver.name.replace(" ", "_"): solver
|
||||||
|
for solver in self.conf.solvers
|
||||||
|
}
|
||||||
|
|
||||||
|
path = os.path.abspath(results_path)
|
||||||
|
while True:
|
||||||
|
directory = os.path.basename(path)
|
||||||
|
if directory in solvers_by_directory:
|
||||||
|
return solvers_by_directory[directory]
|
||||||
|
|
||||||
|
parent = os.path.dirname(path)
|
||||||
|
if parent == path:
|
||||||
|
return None
|
||||||
|
path = parent
|
||||||
|
|
||||||
def open_last_results(self):
|
def open_last_results(self):
|
||||||
if self._last_solver is None:
|
if self._last_solver is None:
|
||||||
return
|
return
|
||||||
|
|
@ -2106,7 +2166,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
|
|
||||||
return [result4, result5, result3]
|
return [result4, result5, result3]
|
||||||
|
|
||||||
def open_results_adists(self):
|
def open_results_adists(self, mode="adists"):
|
||||||
if self._study is None:
|
if self._study is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -2143,10 +2203,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
text=self._trad["mb_results_bin_not_found"]
|
text=self._trad["mb_results_bin_not_found"]
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
path = os.path.normpath(dir_path)
|
solver_results = self._solver_from_results_path(dir_path)
|
||||||
solver_name = path.split(os.sep)[-2]
|
|
||||||
solver_results = next(filter(lambda x: x.name == solver_name,
|
|
||||||
self.conf.solvers), None)
|
|
||||||
if solver_results is None:
|
if solver_results is None:
|
||||||
self.msg_results_warning(
|
self.msg_results_warning(
|
||||||
info=self._trad["mb_results_not_found"],
|
info=self._trad["mb_results_not_found"],
|
||||||
|
|
@ -2154,16 +2211,34 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
expected_type = "adistt" if mode == "adistt" else "adists"
|
||||||
|
solver_type = solver_results._type.lower()
|
||||||
|
if not solver_type.startswith(expected_type):
|
||||||
|
self.msg_results_warning(
|
||||||
|
info=self._trad["mb_results_not_found"],
|
||||||
|
text=self._trad["mb_results_solver_mode_mismatch"].format(
|
||||||
|
solver=solver_results.name,
|
||||||
|
mode=expected_type.upper(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
solver_results_adists = solver_results.results(
|
solver_results_adists = solver_results.results(
|
||||||
self._study,
|
self._study,
|
||||||
repertory=dir_path, qlog=None) # self._output)
|
repertory=dir_path, qlog=None) # self._output)
|
||||||
|
|
||||||
logger.info(f"Select results: {dir_path}")
|
logger.info(f"Select results: {dir_path}")
|
||||||
if len(bin_list) >= 2 and ("total_sediment.bin" in bin_list):
|
if len(bin_list) >= 2 and ("total_sediment.bin" in bin_list):
|
||||||
self.open_solver_results_adists(
|
if mode == "adistt":
|
||||||
solver_results,
|
self.open_solver_results_adistt(
|
||||||
results=solver_results_adists,
|
solver_results,
|
||||||
)
|
results=solver_results_adists,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.open_solver_results_adists(
|
||||||
|
solver_results,
|
||||||
|
results=solver_results_adists,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.msg_results_warning(
|
self.msg_results_warning(
|
||||||
info=self._trad["mb_results_not_found"],
|
info=self._trad["mb_results_not_found"],
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,9 @@ class PlotAdis(PamhyrPlot):
|
||||||
self.label["C"] = _translate("Results", "Concentration")
|
self.label["C"] = _translate("Results", "Concentration")
|
||||||
self.label_max["C"] = _translate("Results", "Max Concentration")
|
self.label_max["C"] = _translate("Results", "Max Concentration")
|
||||||
self.label_min["C"] = _translate("Results", "Min Concentration")
|
self.label_min["C"] = _translate("Results", "Min Concentration")
|
||||||
|
self.label["T"] = _translate("Results", "Temperature")
|
||||||
|
self.label_max["T"] = _translate("Results", "Max Temperature")
|
||||||
|
self.label_min["T"] = _translate("Results", "Min Temperature")
|
||||||
if self._type_pol[pol_id[0]] == -1: # Total
|
if self._type_pol[pol_id[0]] == -1: # Total
|
||||||
self.label["M"] = _translate("Results", "Thickness")
|
self.label["M"] = _translate("Results", "Thickness")
|
||||||
self.label_max["M"] = _translate("Results", "Max Thickness")
|
self.label_max["M"] = _translate("Results", "Max Thickness")
|
||||||
|
|
@ -75,6 +78,7 @@ class PlotAdis(PamhyrPlot):
|
||||||
self.label_y = self._available_values_y["unit_"+self._key]
|
self.label_y = self._available_values_y["unit_"+self._key]
|
||||||
self.val_id = {}
|
self.val_id = {}
|
||||||
self.val_id["C"] = 0
|
self.val_id["C"] = 0
|
||||||
|
self.val_id["T"] = 0
|
||||||
self.val_id["G"] = 1
|
self.val_id["G"] = 1
|
||||||
self.val_id["M"] = 2
|
self.val_id["M"] = 2
|
||||||
self.val_id["D"] = 3
|
self.val_id["D"] = 3
|
||||||
|
|
@ -205,9 +209,12 @@ class PlotAdis_dx(PlotAdis):
|
||||||
self._current_timestamp, "pols"
|
self._current_timestamp, "pols"
|
||||||
)[pol_id][self.val_id[self._key]],
|
)[pol_id][self.val_id[self._key]],
|
||||||
reach.profiles))
|
reach.profiles))
|
||||||
|
label = self.label[self._key]
|
||||||
|
if name != "TEM":
|
||||||
|
label += (" "+name)
|
||||||
self._lines.append(self.canvas.axes.plot(
|
self._lines.append(self.canvas.axes.plot(
|
||||||
x, y,
|
x, y,
|
||||||
label=self.label[self._key]+" "+name,
|
label=label,
|
||||||
color=self.colors[pol_id % len(self.colors)],
|
color=self.colors[pol_id % len(self.colors)],
|
||||||
**self.plot_default_kargs
|
**self.plot_default_kargs
|
||||||
)[0])
|
)[0])
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
# TableAdisTT.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2026 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
|
||||||
|
self._timestamp = min(list(self._data.get("timestamps")))
|
||||||
|
if self._opt_data == "reach":
|
||||||
|
self._lst = _river.reachs
|
||||||
|
elif self._opt_data == "profile":
|
||||||
|
self._lst = _river.reach(0).profiles
|
||||||
|
elif self._opt_data == "raw_data":
|
||||||
|
self._lst = _river.reach(0).profiles
|
||||||
|
|
||||||
|
def __init__(self, type_pol, **kwargs):
|
||||||
|
self._type_pol = type_pol
|
||||||
|
super(TableModel, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def data(self, index, role=Qt.DisplayRole):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._opt_data == "reach":
|
||||||
|
if self._headers[column] == "name":
|
||||||
|
v = self._lst[row].name
|
||||||
|
return str(v)
|
||||||
|
elif self._opt_data == "profile":
|
||||||
|
if self._headers[column] == "name":
|
||||||
|
v = self._lst[row].name
|
||||||
|
return str(v)
|
||||||
|
elif self._headers[column] == "rk":
|
||||||
|
v = self._lst[row].rk
|
||||||
|
return f"{v:.4f}"
|
||||||
|
elif self._opt_data == "raw_data":
|
||||||
|
p = self._lst[row]
|
||||||
|
if self._headers[column] == "name":
|
||||||
|
if p.name == "":
|
||||||
|
return f"{p.rk:.4f}"
|
||||||
|
return f"{p.name}"
|
||||||
|
tmp_list = self._data.pollutants_list.copy()
|
||||||
|
tmp_list.remove("total_sediment")
|
||||||
|
tmp_list2 = self._data.pollutants_list.copy()
|
||||||
|
for pol in tmp_list:
|
||||||
|
pol_index = tmp_list2.index(pol)
|
||||||
|
if self._headers[column] == pol + " Concentration":
|
||||||
|
v = self._lst[row].get_ts_key(
|
||||||
|
self._timestamp, "pols")[pol_index][0]
|
||||||
|
return f"{v:.4f}"
|
||||||
|
if self._headers[column] == pol + " Temperature":
|
||||||
|
v = self._lst[row].get_ts_key(
|
||||||
|
self._timestamp, "pols")[pol_index][0]
|
||||||
|
return f"{v:.4f}"
|
||||||
|
if self._headers[column] == pol + " Mass":
|
||||||
|
if self._type_pol[pol_index] == 7:
|
||||||
|
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}"
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def set_timestamp(self, timestamp):
|
||||||
|
self._timestamp = timestamp
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
@ -527,14 +527,16 @@ class ResultsWindow(PamhyrWindow):
|
||||||
# self._additional_plot[plot].set_result(solver_id)
|
# self._additional_plot[plot].set_result(solver_id)
|
||||||
|
|
||||||
if timestamp is not None:
|
if timestamp is not None:
|
||||||
self.plot_xy.set_timestamp(timestamp)
|
self.plot_xy.set_timestamp_preserve_view(timestamp)
|
||||||
self.plot_ac.set_timestamp(timestamp)
|
self.plot_ac.set_timestamp_preserve_view(timestamp)
|
||||||
self.plot_rkc.set_timestamp(timestamp)
|
self.plot_rkc.set_timestamp_preserve_view(timestamp)
|
||||||
if tab_index == 2:
|
if tab_index == 2:
|
||||||
self.plot_h.set_timestamp(timestamp)
|
self.plot_h.set_timestamp_preserve_view(timestamp)
|
||||||
|
|
||||||
if tab_widget.currentIndex() > 2:
|
if tab_widget.currentIndex() > 2:
|
||||||
self._additional_plot[name].set_timestamp(timestamp)
|
self._additional_plot[name].set_timestamp_preserve_view(
|
||||||
|
timestamp
|
||||||
|
)
|
||||||
|
|
||||||
# for plot in self._additional_plot:
|
# for plot in self._additional_plot:
|
||||||
# self._additional_plot[plot].set_timestamp(timestamp)
|
# self._additional_plot[plot].set_timestamp(timestamp)
|
||||||
|
|
|
||||||
|
|
@ -532,12 +532,12 @@ class ResultsWindowAdisTS(PamhyrWindow):
|
||||||
self.plot_mdt.set_pollutant(self._current_pol_id)
|
self.plot_mdt.set_pollutant(self._current_pol_id)
|
||||||
|
|
||||||
if timestamp is not None:
|
if timestamp is not None:
|
||||||
self.plot_cdt.set_timestamp(timestamp)
|
self.plot_cdt.set_timestamp_preserve_view(timestamp)
|
||||||
self.plot_cdx.set_timestamp(timestamp)
|
self.plot_cdx.set_timestamp_preserve_view(timestamp)
|
||||||
self.plot_mdx.set_timestamp(timestamp)
|
self.plot_mdx.set_timestamp_preserve_view(timestamp)
|
||||||
self.plot_mdt.set_timestamp(timestamp)
|
self.plot_mdt.set_timestamp_preserve_view(timestamp)
|
||||||
self.plot_tdt.set_timestamp(timestamp)
|
self.plot_tdt.set_timestamp_preserve_view(timestamp)
|
||||||
self.plot_tdx.set_timestamp(timestamp)
|
self.plot_tdx.set_timestamp_preserve_view(timestamp)
|
||||||
|
|
||||||
self._table["raw_data"].set_timestamp(timestamp)
|
self._table["raw_data"].set_timestamp(timestamp)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,756 @@
|
||||||
|
# WindowAdisTT.py -- Pamhyr
|
||||||
|
# Copyright (C) 2023-2026 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.PlotSedAdis import PlotAdis_dx, PlotAdis_dt
|
||||||
|
|
||||||
|
from View.Results.CustomPlot.Plot import CustomPlot
|
||||||
|
from View.Results.CustomExport.CustomExportAdis import (
|
||||||
|
CustomExportAdisDialog,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Results.TableAdisTT import TableModel
|
||||||
|
from View.Results.translate import ResultsTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class ResultsWindowAdisTT(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "ResultsAdisTT"
|
||||||
|
_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
|
||||||
|
self.pollutant_label = ["None"]
|
||||||
|
|
||||||
|
pollutants_headers = self._results.pollutants_list.copy()
|
||||||
|
|
||||||
|
trad = ResultsTranslate(pollutants_headers)
|
||||||
|
name = (
|
||||||
|
trad[self._pamhyr_name] + " - "
|
||||||
|
+ study.name + " - "
|
||||||
|
+ self._solver.name
|
||||||
|
)
|
||||||
|
|
||||||
|
super(ResultsWindowAdisTT, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._hash_data.append(self._solver)
|
||||||
|
self._hash_data.append(self._results._repertory)
|
||||||
|
self._hash_data.append(self._results._name)
|
||||||
|
|
||||||
|
self._additional_plot = {}
|
||||||
|
self._current_pol_id = [1]
|
||||||
|
self._reach_id = 0
|
||||||
|
self._profile_id = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._timestamps = sorted(list(self._results.get("timestamps")))
|
||||||
|
self.set_type_pol()
|
||||||
|
self.setup_slider()
|
||||||
|
self.setup_table()
|
||||||
|
self.setup_plots()
|
||||||
|
self.setup_statusbar()
|
||||||
|
self.setup_connections()
|
||||||
|
self.update_table_selection_reach(self._reach_id)
|
||||||
|
self.update_table_selection_profile(self._profile_id)
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def set_type_pol(self):
|
||||||
|
self._type_pol = []
|
||||||
|
self._pol_id_dict = {}
|
||||||
|
tmp_list = self._results.river.reach(0).profiles
|
||||||
|
for pol_index in range(self._results.nb_pollutants):
|
||||||
|
pol_name = self._results.pollutants_list[pol_index]
|
||||||
|
if pol_name == "total_sediment":
|
||||||
|
self._type_pol.append(-1)
|
||||||
|
else:
|
||||||
|
self._type_pol.append(len(
|
||||||
|
tmp_list[0].get_ts_key(
|
||||||
|
self._timestamps[0], "pols")[pol_index])
|
||||||
|
)
|
||||||
|
self._pol_id_dict[pol_name] = pol_index
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
self._table = {}
|
||||||
|
for t in ["reach", "profile", "raw_data"]:
|
||||||
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
|
self._table[t] = TableModel(
|
||||||
|
self._type_pol,
|
||||||
|
table_view=table,
|
||||||
|
table_headers=self._trad.get_dict(f"table_headers_{t}"),
|
||||||
|
data=self._results,
|
||||||
|
undo=self._undo_stack,
|
||||||
|
opt_data=t,
|
||||||
|
)
|
||||||
|
self._table[t]._timestamp = self._timestamps[
|
||||||
|
self._slider_time.value()]
|
||||||
|
|
||||||
|
def setup_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)
|
||||||
|
|
||||||
|
self._icon_start = QIcon()
|
||||||
|
self._icon_start.addPixmap(
|
||||||
|
QPixmap(self._path_file("media-playback-start.png"))
|
||||||
|
)
|
||||||
|
|
||||||
|
self._icon_pause = QIcon()
|
||||||
|
self._icon_pause.addPixmap(
|
||||||
|
QPixmap(self._path_file("media-playback-pause.png"))
|
||||||
|
)
|
||||||
|
self._button_play = self.find(QPushButton, f"playButton")
|
||||||
|
self._button_play.setIcon(self._icon_start)
|
||||||
|
self._button_back = self.find(QPushButton, f"backButton")
|
||||||
|
self._button_next = self.find(QPushButton, f"nextButton")
|
||||||
|
self._button_first = self.find(QPushButton, f"firstButton")
|
||||||
|
self._button_last = self.find(QPushButton, f"lastButton")
|
||||||
|
self._timer = QTimer(self)
|
||||||
|
|
||||||
|
def setup_plots(self):
|
||||||
|
self.canvas_cdt = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_cdt.setObjectName("canvas_cdt")
|
||||||
|
self.toolbar_cdt = PamhyrPlotToolbar(
|
||||||
|
self.canvas_cdt, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_cdt = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_concentration_dt")
|
||||||
|
self.plot_layout_cdt.addWidget(self.toolbar_cdt)
|
||||||
|
self.plot_layout_cdt.addWidget(self.canvas_cdt)
|
||||||
|
|
||||||
|
self.plot_cdt = PlotAdis_dt(
|
||||||
|
canvas=self.canvas_cdt,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=self._reach_id,
|
||||||
|
profile_id=self._profile_id,
|
||||||
|
pol_id=self._current_pol_id,
|
||||||
|
key="T",
|
||||||
|
type_pol=self._type_pol,
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_cdt
|
||||||
|
)
|
||||||
|
self.plot_cdt.draw()
|
||||||
|
|
||||||
|
self.canvas_cdx = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_cdx.setObjectName("canvas_cdx")
|
||||||
|
self.toolbar_cdx = PamhyrPlotToolbar(
|
||||||
|
self.canvas_cdx, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_cdx = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_concentration_dx")
|
||||||
|
self.plot_layout_cdx.addWidget(self.toolbar_cdx)
|
||||||
|
self.plot_layout_cdx.addWidget(self.canvas_cdx)
|
||||||
|
|
||||||
|
self.plot_cdx = PlotAdis_dx(
|
||||||
|
canvas=self.canvas_cdx,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=self._reach_id,
|
||||||
|
profile_id=self._profile_id,
|
||||||
|
pol_id=self._current_pol_id,
|
||||||
|
key="T",
|
||||||
|
type_pol=self._type_pol,
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_cdx
|
||||||
|
)
|
||||||
|
self.plot_cdx.draw()
|
||||||
|
|
||||||
|
# The AdisTT window only displays temperature plots. The code below
|
||||||
|
# belongs to the sediment/pollutant result window and its layouts are
|
||||||
|
# intentionally absent from ResultsAdisTT.ui.
|
||||||
|
return
|
||||||
|
|
||||||
|
self.canvas_mdx = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_mdx.setObjectName("canvas_mdx")
|
||||||
|
self.toolbar_mdx = PamhyrPlotToolbar(
|
||||||
|
self.canvas_mdx, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_mdx = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_mass_dx2")
|
||||||
|
self.plot_layout_mdx.addWidget(self.toolbar_mdx)
|
||||||
|
self.plot_layout_mdx.addWidget(self.canvas_mdx)
|
||||||
|
|
||||||
|
self.plot_mdx = PlotAdis_dx(
|
||||||
|
canvas=self.canvas_mdx,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=self._reach_id,
|
||||||
|
profile_id=self._profile_id,
|
||||||
|
pol_id=self._current_pol_id,
|
||||||
|
key="M",
|
||||||
|
type_pol=self._type_pol,
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_mdx
|
||||||
|
)
|
||||||
|
|
||||||
|
self.plot_mdx.draw()
|
||||||
|
|
||||||
|
self.canvas_mdt = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_mdt.setObjectName("canvas_mdt")
|
||||||
|
self.toolbar_mdt = PamhyrPlotToolbar(
|
||||||
|
self.canvas_mdt, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_mdt = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_mass_dt2")
|
||||||
|
self.plot_layout_mdt.addWidget(self.toolbar_mdt)
|
||||||
|
self.plot_layout_mdt.addWidget(self.canvas_mdt)
|
||||||
|
|
||||||
|
self.plot_mdt = PlotAdis_dt(
|
||||||
|
canvas=self.canvas_mdt,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=self._reach_id,
|
||||||
|
profile_id=self._profile_id,
|
||||||
|
pol_id=self._current_pol_id,
|
||||||
|
key="M",
|
||||||
|
type_pol=self._type_pol,
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_mdt
|
||||||
|
)
|
||||||
|
|
||||||
|
self.plot_mdt.draw()
|
||||||
|
|
||||||
|
# Thickness
|
||||||
|
|
||||||
|
self.canvas_tdx = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_tdx.setObjectName("canvas_tdx")
|
||||||
|
self.toolbar_tdx = PamhyrPlotToolbar(
|
||||||
|
self.canvas_tdx, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_tdx = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_tdx")
|
||||||
|
self.plot_layout_tdx.addWidget(self.toolbar_tdx)
|
||||||
|
self.plot_layout_tdx.addWidget(self.canvas_tdx)
|
||||||
|
|
||||||
|
self.plot_tdx = PlotAdis_dx(
|
||||||
|
canvas=self.canvas_tdx,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=self._reach_id,
|
||||||
|
profile_id=self._profile_id,
|
||||||
|
pol_id=[0],
|
||||||
|
key="M",
|
||||||
|
type_pol=self._type_pol,
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_tdx
|
||||||
|
)
|
||||||
|
|
||||||
|
self.plot_tdx.draw()
|
||||||
|
|
||||||
|
self.canvas_tdt = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
self.canvas_tdt.setObjectName("canvas_tdt")
|
||||||
|
self.toolbar_tdt = PamhyrPlotToolbar(
|
||||||
|
self.canvas_tdt, self, items=[
|
||||||
|
"home", "move", "zoom", "save",
|
||||||
|
"iso", "back/forward"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.plot_layout_tdt = self.find(
|
||||||
|
QVBoxLayout, "verticalLayout_tdt")
|
||||||
|
self.plot_layout_tdt.addWidget(self.toolbar_tdt)
|
||||||
|
self.plot_layout_tdt.addWidget(self.canvas_tdt)
|
||||||
|
|
||||||
|
self.plot_tdt = PlotAdis_dt(
|
||||||
|
canvas=self.canvas_tdt,
|
||||||
|
results=self._results,
|
||||||
|
reach_id=self._reach_id,
|
||||||
|
profile_id=self._profile_id,
|
||||||
|
pol_id=[0],
|
||||||
|
key="M",
|
||||||
|
type_pol=self._type_pol,
|
||||||
|
trad=self._trad,
|
||||||
|
toolbar=self.toolbar_tdt
|
||||||
|
)
|
||||||
|
|
||||||
|
self.plot_tdt.draw()
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
try:
|
||||||
|
self._timer.stop()
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
|
super(ResultsWindowAdisTT, self).closeEvent(event)
|
||||||
|
|
||||||
|
def _compute_status_label(self):
|
||||||
|
return (self.text_bief() + " | " +
|
||||||
|
self.text_profile() + " | " +
|
||||||
|
self.text_time())
|
||||||
|
|
||||||
|
def text_bief(self):
|
||||||
|
# Reach
|
||||||
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
reach = self._study.river.enable_edges()[0]
|
||||||
|
else:
|
||||||
|
reach = self._study.river.enable_edges()[indexes[0].row()]
|
||||||
|
return f"{self._trad['reach']}: {reach.name}"
|
||||||
|
|
||||||
|
def text_profile(self):
|
||||||
|
# Reach
|
||||||
|
table = self.find(QTableView, f"tableView_reach")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) == 0:
|
||||||
|
reach = self._study.river.enable_edges()[0]
|
||||||
|
else:
|
||||||
|
reach = self._study.river.enable_edges()[indexes[0].row()]
|
||||||
|
# Profile
|
||||||
|
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.rk
|
||||||
|
return f"{self._trad['cross_section']}: {pname}"
|
||||||
|
|
||||||
|
def text_time(self):
|
||||||
|
# Timestamp
|
||||||
|
ts = self._timestamps[self._slider_time.value()]
|
||||||
|
|
||||||
|
t0 = datetime.fromtimestamp(0)
|
||||||
|
fts = str(
|
||||||
|
datetime.fromtimestamp(ts) - t0
|
||||||
|
)
|
||||||
|
fts = str(
|
||||||
|
datetime.fromtimestamp(ts) - t0
|
||||||
|
)
|
||||||
|
fts.replace("days", _translate("Results", "days"))\
|
||||||
|
.replace("day", _translate("Results", "day"))
|
||||||
|
return f"{self._trad['time']} : {fts} ({ts} sec)"
|
||||||
|
|
||||||
|
def text_pollutant(self):
|
||||||
|
# Pollutant
|
||||||
|
table = self.find(QTableView, f"tableView_pollutants")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
if len(indexes) != 0:
|
||||||
|
self.pollutant_label = [
|
||||||
|
self._results.pollutants_list[i.row()+1] for i in indexes
|
||||||
|
]
|
||||||
|
|
||||||
|
return (f"Pollutant: {', '.join(self.pollutant_label)}")
|
||||||
|
|
||||||
|
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,
|
||||||
|
# TODO "action_add": self._add_custom_plot,
|
||||||
|
"action_export": self.export,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.find(QAction, "action_add").setEnabled(False)
|
||||||
|
|
||||||
|
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,
|
||||||
|
"raw_data": self._set_current_profile_raw_data,
|
||||||
|
}
|
||||||
|
|
||||||
|
for t in ["reach", "profile"]:
|
||||||
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
|
|
||||||
|
table.selectionModel()\
|
||||||
|
.selectionChanged\
|
||||||
|
.connect(fun[t])
|
||||||
|
|
||||||
|
self._table[t].dataChanged.connect(fun[t])
|
||||||
|
|
||||||
|
self._slider_time.valueChanged.connect(self._set_current_timestamp)
|
||||||
|
self._button_play.setChecked(False)
|
||||||
|
self._button_play.clicked.connect(self._pause)
|
||||||
|
self._button_back.clicked.connect(self._back)
|
||||||
|
self._button_next.clicked.connect(self._next)
|
||||||
|
self._button_first.clicked.connect(self._first)
|
||||||
|
self._button_last.clicked.connect(self._last)
|
||||||
|
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"]:
|
||||||
|
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"]:
|
||||||
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
|
selectionModel = table.selectionModel()
|
||||||
|
index = table.model().index(ind[0] - 1, 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._reach_id = reach_id
|
||||||
|
self.plot_cdt.set_reach(reach_id)
|
||||||
|
self.plot_cdx.set_reach(reach_id)
|
||||||
|
|
||||||
|
self.update_table_selection_reach(reach_id)
|
||||||
|
self.update_table_selection_profile(0)
|
||||||
|
|
||||||
|
if profile_id is not None:
|
||||||
|
self._profile_id = profile_id
|
||||||
|
self.plot_cdt.set_profile(profile_id)
|
||||||
|
self.plot_cdx.set_profile(profile_id)
|
||||||
|
|
||||||
|
self.update_table_selection_profile(profile_id)
|
||||||
|
|
||||||
|
if pol_id is not None:
|
||||||
|
self._current_pol_id = [p+1 for p in pol_id] # rm total_sediment
|
||||||
|
self.plot_cdt.set_pollutant(self._current_pol_id)
|
||||||
|
self.plot_cdx.set_pollutant(self._current_pol_id)
|
||||||
|
|
||||||
|
if timestamp is not None:
|
||||||
|
self.plot_cdt.set_timestamp_preserve_view(timestamp)
|
||||||
|
self.plot_cdx.set_timestamp_preserve_view(timestamp)
|
||||||
|
|
||||||
|
self._table["raw_data"].set_timestamp(timestamp)
|
||||||
|
|
||||||
|
self.update_statusbar()
|
||||||
|
|
||||||
|
def _get_current_timestamp(self):
|
||||||
|
return self._timestamps[
|
||||||
|
self._slider_time.value()
|
||||||
|
]
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
self.update(profile_id=indexes[0].row())
|
||||||
|
|
||||||
|
def _set_current_pol(self):
|
||||||
|
table = self.find(QTableView, f"tableView_pollutants")
|
||||||
|
indexes = table.selectedIndexes()
|
||||||
|
rows = [i.row() for i in indexes]
|
||||||
|
if len(indexes) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.update(pol_id=rows)
|
||||||
|
|
||||||
|
def _set_current_profile_raw_data(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
def _set_current_timestamp(self):
|
||||||
|
timestamp = self._timestamps[self._slider_time.value()]
|
||||||
|
self.update(timestamp=timestamp)
|
||||||
|
|
||||||
|
def _reload_plots(self):
|
||||||
|
self.plot_cdt.results = self._results
|
||||||
|
self.plot_cdx.results = self._results
|
||||||
|
|
||||||
|
self.plot_cdt.draw()
|
||||||
|
self.plot_cdx.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):
|
||||||
|
# focus on raw data table
|
||||||
|
if self.find(QTabWidget, f"tabWidget").currentIndex() == 0:
|
||||||
|
table = self.find(QTableView, f"tableView_raw_data")
|
||||||
|
model = self._table["raw_data"]
|
||||||
|
|
||||||
|
coltext = []
|
||||||
|
for index in sorted(table.selectionModel().selectedRows()):
|
||||||
|
row = index.row()
|
||||||
|
rowtext = []
|
||||||
|
for column in range(model.columnCount()):
|
||||||
|
i = model.createIndex(row, column)
|
||||||
|
try:
|
||||||
|
rowtext.append(str(model.data(i)))
|
||||||
|
except AttributeError:
|
||||||
|
rowtext.append("")
|
||||||
|
coltext.append(rowtext)
|
||||||
|
|
||||||
|
self.copyTableIntoClipboard(coltext)
|
||||||
|
else:
|
||||||
|
logger.info("TODO: copy")
|
||||||
|
|
||||||
|
def _paste(self):
|
||||||
|
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):
|
||||||
|
|
||||||
|
pols = self._results.pollutants_list.copy()
|
||||||
|
dlg = CustomExportAdisDialog(pollutants=pols,
|
||||||
|
parent=self)
|
||||||
|
if dlg.exec():
|
||||||
|
x, y, pol = dlg.value
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.file_dialog(
|
||||||
|
select_file="AnyFile",
|
||||||
|
callback=lambda f: self.export_to(f[0], x, y, pol),
|
||||||
|
default_suffix=".csv",
|
||||||
|
file_filter=["CSV (*.csv)"],
|
||||||
|
)
|
||||||
|
|
||||||
|
def export_to(self, filename, x, y, pol):
|
||||||
|
timestamps = sorted(self._results.get("timestamps"))
|
||||||
|
reach = self._results.river.reachs[self._reach_id]
|
||||||
|
first_line = [f"Study: {self._results.study.name}",
|
||||||
|
f"Reach: {reach.name}"]
|
||||||
|
if x == "rk":
|
||||||
|
timestamp = self._get_current_timestamp()
|
||||||
|
first_line.append(f"Time: {timestamp}s")
|
||||||
|
val_dict = self._export_rk(timestamp, y, pol)
|
||||||
|
elif x == "time":
|
||||||
|
profile = reach.profile(self._profile_id)
|
||||||
|
pname = profile.name if profile.name != "" else profile.rk
|
||||||
|
first_line.append(f"Profile: {pname}")
|
||||||
|
val_dict = self._export_time(self._profile_id, y, pol)
|
||||||
|
with open(filename, 'w', newline='') as csvfile:
|
||||||
|
writer = csv.writer(csvfile, delimiter=',',
|
||||||
|
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||||
|
dict_x = self._trad.get_dict("values_x")
|
||||||
|
header = []
|
||||||
|
writer.writerow(first_line)
|
||||||
|
for text in val_dict.keys():
|
||||||
|
header.append(text)
|
||||||
|
writer.writerow(header)
|
||||||
|
for row in range(len(val_dict[dict_x[x]])):
|
||||||
|
line = []
|
||||||
|
for var in val_dict.keys():
|
||||||
|
line.append(val_dict[var][row])
|
||||||
|
writer.writerow(line)
|
||||||
|
|
||||||
|
def _export_rk(self, timestamp, y, pol):
|
||||||
|
reach = self._results.river.reachs[self._reach_id]
|
||||||
|
dict_x = self._trad.get_dict("values_x")
|
||||||
|
dict_y = self._trad.get_dict("values_y_pol")
|
||||||
|
my_dict = {}
|
||||||
|
my_dict[dict_x["rk"]] = reach.geometry.get_rk()
|
||||||
|
val_id = {}
|
||||||
|
val_id["unit_C"] = 0
|
||||||
|
val_id["unit_M"] = 2
|
||||||
|
val_id["unit_thickness"] = 2
|
||||||
|
for unit in y:
|
||||||
|
if unit == "unit_thickness":
|
||||||
|
pol_id = 0
|
||||||
|
else:
|
||||||
|
pol_id = self._pol_id_dict[pol]
|
||||||
|
if unit == "unit_M" and self._type_pol[pol_id] == 1:
|
||||||
|
my_dict[dict_y[unit]] = [0.0]*len(reach.profiles)
|
||||||
|
else:
|
||||||
|
my_dict[dict_y[unit]] = list(map(lambda p:
|
||||||
|
p.get_ts_key(
|
||||||
|
timestamp, "pols"
|
||||||
|
)[pol_id][val_id[unit]],
|
||||||
|
reach.profiles))
|
||||||
|
|
||||||
|
return my_dict
|
||||||
|
|
||||||
|
def _export_time(self, profile, y, pol):
|
||||||
|
reach = self._results.river.reachs[self._reach_id]
|
||||||
|
profile = reach.profile(profile)
|
||||||
|
ts = list(self._results.get("timestamps"))
|
||||||
|
ts.sort()
|
||||||
|
dict_x = self._trad.get_dict("values_x")
|
||||||
|
dict_y = self._trad.get_dict("values_y_pol")
|
||||||
|
my_dict = {}
|
||||||
|
my_dict[dict_x["time"]] = ts
|
||||||
|
val_id = {}
|
||||||
|
val_id["unit_C"] = 0
|
||||||
|
val_id["unit_M"] = 2
|
||||||
|
val_id["unit_thickness"] = 2
|
||||||
|
for unit in y:
|
||||||
|
if unit == "unit_thickness":
|
||||||
|
pol_id = 0
|
||||||
|
else:
|
||||||
|
pol_id = self._pol_id_dict[pol]
|
||||||
|
if unit == "unit_M" and self._type_pol[pol_id] == 1:
|
||||||
|
my_dict[dict_y[unit]] = [0.0]*len(ts)
|
||||||
|
else:
|
||||||
|
my_dict[dict_y[unit]] = list(map(lambda data_el:
|
||||||
|
data_el[pol_id][val_id[unit]],
|
||||||
|
profile.get_key("pols")
|
||||||
|
))
|
||||||
|
|
||||||
|
return my_dict
|
||||||
|
|
@ -121,8 +121,11 @@ class ResultsTranslate(MainTranslate):
|
||||||
}
|
}
|
||||||
tmp = self._sub_dict["table_headers_raw_data"]
|
tmp = self._sub_dict["table_headers_raw_data"]
|
||||||
for pol in self.pollutants:
|
for pol in self.pollutants:
|
||||||
tmp[pol + " Concentration"] = pol + "\n Concentration"
|
if pol == "TEM":
|
||||||
tmp[pol + " Mass"] = pol + "\n Mass"
|
tmp[pol + " Temperature"] = "Temperature (°C)"
|
||||||
|
else:
|
||||||
|
tmp[pol + " Concentration"] = pol + "\n Concentration"
|
||||||
|
tmp[pol + " Mass"] = pol + "\n Mass"
|
||||||
else:
|
else:
|
||||||
self._sub_dict["table_headers_raw_data"] = {
|
self._sub_dict["table_headers_raw_data"] = {
|
||||||
"name": _translate("Results", "Profile"),
|
"name": _translate("Results", "Profile"),
|
||||||
|
|
@ -146,6 +149,7 @@ class ResultsTranslate(MainTranslate):
|
||||||
|
|
||||||
self._sub_dict["values_y_pol"] = {
|
self._sub_dict["values_y_pol"] = {
|
||||||
"unit_C": self._dict["unit_concentration"],
|
"unit_C": self._dict["unit_concentration"],
|
||||||
|
"unit_T": self._dict["unit_temperature"],
|
||||||
"unit_M": self._dict["unit_mass"],
|
"unit_M": self._dict["unit_mass"],
|
||||||
"unit_thickness": self._dict["unit_thickness"],
|
"unit_thickness": self._dict["unit_thickness"],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ class SelectSolverWindowAdisTS(PamhyrDialog):
|
||||||
# solvers = self._config.solvers
|
# solvers = self._config.solvers
|
||||||
# solvers mage
|
# solvers mage
|
||||||
solvers = list(filter(
|
solvers = list(filter(
|
||||||
lambda x: "mage" not in x._type and "rubar" not in x._type,
|
lambda x: "adists" in x._type.lower(),
|
||||||
self._config.solvers
|
self._config.solvers
|
||||||
))
|
))
|
||||||
solvers_name = list(
|
solvers_name = list(
|
||||||
|
|
@ -94,7 +94,8 @@ class SelectSolverWindowAdisTS(PamhyrDialog):
|
||||||
)
|
)
|
||||||
|
|
||||||
solvers_mage = list(filter(
|
solvers_mage = list(filter(
|
||||||
lambda x: "mage" or "rubar" in x._type.lower(),
|
lambda x: ("mage" in x._type.lower() or
|
||||||
|
"rubar" in x._type.lower()),
|
||||||
self._config.solvers
|
self._config.solvers
|
||||||
))
|
))
|
||||||
solvers_mage_names = list(map(lambda x: x._name, solvers_mage))
|
solvers_mage_names = list(map(lambda x: x._name, solvers_mage))
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ class SelectSolverWindowAdisTT(PamhyrDialog):
|
||||||
# solvers = self._config.solvers
|
# solvers = self._config.solvers
|
||||||
# solvers mage
|
# solvers mage
|
||||||
solvers = list(filter(
|
solvers = list(filter(
|
||||||
lambda x: "mage" not in x._type and "rubar" not in x._type,
|
lambda x: "adistt" in x._type.lower(),
|
||||||
self._config.solvers
|
self._config.solvers
|
||||||
))
|
))
|
||||||
solvers_name = list(
|
solvers_name = list(
|
||||||
|
|
@ -94,7 +94,8 @@ class SelectSolverWindowAdisTT(PamhyrDialog):
|
||||||
)
|
)
|
||||||
|
|
||||||
solvers_mage = list(filter(
|
solvers_mage = list(filter(
|
||||||
lambda x: "mage" or "rubar" in x._type.lower(),
|
lambda x: ("mage" in x._type.lower() or
|
||||||
|
"rubar" in x._type.lower()),
|
||||||
self._config.solvers
|
self._config.solvers
|
||||||
))
|
))
|
||||||
solvers_mage_names = list(map(lambda x: x._name, solvers_mage))
|
solvers_mage_names = list(map(lambda x: x._name, solvers_mage))
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,18 @@ class PamhyrPlot(APlot):
|
||||||
def table(self):
|
def table(self):
|
||||||
return self._table
|
return self._table
|
||||||
|
|
||||||
|
def set_timestamp_preserve_view(self, timestamp):
|
||||||
|
"""Change result frame without resetting the current zoom."""
|
||||||
|
x_limits = self.canvas.axes.get_xlim()
|
||||||
|
y_limits = self.canvas.axes.get_ylim()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.set_timestamp(timestamp)
|
||||||
|
finally:
|
||||||
|
self.canvas.axes.set_xlim(x_limits)
|
||||||
|
self.canvas.axes.set_ylim(y_limits)
|
||||||
|
self.canvas.draw_idle()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def label_x(self):
|
def label_x(self):
|
||||||
"""Plot X axes label"""
|
"""Plot X axes label"""
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ class MplCanvas(FigureCanvasQTAgg):
|
||||||
layout='constrained',
|
layout='constrained',
|
||||||
)
|
)
|
||||||
super(MplCanvas, self).__init__(fig)
|
super(MplCanvas, self).__init__(fig)
|
||||||
|
self.setMinimumSize(1, 1)
|
||||||
|
|
||||||
self.axes = fig.add_subplot(111)
|
self.axes = fig.add_subplot(111)
|
||||||
self.axes.format_coord = lambda x, y: (
|
self.axes.format_coord = lambda x, y: (
|
||||||
|
|
@ -38,6 +39,13 @@ class MplCanvas(FigureCanvasQTAgg):
|
||||||
self.axes.spines[['top', 'right']].set_color('none')
|
self.axes.spines[['top', 'right']].set_color('none')
|
||||||
self.add_arrows()
|
self.add_arrows()
|
||||||
|
|
||||||
|
def resizeEvent(self, event):
|
||||||
|
"""Ignore transient invalid sizes produced by hidden Qt tabs."""
|
||||||
|
if self.width() <= 0 or self.height() <= 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
super(MplCanvas, self).resizeEvent(event)
|
||||||
|
|
||||||
def add_arrows(self):
|
def add_arrows(self):
|
||||||
al = 8.
|
al = 8.
|
||||||
arrowprops = dict(
|
arrowprops = dict(
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,11 @@ class MainTranslate(UnitTranslate):
|
||||||
"MainWindow",
|
"MainWindow",
|
||||||
"Results folder does not correspond to a Pamhyr2 solver name"
|
"Results folder does not correspond to a Pamhyr2 solver name"
|
||||||
)
|
)
|
||||||
|
self._dict["mb_results_solver_mode_mismatch"] = _translate(
|
||||||
|
"MainWindow",
|
||||||
|
"The folder belongs to solver '{solver}',\nwhich is not an "
|
||||||
|
"{mode} solver"
|
||||||
|
)
|
||||||
self._dict["mb_results_bin_not_found"] = _translate(
|
self._dict["mb_results_bin_not_found"] = _translate(
|
||||||
"MainWindow", "Results binary files not found"
|
"MainWindow", "Results binary files not found"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -56,16 +56,22 @@ class EditWeatherParametersWindow(PamhyrWindow):
|
||||||
self._data = data
|
self._data = data
|
||||||
|
|
||||||
trad = WPETranslate()
|
trad = WPETranslate()
|
||||||
name = trad[self._pamhyr_name]
|
# name = trad[self._pamhyr_name]
|
||||||
if self._data is not None:
|
if self._data is not None:
|
||||||
edge_name = (self._data.reach.name if self._data.reach is not None
|
edge_name = (self._data.reach.name if self._data.reach is not None
|
||||||
else trad['not_associated'])
|
else trad['not_associated'])
|
||||||
name += (
|
parameter_type = trad.get_dict("long_types").get(
|
||||||
f" - {study.name} " +
|
self._data.type,
|
||||||
f" - {self._data.name} ({self._data.id}) " +
|
self._data.type,
|
||||||
# f"({trad.get_dict('long_types')[self._data.type]} - " +
|
|
||||||
f"{edge_name})"
|
|
||||||
)
|
)
|
||||||
|
begin_rk = (self._format_rk(self._data.begin_rk)
|
||||||
|
if self._data.begin_section is not None
|
||||||
|
else trad['not_associated'])
|
||||||
|
end_rk = (self._format_rk(self._data.end_rk)
|
||||||
|
if self._data.end_section is not None
|
||||||
|
else trad['not_associated'])
|
||||||
|
name = (f"{parameter_type} - {edge_name} - "
|
||||||
|
f"PK {begin_rk} → {end_rk}")
|
||||||
|
|
||||||
super(EditWeatherParametersWindow, self).__init__(
|
super(EditWeatherParametersWindow, self).__init__(
|
||||||
title=name,
|
title=name,
|
||||||
|
|
@ -81,6 +87,12 @@ class EditWeatherParametersWindow(PamhyrWindow):
|
||||||
self.setup_plot()
|
self.setup_plot()
|
||||||
self.setup_connections()
|
self.setup_connections()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _format_rk(rk):
|
||||||
|
if isinstance(rk, (int, float)):
|
||||||
|
return f"{rk:g}"
|
||||||
|
return str(rk)
|
||||||
|
|
||||||
def setup_table(self):
|
def setup_table(self):
|
||||||
self._delegate_time = PamhyrExTimeDelegate(
|
self._delegate_time = PamhyrExTimeDelegate(
|
||||||
data=self._data,
|
data=self._data,
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,16 @@ class WeatherParametersTableDefaultModel(PamhyrTableModel):
|
||||||
|
|
||||||
return QVariant()
|
return QVariant()
|
||||||
|
|
||||||
|
def headerData(self, section, orientation, role):
|
||||||
|
if (orientation == Qt.Orientation.Horizontal and
|
||||||
|
self._headers[section] == "value" and
|
||||||
|
role == Qt.ItemDataRole.ToolTipRole):
|
||||||
|
return self._trad["default_values_tooltip"]
|
||||||
|
|
||||||
|
return super(WeatherParametersTableDefaultModel, self).headerData(
|
||||||
|
section, orientation, role
|
||||||
|
)
|
||||||
|
|
||||||
def setData(self, index, value, role=Qt.EditRole):
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
if not index.isValid() or role != Qt.EditRole:
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
|
|
@ -128,9 +128,19 @@ class WeatherParametersWindow(PamhyrWindow):
|
||||||
toolBar.addAction(self.action_delete)
|
toolBar.addAction(self.action_delete)
|
||||||
toolBar.addAction(self.action_edit)
|
toolBar.addAction(self.action_edit)
|
||||||
|
|
||||||
|
self.time_series_info = QLabel(
|
||||||
|
self._trad["time_series_unavailable"]
|
||||||
|
)
|
||||||
|
self.time_series_info.setWordWrap(True)
|
||||||
|
layout.addWidget(self.time_series_info)
|
||||||
layout.addWidget(self.table_spec_title)
|
layout.addWidget(self.table_spec_title)
|
||||||
layout.addWidget(self.table_spec)
|
layout.addWidget(self.table_spec)
|
||||||
|
|
||||||
|
selected_type = self._wp_acronyms[
|
||||||
|
self._selected_default_row_index
|
||||||
|
]
|
||||||
|
self.update_time_series_info(selected_type)
|
||||||
|
|
||||||
def setup_table(self):
|
def setup_table(self):
|
||||||
self.table_default = self.find(QTableView, f"tableView")
|
self.table_default = self.find(QTableView, f"tableView")
|
||||||
|
|
||||||
|
|
@ -249,6 +259,7 @@ class WeatherParametersWindow(PamhyrWindow):
|
||||||
self.enable_actions(tab_enabled)
|
self.enable_actions(tab_enabled)
|
||||||
|
|
||||||
self.update_table_spec_title(enabled=tab_enabled)
|
self.update_table_spec_title(enabled=tab_enabled)
|
||||||
|
self.update_time_series_info(type_selected)
|
||||||
|
|
||||||
self._table_spec.update_tab_spec(
|
self._table_spec.update_tab_spec(
|
||||||
type=type_selected, enabled=tab_enabled
|
type=type_selected, enabled=tab_enabled
|
||||||
|
|
@ -256,6 +267,12 @@ class WeatherParametersWindow(PamhyrWindow):
|
||||||
|
|
||||||
return self._selected_default_row_index
|
return self._selected_default_row_index
|
||||||
|
|
||||||
|
def update_time_series_info(self, parameter_type):
|
||||||
|
if hasattr(self, "time_series_info"):
|
||||||
|
self.time_series_info.setVisible(
|
||||||
|
parameter_type in {"ALB", "SC", "CCF"}
|
||||||
|
)
|
||||||
|
|
||||||
def enable_actions(self, enabled):
|
def enable_actions(self, enabled):
|
||||||
if hasattr(self, "action_add"):
|
if hasattr(self, "action_add"):
|
||||||
self.action_add.setEnabled(enabled)
|
self.action_add.setEnabled(enabled)
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,24 @@ class WeatherParametersTranslate(MainTranslate):
|
||||||
|
|
||||||
self._dict["Weather parameters"] = _translate(
|
self._dict["Weather parameters"] = _translate(
|
||||||
"WeatherParameters", "Weather parameters")
|
"WeatherParameters", "Weather parameters")
|
||||||
|
self._dict["time_series_unavailable"] = _translate(
|
||||||
|
"WeatherParameters",
|
||||||
|
"Time series are not available for this parameter type."
|
||||||
|
)
|
||||||
|
self._dict["default_values"] = _translate(
|
||||||
|
"WeatherParameters", "Default values"
|
||||||
|
)
|
||||||
|
self._dict["default_values_tooltip"] = _translate(
|
||||||
|
"WeatherParameters",
|
||||||
|
"These values are applied to sections that have not been "
|
||||||
|
"defined using time series."
|
||||||
|
)
|
||||||
|
|
||||||
self._dict["rk"] = self._dict["unit_rk"]
|
self._dict["rk"] = self._dict["unit_rk"]
|
||||||
|
|
||||||
self._sub_dict["table_headers"] = {
|
self._sub_dict["table_headers"] = {
|
||||||
"name": self._dict["name"],
|
"name": self._dict["name"],
|
||||||
"value": self._dict["value"]
|
"value": self._dict["default_values"]
|
||||||
}
|
}
|
||||||
|
|
||||||
self._sub_dict["table_headers_spec"] = {
|
self._sub_dict["table_headers_spec"] = {
|
||||||
|
|
@ -62,3 +74,13 @@ class WeatherParametersTranslate(MainTranslate):
|
||||||
"cloud_cover_fraction": _translate("WeatherParameters",
|
"cloud_cover_fraction": _translate("WeatherParameters",
|
||||||
"Cloud Cover Fraction"),
|
"Cloud Cover Fraction"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
weather_parameters = self._sub_dict["weather_parameters"]
|
||||||
|
self._sub_dict["long_types"] = {
|
||||||
|
"AT": weather_parameters["air_temperature"],
|
||||||
|
"SH": weather_parameters["specific_humidity"],
|
||||||
|
"GR": weather_parameters["global_radiation"],
|
||||||
|
"RWS": weather_parameters["reference_wind_speed"],
|
||||||
|
"GT": weather_parameters["surface_temperature"],
|
||||||
|
"GFR": weather_parameters["surface_flow_rate"]
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@
|
||||||
<addaction name="action_menu_open_results_from_file"/>
|
<addaction name="action_menu_open_results_from_file"/>
|
||||||
<addaction name="action_menu_compare_scenarios_results"/>
|
<addaction name="action_menu_compare_scenarios_results"/>
|
||||||
<addaction name="action_menu_open_results_adists"/>
|
<addaction name="action_menu_open_results_adists"/>
|
||||||
|
<addaction name="action_menu_open_results_adistt"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menu_help">
|
<widget class="QMenu" name="menu_help">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
|
@ -863,6 +864,14 @@
|
||||||
<string>Run AdisTT</string>
|
<string>Run AdisTT</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_menu_open_results_adistt">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Open results temperature</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,265 @@
|
||||||
|
<?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>1410</width>
|
||||||
|
<height>821</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="1" 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>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="4" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="firstButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/media-skip-backward.png</normaloff>ressources/media-skip-backward.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="backButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/media-seek-backward.png</normaloff>ressources/media-seek-backward.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="playButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/player_play.png</normaloff>
|
||||||
|
<normalon>ressources/player_pause.png</normalon>ressources/player_play.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="nextButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/media-seek-forward.png</normaloff>ressources/media-seek-forward.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="lastButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/media-skip-forward.png</normaloff>ressources/media-skip-forward.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="horizontalSlider_time">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>1</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="Temperature">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Temperature</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabWidget_c">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab_cdx">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Temperature dx</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_17">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_concentration_dx"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_cdt">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Temperature dt</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_18">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_concentration_dt"/>
|
||||||
|
</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>1410</width>
|
||||||
|
<height>20</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/>
|
||||||
|
<buttongroups>
|
||||||
|
<buttongroup name="buttonGroup"/>
|
||||||
|
<buttongroup name="buttonGroup_2"/>
|
||||||
|
</buttongroups>
|
||||||
|
</ui>
|
||||||
Loading…
Reference in New Issue