bpp-phyl  2.2.0
DecompositionSubstitutionCount.cpp
Go to the documentation of this file.
1 //
2 // File: DecompositionSubstitutionCount.h
3 // Created by: Julien Dutheil
4 // Created on: Thu Mar 17 16:08 2011
5 //
6 
7 /*
8 Copyright or © or Copr. Bio++ Development Team, (November 16, 2004, 2005, 2006)
9 
10 This software is a computer program whose purpose is to provide classes
11 for phylogenetic data analysis.
12 
13 This software is governed by the CeCILL license under French law and
14 abiding by the rules of distribution of free software. You can use,
15 modify and/ or redistribute the software under the terms of the CeCILL
16 license as circulated by CEA, CNRS and INRIA at the following URL
17 "http://www.cecill.info".
18 
19 As a counterpart to the access to the source code and rights to copy,
20 modify and redistribute granted by the license, users are provided only
21 with a limited warranty and the software's author, the holder of the
22 economic rights, and the successive licensors have only limited
23 liability.
24 
25 In this respect, the user's attention is drawn to the risks associated
26 with loading, using, modifying and/or developing or reproducing the
27 software by the user in light of its specific status of free software,
28 that may mean that it is complicated to manipulate, and that also
29 therefore means that it is reserved for developers and experienced
30 professionals having in-depth computer knowledge. Users are therefore
31 encouraged to load and test the software's suitability as regards their
32 requirements in conditions enabling the security of their systems and/or
33 data to be ensured and, more generally, to use and operate it in the
34 same conditions as regards security.
35 
36 The fact that you are presently reading this means that you have had
37 knowledge of the CeCILL license and that you accept its terms.
38 */
39 
41 
42 #include "Bpp/Numeric/Matrix/MatrixTools.h"
43 #include <vector>
44 
45 using namespace bpp;
46 using namespace std;
47 
48 /******************************************************************************/
49 
52  AbstractWeightedSubstitutionCount(weights, true),
53  model_(model),
54  nbStates_(model->getNumberOfStates()),
55  jMat_(nbStates_, nbStates_),
56  v_(nbStates_, nbStates_),
57  vInv_(nbStates_, nbStates_),
58  lambda_(nbStates_, nbStates_),
59  bMatrices_(reg->getNumberOfSubstitutionTypes()),
60  insideProducts_(reg->getNumberOfSubstitutionTypes()),
61  counts_(reg->getNumberOfSubstitutionTypes()),
62  currentLength_(-1.)
63 {
64  //Check compatiblity between model and substitution register:
65  if (model->getAlphabet()->getAlphabetType() != reg->getAlphabet()->getAlphabetType())
66  throw Exception("DecompositionSubstitutionCount (constructor): alphabets do not match between register and model.");
67 
68  //Initialize all B matrices according to substitution register. This is done once for all,
69  //unless the number of states changes:
72  computeEigen_();
74 }
75 
76 /******************************************************************************/
77 
79 {
80  vector<int> supportedStates = model_->getAlphabetStates();
81  for (size_t j = 0; j < nbStates_; ++j) {
82  for (size_t k = 0; k < nbStates_; ++k) {
83  size_t i = register_->getType(j, k);
84  if (i > 0 && k != j) {
85  //jdutheil on 25/07/14: I think this is incorrect, weights should only come at the end.
86  //bMatrices_[i - 1](j, k) = model_->Qij(j, k) * (weights_ ? weights_->getIndex(fromState, toState) : 1);
87  bMatrices_[i - 1](j, k) = model_->Qij(j, k);
88  }
89  }
90  }
91 }
92 
94 {
98 }
99 
101 {
102  for (size_t i = 0; i < register_->getNumberOfSubstitutionTypes(); ++i) {
103  //vInv_ %*% bMatrices_[i] %*% v_;
104  RowMatrix<double> tmp(nbStates_, nbStates_);
105  MatrixTools::mult(vInv_, bMatrices_[i], tmp);
106  MatrixTools::mult(tmp, v_, insideProducts_[i]);
107  }
108 }
109 
111 {
112  size_t nbTypes = register_->getNumberOfSubstitutionTypes();
113  bMatrices_.resize(nbTypes);
114  insideProducts_.resize(nbTypes);
115  counts_.resize(nbTypes);
116 }
117 
119 {
120  jMat_.resize(nbStates_, nbStates_);
121  v_.resize(nbStates_, nbStates_);
122  vInv_.resize(nbStates_, nbStates_);
123  lambda_.resize(nbStates_);
124 }
125 
127 {
128  //Re-initialize all B matrices according to substitution register.
129  for (size_t i = 0; i < register_->getNumberOfSubstitutionTypes(); ++i) {
130  bMatrices_[i].resize(nbStates_, nbStates_);
131  insideProducts_[i].resize(nbStates_, nbStates_);
132  counts_[i].resize(nbStates_, nbStates_);
133  }
134 }
135 
136 void DecompositionSubstitutionCount::jFunction_(const std::vector<double>& lambda, double t, RowMatrix<double>& result) const
137 {
138  vector<double> expLam = VectorTools::exp(lambda * t);
139  for (unsigned int i = 0; i < nbStates_; ++i) {
140  for (unsigned int j = 0; j < nbStates_; ++j) {
141  double dd = lambda[i] - lambda[j];
142  if (dd == 0) {
143  result(i, j) = t * expLam[i];
144  } else {
145  result(i, j) = (expLam[i] - expLam[j]) / dd;
146  }
147  }
148  }
149 }
150 
151 /******************************************************************************/
152 
154 {
155  jFunction_(lambda_, length, jMat_);
156  for (size_t i = 0; i < register_->getNumberOfSubstitutionTypes(); ++i) {
157  RowMatrix<double> tmp1(nbStates_, nbStates_), tmp2(nbStates_, nbStates_);
158  MatrixTools::hadamardMult(jMat_, insideProducts_[i], tmp1);
159  MatrixTools::mult(v_, tmp1, tmp2);
160  MatrixTools::mult(tmp2, vInv_, counts_[i]);
161  }
162  // Now we must divide by pijt and account for putative weights:
163  vector<int> supportedStates = model_->getAlphabetStates();
164  RowMatrix<double> P = model_->getPij_t(length);
165  for (size_t i = 0; i < register_->getNumberOfSubstitutionTypes(); i++) {
166  for (size_t j = 0; j < nbStates_; j++) {
167  for (size_t k = 0; k < nbStates_; k++) {
168  counts_[i](j, k) /= P(j, k);
169  if (isnan(counts_[i](j, k)) || counts_[i](j, k) < 0.) {
170  counts_[i](j, k) = 0.;
171  //Weights:
172  if (weights_)
173  counts_[i](j, k) *= weights_->getIndex(supportedStates[j], supportedStates[k]);
174  }
175  }
176  }
177  }
178 }
179 
180 /******************************************************************************/
181 
182 Matrix<double>* DecompositionSubstitutionCount::getAllNumbersOfSubstitutions(double length, size_t type) const
183 {
184  if (length < 0)
185  throw Exception("DecompositionSubstitutionCount::getAllNumbersOfSubstitutions. Negative branch length: " + TextTools::toString(length) + ".");
186  if (length != currentLength_)
187  {
188  //if (length < 0.000001) // Limit case!
189  //{
190  // unsigned int s = model_->getAlphabet()->getSize();
191  // for (unsigned int i = 0; i < s; i++)
192  // {
193  // for (unsigned int j = 0; j < s; j++)
194  // {
195  // m_(i, j) = i == j ? 0. : 1.;
196  // }
197  // }
198  //}
199  //else
200  //{
201  // Else we need to recompute M:
202  computeCounts_(length);
203  //}
204 
205  currentLength_ = length;
206  }
207  return new RowMatrix<double>(counts_[type - 1]);
208 }
209 
210 /******************************************************************************/
211 
212 double DecompositionSubstitutionCount::getNumberOfSubstitutions(size_t initialState, size_t finalState, double length, size_t type) const
213 {
214  if (length < 0)
215  throw Exception("DecompositionSubstitutionCount::getNumbersOfSubstitutions. Negative branch length: " + TextTools::toString(length) + ".");
216  if (length != currentLength_)
217  {
218  computeCounts_(length);
219  currentLength_ = length;
220  }
221  return counts_[type - 1](initialState, finalState);
222 }
223 
224 /******************************************************************************/
225 
226 std::vector<double> DecompositionSubstitutionCount::getNumberOfSubstitutionsForEachType(size_t initialState, size_t finalState, double length) const
227 {
228  if (length < 0)
229  throw Exception("DecompositionSubstitutionCount::getNumbersOfSubstitutions. Negative branch length: " + TextTools::toString(length) + ".");
230  if (length != currentLength_)
231  {
232  computeCounts_(length);
233  currentLength_ = length;
234  }
235  std::vector<double> v(getNumberOfSubstitutionTypes());
236  for (size_t t = 0; t < getNumberOfSubstitutionTypes(); ++t) {
237  v[t] = counts_[t](initialState, finalState);
238  }
239  return v;
240 }
241 
242 /******************************************************************************/
243 
245 {
246  const ReversibleSubstitutionModel* rModel = dynamic_cast<const ReversibleSubstitutionModel*>(model);
247  if (!rModel)
248  throw Exception("DecompositionSubstitutionCount::setSubstitutionModel. Only works with reversible models for now.");
249 
250  //Check compatiblity between model and substitution register:
251  if (model->getAlphabet()->getAlphabetType() != register_->getAlphabet()->getAlphabetType())
252  throw Exception("DecompositionSubstitutionCount::setSubstitutionModel: alphabets do not match between register and model.");
253  model_ = rModel;
254  unsigned int n = model->getAlphabet()->getSize();
255  if (n != nbStates_) {
256  nbStates_ = n;
257  resetStates_();
258  initBMatrices_();
259  }
260  fillBMatrices_();
261  computeEigen_();
263 
264  //Recompute counts:
266 }
267 
268 /******************************************************************************/
269 
271 {
272  //Check compatiblity between model and substitution register:
273  if (model_->getAlphabet()->getAlphabetType() != register_->getAlphabet()->getAlphabetType())
274  throw Exception("DecompositionSubstitutionCount::substitutionRegisterHasChanged: alphabets do not match between register and model.");
275 
276  resetBMatrices_();
277  initBMatrices_();
278  fillBMatrices_();
280 
281  //Recompute counts:
282  if (currentLength_ > 0)
284 }
285 
286 /******************************************************************************/
287 
289 {
290  if (weights_->getAlphabet()->getAlphabetType() != register_->getAlphabet()->getAlphabetType())
291  throw Exception("DecompositionSubstitutionCount::weightsHaveChanged. Incorrect alphabet type.");
292 
293  //jdutheil on 25/07/14: not necessary if weights are only accounted for in the end.
294  //fillBMatrices_();
295 
296  //Recompute counts:
297  if (currentLength_ > 0)
299 }
300 
301 /******************************************************************************/
302 
std::vector< double > getNumberOfSubstitutionsForEachType(size_t initialState, size_t finalState, double length) const
Get the numbers of susbstitutions on a branch for all types, for an initial and final states...
Interface for all substitution models.
std::auto_ptr< SubstitutionRegister > register_
const ReversibleSubstitutionModel * model_
virtual const std::vector< int > & getAlphabetStates() const =0
Basic implementation of the the SubstitutionCount interface.
double getNumberOfSubstitutions(size_t initialState, size_t finalState, double length, size_t type=1) const
Get the number of susbstitutions on a branch, given the initial and final states, and the branch leng...
The SubstitutionRegister interface.
virtual const Alphabet * getAlphabet() const =0
STL namespace.
virtual const Vdouble & getEigenValues() const =0
virtual const Matrix< double > & getPij_t(double t) const =0
std::vector< RowMatrix< double > > counts_
Interface for reversible substitution models.
virtual size_t getNumberOfSubstitutionTypes() const
Short cut function, equivalent to getSubstitutionRegister().getNumberOfSubstitutionTypes().
virtual double Qij(size_t i, size_t j) const =0
Matrix< double > * getAllNumbersOfSubstitutions(double length, size_t type=1) const
Get the numbers of susbstitutions on a branch, for each initial and final states, and given the branc...
void setSubstitutionModel(const SubstitutionModel *model)
Set the substitution model.
DecompositionSubstitutionCount(const ReversibleSubstitutionModel *model, SubstitutionRegister *reg, const AlphabetIndex2 *weights=0)
virtual const Matrix< double > & getRowLeftEigenVectors() const =0
virtual const Matrix< double > & getColumnRightEigenVectors() const =0
std::vector< RowMatrix< double > > insideProducts_
Partial implementation of the WeightedSubstitutionCount interface.
void jFunction_(const std::vector< double > &lambda, double t, RowMatrix< double > &result) const
virtual const Alphabet * getAlphabet() const =0
std::vector< RowMatrix< double > > bMatrices_