bpp-phyl3 3.0.0
SubstitutionProcessCollection.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: The Bio++ Development Group
2//
3// SPDX-License-Identifier: CECILL-2.1
4
7
11
12using namespace bpp;
13using namespace std;
14
15SubstitutionProcessCollection::SubstitutionProcessCollection(const SubstitutionProcessCollection& set) :
17 modelColl_(set.modelColl_),
18 mModelToSubPro_(set.mModelToSubPro_),
19 freqColl_(set.freqColl_),
20 mFreqToSubPro_(set.mFreqToSubPro_),
21 distColl_(set.distColl_),
22 mVConstDist_(set.mVConstDist_),
23 mDistToSubPro_(set.mDistToSubPro_),
24 treeColl_(set.treeColl_),
25 mTreeToSubPro_(set.mTreeToSubPro_),
26 mSubProcess_()
27{
28 for (const auto& it : set.mSubProcess_)
29 {
31 mSubProcess_[it.first] = shared_ptr<SubstitutionProcessCollectionMember>(x, SubstitutionProcessCollectionMember::Deleter());
32 }
33}
34
36{
37 clear();
38
42 freqColl_ = set.freqColl_;
44 distColl_ = set.distColl_;
47 treeColl_ = set.treeColl_;
49
50 for (const auto& it : set.mSubProcess_)
51 {
52 mSubProcess_[it.first] = shared_ptr<SubstitutionProcessCollectionMember>(it.second->clone(), SubstitutionProcessCollectionMember::Deleter());
53 }
54
55 return *this;
56}
57
59{
61
62 modelColl_.clear();
63 mModelToSubPro_.clear();
64 freqColl_.clear();
65 mFreqToSubPro_.clear();
66 distColl_.clear();
67 mDistToSubPro_.clear();
68 mVConstDist_.clear();
69 treeColl_.clear();
70 mTreeToSubPro_.clear();
71
72 mSubProcess_.clear();
73}
74
75void SubstitutionProcessCollection::addParametrizable(std::shared_ptr<Parametrizable> parametrizable, size_t parametrizableIndex, bool withParameters)
76{
77 if (parametrizableIndex < 1)
78 throw BadIntegerException("SubstitutionProcessCollection::addParametrizable: parametrizableIndex should be at least 1.", (int)parametrizableIndex);
79
81 if (std::dynamic_pointer_cast<BranchModelInterface>(parametrizable))
82 {
83 modelColl_.addObject(std::dynamic_pointer_cast<BranchModelInterface>(parametrizable), parametrizableIndex);
84 pl = modelColl_.getParametersForObject(parametrizableIndex);
85 }
86 else if (std::dynamic_pointer_cast<FrequencySetInterface>(parametrizable))
87 {
88 freqColl_.addObject(std::dynamic_pointer_cast<FrequencySetInterface>(parametrizable), parametrizableIndex);
89 pl = freqColl_.getParametersForObject(parametrizableIndex);
90 }
91 else if (std::dynamic_pointer_cast<DiscreteDistributionInterface>(parametrizable))
92 {
93 distColl_.addObject(std::dynamic_pointer_cast<DiscreteDistributionInterface>(parametrizable), parametrizableIndex);
94 pl = distColl_.getParametersForObject(parametrizableIndex);
95 }
96 else if (std::dynamic_pointer_cast<ParametrizablePhyloTree>(parametrizable))
97 {
98 treeColl_.addObject(std::dynamic_pointer_cast<ParametrizablePhyloTree>(parametrizable), parametrizableIndex);
99 pl = treeColl_.getParametersForObject(parametrizableIndex);
100 }
101
102 else
103 throw Exception("Unknown parametrizable object in SubstitutionProcessCollection::addParametrizable.");
104
105 if (withParameters)
106 addParameters_(pl);
107}
108
109void SubstitutionProcessCollection::replaceParametrizable(std::shared_ptr<Parametrizable> parametrizable, size_t parametrizableIndex, bool withParameters)
110{
111 if (parametrizableIndex < 1)
112 throw BadIntegerException("SubstitutionProcessCollection::addParametrizable: parametrizableIndex should be at least 1.", (int)parametrizableIndex);
113
114
115 ParameterList pl;
116 if (std::dynamic_pointer_cast<BranchModelInterface>(parametrizable))
117 {
118 if (!hasModelNumber(parametrizableIndex))
119 {
120 addParametrizable(parametrizable, parametrizableIndex, withParameters);
121 return;
122 }
123 getParameters_().deleteParameters(modelColl_.getParametersForObject(parametrizableIndex).getParameterNames(), false);
124 modelColl_.replaceObject(std::dynamic_pointer_cast<BranchModelInterface>(parametrizable), parametrizableIndex);
125 pl = modelColl_.getParametersForObject(parametrizableIndex);
126 }
127 else if (std::dynamic_pointer_cast<FrequencySetInterface>(parametrizable))
128 {
129 if (!hasFrequenciesNumber(parametrizableIndex))
130 {
131 addParametrizable(parametrizable, parametrizableIndex, withParameters);
132 return;
133 }
134 getParameters_().deleteParameters(freqColl_.getParametersForObject(parametrizableIndex).getParameterNames(), false);
135 freqColl_.replaceObject(std::dynamic_pointer_cast<FrequencySetInterface>(parametrizable), parametrizableIndex);
136 pl = freqColl_.getParametersForObject(parametrizableIndex);
137 }
138 else if (std::dynamic_pointer_cast<DiscreteDistributionInterface>(parametrizable))
139 {
140 if (!hasDistributionNumber(parametrizableIndex))
141 {
142 addParametrizable(parametrizable, parametrizableIndex, withParameters);
143 return;
144 }
145 getParameters_().deleteParameters(distColl_.getParametersForObject(parametrizableIndex).getParameterNames(), false);
146 distColl_.replaceObject(std::dynamic_pointer_cast<DiscreteDistributionInterface>(parametrizable), parametrizableIndex);
147 pl = distColl_.getParametersForObject(parametrizableIndex);
148 }
149 else if (std::dynamic_pointer_cast<ParametrizablePhyloTree>(parametrizable))
150 {
151 if (!hasTreeNumber(parametrizableIndex))
152 {
153 addParametrizable(parametrizable, parametrizableIndex, withParameters);
154 return;
155 }
156 getParameters_().deleteParameters(treeColl_.getParametersForObject(parametrizableIndex).getParameterNames(), false);
157 treeColl_.replaceObject(std::dynamic_pointer_cast<ParametrizablePhyloTree>(parametrizable), parametrizableIndex);
158 pl = treeColl_.getParametersForObject(parametrizableIndex);
159 }
160
161 else
162 throw Exception("Unknown parametrizable object in SubstitutionProcessCollection::addParametrizable.");
163
164 if (withParameters)
165 addParameters_(pl);
166}
167
168
170{
171 ParameterList pl = distColl_.getIndependentParameters();
172 pl.addParameters(modelColl_.getIndependentParameters());
173 pl.addParameters(freqColl_.getIndependentParameters());
174
177
178 return pl;
179}
180
182{
183 ParameterList gAP = getAliasedParameters(parameters);
184
185 gAP.addParameters(parameters);
186
187 modelColl_.clearChanged();
188 modelColl_.matchParametersValues(gAP);
189
190 freqColl_.clearChanged();
191 freqColl_.matchParametersValues(gAP);
192
193 // map of the SubProcess to be fired
194
195 map<size_t, bool> toFire;
196
197 distColl_.clearChanged();
198 distColl_.matchParametersValues(gAP);
199 const vector<size_t>& vD = distColl_.hasChanged();
200
201 for (size_t i = 0; i < vD.size(); i++)
202 {
203 const vector<size_t>& vs = mDistToSubPro_[vD[i]];
204 for (size_t j = 0; j < vs.size(); j++)
205 {
206 toFire[vs[j]] = true;
207 }
208
209 if (mVConstDist_.find(vD[i]) != mVConstDist_.end())
210 {
211 auto dd = getRateDistribution(vD[i]);
212 vector<size_t>& vv = mVConstDist_[vD[i]];
213
214 for (size_t j = 0; j < vv.size(); j++)
215 {
216 gAP.addParameter(new Parameter("Constant.value_" + TextTools::toString(10000 * (vD[i] + 1) + vv[j]), dd->getCategory(j)));
217 std::dynamic_pointer_cast<ConstantDistribution>(distColl_[10000 * (vD[i] + 1) + vv[j]])->setParameterValue("value", dd->getCategory(j));
218 const vector<size_t>& vs2 = mDistToSubPro_[10000 * (vD[i] + 1) + vv[j]];
219 for (size_t k = 0; k < vs2.size(); k++)
220 {
221 toFire[vs2[k]] = true;
222 }
223 }
224 }
225 }
226
227
228 treeColl_.clearChanged();
229 treeColl_.matchParametersValues(gAP);
230
231 const vector<size_t>& vT = treeColl_.hasChanged();
232
233 for (size_t i = 0; i < vT.size(); i++)
234 {
235 const vector<size_t>& vs = mTreeToSubPro_[vT[i]];
236 for (size_t j = 0; j < vs.size(); j++)
237 {
238 toFire[vs[j]] = true;
239 }
240 }
241
242
243 // send the message to subprocesses
244
245 map<size_t, bool>::const_iterator it;
246
247 for (it = toFire.begin(); it != toFire.end(); it++)
248 {
249 mSubProcess_[it->first]->fireParameterChanged(gAP);
250 }
251}
252
253
255{
257 for (auto& it : mSubProcess_)
258 {
259 it.second->setNamespace(prefix);
260 }
261}
262
263void SubstitutionProcessCollection::aliasParameters(const std::string& p1, const std::string& p2)
264{
266 for (auto& it : mSubProcess_)
267 {
268 if (it.second->hasParameter(p2))
269 {
270 string p = p2;
271 it.second->deleteParameter_(p);
272 }
273 }
274}
275
276void SubstitutionProcessCollection::unaliasParameters(const std::string& p1, const std::string& p2)
277{
279 for (auto& it : mSubProcess_)
280 {
281 it.second->updateParameters();
282 }
283}
284
285void SubstitutionProcessCollection::aliasParameters(std::map<std::string, std::string>& unparsedParams, bool verbose)
286{
287 AbstractParameterAliasable::aliasParameters(unparsedParams, verbose);
288 for (auto& itp : unparsedParams)
289 {
290 string p2 = itp.second;
291
292 for (auto& it : mSubProcess_)
293 {
294 if (it.second->hasParameter(p2))
295 it.second->deleteParameter_(p2);
296 }
297 }
298}
299
300
301void SubstitutionProcessCollection::addSubstitutionProcess(size_t nProc, std::map<size_t, std::vector<unsigned int>> mModBr, size_t nTree, size_t nRate, size_t nFreq)
302{
303 addSubstitutionProcess(nProc, mModBr, nTree, nRate);
304
305 if (!freqColl_.hasObject(nFreq))
306 throw BadIntegerException("Wrong Root Frequencies Set number", (int)nFreq);
307
309 pSMS.setRootFrequencies(nFreq);
310
311 mFreqToSubPro_[nFreq].push_back(nProc);
312}
313
314void SubstitutionProcessCollection::addSubstitutionProcess(size_t nProc, std::map<size_t, std::vector<unsigned int>> mModBr, size_t nTree, size_t nRate)
315{
316 if (mSubProcess_.find(nProc) != mSubProcess_.end())
317 throw BadIntegerException("Already assigned substitution process", (int)nProc);
318
319 if (nTree != 0 && !treeColl_.hasObject(nTree))
320 throw BadIntegerException("Wrong Tree number", (int)nTree);
321
322 if (!distColl_.hasObject(nRate))
323 throw BadIntegerException("Wrong Rate distribution number", (int)nRate);
324
325 auto pSMS = shared_ptr<SubstitutionProcessCollectionMember>(
326 new SubstitutionProcessCollectionMember(this, nProc, nTree, nRate),
328 );
329
330 std::map<size_t, std::vector<unsigned int>>::iterator it;
331 for (it = mModBr.begin(); it != mModBr.end(); it++)
332 {
333 pSMS->addModel(it->first, it->second);
334 mModelToSubPro_[it->first].push_back(nProc);
335 }
336
337 pSMS->isFullySetUp(nTree != 0);
338
339 mTreeToSubPro_[nTree].push_back(nProc);
340 mDistToSubPro_[nRate].push_back(nProc);
341
342 mSubProcess_[nProc] = pSMS;
343}
344
346{
347 ParameterList pl = modelColl_.getParameters();
348 pl.addParameters(treeColl_.getParameters());
349 pl.addParameters(freqColl_.getParameters());
350 pl.addParameters(distColl_.getParameters());
351
352 return pl;
353}
354
355
356void SubstitutionProcessCollection::addOnePerBranchSubstitutionProcess(size_t nProc, size_t nMod, size_t nTree, size_t nRate, size_t nFreq, const vector<string>& sharedParameterNames)
357{
358 addOnePerBranchSubstitutionProcess(nProc, nMod, nTree, nRate, sharedParameterNames);
359
360 if (!freqColl_.hasObject(nFreq))
361 throw BadIntegerException("Wrong Root Frequencies Set number", (int)nFreq);
362
364 pSMS.setRootFrequencies(nFreq);
365
366 mFreqToSubPro_[nFreq].push_back(nProc);
367}
368
369
370void SubstitutionProcessCollection::addOnePerBranchSubstitutionProcess(size_t nProc, size_t nMod, size_t nTree, size_t nRate, const vector<string>& sharedParameterNames)
371{
372 if (mSubProcess_.find(nProc) != mSubProcess_.end())
373 throw BadIntegerException("Already assigned substitution process", (int)nProc);
374
375 if (!treeColl_.hasObject(nTree))
376 throw BadIntegerException("Wrong Tree number", (int)nTree);
377 if (!distColl_.hasObject(nRate))
378 throw BadIntegerException("Wrong Rate distribution number", (int)nRate);
379
380 // Build new models and assign to a map
381
382 auto tree = getTree(nTree);
383 const auto model = getModel(nMod);
384
385 vector<uint> ids = tree->getAllEdgesIndexes();
386 sort(ids.begin(), ids.end());
387 vector<size_t> vModN = getModelNumbers();
388
389 size_t maxMod = *max_element(vModN.begin(), vModN.end());
390
391 std::map<size_t, std::vector<unsigned int>> mModBr;
392 mModBr[nMod] = vector<uint>(1, ids[0]);
393
394 for (auto it = ids.begin() + 1; it != ids.end(); it++)
395 {
396 size_t mNb = maxMod + *it;
397 addModel(std::shared_ptr<BranchModelInterface>(model->clone()), mNb);
398 mModBr[mNb] = vector<uint>(1, *it);
399 }
400
401 addSubstitutionProcess(nProc, mModBr, nTree, nRate);
402
404 // Look for aliases in parameters
405
406 ParameterList sharedParameters = model->getIndependentParameters();
407
408 vector<string> sharedParameterNames2; // vector of the complete names of global parameters
409
410 // First get correct parameter names
411 size_t i, j;
412
413 for (i = 0; i < sharedParameterNames.size(); i++)
414 {
415 if (sharedParameterNames[i].find("*") != string::npos)
416 {
417 for (j = 0; j < sharedParameters.size(); j++)
418 {
419 StringTokenizer stj(sharedParameterNames[i], "*", true, false);
420 size_t pos1, pos2;
421 string parn = sharedParameters[j].getName();
422 bool flag(true);
423 string g = stj.nextToken();
424 pos1 = parn.find(g);
425 if (pos1 != 0)
426 flag = false;
427 pos1 += g.length();
428 while (flag && stj.hasMoreToken())
429 {
430 g = stj.nextToken();
431 pos2 = parn.find(g, pos1);
432 if (pos2 == string::npos)
433 {
434 flag = false;
435 break;
436 }
437 pos1 = pos2 + g.length();
438 }
439 if (flag &&
440 ((g.length() == 0) || (pos1 == parn.length()) || (parn.rfind(g) == parn.length() - g.length())))
441 sharedParameterNames2.push_back(parn);
442 }
443 }
444 else if (!sharedParameters.hasParameter(sharedParameterNames[i]))
445 throw Exception("SubstitutionProcessCollection::addOnePerBranchSubstitutionProcess. Parameter '" + sharedParameterNames[i] + "' is not valid.");
446 else
447 sharedParameterNames2.push_back(sharedParameterNames[i]);
448 }
449
450 // Now alias all shared parameters on all nodes:
451
452 string pnum = TextTools::toString(mModBr.begin()->first);
453
454 for (const auto& pname : sharedParameterNames2)
455 {
456 for (auto it = mModBr.begin(); it != mModBr.end(); it++)
457 {
458 if (it != mModBr.begin())
459 aliasParameters(pname + "_" + pnum, pname + "_" + TextTools::toString(it->first));
460 }
461 }
462}
void addParameters_(const ParameterList &parameters)
void unaliasParameters(const std::string &p1, const std::string &p2)
AbstractParameterAliasable & operator=(const AbstractParameterAliasable &ap)
void aliasParameters(const std::string &p1, const std::string &p2)
ParameterList getAliasedParameters(const ParameterList &pl) const
void setNamespace(const std::string &prefix)
ParameterList getFromParameters(const ParameterList &pl) const
ParameterList & getParameters_() override
virtual std::vector< EdgeIndex > getAllEdgesIndexes() const=0
BranchModelInterface * clone() const =0
virtual const ParameterList & getIndependentParameters() const=0
virtual bool hasParameter(const std::string &name) const
virtual void addParameters(const ParameterList &params)
size_t size() const
virtual void addParameter(const Parameter &param)
virtual void includeParameters(const ParameterList &params)
virtual void deleteParameters(const std::vector< std::string > &names, bool mustExist=true)
const std::string & nextToken()
bool hasMoreToken() const
SubstitutionProcessCollectionMember * clone() const override
void setRootFrequencies(size_t numFreq)
Set the root Frequencies Set.
Collection of Substitution Process, which owns all the necessary objects: Substitution models,...
ParametrizableCollection< DiscreteDistributionInterface > distColl_
std::map< size_t, std::shared_ptr< SubstitutionProcessCollectionMember > > mSubProcess_
SubstitutionProcessCollection & operator=(const SubstitutionProcessCollection &set)
ParametrizableCollection< BranchModelInterface > modelColl_
std::map< size_t, std::vector< size_t > > mDistToSubPro_
std::map< size_t, std::vector< size_t > > mModelToSubPro_
ParameterList getNonDerivableParameters() const
Get the Non-derivable parameters.
std::vector< size_t > getModelNumbers() const
Get the numbers of the specified objects from the collections.
void fireParameterChanged(const ParameterList &parameters)
AbstractParameterAliasable functions, redirected towards the process members.
void clear()
Resets all the information contained in this object.
void replaceParametrizable(std::shared_ptr< Parametrizable > parametrizable, size_t parametrizableIndex, bool withParameters=true)
std::shared_ptr< ParametrizablePhyloTree > getTree(size_t treeIndex)
ParametrizableCollection< FrequencySetInterface > freqColl_
void addOnePerBranchSubstitutionProcess(size_t nProc, size_t nMod, size_t nTree, size_t nRate, size_t nFreq, const std::vector< std::string > &sharedParameterNames)
void aliasParameters(const std::string &p1, const std::string &p2)
std::shared_ptr< BranchModelInterface > getModel(size_t modelIndex)
std::map< size_t, std::vector< size_t > > mTreeToSubPro_
void unaliasParameters(const std::string &p1, const std::string &p2)
BranchModelInterface & model(size_t modelIndex)
Get a BranchModel from the collection.
ParametrizableCollection< ParametrizablePhyloTree > treeColl_
void addSubstitutionProcess(size_t nProc, std::map< size_t, std::vector< unsigned int > > mModBr, size_t nTree, size_t nRate, size_t nFreq)
void addModel(std::shared_ptr< BranchModelInterface > model, size_t modelIndex)
specific methods to add specific objects.
void addParametrizable(std::shared_ptr< Parametrizable > parametrizable, size_t parametrizableIndex, bool withParameters=true)
Add a new parametrizable to the matching collection with a given number.
SubstitutionProcessCollectionMember & substitutionProcess(size_t i)
std::shared_ptr< DiscreteDistributionInterface > getRateDistribution(size_t distributionIndex)
Get a DiscreteDistribution from the collection.
std::map< size_t, std::vector< size_t > > mVConstDist_
std::map< size_t, std::vector< size_t > > mFreqToSubPro_
ParametrizablePhyloTree & tree(size_t treeIndex)
Get a tree from the set.
std::string toString(T t)
Defines the basic types of data flow nodes.