diff --git a/src/Model/Geometry/PointXY.py b/src/Model/Geometry/PointXY.py
index 2cd6907fe223d884644ccbb8fc3d730e111d43f3..65d7baf98c53f55cdc06cab342d74073e5ef5598 100644
--- a/src/Model/Geometry/PointXY.py
+++ b/src/Model/Geometry/PointXY.py
@@ -42,4 +42,4 @@ class PointAC(Point):
         Returns:
             Euclidean distance between the two points
         """
-        return dist((p1.a(), p1.c()), (p2.a(), p2.c()))
+        return dist((p1.a, p1.c), (p2.a, p2.c))
diff --git a/src/Model/Geometry/PointXYZ.py b/src/Model/Geometry/PointXYZ.py
index 4441a1d2b5b745c18d90a91d333963d2dc140903..efbb97c892ced09ac9cd565b74a9e1c1bdc1cee9 100644
--- a/src/Model/Geometry/PointXYZ.py
+++ b/src/Model/Geometry/PointXYZ.py
@@ -47,7 +47,7 @@ class PointXYZ(Point):
         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 pd_is_na(self.x) or pd_is_na(self.y) or pd_is_na(self.z)
 
     @staticmethod
     def distance(p1, p2):
@@ -60,4 +60,4 @@ class PointXYZ(Point):
         Returns:
             Euclidean distance between the two points
         """
-        return dist((p1.x(), p1.y(), p1.z()), (p2.x(), p2.y(), p2.z()))
+        return dist((p1.x, p1.y, p1.z), (p2.x, p2.y, p2.z))
diff --git a/src/Model/Geometry/Profile.py b/src/Model/Geometry/Profile.py
index 8243fa489b72f265ebd0da0956adda79c8d1a297..ebc28446e3eb842be371065ef72dedb6f877eb2c 100644
--- a/src/Model/Geometry/Profile.py
+++ b/src/Model/Geometry/Profile.py
@@ -1,13 +1,21 @@
 # -*- coding: utf-8 -*-
 
 class Profile(object):
-    def __init__(self, kp:float = 0.0, name:str = ""):
+    def __init__(self, kp:float = 0.0, name:str = "",
+                 code1: int = 0, code2: int = 0,
+                 _type:str = ""):
         super(Profile, self).__init__()
 
         self._num = int(num)
+        self._code1 = int(code1)
+        self._code2 = int(code2)
         self._kp = float(kp)
         self._name = str(name)
 
+        self._points: List[Point] = []
+
+        self._profile_type = _type
+
     @property
     def num(self):
         """
@@ -20,6 +28,34 @@ class Profile(object):
     def num(self, value: int):
         self._num = int(value)
 
+    @property
+    def code1(self):
+        """
+        Returns:
+            Interpolation code 1.
+        """
+        return self._code1
+
+    @code1.setter
+    def code1(self, value: int):
+        self._code1 = int(value)
+
+    @property
+    def code2(self):
+        """
+        Returns:
+            Interpolation code 2.
+        """
+        return self._code2
+
+    @code2.setter
+    def code2(self, value: int):
+        self._code2 = int(value)
+
+    @property
+    def nb_points(self):
+        return len(self._points)
+
     @property
     def kp(self):
         """
@@ -41,5 +77,17 @@ class Profile(object):
         return self._name
 
     @name.setter
-    def name(self, other: str):
-        self._name = other
+    def name(self, value: str):
+        self._name = value.strip()
+
+    @property
+    def profile_type(self):
+        """
+        Returns:
+            Profile type.
+        """
+        return self._profile_type
+
+    @type.setter
+    def profile_type(self, value: str):
+        self._profile_type = value
diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py
index 237ef6e3f339239847ba656902d470c4deaddfb2..d9d102ed694bf88f73d2008de95ac9e2a70a0dc5 100644
--- a/src/Model/Geometry/ProfileXYZ.py
+++ b/src/Model/Geometry/ProfileXYZ.py
@@ -8,7 +8,8 @@ from Model.Geometry.Profile import Profile
 from Model.Geometry.PointXYZ import PointXYZ
 
 class ProfileXYZ(Profile):
-    def __init__(self, num: int = 0, code1: int = 0, code2: int = 0,
+    def __init__(self, num: int = 0,
+                 code1: int = 0, code2: int = 0,
                  kp: float = 0., name: str = ""):
         """ProfileXYZ constructor
 
@@ -16,7 +17,6 @@ class ProfileXYZ(Profile):
             num: The number of this profile
             code1: The interpolation code 1
             code2: The interpolation code 2
-            nb_points: Number of points
             kp: Kilometer point
             name: The name of profile
 
@@ -27,46 +27,14 @@ class ProfileXYZ(Profile):
             num = num,
             name = name,
             kp = kp,
+            code1 = code1, code2 = code2,
+            _type = "XYZ",
         )
 
-        self._code1 = int(code1)
-        self._code2 = int(code2)
-        self._nb_points = int(nb_points)
-        self._list_points: List[PointXYZ] = []
-
     def __repr__(self):
         df = pd.DataFrame(columns=["X", "Y", "Z", "Name"],
                           data=[[p.x, p.y, p.z, p.name] for p in self._list_points])
-        return f"\n{self.header}\n{df}"
-
-
-    @property
-    def code1(self):
-        """
-        Returns:
-            Interpolation code 1.
-        """
-        return self._code1
-
-    @code1.setter
-    def code1(self, value: int):
-        self._code1 = int(value)
-
-    @property
-    def code2(self):
-        """
-        Returns:
-            Interpolation code 2.
-        """
-        return self._code2
-
-    @code2.setter
-    def code2(self, value: int):
-        self._code2 = int(value)
-
-    @property
-    def nb_points(self):
-        return self._nb_points
+        return f"\nProfileXYZ : {self.name}\n{df}"
 
     @property
     def header(self):
@@ -76,7 +44,7 @@ class ProfileXYZ(Profile):
         """
         return np.array(
             [self._num, self._code1, self._code2,
-             self._nb_points, self._kp, self._name]
+             self.nb_points(), self._kp, self._name]
         )
 
     def import_points(self, list_points: list):
