"""Redundant signal matrix tests.
"""
from __future__ import division, absolute_import

import unittest

import numpy as np

from bcn.redundant_signal import RedundantSignal, _generate_square_blocks_matrix, _generate_pairs, _generate_stds, _generate_directions, _generate_covariance, _generate_matrix_normal_sample


class Test_std_consistency(unittest.TestCase):
    """ Test the consistency of standard deviations.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.m_blocks = 10
        self.shape = (250, 250)
        
    def test(self):
        self.correlation_matrix_U = _generate_square_blocks_matrix(self.shape[0], self.m_blocks, r=1.0)
        self.stds_U, scaling_factor_sample = _generate_stds(self.shape[0], 'random', normalize=True)
        self.U = _generate_covariance(self.correlation_matrix_U, self.stds_U) # sample
        print 'trace U', np.trace(self.U)
        assert np.allclose(np.sum(self.stds_U**2), 1.0, rtol=1e-5, atol=1e-5)
        pairs_sample = _generate_pairs(self.correlation_matrix_U)
        
        self.correlation_matrix_V = _generate_square_blocks_matrix(self.shape[1], self.m_blocks, r=1.0)
        self.stds_V, scaling_factor_feature = _generate_stds(self.shape[1], 'random', normalize=True) 
        self.V = _generate_covariance(self.correlation_matrix_V, self.stds_V) # feature
        print 'trace V', np.trace(self.V)
        assert np.allclose(np.sum(self.stds_U**2), 1.0, rtol=1e-5, atol=1e-5)
        pairs_feature = _generate_pairs(self.correlation_matrix_V)
        
        temp = []
        for q in xrange(100):
            self.sample = _generate_matrix_normal_sample(self.U, self.V)
            temp.append(self.sample)
        self.sample = np.mean(temp, axis=0)
        print self.sample.shape
        sample_stds = np.std(self.sample, axis=1)
        feature_stds = np.std(self.sample, axis=0)

        A = (feature_stds[pairs_feature][:, 0] / feature_stds[pairs_feature][:, 1])[:4]
        B = (sample_stds[pairs_sample][:, 0] / sample_stds[pairs_sample][:, 1])[:4]
        true_A = (self.stds_V[pairs_feature][:, 0] / self.stds_V[pairs_feature][:, 1])[:4]
        true_B = (self.stds_U[pairs_sample][:, 0] / self.stds_U[pairs_sample][:, 1])[:4]

        assert np.allclose(A, true_A, rtol=1e-5, atol=1e-5)
        assert np.allclose(B, true_B, rtol=1e-5, atol=1e-5)
        
        print 'feature mean stds and raw', np.mean(feature_stds), np.mean(self.stds_V) # NOTE To get macht, should not normalize.
        print 'sample mean stds and raw', np.mean(sample_stds), np.mean(self.stds_U)
        print 'difference feature stds and raw', np.mean(feature_stds - self.stds_V)
        print 'difference sample stds and raw', np.mean(sample_stds - self.stds_U)
        
      
class Test_generate_covariance(unittest.TestCase):
    """Test to verify that covariances are generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    correlation_matrix : ndarray, shape (n_samples, n_samples) or (n_features, n_features)
        Correlation matrix on which the covariance matrix is based.
    stds : ndarray, (dimensions = 1, e.g. like list)
        Standard deviations which are used in combination with the correlation amtrix to generate the covariance matrix.
    n : int
        Dimensions of the square block correlation matrix (n, n).
    m_blocks : int, default = 4
        The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.
    shape : tuple of int, computed automatically as (n, n)
        Shape of the covariance matrix.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 15
        self.m_blocks = 4
        self.shape = (self.n, self.n)
        self.correlation_matrix = _generate_square_blocks_matrix(self.n, self.m_blocks, r=1.0)
        self.stds, self.scaling_factor = _generate_stds(self.n, 'random', normalize=True)
        self.covariance_matrix = _generate_covariance(self.correlation_matrix, self.stds)
        
    def _assert_finite(self, covariance_matrix):
        assert np.isfinite(covariance_matrix).all() == True

    def _assert_shape(self, covariance_matrix):
        assert covariance_matrix.shape == self.shape

    def _assert_ndarray(self, covariance_matrix):
        assert type(covariance_matrix) == np.ndarray

    def test(self):
        covariance_matrix = _generate_covariance(self.correlation_matrix, self.stds)
        self._assert_finite(covariance_matrix)
        self._assert_shape(covariance_matrix)
        self._assert_ndarray(covariance_matrix)

        
