Reputation: 81
I am trying to use bandpass filter on an ecg signals, this is the code:
from scipy.signal import butter
def bandpass_filter(self, data, lowcut, highcut, signal_freq, filter_order):
nyquist_freq = 0.5 * signal_freq
low = lowcut / nyquist_freq
high = highcut / nyquist_freq
b, a = butter(filter_order, [low, high], btype='band', analog=False)
y = lfilter(b,a, data)
return y
def detect_peaks(self):
self.filtered_ecg_measurements = self.bandpass_filter(ecg_measurements,
lowcut=self.filter_lowcut,
highcut=self.filter_highcut,
signal_freq=self.signal_frequency,
filter_order=self.filter_order)
self.signal_frequency = 250
self.filter_lowcut = 0.0
self.filter_highcut = 15.0
self.filter_order = 1
This error appears every time I try to run this function:
Traceback (most recent call last):
File "D:/Project/code/untitled/test.py", line 297, in <module>
log_data=True, plot_data=True, show_plot=False)
File "D:/Project/code/untitled/test.py", line 98, in __init__
self.detect_peaks()
File "D:/Project/code/untitled/test.py", line 135, in detect_peaks
filter_order=self.filter_order)
File "D:/Project/code/untitled/test.py", line 256, in bandpass_filter
b, a = butter(filter_order, [low, high], btype='band', analog=False)
File "C:\Users\AppData\Roaming\Python\Python36\site-packages\scipy\signal\filter_design.py", line 2394, in butter
output=output, ftype='butter')
File "C:\Users\AppData\Roaming\Python\Python36\site-packages\scipy\signal\filter_design.py", line 1959, in iirfilter
raise ValueError("Digital filter critical frequencies "
ValueError: Digital filter critical frequencies must be 0 < Wn < 1
the error text is :
Digital filter critical frequencies must be 0 < Wn < 1
Upvotes: 6
Views: 24891
Reputation: 35
I was having a similar problem. What solved for me was defining the Nyquist Frequency in a little bit different manner:
nyquist_freq = 1/(2 * signal_freq)
After doing this, the filter ran perfectly for me, respecting both limits I had set.
OBS: The critical frequency also must be greater than 0.
Upvotes: 0
Reputation: 59
As Darkoob12 pointed out in the comments to the question, lowcut
cannot equal zero. If lowcut
is set to zero, it will produce the error message seen by OP.
Upvotes: 1
Reputation: 11
It may be because of the input of parameter fs
. It has to be larger than any of 2 * Wn
.
As in scipy/signal/filter_design.py source code:
if fs is not None:
if analog:
raise ValueError("fs cannot be specified for an analog filter")
Wn = 2*Wn/fs
And later:
if not analog:
if numpy.any(Wn <= 0) or numpy.any(Wn >= 1):
raise ValueError("Digital filter critical frequencies must be 0 < Wn < 1")
Upvotes: 1
Reputation: 2778
scipy.signal.butter(N, Wn, btype='low', analog=False, output='ba')
Wn : array_like
A scalar or length-2 sequence giving the critical frequencies. For a Butterworth filter, this is the point at which the gain drops to 1/sqrt(2) that of the passband (the “-3 dB point”). For digital filters, Wn is normalized from 0 to 1, where 1 is the Nyquist frequency, pi radians/sample. (Wn is thus in half-cycles / sample.) For analog filters, Wn is an angular frequency (e.g. rad/s).
Your exception is here where low/high is not [0,1]
b, a = butter(filter_order, [low, high], btype='band', analog=False)
for filter_type == 1
, Wn
is float other than nparray.
https://github.com/scipy/scipy/blob/v0.19.1/scipy/signal/filter_design.py#L2226-L2297
>>> N, Wn = signal.buttord([20, 50], [14, 60], 3, 40, True)
>>> b, a = signal.butter(N, Wn, 'band', True)
Upvotes: 0