bpp-phyl  2.2.0
T92.cpp
Go to the documentation of this file.
1 //
2 // File: T92.cpp
3 // Created by: Julien Dutheil
4 // Created on: Mon May 26 14:41:24 2003
5 //
6 
7 /*
8  Copyright or © or Copr. Bio++ Development Team, (November 16, 2004)
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 
40 #include "T92.h"
41 #include "../FrequenciesSet/NucleotideFrequenciesSet.h"
42 
43 #include <Bpp/Numeric/Matrix/MatrixTools.h>
44 
45 // From SeqLib:
46 #include <Bpp/Seq/Container/SequenceContainerTools.h>
47 
48 using namespace bpp;
49 
50 // From the STL:
51 #include <cmath>
52 
53 using namespace std;
54 
55 /******************************************************************************/
56 
57 T92::T92(const NucleicAlphabet* alpha, double kappa, double theta) :
58  AbstractParameterAliasable("T92."),
59  AbstractReversibleSubstitutionModel(alpha, new CanonicalStateMap(alpha, false), "T92."),
60  kappa_(kappa),
61  theta_(theta),
62  k_(),
63  r_(),
64  piA_((1. - theta_) / 2.),
65  piC_(theta_ / 2.),
66  piG_(theta_ / 2.),
67  piT_((1. - theta_) / 2.),
68  exp1_(),
69  exp2_(),
70  l_(),
71  p_(size_, size_)
72 {
73  addParameter_(new Parameter("T92.kappa", kappa, &Parameter::R_PLUS_STAR));
74  addParameter_(new Parameter("T92.theta", theta, &FrequenciesSet::FREQUENCE_CONSTRAINT_SMALL));
75  p_.resize(size_, size_);
77 }
78 
79 /******************************************************************************/
80 
82 {
83  kappa_ = getParameterValue("kappa");
84  theta_ = getParameterValue("theta");
85  piA_ = (1 - theta_) / 2;
86  piC_ = theta_ / 2;
87  piG_ = theta_ / 2;
88  piT_ = (1 - theta_) / 2;
89  k_ = (kappa_ + 1.) / 2.;
90  r_ = 2. / (1. + 2. * theta_ * kappa_ - 2. * theta_ * theta_ * kappa_);
91 
92  freq_[0] = piA_;
93  freq_[1] = piC_;
94  freq_[2] = piG_;
95  freq_[3] = piT_;
96 
97  generator_(0, 0) = -(1. + theta_ * kappa_) / 2;
98  generator_(1, 1) = -(1. + (1. - theta_) * kappa_) / 2;
99  generator_(2, 2) = -(1. + (1. - theta_) * kappa_) / 2;
100  generator_(3, 3) = -(1. + theta_ * kappa_) / 2;
101 
102  generator_(1, 0) = (1. - theta_) / 2;
103  generator_(3, 0) = (1. - theta_) / 2;
104  generator_(0, 1) = theta_ / 2;
105  generator_(2, 1) = theta_ / 2;
106  generator_(1, 2) = theta_ / 2;
107  generator_(3, 2) = theta_ / 2;
108  generator_(0, 3) = (1. - theta_) / 2;
109  generator_(2, 3) = (1. - theta_) / 2;
110 
111  generator_(2, 0) = kappa_ * (1. - theta_) / 2;
112  generator_(3, 1) = kappa_ * theta_ / 2;
113  generator_(0, 2) = kappa_ * theta_ / 2;
114  generator_(1, 3) = kappa_ * (1. - theta_) / 2;
115 
116  // Normalization:
117  MatrixTools::scale(generator_, r_);
118 
119  // Exchangeability:
120  exchangeability_(0, 0) = generator_(0, 0) * 2. / (1. - theta_);
121  exchangeability_(0, 1) = generator_(0, 1) * 2. / theta_;
122  exchangeability_(0, 2) = generator_(0, 2) * 2. / theta_;
123  exchangeability_(0, 3) = generator_(0, 3) * 2. / (1. - theta_);
124 
125  exchangeability_(1, 0) = generator_(1, 0) * 2. / (1. - theta_);
126  exchangeability_(1, 1) = generator_(1, 1) * 2 / theta_;
127  exchangeability_(1, 2) = generator_(1, 2) * 2 / theta_;
128  exchangeability_(1, 3) = generator_(1, 3) * 2 / (1. - theta_);
129 
130  exchangeability_(2, 0) = generator_(2, 0) * 2. / (1. - theta_);
131  exchangeability_(2, 1) = generator_(2, 1) * 2 / theta_;
132  exchangeability_(2, 2) = generator_(2, 2) * 2 / theta_;
133  exchangeability_(2, 3) = generator_(2, 3) * 2 / (1. - theta_);
134 
135  exchangeability_(3, 0) = generator_(3, 0) * 2. / (1. - theta_);
136  exchangeability_(3, 1) = generator_(3, 1) * 2. / theta_;
137  exchangeability_(3, 2) = generator_(3, 2) * 2. / theta_;
138  exchangeability_(3, 3) = generator_(3, 3) * 2. / (1. - theta_);
139 
140  // Eigen values:
141  eigenValues_[0] = 0;
142  eigenValues_[1] = eigenValues_[2] = -r_ * (1. + kappa_) / 2;
143  eigenValues_[3] = -r_;
144 
145  // Eigen vectors:
146  leftEigenVectors_(0, 0) = -(theta_ - 1.) / 2.;
147  leftEigenVectors_(0, 1) = theta_ / 2.;
148  leftEigenVectors_(0, 2) = theta_ / 2.;
149  leftEigenVectors_(0, 3) = -(theta_ - 1.) / 2.;
150 
151  leftEigenVectors_(1, 0) = 0.;
152  leftEigenVectors_(1, 1) = -(theta_ - 1.);
153  leftEigenVectors_(1, 2) = 0.;
154  leftEigenVectors_(1, 3) = theta_ - 1.;
155 
156  leftEigenVectors_(2, 0) = theta_;
157  leftEigenVectors_(2, 1) = 0.;
158  leftEigenVectors_(2, 2) = -theta_;
159  leftEigenVectors_(2, 3) = 0.;
160 
161  leftEigenVectors_(3, 0) = -(theta_ - 1.) / 2.;
162  leftEigenVectors_(3, 1) = -theta_ / 2.;
163  leftEigenVectors_(3, 2) = theta_ / 2.;
164  leftEigenVectors_(3, 3) = (theta_ - 1.) / 2.;
165 
166 
167  rightEigenVectors_(0, 0) = 1.;
168  rightEigenVectors_(0, 1) = 0.;
169  rightEigenVectors_(0, 2) = 1.;
170  rightEigenVectors_(0, 3) = 1.;
171 
172  rightEigenVectors_(1, 0) = 1.;
173  rightEigenVectors_(1, 1) = 1.;
174  rightEigenVectors_(1, 2) = 0.;
175  rightEigenVectors_(1, 3) = -1.;
176 
177  rightEigenVectors_(2, 0) = 1.;
178  rightEigenVectors_(2, 1) = 0.;
179  rightEigenVectors_(2, 2) = (theta_ - 1.) / theta_;
180  rightEigenVectors_(2, 3) = 1.;
181 
182  rightEigenVectors_(3, 0) = 1.;
183  rightEigenVectors_(3, 1) = theta_ / (theta_ - 1.);
184  rightEigenVectors_(3, 2) = 0;
185  rightEigenVectors_(3, 3) = -1.;
186 }
187 
188 /******************************************************************************/
189 
190 double T92::Pij_t(size_t i, size_t j, double d) const
191 {
192  l_ = rate_ * r_ * d;
193  exp1_ = exp(-l_);
194  exp2_ = exp(-k_ * l_);
195 
196  switch (i)
197  {
198  // A
199  case 0: {
200  switch (j)
201  {
202  case 0: return piA_ * (1. + exp1_) + theta_ * exp2_; // A
203  case 1: return piC_ * (1. - exp1_); // C
204  case 2: return piG_ * (1. + exp1_) - theta_ * exp2_; // G
205  case 3: return piT_ * (1. - exp1_); // T, U
206  }
207  }
208  // C
209  case 1: {
210  switch (j)
211  {
212  case 0: return piA_ * (1. - exp1_); // A
213  case 1: return piC_ * (1. + exp1_) + (1. - theta_) * exp2_; // C
214  case 2: return piG_ * (1. - exp1_); // G
215  case 3: return piT_ * (1. + exp1_) - (1. - theta_) * exp2_; // T, U
216  }
217  }
218  // G
219  case 2: {
220  switch (j)
221  {
222  case 0: return piA_ * (1. + exp1_) - (1. - theta_) * exp2_; // A
223  case 1: return piC_ * (1. - exp1_); // C
224  case 2: return piG_ * (1. + exp1_) + (1. - theta_) * exp2_; // G
225  case 3: return piT_ * (1. - exp1_); // T, U
226  }
227  }
228  // T, U
229  case 3: {
230  switch (j)
231  {
232  case 0: return piA_ * (1. - exp1_); // A
233  case 1: return piC_ * (1. + exp1_) - theta_ * exp2_; // C
234  case 2: return piG_ * (1. - exp1_); // G
235  case 3: return piT_ * (1. + exp1_) + theta_ * exp2_; // T, U
236  }
237  }
238  }
239  return 0;
240 }
241 
242 /******************************************************************************/
243 
244 double T92::dPij_dt(size_t i, size_t j, double d) const
245 {
246  l_ = rate_ * r_ * d;
247  exp1_ = exp(-l_);
248  exp2_ = exp(-k_ * l_);
249 
250  switch (i)
251  {
252  // A
253  case 0: {
254  switch (j)
255  {
256  case 0: return rate_ * r_ * (piA_ * -exp1_ + theta_ * -k_ * exp2_); // A
257  case 1: return rate_ * r_ * (piC_ * exp1_); // C
258  case 2: return rate_ * r_ * (piG_ * -exp1_ - theta_ * -k_ * exp2_); // G
259  case 3: return rate_ * r_ * (piT_ * exp1_); // T, U
260  }
261  }
262  // C
263  case 1: {
264  switch (j)
265  {
266  case 0: return rate_ * r_ * (piA_ * exp1_); // A
267  case 1: return rate_ * r_ * (piC_ * -exp1_ + (1. - theta_) * -k_ * exp2_); // C
268  case 2: return rate_ * r_ * (piG_ * exp1_); // G
269  case 3: return rate_ * r_ * (piT_ * -exp1_ - (1. - theta_) * -k_ * exp2_); // T, U
270  }
271  }
272  // G
273  case 2: {
274  switch (j)
275  {
276  case 0: return rate_ * r_ * (piA_ * -exp1_ - (1. - theta_) * -k_ * exp2_); // A
277  case 1: return rate_ * r_ * (piC_ * exp1_); // C
278  case 2: return rate_ * r_ * (piG_ * -exp1_ + (1. - theta_) * -k_ * exp2_); // G
279  case 3: return rate_ * r_ * (piT_ * exp1_); // T, U
280  }
281  }
282  // T, U
283  case 3: {
284  switch (j)
285  {
286  case 0: return rate_ * r_ * (piA_ * exp1_); // A
287  case 1: return rate_ * r_ * (piC_ * -exp1_ - theta_ * -k_ * exp2_); // C
288  case 2: return rate_ * r_ * (piG_ * exp1_); // G
289  case 3: return rate_ * r_ * (piT_ * -exp1_ + theta_ * -k_ * exp2_); // T, U
290  }
291  }
292  }
293  return 0;
294 }
295 
296 /******************************************************************************/
297 
298 double T92::d2Pij_dt2(size_t i, size_t j, double d) const
299 {
300  double k2_ = k_ * k_;
301  l_ = rate_ * r_ * d;
302  double r2 = rate_ * rate_ * r_ * r_;
303  exp1_ = exp(-l_);
304  exp2_ = exp(-k_ * l_);
305 
306  switch (i)
307  {
308  // A
309  case 0: {
310  switch (j)
311  {
312  case 0: return r2 * (piA_ * exp1_ + theta_ * k2_ * exp2_); // A
313  case 1: return r2 * (piC_ * -exp1_); // C
314  case 2: return r2 * (piG_ * exp1_ - theta_ * k2_ * exp2_); // G
315  case 3: return r2 * (piT_ * -exp1_); // T, U
316  }
317  }
318  // C
319  case 1: {
320  switch (j)
321  {
322  case 0: return r2 * (piA_ * -exp1_); // A
323  case 1: return r2 * (piC_ * exp1_ + (1. - theta_) * k2_ * exp2_); // C
324  case 2: return r2 * (piG_ * -exp1_); // G
325  case 3: return r2 * (piT_ * exp1_ - (1. - theta_) * k2_ * exp2_); // T, U
326  }
327  }
328  // G
329  case 2: {
330  switch (j)
331  {
332  case 0: return r2 * (piA_ * exp1_ - (1. - theta_) * k2_ * exp2_); // A
333  case 1: return r2 * (piC_ * -exp1_); // C
334  case 2: return r2 * (piG_ * exp1_ + (1. - theta_) * k2_ * exp2_); // G
335  case 3: return r2 * (piT_ * -exp1_); // T, U
336  }
337  }
338  // T, U
339  case 3: {
340  switch (j)
341  {
342  case 0: return r2 * (piA_ * -exp1_); // A
343  case 1: return r2 * (piC_ * exp1_ - theta_ * k2_ * exp2_); // C
344  case 2: return r2 * (piG_ * -exp1_); // G
345  case 3: return r2 * (piT_ * exp1_ + theta_ * k2_ * exp2_); // T, U
346  }
347  }
348  }
349  return 0;
350 }
351 
352 /******************************************************************************/
353 
354 const Matrix<double>& T92::getPij_t(double d) const
355 {
356  l_ = rate_ * r_ * d;
357  exp1_ = exp(-l_);
358  exp2_ = exp(-k_ * l_);
359 
360  // A
361  p_(0, 0) = piA_ * (1. + exp1_) + theta_ * exp2_; // A
362  p_(0, 1) = piC_ * (1. - exp1_); // C
363  p_(0, 2) = piG_ * (1. + exp1_) - theta_ * exp2_; // G
364  p_(0, 3) = piT_ * (1. - exp1_); // T, U
365 
366  // C
367  p_(1, 0) = piA_ * (1. - exp1_); // A
368  p_(1, 1) = piC_ * (1. + exp1_) + (1. - theta_) * exp2_; // C
369  p_(1, 2) = piG_ * (1. - exp1_); // G
370  p_(1, 3) = piT_ * (1. + exp1_) - (1. - theta_) * exp2_; // T, U
371 
372  // G
373  p_(2, 0) = piA_ * (1. + exp1_) - (1. - theta_) * exp2_; // A
374  p_(2, 1) = piC_ * (1. - exp1_); // C
375  p_(2, 2) = piG_ * (1. + exp1_) + (1. - theta_) * exp2_; // G
376  p_(2, 3) = piT_ * (1. - exp1_); // T, U
377 
378  // T, U
379  p_(3, 0) = piA_ * (1. - exp1_); // A
380  p_(3, 1) = piC_ * (1. + exp1_) - theta_ * exp2_; // C
381  p_(3, 2) = piG_ * (1. - exp1_); // G
382  p_(3, 3) = piT_ * (1. + exp1_) + theta_ * exp2_; // T, U
383 
384  return p_;
385 }
386 
387 const Matrix<double>& T92::getdPij_dt(double d) const
388 {
389  l_ = rate_ * r_ * d;
390  exp1_ = exp(-l_);
391  exp2_ = exp(-k_ * l_);
392 
393  // A
394  p_(0, 0) = rate_ * r_ * (piA_ * -exp1_ + theta_ * -k_ * exp2_); // A
395  p_(0, 1) = rate_ * r_ * (piC_ * exp1_); // C
396  p_(0, 2) = rate_ * r_ * (piG_ * -exp1_ - theta_ * -k_ * exp2_); // G
397  p_(0, 3) = rate_ * r_ * (piT_ * exp1_); // T, U
398 
399  // C
400  p_(1, 0) = rate_ * r_ * (piA_ * exp1_); // A
401  p_(1, 1) = rate_ * r_ * (piC_ * -exp1_ + (1. - theta_) * -k_ * exp2_); // C
402  p_(1, 2) = rate_ * r_ * (piG_ * exp1_); // G
403  p_(1, 3) = rate_ * r_ * (piT_ * -exp1_ - (1. - theta_) * -k_ * exp2_); // T, U
404 
405  // G
406  p_(2, 0) = rate_ * r_ * (piA_ * -exp1_ - (1. - theta_) * -k_ * exp2_); // A
407  p_(2, 1) = rate_ * r_ * (piC_ * exp1_); // C
408  p_(2, 2) = rate_ * r_ * (piG_ * -exp1_ + (1. - theta_) * -k_ * exp2_); // G
409  p_(2, 3) = rate_ * r_ * (piT_ * exp1_); // T, U
410 
411  // T, U
412  p_(3, 0) = rate_ * r_ * (piA_ * exp1_); // A
413  p_(3, 1) = rate_ * r_ * (piC_ * -exp1_ - theta_ * -k_ * exp2_); // C
414  p_(3, 2) = rate_ * r_ * (piG_ * exp1_); // G
415  p_(3, 3) = rate_ * r_ * (piT_ * -exp1_ + theta_ * -k_ * exp2_); // T, U
416 
417  return p_;
418 }
419 
420 const Matrix<double>& T92::getd2Pij_dt2(double d) const
421 {
422  double k2 = k_ * k_;
423  l_ = rate_ * r_ * d;
424  double r2 = rate_ * rate_ * r_ * r_;
425  exp1_ = exp(-l_);
426  exp2_ = exp(-k_ * l_);
427 
428  // A
429  p_(0, 0) = r2 * (piA_ * exp1_ + theta_ * k2 * exp2_); // A
430  p_(0, 1) = r2 * (piC_ * -exp1_); // C
431  p_(0, 2) = r2 * (piG_ * exp1_ - theta_ * k2 * exp2_); // G
432  p_(0, 3) = r2 * (piT_ * -exp1_); // T, U
433 
434  // C
435  p_(1, 0) = r2 * (piA_ * -exp1_); // A
436  p_(1, 1) = r2 * (piC_ * exp1_ + (1. - theta_) * k2 * exp2_); // C
437  p_(1, 2) = r2 * (piG_ * -exp1_); // G
438  p_(1, 3) = r2 * (piT_ * exp1_ - (1. - theta_) * k2 * exp2_); // T, U
439 
440  // G
441  p_(2, 0) = r2 * (piA_ * exp1_ - (1. - theta_) * k2 * exp2_); // A
442  p_(2, 1) = r2 * (piC_ * -exp1_); // C
443  p_(2, 2) = r2 * (piG_ * exp1_ + (1. - theta_) * k2 * exp2_); // G
444  p_(2, 3) = r2 * (piT_ * -exp1_); // T, U
445 
446  // T, U
447  p_(3, 0) = r2 * (piA_ * -exp1_); // A
448  p_(3, 1) = r2 * (piC_ * exp1_ - theta_ * k2 * exp2_); // C
449  p_(3, 2) = r2 * (piG_ * -exp1_); // G
450  p_(3, 3) = r2 * (piT_ * exp1_ + theta_ * k2 * exp2_); // T, U
451 
452  return p_;
453 }
454 
455 /******************************************************************************/
456 
457 void T92::setFreq(std::map<int, double>& freqs)
458 {
459  double f = (freqs[1] + freqs[2]) / (freqs[0] + freqs[1] + freqs[2] + freqs[3]);
460  setParameterValue("theta", f);
461  updateMatrices();
462 }
463 
464 /******************************************************************************/
465 
double r_
Definition: T92.h:164
const Matrix< double > & getd2Pij_dt2(double d) const
Definition: T92.cpp:420
RowMatrix< double > exchangeability_
The exchangeability matrix of the model, defined as . When the model is reversible, this matrix is symetric.
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.
STL namespace.
const Matrix< double > & getPij_t(double d) const
Definition: T92.cpp:354
Vdouble freq_
The vector of equilibrium frequencies.
double theta_
Definition: T92.h:164
double d2Pij_dt2(size_t i, size_t j, double d) const
Definition: T92.cpp:298
double k_
Definition: T92.h:164
double piG_
Definition: T92.h:164
Partial implementation of the ReversibleSubstitutionModel interface.
void updateMatrices()
Compute and diagonalize the matrix, and fill the eigenValues_, leftEigenVectors_ and rightEigenVecto...
Definition: T92.cpp:81
static IntervalConstraint FREQUENCE_CONSTRAINT_SMALL
double exp2_
Definition: T92.h:165
double piC_
Definition: T92.h:164
double piT_
Definition: T92.h:164
double l_
Definition: T92.h:165
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.
double Pij_t(size_t i, size_t j, double d) const
Definition: T92.cpp:190
double rate_
The rate of the model (default: 1). The generator (and all its vectorial components) is independent o...
const Matrix< double > & getdPij_dt(double d) const
Definition: T92.cpp:387
double kappa_
Definition: T92.h:164
double exp1_
Definition: T92.h:165
size_t size_
The size of the generator, i.e. the number of states.
double piA_
Definition: T92.h:164
double dPij_dt(size_t i, size_t j, double d) const
Definition: T92.cpp:244
RowMatrix< double > p_
Definition: T92.h:166
void setFreq(std::map< int, double > &freqs)
This method is over-defined to actualize the &#39;theta&#39; parameter too.
Definition: T92.cpp:457
T92(const NucleicAlphabet *alpha, double kappa=1., double theta=0.5)
Definition: T92.cpp:57