33
$\begingroup$

I saw in a SO thread a suggestion to use filtfilt which performs backwards/forwards filtering instead of lfilter.

What is the motivation for using one against the other technique?

$\endgroup$
6
  • 1
    $\begingroup$ Filtfilt is slower $\endgroup$
    – Aaron
    Commented Nov 10, 2014 at 16:24
  • $\begingroup$ possible duplicate of What is the advantage of MATLAB's filtfilt $\endgroup$
    – Matt L.
    Commented Nov 10, 2014 at 16:35
  • 3
    $\begingroup$ @Aaron filtfilt does the same filter twice, in opposite directions, so it's not any slower than doing lfilter twice in one direction, which is how you would get the same frequency response. $\endgroup$
    – endolith
    Commented Nov 11, 2014 at 14:57
  • 1
    $\begingroup$ Yeah that's all I meant. It's twice as slow. $\endgroup$
    – Aaron
    Commented Nov 11, 2014 at 17:11
  • $\begingroup$ I am new to this and was looking around to use filtfilt. @endolith said that the scipy.signal uses the original signal. I am not sure what the original signal means and how we get it. I have a wav file that I load onto my system but I do not think it is the original signal since it is broken up into a numpy array and number of samples. Please if someone could help. Thank you! $\endgroup$ Commented Jul 31, 2018 at 7:34

2 Answers 2

47
$\begingroup$
  • filtfilt is zero-phase filtering, which doesn't shift the signal as it filters. Since the phase is zero at all frequencies, it is also linear-phase. Filtering backwards in time requires you to predict the future, so it can't be used in "online" real-life applications, only for offline processing of recordings of signals.

  • lfilter is causal forward-in-time filtering only, similar to a real-life electronic filter. It can't be zero-phase. It can be linear-phase (symmetrical FIR), but usually isn't. Usually it adds different amounts of delay at different frequencies.

An example and image should make it obvious. Although the magnitude of the frequency response of the filters is identical (top left and top right), the zero-phase lowpass lines up with the original signal, just without high frequency content, while the minimum phase filtering delays the signal in a causal way:

filtfilt vs lfilter

from __future__ import division, print_function
import numpy as np
from numpy.random import randn
from numpy.fft import rfft
from scipy import signal
import matplotlib.pyplot as plt

b, a = signal.butter(4, 0.03, analog=False)

# Show that frequency response is the same
impulse = np.zeros(1000)
impulse[500] = 1

# Applies filter forward and backward in time
imp_ff = signal.filtfilt(b, a, impulse)

# Applies filter forward in time twice (for same frequency response)
imp_lf = signal.lfilter(b, a, signal.lfilter(b, a, impulse))

plt.subplot(2, 2, 1)
plt.semilogx(20*np.log10(np.abs(rfft(imp_lf))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('lfilter')

plt.subplot(2, 2, 2)
plt.semilogx(20*np.log10(np.abs(rfft(imp_ff))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('filtfilt')

sig = np.cumsum(randn(800))  # Brownian noise
sig_ff = signal.filtfilt(b, a, sig)
sig_lf = signal.lfilter(b, a, signal.lfilter(b, a, sig))
plt.subplot(2, 1, 2)
plt.plot(sig, color='silver', label='Original')
plt.plot(sig_ff, color='#3465a4', label='filtfilt')
plt.plot(sig_lf, color='#cc0000', label='lfilter')
plt.grid(True, which='both')
plt.legend(loc="best")
$\endgroup$
4
  • 5
    $\begingroup$ lfilter is not necessarily minimum-phase, it can be anything depending on the filter coefficients, but in any case it is causal, which filtfilt is not. So the result of the comparison that filtfilt has zero delay, and lfilter always adds some delay is not exactly true, because filtfilt is non-causal in the first place. What actually matters is that filtfilt does not cause any phase distortions, whereas lfilter does (unless it is used as a linear phase FIR filter, i.e. with denominator = 1). $\endgroup$
    – Matt L.
    Commented Nov 10, 2014 at 17:52
  • $\begingroup$ It is also worth noting that filtering of Nth order with filtfilt corresponds to filtering with (2N-1)th order with lfilter. $\endgroup$ Commented Nov 21, 2014 at 10:30
  • $\begingroup$ @ThomasArildsen Isn't it just 2N? That's what I demonstrated in the script $\endgroup$
    – endolith
    Commented Nov 21, 2014 at 15:13
  • $\begingroup$ @ArunimaPathania You should comment under my answer, not under the question. "Original signal" just means the signal that you're filtering. You can filter with either lfilter or filtfilt. They behave differently, as shown $\endgroup$
    – endolith
    Commented Jul 31, 2018 at 13:57
10
$\begingroup$

Answer by @endolith is complete and correct! Please read his post first, and then this one in addition to it. Due to my low reputation I was unable to respond to comments where @Thomas Arildsen and @endolith argue about effective order of filter obtained by filtfilt:

  • lfilter does apply given filter and in Fourier space this is like applying filter transfer function ONCE.

  • filtfilt apply the same filter twice and effect is like applying filter transfer function SQUARED. In case of Butterworth filter (scipy.signal.butter) with the transfer function

$$G(n)=\frac{1}{\sqrt{1+\omega^{2n}}}\quad\text{where } n \text{ is order of filter}$$

the effective gain will be

$$G(n)_{filtfilt}=G(n)^2=\frac{1}{1+\omega^{2n}}$$

and this cannot be interpreted as $2n$ nor $2n-1$ order Butterworth filter

$$G(n)_{filtfilt}\neq G(2n).$$

$\endgroup$
5
  • 1
    $\begingroup$ Please try not to add comments as answers. However, welcome to SE.DSP, and have a +1 from me. I think this adds to the answer... at least try to get enough rep to comment! :-) $\endgroup$
    – Peter K.
    Commented Mar 29, 2018 at 12:08
  • $\begingroup$ I don't think this is true. G(n) is the amplitude gain of the filter. If you cascade the complex transfer function I think it will work out to 2n. $\endgroup$
    – Mike
    Commented Oct 29, 2019 at 22:15
  • 1
    $\begingroup$ I confirmed with a quick simulation that a a 6th order Butterworth gives the same G(ω) as 2 x (3rd order Butterworth) cascaded but with the cutoff frequency of the 3rd order scaled by 1.6. The results are identical except for scaling of the cutoff frequency. So, the order does scale with 2n, but note that the passband will reduce when you cascade and needs to be compensated. Someone feel free to explain theory but I don't really want to go through all the math. $\endgroup$
    – Mike
    Commented Oct 29, 2019 at 23:22
  • $\begingroup$ Can you @drgrujic (or anyone else) please explain why not + sign in the denominator of fliter $G(n)$? $\endgroup$
    – MathArt
    Commented Aug 5 at 12:18
  • $\begingroup$ @MathArt You are right, it should be +, post edited. Thank you! $\endgroup$
    – drgrujic
    Commented Aug 6 at 13:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.