From 2708e81ebb33342aa9886b4893e60049831234fd Mon Sep 17 00:00:00 2001
From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr>
Date: Fri, 14 Apr 2023 10:09:50 +0200
Subject: [PATCH] geometry: Continue to adapt to new model scheme.

---
 src/Model/Geometry/PointXYZ.py            |   7 +-
 src/Model/Geometry/ProfileXYZ.py          | 143 ++++++++++++++----
 src/Model/Geometry/Reach.py               |   4 +-
 src/Model/Geometry/projection_pointXYZ.py |  37 ++---
 src/View/Geometry/GeometryWindow.py       | 168 ++++++++++------------
 src/View/Geometry/qtableview_reach.py     |  33 ++---
 src/pamhyr.py                             |   2 +-
 7 files changed, 235 insertions(+), 159 deletions(-)

diff --git a/src/Model/Geometry/PointXYZ.py b/src/Model/Geometry/PointXYZ.py
index efbb97c8..6939cadf 100644
--- a/src/Model/Geometry/PointXYZ.py
+++ b/src/Model/Geometry/PointXYZ.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 
 from math import dist
-from pandas import isna as pd_is_na
+from pandas import isna
 
 from Model.Geometry.Point import Point
 
@@ -41,13 +41,14 @@ class PointXYZ(Point):
     def z(self, value):
         self._z = float(value)
 
-    @property
     def is_nan(self):
         """
         Returns:
             True if at least one coordinate is as np.nan
         """
-        return pd_is_na(self.x) or pd_is_na(self.y) or pd_is_na(self.z)
+        return (isna(self.x) or
+                isna(self.y) or
+                isna(self.z))
 
     @staticmethod
     def distance(p1, p2):
diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py
index 5da9a645..34f23333 100644
--- a/src/Model/Geometry/ProfileXYZ.py
+++ b/src/Model/Geometry/ProfileXYZ.py
@@ -48,6 +48,36 @@ class ProfileXYZ(Profile):
              self.nb_points(), self._kp, self._name]
         )
 
+    def x(self):
+        return [point.x for point in self._points]
+
+    def y(self):
+        return [point.y for point in self._points]
+
+    def z(self):
+        return [point.z for point in self._points]
+
+    def names(self):
+        return [point.name for point in self._points]
+
+    def x_max(self):
+        return max(self.filter_isnan(self.x))
+
+    def x_min(self):
+        return min(self.filter_isnan(self.x))
+
+    def y_max(self):
+        return max(self.filter_isnan(self.y))
+
+    def y_min(self):
+        return min(self.filter_isnan(self.y))
+
+    def z_max(self):
+        return max(self.filter_isnan(self.z))
+
+    def z_min(self):
+        return min(self.filter_isnan(self.z))
+
     def import_points(self, list_points: list):
         """Import a list of points to profile
 
@@ -148,32 +178,91 @@ class ProfileXYZ(Profile):
         """
         return [x for x in lst if not np.isnan(x)]
 
-    def x(self):
-        return [point.x for point in self._points]
-
-    def y(self):
-        return [point.y for point in self._points]
-
-    def z(self):
-        return [point.z for point in self._points]
-
-    def names(self):
-        return [point.name for point in self._points]
-
-    def x_max(self):
-        return max(self.filter_isnan(self.x))
-
-    def x_min(self):
-        return min(self.filter_isnan(self.x))
-
-    def y_max(self):
-        return max(self.filter_isnan(self.y))
-
-    def y_min(self):
-        return min(self.filter_isnan(self.y))
+    def get_station(self) -> np.ndarray:
+        """Projection of the points of the profile on a plane.
 
-    def z_max(self):
-        return max(self.filter_isnan(self.z))
+        Args:
+            profile: The profile
 
-    def z_min(self):
-        return min(self.filter_isnan(self.z))
+        Returns:
+            Projection of the points of the profile on a plane.
+        """
+        if self.nb_points >= 3:
+            first_named_point = None
+            index_first_named_point = None
+            last_named_point = None
+
+            for index, point in enumerate(self.points):
+                if point.point_is_named():
+                    index_first_named_point = index
+                    first_named_point = point
+                    break
+
+            for point in self._points[::-1]:
+                if point.point_is_named():
+                    last_named_point = point
+                    break
+
+            station = []
+            constant = 0.0
+
+            if ((first_named_point is not None) and
+                (last_named_point is not None)):
+                if (first_named_point != last_named_point and
+                    first_named_point.x != last_named_point.x):
+                    vector = Vector1d(first_named_point, last_named_point)
+                    normalized_direction_vec = vector.normalized_direction_vector()
+                else:
+                    vector = Vector1d(_first_point_not_nan(profile),
+                                      _last_point_not_nan(profile))
+                    normalized_direction_vec = vector.normalized_direction_vector()
+
+                for point in self._points:
+                    xi = point.x - first_named_point.x
+                    yi = point.y - first_named_point.y
+                    station_i = (normalized_direction_vec[0] * xi +
+                                 normalized_direction_vec[1] * yi)
+                    station.append(station_i)
+
+                    station = np.array(station)
+
+                    constant = station[index_first_named_point]
+            elif first_named_point is None:
+                vector = Vector1d(_first_point_not_nan(profile),
+                                  _last_point_not_nan(profile))
+                normalized_direction_vec = vector.normalized_direction_vector()
+
+                for point in self._points:
+                    xi = point.x - _first_point_not_nan(profile).x
+                    yi = point.y - _first_point_not_nan(profile).y
+                    station_i = (normalized_direction_vec[0] * xi +
+                                 normalized_direction_vec[1] * yi)
+                    station.append(station_i)
+
+                station = np.array(station)
+                index_profile_z_min = np.where(np.array(self.z) == self.z_min)[0][0]
+                constant = station[index_profile_z_min]
+
+            return (station - constant)
+        else:
+            return np.array(np.nan)
+
+    def _first_point_not_nan(self):
+        first_point = self._points[0]
+
+        for point in self.points:
+            if not point.is_nan():
+                first_point = point
+                break
+
+        return first_point_not_nan
+
+    def _last_point_not_nan(self):
+        last_point = self._points[-1]
+
+        for point in self._points[::-1]:
+            if not point.is_nan():
+                last_point = point
+                break
+
+        return last_point
diff --git a/src/Model/Geometry/Reach.py b/src/Model/Geometry/Reach.py
index 3b696314..d2c6b4f0 100644
--- a/src/Model/Geometry/Reach.py
+++ b/src/Model/Geometry/Reach.py
@@ -123,10 +123,10 @@ class Reach:
             else:
                 raise TypeError(f"{list_index} is instance of unexpected type '{type(list_index)}'")
 
-    def _sort(self, is_reversed: bool = False):
+    def sort(self, is_reversed: bool = False):
         self._profiles = sorted(
             self._profiles,
-            key=lambda profile: profile.kp(),
+            key=lambda profile: profile.kp,
             reverse=is_reversed
         )
 
diff --git a/src/Model/Geometry/projection_pointXYZ.py b/src/Model/Geometry/projection_pointXYZ.py
index 439d4f4c..579ae63c 100644
--- a/src/Model/Geometry/projection_pointXYZ.py
+++ b/src/Model/Geometry/projection_pointXYZ.py
@@ -44,54 +44,55 @@ def get_station(profile: ProfileXYZ) -> np.ndarray:
                 last_named_point = point
                 break
 
-        station = []  # abscisse en travers
-        constant = 0.0  # constante pour décaler l'origine de l'ascisse en travers caluculée.
+        station = []
+        constant = 0.0
 
-        if (first_named_point is not None) and (last_named_point is not None):
-            if first_named_point != last_named_point and first_named_point.x != last_named_point.x:
+        if ((first_named_point is not None) and
+            (last_named_point is not None)):
+            if (first_named_point != last_named_point and
+                first_named_point.x != last_named_point.x):
                 vector = Vector1d(first_named_point, last_named_point)
                 normalized_direction_vec = vector.normalized_direction_vector()
             else:
-                vector = Vector1d(_first_point_not_nan(profile), _last_point_not_nan(profile))
+                vector = Vector1d(_first_point_not_nan(profile),
+                                  _last_point_not_nan(profile))
                 normalized_direction_vec = vector.normalized_direction_vector()
 
             for point in profile.points:
                 xi = point.x - first_named_point.x
                 yi = point.y - first_named_point.y
-                station_i = normalized_direction_vec[0] * xi + normalized_direction_vec[1] * yi
+                station_i = (normalized_direction_vec[0] * xi +
+                             normalized_direction_vec[1] * yi)
                 station.append(station_i)
 
             station = np.array(station)
 
-            constant = station[index_first_named_point]  # pour placer l'origine au premier point nomme.
+            constant = station[index_first_named_point]
         elif first_named_point is None:
-            vector = Vector1d(_first_point_not_nan(profile), _last_point_not_nan(profile))
+            vector = Vector1d(_first_point_not_nan(profile),
+                              _last_point_not_nan(profile))
             normalized_direction_vec = vector.normalized_direction_vector()
 
             for point in profile.points:
                 xi = point.x - _first_point_not_nan(profile).x
                 yi = point.y - _first_point_not_nan(profile).y
-                station_i = normalized_direction_vec[0] * xi + normalized_direction_vec[1] * yi
+                station_i = (normalized_direction_vec[0] * xi +
+                             normalized_direction_vec[1] * yi)
                 station.append(station_i)
 
             station = np.array(station)
             index_profile_z_min = np.where(np.array(profile.z) == profile.z_min)[0][0]
-            constant = station[index_profile_z_min]  # pour placer l'origine au fond ie à la cote minimale
-            # z_min du profil.
-        station = station - constant
+            constant = station[index_profile_z_min]
 
-        return station
+        return (station - constant)
     else:
         return np.array(np.nan)
 
-def _point_is_nan(point: PointXYZ):
-    return pd.isna(point.x) or pd.isna(point.y) or pd.isna(point.z)
-
 def _first_point_not_nan(profile: ProfileXYZ):
     first_point_not_nan = profile.points[0]
 
     for point in profile.points:
-        if not _point_is_nan(point):
+        if not point.is_nan():
             first_point_not_nan = point
             break
 
@@ -101,7 +102,7 @@ def _last_point_not_nan(profile: ProfileXYZ):
     last_point = profile.points[-1]
 
     for point in profile.points[::-1]:
-        if not _point_is_nan(point):
+        if not point.is_nan():
             last_point = point
             break
 
diff --git a/src/View/Geometry/GeometryWindow.py b/src/View/Geometry/GeometryWindow.py
index ad225f07..03a7c566 100644
--- a/src/View/Geometry/GeometryWindow.py
+++ b/src/View/Geometry/GeometryWindow.py
@@ -89,15 +89,9 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         )
 
         current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY
-        #settings.setValue('current_directory', current_dir)
         if filename != "":
             size = os.stat(filename).st_size
             self._reach.import_geometry(filename)
-            # self.model = qtableview_reach.PandasModelEditable(
-            #     ,
-            #     self.tableView_header
-            # )
-            # self.tableView.setModel(self.model)
             self.model.layoutChanged.emit()
 
             self.update_profile_windows()
@@ -149,7 +143,7 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         for selected_row in list_selected_row[:5]:
             selected_row = int(selected_row)
             profile_identifier = self._reach.get_profile_selected_identifier(selected_row)
-            Kp = self._reach.get_kp_i(selected_row)
+            Kp = self._reach.profile(selected_row).kp
             profile_name = self._reach.get_profile_name(selected_row)
 
             if len(self.list_second_window) == 0:
