Question

Preventing the Gibbs phenomenon on a reverse FFT

i am currently filtering some data and ran into trouble, when filtering smaller frequencies from a large trend.The Reverse FFTs seem to have large spikes at the beginning and the ending. Here is the Data before and after filtering smaller frequencies.Before filteringAfter Filtering

I have looked into the mathematic phenomenon and it is called the Gibbs phenomenon. Is there a way around this to clear the data of some overlying frequencies without getting this effect. Or is there even a workaround to keep the spikes as small as possible.

Here is the code BTW:

fourier_transformation= np.fft.fft(Sensor_4)
frequencies = np.fft.fftfreq(len(time), d=1/Values_per_second) 
fourier_transformation[np.abs(frequencies) > 0.18] = 0
Sensor_4 = np.fft.ifft(fourier_transformation)
 3  61  3
1 Jan 1970

Solution

 1

Following the suggestion of Martin Brown's comment, the following code subtracts a ramp before FFT and adds it back after IFFT (I needed to make up my own values for Sensor_4, Values_per_second, and time, as the corresponding variables were missing in the question, so you might need to tune the parameters to match your actual signal):

import matplotlib.pyplot as plt
import numpy as np

# Create signal of `Sensor_4` (similar to question)
T = 600
Values_per_second = 100  # Just to have a value here
time = np.arange(0, T, 1/Values_per_second)
Sensor_4 = 2 * np.sin(.25 * (2 * np.pi * time / T)) - 2.25
Sensor_4 += .1 * np.sin(2 * np.pi * time * 0.18)

# Create ramp, as suggested in
# https://stackoverflow.com/questions/78788533#comment138912162_78788533
ramp = np.linspace(Sensor_4[0], Sensor_4[-1], len(Sensor_4))
# (1) Subtract ramp, (2) FFT, (3) filter, (4) IFFT, (5) add ramp back
fourier_transformation = np.fft.fft(Sensor_4 - ramp)  # (1, 2)
frequencies = np.fft.fftfreq(len(time), d=1/Values_per_second) 
fourier_transformation[np.abs(frequencies) > 0.18] = 0  # (3)
filtered = np.real(np.fft.ifft(fourier_transformation)) + ramp  # (4)

# Show result
ax1 = plt.subplot(121)
plt.plot(time, Sensor_4)
plt.subplot(122, sharey=ax1)
plt.plot(time, filtered)
plt.show()

Here is the result, before filtering (left) and after (right): result of filtering with ramp integration

2024-07-25
simon