diff --git a/docs/conf.py b/docs/conf.py
index dc7d748bd74d37f351df59e8b30c057d164734d0..df9585dcb7ddf1c62073540a33f79481b225a7a3 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -117,6 +117,8 @@ autodoc_member_order = "bysource"
 autodoc_preserve_defaults = True
 autodoc_typehints = "description"
 
+autodoc_default_options = {"special-members": "__call__"}
+
 ### sphinx-gallery setup ###
 # necessary when building the sphinx gallery
 pyvista.BUILDING_GALLERY = True
diff --git a/docs/examples/howto_meshplotlib/plot_meshplotlib_2d.py b/docs/examples/howto_meshplotlib/plot_meshplotlib_2d.py
index 006e86e3c2e3f449b88db95cf15ff74b6b0be742..363064503006f47f1256d4fce93449625443648b 100644
--- a/docs/examples/howto_meshplotlib/plot_meshplotlib_2d.py
+++ b/docs/examples/howto_meshplotlib/plot_meshplotlib_2d.py
@@ -28,6 +28,14 @@ fig = mpl.plot(mesh, presets.material_id)
 
 fig = mpl.plot(mesh, presets.temperature)
 
+# %%
+# We can also plot components of vector properties:
+
+fig = mpl.plot(mesh, presets.displacement[0])
+
+# %%
+fig = mpl.plot(mesh, presets.displacement[1])
+
 # %%
 # This example has hydraulically deactivated subdomains:
 
@@ -37,19 +45,8 @@ fig = mpl.plot(mesh, presets.pressure.get_mask())
 # Let's plot the fluid velocity field.
 fig = mpl.plot(mesh, presets.velocity)
 
-
 # %%
 # Let's plot it again, this time log-scaled.
 mpl.setup.log_scaled = True
 mpl.setup.p_min = -8
 fig = mpl.plot(mesh, presets.velocity)
-mpl.setup.p_min = None
-mpl.setup.log_scaled = False
-
-# %%
-# We can also plot components of vector property:
-
-fig = mpl.plot(mesh, presets.displacement[0])
-
-# %%
-fig = mpl.plot(mesh, presets.displacement[1])
diff --git a/docs/examples/howto_meshplotlib/plot_solid_mechanics.py b/docs/examples/howto_meshplotlib/plot_solid_mechanics.py
index 22fd4b9044d42c0088634ec6698e2e809e1d67db..0cbfd245f7b0c3618fde696c8876d78832ef3e0c 100644
--- a/docs/examples/howto_meshplotlib/plot_solid_mechanics.py
+++ b/docs/examples/howto_meshplotlib/plot_solid_mechanics.py
@@ -42,23 +42,29 @@ fig = plot(mesh, presets.stress["xy"])
 # %% [markdown]
 # Principal stresses
 # ------------------
-# Let's calculate the the principal stress components and overlay the direcetion
-# of the corresponding eigenvector. Note: the eigenvalues are sorted by
-# increasing order, i.e. eigenvalue[0] is the most negative / largest
+# Let's plot the the principal stress components and also overlay the direction
+# of the corresponding eigenvector in the plot. Note: the eigenvalues are sorted
+# by increasing order, i.e. eigenvalue[0] is the most negative / largest
 # compressive principal stress.
 
 # %%
 eigvecs = presets.stress.eigenvectors
 fig = plot(mesh, mesh_property=presets.stress.eigenvalues[0])
-plot_streamlines(ax=fig.axes[0], mesh=mesh, property=eigvecs[0], arrows=True)
+plot_streamlines(
+    ax=fig.axes[0], mesh=mesh, mesh_property=eigvecs[0], plot_type="lines"
+)
 
 # %%
 fig = plot(mesh, mesh_property=presets.stress.eigenvalues[1])
-plot_streamlines(ax=fig.axes[0], mesh=mesh, property=eigvecs[1], arrows=True)
+plot_streamlines(
+    ax=fig.axes[0], mesh=mesh, mesh_property=eigvecs[1], plot_type="lines"
+)
 
 # %%
 fig = plot(mesh, mesh_property=presets.stress.eigenvalues[2])
-plot_streamlines(ax=fig.axes[0], mesh=mesh, property=eigvecs[2], arrows=True)
+plot_streamlines(
+    ax=fig.axes[0], mesh=mesh, mesh_property=eigvecs[2], plot_type="lines"
+)
 
 # %% [markdown]
 # We can also plot the mean of the principal stress, i.e. the magnitude of the
diff --git a/docs/examples/howto_propertylib/plot_propertylib.py b/docs/examples/howto_propertylib/plot_propertylib.py
index 709895eb1581bd83ac854c3838cfce8c2a9cf0bf..1d536b115223a126d85a33b33be545b49549f2e2 100644
--- a/docs/examples/howto_propertylib/plot_propertylib.py
+++ b/docs/examples/howto_propertylib/plot_propertylib.py
@@ -11,35 +11,14 @@ mesh data. There are several predefined properties stored under the module
 """
 
 # %%
-
-# sphinx_gallery_start_ignore
-
-import pandas as pd
-
 from ogstools.meshplotlib import examples, plot
 from ogstools.propertylib import Scalar, presets
 
-data = ["preset,data_name,data_unit,output_unit,output_name,type".split(",")]
-for preset_name in dir(presets):
-    if isinstance(preset := presets.__dict__[preset_name], presets.Property):
-        data += [
-            [
-                preset_name,
-                preset.data_name,
-                preset.data_unit,
-                preset.output_unit,
-                preset.output_name,
-                preset.type_name,
-            ]
-        ]
-
-pd.DataFrame(data[1:], columns=data[0]).sort_values(
-    ["data_name", "preset"]
-).set_index("preset")
-
-# sphinx_gallery_end_ignore
+presets.get_dataframe()
 
 # %% [markdown]
+# Scalar, Vector and Matrix are inherit from the class Property with its
+# :meth:`~ogstools.propertylib.Property.__call__` operator.
 # Calling a property converts the argument from data_unit to output_unit and
 # applies a function if specified. In this case we convert from K to °C:
 
@@ -57,7 +36,7 @@ custom_temperature = Scalar(
 custom_temperature(273.15)
 
 # %% [markdown]
-# Or us existing presets as a template and replace some parameters:
+# Or use existing presets as a template and replace some parameters:
 custom_temperature = presets.temperature.replace(output_unit="°F")
 custom_temperature(273.15)
 
@@ -81,8 +60,8 @@ presets.strain["xx"]([0.01, 0.02, 0.03, 0.04, 0.05, 0.06])
 presets.displacement.magnitude([0.03, 0.04])
 
 # %% [markdown]
-# The main benefit of having specified how these properties should be
-# transformed is when making use of these in post processing. When plotting
+# We suggest specifying the properties and their transformations once.
+# These can be reused in different kind of post processing. When plotting
 # with :py:mod:`ogstools.meshplotlib` we can use these presets to simplify the
 # task of processing the data (e.g. calculate the von Mises stress):
 
diff --git a/ogstools/meshplotlib/core.py b/ogstools/meshplotlib/core.py
index a5e0444c16ded9378e569ac33cf0b8e3bb2761c6..87ea86b24bec855fe75b5843fef15fad11d710a2 100644
--- a/ogstools/meshplotlib/core.py
+++ b/ogstools/meshplotlib/core.py
@@ -21,7 +21,7 @@ from ogstools.propertylib.unit_registry import u_reg
 
 from . import plot_features as pf
 from . import setup
-from .levels import get_levels, median_exponent
+from .levels import compute_levels, median_exponent
 from .utils import get_style_cycler
 
 # TODO: define default data_name for regions in setup
@@ -236,7 +236,7 @@ def subplot(
 
     if levels is None:
         num_levels = min(setup.num_levels, len(np.unique(values)))
-        levels = get_levels(p_min, p_max, num_levels)
+        levels = compute_levels(p_min, p_max, num_levels)
     cmap, norm = get_cmap_norm(levels, mesh_property)
 
     if (
@@ -372,7 +372,7 @@ def get_combined_levels(
         and setup.p_max is None
     ):
         return unique_vals[(p_min <= unique_vals) & (unique_vals <= p_max)]
-    return get_levels(p_min, p_max, setup.num_levels)
+    return compute_levels(p_min, p_max, setup.num_levels)
 
 
 def _plot_on_figure(
diff --git a/ogstools/meshplotlib/levels.py b/ogstools/meshplotlib/levels.py
index 55cfde5e589153c3d5a8423f6c8115cdccf33831..997048377ef9f59134303a0cef79816253295ec1 100644
--- a/ogstools/meshplotlib/levels.py
+++ b/ogstools/meshplotlib/levels.py
@@ -47,7 +47,7 @@ def adaptive_rounding(vals: np.ndarray, precision: int) -> np.ndarray:
     return np.stack([np.round(v, 12 - median_exp) for v in vals])
 
 
-def get_levels(lower: float, upper: float, n_ticks: int) -> np.ndarray:
+def compute_levels(lower: float, upper: float, n_ticks: int) -> np.ndarray:
     """
     Return an array in the interval [lower, upper] with terminating decimals.
 