class Test_generate_directions(unittest.TestCase):
    """Test to verify that directions are generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    correlation_matrix : ndarray, shape (n_samples, n_samples) or (n_features, n_features)
        Signed correlation matrix from which the signs are extracted as direcitons.
    pairs : ndarray, (dimensions = 1, e.g. like list)
        The pairs of interest for which the directions are to be extraced.
    n : int
        Dimensions of the square block correlation matrix (n, n).
    m_blocks : int, default = 4
        The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 15
        self.m_blocks = 4
        self.correlation_matrix = _generate_square_blocks_matrix(self.n, self.m_blocks, r=1.0)
        self.pairs = _generate_pairs(self.correlation_matrix)

    def _assert_finite(self, directions):
        assert np.isfinite(directions).all() == True

    def _assert_shape(self, directions, pairs):
        assert directions.shape[0] == len(pairs)

    def _assert_ndarray(self, directions):
        assert type(directions) == np.ndarray
        
    def test(self):
        directions = _generate_directions(self.correlation_matrix, self.pairs)
        self._assert_finite(directions)
        self._assert_shape(directions, self.pairs)
        self._assert_ndarray(directions)

        
class Test_generate_stds(unittest.TestCase):
    """Test to verify that standard deviations are generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    n : int, default = 19
        Feature/sample dimensions of the matrix for which the standard deviations are computed.
    model : {'random', 'constant'}
        The type of model to generate standard deviations. Constant uses the `std_value`, whereas `random` samples from a uniform distribution between 0.1 and 2.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 19
        
    def _assert_finite(self, stds):
        assert np.isfinite(stds).all() == True

    def _assert_float(self, scaling_factor):
        assert type(scaling_factor) == float

    def _assert_shape(self, stds, n):
        assert stds.shape[0] == n

    def _assert_ndarray(self, stds):
        assert type(stds) == np.ndarray
        
    def test_random(self):
        stds, scaling_factor = _generate_stds(self.n, 'random', normalize=True)
        self._assert_finite(stds)
        self._assert_float(scaling_factor)
        self._assert_shape(stds, self.n)
        self._assert_ndarray(stds)
        
    def test_constant(self):
        stds, scaling_factor = _generate_stds(self.n, 'constant', normalize=True)
        self._assert_finite(stds)
        self._assert_float(scaling_factor)
        self._assert_shape(stds, self.n)
        self._assert_ndarray(stds)

    
class Test_generate_square_blocks_matrix(unittest.TestCase):
    """Test to verify that the square block matrices are generated correctly.
    
    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    n : int
        Dimensions of the square block matrix (n, n).
    shape :tuple of int, computed from `n` (no need to set)
        Shape of the square block matrix.
    m_blocks : int, default = 4
        Number of blocks in the correlation matix of features or samples that are varying together (with differences only in degree, direction and scale). Fewer blocks are better for bias recovery.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 17
        self.shape = (self.n, self.n)
        self.m_blocks = 4

    def _assert_finite(self, square_blocks_matrix):
        assert np.isfinite(square_blocks_matrix).all() == True

    def _assert_shape(self, square_blocks_matrix):
        assert square_blocks_matrix.shape == self.shape

    def _assert_ndarray(self, square_blocks_matrix):
        assert type(square_blocks_matrix) == np.ndarray
      
    def test(self):
        square_blocks_matrix = _generate_square_blocks_matrix(self.n, self.m_blocks)
        self._assert_finite(square_blocks_matrix)
        self._assert_shape(square_blocks_matrix)
        self._assert_ndarray(square_blocks_matrix)


class Test_generate_pairs(unittest.TestCase):
    """Test to verfiy that indicies of correlated pairs are generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    n : int
        Dimensions of the square block correlation matrix (n, n).
    correlation_matrix: ndarray, shape (n_features. n_features), computed from `n` (no need to set)
        Correlation matrix with a square block structure.
    m_blocks : int, default = 4
        The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 15
        self.m_blocks = 4
        self.correlation_matrix = _generate_square_blocks_matrix(self.n, self.m_blocks, r=1.0)
        
    def _assert_int(self, pairs):
        assert pairs.dtype == int
        
    def _assert_finite(self, pairs):
        assert np.isfinite(pairs).all() == True

    def _assert_shape(self, pairs):
        assert pairs.shape[1] == 2

    def _assert_ndarray(self, pairs):
        assert type(pairs) == np.ndarray

    def test(self):
        pairs = _generate_pairs(self.correlation_matrix)
        self._assert_finite(pairs)
        self._assert_shape(pairs)
        self._assert_ndarray(pairs)
        self._assert_int(pairs)


