diff --git a/extreme_data/meteo_france_data/adamont_data/cmip5/temperature_to_year.py b/extreme_data/meteo_france_data/adamont_data/cmip5/temperature_to_year.py
new file mode 100644
index 0000000000000000000000000000000000000000..c911fa5e7c3ed9aa23787afbd21b900681e84906
--- /dev/null
+++ b/extreme_data/meteo_france_data/adamont_data/cmip5/temperature_to_year.py
@@ -0,0 +1,88 @@
+import matplotlib.pyplot as plt
+import numpy as np
+from matplotlib.lines import Line2D
+
+from extreme_data.meteo_france_data.adamont_data.adamont_gcm_rcm_couples import gcm_to_color
+from extreme_data.meteo_france_data.adamont_data.adamont_scenario import AdamontScenario, rcp_scenarios, get_gcm_list, \
+    get_linestyle_from_scenario, scenario_to_str, adamont_scenarios_real
+from extreme_data.meteo_france_data.adamont_data.cmip5.climate_explorer_cimp5 import years_and_global_mean_temps
+
+
+def temperature_minmax_to_year_minmax(gcm, scenario, temperature_min, temperature_max):
+    years, global_mean_temps = years_and_global_mean_temps(gcm, scenario, year_min=2005, year_max=2100,
+                                                           rolling=30, anomaly=True)
+    years, global_mean_temps = np.array(years), np.array(global_mean_temps)
+    ind = temperature_min < global_mean_temps
+    ind &= global_mean_temps < temperature_max
+    years_to_select = years[ind]
+    ind2 = years_to_select[:-1] == years_to_select[1:] - 1
+    if not all(ind2):
+        i = list(ind2).index(False)
+        years_to_select = years_to_select[:i + 1]
+    # A minimum of 30 years of data is needed to find a trend
+    if len(years_to_select) >= 30:
+        year_min, year_max = years_to_select[0], years_to_select[-1]
+        assert (year_max - year_min + 1) == len(years_to_select)
+        return year_min, year_max
+    else:
+        return None, None
+
+
+def get_nb_data(gcm, scenario, temperature_min, temperature_max):
+    year_min, year_max = temperature_minmax_to_year_minmax(gcm, scenario, temperature_min, temperature_max)
+    if year_min is None:
+        return 0
+    else:
+        return year_max - year_min + 1
+
+
+def plot_nb_data_one_line(ax, gcm, scenario, temp_min, temp_max):
+
+    nb_data = [get_nb_data(gcm, scenario, mi, ma) for mi, ma in zip(temp_min, temp_max)]
+    color = gcm_to_color[gcm]
+    linestyle = get_linestyle_from_scenario(scenario)
+
+    # Filter out the zero value
+    nb_data, temp_min = np.array(nb_data), np.array(temp_min)
+    ind = np.array(nb_data) > 0
+    nb_data, temp_min = nb_data[ind], temp_min[ind]
+
+    # For the legend
+    if scenario is AdamontScenario.rcp26:
+        ax.plot(temp_min[0], nb_data[0], color=color, linestyle='solid', label=gcm)
+
+    ax.plot(temp_min, nb_data, linestyle=linestyle, color=color)
+
+
+def plot_nb_data():
+    temp_max, temp_min = get_temp_min_and_temp_max()
+
+    ax = plt.gca()
+    for gcm in get_gcm_list(adamont_version=2)[:]:
+        for scenario in rcp_scenarios[:]:
+            plot_nb_data_one_line(ax, gcm, scenario, temp_min, temp_max)
+
+    ax.legend()
+    ticks_labels = ['{}-{}'.format(mi, ma) for mi, ma in zip(temp_min, temp_max)]
+    ax.set_xticks(temp_min)
+    ax.set_xticklabels(ticks_labels)
+    ax.set_xlabel('Temperature interval')
+    ax.set_ylabel('Nb of Data')
+    ax2 = ax.twinx()
+    legend_elements = [
+        Line2D([0], [0], color='k', lw=1, label=scenario_to_str(s),
+               linestyle=get_linestyle_from_scenario(s)) for s in adamont_scenarios_real
+    ]
+    ax2.legend(handles=legend_elements, loc='upper center')
+    ax2.set_yticks([])
+    plt.show()
+
+
+def get_temp_min_and_temp_max():
+    temp_min = np.arange(0.5, 2.5, 0.5)
+    temp_max = temp_min + 1.5
+    return temp_min, temp_max
+
+
+if __name__ == '__main__':
+    plot_nb_data()
diff --git a/extreme_fit/distribution/abstract_extreme_params.py b/extreme_fit/distribution/abstract_extreme_params.py
index 8c98f1b99b78cba3071fd99680a442601a544116..e892342d09b545849dac25f5ac3780c41dae3558 100644
--- a/extreme_fit/distribution/abstract_extreme_params.py
+++ b/extreme_fit/distribution/abstract_extreme_params.py
@@ -1,7 +1,10 @@
+import numpy as np
+
 from extreme_fit.distribution.abstract_params import AbstractParams
 
 
 class AbstractExtremeParams(AbstractParams):
