Monday, June 17, 2019

Update to plot.cophylo to permit duplicate tip labels in one or both trees

This morning a phytools user sent the following query to the R-sig-phylo list:

“I want to plot two phylogenetic trees face-to-face using phytools::cophylo function. I see there is no possibility to connect 2 or 3 same taxa in a tree to one taxon in the other tree (attached). Is there anyway doing this in R?”

It turned out that the problem is not precisely as states, as the researcher actually wanted to match Species_genus with Species_genus_1, Species_genus_2, & so on, which was already possible by specifying an association table using the function argument assoc (e.g., here).

On the other hand, I see no particular reason why a cophylo plot should not permit two tips in a tree to share precisely the same label. The only reason it did not work, it turns out, was due to a particular way in which the vertical positions of the linking lines were identified in the plotting method for the "cophylo" object. I just pushed an update to GitHub that should address this issue.

Here's a small demo using random trees (after updating phytools from GitHub using devtools::install_github:

library(phytools)
packageVersion("phytools")
## [1] '0.6.83'
set.seed(999)
t1<-rtree(n=16)
t2<-rtree(n=16)
plot(obj<-cophylo(t1,t2))
## Rotating nodes to optimize matching...
## Done.

plot of chunk unnamed-chunk-1

Now let's set some of our tip labels to be the same as each other:

t1$tip.label[which(t1$tip.label=="t16")]<-
    t1$tip.label[which(t1$tip.label=="t8")]<-"t5"
t2$tip.label[which(t2$tip.label=="t3")]<-"t4"
obj<-cophylo(t1,t2)
## Rotating nodes to optimize matching...
## Done.
summary(obj)
## 
## Co-phylogenetic ("cophylo") object: obj 
## 
## Tree 1 (left tree) is an object of class "phylo" containing 16 species.
## 
## Tree 2 (right tree) is an object of class "phylo" containing 16 species.
## 
## Association (assoc) table as follows:
## 
##  left:   ----    right:
##  t7  ----    t7
##  t5  ----    t5
##  t6  ----    t6
##  t2  ----    t2
##  t1  ----    t1
##  t14 ----    t14
##  t11 ----    t11
##  t10 ----    t10
##  t4  ----    t4
##  t9  ----    t9
##  t13 ----    t13
##  t15 ----    t15
##  t12 ----    t12
plot(obj,link.lwd=2,link.lty="dotted",
    link.col=make.transparent("red",0.5))

plot of chunk unnamed-chunk-2

We can also have duplicating tip labels with an association table. For instance:

for(i in 1:length(t2$tip.label)){
    ii<-as.numeric(strsplit(t2$tip.label[i],
        "t")[[1]][2])
    t2$tip.label[i]<-LETTERS[ii]
}
assoc<-cbind(paste("t",1:20,sep=""),
    LETTERS[1:20])
obj<-cophylo(t1,t2,assoc=assoc)
## Some species in assoc[,1] not in tr1. Removing species & links.
## Some species in assoc[,2] not in tr2. Removing species & links.
## Rotating nodes to optimize matching...
## Done.
summary(obj)
## 
## Co-phylogenetic ("cophylo") object: obj 
## 
## Tree 1 (left tree) is an object of class "phylo" containing 16 species.
## 
## Tree 2 (right tree) is an object of class "phylo" containing 16 species.
## 
## Association (assoc) table as follows:
## 
##  left:   ----    right:
##  t1  ----    A
##  t2  ----    B
##  t4  ----    D
##  t5  ----    E
##  t6  ----    F
##  t7  ----    G
##  t9  ----    I
##  t10 ----    J
##  t11 ----    K
##  t12 ----    L
##  t13 ----    M
##  t14 ----    N
##  t15 ----    O
plot(obj)

plot of chunk unnamed-chunk-3

Don't forget that phytools::plot.cophylo has lots of different options, such as using curved linking lines, e.g.:

plot(obj,link.type="curved",link.lwd=2,
    link.col=make.transparent("grey",0.7))

plot of chunk unnamed-chunk-4

That's it.