From fa8f07b97e63c95be560d2f333898e8f282863f7 Mon Sep 17 00:00:00 2001
From: Theophile Terraz <theophile.terraz@inrae.fr>
Date: Tue, 4 Feb 2025 11:12:56 +0100
Subject: [PATCH] work on multiple results plot

---
 doc/dev/documentation.org                     |   2 +-
 .../simhydro/presentation/presentation.org    |   4 +-
 .../TP_Hydraulique_Hogneau/step-by-step.tex   |   2 +-
 src/View/Results/CustomPlot/Plot.py           |  84 +++----
 src/View/Results/PlotAC.py                    |   4 +-
 src/View/Results/PlotH.py                     |  56 +++--
 src/View/Results/PlotRKC.py                   |   4 +-
 src/View/Results/PlotXY.py                    |   4 +-
 src/View/Results/Window.py                    |  13 +-
 src/View/Translate.py                         |  16 +-
 src/lang/fr.ts                                | 231 ++++--------------
 11 files changed, 155 insertions(+), 265 deletions(-)

diff --git a/doc/dev/documentation.org b/doc/dev/documentation.org
index 7e96edc4..40fe4e0e 100644
--- a/doc/dev/documentation.org
+++ b/doc/dev/documentation.org
@@ -1375,7 +1375,7 @@ contribution.
 #+INCLUDE: "../../AUTHORS" src text
 
 [fn:p2-gitlab] The {{{pamhyr2}}} Gitlab project page:
-https://gitlab.irstea.fr/theophile.terraz/pamhyr
+https://gitlab.com/pamhyr/pamhyr2
 [fn:inrae] The INRAE web site: https://www.inrae.fr/
 
 ** Translate
diff --git a/doc/paper/2023/simhydro/presentation/presentation.org b/doc/paper/2023/simhydro/presentation/presentation.org
index 8cabf332..f8457d23 100644
--- a/doc/paper/2023/simhydro/presentation/presentation.org
+++ b/doc/paper/2023/simhydro/presentation/presentation.org
@@ -424,7 +424,7 @@ Create a new version of {{{pamhyr}}} called {{{pamhyr2}}}
 
 ** Contribution
 #+LaTeX: \begin{center}
-\faIcon{gitlab} https://gitlab.irstea.fr/theophile.terraz/pamhyr/
+\faIcon{gitlab} https://gitlab.com/pamhyr/pamhyr2/
 #+LaTeX: \end{center}
 
 *** For users
@@ -462,7 +462,7 @@ Create a new version of {{{pamhyr}}} called {{{pamhyr2}}}
 # #+END_EXPORT
 
 #+LaTeX: \begin{center}
-\faIcon{gitlab} https://gitlab.irstea.fr/theophile.terraz/pamhyr/
+\faIcon{gitlab} https://gitlab.com/pamhyr/pamhyr2/
 #+LaTeX: \end{center}
 
 #+LaTeX: \begin{center}
diff --git a/doc/users/TP_Hydraulique_Hogneau/step-by-step.tex b/doc/users/TP_Hydraulique_Hogneau/step-by-step.tex
index 87e1a37f..4541f95a 100644
--- a/doc/users/TP_Hydraulique_Hogneau/step-by-step.tex
+++ b/doc/users/TP_Hydraulique_Hogneau/step-by-step.tex
@@ -101,7 +101,7 @@ Authors : & Pierre-Antoine Rouby & pierre-antoine.rouby@inrae.fr\tabularnewline
 
 \section{Install Pamhyr2}
 
