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

[SCM] add shifted visualization for both crocus variables

parent 2497b751
No related merge requests found
Showing with 93 additions and 79 deletions
+93 -79
import os import os
import os.path as op import os.path as op
from collections import OrderedDict from collections import OrderedDict
from typing import List from typing import List, Dict
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import pandas as pd import pandas as pd
...@@ -17,29 +17,30 @@ from utils import get_full_path, cached_property ...@@ -17,29 +17,30 @@ from utils import get_full_path, cached_property
class AbstractStudy(object): class AbstractStudy(object):
ALTITUDES = [1800, 2400]
def __init__(self, safran_altitude=1800): def __init__(self, variable_class, altitude=1800):
assert safran_altitude in [1800, 2400] assert altitude in self.ALTITUDES
self.safran_altitude = safran_altitude self.altitude = altitude
self.model_name = None self.model_name = None
self.variable_class = None self.variable_class = variable_class
def write_to_file(self, df): def write_to_file(self, df):
if not op.exists(self.result_full_path): if not op.exists(self.result_full_path):
os.makedirs(self.result_full_path, exist_ok=True) os.makedirs(self.result_full_path, exist_ok=True)
df.to_csv(op.join(self.result_full_path, 'merged_array_{}_altitude.csv'.format(self.safran_altitude))) df.to_csv(op.join(self.result_full_path, 'merged_array_{}_altitude.csv'.format(self.altitude)))
""" Data """ """ Data """
@property @property
def df_all_snowfall_concatenated(self): def df_all_snowfall_concatenated(self) -> pd.DataFrame:
df_list = [pd.DataFrame(snowfall, columns=self.safran_massif_names) for snowfall in df_list = [pd.DataFrame(snowfall, columns=self.safran_massif_names) for snowfall in
self.year_to_daily_time_serie.values()] self.year_to_daily_time_serie.values()]
df_concatenated = pd.concat(df_list) df_concatenated = pd.concat(df_list)
return df_concatenated return df_concatenated
@property @property
def observations_annual_maxima(self): def observations_annual_maxima(self) -> AnnualMaxima:
return AnnualMaxima(df_maxima_gev=pd.DataFrame(self.year_to_annual_maxima, index=self.safran_massif_names)) return AnnualMaxima(df_maxima_gev=pd.DataFrame(self.year_to_annual_maxima, index=self.safran_massif_names))
""" Load some attributes only once """ """ Load some attributes only once """
...@@ -79,11 +80,11 @@ class AbstractStudy(object): ...@@ -79,11 +80,11 @@ class AbstractStudy(object):
@property @property
def safran_massif_names(self) -> List[str]: def safran_massif_names(self) -> List[str]:
# Load the names of the massif as defined by SAFRAN # Load the names of the massif as defined by SAFRAN
return safran_massif_names_from_datasets(self.year_to_dataset_ordered_dict.values()) return safran_massif_names_from_datasets(list(self.year_to_dataset_ordered_dict.values()))
@property @property
def safran_massif_id_to_massif_name(self): def safran_massif_id_to_massif_name(self) -> Dict[int, str]:
return dict(enumerate(self.safran_massif_names)) return {massif_id: massif_name for massif_id, massif_name in enumerate(self.safran_massif_names)}
@cached_property @cached_property
def massifs_coordinates(self) -> AbstractSpatialCoordinates: def massifs_coordinates(self) -> AbstractSpatialCoordinates:
...@@ -103,13 +104,14 @@ class AbstractStudy(object): ...@@ -103,13 +104,14 @@ class AbstractStudy(object):
return df_centroid return df_centroid
@property @property
def coordinate_id_to_massif_name(self) -> dict: def coordinate_id_to_massif_name(self) -> Dict[int, str]:
df_centroid = self.load_df_centroid() df_centroid = self.load_df_centroid()
return dict(zip(df_centroid['id'], df_centroid.index)) return dict(zip(df_centroid['id'], df_centroid.index))
""" Visualization methods """ """ Visualization methods """
def visualize(self, ax=None, massif_name_to_fill_kwargs=None, show=True, fill=True): def visualize(self, ax=None, massif_name_to_fill_kwargs=None, show=True, fill=True):
print("here")
if ax is None: if ax is None:
ax = plt.gca() ax = plt.gca()
df_massif = pd.read_csv(op.join(self.map_full_path, 'massifsalpes.csv')) df_massif = pd.read_csv(op.join(self.map_full_path, 'massifsalpes.csv'))
...@@ -144,7 +146,7 @@ class AbstractStudy(object): ...@@ -144,7 +146,7 @@ class AbstractStudy(object):
@property @property
def safran_full_path(self) -> str: def safran_full_path(self) -> str:
assert self.model_name in ['Safran', 'Crocus'] assert self.model_name in ['Safran', 'Crocus']
return op.join(self.full_path, 'safran-crocus_{}'.format(self.safran_altitude), self.model_name) return op.join(self.full_path, 'safran-crocus_{}'.format(self.altitude), self.model_name)
@property @property
def map_full_path(self) -> str: def map_full_path(self) -> str:
......
...@@ -3,17 +3,32 @@ from experiment.meteo_france_SCM_study.crocus.crocus_variables import CrocusSweV ...@@ -3,17 +3,32 @@ from experiment.meteo_france_SCM_study.crocus.crocus_variables import CrocusSweV
class Crocus(AbstractStudy): class Crocus(AbstractStudy):
"""
In the Crocus data, there is no 'massifsList' variable, thus we assume massifs are ordered just like Safran data
"""
def __init__(self, safran_altitude=1800, crocus_variable_class=CrocusSweVariable): def __init__(self, variable_class, altitude=1800):
super().__init__(safran_altitude) assert variable_class in [CrocusSweVariable, CrocusDepthVariable]
super().__init__(variable_class, altitude)
self.model_name = 'Crocus' self.model_name = 'Crocus'
assert crocus_variable_class in [CrocusSweVariable, CrocusDepthVariable]
self.variable_class = crocus_variable_class
class CrocusSwe(Crocus):
def __init__(self, altitude=1800):
super().__init__(CrocusSweVariable, altitude)
class CrocusDepth(Crocus):
def __init__(self, altitude=1800):
super().__init__(CrocusDepthVariable, altitude)
if __name__ == '__main__': if __name__ == '__main__':
for variable_class in [CrocusSweVariable, CrocusDepthVariable]: for variable_class in [CrocusSweVariable, CrocusDepthVariable]:
study = Crocus(crocus_variable_class=variable_class) study = Crocus(variable_class=variable_class)
# d = study.year_to_dataset_ordered_dict[1960] # d = study.year_to_dataset_ordered_dict[1960]
# print(d) # print(d)
a = study.year_to_daily_time_serie[1960] a = study.year_to_daily_time_serie[1960]
print(a.shape) print(a.shape)
\ No newline at end of file
from experiment.meteo_france_SCM_study.abstract_study import AbstractStudy
from experiment.meteo_france_SCM_study.crocus.crocus import CrocusDepth, CrocusSwe
from experiment.meteo_france_SCM_study.safran.safran import Safran from experiment.meteo_france_SCM_study.safran.safran import Safran
from itertools import product from itertools import product
from experiment.meteo_france_SCM_study.safran.safran_visualizer import SafranVisualizer from experiment.meteo_france_SCM_study.safran.safran_visualizer import StudyVisualizer
def load_all_safran(only_first_one=False): def load_all_studies(study_class, only_first_one=False):
all_safran = [] all_studies = []
for safran_alti, nb_day in product([1800, 2400], [1, 3, 7]): is_safran_study = study_class == Safran
print('alti: {}, nb_day: {}'.format(safran_alti, nb_day)) nb_days = [1, 5] if is_safran_study else [1]
all_safran.append(Safran(safran_alti, nb_day)) for alti, nb_day in product(AbstractStudy.ALTITUDES, nb_days):
print('alti: {}, nb_day: {}'.format(alti, nb_day))
study = Safran(alti, nb_day) if is_safran_study else study_class(alti)
all_studies.append(study)
if only_first_one: if only_first_one:
break break
return all_safran return all_studies
if __name__ == '__main__': if __name__ == '__main__':
for safran in load_all_safran(only_first_one=True): for study_class in [Safran, CrocusSwe, CrocusDepth][:]:
safran_visualizer = SafranVisualizer(safran) for study in load_all_studies(study_class, only_first_one=True):
# safran_visualizer.visualize_independent_margin_fits(threshold=[None, 20, 40, 60][0]) study_visualizer = StudyVisualizer(study)
safran_visualizer.visualize_smooth_margin_fit() # safran_visualizer.visualize_independent_margin_fits(threshold=[None, 20, 40, 60][0])
# safran_visualizer.visualize_full_fit() study_visualizer.visualize_smooth_margin_fit()
# safran_visualizer.visualize_full_fit()
from utils import first from utils import first
MASSIF_NAMES = ['Pelvoux', 'Queyras', 'Mont-Blanc', 'Aravis', 'Haute-Tarentaise', 'Vercors', 'Alpes-Azur', 'Oisans',
'Mercantour', 'Chartreuse', 'Haute-Maurienne', 'Belledonne', 'Thabor', 'Parpaillon', 'Bauges',
'Chablais', 'Ubaye', 'Grandes-Rousses', 'Devoluy', 'Champsaur', 'Vanoise', 'Beaufortain', 'Maurienne']
class Massif(object): class Massif(object):
...@@ -16,7 +20,11 @@ class Massif(object): ...@@ -16,7 +20,11 @@ class Massif(object):
def safran_massif_names_from_datasets(datasets): def safran_massif_names_from_datasets(datasets):
# Assert the all the datasets have the same indexing for the massif # Massifs names are extracted from SAFRAN dataset
assert len(set([dataset.massifsList for dataset in datasets])) == 1 if hasattr(datasets[0], 'massifsList'):
# List of the name of the massif used by all the SAFRAN datasets # Assert the all the datasets have the same indexing for the massif
return [Massif.from_str(massif_str).name for massif_str in first(datasets).massifsList.split('/')] assert len(set([dataset.massifsList for dataset in datasets])) == 1
\ No newline at end of file # List of the name of the massif used by all the SAFRAN datasets
safran_names = [Massif.from_str(massif_str).name for massif_str in first(datasets).massifsList.split('/')]
assert MASSIF_NAMES == safran_names
return MASSIF_NAMES
...@@ -13,7 +13,7 @@ def fit_mle_gev_for_all_safran_and_different_days(): ...@@ -13,7 +13,7 @@ def fit_mle_gev_for_all_safran_and_different_days():
# safran = Safran(safran_alti, nb_day) # safran = Safran(safran_alti, nb_day)
safran = ExtendedSafran(safran_alti, nb_day) safran = ExtendedSafran(safran_alti, nb_day)
df = safran.df_gev_mle_each_massif df = safran.df_gev_mle_each_massif
df.index += ' Safran{} with {} days'.format(safran.safran_altitude, safran.nb_days_of_snowfall) df.index += ' Safran{} with {} days'.format(safran.altitude, safran.nb_days_of_snowfall)
dfs.append(df) dfs.append(df)
df = pd.concat(dfs) df = pd.concat(dfs)
path = r'/home/erwan/Documents/projects/spatiotemporalextremes/local/spatio_temporal_datasets/results/fit_mle_massif/fit_mle_gev_{}.csv' path = r'/home/erwan/Documents/projects/spatiotemporalextremes/local/spatio_temporal_datasets/results/fit_mle_massif/fit_mle_gev_{}.csv'
......
from typing import List
import os.path as op
from collections import OrderedDict
import matplotlib.pyplot as plt
import pandas as pd
from experiment.meteo_france_SCM_study.abstract_study import AbstractStudy from experiment.meteo_france_SCM_study.abstract_study import AbstractStudy
from experiment.meteo_france_SCM_study.abstract_variable import AbstractVariable from experiment.meteo_france_SCM_study.abstract_variable import AbstractVariable
from experiment.meteo_france_SCM_study.massif import safran_massif_names_from_datasets
from experiment.meteo_france_SCM_study.safran.safran_snowfall_variable import SafranSnowfallVariable from experiment.meteo_france_SCM_study.safran.safran_snowfall_variable import SafranSnowfallVariable
from spatio_temporal_dataset.coordinates.abstract_coordinates import AbstractCoordinates
from spatio_temporal_dataset.coordinates.spatial_coordinates.abstract_spatial_coordinates import \
AbstractSpatialCoordinates
from spatio_temporal_dataset.spatio_temporal_observations.annual_maxima_observations import AnnualMaxima
from utils import cached_property
class Safran(AbstractStudy): class Safran(AbstractStudy):
def __init__(self, safran_altitude=1800, nb_days_of_snowfall=1): def __init__(self, altitude=1800, nb_days_of_snowfall=1):
super().__init__(safran_altitude) super().__init__(SafranSnowfallVariable, altitude)
self.nb_days_of_snowfall = nb_days_of_snowfall self.nb_days_of_snowfall = nb_days_of_snowfall
self.model_name = 'Safran' self.model_name = 'Safran'
self.variable_class = SafranSnowfallVariable
def instantiate_variable_object(self, dataset) -> AbstractVariable: def instantiate_variable_object(self, dataset) -> AbstractVariable:
return self.variable_class(dataset, self.nb_days_of_snowfall) return self.variable_class(dataset, self.nb_days_of_snowfall)
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import pandas as pd import pandas as pd
from experiment.meteo_france_SCM_study.abstract_study import AbstractStudy
from extreme_estimator.estimator.full_estimator.abstract_full_estimator import \ from extreme_estimator.estimator.full_estimator.abstract_full_estimator import \
FullEstimatorInASingleStepWithSmoothMargin FullEstimatorInASingleStepWithSmoothMargin
from extreme_estimator.estimator.margin_estimator.abstract_margin_estimator import SmoothMarginEstimator from extreme_estimator.estimator.margin_estimator.abstract_margin_estimator import SmoothMarginEstimator
...@@ -15,19 +16,19 @@ from extreme_estimator.margin_fits.plot.create_shifted_cmap import get_color_rbg ...@@ -15,19 +16,19 @@ from extreme_estimator.margin_fits.plot.create_shifted_cmap import get_color_rbg
from spatio_temporal_dataset.dataset.abstract_dataset import AbstractDataset from spatio_temporal_dataset.dataset.abstract_dataset import AbstractDataset
class SafranVisualizer(object): class StudyVisualizer(object):
def __init__(self, safran: Safran, show=True): def __init__(self, study: AbstractStudy, show=True):
self.safran = safran self.study = study
self.show = show self.show = show
@property @property
def observations(self): def observations(self):
return self.safran.observations_annual_maxima return self.study.observations_annual_maxima
@property @property
def coordinates(self): def coordinates(self):
return self.safran.massifs_coordinates return self.study.massifs_coordinates
@property @property
def dataset(self): def dataset(self):
...@@ -37,11 +38,10 @@ class SafranVisualizer(object): ...@@ -37,11 +38,10 @@ class SafranVisualizer(object):
estimator.fit() estimator.fit()
axes = estimator.margin_function_fitted.visualize(show=False) axes = estimator.margin_function_fitted.visualize(show=False)
for ax in axes: for ax in axes:
self.safran.visualize(ax, fill=False, show=False) self.study.visualize(ax, fill=False, show=False)
plt.show() plt.show()
def visualize_smooth_margin_fit(self): def visualize_smooth_margin_fit(self):
# todo: fix some blue points in the corner when we display the margin
margin_model = LinearAllParametersAllDimsMarginModel(coordinates=self.coordinates) margin_model = LinearAllParametersAllDimsMarginModel(coordinates=self.coordinates)
estimator = SmoothMarginEstimator(dataset=self.dataset, margin_model=margin_model) estimator = SmoothMarginEstimator(dataset=self.dataset, margin_model=margin_model)
self.fit_and_visualize_estimator(estimator) self.fit_and_visualize_estimator(estimator)
...@@ -73,8 +73,8 @@ class SafranVisualizer(object): ...@@ -73,8 +73,8 @@ class SafranVisualizer(object):
values = list(massif_name_to_value.values()) values = list(massif_name_to_value.values())
colors = get_color_rbga_shifted(ax, gev_param_name, values) colors = get_color_rbga_shifted(ax, gev_param_name, values)
massif_name_to_fill_kwargs = {massif_name: {'color': color} for massif_name, color in massif_name_to_fill_kwargs = {massif_name: {'color': color} for massif_name, color in
zip(self.safran.safran_massif_names, colors)} zip(self.study.safran_massif_names, colors)}
self.safran.visualize(ax=ax, massif_name_to_fill_kwargs=massif_name_to_fill_kwargs, show=False) self.study.visualize(ax=ax, massif_name_to_fill_kwargs=massif_name_to_fill_kwargs, show=False)
if self.show: if self.show:
plt.show() plt.show()
...@@ -86,20 +86,20 @@ class SafranVisualizer(object): ...@@ -86,20 +86,20 @@ class SafranVisualizer(object):
massif_name_to_fill_kwargs = {massif_name: {'color': orig_cmap(value)} for massif_name, value in massif_name_to_fill_kwargs = {massif_name: {'color': orig_cmap(value)} for massif_name, value in
massif_name_to_value.items()} massif_name_to_value.items()}
self.safran.visualize(massif_name_to_fill_kwargs=massif_name_to_fill_kwargs) self.study.visualize(massif_name_to_fill_kwargs=massif_name_to_fill_kwargs)
""" Statistics methods """ """ Statistics methods """
@property @property
def df_gev_mle_each_massif(self): def df_gev_mle_each_massif(self):
# Fit a margin_fits on each massif # Fit a margin_fits on each massif
massif_to_gev_mle = {massif_name: GevMleFit(self.safran.observations_annual_maxima.loc[massif_name]).gev_params.summary_serie massif_to_gev_mle = {massif_name: GevMleFit(self.study.observations_annual_maxima.loc[massif_name]).gev_params.summary_serie
for massif_name in self.safran.safran_massif_names} for massif_name in self.study.safran_massif_names}
return pd.DataFrame(massif_to_gev_mle, columns=self.safran.safran_massif_names) return pd.DataFrame(massif_to_gev_mle, columns=self.study.safran_massif_names)
def df_gpd_mle_each_massif(self, threshold): def df_gpd_mle_each_massif(self, threshold):
# Fit a margin fit on each massif # Fit a margin fit on each massif
massif_to_gev_mle = {massif_name: GpdMleFit(self.safran.df_all_snowfall_concatenated[massif_name], massif_to_gev_mle = {massif_name: GpdMleFit(self.study.df_all_snowfall_concatenated[massif_name],
threshold=threshold).gpd_params.summary_serie threshold=threshold).gpd_params.summary_serie
for massif_name in self.safran.safran_massif_names} for massif_name in self.study.safran_massif_names}
return pd.DataFrame(massif_to_gev_mle, columns=self.safran.safran_massif_names) return pd.DataFrame(massif_to_gev_mle, columns=self.study.safran_massif_names)
...@@ -18,12 +18,14 @@ from spatio_temporal_dataset.slicer.split import Split ...@@ -18,12 +18,14 @@ from spatio_temporal_dataset.slicer.split import Split
def plot_extreme_param(ax, gev_param_name, values): def plot_extreme_param(ax, gev_param_name, values):
# Load the shifted cmap to center on a middle point # Load the shifted cmap to center on a middle point
vmin, vmax = np.min(values), np.max(values) vmin, vmax = np.min(values), np.max(values)
cmap = [plt.cm.coolwarm, plt.cm.bwr, plt.cm.seismic][1] if vmin < 0 < vmax:
if gev_param_name == ExtremeParams.SHAPE and vmin < 0:
midpoint = 1 - vmax / (vmax + abs(vmin)) midpoint = 1 - vmax / (vmax + abs(vmin))
shifted_cmap = shiftedColorMap(cmap, midpoint=midpoint, name='shifted') elif vmin < 0 and vmax < 0:
else: midpoint = 1.0
shifted_cmap = shiftedColorMap(cmap, midpoint=0.0, name='shifted') elif vmin > 0 and vmax > 0:
midpoint = 0.0
cmap = [plt.cm.coolwarm, plt.cm.bwr, plt.cm.seismic][1]
shifted_cmap = shiftedColorMap(cmap, midpoint=midpoint, name='shifted')
norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax) norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax)
divider = make_axes_locatable(ax) divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=0.05) cax = divider.append_axes('right', size='5%', pad=0.05)
...@@ -50,10 +52,9 @@ def imshow_shifted(ax, gev_param_name, values, x, y): ...@@ -50,10 +52,9 @@ def imshow_shifted(ax, gev_param_name, values, x, y):
masked_array = values masked_array = values
if gev_param_name != ExtremeParams.SHAPE: if gev_param_name != ExtremeParams.SHAPE:
epsilon = 1.0 epsilon = 1e-2 * (np.max(values) - np.min(values))
value = np.min(values) value = np.min(values)
# The right blue corner will be blue (but most of the time, another display will be on top) # The right blue corner will be blue (but most of the time, another display will be on top)
masked_array[-1, -1] = value - epsilon masked_array[-1, -1] = value - epsilon
ax.imshow(masked_array, extent=(x.min(), x.max(), y.min(), y.max()), cmap=shifted_cmap) ax.imshow(masked_array, extent=(x.min(), x.max(), y.min(), y.max()), cmap=shifted_cmap)
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