@@ -220,9 +214,6 @@ class GeometryWindow(QMainWindow, WindowToolKit):
             self.update_graphic_1()
             print("update_graphic_1_profile")
 
-    def print_data(self):
-        print(self.model_data.profile)
-
     def update_profile_windows(self):
         self.list_second_window = []
         self.list_row = []
@@ -290,33 +281,33 @@ class GeometryWindow(QMainWindow, WindowToolKit):
             _translate("MainWindow_reach", "Cote (m)"), color='green', fontsize=12
         )
 
-        self.get_kp = self._reach.get_kp()
-        self.get_z_min = self._reach.get_z_min()
-        self.get_z_max = self._reach.get_z_max()
+        kp = self._reach.get_kp()
+        z_min = self._reach.get_z_min()
+        z_max = self._reach.get_z_max()
 
         self.line_kp_zmin_zmax = self.ui.canvas_2.axes.vlines(
-            x=self.get_kp,
-            ymin=self.get_z_min, ymax=self.get_z_max,
+            x=kp,
+            ymin=z_min, ymax=z_max,
             color='r', lw=1.
         )
 
         self.plot_selected_2, = self.ui.canvas_2.axes.plot(
-            (self.get_kp[0], self.get_kp[0]),
-            (self.get_z_min[0], self.get_z_max[0]),
+            (kp[0], kp[0]),
+            (z_min[0], z_max[0]),
             color='b', lw=1.8
         )
         self.plot_selected_2.set_visible(False)
 
         self.before_plot_selected_2, = self.ui.canvas_2.axes.plot(
-            (self.get_kp[0], self.get_kp[0]),
-            (self.get_z_min[0], self.get_z_max[0]),
+            (kp[0], kp[0]),
+            (z_min[0], z_max[0]),
             color='k', lw=1.6, linestyle='--'
         )
         self.before_plot_selected_2.set_visible(False)
 
         self.after_plot_selected_2, = self.ui.canvas_2.axes.plot(
-            (self.get_kp[0], self.get_kp[0]),
-            (self.get_z_min[0], self.get_z_max[0]),
+            (kp[0], kp[0]),
+            (z_min[0], z_max[0]),
             color='m', lw=1.6, linestyle='--'
         )
         self.after_plot_selected_2.set_visible(False)
@@ -331,7 +322,7 @@ class GeometryWindow(QMainWindow, WindowToolKit):
             print("TODO")
 
         self.line_kp_zmin, = self.ui.canvas_2.axes.plot(
-            self.get_kp, self.get_z_min,
+            kp, z_min,
             linestyle=":", lw=1.8,
             color='lightgrey'
         )
@@ -347,8 +338,8 @@ class GeometryWindow(QMainWindow, WindowToolKit):
 
         for ind in range(self.model.rowCount()):
             self.line_xy[ind][0].set_data(
-                self._reach.get_x_profile_i(ind),
-                self._reach.get_y_profile_i(ind)
+                self._reach.profile(ind).x,
+                self._reach.profile(ind).y
             )
 
         for i in range(len(self.line_ld_1)):
@@ -363,23 +354,23 @@ class GeometryWindow(QMainWindow, WindowToolKit):
     def update_graphic_2(self):
         self.tableView.model().blockSignals(True)
 
-        get_kp = self._reach.get_kp()
-        get_z_min = self._reach.get_z_min()
-        get_z_max = self._reach.get_z_max()
+        kp = self._reach.get_kp()
+        z_min = self._reach.get_z_min()
+        z_max = self._reach.get_z_max()
 
-        self.line_kp_zmin.set_data(get_kp, get_z_min)
+        self.line_kp_zmin.set_data(kp, z_min)
 
         self.line_kp_zmin_zmax.remove()
         self.line_kp_zmin_zmax = self.ui.canvas_2.axes.vlines(
-            x=get_kp,
-            ymin=get_z_min, ymax=get_z_max,
+            x=kp,
+            ymin=z_min, ymax=z_max,
             color='r', lw=1.
         )
 
         try:
             for i in range(len(self.line_kp_zld)):
                 self.line_kp_zld[i][0].set_data(
-                    get_kp, self.model.z_complete_guideline()[i]
+                    kp, self.model.z_complete_guideline()[i]
                 )
         except:
             print("TODO")
