Дискретное преобразование Фурье: как правильно использовать fftshift с fft
Я хочу численно вычислить БПФ на массиве numpy Y. Для тестирования я использую гауссовскую функцию Y = exp (- x^2). (Символическое) преобразование Фурье равно Y ' = constant * exp (- k^2/4).
import numpy
X = numpy.arange(-100,100)
Y = numpy.exp(-(X/5.0)**2)
наивный подход терпит неудачу:
from numpy.fft import *
from matplotlib import pyplot
def plotReIm(x,y):
f = pyplot.figure()
ax = f.add_subplot(111)
ax.plot(x, numpy.real(y), 'b', label='R()')
ax.plot(x, numpy.imag(y), 'r:', label='I()')
ax.plot(x, numpy.abs(y), 'k--', label='abs()')
ax.legend()
Y_k = fftshift(fft(Y))
k = fftshift(fftfreq(len(Y)))
plotReIm(k,Y_k)
реальные (Y_k) скачки между положительными и отрицательными значениями, которые соответствуют фазе прыжка, которая отсутствует в символическом результате. Это, конечно, нежелательно. (Результат технически корректен в том смысле, что abs(Y_k) дает амплитуды, как и ожидалось, ifft (Y_k) - Y.)
здесь функция fftshift () монотонно увеличивает массив k и соответственно изменяет Y_k. Пары zip (k, Y_k) не изменяются, применяя эту операцию к обоим векторам.
эти изменения, похоже, устраняют проблему:
Y_k = fftshift(fft(ifftshift(Y)))
k = fftshift(fftfreq(len(Y)))
plotReIm(k,Y_k)
это правильный способ использовать функцию fft (), если требуются монотонные Y и Y_k?
обратная операция выше:
Yx = fftshift(ifft(ifftshift(Y_k)))
x = fftshift(fftfreq(len(Y_k), k[1] - k[0]))
plotReIm(x,Yx)
в этом случае документация ясно заявляет, что Y_k должен быть отсортирован совместимым с выходом fft() и fftfreq (), которого мы можем достичь, применяя ifftshift().
эти вопросы беспокоили меня в течение длительного времени: являются ли выходные и входные массивы как fft (), так и ifft() всегда такими, что a[0] should contain the zero frequency term, a[1:n/2+1] should contain the positive-frequency terms, and a[n/2+1:] should contain the negative-frequency terms, in order of decreasingly negative frequency
[ссылка numpy], где "частота" является независимой переменной?
ответ Фурье Преобразование Гаусса не является гауссовским не отвечает на мой вопрос.
2 ответов
БПФ можно рассматривать как создание множества векторов с амплитудой и фазой. Операция fft_shift изменяет опорную точку для фазового угла нуля от края апертуры FFT до центра исходного вектора входных данных.
фаза (и, следовательно, реальная составляющая комплексного вектора) результата иногда менее "скачкообразна", когда это делается, особенно если некоторая входная функция оконтурена таким образом, что она прерывна по краям Диафрагма БПФ. Или, если вход симметричен вокруг центра диафрагмы FFT, фаза результата FFT всегда будет равна нулю после fft_shift.
fft_shift может быть сделано с помощью вектора поворота N / 2, или просто листать чередующиеся биты знака в результате FFT, который может быть более CPU dcache дружественным.
определение для вывода fft
(и ifft
) здесь: http://docs.scipy.org/doc/numpy/reference/routines.fft.html#background-information
Это то, что процедуры вычисления, не больше и не меньше. Заметим, что дискретное преобразование Фурье сильно отличается от непрерывного преобразования Фурье. Для плотно отобранной функции существует связь между ними, но эта связь также включает в себя фазовые факторы и масштабирование в дополнение к fftshift
. Это причина колебаний, которые вы видите в своем сюжете. Необходимый фазовый фактор вы можете разработать самостоятельно из приведенной выше математической формулы для ДПФ.