filtfilt provides excessive transient

12 views (last 30 days)
I observed that 'filtfilt' suffers from an undesired behavior when I provide IIR bandpass filters having steep transition bands. Specifically, the output signal exhibits excessive transient response; nevertheless, this behaviour does not emerge if I use a 'home-made' version of zerophase filtering based on 'filter'. I guess that it is not a numerical issue involving the filter coefficients or structure, nor the 'filter' function.
% design bandpass filter having transition bandwidth of 200 Hz (Fs = 8000)
bp = designfilt('bandpassiir', 'StopbandFrequency1', 50, 'PassbandFrequency1', 250,...
'PassbandFrequency2', 3600, 'StopbandFrequency2', 3700, 'StopbandAttenuation1', 30,...
'PassbandRipple', 0.1, 'StopbandAttenuation2', 30, 'SampleRate', 8000, 'DesignMethod', 'cheby2');
% check stability
assert(isstable(bp),'Unstable filter');
% apply filtfilt to a random (white) long input signal; output signal shows an undesirable transient
x = randn(2^20,1);
y = filtfilt(bp,x);
% apply 'home-made' filtfilt to the same input; output signal shows a more accptable transient
y2 = flipud(filter(bp,flipud(filter(bp,x))));
% compare effects
figure; semilogy(abs(y-y2));
As a rule of thumb, the effect grows as the transition bands get narrower, while it tends to vanish as they get broader.
Where is the problem? Have I missed some recommendations or hints in the function's help?
  6 Comments
alelap
alelap on 12 Jan 2025

After 7 years I posted this question, I have never found a test case where I had to use filtfilt instead the 'home-made' version I wrote in the post. I think Mathworks should rethink filtfilt or offer an alternative implementation for zero-phase filtering.

Paul
Paul on 12 Jan 2025
Hi alelap,
I think your homemade version could be improved by zero-padding the input to filter on both passes. I've shown what I mean at this thread, which is a more general dicussion on the "zero-phase" response of filtfilt.

Sign in to comment.

Accepted Answer

Wentao
Wentao on 8 Jan 2025
Moved: Rena Berman on 8 Jan 2025
Hello, this issue has been answered by MathWorks Technical Support Department. Please refer to this link for detailed explaination.
Thank you for bringing this issue to our attention.
  1 Comment
Paul
Paul on 11 Jan 2025
Edited: Paul on 12 Jan 2025
I'm going to continue the discussion here because, in my experience, the Mathworks Support Team does not respond to comments on their Q&A.
The linked answer basically states that the issue is with the order of the second order sections, and that order causes the filtfilt method of the digitalFilter object, which calls filtfilt for this IIR filter, to be not as "numerically stable" as one might expect.
I'm afraid I have to disagree with that claim.
The results don't really bear the hallmark of such instability.
The transient in question is a lightly damped sinusoid, which looks very clean.
Furthermore, and more importantly, increasing the nfact parameter in filtfilt completely removes the transient from the output. So it seems that the transient we are seeing is entirely due to the filtfilt implementation (the nfact value is proably a heuristic that doesn't work for this problem?) and not inherently due to the filter structure.
Perhaps you can comment on why filtfilt is implemented as it is, where it yields different outputs for the same input depending on if the filter is implemented in tf or sos form, and now we see that there is also a sensitivity to the ordering of the sos sections.
Wouldn't it be better if filtfilt were implemented by making a single forward and backward pass and simply padding the input signal by an appropriate amount going both ways? Such an approach would, mathematically, be agnostic to the filter implementation and would have the advantage of actually being closer to the zero-phase response that filtfilt purports to achieve (and does not as is apparent for the sos case due to the change in result by reordering the sections).
Having said all of that, I do agree that the zp2sos workaround is a good thing to do regardless, and I was quite surprised to learn that designfilt doesn't already take that approach.

Sign in to comment.

More Answers (1)

Anh Tran
Anh Tran on 4 Jan 2018
The transients observed are due to a combination of using a marginally stable filter coupled with the initial condition matching performed by "filtfilt" to minimize start-up and ending transients, as described in the documentation. This is the reason behind the difference in behavior between using "filter" and using "filtfilt". It is an inherent limitation of the "filtfilt" function.
Regarding the stability of the filter, you may view the filter's stability using "fvtool", (fvtool(bp) in your case). In the Filter Visualization Tool window, select "Analysis > Pole/Zero Plot", and you will see a discrete system pole/zero map If you notice, your zeroes are very close to the edge of the unit circle, indicating the marginally stable behavior of this filter. When this type of filter is combined with the initial condition matching, the numerical conditioning yields the transient results that you observed.

Community Treasure Hunt

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

Start Hunting!