Pamhyr2/src/View/Results/Window.py

897 lines
29 KiB
Python

# Window.py -- Pamhyr
# Copyright (C) 2023-2024 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import os
import csv
import logging
from numpy import sqrt
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, QTabBar
)
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Results.PlotXY import PlotXY
from View.Results.PlotAC import PlotAC
from View.Results.PlotRKC import PlotRKC
from View.Results.PlotH import PlotH
from View.Results.PlotSedReach import PlotSedReach
from View.Results.PlotSedProfile import PlotSedProfile
from View.Results.CustomPlot.Plot import CustomPlot
from View.Results.CustomPlot.CustomPlotValuesSelectionDialog import (
CustomPlotValuesSelectionDialog,
)
from View.Results.Table import TableModel
from View.Results.translate import (
ResultsTranslate,
CompareResultsTranslate
)
from View.Stricklers.Window import StricklersWindow
_translate = QCoreApplication.translate
logger = logging.getLogger()
class ResultsWindow(PamhyrWindow):
_pamhyr_ui = "Results"
_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, trad=None):
self._solver = solver
self._results = results
if trad is None:
trad = ResultsTranslate()
name = (
trad[self._pamhyr_name] + " - "
+ study.name + " - "
+ self._solver.name
)
super(ResultsWindow, self).__init__(
title=name,
study=study,
config=config,
trad=trad,
parent=parent
)
self._hash_data.append(self._solver)
self._hash_data.append(self._results)
self._additional_plot = {}
try:
self._timestamps = sorted(list(self._results.get("timestamps")))
self.setup_slider()
self.setup_table()
self.setup_plots()
self.setup_statusbar()
self.setup_connections()
except Exception as e:
logger_exception(e)
return
def setup_table(self):
self._table = {}
for t in ["reach", "profile", "raw_data"]:
table = self.find(QTableView, f"tableView_{t}")
self._table[t] = TableModel(
table_view=table,
table_headers=self._trad.get_dict(f"table_headers_{t}"),
data=self._results,
undo=self._undo_stack,
opt_data=t
)
self._table[t]._timestamp = self._timestamps[
self._slider_time.value()]
def setup_slider(self):
default_reach = self._results.river.reach(0)
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 = MplCanvas(width=5, height=4, dpi=100)
tab_widget = self.find(QTabWidget, f"tabWidget")
tab_widget.setTabsClosable(True)
tab_widget.tabCloseRequested.connect(self.delete_tab)
tab_widget.tabBar().setTabButton(0, QTabBar.RightSide, None)
tab_widget.tabBar().setTabButton(1, QTabBar.RightSide, None)
tab_widget.tabBar().setTabButton(2, QTabBar.RightSide, None)
self.canvas.setObjectName("canvas")
self.toolbar = PamhyrPlotToolbar(
self.canvas, self, items=[
"home", "move", "zoom", "save",
"iso", "back/forward"
]
)
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
self.plot_layout.addWidget(self.toolbar)
self.plot_layout.addWidget(self.canvas)
self.plot_xy = PlotXY(
canvas=self.canvas,
results=self._results,
reach_id=0,
profile_id=0,
trad=self._trad,
toolbar=self.toolbar,
display_current=True,
parent=self
)
self.plot_xy.draw()
self.canvas_2 = MplCanvas(width=5, height=4, dpi=100)
self.canvas_2.setObjectName("canvas_2")
self.toolbar_2 = PamhyrPlotToolbar(
self.canvas_2, self, items=[
"home", "move", "zoom", "save",
"iso", "back/forward"
]
)
self.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2")
self.plot_layout_2.addWidget(self.toolbar_2)
self.plot_layout_2.addWidget(self.canvas_2)
self.plot_rkc = PlotRKC(
canvas=self.canvas_2,
results=self._results,
reach_id=0,
profile_id=0,
trad=self._trad,
toolbar=self.toolbar_2
)
self.plot_rkc.draw()
self.canvas_3 = MplCanvas(width=5, height=4, dpi=100)
self.canvas_3.setObjectName("canvas_3")
self.toolbar_3 = PamhyrPlotToolbar(
self.canvas_3, self, items=[
"home", "move", "zoom", "save",
"iso", "back/forward"
]
)
self.plot_layout_3 = self.find(QVBoxLayout, "verticalLayout_3")
self.plot_layout_3.addWidget(self.toolbar_3)
self.plot_layout_3.addWidget(self.canvas_3)
self.plot_ac = PlotAC(
canvas=self.canvas_3,
results=self._results,
reach_id=0,
profile_id=0,
trad=self._trad,
toolbar=self.toolbar_3
)
self.plot_ac.draw()
self.canvas_4 = MplCanvas(width=5, height=4, dpi=100)
self.canvas_4.setObjectName("canvas_4")
self.toolbar_4 = PamhyrPlotToolbar(
self.canvas_4, self, items=[
"home", "move", "zoom", "save",
"iso", "back/forward"
]
)
self.plot_layout_4 = self.find(
QVBoxLayout, "verticalLayout_hydrograph")
self.plot_layout_4.addWidget(self.toolbar_4)
self.plot_layout_4.addWidget(self.canvas_4)
self.plot_h = PlotH(
canvas=self.canvas_4,
results=self._results,
reach_id=0,
profile_id=0,
trad=self._trad,
toolbar=self.toolbar_4
)
self.plot_h.draw()
def closeEvent(self, event):
try:
self._timer.stop()
except Exception as e:
logger_exception(e)
super(ResultsWindow, self).closeEvent(event)
def _compute_status_label(self):
# Timestamp
ts = self._timestamps[self._slider_time.value()]
t0 = datetime.fromtimestamp(0)
fts = str(
datetime.fromtimestamp(ts) - t0
)
fts.replace("days", _translate("Results", "days"))\
.replace("day", _translate("Results", "day"))
# 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['reach']}: {reach.name} | " +
f"{self._trad['cross_section']}: {pname} | " +
f"{self._trad['unit_time_s']} : {fts} ({ts} sec)")
def setup_statusbar(self):
txt = self._compute_status_label()
self._status_label = QLabel(txt)
self.statusbar.addPermanentWidget(self._status_label)
def update_statusbar(self):
txt = self._compute_status_label()
self._status_label.setText(txt)
def setup_connections(self):
# Action
actions = {
"action_reload": self._reload,
"action_add": self._add_custom_plot,
"action_export": self._export,
# "action_export": self.export_current,
}
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", "raw_data"]:
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", "raw_data"]:
table = self.find(QTableView, f"tableView_{t}")
selectionModel = table.selectionModel()
index = table.model().index(ind, 0)
selectionModel.select(
index,
QItemSelectionModel.Rows |
QItemSelectionModel.ClearAndSelect |
QItemSelectionModel.Select
)
table.scrollTo(index)
def update(self, reach_id=None, profile_id=None, timestamp=None):
if reach_id is not None:
self.plot_xy.set_reach(reach_id)
self.plot_ac.set_reach(reach_id)
self.plot_rkc.set_reach(reach_id)
self.plot_h.set_reach(reach_id)
for plot in self._additional_plot:
self._additional_plot[plot].set_reach(reach_id)
self.update_table_selection_reach(reach_id)
self.update_table_selection_profile(0)
if profile_id is not None:
self.plot_xy.set_profile(profile_id)
self.plot_ac.set_profile(profile_id)
self.plot_rkc.set_profile(profile_id)
self.plot_h.set_profile(profile_id)
for plot in self._additional_plot:
self._additional_plot[plot].set_profile(profile_id)
self.update_table_selection_profile(profile_id)
if timestamp is not None:
self.plot_xy.set_timestamp(timestamp)
self.plot_ac.set_timestamp(timestamp)
self.plot_rkc.set_timestamp(timestamp)
self.plot_h.set_timestamp(timestamp)
for plot in self._additional_plot:
self._additional_plot[plot].set_timestamp(timestamp)
self._table["raw_data"].timestamp = timestamp
self.update_statusbar()
def _get_current_reach(self):
table = self.find(QTableView, f"tableView_reach")
indexes = table.selectedIndexes()
if len(indexes) == 0:
return 0
return indexes[0].row()
def _get_current_profile(self):
table = self.find(QTableView, f"tableView_profile")
indexes = table.selectedIndexes()
if len(indexes) == 0:
return 0
return indexes[0].row()
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
ind = indexes[0].row()
self.update(profile_id=ind)
def _set_current_profile_raw_data(self):
table = self.find(QTableView, f"tableView_raw_data")
indexes = table.selectedIndexes()
if len(indexes) == 0:
return
ind = indexes[0].row()
self.update(profile_id=ind)
def _set_current_timestamp(self):
timestamp = self._timestamps[self._slider_time.value()]
self.update(timestamp=timestamp)
def _reload_plots(self):
self.plot_xy.results = self._results
self.plot_ac.results = self._results
self.plot_rkc.results = self._results
self.plot_h.results = self._results
self.plot_xy.draw()
self.plot_ac.draw()
self.plot_rkc.draw()
self.plot_h.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 _add_custom_plot(self):
dlg = CustomPlotValuesSelectionDialog(parent=self)
if dlg.exec():
x, y, envelop = dlg.value
self.create_new_tab_custom_plot(x, y, envelop)
def create_new_tab_custom_plot(self, x: str, y: list, envelop: bool):
name = f"{x}: {','.join(y)}"
if envelop and x == "rk":
name += "_envelop"
wname = f"tab_custom_{x}_{y}"
tab_widget = self.find(QTabWidget, f"tabWidget")
# This plot already exists
if name in [tab_widget.tabText(i) for i in range(tab_widget.count())]:
tab_widget.setCurrentWidget(
tab_widget.findChild(QWidget, wname)
)
return
widget = QWidget()
grid = QGridLayout()
widget.setObjectName(wname)
canvas = MplCanvas(width=5, height=4, dpi=100)
canvas.setObjectName(f"canvas_{x}_{y}")
toolbar = PamhyrPlotToolbar(
canvas, self
)
plot = CustomPlot(
x, y, envelop,
self._get_current_reach(),
self._get_current_profile(),
self._get_current_timestamp(),
data=self._results,
canvas=canvas,
toolbar=toolbar,
parent=self,
)
plot.draw()
# Add plot to additional plot
self._additional_plot[name] = plot
grid.addWidget(toolbar, 0, 0)
grid.addWidget(canvas, 1, 0)
widget.setLayout(grid)
tab_widget.addTab(widget, name)
tab_widget.setCurrentWidget(widget)
def _copy(self):
logger.info("TODO: copy")
def _paste(self):
logger.info("TODO: paste")
def _undo(self):
self._table.undo()
def _redo(self):
self._table.redo()
# play / pause buttons
def _update_slider(self):
if self._slider_time.value() == self._slider_time.maximum():
self._slider_time.setValue(self._slider_time.minimum())
else:
self._slider_time.setValue(self._slider_time.value()+1)
def _next(self):
self._slider_time.setValue(self._slider_time.value()+1)
def _back(self):
self._slider_time.setValue(self._slider_time.value()-1)
def _first(self):
self._slider_time.setValue(self._slider_time.minimum())
def _last(self):
self._slider_time.setValue(self._slider_time.maximum())
def _pause(self):
if self._button_play.isChecked():
self._button_next.setEnabled(False)
self._button_back.setEnabled(False)
self._button_first.setEnabled(False)
self._button_last.setEnabled(False)
self._timer.start(100)
self._button_play.setIcon(self._icon_pause)
else:
self._timer.stop()
self._button_next.setEnabled(True)
self._button_back.setEnabled(True)
self._button_first.setEnabled(True)
self._button_last.setEnabled(True)
self._button_play.setIcon(self._icon_start)
def _export(self):
dlg = CustomPlotValuesSelectionDialog(parent=self)
if dlg.exec():
x, y, envelop = dlg.value
else:
return
logger.debug(
"Export custom plot for: " +
f"{x} -> {','.join(y)}"
)
self.file_dialog(
select_file="AnyFile",
callback=lambda f: self.export_to(f[0], x, y, envelop),
default_suffix=".csv",
file_filter=["CSV (*.csv)"],
)
def export_to(self, filename, x, y, envelop):
timestamps = sorted(self._results.get("timestamps"))
reach = self._results.river.reachs[self._get_current_reach()]
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, envelop, filename)
elif x == "time":
profile_id = self._get_current_profile()
profile = reach.profile(profile_id)
pname = profile.name if profile.name != "" else profile.rk
first_line.append(f"Profile: {pname}")
val_dict = self._export_time(profile_id, y, filename)
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_all(self, reach, directory, timestamps):
name = reach.name
name = name.replace(" ", "-")
if len(timestamps) == 1:
name = f"{name}_t{timestamps[0]}"
file_name = os.path.join(
directory,
f"reach_{name}.csv"
)
with open(file_name, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL)
ts = timestamps[0]
writer.writerow(self._table["raw_data"]._headers)
for row in range(self._table["raw_data"].rowCount()):
line = []
for column in range(self._table["raw_data"].columnCount()):
index = self._table["raw_data"].index(row, column)
line.append(self._table["raw_data"].data(index))
writer.writerow(line)
def export_current(self):
self.file_dialog(
select_file="Directory",
callback=lambda d: self.export_current_to(d[0])
)
def export_current_to(self, directory):
reach = self._results.river.reachs[self._get_current_reach()]
self.export_all(reach, directory, [self._get_current_timestamp()])
def delete_tab(self, index):
tab_widget = self.find(QTabWidget, f"tabWidget")
self._additional_plot.pop(tab_widget.tabText(index))
tab_widget.removeTab(index)
def _export_rk(self, timestamp, y, envelop, filename):
reach = self._results.river.reachs[self._get_current_reach()]
dict_x = self._trad.get_dict("values_x")
dict_y = self._trad.get_dict("values_y")
if envelop:
dict_y.update(self._trad.get_dict("values_y_envelop"))
my_dict = {}
my_dict[dict_x["rk"]] = reach.geometry.get_rk()
if "bed_elevation" in y:
my_dict[dict_y["bed_elevation"]] = reach.geometry.get_z_min()
#if envelop and reach.has_sediment():
if "discharge" in y:
my_dict[dict_y["discharge"]] = list(
map(
lambda p: p.get_ts_key(timestamp, "Q"),
reach.profiles
)
)
if envelop:
my_dict[dict_y["min_discharge"]] = list(
map(
lambda p: min(p.get_key("Q")),
reach.profiles
)
)
my_dict[dict_y["max_discharge"]] = list(
map(
lambda p: max(p.get_key("Q")),
reach.profiles
)
)
if "water_elevation" in y:
my_dict[dict_y["water_elevation"]] = list(
map(
lambda p: p.get_ts_key(timestamp, "Z"),
reach.profiles
)
)
if envelop:
my_dict[dict_y["min_water_elevation"]] = list(
map(
lambda p: min(p.get_key("Z")),
reach.profiles
)
)
my_dict[dict_y["max_water_elevation"]] = list(
map(
lambda p: max(p.get_key("Z")),
reach.profiles
)
)
if "velocity" in y:
my_dict[dict_y["velocity"]] = list(
map(
lambda p: p.geometry.speed(
p.get_ts_key(timestamp, "Q"),
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
if envelop:
velocities = list(map(
lambda p: list(map(
lambda q, z:
p.geometry.speed(q, z),
p.get_key("Q"), p.get_key("Z")
)), reach.profiles
)
)
my_dict[dict_y["min_velocity"]] = [min(v) for v in velocities]
my_dict[dict_y["max_velocity"]] = [max(v) for v in velocities]
if "depth" in y:
my_dict[dict_y["depth"]] = list(
map(
lambda p: p.geometry.max_water_depth(
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
if envelop:
my_dict[dict_y["min_depth"]] = list(map(
lambda p1, p2: p1 - p2, map(
lambda p: min(p.get_key("Z")),
reach.profiles
), reach.geometry.get_z_min()
)
)
my_dict[dict_y["max_depth"]] = list(map(
lambda p1, p2: p1 - p2, map(
lambda p: max(p.get_key("Z")),
reach.profiles
), reach.geometry.get_z_min()
)
)
if "mean_depth" in y:
my_dict[dict_y["mean_depth"]] = list(
map(
lambda p: p.geometry.mean_water_depth(
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
if "froude" in y:
my_dict[dict_y["froude"]] = list(
map(
lambda p:
p.geometry.speed(
p.get_ts_key(timestamp, "Q"),
p.get_ts_key(timestamp, "Z")) /
sqrt(9.81 * (
p.geometry.wet_area(
p.get_ts_key(timestamp, "Z")) /
p.geometry.wet_width(
p.get_ts_key(timestamp, "Z"))
)),
reach.profiles
)
)
if "wet_area" in y:
my_dict[dict_y["wet_area"]] = list(
map(
lambda p: p.geometry.wet_area(
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
return my_dict
def _export_time(self, profile, y, filename):
reach = self._results.river.reachs[self._get_current_reach()]
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")
my_dict = {}
my_dict[dict_x["time"]] = ts
z = profile.get_key("Z")
q = profile.get_key("Q")
if "bed_elevation" in y:
my_dict[dict_y["bed_elevation"]] = [
profile.geometry.z_min()] * len(ts)
if "discharge" in y:
my_dict[dict_y["discharge"]] = q
if "water_elevation" in y:
my_dict[dict_y["water_elevation"]] = z
if "velocity" in y:
my_dict[dict_y["velocity"]] = list(
map(
lambda q, z: profile.geometry.speed(q, z),
q, z
)
)
if "depth" in y:
my_dict[dict_y["depth"]] = list(
map(lambda z: profile.geometry.max_water_depth(z), z)
)
if "mean_depth" in y:
my_dict[dict_y["mean_depth"]] = list(
map(lambda z: profile.geometry.mean_water_depth(z), z)
)
if "froude" in y:
my_dict[dict_y["froude"]] = list(
map(lambda z, q:
profile.geometry.speed(q, z) /
sqrt(9.81 * (
profile.geometry.wet_area(z) /
profile.geometry.wet_width(z))
), z, q)
)
if "wet_area" in y:
my_dict[dict_y["wet_area"]] = list(
map(lambda z: profile.geometry.wet_area(z), z)
)
return my_dict
class CompareResultsWindow(ResultsWindow):
_pamhyr_ui = "Results"
_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
trad = CompareResultsTranslate()
name = (
trad[self._pamhyr_name] + " - "
+ study.name + " - "
+ self._solver.name
)
super(CompareResultsWindow, self).__init__(
study=study,
config=config,
solver=solver,
results=results,
parent=parent,
trad=trad
)