Tuesday, March 6, 2018

Coalescent genealogy plot in R

Nowadays every evolutionary genetics seems to feature the same plot illustrating genealogical coalescence. You know the one - it usually consists of different colored circles or squares connected by lines meant to represent parent-daughter relationships? I thought it would be handy to reproduce this in R. Here's my function which will shortly join my PopGen package on GitHub:

coalescent.plot<-function(n=10,ngen=20,colors=NULL,...){
    if(hasArg(sleep)) sleep<-list(...)$sleep
    else sleep<-0.2
    if(is.null(colors)) colors<-rainbow(n=n)
    popn<-matrix(NA,ngen+1,n)
    parent<-matrix(NA,ngen,n)
    popn[1,]<-1:n
    for(i in 1:ngen){
        parent[i,]<-sort(sample(1:n,replace=TRUE))
        popn[i+1,]<-popn[i,parent[i,]]
    }
    plot.new()
    par(mar=c(2.1,4.1,2.1,1.1))
    plot.window(xlim=c(0.5,n+0.5),ylim=c(ngen,0))
    axis(2)
    title(ylab="time (generations)")
    cx.pt<-2*25/max(n,ngen)
    points(1:n,rep(0,n),bg=colors,pch=21,cex=cx.pt)
    for(i in 1:ngen){
        dev.hold()
        for(j in 1:n){
            lines(c(parent[i,j],j),c(i-1,i),lwd=2,
                col=colors[popn[i+1,j]])
        }
        points(1:n,rep(i-1,n),bg=colors[popn[i,]],pch=21,
            cex=cx.pt)
        points(1:n,rep(i,n),bg=colors[popn[i+1,]],pch=21,
            cex=cx.pt)
        dev.flush()
        Sys.sleep(sleep)
    }
}

OK, let's try it!

library(RColorBrewer)
n<-20
cols<-colorRampPalette(brewer.pal("Accent",n=8))(n)
par(bg="grey",fg="white")
coalescent.plot(n=n,colors=cols,ngen=15)

plot of chunk unnamed-chunk-2

The color scheme is arbitrary & the grey background / white foreground is just for effect - but I like it!

Note that the plot shown is static, but in R it is animated. Here's what I mean:

coalescent.plot(n=n,colors=cols,ngen=20)

(Note that I also made the above animation using ImageMagick, but I also had to modify the code of coalescent.plot to include a call to dev.print for every generation of the simulation.)

That's it.

2 comments:

  1. I was working on something similar but more complex: My idea is to simulate the history of multiple populations that can exchange alleles and where the alleles can spontaneously mutate. I wonder if you can suggest a way to model these sceanria in a time-efficient way with R. Thanks in advance!

    ReplyDelete
    Replies
    1. PS: My way was like this: Use a list of length n (# of populations) with 2 vectors in each entry, i) the current alleles (initially numberes from 1:metapopulation.popsize) in the population, ii) immigrating alleles + current alleles. Sample from ii) and create a new i). Then, pick alleles with chance = mutation.rate and change the value to a new value that doesn't already exist.

      That way I hoped to simulate the spread given alleles in generation 0 under given mutation and migration rates and estimate these parameters after many simulation runs with approximate Bayesian computation (ABC). However, my approch is too slow to perfrom a few million runs (it takes about 7 s for 1 single run)

      Delete

Note: due to the very large amount of spam, all comments are now automatically submitted for moderation.