function handles = phytree_plot(tr,varargin)
%PLOT renders a phylogenetic tree.
% Plot a phylogenetic tree. Like Matlab's 'plot', but enable different branch colors.
%
%   PLOT(TREE) renders a phylogenetic tree object into a MATLAB figure as a
%   phylogram. The significant distances between branches and nodes are in
%   horizontal direction, vertical coordinates are accommodated only for
%   display purposes. Handles to graph elements are stored in the
%   'UserData' figure field, such that graphic properties can be easily
%   modified.
%
%   PLOT(TREE,ACTIVEBRANCHES) hides the non'active branches and all their
%   descendants. ACTIVEBRANCHES is a logical array of size
%   [numBranches x 1] indicating the active branches.
%
%   PLOT(...,'TYPE',type) selects the method to render the phylogenetic
%   tree. Options are: 'square' (default), 'angular', and 'radial'.
%
%   PLOT(...,'ORIENTATION',orient) will orient the phylogenetic tree within
%   the figure window. Options are: 'top', 'bottom', 'left' (default), and,
%   'right'. Orientation parameter is valid only for phylograms or
%   cladograms.
%
%   PLOT(...,'BRANCHLABELS',value) hides/unhides branch labels. Options are
%   true or false. Branch labels are placed next to the branch node.
%   Defaults to false (true) when TYPE is (is not) 'radial'.
%
%   PLOT(...,'LEAFLABELS',value) hides/unhides leaf labels. Options are
%   true or false. Leaf labels are placed next to the leaf nodes. Defaults
%   to false (true) when TYPE is (is not) 'radial'.
%
%   PLOT(...,'TERMINALLABELS',value) hides/unhides terminal labels. Options
%   are true (default) or false. Terminal labels are placed over the axis
%   tick labels, ignored when 'radial' type is used.
%
%   H = PLOT(...) returns a structure with handles to the graph elements.
%
%   Example:
%
%       tr = phytreeread('pf00002.tree')
%       plot(tr,'type','radial')
%
%       % Graph element properties can be modified as follows:
%
%       h=get(gcf,'UserData')
%       set(h.branchNodeLabels,'FontSize',6,'Color',[.5 .5 .5])
%
%   See also PHYTREE, PHYTREE/VIEW, PHYTREEREAD, PHYTREETOOL, SEQLINKAGE.

% Copyright 2003-2006 The MathWorks, Inc.
% $Revision: 1.1.6.10 $ $Author: batserve $ $Date: 2006/06/16 20:06:45 $
%
% Changed by Or Zuk 06/2008, to enable drawing colored branches

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

% set defaults
dispBranchLabels = NaN;
dispLeafLabels = NaN;
dispTerminalLabels = true;
renderType = 'square';
orientation = 'left';
rotation = 0;
new_fig_flag = 1; % default is having a new figure 

tr = struct(tr);
tr.numBranches = size(tr.tree,1);

if nargin>1 && islogical(varargin{1})
    activeBranches = varargin{1};
    argStart = 2;
else
    activeBranches = true(tr.numBranches,1);
    argStart = 1;
end

if nargin - argStart > 0
    if rem(nargin - argStart,2) == 1
        error('Bioinfo:phytree:plot:IncorrectNumberOfArguments',...
            'Incorrect number of arguments to %s.',mfilename);
    end
    okargs = {'type','orientation','rotation',...
        'branchlabels','leaflabels','terminallabels', 'weights', 'new_fig'}; % New! added weights! 
    for j = argStart:2:nargin-argStart
        pname = varargin{j};
        pval = varargin{j+1};
        k = find(strncmpi(pname,okargs,numel(pname)));
        if isempty(k)
            error('Bioinfo:phytree:plot:UnknownParameterName',...
                'Unknown parameter name: %s.',pname);
        elseif length(k)>1
            error('Bioinfo:phytree:plot:AmbiguousParameterName',...
                'Ambiguous parameter name: %s.',pname);
        else
            switch(k)
                case 1 % type
                    oktypes={'square','angular','radial'};
                    l = strmatch(lower(pval),oktypes); %#ok
                    if isempty(l)
                        error('Bioinfo:phytree:plot:UnknownTypeName',...
                            'Unknown option for %s.',upper(okargs{k}));
                    else
                        if l==4
                            l=1;
                        end
                        renderType = oktypes{l};
                    end
                case 2 % orientation
                    oktypes={'left','right','top','bottom'};
                    l = strmatch(lower(pval),oktypes); %#ok
                    if isempty(l)
                        error('Bioinfo:phytree:plot:UnknownOrientation',...
                            'Unknown option for %s.',upper(okargs{k}));
                    else
                        orientation = oktypes{l};
                    end
                case 3 % rotation
                    if isreal(pval(1))
                        rotation = double(pval(1));
                    else
                        error('Bioinfo:phytree:plot:NotValidType',...
                            'ROTATION must be numeric and real');
                    end
                case 4 % branch labels
                    dispBranchLabels = opttf(pval);
                case 5 % leaf labels
                    dispLeafLabels = opttf(pval);
                case 6 % terminal labels
                    dispTerminalLabels = opttf(pval);
                case 7 % weights 
                    weights = pval; % numeric 
                case 8 % new figure false
                    new_fig_flag = 0;
            end
        end
    end
