No BSD License  

Highlights from
FourierTransform2.m

image thumbnail
from FourierTransform2.m by Carlos Adrian Vargas Aguilera
Fourier complex transform of a 2D real field.

fouriertransform2(z,varargin)
function [rc,ic,Fx,Fy] = fouriertransform2(z,varargin)
%FOURIERTRANSFORM2   Performs the complex Fourier transform of a matrix.
%   [RC,IC,Fx,Fy] = FOURIERTRANSFORM2(Z,dX,dY) Gives the components of the 
%   complex Fourier transform 
%             Cz(Fx,Fy) = RC(Fx,Fy) + i*IC(Fx,Fy) = complex(RC,IC)
%   of a 2D field Z(X,Y) taken at dX,dY sampling interval, via 
%   FFT2. The spatial 2D frequencies Fx,Fy have the origin at the center. 
%   Fy (and Y) increase upwards contrary to the row index.
%
%   [RC,IC,Fx,Fy] = FOURIERTRANSFORM2(Z,dX,dY,'fft') does the same thing
%   but via fft. Only for academic purpose.
%
%   [RC,IC,Fx,Fy] = FOURIERTRANSFORM2(Z,dX,dY,'exp') does the same thing
%   but via complex exponentials. Only for academic purpose. Not so fast.
%
%   Inputs:                                  units:    Size  
%   Z   - 2D real field, for example units   [u]       Ny times Nx
%   dX  - Sampling spatial interval at x     [v]       Scalar
%   dY  - Sampling spatial interval at y     [w]       Scalar
%
%   Outputs:
%   RC  - Real components                    [u*v*w]   Ny times Nx
%   IC  - Imaginary components               [u*v*w]   Ny times Nx
%   Fx  - Centered x-frequency grid          [cycle/v] Ny times Nx
%   Fy  - Centered y-frequency grid          [cycle/w] Ny times Nx
%
%   Note: the origin of (X,Y) is at the (Ny,1) element (left-bottom 
%   corner), and of (Fx,Fy) at the (Ny-floor(Ny/2),floor(Nx/2)+1) element 
%   (center).
%
%   Note: the components at null frequencies are:
%      RC(Ny-floor(Ny/2),floor(Nx/2)+1) = mean(Z(:))*(Tx*Ty);  
%      IC(Ny-floor(Ny/2),floor(Nx/2)+1) = 0;
%   where Tx=Nx*dX and Ty=Ny*dY are the total sampling interval at x and y.
%
%   Note: the Fourier spatial frequencies (cycle/v, cycle/w) are 
%      nx = -floor(Nx/2):(Nx-1)/2;  % centralized x index
%      ny = -floor(Ny/2):(Ny-1)/2;  % centralized y index
%      ny = fliplr(ny);             % fy increase upwards
%      Fx = nx/(Nx*dX); Fy = ny/(Ny*dY);
%      [Fx,Fy] = meshgrid(Fx,Fy);
%
%   Note: if  dX = 1/Nx        =>  normalized space at x (Bloomfield)
%         if  dY = 1/Ny        =>  normalized space at y (Bloomfield)
%         if  dX = 1 or empty  =>  normalized frequency at x (MATLAB)
%         if  dY = 1 or empty  =>  normalized frequency at y (MATLAB)
%
%   Example:
%      Nx = 100; Ny = 200; dX = 120; dY = dX; 
%      fx1 = 0.0005; fx2 = -0.0010;
%      fy1 = 0.0012; fy2 =  0.0017;
%      x = (0:Nx-1)*dX; y  = fliplr(0:Ny-1)*dY; [x,y] = meshgrid(x,y); 
%      z = 20*sin(2*pi*(fx1*x + fy1*y)) + 30*cos(2*pi*(fx2*x + fy2*y));
%      z = z + rand(size(x));
%      z = z-mean(z(:));
%      [rc,ic,Fx,Fy] = fouriertransform2(z,dX,dY);  
%      subplot(311), surf(x,y,z), view(2), shading interp 
%      xlabel('x, m'), ylabel('y, m'), axis([0 (Nx-1)*dX 0 (Ny-1)*dY])
%      title('Complex Fourier transform 2D example')
%      subplot(312), surf(Fx,Fy,rc), view(2), shading interp
%      hold on, axis([Fx(1,1) Fx(1,end) Fy(end,1) Fy(1,1)])
%      plot3(fx1*[1 -1],fy1*[1 -1],max(rc(:))*[1 1],'ro',...
%            fx2*[1 -1],fy2*[1 -1],max(rc(:))*[1 1],'bo',...
%            [Fx(1,1) Fx(1,end)],[0 0],max(rc(:))*[1 1],'-k',...
%            [0 0],[Fy(end,1) Fy(1,1)],max(rc(:))*[1 1],'-k')
%      hold off
%      xlabel('frecuency, cycle/m'), ylabel('Frequency, cycle/m')  
%      title('Real part')
%      subplot(313), surf(Fx,Fy,ic), view(2), shading interp
%      hold on, axis([Fx(1,1) Fx(1,end) Fy(end,1) Fy(1,1)]) 
%      plot3(fx1*[1 -1],fy1*[1 -1],max(ic(:))*[1 1],'ro',...
%            fx2*[1 -1],fy2*[1 -1],max(ic(:))*[1 1],'bo',...
%            [Fx(1,1) Fx(1,end)],[0 0],max(ic(:))*[1 1],'-k',...
%            [0 0],[Fy(end,1) Fy(1,1)],max(ic(:))*[1 1],'-k')
%      hold off
%      xlabel('frecuency, cycle/m'), ylabel('Frequency, cycle/m')  
%      title('Imaginary part')
%
%   See also INVERSEFOURIERTRANSFORM2, FOURIERTRANSFORM, FFT2

