From acdcf96ffb674ac25c98ea454cbdb10e39c35701 Mon Sep 17 00:00:00 2001
From: Le Roux Erwan <erwan.le-roux@irstea.fr>
Date: Mon, 27 May 2019 10:22:06 +0200
Subject: [PATCH] [SCM][HYPERCUBE] refactor trend types for hypercube
 visualization. add the difference between real_trend_type &
 display_trend_type

---
 .../altitude_hypercube_visualizer.py          | 28 +++++++--------
 .../main_hypercube_visualization.py           |  4 +--
 .../studies_visualizer.py                     |  2 +-
 .../abstract_gev_change_point_test.py         | 11 ++++++
 .../abstract_univariate_test.py               | 34 ++++++++++++-------
 5 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/experiment/meteo_france_SCM_study/visualization/hypercube_visualization/altitude_hypercube_visualizer.py b/experiment/meteo_france_SCM_study/visualization/hypercube_visualization/altitude_hypercube_visualizer.py
index 25ef2966..cb8557e2 100644
--- a/experiment/meteo_france_SCM_study/visualization/hypercube_visualization/altitude_hypercube_visualizer.py
+++ b/experiment/meteo_france_SCM_study/visualization/hypercube_visualization/altitude_hypercube_visualizer.py
@@ -16,12 +16,12 @@ class AltitudeHypercubeVisualizer(AbstractHypercubeVisualizer):
         return self.tuple_values(idx=0)
 
     @property
-    def trend_type_to_style(self):
-        return self.trend_test_class.trend_type_to_style()
+    def display_trend_type_to_style(self):
+        return self.trend_test_class.display_trend_type_to_style()
 
     @property
-    def trend_types(self):
-        return self.trend_type_to_style.keys()
+    def display_trend_types(self):
+        return self.display_trend_type_to_style.keys()
 
     @property
     def nb_axes(self):
@@ -29,12 +29,12 @@ class AltitudeHypercubeVisualizer(AbstractHypercubeVisualizer):
 
     def trend_type_to_series(self, reduction_function):
         # Map each trend type to its serie with percentages
-        return {trend_type: self.trend_type_reduction(reduction_function, trend_type)[0]
-                for trend_type in self.trend_types}
+        return {display_trend_type: self.trend_type_reduction(reduction_function, display_trend_type)[0]
+                for display_trend_type in self.display_trend_types}
 
-    def trend_type_reduction(self, reduction_function, trend_type):
+    def trend_type_reduction(self, reduction_function, display_trend_type):
         # Reduce df_bool df to a serie s_trend_type_percentage
-        df_bool = self.df_hypercube_trend_type.isin(AbstractUnivariateTest.get_trend_types(trend_type))
+        df_bool = self.df_hypercube_trend_type.isin(AbstractUnivariateTest.get_real_trend_types(display_trend_type))
         s_trend_type_percentage = reduction_function(df_bool)
         assert isinstance(s_trend_type_percentage, pd.Series)
         assert not isinstance(s_trend_type_percentage.index, pd.MultiIndex)
@@ -75,8 +75,8 @@ class AltitudeHypercubeVisualizer(AbstractHypercubeVisualizer):
 
         trend_type_to_series = self.trend_type_to_series(reduction_function)
         for ax_idx, ax in enumerate(axes):
-            for trend_type in self.trend_types:
-                style = self.trend_type_to_style[trend_type]
+            for trend_type in self.display_trend_types:
+                style = self.display_trend_type_to_style[trend_type]
                 percentages_values = trend_type_to_series[trend_type][ax_idx]
                 ax.plot(xlabel_values, percentages_values, style + marker, label=trend_type)
 
@@ -101,7 +101,7 @@ class AltitudeHypercubeVisualizer(AbstractHypercubeVisualizer):
 
     def visualize_trend_test_repartition(self, reduction_function, axes=None, subtitle=''):
         if axes is None:
-            nb_trend_type = len(self.trend_test_class.trend_type_to_style())
+            nb_trend_type = len(self.display_trend_type_to_style)
             fig, axes = plt.subplots(self.nb_axes, nb_trend_type, figsize=self.study_visualizer.figsize)
 
         for i, axes_row in enumerate(axes):