end

% set dependent defaults
if isnan(dispBranchLabels)
    if isequal(renderType,'radial')
        dispBranchLabels = true;
    else
        dispBranchLabels = false;
    end
end
if isnan(dispLeafLabels)
    if isequal(renderType,'radial')
        dispLeafLabels = true;
    else
        dispLeafLabels = false;
    end
end

tr = doBasicCalculations(tr,activeBranches,renderType);

nodeIndex   = 1:tr.numLabels;
leafIndex   = 1:tr.numLeaves;
branchIndex = tr.numLeaves+1:tr.numLabels;


% check empty names
for ind = nodeIndex
    if isempty(tr.names{ind})
        if ind > tr.numLeaves
            tr.names{ind} = ['Branch ' num2str(ind-tr.numLeaves)];
        else
            tr.names{ind} = ['Leaf ' num2str(ind)];
        end
    end
end

% rendering graphic objects
if(new_fig_flag)
    fig = figure('Renderer','ZBuffer');
else 
    fig = gcf;
end
h.axes = axes; hold on;  % This is problematic: ruins subplot 
sepUnit = max(tr.x)*[-1/20 21/20];

% setting the axes
switch renderType
    case {'square','angular'}
        switch orientation
            case 'left'
                set(h.axes,'YTick',1:numel(tr.terminalNodes),'Ydir','reverse',...
                    'YtickLabel','','YAxisLocation','Right')
                if dispTerminalLabels
                    set(h.axes,'Position',[.05 .10 .7 .85])
                else
                    set(h.axes,'Position',[.05 .10 .9 .85])
                end
                xlim(sepUnit);
                ylim([0 numel(tr.terminalNodes)+1]);
            case 'right'
                set(h.axes,'YTick',1:numel(tr.terminalNodes),'Xdir','reverse','Ydir','reverse',...
                    'YtickLabel','','YAxisLocation','Left')
                if dispTerminalLabels
                    set(h.axes,'Position',[.25 .10 .7 .85])
                else
                    set(h.axes,'Position',[.05 .10 .9 .85])
                end
                xlim(sepUnit);
                ylim([0 numel(tr.terminalNodes)+1]);
            case 'top'
                set(h.axes,'XTick',1:numel(tr.terminalNodes),...
                    'XtickLabel','','XAxisLocation','Top')
                if dispTerminalLabels
                    set(h.axes,'Position',[.10 .05 .85 .7])
                else
                    set(h.axes,'Position',[.10 .05 .85 .9])
                end
                ylim(sepUnit);
                xlim([0 numel(tr.terminalNodes)+1]);
            case 'bottom'
                set(h.axes,'XTick',1:numel(tr.terminalNodes),'Ydir','reverse',...
                    'XtickLabel','','XAxisLocation','Bottom')
                if dispTerminalLabels
                    set(h.axes,'Position',[.10 .25 .85 .7])
                else
                    set(h.axes,'Position',[.10 .05 .85 .9])
                end
                ylim(sepUnit);
                xlim([0 numel(tr.terminalNodes)+1]);
        end
    case 'radial'
        set(h.axes,'XTick',[],'YTick',[])
        set(h.axes,'Position',[.05 .05 .9 .9])
        dispTerminalLabels = false;
        axis equal
end

