Unexpected peaks in power density following downsampling and filtering I first applied a 100 Hz lowpass filter to my data, which was recorded at 30000 Hz:

import numpy as np
from scipy import signal as ss
from scipy.signal import butter, lfilter, freqz
import matplotlib.pyplot as plt

def butter_lowpass(low_cutoff, fs, order=5):
    nyq = 0.5 * fs
    normal_low_cutoff = low_cutoff / nyq
    b_low, a_low = butter(order, normal_low_cutoff, btype='lowpass', analog=False)
    return b_low, a_low

def butter_lowpass_filter(data, low_cutoff, fs, order=5):
    b_low, a_low = butter_lowpass(low_cutoff, fs, order=order)
    y_low = ss.lfilter(b_low, a_low, data)
    return y_low

# Filter requirements.
order = 5
fs = 30000      # sample rate, Hz
low_cutoff = 100 # desired cutoff frequency of the filter, Hz

print('Filtering data')
filtered_array = butter_lowpass_filter(array, low_cutoff, fs, order)


Then I down sampled my data from 30000 Hz to 250 Hz

updated_array=ss.decimate(filtered_array, 12, ftype = 'fir')
newarray = ss.decimate(updated_array,10, ftype = 'fir')


And then apply the decimated result to a spectrogram:

frequencies, time, Sxx = ss.spectrogram(newarray,sampling_rate, ss.get_window('hamming', bin_size), noverlap=0, nfft=sampling_rate*4)


However, the resulted plot showed some signal higher than 100Hz even though I already used a lowpass 100Hz filter earlier.



For reference, this is the plot if the filter was not sed before decimation:



Is there any explanation for this?

Thanks a lot!
2 comments:

First, scipy signal decimate already low-pass filters the signal. It first filters the signal and then subsamples. So there is no need to pre-filter your signal before decimation. In your case, the signal is filtered at 125 Hz, which is half the resulting sampling frequency. (decimate doc here)

Second, a Butterworth filter is not an ideal filter. This filter will have a 3dB attenuation at the cutoff frequency, no matter the order of the filter. So you are expected to have components remaining between 100 Hz and 125 Hz.

If you want nothing detectable above 100 Hz, then design a filter with stop-band at 100 Hz and sufficient attenuation. This will result in a cutoff frequency below 100 Hz.

Depending on your requirements, an elliptic or Chebyshev filter will result in a narrower transition than a Butterworth of the same order.