From d8718ec5c543e075dd7a4e2bc4c6f3a7c5abbacd Mon Sep 17 00:00:00 2001 From: Le Roux Erwan <erwan.le-roux@irstea.fr> Date: Thu, 9 May 2019 15:34:32 +0200 Subject: [PATCH] [SCM][NON STATIONARITY] improve some display before first experiments. --- .../meteo_france_SCM_study/abstract_study.py | 11 +++---- .../main_study_visualizer.py | 32 ++++++++++++++----- .../non_stationary_trends.py | 27 ++++++++++------ .../study_visualization/study_visualizer.py | 2 +- .../visualization/utils.py | 17 +++++++++- 5 files changed, 63 insertions(+), 26 deletions(-) diff --git a/experiment/meteo_france_SCM_study/abstract_study.py b/experiment/meteo_france_SCM_study/abstract_study.py index 37c067a3..f29b6a5a 100644 --- a/experiment/meteo_france_SCM_study/abstract_study.py +++ b/experiment/meteo_france_SCM_study/abstract_study.py @@ -31,7 +31,7 @@ with redirect_stdout(f): class AbstractStudy(object): """ - Les fichiers netcdf sont autodocumentés (on peut les comprendre avec ncdump -h notamment). + Les fichiers netcdf de SAFRAN et CROCUS sont autodocumentés (on peut les comprendre avec ncdump -h notamment). """ REANALYSIS_FOLDER = 'alp_flat/reanalysis' @@ -164,6 +164,8 @@ class AbstractStudy(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) + # Filter, keep massifs present at the altitude of interest + df_centroid = df_centroid.loc[self.study_massif_names] # Build coordinate object from df_centroid return AbstractSpatialCoordinates.from_df(df_centroid) @@ -311,7 +313,8 @@ class AbstractStudy(object): @property def title(self): - return "{} at altitude {}m".format(self.variable_name, self.altitude) + return "{} at altitude {}m ({} mountain chains)".format(self.variable_name, self.altitude, + len(self.study_massif_names)) @property def variable_name(self): @@ -344,7 +347,3 @@ class AbstractStudy(object): assert self.model_name in ['Safran', 'Crocus'] study_folder = 'meteo' if self.model_name is 'Safran' else 'pro' return op.join(self.full_path, self.REANALYSIS_FOLDER, study_folder) - - - - diff --git a/experiment/meteo_france_SCM_study/visualization/study_visualization/main_study_visualizer.py b/experiment/meteo_france_SCM_study/visualization/study_visualization/main_study_visualizer.py index fbd7d185..358ff9ef 100644 --- a/experiment/meteo_france_SCM_study/visualization/study_visualization/main_study_visualizer.py +++ b/experiment/meteo_france_SCM_study/visualization/study_visualization/main_study_visualizer.py @@ -12,6 +12,14 @@ SCM_EXTENDED_STUDIES = [ExtendedSafranSnowfall, ExtendedCrocusSwe, ExtendedCrocu SCM_STUDY_TO_EXTENDED_STUDY = OrderedDict(zip(SCM_STUDIES, SCM_EXTENDED_STUDIES)) +def study_iterator_global(study_classes, only_first_one=False, both_altitude=False, verbose=True, altitudes=None): + for study_class in study_classes: + for study in study_iterator(study_class, only_first_one, both_altitude, verbose, altitudes): + yield study + if only_first_one: + break + + def study_iterator(study_class, only_first_one=False, both_altitude=False, verbose=True, altitudes=None): all_studies = [] is_safran_study = study_class in [SafranSnowfall, ExtendedSafranSnowfall] @@ -20,11 +28,16 @@ def study_iterator(study_class, only_first_one=False, both_altitude=False, verbo print('Loading studies....') for nb_day in nb_days: altis = [1800] if altitudes is None else altitudes + for alti in altis: + if verbose: print('alti: {}, nb_day: {}'.format(alti, nb_day)) study = study_class(altitude=alti, nb_consecutive_days=nb_day) if is_safran_study \ else study_class(altitude=alti) + massifs = study.altitude_to_massif_names[alti] + if verbose: + print('{} massifs: {}'.format(len(massifs), massifs)) yield study if only_first_one and not both_altitude: break @@ -75,7 +88,8 @@ def normal_visualization(temporal_non_stationarity=False): # for study_class in SCM_STUDIES[:1]: for study_class in [CrocusDepth, SafranSnowfall, SafranRainfall, SafranTemperature][1:2]: for study in study_iterator(study_class, only_first_one=only_first_one): - study_visualizer = StudyVisualizer(study, save_to_file=save_to_file, temporal_non_stationarity=temporal_non_stationarity) + study_visualizer = StudyVisualizer(study, save_to_file=save_to_file, + temporal_non_stationarity=temporal_non_stationarity) # study_visualizer.visualize_independent_margin_fits(threshold=[None, 20, 40, 60][0]) # study_visualizer.visualize_annual_mean_values() study_visualizer.visualize_linear_margin_fit(only_first_max_stable=None) @@ -92,17 +106,19 @@ def complete_analysis(only_first_one=False): study_visualizer.visualize_all_experimental_law() print('Study normal') for study in study_iterator(study_class, only_first_one=only_first_one): - study_visualizer = StudyVisualizer(study, save_to_file=True) - study_visualizer.visualize_linear_margin_fit() + study_visualizer = StudyVisualizer(study, save_to_file=True) + study_visualizer.visualize_linear_margin_fit() def trend_analysis(): - save_to_file = True + save_to_file = False only_first_one = True - for study_class in [CrocusSwe, CrocusDepth, SafranSnowfall, SafranRainfall, SafranTemperature][:3]: - for study in study_iterator(study_class, only_first_one=only_first_one, altitudes=[1800, 2100, 2400, 2700]): - study_visualizer = StudyVisualizer(study, save_to_file=save_to_file) - study_visualizer.visualize_temporal_trend_relevance(complete_analysis=not only_first_one) + altitudes = [300, 1200, 2100, 3000][3:] + study_classes = [CrocusSwe, CrocusDepth, SafranSnowfall, SafranRainfall, SafranTemperature] + for study in study_iterator_global(study_classes, only_first_one=only_first_one, altitudes=altitudes): + study_visualizer = StudyVisualizer(study, save_to_file=save_to_file) + study_visualizer.visualize_temporal_trend_relevance(complete_analysis=False) + if __name__ == '__main__': # annual_mean_vizu_compare_durand_study(safran=True, take_mean_value=True, altitude=2100) diff --git a/experiment/meteo_france_SCM_study/visualization/study_visualization/non_stationary_trends.py b/experiment/meteo_france_SCM_study/visualization/study_visualization/non_stationary_trends.py index 6d30e662..4300cf2f 100644 --- a/experiment/meteo_france_SCM_study/visualization/study_visualization/non_stationary_trends.py +++ b/experiment/meteo_france_SCM_study/visualization/study_visualization/non_stationary_trends.py @@ -1,5 +1,6 @@ from typing import Union +from experiment.meteo_france_SCM_study.visualization.utils import align_yaxis_on_zero from extreme_estimator.estimator.abstract_estimator import AbstractEstimator from scipy.stats import chi2 from extreme_estimator.estimator.full_estimator.abstract_full_estimator import \ @@ -68,6 +69,14 @@ class AbstractNonStationaryTrendTest(object): ax.plot(years, difference, color_difference + 'o-') ax.set_ylabel(self.RESULT_ATTRIBUTE_METRIC + ' difference', color=color_difference) + # Plot zero line + years_line = [years[0] -10, years[-1] + 10] + ax.plot(years_line, [0 for _ in years_line], 'k-', label='zero line') + # Plot significative line corresponding to 0.05 relevance + alpha = 0.05 + significative_deviance = chi2.ppf(q=1 - alpha, df=1) + ax.plot(years_line, [significative_deviance for _ in years_line], 'g-', label='significative line') + # Plot the mu1 parameter mu1_trends = [self.get_mu1(starting_point=year) for year in years] ax2 = ax.twinx() @@ -75,16 +84,14 @@ class AbstractNonStationaryTrendTest(object): ax.plot(years, mu1_trends, color_mu1 + 'o-') ax2.set_ylabel('mu1 parameter', color=color_mu1) - # Plot zero line - ax.plot(years, [0 for _ in years], 'k-', label='zero line') - # Plot significative line corresponding to 0.05 relevance - alpha = 0.05 - significative_deviance = chi2.ppf(q=1 - alpha, df=1) - ax.plot(years, [significative_deviance for _ in years], 'g-', label='significative line') - # Add some informations about the graph - - ax.set_xlabel('year') - ax.set_title(self.display_name) + ax.set_xlabel('starting year for the linear trend of mu1') + align_yaxis_on_zero(ax, ax2) + title = self.display_name + first = mu1_trends[0] + last = mu1_trends[-1] + title += '\n mu1: first {}\nlast {}'.format(first, last) + title += '; equals? {}'.format(first == last) + ax.set_title(title) ax.legend() @property diff --git a/experiment/meteo_france_SCM_study/visualization/study_visualization/study_visualizer.py b/experiment/meteo_france_SCM_study/visualization/study_visualization/study_visualizer.py index ea9d5b5c..799ad66a 100644 --- a/experiment/meteo_france_SCM_study/visualization/study_visualization/study_visualizer.py +++ b/experiment/meteo_france_SCM_study/visualization/study_visualization/study_visualizer.py @@ -141,7 +141,7 @@ class StudyVisualizer(object): trend_tests = [ConditionalIndedendenceLocationTrendTest(self.dataset)] max_stable_models = load_test_max_stable_models(default_covariance_function=self.default_covariance_function) - for max_stable_model in max_stable_models[:1]: + for max_stable_model in [max_stable_models[1], max_stable_models[-2]]: trend_tests.append(MaxStableLocationTrendTest(self.dataset, max_stable_model)) nb_trend_tests = len(trend_tests) diff --git a/experiment/meteo_france_SCM_study/visualization/utils.py b/experiment/meteo_france_SCM_study/visualization/utils.py index 19101351..48ac8b30 100644 --- a/experiment/meteo_france_SCM_study/visualization/utils.py +++ b/experiment/meteo_france_SCM_study/visualization/utils.py @@ -35,11 +35,26 @@ def get_km_formatter(): return tkr.FuncFormatter(numfmt) # create your custom formatter function -def create_adjusted_axes(nb_rows, nb_columns, figsize=(16,10), subplot_space=0.5): +def create_adjusted_axes(nb_rows, nb_columns, figsize=(16, 10), subplot_space=0.5): fig, axes = plt.subplots(nb_rows, nb_columns, figsize=figsize) fig.subplots_adjust(hspace=subplot_space, wspace=subplot_space) return axes +def align_yaxis(ax1, v1, ax2, v2): + # From https://stackoverflow.com/questions/10481990/matplotlib-axis-with-two-scales-shared-origin + """adjust ax2 ylimit so that v2 in ax2 is aligned to v1 in ax1""" + _, y1 = ax1.transData.transform((0, v1)) + _, y2 = ax2.transData.transform((0, v2)) + inv = ax2.transData.inverted() + _, dy = inv.transform((0, 0)) - inv.transform((0, y1 - y2)) + miny, maxy = ax2.get_ylim() + ax2.set_ylim(miny + dy, maxy + dy) + + +def align_yaxis_on_zero(ax1, ax2): + align_yaxis(ax1, 0, ax2, 0) + + if __name__ == '__main__': example_plot_df() -- GitLab