import argparse
import ast
import configparser

import numpy as np

KEYS = ['mean', 'cov', 'size']


def main(config_file, output_file):
    # Read config
    config = configparser.ConfigParser()
    config.read_file(config_file)

    # For each section generate points
    data = []
    for s in config.sections():
        # Read configuration
        mean = ast.literal_eval(config[s]['mean'])
        cov = ast.literal_eval(config[s]['cov'])
        size = ast.literal_eval(config[s]['size'])

        # Is multivariate?
        if isinstance(mean, list):
            data.append(np.random.multivariate_normal(mean, cov, size))
        else:
            data.append(np.transpose([np.random.normal(mean, cov, size)]))

    # Close configuration file
    config_file.close()

    # Save data
    np.save(output_file, data)

    # Close output file
    output_file.close()


def is_valid_config(string):
    # Check if file exists and is readable
    file = argparse.FileType('r')(string)

    # Check if file is a configuration file
    config = configparser.ConfigParser()
    try:
        config.read_file(file)
    except configparser.Error as e:
        raise argparse.ArgumentTypeError(e.message)

    # Check if file contains mandatory keys
    for s in config.sections():
        keys = list(config[s].keys())
        if not np.intersect1d(keys, KEYS).size is len(KEYS):
            message = "missing mandatory keys in section '%s'"
            raise argparse.ArgumentTypeError(message % s)

    # Move to the beginning of a file
    file.seek(0, 0)
    return file


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Generate multivariate normal random data.')
    parser.add_argument('config', metavar='config-file', type=is_valid_config,
                        help='a data configuration file')
    parser.add_argument('output', metavar='output-file', type=argparse.FileType('wb'),
                        help='an output data file')

    args = parser.parse_args()
    main(args.config, args.output)

@@ -59,16 +59,48 @@
 py as np
+%0Afrom scipy.stats import wishart
 %0A%0AKEYS =
@@ -125,16 +125,47 @@
 size'%5D%0A%0A
+CLUSTER_DIM_RANGE = %5B50, 150%5D%0A%0A
 %0Adef mai
@@ -190,18 +190,766 @@
 put_file
-):
+, random=False, k=20, d=2):%0A    if random:%0A        # Mean hyper-parameters%0A        mean = np.zeros(d)%0A        cov = np.eye(d) * k * 8%0A        scale = np.eye(d)%0A%0A        # Define config%0A        config = configparser.ConfigParser()%0A%0A        for i in range(k):%0A            config%5B'c%25d' %25 i%5D = %7B%7D%0A            cluster_config = config%5B'c%25d' %25 i%5D%0A            cluster_config%5B'mean'%5D = str(np.random.multivariate_normal(mean, cov, 1)%5B0%5D.tolist())%0A            cluster_config%5B'cov'%5D = str(wishart.rvs(d + 1, scale).tolist())%0A            cluster_config%5B'size'%5D = str(np.random.randint(CLUSTER_DIM_RANGE%5B0%5D, CLUSTER_DIM_RANGE%5B1%5D))%0A%0A        # Write config%0A        config.write(config_file)%0A%0A        # Move to the beginning of a file%0A        config_file.seek(0, 0)%0A
 %0A    # R
@@ -1742,20 +1742,21 @@
  and is 
-read
+write
 able%0A   
@@ -1782,17 +1782,18 @@
 leType('
-r
+w+
 ')(strin
@@ -2779,16 +2779,454 @@
 a file')
+%0A    parser.add_argument('-k, --clusters', dest='k', type=int,%0A                        help='the number of clusters (default: 10)')%0A    parser.add_argument('-d, --dimension', dest='d', type=int,%0A                        help='the data dimension (default: 2)')%0A    parser.add_argument('-r, --random', dest='random', action='store_true',%0A                        help='randomly generate data')%0A    parser.set_defaults(k=10, d=2, random=False)
 %0A%0A    ar
@@ -3283,10 +3283,31 @@
 s.output
+, args.random, args.k
 )%0A

Add random clusters generator.