% CAT_TREE Concatenates two trees.
% (trees package)
%
% tree = cat_tree (intree1, intree2, inode1, inode2, options)
% -----------------------------------------------------------
%
% concatenates two trees (the second onto the first) at respective
% positions within the branching structure. Sorts the indices according to
% level order (see "sort_tree" with option '-LO'). Fields are prefarably
% taken from intree1, all vectors (X, Y, Z, D etc...) must exist in both if
% they exist in one tree and are concatenated as well. Region fields R and
% rnames are updated. By default, the second tree is connected at its root
% to the node in the first tree which is closest.
%
% Input
% -----
% - intree1::integer:index of tree 1 in trees or structured tree
% - intree2::integer:index of tree 2 in trees or structured tree
% - inode1::number:position in first tree
% {DEFAULT: node which is closest to inode2 of tree 2}
% - inode2::number:position in second tree {DEFAULT: root == 1}
% - options::string: {DEFAULT: '-e'}
% '-s' : show
% '-e' : echo field degeneration
% '-r' : do not update regions
%
% Output
% ------
% if no output is defined tree intree1 is changed in trees
% - tree:: structured output tree
%
% Example
% -------
% sample1 = sample_tree;
% sample2 = tran_tree (sample_tree, [100 70 0]);
% cat_tree (sample1, sample2, [], [], '-s -e')
%
% See also delete_tree insert_tree
% Uses redirect_tree sort_tree ver_tree
%
% the TREES toolbox: edit, visualize and analyze neuronal trees
% Copyright (C) 2009 Hermann Cuntz
function varargout = cat_tree (intree1, intree2, inode1, inode2, options)
% trees : contains the tree structures in the trees package
global trees
ver_tree (intree1); % verify that input 1 is a tree structure
ver_tree (intree2); % verify that input 2 is a tree structure
% use full tree 1 for this function
if ~isstruct(intree1),
tree1 = trees{intree1};
else
tree1 = intree1;
end
% use full tree 2 for this function
if ~isstruct(intree2),
tree2 = trees{intree2};
else
tree2 = intree2;
end
if (nargin < 4)||isempty(inode2),
inode2 = 1; % {DEFAULT: root node of second tree}
end;
if (nargin < 3)||isempty(inode1),
% {DEFAULT: connect to node on first tree which is closest to inode2 of tree 2}
[i1 inode1] = min(eucl_tree(tree1, [tree2.X(inode2) tree2.Y(inode2) tree2.Z(inode2)]));
end;
if (nargin < 5)||isempty(options),
options = '-e'; % {DEFAULT: echo changes}
end
tree2 = redirect_tree (tree2, inode2); % if inode2 is not root on tree2 set it to root
dA1 = tree1.dA; % directed adjacency matrix of tree 1
dA2 = tree2.dA; % directed adjacency matrix of tree 2
N1 = size (dA1, 1); % number of nodes in tree 1
N2 = size (dA2, 1); % number of nodes in tree 2
ndA = sparse ([[dA1; sparse(N2,N1)] [sparse(N1,N2); dA2]]);
ndA (1 + N1, inode1) = 1;
tree.dA = ndA;
% expand all fields, take only tree1 fields
S = fieldnames(tree1);
for ward = 1:length(S),
if ~strcmp(S{ward}, 'dA'),
vec1 = tree1.(S{ward});
tree.(S{ward}) = vec1;
if isfield (tree2, S{ward}),
vec2 = tree2.(S{ward});
if isvector(vec1) && (numel(vec1) == N1)
if isvector(vec2) && (numel(vec2) == N2),
tree.(S{ward}) = [tree1.(S{ward}); tree2.(S{ward})];
else
if strfind (options, '-e'),
warning ('TREES:treeinconsistency',['degenerating field: ' S{ward}]);
end
end
end
end
end
end
% eliminate obsolete regions (only if everything is correct)
if isempty(strfind (options, '-r')),
if isfield(tree1,'R') && isfield(tree2, 'R')
if isfield (tree1, 'rnames') && isfield (tree2, 'rnames'),
[i1 i2 i3] = unique ([tree1.rnames tree2.rnames]);
R = [tree1.R; tree2.R+length(tree1.rnames)];
i3 = i3'; tree.R = i3(R);
tree.rnames = i1;
else
[i1 i2 i3] = unique([tree1.R; tree2.R]);
tree.R = i3;
end
end
end
tree = sort_tree (tree, '-LO');
if strfind (options, '-s'),
clf; shine; hold on; plot_tree(intree1);
plot_tree (intree2, [1 0 0]);
plot_tree (tree, [0 1 0], [200 0 0]);
HP(1) = plot(1, 1, 'k-'); HP(2) = plot(1, 1, 'r-'); HP(3) = plot(1, 1, 'g-');
legend (HP, {'tree 1', 'tree 2', 'concat. tree'}); set(HP, 'visible', 'off');
title ('concatenate two trees');
xlabel ('x [\mum]'); ylabel ('y [\mum]'); zlabel ('z [\mum]');
view(2); grid on; axis image;
end
if (nargout == 1)||(isstruct(intree1)),
varargout{1} = tree;
else
trees{intree1} = tree;
end