Search code examples
scipypython-3.6peakutils

How to reduce error in peak detection problem?


I am trying to identify the R peak of an ECG. I have used the following line of code to do this:

peaks=signal.find_peaks_cwt(signal_slice, widths=np.arange(1,80))
fig, ax = plt.subplots()
ax.set_title('Detect R peak')
ax.plot(signal_slice)
for peak in peaks:
ax.axvline(x=peak, color='r')

And I get the following output: enter image description here

However, with the following signal it inaccurately detects the smaller peak also.

enter image description here

Is there any extra parameter I could add to the scipy.signal.find_peaks_cwt to make this more accurate? Or any way of using peakutils to do so?

Now it has stopped wrongly detecting the small peaks, but still seems to randomly miss the large peak, does anyone know why? enter image description here


Solution

  • You should specify the widths to the expected width of the peak. From the Scipy documentation:

    1-D array of widths to use for calculating the CWT matrix. In general, this range should cover the expected width of peaks of interest.

    Here is an example to illustrate the effect of width.

    from scipy import signal
    xs = np.arange(0, 20*np.pi, 0.05)
    xs2 = np.arange(0, 20*np.pi, 0.025)
    data = np.sin(xs)
    data2 = np.sin(xs2)
    data= data + data2[:1257]
    peakind = signal.find_peaks_cwt(data, np.arange(1,200))
    peakind, xs[peakind], data[peakind]
    fig, ax = plt.subplots()
    ax.set_title('Detect R peak')
    ax.plot(data)
    for peak in peakind:
        ax.axvline(x=peak, color='r')
    

    This results in only the global peaks. One peak

    But if you change the width to np.arange(1,100), you will also see the other local peak.

    peakind = signal.find_peaks_cwt(data, np.arange(1,100))
    

    Here the methods detects more peaks due to the difference in width. Two peaks in the same data