diff --git a/extreme_estimator/estimator/full_estimator.py b/extreme_estimator/estimator/full_estimator.py
index d6df3dd7aba67c2e1efbc4bfd24a576970e2ac38..bd3e1618185eadd8a3f0983a7911ac42101e412d 100644
--- a/extreme_estimator/estimator/full_estimator.py
+++ b/extreme_estimator/estimator/full_estimator.py
@@ -1,4 +1,7 @@
 from extreme_estimator.extreme_models.margin_model.abstract_margin_model import AbstractMarginModel
+from extreme_estimator.extreme_models.margin_model.margin_function.independent_margin_function import \
+    LinearMarginFunction
+from extreme_estimator.extreme_models.margin_model.smooth_margin_model import LinearMarginModel
 from extreme_estimator.extreme_models.max_stable_model.abstract_max_stable_model import AbstractMaxStableModel
 from extreme_estimator.estimator.abstract_estimator import AbstractEstimator
 from extreme_estimator.estimator.margin_estimator import SmoothMarginEstimator
@@ -12,7 +15,7 @@ class AbstractFullEstimator(AbstractEstimator):
 
 class SmoothMarginalsThenUnitaryMsp(AbstractFullEstimator):
 
-    def __init__(self, dataset: AbstractDataset, margin_model: AbstractMarginModel,
+    def __init__(self, dataset: AbstractDataset, margin_model: LinearMarginModel,
                  max_stable_model: AbstractMaxStableModel):
         super().__init__(dataset)
         # Instantiate the two associated estimators
@@ -36,9 +39,25 @@ class FullEstimatorInASingleStep(AbstractFullEstimator):
     pass
 
 
-class FullEstimatorInASingleStepWithSmoothMarginals(AbstractFullEstimator):
+class FullEstimatorInASingleStepWithSmoothMargin(AbstractFullEstimator):
     """The method of Gaume, check if its method is in a single step or not"""
-    pass
+
+    def __init__(self, dataset: AbstractDataset, margin_model: LinearMarginModel,
+                 max_stable_model: AbstractMaxStableModel):
+        super().__init__(dataset)
+        self.max_stable_model = max_stable_model
+        self.smooth_margin_function_to_fit = margin_model.margin_function_start_fit
+
+    def _fit(self):
+        # todo: specify the shape of the margin
+        # Estimate the margin
+        self.max_stable_params_fitted = self.max_stable_model.fitmaxstab(
+            maxima_frech=self.dataset.maxima_frech,
+            df_coordinates=self.dataset.df_coordinates,
+            fit_marge=True,
+            fit_marge_form_dict=self.smooth_margin_function_to_fit.fit_marge_form_dict,
+            margin_start_dict=self.smooth_margin_function_to_fit.margin_start_dict
+        )
 
 
 class PointwiseAndThenUnitaryMsp(AbstractFullEstimator):
diff --git a/extreme_estimator/estimator/max_stable_estimator.py b/extreme_estimator/estimator/max_stable_estimator.py
index b663ac670d7650d4740639eeaf72722f61c8233c..4ca92d18ee48b44a5bee8d581326b78d19a231ea 100644
--- a/extreme_estimator/estimator/max_stable_estimator.py
+++ b/extreme_estimator/estimator/max_stable_estimator.py
@@ -19,7 +19,8 @@ class MaxStableEstimator(AbstractMaxStableEstimator):
         assert self.dataset.maxima_frech is not None
         self.max_stable_params_fitted = self.max_stable_model.fitmaxstab(
             maxima_frech=self.dataset.maxima_frech,
-            coord=self.dataset.coordinates)
+            df_coordinates=self.dataset.spatial_coordinates.df_coordinates)
+            # coord=self.dataset.coordinates)
 
     def _error(self, true_max_stable_params: dict):
         absolute_errors = {param_name: np.abs(param_true_value - self.max_stable_params_fitted[param_name])
diff --git a/extreme_estimator/extreme_models/margin_model/abstract_margin_model.py b/extreme_estimator/extreme_models/margin_model/abstract_margin_model.py
index fea9bfccbc5e6fa747f92c57e24a5ae3ae9d9621..4d4f62625a0f70948521894435857ae920ce4bcd 100644
--- a/extreme_estimator/extreme_models/margin_model/abstract_margin_model.py
+++ b/extreme_estimator/extreme_models/margin_model/abstract_margin_model.py
@@ -28,6 +28,7 @@ class AbstractMarginModel(AbstractModel):
     @classmethod
     def convert_maxima(cls, convertion_r_function, maxima: np.ndarray, coordinates: np.ndarray,
                        margin_function: AbstractMarginFunction):
+        assert isinstance(coordinates, np.ndarray)
         assert len(maxima) == len(coordinates)
         converted_maxima = []
         for x, coordinate in zip(maxima, coordinates):
@@ -58,9 +59,7 @@ class AbstractMarginModel(AbstractModel):
             maxima_gev.append(x_gev)
         return np.array(maxima_gev)
 
-    # Fitting methods
+    # Fitting methods needs to be defined in child classes
 
     def fitmargin_from_maxima_gev(self, maxima_gev: np.ndarray, coordinates: np.ndarray) -> AbstractMarginFunction:
         pass
-
-    # Define the method to sample/fit a single gev
diff --git a/extreme_estimator/extreme_models/margin_model/margin_function/independent_margin_function.py b/extreme_estimator/extreme_models/margin_model/margin_function/independent_margin_function.py
index 18fbd21ecd9fe8b6bc2ae2b55b7950cd017f1ee0..a9f416fa3228082c02985e0529dd00fdbed30d18 100644
--- a/extreme_estimator/extreme_models/margin_model/margin_function/independent_margin_function.py
+++ b/extreme_estimator/extreme_models/margin_model/margin_function/independent_margin_function.py
@@ -41,7 +41,7 @@ class ConstantParamFunction(ParamFunction):
 
 class LinearOneAxisParamFunction(ParamFunction):
 
-    def __init__(self, linear_axis, coordinates_axis, start, end=0.0):
+    def __init__(self, linear_axis: int, coordinates_axis: np.ndarray, start: float, end: float = 0.0):
         self.linear_axis = linear_axis
         self.t_min = coordinates_axis.min()
         self.t_max = coordinates_axis.max()
@@ -63,6 +63,10 @@ class LinearMarginFunction(IndependentMarginFunction):
     def __init__(self, spatial_coordinates: AbstractSpatialCoordinates, default_params: GevParams,
                  gev_param_name_to_linear_axis: Dict[str, int]):
         super().__init__(spatial_coordinates, default_params)
+
+        # By default, set a constant function for all the params
+        self.gev_param_to_str_form = {gev_param_name: '1' for gev_param_name in GevParams.GEV_PARAM_NAMES}
+
         self.param_to_linear_dims = gev_param_name_to_linear_axis
         assert all([axis < np.ndim(spatial_coordinates.coordinates) for axis in gev_param_name_to_linear_axis.values()])
         # Initialize gev_parameter_to_param_function
@@ -76,3 +80,22 @@ class LinearMarginFunction(IndependentMarginFunction):
                 param_function = LinearOneAxisParamFunction(linear_axis=linear_axis, coordinates_axis=coordinates_axis,
                                                             start=self.default_params[gev_param_name])
             self.gev_param_name_to_param_function[gev_param_name] = param_function
+
+
+    @property
+    def fit_marge_form_dict(self):
+        """
+        Example:
+        loc.form = loc ~ E
+        scale.form = scale ~ N
+        shape.form = shape ~ E+N
+        :return:
+        """
+        # todo specify all functions
+        return {gev_param_name + '.form': gev_param_name + ' ~ ' + self.gev_param_to_str_form[gev_param_name]
+                for gev_param_name in GevParams.GEV_PARAM_NAMES}
+
+    @property
+    def margin_start_dict(self):
+        """Example for the names: locCoeff1     locCoeff2 """
+        return {gev_param_name + 'Coeff1': 0 for gev_param_name in GevParams.GEV_PARAM_NAMES}
diff --git a/extreme_estimator/extreme_models/margin_model/smooth_margin_model.py b/extreme_estimator/extreme_models/margin_model/smooth_margin_model.py
index 6a33d939a567af114610bfc45b2fba0653d5c9ff..b15b8c6dac1c75fc6b4d68e839d13523bb0a30ea 100644
--- a/extreme_estimator/extreme_models/margin_model/smooth_margin_model.py
+++ b/extreme_estimator/extreme_models/margin_model/smooth_margin_model.py
@@ -18,6 +18,9 @@ class LinearMarginModel(AbstractMarginModel):
                                                               default_params=GevParams.from_dict(self.params_start_fit),
                                                               gev_param_name_to_linear_axis=gev_param_name_to_linear_axis)
 
