This ended up being a bug with my plotting code :)

I'm relatively new to using IIR filters, I wanted a bandpass filter for the 0.5Hz -> 5.0Hz frequency range and was looking at the zero-pole plots for different options scipy gives you.

I'm using

def zpk_plots(low_cutoff=0.5, high_cutoff=5.0, order=5, attenuation=40):
    sampling_freq = 30
    nyquist_freq = 0.5*sampling_freq
    norm_low_cutoff = low_cutoff / nyquist_freq
    norm_high_cutoff = high_cutoff / nyquist_freq
    cricial_freqs = [norm_low_cutoff, norm_high_cutoff]

    z, p, k = butter(order, Wn=cricial_freqs, btype='bandpass',output="zpk")
    z, p, k = cheby1(order, attenuation, Wn=cricial_freqs, btype='bandpass',output="zpk")
    z, p, k = cheby2(order, attenuation, Wn=cricial_freqs, btype='bandpass',output="zpk")

def pole_zero(z, p, k):
    z_x = np.real(z)
    z_y = np.imag(z)

    p_x = np.real(p)
    p_y = np.imag(z)
    ... plotting code here ...






enter image description here

For Chebyshev2, my zero-pole plot looks very different. What does this mean? I'm not very good at filters so I may be completely misunderstanding it, but the poles are complex, and they don't have conjugate symmetry (I think this means the filter is not fully causal?) and also some of the poles are outside of the unit circle (I think this means the filter is unstable and will blow up the input signal?)

Essentially I want to know:

  1. Why is the Chebyshev2 plot so different from the others?
  2. What can the positions of the poles tell me about this filter's behavior?

1 Answer 1


Why is the Chebyshev2 plot so different from the others?

Because something is really wrong with your code or plotting routine. The poles of Butterworth filters are NOT real and it should look like this

enter image description here

  • $\begingroup$ This would certainly explain the weird behaviour. Would you be able to share the code for this plot so I can compare to mine and see what's wrong? I still can't see it $\endgroup$ Commented Sep 24, 2021 at 12:22
  • $\begingroup$ Found it... "p_y = np.imag(z)"... Whoops! Thanks for the answer... I still need to understand the difference between these plots but this certainly puts me past a roadblock now that I can see what these plots are supposed to look like $\endgroup$ Commented Sep 24, 2021 at 13:04
  • $\begingroup$ Look, the problem here is that you blindly trusted code that was not at all tested or verified. You can easily look up "poles zero plot of a butterworth filter" on google and check whether your plots look anywhere like the real thing. Don't draw any conclusions until you have verified that you accurately reproduce "known good" results. $\endgroup$
    – Hilmar
    Commented Sep 24, 2021 at 13:29
  • $\begingroup$ I appreciate the response, I've actually been stuck on these bandpass filters for a good few days now, I can't work out why mine is misbehaving so I plotted the zero-poles and clearly just confused myself more. I thought the reason mine looked different from the ones on google was because almost all the ones on google are highpass or lowpass filters and mine was a bandpass. I also saw answers on here that suggested "aggressive" filters led to instability so thought maybe it was my input parameters making the plot different... I probably need to start from the beginning! $\endgroup$ Commented Sep 24, 2021 at 14:05
  • $\begingroup$ Yep, step by step is the best approach. A band pass has both a low pass and a high pass. 1) Look at the low pass, 2) Look at the high pass, 3) Look at the bandpass: at this point it should be obvious what's happening here. $\endgroup$
    – Hilmar
    Commented Sep 24, 2021 at 14:38

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.