class Test_generate_matrix_normal_sample(unittest.TestCase):
    """Test to verify that the sample from the matrix variate normal distribution is generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    shape : tuple of int, (n_samples, n_features)
        Shape of the matrix.
    m_blocks : int
        The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.
    U : ndarray, shape (n_samples, n_samples)
        Covariance matrix among samples (rows).
    V : ndarray, shape (n_features, n_features)
        Covariance matrix among features (columns).
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.shape = (25, 35)
        self.m_blocks = 4
        self.correlation_matrix_U = _generate_square_blocks_matrix(self.shape[0], self.m_blocks, r=1.0)
        self.stds_U = _generate_stds(self.shape[0], 'random', normalize=False)[0]
        self.U = _generate_covariance(self.correlation_matrix_U, self.stds_U)
        self.correlation_matrix_V = _generate_square_blocks_matrix(self.shape[1], self.m_blocks, r=1.0)
        self.stds_V = _generate_stds(self.shape[1], 'random', normalize=False)[0]
        self.V = _generate_covariance(self.correlation_matrix_V, self.stds_V)
        
    def _assert_finite(self, sample):
        assert np.isfinite(sample).all() == True

    def _assert_shape(self, sample):
        assert sample.shape == self.shape

    def _assert_ndarray(self, sample):
        assert type(sample) == np.ndarray
        
    def test(self):
        self.sample = _generate_matrix_normal_sample(self.U, self.V)
        self._assert_finite(self.sample)
        self._assert_shape(self.sample)
        self._assert_ndarray(self.sample)

    
class TestRedundantSignal(unittest.TestCase):
    """Test to verify that all signal outputs are finite consistent ndarrays.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    shape : tuple of int, default = (50, 60)
        Shape of the output signal matrix in the form of (n_samples, n_features).
    m_blocks : int, default = 4
        Number of blocks in the correlation matix of features or samples that are varying together (with differences only in degree, direction and scale). Fewer blocks are better for bias recovery.
    correlation_strength : float, default = 1.0
        The strength of correlations between features or samples. Stronger correlations are better for bias recovery.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.shape = (50, 60)
        self.m_blocks = 4
        self.correlation_strength = 1.0
        
    def _assert_shape(self, signal):
        assert signal['X'].shape == self.shape

    def _assert_finite(self, signal):
        assert np.isfinite(signal['X']).all() == True

    def _assert_ndarray(self, signal):
        assert type(signal['X']) == np.ndarray

    def _assert_dict(self, signal):
        assert type(signal) == dict

    def test_constant(self):
        signal = RedundantSignal(self.shape, 'constant', self.m_blocks, self.correlation_strength, std_value=-1.5).generate()
        self._assert_dict(signal)
        self._assert_finite(signal)
        self._assert_ndarray(signal)
        self._assert_shape(signal)
      
    def test_random(self):
        signal = RedundantSignal(self.shape, 'random', self.m_blocks, self.correlation_strength).generate()
        self._assert_dict(signal)
        self._assert_finite(signal)
        self._assert_ndarray(signal)
        self._assert_shape(signal)

        
