Mercurial > hg > ltpda
diff m-toolbox/classes/@matrix/dispersion.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/@matrix/dispersion.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,556 @@ +% DISPERSION computes the dispersion function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: DISPERSION computes the dispersion function +% +% CALL: bs = dipersion(in,pl) +% +% INPUTS: in - matrix objects with input signals to the system +% model - symbolic models containing the transfer function model +% +% pl - parameter list +% +% OUTPUTS: bs - dispersion function AO +% +% <a href="matlab:utils.helper.displayMethodInfo('matrix', 'dispersion')">Parameters Description</a> +% +% VERSION: $Id: dispersion.m,v 1.1 2011/06/22 09:54:19 miquel Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function varargout = dispersion(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); + +% Method can not be used as a modifier +if nargout == 0 + error('### crb cannot be used as a modifier. Please give an output variable.'); +end + +% Collect input variable names +in_names = cell(size(varargin)); +for ii = 1:nargin,in_names{ii} = inputname(ii);end + +% Collect all AOs smodels and plists +[mtxs, mtxs_invars] = utils.helper.collect_objects(varargin(:), 'matrix', in_names); +pl = utils.helper.collect_objects(varargin(:), 'plist', in_names); + +% Combine plists +pl = parse(pl, getDefaultPlist); + +% get params +params = find(pl,'FitParams'); +numparams = find(pl,'paramsValues'); +mmdl = find(pl,'model'); +channel = find(pl,'channel'); +mtxns = find(pl,'noise'); +outModel = find(pl,'outModel'); +bmdl = find(pl,'built-in'); +f1 = find(pl,'f1'); +f2 = find(pl,'f2'); +pseudoinv = find(pl,'pinv'); +tol = find(pl,'tol'); +outNames = find(pl,'outNames'); +inNames = find(pl,'inNames'); + +% Decide on a deep copy or a modify +fin = copy(mtxs, nargout); +n = copy(mtxns, nargout); +mdl = copy(mmdl,1); + +% Get number of experiments +nexp = numel(fin); + +% fft +% fin = fft(in); + +% N should get before spliting, in order to convert correctly from psd to +% fft +N = length(fin(1).getObjectAtIndex(1).x); + +% Get rid of fft f =0, reduce frequency range if needed +if ~isempty(f1) && ~isempty(f2) + fin = split(fin,plist('frequencies',[f1 f2])); +end + +FMall = zeros(numel(params),numel(params)); +% loop over experiments +for k = 1:nexp + + utils.helper.msg(msg.IMPORTANT, sprintf('Analysis of experiment #%d',k), mfilename('class'), mfilename); + +% if (((numel(n(1).objs)) == 2) && (numel(fin(1).objs) == 2)) + + % use signal fft to get frequency vector. Take into account signal + % could be empty or set to zero + % 1st channel + if all(fin(k).getObjectAtIndex(1,1).y == 0) || isempty(fin(k).getObjectAtIndex(1,1).y) + i1 = ao(plist('type','fsdata','xvals',0,'yvals',0)); + else + i1 = fin(k).getObjectAtIndex(1,1); + freqs = i1.x; + end + % 2nd channel + if all(fin(k).getObjectAtIndex(2,1).y == 0) || isempty(fin(k).getObjectAtIndex(2,1).y) + i2 = ao(plist('type','fsdata','xvals',0,'yvals',0)); + else + i2 = fin(k).getObjectAtIndex(2,1); + freqs = i2.x; + end + + % Compute psd + n1 = lpsd(n(k).getObjectAtIndex(1,1)); + n2 = lpsd(n(k).getObjectAtIndex(2,1)); + n12 = lcpsd(n(k).getObjectAtIndex(1,1),n(k).getObjectAtIndex(2,1)); + + % interpolate to given frequencies + % noise + S11 = interp(n1,plist('vertices',freqs)); + S12 = interp(n12,plist('vertices',freqs)); + S22 = interp(n2,plist('vertices',freqs)); + S21 = conj(S12); + + % get some parameters used below + fs = S11.fs; + + +% if (isempty(outModel)) + +% if ~isempty(bmdl) + % compute built-in smodels +% for i = 1:4 +% if strcmp(bmdl{i},'0'); +% h(i) = smodel('0'); +% h(i).setXvar('f'); +% h(i).setXvals(freqs); +% h(i).setParams(params,numparams); +% else +% h(i) = smodel(plist('built-in',bmdl{i},'f',freqs)); +% % set all params to all models. It is not true but harmless +% for ii = 1:numel(params) +% vecparams(ii) = {numparams(ii)*ones(size(freqs))}; +% end +% h(i).setParams(params,vecparams); +% end +% end +% elseif ~isempty(mdl) && all(strcmp(class(mdl),'matrix')) + + for i = 1:numel(mdl.objs) + % set Xvals + h(i) = mdl.getObjectAtIndex(i).setXvals(freqs); + % set alias + h(i).assignalias(mdl.objs(i),plist('xvals',freqs)); + % set paramaters + h(i).setParams(params,numparams); + end + % differentiate and eval + for i = 1:length(params) + utils.helper.msg(msg.IMPORTANT, sprintf('computing symbolic differentiation with respect %s',params{i}), mfilename('class'), mfilename); + % differentiate symbolically + dH11 = diff(h(1),params{i}); + dH12 = diff(h(3),params{i}); % taking into account matrix index convention h(2) > H(2,1) + dH21 = diff(h(2),params{i}); + dH22 = diff(h(4),params{i}); + % evaluate + d11(i) = eval(dH11,plist('output type','fsdata','output x',freqs)); + d12(i) = eval(dH12,plist('output type','fsdata','output x',freqs)); + d21(i) = eval(dH21,plist('output type','fsdata','output x',freqs)); + d22(i) = eval(dH22,plist('output type','fsdata','output x',freqs)); + end + +% elseif ~isempty(mdl) && all(strcmp(class(mdl),'ssm')) +% +% meval = copy(mdl,1); +% % set parameter values +% meval.doSetParameters(params, numparams); +% +% % make numeric +% % meval.doSubsParameters(params, true); +% +% % get the differentiation step +% step = find(pl,'diffStep'); +% if isempty(step) +% error('### Please input a step for the numerical differentiation') +% end +% +% % differentiate and eval +% for i = 1:length(params) +% utils.helper.msg(msg.IMPORTANT, sprintf('computing numerical differentiation with respect %s, Step:%4.2d ',params{i},step(i)), mfilename('class'), mfilename); +% % differentiate numerically +% dH = meval.parameterDiff(plist('names', params(i),'values',step(i))); +% % create plist with correct outNames (since parameterDiff change them) +% out1 = strrep(outNames{1},'.', sprintf('_DIFF_%s.',params{i})); % 2x2 case +% out2 =strrep(outNames{2},'.', sprintf('_DIFF_%s.',params{i})); +% spl = plist('set', 'for bode', ... +% 'outputs', {out1,out2}, ... +% 'inputs', inNames, ... +% 'reorganize', true,... +% 'f', freqs); +% % do bode +% d = bode(dH, spl); +% % assign according matlab's matrix notation: H(1,1)->h(1) H(2,1)->h(2) H(1,2)->h(3) H(2,2)->h(4) +% d11(i) = d(1); +% d21(i) = d(2); +% d12(i) = d(3); +% d22(i) = d(4); +% end +% +% else +% error('### please introduce models for the transfer functions') +% end + +% elseif (~isempty(outModel)) +% +% % if(~isempty(outModel)) +% for lll=1:size(outModel,1) +% for kkk=1:size(outModel,2) +% outModel(lll,kkk) = split(outModel(lll,kkk),plist('frequencies',[f1 f2])); +% end +% end +% %end +% +% % Avoid numerical differentiation (faster for the magnetic case) +% Param{1} = [1 0; +% 0 0;]; +% Param{2} = [0 0; +% 0 1;]; +% +% for pp = 1:length(params) +% for ll = 1:size(outModel,1) +% for kk = 1:size(Param{pp},2) +% % index convention: H(1,1)->h(1) H(2,1)->h(2) H(1,2)->h(3) H(2,2)->h(4) +% tmp = 0; +% for innerIndex = 1:size(outModel,2) +% tmp = tmp + outModel(ll,innerIndex).y * Param{pp}(innerIndex,kk); +% end +% h{pp}(:,(kk-1)*size(outModel,1) + ll) = tmp; +% end +% end +% +% end +% +% for i = 1:length(params) +% d11(i).y = h{i}(:,1); +% d21(i).y = h{i}(:,2); +% d12(i).y = h{i}(:,3); +% d22(i).y = h{i}(:,4); +% end +% +% end + + % scaling of PSD + % PSD = 2/(N*fs) * FFT *conj(FFT) + C11 = N*fs/2.*S11.y; + C22 = N*fs/2.*S22.y; + C12 = N*fs/2.*S12.y; + C21 = N*fs/2.*S21.y; + + % compute elements of inverse cross-spectrum matrix + InvS11 = (C22./(C11.*C22 - C12.*C21)); + InvS22 = (C11./(C11.*C22 - C12.*C21)); + InvS12 = (C21./(C11.*C22 - C12.*C21)); + InvS21 = (C12./(C11.*C22 - C12.*C21)); + + + % compute Fisher Matrix + for i =1:length(params) + for j =1:length(params) + + v1v1 = conj(d11(i).y.*i1.y + d12(i).y.*i2.y).*(d11(j).y.*i1.y + d12(j).y.*i2.y); + v2v2 = conj(d21(i).y.*i1.y + d22(i).y.*i2.y).*(d21(j).y.*i1.y + d22(j).y.*i2.y); + v1v2 = conj(d11(i).y.*i1.y + d12(i).y.*i2.y).*(d21(j).y.*i1.y + d22(j).y.*i2.y); + v2v1 = conj(d21(i).y.*i1.y + d22(i).y.*i2.y).*(d11(j).y.*i1.y + d12(j).y.*i2.y); + + FisMat(i,j) = sum(real(InvS11.*v1v1 + InvS22.*v2v2 - InvS12.*v1v2 - InvS21.*v2v1)); + end + end + utils.helper.msg(msg.IMPORTANT, sprintf('rank(FisMat) = %d', rank(FisMat))); + + for kk = 1:numel(freqs) + % create input signal with power at single freq. + % depending on input channel + p = zeros(1,numel(freqs)); + if channel == 1 + p(kk) = sum(i1.y); + % create aos + i1single = ao(plist('Xvals',freqs,'Yvals',p)); + i2single = ao(plist('Xvals',freqs,'Yvals',zeros(1,numel(freqs)))); + elseif channel == 2 + p(kk) = sum(i2.y); + % create aos + i1single = ao(plist('Xvals',freqs,'Yvals',zeros(1,numel(freqs)))); + i2single = ao(plist('Xvals',freqs,'Yvals',p)); + else + error('### wrong channel') + end + + % compute Fisher Matrix for single frequencies + for i =1:length(params) + for j =1:length(params) + + v1v1 = conj(d11(i).y.*i1single.y + d12(i).y.*i2single.y).*(d11(j).y.*i1single.y + d12(j).y.*i2single.y); + v2v2 = conj(d21(i).y.*i1single.y + d22(i).y.*i2single.y).*(d21(j).y.*i1single.y + d22(j).y.*i2single.y); + v1v2 = conj(d11(i).y.*i1single.y + d12(i).y.*i2single.y).*(d21(j).y.*i1single.y + d22(j).y.*i2single.y); + v2v1 = conj(d21(i).y.*i1single.y + d22(i).y.*i2single.y).*(d11(j).y.*i1single.y + d12(j).y.*i2single.y); + + FisMatsingle(i,j) = sum(real(InvS11.*v1v1 + InvS22.*v2v2 - InvS12.*v1v2 - InvS21.*v2v1)); + end + end + d(kk) = trace(FisMat\FisMatsingle)/numel(i1.x); % had to divide for num. freqs +% d(kk) = trace(pinv(FisMat)*FisMatsingle)/numel(i1.x); % had to divide for num. freqs + + end + +% % store Fisher Matrix for this run +% FM{k} = FisMat; +% % adding up +% FMall = FMall + FisMat; + +% elseif ((numel(n(1).objs) == 3) && (numel(in.objs) == 4) && ~isempty(outModel)) +% % this is only valid for the magnetic model, where we have 4 inputs +% % (corresponding to the 4 conformator waveforms) and 3 outputs +% % (corresponding to IFO.x12, IFO.eta1 and IFO.phi1). And there is a +% % contribution of an outModel converting the conformator waveforms +% % into forces and torques. +% +% +% % For other cases not implemented yet. +% +% % use signal fft to get frequency vector. Take into account signal +% % could be empty or set to zero +% % 1st channel +% freqs = fin.getObjectAtIndex(1,1).x; +% +% for ii = 1:numel(n.objs) +% for jj = ii:numel(n.objs) +% % Compute psd +% if (ii==jj) +% spec(ii,jj) = psd(n(k).getObjectAtIndex(ii), pl); +% S2(ii,jj) = interp(spec(ii,jj),plist('vertices',freqs,'method','linear')); +% else +% spec(ii,jj) = cpsd(n(k).getObjectAtIndex(ii),n(k).getObjectAtIndex(jj),pl); +% S2(ii,jj) = interp(spec(ii,jj),plist('vertices',freqs,'method','linear')); +% S2(jj,ii) = conj(S2(ii,jj)); +% end +% end +% end +% +% S = matrix(S2,plist('shape',[numel(n.objs) numel(n.objs)])); +% +% % get some parameters used below +% fs = S.getObjectAtIndex(1,1).fs; +% +% +% if(~isempty(outModel)) +% for lll=1:size(outModel,1) +% for kkk=1:size(outModel,2) +% outModel(lll,kkk) = split(outModel(lll,kkk),plist('frequencies',[f1 f2])); +% end +% end +% end +% +% % Avoid numerical differentiation (faster for the magnetic case) +% Param{1} = [ 1 0 0 0; +% 0 0 0 0; +% 0 0 0 0;]; +% Param{2} = [ 0 1 0 0; +% 0 0 0 0; +% 0 0 0 0;]; +% Param{3} = [ 0 0 0 0; +% 0 0 1 0; +% 0 0 0 0;]; +% Param{4} = [ 0 0 0 0; +% 0 0 0 0; +% 0 0 0 1;]; +% +% % scaling of PSD +% % PSD = 2/(N*fs) * FFT *conj(FFT) +% for j = 1: numel(S.objs) +% % spectra to variance +% C(:,j) = (N*fs/2)*S.objs(j).data.getY; +% end +% +% detm = (C(:,1).*C(:,5).*C(:,9) + ... +% C(:,2).*C(:,6).*C(:,7) + ... +% C(:,3).*C(:,4).*C(:,8) -... +% C(:,7).*C(:,5).*C(:,3) -... +% C(:,8).*C(:,6).*C(:,1) -... +% C(:,9).*C(:,4).*C(:,2)); +% +% InvS11 = (C(:,5).*C(:,9) - C(:,8).*C(:,6))./detm; +% InvS12 = -(C(:,4).*C(:,9) - C(:,7).*C(:,6))./detm; +% InvS13 = (C(:,4).*C(:,8) - C(:,7).*C(:,5))./detm; +% InvS21 = -(C(:,2).*C(:,9) - C(:,8).*C(:,3))./detm; +% InvS22 = (C(:,1).*C(:,9) - C(:,7).*C(:,3))./detm; +% InvS23 = -(C(:,1).*C(:,8) - C(:,7).*C(:,2))./detm; +% InvS31 = (C(:,2).*C(:,6) - C(:,5).*C(:,3))./detm; +% InvS32 = -(C(:,1).*C(:,6) - C(:,4).*C(:,3))./detm; +% InvS33 = (C(:,1).*C(:,5) - C(:,4).*C(:,2))./detm; +% +% for pp = 1:length(params) +% for ll = 1:size(outModel,1) +% for kk = 1:size(Param{pp},2) +% % index convention: H(1,1)->h(1) H(2,1)->h(2) H(1,2)->h(3) H(2,2)->h(4) +% tmp = 0; +% for innerIndex = 1:size(outModel,2) +% tmp = tmp + outModel(ll,innerIndex).y * Param{pp}(innerIndex,kk); +% end +% h{pp}(:,(kk-1)*size(outModel,1) + ll) = tmp; +% end +% end +% +% end +% +% for kk = 1:numel(in.objs) +% inV(:,kk) = fin.objs(kk).data.getY; +% end +% +% +% % compute Fisher Matrix +% for i =1:length(params) +% for j =1:length(params) +% +% for ll = 1:size(outModel,1) +% tmp = 0; +% for kk = 1:size(Param{1},2) +% tmp = tmp + h{i}(:,(kk-1)*size(outModel,1) + ll).*inV(:,kk); +% end +% v{i}(:,ll) = tmp; +% end +% +% +% for ll = 1:size(outModel,1) +% tmp = 0; +% for kk = 1:size(Param{1},2) +% tmp = tmp + h{j}(:,(kk-1)*size(outModel,1) + ll).*inV(:,kk); +% end +% v{j}(:,ll) = tmp; +% end +% +% v1v1 = conj(v{i}(:,1)).*v{j}(:,1); +% v1v2 = conj(v{i}(:,1)).*v{j}(:,2); +% v1v3 = conj(v{i}(:,1)).*v{j}(:,3); +% v2v1 = conj(v{i}(:,2)).*v{j}(:,1); +% v2v2 = conj(v{i}(:,2)).*v{j}(:,2); +% v2v3 = conj(v{i}(:,2)).*v{j}(:,3); +% v3v1 = conj(v{i}(:,3)).*v{j}(:,1); +% v3v2 = conj(v{i}(:,3)).*v{j}(:,2); +% v3v3 = conj(v{i}(:,3)).*v{j}(:,3); +% +% FisMat(i,j) = sum(real(InvS11.*v1v1 +... +% InvS12.*v1v2 +... +% InvS13.*v1v3 +... +% InvS21.*v2v1 +... +% InvS22.*v2v2 +... +% InvS23.*v2v3 +... +% InvS31.*v3v1 +... +% InvS32.*v3v2 +... +% InvS33.*v3v3)); +% end +% end +% % store Fisher Matrix for this run +% FM{k} = FisMat; +% % adding up +% FMall = FMall + FisMat; +% else +% error('Implemented cases: 2 inputs / 2outputs (TN3045 analysis), and 4 inputs / 3 outpus (magnetic complete analysis model. Other cases have not been implemented yet. Sorry for the inconvenience)'); +% end + + +% end + +% inverse is the optimal covariance matrix +% if pseudoinv && isempty(tol) +% cov = pinv(FMall); +% elseif pseudoinv +% cov = pinv(FMall,tol); +% else +% cov = FMall\eye(size(FMall)); +% end + + +% create AO +out = ao(plist('Xvals',freqs,'Yvals',d,'type','fsdata','fs',fs,'name','')); +% spectrum in the procinfo +if channel == 1 +out.setProcinfo(plist('S11',S11)); +elseif channel == 2 +out.setProcinfo(plist('S22',S22)); +end +% Fisher Matrix in the procinfo +out.setProcinfo(plist('FisMat',FisMat)); + +varargout{1} = out; +end + +end + + +%-------------------------------------------------------------------------- +% Get Info Object +%-------------------------------------------------------------------------- +function ii = getInfo(varargin) +if nargin == 1 && strcmpi(varargin{1}, 'None') + sets = {}; + pls = []; +else + sets = {'Default'}; + pls = getDefaultPlist; +end +% Build info object +ii = minfo(mfilename, 'ao', 'ltpda', utils.const.categories.sigproc, '$Id: dispersion.m,v 1.1 2011/06/22 09:54:19 miquel Exp $', sets, pls); +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.LPSD_PLIST; +pset(pl,'Navs',1) + +p = plist({'f1', 'Initial frequency for the analysis'}, paramValue.EMPTY_DOUBLE); +pl.append(p); + +p = plist({'f2', 'Final frequency for the analysis'}, paramValue.EMPTY_DOUBLE); +pl.append(p); + +p = plist({'FitParamas', 'Parameters of the model'}, paramValue.EMPTY_STRING); +pl.append(p); + +p = plist({'model','An array of matrix models'}, paramValue.EMPTY_STRING); +pl.append(p); + +p = plist({'noise','An array of matrices with the cross-spectrum matrices'}, paramValue.EMPTY_STRING); +pl.append(p); + +p = plist({'built-in','Symbolic models of the system as a string of built-in models'}, paramValue.EMPTY_STRING); +pl.append(p); + +p = plist({'frequencies','Array of start/sop frequencies where the analysis is performed'}, paramValue.EMPTY_STRING); +pl.append(p); + +p = plist({'pinv','Use the Penrose-Moore pseudoinverse'}, paramValue.TRUE_FALSE); +pl.append(p); + +p = plist({'tol','Tolerance for the Penrose-Moore pseudoinverse'}, paramValue.EMPTY_DOUBLE); +pl.append(p); + +p = plist({'diffStep','Numerical differentiation step for ssm models'}, paramValue.EMPTY_DOUBLE); +pl.append(p); + +end