No BSD License  

Highlights from
FourierTransform.m

image thumbnail
from FourierTransform.m by Carlos Adrian Vargas Aguilera
Complex Fourier Transform of a real time series. From zero to Nyquist frequency.

fouriertransform(x,varargin)
function [rc,ic,Ft] = fouriertransform(x,varargin)  
%FOURIERTRANSFORM   Performs the Fourier Complex Transform of real series.  
%   [RC,IC,Ft] = FOURIERTRANSFORM(X,dT) Performs the Fourier Complex   
%   Transform:  
%                CX(Ft) = RC(Ft) + i*IC(Ft) = COMPLEX(RC,IC) 
%   via Fast Fourier Transform from zero to Nyquist frequencies of the real 
%   time series X taken at sampling interval dT.
%
%   [RC,IC,Ft] = FOURIERTRANSFORM(X,dT,'exp') Performs the Fourier Complex   
%   Transform via complex exponentials (not so fast as FFT).
%
%   [RC,IC,Ft] = FOURIERTRANSFORM(X,dT,'trig') Performs the Fourier Complex   
%   Transform via cosine-sine series (not so fast as FFT).
%
%   Note: because the transform of real series is conjugate even (the real 
%   part even and the imaginary part odd) the output is only for the 
%   positive Fourier frequencies:  
%                        Ft = (0:1/N:1/2)/dT  
%   i.e., from zero to the Nyquist frequency. So, it has floor(N/2)+1 
%   elements, where N = length(X).   
%
%   Note: the whole transform from negative to positive frequencies is  
%        N2 = length(RC);   %   Other ways:    N2 = floor(N/2)+1;  
%        N  = length(X);    %                  N = 2*N2-1-(IC(end)==0);  
%        RC(N2+1:N) =  RC(N-N2+1:-1:2); RC = fftshift(RC);   
%        IC(N2+1:N) = -IC(N-N2+1:-1:2); IC = fftshift(IC);  
%        Ft(N2+1:N) = -Ft(N-N2+1:-1:2); Ft = fftshift(Ft);
%     
%   Note: if the sampling interval is 2 minutes, for example, and the X   
%   units, [X], are meters, then:  
%   a) PERCIVAL & WALDEN (normal usage)  
%       if  dT=120          =>  [RC,IC]=m*sec,   [Ft]=cycle/sec    
%   b) BLOOMFIELD (normalized time interval)  
%       if  dT=1/N          =>  [RC,IC]=m,       [Ft]=1 (adimentional)  
%   c) MATLAB (no dT input) (normalized frequency interval)  
%       if  dT=1 or empty   =>  [RC,IC]=m*2min,  [Ft]=cycle/2min  
%     
%   Note: to get a) from b), multiply RC,IC and divide Ft by the total   
%   sample interval. In this example, Tt = N*120 sec.  
%  
%   Note: the components of the zero frequency are RC(1)=mean(x)*Tt and   
%   IC(1)=0. That's why it is recommended to use X with zero mean, to avoid   
%   a huge peak at this null frequency.    
%  
%   Note: the relation between the complex transform and the Fourier series  
%   (sines and cosines) are:  
%        Tt = N*dT;          % total interval  
%        RC =  (AN/2)*Tt;    % real components  
%        IC = -(BN/2)*Tt;    % imaginary components  
%        RC(1) = RC(1)*2;    % zero component (whole, not half)  
%        if IC(end) == 0     % Nyquist component (whole, not half)  
%         RC(end) = RC(end)*2;     
%        end  
%   The inverses are:  
%        Tt = N*dT;          % total interval  
%        AN =  2*RC/Tt;      % cosine components  
%        BN = -2*IC/Tt;      % sine components  
%        AN(1) = AN(1)/2;    % zero component (single, not double)  
%        if BN(end) == 0     % Nyquist component (single, not double)  
%         AN(end) = AN(end)/2;        
%        end  
%  
%   Note: This program was created for teaching purposes. That's the reason 
%   of the 'exp' and 'trig' methods.  
%  
%   Example:  
%      N = 100; dT = 120; t = (0:N-1)*dT; f1 = 0.0007; f2 = 0.0013;  
%      x = 20*sin(2*pi*f1*t) + 30*cos(2*pi*f2*t) + rand(size(t));  
%      x = x-mean(x);  
%      [rc,ic,Ff] = fouriertransform(x,dT);  
%      subplot(211), plot(t,x), xlabel('time, sec'), ylabel('x, m')  
%      title('Complex Fourier transform example')
%      subplot(212), plot(Ff,rc,Ff,ic,[f1 f2],[0 0],'ro')  
%      xlabel('frequency, cycle/sec'), ylabel('Cx, m sec')  
%      legend('Real part','Imaginary Part','Natural Frequencies',4)
%  
%   See also INVERSEFOURIERTRANSFORM, FFT, IFFT  
  
