I'm currently working on an article for ECG classification which it says that it has used elliptic bandpass filter with 0.5Hz and 50Hz critical frequencies to eliminate base-line and interference etc. First problem is that I think it should be stopband instead of bandpass, am I wrong?

Second problem is when I try to do the filtering in matlab. The original signal shape is something like this: ecg signal shape

the sampling rate of the signal is 300Hz.

[b, a] = ellip(10, 1, 100,[0.5 50]/150, 'bandpass')
fvtool(b, a, 'Fs',300)

This is the frequence response of the filter: frequency response of the filter

using this line, I apply the filter to my signal:

s_filtered = filtfilt(b, a, s)

and what it returns is all NaN! Am I doing something wrong?

  • $\begingroup$ That's a terrible filter for pulsed signals, IMHO. The steep skirts are going to cause no end of ringing, and if you want to exclude environmental effects you should have zeros at the local line frequency and its harmonics (so, either every 50Hz or every 60Hz, or if you want to be universal, both). I understand that you've got to use it, but you may want to study up on what's considered best. $\endgroup$
    – TimWescott
    Dec 14, 2020 at 18:13

2 Answers 2


Numerical problems. 64-bit double precision floating point is not nearly enough to implement this filter in the way you have done it.

Your filter is extremely steep: The poles are way too close to the unit circle and the order is way too high to implement it in transfer function form (which is a bad anyway).

Things to do

  1. Implement the filter as cascaded second order section
  2. Review the requirements for your filter. It seems way steeper than it needs to be. Such an aggressive filter will destroy a lot of time domain details since the filter has massive amounts of time domain ringing. The settling time alone is multiple seconds and by using filtfilt you double it again & create an enormous non-causality.

Filter design requires a lot of trade offs, make sure you understand them and optimize to the specific requirements of your application.

  • $\begingroup$ I'm trying to implenent an article in code which preprocess ecg by doing filtfilt on ecg signal with elliptic filter. The article has mentioned the order of filter and the cutoff frequencies which are 10th order with 0.5Hz and 50Hz. I'll add a link to article to the question. According to matlab's website only things that I can change are Rp and Rs which I chose them by looking at some examples in this link:mathworks.com/help/signal/ref/ellip.html $\endgroup$ Dec 14, 2020 at 14:21
  • $\begingroup$ Granted, I'm an audio guy and don't know a lot about ECG processing. However, your filter has a group delay of almost 29s at 0.5 Hz. If you really want -100dB below 0.5Hz you would have to run the filter (even without filtfilt) for over 200 seconds for the attenuation to build up (and the first 200 seconds of the output would have to be discarded). If that works for you: great! But it's a very unusual filter spec to say the least. Even Matlab's fvtool() has trouble with as you can see by the "fuzz" at the low frequencies. $\endgroup$
    – Hilmar
    Dec 14, 2020 at 15:47
  • $\begingroup$ As you mentioned, the problem was numerical and was solved by using 'sos'. I read the docs and saw at the end that using b,a may not work for orders more than 4! $\endgroup$ Dec 14, 2020 at 16:52
  • $\begingroup$ Using transfer functions of order more than 2 is highly dis-recommended. It's pretty much Not Done in DSP, because the requirements on the precision both of the coefficients and the data paths gets absurd. You design your filter as a collection of poles and zeros, then you implement the filter as a cascade of 2nd-order sections because that's what works. Using some extended numerical precision package (which is what I assume sos is) just unnecessarily masks an easily-solved problem. $\endgroup$
    – TimWescott
    Dec 14, 2020 at 18:11
  • $\begingroup$ SOS exactly stands for Second Order Sections $\endgroup$ Dec 14, 2020 at 19:31

If you want to design a band pass filter, you need to call ellip with half the desired filter order (check the corresponding Matlab help page). I.e., for a $10^{th}$ order band pass filter the correct call is

[b,a] = ellip( 5, ... );

This might avoid (part of) the numerical problems you're running into now. Of course, cascading second-order sections may still be necessary.

  • $\begingroup$ Thanks! using sos solved the problem! $\endgroup$ Dec 14, 2020 at 17:10
  • $\begingroup$ @SepehrGolestanian: Good, but the filter order is still 20 instead of 10. $\endgroup$
    – Matt L.
    Dec 14, 2020 at 17:19
  • $\begingroup$ you mean because of filtfilt? $\endgroup$ Dec 14, 2020 at 19:21
  • $\begingroup$ Oh, know I understand, thanks for noticing me. $\endgroup$ Dec 14, 2020 at 19:23
  • $\begingroup$ Is this the case in scipy.signal.ellip too? I'm asking because they didn't write anything in their documentation. $\endgroup$ Dec 14, 2020 at 19:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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