Mercurial > hg > ltpda
diff m-toolbox/classes/@ao/gapfillingoptim.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/gapfillingoptim.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,552 @@ +% GAPFILLINGOPTIM fills possible gaps in data. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: GAPFILLINGOPTIM minimizes a chi square based on the signal's +% expected PSD. It uses ao/optSubtraction for the small scale +% algorithm, optSubstitution for the large scale algorithm. +% +% CALL: [aoGapsFilled, plOut, aoP, aoPini, aoWindow, aoWindowShift] = ao.gapfilling(plist) +% +% INPUTS: ao_data - data segment with the signal to reconstitue +% pl - parameter list +% +% OUTPUTS: aoGapsFilled - data segment containing ao_data, with filled data gaps +% plOut - output plist containing the output of +% gapFillingOptim +% aoP, aoPini - final and initial frequency PSD used to weight +% the optimal problem +% aoWindow - window used for estmating spectrum +% aoWindowShift - shifted window used for optimizing spectrum +% +% <a href="matlab:utils.helper.displayMethodInfo('ao', 'gapfillingoptim')">Parameters Description</a> +% +% VERSION: $Id: gapfillingoptim.m,v 1.27 2011/06/11 14:11:27 adrien Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function varargout = gapfillingoptim(varargin) + % y ycalib fs isgap iscalib freq_weight ncalib ndata nfft ngaps + %%% Check if this is a call for parameters + if utils.helper.isinfocall(varargin{:}) + varargout{1} = getInfo(varargin{3}); + return + end + + %% Collect input variable names + in_names = cell(size(varargin)); + for ii = 1:nargin,in_names{ii} = inputname(ii);end + + % Collect all AOs + [aos, ao_invars] = utils.helper.collect_objects(varargin(:), 'ao', in_names); + pli = utils.helper.collect_objects(varargin(:), 'plist', in_names); + + % Get default parameters + pl = combine(pli, getDefaultPlist); + + %% declaring global optData variable + clear global optData + global optData + + %% getting time-series to fill, and usefull data (frequencies, number of frequencies... ) + if numel(aos)==0 + error('Nothing to fill gaps!') + elseif numel(aos)>1 + error('The filling algorithm only works for one single signal at a time') + end + optData.nData = numel(aos.y); + optData.yNorm = norm(aos.y) / optData.nData; + optData.y = aos.y / optData.yNorm; + optData.Ts = 1/aos(1).fs; + optData.nFreqs = floor(optData.nData/2)+1; + optData.freqs = linspace(0, 1/(2*optData.Ts), optData.nFreqs); + optData.keepFreqs = [true(1,sum(optData.nFreqs)) false(1,sum(optData.nFreqs)-1)]; + + %% finding gaps + aoGaps = pl.find('isgap'); + if isempty(aoGaps) + error('no gap vector provided!') + elseif isequal(aoGaps,'zeros') + optData.isGap = (aos.y==0); + elseif numel(isempty(aoGaps))>1 + error('please provide only one gap vector!') + elseif isa(aoGaps.y, 'double') + optData.isGap = (aoGaps.y==0); + elseif isa(aoGaps.y, 'logical') + optData.isGap = aoGaps.y; + else + error('wrong type for parameter "isGap"') + end + optData.gapsPos = find(optData.isGap); + optData.nGaps = numel(optData.gapsPos); + clear aoGaps + + %% checking number of gaps is not zero + if numel(optData.gapsPos)==0 + error('No gap to fill!') + end + if numel(optData.isGap) ~= optData.nData + error('gap vector is not the same length as the gapped vector!') + end + + %% produce LF window + Win = find(pl, 'Win'); + if isa(Win, 'plist') + Win = ao( combine(plist( 'length', optData.nData), Win) ); + optData.lfWin = Win.y; + elseif isa(Win, 'ao') + if ~isa(Win.data, 'tsdata') + error('An ao window should be a time series') + end + optData.lfWin = Win.y; + if ~length(optData.lfWin)==optData.nData + error('signals and windows don''t have the same length') + end + else + error('input option Win is not acceptable (not a plist nor an ao)!') + end + + %% produce HF window + [shiftVals, shiftCounts, winHF, winsHfShift] = makeHFWindows(optData.nData, optData.gapsPos); + optData.nShifts = numel(shiftVals); + optData.shiftVals = shiftVals; + optData.shiftCounts = shiftCounts; + optData.hfWin = winHF; + optData.win = optData.lfWin .* optData.hfWin; + optData.winsHfShift = winsHfShift; + optData.winsShift = winsHfShift; + for iiShift = 1:(2*optData.nShifts) + optData.winsShift(:, iiShift) = optData.winsHfShift(:, iiShift) .* optData.lfWin; + end + clear shiftVals shiftCounts winHF winsHfShift + + %% get initial M coefficient matrix + M = pl.find('coefs'); + if isempty(M) + M = zeros(1,optData.nGaps); + end + + %% detrending (with a windowing agains HF noise) + trends = [ones(optData.nData,1) linspace(-1,1,optData.nData).' ]; % two orthogonal vectors to subtract + trendsWindowed = trends .* [optData.win optData.win]; % windowing is applied to estimate trends + yWindowed = optData.y .* optData.win; % windowing is applied to de-trened data to be consistent + optData.trend = pinv(trendsWindowed) * yWindowed; % solution of the least-square problem + trendCorrection = trends * optData.trend; % trend is removed from the data while filling gaps. It is re-added later on. + optData.y = optData.y - trendCorrection; % detrended vector + optData.y(optData.gapsPos) = zeros(size(optData.gapsPos)); % setting to zero the gap-data + + %% get sPSD averaging linear-scaling averaging-width coefficient + optData.linCoef = pl.find('linCoef'); + optData.logCoef = pl.find('logCoef'); + + %% get MAX/EXP iterations termination conditions + iterMax = pl.find('iterMax'); + optData.criterion = pl.find('fitCriterion'); + normCriterion = pl.find('normCriterion'); + normCoefs = pl.find('normCoefs'); + + %% set optim CVG options + options.MaxFunEvals = pl.find('maxCall'); + options.Display = pl.find('display'); + options.TolFun = min( pl.find('normCriterion'), 1e-12 ); + options.TolX = min( pl.find('normCoefs'), 1e-14 ); + options.MaxIter = pl.find('maxCall'); + doHessian = pl.find('Hessian'); + if ~isempty(doHessian) + error('Hessian option is now deactivated as it is too demanding computationaly') + end + + %% computing various useful quantities used for the criterion computation + weightingMethod =pl.find('weightingMethod'); + switch weightingMethod + case 'pzmodel' + weightModel = pl.find('pzmodelWeight'); + if numel(weightModel) ~= 1 + error('there should be only one pzmodel') + end + weight = weightModel.resp(optData.freqs); + weight = abs(weight).^2; + Ploc = weight.y; + [freqsAvg, pAvg, nFreqsAvg, nDofs, sumMat] = ltpda_spsd(optData.freqs, Ploc, optData.linCoef, optData.logCoef); %#ok<ASGLU> + case 'ao' + weight =pl.find('aoWeight'); + if numel(weight)~=1 + error('there should be as many pzmodels as weighted entries') + end + if ~isa(weight.data, 'tsdata') + error('if the weight is an ao, it should be a FSdata') + elseif length(weight.y)==optData.nFreqs + error(['length of FS weight is not length of the FFT vector : ' num2str(length(weight.y)) 'instead of ' num2str(optData.nFreqs)]) + else + Ploc = weight.y; + [freqsAvg, pAvg, nFreqsAvg, nDofs, sumMat] = ltpda_spsd(optData.freqs, Ploc, optData.linCoef, optData.logCoef); %#ok<ASGLU> + end + case 'residual' + [pAvg, freqsAvg, powSigma, sumMat, nFreqsAvg ] = computeWeight( optData.y, M, optData.gapsPos, optData.freqs); + otherwise + error('weighting method requested does not exist!') + end + + %% Maximization Expectation iteration loop + for i_iter = 1:iterMax + utils.helper.msg(utils.const.msg.PROC3, ['starting iteration ', num2str(i_iter)]); + + %% setting weight in optData + optData.sumMat = sumMat; + optData.nFreqsAvg = nFreqsAvg; + optData.powInv = pAvg.^-1; + optData.logProbaDensityFactor = - nFreqsAvg * log(2) - gammaln(nFreqsAvg); + + %% initializing historical outputs + if i_iter==1 % storing intial weight + Pini = pAvg; + MHist(1,:) = reshape(M, [1, numel(M)] ); + end + fValIni = optimalCriterion(M); + + %% minimizing the criterion + switch lower(optData.criterion) + case 'ftest' + M = solveProblemFTest( optData.gapsPos, optData.powInv, optData.nFreqsAvg); % very fast direct solver in this case + fval = optimalCriterion(M); + case 'ftest-nohfwin' + M = solveProblemFTestNoHFWin( optData.gapsPos, optData.powInv, optData.nFreqsAvg); % very fast direct solver in this case + fval = optimalCriterion(M); + otherwise + M = solveProblemFTest( optData.gapsPos, optData.powInv, optData.nFreqsAvg); % initialize with fast solver (with the wrong criterion, but it doesn't matter so much) + [M, fval] = fminunc(@optimalCriterion,M,options); % further non-linear minimzation steps with correct criterion + end + + %% updating weight + [pAvg, freqsAvg] = computeWeight(optData.y, M, optData.gapsPos, optData.freqs); + + %% store history + fValHist(i_iter) = fval/fValIni; %#ok<AGROW> + MHist(i_iter+1,:) = reshape(M, [1, numel(M)] ); %#ok<AGROW> + + %% deciding whether to pursue or not ME (=bootstrap) iterations + if strcmpi( weightingMethod, 'pzmodel') + display('One iteration for Pzmodel weighting only') + break + elseif strcmpi( weightingMethod, 'ao') + display('One iteration for ao weighting only') + break + elseif norm(fValHist(i_iter)-1) < normCriterion + display(['Iterations stopped at iteration ' num2str(i_iter) ' because criterion did not make enough progress (see parameter "normCriterion")']) + break + elseif i_iter == iterMax + display(['Iterations stopped at maximum number of iterations ' num2str(i_iter) ' (see parameter "iterMax")']) + break + elseif norm(MHist(i_iter+1,:)-MHist(i_iter,:))<normCoefs + display(['Iterations stopped at iteration ' num2str(i_iter) ' because parameters did not make enough progress (see parameter "normCoefs")']) + break + end + end % ending loop over MAX/EXP iterations + + %% creating output plist + plOut = plist; + p = param({ 'criterion' , 'last value of the criterion in the last optimization'}, fval ); + plOut.append(p); + p = param({ 'M' , 'Best fitting value'}, (M + trendCorrection(optData.gapsPos).') * optData.yNorm ); + plOut.append(p); + + %% creating output aos for weights + aoP = ao( fsdata(freqsAvg, pAvg * (optData.yNorm^2 * optData.Ts / optData.nData) ) ); + aoP.setName('final weight'); + aoP.setXunits('Hz'); + aoP.setYunits(aos.yunits^2 * unit('Hz^-1')); + aoP.setDescription(['final weight for gap-filling after ' num2str(i_iter) ' iterations (identical to )']); + aoP.setT0(aos.t0); + + aoPini = ao( fsdata(freqsAvg, Pini * (optData.yNorm^2 * optData.Ts / optData.nData) ) ); + aoPini.setName('initial weight'); + aoPini.setXunits('Hz'); + aoPini.setYunits(aos.yunits^2 * unit('Hz^-1')); + aoPini.setDescription(['initial weight for gap-filling']); + aoPini.setT0(aos.t0); + + %% creating filled output + aoGapsFilled = ao( plist('yvals', ( trendCorrection + substitution( optData.y, M, optData.gapsPos)) * optData.yNorm, 'fs', 1/optData.Ts, 'type', 'tsdata' )); + aoGapsFilled.setName('filled time-series'); + aoGapsFilled.setXunits('s'); + aoGapsFilled.setYunits(aos.yunits); + aoGapsFilled.setDescription(['Filled time-series using the criteiron: ' optData.criterion ]); + aoGapsFilled.setT0(aos.t0); + aoGapsFilled.addHistory( getInfo('None'), pl , ao_invars, aos.hist ); + + %% creating output windows + aoWindow = ao( plist('yvals', optData.win, 'fs', 1/optData.Ts, 'type', 'tsdata' )); + aoWindow.setName('initial window used to evaluate the spectrum'); + aoWindow.setXunits('s'); + aoWindow.setT0(aos.t0); + aoWindow.addHistory( getInfo('None'), pl , ao_invars, aos.hist ); + + if strcmpi(optData.criterion,'FTest-NoHfWin') + aoWindowShift = ao( plist('yvals', optData.lfWin, 'fs', 1/optData.Ts, 'type', 'tsdata' )); + else + aoWindowShift = ao( plist('yvals', optData.winsShift(:, 1) , 'fs', 1/optData.Ts, 'type', 'tsdata' )); + end + aoWindowShift.setName('window used to optimize the spectrum'); + aoWindowShift.setXunits('s'); + aoWindowShift.setDescription(['one of the ' num2str(optData.nShifts) ' windows involved in the criterion']); + aoWindowShift.setT0(aos.t0); + aoWindowShift.addHistory( getInfo('None'), pl , ao_invars, aos.hist ); + + %% assigning output + varargout = {aoGapsFilled, plOut, aoP, aoPini, aoWindow, aoWindowShift}; + + %% clearing optData from global workspace + clear global optData + +end + +%% usefull function to compute the weights from the residual +function [powAvgs, freqsAvg, powStd, sumMat, nFreqsAvg] = computeWeight(Y, M, gapsPos, freqs) + global optData + yFilled = substitution( Y, M, gapsPos); + if strcmpi(optData.criterion,'FTest-NoHfWin') + win = optData.lfWin; + else + win = optData.win; + end + errDft = fft( yFilled .* win, optData.nData); + errDft = errDft(optData.keepFreqs); % removing aliased frequencies + pow = imag(errDft).^2 + real(errDft).^2; % power + + [freqsAvg, powAvgs, nFreqsAvg, nDofs, sumMat] = ltpda_spsd(freqs, pow, optData.linCoef, optData.logCoef); + powStd = powAvgs./sqrt(nDofs); +end + +%% optimal criterion +function j = optimalCriterion(M) + global optData + j = 0; + yFilled = substitution(optData.y, M, optData.gapsPos); + if strcmpi(optData.criterion, 'FTest-NoHfWin') + errDft = fft( yFilled .* optData.lfWin, optData.nData); % FFT algirthm gets DFT, only a LF window is used here + errDft = errDft(optData.keepFreqs); % keeping positive frequencies + pow = imag(errDft).^2 + real(errDft).^2; % PSD of signal + powSum = optData.sumMat * pow; % binning frequencies as in sPSD + j = sum( powSum .* optData.powInv ); % summing FTest + elseif strcmpi(optData.criterion, 'FTest') + for iiWin=1:numel(optData.nShifts) + for iiDirection = [0 1] % positive/negative window shift + errDft = fft( yFilled .* optData.winsShift(:, 2*iiWin-1+iiDirection), optData.nData); % FFT algirthm gets DFT + errDft = errDft(optData.keepFreqs); % keeping positive frequencies + pow = imag(errDft).^2 + real(errDft).^2; % PSD of signal + powSum = optData.sumMat * pow; % binning frequencies as in sPSD + j = j + sum( powSum .* optData.powInv ) * optData.shiftCounts(iiWin); + end + end + elseif strcmpi(optData.criterion, 'Chi2') + for iiWin=1:numel(optData.nShifts) + for iiDirection = [0 1] % positive/negative window shift + errDft = fft( yFilled .* optData.winsShift(:, 2*iiWin-1+iiDirection), optData.nData); % FFT algirthm gets DFT + errDft = errDft(optData.keepFreqs); % keeping positive frequencies + pow = imag(errDft).^2 + real(errDft).^2; % PSD of signal + powSum = optData.sumMat * pow; % binning frequencies as in sPSD + normlzChi2Sum = (2*powSum) .* optData.powInv; % divide the sum by the expected average of each terms, so the chi2 is normalized + logProbaDensities = optData.logProbaDensityFactor + (optData.nFreqsAvg-1).*log(normlzChi2Sum) - normlzChi2Sum/2 ; % here computing log of probability + j = j - sum(logProbaDensities); % better than taking product of probabilities + end + end + else + error(['criterion badly specified' optData.criterion]) + end +end + +%% function subtituting gaps in time-series +function Y = substitution( Y, M, gapsPos) + Y(gapsPos) = M; +end + +%% Direct solver for "FTest" quadratic criterion +function [M, hessian] = solveProblemFTest( gapsPos, powAvgInv, nFreqsAvg) + global optData + computeDuration = 1.3e-8 * 2 * optData.nShifts * numel(gapsPos)^2 * sum(nFreqsAvg); + display(['expected time for linear solver: ' num2str(computeDuration) 's']) + gapsPhase = exp( -1i*2*pi * (gapsPos-1)/numel(optData.y) ); % FFT value of a gap sample at base frequency + nGaps = numel(gapsPos); % number of gaps + nAvgs = numel(nFreqsAvg); % number of frequency bins + B = zeros(nGaps,1); + A = zeros(nGaps,nGaps); + %% frequency weighted criterion + for iiWin=1:numel(optData.nShifts) % loop on different shifts for HF window + for iiDirection = [0 1] % positive/negative window shift + W = optData.winsShift(:, 2*iiWin-1+iiDirection); + errDft = fft( optData.y .* W, optData.nData); % FFT algirthm gets DFT + errDft = errDft(optData.keepFreqs); % keeping positive frequencies + gapsAmplitude = W(gapsPos); % amplitude of gaps once windowed + gapsPhaseAtFreq = gapsPhase.^0; % FTF at fundamental : it is only the mean value + iiFreq = 0; % frequency (before averaging with binning) + for iiFreqAvg = 1:nAvgs % loop on frequency bins + BLocal = zeros(nGaps,1); + ALocal = zeros(nGaps,nGaps); + for iiFreqInAvg = 1:nFreqsAvg(iiFreqAvg) % loop on frequencies inside frequency bin + iiFreq = iiFreq + 1; % current frequency index (starting with 1!) + gapDFT = reshape( gapsAmplitude .* gapsPhaseAtFreq , [nGaps,1]); % DFT of each windowed gap data at the frequency number iiFreq-1 + % gapDFT = reshape( gapsAmplitude .* gapsPhase.^(iiFreq-1) , [nGaps,1]); % DFT of each windowed gap data at the frequency number iiFreq-1 + gapsPhaseAtFreq = gapsPhaseAtFreq .* gapsPhase; % updating phase for future DFT samples at next frequency + BLocal = BLocal + 2 * real( gapDFT * conj(errDft(iiFreq)) ); + ALocal = ALocal + 2 * real( gapDFT * gapDFT' ); + end + B = B + BLocal * powAvgInv(iiFreqAvg); + A = A + ALocal * powAvgInv(iiFreqAvg); + end + end + end + M = (-pinv(A)*B) .'; % solving least-square problem A*M+B=0 + hessian = A; % this is also the hessian of my criterion +end + +%% Direct solver for "FTest" quadratic criterion with no windowing on each gap +function [M, hessian] = solveProblemFTestNoHFWin( gapsPos, powAvgInv, nFreqsAvg) + global optData + computeDuration = 1.3e-8 * numel(gapsPos)^2 * sum(nFreqsAvg); + display(['expected time for linear solver: ' num2str(computeDuration) 's']) + gapsPhase = exp( -1i*2*pi * (gapsPos-1)/numel(optData.y) ); % FFT value of a gap sample at base frequency + nGaps = numel(gapsPos); % number of gaps + nAvgs = numel(nFreqsAvg); % number of frequency bins + B = zeros(nGaps,1); + A = zeros(nGaps,nGaps); + %% frequency weighted criterion + if strcmpi(optData.criterion, 'FTest-NoHfWin') % retrieving corresponding window + W = optData.lfWin; + else + W = optData.winsShift(:, 2*iiWin-1+iiDirection); + end + errDft = fft( optData.y .* W, optData.nData); % FFT algirthm gets DFT + errDft = errDft(optData.keepFreqs); % keeping positive frequencies + gapsAmplitude = W(gapsPos); % amplitude of gaps once windowed + gapsPhaseAtFreq = gapsPhase.^0; % FTF at fundamental : it is only the mean value + iiFreq = 0; % frequency (before averaging with binning) + for iiFreqAvg = 1:nAvgs % loop on frequency bins + BLocal = zeros(nGaps,1); + ALocal = zeros(nGaps,nGaps); + for iiFreqInAvg = 1:nFreqsAvg(iiFreqAvg) % loop on frequencies inside frequency bin + iiFreq = iiFreq + 1; % current frequency index (starting with 1!) + gapDFT = reshape( gapsAmplitude .* gapsPhaseAtFreq , [nGaps,1]); % DFT of each windowed gap data at the frequency number iiFreq-1 + % gapDFT = reshape( gapsAmplitude .* gapsPhase.^(iiFreq-1) , [nGaps,1]); % DFT of each windowed gap data at the frequency number iiFreq-1 + gapsPhaseAtFreq = gapsPhaseAtFreq .* gapsPhase; % updating phase for future DFT samples at next frequency + BLocal = BLocal + 2 * real( gapDFT * conj(errDft(iiFreq)) ); + ALocal = ALocal + 2 * real( gapDFT * gapDFT' ); + end + B = B + BLocal * powAvgInv(iiFreqAvg); + A = A + ALocal * powAvgInv(iiFreqAvg); + end + M = (-pinv(A)*B) .'; % solving least-square problem A*M+B=0 + hessian = A; % this is also the hessian of my criterion +end + +%% function computing the high-frequency window and all its shifted components +function [shiftVals, shiftCounts, winHF, winsHfShift] = makeHFWindows(ndata, gapsPos) + gapsPos = [1; gapsPos; ndata]; + diffGapsPos = diff(gapsPos); % distance between consecutive gaps + %% detecting segments and corresponding lengths + beginSegments = gapsPos([diffGapsPos>1; false])+1; + endSegments = gapsPos([false; diffGapsPos>1])-1; + segmentsLength = endSegments-beginSegments+1; + %% statitstics on segment (half) length + timeShifts = floor(segmentsLength/2); % windows will be shifted by +/- half a segment + [shiftCounts, shiftVals] = hist(timeShifts, 1:ndata); + shiftVals = shiftVals(shiftCounts>0); + shiftCounts = shiftCounts(shiftCounts>0); + %% making main window + winHF = zeros(ndata,1); + for iiSegment=1:numel(segmentsLength) % a window for each segment + phaseLocal = linspace(0, 2*pi, segmentsLength(iiSegment)+2).'; % building phase vector + winLocal = 0.5 * (1 - cos(phaseLocal)); % making window + winHF(beginSegments(iiSegment):endSegments(iiSegment)) = winLocal( 2:end-1 ); % assigning window to corresponding segment + end + %% making all time-shifted windows + winsHfShift = zeros( ndata, 2*numel(shiftVals) ); + for iiShift=1:numel(shiftVals) + winsHfShift(:, 2*iiShift-1) = circshift(winHF, shiftVals(iiShift)).'; + winsHfShift(:, 2*iiShift) = circshift(winHF, -shiftVals(iiShift)).'; + 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: gapfillingoptim.m,v 1.27 2011/06/11 14:11:27 adrien 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(); + + % isgap + p = param({'isgap', ['Logical ao giving position of gaps. If not<br>'... + 'specified, gaps are positionned where there are zeros.']}, {1, {'zeros', ao}, paramValue.SINGLE}); + pl.append(p); + + % large scale or small scale algorithm? + p = param({'scale', 'large scale or small scale algorithm'}, {1, {'large scale', 'small scale'}, paramValue.SINGLE}); + pl.append(p); + + % initial coefficients for subtraction initialization + p = param({ 'coefs' , 'initial subtracted coefficients, must be a nY*nU double array. If not provided zeros are assumed'}, [] ); + pl.append(p); + + % weighting scheme + p = param({ 'weightingMethod' , 'choose to define a frequency weighting scheme'}, {1, {'residual', 'ao', 'pzmodel'}, paramValue.SINGLE} ); + pl.append(p); + + p = param({ 'aoWeight' , 'ao to define a frequency weighting scheme (if chosen in ''weightingMethod'')'}, ao.initObjectWithSize(0,0) ); + pl.append(p); + + p = param({ 'pzmodelWeight' , 'pzmodel to define a frequency weighting scheme (if chosen in ''weightingMethod'')'}, pzmodel.initObjectWithSize(0,0) ); + pl.append(p); + + p = param({ 'lincoef' , 'linear coefficient for scaling frequencies in chi2'}, 20 ); + pl.append(p); + + p = param({ 'logcoef' , 'logarithmic coefficient for scaling frequencies in chi2'}, 0.0 ); + pl.append(p); + + p = param({'fitCriterion' , 'criterion to fit the amplitude spectra (increasing quality, increasing time)'}, {2, {'FTest-NoHfWin' 'FTest' 'chi2'}, paramValue.SINGLE}); + pl.append(p); + + % iterations convergence stop criterion + p = param({ 'iterMax' , 'max number of Mex/Exp iterations (only makes sense for "FTest-NoHfWin" fitting criteiron)'}, 1 ); + pl.append(p); + + p = param({ 'normCoefs' , 'tolerance on inf norm of coefficient update '}, 1e-12 ); + pl.append(p); + + p = param({ 'normCriterion' , 'tolerance on norm of criterion variation'}, 1e-5 ); + pl.append(p); + + % windowing options + p = param({ 'win' , 'window to operate FFT, may be a plist/ao'}, plist('win', 'levelledHanning', 'PSLL', 200, 'levelOrder', 2 ) ); + pl.append(p); + + % display + p = param({ 'display' , 'choose how much to display of the optimizer output'}, {1, {'off', 'iter', 'final'}, paramValue.SINGLE} ); + pl.append(p); + + % optimizer options + p = param({ 'maxcall' , 'maximum number of calls to the criterion function'}, 50000 ); + pl.append(p); + +end