# Decimation with IIR filter altering amplitude of signal

I'm downsampling a signal through decimate (scipy implementation), but the result has a different amplitude than the original signal, which if I understood correctly, shouldn't happen. The original signal is sampled at 128Hz, and I want to downsample it to 1Hz. Decimation code is:

    sig_d = signal.decimate(sig, 8)
sig_d = signal.decimate(sig_d, 8)
sig_d = signal.decimate(sig_d, 2)


I then checked in the first 1 minute window of the original and decimated signals:

    df = pd.DataFrame(sig[0:7680])
print(df.describe())
df = pd.DataFrame(sig_d[0:60])
print(df.describe())


and this is the output statistics:

          Original
count  7680.000000
mean     94.191307
std       0.551882
min      92.580971
25%      94.028488
50%      94.086906
75%      94.794744
max      94.969666

Decimated
count  60.000000
mean   91.011716
std     0.516294
min    89.658212
25%    90.847055
50%    90.886592
75%    91.589404
max    91.689528


As you can see, there is a huge decrease in amplitude for the same time window in the decimated signal. Per the statistics, it doesn't seem to be related to peak removal, since this window in the original signal has very small variability, and not really any pronounced peaks. I did plot the two signals to check if I wasn't messing up the alignment, and they were aligned perfectly, their shape in this time window is the same (besides sampling rate), but the decimated signal seemed to be "pushed down" in amplitude. Unfortunately, I cannot post the plots (for proxy reasons).

This seems to happen only with IIR filter(though FIR has other issues). Is this normal behavior of decimation? Or am I doing something wrong?

First, 0.3dB is generally considered small potatoes in signal processing.

Second, the documentation for scipy.signal.decimate states that it uses an 8th-order Chebychev filter by default (without specifying the ripple, dangit!). Chebychev filters have some ripple in the passband; if the bulk of your signal's energy is falling into the troughs of the ripple, then you should expect some attenuation. In particular, it appears that your filter has a lot of DC content, and even-order Chebychev filters tend to have a gain of less than unity at DC.

So I suspect that it's doing exactly as expected.

• Also note, from the documentation "When using IIR downsampling, it is recommended to call decimate multiple times for downsampling factors higher than 13". – TimWescott Jan 11 at 15:39
• Minor nitpicking (sorry): even-order Chebychev filters tend to have a gain of less than unity at DC -- that is true for passive filters, but for active (IIR conversions included), DC is usually 1, with maximum being 1+Ap, unless the gain is explicitly corrected, which I don't know in OP's case. But if it is so, and if it's 0.3dB ripple, then it kinda checks out: 0.2988dB@1Hz => 0.96618*94.1913=91.005. – a concerned citizen Jan 11 at 15:56
• @aconcernedcitizen: Don't apologize! I don't happen to know where scipy set the overall gain of the filter (which is unfortunate; they should say) -- but I was assuming the case I stated. It could also be a 0.6dB ripple with the gain centered on unity, which might be odd, but could be sensible. – TimWescott Jan 11 at 16:11
• I'm just as clueless, I only did a quick search for the documentation, and, indeed, it only says it's a Chebyshev type I, nothing else about the ripple. I was a coward, though, and didn't go through the sources... – a concerned citizen Jan 11 at 16:19