%   Written by  
%   Lic. on Physics Carlos Adrin Vargas Aguilera  
%   Physical Oceanography MS candidate  
%   UNIVERSIDAD DE GUADALAJARA   
%   Mexico, 2004  
%  
%   nubeobscura@hotmail.com  

% Time series information:  
[dX,dY,Nx,Ny,Method] = check_arguments(z,varargin,nargin);  
  
% Complex Fourier transform:
switch lower(Method)
 case 'fft2'
  [rc,ic] = fouriertransform_fft2(z,dX*dY);
 case 'fft'
  [rc,ic] = fouriertransform_fft(z,dX,dY); 
 case 'exp'
  [rc,ic] = fouriertransform_exponential(z,dX*dY,Nx,Ny);
 otherwise
  error('Method unknown. Must be one of ''fft2'', ''fft'' or ''exp''.')
end

% Fourier frequency fields:
mx  = -floor(Nx/2):(Nx-1)/2;  % centered index
my  = -floor(Ny/2):(Ny-1)/2;  % centered index
my  = fliplr(my);             % increase upwards
Fx = mx/(Nx*dX);              % Fourier frequency at x, centered
Fy = my/(Ny*dY);              % Fourier frequency at y, centered
[Fx,Fy] = meshgrid(Fx,Fy);


function  [rc,ic] = fouriertransform_fft2(z,dS)  
% 2D complex Fourier Transform via FFT2.
Cz = fft2(flipud(z))*dS;  Cz = fftshift(Cz);  Cz = flipud(Cz);          
rc = real(Cz);  ic = imag(Cz);          

function  [rc,ic] = fouriertransform_fft(z,dX,dY)  
% 2D complex Fourier Transform via FFT.
Cy = fft(flipud(z),[],1)*dY;   
Cz = fft(Cy.',[],1).'*dX;
Cz = fftshift(Cz); Cz = flipud(Cz);
rc = real(Cz);   ic = imag(Cz);           

function  [rc,ic] = fouriertransform_exponential(z,dS,Nx,Ny)  
% 2D complex Fourier Transform via complex exponentials.
nx  = 0:Nx-1;       mx  = -floor(Nx/2):(Nx-1)/2;
ny  = 0:Ny-1;       my  = -floor(Ny/2):(Ny-1)/2;
ny  = fliplr(ny);   my  = fliplr(my);
xn  = nx;           yn  = ny;
[xn,yn] = meshgrid(xn,yn); % (xn*dX,yn*dY): space origin left-lower corner
fxm = mx/Nx;               % fxm/dX: Fourier frequency at x centered
fym = my/Ny;               % fym/dY: Fourier frequency at y centered
kxm = 2*pi*fxm;            % Fourier wavenumber x-component  
kym = 2*pi*fym;            % Fourier wavenumber y-component
Cz = zeros(Ny,Nx);
for my = 1:length(kym)
 for mx = 1:length(kxm)
  Cz(my,mx) = sum( sum( z .* exp(-i*(kxm(mx)*xn + kym(my)*yn)) )) * dS; 
 end
end
rc = real(Cz);   ic = imag(Cz);

function [dX,dY,Nx,Ny,Method] = check_arguments(z,Ventries,Nentries)  
% Is matrix?  
[Ny,Nx] = size(z);  
% Sampling interval?  
dX = [];
dY = 1;           % Default (MATLAB way)
Method = 'fft2';  % Default (MATLAB way)
if Nentries > 1
 if ~ischar(Ventries{1})
  dX = Ventries{1}; dY = dX;
 else
  Method = Ventries{1};
 end
end
if Nentries > 2
 if ~ischar(Ventries{2})
  if isempty(dX)
   dX = Ventries{2}; dY = dX;
  else
   dY = Ventries{2};
  end
 else
  Method = Ventries{2};
 end
end
if Nentries > 3
 if ~ischar(Ventries{3})
  dY = Ventries{3};
 else
  Method = Ventries{3};
 end
end
if isempty(dX)
 dX = dY;
end


% Carlos Adrin. nubeobscura@hotmail.com

Contact us at files@mathworks.com