+    SMALL_SCALE_PARAMETERS_ARE_UNDEFINED = True
 
     def __init__(self, loc: float, scale: float, shape: float):
         self.location = loc
@@ -11,4 +14,6 @@ class AbstractExtremeParams(AbstractParams):
         # (sometimes it happens, when we want to find a quantile for every point of a 2D map
         # then it can happen that a corner point that was not used for fitting correspond to a negative scale,
         # in the case we set all the parameters as equal to np.nan, and we will not display those points)
-        self.has_undefined_parameters = self.scale <= 0
+        self.has_undefined_parameters = (self.scale <= 0)
+        if self.SMALL_SCALE_PARAMETERS_ARE_UNDEFINED:
+            self.has_undefined_parameters = self.has_undefined_parameters or (np.isclose(self.scale, 0))
\ No newline at end of file
diff --git a/extreme_fit/estimator/margin_estimator/abstract_margin_estimator.py b/extreme_fit/estimator/margin_estimator/abstract_margin_estimator.py
index f8afbdcda4071b873fd009c8e8c7c24a395364f6..6c71b8c53a0bef12871d86bf9c9da2cb31e8de24 100644
--- a/extreme_fit/estimator/margin_estimator/abstract_margin_estimator.py
+++ b/extreme_fit/estimator/margin_estimator/abstract_margin_estimator.py
@@ -61,11 +61,13 @@ class LinearMarginEstimator(AbstractMarginEstimator):
     def function_from_fit(self) -> LinearMarginFunction:
         return load_margin_function(self, self.margin_model)
 
+    def coordinates_for_nllh(self, split=Split.all):
+        return pd.concat([self.df_coordinates_spat(split=split), self.df_coordinates_temp(split=split)], axis=1).values
+
     def nllh(self, split=Split.all):
         nllh = 0
         maxima_values = self.dataset.maxima_gev(split=split)
-        df = pd.concat([self.df_coordinates_spat(split=split), self.df_coordinates_temp(split=split)], axis=1)
-        coordinate_values = df.values
+        coordinate_values = self.coordinates_for_nllh(split=split)
         for maximum, coordinate in zip(maxima_values, coordinate_values):
             assert len(maximum) == 1, \
                 'So far, only one observation for each coordinate, but code would be easy to change'
diff --git a/projects/altitude_spatial_model/altitudes_fit/one_fold_analysis/altitude_group.py b/projects/altitude_spatial_model/altitudes_fit/one_fold_analysis/altitude_group.py
index 30d0eb09f3f3cdd1ff73115b26ba87b1090ae918..5a3f8a16d28e890697027c540b03544c7dde0004 100644
--- a/projects/altitude_spatial_model/altitudes_fit/one_fold_analysis/altitude_group.py
+++ b/projects/altitude_spatial_model/altitudes_fit/one_fold_analysis/altitude_group.py
@@ -17,6 +17,10 @@ class AbstractAltitudeGroup(object):
     def name(self):
         raise NotImplementedError
 
+    @property
+    def altitudes(self):
+        return altitudes_for_groups[self.group_id-1]
+
     @property
     def reference_altitude(self):
         raise NotImplementedError
@@ -141,6 +145,10 @@ class DefaultAltitudeGroup(AbstractAltitudeGroup):
         return 500
 
 
+def get_altitude_class_from_altitudes(altitudes):
+    return type(get_altitude_group_from_altitudes(altitudes))
+
+
 def get_altitude_group_from_altitudes(altitudes):
     s = set(altitudes)
     if s == set(altitudes_for_groups[0]):
diff --git a/projects/altitude_spatial_model/altitudes_fit/one_fold_analysis/one_fold_fit.py b/projects/altitude_spatial_model/altitudes_fit/one_fold_analysis/one_fold_fit.py
index 65f900e2eb466fd98d9120bb0b21288ff724ad30..a0451c44757d65d4c15c898937e433a5cbc436ed 100644
--- a/projects/altitude_spatial_model/altitudes_fit/one_fold_analysis/one_fold_fit.py
+++ b/projects/altitude_spatial_model/altitudes_fit/one_fold_analysis/one_fold_fit.py
@@ -180,12 +180,31 @@ class OneFoldFit(object):
             # Remove wrong shape
             estimators = [e for e in estimators if -0.5 < self._compute_shape_for_reference_altitude(e) < 0.5]
             # Remove models with undefined parameters for the coordinate of interest
