diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py
index 86e0f1d2048bd4e28c3c9fd981d512c52c2fed5d..d6abb6c9ea8a847ba3c236d517abe5a2f3c4a444 100644
--- a/src/Model/BoundaryCondition/BoundaryCondition.py
+++ b/src/Model/BoundaryCondition/BoundaryCondition.py
@@ -83,7 +83,8 @@ class BoundaryCondition(SQLSubModel):
     def _get_ctor_from_type(cls, t):
         from Model.BoundaryCondition.BoundaryConditionTypes import (
             NotDefined, PonctualContribution,
-            TimeOverZ, TimeOverDischarge, ZOverDischarge
+            TimeOverZ, TimeOverDischarge, ZOverDischarge,
+            Solid,
         )
 
         res = NotDefined
@@ -95,6 +96,8 @@ class BoundaryCondition(SQLSubModel):
             res = TimeOverDischarge
         elif t == "ZD":
             res = ZOverDischarge
+        elif t == "SL":
+            res = Solid
         return res
 
     @classmethod
diff --git a/src/Model/BoundaryCondition/BoundaryConditionList.py b/src/Model/BoundaryCondition/BoundaryConditionList.py
index 1a342dc781bd846d47c81bdac4c0321a5c64ee6b..2514f32694a598ee1a2c690cf38dc58e4013d560 100644
--- a/src/Model/BoundaryCondition/BoundaryConditionList.py
+++ b/src/Model/BoundaryCondition/BoundaryConditionList.py
@@ -26,7 +26,8 @@ from Model.BoundaryCondition.BoundaryCondition import BoundaryCondition
 from Model.BoundaryCondition.BoundaryConditionTypes import (
     NotDefined,
     PonctualContribution,
-    TimeOverZ, TimeOverDischarge, ZOverDischarge
+    TimeOverZ, TimeOverDischarge, ZOverDischarge,
+    Solid,
 )
 
 class BoundaryConditionList(SQLSubModel):
diff --git a/src/Model/BoundaryCondition/BoundaryConditionTypes.py b/src/Model/BoundaryCondition/BoundaryConditionTypes.py
index b2c73f11326b652184cc92d9fd3d01ae361490a8..963e88e72d58463e2c62b84be9d11733acd3e0a3 100644
--- a/src/Model/BoundaryCondition/BoundaryConditionTypes.py
+++ b/src/Model/BoundaryCondition/BoundaryConditionTypes.py
@@ -83,3 +83,16 @@ class ZOverDischarge(BoundaryCondition):
     @property
     def _default_0(self):
         return 0.0
+
+
+class Solid(BoundaryCondition):
+    def __init__(self, id:int = -1, name:str = "", status = None):
+        super(Solid, self).__init__(id=id, name=name, status=status)
+
+        self._type = "SL"
+        self._header = ["time", "solid"]
+        self._types = [TimeOverDischarge.time_convert, float]
+
+    @classmethod
+    def compatibility(cls):
+        return ["solid"]
diff --git a/src/Model/Geometry/Point.py b/src/Model/Geometry/Point.py
index b3b51e7d07179b24c655136455b682f940f60145..cc1971c096db57224da5c4ef046a68c41ec864b8 100644
--- a/src/Model/Geometry/Point.py
+++ b/src/Model/Geometry/Point.py
@@ -19,12 +19,29 @@
 from Model.Except import NotImplementedMethodeError
 
 class Point(object):
-    def __init__(self, name:str = "", status = None):
+    def __init__(self, name:str = "", profile=None, status = None):
         super(Point, self).__init__()
 
         self._status = status
 
         self._name = name
+        self._profile = profile
+        self._sl = None
+
+
+    @property
+    def sl(self):
+        if self._sl is None:
+            return self._profile.sl
+
+        return self._sl
+
+    @sl.setter
+    def sl(self, sl):
+        if sl == self._profile.sl:
+            self._sl = None
+
+        self._sl = sl
 
     @property
     def name(self):
diff --git a/src/Model/Geometry/PointXYZ.py b/src/Model/Geometry/PointXYZ.py
index cffcee971f6f2b2251353402bd60dfba1073e2a7..19695c7753c63aa93a81e43d508b64c85208dd7f 100644
--- a/src/Model/Geometry/PointXYZ.py
+++ b/src/Model/Geometry/PointXYZ.py
@@ -26,8 +26,8 @@ class PointXYZ(Point, SQLSubModel):
     _sub_classes = []
 
     def __init__(self, x:float = 0.0, y:float = 0.0, z:float = 0.0,
-                 name:str = "", status = None):
-        super(PointXYZ, self).__init__(name=name, status=status)
+                 name:str = "", profile = None, status = None):
+        super(PointXYZ, self).__init__(name=name, profile=profile, status=status)
 
         self._x = float(x)
         self._y = float(y)
@@ -44,7 +44,9 @@ class PointXYZ(Point, SQLSubModel):
             y INTEGER NOT NULL,
             z INTEGER NOT NULL,
             profile INTEGER NOT NULL,
-            FOREIGN KEY(profile) REFERENCES profileXYZ(id)
+            sl INTEGER,
+            FOREIGN KEY(profile) REFERENCES profileXYZ(id),
+            FOREIGN KEY(sl) REFERENCES sedimentary_layer(id)
           )
         """)
 
@@ -53,6 +55,17 @@ class PointXYZ(Point, SQLSubModel):
     @classmethod
     def _sql_update(cls, execute, version):
         cls._update_submodel(execute, version)
+
+        major, minor, release = version.strip().split(".")
+        if major == minor == "0":
+            if int(release) < 2:
+                execute(
+                    """
+                    ALTER TABLE geometry_pointXYZ
+                    ADD COLUMN sl INTEGER
+                    REFERENCES sedimentary_layer(id)
+                    """
+                )
         return True
 
     @classmethod
@@ -63,9 +76,9 @@ class PointXYZ(Point, SQLSubModel):
         profile = data["profile"]
 
         table = execute(
-            "SELECT ind, name, x, y, z " +
+            "SELECT ind, name, x, y, z, sl " +
             "FROM geometry_pointXYZ " +
-            f"WHERE profile = {profile}"
+            f"WHERE profile = {profile.id}"
         )
 
         # Create points list
@@ -79,13 +92,25 @@ class PointXYZ(Point, SQLSubModel):
             x = row[2]
             y = row[3]
             z = row[4]
+            sl = row[5]
 
             new = cls(
                 name = name,
                 x = x, y = y, z = z,
+                profile = profile,
                 status = status
             )
 
+            if sl == -1 or sl == None:
+                new._sl = None
+            else:
+                new._sl = next(
+                    filter(
+                        lambda s: s.id == sl,
+                        data["sediment_layers_list"].sediment_layers
+                    )
+                )
+
             points[ind] = new
 
         return points
@@ -94,13 +119,15 @@ class PointXYZ(Point, SQLSubModel):
         profile = data["profile"]
         ind = data["ind"]
 
+        sl = self._sl.id if self._sl is not None else -1
+
         sql = (
             "INSERT OR REPLACE INTO " +
-            "geometry_pointXYZ(ind, name, x, y, z, profile) "+
+            "geometry_pointXYZ(ind, name, x, y, z, profile, sl) "+
             "VALUES (" +
             f"{ind}, '{self._sql_format(self._name)}', " +
             f"{self.x}, {self.y}, {self.z}, " +
-            f"{profile}" +
+            f"{profile.id}, {sl}" +
             ")"
         )
         execute(sql)
@@ -117,7 +144,7 @@ class PointXYZ(Point, SQLSubModel):
                     *data
                 )
             else:
-                valid_header = {'name', 'x', 'y', 'z'}
+                valid_header = {'name', 'x', 'y', 'z', 'profile'}
                 d = {}
                 for i, v in enumerate(data):
                     h = header[i].strip().lower().split(' ')[0]
diff --git a/src/Model/Geometry/Profile.py b/src/Model/Geometry/Profile.py
index c95d2282ad7634a2790a42558eaa79c8f50897d9..d81379322e1c990f4a0d33686a6519de7bab59a8 100644
--- a/src/Model/Geometry/Profile.py
+++ b/src/Model/Geometry/Profile.py
@@ -50,6 +50,7 @@ class Profile(object):
         self._kp = float(kp)
         self._name = str(name)
         self._reach = reach
+        self._sl = None
 
         self._points: List[Point] = []
 
@@ -63,6 +64,9 @@ class Profile(object):
     def points(self):
         return self._points.copy()
 
+    def point(self, index):
+        return self._points[index]
+
     @property
     def reach(self):
         return self._reach
@@ -136,6 +140,19 @@ class Profile(object):
         self._name = value.strip()
         self._status.modified()
 
+    @property
+    def sl(self):
+        """
+        Returns:
+            Profile sediment layers.
+        """
+        return self._sl
+
+    @sl.setter
+    def sl(self, value):
+        self._sl = value
+        self._status.modified()
+
     @property
     def profile_type(self):
         """
@@ -274,6 +291,39 @@ class Profile(object):
         )
         self._status.modified()
 
+    # Sediment Layers
+
+    def get_sl(self):
+        """Get sediment layer height of points
+
+        Get sediment layer of points (without spesific point sl)
+
+        Returns:
+            List of sediment layers height
+        """
+        res = []
+        psl = [point.sl for point in self.points]
+
+        # Compute max number of layers
+        sl_max = 0
+        for sl in psl:
+            n = 0 if sl is None else len(sl)
+            sl_max = max(n, sl_max)
+
+        # Create list of height for each sl and each layer
+        for i in range(0, sl_max):
+            cur = []
+            # Compute new layer line for each sl
+            for sl in psl:
+                if sl is not None and i < len(sl):
+                    cur.append(sl.get(i).height)
+                else:
+                    cur.append(0)
+            # Add layer line to result
+            res.append(cur)
+
+        return res
+
     # Abstract method, must be implemented for in non abstract class
     def get_station(self):
         raise NotImplementedMethodeError(self, self.get_station)
diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py
index 9cf15da4ad411161998b1cb6fe10c90b1c6c9b7c..e818eabce44a8d5de19c3fc07fad52245f2ffd57 100644
--- a/src/Model/Geometry/ProfileXYZ.py
+++ b/src/Model/Geometry/ProfileXYZ.py
@@ -76,7 +76,9 @@ class ProfileXYZ(Profile, SQLSubModel):
             num INTEGER NOT NULL,
             code1 INTEGER NOT NULL,
             code2 INTEGER NOT NULL,
-            FOREIGN KEY(reach) REFERENCES river_reach(id)
+            sl INTEGER,
+            FOREIGN KEY(reach) REFERENCES river_reach(id),
+            FOREIGN KEY(sl) REFERENCES sedimentary_layer(id)
           )
         """)
 
@@ -84,6 +86,17 @@ class ProfileXYZ(Profile, SQLSubModel):
 
     @classmethod
     def _sql_update(cls, execute, version):
+        major, minor, release = version.strip().split(".")
+        if major == minor == "0":
+            if int(release) < 2:
+                execute(
+                    """
+                    ALTER TABLE geometry_profileXYZ
+                    ADD COLUMN sl INTEGER
+                    REFERENCES sedimentary_layer(id)
+                    """
+                )
+
         return cls._update_submodel(execute, version)
 
     @classmethod
@@ -93,7 +106,7 @@ class ProfileXYZ(Profile, SQLSubModel):
         reach = data["reach"]
 
         table = execute(
-            "SELECT id, ind, name, kp, num, code1, code2 " +
+            "SELECT id, ind, name, kp, num, code1, code2, sl " +
             "FROM geometry_profileXYZ " +
             f"WHERE reach = {reach}"
         )
@@ -109,6 +122,7 @@ class ProfileXYZ(Profile, SQLSubModel):
             num = row[5]
             code1 = row[5]
             code2 = row[6]
+            sl = row[7]
 
             new = cls(
                 id=id, num = num,
@@ -118,7 +132,17 @@ class ProfileXYZ(Profile, SQLSubModel):
                 status = status
             )
 
-            data["profile"] = id
+            if sl == -1 or sl == None:
+                new._sl = None
+            else:
+                new._sl = next(
+                    filter(
+                        lambda s: s.id == sl,
+                        data["sediment_layers_list"].sediment_layers
+                    )
+                )
+
+            data["profile"] = new
             new._points = PointXYZ._sql_load(execute, data)
 
             profiles[ind] = new
@@ -129,18 +153,20 @@ class ProfileXYZ(Profile, SQLSubModel):
         ok = True
         ind = data["ind"]
 
+        sl = self._sl.id if self._sl is not None else -1
+
         sql = (
             "INSERT OR REPLACE INTO " +
-            "geometry_profileXYZ(id, ind, name, reach, kp, num, code1, code2) "+
+            "geometry_profileXYZ(id, ind, name, reach, kp, num, code1, code2, sl) "+
             "VALUES (" +
             f"{self.id}, {ind}, '{self._sql_format(self._name)}', " +
             f"{self.reach.id}, {self.kp}, {self.num}, " +
-            f"{self.code1}, {self.code1}" +
+            f"{self.code1}, {self.code1}, {sl}" +
             ")"
         )
         execute(sql)
 
-        data["profile"] = self.id
+        data["profile"] = self
         execute(f"DELETE FROM geometry_pointXYZ WHERE profile = {self.id}")
 
         ind = 0
@@ -178,11 +204,11 @@ class ProfileXYZ(Profile, SQLSubModel):
         try:
             if len(header) == 0:
                 point = PointXYZ(
-                    *data, status=self._status
+                    *data, profile=self, status=self._status
                 )
             else:
                 valid_header = {'name', 'x', 'y', 'z'}
-                d = {"status": self._status}
+                d = {"status": self._status, "profile": self}
                 for i, v in enumerate(data):
                     h = header[i].strip().lower().split(' ')[0]
                     if h in valid_header:
@@ -235,7 +261,7 @@ class ProfileXYZ(Profile, SQLSubModel):
             Nothing.
         """
         for point in list_points:
-            pt = PointXYZ(*point, status=self._status)
+            pt = PointXYZ(*point, profile=self, status=self._status)
             self._points.append(pt)
         self._status.modified()
 
@@ -259,7 +285,7 @@ class ProfileXYZ(Profile, SQLSubModel):
         Returns:
             Nothing.
         """
-        point_xyz = PointXYZ(0., 0., 0., status=self._status)
+        point_xyz = PointXYZ(0., 0., 0., profile=self, status=self._status)
         self._points.append(point_xyz)
         self._status.modified()
 
@@ -272,7 +298,7 @@ class ProfileXYZ(Profile, SQLSubModel):
         Returns:
             The new point.
         """
-        point = PointXYZ(0., 0., 0., status=self._status)
+        point = PointXYZ(0., 0., 0., profile=self, status=self._status)
         self._points.insert(index, point)
         self._status.modified()
         return point
diff --git a/src/Model/Geometry/Reach.py b/src/Model/Geometry/Reach.py
index d2a573f11153b6e037dfcef5cfc8c5ef0c7a3898..0ddf06d8a21510e9f0d89df58889e0bd86430e85 100644
--- a/src/Model/Geometry/Reach.py
+++ b/src/Model/Geometry/Reach.py
@@ -276,6 +276,39 @@ class Reach(SQLSubModel):
         return max(self.get_kp())
 
 
+    # Sediment Layers
+
+    def get_sl(self):
+        """Get sediment layer height of profile
+
+        Get sediment layer of profile (without spesific point sl)
+
+        Returns:
+            List of sediment layers height
+        """
+        res = []
+        psl = [profile.sl for profile in self.profiles]
+
+        # Compute max number of layers
+        sl_max = 0
+        for sl in psl:
+            n = 0 if sl is None else len(sl)
+            sl_max = max(n, sl_max)
+
+        # Create list of height for each sl and each layer
+        for i in range(0, sl_max):
+            cur = []
+            # Compute new layer line for each sl
+            for sl in psl:
+                if sl is not None and i < len(sl):
+                    cur.append(sl.get(i).height)
+                else:
+                    cur.append(0)
+            # Add layer line to result
+            res.append(cur)
+
+        return res
+
     # Guidelines
 
     @timer
diff --git a/src/Model/Results/River/River.py b/src/Model/Results/River/River.py
index 5ae1e90f50f755868c3e24434b289abed3d5ad8c..9f72f7318cb033f79db8113919615b6acd220de4 100644
--- a/src/Model/Results/River/River.py
+++ b/src/Model/Results/River/River.py
@@ -98,6 +98,9 @@ class River(object):
     def reach(self, id):
         return self._reachs[id]
 
+    def has_reach(self, id):
+        return 0 <= id < len(self._reachs)
+
     def add(self, reach_id):
         reachs = self._study.river.enable_edges()
 
diff --git a/src/Model/River.py b/src/Model/River.py
index d0ae5b2293fcea1a075c1f61b7494aa6e08d6f67..91d765ba05f31cc1e779155fab7a5decd0af0693 100644
--- a/src/Model/River.py
+++ b/src/Model/River.py
@@ -16,6 +16,8 @@
 
 # -*- coding: utf-8 -*-
 
+from tools import flatten
+
 from Model.DB import SQLSubModel
 
 from Model.Network.Node import Node
@@ -31,6 +33,7 @@ from Model.InitialConditions.InitialConditionsDict import InitialConditionsDict
 from Model.Stricklers.StricklersList import StricklersList
 from Model.Friction.FrictionList import FrictionList
 from Model.SolverParameters.SolverParametersList import SolverParametersList
+from Model.SedimentLayer.SedimentLayerList import SedimentLayerList
 
 from Solver.Solvers import solver_type_list
 
@@ -208,6 +211,7 @@ class River(Graph, SQLSubModel):
         InitialConditionsDict,
         StricklersList,
         SolverParametersList,
+        SedimentLayerList,
     ]
 
     def __init__(self, status=None):
@@ -223,6 +227,7 @@ class River(Graph, SQLSubModel):
         self._initial_conditions = InitialConditionsDict(status=self._status)
         self._stricklers = StricklersList(status=self._status)
         self._parameters = {}
