From ef98837860cf795aec2be3d1baf138700dc11ad5 Mon Sep 17 00:00:00 2001
From: Le Roux Erwan <erwan.le-roux@irstea.fr>
Date: Tue, 26 Feb 2019 11:17:53 +0100
Subject: [PATCH] [SCM] improve empirical distribution visualization for
 slides. add single_massif_graph visualization

---
 .../meteo_france_SCM_study/main_visualize.py  |  6 +--
 .../safran/safran_visualizer.py               | 45 +++++++++++--------
 .../abstract_margin_function.py               | 11 ++++-
 .../margin_fits/abstract_params.py            |  7 +--
 .../test_extreme_models/test_margin_model.py  | 44 +++++++++++++-----
 5 files changed, 77 insertions(+), 36 deletions(-)

diff --git a/experiment/meteo_france_SCM_study/main_visualize.py b/experiment/meteo_france_SCM_study/main_visualize.py
index 2cf6622d..180ea81b 100644
--- a/experiment/meteo_france_SCM_study/main_visualize.py
+++ b/experiment/meteo_france_SCM_study/main_visualize.py
@@ -33,9 +33,9 @@ def study_iterator(study_class, only_first_one=False, both_altitude=False, verbo
 
 
 def extended_visualization():
-    for study_class in SCM_EXTENDED_STUDIES[-1:]:
-        for study in study_iterator(study_class, only_first_one=True):
-            study_visualizer = StudyVisualizer(study)
+    for study_class in SCM_EXTENDED_STUDIES[:]:
+        for study in study_iterator(study_class, only_first_one=False):
+            study_visualizer = StudyVisualizer(study, single_massif_graph=True, save_to_file=True)
             # study_visualizer.visualize_all_kde_graphs()
             study_visualizer.visualize_all_experimental_law()
 
diff --git a/experiment/meteo_france_SCM_study/safran/safran_visualizer.py b/experiment/meteo_france_SCM_study/safran/safran_visualizer.py
index 90ac03a8..8e3b0f91 100644
--- a/experiment/meteo_france_SCM_study/safran/safran_visualizer.py
+++ b/experiment/meteo_france_SCM_study/safran/safran_visualizer.py
@@ -28,7 +28,8 @@ from utils import get_display_name_from_object_type, VERSION_TIME, float_to_str_
 
 class StudyVisualizer(object):
 
-    def __init__(self, study: AbstractStudy, show=True, save_to_file=False):
+    def __init__(self, study: AbstractStudy, show=True, save_to_file=False, single_massif_graph=False):
+        self.single_massif_graph = single_massif_graph
         self.save_to_file = save_to_file
         self.study = study
         self.show = False if self.save_to_file else show
@@ -50,18 +51,22 @@ class StudyVisualizer(object):
     # Graph for each massif / or groups of massifs
 
     def visualize_massif_graphs(self, visualize_function):
-        nb_columns = 5
-        nb_rows = math.ceil(len(self.study.safran_massif_names) / nb_columns)
-        fig, axes = plt.subplots(nb_rows, nb_columns, figsize=self.figsize)
-        fig.subplots_adjust(hspace=1.0, wspace=1.0)
-        for massif_id, massif_name in enumerate(self.study.safran_massif_names):
-            row_id, column_id = massif_id // nb_columns, massif_id % nb_columns
-            ax = axes[row_id, column_id]
-            visualize_function(ax, massif_id)
+        if self.single_massif_graph:
+            fig, ax = plt.subplots(1, 1, figsize=self.figsize)
+            visualize_function(ax, 0)
+        else:
+            nb_columns = 5
+            nb_rows = math.ceil(len(self.study.safran_massif_names) / nb_columns)
+            fig, axes = plt.subplots(nb_rows, nb_columns, figsize=self.figsize)
+            fig.subplots_adjust(hspace=1.0, wspace=1.0)
+            for massif_id, massif_name in enumerate(self.study.safran_massif_names):
+                row_id, column_id = massif_id // nb_columns, massif_id % nb_columns
+                ax = axes[row_id, column_id]
+                visualize_function(ax, massif_id)
 
     def visualize_all_experimental_law(self):
         self.visualize_massif_graphs(self.visualize_experimental_law)
-        plot_name = ' Experimental law with all the data'
+        plot_name = ' Empirical distribution with all available data'
         self.show_or_save_to_file(plot_name)
 
     def visualize_experimental_law(self, ax, massif_id):
@@ -76,24 +81,26 @@ class StudyVisualizer(object):
 
         # Plot the mean point in green
         x_level_to_color = {
-            np.mean(all_massif_data): 'g',
+            np.mean(all_massif_data): ('g', 'mean'),
         }
-        # Plot some specific quantiles in red
-        for p in AbstractParams.QUANTILE_P_VALUES:
+        # Plot some specific quantiles in their color
+        for p, color, name in zip(AbstractParams.QUANTILE_P_VALUES, AbstractParams.QUANTILE_COLORS, AbstractParams.QUANTILE_NAMES):
             x_level = all_massif_data[int(p * len(all_massif_data))]
-            x_level_to_color[x_level] = 'r'
+            x_level_to_color[x_level] = (color, name)
 
-        for xi, color in x_level_to_color.items():
+        for xi, (color, name) in x_level_to_color.items():
             yi = np.interp(xi, data_x, data_y)
-            ax.plot([xi], [yi], color=color, marker="o")
+            ax.scatter([xi], [yi], color=color, marker="o", label=name)
 
-        ax.set_ylabel('Density', color=color_kde)
-        ax.set_xlabel(self.study.title)
+        ax.set_ylabel('Probability Density function f(x)', color=color_kde)
+        ax.set_xlabel('x = {}'.format(self.study.title))
         extraticks = [float(float_to_str_with_only_some_significant_digits(x, nb_digits=2))
                       for x in sorted(list(x_level_to_color.keys()))]
-        extraticks = [extraticks[0], extraticks[-1]]
+        if not self.single_massif_graph:
+            extraticks = [extraticks[0], extraticks[-1]]
         ax.set_xticks(extraticks)
         ax.set_title(self.study.safran_massif_names[massif_id])
+        ax.legend()
 
     def visualize_all_mean_and_max_graphs(self):
         self.visualize_massif_graphs(self.visualize_mean_and_max_graph)
diff --git a/extreme_estimator/extreme_models/margin_model/margin_function/abstract_margin_function.py b/extreme_estimator/extreme_models/margin_model/margin_function/abstract_margin_function.py
index cc1ac24b..a88c4beb 100644
--- a/extreme_estimator/extreme_models/margin_model/margin_function/abstract_margin_function.py
+++ b/extreme_estimator/extreme_models/margin_model/margin_function/abstract_margin_function.py
@@ -78,8 +78,10 @@ class AbstractMarginFunction(object):
             self.visualize_1D(gev_value_name, ax, show)
         elif self.coordinates.nb_coordinates_spatial == 2:
             self.visualize_2D(gev_value_name, ax, show)
+        elif self.coordinates.nb_coordinates_spatial == 3:
+            self.visualize_3D(gev_value_name, ax, show)
         else:
-            raise NotImplementedError('3D Margin visualization not yet implemented')
+            raise NotImplementedError('Other visualization not yet implemented')
 
     # Visualization 1D
 
@@ -159,3 +161,10 @@ class AbstractMarginFunction(object):
         grid = {value_name: np.array([g[value_name] for g in grid]).reshape([resolution, resolution])
                 for value_name in GevParams.SUMMARY_NAMES}
         return grid
+
+    # Visualization 3D
+
+    def visualize_3D(self, gev_param_name=GevParams.LOC, ax=None, show=True):
+        # Make the first/the last time step 2D visualization side by side
+        # self.visualize_2D(gev_param_name=gev_param_name, ax=ax, show=show)
+        pass
diff --git a/extreme_estimator/margin_fits/abstract_params.py b/extreme_estimator/margin_fits/abstract_params.py
index 659aa06d..338b4b8d 100644
--- a/extreme_estimator/margin_fits/abstract_params.py
+++ b/extreme_estimator/margin_fits/abstract_params.py
@@ -8,11 +8,12 @@ class AbstractParams(object):
     # Parameters
     PARAM_NAMES = []
     # Quantile
-    QUANTILE_10 = 'quantile 10'
-    QUANTILE_100 = 'quantile 100'
-    QUANTILE_1000 = 'quantile 1000'
+    QUANTILE_10 = 'quantile 0.9'
+    QUANTILE_100 = 'quantile 0.99'
+    QUANTILE_1000 = 'quantile 0.999'
     QUANTILE_NAMES = [QUANTILE_10, QUANTILE_100, QUANTILE_1000][:-1]
     QUANTILE_P_VALUES = [0.9, 0.99, 0.999][:-1]
+    QUANTILE_COLORS = ['orange', 'red', 'darkviolet']
     # Summary
     SUMMARY_NAMES = PARAM_NAMES + QUANTILE_NAMES
 
diff --git a/test/test_extreme_estimator/test_extreme_models/test_margin_model.py b/test/test_extreme_estimator/test_extreme_models/test_margin_model.py
index 7611f024..1be2e00e 100644
--- a/test/test_extreme_estimator/test_extreme_models/test_margin_model.py
+++ b/test/test_extreme_estimator/test_extreme_models/test_margin_model.py
@@ -1,29 +1,53 @@
 import unittest
 
+from extreme_estimator.extreme_models.margin_model.margin_function.linear_margin_function import LinearMarginFunction
 from extreme_estimator.margin_fits.gev.gev_params import GevParams
 from extreme_estimator.extreme_models.margin_model.smooth_margin_model import LinearShapeDim1MarginModel, \
     LinearAllParametersAllDimsMarginModel
-from spatio_temporal_dataset.coordinates.spatial_coordinates.generated_spatial_coordinates import CircleSpatialCoordinates
+from spatio_temporal_dataset.coordinates.spatial_coordinates.generated_spatial_coordinates import \
+    CircleSpatialCoordinates
 from spatio_temporal_dataset.coordinates.spatial_coordinates.coordinates_1D import LinSpaceSpatialCoordinates
+from test.test_utils import load_test_spatiotemporal_coordinates
 
 
 class VisualizationMarginModel(unittest.TestCase):
     DISPLAY = False
     nb_points = 2
-    margin_model = [LinearShapeDim1MarginModel, LinearAllParametersAllDimsMarginModel][-1]
+    margin_model_class = [LinearShapeDim1MarginModel, LinearAllParametersAllDimsMarginModel][-1]
 
-    def test_example_visualization_2D(self):
-        spatial_coordinates = CircleSpatialCoordinates.from_nb_points(nb_points=self.nb_points)
-        margin_model = self.margin_model(coordinates=spatial_coordinates)
-        if self.DISPLAY:
-            margin_model.margin_function_sample.visualize_function()
+    def tearDown(self) -> None:
+        self.margin_model.margin_function_sample.visualize_function(show=self.DISPLAY)
+        self.assertTrue(True)
 
     def test_example_visualization_1D(self):
         coordinates = LinSpaceSpatialCoordinates.from_nb_points(nb_points=self.nb_points)
-        margin_model = self.margin_model(coordinates=coordinates, params_sample={(GevParams.SHAPE, 1): 0.02})
-        margin_model.margin_function_sample.visualize_function(show=self.DISPLAY)
-        self.assertTrue(True)
+        self.margin_model = self.margin_model_class(coordinates=coordinates, params_sample={(GevParams.SHAPE, 1): 0.02})
+
+    def test_example_visualization_2D_spatial(self):
+        spatial_coordinates = CircleSpatialCoordinates.from_nb_points(nb_points=self.nb_points)
+        self.margin_model = self.margin_model_class(coordinates=spatial_coordinates)
+
+    # def test_example_visualization_2D_spatio_temporal(self):
+    #     self.nb_steps = 2
+    #     coordinates = load_test_spatiotemporal_coordinates(nb_steps=self.nb_steps, nb_points=self.nb_points)[0]
+    #     self.margin_model = self.margin_model_class(coordinates)
+    #
+    #     # Load margin function from coef dict
+    #     coef_dict = {'locCoeff1': 0, 'locCoeff2': 1, 'scaleCoeff1': 0,
+    #                  'scaleCoeff2': 1, 'shapeCoeff1': 0,
+    #                  'shapeCoeff2': 1,
+    #                  'tempCoeffLoc1': 1, 'tempCoeffScale1': 1,
+    #                  'tempCoeffShape1': 1}
+    #     margin_function = LinearMarginFunction.from_coef_dict(coordinates,
+    #                                                           self.margin_model.margin_function_sample.gev_param_name_to_linear_dims,
+    #                                                           coef_dict)
+    #     self.margin_model.margin_function_sample = margin_function
+    #     self.margin_model.margin_function_sample.visualize_2D(show=True)
+    #
+    #     # Load
 
 
 if __name__ == '__main__':
     unittest.main()
+    # v = VisualizationMarginModel()
+    # v.test_example_visualization_2D_spatio_temporal()
-- 
GitLab