#--------------------------------------------------------------------------------------
# Module containing methods to perform analytics on a numpy array
# slice():     takes a 2dim regular array, and returns a row or col numpy array slice  
# transpose(): takes a 2dim regular array, and transpose it x/y becomes y/x
# normalize(): takes a 1dim numpy array, and eliminates bad/no data   
# Methods are: mode()
# numpy has built-in:  size,sum(),average(),median(),min(),max(),range ptp(),std()
#--------------------------------------------------------------------------------------
import numpy as np

#--------------------------------------------------------------------------------
# normalize: cleanup a regular array by eliminate all the bad/no data 
#            return a "numpy" array            
#--------------------------------------------------------------------------------
def normalize(array):
    array2 = []                                         #create new clean array

    for col in array:                                   #loop through all columns                  
        try:                                        
            num = float(col)                            #convert string to number
            array2.append(num)                          #add to new clean array
        except:
            pass                                        #do nothing (no op)   

    array3 = np.array(array2)                           #convert to a numpy array
    return array3;                              
                         
#--------------------------------------------------------------------------------
# mode: compute the mode of a numpy array
#       stats.mode() returns an array. [0] is a single mode, 
#                                      [1] number of occurrences for that mode
#--------------------------------------------------------------------------------
def mode(array):
    from scipy import stats    
                  
    modeArr = stats.mode(array)     #[0] the mode (a single mode), 
                                    #[1] the number of occurrences for that mode
    return modeArr[0]                              

#--------------------------------------------------------------------------------
# toString: Returns the array as well as all the analytic computations 
#--------------------------------------------------------------------------------
def toString(array):
    data  = "Data points: "   + str( array )
    data += "\nCount......: " + str( array.size) 
    data += "\nSum........: " + str( np.sum(array)) 
    data += "\nAverage....: " + str( np.average(array)) 
    data += "\nMedian.....: " + str( np.median(array)) 
    data += "\nMode.......: " + str( mode(array)) 
    data += "\nMinimum....: " + str( np.min(array)) 
    data += "\nMaximum....: " + str( np.max(array)) 
    data += "\nRange......: " + str( np.ptp(array)) 
    data += "\nStd.Dev....: " + str( np.std(array)) 
    return data;                              

#--------------------------------------------------------------------------------
# slice: Takes  a 2 dimensional array, slice type (row/col/all), and index
#        Return a single dimension array for that row or column or all cells
#--------------------------------------------------------------------------------
def slice(array2dim, type, idx=0):
    array = np.array([]);                               #create a new numpy array

    if (type =="row"):                                  #ROW slice
        array = array2dim[idx]                          #take a row slice

    if (type =="col"):                                  #COL slice
        obj   = zip(*array2dim)                         #transpose it, returns an object
        array = list(obj)                               #turn the object into a list                             
        array = array[idx] 

    if (type =="all"):                                  #ALL slice (turn a 2dim array to 1 dim)
        array = np.array(array2dim)                     #convert to 2dim numpy array
        array = array.flatten()                         #flattend the array into 1dim                            
    
    return array;

#--------------------------------------------------------------------------------
# transpose: Transpose a 2 dimensional array, x/y dimension become y/x dimension
#            Return a 2 dimensional transposed array
#--------------------------------------------------------------------------------
def transpose(array2dim):

    obj    = zip(*array2dim)                            #transpose 2dim array, returns an object   
    array2 = list(obj)                                  #turn the object to an array

    return array2;

#--------------------------------------------------------------------------------