+        self._sediment_layers = SedimentLayerList(status=self._status)
 
     @classmethod
     def _sql_create(cls, execute):
@@ -246,6 +251,14 @@ class River(Graph, SQLSubModel):
         )
         data["stricklers"] = new._stricklers
 
+
+        # Initial conditions
+        new._sediment_layers = SedimentLayerList._sql_load(
+            execute,
+            data
+        )
+        data["sediment_layers_list"] = new._sediment_layers
+
         # Network
         new._nodes = RiverNode._sql_load(
             execute,
@@ -289,6 +302,7 @@ class River(Graph, SQLSubModel):
         objs.append(self._boundary_condition)
         objs.append(self._initial_conditions)
         objs.append(self._lateral_contribution)
+        objs.append(self._sediment_layers)
         objs.append(self._stricklers)
 
         for solver in self._parameters:
@@ -317,6 +331,10 @@ class River(Graph, SQLSubModel):
     def initial_conditions(self):
         return self._initial_conditions
 
+    @property
+    def sediment_layers(self):
+        return self._sediment_layers
+
     @property
     def stricklers(self):
         return self._stricklers
@@ -366,3 +384,16 @@ class River(Graph, SQLSubModel):
 
     def set_current_reach(self, reach):
         self._current_reach = reach
+
+    def has_sediment(self):
+        has = len(self._sediment_layers) != 0
+        has &= any(
+            filter(
+                lambda p: p.sl != None,
+                flatten(
+                    map(lambda e: e.reach.profiles, self.edges())
+                )
+            )
+        )
+
+        return has
diff --git a/src/Model/SedimentLayer/SedimentLayer.py b/src/Model/SedimentLayer/SedimentLayer.py
new file mode 100644
index 0000000000000000000000000000000000000000..638212c82a8cb267a856d9d1795f5f6fc0da5121
--- /dev/null
+++ b/src/Model/SedimentLayer/SedimentLayer.py
@@ -0,0 +1,339 @@
+# -*- coding: utf-8 -*-
+
+from tools import trace, timer
+
+from Model.DB import SQLSubModel
+from Model.Except import NotImplementedMethodeError
+
+class Layer(SQLSubModel):
+    _sub_classes = []
+    _id_cnt = 0
+
+    def __init__(self,
+                 id:int = -1, name:str = "",
+                 type = "",
+                 height = 0.0, d50 = 0.0, sigma = 0.0,
+                 critical_constraint = 0.0,
+                 sl = None, status = None):
+        super(Layer, self).__init__()
+
+        self._status = status
+
+        self._name = name
+        self._type = type
+
+        self._height = height
+        self._d50 = d50
+        self._sigma = sigma
+        self._critical_constraint = critical_constraint
+
+        if id == -1:
+            self.id = Layer._id_cnt
+        else:
+            self.id = id
+
+        Layer._id_cnt = max(id, Layer._id_cnt+1)
+
+    @property
+    def name(self):
+        return self._name
+
+    @name.setter
+    def name(self, name):
+        self._name = name
+
+    @property
+    def type(self):
+        return self._type
+
+    @type.setter
+    def type(self, type):
+        self._type = type
+
+    @property
+    def height(self):
+        return self._height
+
+    @height.setter
+    def height(self, height):
+        self._height = float(height)
+
+    @property
+    def d50(self):
+        return self._d50
+
+    @d50.setter
+    def d50(self, d50):
+        self._d50 = float(d50)
+
+    @property
+    def sigma(self):
+        return self._sigma
+
+    @sigma.setter
+    def sigma(self, sigma):
+        self._sigma = float(sigma)
+
+    @property
+    def critical_constraint(self):
+        return self._critical_constraint
+
+    @critical_constraint.setter
+    def critical_constraint(self, critical_constraint):
+        self._critical_constraint = float(critical_constraint)
+
+    @classmethod
+    def _sql_create(cls, execute):
+        execute("""
+          CREATE TABLE sedimentary_layer_layer(
+            id INTEGER NOT NULL PRIMARY KEY,
+            ind INTEGER NOT NULL,
+            name TEXT NOT NULL,
+            type TEXT NOT NULL,
+            height REAL NOT NULL,
+            d50 REAL NOT NULL,
+            sigma REAL NOT NULL,
+            critical_constraint REAL NOT NULL,
+            sl INTEGER,
+            FOREIGN KEY(sl) REFERENCES sedimentary_layer(id)
+          )
+        """)
+
+        return cls._create_submodel(execute)
+
+    @classmethod
+    def _sql_update(cls, execute, version):
+        major, minor, release = version.strip().split(".")
+        if major == minor == "0":
+            if int(release) < 2:
+                cls._sql_create(execute)
+
+        return True
+
+    @classmethod
+    def _sql_load(cls, execute, data = None):
+        new = []
+        sl = data["sl"]
+
+        table = execute(
+            "SELECT id, ind, name, type, height, d50, sigma, critical_constraint " +
+            "FROM sedimentary_layer_layer " +
+            f"WHERE sl = {sl}"
+        )
+
+        for _ in table:
+            new.append(None)
+
+        for row in table:
+            ind = row[1]
+
+            layer = cls(
+                id = row[0], name = row[2],
+                type = row[3], height = row[4],
+                d50 = row[5], sigma = row[6],
+                critical_constraint = row[7],
+                sl = sl, status = data['status']
+            )
+
+            new[ind] = layer
+
+        return new
+
+    def _sql_save(self, execute, data = None):
+        ind = data["ind"]
+        sl = data["sl"]
+
+        sql = (
+            "INSERT INTO " +
+            "sedimentary_layer_layer(id, ind, name, type, height, d50, sigma, critical_constraint, sl) "+
+            "VALUES (" +
+            f"{self.id}, {ind}, '{self._sql_format(self._name)}', " +
+            f"'{self._sql_format(self._type)}', {self._height}, " +
+            f"{self._d50}, {self._sigma}, {self._critical_constraint}, " +
+            f"{sl.id}" +
+            ")"
+        )
+        execute(sql)
+
+        return True
+
+
+class SedimentLayer(SQLSubModel):
+    _sub_classes = [Layer]
+    _id_cnt = 0
+
+    def __init__(self, id:int = -1,
+                 name:str = "", comment:str = "",
+                 status = None):
+        super(SedimentLayer, self).__init__()
+
+        self._status = status
+        self._name = name
+        self._comment = comment
+        self._layers = []
+
+        if id == -1:
+            self.id = SedimentLayer._id_cnt
+        else:
+            self.id = id
+
+        SedimentLayer._id_cnt = max(id, SedimentLayer._id_cnt+1)
+
+    def __str__(self):
+        s = f"{self.name} ({len(self)})"
+
+        if self.comment != "":
+            s += f" - {self.comment}"
+
+        return s
+
+    def __len__(self):
+        return len(self._layers)
+
+    @property
+    def layers(self):
+        return self._layers.copy()
+
+    def height(self):
+        return list(
+            map(lambda l: l.height, self._layers)
+        )
+
+    @property
+    def name(self):
+        return self._name
+
+    @name.setter
+    def name(self, name):
+        self._name = name
+
+    def names(self):
+        return list(
+            map(lambda l: l.name, self._layers)
+        )
+
+    @property
+    def comment(self):
+        return self._comment
+
+    @comment.setter
+    def comment(self, comment):
+        self._comment = comment
+
+    @classmethod
+    def _sql_create(cls, execute):
+        execute("""
+          CREATE TABLE sedimentary_layer(
+            id INTEGER NOT NULL PRIMARY KEY,
+            name TEXT NOT NULL,
+            comment TEXT NOT NULL
+          )
+        """)
+
+        return cls._create_submodel(execute)
+
+    @classmethod
+    def _sql_update(cls, execute, version):
+        major, minor, release = version.strip().split(".")
+        if major == minor == "0":
+            if int(release) < 2:
+                cls._sql_create(execute)
+
+        return True
+
+    @classmethod
+    def _sql_load(cls, execute, data = None):
+        new = []
+
+        table = execute(
+            "SELECT id, name, comment " +
+            "FROM sedimentary_layer "
+        )
+
+        for row in table:
+            sl = cls(
+                id = row[0],
+                name = row[1],
+                comment = row[2],
+                status = data['status']
+            )
+
+            data["sl"] = sl.id
+            sl._layers = Layer._sql_load(execute, data)
+
+            new.append(sl)
+
+        return new
+
+    def _sql_save(self, execute, data = None):
+        if data is None:
+            data = {}
+
+        sql = (
+            "INSERT INTO sedimentary_layer (id, name, comment) " +
+            f"VALUES ({self.id}, '{self._sql_format(self._name)}', " +
+            f"'{self._sql_format(self._comment)}')"
+        )
+        execute(sql)
+
+        data["sl"] = self
+
+        ind = 0
+        for l in self._layers:
+            data["ind"] = ind
+            l._sql_save(execute, data)
+            ind += 1
+
+        return True
+
+    def get(self, index):
+        return self._layers[index]
+
+    def set(self, index, new):
+        self._layers[index] = new
+        self._status.modified()
+
+    def insert(self, index, new):
+        self._layers.insert(index, new)
+        self._status.modified()
+
+    def new(self, index):
+        n = Layer(sl=self, status = self._status)
+        self.insert(index, n)
+        self._status.modified()
+        return n
+
+    def delete(self, els):
+        for el in els:
+            self._layers.remove(el)
+        self._status.modified()
+
+    def delete_i(self, indexes):
+        els = list(
+            map(
+                lambda x: x[1],
+                filter(
+                    lambda x: x[0] in indexes,
+                    enumerate(self._layers)
+                )
+            )
+        )
+        self.delete(els)
+
+    def move_up(self, index):
+        if index >= 0:
+            next = index - 1
+
+            l = self._layers
+            l[index], l[next] = l[next], l[index]
+
+            self._status.modified()
+
+    def move_down(self, index):
+        if index + 1 < len(self._layers):
+            prev = index + 1
+
+            l = self._layers
+            l[index], l[prev] = l[prev], l[index]
+
+            self._status.modified()
diff --git a/src/Model/SedimentLayer/SedimentLayerList.py b/src/Model/SedimentLayer/SedimentLayerList.py
new file mode 100644
index 0000000000000000000000000000000000000000..d2b662269cef4d574b6c75b493f3a8bc0c6bbe5f
--- /dev/null
+++ b/src/Model/SedimentLayer/SedimentLayerList.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+
+from tools import trace, timer
+
+from Model.DB import SQLSubModel
+from Model.Except import NotImplementedMethodeError
+from Model.SedimentLayer.SedimentLayer import SedimentLayer
+
+class SedimentLayerList(SQLSubModel):
+    _sub_classes = [SedimentLayer]
+
+    def __init__(self, status = None):
+        super(SedimentLayerList, self).__init__()
+
+        self._status = status
+        self._sl = []
+
+    def __len__(self):
+        return len(self._sl)
+
+    @classmethod
+    def _sql_create(cls, execute):
+        return cls._create_submodel(execute)
+
+    @classmethod
+    def _sql_update(cls, execute, version):
+        return cls._update_submodel(execute, version)
+
+    @classmethod
+    def _sql_load(cls, execute, data = None):
+        new = cls(status = data["status"])
+
+        new._sl = SedimentLayer._sql_load(execute, data)
+
+        return new
+
+    def _sql_save(self, execute, data = None):
+        ok = True
+
+        # Delete previous data
+        execute("DELETE FROM sedimentary_layer")
+        execute("DELETE FROM sedimentary_layer_layer")
+
+        for sl in self._sl:
+            ok &= sl._sql_save(execute, data)
+
+        return ok
+
+    @property
+    def sediment_layers(self):
+        return self._sl.copy()
+
+    def get(self, index):
+        return self._sl[index]
+
+    def set(self, index, new):
+        self._sl[index] = new
+        self._status.modified()
+
+    def insert(self, index, new):
+        self._sl.insert(index, new)
+        self._status.modified()
+
+    def new(self, index):
+        n = SedimentLayer(status = self._status)
+        self.insert(index, n)
+        self._status.modified()
+        return n
+
+    def delete(self, els):
+        for el in els:
+            self._sl.remove(el)
+        self._status.modified()
+
+    def delete_i(self, indexes):
+        els = list(
+            map(
+                lambda x: x[1],
+                filter(
+                    lambda x: x[0] in indexes,
+                    enumerate(self._sl)
+                )
+            )
+        )
+        self.delete(els)
+
+    def move_up(self, index):
+        if index < len(self._sl):
+            next = index - 1
+
+            l = self._sl
+            l[index], l[next] = l[next], l[index]
+            self._status.modified()
+
+    def move_down(self, index):
+        if index >= 0:
+            prev = index + 1
+
+            l = self._sl
+            l[index], l[prev] = l[prev], l[index]
+            self._status.modified()
diff --git a/src/Model/SolverParameters/SolverParametersList.py b/src/Model/SolverParameters/SolverParametersList.py
index a647135680c9e71e41d3c2b316302ee67f71f620..18c455296442ecb9c58493caa7130fff558b6f20 100644
--- a/src/Model/SolverParameters/SolverParametersList.py
+++ b/src/Model/SolverParameters/SolverParametersList.py
@@ -93,6 +93,13 @@ class SolverParametersList(SQLSubModel):
 
     @classmethod
     def _sql_update(cls, execute, version):
+        major, minor, release = version.strip().split(".")
+
+        if major == minor == "0":
+            if int(release) < 3:
+                execute(f"UPDATE solver_parameter SET name='mage_implicitation' WHERE name='mage_implication'")
+                execute(f"UPDATE solver_parameter SET name='mage_iteration_type' WHERE name='mage_iter_type'")
+
         return cls._update_submodel(execute, version)
 
     @classmethod
@@ -160,6 +167,17 @@ class SolverParametersList(SQLSubModel):
     def get(self, index):
         return self._parameters[index]
 
+    def get_by_key(self, key):
+        try:
+            return next(
+                filter(
+                    lambda p: p["name"] == key,
+                    self._parameters
+                )
+            )["value"]
+        except:
+            return None
+
     def set(self, index, new):
         self._parameters[index] = new
         self._status.modified()
diff --git a/src/Model/Study.py b/src/Model/Study.py
index af594c90257a258162af72142567703a14c4cd64..5b44d0a7455a17d5795996b30728dd2071431343 100644
--- a/src/Model/Study.py
+++ b/src/Model/Study.py
@@ -40,7 +40,7 @@ class Study(SQLModel):
 
     def __init__(self, filename = None, init_new = True):
         # Metadata
-        self._version = "0.0.1"
+        self._version = "0.0.3"
         self.creation_date = datetime.now()
         self.last_modification_date = datetime.now()
         self.last_save_date = datetime.now()
diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py
index 64cc01cbffb4cb71dddf7c17e4f84b7160bcd43f..186abbbbd9c93a05ceaa748d1a119e130c854f31 100644
--- a/src/Solver/ASolver.py
+++ b/src/Solver/ASolver.py
@@ -86,6 +86,7 @@ class AbstractSolver(object):
             ("all_init_time", "000:00:00:00"),
             ("all_final_time", "999:99:00:00"),
             ("all_timestep", "300.0"),
+            ("all_command_line_arguments", ""),
         ]
 
         return lst
@@ -153,6 +154,17 @@ class AbstractSolver(object):
     def export(self, study, repertory, qlog = None):
         raise NotImplementedMethodeError(self, self.export)
 
+    def cmd_args(self, study):
+        """Return solver command line arguments list
+
+        Returns:
+            Command line arguments list
+        """
+        params = study.river.get_params(self.type)
+        args = params.get_by_key("all_command_line_arguments")
+
+        return args.split(" ")
+
     def input_param(self):
         """Return input command line parameter(s)
 
@@ -190,7 +202,7 @@ class AbstractSolver(object):
             )
         )
 
-    def _format_command(self, cmd, path = ""):
+    def _format_command(self, study, cmd, path = ""):
         """Format command line
 
         Args:
@@ -206,6 +218,7 @@ class AbstractSolver(object):
         cmd = cmd.replace("@path", path.replace(" ", "\ "))
         cmd = cmd.replace("@input", self.input_param())
         cmd = cmd.replace("@dir", self._process.workingDirectory())
+        cmd = cmd.replace("@args", " ".join(self.cmd_args(study)))
 
         logger.debug(f"! {cmd}")
 
@@ -213,23 +226,33 @@ class AbstractSolver(object):
             # Command line executable path is between " char
             cmd = cmd.split("\"")
             exe = cmd[1].replace("\ ", " ")
-            args = "\"".join(cmd[2:]).split(" ")[1:]
+            args = list(
+                filter(
+                    lambda s: s != "",
+                    "\"".join(cmd[2:]).split(" ")[1:]
+                )
+            )
         else:
             # We suppose the command line executable path as no space char
             cmd = cmd.replace("\ ", "&_&").split(" ")
             exe = cmd[0].replace("&_&", " ")
-            args = list(map(lambda s: s.replace("&_&", "\ "), cmd[1:]))
+            args = list(
+                filter(
+                    lambda s: s != "",
+                    map(lambda s: s.replace("&_&", "\ "), cmd[1:])
+                )
+            )
 
         logger.info(f"! {exe} {args}")
         return exe, args
 
-    def run_input_data_fomater(self):
+    def run_input_data_fomater(self, study):
         if self._cmd_input == "":
-            self._run_next()
+            self._run_next(study)
             return True
 
         cmd = self._cmd_input
-        exe, args = self._format_command(cmd, self._path_input)
+        exe, args = self._format_command(study, cmd, self._path_input)
 
         if not os.path.exists(exe):
             error = f"[ERROR] Path {exe} do not exists"
@@ -242,13 +265,13 @@ class AbstractSolver(object):
 
         return True
 
-    def run_solver(self):
+    def run_solver(self, study):
         if self._cmd_solver == "":
-            self._run_next()
+            self._run_next(study)
             return True
 
         cmd = self._cmd_solver
