diff --git a/experiment/meteo_france_SCM_models/study/abstract_study.py b/experiment/meteo_france_SCM_models/study/abstract_study.py index 2be3827e3e3da3cdb66ad93bdad638237227e26c..13aca7a31e35d8434f20b16ebfdf665c6f5d1915 100644 --- a/experiment/meteo_france_SCM_models/study/abstract_study.py +++ b/experiment/meteo_france_SCM_models/study/abstract_study.py @@ -108,12 +108,15 @@ class AbstractStudy(object): def load_variables(self, path_file): dataset = Dataset(path_file) - keyword = self.variable_class.keyword() + keyword = self.load_keyword() if isinstance(keyword, str): return np.array(dataset.variables[keyword]) else: return [np.array(dataset.variables[k]) for k in keyword] + def load_keyword(self): + return self.variable_class.keyword() + @property def start_year_and_stop_year(self) -> Tuple[int, int]: ordered_years = self.ordered_years diff --git a/experiment/meteo_france_SCM_models/study/abstract_variable.py b/experiment/meteo_france_SCM_models/study/abstract_variable.py index 9e5a07c400f6cc7f93e76bda78d681417c67cece..62e9457cede02af02b2445ae30a2d722cdda1214 100644 --- a/experiment/meteo_france_SCM_models/study/abstract_variable.py +++ b/experiment/meteo_france_SCM_models/study/abstract_variable.py @@ -9,12 +9,12 @@ class AbstractVariable(object): NAME = '' UNIT = '' - def __init__(self, variable_array, nb_consecutive_days_of_snowfall=1): + def __init__(self, variable_array, nb_consecutive_days=3): self.variable_array = variable_array - self.nb_consecutive_days_of_snowfall = nb_consecutive_days_of_snowfall + self.nb_consecutive_days = nb_consecutive_days @classmethod - def keyword(cls): + def keyword(cls, nb_consecutive_days=3): raise NotImplementedError @property diff --git a/experiment/meteo_france_SCM_models/study/crocus/crocus.py b/experiment/meteo_france_SCM_models/study/crocus/crocus.py index fc3b39f463eb4a46603548d9c4ca39d84bc6b746..e567117620823f6031397fcafbb9c8890973f3f9 100644 --- a/experiment/meteo_france_SCM_models/study/crocus/crocus.py +++ b/experiment/meteo_france_SCM_models/study/crocus/crocus.py @@ -40,10 +40,11 @@ class ExtendedCrocusSwe(AbstractExtendedStudy, CrocusSwe): pass -class CrocusDepth(Crocus): +class CrocusDepth(Crocus, CumulatedStudy): def __init__(self, *args, **kwargs): - super().__init__(CrocusDepthVariable, *args, **kwargs) + CumulatedStudy.__init__(self, CrocusDepthVariable, *args, **kwargs) + Crocus.__init__(self, CrocusDepthVariable, *args, **kwargs) def apply_annual_aggregation(self, time_serie): return self.winter_annual_aggregation(time_serie) diff --git a/experiment/meteo_france_SCM_models/study/crocus/crocus_variables.py b/experiment/meteo_france_SCM_models/study/crocus/crocus_variables.py index 874517a3e8dd2b9e8ca8dab424d8b1c70878e947..4663bf4f3ce0ef23e7edc8153446e17ce22c0401 100644 --- a/experiment/meteo_france_SCM_models/study/crocus/crocus_variables.py +++ b/experiment/meteo_france_SCM_models/study/crocus/crocus_variables.py @@ -15,8 +15,8 @@ class CrocusSweVariable(CrocusVariable): UNIT = 'kg per m2 or mm' @classmethod - def keyword(cls): - return 'SWE_1DY_ISBA' + def keyword(cls, nb_consecutive_days=3): + return 'SWE_{}DY_ISBA'.format(nb_consecutive_days) class CrocusDepthVariable(CrocusVariable): @@ -24,5 +24,5 @@ class CrocusDepthVariable(CrocusVariable): UNIT = 'm' @classmethod - def keyword(cls): - return "SD_1DY_ISBA" + def keyword(cls, nb_consecutive_days=3): + return "SD_{}DY_ISBA".format(nb_consecutive_days) diff --git a/experiment/meteo_france_SCM_models/study/cumulated_study.py b/experiment/meteo_france_SCM_models/study/cumulated_study.py index e5300ff483796c7a0ae87a09483e89ed57d7cc54..8dd806ca4a05193556e8e28ca7c92707b6527b63 100644 --- a/experiment/meteo_france_SCM_models/study/cumulated_study.py +++ b/experiment/meteo_france_SCM_models/study/cumulated_study.py @@ -1,20 +1,21 @@ -import numpy as np - from experiment.meteo_france_SCM_models.study.abstract_study import AbstractStudy from experiment.meteo_france_SCM_models.study.abstract_variable import AbstractVariable +NB_DAYS = [1, 3, 5, 7] + class CumulatedStudy(AbstractStudy): - def __init__(self, variable_class: type, nb_consecutive_days: int = 1, *args, **kwargs): - assert nb_consecutive_days in [1, 3, 5, 7] + def __init__(self, variable_class: type, nb_consecutive_days: int = 3, *args, **kwargs): + assert nb_consecutive_days in NB_DAYS super().__init__(variable_class, *args, **kwargs) self.nb_consecutive_days = nb_consecutive_days def instantiate_variable_object(self, variable_array) -> AbstractVariable: return self.variable_class(variable_array, self.nb_consecutive_days) + def load_keyword(self): + return self.variable_class.keyword(self.nb_consecutive_days) + @property def variable_name(self): return super().variable_name + ' cumulated over {} day(s)'.format(self.nb_consecutive_days) - - diff --git a/experiment/meteo_france_SCM_models/study/safran/safran_variable.py b/experiment/meteo_france_SCM_models/study/safran/safran_variable.py index d2c8faa113467438f3bc77fac5c00f8b33c381a6..b40b6cd5bebb6758f2c5d22b3c2b82425b012335 100644 --- a/experiment/meteo_france_SCM_models/study/safran/safran_variable.py +++ b/experiment/meteo_france_SCM_models/study/safran/safran_variable.py @@ -25,12 +25,12 @@ class SafranSnowfallVariable(AbstractVariable): UNIT = 'kg per m2 or mm' @classmethod - def keyword(cls): + def keyword(cls, nb_consecutive_days=3): return 'Snowf' - def __init__(self, variable_array, nb_consecutive_days_of_snowfall=1): + def __init__(self, variable_array, nb_consecutive_days): super().__init__(variable_array) - self.nb_consecutive_days_of_snowfall = nb_consecutive_days_of_snowfall + self.nb_consecutive_days_of_snowfall = nb_consecutive_days # Compute the daily snowfall in kg/m2 snowfall_rates = variable_array @@ -56,10 +56,12 @@ class SafranSnowfallVariable(AbstractVariable): # The zip is done with respect to the shortest list snowfall_in_consecutive_days = np.array([sum(e) for e in zip(*shifted_list)]) # The returned array is of size n-nb_days+1 x nb_massif - # so that the length of the vector match a year, we can add zeros (since it corresponds to the July month, # we are sure that there is no snowfall at this period) However such trick does not work for other variable such as Temperature - + nb_days_in_a_year = len(self.daily_snowfall) + nb_days_in_vector, nb_altitudes = snowfall_in_consecutive_days.shape + zeros_to_add = np.zeros([nb_days_in_a_year - nb_days_in_vector, nb_altitudes]) + snowfall_in_consecutive_days = np.concatenate([snowfall_in_consecutive_days, zeros_to_add]) return snowfall_in_consecutive_days @@ -68,19 +70,19 @@ class SafranRainfallVariable(SafranSnowfallVariable): UNIT = 'kg per m2 or mm' @classmethod - def keyword(cls): + def keyword(cls, nb_consecutive_days=3): return 'Rainf' class SafranTotalPrecipVariable(AbstractVariable): - def __init__(self, snow_variable_array, rain_variable_array, nb_consecutive_days_of_snowfall=1): + def __init__(self, snow_variable_array, rain_variable_array, nb_consecutive_days): 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) + self.snow_precipitation = SafranSnowfallVariable(snow_variable_array, nb_consecutive_days) + self.rain_precipitation = SafranRainfallVariable(rain_variable_array, nb_consecutive_days) @classmethod - def keyword(cls): + def keyword(cls, nb_consecutive_days=3): return [SafranSnowfallVariable.keyword(), SafranRainfallVariable.keyword()] @property @@ -93,7 +95,7 @@ class SafranTemperatureVariable(AbstractVariable): UNIT = 'Celsius Degrees' @classmethod - def keyword(cls): + def keyword(cls, nb_consecutive_days=3): return 'Tair' def __init__(self, variable_array): diff --git a/experiment/meteo_france_SCM_models/visualization/study_visualization/main_study_visualizer.py b/experiment/meteo_france_SCM_models/visualization/study_visualization/main_study_visualizer.py index b09cd17a410df93fbc2ad3075e43bb9ee6f92f9e..893fb39c50642492626d658314a47952a80458d4 100644 --- a/experiment/meteo_france_SCM_models/visualization/study_visualization/main_study_visualizer.py +++ b/experiment/meteo_france_SCM_models/visualization/study_visualization/main_study_visualizer.py @@ -36,28 +36,26 @@ List[AbstractStudy]: break -def study_iterator(study_class, only_first_one=False, verbose=True, altitudes=None, nb_days=None) -> List[AbstractStudy]: +def study_iterator(study_class, only_first_one=False, verbose=True, altitudes=None, nb_consecutive_days=None) -> List[AbstractStudy]: # Default argument - nb_days = [1] if nb_days is None else nb_days + nb_consecutive_days = 1 if nb_consecutive_days is None else nb_consecutive_days altis = [1800] if altitudes is None else altitudes if verbose: print('\n\n\n\n\nLoading studies....') - for nb_day in nb_days: - for alti in altis: - if verbose: - print('alti: {}, nb_day: {} '.format(alti, nb_day), end='') + for alti in altis: + if verbose: + print('alti: {}, nb_day: {} '.format(alti, nb_consecutive_days), end='') - study = study_class(altitude=alti) + study = study_class(altitude=alti, + nb_consecutive_days=nb_consecutive_days) - if verbose: - massifs = study.altitude_to_massif_names[alti] - print('{} massifs: {} \n'.format(len(massifs), massifs)) - yield study + if verbose: + massifs = study.altitude_to_massif_names[alti] + print('{} massifs: {} \n'.format(len(massifs), massifs)) + yield study - # Stop iterations on purpose - if only_first_one: - break + # Stop iterations on purpose if only_first_one: break diff --git a/test/test_experiment/test_SCM_study.py b/test/test_experiment/test_SCM_study.py index a36b3c3538d4589edf3d88d85ba1c98d86f5fed2..de6dd51247638e01bfb50bc9d5da3ce7bb4e8f8f 100644 --- a/test/test_experiment/test_SCM_study.py +++ b/test/test_experiment/test_SCM_study.py @@ -1,25 +1,43 @@ import os.path as op import unittest +from random import sample import pandas as pd -from experiment.meteo_france_SCM_models.visualization.study_visualization.main_study_visualizer import study_iterator -from experiment.meteo_france_SCM_models.study.safran.safran import SafranSnowfall, ExtendedSafranSnowfall, SafranTemperature, \ +from experiment.meteo_france_SCM_models.study.cumulated_study import NB_DAYS +from experiment.meteo_france_SCM_models.study.safran.safran import SafranSnowfall, ExtendedSafranSnowfall, \ + SafranTemperature, \ SafranTotalPrecip +from experiment.meteo_france_SCM_models.visualization.study_visualization.main_study_visualizer import study_iterator, \ + study_iterator_global, SCM_STUDIES, ALL_ALTITUDES from experiment.meteo_france_SCM_models.visualization.study_visualization.study_visualizer import StudyVisualizer +from experiment.trend_analysis.univariate_test.abstract_gev_change_point_test import GevLocationChangePointTest +from utils import get_display_name_from_object_type -# 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, verbose=False): - study_visualizer = StudyVisualizer(study, show=False, save_to_file=False) - study_visualizer.visualize_all_mean_and_max_graphs() + study_visualizer = StudyVisualizer(study, show=False, save_to_file=False, multiprocessing=True) + study_visualizer.df_trend_spatio_temporal(GevLocationChangePointTest, [1958, 1959, 1960], + nb_massif_for_fast_mode=1) self.assertTrue(True) + def test_instantiate_studies(self): + nb_sample = 2 + for nb_days in sample(set(NB_DAYS), k=nb_sample): + for study in study_iterator_global(study_classes=SCM_STUDIES, + only_first_one=False, verbose=False, + altitudes=sample(set(ALL_ALTITUDES), k=nb_sample), nb_days=nb_days): + self.assertTrue('day' in study.variable_name) + first_path_file = study.ordered_years_and_path_files()[0][0] + variable_array = study.load_variables(path_file=first_path_file) + variable_object = study.instantiate_variable_object(variable_array) + self.assertEqual((365, 263), variable_object.daily_time_serie_array.shape, + msg='{} days for type {}'.format(nb_days, get_display_name_from_object_type(type(variable_object)))) + class TestSCMStudy(unittest.TestCase): @@ -53,7 +71,7 @@ class TestSCMPrecipitation(TestSCMStudy): def setUp(self) -> None: super().setUp() - self.study = SafranTotalPrecip(altitude=1800, year_min=1958, year_max=2002) + self.study = SafranTotalPrecip(altitude=1800, year_min=1958, year_max=2002, nb_consecutive_days=1) def test_durand(self): # Test based on Durand paper