/working/auteur.extended/R/rjmcmc.bm.R

http://github.com/eastman/auteur · R · 211 lines · 167 code · 30 blank · 14 comment · 41 complexity · a63ce01a21c70b0bf376ee279d2633ee MD5 · raw file

  1. #function for Markov sampling from a range of model complexities under the general process of Brownian motion evolution of continuous traits
  2. #author: LJ HARMON 2009, A HIPP 2009, and JM EASTMAN 2010
  3. rjmcmc.bm <-
  4. function (phy, dat, SE=0, ngen=1000, sample.freq=100, prob.mergesplit=0.05, prob.root=0.01, lambdaK=log(2), constrainK=FALSE, jumpsize=NULL, simplestart=FALSE, internal.only=FALSE, summary=TRUE, fileBase="result")
  5. {
  6. model="BM"
  7. heat=1 ## heating not currently implemented
  8. require(geiger)
  9. if(is.null(jumpsize)) {
  10. cat("CALIBRATING jumpsize...\n")
  11. adjustable.jumpsize=TRUE
  12. jumpsize=calibrate.jumpsize(phy, dat, nsteps=ngen/1000, model)
  13. } else {
  14. adjustable.jumpsize=FALSE
  15. }
  16. ### prepare data for rjMCMC
  17. cur.model <- model
  18. dataList <- prepare.data(phy, dat, SE)
  19. ape.tre <- dataList$ape.tre
  20. orig.dat <- dataList$orig.dat
  21. SE <- dataList$SE
  22. node.des <- sapply(unique(c(ape.tre$edge[1,1],ape.tre$edge[,2])), function(x) get.descendants.of.node(x, ape.tre))
  23. names(node.des) <- c(ape.tre$edge[1,1], unique(ape.tre$edge[,2]))
  24. # initialize parameters
  25. if(is.numeric(constrainK) & (constrainK > length(ape.tre$edge) | constrainK < 1)) stop("Constraint on rate shifts is nonsensical. Ensure that constrainK is at least 1 and less than the number of available nodes in the tree.")
  26. if(simplestart | is.numeric(constrainK) | internal.only) {
  27. if(is.numeric(constrainK)) {
  28. init.rate <- generate.starting.point(orig.dat, ape.tre, node.des, model, K=constrainK, jumpsize=jumpsize)
  29. } else {
  30. init.rate <- list(values=rep(fit.continuous(ape.tre,orig.dat),length(ape.tre$edge.length)),delta=rep(0,length(ape.tre$edge.length)))
  31. }
  32. } else {
  33. init.rate <- generate.starting.point(orig.dat, ape.tre, node.des, model, K=constrainK, jumpsize=jumpsize )
  34. }
  35. cur.rates <- init.rate$values
  36. cur.delta.rates <- init.rate$delta
  37. cur.root <- adjustvalue(mean(orig.dat), jumpsize)
  38. cur.vcv <- updatevcv(ape.tre, cur.rates)
  39. mod.cur = bm.lik.fn(cur.rates, cur.root, orig.dat, cur.vcv, SE)
  40. # proposal counts
  41. nRateProp = 0
  42. nRateSwapProp = 0
  43. nRcatProp = 0
  44. nRootProp = 0
  45. nRateOK = 0
  46. nRateSwapOK = 0
  47. nRcatOK = 0
  48. nRootOK = 0
  49. cOK=c(
  50. nRateOK,
  51. nRateSwapOK,
  52. nRcatOK,
  53. nRootOK
  54. )
  55. prob.rates=1-sum(c(2*prob.mergesplit, prob.root))
  56. if(prob.rates<0) stop("proposal frequencies must not exceed 1; adjust 'prob.mergesplit' and (or) 'prob.root'")
  57. proposal.rates<-orig.proposal.rates<-c(2*prob.mergesplit, prob.root, prob.rates)
  58. prop.cs<-orig.prop.cs<-cumsum(proposal.rates)
  59. # find jumpsize calibration generations
  60. if(adjustable.jumpsize) {
  61. tf=c()
  62. tenths=function(v)floor(0.1*v)
  63. nn=ngen
  64. while(1) {
  65. vv=tenths(nn)
  66. nn=vv
  67. if(nn<=1) break else tf=c(nn,tf)
  68. }
  69. tuneFreq=tf
  70. } else {
  71. tuneFreq=0
  72. }
  73. cur.acceptancerate=0
  74. tickerFreq=ceiling((ngen+max(tuneFreq))/30)
  75. # file handling
  76. if(summary) parmBase=paste(model, fileBase, "parameters/",sep=".") else parmBase=paste(".", runif(1), model, fileBase, "parameters/",sep="")
  77. if(!file.exists(parmBase)) dir.create(parmBase)
  78. parlogger(model=model, init=TRUE, node.des, parmBase=parmBase)
  79. errorLog=paste(parmBase,paste(cur.model, fileBase, "rjmcmc.errors.log",sep="."),sep="/")
  80. runLog=file(paste(parmBase,paste(cur.model, fileBase, "rjmcmc.log",sep="."),sep="/"),open='w+')
  81. generate.log(bundled.parms=NULL, cur.model, file=runLog, init=TRUE)
  82. ### Begin rjMCMC
  83. for (i in 1:(ngen+max(tuneFreq))) {
  84. lnLikelihoodRatio <- lnHastingsRatio <- lnPriorRatio <- 0
  85. startparms = c(nRateProp, nRateSwapProp, nRcatProp, nRootProp)
  86. if(internal.only) {
  87. tips.tmp=which(as.numeric(names(cur.delta.rates))<=Ntip(ape.tre))
  88. if(any(cur.delta.rates[tips.tmp]==1)) stop("Broken internal only sampling")
  89. }
  90. ## BM IMPLEMENTATION ##
  91. while(1) {
  92. cur.proposal=min(which(runif(1)<prop.cs))
  93. if (cur.proposal==1 & !constrainK) { # adjust rate categories
  94. nr=splitormerge(cur.delta.rates, cur.rates, ape.tre, node.des, lambdaK, theta=FALSE, internal.only)
  95. new.rates=nr$new.values
  96. new.delta.rates=nr$new.delta
  97. new.root=cur.root
  98. nRcatProp=nRcatProp+1
  99. lnHastingsRatio=nr$lnHastingsRatio
  100. lnPriorRatio=nr$lnPriorRatio
  101. break()
  102. } else if(cur.proposal==2) { # adjust root
  103. new.root=adjustvalue(cur.root, jumpsize)
  104. new.rates=cur.rates
  105. new.delta.rates=cur.delta.rates
  106. nRootProp=nRootProp+1
  107. break()
  108. } else if(cur.proposal==3){
  109. if(runif(1)>0.05 & sum(cur.delta.rates)>1) { # tune local rate
  110. new.rates=tune.rate(cur.rates, jumpsize)
  111. new.delta.rates=cur.delta.rates
  112. new.root=cur.root
  113. nRateSwapProp=nRateSwapProp+1
  114. break()
  115. } else { # adjust rates
  116. new.rates=adjustrate(cur.rates, jumpsize)
  117. new.delta.rates=cur.delta.rates
  118. new.root=cur.root
  119. nRateProp=nRateProp+1
  120. break()
  121. }
  122. }
  123. }
  124. if(any(new.rates!=cur.rates)) new.vcv=updatevcv(ape.tre, new.rates) else new.vcv=cur.vcv
  125. mod.new=NULL
  126. mod.new=try(bm.lik.fn(new.rates, new.root, orig.dat, new.vcv, SE), silent=TRUE)
  127. if(inherits(mod.new, "try-error")) {mod.new=as.list(mod.new); mod.new$lnL=-Inf}
  128. if(!is.infinite(mod.new$lnL)) {
  129. lnLikelihoodRatio = mod.new$lnL - mod.cur$lnL
  130. } else {
  131. mod.new$lnL=-Inf
  132. lnLikelihoodRatio = -Inf
  133. }
  134. # compare likelihoods
  135. endparms = c(nRateProp=nRateProp, nRateSwapProp=nRateSwapProp, nRcatProp=nRcatProp, nRootProp=nRootProp)
  136. r=assess.lnR((heat * lnLikelihoodRatio + heat * lnPriorRatio + lnHastingsRatio)->lnR)
  137. # potential errors
  138. if(is.infinite(mod.cur$lnL)) stop("starting point has exceptionally poor likelihood")
  139. if(r$error) generate.error.message(Ntip(phy), i, mod.cur, mod.new, lnLikelihoodRatio, lnPriorRatio, lnHastingsRatio, cur.delta.rates, new.delta.rates, errorLog)
  140. if (runif(1) <= r$r) { ## adopt proposal ##
  141. decision="adopt"
  142. cur.root <- new.root
  143. cur.rates <- new.rates
  144. cur.delta.rates <- new.delta.rates
  145. mod.cur <- mod.new
  146. cur.vcv <- new.vcv
  147. curr.lnL <- mod.new$lnL
  148. cOK <- determine.accepted.proposal(startparms, endparms, cOK)
  149. } else { ## deny proposal ##
  150. decision="reject"
  151. curr.lnL <- mod.cur$lnL
  152. }
  153. # iteration-specific functions
  154. if(i%%tickerFreq==0 & summary) {
  155. if(i==tickerFreq) cat("|",rep(" ",9),toupper("generations complete"),rep(" ",9),"|","\n")
  156. cat(". ")
  157. }
  158. if(i%%sample.freq==0 & i>max(tuneFreq)) {
  159. bundled.parms=list(gen=i-max(tuneFreq), mrate=exp(mean(log(cur.rates))), cats=sum(cur.delta.rates)+1, root=cur.root, lnL=curr.lnL, rates=cur.rates)
  160. generate.log(bundled.parms, cur.model, file=runLog)
  161. parlogger(model=model, init=FALSE, node.des=node.des, i=i-max(tuneFreq), curr.lnL=curr.lnL, cur.root=cur.root, cur.rates=cur.rates, cur.delta.rates=cur.delta.rates, parmBase=parmBase)
  162. }
  163. if(any(tuneFreq%in%i) & adjustable.jumpsize) {
  164. new.acceptancerate=sum(cOK)/sum(endparms)
  165. if((new.acceptancerate<cur.acceptancerate) & adjustable.jumpsize) {
  166. jumpsize=calibrate.jumpsize(phy, dat, nsteps=1000, model, jumpsizes=c(exp(log(jumpsize)-log(2)), exp(log(jumpsize)+log(2))))
  167. }
  168. cur.acceptancerate=new.acceptancerate
  169. }
  170. }
  171. # End rjMCMC
  172. close(runLog)
  173. # clear out jumpsize calibration directories if calibration run
  174. if(summary) {
  175. summarize.run(cOK, endparms, cur.model)
  176. cleanup.files(parmBase, cur.model, fileBase)
  177. } else {
  178. unlink(parmBase, recursive=TRUE)
  179. }
  180. return(list(acceptance.rate=sum(cOK)/sum(endparms), jumpsize=jumpsize))
  181. }