From 942ba36744120d3a7e2019385cc12dc666ae82f9 Mon Sep 17 00:00:00 2001
From: Le Roux Erwan <erwan.le-roux@irstea.fr>
Date: Thu, 27 Feb 2020 16:20:51 +0100
Subject: [PATCH] [paper 1] appendix 2 plot. for the diagnosis when we have few
 data. add plt_exceedance_snow

---
 .../qqplot/plot_qqplot.py                     | 71 +++++++++++++++++--
 .../main_result_trends_and_return_levels.py   |  4 +-
 ...dy_visualizer_for_non_stationary_trends.py | 20 +++++-
 3 files changed, 87 insertions(+), 8 deletions(-)

diff --git a/papers/exceeding_snow_loads/check_mle_convergence_for_trends/qqplot/plot_qqplot.py b/papers/exceeding_snow_loads/check_mle_convergence_for_trends/qqplot/plot_qqplot.py
index 4fc33b67..5e862f55 100644
--- a/papers/exceeding_snow_loads/check_mle_convergence_for_trends/qqplot/plot_qqplot.py
+++ b/papers/exceeding_snow_loads/check_mle_convergence_for_trends/qqplot/plot_qqplot.py
@@ -6,10 +6,10 @@ import numpy as np
 from matplotlib.ticker import PercentFormatter
 
 from experiment.meteo_france_data.scm_models_data.crocus.crocus import CrocusSnowLoadTotal
-from experiment.meteo_france_data.scm_models_data.visualization.study_visualization.main_study_visualizer import \
-    ALL_ALTITUDES_WITHOUT_NAN
 from extreme_fit.model.margin_model.linear_margin_model.abstract_temporal_linear_margin_model import \
     TemporalMarginFitMethod
+from extreme_fit.model.result_from_model_fit.result_from_extremes.abstract_extract_eurocode_return_level import \
+    AbstractExtractEurocodeReturnLevel
 from papers.exceeding_snow_loads.data.main_example_swe_total_plot import tuples_for_examples_paper1
 from papers.exceeding_snow_loads.study_visualizer_for_non_stationary_trends import \
     StudyVisualizerForNonStationaryTrends