@@ -394,9 +385,9 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         selected_profile = 0
         station = self._reach.get_station(selected_profile)  # L'abscisse en travers
         station_plus_1 = self._reach.get_station(selected_profile + 1)
-        elevation = self._reach.get_z_profile_i(selected_profile)
-        elevation_i_plus_1 = self._reach.get_z_profile_i(selected_profile + 1)
-        ld = self._reach.get_ld_profile_i(selected_profile)
+        elevation = self._reach.profile(selected_profile).z
+        elevation_i_plus_1 = self._reach.profile(selected_profile + 1).z
+        ld = self._reach.profile(selected_profile).name
 
         self.ui.canvas_3.axes.cla()
         self.ui.canvas_3.axes.grid(color='grey', linestyle='--', linewidth=0.5)
@@ -500,7 +491,7 @@ class GeometryWindow(QMainWindow, WindowToolKit):
 
         x = self.get_station(ind)
         y = self.get_elevation(ind)
-        ld = self._reach.get_ld_profile_i(ind)
+        ld = self._reach.profile(ind).name
         get_complete_list_ld = self._reach.get_complete_list_ld()
         get_incomplete_list_ld = self._reach.get_incomplete_list_ld()
 
@@ -558,51 +549,47 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         return self._reach.get_station(ind)
 
     def get_elevation(self, ind: int):
-        return self._reach.get_z_profile_i(ind)
+        return self._reach.profile(ind).z
 
     def update_graphic_3(self, ind: int):
         self.tableView.model().blockSignals(True)
 
-        selected_profile = ind
-        print(selected_profile)
-
-        if selected_profile == 0:
+        if ind == 0:
             self.profile_i_minus_1.set_data([], [])
             self.profile_i.set_data(
-                self.get_station(selected_profile),
-                self.get_elevation(selected_profile)
+                self.get_station(ind),
+                self.get_elevation(ind)
             )
             self.profile_i_plus_1.set_data(
-                self.get_station(selected_profile + 1),
-                self.get_elevation(selected_profile + 1)
+                self.get_station(ind + 1),
+                self.get_elevation(ind + 1)
             )
-        elif selected_profile == self.model.rowCount() - 1:
+        elif ind == self.model.rowCount() - 1:
             self.profile_i_minus_1.set_data(
-                self.get_station(selected_profile - 1),
-                self.get_elevation(selected_profile - 1)
+                self.get_station(ind - 1),
+                self.get_elevation(ind - 1)
             )
             self.profile_i.set_data(
-                self.get_station(selected_profile),
-                self.get_elevation(selected_profile)
+                self.get_station(ind),
+                self.get_elevation(ind)
             )
             self.profile_i_plus_1.set_data([], [])
-        elif 0 < selected_profile < self.model.rowCount() - 1:
+        elif 0 < ind < self.model.rowCount() - 1:
             self.profile_i_minus_1.set_data(
-                self.get_station(selected_profile - 1),
-                self.get_elevation(selected_profile - 1)
+                self.get_station(ind - 1),
+                self.get_elevation(ind - 1)
             )
             self.profile_i.set_data(
-                self.get_station(selected_profile),
-                self.get_elevation(selected_profile)
+                self.get_station(ind),
+                self.get_elevation(ind)
             )
             self.profile_i_plus_1.set_data(
-                self.get_station(selected_profile + 1),
-                self.get_elevation(selected_profile + 1)
+                self.get_station(ind + 1),
+                self.get_elevation(ind + 1)
             )
 
         self.tableView.model().blockSignals(False)
-
-        self.update_annotate_3(selected_profile)
+        self.update_annotate_3(ind)
 
         self.ui.canvas_3.axes.relim()
         self.ui.canvas_3.axes.autoscale_view()
