mirror of
https://gitlab.com/pamhyr/pamhyr2.git
synced 2026-10-30 03:20:41 +01:00
758 lines
26 KiB
Python
758 lines
26 KiB
Python
# WindowAdisTS.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 datetime import datetime
|
|
from tools import trace, timer, logger_exception
|
|
|
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
|
|
|
from PyQt5.QtGui import (
|
|
QKeySequence, QIcon, QPixmap,
|
|
)
|
|
|
|
from PyQt5.QtCore import (
|
|
Qt, QVariant, QAbstractTableModel,
|
|
QCoreApplication, QModelIndex, pyqtSlot,
|
|
QItemSelectionModel, QTimer,
|
|
)
|
|
|
|
from PyQt5.QtWidgets import (
|
|
QDialogButtonBox, QPushButton, QLineEdit,
|
|
QFileDialog, QTableView, QAbstractItemView,
|
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
|
QSlider, QLabel, QWidget, QGridLayout,
|
|
)
|
|
|
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
|
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
|
|
|
from View.Results.PlotSedAdis import PlotAdis_dx, PlotAdis_dt
|
|
|
|
from View.Results.CustomPlot.Plot import CustomPlot
|
|
from View.Results.CustomExport.CustomExportAdis import (
|
|
CustomExportAdisDialog,
|
|
)
|
|
|
|
from View.Results.TableAdisTS import TableModel
|
|
from View.Results.translate import ResultsTranslate
|
|
|
|
_translate = QCoreApplication.translate
|
|
|
|
logger = logging.getLogger()
|
|
|
|
|
|
class ResultsWindowAdisTS(PamhyrWindow):
|
|
_pamhyr_ui = "ResultsAdisTS"
|
|
_pamhyr_name = "Results"
|
|
|
|
def _path_file(self, filename):
|
|
return os.path.abspath(
|
|
os.path.join(
|
|
os.path.dirname(__file__),
|
|
"..", "ui", "ressources", filename
|
|
)
|
|
)
|
|
|
|
def __init__(self, study=None, config=None,
|
|
solver=None, results=None,
|
|
parent=None):
|
|
self._solver = solver
|
|
self._results = results
|
|
self.pollutant_label = ["None"]
|
|
|
|
pollutants_headers = self._results.pollutants_list.copy()
|
|
|
|
trad = ResultsTranslate(pollutants_headers)
|
|
name = (
|
|
trad[self._pamhyr_name] + " - "
|
|
+ study.name + " - "
|
|
+ self._solver.name
|
|
)
|
|
|
|
super(ResultsWindowAdisTS, self).__init__(
|
|
title=name,
|
|
study=study,
|
|
config=config,
|
|
trad=trad,
|
|
parent=parent
|
|
)
|
|
|
|
self._hash_data.append(self._solver)
|
|
self._hash_data.append(self._results._repertory)
|
|
self._hash_data.append(self._results._name)
|
|
|
|
self._additional_plot = {}
|
|
self._current_pol_id = [1]
|
|
self._reach_id = 0
|
|
self._profile_id = 0
|
|
|
|
try:
|
|
self._timestamps = sorted(list(self._results.get("timestamps")))
|
|
self.set_type_pol()
|
|
self.setup_slider()
|
|
self.setup_table()
|
|
self.setup_plots()
|
|
self.setup_statusbar()
|
|
self.setup_connections()
|
|
self.update_table_selection_reach(self._reach_id)
|
|
self.update_table_selection_profile(self._profile_id)
|
|
self.update_table_selection_pol(self._current_pol_id)
|
|
except Exception as e:
|
|
logger_exception(e)
|
|
return
|
|
|
|
def set_type_pol(self):
|
|
self._type_pol = []
|
|
self._pol_id_dict = {}
|
|
tmp_list = self._results.river.reach(0).profiles
|
|
for pol_index in range(self._results.nb_pollutants):
|
|
pol_name = self._results.pollutants_list[pol_index]
|
|
if pol_name == "total_sediment":
|
|
self._type_pol.append(-1)
|
|
else:
|
|
self._type_pol.append(len(
|
|
tmp_list[0].get_ts_key(
|
|
self._timestamps[0], "pols")[pol_index])
|
|
)
|
|
self._pol_id_dict[pol_name] = pol_index
|
|
|
|
def setup_table(self):
|
|
self._table = {}
|
|
for t in ["reach", "profile", "pollutants", "raw_data"]:
|
|
table = self.find(QTableView, f"tableView_{t}")
|
|
self._table[t] = TableModel(
|
|
self._type_pol,
|
|
table_view=table,
|
|
table_headers=self._trad.get_dict(f"table_headers_{t}"),
|
|
data=self._results,
|
|
undo=self._undo_stack,
|
|
opt_data=t,
|
|
)
|
|
self._table[t]._timestamp = self._timestamps[
|
|
self._slider_time.value()]
|
|
|
|
def setup_slider(self):
|
|
self._slider_time = self.find(QSlider, f"horizontalSlider_time")
|
|
self._slider_time.setMaximum(len(self._timestamps) - 1)
|
|
self._slider_time.setValue(len(self._timestamps) - 1)
|
|
|
|
self._icon_start = QIcon()
|
|
self._icon_start.addPixmap(
|
|
QPixmap(self._path_file("media-playback-start.png"))
|
|
)
|
|
|
|
self._icon_pause = QIcon()
|
|
self._icon_pause.addPixmap(
|
|
QPixmap(self._path_file("media-playback-pause.png"))
|
|
)
|
|
self._button_play = self.find(QPushButton, f"playButton")
|
|
self._button_play.setIcon(self._icon_start)
|
|
self._button_back = self.find(QPushButton, f"backButton")
|
|
self._button_next = self.find(QPushButton, f"nextButton")
|
|
self._button_first = self.find(QPushButton, f"firstButton")
|
|
self._button_last = self.find(QPushButton, f"lastButton")
|
|
self._timer = QTimer(self)
|
|
|
|
def setup_plots(self):
|
|
self.canvas_cdt = MplCanvas(width=5, height=4, dpi=100)
|
|
self.canvas_cdt.setObjectName("canvas_cdt")
|
|
self.toolbar_cdt = PamhyrPlotToolbar(
|
|
self.canvas_cdt, self, items=[
|
|
"home", "move", "zoom", "save",
|
|
"iso", "back/forward"
|
|
]
|
|
)
|
|
self.plot_layout_cdt = self.find(
|
|
QVBoxLayout, "verticalLayout_concentration_dt")
|
|
self.plot_layout_cdt.addWidget(self.toolbar_cdt)
|
|
self.plot_layout_cdt.addWidget(self.canvas_cdt)
|
|
|
|
self.plot_cdt = PlotAdis_dt(
|
|
canvas=self.canvas_cdt,
|
|
results=self._results,
|
|
reach_id=self._reach_id,
|
|
profile_id=self._profile_id,
|
|
pol_id=self._current_pol_id,
|
|
key="C",
|
|
type_pol=self._type_pol,
|
|
trad=self._trad,
|
|
toolbar=self.toolbar_cdt
|
|
)
|
|
self.plot_cdt.draw()
|
|
|
|
self.canvas_cdx = MplCanvas(width=5, height=4, dpi=100)
|
|
self.canvas_cdx.setObjectName("canvas_cdx")
|
|
self.toolbar_cdx = PamhyrPlotToolbar(
|
|
self.canvas_cdx, self, items=[
|
|
"home", "move", "zoom", "save",
|
|
"iso", "back/forward"
|
|
]
|
|
)
|
|
self.plot_layout_cdx = self.find(
|
|
QVBoxLayout, "verticalLayout_concentration_dx")
|
|
self.plot_layout_cdx.addWidget(self.toolbar_cdx)
|
|
self.plot_layout_cdx.addWidget(self.canvas_cdx)
|
|
|
|
self.plot_cdx = PlotAdis_dx(
|
|
canvas=self.canvas_cdx,
|
|
results=self._results,
|
|
reach_id=self._reach_id,
|
|
profile_id=self._profile_id,
|
|
pol_id=self._current_pol_id,
|
|
key="C",
|
|
type_pol=self._type_pol,
|
|
trad=self._trad,
|
|
toolbar=self.toolbar_cdx
|
|
)
|
|
self.plot_cdx.draw()
|
|
|
|
self.canvas_mdx = MplCanvas(width=5, height=4, dpi=100)
|
|
self.canvas_mdx.setObjectName("canvas_mdx")
|
|
self.toolbar_mdx = PamhyrPlotToolbar(
|
|
self.canvas_mdx, self, items=[
|
|
"home", "move", "zoom", "save",
|
|
"iso", "back/forward"
|
|
]
|
|
)
|
|
self.plot_layout_mdx = self.find(
|
|
QVBoxLayout, "verticalLayout_mass_dx2")
|
|
self.plot_layout_mdx.addWidget(self.toolbar_mdx)
|
|
self.plot_layout_mdx.addWidget(self.canvas_mdx)
|
|
|
|
self.plot_mdx = PlotAdis_dx(
|
|
canvas=self.canvas_mdx,
|
|
results=self._results,
|
|
reach_id=self._reach_id,
|
|
profile_id=self._profile_id,
|
|
pol_id=self._current_pol_id,
|
|
key="M",
|
|
type_pol=self._type_pol,
|
|
trad=self._trad,
|
|
toolbar=self.toolbar_mdx
|
|
)
|
|
|
|
self.plot_mdx.draw()
|
|
|
|
self.canvas_mdt = MplCanvas(width=5, height=4, dpi=100)
|
|
self.canvas_mdt.setObjectName("canvas_mdt")
|
|
self.toolbar_mdt = PamhyrPlotToolbar(
|
|
self.canvas_mdt, self, items=[
|
|
"home", "move", "zoom", "save",
|
|
"iso", "back/forward"
|
|
]
|
|
)
|
|
self.plot_layout_mdt = self.find(
|
|
QVBoxLayout, "verticalLayout_mass_dt2")
|
|
self.plot_layout_mdt.addWidget(self.toolbar_mdt)
|
|
self.plot_layout_mdt.addWidget(self.canvas_mdt)
|
|
|
|
self.plot_mdt = PlotAdis_dt(
|
|
canvas=self.canvas_mdt,
|
|
results=self._results,
|
|
reach_id=self._reach_id,
|
|
profile_id=self._profile_id,
|
|
pol_id=self._current_pol_id,
|
|
key="M",
|
|
type_pol=self._type_pol,
|
|
trad=self._trad,
|
|
toolbar=self.toolbar_mdt
|
|
)
|
|
|
|
self.plot_mdt.draw()
|
|
|
|
# Thickness
|
|
|
|
self.canvas_tdx = MplCanvas(width=5, height=4, dpi=100)
|
|
self.canvas_tdx.setObjectName("canvas_tdx")
|
|
self.toolbar_tdx = PamhyrPlotToolbar(
|
|
self.canvas_tdx, self, items=[
|
|
"home", "move", "zoom", "save",
|
|
"iso", "back/forward"
|
|
]
|
|
)
|
|
self.plot_layout_tdx = self.find(
|
|
QVBoxLayout, "verticalLayout_tdx")
|
|
self.plot_layout_tdx.addWidget(self.toolbar_tdx)
|
|
self.plot_layout_tdx.addWidget(self.canvas_tdx)
|
|
|
|
self.plot_tdx = PlotAdis_dx(
|
|
canvas=self.canvas_tdx,
|
|
results=self._results,
|
|
reach_id=self._reach_id,
|
|
profile_id=self._profile_id,
|
|
pol_id=[0],
|
|
key="M",
|
|
type_pol=self._type_pol,
|
|
trad=self._trad,
|
|
toolbar=self.toolbar_tdx
|
|
)
|
|
|
|
self.plot_tdx.draw()
|
|
|
|
self.canvas_tdt = MplCanvas(width=5, height=4, dpi=100)
|
|
self.canvas_tdt.setObjectName("canvas_tdt")
|
|
self.toolbar_tdt = PamhyrPlotToolbar(
|
|
self.canvas_tdt, self, items=[
|
|
"home", "move", "zoom", "save",
|
|
"iso", "back/forward"
|
|
]
|
|
)
|
|
self.plot_layout_tdt = self.find(
|
|
QVBoxLayout, "verticalLayout_tdt")
|
|
self.plot_layout_tdt.addWidget(self.toolbar_tdt)
|
|
self.plot_layout_tdt.addWidget(self.canvas_tdt)
|
|
|
|
self.plot_tdt = PlotAdis_dt(
|
|
canvas=self.canvas_tdt,
|
|
results=self._results,
|
|
reach_id=self._reach_id,
|
|
profile_id=self._profile_id,
|
|
pol_id=[0],
|
|
key="M",
|
|
type_pol=self._type_pol,
|
|
trad=self._trad,
|
|
toolbar=self.toolbar_tdt
|
|
)
|
|
|
|
self.plot_tdt.draw()
|
|
|
|
def closeEvent(self, event):
|
|
try:
|
|
self._timer.stop()
|
|
except Exception as e:
|
|
logger_exception(e)
|
|
|
|
super(ResultsWindowAdisTS, 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.edges()[0]
|
|
else:
|
|
reach = self._study.river.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
|
|
|
|
# Pollutant
|
|
table = self.find(QTableView, f"tableView_pollutants")
|
|
indexes = table.selectedIndexes()
|
|
if len(indexes) != 0:
|
|
self.pollutant_label = [
|
|
self._results.pollutants_list[i.row()+1] for i in indexes
|
|
]
|
|
|
|
return (f"{self._trad['reach']}: {reach.name} | " +
|
|
f"{self._trad['cross_section']}: {pname} | " +
|
|
f"Pollutant: {', '.join(self.pollutant_label)} | " +
|
|
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,
|
|
# TODO "action_add": self._add_custom_plot,
|
|
"action_export": self.export,
|
|
}
|
|
|
|
self.find(QAction, "action_add").setEnabled(False)
|
|
|
|
for action in actions:
|
|
self.find(QAction, action).triggered.connect(
|
|
actions[action]
|
|
)
|
|
|
|
# Table and Plot
|
|
fun = {
|
|
"reach": self._set_current_reach,
|
|
"profile": self._set_current_profile,
|
|
"pollutants": self._set_current_pol,
|
|
"raw_data": self._set_current_profile_raw_data,
|
|
}
|
|
|
|
for t in ["reach", "profile", "pollutants"]:
|
|
table = self.find(QTableView, f"tableView_{t}")
|
|
|
|
table.selectionModel()\
|
|
.selectionChanged\
|
|
.connect(fun[t])
|
|
|
|
self._table[t].dataChanged.connect(fun[t])
|
|
|
|
self._slider_time.valueChanged.connect(self._set_current_timestamp)
|
|
self._button_play.setChecked(False)
|
|
self._button_play.clicked.connect(self._pause)
|
|
self._button_back.clicked.connect(self._back)
|
|
self._button_next.clicked.connect(self._next)
|
|
self._button_first.clicked.connect(self._first)
|
|
self._button_last.clicked.connect(self._last)
|
|
self._timer.timeout.connect(self._update_slider)
|
|
|
|
def update_table_selection_reach(self, ind):
|
|
table = self.find(QTableView, f"tableView_reach")
|
|
selectionModel = table.selectionModel()
|
|
index = table.model().index(ind, 0)
|
|
|
|
selectionModel.select(
|
|
index,
|
|
QItemSelectionModel.Rows |
|
|
QItemSelectionModel.ClearAndSelect |
|
|
QItemSelectionModel.Select
|
|
)
|
|
table.scrollTo(index)
|
|
|
|
self._table["profile"].update(ind)
|
|
self._table["raw_data"].update(ind)
|
|
|
|
def update_table_selection_profile(self, ind):
|
|
for t in ["profile"]:
|
|
table = self.find(QTableView, f"tableView_{t}")
|
|
selectionModel = table.selectionModel()
|
|
index = table.model().index(ind, 0)
|
|
|
|
selectionModel.select(
|
|
index,
|
|
QItemSelectionModel.Rows |
|
|
QItemSelectionModel.ClearAndSelect |
|
|
QItemSelectionModel.Select
|
|
)
|
|
table.scrollTo(index)
|
|
|
|
def update_table_selection_pol(self, ind):
|
|
for t in ["pollutants"]:
|
|
table = self.find(QTableView, f"tableView_{t}")
|
|
selectionModel = table.selectionModel()
|
|
index = table.model().index(ind[0] - 1, 0)
|
|
|
|
selectionModel.select(
|
|
index,
|
|
QItemSelectionModel.Rows |
|
|
QItemSelectionModel.ClearAndSelect |
|
|
QItemSelectionModel.Select
|
|
)
|
|
table.scrollTo(index)
|
|
|
|
def update(self, reach_id=None, profile_id=None,
|
|
pol_id=None, timestamp=None):
|
|
if reach_id is not None:
|
|
self._reach_id = reach_id
|
|
self.plot_cdt.set_reach(reach_id)
|
|
self.plot_cdx.set_reach(reach_id)
|
|
self.plot_mdx.set_reach(reach_id)
|
|
self.plot_mdt.set_reach(reach_id)
|
|
self.plot_tdt.set_reach(reach_id)
|
|
self.plot_tdx.set_reach(reach_id)
|
|
|
|
self.update_table_selection_reach(reach_id)
|
|
self.update_table_selection_profile(0)
|
|
|
|
if profile_id is not None:
|
|
self._profile_id = profile_id
|
|
self.plot_cdt.set_profile(profile_id)
|
|
self.plot_cdx.set_profile(profile_id)
|
|
self.plot_mdx.set_profile(profile_id)
|
|
self.plot_mdt.set_profile(profile_id)
|
|
self.plot_tdt.set_profile(profile_id)
|
|
self.plot_tdx.set_profile(profile_id)
|
|
|
|
self.update_table_selection_profile(profile_id)
|
|
|
|
if pol_id is not None:
|
|
self._current_pol_id = [p+1 for p in pol_id] # rm total_sediment
|
|
self.plot_cdt.set_pollutant(self._current_pol_id)
|
|
self.plot_cdx.set_pollutant(self._current_pol_id)
|
|
self.plot_mdx.set_pollutant(self._current_pol_id)
|
|
self.plot_mdt.set_pollutant(self._current_pol_id)
|
|
|
|
if timestamp is not None:
|
|
self.plot_cdt.set_timestamp(timestamp)
|
|
self.plot_cdx.set_timestamp(timestamp)
|
|
self.plot_mdx.set_timestamp(timestamp)
|
|
self.plot_mdt.set_timestamp(timestamp)
|
|
self.plot_tdt.set_timestamp(timestamp)
|
|
self.plot_tdx.set_timestamp(timestamp)
|
|
|
|
self._table["raw_data"].set_timestamp(timestamp)
|
|
|
|
self.update_statusbar()
|
|
|
|
def _get_current_timestamp(self):
|
|
return self._timestamps[
|
|
self._slider_time.value()
|
|
]
|
|
|
|
def _set_current_reach(self):
|
|
table = self.find(QTableView, f"tableView_reach")
|
|
indexes = table.selectedIndexes()
|
|
if len(indexes) == 0:
|
|
return
|
|
|
|
self.update(reach_id=indexes[0].row())
|
|
|
|
def _set_current_profile(self):
|
|
table = self.find(QTableView, f"tableView_profile")
|
|
indexes = table.selectedIndexes()
|
|
if len(indexes) == 0:
|
|
return
|
|
|
|
self.update(profile_id=indexes[0].row())
|
|
|
|
def _set_current_pol(self):
|
|
table = self.find(QTableView, f"tableView_pollutants")
|
|
indexes = table.selectedIndexes()
|
|
rows = [i.row() for i in indexes]
|
|
if len(indexes) == 0:
|
|
return
|
|
|
|
self.update(pol_id=rows)
|
|
|
|
def _set_current_profile_raw_data(self):
|
|
return
|
|
|
|
def _set_current_timestamp(self):
|
|
timestamp = self._timestamps[self._slider_time.value()]
|
|
self.update(timestamp=timestamp)
|
|
|
|
def _reload_plots(self):
|
|
self.plot_cdt.results = self._results
|
|
self.plot_cdx.results = self._results
|
|
self.plot_mdx.results = self._results
|
|
self.plot_mdt.results = self._results
|
|
self.plot_tdt.results = self._results
|
|
self.plot_tdx.results = self._results
|
|
|
|
self.plot_cdt.draw()
|
|
self.plot_cdx.draw()
|
|
self.plot_mdx.draw()
|
|
self.plot_mdt.draw()
|
|
self.plot_tdt.draw()
|
|
self.plot_tdx.draw()
|
|
|
|
def _reload_slider(self):
|
|
self._slider_time = self.find(QSlider, f"horizontalSlider_time")
|
|
self._slider_time.setMaximum(len(self._timestamps) - 1)
|
|
self._slider_time.setValue(len(self._timestamps) - 1)
|
|
|
|
def _reload(self):
|
|
logger.debug("Reload results...")
|
|
self._results = self._results.reload()
|
|
|
|
self._timestamps = sorted(list(self._results.get("timestamps")))
|
|
|
|
self._reload_plots()
|
|
self._reload_slider()
|
|
|
|
def _copy(self):
|
|
# focus on raw data table
|
|
if self.find(QTabWidget, f"tabWidget").currentIndex() == 0:
|
|
table = self.find(QTableView, f"tableView_raw_data")
|
|
model = self._table["raw_data"]
|
|
|
|
coltext = []
|
|
for index in sorted(table.selectionModel().selectedRows()):
|
|
row = index.row()
|
|
rowtext = []
|
|
for column in range(model.columnCount()):
|
|
i = model.createIndex(row, column)
|
|
try:
|
|
rowtext.append(str(model.data(i)))
|
|
except AttributeError:
|
|
rowtext.append("")
|
|
coltext.append(rowtext)
|
|
|
|
self.copyTableIntoClipboard(coltext)
|
|
else:
|
|
logger.info("TODO: copy")
|
|
|
|
def _paste(self):
|
|
logger.info("TODO: paste")
|
|
|
|
def _undo(self):
|
|
self._table.undo()
|
|
|
|
def _redo(self):
|
|
self._table.redo()
|
|
|
|
# play / pause buttons
|
|
def _update_slider(self):
|
|
if self._slider_time.value() == self._slider_time.maximum():
|
|
self._slider_time.setValue(self._slider_time.minimum())
|
|
else:
|
|
self._slider_time.setValue(self._slider_time.value()+1)
|
|
|
|
def _next(self):
|
|
self._slider_time.setValue(self._slider_time.value()+1)
|
|
|
|
def _back(self):
|
|
self._slider_time.setValue(self._slider_time.value()-1)
|
|
|
|
def _first(self):
|
|
self._slider_time.setValue(self._slider_time.minimum())
|
|
|
|
def _last(self):
|
|
self._slider_time.setValue(self._slider_time.maximum())
|
|
|
|
def _pause(self):
|
|
if self._button_play.isChecked():
|
|
self._button_next.setEnabled(False)
|
|
self._button_back.setEnabled(False)
|
|
self._button_first.setEnabled(False)
|
|
self._button_last.setEnabled(False)
|
|
self._timer.start(100)
|
|
self._button_play.setIcon(self._icon_pause)
|
|
else:
|
|
self._timer.stop()
|
|
self._button_next.setEnabled(True)
|
|
self._button_back.setEnabled(True)
|
|
self._button_first.setEnabled(True)
|
|
self._button_last.setEnabled(True)
|
|
self._button_play.setIcon(self._icon_start)
|
|
|
|
def export(self):
|
|
|
|
pols = self._results.pollutants_list.copy()
|
|
dlg = CustomExportAdisDialog(pollutants=pols,
|
|
parent=self)
|
|
if dlg.exec():
|
|
x, y, pol = dlg.value
|
|
else:
|
|
return
|
|
|
|
self.file_dialog(
|
|
select_file="AnyFile",
|
|
callback=lambda f: self.export_to(f[0], x, y, pol),
|
|
default_suffix=".csv",
|
|
file_filter=["CSV (*.csv)"],
|
|
)
|
|
|
|
def export_to(self, filename, x, y, pol):
|
|
timestamps = sorted(self._results.get("timestamps"))
|
|
reach = self._results.river.reachs[self._reach_id]
|
|
first_line = [f"Study: {self._results.study.name}",
|
|
f"Reach: {reach.name}"]
|
|
if x == "rk":
|
|
timestamp = self._get_current_timestamp()
|
|
first_line.append(f"Time: {timestamp}s")
|
|
val_dict = self._export_rk(timestamp, y, pol)
|
|
elif x == "time":
|
|
profile = reach.profile(self._profile_id)
|
|
pname = profile.name if profile.name != "" else profile.rk
|
|
first_line.append(f"Profile: {pname}")
|
|
val_dict = self._export_time(self._profile_id, y, pol)
|
|
with open(filename, 'w', newline='') as csvfile:
|
|
writer = csv.writer(csvfile, delimiter=',',
|
|
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
|
dict_x = self._trad.get_dict("values_x")
|
|
header = []
|
|
writer.writerow(first_line)
|
|
for text in val_dict.keys():
|
|
header.append(text)
|
|
writer.writerow(header)
|
|
for row in range(len(val_dict[dict_x[x]])):
|
|
line = []
|
|
for var in val_dict.keys():
|
|
line.append(val_dict[var][row])
|
|
writer.writerow(line)
|
|
|
|
def _export_rk(self, timestamp, y, pol):
|
|
reach = self._results.river.reachs[self._reach_id]
|
|
dict_x = self._trad.get_dict("values_x")
|
|
dict_y = self._trad.get_dict("values_y_pol")
|
|
my_dict = {}
|
|
my_dict[dict_x["rk"]] = reach.geometry.get_rk()
|
|
val_id = {}
|
|
val_id["unit_C"] = 0
|
|
val_id["unit_M"] = 2
|
|
val_id["unit_thickness"] = 2
|
|
for unit in y:
|
|
if unit == "unit_thickness":
|
|
pol_id = 0
|
|
else:
|
|
pol_id = self._pol_id_dict[pol]
|
|
if unit == "unit_M" and self._type_pol[pol_id] == 1:
|
|
my_dict[dict_y[unit]] = [0.0]*len(reach.profiles)
|
|
else:
|
|
my_dict[dict_y[unit]] = list(map(lambda p:
|
|
p.get_ts_key(
|
|
timestamp, "pols"
|
|
)[pol_id][val_id[unit]],
|
|
reach.profiles))
|
|
|
|
return my_dict
|
|
|
|
def _export_time(self, profile, y, pol):
|
|
reach = self._results.river.reachs[self._reach_id]
|
|
profile = reach.profile(profile)
|
|
ts = list(self._results.get("timestamps"))
|
|
ts.sort()
|
|
dict_x = self._trad.get_dict("values_x")
|
|
dict_y = self._trad.get_dict("values_y_pol")
|
|
my_dict = {}
|
|
my_dict[dict_x["time"]] = ts
|
|
val_id = {}
|
|
val_id["unit_C"] = 0
|
|
val_id["unit_M"] = 2
|
|
val_id["unit_thickness"] = 2
|
|
for unit in y:
|
|
if unit == "unit_thickness":
|
|
pol_id = 0
|
|
else:
|
|
pol_id = self._pol_id_dict[pol]
|
|
if unit == "unit_M" and self._type_pol[pol_id] == 1:
|
|
my_dict[dict_y[unit]] = [0.0]*len(ts)
|
|
else:
|
|
my_dict[dict_y[unit]] = list(map(lambda data_el:
|
|
data_el[pol_id][val_id[unit]],
|
|
profile.get_key("pols")
|
|
))
|
|
|
|
return my_dict
|