@@ -56,10 +56,10 @@ def get_levels(lower: float, upper: float, n_ticks: int) -> np.ndarray:
     """
     if lower == upper:
         return np.asarray([lower, nextafter(lower, np.inf)])
-    levels = nice_range(lower, upper, n_ticks)
+    result = nice_range(lower, upper, n_ticks)
     return np.unique(
         adaptive_rounding(
-            np.append(np.append(lower, levels), upper), precision=3
+            np.append(np.append(lower, result), upper), precision=3
         )
     )
 
diff --git a/ogstools/meshplotlib/plot_features.py b/ogstools/meshplotlib/plot_features.py
index 41a8d6b9ee21acaf74d0188fce040e7e03e6a72c..7a9a3e1d4f16dda90da0352162488921f4ada4ad 100644
--- a/ogstools/meshplotlib/plot_features.py
+++ b/ogstools/meshplotlib/plot_features.py
@@ -1,6 +1,6 @@
 """Specialized plot features."""
 
-from typing import Callable, Optional
+from typing import Callable, Literal, Optional
 
 import matplotlib.pyplot as plt
 import numpy as np
@@ -81,14 +81,23 @@ def plot_element_edges(ax: plt.Axes, surf: pv.DataSet, projection: int) -> None:
 def plot_streamlines(
     ax: plt.Axes,
     mesh: pv.DataSet,
-    property: Vector,
+    mesh_property: Vector,
     projection: Optional[int] = None,
-    arrows: bool = False,
+    plot_type: Literal["streamlines", "arrows", "lines"] = "streamlines",
 ) -> None:
-    """Plot vector streamlines on a matplotlib axis."""
+    """
+    Plot the vector streamlines or arrows on a matplotlib axis.
+
+    :param ax:              Matplotlib axis to plot onto
+    :param mesh:            Mesh containing the vector property
+    :param mesh_property:   Vector property to visualize
+    :param projection:      Index of flat dimension (e.g. 2 for z axis),
+                            gets automatically determined if not given
+    :param plot_type:       Whether to plot streamlines, arrows or lines.
+    """
     if (n_pts := setup.num_streamline_interp_pts) is None:
         return
-    if arrows:
+    if plot_type != "streamlines":
         n_pts = 50
     if projection is None:
         mean_normal = np.abs(
@@ -103,47 +112,37 @@ def plot_streamlines(
 
     _mesh = mesh.copy()
     for key in _mesh.point_data:
-        if key not in [property.data_name, property.mask]:
+        if key not in [mesh_property.data_name, mesh_property.mask]:
             del _mesh.point_data[key]
     grid = pv.RectilinearGrid(
         [x, y, z][x_id], [x, y, z][y_id], [x, y, z][projection]
     )
     grid = grid.sample(_mesh, pass_cell_data=False)
-    values = property(grid.point_data[property.data_name])
+    values = mesh_property(grid.point_data[mesh_property.data_name])
     values[np.argwhere(grid["vtkValidPointMask"] == 0), :] = np.nan
     if np.shape(values)[-1] == 3:
         values = np.delete(values, projection, 1)
     val = np.reshape(values, (n_pts, n_pts, 2))
 
-    if property.mask in grid.point_data:
-        mask = np.reshape(grid.point_data[property.mask], (n_pts, n_pts))
+    if mesh_property.mask in grid.point_data:
+        mask = np.reshape(grid.point_data[mesh_property.mask], (n_pts, n_pts))
         val[mask == 0, :] = 0
     val_norm = np.linalg.norm(np.nan_to_num(val), axis=-1)
     lw = 2.5 * val_norm / max(1e-16, np.max(val_norm))
     lw *= setup.rcParams_scaled["lines.linewidth"]
     x_g, y_g = setup.length(np.meshgrid(x, y))
-    if arrows:
-        ax.quiver(
-            x_g,
-            y_g,
-            val[..., 0],
-            val[..., 1],
-            scale=1 / 0.03,
-            headlength=0,
-            headaxislength=0,
-            headwidth=1,
-            pivot="mid",
-        )
+    plot_args = [x_g, y_g, val[..., 0], val[..., 1]]
+    if plot_type == "streamlines":
+        ax.streamplot(*plot_args, color="k", linewidth=lw, density=1.5)
     else:
-        ax.streamplot(
-            x_g,
-            y_g,
-            val[..., 0],
-            val[..., 1],
-            color="k",
-            linewidth=lw,
-            density=1.5,
+        line_args = (
+            dict(  # noqa: C408
+                headlength=0, headaxislength=0, headwidth=1, pivot="mid"
+            )
+            if plot_type == "lines"
+            else {}
         )
+        ax.quiver(*plot_args, **line_args, scale=1 / 0.03)
 
 
 def plot_on_top(
diff --git a/ogstools/propertylib/matrix.py b/ogstools/propertylib/matrix.py
index d8ad499a181e7dfcc6c671f2e8c76e61e2767489..e37c88117119b9fc5730d910943239323244fa44 100644
--- a/ogstools/propertylib/matrix.py
+++ b/ogstools/propertylib/matrix.py
@@ -78,32 +78,32 @@ class Matrix(Property):
         )
 
     @property
-    def I1(self) -> Scalar:  # pylint: disable=invalid-name
+    def invariant_1(self) -> Scalar:
         "A scalar property as the first invariant of the matrix."
         return Scalar.from_property(
             self,
             output_name=self.output_name + "_I1",
-            func=lambda x: tensor_math.I1(self.func(x)),
+            func=lambda x: tensor_math.invariant_1(self.func(x)),
         )
 
     @property
-    def I2(self) -> Scalar:  # pylint: disable=invalid-name
+    def invariant_2(self) -> Scalar:
         "A scalar property as the second invariant of the matrix."
         return Scalar.from_property(
             self,
             output_unit=self.output_unit + "^2",
             output_name=self.output_name + "_I2",
-            func=lambda x: tensor_math.I2(self.func(x)),
+            func=lambda x: tensor_math.invariant_2(self.func(x)),
             process_with_units=True,
         )
 
     @property
-    def I3(self) -> Scalar:  # pylint: disable=invalid-name
+    def invariant_3(self) -> Scalar:
         "A scalar property as the third invariant of the matrix."
         return Scalar.from_property(
             self,
             output_name=self.output_name + "_I3",
-            func=lambda x: tensor_math.I3(self.func(x)),
+            func=lambda x: tensor_math.invariant_3(self.func(x)),
         )
 
     @property
@@ -134,30 +134,30 @@ class Matrix(Property):
         )
 
     @property
-    def J1(self) -> Scalar:  # pylint: disable=invalid-name
+    def deviator_invariant_1(self) -> Scalar:
         "A scalar property as the first invariant of the matrix deviator."
         return Scalar.from_property(
             self,
             output_name=self.output_name + "_J1",
-            func=lambda x: tensor_math.J1(self.func(x)),
+            func=lambda x: tensor_math.deviator_invariant_1(self.func(x)),
         )
 
     @property
-    def J2(self) -> Scalar:  # pylint: disable=invalid-name
+    def deviator_invariant_2(self) -> Scalar:
         "A scalar property as the second invariant of the matrix deviator."
         return Scalar.from_property(
             self,
             output_name=self.output_name + "_J2",
-            func=lambda x: tensor_math.J2(self.func(x)),
+            func=lambda x: tensor_math.deviator_invariant_2(self.func(x)),
         )
 
     @property
-    def J3(self) -> Scalar:  # pylint: disable=invalid-name
+    def deviator_invariant_3(self) -> Scalar:
         "A scalar property as the third invariant of the matrix deviator."
         return Scalar.from_property(
             self,
             output_name=self.output_name + "_J3",
-            func=lambda x: tensor_math.J3(self.func(x)),
+            func=lambda x: tensor_math.deviator_invariant_3(self.func(x)),
         )
 
     @property
diff --git a/ogstools/propertylib/mesh_dependent.py b/ogstools/propertylib/mesh_dependent.py
index c26938ba0956036d77e17c3ebb48310efe2fb778..6f9682442eb8792cfe03cda95661e0256afbbb14 100644
--- a/ogstools/propertylib/mesh_dependent.py
+++ b/ogstools/propertylib/mesh_dependent.py
@@ -1,6 +1,5 @@
 "Functions related to stress analysis which can be only applied to a mesh."
 
-from functools import partial
 from typing import Union
 
 import numpy as np
@@ -17,8 +16,9 @@ ValType = Union[PlainQuantity, np.ndarray]
 def depth(mesh: pv.UnstructuredGrid, use_coords: bool = False) -> np.ndarray:
     """Return the depth values of the mesh.
 