+    def fitmargin_from_maxima_gev(self, maxima_gev: np.ndarray, coordinates: np.ndarray) -> AbstractMarginFunction:
+        return self.margin_function_start_fit
+
 
 class ConstantMarginModel(LinearMarginModel):
 
@@ -33,8 +36,8 @@ class LinearShapeAxis0MarginModel(LinearMarginModel):
     def load_margin_functions(self, margin_function_class: type = None, gev_param_name_to_linear_axis=None):
         super().load_margin_functions({GevParams.GEV_SHAPE: 0})
 
-    def fitmargin_from_maxima_gev(self, maxima_gev: np.ndarray, coordinates: np.ndarray) -> AbstractMarginFunction:
-        return self.margin_function_start_fit
+    # def fitmargin_from_maxima_gev(self, maxima_gev: np.ndarray, coordinates: np.ndarray) -> AbstractMarginFunction:
+    #     pass
 
 
 if __name__ == '__main__':
diff --git a/extreme_estimator/extreme_models/max_stable_model/abstract_max_stable_model.py b/extreme_estimator/extreme_models/max_stable_model/abstract_max_stable_model.py
index 8c5a5f31e59ca89d7c3442cc7ea74bfc127ea401..1043f5bc51a3c9879a57ce9f26341b3e9e0323fc 100644
--- a/extreme_estimator/extreme_models/max_stable_model/abstract_max_stable_model.py
+++ b/extreme_estimator/extreme_models/max_stable_model/abstract_max_stable_model.py
@@ -1,7 +1,9 @@
+import pandas as pd
 from enum import Enum
 
 import numpy as np
 import rpy2
