From 35ee6617ac6aaa41764530aa09229a966ccc4cef Mon Sep 17 00:00:00 2001
From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr>
Date: Fri, 11 Aug 2023 09:28:15 +0200
Subject: [PATCH] Results: Add hydrograph.

---
 src/View/Results/PlotH.py  | 131 +++++++++++++++++++++++++++++++++++++
 src/View/Results/Window.py |  19 ++++++
 2 files changed, 150 insertions(+)
 create mode 100644 src/View/Results/PlotH.py

diff --git a/src/View/Results/PlotH.py b/src/View/Results/PlotH.py
new file mode 100644
index 00000000..dcc9f7f6
--- /dev/null
+++ b/src/View/Results/PlotH.py
@@ -0,0 +1,131 @@
+# PlotH.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, trace
+from View.Plot.APlot import APlot
+
+from PyQt5.QtCore import (
+    QCoreApplication
+)
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class PlotH(APlot):
+    def __init__(self, canvas=None, results=None,
+                 reach_id=0, profile_id=0,
+                 toolbar=None, display_current=True):
+        super(PlotH, self).__init__(
+            canvas=canvas,
+            data=results,
+            toolbar=toolbar
+        )
+
+        self.display_current = display_current
+
+        self._current_timestamp = max(results.get("timestamps"))
+        self._current_reach_id = reach_id
+        self._current_profile_id = profile_id
+
+    @property
+    def results(self):
+        return self.data
+
+    @timer
+    def draw(self, highlight=None):
+        self.canvas.axes.cla()
+        self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+
+        if self.results is None:
+            return
+
+        reach = self.results.river.reach(self._current_reach_id)
+        profile = reach.profile(self._current_profile_id)
+
+        if reach.geometry.number_profiles == 0:
+            self._init = False
+            return
+
+        kp_min, kp_max = (-1, -1)
+        if highlight is not None:
+            kp_min, kp_max = highlight
+
+        # Axes
+        self.canvas.axes.set_xlabel(
+            _translate("Results", "Time (s)"),
+            color='green', fontsize=12
+        )
+        self.canvas.axes.set_ylabel(
+            _translate("Results", "Discharge (m³/s)"),
+            color='green', fontsize=12
+        )
+
+        ts = list(self.results.get("timestamps"))
+        ts.sort()
+
+        self.canvas.axes.set_xlim(
+            left = min(ts), right = max(ts)
+        )
+
+        # Draw discharge for each timestamp
+        x = ts
+        y = profile.get_key("Q")
+
+        if len(ts) != len(x):
+            logger.warning(
+                "Results as less Q data ({len(x)}) " +
+                "than timestamps ({len(ts)}) " +
+                "for profile {self._current_profile_id}"
+            )
+            return
+
+        self._line = [
+            self.canvas.axes.plot(
+                x, y, lw=1.,
+                color='r',
+                markersize=3, marker='+'
+            )
+        ]
+
+        self.canvas.axes.autoscale_view(True, True, True)
+        self.canvas.axes.autoscale()
+        self.canvas.figure.tight_layout()
+        self.canvas.figure.canvas.draw_idle()
+        if self.toolbar is not None:
+            self.toolbar.update()
+
+    def set_reach(self, reach_id):
+        self._current_reach_id = reach_id
+        self._current_profile_id = 0
+        self.draw()
+
+    def set_profile(self, profile_id):
+        self._current_profile_id = profile_id
+        self.draw()
+
+    def set_timestamp(self, timestamp):
+        self._current_timestamp = timestamp
+        self.draw()
+
+    def update(self):
+        self.draw()
diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py
index 99022b2f..22d0a2c4 100644
--- a/src/View/Results/Window.py
+++ b/src/View/Results/Window.py
@@ -45,6 +45,7 @@ from View.Plot.MplCanvas import MplCanvas
 from View.Results.PlotXY import PlotXY
 from View.Results.PlotAC import PlotAC
 from View.Results.PlotKPC import PlotKPC
+from View.Results.PlotH import PlotH
 
 from View.Results.Table import TableModel
 from View.Results.translate import *
@@ -165,6 +166,20 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
         )
         self.plot_ac.draw()
 
+        self.canvas_4 = MplCanvas(width=5, height=4, dpi=100)
+        self.canvas_4.setObjectName("canvas_4")
+        self.plot_layout_4 = self.find(QVBoxLayout, "verticalLayout_hydrograph")
+        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,
+            toolbar = None
+        )
+        self.plot_h.draw()
+
     def setup_connections(self):
         self.undo_sc.activated.connect(self.undo)
         self.redo_sc.activated.connect(self.redo)
@@ -194,18 +209,22 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
             self.plot_xy.set_reach(reach_id)
             self.plot_ac.set_reach(reach_id)
             self.plot_kpc.set_reach(reach_id)
+            self.plot_h.set_reach(reach_id)
         if profile_id is not None:
             self.plot_xy.set_profile(profile_id)
             self.plot_ac.set_profile(profile_id)
             self.plot_kpc.set_profile(profile_id)
+            self.plot_h.set_profile(profile_id)
         if timestamp is not None:
             self.plot_xy.set_timestamp(timestamp)
             self.plot_ac.set_timestamp(timestamp)
             self.plot_kpc.set_timestamp(timestamp)
+            self.plot_h.set_timestamp(timestamp)
 
         self.plot_xy.draw()
         self.plot_ac.draw()
         self.plot_kpc.draw()
+        self.plot_h.draw()
 
 
     def _set_current_reach(self):
-- 
GitLab