diff --git a/extreme_data/meteo_france_data/scm_models_data/abstract_study.py b/extreme_data/meteo_france_data/scm_models_data/abstract_study.py index 91be36f36cfcfc76af97424480e4ddcaecfd58ce..5cd271a392cd43447353698232277b296a296b73 100644 --- a/extreme_data/meteo_france_data/scm_models_data/abstract_study.py +++ b/extreme_data/meteo_france_data/scm_models_data/abstract_study.py @@ -1,4 +1,5 @@ import datetime +from enum import Enum from matplotlib.lines import Line2D import io @@ -22,7 +23,8 @@ from extreme_data.edf_data.weather_types import load_df_weather_types from extreme_data.meteo_france_data.scm_models_data.abstract_variable import AbstractVariable from extreme_data.meteo_france_data.scm_models_data.utils import ALTITUDES, ZS_INT_23, ZS_INT_MASK, LONGITUDES, \ LATITUDES, ORIENTATIONS, SLOPES, ORDERED_ALLSLOPES_ALTITUDES, ORDERED_ALLSLOPES_ORIENTATIONS, \ - ORDERED_ALLSLOPES_SLOPES, ORDERED_ALLSLOPES_MASSIFNUM, date_to_str, WP_PATTERN_MAX_YEAR + ORDERED_ALLSLOPES_SLOPES, ORDERED_ALLSLOPES_MASSIFNUM, date_to_str, WP_PATTERN_MAX_YEAR, SeasonForTheMaxima, \ + first_day_and_last_day from extreme_data.meteo_france_data.scm_models_data.visualization.utils import get_km_formatter from extreme_fit.function.margin_function.abstract_margin_function import \ AbstractMarginFunction @@ -60,7 +62,8 @@ class AbstractStudy(object): # REANALYSIS_FOLDER = 'SAFRAN_montagne-CROCUS_2019/postes/reanalysis' def __init__(self, variable_class: type, altitude: int = 1800, year_min=1959, year_max=2019, - multiprocessing=True, orientation=None, slope=20.0): + multiprocessing=True, orientation=None, slope=20.0, + season=SeasonForTheMaxima.annual): assert isinstance(altitude, int), type(altitude) assert altitude in ALTITUDES, altitude self.altitude = altitude @@ -69,6 +72,7 @@ class AbstractStudy(object): self.year_min = year_min self.year_max = year_max self.multiprocessing = multiprocessing + self.season = season # Add some attributes, for the "allslopes" reanalysis assert orientation is None or orientation in ORIENTATIONS assert slope in SLOPES @@ -77,11 +81,29 @@ class AbstractStudy(object): """ Time """ + @cached_property + def year_to_first_index_and_last_index(self): + year_to_first_index_and_last_index = OrderedDict() + first_day, last_day = first_day_and_last_day(self.season) + for year, all_days in self.year_to_all_days.items(): + first_index = all_days.index('{}-{}'.format(year-1, first_day)) + last_index = all_days.index('{}-{}'.format(year, last_day)) + year_to_first_index_and_last_index[year] = (first_index, last_index) + return year_to_first_index_and_last_index + @cached_property def year_to_days(self) -> OrderedDict: + year_to_days = OrderedDict() + for year, (start_index, last_index) in self.year_to_first_index_and_last_index.items(): + year_to_days[year] = self.year_to_all_days[year][start_index:last_index+1] + return year_to_days + + @cached_property + def year_to_all_days(self) -> OrderedDict: # Map each year to the 'days since year-08-01 06:00:00' year_to_days = OrderedDict() for year in self.ordered_years: + # Load days for the full year date = datetime.datetime(year=year - 1, month=8, day=1, hour=6, minute=0, second=0) days = [] for i in range(366): @@ -266,8 +288,12 @@ class AbstractStudy(object): daily_time_serie = self.year_to_variable_object[year].daily_time_serie_array assert daily_time_serie.shape[0] in [365, 366] assert daily_time_serie.shape[1] == len(self.column_mask) - # Filter only the data corresponding to the altitude of interest - daily_time_serie = daily_time_serie[:, self.column_mask] + # Filter only the data corresponding: + # 1: to the start_index and last_index of the season + # 2: to the massifs for the altitude of interest + first_index, last_index = self.year_to_first_index_and_last_index[year] + daily_time_serie = daily_time_serie[first_index:last_index+1, self.column_mask] + assert daily_time_serie.shape == (len(self.year_to_days[year]), len(self.study_massif_names)) year_to_daily_time_serie_array[year] = daily_time_serie return year_to_daily_time_serie_array diff --git a/extreme_data/meteo_france_data/scm_models_data/utils.py b/extreme_data/meteo_france_data/scm_models_data/utils.py index f73d6db2b5ad8b4861ec29a855834abff193c4a7..1dbdfe4be64711cb2e9cd5cb5886bb6a9850e284 100644 --- a/extreme_data/meteo_france_data/scm_models_data/utils.py +++ b/extreme_data/meteo_france_data/scm_models_data/utils.py @@ -2,6 +2,7 @@ ZS was extracted from a netcdf file """ from datetime import datetime +from enum import Enum import numpy as np @@ -12,6 +13,20 @@ def date_to_str(date: datetime) -> str: return str(date).split()[0] +class SeasonForTheMaxima(Enum): + annual = 0 + winter_extended = 1 + # i could add the classical seasons if needed + + +def first_day_and_last_day(season): + season_to_start_day_and_last_day = { + SeasonForTheMaxima.annual: ('08-01', '07-31'), + SeasonForTheMaxima.winter_extended: ('11-01', '05-31') + } + return season_to_start_day_and_last_day[season] + + ZS = """[ 300. 600. 900. 1200. 1500. 1800. 2100. 2400. 2700. 3000. 3300. 300. 600. 900. 1200. 1500. 1800. 2100. 2400. 2700. 3000. 300. 600. 900. 1200. 1500. 1800. 2100. 2400. 2700. 3000. 3300. 3600. 3900. 4200. 4500. diff --git a/test/test_extreme_data/test_meteo_france_data/test_SCM_study.py b/test/test_extreme_data/test_meteo_france_data/test_SCM_study.py index c3ff62e7b125ca16bbd5bfb22670c94a9b8e9a85..9c829c99bde81cbb77d6ed1b3de59d9e11b4c47a 100644 --- a/test/test_extreme_data/test_meteo_france_data/test_SCM_study.py +++ b/test/test_extreme_data/test_meteo_france_data/test_SCM_study.py @@ -7,6 +7,7 @@ import pandas as pd from extreme_data.meteo_france_data.scm_models_data.safran.cumulated_study import NB_DAYS from extreme_data.meteo_france_data.scm_models_data.safran.safran import SafranSnowfall, SafranTemperature, \ SafranPrecipitation +from extreme_data.meteo_france_data.scm_models_data.utils import SeasonForTheMaxima from extreme_data.meteo_france_data.scm_models_data.visualization.main_study_visualizer import \ study_iterator_global, SCM_STUDIES, ALL_ALTITUDES from root_utils import get_display_name_from_object_type @@ -18,8 +19,18 @@ class TestSCMAllStudy(unittest.TestCase): year = 2019 study = SafranSnowfall(altitude=900, year_min=year, year_max=year) first_day, *_, last_day = study.year_to_days[year] - self.assertIn(str(year-1), first_day) - self.assertIn(str(year), last_day) + self.assertEqual('{}-08-01'.format(year - 1), first_day) + self.assertEqual('{}-07-31'.format(year), last_day) + + def test_year_to_winter_date(self): + year = 2019 + study = SafranSnowfall(altitude=900, year_min=year, year_max=year, season=SeasonForTheMaxima.winter_extended) + first_day, *_, last_day = study.year_to_days[year] + self.assertEqual('{}-11-01'.format(year - 1), first_day) + self.assertEqual('{}-05-31'.format(year), last_day) + days = study.year_to_days[year] + daily_time_series = study.year_to_daily_time_serie_array[year] + self.assertEqual(len(days), len(daily_time_series)) def test_instantiate_studies(self): nb_sample = 2 @@ -30,7 +41,8 @@ class TestSCMAllStudy(unittest.TestCase): first_path_file = study.ordered_years_and_path_files[0][0] variable_object = study.load_variable_object(path_file=first_path_file) 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)))) + msg='{} days for type {}'.format(nb_days, get_display_name_from_object_type( + type(variable_object)))) class TestSCMStudy(unittest.TestCase):