function a_pm = ...
      param_mult(var_names, param_init_vals, param_names, param_funcs, ...
                 func_handle, id, props)
  
% param_mult - Function composed of multiple param_func objects.
%
% Usage:
%   a_pm = ...
%     param_mult(var_names, param_init_vals, param_names, param_funcs, ...
%                func_handle, id, props)
%
% Parameters:
%   var_names: Cell array of names for input and output variables, resp.
%   param_init_vals: Initial values of function parameters.
%   param_names: Cell array of parameter names.
%   param_funcs: Structure of param_func or subclass objects.
%   func_handle: Function name or handle that takes funcs, params 
%   		 and variable (fs,p,x) to produce output.
%   id: An identifying string for this function.
%   props: A structure with any optional properties.
%     (Rest passed to param_func)
%		
% Returns a structure object with the following fields:
%	f: param_funcs from above,
%	param_func.
%
% Description:  
%   Specialized version (subclass) of param_func for combining multiple
% param_func objects in one function. Retains the ability to define its
% own parameters.
%
% Additional methods:
%	See methods('param_mult') and methods('param_func')
%
% Example:
%   f_Itot = ...
%      param_mult(...
%        {'mV', 'nA'}, struct('ENa', 45), [], 
%        struct('gNaP', f_gNaP), ...
%        @(fs, p, x) f(fs.gNaP, x) * ( x - p.ENa), ...
%        'INaP', struct('xMin', -90, 'xMax', 30));
%
% See also: param_func, tests_db, plot_abstract
%
% $Id: param_mult.m 772 2013-08-09 21:14:58Z cengiz $
%
% Author: Cengiz Gunay <cgunay@emory.edu>, 2009/12/09
  
% TODO: make this not a subclass of param_func? [no, loses advantage of
% polymorphism]
  if ~ exist('props', 'var')
    props = struct;
  end

  props = mergeStructs(props, struct('xMin', -100, 'xMax', 100));

  if nargin == 0 % Called with no params
    a_pm = struct;
    a_pm.f = struct;
    a_pm = class(a_pm, 'param_mult', ...
                 param_func({}, [], {}, [], '', props));
  elseif isa(param_funcs, 'param_mult') % copy constructor?
    a_pm = param_funcs;
  else
    a_pm = struct;
    a_pm.f = param_funcs;
    
    % pass param and var names to param_func for display purposes only
    % (remove if leads to confusion)
    a_pm = class(a_pm, 'param_mult', ...
                 param_func(var_names, param_init_vals, param_names, ...
                            func_handle, id, props));
  end

  % TODO: doesn't work
    %var_names = ...
    %   cellfun(@(c) c.var_names{:}, param_func_cell, ...
    %            'UniformOutput', true)

    % OBSOLETE:
% $$$     var_names = {};
% $$$     param_names = {};
% $$$     param_func_cell = struct2cell(param_funcs)';
% $$$     for a_f = param_func_cell
% $$$       a_f = a_f{1};
% $$$       vn = a_f.var_names;
% $$$       var_names = [ var_names, vn{:} ];
% $$$       pn = getParamNames(a_f);
% $$$       % TODO: add sub-func name to param name
% $$$       param_names = [ param_names, pn{:} ];
% $$$     end