-        exe, args = self._format_command(cmd, self._path_solver)
+        exe, args = self._format_command(study, cmd, self._path_solver)
 
         if not os.path.exists(exe):
             error = f"[ERROR] Path {exe} do not exists"
@@ -262,13 +285,13 @@ class AbstractSolver(object):
         self._status = STATUS.RUNNING
         return True
 
-    def run_output_data_fomater(self):
+    def run_output_data_fomater(self, study):
         if self._cmd_output == "":
-            self._run_next()
+            self._run_next(study)
             return True
 
         cmd = self._cmd_output
-        exe, args = self._format_command(cmd, self._path_output)
+        exe, args = self._format_command(study, cmd, self._path_output)
 
         if not os.path.exists(exe):
             error = f"[ERROR] Path {exe} do not exists"
@@ -287,29 +310,29 @@ class AbstractSolver(object):
             for x in s.split('\n'):
                 self._output.put(x)
 
-    def _run_next(self):
+    def _run_next(self, study):
         self._step += 1
         if self._step < len(self._runs):
-            res = self._runs[self._step]()
+            res = self._runs[self._step](study)
             if res is not True:
                 self._output.put(res)
         else:
             self._status = STATUS.STOPED
 
-    def _finished(self, exit_code, exit_status):
+    def _finished(self, study, exit_code, exit_status):
         if self._output is not None:
             self._output.put(exit_code)
 
-        self._run_next()
+        self._run_next(study)
 
-    def run(self, process = None, output_queue = None):
+    def run(self, study, process = None, output_queue = None):
         if process is not None:
             self._process = process
         if output_queue is not None:
             self._output = output_queue
 
         self._process.readyRead.connect(self._data_ready)
-        self._process.finished.connect(self._finished)
+        self._process.finished.connect(lambda c, s: self._finished(study, c, s))
 
         self._runs = [
             self.run_input_data_fomater,
@@ -318,7 +341,7 @@ class AbstractSolver(object):
         ]
         self._step = 0
         # Run first step
-        res = self._runs[0]()
+        res = self._runs[0](study)
         if res is not True:
             self._output.put(res)
 
@@ -330,14 +353,14 @@ class AbstractSolver(object):
         self._status = STATUS.STOPED
         return True
 
-    def start(self, process = None):
+    def start(self, study, process = None):
         if _signal:
             if self._status == STATUS.PAUSED:
                 os.kill(self._process.pid(), SIGCONT)
                 self._status = STATUS.RUNNING
                 return True
 
-        self.run(process)
+        self.run(study, process)
         return True
 
     def pause(self):
diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py
index 6c129f887d717a19d0b88b06fca112451143b7ad..aa68802f1a96868104214559faeefeb2553c9927 100644
--- a/src/Solver/Mage.py
+++ b/src/Solver/Mage.py
@@ -61,11 +61,11 @@ class Mage(AbstractSolver):
             ("mage_timestep_tra", "3600"),
             ("mage_timestep_bin", "0"),
             # ("mage_timestep_melissa", "0"),
-            ("mage_implication", "0.70"),
+            ("mage_implicitation", "0.70"),
             ("mage_continuity_discretization", "S"),
             ("mage_qsj_discretization", "B"),
             ("mage_stop_criterion_iterations", "R"),
-            ("mage_iter_type", "0"),
+            ("mage_iteration_type", "0"),
             ("mage_smooth_coef", "0"),
             ("mage_cfl_max", "-1."),
             ("mage_min_height", "0.1"),
@@ -97,6 +97,13 @@ class Mage(AbstractSolver):
     # Export #
     ##########
 
+    def cmd_args(self, study):
+        l = super(Mage, self).cmd_args(study)
+
+        l.append("-r")
+
+        return l
+
     def input_param(self):
         return "0.REP"
 
@@ -127,23 +134,47 @@ class Mage(AbstractSolver):
             with mage_file_open(os.path.join(repertory, f"{name}.ST"), "w+") as f:
                 files.append(f"{name}.ST")
 
+                cnt_num = 1
                 for profile in edge.reach.profiles:
-                    num = f"{profile.num:>6}"
+                    num = f"{cnt_num:>6}"
                     c1 = f"{profile.code1:>6}"
                     c2 = f"{profile.code2:>6}"
                     t = f"{len(profile.points):>6}"
                     kp = f"{profile.kp:>13.4f}"
-                    name = profile.name
+                    pname = profile.name
+                    if profile.name == "":
+                        pname = f"p{profile.id:>3}".replace(" ", "p")
+                    name = f"{pname}"
+
+                    sediment = ""
+                    if profile.sl is not None:
+                        if not any(filter(lambda f: ".GRA" in f, files)):
+                            files.append("0.GRA")
+
+                        nl = len(profile.sl)
+                        sediment = f" {nl:>3}"
+                        for l in profile.sl.layers:
+                            sediment += f" {l.height:>10} {l.d50:>10} {l.sigma:>10} {l.critical_constraint:>10}"
 
-                    f.write(f"{num}{c1}{c2}{t}{kp}  {name}\n")
+                    f.write(f"{num}{c1}{c2}{t}{kp}  {name} {sediment}\n")
+                    cnt_num += 1
 
                     for point in profile.points:
                         x = f"{point.x:>13.4f}"
                         y = f"{point.y:>13.4f}"
                         z = f"{point.z:>13.4f}"
-                        n = point.name
+                        n = f"{point.name:<3}"
 
-                        f.write(f"{x}{y}{z} {n}\n")
+                        sediment = ""
+                        prev = point.z
+                        if point.sl is not None:
+                            nl = len(point.sl)
+                            sediment = f"{nl:>3}"
+                            for l in point.sl.layers:
+                                prev = round(prev - l.height, 5)
+                                sediment += f" {prev:>10} {l.d50:>10} {l.sigma:>10} {l.critical_constraint:>10}"
+
+                        f.write(f"{x}{y}{z} {n} {sediment}\n")
 
                     f.write(f"     999.9990     999.9990     999.9990\n")
 
@@ -170,7 +201,7 @@ class Mage(AbstractSolver):
                 f.write(f"*{header[0]:>9}|{header[1]:>10}\n")
 
                 for d in bound.data:
-                    f.write(f"{d[0]:10.3f}{d[1]:10.3f}\n")
+                    f.write(f"{d[0]:10}{d[1]:10}\n")
 
         return files
 
@@ -182,6 +213,7 @@ class Mage(AbstractSolver):
         AVA = []
         HYD = []
         LIM = []
+        QSO = []
 
         for tab in ["liquid", "solid", "suspenssion"]:
             for bound in lst.get_tab(tab):
@@ -191,10 +223,13 @@ class Mage(AbstractSolver):
                     HYD.append(bound)
                 elif bound.bctype == "TZ":
                     LIM.append(bound)
+                elif bound.bctype == "SL":
+                    QSO.append(bound)
 
         files = files + self._export_BC("AVA", AVA, repertory,  qlog)
         files = files + self._export_BC("HYD", HYD, repertory,  qlog)
         files = files + self._export_BC("LIM", LIM, repertory,  qlog)
+        files = files + self._export_QSO(QSO, repertory,  qlog)
 
         return files
 
@@ -332,12 +367,20 @@ class Mage(AbstractSolver):
             for file in files:
                 EXT = file.split('.')[1]
 
-                f.write(f"{EXT} {file}\n")
+                if EXT not in ["ST", "GRA"]:
+                    f.write(f"{EXT} {file}\n")
 
             f.write("* OUTPUT\n")
             f.write(f"TRA 0.TRA\n")
             f.write(f"BIN 0.BIN\n")
 
+            for file in files:
+                EXT = file.split('.')[1]
+
+                if EXT in ["GRA"]:
+                    f.write(f"{EXT} {file}\n")
+
+
     @timer
     def export(self, study, repertory, qlog = None):
         self._export_ST(study, repertory, qlog)
@@ -404,6 +447,14 @@ class Mage8(Mage):
     # Export #
     ##########
 
+    def cmd_args(self, study):
+        l = super(Mage8, self).cmd_args(study)
+
+        if study.river.has_sediment():
+            l.append("-c=3")
+
+        return l
+
     @timer
     def _export_PAR(self, study, repertory, qlog = None):
         files = []
@@ -423,7 +474,6 @@ class Mage8(Mage):
 
                 f.write(f"{name} {value}\n")
 
-
         return files
 
     @timer
@@ -459,11 +509,37 @@ class Mage8(Mage):
 
         return files
 
+    @timer
+    def _export_QSO(self, bounds, repertory, qlog):
+        files = []
+
+        if len(bounds) == 0:
+            return files
+
+        if qlog is not None:
+            qlog.put(f"Export QSO file")
+
+        with mage_file_open(os.path.join(repertory, f"0.QSO"), "w+") as f:
+            files.append(f"0.QSO")
+
+            for bound in bounds:
+                name = f"{bound.node.id:3}".replace(" ", "x")
+                f.write(f"* {bound.node.name} ({name}) {bound.bctype}\n")
+                f.write(f"${name}\n")
+                header = bound.header
+                f.write(f"*{header[0]:>9}|{header[1]:>10}\n")
+
+                for d in bound.data:
+                    f.write(f"{d[0]:10.3f}{d[1]:10.3f}\n")
+
+        return files
+
+
     @timer
     def export(self, study, repertory, qlog = None):
         files = []
 
-        self._export_ST(study, repertory, qlog)
+        files = self._export_ST(study, repertory, qlog)
         files = files + self._export_PAR(study, repertory, qlog)
         files = files + self._export_NET(study, repertory, qlog)
         files = files + self._export_bound_cond(study, repertory, qlog)
@@ -477,6 +553,7 @@ class Mage8(Mage):
     # RESULTS #
     ###########
 
+    @timer
     def read_bin(self, study, repertory, results, qlog = None):
         logger.info(f"read_bin: Start ...")
 
@@ -597,3 +674,162 @@ class Mage8(Mage):
             logger.debug(reachs[0].profiles[0]._data)
             results.set("timestamps", ts)
             logger.info(f"read_bin: ... end with {len(ts)} timestamp read")
+
+    @timer
+    def read_gra(self, study, repertory, results, qlog = None):
+        if not study.river.has_sediment():
+            return
+
+        logger.info(f"read_gra: Start ...")
+
+        with mage_file_open(os.path.join(repertory, f"0.GRA"), "r") as f:
+            newline = lambda: np.fromfile(f, dtype=np.int32, count=1)
+            endline = lambda: np.fromfile(f, dtype=np.int32, count=1)
+
+            read_int = lambda size: np.fromfile(f, dtype=np.int32, count=size)
+            read_float = lambda size: np.fromfile(f, dtype=np.float32, count=size)
+            read_float64 = lambda size: np.fromfile(f, dtype=np.float64, count=size)
+
+            # Meta data (1st line)
+            newline()
+
+            data = read_int(3)
+
+            nb_reach = data[0]
+            nb_profile = data[1]
+            mage_version = data[2]
+
+            logger.debug(f"read_gra: nb_reach = {nb_reach}")
+            logger.debug(f"read_gra: nb_profile = {nb_profile}")
+            logger.debug(f"read_gra: mage_version = {mage_version}")
+
+            if mage_version <= 80:
+                msg = (
+                    "Read GRA files: " +
+                    f"Possible incompatible mage version '{mage_version}', " +
+                    "please check your solver configuration..."
+                )
+                logger.warning(msg)
+
+                if qlog is not None:
+                    qlog.put("[WARNING] " + msg)
+
+            results.set("gra_solver_version", f"Mage8 ({mage_version})")
+            results.set("gra_nb_reach", f"{nb_reach}")
+            results.set("gra_nb_profile", f"{nb_profile}")
+
+            endline()
+
+            # Reach information (2nd line)
+            newline()
+
+            reachs = []
+            iprofiles = {}
+            reach_offset = {}
+
+            data = read_int(2*nb_reach)
+
+            for i in range(nb_reach):
+                # Get results reach to reach list
+                r = results.river.reach(i)
+                reachs.append(r)
+
+                # ID of first and last reach profiles
+                i1 = data[2*i] - 1
+                i2 = data[2*i+1] - 1
+
+                # Add profile id correspondance to reach
+                key = (i1, i2)
+                iprofiles[key] = r
+
+                # Profile ID offset
+                reach_offset[r] = i1
+
+            logger.debug(f"read_gra: iprofiles = {iprofiles}")
+
+            endline()
+
+            # X (3rd line)
+            newline()
+            _ = read_float(nb_profile)
+            endline()
+
+            # npts (4th line)
+            newline()
+            _ = read_int(nb_profile)
+            endline()
+
+            # Data
+            ip_to_r = lambda i: iprofiles[
+                next(
+                    filter(
+                        lambda k: k[0] <= i <= k[1],
+                        iprofiles
+                    )
+                )
+            ]
+            ip_to_ri = lambda r, i: i - reach_offset[r]
+
+            ts = set()
+            ind = 0
+            end = False
+
+            newline()
+            while not end:
+                n = read_int(1)[0]
+                timestamp = read_float64(1)[0]
+
+                logger.debug(f"read_gra: timestamp = {timestamp} sec")
+                ts.add(timestamp)
+
+                endline()
+
+                for i in range(n):
+                    newline()
+                    nsl = read_int(1)[0]
+                    endline()
+
+                    # Get current profile id
+                    reach = ip_to_r(i)
+                    ri = ip_to_ri(reach, i)
+
+                    if nsl > 1:
+                        logger.warning(
+                            "read_gra: " +
+                            "Multiple sediment layers for one profile " +
+                            "is not implemented yet..."
+                        )
+
+                    for j in range(nsl):
+                        newline()
+                        nl = read_int(1)[0]
+                        endline()
+
+                        sl = []
+
+                        for k in range(nl):
+                            newline()
+                            data = read_float64(3)
+                            endline()
+
+                            h = data[0]
+                            d50 = data[1]
+                            sigma = data[2]
+
+                            sl.append((h, d50, sigma))
+
+                        reach.set(ri, timestamp, "sl", sl)
+
+                ind += 1
+                end = newline().size <= 0
+
+            logger.debug(reachs[0].profiles[0]._data)
+            results.set("timestamps", ts)
+            logger.info(f"read_gra: ... end with {len(ts)} timestamp read")
+
+    @timer
+    def results(self, study, repertory, qlog = None):
+        results = super(Mage8, self).results(study, repertory, qlog)
+        self.read_gra(study, repertory, results, qlog)
+
+        return results
diff --git a/src/View/BoundaryCondition/Edit/translate.py b/src/View/BoundaryCondition/Edit/translate.py
index 4c09f5fce4e24180390dfca3cd9d7d6bb46ac5e4..c803979592e1baa36c2e9981b83ec6dab3e6f2f3 100644
--- a/src/View/BoundaryCondition/Edit/translate.py
+++ b/src/View/BoundaryCondition/Edit/translate.py
@@ -26,5 +26,6 @@ table_headers = {
     "time": _translate("BoundaryCondition", "Time"),
     "date": _translate("BoundaryCondition", "Date"),
     "discharge": _translate("BoundaryCondition", "Discharge (m³/s)"),
-    "z": _translate("BoundaryCondition", "Z (m)")
+    "z": _translate("BoundaryCondition", "Z (m)"),
+    "solid": _translate("BoundaryCondition", "Solid (kg/s)"),
 }
diff --git a/src/View/BoundaryCondition/translate.py b/src/View/BoundaryCondition/translate.py
index 661c1ad071a4a475ab3783a53b4474c3b0e0e2f1..c4ff8f8815e620d75bbde9030d82224c43acb160 100644
--- a/src/View/BoundaryCondition/translate.py
+++ b/src/View/BoundaryCondition/translate.py
@@ -20,7 +20,8 @@ from PyQt5.QtCore import QCoreApplication
 
 from Model.BoundaryCondition.BoundaryConditionTypes import (
     NotDefined, PonctualContribution,
-    TimeOverZ, TimeOverDischarge, ZOverDischarge
+    TimeOverZ, TimeOverDischarge, ZOverDischarge,
+    Solid
 )
 
 _translate = QCoreApplication.translate
