NeuroKit
NeuroKit copied to clipboard
engzeemod2012 method of ecg_clean() fails with low sampling rate
Describe the bug
When the input ECG signal has a low sampling rate, the "engzeemod2012"
method of the ecg_clean() function does not work:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
[<ipython-input-10-7058798300e2>](https://localhost:8080/#) in <module>()
1 sampling_rate = 100
2 ecg_signal = nk.ecg.ecg_simulate(sampling_rate=sampling_rate)
----> 3 clean_ecg_signal = nk.ecg_clean(ecg_signal, sampling_rate=sampling_rate, method="engzeemod2012")
3 frames
[/usr/local/lib/python3.7/dist-packages/neurokit2/ecg/ecg_clean.py](https://localhost:8080/#) in ecg_clean(ecg_signal, sampling_rate, method, **kwargs)
108 clean = _ecg_clean_elgendi(ecg_signal, sampling_rate)
109 elif method in ["engzee", "engzee2012", "engzeemod", "engzeemod2012"]:
--> 110 clean = _ecg_clean_engzee(ecg_signal, sampling_rate)
111 elif method in [
112 "christov",
[/usr/local/lib/python3.7/dist-packages/neurokit2/ecg/ecg_clean.py](https://localhost:8080/#) in _ecg_clean_engzee(ecg_signal, sampling_rate)
260 f2 = 52 / (0.5 * sampling_rate)
261
--> 262 sos = scipy.signal.butter(4, [f1, f2], btype="bandstop", output="sos")
263 zi_coeff = scipy.signal.sosfilt_zi(sos)
264 zi = zi_coeff * np.mean(ecg_signal)
[/usr/local/lib/python3.7/dist-packages/scipy/signal/filter_design.py](https://localhost:8080/#) in butter(N, Wn, btype, analog, output, fs)
2955 """
2956 return iirfilter(N, Wn, btype=btype, analog=analog,
-> 2957 output=output, ftype='butter', fs=fs)
2958
2959
[/usr/local/lib/python3.7/dist-packages/scipy/signal/filter_design.py](https://localhost:8080/#) in iirfilter(N, Wn, rp, rs, btype, analog, ftype, output, fs)
2422 raise ValueError("Digital filter critical frequencies "
2423 "must be 0 < Wn < fs/2 (fs={} -> fs/2={})".format(fs, fs/2))
-> 2424 raise ValueError("Digital filter critical frequencies "
2425 "must be 0 < Wn < 1")
2426 fs = 2.0
ValueError: Digital filter critical frequencies must be 0 < Wn < 1
To Reproduce To get the error above, I ran the following code:
import neurokit2 as nk
sampling_rate = 100
ecg_signal = nk.ecg.ecg_simulate(sampling_rate=sampling_rate)
clean_ecg_signal = nk.ecg_clean(ecg_signal, sampling_rate=sampling_rate, method="engzeemod2012")
Expected behaviour Maybe a warning telling me to resample?
System Specifications
- OS: Linux ( 64bit)
- Python: 3.7.13
- NeuroKit2: 0.2.0
- NumPy: 1.21.6
- Pandas: 1.3.5
- SciPy: 1.7.3
- sklearn: 1.0.2
- matplotlib: 3.2.2
If the sampling rate is too low / high to achieve a given bandpass filtering we should just apply a highcut / lowcut (depending on what's possible) no? also perhaps we should use signal_filter here? Initially I wanted to use the exact same functions as used in other implementations (e.g., biosppy), but now I am thinking that if an implementation is not optimal we might as well update it
If the sampling rate is too low / high to achieve a given bandpass filtering we should just apply a highcut / lowcut (depending on what's possible) no? also perhaps we should use signal_filter here?
@DominiqueMakowski Yeah that works! Should that be a general change to signal_filter()
then?
There's already a warning but it doesn't change the critical frequencies: https://github.com/neuropsychology/NeuroKit/blob/277f614ee3984647d71ba31aadffea97766aeb0f/neurokit2/signal/signal_filter.py#L305-L315
Also it only checks highcut
, but in the case of filter_type = "bandstop"
, lowcut
should also be checked:
https://github.com/neuropsychology/NeuroKit/blob/277f614ee3984647d71ba31aadffea97766aeb0f/neurokit2/signal/signal_filter.py#L325-L326
Actually, I don't understand how a bandstop filter is supposed to be indicated with the current implementation of signal_filter
, since lowcut
shouldn't be higher than highcut
for the underlying default scipy function? See https://gist.github.com/danibene/12e95a7cdf881d5fc1a8eab742ffa0f2
Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
i'm gonna modify stale bot's setting so that it doesn't close the issues...
but this issue has been addressed right?