% DELETE_TREE Delete nodes from a tree.
% (trees package)
%
% tree = delete_tree (intree, inodes, options)
% --------------------------------------------
%
% deletes a node in a tree. Trifurcation occurs when deleting any branching
% point following directly another branch point. Region numbers are changed
% and region name array is trimmed.
% Alters the topology! Root deletion can lead to unexpected results!
%
% Input
% -----
% - intree::integer: index of tree in trees or structured tree
% - inodes::vector: node indices {DEFAULT: last node}
% - options::string: {DEFAULT: ''}
% '-s' : show
% '-w' : waitbar
% '-r' : do not trim regions array
%
% Output
% ------
% if no output is declared the tree is changed in trees
% - tree:: structured output tree
%
% Example
% -------
% delete_tree (sample_tree, 5:2:8, '-s')
%
% See also insert_tree cat_tree
% Uses idpar_tree dA
%
% the TREES toolbox: edit, visualize and analyze neuronal trees
% Copyright (C) 2009 Hermann Cuntz
function varargout = delete_tree (intree, inodes, options)
% trees : contains the tree structures in the trees package
global trees
if (nargin < 1)||isempty(intree),
intree = length (trees); % {DEFAULT tree: last tree in trees cell array}
end;
ver_tree (intree); % verify that input is a tree structure
% use full tree for this function
if ~isstruct(intree),
tree = trees {intree};
else
tree = intree;
end
dA = tree.dA; % directed adjacency matrix of tree
N = size (dA, 1); % number of nodes in tree
if (nargin < 2)||isempty(inodes),
inodes = N; % {DEFAULT: delete last node}
end
if size(inodes,1) == N,
% all nodes are deleted, return empty vector:
if (nargout == 1)||(isstruct(intree)),
varargout{1} = [];
else
trees{intree} = [];
end
return
end
if (nargin < 3)||isempty(options),
options = ''; % {DEFAULT: no option}
end
% nodes get deleted one by one, therefore new index has to be calculated
% each time, using sindex:
sindex = 1 : N;
if strfind (options, '-w'), % waitbar option: initialization
HW = waitbar (0, 'deleting nodes...');
set (HW, 'Name', '..PLEASE..WAIT..YEAH..');
end
for ward = 1 : length (inodes)
if strfind (options, '-w'), % waitbar option: update
if mod(ward,500) == 0,
waitbar (ward/length(inodes), HW);
end
end
% find the node index corresponding to the pruned tree:
inode = find (inodes (ward) == sindex);
% delete this node from the index list
sindex (inode) = [];
% find the column in dA corresponding to this node
ydA = dA (:, inode);
% this column contains ones at the node's child indices
% find the parent index to inode
idpar = find (dA (inode, :));
if ~isempty (idpar),
% if it is not root then add inode's children to inode's parent
dA (:,idpar) = dA (:,idpar) + ydA;
end
% get rid of the node in the adjacency matrix by eliminating row and
% column inode.
dA (:, inode) = [];
dA (inode, :) = [];
end
if strfind (options, '-w'), % waitbar option: close
close(HW);
end
tree.dA = dA;
% shorten all vectors of form Nx1
S = fieldnames (tree);
for ward = 1 : length(S),
if ~strcmp(S{ward},'dA'),
vec = tree.(S{ward});
if isvector(vec) && (numel(vec) == N),
tree.(S{ward})(inodes) = [];
end
end
end
% eliminate obsolete regions
if isempty (strfind (options, '-r')),
if isfield (tree, 'R'),
[i1 i2 i3] = unique (tree.R);
tree.R = i3;
if isfield (tree, 'rnames'),
tree.rnames = {tree.rnames{i3(i2)}};
end
end
end
if strfind (options, '-s'),
clf; shine; hold on; plot_tree (intree);
plot_tree (tree, [0 1 0], 100);
HP(1) = plot (1, 1, 'k-'); HP(2) = plot (1, 1, 'g-');
legend (HP, {'original tree', 'trimmed tree'}); set (HP, 'visible', 'off');
title ('find the differences: delete nodes in tree');
xlabel ('x [\mum]'); ylabel ('y [\mum]'); zlabel ('z [\mum]');
view(2); grid on; axis image;
HP = pointer_tree (intree, inodes); set (HP, 'facealpha', .5);
end
if (nargout == 1)||(isstruct(intree)),
varargout {1} = tree;
else
trees {intree} = tree;
end