% drawing lines
switch renderType
    case 'square'
        X = tr.x([nodeIndex;repmat([tr.par(1:tr.numLabels-1) tr.numLabels],2,1)]);
        Y = tr.y([repmat(nodeIndex,2,1);[tr.par(1:tr.numLabels-1) tr.numLabels]]);
        hold on;
    case 'angular'
        X = tr.x([nodeIndex;[tr.par(1:tr.numLabels-1) tr.numLabels]]);
        Y = tr.y([nodeIndex;[tr.par(1:tr.numLabels-1) tr.numLabels]]);
    case 'radial'
        R = tr.x;
        A = tr.y / numel(tr.terminalNodes)*2*pi+rotation*pi/180;
        tr.x = R .* sin(A);
        tr.y = R .* cos(A);
        X = tr.x([nodeIndex;[tr.par(1:tr.numLabels-1) tr.numLabels]]);
        Y = tr.y([nodeIndex;[tr.par(1:tr.numLabels-1) tr.numLabels]]);
end
switch orientation % Note: do not use bottom/top orientation with radial type!!!
    case {'left','right'}
        h.BranchLines = plot(X,Y,'-k');
    case {'top','bottom'}
        if(strmatch('radial', renderType, 'exact'))
            h.BranchLines = plot(X,Y,'-k');
        else
            h.BranchLines = plot(Y,X,'-k');
            tmp_X = Y; Y = X; X = tmp_X;
        end
end
delete(h.BranchLines(~tr.activeNodes));
h.BranchLines = h.BranchLines(tr.activeNodes);

if(exist('weights', 'var')) % New: check if we have also weights information.
    n = size(X, 2); linewidth = 0.5; 
    color_mat = colormap; ncolors = size(color_mat,1); % 64 colors
    min_w = min(weights(weights>0)), max_w = max(weights(:)), range_w = max_w - min_w; 
    k_max = min(range_w / min_w, 10); % set maximum line width
    
    for i=1:n % loop over branches and color them
        line([X(1,i), X(2,i)], [Y(1,i), Y(2,i)], ...
            'Color', color_mat(   max(1,ceil( ncolors * (weights(i) - min_w) / range_w  )),: ), ...
            'LineWidth', linewidth + (weights(i) - min_w) * (k_max-1)*linewidth / range_w  ); % draw the horizonal lines
        switch renderType
            case 'square'
                line([X(2,i), X(3,i)], [Y(2,i), Y(3,i)], ...
                    'Color', color_mat(   max(1,ceil( ncolors * (weights(i) - min_w) / range_w  )),: ), ...
                    'LineWidth', linewidth + (weights(i) - min_w) * (k_max-1)*linewidth / range_w   ); % draw the vertical lines
        end
    end
end

% drawing nodes
switch renderType
    case {'square','angular'}
        switch orientation
            case {'left','right'}
                h.BranchDots = plot(tr.x(branchIndex(tr.activeNodes(branchIndex))),...
                    tr.y(branchIndex(tr.activeNodes(branchIndex))),'o',...
                    'MarkerSize',5,'MarkerEdgeColor','k',...
                    'MarkerFaceColor','b');
                h.LeafDots = plot(tr.x(leafIndex(tr.activeNodes(leafIndex))),...
                    tr.y(leafIndex(tr.activeNodes(leafIndex))),'square',...
                    'MarkerSize',4,'MarkerEdgeColor','k',...
                    'MarkerFaceColor','w');
            case {'top','bottom'}
                h.BranchDots = plot(tr.y(branchIndex(tr.activeNodes(branchIndex))),...
                    tr.x(branchIndex(tr.activeNodes(branchIndex))),'o',...
                    'MarkerSize',5,'MarkerEdgeColor','k',...
                    'MarkerFaceColor','b');
                h.LeafDots = plot(tr.y(leafIndex(tr.activeNodes(leafIndex))),...
                    tr.x(leafIndex(tr.activeNodes(leafIndex))),'square',...
                    'MarkerSize',4,'MarkerEdgeColor','k',...
                    'MarkerFaceColor','w');
        end
    case 'radial'
        h.BranchDots = plot(tr.x(branchIndex(tr.activeNodes(branchIndex))),...
            tr.y(branchIndex(tr.activeNodes(branchIndex))),'o',...
            'MarkerSize',5,'MarkerEdgeColor','k',...
            'MarkerFaceColor','b');
        h.LeafDots = plot(tr.x(leafIndex(tr.activeNodes(leafIndex))),...
            tr.y(leafIndex(tr.activeNodes(leafIndex))),'square',...
            'MarkerSize',4,'MarkerEdgeColor','k',...
            'MarkerFaceColor','w');
end

if(exist('weights', 'var'))
    colorbar('WestOutside', 'YTickLabel', [min_w:(range_w/10):max_w]);
end

