Mercurial > hg > ltpda
diff m-toolbox/classes/+utils/@math/linlsqsvd.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/+utils/@math/linlsqsvd.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,140 @@ +% LINLSQSVD Linear least squares with singular value decomposition +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: Linear least square problem with singular value +% decomposition +% +% ALGORITHM: % It solves the problem +% +% Y = HX +% +% where X are the parameters, Y the measurements, and H the linear +% equations relating the two. +% It is able to perform linear identification of the parameters of a +% multichannel systems. The results of different experiments on the same +% system can be passed as input. The algorithm, thanks to the singular +% value decomposition, extract the maximum amount of information from each +% single channel and for each experiment. Total information is then +% combined to get the final result. +% +% CALL: [a,Ca,Corra,Vu,bu,Cbu,Fbu,mse,dof,ppm] = utils.math.linlsqsvd(H1,...,HN,Y); +% [a,Ca,Corra,Vu,bu,Cbu,Fbu,mse,dof,ppm] = utils.math.linlsqsvd(H1,...,HN,Y,errthres); +% [a,Ca,Corra,Vu,bu,Cbu,Fbu,mse,dof,ppm] = utils.math.linlsqsvd(H1,...,HN,Y,errthres,knwpars); +% +% If the experiment is 1 then H1,...,HN and Y are aos. +% If the experiments are M, then H1,...,HN and Y are Mx1 matrix objects +% with the aos relating to the given experiment in the proper position. +% +% INPUT: +% - Hi represent the columns of H +% - Y represent the measurement set +% - sThreshold it's a threshold for singular values. It is a +% number, typically 1. It will remove singular values larger +% than sThreshold which corresponds to removing svd parameters estimated +% with an error larger than sThreshold. +% - knwpars A struct array with the fields: +% pos - a number indicating the corresponding position of +% the parameter (corresponding column of H) +% value - the value for the parameter +% err - the uncertainty associated to the parameter +% +% OUTPUT: +% a: params values +% Ca: fit covariance matrix for A +% Corra: fit correlation matrix for A +% Vu: is the complete conversion matrix +% Cbu: is the new variables covariance matrix +% Fbu: is the information matrix for the new variable +% mse: is the fit Mean Square Error +% dof: degrees of freedom for the global estimation +% ppm: number of svd parameters per measurements, provides also the +% number of independent combinations of parameters per each singular +% measurement. The coefficients of the combinations are then stored in Vu +% +% 09-11-2010 L Ferraioli +% CREATION +% +% <a href="matlab:utils.helper.displayMethodInfo('matrix', 'linfitsvd')">Parameter Sets</a> +% +% VERSION: $Id: linlsqsvd.m,v 1.2 2011/03/11 09:28:26 luigi Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [a,Ca,Corra,Vu,bu,Cbu,Fbu,mse,dof,ppm] = linlsqsvd(varargin) + + + + %%% get input params + if isstruct(varargin{end}) + kwnpars = varargin{end}; + if isnumeric(varargin{end-1}) + sThreshold = varargin{end-1}; + A = varargin{1:end-2}; + else + A = varargin{1:end-1}; + sThreshold = []; + end + else + kwnpars = []; + if isnumeric(varargin{end}) + sThreshold = varargin{end}; + A = varargin{1:end-1}; + else + A = varargin{:}; + sThreshold = []; + end + end + + + %%% sort between one or multiple experiments + exps = struct; + + if isa(A(1),'ao') % one experiment + % Build matrices for lscov + C = A(1:end-1); + Y = A(end); + + H = C(:).y; + y = Y.y; + exps.fitbasis = H; + exps.fitdata = y; + elseif isa(A(1),'matrix') % multiple experiments + % run over input objects and experiments + for jj=1:numel(A(1).objs) + C = []; + for ii=1:numel(A)-1 + D = A(ii).objs(jj).y; + % willing to work with columns + if size(D,1)<size(D,2) + D = D.'; + end + C = [C D]; + end + y = A(end).objs(jj).y; + exps(jj).fitbasis = C; + exps(jj).fitdata = y; + end + else + error('Unknown input data type!') + end + + %%% do fit + if ~isempty(kwnpars) && isfield(kwnpars,'pos') + if ~isempty(sThreshold) + [a,Ca,Corra,Vu,bu,Cbu,Fbu,mse,dof,ppm] = utils.math.linfitsvd(exps,kwnpars,sThreshold); + else + [a,Ca,Corra,Vu,bu,Cbu,Fbu,mse,dof,ppm] = utils.math.linfitsvd(exps,kwnpars); + end + else + if ~isempty(sThreshold) + [a,Ca,Corra,Vu,bu,Cbu,Fbu,mse,dof,ppm] = utils.math.linfitsvd(exps,sThreshold); + else + [a,Ca,Corra,Vu,bu,Cbu,Fbu,mse,dof,ppm] = utils.math.linfitsvd(exps); + end + end + + + + +end +