@@ -612,28 +599,27 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         self.tableView.model().blockSignals(True)
 
         if 0 <= ind < self.model.rowCount():
-            self.plot_selected_1.set_data(self._reach.get_x_profile_i(ind),
-                                          self._reach.get_y_profile_i(ind))
+            self.plot_selected_1.set_data(self._reach.profile(ind).x,
+                                          self._reach.profile(ind).y)
             self.plot_selected_1.set_visible(True)
+
         self.tableView.model().blockSignals(False)
 
     def select_plot_graphic_2(self, ind: int):
-        get_kp_i = self.get_kp_i(ind)
-        get_z_min_i = self.get_z_min_i(ind)
-        get_z_max_i = self.get_z_max_i(ind)
+        kp_i = self._reach.profile(ind).kp
+        z_min_i = self._reach.profile(ind).z_min
+        z_max_i = self._reach.profile(ind).z_max
 
         if 0 <= ind < self.model.rowCount():
-            self.plot_selected_2.set_data((get_kp_i, get_kp_i),
-                                          (get_z_min_i, get_z_max_i))
+            self.plot_selected_2.set_data((kp_i, kp_i),
+                                          (z_min_i, z_max_i))
             self.plot_selected_2.set_visible(True)
 
     def select_before_plot_selected_1(self, ind: int):
         if 0 <= ind < self.model.rowCount():
-            t0 = time.time()
-
             self.before_plot_selected_1.set_data(
-                self._reach.get_x_profile_i(ind),
-                self._reach.get_y_profile_i(ind)
+                self._reach.profile(ind).x,
+                self._reach.profile(ind).y
             )
 
             self.before_plot_selected_1.set_visible(True)
@@ -642,22 +628,21 @@ class GeometryWindow(QMainWindow, WindowToolKit):
     def select_after_plot_selected_1(self, ind: int):
         if 0 <= ind < self.model.rowCount():
             self.after_plot_selected_1.set_data(
-                self._reach.get_x_profile_i(ind),
-                self._reach.get_y_profile_i(ind)
+                self._reach.profile(ind).x,
+                self._reach.profile(ind).y
             )
             self.after_plot_selected_1.set_visible(True)
             self.ui.canvas_1.figure.canvas.draw_idle()
 
     def select_before_plot_selected_2(self, ind: int):
         if 0 <= ind < self.model.rowCount():
-            t0 = time.time()
-            get_kp_i = self.get_kp_i(ind)
-            get_z_min_i = self.get_z_min_i(ind)
-            get_z_max_i = self.get_z_max_i(ind)
+            kp_i = self._reach.profile(ind).kp
+            z_min_i = self._reach.profile(ind).z_min
+            z_max_i = self._reach.profile(ind).z_max
 
             self.before_plot_selected_2.set_data(
-                (get_kp_i, get_kp_i),
-                (get_z_min_i, get_z_max_i)
+                (kp_i, kp_i),
+                (z_min_i, z_max_i)
             )
 
             self.before_plot_selected_2.set_visible(True)
@@ -665,14 +650,13 @@ class GeometryWindow(QMainWindow, WindowToolKit):
 
     def select_after_plot_selected_2(self, ind: int):
         if 0 <= ind < self.model.rowCount():
-            t0 = time.time()
-            get_kp_i = self.get_kp_i(ind)
-            get_z_min_i = self.get_z_min_i(ind)
-            get_z_max_i = self.get_z_max_i(ind)
+            kp_i = self._reach.profile(ind).kp
+            z_min_i = self._reach.profile(ind).z_min
+            z_max_i = self._reach.profile(ind).z_max
 
             self.after_plot_selected_2.set_data(
-                (get_kp_i, get_kp_i),
-                (get_z_min_i, get_z_max_i)
+                (kp_i, kp_i),
+                (z_min_i, z_max_i)
             )
 
             self.after_plot_selected_2.set_visible(True)
