2009-11-11 178 views
93

Puedo escribir algo yo mismo buscando cero cruces de la primera derivada o algo así, pero parece una función bastante común para ser incluida en bibliotecas estándar. Alguien sabe de uno?Algoritmo de búsqueda de picos para Python/SciPy

Mi aplicación particular es una matriz 2D, pero por lo general se utiliza para encontrar picos en FFT, etc.

En concreto, en este tipo de problemas, hay múltiples picos fuertes, y luego un montón de pequeños " picos "que son causados ​​por ruido que debe ignorarse. Estos son solo ejemplos; no es mi datos reales: picos

1-dimensionales:

picos FFT output with peaks

2 dimensiones:

Radon transform output with circled peak

El pico-algoritmo de búsqueda sería encontrar la ubicación de estos picos (no solo sus valores), e idealmente encontraría el verdadero pico entre muestras, no solo el índice con valor máximo, probablemente usando quadratic interpolation o algo así.

Normalmente solo le importan unos pocos picos fuertes, por lo que se elegirían porque están por encima de un determinado umbral o porque son los primeros n picos de una lista ordenada, ordenados por amplitud.

Como dije, sé cómo escribir algo como esto yo mismo. Solo estoy preguntando si hay una función o paquete preexistente que se sabe que funciona bien.

Actualización:

I translated a MATLAB script y funciona bastante bien para el caso 1-D, pero podría ser mejor.

actualización Actualizado:

sixtenbe created a better version para el caso 1-D.

+0

@endolith ¿Tiene el archivo MATLAB original que ha traducido a python para esto? ¡Gracias! – Spacey

+0

@Mohammad: http://billauer.co.il/peakdet.html https://gist.github.com/250860#file_peakdet.m – endolith

+2

¿Qué pasa con esto: http://docs.scipy.org/doc/scipy /reference/generated/scipy.signal.find_peaks_cwt.html – dashesy

Respuesta

10

No creo que lo que está buscando sea proporcionado por SciPy. Yo escribiría el código yo mismo, en esta situación.

La interpolación y suavizado de splines de scipy.interpolate son bastante agradables y pueden ser bastante útiles para ajustar los picos y luego encontrar la ubicación de su máximo.

2

Existen funciones estadísticas y métodos estándar para encontrar valores atípicos a los datos, que es probablemente lo que necesita en el primer caso. Usar derivados resolvería tu segundo. Sin embargo, no estoy seguro de un método que resuelva tanto las funciones continuas como los datos muestreados.

6

La detección de picos en un espectro de manera confiable se ha estudiado bastante, por ejemplo todo el trabajo de modelado sinusoidal para señales de música/audio en la década de los 80. Busque "Modelado Sinusoidal" en la literatura.

Si sus señales son tan limpias como en el ejemplo, un simple "darme algo con una amplitud superior a N vecinos" debería funcionar razonablemente bien. Si tiene señales ruidosas, una forma simple pero efectiva es mirar sus picos a tiempo, para rastrearlos: luego detecta líneas espectrales en lugar de picos espectrales.IOW, calcula la FFT en una ventana deslizante de su señal, para obtener un conjunto de espectro a tiempo (también llamado espectrograma). Luego observa la evolución del pico espectral en el tiempo (es decir, en ventanas consecutivas).

+0

¿Mira los picos en el tiempo? Detecta líneas espectrales? No estoy seguro de lo que esto significa. ¿Funcionaría para ondas cuadradas? – endolith

+0

Traté de agregar alguna explicación, avíseme si esto aún no está claro. –

+0

Oh, estás hablando de usar STFT en lugar de FFT. Esta pregunta no se trata específicamente de FFT; eso es solo un ejemplo. Se trata de encontrar los picos en cualquier matriz general 1D o 2D. – endolith

38

Estoy viendo un problema similar, y he encontrado que algunas de las mejores referencias provienen de la química (a partir de los picos encontrados en datos de especificaciones de masas). Para una buena revisión exhaustiva de los algoritmos de búsqueda de picos, lea this. Esta es una de las mejores críticas de las técnicas de búsqueda de picos que he encontrado. (Las ondículas son las mejores para encontrar picos de este tipo en datos ruidosos).

Parece que sus picos están claramente definidos y no están ocultos en el ruido. Siendo este el caso, recomendaría usar derivados de savtizky-golay para encontrar los picos (si solo diferencia los datos anteriores, tendrá un aluvión de falsos positivos). Esta es una técnica muy efectiva y es bastante fácil de implementar (se necesita una clase matricial con operaciones básicas). Si simplemente encuentras el cruce por cero del primer derivado S-G, creo que serás feliz.

+2

Estaba buscando una solución de propósito general, no una que solo funciona en esas imágenes particulares. Adapte una secuencia de comandos MATLAB a Python y funciona decentemente. – endolith

+1

Derecho encendido. Matlab es una buena fuente de algoritmos. ¿Qué técnica usa el script? (Por cierto, SG es una técnica de uso muy general). – Paul

+2

Lo he vinculado arriba. Básicamente solo busca los máximos locales que son más grandes que un cierto umbral por encima de sus vecinos. Ciertamente hay mejores métodos. – endolith

14

Hay una función llamada en scipy scipy.signal.find_peaks_cwt que suena como es adecuado para sus necesidades, sin embargo, no tengo experiencia con él, así que no puedo recomendar ..

http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks_cwt.html

+8

Sí, eso no existía cuando pregunté esto, y todavía no estoy seguro de cómo usarlo – endolith

+1

Has añadido esto hace un tiempo, pero funcionó de maravilla. Usarlo es simple como un pastel. Simplemente pase la matriz y otra matriz (es decir, np.arange (1,10)) que enumera todos los anchos de picos que desea; buen beneficio para filtrar picos angostos o anchos si es necesario. ¡Gracias de nuevo! – Miles

10

Para los que no está seguro acerca de cuyo pico de búsqueda de algoritmos para usar en Python, aquí una visión rápida de las alternativas: https://github.com/MonsieurV/py-findpeaks

Queriendo yo un equivalente a la función de MatLab findpeaks, he encontrado que la detect_peaks function de Marcos Duarte es un buen partido.

bastante fácil de usar:

import numpy as np 
from vector import vector, plot_peaks 
from libs import detect_peaks 
print('Detect peaks with minimum height and distance filters.') 
indexes = detect_peaks.detect_peaks(vector, mph=7, mpd=2) 
print('Peaks are: %s' % (indexes)) 

que le dará:

detect_peaks results

1

Lo primero es lo primero, la definición de "pico" es vaga si sin más especificaciones. Por ejemplo, para la siguiente serie, ¿llamarías a 5-4-5 un pico o dos?

1-2-1-2-1-1-5-4-5-1-1-5-1

En este caso, se necesitan al menos dos umbrales: 1) un alto umbral solo por encima del cual puede registrarse un valor extremo como un pico; y 2) un umbral bajo para que los valores extremos separados por valores pequeños debajo de él se conviertan en dos picos.

La detección de picos es un tema bien estudiado en la literatura de Extreme Value Theory, también conocida como "desclustering of extreme values". Sus aplicaciones típicas incluyen la identificación de eventos de peligro basados ​​en lecturas continuas de variables ambientales, p. analizar la velocidad del viento para detectar eventos de tormenta.

Cuestiones relacionadas