# function does Bayes ancestral character estimation # written by Liam J. Revell 2011 anc.Bayes<-function(tree,x,ngen=10000,control=list()){ # give the function some defaults (in case none are provided) temp<-phyl.vcv(as.matrix(x),vcv(tree),1) sig2<-temp$R[1,1] a<-temp$alpha y<-rep(a,tree$Nnode-1) pr.mean<-c(1000,rep(0,tree$Nnode)) pr.var<-c(pr.mean[1]^2,rep(1000,tree$Nnode)) prop<-rep(0.01*max(temp$C)*sig2,tree$Nnode+1) # populate control list con=list(sig2=sig2,a=a,y=y,pr.mean=pr.mean,pr.var=pr.var,prop=prop,sample=100) con[(namc<-names(control))]<-control con<-con[!sapply(con,is.null)] # print control parameters to screen message("Control parameters (set by user or default):"); str(con) # function returns the log-likelihood likelihood<-function(C,x,sig2,a,y){ logLik<-dmnorm(x=c(x,y),mean=rep(a,nrow(C)),varcov=sig2*C,log=TRUE) return(logLik) } # function returns the prior log.prior<-function(pr.mean,pr.var,sig2,a,y) pp<-dexp(sig2,rate=1/pr.mean[1],log=TRUE)+sum(dnorm(c(a,y),sd=sqrt(pr.var[1+1:tree$Nnode]),log=TRUE)) # compute C C<-vcvPhylo(tree) # now set starting values for MCMC sig2<-con$sig2; a<-con$a; y<-con$y x<-x[tree$tip.label] if(is.null(names(y))) names(y)<-length(tree$tip)+2:tree$Nnode else y[as.character(length(tree$tip)+2:tree$Nnode)] L<-likelihood(C,x,sig2,a,y) Pr<-log.prior(con$pr.mean,con$pr.var,sig2,a,y) # store X<-matrix(NA,ngen/con$sample+1,tree$Nnode+3,dimnames=list(NULL,c("gen","sig2",length(tree$tip)+1:tree$Nnode,"logLik"))) X[1,]<-c(0,sig2,a,y,L) message("Starting MCMC...") # start MCMC for(i in 1:ngen){ j<-(i-1)%%(tree$Nnode+1) if(j==0){ # update sig2 sig2.prime<-sig2+rnorm(n=1,sd=sqrt(con$prop[j+1])) if(sig2.prime<0) sig2.prime<--sig2.prime L.prime<-likelihood(C,x,sig2.prime,a,y) Pr.prime<-log.prior(con$pr.mean,con$pr.var,sig2.prime,a,y) post.odds<-min(1,exp(Pr.prime+L.prime-Pr-L)) if(post.odds>runif(n=1)){ if(i%%con$sample==0) X[i/con$sample+1,]<-c(i,sig2.prime,a,y,L.prime) sig2<-sig2.prime L<-L.prime Pr<-Pr.prime } else if(i%%con$sample==0) X[i/con$sample+1,]<-c(i,sig2,a,y,L) } else if(j==1){ # update a a.prime<-a+rnorm(n=1,sd=sqrt(con$prop[j+1])) L.prime<-likelihood(C,x,sig2,a.prime,y) Pr.prime<-log.prior(con$pr.mean,con$pr.var,sig2,a.prime,y) post.odds<-min(1,exp(Pr.prime+L.prime-Pr-L)) if(post.odds>runif(n=1)){ if(i%%con$sample==0) X[i/con$sample+1,]<-c(i,sig2,a.prime,y,L.prime) a<-a.prime L<-L.prime Pr<-Pr.prime } else if(i%%con$sample==0) X[i/con$sample+1,]<-c(i,sig2,a,y,L) } else { k<-j-1 # update node k y.prime<-y y.prime[k]<-y[k]+rnorm(n=1,sd=sqrt(con$prop[j+1])) L.prime<-likelihood(C,x,sig2,a,y.prime) Pr.prime<-log.prior(con$pr.mean,con$pr.var,sig2,a,y.prime) post.odds<-min(1,exp(Pr.prime+L.prime-Pr-L)) if(post.odds>runif(n=1)){ if(i%%con$sample==0) X[i/con$sample+1,]<-c(i,sig2,a,y.prime,L.prime) y<-y.prime L<-L.prime Pr<-Pr.prime } else if(i%%con$sample==0) X[i/con$sample+1,]<-c(i,sig2,a,y,L) } } # done MCMC message("Done MCMC.") return(X) }