% resize figure if needed
switch renderType
    case {'square','angular'}
        switch orientation
            case {'left','right'}
                correctFigureSize(fig, 15 * numel(tr.terminalNodes),0);
                fontRatio = max(get(fig,'Position').*[0 0 0 1])/numel(tr.terminalNodes);
            case {'top','bottom'}
                correctFigureSize(fig, 0, 15 * numel(tr.terminalNodes));
                fontRatio = max(get(fig,'Position').*[0 0 1 0])/numel(tr.terminalNodes);
        end
    case 'radial'
        temp = 10/pi*numel(tr.terminalNodes);
        correctFigureSize(fig,temp,temp);
        fontRatio = max(get(fig,'Position').*[0 0 1 0])/numel(tr.terminalNodes);
end

set(h.axes,'Fontsize',min(9,ceil(fontRatio/1.5)));

% set branch node labels
X = tr.x(branchIndex(tr.activeNodes(tr.numLeaves+1:tr.numLabels)));
Y = tr.y(branchIndex(tr.activeNodes(tr.numLeaves+1:tr.numLabels)));
switch renderType
    case {'square','angular'}
        switch orientation
            case {'left'}
                h.branchNodeLabels = text(X+sepUnit(1)/2,Y,tr.names(branchIndex(tr.activeNodes(tr.numLeaves+1:tr.numLabels))));
                set(h.branchNodeLabels,'color',[0 0 .8],'clipping','on')
                set(h.branchNodeLabels,'vertical','bottom')
                set(h.branchNodeLabels,'horizontal','right')
                set(h.branchNodeLabels,'Fontsize',min(8,ceil(fontRatio/2)));
            case {'right'}
                h.branchNodeLabels = text(X+sepUnit(1)/2,Y,tr.names(branchIndex(tr.activeNodes(tr.numLeaves+1:tr.numLabels))));
                set(h.branchNodeLabels,'color',[0 0 .8],'clipping','on')
                set(h.branchNodeLabels,'vertical','bottom')
                set(h.branchNodeLabels,'Fontsize',min(8,ceil(fontRatio/2)));
            case {'top'}
                h.branchNodeLabels = text(Y,X-sepUnit(1)/2,tr.names(branchIndex(tr.activeNodes(tr.numLeaves+1:tr.numLabels))));
                set(h.branchNodeLabels,'color',[0 0 .8],'clipping','on')
                set(h.branchNodeLabels,'vertical','bottom','Rotation',30)
                set(h.branchNodeLabels,'Fontsize',min(8,ceil(fontRatio/2)));
            case {'bottom'}
                h.branchNodeLabels = text(Y,X+sepUnit(1)/2,tr.names(branchIndex(tr.activeNodes(tr.numLeaves+1:tr.numLabels))));
                set(h.branchNodeLabels,'color',[0 0 .8],'clipping','on')
                set(h.branchNodeLabels,'vertical','bottom','Rotation',30)
                set(h.branchNodeLabels,'Fontsize',min(8,ceil(fontRatio/2)));
        end
    case 'radial'
        h.branchNodeLabels = text(X,Y,tr.names(branchIndex(tr.activeNodes(tr.numLeaves+1:tr.numLabels))));
        set(h.branchNodeLabels,'color',[0 0 .8],'clipping','on')
        set(h.branchNodeLabels,'vertical','bottom')
        set(h.branchNodeLabels,'Fontsize',min(8,ceil(fontRatio*1.2)));
        for ind = 1:numel(h.branchNodeLabels)
            if X(ind)<0
                set(h.branchNodeLabels(ind),'horizontal','right')
                set(h.branchNodeLabels(ind),'Position',get(h.branchNodeLabels(ind),'Position')+[sepUnit(1)/2 0 0])
            else
                set(h.branchNodeLabels(ind),'horizontal','left')
                set(h.branchNodeLabels(ind),'Position',get(h.branchNodeLabels(ind),'Position')-[sepUnit(1)/2 0 0])
            end
        end
end

