Thursday, May 23, 2013

Plotting a circular discrete character mapped tree, part II: The colors

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]])
  }
}

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]))
> source("plotFan.R")
> 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