bpp-phyl  2.1.0
Bpp/Phyl/Model/MarkovModulatedSubstitutionModel.cpp
Go to the documentation of this file.
00001 //
00002 // File: MarkovModulatedSubstitutionModel.cpp
00003 // Created by: Julien Dutheil
00004 // Created on: Sat Aug 05 08:21 2006
00005 //
00006 
00007 /*
00008    Copyright or © or Copr. Bio++ Development Team, (November 16, 2004)
00009 
00010    This software is a computer program whose purpose is to provide classes
00011    for phylogenetic data analysis.
00012 
00013    This software is governed by the CeCILL  license under French law and
00014    abiding by the rules of distribution of free software.  You can  use,
00015    modify and/ or redistribute the software under the terms of the CeCILL
00016    license as circulated by CEA, CNRS and INRIA at the following URL
00017    "http://www.cecill.info".
00018 
00019    As a counterpart to the access to the source code and  rights to copy,
00020    modify and redistribute granted by the license, users are provided only
00021    with a limited warranty  and the software's author,  the holder of the
00022    economic rights,  and the successive licensors  have only  limited
00023    liability.
00024 
00025    In this respect, the user's attention is drawn to the risks associated
00026    with loading,  using,  modifying and/or developing or reproducing the
00027    software by the user in light of its specific status of free software,
00028    that may mean  that it is complicated to manipulate,  and  that  also
00029    therefore means  that it is reserved for developers  and  experienced
00030    professionals having in-depth computer knowledge. Users are therefore
00031    encouraged to load and test the software's suitability as regards their
00032    requirements in conditions enabling the security of their systems and/or
00033    data to be ensured and,  more generally, to use and operate it in the
00034    same conditions as regards security.
00035 
00036    The fact that you are presently reading this means that you have had
00037    knowledge of the CeCILL license and that you accept its terms.
00038  */
00039 
00040 #include "MarkovModulatedSubstitutionModel.h"
00041 
00042 #include <Bpp/Numeric/VectorTools.h>
00043 #include <Bpp/Numeric/Matrix/MatrixTools.h>
00044 #include <Bpp/Numeric/Matrix/EigenValue.h>
00045 
00046 using namespace bpp;
00047 using namespace std;
00048 
00049 /******************************************************************************/
00050 
00051 MarkovModulatedSubstitutionModel::MarkovModulatedSubstitutionModel(
00052   const MarkovModulatedSubstitutionModel& model) :
00053   AbstractParameterAliasable(model),
00054   model_               (dynamic_cast<ReversibleSubstitutionModel*>(model.model_->clone())),
00055   nbStates_            (model.nbStates_),
00056   nbRates_             (model.nbRates_),
00057   rates_               (model.rates_),
00058   ratesExchangeability_(model.ratesExchangeability_),
00059   ratesFreq_           (model.ratesFreq_),
00060   ratesGenerator_      (model.ratesGenerator_),
00061   chars_               (model.chars_),
00062   generator_           (model.generator_),
00063   exchangeability_     (model.exchangeability_),
00064   leftEigenVectors_    (model.leftEigenVectors_),
00065   rightEigenVectors_   (model.rightEigenVectors_),
00066   eigenValues_         (model.eigenValues_),
00067   iEigenValues_        (model.iEigenValues_),
00068   eigenDecompose_      (model.eigenDecompose_),
00069   pijt_                (model.pijt_),
00070   dpijt_               (model.dpijt_),
00071   d2pijt_              (model.d2pijt_),
00072   freq_                (model.freq_),
00073   normalizeRateChanges_(model.normalizeRateChanges_),
00074   nestedPrefix_        (model.nestedPrefix_)
00075 {}
00076 
00077 MarkovModulatedSubstitutionModel& MarkovModulatedSubstitutionModel::operator=(
00078   const MarkovModulatedSubstitutionModel& model)
00079 {
00080   AbstractParametrizable::operator=(model);
00081   model_                = dynamic_cast<ReversibleSubstitutionModel*>(model.model_->clone());
00082   nbStates_             = model.nbStates_;
00083   nbRates_              = model.nbRates_;
00084   rates_                = model.rates_;
00085   ratesExchangeability_ = model.ratesExchangeability_;
00086   ratesFreq_            = model.ratesFreq_;
00087   ratesGenerator_       = model.ratesGenerator_;
00088   chars_                = model.chars_;
00089   generator_            = model.generator_;
00090   exchangeability_      = model.exchangeability_;
00091   leftEigenVectors_     = model.leftEigenVectors_;
00092   rightEigenVectors_    = model.rightEigenVectors_;
00093   eigenValues_          = model.eigenValues_;
00094   iEigenValues_         = model.iEigenValues_;
00095   eigenDecompose_       = model.eigenDecompose_;
00096   pijt_                 = model.pijt_;
00097   dpijt_                = model.dpijt_;
00098   d2pijt_               = model.d2pijt_;
00099   freq_                 = model.freq_;
00100   normalizeRateChanges_ = model.normalizeRateChanges_;
00101   nestedPrefix_         = model.nestedPrefix_;
00102   return *this;
00103 }
00104 
00105 /******************************************************************************/
00106 
00107 void MarkovModulatedSubstitutionModel::updateMatrices()
00108 {
00109   // ratesGenerator_ and rates_ must be initialized!
00110   nbStates_        = model_->getNumberOfStates();
00111   nbRates_         = rates_.getNumberOfColumns();
00112   chars_           = VectorTools::rep(model_->getAlphabetChars(), nbRates_);
00113   RowMatrix<double> Tmp1, Tmp2;
00114   MatrixTools::diag(ratesFreq_, Tmp1);
00115   MatrixTools::mult(ratesExchangeability_, Tmp1, ratesGenerator_);
00116   MatrixTools::kroneckerMult(rates_, model_->getGenerator(), generator_);
00117 
00118   MatrixTools::MatrixTools::getId< RowMatrix<double> >(nbStates_, Tmp1);
00119   MatrixTools::kroneckerMult(ratesGenerator_, Tmp1, Tmp2);
00120   MatrixTools::add(generator_, Tmp2);
00121 
00122   MatrixTools::diag(1. / ratesFreq_, Tmp1);
00123   MatrixTools::mult(rates_, Tmp1, Tmp2);
00124   MatrixTools::kroneckerMult(Tmp2, model_->getExchangeabilityMatrix(), exchangeability_);
00125 
00126   MatrixTools::diag(1 / model_->getFrequencies(), Tmp1);
00127   MatrixTools::kroneckerMult(ratesExchangeability_, Tmp1, Tmp2);
00128   MatrixTools::add(exchangeability_, Tmp2);
00129   freq_ = VectorTools::kroneckerMult(ratesFreq_, model_->getFrequencies());
00130   if (normalizeRateChanges_)
00131   {
00132     // Normalization:
00133     Vdouble Tmp;
00134     MatrixTools::diag(generator_, Tmp);
00135     double scale = -VectorTools::scalar<double, double>(Tmp, freq_);
00136     MatrixTools::scale(generator_, 1. / scale);
00137 
00138     // Normalize exchangeability matrix too:
00139     MatrixTools::scale(exchangeability_, 1. / scale);
00140   }
00141 
00142   // Compute eigen values and vectors:
00143   eigenValues_.resize(nbRates_ * nbStates_);
00144   iEigenValues_.resize(nbRates_ * nbStates_);
00145   rightEigenVectors_.resize(nbStates_ * nbRates_, nbStates_ * nbRates_);
00146   pijt_.resize(nbStates_ * nbRates_, nbStates_ * nbRates_);
00147   dpijt_.resize(nbStates_ * nbRates_, nbStates_ * nbRates_);
00148   d2pijt_.resize(nbStates_ * nbRates_, nbStates_ * nbRates_);
00149 
00150   vector<double>    modelEigenValues       = model_->getEigenValues();
00151   RowMatrix<double> modelRightEigenVectors = model_->getColumnRightEigenVectors();
00152   for (unsigned int i = 0; i < nbStates_; i++)
00153   {
00154     RowMatrix<double> tmp = rates_;
00155     MatrixTools::scale(tmp, modelEigenValues[i]);
00156     MatrixTools::add(tmp, ratesGenerator_);
00157     EigenValue<double> ev(tmp);
00158     vector<double>    values  = ev.getRealEigenValues();
00159     RowMatrix<double> vectors = ev.getV();
00160     for (size_t j = 0; j < nbRates_; j++)
00161     {
00162       size_t c = i * nbRates_ + j; // Current eigen value index.
00163       eigenValues_[c] = values[j];
00164       // Compute the Kronecker product of the jth vector and the ith modelRightEigenVector.
00165       for (unsigned int ii = 0; ii < nbRates_; ii++)
00166       {
00167         double vii = vectors(ii, j);
00168         for (unsigned int jj = 0; jj < nbStates_; jj++)
00169         {
00170           rightEigenVectors_(ii * nbStates_ + jj, c) = vii * modelRightEigenVectors(jj, i);
00171         }
00172       }
00173     }
00174   }
00175   // Now compute left eigen vectors by inversion:
00176   MatrixTools::inv(rightEigenVectors_, leftEigenVectors_);
00177 }
00178 
00179 /******************************************************************************/
00180 
00181 const Matrix<double>& MarkovModulatedSubstitutionModel::getPij_t(double t) const
00182 {
00183   if (t == 0)
00184     MatrixTools::getId< RowMatrix<double> >(nbStates_ * nbRates_, pijt_);
00185   else
00186     MatrixTools::mult(rightEigenVectors_, VectorTools::exp(eigenValues_ * t), leftEigenVectors_, pijt_);
00187   return pijt_;
00188 }
00189 
00190 const Matrix<double>& MarkovModulatedSubstitutionModel::getdPij_dt(double t) const
00191 {
00192   MatrixTools::mult(rightEigenVectors_, eigenValues_ * VectorTools::exp(eigenValues_ * t), leftEigenVectors_, dpijt_);
00193   return dpijt_;
00194 }
00195 
00196 const Matrix<double>& MarkovModulatedSubstitutionModel::getd2Pij_dt2(double t) const
00197 {
00198   MatrixTools::mult(rightEigenVectors_, NumTools::sqr(eigenValues_) * VectorTools::exp(eigenValues_ * t), leftEigenVectors_, d2pijt_);
00199   return d2pijt_;
00200 }
00201 
00202 /******************************************************************************/
00203 
00204 double MarkovModulatedSubstitutionModel::getInitValue(size_t i, int state) const throw (IndexOutOfBoundsException, BadIntException)
00205 {
00206   if (i >= (nbStates_ * nbRates_))
00207     throw IndexOutOfBoundsException("MarkovModulatedSubstitutionModel::getInitValue", i, 0, nbStates_ * nbRates_ - 1);
00208   if (state < 0 || !model_->getAlphabet()->isIntInAlphabet(state))
00209     throw BadIntException(state, "MarkovModulatedSubstitutionModel::getInitValue. Character " + model_->getAlphabet()->intToChar(state) + " is not allowed in model.");
00210   vector<int> states = model_->getAlphabet()->getAlias(state);
00211   for (size_t j = 0; j < states.size(); j++)
00212   {
00213     if (getAlphabetChar(i) == states[j])
00214       return 1.;
00215   }
00216   return 0.;
00217 }
00218 
00219 /******************************************************************************/
00220 
00221 void MarkovModulatedSubstitutionModel::setNamespace(const string& prefix)
00222 {
00223   AbstractParameterAliasable::setNamespace(prefix);
00224   // We also need to update the namespace of the nested model:
00225   model_->setNamespace(prefix + nestedPrefix_);
00226 }
00227 
00228 /******************************************************************************/
00229 
 All Classes Namespaces Files Functions Variables Typedefs Friends