% set leaf nodes labels
X = tr.x(leafIndex(tr.activeNodes(1:tr.numLeaves)));
Y = tr.y(leafIndex(tr.activeNodes(1:tr.numLeaves)));
switch renderType
    case {'square','angular'}
        switch orientation
            case {'left'}
                h.leafNodeLabels = text(X-sepUnit(1)/2,Y,tr.names(leafIndex(tr.activeNodes(1:tr.numLeaves))));
                set(h.leafNodeLabels,'color',[.5 .5 .5],'clipping','on')
                set(h.leafNodeLabels,'horizontal','left')
                set(h.leafNodeLabels,'Fontsize',min(8,ceil(fontRatio/2)));
            case {'right'}
                h.leafNodeLabels = text(X-sepUnit(1)/2,Y,tr.names(leafIndex(tr.activeNodes(1:tr.numLeaves))));
                set(h.leafNodeLabels,'color',[.5 .5 .5],'clipping','on')
                set(h.leafNodeLabels,'horizontal','right')
                set(h.leafNodeLabels,'Fontsize',min(8,ceil(fontRatio/2)));
            case {'top'}
                h.leafNodeLabels = text(Y,X-sepUnit(1)/2,tr.names(leafIndex(tr.activeNodes(1:tr.numLeaves))));
                set(h.leafNodeLabels,'color',[.5 .5 .5],'clipping','on')
                set(h.leafNodeLabels,'horizontal','left','Rotation',60)
                set(h.leafNodeLabels,'Fontsize',min(8,ceil(fontRatio/2)));
            case {'bottom'}
                h.leafNodeLabels = text(Y,X-sepUnit(1),tr.names(leafIndex(tr.activeNodes(1:tr.numLeaves))));
                set(h.leafNodeLabels,'color',[.5 .5 .5],'clipping','on')
                set(h.leafNodeLabels,'horizontal','right','Rotation',60)
                set(h.leafNodeLabels,'Fontsize',min(8,ceil(fontRatio/2)));
        end
    case 'radial'
        h.leafNodeLabels = text(X,Y,tr.names(leafIndex(tr.activeNodes(1:tr.numLeaves))));
        set(h.leafNodeLabels,'color',[.5 .5 .5],'clipping','on')
        set(h.leafNodeLabels,'Fontsize',min(8,ceil(fontRatio*1.2)));
        % textHeight = mean(cell2mat(get(h.leafNodeLabels,'Extent')))*[0 0 0 1]';
        for ind = 1:numel(h.leafNodeLabels)
            if X(ind)<0
                set(h.leafNodeLabels(ind),'horizontal','right')
                set(h.leafNodeLabels(ind),'Position',get(h.leafNodeLabels(ind),'Position')+[sepUnit(1) 0 0])
            else
                set(h.leafNodeLabels(ind),'horizontal','left')
                set(h.leafNodeLabels(ind),'Position',get(h.leafNodeLabels(ind),'Position')-[sepUnit(1) 0 0])
            end
            %             a=atan(Y(ind)/X(ind))*180/pi;
            %             if a > 0  a = max(0,a-60)/2; else
            %                       a = min(0,a+60)/2; end
            %             set(h.leafNodeLabels(ind),'Rotation',a)
        end
        [sortedY,hsY]=sort(Y);
        idx=hsY(X(hsY)>0 & sortedY>0);
        if numel(idx)
            extentY = get(h.leafNodeLabels(idx(1)),'Extent')*[0;0;0;1];
            positionY = get(h.leafNodeLabels(idx(1)),'Position')*[0;1;0];
            for i = 2:numel(idx)
                position = get(h.leafNodeLabels(idx(i)),'Position');
                positionY = max(positionY+extentY,position(2));
                position(2) = positionY;
                set(h.leafNodeLabels(idx(i)),'Position',position)
            end
        end
        idx=hsY(X(hsY)<0 & sortedY>0);
        if numel(idx)
            extentY = get(h.leafNodeLabels(idx(1)),'Extent')*[0;0;0;1];
            positionY = get(h.leafNodeLabels(idx(1)),'Position')*[0;1;0];
            for i = 2:numel(idx)
                position = get(h.leafNodeLabels(idx(i)),'Position');
                positionY = max(positionY+extentY,position(2));
                position(2) = positionY;
                set(h.leafNodeLabels(idx(i)),'Position',position)
            end
        end
        idx=flipud(hsY(X(hsY)>0 & sortedY<0));
        if numel(idx)
            extentY = get(h.leafNodeLabels(idx(1)),'Extent')*[0;0;0;1];
            positionY = get(h.leafNodeLabels(idx(1)),'Position')*[0;1;0];
            for i = 2:numel(idx)
                position = get(h.leafNodeLabels(idx(i)),'Position');
                positionY = min(positionY-extentY,position(2));
                position(2) = positionY;
                set(h.leafNodeLabels(idx(i)),'Position',position)
            end
        end
        idx=flipud(hsY(X(hsY)<0 & sortedY<0));
        if numel(idx)
            extentY = get(h.leafNodeLabels(idx(1)),'Extent')*[0;0;0;1];
            positionY = get(h.leafNodeLabels(idx(1)),'Position')*[0;1;0];
            for i = 2:numel(idx)
                position = get(h.leafNodeLabels(idx(i)),'Position');
                positionY = min(positionY-extentY,position(2));
                position(2) = positionY;
                set(h.leafNodeLabels(idx(i)),'Position',position)
            end
        end

