Commit 0cdf467d authored by Le Roux Erwan's avatar Le Roux Erwan
Browse files

[SCM][HYPERCUBE] refactor hypercube_visualization folder.

parent db8ab9c8
No related merge requests found
Showing with 159 additions and 148 deletions
+159 -148
import os
import os.path as op
from typing import Dict, Tuple
import matplotlib.pyplot as plt
import pandas as pd
from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer
from utils import cached_property, VERSION_TIME, get_display_name_from_object_type
class AbstractHypercubeVisualizer(object):
"""
A study visualizer contain some massifs and years. This forms the base DataFrame of the hypercube
Additional index will come from the tuple.
Tuple could contain altitudes, type of snow quantity
"""
def __init__(self, tuple_to_study_visualizer: Dict[Tuple, StudyVisualizer],
trend_test_class,
fast=False,
save_to_file=False):
self.nb_data_for_fast_mode = 7 if fast else None
self.save_to_file = save_to_file
self.trend_test_class = trend_test_class
self.tuple_to_study_visualizer = tuple_to_study_visualizer # type: Dict[Tuple, StudyVisualizer]
# Main attributes defining the hypercube
@property
def trend_test_name(self):
return get_display_name_from_object_type(self.trend_test_class)
@cached_property
def starting_years(self):
starting_years = self.study_visualizer.starting_years
if self.nb_data_for_fast_mode is not None:
starting_years = starting_years[:self.nb_data_for_fast_mode]
return starting_years
def tuple_values(self, idx):
return sorted(set([t[idx] if isinstance(t, tuple) else t for t in self.tuple_to_study_visualizer.keys()]))
@cached_property
def df_hypercube_trend_type(self) -> pd.DataFrame:
df_spatio_temporal_trend_types = [
study_visualizer.df_trend_spatio_temporal(self.trend_test_class, self.starting_years,
self.nb_data_for_fast_mode)
for study_visualizer in self.tuple_to_study_visualizer.values()]
return pd.concat(df_spatio_temporal_trend_types, keys=list(self.tuple_to_study_visualizer.keys()), axis=0)
@cached_property
def df_hypercube_trend_strength(self) -> pd.DataFrame:
df_spatio_temporal_trend_types = [
study_visualizer.df_trend_spatio_temporal(self.trend_test_class, self.starting_years,
self.nb_data_for_fast_mode)
for study_visualizer in self.tuple_to_study_visualizer.values()]
return pd.concat(df_spatio_temporal_trend_types, keys=list(self.tuple_to_study_visualizer.keys()), axis=0)
# Some properties
@property
def study_title(self):
return self.study.title
def show_or_save_to_file(self, specific_title=''):
if self.save_to_file:
main_title, *_ = '_'.join(self.study_title.split()).split('/')
filename = "{}/{}/".format(VERSION_TIME, main_title)
filename += specific_title
filepath = op.join(self.study.result_full_path, filename + '.png')
dirname = op.dirname(filepath)
if not op.exists(dirname):
os.makedirs(dirname, exist_ok=True)
plt.savefig(filepath)
else:
plt.show()
@property
def study_visualizer(self) -> StudyVisualizer:
return list(self.tuple_to_study_visualizer.values())[0]
@property
def study(self):
return self.study_visualizer.study
@property
def starting_year_to_weights(self):
# Load uniform weights by default
uniform_weight = 1 / len(self.starting_years)
return {year: uniform_weight for year in self.starting_years}
import os
import os.path as op
from typing import Dict, Tuple
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import pandas as pd import pandas as pd
from experiment.meteo_france_SCM_study.visualization.hypercube_visualization.abstract_hypercube_visualizer import \
AbstractHypercubeVisualizer
from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer
from experiment.trend_analysis.univariate_trend_test.abstract_trend_test import AbstractTrendTest from experiment.trend_analysis.univariate_trend_test.abstract_trend_test import AbstractTrendTest
from utils import cached_property, VERSION_TIME, get_display_name_from_object_type from utils import get_display_name_from_object_type
class HypercubeVisualizer(object):
"""
A study visualizer contain some massifs and years. This forms the base DataFrame of the hypercube
Additional index will come from the tuple.
Tuple could contain altitudes, type of snow quantity
"""
def __init__(self, tuple_to_study_visualizer: Dict[Tuple, StudyVisualizer],
trend_test_class,
fast=False,
save_to_file=False):
self.nb_data_for_fast_mode = 7 if fast else None
self.save_to_file = save_to_file
self.trend_test_class = trend_test_class
self.tuple_to_study_visualizer = tuple_to_study_visualizer # type: Dict[Tuple, StudyVisualizer]
# Main attributes defining the hypercube
@property
def trend_test_name(self):
return get_display_name_from_object_type(self.trend_test_class)
@cached_property
def starting_years(self):
starting_years = self.study_visualizer.starting_years
if self.nb_data_for_fast_mode is not None:
starting_years = starting_years[:self.nb_data_for_fast_mode]
return starting_years
@cached_property
def tuple_to_df_trend_type(self):
df_spatio_temporal_trend_types = [
study_visualizer.df_trend_spatio_temporal(self.trend_test_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))
def tuple_values(self, idx):
return sorted(set([t[idx] if isinstance(t, tuple) else t for t in self.tuple_to_study_visualizer.keys()]))
@cached_property
def df_hypercube(self) -> pd.DataFrame:
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)
return df
# Some properties
@property class AltitudeHypercubeVisualizer(AbstractHypercubeVisualizer):
def study_title(self):
return self.study.title
def show_or_save_to_file(self, specific_title=''):
if self.save_to_file:
main_title, *_ = '_'.join(self.study_title.split()).split('/')
filename = "{}/{}/".format(VERSION_TIME, main_title)
filename += specific_title
filepath = op.join(self.study.result_full_path, filename + '.png')
dirname = op.dirname(filepath)
if not op.exists(dirname):
os.makedirs(dirname, exist_ok=True)
plt.savefig(filepath)
else:
plt.show()
@property
def study_visualizer(self) -> StudyVisualizer:
return list(self.tuple_to_study_visualizer.values())[0]
@property
def study(self):
return self.study_visualizer.study
@property
def starting_year_to_weights(self):
# Load uniform weights by default
uniform_weight = 1 / len(self.starting_years)
return {year: uniform_weight for year in self.starting_years}
class AltitudeHypercubeVisualizer(HypercubeVisualizer):
@property @property
def altitudes(self): def altitudes(self):
...@@ -109,7 +26,7 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer): ...@@ -109,7 +26,7 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer):
# Map each trend type to its serie with percentages # Map each trend type to its serie with percentages
trend_type_to_s_percentages = {} trend_type_to_s_percentages = {}
for trend_type in self.trend_types: for trend_type in self.trend_types:
df_bool = (self.df_hypercube == trend_type) df_bool = (self.df_hypercube_trend_type == trend_type)
# Reduce the entire dataframe to a serie # Reduce the entire dataframe to a serie
s_percentages = reduction_function(df_bool) s_percentages = reduction_function(df_bool)
assert isinstance(s_percentages, pd.Series) assert isinstance(s_percentages, pd.Series)
...@@ -125,10 +42,8 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer): ...@@ -125,10 +42,8 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer):
def subtitle_to_reduction_function(self, reduction_function, level=None, add_detailed_plot=False): def subtitle_to_reduction_function(self, reduction_function, level=None, add_detailed_plot=False):
def reduction_function_with_level(df_bool): def reduction_function_with_level(df_bool):
if level is None: return reduction_function(df_bool) if level is None else reduction_function(df_bool, level)
return reduction_function(df_bool)
else:
return reduction_function(df_bool, level)
return {'global': reduction_function_with_level} return {'global': reduction_function_with_level}
def visualize_trend_test_evolution(self, reduction_function, xlabel, xlabel_values, ax=None, marker='o', def visualize_trend_test_evolution(self, reduction_function, xlabel, xlabel_values, ax=None, marker='o',
...@@ -214,10 +129,10 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer): ...@@ -214,10 +129,10 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer):
# Take the mean with respect to the years # Take the mean with respect to the years
df_bool = df_bool.mean(axis=1) df_bool = df_bool.mean(axis=1)
# Take the mean with respect the massifs # Take the mean with respect the massifs
print(df_bool.head())
return df_bool.mean(level=level) return df_bool.mean(level=level)
for subtitle, reduction_function in self.subtitle_to_reduction_function(altitude_reduction, level=self.altitude_index_level, for subtitle, reduction_function in self.subtitle_to_reduction_function(altitude_reduction,
level=self.altitude_index_level,
add_detailed_plot=add_detailed_plots).items(): add_detailed_plot=add_detailed_plots).items():
self.visualize_trend_test_evolution(reduction_function=reduction_function, xlabel='altitude', self.visualize_trend_test_evolution(reduction_function=reduction_function, xlabel='altitude',
xlabel_values=self.altitudes, ax=ax, marker=marker, xlabel_values=self.altitudes, ax=ax, marker=marker,
...@@ -230,51 +145,7 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer): ...@@ -230,51 +145,7 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer):
# Take the mean with respect the altitude # Take the mean with respect the altitude
return df_bool.mean(level=level) return df_bool.mean(level=level)
for subtitle, reduction_function in self.subtitle_to_reduction_function(massif_reduction,level=self.massif_index_level, for subtitle, reduction_function in self.subtitle_to_reduction_function(massif_reduction,
level=self.massif_index_level,
add_detailed_plot=add_detailed_plots).items(): add_detailed_plot=add_detailed_plots).items():
self.visualize_trend_test_repartition(reduction_function, axes, subtitle=subtitle) self.visualize_trend_test_repartition(reduction_function, axes, subtitle=subtitle)
class QuantityAltitudeHypercubeVisualizer(AltitudeHypercubeVisualizer):
@property
def study_title(self):
return 'Quantity Altitude Study'
def subtitle_to_reduction_function(self, reduction_function, level=None, add_detailed_plot=False):
subtitle_to_reduction_function = super().subtitle_to_reduction_function(reduction_function, level, add_detailed_plot)
def get_function_from_tuple(tuple_for_axis_0):
def f(df_bool: pd.DataFrame):
# Loc with a tuple with respect the axis 0
df_bool = df_bool.loc[tuple_for_axis_0, :].copy()
# Apply the reduction function
if level is None:
return reduction_function(df_bool)
else:
return reduction_function(df_bool, level-1)
return f
# Add the detailed plot, taken by loc with respect to the first index
if add_detailed_plot:
tuples_axis_0 = self.tuple_values(idx=0)
for tuple_axis_0 in tuples_axis_0:
subtitle_to_reduction_function[tuple_axis_0] = get_function_from_tuple(tuple_axis_0)
return subtitle_to_reduction_function
@property
def quantities(self):
return self.tuple_values(idx=0)
@property
def altitudes(self):
return self.tuple_values(idx=1)
@property
def altitude_index_level(self):
return 1
@property
def massif_index_level(self):
return 2
...@@ -2,8 +2,10 @@ import time ...@@ -2,8 +2,10 @@ import time
from itertools import product from itertools import product
from collections import OrderedDict from collections import OrderedDict
from experiment.meteo_france_SCM_study.visualization.hypercube_visualization.hypercube_visualizer import \ from experiment.meteo_france_SCM_study.visualization.hypercube_visualization.altitude_hypercube_visualizer import \
AltitudeHypercubeVisualizer, QuantityAltitudeHypercubeVisualizer AltitudeHypercubeVisualizer
from experiment.meteo_france_SCM_study.visualization.hypercube_visualization.quantity_altitude_visualizer import \
QuantityAltitudeHypercubeVisualizer
from experiment.meteo_france_SCM_study.visualization.study_visualization.main_study_visualizer import ALL_ALTITUDES, \ from experiment.meteo_france_SCM_study.visualization.study_visualization.main_study_visualizer import ALL_ALTITUDES, \
SCM_STUDIES, study_iterator, study_iterator_global SCM_STUDIES, study_iterator, study_iterator_global
from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer
...@@ -90,9 +92,9 @@ def fast_trends_with_quantity_altitude_hypercube(): ...@@ -90,9 +92,9 @@ def fast_trends_with_quantity_altitude_hypercube():
def main_run(): def main_run():
# fast_trends_with_altitude_hypercube() fast_trends_with_altitude_hypercube()
# fast_trends_with_quantity_altitude_hypercube() # fast_trends_with_quantity_altitude_hypercube()
full_trends_with_quantity_altitude_hypercube() # full_trends_with_quantity_altitude_hypercube()
if __name__ == '__main__': if __name__ == '__main__':
......
import pandas as pd
from experiment.meteo_france_SCM_study.visualization.hypercube_visualization.altitude_hypercube_visualizer import \
AltitudeHypercubeVisualizer
class QuantityAltitudeHypercubeVisualizer(AltitudeHypercubeVisualizer):
@property
def study_title(self):
return 'Quantity Altitude Study'
def subtitle_to_reduction_function(self, reduction_function, level=None, add_detailed_plot=False):
subtitle_to_reduction_function = super().subtitle_to_reduction_function(reduction_function,
level, add_detailed_plot)
def get_function_from_tuple(tuple_for_axis_0):
def f(df_bool: pd.DataFrame):
# Loc with a tuple with respect the axis 0
df_bool = df_bool.loc[tuple_for_axis_0, :].copy()
# Apply the reduction function
return reduction_function(df_bool) if level is None else reduction_function(df_bool, level-1)
return f
# Add the detailed plot, taken by loc with respect to the first index
if add_detailed_plot:
tuples_axis_0 = self.tuple_values(idx=0)
for tuple_axis_0 in tuples_axis_0:
subtitle_to_reduction_function[tuple_axis_0] = get_function_from_tuple(tuple_axis_0)
return subtitle_to_reduction_function
@property
def quantities(self):
return self.tuple_values(idx=0)
@property
def altitudes(self):
return self.tuple_values(idx=1)
@property
def altitude_index_level(self):
return 1
@property
def massif_index_level(self):
return 2
import time import time
from experiment.meteo_france_SCM_study.visualization.hypercube_visualization.hypercube_visualizer import \
AltitudeHypercubeVisualizer
from experiment.trend_analysis.abstract_score import MannKendall, WeigthedScore, MeanScore, MedianScore from experiment.trend_analysis.abstract_score import MannKendall, WeigthedScore, MeanScore, MedianScore
from experiment.trend_analysis.univariate_trend_test.abstract_gev_trend_test import GevLocationTrendTest, \ from experiment.trend_analysis.univariate_trend_test.abstract_gev_trend_test import GevLocationTrendTest, \
GevScaleTrendTest, GevShapeTrendTest GevScaleTrendTest, GevShapeTrendTest
...@@ -11,7 +8,7 @@ from experiment.meteo_france_SCM_study.visualization.studies_visualization.studi ...@@ -11,7 +8,7 @@ from experiment.meteo_france_SCM_study.visualization.studies_visualization.studi
from experiment.meteo_france_SCM_study.visualization.studies_visualization.studies_visualizer import StudiesVisualizer, \ from experiment.meteo_france_SCM_study.visualization.studies_visualization.studies_visualizer import StudiesVisualizer, \
AltitudeVisualizer AltitudeVisualizer
from experiment.meteo_france_SCM_study.visualization.study_visualization.main_study_visualizer import ALL_ALTITUDES, \ from experiment.meteo_france_SCM_study.visualization.study_visualization.main_study_visualizer import ALL_ALTITUDES, \
study_iterator_global, SCM_STUDIES, study_iterator study_iterator_global, SCM_STUDIES
from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer
from collections import OrderedDict from collections import OrderedDict
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment