Mercurial > hg > ltpda
diff m-toolbox/classes/@ao/consolidate.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/consolidate.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,251 @@ +% CONSOLIDATE resamples all input AOs onto the same time grid. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% CONSOLIDATE resamples all input AOs onto the same time grid and truncates all +% time-series to start at the maximum start time of the inputs and end +% at the minimum stop time of the inputs. +% +% ALGORITHM: +% 1) Drop duplicate samples (ao/dropduplicates) +% 2) Interpolate missing samples (ao/interpmissing) +% 3) Fix uneven sample rate using interpolate (ao/fixfs) +% 4) Resample to same fs, either max or specified (ao/resample +% or ao/interp depending on ratio of old and new sample +% rate) +% 5) Truncate all vectors to minimum overlap of time-series +% (ao/split) +% 6) Resample on to the same timing grid (ao/interp) +% 7) Truncate all vectors to same number of samples to correct for +% any rounding errors in previous steps (ao/select) +% +% CALL: >> bs = consolidate(as) +% +% INPUTS: as - array of at least two time-series analysis objects +% pl - parameter list (see below) +% +% OUTPUTS: bs - array of analysis objects, one for each input +% +% <a href="matlab:utils.helper.displayMethodInfo('ao', 'consolidate')">Parameters Description</a> +% +% VERSION: $Id: consolidate.m,v 1.32 2011/04/08 08:56:13 hewitson Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% 't' - specify a new time vector to resample on to. This +% will be truncated to fit within the maximum start +% time and minimum stop time of the inputs. +% or + +function varargout = consolidate(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 + [as, ao_invars] = utils.helper.collect_objects(varargin(:), 'ao', in_names); + [pl, pl_invars] = utils.helper.collect_objects(varargin(:), 'plist', in_names); + + if numel(as) < 2 + error('### Consolidate requires at least two time-series AOs to work.'); + end + + if nargout == 0 + error('### Consolidate cannot be used as a modifier. Please give an output variable.'); + end + + % Decide on a deep copy or a modify + bs = copy(as, nargout); + na = numel(bs); + + % Combine plists + pl = parse(pl, getDefaultPlist); + + % Get only tsdata AOs + inhists = []; + for j=1:na + if ~isa(bs(j).data, 'tsdata') + bs(j) = []; + warning('!!! Skipping AO %s - it''s not a time-series AO.', bs(j).name); + else + % gather the input history objects + inhists = [inhists bs(j).hist]; + end + end + + % If fs is specified, use it. Otherwise, use max of all + % input AOs. + fs = find(pl, 'fs'); + if isempty(fs) + % compute max fs + fs = 0; + for j=1:na + if bs(j).data.fs > fs + fs = bs(j).data.fs; + end + end + end + utils.helper.msg(msg.PROC2, 'resampling all time-series to an fs of %f', fs); + + %----------------- Drop all repeated samples + utils.helper.msg(msg.PROC1, 'drop duplicates'); + for j=1:na + utils.helper.msg(msg.PROC2, 'processing %s', bs(j).name); + dropduplicates(bs(j),pl); + end + + %----------------- Interpolate all missing samples + utils.helper.msg(msg.PROC1, 'interpolate missing samples'); + for j=1:na + utils.helper.msg(msg.PROC2, 'processing %s', bs(j).name); + interpmissing(bs(j),pl.pset('method', find(pl, 'interp_method'))); + end + + + %----------------- Fix uneven sampling + utils.helper.msg(msg.PROC1, 'fixing uneven sample rates'); + for j=1:na + utils.helper.msg(msg.PROC2, 'processing %s', bs(j).name); + fixfs(bs(j),pl.pset('method', find(pl, 'fixfs_method'))); + end + %----------------- Resample all vectors to same fs + utils.helper.msg(msg.PROC1, 'resample to same fs'); + + for j=1:na + % Check the resampling factor + [P,Q] = utils.math.intfact(fs,bs(j).data.fs); + if P > 100 || Q > 100 + utils.helper.msg(msg.PROC2, 'resampling factor too high [%g/%g]. Trying interpolation', P, Q); + N = length(bs(j).data.getX); + t = linspace(0, (P*N/Q-1)/fs, P*N/Q); + interp(bs(j), plist('vertices', t)); + else + resample(bs(j), plist('fsout', fs)); + end + end + + %---------------- Time properties of AOs + % Find max start time + start = 0; + for j=1:na + dstart = bs(j).data.t0.utc_epoch_milli/1000 + bs(j).data.getX(1); + if dstart > start + start = dstart; + end + end + + % Find min stop time + stop = 1e20; + for j=1:na + dstop = floor(bs(j).data.t0.utc_epoch_milli/1000 + bs(j).data.getX(end)); + if dstop < stop + stop = dstop; + end + end + + %----------------- Truncate all vectors + utils.helper.msg(msg.PROC1, 'truncate all vectors'); + utils.helper.msg(msg.PROC2, 'truncating vectors on interval [%.4f,%.4f]', start, stop); + + % split each ao + bs = split(bs, plist('timespan', timespan(start, stop))); + + %----------------- Resample all vectors on to the same grid + utils.helper.msg(msg.PROC1, 'resample to same grid'); + % compute new time grid + + % get the grid from the first AO + for j=1:na + toff = start - bs(j).t0.utc_epoch_milli/1000; + N = length(bs(j).data.getX); + t = linspace(toff, toff+(N-1)/fs, N); + interp(bs(j), plist('vertices', t)); + end + + % Now ensure that we have the same data length + ns = realmax; + for jj=1:na + if len(bs(jj)) < ns + ns = len(bs(jj)); + end + end + + bs = select(bs, 1:ns); + + nsecs = []; + for j=1:na + if isempty(nsecs) + nsecs = bs(j).data.nsecs; + end + if nsecs ~= bs(j).data.nsecs + error('### Something went wrong with the truncation. Vectors don''t span the same time period.'); + end + end + + %----------------- Set history on output AOs + + for j=1:na + bs(j).name = sprintf('%s(%s)', mfilename, ao_invars{j}); + bs(j).addHistory(getInfo('None'), pl, ao_invars(j), inhists(j)); + end + + % Set output + if nargout == numel(bs) + % List of outputs + for ii = 1:numel(bs) + varargout{ii} = bs(ii); + end + else + % Single output + varargout{1} = bs; + 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: consolidate.m,v 1.32 2011/04/08 08:56:13 hewitson Exp $', sets, pl); + ii.setModifier(false); + ii.setArgsmin(2); +end + +%-------------------------------------------------------------------------- +% Get Default Plist +%-------------------------------------------------------------------------- + +function plout = getDefaultPlist() + persistent pl; + if exist('pl', 'var')==0 || isempty(pl) + pl = buildplist(); + end + plout = pl; +end + +function pl_default = buildplist() + pl_default = combine(... + plist({'fs','The target sampling frequency for consolidate'}, paramValue.EMPTY_DOUBLE),... + plist({'interp_method', 'The method for the interpolation step'}, {2, {'nearest', 'linear', 'spline', 'cubic'}, paramValue.SINGLE}), ... + plist({'fixfs_method', 'The method for the fixfs step'}, {1, {'Time', 'Samples'}, paramValue.SINGLE}), ... + ao.getInfo('dropduplicates').plists,... + ao.getInfo('interpmissing').plists,... + ao.getInfo('fixfs').plists); +end +