diff m-toolbox/classes/@ltpda_tf/resp.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/@ltpda_tf/resp.m	Wed Nov 23 19:22:13 2011 +0100
@@ -0,0 +1,365 @@
+% RESP returns the complex response of a transfer function as an Analysis Object.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% DESCRIPTION: RESP returns the complex response of a transfer function as
+%              an Analysis Object.
+%
+% CALL:        a = resp(obj, f);          % compute response for vector f
+%              a = resp(obj, f1, f2, nf); % compute response from f1 to f2 in nf
+%                                           steps.
+%              a = resp(obj, pl);         % compute response from parameter list.
+%              a = resp(obj);             % compute response
+%
+% <a href="matlab:utils.helper.displayMethodInfo('ltpda_tf', 'resp')">Parameters Description</a>
+%
+% VERSION:     $Id: resp.m,v 1.14 2011/04/18 16:50:51 ingo Exp $
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function varargout = resp(varargin)
+  
+  %%% Check if this is a call for parameters
+  if utils.helper.isinfocall(varargin{:})
+    varargout{1} = getInfo(varargin{3});
+    return
+  end
+  
+  %%% Input objects checks
+  if nargin < 1
+    error('### incorrect number of inputs.')
+  end
+  
+  objs = {};
+  rest = {};
+  plin = [];
+  invars = {};
+  % Check input shape
+  % only one input -> keep shape
+  % more than one input -> convert to list.
+  classMatch = zeros(nargin, 1);
+  for ii = 1:nargin
+    if isa(varargin{ii}, 'ltpda_tf')
+      classMatch(ii) = 1;
+    end
+  end
+  
+  for ii = 1:nargin
+    if classMatch(ii) == 1
+      if sum(classMatch) == 1
+        objs = num2cell(varargin{ii});
+        invars = [invars repmat({inputname(ii)}, 1, numel(varargin{ii}))];
+      else
+        objs = [objs reshape(num2cell(varargin{ii}), 1, [])];
+        invars = [invars repmat({inputname(ii)}, 1, numel(varargin{ii}))];
+      end
+    else
+      if isa(varargin{ii}, 'plist')
+        plin = [plin varargin{ii}];
+      else
+        rest = [rest {varargin{ii}}];
+      end
+    end
+  end
+    
+  % Combine the input plists
+  plin = combine(plin, plist());
+  
+  % Initialize output
+  bank = plin.combine(getDefaultPlist('Range')).find('bank');
+  switch lower(bank) 
+    case 'none'
+    bs = ao.initObjectWithSize(size(objs,1), size(objs,2));
+    otherwise
+    bs = [];
+  end
+  
+  % Loop over transfer functions
+  for pp=1:numel(objs)
+    
+    % process this transfer function
+    obj = objs{pp};
+    % Now look at the model
+    name  = obj.name;
+    
+    if (plin.isparam('f')) || ...
+        (numel(rest) == 1 && isnumeric(rest{1}) && isvector(rest{1})) || ...
+        (numel(rest) == 1 && isa(rest{1}, 'ao') && isa(rest{1}.data, 'fsdata')) || ...
+        (numel(rest) == 1 && isa(rest{1}, 'ao') && isa(rest{1}.data, 'xydata'))
+      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+      %%%%%%%%%%              Response with a f vector               %%%%%%%%%%
+      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+      %%% r = obj.resp(plist-object('f'))
+      %%% r = obj.resp(ao-object(fsdata))
+      %%% r = obj.resp(ao-object(xydata))
+      
+      if numel(rest) == 1
+        pl = combine(plist('f', rest{1}), getDefaultPlist('List'));
+      else
+        pl = combine(plin, getDefaultPlist('List'));
+      end
+      
+      %%% Get f-vector
+      f = pl.find('f');
+      
+      %%% Get the f-vector from the AO
+      if isa(f, 'ao')
+        f = f.data.x;
+      elseif isnumeric(f) && isvector(f)
+        %%% nothing to do
+      else
+        error('### The f-vector must be a vector or an AO, but it is from the class [%s]', class(f));
+      end
+      
+    elseif (plin.isparam('f1')) || ...
+        (plin.isparam('f2'))    || ...
+        (numel(rest) == 0)      || ...
+        (numel(rest) == 2 && isnumeric(rest{1}) && isnumeric(rest{2})) || ...
+        (numel(rest) == 3 && isnumeric(rest{1}) && isnumeric(rest{2}) && isnumeric(rest{3}))
+      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+      %%%%%%%%%%             Response with f1, f2 and nf             %%%%%%%%%%
+      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+      %%% r = obj.resp(plist-object('f1', 'f2'))
+      %%% r = obj.resp(plist-object('f1'))
+      %%% r = obj.resp(plist-object('f2'))
+      %%% r = obj.resp()
+      %%% r = obj.resp(f1, f2)
+      %%% r = obj.resp(f1, f2, nf)
+      
+      if numel(rest) == 0 && plin.nparams == 0
+        pl = getDefaultPlist('Range');
+        
+      elseif numel(rest) == 2
+        pl = combine(plist('f1', rest{1}, 'f2', rest{2}), getDefaultPlist('Range'));
+        
+      elseif numel(rest) == 3
+        pl = combine(plist('f1', rest{1}, 'f2', rest{2}, 'nf', rest{3}), getDefaultPlist('Range'));
+        
+      else
+        pl = combine(plin, getDefaultPlist('Range'));
+      end
+      
+      f1 = pl.find('f1');
+      f2 = pl.find('f2');
+      nf = pl.find('nf');
+      scale = pl.find('scale');
+      
+      % Get the default values if 'f1' or 'f2' are not existing
+      if isa(obj, 'miir') || isa(obj, 'mfir')
+        % Special case for iir- and fir filters.
+        if isempty(f1), f1 = obj.fs/1000; end
+        if isempty(f2), f2 = obj.fs/2-1/nf; end
+        if isempty(f1), f1 = 0; end
+        if isempty(f2), f2 = 0.5; end
+        
+      else
+        if isempty(f1), f1 = getlowerFreq(obj)/10; end
+        if isempty(f2), f2 = getupperFreq(obj)*10; end
+      end
+      
+      switch lower(scale)
+        case 'lin'
+          f = linspace(f1, f2, nf);
+        case 'log'
+          f = logspace(log10(f1), log10(f2), nf);
+      end
+      
+    else
+      error('### Unknown or incorrect number of inputs.');
+    end
+    
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%%%%%%%%%                    deal with rows                     %%%%%%%%%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    reshape_f = false;
+    if size(f,1) > 1
+      f = f.';
+      reshape_f = true;
+    end
+    
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%%%%%%%%%                 compute the response                  %%%%%%%%%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    
+    r = respCore(obj, f);
+    
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%%%%%%%%%                   Build output AO                     %%%%%%%%%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    if reshape_f
+      f = f.';
+      r = r.';
+    end
+    
+    % create new output fsdata
+    fsd = fsdata(f, r);
+    
+    % set yunits = ounits./iunits
+    fsd.setXunits('Hz');
+    fsd.setYunits(obj.ounits./obj.iunits);
+    
+    % set fs, if the object is a discrete filter
+    if isa(obj, 'ltpda_filter')
+      fsd.setFs(obj.fs);
+    end
+    
+    % make output analysis object
+    b = ao(fsd);
+    
+    switch lower(bank)
+      case 'none'
+        % Add history
+        b.addHistory(getInfo('None'), pl, invars, obj.hist);
+        % set name
+        if isempty(name)
+          b.setName(sprintf('resp(%s)', invars{pp}));
+        else
+          b.setName(sprintf('resp(%s)', name));
+        end
+        % Add to outputs
+        bs(pp) = b;
+
+      case 'serial'
+        if isempty(bs)
+          bs = b;
+          oname = obj.name;
+        else
+          bs = bs .* b;
+          oname = [oname '.*' obj.name];
+        end
+        
+      case 'parallel'
+        if isempty(bs)
+          bs = b;
+          oname = obj.name;
+        else
+          bs = bs + b;
+          oname = [oname '+' obj.name];
+        end
+      otherwise
+        error('Unknown option for parameter ''bank'': %s', bank);
+    end
+    
+  end
+  
+  if strcmpi(bank, 'parallel') || strcmpi(bank, 'serial')
+    inhists = [];
+    for ii = 1:numel(objs)
+      inhists = [inhists objs{ii}.hist];
+    end
+    % Add history
+    bs.addHistory(getInfo('None'), pl, [], inhists);
+    % set name
+    bs.setName(sprintf('resp(%s)', oname));
+  end
+  
+  % Outputs
+  if nargout == 0
+    iplot(bs)
+  elseif nargout == numel(bs)
+    % List of outputs
+    for ii = 1:numel(bs)
+      varargout{ii} = bs(ii);
+    end
+  else
+    % Single output
+    varargout{1} = bs;
+  end
+  
+end
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                               Local Functions                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% FUNCTION:    getInfo
+%
+% DESCRIPTION: Get Info Object
+%
+% HISTORY:     11-07-07 M Hewitson
+%                Creation.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function ii = getInfo(varargin)
+  if nargin == 1 && strcmpi(varargin{1}, 'None')
+    sets = {};
+    pls   = [];
+  elseif nargin == 1&& ~isempty(varargin{1}) && ischar(varargin{1})
+    sets{1} = varargin{1};
+    pls = getDefaultPlist(sets{1});
+  else
+    sets = {'List', 'Range'};
+    pls = [];
+    for kk=1:numel(sets)
+      pls = [pls getDefaultPlist(sets{kk})];
+    end
+  end
+  % Build info object
+  ii = minfo(mfilename, 'ltpda_tf', 'ltpda', utils.const.categories.sigproc, '$Id: resp.m,v 1.14 2011/04/18 16:50:51 ingo Exp $', sets, pls);
+  ii.setModifier(false);
+  ii.setArgsmin(1);
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% FUNCTION:    getDefaultPlist
+%
+% DESCRIPTION: Get Default Plist
+%
+% HISTORY:     11-07-07 M Hewitson
+%                Creation.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function plout = getDefaultPlist(set)
+  persistent pl;
+  persistent lastset;
+  if exist('pl', 'var')==0 || isempty(pl) || ~strcmp(lastset, set)
+    pl = buildplist(set);
+    lastset = set;
+  end
+  plout = pl;
+end
+
+function plo = buildplist(set)
+  switch lower(set)
+    case 'list'
+      
+      plo = plist();
+      
+      p = param({'f',['A vector of frequencies to evaluate at or an AO \n',...
+        'whereby the x-axis is taken for the frequency values.']}, paramValue.EMPTY_DOUBLE);
+      plo.append(p);
+      
+    case 'range'
+      plo = plist();
+      
+      p = param({'f1','Start frequency.'}, paramValue.EMPTY_DOUBLE);
+      plo.append(p);
+      
+      p = param({'f2','Stop frequency.'}, paramValue.EMPTY_DOUBLE);
+      plo.append(p);
+      
+      p = param({'nf','Number of evaluation frequencies.'}, paramValue.DOUBLE_VALUE(1000));
+      plo.append(p);
+      
+      p = param({'scale',['Spacing of frequencies:<ul>', ...
+        '<li>''lin'' - Linear scale.</li>', ...
+        '<li>''log'' - Logarithmic scale.</li></ul>']}, {2, {'lin', 'log'} paramValue.SINGLE});
+      plo.append(p);
+      
+    otherwise
+      error('### Unknown set [%s]', set);
+  end
+  
+  p = param({'bank',['How to handle a vector of input filters<br/>(only iir and fir filters):<ul>',...
+    '<li>''None''     - process each filter individually.</li>',...
+    '<li>''Serial''   - return the response of a serial filter bank.</li>',...
+    '<li>''Parallel'' - return the response of a parallel filter bank.</li></ul>']}, {1, {'none', 'serial', 'parallel'}, paramValue.SINGLE});
+  plo.append(p);
+  
+end
+