No BSD License  

Highlights from
plotphytree

image thumbnail

plotphytree

by

 

12 Apr 2007 (Updated )

PLOTPHYTREE(TREE) renders a phylogenetic tree object into a MATLAB figure as a phylogram.

plotphytree(tr,varargin)
function plotphytree(tr,varargin)
%PLOTPHYTREE renders a phylogenetic tree.
%
%   PLOTPHYTREE(TREE) renders a phylogenetic tree object into a MATLAB figure as a
%   phylogram. 
%
%   plotphytree(...,'ROTATION',value) will orient the phylogenetic tree within
%   the figure window. Positive angles cause counterclockwise rotation,
%   otherwise clockwise rotation.   
%
%   plotphytree(...,'FONTSIZE',value) will set the lable font size.A value
%   specifying the font size to use for text in units determined by the FontUnits
%   property (1 point = 1/72 inch). The default is calculated from the data
%   according to the number of nodes.
%
%   plotphytree(...,'LINESTYLE',value) will set the color of the tree. The
%   default color is blue.
%          b     blue          .     point              -     solid
%          g     green         o     circle             :     dotted
%          r     red           x     x-mark             -.    dashdot 
%          c     cyan          +     plus               --    dashed   
%          m     magenta       *     star             (none)  no line
%          y     yellow        s     square
%          k     black         d     diamond
%                              v     triangle (down)
%                              ^     triangle (up)
%                              <     triangle (left)
%                              >     triangle (right)
%                              p     pentagram
%                              h     hexagram
%
%   plotphytree(...,'FONTCOLOR',value) will set the color of lable. It is a
%   vector includes [R, G, B] components. Each with the range of 0 to 1.
%   The default setting is [.2 .2 .2].
%
%   
%   Example:
%      
%       tr = phytreeread('pf00002.tree');
%       plotphytree(tr,'ROTATION',-pi/2, 'FONTSIZE', 8, 'LINESTYLE', 'b', 'FONTCOLOR', [0.2 0.2 0.2]);
%
%       

if numel(tr)~=1
     error('plotphytree:NoMultielementArrays',...
           'Phylogenetic tree must be an 1-by-1 object.');
end

% set defaults
rotation = 0;
fontsize = 1;
fontsizeset = false;
linestyle = '-b';
fontcolor = [.2 .2 .2];


if nargin>1 && islogical(varargin{1})
    activeBranches = varargin{1};  
    argStart = 2;
else     
    argStart = 1;
end

if nargin - argStart > 0
        if rem(nargin - argStart,2) == 1
        error('plotphytree:IncorrectNumberOfArguments',...
              'Incorrect number of arguments to %s.',mfilename);
    end
    okargs = {'rotation', 'fontsize', 'linestyle', 'fontcolor'}; 
    
    for j = argStart:2:nargin-argStart          
        pname = varargin{j};
        pval = varargin{j+1};
        k = find(strncmpi(pname,okargs,numel(pname)));
        if isempty(k)
            error('plotphytree:UnknownParameterName',...
                  'Unknown parameter name: %s.',pname);
        elseif length(k)>1
            error('plotphytree:AmbiguousParameterName',...
                  'Ambiguous parameter name: %s.',pname);
        else
            switch(k)
                case 1 % rotation
                    if isreal(pval(1))
                        rotation = double(pval(1));
                    else
                        error('plotphytree:NotValidType',...
                              'ROTATION must be numeric and real');
                    end
                case 2 % fontsize
                    if isreal(pval(1))
                        fontsize = uint8(pval(1));
                        fontsizeset = true;
                    else
                        error('plotphytree:NotValidType',...
                              'fontsize must be numeric');
                    end  
                case 3 % linecolor
                    linestyle = pval(1);
                case 4 % Fontcolor
                    fontcolor = [pval(1) pval(2) pval(3)];                    
            end
        end
    end
end    

orgtr=tr;
treeinfo = get(tr);

