% SCALE scales the data in the AO by the specified factor.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DESCRIPTION: SCALE scales the data in the AO by the specified factor.
%
% CALL:        bs = scale(a1,a2,a3,...,pl)
%              bs = scale(as,pl)
%              bs = as.scale(pl)
%
% INPUTS:      aN   - input analysis objects
%              as   - input analysis objects array
%              pl   - input parameter list
% 
% OUTPUTS:     bs   - array of analysis objects, one for each input
%
% <a href="matlab:utils.helper.displayMethodInfo('ao', 'scale')">Parameters Description</a>
%
% VERSION:     $Id: scale.m,v 1.18 2011/04/08 08:56:11 hewitson Exp $
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% PARAMETERS:
%              'factor' - the factor to scale by [default: 1]
%              'yunits' - set a value for the scale factor units
%                         [default: empty => output object will have the same units as input]
%
%

function varargout = scale(varargin)
  
  import utils.const.*
  
  % Check if this is a call for parameters
  if utils.helper.isinfocall(varargin{:})
    varargout{1} = getInfo(varargin{3});
    return
  end
  
  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
  [as, ao_invars,rest] = utils.helper.collect_objects(varargin(:), 'ao', in_names);
  [pls,  invars, rest] = utils.helper.collect_objects(rest(:), 'plist');
  
  % Get default parameters
  pl = parse(pls, getDefaultPlist);
  
  % Get the factor from the plist
  factor = find(pl, 'factor');
  
  % Get user specified yunits
  if find(pl, 'yunits') 
    factor_units = find(pl, 'yunits');
  else
    factor_units = '';
  end
    
  if isa(factor, 'ao')
    % If the factor is an ao, then also get the units
    if isempty (factor_units) 
      factor_units = factor.yunits;
    end
    factor = factor.y;    
  end
  
  % look in rest
  if factor == 1 && ~isempty(rest)
    factor = rest{1};
  end
  
  % now check we got a factor
  if isempty(factor) || ~isnumeric(factor) || numel(factor) ~= 1
    error('### The factor must be a single numeric value.');
  end
  
  % Set the factor to the plist.
  % It might be that the factor was not in the plist
  pl.pset('factor', factor);
    
  % Decide on a deep copy or a modify
  bs = copy(as, nargout);
  

  % Apply method to all AOs
  for kk = 1:numel(bs)
    
    bs(kk).data.setY(bs(kk).data.y .* factor);
    bs(kk).data.setDy(bs(kk).data.dy .* factor);
    
    % Set yunits
    if ~isempty(factor_units)
      bs(kk).data.setYunits(...
        simplify(unit(factor_units) .* bs(kk).data.yunits, ...
        plist('prefixes', false)));
    end
    % set name
    bs(kk).name = sprintf('(%s.*%g)', bs(kk).name, factor);
    % add history
    bs(kk).addHistory(getInfo('None'), pl, ao_invars(kk), as(kk).hist);
  end
  
  % Set output
  if nargout == numel(bs) && numel(bs)>1
    for ii = 1:numel(bs)
      varargout{ii} = bs(ii);
    end
  else
    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.op, '$Id: scale.m,v 1.18 2011/04/08 08:56:11 hewitson Exp $', sets, pl);
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();
  
  p = param({'factor',['The factor to scale by.<br>', ...
    'It can be a double or an ao. In this latter case, the units will be multiplied as well']}, paramValue.DOUBLE_VALUE(1));
  pl.append(p);
  
  p = param({'yunits', ['Set a value for the scale factor units;<br>', ...
    'empty => output object will have the same units as input.<br>', ...
    'Note: these units will override those from the scale factor, if the user specified it as an ao!']}, paramValue.EMPTY_STRING);
  pl.append(p);
  
end

% END
