diff --git a/experiment/meteo_france_SCM_study/abstract_extended_study.py b/experiment/meteo_france_SCM_study/abstract_extended_study.py index 2da5a1e8de34dae4929b2c4cb8959a5f5a7e9911..fad23841dddb2ab58be3336d2f4aa0f2d7a915b6 100644 --- a/experiment/meteo_france_SCM_study/abstract_extended_study.py +++ b/experiment/meteo_france_SCM_study/abstract_extended_study.py @@ -57,6 +57,5 @@ class AbstractExtendedStudy(AbstractStudy): massifs_ids_belong_to_region = self.region_name_to_massif_ids[region_name] aggregated_time_serie = aggregation_function(old_time_serie[:, massifs_ids_belong_to_region], axis=1) new_time_serie[:, i] = aggregated_time_serie - year_to_extended_time_serie[year] = new_time_serie return year_to_extended_time_serie diff --git a/experiment/meteo_france_SCM_study/abstract_study.py b/experiment/meteo_france_SCM_study/abstract_study.py index 22d18fce45aa9771c820318580e576fc34efeeef..c1f362f5b0a4ca334e74de4739a2a321c3b84eb9 100644 --- a/experiment/meteo_france_SCM_study/abstract_study.py +++ b/experiment/meteo_france_SCM_study/abstract_study.py @@ -44,6 +44,10 @@ class AbstractStudy(object): def observations_annual_maxima(self) -> AnnualMaxima: return AnnualMaxima(df_maxima_gev=pd.DataFrame(self.year_to_annual_maxima, index=self.safran_massif_names)) + @property + def df_annual_mean(self) -> pd.DataFrame: + return pd.DataFrame(self.year_to_annual_mean, index=self.safran_massif_names).transpose() + """ Load some attributes only once """ @cached_property @@ -67,6 +71,14 @@ class AbstractStudy(object): year_to_annual_maxima[year] = time_serie.max(axis=0) return year_to_annual_maxima + @cached_property + def year_to_annual_mean(self) -> OrderedDict: + # Map each year to an array of size nb_massif + year_to_annual_mean = OrderedDict() + for year, time_serie in self._year_to_daily_time_serie.items(): + year_to_annual_mean[year] = time_serie.mean(axis=0) + return year_to_annual_mean + def instantiate_variable_object(self, dataset) -> AbstractVariable: return self.variable_class(dataset, self.altitude) @@ -86,6 +98,8 @@ class AbstractStudy(object): def _year_to_max_daily_time_serie(self) -> OrderedDict: return self._year_to_daily_time_serie + + ########## @property diff --git a/experiment/meteo_france_SCM_study/safran/safran.py b/experiment/meteo_france_SCM_study/safran/safran.py index 6588b1e517ff1caf8f3cc94a2fbe792706c74ccd..ccc30a1f57321854029620c2df20cbff729f21f4 100644 --- a/experiment/meteo_france_SCM_study/safran/safran.py +++ b/experiment/meteo_france_SCM_study/safran/safran.py @@ -26,6 +26,8 @@ class ExtendedSafran(AbstractExtendedStudy, Safran): 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 + # print(d.variables['time']) + # print(study.year_to_daily_time_serie[1958].shape) + # print(len(d.variables['time'])) + print(study.year_to_annual_mean) + print(study.df_annual_mean) diff --git a/experiment/meteo_france_SCM_study/visualization/__init__.py b/experiment/meteo_france_SCM_study/visualization/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/experiment/meteo_france_SCM_study/visualization/studies_visualization/__init__.py b/experiment/meteo_france_SCM_study/visualization/studies_visualization/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 new file mode 100644 index 0000000000000000000000000000000000000000..83d192def46ff1600212489683f8cbe64c9a8b03 --- /dev/null +++ b/experiment/meteo_france_SCM_study/visualization/studies_visualization/main_studies_visualizer.py @@ -0,0 +1,24 @@ +from experiment.meteo_france_SCM_study.abstract_study import AbstractStudy +from experiment.meteo_france_SCM_study.crocus.crocus import CrocusDepth, CrocusSwe, ExtendedCrocusDepth, \ + ExtendedCrocusSwe +from experiment.meteo_france_SCM_study.safran.safran import Safran, ExtendedSafran +from experiment.meteo_france_SCM_study.visualization.studies_visualization.studies import Studies +from experiment.meteo_france_SCM_study.visualization.studies_visualization.studies_visualizer import StudiesVisualizer + +from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer +from collections import OrderedDict + +SCM_STUDIES = [Safran, CrocusSwe, CrocusDepth] +SCM_EXTENDED_STUDIES = [ExtendedSafran, ExtendedCrocusSwe, ExtendedCrocusDepth] +SCM_STUDY_TO_EXTENDED_STUDY = OrderedDict(zip(SCM_STUDIES, SCM_EXTENDED_STUDIES)) + + +def normal_visualization(): + for study_type in SCM_EXTENDED_STUDIES[1:2]: + extended_studies = Studies(study_type) + studies_visualizer = StudiesVisualizer(extended_studies) + studies_visualizer.mean_as_a_function_of_altitude(region_only=True) + + +if __name__ == '__main__': + normal_visualization() diff --git a/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies.py b/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies.py new file mode 100644 index 0000000000000000000000000000000000000000..784f1bc013b3df92333cca8098dca4b25074a402 --- /dev/null +++ b/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies.py @@ -0,0 +1,28 @@ +from collections import OrderedDict +from typing import Dict + +from experiment.meteo_france_SCM_study.abstract_study import AbstractStudy + + +class Studies(object): + """Object that will handle studies of the same study type (it could be Safran for instance) + at several altitudes""" + + def __init__(self, study_type, altitude_list=None) -> None: + # Load altitude_list attribute + if altitude_list is None: + altitude_list = AbstractStudy.ALTITUDES + else: + assert isinstance(altitude_list, list) + assert len(altitude_list) > 0 + assert all([altitudes in AbstractStudy.ALTITUDES for altitudes in altitude_list]) + altitude_list = sorted(altitude_list) + self.altitude_list = altitude_list + # Load altitude_to_study attribute + self.altitude_to_study = OrderedDict() # type: Dict[int, AbstractStudy] + for altitude in self.altitude_list: + self.altitude_to_study[altitude] = study_type(altitude=altitude) + + @property + def first_study(self): + return self.altitude_to_study[self.altitude_list[0]] diff --git a/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies_visualizer.py b/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies_visualizer.py new file mode 100644 index 0000000000000000000000000000000000000000..398d5af703026f5a55559e3b24ff0166e5e365cd --- /dev/null +++ b/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies_visualizer.py @@ -0,0 +1,39 @@ +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +from experiment.meteo_france_SCM_study.abstract_extended_study import AbstractExtendedStudy +from experiment.meteo_france_SCM_study.visualization.studies_visualization.studies import \ + Studies +from experiment.meteo_france_SCM_study.visualization.utils import plot_df + + +class StudiesVisualizer(object): + + def __init__(self, studies: Studies) -> None: + self.studies = studies + + @property + def first_study(self): + return self.studies.first_study + + def mean_as_a_function_of_altitude(self, region_only=False): + # Load the massif names to display + if region_only: + assert isinstance(self.first_study, AbstractExtendedStudy) + massif_names = self.first_study.region_names + else: + massif_names = self.first_study.safran_massif_names + # Load the dictionary that maps each massif_name to its corresponding time series + mean_series = [] + for study in self.studies.altitude_to_study.values(): + mean_serie = study.df_annual_mean.loc[:, massif_names].mean(axis=0) + mean_series.append(mean_serie) + df_mean = pd.concat(mean_series, axis=1) # type: pd.DataFrame + df_mean.columns = self.studies.altitude_list + plot_df(df_mean) + + + + + diff --git a/experiment/meteo_france_SCM_study/visualization/study_visualization/__init__.py b/experiment/meteo_france_SCM_study/visualization/study_visualization/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/experiment/meteo_france_SCM_study/main_visualize.py b/experiment/meteo_france_SCM_study/visualization/study_visualization/main_study_visualizer.py similarity index 96% rename from experiment/meteo_france_SCM_study/main_visualize.py rename to experiment/meteo_france_SCM_study/visualization/study_visualization/main_study_visualizer.py index 1719c32503c49973553b034dcb2b389f0dfa2824..0b6f82962472a0e9e63b3f431a53ae0bbf3a851f 100644 --- a/experiment/meteo_france_SCM_study/main_visualize.py +++ b/experiment/meteo_france_SCM_study/visualization/study_visualization/main_study_visualizer.py @@ -2,9 +2,8 @@ from experiment.meteo_france_SCM_study.abstract_study import AbstractStudy from experiment.meteo_france_SCM_study.crocus.crocus import CrocusDepth, CrocusSwe, ExtendedCrocusDepth, \ ExtendedCrocusSwe from experiment.meteo_france_SCM_study.safran.safran import Safran, ExtendedSafran -from itertools import product -from experiment.meteo_france_SCM_study.safran.safran_visualizer import StudyVisualizer +from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer from collections import OrderedDict SCM_STUDIES = [Safran, CrocusSwe, CrocusDepth] diff --git a/experiment/meteo_france_SCM_study/safran/safran_visualizer.py b/experiment/meteo_france_SCM_study/visualization/study_visualization/study_visualizer.py similarity index 100% rename from experiment/meteo_france_SCM_study/safran/safran_visualizer.py rename to experiment/meteo_france_SCM_study/visualization/study_visualization/study_visualizer.py diff --git a/experiment/meteo_france_SCM_study/visualization/utils.py b/experiment/meteo_france_SCM_study/visualization/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..1a0e4532a46ed09ba1cfd745e71d108217d1369f --- /dev/null +++ b/experiment/meteo_france_SCM_study/visualization/utils.py @@ -0,0 +1,29 @@ +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd + + +def plot_df(df: pd.DataFrame, ax=None, ylabel='Example plot', show=True, xlabel='Altitude (m)'): + if ax is None: + fig, ax = plt.subplots(1, 1) + for _, row in df.iterrows(): + ax.set_xlabel(xlabel) + ax.set_ylabel(ylabel) + ax.plot(np.array(row.index), row.values, '-+', label=row.name) + ax.set_title("") + ax.legend() + + if show: + plt.show() + + +def example_plot_df(): + df = pd.DataFrame.from_dict({ + '1800': [0, 2], + '2400': [1, 3], + }, columns=['North', 'South'], orient='index').transpose() + plot_df(df) + + +if __name__ == '__main__': + example_plot_df() diff --git a/test/test_experiment/test_meteo_france_SCM_study/test_SCM_study.py b/test/test_experiment/test_meteo_france_SCM_study/test_SCM_study.py index 01c0f51214a58a35c3484ba3cab52cec3b51b8af..811c519db8d9871938c219b96e10dd497796b610 100644 --- a/test/test_experiment/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,10 @@ import unittest import pandas as pd -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.crocus.crocus import ExtendedCrocusSwe +from experiment.meteo_france_SCM_study.visualization.study_visualization.main_study_visualizer 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 experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer from test.test_utils import load_scm_studies