## L416_x

'''
Haar wavelets algorithms: continued.
'''
from math import *

def trend(f):
    r2 = sqrt(2)
    N = len(f)
    J = range(N//2)
    return [(f[2*j]+f[2*j+1])/r2 for j in J]

def fluct(f):
    r2 = sqrt(2)
    N = len(f)
    J = range(N//2)
    return [(f[2*j]-f[2*j+1])/r2 for j in J]

def haar(f,r=1):
    if r==0: return f
    if r==1: return(trend(f)+fluct(f))
    N = len(f); m = N // 2**(r-1)
    h = haar(f,r-1); a = h[:m]
    return trend(a) + fluct(a) + h[m:]

def energy(f):
    return sum(t**2 for t in f)

# High level trend and fluctuation functions
def trend(f,r=1): 
    if r == 0:
        return f
    N = len(f)
    if N % 2**r :
        return 'Trend: %d is not divisible by 2^%d ' % N, r
    r2 = sqrt(2.)
    while r  >= 1:
        N = N // 2
        f = [(f[2*j] + f[2*j+1])/r2 for j in range(N)]
        r -= 1
    return f

def fluct(f,r=1):
    if r == 0:
        return [0]*len(f)
    if len(f) % 2 ** r:
        return 'Fluct: %d is not divisible by 2^%d'
    a = trend(f, r-1)
    N = len(a) // 2
    r2 = sqrt(2.)
    r2 = sqrt(2.)
    return [(a[2*j] - a[2*j+1])/r2 for j in range(N)]

# Iterative form of high level Haar transform
def HaarT(f,r=1):
    if r == 0:
        return f
    N = len(f)
    a = list(f)
    h = []

    if N % 2**r:
        return 'HaarTransform: pinch'
    N = N // 2 ** r
    while len(a)> N:
        d = fluct(a)
        h = d + h
        a = trend(a)
    return a + h

def f(l):
    return [sin(1/cos(x)) for x in l] 

   
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0.0, 100, 0.05)
for i in range(0,4):
    print('Energy of Haar Transform of level %d: %.6f' 
            %  (i, energy(HaarT(f(x),i))))

plt.close('all')
fig = plt.figure('Haar transformations')
plt.subplot(4,1,4)
colors = ['r-', 'g-', 'b-', 'y-']
for i in range(0,4):
    plt.subplot(4, 1, i+1)
    plt.plot(HaarT(f(x), i), colors[i], lw=1)
plt.show()

