Ich schreibe diese zusätzliche Antwort, um die Ursprünge der Diffusion der Spikes bei der Verwendung von fft zu erklären und insbesondere das scipy.fftpack- Tutorial zu diskutieren, mit dem ich irgendwann nicht einverstanden bin.
In diesem Beispiel die Aufnahmezeit tmax=N*T=0.75
. Das Signal ist sin(50*2*pi*x)+0.5*sin(80*2*pi*x)
. Das Frequenzsignal sollte 2 Spitzen bei Frequenzen 50
und 80
mit Amplituden 1
und enthalten 0.5
. Wenn das analysierte Signal jedoch keine ganzzahlige Anzahl von Perioden aufweist, kann aufgrund der Verkürzung des Signals eine Diffusion auftreten:
- Pike 1:
50*tmax=37.5
=> Frequenz 50
ist kein Vielfaches von 1/tmax
=> Vorhandensein von Diffusion aufgrund von Signalabschneidung bei dieser Frequenz.
- Pike 2:
80*tmax=60
=> Frequenz 80
ist ein Vielfaches von 1/tmax
=> Keine Diffusion aufgrund von Signalabschneidung bei dieser Frequenz.
Hier ist ein Code, der das gleiche Signal wie im Tutorial ( sin(50*2*pi*x)+0.5*sin(80*2*pi*x)
) analysiert, jedoch mit geringfügigen Unterschieden:
- Das ursprüngliche Beispiel für scipy.fftpack.
- Das ursprüngliche Beispiel für scipy.fftpack mit einer ganzzahligen Anzahl von Signalperioden (
tmax=1.0
anstatt eine Kürzungsdiffusion 0.75
zu vermeiden).
- Das ursprüngliche Beispiel für scipy.fftpack mit einer ganzzahligen Anzahl von Signalperioden und wobei die Daten und Frequenzen der FFT-Theorie entnommen sind.
Der Code:
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack
N = 600
tmax = 3/4
T = tmax / N
x1 = np.linspace(0.0, N*T, N)
y1 = np.sin(50.0 * 2.0*np.pi*x1) + 0.5*np.sin(80.0 * 2.0*np.pi*x1)
yf1 = scipy.fftpack.fft(y1)
xf1 = np.linspace(0.0, 1.0/(2.0*T), N//2)
tmax = 1
T = tmax / N
x2 = np.linspace(0.0, N*T, N)
y2 = np.sin(50.0 * 2.0*np.pi*x2) + 0.5*np.sin(80.0 * 2.0*np.pi*x2)
yf2 = scipy.fftpack.fft(y2)
xf2 = np.linspace(0.0, 1.0/(2.0*T), N//2)
tmax = 1
T = tmax / N
x3 = T * np.arange(N)
y3 = np.sin(50.0 * 2.0*np.pi*x3) + 0.5*np.sin(80.0 * 2.0*np.pi*x3)
yf3 = scipy.fftpack.fft(y3)
xf3 = 1/(N*T) * np.arange(N)[:N//2]
fig, ax = plt.subplots()
ax.plot(xf1, 2.0/N * np.abs(yf1[:N//2]), label='fftpack tutorial')
ax.plot(xf2, 2.0/N * np.abs(yf2[:N//2]), label='Integer number of periods')
ax.plot(xf3, 2.0/N * np.abs(yf3[:N//2]), label='Correct positionning of dates')
plt.legend()
plt.grid()
plt.show()
Ausgabe:
Wie es hier sein kann, bleibt auch bei Verwendung einer ganzzahligen Anzahl von Perioden eine gewisse Diffusion bestehen. Dieses Verhalten ist auf eine schlechte Positionierung von Daten und Häufigkeiten im Tutorial scipy.fftpack zurückzuführen. Daher in der Theorie der diskreten Fourier-Transformationen:
- Das Signal sollte an Daten ausgewertet werden, an
t=0,T,...,(N-1)*T
denen T die Abtastperiode und die Gesamtdauer des Signals ist tmax=N*T
. Beachten Sie, dass wir bei anhalten tmax-T
.
- Die zugehörigen Frequenzen sind dort,
f=0,df,...,(N-1)*df
wo df=1/tmax=1/(N*T)
die Abtastfrequenz ist. Alle Harmonischen des Signals sollten ein Vielfaches der Abtastfrequenz sein, um eine Diffusion zu vermeiden.
Im obigen Beispiel können Sie sehen, dass die Verwendung von arange
anstelle von linspace
ermöglicht, eine zusätzliche Diffusion im Frequenzspektrum zu vermeiden. Darüber hinaus führt die Verwendung der linspace
Version auch zu einem Versatz der Spitzen, die sich bei etwas höheren Frequenzen befinden als sie sein sollten, wie auf dem ersten Bild zu sehen ist, wo sich die Spitzen etwas rechts von den Frequenzen 50
und befinden 80
.
Ich komme nur zu dem Schluss, dass das Verwendungsbeispiel durch den folgenden Code ersetzt werden sollte (der meiner Meinung nach weniger irreführend ist):
import numpy as np
from scipy.fftpack import fft
N = 600
T = 1.0 / 800.0
x = T*np.arange(N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
yf = fft(y)
xf = 1/(N*T)*np.arange(N//2)
import matplotlib.pyplot as plt
plt.plot(xf, 2.0/N * np.abs(yf[0:N//2]))
plt.grid()
plt.show()
Ausgabe (die zweite Spitze ist nicht mehr diffus):
Ich denke, diese Antwort bringt noch einige zusätzliche Erklärungen, wie man eine korrekt diskrete Fourier-Transformation anwendet. Offensichtlich ist meine Antwort zu lang und es gibt immer zusätzliche Dinge zu sagen (@ewerlopes hat zum Beispiel kurz über Aliasing gesprochen und es kann viel über Fensterung gesagt werden ), also werde ich aufhören. Ich denke, dass es sehr wichtig ist, die Prinzipien der diskreten Fourier-Transformation bei der Anwendung genau zu verstehen, da wir alle so viele Leute kennen, die hier und da Faktoren hinzufügen, wenn sie angewendet werden, um das zu erhalten, was sie wollen.