23 deleteWithNodes =
false;
42 #if defined(PROVIDE_TREE_STRUCTURE_TESTS)
44 Validity TreeNode::is_valid()
const {
55 if (valid) valid = get_rightson()->is_valid();
56 if (valid) valid = get_leftson()->is_valid();
60 if (valid) valid =
Validity(troot->get_root_node()->is_ancestor_of(
this),
"root is not nodes ancestor");
64 if (valid) valid =
Validity(troot->get_root_node() ==
this,
"node has no father, but isn't root-node");
74 if (
rightson) valid = get_rightson()->is_valid();
75 if (
leftson && valid) valid = get_leftson()->is_valid();
84 #endif // PROVIDE_TREE_STRUCTURE_TESTS
87 if (tree_root != new_root) {
89 if (
leftson) get_leftson()->set_tree_root(new_root);
90 if (
rightson) get_rightson()->set_tree_root(new_root);
94 void TreeNode::reorder_subtree(
TreeOrder mode) {
95 static const char *smallest_leafname;
98 smallest_leafname =
name;
101 int leftsize = get_leftson() ->get_leaf_count();
102 int rightsize = get_rightson()->get_leaf_count();
105 bool big_at_top = leftsize>rightsize;
106 bool big_at_bottom = leftsize<rightsize;
107 bool swap_branches = (mode&
ORDER_BIG_DOWN) ? big_at_top : big_at_bottom;
131 get_leftson()->reorder_subtree(lmode);
132 const char *leftleafname = smallest_leafname;
134 get_rightson()->reorder_subtree(rmode);
135 const char *rightleafname = smallest_leafname;
137 if (leftleafname && rightleafname) {
138 int name_cmp = strcmp(leftleafname, rightleafname);
140 smallest_leafname = leftleafname;
143 smallest_leafname = rightleafname;
144 if (leftsize == rightsize) {
145 const char *smallest_leafname_save = smallest_leafname;
148 get_leftson ()->reorder_subtree(lmode);
rt_assert(strcmp(smallest_leafname, rightleafname)== 0);
149 get_rightson()->reorder_subtree(rmode);
rt_assert(strcmp(smallest_leafname, leftleafname) == 0);
151 smallest_leafname = smallest_leafname_save;
163 reorder_subtree(mode);
169 get_leftson()->rotate_subtree();
170 get_rightson()->rotate_subtree();
186 if (inverseLeft) keeledOver =
false;
198 if (!inverseLeft) keeledOver =
false;
218 TreeNode *old_brother =
is_inside(old_root->get_leftson()) ? old_root->get_rightson() : old_root->get_leftson();
225 SmartCharPtr remarkPtr;
255 pntr->keelOver(prev, next, len);
259 next = next->get_father();
267 pntr->keelOver(prev, old_brother, old_root_len);
269 old_brother->
father = pntr;
279 if (
name && strcmp(
name, wantedName) == 0) found =
this;
283 if (!found) found = get_rightson()->
findLeafNamed(wantedName);
293 enum { NLD_NODIST = 0, NLD_DOWNDIST, NLD_BOTHDIST } state;
305 if (state < NLD_DOWNDIST) state = NLD_DOWNDIST;
311 if (state < NLD_BOTHDIST) state = NLD_BOTHDIST;
318 std::map<TreeNode*, NodeLeafDistance> data;
327 data[node].set_downdist(0.0);
330 insert_tree(node->get_leftson());
331 insert_tree(node->get_rightson());
333 data[node].set_downdist(
std::max(data[node->get_leftson()].get_downdist()+node->
leftlen,
334 data[node->get_rightson()].get_downdist()+node->
rightlen));
338 void findBetterEdge_sub(
TreeNode *node) {
345 GBT_LEN upDist =
std::max(data[father].get_updist(), data[brother].get_downdist()+brothLen);
346 GBT_LEN downDist = data[node].get_downdist();
349 GBT_LEN edge_dd = calc_distdiff(upDist, downDist);
350 if (edge_dd<min_distdiff) {
352 min_distdiff = edge_dd;
356 data[node].set_updist(upDist+len);
359 findBetterEdge_sub(node->get_leftson());
360 findBetterEdge_sub(node->get_rightson());
364 void findBetterEdge(
TreeNode *node) {
366 findBetterEdge_sub(node->get_leftson());
367 findBetterEdge_sub(node->get_rightson());
373 : innermost(rootNode->get_leftson(), rootNode->get_rightson())
375 insert_tree(rootNode);
377 TreeNode *lson = rootNode->get_leftson();
378 TreeNode *rson = rootNode->get_rightson();
382 GBT_LEN lddist = data[lson].get_downdist();
383 GBT_LEN rddist = data[rson].get_downdist();
385 data[lson].set_updist(rddist+rootEdgeLen);
386 data[rson].set_updist(lddist+rootEdgeLen);
388 min_distdiff = calc_distdiff(lddist, rddist);
390 findBetterEdge(lson);
391 findBetterEdge(rson);
406 typedef std::map<TreeNode*,GBT_LEN> LengthMap;
407 typedef std::set<TreeNode*> NodeSet;
409 LengthMap eliminatedParentLength;
410 LengthMap addedParentLength;
420 addedParentLength[node] += addLen;
427 if (useProgress) progress =
new arb_progress(
"Distributing eliminated lengths", eliminatedParentLength.size());
429 while (!eliminatedParentLength.empty()) {
430 for (LengthMap::iterator from = eliminatedParentLength.begin(); from != eliminatedParentLength.end(); ++from) {
432 GBT_LEN elimLen = from->second;
435 if (progress) ++*progress;
437 eliminatedParentLength.clear();
445 for (LengthMap::iterator to = addedParentLength.begin(); to != addedParentLength.end(); ++to) {
447 GBT_LEN additionalLen = to->second;
448 double effective_length = affectedEdge.
length() + additionalLen;
450 if (effective_length<=0.0) {
453 handled.insert(to->first);
457 if (progress && !eliminatedParentLength.empty()) {
464 for (NodeSet::iterator del = handled.begin(); del != handled.end(); ++del) {
465 addedParentLength.erase(*del);
470 for (LengthMap::iterator to = addedParentLength.begin(); to != addedParentLength.end(); ++to) {
472 GBT_LEN additionalLen = to->second;
473 double effective_length = affectedEdge.
length() + additionalLen;
478 if (progress)
delete progress;
482 GBT_LEN ARB_edge::adjacent_distance()
const {
486 return next().length_or_adjacent_distance() +
counter_next().length_or_adjacent_distance();
495 if (len != 0.0) virtually_distribute_length_forward(len, collect);
513 GBT_LEN d1 = e1.length_or_adjacent_distance();
514 GBT_LEN d2 = e2.length_or_adjacent_distance();
518 e1.virtually_add_or_distribute_length_forward(len*d1, collect);
519 e2.virtually_add_or_distribute_length_forward(len*d2, collect);
536 GBT_LEN dist_fwd = adjacent_distance();
537 GBT_LEN dist_bwd = backEdge.adjacent_distance();
538 GBT_LEN lenW = len/(dist_fwd+dist_bwd);
539 len_fwd = lenW*dist_fwd;
540 len_bwd = lenW*dist_bwd;
544 if (
is_normal(len_fwd)) virtually_distribute_length_forward(len_fwd, collect);
545 if (
is_normal(len_bwd)) backEdge.virtually_distribute_length_forward(len_bwd, collect);
548 void TreeNode::eliminate_and_collect(
const multifurc_limits& below, LengthCollector& collect) {
553 if (!
is_leaf() || below.applyAtLeafs) {
566 collect.eliminate_parent_edge(
this);
575 get_leftson() ->eliminate_and_collect(below, collect);
576 get_rightson()->eliminate_and_collect(below, collect);
606 GBT_LEN change = new_len-old_len;
618 #if defined(ASSERTION_USED)
636 progress.
subtitle(
"Collecting branches to eliminate");
637 root->get_leftson()->eliminate_and_collect(below, collector);
638 root->get_rightson()->eliminate_and_collect(below, collector);
647 remark_branch.setNull();
649 get_leftson()->remove_bootstrap();
650 get_rightson()->remove_bootstrap();
663 freeset(new_remark,
GBS_trim(new_remark));
664 if (!new_remark[0]) {
666 remark_branch.setNull();
669 remark_branch = new_remark;
674 if (!error) error = get_leftson()->apply_aci_to_remarks(aci, callEnv);
675 if (!error) error = get_rightson()->apply_aci_to_remarks(aci, callEnv);
684 get_leftson()->reset_branchlengths();
685 get_rightson()->reset_branchlengths();
694 get_leftson()->scale_branchlengths(factor);
695 get_rightson()->scale_branchlengths(factor);
704 get_leftson()->sum_child_lengths() +
705 get_rightson()->sum_child_lengths();
720 double len = bootstrap/100.0;
723 get_leftson()->bootstrap2branchlen();
724 get_rightson()->bootstrap2branchlen();
734 get_leftson()->branchlen2bootstrap();
735 get_rightson()->branchlen2bootstrap();
737 #if defined(ASSERTION_USED)
758 get_leftson()->branchlenXbootstrap();
759 get_rightson()->branchlenXbootstrap();
773 double brothersBootstrap;
779 report(
GBS_global_string(
"Ignored invalid bootstrap '%s' at root edge leading to a leaf", remark_branch.content()));
784 switch (brothersType) {
786 double averageBootstrap = (bootstrap + brothersBootstrap) / 2.0;
789 SmartCharPtr myOrgRemark = remark_branch;
790 SmartCharPtr brothersOrgRemark = brother->remark_branch;
793 type =
parse_remark(remark_branch.content(), bootstrap);
795 const double REMARKABLE_DIFF = 2.0;
796 #if defined(ASSERTION_USED)
797 const double EPSILON = 0.001 + 0.5;
798 double diffToAverage =
std::abs(bootstrap-averageBootstrap);
803 if (diff>REMARKABLE_DIFF) {
804 report(
GBS_global_string(
"Root-edge has conflicting support values '%s' and '%s' -> using average '%s'",
805 myOrgRemark.content(),
806 brothersOrgRemark.content(),
807 remark_branch.content()));
814 const char *what =
GBS_global_string(
"Using comment '%s' on both sides of root-edge", remark_branch.content());
845 int bootstrap_rounded =
int(bootstrap_percent+0.5);
861 result = get_leftson();
868 result = get_rightson();
902 if (
this == other)
return this;
905 return get_father()->ancestor_common_with(other->get_father());
910 return get_leftson()->count_clades() + get_rightson()->count_clades() +
is_clade();
913 #if defined(ASSERTION_USED) || defined(PROVIDE_TREE_STRUCTURE_TESTS)
932 void TEST_tree_iterator() {
965 if (edge.is_edge_to_leaf()) ++count_leafs;
967 while (edge != start);
980 if (edge.is_edge_to_leaf()) ++count_leafs;
982 while (edge != start);
994 void TEST_tree_branch_modifications() {
998 const char *newick_bs2bl =
"(((((((CloTyro3:.1,CloTyro4:.1):.4,CloTyro2:.1):0,CloTyrob:.1):.97,CloInnoc:.1):0,CloBifer:.1):.53,(((CloButy2:.1,CloButyr:.1):1,CloCarni:.1):.33,CloPaste:.1):.97):.5,((((CorAquat:.1,CurCitre:.1):1,CorGluta:.1):.17,CelBiazo:.1):.4,CytAquat:.1):.5);";
999 const char *newick_bl2bs =
"(((((((CloTyro3,CloTyro4)'3%',CloTyro2)'2%',CloTyrob)'27%',CloInnoc)'6%',CloBifer)'12%',(((CloButy2,CloButyr)'56%',CloCarni)'1%',CloPaste)'13%')'16%',((((CorAquat,CurCitre)'10%',CorGluta)'5%',CelBiazo)'21%',CytAquat)'16%');";
1000 const char *newick =
"(((((((CloTyro3:1.046,CloTyro4:.061)'40%':.026,CloTyro2:.017)'0%':.017,CloTyrob:.009)'97%':.274,CloInnoc:.371)'0%':.057,CloBifer:.388)'53%':.124,(((CloButy2:.009,CloButyr:0):.564,CloCarni:.12)'33%':.01,CloPaste:.179)'97%':.131):.081,((((CorAquat:.084,CurCitre:.058):.103,CorGluta:.522)'17%':.053,CelBiazo:.059)'40%':.207,CytAquat:.711):.081);";
1002 #define LEFT_SWAP_EVEN "((((((CloTyro3:1.046,CloTyro4:.061)'40%':.03,CloTyro2:.017)'0%':.02,CloTyrob:.009)'97%':.27,CloInnoc:.371)'0%':.06,CloBifer:.388)'53%':.12,(((CloButy2:.009,CloButyr:0):.56,CloCarni:.12)'33%':.01,CloPaste:.179)'97%':.13)"
1003 #define LEFT_SWAP_ODD "((((((CloTyro3:1.046,CloTyro4:.061)'3%':.4,CloTyro2:.017)'2%':0,CloTyrob:.009)'27%':.97,CloInnoc:.371)'6%':0,CloBifer:.388)'12%':.53,(((CloButy2:.009,CloButyr:0)'56%':1,CloCarni:.12)'1%':.33,CloPaste:.179)'13%':.97)"
1004 #define RIGHT_SWAP_EVEN "((((CorAquat:.084,CurCitre:.058):.1,CorGluta:.522)'17%':.05,CelBiazo:.059)'40%':.21,CytAquat:.711)"
1005 #define RIGHT_SWAP_ODD "((((CorAquat:.084,CurCitre:.058)'10%':1,CorGluta:.522)'5%':.17,CelBiazo:.059)'21%':.4,CytAquat:.711)"
1007 const char *newick_blXbs_2 =
"(" LEFT_SWAP_EVEN
":.08," RIGHT_SWAP_EVEN
":.08);";
1008 const char *newick_blXbs_1 =
"(" LEFT_SWAP_ODD
"'16%':.5," RIGHT_SWAP_ODD
"'16%':.5);";
1010 const char *right_newick =
"((((CorAquat:.084,CurCitre:.058):.103,CorGluta:.522)'17%':.053,CelBiazo:.059)'40%':.207,CytAquat:.711):.081;";
1011 const char *right_newick_preserved1 =
"((((CorAquat:.084,CurCitre:.058):.103,CorGluta:.522)'17%':.06,CelBiazo:.029)'40%':.231,CytAquat:.711):.081;";
1012 const char *right_newick_preserved2 =
"((((CorAquat:.084,CurCitre:.058):.103,CorGluta:.522)'17%':.041,CelBiazo:.117)'40%':.161,CytAquat:.711):.081;";
1045 for (
int repeat = 1; repeat<=3; ++repeat) {
1063 TreeNode *right = tree->get_rightson();
1086 #endif // UNIT_TESTS
void set_bootstrap(double bootstrap)
void set_branchlength_unrooted(GBT_LEN newlen)
void set_updist(GBT_LEN UpDist)
size_t GBT_count_leafs(const TreeNode *tree)
GBDATA * GB_open(const char *path, const char *opent)
void virtually_distribute_length(GBT_LEN len, TreeNode::LengthCollector &collect) const
void bootstrap2branchlen()
void GB_warning(const char *message)
#define implicated(hypothesis, conclusion)
TreeNode * findLeafNamed(const char *wantedName)
const TreeNode * get_root_node() const
GBT_LEN get_branchlength_unrooted() const
virtual void compute_tree()=0
POS_TREE1 * get_father() const
TreeRoot * get_tree_root() const
TreeNode * GBT_read_tree(GBDATA *gb_main, const char *tree_name, TreeRoot *troot)
#define DEFAULT_BRANCH_LENGTH
const char * GBS_global_string(const char *templat,...)
void warning(int warning_num, const char *warning_message)
ARB_edge previous() const
ARB_edge rootEdge(TreeRoot *root)
void use_as_remark(const SmartCharPtr &newRemark)
void branchlenXbootstrap()
int ARB_strNULLcmp(const char *s1, const char *s2)
void reset_branchlengths()
bool has_valid_root_remarks() const
static HelixNrInfo * start
ARB_edge parentEdge(TreeNode *son)
GBT_RemarkType parse_remark(const char *remark, double &bootstrap)
#define TEST_PUBLISH(testfunction)
POS_TREE1 * get_father() const
GB_ERROR GB_await_error()
void branchlen2bootstrap()
static int diff(int v1, int v2, int v3, int v4, int st, int en)
void add_parent_length(TreeNode *node, GBT_LEN addLen)
#define TEST_EXPECT(cond)
#define TEST_EXPECT_NEWICK(format, tree, expected_newick)
bool is_son_of_root() const
const TreeNode * ancestor_common_with(const TreeNode *other) const
CONSTEXPR_INLINE int leafs_2_edges(int leafs, TreeModel model)
GBT_RemarkType parse_bootstrap(double &bootstrap, WarningConsumer report)
char * GBS_trim(const char *str)
static void error(const char *msg)
bool is_root_node() const
CONSTEXPR_INLINE_Cxx14 void swap(unsigned char &c1, unsigned char &c2)
const ARB_edge & innermost_edge() const
EdgeFinder(TreeNode *rootNode)
void multifurcate_whole_tree(const multifurc_limits &below)
void set_downdist(GBT_LEN DownDist)
AP_tree_nlen * rootNode()
CONSTEXPR_INLINE bool valid(SpeciesCreationMode m)
void eliminate_parent_edge(TreeNode *node)
bool is_ancestor_of(const TreeNode *descendant) const
void reorder_tree(TreeOrder mode)
bool knownNonNull(const void *nonnull)
bool has_no_remark() const
bool is_edge_to_leaf() const
void set_branchlength_preserving(GBT_LEN new_len)
TreeNode * fixDeletedSon()
bool is_inside(const TreeNode *subtree) const
GBT_LEN get_updist() const
void subtitle(const char *stitle)
void scale_branchlengths(double factor)
void independent_distribution(bool useProgress)
void set_tree_root(TreeRoot *new_root)
GBT_LEN sum_child_lengths() const
ARB_edge counter_next() const
GBT_LEN get_downdist() const
GB_ERROR apply_aci_to_remarks(const char *aci, const GBL_call_env &callEnv)
ARB_edge find_innermost_edge()
#define TEST_EXPECT_DIFFERENT(expr, want)
NOT4PERL char * GB_command_interpreter_in_env(const char *str, const char *commands, const GBL_call_env &callEnv)
GBT_LEN get_branchlength() const
GB_transaction ta(gb_var)
void destroy(TreeNode *that)
virtual void change_root(TreeNode *old, TreeNode *newroot)
void set_length(GBT_LEN len)
const char * get_remark() const
const SmartCharPtr & get_remark_ptr() const
void(* WarningConsumer)(const char *message)
#define TEST_EXPECT_EQUAL(expr, want)
char * GBS_global_string_copy(const char *templat,...)
void GB_close(GBDATA *gbd)
static int iteration_count(int leafs_in_tree)