1 | function [w,e] = ezfft(varargin)
|
---|
2 | %EZFFT Easy to use Power Spectrum
|
---|
3 | % EZFFT(T,U) plots the power spectrum of the signal U(T) , where T is a
|
---|
4 | % 'time' and U is a real signal (T can be considered as a space
|
---|
5 | % coordinate as well). If T is a scalar, then it is interpreted as the
|
---|
6 | % 'sampling time' of the signal U. If T is a vector, then it is
|
---|
7 | % interpreted as the 'time' itself. In this latter case, T must be
|
---|
8 | % equally spaced (as obtained by LINSPACE for instance), and it must
|
---|
9 | % have the same length as U. If T is not specified, then a 'sampling
|
---|
10 | % time' of unity (1 second for instance) is taken. Windowing
|
---|
11 | % (appodization) can be applied to reduce border effects (see below).
|
---|
12 | %
|
---|
13 | % [W,E] = EZFFT(T,U) returns the power spectrum E(W), where E is the
|
---|
14 | % energy density and W the pulsation 'omega'. W is *NOT* the frequency:
|
---|
15 | % the frequency is W/(2*pi). If T is considered as a space coordinate,
|
---|
16 | % W is a wave number (usually noted K = 2*PI/LAMBDA, where LAMBDA is a
|
---|
17 | % wavelength).
|
---|
18 | %
|
---|
19 | % EZFFT(..., 'Property1', 'Property2', ...) specifies the properties:
|
---|
20 | % 'hann' applies a Hann appodization window to the data (reduces
|
---|
21 | % aliasing).
|
---|
22 | % 'disp' displays the spectrum (by default if no output argument)
|
---|
23 | % 'freq' the frequency f is displayed instead of the pulsation omega
|
---|
24 | % (this applies for the display only: the output argument
|
---|
25 | % remains the pulsation omega, not the frequency f).
|
---|
26 | % 'space' the time series is considered as a space series. This simply
|
---|
27 | % renames the label 'omega' by 'k' (wave number) in the plot,
|
---|
28 | % but has no influence on the computation itself.
|
---|
29 | % 'handle' returns a handle H instead of [W,E] - it works only if the
|
---|
30 | % properties 'disp' is also specified. The handle H is useful
|
---|
31 | % to change the line properties (color, thickness) of the
|
---|
32 | % plot (see the example below).
|
---|
33 | %
|
---|
34 | % The length of the vectors W and E is N/2, where N is the length of U
|
---|
35 | % (this is because U is assumed to be a real signal.) If N is odd, the
|
---|
36 | % last point of U and T are ignored. If U is not real, only its real part
|
---|
37 | % is considered.
|
---|
38 | %
|
---|
39 | % W(1) is always 0. E(1) is the energy density of the average of U
|
---|
40 | % (when plotted in log coordinates, the first point is W(2), E(2)).
|
---|
41 | % W(2) is the increment of pulsation, Delta W, given by 2*PI/Tmax
|
---|
42 | % W(end), the highest measurable pulsation, is PI/DT, where DT is the
|
---|
43 | % sampling time (Nyquist theorem).
|
---|
44 | %
|
---|
45 | % Parseval Theorem (Energy conservation):
|
---|
46 | % For every signal U, the 'energy' computed in the time domain and in the
|
---|
47 | % frequency domain are equal,
|
---|
48 | % MEAN(U.^2) == SUM(E)*W(2)
|
---|
49 | % where W(2) is the pulsation increment Delta W.
|
---|
50 | % Note that, depending on the situation considered, the physical 'energy'
|
---|
51 | % is usually defined as 0.5*MEAN(U.^2). Energy conservation only applies
|
---|
52 | % if no appodization of the signal (windowing) is used. Otherwise, some
|
---|
53 | % energy is lost in the appodization, so the spectral energy is lower
|
---|
54 | % than the actual one.
|
---|
55 | %
|
---|
56 | % As for FFT, the execution time depends on the length of the signal.
|
---|
57 | % It is fastest for powers of two.
|
---|
58 | %
|
---|
59 | % Example 1: simple display of a power spectrum
|
---|
60 | % t = linspace(0,400,2000);
|
---|
61 | % u = 0.2 + 0.7*sin(2*pi*t/47) + cos(2*pi*t/11);
|
---|
62 | % ezfft(t,u);
|
---|
63 | %
|
---|
64 | % Example 2: how to change the color of the plot
|
---|
65 | % h = ezfft(t,u,'disp','handle');
|
---|
66 | % set(h,'Color','red');
|
---|
67 | %
|
---|
68 | % Example 3: how to use the output of ezfft
|
---|
69 | % [w,e] = ezfft(t,u,'hann');
|
---|
70 | % loglog(w,e,'b*');
|
---|
71 | %
|
---|
72 | % See also FFT
|
---|
73 |
|
---|
74 |
|
---|
75 | % F. Moisy, moisy_at_fast.u-psud.fr
|
---|
76 | % Revision: 1.01, Date: 2008/11/20
|
---|
77 | % This function is part of the EzyFit Toolbox
|
---|
78 |
|
---|
79 |
|
---|
80 | % History:
|
---|
81 | % 2008/11/19: v1.00, first version.
|
---|
82 | % 2008/11/20: v1.01, includes property 'space'. Help text improved
|
---|
83 |
|
---|
84 |
|
---|
85 | error(nargchk(1,inf,nargin));
|
---|
86 |
|
---|
87 | if nargin==1
|
---|
88 | u=varargin{1};
|
---|
89 | dt=1;
|
---|
90 | else
|
---|
91 | dt=varargin{1};
|
---|
92 | u=varargin{2};
|
---|
93 | end
|
---|
94 |
|
---|
95 | if length(dt)>1
|
---|
96 | if length(u)~=length(dt)
|
---|
97 | error('Vectors T and U should be of equal length.');
|
---|
98 | end
|
---|
99 | dt = abs(dt(2)-dt(1));
|
---|
100 | end
|
---|
101 |
|
---|
102 | % works only with vectors of even length
|
---|
103 | if mod(length(u),2)~=0;
|
---|
104 | u=u(1:(end-1));
|
---|
105 | end
|
---|
106 |
|
---|
107 | u=real(u);
|
---|
108 |
|
---|
109 | % works with line vector (otherwise transpose it)
|
---|
110 | if size(u,2)==1
|
---|
111 | u=u';
|
---|
112 | end
|
---|
113 |
|
---|
114 | % signal appodization with a Hann window
|
---|
115 | if any(strcmpi(varargin,'hann'))
|
---|
116 | u=u.*hann(length(u))';
|
---|
117 | end
|
---|
118 |
|
---|
119 | n = length(u)/2; % length of the output fft (half the signal length)
|
---|
120 | w = linspace(0,pi,n)/dt; % output pulsation
|
---|
121 |
|
---|
122 | e = abs(fft(u)).^2; % power spectrum
|
---|
123 | e = 2*e(1:n) / (2*n)^2 / w(2); % normalisation
|
---|
124 | e(1)=e(1)/2; % mode w=0 was counted twice is the previous line
|
---|
125 |
|
---|
126 | % display
|
---|
127 | if nargout==0 || any(strncmpi(varargin,'disp',1))
|
---|
128 | if any(strncmpi(varargin,'freq',1)) && any(strncmpi(varargin,'space',1))
|
---|
129 | error('Properties ''freq'' and ''space'' cannot be specified simultaneously');
|
---|
130 | elseif any(strncmpi(varargin,'freq',1)) && ~any(strncmpi(varargin,'space',1))
|
---|
131 | hh=loglog(w/(2*pi),2*pi*e);
|
---|
132 | xlabel('f = \omega / 2\pi');
|
---|
133 | ylabel('E(f)');
|
---|
134 | elseif ~any(strncmpi(varargin,'freq',1)) && any(strncmpi(varargin,'space',1))
|
---|
135 | hh=loglog(w,e);
|
---|
136 | xlabel('k');
|
---|
137 | ylabel('E(k)');
|
---|
138 | else
|
---|
139 | hh=loglog(w,e);
|
---|
140 | xlabel('\omega');
|
---|
141 | ylabel('E(\omega)');
|
---|
142 | end
|
---|
143 | end
|
---|
144 |
|
---|
145 | % output
|
---|
146 | if nargout>0 && any(strncmpi(varargin,'handle',4)) && any(strncmpi(varargin,'disp',1))
|
---|
147 | w=hh;
|
---|
148 | clear e
|
---|
149 | return
|
---|
150 | end
|
---|
151 |
|
---|
152 | if nargout==0
|
---|
153 | clear w e
|
---|
154 | end
|
---|
155 |
|
---|
156 |
|
---|
157 | function y=hann(n)
|
---|
158 | %HANN Window Hann function
|
---|
159 | % Y = HANN(N) returns a N-point Hann function (usually N is a power of
|
---|
160 | % 2), ie a discretization of Y(X) = (1 - COS (2*PI*X))/2.
|
---|
161 | %
|
---|
162 | % The HANN function is used to window (apodize) finite samples of signal
|
---|
163 | % in order to avoid high frequency oscillations in Fourier transform.
|
---|
164 | %
|
---|
165 | % Example: plot(hann(128));
|
---|
166 | %
|
---|
167 | % F. Moisy
|
---|
168 | % Revision: 1.03, Date: 2006/03/03
|
---|
169 | %
|
---|
170 | % See also FFT.
|
---|
171 |
|
---|
172 | % History:
|
---|
173 | % 2004/09/17: v1.00, first version.
|
---|
174 | % 2005/23/02: v1.01, cosmetics
|
---|
175 | % 2005/09/03: v1.02, id.
|
---|
176 | % 2006/03/03: v1.03, bug fixed 0:n-1
|
---|
177 |
|
---|
178 | error(nargchk(1,1,nargin));
|
---|
179 | y=0.5*(1-cos(2*pi*(0:n-1)/(n-1)))';
|
---|
180 |
|
---|