@@ -53,10 +53,71 @@ def plot_qqplot_for_time_series_examples(altitude_to_visualizer: Dict[int, Study
         v.qqplot(m, color)
 
 
+def plot_exceedance_psnow(altitude_to_visualizer: Dict[int, StudyVisualizerForNonStationaryTrends]):
+    altitudes = list(altitude_to_visualizer.keys())
+    percentages_list = []
+    for a, v in altitude_to_visualizer.items():
+        percentages = v.mean_percentage_of_standards_for_massif_names_with_years_without_snow()
+        percentages_list.append(percentages)
+
+    ax2 = plt.gca()
+    ax = ax2.twinx()
+    ax2.bar(altitudes, [len(v.massifs_names_with_year_without_snow) for v in altitude_to_visualizer.values()],
+            width=150, label='Number of time series', edgecolor='black', hatch='x', fill=False)
+    ax2.set_ylabel('Number of time series with some\nannual maxima equal to zero, i.e. with $P(Y > 0) < 1$')
+
+    mean = [p[1] for p in percentages_list]
+    alpha = 0.2
+    color = 'blue'
+    label_name = 'ratio'
+
+    confidence_interval_str = ' {}'.format(AbstractExtractEurocodeReturnLevel.percentage_confidence_interval)
+    confidence_interval_str += '% confidence interval'
+    ax.plot(altitudes, mean, linestyle='--', marker='o', color=color,
+            label=label_name)
+    lower_bound = [p[0] for p in percentages_list]
+    upper_bound = [p[2] for p in percentages_list]
+
+    ax.fill_between(altitudes, lower_bound, upper_bound, color=color, alpha=alpha,
+                    label=label_name + confidence_interval_str)
+    # Plot error bars
+    yerr = np.array([[d[1] - d[0], d[2] - d[1]] for d in zip(lower_bound, mean, upper_bound)]).transpose()
+    ax.bar(altitudes, mean, ecolor='black', capsize=5, yerr=yerr)
+
+    ax.set_xticks(altitudes)
+    ax.set_yticks([j * 20 for j in range(6)])
+    ax2.set_yticks([j * 4 for j in range(6)])
+
+    ax.set_xlabel('Altitude (m)')
+    ax.set_ylabel('Mean ratio, i.e. French standards divided by return levels (%)')
+    size = 10
+    ax.legend(loc='upper left', prop={'size': size})
+    ax.grid()
+    ax2.legend(loc='upper right', prop={'size': size})
+
+    plt.show()
+
+
 def plot_hist_psnow(altitude_to_visualizer: Dict[int, StudyVisualizerForNonStationaryTrends]):
     """Plot an histogram of psnow containing data from all the visualizers given as argument"""
+    """
+    Altitude with psnow < 1
+    300 13 ['Chablais', 'Aravis', 'Mont-Blanc', 'Bauges', 'Beaufortain', 'Chartreuse', 'Belledonne', 'Maurienne', 'Vanoise', 'Oisans', 'Devoluy', 'Haut_Var-Haut_Verdon', 'Mercantour']
+    600 4 ['Parpaillon', 'Ubaye', 'Haut_Var-Haut_Verdon', 'Mercantour']
+    900 1 ['Mercantour']
+    1200 1 ['Mercantour']
+
+    300m all massifs with data except Vercors (for 9 we don't have data)
+    600m the 4 most southern massif
+    900 and 1200 for the most southern of all massif
+
+    """
     ax = plt.gca()
     # Gather the data
+    for a, v in altitude_to_visualizer.items():
+        m = v.massifs_names_with_year_without_snow
+        if len(m) > 0:
+            print(a, len(m), m)
     data = [list(v.massif_name_to_psnow.values()) for v in altitude_to_visualizer.values()]
     data = list(chain.from_iterable(data))
     print(sorted(data))
@@ -111,7 +172,7 @@ if __name__ == '__main__':
     300 Haut_Var-Haut_Verdon 0.8446498197950775
 
     """
-    altitudes = [300, 600, 900, 1200, 1500, 1800][:2]
+    altitudes = [300, 600, 900, 1200, 1500, 1800][:-2]
     # altitudes = ALL_ALTITUDES_WITHOUT_NAN
     # altitudes = [900, 1800, 2700]
     altitude_to_visualizer = {altitude: StudyVisualizerForNonStationaryTrends(CrocusSnowLoadTotal(altitude=altitude),
@@ -122,5 +183,7 @@ if __name__ == '__main__':
 
     # plot_qqplot_wrt_standard_gumbel(altitude_to_visualizer)
     # plot_hist_psnow(altitude_to_visualizer)
+    plot_exceedance_psnow(altitude_to_visualizer)
+
     # plot_qqplot_for_time_series_examples(altitude_to_visualizer)
-    plot_intensity_against_gumbel_quantile_for_time_series_with_missing_zeros(altitude_to_visualizer, nb_worst_examples=3)
+    # plot_intensity_against_gumbel_quantile_for_time_series_with_missing_zeros(altitude_to_visualizer, nb_worst_examples=3)
diff --git a/papers/exceeding_snow_loads/result_trends_and_return_levels/main_result_trends_and_return_levels.py b/papers/exceeding_snow_loads/result_trends_and_return_levels/main_result_trends_and_return_levels.py
index 4ee5af9c..7f20be5a 100644
--- a/papers/exceeding_snow_loads/result_trends_and_return_levels/main_result_trends_and_return_levels.py
+++ b/papers/exceeding_snow_loads/result_trends_and_return_levels/main_result_trends_and_return_levels.py
@@ -68,8 +68,8 @@ def intermediate_result(altitudes, massif_names=None,
     # Plots
     # plot_trend_map(altitude_to_visualizer)
     # plot_diagnosis_risk(altitude_to_visualizer)
-    plot_trend_curves(altitude_to_visualizer={a: v for a, v in altitude_to_visualizer.items() if a >= 900})
-    # plot_uncertainty_massifs(altitude_to_visualizer)
+    # plot_trend_curves(altitude_to_visualizer={a: v for a, v in altitude_to_visualizer.items() if a >= 900})
+    plot_uncertainty_massifs(altitude_to_visualizer)
     # plot_uncertainty_histogram(altitude_to_visualizer)
     plot_selection_curves(altitude_to_visualizer)
 
diff --git a/papers/exceeding_snow_loads/study_visualizer_for_non_stationary_trends.py b/papers/exceeding_snow_loads/study_visualizer_for_non_stationary_trends.py
index 7885689d..7d71e1b7 100644
--- a/papers/exceeding_snow_loads/study_visualizer_for_non_stationary_trends.py
+++ b/papers/exceeding_snow_loads/study_visualizer_for_non_stationary_trends.py
@@ -98,6 +98,10 @@ class StudyVisualizerForNonStationaryTrends(StudyVisualizer):
         return {m: np.count_nonzero(maxima) / len(maxima) for m, (_, maxima) in
                 self.massif_name_to_years_and_maxima.items()}
 
+    @property
+    def massifs_names_with_year_without_snow(self):
+        return [m for m, psnow in self.massif_name_to_psnow.items() if psnow < 1]
+
     @cached_property
     def massif_name_to_eurocode_quantile_level_in_practice(self):
         """Due to missing data, the the eurocode quantile which 0.98 if we have all the data
@@ -453,8 +457,20 @@ class StudyVisualizerForNonStationaryTrends(StudyVisualizer):
         else:
             mean_changes = [
                 compute_mean_change([v for m, v in self.massif_name_to_relative_change_value.items()
-                                    if massif_name_to_region_name[m] in regions])
-                for regions in [AbstractExtendedStudy.real_region_names[:2], AbstractExtendedStudy.real_region_names[2:]]
+                                     if massif_name_to_region_name[m] in regions])
+                for regions in
+                [AbstractExtendedStudy.real_region_names[:2], AbstractExtendedStudy.real_region_names[2:]]
             ]
 
         return (self.altitude, *mean_changes)
+
+    def mean_percentage_of_standards_for_massif_names_with_years_without_snow(self):
+        model_subset_for_uncertainty = ModelSubsetForUncertainty.non_stationary_gumbel_and_gev
+        ci_method = ConfidenceIntervalMethodFromExtremes.ci_mle
+        percentages = []
+        for massif_name in self.massifs_names_with_year_without_snow:
+            eurocode_value = self.massif_name_to_eurocode_values[massif_name]
+            eurocode_uncertainty = self.triplet_to_eurocode_uncertainty[(ci_method, model_subset_for_uncertainty, massif_name)]
+            percentage = 100 * np.array(eurocode_uncertainty.triplet) / eurocode_value
+            percentages.append(percentage)
+        return np.round(np.mean(percentages, axis=0))
-- 
GitLab