comparison m-toolbox/classes/@matrix/mchNoisegen.m @ 0:f0afece42f48

Import.
author Daniele Nicolodi <nicolodi@science.unitn.it>
date Wed, 23 Nov 2011 19:22:13 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f0afece42f48
1 % MCHNOISEGEN Generates multichannel noise data series given a model
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %
4 % FUNCTION: mchNoisegen generates multichannel noise data series given a
5 % mutichannel noise generating filter.
6 %
7 % DESCRIPTION:
8 %
9 %
10 % CALL: out = mchNoisegen(mod, pl)
11 %
12 % INPUT:
13 % mod: is a matrix containing a multichannel noise generating
14 % filter aiming to generate colored noise from unitary variance
15 % independent white data series. Each element of the multichannel
16 % filter must be a parallel bank of filters as that produced by
17 % matrix/mchNoisegenFilter or ao/Noisegen2D. The filter matrix must
18 % be square.
19 %
20 % OUTPUT:
21 % out: is a matrix containg a multichannel colored noise time
22 % series which csd matrix is defined by mod'*mod.
23 %
24 % HISTORY: 19-10-2009 L Ferraioli
25 % Creation
26 %
27 % ------------------------------------------------------------------------
28 %
29 % <a href="matlab:utils.helper.displayMethodInfo('matrix', 'mchNoisegen')">Parameters Description</a>
30 %
31 % VERSION: $Id: mchNoisegen.m,v 1.6 2011/04/08 08:56:31 hewitson Exp $
32 %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 function varargout = mchNoisegen(varargin)
35
36 % Check if this is a call for parameters
37 if utils.helper.isinfocall(varargin{:})
38 varargout{1} = getInfo(varargin{3});
39 return
40 end
41
42 import utils.const.*
43 utils.helper.msg(msg.OMNAME, 'running %s/%s', mfilename('class'), mfilename);
44
45 % Collect input variable names
46 in_names = cell(size(varargin));
47 for ii = 1:nargin,in_names{ii} = inputname(ii);end
48
49 % Collect all ltpdauoh objects
50 [mtxs, mtxs_invars] = utils.helper.collect_objects(varargin(:), 'matrix', in_names);
51 [pl, invars] = utils.helper.collect_objects(varargin(:), 'plist');
52
53 inhists = mtxs.hist;
54
55 % combine plists
56 pl = parse(pl, getDefaultPlist());
57 pl.getSetRandState();
58
59 outm = copy(mtxs,nargout);
60
61 % Get parameters and set params for fit
62 Nsecs = find(pl, 'nsecs');
63 fs = find(pl, 'fs');
64 yunit = find(pl, 'yunits');
65
66 % total number of data in the series
67 Ntot = round(Nsecs*fs);
68
69 % chose case for input filter
70 if isa(outm,'matrix') && isa(outm.objs(1),'filterbank')
71 % discrete system
72 sys = 'z';
73 mfil = outm.objs;
74 [nn,mm] = size(mfil);
75 if nn~=mm
76 error('!!! Filter matrix must be square')
77 end
78 % check if filter is a matrix built with noisegen2D
79 fromnsg2D = false;
80 if nn == 2
81 nn11 = numel(mfil(1,1).filters);
82 nn21 = numel(mfil(2,1).filters);
83 if nn11 == nn21
84 % get poles out of the filters
85 pl11 = zeros(nn11,1);
86 pl21 = zeros(nn21,1);
87 for ii=1:nn11
88 pl11(ii) = -1*mfil(1,1).filters(ii).b(2);
89 pl21(ii) = -1*mfil(2,1).filters(ii).b(2);
90 end
91 % check if poles are equal that means they are produced with
92 % noisegen2D
93 if all((pl11-pl21)<eps)
94 fromnsg2D = true;
95 end
96 end
97 end
98 elseif isa(outm,'matrix') && isa(outm.objs(1),'parfrac')
99 % continuous system
100 sys = 's';
101 mfil = outm.objs;
102 [nn,mm] = size(mfil);
103 if nn~=mm
104 error('!!! Filter matrix must be square')
105 end
106 else
107 error('!!! Input filter must be a ''matrix'' of ''filterbank'' or ''parfrac'' objects.')
108 end
109
110 % init output
111 out(nn,1) = ao;
112
113 % switch between input filter type
114 switch sys
115 case 'z' % discrete input filters
116
117 % init output data
118 o = zeros(nn,Ntot);
119
120 for zz=1:nn % moving along system dimension
121
122 % extract residues and poles from input objects
123 % run over matrix dimensions
124 res = [];
125 pls = [];
126 filtsz = [];
127 for jj=1:nn % collect filters coefficients along the columns zz
128 bfil = mfil(jj,zz).filters;
129 filtsz = [filtsz; numel(bfil)];
130 for kk=1:numel(bfil)
131 num = bfil(kk).a;
132 den = bfil(kk).b;
133 res = [res; num(1)];
134 pls = [pls; -1*den(2)];
135 end
136 end
137
138 % rescaling residues to get the correct result for univariate psd
139 res = res.*sqrt(fs/2);
140
141
142 % Nrs = numel(res);
143 % % get covariance matrix
144 % R = zeros(Nrs);
145 % for aa=1:Nrs
146 % for bb=1:Nrs
147 % R(aa,bb) = (res(aa)*conj(res(bb)))/(1-pls(aa)*conj(pls(bb)));
148 % end
149 % end
150 %
151 % % avoiding problems caused by roundoff errors
152 % HH = triu(R,0); % get upper triangular part of R
153 % HH1 = triu(R,1); % get upper triangular part of R above principal diagonal
154 % HH2 = HH1'; % do transpose conjugate
155 % R = HH + HH2; % reconstruct R in order to be really hermitian
156 %
157 % % get singular value decomposition of R
158 % [U,S,V] = svd(R,0);
159 %
160 % % conversion matrix
161 % A = V*sqrt(S);
162 %
163 % % generate unitary variance gaussian random noise
164 % %ns = randn(Nrs,Ntot);
165 % ns = randn(Nrs,1);
166 %
167 % % get correlated starting data points
168 % cns = A*ns;
169 %
170 % % need to correct for roundoff errors
171 % % cleaning up results for numerical approximations
172 % idx = imag(pls(:,1))==0;
173 % cns(idx) = real(cns(idx));
174 %
175 % % cleaning up results for numerical roundoff errors
176 % % states associated to complex conjugate poles must be complex
177 % % conjugate
178 % idxi = imag(pls(:,1))~=0;
179 % icns = cns(idxi);
180 % for jj = 1:2:numel(icns)
181 % icns(jj+1,1) = conj(icns(jj,1));
182 % end
183 % cns(idxi) = icns;
184
185 cns = getinitz(res,pls,filtsz,fromnsg2D);
186
187 y = zeros(sum(filtsz),2);
188 rnoise = zeros(sum(filtsz),1);
189 rns = randn(1,Ntot);
190 %rns = utils.math.blwhitenoise(Ntot,fs,1/Nsecs,fs/2);
191 %rns = rns.'; % willing to work with raw
192
193 y(:,1) = cns;
194
195 % start recurrence
196 for xx = 2:Ntot+1
197 rnoise(:,1) = rns(xx-1);
198 y(:,2) = pls.*y(:,1) + res.*rnoise;
199 idxr = 0;
200 for kk=1:nn
201 o(kk,xx-1) = o(kk,xx-1) + sum(y(idxr+1:idxr+filtsz(kk),2));
202 idxr = idxr+filtsz(kk);
203 end
204 y(:,1) = y(:,2);
205 end
206
207 end
208
209 clear rns
210
211 % build output ao
212 for dd=1:nn
213 out(dd,1) = ao(tsdata(o(dd,:),fs));
214 out(dd,1).setYunits(unit(yunit));
215 end
216
217 outm = matrix(out);
218
219 case 's' % continuous input filters
220
221 o = zeros(nn,Ntot);
222
223 T = 1/fs; % sampling period
224
225 for zz=1:nn % moving along system dimension
226
227 % extract residues and poles from input objects
228 % run over matrix dimensions
229 res = [];
230 pls = [];
231 filtsz = [];
232 for jj=1:nn % collect filters coefficients along the columns zz
233 bfil = mfil(jj,zz);
234 filtsz = [filtsz; numel(bfil.res)];
235 res = [res; bfil.res];
236 pls = [pls; bfil.poles];
237 end
238
239 % rescaling residues to get the correct result for univariate psd
240 res = res.*sqrt(fs/2);
241
242 Nrs = numel(res);
243
244 % get covariance matrix for innovation
245 Ri = zeros(Nrs);
246 for aa=1:Nrs
247 for bb=1:Nrs
248 Ri(aa,bb) = (res(aa)*conj(res(bb)))*(exp((pls(aa) + conj(pls(bb)))*T)-1)/(pls(aa) + conj(pls(bb)));
249 end
250 end
251
252 % avoiding problems caused by roundoff errors
253 HH = triu(Ri,0); % get upper triangular part of R
254 HH1 = triu(Ri,1); % get upper triangular part of R above principal diagonal
255 HH2 = HH1'; % do transpose conjugate
256 Ri = HH + HH2; % reconstruct R in order to be really hermitian
257
258 % get singular value decomposition of R
259 [Ui,Si,Vi] = svd(Ri,0);
260
261 % conversion matrix for innovation
262 Ai = Vi*sqrt(Si);
263
264 % get covariance matrix for initial state
265 Rx = zeros(Nrs);
266 for aa=1:Nrs
267 for bb=1:Nrs
268 Rx(aa,bb) = -1*(res(aa)*conj(res(bb)))/(pls(aa) + conj(pls(bb)));
269 end
270 end
271
272 % avoiding problems caused by roundoff errors
273 HH = triu(Rx,0); % get upper triangular part of R
274 HH1 = triu(Rx,1); % get upper triangular part of R above principal diagonal
275 HH2 = HH1'; % do transpose conjugate
276 Rx = HH + HH2; % reconstruct R in order to be really hermitian
277
278 % get singular value decomposition of R
279 [Ux,Sx,Vx] = svd(Rx,0);
280
281 % conversion matrix for initial state
282 Ax = Vx*sqrt(Sx);
283
284 % generate unitary variance gaussian random noise
285 %ns = randn(Nrs,Ntot);
286 ns = randn(Nrs,1);
287
288 % get correlated starting data points
289 cns = Ax*ns;
290
291 % need to correct for roundoff errors
292 % cleaning up results for numerical approximations
293 idx = imag(pls(:,1))==0;
294 cns(idx) = real(cns(idx));
295
296 % cleaning up results for numerical roundoff errors
297 % states associated to complex conjugate poles must be complex
298 % conjugate
299 idxi = imag(pls(:,1))~=0;
300 icns = cns(idxi);
301 for jj = 1:2:numel(icns)
302 icns(jj+1,1) = conj(icns(jj,1));
303 end
304 cns(idxi) = icns;
305
306 y = zeros(sum(filtsz),2);
307 rnoise = zeros(sum(filtsz),1);
308 rns = randn(1,Ntot);
309 %rns = utils.math.blwhitenoise(Ntot,fs,1/Nsecs,fs/2);
310 %rns = rns.'; % willing to work with raw
311
312 y(:,1) = cns;
313
314 % start recurrence
315 for xx = 2:Ntot+1
316 % innov = Ai*randn(sum(filtsz),1);
317 rnoise(:,1) = rns(xx-1);
318 innov = Ai*rnoise;
319 % need to correct for roundoff errors
320 % cleaning up results for numerical approximations
321 innov(idx) = real(innov(idx));
322
323 % cleaning up results for numerical roundoff errors
324 % states associated to complex conjugate poles must be complex
325 % conjugate
326 iinnov = innov(idxi);
327 for jj = 1:2:numel(iinnov)
328 iinnov(jj+1,1) = conj(iinnov(jj,1));
329 end
330 innov(idxi) = iinnov;
331
332 y(:,2) = diag(exp(pls.*T))*y(:,1) + innov;
333
334 idxr = 0;
335 for kk=1:nn
336 o(kk,xx-1) = o(kk,xx-1) + sum(y(idxr+1:idxr+filtsz(kk),2));
337 idxr = idxr+filtsz(kk);
338 end
339 y(:,1) = y(:,2);
340 end
341
342 end
343
344 % clear rns
345
346 % build output ao
347 for dd=1:nn
348 out(dd,1) = ao(tsdata(o(dd,:),fs));
349 out(dd,1).setYunits(unit(yunit));
350 end
351
352 outm = matrix(out);
353
354 end
355
356 % set output
357 varargout{1} = outm;
358
359
360 end
361
362 %--------------------------------------------------------------------------
363 % Get Info Object
364 %--------------------------------------------------------------------------
365 function ii = getInfo(varargin)
366 if nargin == 1 && strcmpi(varargin{1}, 'None')
367 sets = {};
368 pl = [];
369 else
370 sets = {'Default'};
371 pl = getDefaultPlist;
372 end
373 % Build info object
374 ii = minfo(mfilename, 'matrix', 'ltpda', utils.const.categories.sigproc, '$Id: mchNoisegen.m,v 1.6 2011/04/08 08:56:31 hewitson Exp $', sets, pl);
375 ii.setArgsmin(1);
376 ii.setOutmin(1);
377 ii.setOutmax(1);
378 end
379
380 %--------------------------------------------------------------------------
381 % Get Default Plist
382 %--------------------------------------------------------------------------
383 function plout = getDefaultPlist()
384 persistent pl;
385 if exist('pl', 'var')==0 || isempty(pl)
386 pl = buildplist();
387 end
388 plout = pl;
389 end
390
391 function pl = buildplist()
392
393 pl = plist();
394
395 % Nsecs
396 p = param({'nsecs', 'Number of seconds in the desired noise data series.'}, {1, {1}, paramValue.OPTIONAL});
397 pl.append(p);
398
399 % Fs
400 p = param({'fs', 'The sampling frequency of the noise data series.'}, {1, {1}, paramValue.OPTIONAL});
401 pl.append(p);
402
403 % Yunits
404 p = param({'yunits','Unit on Y axis.'}, paramValue.STRING_VALUE(''));
405 pl.append(p);
406
407 end
408
409 %--------------------------------------------------------------------------
410 % Local function
411 % Estimate init values for the z domain case
412 %--------------------------------------------------------------------------
413 function cns = getinitz(res,pls,filtsz,fromnsg2D)
414
415 if fromnsg2D % init in the case of filters produced with noisegen2D
416 % divide in 2 the problem
417 res1 = res(1:filtsz(1));
418 res2 = res(filtsz(1)+1:filtsz(2));
419 pls1 = pls(1:filtsz(1));
420 pls2 = pls(filtsz(1)+1:filtsz(2));
421
422 %%% the first series %%%
423 Nrs = numel(res1);
424 % get covariance matrix
425 R = zeros(Nrs);
426 for aa=1:Nrs
427 for bb=1:Nrs
428 R(aa,bb) = (res1(aa)*conj(res1(bb)))/(1-pls1(aa)*conj(pls1(bb)));
429 end
430 end
431
432 % avoiding problems caused by roundoff errors
433 HH = triu(R,0); % get upper triangular part of R
434 HH1 = triu(R,1); % get upper triangular part of R above principal diagonal
435 HH2 = HH1'; % do transpose conjugate
436 R = HH + HH2; % reconstruct R in order to be really hermitian
437
438 % get singular value decomposition of R
439 [U,S,V] = svd(R,0);
440
441 % conversion matrix
442 A = V*sqrt(S);
443
444 % generate unitary variance gaussian random noise
445 %ns = randn(Nrs,Ntot);
446 ns = randn(Nrs,1);
447
448 % get correlated starting data points
449 cns1 = A*ns;
450
451 % need to correct for roundoff errors
452 % cleaning up results for numerical approximations
453 idx = imag(pls1(:,1))==0;
454 cns1(idx) = real(cns1(idx));
455
456 % cleaning up results for numerical roundoff errors
457 % states associated to complex conjugate poles must be complex
458 % conjugate
459 idxi = imag(pls1(:,1))~=0;
460 icns1 = cns1(idxi);
461 for jj = 1:2:numel(icns1)
462 icns1(jj+1,1) = conj(icns1(jj,1));
463 end
464 cns1(idxi) = icns1;
465
466 %%% the second series %%%
467 Nrs = numel(res2);
468 % get covariance matrix
469 R = zeros(Nrs);
470 for aa=1:Nrs
471 for bb=1:Nrs
472 R(aa,bb) = (res2(aa)*conj(res2(bb)))/(1-pls2(aa)*conj(pls2(bb)));
473 end
474 end
475
476 % avoiding problems caused by roundoff errors
477 HH = triu(R,0); % get upper triangular part of R
478 HH1 = triu(R,1); % get upper triangular part of R above principal diagonal
479 HH2 = HH1'; % do transpose conjugate
480 R = HH + HH2; % reconstruct R in order to be really hermitian
481
482 % get singular value decomposition of R
483 [U,S,V] = svd(R,0);
484
485 % conversion matrix
486 A = V*sqrt(S);
487
488 % generate unitary variance gaussian random noise
489 %ns = randn(Nrs,Ntot);
490 ns = randn(Nrs,1);
491
492 % get correlated starting data points
493 cns2 = A*ns;
494
495 % need to correct for roundoff errors
496 % cleaning up results for numerical approximations
497 idx = imag(pls2(:,1))==0;
498 cns2(idx) = real(cns2(idx));
499
500 % cleaning up results for numerical roundoff errors
501 % states associated to complex conjugate poles must be complex
502 % conjugate
503 idxi = imag(pls2(:,1))~=0;
504 icns2 = cns2(idxi);
505 for jj = 1:2:numel(icns2)
506 icns2(jj+1,1) = conj(icns2(jj,1));
507 end
508 cns2(idxi) = icns2;
509
510 %%% combine results %%%
511 cns = [cns1;cns2];
512
513 else % init in the case of filters produced with matrix constructor
514
515 Nrs = numel(res);
516 % get covariance matrix
517 R = zeros(Nrs);
518 for aa=1:Nrs
519 for bb=1:Nrs
520 R(aa,bb) = (res(aa)*conj(res(bb)))/(1-pls(aa)*conj(pls(bb)));
521 end
522 end
523
524 % avoiding problems caused by roundoff errors
525 HH = triu(R,0); % get upper triangular part of R
526 HH1 = triu(R,1); % get upper triangular part of R above principal diagonal
527 HH2 = HH1'; % do transpose conjugate
528 R = HH + HH2; % reconstruct R in order to be really hermitian
529
530 % get singular value decomposition of R
531 [U,S,V] = svd(R,0);
532
533 % conversion matrix
534 A = V*sqrt(S);
535
536 % generate unitary variance gaussian random noise
537 %ns = randn(Nrs,Ntot);
538 ns = randn(Nrs,1);
539
540 % get correlated starting data points
541 cns = A*ns;
542
543 % need to correct for roundoff errors
544 % cleaning up results for numerical approximations
545 idx = imag(pls(:,1))==0;
546 cns(idx) = real(cns(idx));
547
548 % cleaning up results for numerical roundoff errors
549 % states associated to complex conjugate poles must be complex
550 % conjugate
551 idxi = imag(pls(:,1))~=0;
552 icns = cns(idxi);
553 for jj = 1:2:numel(icns)
554 icns(jj+1,1) = conj(icns(jj,1));
555 end
556 cns(idxi) = icns;
557
558 end
559
560 end