From daaa9b193ee7397a927a699d5b63a25dc22e746e Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr> Date: Tue, 17 Oct 2023 11:18:35 +0200 Subject: [PATCH] Resutls: CustomPlot: Prepare ploting mecanisme. --- src/View/Results/CustomPlot/Plot.py | 112 +++++++++++++++++++++++ src/View/Results/CustomPlot/Translate.py | 16 +++- src/View/Results/Window.py | 75 ++++++++++++++- 3 files changed, 195 insertions(+), 8 deletions(-) create mode 100644 src/View/Results/CustomPlot/Plot.py diff --git a/src/View/Results/CustomPlot/Plot.py b/src/View/Results/CustomPlot/Plot.py new file mode 100644 index 00000000..ea1e2001 --- /dev/null +++ b/src/View/Results/CustomPlot/Plot.py @@ -0,0 +1,112 @@ +# Plot.py -- Pamhyr +# Copyright (C) 2023 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 logging + +from functools import reduce + +from tools import timer +from View.Tools.PamhyrPlot import PamhyrPlot + +logger = logging.getLogger() + +unit = { + "elevation": "meter", + "water_elevation": "meter", + "discharge": "m3s", +} + + +class CustomPlot(PamhyrPlot): + def __init__(self, x, y, reach, profile, timestamp, + data=None, canvas=None, trad=None, + toolbar=None, parent=None): + super(CustomPlot, self).__init__( + canvas=canvas, + trad=trad, + data=data, + toolbar=toolbar, + parent=parent + ) + + self._x = x + self._y = y + self._reach = reach + self._profile = profile + self._timestamp = timestamp + + self._y_axis = list( + set( + map( + lambda y: self._trad[y], + self._y + ) + ) + ) + + @timer + def draw(self): + self.canvas.axes.cla() + self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5) + + if self.data is None: + return + + self.canvas.axes.set_xlabel( + self._trad[self._x], + color='green', fontsize=12 + ) + self.canvas.axes.set_ylabel( + self._trad[self._y_axis[0]], + color='green', fontsize=12 + ) + + for axes in self._y_axis[1:]: + logger.info(axes) + ax_new = ax.twinx() + #ax_new.spines['right'].set_position(('axes', 1 + spacing * (n - 1))) + ax_new.set_ylabel( + self._trad[axes], + color='green', fontsize=12 + ) + + if self._x is "kp": + if "elevation" in self._y: + logging.info("TODO: kp/elevation") + if "water_elevation" in self._y: + logging.info("TODO: kp/water_elevation") + if "discharge" in self._y: + logging.info("TODO: kp/discharge") + elif self._x is "time": + if "elevation" in self._y: + logging.info("TODO: time/elevation") + if "water_elevation" in self._y: + logging.info("TODO: time/water_elevation") + if "discharge" in self._y: + logging.info("TODO: time/discharge") + + self.canvas.figure.tight_layout() + self.canvas.figure.canvas.draw_idle() + if self.toolbar is not None: + self.toolbar.update() + + @timer + def update(self, reach, profile, timestamp): + if not self._init: + self.draw() + return diff --git a/src/View/Results/CustomPlot/Translate.py b/src/View/Results/CustomPlot/Translate.py index 11c3187e..aee28e0d 100644 --- a/src/View/Results/CustomPlot/Translate.py +++ b/src/View/Results/CustomPlot/Translate.py @@ -27,33 +27,39 @@ class CustomPlotTranslate(ResultsTranslate): def __init__(self): super(CustomPlotTranslate, self).__init__() + # Value type + self._dict['time'] = _translate( "CustomPlot", "Time (sec)" ) - self._dict['kp'] = _translate( "CustomPlot", "Kp (m)" ) - self._dict['elevation'] = _translate( "CustomPlot", "Elevation (m)" ) - self._dict['water_elevation'] = _translate( "CustomPlot", "Water elevation (m)" ) - self._dict['discharge'] = _translate( "CustomPlot", "Discharge (m³/s)" ) + # Unit corresponding long name (plot axes display) + + self._dict['meter'] = _translate( + "CustomPlot", "Elevation (m)" + ) + self._dict['m3s'] = _translate( + "CustomPlot", "Discharge (m³/s)" + ) + # SubDict self._sub_dict["values_x"] = { "kp": self._dict["kp"], "time": self._dict["time"], } - self._sub_dict["values_y"] = { "elevation": self._dict["elevation"], "water_elevation": self._dict["water_elevation"], diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index 353a036c..eb8c5b1d 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -38,7 +38,7 @@ from PyQt5.QtWidgets import ( QFileDialog, QTableView, QAbstractItemView, QUndoStack, QShortcut, QAction, QItemDelegate, QComboBox, QVBoxLayout, QHeaderView, QTabWidget, - QSlider, QLabel, + QSlider, QLabel, QWidget, QGridLayout, ) from View.Tools.Plot.PamhyrCanvas import MplCanvas @@ -51,6 +51,7 @@ 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, ) @@ -91,6 +92,8 @@ class ResultsWindow(PamhyrWindow): parent=parent ) + self._additional_plot = {} + self.setup_table() self.setup_plot() self.setup_slider() @@ -377,6 +380,27 @@ class ResultsWindow(PamhyrWindow): 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() @@ -408,8 +432,53 @@ class ResultsWindow(PamhyrWindow): def _add_custom_plot(self): dlg = CustomPlotValuesSelectionDialog(parent=self) if dlg.exec(): - value = dlg.value - logger.info(value) + x, y = dlg.value + self.create_new_tab_custom_plot(x, y) + + def create_new_tab_custom_plot(self, x:str, y:list): + name = f"{x}: {','.join(y)}" + wname = f"tab_custom_{x}_{y}" + + tab_widget = self.find(QTabWidget, f"tabWidget") + + # This plot already exists + if name in self._additional_plot: + 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, + self._get_current_reach(), + self._get_current_profile(), + self._get_current_timestamp(), + data=self._results, + canvas=canvas, + toolbar=toolbar, + trad=self._trad, + 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) def _copy(self): logger.info("TODO: copy") -- GitLab