-            coordinate = np.array([self.altitude_group.reference_altitude, self.last_year])
-            estimators = [e for e in estimators if not e.function_from_fit.get_params(coordinate).has_undefined_parameters]
+            well_defined_estimators = []
+            for e in estimators:
+                coordinate_values_for_the_fit = e.coordinates_for_nllh(Split.all)
+                coordinate_values_for_the_result = [np.array([self.altitude_group.reference_altitude, c])
+                                                             for c in self._covariate_before_and_after]
+                coordinate_values_to_check = list(coordinate_values_for_the_fit) + coordinate_values_for_the_result
+                has_undefined_parameters = False
+                for coordinate in coordinate_values_to_check:
+                    gev_params = e.function_from_fit.get_params(coordinate)
+                    if gev_params.has_undefined_parameters:
+                        has_undefined_parameters = True
+                        break
+                if not has_undefined_parameters:
+                    well_defined_estimators.append(e)
+            estimators = well_defined_estimators
+
             if len(estimators) == 0:
                 print(self.massif_name, " has only implausible models")
 
-        sorted_estimators = sorted([estimator for estimator in estimators], key=lambda e: e.aic())
+        try:
+            sorted_estimators = sorted([estimator for estimator in estimators], key=lambda e: e.aic())
+        except AssertionError as e:
+            print('Error for')
+            print(self.massif_name, self.altitude_group)
+            raise
         return sorted_estimators
 
     def _compute_shape_for_reference_altitude(self, estimator):
diff --git a/projects/altitude_spatial_model/altitudes_fit/utils_altitude_studies_visualizer.py b/projects/altitude_spatial_model/altitudes_fit/utils_altitude_studies_visualizer.py
index e0a556db286c0b1c90d3833323dfebd10e1a2081..484634526ba5032595c4e7a83636ba9c63c5e2bd 100644
--- a/projects/altitude_spatial_model/altitudes_fit/utils_altitude_studies_visualizer.py
+++ b/projects/altitude_spatial_model/altitudes_fit/utils_altitude_studies_visualizer.py
@@ -34,6 +34,9 @@ def compute_and_assign_max_abs(visualizer_list):
             max_abs = max([
                 max([abs(e) for e in v.method_name_and_order_to_d(method_name, order).values()
                      ]) for v in visualizer_list])
+            if max_abs == 0:
+                epsilon = 0.1
+                max_abs = epsilon
             method_name_and_order_to_max_abs[c] = max_abs
     # Assign the max abs dictionary
     for v in visualizer_list:
diff --git a/projects/projected_snowfall/elevation_temporal_model_for_projections/main_elevation_temporal_for_projections_ensemble.py b/projects/projected_snowfall/elevation_temporal_model_for_projections/main_elevation_temporal_for_projections_ensemble.py
index 268b38fc16a94ee5972e6f9b8af50a959e93a4b3..23f51598fbd3da1818e43859218098e9b8395dcb 100644
--- a/projects/projected_snowfall/elevation_temporal_model_for_projections/main_elevation_temporal_for_projections_ensemble.py
+++ b/projects/projected_snowfall/elevation_temporal_model_for_projections/main_elevation_temporal_for_projections_ensemble.py
@@ -4,13 +4,16 @@ from typing import List
 
 import matplotlib as mpl
 
+from projects.projected_snowfall.elevation_temporal_model_for_projections.visualizer_for_sensitivity import \
+    VisualizerForSensivity
+
 mpl.rcParams['text.usetex'] = True
 mpl.rcParams['text.latex.preamble'] = [r'\usepackage{amsmath}']
 
 from extreme_fit.model.margin_model.polynomial_margin_model.utils import \
     ALTITUDINAL_GEV_MODELS_BASED_ON_POINTWISE_ANALYSIS
 from projects.projected_snowfall.elevation_temporal_model_for_projections.visualizer_for_projection_ensemble import \
-    MetaVisualizerForProjectionEnsemble
+    VisualizerForProjectionEnsemble
 import matplotlib
 from extreme_fit.model.utils import set_seed_for_test
 
@@ -34,62 +37,72 @@ from extreme_data.meteo_france_data.scm_models_data.utils import Season
 
 def main():
     start = time.time()