if __name__ == '__main__':
    unittest.main()



"""Redundant signal matrix tests.
"""
from __future__ import division, absolute_import

import unittest

import numpy as np

from bcn.redundant_signal import RedundantSignal, _generate_square_blocks_matrix, _generate_pairs, _generate_stds, _generate_directions, _generate_covariance, _generate_matrix_normal_sample


class Test_std_consistency(unittest.TestCase):
    """ Test the consistency of standard deviations.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.m_blocks = 10
        self.shape = (250, 250)
        
    def test(self):
        self.correlation_matrix_U = _generate_square_blocks_matrix(self.shape[0], self.m_blocks, r=1.0)
        self.stds_U, scaling_factor_sample = _generate_stds(self.shape[0], 'random', normalize=True)
        self.U = _generate_covariance(self.correlation_matrix_U, self.stds_U) # sample
        print 'trace U', np.trace(self.U)
        assert np.allclose(np.sum(self.stds_U**2), 1.0, rtol=1e-5, atol=1e-5)
        pairs_sample = _generate_pairs(self.correlation_matrix_U)
        
        self.correlation_matrix_V = _generate_square_blocks_matrix(self.shape[1], self.m_blocks, r=1.0)
        self.stds_V, scaling_factor_feature = _generate_stds(self.shape[1], 'random', normalize=True) 
        self.V = _generate_covariance(self.correlation_matrix_V, self.stds_V) # feature
        print 'trace V', np.trace(self.V)
        assert np.allclose(np.sum(self.stds_U**2), 1.0, rtol=1e-5, atol=1e-5)
        pairs_feature = _generate_pairs(self.correlation_matrix_V)
        
        temp = []
        for q in xrange(100):
            self.sample = _generate_matrix_normal_sample(self.U, self.V)
            temp.append(self.sample)
        self.sample = np.mean(temp, axis=0)
        print self.sample.shape
        sample_stds = np.std(self.sample, axis=1)
        feature_stds = np.std(self.sample, axis=0)

        A = (feature_stds[pairs_feature][:, 0] / feature_stds[pairs_feature][:, 1])[:4]
        B = (sample_stds[pairs_sample][:, 0] / sample_stds[pairs_sample][:, 1])[:4]
        true_A = (self.stds_V[pairs_feature][:, 0] / self.stds_V[pairs_feature][:, 1])[:4]
        true_B = (self.stds_U[pairs_sample][:, 0] / self.stds_U[pairs_sample][:, 1])[:4]

        assert np.allclose(A, true_A, rtol=1e-5, atol=1e-5)
        assert np.allclose(B, true_B, rtol=1e-5, atol=1e-5)
        
        print 'feature mean stds and raw', np.mean(feature_stds), np.mean(self.stds_V) # NOTE To get macht, should not normalize.
        print 'sample mean stds and raw', np.mean(sample_stds), np.mean(self.stds_U)
        print 'difference feature stds and raw', np.mean(feature_stds - self.stds_V)
        print 'difference sample stds and raw', np.mean(sample_stds - self.stds_U)
        
      
class Test_generate_covariance(unittest.TestCase):
    """Test to verify that covariances are generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    correlation_matrix : ndarray, shape (n_samples, n_samples) or (n_features, n_features)
        Correlation matrix on which the covariance matrix is based.
    stds : ndarray, (dimensions = 1, e.g. like list)
        Standard deviations which are used in combination with the correlation amtrix to generate the covariance matrix.
    n : int
        Dimensions of the square block correlation matrix (n, n).
    m_blocks : int, default = 4
        The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.
    shape : tuple of int, computed automatically as (n, n)
        Shape of the covariance matrix.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 15
        self.m_blocks = 4
        self.shape = (self.n, self.n)
        self.correlation_matrix = _generate_square_blocks_matrix(self.n, self.m_blocks, r=1.0)
        self.stds, self.scaling_factor = _generate_stds(self.n, 'random', normalize=True)
        self.covariance_matrix = _generate_covariance(self.correlation_matrix, self.stds)
        
    def _assert_finite(self, covariance_matrix):
        assert np.isfinite(covariance_matrix).all() == True

    def _assert_shape(self, covariance_matrix):
        assert covariance_matrix.shape == self.shape

    def _assert_ndarray(self, covariance_matrix):
        assert type(covariance_matrix) == np.ndarray

    def test(self):
        covariance_matrix = _generate_covariance(self.correlation_matrix, self.stds)
        self._assert_finite(covariance_matrix)
        self._assert_shape(covariance_matrix)
        self._assert_ndarray(covariance_matrix)

        
