Now that we've figured out how to plot the structure of a circular (i.e., "fan") tree, the next step is segmenting our plotted edges by a discrete character & then plotting segment by color. Here's my function for this next step. Note that (again) this depends on the package 'plotrix' and will not work if there is no character mapped on the tree:
plotFan<-function(tree,colors=NULL){
if(!require(plotrix)) stop("install 'plotrix'")
# check colors
if(is.null(colors)){
st<-sort(unique(unlist(sapply(tree$maps,names))))
colors<-palette()[1:length(st)]
names(colors)<-st
if(length(st)>1){
cat("no colors provided. ")
cat("using the following legend:\n")
print(colors)
}
}
# reorder
cw<-reorder(tree)
pw<-reorder(tree,"pruningwise")
# count nodes and tips
n<-length(cw$tip)
m<-cw$Nnode
# get Y coordinates on uncurved space
Y<-vector(length=m+n)
Y[cw$edge[cw$edge[,2]<=length(cw$tip),2]]<-1:n
nodes<-unique(pw$edge[,1])
for(i in 1:m){
desc<-pw$edge[which(pw$edge[,1]==nodes[i]),2]
Y[nodes[i]]<-(min(Y[desc])+max(Y[desc]))/2
}
Y<-setNames(Y/max(Y)*2*pi,1:(n+m))
Y<-cbind(Y[as.character(tree$edge[,2])],
Y[as.character(tree$edge[,2])])
R<-nodeHeights(cw)
# now put into a circular coordinate system
x<-R*cos(Y)
y<-R*sin(Y)
# plot nodes
plot(x,y,axes=FALSE,asp=1)
# plot radial lines (edges)
for(i in 1:nrow(cw$edge)){
maps<-cumsum(cw$maps[[i]])/sum(cw$maps[[i]])
xx<-c(x[i,1],x[i,1]+(x[i,2]-x[i,1])*maps)
yy<-c(y[i,1],y[i,1]+(y[i,2]-y[i,1])*maps)
for(i in 1:(length(xx)-1))
lines(xx[i+0:1],yy[i+0:1],
col=colors[names(maps)[i]],lwd=2)
}
# plot circular lines
for(i in 1:m+n){
r<-R[match(i,cw$edge)]
a1<-min(Y[which(cw$edge==i)])
a2<-max(Y[which(cw$edge==i)])
draw.arc(0,0,r,a1,a2,lwd=2,col=
colors[names(cw$maps[[match(i,cw$edge[,1])]])[1]])
}
}
if(!require(plotrix)) stop("install 'plotrix'")
# check colors
if(is.null(colors)){
st<-sort(unique(unlist(sapply(tree$maps,names))))
colors<-palette()[1:length(st)]
names(colors)<-st
if(length(st)>1){
cat("no colors provided. ")
cat("using the following legend:\n")
print(colors)
}
}
# reorder
cw<-reorder(tree)
pw<-reorder(tree,"pruningwise")
# count nodes and tips
n<-length(cw$tip)
m<-cw$Nnode
# get Y coordinates on uncurved space
Y<-vector(length=m+n)
Y[cw$edge[cw$edge[,2]<=length(cw$tip),2]]<-1:n
nodes<-unique(pw$edge[,1])
for(i in 1:m){
desc<-pw$edge[which(pw$edge[,1]==nodes[i]),2]
Y[nodes[i]]<-(min(Y[desc])+max(Y[desc]))/2
}
Y<-setNames(Y/max(Y)*2*pi,1:(n+m))
Y<-cbind(Y[as.character(tree$edge[,2])],
Y[as.character(tree$edge[,2])])
R<-nodeHeights(cw)
# now put into a circular coordinate system
x<-R*cos(Y)
y<-R*sin(Y)
# plot nodes
plot(x,y,axes=FALSE,asp=1)
# plot radial lines (edges)
for(i in 1:nrow(cw$edge)){
maps<-cumsum(cw$maps[[i]])/sum(cw$maps[[i]])
xx<-c(x[i,1],x[i,1]+(x[i,2]-x[i,1])*maps)
yy<-c(y[i,1],y[i,1]+(y[i,2]-y[i,1])*maps)
for(i in 1:(length(xx)-1))
lines(xx[i+0:1],yy[i+0:1],
col=colors[names(maps)[i]],lwd=2)
}
# plot circular lines
for(i in 1:m+n){
r<-R[match(i,cw$edge)]
a1<-min(Y[which(cw$edge==i)])
a2<-max(Y[which(cw$edge==i)])
draw.arc(0,0,r,a1,a2,lwd=2,col=
colors[names(cw$maps[[match(i,cw$edge[,1])]])[1]])
}
}
The key attributes that I've added is segmentalization of each edge by the mapped state, and then separate plotting of each edge segment according to the colors for the state.
Let's try it out:
> Q<-matrix(c(-1,1,1,-1),2,2)
> rownames(Q)<-colnames(Q)<-letters[1:2]
> Q
a b
a -1 1
b 1 -1
> tree<-sim.history(tree,Q)
> plotSimmap(tree,colors=setNames(c("blue","red"), letters[1:2]))
> rownames(Q)<-colnames(Q)<-letters[1:2]
> Q
a b
a -1 1
b 1 -1
> tree<-sim.history(tree,Q)
> plotSimmap(tree,colors=setNames(c("blue","red"), letters[1:2]))
> source("plotFan.R")
> plotFan(tree,colors=setNames(c("blue","red"), letters[1:2]))
> plotFan(tree,colors=setNames(c("blue","red"), letters[1:2]))
Cool. Now we just need to clean it up a bit & add labels....
No comments:
Post a Comment
Note: due to the very large amount of spam, all comments are now automatically submitted for moderation.