import unittest
import numpy as np
from PCAfold import preprocess
from PCAfold import reduction
from PCAfold import analysis

class Preprocess(unittest.TestCase):

    def test_invert_center_scale(self):
        # This function tests all possible inversions of center_scale function:
        test_data_set = np.random.rand(200,20)

        try:
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'none', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'auto', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'std', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'pareto', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'range', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, '0to1', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, '-1to1', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'level', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'max', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'poisson', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_2', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_3', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_4', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
        except Exception:
            self.assertTrue(False)

        try:
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'none', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'auto', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'std', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'pareto', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'range', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, '0to1', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, '-1to1', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'level', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'max', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'poisson', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_2', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_3', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_4', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
        except Exception:
            self.assertTrue(False)

# ------------------------------------------------------------------------------

    def test_invert_center_scale_not_allowed_calls(self):

        X_cs = np.random.rand(100,)
        X_center = np.array([0])
        X_scale = np.array([1])

        with self.assertRaises(ValueError):
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)

        with self.assertRaises(ValueError):
            X = preprocess.invert_center_scale([1,2,3], X_center, X_scale)

        X_cs = np.random.rand(100,2)

        with self.assertRaises(ValueError):
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)

        X_scale = np.array([1,2])

        with self.assertRaises(ValueError):
            X = preprocess.invert_center_scale(X_cs, [0,0], X_scale)

        X_center = np.array([1,2])

        with self.assertRaises(ValueError):
            X = preprocess.invert_center_scale(X_cs, X_center, [1,1])

        X_cs = np.random.rand(100,10)
        X_center = np.array([0,0,0,0])
        X_scale = np.array([1,1,2,2])

        with self.assertRaises(ValueError):
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)

# ------------------------------------------------------------------------------

    def test_invert_center_scale_on_1D_variable(self):
        # This function tests all possible inversions of center_scale function:
        test_data_set = np.random.rand(200,1)

        try:
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'none', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'auto', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'std', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'pareto', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'range', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, '0to1', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, '-1to1', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'level', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'max', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'poisson', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_2', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_3', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_4', nocenter=False)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
        except Exception:
            self.assertTrue(False)

        try:
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'none', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'auto', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'std', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'pareto', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'range', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, '0to1', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, '-1to1', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'level', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'max', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'poisson', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_2', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_3', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
            (X_cs, X_center, X_scale) = preprocess.center_scale(test_data_set, 'vast_4', nocenter=True)
            X = preprocess.invert_center_scale(X_cs, X_center, X_scale)
            difference = abs(X - test_data_set)
            comparison = difference < 10**(-14)
            self.assertTrue(comparison.all())
        except Exception:
            self.assertTrue(False)

# ------------------------------------------------------------------------------

    def test_invert_center_scale_single_variable(self):

        try:
            test_data_set = np.ones((200,1))
            X_result = 2*np.ones((200,1))
            X = preprocess.invert_center_scale(test_data_set, np.array([0]), np.array([2]))
            comparison = X == X_result
            self.assertTrue(comparison.all())
        except Exception:
            self.assertTrue(False)

        try:
            test_data_set = np.ones((200,1))
            X_result = 3*np.ones((200,1))
            X = preprocess.invert_center_scale(test_data_set, np.array([1]), np.array([2]))
            comparison = X == X_result
            self.assertTrue(comparison.all())
        except Exception:
            self.assertTrue(False)

        try:
            test_data_set = np.ones((200,1))
            X_result = 2*np.ones((200,1))
            X = preprocess.invert_center_scale(test_data_set, np.array([0]), np.array([2]))
            comparison = X == X_result
            self.assertTrue(comparison.all())
        except Exception:
            self.assertTrue(False)

        try:
            test_data_set = np.ones((200,1))
            X_result = 3*np.ones((200,1))
            X = preprocess.invert_center_scale(test_data_set, np.array([1]), np.array([2]))
            comparison = X == X_result
            self.assertTrue(comparison.all())
        except Exception:
            self.assertTrue(False)

# ------------------------------------------------------------------------------