@@ -726,11 +710,11 @@ class GeometryWindow(QMainWindow, WindowToolKit):
     def changed_slider_value(self):
         self.tableView.model().blockSignals(True)
 
-        if self.filename is not None:
+        if self.model.rowCount() != 0:
             self.ui.verticalSlider.setMaximum(self.model.rowCount() - 1)
 
             slider_value = self.ui.verticalSlider.value()
-            kp = self._reach.get_kp_profile_i(slider_value)
+            kp = self._reach.profile(slider_value).kp
 
             self.ui.vertical_slider_label.setText(
                 _translate("MainWindow_reach", "Kp : ") +
@@ -784,7 +768,7 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         return [index.row() for index in self.tableView.selectedIndexes()][0]
 
     def sort_ascending(self):
-        self.model.sort_data(True)
+        self.model.sort_profiles(True)
         self.select_current_profile()
         self.changed_slider_value()
 
@@ -792,7 +776,7 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         self.update_graphic_3(self.index_selected_row)
 
     def sort_descending(self):
-        self.model.sort_data(False)
+        self.model.sort_profiles(False)
 
         self.select_current_profile()
         self.changed_slider_value()
@@ -859,7 +843,7 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         current_dir = settings.value('current_directory', DEFAULT_DIRECTORY, type=str)
         options |= QFileDialog.DontUseNativeDialog
 
-        filename, self.filters = QFileDialog.getSaveFileName(
+        filename, filters = QFileDialog.getSaveFileName(
             self,
             filter=_translate("MainWindow_reach",
                               "Fichiers .ST(*.ST ou *.st)")
@@ -875,10 +859,10 @@ class GeometryWindow(QMainWindow, WindowToolKit):
             self.model.export_reach(filename)
 
     def handleOpen(self):
-        self.filename, self.filterName = QFileDialog.getOpenFileName(self)
+        filename, filterName = QFileDialog.getOpenFileName(self)
 
-        if self.filename != '':
-            with open(self.filename, 'r') as f:
+        if filename != '':
+            with open(filename, 'r') as f:
                 reader = csv.reader(f, delimiter='\t')
                 header = next(reader)
                 buf = []
@@ -889,7 +873,7 @@ class GeometryWindow(QMainWindow, WindowToolKit):
                 self.model = None
                 self.model = qtableview_reach.PandasModelEditable(buf)
                 self.tableView.setModel(self.model)
-                self.filename = ''
+                filename = ''
 
     def get_lignes_directrices(self):
         liste_lignes_directrices = [
diff --git a/src/View/Geometry/qtableview_reach.py b/src/View/Geometry/qtableview_reach.py
index e22e0393..855dfea0 100644
--- a/src/View/Geometry/qtableview_reach.py
+++ b/src/View/Geometry/qtableview_reach.py
@@ -12,7 +12,8 @@ from PyQt5 import (
     QtGui, QtWidgets
 )
 from PyQt5.QtCore import (
-    Qt, QAbstractTableModel, QModelIndex, QVariant, pyqtSlot, QCoreApplication
+    Qt, QAbstractTableModel, QModelIndex,
+    QVariant, pyqtSlot, QCoreApplication
 )
 from PyQt5.QtWidgets import (
     QMessageBox
@@ -27,7 +28,7 @@ class PandasModelEditable(QAbstractTableModel):
         QAbstractTableModel.__init__(self)
         data_list = []
 
-        self._data = reach
+        self._reach = reach
 
         if headers is None:
             self.headers = [
@@ -39,7 +40,7 @@ class PandasModelEditable(QAbstractTableModel):
             self.headers = headers
 
     def rowCount(self, parent=QModelIndex()):
-        return self._data.number_profiles
+        return self._reach.number_profiles
 
     def columnCount(self, parent=QModelIndex()):
         return len(self.headers)
@@ -47,21 +48,21 @@ class PandasModelEditable(QAbstractTableModel):
     def data(self, index, role=Qt.DisplayRole):
         if index.isValid():
             if role == Qt.DisplayRole and index.column() == 0:
-                return self._data.profile(index.row()).name
+                return self._reach.profile(index.row()).name
 
             if role == Qt.DisplayRole and index.column() == 1:
-                kp = self._data.profile(index.row()).kp
+                kp = self._reach.profile(index.row()).kp
                 return f"{kp:.4f}"
 
             if role == Qt.DisplayRole and index.column() == 2:
-                return self._data.profile(index.row()).profile_type
+                return self._reach.profile(index.row()).profile_type
 
             for column in range(0, self.columnCount()):
                 if index.column() == column and role == Qt.TextAlignmentRole:
                     return Qt.AlignHCenter | Qt.AlignVCenter
 
             if role == Qt.ForegroundRole and index.column() == 0:
-                name = self._data.profile(index.row()).name\
+                name = self._reach.profile(index.row()).name\
                                                       .strip()\
                                                       .lower()
                 if (name == "upstream" or name == "up" or
@@ -89,10 +90,10 @@ class PandasModelEditable(QAbstractTableModel):
 
         if role == Qt.EditRole and index.column() != 2:
             if role == Qt.EditRole and index.column() == 0:
-                self._data.profile(index.row()).name = value
+                self._reach.profile(index.row()).name = value
 
             if role == Qt.EditRole and index.column() == 1:
-                self._data.profile(index.row()).pk = float(value)
+                self._reach.profile(index.row()).pk = float(value)
 
             self.dataChanged.emit(index, index)
             self.layoutChanged.emit()
@@ -122,7 +123,7 @@ class PandasModelEditable(QAbstractTableModel):
     def insertRows(self, row, count, parent=QModelIndex()):
         self.beginInsertRows(parent, row, row + count - 1)
 
-        self._data.add_profile(row)
+        self._reach.add_profile(row)
 
         self.endInsertRows()
         self.layoutChanged.emit()
@@ -132,17 +133,17 @@ class PandasModelEditable(QAbstractTableModel):
 
         if len(list_row_selected) >= 1:
             if len(list_row_selected) == 1:
-                self._data.delete_profile(list_row_selected[0])
+                self._reach.delete_profile(list_row_selected[0])
             elif len(list_row_selected) > 1:
-                self._data.delete_profile_rows(list_row_selected)
+                self._reach.delete_profile_rows(list_row_selected)
 
         self.endRemoveRows()
         self.layoutChanged.emit()
 
-    def sort_data(self, _reverse):
+    def sort_profiles(self, _reverse):
         self.layoutAboutToBeChanged.emit()
 
-        self._data.sort(_reverse)
+        self._reach.sort(_reverse)
 
         self.layoutAboutToBeChanged.emit()
         self.layoutChanged.emit()
@@ -151,7 +152,7 @@ class PandasModelEditable(QAbstractTableModel):
         target = row_to_move + 2
         self.beginMoveRows(parent, row_to_move, row_to_move, parent, target)
 
-        self._data.move_down_profile(row_to_move)
+        self._reach.move_down_profile(row_to_move)
 
         self.endMoveRows()
         self.layoutChanged.emit()
@@ -160,7 +161,7 @@ class PandasModelEditable(QAbstractTableModel):
         target = row_to_move + 1
         self.beginMoveRows(parent, row_to_move - 1, row_to_move - 1, parent, target)
 
-        self._data.move_up_profile(row_to_move)
+        self._reach.move_up_profile(row_to_move)
 
         self.endMoveRows()
         self.layoutChanged.emit()
diff --git a/src/pamhyr.py b/src/pamhyr.py
index b56d0af9..de12d2e1 100755
--- a/src/pamhyr.py
+++ b/src/pamhyr.py
@@ -39,7 +39,7 @@ def main():
 
     application = ApplicationWindow(conf=conf)
     application.show()
-    sys.exit(app.exec_())
+    sys.exit(int(app.exec_()))
 
 if __name__ == "__main__":
     main()
-- 
GitLab