Compare commits

..

No commits in common. "279fa0bf5ea527083b6aa6c5ac6c0daf21f29533" and "a8a408b5d5afebb56d1e0a511e95faab91b213ea" have entirely different histories.

17 changed files with 263 additions and 534 deletions

View File

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

View File

@ -881,31 +881,25 @@ class ProfileXYZ(Profile, SQLSubModel):
# Interpolate points at river left side # Interpolate points at river left side
if (i_left > 0): if (i_left > 0):
if abs(self.point(i_left - 1).z - self.point(i_left).z) < 1e-20: fact = (z - self.point(i_left).z) / (self.point(i_left - 1).z
pt_left = self.point(i_left) - self.point(i_left).z)
else: x = self.point(i_left).x + fact * (self.point(i_left - 1).x
fact = (z - self.point(i_left).z) / (self.point(i_left - 1).z - self.point(i_left).x)
- self.point(i_left).z) y = self.point(i_left).y + fact * (self.point(i_left - 1).y
x = self.point(i_left).x + fact * (self.point(i_left - 1).x - self.point(i_left).y)
- self.point(i_left).x) pt_left = PointXYZ(x=x, y=y, z=z, name="wl_left")
y = self.point(i_left).y + fact * (self.point(i_left - 1).y
- self.point(i_left).y)
pt_left = PointXYZ(x=x, y=y, z=z, name="wl_left")
else: else:
pt_left = self.point(0) pt_left = self.point(0)
# Interpolate points at river right side # Interpolate points at river right side
if (i_right < self.number_points - 1): if (i_right < self.number_points - 1):
if abs(self.point(i_right + 1).z - self.point(i_right).z) < 1e-20: fact = (z - self.point(i_right).z) / (self.point(i_right + 1).z -
pt_right = self.point(i_right) self.point(i_right).z)
else: x = self.point(i_right).x + fact * (self.point(i_right + 1).x -
fact = (z - self.point(i_right).z) / \ self.point(i_right).x)
(self.point(i_right + 1).z - self.point(i_right).z) y = self.point(i_right).y + fact * (self.point(i_right + 1).y -
x = self.point(i_right).x + fact * \ self.point(i_right).y)
(self.point(i_right + 1).x - self.point(i_right).x) pt_right = PointXYZ(x=x, y=y, z=z, name="wl_right")
y = self.point(i_right).y + fact * \
(self.point(i_right + 1).y - self.point(i_right).y)
pt_right = PointXYZ(x=x, y=y, z=z, name="wl_right")
else: else:
pt_right = self.point(self.number_points - 1) pt_right = self.point(self.number_points - 1)

View File

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

View File

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

View File

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

View File

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

View File

@ -44,10 +44,7 @@ class Study(SQLModel):
River, River,
] ]
def __init__(self, filename=None, init_new=True, copy=False): def __init__(self, filename=None, init_new=True):
if copy:
return
# Metadata # Metadata
self.creation_date = datetime.now() self.creation_date = datetime.now()
self.last_modification_date = datetime.now() self.last_modification_date = datetime.now()
@ -479,10 +476,31 @@ class Study(SQLModel):
return new return new
def reload_from_scenario(self, scenario): def reload_from_scenario(self, scenario):
river = self.load_scenario(scenario) if scenario in self._river_scenario_cache:
self._river = river 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 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
if reduce( if reduce(
lambda a, s: a or (s.parent is scenario), lambda a, s: a or (s.parent is scenario),
@ -493,80 +511,6 @@ class Study(SQLModel):
else: else:
self.status.set_as_editable() 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): def duplicate_current_scenario(self):
source = self.status.scenario_id source = self.status.scenario_id
new = self.scenarios.new( new = self.scenarios.new(

View File

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

View File

@ -446,7 +446,7 @@ class Rubar3(CommandLineSolver):
ind = 1 ind = 1
for mail in edge.reach.inter_profiles_rk(): for mail in edge.reach.inter_profiles_rk():
coef = get_stricklers_from_rk(mail, lst) coef = get_stricklers_from_rk(mail, lst)
if coef is not None: if coeff is not None:
f.write(f"{ind:>6} {coef:>12.5f}") f.write(f"{ind:>6} {coef:>12.5f}")
ind += 1 ind += 1

View File

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

View File

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

View File

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

View File

@ -1,149 +0,0 @@
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 CompareScenariosWindow(PamhyrDialog):
_pamhyr_ui = "CompareScenarios"
_pamhyr_name = "Compare scenarios"
def __init__(self, study=None, config=None,
parent=None):
self._solvers = []
self._scenarios = []
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._solvers[0]
@property
def solver2(self):
return self._solvers[1]
@property
def scenario1(self):
return self._scenarios[0]
@property
def scenario2(self):
return self._scenarios[1]
def accept(self):
for cb in ["comboBoxSolver1", "comboBoxSolver2"]:
name = self.get_combobox_text(cb)
name = name.rsplit(" - ", 1)[0]
self._solvers.append(
next(
filter(
lambda s: s.name == name,
self._config.solvers
)
)
)
for cb in ["comboBoxScenario1", "comboBoxScenario2"]:
name = self.get_combobox_text(cb)
self._scenarios.append(
next(
filter(
lambda s: s.name == name,
self._study.scenarios.lst
)
)
)
super(CompareScenariosWindow, self).accept()

View File

@ -138,6 +138,107 @@ class SelectSolverWindow(PamhyrDialog):
super(SelectSolverWindow, self).accept() 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): class SolverLogWindow(PamhyrWindow):
_pamhyr_ui = "SolverLog" _pamhyr_ui = "SolverLog"
_pamhyr_name = "Solver Log" _pamhyr_name = "Solver Log"

View File

@ -228,18 +228,6 @@ class MainTranslate(UnitTranslate):
"Do you still want to open those results?" "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["x"] = _translate("MainWindow", "X (m)")
self._dict["y"] = _translate("MainWindow", "Y (m)") self._dict["y"] = _translate("MainWindow", "Y (m)")
self._dict["Yes"] = _translate("MainWindow", "Yes") self._dict["Yes"] = _translate("MainWindow", "Yes")

View File

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