diff --git a/safran_study/safran.py b/safran_study/safran.py
index 7b735f0cffe14b7fed8ccdede33d73bd0868353c..24d4e7965e057dab4f6fbeeef4f63055dae43aed 100644
--- a/safran_study/safran.py
+++ b/safran_study/safran.py
@@ -2,12 +2,16 @@ import os
 import os.path as op
 from collections import OrderedDict
 
+import matplotlib
 import matplotlib.pyplot as plt
 import pandas as pd
+from mpl_toolkits.axes_grid1 import AxesGrid
 from netCDF4 import Dataset
 
 from extreme_estimator.gev.gevmle_fit import GevMleFit
+from extreme_estimator.gev_params import GevParams
 from safran_study.massif import safran_massif_names_from_datasets
+from safran_study.shifted_color_map import shiftedColorMap
 from safran_study.snowfall_annual_maxima import SafranSnowfall
 from spatio_temporal_dataset.coordinates.abstract_coordinates import AbstractCoordinates
 from spatio_temporal_dataset.coordinates.spatial_coordinates.abstract_spatial_coordinates import \
@@ -29,17 +33,71 @@ class Safran(object):
 
     """ Visualization methods """
 
-    def visualize(self):
+    def visualize(self, ax=None, massif_name_to_fill_kwargs=None, show=True):
+        if ax is None:
+            ax = plt.gca()
         df_massif = pd.read_csv(op.join(self.map_full_path, 'massifsalpes.csv'))
         coord_tuples = [(row_massif['idx'], row_massif[AbstractCoordinates.COORDINATE_X],
                          row_massif[AbstractCoordinates.COORDINATE_Y])
                         for _, row_massif in df_massif.iterrows()]
-        for massif_idx in set([tuple[0] for tuple in coord_tuples]):
-            l = [coords for idx, *coords in coord_tuples if idx == massif_idx]
+
+        for coordinate_id in set([tuple[0] for tuple in coord_tuples]):
+            l = [coords for idx, *coords in coord_tuples if idx == coordinate_id]
             l = list(zip(*l))
-            plt.plot(*l, color='black')
-            plt.fill(*l)
-        self.massifs_coordinates.visualization_2D()
+            ax.plot(*l, color='black')
+            massif_name = self.coordinate_id_to_massif_name[coordinate_id]
+            fill_kwargs = massif_name_to_fill_kwargs[massif_name] if massif_name_to_fill_kwargs is not None else {}
+            ax.fill(*l, **fill_kwargs)
+        cax = ax.scatter(self.massifs_coordinates.x_coordinates, self.massifs_coordinates.y_coordinates)
+
+        if show:
+            plt.show()
+        return cax
+
+    def visualize_gev_fit_with_cmap(self, show=True, axes=None):
+        if axes is None:
+            fig, axes = plt.subplots(1, len(GevParams.GEV_PARAM_NAMES))
+            fig.subplots_adjust(hspace=1.0, wspace=1.0)
+
+            # fig = plt.figure(figsize=(6, 6))
+            # axes = AxesGrid(fig, 111, nrows_ncols=(1, 3), axes_pad=0.5,
+            #                 label_mode="1", share_all=True,
+            #                 cbar_location="right", cbar_mode="each",
+            #                 cbar_size="7%", cbar_pad="2%")
+
+        for i, gev_param_name in enumerate(GevParams.GEV_PARAM_NAMES[-1:]):
+            massif_name_to_value = self.df_gev_mle_each_massif.loc[gev_param_name, :].to_dict()
+            # Compute the middle point of the values for the color map
+            values = list(massif_name_to_value.values())
+            vmin, vmax = min(values), max(values)
+            midpoint = 1 - vmax / (vmax + abs(vmin))
+            scaling_factor = max(vmax, -vmin)
+            # print(gev_param_name, midpoint, vmin, vmax, scaling_factor)
+            # Load the shifted cmap to center on a middle point
+            cmap = [plt.cm.coolwarm, plt.cm.bwr, plt.cm.seismic][0]
+            shifted_cmap = shiftedColorMap(plt.cm.coolwarm, midpoint=0.0, name='shifted')
+            massif_name_to_fill_kwargs = {massif_name: {'color': shifted_cmap(value / scaling_factor)} for massif_name, value in
+                                          massif_name_to_value.items()}
+            ax = axes[i]
+            cax = self.visualize(ax=ax, massif_name_to_fill_kwargs=massif_name_to_fill_kwargs, show=False)
+
+            # cbar = fig.colorbar(cax, ticks=[-1, 0, 1], orientation='horizontal')
+            # cbar.ax.set_xticklabels(['Low', 'Medium', 'High'])  # horizontal colorbar
+            # cbar = fig.colorbar(cax, ticks=[-1, 0, 1])
+            # cbar.ax.set_yticklabels(['< -1', '0', '> 1'])  # vertically oriented colorbar
+            title_str = gev_param_name
+            ax.set_title(title_str)
+
+        if show:
+            plt.show()
+
+    def visualize_cmap(self, massif_name_to_value):
+        orig_cmap = plt.cm.coolwarm
+        # shifted_cmap = shiftedColorMap(orig_cmap, midpoint=0.75, name='shifted')
+
+        massif_name_to_fill_kwargs = {massif_name: {'color': orig_cmap(value)} for massif_name, value in massif_name_to_value.items()}
+
+        self.visualize(massif_name_to_fill_kwargs=massif_name_to_fill_kwargs)
 
     """ Statistics methods """
 
@@ -73,6 +131,10 @@ class Safran(object):
         # Load the names of the massif as defined by SAFRAN
         return safran_massif_names_from_datasets(self.year_to_dataset_ordered_dict.values())
 
