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 
12 using namespace bpp;
13 using namespace std;
14 
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 
40  modelColl_ = set.modelColl_;
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 
75 void 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 
80  ParameterList pl;
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 
109 void 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 
263 void 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 
276 void SubstitutionProcessCollection::unaliasParameters(const std::string& p1, const std::string& p2)
277 {
279  for (auto& it : mSubProcess_)
280  {
281  it.second->updateParameters();
282  }
283 }
284 
285 void 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 
301 void 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 
314 void 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 
356 void 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 
370 void 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
void setRootFrequencies(size_t numFreq)
Set the root Frequencies Set.
SubstitutionProcessCollectionMember * clone() const override
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::vector< size_t > getModelNumbers() const
Get the numbers of the specified objects from the collections.
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.
void fireParameterChanged(const ParameterList &parameters)
AbstractParameterAliasable functions, redirected towards the process members.
BranchModelInterface & model(size_t modelIndex)
Get a BranchModel from the collection.
void clear()
Resets all the information contained in this object.
SubstitutionProcessCollectionMember & substitutionProcess(size_t i)
std::shared_ptr< DiscreteDistributionInterface > getRateDistribution(size_t distributionIndex)
Get a DiscreteDistribution from the collection.
void replaceParametrizable(std::shared_ptr< Parametrizable > parametrizable, size_t parametrizableIndex, bool withParameters=true)
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::map< size_t, std::vector< size_t > > mTreeToSubPro_
void unaliasParameters(const std::string &p1, const std::string &p2)
std::shared_ptr< BranchModelInterface > getModel(size_t modelIndex)
SubstitutionProcessCollection()
Create empty collections.
ParametrizableCollection< ParametrizablePhyloTree > treeColl_
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.
void addSubstitutionProcess(size_t nProc, std::map< size_t, std::vector< unsigned int >> mModBr, size_t nTree, size_t nRate, size_t nFreq)
std::map< size_t, std::vector< size_t > > mVConstDist_
std::shared_ptr< ParametrizablePhyloTree > getTree(size_t treeIndex)
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.