%Get tree structure
tr = struct(tr);
tr.numLeaves = treeinfo.NumLeaves;
tr.numNodes = treeinfo.NumNodes;
tr.numBranches = treeinfo.NumBranches;
tr.LeafNames = treeinfo.LeafNames;
tr.BranchNames = treeinfo.BranchNames;
tr.numTree = size(tr.tree, 1);

% obtain parents for every node
tr.par(tr.tree(:)) = tr.numLeaves + [1:tr.numBranches 1:tr.numBranches];

% obtain numbers of leaves for each nodes
tr.numChildrenofNode = ChildCount(tr.par, tr.numLeaves, tr.numNodes);
tr.numChildrenofNode(tr.numChildrenofNode == 0) = 1;

% find angle of each node 
unitDegree = 2 * pi / tr.numLeaves;

tr.NodeSector = tr.numChildrenofNode * unitDegree;    
tr.NodeSector(tr.NodeSector == 0) = unitDegree;
tr.NodeSector(tr.numNodes) = 0;

tr.NodeAngle = zeros(tr.numNodes, 1);
tr.NodeAngle(tr.tree(tr.numTree, 2)) = tr.NodeSector(tr.tree(tr.numTree, 2)) / 2;
tr.NodeAngle(tr.tree(tr.numTree, 1)) = tr.NodeSector(tr.tree(tr.numTree, 2)) + tr.NodeSector(tr.tree(tr.numTree, 1)) / 2;
for i = tr.numTree - 1 : -1 :1
    tr.NodeAngle(tr.tree(i, 2)) = tr.NodeAngle(tr.par(tr.tree(i, 2))) - tr.NodeSector(tr.par(tr.tree(i, 2))) / 2 + tr.NodeSector(tr.tree(i, 2)) / 2;
    tr.NodeAngle(tr.tree(i, 1)) = tr.NodeAngle(tr.par(tr.tree(i, 1))) + tr.NodeSector(tr.par(tr.tree(i, 1))) / 2 - tr.NodeSector(tr.tree(i, 1)) / 2;
end

% Rotation
tr.NodeAngle = tr.NodeAngle + rotation;

% find (x, y) coordinates of nodes
tr.d = tr.dist; 
tr.x = tr.d .* cos(tr.NodeAngle);
tr.y = tr.d .* sin(tr.NodeAngle);
 
for i = tr.numNodes - 1: -1 : 1
    tr.x(i) = tr.x(i) + tr.x(tr.par(i));
    tr.y(i) = tr.y(i) + tr.y(tr.par(i));
end

nodeIndex = 1 : tr.numNodes;
X = tr.x([nodeIndex;[tr.par(1:tr.numNodes-1) tr.numNodes]]);
Y = tr.y([nodeIndex;[tr.par(1:tr.numNodes-1) tr.numNodes]]); 
tr.txtAngle = cal_textAngle(tr);

fig = figure('Renderer','ZBuffer');
h.axes = axes; hold on;
sepUnit = max(tr.x)*[-1/20 21/20];

set(h.axes,'XTick',[],'YTick',[]);
set(h.axes,'Position',[.05 .05 .9 .9])
dispTerminalLabels = false;
axis equal

h.BranchLines = plot(X,Y,linestyle);

% resize figure if needed
temp = 10/pi*tr.numLeaves;
correctFigureSize(fig,temp,temp);
fontRatio = max(get(fig,'Position').*[0 0 1 0])/tr.numLeaves;
set(h.axes, 'Fontsize', fontsize);

% set leaf nodes labels
leafIndex = 1 : tr.numLeaves;
X = tr.x(leafIndex);
Y = tr.y(leafIndex);

txtangle = tr.txtAngle;

% % Rotate Label
h.leafNodeLabels = zeros(1, tr.numLeaves);
for i = 1:tr.numLeaves
    h.leafNodeLabels(i) = text(X(i),Y(i),tr.names(i), 'Rotation', txtangle(i));
end

set(h.leafNodeLabels,'color',fontcolor,'clipping','on')
if fontsizeset
    set(h.leafNodeLabels, 'Fontsize', fontsize);
else
    set(h.leafNodeLabels,'Fontsize',min(8,ceil(fontRatio*1.2)));
end
 
textHeight = mean(cell2mat(get(h.leafNodeLabels,'Extent')))*[0 0 0 1]';
for ind = 1:numel(h.leafNodeLabels)
    if X(ind) - tr.x(tr.par(ind)) < 0
        if txtangle(ind) < 90.0 - 0.001 || txtangle(ind) > 90.0 + 0.001
            set(h.leafNodeLabels(ind),'horizontal','right')
            set(h.leafNodeLabels(ind),'Position',get(h.leafNodeLabels(ind),'Position')+[sepUnit(1)*cos(txtangle(ind) * 2 * pi/360) sepUnit(1)*sin(txtangle(ind) * 2 * pi/360) 0])
        else
            if Y(ind) > 0 
                set(h.leafNodeLabels(ind),'Position',get(h.leafNodeLabels(ind),'Position')-[0 sepUnit(1) 0])
            else
                set(h.leafNodeLabels(ind),'Position',get(h.leafNodeLabels(ind),'Position')+[0 sepUnit(1) 0])
            end
        end
    else
        if txtangle(ind) < 90.0 - 0.001 || txtangle(ind) > 90.0 + 0.001
            set(h.leafNodeLabels(ind),'horizontal','left')
            set(h.leafNodeLabels(ind),'Position',get(h.leafNodeLabels(ind),'Position')-[sepUnit(1)*cos(txtangle(ind) * 2 * pi/360) sepUnit(1)*sin(txtangle(ind) * 2 * pi/360) 0])
        else
            if Y(ind) > 0 
                set(h.leafNodeLabels(ind),'Position',get(h.leafNodeLabels(ind),'Position')-[0 sepUnit(1) 0])
            else
                set(h.leafNodeLabels(ind),'Position',get(h.leafNodeLabels(ind),'Position')+[0 sepUnit(1) 0])
            end
        end
    end
end

dispLeafLabels = 1;
% correct axis limits given the extent of labels
if dispLeafLabels
    E = cell2mat(get(h.leafNodeLabels,'Extent'));
    if strcmp(get(gca,'XDir'),'reverse')
        E(:,1) = E(:,1) - E(:,3);
    end
    if strcmp(get(gca,'YDir'),'reverse')
        E(:,2) = E(:,2) - E(:,4);
    end
    E=[E;[xlim*[1;0] ylim*[1;0] diff(xlim) diff(ylim)]];
    mins = min(E(:,[1 2]));
    maxs = max([sum(E(:,[1 3]),2) sum(E(:,[2 4]),2)]);
    axis([mins(1) maxs(1) mins(2) maxs(2)])
end

if dispTerminalLabels
    set(h.terminalNodeLabels,'Fontsize',min(9,ceil(fontRatio/1.5)));  
end

box off
hold off

% store handles
set(fig,'UserData',h)   
if nargout
    handles = h;
end


%**************************************************************
% Count number of children for each node
function numChildren = ChildCount(par, numleafs, numnodes)
n = length(par);
numChildren = zeros(1, numnodes);
NoBranchStart = numleafs + 1;

for i = 1 : numleafs
    numChildren(par(i)) = numChildren(par(i)) + 1;
end

for i = NoBranchStart : n
    numChildren(par(i)) = numChildren(par(i)) + numChildren(i);
end
%**************************************************************

%*********************************************************************
function correctFigureSize(fig,recommendedHeight,recommendedWidth)
% helper function to increase initial figure size depending on the screen &
% tree sizes
screenSize = diff(reshape(get(0,'ScreenSize'),2,2),[],2)-[0;100];
            % 100 gives extra space for the figure header and win toolbar
position = get(fig,'Position');
if recommendedHeight > position(4)
    if recommendedHeight < sum(position([2 4]))
        position(2) = sum(position([2 4])) - recommendedHeight;
        position(4) = recommendedHeight;
    elseif recommendedHeight < screenSize(2)
        position(2) = 30; 
        position(4) = recommendedHeight;
    else 
        position(2) = 30; 
        position(4) = screenSize(2);
    end
end
if recommendedWidth > position(3)
    if recommendedWidth < sum(position([1 3]))
        position(1) = sum(position([1 3])) - recommendedWidth;
        position(3) = recommendedWidth;
    elseif recommendedWidth < screenSize(1)
        position(1) = 0; 
        position(3) = recommendedHeight;
    else 
        position(1) = 0; 
        position(3) = screenSize(1);
    end
end    
set(fig,'Position',position)
%*********************************************************************

%*********************************************************************
function [lefttree, righttree, thirdtree] = findsubtreeofnode(tr)

lefttree = zeros(tr.numBranches, tr.numNodes);
righttree = zeros(tr.numBranches, tr.numNodes);
thirdtree = zeros(tr.numBranches, tr.numNodes);

% thirdtree_left = zeros(tr.numBranches, tr.numNodes);
% thirdtree_right = zeros(tr.numBranches, tr.numNodes);

lefttree(1, 1) = tr.tree(1, 1);
righttree(1,1) = tr.tree(1, 2);
lefttree(1, tr.numNodes) = 1;
righttree(1, tr.numNodes) = 1;

for i = 2 : tr.numBranches
    j = 0; 
    tmp = tr.tree(i, 1);
    lefttree(i, 1) = tmp;
    lefttree(i, tr.numNodes) = 1;
    if tmp > tr.numLeaves
        lefttrlen = lefttree(tmp - tr.numLeaves, tr.numNodes);
        sub = lefttree(tmp - tr.numLeaves, 1 : lefttrlen);
        lefttree(i, 2 : lefttrlen + 2 - 1) = sub;
        
        righttrlen = righttree(tmp - tr.numLeaves, tr.numNodes);
        sub = righttree(tmp - tr.numLeaves, 1 : righttrlen);
        lefttree(i, lefttrlen + 3 - 1: lefttrlen + 3 - 1 + righttrlen - 1) = sub;  
        lefttree(i, tr.numNodes) = lefttrlen + righttrlen + lefttree(i, tr.numNodes);
    end
        
    j = 0;
    tmp = tr.tree(i, 2);
    righttree(i, 1) = tmp;
    righttree(i, tr.numNodes) = 1; 
    if tmp > tr.numLeaves
        lefttrlen = lefttree(tmp - tr.numLeaves, tr.numNodes);
        sub = lefttree(tmp - tr.numLeaves, 1 : lefttrlen);
        righttree(i, 2 : lefttrlen + 2 - 1) = sub;
        
        righttrlen = righttree(tmp - tr.numLeaves, tr.numNodes);
        sub = righttree(tmp - tr.numLeaves, 1 : righttrlen);
        righttree(i, lefttrlen + 3 - 1: lefttrlen + 3 - 1 + righttrlen - 1) = sub;  
        righttree(i, tr.numNodes) = lefttrlen + righttrlen + righttree(i, tr.numNodes);
    end        
end

% Third tree
node = 1 : tr.numLeaves;
for i = 1 : tr.numBranches
    tmp = [lefttree(i, 1:lefttree(i, tr.numNodes)), righttree(i, 1:righttree(i, tr.numNodes))];
    tf = ismember(node, tmp);
    tmp = node(find(tf == 0));
    tmp = tmp(find(tmp <= tr.numLeaves));
    nlength = length(tmp);
    thirdtree(i, 1 : nlength) = tmp;
    thirdtree(i, tr.numNodes) = nlength;
end

%*********************************************************************
function [treeangle, leftnode, rightnode] = caltreeangle(treenode, root, tr)
tmp = find(treenode <= tr.numLeaves);
leftnode = treenode(tmp(1));
rightnode = treenode(tmp(length(tmp)));

x0 = tr.x(root);
y0 = tr.y(root);
x1 = tr.x(leftnode);
y1 = tr.y(leftnode);
x2 = tr.x(rightnode);
y2 = tr.y(rightnode);

treeangle = cal_angle(x0, y0, x1, y1, x2, y2);
 
%*********************************************************************
function [subtree1, subtree2] = findsubtree(node, tr)
subtree1 = [];
subtree2 = [];

nodeindex = 1 : tr.numNodes;

i1 = 0;
i2 = 0;

flag1 = 0;
flag2 = 0;    

while ~flag1 || ~flag2
    nodetmp = find(tr.par == node);
    
    if nodetmp(1) <= tr.numLeaves
        subtree1 = [subtree1, nodetmp(1)];        
        i1 = i1 + 1;
        flag1 = 1;
    else
        if i1 == 0
            subtree1 = [subtree1, nodetmp(1)];
        end
        [subtr1, subtr2] = findsubtree(nodetmp(1), tr);
        flag1 = 1;
        subtree1 = [subtree1, subtr1, subtr2];        
    end
    
    if nodetmp(2) <= tr.numLeaves
        subtree2 = [subtree2, nodetmp(2)];
        i2 = i2 + 1;
        flag2 = 1;
    else
        if i2 == 0
            subtree2 = [subtree2, nodetmp(2)];
        end
        [subtr1, subtr2] = findsubtree(nodetmp(2), tr);
        flag2 = 1;
        subtree2 = [subtree2, subtr1, subtr2];
    end
end

%*********************************************************************
function leavenodes = findanothersubtree(node, tr)
nextnode = node;
cutpoint = tr.par(length(tr.par));
subtree = [];
tmpnode = nextnode;
nextnode = tr.par(nextnode);

while nextnode <= cutpoint
    [subtree1, subtree2] = findsubtree(nextnode, tr);
    if sum(find(subtree1 == node)) == 0
        subtree = [subtree, subtree1];
    else
        subtree = [subtree, subtree2];
    end    
    tmpnode = nextnode;
    if nextnode < cutpoint
        nextnode = tr.par(nextnode); 
    else 
        break;
    end
end
leavenodes = subtree(find(subtree <= tr.numLeaves));
    
%*********************************************************************
function slope = cal_slope(x1, y1, x2, y2)
if x1 == x2
    slope = tan(pi/2);
else
    slope = (y2 - y1)/(x2 - x1);
end

%*********************************************************************
function xangle = cal_angle(x0, y0, x1, y1, x2, y2)
k1 = cal_slope(x0, y0, x1, y1);
k2 = cal_slope(x0, y0, x2, y2);
xangle = atan(abs((k2 - k1)/(1 + k1 * k2)));

%*********************************************************************
function [leftnode, rightnode, xangle] = cal_thr_angle(trnode, node, tr)
leftnode = 0;
rightnode = 0; 
xangle = 0;

n = length(trnode);
if n == 1
    leftnode = trnode(1);
    rightnode = trnode(1);
    xangle = 0;
    return;
end

x0 = tr.x(node);
y0 = tr.y(node);

for i = 1 : n - 1
    x1 = tr.x(trnode(i));
    y1 = tr.y(trnode(i));    
    k1 = cal_slope(x0, y0, x1, y1);
    for j = i + 1 : n
        x2 = tr.x(trnode(j));
        y2 = tr.y(trnode(j));
        k2 = cal_slope(x0, y0, x2, y2);
        theta = atan(abs((k2 - k1)/(1 + k1 * k2)));
        if xangle < theta
            xangle = theta;
            leftnode = trnode(i);
            rightnode = trnode(j);
        end
    end
end

%*********************************************************************
function [left, right] = leftnrightnode(subtree, tr)
lefttree = tr.tree(:, 1);
righttree = tr.tree(:, 2);

left = 0;
right = 0;
numindex = length(lefttree);
i = 1;
for i = 1 : numindex
    [tf, index] = ismember(lefttree(i), subtree);
    if tf == 1 
        left = lefttree(i);
        break;
    end
end

for i = 1 : numindex
    [tf, index] = ismember(righttree(i), subtree);
    if tf == 1
        right = righttree(i);
        break;
    end