class Test_generate_directions(unittest.TestCase):
    """Test to verify that directions are generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    correlation_matrix : ndarray, shape (n_samples, n_samples) or (n_features, n_features)
        Signed correlation matrix from which the signs are extracted as direcitons.
    pairs : ndarray, (dimensions = 1, e.g. like list)
        The pairs of interest for which the directions are to be extraced.
    n : int
        Dimensions of the square block correlation matrix (n, n).
    m_blocks : int, default = 4
        The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 15
        self.m_blocks = 4
        self.correlation_matrix = _generate_square_blocks_matrix(self.n, self.m_blocks, r=1.0)
        self.pairs = _generate_pairs(self.correlation_matrix)

    def _assert_finite(self, directions):
        assert np.isfinite(directions).all() == True

    def _assert_shape(self, directions, pairs):
        assert directions.shape[0] == len(pairs)

    def _assert_ndarray(self, directions):
        assert type(directions) == np.ndarray
        
    def test(self):
        directions = _generate_directions(self.correlation_matrix, self.pairs)
        self._assert_finite(directions)
        self._assert_shape(directions, self.pairs)
        self._assert_ndarray(directions)

        
class Test_generate_stds(unittest.TestCase):
    """Test to verify that standard deviations are generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    n : int, default = 19
        Feature/sample dimensions of the matrix for which the standard deviations are computed.
    model : {'random', 'constant'}
        The type of model to generate standard deviations. Constant uses the `std_value`, whereas `random` samples from a uniform distribution between 0.1 and 2.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 19
        
    def _assert_finite(self, stds):
        assert np.isfinite(stds).all() == True

    def _assert_float(self, scaling_factor):
        assert type(scaling_factor) == float

    def _assert_shape(self, stds, n):
        assert stds.shape[0] == n

    def _assert_ndarray(self, stds):
        assert type(stds) == np.ndarray
        
    def test_random(self):
        stds, scaling_factor = _generate_stds(self.n, 'random', normalize=True)
        self._assert_finite(stds)
        self._assert_float(scaling_factor)
        self._assert_shape(stds, self.n)
        self._assert_ndarray(stds)
        
    def test_constant(self):
        stds, scaling_factor = _generate_stds(self.n, 'constant', normalize=True)
        self._assert_finite(stds)
        self._assert_float(scaling_factor)
        self._assert_shape(stds, self.n)
        self._assert_ndarray(stds)

    
