From 66230161a9d0cc343c0d1900a29ff4a7910e4893 Mon Sep 17 00:00:00 2001 From: Le Roux Erwan <erwan.le-roux@irstea.fr> Date: Wed, 14 Nov 2018 16:17:48 +0100 Subject: [PATCH] [R Model] add abstract_margin_function. refactor accordingly --- extreme_estimator/R_model/abstract_model.py | 21 +++- extreme_estimator/R_model/gev/__init__.py | 0 .../{margin_model => gev}/gev_mle_fit.R | 0 .../{margin_model => gev}/gev_mle_fit.py | 14 +-- .../R_model/gev/gev_parameters.py | 29 +++++ .../margin_model/abstract_margin_function.py | 44 ++++++++ .../margin_model/abstract_margin_model.py | 104 ++++++++---------- .../margin_model/smooth_margin_model.py | 30 +++++ .../abstract_max_stable_model.py | 30 +---- extreme_estimator/estimator/full_estimator.py | 3 +- .../estimator/margin_estimator.py | 12 +- .../annual_maxima_observations.py | 7 +- .../test_R_model/__init__.py | 0 .../test_R_model/test_gev_mle_fit.py | 33 ++++++ .../test_R_model/test_margin_model.py | 21 ++++ .../test_estimator/__init__.py | 0 .../test_full_estimators.py | 10 +- .../test_estimator/test_margin_estimators.py | 40 +++++++ .../test_max_stable_estimators.py | 0 .../test_margin_estimators.py | 63 ----------- 20 files changed, 295 insertions(+), 166 deletions(-) create mode 100644 extreme_estimator/R_model/gev/__init__.py rename extreme_estimator/R_model/{margin_model => gev}/gev_mle_fit.R (100%) rename extreme_estimator/R_model/{margin_model => gev}/gev_mle_fit.py (64%) create mode 100644 extreme_estimator/R_model/gev/gev_parameters.py create mode 100644 extreme_estimator/R_model/margin_model/abstract_margin_function.py create mode 100644 extreme_estimator/R_model/margin_model/smooth_margin_model.py create mode 100644 test/test_extreme_estimator/test_R_model/__init__.py create mode 100644 test/test_extreme_estimator/test_R_model/test_gev_mle_fit.py create mode 100644 test/test_extreme_estimator/test_R_model/test_margin_model.py create mode 100644 test/test_extreme_estimator/test_estimator/__init__.py rename test/test_extreme_estimator/{ => test_estimator}/test_full_estimators.py (79%) create mode 100644 test/test_extreme_estimator/test_estimator/test_margin_estimators.py rename test/test_extreme_estimator/{ => test_estimator}/test_max_stable_estimators.py (100%) delete mode 100644 test/test_extreme_estimator/test_margin_estimators.py diff --git a/extreme_estimator/R_model/abstract_model.py b/extreme_estimator/R_model/abstract_model.py index 304ca708..ea8b2f20 100644 --- a/extreme_estimator/R_model/abstract_model.py +++ b/extreme_estimator/R_model/abstract_model.py @@ -2,11 +2,28 @@ from extreme_estimator.R_model.utils import get_loaded_r class AbstractModel(object): - r = get_loaded_r() def __init__(self, params_start_fit=None, params_sample=None): self.default_params_start_fit = None self.default_params_sample = None self.user_params_start_fit = params_start_fit - self.user_params_sample = params_sample \ No newline at end of file + self.user_params_sample = params_sample + + @property + def params_start_fit(self) -> dict: + return self.merge_params(default_params=self.default_params_start_fit, input_params=self.user_params_start_fit) + + @property + def params_sample(self) -> dict: + return self.merge_params(default_params=self.default_params_sample, input_params=self.user_params_sample) + + @staticmethod + def merge_params(default_params, input_params): + assert default_params is not None, 'some default_params need to be specified' + merged_params = default_params.copy() + if input_params is not None: + assert isinstance(default_params, dict) and isinstance(input_params, dict) + assert set(input_params.keys()).issubset(set(default_params.keys())) + merged_params.update(input_params) + return merged_params diff --git a/extreme_estimator/R_model/gev/__init__.py b/extreme_estimator/R_model/gev/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/extreme_estimator/R_model/margin_model/gev_mle_fit.R b/extreme_estimator/R_model/gev/gev_mle_fit.R similarity index 100% rename from extreme_estimator/R_model/margin_model/gev_mle_fit.R rename to extreme_estimator/R_model/gev/gev_mle_fit.R diff --git a/extreme_estimator/R_model/margin_model/gev_mle_fit.py b/extreme_estimator/R_model/gev/gev_mle_fit.py similarity index 64% rename from extreme_estimator/R_model/margin_model/gev_mle_fit.py rename to extreme_estimator/R_model/gev/gev_mle_fit.py index 8778f990..f879f2bf 100644 --- a/extreme_estimator/R_model/margin_model/gev_mle_fit.py +++ b/extreme_estimator/R_model/gev/gev_mle_fit.py @@ -4,10 +4,11 @@ import rpy2.robjects.numpy2ri as rpyn import os.path as op # Defining some constants +from extreme_estimator.R_model.gev.gev_parameters import GevParams from extreme_estimator.R_model.utils import get_associated_r_file -def mle_gev(x_gev: np.ndarray, start_loc=0, start_scale=1, start_shape=0): +def gev_mle_fit(x_gev: np.ndarray, start_loc=0, start_scale=1, start_shape=0): assert np.ndim(x_gev) == 1 assert start_scale > 0 r = ro.r @@ -21,13 +22,10 @@ def mle_gev(x_gev: np.ndarray, start_loc=0, start_scale=1, start_shape=0): class GevMleFit(object): - GEV_SCALE = 'scale' - GEV_LOCATION = 'loc' - GEV_SHAPE = 'shape' def __init__(self, x_gev: np.ndarray, start_loc=0, start_scale=1, start_shape=0): self.x_gev = x_gev - self.mle_params = mle_gev(x_gev, start_loc, start_scale, start_shape) - self.shape = self.mle_params[self.GEV_SHAPE] - self.scale = self.mle_params[self.GEV_SCALE] - self.location = self.mle_params[self.GEV_LOCATION] + self.mle_params = gev_mle_fit(x_gev, start_loc, start_scale, start_shape) + self.shape = self.mle_params[GevParams.GEV_SHAPE] + self.scale = self.mle_params[GevParams.GEV_SCALE] + self.loc = self.mle_params[GevParams.GEV_LOC] diff --git a/extreme_estimator/R_model/gev/gev_parameters.py b/extreme_estimator/R_model/gev/gev_parameters.py new file mode 100644 index 00000000..387f8ab7 --- /dev/null +++ b/extreme_estimator/R_model/gev/gev_parameters.py @@ -0,0 +1,29 @@ + +class GevParams(object): + GEV_SCALE = 'scale' + GEV_LOC = 'loc' + GEV_SHAPE = 'shape' + + def __init__(self, loc: float, scale: float, shape: float): + self.location = loc + self.scale = scale + self.shape = shape + + @classmethod + def from_dict(cls, params: dict): + return cls(**params) + + def to_dict(self) -> dict: + return { + self.GEV_LOC: self.location, + self.GEV_SCALE: self.scale, + self.GEV_SHAPE: self.shape, + } + + def rgev(self, nb_obs): + gev_params = { + self.GEV_LOC: loc, + self.GEV_SCALE: scale, + self.GEV_SHAPE: shape, + } + return self.r.rgev(nb_obs, **gev_params) diff --git a/extreme_estimator/R_model/margin_model/abstract_margin_function.py b/extreme_estimator/R_model/margin_model/abstract_margin_function.py new file mode 100644 index 00000000..d1eb05dd --- /dev/null +++ b/extreme_estimator/R_model/margin_model/abstract_margin_function.py @@ -0,0 +1,44 @@ +from typing import List + +import numpy as np + +from extreme_estimator.R_model.gev.gev_parameters import GevParams +from spatio_temporal_dataset.spatial_coordinates.abstract_spatial_coordinates import AbstractSpatialCoordinates + + +class AbstractMarginFunction(object): + """ + It represents any function mapping points from a space S (could be 2D, 3D,...) to R^3 (the 3 parameters of the GEV) + """ + + def __init__(self, spatial_coordinates: AbstractSpatialCoordinates, default_params: GevParams): + self.spatial_coordinates = spatial_coordinates + self.default_params = default_params + + def get_gev_params(self, coordinate: np.ndarray) -> GevParams: + pass + + +class ConstantMarginFunction(AbstractMarginFunction): + + def get_gev_params(self, coordinate: np.ndarray) -> GevParams: + return self.default_params + + +class LinearMarginFunction(AbstractMarginFunction): + + def __init__(self, spatial_coordinates: AbstractSpatialCoordinates, default_params: GevParams, + linear_dims: List[int]): + super().__init__(spatial_coordinates, default_params) + self.linear_dims = linear_dims + +# class LinearShapeMarginFunction(AbstractMarginFunction): +# """Linear function """ +# +# def __init__(self, coordinates, dimension_index_for_linearity=0): +# super().__init__(coordinates) +# self.dimension_index_for_linearity = dimension_index_for_linearity +# assert dimension_index_for_linearity < np.ndim(self.coordinates) +# # Compute +# +# def get_gev_params(self, coordinate): diff --git a/extreme_estimator/R_model/margin_model/abstract_margin_model.py b/extreme_estimator/R_model/margin_model/abstract_margin_model.py index 25e59524..747ac64f 100644 --- a/extreme_estimator/R_model/margin_model/abstract_margin_model.py +++ b/extreme_estimator/R_model/margin_model/abstract_margin_model.py @@ -1,82 +1,72 @@ import numpy as np -import pandas as pd from extreme_estimator.R_model.abstract_model import AbstractModel -from extreme_estimator.R_model.margin_model.gev_mle_fit import GevMleFit, mle_gev +from extreme_estimator.R_model.margin_model.abstract_margin_function import AbstractMarginFunction +from extreme_estimator.R_model.gev.gev_parameters import GevParams +from spatio_temporal_dataset.spatial_coordinates.abstract_spatial_coordinates import AbstractSpatialCoordinates class AbstractMarginModel(AbstractModel): - GEV_SCALE = GevMleFit.GEV_SCALE - GEV_LOCATION = GevMleFit.GEV_LOCATION - GEV_SHAPE = GevMleFit.GEV_SHAPE - GEV_PARAMETERS = [GEV_LOCATION, GEV_SCALE, GEV_SHAPE] + GEV_SCALE = GevParams.GEV_SCALE + GEV_LOC = GevParams.GEV_LOC + GEV_SHAPE = GevParams.GEV_SHAPE + GEV_PARAMETERS = [GEV_LOC, GEV_SCALE, GEV_SHAPE] - def __init__(self, params_start_fit=None, params_sample=None): + def __init__(self, spatial_coordinates: AbstractSpatialCoordinates, params_start_fit=None, params_sample=None): super().__init__(params_start_fit, params_sample) + self.spatial_coordinates = spatial_coordinates + self.margin_function_sample = None # type: AbstractMarginFunction + self.margin_function_start_fit = None # type: AbstractMarginFunction + self.load_margin_functions() - # Define the method to sample/fit a single gev + def load_margin_functions(self, margin_function_class: type = None): + assert margin_function_class is not None + self.margin_function_sample = margin_function_class(spatial_coordinates=self.spatial_coordinates, + default_params=GevParams.from_dict(self.params_sample)) + self.margin_function_start_fit = margin_function_class(spatial_coordinates=self.spatial_coordinates, + default_params=GevParams.from_dict( + self.params_start_fit)) - def rgev(self, nb_obs, loc, scale, shape): - gev_params = { - self.GEV_LOCATION: loc, - self.GEV_SCALE: scale, - self.GEV_SHAPE: shape, - } - return self.r.rgev(nb_obs, **gev_params) + # Conversion class methods - def fitgev(self, x_gev, estimator=GevMleFit): - mle_params = mle_gev(x_gev=x_gev) + @classmethod + def convert_maxima(cls, convertion_r_function, maxima: np.ndarray, coordinates: np.ndarray, + margin_function: AbstractMarginFunction): + assert len(maxima) == len(coordinates) + converted_maxima = [] + for x, coordinate in zip(maxima, coordinates): + gev_params = margin_function.get_gev_params(coordinate) + x_gev = convertion_r_function(x, **gev_params.to_dict()) + converted_maxima.append(x_gev) + return np.array(converted_maxima) - def gev_params_sample(self, coordinate) -> dict: - pass + @classmethod + def gev2frech(cls, maxima_gev: np.ndarray, coordinates: np.ndarray, margin_function: AbstractMarginFunction): + return cls.convert_maxima(cls.r.gev2frech, maxima_gev, coordinates, margin_function) - # Define the method to sample/fit all marginals globally in the child classes + @classmethod + def frech2gev(cls, maxima_frech: np.ndarray, coordinates: np.ndarray, margin_function: AbstractMarginFunction): + return cls.convert_maxima(cls.r.frech2gev, maxima_frech, coordinates, margin_function) - def fitmargin(self, maxima, coord): - df_fit_gev_params = None - return df_fit_gev_params + # Sampling methods - def rmargin(self, nb_obs, coord): - maxima_gev = None + def rmargin_from_maxima_frech(self, maxima_frech: np.ndarray, coordinates: np.ndarray): + maxima_gev = self.frech2gev(maxima_frech, coordinates, self.margin_function_sample) return maxima_gev - def frech2gev(self, maxima_frech: np.ndarray, coordinates: np.ndarray): - assert len(maxima_frech) == len(coordinates) + def rmargin_from_nb_obs(self, nb_obs, coordinates): maxima_gev = [] - for x_frech, coordinate in zip(maxima_frech, coordinates): - gev_params = self.gev_params_sample(coordinate) - x_gev = self.r.frech2gev(x_frech, **gev_params) + for coordinate in coordinates: + gev_params = self.margin_function_sample.get_gev_params(coordinate) + x_gev = self.r.rgev(nb_obs, **gev_params.to_dict()) maxima_gev.append(x_gev) return np.array(maxima_gev) - @classmethod - def gev2frech(cls, maxima_gev: np.ndarray, df_gev_params: pd.DataFrame): - assert len(maxima_gev) == len(df_gev_params) - maxima_frech = [] - for x_gev, (_, s_gev_params) in zip(maxima_gev, df_gev_params.iterrows()): - gev_params = dict(s_gev_params) - gev2frech_param = {'emp': False} - x_frech = cls.r.gev2frech(x_gev, **gev_params, **gev2frech_param) - maxima_frech.append(x_frech) - return np.array(maxima_frech) - - -class SmoothMarginModel(AbstractMarginModel): - pass - - -class ConstantMarginModel(SmoothMarginModel): - def __init__(self, params_start_fit=None, params_sample=None): - super().__init__(params_start_fit, params_sample) - self.default_params_sample = {gev_param: 1.0 for gev_param in self.GEV_PARAMETERS} - self.default_params_start_fit = {gev_param: 1.0 for gev_param in self.GEV_PARAMETERS} - - def gev_params_sample(self, coordinate): - return self.default_params_sample - - def fitmargin(self, maxima, coord): - return pd.DataFrame([pd.Series(self.default_params_start_fit) for _ in maxima]) + # Fitting methods + def fitmargin_from_maxima_gev(self, maxima_gev: np.ndarray, coordinates: np.ndarray) -> AbstractMarginFunction: + pass + # Define the method to sample/fit a single gev diff --git a/extreme_estimator/R_model/margin_model/smooth_margin_model.py b/extreme_estimator/R_model/margin_model/smooth_margin_model.py new file mode 100644 index 00000000..c1210d6c --- /dev/null +++ b/extreme_estimator/R_model/margin_model/smooth_margin_model.py @@ -0,0 +1,30 @@ +import numpy as np + +from extreme_estimator.R_model.margin_model.abstract_margin_function import ConstantMarginFunction, \ + AbstractMarginFunction +from extreme_estimator.R_model.margin_model.abstract_margin_model import AbstractMarginModel +from extreme_estimator.R_model.gev.gev_parameters import GevParams +from spatio_temporal_dataset.spatial_coordinates.abstract_spatial_coordinates import AbstractSpatialCoordinates + + +class SmoothMarginModel(AbstractMarginModel): + pass + + +class ConstantMarginModel(SmoothMarginModel): + + def load_margin_functions(self, margin_function_class: type = None): + self.default_params_sample = GevParams(1.0, 1.0, 1.0).to_dict() + self.default_params_start_fit = GevParams(1.0, 1.0, 1.0).to_dict() + super().load_margin_functions(margin_function_class=ConstantMarginFunction) + + def fitmargin_from_maxima_gev(self, maxima_gev: np.ndarray, coordinates: np.ndarray) -> AbstractMarginFunction: + return self.margin_function_start_fit + + +class LinearShapeMarginModel(SmoothMarginModel): + pass + + +if __name__ == '__main__': + pass diff --git a/extreme_estimator/R_model/max_stable_model/abstract_max_stable_model.py b/extreme_estimator/R_model/max_stable_model/abstract_max_stable_model.py index ab0c717c..1075d383 100644 --- a/extreme_estimator/R_model/max_stable_model/abstract_max_stable_model.py +++ b/extreme_estimator/R_model/max_stable_model/abstract_max_stable_model.py @@ -13,6 +13,10 @@ class AbstractMaxStableModel(AbstractModel): super().__init__(params_start_fit, params_sample) self.cov_mod = None + @property + def cov_mod_param(self): + return {'cov.mod': self.cov_mod} + def fitmaxstab(self, maxima_frech: np.ndarray, coord: np.ndarray, fit_marge=False): assert all([isinstance(arr, np.ndarray) for arr in [maxima_frech, coord]]) # Specify the fit params @@ -33,36 +37,14 @@ class AbstractMaxStableModel(AbstractModel): fitted_values = {key: fitted_values.rx2(key)[0] for key in fitted_values.names} return fitted_values - def rmaxstab(self, nb_obs: int, coord: np.ndarray) -> np.ndarray: + def rmaxstab(self, nb_obs: int, coordinates: np.ndarray) -> np.ndarray: """ Return an numpy of maxima. With rows being the stations and columns being the years of maxima """ maxima_frech = np.array( - self.r.rmaxstab(nb_obs, coord, *list(self.cov_mod_param.values()), **self.params_sample)) + self.r.rmaxstab(nb_obs, coordinates, *list(self.cov_mod_param.values()), **self.params_sample)) return np.transpose(maxima_frech) - @property - def cov_mod_param(self): - return {'cov.mod': self.cov_mod} - - @property - def params_start_fit(self): - return self.merge_params(default_params=self.default_params_start_fit, input_params=self.user_params_start_fit) - - @property - def params_sample(self): - return self.merge_params(default_params=self.default_params_sample, input_params=self.user_params_sample) - - @staticmethod - def merge_params(default_params, input_params): - assert default_params is not None, 'some default_params need to be specified' - merged_params = default_params.copy() - if input_params is not None: - assert isinstance(default_params, dict) and isinstance(input_params, dict) - assert set(input_params.keys()).issubset(set(default_params.keys())) - merged_params.update(input_params) - return merged_params - class CovarianceFunction(Enum): whitmat = 0 diff --git a/extreme_estimator/estimator/full_estimator.py b/extreme_estimator/estimator/full_estimator.py index 3d31d97f..f674fb3f 100644 --- a/extreme_estimator/estimator/full_estimator.py +++ b/extreme_estimator/estimator/full_estimator.py @@ -24,7 +24,8 @@ class SmoothMarginalsThenUnitaryMsp(AbstractFullEstimator): self.margin_estimator.fit() # Compute the maxima_frech maxima_frech = AbstractMarginModel.gev2frech(maxima_gev=self.dataset.maxima_gev, - df_gev_params=self.margin_estimator.df_gev_params) + coordinates=self.dataset.coordinates, + margin_function=self.margin_estimator.margin_function_fitted) # Update maxima frech field through the dataset object self.dataset.maxima_frech = maxima_frech # Estimate the max stable parameters diff --git a/extreme_estimator/estimator/margin_estimator.py b/extreme_estimator/estimator/margin_estimator.py index 0bcf9006..fd9c3e95 100644 --- a/extreme_estimator/estimator/margin_estimator.py +++ b/extreme_estimator/estimator/margin_estimator.py @@ -8,6 +8,12 @@ class AbstractMarginEstimator(AbstractEstimator): def __init__(self, dataset: AbstractDataset): super().__init__(dataset) assert self.dataset.maxima_gev is not None + self._margin_function_fitted = None + + @property + def margin_function_fitted(self): + assert self._margin_function_fitted is not None, 'Error: estimator has not been not fitted yet' + return self._margin_function_fitted class PointWiseMarginEstimator(AbstractMarginEstimator): @@ -19,9 +25,9 @@ class SmoothMarginEstimator(AbstractMarginEstimator): def __init__(self, dataset: AbstractDataset, margin_model: AbstractMarginModel): super().__init__(dataset) + assert isinstance(margin_model, AbstractMarginModel) self.margin_model = margin_model - self.df_gev_params = None def _fit(self): - self.df_gev_params = self.margin_model.fitmargin(maxima=self.dataset.maxima_gev, - coord=self.dataset.coordinates) + self._margin_function_fitted = self.margin_model.fitmargin_from_maxima_gev(maxima_gev=self.dataset.maxima_gev, + coordinates=self.dataset.coordinates) diff --git a/spatio_temporal_dataset/temporal_observations/annual_maxima_observations.py b/spatio_temporal_dataset/temporal_observations/annual_maxima_observations.py index 9c4f1387..a24f6cdf 100644 --- a/spatio_temporal_dataset/temporal_observations/annual_maxima_observations.py +++ b/spatio_temporal_dataset/temporal_observations/annual_maxima_observations.py @@ -19,7 +19,7 @@ class MarginAnnualMaxima(AnnualMaxima): @classmethod def from_sampling(cls, nb_obs: int, spatial_coordinates: AbstractSpatialCoordinates, margin_model: AbstractMarginModel): - maxima_gev = margin_model.rmargin(nb_obs=nb_obs, coord=spatial_coordinates.coordinates) + maxima_gev = margin_model.rmargin_from_nb_obs(nb_obs=nb_obs, coordinates=spatial_coordinates.coordinates) df_maxima_gev = pd.DataFrame(data=maxima_gev, index=spatial_coordinates.index) return cls(df_maxima_gev=df_maxima_gev) @@ -29,7 +29,7 @@ class MaxStableAnnualMaxima(AbstractTemporalObservations): @classmethod def from_sampling(cls, nb_obs: int, max_stable_model: AbstractMaxStableModel, spatial_coordinates: AbstractSpatialCoordinates): - maxima_frech = max_stable_model.rmaxstab(nb_obs=nb_obs, coord=spatial_coordinates.coordinates) + maxima_frech = max_stable_model.rmaxstab(nb_obs=nb_obs, coordinates=spatial_coordinates.coordinates) df_maxima_frech = pd.DataFrame(data=maxima_frech, index=spatial_coordinates.index) return cls(df_maxima_frech=df_maxima_frech) @@ -42,6 +42,7 @@ class FullAnnualMaxima(MaxStableAnnualMaxima): margin_model: AbstractMarginModel): max_stable_annual_maxima = super().from_sampling(nb_obs, max_stable_model, spatial_coordinates) # Compute df_maxima_gev from df_maxima_frech - maxima_gev = margin_model.frech2gev(max_stable_annual_maxima.maxima_frech, spatial_coordinates.coordinates) + maxima_gev = margin_model.rmargin_from_maxima_frech(maxima_frech=max_stable_annual_maxima.maxima_frech, + coordinates=spatial_coordinates.coordinates) max_stable_annual_maxima.df_maxima_gev = pd.DataFrame(data=maxima_gev, index=spatial_coordinates.index) return max_stable_annual_maxima diff --git a/test/test_extreme_estimator/test_R_model/__init__.py b/test/test_extreme_estimator/test_R_model/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/test_extreme_estimator/test_R_model/test_gev_mle_fit.py b/test/test_extreme_estimator/test_R_model/test_gev_mle_fit.py new file mode 100644 index 00000000..60da9acc --- /dev/null +++ b/test/test_extreme_estimator/test_R_model/test_gev_mle_fit.py @@ -0,0 +1,33 @@ +import unittest + +import numpy as np + +from extreme_estimator.R_model.gev.gev_mle_fit import GevMleFit +from extreme_estimator.R_model.utils import get_loaded_r + + +class TestGevMleFit(unittest.TestCase): + + def test_unitary_gev_mle_fit(self): + r = get_loaded_r() + r(""" + set.seed(42) + N <- 50 + loc = 0; scale = 1; shape <- 1 + x_gev <- rgev(N, loc = loc, scale = scale, shape = shape) + start_loc = 0; start_scale = 1; start_shape = 1 + """) + # Get the MLE estimator + estimator = GevMleFit(x_gev=np.array(r['x_gev']), + start_loc=np.float(r['start_loc'][0]), + start_scale=np.float(r['start_scale'][0]), + start_shape=np.float(r['start_shape'][0])) + # Compare the MLE estimated parameters to the reference + mle_params_estimated = estimator.mle_params + mle_params_ref = {'loc': 0.0219, 'scale': 1.0347, 'shape': 0.8290} + for key in mle_params_ref.keys(): + self.assertAlmostEqual(mle_params_ref[key], mle_params_estimated[key], places=3) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_extreme_estimator/test_R_model/test_margin_model.py b/test/test_extreme_estimator/test_R_model/test_margin_model.py new file mode 100644 index 00000000..ef3ccb84 --- /dev/null +++ b/test/test_extreme_estimator/test_R_model/test_margin_model.py @@ -0,0 +1,21 @@ +import unittest + +from extreme_estimator.R_model.margin_model.smooth_margin_model import ConstantMarginModel +from spatio_temporal_dataset.spatial_coordinates.generated_coordinates import CircleCoordinatesRadius1 + + +class TestMarginModel(unittest.TestCase): + DISPLAY = True + MARGIN_TYPES = [ConstantMarginModel] + + # def test_visualization(self): + # coord_2D = CircleCoordinatesRadius1.from_nb_points(nb_points=50) + # if self.DISPLAY: + # coord_2D.visualization_2D() + # for margin_class in self.MARGIN_TYPES: + # margin_model = margin_class() + # margin_model.visualize(coordinates=coord_2D.coordinates) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_extreme_estimator/test_estimator/__init__.py b/test/test_extreme_estimator/test_estimator/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/test_extreme_estimator/test_full_estimators.py b/test/test_extreme_estimator/test_estimator/test_full_estimators.py similarity index 79% rename from test/test_extreme_estimator/test_full_estimators.py rename to test/test_extreme_estimator/test_estimator/test_full_estimators.py index 2a9aa6b3..5e03f8fd 100644 --- a/test/test_extreme_estimator/test_full_estimators.py +++ b/test/test_extreme_estimator/test_estimator/test_full_estimators.py @@ -4,8 +4,8 @@ from itertools import product from extreme_estimator.estimator.full_estimator import SmoothMarginalsThenUnitaryMsp from spatio_temporal_dataset.dataset.simulation_dataset import FullSimulatedDataset from spatio_temporal_dataset.spatial_coordinates.generated_coordinates import CircleCoordinatesRadius1 -from test.test_extreme_estimator.test_margin_estimators import TestMarginEstimators -from test.test_extreme_estimator.test_max_stable_estimators import TestMaxStableEstimators +from test.test_extreme_estimator.test_estimator.test_margin_estimators import TestMarginEstimators +from test.test_extreme_estimator.test_estimator.test_max_stable_estimators import TestMaxStableEstimators class TestFullEstimators(unittest.TestCase): @@ -14,14 +14,14 @@ class TestFullEstimators(unittest.TestCase): def setUp(self): super().setUp() - self.spatial_coord = CircleCoordinatesRadius1.from_nb_points(nb_points=5, max_radius=1) + self.spatial_coordinates = CircleCoordinatesRadius1.from_nb_points(nb_points=5, max_radius=1) self.max_stable_models = TestMaxStableEstimators.load_max_stable_models() - self.margin_models = TestMarginEstimators.load_margin_models() + self.margin_models = TestMarginEstimators.load_margin_models(spatial_coordinates=self.spatial_coordinates) def test_full_estimators(self): for margin_model, max_stable_model in product(self.margin_models, self.max_stable_models): dataset = FullSimulatedDataset.from_double_sampling(nb_obs=10, margin_model=margin_model, - spatial_coordinates=self.spatial_coord, + spatial_coordinates=self.spatial_coordinates, max_stable_model=max_stable_model) for estimator_class in self.FULL_ESTIMATORS: diff --git a/test/test_extreme_estimator/test_estimator/test_margin_estimators.py b/test/test_extreme_estimator/test_estimator/test_margin_estimators.py new file mode 100644 index 00000000..322fd309 --- /dev/null +++ b/test/test_extreme_estimator/test_estimator/test_margin_estimators.py @@ -0,0 +1,40 @@ +import unittest + +from extreme_estimator.R_model.margin_model.abstract_margin_model import AbstractMarginModel +from extreme_estimator.R_model.margin_model.smooth_margin_model import ConstantMarginModel +from extreme_estimator.estimator.margin_estimator import SmoothMarginEstimator +from spatio_temporal_dataset.dataset.simulation_dataset import MarginDataset +from spatio_temporal_dataset.spatial_coordinates.generated_coordinates import CircleCoordinatesRadius1 + + +class TestMarginEstimators(unittest.TestCase): + DISPLAY = False + MARGIN_TYPES = [ConstantMarginModel] + MARGIN_ESTIMATORS = [SmoothMarginEstimator] + + def setUp(self): + super().setUp() + self.spatial_coordinates = CircleCoordinatesRadius1.from_nb_points(nb_points=5, max_radius=1) + self.margin_models = self.load_margin_models(spatial_coordinates=self.spatial_coordinates) + + @classmethod + def load_margin_models(cls, spatial_coordinates): + return [margin_class(spatial_coordinates=spatial_coordinates) for margin_class in cls.MARGIN_TYPES] + + def test_dependency_estimators(self): + for margin_model in self.margin_models: + dataset = MarginDataset.from_sampling(nb_obs=10, margin_model=margin_model, + spatial_coordinates=self.spatial_coordinates) + + for estimator_class in self.MARGIN_ESTIMATORS: + estimator = estimator_class(dataset=dataset, margin_model=margin_model) + estimator.fit() + if self.DISPLAY: + print(type(margin_model)) + print(dataset.df_dataset.head()) + print(estimator.additional_information) + self.assertTrue(True) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_extreme_estimator/test_max_stable_estimators.py b/test/test_extreme_estimator/test_estimator/test_max_stable_estimators.py similarity index 100% rename from test/test_extreme_estimator/test_max_stable_estimators.py rename to test/test_extreme_estimator/test_estimator/test_max_stable_estimators.py diff --git a/test/test_extreme_estimator/test_margin_estimators.py b/test/test_extreme_estimator/test_margin_estimators.py deleted file mode 100644 index 2b896d91..00000000 --- a/test/test_extreme_estimator/test_margin_estimators.py +++ /dev/null @@ -1,63 +0,0 @@ -import unittest - -import numpy as np - -from extreme_estimator.R_model.margin_model.abstract_margin_model import ConstantMarginModel -from extreme_estimator.R_model.margin_model.gev_mle_fit import GevMleFit -from extreme_estimator.R_model.utils import get_loaded_r -from extreme_estimator.estimator.margin_estimator import SmoothMarginEstimator -from spatio_temporal_dataset.dataset.simulation_dataset import MarginDataset -from spatio_temporal_dataset.spatial_coordinates.generated_coordinates import CircleCoordinatesRadius1 - - -class TestMarginEstimators(unittest.TestCase): - DISPLAY = False - MARGIN_TYPES = [ConstantMarginModel] - MARGIN_ESTIMATORS = [SmoothMarginEstimator] - - def test_unitary_mle_gev_fit(self): - r = get_loaded_r() - r(""" - set.seed(42) - N <- 50 - loc = 0; scale = 1; shape <- 1 - x_gev <- rgev(N, loc = loc, scale = scale, shape = shape) - start_loc = 0; start_scale = 1; start_shape = 1 - """) - # Get the MLE estimator - estimator = GevMleFit(x_gev=np.array(r['x_gev']), - start_loc=np.float(r['start_loc'][0]), - start_scale=np.float(r['start_scale'][0]), - start_shape=np.float(r['start_shape'][0])) - # Compare the MLE estimated parameters to the reference - mle_params_estimated = estimator.mle_params - mle_params_ref = {'loc': 0.0219, 'scale': 1.0347, 'shape': 0.8290} - for key in mle_params_ref.keys(): - self.assertAlmostEqual(mle_params_ref[key], mle_params_estimated[key], places=3) - - def setUp(self): - super().setUp() - self.spatial_coord = CircleCoordinatesRadius1.from_nb_points(nb_points=5, max_radius=1) - self.margin_models = self.load_margin_models() - - @classmethod - def load_margin_models(cls): - return [margin_class() for margin_class in cls.MARGIN_TYPES] - - def test_dependency_estimators(self): - for margin_model in self.margin_models: - dataset = MarginDataset.from_sampling(nb_obs=10, margin_model=margin_model, - spatial_coordinates=self.spatial_coord) - - for estimator_class in self.MARGIN_ESTIMATORS: - estimator = estimator_class(dataset=dataset, margin_model=margin_model) - estimator.fit() - if self.DISPLAY: - print(type(margin_model)) - print(dataset.df_dataset.head()) - print(estimator.additional_information) - self.assertTrue(True) - - -if __name__ == '__main__': - unittest.main() -- GitLab