-    study_classes = [AdamontSnowfall][:1]
+    study_class = AdamontSnowfall
     ensemble_fit_class = [IndependentEnsembleFit]
     temporal_covariate_for_fit = [TimeTemporalCovariate, AnomalyTemperatureTemporalCovariate][1]
     set_seed_for_test()
     AbstractExtractEurocodeReturnLevel.ALPHA_CONFIDENCE_INTERVAL_UNCERTAINTY = 0.2
 
     fast = None
-    scenarios = rcp_scenarios[:1] if fast is False else [AdamontScenario.rcp26]
+    sensitivity_plot = True
+    scenarios = rcp_scenarios if fast is False else [AdamontScenario.rcp85]
 
     for scenario in scenarios:
         gcm_rcm_couples = get_gcm_rcm_couples(scenario)
         if fast is None:
             massif_names = None
-            gcm_rcm_couples = gcm_rcm_couples[:]
+            gcm_rcm_couples = None
             AbstractExtractEurocodeReturnLevel.NB_BOOTSTRAP = 10
-            altitudes_list = altitudes_for_groups[:1]
+            altitudes_list = altitudes_for_groups[3:]
         elif fast:
+            massif_names = ['Vanoise', 'Haute-Maurienne']
+            gcm_rcm_couples = gcm_rcm_couples[4:6]
             AbstractExtractEurocodeReturnLevel.NB_BOOTSTRAP = 10
-            massif_names = None
-            gcm_rcm_couples = [('EC-EARTH', 'RACMO22E')]
-            altitudes_list = altitudes_for_groups[1:2]
+            altitudes_list = altitudes_for_groups[2:]
         else:
             massif_names = None
             altitudes_list = altitudes_for_groups[:]
 
         assert isinstance(gcm_rcm_couples, list)
 
-        main_loop(gcm_rcm_couples, altitudes_list, massif_names, study_classes, ensemble_fit_class, scenario,
-                  temporal_covariate_for_fit)
+        main_loop(gcm_rcm_couples, altitudes_list, massif_names, study_class, ensemble_fit_class, scenario,
+                  temporal_covariate_for_fit, sensitivity_plot=sensitivity_plot)
 
     end = time.time()
     duration = str(datetime.timedelta(seconds=end - start))
     print('Total duration', duration)
 
 
-def main_loop(gcm_rcm_couples, altitudes_list, massif_names, study_classes, ensemble_fit_classes, scenario,
-              temporal_covariate_for_fit):
+def main_loop(gcm_rcm_couples, altitudes_list, massif_names, study_class, ensemble_fit_classes, scenario,
+              temporal_covariate_for_fit, sensitivity_plot=False):
     assert isinstance(altitudes_list, List)
     assert isinstance(altitudes_list[0], List)
     print('Covariate is {}'.format(temporal_covariate_for_fit))
-    for study_class in study_classes:
-        print('Inner loop', study_class)
-        model_classes = ALTITUDINAL_GEV_MODELS_BASED_ON_POINTWISE_ANALYSIS
-        assert scenario in rcp_scenarios
 
