########################################
# The contents of this file are subject to the MLX PUBLIC LICENSE version
# 1.0 (the "License"); you may not use this file except in
# compliance with the License.
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
# the License for the specific language governing rights and limitations
# under the License.
# 
# The Original Source Code is "compClust", released 2003 September 03.
# 
# The Original Source Code was developed by the California Institute of
# Technology (Caltech).  Portions created by Caltech are Copyright (C)
# 2002-2003 California Institute of Technology. All Rights Reserved.
########################################

"""
pyPipe.py -c <command> <optional arguements>

        -c <command> or --command <commnad>: where command is a numeric or
                                             MLab function which operates
                                             on an array

        -i <filename> or --infile <filename>: where filename is input, default
                                              is stdin

        -n or --non-numeric : Don't mask the input date into a Numeric array.
                              Leave it as a python list

        -v or --verbose     : verbose output to stderr

        -s or --strip-output : strip the output of any python formating

        -f or --full-command : speciy the full python command including
                               note that the matrix will be data.
                               example on how to multiply a dataset by 10:
                               pyPipe.py -f -c "data*10"

    This tool constructs an Numeric array where each line is considered
    a row (seperated by whitespaces) and rows are seperated by newlines

    Note: Although this was originally written to expose the Numeric
    packages function to a convient command line pipe, the command is
    an arbitrary python command

A command line wrapper around Numeric and the MLab tools

Author:  Christopher Hart
Date  :  July 2001

"""

# non-standard libs

# only do these global inports to ease
# the amount of typeing on the command line
from  Numeric import *
from  MLab    import *

from compClust.util import Usage, WrapperUtil

try:
   from gracePlot import plot
   from gracePlot import histoPlot
except:
   pass

# standard python libs
import types
import sys
import string
import traceback
import string
import re
import os

def main(opts, args):

    # basic setup
    errorStream = sys.stderr
    useNumeric  = not (opts.has_key('-n') or opts.has_key('--non-numeric'))
    verbose     = (opts.has_key('-v') or opts.has_key('--verbose'))
    command     =  opts.get('-c', opts.get('--command', 'None'))
    stripOutput =  opts.has_key('-s') or opts.has_key('--strip-output')
    fullCommand =  opts.has_key('-f') or opts.has_key('--full-command')

    try:
        isAfunction = callable(eval(command))
    except:
        isAfunction = 0

    if opts.has_key('-h') or opts.has_key('--help'):
        Usage.showHelp(sys.argv[0], exit=1)

    if isAfunction or fullCommand :
        inputStreamName = opts.get('-i', opts.get('--infile'))
        if inputStreamName:
            inputStream = open(inputStreamName, 'r')
        else:
            inputStream = sys.stdin

        data = []
        if verbose:
            errorStream.write("Reading Data...")
        for line in inputStream.xreadlines():
            tokens = string.split(line)
            if useNumeric:
                try:
                    tokens = map(lambda x: float(x), tokens)
                except:
                    print "**Unable to mask all values to floats**"
                    print traceback.print_tb(sys.exc_traceback)
                    Usage.showHelp(sys.argv[0], exit=1)
            data.append(tokens)
        if verbose:
            sys.stderr.write("..Done\n")

        if useNumeric:
            try:
                data = array(data)
            except:
                print "**Unable to cast matrix into numeric array**"
                print traceback.print_tb(sys.exc_traceback)
                Usage.showHelp(sys.argv[0], exit=1)
            
        if not fullCommand:
            command = command+"(data)"
        try:
            if verbose:
                sys.stderr.write("Evaluating command: %s\n"%command)
            result = eval(command)
        except:
            print "**Command Couldn't be executed**"
            print traceback.print_tb(sys.exc_traceback)
            Usage.showHelp(sys.argv[0], exit=1)

            
        if stripOutput:

            if verbose:
                sys.stderr.write("Stripping python formatting tags (result dim = %i) \n"%len(shape(data)))

            if len(shape(result)) == 2:
                # for 2d arrays
                for row in result:
                    for element in row:
                        print "%3.2f\t"%element,
                    print
            elif len(shape(result)) == 1:
                # for 1d arrays
                for element in result:
                    print "%3.2f\t"%element,
                    
            elif len(shape(result)) == 0:
                print "%3.2\t"%result

            else:
                print "Unable to perform output stripping"

        else:
            print result

    else:
        print "invalid python command"
        Usage.showHelp(sys.argv[0], exit=1)
        
if __name__ == "__main__":

    opts, args = WrapperUtil.createOptTree('c:i:nvshf',['command=',
                                                        'infile=',
                                                        'non-numeric',
                                                        'verbose',
                                                        'strip-output',
                                                        'help',
                                                        'full-command'])
    main(opts, args)