@@ -167,3 +135,44 @@ class ProfileXYZ(Profile):
                 raise TypeError(
                     f"{list_index} is instance of unexpected type '{type(list_index)}'"
                 )
+
+    def filter_isnan(self, lst):
+        """Returns the input list without 'nan' element
+
+        Args:
+            lst: The list to filter
+
+        Returns:
+            The list without 'nan'
+        """
+        return [x for x in lst if not np.isnan(x)]
+
+    def x(self):
+        return [point.x for point in self._list_points]
+
+    def y(self):
+        return [point.y for point in self._list_points]
+
+    def z(self):
+        return [point.z for point in self._list_points]
+
+    def names(self):
+        return [point.name for point in self._list_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))
diff --git a/src/Model/Geometry/Reach.py b/src/Model/Geometry/Reach.py
index 46decef0188014a79d2571663dbf0a26e1cb3d1d..7f4461184399cbdff1126d9ff8abf69c0ee3fac3 100644
--- a/src/Model/Geometry/Reach.py
+++ b/src/Model/Geometry/Reach.py
@@ -15,26 +15,47 @@ from Model.Except import FileFormatError, exception_message_box
 class Reach:
     def __init__(self, edge):
         self._edge = edge
-        self._list_profiles: List[Profile] = []
+        self._profiles: List[Profile] = []
+
+        # Copy/Paste
+        self.__list_copied_profiles = []
 
     def __repr__(self):
-        return f"\n===== Début liste des profils ======> {np.array(self._list_profiles)}" \
+        return f"\n===== Début liste des profils ======> {np.array(self._profiles)}" \
                f"\n<====== Fin liste des profils ====="
 
+    def profile(self, i):
+        """Returns profile at index i
+
+        Args:
+            i: The index of profile
+
+        Returns:
+            The profile at index i
+        """
+        if i in self._profiles:
+            return self._profiles[i]
+
+        return None
+
+    @property
+    def profiles(self):
+        return self._profiles.copy()
+
     @property
     def number_profiles(self):
         """
         Returns:
             Number of profiles
         """
-        return len(self._list_profiles)
+        return len(self._profiles)
 
     def get_geometry(self) -> List[Profile]:
         """
         Returns:
             The profiles list.
         """
-        return self._list_profiles
+        return self._profiles
 
     def get_profile_i(self, i: int) -> Profile:
         """
@@ -45,11 +66,11 @@ class Reach:
             The profile at index i.
         """
         try:
-            return self._list_profiles[i]
+            return self._profiles[i]
         except IndexError:
             raise IndexError(f"Invalid profile index: {i}")
 
-    def add_XYZ(self):
+    def add_profile(self, index):
         """Add a new profile at the end of profiles list
 
         Returns:
@@ -58,7 +79,8 @@ class Reach:
         nb_profile = self.number_profiles
         profile = ProfileXYZ()
         profile.num = nb_profile + 1
-        self._list_profiles.append(profile)
+        self._profiles.insert(profile, index + 1)
+        # self._update_profile_numbers()
 
     def _update_profile_numbers(self):
         """Update profiles index
@@ -79,7 +101,7 @@ class Reach:
             Nothing.
         """
         profile = ProfileXYZ()
-        self._list_profiles.insert(index, profile)
+        self._profiles.insert(index, profile)
         self._update_profile_numbers()
 
     def delete(self, list_index: list):
@@ -95,26 +117,50 @@ class Reach:
             if list_index:
                 indices = sorted(list(set(list_index)), reverse=True)
                 for idx in indices:
-                    # if idx < len(self._list_profiles) :
+                    # if idx < len(self._profiles) :
                     try:
-                        self._list_profiles.pop(idx)
+                        self._profiles.pop(idx)
                         self._update_profile_numbers()
                     except IndexError:
                         print(f"Invalid profile index: {idx}")
         except TypeError:
             if isinstance(list_index, int):
-                self._list_profiles.pop(list_index)
+                self._profiles.pop(list_index)
                 self._update_profile_numbers()
             else:
                 raise TypeError(f"{list_index} is instance of unexpected type '{type(list_index)}'")
 
     def _sort(self, is_reversed: bool = False):
-        self._list_profiles = sorted(
-            self._list_profiles,
+        self._profiles = sorted(
+            self._profiles,
             key=lambda profile: profile.kp(),
             reverse=is_reversed
         )
 
+    def z_min(self):
+        """List of z min for each profile
+
+        Returns:
+            List of z min for each profile
+        """
+        return [profile.z_min() for profile in self._data.profiles]
+
+    def z_max(self):
+        """List of z max for each profile
+
+        Returns:
+            List of z max for each profile
+        """
+        return [profile.z_max() for profile in self._data.profiles]
+
+    def kp(self):
+        """List of profiles kp
+
+        Returns:
+            List of profiles kp
+        """
+        return [profile.kp for profile in self._data.profiles]
+
     def sort_ascending(self):
         """Sort profiles by increasing KP
 