-        visualizer = MetaVisualizerForProjectionEnsemble(
+    model_classes = ALTITUDINAL_GEV_MODELS_BASED_ON_POINTWISE_ANALYSIS
+    assert scenario in rcp_scenarios
+    remove_physically_implausible_models = True
+
+    if sensitivity_plot:
+        visualizer = VisualizerForSensivity(
+            altitudes_list, gcm_rcm_couples, study_class, Season.annual, scenario,
+            model_classes=model_classes,
+            ensemble_fit_classes=ensemble_fit_classes,
+            massif_names=massif_names,
+            temporal_covariate_for_fit=temporal_covariate_for_fit,
+            remove_physically_implausible_models=remove_physically_implausible_models,
+        )
+    else:
+        visualizer = VisualizerForProjectionEnsemble(
             altitudes_list, gcm_rcm_couples, study_class, Season.annual, scenario,
             model_classes=model_classes,
             ensemble_fit_classes=ensemble_fit_classes,
             massif_names=massif_names,
             temporal_covariate_for_fit=temporal_covariate_for_fit,
-            remove_physically_implausible_models=True,
+            remove_physically_implausible_models=remove_physically_implausible_models,
+            gcm_to_year_min_and_year_max=None,
         )
-        visualizer.plot()
-        del visualizer
-        time.sleep(2)
+    visualizer.plot()
 
 
 if __name__ == '__main__':
diff --git a/projects/projected_snowfall/elevation_temporal_model_for_projections/visualizer_for_projection_ensemble.py b/projects/projected_snowfall/elevation_temporal_model_for_projections/visualizer_for_projection_ensemble.py
index 9d51602b169ccfac2e44ed2262711dfebdfff9ad..e7d9e38ef1aa0b93d6e85395fa257be7123d788a 100644
--- a/projects/projected_snowfall/elevation_temporal_model_for_projections/visualizer_for_projection_ensemble.py
+++ b/projects/projected_snowfall/elevation_temporal_model_for_projections/visualizer_for_projection_ensemble.py
@@ -5,7 +5,7 @@ from extreme_fit.model.margin_model.polynomial_margin_model.spatio_temporal_poly
 from extreme_fit.model.margin_model.utils import MarginFitMethod
 from projects.altitude_spatial_model.altitudes_fit.altitudes_studies import AltitudesStudies
 from projects.altitude_spatial_model.altitudes_fit.one_fold_analysis.altitude_group import \
-    get_altitude_group_from_altitudes
+    get_altitude_group_from_altitudes, get_altitude_class_from_altitudes
 from projects.altitude_spatial_model.altitudes_fit.plots.plot_histogram_altitude_studies import \
     plot_histogram_all_trends_against_altitudes, plot_shoe_plot_changes_against_altitude
 from projects.altitude_spatial_model.altitudes_fit.utils_altitude_studies_visualizer import compute_and_assign_max_abs
@@ -13,7 +13,7 @@ from projects.projected_snowfall.elevation_temporal_model_for_projections.indepe
     IndependentEnsembleFit
 
 
-class MetaVisualizerForProjectionEnsemble(object):
+class VisualizerForProjectionEnsemble(object):
 
     def __init__(self, altitudes_list, gcm_rcm_couples, study_class, season, scenario,
                  model_classes: List[AbstractSpatioTemporalPolynomialModel],
@@ -24,25 +24,39 @@ class MetaVisualizerForProjectionEnsemble(object):
                  display_only_model_that_pass_gof_test=False,
                  confidence_interval_based_on_delta_method=False,
                  remove_physically_implausible_models=False,
+                 gcm_to_year_min_and_year_max=None,
                  ):
         self.gcm_rcm_couples = gcm_rcm_couples
         self.massif_names = massif_names
         self.ensemble_fit_classes = ensemble_fit_classes
 
         # Load all studies
-        altitude_group_to_gcm_couple_to_studies = {}
+        altitude_class_to_gcm_couple_to_studies = {}
         for altitudes in altitudes_list:
-            altitude_group = get_altitude_group_from_altitudes(altitudes)
+            altitude_class = get_altitude_class_from_altitudes(altitudes)
             gcm_rcm_couple_to_studies = {}
             for gcm_rcm_couple in gcm_rcm_couples:
+                if gcm_to_year_min_and_year_max is None:
+                    kwargs_study = {}
+                else:
+                    gcm = gcm_rcm_couple[0]
+                    if gcm not in gcm_to_year_min_and_year_max:
+                        # It means that for this gcm and scenario,
+                        # there is not enough data (less than 30 years) for the fit
+                        continue
+                    year_min, year_max = gcm_to_year_min_and_year_max[gcm]
+                    kwargs_study = {'year_min': year_min, 'year_max': year_max}
                 studies = AltitudesStudies(study_class, altitudes, season=season,
-                                           scenario=scenario, gcm_rcm_couple=gcm_rcm_couple)
+                                           scenario=scenario, gcm_rcm_couple=gcm_rcm_couple,
+                                           **kwargs_study)
                 gcm_rcm_couple_to_studies[gcm_rcm_couple] = studies
-            altitude_group_to_gcm_couple_to_studies[altitude_group] = gcm_rcm_couple_to_studies
+            if len(gcm_rcm_couple_to_studies) == 0:
+                print('No valid studies for the following couples:', self.gcm_rcm_couples)
+            altitude_class_to_gcm_couple_to_studies[altitude_class] = gcm_rcm_couple_to_studies
 
         # Load ensemble fit
-        self.altitude_group_to_ensemble_class_to_ensemble_fit = {}
-        for altitude_group, gcm_rcm_couple_to_studies in altitude_group_to_gcm_couple_to_studies.items():
+        self.altitude_class_to_ensemble_class_to_ensemble_fit = {}
+        for altitude_class, gcm_rcm_couple_to_studies in altitude_class_to_gcm_couple_to_studies.items():
             ensemble_class_to_ensemble_fit = {}
             for ensemble_fit_class in ensemble_fit_classes:
                 ensemble_fit = ensemble_fit_class(massif_names, gcm_rcm_couple_to_studies, model_classes,
@@ -51,7 +65,7 @@ class MetaVisualizerForProjectionEnsemble(object):
                                                   confidence_interval_based_on_delta_method,
                                                   remove_physically_implausible_models)
                 ensemble_class_to_ensemble_fit[ensemble_fit_class] = ensemble_fit
