function a_db=unionCat(db, with_db, props)

% unionCat - Vertically concatenate two databases with different parameters or tests.
%
% Usage:
% a_db = unionCat(db, with_db, props)
%
% Parameters:
%	db, with_db: tests_db objects to be concatenated together.
%	props: A structure with any optional properties.
%	  offsetTracesets: If 1, make sure the TracesetIndex column is
%	  	offset to non-overlapping values in the concatenated
%	  	databases (default=0).
%
% Description:
%   The parameters and tests in the result are a union of both. Adds 0 for
% parameter and NaN for tests in the rows which didn't have the additional
% columns before.
%
% $Id$
%
% Author: Li Su, 2008-04-10

% Copyright (c) 2007 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.

if ~ exist('props', 'var')
  props = struct;
end

% find params and other column names separately
with_params = getParamNames(with_db);
with_names = setdiff(getColNames(with_db), with_params);
params = getParamNames(db);
names = setdiff(getColNames(db), params);

% combine to find final set of params and cols
combined_params = union(params, with_params);
combined_cols = union(names, with_names);

% fill in params and cols
with_db = fillMissingParams(with_db, combined_params, 0);
db = fillMissingParams(db, combined_params, 0);

with_db = fillMissingColumns(with_db, combined_cols, NaN);
db = fillMissingColumns(db, combined_cols, NaN);

% count tracesets
% [this shouldn't be here, since tracesets correspond to dataset items. I
% added code into physiol_bundle/mergeBundles to count tracesets
% before merging.]
if isfield(props, 'offsetTracesets')
  % take the maximum of tracesetIndex
  max_idx = max(get(onlyRowsTests(db, ':', 'TracesetIndex'), 'data'));
  with_db = ...
      assignRowsTests(with_db, ...
                      onlyRowsTests(with_db, ':', 'TracesetIndex') + max_idx, ...
                      ':', 'TracesetIndex')
end

% delegated to tests_db/vertcat
a_db=[db; with_db];

% merge props recursively
% TODO: put this functinality into mergeStructs [made it recursive, but
% doesn't concat vectors and cells]
props=get(db,'props');
with_props=get(with_db,'props');
commonfield=intersect(fieldnames(props), fieldnames(with_props));
for field={commonfield{:}}
    if isstruct(props.(field{1}))
        props.(field{1})=mergeStructs(props.(field{1}),with_props.(field{1}));
    elseif iscell(props.(field{1})) || isnumeric(props.(field{1}))
        props.(field{1})=[props.(field{1}), with_props.(field{1})];
    end
end
props=mergeStructs(props, with_props); % a union of both fields.

a_db = set(a_db, 'props', props );