From bdcaf002c989e6e1346988fd255642ca6e28e19d Mon Sep 17 00:00:00 2001
From: Le Roux Erwan <erwan.le-roux@irstea.fr>
Date: Thu, 30 Apr 2020 11:57:04 +0200
Subject: [PATCH] [contrasting] add a validation for the change in the ratio

---
 extreme_trend/abstract_gev_trend_test.py      |  5 +-
 .../main_snowfall_article.py                  |  7 +--
 .../study_visualizer_for_mean_values.py       | 50 +++++++++++++++----
 .../validation_plot.py                        | 32 +++++++++---
 4 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/extreme_trend/abstract_gev_trend_test.py b/extreme_trend/abstract_gev_trend_test.py
index eac300d0..ce17e3c3 100644
--- a/extreme_trend/abstract_gev_trend_test.py
+++ b/extreme_trend/abstract_gev_trend_test.py
@@ -385,10 +385,9 @@ class AbstractGevTrendTest(object):
 
     # Mean value
 
-    @property
-    def unconstrained_average_mean_value(self) -> float:
+    def unconstrained_average_mean_value(self, year_min, year_max) -> float:
         mean_values = []
-        for year in self.years:
+        for year in range(year_min, year_max+1):
             mean = self.get_unconstrained_gev_params(year).mean
             mean_values.append(mean)
         average_mean_value = np.mean(mean_values)
diff --git a/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/main_snowfall_article.py b/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/main_snowfall_article.py
index 8c409087..f7137c76 100644
--- a/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/main_snowfall_article.py
+++ b/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/main_snowfall_article.py
@@ -72,9 +72,10 @@ def intermediate_result(altitudes, massif_names=None,
             _ = compute_minimized_aic(visualizer)
 
     # Plots
-    validation_plot(altitude_to_visualizer)
-    plot_snowfall_mean(altitude_to_visualizer)
-    plot_snowfall_time_derivative_mean(altitude_to_visualizer)
+    validation_plot(altitude_to_visualizer, order_derivative=0)
+    validation_plot(altitude_to_visualizer, order_derivative=1)
+    # plot_snowfall_mean(altitude_to_visualizer)
+    # plot_snowfall_time_derivative_mean(altitude_to_visualizer)
 
 
 def major_result():
diff --git a/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/study_visualizer_for_mean_values.py b/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/study_visualizer_for_mean_values.py
index 9fd53430..ca2cfce6 100644
--- a/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/study_visualizer_for_mean_values.py
+++ b/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/study_visualizer_for_mean_values.py
@@ -27,6 +27,13 @@ class StudyVisualizerForMeanValues(StudyVisualizerForNonStationaryTrends):
                          non_stationary_trend_test_to_marker, fit_method, select_only_acceptable_shape_parameter,
                          fit_gev_only_on_non_null_maxima, fit_only_time_series_with_ninety_percent_of_non_null_values)
 
+
+    def plot_abstract_fast(self, massif_name_to_value, label, graduation=10.0, cmap=plt.cm.coolwarm, add_x_label=True,
+                           negative_and_positive_values=True):
+        super().plot_abstract(massif_name_to_value, label, label, self.fit_method, graduation, cmap, add_x_label, negative_and_positive_values)
+
+    # Study of the mean
+
     @cached_property
     def massif_name_to_empirical_mean(self):
         massif_name_to_empirical_value = {}
@@ -36,23 +43,48 @@ class StudyVisualizerForMeanValues(StudyVisualizerForNonStationaryTrends):
 
     @cached_property
     def massif_name_to_model_mean(self):
-        massif_name_to_parameter_value = {}
+        massif_name_to_model_value = {}
         for massif_name, trend_test in self.massif_name_to_trend_test_that_minimized_aic.items():
-            parameter_value = trend_test.unconstrained_average_mean_value
-            massif_name_to_parameter_value[massif_name] = parameter_value
-        return massif_name_to_parameter_value
+            parameter_value = trend_test.unconstrained_average_mean_value(self.study.year_min, self.study.year_max)
+            massif_name_to_model_value[massif_name] = parameter_value
+        return massif_name_to_model_value
 
     @cached_property
     def massif_name_to_relative_difference_for_mean(self):
         massif_name_to_relative_difference = {}
         for massif_name in self.massif_name_to_trend_test_that_minimized_aic.keys():
             e = self.massif_name_to_empirical_mean[massif_name]
-            p = self.massif_name_to_model_mean[massif_name]
-            relative_diference = 100 * (p-e) / e
+            m = self.massif_name_to_model_mean[massif_name]
+            relative_diference = 100 * (m-e) / e
             massif_name_to_relative_difference[massif_name] = relative_diference
         return massif_name_to_relative_difference
 
-    def plot_abstract_fast(self, massif_name_to_value, label, graduation=10.0, cmap=plt.cm.coolwarm, add_x_label=True,
-                           negative_and_positive_values=True):
-        super().plot_abstract(massif_name_to_value, label, label, self.fit_method, graduation, cmap, add_x_label, negative_and_positive_values)
+    # Study of the change in the mean
 
