Pull to refresh

О классификации методов преобразования Фурье на примерах их программной реализации средствами Python

Reading time7 min
Views28K

Введение


Публикации по методу Фурье условно можно разделить на две группы. Первая группа так называемых познавательных публикаций, например, [1,2].

Вторая группа публикаций касается применения преобразований Фурье в технике, например, при спектральном анализе [3,4].

Ни в коем случае не умоляя достоинства этих групп публикации стоит признать, что без классификации, или хотя бы попытки осуществить такую классификацию, получить системное представление о методе Фурье, по моему мнению, затруднительно.

Задачи публикации


Провести классификацию методов преобразования Фурье на примерах их программной реализации средствами Python. При этом для облегчения чтения использовать формулы только в программном коде с соответствующими пояснениями.

Гармонический анализ и синтез


Гармоническим анализом называют разложение функции f(t), заданной на отрезке [0, Т] в ряд Фурье или в вычислении коэффициентов Фурье по формулам.

Гармоническим синтезом называют получение колебаний сложной формы путем суммирования их гармонических составляющих (гармоник).

Программная реализация
#!/usr/bin/python
# -*- coding: utf-8 -*
from scipy.integrate import quad # модуль для интегрирования
import matplotlib.pyplot as plt # модуль для графиков
import numpy as np # модуль для операций со списками и массивами
T=np.pi; w=2*np.pi/T# период и круговая частота
def func(t):# анализируемая функция
         if t<np.pi:
                  p=np.cos(t)
         else:
                  p=-np.cos(t)
         return p
def func_1(t,k,w):# функция для расчёта коэффициента a[k] 
         if t<np.pi:
                  z=np.cos(t)*np.cos(w*k*t)
         else:
                  z=-np.cos(t)*np.cos(w*k*t)
         return z
def func_2(t,k,w):#функция для расчёта коэффициента b[k] 
         if t<np.pi:
                  y=np.cos(t)*np.sin(w*k*t)
         else:
                  y=-np.cos(t)*np.sin(w*k*t)
         return y
a=[];b=[];c=4;g=[];m=np.arange(0,c,1);q=np.arange(0,2*np.pi,0.01)# подготовка списков для численного анализа
a=[round(2*quad(func_1, 0, T, args=(k,w))[0]/T,3) for k in m]# интеграл для a[k], k -номер гармоники 
b=[round(2*quad(func_2, 0, T, args=(k,w))[0]/T,3) for k in m]# интеграл для b[k], k -номер гармоники
F1=[a[1]*np.cos(w*1*t)+b[1]*np.sin(w*1*t) for t in q]#функции для гармоник
F2=[a[2]*np.cos(w*2*t)+b[2]*np.sin(w*2*t) for t in q]
F3=[a[3]*np.cos(w*3*t)+b[3]*np.sin(w*3*t) for t in q]
plt.figure()
plt.title("Классический гармонический анализ функции \n при t<pi  f(t)=cos(t)  при t>=pi  f(t)=-cos(t)")
plt.plot(q, F1, label='1 гармоника')
plt.plot(q, F2 , label='2 гармоника')
plt.plot(q, F3, label='3 гармоника')
plt.xlabel("Время t")
plt.ylabel("Амплитуда А")
plt.legend(loc='best')
plt.grid(True)
F=np.array(a[0]/2)+np.array([0*t for t in q-1])# подготовка массива для анализа с a[0]/2
for k in np.arange(1,c,1):
         F=F+np.array([a[k]*np.cos(w*k*t)+b[k]*np.sin(w*k*t) for t in q])# вычисление членов ряда Фурье
plt.figure()
P=[func(t) for t in q]
plt.title("Классический гармонический синтез")
plt.plot(q, P, label='f(t)')
plt.plot(q, F, label='F(t)')
plt.xlabel("Время t")
plt.ylabel("f(t),F(t)")
plt.legend(loc='best')
plt.grid(True)
plt.show()


Результат






Спектральный анализ периодических функций заключается в нахождении амплитуды Аk и фазы j k гармоник (косинусоид) ряда Фурье. Задача, обратная спектральному анализу, называется спектральным синтезом.

Программная реализация для спектрального анализа и синтеза без специальных функций NumPy для Фурье преобразования
#!/usr/bin/python
# -*- coding: utf-8 -*
from scipy.integrate import quad # модуль для интегрирования
import matplotlib.pyplot as plt # модуль для графиков
import numpy as np # модуль для операций со списками и массивами
T=np.pi; w=2*np.pi/T# период и круговая частота
def func(t):# анализируемая функция
         if t<np.pi:
                  p=np.cos(t)
         else:
                  p=-np.cos(t)
         return p
def func_1(t,k,w):# функция для расчёта коэффициента a[k] 
         if t<np.pi:
                  z=np.cos(t)*np.cos(w*k*t)
         else:
                  z=-np.cos(t)*np.cos(w*k*t)
         return z
