import sys
import os
from common import PostProcess, update_metrics_in_report_json
from common import read_limits, check_limits_and_add_to_report_json
import math
import numpy as np
from scipy.io import loadmat
import xml.etree.ElementTree as ET
from xml.etree import ElementTree
from xml.etree.ElementTree import Element
from xml.etree.ElementTree import SubElement
import random
import glob
import shutil

ftable = open('result.html', 'w')


class postprocess:

    def __init__(self):
        self.stuff = {}

# gets array of data wanted
# parameters: result_mat[0], string of the data name
# returns the data in an array
    def data_array(self, result, name):
        data = result[name]
        #data_arr = np.array(data)
        return data
    
# prints array of data wanted
# parameters: result_mat[0], string of the data name
# returns the data in an array
    def print_data(self, result, name):
        data = self.data_array(result, name)
        print 'name of data: '
        print name
        print 'here is the data: (with index)'
        print '[' ,
        for i in xrange(data.size-1):
            print str(i) + ':', str(data[i]) + ',',
        print str(i+1) + ':', str(data[i+1]) + ']'
        return data
    
# gets array of time
# parameter: result_mat[0]
# returns the time/time intervals in an array
    def time_array(self, result):
        time = result['time']
        
        return time 
    
# prints array of time
# parameter: result_mat[0]
# returns the time/time intervals in an array
    def print_time(self, result):
        time = time_array(self, result)
        print 'here are time intervals:', time
    
        return time 

# get an array between 2 values
# parameters: result_mat[0], name of the data, 2 values
# returns the "shortened" array
    def short_array(self, result, name, val1, val2):
        array = []
        data = result[name]
        for i in range(val1, val2):
            array.append(data[i])
        new_array = np.array(array)
        return new_array
        
# plot of data and time
# parameters: result_mat[0], string of the data name
# returns the data and time in an array
    def plot(self, result, name):
        data = self.data_array(self, result, name)
        time = self.time_array(self, result)

        return data, time

# get data based on time value
# parameters: time value, name of data, time data, result_mat[0]
# returns the data and the index of the data
    def get_data(self, time_val, name, time, result):
        i = 0
        while time[i] < time_val and i in xrange(time.size-1):
            i += 1
        data_arr = self.data_array(result, name)   
        if time[i-1] != time_val:
            cur = data_arr[i-1]
            next = data_arr[i]
            data = time[i-1] / ((time[i-1]+time[i])/2) * (next-cur) + cur
        else:
            data = data_arr[i-1]
        
        return data, i
                
# get time based on data value
    def get_time(self, data):
        pass
        
# last value
# parameter: result_mat[0]
# returns the last value
    def last_value(self, data):
        result = data[-1]
    
        return result

# maximum
# parameters: data array
# returns the result in an array
    def global_max(self, data):
        result = data.max()
    
        return result
    
# time of max
# parameters: data array
# returns the time at where the max is
    def global_max_time(self, data, time_arr):
        index = data.argmax()
        time = time_arr[index]  
    
        return time
    
# minimum
# parameters: data array
# returns the result in an array
    def global_min(self, data):
        result = data.min()
    
        return result
    
# time of min
# parameters: data array, time array
# returns the time at where the min is
    def global_min_time(self, data, time_arr):
        index = data.argmin()
        time = time_arr[index]   
    
        return time

# standard deviation
# parameters: data array
# returns the standard deviation of data
    def std_dev(self, data):
        stddev = data.std()
    
        return stddev

# variance
# parameters: data array
# returns the variance of data
    def variance(self, data):
        variance = data.var()
    
        return variance
    
# sum
# parameters: data array
# returns the sum of data
    def sum_value(self, data):
        result = data.sum()
    
        return result
    
# mean
# parameters: data array
# returns the mean of data
    def mean(self, data):
        result = np.mean(data, dtype=np.float64)
    
        return result
 
# integral
# parameters: data array, time array
# returns the area under the curve of data
    def integrate(self, data, time):
        sum = 0
        next = data[0]
        next_t = time[0]
        for i in xrange(data.size):
            cur = next
            next = data[i]
            cur_t = next_t
            next_t = time[i]
            height = (next + cur) / 2
            interval = next_t - cur_t
            sum = sum + (height * interval)
    
        return sum

# minimums
# parameters: data array
# returns the minimums of data
    def minimums(self, data):
        min = []
        prev = 0
        cur = 0
        next = data[0]
        for i in xrange(data.size):
            if cur < prev and cur <= next:
                min.append(cur)     
            prev = cur
            cur = next
            next = data[++i]
        minimum = np.array(min)
        
        return minimum
        
# maximums
# parameters: data array
# returns the maximums of data
    def maximums(self, data):
        max = []
        prev = 0
        cur = 0
        next = data[0]
        for i in xrange(data.size):
            if cur >= prev and cur > next:
                max.append(cur)        
            prev = cur
            cur = next
            next = data[++i]  
        maximum = np.array(max)
        
        return maximum

# time of positive to negative roots
# parameters: data array, time array
# returns time of the roots from positive to negative of data
    def pos_neg(self, data, time_arr):
        time = []
        tolerance = 0.00000015
        next = -1
        for i in xrange(data.size):
            cur = next
            next = data[i]
            if cur > 0+tolerance and next <= 0+tolerance:
                if cur != 0:
                    cur_t = time_arr[i-1]
                    next_t = time_arr[i]
                    time.append((cur / (cur+next)/2) * (next_t-cur_t) + cur_t)
                else:
                    time.append(time_arr[i-1])
        timing = np.array(time)
        
        return timing

# time of negative to positive roots
# parameters: data array, time array
# returns time of the roots from negative to positive of data
    def neg_pos(self, data, time_arr):
        time = [] 
        tolerance = 0.00000015
        next = 1
        for i in xrange(data.size):
            cur = next
            next = data[i]
            if cur <= 0+tolerance and next > 0+tolerance:
                if cur != 0:
                    cur_t = time_arr[i-1]
                    next_t = time_arr[i]
                    time.append(cur / ((cur+next)/2) * (next_t-cur_t) + cur_t)