Closed megies closed 7 years ago
I suspect you might be hitting some boundary condition, where we probably shouldn't allow an upper limit equal to Nyquist (or we need to treat it differently to get it right). But I need to do some reading to figure that out...
In the meantime, you could look at the pole-zero plots of those filters, and also look at the frequency response with freqz
to see how it varies.
This may be the culprit: filter_design.py
if numpy.any(Wn < 0) or numpy.any(Wn > 1):
raise ValueError("Digital filter critical frequencies must be 0 <= Wn <= 1")
fs = 2.0
warped = 2 * fs * tan(pi * Wn / fs)
The code that @e-q points out certainly is problematic if an element of Wn
is 1. Theoretically, the warping doesn't work in this case, because Wn = 1
gets mapped to infinity, and the formulas used by the subsequent code are not designed to handle that case. In practice, because np.pi
is not exactly π, tan(np.pi/2)
is 16331239353195370.0
. That's a big number, but still a poor approximation to infinity. :smile:
A quick fix is to simply not accept 1 in Wn
. I haven't looked more closely to determine if there is a correct way to handle this edge case. A user can work around the problem by explicitly checking for 1, and designing a high-pass filter instead of a band-pass filter in that case.
+1 for raising an error if Wn == 1
, and letting the user change to a high-pass in that case. Won'
...t make it for 0.18 but we should fix it before 0.19
we should fix it before 0.19
Ping :-)
Okay moved to 1.0 :)
We have come across what seems to be a bug in
scipy.signal.iirfilter
(or some underlying routine), see obspy/obspy#1451.When the high corner of a digital butterworth bandpass filter happens to be exactly at Nyquist frequency, i.e.
iirfilter(filter_order, (x, 1.0), btype='band', analog=False, ftype='butter', ..)
, (which is not raising an exception as is done when using a high corner above Nyquist), the filter gives bad results (the exact looks of which depending on a combination of filter order and low corner).To illustrate the issue here's a plot and the code to generate it. Please excuse the longish example code, but I think the plot gives the best first impression of the issue. The signal is a real world example of a seismogram recording (link to data at the bottom).
Data used in the example: seismogram_100Hz.txt
I don't think it matters but I'm on Linux 64bit using Anaconda, Python 2.7: