bpp-phyl3 3.0.0
NonHomogeneousSequenceSimulator.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#include "../Model/SubstitutionModelSetTools.h"
7#include "../../Tree/PhyloTreeTools.h"
8
12
13// From bpp-seq:
16
17using namespace bpp;
18using namespace std;
19
20/******************************************************************************/
21
22NonHomogeneousSequenceSimulator::NonHomogeneousSequenceSimulator(
23 std::shared_ptr<const SubstitutionModelSet> modelSet,
24 std::shared_ptr<const DiscreteDistributionInterface> rate,
25 std::shared_ptr<const Tree> tree) :
26 modelSet_(modelSet),
27 alphabet_(modelSet_->getAlphabet()),
28 supportedStates_(modelSet_->getAlphabetStates()),
29 rate_(rate),
30 templateTree_(tree),
31 tree_(*tree),
32 phyloTree_(make_shared<const ParametrizablePhyloTree>(*PhyloTreeTools::buildFromTreeTemplate(*tree))),
33 leaves_(tree_.getLeaves()),
34 seqNames_(),
35 nbNodes_(),
36 nbClasses_(rate_->getNumberOfCategories()),
37 nbStates_(modelSet_->getNumberOfStates()),
38 continuousRates_(false),
39 outputInternalSequences_(false)
40{
41 if (!modelSet->isFullySetUpFor(*tree))
42 throw Exception("NonHomogeneousSequenceSimulator(constructor). Model set is not fully specified.");
43 init();
44}
45
46/******************************************************************************/
47
49 std::shared_ptr<const TransitionModelInterface> model,
50 std::shared_ptr<const DiscreteDistributionInterface> rate,
51 std::shared_ptr<const Tree> tree) :
52 modelSet_(0),
53 alphabet_(model->getAlphabet()),
54 supportedStates_(model->getAlphabetStates()),
55 rate_(rate),
56 templateTree_(tree),
57 tree_(*tree),
58 phyloTree_(make_shared<const ParametrizablePhyloTree>(*PhyloTreeTools::buildFromTreeTemplate(*tree))),
59 leaves_(tree_.getLeaves()),
60 seqNames_(),
61 nbNodes_(),
62 nbClasses_(rate_->getNumberOfCategories()),
63 nbStates_(model->getNumberOfStates()),
64 continuousRates_(false),
65 outputInternalSequences_(false)
66{
67 auto fSet = make_shared<FixedFrequencySet>(model->getStateMap(), model->getFrequencies());
68 fSet->setNamespace("anc.");
69 modelSet_ = SubstitutionModelSetTools::createHomogeneousModelSet(shared_ptr<TransitionModelInterface>(model->clone()), fSet, *templateTree_);
70 init();
71}
72
73/******************************************************************************/
74
76{
77 vector<SNode*> nodes = tree_.getNodes();
78
80 {
81 seqNames_.resize(nodes.size());
82 for (size_t i = 0; i < seqNames_.size(); i++)
83 {
84 if (nodes[i]->isLeaf())
85 {
86 seqNames_[i] = nodes[i]->getName();
87 }
88 else
89 {
90 seqNames_[i] = TextTools::toString( nodes[i]->getId() );
91 }
92 }
93 }
94 else
95 {
96 seqNames_.resize(leaves_.size());
97 for (size_t i = 0; i < seqNames_.size(); i++)
98 {
99 seqNames_[i] = leaves_[i]->getName();
100 }
101 }
102 // Initialize cumulative pxy:
103 nodes.pop_back(); // remove root
104 nbNodes_ = nodes.size();
105
106 for (size_t i = 0; i < nodes.size(); i++)
107 {
108 SNode* node = nodes[i];
109 node->getInfos().model = modelSet_->getModelForNode(node->getId());
110 double d = node->getDistanceToFather();
111 VVVdouble* cumpxy_node_ = &node->getInfos().cumpxy;
112 cumpxy_node_->resize(nbClasses_);
113 for (size_t c = 0; c < nbClasses_; c++)
114 {
115 VVdouble* cumpxy_node_c_ = &(*cumpxy_node_)[c];
116 cumpxy_node_c_->resize(nbStates_);
117 RowMatrix<double> P = node->getInfos().model->getPij_t(d * rate_->getCategory(c));
118 for (size_t x = 0; x < nbStates_; x++)
119 {
120 Vdouble* cumpxy_node_c_x_ = &(*cumpxy_node_c_)[x];
121 cumpxy_node_c_x_->resize(nbStates_);
122 (*cumpxy_node_c_x_)[0] = P(x, 0);
123 for (size_t y = 1; y < nbStates_; y++)
124 {
125 (*cumpxy_node_c_x_)[y] = (*cumpxy_node_c_x_)[y - 1] + P(x, y);
126 }
127 }
128 }
129 }
130}
131
132/******************************************************************************/
133
135{
136 // Draw an initial state randomly according to equilibrium frequencies:
137 size_t initialStateIndex = 0;
139 double cumprob = 0;
140 vector<double> freqs = modelSet_->getRootFrequencies();
141 for (size_t i = 0; i < nbStates_; i++)
142 {
143 cumprob += freqs[i];
144 if (r <= cumprob)
145 {
146 initialStateIndex = i;
147 break;
148 }
149 }
150 return simulateSite(initialStateIndex);
151}
152
153/******************************************************************************/
154
155unique_ptr<Site> NonHomogeneousSequenceSimulator::simulateSite(size_t ancestralStateIndex) const
156{
158 {
159 // Draw a random rate:
160 double rate = rate_->randC();
161 // Make this state evolve:
162 return simulateSite(ancestralStateIndex, rate);
163 }
164 else
165 {
166 // Draw a random rate:
167 size_t rateClass = RandomTools::giveIntRandomNumberBetweenZeroAndEntry<size_t>(rate_->getNumberOfCategories());
168 // Make this state evolve:
169 return simulateSite(ancestralStateIndex, rateClass);
170 }
171}
172
173/******************************************************************************/
174
175std::unique_ptr<Site> NonHomogeneousSequenceSimulator::simulateSite(size_t ancestralStateIndex, size_t rateClass) const
176{
177 // Launch recursion:
178 SNode* root = tree_.getRootNode();
179 root->getInfos().state = ancestralStateIndex;
180 for (size_t i = 0; i < root->getNumberOfSons(); ++i)
181 {
182 evolveInternal(root->getSon(i), rateClass);
183 }
184 // Now create a Site object:
185 size_t n = nbNodes_ + 1;
187 {
188 n = leaves_.size();
189 }
190 Vint site(n);
191
193 {
194 vector<SNode*> nodes = tree_.getNodes();
195 for (size_t i = 0; i < n; i++)
196 {
197 if (i == n - 1) // We take the model of node i-1 because the root has no model
198 {
199 site[i] = nodes[i - 1]->getInfos().model->getAlphabetStateAsInt(nodes[i]->getInfos().state);
200 }
201 else
202 {
203 site[i] = nodes[i]->getInfos().model->getAlphabetStateAsInt(nodes[i]->getInfos().state);
204 }
205 }
206 }
207 else
208 {
209 for (size_t i = 0; i < leaves_.size(); ++i)
210 {
211 site[i] = leaves_[i]->getInfos().model->getAlphabetStateAsInt(leaves_[i]->getInfos().state);
212 }
213 }
214 return make_unique<Site>(site, alphabet_);
215}
216
217/******************************************************************************/
218
219std::unique_ptr<Site> NonHomogeneousSequenceSimulator::simulateSite(size_t ancestralStateIndex, double rate) const
220{
221 // Launch recursion:
222 SNode* root = tree_.getRootNode();
223 root->getInfos().state = ancestralStateIndex;
224 for (size_t i = 0; i < root->getNumberOfSons(); i++)
225 {
226 evolveInternal(root->getSon(i), rate);
227 }
228 // Now create a Site object:
229 size_t n = nbNodes_ + 1;
231 {
232 n = leaves_.size();
233 }
234 Vint site(n);
235
237 {
238 vector<SNode*> nodes = tree_.getNodes();
239 for (size_t i = 0; i < n; i++)
240 {
241 if (i == n - 1) // We take the model of node i-1 because the root has no model
242 {
243 site[i] = nodes[i - 1]->getInfos().model->getAlphabetStateAsInt(nodes[i]->getInfos().state);
244 }
245 else
246 {
247 site[i] = nodes[i]->getInfos().model->getAlphabetStateAsInt(nodes[i]->getInfos().state);
248 }
249 }
250 }
251 else
252 {
253 for (size_t i = 0; i < leaves_.size(); i++)
254 {
255 site[i] = leaves_[i]->getInfos().model->getAlphabetStateAsInt(leaves_[i]->getInfos().state);
256 }
257 }
258 return make_unique<Site>(site, alphabet_);
259}
260
261/******************************************************************************/
262
263unique_ptr<Site> NonHomogeneousSequenceSimulator::simulateSite(double rate) const
264{
265 // Draw an initial state randomly according to equilibrium frequencies:
266 size_t ancestralStateIndex = 0;
268 double cumprob = 0;
269 vector<double> freqs = modelSet_->getRootFrequencies();
270 for (size_t i = 0; i < nbStates_; i++)
271 {
272 cumprob += freqs[i];
273 if (r <= cumprob)
274 {
275 ancestralStateIndex = i;
276 break;
277 }
278 }
279 // Make this state evolve:
280 return simulateSite(ancestralStateIndex, rate);
281}
282
283/******************************************************************************/
284
285unique_ptr<SiteContainerInterface> NonHomogeneousSequenceSimulator::simulate(size_t numberOfSites) const
286{
287 vector<size_t> ancestralStateIndices(numberOfSites, 0);
288 for (size_t j = 0; j < numberOfSites; j++)
289 {
291 double cumprob = 0;
292 vector<double> freqs = modelSet_->getRootFrequencies();
293 for (size_t i = 0; i < nbStates_; i++)
294 {
295 cumprob += freqs[i];
296 if (r <= cumprob)
297 {
298 ancestralStateIndices[j] = i;
299 break;
300 }
301 }
302 }
304 {
305 auto sites = make_unique<VectorSiteContainer>(seqNames_.size(), alphabet_);
306 sites->setSequenceNames(seqNames_, true);
307 for (size_t j = 0; j < numberOfSites; j++)
308 {
309 auto site = simulateSite();
310 site->setCoordinate(static_cast<int>(j));
311 sites->addSite(site);
312 }
313 return sites;
314 }
315 else
316 {
317 // More efficient to do site this way:
318 // Draw random rates:
319 vector<size_t> rateClasses(numberOfSites);
320 size_t nCat = rate_->getNumberOfCategories();
321 for (size_t j = 0; j < numberOfSites; j++)
322 {
323 rateClasses[j] = RandomTools::giveIntRandomNumberBetweenZeroAndEntry<size_t>(nCat);
324 }
325 // Make these states evolve:
326 return multipleEvolve(ancestralStateIndices, rateClasses);
327 }
328}
329
330/******************************************************************************/
331
332std::unique_ptr<SiteSimulationResult> NonHomogeneousSequenceSimulator::dSimulateSite() const
333{
334 // Draw an initial state randomly according to equilibrium frequencies:
335 size_t ancestralStateIndex = 0;
337 double cumprob = 0;
338 vector<double> freqs = modelSet_->getRootFrequencies();
339 for (size_t i = 0; i < nbStates_; i++)
340 {
341 cumprob += freqs[i];
342 if (r <= cumprob)
343 {
344 ancestralStateIndex = i;
345 break;
346 }
347 }
348
349 return dSimulateSite(ancestralStateIndex);
350}
351
352/******************************************************************************/
353
354std::unique_ptr<SiteSimulationResult> NonHomogeneousSequenceSimulator::dSimulateSite(size_t ancestralStateIndex) const
355{
356 // Draw a random rate:
358 {
359 double rate = rate_->randC();
360 return dSimulateSite(ancestralStateIndex, rate);
361 }
362 else
363 {
364 size_t rateClass = RandomTools::giveIntRandomNumberBetweenZeroAndEntry<size_t>(rate_->getNumberOfCategories());
365 return dSimulateSite(ancestralStateIndex, rateClass);
366 // NB: this is more efficient than dSimulate(initialState, rDist_->rand())
367 }
368}
369
370/******************************************************************************/
371
372unique_ptr<SiteSimulationResult> NonHomogeneousSequenceSimulator::dSimulateSite(size_t ancestralStateIndex, double rate) const
373{
374 // Make this state evolve:
375 auto hssr = make_unique<RASiteSimulationResult>(phyloTree_, modelSet_->getStateMap(), ancestralStateIndex, rate);
376 dEvolve(ancestralStateIndex, rate, *hssr);
377 return std::move(hssr);
378}
379
380/******************************************************************************/
381
382unique_ptr<SiteSimulationResult> NonHomogeneousSequenceSimulator::dSimulateSite(size_t ancestralStateIndex, size_t rateClass) const
383{
384 return dSimulateSite(ancestralStateIndex, rate_->getCategory(rateClass));
385}
386
387/******************************************************************************/
388
389unique_ptr<SiteSimulationResult> NonHomogeneousSequenceSimulator::dSimulateSite(double rate) const
390{
391 // Draw an initial state randomly according to equilibrium frequencies:
392 size_t ancestralStateIndex = 0;
394 double cumprob = 0;
395 vector<double> freqs = modelSet_->getRootFrequencies();
396 for (size_t i = 0; i < nbStates_; i++)
397 {
398 cumprob += freqs[i];
399 if (r <= cumprob)
400 {
401 ancestralStateIndex = i;
402 break;
403 }
404 }
405 return dSimulateSite(ancestralStateIndex, rate);
406}
407
408/******************************************************************************/
409
410size_t NonHomogeneousSequenceSimulator::evolve(const SNode* node, size_t initialStateIndex, size_t rateClass) const
411{
412 const Vdouble* cumpxy_node_c_x_ = &node->getInfos().cumpxy[rateClass][initialStateIndex];
414 for (size_t y = 0; y < nbStates_; y++)
415 {
416 if (rand < (*cumpxy_node_c_x_)[y])
417 return y;
418 }
419 throw Exception("HomogeneousSequenceSimulator::evolve. The impossible happened! rand = " + TextTools::toString(rand) + ".");
420}
421
422/******************************************************************************/
423
424size_t NonHomogeneousSequenceSimulator::evolve(const SNode* node, size_t initialStateIndex, double rate) const
425{
426 double cumpxy = 0;
428 double l = rate * node->getDistanceToFather();
429 auto model = node->getInfos().model;
430 for (size_t y = 0; y < nbStates_; y++)
431 {
432 cumpxy += model->Pij_t(initialStateIndex, y, l);
433 if (rand < cumpxy)
434 return y;
435 }
436 MatrixTools::print(model->getPij_t(l));
437 throw Exception("HomogeneousSequenceSimulator::evolve. The impossible happened! rand = " + TextTools::toString(rand) + ".");
438}
439
440/******************************************************************************/
441
443 const SNode* node,
444 const std::vector<size_t>& initialStateIndices,
445 const vector<size_t>& rateClasses,
446 std::vector<size_t>& finalStateIndices) const
447{
448 const VVVdouble* cumpxy_node_ = &node->getInfos().cumpxy;
449 for (size_t i = 0; i < initialStateIndices.size(); i++)
450 {
451 const Vdouble* cumpxy_node_c_x_ = &(*cumpxy_node_)[rateClasses[i]][initialStateIndices[i]];
453 for (size_t y = 0; y < nbStates_; y++)
454 {
455 if (rand < (*cumpxy_node_c_x_)[y])
456 {
457 finalStateIndices[i] = y;
458 break;
459 }
460 }
461 }
462}
463
464/******************************************************************************/
465
467{
468 if (!node->hasFather())
469 {
470 cerr << "DEBUG: NonHomogeneousSequenceSimulator::evolveInternal. Forbidden call of method on root node." << endl;
471 return;
472 }
473 node->getInfos().state = evolve(node, node->getFather()->getInfos().state, rateClass);
474 for (size_t i = 0; i < node->getNumberOfSons(); i++)
475 {
476 evolveInternal(node->getSon(i), rateClass);
477 }
478}
479
480/******************************************************************************/
481
483{
484 if (!node->hasFather())
485 {
486 cerr << "DEBUG: NonHomogeneousSequenceSimulator::evolveInternal. Forbidden call of method on root node." << endl;
487 return;
488 }
489 node->getInfos().state = evolve(node, node->getFather()->getInfos().state, rate);
490 for (size_t i = 0; i < node->getNumberOfSons(); i++)
491 {
492 evolveInternal(node->getSon(i), rate);
493 }
494}
495
496/******************************************************************************/
497
498void NonHomogeneousSequenceSimulator::multipleEvolveInternal(SNode* node, const vector<size_t>& rateClasses) const
499{
500 if (!node->hasFather())
501 {
502 cerr << "DEBUG: NonHomogeneousSequenceSimulator::multipleEvolveInternal. Forbidden call of method on root node." << endl;
503 return;
504 }
505 const vector<size_t>* initialStates = &node->getFather()->getInfos().states;
506 size_t n = initialStates->size();
507 node->getInfos().states.resize(n); // allocation.
508 multipleEvolve(node, node->getFather()->getInfos().states, rateClasses, node->getInfos().states);
509 for (size_t i = 0; i < node->getNumberOfSons(); i++)
510 {
511 multipleEvolveInternal(node->getSon(i), rateClasses);
512 }
513}
514
515/******************************************************************************/
516
517unique_ptr<SiteContainerInterface> NonHomogeneousSequenceSimulator::multipleEvolve(
518 const std::vector<size_t>& initialStateIndices,
519 const vector<size_t>& rateClasses) const
520{
521 // Launch recursion:
522 SNode* root = tree_.getRootNode();
523 root->getInfos().states = initialStateIndices;
524 for (size_t i = 0; i < root->getNumberOfSons(); i++)
525 {
526 multipleEvolveInternal(root->getSon(i), rateClasses);
527 }
528 // Now create a SiteContainer object:
529 auto sites = make_unique<AlignedSequenceContainer>(alphabet_);
530 size_t nbSites = initialStateIndices.size();
531 shared_ptr<const TransitionModelInterface> model = nullptr;
533 {
534 vector<SNode*> nodes = tree_.getNodes();
535 size_t n = nbNodes_ + 1;
536 for (size_t i = 0; i < n; i++)
537 {
538 vector<int> content(nbSites);
539 vector<size_t>& states = nodes[i]->getInfos().states;
540 if (i == n - 1) // If at the root, there is no model, so we take the model of node n-1.
541 {
542 model = nodes[i - 1]->getInfos().model;
543 }
544 else
545 {
546 model = nodes[i]->getInfos().model;
547 }
548 for (size_t j = 0; j < nbSites; j++)
549 {
550 content[j] = model->getAlphabetStateAsInt(states[j]);
551 }
552 if (nodes[i]->isLeaf())
553 {
554 auto seq = make_unique<Sequence>(nodes[i]->getName(), content, alphabet_);
555 sites->addSequence(nodes[i]->getName(), seq);
556 }
557 else
558 {
559 auto seq = make_unique<Sequence>(TextTools::toString(nodes[i]->getId()), content, alphabet_);
560 sites->addSequence(TextTools::toString(nodes[i]->getId()), seq);
561 }
562 }
563 }
564 else
565 {
566 size_t n = leaves_.size();
567 for (size_t i = 0; i < n; i++)
568 {
569 vector<int> content(nbSites);
570 vector<size_t>& states = leaves_[i]->getInfos().states;
571 model = leaves_[i]->getInfos().model;
572 for (size_t j = 0; j < nbSites; j++)
573 {
574 content[j] = model->getAlphabetStateAsInt(states[j]);
575 }
576 auto seq = make_unique<Sequence>(leaves_[i]->getName(), content, alphabet_);
577 sites->addSequence(leaves_[i]->getName(), seq);
578 }
579 }
580 return std::move(sites);
581}
582
583/******************************************************************************/
584
585void NonHomogeneousSequenceSimulator::dEvolve(size_t initialState, double rate, RASiteSimulationResult& rassr) const
586{
587 // Launch recursion:
588 SNode* root = tree_.getRootNode();
589 root->getInfos().state = initialState;
590 for (size_t i = 0; i < root->getNumberOfSons(); i++)
591 {
592 dEvolveInternal(root->getSon(i), rate, rassr);
593 }
594}
595
596/******************************************************************************/
597
599{
600 if (!node->hasFather())
601 {
602 cerr << "DEBUG: NonHomogeneousSequenceSimulator::evolveInternal. Forbidden call of method on root node." << endl;
603 return;
604 }
605 auto tm = node->getInfos().model;
606 if (!dynamic_pointer_cast<const SubstitutionModelInterface>(tm))
607 throw Exception("NonHomogeneousSequenceSimulator::dEvolveInternal : detailed simulation not possible for non-markovian model");
608
609 SimpleMutationProcess process(dynamic_pointer_cast<const SubstitutionModelInterface>(tm));
610
611 MutationPath mp = process.detailedEvolve(node->getFather()->getInfos().state, node->getDistanceToFather() * rate);
612 node->getInfos().state = mp.getFinalState();
613
614 // Now append infos in rassr:
615 rassr.addNode(static_cast<unsigned int>(node->getId()), mp);
616
617 // Now jump to son nodes:
618 for (size_t i = 0; i < node->getNumberOfSons(); i++)
619 {
620 dEvolveInternal(node->getSon(i), rate, rassr);
621 }
622}
623
624/******************************************************************************/
625
627{
630 {
631 vector<SNode*> nodes = tree_.getNodes();
632 seqNames_.resize(nodes.size());
633 for (size_t i = 0; i < seqNames_.size(); i++)
634 {
635 if (nodes[i]->isLeaf())
636 {
637 seqNames_[i] = nodes[i]->getName();
638 }
639 else
640 {
641 seqNames_[i] = TextTools::toString( nodes[i]->getId() );
642 }
643 }
644 }
645 else
646 {
647 seqNames_.resize(leaves_.size());
648 for (size_t i = 0; i < seqNames_.size(); i++)
649 {
650 seqNames_[i] = leaves_[i]->getName();
651 }
652 }
653}
654
655/******************************************************************************/
MutationPath detailedEvolve(size_t initialState, double time) const
Simulation a character evolution during a specified time according to the given substitution model an...
static void print(const Matrix &m, std::ostream &out=std::cout)
This class is used by MutationProcess to store detailed results of simulations.
size_t getFinalState() const
Retrieve the final state of this path.
The NodeTemplate class.
Definition: NodeTemplate.h:39
const NodeTemplate< NodeInfos > * getFather() const
Get the father of this node is there is one.
Definition: NodeTemplate.h:102
virtual const NodeInfos & getInfos() const
Definition: NodeTemplate.h:144
const NodeTemplate< NodeInfos > * getSon(size_t i) const
Definition: NodeTemplate.h:108
virtual int getId() const
Get the node's id.
Definition: Node.h:170
virtual bool hasFather() const
Tell if this node has a father node.
Definition: Node.h:346
virtual double getDistanceToFather() const
Get the distance to the father node is there is one, otherwise throw a NodeException.
Definition: Node.h:250
virtual size_t getNumberOfSons() const
Definition: Node.h:355
const Tree & tree() const
Get the tree associated to this instance.
std::shared_ptr< const SubstitutionModelSet > modelSet_
std::unique_ptr< SiteContainerInterface > simulate(size_t numberOfSites) const override
std::shared_ptr< const DiscreteDistributionInterface > rate_
void multipleEvolve(const SNode *node, const std::vector< size_t > &initialStateIndices, const std::vector< size_t > &rateClasses, std::vector< size_t > &finalStates) const
The same as the evolve(initialState, rateClass) function, but for several sites at a time.
std::unique_ptr< Site > simulateSite() const override
void outputInternalSequences(bool yn) override
Sets whether we will output the internal sequences or not.
void multipleEvolveInternal(SNode *node, const std::vector< size_t > &rateClasses) const
std::vector< SNode * > leaves_
This stores once for all all leaves in a given order. This order will be used during site creation.
void dEvolve(size_t initialState, double rate, RASiteSimulationResult &rassr) const
void dEvolveInternal(SNode *node, double rate, RASiteSimulationResult &rassr) const
NonHomogeneousSequenceSimulator(std::shared_ptr< const SubstitutionModelSet > modelSet, std::shared_ptr< const DiscreteDistributionInterface > rate, std::shared_ptr< const Tree > tree)
size_t evolve(const SNode *node, size_t initialStateIndex, size_t rateClass) const
Evolve from an initial state along a branch, knowing the evolutionary rate class.
std::unique_ptr< SiteSimulationResult > dSimulateSite() const override
Get a detailed simulation result for one site.
std::shared_ptr< const ParametrizablePhyloTree > phyloTree_
void evolveInternal(SNode *node, size_t rateClass) const
PhyloTree with Parametrizable Phylo Branches. They SHARE their branch length parameters.
Generic utilitary methods dealing with trees.
Data structure to store the result of a DetailedSiteSimulator.
static double giveRandomNumberBetweenZeroAndEntry(double entry)
Generally used mutation process model.
virtual void addNode(unsigned int nodeId, MutationPath path)
static std::unique_ptr< SubstitutionModelSet > createHomogeneousModelSet(std::shared_ptr< TransitionModelInterface > model, std::shared_ptr< FrequencySetInterface > rootFreqs, const Tree &tree)
Create a SubstitutionModelSet object, corresponding to the homogeneous case.
std::string toString(T t)
Defines the basic types of data flow nodes.
std::vector< double > Vdouble
std::vector< int > Vint
std::vector< VVdouble > VVVdouble
std::vector< Vdouble > VVdouble