Mercurial > hg > ltpda
diff m-toolbox/classes/@ao/xspec.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children | bc767aaa99a8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m-toolbox/classes/@ao/xspec.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,197 @@ +% XSPEC performs cross-spectral analysis of various forms. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: XSPEC performs cross-spectral analysis of various forms. +% The function is a helper function for various higher level +% functions. It is meant to be called from other functions +% (e.g., tfe). +% +% CALL: b = xspec(a, pl, method, iALGO, iVER, invars); +% +% INPUTS: a - vector of 2 input AOs +% pl - input parameter list +% method - one of +% 'cpsd' - compute cross-spectral density +% 'tfe' - estimate transfer function between inputs +% 'mscohere' - estimate magnitude-squared cross-coherence +% 'cohere' - estimate complex cross-coherence +% iALGO - ALGONAME from the calling higher level script +% iVER - VERSION from the calling higher level script +% invars - invars variable from the calling higher level script +% +% OUTPUTS: b - output AO +% +% VERSION: $Id: xspec.m,v 1.61 2011/05/22 22:09:44 mauro Exp $ +% +% HISTORY: 30-05-2007 M Hewitson +% Creation +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function varargout = xspec(varargin) + + import utils.const.* + + % unpack inputs + as = varargin{1}; + pl = varargin{2}; + method = varargin{3}; + mi = varargin{4}; + invars = varargin{5}; + + VERSION = '$Id: xspec.m,v 1.61 2011/05/22 22:09:44 mauro Exp $'; + + % Set the method version string in the minfo object + mi.setMversion([VERSION '-->' mi.mversion]); + + %----------------- Select all AOs with time-series data + tsao = []; + for ll = 1:numel(as) + if isa(as(ll).data, 'tsdata') + tsao = [tsao as(ll)]; + else + warning('### xspec requires tsdata (time-series) inputs. Skipping AO %s. \nREMARK: The output doesn''t contain this AO', invars{ll}); + end + end + if numel(tsao) ~= 2 + error('### XSPEC needs two time-series AOs.'); + end + + %----------------- Gather the input history objects + inhists = [tsao(:).hist]; + + %----------------- Check the time range + time_range = mfind(pl, 'split', 'times'); + for ll = 1:numel(tsao) + if ~isempty(time_range) + switch class(time_range) + case 'double' + tsao(ll) = split(tsao(ll), plist(... + 'times', time_range)); + case 'timespan' + tsao(ll) = split(tsao(ll), plist(... + 'timespan', time_range)); + case 'time' + tsao(ll) = split(tsao(ll), plist(... + 'start_time', time_range(1), ... + 'end_time', time_range(2))); + case 'cell' + tsao(ll) = split(tsao(ll), plist(... + 'start_time', time_range{1}, ... + 'end_time', time_range{2})); + otherwise + end + end + if tsao(ll).len <= 0 + error('### The object is empty! Please revise your settings ...'); + end + end + + %----------------- Resample all AOs + copies = zeros(size(tsao)); + + fsmin = ao.findFsMin(tsao); + fspl = plist(param('fsout', fsmin)); + for ll = 1:numel(tsao) + % Check Fs + if tsao(ll).data.fs ~= fsmin + utils.helper.msg(msg.PROC1, 'resampling AO %s to %f Hz', tsao(ll).name, fsmin); + % Make a deep copy so we don't + % affect the original input data + tsao(ll) = copy(tsao(ll), 1); + copies(ll) = 1; + resample(tsao(ll), fspl); + end + end + + %----------------- Truncate all vectors + + % Get shortest vector + lmin = ao.findShortestVector(tsao); + nsecs = lmin / fsmin; + for ll = 1:numel(tsao) + if len(tsao(ll)) ~= lmin + utils.helper.msg(msg.PROC2, 'truncating AO %s to %d secs', tsao(ll).name, nsecs); + % do we already have a copy? + if ~copies(ll) + % Make a deep copy so we don't + % affect the original input data + tsao(ll) = copy(tsao(ll), 1); + copies(ll) = 1; + end + tsao(ll).select(1:lmin); + end + end + + %----------------- check input parameters + + usepl = utils.helper.process_spectral_options(pl, 'lin', lmin, fsmin); + + % Loop over input AOs + utils.helper.msg(msg.PROC1, 'computing %s(%s -> %s)', method, invars{1}, invars{2}); + + % -------- Make Xspec estimate + + % Compute xspec using welch and always scale to PSD + [txy, f, info, dev] = welch(tsao(1), tsao(2), method, usepl.pset('Scale', 'PSD')); + + % Keep the data shape of the first input AO + if size(tsao(1).data.y,1) == 1 + txy = txy.'; + f = f.'; + dev = dev.'; + end + + % create new output fsdata + fsd = fsdata(f, txy, fsmin); + fsd.setEnbw(info.enbw); + fsd.setXunits('Hz'); + + switch lower(method) + case 'tfe' + fsd.setYunits(tsao(2).data.yunits / tsao(1).data.yunits); + case 'cpsd' + fsd.setYunits(tsao(2).data.yunits * tsao(1).data.yunits / unit('Hz')); + case {'mscohere','cohere'} + fsd.setYunits(unit()); + otherwise + error(['### Unknown method:' method]); + end + fsd.setNavs(info.navs); + + % set object t0 + if eq(tsao(1).t0, tsao(2).t0) + fsd.setT0(tsao(1).t0); + end + + % make output analysis object + bs = ao(fsd); + % add variance + bs.data.dy = dev; + + % simplify the units in the case of cpsd calculation + if strcmp(method, 'cpsd') + bs.simplifyYunits(... + plist('prefixes', false, 'exceptions', 'Hz')); + end + + %----------- Add history + + % set name + bs.name = sprintf('%s(%s->%s)', upper(method), invars{1}, invars{2}); + + % we need to get the input histories in the same order tsao the inputs + % to this function call, not in the order of the input to xspec; + % otherwise the resulting matrix on a 'create from history' will be + % mirrored. + bs.addHistory(mi, usepl, [invars(:)], inhists); + + % Propagate 'plotinfo' + if ~isempty(tsao(1).plotinfo) || ~isempty(tsao(2).plotinfo) + bs.plotinfo = combine(tsao(1).plotinfo, tsao(2).plotinfo); + end + + % Set output + varargout{1} = bs; +end +