/PhyloSim.R

http://github.com/sbotond/phylosim · R · 6741 lines · 2944 code · 500 blank · 3297 comment · 491 complexity · 599a6b1f6c5fd46221d5d716d177dc82 MD5 · raw file

Large files are truncated click here to view the full file

  1. ##
  2. ## Copyright 2009 Botond Sipos
  3. ## See the package description for licensing information.
  4. ##
  5. ##########################################################################/**
  6. #
  7. # @RdocClass PhyloSim
  8. # \alias{phylosim}
  9. #
  10. # @title "The PhyloSim class"
  11. #
  12. # \description{
  13. #
  14. # PhyloSim is an extensible object-oriented framework for the Monte Carlo simulation
  15. # of sequence evolution written in 100 percent \code{R}.
  16. # It is built on the top of the \code{\link{R.oo}} and \code{\link{ape}} packages and uses
  17. # Gillespie's direct method to simulate substitutions, insertions and deletions.
  18. #
  19. # Key features offered by the framework:
  20. # \itemize{
  21. # \item Simulation of the evolution of a set of discrete characters with arbitrary states evolving
  22. # by a continuous-time Markov process with an arbitrary rate matrix.
  23. # \item Explicit implementations of the most popular substitution models (for nucleotides, amino acids and codons).
  24. # \item Simulation under the popular models of among-sites rate variation, like the gamma (+G) and invariants plus gamma (+I+G) models.
  25. # \item The possibility to simulate with arbitrarily complex patterns of among-sites rate variation by setting the site specific rates according to any \code{R} expression.
  26. # \item Simulation with one or more separate insertion and/or deletion processes acting on the sequences, which sample the insertion/deletion length from an arbitrary discrete distribution or an \code{R} expression (so all the probability distributions implemented in \code{R} are readily available for this purpose).
  27. # \item Simulation of the effects of variable functional constraints over the sites by site-process-specific insertion and deletion tolerance parameters, which determine the rejection probability of a proposed insertion/deletion.
  28. # \item The possibility of having a different set of processes and site-process-specific parameters for every site, which allow for an arbitrary number of partitions in the simulated data.
  29. # \item Simulation of heterotachy and other cases of non-homogeneous evolution by allowing the user to set "node hook" functions altering the site properties at internal nodes of the phylogeny.
  30. # \item The possibility to export the counts of various events ("branch statistics") as phylo objects (see \code{\link{exportStatTree.PhyloSim}}).
  31. # }
  32. #
  33. # General notes:
  34. # \itemize{
  35. # \item The \code{Sequence} objects have no "immortal links". The simulation
  36. # is aborted if the sequence length shrinks to zero. It is up to the user
  37. # to choose sensible indel rates and sequence lengths to prevent that.
  38. # \item The sites near the beginning and end of the sequences have less sites proposing
  39. # insertion and deletion events around the so the insertion and deletion processes
  40. # have an "edge effect". The user can simulate
  41. # realistic flanking sequences to alleviate the edge effect in the simulation settings where
  42. # it may be an issue.
  43. # }
  44. #
  45. # Notes on performance:
  46. # \itemize{
  47. # \item The pure \code{R} implementation offers felxibility, but also comes
  48. # with a slower simulation speed. If the \code{PSIM_FAST} object is present in the environment, a "fast & careless"
  49. # mode is enabled. In this mode most of the error checking is skipped, increasing the speed.
  50. # It is recomended that simulations are only run in fast mode if you are sure that the simulation
  51. # settings are free from errors. It is probably a good practice to set up the simulations in normal mode
  52. # with short sequences and enable fast mode when running the actual simulation with long sequences.
  53. # \item Please note, that no "branch statistics" are saved in fast mode.
  54. # \item Logging also has a negative impact on performance, so it's not a good idea to run
  55. # large simulations with the logging enabled.
  56. # \item The time needed to run a simulation depends not only on the number of the sites,
  57. # but also on the length of the tree.
  58. # \item Constructing \code{Sequence} objects with large number of sites is expensive. Avoid doing
  59. # that inside a cycle.
  60. # \item In the case of \code{Sequence} objects with a large number of sites (more than 10 000) the
  61. # amount of available memory can be limiting as well.
  62. # }
  63. #
  64. # The examples below demonstrate only some more common simulation settings,
  65. # the framework offers much more flexibility. See the package
  66. # vignette (\code{vignette("PhyloSim",package="phylosim")}) and the
  67. # examples directory (\url{http://github.com/sbotond/phylosim/tree/master/examples/})
  68. # for additional examples.
  69. #
  70. # @classhierarchy
  71. # }
  72. #
  73. #
  74. # \references{
  75. # Gillespie, DT (1977) Exact stochastic simulation of coupled chemical reactions -
  76. # J. Phys. Chem. 81 (25):2340-2361 \url{http://dx.doi.org/10.1021/j100540a008}
  77. # }
  78. #
  79. # @synopsis
  80. #
  81. # \arguments{
  82. # \item{phylo}{A rooted phylo object, constructed by the APE package.}
  83. # \item{root.seq}{A valid Sequence object with Process objects attached. Used as the starting sequence during simulation.}
  84. # \item{name}{The name of the object (a character vector of length one).}
  85. # \item{log.file}{Name of the file used for logging.}
  86. # \item{log.level}{An integer specifying the verbosity of logging (see \code{\link{setLogLevel.PhyloSim}}).}
  87. # \item{...}{Not used.}
  88. # }
  89. #
  90. # \section{Fields and Methods}{
  91. # @allmethods
  92. # }
  93. #
  94. # \examples{
  95. # set.seed(1)
  96. # ## The following examples demonstrate
  97. # ## the typical use of the framework.
  98. # ## See the package vignette and
  99. # ## \url{http://github.com/sbotond/phylosim/tree/master/examples/}
  100. #
  101. # ## The ll() method gives information about the methods defined
  102. # ## in the immediate class of an object.
  103. # ## Useful when exploring the framework.
  104. #
  105. # s<-Sequence()
  106. # ll(s)
  107. # ll(PhyloSim())
  108. # ll(GTR())
  109. #
  110. # ## Example 1 - A short simulation:
  111. # ## simulate nucleotide seqeunces and display
  112. # ## the resulting alignment matrix.
  113. #
  114. # Simulate(
  115. # PhyloSim(phy=rcoal(3),
  116. # root=NucleotideSequence(string="ATGC", proc=list(list(JC69())) ) )
  117. # )$alignment
  118. #
  119. # # Construct a phylo object for the following
  120. # # simulations, scale total tree length to 1:
  121. #
  122. # tmp<-PhyloSim(phylo=rcoal(3))
  123. # scaleTree(tmp,1/tmp$treeLength)
  124. # tmp$treeLength
  125. # t<-tmp$phylo
  126. #
  127. # ## Example 3 - simulating rate variation,
  128. # ## insertions and deletions.
  129. # ## See the examples/example_3_clean.R file
  130. # ## in the phylosim GitHub repository.
  131. #
  132. # # construct a GTR process object
  133. # gtr<-GTR(
  134. # name="MyGTR",
  135. # rate.params=list(
  136. # "a"=1, "b"=2, "c"=3,
  137. # "d"=1, "e"=2, "f"=3
  138. # ),
  139. # base.freqs=c(2,2,1,1)/6
  140. # )
  141. # # get object summary
  142. # summary(gtr)
  143. # # display a bubble plot
  144. # plot(gtr)
  145. #
  146. # # construct root sequence object
  147. # s<-NucleotideSequence(length=20)
  148. # # attach process via virtual field
  149. # s$processes<-list(list(gtr))
  150. # # sample states from the equilibrium
  151. # # distribution of the attached processes
  152. # sampleStates(s)
  153. # # create among-site rate variation by sampling
  154. # # the "rate.multiplier" site-process-specific parameter
  155. # # from a discrete gamma distribution (GTR+G).
  156. # plusGamma(s,gtr,shape=0.1)
  157. # # make the range 11:12 invariable
  158. # setRateMultipliers(s,gtr,0,11:12)
  159. # # get the rate multipliers for s and gtr
  160. # getRateMultipliers(s,gtr)
  161. #
  162. # construct a deletion process object
  163. # # proposing lengths in the range 1:3
  164. # d<-DiscreteDeletor(
  165. # rate=0.1,
  166. # name="MyDel",
  167. # sizes=c(1:3),
  168. # probs=c(3/6,2/6,1/6)
  169. # )
  170. # # get object
  171. # summary(d)
  172. # # plot deletion length distribution
  173. # plot(d)
  174. # # attach deletion process d to sequence s
  175. # attachProcess(s,d)
  176. # # create a region rejecting all deletions
  177. # setDeletionTolerance(s,d,0,11:12)
  178. #
  179. # # construct an insertion process object
  180. # # proposing lengths in the range 1:3
  181. # i<-DiscreteInsertor(
  182. # rate=0.1,
  183. # name="MyDel",
  184. # sizes=c(1:2),
  185. # probs=c(1/2,1/2),
  186. # template.seq=NucleotideSequence(length=1,processes=list(list(JC69())))
  187. # )
  188. # # states will be sampled from the JC69 equilibrium distribution
  189. # # get object
  190. # summary(i)
  191. # # plot insertion length distribution
  192. # plot(i)
  193. # # attach insertion process i to sequence s
  194. # attachProcess(s,i)
  195. # # create a region rejecting all insertions
  196. # setInsertionTolerance(s,i,0,11:12)
  197. #
  198. # # plot total site rates
  199. # plot(s)
  200. # # construct simulation object
  201. # sim<-PhyloSim(root.seq=s, phylo=t)
  202. # # get object summary
  203. # summary(sim)
  204. # # plot tree
  205. # plot(sim)
  206. # # run simulation
  207. # Simulate(sim)
  208. # # get the list of recorded per-branch event counts
  209. # getBranchEvents(sim)
  210. # # export the number of substitutions as a phylo object
  211. # subst<-exportStatTree(sim,"substitution")
  212. # # plot the exported phylo object
  213. # plot(subst)
  214. # # plot tree and alignment
  215. # plot(sim)
  216. # # save and display alingment
  217. # file<-paste("PhyloSim_dummy_fasta_",Sys.getpid(),".fas",sep="");
  218. # saveAlignment(sim,file=file);
  219. # # print out the Fasta file
  220. # cat(paste(scan(file=file,what=character(),sep="\n"),collapse="\n"));cat("\n");
  221. # # delete Fasta file
  222. # unlink(file);
  223. #
  224. # # See \url{http://github.com/sbotond/phylosim/tree/master/examples/examples_class.R}
  225. # # for the full list of PhyloSim constructor examples.
  226. #
  227. # ## See the package vignette and
  228. # ## the GitHub repository for even more examples.
  229. # }
  230. #
  231. # @author
  232. #
  233. # \seealso{
  234. # \code{\link{PSRoot} \link{Alphabet} \link{AminoAcidAlphabet}
  235. # \link{AminoAcidSequence} \link{AminoAcidSubst}
  236. # \link{AnyAlphabet} \link{BinaryAlphabet} \link{BinarySequence}
  237. # \link{BinarySubst} \link{BrownianInsertor} \link{CodonAlphabet}
  238. # \link{CodonSequence} \link{CodonUNREST} \link{ContinuousDeletor}
  239. # \link{ContinuousInsertor} \link{cpREV} \link{DiscreteDeletor}
  240. # \link{DiscreteInsertor} \link{Event} \link{F81} \link{F84}
  241. # \link{FastFieldDeletor} \link{GeneralDeletor}
  242. # \link{GeneralInDel} \link{GeneralInsertor} \link{GeneralSubstitution}
  243. # \link{GTR} \link{GY94} \link{HKY} \link{JC69} \link{JTT} \link{JTT.dcmut}
  244. # \link{K80} \link{K81} \link{LG} \link{mtArt} \link{mtMam} \link{mtREV24}
  245. # \link{MtZoa} \link{NucleotideAlphabet} \link{NucleotideSequence} \link{PAM}
  246. # \link{PAM.dcmut} \link{PhyloSim} \link{Process} \link{QMatrix} \link{Sequence}
  247. # \link{Site} \link{T92} \link{TN93} \link{UNREST} \link{WAG}}
  248. # }
  249. #
  250. #*/###########################################################################
  251. setConstructorS3(
  252. "PhyloSim",
  253. function(
  254. phylo=NA,
  255. root.seq=NA,
  256. name=NA,
  257. log.file=NA,
  258. log.level=-1, # no loggin is performed by default
  259. ...
  260. ) {
  261. this<-PSRoot();
  262. this<-extend(this,
  263. "PhyloSim",
  264. .name="Anonymous",
  265. .phylo=NA,
  266. .root.sequence=NA,
  267. .sequences=list(), # references to the sequence objects
  268. .node.hooks=list(), # references to the node hook functions.
  269. .branch.stats=list(), # branch statistics.
  270. .alignment=NA, # the resulting alignment in fasat format.
  271. .log.file=NA, # the name of the log file.
  272. .log.connection=NA, # connection for the log file.
  273. .log.level=NA # log level
  274. );
  275. if(!all(is.na(phylo))){
  276. this$phylo<-phylo;
  277. }
  278. if(!all(is.na(root.seq))){
  279. this$rootSeq<-root.seq;
  280. }
  281. if(!missing(name)){
  282. this$name<-name;
  283. }
  284. if(!missing(log.file)){
  285. this$logFile<-log.file;
  286. } else {
  287. # Setting default log file:
  288. tmp<-this$id;
  289. tmp<-gsub(":","_",tmp);
  290. this$logFile<-paste(tmp,".log",sep="");
  291. }
  292. # Setting log level:
  293. this$logLevel<-log.level;
  294. return(this);
  295. },
  296. enforceRCC=TRUE
  297. );
  298. ##
  299. ## Method: checkConsistency
  300. ##
  301. ###########################################################################/**
  302. #
  303. # @RdocMethod checkConsistency
  304. #
  305. # @title "Check object consistency"
  306. #
  307. # \description{
  308. # @get "title".
  309. # }
  310. #
  311. # @synopsis
  312. #
  313. # \arguments{
  314. # \item{this}{An object.}
  315. # \item{...}{Not used.}
  316. # }
  317. #
  318. #
  319. # \value{
  320. # Returns an invisible TRUE if no inconsistencies found in the object, throws
  321. # an error otherwise.
  322. # }
  323. #
  324. # @author
  325. #
  326. # \seealso{
  327. # @seeclass
  328. # }
  329. #
  330. #*/###########################################################################
  331. setMethodS3(
  332. "checkConsistency",
  333. class="PhyloSim",
  334. function(
  335. this,
  336. ...
  337. ){
  338. may.fail<-function(this) {
  339. # Checking the name:
  340. this$name<-this$name;
  341. # Checking the phylo object:
  342. if (!any(is.na(this$.phylo)) & !is.phylo(this$.phylo) ){
  343. throw("The phylo object is invalid!\n");
  344. }
  345. # Checking the log level:
  346. if(!is.numeric(this$.log.level) | (length(this$.log.level) != 1) ){
  347. throw("The log level must be numeric vector of length 1!\n");
  348. }
  349. # Checking lof file:
  350. if(!is.character(this$.log.file) | (length(this$.log.level) != 1) ){
  351. throw("The log file must be charcter vector of length 1!\n");
  352. }
  353. # Checking the sequences:
  354. for (seq in this$.sequences){
  355. if(is.Sequence(seq)){
  356. checkConsistency(seq);
  357. }
  358. }
  359. # Checking node hooks:
  360. for (hook in this$.node.hooks){
  361. if(!is.null(hook) & !is.function(hook)){
  362. throw("Invalid node hook found!\n");
  363. }
  364. }
  365. # Checking the alignment:
  366. if(!any(is.na(this$.alignment))){
  367. .checkAlignmentConsistency(this, this$.alignment);
  368. }
  369. }
  370. tryCatch(may.fail(this));
  371. return(invisible(TRUE));
  372. },
  373. private=FALSE,
  374. protected=FALSE,
  375. overwrite=FALSE,
  376. conflict="warning",
  377. validators=getOption("R.methodsS3:validators:setMethodS3")
  378. )
  379. ##
  380. ## Method: is.phylo.default
  381. ##
  382. ###########################################################################/**
  383. #
  384. # @RdocDefault is.phylo
  385. #
  386. # @title "Check if an object is an instance of the phylo class"
  387. #
  388. # \description{
  389. # @get "title".
  390. # Phylo objects are created by the \pkg{APE} package. This method just return the value of \code{inherits(this,"phylo")}.
  391. # }
  392. #
  393. # @synopsis
  394. #
  395. # \arguments{
  396. # \item{this}{An object.}
  397. # \item{...}{Not used.}
  398. # }
  399. #
  400. # \value{
  401. # TRUE or FALSE.
  402. # }
  403. #
  404. # \examples{
  405. # # load APE
  406. # library(ape);
  407. # # create some objects
  408. # o1<-Object();
  409. # o2<-rcoal(3);
  410. # # check if they are phylo objects
  411. # is.phylo(o1);
  412. # is.phylo(o2);
  413. #
  414. # }
  415. #
  416. # @author
  417. #
  418. # \seealso{
  419. # The \pkg{ape} package.
  420. # }
  421. #
  422. #*/###########################################################################
  423. setMethodS3(
  424. "is.phylo",
  425. class="default",
  426. function(
  427. this,
  428. ...
  429. ){
  430. inherits(this,"phylo");
  431. },
  432. private=FALSE,
  433. protected=FALSE,
  434. overwrite=FALSE,
  435. conflict="warning",
  436. validators=getOption("R.methodsS3:validators:setMethodS3")
  437. )
  438. ##
  439. ## Method: setPhylo
  440. ##
  441. ###########################################################################/**
  442. #
  443. # @RdocMethod setPhylo
  444. #
  445. # @title "Set the phylo object for a PhyloSim object"
  446. #
  447. # \description{
  448. # @get "title".
  449. #
  450. # The internal structure of the provided phylo object is reordered in a cladeweise fashion.
  451. # }
  452. #
  453. # @synopsis
  454. #
  455. # \arguments{
  456. # \item{this}{A PhyloSim object.}
  457. # \item{value}{A phylo object created by the \pkg{ape} package.}
  458. # \item{...}{Not used.}
  459. # }
  460. #
  461. # \value{
  462. # A phylo object or FALSE.
  463. # }
  464. #
  465. # \examples{
  466. # #create a PhyloSim object
  467. # sim<-PhyloSim();
  468. # # creat a phylo object
  469. # tree<-rcoal(3);
  470. # # get/set phylo object
  471. # setPhylo(sim,tree);
  472. # getPhylo(sim,tree);
  473. # # get/set phylo object via virtual field
  474. # sim$tree<-rcoal(5);
  475. # sim$tree;
  476. # }
  477. #
  478. # @author
  479. #
  480. # \seealso{
  481. # The PhyloSim class, the \pkg{ape} package.
  482. # }
  483. #
  484. #*/###########################################################################
  485. setMethodS3(
  486. "setPhylo",
  487. class="PhyloSim",
  488. function(
  489. this,
  490. value,
  491. ...
  492. ){
  493. if(missing(value)){
  494. throw("No object provided!\n");
  495. }
  496. else if(!is.phylo(value)){
  497. throw("The new value must be a \"phylo\" object!\n");
  498. }
  499. else if(!is.rooted(value)){
  500. throw("The new value must be a rooted \"phylo\" object!\n");
  501. }
  502. else {
  503. .checkTipLabels(value);
  504. this$.phylo<-value;
  505. this$.phylo<-reorder(this$.phylo, order="cladewise");
  506. for (i in this$nodes){
  507. this$.sequences[[i]]<-NA;
  508. }
  509. return(this$.phylo);
  510. }
  511. return(FALSE);
  512. },
  513. private=FALSE,
  514. protected=FALSE,
  515. overwrite=FALSE,
  516. conflict="warning",
  517. validators=getOption("R.methodsS3:validators:setMethodS3")
  518. );
  519. ##
  520. ## Method: .checkTipLabels
  521. ##
  522. setMethodS3(
  523. ".checkTipLabels",
  524. class="phylo",
  525. function(
  526. this,
  527. ...
  528. ){
  529. for(label in this$tip.label){
  530. if(length(grep("^Node \\d+$",label,perl=TRUE,value=FALSE)) > 0){
  531. throw("Sorry, but the node labels matching \"Node \\d+\" are reserved for internal nodes! Blaming label: ",label,".\n");
  532. }
  533. else if(length(grep("^Root node \\d+$",label,perl=TRUE,value=FALSE)) > 0){
  534. throw("Sorry, but the node labels matching \"Root node \\d+\" are reserved for the root node! Blaming label: ",label,".\n");
  535. }
  536. }
  537. },
  538. private=TRUE,
  539. protected=FALSE,
  540. overwrite=FALSE,
  541. conflict="warning",
  542. validators=getOption("R.methodsS3:validators:setMethodS3")
  543. )
  544. ##
  545. ## Method: getPhylo
  546. ##
  547. ###########################################################################/**
  548. #
  549. # @RdocMethod getPhylo
  550. #
  551. # @title "Get the phylo object aggregated in a PhyloSim object"
  552. #
  553. # \description{
  554. # @get "title".
  555. #
  556. # }
  557. #
  558. # @synopsis
  559. #
  560. # \arguments{
  561. # \item{this}{A PhyloSim object.}
  562. # \item{...}{Not used.}
  563. # }
  564. #
  565. # \value{
  566. # A phylo object or NA.
  567. # }
  568. #
  569. # \examples{
  570. # #create a PhyloSim object
  571. # sim<-PhyloSim();
  572. # # creat a phylo object
  573. # tree<-rcoal(3);
  574. # # get/set phylo object
  575. # setPhylo(sim,tree);
  576. # getPhylo(sim,tree);
  577. # # get/set phylo object via virtual field
  578. # sim$tree<-rcoal(5);
  579. # sim$tree;
  580. # }
  581. #
  582. # @author
  583. #
  584. # \seealso{
  585. # The PhyloSim class, the \pkg{ape} package.
  586. # }
  587. #
  588. #*/###########################################################################
  589. setMethodS3(
  590. "getPhylo",
  591. class="PhyloSim",
  592. function(
  593. this,
  594. ...
  595. ){
  596. this$.phylo;
  597. },
  598. private=FALSE,
  599. protected=FALSE,
  600. overwrite=FALSE,
  601. conflict="warning",
  602. validators=getOption("R.methodsS3:validators:setMethodS3")
  603. )
  604. ##
  605. ## Method: setRootSeq
  606. ##
  607. ###########################################################################/**
  608. #
  609. # @RdocMethod setRootSeq
  610. #
  611. # @title "Set the root sequence for a PhyloSim object"
  612. #
  613. # \description{
  614. # @get "title".
  615. #
  616. # The root sequence will be used as a starting point for the simulation. The phylo object must be set before
  617. # trying to set the root sequence object.
  618. # }
  619. #
  620. # @synopsis
  621. #
  622. # \arguments{
  623. # \item{this}{A PhyloSim object.}
  624. # \item{value}{A valid Sequence object.}
  625. # \item{...}{Not used.}
  626. # }
  627. #
  628. # \value{
  629. # The root Sequence object if succesfull, FALSE otherwise.
  630. # }
  631. #
  632. # \examples{
  633. # # create some objects
  634. # sim<-PhyloSim(phylo=rcoal(3));
  635. # seq<-NucleotideSequence(string="ATGCC");
  636. # # set/get root sequence
  637. # setRootSeq(sim, seq);
  638. # getRootSeq(sim, seq);
  639. # # set/get root sequence via virtual field
  640. # sim$rootSeq<-BinarySequence(string="111000111000");
  641. # sim$rootSeq;
  642. #
  643. # }
  644. #
  645. # @author
  646. #
  647. # \seealso{
  648. # @seeclass Sequence Process
  649. # }
  650. #
  651. #*/###########################################################################
  652. setMethodS3(
  653. "setRootSeq",
  654. class="PhyloSim",
  655. function(
  656. this,
  657. value,
  658. ...
  659. ){
  660. if(missing(value)){
  661. throw("No object provided!\n");
  662. }
  663. else if(!is.Sequence(value)){
  664. throw("The new value must be a sequence object!\n");
  665. }
  666. else {
  667. this$.root.sequence<-clone(value);
  668. this$.root.sequence$name<-paste("Root node",this$rootNode);
  669. # Call garbage collection:
  670. gc();
  671. gc();
  672. return(this$.root.sequence);
  673. }
  674. return(FALSE);
  675. },
  676. private=FALSE,
  677. protected=FALSE,
  678. overwrite=FALSE,
  679. conflict="warning",
  680. validators=getOption("R.methodsS3:validators:setMethodS3")
  681. )
  682. ##
  683. ## Method: getRootSeq
  684. ##
  685. ###########################################################################/**
  686. #
  687. # @RdocMethod getRootSeq
  688. #
  689. # @title "Get the root sequence aggregated by a PhyloSim object"
  690. #
  691. # \description{
  692. # @get "title".
  693. #
  694. # }
  695. #
  696. # @synopsis
  697. #
  698. # \arguments{
  699. # \item{this}{A PhyloSim object.}
  700. # \item{...}{Not used.}
  701. # }
  702. #
  703. # \value{
  704. # The root Sequence object or NA.
  705. # }
  706. #
  707. # \examples{
  708. # # create some objects
  709. # sim<-PhyloSim(phylo=rcoal(3));
  710. # seq<-NucleotideSequence(string="ATGCC");
  711. # # set/get root sequence
  712. # setRootSeq(sim, seq);
  713. # getRootSeq(sim, seq);
  714. # # set/get root sequence via virtual field
  715. # sim$rootSeq<-BinarySequence(string="111000111000");
  716. # sim$rootSeq;
  717. #
  718. # }
  719. #
  720. # @author
  721. #
  722. # \seealso{
  723. # @seeclass Sequence Process
  724. # }
  725. #
  726. #*/###########################################################################
  727. setMethodS3(
  728. "getRootSeq",
  729. class="PhyloSim",
  730. function(
  731. this,
  732. ...
  733. ){
  734. this$.root.sequence;
  735. },
  736. private=FALSE,
  737. protected=FALSE,
  738. overwrite=FALSE,
  739. conflict="warning",
  740. validators=getOption("R.methodsS3:validators:setMethodS3")
  741. )
  742. ##
  743. ## Method: as.character.PhyloSim
  744. ##
  745. ###########################################################################/**
  746. #
  747. # @RdocMethod as.character
  748. #
  749. # @title "Return the character representation of a PhyloSim object"
  750. #
  751. # \description{
  752. # @get "title".
  753. #
  754. # The character representation is the identifier of the PhyloSim object as returned by the \code{getId} method.
  755. # }
  756. #
  757. # @synopsis
  758. #
  759. # \arguments{
  760. # \item{x}{A PhyloSim object.}
  761. # \item{...}{Not used.}
  762. # }
  763. #
  764. # \value{
  765. # A character vector of length one.
  766. # }
  767. #
  768. # \examples{
  769. # # create a PhyloSim object
  770. # o<-PhyloSim(name="MySim");
  771. # # get character representation
  772. # as.character(o)
  773. # }
  774. #
  775. # @author
  776. #
  777. # \seealso{
  778. # @seeclass
  779. # }
  780. #
  781. #*/###########################################################################
  782. setMethodS3(
  783. "as.character",
  784. class="PhyloSim",
  785. function(
  786. x,
  787. ...
  788. ){
  789. return(getId(x));
  790. },
  791. private=FALSE,
  792. protected=FALSE,
  793. overwrite=FALSE,
  794. conflict="warning",
  795. validators=getOption("R.methodsS3:validators:setMethodS3")
  796. )
  797. ##
  798. ## Method: getName
  799. ##
  800. ###########################################################################/**
  801. #
  802. # @RdocMethod getName
  803. #
  804. # @title "Get the name of a PhyloSim object"
  805. #
  806. # \description{
  807. # @get "title".
  808. # }
  809. #
  810. # @synopsis
  811. #
  812. # \arguments{
  813. # \item{this}{A PhyloSim object.}
  814. # \item{...}{Not used.}
  815. # }
  816. #
  817. # \value{
  818. # A character vector of length one.
  819. # }
  820. #
  821. # \examples{
  822. # # create a PhyloSim object
  823. # o<-PhyloSim();
  824. # # set/get name
  825. # setName(o,"MySim");
  826. # getName(o,"MySim");
  827. # # set/get name via virtual field
  828. # o$name<-"George";
  829. # o$name
  830. # }
  831. #
  832. # @author
  833. #
  834. # \seealso{
  835. # @seeclass
  836. # }
  837. #
  838. #*/###########################################################################
  839. setMethodS3(
  840. "getName",
  841. class="PhyloSim",
  842. function(
  843. this,
  844. ...
  845. ){
  846. this$.name;
  847. },
  848. private=FALSE,
  849. protected=FALSE,
  850. overwrite=FALSE,
  851. conflict="warning",
  852. validators=getOption("R.methodsS3:validators:setMethodS3")
  853. );
  854. ##
  855. ## Method: setName
  856. ##
  857. ###########################################################################/**
  858. #
  859. # @RdocMethod setName
  860. #
  861. # @title "Set the name of a PhyloSim object"
  862. #
  863. # \description{
  864. # @get "title".
  865. # }
  866. #
  867. # @synopsis
  868. #
  869. # \arguments{
  870. # \item{this}{A PhyloSim object.}
  871. # \item{new.name}{A character vector of length one.}
  872. # \item{...}{Not used.}
  873. # }
  874. #
  875. # \value{
  876. # The new name.
  877. # }
  878. #
  879. # \examples{
  880. # # create a PhyloSim object
  881. # o<-PhyloSim();
  882. # # set/get name
  883. # setName(o,"MySim");
  884. # getName(o,"MySim");
  885. # # set/get name via virtual field
  886. # o$name<-"George";
  887. # o$name
  888. # }
  889. #
  890. # @author
  891. #
  892. # \seealso{
  893. # @seeclass
  894. # }
  895. #
  896. #*/###########################################################################
  897. setMethodS3(
  898. "setName",
  899. class="PhyloSim",
  900. function(
  901. this,
  902. new.name,
  903. ...
  904. ){
  905. this$.name<-as.character(new.name);
  906. },
  907. private=FALSE,
  908. protected=FALSE,
  909. overwrite=FALSE,
  910. conflict="warning",
  911. validators=getOption("R.methodsS3:validators:setMethodS3")
  912. );
  913. ##
  914. ## Method: getId
  915. ##
  916. ###########################################################################/**
  917. #
  918. # @RdocMethod getId
  919. #
  920. # @title "Get the unique identifier of a PhyloSim object"
  921. #
  922. # \description{
  923. # @get "title".
  924. # The unique identifier is the concatenation of the class, the object name as returned by getName() and the object hash
  925. # as returned by hashCode().
  926. # }
  927. #
  928. # @synopsis
  929. #
  930. # \arguments{
  931. # \item{this}{A PhyloSim object.}
  932. # \item{...}{Not used.}
  933. # }
  934. #
  935. # \value{
  936. # A character vector of length one.
  937. # }
  938. #
  939. # \examples{
  940. # # create a PhyloSim object
  941. # o<-PhyloSim(name="MySim");
  942. # # get id
  943. # getId(o);
  944. # # get id via virtual field
  945. # o$id;
  946. # }
  947. #
  948. # @author
  949. #
  950. # \seealso{
  951. # @seeclass
  952. # }
  953. #
  954. #*/###########################################################################
  955. setMethodS3(
  956. "getId",
  957. class="PhyloSim",
  958. function(
  959. this,
  960. ...
  961. ){
  962. this.class<-class(this)[1];
  963. id<-paste(this.class,this$.name,hashCode(this),sep=":");
  964. return(id);
  965. },
  966. private=FALSE,
  967. protected=FALSE,
  968. overwrite=FALSE,
  969. conflict="warning",
  970. validators=getOption("R.methodsS3:validators:setMethodS3")
  971. );
  972. ##
  973. ## Method: setId
  974. ##
  975. ###########################################################################/**
  976. #
  977. # @RdocMethod setId
  978. #
  979. # @title "Forbidden action: setting the unique identifier of a PhyloSim object"
  980. #
  981. # \description{
  982. # @get "title".
  983. #
  984. # }
  985. #
  986. # @synopsis
  987. #
  988. # \arguments{
  989. # \item{this}{An object.}
  990. # \item{value}{Not used.}
  991. # \item{...}{Not used.}
  992. # }
  993. #
  994. # \value{
  995. # Throws an error.
  996. # }
  997. #
  998. # @author
  999. #
  1000. # \seealso{
  1001. # @seeclass
  1002. # }
  1003. #
  1004. #*/###########################################################################
  1005. setMethodS3(
  1006. "setId",
  1007. class="PhyloSim",
  1008. function(
  1009. this,
  1010. value,
  1011. ...
  1012. ){
  1013. throw("Id is generated automatically and it cannot be set!\n");
  1014. },
  1015. private=FALSE,
  1016. protected=FALSE,
  1017. overwrite=FALSE,
  1018. conflict="warning",
  1019. validators=getOption("R.methodsS3:validators:setMethodS3")
  1020. );
  1021. ##
  1022. ## Method: Simulate
  1023. ##
  1024. ###########################################################################/**
  1025. #
  1026. # @RdocMethod Simulate
  1027. #
  1028. # @title "Run a simulation according to a PhyloSim object"
  1029. #
  1030. # \description{
  1031. # @get "title".
  1032. #
  1033. # The phylo object and the root sequence must be set before attempting to run a simulation.
  1034. # Also the bigRate of the root sequence must not be NA or zero, so at least one sane
  1035. # Process object must be attached to the root sequence object.
  1036. # }
  1037. #
  1038. # @synopsis
  1039. #
  1040. # \arguments{
  1041. # \item{this}{A PhyloSim object.}
  1042. # \item{quiet}{TRUE or FALSE (default).}
  1043. # \item{...}{Not used.}
  1044. # }
  1045. #
  1046. # \value{
  1047. # The PhyloSim object (invisible).
  1048. # }
  1049. #
  1050. # \examples{
  1051. # # Create a PhyloSim object.
  1052. # # Provide the phylo object
  1053. # # and the root sequence.
  1054. # sim<-PhyloSim(
  1055. # name="TinySim",
  1056. # phylo=rcoal(3),
  1057. # root.seq=NucleotideSequence(string="ATGC",processes=list(list(JC69())))
  1058. # );
  1059. # # Run the simulation
  1060. # Simulate(sim);
  1061. # # Print the resulting sequences
  1062. # sim$sequences
  1063. # # Print the resulting alignment
  1064. # sim$alignment
  1065. # }
  1066. #
  1067. # @author
  1068. #
  1069. # \seealso{
  1070. # @seeclass
  1071. # }
  1072. #
  1073. #*/###########################################################################
  1074. setMethodS3(
  1075. "Simulate",
  1076. class="PhyloSim",
  1077. function(
  1078. this,
  1079. quiet=FALSE,
  1080. ...
  1081. ){
  1082. if(!is.phylo(this$.phylo)){
  1083. throw("Cannot simulate because the phylo object is not set or it is invalid!\n");
  1084. }
  1085. # Check for the root sequence:
  1086. else if(!is.Sequence(this$.root.sequence)){
  1087. throw("Cannot simulate because the root sequence is not set or it is invalid!\n");
  1088. }
  1089. # Check bigRate validity:
  1090. else if(is.na(this$.root.sequence$bigRate)){
  1091. throw("Cannot simulate because the bigRate of the root sequence is NA!\n");
  1092. }
  1093. else{
  1094. # Warn for zero bigRate:
  1095. if(this$.root.sequence$bigRate == 0){
  1096. warning("The bigRate of the root sequence is zero! You are running a pointless simulation!\n");
  1097. }
  1098. if(exists(x="PSIM_FAST")){
  1099. if(!quiet){
  1100. cat("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
  1101. cat("!! WARNING: fast & careless mode is on, most of the error checking is omitted! !!\n");
  1102. cat("!! Please note that this also disables the saving of branch statistics. !!\n");
  1103. cat("!! You can go back to normal mode by deleting the PSIM_FAST object. !!\n");
  1104. cat("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
  1105. }
  1106. Log(this,"WARNING: fast & careless mode is on, most of the error checking is omitted!");
  1107. }
  1108. # Attach root sequence to root node:
  1109. Log(this,paste("Attaching root sequence ",this$.root.sequence$id,sep=""));
  1110. attachSeqToNode(this, node=getRootNode(this),seq=this$.root.sequence);
  1111. # Write protecting the root sequence:
  1112. Log(this,paste("Write protecting root sequence ",this$.root.sequence$id,sep=""));
  1113. this$.root.sequence$writeProtected<-TRUE;
  1114. # Traverse the tree and simulate:
  1115. Log(this,paste("Starting simulation on the object",this$id));
  1116. edge.counter<-1;
  1117. n.edges<-this$nedges;
  1118. for(edge in 1:n.edges){
  1119. if(!quiet){ cat("Simulating edge",edge,"of", n.edges,"\n");}
  1120. Log(this,paste("Starting to simulate edge",edge,"of",n.edges));
  1121. .simulateEdge(this,number=edge);
  1122. edge.counter<-edge.counter+1;
  1123. }
  1124. }
  1125. Log(this, "Simulation finished, building alignment!\n");
  1126. this$.alignment<-.recoverAlignment(this);
  1127. # Flush the log connection:
  1128. if(!is.na(this$.log.connection)){
  1129. close(this$.log.connection);
  1130. }
  1131. # Call the garbage collector:
  1132. gc();
  1133. gc();
  1134. return(invisible(this));
  1135. },
  1136. private=FALSE,
  1137. protected=FALSE,
  1138. overwrite=FALSE,
  1139. conflict="warning",
  1140. validators=getOption("R.methodsS3:validators:setMethodS3")
  1141. );
  1142. ##
  1143. ## Method: .simulateEdge
  1144. ##
  1145. setMethodS3(
  1146. ".simulateEdge",
  1147. class="PhyloSim",
  1148. function(
  1149. this,
  1150. number=NA,
  1151. ...
  1152. ){
  1153. # Get edge:
  1154. edge<-getEdge(this, number);
  1155. # Get parent node:
  1156. start.seq<-getSeqFromNode(this, edge[[1,"from"]]);
  1157. # Evolve sequence:
  1158. new.seq<-.evolveBranch(this, start.seq=start.seq, branch.length=edge[1,"length"], old.node=edge[[1,"from"]],new.node=edge[[1,"to"]], branch.number=number);
  1159. # Write protect the sequence:
  1160. new.seq$writeProtected<-TRUE;
  1161. # Attach sequence to children node:
  1162. attachSeqToNode(this, node=edge[1,"to"], seq=new.seq);
  1163. },
  1164. private=TRUE,
  1165. protected=FALSE,
  1166. overwrite=FALSE,
  1167. conflict="warning",
  1168. validators=getOption("R.methodsS3:validators:setMethodS3")
  1169. );
  1170. ##
  1171. ## Method: .evolveBranch
  1172. ##
  1173. setMethodS3(
  1174. ".evolveBranch",
  1175. class="PhyloSim",
  1176. function(
  1177. this,
  1178. start.seq=NA,
  1179. branch.length=NA,
  1180. old.node=NA,
  1181. new.node=NA,
  1182. branch.number=NA,
  1183. ...
  1184. ){
  1185. if(!exists(x="PSIM_FAST")){
  1186. if(missing(start.seq)){
  1187. throw("No starting sequence provided!\n");
  1188. }
  1189. else if(missing(branch.length)){
  1190. throw("No branch length provided!\n");
  1191. }
  1192. else if(!is.numeric(branch.length)){
  1193. throw("The branch length must be numeric!\n");
  1194. }
  1195. }
  1196. if(.checkSeq(this, start.seq) ){
  1197. # Cloning the starting sequence:
  1198. seq<-clone(start.seq);
  1199. # Set the name of the sequence object:
  1200. if(is.tip(this, new.node)){
  1201. seq$name<-this$tipLabels[[new.node]];
  1202. }
  1203. else {
  1204. seq$name<-paste("Node",new.node);
  1205. }
  1206. .GillespieDirect(this, seq=seq, branch.length=branch.length, branch.number=branch.number);
  1207. # Call the node hook if exists:
  1208. hook<-this$.node.hooks[[as.character(new.node)]];
  1209. if(!is.null(hook) & is.function(hook)){
  1210. Log(this,paste("Calling node hook for node",new.node));
  1211. seq<-hook(seq=seq);
  1212. if(!is.Sequence(seq)){
  1213. throw("Node hook returned an invalid sequence object!\n");
  1214. }
  1215. else if(is.na(seq$bigRate)){
  1216. throw("Node hook returned sequence with NA bigRate!\n");
  1217. }
  1218. else if(seq$bigRate == 0.0){
  1219. throw("Node hook returned sequence with zero bigRate!\n");
  1220. }
  1221. else{
  1222. checkConsistency(seq, omit.sites=TRUE);
  1223. }
  1224. }
  1225. # Return the resulting sequence object:
  1226. return(seq);
  1227. }
  1228. },
  1229. private=FALSE,
  1230. protected=FALSE,
  1231. overwrite=FALSE,
  1232. conflict="warning",
  1233. validators=getOption("R.methodsS3:validators:setMethodS3")
  1234. );
  1235. ##
  1236. ## Method: .GillespieDirect
  1237. ##
  1238. setMethodS3(
  1239. ".GillespieDirect",
  1240. class="PhyloSim",
  1241. function(
  1242. this,
  1243. seq=NA,
  1244. branch.length=NA,
  1245. branch.number=NA,
  1246. ...
  1247. ){
  1248. Debug(this, paste("Branch length is",branch.length));
  1249. # Initialize time:
  1250. time<-0.0;
  1251. # Sample the next waiting time until
  1252. # the branch length is consumed:
  1253. while( (time<-time + rexp(n=1, rate=(big.rate<-getBigRate(seq)))) <= branch.length){
  1254. # Generate a random number between zero and the bigRate:
  1255. E<-runif(n=1,min=0,max=big.rate);
  1256. # Identify the target site:
  1257. site.number<-which(.getCumulativeRatesFast(seq) >= E)[[1]];
  1258. # Get the events from the target site:
  1259. site<-seq$.sites[[site.number]];
  1260. site$.position<-site.number;
  1261. events<-getEvents(site);
  1262. site$.position<-NULL;
  1263. # Get the rates:
  1264. rates<-double();
  1265. for(e in events){
  1266. rates<-c(rates,e$.rate);
  1267. }
  1268. # Calculate the corresponding cumulative rates:
  1269. if(site.number > 1){
  1270. rates<-cumsum(c(seq$.cumulative.rates[[site.number - 1]], rates));
  1271. }
  1272. else {
  1273. rates<-cumsum(c(0.0, rates));
  1274. }
  1275. # Pick the event:
  1276. event.number<-which(rates >= E)[[1]] - 1;
  1277. event<-events[[event.number]];
  1278. # Log the event:
  1279. Log(this,paste("Performing event [",event$.name,"] at position",event$.position,"generated by the process",event$.process$.id));
  1280. # Perform the event:
  1281. event.details<-Perform(event);
  1282. Debug(this,paste("Remaining branch length is",(branch.length-time) ));
  1283. # Log event details:
  1284. # Log deletion event details:
  1285. if(event$.name == "Deletion"){
  1286. Log(this,paste("The process",event$.process,"proposed to delete range",paste(event.details$range,collapse="--"),". Accepted:",event.details$accepted));
  1287. }
  1288. # Log insertion event details:
  1289. else if(event$.name == "Insertion"){
  1290. message<-paste("The process ",event$.process," proposed insertion at position ",event.details$position,". Accepted: ",event.details$accepted,sep="");
  1291. if(event.details$accepted == TRUE){
  1292. message<-paste(message,"."," Insert length was ",event.details$length,sep="");
  1293. }
  1294. Log(this, message);
  1295. }
  1296. # Update branch statistics if not in fast mode:
  1297. if(!exists(x="PSIM_FAST")){
  1298. .UpdateBranchStats(this,event,event.details, branch.number);
  1299. }
  1300. # Abort if sequence length shrunk to zero:
  1301. if(seq$.length == 0){
  1302. message<-paste("Terminating the simulation because the length of the sequence ",seq$name," shrunk to zero! Please be more careful when tuning the indel rates!\n");
  1303. Log(this, message);
  1304. throw(message);
  1305. }
  1306. } #/while
  1307. # Calling garbage collection:
  1308. gc();
  1309. gc();
  1310. return(seq);
  1311. },
  1312. private=FALSE,
  1313. protected=FALSE,
  1314. overwrite=FALSE,
  1315. conflict="warning",
  1316. validators=getOption("R.methodsS3:validators:setMethodS3")
  1317. );
  1318. ##
  1319. ## Method: attachSeqToNode
  1320. ##
  1321. ###########################################################################/**
  1322. #
  1323. # @RdocMethod attachSeqToNode
  1324. #
  1325. # @title "Assotiate a Sequence object with a given node of a phylo object aggregated by a PhyloSim object"
  1326. #
  1327. # \description{
  1328. # @get "title".
  1329. #
  1330. # This method is mainly used internally.
  1331. #
  1332. # }
  1333. #
  1334. # @synopsis
  1335. #
  1336. # \arguments{
  1337. # \item{this}{A PhyloSim object.}
  1338. # \item{node}{Node identifier.}
  1339. # \item{seq}{A Sequence object.}
  1340. # \item{...}{Not used.}
  1341. # }
  1342. #
  1343. # \value{
  1344. # The PhyloSim object (invisible).
  1345. # }
  1346. #
  1347. #
  1348. # @author
  1349. #
  1350. # \seealso{
  1351. # @seeclass
  1352. # }
  1353. #
  1354. #*/###########################################################################
  1355. setMethodS3(
  1356. "attachSeqToNode",
  1357. class="PhyloSim",
  1358. function(
  1359. this,
  1360. node=NA,
  1361. seq=NA,
  1362. ...
  1363. ){
  1364. if(!is.phylo(this$.phylo)){
  1365. throw("The phylo object is not set, sequence to node is not possible!\n");
  1366. }
  1367. if(missing(node)){
  1368. throw("No node specified!\n");
  1369. }
  1370. else if(missing(seq)){
  1371. throw("No sequence object given");
  1372. }
  1373. else if(.checkNode(this,node) & .checkSeq(this, seq)){
  1374. if(is.Sequence(this$.sequences[[node]])){
  1375. throw("The node has already an attached sequence. Detach that before trying to attach a new one!\n");
  1376. }
  1377. else {
  1378. this$.sequences[[as.numeric(node)]]<-seq;
  1379. return(invisible(this));
  1380. }
  1381. }
  1382. return(invisible(this));
  1383. },
  1384. private=FALSE,
  1385. protected=FALSE,
  1386. overwrite=FALSE,
  1387. conflict="warning",
  1388. validators=getOption("R.methodsS3:validators:setMethodS3")
  1389. );
  1390. ##
  1391. ## Method: attachHookToNode
  1392. ##
  1393. ###########################################################################/**
  1394. #
  1395. # @RdocMethod attachHookToNode
  1396. #
  1397. # @title "Attach a callback function to a given node of a phylo object aggregated by a PhyloSim object"
  1398. #
  1399. # \description{
  1400. # @get "title".
  1401. #
  1402. # A "node hook" is a function which accepts a Sequence object through the named argument "seq" and returns a
  1403. # Sequence object. The node hook function must accept any object which inherits from the \code{Sequence} class!
  1404. #
  1405. # After simulating the branch leading to the node, the resulting Sequence object is passed
  1406. # to the node hook and the returned object is used to simulate the downstream branches.
  1407. #
  1408. # By using node hooks the attached processes can be replaced during simulation, hence enabling the simulation of
  1409. # non-homogeneous sequence evolution.
  1410. # }
  1411. #
  1412. # @synopsis
  1413. #
  1414. # \arguments{
  1415. # \item{this}{A PhyloSim object.}
  1416. # \item{node}{Node identifier.}
  1417. # \item{fun}{A function (see above).}
  1418. # \item{...}{Not used.}
  1419. # }
  1420. #
  1421. # \value{
  1422. # The PhyloSim object (invisible).
  1423. # }
  1424. #
  1425. # \examples{
  1426. # # Create a PhyloSim object.
  1427. # # Provide the phylo object
  1428. # # and the root sequence.
  1429. # sim<-PhyloSim(
  1430. # name="TinySim",
  1431. # phylo=rcoal(3),
  1432. # root.seq=NucleotideSequence(string="ATGC",processes=list(list(JC69())))
  1433. # );
  1434. # # create a node hook function
  1435. # hook<-function(seq=NA){
  1436. # # replace the substitution process with F84
  1437. # if(inherits(seq,"NucleotideSequence")){
  1438. # cat("Replacing JC69 with F84.\n");
  1439. # seq$processes<-list(list(F84(rate.params=list("Kappa" = 2))));
  1440. # }
  1441. # return(seq);
  1442. # }
  1443. # # attach hook function to node 5
  1444. # attachHookToNode(sim,5,hook);
  1445. # # Run the simulation
  1446. # Simulate(sim);
  1447. # # Check if the processes have been truly replaced
  1448. # lapply(sim$sequences, getUniqueProcesses.Sequence)
  1449. # # Print the resulting alignment
  1450. # sim$alignment
  1451. # }
  1452. #
  1453. # @author
  1454. #
  1455. # \seealso{
  1456. # @seeclass
  1457. # }
  1458. #
  1459. #*/###########################################################################
  1460. setMethodS3(
  1461. "attachHookToNode",
  1462. class="PhyloSim",
  1463. function(
  1464. this,
  1465. node=NA,
  1466. fun=NA,
  1467. ...
  1468. ){
  1469. if(!is.phylo(this$.phylo)){
  1470. throw("The phylo object is not set, attaching node hook is not possible!\n");
  1471. }
  1472. if(missing(node)){
  1473. throw("No node specified!\n");
  1474. }
  1475. else if(missing(fun)){
  1476. throw("No function given!");
  1477. }
  1478. else if(!is.function(fun)){
  1479. throw("The argument \"fun\" must be a function!\n");
  1480. }
  1481. else if( length(intersect(names(formals(fun)), "seq")) == 0 ){
  1482. throw("The function argument must have a an argument named \"seq\"");
  1483. }
  1484. else if(!is.Sequence(fun(Sequence(length=1)))){
  1485. throw("The insert hook function must return a Sequence object!\n");
  1486. }
  1487. else if( .checkNode(this,node) ){
  1488. if(is.function(this$.node.hooks[[as.character(node)]])){
  1489. throw("The node has already an attached node hook. Detach that before trying to attach a new one!\n");
  1490. }
  1491. else {
  1492. this$.node.hooks[[as.character(node)]]<-fun;
  1493. return(invisible(this));
  1494. }
  1495. }
  1496. return(invisible(this));
  1497. },
  1498. private=FALSE,
  1499. protected=FALSE,
  1500. overwrite=FALSE,
  1501. conflict="warning",
  1502. validators=getOption("R.methodsS3:validators:setMethodS3")
  1503. );
  1504. ##
  1505. ## Method: .checkNode
  1506. ##
  1507. setMethodS3(
  1508. ".checkNode",
  1509. class="PhyloSim",
  1510. function(
  1511. this,
  1512. node=NA,
  1513. ...
  1514. ){
  1515. if(missing(node)){
  1516. throw("No node specified!\n");
  1517. } else if( length(intersect(node, getNodes(this))) != 1){
  1518. throw("The specified node is invalid!\n");
  1519. }
  1520. else {
  1521. return(TRUE);
  1522. }
  1523. },
  1524. private=FALSE,
  1525. protected=FALSE,
  1526. overwrite=FALSE,
  1527. conflict="warning",
  1528. validators=getOption("R.methodsS3:validators:setMethodS3")
  1529. );
  1530. ##
  1531. ## Method: .checkSeq
  1532. ##
  1533. setMethodS3(
  1534. ".checkSeq",
  1535. class="PhyloSim",
  1536. function(
  1537. this,
  1538. seq=NA,
  1539. ...
  1540. ){
  1541. if(missing(seq)){
  1542. throw("No sequence specified!\n");
  1543. } else if(!is.Sequence(seq)){
  1544. throw("The sequence object is invalid!\n");
  1545. }
  1546. else {
  1547. return(TRUE);
  1548. }
  1549. },
  1550. private=FALSE,
  1551. protected=FALSE,
  1552. overwrite=FALSE,
  1553. conflict="warning",
  1554. validators=getOption("R.methodsS3:validators:setMethodS3")
  1555. );
  1556. ##
  1557. ## Method: detachSeqFromNode
  1558. ##
  1559. ###########################################################################/**
  1560. #
  1561. # @RdocMethod detachSeqFromNode
  1562. #
  1563. # @title "Detach a Sequence object from a given node of a phylo object aggregated by a PhyloSim object"
  1564. #
  1565. # \description{
  1566. # @get "title".
  1567. #
  1568. # This method is mainly used internally.
  1569. #
  1570. # }
  1571. #
  1572. # @synopsis
  1573. #
  1574. # \arguments{
  1575. # \item{this}{A PhyloSim object.}
  1576. # \item{node}{Node identifier.}
  1577. # \item{...}{Not used.}
  1578. # }
  1579. #
  1580. # \value{
  1581. # The PhyloSim object (invisible).
  1582. # }
  1583. #
  1584. # @author
  1585. #
  1586. # \seealso{
  1587. # @seeclass
  1588. # }
  1589. #
  1590. #*/###########################################################################
  1591. setMethodS3(
  1592. "detachSeqFromNode",
  1593. class="PhyloSim",
  1594. function(
  1595. this,
  1596. node=NA,
  1597. ...
  1598. ){
  1599. if(missing(node)){
  1600. throw("No node specified!\n");
  1601. }
  1602. else if( .checkNode(this,node) ){
  1603. this$.sequences[[as.numeric(node)]]<-NA;
  1604. }
  1605. return(invisible(this));
  1606. },
  1607. private=FALSE,
  1608. protected=FALSE,
  1609. overwrite=FALSE,
  1610. conflict="warning",
  1611. validators=getOption("R.methodsS3:validators:setMethodS3")
  1612. );
  1613. ##
  1614. ## Method: detachHookFromNode
  1615. ##
  1616. ###########################################################################/**
  1617. #
  1618. # @RdocMethod detachHookFromNode
  1619. #
  1620. # @title "Detach a node hook function from a given node of a phylo object aggregated by a PhyloSim object"
  1621. #
  1622. # \description{
  1623. # @get "title".
  1624. #
  1625. # }
  1626. #
  1627. # @synopsis
  1628. #
  1629. # \arguments{
  1630. # \item{this}{A PhyloSim object.}
  1631. # \item{node}{Node identifier.}
  1632. # \item{...}{Not used.}
  1633. # }
  1634. #
  1635. # \value{
  1636. # The PhyloSim object (invisible).
  1637. # }
  1638. #
  1639. # \examples{
  1640. # # Create a PhyloSim object.
  1641. # # Provide the phylo object
  1642. # # and the root sequence.
  1643. # sim<-PhyloSim(
  1644. # name="TinySim",
  1645. # phylo=rcoal(3),
  1646. # root.seq=NucleotideSequence(string="ATGC",processes=list(list(JC69())))
  1647. # );
  1648. # # create a node hook function
  1649. # hook<-function(seq=NA){
  1650. # # replace the substitution process with F84
  1651. # if(inherits(seq,"NucleotideSequence")){
  1652. # cat("Replacing JC69 with F84.\n");
  1653. # seq$processes<-list(list(F84(rate.params=list("Kappa" = 2))));
  1654. # }
  1655. # return(seq);
  1656. # }
  1657. # # attach hook function to node 5
  1658. # attachHookToNode(sim,5,hook);
  1659. # # detach hook from node 5
  1660. # detachHookFromNode(sim,5);
  1661. # # Run the simulation again
  1662. # Simulate(sim); # You should not see the message printed out by the "hook" function.
  1663. #
  1664. # }
  1665. #
  1666. # @author
  1667. #
  1668. # \seealso{
  1669. # attachHookToNode PhyloSim Simulate.PhyloSim
  1670. # }
  1671. #
  1672. #*/###########################################################################
  1673. setMethodS3(
  1674. "detachHookFromNode",
  1675. class="PhyloSim",
  1676. function(
  1677. this,
  1678. node=NA,
  1679. ...
  1680. ){
  1681. if(missing(node)){
  1682. throw("No node specified!\n");
  1683. }
  1684. else if( .checkNode(this,node) ){
  1685. this$.node.hooks[[as.character(node)]]<-NA;
  1686. }
  1687. return(invisible(this));
  1688. },
  1689. private=FALSE,
  1690. protected=FALSE,
  1691. overwrite=FALSE,
  1692. conflict="warning",
  1693. validators=getOption("R.methodsS3:validators:setMethodS3")
  1694. );
  1695. ##
  1696. ## Method: getSeqFromNode
  1697. ##
  1698. ###########################################################################/**
  1699. #
  1700. # @RdocMethod getSeqFromNode
  1701. #
  1702. # @title "Get the Sequence object associated with a given node of a phylo object aggregated by a PhyloSim object"
  1703. #
  1704. # \description{
  1705. # @get "title".
  1706. # }
  1707. #
  1708. # @synopsis
  1709. #
  1710. # \arguments{
  1711. # \item{this}{A PhyloSim object.}
  1712. # \item{node}{Node identifier.}
  1713. # \item{...}{Not used.}
  1714. # }
  1715. #
  1716. # \value{
  1717. # A Sequence object.
  1718. # }
  1719. #
  1720. # \examples{
  1721. # # Create a PhyloSim object.
  1722. # # Provide the phylo object
  1723. # # and the root sequence.
  1724. # sim<-PhyloSim(
  1725. # name="TinySim",
  1726. # phylo=rcoal(3),
  1727. # root.seq=NucleotideSequence(string="ATG",processes=list(list(JC69())))
  1728. # );
  1729. # # get the sequence associated with node 5
  1730. # getSeqFromNode(sim,5) # Should be NA
  1731. # # Run the simulation
  1732. # Simulate(sim)
  1733. # # try again
  1734. # getSeqFromNode(sim,5)
  1735. # }
  1736. #
  1737. # @author
  1738. #
  1739. # \seealso{
  1740. # @seeclass
  1741. # }
  1742. #
  1743. #*/###########################################################################
  1744. setMethodS3(
  1745. "getSeqFromNode",
  1746. class="PhyloSim",
  1747. function(
  1748. this,
  1749. node=NA,
  1750. ...
  1751. ){
  1752. if(missing(node)){
  1753. throw("No node specified!\n");
  1754. }
  1755. else if( .checkNode(this,node) ){
  1756. return(this$.sequences[[as.numeric(node)]]);
  1757. }
  1758. },
  1759. private=FALSE,
  1760. protected=FALSE,
  1761. overwrite=FALSE,
  1762. conflict="warning",
  1763. validators=getOption("R.methodsS3:validators:setMethodS3")
  1764. );
  1765. ##
  1766. ## Method: getSequences
  1767. ##
  1768. ###########################################################################/**
  1769. #
  1770. # @RdocMethod getSequences
  1771. #
  1772. # @title "Gets all the Sequence objects associated with the nodes of a phylo object aggregated by a PhyloSim object"
  1773. #
  1774. # \description{
  1775. # @get "title".
  1776. #
  1777. # The order of the Sequence objects in the returned list reflects the identifiers of the associated nodes.
  1778. # }
  1779. #
  1780. # @synopsis
  1781. #
  1782. # \arguments{
  1783. # \item{this}{A PhyloSim object.}
  1784. # \item{...}{Not used.}
  1785. # }
  1786. #
  1787. # \value{
  1788. # A list of sequence objects.
  1789. # }
  1790. #
  1791. # \examples{
  1792. # # Create a PhyloSim object.
  1793. # # Provide the phylo object
  1794. # # and the root sequence.
  1795. # sim<-PhyloSim(
  1796. # name="TinySim",
  1797. # phylo=rcoal(3),
  1798. # root.seq=NucleotideSequence(string="ATG",processes=list(list(JC69())))
  1799. # );
  1800. # # run the simulation
  1801. # Simulate(sim)
  1802. # # get all the associated sequence objects
  1803. # getSequences(sim)
  1804. # # get the sequence associated with node 3
  1805. # # via virtual field
  1806. # sim$sequences[[3]]
  1807. # }
  1808. #
  1809. # @author
  1810. #
  1811. # \seealso{
  1812. # @seeclass
  1813. # }
  1814. #
  1815. #*/###########################################################################
  1816. setMethodS3(
  1817. "getSequences",
  1818. class="PhyloSim",
  1819. function(
  1820. this,
  1821. ...
  1822. ){
  1823. slist<-list();
  1824. for (node in getNodes(this)){
  1825. slist[[node]]<-getSeqFromNode(this, node=node);
  1826. }
  1827. return(slist);
  1828. },
  1829. private=FALSE,
  1830. protected=FALSE,
  1831. overwrite=FALSE,
  1832. conflict="warning",
  1833. validators=getOption("R.methodsS3:validators:setMethodS3")
  1834. );
  1835. ##
  1836. ## Method: setSequences
  1837. ##
  1838. ###########################################################################/**
  1839. #
  1840. # @RdocMethod setSequences
  1841. #
  1842. # @title "Forbidden action: setting the Sequence objects associated with the nodes of a phylo object aggregated by a PhyloSim object"
  1843. #
  1844. # \description{
  1845. # @get "title".
  1846. # }
  1847. #
  1848. # @synopsis
  1849. #
  1850. # \arguments{
  1851. # \item{this}{An object.}
  1852. # \item{value}{Not used.}
  1853. # \item{...}{Not used.}
  1854. # }
  1855. #
  1856. # \value{
  1857. # Throws an error.
  1858. # }
  1859. #
  1860. # @author
  1861. #
  1862. # \seealso{
  1863. # @seeclass
  1864. # }
  1865. #
  1866. #*/###########################################################################
  1867. setMethodS3(
  1868. "setSequences",
  1869. class="PhyloSim",
  1870. function(
  1871. this,
  1872. value,
  1873. ...
  1874. ){
  1875. virtualAssignmentForbidden(this);
  1876. },
  1877. private=FALSE,
  1878. protected=FALSE,
  1879. overwrite=FALSE,
  1880. conflict="warning",
  1881. validators=getOption("R.methodsS3:validators:setMethodS3")
  1882. );
  1883. ##
  1884. ## Method: getAlignment
  1885. ##
  1886. ###########################################################################/**
  1887. #
  1888. # @RdocMethod getAlignment
  1889. #
  1890. # @title "Get the alignment stored in a PhyloSim object"
  1891. #
  1892. # \description{
  1893. # @get "title".
  1894. # }
  1895. #
  1896. # @synopsis
  1897. #
  1898. # \arguments{
  1899. # \item{this}{A PhyloSim object.}
  1900. # \item{...}{Not used.}
  1901. # }
  1902. #
  1903. # \value{
  1904. # The alignment as a matrix. Gap are represented by strings composed of dashes.
  1905. # }
  1906. #
  1907. # \examples{
  1908. # # Create a PhyloSim object.
  1909. # # Provide the phylo object
  1910. # # and the root sequence.
  1911. # sim<-PhyloSim(
  1912. # name="TinySim",
  1913. # phylo=rcoal(3),
  1914. # root.seq=NucleotideSequence(string="ATG",processes=list(list(JC69())))
  1915. # );
  1916. # # run the simulation
  1917. # Simulate(sim)
  1918. # # get the resulting aligment
  1919. # getAlignment(sim)
  1920. # # via virtual fileld:
  1921. # sim$alignment
  1922. # }
  1923. #
  1924. # @author
  1925. #
  1926. # \seealso{
  1927. # @seeclass
  1928. # }
  1929. #
  1930. #*/###########################################################################
  1931. setMethodS3(
  1932. "getAlignment",
  1933. class="PhyloSim",
  1934. function(
  1935. this,
  1936. ...
  1937. ){
  1938. this$.alignment;
  1939. },
  1940. private=FALSE,
  1941. protected=FALSE,
  1942. overwrite=FALSE,
  1943. conflict="warning",
  1944. validators=getOption("R.methodsS3:validators:setMethodS3")
  1945. );
  1946. ##
  1947. ## Method: setAlignment
  1948. ##
  1949. ###########################################################################/**
  1950. #
  1951. # @RdocMethod setAlignment
  1952. #
  1953. # @title "Forbidden action: setting the alignment stored in a PhyloSim object"
  1954. #
  1955. # \description{
  1956. # @get "title".
  1957. # }
  1958. #
  1959. # @synopsis
  1960. #
  1961. # \arguments{
  1962. # \item{this}{An object.}
  1963. # \item{value}{Not used.}
  1964. # \item{...}{Not used.}
  1965. # }
  1966. #
  1967. # \value{
  1968. # Throws an error.
  1969. # }
  1970. #
  1971. # @author
  1972. #
  1973. # \seealso{
  1974. # @seeclass
  1975. # }
  1976. #
  1977. #*/###########################################################################
  1978. setMethodS3(
  1979. "setAlignment",
  1980. class="PhyloSim",
  1981. function(
  1982. this,
  1983. value,
  1984. ...
  1985. ){
  1986. this$alignment <- value;
  1987. },
  1988. private=FALSE,
  1989. protected=FALSE,
  1990. overwrite=FALSE,
  1991. conflict="warning",
  1992. validators=getOption("R.methodsS3:validators:setMethodS3")
  1993. );
  1994. ##
  1995. ## Method: .recoverAlignment
  1996. ##
  1997. setMethodS3(
  1998. ".recoverAlignment",
  1999. class="PhyloSim",
  2000. function(
  2001. this,
  2002. paranoid=FALSE,
  2003. ...
  2004. ){
  2005. # Refuse to build alignment if at least one of the sequences is NA:
  2006. for (seq in this$.sequences){
  2007. if(!is.Sequence(seq)){
  2008. throw("Cannot build alignment because the simulation is incomplete!\n");
  2009. }
  2010. }
  2011. # The list holding all the partial alignment matrices:
  2012. aln.mat<-list();
  2013. # Assigning NA-s here to prevent creation of these variables in the global
  2014. # environment.
  2015. row.names<-NA;
  2016. from.node<-NA;
  2017. to.node<-NA;
  2018. from.seq<-NA;
  2019. to.seq<-NA;
  2020. edge<-NA;
  2021. from.name<-NA;
  2022. to.name<-NA;
  2023. from.mat<-NA;
  2024. to.mat<-NA;
  2025. # Initialize the variables:
  2026. init.vars<-function(){
  2027. # Getting the edge:
  2028. edge<<-getEdge(this, edge.number);
  2029. # Getting the nodes:
  2030. from.node<<-edge[[1,"from"]];
  2031. to.node<<-edge[[1,"to"]];
  2032. # Getting the sequence objects:
  2033. from.seq<<-getSeqFromNode(this, from.node)
  2034. to.seq<<-getSeqFromNode(this, to.node)
  2035. # Getting sequence names:
  2036. from.name<<-from.seq$name;
  2037. to.name<<-to.seq$name;
  2038. }
  2039. # Initialize the aligment matrices:
  2040. init.aln.mats