Results: Compare scenarios.

scenarios
Pierre-Antoine 2025-10-27 17:14:29 +01:00
parent bc08d06bb1
commit 188486f33a
5 changed files with 426 additions and 124 deletions

View File

@ -84,10 +84,12 @@ 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 (
CompareSolversWindow, CompareScenariosWindow
)
from View.RunSolver.WindowAdisTS import ( from View.RunSolver.WindowAdisTS import (
SelectSolverWindowAdisTS, SelectSolverWindowAdisTS,
@ -128,8 +130,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_open_results_from_file", "action_menu_numerical_parameter", "action_menu_open_results_from_file",
"action_open_results_adists", "action_menu_open_results_adists",
] ]
other_model_action = [ other_model_action = [
@ -150,8 +152,9 @@ 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_open_results_from_file", "action_menu_results_last", "action_menu_open_results_from_file",
"action_compare_results", "action_menu_boundary_conditions_sediment", "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_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",
@ -296,9 +299,10 @@ 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_open_results_from_file": self.open_results_from_file, "action_menu_open_results_from_file": self.open_results_from_file,
"action_compare_results": self.compare_results, "action_menu_compare_results": self.compare_results,
"action_open_results_adists": self.open_results_adists, "action_menu_compare_scenarios_results": self.compare_results_scenarios,
"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":
@ -1641,13 +1645,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
res.show() 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( 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(" ", "_"),
self._study.status.scenario.workdir(), scenario.workdir(),
) )
return workdir return workdir
@ -1724,7 +1731,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
# Windows already opened # Windows already opened
if self.sub_window_exists( if self.sub_window_exists(
ResultsWindow, CompareSolversWindow,
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] +
@ -1739,6 +1746,46 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
res.show() res.show()
def compare_results_scenarios(self):
if self._study is None:
return
dlg = CompareScenariosWindow(
study=self._study,
config=self.conf,
parent=self
)
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(
CompareScenariosWindow,
data=[self._study, None] +
[r._solver for r in results] +
[r._repertory for r in results] +
[r._name for r in results] +
[dlg.scenario1, dlg.scenario2]
):
return
res = ResultsWindow(
study=self._study,
results=results,
parent=self
)
res.show()
def msg_diff_results_param(self): def msg_diff_results_param(self):
self.message_box( self.message_box(
window_title=self._trad["Error"], window_title=self._trad["Error"],
@ -1754,21 +1801,33 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
@timer @timer
def diff_results(self, solver1, solver2): def diff_results(self, solver1, solver2,
scenario1=None, scenario2=None):
if solver1 is None or solver2 is None: if solver1 is None or solver2 is None:
self.msg_diff_results_param() self.msg_diff_results_param()
return None return None
solver3 = GenericSolver(solver1.name + " <> " + 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( result1 = solver1.results(
self._study, study1,
self._solver_workdir(solver1), self._solver_workdir(solver1, scenario=scenario1),
) )
result2 = solver2.results( result2 = solver2.results(
self._study, study2,
self._solver_workdir(solver2), self._solver_workdir(solver2, scenario=scenario2),
) )
if result1 is None or result2 is None: if result1 is None or result2 is None:

View File

@ -0,0 +1,253 @@
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() 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

@ -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,10 @@
<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_open_results_from_file"/> <addaction name="action_menu_open_results_from_file"/>
<addaction name="action_compare_results"/> <addaction name="action_menu_compare_results"/>
<addaction name="action_open_results_adists"/> <addaction name="action_menu_compare_scenarios_results"/>
<addaction name="action_menu_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 +727,7 @@
<string>Edit hydraulic structures</string> <string>Edit hydraulic structures</string>
</property> </property>
</action> </action>
<action name="action_open_results_from_file"> <action name="action_menu_open_results_from_file">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
@ -787,12 +788,15 @@
<string>DIF</string> <string>DIF</string>
</property> </property>
</action> </action>
<action name="action_compare_results"> <action name="action_menu_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_open_results_adists"> <action name="action_menu_open_results_adists">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
@ -800,6 +804,14 @@
<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 scenarios results</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections> <connections>