function a_params_db = varyParams(a_db, params, levels, props)

% varyParams - Varies chosen parameters in all rows by given levels.
%
% Usage:
% a_params_db = varyParamsOneRow(a_db, params, levels, props)
%
% Parameters:
%   a_db: A params_tests_db object.
%   params: Parameters to be varied (see tests2cols).
%   levels: Column vector of parameter values to multiply (1=unity)
%	or to replace parameters with (see 'replace' prop).
%   props: A structure with any optional properties.
%	replace: Replace parameter values with levels instead of scaling.
%
% Returns:
%   a_params_db: A db only with params.
%
% Example:
% Blocks NaF from 0%-100% with 10% increments:
% >> naf_rows_db = varyParams(a_db(desired_row, :), 'NaF', 0:0.1:1);
%
% Description:
%   Produces new rows by either multiplying or replacing the desired params
% with each value in levels. Thus, the newly created parameter db will be
% size of levels times bigger. Columns other than parameers will be
% pruned. Then, writeParFile can be used to generate a parameter file
% from this DB to drive new simulations.
%
% See also: writeParFile, ranked_db/blockedDistances, getParamRowIndices
%
% $Id$
%
% Author: Cengiz Gunay <cgunay@emory.edu>, 2006/02/16

% Copyright (c) 2007-2014 Cengiz Gunay <cengique@users.sf.net>.
% This work is licensed under the Academic Free License ("AFL")
% v. 3.0. To view a copy of this license, please look at the COPYING
% file distributed with this software or visit
% http://opensource.org/licenses/afl-3.0.php.

props = defaultValue('props', struct);

if ~ iscell(params)
  params = {params};
end

% make column vector
levels=levels(:); 

% Select parameters
a_params_db = onlyRowsTests(a_db, ':', params);

% multiply or replace?
new_params = repmat(levels, dbsize(a_params_db));
if ~ isfield(props, 'replace')
  % replicate each row length(levels) times to align with levels
  data = get(a_params_db, 'data');
  index = reshape(repmat(1:size(data, 1), length(levels), 1), ...
                  size(data, 1) * length(levels), 1);
  new_params = new_params .* data(index, :);
end

a_params_db = params_tests_db(new_params, ...
			      params, [], {}, [ params{:} ' DB' ]);
% name
param_names = ...
    cellfun(@(x)[ x ' '], getColNames(onlyRowsTests(a_db, ':', params)), ...
            'UniformOutput', false);

% expand db using fake column(s)
a_params_expand_db = ...
    crossProd(delColumns(a_db, params), ...
              params_tests_db(repmat(NaN, length(levels), ...
                                     dbsize(a_params_db, 2)), params, ...
                              [], {}, [ param_names{:}  ' vary DB']));
a_params_expand_db = delColumns(a_params_expand_db, params);

% combine with new params
a_params_db = ...    
    addParams(a_params_db, getColNames(a_params_expand_db), ...
              get(a_params_expand_db, 'data'));

% Keep original order of params
a_params_db = onlyRowsTests(a_params_db, ':', getParamNames(a_db));