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