comparison m-toolbox/classes/@ao/noisegen1D.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 % NOISEGEN1D generates colored noise from white noise.
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %
4 % DESCRIPTION: noisegen1D can work in two different modes:
5 %
6 % ------------------------------------------------------------------------
7 % 1) Generates colored noise from white noise with a given spectrum. The
8 % function constructs a coloring filter through a fitting procedure to the
9 % model provided. If no model is provided an error is prompted. The colored
10 % noise provided has one-sided psd corresponding to the input model.
11 %
12 % This mode correspond to the 'Default' set for the method (see the list of
13 % parameters).
14 %
15 % ALGORITHM:
16 % 1) Fit a set of partial fraction z-domain filters using
17 % utils.math.psd2tf
18 % 2) Convert to array of MIIR filters
19 % 3) Filter time-series in parallel
20 %
21 % CALL: b = noisegen1D(a, pl)
22 %
23 % INPUT:
24 % - a is a white noise time-series analysis object or a
25 % vector of analysis objects
26 % - pl is a plist with the input parameters
27 %
28 % OUTPUT:
29 %
30 % - b Colored time-series AOs. The coloring filters used
31 % are stored in the objects procinfo field under the
32 % parameter 'Filt'.
33 %
34 % ------------------------------------------------------------------------
35 %
36 % 2) Generates noise coloring filters for given input psd models.
37 %
38 % This mode correspond to the 'Filter' set for the method (see the list of
39 % parameters).
40 %
41 % ALGORITHM:
42 % 1) Fit a set of partial fraction z-domain filters
43 % 2) Convert to array of MIIR filters
44 %
45 % CALL: fil = noisegen1D(psd, pl)
46 %
47 % INPUT:
48 % - psd is a fsdata analysis object representing the desired
49 % model for the power spectral density of the colored noise
50 % - pl is a plist with the input parameters
51 %
52 % OUTPUT:
53 %
54 % - fil is a filterbank parallel object which elements are
55 % miir filters. Filters are initialized to avoid startup
56 % transients.
57 %
58 % ------------------------------------------------------------------------
59 %
60 % <a href="matlab:utils.helper.displayMethodInfo('ao', 'noisegen1D')">Parameters Description</a>
61 %
62 % VERSION: $Id: noisegen1D.m,v 1.30 2011/04/08 08:56:15 hewitson Exp $
63 %
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65
66 function varargout = noisegen1D(varargin)
67
68 % Check if this is a call for parameters
69 if utils.helper.isinfocall(varargin{:})
70 varargout{1} = getInfo(varargin{3});
71 return
72 end
73
74 import utils.const.*
75 utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename);
76
77 % Collect input variable names
78 in_names = cell(size(varargin));
79 for ii = 1:nargin,in_names{ii} = inputname(ii);end
80
81 % Collect all AOs and plists
82 [as, ao_invars] = utils.helper.collect_objects(varargin(:), 'ao', in_names);
83 pl = utils.helper.collect_objects(varargin(:), 'plist', in_names);
84
85 % Decide on a deep copy or a modify
86 bs = copy(as, nargout);
87 inhists = [as.hist];
88
89 % combine plists
90 % define input/output combinations. Different combination are
91 % 1) input tsdata and csd# into the plist, output are colored tsdata
92 % 2) input fsdata, output is a coloring filter (in a matrix)
93 if isempty(pl) % no model input, get model from input
94 setpar = 'Filter';
95 elseif isa(as(1).data,'fsdata') % get model from input
96 setpar = 'Filter';
97 else % get model from plist, output tsdata, back compatibility mode
98 setpar = 'Default';
99 end
100
101 pl = parse(pl, getDefaultPlist(setpar));
102 pl.getSetRandState();
103
104 switch lower(setpar)
105 case 'default'
106 % Extract necessary parameters
107 model = find(pl, 'model');
108 case 'filter'
109 fs = find(pl,'fs');
110 Iunits = find(pl, 'Iunits');
111 Ounits = find(pl, 'Ounits');
112
113 % init filter objects
114 fil = filterbank.initObjectWithSize(size(bs,1),size(bs,2));
115 end
116
117 % start building input structure for psd2tf
118 params.idtp = 1;
119 params.Nmaxiter = find(pl, 'MaxIter');
120 params.minorder = find(pl, 'MinOrder');
121 params.maxorder = find(pl, 'MaxOrder');
122 params.spolesopt = find(pl, 'PoleType');
123 params.weightparam = find(pl, 'Weights');
124 params.spy = find(pl, 'Disp');
125
126 % Tolerance for MSE Value
127 lrscond = find(pl, 'FITTOL');
128 % give an error for strange values of lrscond
129 if lrscond<0
130 error('!!! Negative values for FITTOL are not allowed !!!')
131 end
132 % handling data
133 lrscond = -1*log10(lrscond);
134 % give a warning for strange values of lrscond
135 if lrscond<0
136 warning('You are searching for a MSE lower than %s', num2str(10^(-1*lrscond)))
137 end
138 params.lrscond = lrscond;
139
140 % Tolerance for the MSE relative variation
141 msevar = find(pl, 'MSEVARTOL');
142 % handling data
143 msevar = -1*log10(msevar);
144 % give a warning for strange values of msevar
145 if msevar<0
146 warning('You are searching for MSE relative variation lower than %s', num2str(10^(-1*msevar)))
147 end
148 params.msevar = msevar;
149
150 if isempty(params.msevar)
151 params.ctp = 'chival';
152 else
153 params.ctp = 'chivar';
154 end
155
156 if(find(pl, 'plot'))
157 params.plot = 1;
158 else
159 params.plot = 0;
160 end
161
162 params.usesym = 0;
163 params.dterm = 0; % it is better to fit without dterm
164
165 % Loop over input AOs
166 for jj=1:numel(bs)
167
168 switch lower(setpar)
169 case 'default'
170 if ~isa(bs(jj).data, 'tsdata')
171 warning('!!! %s expects ao/tsdata objects. Skipping AO %s', mfilename, ao_invars{jj});
172 else
173 %-------------- Colored noise from white noise
174
175 % 1) If we have no model gives an error
176 if(isempty(model))
177 error('!!! Input a model for the desired PSD')
178 end
179
180 % 2) Noise Generation
181
182 params.fs = bs(jj).fs;
183
184 % call psd2tf
185 [res, poles, dterm, mresp, rdl] = ...
186 utils.math.psd2tf(model.y,[],[],[],model.x,params);
187
188 % get init state
189 Zi = utils.math.getinitstate(res,poles,1,'mtd','svd');
190
191 % 3) Convert to MIIR filters
192 % add yunits, taking them from plist or, if empty, from input object
193 Iunits = as(jj).yunits;
194 Ounits = find(pl, 'yunits');
195 if eq(unit(Ounits), unit(''))
196 Ounits = as(jj).yunits;
197 end
198 pfilts = [];
199 for kk=1:numel(res)
200 ft = miir(res(kk), [ 1 -poles(kk)], bs(jj).fs);
201 ft.setIunits(Iunits);
202 ft.setOunits(Ounits);
203 ft.setHistout(Zi(kk));
204 % build parallel bank of filters
205 pfilts = [pfilts ft];
206 end
207
208 % 4) Filter data
209 bs(jj).filter(pfilts);
210
211 % 5) Output data
212 % add history
213 bs(jj).addHistory(getInfo('None'), pl, [ao_invars(:)], [inhists(:)]);
214 % name for this object
215 bs(jj).setName(sprintf('noisegen1D(%s)', ao_invars{jj}));
216 % Collect the filters into procinfo
217 bs(jj).procinfo = plist('filter', pfilts);
218
219 end
220 case 'filter'
221
222 params.fs = fs;
223
224 % call psd2tf
225 [res, poles, dterm, mresp, rdl] = ...
226 utils.math.psd2tf(bs(jj).y,[],[],[],bs(jj).x,params);
227
228 % get init state
229 Zi = utils.math.getinitstate(res,poles,1,'mtd','svd');
230
231 % build miir
232 pfilts = [];
233 for kk=1:numel(res)
234 ft = miir(res(kk), [ 1 -poles(kk)], fs);
235 ft.setIunits(Iunits);
236 ft.setOunits(Ounits);
237 ft.setHistout(Zi(kk));
238 % build parallel bank of filters
239 pfilts = [pfilts ft];
240 end
241
242 % build output filterbanks
243 fil(jj) = filterbank(plist('filters',pfilts,'type','parallel'));
244 fil(jj).setName(sprintf('noisegen1D(%s)',ao_invars{jj}));
245 fil(jj).addHistory(getInfo('None'), pl, [ao_invars(:)], [inhists(:)]);
246 end
247 end
248
249 % switch output
250 switch lower(setpar)
251
252 case 'default'
253 % Set output
254 if nargout > 1 && nargout == numel(bs)
255 % List of outputs
256 for ii = 1:numel(bs)
257 varargout{ii} = bs.index(ii);
258 end
259 else
260 % Single output
261 varargout{1} = bs;
262 end
263
264 case 'filter'
265
266 % Set output
267 if nargout > 1 && nargout == numel(bs)
268 % List of outputs
269 for ii = 1:numel(fil)
270 varargout{ii} = fil.index(ii);
271 end
272 else
273 % Single output
274 varargout{1} = fil;
275 end
276
277 end
278 end
279
280 %--------------------------------------------------------------------------
281 % Get Info Object
282 %--------------------------------------------------------------------------
283 function ii = getInfo(varargin)
284 if nargin == 1 && strcmpi(varargin{1}, 'None')
285 sets = {};
286 pl = [];
287 elseif nargin == 1 && ~isempty(varargin{1}) && ischar(varargin{1})
288 sets{1} = varargin{1};
289 pl = getDefaultPlist(sets{1});
290 else
291 sets = SETS();
292 % get plists
293 pl(size(sets)) = plist;
294 for kk = 1:numel(sets)
295 pl(kk) = getDefaultPlist(sets{kk});
296 end
297 end
298 % Build info object
299 ii = minfo(mfilename, 'ao', 'ltpda', utils.const.categories.sigproc, '$Id: noisegen1D.m,v 1.30 2011/04/08 08:56:15 hewitson Exp $', sets, pl);
300
301 end
302
303
304 %--------------------------------------------------------------------------
305 % Defintion of Sets
306 %--------------------------------------------------------------------------
307
308 function out = SETS()
309 out = {...
310 'Default', ...
311 'Filter' ...
312 };
313 end
314
315 %--------------------------------------------------------------------------
316 % Get Default Plist
317 %--------------------------------------------------------------------------
318 function plout = getDefaultPlist(set)
319 persistent pl;
320 persistent lastset;
321 if exist('pl', 'var')==0 || isempty(pl) || ~strcmp(lastset, set)
322 pl = buildplist(set);
323 lastset = set;
324 end
325 plout = pl;
326 end
327
328 function pl = buildplist(set)
329
330 pl = plist();
331
332 switch lower(set)
333 case 'default'
334 % Yunits
335 p = param({'yunits',['Unit on Y axis. <br>' ...
336 'If left empty, it will take the y-units from the input object']}, paramValue.STRING_VALUE(''));
337 pl.append(p);
338
339 % Model
340 p = param({'model', 'A frequency-series AO describing the model psd'}, paramValue.EMPTY_DOUBLE);
341 pl.append(p);
342
343 case 'filter'
344 % Fs
345 p = param({'fs','The sampling frequency to design for.'}, paramValue.DOUBLE_VALUE(1));
346 pl.append(p);
347
348 % Iunits
349 p = param({'iunits','The input units of the filter.'}, paramValue.EMPTY_STRING);
350 pl.append(p);
351
352 % Ounits
353 p = param({'ounits','The output units of the filter.'}, paramValue.EMPTY_STRING);
354 pl.append(p);
355 end
356
357 % MaxIter
358 p = param({'MaxIter', 'Maximum number of iterations in fit routine.'}, paramValue.DOUBLE_VALUE(30));
359 pl.append(p);
360
361 % PoleType
362 p = param({'PoleType', ['Choose the pole type for fitting:<ol>'...
363 '<li>use real starting poles</li>' ...
364 '<li>generates complex conjugate poles of the<br>'...
365 'type <tt>a.*exp(theta*pi*j)</tt><br>'...
366 'with <tt>theta = linspace(0,pi,N/2+1)</tt></li>'...
367 '<li>generates complex conjugate poles of the type<br>'...
368 '<tt>a.*exp(theta*pi*j)</tt><br>'...
369 'with <tt>theta = linspace(0,pi,N/2+2)</tt></li></ol>']}, {3, {1,2,3}, paramValue.SINGLE});
370 pl.append(p);
371
372 % MinOrder
373 p = param({'MinOrder', 'Minimum order to fit with.'}, paramValue.DOUBLE_VALUE(2));
374 pl.append(p);
375
376 % MaxOrder
377 p = param({'MaxOrder', 'Maximum order to fit with.'}, paramValue.DOUBLE_VALUE(25));
378 pl.append(p);
379
380 % Weights
381 p = param({'Weights', ['Choose weighting for the fit:<ol>'...
382 '<li>equal weights for each point</li>'...
383 '<li>weight with <tt>1/abs(model)</tt></li>'...
384 '<li>weight with <tt>1/abs(model).^2</tt></li>'...
385 '<li>weight with inverse of the square mean spread<br>'...
386 'of the model</li></ol>']}, paramValue.DOUBLE_VALUE(3));
387 pl.append(p);
388
389 % Plot
390 p = param({'Plot', 'Plot results of each fitting step.'}, paramValue.FALSE_TRUE);
391 pl.append(p);
392
393 % Disp
394 p = param({'Disp', 'Display the progress of the fitting iteration.'}, paramValue.FALSE_TRUE);
395 pl.append(p);
396
397 % MSEVARTOL
398 p = param({'MSEVARTOL', ['Mean Squared Error Variation - Check if the<br>'...
399 'realtive variation of the mean squared error is<br>'...
400 'smaller than the value specified. This<br>'...
401 'option is useful for finding the minimum of Chi-squared.']}, ...
402 paramValue.DOUBLE_VALUE(1e-2));
403 pl.append(p);
404
405 % FITTOL
406 p = param({'FITTOL', ['Mean Squared Error Value - Check if the mean<br>'...
407 'squared error value is lower than the value<br>'...
408 'specified.']}, paramValue.DOUBLE_VALUE(1e-2));
409 pl.append(p);
410
411 end
412
413