I'm creating a web application and one of the features is visualizing phylogenetic trees. The application is mainly written in JavaScript, and I am using jsPhyloSVG to draw the trees from Newick files that are provided.
One of the things that users need to be able to do is to root the tree on a given leaf/node. JsPhyloSVG doesn't provide functionality to do that - it just draws a tree from a Newick file. I'd like to create a function that takes as input a Newick file and a chosen node and produces as output the Newick file for that tree, rooted on that node. Then I could just use jsPhyloSVG to draw the new, rooted tree.
Using the 'retree' program in the Phylip package seems to work okay and as an example I can use it to root the following tree on N1:
((N1:0.5,N2:0.75),N3:0.3); ----> (N1:0.5,(N2:0.75,N3:0.30000):0.5);
I'd rather not use Phylip, however, because it would require a client-server interaction and it doesn't seem like this should be a terribly complex thing to implement in JavaScript for example. Can anyone point me in the direction of an algorithm for rooting a phylogenetic tree that I might be able to adapt to JavaScript or better yet, a JavaScript package that might provide this functionality?
Thanks.
EDIT - Response to lh3:
Thank you, your code worked very well but is there any way to recalculate the distance values when the tree is rerooted? They are missing from the result.
>>> tree = kn_parse("(((1984: 0.00178,676: 0.00059): 0,((((1494: 0,1486: 0): 0.00178,1080: 0.00119): 0,712: 0.00059): 0,1032: 0): 0): 0,960: 0.00297);")
Object { n_tips=8, error=0, node=[15], more...}
>>> tree.root = kn_reroot(tree.root,tree.node[1],-1.0)
Object { child=[2], d=-1, hl=false, more...}
>>> tree.node = kn_expand_node(tree.root)
[Object { parent={...}, child=[0], name="676", more...}, Object { parent={...}, child=[0], name="1984", more...}, Object { parent={...}, child=[0], name="960", more...}, Object { parent={...}, child=[0], name="1494", more...}, Object { parent={...}, child=[0], name="1486", more...}, Object { parent={...}, child=[2], d=NaN, more...}, Object { parent={...}, child=[0], name="1080", more...}, Object { parent={...}, child=[2], d=NaN, more...}, Object { parent={...}, child=[0], name="712", more...}, Object { parent={...}, child=[2], d=NaN, more...}, Object { parent={...}, child=[0], name="1032", more...}, Object { parent={...}, child=[2], d=NaN, more...}, Object { parent={...}, child=[2], d=NaN, more...}, Object { parent={...}, child=[2], d=NaN, more...}, Object { child=[2], d=-1, hl=false, more...}]
>>> nh_str = kn_write_nh(tree)
"(676, (1984, (960, ((((1494, 1486 ), 1080 ), 712 ), 1032 ) ) ) ) "
As you can see, the input had distance values but the output does not. Thanks again for your help.
EDIT #2:
Ok, that worked. Thanks again. However, I am getting the following error for some trees:
p.node is undefined
[Break On This Error] p.node[k] = p.node[j];
knhx.js (line 339)
An example of a tree that causes this error is:
((((((AF225:0.00122,AF279:0.00061):0.00010,AF271:0.00061):0.00010,AF255:0.00010):0.00010,AF217:0.00010):0.00010,AF207:0.00010):0.00010,AF245:0.00010,(AF190:0.00122,AF263:0.00122):0.00010);
You can replicate this error by using jstree to draw the tree and then trying to reroot on AF225. I will attempt to debug as well.
Please remove the space after each colon. My NH parse is unfortunately does not work with that.
Please remove the space after each colon. My NH parse is unfortunately does not parse the branch length separated by space.
Ok, that worked. Thanks again. However, I am getting the following error for some trees:
p.node is undefined [Break On This Error] p.node[k] = p.node[j]; knhx.js (line 339)
An example of a tree that causes this error is:
((((((AF225:0.00122,AF279:0.00061):0.00010,AF271:0.00061):0.00010,AF255:0.00010):0.00010,AF217:0.00010):0.00010,AF207:0.00010):0.00010,AF245:0.00010,(AF190:0.00122,AF263:0.00122):0.00010);
You can replicate this error by using jstree to draw the tree and then trying to reroot on AF225.
Ok, that worked. Thanks again. However, I am getting an error for some trees. See my edit, thank you.
That is a very silly typo. Fixed. It is now working.
perfect, thank you