bpp-phyl  2.2.0
gBGC.cpp
Go to the documentation of this file.
1 //
2 // File: gBGC.cpp
3 // Created by: Laurent Gueguen
4 // Created on: lundi 13 février 2012, à 09h 42
5 //
6 
7 /*
8  Copyright or © or Copr. Bio++ Development Team, (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 "gBGC.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 /******************************************************************************/
51 
52 gBGC::gBGC(const NucleicAlphabet* alph, NucleotideSubstitutionModel* const pm, double gamma) :
53  AbstractParameterAliasable("gBGC."),
54  AbstractSubstitutionModel(alph, new CanonicalStateMap(alph, false), "gBGC."),
55  model_(pm),
56  nestedPrefix_(pm->getNamespace()),
57  gamma_(gamma)
58 {
59  model_->setNamespace("gBGC."+nestedPrefix_);
60  model_->enableEigenDecomposition(0);
61  addParameters_(model_->getParameters());
62  addParameter_(new Parameter("gBGC.gamma", gamma_, new IntervalConstraint(-999, 10, true, true), true));
63 
65 }
66 
67 gBGC::gBGC(const gBGC& gbgc) :
68  AbstractParameterAliasable(gbgc),
70  model_(gbgc.model_->clone()),
71  nestedPrefix_(gbgc.nestedPrefix_),
72  gamma_(gbgc.gamma_)
73 {
74 }
75 
76 gBGC& gBGC::operator=(const gBGC& gbgc)
77 {
78  AbstractParameterAliasable::operator=(gbgc);
80  model_ = auto_ptr<NucleotideSubstitutionModel>(gbgc.model_.get());
82  gamma_=gbgc.gamma_;
83  return *this;
84 }
85 
86 void gBGC::fireParameterChanged(const ParameterList& parameters)
87 {
89  model_->matchParametersValues(parameters);
91 }
92 
94 {
95  gamma_=getParameterValue("gamma");
96  unsigned int i,j;
97  // Generator:
98  double eg=exp(gamma_);
99 
100  for ( i = 0; i < 4; i++)
101  for ( j = 0; j < 4; j++)
102  generator_(i,j)=model_->Qij(i,j);
103 
104  generator_(0,1) *= eg;
105  generator_(0,2) *= eg;
106  generator_(3,1) *= eg;
107  generator_(3,2) *= eg;
108  generator_(1,0) /= eg;
109  generator_(2,0) /= eg;
110  generator_(1,3) /= eg;
111  generator_(2,3) /= eg;
112 
113  generator_(0,0) -= (generator_(0,1)+generator_(0,2))*(1-1/eg);
114  generator_(3,3) -= (generator_(3,1)+generator_(3,2))*(1-1/eg);
115 
117  {
118  // calcul spectral
119 
120  EigenValue<double> ev(generator_);
121  eigenValues_ = ev.getRealEigenValues();
122  iEigenValues_ = ev.getImagEigenValues();
123 
124  rightEigenVectors_ = ev.getV();
125  try
126  {
127  MatrixTools::inv(rightEigenVectors_, leftEigenVectors_);
128  isNonSingular_ = true;
129  isDiagonalizable_ = true;
130 
131  for (i = 0; i < 4 && isDiagonalizable_; i++)
132  {
133  if (abs(iEigenValues_[i]) > NumConstants::TINY())
134  isDiagonalizable_ = false;
135  }
136 
137  // frequence stationnaire
138 
139  if (isDiagonalizable_)
140  {
141  size_t nulleigen = 0;
142  double val;
143  isNonSingular_ = false;
144 
145  while (nulleigen < 4){
146  if (abs(eigenValues_[nulleigen]) < 0.000001 && abs(iEigenValues_[nulleigen]) < 0.000001) {
147  val = rightEigenVectors_(0, nulleigen);
148  i=1;
149  while (i < 4)
150  {
151  if (abs(rightEigenVectors_(i, nulleigen) - val) > NumConstants::SMALL())
152  break;
153  i++;
154  }
155 
156  if (i < 4)
157  nulleigen++;
158  else
159  {
160  isNonSingular_ = true;
161  break;
162  }
163  }
164  else
165  nulleigen++;
166  }
167 
168  if (isNonSingular_)
169  {
170  eigenValues_[nulleigen] = 0; // to avoid approximation errors on long long branches
171  iEigenValues_[nulleigen] = 0; // to avoid approximation errors on long long branches
172 
173  for (i = 0; i < 4; i++)
174  freq_[i] = leftEigenVectors_(nulleigen, i);
175 
176  val = 0;
177  for (i = 0; i < 4; i++)
178  val += freq_[i];
179 
180  for (i = 0; i < 4; i++)
181  freq_[i] /= val;
182  }
183  else
184  {
185  ApplicationTools::displayMessage("Unable to find eigenvector for eigenvalue 1 in gBGC. Taylor series used instead.");
186  isDiagonalizable_ = false;
187  }
188  }
189  }
190  catch (ZeroDivisionException& e)
191  {
192  ApplicationTools::displayMessage("Singularity during diagonalization of gBGC in gBGC. Taylor series used instead.");
193  isNonSingular_ = false;
194  isDiagonalizable_ = false;
195  }
196 
197  if (!isNonSingular_)
198  {
199  double min = generator_(0, 0);
200  for (i = 1; i < 4; i++)
201  {
202  if (min > generator_(i, i))
203  min = generator_(i, i);
204  }
205 
206  MatrixTools::scale(generator_, -1 / min);
207 
208  if (vPowGen_.size() == 0)
209  vPowGen_.resize(30);
210 
211  MatrixTools::getId(4, tmpMat_); // to compute the equilibrium frequency (Q+Id)^256
212  MatrixTools::add(tmpMat_, generator_);
213  MatrixTools::pow(tmpMat_, 4, vPowGen_[0]);
214 
215  for (i = 0; i < 4; i++)
216  freq_[i] = vPowGen_[0](0, i);
217 
218  MatrixTools::getId(4, vPowGen_[0]);
219  }
220 
221  // mise a l'echelle
222 
223  double x = 0;
224  for (i = 0; i < 4; i++)
225  x += freq_[i] * generator_(i,i);
226 
227  MatrixTools::scale(generator_,-1 / x);
228  for (i = 0; i < 4; i++)
229  {
230  eigenValues_[i] /= -x;
231  iEigenValues_[i] /= -x;
232  }
233 
234  if (!isNonSingular_)
235  MatrixTools::Taylor(generator_, 30, vPowGen_);
236 
237  }
238 
239 }
240 
241 void gBGC::setNamespace(const std::string& prefix)
242 {
243  AbstractSubstitutionModel::setNamespace(prefix);
244  // We also need to update the namespace of the nested model:
245  model_->setNamespace(prefix + nestedPrefix_);
246 }
247 
248 
249 std::string gBGC::getName() const
250 {
251  return "gBGC";
252 }
253 
void updateMatrices()
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
Definition: gBGC.cpp:93
bool enableEigenDecomposition()
Tell if eigenValues and Vectors must be computed.
virtual void fireParameterChanged(const ParameterList &parameters)
Tells the model that a parameter value has changed.
void fireParameterChanged(const ParameterList &)
Tells the model that a parameter value has changed.
Definition: gBGC.cpp:86
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).
gBGC model.
Definition: gBGC.h:75
double gamma_
Definition: gBGC.h:88
Vdouble eigenValues_
The vector of eigen values.
std::auto_ptr< NucleotideSubstitutionModel > model_
Definition: gBGC.h:80
Vdouble freq_
The vector of equilibrium frequencies.
AbstractSubstitutionModel & operator=(const AbstractSubstitutionModel &model)
Partial implementation of the SubstitutionModel interface.
gBGC & operator=(const gBGC &gbgc)
Definition: gBGC.cpp:76
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.
std::vector< RowMatrix< double > > vPowGen_
vector of the powers of generator_ for Taylor development (if rightEigenVectors_ is singular)...
Specialisation interface for nucleotide substitution model.
std::string nestedPrefix_
Definition: gBGC.h:81
std::string getName() const
Get the name of the model.
Definition: gBGC.cpp:249
RowMatrix< double > tmpMat_
For computational issues.
gBGC(const NucleicAlphabet *, NucleotideSubstitutionModel *const, double gamma=0)
Definition: gBGC.cpp:52
bool isDiagonalizable_
boolean value for diagonalizability in R of the generator_
Vdouble iEigenValues_
The vector of the imaginary part of the eigen values.
void setNamespace(const std::string &)
Definition: gBGC.cpp:241