diff m-toolbox/classes/+utils/@helper/process_spectral_options.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/+utils/@helper/process_spectral_options.m	Wed Nov 23 19:22:13 2011 +0100
@@ -0,0 +1,224 @@
+function pl_out = process_spectral_options(pl, type, varargin)
+  % PROCESS_SPECTRAL_OPTIONS checks the options for the parameters needed
+  % by spectral estimators, recalculating  and/or resetting them if needed.
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  %
+  % DESCRIPTION: PROCESS_SPECTRAL_OPTIONS checks the options for:
+  %              - olap
+  %              - order
+  %              - win
+  %              - psll
+  %              - navs (for linear frequency scaled estimators)
+  %              - nfft (for linear frequency scaled estimators)
+  %              - kdes (for logarithmic frequency scaled estimators)
+  %              - jdes (for logarithmic frequency scaled estimators)
+  %              - lmin (for logarithmic frequency scaled estimators)
+  %
+  % CALL:       pl = process_spectral_options(pl, type, varargin)
+  %
+  % INPUTS:
+  %          pl      - the parameter list to scan
+  %          type    - the type of estimator. Choose between:
+  %                  'welch' (or 'lin') for linear frequency scaled
+  %                  'lpsd' (or 'log') for logarithmic frequency scaled
+  %          Optionals:
+  %          obj_len - the length of the object (the shortest in case of x-spec)
+  %          obj_fs  - the sampling frequency of the object (the highest in case of x-spec)
+  %
+  %
+  % OUTPUTS:    pl_out - the revised plist
+  %
+  % VERSION: $Id: process_spectral_options.m,v 1.11 2011/05/23 20:40:46 mauro Exp $
+  %
+  % HISTORY: 20-08-2009 M Hueller
+  %             Creation
+  %
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  
+  % Necessary for debug messages
+  import utils.const.*
+  
+  LIN = 'lin';
+  LOG = 'log';
+  
+  pl_out = copy(pl, true);
+  
+  switch length(varargin)
+    case 0
+      if strcmpi(type, LIN)
+        error('### please provide the object length!');
+      end
+    case 1
+      obj_len = varargin{1};
+    otherwise
+      obj_len = varargin{1};
+      fs = varargin{2};
+  end
+  
+  % Check the type of estimator
+  switch lower(type)
+    case {'welch', 'lin', 'linear'}
+      type = LIN;
+    case {'lpsd', 'log', 'logarithmic'}
+      type = LOG;
+    otherwise
+      error(['### Unsupported estimator type ' type]);
+  end
+  
+  if strcmpi(type, LIN)
+    % Check the number of points in FFT. If this is not set (<0) we set it
+    % to be the length of the input data.
+    Nfft = find(pl, 'Nfft');
+    if isempty(Nfft)
+      Nfft = -1;
+    end
+    setWindow = 0;
+    if ischar(Nfft)
+      nNfft = floor(eval(Nfft));
+      utils.helper.msg(msg.PROC1, 'setting Nfft to %s = %d', Nfft, nNfft);
+      Nfft = nNfft;
+    end
+    if Nfft <= 0
+      Nfft = obj_len;
+      utils.helper.msg(msg.PROC1, 'using default Nfft of %g', Nfft);
+      setWindow = 1;
+    end
+    pl_out.pset('Nfft', Nfft);
+  end
+  
+  % Check the window function.
+  Win = find(pl, 'Win');
+  psll = find(pl, 'psll');
+  levelcoeff = find(pl, 'level');
+  if isempty(Win)
+    Win = 'Rectangular';
+    utils.helper.msg(msg.PROC1, 'using no window (Rectangular)');
+  end
+  if isempty(psll)
+    psll = 0;
+    utils.helper.msg(msg.PROC1, 'setting psll level to 0');
+  end
+  if ischar(psll)
+    npsll = floor(eval(psll));
+    utils.helper.msg(msg.PROC1, 'setting psll to %s = %d', psll, npsll);
+    psll = npsll;
+  end
+  if ischar(Win)
+    % We always want to work with a specwin
+    switch lower(Win)
+      case 'kaiser'
+        Win = specwin(Win, 0, psll);
+      case 'levelledhanning'
+        Win = specwin(Win, 0, levelcoeff);
+      otherwise
+        Win = specwin(Win, 0);
+    end
+  end
+  if strcmpi(type, LIN)
+    % If the length of the window doesn't match NFFT then we resize it.
+    if setWindow || Win.len ~= Nfft
+      Win.len = Nfft;
+      utils.helper.msg(msg.PROC1, 'reset window to %s(%d)', strrep(Win.type, '_', '\_'), Win.len);
+    end
+  else
+    % For log-spaced estimators, let's always reset to a 0-point window
+    Win.len = 0;
+    utils.helper.msg(msg.PROC1, 'reset window to %s(%d)', strrep(Win.type, '_', '\_'), Win.len);
+  end
+  pl_out.pset('Win', Win);
+  pl_out.pset('psll', psll);
+  
+  % Check the overlap. If this is not set, we take the overlap from that
+  % recommended by the window function.
+  Olap = find(pl, 'Olap');
+  if isempty(Olap) || Olap < 0
+    Olap = Win.rov;
+    utils.helper.msg(msg.PROC1, 'using default overlap of %2.1f%%', Olap);
+  end
+  pl_out.pset('Olap', Olap);
+  
+  if strcmpi(type, LIN)
+    % Check if the user is asking for a given number of averages
+    % If so, the Nfft and the win values are reset based on the
+    % calculated value:
+    navs = find(pl, 'navs');
+    if ~isempty(navs) && navs > 1 && setWindow
+      % Compute the number of segments
+      M = obj_len;
+      overlap = Olap/100;
+      L = round(M/(navs*(1-overlap) + overlap));
+      utils.helper.msg(msg.PROC1, 'Asked for navs = %d', navs);
+      % Checks it will really obtain the correct answer.
+      % This is needed to cope with the need to work with integers
+      while fix((M-round(L*overlap))/(L-round(L*overlap))) < navs
+        L = L - 1;
+      end
+      navs_actual = fix((M-round(L*overlap))/(L-round(L*overlap)));
+      utils.helper.msg(msg.PROC1, 'Expect to get navs_actual = %d', navs_actual); 
+      if L > 0
+        % Reset Nfft
+        Nfft = L;
+        pl_out.pset('Nfft', Nfft);
+        % Reset window
+        Win.len = Nfft;
+        pl_out.pset('Win', Win);
+        pl_out.pset('navs', fix(navs_actual));
+        utils.helper.msg(msg.PROC1, 'reset navs to %d', fix(navs_actual));
+      end
+    end
+  end
+  
+  % desired detrending order
+  order = pl.find('Order');
+  if isempty(order)
+    order = 0;
+    utils.helper.msg(msg.PROC1, 'using default detrending order 0 (mean)');    
+  end
+  if ischar(order)
+    norder = floor(eval(order));
+    utils.helper.msg(msg.PROC1, 'setting detrending order to %s = %d', order, norder);
+    order = norder;    
+  end
+  pl_out.pset('Order', order);
+  
+  if strcmpi(type, LOG)
+    % Desired number of averages
+    Kdes = find(pl, 'Kdes');
+    if isempty(Kdes)
+      Kdes = 100;
+      utils.helper.msg(msg.PROC1, 'using default Kdes value 100');      
+    end
+    if ischar(Kdes)
+      nKdes = floor(eval(Kdes));
+      utils.helper.msg(msg.PROC1, 'setting Kdes value to %s = %d', Kdes, nKdes);
+      Kdes = nKdes;
+    end
+    pl_out.pset('Kdes', Kdes);
+    
+    % num desired spectral frequencies
+    Jdes = find(pl, 'Jdes');
+    if isempty(Jdes)
+      Jdes = 1000;
+      utils.helper.msg(msg.PROC1, 'using default Jdes value 1000');      
+    end
+    if ischar(Jdes)
+      nJdes = floor(eval(Jdes));
+      utils.helper.msg(msg.PROC1, 'setting Jdes value to %s = %d', Jdes, nJdes);
+      Jdes = nJdes;
+    end
+    pl_out.pset('Jdes', Jdes);
+    
+    % Minimum segment length
+    Lmin = find(pl, 'Lmin');
+    if isempty(Lmin)
+      Lmin = 0;
+      utils.helper.msg(msg.PROC1, 'using default Lmin value 0');      
+    end
+    if ischar(Lmin)
+      nLmin = floor(eval(Lmin));
+      utils.helper.msg(msg.PROC1, 'setting Kdes value to %s = %d', Lmin, nLmin);
+      Lmin = nLmin;
+    end
+    pl_out.pset('Lmin', Lmin);
+  end
+