From 756977ccec241e381570af9ea362c0ea2085d9ca Mon Sep 17 00:00:00 2001 From: Le Roux Erwan <erwan.le-roux@irstea.fr> Date: Thu, 27 Feb 2020 13:33:26 +0100 Subject: [PATCH] [paper 1] intensity plots. fit ylabel pour selection curves. --- .../abstract_gev_trend_test.py | 106 +++++++++++++++++- .../qqplot/plot_qqplot.py | 22 +++- ...study_visualizer_for_fit_witout_maximum.py | 2 +- .../main_result_trends_and_return_levels.py | 16 +-- .../plot_selection_curves.py | 4 +- ...dy_visualizer_for_non_stationary_trends.py | 4 + 6 files changed, 134 insertions(+), 20 deletions(-) diff --git a/experiment/trend_analysis/univariate_test/extreme_trend_test/abstract_gev_trend_test.py b/experiment/trend_analysis/univariate_test/extreme_trend_test/abstract_gev_trend_test.py index 8d4fde60..d6a67436 100644 --- a/experiment/trend_analysis/univariate_test/extreme_trend_test/abstract_gev_trend_test.py +++ b/experiment/trend_analysis/univariate_test/extreme_trend_test/abstract_gev_trend_test.py @@ -6,6 +6,7 @@ from cached_property import cached_property from scipy.stats import chi2 from experiment.eurocode_data.utils import EUROCODE_QUANTILE +from experiment.meteo_france_data.scm_models_data.crocus.crocus_variables import AbstractSnowLoadVariable from experiment.trend_analysis.univariate_test.abstract_univariate_test import AbstractUnivariateTest from experiment.trend_analysis.univariate_test.utils import load_temporal_coordinates_and_dataset, \ fitted_linear_margin_estimator @@ -209,13 +210,87 @@ class AbstractGevTrendTest(AbstractUnivariateTest): # Some display function + def intensity_plot_wrt_standard_gumbel(self, massif_name, altitude, psnow): + ax = plt.gca() + sorted_maxima = sorted(self.maxima) + label_generic = '{} massif \nat {} m '.format(massif_name, altitude) + size = 15 + + # Plot for the empirical + standard_gumbel_quantiles = self.get_standard_gumbel_quantiles() + ax.plot(standard_gumbel_quantiles, sorted_maxima, linestyle='None', + label='Empirical model', marker='o') + + # Plot for the selected model + unconstrained_empirical_quantiles = self.compute_empirical_quantiles(self.unconstrained_estimator) + ax.plot(unconstrained_empirical_quantiles, sorted_maxima, + label='Selected model, which is ${}$'.format(self.label)) + print(unconstrained_empirical_quantiles) + + ax_twiny = ax.twiny() + return_periods = [10, 25, 50, 100] + quantiles = self.get_standard_quantiles_for_return_periods(return_periods, psnow) + print(quantiles) + ax_twiny.plot(quantiles, [0 for _ in quantiles], linewidth=0) + ax_twiny.set_xticks(quantiles) + ax_twiny.set_xticklabels([return_period for return_period in return_periods]) + ax_twiny.set_xlabel('Return period w.r.t all annual maxima of GSL (years)', fontsize=size) + + # Plot for the discarded model + if 'Verdon' in massif_name and altitude == 300: + q = [-1.4541688117485054, -1.2811308174310914, -1.216589300814509, -0.7635793791201918, -0.6298883422064275, + -0.5275954855697504, -0.4577268043676126, -0.4497570331795861, -0.1647955002136654, + -0.14492222503785876, -0.139173823298689, -0.11945617994263039, -0.07303100174657867, + -5.497308509286266e-05, 0.13906416388625908, 0.15274793441408543, 0.1717763342727519, + 0.17712605315013535, 0.17900143646245203, 0.371986176207554, 0.51640780422156, 0.7380550963951035, + 0.7783015252180445, 0.887836077295502, 0.917853338231094, 0.9832396811506262, 1.0359396416309927, + 1.1892663813729711, 1.2053261113817888, 1.5695111391491652, 2.3223652143938476, 2.674882764437432, + 2.6955728524900406, 2.8155882785356896, 3.282838470153471, 3.2885313947906765] + color = 'red' + ax.plot(q, sorted_maxima, + label='Discarded model, which is ${}$\n'.format('\mathcal{M}_{\zeta_0, \sigma_1}') + + 'with $\zeta_0=0.84$', + color=color) + + # Extend the curve linear a bit if the return period 50 is not in the quantiles + + def compute_slope_intercept(x, y): + x1, x2 = x[-2:] + y1, y2 = y[-2:] + a = (y2 - y1) / (x2 - x1) + b = y1 - a * x1 + return a, b + + def compute_maxima_corresponding_to_return_period(return_period_quantiles, quantiles, model_maxima): + a, b = compute_slope_intercept(quantiles, model_maxima) + return a * return_period_quantiles + b + + quantile_return_period_50 = quantiles[-1] + if max(q) < quantile_return_period_50: + maxima_extended = compute_maxima_corresponding_to_return_period(quantile_return_period_50, + q, + sorted_maxima) + ax.plot([q[-1], quantile_return_period_50], + [sorted_maxima[-1], maxima_extended], linestyle='--', + color=color) + + all_quantiles = standard_gumbel_quantiles + unconstrained_empirical_quantiles + quantiles + epsilon = 0.5 + ax_lim = [min(all_quantiles) - epsilon, max(all_quantiles) + epsilon] + ax.set_xlim(ax_lim) + ax_twiny.set_xlim(ax_lim) + + ax.legend() + + ax.set_xlabel("Standard Gumbel quantile", fontsize=size) + ax.set_ylabel("Non-zero annual maxima of GSL ({})".format(AbstractSnowLoadVariable.UNIT), fontsize=size) + ax.legend(loc='lower right', prop={'size': 10}) + plt.show() + def qqplot_wrt_standard_gumbel(self, massif_name, altitude): ax = plt.gca() size = 15 - # Standard Gumbel quantiles - standard_gumbel_distribution = GevParams(loc=0, scale=1, shape=0) - n = len(self.years) - standard_gumbel_quantiles = [standard_gumbel_distribution.quantile(i / (n + 1)) for i in range(1, n + 1)] + standard_gumbel_quantiles = self.get_standard_gumbel_quantiles() unconstrained_empirical_quantiles = self.compute_empirical_quantiles(self.unconstrained_estimator) constrained_empirical_quantiles = self.compute_empirical_quantiles(self.constrained_estimator) all_quantiles = standard_gumbel_quantiles + unconstrained_empirical_quantiles + constrained_empirical_quantiles @@ -230,7 +305,14 @@ class AbstractGevTrendTest(AbstractUnivariateTest): ax.plot(standard_gumbel_quantiles, unconstrained_empirical_quantiles, linestyle='None', label=label_generic + '(selected model is ${}$)'.format(self.label), marker='o') if 'Verdon' in massif_name and altitude == 300: - q = [-1.4541688117485054, -1.2811308174310914, -1.216589300814509, -0.7635793791201918, -0.6298883422064275, -0.5275954855697504, -0.4577268043676126, -0.4497570331795861, -0.1647955002136654, -0.14492222503785876, -0.139173823298689, -0.11945617994263039, -0.07303100174657867, -5.497308509286266e-05, 0.13906416388625908, 0.15274793441408543, 0.1717763342727519, 0.17712605315013535, 0.17900143646245203, 0.371986176207554, 0.51640780422156, 0.7380550963951035, 0.7783015252180445, 0.887836077295502, 0.917853338231094, 0.9832396811506262, 1.0359396416309927, 1.1892663813729711, 1.2053261113817888, 1.5695111391491652, 2.3223652143938476, 2.674882764437432, 2.6955728524900406, 2.8155882785356896, 3.282838470153471, 3.2885313947906765] + q = [-1.4541688117485054, -1.2811308174310914, -1.216589300814509, -0.7635793791201918, -0.6298883422064275, + -0.5275954855697504, -0.4577268043676126, -0.4497570331795861, -0.1647955002136654, + -0.14492222503785876, -0.139173823298689, -0.11945617994263039, -0.07303100174657867, + -5.497308509286266e-05, 0.13906416388625908, 0.15274793441408543, 0.1717763342727519, + 0.17712605315013535, 0.17900143646245203, 0.371986176207554, 0.51640780422156, 0.7380550963951035, + 0.7783015252180445, 0.887836077295502, 0.917853338231094, 0.9832396811506262, 1.0359396416309927, + 1.1892663813729711, 1.2053261113817888, 1.5695111391491652, 2.3223652143938476, 2.674882764437432, + 2.6955728524900406, 2.8155882785356896, 3.282838470153471, 3.2885313947906765] print(len(q), len(standard_gumbel_quantiles)) ax.plot(standard_gumbel_quantiles, q, linestyle='None', label=label_generic @@ -251,6 +333,20 @@ class AbstractGevTrendTest(AbstractUnivariateTest): plt.show() + def get_standard_gumbel_quantiles(self): + # Standard Gumbel quantiles + standard_gumbel_distribution = GevParams(loc=0, scale=1, shape=0) + n = len(self.years) + standard_gumbel_quantiles = [standard_gumbel_distribution.quantile(i / (n + 1)) for i in range(1, n + 1)] + return standard_gumbel_quantiles + + def get_standard_quantiles_for_return_periods(self, return_periods, psnow): + n = len(self.years) + p_list = [1 - ((1 / return_period) / psnow) for return_period in return_periods] + standard_gumbel_distribution = GevParams(loc=0, scale=1, shape=0) + corresponding_quantiles = [standard_gumbel_distribution.quantile(p) for p in p_list] + return corresponding_quantiles + def compute_empirical_quantiles(self, estimator): empirical_quantiles = [] for year, maximum in sorted(zip(self.years, self.maxima), key=lambda t: t[1]): 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 48e1b663..4fc33b67 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 @@ -16,9 +16,7 @@ from papers.exceeding_snow_loads.study_visualizer_for_non_stationary_trends impo from extreme_fit.distribution.gev.gev_params import GevParams -def plot_qqplot_for_time_series_with_missing_zeros( - altitude_to_visualizer: Dict[int, StudyVisualizerForNonStationaryTrends], - nb_worst_examples=3): +def extract_time_serimes_with_worst_number_of_zeros(altitude_to_visualizer, nb_worst_examples): # Extract all the values l = [] for a, v in altitude_to_visualizer.items(): @@ -29,9 +27,25 @@ def plot_qqplot_for_time_series_with_missing_zeros( for a, v, m, p in l: print(a, m, p) print('Last standard quantile (depends on the number of data):', last_quantile(p)) + return l + + +def plot_qqplot_for_time_series_with_missing_zeros( + altitude_to_visualizer: Dict[int, StudyVisualizerForNonStationaryTrends], + nb_worst_examples=3): + l = extract_time_serimes_with_worst_number_of_zeros(altitude_to_visualizer, nb_worst_examples) + for a, v, m, p in l: v.qqplot(m) +def plot_intensity_against_gumbel_quantile_for_time_series_with_missing_zeros( + altitude_to_visualizer: Dict[int, StudyVisualizerForNonStationaryTrends], + nb_worst_examples=3): + l = extract_time_serimes_with_worst_number_of_zeros(altitude_to_visualizer, nb_worst_examples) + for a, v, m, p in l: + v.intensity_plot(m, p) + + def plot_qqplot_for_time_series_examples(altitude_to_visualizer: Dict[int, StudyVisualizerForNonStationaryTrends]): marker_altitude_massif_name_for_paper1 = tuples_for_examples_paper1() for color, a, m in marker_altitude_massif_name_for_paper1: @@ -109,4 +123,4 @@ if __name__ == '__main__': # plot_qqplot_wrt_standard_gumbel(altitude_to_visualizer) # plot_hist_psnow(altitude_to_visualizer) # plot_qqplot_for_time_series_examples(altitude_to_visualizer) - plot_qqplot_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/check_mle_convergence_for_trends/without_maximum/study_visualizer_for_fit_witout_maximum.py b/papers/exceeding_snow_loads/check_mle_convergence_for_trends/without_maximum/study_visualizer_for_fit_witout_maximum.py index 6a929d1f..ea904aba 100644 --- a/papers/exceeding_snow_loads/check_mle_convergence_for_trends/without_maximum/study_visualizer_for_fit_witout_maximum.py +++ b/papers/exceeding_snow_loads/check_mle_convergence_for_trends/without_maximum/study_visualizer_for_fit_witout_maximum.py @@ -6,7 +6,7 @@ from cached_property import cached_property from experiment.meteo_france_data.plot.create_shifted_cmap import get_shifted_map from experiment.meteo_france_data.scm_models_data.abstract_study import AbstractStudy -from experiment.exceeding_snow_loads.study_visualizer_for_non_stationary_trends import \ +from papers.exceeding_snow_loads.study_visualizer_for_non_stationary_trends import \ StudyVisualizerForNonStationaryTrends from experiment.trend_analysis.abstract_score import MeanScore 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 3160bed2..4ee5af9c 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,10 +68,10 @@ 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) + plot_selection_curves(altitude_to_visualizer) def major_result(): @@ -91,11 +91,11 @@ def major_result(): if __name__ == '__main__': - # major_result() - intermediate_result(altitudes=paper_altitudes, massif_names=['Beaufortain', 'Vercors'], - uncertainty_methods=[ConfidenceIntervalMethodFromExtremes.my_bayes, - ConfidenceIntervalMethodFromExtremes.ci_mle][1:], - multiprocessing=True) + major_result() + # intermediate_result(altitudes=[900], massif_names=['Beaufortain', 'Vercors'], + # uncertainty_methods=[ConfidenceIntervalMethodFromExtremes.my_bayes, + # ConfidenceIntervalMethodFromExtremes.ci_mle][1:], + # multiprocessing=True) # intermediate_result(altitudes=[900, 1200], massif_names=['Maurienne'], # uncertainty_methods=[ConfidenceIntervalMethodFromExtremes.my_bayes, # ConfidenceIntervalMethodFromExtremes.ci_mle][1:], diff --git a/papers/exceeding_snow_loads/result_trends_and_return_levels/plot_selection_curves.py b/papers/exceeding_snow_loads/result_trends_and_return_levels/plot_selection_curves.py index 910cdb99..cb17d737 100644 --- a/papers/exceeding_snow_loads/result_trends_and_return_levels/plot_selection_curves.py +++ b/papers/exceeding_snow_loads/result_trends_and_return_levels/plot_selection_curves.py @@ -51,8 +51,8 @@ def plot_selection_curves(altitude_to_visualizer: Dict[int, StudyVisualizerForNo label='Significative model', linewidth=linewidth) ax.legend(loc='upper right', prop={'size': size}) - ax.set_ylabel('Time series where the model is selected\n' - 'i.e. where it minimizes the AIC (\%)', fontsize=legend_fontsize) + ax.set_ylabel(' Frequency of selected model w.r.t all time series \n ' + 'i.e. for all massifs and altitudes (\%)', fontsize=legend_fontsize) ax.set_xlabel('Models', fontsize=legend_fontsize) ax.tick_params(axis='both', which='major', labelsize=labelsize) ax.set_xticks(x) 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 52af41d3..7885689d 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 @@ -392,6 +392,10 @@ class StudyVisualizerForNonStationaryTrends(StudyVisualizer): # Part 3 - QQPLOT + def intensity_plot(self, massif_name, psnow, color=None): + trend_test = self.massif_name_to_trend_test_that_minimized_aic[massif_name] + trend_test.intensity_plot_wrt_standard_gumbel(massif_name, self.altitude, psnow) + def qqplot(self, massif_name, color=None): trend_test = self.massif_name_to_trend_test_that_minimized_aic[massif_name] trend_test.qqplot_wrt_standard_gumbel(massif_name, self.altitude) -- GitLab