0
$\begingroup$

I am hoping to use scipy.signals.filtfilt() to smooth some signals in Python, and wanted to build the filter based on a window like a hanning window or whatever. E.g.:

import scipy.signal.windows as windows
window = windows.hann(filter_width)

But standard filters don't just take in windows, they take in numerator and denominator transfer function coefficient arrays a and b:

data_smoothed = scipy.signal.filtfilt(b, a, data_noisy)

Is there a way to calculate the transfer function coefficients a and b from a window? I like filtfilt() more than straight-up convolution with the window because it has a lot of useful features baked in.

$\endgroup$
  • 1
    $\begingroup$ Windows are usually not directly used as a filter, but they are used to design a filter by multiplying a window with coefficients of an ideal (infinitely long) filter. So I'm not sure if what you're trying to do is really what you want to do. $\endgroup$ – Matt L. Jul 23 '20 at 5:31
  • $\begingroup$ @MattL. This is definitely not my area of expertise, so any links or discussion of this or alternate answers I would appreciate. Usually I just convolve with a window to smooth signals. But the function filtfilt has so many nice features built in that I would like to use it (e.g., Gustaffson's method to deal with edges). I realize this is sort of weird, because it is more of a frequency domain method....my big concern is what am I doing wrong (i.e., will yield mistakes) or just weird? E.g., if I do what is in the accepted answer, will my smoothed signals be reasonable, or fubar? $\endgroup$ – eric Jul 23 '20 at 14:27
  • 1
    $\begingroup$ It's okay to use a window as a filter if you just want a simple smoothing, since it's just a weighted average of the last $N$ input samples. For more sophisticated filtering with more control over frequency domain parameters you'd need a better filter. But note that the implementation will be the same, you'd just have different filter coefficients. $\endgroup$ – Matt L. Jul 24 '20 at 8:19
1
$\begingroup$

What you are describing is an FIR filter, such that all the denominator coefficients are zero, save the basis, a[0]=1. So you could do something like:

data_smoothed = scipy.signal.filtfilt(window, 1, data_noisy)

There is a notable point. The DC gain of the filter is equal to the sum of the coefficients for FIR filters. Your window is likely normalized to 1, so the sum is probably higher than 1, which means your filter will have gain at low frequencies. You would want to divide all the coefficients by the sum of the window to keep the gain to unity.

$\endgroup$
  • $\begingroup$ Thanks this is really helpful -- I have been dividing the window by the sum of the values in the window, so that the sum of all the elements is 1 (iirc the DC gain is the sum of the elements, not the average of the elements, right?). $\endgroup$ – eric Jul 23 '20 at 1:53
  • 1
    $\begingroup$ @eric. You are correct. I totally brain farted that one. Thanks much, I have updated the answer. $\endgroup$ – Dan Szabo Jul 23 '20 at 2:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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