2020-02-13 16:38:54 +01:00
#!/usr/bin/env python3
import numpy as np
# Example Functions
def func1 ( x ) :
return np . exp ( 20 j * x ) + np . exp ( 40 j * x )
def func2 ( x ) :
return np . exp ( 5 j * x * * 2 )
####################
# Fourier Transforms
####################
def DFT ( yk ) :
N = np . size ( yk )
xk = 2 * np . pi / N * np . arange ( N )
2020-02-20 14:02:28 +01:00
beta = np . zeros ( N , dtype = np . complex128 )
2020-02-13 16:38:54 +01:00
for j in range ( N ) :
beta [ j ] = np . dot ( yk , np . exp ( - 1 j * j * xk ) )
return beta
def FFT ( yk ) :
N = np . size ( yk )
if ( N % 2 > 0 ) :
raise ValueError ( " The data set does not consist of 2^M values: " , N )
if N < = 2 :
return DFT ( yk )
else :
beta_even = FFT ( yk [ : : 2 ] )
beta_odd = FFT ( yk [ 1 : : 2 ] )
exp_terms = np . exp ( - 2 j * np . pi * np . arange ( 0 , N ) / N )
beta_even_full = np . concatenate ( [ beta_even , beta_even ] )
beta_odd_full = np . concatenate ( [ beta_odd , beta_odd ] )
return beta_even_full + exp_terms * beta_odd_full
# Plotting functions
2020-02-20 14:02:28 +01:00
def plot_DFTs ( N = 128 , fft1 = DFT , fft2 = np . fft . fft , datafuncs = [ func1 , func2 ] ) :
2020-02-13 16:38:54 +01:00
from matplotlib import pyplot
j = np . arange ( N )
xk = 2 * np . pi / N * np . arange ( N )
pyplot . subplot ( )
pyplot . title ( " Discrete Fourier Transform " )
pyplot . xlabel ( " j " )
pyplot . ylabel ( " |$ \\ beta_j$| " )
# First Function
for i , dataf in enumerate ( datafuncs ) :
pyplot . plot ( j , np . abs ( fft1 ( func1 ( xk ) ) ) , label = " {} {} " . format ( fft1 . __name__ , dataf . __name__ ) , linewidth = 3 )
pyplot . plot ( j , np . abs ( fft2 ( func1 ( xk ) ) ) , ' -- ' , label = " {} {} " . format ( fft1 . __name__ , dataf . __name__ ) )
pyplot . legend ( )
pyplot . show ( )
def time_FT_func ( func , yk , * args , * * kwargs ) :
import timeit
tOut = timeit . repeat ( stmt = lambda : func ( yk ) , * args , * * kwargs )
return np . mean ( tOut )
def plot_FT_func_timing ( func = DFT , M_max = 4 , repeat = 10 , number = 5 , show = True ) :
from matplotlib import pyplot
M = np . arange ( 1 , M_max )
Ns = 2 * * M
times = np . zeros ( M_max - 1 )
for i in range ( np . size ( times ) ) :
xk = 2 * np . pi / Ns [ i ] * np . arange ( Ns [ i ] )
yk = func1 ( xk )
times [ i ] = time_FT_func ( func , yk , repeat = repeat , number = number )
pyplot . subplot ( )
pyplot . title ( " Evaluation Time for {} * {} DFTs for each N " . format ( repeat , number ) )
pyplot . ylabel ( " Time (sec) " )
pyplot . xlabel ( " $N^2$ " )
pyplot . ticklabel_format ( scilimits = ( 0 , 0 ) )
pyplot . plot ( Ns * * 2 , times , " o: " , label = func . __name__ )
pyplot . legend ( )
if show :
pyplot . show ( )
if __name__ == " __main__ " :
2020-02-20 14:02:28 +01:00
plot_DFTs ( )
2020-02-13 16:38:54 +01:00
plot_DFTs ( fft1 = DFT , fft2 = FFT )
plot_FT_func_timing ( M_max = 9 , func = FFT , show = False ) # 12 takes 10 seconds, 13 takes 50 seconds
plot_FT_func_timing ( M_max = 9 , func = DFT ) # 12 takes 10 seconds, 13 takes 50 seconds