From 9f042157f5e66a6a36584d64cd02e9e69ca2340c Mon Sep 17 00:00:00 2001 From: Le Roux Erwan <erwan.le-roux@irstea.fr> Date: Wed, 11 Nov 2020 18:34:02 +0100 Subject: [PATCH] [snow projection] improve rank & bias plots. remove dataset attribute for abstract_adamont_study.py. --- .../adamont_data/abstract_adamont_study.py | 16 +++--- .../adamont_data/adamont_scenario.py | 3 +- .../comparison_historical_visualizer.py | 55 +++++++++++++++---- .../comparison_with_scm/comparison_plot.py | 35 ++++++++++-- .../main_comparison_on_rcp_85_extended.py | 54 ++++++++++++++---- 5 files changed, 127 insertions(+), 36 deletions(-) diff --git a/extreme_data/meteo_france_data/adamont_data/abstract_adamont_study.py b/extreme_data/meteo_france_data/adamont_data/abstract_adamont_study.py index 43eae3c0..2cd805a7 100644 --- a/extreme_data/meteo_france_data/adamont_data/abstract_adamont_study.py +++ b/extreme_data/meteo_france_data/adamont_data/abstract_adamont_study.py @@ -102,23 +102,24 @@ class AbstractAdamontStudy(AbstractStudy): @cached_property def flat_mask(self): - zs_list = [int(e) for e in np.array(self.dataset.variables['ZS'])] + zs_list = [int(e) for e in np.array(self.datasets[0].variables['ZS'])] + if len(self.datasets) > 1: + zs_list_bis = [int(e) for e in np.array(self.datasets[1].variables['ZS'])] + assert all([a == b for a, b in zip(zs_list, zs_list_bis)]) return np.array(zs_list) == self.altitude @cached_property def study_massif_names(self) -> List[str]: - massif_ids = np.array(self.dataset.variables['MASSIF_NUMBER'])[self.flat_mask] + massif_ids = np.array(self.datasets[0].variables['MASSIF_NUMBER'])[self.flat_mask] + if len(self.datasets) > 1: + massif_ids_bis = np.array(self.datasets[1].variables['MASSIF_NUMBER'])[self.flat_mask] + assert all(massif_ids == massif_ids_bis) return [massif_number_to_massif_name[massif_id] for massif_id in massif_ids] @cached_property def datasets(self): return [Dataset(file_path) for file_path in self.nc_file_paths] - @property - def dataset(self): - # todo: improve that - return self.datasets[0] - # PATHS @property @@ -150,4 +151,5 @@ class AbstractAdamontStudy(AbstractStudy): scenario_name, self.region_name, suffix_nc_file) file_paths.append(op.join(files_path, nc_file)) + assert len(file_paths) <= 2, 'change my code to handle datasets of length larger than' return file_paths diff --git a/extreme_data/meteo_france_data/adamont_data/adamont_scenario.py b/extreme_data/meteo_france_data/adamont_data/adamont_scenario.py index f95decdb..0791a974 100644 --- a/extreme_data/meteo_france_data/adamont_data/adamont_scenario.py +++ b/extreme_data/meteo_france_data/adamont_data/adamont_scenario.py @@ -67,7 +67,8 @@ def get_suffix_for_the_nc_file(adamont_scenario, gcm_rcm_couple): def scenario_to_str(adamont_scenario): - return str(adamont_scenario).split('.')[-1].upper() + return '+'.join([str(real_adamont_scenario).split('.')[-1].upper() + for real_adamont_scenario in scenario_to_real_scenarios(adamont_scenario)]) def scenario_to_real_scenarios(adamont_scenario): diff --git a/projects/projected_snowfall/comparison_with_scm/comparison_historical_visualizer.py b/projects/projected_snowfall/comparison_with_scm/comparison_historical_visualizer.py index 72beeb55..652a5581 100644 --- a/projects/projected_snowfall/comparison_with_scm/comparison_historical_visualizer.py +++ b/projects/projected_snowfall/comparison_with_scm/comparison_historical_visualizer.py @@ -2,9 +2,11 @@ import matplotlib.pyplot as plt import numpy as np from cached_property import cached_property from matplotlib.lines import Line2D +import os.path as op +from extreme_data.meteo_france_data.adamont_data.abstract_adamont_study import AbstractAdamontStudy from extreme_data.meteo_france_data.adamont_data.adamont_scenario import get_color_from_gcm_rcm_couple, \ - gcm_rcm_couple_to_str, gcm_rcm_couple_to_color + gcm_rcm_couple_to_str, gcm_rcm_couple_to_color, scenario_to_str from extreme_data.meteo_france_data.adamont_data.adamont_studies import AdamontStudies from extreme_data.meteo_france_data.scm_models_data.abstract_study import AbstractStudy from extreme_data.meteo_france_data.scm_models_data.visualization.main_study_visualizer import \ @@ -14,6 +16,7 @@ from projects.altitude_spatial_model.altitudes_fit.altitudes_studies import Alti class ComparisonHistoricalVisualizer(StudyVisualizer): + study: AbstractAdamontStudy def __init__(self, scm_study: AbstractStudy, adamont_studies: AdamontStudies, @@ -61,19 +64,24 @@ class ComparisonHistoricalVisualizer(StudyVisualizer): massif_name_to_bias_list = {} for massif_name in self.massif_names: bias_list, gcm_rcm_couples = self.compute_bias_list_in_the_mean(massif_name, relative, study_method) - massif_name_to_bias_list[massif_name] = bias_list + if len(bias_list) == len(self.adamont_studies.gcm_rcm_couples): + massif_name_to_bias_list[massif_name] = bias_list return massif_name_to_bias_list + def massif_name_to_mean_bias_in_the_mean(self, plot_maxima=True, relative=False): + return {m: np.mean(l) for m, l in self.massif_name_to_bias_list_in_the_mean(plot_maxima, relative).items()} + @property def massif_name_to_rank(self): massif_name_to_rank = {} for massif_name, bias_list in self.massif_name_to_bias_list_in_the_mean(plot_maxima=True).items(): # Count the number of bias negative nb_of_negative = sum([b < 0 for b in bias_list]) - # Rank starts to 1 - massif_name_to_rank[massif_name] = float(1 + nb_of_negative) + # Rank starts to 0 + massif_name_to_rank[massif_name] = float(nb_of_negative) return massif_name_to_rank + # Map gcm_rcm_couple to bias list (ordered by the massif_names) @cached_property @@ -163,10 +171,12 @@ class ComparisonHistoricalVisualizer(StudyVisualizer): def plot_map_with_the_rank(self): massif_name_to_value = self.massif_name_to_rank - max_abs_change = self.adamont_studies.nb_ensemble_members + 1 - ylabel = 'Rank of the mean maxima\n,' \ - 'which is between 1 (lowest) and {} (largest)'.format(max_abs_change) - plot_name = ylabel + max_abs_change = self.adamont_studies.nb_ensemble_members + ylabel = 'Rank of the mean maxima\n' \ + 'for the period {}-{} and the scenario {}\n' \ + 'which is between 0 (lowest) and {} (largest)'.format(self.study.year_min, self.study.year_max, + scenario_to_str(self.study.scenario), max_abs_change) + plot_name = op.join('rank', ylabel) self.plot_map(cmap=plt.cm.coolwarm, graduation=1, label=ylabel, massif_name_to_value=massif_name_to_value, @@ -175,9 +185,32 @@ class ComparisonHistoricalVisualizer(StudyVisualizer): altitude=self.altitude, add_colorbar=True, max_abs_change=max_abs_change, - massif_name_to_text={m: str(v) for m, v in massif_name_to_value.items()}, + massif_name_to_text={m: str(int(v)) for m, v in massif_name_to_value.items()}, # xlabel=self.altitude_group.xlabel, ) - def plot_map_with_the_bias_in_the_mean(self, relative=True): - pass + def plot_map_with_the_mean_bias_in_the_mean(self, relative=True): + massif_name_to_value = self.massif_name_to_mean_bias_in_the_mean(plot_maxima=True, relative=relative) + name = 'relative difference' if relative else 'difference' + abreviation = ADAMONT_STUDY_CLASS_TO_ABBREVIATION[type(self.study)] + unit = '\%' if relative else self.study.variable_unit + ylabel = 'Mean {} of the ensemble members with the reanalysis\n' \ + 'for the period {}-{} and the scenario {}\n' \ + 'in the mean annual maxima of {} ({})'.format(name, + self.study.year_min, self.study.year_max, + scenario_to_str(self.study.scenario), + abreviation, unit) + plot_name = op.join(name, ylabel) + self.plot_map(cmap=plt.cm.coolwarm, graduation=10, + label=ylabel, + massif_name_to_value=massif_name_to_value, + plot_name=plot_name, add_x_label=True, + negative_and_positive_values=True, + altitude=self.altitude, + add_colorbar=True, + massif_name_to_text={m: ('+' if v > 0 else '') + + str(int(v)) + + ('\%' if relative else '') + for m, v in massif_name_to_value.items()}, + # xlabel=self.altitude_group.xlabel, + ) diff --git a/projects/projected_snowfall/comparison_with_scm/comparison_plot.py b/projects/projected_snowfall/comparison_with_scm/comparison_plot.py index 5ebafb6b..7c50dced 100644 --- a/projects/projected_snowfall/comparison_with_scm/comparison_plot.py +++ b/projects/projected_snowfall/comparison_with_scm/comparison_plot.py @@ -1,9 +1,11 @@ import matplotlib.pyplot as plt from typing import Dict +import numpy as np from matplotlib.lines import Line2D -from extreme_data.meteo_france_data.adamont_data.adamont_scenario import gcm_rcm_couple_to_color, gcm_rcm_couple_to_str +from extreme_data.meteo_france_data.adamont_data.adamont_scenario import gcm_rcm_couple_to_color, gcm_rcm_couple_to_str, \ + scenario_to_str from projects.projected_snowfall.comparison_with_scm.comparison_historical_visualizer import \ ComparisonHistoricalVisualizer @@ -11,17 +13,38 @@ from projects.projected_snowfall.comparison_with_scm.comparison_historical_visua def individual_plot(visualizer: ComparisonHistoricalVisualizer): # visualizer.adamont_studies.plot_maxima_time_series_adamont(visualizer.massif_names, visualizer.scm_study) # visualizer.shoe_plot_bias_maxima_comparison() - # for relative in [True, False]: - # visualizer.plot_map_with_the_bias_in_the_mean(relative) + for relative in [True, False]: + visualizer.plot_map_with_the_mean_bias_in_the_mean(relative) visualizer.plot_map_with_the_rank() + # for relative # for plot_maxima in [True, False][:1]: # visualizer.plot_comparison(plot_maxima) -def collective_plot(altitude_to_visualizer): - # bias_of_the_mean_with_the_altitude(altitude_to_visualizer) - pass +def collective_plot(altitude_to_visualizer: Dict[int, ComparisonHistoricalVisualizer]): + visualizer = list(altitude_to_visualizer.values())[0] + count_number_of_total_massifs = 0 + count_number_of_time_the_reanalysis_is_the_smallest = 0 + count_number_of_time_the_reanalysis_is_the_biggest = 0 + altitudes = list(altitude_to_visualizer.keys()) + all_ranks = [] + for v in altitude_to_visualizer.values(): + ranks = np.array(list(v.massif_name_to_rank.values())) + count_number_of_total_massifs += len(ranks) + count_number_of_time_the_reanalysis_is_the_smallest += sum(ranks == 0.0) + all_ranks.extend(ranks) + print(scenario_to_str(visualizer.study.scenario), visualizer.study.year_min, visualizer.study.year_max) + print('Summary for rank for altitudes:', altitudes) + print('Mean ranks:', np.mean(all_ranks)) + print('percentages of time reanalysis is the biggest:', + 100 * count_number_of_time_the_reanalysis_is_the_biggest / count_number_of_total_massifs) + print('number of time reanalysis is the biggest:', count_number_of_time_the_reanalysis_is_the_biggest, + ' out of ', count_number_of_total_massifs, ' time series') + print('percentages of time reanalysis is the smallest:', + 100 * count_number_of_time_the_reanalysis_is_the_smallest / count_number_of_total_massifs) + print('number of time reanalysis is the smallest:', count_number_of_time_the_reanalysis_is_the_smallest, + ' out of ', count_number_of_total_massifs, ' time series') def bias_of_the_mean_with_the_altitude(altitude_to_visualizer: Dict[int, ComparisonHistoricalVisualizer]): diff --git a/projects/projected_snowfall/comparison_with_scm/main_comparison_on_rcp_85_extended.py b/projects/projected_snowfall/comparison_with_scm/main_comparison_on_rcp_85_extended.py index 894613de..cda70659 100644 --- a/projects/projected_snowfall/comparison_with_scm/main_comparison_on_rcp_85_extended.py +++ b/projects/projected_snowfall/comparison_with_scm/main_comparison_on_rcp_85_extended.py @@ -19,25 +19,51 @@ from projects.projected_snowfall.comparison_with_scm.comparison_historical_visua def main(): - fast = True + fast = 7 + year_max = 2019 # Set the year_min and year_max for the comparison - if fast is None: - year_min = [1982, 1950][1] - massif_names = ['Vanoise'] - altitudes = [1200, 1500, 1800, 2100, 2400] - elif fast: + if fast is 1: year_min = [1982, 1950][0] massif_names = ['Vanoise'] altitudes = [1800] + elif fast is 2: + year_min = [1982, 1950][0] + massif_names = None + altitudes = [1800] + elif fast is 3: + year_min = [1982, 1950][0] + massif_names = ['Vanoise'] + altitudes = [1200, 1500, 1800, 2100, 2400] + elif fast is 4: + year_max = 2019 + massif_names = None + year_min = 2006 + altitudes = [600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600][:] + elif fast is 5: + year_max = 2019 + massif_names = None + year_min = 2013 + altitudes = [600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600][:] + elif fast is 6: + year_max = 2012 + massif_names = None + year_min = 2006 + altitudes = [600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600][:] + elif fast is 7: + year_max = 2019 + massif_names = None + year_min = 1982 + altitudes = [600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600][:] else: + year_max = 2005 massif_names = None - year_min = [1982, 1950][1] + year_min = 1982 altitudes = [600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600][:] # Load visualizers altitude_to_visualizer = OrderedDict() for altitude in altitudes: - visualizer = load_visualizer(altitude, massif_names, year_min) + visualizer = load_visualizer(altitude, massif_names, year_min, year_max) altitude_to_visualizer[altitude] = visualizer # Individual plot individual_plot(visualizer) @@ -45,13 +71,19 @@ def main(): collective_plot(altitude_to_visualizer) -def load_visualizer(altitude, massif_names, year_min) -> ComparisonHistoricalVisualizer: +def load_visualizer(altitude, massif_names, year_min, year_max) -> ComparisonHistoricalVisualizer: year_min = max(1959, year_min) - year_max = 2019 + year_max = min(2019, year_max) study_class_couple = [(SafranSnowfall1Day, AdamontSnowfall)][0] scm_study_class, adamont_study_class = study_class_couple season = Season.annual - adamont_scenario = AdamontScenario.rcp85_extended + if year_min <= 2005: + if year_max > 2005: + adamont_scenario = AdamontScenario.rcp85_extended + else: + adamont_scenario = AdamontScenario.histo + else: + adamont_scenario = AdamontScenario.rcp85 # Loading part scm_study = scm_study_class(altitude=altitude, year_min=year_min, year_max=year_max, season=season) -- GitLab