Commit a7fa4dda authored by Le Roux Erwan's avatar Le Roux Erwan
Browse files

[SCM][SCORE TREND] add altitude visualization for the studies

parent 3bf99043
No related merge requests found
Showing with 113 additions and 14 deletions
+113 -14
from experiment.meteo_france_SCM_study.abstract_score import MannKendall, WeigthedScore, MeanScore, MedianScore
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 SafranSnowfall, ExtendedSafranSnowfall, \
ExtendedSafranTotalPrecip
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.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
from experiment.meteo_france_SCM_study.visualization.study_visualization.study_visualizer import StudyVisualizer
from collections import OrderedDict
SCM_STUDIES = [SafranSnowfall, CrocusSwe, CrocusDepth]
SCM_EXTENDED_STUDIES = [ExtendedSafranTotalPrecip, ExtendedSafranSnowfall, 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]:
for study_type in [ExtendedSafranTotalPrecip]:
extended_studies = Studies(study_type)
studies_visualizer = StudiesVisualizer(extended_studies)
studies_visualizer.mean_as_a_function_of_altitude(region_only=True)
def altitude_trends():
save_to_file = False
only_first_one = False
# altitudes that have 20 massifs at least
altitudes = ALL_ALTITUDES[3:-6]
# altitudes = ALL_ALTITUDES[:2]
visualizers = [StudyVisualizer(study, save_to_file=save_to_file, temporal_non_stationarity=True, verbose=True,
score_class=MedianScore)
for study in study_iterator_global(study_classes=[SafranSnowfall], only_first_one=only_first_one,
altitudes=altitudes)]
altitude_to_visualizer = OrderedDict(zip(altitudes, visualizers))
visualizer = AltitudeVisualizer(altitude_to_visualizer)
visualizer.negative_trend_percentages_evolution()
if __name__ == '__main__':
normal_visualization()
altitude_trends()
from collections import OrderedDict, Counter
from typing import Dict
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
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.study_visualization.study_visualizer import StudyVisualizer
from experiment.meteo_france_SCM_study.visualization.utils import plot_df
from utils import cached_property, get_display_name_from_object_type
class StudiesVisualizer(object):
......@@ -29,11 +35,86 @@ class StudiesVisualizer(object):
for study in self.studies.altitude_to_study.values():
mean_serie = study.df_annual_total.loc[:, massif_names].mean(axis=0)
mean_series.append(mean_serie)
df_mean = pd.concat(mean_series, axis=1) # type: pd.DataFrame
df_mean = pd.concat(mean_series, axis=1) # type: pd.DataFrame
df_mean.columns = self.studies.altitude_list
plot_df(df_mean)
class AltitudeVisualizer(object):
def __init__(self, altitude_to_study_visualizer: Dict[int, StudyVisualizer]):
assert isinstance(altitude_to_study_visualizer, OrderedDict)
self.altitude_to_study_visualizer = altitude_to_study_visualizer
@property
def altitudes(self):
return list(self.altitude_to_study_visualizer.keys())
@cached_property
def all_percentages(self):
return [v.percentages_of_negative_trends()[0] for v in self.altitude_to_study_visualizer.values()]
@property
def any_study_visualizer(self) -> StudyVisualizer:
return list(self.altitude_to_study_visualizer.values())[0]
def get_item_fct(self, year):
idx = self.any_study_visualizer.starting_years.index(year)
f = lambda s: s[idx]
return f
@cached_property
def starting_year(self):
return self.any_study_visualizer.starting_years[0]
def get_top_potential_years(self, reverse=False):
top_n = 5
top_top = 3
# keep the top_n for each altitude
all_years = [[year for year, _ in sorted(enumerate(p), key=lambda s:s[1], reverse=reverse)[-top_n:]] for p in self.all_percentages]
from itertools import chain
all_years = list(chain(*all_years))
years = [y for y, _ in sorted(Counter(all_years).items(), key=lambda s:s[1])[-top_top:]]
years = [y + self.starting_year for y in years]
return years
def negative_trend_percentages_evolution(self):
curve_name__metric_and_color = [
('max', np.max, 'r'),
('mean', np.mean, 'b'),
('median', np.median, 'c'),
('min', np.min, 'g'),
]
# Add some years
# spotted_years = [1963, 1976]
# years_to_display = spotted_years
str_markers = ['o'] + [m for m in Line2D.markers if isinstance(m, str)][3:]
# for year, marker in zip(years_to_display, str_markers):
# new = (str(year), self.get_item_fct(year), 'y', marker + ':')
# curve_name__metric_and_color.append(new)
for year, marker in zip(self.get_top_potential_years(), str_markers):
new = (str(year), self.get_item_fct(year), 'm', marker + ':')
curve_name__metric_and_color.append(new)
for year, marker in zip(self.get_top_potential_years(reverse=True), str_markers):
new = (str(year), self.get_item_fct(year), 'y', marker + ':')
curve_name__metric_and_color.append(new)
fig, ax = plt.subplots(1, 1, figsize=self.any_study_visualizer.figsize)
for curve_name, metric, color, *marker in curve_name__metric_and_color[:]:
marker, curve_name = (marker[0], curve_name + ' starting year') if marker \
else ('-', curve_name + ' over the starting years')
values = [metric(p) for p in self.all_percentages]
ax.plot(self.altitudes, values, color + marker, label=curve_name)
ax.legend()
ax.set_xticks(self.altitudes)
ax.set_yticks(list(range(0,101, 10)))
ax.grid()
ax.axhline(y=50, color='k')
ax.set_ylabel('% of negative trends')
ax.set_xlabel('altitude')
scoer_class_name = get_display_name_from_object_type(self.any_study_visualizer.score_class)
title = 'Distribution of negative trend for the {}'.format(scoer_class_name)
ax.set_title(title)
plt.show()
......@@ -402,7 +402,7 @@ class StudyVisualizer(object):
def visualize_score_wrt_starting_year(self, ax, massif_name):
if massif_name is None:
percentage, title = self.percentage_of_negative_trends()
percentage, title = self.percentages_of_negative_trends()
scores = percentage
ax.set_ylabel('% of negative trends')
# Add two lines of interest
......@@ -420,24 +420,27 @@ class StudyVisualizer(object):
ax.set_title(title)
ax.xaxis.set_ticks(self.starting_years[2::20])
def percentage_of_negative_trends(self):
def percentages_of_negative_trends(self):
print('start computing percentages negative trends')
# scores = np.median([np.array(v) < 0 for v in self.massif_name_to_scores.values()], axis=0)
# Take the mean with respect to the massifs
# We obtain an array whose length equal the length of starting years
scores = np.mean([np.array(v) < 0 for v in self.massif_name_to_scores.values()], axis=0)
percentage = 100 * scores
percentages = 100 * scores
# First argmin, first argmax
argmin, argmax = np.argmin(scores), np.argmax(scores)
# Last argmin, last argmax
# argmin, argmax = len(scores) - 1 - np.argmin(scores[::-1]), len(scores) - 1 - np.argmax(scores[::-1])
top_starting_year_for_positive_trend = self.starting_years[argmin]
top_starting_year_for_negative_trend = self.starting_years[argmax]
top_percentage_positive_trend = round(100 - percentage[argmin], 0)
top_percentage_negative_trend = round(percentage[argmax], 0)
top_percentage_positive_trend = round(100 - percentages[argmin], 0)
top_percentage_negative_trend = round(percentages[argmax], 0)
title = "Global trend; > 0: {}% in {}; < 0: {}% in {}".format(top_percentage_positive_trend,
top_starting_year_for_positive_trend,
top_percentage_negative_trend,
top_starting_year_for_negative_trend)
return percentage, title
return percentages, title
def visualize_all_mean_and_max_graphs(self):
specified_massif_ids = [self.study.study_massif_names.index(massif_name)
......
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