% DENDROGRAM_TREE plots a dendrogram of a tree.
% (trees package)
%
% HP = dendrogram_tree (intree, diam, yvec, color, DD, wscale, options)
% ---------------------------------------------------------------------
%
% plots a dendrogram of the topology of a tree (must be BCT conform).
% (consider applying repair_tree first)
%
% Input
% -----
% - intree::integer:index of tree in trees or structured tree
% - diam::vector/single value: attributes to each element a horizontal
% width {DEFAULT 0.5}
% - yvec ::vertical vector: attributes to each element a Y-position
% {DEFAULT: metric path length}, might consider branch order instead
% - color::RGB 3-tupel, vector or matrix: RGB values {DEFAULT [0 0 0]}
% if vector then values are treated in colormap (must be Nx1!,
% works only with '-p' option)
% if matrix (num x 3) then individual colors are mapped to each element
% - DD:: X XY-tupel or XYZ-tupel: coordinates offset {DEFAULT [0,0,0]}
% - wscale::scalar: spacing of terminals [default is 1].
% - options::string: {DEFAULT: ''}
% '-p' : drawn as patches instead of lines (color then be Nx1 vector)
% '-v' : no horizontal lines
%
% Output
% ------
% - HP::handles: depending on options HP links to the graphical objects.
%
% Example
% -------
% dendrogram_tree (sample_tree)
%
% See also xdend_tree BCT_tree
% Uses xdend_tree ver_tree dA
%
% the TREES toolbox: edit, visualize and analyze neuronal trees
% Copyright (C) 2009 Hermann Cuntz
function HP = dendrogram_tree (intree, diam, yvec, color, DD, wscale, 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 only directed adjacency for this function
if ~isstruct (intree),
dA = trees {intree}.dA;
else
dA = intree.dA;
end
if (nargin<2)||isempty(diam),
diam = 0.5; % {DEFAULT: half of distance between two end-nodes}
end
if (nargin<3)||isempty(yvec),
yvec = Pvec_tree (intree); % {DEFAULT vector: metric path length}
end
if (nargin<4)||isempty(color),
color = [0 0 0]; % {DEFAULT color: black}
end
if (nargin<5)||isempty(DD),
DD = [0 0 0]; % {DEFAULT 3-tupel: no spatial displacement from the root}
end
if length(DD)<3,
DD = [DD zeros(1, 3 - length (DD))]; % append 3-tupel with zeros
end
if (nargin<6)||isempty(wscale),
wscale = 1; % {DEFAULT: 1 um between two terminal nodes}
end
if (nargin<7)||isempty(options),
options = ''; % {DEFAULT: no option}
end
% get the x-positions for the dendrogram:
xdend = xdend_tree (intree);
% xdend (idpar) is the same as dA*xdend
idpar = dA * (1 : size (dA, 1))'; % vector containing index to direct parent
idpar (idpar == 0) = 1;
X1 = ((xdend (idpar)) .* wscale) + DD (1); % coordinates of the nodes in dendrogram
X2 = (xdend .* wscale) + DD (1);
Y1 = yvec (idpar) + DD (2);
Y2 = yvec + DD (2);
Z1 = zeros (size (X1, 1), 1) + DD (3);
Z2 = zeros (size (X1, 1), 1) + DD (3);
Diam = ones (size (X1, 1), 1) .* diam;
if isempty (strfind (options, '-v')),
% separate in horizontal and vertical components:
X1 = [X1; X2];
X2 = [X2; X2];
Y2 = [Y1; Y2];
Y1 = [Y1; Y1];
Z1 = [Z1; Z2];
Z2 = [Z2; Z2];
if size (color, 1) > 1,
color = [color; color]';
end
Diam = [Diam*(max (Y1) - min (Y1))/(max (X1) - min (X1)); Diam];
else
if size (color, 1) > 1,
color = color';
end
end
if isempty (strfind (options, '-p')), % as lines:
HP = line ([X1 X2]', [Y1 Y2]', [Z1 Z2]');
set (HP, 'linewidth', diam, 'color', color);
else % as patches:
warning ('off', 'MATLAB:divideByZero');
A = [X2-X1 Y2-Y1] ./ repmat (sqrt ((X2-X1).^2 + (Y2-Y1).^2), 1, 2);
warning ('on', 'MATLAB:divideByZero');
% use rotation matrix to rotate the data
V1 =(A*[0,-1;1,0]).*(repmat(Diam, 1, 2)./2);
V2 =(A*[0,1;-1,0]).*(repmat(Diam, 1, 2)./2);
HP = patch([X1+V2(:,1) X1+V1(:,1) X2+V1(:,1) X2+V2(:,1)]',...
[Y1+V2(:,2) Y1+V1(:,2) Y2+V1(:,2) Y2+V2(:,2)]',[Z1 Z1 Z2 Z2]',color);
set (HP, 'edgecolor', 'none');
end