def func_2(t,k,w):#функция для расчёта коэффициента b[k] 
         if t<np.pi:
                  y=np.cos(t)*np.sin(w*k*t)
         else:
                  y=-np.cos(t)*np.sin(w*k*t)
         return y
a=[];b=[];c=4;g=[];m=np.arange(0,c,1);q=np.arange(0,2*np.pi,0.01)# подготовка списков для численного анализа
a=[round(2*quad(func_1, 0, T, args=(k,w))[0]/T,3) for k in m]# интеграл для a[k], k -номер гармоники 
b=[round(2*quad(func_2, 0, T, args=(k,w))[0]/T,3) for k in m]# интеграл для b[k], k -номер гармоники
plt.figure()
plt.title("Спектральный анализ \n Спектр амплитуд-A[k]")
A=np.array([(a[k]**2+b[k]**2)**0.5 for k in m])# численные значения амплитуды гармоник
plt.plot([m[1],m[1]],[0,A[1]],label='1 гармоника')
plt.plot([m[2],m[2]],[0,A[2]],label='2 гармоника')
plt.plot([m[3],m[3]],[0,A[3]],label='3 гармоника')
plt.xlabel("Номер гармоники")
plt.ylabel("Амплитуда")
plt.legend(loc='best')
plt.grid(True)
for k in m:#вычисление численных значений фазы
         if a[k]!=0:
                  g.append(-np.tanh(b[k]/a[k]))                  
         else:
                  g.append(-np.pi/2)# фаза когда тангенс равен бесконечности
plt.figure()
plt.title("Спектральный анализ \n Спектр фаз -g(k)")
plt.plot([m[1],m[1]],[0, g[1]],label='Фаза 1 гармоники')
plt.plot([m[2],m[2]],[0, g[2]],label='Фаза 2 гармоники')
plt.plot([m[3],m[3]],[0, g[3]],label='Фаза 3 гармоники')
plt.xlabel("Номер гармоники")
plt.ylabel("Фаза")
plt.legend(loc='best')
plt.grid(True)
plt.figure()
plt.title("Спектральный синтез - FK=A[k]*cos(w*k*t+g[k])")
FK=-np.array(a[0]/2)+np.array([0*t for t in q-1])#подготовка массива длячисленного синтеза 
for k in m:       
         FK=FK+np.array([A[k]*np.cos(w*k*t+g[k]) for t in q])# численный спектральный синтез
P=[func(t) for t in q]
plt.plot(q, P, label='f(t)')
plt.plot(q, FK, label='FK(t)')
plt.xlabel("Время t")
plt.ylabel("f(t),FK(t)")
plt.legend(loc='best')
plt.grid(True)
plt.show()


Результат








Программная реализация спектрального анализа и синтеза с использованием функций NumPy прямого быстрого преобразования Фурье – rfft и обратного преобразования – irfft
#!/usr/bin/python
# -*- coding: utf-8 -*
import matplotlib.pyplot as plt 
import numpy as np
import numpy.fft 
T=np.pi;z=T/16; m=[k*z for k in np.arange(0,16,1)];arg=[];q=[]#  16 отсчётов на период в пи
def f(t):# анализируемая функция
         if t<np.pi:
                  p=np.cos(t)
         else:
                  p=-np.cos(t)
         return p
v=[f(t) for t in m]
F=np.fft.rfft(v, n=None, axis=-1) # прямое быстрое преобразование Фурье в частотную область
A=[((F[i].real)**2+(F[i].imag)**2)**0.5 for i in np.arange(0,7,1)]#модуль амплитуды
for i in np.arange(0,7,1):# определение фазы
         if F[i].imag!=0:
                  t=(-np.tanh((F[i].real)/(F[i].imag)))
                  arg.append(t)                  
         else:
                arg.append(np.pi/2)
plt.figure()
plt.title("Спектральный анализ с использованием  прямого БПФ ")
plt.plot(np.arange(0,7,1),arg,label='Фаза')
plt.plot(np.arange(0,7,1),A,label='Амплитуда')
plt.xlabel("Частота")
plt.ylabel("Фаза,Амплитуда")
plt.legend(loc='best')
plt.grid(True)
for i in np.arange(0,9,1):
         if i<=7:
                  q.append(F[i])
         else:
                  q.append(0)
h=np.fft.irfft(q, n=None, axis=-1)# обратное быстрое преобразование Фурье во временную область
plt.figure()
plt.title("Спектральный синтез с использованием  обратного БПФ ")
plt.plot(m, v,label='Исходная функция')
plt.plot(m, h,label='Синтезированная функция')
plt.xlabel("Время")
plt.ylabel("Амплитуда")
plt.legend(loc='best')
plt.grid(True)          
plt.show()






Фильтрация аналоговых сигналов


