Mercurial > hg > ltpda
diff m-toolbox/classes/@ao/whiten2D.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m-toolbox/classes/@ao/whiten2D.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,456 @@ +% WHITEN2D whiten the noise for two cross correlated time series. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: whiten2D whitens cross-correlated time-series. Whitening +% filters are constructed by a fitting procedure to the cross-spectrum +% models provided. +% Note: The function assumes that the input model corresponds to the +% one-sided csd of the data to be whitened. +% +% ALGORITHM: +% 1) Fit a set of partial fraction z-domain filters using +% utils.math.psd2wf +% 2) Convert to bank of mIIR filters +% 3) Filter time-series in parallel +% The filtering process is: +% b(1) = Filt11(a(1)) + Filt12(a(2)) +% b(2) = Filt21(a(1)) + Filt22(a(2)) +% +% CALL: b = whiten2D(a, pl) % returns whitened time-series AOs +% [b1,b2] = whiten2D(a1, a2, pl) +% [b1,b2,...,bn] = whiten2D(a1,a2,...,an, pl); +% Note: Input AOs must come in couples. +% Note: this method cannot be used as a modifier, the +% call a.whiten2D(pl) is forbidden. +% +% INPUT: +% +% - a is a couple of two colored noise time-series AOs +% +% OUTPUT: +% +% - b is a couple of "whitened" time-series AOs. The whitening +% filters used are stored in the objects procinfo field under +% the parameters: +% - b(1): 'Filt11' and 'Filt12' +% - b(2): 'Filt21' and 'Filt22' +% +% <a href="matlab:utils.helper.displayMethodInfo('ao', 'whiten2D')">Parameters Description</a> +% +% VERSION: $Id: whiten2D.m,v 1.35 2011/04/08 08:56:16 hewitson Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function varargout = whiten2D(varargin) + + % Check if this is a call for parameters + if utils.helper.isinfocall(varargin{:}) + varargout{1} = getInfo(varargin{3}); + return + end + + import utils.const.* + utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename); + + % Collect input variable names + in_names = cell(size(varargin)); + for ii = 1:nargin,in_names{ii} = inputname(ii);end + + % Collect all AOs and plists + [as, ao_invars] = utils.helper.collect_objects(varargin(:), 'ao', in_names); + pl = utils.helper.collect_objects(varargin(:), 'plist', in_names); + + % Decide on a deep copy or a modify + bs = copy(as, nargout); + cs = copy(as, nargout); + inhists = [as.hist]; + + % combine plists + pl = parse(pl, getDefaultPlist()); + pl.getSetRandState(); + + + % Extract necessary model parameters + csd11 = find(pl, 'csd11'); + csd12 = find(pl, 'csd12'); + csd21 = find(pl, 'csd21'); + csd22 = find(pl, 'csd22'); + + if nargout == 0 + error('### noisegen2D cannot be used as a modifier. Please give an output variable.'); + end + + % Check the number of input AO + if numel(bs)==1 + error('!!! One input AO! The input AOs must come in pairs!'); + end + % Checks that the input AOs come in pairs + odc = 0; + if rem(numel(as),2) + warning('The input AOs must come in pairs! Skipping AO %s during calculation', ao_invars{end}); + odc = 1; + end + + % Loop over input AOs to check for non time series objects + fsv = zeros(numel(bs),1); + for jj=1:numel(bs) + if ~isa(bs(jj).data, 'tsdata') + error('!!! %s expects ao/tsdata objects. ', mfilename); + end + fsv(jj,1) = bs(jj).data.fs; % collecting sampling frequencies + end + % Check that input Aos have the same sampling frequency + if any(diff(fsv)) + error('!!! Sampling frequency must be the same for all input objects') + end + + % ------------------- Coloring Noise + + % ---------------------------------- + % 1) - Fitting the models to identify the innovation filters + + % Build input structure for psd2tf + params = struct(); + + params.idtp = 1; + params.Nmaxiter = find(pl, 'MaxIter'); + params.minorder = find(pl, 'MinOrder'); + params.maxorder = find(pl, 'MaxOrder'); + params.spolesopt = find(pl, 'PoleType'); + params.weightparam = find(pl, 'Weights'); + params.usesym = find(pl, 'UseSym'); + params.spy = find(pl, 'Disp'); + params.keepvar = find(pl, 'keepvar'); + + % Tolerance for MSE Value + lrscond = find(pl, 'FITTOL'); + % give an error for strange values of lrscond + if lrscond<0 + error('!!! Negative values for FITTOL are not allowed !!!') + end + % handling data + lrscond = -1*log10(lrscond); + % give a warning for strange values of lrscond + if lrscond<0 + warning('You are searching for a MSE lower than %s', num2str(10^(-1*lrscond))) + end + params.lrscond = lrscond; + + % Tolerance for the MSE relative variation + msevar = find(pl, 'MSEVARTOL'); + % handling data + msevar = -1*log10(msevar); + % give a warning for strange values of msevar + if msevar<0 + warning('You are searching for MSE relative variation lower than %s', num2str(10^(-1*msevar))) + end + params.msevar = msevar; + + if isempty(params.msevar) + params.ctp = 'chival'; + else + params.ctp = 'chivar'; + end + + if(find(pl, 'plot')) + params.plot = 1; + else + params.plot = 0; + end + + params.fs = fsv(1,1); + params.dterm = 0; + + % get data variance + vars = [1 1]; + if numel(bs)==2 + for ii=1:numel(bs) + b = bs(ii).y; + v = var(b); + vars(ii) = v; + end + end + params.vars = vars; + + % call psd2wf + ostruct = utils.math.psd2wf(csd11.y,csd12.y,csd21.y,csd22.y,csd11.x,params); + + % ---------------------------------- + % 2) - Convert into MIIR filters + + fs = fsv(1,1); + + % --- filter 1 --- + res = ostruct(1).res; + poles = ostruct(1).poles; + dterm = ostruct(1).dterm; + % construct a struct array of miir filters vectors + pfilts1 = []; + for kk=1:numel(res) + ft = miir(res(kk), [ 1 -poles(kk)], fs); + pfilts1 = [pfilts1 ft]; + end +% pfilts1 = [pfilts1 miir(dterm, [1 0], fs)]; + + % --- filter 2 --- + res = ostruct(2).res; + poles = ostruct(2).poles; + dterm = ostruct(2).dterm; + % construct a struct array of miir filters vectors + pfilts2 = []; + for kk=1:numel(res) + ft = miir(res(kk), [ 1 -poles(kk)], fs); + pfilts2 = [pfilts2 ft]; + end +% pfilts2 = [pfilts2 miir(dterm, [1 0], fs)]; + + % --- filter 3 --- + res = ostruct(3).res; + poles = ostruct(3).poles; + dterm = ostruct(3).dterm; + % construct a struct array of miir filters vectors + pfilts3 = []; + for kk=1:numel(res) + ft = miir(res(kk), [ 1 -poles(kk)], fs); + pfilts3 = [pfilts3 ft]; + end +% pfilts3 = [pfilts3 miir(dterm, [1 0], fs)]; + + % --- filter 4 --- + res = ostruct(4).res; + poles = ostruct(4).poles; + dterm = ostruct(4).dterm; + % construct a struct array of miir filters vectors + pfilts4 = []; + for kk=1:numel(res) + ft = miir(res(kk), [ 1 -poles(kk)], fs); + pfilts4 = [pfilts4 ft]; + end +% pfilts4 = [pfilts4 miir(dterm, [1 0], fs)]; + + % ---------------------------------- + % 3) Filtering data + + for jj = 1:2:numel(bs)-1-odc + + bs(jj) = filter(cs(jj), pfilts1) + filter(cs(jj+1), pfilts2); + bs(jj+1) = filter(cs(jj), pfilts3) + filter(cs(jj+1), pfilts4); + + % ----------------------------------- + % 4) Output data + + % name for this object + bs(jj).name = sprintf('whiten2D(%s)_c1', [ao_invars{jj} ao_invars{jj+1}]); + % Collect the filters into procinfo + bs(jj).procinfo = combine(plist('Filt11', pfilts1,'Filt12', pfilts2),as(jj).procinfo); + % add history + bs(jj).addHistory(getInfo('None'), pl, [ao_invars(:)], [inhists(:)]); + + % name for this object + bs(jj+1).name = sprintf('whiten2D(%s)_c2', [ao_invars{jj} ao_invars{jj+1}]); + % Collect the filters into procinfo + bs(jj+1).procinfo = combine(plist('Filt21', pfilts3,'Filt22', pfilts4),as(jj+1).procinfo); + % add history + bs(jj+1).addHistory(getInfo('None'), pl, [ao_invars(:)], [inhists(:)]); + + end + + % clear errors + bs.clearErrors; + + % Set output + if nargout == numel(bs) + % List of outputs + for ii = 1:numel(bs) + varargout{ii} = bs.index(ii); + end + else + % Single output + varargout{1} = bs; + end +end + +%-------------------------------------------------------------------------- +% Get Info Object +%-------------------------------------------------------------------------- +function ii = getInfo(varargin) + if nargin == 1 && strcmpi(varargin{1}, 'None') + sets = {}; + pl = []; + else + sets = {'Default'}; + pl = getDefaultPlist; + end + % Build info object + ii = minfo(mfilename, 'ao', 'ltpda', utils.const.categories.sigproc, '$Id: whiten2D.m,v 1.35 2011/04/08 08:56:16 hewitson Exp $', sets, pl); + ii.setArgsmin(2); + ii.setOutmin(2); + ii.setModifier(false); +end + +%-------------------------------------------------------------------------- +% Get Default Plist +%-------------------------------------------------------------------------- + +function plout = getDefaultPlist() + persistent pl; + if exist('pl', 'var')==0 || isempty(pl) + pl = buildplist(); + end + plout = pl; +end + +function pl = buildplist() + + pl = plist(); + + % CSD11 + p = param({'csd11', 'A frequency-series AO describing the model csd11'}, paramValue.EMPTY_DOUBLE); + pl.append(p); + + % CSD12 + p = param({'csd12', 'A frequency-series AO describing the model csd12'}, paramValue.EMPTY_DOUBLE); + pl.append(p); + + % CSD21 + p = param({'csd21', 'A frequency-series AO describing the model csd21'}, paramValue.EMPTY_DOUBLE); + pl.append(p); + + % CSD22 + p = param({'csd22', 'A frequency-series AO describing the model csd22'}, paramValue.EMPTY_DOUBLE); + pl.append(p); + + % MaxIter + p = param({'MaxIter', 'Maximum number of iterations in fit routine.'}, paramValue.DOUBLE_VALUE(30)); + pl.append(p); + + % PoleType + p = param({'PoleType', ['Choose the pole type for fitting:<ol>'... + '<li>use real starting poles</li>' ... + '<li>generates complex conjugate poles of the<br>'... + 'type <tt>a.*exp(theta*pi*j)</tt><br>'... + 'with <tt>theta = linspace(0,pi,N/2+1)</tt></li>'... + '<li>generates complex conjugate poles of the type<br>'... + '<tt>a.*exp(theta*pi*j)</tt><br>'... + 'with <tt>theta = linspace(0,pi,N/2+2)</tt></li></ol>']}, {3, {1,2,3}, paramValue.SINGLE}); + pl.append(p); + + % MinOrder + p = param({'MinOrder', 'Minimum order to fit with.'}, paramValue.DOUBLE_VALUE(2)); + pl.append(p); + + % MaxOrder + p = param({'MaxOrder', 'Maximum order to fit with.'}, paramValue.DOUBLE_VALUE(25)); + pl.append(p); + + % Weights + p = param({'Weights', ['Choose weighting for the fit:<ol>'... + '<li>equal weights for each point</li>'... + '<li>weight with <tt>1/abs(model)</tt></li>'... + '<li>weight with <tt>1/abs(model).^2</tt></li>'... + '<li>weight with inverse of the square mean spread<br>'... + 'of the model</li></ol>']}, paramValue.DOUBLE_VALUE(3)); + pl.append(p); + + % Plot + p = param({'Plot', 'Plot results of each fitting step.'}, paramValue.FALSE_TRUE); + pl.append(p); + + % Disp + p = param({'Disp', 'Display the progress of the fitting iteration.'}, paramValue.FALSE_TRUE); + pl.append(p); + + % MSEVARTOL + p = param({'MSEVARTOL', ['Mean Squared Error Variation - Check if the<br>'... + 'realtive variation of the mean squared error is<br>'... + 'smaller than the value specified. This<br>'... + 'option is useful for finding the minimum of Chi-squared.']}, ... + paramValue.DOUBLE_VALUE(1e-2)); + pl.append(p); + + % FITTOL + p = param({'FITTOL', ['Mean Squared Error Value - Check if the mean<br>'... + 'squared error value is lower than the value<br>'... + 'specified.']}, paramValue.DOUBLE_VALUE(1e-2)); + pl.append(p); + + % UseSym + p = param({'UseSym', ['Use symbolic calculation in eigen-decomposition.<ul>'... + '<li>0 - perform double-precision calculation in the<br>'... + 'eigendecomposition procedure to identify 2-Dim<br>'... + 'systems and for poles stabilization</li>'... + '<li>1 - uses symbolic math toolbox variable precision<br>'... + 'arithmetic in the eigen-decomposition for 2-Dim<br>'... + 'system identification and double-precison for<br>'... + 'poles stabilization</li>'... + '<li>2 - uses symbolic math toolbox variable precision<br>'... + 'arithmetic in the eigen-decomposition for 2-Dim<br>'... + 'system identification and for poles stabilization.']}, {1, {0,1,2}, paramValue.SINGLE}); + pl.append(p); + + % Keep var + p = param({'keepvar', '???'}, paramValue.TRUE_FALSE); + p.val.setValIndex(2); + pl.append(p); + +end + + +% PARAMETERS: +% +% 'csd11' - a frequency-series AO describing the model csd11 +% 'csd12' - a frequency-series AO describing the model csd12 +% 'csd21' - a frequency-series AO describing the model csd21 +% 'csd22' - a frequency-series AO describing the model csd22 +% +% 'MaxIter' - Maximum number of iterations in fit routine +% [default: 30] +% +% 'PoleType' - Choose the pole type for fitting: +% 1 - use real starting poles +% 2 - generates complex conjugate poles of the +% type a.*exp(theta*pi*j) +% with theta = linspace(0,pi,N/2+1) +% 3 - generates complex conjugate poles of the type +% a.*exp(theta*pi*j) +% with theta = linspace(0,pi,N/2+2) [default] +% +% 'MinOrder' - Minimum order to fit with. [default: 2] +% +% 'MaxOrder' - Maximum order to fit with. [default: 25] +% +% 'Weights' - choose weighting for the fit: [default: 2] +% 1 - equal weights for each point +% 2 - weight with 1/abs(model) +% 3 - weight with 1/sqrt(abs(model)) +% 4 - weight with inverse of the square mean spread +% of the model +% +% 'Plot' - plot results of each fitting step. [default: false] +% +% 'Disp' - Display the progress of the fitting iteration. +% [default: false] +% +% 'FITTOL' - Mean Squared Error Value - Check if the mean +% squared error value is lower than the value +% specified. [defalut: 1e-2] +% +% 'MSEVARTOL' - Mean Squared Error Variation - Check if the +% realtive variation of the mean squared error is +% smaller than the value specified. This +% option is useful for finding the minimum of Chi +% squared. [default: 1e-2]] +% +% 'UseSym' - Use symbolic calculation in eigendecomposition. +% [default: 0] +% 0 - perform double-precision calculation in the +% eigendecomposition procedure to identify 2dim +% systems and for poles stabilization +% 1 - uses symbolic math toolbox variable precision +% arithmetic in the eigendecomposition for 2dim +% system identification and double-precison for +% poles stabilization +% 2 - uses symbolic math toolbox variable precision +% arithmetic in the eigendecomposition for 2dim +% system identification and for poles +% stabilization