Search code examples
pythonsignalsfilteringfftifft

Filtering signal frequency in Python


I tried to filter some signal with fft. The signal I am working on is quite complicated and im not really experienced in this topic. That's why I created a simple sin wave 3Hz and tried to cut off the 3 Hz.

and so far, so good

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fftfreq, irfft, rfft

t = np.linspace(0, 2*np.pi, 1000, endpoint=True)
f = 3.0 # Frequency in Hz
A = 100.0 # Amplitude in Unit
s = A * np.sin(2*np.pi*f*t) # Signal
dt = t[1] - t[0] # Sample Time

W = fftfreq(s.size, d=dt)
f_signal = rfft(s)

cut_f_signal = f_signal.copy()
cut_f_signal[(np.abs(W)>3)] = 0 # cut signal above 3Hz

cs = irfft(cut_f_signal)

fig = plt.figure(figsize=(10,5))
plt.plot(s)
plt.plot(cs)

What i expected expected output

What i got Result

I don't really know where the noise is coming from. I think it is some basic stuff, but i dont get it. Can someone explain to to me?

Edit

Just further information

Frequency

yf = fft(s)
N = s.size
xf = np.linspace(0, fa/2, N/2, endpoint=True)
fig, ax = plt.subplots()
ax.plot(xf,(2.0/N * np.abs(yf[:N//2])))
plt.xlabel('Frequency ($Hz$)')
plt.ylabel('Amplitude ($Unit$)')
plt.show()

enter image description here


Solution

  • You could change the way you create your signal and use a sample frequency:

    fs = 1000
    t = np.linspace(0, 1000 / fs, 1000, endpoint=False) # 1000 samples
    f = 3.0 # Frequency in Hz
    A = 100.0 # Amplitude in Unit
    s = A * np.sin(2*np.pi*f*t) # Signal
    dt = 1/fs
    

    And here the whole code:

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.fftpack import fftfreq, irfft, rfft
    
    fs = 1000
    t = np.linspace(0, 1000 / fs, 1000, endpoint=False)
    f = 3.0 # Frequency in Hz
    A = 100.0 # Amplitude in Unit
    s = A * np.sin(2*np.pi*f*t) # Signal
    dt = 1/fs
    
    W = fftfreq(s.size, d=dt)
    f_signal = rfft(s)
    
    cut_f_signal = f_signal.copy()
    cut_f_signal[(np.abs(W)>3)] = 0 # cut signal above 3Hz
    
    cs = irfft(cut_f_signal)
    
    fig = plt.figure(figsize=(10,5))
    plt.plot(s)
    plt.plot(cs)
    

    And with f = 3.0 Hz and (np.abs(W) >= 3): enter image description here

    And with f = 1.0 Hz: enter image description here