MATLAB Answers

Filter function in MATLAB

5 views (last 30 days)
Mohammad Zulqarnain
Mohammad Zulqarnain on 12 May 2021
Commented: William Rose on 11 Jun 2021
I have a dataset in csv format. I have to band pass filter it. I am using the code as given in the code section.
Which in built filter function in MATLAB is more appropriate, filter or filtfilt? And is there any condition where we cannot use filter function and should use only filtfilt function? The response from filter function and filtfilt function is very much different.
M = csvread(csv_name);
Fs = 2048;
x = M;
%Design and apply the bandpass filter
order1 = 2;
fcutlow1 = 0.1;
fcuthigh1 = 5;
[b,a] = butter(order1,[fcutlow1,fcuthigh1]/(Fs/2), 'bandpass');
X = filter(b,a,x);
Y = filtfilt(b,a,x);
t = (0:1:length(x)-1)/Fs;
plot(t,X);hold on;

Answers (3)

William Rose
William Rose on 12 May 2021
@Jan is right, as usual. I really like filtfilt() because it has zero phase lag at all frequencies. filtfilt() is non-causal because it filters data backwards as well as forwards. Therefore you could not use filtfilt(), or some version of it, in a real-time application.
Also possibly of interest to you: because filtfilt() filters the data twice, both forward and backward, it produce double the attentuation (measured in dB) at every frequency, compared to the filter whose parameters you pass to it. For example, if you design a fourth order Butterworth with a 100 Hz cutoff, and use it directly (with filter()) it will have 3 dB attentuation at 100 Hz. If you pass its parameters to filtfilt() and use filtfilt(), you will get 6 dB attenuation at 100 Hz. You can make a compensatory adjustment in the cutoff frequency of the original Butterworth, if you really want 3 dB at 100 Hz.
A particular filter applied twice with filtfilt() is not the same as a doubled-order of the same type. For example, a fourth order Butterworth applied twice with filtfilt() is eighth-order, but it is not eighth-order Butterworth. For most users, this is not important.
For high-order filters, the direct-form implementaiton of filtfilt() may be unstable. HIgh-order is often defined as order 12 or more, but I have seen instability at lower orders. Therefore I would be careful using an initial filter order of greater than four with filtfilt(). If you filter is unstable, you will know it because you get crazy large outputs.
William Rose
William Rose on 11 Jun 2021
It is not true that filter() can not be used with IIR filters. filter() can be used with IIR filters. For instance, the following works fine.
Notice that the filtered signal, y, starts out close to zero - as @Jan explained. @Star Strider gave a way you can deal with this, if you don't want to use filtfilt(). Since the above example is only a second order filter, it is stable and works fine exactly as written. If you were using a high order filter (order 6 or more). you might want to implement the filter with second order sections (SOS) to avoid possible instability, as @Star Strider said. (You will know you have a stability problem if the output takes on values like 10^307, or something like that!) The SOS version of the above code follows. The plot is about the same, although not exactly the same, since the random numbers in x are different than before.

Sign in to comment.

Jan on 12 May 2021
Did you read the documentation already?
doc filter
doc filtfilt
filter() introduces a delay between input and output signals, while filtfilt applies the filter in both directions, such that the delay vanishes. In addition filtfilt tries to estimate the initial values of the filter state by extrapolating the signal. This can reduce transitional effects.

Star Strider
Star Strider on 7 Jun 2021
The instability is generally not a problem with second-order-section realisation of IIR filters.
The filtfilt function can occasionally have beginning and ending transients that can usually be minimised by adding a vector of ones equal to the values of the beginning and end values at the appropriate ends of the signal, then deleting those regions from the filtered signal.
The preferred method of realising filters is to use zero-pole-gain and Second-Order Section —
[z,p,k] = butter(order1,[fcutlow1,fcuthigh1]/(Fs/2), 'bandpass');
[sos,g] = zp2sos(z,p,k);


Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!