bpp-phyl3 3.0.0
SubstitutionModelSet.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: The Bio++ Development Group
2//
3// SPDX-License-Identifier: CECILL-2.1
4
6
7#include "../../Model/MixedTransitionModel.h"
9
10using namespace bpp;
11using namespace std;
12
13SubstitutionModelSet::SubstitutionModelSet(const SubstitutionModelSet& set) :
15 alphabet_ (set.alphabet_),
16 nbStates_ (set.nbStates_),
17 modelSet_(set.modelSet_.size()),
18 rootFrequencies_(set.stationarity_ ? nullptr : set.rootFrequencies_->clone()),
19 nodeToModel_ (set.nodeToModel_),
20 modelToNodes_ (set.modelToNodes_),
21 modelParameters_ (set.modelParameters_),
22 stationarity_ (set.stationarity_)
23{
24 // Duplicate all model objects:
25 for (size_t i = 0; i < set.modelSet_.size(); ++i)
26 {
27 modelSet_[i].reset(set.modelSet_[i]->clone());
28 }
29}
30
32{
34 alphabet_ = set.alphabet_;
35 nbStates_ = set.nbStates_;
40 if (set.stationarity_)
41 rootFrequencies_ = nullptr;
42 else
43 rootFrequencies_.reset(set.rootFrequencies_->clone());
44
45 // Duplicate all model objects:
46 modelSet_.resize(set.modelSet_.size());
47 for (size_t i = 0; i < set.modelSet_.size(); ++i)
48 {
49 modelSet_[i].reset(set.modelSet_[i]->clone());
50 }
51 return *this;
52}
53
55{
57 nbStates_ = 0;
58 modelSet_.clear();
59 rootFrequencies_.reset();
60 nodeToModel_.clear();
61 modelParameters_.clear();
62 stationarity_ = true;
63}
64
65void SubstitutionModelSet::setRootFrequencies(shared_ptr<FrequencySetInterface> rootFreqs)
66{
67 if (rootFreqs)
68 {
69 stationarity_ = false;
70 rootFrequencies_ = rootFreqs;
71 addParameters_(rootFrequencies_->getParameters());
72 }
73}
74
75std::vector<int> SubstitutionModelSet::getNodesWithParameter(const std::string& name) const
76{
77 if (!(hasParameter(name)))
78 throw ParameterNotFoundException("SubstitutionModelSet::getNodesWithParameter.", name);
79
80 vector<string> nalias = getAlias(name);
81 size_t p = name.rfind("_");
82 vector<int> inode = getNodesWithModel(TextTools::to<size_t>(name.substr(p + 1, string::npos)) - 1);
83
84 for (size_t i = 0; i < nalias.size(); i++)
85 {
86 p = nalias[i].rfind("_");
87 size_t pos = TextTools::to<size_t>(nalias[i].substr(p + 1, string::npos));
88 if (pos > 0)
89 {
90 vector<int> ni = getNodesWithModel(pos - 1);
91 inode.insert(inode.end(), ni.begin(), ni.end());
92 }
93 }
94
95 return inode;
96}
97
98void SubstitutionModelSet::addModel(shared_ptr<TransitionModelInterface> model, const std::vector<int>& nodesId) // , const vector<string>& newParams)
99{
100 if (model->alphabet().getAlphabetType() != alphabet_->getAlphabetType())
101 throw Exception("SubstitutionModelSet::addModel. A Substitution Model cannot be added to a Model Set if it does not have the same alphabet.");
102 if (modelSet_.size() > 0 && model->getNumberOfStates() != nbStates_)
103 throw Exception("SubstitutionModelSet::addModel. A Substitution Model cannot be added to a Model Set if it does not have the same number of states.");
104 if (modelSet_.size() == 0)
106 modelSet_.push_back(model);
107 size_t thisModelIndex = modelSet_.size() - 1;
108
109 // Associate this model to specified nodes:
110 for (size_t i = 0; i < nodesId.size(); i++)
111 {
112 nodeToModel_[nodesId[i]] = thisModelIndex;
113 modelToNodes_[thisModelIndex].push_back(nodesId[i]);
114 }
115
116 // Associate parameters:
117 string pname;
118
119 vector<string> nplm = model->getParameters().getParameterNames();
120
122
123 for (size_t i = 0; i < nplm.size(); i++)
124 {
125 pname = nplm[i];
126 Parameter* p = new Parameter(model->getParameters().parameter(pname)); // We work with namespaces here, so model->parameter(pname) does not work.
127 p->setName(pname + "_" + TextTools::toString(thisModelIndex + 1));
128 addParameter_(p);
129 }
130}
131
133{
134 // reset nodeToModel_
135 nodeToModel_.clear();
136 // reset modelToNodes_
137 modelToNodes_.clear();
138}
139
140void SubstitutionModelSet::setNodeToModel(size_t modelIndex, int nodeId)
141{
142 if (modelIndex > modelSet_.size() - 1)
143 throw Exception("SubstitutionModelSet::setNodesToModel. There is no Substitution Model of index " + TextTools::toString(modelIndex));
144
145 nodeToModel_[nodeId] = modelIndex;
146 modelToNodes_[modelIndex].push_back(nodeId);
147}
148
149void SubstitutionModelSet::replaceModel(size_t modelIndex, shared_ptr<TransitionModelInterface> model)
150{
151 modelSet_[modelIndex] = model;
152
153 // Erase all parameter references to this model
154
156
157 for (size_t i = pl.size(); i > 0; i--)
158 {
159 string pn = pl[i - 1].getName();
160
161 size_t pu = pn.rfind("_");
162 int nm = TextTools::toInt(pn.substr(pu + 1, string::npos));
163
164 if (nm == (int)modelIndex + 1)
165 {
166 vector<string> alpn = getAlias(pn);
167 for (unsigned j = 0; j < alpn.size(); j++)
168 {
169 try
170 {
171 unaliasParameters(alpn[j], pn);
172 }
173 catch (Exception& e)
174 {
175 continue;
176 }
177 }
179 }
180 }
181
182 // Associate new parameters
183 string pname;
184
185 vector<string> nplm = model->getParameters().getParameterNames();
186
187 for (size_t i = 0; i < nplm.size(); i++)
188 {
189 pname = nplm[i];
190 Parameter* p = new Parameter(model->getParameters().parameter(pname)); // We work with namespaces here, so model->parameter(pname) does not work.
191 p->setName(pname + "_" + TextTools::toString(modelIndex + 1));
192 addParameter_(p);
193 }
194
195 // update modelParameters_
196
197 modelParameters_[modelIndex].reset();
198 modelParameters_[modelIndex] = *model->getParameters().clone();
199}
200
201void SubstitutionModelSet::listModelNames(std::ostream& out) const
202{
203 for (size_t i = 0; i < modelSet_.size(); i++)
204 {
205 out << "Model " << i + 1 << ": " << modelSet_[i]->getName() << "\t attached to nodes ";
206 for (size_t j = 0; j < modelToNodes_[i].size(); j++)
207 {
208 out << modelToNodes_[i][j];
209 }
210 out << endl;
211 }
212}
213
215{
216 // Update root frequencies:
218
219 // Then we update all models in the set:
220 for (size_t i = 0; i < modelParameters_.size(); i++)
221 {
222 for (size_t np = 0; np < modelParameters_[i].size(); np++)
223 {
224 modelParameters_[i][np].setValue(getParameterValue(modelParameters_[i][np].getName() + "_" + TextTools::toString(i + 1)));
225 }
226 modelSet_[i]->matchParametersValues(modelParameters_[i]);
227 }
228}
229
231{
232 vector<size_t> index = MapTools::getValues(nodeToModel_);
233 for (size_t i = 0; i < modelSet_.size(); i++)
234 {
235 if (!VectorTools::contains(index, i))
236 {
237 if (throwEx)
238 throw Exception("SubstitutionModelSet::checkOrphanModels(). Model '" + TextTools::toString(i + 1) + "' is associated to no node.");
239 return false;
240 }
241 }
242 return true;
243}
244
245bool SubstitutionModelSet::checkOrphanNodes(const Tree& tree, bool throwEx) const
246{
247 vector<int> ids = tree.getNodesId();
248 int rootId = tree.getRootId();
249 for (size_t i = 0; i < ids.size(); i++)
250 {
251 if (ids[i] != rootId && nodeToModel_.find(ids[i]) == nodeToModel_.end())
252 {
253 if (throwEx)
254 throw Exception("SubstitutionModelSet::checkOrphanNodes(). Node '" + TextTools::toString(ids[i]) + "' in tree has no model associated.");
255 return false;
256 }
257 }
258 return true;
259}
260
261bool SubstitutionModelSet::checkUnknownNodes(const Tree& tree, bool throwEx) const
262{
263 vector<int> ids = tree.getNodesId();
264 int id;
265 int rootId = tree.getRootId();
266 for (size_t i = 0; i < modelToNodes_.size(); i++)
267 {
268 for (size_t j = 0; j < modelToNodes_[i].size(); j++)
269 {
270 id = modelToNodes_[i][j];
271 if (id == rootId || !VectorTools::contains(ids, id))
272 {
273 if (throwEx)
274 throw Exception("SubstitutionModelSet::checkUnknownNodes(). Node '" + TextTools::toString(id) + "' is not found in tree or is the root node.");
275 return false;
276 }
277 }
278 }
279 return true;
280}
281
283{
284 for (size_t i = 0; i < getNumberOfModels(); ++i)
285 {
286 if ((dynamic_cast<const MixedTransitionModelInterface*>(getModel(i).get()) != nullptr) && (modelToNodes_[i].size() > 1))
287 return true;
288 }
289 return false;
290}
void addParameters_(const ParameterList &parameters)
virtual std::vector< std::string > getAlias(const std::string &name) const
void unaliasParameters(const std::string &p1, const std::string &p2)
void deleteParameter_(size_t index)
void addParameter_(Parameter *parameter)
AbstractParameterAliasable & operator=(const AbstractParameterAliasable &ap)
bool hasParameter(const std::string &name) const override
double getParameterValue(const std::string &name) const override
virtual std::string getAlphabetType() const=0
virtual size_t getNumberOfStates() const =0
Get the number of states.
virtual const Alphabet & alphabet() const =0
static std::vector< T > getValues(const std::map< Key, T, Cmp > &myMap)
Interface for Transition models, defined as a mixture of "simple" transition models.
size_t size() const
virtual std::vector< std::string > getParameterNames() const
ParameterList * clone() const
virtual const Parameter & parameter(const std::string &name) const
virtual void setName(const std::string &name)
virtual const ParameterList & getParameters() const=0
Substitution models manager for non-homogeneous / non-reversible models of evolution.
virtual void fireParameterChanged(const ParameterList &parameters)
const TransitionModelInterface & model(size_t i) const
void setNodeToModel(size_t modelIndex, int nodeId)
Sets an assignment of a given model index to a given onde id.
std::shared_ptr< FrequencySetInterface > rootFrequencies_
Root frequencies.
std::vector< int > getNodesWithParameter(const std::string &name) const
bool checkOrphanModels(bool throwEx) const
std::shared_ptr< const Alphabet > alphabet_
A pointer toward the common alphabet to all models in the set.
bool checkOrphanNodes(const Tree &tree, bool throwEx) const
void setRootFrequencies(std::shared_ptr< FrequencySetInterface > rootFreqs)
Sets a given FrequencySet for root frequencies.
std::map< int, size_t > nodeToModel_
Contains for each node in a tree the index of the corresponding model in modelSet_.
void addModel(std::shared_ptr< TransitionModelInterface > model, const std::vector< int > &nodesId)
Add a new model to the set, and set relationships with nodes and params.
void listModelNames(std::ostream &out=std::cout) const
void resetModelToNodeIds()
Reset model indices to node ids assignment.
SubstitutionModelSet & operator=(const SubstitutionModelSet &set)
const std::vector< int > & getNodesWithModel(size_t i) const
Get a list of nodes id for which the given model is associated.
std::map< size_t, std::vector< int > > modelToNodes_
ParameterList getNodeParameters() const
Get the parameters corresponding attached to the nodes of the tree.
bool checkUnknownNodes(const Tree &tree, bool throwEx) const
void replaceModel(size_t modelIndex, std::shared_ptr< TransitionModelInterface > model)
Replace a model in the set, and all corresponding parameters. The replaced model deleted.
std::vector< std::shared_ptr< TransitionModelInterface > > modelSet_
Contains all models used in this tree.
std::vector< ParameterList > modelParameters_
Parameters for each model in the set.
void clear()
Resets all the information contained in this object.
std::shared_ptr< const TransitionModelInterface > getModel(size_t i) const
Get one model from the set knowing its index.
Interface for phylogenetic tree objects.
Definition: Tree.h:115
virtual std::vector< int > getNodesId() const =0
virtual int getRootId() const =0
static bool contains(const std::vector< T > &vec, T el)
int toInt(const std::string &s, char scientificNotation='e')
std::string toString(T t)
Defines the basic types of data flow nodes.