line source
+ − % tdChi2 computes the chi-square for a parameter estimate.
+ − %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ − %
+ − % DESCRIPTION: tdChi2 computes the chi-square in time domain for an input
+ − % pest. The system measured outputs, inputs and models must be
+ − % contained in the plist. Also whitening filters for each
+ − % output may be taken into account.
+ − %
+ − % CALL: obj = tdChi2(objs,pl);
+ − %
+ − % INPUTS: obj - must be a single pest
+ − %
+ − % <a href="matlab:utils.helper.displayMethodInfo('pest', 'tdChi2')">Parameters Description</a>
+ − %
+ − % VERSION: $Id: tdChi2.m,v 1.5 2011/04/08 08:56:25 hewitson Exp $
+ − %
+ − % HISTORY: 08-02-2011 G. Congedo
+ − %
+ − %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ −
+ − function varargout = tdChi2(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
+ − [pests, pest_invars] = utils.helper.collect_objects(varargin(:), 'pest', in_names);
+ − pl = utils.helper.collect_objects(varargin(:), 'plist', in_names);
+ −
+ −
+ − % combine plists
+ − pl = parse(pl, getDefaultPlist());
+ −
+ − % Extract necessary parameters
+ − inputs = pl.find('inputs');
+ − outputs = pl.find('outputs');
+ − models = pl.find('models');
+ − WF = pl.find('WhiteningFilters');
+ − Ncut = pl.find('Ncut');
+ − Npad = pl.find('Npad');
+ −
+ − if nargout == 0
+ − error('### tdChi2 cannot be used as a modifier. Please give an output variable.');
+ − end
+ −
+ − if ~all(isa(pests, 'pest'))
+ − error('### tdChi2 must be only applied to pest objects.');
+ − end
+ −
+ − % Determine the class
+ − outClass = class(outputs);
+ −
+ − % Check ouputs
+ − if isempty(outputs)
+ − error('### Please give the outputs');
+ − end
+ − switch outClass
+ − case 'ao'
+ − N = numel(outputs);
+ − if N>1
+ − error('### Please give the outputs in a MATRIX');
+ − end
+ − case 'matrix'
+ − N = numel(outputs);
+ − if N>1
+ − error('### Please give the outputs in a COLLECTION of MATRIXs');
+ − end
+ − if outputs.ncols>1
+ − outputs = outputs.';
+ − end
+ − case 'collection'
+ − N = numel(outputs.objs);
+ − for ii=1:N
+ − if outputs.objs{ii}.ncols>1
+ − outputs.objs{ii} = outputs.objs{ii}.';
+ − end
+ − end
+ − otherwise
+ − error('### Unknown class for outputs');
+ − end
+ −
+ − % Check inputs
+ − if isempty(inputs)
+ − error('### Please give the inputs');
+ − end
+ − if ~strcmp(class(inputs),outClass)
+ − error('### Please give inputs as the same class of outputs');
+ − end
+ − switch outClass
+ − case 'ao'
+ − if numel(inputs)>1
+ − error('### Please give the inputs in a MATRIX');
+ − end
+ − case 'matrix'
+ − if numel(inputs)>1
+ − error('### Please give the inputs in a COLLECTION of MATRIXs');
+ − end
+ − if inputs.ncols>1
+ − inputs = inputs.';
+ − end
+ − case 'collection'
+ − for ii=1:numel(inputs.objs)
+ − if inputs.objs{ii}.ncols>1
+ − inputs.objs{ii} = inputs.objs{ii}.';
+ − end
+ − end
+ − end
+ −
+ − % Check models
+ − if isempty(models)
+ − error('### Please give the transfer function models');
+ − end
+ − switch outClass
+ − case 'ao'
+ − if ~strcmp(class(models),'smodel')
+ − error('### Please, give the transfer function in a SMODEL.');
+ − end
+ − if numel(models)>1
+ − error('### The size of the transfer function SMODEL does not match with the number of inputs/outputs.');
+ − end
+ − case {'matrix','collection'}
+ − if ~strcmp(class(models),'matrix')
+ − error('### Please, give the transfer function in a MATRIX of SMODELs.');
+ − end
+ − for ii=1:N
+ − if strcmp(outClass,'matrix')
+ − checkSz = models.nrows~=outputs.nrows || models.ncols~=inputs.nrows;
+ − elseif strcmp(outClass,'collection')
+ − checkSz = models.nrows~=outputs.objs{ii}.nrows || models.ncols~=inputs.objs{ii}.nrows;
+ − end
+ − if checkSz
+ − error('### The size of the transfer function MATRIX does not match with the number of inputs/outputs.');
+ − end
+ − end
+ − end
+ −
+ − % Check whitening filters
+ − whiten = ~isempty(WF);
+ − if whiten
+ − switch outClass
+ − case 'ao'
+ − if numel(WF)>1 || ~any(strcmp(class(WF),{'miir','fiir','filterbank'}))
+ − error('### Please give the whitening filters in a FIIR, MIIR or FILTERBANK');
+ − end
+ − case {'matrix','collection'}
+ − if ~strcmp(class(WF),'matrix')
+ − error('### Please give the whitening filters in a MATRIX of FIIRs, MIIRs or FILTERBANKs');
+ − end
+ − for ii=1:N
+ − if strcmp(outClass,'matrix')
+ − checkSz = WF.nrows~=outputs.nrows && WF.ncols~=outputs.nrows;
+ − elseif strcmp(outClass,'collection')
+ − checkSz = WF.nrows~=outputs.objs{ii}.nrows && WF.ncols~=outputs.objs{ii}.nrows;
+ − end
+ − if checkSz
+ − error('### The size of the whitening filters MATRIX does not match with the number of outputs.');
+ − end
+ − end
+ − end
+ − end
+ −
+ −
+ − % Actual computation
+ −
+ − chi2 = zeros(N,1);
+ − Ndata = zeros(N,1);
+ −
+ − % Subs unwanted params
+ − if strcmp(outClass,'matrix') || strcmp(outClass,'collection')
+ − for kk=1:numel(models.objs)
+ − models.objs(kk).setParams(pests.names,pests.y);
+ − models.objs(kk).subs(setdiff(models.objs(kk).params,pests.names));
+ − end
+ − else
+ − models.setParams(pests.names,pests.y);
+ − models.subs(setdiff(models.params,pests.names));
+ − end
+ −
+ − for ii=1:N
+ −
+ − % Time-domain template
+ − if strcmp(outClass,'matrix') || strcmp(outClass,'collection')
+ − template = fftfilt(inputs.objs{ii},models,plist('Npad',Npad));
+ − else
+ − template = fftfilt(inputs,models,plist('Npad',Npad));
+ − end
+ −
+ − % Residues
+ − if strcmp(outClass,'matrix') || strcmp(outClass,'collection')
+ − res = template-outputs.objs{ii};
+ − else
+ − res = template-outputs;
+ − end
+ −
+ − % Whiten
+ − if whiten
+ − res = filter(res,WF);
+ − end
+ −
+ − % Split-out transients
+ − if ~isempty(Ncut) || Ncut~=0
+ − res = split(res,plist('samples',[Ncut+1,Inf]));
+ − end
+ −
+ − % Compute chi2 & dof
+ − if strcmp(outClass,'matrix') || strcmp(outClass,'collection')
+ − chi2(ii) = sum(sum((res.objs.y).^2));
+ − Ndata(ii) = max(size(res.objs.y))*min(size(res.objs.y));
+ − else
+ − chi2(ii) = sum((res.y).^2);
+ − Ndata(ii) = numel(res.y);
+ − end
+ −
+ − end
+ −
+ − % Compute total chi2 & dof
+ − chi2 = sum(chi2);
+ − dof = sum(Ndata)-numel(pests.y);
+ −
+ − % Output pest
+ − out = copy(pests,1);
+ − out = out.setChi2(chi2/dof);
+ − out = out.setDof(dof);
+ − out = out.setName(['tdChi2(' pests.name ')']);
+ −
+ − out.addHistory(getInfo('None'), pl, pest_invars(:), [pests(:).hist]);
+ −
+ − % Set outputs
+ − if nargout > 0
+ − varargout{1} = out;
+ − 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, 'pest', 'ltpda', utils.const.categories.helper, '$Id: tdChi2.m,v 1.5 2011/04/08 08:56:25 hewitson Exp $', sets, pl);
+ − end
+ −
+ − %--------------------------------------------------------------------------
+ − % Get Default Plist
+ − %--------------------------------------------------------------------------
+ − function plout = getDefaultPlist()
+ − persistent pl;
+ − if exist('pl', 'var')==0 || isempty(pl)
+ − pl = buildplist();
+ − end
+ − plout = pl;
+ − end
+ −
+ − function plo = buildplist()
+ − plo = plist();
+ −
+ − % Outputs
+ − p = param({'Outputs', 'The system outputs. Must be an AO, a MATRIX or a COLLECTION of MATRIXs, one per each experiment.'}, paramValue.EMPTY_DOUBLE);
+ − plo.append(p);
+ −
+ − % Inputs
+ − p = param({'Inputs', 'The system inputs. Must be an AO, a MATRIX or a COLLECTION of MATRIXs, one per each experiment.'}, paramValue.EMPTY_DOUBLE);
+ − plo.append(p);
+ −
+ − % Models
+ − p = param({'Models', 'The system transfer function SMODELs. Must be a SMODEL or a MATRIX of SMODELs.'}, paramValue.EMPTY_DOUBLE);
+ − plo.append(p);
+ −
+ − % Whitening filters
+ − p = param({'WhiteningFilters', 'The output whitening filters. Must be a MIIR, FIIR, FILTERBANK or a MATRIX.'}, paramValue.EMPTY_DOUBLE);
+ − plo.append(p);
+ −
+ − % Ncut
+ − p = param({'Ncut', 'The number of points to cut out initial whitening filter transients.'}, paramValue.EMPTY_DOUBLE);
+ − plo.append(p);
+ −
+ − % Npad
+ − p = param({'Npad', 'The number of points to zero-pad the input for ifft. If left empty, a data length is assumed.'}, paramValue.EMPTY_DOUBLE);
+ − plo.append(p);
+ −
+ − end