Friday, August 23, 2013

New version of plotSimmap (that shouldn't affect anyone - except negatively)

I just posted a new version of the important phytools plotting function plotSimmap. The basic function of plotSimmap is to plot a stochastically mapped tree; however the function is also called internally by a number of other phytools functions such as plotTree, plot.contMap, and plot.densityMap. (This is the basis for the parenthetical part of the post title. More details at the bottom.)

This new version has a number of small updates around the edges - but the biggest update is that it now plots the tree on the original scale, rather than fixing the plotting window at a particular size and then rescaling the tree to the the plotting window. The advantage of this is huge as it makes it much easier to overlay additional plotting elements on our graph.

Now you might ask why would I have fixed the plotting window and rescaled the tree to the plotting window in the first place? Well - good question. The problem is how to figure out what amount of space to leave to the right of the tips of the tree for labels. At the time, the most obvious way to do this was to set the plotting window at a fixed width (say 1.0 unit), and then compute the maximum fraction of that horizontal space to allow for our labels - then rescale the tree to occupy the rest of the space.

Just to quickly demo the consequences of doing it this way:

> library(phytools)
Loading required package: ape
...
> packageVersion("phytools")
[1] ‘0.3.34’
> tree<-pbtree(n=26)
> tree$tip.label<-LETTERS[26:1]
> max(nodeHeights(tree))
[1] 4.31398
> plotTree(tree,mar=c(2,2,2,2))
> axis(1)

First off - by adding the x-axis to the plot we can see that it's not on the original scale, but rescale to a total length of 1.0 (including the tip label). That further predicts that if we had longer tip labels, the length of the plotted tree would also change, and we can see that that is the case:

> tree$tip.label[26]<-paste(c(LETTERS[1],letters[2:12]), collapse="")
> plotTree(tree,mar=c(2,2,2,2))
> axis(1)

So you can see - that in terms of our plotting window, the scale of our tree is actually changing if we get longer tip labels! Oh no. So long as we don't want to add anything to our plotting window this is not a huge issue - and in many situations that will be the case. However as soon as we, say, decide after the fact that we'd like to add a scale bar to our plotted tree, we're in trouble.

Well, I discovered a much better way to handle this problem when I was working on nicer looking labels for the function phenogram. In this method we actually use numerical optimization to find the plotting area that we need to permit our labels & the tree to be plotted. It is based on code modified from the ape package function plot.phylo. Now I've implemented this method in plotSimmap and it is in a new build of phytools (phytools 0.3-36). Let's try it:

> detach("package:phytools",unload=TRUE)
> install.packages("phytools_0.3-36.tar.gz",type="source")
* installing *source* package 'phytools' ...
...
* DONE (phytools)
> library(phytools)
> packageVersion("phytools")
[1] ‘0.3.36’
> tree$tip.label[26]<-LETTERS[1]
> plotTree(tree,mar=c(2,2,2,2))
> axis(1)
> tree$tip.label[26]<-paste(c(LETTERS[1],letters[2:12]), collapse="")
> plotTree(tree,mar=c(2,2,2,2))
> axis(1)

We can see that the scale is the original scale of the tree - and it is retained when we use different sized tip labels.

The new version of plotSimmap also has some other handy updates - for instance, user control of x & y limits. This can be useful in, for instance, adding a legend to the plotted tree. Let's see:

> data(anoletree) # load anole tree
> colors<-setNames(palette()[1:6],sort(unique(getStates(anoletree,"tips"))))
> colors
      CG        GB        TC        TG        Tr        TW
  "black"    "red"  "green3"    "blue"    "cyan" "magenta"
> plotSimmap(anoletree,colors,fsize=0.7,ylim=c(-4, length(anoletree$tip.label)),ftype="i")
> add.simmap.legend(colors=colors,prompt=TRUE, vertical=FALSE)
Click where you want to draw the legend

Pretty cool.

The only problem with this update is that - as mentioned earlier - many of the other plotting functions in phytools rely on plotSimmap internally, and they have been built to accommodate its quirks. Consequently, there is a good chance that this update will break those functions. Fear not - I will work on bringing the rest of phytools into line quickly.

No comments:

Post a Comment