NeuroKit icon indicating copy to clipboard operation
NeuroKit copied to clipboard

Bug in _ecg_findpeaks_rodrigues function

Open FrancisThibaultNRC opened this issue 2 years ago • 9 comments

Describe the bug out of bounds happens in the function __ecg_findpeaks_rodrigues while doing something simple.

To Reproduce

Simulate data: heart beat = 75 bpm with ecgsyn method with a bit of noise

duration = 600; sampling_rate = 500; heart_rate = 75; noise = 0.1; method = 'ecgsyn' ecg = nk.ecg_simulate(duration=duration, sampling_rate=sampling_rate, noise=noise, heart_rate=heart_rate, method=method, random_state=10) ecg_clean = nk.ecg_clean(ecg, sampling_rate=sampling_rate)

_, neurokit = nk.ecg_peaks(ecg_clean, sampling_rate=sampling_rate, method="rodrigues2021")

System Specifications python 3.8.6 neurokit2 version 0.1.3 OS windows 10

And copy paste the output: src\scripts\plugin\test_rodrigues.py:40:


C:\ProgramData\miniforge3\envs\hrv\lib\site-packages\neurokit2\ecg\ecg_peaks.py:71: in ecg_peaks rpeaks = ecg_findpeaks(ecg_cleaned, sampling_rate=sampling_rate, method=method) C:\ProgramData\miniforge3\envs\hrv\lib\site-packages\neurokit2\ecg\ecg_findpeaks.py:157: in ecg_findpeaks rpeaks = _ecg_findpeaks_rodrigues(ecg_cleaned, sampling_rate)


signal = array([-0.08944387, -0.12784971, -0.16738688, ..., -0.03866687, -0.03586953, -0.03304892]), sampling_rate = 500

def _ecg_findpeaks_rodrigues(signal, sampling_rate=1000):
    """Segmenter by Tiago Rodrigues, inspired by on Gutierrez-Rivas (2015) and Sadhukhan (2012).

    References
    ----------
    - Gutiérrez-Rivas, R., García, J. J., Marnane, W. P., & Hernández, A. (2015). Novel real-time
      low-complexity QRS complex detector based on adaptive thresholding. IEEE Sensors Journal,
      15(10), 6036-6043.

    - Sadhukhan, D., & Mitra, M. (2012). R-peak detection algorithm for ECG using double difference
      and RR interval processing. Procedia Technology, 4, 873-877.

    """

    N = int(np.round(3 * sampling_rate / 128))
    Nd = N - 1
    Pth = (0.7 * sampling_rate) / 128 + 2.7
    # Pth = 3, optimal for fs = 250 Hz
    Rmin = 0.26

    rpeaks = []
    i = 1
    Ramptotal = 0

    # Double derivative squared
    diff_ecg = [signal[i] - signal[i - Nd] for i in range(Nd, len(signal))]
    ddiff_ecg = [diff_ecg[i] - diff_ecg[i - 1] for i in range(1, len(diff_ecg))]
    squar = np.square(ddiff_ecg)

    # Integrate moving window
    b = np.array(np.ones(N))
    a = [1]
    processed_ecg = scipy.signal.lfilter(b, a, squar)
    tf = len(processed_ecg)

    # R-peak finder FSM
    while i < tf:  # ignore last second of recording
        # State 1: looking for maximum
        tf1 = np.round(i + Rmin * sampling_rate)
        Rpeakamp = 0
        while i < tf1:
            # Rpeak amplitude and position
          if processed_ecg[i] > Rpeakamp:

E IndexError: index 299988 is out of bounds for axis 0 with size 299988

C:\ProgramData\miniforge3\envs\hrv\lib\site-packages\neurokit2\ecg\ecg_findpeaks.py:985: IndexErro

Thanks.

FrancisThibaultNRC avatar Sep 28 '21 14:09 FrancisThibaultNRC

Looks a bit similar to a previous bug but not exactly the same.

FrancisThibaultNRC avatar Sep 28 '21 17:09 FrancisThibaultNRC

Hi @TiagoTostas

Could you help us to look at this out-of-bound error? It seems to be related to #465 but the error is at stage 1 now.

https://github.com/neuropsychology/NeuroKit/blob/c1104386655724a5c624e740abf651c939fc5e48/neurokit2/ecg/ecg_findpeaks.py#L983

Would it help if we assert in the line above an additional condition of i < tf?

Tam-Pham avatar Nov 09 '21 08:11 Tam-Pham

@TiagoTostas bump

DominiqueMakowski avatar Feb 15 '22 02:02 DominiqueMakowski

I added a small fix, @manef1994 @FrancisThibaultNRC do let us know if that fixes it correctly (you'll need to install the dev branch)

DominiqueMakowski avatar Jun 01 '22 00:06 DominiqueMakowski

i got this bug now:

Traceback (most recent call last): File "C:\Users\Ftay\PycharmProjects\R peaks verification trc\main.py", line 344, in r_peaks = nk.ecg_peaks(signal_output, sampling_rate=fs,method="rodrigues2021") File "C:\Users\Ftay\AppData\Local\Programs\Python\Python310\lib\site-packages\neurokit2\ecg\ecg_peaks.py", line 199, in ecg_peaks rpeaks = ecg_findpeaks(ecg_cleaned, sampling_rate=sampling_rate, method=method, **kwargs) File "C:\Users\Ftay\AppData\Local\Programs\Python\Python310\lib\site-packages\neurokit2\ecg\ecg_findpeaks.py", line 65, in ecg_findpeaks rpeaks = func(ecg_cleaned, sampling_rate=sampling_rate, show=show, **kwargs) File "C:\Users\Ftay\AppData\Local\Programs\Python\Python310\lib\site-packages\neurokit2\ecg\ecg_findpeaks.py", line 1006, in _ecg_findpeaks_rodrigues rpeaks.append(rpeakpos) UnboundLocalError: local variable 'rpeakpos' referenced before assignment

manef1994 avatar Jun 01 '22 08:06 manef1994

I pushed another fix, can you give it another try?

DominiqueMakowski avatar Jun 01 '22 08:06 DominiqueMakowski

well this bug occured:

Traceback (most recent call last): File "C:\Users\Ftay\PycharmProjects\R peaks verification trc\main.py", line 331, in r_peaks = nk.ecg_peaks(signal_output, sampling_rate=fs,method="rodrigues2021") File "C:\Users\Ftay\AppData\Local\Programs\Python\Python310\lib\site-packages\neurokit2\ecg\ecg_peaks.py", line 199, in ecg_peaks rpeaks = ecg_findpeaks(ecg_cleaned, sampling_rate=sampling_rate, method=method, **kwargs) File "C:\Users\Ftay\AppData\Local\Programs\Python\Python310\lib\site-packages\neurokit2\ecg\ecg_findpeaks.py", line 62, in ecg_findpeaks rpeaks = func(ecg_cleaned, sampling_rate=sampling_rate, show=show, **kwargs) File "C:\Users\Ftay\AppData\Local\Programs\Python\Python310\lib\site-packages\neurokit2\ecg\ecg_findpeaks.py", line 1006, in _ecg_findpeaks_rodrigues d = tf1 - rpeakpos TypeError: unsupported operand type(s) for -: 'float' and 'NoneType'

manef1994 avatar Jun 01 '22 08:06 manef1994

Thanks for your help! I pushed another update which hopefully will work 🤞

DominiqueMakowski avatar Jun 01 '22 09:06 DominiqueMakowski

I did multiple tests on different acquisitions and it worked finally. Thansk !

manef1994 avatar Jun 01 '22 10:06 manef1994