import numpy as np
import matplotlib.pyplot as plt

% matplotlib inline

"""
Explanation: Test: Error of the median filter with different wave number, with higher sample rate (2015.10.14. DW)
End of explanation
"""


def ErrorPlot( waveNumber,windowLength ):
        data = np.fromfunction( lambda x: np.sin((x-windowLength / 2)/1024 * 2 * np.pi * waveNumber), (1024 + windowLength / 2, ) )    #creating an array with a sine wave
        datafiltered = medianFilter(data, windowLength)  #calculate the filtered wave with the medianFiltered function
        data = data[ windowLength / 2 : - windowLength ] # slice the data array to synchronize both waves
        datafiltered = datafiltered[ : len(data) ]       # cut the filtered wave to the same length as the data wave
        error = ErrorRate(data,datafiltered,windowLength,waveNumber) #calculate the error with the ErrorRate function
        plt.axis([0, y + 1, 0, 1.2])
        plt.xlabel('Wave number', fontsize = 20)
        plt.ylabel('Error rate', fontsize = 20)
        plt.scatter(*error)

def ErrorRate(data,datafiltered,windowLength, waveNumber):
    errorrate = data-datafiltered  #calculate the difference between the sine wave and the filtered wave
    error = [] #creating a list and save the error rate with the matching wavenumber in it 
    errorrate = np.abs(errorrate)
    error.append([waveNumber ,np.mean(errorrate)])# fill the list with the errorrate and corresponding wave number
    error = zip(*error) #zip the error ([1,1],[2,2],[3,3]) = ([1,2,3],[1,2,3])
    return error

def medianFilter( data, windowLength ): 
    if (windowLength < len(data)and data.ndim == 1):
        tempret = np.zeros(len(data)-windowLength+1)  # creating an array where the filtered values will be saved in
        if windowLength % 2 ==0:                      # check if the window length is odd or even because with even window length we get an unsynchrone filtered wave 
            for c in range(0, len(tempret)):
                tempret[c] = np.median( data[ c : c + windowLength +1 ] ) # write the values of the median filtered wave in tempret, calculate the median of all values in the window
            return tempret
        else:
            for c in range(0, len(tempret)):
                tempret[c] = np.median( data[ c : c + windowLength ] )
            return tempret
    else:
         raise ValueError("windowLength must be smaller than len(data) and data must be a 1D array")

def medianSinPlot( waveNumber, windowLength ):
    data = np.fromfunction( lambda x: np.sin((x-windowLength / 2)/1024 * 2 * np.pi * waveNumber), (1024 + windowLength / 2, ) )    #creating an array with a sine wave
    datafiltered = medianFilter(data, windowLength)  #calculate the filtered wave with the medianFiltered function
    data = data[ windowLength / 2 : -windowLength  ] # slice the data array to synchronize both waves
    datafiltered = datafiltered[ : len(data) ]       # cut the filtered wave to the same length as the data wave
    plt.plot( data )
    plt.plot( datafiltered )
    plt.plot( data-datafiltered ) 

"""
Explanation: Testing with more samples ( now 1024, before 128)
Functions
End of explanation
"""


fig = plt.figure()
for y in range (0,40):
    ErrorPlot(y,128)

"""
Explanation: Plots
End of explanation
"""


fig = plt.figure(1, figsize=(15,3))
medianSinPlot(15,128)
plt.title('Wave number 15')
fig = plt.figure(2,figsize=(15,3)) 
medianSinPlot(16,128)
plt.title('Wave number 16')
fig = plt.figure(3,figsize=(15,3)) 
medianSinPlot(17,128)
plt.title('Wave number 17')

fig = plt.figure(1, figsize=(15,3))
medianSinPlot(31,128)
plt.title('Wave number 31')
fig = plt.figure(2,figsize=(15,3)) 
medianSinPlot(32,128)
plt.title('Wave number 32')
fig = plt.figure(3,figsize=(15,3)) 
medianSinPlot(33,128)
plt.title('Wave number 33')

"""
Explanation: With more samples the error rate at wave number 16 and 32 is no longer lower then expected.
End of explanation
"""


