bpp-phyl  2.2.0
SubstitutionModelSet.cpp
Go to the documentation of this file.
1 //
2 // File: SubstitutionModelSet.cpp
3 // Created by: Bastien Boussau
4 // Julien Dutheil
5 // Created on: Tue Aug 21 2007
6 //
7 
8 /*
9  Copyright or <A9> or Copr. CNRS, (November 16, 2004)
10 
11  This software is a computer program whose purpose is to provide classes
12  for phylogenetic data analysis.
13 
14  This software is governed by the CeCILL license under French law and
15  abiding by the rules of distribution of free software. You can use,
16  modify and/ or redistribute the software under the terms of the CeCILL
17  license as circulated by CEA, CNRS and INRIA at the following URL
18  "http://www.cecill.info".
19 
20  As a counterpart to the access to the source code and rights to copy,
21  modify and redistribute granted by the license, users are provided only
22  with a limited warranty and the software's author, the holder of the
23  economic rights, and the successive licensors have only limited
24  liability.
25 
26  In this respect, the user's attention is drawn to the risks associated
27  with loading, using, modifying and/or developing or reproducing the
28  software by the user in light of its specific status of free software,
29  that may mean that it is complicated to manipulate, and that also
30  therefore means that it is reserved for developers and experienced
31  professionals having in-depth computer knowledge. Users are therefore
32  encouraged to load and test the software's suitability as regards their
33  requirements in conditions enabling the security of their systems and/or
34  data to be ensured and, more generally, to use and operate it in the
35  same conditions as regards security.
36 
37  The fact that you are presently reading this means that you have had
38  knowledge of the CeCILL license and that you accept its terms.
39 */
40 
41 #include "SubstitutionModelSet.h"
42 #include "MixedSubstitutionModel.h"
43 
44 #include <Bpp/Utils/MapTools.h>
45 
46 using namespace bpp;
47 using namespace std;
48 
50  AbstractParameterAliasable(set),
51  alphabet_ (set.alphabet_),
52  nbStates_ (set.nbStates_),
53  modelSet_(set.modelSet_.size()),
54  rootFrequencies_(set.stationarity_ ? 0 : dynamic_cast<FrequenciesSet*>(set.rootFrequencies_->clone())),
55  nodeToModel_ (set.nodeToModel_),
56  modelToNodes_ (set.modelToNodes_),
57  modelParameters_ (set.modelParameters_),
58  stationarity_ (set.stationarity_)
59 {
60  // Duplicate all model objects:
61  for (size_t i = 0; i < set.modelSet_.size(); i++)
62  {
63  modelSet_[i] = dynamic_cast<SubstitutionModel*>(set.modelSet_[i]->clone());
64  }
65 }
66 
68 {
69  AbstractParameterAliasable::operator=(set);
70  alphabet_ = set.alphabet_;
71  nbStates_ = set.nbStates_;
72  nodeToModel_ = set.nodeToModel_;
73  modelToNodes_ = set.modelToNodes_;
74  modelParameters_ = set.modelParameters_;
75  stationarity_ = set.stationarity_;
76  if (set.stationarity_)
77  rootFrequencies_.reset(0);
78  else
79  rootFrequencies_.reset(dynamic_cast<FrequenciesSet*>(set.rootFrequencies_->clone()));
80 
81  // Duplicate all model objects:
82  modelSet_.resize(set.modelSet_.size());
83  for (size_t i = 0; i < set.modelSet_.size(); i++)
84  {
85  modelSet_[i] = dynamic_cast<SubstitutionModel*>(set.modelSet_[i]->clone());
86  }
87  return *this;
88 }
89 
91 {
92  resetParameters_();
93  nbStates_=0;
94  for (size_t i = 0; i < modelSet_.size(); i++)
95  {
96  delete modelSet_[i];
97  }
98  modelSet_.clear();
99  rootFrequencies_.reset();
100  nodeToModel_.clear();
101  modelParameters_.clear();
102  stationarity_=true;
103 
104 }
105 
107 {
108  if (rootFreqs){
109  stationarity_=false;
110  rootFrequencies_.reset(rootFreqs);
111  addParameters_(rootFrequencies_->getParameters());
112  }
113 }
114 
115 std::vector<int> SubstitutionModelSet::getNodesWithParameter(const std::string& name) const
116  throw (ParameterNotFoundException)
117 {
118  if (!(hasParameter(name)))
119  throw ParameterNotFoundException("SubstitutionModelSet::getNodesWithParameter.", name);
120 
121  vector<string> nalias=getAlias(name);
122  size_t p=name.rfind("_");
123  vector<int> inode = getNodesWithModel(TextTools::to<size_t>(name.substr(p+1,string::npos)) - 1);
124 
125  for (size_t i = 0; i < nalias.size(); i++)
126  {
127  p=nalias[i].rfind("_");
128  vector<int> ni = getNodesWithModel(TextTools::to<size_t>(nalias[i].substr(p+1,string::npos))-1);
129  inode.insert(inode.end(),ni.begin(),ni.end());
130  }
131 
132  return inode;
133 }
134 
135 void SubstitutionModelSet::addModel(SubstitutionModel* model, const std::vector<int>& nodesId)//, const vector<string>& newParams) throw (Exception)
136 {
137  if (model->getAlphabet()->getAlphabetType() != alphabet_->getAlphabetType())
138  throw Exception("SubstitutionModelSet::addModel. A Substitution Model cannot be added to a Model Set if it does not have the same alphabet.");
139  if (modelSet_.size() > 0 && model->getNumberOfStates() != nbStates_)
140  throw Exception("SubstitutionModelSet::addModel. A Substitution Model cannot be added to a Model Set if it does not have the same number of states.");
141  if (modelSet_.size() == 0)
142  nbStates_ = model->getNumberOfStates();
143  modelSet_.push_back(model);
144  size_t thisModelIndex = modelSet_.size() - 1;
145 
146  // Associate this model to specified nodes:
147  for (size_t i = 0; i < nodesId.size(); i++)
148  {
149  nodeToModel_[nodesId[i]] = thisModelIndex;
150  modelToNodes_[thisModelIndex].push_back(nodesId[i]);
151  }
152 
153  // Associate parameters:
154  string pname;
155 
156  vector<string> nplm=model->getParameters().getParameterNames();
157 
158  modelParameters_.push_back(*model->getParameters().clone());
159 
160  for (size_t i = 0; i < nplm.size(); i++)
161  {
162  pname = nplm[i];
163  Parameter* p = new Parameter(model->getParameters().getParameter(pname)); // We work with namespaces here, so model->getParameter(pname) does not work.
164  p->setName(pname + "_" + TextTools::toString(thisModelIndex+1));
165  addParameter_(p);
166  }
167 }
168 
169 void SubstitutionModelSet::replaceModel(size_t modelIndex, SubstitutionModel* model) throw (Exception)
170 {
171  delete modelSet_[modelIndex];
172  modelSet_[modelIndex]=model;
173 
174 
175  // Erase all parameter references to this model
176 
177  ParameterList pl=getNodeParameters();
178 
179  for (size_t i = pl.size(); i>0; i--)
180  {
181  string pn=pl[i-1].getName();
182 
183  size_t pu=pn.rfind("_");
184  int nm=TextTools::toInt(pn.substr(pu+1,string::npos));
185  if (nm==(int)modelIndex+1){
186  vector<string> alpn=getAlias(pn);
187  for (unsigned j=0; j<alpn.size(); j++)
188  try {
189  unaliasParameters(alpn[j],pn);
190  }
191  catch (Exception& e)
192  {
193  continue;
194  }
195  deleteParameter_(i-1);
196  }
197  }
198 
199  // Associate new parameters
200  string pname;
201 
202  vector<string> nplm=model->getParameters().getParameterNames();
203 
204  for (size_t i = 0; i < nplm.size(); i++)
205  {
206  pname = nplm[i];
207  Parameter* p = new Parameter(model->getParameters().getParameter(pname)); // We work with namespaces here, so model->getParameter(pname) does not work.
208  p->setName(pname + "_" + TextTools::toString(modelIndex+1));
209  addParameter_(p);
210  }
211 
212  // update modelParameters_
213 
214  modelParameters_[modelIndex].reset();
215  modelParameters_[modelIndex]=*model->getParameters().clone();
216 }
217 
218 void SubstitutionModelSet::listModelNames(std::ostream& out) const
219 {
220  for (size_t i = 0; i < modelSet_.size(); i++)
221  {
222  out << "Model " << i + 1 << ": " << modelSet_[i]->getName() << "\t attached to nodes ";
223  for (size_t j = 0; j < modelToNodes_[i].size(); j++)
224  {
225  out << modelToNodes_[i][j];
226  }
227  out << endl;
228  }
229 }
230 
231 void SubstitutionModelSet::fireParameterChanged(const ParameterList& parameters)
232 {
233  AbstractParameterAliasable::fireParameterChanged(parameters);
234 
235  // Update root frequencies:
237 
238  // Then we update all models in the set:
239  for (size_t i = 0; i < modelParameters_.size(); i++)
240  {
241  for (size_t np = 0 ; np< modelParameters_[i].size() ; np++)
242  {
243  modelParameters_[i][np].setValue(getParameterValue(modelParameters_[i][np].getName()+"_"+TextTools::toString(i+1)));
244  }
245  modelSet_[i]->matchParametersValues(modelParameters_[i]);
246  }
247 }
248 
250  throw (Exception)
251 {
252  vector<size_t> index = MapTools::getValues(nodeToModel_);
253  for (size_t i = 0; i < modelSet_.size(); i++)
254  {
255  if (!VectorTools::contains(index, i))
256  {
257  if (throwEx) throw Exception("SubstitutionModelSet::checkOrphanModels(). Model '" + TextTools::toString(i + 1) + "' is associated to no node.");
258  return false;
259  }
260  }
261  return true;
262 }
263 
264 bool SubstitutionModelSet::checkOrphanNodes(const Tree& tree, bool throwEx) const
265  throw (Exception)
266 {
267  vector<int> ids = tree.getNodesId();
268  int rootId = tree.getRootId();
269  for (size_t i = 0; i < ids.size(); i++)
270  {
271  if (ids[i] != rootId && nodeToModel_.find(ids[i]) == nodeToModel_.end())
272  {
273  if (throwEx) throw Exception("SubstitutionModelSet::checkOrphanNodes(). Node '" + TextTools::toString(ids[i]) + "' in tree has no model associated.");
274  return false;
275  }
276  }
277  return true;
278 }
279 
280 bool SubstitutionModelSet::checkUnknownNodes(const Tree& tree, bool throwEx) const
281  throw (Exception)
282 {
283  vector<int> ids = tree.getNodesId();
284  int id;
285  int rootId = tree.getRootId();
286  for (size_t i = 0; i < modelToNodes_.size(); i++)
287  {
288  for (size_t j = 0; j < modelToNodes_[i].size(); j++)
289  {
290  id = modelToNodes_[i][j];
291  if (id == rootId || !VectorTools::contains(ids, id))
292  {
293  if (throwEx) throw Exception("SubstitutionModelSet::checkUnknownNodes(). Node '" + TextTools::toString(id) + "' is not found in tree or is the root node.");
294  return false;
295  }
296  }
297  }
298  return true;
299 }
300 
302 {
303  for (size_t i = 0; i < getNumberOfModels(); i++)
304  {
305  if (dynamic_cast<const MixedSubstitutionModel*>(getModel(i)) != NULL)
306  return true;
307  }
308  return false;
309 }
310 
std::map< size_t, std::vector< int > > modelToNodes_
Substitution models manager for non-homogeneous / non-reversible models of evolution.
Interface for all substitution models.
const SubstitutionModel * getModel(size_t i) const
Get one model from the set knowing its index.
void setRootFrequencies(FrequenciesSet *rootFreqs)
Sets a given FrequenciesSet for root frequencies.
virtual const Alphabet * getAlphabet() const =0
STL namespace.
void listModelNames(std::ostream &out=std::cout) const
Interface for phylogenetic tree objects.
Definition: Tree.h:148
Parametrize a set of state frequencies.
void addModel(SubstitutionModel *model, const std::vector< int > &nodesId)
Add a new model to the set, and set relationships with nodes and params.
std::map< int, size_t > nodeToModel_
Contains for each node in a tree the index of the corresponding model in modelSet_.
std::vector< ParameterList > modelParameters_
Parameters for each model in the set.
void clear()
Resets all the information contained in this object.
void replaceModel(size_t modelIndex, SubstitutionModel *model)
Replace a model in the set, and all corresponding parameters. The replaced model deleted.
std::auto_ptr< FrequenciesSet > rootFrequencies_
Root frequencies.
std::vector< SubstitutionModel * > modelSet_
Contains all models used in this tree.
bool checkOrphanModels(bool throwEx) const
virtual void fireParameterChanged(const ParameterList &parameters)
SubstitutionModelSet & operator=(const SubstitutionModelSet &set)
virtual size_t getNumberOfStates() const =0
Get the number of states.
SubstitutionModel * clone() const =0
SubstitutionModelSet(const Alphabet *alpha)
Create a model set according to the specified alphabet. Stationarity is assumed.
std::vector< int > getNodesWithParameter(const std::string &name) const
const Alphabet * alphabet_
A pointer toward the common alphabet to all models in the set.
bool checkOrphanNodes(const Tree &tree, bool throwEx) const
bool checkUnknownNodes(const Tree &tree, bool throwEx) const