From aae23816be7af421aefbbd51d3898a1369254667 Mon Sep 17 00:00:00 2001
From: Le Roux Erwan <erwan.le-roux@irstea.fr>
Date: Wed, 24 Jun 2020 15:02:38 +0200
Subject: [PATCH] [contrasting] add coordinate_name_to_dim, and use it to
 extract results

---
 .../margin_function/linear_margin_function.py | 18 +++++++++--------
 .../abstract_temporal_linear_margin_model.py  |  1 +
 .../abstract_result_from_extremes.py          |  3 ++-
 .../result_from_mle_extremes.py               |  6 ++++--
 .../model/result_from_model_fit/utils.py      | 20 +++++++++++--------
 .../coordinates/abstract_coordinates.py       |  8 ++++++++
 6 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/extreme_fit/function/margin_function/linear_margin_function.py b/extreme_fit/function/margin_function/linear_margin_function.py
index d9b6b273..d2882b1b 100644
--- a/extreme_fit/function/margin_function/linear_margin_function.py
+++ b/extreme_fit/function/margin_function/linear_margin_function.py
@@ -42,9 +42,8 @@ class LinearMarginFunction(ParametricMarginFunction):
     def idx_to_coefficient_name(cls, coordinates: AbstractCoordinates) -> Dict[int, str]:
         # Intercept correspond to the dimension 0
         idx_to_coefficient_name = {-1: LinearCoef.INTERCEPT_NAME}
-        # Coordinates correspond to the dimension starting from 1
-        for idx, coordinate_name in enumerate(coordinates.coordinates_names):
-            idx_to_coefficient_name[idx] = coordinate_name
+        # Coordinates correspond to the dimension starting from 0
+        idx_to_coefficient_name.update(coordinates.dim_to_coordinate)
         return idx_to_coefficient_name
 
     @classmethod
@@ -64,25 +63,28 @@ class LinearMarginFunction(ParametricMarginFunction):
     def is_a_stationary_model(self) -> bool:
         return all([v == 'NULL' for v in self.form_dict.values()])
 
+    @property
+    def coordinate_name_to_dim(self):
+        return self.coordinates.coordinate_name_to_dim
+
     @property
     def form_dict(self) -> Dict[str, str]:
-        coordinate_name_to_dim = self.coefficient_name_to_dim(self.coordinates)
         form_dict = {}
         for param_name in self.params_class.PARAM_NAMES:
             linear_dims = self.param_name_to_dims.get(param_name, [])
             # Load spatial form_dict (only if we have some spatial coordinates)
             if self.coordinates.has_spatial_coordinates:
                 spatial_names = [name for name in self.coordinates.spatial_coordinates_names
-                                 if coordinate_name_to_dim[name] in linear_dims]
-                spatial_dims = [coordinate_name_to_dim[name] for name in spatial_names]
+                                 if self.coordinate_name_to_dim[name] in linear_dims]
+                spatial_dims = [self.coordinate_name_to_dim[name] for name in spatial_names]
                 spatial_form = self.param_name_to_coef[param_name].spatial_form_dict(spatial_names, spatial_dims)
                 form_dict.update(spatial_form)
             # Load temporal form dict (only if we have some temporal coordinates)
 
             if self.coordinates.has_temporal_coordinates:
                 temporal_names = [name for name in self.coordinates.temporal_coordinates_names
-                                  if coordinate_name_to_dim[name] in linear_dims]
-                temporal_dims = [coordinate_name_to_dim[name] for name in temporal_names]
+                                  if self.coordinate_name_to_dim[name] in linear_dims]
+                temporal_dims = [self.coordinate_name_to_dim[name] for name in temporal_names]
                 temporal_form = self.param_name_to_coef[param_name].temporal_form_dict(temporal_names, temporal_dims)
                 # Specifying a formula '~ 1' creates a bug in fitspatgev of SpatialExtreme R package
                 assert not any(['~ 1' in formula for formula in temporal_form.values()])
diff --git a/extreme_fit/model/margin_model/linear_margin_model/abstract_temporal_linear_margin_model.py b/extreme_fit/model/margin_model/linear_margin_model/abstract_temporal_linear_margin_model.py
index b28219a4..d2f301cb 100644
--- a/extreme_fit/model/margin_model/linear_margin_model/abstract_temporal_linear_margin_model.py
+++ b/extreme_fit/model/margin_model/linear_margin_model/abstract_temporal_linear_margin_model.py
@@ -90,6 +90,7 @@ class AbstractTemporalLinearMarginModel(LinearMarginModel):
                                    **r_type_argument_kwargs
                                    )
         return ResultFromMleExtremes(res, self.param_name_to_list_for_result,
+                                     self.coordinates.dim_to_coordinate,
                                      type_for_mle=self.type_for_mle)
 
     def extremes_fevd_bayesian_fit(self, x, df_coordinates_temp) -> AbstractResultFromExtremes:
diff --git a/extreme_fit/model/result_from_model_fit/result_from_extremes/abstract_result_from_extremes.py b/extreme_fit/model/result_from_model_fit/result_from_extremes/abstract_result_from_extremes.py
index 9211019a..8df785c8 100644
--- a/extreme_fit/model/result_from_model_fit/result_from_extremes/abstract_result_from_extremes.py
+++ b/extreme_fit/model/result_from_model_fit/result_from_extremes/abstract_result_from_extremes.py
@@ -14,9 +14,10 @@ from extreme_fit.model.utils import r
 
 class AbstractResultFromExtremes(AbstractResultFromModelFit):
 
