Merge branch 'scenario-dev-pa' into scenarios

scenarios
Pierre-Antoine 2025-10-31 09:14:50 +01:00
commit d31be61af8
15 changed files with 654 additions and 249 deletions

View File

@ -582,10 +582,10 @@ class BoundaryCondition(SQLSubModel):
self._data.index(bc)
def get_i(self, index):
if len(self.data) == 0:
if len(self._data) == 0:
return None
return self.data[index]
return self._data[index]
def get_range(self, _range):
lst = []

View File

@ -52,6 +52,9 @@ class Results(SQLSubModel):
"study_revision": study.status.version,
}
if solver is not None:
self.set("solver_type", solver._type)
@property
def date(self):
date = self._meta_data["creation_date"]
@ -112,7 +115,10 @@ class Results(SQLSubModel):
)
""")
return True
if ext != "":
return True
return cls._create_submodel(execute)
@classmethod
def _db_update(cls, execute, version, data=None):
@ -147,7 +153,7 @@ class Results(SQLSubModel):
)
if table is None:
yield new
yield
if len(table) > 1:
logger.warning("Multiple results for this scenario")
@ -178,23 +184,33 @@ class Results(SQLSubModel):
data["timestamps"] = sorted(ts)
new_results._river = River._db_load(execute, data)
new = new_results
yield (solver_type, new_results)
yield new
def _db_save_clear(self, execute, solver_type, data=None):
old_pid = execute(
"SELECT pamhyr_id FROM results " +
f"WHERE scenario = {self._owner_scenario} " +
f"AND solver_type = '{solver_type}'"
)
if len(old_pid) != 0:
for pid in old_pid:
pid = pid[0]
execute(
"DELETE FROM results " +
f"WHERE scenario = {self._owner_scenario} " +
f"AND solver_type = '{solver_type}'"
)
execute(
"DELETE FROM results_data " +
f"WHERE scenario = {self._owner_scenario} " +
f"AND result = {pid}"
)
def _db_save(self, execute, data=None):
if self._status.scenario.id != self._owner_scenario:
return
execute(
"DELETE FROM results " +
f"WHERE scenario = {self._owner_scenario}"
)
execute(
"DELETE FROM results_data " +
f"WHERE scenario = {self._owner_scenario}"
)
pid = self._pamhyr_id
if self._solver is None:
solver_name = self.get("solver_name")
@ -203,6 +219,8 @@ class Results(SQLSubModel):
solver_name = self._solver._name
solver_type = self._solver._type
self._db_save_clear(execute, solver_type, data=data)
ts = sorted(self.get("timestamps"))
sf = ">" + ''.join(itertools.repeat("d", len(ts)))

View File

@ -227,7 +227,7 @@ class Profile(SQLSubModel):
values = list(map(float, values))
sf = ">" + ''.join(itertools.repeat("f", len(values)))
len_values = len(values)
elif key is "sl":
elif key == "sl":
# HACK: Some dirty code to transforme list of list of
# tuple to list of values and ensure the values is
# float type...

View File

@ -505,7 +505,7 @@ class River(Graph):
self._D90AdisTS = D90AdisTSList(status=self._status)
self._DIFAdisTS = DIFAdisTSList(status=self._status)
self._results = None
self._results = {}
@classmethod
def _db_create(cls, execute):
@ -620,7 +620,10 @@ class River(Graph):
return new
def _db_load_results(self, execute, data=None):
self._results = Results._db_load(execute, data)
results_lst = Results._db_load(execute, data)
for solv_type, results in results_lst:
self._results[solv_type] = results
def _db_save(self, execute, data=None):
self._db_save_delete_artefact(execute, data)
@ -647,8 +650,8 @@ class River(Graph):
objs.append(self._D90AdisTS)
objs.append(self._DIFAdisTS)
if self.results is not None:
objs.append(self.results)
for solv_type in self.results:
objs.append(self.results[solv_type])
self._save_submodel(execute, objs, data)
return True
@ -902,7 +905,9 @@ Last export at: @date."""
@results.setter
def results(self, results):
self._results = results
solv_type = results.get("solver_type")
self._results[solv_type] = results
def _split_reach(self, reach, profile):
node1 = reach.node1