class Test_generate_square_blocks_matrix(unittest.TestCase):
    """Test to verify that the square block matrices are generated correctly.
    
    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    n : int
        Dimensions of the square block matrix (n, n).
    shape :tuple of int, computed from `n` (no need to set)
        Shape of the square block matrix.
    m_blocks : int, default = 4
        Number of blocks in the correlation matix of features or samples that are varying together (with differences only in degree, direction and scale). Fewer blocks are better for bias recovery.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 17
        self.shape = (self.n, self.n)
        self.m_blocks = 4

    def _assert_finite(self, square_blocks_matrix):
        assert np.isfinite(square_blocks_matrix).all() == True

    def _assert_shape(self, square_blocks_matrix):
        assert square_blocks_matrix.shape == self.shape

    def _assert_ndarray(self, square_blocks_matrix):
        assert type(square_blocks_matrix) == np.ndarray
      
    def test(self):
        square_blocks_matrix = _generate_square_blocks_matrix(self.n, self.m_blocks)
        self._assert_finite(square_blocks_matrix)
        self._assert_shape(square_blocks_matrix)
        self._assert_ndarray(square_blocks_matrix)


class Test_generate_pairs(unittest.TestCase):
    """Test to verfiy that indicies of correlated pairs are generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    n : int
        Dimensions of the square block correlation matrix (n, n).
    correlation_matrix: ndarray, shape (n_features. n_features), computed from `n` (no need to set)
        Correlation matrix with a square block structure.
    m_blocks : int, default = 4
        The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.n = 15
        self.m_blocks = 4
        self.correlation_matrix = _generate_square_blocks_matrix(self.n, self.m_blocks, r=1.0)
        
    def _assert_int(self, pairs):
        assert pairs.dtype == int
        
    def _assert_finite(self, pairs):
        assert np.isfinite(pairs).all() == True

    def _assert_shape(self, pairs):
        assert pairs.shape[1] == 2

    def _assert_ndarray(self, pairs):
        assert type(pairs) == np.ndarray

    def test(self):
        pairs = _generate_pairs(self.correlation_matrix)
        self._assert_finite(pairs)
        self._assert_shape(pairs)
        self._assert_ndarray(pairs)
        self._assert_int(pairs)


