# How to practically correct for group delay imposed by a digital filter (Python)

I'm using Python to filter a signal using a Butterworth filter (scipy.signal.butter) and subsequently passing this through a forward-backward filter with cascaded second order sections (scipy.signal.sosfiltfilt). Obviously, this introduces a group delay which I don't like.

I was told to use just the scipy.signal.filtfilt as it has a zero phase shift, though it is less numerically stable than the sosfiltfilt method.

I understand there are ways to calculate the group delay, for example scipy.signal.group_delay. This gives me an array of the phase shift for each frequency in my sample domain.

So this brings me to my general question - how is knowing the group delay useful? How can I practically use the group delay at each frequency to correct for the phase shift in the filtered signal? Is there a method for this, or is it as tedious as delaying each frequency component separately and then summing them up to get a zero phase shifted signal?

Cheers

• sosfiltfilt and filtfilt do the same thing, just with different implementations. They're both zero phase and don't introduce any delay. – endolith Oct 24 '20 at 1:16

A causal filter such as what must be used in real time filters will always have group delay. Because it is unavoidable in such a circumstance it’s beneficial to know what it is.

Group delay cannot be corrected for in real time, as it would require knowledge about signal which hasn’t happened yet. Variable group delay can be made constant by applying a filter with a phase response such that the sum of the applied filter and the incident filter is linear, but this will result in a constant, almost certainly non-zero and positive group delay.

In rendered applications, a method such as filtfilt will apply the filter, then flip the filter about zero time and apply it again, which will square the magnitude responds and result in no phase shift. There should not be anything about this process that results in stability problems.

Hypothetically, one could construct a zero phase version of a filter in a rendered application by way of some maths. One way would be to take the frequency transform of the resulting signal and subtract the phase response of the filter, and transform it back to the time domain. This might have some gnarly edge artifacts. You might try creating an all pass filter with the negative of the filter’s phase response, use that to filter the signal. That would result in a signal that’s delayed by half the filter length, which you could remove manually. However, it sounds like you are using an IIR filter, so picking an appropriate length for prototyping the all pass might be tricky.

While designing the initial two filters, make sure that they have either zero phase or constant phase. Usually linear filters have constant phase, which gives the same group delay for all samples. Or you can design another filter with constant gain but phase as the inverse of group delay, so that it cancels.

All implementable signals are causal so there will be an inevitable delay, but when we refer to correcting the delay what we are really doing is including a compensatory delay in the reference we are using to compare inputs and outputs. filtfilt accomplishes this which is why it is known as a "zero-phase" filter, in that the results based on a reference from the first samples of both the input and output, will be completely aligned with zero delay. This of course is through post-processing, in that there was a time delay for us to see those results as aligned. In other applications of implementation we can do the same thing: include a compensatory delay of the input in order to get an aligned comparison at the output with zero delay. This is what it is meant when we say "correct for group delay" in a filter.

Further with regards to group delay do not construct the filter as an IIR Butterworth filter since it will not only introduce Group Delay, but more significantly Group Delay Variation across the usable bandwidth, which is then much more challenging to correct for (can be done with equalizers, but why add the effort?). Linear phase FIR filters should be the selection of choice, as they will have a fixed delay across all frequencies that is half the length of the filter (number of taps), so is so easy to correct for: It is simply delaying the comparison signal (such as the input to compare to the output) by that many samples.

• Thanks for the insight. Could you suggest an example of a linear phase FIR filter that could be used in place of a Butterworth filter? – Cazador Dec 1 '20 at 23:03
• @Cazador for what requirements exactly? I would likely pursue the least squares algorithm for a linear phase FIR filter (firls in Matlab, Python and Octave) in place of a butterworth prototype IIR filter. – Dan Boschen Dec 1 '20 at 23:09