end

if left == 0
    left = right;
end
if right == 0 
    right = left;
end

%*********************************************************************
function nodeangle = cal_nodeangle(y, x)
nodeangle = atan2(y, x);
if nodeangle < 0
    nodeangle = 2*pi + nodeangle;
end

%*********************************************************************
function tree = adjustsubtreeangle(subtr1, subtr2, subtr3, orgnode, tr)

tr1node = subtr1(find(subtr1 <= tr.numLeaves));
tr2node = subtr2(find(subtr2 <= tr.numLeaves));

tr.x(subtr1) = tr.x(subtr1) - tr.x(orgnode);
tr.y(subtr1) = tr.y(subtr1) - tr.y(orgnode);

tr.x(subtr2) = tr.x(subtr2) - tr.x(orgnode);
tr.y(subtr2) = tr.y(subtr2) - tr.y(orgnode);

tr.x(subtr3) = tr.x(subtr3) - tr.x(orgnode);
tr.y(subtr3) = tr.y(subtr3) - tr.y(orgnode);

[tree1left, tree1right] = leftnrightnode(tr1node, tr);
[tree2left, tree2right] = leftnrightnode(tr2node, tr);
tr3node = subtr3;%leftnrightnode(subtr3, tr);
tree3left = tr3node(1);
tree3right = tr3node(2);    

a1left = cal_nodeangle(tr.y(tree1left), tr.x(tree1left));
a1right = cal_nodeangle(tr.y(tree1right), tr.x(tree1right));

a2left = cal_nodeangle(tr.y(tree2left), tr.x(tree2left));
a2right = cal_nodeangle(tr.y(tree2right), tr.x(tree2right));

a3left = cal_nodeangle(tr.y(tree3left), tr.x(tree3left));
a3right = cal_nodeangle(tr.y(tree3right), tr.x(tree3right));

daylight = [a1right - a3left, a2right - a1left, a3right - a2left];
equaldaylight = sum(abs(daylight))/3;

adjust1n3 = equaldaylight - daylight(1);
adjust2n3 = daylight(3) - equaldaylight;

% Rotation --- subtr1
a = tr.x(subtr1);
b = tr.y(subtr1);
if adjust1n3 ~= 0
    tr.x(subtr1) = a * cos(adjust1n3) - b * sin(adjust1n3);
    tr.y(subtr1) = a * sin(adjust1n3) + b * cos(adjust1n3);
end

% Rotation --- subtr2
a = tr.x(subtr2);
b = tr.y(subtr2);
if adjust2n3 ~= 0
    tr.x(subtr2) = a * cos(adjust2n3) - b * sin(adjust2n3);
    tr.y(subtr2) = a * sin(adjust2n3) + b * cos(adjust2n3);
end

tr.x(subtr1) = tr.x(subtr1) + tr.x(orgnode);
tr.y(subtr1) = tr.y(subtr1) + tr.y(orgnode);

tr.x(subtr2) = tr.x(subtr2) + tr.x(orgnode);
tr.y(subtr2) = tr.y(subtr2) + tr.y(orgnode);

tr.x(subtr3) = tr.x(subtr3) + tr.x(orgnode);
tr.y(subtr3) = tr.y(subtr3) + tr.y(orgnode);

tree = tr;

%*********************************************************************
function tree = adjusttree(lefttree, righttree, thirdtree, node, tr)