%   Written by  
%   Lic. on Physics Carlos Adrin Vargas Aguilera  
%   Physical Oceanography MS candidate  
%   UNIVERSIDAD DE GUADALAJARA   
%   Mexico, 2004  
%  
%   nubeobscura@hotmail.com  
  
% Time series information:  
[dT,N,Method] = check_arguments(x,varargin,nargin);  
  
% Complex Fourier transform:
switch lower(Method)
 case 'fft'
  [rc,ic] = fouriertransform_fft(x,dT,N);
 case 'exp'
  [rc,ic] = fouriertransform_exponential(x,dT,N);
 case 'trig'
  [rc,ic] = fouriertransform_trigonometric(x,dT,N); 
 otherwise
  error('Method unknown. Must be one of ''fft'', ''exp'' or ''trig''.')
end
  
% Fourier frequencies:  
Ft = (0:1/N:1/2)/dT;     Ft = reshape(Ft,size(rc));  

% Ensures null Nyquist imaginary component:  
if (ic(end)==0) && rem(N,2)  
 warning('Fourier:Nyquist', ...
  'The last imaginary component is zero but the series is odd.')  
else
 ic(end) = 0;
end  
  

function [rc,ic] = fouriertransform_fft(x,dT,N)  
% Complex Fourier transform via FFT.  
Cx = fft(x)*dT;   Cx = Cx(1:floor(N/2)+1);   
rc = real(Cx);    ic = imag(Cx);              
  
function [rc,ic] = fouriertransform_exponential(xn,dT,N)  
% Complex Fourier transform via complex series.  
n  = 0:N-1;       m  =  n(1:floor(N/2)+1);  
tn = n;           % tn*dT:  time    
fm = m/N;         % fm/dT:  Fourier frequency  
wm = 2*pi*fm;     % angular Fourier frequency  
Cx = zeros(floor(size(xn)/2)+1);  
for m = 1:length(wm)  
 Cx(m) = sum( xn(:) .* exp(-i*wm(m)*tn(:)) ) * dT;  
end  
rc = real(Cx);    ic = imag(Cx);  
  
function [rc,ic] = fouriertransform_trigonometric(xn,dT,N)  
% Complex Fourier transform via cosine-sine series.  
n  = 0:N-1;       m  =  n(1:floor(N/2)+1);  
tn = n;           % tn*dT:  time    
fm = m/N;         % fm/dT:  Fourier frequency  
wm = 2*pi*fm;     % angular Fourier frequency  
am = zeros(floor(size(xn)/2)+1); bm = am;    
am(1) = mean(xn);  
bm(1) = 0;  
for m = 2:length(wm)  
 am(m) = 2 * mean( xn(:) .* cos(wm(m)*tn(:)) );  
 bm(m) = 2 * mean( xn(:) .* sin(wm(m)*tn(:)) );  
end  
if ~rem(N,2)   % even series  
 am(end) = am(end)/2;  
 bm(end) = 0;  
end  
% Translation to complex transform:  
Tt = N*dT;   
rc =  (am/2)*Tt;  
ic = -(bm/2)*Tt;  
rc(1) = rc(1)*2;  
if ic(end) == 0   
 rc(end) = rc(end)*2;     
end  
  
function [dT,N,Method] = check_arguments(x,Ventries,Nentries)  
% Is vector?  
N = length(x);  
if N~=numel(x)  
 error('Entry must be a vector.')  
end  
% Sampling interval?  
dT = 1;           % Default (MATLAB way)
Method = 'fft';   % Default (MATLAB way)
if Nentries > 1
 if ~ischar(Ventries{1})
  dT = Ventries{1};
 else
  Method = Ventries{1};
 end
end
if Nentries > 2
 if ~ischar(Ventries{2})
  dT = Ventries{2};
 else
  Method = Ventries{2};
 end
end
  
  
% Carlos Adrin. nubeobscura@hotmail.com

Contact us at files@mathworks.com