-            self.altitude_group_to_ensemble_class_to_ensemble_fit[altitude_group] = ensemble_class_to_ensemble_fit
+            self.altitude_class_to_ensemble_class_to_ensemble_fit[altitude_class] = ensemble_class_to_ensemble_fit
 
     def plot(self):
         if IndependentEnsembleFit in self.ensemble_fit_classes:
@@ -74,6 +88,8 @@ class MetaVisualizerForProjectionEnsemble(object):
         # Aggregated at gcm_rcm_level plots
         merge_keys = [IndependentEnsembleFit.Median_merge, IndependentEnsembleFit.Mean_merge]
         keys = self.gcm_rcm_couples + merge_keys
+        # Only plot Mean for speed
+        keys = [IndependentEnsembleFit.Mean_merge]
         for key in keys:
             visualizer_list = [independent_ensemble_fit.gcm_rcm_couple_to_visualizer[key]
                                if key in self.gcm_rcm_couples
@@ -92,7 +108,7 @@ class MetaVisualizerForProjectionEnsemble(object):
     def ensemble_fits(self, ensemble_class):
         return [ensemble_class_to_ensemble_fit[ensemble_class]
                 for ensemble_class_to_ensemble_fit
-                in self.altitude_group_to_ensemble_class_to_ensemble_fit.values()]
+                in self.altitude_class_to_ensemble_class_to_ensemble_fit.values()]
 
     def plot_together(self):
         pass
