bpp-phyl  2.2.0
YpR.cpp
Go to the documentation of this file.
1 //
2 // File: YpR.cpp
3 // Created by: Laurent Gueguen
4 // Created on: Thu August 2 2007
5 //
6 
7 /*
8  Copyright or © or Copr. CNRS, (November 16, 2004)
9  This software is a computer program whose purpose is to provide
10  classes for phylogenetic data analysis.
11 
12  This software is governed by the CeCILL license under French law and
13  abiding by the rules of distribution of free software. You can use,
14  modify and/ or redistribute the software under the terms of the CeCILL
15  license as circulated by CEA, CNRS and INRIA at the following URL
16  "http://www.cecill.info".
17 
18  As a counterpart to the access to the source code and rights to copy,
19  modify and redistribute granted by the license, users are provided
20  only with a limited warranty and the software's author, the holder of
21  the economic rights, and the successive licensors have only limited
22  liability.
23 
24  In this respect, the user's attention is drawn to the risks associated
25  with loading, using, modifying and/or developing or reproducing the
26  software by the user in light of its specific status of free software,
27  that may mean that it is complicated to manipulate, and that also
28  therefore means that it is reserved for developers and experienced
29  professionals having in-depth computer knowledge. Users are therefore
30  encouraged to load and test the software's suitability as regards
31  their requirements in conditions enabling the security of their
32  systems and/or data to be ensured and, more generally, to use and
33  operate it in the same conditions as regards security.
34 
35  The fact that you are presently reading this means that you have had
36  knowledge of the CeCILL license and that you accept its terms.
37  */
38 
39 #include "YpR.h"
40 
41 // From the STL:
42 #include <cmath>
43 
44 using namespace bpp;
45 
46 #include <Bpp/Numeric/Matrix/MatrixTools.h>
47 #include <Bpp/Numeric/VectorTools.h>
48 #include <Bpp/Numeric/Matrix/EigenValue.h>
49 
50 #include <Bpp/Text/TextTools.h>
51 
52 /******************************************************************************/
53 
54 YpR::YpR(const RNY* alph, SubstitutionModel* const pm, const std::string& prefix) :
55  AbstractParameterAliasable(prefix),
56  AbstractSubstitutionModel(alph, new CanonicalStateMap(alph, false), prefix),
57  pmodel_(pm->clone()),
58  _nestedPrefix(pm->getNamespace())
59 {
60  pmodel_->setNamespace(prefix + _nestedPrefix);
62  addParameters_(pmodel_->getParameters());
63 }
64 
65 YpR::YpR(const YpR& ypr, const std::string& prefix) :
66  AbstractParameterAliasable(ypr),
68  pmodel_(ypr.pmodel_->clone()),
69  _nestedPrefix(ypr.getNestedPrefix())
70 
71 {
72  pmodel_->setNamespace(prefix + _nestedPrefix);
73 }
74 
75 YpR::YpR(const YpR& ypr) :
76  AbstractParameterAliasable(ypr),
78  pmodel_(ypr.pmodel_->clone()),
79  _nestedPrefix(ypr.getNestedPrefix())
80 {}
81 
83 {
84  updateMatrices(0, 0, 0, 0, 0, 0, 0, 0);
85 }
86 
87 
88 void YpR::updateMatrices(double CgT, double cGA,
89  double TgC, double tGA,
90  double CaT, double cAG,
91  double TaC, double tAC)
92 {
93  // check_model(pmodel_);
94 
95  // Generator:
96  const Alphabet* alph = pmodel_->getAlphabet();
97  std::vector<size_t> l(4);
98 
99  l[0] = alph->getStateIndex("A");
100  l[1] = alph->getStateIndex("G");
101  l[2] = alph->getStateIndex("C");
102  l[3] = alph->getStateIndex("T");
103 
104  unsigned int i, j, i1, i2, i3, j1, j2, j3;
105 
106  std::vector<double> a(4); // a[A], a[G], a[C], a[T]
107  std::vector<double> b(4); // b[A], b[G], b[C], b[T]
108 
109  for (i = 0; i < 2; i++)
110  {
111  a[i] = pmodel_->Qij(l[1 - i], l[i]);
112  b[i] = pmodel_->Qij(l[3 - i], l[i]);
113  a[i + 2] = pmodel_->Qij(l[3 - i], l[i + 2]);
114  b[i + 2] = pmodel_->Qij(l[1 - i], l[i + 2]);
115  }
116 
117  // M_1
118  RowMatrix<double> M1(3, 3);
119 
120  M1(0, 0) = 0;
121  M1(0, 1) = b[2];
122  M1(0, 2) = b[3];
123  M1(1, 0) = b[0] + b[1];
124  M1(1, 1) = 0;
125  M1(1, 2) = a[3];
126  M1(2, 0) = b[0] + b[1];
127  M1(2, 1) = a[2];
128  M1(2, 2) = 0;
129 
130  // M_2
131  RowMatrix<double> M2(4, 4);
132 
133  M2(0, 0) = 0;
134  M2(0, 1) = a[1];
135  M2(0, 2) = b[2];
136  M2(0, 3) = b[3];
137  M2(1, 0) = a[0];
138  M2(1, 1) = 0;
139  M2(1, 2) = b[2];
140  M2(1, 3) = b[3];
141  M2(2, 0) = b[0];
142  M2(2, 1) = b[1];
143  M2(2, 2) = 0;
144  M2(2, 3) = a[3];
145  M2(3, 0) = b[0];
146  M2(3, 1) = b[1];
147  M2(3, 2) = a[2];
148  M2(3, 3) = 0;
149 
150  // M_3
151  RowMatrix<double> M3(3, 3);
152 
153  M3(0, 0) = 0;
154  M3(0, 1) = a[1];
155  M3(0, 2) = b[2] + b[3];
156  M3(1, 0) = a[0];
157  M3(1, 1) = 0;
158  M3(1, 2) = b[2] + b[3];
159  M3(2, 0) = b[0];
160  M3(2, 1) = b[1];
161  M3(2, 2) = 0;
162 
163 
164  for (i1 = 0; i1 < 3; i1++)
165  {
166  for (i2 = 0; i2 < 4; i2++)
167  {
168  for (i3 = 0; i3 < 3; i3++)
169  {
170  i = 12 * i1 + 3 * i2 + i3;
171  for (j1 = 0; j1 < 3; j1++)
172  {
173  for (j2 = 0; j2 < 4; j2++)
174  {
175  for (j3 = 0; j3 < 3; j3++)
176  {
177  j = 12 * j1 + 3 * j2 + j3;
178  if ((i1 == j1) && (i2 == j2))
179  generator_(i, j) = M3(i3, j3);
180  else if ((i1 == j1) && (i3 == j3))
181  generator_(i, j) = M2(i2, j2);
182  else if ((i2 == j2) && (i3 == j3))
183  generator_(i, j) = M1(i1, j1);
184  else
185  generator_(i, j) = 0;
186  }
187  }
188  }
189  }
190  }
191  }
192 
193  // Introduction des dependances
194 
195  for (i3 = 0; i3 < 3; i3++)
196  {
197  generator_(15 + i3, 12 + i3) += cGA * a[0]; // CG -> CA
198  generator_(12 * i3 + 7, 12 * i3 + 6) += cGA * a[0];
199 
200  generator_(15 + i3, 27 + i3) += CgT * a[3]; // CG -> TG
201  generator_(12 * i3 + 7, 12 * i3 + 10) += CgT * a[3];
202 
203  generator_(27 + i3, 24 + i3) += tGA * a[0]; // TG -> TA
204  generator_(12 * i3 + 10, 12 * i3 + 9) += tGA * a[0];
205 
206  generator_(27 + i3, 15 + i3) += TgC * a[2]; // TG -> CG
207  generator_(12 * i3 + 10, 12 * i3 + 7) += TgC * a[2];
208 
209  generator_(12 + i3, 24 + i3) += CaT * a[3]; // CA -> TA
210  generator_(12 * i3 + 6, 12 * i3 + 9) += CaT * a[3];
211 
212  generator_(12 + i3, 15 + i3) += cAG * a[1]; // CA -> CG
213  generator_(12 * i3 + 6, 12 * i3 + 7) += cAG * a[1];
214 
215  generator_(24 + i3, 27 + i3) += tAC * a[1]; // TA -> TG
216  generator_(12 * i3 + 9, 12 * i3 + 10) += tAC * a[1];
217 
218  generator_(24 + i3, 12 + i3) += TaC * a[2]; // TA -> CA
219  generator_(12 * i3 + 9, 12 * i3 + 6) += TaC * a[2];
220  }
221 
222  double x;
223 
224  for (i = 0; i < 36; i++)
225  {
226  x = 0;
227  for (j = 0; j < 36; j++)
228  {
229  if (j != i)
230  x += generator_(i, j);
231  }
232  generator_(i, i) = -x;
233  }
234 
235  // calcul spectral
236 
237  EigenValue<double> ev(generator_);
238  eigenValues_ = ev.getRealEigenValues();
239  iEigenValues_ = ev.getImagEigenValues();
240 
241  rightEigenVectors_ = ev.getV();
242 
243  try
244  {
245  MatrixTools::inv(rightEigenVectors_, leftEigenVectors_);
246 
247  isNonSingular_ = true;
248  isDiagonalizable_ = true;
249  for (i = 0; i < size_; i++)
250  {
251  if (abs(iEigenValues_[i]) > NumConstants::TINY())
252  {
253  isDiagonalizable_ = false;
254  }
255  }
256 
257  // frequence stationnaire
258 
259  x = 0;
260  j = 0;
261  while (j < 36)
262  {
263  if (abs(eigenValues_[j]) < NumConstants::SMALL() &&
264  abs(iEigenValues_[j]) < NumConstants::SMALL())
265  {
266  eigenValues_[j] = 0; // to avoid approximation problems in the future
267  for (i = 0; i < 36; i++)
268  {
269  freq_[i] = leftEigenVectors_(j, i);
270  x += freq_[i];
271  }
272  break;
273  }
274  j++;
275  }
276  for (i = 0; i < 36; i++)
277  {
278  freq_[i] /= x;
279  }
280  }
281  catch (ZeroDivisionException& e)
282  {
283  ApplicationTools::displayMessage("Singularity during diagonalization. Taylor series used instead.");
284  isNonSingular_ = false;
285  isDiagonalizable_ = false;
286 
287  if (vPowGen_.size() == 0)
288  vPowGen_.resize(30);
289 
290  double min = generator_(0, 0);
291  for (i = 1; i < 36; i++)
292  {
293  if (min > generator_(i, i))
294  min = generator_(i, i);
295  }
296 
297  MatrixTools::scale(generator_, -1 / min);
298 
299  MatrixTools::getId(36, tmpMat_); // to compute the equilibrium frequency (Q+Id)^256
300 
301  MatrixTools::add(tmpMat_, generator_);
302  MatrixTools::pow(tmpMat_, 256, vPowGen_[0]);
303 
304  for (i = 0; i < 36; i++)
305  {
306  freq_[i] = vPowGen_[0](0, i);
307  }
308 
309  MatrixTools::getId(36, vPowGen_[0]);
310  }
311 
312  // mise a l'echelle
313 
314  x = 0;
315  for (i1 = 0; i1 < 3; i1++)
316  {
317  for (i2 = 0; i2 < 4; i2++)
318  {
319  for (i3 = 0; i3 < 3; i3++)
320  {
321  i = 12 * i1 + 3 * i2 + i3;
322  for (j2 = 0; j2 < 4; j2++)
323  {
324  if (j2 != i2)
325  {
326  j = 12 * i1 + 3 * j2 + i3;
327  x += freq_[i] * generator_(i, j);
328  }
329  }
330  }
331  }
332  }
333 
334  MatrixTools::scale(generator_, 1 / x);
335 
336  if (!isNonSingular_)
337  MatrixTools::Taylor(generator_, 30, vPowGen_);
338 
339  for (i = 0; i < 36; i++)
340  {
341  eigenValues_[i] /= x;
342  iEigenValues_[i] /= x;
343  }
344 
345  // and the exchangeability_
346  for (i = 0; i < size_; i++)
347  {
348  for (j = 0; j < size_; j++)
349  {
350  exchangeability_(i, j) = generator_(i, j) / freq_[j];
351  }
352  }
353 }
354 
355 void YpR::check_model(SubstitutionModel* const pm) const
356 throw (Exception)
357 {
358  if (!pm)
359  throw Exception("No Model ");
360 
361  const Alphabet* alph = pm->getAlphabet();
362  if (alph->getAlphabetType() != "DNA alphabet")
363  throw Exception("Need a DNA model");
364 
365  std::vector<size_t> l(4);
366 
367  l[0] = alph->getStateIndex("A");
368  l[1] = alph->getStateIndex("G");
369  l[2] = alph->getStateIndex("C");
370  l[3] = alph->getStateIndex("T");
371 
372  // Check that the model is good for YpR
373 
374  for (size_t i = 0; i < 2; ++i)
375  {
376  if (pm->Qij(l[2], l[i]) != pm->Qij(l[3], l[i]))
377  throw Exception("Not R/Y Model " + pm->getName());
378  }
379  for (size_t i = 2; i < 4; ++i)
380  {
381  if (pm->Qij(l[0], l[i]) != pm->Qij(l[1], l[i]))
382  throw Exception("Not R/Y Model " + pm->getName());
383  }
384 }
385 
386 void YpR::setNamespace(const std::string& prefix)
387 {
388  AbstractSubstitutionModel::setNamespace(prefix);
389  // We also need to update the namespace of the nested model:
390  pmodel_->setNamespace(prefix + _nestedPrefix);
391 }
392 
393 // ///////////////////////////////////////////////
394 // ///////////////////////////////////////////////
395 
396 
397 /******************************************************************************/
398 
399 YpR_Sym::YpR_Sym(const RNY* alph,
400  SubstitutionModel* const pm,
401  double CgT, double TgC,
402  double CaT, double TaC) : AbstractParameterAliasable("YpR_Sym."),
403  YpR(alph, pm, "YpR_Sym.")
404 {
405  addParameter_(new Parameter("YpR_Sym.rCgT", CgT, &Parameter::R_PLUS));
406  addParameter_(new Parameter("YpR_Sym.rTgC", TgC, &Parameter::R_PLUS));
407  addParameter_(new Parameter("YpR_Sym.rCaT", CaT, &Parameter::R_PLUS));
408  addParameter_(new Parameter("YpR_Sym.rTaC", TaC, &Parameter::R_PLUS));
409 
410  updateMatrices();
411 }
412 
414 {
415  double rCgT = getParameterValue("rCgT");
416  double rTgC = getParameterValue("rTgC");
417  double rCaT = getParameterValue("rCaT");
418  double rTaC = getParameterValue("rTaC");
419 
420  YpR::updateMatrices(rCgT, rCgT, rTgC, rTgC, rCaT, rCaT, rTaC, rTaC);
421 }
422 
423 YpR_Sym::YpR_Sym(const YpR_Sym& ypr) : AbstractParameterAliasable(ypr),
424  YpR(ypr, "YpR_Sym.")
425 {}
426 
427 /******************************************************************************/
428 
429 std::string YpR_Sym::getName() const
430 {
431  return "YpR_Sym";
432 }
433 
434 
435 // ///////////////////////////////////////////////
436 // ///////////////////////////////////////////////
437 
438 /******************************************************************************/
439 
440 YpR_Gen::YpR_Gen(const RNY* alph,
441  SubstitutionModel* const pm,
442  double CgT, double cGA,
443  double TgC, double tGA,
444  double CaT, double cAG,
445  double TaC, double tAG) : AbstractParameterAliasable("YpR_Gen."),
446  YpR(alph, pm, "YpR_Gen.")
447 {
448  addParameter_(new Parameter("YpR_Gen.rCgT", CgT, &Parameter::R_PLUS));
449  addParameter_(new Parameter("YpR_Gen.rcGA", cGA, &Parameter::R_PLUS));
450  addParameter_(new Parameter("YpR_Gen.rTgC", TgC, &Parameter::R_PLUS));
451  addParameter_(new Parameter("YpR_Gen.rtGA", tGA, &Parameter::R_PLUS));
452  addParameter_(new Parameter("YpR_Gen.rCaT", CaT, &Parameter::R_PLUS));
453  addParameter_(new Parameter("YpR_Gen.rcAG", cAG, &Parameter::R_PLUS));
454  addParameter_(new Parameter("YpR_Gen.rTaC", TaC, &Parameter::R_PLUS));
455  addParameter_(new Parameter("YpR_Gen.rtAG", tAG, &Parameter::R_PLUS));
456 
457  updateMatrices();
458 }
459 
461 {
462  double rCgT = getParameterValue("rCgT");
463  double rcGA = getParameterValue("rcGA");
464  double rTgC = getParameterValue("rTgC");
465  double rtGA = getParameterValue("rtGA");
466  double rCaT = getParameterValue("rCaT");
467  double rcAG = getParameterValue("rcAG");
468  double rTaC = getParameterValue("rTaC");
469  double rtAG = getParameterValue("rtAG");
470 
471  YpR::updateMatrices(rCgT, rcGA, rTgC, rtGA, rCaT, rcAG, rTaC, rtAG);
472 }
473 
474 YpR_Gen::YpR_Gen(const YpR_Gen& ypr) : AbstractParameterAliasable(ypr),
475  YpR(ypr, "YpR_Gen.")
476 {
477  updateMatrices();
478 }
479 
480 /******************************************************************************/
481 
482 std::string YpR_Gen::getName() const
483 {
484  return "YpR_Gen";
485 }
Interface for all substitution models.
virtual void updateMatrices()
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
Definition: YpR.cpp:82
void updateMatrices()
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
Definition: YpR.cpp:460
RowMatrix< double > exchangeability_
The exchangeability matrix of the model, defined as . When the model is reversible, this matrix is symetric.
std::string _nestedPrefix
Definition: YpR.h:133
bool isNonSingular_
boolean value for non-singularity of rightEigenVectors_
This class implements a state map where all resolved states are modeled.
Definition: StateMap.h:161
RowMatrix< double > rightEigenVectors_
The matrix made of right eigen vectors (by column).
Vdouble eigenValues_
The vector of eigen values.
YpR model.
Definition: YpR.h:123
std::string getName() const
Get the name of the model.
Definition: YpR.cpp:429
virtual const Alphabet * getAlphabet() const =0
Vdouble freq_
The vector of equilibrium frequencies.
YpR_Sym(const RNY *alph, SubstitutionModel *pm, double CgT=0., double TgC=0., double CaT=0., double TaC=0.)
Build a new YpR_Sym substitution model.
Definition: YpR.cpp:399
Partial implementation of the SubstitutionModel interface.
virtual void enableEigenDecomposition(bool yn)=0
Set if eigenValues and Vectors must be computed.
symetrical YpR model.
Definition: YpR.h:211
virtual double Qij(size_t i, size_t j) const =0
RowMatrix< double > leftEigenVectors_
The matrix made of left eigen vectors (by row) if rightEigenVectors_ is non-singular.
RowMatrix< double > generator_
The generator matrix of the model.
YpR(const RNY *, SubstitutionModel *const, const std::string &prefix)
Build a new YpR substitution model, with no dependency parameters.
Definition: YpR.cpp:54
std::vector< RowMatrix< double > > vPowGen_
vector of the powers of generator_ for Taylor development (if rightEigenVectors_ is singular)...
void check_model(SubstitutionModel *const) const
Definition: YpR.cpp:355
std::string getName() const
Get the name of the model.
Definition: YpR.cpp:482
SubstitutionModel * pmodel_
Definition: YpR.h:127
virtual void setNamespace(const std::string &)
Definition: YpR.cpp:386
General YpR model.
Definition: YpR.h:256
size_t size_
The size of the generator, i.e. the number of states.
void updateMatrices()
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
Definition: YpR.cpp:413
YpR_Gen(const RNY *alph, SubstitutionModel *pm, double CgT=0., double cGA=0., double TgC=0., double tGA=0., double CaT=0., double cAG=0., double TaC=0., double tAG=0.)
Build a new YpR_Gen substitution model.
Definition: YpR.cpp:440
RowMatrix< double > tmpMat_
For computational issues.
bool isDiagonalizable_
boolean value for diagonalizability in R of the generator_
Vdouble iEigenValues_
The vector of the imaginary part of the eigen values.