@@ -144,7 +190,7 @@ class Reach:
     def paste(self):
         if self.__list_copied_profiles:
             for profile in self.__list_copied_profiles:
-                self._list_profiles.append(profile)
+                self._profiles.append(profile)
 
     def import_geometry(self, file_path_name: str):
         """Import a geometry from file (.ST or .st)
@@ -162,7 +208,7 @@ class Reach:
                 for ind, profile in enumerate(list_profile):
                     prof = ProfileXYZ(*list_header[ind])
                     prof.import_points(profile)
-                    self._list_profiles.append(prof)
+                    self._profiles.append(prof)
                     self._update_profile_numbers()
         except FileNotFoundError as e:
             print(e)
@@ -225,3 +271,22 @@ class Reach:
 
         print("******  Fichier {} lu et traité en {} secondes *******".format(self.file_st, time() - t0))
         return list_profile, list_header
+
+
+    # TODO: Move this function to model reach
+    def export_reach(self, filename):
+        with open(f"{filename}", "w") as file_st:
+            for index in range(len(self._profiles)):
+                profile = self._profiles[index]
+
+                for v in profile.header:
+                    file_st.write(f"{v:>6}")
+                file_st.write("\n")
+
+                for point in self._data.profile[index_pro].points:
+                    for i in [point.x, point.y, point.z, point.name]:
+                        file_st.write(f"{i:>13.4f}")
+                        file_st.write("\n")
+
+                file_st.write("    999.9990     999.9990     999.9990")
+                file_st.write("\n")
diff --git a/src/Model/River.py b/src/Model/River.py
index 5d6e9647c9e1c6bb0ba7aad93528035a03de7a92..027fd37ef173a4e82ef1ce9a4164e2496aaf685d 100644
--- a/src/Model/River.py
+++ b/src/Model/River.py
@@ -17,9 +17,11 @@ class RiverNode(Node):
 
         self._locker = None
 
+    @property
     def locker(self):
         return self._locker
 
+    @locker.setter
     def locker(self, locker):
         self._locker = locker
 
@@ -35,9 +37,11 @@ class RiverReach(Edge):
 
         self._reach = None
 
+    @property
     def reach(self):
         return self._reach
 
+    @reach.setter
     def reach(self, reach:Reach):
         self._reach = reach
 
diff --git a/src/View/Geometry/qtableview_reach.py b/src/View/Geometry/qtableview_reach.py
index 22c8f2fc5402857be2c003a120c16cb60c2b3f0b..0a0bb274ff71adfb6df3bf096dcd4d76034a27d1 100644
--- a/src/View/Geometry/qtableview_reach.py
+++ b/src/View/Geometry/qtableview_reach.py
@@ -45,7 +45,7 @@ class PandasModelEditable(QAbstractTableModel):
             ]
 
     def rowCount(self, parent=QModelIndex()):
-        return len(self._data.profile)
+        return self._data.number_profiles
 
     def columnCount(self, parent=QModelIndex()):
         return len(self.headers)
@@ -53,39 +53,29 @@ class PandasModelEditable(QAbstractTableModel):
     def data(self, index, role=Qt.DisplayRole):
         if index.isValid():
             if role == Qt.DisplayRole and index.column() == 0:
-                value = self._data.profile[index.row()].name
-                return self._data.profile[index.row()].name
+                return self._data.profile(index.row()).name
 
             if role == Qt.DisplayRole and index.column() == 1:
-                return "%.4f" % float(self._data.profile[index.row()].pk)
+                kp = self._data.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._data.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.BackgroundRole and index.column() == 1:
-            #     return QtGui.QColor(Qt.lightGray)
-
-            # if role == Qt.BackgroundRole and index.column() == 2:
-            #     color = QtGui.QColor()
-            #     data_i_profile_type = self._data.profile[index.row()].profile_type
-
-            #     if data_i_profile_type == self.profiles_type[1]:
-            #         color = QtGui.QColor("magenta")
-            #     elif data_i_profile_type == self.profiles_type[2]:
-            #         color = QtGui.QColor("red")
-            #     else:
-            #         color = QtGui.QColor("lightgreen")
-
-            #     return color
-
             if role == Qt.ForegroundRole and index.column() == 0:
-                if self._data.profile[index.row()].name == "Amont":
+                name = self._data.profile(index.row()).name\
+                                                      .strip()\
+                                                      .lower()
+
+                if (name == "upstream" or
+                    name == _translate("Geometry", "upstream")):
                     return QtGui.QColor("Green")
-                elif self._data.profile[index.row()].name == "Aval":
+                elif (name == "downstream" or
+                      name == _translate("Geometry", "downstream")):
                     return QtGui.QColor("Red")
 
         return QVariant()
@@ -95,31 +85,27 @@ class PandasModelEditable(QAbstractTableModel):
             if orientation == Qt.Horizontal:
                 if section < len(self.headers):
                     return self.headers[section]
-                else:
-                    return "not implemented"
             else:
-                return "%d" % (section + 1)
+                return str(section + 1)
 
         if orientation == Qt.Vertical and role == Qt.DisplayRole:
             return self.headers[section]
 
-        return None
+        return QVariant()
 
     def setData(self, index, value, role=Qt.EditRole):
         row = index.row()
         column = index.column()
 
         if role == Qt.EditRole and index.column() != 2:
-            try:
-                if role == Qt.EditRole and index.column() == 0:
-                    self._data.profile[index.row()].name = value
+            if role == Qt.EditRole and index.column() == 0:
+                self._data.profile(index.row()).name = value
 
-                if role == Qt.EditRole and index.column() == 1:
-                    self._data.profile[index.row()].pk = float(value)
+            if role == Qt.EditRole and index.column() == 1:
+                self._data.profile(index.row()).pk = float(value)
 
-                self.dataChanged.emit(index, index)
-            except:
-                self.QMessageBoxCritical(value)
+            self.dataChanged.emit(index, index)
+            self.layoutChanged.emit()
 
             return True
 
@@ -128,20 +114,6 @@ class PandasModelEditable(QAbstractTableModel):
 
         return False
 
-    @staticmethod
-    def QMessageBoxCritical(value):
-        msg = QMessageBox()
-        msg.setIcon(QMessageBox.Warning)
-        msg.setText("{} : Valeur saisie incorrecte".format(value))
-        msg.setInformativeText("Seules les valeurs numériques sont autorisées.")
-        msg.setWindowTitle("Warning ")
-        msg.setStyleSheet("QLabel{min-width:250 px; font-size: 13px}; "
-                          "QPushButton{ width:20px; font-size: 12px}; "
-                          "background-color: Ligthgray ; "
-                          "color : gray;font-size: 8pt; "
-                          "color: #888a80;")
-        msg.exec_()
-
     def index(self, row, column, parent=QModelIndex()):
         if not self.hasIndex(row, column, parent):
             return QModelIndex()
@@ -149,27 +121,22 @@ class PandasModelEditable(QAbstractTableModel):
         return self.createIndex(row, column, QModelIndex())
 
     def flags(self, index):
+        flg = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+
         if index.column() == 2:
-            return Qt.ItemIsEnabled | Qt.ItemIsSelectable
+            return flg
         else:
-            return Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsEnabled
+            return Qt.ItemIsEditable | flg
 
     # @QtCore.pyqtSlot()
     def insertRows(self, row, count, parent=QModelIndex()):
         self.beginInsertRows(parent, row, row + count - 1)
 
         self._data.add_profile(row)
-        self._data.profile[row].profile_type = "XYZ"
 
         self.endInsertRows()
         self.layoutChanged.emit()
 
-    def insertRows_(self, row, rowt=1, parent=QModelIndex()):
-        self.beginInsertRows(parent, row, rowt)
-        self._data.add_profile(row)
-        self.endInsertRows()
-        self.layoutChanged.emit()
-
     def remove_rows(self, list_row_selected, parent=QModelIndex()):
         self.beginRemoveRows(parent, list_row_selected[0], list_row_selected[-1])
 
@@ -182,190 +149,31 @@ class PandasModelEditable(QAbstractTableModel):
         self.endRemoveRows()
         self.layoutChanged.emit()
 
-    def removeRows_(self, position, rows, parent=QModelIndex()):
-        self.beginRemoveRows(QModelIndex(), position, position + 1)
-        self._data.delete_profile(position)
-        self.endRemoveRows()
-        self.layoutChanged.emit()
-
-    def export_reach(self, filename):
-        with open(f"{filename}", "w") as file_st:
-            for index_pro in range(len(self._data.profile)):
-                file_st.write("    ")
-                for head in self._data.headers[index_pro]:
-                    file_st.write(str(head))
-                    file_st.write("    ")
-                file_st.write("\n")
-
-                for point in self._data.profile[index_pro].points:
-                    for i in [point.x, point.y, point.z, point.name]:
-                        if isinstance(i, float):
-                            if i >= 0:
-                                file_st.write("    " + str("%.4f" % i))
-                            else:
-                                file_st.write("   " + str("%.4f" % i))
-                        else:
-                            file_st.write("    " + str(i))
-
-                        file_st.write("\n")
-                file_st.write("    999.9990     999.9990     999.9990")
-                file_st.write("\n")
-
     def sort_data(self, _reverse):
         self.layoutAboutToBeChanged.emit()
-        self._data.sort_descending(_reverse)
+
+        self._data.sort(_reverse)
+
         self.layoutAboutToBeChanged.emit()
         self.layoutChanged.emit()
 
     def moveRowDown(self, row_to_move, parent=QModelIndex()):
         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.endMoveRows()
         self.layoutChanged.emit()
 
     def moveRowUp(self, row_to_move, parent=QModelIndex()):
         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.endMoveRows()
-        self.layoutChanged.emit()
 
-    def graphique(self, ax):
+        self.endMoveRows()
         self.layoutChanged.emit()
-        self.ax = ax
-        for i in range(len(self._data)):
-            self.ax.plot(self._data[i][1].iloc[:, 0],
-                         self._data[i][1].iloc[:, 1],
-                         color='r', lw=1., markersize=3, marker='+')
-
-    def get_profile_selected(self, index):
-        return self._data.profile[index]
-
-    def get_profile_selected_identifier(self, index):
-        return self._data.profile[index].headers[0]
-
-    def get_profile_name(self, index):
-        return self._data.profile[index].name
-
-    def get_profile_via_identifier(self, identifier):
-        profile, = [
-            profile for profile in self._data.profile
-            if profile.headers[0] == str(identifier)
-        ]
-        return profile
-
-    def get_z_min(self):
-        return self._data.get_bief_list_z_min()
-
-    def get_z_min_i(self, index):
-        return self._data.profile[index].z_min
-
-    def get_z_max(self):
-        """
-        Returns: liste des z_max du profile
-        """
-        return self._data.get_bief_list_z_max()
-
-    def get_z_max_i(self, index):
-        return self._data.profile[index].z_max
-
-    def get_pk(self):
-        """
-        Returns: liste des Pk
-        """
-        return self._data.get_bief_pk()
-
-    def get_pk_i(self, index):
-        return self._data.profile[index].pk
-
-    def get_x(self):
-        return self._data.get_bief_x()
-
-    def get_y(self):
-        return self._data.get_bief_y()
-
-    def get_x_complete_list_ld(self):
-        return self._data.get_bief_x_complete_ld()
-
-    def get_y_complete_list_ld(self):
-        return self._data.get_bief_y_complete_ld()
-
-    def get_z_complete_list_ld(self):
-        return self._data.get_bief_z_complete_ld()
-
-    def get_pk_complete_list_ld(self):
-        return self._data.get_bief_pk_complete_guideline()
-
-    def get_x_incomplete_list_ld(self):
-        pass
-
-    def x_complete_guideline(self):
-        return [
-            [
-                profile.x_all_points_complete_guideline(name)
-                for profile in self._data.profile
-            ] for name in self._data.complete_guideline()
-        ]
-
-    def y_complete_guideline(self):
-        return [
-            [
-                profile.y_all_points_complete_guideline(name)
-                for profile in self._data.profile
-            ] for name in self._data.complete_guideline()
-        ]
-
-    def z_complete_guideline(self):
-        return [
-            [
-                profile.z_all_points_complete_guideline(name)
-                for profile in self._data.profile
-            ] for name in self._data.complete_guideline()
-        ]
-
-    def get_station(self, index):
-        return self._data.get_station(index)
-
-    def get_z(self):
-        return self._data.get_bief_z()
-
-    def get_x_profile_i(self, index):
-        return self._data.profile[index].x
-
-    def get_y_profile_i(self, index):
-        return self._data.profile[index].y
-
-    def get_z_profile_i(self, index):
-        return self._data.profile[index].z
-
-    def get_ld_profile_i(self, index):
-        return self._data.profile[index].ld
-
-    def get_pk_profile_i(self, index):
-        return self._data.profile[index].pk
-
-    def get_complete_list_ld(self):
-        return self._data.complete_guideline()
-
-    def get_incomplete_list_ld(self):
-        return self._data.incomplete_guideline()
-
-    def model_data(self):
-        return self._data
-
-    def add_ld(self, *args):
-        lst = []
-        for i in args:
-            list_i = []
-            for j in range(len(i)):
-                l = i[1]
-                list_i.append(l)
-            lst.extend(list_i)
-        return lst, len(lst)
-
-    def size_list_named_points(self):
-        return len(self.get_all_maned_points())
 
 
 class Delegate(QtWidgets.QStyledItemDelegate):
@@ -398,104 +206,6 @@ class Delegate(QtWidgets.QStyledItemDelegate):
         editor.setGeometry(option.rect)
 
 
-class Delegate11(QtWidgets.QItemDelegate):
-    def __init__(self, owner, choices):
-        super().__init__(owner)
-        self.items = choices
-
-    def createEditor(self, parent, option, index):
-        self.editor = QtWidgets.QComboBox(parent)
-        # self.editor.currentIndexChanged.connect(self.commit_editor)
-        self.editor.addItems(self.items)
-        return self.editor
-
-    def paint(self, painter, option, index):
-        value = index.data(Qt.DisplayRole)
-        style = QtWidgets.QApplication.style()
-        opt = QtWidgets.QStyleOptionComboBox()
-        opt.text = str(value)
-        opt.rect = option.rect
-        style.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, opt, painter)
-        QtWidgets.QItemDelegate.paint(self, painter, option, index)
-
-    # def commit_editor(self):
-    #     editor = self.sender()
-    #     color = QtGui.QColor()
-    #     if editor.currentText() == "ProfilXYZ":
-    #         color = QtGui.QColor("lightgreen")
-    #     elif editor.currentText() == "ProfilAC":
-    #         color = QtGui.QColor("red")
-    #     qss = """QComboBox{background-color : %s;}""" % (color.name(),)
-    #     editor.setStyleSheet(qss)
-    #     self.commitData.emit(editor)
-
-    def setEditorData(self, editor, index):
-        editor.blockSignals(True)
-        editor.setCurrentIndex(index.row())  # replacement
-        editor.blockSignals(False)
-
-    # @pyqtSlot()
-    # def currentIndexChanged(self):
-    #     self.commit_editor.emit(self.sender())
-
-    def setModelData(self, editor, model, index):
-        value = editor.currentText()
-        model.setData(index, Qt.DisplayRole, QVariant(value))
-
-    def updateEditorGeometry(self, editor, option, index):
-        editor.setGeometry(option.rect)
-
-
-class Delegate1(QtWidgets.QStyledItemDelegate):
-    def __init__(self, owner, choices):
-        super().__init__(owner)
-        self.items = choices
-
-    def paint(self, painter, option, index):
-        if isinstance(self.parent(), QtWidgets.QAbstractItemView):
-            self.parent().openPersistentEditor(index)
-        super(Delegate1, self).paint(painter, option, index)
-
-    def createEditor(self, parent, option, index):
-        editor = QtWidgets.QComboBox(parent)
-        # editor.currentIndexChanged.connect(self.commit_editor)
-        editor.addItems(self.items)
-        return editor
-
-    # def commit_editor(self):
-    #     editor = self.sender()
-    #     color = QtGui.QColor()
-
-    #     if editor.currentText() == "ProfilXYZ":
-    #         color = QtGui.QColor("lightgreen")
-    #     elif editor.currentText() == "ProfilAC":
-    #         color = QtGui.QColor("red")
-
-    #     qss = """QComboBox{background-color : %s;}""" % (color.name(),)
-    #     editor.setStyleSheet(qss)
-    #     self.commitData.emit(editor)
-
-    def setEditorData(self, editor, index):
-        editor.blockSignals(True)
-        text = index.model().data(index, Qt.DisplayRole)
-        try:
-            i = self.items.index(text)
-        except ValueError:
-            i = 0
-        editor.setCurrentIndex(i)
-        editor.blockSignals(False)
-
-    def setModelData(self, editor, model, index):
-        model.setData(index, editor.currentText(), Qt.DisplayRole)
-
-    def updateEditorGeometry(self, editor, option, index):
-        editor.setGeometry(option.rect)
-
-    @pyqtSlot()
-    def currentIndexChanged(self):
-        self.commitData.emit(self.sender())
-
-
 class PandasModelEditableCreateReach(QAbstractTableModel):
     # TODO : Cette calsse permet juste d'éviter que l'application plante lorsque 'on essaye d'éditer le tablueau. Le
     #  problème se trouve au niveau du délégué QtWidgets.QStyledItemDelegate. Il faudra prendre en compte le cas où
@@ -631,285 +341,6 @@ class PandasModelEditableCreateReach(QAbstractTableModel):
         self.endMoveRows()
         self.layoutChanged.emit()
 
-    def graphique(self, ax):
-        self.layoutChanged.emit()
-        self.ax = ax
-
-        for i in range(len(self._data)):
-            self.ax.plot(self._data[i][1].iloc[:, 0],
-                         self._data[i][1].iloc[:, 1],
-                         color='r', lw=1., markersize=3, marker='+')
-
-    def get_z_min(self):
-        z_min = []
-
-        for row in range(self.rowCount()):
-            z_min.append(min(self._data[row][1].iloc[:, 2].tolist()))
-
-        return z_min
-
-    def get_z_max(self):
-        """
-        Returns: liste des z_max du profile
-        """
-        z_max = []
-
-        for row in range(self.rowCount()):
-            z_max.append(max(self._data[row][1].iloc[:, 2].tolist()))
-
-        return z_max
-
-    def get_pk(self):
-        """
-        Returns: liste des Pk
-        """
-        Pk = [
-            float(self._data[row][0][4]) for row in range(self.rowCount())
-        ]
-
-        return Pk
-
-    def get_x(self):
-        d = time.time()
-        x = []
-
-        for row in range(self.rowCount()):
-            lst = self._data[row][1].iloc[:, 0]  # .tolist()
-            x.append(lst)
-
-        return x
-
-    def get_y(self):
-        y = []
-
-        for row in range(self.rowCount()):
-            lst = self._data[row][1].iloc[:, 1]  # .tolist()
-            y.append(lst)
-
-        return y
-
-    def get_z(self):
-        z = []
-
-        for row in range(self.rowCount()):
-            z.append(float(self._data[row][1].iloc[:, 2]))
-
-        return z
-
-    def add_ld(self, *args):
-        lst = []
-
-        for i in args:
-            list_i = []
-            for j in range(len(i)):
-                l = i[1]
-                list_i.append(l)
-            lst.extend(list_i)
-
-        return lst, len(lst)
-
-    def get_all_maned_points(self):
-        """
-            Returns: la liste qui est l'union disjointe des listes de nom de points de tous les profils du profile
-        """
-        # je considère une union disjointe au lieu d'une intersection pour prendre en compte d'éventuelles lignes
-        # directrices qui ne sont définies qu'à une partie du profile ie qui ne relient pas les deux deux profils
-        # extrêmes.
-        # NB : la liste retournée est "alphanumériquement" ordonnée ?!
-        liste = [data[1].iloc[:, 3].tolist() for data in self._data]
-        disjoint_union_ld = reduce(np.union1d, liste)
-        disjoint_union_ld_list = [
-            element for element in disjoint_union_ld.tolist() if len(element.strip()) != 0
-        ]
-
-        return disjoint_union_ld_list
-
-    def size_list_named_points(self):
-        return len(self.get_all_maned_points())
-
-    def get_complete_list_ld(self):
-        liste = [data[1].iloc[:, 3] for data in self._data]
-        intersection_ld = reduce(np.intersect1d, liste)
-        intersection_ld_list = [el for el in intersection_ld.tolist() if el != ""]
-        return intersection_ld_list
-
-    def get_incomplete_list_ld(self):
-        """
-            Returns : liste de noms de points nommés incomplets, c'est-à-dire, des points nommés définis que
-            sur un ou quelques profils seulement. Il s'agit de la liste des lignes directrices "incomplètes".
-        """
-        liste = [data[1].iloc[:, 3] for data in self._data]
-        disjoint_union_ld = reduce(np.union1d, liste)
-        disjoint_union_ld_list = [el for el in disjoint_union_ld.tolist() if el != ""]
-        diff_union_instersect_ld = list(
-            set(disjoint_union_ld_list).symmetric_difference(set(self.get_complete_list_ld())))
-        return diff_union_instersect_ld
-
-    def get_x_y_named_points(self):
-        """
-            Returns : les coordonnées (x,y) des points nommés "complets" et (éventuellement) "incomplets"
-        """
-        list_x_y_ld = []
-        list_x_y_ld_incomplete = []
-
-        liste = [data[1].iloc[:, 3] for data in self._data]
-        intersection_ld = reduce(np.intersect1d, liste)
-        intersection_ld_list = [el for el in intersection_ld.tolist() if el != ""]
-        disjoint_union_ld = reduce(np.union1d, liste)
-        disjoint_union_ld_list = [el for el in disjoint_union_ld.tolist() if el != ""]
-        diff_union_instersect_ld = list(set(disjoint_union_ld_list).symmetric_difference(set(intersection_ld_list)))
-
-        if len(intersection_ld_list) != 0:
-            for data in self._data:
-                df = data[1]  # .iloc[row, 3]
-                col_name = df.columns[3]  # colonne (Name) des lignes directrices
-                col_x = df.columns[0]
-                col_y = df.columns[1]
-                list_name = df[col_name].to_list()  # liste de noms de lignes directrices
-                list_x = df[col_x].to_list()
-                list_y = df[col_y].to_list()
-                list_ld = [[list_x[list_name.index(name)], list_y[list_name.index(name)], name]
-                           for name in intersection_ld_list]
-                list_x_y_ld.append(list_ld)
-                if len(diff_union_instersect_ld) != 0:
-                    list_ld_incomlete = [
-                        [list_x[list_name.index(name)], list_y[list_name.index(name)], name]
-                        for name in diff_union_instersect_ld
-                        if name in list_name
-                    ]
-
-                    if len(list_ld_incomlete) != 0:
-                        [list_x_y_ld_incomplete.append(i) for i in list_ld_incomlete]
-
-            x_y_list_named_pt_i = [
-                [listeld[i] for listeld in list_x_y_ld]
-                for i in range(len(intersection_ld_list))
-            ]
-
-            liste_x_ld = [[element[0] for element in x_y_list_named_pt_ii]
-                          for x_y_list_named_pt_ii in x_y_list_named_pt_i]
-
-            liste_y_ld = [[element[1] for element in x_y_list_named_pt_ii]
-                          for x_y_list_named_pt_ii in x_y_list_named_pt_i]
-
-            x_y_ld = [np.array([liste_x_ld[i], liste_y_ld[i]]) for i in range(len(x_y_list_named_pt_i))]
-
-            if len(diff_union_instersect_ld) != 0:
-                x_y_list_named_pt_i_incomplete = [
-                    list(v) for _, v in
-                    groupby(sorted(list_x_y_ld_incomplete, key=itemgetter(2)),
-                            key=itemgetter(2))
-                ]
-
-                liste_x_ld_incomplete = [[element[0] for element in x_y_list_named_pt_ii] for x_y_list_named_pt_ii in
-                                         x_y_list_named_pt_i_incomplete]
-                liste_y_ld_incomplete = [[element[1] for element in x_y_list_named_pt_ii] for x_y_list_named_pt_ii in
-                                         x_y_list_named_pt_i_incomplete]
-                x_y_ld_incomplete = [np.array([liste_x_ld_incomplete[i], liste_y_ld_incomplete[i]]) for i in
-                                     range(len(x_y_list_named_pt_i_incomplete))]
-            else:
-                x_y_ld_incomplete = []
-            return x_y_ld, x_y_ld_incomplete
-        else:
-            print("TODO")
-            return []
-
-    def get_pk_z_named_points(self):
-        list_pk_z_ld = []
-
-        for row in range(self.rowCount()):
-            df = self._data[row][1]  # .iloc[row, 3]
-            col_name = df.columns[3]  # colonne (Name) des lignes directrices
-            col_z = df.columns[2]
-            list_name = df[col_name].to_list()  # liste de noms de lignes directrices
-            list_z = df[col_z].to_list()
-            Pk_i = float(self._data[row][0][4])  # le ième Pk
-            list_ld = [
-                [Pk_i, list_z[list_name.index(name)], name]
-                for name in self.get_all_maned_points()
-            ]
-
-            if len(list_ld) > 0:
-                list_pk_z_ld.append(list_ld)
-
-        mon_list = [
-            [listeld[i] for listeld in list_pk_z_ld]
-            for i in range(len(self.get_all_maned_points()))
-        ]
-
-        liste_pk_ld = [
-            [element[0] for element in mon_list[i]]
-            for i in range(len(mon_list))
-        ]
-        liste_z_ld = [
-            [element[1] for element in mon_list[i]]
-            for i in range(len(mon_list))
-        ]
-        pk_z_ld = [
-            np.array([liste_pk_ld[i], liste_z_ld[i]])
-            for i in range(len(mon_list))
-        ]
-
-        return pk_z_ld
-
-    def get_pk_z_ld(self):
-        """
-        Returns: liste de [Pk, z, ld] par profil
-                liste de listes contenant les z des points nommés (lignes directrices) par profil
-        """
-
-        list_pk_z_ld = []
-        list_pk_z_ld_incomplete = []
-
-        start = time.time()
-        liste = [data[1].iloc[:, 3].tolist() for data in self._data]
-
-        intersection_ld = reduce(np.intersect1d, liste)
-        intersection_ld_list = [el for el in intersection_ld.tolist() if el != ""]
-        disjoint_union_ld = reduce(np.union1d, liste)
-        disjoint_union_ld_list = [el for el in disjoint_union_ld.tolist() if el != ""]
-        diff_union_instersect_ld = list(set(disjoint_union_ld_list).symmetric_difference(set(intersection_ld_list)))
-
-        for row in range(self.rowCount()):
-            df = self._data[row][1]  # .iloc[row, 3]
-            col_name = df.columns[3]  # colonne (Name) des lignes directrices
-            col_z = df.columns[2]
-            list_name = df[col_name].to_list()  # liste de noms de lignes directrices
-            list_z = df[col_z].to_list()
-            Pk_i = float(self._data[row][0][4])  # le ième Pk
-
-            list_ld = [[Pk_i, list_z[list_name.index(name)], name] for name in
-                       intersection_ld_list]  # disjoint_union_ld_list]
-
-            if len(diff_union_instersect_ld) != 0:
-                list_ld_incomlete = [[Pk_i, list_z[list_name.index(name)], name] for name in diff_union_instersect_ld if
-                                     name in list_name]
-                list_pk_z_ld_incomplete.append(list_ld_incomlete)
-
-            if len(list_ld) > 0:
-                list_pk_z_ld.append(list_ld)
-
-        my_list = []
-        ll = []
-
-        for listeld in list_pk_z_ld:
-            ll.append(listeld[1])
-
-        ll0 = [listeld[1] for listeld in list_pk_z_ld]
-        mon_list = [[listeld[i] for listeld in list_pk_z_ld] for i in range(len(intersection_ld_list))]
-        liste_z_ld = [[el[1] for el in mon_list[i]] for i in range(len(mon_list))]
-        liste_pk_ld = [[el[0] for el in mon_list[i]] for i in range(len(mon_list))]
-        pk_z_ld = [np.array([liste_pk_ld[i], liste_z_ld[i]]) for i in range(len(mon_list))]
-
-        for j in range(len(list_pk_z_ld[0])):
-            lst = [el[j][1] for el in list_pk_z_ld]
-            my_list.append(lst)
-
-        return my_list  # liste de listes contenant les z des points nommés (lignes directrices) par profil
-
-    def model_data(self):
-        return self._data
-
 
 class Delegate(QtWidgets.QStyledItemDelegate):
     # Lorsque l'on souhaite uniquement personnaliser l'édition des éléments dans une vue et non le rendu,
@@ -941,56 +372,6 @@ class Delegate(QtWidgets.QStyledItemDelegate):
         """permet de redimensionner l'éditeur à la bonne taille lorsque la taille de la vue change"""
         editor.setGeometry(option.rect)
 
