bpp-phyl3  3.0.0
YpR.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #include "YpR.h"
6 
7 // From the STL:
8 #include <cmath>
9 
10 using namespace bpp;
11 
15 
17 
18 #include <Bpp/Text/TextTools.h>
19 
20 /******************************************************************************/
21 
23  std::shared_ptr<const RNY> alph,
24  std::unique_ptr<NucleotideSubstitutionModelInterface> pm,
25  const string& prefix) :
27  AbstractSubstitutionModel(alph, make_shared<CanonicalStateMap>(alph, false), prefix),
28  pmodel_(pm->clone()),
29  nestedPrefix_(pm->getNamespace())
30 {
31  pmodel_->setNamespace(prefix + nestedPrefix_);
32  pmodel_->enableEigenDecomposition(0);
33  pmodel_->computeFrequencies(false);
34 
35  addParameters_(pmodel_->getParameters());
36  computeFrequencies(true);
37 }
38 
39 YpR::YpR(const YpR& ypr) :
42  pmodel_(ypr.pmodel_->clone()),
43  nestedPrefix_(ypr.getNestedPrefix())
44 {
45 }
46 
48 {
49  updateMatrices_(0, 0, 0, 0, 0, 0, 0, 0);
50 }
51 
52 
53 void YpR::updateMatrices_(double CgT, double cGA,
54  double TgC, double tGA,
55  double CaT, double cAG,
56  double TaC, double tAC)
57 {
59 
60  // Generator:
61  unsigned int i, j, i1, i2, i3, j1, j2, j3;
62 
63  std::vector<double> a(4); // a[A], a[G], a[C], a[T]
64  std::vector<double> b(4); // b[A], b[G], b[C], b[T]
65 
66  // From M
67 
68  a[0] = pmodel_->Qij(2, 0);
69  a[1] = pmodel_->Qij(0, 2);
70  a[2] = pmodel_->Qij(3, 1);
71  a[3] = pmodel_->Qij(1, 3);
72  b[0] = (pmodel_->Qij(1, 0) + pmodel_->Qij(3, 0))/2; // To limit numerical issues
73  b[1] = (pmodel_->Qij(1, 2) + pmodel_->Qij(3, 2))/2;
74  b[2] = (pmodel_->Qij(0, 1) + pmodel_->Qij(2, 1))/2;
75  b[3] = (pmodel_->Qij(0, 3) + pmodel_->Qij(2, 3))/2;
76 
77 
78 
79  // M_1 on R C T
80  RowMatrix<double> M1(3, 3);
81 
82  M1(0, 0) = 0;
83  M1(0, 1) = b[2];
84  M1(0, 2) = b[3];
85  M1(1, 0) = pmodel_->Qij(1, 0) + pmodel_->Qij(1, 2);
86  M1(1, 1) = 0;
87  M1(1, 2) = pmodel_->Qij(1, 3);
88  M1(2, 0) = pmodel_->Qij(3, 0) + pmodel_->Qij(3, 2);
89  M1(2, 1) = pmodel_->Qij(3, 1);
90  M1(2, 2) = 0;
91 
92  // M_2 on A G C T
93  RowMatrix<double> M2(4, 4);
94 
95  M2(0, 0) = 0;
96  M2(0, 1) = pmodel_->Qij(0, 2);
97  M2(0, 2) = pmodel_->Qij(0, 1);
98  M2(0, 3) = pmodel_->Qij(0, 3);
99  M2(1, 0) = pmodel_->Qij(2, 0);
100  M2(1, 1) = 0;
101  M2(1, 2) = pmodel_->Qij(2, 1);
102  M2(1, 3) = pmodel_->Qij(2, 3);
103  M2(2, 0) = pmodel_->Qij(1, 0);
104  M2(2, 1) = pmodel_->Qij(1, 2);
105  M2(2, 2) = 0;
106  M2(2, 3) = pmodel_->Qij(1, 3);
107  M2(3, 0) = pmodel_->Qij(3, 0);
108  M2(3, 1) = pmodel_->Qij(3, 2);
109  M2(3, 2) = pmodel_->Qij(3, 1);
110  M2(3, 3) = 0;
111 
112  // M_3 on A G Y
113  RowMatrix<double> M3(3, 3);
114 
115  M3(0, 0) = 0;
116  M3(0, 1) = pmodel_->Qij(0, 2);
117  M3(0, 2) = pmodel_->Qij(0, 1) + pmodel_->Qij(0, 3);
118  M3(1, 0) = pmodel_->Qij(2, 0);
119  M3(1, 1) = 0;
120  M3(1, 2) = pmodel_->Qij(2, 1) + pmodel_->Qij(2, 3);
121  M3(2, 0) = b[0];
122  M3(2, 1) = b[1];
123  M3(2, 2) = 0;
124 
125 
126  for (i1 = 0; i1 < 3; i1++)
127  {
128  for (i2 = 0; i2 < 4; i2++)
129  {
130  for (i3 = 0; i3 < 3; i3++)
131  {
132  i = 12 * i1 + 3 * i2 + i3;
133  for (j1 = 0; j1 < 3; j1++)
134  {
135  for (j2 = 0; j2 < 4; j2++)
136  {
137  for (j3 = 0; j3 < 3; j3++)
138  {
139  j = 12 * j1 + 3 * j2 + j3;
140  if ((i1 == j1) && (i2 == j2))
141  generator_(i, j) = M3(i3, j3);
142  else if ((i1 == j1) && (i3 == j3))
143  generator_(i, j) = M2(i2, j2);
144  else if ((i2 == j2) && (i3 == j3))
145  generator_(i, j) = M1(i1, j1);
146  else
147  generator_(i, j) = 0;
148  }
149  }
150  }
151  }
152  }
153  }
154 
155  // Introduction des dependances
156 
157  for (i3 = 0; i3 < 3; i3++)
158  {
159  generator_(15 + i3, 12 + i3) += cGA * a[0]; // CG -> CA
160  generator_(12 * i3 + 7, 12 * i3 + 6) += cGA * a[0];
161 
162  generator_(15 + i3, 27 + i3) += CgT * a[3]; // CG -> TG
163  generator_(12 * i3 + 7, 12 * i3 + 10) += CgT * a[3];
164 
165  generator_(27 + i3, 24 + i3) += tGA * a[0]; // TG -> TA
166  generator_(12 * i3 + 10, 12 * i3 + 9) += tGA * a[0];
167 
168  generator_(27 + i3, 15 + i3) += TgC * a[2]; // TG -> CG
169  generator_(12 * i3 + 10, 12 * i3 + 7) += TgC * a[2];
170 
171  generator_(12 + i3, 24 + i3) += CaT * a[3]; // CA -> TA
172  generator_(12 * i3 + 6, 12 * i3 + 9) += CaT * a[3];
173 
174  generator_(12 + i3, 15 + i3) += cAG * a[1]; // CA -> CG
175  generator_(12 * i3 + 6, 12 * i3 + 7) += cAG * a[1];
176 
177  generator_(24 + i3, 27 + i3) += tAC * a[1]; // TA -> TG
178  generator_(12 * i3 + 9, 12 * i3 + 10) += tAC * a[1];
179 
180  generator_(24 + i3, 12 + i3) += TaC * a[2]; // TA -> CA
181  generator_(12 * i3 + 9, 12 * i3 + 6) += TaC * a[2];
182  }
183 
184  double x;
185 
186  for (i = 0; i < 36; ++i)
187  {
188  x = 0;
189  for (j = 0; j < 36; ++j)
190  {
191  if (j != i)
192  x += generator_(i, j);
193  }
194  generator_(i, i) = -x;
195  }
196 
197  // calcul spectral
198 
202 
203  rightEigenVectors_ = ev.getV();
204 
205  try
206  {
208 
209  isNonSingular_ = true;
210  isDiagonalizable_ = true;
211  for (i = 0; i < size_; i++)
212  {
214  {
215  isDiagonalizable_ = false;
216  }
217  }
218 
219  // frequence stationnaire
220 
221  x = 0;
222  j = 0;
223  while (j < 36)
224  {
225  if (abs(eigenValues_[j]) < NumConstants::SMALL() &&
227  {
228  eigenValues_[j] = 0; // to avoid approximation problems in the future
229  for (i = 0; i < 36; i++)
230  {
231  freq_[i] = leftEigenVectors_(j, i);
232  x += freq_[i];
233  }
234  break;
235  }
236  j++;
237  }
238  for (i = 0; i < 36; i++)
239  {
240  freq_[i] /= x;
241  }
242  }
243  catch (ZeroDivisionException& e)
244  {
245  ApplicationTools::displayMessage("Singularity during diagonalization. Taylor series used instead.");
246  isNonSingular_ = false;
247  isDiagonalizable_ = false;
248 
249  if (vPowGen_.size() == 0)
250  vPowGen_.resize(30);
251 
252  double min = generator_(0, 0);
253  for (i = 1; i < 36; i++)
254  {
255  if (min > generator_(i, i))
256  min = generator_(i, i);
257  }
258 
259  setScale(-1 / min);
260 
261  MatrixTools::getId(36, tmpMat_); // to compute the equilibrium frequency (Q+Id)^256
262 
265 
266  for (i = 0; i < 36; i++)
267  {
268  freq_[i] = vPowGen_[0](0, i);
269  }
270 
272  }
273 
274  // mise a l'echelle
275 
276  x = 0;
277  for (i1 = 0; i1 < 3; i1++)
278  {
279  for (i2 = 0; i2 < 4; i2++)
280  {
281  for (i3 = 0; i3 < 3; i3++)
282  {
283  i = 12 * i1 + 3 * i2 + i3;
284  for (j2 = 0; j2 < 4; j2++)
285  {
286  if (j2 != i2)
287  {
288  j = 12 * i1 + 3 * j2 + i3;
289  x += freq_[i] * generator_(i, j);
290  }
291  }
292  }
293  }
294  }
295 
296  setScale(1 / x);
297 
298  if (isScalable())
299  {
300  for (i = 0; i < 36; i++)
301  {
302  eigenValues_[i] /= x;
303  iEigenValues_[i] /= x;
304  }
305  }
306 
307  if (!isNonSingular_)
309 
310  // and the exchangeability_
311  for (i = 0; i < size_; i++)
312  {
313  for (j = 0; j < size_; j++)
314  {
315  exchangeability_(i, j) = generator_(i, j) / freq_[j];
316  }
317  }
318 }
319 
321 {
322  auto alph = pm.getAlphabet();
324  throw Exception("Need a DNA model");
325 
326  // Check that the model is good for YpR, ie transversion rates do
327  // not depend on the origin state
328 
329  if ((pm.Qij(0, 1) != pm.Qij(2, 1)) || (pm.Qij(0, 3) != pm.Qij(2, 3))
330  || (pm.Qij(1, 0) != pm.Qij(3, 0)) || (pm.Qij(1, 2) != pm.Qij(3, 2)))
331  throw Exception("Not R/Y Model " + pm.getName());
332 }
333 
334 void YpR::setNamespace(const std::string& prefix)
335 {
337 
338  // We also need to update the namespace of the nested model:
339  pmodel_->setNamespace(prefix + nestedPrefix_);
340 }
341 
342 // ///////////////////////////////////////////////
343 // ///////////////////////////////////////////////
344 
345 
346 /******************************************************************************/
347 
349  std::shared_ptr<const RNY> alph,
350  std::unique_ptr<NucleotideSubstitutionModelInterface> pm,
351  double CgT, double TgC,
352  double CaT, double TaC) :
353  AbstractParameterAliasable("YpR_Sym."),
354  YpR(alph, std::move(pm), "YpR_Sym.")
355 {
356  addParameter_(new Parameter("YpR_Sym.rCgT", CgT, Parameter::R_PLUS));
357  addParameter_(new Parameter("YpR_Sym.rTgC", TgC, Parameter::R_PLUS));
358  addParameter_(new Parameter("YpR_Sym.rCaT", CaT, Parameter::R_PLUS));
359  addParameter_(new Parameter("YpR_Sym.rTaC", TaC, Parameter::R_PLUS));
360 
361  updateMatrices_();
362 }
363 
365 {
366  double rCgT = getParameterValue("rCgT");
367  double rTgC = getParameterValue("rTgC");
368  double rCaT = getParameterValue("rCaT");
369  double rTaC = getParameterValue("rTaC");
370 
371  YpR::updateMatrices_(rCgT, rCgT, rTgC, rTgC, rCaT, rCaT, rTaC, rTaC);
372 }
373 
376  YpR(ypr)
377 {}
378 
379 /******************************************************************************/
380 
381 std::string YpR_Sym::getName() const
382 {
383  return "YpR_Sym";
384 }
385 
386 
387 // ///////////////////////////////////////////////
388 // ///////////////////////////////////////////////
389 
390 /******************************************************************************/
391 
393  std::shared_ptr<const RNY> alph,
394  std::unique_ptr<NucleotideSubstitutionModelInterface> pm,
395  double CgT, double cGA,
396  double TgC, double tGA,
397  double CaT, double cAG,
398  double TaC, double tAG) :
399  AbstractParameterAliasable("YpR_Gen."),
400  YpR(alph, std::move(pm), "YpR_Gen.")
401 {
402  addParameter_(new Parameter("YpR_Gen.rCgT", CgT, Parameter::R_PLUS));
403  addParameter_(new Parameter("YpR_Gen.rcGA", cGA, Parameter::R_PLUS));
404  addParameter_(new Parameter("YpR_Gen.rTgC", TgC, Parameter::R_PLUS));
405  addParameter_(new Parameter("YpR_Gen.rtGA", tGA, Parameter::R_PLUS));
406  addParameter_(new Parameter("YpR_Gen.rCaT", CaT, Parameter::R_PLUS));
407  addParameter_(new Parameter("YpR_Gen.rcAG", cAG, Parameter::R_PLUS));
408  addParameter_(new Parameter("YpR_Gen.rTaC", TaC, Parameter::R_PLUS));
409  addParameter_(new Parameter("YpR_Gen.rtAG", tAG, Parameter::R_PLUS));
410 
411  updateMatrices_();
412 }
413 
415 {
416  double rCgT = getParameterValue("rCgT");
417  double rcGA = getParameterValue("rcGA");
418  double rTgC = getParameterValue("rTgC");
419  double rtGA = getParameterValue("rtGA");
420  double rCaT = getParameterValue("rCaT");
421  double rcAG = getParameterValue("rcAG");
422  double rTaC = getParameterValue("rTaC");
423  double rtAG = getParameterValue("rtAG");
424 
425  YpR::updateMatrices_(rCgT, rcGA, rTgC, rtGA, rCaT, rcAG, rTaC, rtAG);
426 }
427 
430  YpR(ypr)
431 {
432  updateMatrices_();
433 }
434 
435 /******************************************************************************/
436 
437 std::string YpR_Gen::getName() const
438 {
439  return "YpR_Gen";
440 }
void addParameters_(const ParameterList &parameters)
void addParameter_(Parameter *parameter)
void setNamespace(const std::string &prefix)
double getParameterValue(const std::string &name) const override
RowMatrix< double > generator_
The generator matrix of the model.
bool isDiagonalizable_
boolean value for diagonalizability in R of the generator_
bool isNonSingular_
boolean value for non-singularity of rightEigenVectors_
std::vector< RowMatrix< double > > vPowGen_
vector of the powers of generator_ for Taylor development (if rightEigenVectors_ is singular).
Vdouble eigenValues_
The vector of eigen values.
RowMatrix< double > exchangeability_
The exchangeability matrix of the model, defined as . When the model is reversible,...
Vdouble iEigenValues_
The vector of the imaginary part of the eigen values.
RowMatrix< double > leftEigenVectors_
The matrix made of left eigen vectors (by row) if rightEigenVectors_ is non-singular.
virtual bool isScalable() const
returns if model is scalable
RowMatrix< double > rightEigenVectors_
The matrix made of right eigen vectors (by column).
void setScale(double scale)
Multiplies the current generator by the given scale.
RowMatrix< double > tmpMat_
For computational issues.
size_t size_
The number of states.
Vdouble freq_
The vector of equilibrium frequencies.
static bool isNucleicAlphabet(const Alphabet &alphabet)
static void displayMessage(const std::string &text)
virtual std::string getName() const =0
Get the name of the model.
virtual std::shared_ptr< const Alphabet > getAlphabet() const =0
This class implements a state map where all resolved states are modeled.
Definition: StateMap.h:168
const RowMatrix< Real > & getV() const
const std::vector< Real > & getImagEigenValues() const
const std::vector< Real > & getRealEigenValues() const
static Scalar inv(const Matrix< Scalar > &A, Matrix< Scalar > &O)
static void Taylor(const Matrix &A, size_t p, std::vector< RowMatrix< Scalar >> &vO)
static void pow(const Matrix &A, size_t p, Matrix &O)
static void add(MatrixA &A, const MatrixB &B)
static void getId(size_t n, Matrix &O)
static double TINY()
static double SMALL()
static const std::shared_ptr< IntervalConstraint > R_PLUS
Interface for all substitution models.
virtual double Qij(size_t i, size_t j) const =0
A method for computing all necessary matrices.
General YpR model.
Definition: YpR.h:212
void updateMatrices_() override
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
Definition: YpR.cpp:414
std::string getName() const override
Get the name of the model.
Definition: YpR.cpp:437
YpR_Gen(std::shared_ptr< const RNY > alph, std::unique_ptr< NucleotideSubstitutionModelInterface > 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:392
symmetrical YpR model.
Definition: YpR.h:171
std::string getName() const override
Get the name of the model.
Definition: YpR.cpp:381
YpR_Sym(std::shared_ptr< const RNY > alph, std::unique_ptr< NucleotideSubstitutionModelInterface > pm, double CgT=0., double TgC=0., double CaT=0., double TaC=0.)
Build a new YpR_Sym substitution model.
Definition: YpR.cpp:348
void updateMatrices_() override
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
Definition: YpR.cpp:364
YpR model.
Definition: YpR.h:88
std::string nestedPrefix_
Definition: YpR.h:93
void checkModel(const SubstitutionModelInterface &model) const
Definition: YpR.cpp:320
virtual void updateMatrices_() override
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
Definition: YpR.cpp:47
YpR(std::shared_ptr< const RNY >, std::unique_ptr< NucleotideSubstitutionModelInterface > const, const std::string &prefix)
Build a new YpR substitution model, with no dependency parameters.
Definition: YpR.cpp:22
std::unique_ptr< NucleotideSubstitutionModelInterface > pmodel_
Definition: YpR.h:90
virtual void setNamespace(const std::string &) override
Definition: YpR.cpp:334
Defines the basic types of data flow nodes.
ExtendedFloat abs(const ExtendedFloat &ef)