From 615bd53275f8a7b6d732a4533c6ce8426c6a6f15 Mon Sep 17 00:00:00 2001
From: Baptiste Bauvin <baptiste.bauvin@lis-lab.fr>
Date: Mon, 27 Apr 2020 10:04:03 -0400
Subject: [PATCH] Test coverage OK"

---
 .gitignore                                    |  4 +-
 .../result_analysis/error_analysis.py         | 12 ++--
 .../result_analysis/execution.py              |  4 +-
 .../result_analysis/feature_importances.py    |  2 +-
 .../result_analysis/metric_analysis.py        |  4 +-
 .../test_duration_analysis.py                 | 41 +++++++++++++
 .../test_result_analysis/test_execution.py    | 57 ++++++++++++++++++-
 .../test_feature_importances.py               | 36 ++++++++++++
 .../test_metric_analysis.py                   | 31 +++++++++-
 .../test_tracebacks_analysis.py               | 47 +++++++++++++++
 10 files changed, 221 insertions(+), 17 deletions(-)

diff --git a/.gitignore b/.gitignore
index 372dd296..5c20b764 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,4 +23,6 @@ multiview_platform/examples/results/example_3/*
 multiview_platform/examples/results/example_4/*
 multiview_platform/examples/results/example_5/*
 multiview_platform/html_cov/
-multiview_platform/.coverage*
\ No newline at end of file
+multiview_platform/.coverage*
+.coverage*
+htmlcov/
\ No newline at end of file
diff --git a/multiview_platform/mono_multi_view_classifiers/result_analysis/error_analysis.py b/multiview_platform/mono_multi_view_classifiers/result_analysis/error_analysis.py
index f78955dc..97aa6baa 100644
--- a/multiview_platform/mono_multi_view_classifiers/result_analysis/error_analysis.py
+++ b/multiview_platform/mono_multi_view_classifiers/result_analysis/error_analysis.py
@@ -47,7 +47,7 @@ def get_example_errors(groud_truth, results):
 
 
 def publish_example_errors(example_errors, directory, databaseName,
-                           labels_names, example_ids, labels):
+                           labels_names, example_ids, labels): # pragma: no cover
     logging.debug("Start:\t Label analysis figure generation")
 
     base_file_name = os.path.join(directory, databaseName + "-" )
@@ -70,7 +70,7 @@ def publish_example_errors(example_errors, directory, databaseName,
 
 def publish_all_example_errors(iter_results, directory,
                                stats_iter,
-                               example_ids, labels):
+                               example_ids, labels): # pragma: no cover
     logging.debug(
         "Start:\t Global label analysis figure generation")
 
@@ -132,11 +132,7 @@ def gen_error_data(example_errors):
     data_2d = np.zeros((nb_examples, nb_classifiers))
     for classifierIndex, (classifier_name, error_on_examples) in enumerate(
             example_errors.items()):
-        try:
-            data_2d[:, classifierIndex] = error_on_examples
-        except:
-            import pdb;
-            pdb.set_trace()
+        data_2d[:, classifierIndex] = error_on_examples
     error_on_examples = np.sum(data_2d, axis=1) / nb_classifiers
     return nb_classifiers, nb_examples, classifiers_names, data_2d, error_on_examples
 
@@ -267,7 +263,7 @@ def plot_errors_bar(error_on_examples, nb_examples, file_name,
 
 
 
-def iter_cmap(statsIter):
+def iter_cmap(statsIter): # pragma: no cover
     r"""Used to generate a colormap that will have a tick for each iteration : the whiter the better.
 
     Parameters
diff --git a/multiview_platform/mono_multi_view_classifiers/result_analysis/execution.py b/multiview_platform/mono_multi_view_classifiers/result_analysis/execution.py
index 88392cd6..e620a934 100644
--- a/multiview_platform/mono_multi_view_classifiers/result_analysis/execution.py
+++ b/multiview_platform/mono_multi_view_classifiers/result_analysis/execution.py
@@ -8,7 +8,7 @@ from .error_analysis import get_example_errors, publish_example_errors, publish_
 from .feature_importances import get_feature_importances, publish_feature_importances
 
 def analyze(results, stats_iter, benchmark_argument_dictionaries,
-                metrics, directory, example_ids, labels):
+                metrics, directory, example_ids, labels): # pragma: no cover
     """Used to analyze the results of the previous benchmarks"""
     data_base_name = benchmark_argument_dictionaries[0]["args"]["name"]
 
@@ -105,7 +105,7 @@ def analyze_iterations(results, benchmark_argument_dictionaries, stats_iter,
 
 
 def analyze_all(iter_results, stats_iter, directory, data_base_name,
-                example_ids, label_names):
+                example_ids, label_names): # pragma: no cover
     """Used to format the results in order to plot the mean results on
     the iterations"""
     metrics_analysis, class_metrics_analysis, error_analysis, feature_importances, \
diff --git a/multiview_platform/mono_multi_view_classifiers/result_analysis/feature_importances.py b/multiview_platform/mono_multi_view_classifiers/result_analysis/feature_importances.py
index c30a1c63..459f664f 100644
--- a/multiview_platform/mono_multi_view_classifiers/result_analysis/feature_importances.py
+++ b/multiview_platform/mono_multi_view_classifiers/result_analysis/feature_importances.py
@@ -38,7 +38,7 @@ def get_feature_importances(result, feature_names=None):
     return feature_importances
 
 def publish_feature_importances(feature_importances, directory, database_name,
-                                feature_stds=None):
+                                feature_stds=None):  # pragma: no cover
     for view_name, feature_importance in feature_importances.items():
         if not os.path.exists(os.path.join(directory, "feature_importances")):
             os.mkdir(os.path.join(directory, "feature_importances"))
diff --git a/multiview_platform/mono_multi_view_classifiers/result_analysis/metric_analysis.py b/multiview_platform/mono_multi_view_classifiers/result_analysis/metric_analysis.py
index 94c50be9..fff1e365 100644
--- a/multiview_platform/mono_multi_view_classifiers/result_analysis/metric_analysis.py
+++ b/multiview_platform/mono_multi_view_classifiers/result_analysis/metric_analysis.py
@@ -67,7 +67,7 @@ def get_metrics_scores(metrics, results, label_names):
 
 
 def publish_metrics_graphs(metrics_scores, directory, database_name,
-                           labels_names, class_metric_scores):
+                           labels_names, class_metric_scores):  # pragma: no cover
     r"""Used to sort the results (names and both scores) in descending test
     score order.
 
@@ -114,7 +114,7 @@ def publish_metrics_graphs(metrics_scores, directory, database_name,
 
 def publish_all_metrics_scores(iter_results, class_iter_results, directory,
                                data_base_name, stats_iter, label_names,
-                               min_size=10):
+                               min_size=10): # pragma: no cover
     results = []
     secure_file_path(os.path.join(directory, "a"))
 
diff --git a/multiview_platform/tests/test_result_analysis/test_duration_analysis.py b/multiview_platform/tests/test_result_analysis/test_duration_analysis.py
index e69de29b..efe6c68d 100644
--- a/multiview_platform/tests/test_result_analysis/test_duration_analysis.py
+++ b/multiview_platform/tests/test_result_analysis/test_duration_analysis.py
@@ -0,0 +1,41 @@
+import unittest
+import numpy as np
+import pandas as pd
+
+from multiview_platform.mono_multi_view_classifiers.result_analysis import duration_analysis
+
+class FakeClassifierResult:
+
+    def __init__(self, i=0):
+        self.i=i
+        if i == 0:
+            self.hps_duration = 10
+            self.fit_duration = 12
+            self.pred_duration = 15
+        else:
+            self.hps_duration = 1
+            self.fit_duration = 2
+            self.pred_duration = 5
+
+
+    def get_classifier_name(self):
+        if self.i == 0:
+            return 'test1'
+        else:
+            return 'test2'
+
+
+
+class Test_get_duration(unittest.TestCase):
+
+    def test_simple(self):
+        results = [FakeClassifierResult(), FakeClassifierResult(i=1)]
+        durs = duration_analysis.get_duration(results)
+        pd.testing.assert_frame_equal(durs,
+                                      pd.DataFrame(index=['test1', 'test2'],
+                                                   columns=['hps', 'fit', 'pred'],
+                                                   data=np.array([np.array([10,12,15]),
+                                                                  np.array([1,2,5])]),
+                                                   dtype=object))
+
+
diff --git a/multiview_platform/tests/test_result_analysis/test_execution.py b/multiview_platform/tests/test_result_analysis/test_execution.py
index cafd6c90..f42f818c 100644
--- a/multiview_platform/tests/test_result_analysis/test_execution.py
+++ b/multiview_platform/tests/test_result_analysis/test_execution.py
@@ -1,11 +1,26 @@
 import unittest
 import numpy as np
 import pandas as pd
+import os
 
 from multiview_platform.mono_multi_view_classifiers.monoview.monoview_utils import MonoviewResult
 from multiview_platform.mono_multi_view_classifiers.multiview.multiview_utils import MultiviewResult
 
-from multiview_platform.mono_multi_view_classifiers.result_analysis.execution import format_previous_results, get_arguments
+from multiview_platform.mono_multi_view_classifiers.result_analysis.execution import format_previous_results, get_arguments, analyze_iterations
+from multiview_platform.tests.utils import rm_tmp, tmp_path, test_dataset
+
+
+class FakeClassifierResult:
+
+    def __init__(self, i=1):
+        self.classifier_name='test'+str(i)
+        self.full_labels_pred = np.array([0,1,1,2,1])
+        self.hps_duration=i
+        self.fit_duration=i
+        self.pred_duration=i
+
+    def get_classifier_name(self):
+        return self.classifier_name
 
 class Test_format_previous_results(unittest.TestCase):
 
@@ -82,3 +97,43 @@ class Test_get_arguments(unittest.TestCase):
     def test_benchmark_wanted(self):
         argument_dict = get_arguments(self.benchamrk_argument_dictionaries, "good_flag")
         self.assertTrue(argument_dict["valid"])
+
+
+class Test_analyze_iterations(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        os.mkdir(tmp_path)
+        cls.results = [[0, [FakeClassifierResult(), FakeClassifierResult(i=2)], []], [1, [FakeClassifierResult(), FakeClassifierResult(i=2)], []]]
+        cls.benchmark_argument_dictionaries = [{"labels_dictionary":{0:"zero",1:"one",2:"two"}, "flag":0, "directory":tmp_path, "args":{"name":"test_dataset"}},{"labels_dictionary":{0:"zero",1:"one",2:"two"}, "flag":1, "directory":tmp_path, "args":{"name":"test_dataset"}} ]
+        cls.stats_iter = 2
+        cls.metrics = {}
+        cls.example_ids = ['ex1', 'ex5','ex4','ex3','ex2',]
+        cls.labels = np.array([0,1,2,1,1])
+
+
+    @classmethod
+    def tearDownClass(cls):
+        rm_tmp()
+
+    def test_simple(self):
+        analysis = analyze_iterations(self.results,
+                                      self.benchmark_argument_dictionaries,
+                                      self.stats_iter,
+                                      self.metrics,
+                                      self.example_ids,
+                                      self.labels)
+        res, iter_res, tracebacks, labels_names = analysis
+        self.assertEqual(labels_names, ['zero', 'one', 'two'])
+
+        self.assertEqual(iter_res['class_metrics_scores'], [{}, {}])
+
+        pd.testing.assert_frame_equal(iter_res['durations'][0], pd.DataFrame(index=['test1','test2'],
+                                 columns=['hps', 'fit', 'pred'],
+                            data=np.array([1,1,1,2,2,2]).reshape((2,3)), dtype=object))
+        np.testing.assert_array_equal(iter_res['example_errors'][0]['test1'], np.array([1, 1, 0, 0, 1]))
+        self.assertEqual(iter_res["feature_importances"], [{},{}])
+        np.testing.assert_array_equal(iter_res['labels'], np.array([0, 1, 2, 1, 1]))
+        self.assertEqual(iter_res['metrics_scores'], [{},{}])
+
+
diff --git a/multiview_platform/tests/test_result_analysis/test_feature_importances.py b/multiview_platform/tests/test_result_analysis/test_feature_importances.py
index e69de29b..2a69e88c 100644
--- a/multiview_platform/tests/test_result_analysis/test_feature_importances.py
+++ b/multiview_platform/tests/test_result_analysis/test_feature_importances.py
@@ -0,0 +1,36 @@
+import unittest
+import numpy as np
+import pandas as pd
+
+from multiview_platform.mono_multi_view_classifiers.result_analysis import feature_importances
+from multiview_platform.mono_multi_view_classifiers.monoview.monoview_utils import MonoviewResult
+
+class FakeClassifier:
+    def __init__(self, i=0):
+        self.feature_importances_ = [i, i+1]
+
+class FakeClassifierResult(MonoviewResult):
+
+    def __init__(self, i=0):
+        self.i=i
+        self.hps_duration = i*10
+        self.fit_duration = (i+2)*10
+        self.pred_duration = (i+5)*10
+        self.clf = FakeClassifier(i)
+        self.view_name = 'testview'+str(i)
+        self.classifier_name = "test"+str(i)
+
+    def get_classifier_name(self):
+        return self.classifier_name
+
+
+
+class Test_get_duration(unittest.TestCase):
+
+    def test_simple(self):
+        results = [FakeClassifierResult(), FakeClassifierResult(i=1)]
+        feat_importance = feature_importances.get_feature_importances(results)
+        pd.testing.assert_frame_equal(feat_importance["testview1"],
+                                      pd.DataFrame(index=None,columns=['test1'],
+                                                   data=np.array([1,2]).reshape((2,1)),
+                                                   ))
\ No newline at end of file
diff --git a/multiview_platform/tests/test_result_analysis/test_metric_analysis.py b/multiview_platform/tests/test_result_analysis/test_metric_analysis.py
index 800b916e..a34f06a4 100644
--- a/multiview_platform/tests/test_result_analysis/test_metric_analysis.py
+++ b/multiview_platform/tests/test_result_analysis/test_metric_analysis.py
@@ -6,7 +6,7 @@ import os
 from multiview_platform.mono_multi_view_classifiers.monoview.monoview_utils import MonoviewResult
 from multiview_platform.mono_multi_view_classifiers.multiview.multiview_utils import MultiviewResult
 
-from multiview_platform.mono_multi_view_classifiers.result_analysis.metric_analysis import get_metrics_scores, init_plot
+from multiview_platform.mono_multi_view_classifiers.result_analysis.metric_analysis import get_metrics_scores, init_plot, get_fig_size, sort_by_test_score
 
 class Test_get_metrics_scores(unittest.TestCase):
 
@@ -150,4 +150,31 @@ class Test_init_plot(unittest.TestCase):
         np.testing.assert_array_equal(classifier_names, np.array(["dt-1", "mv"]))
         self.assertEqual(nb_results, 2)
         self.assertEqual(results, [["dt-1", "acc", data[1,0], 0.0, data[1,0]],
-                                   ["mv", "acc", data[1,1], 0.0, data[1,1]]])
\ No newline at end of file
+                                   ["mv", "acc", data[1,1], 0.0, data[1,1]]])
+
+
+class Test_small_func(unittest.TestCase):
+
+    def test_fig_size(self):
+        kw, width = get_fig_size(5)
+        self.assertEqual(kw, {"figsize":(15,5)})
+        self.assertEqual(width, 0.35)
+        kw, width = get_fig_size(100)
+        self.assertEqual(kw, {"figsize": (100, 100/3)})
+        self.assertEqual(width, 0.35)
+
+    def test_sort_by_test_scores(self):
+        train_scores = np.array([1,2,3,4])
+        test_scores = np.array([4, 3, 2, 1])
+        train_STDs = np.array([1, 2, 3, 4])
+        test_STDs = np.array([1, 2, 3, 4])
+        names = np.array(['1', '2', '3', '4'])
+        sorted_names, sorted_train_scores, \
+        sorted_test_scores, sorted_train_STDs, \
+        sorted_test_STDs = sort_by_test_score(train_scores, test_scores,
+                                              names, train_STDs, test_STDs)
+        np.testing.assert_array_equal(sorted_names, np.array(['4', '3', '2', '1']))
+        np.testing.assert_array_equal(sorted_test_scores, [1, 2, 3, 4])
+        np.testing.assert_array_equal(sorted_test_STDs, [4, 3, 2, 1])
+        np.testing.assert_array_equal(sorted_train_scores, [4, 3, 2, 1])
+        np.testing.assert_array_equal(sorted_train_STDs, [4, 3, 2, 1])
\ No newline at end of file
diff --git a/multiview_platform/tests/test_result_analysis/test_tracebacks_analysis.py b/multiview_platform/tests/test_result_analysis/test_tracebacks_analysis.py
index e69de29b..61296f85 100644
--- a/multiview_platform/tests/test_result_analysis/test_tracebacks_analysis.py
+++ b/multiview_platform/tests/test_result_analysis/test_tracebacks_analysis.py
@@ -0,0 +1,47 @@
+import unittest
+import numpy as np
+import pandas as pd
+import os
+
+from multiview_platform.mono_multi_view_classifiers.result_analysis import tracebacks_analysis
+from multiview_platform.tests.utils import tmp_path, rm_tmp
+
+class FakeClassifierResult:
+
+    def __init__(self, i=0):
+        self.i=i
+        if i == 0:
+            self.hps_duration = 10
+            self.fit_duration = 12
+            self.pred_duration = 15
+        else:
+            self.hps_duration = 1
+            self.fit_duration = 2
+            self.pred_duration = 5
+
+
+    def get_classifier_name(self):
+        if self.i == 0:
+            return 'test1'
+        else:
+            return 'test2'
+
+
+
+class Test_funcs(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        os.mkdir(tmp_path)
+        cls.res_file = open(os.path.join(tmp_path,"tmp.txt"), "w")
+
+    @classmethod
+    def tearDownClass(cls):
+        rm_tmp()
+
+    def test_save_dict_to_text(self):
+        keys = tracebacks_analysis.save_dict_to_text({"a":"i", "b":"j"}, self.res_file)
+        self.res_file.close()
+        self.assertEqual(list(keys),["a", "b"])
+        with open(os.path.join(tmp_path,"tmp.txt"), 'r') as res_file:
+            self.assertEqual(res_file.read(), 'Failed algorithms : \n\ta,\n\tb.\n\n\na\n\ni\n\n\nb\n\nj\n\n\n')
-- 
GitLab