-    For 2D, the last non-flat dimension is used as the vertical axis, for 3D,
-    the z-axes is used.
+    For 2D, the last axis of the plane wherein the mesh is lying is used as the
+    vertical axis (i.e. y if the mesh is in the xy-plane, z if it is in the
+    xz-plane), for 3D, the z-axes is used.
     If `use_coords` is True, returns the negative coordinate value of the
     vertical axis. Otherwise, the vertical distance to the top facing edges /
     surfaces are returned.
@@ -26,18 +26,18 @@ def depth(mesh: pv.UnstructuredGrid, use_coords: bool = False) -> np.ndarray:
     if mesh.volume > 0:
         # prevents inner edge (from holes) to be detected as a top boundary
         edges = mesh.extract_surface().connectivity("point_seed", point_ids=[0])
-        top_id = 2
+        vertical_dim = 2
         if use_coords:
-            return -mesh.points[:, top_id]
-        point_upwards = edges.cell_normals[..., top_id] > 0
+            return -mesh.points[:, vertical_dim]
+        point_upwards = edges.cell_normals[..., vertical_dim] > 0
         top_cells = point_upwards
     else:
         mean_normal = np.abs(
             np.mean(mesh.extract_surface().cell_normals, axis=0)
         )
-        top_id = np.delete([0, 1, 2], int(np.argmax(mean_normal)))[-1]
+        vertical_dim = np.delete([0, 1, 2], int(np.argmax(mean_normal)))[-1]
         if use_coords:
-            return -mesh.points[:, top_id]
+            return -mesh.points[:, vertical_dim]
         # prevents inner edge (from holes) to be detected as a top boundary
         edges = mesh.extract_feature_edges().connectivity(
             "point_seed", point_ids=[0]
@@ -49,16 +49,23 @@ def depth(mesh: pv.UnstructuredGrid, use_coords: bool = False) -> np.ndarray:
         edge_centers = edges.cell_centers().points
         adj_cells = [mesh.find_closest_cell(point) for point in edge_centers]
         adj_cell_centers = mesh.extract_cells(adj_cells).cell_centers().points
-        are_above = edge_centers[..., top_id] > adj_cell_centers[..., top_id]
+        are_above = (
+            edge_centers[..., vertical_dim]
+            > adj_cell_centers[..., vertical_dim]
+        )
         are_non_vertical = np.asarray(edge_horizontal_extent) > 1e-12
         top_cells = are_above & are_non_vertical
     top = edges.extract_cells(top_cells)
     eucl_distance_projected_top_points = np.sum(
-        np.abs(np.delete(mesh.points[:, None] - top.points, top_id, axis=-1)),
+        np.abs(
+            np.delete(mesh.points[:, None] - top.points, vertical_dim, axis=-1)
+        ),
         axis=-1,
     )
     matching_top = np.argmin(eucl_distance_projected_top_points, axis=-1)
-    return np.abs(mesh.points[..., top_id] - top.points[matching_top, top_id])
+    return np.abs(
+        mesh.points[..., vertical_dim] - top.points[matching_top, vertical_dim]
+    )
 
 
 def p_fluid(mesh: pv.UnstructuredGrid) -> PlainQuantity:
@@ -74,11 +81,11 @@ def p_fluid(mesh: pv.UnstructuredGrid) -> PlainQuantity:
     where `h` is the depth below surface. If "depth" is not given in the mesh,
     it is calculated via :py:func:`ogstools.propertylib.mesh_dependent.depth`.
     """
-    qty = u_reg.Quantity
+    Qty = u_reg.Quantity
     if "pressure" in mesh.point_data:
-        return qty(mesh["pressure"], "Pa")
+        return Qty(mesh["pressure"], "Pa")
     _depth = mesh["depth"] if "depth" in mesh.point_data else depth(mesh)
-    return qty(1000, "kg/m^3") * qty(9.81, "m/s^2") * qty(_depth, "m")
+    return Qty(1000, "kg/m^3") * Qty(9.81, "m/s^2") * Qty(_depth, "m")
 
 
 def fluid_pressure_criterion(
@@ -97,8 +104,8 @@ def fluid_pressure_criterion(
     :py:func:`ogstools.propertylib.mesh_dependent.p_fluid`.
     """
 
-    qty = u_reg.Quantity
-    sigma = -qty(mesh[mesh_property.data_name], mesh_property.data_unit)
+    Qty = u_reg.Quantity
+    sigma = -Qty(mesh[mesh_property.data_name], mesh_property.data_unit)
     return p_fluid(mesh) - eigenvalues(sigma)[..., 0]
 
 
@@ -115,12 +122,21 @@ def dilatancy_critescu(
 
         F_{dil} = \\frac{\\tau_{oct}}{\\sigma_0} - a \\left( \\frac{\\sigma_m}{\\sigma_0} \\right)^2 - b \\frac{\\sigma_m}{\\sigma_0}
 
+    for total stresses and defined as:
+
+    .. math::
+
+        F'_{dil} = \\frac{\\tau_{oct}}{\\sigma_0} - a \\left( \\frac{\\sigma'_m}{\\sigma_0} \\right)^2 - b \\frac{\\sigma'_m}{\\sigma_0}
+
+    for effective stresses
+    (uses :func:`~ogstools.propertylib.mesh_dependent.p_fluid`).
+
     <https://www.sciencedirect.com/science/article/pii/S0360544222000512?via%3Dihub>
     """
 
-    qty = u_reg.Quantity
-    sigma = -qty(mesh[mesh_property.data_name], mesh_property.data_unit)
-    sigma_0 = qty(1, "MPa")
+    Qty = u_reg.Quantity
+    sigma = -Qty(mesh[mesh_property.data_name], mesh_property.data_unit)
+    sigma_0 = Qty(1, "MPa")
     sigma_m = mean(sigma)
     if effective:
         sigma_m -= p_fluid(mesh)
@@ -130,17 +146,6 @@ def dilatancy_critescu(
     )
 
 
-dilatancy_critescu_eff = partial(dilatancy_critescu, effective=True)
-"""Return the dilatancy criterion defined as:
-
-.. math::
-
-    F'_{dil} = \\frac{\\tau_{oct}}{\\sigma_0} - a \\left( \\frac{\\sigma'_m}{\\sigma_0} \\right)^2 - b \\frac{\\sigma'_m}{\\sigma_0}
-
-<https://www.sciencedirect.com/science/article/pii/S0360544222000512?via%3Dihub>
-"""
-
-
 def dilatancy_alkan(
     mesh: pv.UnstructuredGrid,
     mesh_property: Property,
@@ -153,25 +158,23 @@ def dilatancy_alkan(
 
         F_{dil} = \\tau_{oct} - \\tau_{max} \\cdot b \\frac{\\sigma'_m}{\\sigma_0 + b \\cdot \\sigma'_m}
 
+    for total stresses and defined as:
+
+    .. math::
+
+        F_{dil} = \\tau_{oct} - \\tau_{max} \\cdot b \\frac{\\sigma'_m}{\\sigma_0 + b \\cdot \\sigma'_m}
+
+    for effective stresses
+    (uses :func:`~ogstools.propertylib.mesh_dependent.p_fluid`).
+
     <https://www.sciencedirect.com/science/article/pii/S1365160906000979>
     """
 
-    qty = u_reg.Quantity
-    sigma = -qty(mesh[mesh_property.data_name], mesh_property.data_unit)
-    tau_max = qty(33, "MPa")
+    Qty = u_reg.Quantity
+    sigma = -Qty(mesh[mesh_property.data_name], mesh_property.data_unit)
+    tau_max = Qty(33, "MPa")
     sigma_m = mean(sigma)
     if effective:
         sigma_m -= p_fluid(mesh)
     tau = octahedral_shear(sigma)
-    return tau - tau_max * (b * sigma_m / (qty(1, "MPa") + b * sigma_m))
-
-
-dilatancy_alkan_eff = partial(dilatancy_alkan, effective=True)
-"""Return the dilatancy criterion defined as:
-
-.. math::
-
-    F_{dil} = \\tau_{oct} - \\tau_{max} \\cdot b \\frac{\\sigma'_m}{\\sigma_0 + b \\cdot \\sigma'_m}
-
-<https://www.sciencedirect.com/science/article/pii/S1365160906000979>
-"""
+    return tau - tau_max * (b * sigma_m / (Qty(1, "MPa") + b * sigma_m))
diff --git a/ogstools/propertylib/presets.py b/ogstools/propertylib/presets.py
index 139faac875debf1d1ee142f1cd3480c04bdd578a..f53b6c17b2813509e2f29c6303336b980f5a9270 100644
--- a/ogstools/propertylib/presets.py
+++ b/ogstools/propertylib/presets.py
@@ -4,8 +4,11 @@
 ".. seealso:: :py:mod:`ogstools.propertylib.tensor_math`"
 """
 
+from functools import partial
 from typing import Optional
 
+import pandas as pd
+
 from . import mesh_dependent, tensor_math
 from .custom_colormaps import integrity_cmap, temperature_cmap
 from .matrix import Matrix
@@ -99,17 +102,11 @@ dilatancy_critescu = Scalar(
     cmap=integrity_cmap,
     bilinear_cmap=True,
 )
-dilatancy_critescu_eff = Scalar(
-    data_name="sigma",
-    data_unit="Pa",
-    output_unit="",
+dilatancy_critescu_eff = dilatancy_critescu.replace(
     output_name="effective_dilatancy_criterion",
-    mask=M_MASK,
-    func=mesh_dependent.dilatancy_critescu_eff,
-    mesh_dependent=True,
-    cmap=integrity_cmap,
-    bilinear_cmap=True,
+    func=partial(mesh_dependent.dilatancy_critescu, effective=True),
 )
+
 dilatancy_alkan = Scalar(
     data_name="sigma",
     data_unit="Pa",
@@ -121,17 +118,11 @@ dilatancy_alkan = Scalar(
     cmap=integrity_cmap,
     bilinear_cmap=True,
 )
-dilatancy_alkan_eff = Scalar(
-    data_name="sigma",
-    data_unit="Pa",
-    output_unit="MPa",
+dilatancy_alkan_eff = dilatancy_alkan.replace(
     output_name="effective_dilatancy_criterion",
-    mask=M_MASK,
-    func=mesh_dependent.dilatancy_alkan_eff,
-    mesh_dependent=True,
-    cmap=integrity_cmap,
-    bilinear_cmap=True,
+    func=partial(mesh_dependent.dilatancy_alkan, effective=True),
 )
+
 fluid_pressure_crit = Scalar(
     data_name="sigma",
     data_unit="Pa",
@@ -167,3 +158,27 @@ def get_preset(property_name: str, shape: Optional[tuple] = None) -> Property:
     if shape[1] in [2, 3]:
         return Vector(property_name)
     return Matrix(property_name)
+
+
+def get_dataframe() -> pd.DataFrame:
+    data = [
+        "preset,data_name,data_unit,output_unit,output_name,type".split(",")
+    ]
+    for preset_name, preset_value in globals().items():
+        if isinstance(preset := preset_value, Property):
+            data += [
+                [
+                    preset_name,
+                    preset.data_name,
+                    preset.data_unit,
+                    preset.output_unit,
+                    preset.output_name,
+                    preset.type_name,
+                ]
+            ]
+
+    return (
+        pd.DataFrame(data[1:], columns=data[0])
+        .sort_values(["data_name", "preset"])
+        .set_index("preset")
+    )
diff --git a/ogstools/propertylib/property.py b/ogstools/propertylib/property.py
index fe83d01dfc42c5ef893aad41b29f3fb77b5ea5b7..c61a6c8120e8fac14d5013ae35e789c88e6cc6e5 100644
--- a/ogstools/propertylib/property.py
+++ b/ogstools/propertylib/property.py
@@ -33,7 +33,8 @@ class Property:
     mask: str = ""
     """The name of the mask data in the dataset."""
     func: Callable = identity
-    """The function to be applied on the data."""
+    """The function to be applied on the data.
+       .. seealso:: :meth:`~ogstools.propertylib.Property.__call__`"""
     mesh_dependent: bool = False
     """If the function to be applied is dependent on the mesh itself"""
     process_with_units: bool = False
@@ -90,27 +91,30 @@ class Property:
         """
         Return the transformed data values.
 
-        Apply property function, convert from data_unit to output_unit and
-        return the values, optionally with the unit.
+        Converts the data from data_unit to output_unit and apply a function
+        the transformation function of this property. The result is returned by
+        default without units. if `strip_unit` is False, a quantity is returned.
 
-        :param vals: The input data values.
-
-        :returns: The transformed data values.
+        Note:
+        If `self.mesh_dependent` is True, `self.func` is applied directly to the
+        DataSet. Otherwise, it is determined by `self.process_with_units` if the
+        data is passed to the function with units (i.e. as a pint quantity) or
+        without.
         """
-        qty, _du, _ou = u_reg.Quantity, self.data_unit, self.output_unit
+        Qty, d_u, o_u = u_reg.Quantity, self.data_unit, self.output_unit
         if self.mesh_dependent:
             if isinstance(data, pv.DataSet):
-                result = qty(self.func(data, self), _ou)
+                result = Qty(self.func(data, self), o_u)
             else:
                 msg = "This property can only be evaluated on a mesh."
                 raise TypeError(msg)
         else:
             if isinstance(data, pv.DataSet):
-                result = qty(self.func(qty(self.get_data(data), _du)), _ou)
+                result = Qty(self.func(Qty(self._get_data(data), d_u)), o_u)
             elif self.process_with_units:
-                result = qty(self.func(qty(data, _du)), _ou)
+                result = Qty(self.func(Qty(data, d_u)), o_u)
             else:
-                result = qty(qty(self.func(np.asarray(data)), _du), _ou)
+                result = Qty(Qty(self.func(np.asarray(data)), d_u), o_u)
         return result.magnitude if strip_unit else result
 
     def get_output_unit(self) -> str:
@@ -142,13 +146,14 @@ class Property:
         return self
 
     def mask_used(self, mesh: pv.UnstructuredGrid) -> bool:
+        "Check whether the mesh contains the mask of this property."
         return (
             not self.is_mask()
             and self.mask in mesh.cell_data
             and (len(mesh.cell_data[self.mask]) != 0)
         )
 
-    def get_data(
+    def _get_data(
         self, mesh: pv.UnstructuredGrid, masked: bool = True
     ) -> pv.UnstructuredGrid:
         """Get the data associated with a scalar or vector property from a mesh."""
diff --git a/ogstools/propertylib/tensor_math.py b/ogstools/propertylib/tensor_math.py
index 78a4d8cea05b20b7492e3c3b9fe2d8d8ec857d9c..599a5a78a991fe6fb19ec86f17271d97e702e589 100644
--- a/ogstools/propertylib/tensor_math.py
+++ b/ogstools/propertylib/tensor_math.py
@@ -103,7 +103,7 @@ def frobenius_norm(val: ValType) -> ValType:
     return np.linalg.norm(sym_tensor_to_mat(val), axis=(-2, -1))
 
 
-def I1(vals: ValType) -> ValType:  # pylint: disable=invalid-name
+def invariant_1(vals: ValType) -> ValType:
     """Return the first invariant.
 
     :math:`I1 = tr(\\mathbf{\\sigma})`
@@ -111,7 +111,7 @@ def I1(vals: ValType) -> ValType:  # pylint: disable=invalid-name
     return trace(vals)
 
 
-def I2(vals: ValType) -> ValType:  # pylint: disable=invalid-name
+def invariant_2(vals: ValType) -> ValType:
     """Return the second invariant.
 
     :math:`I2 = \\frac{1}{2} \\left[(tr(\\mathbf{\\sigma}))^2 - tr(\\mathbf{\\sigma}^2) \\right]`
@@ -119,7 +119,7 @@ def I2(vals: ValType) -> ValType:  # pylint: disable=invalid-name
     return 0.5 * (trace(vals) ** 2 - trace(vals**2))
 
 
-def I3(vals: ValType) -> ValType:  # pylint: disable=invalid-name
+def invariant_3(vals: ValType) -> ValType:
     """Return the third invariant.
 
     :math:`I3 = det(\\mathbf{\\sigma})`
@@ -133,7 +133,7 @@ def mean(vals: ValType) -> ValType:
 
     :math:`\\pi = \\frac{1}{3} I1`
     """
-    return (1.0 / 3.0) * I1(vals)
+    return (1.0 / 3.0) * invariant_1(vals)
 
 
 def effective_pressure(vals: ValType) -> ValType:
@@ -167,7 +167,7 @@ def deviator(vals: ValType) -> ValType:
     return vals - hydrostatic_component(vals)
 
 
-def J1(vals: ValType) -> ValType:  # pylint: disable=invalid-name
+def deviator_invariant_1(vals: ValType) -> ValType:
     """Return the first invariant of the deviator.
 
     :math:`J1 = 0`
@@ -175,7 +175,7 @@ def J1(vals: ValType) -> ValType:  # pylint: disable=invalid-name
     return trace(deviator(vals))
 
 
-def J2(vals: ValType) -> ValType:  # pylint: disable=invalid-name
+def deviator_invariant_2(vals: ValType) -> ValType:
     """Return the second invariant of the deviator.
 
     :math:`J2 = \\frac{1}{2} tr(\\mathbf{s}^2)`
@@ -183,7 +183,7 @@ def J2(vals: ValType) -> ValType:  # pylint: disable=invalid-name
     return 0.5 * trace(deviator(vals) ** 2)
 
 
-def J3(vals: ValType) -> ValType:  # pylint: disable=invalid-name
+def deviator_invariant_3(vals: ValType) -> ValType:
     """Return the third invariant of the deviator.
 
     :math:`J3 = \\frac{1}{3} tr(\\mathbf{s}^3)`
@@ -196,7 +196,7 @@ def octahedral_shear(vals: ValType) -> ValType:
 
     :math:`\\tau_{oct} = \\sqrt{\\frac{2}{3} J2}`
     """
-    return np.sqrt((2.0 / 3.0) * J2(vals))
+    return np.sqrt((2.0 / 3.0) * deviator_invariant_2(vals))
 
 
 def von_mises(vals: ValType) -> ValType:
@@ -204,7 +204,7 @@ def von_mises(vals: ValType) -> ValType:
 
     :math:`\\sigma_{Mises} = \\sqrt{3 J2}`
     """
-    return np.sqrt(3.0 * J2(vals))
+    return np.sqrt(3.0 * deviator_invariant_2(vals))
 
 
 def qp_ratio(vals: ValType) -> ValType:
diff --git a/ogstools/propertylib/vector.py b/ogstools/propertylib/vector.py
index a5a2b73dc2c2fc327335955f36a54a4a2fba4ec3..25abd336fa89bfe8f211626a6b98a9f9e39cc0f6 100644
--- a/ogstools/propertylib/vector.py
+++ b/ogstools/propertylib/vector.py
@@ -12,7 +12,7 @@ ValType = Union[PlainQuantity, np.ndarray]
 
 
 def vector_norm(vals: ValType) -> ValType:
-    "Return the magnitudes."
+    ":returns: The norm of the vector."
     if isinstance(vals, PlainQuantity):
         unit = vals.units
         vals = vals.magnitude
@@ -61,9 +61,7 @@ class VectorList(Property):
     """Represent a list of vector properties of a dataset."""
 
     def __getitem__(self, index: int) -> Vector:
-        """
-        Get a vector property as a component of the vectorlist property.
-        """
+        ":returns: A vector property as a component of the vectorlist property."
         return Vector.from_property(
             self,
             output_name=self.output_name + f"_{index}",
diff --git a/pyproject.toml b/pyproject.toml
index 292e85a3735f5e3cc4550fa1d86dac51cf2ea9a2..d4253813d11c0f99e7cfbaae4734cd50dc9da821 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -49,7 +49,7 @@ feflow2ogs = 'ogstools.feflowlib._cli:cli'
 
 [project.optional-dependencies]
 dev = ["pre-commit>=2.20", "build", "black"]
-test = ["pytest", "coverage", "gmsh", "ogs6py"]
+test = ["pytest", "coverage", "gmsh", "ogs6py", "parameterized"]
 docs = [
   "sphinx",
   "sphinx-argparse",
diff --git a/tests/test_mechanics.py b/tests/test_mechanics.py
index 611eaba7fd242d8f79c29da4e260650753e63b30..d32072841d0be1f8e7ec45aa43f144f66b8bd5b6 100644
--- a/tests/test_mechanics.py
+++ b/tests/test_mechanics.py
@@ -3,127 +3,127 @@
 import unittest
 
 import numpy as np
+from parameterized import parameterized
 
 from ogstools.propertylib import tensor_math
 from ogstools.propertylib.tensor_math import sym_tensor_to_mat
 
 
+def assert_allclose(vals1: np.ndarray, vals2: np.ndarray, rtol=1e-7, atol=1e-9):
+    """Assert the equality of two arrays."""
+    np.testing.assert_allclose(vals1, vals2, verbose=True, rtol=rtol, atol=atol)
+
+
 class MechanicsTest(unittest.TestCase):
     """Test case for physical properties."""
 
     rng = np.random.default_rng()
-    N_SAMPLES = 100000
-
-    def equality(
-        self, vals1: np.ndarray, vals2: np.ndarray, rtol=1e-7, atol=1e-9
-    ):
-        """Assert the equality of two arrays."""
-        np.testing.assert_allclose(
-            vals1, vals2, verbose=True, rtol=rtol, atol=atol
-        )
 
-    def test_frobenius_norm(self):
+    def generate_random_sig(self, symten_len: int):
+        """Generate random stress matrix."""
+        return self.rng.random((100000, symten_len)) * 1e6
+
+    @parameterized.expand([(4,), (6,)])
+    def test_frobenius_norm(self, symten_len: int):
         """Test Frobenius norm."""
-        for symten_len in [4, 6]:
-            sig = self.rng.random((self.N_SAMPLES, symten_len)) * 1e6
-            sig_mat = sym_tensor_to_mat(sig)
-            frob2 = np.sqrt(
-                tensor_math.trace(
-                    np.diagonal(
-                        np.transpose(sig_mat, (0, 2, 1)) @ sig_mat, 0, 2
-                    )
-                )
+        sig = self.generate_random_sig(symten_len)
+        sig_mat = sym_tensor_to_mat(sig)
+        frob2 = np.sqrt(
+            tensor_math.trace(
+                np.diagonal(np.transpose(sig_mat, (0, 2, 1)) @ sig_mat, 0, 2)
             )
-            self.equality(tensor_math.frobenius_norm(sig), frob2)
+        )
+        assert_allclose(tensor_math.frobenius_norm(sig), frob2)
 
-    def test_I1(self):
+    @parameterized.expand([(4,), (6,)])
+    def test_invariant_1(self, symten_len: int):
         """Test first invariant."""
-        for symten_len in [4, 6]:
-            sig = self.rng.random((self.N_SAMPLES, symten_len)) * 1e6
-            self.equality(
-                tensor_math.I1(sig),
-                tensor_math.trace(tensor_math.eigenvalues(sig)),
-            )
+        sig = self.generate_random_sig(symten_len)
+        assert_allclose(
+            tensor_math.invariant_1(sig),
+            tensor_math.trace(tensor_math.eigenvalues(sig)),
+        )
 
-    def test_I2(self):
+    @parameterized.expand([(4,), (6,)])
+    def test_invariant_2(self, symten_len: int):
         """Test second invariant."""
-        for symten_len in [4, 6]:
-            sig = self.rng.random((self.N_SAMPLES, symten_len)) * 1e6
-            eig_vals = tensor_math.eigenvalues(sig)
-            self.equality(
-                tensor_math.I2(sig),
-                np.sum(eig_vals * np.roll(eig_vals, 1, axis=-1), axis=-1),
-            )
+        sig = self.generate_random_sig(symten_len)
+        eig_vals = tensor_math.eigenvalues(sig)
+        assert_allclose(
+            tensor_math.invariant_2(sig),
+            np.sum(eig_vals * np.roll(eig_vals, 1, axis=-1), axis=-1),
+        )
 
-    def test_I3(self):
+    @parameterized.expand([(4,), (6,)])
+    def test_invariant_3(self, symten_len: int):
         """Test third invariant."""
-        for symten_len in [4, 6]:
-            sig = self.rng.random((self.N_SAMPLES, symten_len)) * 1e6
-            eig_vals = tensor_math.eigenvalues(sig)
-            self.equality(tensor_math.I3(sig), np.prod(eig_vals, axis=-1))
+        sig = self.generate_random_sig(symten_len)
+        eig_vals = tensor_math.eigenvalues(sig)
+        assert_allclose(
+            tensor_math.invariant_3(sig), np.prod(eig_vals, axis=-1)
+        )
 
-    def test_J1(self):
+    @parameterized.expand([(4,), (6,)])
+    def test_deviator_invariant_1(self, symten_len: int):
         """Test first deviator invariant."""
-        for symten_len in [4, 6]:
-            sig = self.rng.random((self.N_SAMPLES, symten_len)) * 1e6
-            j1 = tensor_math.J1(sig)
-            self.equality(j1, np.zeros(j1.shape))
+        sig = self.generate_random_sig(symten_len)
+        j1 = tensor_math.deviator_invariant_1(sig)
+        assert_allclose(j1, np.zeros(j1.shape))
 
-    def test_J2(self):
+    @parameterized.expand([(4,), (6,)])
+    def test_deviator_invariant_2(self, symten_len: int):
         """Test second deviator invariant."""
-        for symten_len in [4, 6]:
-            sig = self.rng.random((self.N_SAMPLES, symten_len)) * 1e6
-            self.equality(
-                tensor_math.J2(sig),
-                0.5
-                * (
-                    tensor_math.trace(sig**2)
-                    - (1.0 / 3.0) * tensor_math.trace(sig) ** 2
-                ),
-            )
+        sig = self.generate_random_sig(symten_len)
+        assert_allclose(
+            tensor_math.deviator_invariant_2(sig),
+            0.5
+            * (
+                tensor_math.trace(sig**2)
+                - (1.0 / 3.0) * tensor_math.trace(sig) ** 2
+            ),
+        )
 
-    def test_J3(self):
+    @parameterized.expand([(4,), (6,)])
+    def test_deviator_invariant_3(self, symten_len: int):
         """Test third deviator invariant."""
-        for symten_len in [4, 6]:
-            sig = self.rng.random((self.N_SAMPLES, symten_len)) * 1e6
-            # not exactly sure why, but for stresses where the below condition
-            # is very close to zero, the error of this test shoots up.
-            # Probably some floating point precision issue.
-            mask = (
-                np.abs(
-                    tensor_math.trace(sig - tensor_math.mean(sig)[..., None])
-                )
-                > 1e-9
-            )
-            sig = sig[mask]
-            self.equality(
-                tensor_math.J3(sig),
-                (1.0 / 3.0)
-                * (
-                    tensor_math.trace(sig**3)
-                    - tensor_math.trace(sig**2) * tensor_math.trace(sig)
-                    + (2.0 / 9.0) * tensor_math.trace(sig) ** 3.0
-                ),
-            )
+        sig = self.generate_random_sig(symten_len)
+        # not exactly sure why, but for stresses where the below condition
+        # is very close to zero, the error of this test shoots up.
+        # Probably some floating point precision issue.
+        mask = (
+            np.abs(tensor_math.trace(sig - tensor_math.mean(sig)[..., None]))
+            > 1e-9
+        )
+        sig = sig[mask]
+        assert_allclose(
+            tensor_math.deviator_invariant_3(sig),
+            (1.0 / 3.0)
+            * (
+                tensor_math.trace(sig**3)
+                - tensor_math.trace(sig**2) * tensor_math.trace(sig)
+                + (2.0 / 9.0) * tensor_math.trace(sig) ** 3.0
+            ),
+        )
 
-    def test_von_mises(self):
+    @parameterized.expand([(4,), (6,)])
+    def test_von_mises(self, symten_len: int):
         """Test von Mises invariant."""
-        for symten_len in [4, 6]:
-            sig = self.rng.random((self.N_SAMPLES, symten_len)) * 1e6
-            ev = tensor_math.eigenvalues(sig)
-            self.equality(
-                tensor_math.von_mises(sig),
-                np.sqrt(0.5 * np.sum(np.square(ev - np.roll(ev, 1, -1)), -1)),
-            )
+        sig = self.generate_random_sig(symten_len)
+        ev = tensor_math.eigenvalues(sig)
+        assert_allclose(
+            tensor_math.von_mises(sig),
+            np.sqrt(0.5 * np.sum(np.square(ev - np.roll(ev, 1, -1)), -1)),
+        )
 
-    def test_octahedral_shear_stress(self):
+    @parameterized.expand([(4,), (6,)])
+    def test_octahedral_shear_stress(self, symten_len: int):
         """Test octahedral shear stress invariant."""
-        for symten_len in [4, 6]:
-            sig = self.rng.random((self.N_SAMPLES, symten_len)) * 1e6
-            self.equality(
-                tensor_math.octahedral_shear(sig),
-                (1.0 / 3.0)
-                * np.sqrt(
-                    2 * tensor_math.I1(sig) ** 2 - 6 * tensor_math.I2(sig)
-                ),
-            )
+        sig = self.generate_random_sig(symten_len)
+        assert_allclose(
+            tensor_math.octahedral_shear(sig),
+            (1.0 / 3.0)
+            * np.sqrt(
+                2 * tensor_math.invariant_1(sig) ** 2
+                - 6 * tensor_math.invariant_2(sig)
+            ),
+        )
diff --git a/tests/test_meshplotlib.py b/tests/test_meshplotlib.py
index 6e7911ef83d9bfbe9f63e9363b16e288c472dbc7..8df8486d581abf2a5fca1d49134637137e843d35 100644
--- a/tests/test_meshplotlib.py
+++ b/tests/test_meshplotlib.py
@@ -17,12 +17,12 @@ from ogstools.meshplotlib import (
 )
 from ogstools.meshplotlib.animation import animate, save_animation
 from ogstools.meshplotlib.core import get_ticklabels
-from ogstools.meshplotlib.levels import get_levels
+from ogstools.meshplotlib.levels import compute_levels
 from ogstools.meshplotlib.plot_features import plot_on_top
 from ogstools.meshplotlib.utils import justified_labels
 from ogstools.propertylib import Scalar, presets
 
-equality = partial(
+assert_allclose = partial(
     np.testing.assert_allclose, rtol=1e-7, atol=1e-100, verbose=True
 )
 
@@ -40,18 +40,26 @@ class MeshplotlibTest(unittest.TestCase):
 
     def test_levels(self):
         """Test levels calculation property."""
-        equality(get_levels(0.5, 10.1, 10), [0.5, *range(1, 11), 10.1])
-        equality(get_levels(293, 350, 10), [293, *range(295, 355, 5)])
-        equality(get_levels(1e-3, 1.2, 5), [1e-3, *np.arange(0.2, 1.4, 0.2)])
-        equality(get_levels(1e5, 9e6, 20), [1e5, *np.arange(5e5, 9.5e6, 5e5)])
-        equality(get_levels(1, 40, 20), [1, *range(2, 42, 2)])
-        equality(get_levels(0.0, 0.0, 10), [0.0, 0.0])
-        equality(get_levels(1e9, 1e9, 10), [1e9, 1e9])
+        assert_allclose(
+            compute_levels(0.5, 10.1, 10), [0.5, *range(1, 11), 10.1]
+        )
+        assert_allclose(
+            compute_levels(293, 350, 10), [293, *range(295, 355, 5)]
+        )
+        assert_allclose(
+            compute_levels(1e-3, 1.2, 5), [1e-3, *np.arange(0.2, 1.4, 0.2)]
+        )
+        assert_allclose(
+            compute_levels(1e5, 9e6, 20), [1e5, *np.arange(5e5, 9.5e6, 5e5)]
+        )
+        assert_allclose(compute_levels(1, 40, 20), [1, *range(2, 42, 2)])
+        assert_allclose(compute_levels(0.0, 0.0, 10), [0.0, 0.0])
+        assert_allclose(compute_levels(1e9, 1e9, 10), [1e9, 1e9])
 
     def test_ticklabels(self):
         def compare(lower, upper, precision, ref_labels, ref_offset=None):
             labels, offset = get_ticklabels(
-                np.asarray(get_levels(lower, upper, n_ticks=precision))
+                np.asarray(compute_levels(lower, upper, n_ticks=precision))
             )
             self.assertTrue(np.all(labels == ref_labels))
             self.assertEqual(offset, ref_offset)
diff --git a/tests/test_propertylib.py b/tests/test_propertylib.py
index 2a203cf732b5185e52c79c117e1b26f46a41cfbc..373c39af3601a5db6895fe1484a1a7fb7d01ec44 100644
--- a/tests/test_propertylib.py
+++ b/tests/test_propertylib.py
@@ -13,7 +13,7 @@ from ogstools.propertylib.mesh_dependent import depth
 from ogstools.propertylib.property import Scalar, u_reg
 from ogstools.propertylib.vector import Vector
 
-qty = u_reg.Quantity
+Qty = u_reg.Quantity
 
 
 class PhysicalPropertyTest(unittest.TestCase):
@@ -38,66 +38,66 @@ class PhysicalPropertyTest(unittest.TestCase):
 
     def test_temperature(self):
         """Test temperature property."""
-        self.equality(pp.temperature, 293.15, qty(20, "°C"))
-        self.equality(pp.temperature, [293.15, 303.15], qty([20, 30], "°C"))
+        self.equality(pp.temperature, 293.15, Qty(20, "°C"))
+        self.equality(pp.temperature, [293.15, 303.15], Qty([20, 30], "°C"))
 
     def test_pressure(self):
         """Test pressure property."""
-        self.equality(pp.pressure, 1e6, qty(1, "MPa"))
-        self.equality(pp.pressure, [1e6, 2e6], qty([1, 2], "MPa"))
+        self.equality(pp.pressure, 1e6, Qty(1, "MPa"))
+        self.equality(pp.pressure, [1e6, 2e6], Qty([1, 2], "MPa"))
 
     def test_velocity(self):
         """Test velocity property."""
-        self.equality(pp.velocity.magnitude, [3, 4], qty(5, "m/s"))
+        self.equality(pp.velocity.magnitude, [3, 4], Qty(5, "m/s"))
         self.equality(
-            pp.velocity.magnitude, [[3, 4], [1, 0]], qty([5, 1], "m/s")
+            pp.velocity.magnitude, [[3, 4], [1, 0]], Qty([5, 1], "m/s")
         )
 
     def test_displacement(self):
         """Test displacement property."""
-        self.equality(pp.displacement.magnitude, [3e-3, 4e-3], qty(5, "mm"))
+        self.equality(pp.displacement.magnitude, [3e-3, 4e-3], Qty(5, "mm"))
         u = np.array([[2, 3, 6], [1, 4, 8]]) * 1e-3
-        self.equality(pp.displacement.magnitude, u, qty([7.0, 9.0], "mm"))
+        self.equality(pp.displacement.magnitude, u, Qty([7.0, 9.0], "mm"))
 
     def test_strain(self):
         """Test strain property."""
         eps = np.array([1, 3, 9, 1, 2, 2]) * 1e-2
-        self.equality(pp.strain.magnitude, eps, qty(10, "%"))
-        self.equality(pp.strain.magnitude, [eps, eps], qty([10, 10], "%"))
-        self.equality(pp.strain.trace, eps, qty(13, "%"))
-        self.equality(pp.strain.trace, [eps, eps], qty([13, 13], "%"))
+        self.equality(pp.strain.magnitude, eps, Qty(10, "%"))
+        self.equality(pp.strain.magnitude, [eps, eps], Qty([10, 10], "%"))
+        self.equality(pp.strain.trace, eps, Qty(13, "%"))
+        self.equality(pp.strain.trace, [eps, eps], Qty([13, 13], "%"))
 
     def test_components(self):
         """Test strain components."""
         eps = np.array([0, 1, 2, 3, 4, 5]) * 1e-2
         u = np.array([0, 1, 2]) * 1e-3
         for i in range(len(eps)):
-            self.equality(pp.strain[i], eps, qty(i, "%"))
-            self.equality(pp.strain[i], [eps, eps], qty([i, i], "%"))
+            self.equality(pp.strain[i], eps, Qty(i, "%"))
+            self.equality(pp.strain[i], [eps, eps], Qty([i, i], "%"))
         for i in range(len(u)):
-            self.equality(pp.displacement[i], u, qty(i, "mm"))
-            self.equality(pp.displacement[i], [u, u], qty([i, i], "mm"))
+            self.equality(pp.displacement[i], u, Qty(i, "mm"))
+            self.equality(pp.displacement[i], [u, u], Qty([i, i], "mm"))
         assert pp.strain[0].bilinear_cmap is True
 
     def test_von_mises(self):
         """Test von_mises_stress property."""
         sig_3D = np.array([3, 1, 1, 1, 1, 1]) * 1e6
-        self.equality(pp.stress.von_Mises, sig_3D, qty(2, "MPa"))
-        self.equality(pp.stress.von_Mises, [sig_3D, sig_3D], qty([2, 2], "MPa"))
+        self.equality(pp.stress.von_Mises, sig_3D, Qty(2, "MPa"))
+        self.equality(pp.stress.von_Mises, [sig_3D, sig_3D], Qty([2, 2], "MPa"))
         sig_2D = np.array([2, 1, 1, 1]) * 1e6
-        self.equality(pp.stress.von_Mises, sig_2D, qty(1, "MPa"))
+        self.equality(pp.stress.von_Mises, sig_2D, Qty(1, "MPa"))
 
     def test_eff_pressure(self):
         """Test effective_pressure property."""
         sig = np.array([-1, -2, -3, 1, 1, 1]) * 1e6
-        self.equality(pp.effective_pressure, sig, qty(2, "MPa"))
-        self.equality(pp.effective_pressure, [sig, sig], qty([2, 2], "MPa"))
+        self.equality(pp.effective_pressure, sig, Qty(2, "MPa"))
+        self.equality(pp.effective_pressure, [sig, sig], Qty([2, 2], "MPa"))
 
     def test_qp_ratio(self):
         """Test qp_ratio property."""
         sig = np.array([4, 4, 1, 1, 1, 1]) * 1e6
-        self.equality(pp.stress.qp_ratio, sig, qty(-100, "percent"))
-        self.equality(pp.stress.qp_ratio, [sig] * 2, qty([-100] * 2, "percent"))
+        self.equality(pp.stress.qp_ratio, sig, Qty(-100, "percent"))
+        self.equality(pp.stress.qp_ratio, [sig] * 2, Qty([-100] * 2, "percent"))
 
     def test_depth_2D(self):
         mesh = mesh_mechanics
@@ -135,24 +135,24 @@ class PhysicalPropertyTest(unittest.TestCase):
                 pp.stress.eigenvectors[i].magnitude(sig), 1.0
             )
         self.assertGreater(pp.stress.det(sig), 0)
-        self.assertGreater(pp.stress.I1(sig), 0)
-        self.assertGreater(pp.stress.I2(sig), 0)
-        self.assertGreater(pp.stress.I3(sig), 0)
+        self.assertGreater(pp.stress.invariant_1(sig), 0)
+        self.assertGreater(pp.stress.invariant_2(sig), 0)
+        self.assertGreater(pp.stress.invariant_3(sig), 0)
         self.assertGreater(pp.stress.mean(sig), 0)
         self.assertGreater(pp.stress.deviator.magnitude(sig), 0)
-        self.assertGreater(pp.stress.J1(sig), 0)
-        self.assertGreater(pp.stress.J2(sig), 0)
-        self.assertGreater(pp.stress.J3(sig), 0)
+        self.assertGreater(pp.stress.deviator_invariant_1(sig), 0)
+        self.assertGreater(pp.stress.deviator_invariant_2(sig), 0)
+        self.assertGreater(pp.stress.deviator_invariant_3(sig), 0)
         self.assertGreater(pp.stress.octahedral_shear(sig), 0)
 
     def test_simple(self):
         """Test call functionality."""
-        self.assertEqual(pp.temperature(273.15, strip_unit=False), qty(0, "°C"))
+        self.assertEqual(pp.temperature(273.15, strip_unit=False), Qty(0, "°C"))
         self.assertEqual(
-            pp.displacement[0]([1, 2, 3], strip_unit=False), qty(1, "m")
+            pp.displacement[0]([1, 2, 3], strip_unit=False), Qty(1, "m")
         )
         self.assertEqual(
-            pp.displacement([1, 2, 3], strip_unit=False)[1], qty(2, "m")
+            pp.displacement([1, 2, 3], strip_unit=False)[1], Qty(2, "m")
         )
 
     def test_values(self):