+    @property
+    def safran_massif_id_to_massif_name(self):
+        return dict(enumerate(self.safran_massif_names))
+
     @cached_property
     def year_to_dataset_ordered_dict(self) -> OrderedDict:
         # Map each year to the correspond netCDF4 Dataset
@@ -88,13 +150,20 @@ class Safran(object):
         df_centroid = self.load_df_centroid()
         for coord_column in [AbstractCoordinates.COORDINATE_X, AbstractCoordinates.COORDINATE_Y]:
             df_centroid.loc[:, coord_column] = df_centroid[coord_column].str.replace(',', '.').astype(float)
-        # Assert that the massif names are the same between SAFRAN and the coordinate file
-        assert not set(self.safran_massif_names).symmetric_difference(set(df_centroid['NOM']))
         # Build coordinate object from df_centroid
         return AbstractSpatialCoordinates.from_df(df_centroid)
 
-    def load_df_centroid(self):
-        return pd.read_csv(op.join(self.map_full_path, 'coordonnees_massifs_alpes.csv'))
+    def load_df_centroid(self) -> pd.DataFrame:
+        df_centroid = pd.read_csv(op.join(self.map_full_path, 'coordonnees_massifs_alpes.csv'))
+        # Assert that the massif names are the same between SAFRAN and the coordinate file
+        assert not set(self.safran_massif_names).symmetric_difference(set(df_centroid['NOM']))
+        return df_centroid
+
+    @property
+    def coordinate_id_to_massif_name(self):
+        df_centroid = self.load_df_centroid()
+        print(df_centroid.columns)
+        return dict(zip(df_centroid['id'], df_centroid['NOM']))
 
     """ Some properties """
 
diff --git a/safran_study/shifted_color_map.py b/safran_study/shifted_color_map.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd4ac7d627b5eba0ef982e271a1780955c8f5533
--- /dev/null
+++ b/safran_study/shifted_color_map.py
@@ -0,0 +1,56 @@
+import numpy as np
+import matplotlib
+import matplotlib.pyplot as plt
+from mpl_toolkits.axes_grid1 import AxesGrid
+
+# from: https://stackoverflow.com/questions/7404116/defining-the-midpoint-of-a-colormap-in-matplotlib/20528097
+def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name='shiftedcmap'):
+    '''
+    Function to offset the "center" of a colormap. Useful for
+    data with a negative min and positive max and you want the
+    middle of the colormap's dynamic range to be at zero.
+
+    Input
+    -----
+      cmap : The matplotlib colormap to be altered
+      start : Offset from lowest point in the colormap's range.
+          Defaults to 0.0 (no lower offset). Should be between
+          0.0 and `midpoint`.
+      midpoint : The new center of the colormap. Defaults to
+          0.5 (no shift). Should be between 0.0 and 1.0. In
+          general, this should be  1 - vmax / (vmax + abs(vmin))
+          For example if your data range from -15.0 to +5.0 and
+          you want the center of the colormap at 0.0, `midpoint`
+          should be set to  1 - 5/(5 + 15)) or 0.75
+      stop : Offset from highest point in the colormap's range.
+          Defaults to 1.0 (no upper offset). Should be between
+          `midpoint` and 1.0.
+    '''
+    cdict = {
+        'red': [],
+        'green': [],
+        'blue': [],
+        'alpha': []
+    }
+
+    # regular index to compute the colors
+    reg_index = np.linspace(start, stop, 257)
+
+    # shifted index to match the data
+    shift_index = np.hstack([
+        np.linspace(0.0, midpoint, 128, endpoint=False),
+        np.linspace(midpoint, 1.0, 129, endpoint=True)
+    ])
+
+    for ri, si in zip(reg_index, shift_index):
+        r, g, b, a = cmap(ri)
+
+        cdict['red'].append((si, r, r))
+        cdict['green'].append((si, g, g))
+        cdict['blue'].append((si, b, b))
+        cdict['alpha'].append((si, a, a))
+
+    newcmap = matplotlib.colors.LinearSegmentedColormap(name, cdict)
+    plt.register_cmap(cmap=newcmap)
+
+    return newcmap
diff --git a/safran_study/visualize_safran.py b/safran_study/visualize_safran.py
new file mode 100644
index 0000000000000000000000000000000000000000..5937e40d9eeb7078dd3338a57b0d90e915a2f1a6
--- /dev/null
+++ b/safran_study/visualize_safran.py
@@ -0,0 +1,34 @@
+import pandas as pd
+
+from extreme_estimator.gev_params import GevParams
+from safran_study.safran import Safran
+from safran_study.safran_extended import ExtendedSafran
+from utils import VERSION
+from itertools import product
+
+
+def load_all_safran(only_first_one=False):
+    all_safran = []
+    for safran_alti, nb_day in product([1800, 2400], [1, 3, 7]):
+        print('alti: {}, nb_day: {}'.format(safran_alti, nb_day))
+        all_safran.append(Safran(safran_alti, nb_day))
+        if only_first_one:
+            break
+    return all_safran
+
+
+def fit_mle_gev_independent():
+    # Dump the result in a csv
+    dfs = []
+    for safran in load_all_safran(only_first_one=True):
+        safran.visualize_gev_fit_with_cmap()
+        # path = r'/home/erwan/Documents/projects/spatiotemporalextremes/local/spatio_temporal_datasets/results/fit_mle_massif/fit_mle_gev_{}.csv'
+        # df.to_csv(path.format(VERSION))
+
+
+def fit_max_stab():
+    pass
+
+
+if __name__ == '__main__':
+    fit_mle_gev_independent()