2 votes

Compter les ondes dans un tracé en utilisant Python

Je viens de générer un graphique qui ressemble à celui ci-dessous ; j'essaie de compter combien de vagues complètes il y a dans ce graphique. Comme annoté, il devrait y avoir 7 vagues complètes. J'ai essayé de lisser le graphique mais je n'arrive à rien. J'ai aussi cherché find_peaks dans scipy mais il ne semble pas s'appliquer à cette situation car une vague peut avoir plusieurs pics.

enter image description here

EDIT :

Cette question découle d'un problème réel : déterminer le nombre d'étagères dans l'image (voir ci-dessous) :

enter image description here

Après le seuillage, j'obtiens le fichier de données ci-dessous :

Original : fichier-1

Moyenne sur les rangs : fichier-2

Le résultat du fichier 2 est le graphique présenté au début.

2voto

Péter Leéh Points 1668

Je pense qu'il est difficile de répondre à ce problème en général, car il existe des ensembles de données pour lesquels une solution pourrait fonctionner, et d'autres pour lesquels elle ne fonctionne pas. Vos données sont à l'envers, donc la première étape consiste à inverser y à -y Ainsi, les minimums seront interprétés comme des maximums (et prendront peut-être la valeur absolue pour éviter de traiter les nombres négatifs).

La première option consiste à utiliser scipy.signal.find_peaks . En connaissant vos données, vous pouvez utiliser certains des paramètres : d'après mon expérience, la hauteur, la distance et la proéminence sont les plus utiles. Il y a une bonne explication sur les paramètres de find_peaks . Cette méthode permet d'identifier correctement les pics dans la plupart des cas, mais nécessite du temps pour définir les arguments de manière appropriée.

Une solution similaire avec scipy.signal.find_peaks_cwt Dans ce cas (dans la plupart des cas), vous devrez ajuster le paramètre widths, qui est (d'après la documentation) :

Tableau 1-D des largeurs à utiliser pour le calcul de la matrice CWT. En général, cette plage doit couvrir la largeur attendue des pics d'intérêt.

Mais là encore, cela nécessite une certaine connaissance préalable de vos données.

Comme vous avez des données périodiques, vous pouvez peut-être utiliser la FFT pour trouver les fréquences caractéristiques et ajuster les paramètres à l'intérieur. find_peaks et find_peaks_cwt . Comme vous n'avez pas fourni l'ensemble des données, je n'ai que des données synthétiques à traiter. Notez que je renvoie len(peaks) - 1 parce qu'en général, sur les frontières, il y a une période supplémentaire qui est comptée.

import numpy as np
from scipy.signal import find_peaks, find_peaks_cwt
import matplotlib.pyplot as plt

# some generic data
x = np.linspace(0, 1000, 10000)
y = 250 + 100 * np.sin(0.08 * x) - np.random.normal(30, 20, 10000)

def count_waves_1(x, y):
    peaks, props = find_peaks(y, prominence=120, height= np.max(y) / 10, distance=200)
    # here you can make use of props to filter the peaks by different properties,
    # for example extract only the n largest prominence peak:
    #
    # ind = np.argpartition(props["prominences"], -n_largest)[-n_largest:]
    # peaks = peaks[ind]

    plt.plot(x, y)
    plt.plot(x[peaks], y[peaks], 'ro')
    return len(peaks) - 1

first_solution = count_waves_1(x, y)

def count_waves_2(x, y):
    peaks = find_peaks_cwt(y, widths=np.arange(100, 200))
    plt.plot(x, y)
    plt.plot(x[peaks], y[peaks], 'ro')
    return len(peaks) - 1

second_solution = count_waves_2(x, y)

print(first_solution, second_solution)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X