-    def __init__(self, result_from_fit: robjects.ListVector, param_name_to_dim=None) -> None:
+    def __init__(self, result_from_fit: robjects.ListVector, param_name_to_dim=None, dim_to_coordinate=None) -> None:
         super().__init__(result_from_fit)
         self.param_name_to_dim = param_name_to_dim
+        self.dim_to_coordinate = dim_to_coordinate
 
     @property
     def summary_name_to_value(self):
diff --git a/extreme_fit/model/result_from_model_fit/result_from_extremes/result_from_mle_extremes.py b/extreme_fit/model/result_from_model_fit/result_from_extremes/result_from_mle_extremes.py
index 4346be81..124093a4 100644
--- a/extreme_fit/model/result_from_model_fit/result_from_extremes/result_from_mle_extremes.py
+++ b/extreme_fit/model/result_from_model_fit/result_from_extremes/result_from_mle_extremes.py
@@ -12,8 +12,9 @@ from extreme_fit.model.utils import r
 class ResultFromMleExtremes(AbstractResultFromExtremes):
 
     def __init__(self, result_from_fit: robjects.ListVector, param_name_to_dim=None,
+                 dim_to_coordinate=None,
                  type_for_mle="GEV") -> None:
-        super().__init__(result_from_fit, param_name_to_dim)
+        super().__init__(result_from_fit, param_name_to_dim, dim_to_coordinate)
         self.type_for_mle = type_for_mle
 
     @property
@@ -25,7 +26,8 @@ class ResultFromMleExtremes(AbstractResultFromExtremes):
             values = {i: param for i, param in enumerate(np.array(d['par']))}
         else:
             values = {i: np.array(v)[0] for i, v in enumerate(d.values())}
-        return get_margin_coef_ordered_dict(self.param_name_to_dim, values, self.type_for_mle)
+        return get_margin_coef_ordered_dict(self.param_name_to_dim, values, self.type_for_mle,
+                                            dim_to_coordinate_name=self.dim_to_coordinate)
 
     def _confidence_interval_method(self, common_kwargs, ci_method, return_period):
         method_name = ci_method_to_method_name[ci_method]
diff --git a/extreme_fit/model/result_from_model_fit/utils.py b/extreme_fit/model/result_from_model_fit/utils.py
index 2b2e5dac..d6a7367c 100644
--- a/extreme_fit/model/result_from_model_fit/utils.py
+++ b/extreme_fit/model/result_from_model_fit/utils.py
@@ -11,7 +11,7 @@ def convertFloatVector_to_float(f):
     return np.array(f)[0]
 
 
-def get_margin_coef_ordered_dict(param_name_to_dims, mle_values, type_for_mle="GEV"):
+def get_margin_coef_ordered_dict(param_name_to_dims, mle_values, type_for_mle="GEV", dim_to_coordinate_name=None):
     assert param_name_to_dims is not None
     # Build the Coeff dict from param_name_to_dim
     coef_dict = OrderedDict()
@@ -29,12 +29,16 @@ def get_margin_coef_ordered_dict(param_name_to_dims, mle_values, type_for_mle="G
         if param_name in param_name_to_dims:
             dims = param_name_to_dims[param_name]
             if isinstance(dims[0], int):
-                nb_parameters = 1
-            else:
-                nb_parameters = dims[0][1]
-            for j in range(nb_parameters):
-                temporal_coef_name = LinearCoef.coef_template_str(param_name,
-                                                                  AbstractCoordinates.COORDINATE_T).format(1 + j)
-                coef_dict[temporal_coef_name] = mle_values[i]
+                coef_name = LinearCoef.coef_template_str(param_name, AbstractCoordinates.COORDINATE_T).format(1)
+                coef_dict[coef_name] = mle_values[i]
                 i += 1
+            else:
+                for dim, max_degree in dims:
+                    coordinate_name = dim_to_coordinate_name[dim]
+                    coef_template = LinearCoef.coef_template_str(param_name, coordinate_name)
+                    for j in range(1, max_degree + 1):
+                        k = j if coordinate_name == AbstractCoordinates.COORDINATE_T else j + 1
+                        coef_name = coef_template.format(k)
+                        coef_dict[coef_name] = mle_values[i]
+                        i += 1
     return coef_dict
diff --git a/spatio_temporal_dataset/coordinates/abstract_coordinates.py b/spatio_temporal_dataset/coordinates/abstract_coordinates.py
index 443a557d..8d153985 100644
--- a/spatio_temporal_dataset/coordinates/abstract_coordinates.py
+++ b/spatio_temporal_dataset/coordinates/abstract_coordinates.py
@@ -319,6 +319,14 @@ class AbstractCoordinates(object):
     def ind_of_df_all_coordinates(self, coordinate_name, value):
         return self.df_all_coordinates.loc[:, coordinate_name] == value
 
+    @property
+    def coordinate_name_to_dim(self):
+        return {v: k for k, v in self.dim_to_coordinate.items()}
+
+    @property
+    def dim_to_coordinate(self):
+        return dict(enumerate(self.coordinates_names))
+
     #  Visualization
 
     @property
-- 
GitLab