class Test_generate_matrix_normal_sample(unittest.TestCase):
    """Test to verify that the sample from the matrix variate normal distribution is generated correctly.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    shape : tuple of int, (n_samples, n_features)
        Shape of the matrix.
    m_blocks : int
        The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.
    U : ndarray, shape (n_samples, n_samples)
        Covariance matrix among samples (rows).
    V : ndarray, shape (n_features, n_features)
        Covariance matrix among features (columns).
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.shape = (25, 35)
        self.m_blocks = 4
        self.correlation_matrix_U = _generate_square_blocks_matrix(self.shape[0], self.m_blocks, r=1.0)
        self.stds_U = _generate_stds(self.shape[0], 'random', normalize=False)[0]
        self.U = _generate_covariance(self.correlation_matrix_U, self.stds_U)
        self.correlation_matrix_V = _generate_square_blocks_matrix(self.shape[1], self.m_blocks, r=1.0)
        self.stds_V = _generate_stds(self.shape[1], 'random', normalize=False)[0]
        self.V = _generate_covariance(self.correlation_matrix_V, self.stds_V)
        
    def _assert_finite(self, sample):
        assert np.isfinite(sample).all() == True

    def _assert_shape(self, sample):
        assert sample.shape == self.shape

    def _assert_ndarray(self, sample):
        assert type(sample) == np.ndarray
        
    def test(self):
        self.sample = _generate_matrix_normal_sample(self.U, self.V)
        self._assert_finite(self.sample)
        self._assert_shape(self.sample)
        self._assert_ndarray(self.sample)

    
class TestRedundantSignal(unittest.TestCase):
    """Test to verify that all signal outputs are finite consistent ndarrays.

    Attributes
    ----------
    seed : int, default = 42
        Random seed of the whole test.
    shape : tuple of int, default = (50, 60)
        Shape of the output signal matrix in the form of (n_samples, n_features).
    m_blocks : int, default = 4
        Number of blocks in the correlation matix of features or samples that are varying together (with differences only in degree, direction and scale). Fewer blocks are better for bias recovery.
    correlation_strength : float, default = 1.0
        The strength of correlations between features or samples. Stronger correlations are better for bias recovery.
    """
    def setUp(self, seed=42):
        np.random.seed(seed)
        self.shape = (50, 60)
        self.m_blocks = 4
        self.correlation_strength = 1.0
        
    def _assert_shape(self, signal):
        assert signal['X'].shape == self.shape

    def _assert_finite(self, signal):
        assert np.isfinite(signal['X']).all() == True

    def _assert_ndarray(self, signal):
        assert type(signal['X']) == np.ndarray

    def _assert_dict(self, signal):
        assert type(signal) == dict

    def test_constant(self):
        signal = RedundantSignal(self.shape, 'constant', self.m_blocks, self.correlation_strength, std_value=-1.5).generate()
        self._assert_dict(signal)
        self._assert_finite(signal)
        self._assert_ndarray(signal)
        self._assert_shape(signal)
      
    def test_random(self):
        signal = RedundantSignal(self.shape, 'random', self.m_blocks, self.correlation_strength).generate()
        self._assert_dict(signal)
        self._assert_finite(signal)
        self._assert_ndarray(signal)
        self._assert_shape(signal)

        
if __name__ == '__main__':
    unittest.main()



Redundant signal matrix tests. Test the consistency of standard deviations. # sample # feature # NOTE To get macht, should not normalize. Test to verify that covariances are generated correctly.      Attributes     ----------     seed : int, default = 42         Random seed of the whole test.     correlation_matrix : ndarray, shape (n_samples, n_samples) or (n_features, n_features)         Correlation matrix on which the covariance matrix is based.     stds : ndarray, (dimensions = 1, e.g. like list)         Standard deviations which are used in combination with the correlation amtrix to generate the covariance matrix.     n : int         Dimensions of the square block correlation matrix (n, n).     m_blocks : int, default = 4         The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.     shape : tuple of int, computed automatically as (n, n)         Shape of the covariance matrix. Test to verify that directions are generated correctly.      Attributes     ----------     seed : int, default = 42         Random seed of the whole test.     correlation_matrix : ndarray, shape (n_samples, n_samples) or (n_features, n_features)         Signed correlation matrix from which the signs are extracted as direcitons.     pairs : ndarray, (dimensions = 1, e.g. like list)         The pairs of interest for which the directions are to be extraced.     n : int         Dimensions of the square block correlation matrix (n, n).     m_blocks : int, default = 4         The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`. Test to verify that standard deviations are generated correctly.      Attributes     ----------     seed : int, default = 42         Random seed of the whole test.     n : int, default = 19         Feature/sample dimensions of the matrix for which the standard deviations are computed.     model : {'random', 'constant'}         The type of model to generate standard deviations. Constant uses the `std_value`, whereas `random` samples from a uniform distribution between 0.1 and 2. Test to verify that the square block matrices are generated correctly.          Attributes     ----------     seed : int, default = 42         Random seed of the whole test.     n : int         Dimensions of the square block matrix (n, n).     shape :tuple of int, computed from `n` (no need to set)         Shape of the square block matrix.     m_blocks : int, default = 4         Number of blocks in the correlation matix of features or samples that are varying together (with differences only in degree, direction and scale). Fewer blocks are better for bias recovery. Test to verfiy that indicies of correlated pairs are generated correctly.      Attributes     ----------     seed : int, default = 42         Random seed of the whole test.     n : int         Dimensions of the square block correlation matrix (n, n).     correlation_matrix: ndarray, shape (n_features. n_features), computed from `n` (no need to set)         Correlation matrix with a square block structure.     m_blocks : int, default = 4         The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`. Test to verify that the sample from the matrix variate normal distribution is generated correctly.      Attributes     ----------     seed : int, default = 42         Random seed of the whole test.     shape : tuple of int, (n_samples, n_features)         Shape of the matrix.     m_blocks : int         The number of square blocks in the correlation matrix. Does not have to be an even fit into `n`.     U : ndarray, shape (n_samples, n_samples)         Covariance matrix among samples (rows).     V : ndarray, shape (n_features, n_features)         Covariance matrix among features (columns). Test to verify that all signal outputs are finite consistent ndarrays.      Attributes     ----------     seed : int, default = 42         Random seed of the whole test.     shape : tuple of int, default = (50, 60)         Shape of the output signal matrix in the form of (n_samples, n_features).     m_blocks : int, default = 4         Number of blocks in the correlation matix of features or samples that are varying together (with differences only in degree, direction and scale). Fewer blocks are better for bias recovery.     correlation_strength : float, default = 1.0         The strength of correlations between features or samples. Stronger correlations are better for bias recovery.