@@ -109,7 +109,7 @@ class AltitudeHypercubeVisualizer(AbstractHypercubeVisualizer):
             vmax = max([s.max() for s in trend_type_to_serie.values()])
             vmin = min([s.min() for s in trend_type_to_serie.values()])
             vmax = max(vmax, 0.01)
-            for ax, trend_type in zip(axes_row, self.trend_types):
+            for ax, trend_type in zip(axes_row, self.display_trend_types):
                 s_percentages = trend_type_to_serie[trend_type]
                 massif_to_value = dict(s_percentages)
                 cmap = self.trend_test_class.get_cmap_from_trend_type(trend_type)
@@ -183,8 +183,8 @@ class Altitude_Hypercube_Year_Visualizer(AltitudeHypercubeVisualizer):
         # Take the mean with respect to the level of interest
         return df.mean(level=level)
 
-    def trend_type_reduction(self, reduction_function, trend_type):
-        series, df_bool = super().trend_type_reduction(reduction_function, trend_type)
+    def trend_type_reduction(self, reduction_function, display_trend_type):
+        series, df_bool = super().trend_type_reduction(reduction_function, display_trend_type)
         # Create df argmax
         df = df_bool.copy()
         df = (df * df.columns)[df_bool]
diff --git a/experiment/meteo_france_SCM_study/visualization/hypercube_visualization/main_hypercube_visualization.py b/experiment/meteo_france_SCM_study/visualization/hypercube_visualization/main_hypercube_visualization.py
index 07a1c6b9..f274e0ab 100644
--- a/experiment/meteo_france_SCM_study/visualization/hypercube_visualization/main_hypercube_visualization.py
+++ b/experiment/meteo_france_SCM_study/visualization/hypercube_visualization/main_hypercube_visualization.py
@@ -132,8 +132,8 @@ def fast_quantity_altitude_hypercube():
 
 def main_run():
     # fast_altitude_hypercube()
-    # fast_altitude_year_hypercube()
-    full_altitude_year_hypercube()
+    fast_altitude_year_hypercube()
+    # full_altitude_year_hypercube()
     # fast_quantity_altitude_hypercube()
     # full_quantity_altitude_hypercube()
 
diff --git a/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies_visualizer.py b/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies_visualizer.py
index 3b618abd..664506f8 100644
--- a/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies_visualizer.py
+++ b/experiment/meteo_france_SCM_study/visualization/studies_visualization/studies_visualizer.py
@@ -237,7 +237,7 @@ class AltitudeVisualizer(object):
             s = study_visualizer.df_trend_test_count(trend_test_class, starting_year_to_weights).mean(axis=1)
             altitude_to_serie_with_mean_percentages[altitude] = s
         # Plot weighted percentages over the years
-        for trend_type, style in trend_test_class.trend_type_to_style().items():
+        for trend_type, style in trend_test_class.display_trend_type_to_style().items():
 
             weighted_percentages = [v.loc[trend_type] if trend_type in v.index else 0.0
                                     for v in altitude_to_serie_with_mean_percentages.values()]
diff --git a/experiment/trend_analysis/univariate_test/abstract_gev_change_point_test.py b/experiment/trend_analysis/univariate_test/abstract_gev_change_point_test.py
index cc46b8a8..c326ac2d 100644
--- a/experiment/trend_analysis/univariate_test/abstract_gev_change_point_test.py
+++ b/experiment/trend_analysis/univariate_test/abstract_gev_change_point_test.py
@@ -44,6 +44,17 @@ class AbstractGevChangePointTest(AbstractUnivariateTest):
         except SafeRunException:
             self.crashed = True
 
