/auteur/src/vmat.cpp

http://github.com/eastman/auteur · C++ · 195 lines · 108 code · 30 blank · 57 comment · 15 complexity · b97dd10751bc4268b037e00663e41ee3 MD5 · raw file

  1. #include <Rcpp.h>
  2. #include <vector>
  3. /*
  4. * FUNCTIONS TO GENERATE VARIANCE-COVARIANCE MATRIX from an S3 'phylo' object from the R-package ape (Paradis E, J Claude, and K Strimmer 2004 [BIOINFORMATICS 20:289-290])
  5. * author: Jonathan M Eastman 01.11.2011
  6. */
  7. /* INTERNAL C++ */
  8. void sortedges(std::vector<double> const &unsortededges,
  9. std::vector<double> &edges,
  10. std::vector<int> const &des)
  11. {
  12. std::vector<int>::size_type i,j;
  13. //int i, j;
  14. for(i=0; i<edges.size(); i++) {
  15. for(j=0; j<des.size(); j++){
  16. if(des.at(j)==(signed)i+1)
  17. {
  18. edges.at(i)=unsortededges.at(j);
  19. }
  20. }
  21. }
  22. }
  23. /* INTERNAL C++ */
  24. void gatherdescendants(int const &node,
  25. int const &root,
  26. int const &endofclade,
  27. std::vector<int> &TIPS,
  28. std::vector<int> const &anc,
  29. std::vector<int> const &des)
  30. {
  31. /*
  32. * node: current internal node
  33. * root: most internal node
  34. * endofclade: number of rows in the phylogenetic edge matrix (of the 'phylo' object)
  35. * TIPS: vector in which to store all (tip) descendants of node (by node label)
  36. * anc: first column of 'phylo' edge matrix (e.g., phy$edge[,1])
  37. * des: second column of 'phylo' edge matrix (e.g., phy$edge[,2])
  38. */
  39. int i, eoc=endofclade, r=root, n=node;
  40. for(i=0; i<eoc; i++) {
  41. if(anc.at(i) == n)
  42. {
  43. if(des.at(i)>r)
  44. {
  45. gatherdescendants(des.at(i), r, eoc, TIPS, anc, des);
  46. }
  47. else
  48. {
  49. TIPS.push_back(des.at(i));
  50. }
  51. }
  52. }
  53. }
  54. /* INTERNAL C++ */
  55. void descend_vcv(int const &node,
  56. double const &edge,
  57. int const &root,
  58. int const &endofclade,
  59. std::vector<int> const &anc,
  60. std::vector<int> const &des,
  61. std::vector<double> &vcv)
  62. {
  63. /*
  64. * node: internal node of which descendants are recorded
  65. * edge: length to add to covariances of all descendants where 'node' is internal
  66. * root: node to initiate vcv update
  67. * endofclade: rows in the phylogenetic edge matrix (of the 'phylo' object)
  68. * anc: first column of phylo edge matrix (e.g., phy$edge[,1]
  69. * des: second column of phylo edge matrix (e.g., phy$edge[,2]
  70. * vcv: the current variance-covariance matrix
  71. * TIPS: an empty vector in which to store all (tip) descendants of node
  72. */
  73. int n;
  74. std::vector<int>::size_type a,b,j;
  75. n=root-1;
  76. std::vector<int> TIPS;
  77. TIPS.reserve(root-1);
  78. gatherdescendants(node, root, endofclade, TIPS, anc, des);
  79. /* add 'edge' length of 'node' to covariances V[a,b] where a and b are tips descended from 'node' and a!=b [OFFDIAGONAL ELEMENTS in V] */
  80. for(a=0; a<TIPS.size(); a++) {
  81. for(b=a; b<TIPS.size(); b++) {
  82. if(a!=b)
  83. {
  84. vcv[ TIPS.at(a)-1 + n*( TIPS.at(b)-1 ) ] = vcv[ TIPS.at(b)-1 + n*(TIPS.at(a)-1 ) ] += edge;
  85. }
  86. }
  87. }
  88. /* add 'edge' length of 'node' to variances of V[a,b] where a and b are tips descended from 'node' and a==b [DIAGONAL ELEMENTS in V]*/
  89. for(j=0; j<TIPS.size(); j++) {
  90. vcv[ TIPS.at(j)-1 + n*( TIPS.at(j)-1 ) ] += edge;
  91. }
  92. std::vector<int>().swap(TIPS);
  93. }
  94. /* INTERNAL C++ */
  95. void vcv_internal (int const &maxnode,
  96. int const &root,
  97. int const &endofclade,
  98. std::vector<int> const &anc,
  99. std::vector<int> const &des,
  100. std::vector<double> const &edges,
  101. std::vector<double> &vcv)
  102. {
  103. /*
  104. * maxnode: largest internal node
  105. * root: most internal node
  106. * endofclade: number of rows in the phylogenetic edge matrix (of the 'phylo' object)
  107. * anc: first column of phylo edge matrix (e.g., phy$edge[,1]
  108. * des: second column of phylo edge matrix (e.g., phy$edge[,2]
  109. * edges: sorted branch lengths (by node label), including the root (ntips+1)
  110. * vcv: the current state of the variance-covariance matrix
  111. */
  112. int n, nn, r=root, mx=maxnode, eoc=endofclade;
  113. nn=r-1;
  114. /* cycle over internal nodes within the tree; tree stem does not contribute to VCV so is skipped */
  115. for(n=r+1; n<=mx; n++) {
  116. /* find descendants of n; add edge length of n to variances for tips and covariances among tips */
  117. descend_vcv(n, edges.at(n-1), r, eoc, anc, des, vcv);
  118. }
  119. /* add leaves to lengths in V[n,n] where n is a tip [DIAGONAL ELEMENTS in V]*/
  120. for(n=1; n<r; n++) {
  121. vcv[ n-1 + nn*( n-1 ) ] += edges.at(n-1);
  122. }
  123. }
  124. /* C++ | R INTERFACE; main function */
  125. RcppExport SEXP vmat (SEXP tree)
  126. {
  127. /*
  128. * tree: a list of elements
  129. * ROOT: most internal node
  130. * MAXNODE: least internal internal node (and largest valued in edge matrix)
  131. * ENDOFCLADE: rows in edge matrix
  132. * ANC: first column of 'phylo' edge matrix (e.g., phy$edge[,1])
  133. * DES: second column of 'phylo' edge matrix (e.g., phy$edge[,2])
  134. * EDGES: edge lengths, sorted by node label and including the root (at position Ntip(phy)+1)
  135. * VCV: the current state of the variance-covariance matrix, initialized with 0s in R
  136. */
  137. try {
  138. std::vector<int>::size_type i;
  139. /* call in parameters associated with 'phylo' object */
  140. Rcpp::List phylo(tree);
  141. int root = (int) Rcpp::as<int>(phylo["ROOT"]);
  142. int maxnode = Rcpp::as<int>(phylo["MAXNODE"]);
  143. int endofclade = Rcpp::as<int>(phylo["ENDOFCLADE"]);
  144. std::vector<int> anc=phylo["ANC"];
  145. std::vector<int> des=phylo["DES"];
  146. std::vector<double> unsortededges=phylo["EDGES"];
  147. std::vector<double> edges=phylo["EDGES"];
  148. std::vector<double> V=phylo["VCV"];
  149. /* initialize edges */
  150. for(i=0; i<edges.size(); i++) {
  151. edges.at(i)=0;
  152. }
  153. /* sort edges by node label */
  154. sortedges(unsortededges, edges, des);
  155. /* call to primary function that updates VCV matrix */
  156. vcv_internal(maxnode, root, endofclade, anc, des, edges, V);
  157. /* PREPARE OUTPUT FOR R */
  158. return Rcpp::List::create(Rcpp::Named("VCV",V));
  159. } catch( std::exception &ex ) {
  160. forward_exception_to_r( ex );
  161. } catch(...) {
  162. ::Rf_error( "C++ exception: unknown reason" );
  163. }
  164. return R_NilValue;
  165. }