Discrete Fourier Transform#

The discrete Fourier transform (DFT) is at the heart of Lentil’s diffraction modeling capability. In addition to FFT-based propagation routines, Lentil includes propagation routines using the matrix triple product formulation of the DFT described in [1]. The code below validates Lentil’s DFT implementation against Numpy’s FFT.

lentil.fourier.dft2() == numpy.fourier.fft2() for even sized input#

n = 10
f = np.random.uniform(low=-1, high=1, size=(n, n))
F_dft = lentil.fourier.dft2(f, 1/n, unitary=False)
F_fft = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(f)))


fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8,4))
abs_dft = ax[0,0].imshow(np.abs(F_dft))
ax[0,0].set_ylabel('Amplitude')
ax[0,0].set_title('lentil.fourier.dft2()')
plt.colorbar(abs_dft, ax=ax[0,0])

abs_fft = ax[0,1].imshow(np.abs(F_fft))
ax[0,1].set_title('numpy.fourier.fft2()')
plt.colorbar(abs_fft, ax=ax[0,1])

abs_diff = ax[0,2].imshow(np.abs(F_dft) - np.abs(F_fft))
ax[0,2].set_title('Difference')
plt.colorbar(abs_diff, ax=ax[0,2])

angle_dft = ax[1,0].imshow(np.angle(F_dft))
ax[1,0].set_ylabel('Phase')
plt.colorbar(angle_dft, ax=ax[1,0])

angle_fft = ax[1,1].imshow(np.angle(F_fft))
plt.colorbar(angle_fft, ax=ax[1,1])

angle_diff = ax[1,2].imshow(np.angle(F_dft) - np.angle(F_fft))
plt.colorbar(angle_diff, ax=ax[1,2])

assert np.allclose(F_dft, F_fft)
../../_images/dft-1.png

lentil.fourier.dft2() == numpy.fourier.fft2() for odd sized input#

n = 11
f = np.random.uniform(low=-1, high=1, size=(n, n))
F_dft = lentil.fourier.dft2(f, 1/n, unitary=False)
F_fft = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(f)))


fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8,4))
abs_dft = ax[0,0].imshow(np.abs(F_dft))
ax[0,0].set_ylabel('Amplitude')
ax[0,0].set_title('lentil.fourier.dft2()')
plt.colorbar(abs_dft, ax=ax[0,0])

abs_fft = ax[0,1].imshow(np.abs(F_fft))
ax[0,1].set_title('numpy.fourier.fft2()')
plt.colorbar(abs_fft, ax=ax[0,1])

abs_diff = ax[0,2].imshow(np.abs(F_dft) - np.abs(F_fft))
ax[0,2].set_title('Difference')
plt.colorbar(abs_diff, ax=ax[0,2])

angle_dft = ax[1,0].imshow(np.angle(F_dft))
ax[1,0].set_ylabel('Phase')
plt.colorbar(angle_dft, ax=ax[1,0])

angle_fft = ax[1,1].imshow(np.angle(F_fft))
plt.colorbar(angle_fft, ax=ax[1,1])

angle_diff = ax[1,2].imshow(np.angle(F_dft) - np.angle(F_fft))
plt.colorbar(angle_diff, ax=ax[1,2])

assert np.allclose(F_dft, F_fft)
../../_images/dft-2.png