Closed KlausVigo closed 4 months ago
Hi @KlausVigo,
Thanks a lot for reporting this since, I think, it can help to clarify a point on the structure and manipulation of "phylo" objects.
The $root.edge
element can be confusing because it stores an edge length separately from the other edges, but it makes possible to distinguish the 3 following trees:
((a:1,b:1):1);
(a:1,b:1):1;
(a:1,b:1, :1);
When plotted, they look identical (unless the internal nodes are visualized explicitly). Only the 2nd one has a $root.edge
element. Your tree1
is similar to the 1st one: I can reproduce the bug with it:
R> mytree <- read.tree(text = "((a:1,b:1):1);")
R> is.rooted(unroot(mytree))
[1] TRUE
So these kind of edges can cause quite some problems and the behaviour is often random.
Correct! Let's take a more extreme example:
R> mytree2 <- read.tree(text = "((((((((((a:1,b:1))))))))));")
R> is.rooted(unroot(unroot(unroot(unroot(unroot(mytree2))))))
[1] TRUE
You can call unroot()
multiple times but:
R> mytree3 <- mytree2 # keep the original tree
R> while (is.rooted(mytree3)) mytree3 <- unroot(mytree3)
Erreur dans .unroot_ape(phy, length(phy$tip.label)) :
cannot unroot a tree with less than three edges.
Same thing if you call collapse.singles()
.
There might be even cases where one want to treat the root (with an root edge) as tip after unrooting.
That seems a very good idea which will require a new option to unroot()
. drop.tip()
has a similar option (root.edge = 0
) doing actually the opposite operation (taking internal edges to build a root edge).
To summarize, the changes needed are:
root.edge.as.terminal = 0
.unroot
repeatedly. collapse.singles()
does the work but maybe there is a more efficient solution directly within the function.Cheers, Emmanuel
Hi @emmanuelparadis,
nice examples. Just some weird behaviour of the axisPhylo
.
mytree2 <- read.tree(text = "((((((((((a:1,b:1))))))))));")
mytree2$edge.length <- runif(11)
mytree3 <- collapse.singles(mytree2, TRUE)
# fine
plot(mytree2)
axisPhylo()
# weird
plot(mytree3, root.edge=TRUE)
axisPhylo()
Might worth fixing, too.
Cheers, Klaus
Hi @KlausVigo,
I've pushed a new version with an improved version of unroot()
. There are two new options:
collapse.singles = FALSE
keep.root.edge = FALSE
The first one needs to be switched to TRUE to have a completely unrooted tree. I prefer to keep the default FALSE to agree with the current behaviour of the function.
More tests welcome!
Cheers, Emmanuel
Hi @emmanuelparadis,
the new unroot function needs some small improvements.
unroot.multiPhylo
fails if trees are compressed.
> trees <- rmtree(10, 10)
> trees <- .compressTipLabel(trees)
> unroot(trees)
Fehler in FUN(X[[i]], ...) :
cannot unroot a tree where all nodes are singleton
ape:::.unroot_ape
and degree.phylo
assume that there is slot $tip.label
.
Regards, Klaus
Hi Klaus, I've just pushed the fix. Regards, Emmanuel
Hi @emmanuelparadis,
I got a bug report which contained this tree
If you plot this tree
you will see that the tree has a root node (n1 to n2) and I quite like that it is possible to plot a tree like that. I think the tree is stored quite elegant, but one need to check for the root edge and in many wants cases remove it. However this tree comes with side effects and can cause problems afterwards.
As you can see
unroot
removes the root edge, but leaves the tree rooted. So one would have to callunroot
twice to unroot the tree.collapse.singles
removes the singleton (node n24) and also the root node and solved the bug. So these kind of edges can cause quite some problems and the behaviour is often random. There might be even cases where one want to treat the root (with an root edge) as tip after unrooting.Cheers, Klaus