diff --git a/projects/projected_snowfall/elevation_temporal_model_for_projections/visualizer_for_sensitivity.py b/projects/projected_snowfall/elevation_temporal_model_for_projections/visualizer_for_sensitivity.py
new file mode 100644
index 0000000000000000000000000000000000000000..f3e40b69e2b800bb894c03b6ef234044a91dfffe
--- /dev/null
+++ b/projects/projected_snowfall/elevation_temporal_model_for_projections/visualizer_for_sensitivity.py
@@ -0,0 +1,115 @@
+from collections import OrderedDict
+import matplotlib.pyplot as plt
+from typing import List, Dict
+
+from extreme_data.meteo_france_data.adamont_data.cmip5.temperature_to_year import get_temp_min_and_temp_max, \
+    temperature_minmax_to_year_minmax
+from extreme_data.meteo_france_data.scm_models_data.utils import Season
+from extreme_fit.model.margin_model.polynomial_margin_model.spatio_temporal_polynomial_model import \
+    AbstractSpatioTemporalPolynomialModel
+from extreme_fit.model.margin_model.utils import MarginFitMethod
+from projects.altitude_spatial_model.altitudes_fit.altitudes_studies import AltitudesStudies
+from projects.altitude_spatial_model.altitudes_fit.one_fold_analysis.altitude_group import \
+    get_altitude_group_from_altitudes, get_altitude_class_from_altitudes
+from projects.altitude_spatial_model.altitudes_fit.plots.plot_histogram_altitude_studies import \
+    plot_histogram_all_trends_against_altitudes, plot_shoe_plot_changes_against_altitude
+from projects.altitude_spatial_model.altitudes_fit.utils_altitude_studies_visualizer import compute_and_assign_max_abs
+from projects.projected_snowfall.elevation_temporal_model_for_projections.independent_ensemble_fit.independent_ensemble_fit import \
+    IndependentEnsembleFit
+from projects.projected_snowfall.elevation_temporal_model_for_projections.visualizer_for_projection_ensemble import \
+    VisualizerForProjectionEnsemble
+
+
+class VisualizerForSensivity(object):
+
+    def __init__(self, altitudes_list, gcm_rcm_couples, study_class, season, scenario,
+                 model_classes: List[AbstractSpatioTemporalPolynomialModel],
+                 ensemble_fit_classes=None,
+                 massif_names=None,
+                 fit_method=MarginFitMethod.extremes_fevd_mle,
+                 temporal_covariate_for_fit=None,
+                 display_only_model_that_pass_gof_test=False,
+                 confidence_interval_based_on_delta_method=False,
+                 remove_physically_implausible_models=False,
+                 ):
+        self.altitudes_list = altitudes_list
+        self.massif_names = massif_names
+        self.temp_min, self.temp_max = get_temp_min_and_temp_max()
+        self.temp_min_to_temp_max = OrderedDict(zip(self.temp_min, self.temp_max))
+        self.temp_min_to_visualizer = {} # type: Dict[float, VisualizerForProjectionEnsemble]
+
+        for temp_min, temp_max in zip(self.temp_min, self.temp_max):
+            print(temp_min, temp_max)
+            # Build 
+            gcm_to_year_min_and_year_max = {}
+            gcm_list = list(set([g for g, r in gcm_rcm_couples]))
+            for gcm in gcm_list:
+                year_min_and_year_max = temperature_minmax_to_year_minmax(gcm, scenario, temp_min, temp_max)
+                if year_min_and_year_max[0] is not None:
+                    gcm_to_year_min_and_year_max[gcm] = year_min_and_year_max
+                
+            visualizer = VisualizerForProjectionEnsemble(
+                altitudes_list, gcm_rcm_couples, study_class, Season.annual, scenario,
+                model_classes=model_classes,
+                fit_method=fit_method,
+                ensemble_fit_classes=ensemble_fit_classes,
+                display_only_model_that_pass_gof_test=display_only_model_that_pass_gof_test,
+                confidence_interval_based_on_delta_method=confidence_interval_based_on_delta_method,
+                massif_names=massif_names,
+                temporal_covariate_for_fit=temporal_covariate_for_fit,
+                remove_physically_implausible_models=remove_physically_implausible_models,
+                gcm_to_year_min_and_year_max=gcm_to_year_min_and_year_max
+            )
+            self.temp_min_to_visualizer[temp_min] = visualizer
+
+    def plot(self):
+        # todo: before reactivating the subplot, i should ensure that we can modify the prefix
+        # so that we can have all the subplot, and not juste for the last t_min
+        # for visualizer in self.temp_min_to_visualizer.values():
+        #     visualizer.plot()
+        self.sensitivity_plot()
+
+    def sensitivity_plot(self):
+        ax = plt.gca()
+        for altitudes in self.altitudes_list:
+            altitude_class = get_altitude_class_from_altitudes(altitudes)
+            self.temperature_interval_plot(ax, altitude_class)
+
+        ticks_labels = ['+{} to +{}'.format(mi, ma) for mi, ma in zip(self.temp_min, self.temp_max)]
+        ax.set_ylabel('Percentages of massifs (%)')
+        ax.set_xlabel('Range of temperatures used to compute the trends ')
+        ax.set_xticks(self.temp_min)
+        ax.set_xticklabels(ticks_labels)
+        ax.legend()
+        mean_visualizer = self.first_mean_visualizer
+        mean_visualizer.plot_name = 'Sensitivity plot'
+        mean_visualizer.show_or_save_to_file(no_title=True)
+
+    @property
+    def first_mean_visualizer(self):
+        altitude_class = get_altitude_class_from_altitudes(self.altitudes_list[0])
+        visualizer_projection = list(self.temp_min_to_visualizer.values())[0]
+        return self.get_mean_visualizer(altitude_class, visualizer_projection)
+
+    def get_mean_visualizer(self, altitude_class, visualizer_projection: VisualizerForProjectionEnsemble):
+        independent_ensemble_fit = visualizer_projection.altitude_class_to_ensemble_class_to_ensemble_fit[altitude_class][
+            IndependentEnsembleFit]
+        mean_visualizer = independent_ensemble_fit.merge_function_name_to_visualizer[IndependentEnsembleFit.Mean_merge]
+        mean_visualizer.studies.study.gcm_rcm_couple = (IndependentEnsembleFit.Mean_merge, "merge")
+        return mean_visualizer
+
+    def temperature_interval_plot(self, ax, altitude_class):
+        label_to_l = {
+            'increasing': [],
+            'decreasing': []
+        }
+        for v in self.temp_min_to_visualizer.values():
+            mean_visualizer = self.get_mean_visualizer(altitude_class, v)
+            _, *trends = mean_visualizer.all_trends(self.massif_names, with_significance=False)
+            label_to_l['decreasing'].append(trends[0])
+            label_to_l['increasing'].append(trends[2])
+        altitude_str = altitude_class().formula
+        for label, l in label_to_l.items():
+            label_improved = 'with {} trends {}'.format(label, altitude_str)
+            ax.plot(self.temp_min, l, label=label_improved)
+
diff --git a/test/test_extreme_fit/test_estimator/test_full_estimators.py b/test/test_extreme_fit/test_estimator/test_full_estimators.py
index 9322f03459ba33915e3d0099492d256eb987e419..abbb240b144f7fabcb45edd8e012d7bd4ea143e9 100644
--- a/test/test_extreme_fit/test_estimator/test_full_estimators.py
+++ b/test/test_extreme_fit/test_estimator/test_full_estimators.py
@@ -1,6 +1,7 @@
 import unittest
 from itertools import product
 
