Added source Matlab code for reference
This commit is contained in:
parent
b8af977117
commit
b5d99903d2
186 changed files with 61405 additions and 1 deletions
206
matlab/graph/@phyTree/reRoot.m
Normal file
206
matlab/graph/@phyTree/reRoot.m
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
function tr = reRoot(tr,node,distance)
|
||||
%REROOT changes the root of a phylogenetic tree.
|
||||
%
|
||||
% T2 = REROOT(T1) changes the root of the phylogenetic tree T1 using the
|
||||
% mid-point method. The mid-point is the location where the means of
|
||||
% the branch lengths of either side of the tree are equalized. The
|
||||
% original root is deleted.
|
||||
%
|
||||
% T2 = REROOT(T1,NODE) changes the root to the branch indexed by NODE.
|
||||
% The new root is placed at half the distance between NODE and its
|
||||
% parent.
|
||||
%
|
||||
% T2 = REROOT(T1,NODE,DISTANCE) re-roots T1 by placing the new root at a
|
||||
% given DISTANCE from the reference NODE towards the root of the tree.
|
||||
%
|
||||
% Note: The new branch in T2 representing the root is labeled as 'Root'.
|
||||
%
|
||||
% Example:
|
||||
%
|
||||
% % Create an ultrametric tree
|
||||
% tr_1 = phytree([5 7;8 9;6 11; 1 2;3 4;10 12;14 16;15 17;13 18])
|
||||
% plot(tr_1,'branchlabels',true)
|
||||
%
|
||||
% % Place the new root at 'Branch 7'
|
||||
% sel = getbyname(tr_1,'Branch 7');
|
||||
% tr_2 = reroot(tr_1,sel)
|
||||
% plot(tr_2,'branchlabels',true)
|
||||
%
|
||||
% % The mid-point of the original tree was the root, since it was an
|
||||
% % ultrametric tree
|
||||
% tr_3 = reroot(tr_2)
|
||||
% plot(tr_3,'branchlabels',true)
|
||||
%
|
||||
% See also PHYTREE, PHYTREE/GET, PHYTREE/GETBYNAME, PHYTREE/PRUNE,
|
||||
% PHYTREE/SELECT, SEQNEIGHJOIN.
|
||||
|
||||
% Copyright 2003-2006 The MathWorks, Inc.
|
||||
% $Revision: 1.1.8.3 $ $Author: batserve $ $Date: 2006/06/16 20:06:46 $
|
||||
|
||||
if numel(tr)~=1
|
||||
error('Bioinfo:phytree:reroot:NoMultielementArrays',...
|
||||
'Phylogenetic tree must be an 1-by-1 object.');
|
||||
end
|
||||
numBranches = size(tr.tree,1);
|
||||
numLeaves = numBranches + 1;
|
||||
numLabels = numBranches + numLeaves;
|
||||
|
||||
if nargin == 1;
|
||||
[node,distance] = midpoint(tr);
|
||||
else
|
||||
% validate node
|
||||
if islogical(node)
|
||||
if any(numel(node) == [numLabels numLeaves])
|
||||
node = find(node);
|
||||
elseif numel(node) == numBranches
|
||||
node = find(node) + numLeaves;
|
||||
else
|
||||
error('Bioinfo:phytree:reroot:IncorrectSizeInputVector',...
|
||||
'Logical vector must have the same number of elements as nodes in the Phylogenetic Tree.');
|
||||
end
|
||||
end
|
||||
if ~isscalar(node) || node<1 || node>numLabels
|
||||
error('Bioinfo:phytree:reroot:InvalidInputNode',...
|
||||
'Invalid value for NODE.');
|
||||
end
|
||||
node = round(node);
|
||||
% when no distance is given put the root at half the branch
|
||||
if nargin<3
|
||||
distance = tr.dist(node)/2;
|
||||
end
|
||||
end
|
||||
|
||||
% find parents for every tree node
|
||||
parent = zeros(numLabels,1);
|
||||
parent(tr.tree) = repmat(numLeaves+1:numLabels,1,2);
|
||||
|
||||
% validate distance, if necessary shift the origin node
|
||||
if ~isscalar(distance) || distance<0
|
||||
error('Bioinfo:phytree:reroot:InvalidInputDistance',...
|
||||
'Invalid value for DISTANCE.');
|
||||
end
|
||||
|
||||
% validate distance, if necessary shift the origin node
|
||||
while (tr.dist(node)<=distance) && (node ~= numLabels)
|
||||
distance = distance - tr.dist(node);
|
||||
node = parent(node);
|
||||
end
|
||||
|
||||
if node == numLabels
|
||||
if distance>0
|
||||
warning('Bioinfo:phytree:reroot:BeyondRoot',...
|
||||
'Distance goes beyond the root, tree unchanged.')
|
||||
else
|
||||
tr.names{end} = 'Root';
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
% check if we just need to move the branches of current root
|
||||
if parent(node) == numLabels
|
||||
tr.dist(setxor(tr.tree(end,:),node)) = ...
|
||||
sum(tr.dist(tr.tree(end,:))) - distance;
|
||||
tr.dist(node) = distance;
|
||||
tr.names{end} = 'Root';
|
||||
return
|
||||
end
|
||||
|
||||
% path to root from node and bros for every point in the path
|
||||
path2r = false(numBranches,1);
|
||||
pathBros = [];
|
||||
me = node;
|
||||
par = parent(node);
|
||||
while par
|
||||
pathBros = [pathBros;setxor(tr.tree(par-numLeaves,:),me)];
|
||||
path2r(par-numLeaves) = true;
|
||||
me = par;
|
||||
par = parent(par);
|
||||
end
|
||||
path2rInd=find(path2r)+numLeaves;
|
||||
|
||||
% new tree pointers
|
||||
tr.tree = [tr.tree(~path2r,:);...
|
||||
[[pathBros(end-1:-1:1);node],[pathBros(end);path2rInd(end-1:-1:1)]]];
|
||||
|
||||
% swapping distances in the nodes that belong to the path2r
|
||||
tr.dist(pathBros(end)) = tr.dist(pathBros(end)) + tr.dist(path2rInd(end-1));
|
||||
tr.dist(path2rInd(2:end-1)) = tr.dist(path2rInd(1:end-2));
|
||||
tr.dist(parent(node)) = tr.dist(node) - distance;
|
||||
tr.dist(node) = distance;
|
||||
|
||||
% some branches changed positions, need to tree
|
||||
permuta = [(1:numLeaves)';find(~path2r)+numLeaves;...
|
||||
path2rInd(end-1:-1:1);numLabels];
|
||||
ipermuta(permuta)=1:numLabels;
|
||||
tr.tree = ipermuta(tr.tree);
|
||||
tr.dist = tr.dist(permuta);
|
||||
tr.names = tr.names(permuta);
|
||||
tr.names{end} = 'Root';
|
||||
|
||||
% re-order leaves for no branch crossings
|
||||
tr = prettyorder(tr);
|
||||
|
||||
%-% ----------------------------------------------------------------
|
||||
% Selects the point where the mean of the branch length is equalized
|
||||
function [node,distance] = midpoint(tr)
|
||||
|
||||
numBranches = size(tr.tree,1);
|
||||
numLeaves = numBranches + 1;
|
||||
numLabels = numBranches + numLeaves;
|
||||
|
||||
|
||||
branchWidth = ones(numLabels,1);
|
||||
downDist = zeros(numLabels,1);
|
||||
upDist = zeros(numLabels,1);
|
||||
% cumulative distance and width downwards the tree
|
||||
for ind = 1:numBranches
|
||||
branchWidth(numLeaves+ind) = sum(branchWidth(tr.tree(ind,:)));
|
||||
downDist(numLeaves+ind) = sum(downDist(tr.tree(ind,:)) + ...
|
||||
tr.dist(tr.tree(ind,:)).*branchWidth(tr.tree(ind,:)));
|
||||
end
|
||||
% backpropagate distances
|
||||
for ind = numBranches:-1:1
|
||||
upDist(tr.tree(ind,:)) = downDist(tr.tree(ind,[2 1])) +...
|
||||
upDist(ind+numLeaves) + ...
|
||||
tr.dist(ind+numLeaves).*(numLeaves-branchWidth(ind+numLeaves)) + ...
|
||||
tr.dist(tr.tree(ind,[2 1])).*(branchWidth(tr.tree(ind,[2 1])));
|
||||
end
|
||||
|
||||
% find all possible midpoints, solve this eq for every edge
|
||||
% ud/Nu + (x)*e = dd/Nd + (1-x)*e
|
||||
% ud = cumulative upwards distances
|
||||
% dd = cumulative downwards distances
|
||||
% Nu = number of leaves in the upper braches
|
||||
% Nd = number of leaves in the lower braches
|
||||
% e = distance of current edge
|
||||
|
||||
h = tr.dist~=0; % root can not be in an edge which length is zero
|
||||
h(numLabels) = false; % the route can not be segmented
|
||||
x = inf(numLabels,1);
|
||||
x(h) = (upDist(h)./branchWidth(h) - ...
|
||||
downDist(h)./(numLeaves-branchWidth(h)))./tr.dist(h)/2 + 1/2;
|
||||
|
||||
x(h) = (upDist(h)./(numLeaves-branchWidth(h)) - ...
|
||||
downDist(h)./(branchWidth(h)))./tr.dist(h)/2 + 1/2;
|
||||
|
||||
% find all possible roots
|
||||
h = find(x>=0 & x<=1);
|
||||
if isempty(h)
|
||||
[dummy,h] = min(abs(x-1/2)); %#ok
|
||||
end
|
||||
% pick the most balanced one
|
||||
[d,g]=min(abs(branchWidth(h)*2-numLeaves)); %#ok
|
||||
|
||||
node = h(g);
|
||||
ratio = min(max(x(h(g)),0),1);
|
||||
|
||||
% if ratio is 1 then better pick the parent
|
||||
if ratio == 1
|
||||
[node,dummy] = find(tr.tree==node); %#ok
|
||||
node = node + numLeaves;
|
||||
ratio = 0;
|
||||
end
|
||||
|
||||
% change the ratio (x) to the distance to the selected node
|
||||
distance = ratio .* tr.dist(node);
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue