2017-07-31 5 views
1

Je sais qu'il ya eu plusieurs questions sur l'utilisation de la méthode transformée de Fourier rapide (FFT) en python, mais malheureusement, aucun d'entre eux ne pouvait me aider avec mon problème:Deux FFT dimensions en utilisant les résultats de python légèrement décalé fréquence

I vouloir utiliser python pour calculer la Transformée de Fourier Rapide d'un signal bidimensionnel donné f, c'est-à-dire f (x, y). La documentation de Python aide beaucoup, en résolvant quelques problèmes, que la FFT apporte avec, mais je me retrouve quand même avec une fréquence légèrement décalée par rapport à la fréquence que je m'attends à ce qu'elle montre. Voici mon code python:

from scipy.fftpack import fft, fftfreq, fftshift 
import matplotlib.pyplot as plt 
import numpy as np 
import math 

fq = 3.0 # frequency of signal to be sampled 
N = 100.0 # Number of sample points within interval, on which signal is considered 
x = np.linspace(0, 2.0 * np.pi, N) # creating equally spaced vector from 0 to 2pi, with spacing 2pi/N 
y = x 
xx, yy = np.meshgrid(x, y) # create 2D meshgrid 
fnc = np.sin(2 * np.pi * fq * xx) # create a signal, which is simply a sine function with frequency fq = 3.0, modulating the x(!) direction 
ft = np.fft.fft2(fnc) # calculating the fft coefficients 

dx = x[1] - x[0] # spacing in x (and also y) direction (real space) 
sampleFrequency = 2.0 * np.pi/dx 
nyquisitFrequency = sampleFrequency/2.0 

freq_x = np.fft.fftfreq(ft.shape[0], d = dx) # return the DFT sample frequencies 
freq_y = np.fft.fftfreq(ft.shape[1], d = dx) 

freq_x = np.fft.fftshift(freq_x) # order sample frequencies, such that 0-th frequency is at center of spectrum 
freq_y = np.fft.fftshift(freq_y) 

half = len(ft)/2 + 1 # calculate half of spectrum length, in order to only show positive frequencies 

plt.imshow(
    2 * abs(ft[:half,:half])/half, 
    aspect = 'auto', 
    extent = (0, freq_x.max(), 0, freq_y.max()), 
    origin = 'lower', 
    interpolation = 'nearest', 
) 
plt.grid() 
plt.colorbar() 
plt.show() 

Et ce que je sors de ce lors de l'exécution, est:

FFT of signal

Maintenant, vous voyez que la fréquence dans la direction x est pas exactement à fq = 3, mais légèrement décalé vers la gauche. Pourquoi est-ce? Je suppose que c'est a à voir avec le fait que la FFT est un algorithme en utilisant des arguments de symétrie et

half = len(ft)/2 + 1 

est utilisé pour montrer les fréquences au bon endroit. Mais je ne comprends pas très bien quel est le problème exact et comment le réparer. Edit: J'ai également essayé d'utiliser une fréquence d'échantillonnage plus élevée (N = 10000.0), ce qui n'a pas résolu le problème, mais a légèrement décalé la fréquence légèrement trop vers la droite. Donc, je suis assez sûr que le problème n'est pas la fréquence d'échantillonnage.

Note: Je suis conscient du fait que l'effet de fuite conduit à des amplitudes non physiques ici, mais dans ce post, je suis principalement intéressé par les fréquences correctes.

+0

Comme votre grap h montre, le domaine fréquentiel est quantifié - et il semble que votre "problème" est que les quanta ne sont pas centrés sur la fréquence de votre signal. C'est JTWIW. Pensez-vous que la FFT devrait savoir par magie que l'entrée a une seule composante de fréquence? Si vous voulez le centrer, vous pouvez augmenter le nombre d'échantillons ou ajuster l'espacement. – barny

+0

Bien sûr, FFT ne sait pas "magiquement" que l'entrée a une seule composante de fréquence, mais comme vous l'avez suggéré, on peut s'attendre à ce que ce centrage s'améliore à mesure que la fréquence d'échantillonnage augmente. J'ai aussi simulé cela avec "N" plusieurs ordres de grandeur plus haut (N = 10000.0), ce qui déplace la fréquence légèrement trop loin vers la droite. Cela m'amène à la conclusion qu'il ne s'agit pas d'une fréquence d'échantillonnage ici. – Alienbash

+0

Alors modifiez cette recherche sur la question plutôt que de laisser les répondants possibles perdre leur temps à se demander quelles autres recherches vous avez faites et ne pas pris la peine de mettre dans la question. Ou ne pas prendre la peine de perdre son temps. – barny

Répondre

1

Je trouve un certain nombre de questions

vous utilisez 2 * np.pi deux fois, vous devez choisir l'un des deux linspace ou arg au sinus en radians si vous voulez un nombre entier agréable de cycles

en outre np.linspace par défaut à endpoint=True, vous donnant un point supplémentaire pour 101 au lieu de 100

fq = 3.0 # frequency of signal to be sampled 
N = 100 # Number of sample points within interval, on which signal is considered 
x = np.linspace(0, 1, N, endpoint=False) # creating equally spaced vector from 0 to 2pi, with spacing 2pi/N 
y = x 
xx, yy = np.meshgrid(x, y) # create 2D meshgrid 
fnc = np.sin(2 * np.pi * fq * xx) # create a signal, which is simply a sine function with frequency fq = 3.0, modulating the x(!) direction 

vous pouvez vérifier ces questions:

len(x) 
Out[228]: 100 

plt.plot(fnc[0]) 

fixer le point final de linspace signifie maintenant que vous avez un nombre pair de bacs fft de sorte que vous laissez tomber le + 1 dans le half calc

matshow() semble avoir de meilleurs paramètres par défaut, votre extent = (0, freq_x.max(), 0, freq_y.max()), en imshow semble Fubar la numérotation bin fft

from scipy.fftpack import fft, fftfreq, fftshift 
import matplotlib.pyplot as plt 
import numpy as np 
import math 

fq = 3.0 # frequency of signal to be sampled 
N = 100 # Number of sample points within interval, on which signal is considered 
x = np.linspace(0, 1, N, endpoint=False) # creating equally spaced vector from 0 to 2pi, with spacing 2pi/N 
y = x 
xx, yy = np.meshgrid(x, y) # create 2D meshgrid 
fnc = np.sin(2 * np.pi * fq * xx) # create a signal, which is simply a sine function with frequency fq = 3.0, modulating the x(!) direction 

plt.plot(fnc[0]) 

ft = np.fft.fft2(fnc) # calculating the fft coefficients 

#dx = x[1] - x[0] # spacing in x (and also y) direction (real space) 
#sampleFrequency = 2.0 * np.pi/dx 
#nyquisitFrequency = sampleFrequency/2.0 
# 
#freq_x = np.fft.fftfreq(ft.shape[0], d=dx) # return the DFT sample frequencies 
#freq_y = np.fft.fftfreq(ft.shape[1], d=dx) 
# 
#freq_x = np.fft.fftshift(freq_x) # order sample frequencies, such that 0-th frequency is at center of spectrum 
#freq_y = np.fft.fftshift(freq_y) 

half = len(ft) // 2 # calculate half of spectrum length, in order to only show positive frequencies 

plt.matshow(
      2 * abs(ft[:half, :half])/half, 
      aspect='auto', 
      origin='lower' 
      ) 
plt.grid() 
plt.colorbar() 
plt.show() 

zoomée la parcelle: enter image description here

+0

Merci beaucoup pour votre effort! Cela résout en fait le problème. "matshow()" semble être le bon choix ici. – Alienbash

+0

Cela soulèverait une autre question: l'utilisation de 'fftfreq' et de 'fftshift' n'est-elle pas un problème redondant, en utilisant simplement 'matshow()' au lieu de 'imshow()'? – Alienbash

+0

oui, ces calculs sont inutilisés, les a commentés – f5r5e5d