Алгоритм обнаружения пиков в Python - PullRequest
0 голосов
/ 08 июня 2018

Я реализую алгоритм обнаружения пиков в Python, который обнаруживает только те пики, которые превышают пороговую величину.Я не хочу использовать встроенную функцию, так как мне нужно расширить эту симуляцию и до аппаратной реализации.

from math import sin,isnan
from pylab import *

def peakdet(v, delta,thresh,x):
    delta=abs(delta)
    maxtab = []
    mintab = []

    v = asarray(v)

    mn, mx = v[0], v[0]
    mnpos, mxpos = NaN, NaN

    lookformax = True

    for i in arange(len(v)):
        this = v[i]
        if abs(this)>thresh:
            if this > mx:
                mx = this
                mxpos = x[i]
            if this < mn:
                mn = this
                mnpos = x[i]
            if lookformax:
                if (this < mx-delta):
                    if (mx>abs(thresh)) and not isnan(mxpos):
                        maxtab.append((mxpos, mx))
                    mn = this
                    mnpos = x[i]
                    lookformax = False
            else:
                if (this > mn+delta):
                    if (mn<-abs(thresh)) and not isnan(mnpos):
                        mintab.append((mnpos, mn))
                    mx = this
                    mxpos = x[i]
                    lookformax = True
    return array(maxtab), array(mintab)

#Input Signal
t=array(range(100))
series=0.3*sin(t)+0.7*cos(2*t)-0.5*sin(1.2*t)

thresh=0.95 #Threshold value
delta=0.0 #

a=zeros(len(t)) #
a[:]=thresh #

maxtab, mintab = peakdet(series,delta,thresh,t)

#Plotting output
scatter(array(maxtab)[:,0], array(maxtab)[:,1], color='red')
scatter(array(mintab)[:,0], array(mintab)[:,1], color='blue')
xlim([0,t[-1]])
title('Peak Detector')
grid(True)
plot(t,a,color='green',linestyle='--',dashes=(5,3))
plot(t,-a,color='green',linestyle='--',dashes=(5,3))
annotate('Threshold',xy=(t[-1],thresh),fontsize=9)
plot(t,series,'k')
show()

Проблема этой программы в том, что она не может обнаружить некоторые пики, даже если они превышают пороговое значение.Это вывод, который я получил:

Peak Detection Output

Я видел другие сообщения с проблемами обнаружения пиков, но не мог найти никакого решения.Пожалуйста, помогите и предложите исправления.

Ответы [ 3 ]

0 голосов
/ 08 июня 2018

Ваша функция использует довольно много параметров.Вы можете разбить проблему на несколько шагов:

  1. Сначала определите все точки выше порога.Добавьте эти точки в список maxthresh и minthresh.
  2. Выполните итерацию по списку maxthresh, и если значение y перед точкой меньше, чем точка, а значение y после точки равноменьше точки, то точка является пиком.
  3. Выполните итерацию по списку minthresh, и если значение y до точки больше, чем точка, а значение y после точки больше, чемточка, то точка является вершиной.

Реализация кода:

from math import sin
from matplotlib import pylab
from pylab import *

def peakdet(v, thresh):
    maxthresh = []
    minthresh = []
    peaks = []
    valleys = []

    for x, y in v:
        if y > thresh:
            maxthresh.append((x, y))
        elif y < -thresh:
            minthresh.append((x, y))

    for x, y in maxthresh:
        try:
            if (v[x - 1][1] < y) & (v[x + 1][1] < y):
                peaks.append((x, y))
        except Exception:
            pass

    for x, y in minthresh:
        try:
            if (v[x - 1][1] > y) & (v[x + 1][1] > y):
                valleys.append((x, y))
        except Exception:
            pass

    return peaks, valleys

Проверка кода:

# input signal
t = array(range(100))
series = 0.3 * sin(t) + 0.7 * cos(2 * t) - 0.5 * sin(1.2 * t)

arr = [*zip(t, series)]  # create a list of tuples where the tuples represent the (x, y) values of the function
thresh = 0.95

peaks, valleys = peakdet(arr, thresh)

scatter([x for x, y in peaks], [y for x, y in peaks], color = 'red')
scatter([x for x, y in valleys], [y for x, y in valleys], color = 'blue')
plot(t, 100 * [thresh], color='green', linestyle='--', dashes=(5, 3))
plot(t, 100 * [-thresh], color='green', linestyle='--', dashes=(5, 3))
plot(t, series, 'k')
show()

enter image description here

Дополнительный тест, чтобы убедиться, что пик обнаружен, когда несколько точек выше порога:

# input signal
t = array(range(100))
series = 6.3 * sin(t) + 4.7 * cos(2 * t) - 3.5 * sin(1.2 * t)

arr = [*zip(t, series)]
thresh = 0.95

peaks, valleys = peakdet(arr, thresh)

scatter([x for x, y in peaks], [y for x, y in peaks], color = 'red')
scatter([x for x, y in valleys], [y for x, y in valleys], color = 'blue')
plot(t, 100 * [thresh], color='green', linestyle='--', dashes=(5, 3))
plot(t, 100 * [-thresh], color='green', linestyle='--', dashes=(5, 3))
plot(t, series, 'k')
show()

enter image description here

0 голосов
/ 09 июня 2018

Итак, здесь у вас есть решение для numpythonic (что гораздо лучше, чем делать цикл в явном виде). ​​

Я использую функцию roll для смещения чисел +1 или -1 в позиции.Также «пик» определяется как локальный максимум, где предыдущее и заднее число меньше центрального значения.

Полный код указан выше:

import numpy as np
import matplotlib.pyplot as plt

# input signal
x = np.arange(1,100,1)
y = 0.3 * np.sin(t) + 0.7 * np.cos(2 * t) - 0.5 * np.sin(1.2 * t)
threshold = 0.95

# max
maxi = np.where(np.where([(y - np.roll(y,1) > 0) & (y - np.roll(y,-1) > 0)],y, 0)> threshold, y,np.nan)
# min
mini = np.where(np.where([(y - np.roll(y,1) < 0) & (y - np.roll(y,-1) < 0)],y, 0)< -threshold, y,np.nan)

, если вы строите его, вы получите:

enter image description here

0 голосов
/ 08 июня 2018

эти коды

        if lookformax:
            if (this < mx-delta):
                if (mx>abs(thresh)) and not isnan(mxpos):
                    maxtab.append((mxpos, mx))
                mn = this
                mnpos = x[i]
                lookformax = False
        else:
            if (this > mn+delta):
                if (mn<-abs(thresh)) and not isnan(mnpos):
                    mintab.append((mnpos, mn))
                mx = this
                mxpos = x[i]
                lookformax = True

работают только при условии

    if abs(this)>thresh:

, поэтому вы можете найти пик только тогда, когда следующая точка выше порога меньше его.

выложи условие

...