tr1 = lefttree(node - tr.numLeaves, 1 : lefttree(node - tr.numLeaves, tr.numNodes));
tr2 = righttree(node - tr.numLeaves, 1 : righttree(node - tr.numLeaves, tr.numNodes));
tr3 = thirdtree(node - tr.numLeaves, 1 : thirdtree(node - tr.numLeaves, tr.numNodes));
[lefttreeangle, l_leftnode, l_rightnode] = caltreeangle(tr1, node, tr);
[righttreeangle, r_leftnode, r_rightnode] = caltreeangle(tr2, node, tr);
[thr_leftnode, thr_rightnode, xangle] = cal_thr_angle(tr3, node, tr);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
d1 = sqrt((tr.x(l_rightnode) - tr.x(thr_leftnode)) * (tr.x(l_rightnode) - tr.x(thr_leftnode)) + (tr.y(l_rightnode) -tr.y(thr_leftnode)) * (tr.y(l_rightnode) -tr.y(thr_leftnode)));
d2 = sqrt((tr.x(l_rightnode) - tr.x(thr_rightnode)) * (tr.x(l_rightnode) - tr.x(thr_rightnode)) + (tr.y(l_rightnode) -tr.y(thr_rightnode)) * (tr.y(l_rightnode) -tr.y(thr_rightnode)));

if d2 > d1
    tmp = thr_leftnode;
    thr_leftnode = thr_rightnode;
    thr_rightnode = tmp;
end

% daylight = 2 * pi - lefttreeangle - righttreeangle - xangle;
% equaldaylight = daylight / 3;

[angle1to3, angle2to3, angle1to2] = cal_daylight(l_leftnode, l_rightnode, r_leftnode, r_rightnode, thr_leftnode, thr_rightnode, node, tr);

daylight = angle1to3 + angle2to3 + angle1to2;
equaldaylight = daylight / 3;

adjust1n3 = equaldaylight - angle1to3;
adjust2n3 = angle2to3 - equaldaylight;

tr.x(tr1) = tr.x(tr1) - tr.x(node);
tr.y(tr1) = tr.y(tr1) - tr.y(node);

tr.x(tr2) = tr.x(tr2) - tr.x(node);
tr.y(tr2) = tr.y(tr2) - tr.y(node);

% Rotation --- subtr1
a = tr.x(tr1);
b = tr.y(tr1);
if adjust1n3 ~= 0
    tr.x(tr1) = a * cos(adjust1n3) - b * sin(adjust1n3);
    tr.y(tr1) = a * sin(adjust1n3) + b * cos(adjust1n3);
end

% Rotation --- subtr2
a = tr.x(tr2);
b = tr.y(tr2);
if adjust2n3 ~= 0
    tr.x(tr2) = a * cos(adjust2n3) - b * sin(adjust2n3);
    tr.y(tr2) = a * sin(adjust2n3) + b * cos(adjust2n3);
end

tr.x(tr1) = tr.x(tr1) + tr.x(node);
tr.y(tr1) = tr.y(tr1) + tr.y(node);

tr.x(tr2) = tr.x(tr2) + tr.x(node);
tr.y(tr2) = tr.y(tr2) + tr.y(node);

tree = tr;

%*********************************************************************
function [angle1to3, angle2to3, angle1to2] = cal_daylight(l_leftnode, l_rightnode, r_leftnode, r_rightnode, thr_leftnode, thr_rightnode, node, tr)

x0 = tr.x(node);
y0 = tr.y(node);

llx = tr.x(l_leftnode);
lly = tr.y(l_leftnode);
lrx = tr.x(l_rightnode);
lry = tr.y(l_rightnode);
rlx = tr.x(r_leftnode);
rly = tr.y(r_leftnode);
rrx = tr.x(r_rightnode);
rry = tr.y(r_rightnode);

tlx = tr.x(thr_leftnode);
tly = tr.y(thr_leftnode);
trx = tr.x(thr_rightnode);
tryy = tr.y(thr_rightnode);

angle1to3 = cal_angle(x0, y0, llx, lly, trx, tryy);
angle2to3 = cal_angle(x0, y0, rrx, rry, tlx, tly);
angle1to2 = cal_angle(x0, y0, lrx, lry, rlx, rly);

%*********************************************************************
function txtAngle = cal_textAngle(tr)
nodeIndex = 1 : tr.numLeaves;
X = tr.x(nodeIndex) - tr.x(tr.par(nodeIndex));
Y = tr.y(nodeIndex) - tr.y(tr.par(nodeIndex)); 

txtAngle = atan(Y./X) * 360/(2*pi);

Contact us