-Pamhyr2 can be downloaded from \url{https://gitlab.irstea.fr/theophile.terraz/pamhyr}.
+Pamhyr2 can be downloaded from \url{https://gitlab.com/pamhyr/pamhyr2}.
 \begin{center}
 \includegraphics[width=15cm]{img/dl.png}
 \par\end{center}
diff --git a/src/View/Results/CustomPlot/Plot.py b/src/View/Results/CustomPlot/Plot.py
index 28ae310c..e67a6ea6 100644
--- a/src/View/Results/CustomPlot/Plot.py
+++ b/src/View/Results/CustomPlot/Plot.py
@@ -49,7 +49,7 @@ unit = {
 
 class CustomPlot(PamhyrPlot):
     def __init__(self, x, y, envelop, reach, profile, timestamp,
-                 data=None, canvas=None, trad=None, res_id=0,
+                 data=None, canvas=None, trad=None, res_id=[0],
                  toolbar=None, parent=None):
         super(CustomPlot, self).__init__(
             canvas=canvas,
@@ -65,7 +65,7 @@ class CustomPlot(PamhyrPlot):
         self._reach = reach
         self._profile = profile
         self._timestamp = timestamp
-        self._current_res_id = res_id
+        self._current_res_id = res_id[0]
         self._parent = parent
 
         logger.debug(
@@ -133,7 +133,7 @@ class CustomPlot(PamhyrPlot):
         """
         Get SL list for profile p at initial time (initial data)
         """
-        t0 = min(list(self.data[self._current_res_id].get("timestamps")))
+        t0 = min(list(self.data[self._current_res_id[0]].get("timestamps")))
         return map(
             lambda p: p.get_ts_key(t0, "sl")[0],
             reach.profiles
@@ -148,8 +148,8 @@ class CustomPlot(PamhyrPlot):
             reach.profiles
         )
 
-    def get_ts_zmin(self, profile):
-        results = self.data[self._current_res_id]
+    def get_ts_zmin(self, profile, res_id):
+        results = self.data[res_id]
         nt = len(list(results.get("timestamps")))
         reach = results.river.reach(self._reach)
         berdrock = self.sl_compute_bedrock(reach)
@@ -170,6 +170,7 @@ class CustomPlot(PamhyrPlot):
         return ts_z_min
 
     def _draw_rk(self):
+        #for res_id in self._current_res_id:
         results = self.data[self._current_res_id]
         reach = results.river.reach(self._reach)
         if self._current_res_id == 2:  # compare results
@@ -215,7 +216,7 @@ class CustomPlot(PamhyrPlot):
         if "bed_elevation" in self._y:
 
             ax = self._axes[unit["bed_elevation"]]
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 line = ax.plot(
                     rk, z_min,
                     color='grey', lw=1.,
@@ -242,13 +243,13 @@ class CustomPlot(PamhyrPlot):
 
             if (self._envelop and
                     reach.has_sediment() and
-                    self._current_res_id != 2):
+                    self._current_res_id < 2):
 
                 ax = self._axes[unit["bed_elevation_envelop"]]
 
                 e = list(
                         map(
-                            lambda p: max(self.get_ts_zmin(p)),
+                            lambda p: max(self.get_ts_zmin(p, res_id)),
                             range(len(reach))
                         )
                     )
@@ -261,7 +262,7 @@ class CustomPlot(PamhyrPlot):
 
                 e = list(
                         map(
-                            lambda p: min(self.get_ts_zmin(p)),
+                            lambda p: min(self.get_ts_zmin(p, res_id)),
                             range(len(reach))
                         )
                     )
@@ -281,7 +282,7 @@ class CustomPlot(PamhyrPlot):
             )
             self.lines["water_elevation"] = line
 
-            if "bed_elevation" in self._y and self._current_res_id != 2:
+            if "bed_elevation" in self._y and self._current_res_id < 2:
                 self.fill = ax.fill_between(
                     rk, z_min, z,
                     color='blue', alpha=0.5, interpolate=True
@@ -398,7 +399,7 @@ class CustomPlot(PamhyrPlot):
         if "depth" in self._y:
 
             ax = self._axes[unit["depth"]]
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(
                         lambda p: p.geometry.max_water_depth(
@@ -434,7 +435,7 @@ class CustomPlot(PamhyrPlot):
             )
             self.lines["depth"] = line
 
-            if self._envelop and self._current_res_id != 2:
+            if self._envelop and self._current_res_id < 2:
 
                 ax = self._axes[unit["depth_envelop"]]
 
@@ -467,7 +468,7 @@ class CustomPlot(PamhyrPlot):
         if "mean_depth" in self._y:
 
             ax = self._axes[unit["mean_depth"]]
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(
                         lambda p: p.geometry.mean_water_depth(
@@ -506,7 +507,7 @@ class CustomPlot(PamhyrPlot):
         if "froude" in self._y:
 
             ax = self._axes[unit["froude"]]
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 fr = list(
                     map(
                         lambda p:
@@ -562,7 +563,7 @@ class CustomPlot(PamhyrPlot):
         if "wet_area" in self._y:
 
             ax = self._axes[unit["wet_area"]]
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(
                         lambda p: p.geometry.wet_area(
@@ -640,7 +641,7 @@ class CustomPlot(PamhyrPlot):
             )
         )
         if "bed_elevation" in self._y:
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 dz = z_min
             else:
                 if reach.has_sediment():
@@ -660,7 +661,7 @@ class CustomPlot(PamhyrPlot):
         if "water_elevation" in self._y:
             self.lines["water_elevation"][0].set_ydata(z)
 
-            if "bed_elevation" in self._y and self._current_res_id != 2:
+            if "bed_elevation" in self._y and self._current_res_id < 2:
                 ax = self._axes[unit["water_elevation"]]
                 self.fill.remove()
                 self.fill = ax.fill_between(
@@ -675,7 +676,7 @@ class CustomPlot(PamhyrPlot):
             self.lines["velocity"][0].set_ydata(v)
 
         if "depth" in self._y:
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(
                         lambda p: p.geometry.max_water_depth(
@@ -708,7 +709,7 @@ class CustomPlot(PamhyrPlot):
             self.lines["depth"][0].set_ydata(d)
 
         if "mean_depth" in self._y:
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(
                         lambda p: p.geometry.mean_water_depth(
@@ -741,7 +742,7 @@ class CustomPlot(PamhyrPlot):
             self.lines["mean_depth"][0].set_ydata(d)
 
         if "froude" in self._y:
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 fr = list(
                     map(
                         lambda p:
@@ -792,7 +793,7 @@ class CustomPlot(PamhyrPlot):
             self.lines["froude"][0].set_ydata(fr)
 
         if "wet_area" in self._y:
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(
                         lambda p: p.geometry.wet_area(
@@ -901,9 +902,9 @@ class CustomPlot(PamhyrPlot):
         z = profile.get_key("Z")
         v = profile.get_key("V")
         z_min = profile.geometry.z_min()
-        if self._current_res_id != 2:
+        if self._current_res_id < 2:
             if reach.has_sediment():
-                ts_z_min = self.get_ts_zmin(self._profile)
+                ts_z_min = self.get_ts_zmin(self._profile, res_id)
             else:
                 ts_z_min = list(
                     map(
@@ -920,8 +921,8 @@ class CustomPlot(PamhyrPlot):
 
             if self._current_res_id == 2:
                 if reach.has_sediment():
-                    ts_z_min1 = self.get_ts_zmin(self._profile1)
-                    ts_z_min2 = self.get_ts_zmin(self._profile2)
+                    ts_z_min1 = self.get_ts_zmin(self._profile1, 0)
+                    ts_z_min2 = self.get_ts_zmin(self._profile2, 1)
                     ts_z_min = list(
                         map(
                             lambda x, y: x - y,
@@ -953,7 +954,7 @@ class CustomPlot(PamhyrPlot):
             )
             self.lines["water_elevation"] = line
 
-            if "bed_elevation" in self._y and self._current_res_id != 2:
+            if "bed_elevation" in self._y and self._current_res_id < 2:
 
                 self.fill = ax.fill_between(
                     ts, ts_z_min, z,
@@ -982,7 +983,7 @@ class CustomPlot(PamhyrPlot):
         if "depth" in self._y:
 
             ax = self._axes[unit["depth"]]
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(lambda z: profile.geometry.max_water_depth(z), z)
                 )
@@ -1009,7 +1010,7 @@ class CustomPlot(PamhyrPlot):
         if "mean_depth" in self._y:
 
             ax = self._axes[unit["mean_depth"]]
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(lambda z: profile.geometry.mean_water_depth(z), z)
                 )
@@ -1036,7 +1037,7 @@ class CustomPlot(PamhyrPlot):
         if "froude" in self._y:
 
             ax = self._axes[unit["froude"]]
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(lambda z, v:
                         v /
@@ -1077,7 +1078,7 @@ class CustomPlot(PamhyrPlot):
         if "wet_area" in self._y:
 
             ax = self._axes[unit["wet_area"]]
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(lambda z: profile.geometry.wet_area(z), z)
                 )
@@ -1136,7 +1137,7 @@ class CustomPlot(PamhyrPlot):
         q = profile.get_key("Q")
         z = profile.get_key("Z")
         v = profile.get_key("V")
-        if self._current_res_id != 2:
+        if self._current_res_id < 2:
             if reach.has_sediment():
                 ts_z_min = self.get_ts_zmin(self._profile)
             else:
@@ -1150,8 +1151,8 @@ class CustomPlot(PamhyrPlot):
         if "bed_elevation" in self._y:
             if self._current_res_id == 2:
                 if reach.has_sediment():
-                    ts_z_min1 = self.get_ts_zmin(self._profile1)
-                    ts_z_min2 = self.get_ts_zmin(self._profile2)
+                    ts_z_min1 = self.get_ts_zmin(self._profile1, 0)
+                    ts_z_min2 = self.get_ts_zmin(self._profile2, 1)
                     ts_z_min = list(
                         map(
                             lambda x, y: x - y,
@@ -1172,7 +1173,7 @@ class CustomPlot(PamhyrPlot):
         if "water_elevation" in self._y:
             self.lines["water_elevation"][0].set_ydata(z)
 
-            if "bed_elevation" in self._y and self._current_res_id != 2:
+            if "bed_elevation" in self._y and self._current_res_id < 2:
                 ax = self._axes[unit["bed_elevation"]]
                 self.fill.remove()
                 self.fill = ax.fill_between(
@@ -1187,7 +1188,7 @@ class CustomPlot(PamhyrPlot):
             self.lines["velocity"][0].set_ydata(v)
 
         if "depth" in self._y:
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(lambda z: profile.geometry.max_water_depth(z), z)
                 )
@@ -1208,7 +1209,7 @@ class CustomPlot(PamhyrPlot):
             self.lines["depth"][0].set_ydata(d)
 
         if "mean_depth" in self._y:
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(lambda z: profile.geometry.mean_water_depth(z), z)
                 )
@@ -1229,7 +1230,7 @@ class CustomPlot(PamhyrPlot):
             self.lines["mean_depth"][0].set_ydata(d)
 
         if "froude" in self._y:
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(lambda z, v:
                         v /
@@ -1265,7 +1266,7 @@ class CustomPlot(PamhyrPlot):
             self.lines["froude"][0].set_ydata(d)
 
         if "wet_area" in self._y:
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 d = list(
                     map(lambda z: profile.geometry.wet_area(z), z)
                 )
@@ -1319,7 +1320,7 @@ class CustomPlot(PamhyrPlot):
             color='black', fontsize=10
         )
 
-        if self._current_res_id != 2:
+        if self._current_res_id < 2:
             self.canvas.axes.set_ylabel(
                 self._trad[self._y_axes[0]],
                 color='black', fontsize=10
@@ -1334,14 +1335,13 @@ class CustomPlot(PamhyrPlot):
         if len(self.lines) != 0:
             self.lines.clear()
         for axes in self._y_axes[1:]:
-            print("axes: ", axes)
             if axes in self._axes.keys():
                 for ll in self._axes[axes].lines:
                     ll.remove()
             else:
                 ax_new = self.canvas.axes.twinx()
                 self._axes[axes] = ax_new
-            if self._current_res_id != 2:
+            if self._current_res_id < 2:
                 self._axes[axes].set_ylabel(
                     self._trad[axes],
                     color='black', fontsize=10
@@ -1398,7 +1398,7 @@ class CustomPlot(PamhyrPlot):
             self.draw_current()
 
     def set_result(self, res_id):
-        self._current_res_id = res_id
+        self._current_res_id = res_id[0]
         self.draw()
 
     def set_timestamp(self, timestamp):
diff --git a/src/View/Results/PlotAC.py b/src/View/Results/PlotAC.py
index 614d1b4e..77877022 100644
--- a/src/View/Results/PlotAC.py
+++ b/src/View/Results/PlotAC.py
@@ -41,7 +41,7 @@ class PlotAC(PamhyrPlot):
 
         self._current_reach_id = reach_id
         self._current_profile_id = profile_id
-        self._current_res_id = res_id
+        self._current_res_id = res_id[0]
         self._timestamps = parent._timestamps
         self._current_timestamp = max(self._timestamps)
 
@@ -144,7 +144,7 @@ class PlotAC(PamhyrPlot):
         self.update()
 
     def set_result(self, res_id):
-        self._current_res_id = res_id
+        self._current_res_id = res_id[0]
         self.update()
 
     def set_timestamp(self, timestamp):
diff --git a/src/View/Results/PlotH.py b/src/View/Results/PlotH.py
index 09d6acb3..3dfe2466 100644
--- a/src/View/Results/PlotH.py
+++ b/src/View/Results/PlotH.py
@@ -35,7 +35,7 @@ logger = logging.getLogger()
 
 class PlotH(PamhyrPlot):
     def __init__(self, canvas=None, trad=None, toolbar=None,
-                 results=None, reach_id=0, profile_id=0, res_id=0,
+                 results=None, reach_id=0, profile_id=0, res_id=[0],
                  parent=None):
         super(PlotH, self).__init__(
             canvas=canvas,
@@ -65,6 +65,9 @@ class PlotH(PamhyrPlot):
         # self._auto_relim_update = False
         # self._autoscale_update = False
 
+        self._line_max = []
+        self._line = []
+
     @property
     def results(self):
         return self.data
@@ -82,19 +85,33 @@ class PlotH(PamhyrPlot):
         if self.results is None:
             return
 
-        if self.results[self._current_res_id] is None:
+        if len(self._current_res_id) < 1:
             return
 
-        results = self.results[self._current_res_id]
-        reach = results.river.reach(self._current_reach_id)
-        profile = reach.profile(self._current_profile_id)
+        for res_id in self._current_res_id:
+            if self.results[res_id] is None:
+                continue
 
-        if reach.geometry.number_profiles == 0:
-            self._init = False
-            return
+            results = self.results[res_id]
+            reach = results.river.reach(self._current_reach_id)
+            profile = reach.profile(self._current_profile_id)
+
+            if reach.geometry.number_profiles == 0:
+                self._init = False
+                return
 
-        self.draw_max(reach)
-        self.draw_data(reach, profile)
+            self.draw_max(reach)
+            self.draw_data(reach, profile)
+
+        self.canvas.axes.set_xlabel(
+            self._trad["unit_time_s"],
+            color='black', fontsize=10
+        )
+
+        self.canvas.axes.set_ylabel(
+            self._trad["unit_discharge"],
+            color='black', fontsize=10
+        )
 
         self.set_ticks_time_formater()
 
@@ -110,12 +127,13 @@ class PlotH(PamhyrPlot):
         x = self._timestamps
         y = profile.get_key("Q")
 
-        self._line, = self.canvas.axes.plot(
+        line, = self.canvas.axes.plot(
             x, y,
             label=self.label_discharge,
             color=self.color_plot,
             **self.plot_default_kargs
         )
+        self._line.append(line)
 
     def draw_current(self):
         self._current, = self.canvas.axes.plot(
@@ -138,13 +156,14 @@ class PlotH(PamhyrPlot):
                 ts_y = max(ts_y, q)
             y.append(ts_y)
 
-        self._line_max, = self.canvas.axes.plot(
+        m, = self.canvas.axes.plot(
             x, y,
             label=self.label_discharge_max,
             color=self.color_plot_highlight,
             linestyle='dotted',
             **self.plot_default_kargs
         )
+        self._line_max.append(m)
 
     def set_reach(self, reach_id):
         self._current_reach_id = reach_id
@@ -173,14 +192,15 @@ class PlotH(PamhyrPlot):
         self.update_idle()
 
     def update_data(self):
-        results = self.results[self._current_res_id]
-        reach = results.river.reach(self._current_reach_id)
-        profile = reach.profile(self._current_profile_id)
+        for res, res_id in enumerate(self._current_res_id):
+            results = self.results[res_id]
+            reach = results.river.reach(self._current_reach_id)
+            profile = reach.profile(self._current_profile_id)
 
-        x = self._timestamps
-        y = profile.get_key("Q")
+            x = self._timestamps
+            y = profile.get_key("Q")
 
-        self._line.set_data(x, y)
+            self._line[res].set_data(x, y)
 
     def update_current(self):
         y = self._current.get_ydata()
diff --git a/src/View/Results/PlotRKC.py b/src/View/Results/PlotRKC.py
index 8abe8ad9..e1f53c6c 100644
--- a/src/View/Results/PlotRKC.py
+++ b/src/View/Results/PlotRKC.py
@@ -44,7 +44,7 @@ class PlotRKC(PamhyrPlot):
 
         self._current_reach_id = reach_id
         self._current_profile_id = profile_id
-        self._current_res_id = res_id
+        self._current_res_id = res_id[0]
         self._timestamps = parent._timestamps
         self._current_timestamp = max(self._timestamps)
 
@@ -323,7 +323,7 @@ class PlotRKC(PamhyrPlot):
         self.update_current()
 
     def set_result(self, res_id):
-        self._current_res_id = res_id
+        self._current_res_id = res_id[0]
         self.update()
 
     def set_timestamp(self, timestamp):
diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py
index 013e746e..5fb00460 100644
--- a/src/View/Results/PlotXY.py
+++ b/src/View/Results/PlotXY.py
@@ -56,7 +56,7 @@ class PlotXY(PamhyrPlot):
         self._current_timestamp = max(self._timestamps)
         self._current_reach_id = reach_id
         self._current_profile_id = profile_id
-        self._current_res_id = res_id
+        self._current_res_id = res_id[0]
 
         self.label_x = _translate("Results", "X (m)")
         self.label_y = _translate("Results", "Y (m)")
@@ -316,7 +316,7 @@ class PlotXY(PamhyrPlot):
         self.update_idle()
 
     def set_result(self, res_id):
-        self._current_res_id = res_id
+        self._current_res_id = res_id[0]
         self.update()
 
     def set_timestamp(self, timestamp):
diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py
index ad1c2b7f..6616ac8b 100644
--- a/src/View/Results/Window.py
+++ b/src/View/Results/Window.py
@@ -88,7 +88,7 @@ class ResultsWindow(PamhyrWindow):
                  results=None, parent=None, trad=None):
         self._solvers = [r._solver for r in results]
         self._results = results
-        self._current_results = 0
+        self._current_results = [0]
 
         if trad is None:
             trad = ResultsTranslate()
@@ -125,8 +125,9 @@ class ResultsWindow(PamhyrWindow):
             return
 
         self.update(reach_id=0,
-                    profile_id=0,
-                    solver_id=0)
+                    profile_id=0)
+
+        self.update_table_selection_solver(0)
 
     def setup_table(self):
         self._table = {}
@@ -147,7 +148,7 @@ class ResultsWindow(PamhyrWindow):
             table.hide()
 
     def setup_slider(self):
-        default_reach = self._results[self._current_results].river.reach(0)
+        default_reach = self._results[self._current_results[0]].river.reach(0)
 
         self._slider_time = self.find(QSlider, f"horizontalSlider_time")
         self._slider_time.setMaximum(len(self._timestamps) - 1)
@@ -450,8 +451,6 @@ class ResultsWindow(PamhyrWindow):
             for plot in self._additional_plot:
                 self._additional_plot[plot].set_result(solver_id)
 
-            self.update_table_selection_solver(solver_id)
-
         if timestamp is not None:
             self.plot_xy.set_timestamp(timestamp)
             self.plot_ac.set_timestamp(timestamp)
@@ -512,7 +511,7 @@ class ResultsWindow(PamhyrWindow):
         if len(indexes) == 0:
             return
 
-        self.update(solver_id=indexes[0].row())
+        self.update(solver_id=[i.row() for i in indexes])
 
     def _set_current_timestamp(self):
         timestamp = self._timestamps[self._slider_time.value()]
diff --git a/src/View/Translate.py b/src/View/Translate.py
index 988f55db..3abf9b9c 100644
--- a/src/View/Translate.py
+++ b/src/View/Translate.py
@@ -106,16 +106,13 @@ class UnitTranslate(CommonWordTranslate):
         self._dict["unit_min_velocity"] = _translate(
             "Unit", "Min Velocity (m/s)"
         )
-        self._dict["unit_discharge"] = _translate("Unit", "Discharge (m³/s)")
+        self._dict["unit_discharge"] = _translate("Unit", "Discharge") + " (m³/s)"
         self._dict["unit_discharge_envelop"] = _translate(
-            "Unit", "Discharge Envelop (m³/s)"
-        )
+            "Unit", "Discharge Envelop") + " (m³/s)"
         self._dict["unit_max_discharge"] = _translate(
-            "Unit", "Max Discharge (m³/s)"
-        )
+            "Unit", "Max Discharge") + " (m³/s)"
         self._dict["unit_min_discharge"] = _translate(
-            "Unit", "Min Discharge (m³/s)"
-        )
+            "Unit", "Min Discharge") + " (m³/s)"
         self._dict["unit_area_he"] = _translate("Unit", "Area (hectare)")
 
         self._dict["unit_time_s"] = _translate("Unit", "Time (sec)")
@@ -136,7 +133,7 @@ class UnitTranslate(CommonWordTranslate):
         self._dict["unit_concentration"] = _translate(
             "Unit", "Concentration (g/l)"
         )
-        self._dict["unit_wet_area"] = _translate("Unit", "Wet Area (m²)")
+        self._dict["unit_wet_area"] = _translate("Unit", "Wet Area") + " (m²)"
         self._dict["unit_wet_perimeter"] = _translate(
             "Unit", "Wet Perimeter (m)"
         )
@@ -146,8 +143,7 @@ class UnitTranslate(CommonWordTranslate):
         self._dict["unit_froude"] = _translate("Unit", "Froude number")
         self._dict["unit_mass"] = _translate("Unit", "Mass (kg)")
         self._dict["unit_concentration"] = _translate(
-            "Unit", "Concentration (kg/m³)"
-        )
+            "Unit", "Concentration") + " (kg/m³)"
 
 
 class MainTranslate(UnitTranslate):
diff --git a/src/lang/fr.ts b/src/lang/fr.ts
index 7baa3c41..3c36b6cf 100644
--- a/src/lang/fr.ts
+++ b/src/lang/fr.ts
@@ -28,11 +28,6 @@
 </context>
 <context>
     <name>BasicHydraulicStructures</name>
-    <message>
-        <location filename="../View/HydraulicStructures/BasicHydraulicStructures/Translate.py" line="30"/>
-        <source>Basic Hydraulic Structure</source>
-        <translation type="obsolete">Ouvrage hydraulique élémentaire</translation>
-    </message>
     <message>
         <location filename="../View/HydraulicStructures/BasicHydraulicStructures/Translate.py" line="34"/>
         <source>Change hydraulic structure type</source>
@@ -269,19 +264,6 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <translation>Polluant</translation>
     </message>
 </context>
-<context>
-    <name>BoundaryConditionAdisTS</name>
-    <message>
-        <location filename="../View/BoundaryConditionsAdisTS/Edit/translate.py" line="32"/>
-        <source>Edit boundary conditions AdisTS</source>
-        <translation type="obsolete">Éditer les conditions aux limites AdisTS</translation>
-    </message>
-    <message>
-        <location filename="../View/BoundaryConditionsAdisTS/Edit/translate.py" line="40"/>
-        <source>Concentration</source>
-        <translation type="obsolete">Concentration</translation>
-    </message>
-</context>
 <context>
     <name>BoundaryConditions</name>
     <message>
@@ -525,11 +507,6 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <source>Custom plot selection</source>
         <translation>Sélection des graphiques personnalisés</translation>
     </message>
-    <message>
-        <location filename="../View/Results/CustomPlot/Translate.py" line="40"/>
-        <source>Bed elevation (m)</source>
-        <translation type="obsolete">Cote du fond (m)</translation>
-    </message>
     <message>
         <location filename="../View/Results/CustomPlot/Translate.py" line="61"/>
         <source>Elevation (m)</source>
@@ -852,11 +829,6 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <source>Parameters</source>
         <translation>Paramètres</translation>
     </message>
-    <message>
-        <location filename="../View/ui/ConfigureDialog.ui" line="385"/>
-        <source>Langue</source>
-        <translation type="obsolete">Langue</translation>
-    </message>
     <message>
         <location filename="../View/ui/REPLineDialog.ui" line="57"/>
         <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Comment lines start with &apos;*&apos; char (let see Mage documentation for more details)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
@@ -1102,11 +1074,6 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <source>...</source>
         <translation>...</translation>
     </message>
-    <message>
-        <location filename="../View/ui/about.ui" line="131"/>
-        <source>Version: @version</source>
-        <translation type="obsolete">Version : @version</translation>
-    </message>
     <message>
         <location filename="../View/ui/about.ui" line="168"/>
         <source>License: GPLv3+</source>
@@ -1290,16 +1257,6 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <source>End (m)</source>
         <translation>PK de fin (m)</translation>
     </message>
-    <message>
-        <location filename="../View/Frictions/translate.py" line="47"/>
-        <source>Start coefficient</source>
-        <translation type="obsolete">Coefficient de départ</translation>
-    </message>
-    <message>
-        <location filename="../View/Frictions/translate.py" line="48"/>
-        <source>End coefficient</source>
-        <translation type="obsolete">Coefficient de fin</translation>
-    </message>
     <message>
         <location filename="../View/Frictions/translate.py" line="34"/>
         <source>Stricklers</source>
@@ -1473,18 +1430,6 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <source>Shift</source>
         <translation>Translater</translation>
     </message>
-    <message>
-        <location filename="../View/BoundaryCondition/Edit/translate.py" line="48"/>
-        <source>No geometry</source>
-        <translation type="obsolete">Aucune géométrie</translation>
-    </message>
-    <message>
-        <location filename="../View/BoundaryCondition/Edit/translate.py" line="51"/>
-        <source>No geometry found for this reach.
-This feature requires a reach with a geometry.</source>
-        <translation type="obsolete">Aucune géométrie n&apos;a été trouvée sur ce bief.
-Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translation>
-    </message>
 </context>
 <context>
     <name>HydraulicStructures</name>
@@ -1594,17 +1539,17 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
 <context>
     <name>MainWindow</name>
     <message>
-        <location filename="../View/Translate.py" line="164"/>
+        <location filename="../View/Translate.py" line="160"/>
         <source>Open debug window</source>
         <translation>Ouvrir la fenêtre de débogage</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="167"/>
+        <location filename="../View/Translate.py" line="163"/>
         <source>Open SQLite debuging tool (&apos;sqlitebrowser&apos;)</source>
         <translation>Ouvrir l&apos;outil de débogage SQLite (&apos;sqlitebrowser&apos;)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="170"/>
+        <location filename="../View/Translate.py" line="166"/>
         <source>Enable this window</source>
         <translation>Activer cette fenêtre</translation>
     </message>
@@ -2449,12 +2394,12 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <translation>Maillage</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="157"/>
+        <location filename="../View/Translate.py" line="153"/>
         <source>Summary</source>
         <translation>Résumé</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="160"/>
+        <location filename="../View/Translate.py" line="156"/>
         <source>Checks</source>
         <translation>Vérifications</translation>
     </message>
@@ -2674,52 +2619,47 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <translation>Données</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="178"/>
+        <location filename="../View/Translate.py" line="174"/>
         <source>Please select a reach</source>
         <translation>Veuillez sélectionner un bief</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="110"/>
-        <source>Geometry edition need a reach selected into the river network to work on it</source>
-        <translation type="obsolete">L&apos;édition de la géométrie nécessite un bief sélectionné dans le réseau fluvial pour pouvoir travailler dessus</translation>
-    </message>
-    <message>
-        <location filename="../View/Translate.py" line="187"/>
+        <location filename="../View/Translate.py" line="183"/>
         <source>Last open study</source>
         <translation>Dernière étude ouverte</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="190"/>
+        <location filename="../View/Translate.py" line="186"/>
         <source>Do you want to open again the last open study?</source>
         <translation>Voulez-vous rouvrir la dernière étude ?</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="181"/>
+        <location filename="../View/Translate.py" line="177"/>
         <source>This edition window need a reach selected into the river network to work on it</source>
         <translation>Cette fenêtre d&apos;édition a besoin d&apos;un bief sélectionné dans le réseau pour travailler dessus</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="195"/>
+        <location filename="../View/Translate.py" line="191"/>
         <source>Close without saving study</source>
         <translation>Fermer sans sauvegarder l&apos;étude</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="198"/>
+        <location filename="../View/Translate.py" line="194"/>
         <source>Do you want to save current study before closing it?</source>
         <translation>Souhaitez-vous sauvegarder l&apos;étude en cours avant de la fermer ?</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="175"/>
+        <location filename="../View/Translate.py" line="171"/>
         <source>Warning</source>
         <translation>Avertissement</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="202"/>
+        <location filename="../View/Translate.py" line="198"/>
         <source>X (m)</source>
         <translation>X (m)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="203"/>
+        <location filename="../View/Translate.py" line="199"/>
         <source>Y (m)</source>
         <translation>Y (m)</translation>
     </message>
@@ -2894,12 +2834,12 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <translation>Export données brutes</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="204"/>
+        <location filename="../View/Translate.py" line="200"/>
         <source>Yes</source>
         <translation>Oui</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="205"/>
+        <location filename="../View/Translate.py" line="201"/>
         <source>No</source>
         <translation>Non</translation>
     </message>
@@ -3128,12 +3068,7 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <translation>Lecture des résultats</translation>
     </message>
     <message>
-        <location filename="../View/Results/translate.py" line="40"/>
-        <source>River bottom</source>
-        <translation type="obsolete">Fond de la rivière</translation>
-    </message>
-    <message>
-        <location filename="../View/Results/translate.py" line="146"/>
+        <location filename="../View/Results/translate.py" line="147"/>
         <source>Water elevation</source>
         <translation>Cote de l&apos;eau</translation>
     </message>
@@ -3148,7 +3083,7 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <translation>Nom du bief</translation>
     </message>
     <message>
-        <location filename="../View/Results/translate.py" line="150"/>
+        <location filename="../View/Results/translate.py" line="153"/>
         <source>Profile</source>
         <translation>Profil</translation>
     </message>
@@ -3644,32 +3579,27 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <translation>Cote (m)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="63"/>
-        <source>Water elevation (m)</source>
-        <translation type="obsolete">Cote de l&apos;eau (m)</translation>
-    </message>
-    <message>
-        <location filename="../View/Translate.py" line="119"/>
+        <location filename="../View/Translate.py" line="116"/>
         <source>Area (hectare)</source>
         <translation>Aire (hectare)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="121"/>
+        <location filename="../View/Translate.py" line="118"/>
         <source>Time (sec)</source>
         <translation>Temps (s)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="122"/>
+        <location filename="../View/Translate.py" line="119"/>
         <source>Time (JJJ:HH:MM:SS)</source>
         <translation>Temps (JJJ:HH:MM:SS)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="124"/>
+        <location filename="../View/Translate.py" line="121"/>
         <source>Date (sec)</source>
         <translation>Date (s)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="125"/>
+        <location filename="../View/Translate.py" line="122"/>
         <source>Date (ISO format)</source>
         <translation>Date (format ISO)</translation>
     </message>
@@ -3694,25 +3624,20 @@ Cette fonctionnalité nécessite un bief muni d&apos;une géométrie.</translati
         <translation>Vitesse (m/s)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="140"/>
+        <location filename="../View/Translate.py" line="137"/>
         <source>Wet Perimeter (m)</source>
         <translation>Périmètre mouillé (m)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="143"/>
+        <location filename="../View/Translate.py" line="140"/>
         <source>Hydraulic Radius (m)</source>
         <translation>Rayon hydraulique (m)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="146"/>
+        <location filename="../View/Translate.py" line="143"/>
         <source>Froude number</source>
         <translation>Nombre de Froude</translation>
     </message>
-    <message>
-        <location filename="../View/Translate.py" line="109"/>
-        <source>Discharge (m^3/s)</source>
-        <translation type="obsolete">Débit (m³/s)</translation>
-    </message>
     <message>
         <location filename="../View/InitialConditionsAdisTS/translate.py" line="49"/>
         <source>EG (m)</source>
@@ -3832,75 +3757,55 @@ moyen droit (m)</translation>
         <translation>Vitesse min (m/s)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="110"/>
-        <source>Discharge Envelop (m^3/s)</source>
-        <translation type="obsolete">Enveloppe du débit (m³/s)</translation>
-    </message>
-    <message>
-        <location filename="../View/Translate.py" line="113"/>
-        <source>Max Discharge (m^3/s)</source>
-        <translation type="obsolete">Débit max (m³/s)</translation>
-    </message>
-    <message>
-        <location filename="../View/Translate.py" line="116"/>
-        <source>Min Discharge (m^3/s)</source>
-        <translation type="obsolete">Débit min (m³/s)</translation>
-    </message>
-    <message>
-        <location filename="../View/Translate.py" line="127"/>
+        <location filename="../View/Translate.py" line="124"/>
         <source>Area</source>
         <translation>Aire</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="128"/>
+        <location filename="../View/Translate.py" line="125"/>
         <source>Rho</source>
         <translation>Rho</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="129"/>
+        <location filename="../View/Translate.py" line="126"/>
         <source>Porosity</source>
         <translation>Porosité</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="130"/>
+        <location filename="../View/Translate.py" line="127"/>
         <source>CDC_RIV</source>
         <translation>CDC_RIV</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="131"/>
+        <location filename="../View/Translate.py" line="128"/>
         <source>CDC_CAS</source>
         <translation>CDC_CAS</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="132"/>
+        <location filename="../View/Translate.py" line="129"/>
         <source>APD</source>
         <translation>APD</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="133"/>
+        <location filename="../View/Translate.py" line="130"/>
         <source>AC</source>
         <translation>AC</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="134"/>
+        <location filename="../View/Translate.py" line="131"/>
         <source>BC</source>
         <translation>BC</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="136"/>
+        <location filename="../View/Translate.py" line="133"/>
         <source>Concentration (g/l)</source>
         <translation>Concentration (g/l)</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="147"/>
+        <location filename="../View/Translate.py" line="144"/>
         <source>Mass (kg)</source>
         <translation>Masse</translation>
     </message>
-    <message>
-        <location filename="../View/Translate.py" line="148"/>
-        <source>Concentration (kg/m^3)</source>
-        <translation type="obsolete">Concentration (kg/m³)</translation>
-    </message>
     <message>
         <location filename="../View/DIFAdisTS/translate.py" line="47"/>
         <source>DIF</source>
@@ -3916,65 +3821,35 @@ moyen droit (m)</translation>
         <source>Coeff c</source>
         <translation>Coeff c</translation>
     </message>
-    <message>
-        <location filename="../View/Translate.py" line="139"/>
-        <source>Wet Area (m&#xb2;)</source>
-        <translation type="obsolete">Aire Mouillée (m²)</translation>
-    </message>
     <message>
         <location filename="../View/Translate.py" line="109"/>
-        <source>Discharge (m&#xb3;/s)</source>
-        <translation type="obsolete">Débit (m³/s)</translation>
+        <source>Discharge</source>
+        <translation>Débit</translation>
     </message>
     <message>
         <location filename="../View/Translate.py" line="110"/>
-        <source>Discharge Envelop (m&#xb3;/s)</source>
-        <translation type="obsolete">Enveloppe du débit (m³/s)</translation>
+        <source>Discharge Envelop</source>
+        <translation>Enveloppe du débit</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="113"/>
-        <source>Max Discharge (m&#xb3;/s)</source>
-        <translation type="obsolete">Débit max (m³/s)</translation>
+        <location filename="../View/Translate.py" line="112"/>
+        <source>Max Discharge</source>
+        <translation>Débit max</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="116"/>
-        <source>Min Discharge (m&#xb3;/s)</source>
-        <translation type="obsolete">Débit min (m³/s)</translation>
+        <location filename="../View/Translate.py" line="114"/>
+        <source>Min Discharge</source>
+        <translation>Débit min</translation>
     </message>
     <message>
-        <location filename="../View/Translate.py" line="148"/>
-        <source>Concentration (kg/m&#xb3;)</source>
-        <translation type="obsolete">Concentration (kg/m³)</translation>
-    </message>
-    <message encoding="UTF-8">
-        <location filename="../View/Translate.py" line="109"/>
-        <source>Discharge (m³/s)</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message encoding="UTF-8">
-        <location filename="../View/Translate.py" line="110"/>
-        <source>Discharge Envelop (m³/s)</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message encoding="UTF-8">
-        <location filename="../View/Translate.py" line="113"/>
-        <source>Max Discharge (m³/s)</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message encoding="UTF-8">
-        <location filename="../View/Translate.py" line="116"/>
-        <source>Min Discharge (m³/s)</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message encoding="UTF-8">
-        <location filename="../View/Translate.py" line="139"/>
-        <source>Wet Area (m²)</source>
-        <translation type="unfinished"></translation>
+        <location filename="../View/Translate.py" line="145"/>
+        <source>Concentration</source>
+        <translation>Concentration</translation>
     </message>
-    <message encoding="UTF-8">
-        <location filename="../View/Translate.py" line="148"/>
-        <source>Concentration (kg/m³)</source>
-        <translation type="unfinished"></translation>
+    <message>
+        <location filename="../View/Translate.py" line="136"/>
+        <source>Wet Area</source>
+        <translation>Aire mouillée</translation>
     </message>
 </context>
 </TS>
-- 
GitLab