+from extreme_fit.distribution.abstract_extreme_params import AbstractExtremeParams
 from spatio_temporal_dataset.dataset.simulation_dataset import FullSimulatedDataset
 from test.test_utils import load_test_max_stable_models, load_smooth_margin_models, load_test_1D_and_2D_spatial_coordinates, \
     load_test_full_estimators
@@ -17,6 +18,7 @@ class TestFullEstimators(unittest.TestCase):
         self.max_stable_models = load_test_max_stable_models()
 
     def test_full_estimators(self):
+        AbstractExtremeParams.SMALL_SCALE_PARAMETERS_ARE_UNDEFINED = False
         for coordinates in self.spatial_coordinates:
             smooth_margin_models = load_smooth_margin_models(coordinates=coordinates)
             for margin_model, max_stable_model in product(smooth_margin_models, self.max_stable_models):
diff --git a/test/test_projects/test_altitude_spatial/test_one_fold_fit.py b/test/test_projects/test_altitude_spatial/test_one_fold_fit.py
index 33daf73f40f49f089d600a4bf3f659bc41aad89d..f939768679cbbabbcd27a4173ea1fb0f6662ac93 100644
--- a/test/test_projects/test_altitude_spatial/test_one_fold_fit.py
+++ b/test/test_projects/test_altitude_spatial/test_one_fold_fit.py
@@ -2,6 +2,7 @@ import unittest
 
 from extreme_data.meteo_france_data.adamont_data.adamont.adamont_snowfall import AdamontSnowfall
 from extreme_data.meteo_france_data.adamont_data.adamont_scenario import AdamontScenario
+from extreme_data.meteo_france_data.adamont_data.cmip5.temperature_to_year import temperature_minmax_to_year_minmax
 from extreme_data.meteo_france_data.scm_models_data.safran.safran import SafranSnowfall1Day
 from extreme_fit.model.margin_model.linear_margin_model.temporal_linear_margin_models import StationaryTemporalModel
 from extreme_fit.model.margin_model.polynomial_margin_model.gev_altitudinal_models import StationaryAltitudinal
@@ -11,6 +12,7 @@ from extreme_fit.model.margin_model.polynomial_margin_model.models_based_on_pari
 from extreme_fit.model.margin_model.polynomial_margin_model.utils import \
     ALTITUDINAL_GEV_MODELS_BASED_ON_POINTWISE_ANALYSIS
 from projects.altitude_spatial_model.altitudes_fit.altitudes_studies import AltitudesStudies
+from projects.altitude_spatial_model.altitudes_fit.one_fold_analysis.altitude_group import VeyHighAltitudeGroup
 from projects.altitude_spatial_model.altitudes_fit.one_fold_analysis.one_fold_fit import OneFoldFit
 from spatio_temporal_dataset.coordinates.temporal_coordinates.abstract_temporal_covariate_for_fit import \
     TimeTemporalCovariate, AnomalyTemperatureTemporalCovariate
@@ -75,6 +77,24 @@ class TestOneFoldFit(unittest.TestCase):
                                   remove_physically_implausible_models=True)
         self.assertFalse(one_fold_fit.has_at_least_one_valid_model)
 
+    def test_assertion_error_for_a_specific_case(self):
+        self.massif_name = "Thabor"
+        self.model_classes = ALTITUDINAL_GEV_MODELS_BASED_ON_POINTWISE_ANALYSIS[:]
+        self.altitudes = [3000, 3300, 3600]
+        gcm_rcm_couple = ('HadGEM2-ES', 'RegCM4-6')
+        scenario = AdamontScenario.rcp85
+        year_min, year_max = temperature_minmax_to_year_minmax(gcm_rcm_couple[0], scenario, temperature_min=1.0,
+                                                               temperature_max=2.5)
+        dataset = self.load_dataset(AdamontSnowfall,
+                                    scenario=scenario, gcm_rcm_couple=gcm_rcm_couple,
+                                    year_min=year_min, year_max=year_max)
+        one_fold_fit = OneFoldFit(self.massif_name, dataset,
+                                  models_classes=self.model_classes,
+                                  temporal_covariate_for_fit=AnomalyTemperatureTemporalCovariate,
+                                  altitude_class=VeyHighAltitudeGroup,
+                                  only_models_that_pass_goodness_of_fit_test=False,
+                                  remove_physically_implausible_models=True)
+        self.assertTrue(one_fold_fit.has_at_least_one_valid_model)
 
 if __name__ == '__main__':
     unittest.main()