+import rpy2.robjects as ro
 from rpy2.robjects import ListVector
 
 from extreme_estimator.extreme_models.abstract_model import AbstractModel
@@ -17,20 +19,34 @@ class AbstractMaxStableModel(AbstractModel):
     def cov_mod_param(self):
         return {'cov.mod': self.cov_mod}
 
-    def fitmaxstab(self, maxima_frech: np.ndarray, coord: np.ndarray, fit_marge=False):
-        assert all([isinstance(arr, np.ndarray) for arr in [maxima_frech, coord]])
+    def fitmaxstab(self, maxima_frech: np.ndarray, df_coordinates: pd.DataFrame, fit_marge=False,
+                   fit_marge_form_dict=None, margin_start_dict=None):
+        assert isinstance(maxima_frech, np.ndarray)
+        assert isinstance(df_coordinates, pd.DataFrame)
+        if fit_marge:
+            assert fit_marge_form_dict is not None
+            assert margin_start_dict is not None
+
+        # Add the colnames to df_coordinates DataFrame to enable specification of the margin functions
+        df_coordinates = df_coordinates.copy()
+        df_coordinates.colnames = ro.StrVector(list(df_coordinates.columns))
+        # Transform the formula string representation into robjects.Formula("y ~ x")
         #  Specify the fit params
-        fit_params = {
-            'fit.marge': fit_marge,
-            'start': self.r.list(**self.params_start_fit),
-        }
+        fit_params = self.cov_mod_param.copy()
+        start_dict = self.params_start_fit
+        if fit_marge:
+            start_dict.update(margin_start_dict)
+            fit_params.update({k: ro.Formula(v) for k, v in fit_marge_form_dict.items()})
+        fit_params['start'] = self.r.list(**start_dict)
+        fit_params['fit.marge'] = fit_marge
         # Run the fitmaxstab in R
         # todo: find how to specify the optim function to use