View File

@ -276,7 +276,7 @@ class Scenario(SQLSubModel):
if self.id != 0:
srep = os.path.join(
self.parent.workdir(),
"senario_" + str(self.id)
"scenario_" + str(self.id)
)
return srep

View File

@ -44,7 +44,10 @@ class Study(SQLModel):
River,
]
def __init__(self, filename=None, init_new=True):
def __init__(self, filename=None, init_new=True, copy=False):
if copy:
return
# Metadata
self.creation_date = datetime.now()
self.last_modification_date = datetime.now()
@ -476,31 +479,8 @@ class Study(SQLModel):
return new
def reload_from_scenario(self, scenario):
if scenario in self._river_scenario_cache:
self._river = self._river_scenario_cache[scenario]
self.status.scenario = scenario
else:
def sql_exec(sql):
return self.execute(
sql, fetch_one=False, commit=True
)
self.status.scenario = scenario
data = {
"status": self.status,
"loaded_pid": set(),
"scenario": scenario
}
# Reload river data
river = River._db_load(
sql_exec, data=data
)
data["study"] = self
river._db_load_results(sql_exec, data=data)
self._river_scenario_cache[scenario] = river
self._river = river
river = self.load_scenario(scenario)
self._river = river
if reduce(
lambda a, s: a or (s.parent is scenario),
@ -511,6 +491,80 @@ class Study(SQLModel):
else:
self.status.set_as_editable()
def load_scenario(self, scenario):
if scenario in self._river_scenario_cache:
return self._river_scenario_cache[scenario]
def sql_exec(sql):
return self.execute(
sql, fetch_one=False, commit=True
)
old_scenario = self.status.scenario
self.status.scenario = scenario
data = {
"status": self.status,
"loaded_pid": set(),
"scenario": scenario
}
# Load river data
river = River._db_load(
sql_exec, data=data
)
data["study"] = self
river._db_load_results(sql_exec, data=data)
self._river_scenario_cache[scenario] = river
self.status.scenario = old_scenario
return river
def copy_from_scenario(self, scenario):
new = self._copy()
new._river = self.load_scenario(scenario)
def set_status(obj):
obj._status = new.status
new.river._data_traversal(
modifier=lambda obj, data: set_status(obj),
)
return new
def _copy(self):
"""
This method make a copy of current study. This copy is like an
empty shell, it's not fully functional. Study object use
SQLite connection to file, this copy as no valid connection.
(!) Please use this copy as read only object!
"""
new = Study(copy=True)
new._filename = ""
new.creation_date = self.creation_date
new.last_modification_date = self.last_modification_date
new.last_save_date = self.last_save_date
new._name = self._name
new.description = self.description
new._time_system = self._time_system
new._date = self._date
new.status = StudyStatus()
new.scenarios = self.scenarios
new.status.scenario = self.status.scenario
new._river = self._river
new._river_scenario_cache = self._river_scenario_cache
return new
def duplicate_current_scenario(self):
source = self.status.scenario_id
new = self.scenarios.new(

View File

@ -177,15 +177,15 @@ class Mage(CommandLineSolver):
return lst
def input_param(self):
name = self._study.name
name = self._study.name.replace(" ", "_")
return f"{name}.REP"
def output_param(self):
name = self._study.name
name = self._study.name.replace(" ", "_")
return f"{name}.BIN"
def log_file(self):
name = self._study.name
name = self._study.name.replace(" ", "_")
return f"{name}.TRA"
def _export_REP_additional_lines(self, study, rep_file):
@ -819,7 +819,8 @@ class Mage(CommandLineSolver):
repertory=repertory,
name=name,
)
fname = os.path.join(repertory, f"{name}.BIN")
fname = os.path.join(repertory, f"{name}.BIN".replace(" ", "_"))
if not os.path.isfile(fname):
logger.info(f"Result file {name}.BIN does not exist")
return None
@ -1374,6 +1375,7 @@ class Mage8(Mage):
results = super(Mage8, self).results(study, repertory, qlog, name=name)
if results is None:
return None
if with_gra:
self.read_gra(study, repertory, results, qlog, name=name)

View File

@ -58,7 +58,7 @@ logger = logging.getLogger()
class TableModel(PamhyrTableModel):
def get_true_data_row(self, row):
bc = self._data.get_i(row)
bc = self._data.data[row]
return next(
map(
@ -83,6 +83,7 @@ class TableModel(PamhyrTableModel):
value = QVariant()
if 0 <= column < 2:
row = self.get_true_data_row(row)
v = self._data.get_i(row)[column]
if self._data.get_type_column(column) == float:
if type(v) is str:
@ -106,13 +107,16 @@ class TableModel(PamhyrTableModel):
column = index.column()
try:
row = self.get_true_data_row(row)
self._undo.push(
SetDataCommand(
self._data, row, column, value
self._data, row,
column, value
)
)
except Exception as e:
logger.info(e)
logger.warning(e)
logger.debug(traceback.format_exc())
self.update()

View File

@ -83,13 +83,13 @@ class AddCommand(QUndoCommand):
self._new = None
def undo(self):
self._data.delete_i([self._index])
self._new.set_as_deleted()
def redo(self):
if self._new is None:
self._new = self._data.add(self._index)
else:
self._data.insert(self._index, self._new)
self._new.set_as_not_deleted()
class DelCommand(QUndoCommand):
@ -101,15 +101,16 @@ class DelCommand(QUndoCommand):
self._bc = []
for row in rows:
self._bc.append((row, self._data.get_i(row)))
self._bc.append(self._data.get_i(row))
self._bc.sort()
def undo(self):
for row, el in self._bc:
self._data.insert(row, el)
for el in self._bc:
el.set_as_not_deleted()
def redo(self):
self._data.delete_i(self._rows)
for el in self._bc:
el.set_as_deleted()
class SortCommand(QUndoCommand):

View File

@ -32,7 +32,7 @@ from platformdirs import user_cache_dir
from Solver.AdisTS import AdisTS
from Solver.Mage import Mage8
from Solver.RubarBE import Rubar3
from tools import logger_exception, pamhyr_db_need_update
from tools import logger_exception, pamhyr_db_need_update, timer
from PyQt5 import QtGui
from PyQt5.QtGui import (
@ -84,10 +84,12 @@ from View.SolverParameters.Window import SolverParametersWindow
from View.RunSolver.Window import (
SelectSolverWindow,
SolverLogWindow,
CompareSolversWindow
)
from View.Results.Window import ResultsWindow
from View.Results.CompareDialog import (
CompareSolversWindow, CompareScenariosWindow
)
from View.RunSolver.WindowAdisTS import (
SelectSolverWindowAdisTS,
@ -128,8 +130,8 @@ no_model_action = [
model_action = [
"action_menu_close", "action_menu_edit", "action_menu_save",
"action_menu_save_as", "action_toolBar_close", "action_toolBar_save",
"action_menu_numerical_parameter", "action_open_results_from_file",
"action_open_results_adists",
"action_menu_numerical_parameter", "action_menu_open_results_from_file",
"action_menu_open_results_adists",
]
other_model_action = [
@ -150,8 +152,10 @@ define_model_action = [
"action_menu_run_solver", "action_menu_sediment_layers",
"action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
"action_menu_edit_hydraulic_structures", "action_menu_additional_file",
"action_menu_results_last", "action_open_results_from_file",
"action_compare_results", "action_menu_boundary_conditions_sediment",
"action_menu_results_last", "action_menu_open_results_from_file",
# "action_menu_compare_results",
"action_menu_compare_scenarios_results",
"action_menu_boundary_conditions_sediment",
"action_menu_rep_additional_lines", "action_menu_output_rk",
"action_menu_run_adists", "action_menu_pollutants",
"action_menu_d90", "action_menu_dif",
@ -296,9 +300,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
"action_menu_rep_additional_lines": self.open_rep_lines,
"action_menu_close": self.close_model,
"action_menu_results_last": self.open_last_results,
"action_open_results_from_file": self.open_results_from_file,
"action_compare_results": self.compare_results,
"action_open_results_adists": self.open_results_adists,
"action_menu_open_results_from_file": self.open_results_from_file,
# "action_menu_compare_results": self.compare_results,
"action_menu_compare_scenarios_results":
self.compare_results_scenarios,
"action_menu_open_results_adists": self.open_results_adists,
# Help
"action_menu_pamhyr_users_wiki": self.open_doc_user,
"action_menu_pamhyr_developers_pdf":
@ -596,7 +602,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if self._study is None:
return None
return self._study.results
results = self._study.results
if self._last_solver._type in results:
return self._study.results[self._last_solver._type]
return None
@last_results.setter
def last_results(self, results):
@ -1507,7 +1517,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
return False
def open_solver_results(self, solver, results=None):
logger.info(f"{solver} {results}")
logger.info(f"Open results for '{solver}' ({results})")
def reading_fn():
self._tmp_results = results
@ -1637,12 +1647,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
)
res.show()
def _solver_workdir(self, solver):
def _solver_workdir(self, solver, scenario=None):
if scenario is None:
scenario = self._study.status.scenario
workdir = os.path.join(
os.path.dirname(self._study.filename),
"_PAMHYR_",
self._study.name.replace(" ", "_"),
solver.name.replace(" ", "_"),
scenario.workdir(),
)
return workdir
@ -1697,32 +1711,73 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
results=file_name[0]
)
def compare_results(self):
# def compare_results(self):
# if self._study is None:
# return
# run = CompareSolversWindow(
# study=self._study,
# config=self.conf,
# parent=self
# )
# if not run.exec():
# return
# results = self.diff_results(
# run.solver1, run.solver2
# )
# # At least one result not available
# if results is None:
# return
# # Windows already opened
# if self.sub_window_exists(
# CompareSolversWindow,
# data=[self._study, None] +
# [r._solver for r in results] +
# [r._repertory for r in results] +
# [r._name for r in results]
# ):
# return
# res = ResultsWindow(
# study=self._study,
# results=results,
# parent=self
# )
# res.show()
def compare_results_scenarios(self):
if self._study is None:
return
run = CompareSolversWindow(
dlg = CompareScenariosWindow(
study=self._study,
config=self.conf,
parent=self
)
if run.exec():
results = self.diff_results(run.solver1,
run.solver2)
else:
if not dlg.exec():
return
results = self.diff_results(
dlg.solver1, dlg.solver2,
scenario1=dlg.scenario1,
scenario2=dlg.scenario2
)
# At least one result not available
if results is None:
return
# Windows already opened
if self.sub_window_exists(
ResultsWindow,
CompareScenariosWindow,
data=[self._study, None] +
[r._solver for r in results] +
[r._repertory for r in results] +
[r._name for r in results]
[r._name for r in results] +
[dlg.scenario1, dlg.scenario2]
):
return
@ -1733,97 +1788,109 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
)
res.show()
def diff_results(self, solver1, solver2):
if solver1 is None:
# TODO message
return None
if solver2 is None:
# TODO message
def msg_diff_results_param(self):
self.message_box(
window_title=self._trad["Error"],
text=self._trad["mb_diff_results_title"],
informative_text=self._trad["mb_diff_results_param_msg"]
)
def msg_diff_results_compatibility(self):
self.message_box(
window_title=self._trad["Error"],
text=self._trad["mb_diff_results_title"],
informative_text=self._trad["mb_diff_results_compatibility_msg"]
)
@timer
def diff_results(self, solver1, solver2,
scenario1=None, scenario2=None):
if solver1 is None or solver2 is None:
self.msg_diff_results_param()
return None
solver3 = GenericSolver(solver1.name+" - "+solver2.name)
solver4 = GenericSolver(solver1.name)
solver5 = GenericSolver(solver2.name)
study1 = self._study
study2 = self._study
s3_name = solver1.name + " <> " + solver2.name
if not (scenario2 is None or scenario2 is None):
study1 = self._study.copy_from_scenario(scenario1)
study2 = self._study.copy_from_scenario(scenario2)
s3_name = scenario1.name + " <> " + scenario2.name
solver3 = GenericSolver(s3_name)
result1 = solver1.results(
self._study,
self._solver_workdir(solver1),
)
if result1 is None:
# TODO message
return None
study1,
self._solver_workdir(solver1, scenario=scenario1),
)
result2 = solver2.results(
self._study,
self._solver_workdir(solver2),
)
study2,
self._solver_workdir(solver2, scenario=scenario2),
)
if result2 is None:
# TODO message
if result1 is None or result2 is None:
self.msg_diff_results_param()
return None
if result2.get("nb_reach") != result1.get("nb_reach"):
# TODO message
if result1.get("nb_reach") != result2.get("nb_reach"):
self.msg_diff_results_compatibility()
return None
if result2.get("nb_profile") != result1.get("nb_profile"):
# TODO message
if result1.get("nb_profile") != result2.get("nb_profile"):
self.msg_diff_results_compatibility()
return None
# return [result1, result2]
return self._diff_results(
solver1, solver2, solver3,
result1, result2,
)
@timer
def _diff_results(self, solver1, solver2, solver3, result1, result2):
result3 = Results(study=self._study, solver=solver3)
ts = sorted(
list(
result1.get("timestamps").intersection(
result2.get("timestamps")
)
)
)
result3 = Results(self._study, solver3)
result4 = Results(self._study, solver1)
result5 = Results(self._study, solver2)
result3.set("nb_reach", result1.get("nb_reach"))
result4.set("nb_reach", result1.get("nb_reach"))
result5.set("nb_reach", result1.get("nb_reach"))
result3.set("nb_profile", result1.get("nb_profile"))
result4.set("nb_profile", result1.get("nb_profile"))
result5.set("nb_profile", result1.get("nb_profile"))
ts = sorted(list(result1.get("timestamps").intersection(
result2.get("timestamps"))))
result3.set("timestamps", ts)
result4.set("timestamps", ts)
result5.set("timestamps", ts)
for i in range(int(result1.get("nb_reach"))):
# Add reach to results reach list
r = result3.river.add(i)
r = result4.river.add(i)
r = result5.river.add(i)
for timestamp in result3.get("timestamps"):
for r in range(int(result1.get("nb_reach"))):
reach1 = result1.river.reach(r)
reach2 = result2.river.reach(r)
reach3 = result3.river.reach(r)
reach4 = result4.river.reach(r)
reach5 = result5.river.reach(r)
for p, (profile1, profile2) in enumerate(zip(
reach1.profiles, reach2.profiles)):
for profile1, profile2, profile3 in zip(
reach1.profiles,
reach2.profiles,
reach3.profiles):
for key in ["Z", "Q", "V"]:
d1 = profile1.get_ts_key(timestamp, key)
d2 = profile2.get_ts_key(timestamp, key)
d = d1-d2
reach3.set(p, timestamp, key, d)
reach4.set(p, timestamp, key, d1)
reach5.set(p, timestamp, key, d2)
limits = reach3.profile(p).geometry.get_water_limits(
reach3.profile(p).get_ts_key(timestamp, "Z")
)
reach3.set(
p, timestamp,
"water_limits",
limits
)
limits = profile1.get_ts_key(timestamp, "water_limits")
reach4.set(p, timestamp, "water_limits", limits)
limits = profile2.get_ts_key(timestamp, "water_limits")
reach5.set(p, timestamp, "water_limits", limits)
d = d1 - d2
return [result4, result5, result3]
profile3.set(timestamp, key, d)
limits = profile3.geometry\
.get_water_limits(
profile3.get_ts_key(timestamp, "Z")
)
profile3.set(timestamp, "water_limits", limits)
return [result1, result2, result3]
def open_results_adists(self):
if self._study is None:
@ -1866,6 +1933,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
solver_results_adists = solver_results.results(
self._study,
repertory=dir_path, qlog=None) # self._output)
logger.info(f"Select results: {dir_path}")
if len(bin_list) >= 2 and ("total_sediment.bin" in bin_list):
self.open_solver_results_adists(

View File

@ -0,0 +1,252 @@
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.WaitingDialog import WaitingDialog
_translate = QCoreApplication.translate
logger = logging.getLogger()
class CompareSolversWindow(PamhyrDialog):
_pamhyr_ui = "CompareSolvers"
_pamhyr_name = "Compare solvers"
def __init__(self, study=None, config=None,
parent=None):
self._solver1 = None
self._solver2 = None
name = _translate("Solver", "Compare solvers")
super(CompareSolversWindow, self).__init__(
title=name,
study=study,
config=config,
options=[],
parent=parent
)
self.setup_solvers()
self.setup_connections()
self.select_last_solver()
def setup_solvers(self):
solvers = self._config.solvers
solvers_name = list(
map(
self._format_solver_name,
solvers
)
)
self.combobox_add_items("comboBox1", solvers_name)
self.combobox_add_items("comboBox2", solvers_name)
def setup_connections(self):
self.find(QPushButton, "pushButton_ok").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(
"comboBox1",
self._format_solver_name(solver[0])
)
def _format_solver_name(self, solver):
return f"{solver.name} - ({solver._type})"
@property
def solver1(self):
return self._solver1
@property
def solver2(self):
return self._solver2
def accept(self):
solver_name1 = self.get_combobox_text("comboBox1")
solver_name1 = solver_name1.rsplit(" - ", 1)[0]
self._solver1 = next(
filter(
lambda s: s.name == solver_name1,
self._config.solvers
)
)
solver_name2 = self.get_combobox_text("comboBox2")
solver_name2 = solver_name2.rsplit(" - ", 1)[0]
self._solver2 = next(
filter(
lambda s: s.name == solver_name2,
self._config.solvers
)
)
super(CompareSolversWindow, self).accept()
class CompareScenariosWindow(PamhyrDialog):
_pamhyr_ui = "CompareScenarios"
_pamhyr_name = "Compare scenarios"
def __init__(self, study=None, config=None,
parent=None):
self._solver1 = None
self._solver2 = None
self._scenario1 = None
self._scenario2 = None
name = _translate("Solver", "Compare solvers")
super(CompareScenariosWindow, self).__init__(
title=name,
study=study,
config=config,
options=[],
parent=parent
)
self.setup_solvers()
self.setup_scenarios()
self.setup_connections()
self.select_last_solver()
def setup_solvers(self):
solvers = self._config.solvers
solvers_name = list(
map(
self._format_solver_name, solvers
)
)
self.combobox_add_items("comboBoxSolver1", solvers_name)
self.combobox_add_items("comboBoxSolver2", solvers_name)
def setup_scenarios(self):
scenarios = self._study.scenarios.lst
scenarios_name = list(
map(
lambda s: s.name, scenarios
)
)
self.combobox_add_items("comboBoxScenario1", scenarios_name)
self.combobox_add_items("comboBoxScenario2", scenarios_name)
def setup_connections(self):
self.find(QPushButton, "pushButton_ok").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(
"comboBoxSolver1",
self._format_solver_name(solver[0])
)
self.set_combobox_text(
"comboBoxSolver2",
self._format_solver_name(solver[0])
)
def _format_solver_name(self, solver):
return f"{solver.name} - ({solver._type})"
@property
def solver1(self):
return self._solver1
@property
def solver2(self):
return self._solver2
@property
def scenario1(self):
return self._scenario1
@property
def scenario2(self):
return self._scenario2
def accept(self):
solver_name1 = self.get_combobox_text("comboBoxSolver1")
solver_name1 = solver_name1.rsplit(" - ", 1)[0]
self._solver1 = next(
filter(
lambda s: s.name == solver_name1,
self._config.solvers
)
)
solver_name2 = self.get_combobox_text("comboBoxSolver2")
solver_name2 = solver_name2.rsplit(" - ", 1)[0]
self._solver2 = next(
filter(
lambda s: s.name == solver_name2,
self._config.solvers
)
)
scenario_name1 = self.get_combobox_text("comboBoxScenario1")
self._scenario1 = next(
filter(
lambda s: s.name == scenario_name1,
self._study.scenarios
)
)
scenario_name2 = self.get_combobox_text("comboBoxScenario2")
self._scenario2 = next(
filter(
lambda s: s.name == scenario_name2,
self._study.scenarios
)
)
super(CompareScenariosWindow, self).accept()

View File

@ -138,107 +138,6 @@ class SelectSolverWindow(PamhyrDialog):
super(SelectSolverWindow, self).accept()
class CompareSolversWindow(PamhyrDialog):
_pamhyr_ui = "CompareSolvers"
_pamhyr_name = "Compare solvers"
def __init__(self, study=None, config=None,
parent=None):
self._solver1 = None
self._solver2 = None
name = _translate("Solver", "Compare solvers")
super(CompareSolversWindow, self).__init__(
title=name,
study=study,
config=config,
options=[],
parent=parent
)
self.setup_combobox1()
self.setup_combobox2()
self.setup_connections()
self.select_last_solver()
def setup_combobox1(self):
solvers = self._config.solvers
solvers_name = list(
map(
self._format_solver_name,
solvers
)
)
self.combobox_add_items("comboBox1", solvers_name)
def setup_combobox2(self):
solvers = self._config.solvers
solvers_name = list(
map(
self._format_solver_name,
solvers
)
)
self.combobox_add_items("comboBox2", solvers_name)
def setup_connections(self):
self.find(QPushButton, "pushButton_ok").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(
"comboBox1",
self._format_solver_name(solver[0])
)
def _format_solver_name(self, solver):
return f"{solver.name} - ({solver._type})"
@property
def solver1(self):
return self._solver1
@property
def solver2(self):
return self._solver2
def accept(self):
solver_name1 = self.get_combobox_text("comboBox1")
solver_name1 = solver_name1.rsplit(" - ", 1)[0]
self._solver1 = next(
filter(
lambda s: s.name == solver_name1,
self._config.solvers
)
)
solver_name2 = self.get_combobox_text("comboBox2")
solver_name2 = solver_name2.rsplit(" - ", 1)[0]
self._solver2 = next(
filter(
lambda s: s.name == solver_name2,
self._config.solvers
)
)
super(CompareSolversWindow, self).accept()
class SolverLogWindow(PamhyrWindow):
_pamhyr_ui = "SolverLog"
_pamhyr_name = "Solver Log"

View File

@ -228,6 +228,18 @@ class MainTranslate(UnitTranslate):
"Do you still want to open those results?"
)
self._dict["mb_diff_results_title"] = _translate(
"MainWindow", "Results compare"
)
self._dict["mb_diff_results_param_msg"] = _translate(
"MainWindow", "Results comparison parameters is invalid"
)
self._dict["mb_diff_results_compatibility_msg"] = _translate(
"MainWindow",
"Results comparison with two "
"incompatible study version"
)
self._dict["x"] = _translate("MainWindow", "X (m)")
self._dict["y"] = _translate("MainWindow", "Y (m)")
self._dict["Yes"] = _translate("MainWindow", "Yes")

View File

@ -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>488</width>
<height>117</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="locale">
<locale language="English" country="Europe"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="comboBoxSolver1"/>
</item>
<item>
<widget class="QComboBox" name="comboBoxSolver2"/>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QComboBox" name="comboBoxScenario1"/>
</item>
<item>
<widget class="QComboBox" name="comboBoxScenario2"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<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_cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_ok">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -160,9 +160,9 @@
<string>&amp;Results</string>
</property>
<addaction name="action_menu_results_last"/>
<addaction name="action_open_results_from_file"/>
<addaction name="action_compare_results"/>
<addaction name="action_open_results_adists"/>
<addaction name="action_menu_open_results_from_file"/>
<addaction name="action_menu_compare_scenarios_results"/>
<addaction name="action_menu_open_results_adists"/>
</widget>
<widget class="QMenu" name="menu_help">
<property name="title">
@ -726,7 +726,7 @@
<string>Edit hydraulic structures</string>
</property>
</action>
<action name="action_open_results_from_file">
<action name="action_menu_open_results_from_file">
<property name="enabled">
<bool>false</bool>
</property>
@ -787,12 +787,15 @@
<string>DIF</string>
</property>
</action>
<action name="action_compare_results">
<action name="action_menu_compare_results">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Compare results</string>
</property>
</action>
<action name="action_open_results_adists">
<action name="action_menu_open_results_adists">
<property name="enabled">
<bool>false</bool>
</property>
@ -800,6 +803,14 @@
<string>Open results AdisTS</string>
</property>
</action>
<action name="action_menu_compare_scenarios_results">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Compare results</string>
</property>
</action>
</widget>
<resources/>
<connections>