2
// File: TreeTemplate.h
3
// Created by: Julien Dutheil
5
// Created on: Thu Mar 13 12:03:18 2003
9
Copyright or Ā© or Copr. CNRS, (November 16, 2004)
11
This software is a computer program whose purpose is to provide classes
12
for phylogenetic data analysis.
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".
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
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.
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.
41
#ifndef _TREETEMPLATE_H_
42
#define _TREETEMPLATE_H_
44
#include "TreeExceptions.h"
45
#include "TreeTemplateTools.h"
57
* @brief The phylogenetic tree class.
59
* This class is part of the object implementation of phylogenetic trees. Tree are made
60
* made of nodes, instances of the class Node.
62
* Trees are oriented (rooted), i.e. each node has one <i>father node</i> and possibly
63
* many <i>son nodes</i>. Leaves are nodes without descendant and root is defined has the without
64
* father. Inner nodes will generally contain two descendants (the tree is then called
65
* <i>bifurcating</i>), but mutlifurcating trees are also allowed with this kind of description.
66
* In the rooted case, each inner node also defines a <i>subtree</i>.
67
* This allows to work recursively on trees, which is very convenient in most cases.
68
* To deal with non-rooted trees, we place an artificial root at a particular node:
69
* hence the root node appears to be trifurcated. This is the way unrooted trees are
70
* described in the parenthetic description, the so called Newick format.
72
* To clone a tree from from another tree with a different template,
73
* consider using the TreeTools::cloneSutree<N>() method:
75
* Tree * t = new Tree<Node>(...)
76
* NodeTemplate<int> * newRoot = TreeTools::cloneSubtree< NodeTemplate<int> >(* (t -> getRootNode()))
77
* Tree< NodeTemplate<int> > * tt = new Tree< NodeTemplate<int> >(* newRoot);
80
* The getNextId() method sends a id value which is not used in the tree.
81
* In the current implementation, it uses the TreeTools::getMPNUId() method.
82
* This avoids to use duplicated ids, but is time consuming.
83
* In most cases, it is of better efficiency if the user deal with the ids himself, by using the Node::setId() method.
84
* The TreeTools::getMaxId() method may also prove useful in this respect.
85
* The resetNodesId() method can also be used to re-initialize all ids.
102
public: // Constructors and destructor:
104
TreeTemplate(): root_(0), name_() {}
106
TreeTemplate(const TreeTemplate<N>& t):
107
root_(0), name_(t.name_)
109
//Perform a hard copy of the nodes:
110
root_ = TreeTemplateTools::cloneSubtree<N>(*t.getRootNode());
113
TreeTemplate(const Tree& t):
114
root_(0), name_(t.getName())
116
//Create new nodes from an existing tree:
117
root_ = TreeTemplateTools::cloneSubtree<N>(t, t.getRootId());
120
TreeTemplate(N* root): root_(root), name_()
122
root_->removeFather(); //In case this is a subtree from somewhere else...
125
TreeTemplate<N> & operator=(const TreeTemplate<N>& t)
127
//Perform a hard copy of the nodes:
128
if(root_) { destroySubtree_(root_); delete root_; }
129
root_ = TreeTemplateTools::cloneSubtree<N>(* t.getRootNode());
134
TreeTemplate<N>* cloneSubtree(int newRootId) const
136
N* newRoot = TreeTemplateTools::cloneSubtree<N>(*this, newRootId);
137
return new TreeTemplate<N> (newRoot);
140
virtual ~TreeTemplate()
142
destroySubtree_(root_);
146
TreeTemplate<N>* clone() const { return new TreeTemplate<N>(*this); }
154
std::string getName() const { return name_; }
156
void setName(const std::string& name) { name_ = name; }
158
int getRootId() const { return root_->getId(); }
160
unsigned int getNumberOfLeaves() const { return TreeTemplateTools::getNumberOfLeaves(*root_); }
162
unsigned int getNumberOfNodes() const { return TreeTemplateTools::getNumberOfNodes(*root_); }
164
int getLeafId(const std::string& name) const throw (NodeNotFoundException) { return TreeTemplateTools::getLeafId(*root_, name); }
166
std::vector<int> getLeavesId() const { return TreeTemplateTools::getLeavesId(*root_); }
168
std::vector<int> getNodesId() const { return TreeTemplateTools::getNodesId(*root_); }
170
std::vector<int> getInnerNodesId() const { return TreeTemplateTools::getInnerNodesId(*root_); }
172
std::vector<int> getBranchesId() const { return TreeTemplateTools::getBranchesId(*root_); }
174
std::vector<double> getBranchLengths() const { return TreeTemplateTools::getBranchLengths(*root_); }
176
std::vector<std::string> getLeavesNames() const { return TreeTemplateTools::getLeavesNames(*const_cast<const N*>( root_)); }
178
std::vector<int> getSonsId(int parentId) const throw (NodeNotFoundException) { return getNode(parentId)->getSonsId(); }
180
std::vector<int> getAncestorsId(int nodeId) const throw (NodeNotFoundException) { return TreeTemplateTools::getAncestorsId(*getNode(nodeId));}
182
int getFatherId(int parentId) const throw (NodeNotFoundException) { return getNode(parentId)->getFatherId(); }
184
bool hasFather(int nodeId) const throw (NodeNotFoundException) { return getNode(nodeId)->hasFather(); }
186
std::string getNodeName(int nodeId) const throw (NodeNotFoundException) { return getNode(nodeId)->getName(); }
188
bool hasNodeName(int nodeId) const throw (NodeNotFoundException) { return getNode(nodeId)->hasName(); }
190
void setNodeName(int nodeId, const std::string& name) throw (NodeNotFoundException) { getNode(nodeId)->setName(name); }
192
void deleteNodeName(int nodeId) throw (NodeNotFoundException) { return getNode(nodeId)->deleteName(); }
194
bool hasNode(int nodeId) const { return TreeTemplateTools::hasNodeWithId(*root_, nodeId); }
196
bool isLeaf(int nodeId) const throw (NodeNotFoundException) { return getNode(nodeId)->isLeaf(); }
198
bool isRoot(int nodeId) const throw (NodeNotFoundException) { return TreeTemplateTools::isRoot(*getNode(nodeId)); }
200
double getDistanceToFather(int nodeId) const { return getNode(nodeId)->getDistanceToFather(); }
202
void setDistanceToFather(int nodeId, double length) { getNode(nodeId)->setDistanceToFather(length); }
204
void deleteDistanceToFather(int nodeId) { getNode(nodeId)->deleteDistanceToFather(); }
206
bool hasDistanceToFather(int nodeId) const { return getNode(nodeId)->hasDistanceToFather(); }
208
bool hasNodeProperty(int nodeId, const std::string& name) const throw (NodeNotFoundException) { return getNode(nodeId)->hasNodeProperty(name); }
210
void setNodeProperty(int nodeId, const std::string& name, const Clonable & property) throw (NodeNotFoundException) { getNode(nodeId)->setNodeProperty(name, property); }
212
Clonable* getNodeProperty(int nodeId, const std::string& name) throw (NodeNotFoundException) { return getNode(nodeId)->getNodeProperty(name); }
214
const Clonable* getNodeProperty(int nodeId, const std::string& name) const throw (NodeNotFoundException) { return getNode(nodeId)->getNodeProperty(name); }
216
Clonable* removeNodeProperty(int nodeId, const std::string& name) throw (NodeNotFoundException) { return getNode(nodeId)->removeNodeProperty(name); }
218
std::vector<std::string> getNodePropertyNames(int nodeId) const throw (NodeNotFoundException) { return getNode(nodeId)->getNodePropertyNames(); }
220
bool hasBranchProperty(int nodeId, const std::string& name) const throw (NodeNotFoundException) { return getNode(nodeId)->hasBranchProperty(name); }
222
void setBranchProperty(int nodeId, const std::string& name, const Clonable & property) throw (NodeNotFoundException) { getNode(nodeId)->setBranchProperty(name, property); }
224
Clonable* getBranchProperty(int nodeId, const std::string& name) throw (NodeNotFoundException) { return getNode(nodeId)->getBranchProperty(name); }
226
const Clonable* getBranchProperty(int nodeId, const std::string& name) const throw (NodeNotFoundException) { return getNode(nodeId)->getBranchProperty(name); }
228
Clonable* removeBranchProperty(int nodeId, const std::string& name) throw (NodeNotFoundException) { return getNode(nodeId)->removeBranchProperty(name); }
230
std::vector<std::string> getBranchPropertyNames(int nodeId) const throw (NodeNotFoundException) { return getNode(nodeId)->getBranchPropertyNames(); }
232
void rootAt(int nodeId) throw (NodeNotFoundException) { rootAt(getNode(nodeId)); }
234
void newOutGroup(int nodeId) throw (NodeNotFoundException) { newOutGroup(getNode(nodeId)); }
236
bool isRooted() const { return root_->getNumberOfSons() == 2; }
238
bool unroot() throw (UnrootedTreeException)
240
if(!isRooted()) throw UnrootedTreeException("Tree::unroot", this);
242
if(root_->getNumberOfSons() == 2)
244
N* son1 = root_->getSon(0);
245
N* son2 = root_->getSon(1);
246
if(son1->isLeaf() && son2->isLeaf()) return false; // We can't unroot a single branch!
248
// We manage to have a subtree in position 0:
252
son1 = root_->getSon(0);
253
son2 = root_->getSon(1);
256
// Take care of branch lengths:
257
if(son1->hasDistanceToFather())
259
if(son2->hasDistanceToFather())
261
// Both nodes have lengths, we sum them:
262
son2->setDistanceToFather(son1->getDistanceToFather() + son2->getDistanceToFather());
266
// Only node 1 has length, we set it to node 2:
267
son2->setDistanceToFather(son1->getDistanceToFather());
269
son1->deleteDistanceToFather();
270
} // Else node 2 may or may not have a branch length, we do not care!
279
else return false; // Tree is already unrooted.
284
std::vector<N *> nodes = getNodes();
285
for (unsigned int i = 0; i < nodes.size(); i++)
291
bool isMultifurcating() const
294
for(unsigned int i = 0; i < root_ -> getNumberOfSons(); i++)
296
b = b || TreeTemplateTools::isMultifurcating(* root_->getSon(i));
302
* @brief Tells if this tree has the same topology as the one given for comparison.
304
* This method compares recursively all subtrees. The comparison is performed only on the nodes names and the parental relationships.
305
* Nodes ids are ignored, and so are branch lengths and any branch/node properties. The default is to ignore the ordering of the descendants,
306
* that is (A,B),C) will be considered as having the same topology as (B,A),C). Multifurcations are permited.
307
* If ordering is ignored, a copy of the two trees to be compared is performed and are ordered before comparison, making the whole comparison
308
* slower and more memory greedy.
310
* @param tree The tree to be compared with.
311
* @param ordered Should the ordering of the branching be taken into account?
312
* @return True if the input tree has the same topology as this one.
315
bool hasSameTopologyAs(const TreeTemplate<N2>& tree, bool ordered = false) const
317
const TreeTemplate<N>* t1 = 0;
318
const TreeTemplate<N2>* t2 = 0;
323
TreeTemplate<N>* t1tmp = this->clone();
324
TreeTemplate<N2>* t2tmp = tree.clone();
325
TreeTemplateTools::orderTree(*t1tmp->getRootNode(), true, true);
326
TreeTemplateTools::orderTree(*t2tmp->getRootNode(), true, true);
330
bool test = TreeTemplateTools::haveSameOrderedTopology(*t1->getRootNode(), *t2->getRootNode());
338
std::vector<double> getBranchLengths() throw (NodeException)
341
for(unsigned int i = 0; i < root_->getNumberOfSons(); i++)
343
Vdouble sonBrLen = TreeTemplateTools::getBranchLengths(* root_->getSon(i));
344
for(unsigned int j = 0; j < sonBrLen.size(); j++) brLen.push_back(sonBrLen[j]);
349
double getTotalLength() throw (NodeException)
351
return TreeTemplateTools::getTotalLength(*root_, false);
354
void setBranchLengths(double brLen)
356
for(unsigned int i = 0; i < root_->getNumberOfSons(); i++)
358
TreeTemplateTools::setBranchLengths(*root_->getSon(i), brLen);
362
void setVoidBranchLengths(double brLen)
364
for(unsigned int i = 0; i < root_->getNumberOfSons(); i++)
366
TreeTemplateTools::setVoidBranchLengths(*root_->getSon(i), brLen);
370
void scaleTree(double factor) throw (NodeException)
372
for(unsigned int i = 0; i < root_->getNumberOfSons(); i++)
374
TreeTemplateTools::scaleTree(*root_->getSon(i), factor);
380
return TreeTools::getMPNUId(*this, root_->getId());
383
void swapNodes(int parentId, unsigned int i1, unsigned int i2) throw (NodeNotFoundException,IndexOutOfBoundsException)
385
std::vector<N*> nodes = TreeTemplateTools::searchNodeWithId<N>(*root_, parentId);
386
if(nodes.size() == 0) throw NodeNotFoundException("TreeTemplate:swapNodes(): Node with id not found.", "" + parentId);
387
for(unsigned int i = 0; i < nodes.size(); i++) nodes[i]->swap(i1, i2);
392
* @name Specific methods
396
virtual void setRootNode(N* root) { root_ = root; }
398
virtual N* getRootNode() { return root_; }
400
virtual const N* getRootNode() const { return root_; }
402
virtual std::vector<const N*> getLeaves() const { return TreeTemplateTools::getLeaves(* const_cast<const N *>(root_)); }
404
virtual std::vector<N*> getLeaves() { return TreeTemplateTools::getLeaves(* root_); }
406
virtual std::vector<const N*> getNodes() const { return TreeTemplateTools::getNodes(* const_cast<const N *>(root_)); }
408
virtual std::vector<N*> getNodes() { return TreeTemplateTools::getNodes(* root_); }
410
virtual std::vector<const N*> getInnerNodes() const { return TreeTemplateTools::getInnerNodes(* const_cast<const N *>(root_)); }
412
virtual std::vector<N *> getInnerNodes() { return TreeTemplateTools::getInnerNodes(* root_); }
414
virtual N* getNode(int id) throw (NodeNotFoundException, Exception)
416
std::vector<N*> nodes;
417
TreeTemplateTools::searchNodeWithId<N>(*root_, id, nodes);
418
if (nodes.size() > 1) throw Exception("TreeTemplate::getNode(): Non-unique id! (" + TextTools::toString(id) + ").");
419
if (nodes.size() == 0) throw NodeNotFoundException("TreeTemplate::getNode(): Node with id not found.", TextTools::toString(id));
423
virtual const N* getNode(int id) const throw (NodeNotFoundException, Exception)
425
std::vector<const N*> nodes;
426
TreeTemplateTools::searchNodeWithId<const N>(*root_, id, nodes);
427
if (nodes.size() > 1) throw Exception("TreeTemplate::getNode(): Non-unique id! (" + TextTools::toString(id) + ").");
428
if (nodes.size() == 0) throw NodeNotFoundException("TreeTemplate::getNode(): Node with id not found.", TextTools::toString(id));
432
virtual N* getNode(const std::string& name) throw (NodeNotFoundException, Exception)
434
std::vector<N*> nodes;
435
TreeTemplateTools::searchNodeWithName(*root_, name, nodes);
436
if (nodes.size() > 1) throw NodeNotFoundException("TreeTemplate::getNode(): Non-unique name.", "" + name);
437
if (nodes.size() == 0) throw NodeNotFoundException("TreeTemplate::getNode(): Node with name not found.", "" + name);
441
virtual const N* getNode(const std::string& name) const throw (NodeNotFoundException, Exception)
443
std::vector<const N*> nodes;
444
TreeTemplateTools::searchNodeWithName<const N>(*root_, name, nodes);
445
if(nodes.size() > 1) throw NodeNotFoundException("TreeTemplate::getNode(): Non-unique name.", "" + name);
446
if(nodes.size() == 0) throw NodeNotFoundException("TreeTemplate::getNode(): Node with name not found.", "" + name);
450
void rootAt(N* newRoot)
452
if (root_ == newRoot) return;
453
if (isRooted()) unroot();
454
std::vector<Node*> path = TreeTemplateTools::getPathBetweenAnyTwoNodes(*root_, *newRoot);
456
for (unsigned int i = 0; i < path.size() - 1 ; i++)
458
//pathMatrix[i] -> _father = pathMatrix[i + 1];
459
//pathMatrix[i] -> setDistanceToFather(pathMatrix[i + 1] -> getDistanceToFather());
460
//typename vector<Node *>::iterator vec_iter;
461
//vec_iter = remove(pathMatrix[i] -> _sons.begin(), pathMatrix[i] -> _sons.end(), pathMatrix[i + 1]);
462
//pathMatrix[i] -> _sons.erase(vec_iter, pathMatrix[i] -> _sons.end()); // pg 1170, primer.
463
//pathMatrix[i+1] -> _sons.push_back(pathMatrix[i + 1] -> getFather());
464
//pathMatrix[i+1] -> _father = 0;
465
path[i]->removeSon(path[i+1]);
466
if(path[i+1]->hasDistanceToFather()) path[i]->setDistanceToFather(path[i+1]->getDistanceToFather());
467
else path[i]->deleteDistanceToFather();
468
path[i+1]->addSon(path[i]);
470
std::vector<std::string> names = path[i+1]->getBranchPropertyNames();
471
for(unsigned int j = 0; j < names.size(); j++)
473
path[i]->setBranchProperty(names[j], *path[i+1]->getBranchProperty(names[j]));
475
path[i+1]->deleteBranchProperties();
477
newRoot->deleteDistanceToFather();
478
newRoot->deleteBranchProperties();
482
void newOutGroup(N* outGroup)
484
if(root_ == outGroup) return;
488
for(unsigned int i = 0; i < root_->getNumberOfSons(); i++)
490
if(root_->getSon(i) == outGroup) return; //This tree is already rooted appropriately.
492
rootId = getRootId();
497
rootId = getNextId();
499
rootAt(outGroup->getFather());
501
oldRoot->removeSon(outGroup);
503
root_->setId(rootId);
504
root_->addSon(oldRoot);
505
root_->addSon(outGroup);
507
if(outGroup->hasDistanceToFather())
509
double l = outGroup->getDistanceToFather() / 2.;
510
outGroup->setDistanceToFather(l);
511
oldRoot->setDistanceToFather(l);
519
virtual void destroySubtree_(N* node)
521
for(unsigned int i = 0; i < node->getNumberOfSons(); i++)
523
N* son = node->getSon(i);
524
destroySubtree_(son);
531
} //end of namespace bpp.
533
#endif //_TREETEMPLATE_H_