end

% correct axis limits given the extent of labels
if dispBranchLabels
    E = cell2mat(get(h.branchNodeLabels,'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 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

% set terminal nodes labels
switch renderType
    case {'square','angular'}
        X = tr.x(tr.terminalNodes) * 0;
        Y = tr.y(tr.terminalNodes);
        switch orientation
            case {'left'}
                X = X + max(xlim) - sepUnit(1)/2;
                h.terminalNodeLabels = text(X,Y,tr.names(tr.terminalNodes));
            case {'right'}
                X = X + max(xlim) - sepUnit(1)/2;
                h.terminalNodeLabels = text(X,Y,tr.names(tr.terminalNodes));
                set(h.terminalNodeLabels,'Horizontal','right')
            case {'top'}
                X = X + max(ylim) - sepUnit(1)/2;
                h.terminalNodeLabels = text(Y,X,tr.names(tr.terminalNodes));
                set(h.terminalNodeLabels,'Rotation',90)
            case {'bottom'}
                X = X + max(ylim) - sepUnit(1)/2;
                h.terminalNodeLabels = text(Y,X,tr.names(tr.terminalNodes));
                set(h.terminalNodeLabels,'Rotation',270)
        end
    case 'radial'
        h.terminalNodeLabels = text(0,0,' ');
end

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

if ~dispBranchLabels
    set(h.branchNodeLabels,'visible','off');
end
if ~dispLeafLabels
    set(h.leafNodeLabels,'visible','off');
end
if ~dispTerminalLabels
    set(h.terminalNodeLabels,'visible','off');
end

box on
hold off

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

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function tr = doBasicCalculations(tr,activeBranches,renderType)

% helper function to compute and find some features of the tree
tr.numLeaves = tr.numBranches + 1;
tr.numLabels = tr.numBranches + tr.numLeaves;

% remove uderscores from names
for ind = 1:tr.numLabels
    tr.names{ind}(tr.names{ind}=='_')=' ';
end

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

% find active nodes
tr.activeNodes = true(tr.numLabels,1);
for ind =tr.numBranches:-1:1
    tr.activeNodes(tr.tree(ind,:)) = tr.activeNodes(tr.numLeaves+ind) & activeBranches(ind);
end

% propagate last leaf
tr.lastleaf = 1:tr.numLabels;
for ind = tr.numBranches:-1:1
    if ~tr.activeNodes(tr.tree(ind,1))
        tr.lastleaf(tr.tree(ind,:))=tr.lastleaf(ind+tr.numLeaves);
    end
end

tr.activeBranches = tr.activeNodes(tr.numLeaves+1:tr.numLabels)&activeBranches;
tr.activeLeaves = tr.activeNodes(1:tr.numLeaves);

% find x coordinates of branches
tr.x = tr.dist;
for ind = tr.numBranches:-1:1
    tr.x(tr.tree(ind,:)) = tr.x(tr.tree(ind,:)) + tr.x(ind+tr.numLeaves);
end

% find y coordinates of branches
tr.terminalNodes = tr.lastleaf([true,diff(tr.lastleaf(1:tr.numLeaves))~=0]);
tr.y=zeros(tr.numLabels,1);
tr.y(tr.terminalNodes)=1:length(tr.terminalNodes);
switch renderType
    case 'square'
        for ind = 1:tr.numBranches
            if tr.activeBranches(ind)
                tr.y(ind+tr.numLeaves) = mean(tr.y(tr.tree(ind,:)));
            end
        end
    case {'angular','radial'}
        for ind = 1:tr.numBranches
            if tr.activeBranches(ind)
                if tr.x(tr.tree(ind,1))/tr.x(tr.tree(ind,2))>3
                    tr.y(ind+tr.numLeaves) = tr.y(tr.tree(ind,1));
                elseif tr.x(tr.tree(ind,2))/tr.x(tr.tree(ind,1))>3
                    tr.y(ind+tr.numLeaves) = tr.y(tr.tree(ind,2));
                else
                    tr.y(ind+tr.numLeaves) = mean(tr.y(tr.tree(ind,:)));
                end
            end
        end
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)
