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 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.trend_analysis.univariate_trend_test.abstract_trend_test import AbstractTrendTest
from utils import cached_property, VERSION_TIME, 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
from utils import get_display_name_from_object_type
# 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}
class AltitudeHypercubeVisualizer(HypercubeVisualizer):
class AltitudeHypercubeVisualizer(AbstractHypercubeVisualizer):
@property
def altitudes(self):
......@@ -109,7 +26,7 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer):
# Map each trend type to its serie with percentages
trend_type_to_s_percentages = {}
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
s_percentages = reduction_function(df_bool)
assert isinstance(s_percentages, pd.Series)
......@@ -125,10 +42,8 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer):
def subtitle_to_reduction_function(self, reduction_function, level=None, add_detailed_plot=False):
def reduction_function_with_level(df_bool):
if level is None:
return reduction_function(df_bool)
else:
return reduction_function(df_bool, level)
return reduction_function(df_bool) if level is None else reduction_function(df_bool, level)
return {'global': reduction_function_with_level}
def visualize_trend_test_evolution(self, reduction_function, xlabel, xlabel_values, ax=None, marker='o',
......@@ -214,10 +129,10 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer):
# Take the mean with respect to the years
df_bool = df_bool.mean(axis=1)
# Take the mean with respect the massifs
print(df_bool.head())
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():
self.visualize_trend_test_evolution(reduction_function=reduction_function, xlabel='altitude',
xlabel_values=self.altitudes, ax=ax, marker=marker,
......@@ -230,51 +145,7 @@ class AltitudeHypercubeVisualizer(HypercubeVisualizer):
# Take the mean with respect the altitude
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():
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
from itertools import product
from collections import OrderedDict
from experiment.meteo_france_SCM_study.visualization.hypercube_visualization.hypercube_visualizer import \
AltitudeHypercubeVisualizer, QuantityAltitudeHypercubeVisualizer
from experiment.meteo_france_SCM_study.visualization.hypercube_visualization.altitude_hypercube_visualizer import \
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, \
SCM_STUDIES, study_iterator, study_iterator_global
from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer
......@@ -90,9 +92,9 @@ def fast_trends_with_quantity_altitude_hypercube():
def main_run():
# fast_trends_with_altitude_hypercube()
fast_trends_with_altitude_hypercube()
# fast_trends_with_quantity_altitude_hypercube()
full_trends_with_quantity_altitude_hypercube()
# full_trends_with_quantity_altitude_hypercube()
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
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.univariate_trend_test.abstract_gev_trend_test import GevLocationTrendTest, \
GevScaleTrendTest, GevShapeTrendTest
......@@ -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, \
AltitudeVisualizer
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 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