{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Bidimensional Fourier Transform\n", "The BidimensionalFourierTransform computes FFT of functions defined on bidimensional domain and return a ScalarBidimensionalFunction representing the spectrum and the frequency domain." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from arte.utils.discrete_fourier_transform import \\\n", " BidimensionalFourierTransform as bfft\n", "from arte.types.domainxy import DomainXY\n", "from arte.types.scalar_bidimensional_function import ScalarBidimensionalFunction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Direct transform of 2D functions\n", "In the simplest example we transform a constant function of amplitude=1 defined in the domain [-2,2), sampled on 4x4 grid. As the normalization perserve the total power we expect a spectrum centered in (0,0) with amplitude sqrt(16)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Values:\n", "[[0. 0. 0. 0.]\n", " [0. 0. 0. 0.]\n", " [0. 0. 4. 0.]\n", " [0. 0. 0. 0.]]\n", "Freq X:\n", "[[-0.5 -0.25 0. 0.25]\n", " [-0.5 -0.25 0. 0.25]\n", " [-0.5 -0.25 0. 0.25]\n", " [-0.5 -0.25 0. 0.25]]\n", "Freq Y:\n", "[[-0.5 -0.5 -0.5 -0.5 ]\n", " [-0.25 -0.25 -0.25 -0.25]\n", " [ 0. 0. 0. 0. ]\n", " [ 0.25 0.25 0.25 0.25]]\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "sz = 4\n", "spatial_step= 1.0\n", "ampl = 1.0\n", "xy = DomainXY.from_shape((sz, sz), spatial_step)\n", "constant_map= ampl*np.ones(xy.shape) \n", "spatial_funct = ScalarBidimensionalFunction(constant_map, domain=xy)\n", "spectr = bfft.direct(spatial_funct)\n", "plt.imshow(abs(spectr.values))\n", "print(\"Values:\\n%s\" % abs(spectr.values))\n", "print(\"Freq X:\\n%s\" % spectr.xmap)\n", "print(\"Freq Y:\\n%s\" % spectr.ymap)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Inverse Transform\n", "The inverse transform return the original spatial function, as expected." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Values:\n", "[[1.+0.j 1.+0.j 1.+0.j 1.+0.j]\n", " [1.+0.j 1.+0.j 1.+0.j 1.+0.j]\n", " [1.+0.j 1.+0.j 1.+0.j 1.+0.j]\n", " [1.+0.j 1.+0.j 1.+0.j 1.+0.j]]\n", "Freq X:\n", "[[-2. -1. 0. 1.]\n", " [-2. -1. 0. 1.]\n", " [-2. -1. 0. 1.]\n", " [-2. -1. 0. 1.]]\n", "Freq Y:\n", "[[-2. -2. -2. -2.]\n", " [-1. -1. -1. -1.]\n", " [ 0. 0. 0. 0.]\n", " [ 1. 1. 1. 1.]]\n" ] } ], "source": [ "inverse_spectr = bfft.inverse(spectr)\n", "print(\"Values:\\n%s\" % inverse_spectr.values)\n", "print(\"Freq X:\\n%s\" % inverse_spectr.xmap)\n", "print(\"Freq Y:\\n%s\" % inverse_spectr.ymap)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Normalization\n", "Spectra are normalized to preserve total energy " ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Power of spatial funct 2.59543\n", "Power of spectral funct 2.59543\n" ] } ], "source": [ "xy = DomainXY.from_xy_vectors(np.linspace(-2,2,4), np.linspace(-4,0,5))\n", "spatial_map = np.random.random(xy.xmap.shape)\n", "spatial_funct = ScalarBidimensionalFunction(spatial_map, domain=xy)\n", "spectral_funct = bfft.direct(spatial_funct)\n", "print(\"Power of spatial funct %g\" % np.linalg.norm(spatial_funct.values))\n", "print(\"Power of spectral funct %g\" % np.linalg.norm(spectral_funct.values))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Non centered domain\n", "The same example as before, on a spatial domain centered in (3,2) instead of the origin" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Spatial Domain X: [1.5 2.5 3.5 4.5]\n", "Spatial Domain Y: [0.5 1.5 2.5 3.5]\n", "Spectrum Map:\n", "[[0. 0. 0. 0.]\n", " [0. 0. 0. 0.]\n", " [0. 0. 4. 0.]\n", " [0. 0. 0. 0.]]\n", "Freq X: [-0.5 -0.25 0. 0.25]\n", "Freq Y: [-0.5 -0.25 0. 0.25]\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "sz = 4\n", "spatial_step= 1.0\n", "ampl = 1.0\n", "xy = DomainXY.from_shape((sz, sz), spatial_step)\n", "xy.shift(3, 2)\n", "constant_map= ampl*np.ones(xy.shape) \n", "spatial_funct = ScalarBidimensionalFunction(constant_map, domain=xy)\n", "spectr = bfft.direct(spatial_funct)\n", "plt.imshow(abs(spectr.values))\n", "print(\"Spatial Domain X: %s\" % xy.xcoord)\n", "print(\"Spatial Domain Y: %s\" % xy.ycoord)\n", "print(\"Spectrum Map:\\n%s\" % abs(spectr.values))\n", "print(\"Freq X: %s\" % spectr.xcoord)\n", "print(\"Freq Y: %s\" % spectr.ycoord)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Direct transform on rectangular, unevenly spaced domain\n", "In the example below the spectrum of a constant function defined on a rectangular domain with regular sampling is computed. With a spatial domain of (x,y)=(20,10) points sampled at dx=0.1 and dy=0.4, we expect the spectral range to have minimum frequencies $(f^{min}_x, f^{min}_y) = (5, 1.25)$ and spectral resolution $(df_x, df_y) = (0.5, 0.25)$" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "spatial domain X: [-0.95 -0.85 -0.75 -0.65 -0.55 -0.45 -0.35 -0.25 -0.15 -0.05 0.05 0.15\n", " 0.25 0.35 0.45 0.55 0.65 0.75 0.85 0.95]\n", "spatial domain Y: [-1.8 -1.4 -1. -0.6 -0.2 0.2 0.6 1. 1.4 1.8]\n", "spectral value in (0,0) should be 14.1421\n", "Check: v(0,0) = 14.1421\n", "Min/Max freq x should be 5. delta_freq_x should be 0.5\n", "Check: freq x min/max/delta -5/4.5/0.5\n", "Min/Max freq y should be 1.25. delta_freq_x should be 0.25\n", "Check: freq y min/max/delta -1.25/1/0.25\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "szx, szy = (20,10)\n", "stepx, stepy= (0.1, 0.4)\n", "ampl = 1.0\n", "xy = DomainXY.from_shape((szy, szx), (stepy, stepx))\n", "constant_map= ampl*np.ones(xy.shape) \n", "spatial_funct = ScalarBidimensionalFunction(constant_map, domain=xy)\n", "spectr = bfft.direct(spatial_funct)\n", "plt.imshow(abs(spectr.values))\n", "\n", "print(\"spatial domain X: %s\" % xy.xcoord)\n", "print(\"spatial domain Y: %s\" % xy.ycoord)\n", "\n", "print(\"spectral value in (0,0) should be %g\" % (np.sqrt(ampl*szx*szy)))\n", "print(\"Check: v(%g,%g) = %g\" % (\n", " spectr.xmap[szy//2, szx//2],spectr.ymap[szy//2,szx//2],spectr.values[szy//2,szx//2].real))\n", "freq_step_x, freq_step_y = spectr.domain.step\n", "print(\"Min/Max freq x should be %g. delta_freq_x should be %g\" % (\n", " 0.5/stepx, 1/(szx*stepx)))\n", "print(\"Check: freq x min/max/delta %g/%g/%g\" % (spectr.xcoord[0], spectr.xcoord[-1], freq_step_x))\n", "print(\"Min/Max freq y should be %g. delta_freq_x should be %g\" % (\n", " 0.5/stepy, 1/(szy*stepy)))\n", "print(\"Check: freq y min/max/delta %g/%g/%g\" % (spectr.ycoord[0], spectr.ycoord[-1], freq_step_y))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Units\n", "The discrete_fourier_transform module preserve units" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Spectrum xmap unit: 1 / m\n", "Spectrum ymap unit: 1 / kg\n", "Spectrum xcoord unit: 1 / m\n", "Spectrum ycoord unit: 1 / kg\n", "Spectrum value unit: V\n" ] } ], "source": [ "from astropy import units as u\n", "szx, szy = (20,10)\n", "stepx, stepy= (0.1 * u.m, 0.4*u.kg)\n", "ampl = 1.0 * u.V\n", "xy = DomainXY.from_shape((szy, szx), (stepy, stepx))\n", "map_in_V= ampl*np.ones(xy.shape) \n", "spatial_funct = ScalarBidimensionalFunction(map_in_V, domain=xy)\n", "spectr = bfft.direct(spatial_funct)\n", "print(\"Spectrum xmap unit: %s\" % spectr.xmap.unit)\n", "print(\"Spectrum ymap unit: %s\" % spectr.ymap.unit)\n", "print(\"Spectrum xcoord unit: %s\" % spectr.xcoord.unit)\n", "print(\"Spectrum ycoord unit: %s\" % spectr.ycoord.unit)\n", "print(\"Spectrum value unit: %s\" % spectr.values.unit)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Transform of numpy array\n", "The class BidimensionalFourierTransform is meant to be used with ScalarBidimensionalFunction, but it provides also the two methods direct_transform and inverse_transform that can be used with numpy arrays representing the function values. The return value is a complex array, the computation of the frequency domain is demanded to the user." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 0.+0.j, 0.+0.j, 0.+0.j],\n", " [ 0.+0.j, 33.+0.j, 0.+0.j],\n", " [ 0.+0.j, 0.+0.j, 0.+0.j]])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sz = 10\n", "constant_map = np.ones((sz, sz)) * 3.3\n", "res = bfft.direct_transform(constant_map)\n", "res[4:7,4:7]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00\n", " 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00\n", " 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00\n", " 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00\n", " 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]\n", " [4.38854184e-18 5.87009310e-16 2.63739711e-16 3.50612825e-16\n", " 2.80900961e-16 5.51212035e-16 5.82806108e-16 1.03947191e-15\n", " 3.16227766e+00 8.63625182e-16 3.15975012e-16 8.63625182e-16\n", " 3.16227766e+00 1.03947191e-15 5.82806108e-16 5.51212035e-16\n", " 7.02166694e-17 3.50612825e-16 2.63739711e-16 5.87009310e-16]] V\n", "[-5. -4.5 -4. -3.5 -3. -2.5 -2. -1.5 -1. -0.5 0. 0.5 1. 1.5\n", " 2. 2.5 3. 3.5 4. 4.5] 1 / s\n", "[-0.5 0. ] 1 / kg\n" ] }, { "data": { "text/plain": [ "[]" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from astropy import units as u\n", "szx, szy = (20,2)\n", "stepx, stepy= (0.1 * u.s, 1*u.kg)\n", "ampl = 1.0 * u.V\n", "period = 1 * u.s\n", "xy = DomainXY.from_shape((szy, szx), (stepy, stepx))\n", "map_in_V= ampl*np.sin( (2*np.pi*xy.xmap/period).to(u.rad, equivalencies=u.dimensionless_angles())) \n", "spatial_f = ScalarBidimensionalFunction(map_in_V, domain=xy)\n", "spectral_f = bfft.direct(spatial_f)\n", "print(np.abs(spectral_f.values))\n", "print(spectral_f.xcoord)\n", "print(spectral_f.ycoord)\n", "plt.figure()\n", "plt.plot(spatial_f.xmap[0,:], spatial_f.values[0,:], '.-')\n", "plt.figure()\n", "plt.plot(spectral_f.xmap[1,:], np.abs(spectral_f.values)[1,:], '.-')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.10" } }, "nbformat": 4, "nbformat_minor": 4 }