-
-class Delegate11(QtWidgets.QItemDelegate):
-    def __init__(self, owner, choices):
-        super().__init__(owner)
-        self.items = choices
-
-    def createEditor(self, parent, option, index):
-        self.editor = QtWidgets.QComboBox(parent)
-        # self.editor.currentIndexChanged.connect(self.commit_editor)
-        self.editor.addItems(self.items)
-        return self.editor
-
-    def paint(self, painter, option, index):
-        value = index.data(Qt.DisplayRole)
-        style = QtWidgets.QApplication.style()
-        opt = QtWidgets.QStyleOptionComboBox()
-        opt.text = str(value)
-        opt.rect = option.rect
-        style.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, opt, painter)
-        QtWidgets.QItemDelegate.paint(self, painter, option, index)
-
-
-    # def commit_editor(self):
-    #     editor = self.sender()
-    #     color = QtGui.QColor()
-    #     if editor.currentText() == "ProfilXYZ":
-    #         color = QtGui.QColor("lightgreen")
-    #     elif editor.currentText() == "ProfilAC":
-    #         color = QtGui.QColor("red")
-    #     qss = """QComboBox{background-color : %s;}""" % (color.name(),)
-    #     editor.setStyleSheet(qss)
-    #     self.commitData.emit(editor)
-
-    def setEditorData(self, editor, index):
-        editor.blockSignals(True)
-        editor.setCurrentIndex(index.row())  # replacement
-        editor.blockSignals(False)
-
-    # @pyqtSlot()
-    # def currentIndexChanged(self):
-    #     self.commit_editor.emit(self.sender())
-
-    def setModelData(self, editor, model, index):
-        value = editor.currentText()
-        model.setData(index, Qt.DisplayRole, QVariant(value))
-
-    def updateEditorGeometry(self, editor, option, index):
-        editor.setGeometry(option.rect)
-
-
 class Delegate1(QtWidgets.QStyledItemDelegate):
     def __init__(self, owner, choices):
         super().__init__(owner)
@@ -1007,17 +388,6 @@ class Delegate1(QtWidgets.QStyledItemDelegate):
         editor.addItems(self.items)
         return editor
 
-    # def commit_editor(self):
-    #     editor = self.sender()
-    #     color = QtGui.QColor()
-    #     if editor.currentText() == "ProfilXYZ":
-    #         color = QtGui.QColor("lightgreen")
-    #     elif editor.currentText() == "ProfilAC":
-    #         color = QtGui.QColor("red")
-    #     qss = """QComboBox{background-color : %s;}""" % (color.name(),)
-    #     editor.setStyleSheet(qss)
-    #     self.commitData.emit(editor)
-
     def setEditorData(self, editor, index):
         editor.blockSignals(True)
         text = index.model().data(index, Qt.DisplayRole)