annotate main/signal/pwelch.m @ 0:6b33357c7561 octave-forge

Initial revision
author pkienzle
date Wed, 10 Oct 2001 19:54:49 +0000
parents
children 13d7efaa47b8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
1 ## Copyright (C) 1999-2001 Paul Kienzle
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
2 ##
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
3 ## This program is free software; you can redistribute it and/or modify
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
4 ## it under the terms of the GNU General Public License as published by
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
5 ## the Free Software Foundation; either version 2 of the License, or
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
6 ## (at your option) any later version.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
7 ##
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
8 ## This program is distributed in the hope that it will be useful,
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
9 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
10 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
11 ## GNU General Public License for more details.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
12 ##
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
13 ## You should have received a copy of the GNU General Public License
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
14 ## along with this program; if not, write to the Free Software
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
15 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
16
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
17 ## usage: [Pxx, w] = pwelch(x,n,Fs,window,overlap,ci,range,units,trend)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
18 ## [Pxx, Pci, w] = pwelch(x,n,Fs,window,overlap,ci,range,units,trend)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
19 ##
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
20 ## Estimate power spectrum of a stationary signal. This chops the signal
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
21 ## into overlapping slices, windows each slice and applies a Fourier
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
22 ## transform to determine the frequency components at that slice. The
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
23 ## magnitudes of these slices are then averaged to produce the estimate Pxx.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
24 ## The confidence interval around the estimate is returned in Pci.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
25 ##
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
26 ## x: vector of samples
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
27 ## n: size of fourier transform window, or [] for default=256
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
28 ## Fs: sample rate, or [] for default=2 Hz
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
29 ## window: shape of the fourier transform window, or [] for default=hanning(n)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
30 ## Note: window length can be specified instead, in which case
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
31 ## window=hanning(length)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
32 ## overlap: overlap with previous window, or [] for default=length(window)/2
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
33 ## ci: confidence interval, or [] for default=0.95
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
34 ## ci must be between 0 and 1; if ci is not passed, or if it is
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
35 ## passed as 0, then no confidence intervals will be computed.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
36 ## range: 'whole', or [] for default='half'
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
37 ## show all frequencies, or just half of the frequencies
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
38 ## units: 'squared', or [] for default='db'
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
39 ## show results as magnitude squared or as log magnitude squared
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
40 ## trend: 'mean', 'linear', or [] for default='none'
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
41 ## remove trends from the data slices before computing spectral estimates
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
42 ##
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
43 ## Example
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
44 ## [b,a] = cheby1(4,3,[0.2, 0.4]); ## define noise colour
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
45 ## pwelch(filter(b,a,randn(2^12,1))); ## estimate noise colour
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
46
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
47 ## 2001-04-02 Paul Kienzle
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
48 ## * return nfft/2+1 elements rather than nfft/2 for even nfft.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
49 ## * use more accurate (and faster) computation of confidence intervals
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
50
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
51 ## TODO: Should be extended to accept a vector of frequencies at which to
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
52 ## TODO: evaluate the fourier transform (via filterbank or chirp
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
53 ## TODO: z-transform).
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
54 ## TODO: What should happen with the final window when it isn't full?
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
55 ## TODO: currently I dump it, but I should probably zero pad and add
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
56 ## TODO: it in.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
57 ## TODO: Consider returning the whole gamit of Pxx, Pyy, Pxy, Cxy, Txy
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
58 ## TODO: as well as confidence intervals for each; if users tend
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
59 ## TODO: only to use one of these don't bother, but if they ever need
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
60 ## TODO: more than one, then it's free. Alternatively, break out the
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
61 ## TODO: compute engine into a function that the user can call directly.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
62 ## TODO: Check if Cxy, Txy are computed frame-by-frame or on the average
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
63 ## TODO: of the frames. SpcTools and I do it on the average,
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
64 ## TODO: wdkirby@ix.netcom.com (1998-04-29 octave-sources) computes
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
65 ## TODO: them frame-by-frame.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
66 function [...] = pwelch(x, ...)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
67 ## sort out parameters
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
68 if nargin < 1,
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
69 usage("[Pxx, w] = pwelch(x,nfft,Fs,window,overlap,pc,range,units,trend)");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
70 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
71 va_start();
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
72
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
73 ## Determine if we are called as pwelch, csd, cohere or tfe
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
74 if isstr(x)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
75 calledby = x;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
76 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
77 calledby = "pwelch";
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
78 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
79 if !isstr(x)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
80 ftype = 1;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
81 elseif strcmp(x, 'csd')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
82 ftype = 2;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
83 elseif strcmp(x, 'cohere')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
84 ftype = 3;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
85 elseif strcmp(x, 'tfe')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
86 ftype = 4;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
87 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
88
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
89 ## Sort out x and y vectors
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
90 if ftype!=1
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
91 x=va_arg(); y=va_arg();
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
92 first = 4;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
93 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
94 y=[];
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
95 first = 2;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
96 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
97 if (columns(x) != 1 && rows(x) != 1) || ...
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
98 (!isempty(y) && columns(y) != 1 && rows(y) != 1)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
99 error ([calledby, " data must be a vector"]);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
100 end
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
101 if columns(x) != 1, x = x'; end
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
102 if columns(y) != 1, y = y'; end
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
103 if !isempty(y) && rows(x)!=rows(y)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
104 error ([calledby, " x and y vectors must be the same length"]);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
105 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
106
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
107 ## interpret remaining arguments
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
108 trend=nfft=Fs=window=overlap=whole=use_dB=[];
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
109 ci=-1; ## need to do stupid things with ci
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
110 pos=0; ## no positional parameters yet interpreted.
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
111 for i=first:nargin
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
112 arg = va_arg();
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
113 if isstr(arg),
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
114 arg=tolower(arg);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
115 if strcmp(arg, 'squared')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
116 use_dB = 0;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
117 elseif strcmp(arg, 'db')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
118 use_dB = 1;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
119 elseif strcmp(arg, 'whole')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
120 whole = 1;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
121 elseif strcmp(arg, 'half')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
122 whole = 0;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
123 elseif strcmp(arg, 'none')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
124 trend = -1;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
125 elseif strcmp(arg, 'mean')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
126 trend = 0;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
127 elseif strcmp(arg, 'linear')
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
128 trend = 1;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
129 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
130 error([calledby, " doesn't understand '", arg, "'"]);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
131 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
132 elseif pos == 0
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
133 nfft = arg;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
134 pos++;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
135 elseif pos == 1
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
136 Fs = arg;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
137 pos++;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
138 elseif pos == 2
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
139 window = arg;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
140 pos++;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
141 elseif pos == 3
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
142 overlap = arg;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
143 pos++;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
144 elseif pos == 4
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
145 ci = arg;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
146 pos++;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
147 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
148 usage(usagestr);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
149 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
150 endfor
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
151
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
152 ## Fill in defaults for arguments that aren't specified
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
153 if isempty(nfft), nfft = min(256, length(x)); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
154 if isempty(Fs), Fs = 2; endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
155 if isempty(window), window = hanning(nfft); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
156 if isempty(overlap), overlap = length(window)/2; endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
157 if isempty(whole), whole = !isreal(x)||(!isempty(y)&&!isreal(y)); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
158 if isempty(trend), trend=-1; endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
159 if isempty(use_dB),
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
160 ## don't default to db for cohere, or for returned values
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
161 use_dB = (ftype!=3 && nargout == 0);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
162 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
163 if isempty(ci), ci=0.95; endif # if ci was not passed in, it would be 0
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
164
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
165 ## sort out default confidence intervals
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
166 if (ci < 0) # ci was not passed in
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
167 if nargout > 2
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
168 ci = 0.95;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
169 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
170 ci = 0.0;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
171 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
172 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
173 if (ftype > 2 && ci > 0)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
174 error([ calledby, " can't compute confidence intervals" ]);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
175 elseif (ci < 0 || ci > 1)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
176 error([ calledby, " confidence interval must be between 0 and 1" ]);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
177 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
178
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
179 ## if only the window length is given, generate hanning window
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
180 if length(window) == 1, window = hanning(window); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
181 if rows(window)==1, window = window.'; endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
182
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
183 ## Normalize the window
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
184 window = window / norm(window);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
185
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
186 ## compute window offsets
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
187 win_size = length(window);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
188 if (win_size > nfft)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
189 nfft = win_size;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
190 warning (sprintf("%s fft size adjusted to %d", calledby, n));
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
191 end
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
192 step = win_size - overlap;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
193
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
194 ## Determine which correlations to compute
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
195 Pxx = Pyy = Pxy = [];
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
196 if ftype!=2, Pxx = zeros(nfft,1); endif # Not needed for csd
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
197 if ftype==3, Pyy = zeros(nfft,1); endif # Only needed for cohere
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
198 if ftype!=1, Pxy = zeros(nfft,1); endif # Not needed for psd
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
199
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
200 ## Average the slices
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
201 offset = 1:step:length(x)-win_size+1;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
202 N = length(offset);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
203 for i=1:N
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
204 a = x(offset(i):offset(i)+win_size-1);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
205 if trend>=0, a=detrend(a,trend); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
206 a = fft(postpad(a.*window, nfft));
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
207 if !isempty(Pxx), Pxx = Pxx + a.*conj(a); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
208 if !isempty(Pxy)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
209 b = y(offset(i):offset(i)+win_size-1);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
210 if trend>=0, b=detrend(b,trend); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
211 b = fft(postpad(b.*window, nfft));
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
212 Pxy = Pxy + a .*conj(b);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
213 if !isempty(Pyy), Pyy = Pyy + b.*conj(b); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
214 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
215 endfor
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
216 if (ftype <= 2)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
217 ## the factors of N cancel when computing cohere and tfe
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
218 if !isempty(Pxx), Pxx = Pxx / N; endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
219 if !isempty(Pxy), Pxy = Pxy / N; endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
220 if !isempty(Pyy), Pyy = Pyy / N; endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
221 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
222
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
223 ## Compute confidence intervals
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
224 if ci > 0, Pci = zeros(nfft,1); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
225 if (ci > 0 && N > 1)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
226 if ftype>2
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
227 error([calledby, ": internal error -- shouldn't compute Pci"]);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
228 end
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
229
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
230 ## c.i. = mean +/- dev
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
231 ## dev = z_ci*std/sqrt(n)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
232 ## std = sqrt(sumsq(P-mean(P))/(N-1))
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
233 ## z_ci = normal_inv( 1-(1-ci)/2 ) = normal_inv( (1+ci)/2 );
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
234 ## normal_inv(x) = sqrt(2) * erfinv(2*x-1)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
235 ## => z_ci = sqrt(2)*erfinv(2*(1+ci)/2-1) = sqrt(2)*erfinv(ci)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
236 for i=1:N
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
237 a=x(offset(i):offset(i)+win_size-1);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
238 if trend>=0, a=detrend(a,trend); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
239 a=fft(postpad(a.*window, nfft));
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
240 if ftype == 1 # psd
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
241 P = a.*conj(a) - Pxx;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
242 Pci = Pci + P.*conj(P);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
243 else # csd
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
244 b=y(offset(i):offset(i)+win_size-1);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
245 if trend>=0, b=detrend(b,trend); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
246 b=fft(postpad(b.*window, nfft));
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
247 P = a.*conj(b) - Pxy;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
248 Pci = Pci + P.*conj(P);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
249 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
250 endfor
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
251
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
252 Pci = ( erfinv(ci) * sqrt( 2/N/(N-1) ) ) * sqrt ( Pci );
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
253 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
254
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
255 switch (ftype)
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
256 case 1, # psd
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
257 P = Pxx / Fs;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
258 if ci > 0, Pci = Pci / Fs; endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
259 case 2, # csd
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
260 P = Pxy;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
261 case 3, # cohere
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
262 P = Pxy.*conj(Pxy)./Pxx./Pyy;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
263 case 4, # tfe
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
264 P = Pxy./Pxx;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
265 endswitch
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
266
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
267 ## compute confidence intervals
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
268 if ci > 0, Pci = [ P - Pci, P + Pci ]; endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
269
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
270 if use_dB
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
271 P = 10.0*log10(P);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
272 if ci > 0, Pci = 10.0*log10(Pci); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
273 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
274
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
275 ## extract the positive frequency components
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
276 if whole
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
277 ret_n = nfft;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
278 elseif rem(nfft,2)==1
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
279 ret_n = (nfft+1)/2;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
280 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
281 ret_n = nfft/2 + 1;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
282 end
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
283 P = P(1:ret_n, :);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
284 if ci > 0, Pci = Pci(1:ret_n, :); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
285 f = [0:ret_n-1]*Fs/nfft;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
286
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
287 ## Plot if there is no
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
288 if nargout==0,
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
289 unwind_protect
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
290 if Fs==2
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
291 xlabel("Frequency (rad/pi)");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
292 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
293 xlabel("Frequency (Hz)");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
294 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
295 if ftype==1
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
296 title ("Welch's Spectral Estimate Pxx/Fs");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
297 ytext="Power Spectral Density";
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
298 elseif ftype==2
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
299 title ("Cross Spectral Estimate Pxy");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
300 ytext="Cross Spectral Density";
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
301 elseif ftype==3
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
302 title ("Coherence Function Estimate |Pxy|^2/(PxxPyy)");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
303 ytext="Coherence ";
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
304 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
305 title ("Transfer Function Estimate Pxy/Pxx");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
306 ytext="Transfer";
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
307 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
308 if use_dB,
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
309 ylabel(strcat(ytext, " (dB)"));
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
310 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
311 ylabel(ytext);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
312 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
313 grid("on");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
314 if ci>0
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
315 plot(f, [P, Pci], ";;");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
316 else
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
317 plot(f, P, ";;");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
318 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
319 unwind_protect_cleanup
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
320 grid("off");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
321 title("");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
322 xlabel("");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
323 ylabel("");
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
324 end_unwind_protect
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
325 endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
326
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
327 if nargout>=1, vr_val(P); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
328 if nargout>=2 && ci>0, vr_val(Pci); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
329 if nargout>=2 && ci==0, vr_val(f); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
330 if nargout>=3 && ci>0, vr_val(f); endif
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
331
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
332 endfunction
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
333
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
334 %!demo
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
335 %! Fs=8000;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
336 %! [b,a] = cheby1(4,3,2*[500, 1000]/Fs); ## define spectral envelope
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
337 %! s=0.05*randn(2^11,1); ## define noise
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
338 %! idx=fix(1:Fs/70:length(s))';
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
339 %! s(idx)=s(idx)+ones(size(idx)); ## add 70 Hz excitation
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
340 %! x=filter(b,a,s); ## generate signal
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
341 %!
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
342 %! figure(1); subplot(221);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
343 %! text(0,0.9,'basic estimate','Units','Normalized');
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
344 %! pwelch(x',[],Fs); text; # slip in a test for row vs. column vector
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
345 %! subplot(222);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
346 %! text(0,0.9,'nfft=1024 instead of 256','Units','Normalized');
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
347 %! pwelch(x,1024); text;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
348 %! subplot(223);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
349 %! text(0,0.9,'boxcar instead of hanning','Units','Normalized');
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
350 %! pwelch(x,[],[],boxcar(256)); text;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
351 %! subplot(224);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
352 %! text(0,0.9,'no overlap','Units','Normalized');
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
353 %! pwelch(x,[],[],[],0); text;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
354 %!
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
355 %! figure(2); subplot(121);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
356 %! text(0,0.9,'magnitude units, whole range','Units','Normalized');
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
357 %! pwelch(x,'whole','squared'); text;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
358 %! subplot(122);
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
359 %! text(0,0.9,'90% confidence intervals','Units','Normalized');
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
360 %! pwelch(x,[],[],[],[],0.9); text;
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
361 %! oneplot();
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
362 %! %----------------------------------------------------------
6b33357c7561 Initial revision
pkienzle
parents:
diff changeset
363 %! % plots should show a chebyshev bandpass filter shape