Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is there a better way to define this simple hat function?

I am studying Fourier series and want to plot some of the results in Python. One common function to analyze using Fourier series is the hat function:

example plot here

The code below shows two different ways that I’ve coded the hat function. One uses numpy, the other uses a custom function hat(x,a,L) that I wrote. The parameter a represents the width of the hat, while L is the overall domain of the function from (-L,L).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I think that the function I wrote is more readable, but I doubt it’s as fast as the numpy piecewise function. But I think the numpy function is pretty ugly.

Is there a better way to write the hat function that is both more readable and fast?

import matplotlib.pyplot as plt
import numpy as np

# defining the hat function parameters, domain
L=-5
a=1
x=np.linspace(-L,L,100)

# using my hat function
y=hat(x,a,L)
plt.plot(x,y,'r')
plt.show()

# numpy hat function - piecewise
y=np.piecewise(x,
               [x<-a,(-a<x)&(x<0),x==0,(0<x)&(x<a),a<x],
               [0,lambda x:1+x,1,lambda x:1-x,0])
plt.plot(x,y,'r')
plt.show()

# hat function
def hat(x,a,L):
    y=x.copy()
    y[x<-a]=0
    y[(x>-a)&(x<0)]=1+x[(x>-a)&(x<0)]
    y[x==0]=1
    y[(x>0)&(x<a)]=1-x[(x>0)&(x<a)]
    y[x>a]=0
    return y

>Solution :

Here’s another solution

def hat(x,a,L):
    y=x.copy()
    y[(x<-a) | (x>a)]=0
    y[(x>-a)&(x<0)]+=1
    y[x==a]=1
    y[(x>0)&(x<a)]*=-1
    y[(x>0)&(x<a)]+=1
    return y

in your hat function, you have y[x==a]=1 but in the numpy version you have ,x==0, = ,1,, which are not the same.

_______

Something like this with symmetry

import matplotlib.pyplot as plt
import numpy as np

# defining the hat function parameters, domain
L=5
a=1
x=np.linspace(0,L,51)
# hat function
def hat(x,a,L):
    y=x.copy()
    y[x==0]=1
    y[(x > 0) & (x < a)] *= -1
    y[(x > 0) & (x < a)] += 1
    y[(x>=a)]=0
    y = np.hstack((y[-1:0:-1], y))
    return y
# using my hat function
y2=hat(x,a,L)

x=np.linspace(-L,L,101)
# numpy hat function - piecewise
y=np.piecewise(x,
               [x<-a,(-a<x)&(x<0),x==0,(0<x)&(x<a),a<x],
               [0,lambda x:1+x,1,lambda x:1-x,0])
plt.plot(x,y,'b')
plt.plot(x,y2,'r')
plt.show()

____

you could also use math to compute the y signal and then put some zeros

x=np.linspace(-L,L,101)
y3 = np.zeros(x.shape)
y3[(x>-a)&(x<a)] = -np.abs(x[(x>-a)&(x<a)]) + 1

but it really depend on your case

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading