from pylab import array, eig, diagflat, dot, sqrt, randn, tile, \
        plot, subplot, axis, figure, clf, show

# The used mu (mean vector) and cov (covariance matrix).
mu = array([[3],
            [4],
            [5],
            [6]])

cov  = array(
    [[ 3.01602775,  1.02746769, -3.60224613, -2.08792829],
     [ 1.02746769,  5.65146472, -3.98616664,  0.48723704],
     [-3.60224613, -3.98616664, 13.04508284, -1.59255406],
     [-2.08792829,  0.48723704, -1.59255406,  8.28742469]])

# Samples is the constant `N' which is the total amount of numbers to generate
# according to the normal distribution.
samples = 1000
vector_size = 4

def dataset(samples):
    """Generate a dataset, consisting of a soecified number of random vectors."""
    # The covariance matrix is used to transform the generated dataset into a
    # multivariant normal distribution dataset.
    d, U = eig(cov)
    L = diagflat(d)
    A = dot(U, sqrt(L))
    X = randn(vector_size, samples)
    return dot(A,X) + tile(mu, samples)

if __name__ == '__main__':
    # Create a n*n grid of subplots and generate a new dataset.
    figure(vector_size**2)
    clf()
    Y = dataset(samples)
    for i in range(vector_size):
        for j in range(vector_size):
            # Skip the diagonal subplots since those are irrelevant.
            if i != j:
                subplot(vector_size, vector_size, (i + 1) + j * vector_size)
                plot(Y[i], Y[j], 'x')
                axis('equal')
    show()
