Comments (4)
Instead of doing forward backward you can just do a Fourier Transform of the signal because you have your signal completely. Manipulate the frequency spectrum and then transform it back. That will give you the theoretically best result.
This IIR filter here is a causal filter where samples trickle in and the future is not known. It's not MATLAB and not Python which both do post processing. This is realtime processing where the length of the sequence is unknown. It's actually weird that in Python there is an lfilter and filtfilt (lfilter is the actual filter and MATLAB is here correct but still processes arrays as a postprocessing program).
Please have a look at the humble Fourier Transform because that's what you want if you (post-) process a whole recording.
I've made a video about it (part of my class):
https://youtu.be/FaRs4YEO7Zg
Best,
/Bernd
from iirj.
Thank you, spectrum-based filtering is indeed a cleaner way to do it, you're right.
However, I can think of a couple of reasons why forward-backward filtering could be useful too.
Firstly, the performance of forward-backard IIR filtering seems to be better. (If I'm not mistaken, the complexity of the FFT is O(n*log(n))
, whereas the forward-backward IIR would be O(n)
.)
Here is a quick timing result comparison (low-pass Butterworth filter, order 12) using Scipy on a larger signal:
IIR forward-backward time: 17.5987132
Spectrum filtering time: 30.1460402
(Those IIR timings get better if we accept lower order filters.)
Secondly, the results seem to differ more widely at the start/end of the signal. The sosfiltfilt
output is a closer match to the start and end values of the original signal. This may have something to do with the way sosfiltfilt
pads and computes the initial values.
(Maybe the people who implemented filtfilt
in Matlab and Scipy had other use cases too, I'm not sure.)
import timeit
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
def sos_lowpass_filter(x, fs, high_cutoff_freq, order=12):
sos = signal.butter(order, high_cutoff_freq / (fs / 2.0), 'lowpass', output='sos')
y = signal.sosfiltfilt(sos, x)
return y
def fft_ifft(x):
fft_size = len(x)
tmp = np.fft.fft(x, n=fft_size)
y = np.fft.ifft(tmp)
# Remove imaginary part due to imprecisions
return np.real(y)
def fft_lowpass_filter(x, fs, high_cutoff_freq):
fft_size = len(x)
high_cutoff_idx = int(high_cutoff_freq * float(fft_size) / float(fs))
tmp = np.fft.fft(x, n=fft_size)
tmp[high_cutoff_idx:fft_size-high_cutoff_idx+1] = 0
y = np.fft.ifft(tmp)
# Remove imaginary part due to imprecisions
return np.real(y)
# Timing comparison between sosfiltfilt and spectrum-based filtering
t = np.linspace(0.0, 60.0, num=60*44100, endpoint=False)
x = np.random.randn(len(t))
def sosfiltfilt_test():
return sos_lowpass_filter(x, 44100.0, 7500.0)
def fft_filter_test():
return fft_lowpass_filter(x, 44100.0, 7500.0)
t1 = timeit.timeit("sosfiltfilt_test()", number=50, setup="from __main__ import sosfiltfilt_test")
print "IIR forward-backward time: %s" % (t1,)
t2 = timeit.timeit("fft_filter_test()", number=50, setup="from __main__ import fft_filter_test")
print "Spectrum filtering time: %s" % (t2,)
# Sample data output (lfilter doc sample data)
t = np.linspace(-1, 1, 201)
x = (np.sin(2*np.pi*0.75*t*(1-t) + 2.1) +
0.1*np.sin(2*np.pi*1.25*t + 1) +
0.18*np.cos(2*np.pi*3.85*t))
x = x + np.random.randn(len(t)) * 0.08
x2 = fft_ifft(x)
y1 = sos_lowpass_filter(x, 2.0, 0.05)
y2 = fft_lowpass_filter(x, 2.0, 0.05)
plt.figure()
plt.plot(t, x, 'b', alpha=0.75, label='Signal')
plt.plot(t, x2, 'k.', label='FFT -> IFFT')
plt.plot(t, y1, 'm', label='Butterworth sosfiltfilt')
plt.plot(t, y2, 'g', label='FFT -> Filter -> IFFT')
plt.legend()
plt.show()
from iirj.
Obviously IIR filters have a certain settling time. You could even save more time by not filtering it backwards which is the standard approach. -- I'm not interested in adding this feature. As I said before this is a causal filter for realtime applications and any array operations won't be added.
from iirj.
Generally for anybody submitting array based issues: this library won't support array operations and is kept deliberately for realtime purposes where all filter functions are strictly "sample in and sample out".
Any feature requests about array (a-causal) operations will be ignored.
from iirj.
Related Issues (20)
- Version number mismatch? HOT 4
- Some help converting code from Matlab HOT 3
- Debug message HOT 2
- Bandpass filter frequency settings HOT 6
- Real-time filtering vs array filtering HOT 2
- Question on Butterworth highPass, cutoff==Nyquist, coefficients are NaN? HOT 1
- Applying butterworth bandpass filter on a wav file HOT 1
- Input for butterworth filter on audio signal HOT 1
- Changing target Frequency while feeding in new Samples HOT 3
- Basic question on applying the filter HOT 2
- Python equivalent of a simple filter HOT 2
- A querstion about HighPass HOT 1
- A querstion about HighPass with value HOT 1
- [Question] I want to make a C# port of this, but... HOT 2
- Unusual results when using Bessel filters of higher orders HOT 5
- Add Support for Cauer / Elliptic Filter HOT 1
- Issue with Odd-Order Highpass Filters HOT 2
- about sampling rate and cut off frequency HOT 1
- voice filter HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from iirj.