8
votes

Analyse de fréquence Scipey FFT du signal très bruyant

J'ai Noisy Data pour lequel je veux calculer fréquence et amplitude. Les échantillons ont été collectés toutes les 1 / 100e seconde. De ces tendances, je crois que la fréquence d'être ~ 0.3

Entrez la description de l'image ici P>

Lorsque j'utilise numpy code> FFT code>, je finis à obtenir une très haute fréquence (36,32 / sec) qui n'est clairement pas correcte. J'ai essayé de filtrer les données avec pandas code> rolling_mean code> pour supprimer le bruit avant la FFT, mais cela n'a pas trop fonctionné. P>

import pandas as pd
from numpy import fft
import numpy as np
import matplotlib.pyplot as plt

Moisture_mean_x = pd.read_excel("signal.xlsx", header = None)
Moisture_mean_x = pd.rolling_mean(Moisture_mean_x, 10) # doesn't helps
Moisture_mean_x = Moisture_mean_x.dropna()
Moisture_mean_x = Moisture_mean_x -Moisture_mean_x.mean()
frate = 100. #/sec           
Hn = fft.fft(Moisture_mean_x)
freqs = fft.fftfreq(len(Hn), 1/frate)
idx = np.argmax(np.abs(Hn))
freq_in_hertz = freqs[idx]


4 commentaires

1) Le code va bien. 2) Pourquoi vous attendez-vous à 0,3 Hz? Je compte 6/8 pics en 2500 secondes, pour une estimation d'un Freq à faible freq dominant d'environ 0,0024 à 0,0032 Hz. 3) Quel est le problème avec 36.32 Hz, c'est-à-dire pourquoi êtes-vous sûr que cela n'est pas correct? 4) Si vous voulez vraiment préférer le signal avec une moyenne de rouleau, choisissez une taille de fenêtre différente de 1. Comme il est maintenant, l'appel à rolling_mean () ne fait rien.


@ GG349 Je suppose que la photo affiche 2500 échantillons, pas de 2500 secondes. Cela rend votre plage de 0,24 à 0,32 Hz qui contient certainement 0,3.


@MarkRansom bien repéré


Désolé, c'était typo avec rolling_mean , corrigé-le maintenant.


6 Réponses :


0
votes

J'espère que cela peut vous aider.

https://scipy-cookbook.readthedocs.io/items/butterworthbandpass.html

Vous devez filtrer uniquement la bande autour de la fréquence attendue et améliorer le rapport de bruit du signal avant d'appliquer la FFT.

EDIT:

Mark Ransom a donné une réponse plus intelligente, si vous devez faire la FFT, vous pouvez simplement couper le bruit après la transformation. Cela ne donnera pas un résultat pire qu'un filtre.


3 commentaires

Pourquoi devez-vous filtrer? Mark Ransom Commentaire à l'autre post similaire. Pourquoi une valeur de 10 conduirait-elle à une moyenne géométrique?


Désolé, c'était typo. J'avais essayé rolling_mean (.., 10) et a reçu 36,4 Hz.


ARGH, vous avez raison, la réponse de la marque est la plus intelligente. J'ai mal compris les données de la demande. En fait, je ne comprends pas pourquoi sa réponse a été votée. +1



-1
votes

Vous devez utiliser un filtre passe-bas, qui doit conserver les variations périodiques plus grandes et lisser d'abord certaines des trucs de fréquence la plus élevée. Après cela, alors peut faire FFT pour obtenir les sommets. Voici un Recette du filtre à sapin généralement utilisé pour ce type de chose exacte.


1 commentaires

Le filtrage est totalement redondant, la FFT divise déjà des trucs par la fréquence. Il est juste nécessaire d'ignorer ces parties du résultat de la FFT qui correspondent aux fréquences en dehors de la gamme d'intérêts.



1
votes

Un FFT est une banque de filtres. Il suffit de rechercher le pic de magnitude seulement dans la plage de fréquences attendue du résultat FFT (au lieu de tout le vecteur de résultat), et la plupart des autres spectres seront essentiellement filtrés.


3 commentaires

Merci. J'ai également pensé à cela, mais je n'ai donné qu'un seul échantillon pour la question ici, alors que j'ai des centaines de tels signaux à analyser. La sélection de la gamme de fréquences attendue manuellement sera très fastidieuse. Y a-t-il un meilleur moyen de vous automatiquement calculer cette gamme de fréquences?


Vous ne pouvez pas filtrer sans savoir quelles fréquences pour essayer de supprimer (et donc ce qui reste). Même une moyenne mobile est un filtre (de mauvaise qualité). Vous devez donc savoir quelle gamme à espérer ou laisser le résultat bruyant non filtré et prendre ce que vous obtenez.


Je comprends que la moyenne mobile est un filtre de mauvaise qualité, mais je m'attendais à cela me rapprocherait de la fréquence attendue. Mais, même si j'utilisais Rolling Working Mean (..., 100) qui me donne un signal assez lissé [1], le résultat reste 34,8 Hz! Cela me donne sentir que je manque quelque chose. [1] Dropbox.com/s/75e0pgdcdzue9a5/smooth_signal.png?dl = 0



1
votes

Il n'est pas nécessaire de filtrer le signal à l'avance, car la FFT est un filtre. Il suffit de sauter ces parties de la FFT correspondant aux fréquences que vous savez contenir beaucoup de bruit - zéro-les ou les exclure autrement.


3 commentaires

Non, vous n'êtes pas obligé. Le signal est valorisé réel, alors étudier ainsi que le composant de fréquence négatif est redondant et conduira au même résultat.


@ GG349 Absolument correct, je n'ai pas réalisé que FFT renvoyait des valeurs complexes non réelles. Je vais supprimer les parties inexactes de cette réponse, qui devrait en être la plupart.


@MarkRansom Je suis d'accord, et cela semble être la seule solution jusqu'à présent. Mais, je me demande même si j'avais complètement le bruit le signal pour calculer le Fréquence, le résultat reste 34,8 Hz! Cela me donne un sentiment que je manque quelques étapes dans le code.



5
votes

Vous avez raison, il y a quelque chose qui ne va pas. Il faut expliquer à Explictiy Demander aux Pandas pour la colonne Zeroth:

Hn = np.fft.fft(Moisture_mean_x[0])


1 commentaires

En effet. Et maintenant, aucun filtrage n'est également nécessaire. Merci!



4
votes

semble que @tillsten em> a déjà répondu à votre question, mais voici une certaine confirmation supplémentaire. La première intrigue est vos données (zéro moyenne et je l'ai changée à un CSV). La seconde est la densité spectrale de puissance et vous pouvez voir une masse grasse avec un pic à ~ 0,3 Hz. J'ai zoomé dans le troisième parcelle pour voir s'il y avait une deuxième fréquence cachée proche de la fréquence principale.

Main freq: 0.32012805122
RMS amp: 0.0556044913489


2 commentaires

Oui, j'ai également remarqué la fréquence cachée. Donc, je calcule la fréquence moyenne comme suit: freqs = fft.ftfreq (len (hn), 1 / frère); ind = np.arange (1, len (hn) / 2 + 1); psd = np.abs (hn [ind]) ** 2+ np.abs (hn [-ind]) ** 2; couper = 0,7 * psd.max (); ind1 = np.where (PSD> coupé); FREQ_IN_HERTZ = FREQS [IND [IND1]]. moyenne () .


Ça marche. Vous pouvez également trouver le deuxième pic par idx = np.argmax (np.abs (hn) [: 5]) freq_in_hertz = freqs [idx] et il s'avère être 0.16006402561 (exactement la moitié de 0.32012 ...).