#!/usr/bin/env python -u

""" Reads in observable data and performs a metric optimization by
minimizing the variance of the kinetic distribution """

import sys
import os
import glob

from optparse import OptionParser
import numpy as np

from euclid import markowitz 

def pad(obj,l):
    """ Pads an object with predeeding whitespace """
    n=len(str(obj))
    diff=l-n
    if diff < 0:
        print "Error in function pad(). String longer than pad: %s"%str(obj)
        sys.exit(1)
    else:
        return ' '*diff + str(obj)

def main(in_dir="Metrics", output="parameters.dat"):

    # Initialize
    obj = markowitz.objective()
    obj.add_metric_directory(in_dir)
    obj.initialize_default_weights()
    obj.get_Smat()

    # Optimize
    alphas, opt_params, new_obj = markowitz.quadratic_optimize(obj)
    param_names = np.array( obj.get_names() )

    # Write Output
    max_len = max( [len(nm) for nm in param_names] )

    print "\n --- Optimal Paramters ---\n"
    print "%s\t  Alpha \tOptimizer Output" % pad("Metric", max_len)
    print "%s\t--------\t----------------" % ("-" * max_len, )
    for i,param in enumerate(param_names):
        print "%s\t%f\t(%e)" % ( pad(param, max_len), alphas[i], opt_params[i])

    print "\nSaving alpha coefficients to: %s" % output
    np.savetxt(output, alphas)

    return


def parse():
    """ a helper function to contain all the optparse code """
    
    parser = OptionParser()
    parser.add_option("-d", "--directory", dest="dir", default="Observables",
                      help="Directory containing all observable data. Default: Observables")
    parser.add_option("-o", "--output", dest="output", default="parameters.dat",
                      help="""The filename to write the parameters to. Output is a flat text
                      file containing floats corresponding to each observable, in the order
                      in which they were input.""")
    (options, args) = parser.parse_args()

    # check that the output filename isn't taken
    if os.path.exists( options.output ):
        print "Error: %s already exists!" % options.output
        sys.exit(1)

    return options


if __name__ == "__main__":
    options = parse()
    main(in_dir=options.dir, output=options.output)