Под фильтрацией подразумевается выделение полезного сигнала из его смеси с мешающим сигналом — шумом. Наиболее распространенный тип фильтрации — частотная фильтрация. Если известна область частот, занимаемых полезным сигналом, достаточно выделить эту область и подавить те области, которые заняты шумом.

Программная реализация иллюстрирует технику фильтрации с применением БПФ. Сначала синтезируется исходный сигнал, представленный 128 отсчетами вектора v. Затем к этому сигналу присоединяется шум с помощью генератора случайных чисел (функция np. random.uniform(0,0.5)) и формируется вектор из 128 отсчетов зашумленного сигнала.

Программная реализация
#!/usr/bin/python
# -*- coding: utf-8 -*
import matplotlib.pyplot as plt 
import numpy as np
from numpy.fft import rfft, irfft
from numpy.random import uniform
k=np.arange(0,128,1)
T=np.pi;z=T/128; m=[t*z for t in k]#задание для дискретизации функции на 128 отсчётов
def f(t):#анализируемая функция
         if t<np.pi:
                  p=np.cos(t)
         else:
                  p=-np.cos(t)
         return p
def FH(x):# ступенчатая функция Хэвисайда 
         if x>=0:
                  q=1
         else:
                  q=0
         return q
v=[f(t) for t in m]#дискретизация исходной функции
vs= [f(t)+np.random.uniform(0,0.5) for t in m]# добавление шума
plt.figure()
plt.title("Фильтрация аналоговых сигналов  \n Окно исходной и зашумленной функций")
plt.plot(k,v, label='Окно исходной функции шириной pi')
plt.plot(k,vs,label='Окно зашумленной функции шириной pi')
plt.xlabel("Отсчёты -k")
plt.ylabel("Амплитуда А")
plt.legend(loc='best')
plt.grid(True)
al=2# степень фильтрации высших гармоник
fs=np. fft.rfft(v)# переход из временной области в частотную с помощью БПФ
g=[fs[j]*FH(abs(fs[j])-2) for j in np.arange(0,65,1)]# фильтрация высших гармоник
h=np.fft.irfft(g) # возврат во временную область
plt.figure()
plt.title("Фильтрация аналоговых сигналов  \n Результат фильтрации")
plt.plot(k,v,label='Окно исходной функции шириной pi')
plt.plot(k,h, label='Окно результата фильтрации шириной pi')
plt.xlabel("Отсчёты -k")
plt.ylabel("Амплитуда А")
plt.legend(loc='best')
plt.grid(True)
plt.show()


Результат






Решение дифференциальных уравнений в частных производных


Алгоритм решения дифференциальных уравнений математической физики с использованием прямого и обратного БПФ приведен в [5]. Воспользуемся приведенными данными для программной реализации на Python решения дифференциального уравнения распространения тепла в стержне с применением преобразования Фурье.

Программная реализация
#!/usr/bin/env python
#coding=utf8
import numpy as np
from numpy.fft import fft, ifft # функции быстрого прямого и обратного преобразования Фурье
import pylab# модуль построения поверхности
from mpl_toolkits.mplot3d import Axes3D# модуль построения поверхности
n=50# стержень длиной 2 пи разбивается на 50 точек
times=10# количества итераций во времени
h=0.01# шаг по времени
x=[r*2*np.pi/n  for r in np.arange(0,n)]# дискретизация х
w= np.fft.fftfreq(n,0.02)# сдвиг нулевой частотной составляющей к центру спектра
k2=[ r**2 for r in w]# коэффициенты разложения 
u0 =[2 +np.sin(i) + np.sin(2*i) for i in x]# дискретизация начального распределения температуры вдоль стержня
u = np.zeros([times,n])# матрица нулей размерностью 10*50
u[0,:] = u0 # нудевые начальные условия
uf =np.fft. fft(u0) # коэффициенты Фурье начальной функции
for i in np.arange(1,times,1):         
         uf=uf*[(1-h*k) for k in k2]  #следующий временной шаг в пространстве Фурье      
         u[i,:]=np.fft.ifft(uf).real  #до конца физического пространства
X = np.zeros([times,n])# подготовка данных координаты х для поверхности
for i in np.arange(0,times,1):
         X[i:]=x
T = np.zeros([times,n])# подготовка данных координаты t для поверхности
for i in np.arange(0,times,1):
         T[i:]=[h*i for r in np.arange(0,n)]
fig = pylab.figure()
axes = Axes3D(fig)
axes.plot_surface(X, T, u)
pylab.show()       


Результат




Вывод


В статье приведена попытка классификации по областям применения методов преобразования Фурье.

Ссылки


  1. Математика на пальцах: давайте посчитаем хотя бы один ряд Фурье в уме.
  2. Простыми словами о преобразовании Фурье.
  3. Спектральный анализ сигналов нелинейных звеньев АСУ на Python.
  4. Математика в Python: Преобразование Фурье.
  5. Спектральный метод на примере простых задач матфизики.
Tags:
Hubs:
+6
Comments1

Articles

Change theme settings