@@ -31,6 +32,7 @@ long_types = {
     "TZ": _translate("BoundaryCondition", "Time over Z"),
     "TD": _translate("BoundaryCondition", "Time over Discharge"),
     "ZD": _translate("BoundaryCondition", "Z over Discharge"),
+    "SL": _translate("BoundaryCondition", "Solid"),
 }
 
 table_headers = {
@@ -44,5 +46,6 @@ BC_types = {
     "PC": PonctualContribution,
     "TZ": TimeOverZ,
     "TD": TimeOverDischarge,
-    "ZD": ZOverDischarge
+    "ZD": ZOverDischarge,
+    "SL": Solid,
 }
diff --git a/src/View/Frictions/Window.py b/src/View/Frictions/Window.py
index 81049593c6d8d2c86f6fa80fc84d364ad109ab34..4af3b66c11643f034912b66fbce44bfba56b181b 100644
--- a/src/View/Frictions/Window.py
+++ b/src/View/Frictions/Window.py
@@ -49,7 +49,7 @@ from View.Frictions.Table import (
 )
 
 from View.Plot.MplCanvas import MplCanvas
-from View.Geometry.PlotKPC import PlotKPC
+from View.Geometry.PlotKPZ import PlotKPZ
 from View.Frictions.PlotStricklers import PlotStricklers
 from View.Frictions.translate import *
 
@@ -128,7 +128,7 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
         self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
         self.plot_layout.addWidget(self.canvas)
 
-        self.plot = PlotKPC(
+        self.plot = PlotKPZ(
             canvas = self.canvas,
             data = self._reach.reach,
             toolbar = None,
@@ -193,7 +193,7 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
             sec = self._frictions.get(rows[0])
             highlight = (sec.begin_kp, sec.end_kp)
 
-        self.plot = PlotKPC(
+        self.plot = PlotKPZ(
             canvas = self.canvas,
             data = reach,
             toolbar = None,
diff --git a/src/View/Geometry/PlotKPC.py b/src/View/Geometry/PlotKPZ.py
similarity index 97%
rename from src/View/Geometry/PlotKPC.py
rename to src/View/Geometry/PlotKPZ.py
index 7fb31dae60971b3e108413e3aa2bb5fabfc75378..eb7d5e28b8660bf62ef11874522ad3c646290784 100644
--- a/src/View/Geometry/PlotKPC.py
+++ b/src/View/Geometry/PlotKPZ.py
@@ -29,10 +29,10 @@ _translate = QCoreApplication.translate
 
 logger = logging.getLogger()
 
-class PlotKPC(APlot):
+class PlotKPZ(APlot):
     def __init__(self, canvas=None, data=None, toolbar=None,
                  display_current=True):
-        super(PlotKPC, self).__init__(
+        super(PlotKPZ, self).__init__(
             canvas=canvas,
             data=data,
             toolbar=toolbar
@@ -64,7 +64,7 @@ class PlotKPC(APlot):
             color='green', fontsize=12
         )
         self.canvas.axes.set_ylabel(
-            _translate("MainWindow_reach", "Cote (m)"),
+            _translate("MainWindow_reach", "Height (m)"),
             color='green', fontsize=12
         )
 
@@ -234,7 +234,7 @@ class PlotKPC(APlot):
                         kp, z_complete[i]
                     )
             except Exception as e:
-                logger.warning(f"Failed to update graphic KPC: {e}")
+                logger.warning(f"Failed to update graphic KPZ: {e}")
 
             self.canvas.axes.autoscale_view(True, True, True)
             self.canvas.figure.canvas.draw_idle()
diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py
index e33b6d5404a567346f0dcb2cf6734dd97f2501b2..7776d737389c564c89b4bb752cb0dfc600ddc7b8 100644
--- a/src/View/Geometry/Window.py
+++ b/src/View/Geometry/Window.py
@@ -38,7 +38,7 @@ from PyQt5.QtWidgets import (
 )
 
 from View.Geometry.PlotXY import PlotXY
-from View.Geometry.PlotKPC import PlotKPC
+from View.Geometry.PlotKPZ import PlotKPZ
 from View.Geometry.PlotAC import PlotAC
 
 from View.ASubWindow import ASubMainWindow, WindowToolKit
@@ -230,7 +230,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
     def plot_kpc(self):
         self.tableView.model().blockSignals(True)
 
-        self._plot_kpc = PlotKPC(
+        self._plot_kpc = PlotKPZ(
             canvas = self.ui.canvas_2,
             data = self._reach,
             toolbar = self.ui.toolbar_2
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index 559601c26cd8a9979504b06581f8658b188012f6..2fc14efab43d6c6622282b8a28f585e1619272aa 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -18,6 +18,7 @@
 
 import os
 import logging
+import subprocess
 from queue import Queue
 
 from PyQt5 import QtGui
@@ -49,6 +50,8 @@ from View.LateralContribution.Window import LateralContributionWindow
 from View.InitialConditions.Window import InitialConditionsWindow
 from View.Stricklers.Window import StricklersWindow
 from View.Frictions.Window import FrictionsWindow
+from View.SedimentLayers.Window import SedimentLayersWindow
+from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
 from View.SolverParameters.Window import SolverParametersWindow
 from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
 from View.CheckList.Window import CheckListWindow
@@ -87,7 +90,8 @@ define_model_action = [
     "action_menu_edit_network", "action_menu_edit_geometry",
     "action_menu_boundary_conditions", "action_menu_initial_conditions",
     "action_menu_edit_friction", "action_menu_edit_lateral_contribution",
-    "action_menu_run_solver",
+    "action_menu_run_solver", "action_menu_sediment_layers",
+    "action_menu_edit_reach_sediment_layers"
 ]
 
 action = (
@@ -170,6 +174,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
             "action_menu_edit_friction": self.open_frictions,
             "action_menu_edit_lateral_contribution": self.open_lateral_contrib,
             "action_menu_run_solver": self.run_solver,
+            "action_menu_sediment_layers": self.open_sediment_layers,
+            "action_menu_edit_reach_sediment_layers": self.open_reach_sediment_layers,
             ## Help
             "action_menu_about": self.open_about,
             # ToolBar action
@@ -258,15 +264,22 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
             self.debug_action.setStatusTip("Debug")
             self.debug_action.triggered.connect(self.open_debug)
 
+            self.debug_sqlite_action = QAction("Debug SQLite", self)
+            self.debug_sqlite_action.setStatusTip("Open SQLite debuging tool (sqlitebrowser)")
+            self.debug_sqlite_action.triggered.connect(self.open_sqlite)
+
             if self.conf.debug:
                 menu.addAction(self.debug_action)
+                menu.addAction(self.debug_sqlite_action)
                 self.set_debug_lvl(debug = True)
         else:
             if self.conf.debug:
                 menu.addAction(self.debug_action)
+                menu.addAction(self.debug_sqlite_action)
                 self.set_debug_lvl(debug = True)
             else:
                 menu.removeAction(self.debug_action)
+                menu.removeAction(self.debug_sqlite_action)
                 self.set_debug_lvl(debug = False)
 
     #########
@@ -617,6 +630,20 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
         else:
             params.activateWindow()
 
+    def open_sediment_layers(self):
+        sl = SedimentLayersWindow(
+            study = self.model,
+            parent = self
+        )
+        sl.show()
+
+    def open_reach_sediment_layers(self):
+        sl = ReachSedimentLayersWindow(
+            study = self.model,
+            parent = self
+        )
+        sl.show()
+
     def run_solver(self):
         if self.model is None:
             return
@@ -683,6 +710,17 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
         )
         repl.show()
 
+    def open_sqlite(self):
+        if self.model is None:
+            logger.debug("No study open for sql debuging...")
+            return
+
+        file = self.model.filename
+        _ = subprocess.Popen(
+            f"sqlitebrowser {file}",
+            shell=True
+        )
+
     # TODO: Delete me !
     ###############
     # DUMMY STUFF #
diff --git a/src/View/Results/PlotH.py b/src/View/Results/PlotH.py
index dcc9f7f6c3fdd6e2c11943e004e17e6ec38c1dd8..47c3f1bf48d89a56e3bb69d83ead4332e19bc905 100644
--- a/src/View/Results/PlotH.py
+++ b/src/View/Results/PlotH.py
@@ -19,6 +19,7 @@
 import logging
 
 from functools import reduce
+from datetime import datetime
 
 from tools import timer, trace
 from View.Plot.APlot import APlot
@@ -34,14 +35,14 @@ logger = logging.getLogger()
 class PlotH(APlot):
     def __init__(self, canvas=None, results=None,
                  reach_id=0, profile_id=0,
-                 toolbar=None, display_current=True):
+                 toolbar=None):
         super(PlotH, self).__init__(
             canvas=canvas,
             data=results,
             toolbar=toolbar
         )
 
-        self.display_current = display_current
+        self._mode = "time"
 
         self._current_timestamp = max(results.get("timestamps"))
         self._current_reach_id = reach_id
@@ -99,6 +100,10 @@ class PlotH(APlot):
             )
             return
 
+        self.canvas.axes.set_ylim(
+            [min(min(y),0), max(y)]
+        )
+
         self._line = [
             self.canvas.axes.plot(
                 x, y, lw=1.,
@@ -107,8 +112,47 @@ class PlotH(APlot):
             )
         ]
 
-        self.canvas.axes.autoscale_view(True, True, True)
-        self.canvas.axes.autoscale()
+        # Custom time display
+        nb = len(x)
+        mod = int(nb / 5)
+        mod = mod if mod > 0 else nb
+
+        fx = list(
+            map(
+                lambda x: x[1],
+                filter(
+                    lambda x: x[0] % mod == 0,
+                    enumerate(x)
+                )
+            )
+        )
+
+        if self._mode == "time":
+            t0 = datetime.fromtimestamp(0)
+            xt = list(
+                map(
+                    lambda v: (
+                        str(
+                            datetime.fromtimestamp(v) - t0
+                        ).split(",")[0]\
+                        .replace("days", _translate("Results", "days"))\
+                        .replace("day", _translate("Results", "day"))
+                    ),
+                    fx
+                )
+            )
+        else:
+            xt = list(
+                map(
+                    lambda v: str(datetime.fromtimestamp(v).date()),
+                    fx
+                )
+            )
+
+        self.canvas.axes.set_xticks(ticks=fx, labels=xt, rotation=45)
+
+        # self.canvas.axes.autoscale_view(True, True, True)
+        # self.canvas.axes.autoscale()
         self.canvas.figure.tight_layout()
         self.canvas.figure.canvas.draw_idle()
         if self.toolbar is not None:
diff --git a/src/View/Results/PlotSedProfile.py b/src/View/Results/PlotSedProfile.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b34bb1e2e87fa5eddf0e59b5e12eec9ddd238af
--- /dev/null
+++ b/src/View/Results/PlotSedProfile.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from functools import reduce
+
+from tools import timer
+from View.Plot.APlot import APlot
+
+from PyQt5.QtCore import (
+    QCoreApplication
+)
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class PlotSedProfile(APlot):
+    def __init__(self, canvas=None, study=None, results=None,
+                 reach_id=0, profile_id=0,
+                 toolbar=None):
+        super(PlotSedProfile, self).__init__(
+            canvas=canvas,
+            data=study,
+            toolbar=toolbar
+        )
+
+        self._results = results
+
+        self._current_timestamp = max(results.get("timestamps"))
+        self._current_reach_id = reach_id
+        self._current_profile_id = profile_id
+
+    @timer
+    def draw(self):
+        self.canvas.axes.cla()
+        self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+
+        if self.data is None:
+            return
+
+        reach = self._results.river.reach(self._current_reach_id)
+        profile = reach.profile(self._current_profile_id)
+        if profile.geometry.number_points == 0:
+            return
+
+        self.canvas.axes.set_xlabel(
+            _translate("MainWindow_reach", "X (m)"),
+            color='green', fontsize=12
+        )
+        self.canvas.axes.set_ylabel(
+            _translate("MainWindow_reach", "Height (m)"),
+            color='green', fontsize=12
+        )
+
+        x = profile.geometry.get_station()
+        z = profile.geometry.z()
+
+        psl = list(
+            map(
+                lambda sl: sl[0],
+                profile.get_ts_key(self._current_timestamp, "sl")
+            )
+        )
+
+        sl = []
+        for i in range(len(psl)):
+            cur = []
+            for p in range(profile.geometry.number_points):
+                    cur.append(psl[i])
+            sl.append(cur)
+
+        # logger.info(sl)
+
+        self.canvas.axes.set_xlim(
+            left = min(x), right = max(x)
+        )
+
+        # Compute sediment layer in function to point z
+        z_sl = reduce(
+            lambda acc, v: acc + [
+                list(
+                    map(lambda x, y: y - x, v, acc[-1])
+                )
+            ],
+            sl,
+            [z]
+        )
+
+        self.line_kp_sl = []
+        for i, zsl in enumerate(reversed(z_sl)):
+            self.line_kp_sl.append(None)
+            self.line_kp_sl[i], = self.canvas.axes.plot(
+                x, zsl,
+                linestyle="solid" if i == len(z_sl) - 1 else "--",
+                lw=1.8,
+                color='grey' if i == len(z_sl) - 1 else None
+            )
+
+        self.canvas.figure.tight_layout()
+        self.canvas.figure.canvas.draw_idle()
+        if self.toolbar is not None:
+            self.toolbar.update()
+
+        self._init = False
+
+    @timer
+    def update(self, ind=None):
+        if self._init == False:
+            self.draw()
+            return
+
+        if ind is None:
+            logger.info("TODO: Update")
+
+            self.canvas.axes.autoscale_view(True, True, True)
+            self.canvas.figure.canvas.draw_idle()
+
+    def set_reach(self, reach_id):
+        self._current_reach_id = reach_id
+        self._current_profile_id = 0
+        self.draw()
+
+    def set_profile(self, profile_id):
+        self._current_profile_id = profile_id
+        self.draw()
+
+    def set_timestamp(self, timestamp):
+        self._current_timestamp = timestamp
+        self.draw()
diff --git a/src/View/Results/PlotSedReach.py b/src/View/Results/PlotSedReach.py
new file mode 100644
index 0000000000000000000000000000000000000000..892120c60c96a742be65ec0f1edd52179ac881bd
--- /dev/null
+++ b/src/View/Results/PlotSedReach.py
@@ -0,0 +1,134 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from functools import reduce
+
+from tools import timer
+from View.Plot.APlot import APlot
+
+from PyQt5.QtCore import (
+    QCoreApplication
+)
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class PlotSedReach(APlot):
+    def __init__(self, canvas=None, study=None, results=None,
+                 reach_id=0, profile_id=0,
+                 toolbar=None):
+        super(PlotSedReach, self).__init__(
+            canvas=canvas,
+            data=study,
+            toolbar=toolbar
+        )
+
+        self._results = results
+
+        self._current_timestamp = max(results.get("timestamps"))
+        self._current_reach_id = reach_id
+        self._current_profile_id = profile_id
+
+    @timer
+    def draw(self):
+        self.canvas.axes.cla()
+        self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+
+        if self.data is None:
+            return
+
+        reach = self._results.river.reach(self._current_reach_id)
+        if reach.geometry.number_profiles == 0:
+            return
+
+        self.canvas.axes.set_xlabel(
+            _translate("MainWindow_reach", "Kp (m)"),
+            color='green', fontsize=12
+        )
+        self.canvas.axes.set_ylabel(
+            _translate("MainWindow_reach", "Height (m)"),
+            color='green', fontsize=12
+        )
+
+        kp = reach.geometry.get_kp()
+        z_min = reach.geometry.get_z_min()
+        z_max = reach.geometry.get_z_max()
+
+        psl = list(
+            map(
+                # Get SL list for profile p
+                lambda p: p.get_ts_key(self._current_timestamp, "sl"),
+                reach.profiles
+            )
+        )
+
+        max_sl = reduce(
+            lambda acc, sl: max(acc, len(sl)),
+            psl,
+            0
+        )
+
+        sl = []
+        for i in range(max_sl):
+            cur = []
+            for csl in psl:
+                if i < len(csl):
+                    cur.append(csl[i][0])
+                else:
+                    cur.append(0)
+            sl.append(cur)
+
+        # logger.info(f"sl = {sl}")
+
+        self.canvas.axes.set_xlim(
+            left = min(kp), right = max(kp)
+        )
+
+        # Compute sediment layer in function to profile z_min
+        z_sl = reduce(
+            lambda acc, v: acc + [
+                list(
+                    map(lambda x, y: y - x, v, acc[-1])
+                )
+            ],
+            sl,
+            [z_min]
+        )
+
+        self.line_kp_sl = []
+        for i, z in enumerate(reversed(z_sl)):
+            self.line_kp_sl.append(None)
+            self.line_kp_sl[i], = self.canvas.axes.plot(
+                kp, z,
+                linestyle="solid" if i == len(z_sl) - 1 else "--",
+                lw=1.8,
+                color='grey' if i == len(z_sl) - 1 else None
+            )
+
+        self.canvas.figure.tight_layout()
+        self.canvas.figure.canvas.draw_idle()
+        if self.toolbar is not None:
+            self.toolbar.update()
+
+        self._init = False
+
+    @timer
+    def update(self, ind=None):
+        if self._init == False:
+            self.draw()
+            return
+
+    def set_reach(self, reach_id):
+        self._current_reach_id = reach_id
+        self._current_profile_id = 0
+        self.draw()
+
+    def set_profile(self, profile_id):
+        self._current_profile_id = profile_id
+        self.draw()
+
+    def set_timestamp(self, timestamp):
+        self._current_timestamp = timestamp
+        self.draw()
diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py
index 22d0a2c44e4158ebcf92664774483a6f2b88b461..3882a7ba6277dae7028fd1dd592714431b8b9f5e 100644
--- a/src/View/Results/Window.py
+++ b/src/View/Results/Window.py
@@ -46,6 +46,8 @@ from View.Results.PlotXY import PlotXY
 from View.Results.PlotAC import PlotAC
 from View.Results.PlotKPC import PlotKPC
 from View.Results.PlotH import PlotH
+from View.Results.PlotSedReach import PlotSedReach
+from View.Results.PlotSedProfile import PlotSedProfile
 
 from View.Results.Table import TableModel
 from View.Results.translate import *
@@ -180,6 +182,38 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
         )
         self.plot_h.draw()
 
+        self.canvas_5 = MplCanvas(width=5, height=4, dpi=100)
+        self.canvas_5.setObjectName("canvas_5")
+        self.plot_layout_5 = self.find(QVBoxLayout, "verticalLayout_sed_reach")
+        self.plot_layout_5.addWidget(self.canvas_5)
+
+        if self._study.river.has_sediment():
+            self.plot_sed_reach = PlotSedReach(
+                canvas = self.canvas_5,
+                results = self._results,
+                study = self._study,
+                reach_id = 0,
+                profile_id = 0,
+                toolbar = None
+            )
+            self.plot_sed_reach.draw()
+
+        self.canvas_6 = MplCanvas(width=5, height=4, dpi=100)
+        self.canvas_6.setObjectName("canvas_6")
+        self.plot_layout_6 = self.find(QVBoxLayout, "verticalLayout_sed_profile")
+        self.plot_layout_6.addWidget(self.canvas_6)
+
+        if self._study.river.has_sediment():
+            self.plot_sed_profile = PlotSedProfile(
+                canvas = self.canvas_6,
+                results = self._results,
+                study = self._study,
+                reach_id = 0,
+                profile_id = 0,
+                toolbar = None
+            )
+            self.plot_sed_profile.draw()
+
     def setup_connections(self):
         self.undo_sc.activated.connect(self.undo)
         self.redo_sc.activated.connect(self.redo)
@@ -210,22 +244,38 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
             self.plot_ac.set_reach(reach_id)
             self.plot_kpc.set_reach(reach_id)
             self.plot_h.set_reach(reach_id)
+
+            if self._study.river.has_sediment():
+                self.plot_sed_reach.set_reach(reach_id)
+                self.plot_sed_profile.set_reach(reach_id)
         if profile_id is not None:
             self.plot_xy.set_profile(profile_id)
             self.plot_ac.set_profile(profile_id)
             self.plot_kpc.set_profile(profile_id)
             self.plot_h.set_profile(profile_id)
+
+            if self._study.river.has_sediment():
+                self.plot_sed_reach.set_profile(profile_id)
+                self.plot_sed_profile.set_profile(profile_id)
         if timestamp is not None:
             self.plot_xy.set_timestamp(timestamp)
             self.plot_ac.set_timestamp(timestamp)
             self.plot_kpc.set_timestamp(timestamp)
             self.plot_h.set_timestamp(timestamp)
 
+            if self._study.river.has_sediment():
+                self.plot_sed_reach.set_timestamp(timestamp)
+                self.plot_sed_profile.set_timestamp(timestamp)
+
         self.plot_xy.draw()
         self.plot_ac.draw()
         self.plot_kpc.draw()
         self.plot_h.draw()
 
+        if self._study.river.has_sediment():
+            self.plot_sed_reach.draw()
+            self.plot_sed_profile.draw()
+
 
     def _set_current_reach(self):
         table = self.find(QTableView, f"tableView_reach")
diff --git a/src/View/RunSolver/Window.py b/src/View/RunSolver/Window.py
index 872d72ef008dd30db05c20c7ae481c1ddf575f19..c307157af191b3b1d89ad1034098bd1e4b084f52 100644
--- a/src/View/RunSolver/Window.py
+++ b/src/View/RunSolver/Window.py
@@ -147,6 +147,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
 
         self._log(f" *** Run solver {self._solver.name}", color="blue")
         self._solver.run(
+            study,
             process = self._process,
             output_queue = self._output
         )
@@ -220,7 +221,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
 
         self._log(" *** Start", color="blue")
         self._results = None
-        self._solver.start(self._process)
+        self._solver.start(self._study, process = self._process)
 
         self.find(QAction, "action_start").setEnabled(False)
         if _signal:
diff --git a/src/View/SedimentLayers/Edit/Plot.py b/src/View/SedimentLayers/Edit/Plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..e48ec5eb61ea21c32b76cb179754d97c278df00a
--- /dev/null
+++ b/src/View/SedimentLayers/Edit/Plot.py
@@ -0,0 +1,105 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from functools import reduce
+
+from tools import timer
+from View.Plot.APlot import APlot
+
+from PyQt5.QtCore import (
+    QCoreApplication
+)
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class Plot(APlot):
+    def __init__(self, canvas=None, data=None, toolbar=None,
+                 display_current=True):
+        super(Plot, self).__init__(
+            canvas=canvas,
+            data=data,
+            toolbar=toolbar
+        )
+
+        self._display_current = display_current
+
+        self.line_kp_zmin = None
+        self.line_kp_sl = []
+
+    @timer
+    def draw(self):
+        self.canvas.axes.cla()
+        self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+
+        # self.canvas.axes.set_xlabel(
+        #     _translate("MainWindow_reach", "X (m)"),
+        #     color='green', fontsize=12
+        # )
+        self.canvas.axes.axes.get_xaxis().set_visible(False)
+        self.canvas.axes.set_ylabel(
+            _translate("MainWindow_reach", "Height (m)"),
+            color='green', fontsize=12
+        )
+
+        if self.data is None:
+            return
+
+        x = [0,1]
+        z = [0,0]
+        sl = self.data.height()
+        names = ["bottom"] + self.data.names()
+
+        self.canvas.axes.set_xlim(
+            left = min(x), right = max(x)
+        )
+
+        lsl = []
+        for i in range(len(sl)):
+            cur = []
+            for _ in x:
+                cur.append(sl[i])
+            lsl.append(cur)
+
+        # Compute sediment layer in function to point z
+        z_sl = reduce(
+            lambda acc, v: acc + [
+                list(
+                    map(lambda x, y: y - x, v, acc[-1])
+                )
+            ],
+            lsl,
+            [z]
+        )
+
+        for i, zsl in enumerate(reversed(z_sl)):
+            self.line_kp_sl.append(None)
+            self.line_kp_sl[i], = self.canvas.axes.plot(
+                x, zsl,
+                label=names[-(i+1)],
+                linestyle="solid" if i == len(names) - 1 else "--",
+                lw=1.8,
+                color='grey' if i == len(names) - 1 else None
+            )
+            self.canvas.axes.text(x[0] + 0.01, zsl[0] + 0.01, f'{names[-(i+1)]}')
+
+        self.canvas.figure.tight_layout()
+        self.canvas.figure.canvas.draw_idle()
+        if self.toolbar is not None:
+            self.toolbar.update()
+
+        self._init = True
+
+    @timer
+    def update(self, ind=None):
+        if self._init == False:
+            self.draw()
+            return
+
+        if ind is None:
+            logger.info("TODO: Update")
+
+            self.canvas.axes.autoscale_view(True, True, True)
+            self.canvas.figure.canvas.draw_idle()
diff --git a/src/View/SedimentLayers/Edit/Table.py b/src/View/SedimentLayers/Edit/Table.py
new file mode 100644
index 0000000000000000000000000000000000000000..e1a41cb2970ad921f47f5da7f29544f452718213
--- /dev/null
+++ b/src/View/SedimentLayers/Edit/Table.py
@@ -0,0 +1,183 @@
+# -*- coding: utf-8 -*-
+
+from tools import trace, timer
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox,
+)
+
+from View.SedimentLayers.Edit.UndoCommand import *
+from View.SedimentLayers.Edit.translate import *
+
+_translate = QCoreApplication.translate
+
+
+class TableModel(QAbstractTableModel):
+    def __init__(self, study=None, sl=None, undo=None):
+        super(QAbstractTableModel, self).__init__()
+        self._headers = list(table_headers.keys())
+        self._study = study
+        self._undo = undo
+        self._sl = sl
+
+    def flags(self, index):
+        options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+        options |= Qt.ItemIsEditable
+
+        return options
+
+    def rowCount(self, parent):
+        return len(self._sl)
+
+    def columnCount(self, parent):
+        return len(self._headers)
+
+    def data(self, index, role):
+        if role != Qt.ItemDataRole.DisplayRole:
+            return QVariant()
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "name":
+            return self._sl.get(row).name
+        elif self._headers[column] == "type":
+            return self._sl.get(row).type
+        elif self._headers[column] == "height":
+            return self._sl.get(row).height
+        elif self._headers[column] == "d50":
+            return self._sl.get(row).d50
+        elif self._headers[column] == "sigma":
+            return self._sl.get(row).sigma
+        elif self._headers[column] == "critical_constraint":
+            return self._sl.get(row).critical_constraint
+
+        return QVariant()
+
+    def headerData(self, friction, orientation, role):
+        if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
+            return table_headers[self._headers[friction]]
+
+        return QVariant()
+
+    def setData(self, index, value, role=Qt.EditRole):
+        if not index.isValid() or role != Qt.EditRole:
+            return False
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "name":
+            self._undo.push(
+                SetNameCommand(
+                    self._sl, row, value
+                )
+            )
+        if self._headers[column] == "type":
+            self._undo.push(
+                SetTypeCommand(
+                    self._sl, row, value
+                )
+            )
+        if self._headers[column] == "height":
+            self._undo.push(
+                SetHeightCommand(
+                    self._sl, row, value
+                )
+            )
+        if self._headers[column] == "d50":
+            self._undo.push(
+                SetD50Command(
+                    self._sl, row, value
+                )
+            )
+        if self._headers[column] == "sigma":
+            self._undo.push(
+                SetSigmaCommand(
+                    self._sl, row, value
+                )
+            )
+        if self._headers[column] == "critical_constraint":
+            self._undo.push(
+                SetCriticalConstraintCommand(
+                    self._sl, row, value
+                )
+            )
+
+        self.dataChanged.emit(index, index)
+        return True
+
+    def add(self, row, parent=QModelIndex()):
+        self.beginInsertRows(parent, row, row - 1)
+
+        self._undo.push(
+            AddCommand(
+                self._sl, row
+            )
+        )
+
+        self.endInsertRows()
+        self.layoutChanged.emit()
+
+    def delete(self, rows, parent=QModelIndex()):
+        self.beginRemoveRows(parent, rows[0], rows[-1])
+
+        self._undo.push(
+            DelCommand(
+                self._sl, rows
+            )
+        )
+
+        self.endRemoveRows()
+        self.layoutChanged.emit()
+
+    def move_up(self, row, parent=QModelIndex()):
+        if row <= 0:
+            return
+
+        target = row + 2
+
+        self.beginMoveRows(parent, row - 1, row - 1, parent, target)
+
+        self._undo.push(
+            MoveCommand(
+                self._sl, "up", row
+            )
+        )
+
+        self.endMoveRows()
+        self.layoutChanged.emit()
+
+    def move_down(self, row, parent=QModelIndex()):
+        if row + 1 >= len(self._sl):
+            return
+
+        target = row
+
+        self.beginMoveRows(parent, row + 1, row + 1, parent, target)
+
+        self._undo.push(
+            MoveCommand(
+                self._sl, "down", row
+            )
+        )
+
+        self.endMoveRows()
+        self.layoutChanged.emit()
+
+    def undo(self):
+        self._undo.undo()
+        self.layoutChanged.emit()
+
+    def redo(self):
+        self._undo.redo()
+        self.layoutChanged.emit()
diff --git a/src/View/SedimentLayers/Edit/UndoCommand.py b/src/View/SedimentLayers/Edit/UndoCommand.py
new file mode 100644
index 0000000000000000000000000000000000000000..298fa529708b659785d7ac56b0ede3cc98bb80d3
--- /dev/null
+++ b/src/View/SedimentLayers/Edit/UndoCommand.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+
+from copy import deepcopy
+from tools import trace, timer
+
+from PyQt5.QtWidgets import (
+    QMessageBox, QUndoCommand, QUndoStack,
+)
+
+from Model.SedimentLayer.SedimentLayer import SedimentLayer
+from Model.SedimentLayer.SedimentLayerList import SedimentLayerList
+
+class SetNameCommand(QUndoCommand):
+    def __init__(self, sediment_layers, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers = sediment_layers
+        self._index = index
+        self._old = self._sediment_layers.get(self._index).name
+        self._new = new_value
+
+    def undo(self):
+        self._sediment_layers.get(self._index).name = self._old
+
+    def redo(self):
+        self._sediment_layers.get(self._index).name = self._new
+
+class SetTypeCommand(QUndoCommand):
+    def __init__(self, sediment_layers, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers = sediment_layers
+        self._index = index
+        self._old = self._sediment_layers.get(self._index).type
+        self._new = new_value
+
+    def undo(self):
+        self._sediment_layers.get(self._index).type = self._old
+
+    def redo(self):
+        self._sediment_layers.get(self._index).type = self._new
+
+class SetHeightCommand(QUndoCommand):
+    def __init__(self, sediment_layers, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers = sediment_layers
+        self._index = index
+        self._old = self._sediment_layers.get(self._index).height
+        self._new = new_value
+
+    def undo(self):
+        self._sediment_layers.get(self._index).height = self._old
+
+    def redo(self):
+        self._sediment_layers.get(self._index).height = self._new
+
+class SetD50Command(QUndoCommand):
+    def __init__(self, sediment_layers, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers = sediment_layers
+        self._index = index
+        self._old = self._sediment_layers.get(self._index).d50
+        self._new = new_value
+
+    def undo(self):
+        self._sediment_layers.get(self._index).d50 = self._old
+
+    def redo(self):
+        self._sediment_layers.get(self._index).d50 = self._new
+
+class SetSigmaCommand(QUndoCommand):
+    def __init__(self, sediment_layers, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers = sediment_layers
+        self._index = index
+        self._old = self._sediment_layers.get(self._index).sigma
+        self._new = new_value
+
+    def undo(self):
+        self._sediment_layers.get(self._index).sigma = self._old
+
+    def redo(self):
+        self._sediment_layers.get(self._index).sigma = self._new
+
+class SetCriticalConstraintCommand(QUndoCommand):
+    def __init__(self, sediment_layers, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers = sediment_layers
+        self._index = index
+        self._old = self._sediment_layers.get(self._index).critical_constraint
+        self._new = new_value
+
+    def undo(self):
+        self._sediment_layers.get(self._index).critical_constraint = self._old
+
+    def redo(self):
+        self._sediment_layers.get(self._index).critical_constraint = self._new
+
+class AddCommand(QUndoCommand):
+    def __init__(self, sediment_layers, index):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers = sediment_layers
+        self._index = index
+        self._new = None
+
+    def undo(self):
+        self._sediment_layers.delete_i([self._index])
+
+    def redo(self):
+        if self._new is None:
+            self._new = self._sediment_layers.new(self._index)
+        else:
+            self._sediment_layers.insert(self._index, self._new)
+
+class DelCommand(QUndoCommand):
+    def __init__(self, sediment_layers, rows):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers = sediment_layers
+        self._rows = rows
+
+        self._sl_pos = []
+        for row in rows:
+            self._sl_pos.append((row, self._sediment_layers.get(row)))
+        self._sl_pos.sort()
+
+    def undo(self):
+        for row, el in self._sl_pos:
+            self._sediment_layers.insert(row, el)
+
+    def redo(self):
+        self._sediment_layers.delete_i(self._rows)
+
+class MoveCommand(QUndoCommand):
+    def __init__(self, sediment_layers, up, i):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers = sediment_layers
+        self._up = up == "up"
+        self._i = i
+
+    def undo(self):
+        if self._up:
+            self._sediment_layers.move_up(self._i)
+        else:
+            self._sediment_layers.move_down(self._i)
+
+    def redo(self):
+        if self._up:
+            self._sediment_layers.move_up(self._i)
+        else:
+            self._sediment_layers.move_down(self._i)
diff --git a/src/View/SedimentLayers/Edit/Window.py b/src/View/SedimentLayers/Edit/Window.py
new file mode 100644
index 0000000000000000000000000000000000000000..965895d24c176f76d42a78b02041560b85ab0681
--- /dev/null
+++ b/src/View/SedimentLayers/Edit/Window.py
@@ -0,0 +1,170 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from tools import trace, timer
+
+from View.ASubWindow import ASubMainWindow
+from View.ListedSubWindow import ListedSubWindow
+
+from PyQt5.QtGui import (
+    QKeySequence,
+)
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
+)
+
+from View.Plot.MplCanvas import MplCanvas
+
+from View.SedimentLayers.Edit.UndoCommand import *
+from View.SedimentLayers.Edit.Table import *
+from View.SedimentLayers.Edit.Plot import Plot
+from View.SedimentLayers.Edit.translate import *
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class EditSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
+    def __init__(self, title="Edit Sediment Layers",
+                 study=None, sl=None, parent=None):
+        self._study = study
+        self._sl = sl
+
+        self.setup_title(title)
+
+        super(EditSedimentLayersWindow, self).__init__(
+            name=self._title, ui="EditSedimentLayers", parent=parent
+        )
+
+        self.setup_sc()
+        self.setup_table()
+        self.setup_graph()
+        self.setup_connections()
+
+        self.ui.setWindowTitle(self._title)
+
+    def setup_title(self, title):
+        name = self._sl.name
+        if name == "":
+            name = _translate("SedimentLayers", "(no name)")
+
+        self._title = (
+            title + " - " + self._study.name + " - " + name
+        )
+
+    def setup_sc(self):
+        self._undo_stack = QUndoStack()
+
+        self.undo_sc = QShortcut(QKeySequence.Undo, self)
+        self.redo_sc = QShortcut(QKeySequence.Redo, self)
+        self.copy_sc = QShortcut(QKeySequence.Copy, self)
+        self.paste_sc = QShortcut(QKeySequence.Paste, self)
+
+    def setup_table(self):
+        self._table = {}
+
+        table = self.find(QTableView, f"tableView")
+        self._table = TableModel(
+            study = self._study,
+            sl = self._sl,
+            undo = self._undo_stack,
+        )
+        table.setModel(self._table)
+
+        table.setSelectionBehavior(QAbstractItemView.SelectRows)
+        table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+        table.setAlternatingRowColors(True)
+
+    def setup_graph(self):
+        self.canvas = MplCanvas(width=5, height=4, dpi=100)
+        self.canvas.setObjectName("canvas")
+        self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
+        self.plot_layout.addWidget(self.canvas)
+        self._set_plot()
+
+    def _set_plot(self):
+        self.plot = Plot(
+            canvas = self.canvas,
+            data = self._sl,
+            toolbar = None,
+            display_current = False
+        )
+        self.plot.draw()
+
+
+    def setup_connections(self):
+        self.find(QAction, "action_add").triggered.connect(self.add)
+        self.find(QAction, "action_del").triggered.connect(self.delete)
+        self.find(QAction, "action_move_up").triggered.connect(self.move_up)
+        self.find(QAction, "action_move_down").triggered.connect(self.move_down)
+
+        self.undo_sc.activated.connect(self.undo)
+        self.redo_sc.activated.connect(self.redo)
+        self.copy_sc.activated.connect(self.copy)
+        self.paste_sc.activated.connect(self.paste)
+
+        self._table.dataChanged.connect(self._set_plot)
+        self._table.layoutChanged.connect(self._set_plot)
+
+    def index_selected_rows(self):
+        table = self.find(QTableView, f"tableView")
+        return list(
+            # Delete duplicate
+            set(
+                map(
+                    lambda i: i.row(),
+                    table.selectedIndexes()
+                )
+            )
+        )
+
+    def add(self):
+        rows = self.index_selected_rows()
+        if len(self._sl) == 0 or len(rows) == 0:
+            self._table.add(0)
+        else:
+            self._table.add(rows[0])
+
+    def delete(self):
+        rows = self.index_selected_rows()
+        if len(rows) == 0:
+            return
+
+        self._table.delete(rows)
+
+    def move_up(self):
+        rows = self.index_selected_rows()
+        if len(rows) == 0:
+            return
+
+        self._table.move_up(rows[0])
+
+    def move_down(self):
+        rows = self.index_selected_rows()
+        if len(rows) == 0:
+            return
+
+        self._table.move_down(rows[0])
+
+    def copy(self):
+        logger.info("TODO: copy")
+
+    def paste(self):
+        logger.info("TODO: paste")
+
+    def undo(self):
+        self._table.undo()
+
+    def redo(self):
+        self._table.redo()
diff --git a/src/View/SedimentLayers/Edit/translate.py b/src/View/SedimentLayers/Edit/translate.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe9e44a923ad21bf50cb1051e6868f82c16678a5
--- /dev/null
+++ b/src/View/SedimentLayers/Edit/translate.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+_translate = QCoreApplication.translate
+
+table_headers = {
+    "name": _translate("SedimentLayers", "Name"),
+    "type": _translate("SedimentLayers", "Type"),
+    "height": _translate("Sedimentlayers", "Height"),
+    "d50": _translate("Sedimentlayers", "D50"),
+    "sigma": _translate("Sedimentlayers", "Sigma"),
+    "critical_constraint": _translate("Sedimentlayers", "Critical constraint"),
+}
diff --git a/src/View/SedimentLayers/Reach/Plot.py b/src/View/SedimentLayers/Reach/Plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..a312a8ceea6ffd9784cd8d56b83781f029250063
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/Plot.py
@@ -0,0 +1,102 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from functools import reduce
+
+from tools import timer
+from View.Plot.APlot import APlot
+
+from PyQt5.QtCore import (
+    QCoreApplication
+)
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class Plot(APlot):
+    def __init__(self, canvas=None, data=None, toolbar=None,
+                 display_current=True):
+        super(Plot, self).__init__(
+            canvas=canvas,
+            data=data,
+            toolbar=toolbar
+        )
+
+        self._display_current = display_current
+
+        self.line_kp_zmin = None
+        self.line_kp_sl = []
+
+    @timer
+    def draw(self):
+        self.canvas.axes.cla()
+        self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+
+        if self.data is None:
+            return
+
+        if self.data.number_profiles == 0:
+            return
+
+        self.canvas.axes.set_xlabel(
+            _translate("MainWindow_reach", "Kp (m)"),
+            color='green', fontsize=12
+        )
+        self.canvas.axes.set_ylabel(
+            _translate("MainWindow_reach", "Height (m)"),
+            color='green', fontsize=12
+        )
+
+        kp = self.data.get_kp()
+        sl = self.data.get_sl()
+        z_min = self.data.get_z_min()
+        z_max = self.data.get_z_max()
+
+        self.canvas.axes.set_xlim(
+            left = min(kp), right = max(kp)
+        )
+
+        # Compute sediment layer in function to profile z_min
+        z_sl = reduce(
+            lambda acc, v: acc + [
+                list(
+                    map(lambda x, y: y - x, v, acc[-1])
+                )
+            ],
+            sl,
+            [z_min]
+        )
+
+        for i, z in enumerate(reversed(z_sl)):
+            self.line_kp_sl.append(None)
+            self.line_kp_sl[i], = self.canvas.axes.plot(
+                kp, z,
+                linestyle="solid" if i == len(z_sl) - 1 else "--",
+                lw=1.8,
+                color='grey' if i == len(z_sl) - 1 else None
+            )
+
+        self.canvas.figure.tight_layout()
+        self.canvas.figure.canvas.draw_idle()
+        if self.toolbar is not None:
+            self.toolbar.update()
+
+        self._init = True
+
+    @timer
+    def update(self, ind=None):
+        if self._init == False:
+            self.draw()
+            return
+
+        if ind is None:
+            kp = self.data.get_kp()
+            z_min = self.data.get_z_min()
+            z_max = self.data.get_z_max()
+
+            self.line_kp_zmin.set_data(kp, z_min)
+
+            self.canvas.axes.autoscale_view(True, True, True)
+            self.canvas.figure.canvas.draw_idle()
diff --git a/src/View/SedimentLayers/Reach/Profile/Plot.py b/src/View/SedimentLayers/Reach/Profile/Plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..50b4bba26c40ebaf4b10c04bbe82d9184407396d
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/Profile/Plot.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from functools import reduce
+
+from tools import timer
+from View.Plot.APlot import APlot
+
+from PyQt5.QtCore import (
+    QCoreApplication
+)
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class Plot(APlot):
+    def __init__(self, canvas=None, data=None, toolbar=None,
+                 display_current=True):
+        super(Plot, self).__init__(
+            canvas=canvas,
+            data=data,
+            toolbar=toolbar
+        )
+
+        self._display_current = display_current
+
+        self.line_kp_zmin = None
+        self.line_kp_sl = []
+
+    @timer
+    def draw(self):
+        self.canvas.axes.cla()
+        self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+
+        if self.data is None:
+            return
+
+        if self.data.number_points == 0:
+            return
+
+        self.canvas.axes.set_xlabel(
+            _translate("MainWindow_reach", "X (m)"),
+            color='green', fontsize=12
+        )
+        self.canvas.axes.set_ylabel(
+            _translate("MainWindow_reach", "Height (m)"),
+            color='green', fontsize=12
+        )
+
+        x = self.data.get_station()
+        z = self.data.z()
+        sl = self.data.get_sl()
+
+        self.canvas.axes.set_xlim(
+            left = min(x), right = max(x)
+        )
+
+        # Compute sediment layer in function to point z
+        z_sl = reduce(
+            lambda acc, v: acc + [
+                list(
+                    map(lambda x, y: y - x, v, acc[-1])
+                )
+            ],
+            sl,
+            [z]
+        )
+
+        for i, zsl in enumerate(reversed(z_sl)):
+            self.line_kp_sl.append(None)
+            self.line_kp_sl[i], = self.canvas.axes.plot(
+                x, zsl,
+                linestyle="solid" if i == len(z_sl) - 1 else "--",
+                lw=1.8,
+                color='grey' if i == len(z_sl) - 1 else None
+            )
+
+        self.canvas.figure.tight_layout()
+        self.canvas.figure.canvas.draw_idle()
+        if self.toolbar is not None:
+            self.toolbar.update()
+
+        self._init = True
+
+    @timer
+    def update(self, ind=None):
+        if self._init == False:
+            self.draw()
+            return
+
+        if ind is None:
+            logger.info("TODO: Update")
+
+            self.canvas.axes.autoscale_view(True, True, True)
+            self.canvas.figure.canvas.draw_idle()
diff --git a/src/View/SedimentLayers/Reach/Profile/Table.py b/src/View/SedimentLayers/Reach/Profile/Table.py
new file mode 100644
index 0000000000000000000000000000000000000000..102bec3274033651495cb25ab06f78ff4517c3e8
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/Profile/Table.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from tools import trace, timer
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox,
+)
+
+from View.SedimentLayers.Reach.Profile.UndoCommand import *
+from View.SedimentLayers.Reach.Profile.translate import *
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class ComboBoxDelegate(QItemDelegate):
+    def __init__(self, study=None, parent=None):
+        super(ComboBoxDelegate, self).__init__(parent)
+
+        self._study = study
+
+    def createEditor(self, parent, option, index):
+        self.editor = QComboBox(parent)
+
+        self.editor.addItems(
+            # [_translate("SedimentLayers", "Not defined")] +
+            list(
+                map(
+                    lambda sl: str(sl),
+                    self._study.river.sediment_layers.sediment_layers
+                )
+            )
+        )
+
+        self.editor.setCurrentText(index.data(Qt.DisplayRole))
+        return self.editor
+
+    def setEditorData(self, editor, index):
+        value = index.data(Qt.DisplayRole)
+        self.editor.currentTextChanged.connect(self.currentItemChanged)
+
+    def setModelData(self, editor, model, index):
+        text = str(editor.currentText())
+        model.setData(index, text)
+        editor.close()
+        editor.deleteLater()
+
+    def updateEditorGeometry(self, editor, option, index):
+        r = QRect(option.rect)
+        if self.editor.windowFlags() & Qt.Popup and editor.parent() is not None:
+            r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
+        editor.setGeometry(r)
+
+    @pyqtSlot()
+    def currentItemChanged(self):
+        self.commitData.emit(self.sender())
+
+
+class TableModel(QAbstractTableModel):
+    def __init__(self, study=None, profile=None, undo=None):
+        super(QAbstractTableModel, self).__init__()
+        self._headers = list(table_headers.keys())
+        self._study = study
+        self._undo = undo
+        self._profile = profile
+
+    def flags(self, index):
+        column = index.column()
+
+        options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+        if self._headers[column] == "sl":
+            options |= Qt.ItemIsEditable
+
+        return options
+
+    def rowCount(self, parent):
+        return self._profile.number_points
+
+    def columnCount(self, parent):
+        return len(self._headers)
+
+    def data(self, index, role):
+        if role != Qt.ItemDataRole.DisplayRole:
+            return QVariant()
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "name":
+            return self._profile.point(row).name
+        elif self._headers[column] == "sl":
+            value = self._profile.point(row).sl
+            if value == None:
+                text = _translate("SedimentLayers", "Not defined")
+                return text
+            return str(value)
+        elif self._headers[column] == "x":
+            return self._profile.point(row).x
+        elif self._headers[column] == "y":
+            return self._profile.point(row).y
+        elif self._headers[column] == "z":
+            return self._profile.point(row).z
+
+        return QVariant()
+
+    def headerData(self, friction, orientation, role):
+        if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
+            return table_headers[self._headers[friction]]
+
+        return QVariant()
+
+    def setData(self, index, value, role=Qt.EditRole):
+        if not index.isValid() or role != Qt.EditRole:
+            return False
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "sl":
+            new = None
+            if value != _translate("SedimentLayers", "Not defined"):
+                new = next(
+                    filter(
+                        lambda sl: str(sl) == value,
+                        self._study.river.sediment_layers.sediment_layers
+                    )
+                )
+
+            self._undo.push(
+                SetSLCommand(
+                    self._profile, row, new
+                )
+            )
+
+        self.dataChanged.emit(index, index)
+        return True
+
+    def undo(self):
+        self._undo.undo()
+        self.layoutChanged.emit()
+
+    def redo(self):
+        self._undo.redo()
+        self.layoutChanged.emit()
diff --git a/src/View/SedimentLayers/Reach/Profile/UndoCommand.py b/src/View/SedimentLayers/Reach/Profile/UndoCommand.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe3497aede40ac048aa6ea1999e6da1566bce976
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/Profile/UndoCommand.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from copy import deepcopy
+from tools import trace, timer
+
+from PyQt5.QtWidgets import (
+    QMessageBox, QUndoCommand, QUndoStack,
+)
+
+from Model.Geometry.Reach import Reach
+from Model.Geometry.Profile import Profile
+from Model.SedimentLayer.SedimentLayer import SedimentLayer
+from Model.SedimentLayer.SedimentLayerList import SedimentLayerList
+
+logger = logging.getLogger()
+
+class SetSLCommand(QUndoCommand):
+    def __init__(self, profile, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._profile = profile
+        self._index = index
+        self._old = self._profile.point(self._index).sl
+        self._new = new_value
+
+    def undo(self):
+        self._profile.point(self._index).sl = self._old
+
+    def redo(self):
+        self._profile.point(self._index).sl = self._new
diff --git a/src/View/SedimentLayers/Reach/Profile/Window.py b/src/View/SedimentLayers/Reach/Profile/Window.py
new file mode 100644
index 0000000000000000000000000000000000000000..d1dd5e691db9cb7579e4f43a2c011a22ecf018b2
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/Profile/Window.py
@@ -0,0 +1,161 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from tools import trace, timer
+
+from View.ASubWindow import ASubMainWindow
+from View.ListedSubWindow import ListedSubWindow
+
+from PyQt5.QtGui import (
+    QKeySequence,
+)
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
+)
+
+from View.SedimentLayers.Reach.Profile.UndoCommand import *
+from View.SedimentLayers.Reach.Profile.Table import *
+from View.SedimentLayers.Reach.Profile.Plot import Plot
+
+from View.Plot.MplCanvas import MplCanvas
+from View.SedimentLayers.Reach.Profile.translate import *
+
+from View.SedimentLayers.Window import SedimentLayersWindow
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class ProfileSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
+    def __init__(self, title="Profile sediment layers", study=None, profile=None, parent=None):
+        self._study = study
+        self._sediment_layers = self._study.river.sediment_layers
+        self._profile = profile
+        self._reach = self._study.river.current_reach().reach
+
+        self.setup_title(title)
+
+        super(ProfileSedimentLayersWindow, self).__init__(
+            name=self._title, ui="ProfileSedimentLayers", parent=parent
+        )
+
+        self.setup_sc()
+        self.setup_table()
+        self.setup_graph()
+        self.setup_connections()
+
+        self.ui.setWindowTitle(self._title)
+
+    def setup_title(self, title):
+        rname = self._reach.name
+        if rname == "":
+            rname = _translate("SedimentLayers", "(no name)")
+
+        pname = self._profile.name
+        if pname == "":
+            pname = _translate(
+                "SedimentLayers",
+                "(no name - @kp)").replace("@kp", str(self._profile.kp)
+            )
+
+        self._title = (
+            title + " - "
+            + self._study.name + " - "
+            + rname + " - " + pname
+        )
+
+    def setup_sc(self):
+        self._undo_stack = QUndoStack()
+
+        self.undo_sc = QShortcut(QKeySequence.Undo, self)
+        self.redo_sc = QShortcut(QKeySequence.Redo, self)
+        self.copy_sc = QShortcut(QKeySequence.Copy, self)
+        self.paste_sc = QShortcut(QKeySequence.Paste, self)
+
+    def setup_table(self):
+        table = self.find(QTableView, f"tableView")
+        self._table = TableModel(
+            study = self._study,
+            profile = self._profile,
+            undo = self._undo_stack,
+        )
+        table.setModel(self._table)
+
+        self._delegate_stricklers = ComboBoxDelegate(
+            study = self._study,
+            parent=self
+        )
+
+        table.setItemDelegateForColumn(
+            list(table_headers).index("sl"),
+            self._delegate_stricklers
+        )
+
+        table.setSelectionBehavior(QAbstractItemView.SelectRows)
+        table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+        table.setAlternatingRowColors(True)
+
+    def setup_graph(self):
+        self.canvas = MplCanvas(width=5, height=4, dpi=100)
+        self.canvas.setObjectName("canvas")
+        self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
+        self.plot_layout.addWidget(self.canvas)
+
+        self._update_plot()
+
+    def _update_plot(self):
+        self.plot = Plot(
+            canvas = self.canvas,
+            data = self._profile,
+            toolbar = None,
+            display_current = False
+        )
+        self.plot.draw()
+
+
+    def setup_connections(self):
+        self.undo_sc.activated.connect(self.undo)
+        self.redo_sc.activated.connect(self.redo)
+        self.copy_sc.activated.connect(self.copy)
+        self.paste_sc.activated.connect(self.paste)
+
+        self._table.layoutChanged\
+                   .connect(self._update_plot)
+        self._table.dataChanged\
+                   .connect(self._update_plot)
+
+
+    def index_selected_rows(self):
+        table = self.find(QTableView, f"tableView")
+        return list(
+            # Delete duplicate
+            set(
+                map(
+                    lambda i: i.row(),
+                    table.selectedIndexes()
+                )
+            )
+        )
+
+    def copy(self):
+        logger.info("TODO: copy")
+
+    def paste(self):
+        logger.info("TODO: paste")
+
+    def undo(self):
+        self._table.undo()
+
+    def redo(self):
+        self._table.redo()
diff --git a/src/View/SedimentLayers/Reach/Profile/translate.py b/src/View/SedimentLayers/Reach/Profile/translate.py
new file mode 100644
index 0000000000000000000000000000000000000000..33e204b33552e41cece53621407ab7f0fbe3774c
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/Profile/translate.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+_translate = QCoreApplication.translate
+
+table_headers = {
+    "x": _translate("SedimentLayers", "X (m)"),
+    "y": _translate("SedimentLayers", "Y (m)"),
+    "z": _translate("SedimentLazers", "Z (m)"),
+    "name": _translate("SedimentLayers", "Name"),
+    "sl": _translate("SedimentLayers", "Sediment layers"),
+}
diff --git a/src/View/SedimentLayers/Reach/SLDialog.py b/src/View/SedimentLayers/Reach/SLDialog.py
new file mode 100644
index 0000000000000000000000000000000000000000..ce1e97942547b805c0bfb2d5c328ca87c66137b0
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/SLDialog.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+
+from View.ASubWindow import ASubWindow
+from View.ListedSubWindow import ListedSubWindow
+
+from PyQt5.QtGui import (
+    QKeySequence,
+)
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
+    QDoubleSpinBox,
+)
+
+from View.SedimentLayers.Reach.translate import *
+
+_translate = QCoreApplication.translate
+
+class SLDialog(ASubWindow, ListedSubWindow):
+    def __init__(self, title="SL", study=None, parent=None):
+        self._study = study
+
+        super(SLDialog, self).__init__(
+            name=title, ui="SLDialog", parent=parent
+        )
+
+        self.setup_combobox()
+
+        self.value = None
+
+    def setup_combobox(self):
+        self.combobox_add_items(
+            "comboBox",
+            [_translate("SedimentLayers", "Not defined")] +
+            list(
+                map(
+                    lambda sl: str(sl),
+                    self._study.river.sediment_layers.sediment_layers
+                )
+            )
+        )
+
+    @property
+    def sl(self):
+        if self.value == _translate("SedimentLayers", "Not defined"):
+            return None
+
+        return next(
+            filter(
+                lambda sl: str(sl) == self.value,
+                self._study.river.sediment_layers.sediment_layers
+            )
+        )
+
+    def accept(self):
+        self.value = self.get_combobox_text("comboBox")
+        super().accept()
diff --git a/src/View/SedimentLayers/Reach/Table.py b/src/View/SedimentLayers/Reach/Table.py
new file mode 100644
index 0000000000000000000000000000000000000000..8fdb8d7e87099902ccab21d6799edf3a1f65e8ae
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/Table.py
@@ -0,0 +1,159 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from tools import trace, timer
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox,
+)
+
+from View.SedimentLayers.Reach.UndoCommand import *
+from View.SedimentLayers.Reach.translate import *
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class ComboBoxDelegate(QItemDelegate):
+    def __init__(self, study=None, parent=None):
+        super(ComboBoxDelegate, self).__init__(parent)
+
+        self._study = study
+
+    def createEditor(self, parent, option, index):
+        self.editor = QComboBox(parent)
+
+        self.editor.addItems(
+            [_translate("SedimentLayers", "Not defined")] +
+            list(
+                map(
+                    lambda sl: str(sl),
+                    self._study.river.sediment_layers.sediment_layers
+                )
+            )
+        )
+
+        self.editor.setCurrentText(index.data(Qt.DisplayRole))
+        return self.editor
+
+    def setEditorData(self, editor, index):
+        value = index.data(Qt.DisplayRole)
+        self.editor.currentTextChanged.connect(self.currentItemChanged)
+
+    def setModelData(self, editor, model, index):
+        text = str(editor.currentText())
+        model.setData(index, text)
+        editor.close()
+        editor.deleteLater()
+
+    def updateEditorGeometry(self, editor, option, index):
+        r = QRect(option.rect)
+        if self.editor.windowFlags() & Qt.Popup and editor.parent() is not None:
+            r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
+        editor.setGeometry(r)
+
+    @pyqtSlot()
+    def currentItemChanged(self):
+        self.commitData.emit(self.sender())
+
+
+class TableModel(QAbstractTableModel):
+    def __init__(self, study=None, reach=None, undo=None):
+        super(QAbstractTableModel, self).__init__()
+        self._headers = list(table_headers.keys())
+        self._study = study
+        self._undo = undo
+        self._reach = reach
+
+    def flags(self, index):
+        column = index.column()
+
+        options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+        if self._headers[column] == "sl":
+            options |= Qt.ItemIsEditable
+
+        return options
+
+    def rowCount(self, parent):
+        return self._reach.number_profiles
+
+    def columnCount(self, parent):
+        return len(self._headers)
+
+    def data(self, index, role):
+        if role != Qt.ItemDataRole.DisplayRole:
+            return QVariant()
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "name":
+            return self._reach.profile(row).name
+        if self._headers[column] == "kp":
+            return self._reach.profile(row).kp
+        if self._headers[column] == "sl":
+            value = self._reach.profile(row).sl
+            if value == None:
+                text = _translate("SedimentLayers", "Not defined")
+                return text
+            return str(value)
+
+        return QVariant()
+
+    def headerData(self, friction, orientation, role):
+        if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
+            return table_headers[self._headers[friction]]
+
+        return QVariant()
+
+    def setData(self, index, value, role=Qt.EditRole):
+        if not index.isValid() or role != Qt.EditRole:
+            return False
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "sl":
+            new = None
+            if value != _translate("SedimentLayers", "Not defined"):
+                new = next(
+                    filter(
+                        lambda sl: str(sl) == value,
+                        self._study.river.sediment_layers.sediment_layers
+                    )
+                )
+
+            self._undo.push(
+                SetSLCommand(
+                    self._reach, row, new
+                )
+            )
+
+        self.dataChanged.emit(index, index)
+        return True
+
+    def apply_sl_each_profile(self, sl):
+        self._undo.push(
+            ApplySLCommand(
+                self._reach, sl
+            )
+        )
+        self.layoutChanged.emit()
+
+    def undo(self):
+        self._undo.undo()
+        self.layoutChanged.emit()
+
+    def redo(self):
+        self._undo.redo()
+        self.layoutChanged.emit()
diff --git a/src/View/SedimentLayers/Reach/UndoCommand.py b/src/View/SedimentLayers/Reach/UndoCommand.py
new file mode 100644
index 0000000000000000000000000000000000000000..17e1f0f1d308855606e2e8a0b972dc57b48d3983
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/UndoCommand.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from copy import deepcopy
+from tools import trace, timer
+
+from PyQt5.QtWidgets import (
+    QMessageBox, QUndoCommand, QUndoStack,
+)
+
+from Model.Geometry.Reach import Reach
+from Model.Geometry.Profile import Profile
+from Model.SedimentLayer.SedimentLayer import SedimentLayer
+from Model.SedimentLayer.SedimentLayerList import SedimentLayerList
+
+logger = logging.getLogger()
+
+class SetSLCommand(QUndoCommand):
+    def __init__(self, reach, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._reach = reach
+        self._index = index
+        self._old = self._reach.profile(self._index).sl
+        self._new = new_value
+
+    def undo(self):
+        self._reach.profile(self._index).sl = self._old
+
+    def redo(self):
+        self._reach.profile(self._index).sl = self._new
+
+
+class ApplySLCommand(QUndoCommand):
+    def __init__(self, reach, new_value):
+        QUndoCommand.__init__(self)
+
+        self._reach = reach
+        self._old = []
+        for profile in self._reach.profiles:
+            self._old.append(profile.sl)
+        self._new = new_value
+
+    def undo(self):
+        for i, profile in enumerate(self._reach.profiles):
+            profile.sl = self._old[i]
+
+    def redo(self):
+        for profile in self._reach.profiles:
+            profile.sl = self._new
diff --git a/src/View/SedimentLayers/Reach/Window.py b/src/View/SedimentLayers/Reach/Window.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee477edc15ec87e7500de8388c0bf02d46e2edb5
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/Window.py
@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from tools import trace, timer
+
+from View.ASubWindow import ASubMainWindow
+from View.ListedSubWindow import ListedSubWindow
+
+from PyQt5.QtGui import (
+    QKeySequence,
+)
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
+)
+
+from View.SedimentLayers.Reach.UndoCommand import *
+from View.SedimentLayers.Reach.Table import *
+from View.SedimentLayers.Reach.Plot import Plot
+from View.SedimentLayers.Reach.SLDialog import SLDialog
+
+from View.Plot.MplCanvas import MplCanvas
+from View.SedimentLayers.Reach.translate import *
+
+from View.SedimentLayers.Window import SedimentLayersWindow
+from View.SedimentLayers.Reach.Profile.Window import ProfileSedimentLayersWindow
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class ReachSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
+    def __init__(self, title="Reach sediment layers", study=None, parent=None):
+        self._study = study
+        self._sediment_layers = self._study.river.sediment_layers
+        self._reach = self._study.river.current_reach().reach
+
+        self.setup_title(title)
+
+        super(ReachSedimentLayersWindow, self).__init__(
+            name=self._title, ui="ReachSedimentLayers", parent=parent
+        )
+
+        self.setup_sc()
+        self.setup_table()
+        self.setup_graph()
+        self.setup_connections()
+
+        self.ui.setWindowTitle(self._title)
+
+    def setup_title(self, title):
+        self._title = (
+            title + " - " + self._study.name + " - " + self._reach.name
+        )
+
+    def setup_sc(self):
+        self._undo_stack = QUndoStack()
+
+        self.undo_sc = QShortcut(QKeySequence.Undo, self)
+        self.redo_sc = QShortcut(QKeySequence.Redo, self)
+        self.copy_sc = QShortcut(QKeySequence.Copy, self)
+        self.paste_sc = QShortcut(QKeySequence.Paste, self)
+
+    def setup_table(self):
+        table = self.find(QTableView, f"tableView")
+        self._table = TableModel(
+            study = self._study,
+            reach = self._reach,
+            undo = self._undo_stack,
+        )
+        table.setModel(self._table)
+
+        self._delegate_stricklers = ComboBoxDelegate(
+            study = self._study,
+            parent=self
+        )
+
+        table.setItemDelegateForColumn(
+            list(table_headers).index("sl"),
+            self._delegate_stricklers
+        )
+
+        table.setSelectionBehavior(QAbstractItemView.SelectRows)
+        table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+        table.setAlternatingRowColors(True)
+
+    def setup_graph(self):
+        self.canvas = MplCanvas(width=5, height=4, dpi=100)
+        self.canvas.setObjectName("canvas")
+        self.plot_layout = self.find(QVBoxLayout, "verticalLayout_2")
+        self.plot_layout.addWidget(self.canvas)
+
+        self._update_plot()
+
+    def _update_plot(self):
+        self.plot = Plot(
+            canvas = self.canvas,
+            data = self._reach,
+            toolbar = None,
+            display_current = False
+        )
+        self.plot.draw()
+
+
+    def setup_connections(self):
+        self.find(QAction, "action_edit").triggered.connect(self.edit_profile)
+
+        self.find(QPushButton, "pushButton_edit")\
+            .clicked\
+            .connect(self.edit_sl)
+        self.find(QPushButton, "pushButton_apply")\
+            .clicked\
+            .connect(self.apply_sl_each_profile)
+
+        self.undo_sc.activated.connect(self.undo)
+        self.redo_sc.activated.connect(self.redo)
+        self.copy_sc.activated.connect(self.copy)
+        self.paste_sc.activated.connect(self.paste)
+
+        self._table.layoutChanged\
+                   .connect(self._update_plot)
+        self._table.dataChanged\
+                   .connect(self._update_plot)
+
+
+    def index_selected_rows(self):
+        table = self.find(QTableView, f"tableView")
+        return list(
+            # Delete duplicate
+            set(
+                map(
+                    lambda i: i.row(),
+                    table.selectedIndexes()
+                )
+            )
+        )
+
+    def copy(self):
+        logger.info("TODO: copy")
+
+    def paste(self):
+        logger.info("TODO: paste")
+
+    def undo(self):
+        self._table.undo()
+        self._update_plot()
+
+    def redo(self):
+        self._table.redo()
+        self._update_plot()
+
+    def apply_sl_each_profile(self):
+        slw = SLDialog(
+            study = self._study,
+            parent = self
+        )
+        if slw.exec():
+            sl = slw.sl
+            self._table.apply_sl_each_profile(sl)
+
+        self._update_plot()
+
+    def edit_profile(self):
+        rows = self.index_selected_rows()
+
+        for row in rows:
+            slw = ProfileSedimentLayersWindow(
+                study = self._study,
+                profile = self._reach.profile(row),
+                parent = self
+            )
+            slw.show()
+
+
+    def edit_sl(self):
+        slw = SedimentLayersWindow(
+            study = self._study,
+            parent = self
+        )
+        slw.show()
diff --git a/src/View/SedimentLayers/Reach/translate.py b/src/View/SedimentLayers/Reach/translate.py
new file mode 100644
index 0000000000000000000000000000000000000000..f6b17cf8a5395417b5c655ab8c3e141397985f4e
--- /dev/null
+++ b/src/View/SedimentLayers/Reach/translate.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+_translate = QCoreApplication.translate
+
+table_headers = {
+    "name": _translate("SedimentLayers", "Name"),
+    "kp": _translate("SedimentLayers", "KP (m)"),
+    "sl": _translate("SedimentLayers", "Sediment layers"),
+}
diff --git a/src/View/SedimentLayers/Table.py b/src/View/SedimentLayers/Table.py
new file mode 100644
index 0000000000000000000000000000000000000000..f375c3188bba6cf0100b327d38197c1f5a8b0fa4
--- /dev/null
+++ b/src/View/SedimentLayers/Table.py
@@ -0,0 +1,151 @@
+# -*- coding: utf-8 -*-
+
+from tools import trace, timer
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox,
+)
+
+from View.SedimentLayers.UndoCommand import *
+from View.SedimentLayers.translate import *
+
+_translate = QCoreApplication.translate
+
+
+class TableModel(QAbstractTableModel):
+    def __init__(self, study=None, undo=None):
+        super(QAbstractTableModel, self).__init__()
+        self._headers = list(table_headers.keys())
+        self._study = study
+        self._undo = undo
+        self._sl = self._study.river.sediment_layers
+
+    def flags(self, index):
+        options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+        options |= Qt.ItemIsEditable
+
+        return options
+
+    def rowCount(self, parent):
+        return len(self._sl)
+
+    def columnCount(self, parent):
+        return len(self._headers)
+
+    def data(self, index, role):
+        if role != Qt.ItemDataRole.DisplayRole:
+            return QVariant()
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "name":
+            return self._sl.get(row).name
+        elif self._headers[column] == "comment":
+            return self._sl.get(row).comment
+
+        return QVariant()
+
+    def headerData(self, friction, orientation, role):
+        if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
+            return table_headers[self._headers[friction]]
+
+        return QVariant()
+
+    def setData(self, index, value, role=Qt.EditRole):
+        if not index.isValid() or role != Qt.EditRole:
+            return False
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "name":
+            self._undo.push(
+                SetNameCommand(
+                    self._sl, row, value
+                )
+            )
+        if self._headers[column] == "comment":
+            self._undo.push(
+                SetCommentCommand(
+                    self._sl, row, value
+                )
+            )
+
+        self.dataChanged.emit(index, index)
+        return True
+
+    def add(self, row, parent=QModelIndex()):
+        self.beginInsertRows(parent, row, row - 1)
+
+        self._undo.push(
+            AddCommand(
+                self._sl, row
+            )
+        )
+
+        self.endInsertRows()
+        self.layoutChanged.emit()
+
+    def delete(self, rows, parent=QModelIndex()):
+        self.beginRemoveRows(parent, rows[0], rows[-1])
+
+        self._undo.push(
+            DelCommand(
+                self._sl, rows
+            )
+        )
+
+        self.endRemoveRows()
+        self.layoutChanged.emit()
+
+    def move_up(self, row, parent=QModelIndex()):
+        if row <= 0:
+            return
+
+        target = row + 2
+
+        self.beginMoveRows(parent, row - 1, row - 1, parent, target)
+
+        self._undo_stack.push(
+            MoveCommand(
+                self._sl, "up", row
+            )
+        )
+
+        self.endMoveRows()
+        self.layoutChanged.emit()
+
+    def move_down(self, index, parent=QModelIndex()):
+        if row > len(self._sl):
+            return
+
+        target = row
+
+        self.beginMoveRows(parent, row + 1, row + 1, parent, target)
+
+        self._undo_stack.push(
+            MoveCommand(
+                self._sl, "down", row
+            )
+        )
+
+        self.endMoveRows()
+        self.layoutChanged.emit()
+
+    def undo(self):
+        self._undo.undo()
+        self.layoutChanged.emit()
+
+    def redo(self):
+        self._undo.redo()
+        self.layoutChanged.emit()
diff --git a/src/View/SedimentLayers/UndoCommand.py b/src/View/SedimentLayers/UndoCommand.py
new file mode 100644
index 0000000000000000000000000000000000000000..f785743b4aa0b455a51bdb4228d0f961af3ee013
--- /dev/null
+++ b/src/View/SedimentLayers/UndoCommand.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+
+from copy import deepcopy
+from tools import trace, timer
+
+from PyQt5.QtWidgets import (
+    QMessageBox, QUndoCommand, QUndoStack,
+)
+
+from Model.SedimentLayer.SedimentLayer import SedimentLayer
+from Model.SedimentLayer.SedimentLayerList import SedimentLayerList
+
+class SetNameCommand(QUndoCommand):
+    def __init__(self, sediment_layers_list, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers_list = sediment_layers_list
+        self._index = index
+        self._old = self._sediment_layers_list.get(self._index).name
+        self._new = new_value
+
+    def undo(self):
+        self._sediment_layers_list.get(self._index).name = self._old
+
+    def redo(self):
+        self._sediment_layers_list.get(self._index).name = self._new
+
+class SetCommentCommand(QUndoCommand):
+    def __init__(self, sediment_layers_list, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers_list = sediment_layers_list
+        self._index = index
+        self._old = self._sediment_layers_list.get(self._index).comment
+        self._new = new_value
+
+    def undo(self):
+        self._sediment_layers_list.get(self._index).comment = self._old
+
+    def redo(self):
+        self._sediment_layers_list.get(self._index).comment = self._new
+
+class AddCommand(QUndoCommand):
+    def __init__(self, sediment_layers_list, index):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers_list = sediment_layers_list
+        self._index = index
+        self._new = None
+
+    def undo(self):
+        self._sediment_layers_list.delete_i([self._index])
+
+    def redo(self):
+        if self._new is None:
+            self._new = self._sediment_layers_list.new(self._index)
+        else:
+            self._sediment_layers_list.insert(self._index, self._new)
+
+class DelCommand(QUndoCommand):
+    def __init__(self, sediment_layers_list, rows):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers_list = sediment_layers_list
+        self._rows = rows
+
+        self._sl_pos = []
+        for row in rows:
+            self._sl_pos.append((row, self._sediment_layers_list.get(row)))
+        self._sl_pos.sort()
+
+    def undo(self):
+        for row, el in self._sl_pos:
+            self._sediment_layers_list.insert(row, el)
+
+    def redo(self):
+        self._sediment_layers_list.delete_i(self._rows)
+
+class MoveCommand(QUndoCommand):
+    def __init__(self, sediment_layers_list, up, i):
+        QUndoCommand.__init__(self)
+
+        self._sediment_layers_list = sediment_layers_list
+        self._up = up == "up"
+        self._i = i
+
+    def undo(self):
+        if self._up:
+            self._sediment_layers_list.move_up(self._i)
+        else:
+            self._sediment_layers_list.move_down(self._i)
+
+    def redo(self):
+        if self._up:
+            self._sediment_layers_list.move_up(self._i)
+        else:
+            self._sediment_layers_list.move_down(self._i)
diff --git a/src/View/SedimentLayers/Window.py b/src/View/SedimentLayers/Window.py
new file mode 100644
index 0000000000000000000000000000000000000000..f8b9d2d2676b50b88fbb0de095d9291efdf2f240
--- /dev/null
+++ b/src/View/SedimentLayers/Window.py
@@ -0,0 +1,170 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from tools import trace, timer
+
+from View.ASubWindow import ASubMainWindow
+from View.ListedSubWindow import ListedSubWindow
+
+from PyQt5.QtGui import (
+    QKeySequence,
+)
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
+)
+
+from View.SedimentLayers.UndoCommand import *
+from View.SedimentLayers.Table import *
+
+from View.SedimentLayers.Edit.Plot import Plot
+
+from View.Plot.MplCanvas import MplCanvas
+from View.SedimentLayers.translate import *
+
+from View.SedimentLayers.Edit.Window import EditSedimentLayersWindow
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class SedimentLayersWindow(ASubMainWindow, ListedSubWindow):
+    def __init__(self, title="SedimentLayersList", study=None, parent=None):
+        self._study = study
+        self._sediment_layers = self._study.river.sediment_layers
+
+        self.setup_title(title)
+
+        super(SedimentLayersWindow, self).__init__(
+            name=self._title, ui="SedimentLayersList", parent=parent
+        )
+
+        self.setup_sc()
+        self.setup_table()
+        self.setup_graph()
+        self.setup_connections()
+
+        self.ui.setWindowTitle(self._title)
+
+    def setup_title(self, title):
+        self._title = (
+            title + " - " + self._study.name
+        )
+
+    def setup_sc(self):
+        self._undo_stack = QUndoStack()
+
+        self.undo_sc = QShortcut(QKeySequence.Undo, self)
+        self.redo_sc = QShortcut(QKeySequence.Redo, self)
+        self.copy_sc = QShortcut(QKeySequence.Copy, self)
+        self.paste_sc = QShortcut(QKeySequence.Paste, self)
+
+    def setup_table(self):
+        table = self.find(QTableView, f"tableView")
+        self._table = TableModel(
+            study = self._study,
+            undo = self._undo_stack,
+        )
+        table.setModel(self._table)
+
+        table.setSelectionBehavior(QAbstractItemView.SelectRows)
+        table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+        table.setAlternatingRowColors(True)
+
+    def setup_graph(self):
+        self.canvas = MplCanvas(width=5, height=4, dpi=100)
+        self.canvas.setObjectName("canvas")
+        self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
+        self.plot_layout.addWidget(self.canvas)
+
+    def setup_connections(self):
+        self.find(QAction, "action_add").triggered.connect(self.add)
+        self.find(QAction, "action_del").triggered.connect(self.delete)
+        self.find(QAction, "action_edit").triggered.connect(self.edit_sediment_layers)
+
+        self.undo_sc.activated.connect(self.undo)
+        self.redo_sc.activated.connect(self.redo)
+        self.copy_sc.activated.connect(self.copy)
+        self.paste_sc.activated.connect(self.paste)
+
+        table = self.find(QTableView, f"tableView")
+        table.selectionModel()\
+             .selectionChanged\
+             .connect(self._set_current_sl)
+
+        self._table.dataChanged\
+                   .connect(self._set_current_sl)
+
+    def _set_current_sl(self):
+        rows = self.index_selected_rows()
+
+        if len(rows) == 0:
+            return
+
+        self.plot = Plot(
+            canvas = self.canvas,
+            data = self._sediment_layers.get(rows[0]),
+            toolbar = None,
+            display_current = False
+        )
+        self.plot.draw()
+
+
+    def index_selected_rows(self):
+        table = self.find(QTableView, f"tableView")
+        return list(
+            # Delete duplicate
+            set(
+                map(
+                    lambda i: i.row(),
+                    table.selectedIndexes()
+                )
+            )
+        )
+
+    def add(self):
+        rows = self.index_selected_rows()
+        if len(self._sediment_layers) == 0 or len(rows) == 0:
+            self._table.add(0)
+        else:
+            self._table.add(rows[0])
+
+    def delete(self):
+        rows = self.index_selected_rows()
+        if len(rows) == 0:
+            return
+
+        self._table.delete(rows)
+
+    def copy(self):
+        logger.info("TODO: copy")
+
+    def paste(self):
+        logger.info("TODO: paste")
+
+    def undo(self):
+        self._table.undo()
+
+    def redo(self):
+        self._table.redo()
+
+    def edit_sediment_layers(self):
+        rows = self.index_selected_rows()
+
+        for row in rows:
+            slw = EditSedimentLayersWindow(
+                study = self._study,
+                sl = self._sediment_layers.get(row),
+                parent = self
+            )
+            slw.show()
diff --git a/src/View/SedimentLayers/translate.py b/src/View/SedimentLayers/translate.py
new file mode 100644
index 0000000000000000000000000000000000000000..6eafe079bbbc07c58e8bad45d5cd9c107bf65c30
--- /dev/null
+++ b/src/View/SedimentLayers/translate.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+_translate = QCoreApplication.translate
+
+table_headers = {
+    "name": _translate("SedimentLayers", "Name"),
+    "comment": _translate("SedimentLayers", "Comment"),
+}
diff --git a/src/View/SolverParameters/translate.py b/src/View/SolverParameters/translate.py
index 76cb70ac627ce7fd4a9b15a618946a3c1cf30e16..2508629ea0ab0cfdeb70d639b7a1bb9174ab4715 100644
--- a/src/View/SolverParameters/translate.py
+++ b/src/View/SolverParameters/translate.py
@@ -55,15 +55,16 @@ def init():
         "all_init_time": _translate("SolverParameters", "Initial time (jj:hh:mm:ss)"),
         "all_final_time": _translate("SolverParameters", "Final time (jj:hh:mm:ss)"),
         "all_timestep": _translate("SolverParameters", "Timestep (second)"),
+        "all_command_line_arguments": _translate("SolverParameters", "Command line arguments"),
         # Mage specific parameters
         "mage_min_timestep": _translate("SolverParameters", "Minimum timestep (second)"),
         "mage_timestep_tra": _translate("SolverParameters", "Time step of writing on .TRA"),
         "mage_timestep_bin": _translate("SolverParameters", "Time step of writing on .BIN"),
-        "mage_implication": _translate("SolverParameters", "Implicitation parameter"),
+        "mage_implicitation": _translate("SolverParameters", "Implicitation parameter"),
         "mage_continuity_discretization": _translate("SolverParameters", "Continuity discretization type (S/L)"),
         "mage_qsj_discretization": _translate("SolverParameters", "QSJ discretization (A/B)"),
         "mage_stop_criterion_iterations": _translate("SolverParameters", "Stop criterion iterations (G/A/R)"),
-        "mage_iter_type": _translate("SolverParameters", "Iteration type"),
+        "mage_iteration_type": _translate("SolverParameters", "Iteration type"),
         "mage_smooth_coef": _translate("SolverParameters", "Smoothing coefficient"),
         "mage_cfl_max": _translate("SolverParameters", "Maximun accepted number of CFL"),
         "mage_min_height": _translate("SolverParameters", "Minimum water height (meter)"),
diff --git a/src/View/ui/EditSedimentLayers.ui b/src/View/ui/EditSedimentLayers.ui
new file mode 100644
index 0000000000000000000000000000000000000000..6fe4c11b0c00dba95e08413308e8a8782fac1ede
--- /dev/null
+++ b/src/View/ui/EditSedimentLayers.ui
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>960</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QSplitter" name="splitter">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QTableView" name="tableView"/>
+      <widget class="QWidget" name="verticalLayoutWidget">
+       <layout class="QVBoxLayout" name="verticalLayout"/>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>960</width>
+     <height>22</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <widget class="QToolBar" name="toolBar">
+   <property name="windowTitle">
+    <string>toolBar</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="action_add"/>
+   <addaction name="action_del"/>
+   <addaction name="action_move_up"/>
+   <addaction name="action_move_down"/>
+  </widget>
+  <action name="action_add">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/gtk-add.png</normaloff>ressources/gtk-add.png</iconset>
+   </property>
+   <property name="text">
+    <string>Add sediment layer</string>
+   </property>
+   <property name="toolTip">
+    <string>Add a new sediment layer</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+N</string>
+   </property>
+  </action>
+  <action name="action_del">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/gtk-remove.png</normaloff>ressources/gtk-remove.png</iconset>
+   </property>
+   <property name="text">
+    <string>Delete sediment layer</string>
+   </property>
+   <property name="toolTip">
+    <string>Delete selected sediment layer(s)</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+D</string>
+   </property>
+  </action>
+  <action name="action_move_up">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/up.png</normaloff>ressources/up.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move up</string>
+   </property>
+   <property name="toolTip">
+    <string>Move up</string>
+   </property>
+  </action>
+  <action name="action_move_down">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/down.png</normaloff>ressources/down.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move down</string>
+   </property>
+   <property name="toolTip">
+    <string>Move down</string>
+   </property>
+  </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/View/ui/MainWindow.ui b/src/View/ui/MainWindow.ui
index 217bd2b42ab461e2bc7c8990752268ab476cd51a..ea77d698538b0c64532eeb76c8942fe436f55e94 100644
--- a/src/View/ui/MainWindow.ui
+++ b/src/View/ui/MainWindow.ui
@@ -165,10 +165,18 @@
     <addaction name="action_menu_help_mage"/>
     <addaction name="action_menu_about"/>
    </widget>
+   <widget class="QMenu" name="menuSediment">
+    <property name="title">
+     <string>&amp;Sediment</string>
+    </property>
+    <addaction name="action_menu_sediment_layers"/>
+    <addaction name="action_menu_edit_reach_sediment_layers"/>
+   </widget>
    <addaction name="menu_File"/>
    <addaction name="menu_network"/>
    <addaction name="menu_geometry"/>
    <addaction name="menu_Hydraulics"/>
+   <addaction name="menuSediment"/>
    <addaction name="menu_run"/>
    <addaction name="menu_plot"/>
    <addaction name="menu_cartography"/>
@@ -878,6 +886,16 @@
     <string>Define initial conditions</string>
    </property>
   </action>
+  <action name="action_menu_sediment_layers">
+   <property name="text">
+    <string>Sediment layers</string>
+   </property>
+  </action>
+  <action name="action_menu_edit_reach_sediment_layers">
+   <property name="text">
+    <string>Edit reach sediment layers</string>
+   </property>
+  </action>
  </widget>
  <resources/>
  <connections>
diff --git a/src/View/ui/ProfileSedimentLayers.ui b/src/View/ui/ProfileSedimentLayers.ui
new file mode 100644
index 0000000000000000000000000000000000000000..b9f5106dab3d25190b3d41bd8209e2e89cdd36ed
--- /dev/null
+++ b/src/View/ui/ProfileSedimentLayers.ui
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>960</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QSplitter" name="splitter">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QTableView" name="tableView"/>
+      <widget class="QWidget" name="verticalLayoutWidget">
+       <layout class="QVBoxLayout" name="verticalLayout"/>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>960</width>
+     <height>22</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <widget class="QToolBar" name="toolBar">
+   <property name="windowTitle">
+    <string>toolBar</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="action_add_sediment_layers"/>
+   <addaction name="action_delete_sediment_layers"/>
+   <addaction name="action_edit_sediment_layers"/>
+  </widget>
+  <action name="action_add_sediment_layers">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/gtk-add.png</normaloff>ressources/gtk-add.png</iconset>
+   </property>
+   <property name="text">
+    <string>Add sediment layers</string>
+   </property>
+   <property name="toolTip">
+    <string>Add specific sediment layers on selected point(s)</string>
+   </property>
+  </action>
+  <action name="action_delete_sediment_layers">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/gtk-remove.png</normaloff>ressources/gtk-remove.png</iconset>
+   </property>
+   <property name="text">
+    <string>Delete sediment layers</string>
+   </property>
+   <property name="toolTip">
+    <string>Delete specific sediment layers of selected point(s)</string>
+   </property>
+  </action>
+  <action name="action_edit_sediment_layers">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/edit.png</normaloff>ressources/edit.png</iconset>
+   </property>
+   <property name="text">
+    <string>Edit sediment layers</string>
+   </property>
+   <property name="toolTip">
+    <string>Edit sediment layers list</string>
+   </property>
+  </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/View/ui/ReachSedimentLayers.ui b/src/View/ui/ReachSedimentLayers.ui
new file mode 100644
index 0000000000000000000000000000000000000000..dfe39a823d819abf8351e0cf9cc490438fb209be
--- /dev/null
+++ b/src/View/ui/ReachSedimentLayers.ui
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>960</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QSplitter" name="splitter">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QWidget" name="verticalLayoutWidget">
+       <layout class="QVBoxLayout" name="verticalLayout">
+        <item>
+         <widget class="QTableView" name="tableView"/>
+        </item>
+        <item>
+         <widget class="QPushButton" name="pushButton_edit">
+          <property name="text">
+           <string>Edit sediment layers list</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="pushButton_apply">
+          <property name="text">
+           <string>Apply sediment layers on all reach</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+      <widget class="QWidget" name="verticalLayoutWidget_2">
+       <layout class="QVBoxLayout" name="verticalLayout_2"/>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>960</width>
+     <height>22</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <widget class="QToolBar" name="toolBar">
+   <property name="windowTitle">
+    <string>toolBar</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="action_edit"/>
+  </widget>
+  <action name="action_edit">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/edit.png</normaloff>ressources/edit.png</iconset>
+   </property>
+   <property name="text">
+    <string>Edit profile</string>
+   </property>
+   <property name="toolTip">
+    <string>Edit profile sediment layer</string>
+   </property>
+  </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/View/ui/Results.ui b/src/View/ui/Results.ui
index d975641b9d1fd8ba90c54f4a33f7feeb5fd7150f..5b7977242bbdeaec70fa2548687695f6ad45e888 100644
--- a/src/View/ui/Results.ui
+++ b/src/View/ui/Results.ui
@@ -30,7 +30,7 @@
        <widget class="QTableView" name="tableView_reach"/>
        <widget class="QTableView" name="tableView_profile"/>
       </widget>
-      <widget class="QWidget" name="">
+      <widget class="QWidget" name="layoutWidget">
        <layout class="QGridLayout" name="gridLayout_2">
         <item row="0" column="0">
          <widget class="QTabWidget" name="tabWidget">
@@ -75,6 +75,32 @@
             </item>
            </layout>
           </widget>
+          <widget class="QWidget" name="tab_3">
+           <property name="enabled">
+            <bool>true</bool>
+           </property>
+           <attribute name="title">
+            <string>Sediment</string>
+           </attribute>
+           <layout class="QGridLayout" name="gridLayout_5">
+            <item row="0" column="0">
+             <widget class="QSplitter" name="splitter_5">
+              <property name="enabled">
+               <bool>true</bool>
+              </property>
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+              <widget class="QWidget" name="verticalLayoutWidget_4">
+               <layout class="QVBoxLayout" name="verticalLayout_sed_reach"/>
+              </widget>
+              <widget class="QWidget" name="verticalLayoutWidget_5">
+               <layout class="QVBoxLayout" name="verticalLayout_sed_profile"/>
+              </widget>
+             </widget>
+            </item>
+           </layout>
+          </widget>
          </widget>
         </item>
         <item row="0" column="1">
diff --git a/src/View/ui/SLDialog.ui b/src/View/ui/SLDialog.ui
new file mode 100644
index 0000000000000000000000000000000000000000..8681418bd621fdbbf0016add2de546e03f1fc947
--- /dev/null
+++ b/src/View/ui/SLDialog.ui
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>194</width>
+    <height>76</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QComboBox" name="comboBox"/>
+   </item>
+   <item row="1" column="0">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>Dialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>Dialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/View/ui/SedimentLayersList.ui b/src/View/ui/SedimentLayersList.ui
new file mode 100644
index 0000000000000000000000000000000000000000..399b09953889574a12ecb6ce78373ab7b0389a77
--- /dev/null
+++ b/src/View/ui/SedimentLayersList.ui
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>960</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QSplitter" name="splitter">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QTableView" name="tableView"/>
+      <widget class="QWidget" name="verticalLayoutWidget">
+       <layout class="QVBoxLayout" name="verticalLayout"/>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>960</width>
+     <height>22</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <widget class="QToolBar" name="toolBar">
+   <property name="windowTitle">
+    <string>toolBar</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="action_add"/>
+   <addaction name="action_del"/>
+   <addaction name="action_edit"/>
+  </widget>
+  <action name="action_add">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/gtk-add.png</normaloff>ressources/gtk-add.png</iconset>
+   </property>
+   <property name="text">
+    <string>Add sediment layer</string>
+   </property>
+  </action>
+  <action name="action_del">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/gtk-remove.png</normaloff>ressources/gtk-remove.png</iconset>
+   </property>
+   <property name="text">
+    <string>Delete sediment layer</string>
+   </property>
+   <property name="toolTip">
+    <string>Delete sediment layer</string>
+   </property>
+  </action>
+  <action name="action_edit">
+   <property name="icon">
+    <iconset>
+     <normaloff>ressources/edit.png</normaloff>ressources/edit.png</iconset>
+   </property>
+   <property name="text">
+    <string>Edit sediment layer</string>
+   </property>
+   <property name="toolTip">
+    <string>Edit sediment layer</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+E</string>
+   </property>
+  </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/View/ui/Widgets/extendedTimeEdit.ui b/src/View/ui/Widgets/extendedTimeEdit.ui
index 493a96a11eece3431108500c8eff0555f019ea81..eddf38928e30fc06e392a100332342fc74d4ec43 100644
--- a/src/View/ui/Widgets/extendedTimeEdit.ui
+++ b/src/View/ui/Widgets/extendedTimeEdit.ui
@@ -28,6 +28,9 @@
      <property name="alignment">
       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
      </property>
+     <property name="maximum">
+      <number>999999</number>
+     </property>
     </widget>
    </item>
    <item>
diff --git a/tests_cases/Saar/Saar.pamhyr b/tests_cases/Saar/Saar.pamhyr
index df56a2984353c1c2f9d8f73ffc277b4fab764ba6..711ef7bc929574e1ca841b76442e1262bddd4c8b 100644
Binary files a/tests_cases/Saar/Saar.pamhyr and b/tests_cases/Saar/Saar.pamhyr differ