'''
Created on Aug 17, 2011
Modified on Aug 20, 2012
@author: Dilum Bandara
@version: 0.1
@license: Apache License v2.0

   Copyright 2012 H. M. N. Dilum Bandara and Anura P. Jayasumana, Colorado State
   University

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
'''


'''
Break time series based on the difference between two window values
Hamming filer is used to as the windowing function
'''

import sys
import math

if len(sys.argv) != 5:
    print 'Command format: python  WinodwBasedFilter.py <input_file> <window_size> <threshold> <minSegment>'
    sys.exit(0)

fIn = sys.argv[1]
wSize = int(sys.argv[2]) #Window size
halfWSize = wSize/2 + 1
threshold = float(sys.argv[3]) #Threshold to apply when selecting a change
minSegSize = int(sys.argv[4]) #Minimum segment size in terms of samples
fOut = 'partitions.txt'


#Read data
data = []
fdIn = open(fIn, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    #for i in range(len(tmpLine)):
    for i in range(len(tmpLine) - 1):
        tmpLine[i] = float(tmpLine[i])
    #data.append(tmpLine)
    data.append(tmpLine[:-1])
fdIn.close()
N = len(data[0])
t = len(data)
print 'No of nodes', N
print 'No of samples/node', t


#Create coefficients of hamming filter
filter = []
w = wSize - 1
for i in range(wSize):
    filter.append(0.54 - 0.46 * math.cos(2 * math.pi * i/w))
w1st = filter[0:halfWSize]; #1st half of window
w2nd = filter[(halfWSize - 1):wSize]; #2nd half of window

tmpSum = sum(w1st)
for i in range(len(w1st)): #Normalize
    w1st[i] = w1st[i]/tmpSum
    w2nd[i] = w2nd[i]/tmpSum

parti = [] #Partitions
for i in range(N):
    diff = [] #Differences
    for j in range(t - wSize):
        a = 0.0
        b = 0.0
        for k in range(halfWSize):
            #print i, j, k
            a += data[j + k][i] * w1st[k] 
            b += data[j + k + halfWSize][i] * w2nd[k]
        diff.append([j + halfWSize, abs(a - b)]) #Absolute value

    #fdOut2 = open('tmp2.txt', 'w') #Dump differences
    #for kk in diff:
    #    fdOut2.write(str(kk[0]) + '\t' + str(kk[1])+ '\n')
    #fdOut2.close()

    #Apply threshold
    maxValue = -1
    maxIdx = -1
    tmpParti = []
    for m in range(len(diff)):
        if diff[m][1] > threshold:
            if diff[m][1] > maxValue: #Find local maximum
                maxValue = diff[m][1]
                maxIdx = m + halfWSize
        else:
            if maxValue > -1:
                tmpParti.append(maxIdx)
                maxValue = -1
                maxIdx = -1
    tmpParti.append(t) #No partitions break at end
    selParti = [tmpParti[0]] #Pick subset of partitions that are spaced at least minSegSize
    for k in range(1, len(tmpParti)):
        if tmpParti[k] - selParti[-1] >= minSegSize:
            selParti.append(tmpParti[k])
    if selParti[-1] != t: selParti.append(t) #End must always be there
    parti.append(selParti)

#Dump to file
fdOut = open(fOut, 'w')
for i in parti:
    for j in range(len(i)):
        if j != len(i) - 1: fdOut.write(str(i[j]) + '\t')
        else: fdOut.write(str(i[j]) + '\n')
fdOut.close()