+        coord = df_coordinates.values
+
         try:
-            res = self.r.fitmaxstab(np.transpose(maxima_frech), coord, **self.cov_mod_param,
-                                    **fit_params)  # type: ListVector
+            res = self.r.fitmaxstab(data=np.transpose(maxima_frech), coord=coord, **fit_params)  # type: ListVector
         except rpy2.rinterface.RRuntimeError as error:
-            raise Exception('Some R exception have been launched at RunTime: {}'.format(error.__repr__()))
+            raise Exception('Some R exception have been launched at RunTime: \n {}'.format(error.__repr__()))
         # todo: maybe if the convergence was not successful I could try other starting point several times
         # Retrieve the resulting fitted values
         fitted_values = res.rx2('fitted.values')
diff --git a/extreme_estimator/extreme_models/max_stable_model/max_stable_fit.R b/extreme_estimator/extreme_models/max_stable_model/max_stable_fit.R
index 5c0491e8b4b948f6df4f378097f7c7ab4fc91c2f..4daba7f105b904c578c7df2d1f429feced3f5235 100644
--- a/extreme_estimator/extreme_models/max_stable_model/max_stable_fit.R
+++ b/extreme_estimator/extreme_models/max_stable_model/max_stable_fit.R
@@ -9,24 +9,29 @@ if (call_main) {
     n.obs = 50
     n.site = 2
     coord <- matrix(rnorm(2*n.site, sd = sqrt(.2)), ncol = 2)
+    colnames(coord) = c("E", "N")
 
     #  Generate the data
     data <- rmaxstab(n.obs, coord, "gauss", cov11 = 100, cov12 = 25, cov22 = 220)
     # data <- rmaxstab(n.obs, coord, "brown", range = 3, smooth = 0.5)
     # data <- rmaxstab(n.obs, coord, "whitmat", nugget = 0.0, range = 3, smooth = 0.5)
     #  Fit back the data
-    # print(data)
+    # print(data)n
     # res = fitmaxstab(data, coord, "gauss", fit.marge=FALSE, )
     # res = fitmaxstab(data, coord, "brown")
     # res = fitmaxstab(data, coord, "whitmat", start=)
-    namedlist = list(cov11 = 1.0, cov12 = 1.2, cov22 = 2.2)
-    res = fitmaxstab(data=data, coord=coord, cov.mod="gauss", start=namedlist)
-    # res = fitmaxstab(data, coord, "whitmat", par())
-    # print(res)
-    # print(class(res))
-    gev2frech(x, loc, scale, shape, emp=FALSE)
-    frech2gev(x, loc, scale, shape)
-    # print(names(res))
+
+    loc.form = loc ~ 1
+    scale.form = scale ~ 1
+    shape.form = shape ~ 1
+
+
+    namedlist = list(cov11 = 1.0, cov12 = 1.2, cov22 = 2.2, locCoeff1=1.0, scaleCoeff1=1.0, shapeCoeff1=1.0)
+    res = fitmaxstab(data=data, coord=coord, cov.mod="gauss", start=namedlist, fit.marge=TRUE, loc.form=loc.form, scale.form=scale.form,shape.form=shape.form)
+
+    # namedlist = list(cov11 = 1.0, cov12 = 1.2, cov22 = 2.2)
+    # res = fitmaxstab(data=data, coord=coord, cov.mod="gauss", start=namedlist)
+
     for (name in names(res)){
         print(name)
         print(res[name])
diff --git a/extreme_estimator/extreme_models/max_stable_model/max_stable_fit.py b/extreme_estimator/extreme_models/max_stable_model/max_stable_fit.py
new file mode 100644
index 0000000000000000000000000000000000000000..cfb879503863c680f066a1d627c6d40d84f96390
--- /dev/null
+++ b/extreme_estimator/extreme_models/max_stable_model/max_stable_fit.py
@@ -0,0 +1,57 @@
+# test how to call the max stable method
+import pandas as pd
+
+import numpy as np
+
+from extreme_estimator.extreme_models.utils import get_loaded_r
+from extreme_estimator.gev.gev_mle_fit import GevMleFit
+import rpy2.robjects.numpy2ri as rpyn
+
+
+import rpy2.robjects as robjects
+
+def max_stable_fit():
+    r = get_loaded_r()
+    r("""
+    set.seed(42)
+    n.obs = 50
+    n.site = 2
+    coord <- matrix(rnorm(2*n.site, sd = sqrt(.2)), ncol = 2)
+    colnames(coord) = c("E", "N")
+
+    #  Generate the data
+    data <- rmaxstab(n.obs, coord, "gauss", cov11 = 100, cov12 = 25, cov22 = 220)
+
+
+    loc.form = loc ~ 1
+    scale.form = scale ~ 1
+    shape.form = shape ~ 1
+    
+    namedlist = list(cov11 = 1.0, cov12 = 1.2, cov22 = 2.2, locCoeff1=1.0, scaleCoeff1=1.0, shapeCoeff1=1.0)
+    # res = fitmaxstab(data=data, coord=coord, cov.mod="gauss", start=namedlist, fit.marge=TRUE, loc.form=loc.form, scale.form=scale.form,shape.form=shape.form)
+    """)
+
+    # coord = np.array(r['coord'])
+    data = r['data']
+    coord = pd.DataFrame(r['coord'])
+    coord.colnames = robjects.StrVector(['E', 'N'])
+
+    print(r['loc.form'])
+    print(type(r['loc.form']))
+    # x_gev = rpyn.numpy2ri(x_gev)
+    print(coord)
+
+    print(coord.colnames)
+
+    # res = r.fitmaxstab(data=data, coord=coord, covmod="gauss", start=namedlist, fit.marge=TRUE, loc.form=loc.form, scale.form=scale.form,shape.form=shape.form)
+
+
+
+    # m2.colnames = R.StrVector(['x', 'y'])
+    # res = r.fitmaxstab()
+    # mle_params = dict(r.attr(res, 'coef').items())
+    # print(mle_params)
+
+
+if __name__ == '__main__':
+    max_stable_fit()
diff --git a/extreme_estimator/extreme_models/utils.py b/extreme_estimator/extreme_models/utils.py
index 87a89fb947fb1504a02892e901c285e5c25441a6..513d50c7506a84f768a2a33082d9065a9b66f26f 100644
--- a/extreme_estimator/extreme_models/utils.py
+++ b/extreme_estimator/extreme_models/utils.py
@@ -1,13 +1,14 @@
 import os.path as op
+
 import rpy2.robjects as ro
-import pandas as pd
-import numpy as np
-import rpy2.robjects.numpy2ri as npr
+from rpy2.robjects import numpy2ri
+from rpy2.robjects import pandas2ri
 
 
 def get_loaded_r() -> ro.R:
     r = ro.r
-    ro.numpy2ri.activate()
+    numpy2ri.activate()
+    pandas2ri.activate()
     r.library('SpatialExtremes')
     return r
 
diff --git a/spatio_temporal_dataset/dataset/abstract_dataset.py b/spatio_temporal_dataset/dataset/abstract_dataset.py
index 33faaa6d5771fe11fa0618bd25b4b1be1b580440..a63ed182d556fd27c8202fe9774d6fa92878a19a 100644
--- a/spatio_temporal_dataset/dataset/abstract_dataset.py
+++ b/spatio_temporal_dataset/dataset/abstract_dataset.py
@@ -33,6 +33,10 @@ class AbstractDataset(object):
         # Merge dataframes with the maxima and with the coordinates
         return self.temporal_observations.df_maxima_gev.join(self.spatial_coordinates.df_coordinates)
 
+    @property
+    def df_coordinates(self):
+        return self.spatial_coordinates.df_coordinates
+
     @property
     def coordinates(self):
         return self.spatial_coordinates.coordinates
diff --git a/test/test_extreme_estimator/test_estimator/test_full_estimators.py b/test/test_extreme_estimator/test_estimator/test_full_estimators.py
index 49df744f0ded4bbefef5f84e2825a2e02bf2e4d4..938462e19b31ab450044b5e462dfc17702480593 100644
--- a/test/test_extreme_estimator/test_estimator/test_full_estimators.py
+++ b/test/test_extreme_estimator/test_estimator/test_full_estimators.py
@@ -1,7 +1,8 @@
 import unittest
 from itertools import product
 
-from extreme_estimator.estimator.full_estimator import SmoothMarginalsThenUnitaryMsp
+from extreme_estimator.estimator.full_estimator import SmoothMarginalsThenUnitaryMsp, \
+    FullEstimatorInASingleStepWithSmoothMargin
 from spatio_temporal_dataset.dataset.simulation_dataset import FullSimulatedDataset
 from spatio_temporal_dataset.spatial_coordinates.generated_coordinates import CircleCoordinatesRadius1
 from test.test_extreme_estimator.test_estimator.test_margin_estimators import TestSmoothMarginEstimator
@@ -10,16 +11,16 @@ from test.test_extreme_estimator.test_estimator.test_max_stable_estimators impor
 
 class TestFullEstimators(unittest.TestCase):
     DISPLAY = False
-    FULL_ESTIMATORS = [SmoothMarginalsThenUnitaryMsp]
+    FULL_ESTIMATORS = [SmoothMarginalsThenUnitaryMsp, FullEstimatorInASingleStepWithSmoothMargin][:]
 
     def setUp(self):
         super().setUp()
         self.spatial_coordinates = CircleCoordinatesRadius1.from_nb_points(nb_points=5, max_radius=1)
         self.max_stable_models = TestMaxStableEstimators.load_max_stable_models()
-        self.margin_models = TestSmoothMarginEstimator.load_margin_models(spatial_coordinates=self.spatial_coordinates)
+        self.smooth_margin_models = TestSmoothMarginEstimator.load_smooth_margin_models(spatial_coordinates=self.spatial_coordinates)
 
     def test_full_estimators(self):
-        for margin_model, max_stable_model in product(self.margin_models, self.max_stable_models):
+        for margin_model, max_stable_model in product(self.smooth_margin_models, self.max_stable_models):
             dataset = FullSimulatedDataset.from_double_sampling(nb_obs=10, margin_model=margin_model,
                                                                 spatial_coordinates=self.spatial_coordinates,
                                                                 max_stable_model=max_stable_model)
diff --git a/test/test_extreme_estimator/test_estimator/test_margin_estimators.py b/test/test_extreme_estimator/test_estimator/test_margin_estimators.py
index 9dcea3dcaef2861970b3cf0e4244f8bc0f70b94c..fe77b35ac48b9bcaa19c5f8faced344a5b8b345c 100644
--- a/test/test_extreme_estimator/test_estimator/test_margin_estimators.py
+++ b/test/test_extreme_estimator/test_estimator/test_margin_estimators.py
@@ -12,19 +12,19 @@ from spatio_temporal_dataset.spatial_coordinates.generated_coordinates import Ci
 class TestSmoothMarginEstimator(unittest.TestCase):
     DISPLAY = False
     MARGIN_TYPES = [ConstantMarginModel, LinearShapeAxis0MarginModel][1:]
-    MARGIN_ESTIMATORS = [SmoothMarginEstimator]
+    SMOOTH_MARGIN_ESTIMATORS = [SmoothMarginEstimator]
 
     def setUp(self):
         super().setUp()
         self.spatial_coordinates = CircleCoordinatesRadius1.from_nb_points(nb_points=5, max_radius=1)
-        self.margin_models = self.load_margin_models(spatial_coordinates=self.spatial_coordinates)
+        self.smooth_margin_models = self.load_smooth_margin_models(spatial_coordinates=self.spatial_coordinates)
 
     @classmethod
-    def load_margin_models(cls, spatial_coordinates):
+    def load_smooth_margin_models(cls, spatial_coordinates):
         return [margin_class(spatial_coordinates=spatial_coordinates) for margin_class in cls.MARGIN_TYPES]
 
     def test_dependency_estimators(self):
-        for margin_model in self.margin_models:
+        for margin_model in self.smooth_margin_models:
             dataset = MarginDataset.from_sampling(nb_obs=10, margin_model=margin_model,
                                                   spatial_coordinates=self.spatial_coordinates)
             # Fit estimator