From a4b56e9ea9bb89d0e167693486b234e69c2ec584 Mon Sep 17 00:00:00 2001 From: Le Roux Erwan <erwan.le-roux@irstea.fr> Date: Thu, 28 Feb 2019 10:57:45 +0100 Subject: [PATCH] [SCM] ensure that each daily_series are indeed daily series. add test --- .../meteo_france_SCM_study/abstract_study.py | 2 +- .../abstract_variable.py | 3 +- .../meteo_france_SCM_study/crocus/crocus.py | 6 +++- .../crocus/crocus_variables.py | 26 +++++++++++------ .../meteo_france_SCM_study/main_visualize.py | 4 +-- .../meteo_france_SCM_study/safran/safran.py | 8 ++++++ .../safran/safran_snowfall_variable.py | 6 ++-- .../safran/safran_visualizer.py | 8 ++++-- .../__init__.py | 0 .../test_meteo_france_SCM_study/__init__.py | 0 .../test_SCM_study.py | 12 ++++++-- .../test_safran_gev.py | 0 test/test_utils.py | 28 +++++++++++++++---- 13 files changed, 78 insertions(+), 25 deletions(-) rename test/{test_meteo_france_SCM_study => test_experiment}/__init__.py (100%) create mode 100644 test/test_experiment/test_meteo_france_SCM_study/__init__.py rename test/{ => test_experiment}/test_meteo_france_SCM_study/test_SCM_study.py (69%) rename test/{ => test_experiment}/test_meteo_france_SCM_study/test_safran_gev.py (100%) diff --git a/experiment/meteo_france_SCM_study/abstract_study.py b/experiment/meteo_france_SCM_study/abstract_study.py index 7b60a4c4..c47ee107 100644 --- a/experiment/meteo_france_SCM_study/abstract_study.py +++ b/experiment/meteo_france_SCM_study/abstract_study.py @@ -67,7 +67,7 @@ class AbstractStudy(object): return year_to_annual_maxima def instantiate_variable_object(self, dataset) -> AbstractVariable: - return self.variable_class(dataset) + return self.variable_class(dataset, self.altitude) """ Private methods to be overwritten """ diff --git a/experiment/meteo_france_SCM_study/abstract_variable.py b/experiment/meteo_france_SCM_study/abstract_variable.py index 777d7f21..d60cdfc3 100644 --- a/experiment/meteo_france_SCM_study/abstract_variable.py +++ b/experiment/meteo_france_SCM_study/abstract_variable.py @@ -4,8 +4,9 @@ class AbstractVariable(object): NAME = '' - def __init__(self, dataset): + def __init__(self, dataset, altitude): self.dataset = dataset + self.altitude = altitude @property def daily_time_serie(self): diff --git a/experiment/meteo_france_SCM_study/crocus/crocus.py b/experiment/meteo_france_SCM_study/crocus/crocus.py index b14c2fdb..43caec2a 100644 --- a/experiment/meteo_france_SCM_study/crocus/crocus.py +++ b/experiment/meteo_france_SCM_study/crocus/crocus.py @@ -1,3 +1,5 @@ +import numpy as np + from experiment.meteo_france_SCM_study.abstract_extended_study import AbstractExtendedStudy from experiment.meteo_france_SCM_study.abstract_study import AbstractStudy from experiment.meteo_france_SCM_study.crocus.crocus_variables import CrocusSweVariable, CrocusDepthVariable @@ -36,8 +38,10 @@ class ExtendedCrocusDepth(AbstractExtendedStudy, CrocusDepth): if __name__ == '__main__': for variable_class in [CrocusSweVariable, CrocusDepthVariable]: - study = Crocus(variable_class=variable_class) + study = Crocus(variable_class=variable_class, altitude=2400) d = study.year_to_dataset_ordered_dict[1960] + time_arr = np.array(d.variables['time']) + print(time_arr) # print(d) a = study.year_to_daily_time_serie[1960] print(a.shape) diff --git a/experiment/meteo_france_SCM_study/crocus/crocus_variables.py b/experiment/meteo_france_SCM_study/crocus/crocus_variables.py index 516221c9..c8b1c120 100644 --- a/experiment/meteo_france_SCM_study/crocus/crocus_variables.py +++ b/experiment/meteo_france_SCM_study/crocus/crocus_variables.py @@ -5,27 +5,37 @@ from experiment.meteo_france_SCM_study.abstract_variable import AbstractVariable class CrocusVariable(AbstractVariable): - def __init__(self, dataset, variable_name): - super().__init__(dataset) + def __init__(self, dataset, altitude, variable_name): + super().__init__(dataset, altitude) self.variable_name = variable_name @property def daily_time_serie(self): - # So far the dimension of the time serie is 1460 x 23 - return np.array(self.dataset.variables[self.variable_name])[:, 0, :] + time_serie_every_6_hours = np.array(self.dataset.variables[self.variable_name])[:, 0, :] + if self.altitude == 2400: + time_serie_daily = time_serie_every_6_hours + else: + # Take the mean over a full day (WARNING: by doing that I am potentially destroying some maxima) + # TODO: I could create a special mode where I take the maximum instead of the mean here + nb_days = len(time_serie_every_6_hours) // 4 + time_serie_daily = np.array([np.mean(time_serie_every_6_hours[4 * i:4 * (i + 1)], axis=0) + for i in range(nb_days)]) + return time_serie_daily class CrocusSweVariable(CrocusVariable): NAME = 'Snow Water Equivalent' - def __init__(self, dataset): + def __init__(self, dataset, altitude): # Units are kg m-2 - super().__init__(dataset, 'SNOWSWE') + super().__init__(dataset, altitude, 'SNOWSWE') class CrocusDepthVariable(CrocusVariable): + """Crocus Depth data is every 6 hours + To obtain daily data, we take the average over the 4 slots of 6 hours that compose a full day """ NAME = 'Snow Depth' - def __init__(self, dataset): + def __init__(self, dataset, altitude): # Units are m - super().__init__(dataset, "SNOWDEPTH") + super().__init__(dataset, altitude, "SNOWDEPTH") diff --git a/experiment/meteo_france_SCM_study/main_visualize.py b/experiment/meteo_france_SCM_study/main_visualize.py index 84bde0b8..8322c9e6 100644 --- a/experiment/meteo_france_SCM_study/main_visualize.py +++ b/experiment/meteo_france_SCM_study/main_visualize.py @@ -15,7 +15,7 @@ SCM_STUDY_TO_EXTENDED_STUDY = OrderedDict(zip(SCM_STUDIES, SCM_EXTENDED_STUDIES) def study_iterator(study_class, only_first_one=False, both_altitude=False, verbose=True): all_studies = [] is_safran_study = study_class in [Safran, ExtendedSafran] - nb_days = [3, 1] if is_safran_study else [1] + nb_days = [1] if is_safran_study else [1] if verbose: print('Loading studies....') for nb_day in nb_days: @@ -35,7 +35,7 @@ def study_iterator(study_class, only_first_one=False, both_altitude=False, verbo def extended_visualization(): for study_class in SCM_EXTENDED_STUDIES[:]: for study in study_iterator(study_class, only_first_one=False): - study_visualizer = StudyVisualizer(study, save_to_file=True, only_one_graph=True, plot_bm_quantiles=True) + study_visualizer = StudyVisualizer(study, save_to_file=True, only_one_graph=True, plot_block_maxima_quantiles=True) # study_visualizer.visualize_all_mean_and_max_graphs() study_visualizer.visualize_all_experimental_law() # for study_class in SCM_EXTENDED_STUDIES[:]: diff --git a/experiment/meteo_france_SCM_study/safran/safran.py b/experiment/meteo_france_SCM_study/safran/safran.py index f5877b9e..6588b1e5 100644 --- a/experiment/meteo_france_SCM_study/safran/safran.py +++ b/experiment/meteo_france_SCM_study/safran/safran.py @@ -21,3 +21,11 @@ class Safran(AbstractStudy): class ExtendedSafran(AbstractExtendedStudy, Safran): pass + + +if __name__ == '__main__': + study = Safran() + d = study.year_to_dataset_ordered_dict[1958] + print(d.variables['time']) + print(study.year_to_daily_time_serie[1958].shape) + print(len(d.variables['time'])) \ No newline at end of file diff --git a/experiment/meteo_france_SCM_study/safran/safran_snowfall_variable.py b/experiment/meteo_france_SCM_study/safran/safran_snowfall_variable.py index 491dd3d2..1e919aa8 100644 --- a/experiment/meteo_france_SCM_study/safran/safran_snowfall_variable.py +++ b/experiment/meteo_france_SCM_study/safran/safran_snowfall_variable.py @@ -5,6 +5,8 @@ from experiment.meteo_france_SCM_study.abstract_variable import AbstractVariable class SafranSnowfallVariable(AbstractVariable): """" + Safran data is hourly + Hypothesis: -How to count how much snowfall in one hour ? @@ -21,8 +23,8 @@ class SafranSnowfallVariable(AbstractVariable): NAME = 'Snowfall' - def __init__(self, dataset, nb_consecutive_days_of_snowfall=1): - super().__init__(dataset) + def __init__(self, dataset, altitude, nb_consecutive_days_of_snowfall=1): + super().__init__(dataset, altitude) self.nb_consecutive_days_of_snowfall = nb_consecutive_days_of_snowfall # Compute the daily snowfall in kg/m2 snowfall_rates = np.array(dataset.variables['Snowf']) diff --git a/experiment/meteo_france_SCM_study/safran/safran_visualizer.py b/experiment/meteo_france_SCM_study/safran/safran_visualizer.py index d72300d4..430f9641 100644 --- a/experiment/meteo_france_SCM_study/safran/safran_visualizer.py +++ b/experiment/meteo_france_SCM_study/safran/safran_visualizer.py @@ -31,7 +31,7 @@ BLOCK_MAXIMA_DISPLAY_NAME = 'block maxima ' class StudyVisualizer(object): def __init__(self, study: AbstractStudy, show=True, save_to_file=False, only_one_graph=False, only_first_row=False, - vertical_kde_plot=False, year_for_kde_plot=None, plot_bm_quantiles=False): + vertical_kde_plot=False, year_for_kde_plot=None, plot_block_maxima_quantiles=False): self.only_first_row = only_first_row self.only_one_graph = only_one_graph self.save_to_file = save_to_file @@ -40,7 +40,7 @@ class StudyVisualizer(object): # KDE PLOT ARGUMENTS self.vertical_kde_plot = vertical_kde_plot self.year_for_kde_plot = year_for_kde_plot - self.plot_bm_quantiles = plot_bm_quantiles + self.plot_block_maxima_quantiles = plot_block_maxima_quantiles self.show = False if self.save_to_file else show self.window_size_for_smoothing = 21 @@ -115,7 +115,9 @@ class StudyVisualizer(object): x_level = all_massif_data[int(p * len(all_massif_data))] x_level_to_color[x_level] = (color, name) # Plot some additional quantiles from the correspond Annual Maxima law - if self.plot_bm_quantiles: + if self.plot_block_maxima_quantiles: + # This formula can only be applied if we have a daily time serie + assert len(self.study.year_to_daily_time_serie[1958]) in [365, 366] p = p ** (1 / 365) x_level = all_massif_data[int(p * len(all_massif_data))] x_level_to_color[x_level] = (color, BLOCK_MAXIMA_DISPLAY_NAME + name) diff --git a/test/test_meteo_france_SCM_study/__init__.py b/test/test_experiment/__init__.py similarity index 100% rename from test/test_meteo_france_SCM_study/__init__.py rename to test/test_experiment/__init__.py diff --git a/test/test_experiment/test_meteo_france_SCM_study/__init__.py b/test/test_experiment/test_meteo_france_SCM_study/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/test_meteo_france_SCM_study/test_SCM_study.py b/test/test_experiment/test_meteo_france_SCM_study/test_SCM_study.py similarity index 69% rename from test/test_meteo_france_SCM_study/test_SCM_study.py rename to test/test_experiment/test_meteo_france_SCM_study/test_SCM_study.py index 2f670d3d..01c0f512 100644 --- a/test/test_meteo_france_SCM_study/test_SCM_study.py +++ b/test/test_experiment/test_meteo_france_SCM_study/test_SCM_study.py @@ -3,10 +3,11 @@ import unittest import pandas as pd -from experiment.meteo_france_SCM_study.crocus.crocus import ExtendedCrocusSwe +from experiment.meteo_france_SCM_study.crocus.crocus import ExtendedCrocusSwe, Crocus from experiment.meteo_france_SCM_study.main_visualize import study_iterator from experiment.meteo_france_SCM_study.safran.safran import Safran, ExtendedSafran from experiment.meteo_france_SCM_study.safran.safran_visualizer import StudyVisualizer +from test.test_utils import load_scm_studies class TestSCMStudy(unittest.TestCase): @@ -22,11 +23,18 @@ class TestSCMStudy(unittest.TestCase): def test_extended_run(self): for study_class in [ExtendedSafran, ExtendedCrocusSwe]: - for study in study_iterator(study_class, only_first_one=True, both_altitude=True, verbose=False): + 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[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))) + if __name__ == '__main__': unittest.main() diff --git a/test/test_meteo_france_SCM_study/test_safran_gev.py b/test/test_experiment/test_meteo_france_SCM_study/test_safran_gev.py similarity index 100% rename from test/test_meteo_france_SCM_study/test_safran_gev.py rename to test/test_experiment/test_meteo_france_SCM_study/test_safran_gev.py diff --git a/test/test_utils.py b/test/test_utils.py index 36e1ea3a..8cd297f0 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -1,3 +1,9 @@ +from itertools import product +from typing import List + +from experiment.meteo_france_SCM_study.abstract_study import AbstractStudy +from experiment.meteo_france_SCM_study.crocus.crocus import Crocus, CrocusSwe, CrocusDepth +from experiment.meteo_france_SCM_study.crocus.crocus_variables import CrocusSweVariable, CrocusDepthVariable from extreme_estimator.estimator.full_estimator.abstract_full_estimator import SmoothMarginalsThenUnitaryMsp, \ FullEstimatorInASingleStepWithSmoothMargin from extreme_estimator.estimator.max_stable_estimator.abstract_max_stable_estimator import MaxStableEstimator @@ -15,7 +21,8 @@ from spatio_temporal_dataset.coordinates.spatial_coordinates.generated_spatial_c from spatio_temporal_dataset.coordinates.spatio_temporal_coordinates.generated_spatio_temporal_coordinates import \ UniformSpatioTemporalCoordinates from spatio_temporal_dataset.coordinates.spatial_coordinates.coordinates_1D import UniformSpatialCoordinates -from spatio_temporal_dataset.coordinates.temporal_coordinates.generated_temporal_coordinates import ConsecutiveTemporalCoordinates +from spatio_temporal_dataset.coordinates.temporal_coordinates.generated_temporal_coordinates import \ + ConsecutiveTemporalCoordinates """ Common objects to load for the test. @@ -87,7 +94,18 @@ def load_test_spatiotemporal_coordinates(nb_points, nb_steps, train_split_ratio= for coordinate_class in TEST_SPATIO_TEMPORAL_COORDINATES] -def load_safran_objects(): - nb_days_list = [1, 3, 5][:1] - safran_altitude_list = [1800, 2400][:1] - return [Safran(safran_altitude, nb_days) for safran_altitude in safran_altitude_list for nb_days in nb_days_list] \ No newline at end of file +def load_safran_studies(altitudes) -> List[Safran]: + nb_days_list = [1] + return [Safran(safran_altitude, nb_days) for safran_altitude in altitudes for nb_days in nb_days_list] + + +def load_crocus_studies(altitudes) -> List[Crocus]: + crocus_classes = [CrocusSwe, CrocusDepth][:] + return [crocus_class(altitude) for crocus_class, altitude in product(crocus_classes, altitudes)] + + +def load_scm_studies() -> List[AbstractStudy]: + altitudes = [1800, 2400][:] + scm_studies = load_safran_studies(altitudes) + scm_studies += load_crocus_studies(altitudes) + return scm_studies -- GitLab