filtfilt vs filter gives strange results
12 views (last 30 days)
Show older comments
I am attempting to use a bandstop filter on a signal with filtfilt(), but the results are unexpected. The code used to design the bandstop filter is
bfilt_spin = designfilt('bandstopiir', 'PassbandFrequency1', 1.90, 'StopbandFrequency1', 1.95, 'StopbandFrequency2', 2.05, 'PassbandFrequency2', 2.10, 'PassbandRipple1', 1, 'StopbandAttenuation', 60, 'PassbandRipple2', 1, 'SampleRate', (t_filt(2)-t_filt(1))^-1, 'DesignMethod', 'cheby2');
I have attached the signal I am trying to filter (wform is the signal, and time vector is t_filt) and the designed filter. When I plot the filtered signal or the FFT, something is clearly wrong in the filtfilt() case (see plots below). Am I using filtfilt() incorrectly, or is there something wrong with the data I am using? I have looked at the documentation for filter() and filtfilt() for clues, but I am stuck.
To troubleshoot, I tried using filter() for comparison. I would expect filtfilt to produce a similar result to filter, but with no phase-shift and better end effects, per the documentation. The digital filter performed as expected, here is the plot of the FFT:

When I use filtfilt() instead, it looks broken. It seems more than just a small side-effect, there's something wrong with this use-case that I don't know and I haven't found in the documentation. Note the magnitudes of the two plots.

Adjusting the parameters of the filter (frequencies, ripple, and attenuation - I always used cheby2) seems to affect how the strangeness looks, but not whether it is there. Plotting in the time domain reflects what is seen in the FFT.
Thanks for any suggestions.
0 Comments
Answers (1)
Star Strider
on 19 May 2015
I don’t usually use designfilt, preferring the ‘lower-level’ functions because I’m used to them. The filtfilt function is preferable for filtering because of its phase characteristics.
Much depends on how you designed and implemented your filter. I always use the ‘second-order-section’ (SOS) implementation rather than the transfer function, and check the filter for stability with the freqz function before I apply it to the signal. (I detailed my filter design procedure here.) Since I don’t have ‘t_filt’, I can’t run your code and use freqz to see how your filter functions.
Lacking those data, it’s not possible to determine what — if any — errors might be in your design.
2 Comments
Star Strider
on 19 May 2015
Edited: Star Strider
on 20 May 2015
I found it to work well just as you designed it. The designfilt function automatically uses the SOS implementation (obvious from the code). The only suggestion I have is to set the passband ripple to 1dB and the stopband ripple to 10dB.
My code:
filt = load('Ryan filterdata.mat');
df = filt.bfilt_spin;
sg = filt.wform;
t = filt.t_filt;
%
Ts = mean(diff(t));
Fs = 1/Ts;
Fn = Fs/2;
fsg = fft(sg)/length(sg);
Fv = linspace(0, 1, fix(length(sg)/2)+1)*Fn; % Frequency Vector
Ix = 1:length(Fv); % Index Vector
%
figure(1)
plot(Fv, abs(fsg(Ix)))
grid
xlabel('Frequency')
ylabel('Amplitude')
axis([0 5 ylim])
%
fvtool(df)
axis([0 5 ylim])
%
ysg = filter(df, sg); % Filter Signal
fysg = fft(ysg)/length(ysg);
%
figure(3)
plot(Fv, abs(fysg(Ix)))
grid
xlabel('Frequency')
ylabel('Amplitude')
axis([0 5 ylim])
So you designed your filter correctly, and correctly implemented it. Other than the passband ripple (that I would reduce), I see no problems.
EDIT — The freqz plot is instructive. The filter appears to be unstable:
figure(4)
freqz(df, 1204)
axis([0 0.05 ylim])
EDIT 2 — I brought this to the attention of TMW with a Support Request, including the URL.
See Also
Categories
Find more on Digital Filtering in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!