Mercurial > hg > ltpda
diff m-toolbox/classes/@ao/getdof.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/getdof.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,402 @@ +% GETDOF Calculates degrees of freedom for psd, lpsd, cohere and lcohere +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: GETDOF Input psd or mscohere (magnitude square coherence) +% estimated with the WOSA (Welch's Overlapped Segment Averaging Method) and +% return degrees of freedom of the estimator. +% +% CALL: dof = getdof(a,pl) +% +% INPUTS: +% a - input analysis objects containing power spectral +% densities or magnitude squared coherence. +% pl - input parameter list +% +% OUTPUTS: +% dof - cdata AO with degrees of freedom for the +% corresponding estimator. If the estimators are lpsd +% or lcohere then dof number of elements is the same of +% the spectral estimator +% +% +% If the last input argument is a parameter list (plist). +% The following parameters are recognised. +% +% +% +% <a href="matlab:utils.helper.displayMethodInfo('ao', 'getdof')">Parameters Description</a> +% +% VERSION: $Id: getdof.m,v 1.19 2011/05/23 20:36:47 mauro Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function varargout = getdof(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 + [as, ao_invars] = utils.helper.collect_objects(varargin(:), 'ao', in_names); + pl = utils.helper.collect_objects(varargin(:), 'plist', in_names); + + %%% avoid multiple AO at input + if numel(as) > 1 + error('!!! Too many input AOs, GETDOF can process only one AO per time !!!') + end + + %%% check that fsdata is input + if ~isa(as.data, 'fsdata') + error('!!! Non-fsdata input, GETDOF can process only fsdata !!!') + end + + %%% avoid input modification + if nargout == 0 + error('!!! GETDOF cannot be used as a modifier. Please give an output variable !!!'); + end + + %%% Parse plists + pl = parse(pl, getDefaultPlist()); + + %%% Find parameters + mtd = lower(find(pl, 'method')); + if ~ischar(mtd) + error('!!! Method must be a string !!!') + end + mtd = lower(mtd); + + Ntot = find(pl,'DataLength'); + + %%% switching over methods + switch mtd + case 'psd' + % get hist + hst = as.hist; + % get nodes + [n,a, nodes] = getNodes(hst); + % get plists from nodes + pls = [nodes(:).pl]; + if numel(pls) > 1 + plss = pls(1); + for ii = 2:numel(pls)-1 + plss = parse(plss, pls(ii)); + end + end + % get number of averages + navs = as.data.navs; + % get window object + w = find(plss, 'WIN'); + % percentage of overlap + olap = find(plss, 'OLAP')./100; + % number of bins in each fft + nfft = find(plss, 'NFFT'); + psll = find(plss, 'psll'); + + % Normalize window data in order to be square integrable to 1 + if ischar(w) + switch lower(w) + case 'kaiser' + Win = specwin(w, nfft, psll); + otherwise + Win = specwin(w, nfft); + end + else + Win = w; + end + win = Win.win ./ sqrt(Win.ws2); + + % Calculates total number of data in the original time-series + if isempty(Ntot) + Ntot = ceil(navs*(nfft-olap*nfft)+olap*nfft); + end + + if navs == 1 + dofs = round(2*navs); + else + [R,n] = utils.math.overlapCorr(win,Ntot,navs); + dof = 2*navs/(2*R*navs+1); + dofs = round(dof); + end + + case 'lpsd' + % get hist + hst = as.hist; + % get nodes + [n,a, nodes] = getNodes(hst); + % get plists from nodes + pls = [nodes(:).pl]; + if numel(pls) > 1 + plss = pls(1); + for ii = 2:numel(pls)-1 + plss = parse(plss, pls(ii)); + end + end + % get window used + uwin = find(plss, 'WIN'); + + % extract number of frequencies bins + nf = length(as.x); + + % dft length for each bin + if ~isempty(as.procinfo) + L = as.procinfo.find('L'); + else + error('### The AO doesn''t have any procinfo with the key ''L'''); + end + + % set original data length as the length of the first window + if isempty(Ntot) + nx = L(1); + else + nx = Ntot; + end + + % windows overlap + olap = find(plss, 'OLAP')./100; + psll = find(plss, 'psll'); + + dofs = ones(nf,1); + for jj = 1:nf + l = L(jj); + % compute window + if ischar(uwin) + switch lower(uwin) + case 'kaiser' + w = specwin(uwin, l, psll); + otherwise + w = specwin(uwin, l); + end + else + w = uwin; + end + % Normalize window data in order to be square integrable to 1 + owin = w.win; + owin = owin./sqrt(w.ws2); + + % Compute the number of averages we want here + segLen = l; + nData = nx; + ovfact = 1 / (1 - olap); + davg = (((nData - segLen)) * ovfact) / segLen + 1; + navg = round(davg); + + if navg == 1 + dof = 2*navg; + else + [R,n] = utils.math.overlapCorr(owin,nx,navg); + dof = 2*navg/(2*R*navg+1); + end + + % storing c and dof + dofs(jj) = dof; + + end % for jj=1:nf + + case 'mscohere' + % get hist + hst = as.hist; + % get nodes + [n,a, nodes] = getNodes(hst); + % get plists from nodes + pls = [nodes(:).pl]; + if numel(pls) > 1 + plss = pls(1); + for ii = 2:numel(pls)-1 + plss = parse(plss, pls(ii)); + end + end + % get number of averages + navs = as.data.navs; + % get window object + w = find(plss,'WIN'); + % percentage of overlap + olap = find(plss,'OLAP')./100; + % number of bins in each fft + nfft = find(plss,'NFFT'); + psll = find(plss, 'psll'); + + % Normalize window data in order to be square integrable to 1 + if ischar(w) + switch lower(w) + case 'kaiser' + Win = specwin(w, nfft, psll); + otherwise + Win = specwin(w, nfft); + end + else + Win = w; + end + win = Win.win ./ sqrt(Win.ws2); + + % Calculates total number of data in the original time-series + if isempty(Ntot) + Ntot = ceil(navs*(nfft-olap*nfft)+olap*nfft); + end + + if navs == 1 + dofs = round(2*navs); + else + [R,n] = utils.math.overlapCorr(win,Ntot,navs); + dof = 2*navs/(2*R*navs+1); + dofs = round(dof); + end + + case 'mslcohere' + % get hist + hst = as.hist; + % get nodes + [n,a, nodes] = getNodes(hst); + % get plists from nodes + pls = [nodes(:).pl]; + if numel(pls) > 1 + plss = pls(1); + for ii = 2:numel(pls)-1 + plss = parse(plss, pls(ii)); + end + end + % get window used + uwin = find(plss,'WIN'); + + % extract number of frequencies bins + nf = length(as.x); + + % dft length for each bin + if ~isempty(as.procinfo) + L = as.procinfo.find('L'); + else + error('### The AO doesn''t have any procinfo with the key ''L'''); + end + + % set original data length as the length of the first window + if isempty(Ntot) + nx = L(1); + else + nx = Ntot; + end + + % windows overlap + olap = find(plss, 'OLAP')./100; + psll = find(plss, 'psll'); + + dofs = ones(nf, 1); + for jj = 1:nf + l = L(jj); + % compute window + if ischar(uwin) + switch lower(uwin) + case 'kaiser' + w = specwin(uwin, l, psll); + otherwise + w = specwin(uwin, l); + end + else + w = uwin; + end + % Normalize window data in order to be square integrable to 1 + owin = w.win ./ sqrt(w.ws2); + + % Compute the number of averages we want here + segLen = l; + nData = nx; + ovfact = 1 / (1 - olap); + davg = (((nData - segLen)) * ovfact) / segLen + 1; + navg = round(davg); + + if navg == 1 + dof = 2*navg; + else + [R,n] = utils.math.overlapCorr(owin,nx,navg); + dof = 2*navg/(2*R*navg+1); + end + + % storing c and dof + dofs(jj) = dof; + + end % for jj=1:nf + + end %switch mtd + + % Output data + + % dof + ddof = cdata(); + ddof.setY(dofs); + odof = ao(ddof); + % Set output AO name + odof.name = sprintf('dof(%s)', ao_invars{:}); + % Add history + odof.addHistory(getInfo('None'), pl, [ao_invars(:)], [as.hist]); + + % output + if nargout == 1 + varargout{1} = odof; + else + error('!!! getdof can have only one output') + 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: getdof.m,v 1.19 2011/05/23 20:36:47 mauro Exp $', sets, pl); + ii.setModifier(false); + ii.setOutmin(1); + ii.setOutmax(1); +end + +%-------------------------------------------------------------------------- +% Get Default Plist +%-------------------------------------------------------------------------- +function plout = getDefaultPlist() + persistent pl; + if ~exist('pl', 'var') || isempty(pl) + pl = buildplist(); + end + plout = pl; +end + +function pl = buildplist() + + pl = plist(); + + p = param({'method', ['Set the desired method. Supported values are<ul>'... + '<li>''psd'' power spectrum calculated with ao/psd, whatever the scale</li>'... + '<li>''lpsd'' power spectrum calculated with ao/lpsd, whatever the scale</li>'... + '<li>''mscohere'' magnitude square coherence spectrum calculated with ao/cohere</li>'... + '<li>''mslcohere'' magnitude square coherence spectrum calculated with ao/lcohere</li>']}, ... + {1, {'psd', 'lpsd', 'mscohere', 'mslcohere'}, paramValue.OPTIONAL}); + pl.append(p); + + p = param({'DataLength',['Data length of the time series.'... + 'It is better to input for more stable calculation.'... + 'Leave it empty if you do not know its value.']},... + paramValue.EMPTY_DOUBLE); + pl.append(p); + + +end + + + +% END + +