+    @classmethod
+    def real_trend_types(cls):
+        return super().real_trend_types() + [cls.RRunTimeError_TREND]
+
+    @classmethod
+    def get_real_trend_types(cls, display_trend_type):
+        real_trend_types = super().get_real_trend_types(display_trend_type)
+        if display_trend_type is cls.NON_SIGNIFICATIVE_TREND:
+            real_trend_types.append(cls.RRunTimeError_TREND)
+        return real_trend_types
+
     @property
     def likelihood_ratio(self):
         return 2 * (self.non_stationary_estimator.result_from_fit.deviance -
diff --git a/experiment/trend_analysis/univariate_test/abstract_univariate_test.py b/experiment/trend_analysis/univariate_test/abstract_univariate_test.py
index 2bb3baf3..b646301a 100644
--- a/experiment/trend_analysis/univariate_test/abstract_univariate_test.py
+++ b/experiment/trend_analysis/univariate_test/abstract_univariate_test.py
@@ -21,7 +21,9 @@ class AbstractUnivariateTest(object):
     SIGNIFICATIVE_ALL_TREND = SIGNIFICATIVE + ' ' + ALL_TREND
     SIGNIFICATIVE_POSITIVE_TREND = SIGNIFICATIVE + ' ' + POSITIVE_TREND
     SIGNIFICATIVE_NEGATIVE_TREND = SIGNIFICATIVE + ' ' + NEGATIVE_TREND
+    NON_SIGNIFICATIVE_TREND = 'non ' + SIGNIFICATIVE + ' trend'
 
+    # this is the most common level of significance
     SIGNIFICANCE_LEVEL = 0.05
 
     def __init__(self, years, maxima, starting_year):
@@ -43,29 +45,37 @@ class AbstractUnivariateTest(object):
         return self.maxima[self.idx_for_starting_year:]
 
     @classmethod
-    def trend_type_to_style(cls):
+    def real_trend_types(cls):
+        return [cls.POSITIVE_TREND, cls.NEGATIVE_TREND,
+                cls.SIGNIFICATIVE_POSITIVE_TREND, cls.SIGNIFICATIVE_NEGATIVE_TREND, cls.NO_TREND]
+
+    @classmethod
+    def display_trend_type_to_style(cls):
         d = OrderedDict()
+        # d[cls.POSITIVE_TREND] = 'g--'
+        # d[cls.NEGATIVE_TREND] = 'r--'
         d[cls.ALL_TREND] = 'k--'
-        d[cls.POSITIVE_TREND] = 'g--'
-        d[cls.NEGATIVE_TREND] = 'r--'
-        d[cls.SIGNIFICATIVE_ALL_TREND] = 'k-'
+        d[cls.NON_SIGNIFICATIVE_TREND] = 'b--'
+        # d[cls.SIGNIFICATIVE_ALL_TREND] = 'k-'
         d[cls.SIGNIFICATIVE_POSITIVE_TREND] = 'g-'
         d[cls.SIGNIFICATIVE_NEGATIVE_TREND] = 'r-'
         # d[cls.NO_TREND] = 'k--'
         return d
 
     @classmethod
-    def get_trend_types(cls, trend_type):
-        if trend_type is cls.ALL_TREND:
-            return cls.get_trend_types(cls.POSITIVE_TREND) + cls.get_trend_types(cls.NEGATIVE_TREND)
-        elif trend_type is cls.SIGNIFICATIVE_ALL_TREND:
+    def get_real_trend_types(cls, display_trend_type):
+        if display_trend_type is cls.ALL_TREND:
+            return cls.real_trend_types()
+        elif display_trend_type is cls.SIGNIFICATIVE_ALL_TREND:
             return [cls.SIGNIFICATIVE_POSITIVE_TREND, cls.SIGNIFICATIVE_NEGATIVE_TREND]
-        if trend_type is cls.POSITIVE_TREND:
+        if display_trend_type is cls.POSITIVE_TREND:
             return [cls.POSITIVE_TREND, cls.SIGNIFICATIVE_POSITIVE_TREND]
-        elif trend_type is cls.NEGATIVE_TREND:
+        elif display_trend_type is cls.NEGATIVE_TREND:
             return [cls.NEGATIVE_TREND, cls.SIGNIFICATIVE_NEGATIVE_TREND]
+        elif display_trend_type is cls.NON_SIGNIFICATIVE_TREND:
+            return [cls.POSITIVE_TREND, cls.NEGATIVE_TREND, cls.NO_TREND]
         else:
-            return [trend_type]
+            return [display_trend_type]
 
     @classmethod
     def get_cmap_from_trend_type(cls, trend_type):
@@ -94,7 +104,7 @@ class AbstractUnivariateTest(object):
             trend_type = self.POSITIVE_TREND if test_sign > 0 else self.NEGATIVE_TREND
             if self.is_significant:
                 trend_type = self.SIGNIFICATIVE + ' ' + trend_type
-        assert trend_type in self.trend_type_to_style()
+        assert trend_type in self.real_trend_types(), trend_type
         return trend_type
 
     @property
-- 
GitLab