diff --git a/experiment/meteo_france_SCM_study/abstract_study.py b/experiment/meteo_france_SCM_study/abstract_study.py index 9620e50ed365aabef007a614637827d9fc2bcf32..42973271055ddb57cef77cc631318be7b60b4bd2 100644 --- a/experiment/meteo_france_SCM_study/abstract_study.py +++ b/experiment/meteo_france_SCM_study/abstract_study.py @@ -37,7 +37,7 @@ class AbstractStudy(object): REANALYSIS_FOLDER = 'alp_flat/reanalysis' def __init__(self, variable_class: type, altitude: int = 1800, year_min=1000, year_max=3000, - multiprocessing=False): + multiprocessing=True): assert altitude in ALTITUDES, altitude self.altitude = altitude self.model_name = None @@ -148,7 +148,7 @@ class AbstractStudy(object): @property def _year_to_daily_time_serie_array(self) -> OrderedDict: # Map each year to a matrix of size 365-nb_days_consecutive+1 x nb_massifs - variables = [self.instantiate_variable_object(dataset) for dataset in + variables = [self.instantiate_variable_object(variable_array) for variable_array in self.year_to_variable_array.values()] year_to_variable = dict(zip(self.ordered_years, variables)) year_to_daily_time_serie_array = OrderedDict() diff --git a/experiment/meteo_france_SCM_study/safran/safran.py b/experiment/meteo_france_SCM_study/safran/safran.py index 7e4d928270f049da9c8290bf4c72bcb550aaa5ad..0258c0ff95c8704a32ae95e63f99043d9927f0fa 100644 --- a/experiment/meteo_france_SCM_study/safran/safran.py +++ b/experiment/meteo_france_SCM_study/safran/safran.py @@ -23,8 +23,8 @@ class SafranFrequency(Safran): super().__init__(variable_class, *args, **kwargs) self.nb_consecutive_days = nb_consecutive_days - def instantiate_variable_object(self, dataset) -> AbstractVariable: - return self.variable_class(dataset, self.nb_consecutive_days) + def instantiate_variable_object(self, variable_array) -> AbstractVariable: + return self.variable_class(variable_array, self.nb_consecutive_days) @property def variable_name(self): @@ -55,6 +55,10 @@ class SafranTotalPrecip(SafranFrequency): def __init__(self, *args, **kwargs): super().__init__(SafranTotalPrecipVariable, *args, **kwargs) + def instantiate_variable_object(self, variable_array) -> AbstractVariable: + variable_array_snowfall, variable_array_rainfall = variable_array + return self.variable_class(variable_array_snowfall, variable_array_rainfall, self.nb_consecutive_days) + class ExtendedSafranTotalPrecip(AbstractExtendedStudy, SafranTotalPrecip): pass diff --git a/experiment/meteo_france_SCM_study/safran/safran_variable.py b/experiment/meteo_france_SCM_study/safran/safran_variable.py index 1903abcd231e9e37ee410f19730d70b5ef6c2809..6ed6bd83487a4773fb23a9db027dc7d134c08a8e 100644 --- a/experiment/meteo_france_SCM_study/safran/safran_variable.py +++ b/experiment/meteo_france_SCM_study/safran/safran_variable.py @@ -71,11 +71,10 @@ class SafranRainfallVariable(SafranSnowfallVariable): class SafranTotalPrecipVariable(AbstractVariable): - def __init__(self, variable_array): - super().__init__(variable_array) - snow_variable_array, rain_variable_array = self.variable_array - self.snow_precipitation = SafranSnowfallVariable(snow_variable_array) - self.rain_precipitation = SafranRainfallVariable(rain_variable_array) + def __init__(self, snow_variable_array, rain_variable_array, nb_consecutive_days_of_snowfall=1): + super().__init__(None) + self.snow_precipitation = SafranSnowfallVariable(snow_variable_array, nb_consecutive_days_of_snowfall) + self.rain_precipitation = SafranRainfallVariable(rain_variable_array, nb_consecutive_days_of_snowfall) @classmethod def keyword(cls): diff --git a/experiment/meteo_france_SCM_study/visualization/studies_visualization/hypercube_visualizer.py b/experiment/meteo_france_SCM_study/visualization/studies_visualization/hypercube_visualizer.py index 971bf62f511a6bbe62522d7555b91b80ebbe7e8f..99d5c5189ac9dd4b469cd32d5b9b450e76f61bc6 100644 --- a/experiment/meteo_france_SCM_study/visualization/studies_visualization/hypercube_visualizer.py +++ b/experiment/meteo_france_SCM_study/visualization/studies_visualization/hypercube_visualizer.py @@ -39,13 +39,14 @@ class HypercubeVisualizer(object): @cached_property def tuple_to_df_trend_type(self): - df_spatio_temporal_trend_types = [study_visualizer.df_trend_spatio_temporal(self.trend_class, self.starting_years, - self.nb_data_for_fast_mode) - for study_visualizer in self.tuple_to_study_visualizer.values()] + df_spatio_temporal_trend_types = [ + study_visualizer.df_trend_spatio_temporal(self.trend_class, self.starting_years, + self.nb_data_for_fast_mode) + for study_visualizer in self.tuple_to_study_visualizer.values()] return dict(zip(self.tuple_to_study_visualizer.keys(), df_spatio_temporal_trend_types)) @cached_property - def hypercube(self): + def df_hypercube(self): keys = list(self.tuple_to_df_trend_type.keys()) values = list(self.tuple_to_df_trend_type.values()) df = pd.concat(values, keys=keys, axis=0) @@ -82,7 +83,42 @@ class HypercubeVisualizer(object): class AltitudeHypercubeVisualizer(HypercubeVisualizer): - pass + + @property + def altitudes(self): + return list(self.tuple_to_study_visualizer.keys()) + + def visualize_trend_test(self, ax=None, marker='o'): + if ax is None: + fig, ax = plt.subplots(1, 1, figsize=self.study_visualizer.figsize) + + # Plot weighted percentages over the years + for trend_type, style in self.trend_class.trend_type_to_style().items(): + altitude_percentages = (self.df_hypercube == trend_type) + # Take the mean with respect to the years + altitude_percentages = altitude_percentages.mean(axis=1) + # Take the mean with respect the massifs + altitude_percentages = altitude_percentages.mean(axis=0, level=0) + # Take the numpy array + altitude_percentages = altitude_percentages.values * 100 + # Plot + ax.plot(self.altitudes, altitude_percentages, style + marker, label=trend_type) + + # Global information + added_str = 'weighted ' + ylabel = '% averaged on massifs & {}averaged on starting years'.format(added_str) + ylabel += ' (with uniform weights)' + ax.set_ylabel(ylabel) + ax.set_xlabel('altitude') + ax.set_xticks(self.altitudes) + ax.set_yticks(list(range(0, 101, 10))) + ax.grid() + ax.legend() + + variable_name = self.study.variable_class.NAME + title = 'Evolution of {} trends (significative or not) wrt to the altitude'.format(variable_name) + ax.set_title(title) + self.show_or_save_to_file(specific_title=title) class QuantitityAltitudeHypercubeVisualizer(HypercubeVisualizer): diff --git a/experiment/meteo_france_SCM_study/visualization/studies_visualization/main_studies_visualizer.py b/experiment/meteo_france_SCM_study/visualization/studies_visualization/main_studies_visualizer.py index 337449f621069410d4b45dc575eb24320244eee1..ad30484bdb1151090ac405346e3358253a3b5301 100644 --- a/experiment/meteo_france_SCM_study/visualization/studies_visualization/main_studies_visualizer.py +++ b/experiment/meteo_france_SCM_study/visualization/studies_visualization/main_studies_visualizer.py @@ -1,7 +1,7 @@ import time from experiment.meteo_france_SCM_study.visualization.studies_visualization.hypercube_visualizer import \ - HypercubeVisualizer + HypercubeVisualizer, AltitudeHypercubeVisualizer from experiment.trend_analysis.abstract_score import MannKendall, WeigthedScore, MeanScore, MedianScore from experiment.trend_analysis.univariate_trend_test.abstract_gev_trend_test import GevLocationTrendTest, \ GevScaleTrendTest, GevShapeTrendTest @@ -59,26 +59,28 @@ def altitude_trends_significant(): visualizer.trend_tests_percentage_evolution_with_altitude(trend_test_classes, starting_year_to_weights=None) -def hypercube_test(): +def altitude_hypercube_test(): save_to_file = False only_first_one = False + fast = False altitudes = ALL_ALTITUDES[3:-6] altitudes = ALL_ALTITUDES[2:4] for study_class in SCM_STUDIES[:1]: trend_test_class = [MannKendallTrendTest, GevLocationTrendTest, GevScaleTrendTest, GevShapeTrendTest][0] visualizers = [StudyVisualizer(study, temporal_non_stationarity=True, verbose=False, multiprocessing=True) for study in study_iterator(study_class=study_class, only_first_one=only_first_one, - altitudes=altitudes, multiprocessing=True)] + altitudes=altitudes)] altitude_to_visualizer = OrderedDict(zip(altitudes, visualizers)) - visualizer = HypercubeVisualizer(altitude_to_visualizer, save_to_file=save_to_file, - trend_class=trend_test_class, fast=True) - print(visualizer.hypercube) + visualizer = AltitudeHypercubeVisualizer(altitude_to_visualizer, save_to_file=save_to_file, + trend_class=trend_test_class, fast=fast) + visualizer.visualize_trend_test() + # print(visualizer.df_hypercube) def main_run(): # altitude_trends() # altitude_trends_significant() - hypercube_test() + altitude_hypercube_test() if __name__ == '__main__': 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 ded791ecbb663514de9749be3779716efeca127f..645955e4657eede24fe0b877f4d099b6a70a153f 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 @@ -35,8 +35,7 @@ List[AbstractStudy]: break -def study_iterator(study_class, only_first_one=False, both_altitude=False, verbose=True, altitudes=None, - multiprocessing=True) -> List[ +def study_iterator(study_class, only_first_one=False, both_altitude=False, verbose=True, altitudes=None) -> List[ AbstractStudy]: all_studies = [] is_safran_study = study_class in [SafranSnowfall, ExtendedSafranSnowfall] @@ -50,7 +49,7 @@ def study_iterator(study_class, only_first_one=False, both_altitude=False, verbo if verbose: print('alti: {}, nb_day: {} '.format(alti, nb_day), end='') - study = study_class(altitude=alti, multiprocessing=multiprocessing) + study = study_class(altitude=alti) massifs = study.altitude_to_massif_names[alti] if verbose: print('{} massifs: {} \n'.format(len(massifs), massifs)) diff --git a/test/test_experiment/test_SCM_study.py b/test/test_experiment/test_SCM_study.py index 6b22c30965a3274220763d3f389394963866b81f..e8070c84f14c6f36af0efb63415b6d8ce18c255a 100644 --- a/test/test_experiment/test_SCM_study.py +++ b/test/test_experiment/test_SCM_study.py @@ -10,89 +10,83 @@ from experiment.meteo_france_SCM_study.safran.safran import SafranSnowfall, Exte from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer from test.test_utils import load_scm_studies + # TESTS TO REACTIVATE SOMETIMES -# -# class TestSCMAllStudy(unittest.TestCase): -# -# def test_extended_run(self): -# for study_class in [ExtendedSafranSnowfall]: -# for study in study_iterator(study_class, only_first_one=True, both_altitude=False, verbose=False): -# study_visualizer = StudyVisualizer(study, show=False, save_to_file=False) -# study_visualizer.visualize_all_mean_and_max_graphs() -# self.assertTrue(True) -# -# def test_scm_daily_data(self): -# for study in load_scm_studies(): -# time_serie = study.year_to_daily_time_serie_array[1958] -# self.assertTrue(time_serie.ndim == 2, msg='for {} ndim={}'.format(study.__repr__(), time_serie.ndim)) -# self.assertTrue(len(time_serie) in [365, 366], -# msg="current time serie length for {} is {}".format(study.__repr__(), len(time_serie))) -# -# -# class TestSCMStudy(unittest.TestCase): -# -# def setUp(self) -> None: -# super().setUp() -# self.study = None -# -# def check(self, massif_name_to_value_to_check): -# df_annual_total = self.study.df_annual_total -# for massif_name, value in massif_name_to_value_to_check.items(): -# found_value = df_annual_total.loc[:, massif_name].mean() -# self.assertEqual(value, self.round(found_value)) -# -# def round(self, f): -# raise NotImplementedError -# -# -# class TestSCMSafranSnowfall(TestSCMStudy): -# -# def setUp(self) -> None: -# super().setUp() -# self.study = SafranSnowfall() -# -# def test_massif_safran(self): -# df_centroid = pd.read_csv(op.join(self.study.map_full_path, 'coordonnees_massifs_alpes.csv')) -# # Assert that the massif names are the same between SAFRAN and the coordinate file -# assert not set(self.study.study_massif_names).symmetric_difference(set(df_centroid['NOM'])) -# -# -# class TestSCMPrecipitation(TestSCMStudy): -# -# def setUp(self) -> None: -# super().setUp() -# self.study = SafranTotalPrecip(altitude=1800, year_min=1958, year_max=2002) -# -# def test_durand(self): -# # Test based on Durand paper -# # (some small differences probably due to the fact that SAFRAN model has evolved since then) -# # Test for the mean total precipitation (rainfall + snowfall) between 1958 and 2002 -# self.check({ -# "Mercantour": 1281, -# 'Chablais': 1922, -# }) -# -# def round(self, f): -# return int(f) -# -# -# class TestSafranTemperature(TestSCMStudy): -# -# def setUp(self): -# super().setUp() -# self.study = SafranTemperature(altitude=1800, year_min=1958, year_max=2002) -# -# def test_durand(self): -# # Test based on Durand paper -# # Test for the mean temperature between 1958 and 2002 -# self.check({ -# "Mercantour": 5.3, -# 'Chablais': 3.5, -# }) -# -# def round(self, f): -# return round(float(f), 1) -# -# -# if __name__ == '__main__': -# unittest.main() + +class TestSCMAllStudy(unittest.TestCase): + + def test_extended_run(self): + for study_class in [ExtendedSafranSnowfall]: + for study in study_iterator(study_class, only_first_one=True, both_altitude=False, verbose=False): + study_visualizer = StudyVisualizer(study, show=False, save_to_file=False) + study_visualizer.visualize_all_mean_and_max_graphs() + self.assertTrue(True) + + +class TestSCMStudy(unittest.TestCase): + + def setUp(self) -> None: + super().setUp() + self.study = None + + def check(self, massif_name_to_value_to_check): + df_annual_total = self.study.df_annual_total + for massif_name, value in massif_name_to_value_to_check.items(): + found_value = df_annual_total.loc[:, massif_name].mean() + self.assertEqual(value, self.round(found_value)) + + def round(self, f): + raise NotImplementedError + + +class TestSCMSafranSnowfall(TestSCMStudy): + + def setUp(self) -> None: + super().setUp() + self.study = SafranSnowfall() + + def test_massif_safran(self): + df_centroid = pd.read_csv(op.join(self.study.map_full_path, 'coordonnees_massifs_alpes.csv')) + # Assert that the massif names are the same between SAFRAN and the coordinate file + assert not set(self.study.study_massif_names).symmetric_difference(set(df_centroid['NOM'])) + + +class TestSCMPrecipitation(TestSCMStudy): + + def setUp(self) -> None: + super().setUp() + self.study = SafranTotalPrecip(altitude=1800, year_min=1958, year_max=2002) + + def test_durand(self): + # Test based on Durand paper + # (some small differences probably due to the fact that SAFRAN model has evolved since then) + # Test for the mean total precipitation (rainfall + snowfall) between 1958 and 2002 + self.check({ + "Mercantour": 1281, + 'Chablais': 1922, + }) + + def round(self, f): + return int(f) + + +class TestSafranTemperature(TestSCMStudy): + + def setUp(self): + super().setUp() + self.study = SafranTemperature(altitude=1800, year_min=1958, year_max=2002) + + def test_durand(self): + # Test based on Durand paper + # Test for the mean temperature between 1958 and 2002 + self.check({ + "Mercantour": 5.3, + 'Chablais': 3.5, + }) + + def round(self, f): + return round(float(f), 1) + + +if __name__ == '__main__': + unittest.main()