+    @cached_property
+    def massif_name_to_change_ratio_in_empirical_mean(self):
+        massif_name_to_empirical_value = {}
+        for massif_name, maxima in self.study.massif_name_to_annual_maxima.items():
+            index = self.study.ordered_years.index(1989)
+            maxima_before, maxima_after = maxima[:index+1], maxima[index+1:]
+            massif_name_to_empirical_value[massif_name] = np.mean(maxima_after) / np.mean(maxima_before)
+        return massif_name_to_empirical_value
+
+    @cached_property
+    def massif_name_to_change_ratio_in_model_mean(self):
+        massif_name_to_parameter_value = {}
+        for massif_name, trend_test in self.massif_name_to_trend_test_that_minimized_aic.items():
+            model_mean_before = trend_test.unconstrained_average_mean_value(year_min=self.study.year_min, year_max=1989)
+            model_mean_after = trend_test.unconstrained_average_mean_value(year_min=1990, year_max=self.study.year_max)
+            massif_name_to_parameter_value[massif_name] = model_mean_after / model_mean_before
+        return massif_name_to_parameter_value
+
+    @cached_property
+    def massif_name_to_relative_difference_for_change_ratio_in_mean(self):
+        massif_name_to_relative_difference = {}
+        for massif_name in self.massif_name_to_trend_test_that_minimized_aic.keys():
+            e = self.massif_name_to_change_ratio_in_empirical_mean[massif_name]
+            m = self.massif_name_to_change_ratio_in_model_mean[massif_name]
+            relative_diference = 100 * (m-e) / e
+            massif_name_to_relative_difference[massif_name] = relative_diference
+        return massif_name_to_relative_difference
\ No newline at end of file
diff --git a/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/validation_plot.py b/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/validation_plot.py
index 2da8bda5..4847c939 100644
--- a/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/validation_plot.py
+++ b/projects/contrasting_trends_in_snow_loads/snowfall_versus_time_and_altitude/validation_plot.py
@@ -10,34 +10,42 @@ from projects.ogorman.gorman_figures.figure1.study_visualizer_for_double_station
     StudyVisualizerForReturnLevelChange
 
 
-def validation_plot(altitude_to_visualizer: Dict[int, StudyVisualizerForMeanValues]):
+def validation_plot(altitude_to_visualizer: Dict[int, StudyVisualizerForMeanValues], order_derivative=0):
     # Plot the mean empirical, the mean parametric and the relative difference between the two
     altitudes = list(altitude_to_visualizer.keys())
     study_visualizer = list(altitude_to_visualizer.values())[0]
     altitude_to_relative_differences = {}
+    if order_derivative == 0:
+        plot_function = plot_relative_difference_map_order_zero
+    else:
+        plot_function = plot_relative_difference_map_order_one
     # Plot map for the repartition of the difference
     for altitude, visualizer in altitude_to_visualizer.items():
-        altitude_to_relative_differences[altitude] = plot_relative_difference_map(visualizer)
+        altitude_to_relative_differences[altitude] = plot_function(visualizer)
         study_visualizer.show_or_save_to_file(add_classic_title=False, dpi=500)
     # Shoe plot with respect to the altitude.
-    plot_shoe_relative_differences_distribution(altitude_to_relative_differences, altitudes)
+    plot_shoe_relative_differences_distribution(altitude_to_relative_differences, altitudes, study_visualizer, order_derivative)
     study_visualizer.show_or_save_to_file(add_classic_title=False, dpi=500)
     plt.close()
 
 
-def plot_shoe_relative_differences_distribution(altitude_to_relative_differences, altitudes):
+def plot_shoe_relative_differences_distribution(altitude_to_relative_differences, altitudes, visualizer, order_derivative):
+    study = visualizer.study
     ax = plt.gca()
     width = 150
     ax.boxplot([altitude_to_relative_differences[a] for a in altitudes], positions=altitudes, widths=width)
     ax.set_xlim([min(altitudes) - width, max(altitudes) + width])
-    ylabel = 'Relative difference of the model mean w.r.t. the empirical mean (\%)'
+    moment = '' if order_derivative == 0 else 'time derivative of '
+    ylabel = 'Relative difference of the {} model mean \n' \
+             'w.r.t. the {}empirical mean of {} (\%)'.format(moment, moment, SCM_STUDY_CLASS_TO_ABBREVIATION[type(study)])
+    visualizer.plot_trends = ylabel
     ax.set_ylabel(ylabel)
     ax.set_xlabel('Altitude (m)')
     ax.legend()
     ax.grid()
 
 
-def plot_relative_difference_map(visualizer: StudyVisualizerForMeanValues):
+def plot_relative_difference_map_order_zero(visualizer: StudyVisualizerForMeanValues):
     study = visualizer.study
     label = ' mean annual maxima of {} ({})'.format(SCM_STUDY_CLASS_TO_ABBREVIATION[type(study)], study.variable_unit)
     visualizer.plot_abstract_fast(massif_name_to_value=visualizer.massif_name_to_empirical_mean,
@@ -48,3 +56,15 @@ def plot_relative_difference_map(visualizer: StudyVisualizerForMeanValues):
                                   label='Relative difference of the model mean w.r.t. the empirical mean \n'
                                         'for the ' + label, graduation=1)
     return list(visualizer.massif_name_to_relative_difference_for_mean.values())
+
+def plot_relative_difference_map_order_one(visualizer: StudyVisualizerForMeanValues):
+    study = visualizer.study
+    label = ' time derivative of mean annual maxima of {} ({})'.format(SCM_STUDY_CLASS_TO_ABBREVIATION[type(study)], study.variable_unit)
+    visualizer.plot_abstract_fast(massif_name_to_value=visualizer.massif_name_to_change_ratio_in_empirical_mean,
+                                  label='Empirical' + label, negative_and_positive_values=False, graduation=0.5)
+    visualizer.plot_abstract_fast(massif_name_to_value=visualizer.massif_name_to_change_ratio_in_model_mean,
+                                  label='Model' + label, negative_and_positive_values=False, graduation=0.5)
+    visualizer.plot_abstract_fast(massif_name_to_value=visualizer.massif_name_to_relative_difference_for_change_ratio_in_mean,
+                                  label='Relative difference of the model mean w.r.t. the empirical mean \n'
+                                        'for the ' + label, graduation=1)
+    return list(visualizer.massif_name_to_relative_difference_for_mean.values())
\ No newline at end of file
-- 
GitLab