Fourier transform of a Gaussian function

Fourier transform of a Gaussian function#

[1]:
import math
import numpy as np
from bokeh.io import output_notebook

import fftarray as fa
from helpers import plt_array

output_notebook(hide_banner=True)

def fa_array_assert_all_close(space: fa.Space, a: fa.Array, b: fa.Array):
    # Since we compare a real-valued and a complex-valued array, we have to give some absolute tolerance.
    # Otherwise the imaginary values which move slightly away from zero would make the comparison fail.
    np.testing.assert_allclose(a.values(space, xp=np), b.values(space, xp=np), atol=4e-15)

def gauss_pos(x, a, sigma):
    return (a * fa.exp(-(x**2/(2.* sigma**2))))/(math.sqrt(2 * np.pi) * sigma)

def gauss_freq(f, a, sigma):
    return (a * fa.exp(-(1/2)*(2*np.pi*f)**2*sigma**2))

Initialize the dimension and get the basic x and f arrays.

[2]:
dim = fa.dim_from_constraints("x",
        pos_middle=1.,
        pos_extent = 10.,
        freq_middle = 2.5/(2*np.pi),
        freq_extent = 20./(2*np.pi),
        loose_params=["pos_extent", "freq_extent"]
    )


x = fa.coords_from_dim(dim, "pos")
f = fa.coords_from_dim(dim, "freq")

plt_array(x, data_name="Array (identity in pos space)")
plt_array(f, data_name="Array (identity in freq space)")
[3]:
gauss_from_pos = gauss_pos(a = 1.2, x = x, sigma = 0.7)
gauss_from_freq = gauss_freq(a = 1.2, f = f, sigma = 0.7)

fa_array_assert_all_close("pos", gauss_from_pos, gauss_from_freq)
fa_array_assert_all_close("freq", gauss_from_pos, gauss_from_freq)

plt_array(gauss_from_pos, data_name="Gauss (initialised with position)")
plt_array(gauss_from_freq, data_name="Gauss (initialised with frequency)")

Just compute a centered Gaussian in position and frequency space. It does not matter where it is defined, the result is the same (up to numerical inaccuracies).

[4]:
gauss_from_pos = fa.shift_freq(gauss_pos(a = 1.2, x = x, sigma = 0.7), {"x": 0.9})
gauss_from_freq = gauss_freq(a = 1.2, f = f - 0.9, sigma = 0.7)

fa_array_assert_all_close("pos", gauss_from_pos, gauss_from_freq)
fa_array_assert_all_close("freq", gauss_from_pos, gauss_from_freq)

plt_array(gauss_from_pos, data_name="Gauss (freq. shifted via FFT)")
plt_array(gauss_from_freq, data_name="Gauss (freq. shifted at init)")

Now we test this with a Gauss shifted in position space. The shift_position function multiplies a phase factor onto the Array in frequency space to achieve a user-defined shift.

[5]:
gauss_from_pos = gauss_pos(a = 1.2, x = x - 0.9, sigma = 0.7)
gauss_from_freq = fa.shift_pos(gauss_freq(a = 1.2, f = f, sigma = 0.7), {"x": 0.9})

fa_array_assert_all_close("pos", gauss_from_pos, gauss_from_freq)
fa_array_assert_all_close("freq", gauss_from_pos, gauss_from_freq)

plt_array(gauss_from_pos, data_name="Gauss (pos. shifted at init)")
plt_array(gauss_from_freq, data_name="Gauss (pos. shifted via FFT)")