ARB
TreeNode.cxx
Go to the documentation of this file.
1 // ================================================================ //
2 // //
3 // File : TreeNode.cxx //
4 // Purpose : //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in December 2013 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // ================================================================ //
11 
12 #include "TreeNode.h"
13 #include <arb_progress.h>
14 #include <arb_str.h>
15 #include <map>
16 #include <set>
17 #include <cmath> // needed with 4.4.3 (but not with 4.7.3)
18 
19 // ------------------
20 // TreeRoot
21 
23  deleteWithNodes = false; // avoid recursive call of ~TreeRoot (obsolete?)
24  rt_assert(!rootNode); // you have to call TreeRoot::predelete() before dtor! you can do this is dtor of that derived class, which defines makeNode/destroyNode
25  // Note: destroying nodes from here is impossible (leads to pure virtual call, as derived class instance of 'this' is already under destruction)
26 }
27 
28 void TreeRoot::change_root(TreeNode *oldroot, TreeNode *newroot) {
29  // Note: when oldroot == NULp -> better use announce_tree_constructed()
30 
31  rt_assert(rootNode == oldroot);
32  rt_assert(implicated(newroot, !newroot->father));
33  rootNode = newroot;
34 
35  if (oldroot && oldroot->get_tree_root() && !oldroot->is_inside(newroot)) oldroot->set_tree_root(NULp); // unlink from this
36  if (newroot && newroot->get_tree_root() != this) newroot->set_tree_root(this); // link to this
37 }
38 
39 // --------------------
40 // TreeNode
41 
42 #if defined(PROVIDE_TREE_STRUCTURE_TESTS)
43 
44 Validity TreeNode::is_valid() const {
45  rt_assert(knownNonNull(this));
47 
48  TreeRoot *troot = get_tree_root();
49  if (troot) {
50  if (is_leaf()) {
51  valid = Validity(!rightson && !leftson, "leaf has son");
52  }
53  else {
54  valid = Validity(rightson && leftson, "inner node lacks sons");
55  if (valid) valid = get_rightson()->is_valid();
56  if (valid) valid = get_leftson()->is_valid();
57  }
58  if (father) {
59  if (valid) valid = Validity(is_inside(get_father()), "node not inside father subtree");
60  if (valid) valid = Validity(troot->get_root_node()->is_ancestor_of(this), "root is not nodes ancestor");
61  if (valid) valid = Validity(get_father()->get_tree_root() == troot, "node and father have different TreeRoot");
62  }
63  else {
64  if (valid) valid = Validity(troot->get_root_node() == this, "node has no father, but isn't root-node");
65  if (valid) valid = Validity(!is_leaf(), "root-node is leaf"); // leaf@root (tree has to have at least 2 leafs)
66  if (valid) valid = Validity(has_valid_root_remarks(), "root-node has invalid remarks");
67  }
68  }
69  else { // removed node (may be incomplete)
70  if (is_leaf()) {
71  valid = Validity(!rightson && !leftson, "(removed) leaf has son");
72  }
73  else {
74  if (rightson) valid = get_rightson()->is_valid();
75  if (leftson && valid) valid = get_leftson()->is_valid();
76  }
77  if (father) {
78  if (valid) valid = Validity(is_inside(get_father()), "(removed) node not inside father subtree");
79  if (valid) valid = Validity(get_father()->get_tree_root() == troot, "(removed) node and father have different TreeRoot");
80  }
81  }
82  return valid;
83 }
84 #endif // PROVIDE_TREE_STRUCTURE_TESTS
85 
87  if (tree_root != new_root) {
88  tree_root = new_root;
89  if (leftson) get_leftson()->set_tree_root(new_root);
90  if (rightson) get_rightson()->set_tree_root(new_root);
91  }
92 }
93 
94 void TreeNode::reorder_subtree(TreeOrder mode) {
95  static const char *smallest_leafname; // has to be set to the alphabetically smallest name (when function exits)
96 
97  if (is_leaf()) {
98  smallest_leafname = name;
99  }
100  else {
101  int leftsize = get_leftson() ->get_leaf_count();
102  int rightsize = get_rightson()->get_leaf_count();
103 
104  {
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;
108  if (swap_branches) swap_sons();
109  }
110 
111  TreeOrder lmode, rmode;
112  if (mode & (ORDER_BIG_TO_EDGE|ORDER_BIG_TO_CENTER)) { // symmetric
114 
115  if (mode & ORDER_BIG_TO_CENTER) {
116  lmode = TreeOrder(mode | ORDER_BIG_DOWN);
117  rmode = TreeOrder(mode & ~ORDER_BIG_DOWN);
118  }
119  else {
120  lmode = TreeOrder(mode & ~ORDER_BIG_DOWN);
121  rmode = TreeOrder(mode | ORDER_BIG_DOWN);
122  }
123  }
124  else { // asymmetric
125  if (mode & ORDER_ALTERNATING) mode = TreeOrder(mode^ORDER_BIG_DOWN);
126 
127  lmode = mode;
128  rmode = mode;
129  }
130 
131  get_leftson()->reorder_subtree(lmode);
132  const char *leftleafname = smallest_leafname;
133 
134  get_rightson()->reorder_subtree(rmode);
135  const char *rightleafname = smallest_leafname;
136 
137  if (leftleafname && rightleafname) {
138  int name_cmp = strcmp(leftleafname, rightleafname);
139  if (name_cmp <= 0) {
140  smallest_leafname = leftleafname;
141  }
142  else {
143  smallest_leafname = rightleafname;
144  if (leftsize == rightsize) { // if sizes of subtrees are equal and rightleafname<leftleafname -> swap branches
145  const char *smallest_leafname_save = smallest_leafname;
146 
147  swap_sons();
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);
150 
151  smallest_leafname = smallest_leafname_save;
152  }
153  }
154  }
155  }
156  rt_assert(smallest_leafname);
157 }
158 
162  compute_tree();
163  reorder_subtree(mode);
164 }
165 
167  if (!is_leaf()) {
168  swap_sons();
169  get_leftson()->rotate_subtree();
170  get_rightson()->rotate_subtree();
171  }
172 }
173 
174 void TreeNode::keelOver(TreeNode *prev, TreeNode *next, double len) {
181  if (leftson == prev) {
182  leftson = next;
183  leftlen = len;
184 
185  if (keeledOver) {
186  if (inverseLeft) keeledOver = false;
187  }
188  else {
189  keeledOver = true;
190  inverseLeft = true;
191  }
192  }
193  else {
194  rightson = next;
195  rightlen = len;
196 
197  if (keeledOver) {
198  if (!inverseLeft) keeledOver = false;
199  }
200  else {
201  keeledOver = true;
202  inverseLeft = false;
203  }
204  }
205  father = prev;
206 }
207 
215  if (at_root()) return; // already root
216 
217  TreeNode *old_root = get_root_node();
218  TreeNode *old_brother = is_inside(old_root->get_leftson()) ? old_root->get_rightson() : old_root->get_leftson();
219 
220  rt_assert(old_root->has_valid_root_remarks());
221 
222  // move remark branches to top
223  {
224  // Note: no remark is lost here (duplicate removed from old root; new duplicate created at new root)
225  SmartCharPtr remarkPtr;
226  if (!is_leaf()) remarkPtr = get_remark_ptr();
227  for (TreeNode *node = this; node->father; node = node->get_father()) {
228  std::swap(node->remark_branch, remarkPtr);
229  }
230  }
231 
232  GBT_LEN old_root_len = old_root->leftlen + old_root->rightlen;
233 
234  // new node & this init
235  old_root->leftson = this;
236  old_root->rightson = father; // will be set later
237 
238  if (father->leftson == this) {
239  old_root->leftlen = old_root->rightlen = father->leftlen*.5;
240  }
241  else {
242  old_root->leftlen = old_root->rightlen = father->rightlen*.5;
243  }
244 
245  TreeNode *next = get_father()->get_father();
246  TreeNode *prev = old_root;
247  TreeNode *pntr = get_father();
248 
249  if (father->leftson == this) father->leftson = old_root; // to set the flag correctly
250 
251  // loop from father to son of root, rotate tree
252  while (next->father) {
253  double len = (next->leftson == pntr) ? next->leftlen : next->rightlen;
254 
255  pntr->keelOver(prev, next, len);
256 
257  prev = pntr;
258  pntr = next;
259  next = next->get_father();
260  }
261  // now 'next' points to the old root, which has been destroyed above
262  // 'pntr' points to one former son-of-root (the one nearer to new root)
263  //
264  // pointer at oldroot
265  // pntr == brother before old root == next
266 
267  pntr->keelOver(prev, old_brother, old_root_len);
268 
269  old_brother->father = pntr;
270  father = old_root;
271 
272  rt_assert(get_root_node() == old_root); // the root node itself remains unchanged (its sons change)
273  rt_assert(old_root->has_valid_root_remarks());
274 }
275 
276 TreeNode *TreeNode::findLeafNamed(const char *wantedName) {
277  TreeNode *found = NULp;
278  if (is_leaf()) {
279  if (name && strcmp(name, wantedName) == 0) found = this;
280  }
281  else {
282  found = get_leftson()->findLeafNamed(wantedName);
283  if (!found) found = get_rightson()->findLeafNamed(wantedName);
284  }
285  return found;
286 }
287 
288 // ----------------------------
289 // find_innermost_edge
290 
292  GBT_LEN downdist, updist;
293  enum { NLD_NODIST = 0, NLD_DOWNDIST, NLD_BOTHDIST } state;
294 
295 public:
296 
298  : downdist(-1.0),
299  updist(-1.0),
300  state(NLD_NODIST)
301  {}
302 
303  GBT_LEN get_downdist() const { rt_assert(state >= NLD_DOWNDIST); return downdist; }
304  void set_downdist(GBT_LEN DownDist) {
305  if (state < NLD_DOWNDIST) state = NLD_DOWNDIST;
306  downdist = DownDist;
307  }
308 
309  GBT_LEN get_updist() const { rt_assert(state >= NLD_BOTHDIST); return updist; }
310  void set_updist(GBT_LEN UpDist) {
311  if (state < NLD_BOTHDIST) state = NLD_BOTHDIST;
312  updist = UpDist;
313  }
314 
315 };
316 
317 class EdgeFinder {
318  std::map<TreeNode*, NodeLeafDistance> data; // maximum distance to farthest leaf
319 
320  ARB_edge innermost;
321  double min_distdiff; // abs diff between up- and downdiff
322 
323  GBT_LEN calc_distdiff(GBT_LEN d1, GBT_LEN d2) { return fabs(d1-d2); }
324 
325  void insert_tree(TreeNode *node) {
326  if (node->is_leaf()) {
327  data[node].set_downdist(0.0);
328  }
329  else {
330  insert_tree(node->get_leftson());
331  insert_tree(node->get_rightson());
332 
333  data[node].set_downdist(std::max(data[node->get_leftson()].get_downdist()+node->leftlen,
334  data[node->get_rightson()].get_downdist()+node->rightlen));
335  }
336  }
337 
338  void findBetterEdge_sub(TreeNode *node) {
339  TreeNode *father = node->get_father();
340  TreeNode *brother = node->get_brother();
341 
342  GBT_LEN len = node->get_branchlength();
343  GBT_LEN brothLen = brother->get_branchlength();
344 
345  GBT_LEN upDist = std::max(data[father].get_updist(), data[brother].get_downdist()+brothLen);
346  GBT_LEN downDist = data[node].get_downdist();
347 
348  {
349  GBT_LEN edge_dd = calc_distdiff(upDist, downDist);
350  if (edge_dd<min_distdiff) { // found better edge
351  innermost = ARB_edge(node, father);
352  min_distdiff = edge_dd;
353  }
354  }
355 
356  data[node].set_updist(upDist+len);
357 
358  if (!node->is_leaf()) {
359  findBetterEdge_sub(node->get_leftson());
360  findBetterEdge_sub(node->get_rightson());
361  }
362  }
363 
364  void findBetterEdge(TreeNode *node) {
365  if (!node->is_leaf()) {
366  findBetterEdge_sub(node->get_leftson());
367  findBetterEdge_sub(node->get_rightson());
368  }
369  }
370 
371 public:
373  : innermost(rootNode->get_leftson(), rootNode->get_rightson()) // root-edge
374  {
375  insert_tree(rootNode);
376 
377  TreeNode *lson = rootNode->get_leftson();
378  TreeNode *rson = rootNode->get_rightson();
379 
380  GBT_LEN rootEdgeLen = rootNode->leftlen + rootNode->rightlen;
381 
382  GBT_LEN lddist = data[lson].get_downdist();
383  GBT_LEN rddist = data[rson].get_downdist();
384 
385  data[lson].set_updist(rddist+rootEdgeLen);
386  data[rson].set_updist(lddist+rootEdgeLen);
387 
388  min_distdiff = calc_distdiff(lddist, rddist);
389 
390  findBetterEdge(lson);
391  findBetterEdge(rson);
392  }
393 
394  const ARB_edge& innermost_edge() const { return innermost; }
395 };
396 
398  EdgeFinder edgeFinder(get_root_node());
399  return edgeFinder.innermost_edge();
400 }
401 
402 // ------------------------
403 // multifurcation
404 
406  typedef std::map<TreeNode*,GBT_LEN> LengthMap;
407  typedef std::set<TreeNode*> NodeSet;
408 
409  LengthMap eliminatedParentLength;
410  LengthMap addedParentLength;
411 
412 public:
414  rt_assert(!node->is_root_node());
415  eliminatedParentLength[node] += parentEdge(node).eliminate();
416  }
417 
419  rt_assert(!node->is_root_node());
420  addedParentLength[node] += addLen;
421  }
422 
423  void independent_distribution(bool useProgress) {
424  // step 2: (see caller)
425  arb_progress *progress = NULp;
426  int redistCount = 0;
427  if (useProgress) progress = new arb_progress("Distributing eliminated lengths", eliminatedParentLength.size());
428 
429  while (!eliminatedParentLength.empty()) { // got eliminated lengths which need to be distributed
430  for (LengthMap::iterator from = eliminatedParentLength.begin(); from != eliminatedParentLength.end(); ++from) {
431  ARB_edge elimEdge = parentEdge(from->first);
432  GBT_LEN elimLen = from->second;
433 
434  elimEdge.virtually_distribute_length(elimLen, *this);
435  if (progress) ++*progress;
436  }
437  eliminatedParentLength.clear(); // all distributed!
438 
439  // handle special cases where distributed length is negative and results in negative destination branches.
440  // Avoid generating negative dest. branchlengths by
441  // - eliminating the dest. branch
442  // - redistributing the additional (negative) length (may cause additional negative lengths on other dest. branches)
443 
444  NodeSet handled;
445  for (LengthMap::iterator to = addedParentLength.begin(); to != addedParentLength.end(); ++to) {
446  ARB_edge affectedEdge = parentEdge(to->first);
447  GBT_LEN additionalLen = to->second;
448  double effective_length = affectedEdge.length() + additionalLen;
449 
450  if (effective_length<=0.0) { // negative or zero
451  affectedEdge.set_length(effective_length);
452  eliminate_parent_edge(to->first); // adds entry to eliminatedParentLength and causes another additional loop
453  handled.insert(to->first);
454  }
455  }
456 
457  if (progress && !eliminatedParentLength.empty()) {
458  delete progress;
459  ++redistCount;
460  progress = new arb_progress(GBS_global_string("Redistributing negative lengths (#%i)", redistCount), eliminatedParentLength.size());
461  }
462 
463  // remove all redistributed nodes
464  for (NodeSet::iterator del = handled.begin(); del != handled.end(); ++del) {
465  addedParentLength.erase(*del);
466  }
467  }
468 
469  // step 3:
470  for (LengthMap::iterator to = addedParentLength.begin(); to != addedParentLength.end(); ++to) {
471  ARB_edge affectedEdge = parentEdge(to->first);
472  GBT_LEN additionalLen = to->second;
473  double effective_length = affectedEdge.length() + additionalLen;
474 
475  affectedEdge.set_length(effective_length);
476  }
477 
478  if (progress) delete progress;
479  }
480 };
481 
482 GBT_LEN ARB_edge::adjacent_distance() const {
484 
485  if (is_edge_to_leaf()) return 0.0;
486  return next().length_or_adjacent_distance() + counter_next().length_or_adjacent_distance();
487 }
488 
489 void ARB_edge::virtually_add_or_distribute_length_forward(GBT_LEN len, TreeNode::LengthCollector& collect) const {
490  rt_assert(!is_nan_or_inf(len));
491  if (length() > 0.0) {
492  collect.add_parent_length(son(), len);
493  }
494  else {
495  if (len != 0.0) virtually_distribute_length_forward(len, collect);
496  }
497 }
498 
499 
500 void ARB_edge::virtually_distribute_length_forward(GBT_LEN len, TreeNode::LengthCollector& collect) const {
507  rt_assert(is_normal(len));
508  rt_assert(!is_edge_to_leaf()); // cannot forward anything (nothing beyond leafs)
509 
510  ARB_edge e1 = next();
511  ARB_edge e2 = counter_next();
512 
513  GBT_LEN d1 = e1.length_or_adjacent_distance();
514  GBT_LEN d2 = e2.length_or_adjacent_distance();
515 
516  len = len/(d1+d2);
517 
518  e1.virtually_add_or_distribute_length_forward(len*d1, collect);
519  e2.virtually_add_or_distribute_length_forward(len*d2, collect);
520 }
521 
533  ARB_edge backEdge = inverse();
534  GBT_LEN len_fwd, len_bwd;
535  {
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;
541 
542  }
543 
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);
546 }
547 
548 void TreeNode::eliminate_and_collect(const multifurc_limits& below, LengthCollector& collect) {
553  if (!is_leaf() || below.applyAtLeafs) {
554  double value;
555  if (is_leaf()) {
556  value = 100.0;
557  goto hack; // @@@ remove applyAtLeafs from multifurc_limits (does that really make sense? rethink!)
558  }
559  switch (parse_bootstrap(value, GB_warning)) {
560  case REMARK_NONE:
561  value = 100.0;
562  // fall-through
563  case REMARK_BOOTSTRAP:
564  hack:
565  if (value<below.bootstrap && get_branchlength_unrooted()<below.branchlength) {
566  collect.eliminate_parent_edge(this);
567  }
568  break;
569 
570  case REMARK_OTHER: break;
571  }
572  }
573 
574  if (!is_leaf()) {
575  get_leftson() ->eliminate_and_collect(below, collect);
576  get_rightson()->eliminate_and_collect(below, collect);
577  }
578 }
579 
586  TreeNode::LengthCollector collector;
587  collector.eliminate_parent_edge(son());
588  collector.independent_distribution(false);
589 }
594  rt_assert(father); // cannot multifurcate at root; call with son of root to multifurcate root-edge
595  if (father) parentEdge(this).multifurcate();
596 }
597 
606  GBT_LEN change = new_len-old_len;
607 
608  char *old_remark = is_leaf() ? NULp : nulldup(get_remark());
609 
610  // distribute the negative 'change' to neighbours:
611  set_branchlength_unrooted(-change);
612  multifurcate();
613 
614  set_branchlength_unrooted(new_len);
615  if (old_remark) {
616  use_as_remark(old_remark); // restore remark (was removed by multifurcate())
617  }
618 #if defined(ASSERTION_USED)
619  else {
621  }
622 #endif
623 }
624 
631  TreeNode *root = get_root_node();
632  LengthCollector collector;
633  arb_progress progress("Multifurcating tree");
634 
635  // step 1:
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);
639  // root-edge is handled twice by the above calls.
640  // Unproblematic: first call will eliminate root-edge, so second call will do nothing.
641 
642  // step 2 and 3:
643  collector.independent_distribution(true);
644 }
645 
647  remark_branch.setNull();
648  if (!is_leaf()) {
649  get_leftson()->remove_bootstrap();
650  get_rightson()->remove_bootstrap();
651  }
652 }
653 
654 GB_ERROR TreeNode::apply_aci_to_remarks(const char *aci, const GBL_call_env& callEnv) {
655  GB_ERROR error = NULp;
656  if (!is_leaf()) {
657  {
658  char *new_remark = GB_command_interpreter_in_env(remark_branch.isSet() ? remark_branch.content() : "", aci, callEnv);
659  if (!new_remark) {
660  error = GB_await_error();
661  }
662  else {
663  freeset(new_remark, GBS_trim(new_remark));
664  if (!new_remark[0]) { // skip empty results
665  free(new_remark);
666  remark_branch.setNull();
667  }
668  else {
669  remark_branch = new_remark;
670  }
671  }
672  }
673 
674  if (!error) error = get_leftson()->apply_aci_to_remarks(aci, callEnv);
675  if (!error) error = get_rightson()->apply_aci_to_remarks(aci, callEnv);
676  }
677 
678  return error;
679 }
681  if (!is_leaf()) {
683 
684  get_leftson()->reset_branchlengths();
685  get_rightson()->reset_branchlengths();
686  }
687 }
688 
689 void TreeNode::scale_branchlengths(double factor) {
690  if (!is_leaf()) {
691  leftlen *= factor;
692  rightlen *= factor;
693 
694  get_leftson()->scale_branchlengths(factor);
695  get_rightson()->scale_branchlengths(factor);
696  }
697 }
698 
700  if (is_leaf()) return 0.0;
701  return
702  leftlen +
703  rightlen +
704  get_leftson()->sum_child_lengths() +
705  get_rightson()->sum_child_lengths();
706 }
707 
710  if (is_leaf()) {
712  }
713  else {
714  if (!is_root_node()) {
715  double bootstrap;
716  if (parse_bootstrap(bootstrap, GB_warning) != REMARK_BOOTSTRAP) {
717  bootstrap = 100.0; // no bootstrap means "100%"
718  }
719 
720  double len = bootstrap/100.0;
722  }
723  get_leftson()->bootstrap2branchlen();
724  get_rightson()->bootstrap2branchlen();
725  }
726 }
729  if (!is_leaf()) {
730  remove_remark();
731  if (!is_root_node()) {
733  }
734  get_leftson()->branchlen2bootstrap();
735  get_rightson()->branchlen2bootstrap();
736  }
737 #if defined(ASSERTION_USED)
738  else {
740  }
741 #endif
742 }
744  if (!is_leaf()) {
745  if (!is_root_node()) {
746  if (!is_son_of_root() || is_leftson()) { // Note: condition depends on order of recursive calls below!
747  double bootstrap;
748  if (parse_bootstrap(bootstrap, GB_warning) != REMARK_BOOTSTRAP) {
749  bootstrap = 100.0; // no bootstrap means "100%"
750  }
751  double len = get_branchlength_unrooted();
752 
753  set_branchlength_unrooted(bootstrap/100.0);
754  set_bootstrap(len*100.0);
755  }
756  }
757 
758  get_leftson()->branchlenXbootstrap();
759  get_rightson()->branchlenXbootstrap();
760  }
761 }
762 
764  // If this function reports a warning to the caller, it will also repair the incorrect TreeNode(s).
765  // Reporting a warning will cause the tree to be saved to DB in ARB_NTREE, if it has been loaded from DB.
766 
767  rt_assert(!is_leaf()); // only inner nodes may have bootstraps
768  rt_assert(!is_root_node()); // root nodes have no bootstrap values (because they do not have a parent branch)
769 
770  GBT_RemarkType type = parse_remark(remark_branch.content(), bootstrap);
771  if (is_son_of_root()) {
772  TreeNode *brother = get_brother();
773  double brothersBootstrap;
774  GBT_RemarkType brothersType = parse_remark(brother->remark_branch.content(), brothersBootstrap);
775 
776  // Only inspect bootstrap(s) of root-edge, if at least one brother has type REMARK_BOOTSTRAP.
777  if (type == REMARK_BOOTSTRAP) {
778  if (brother->is_leaf()) {
779  report(GBS_global_string("Ignored invalid bootstrap '%s' at root edge leading to a leaf", remark_branch.content()));
780  remove_remark();
781  type = REMARK_NONE;
782  }
783  else {
784  switch (brothersType) {
785  case REMARK_BOOTSTRAP: {
786  double averageBootstrap = (bootstrap + brothersBootstrap) / 2.0;
787  double diff = std::abs(bootstrap-brothersBootstrap);
788 
789  SmartCharPtr myOrgRemark = remark_branch;
790  SmartCharPtr brothersOrgRemark = brother->remark_branch;
791 
792  set_bootstrap(averageBootstrap);
793  type = parse_remark(remark_branch.content(), bootstrap);
794 
795  const double REMARKABLE_DIFF = 2.0;
796 #if defined(ASSERTION_USED)
797  const double EPSILON = 0.001 + 0.5; // "huge" EPSILON required, because set_bootstrap rounds value (causing 0.5 diff)
798  double diffToAverage = std::abs(bootstrap-averageBootstrap);
799  rt_assert(diffToAverage<EPSILON);
800  rt_assert(REMARKABLE_DIFF>EPSILON);
801 #endif
802 
803  if (diff>REMARKABLE_DIFF) { // only warn for reasonable difference
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()));
808  }
809  break;
810  }
811  case REMARK_OTHER:
812  case REMARK_NONE: {
813  // brother lacks bootstrap
814  const char *what = GBS_global_string("Using comment '%s' on both sides of root-edge", remark_branch.content());
815  const char *warning = brothersType == REMARK_NONE ? what : GBS_global_string("%s (had '%s')", what, brother->remark_branch.content());
816 
817  report(warning);
818  // -> use bootstrap of 'this' for both sons of root:
819  brother->use_as_remark(remark_branch);
820  break;
821  }
822  }
823  }
824  }
825  else if (brothersType == REMARK_BOOTSTRAP) {
826  rt_assert(!brother->is_leaf());
827  type = brother->parse_bootstrap(bootstrap, report);
828  }
829  // @@@ correct root remarks here. see code in TREE_load: ../SL/TREE_READ/TreeRead.cxx@CORR_ROOT_REM
830  }
831 #if defined(DEBUG)
832  else {
833  // avoid using parse_bootstrap while constructing tree
834  bool under_construction = father && !father->father; // otherwise would have entered the if-branch above
835  rt_assert(!under_construction); // fail if this tree is under construction
836  }
837 #endif
838 
839  return type;
840 }
841 void TreeNode::set_bootstrap(double bootstrap_percent) {
842  rt_assert(!is_leaf()); // only inner nodes may have bootstraps
843  rt_assert(!is_root_node()); // root nodes have no bootstrap values (because they do not have a parent branch)
844 
845  int bootstrap_rounded = int(bootstrap_percent+0.5);
846  if (bootstrap_rounded == 100) remove_remark();
847  else use_as_remark(GBS_global_string_copy("%i%%", bootstrap_rounded));
848 
849  if (is_son_of_root()) {
850  TreeNode *bro = get_brother();
851  if (!bro->is_leaf()) bro->use_as_remark(remark_branch);
852  }
853 }
854 
856  // fix node after one son has been deleted
857  TreeNode *result = NULp;
858 
859  if (leftson) {
861  result = get_leftson();
862  leftson = NULp;
863  }
864  else {
865  gb_assert(!leftson);
867 
868  result = get_rightson();
869  rightson = NULp;
870  }
871 
872  // now 'result' contains the lasting tree
873  result->father = father;
874 
875  // rescue remarks if possible
876  if (!is_leaf() && !result->is_leaf()) {
877  if (get_remark() && !result->get_remark()) {
878  result->use_as_remark(get_remark_ptr());
879  remove_remark();
880  }
881  }
882 
883  if (gb_node && !result->gb_node) { // rescue group if possible
884  result->gb_node = gb_node;
885  gb_node = NULp;
886  }
887 
888  if (!result->father) {
889  get_tree_root()->change_root(this, result);
890  }
891 
893 
894  forget_origin();
896  delete this;
897 
898  return result;
899 }
900 
902  if (this == other) return this;
903  if (is_ancestor_of(other)) return this;
904  if (other->is_ancestor_of(this)) return other;
905  return get_father()->ancestor_common_with(other->get_father());
906 }
907 
909  if (is_leaf()) return is_clade();
910  return get_leftson()->count_clades() + get_rightson()->count_clades() + is_clade();
911 }
912 
913 #if defined(ASSERTION_USED) || defined(PROVIDE_TREE_STRUCTURE_TESTS)
915  // tests whether the root-edge has a valid remark:
916  // - if one son is a leaf, the other son may contain the remark for the root-edge
917  // - if no son is a leaf, both sons shall contain the same remark (or none)
919  return implicated(!get_leftson()->is_leaf() && !get_rightson()->is_leaf(),
920  ARB_strNULLcmp(get_leftson()->get_remark(), get_rightson()->get_remark()) == 0);
921 }
922 
923 #endif
924 
925 // --------------------------------------------------------------------------------
926 
927 #ifdef UNIT_TESTS
928 #ifndef TEST_UNIT_H
929 #include <test_unit.h>
930 #endif
931 
932 void TEST_tree_iterator() {
933  GB_shell shell;
934  GBDATA *gb_main = GB_open("TEST_trees.arb", "r");
935  {
936  GB_transaction ta(gb_main);
937  TreeNode *tree = GBT_read_tree(gb_main, "tree_removal", new SimpleRoot);
938 
939  int leafs = GBT_count_leafs(tree);
940  TEST_EXPECT_EQUAL(leafs, 17);
942 
943  int iter_steps = ARB_edge::iteration_count(leafs);
944  TEST_EXPECT_EQUAL(iter_steps, 62);
945 
946  // test edge-cases of iteration_count:
947  {
948  TEST_EXPECT_EQUAL(ARB_edge::iteration_count(3), 6); // 3 leafs -> 4 nodes -> 3 edges in 2 directions -> 6 iterations
949  TEST_EXPECT_EQUAL(ARB_edge::iteration_count(2), 2); // 2 leafs -> 2 nodes -> 1 edge in 2 directions -> 2 iterations
950  TEST_EXPECT_EQUAL(ARB_edge::iteration_count(1), 0); // one leaf -> invalid tree -> will not iterate -> return 0
951  TEST_EXPECT_EQUAL(ARB_edge::iteration_count(0), 0); // no leafs -> invalid tree -> will not iterate -> return 0
952  }
953 
954  const ARB_edge start = rootEdge(tree->get_tree_root());
955 
956  // iterate forward + count (until same edge reached)
957  int count = 0;
958  int count_leafs = 0;
959  ARB_edge edge = start;
960  do {
961  ARB_edge next = edge.next();
962  TEST_EXPECT(next.previous() == edge); // test reverse operation
963  edge = next;
964  ++count;
965  if (edge.is_edge_to_leaf()) ++count_leafs;
966  }
967  while (edge != start);
968  TEST_EXPECT_EQUAL(count, iter_steps);
969  TEST_EXPECT_EQUAL(count_leafs, leafs);
970 
971  // iterate backward + count (until same edge reached)
972  count = 0;
973  count_leafs = 0;
974  edge = start;
975  do {
976  ARB_edge next = edge.previous();
977  TEST_EXPECT(next.next() == edge); // test reverse operation
978  edge = next;
979  ++count;
980  if (edge.is_edge_to_leaf()) ++count_leafs;
981  }
982  while (edge != start);
983  TEST_EXPECT_EQUAL(count, iter_steps);
984  TEST_EXPECT_EQUAL(count_leafs, leafs);
985 
986  if (tree) {
987  gb_assert(tree->is_root_node());
988  destroy(tree);
989  }
990  }
991  GB_close(gb_main);
992 }
993 
994 void TEST_tree_branch_modifications() {
995  GB_shell shell;
996  GBDATA *gb_main = GB_open("TEST_trees.arb", "r");
997  {
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);"; // bootstrap2branchlen
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%');"; // branchlen2bootstrap
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);";
1001 
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)"
1006 
1007  const char *newick_blXbs_2 = "(" LEFT_SWAP_EVEN ":.08," RIGHT_SWAP_EVEN ":.08);"; // branchlenXbootstrap
1008  const char *newick_blXbs_1 = "(" LEFT_SWAP_ODD "'16%':.5," RIGHT_SWAP_ODD "'16%':.5);"; // branchlenXbootstrap
1009 
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;"; // set_branchlength_preserving to 0.029 at CelBiazo
1012  const char *right_newick_preserved2 = "((((CorAquat:.084,CurCitre:.058):.103,CorGluta:.522)'17%':.041,CelBiazo:.117)'40%':.161,CytAquat:.711):.081;"; // set_branchlength_preserving to 0.117 at CelBiazo
1013 
1015 
1016  GB_transaction ta(gb_main);
1017 
1018  // test bootstrap2branchlen:
1019  {
1020  TreeNode *tree = GBT_read_tree(gb_main, "tree_test", new SimpleRoot);
1021  TEST_EXPECT_NEWICK(BSLEN, tree, newick);
1023  tree->bootstrap2branchlen();
1024  TEST_EXPECT_NEWICK(nLENGTH, tree, newick_bs2bl);
1026  destroy(tree);
1027  }
1028 
1029  // test branchlen2bootstrap:
1030  {
1031  TreeNode *tree = GBT_read_tree(gb_main, "tree_test", new SimpleRoot);
1032  TEST_EXPECT_NEWICK(BSLEN, tree, newick);
1033  tree->branchlen2bootstrap();
1034  TEST_EXPECT_NEWICK(nREMARK, tree, newick_bl2bs);
1036  destroy(tree);
1037  }
1038  // test branchlenXbootstrap:
1039  {
1040  TreeNode *tree = GBT_read_tree(gb_main, "tree_test", new SimpleRoot);
1041  TEST_EXPECT_NEWICK(BSLEN, tree, newick);
1042 
1043  TEST_EXPECT_DIFFERENT(newick_blXbs_2, newick); // did change due to rounding issues
1044 
1045  for (int repeat = 1; repeat<=3; ++repeat) {
1046  // swap operation stabilizes after 2 swaps
1047 
1048  tree->branchlenXbootstrap(); // 1st swap
1049  TEST_EXPECT_NEWICK(BSLEN, tree, newick_blXbs_1);
1051 
1052  tree->branchlenXbootstrap(); // 2nd swap
1053  TEST_EXPECT_NEWICK(BSLEN, tree, newick_blXbs_2);
1055  }
1056 
1057  destroy(tree);
1058  }
1059 
1060  {
1061  TreeNode *tree = GBT_read_tree(gb_main, "tree_test", new SimpleRoot);
1062 
1063  TreeNode *right = tree->get_rightson();
1064  TreeNode *CelBiazo = right->findLeafNamed("CelBiazo");
1065 
1067 
1068  TEST_EXPECT_NEWICK(BSLEN, right, right_newick);
1069 
1070  CelBiazo->set_branchlength_preserving(CelBiazo->get_branchlength() * 0.5);
1071  TEST_EXPECT_NEWICK(BSLEN, right, right_newick_preserved1);
1072 
1073  CelBiazo->set_branchlength_preserving(CelBiazo->get_branchlength() * 4.0);
1074  TEST_EXPECT_NEWICK(BSLEN, right, right_newick_preserved2);
1075 
1077 
1078  destroy(tree);
1079  }
1080  }
1081  GB_close(gb_main);
1082 }
1083 
1084 TEST_PUBLISH(TEST_tree_branch_modifications);
1085 
1086 #endif // UNIT_TESTS
1087 
1088 // --------------------------------------------------------------------------------
void set_bootstrap(double bootstrap)
Definition: TreeNode.cxx:841
void set_branchlength_unrooted(GBT_LEN newlen)
Definition: TreeNode.h:324
void set_updist(GBT_LEN UpDist)
Definition: TreeNode.cxx:310
string result
size_t GBT_count_leafs(const TreeNode *tree)
Definition: adtree.cxx:894
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
GB_TYPES type
virtual ~TreeRoot()
Definition: TreeNode.cxx:22
void virtually_distribute_length(GBT_LEN len, TreeNode::LengthCollector &collect) const
Definition: TreeNode.cxx:522
void bootstrap2branchlen()
Definition: TreeNode.cxx:708
void GB_warning(const char *message)
Definition: arb_msg.cxx:530
virtual void swap_sons()
Definition: TreeNode.h:620
#define implicated(hypothesis, conclusion)
Definition: arb_assert.h:289
TreeNode * findLeafNamed(const char *wantedName)
Definition: TreeNode.cxx:276
const TreeNode * get_root_node() const
Definition: TreeNode.h:475
virtual void set_root()
Definition: TreeNode.cxx:208
GBT_LEN get_branchlength_unrooted() const
Definition: TreeNode.h:317
virtual void compute_tree()=0
bool is_clade() const
Definition: TreeNode.h:547
POS_TREE1 * get_father() const
Definition: probe_tree.h:211
void forget_origin()
Definition: TreeNode.h:466
TreeRoot * get_tree_root() const
Definition: TreeNode.h:473
TreeNode * GBT_read_tree(GBDATA *gb_main, const char *tree_name, TreeRoot *troot)
Definition: adtree.cxx:889
ARB_edge inverse() const
Definition: TreeNode.h:861
#define DEFAULT_BRANCH_LENGTH
Definition: arbdbt.h:18
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
void warning(int warning_num, const char *warning_message)
Definition: util.cxx:61
ARB_edge previous() const
Definition: TreeNode.h:882
GBT_LEN length() const
Definition: TreeNode.h:840
TreeNode * son() const
Definition: TreeNode.h:837
ARB_edge rootEdge(TreeRoot *root)
Definition: TreeNode.h:965
CONSTEXPR_INLINE bool is_normal(const T &n)
Definition: arbtools.h:179
void use_as_remark(const SmartCharPtr &newRemark)
Definition: TreeNode.h:367
void branchlenXbootstrap()
Definition: TreeNode.cxx:743
int ARB_strNULLcmp(const char *s1, const char *s2)
Definition: arb_str.h:52
void reset_branchlengths()
Definition: TreeNode.cxx:680
GBT_LEN leftlen
Definition: TreeNode.h:224
TreeNode * rightson
Definition: TreeNode.h:223
bool has_valid_root_remarks() const
Definition: TreeNode.cxx:914
ARB_edge next() const
Definition: TreeNode.h:871
static HelixNrInfo * start
ARB_edge parentEdge(TreeNode *son)
Definition: TreeNode.h:950
GBT_RemarkType parse_remark(const char *remark, double &bootstrap)
Definition: TreeNode.h:136
CONSTEXPR_INLINE bool is_nan_or_inf(const T &n)
Definition: arbtools.h:178
POS_TREE1 * father
Definition: probe_tree.h:39
const double EPSILON
Definition: aw_position.hxx:73
#define TEST_PUBLISH(testfunction)
Definition: test_unit.h:1517
POS_TREE1 * get_father() const
Definition: probe_tree.h:49
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
void branchlen2bootstrap()
Definition: TreeNode.cxx:727
static int diff(int v1, int v2, int v3, int v4, int st, int en)
Definition: ClustalV.cxx:534
void add_parent_length(TreeNode *node, GBT_LEN addLen)
Definition: TreeNode.cxx:418
#define TEST_EXPECT(cond)
Definition: test_unit.h:1328
#define TEST_EXPECT_NEWICK(format, tree, expected_newick)
Definition: test_unit.h:1481
bool is_son_of_root() const
Definition: TreeNode.h:307
const TreeNode * ancestor_common_with(const TreeNode *other) const
Definition: TreeNode.cxx:901
bool is_leftson() const
Definition: TreeNode.h:280
CONSTEXPR_INLINE int leafs_2_edges(int leafs, TreeModel model)
Definition: arbdbt.h:62
GBT_RemarkType parse_bootstrap(double &bootstrap, WarningConsumer report)
Definition: TreeNode.cxx:763
char * GBS_trim(const char *str)
Definition: adstring.cxx:952
void multifurcate()
Definition: TreeNode.cxx:580
TreeNode * father
Definition: TreeNode.h:223
static void error(const char *msg)
Definition: mkptypes.cxx:96
bool is_root_node() const
Definition: TreeNode.h:486
CONSTEXPR_INLINE_Cxx14 void swap(unsigned char &c1, unsigned char &c2)
Definition: ad_io_inline.h:19
TreeNode * get_brother()
Definition: TreeNode.h:489
const ARB_edge & innermost_edge() const
Definition: TreeNode.cxx:394
EdgeFinder(TreeNode *rootNode)
Definition: TreeNode.cxx:372
void multifurcate_whole_tree(const multifurc_limits &below)
Definition: TreeNode.cxx:625
void set_downdist(GBT_LEN DownDist)
Definition: TreeNode.cxx:304
void rotate_subtree()
Definition: TreeNode.cxx:166
bool at_root() const
Definition: TreeNode.h:399
AP_tree_nlen * rootNode()
Definition: ap_main.hxx:54
NewickFormat
Definition: arbdb_base.h:68
CONSTEXPR_INLINE bool valid(SpeciesCreationMode m)
Definition: ed4_class.hxx:2248
TreeNode * leftson
Definition: TreeNode.h:223
GBT_RemarkType
Definition: arbdbt.h:30
void eliminate_parent_edge(TreeNode *node)
Definition: TreeNode.cxx:413
GBT_LEN rightlen
Definition: TreeNode.h:224
bool is_ancestor_of(const TreeNode *descendant) const
Definition: TreeNode.h:293
int count_clades() const
Definition: TreeNode.cxx:908
void reorder_tree(TreeOrder mode)
Definition: TreeNode.cxx:159
bool knownNonNull(const void *nonnull)
Definition: arb_assert.h:368
void remove_remark()
Definition: TreeNode.h:376
bool has_no_remark() const
Definition: TreeNode.h:381
#define rt_assert(cond)
Definition: TreeNode.h:22
bool is_edge_to_leaf() const
Definition: TreeNode.h:931
bool is_leaf() const
Definition: TreeNode.h:263
void set_branchlength_preserving(GBT_LEN new_len)
Definition: TreeNode.cxx:598
TreeNode * fixDeletedSon()
Definition: TreeNode.cxx:855
#define gb_assert(cond)
Definition: arbdbt.h:11
void multifurcate()
Definition: TreeNode.cxx:590
bool is_inside(const TreeNode *subtree) const
Definition: TreeNode.h:290
GBT_LEN get_updist() const
Definition: TreeNode.cxx:309
char * name
Definition: TreeNode.h:226
void subtitle(const char *stitle)
Definition: arb_progress.h:321
void scale_branchlengths(double factor)
Definition: TreeNode.cxx:689
void independent_distribution(bool useProgress)
Definition: TreeNode.cxx:423
#define abs(x)
Definition: f2c.h:151
TreeOrder
Definition: TreeNode.h:35
void set_tree_root(TreeRoot *new_root)
Definition: TreeNode.cxx:86
GBT_LEN sum_child_lengths() const
Definition: TreeNode.cxx:699
void remove_bootstrap()
Definition: TreeNode.cxx:646
ARB_edge counter_next() const
Definition: TreeNode.h:894
float GBT_LEN
Definition: arbdb_base.h:34
#define NULp
Definition: cxxforward.h:116
GBT_LEN get_downdist() const
Definition: TreeNode.cxx:303
GB_ERROR apply_aci_to_remarks(const char *aci, const GBL_call_env &callEnv)
Definition: TreeNode.cxx:654
ARB_edge find_innermost_edge()
Definition: TreeNode.cxx:397
#define TEST_EXPECT_DIFFERENT(expr, want)
Definition: test_unit.h:1301
NOT4PERL char * GB_command_interpreter_in_env(const char *str, const char *commands, const GBL_call_env &callEnv)
Definition: gb_aci.cxx:361
GBT_LEN get_branchlength() const
Definition: TreeNode.h:311
GB_transaction ta(gb_var)
void destroy(TreeNode *that)
Definition: TreeNode.h:667
GBDATA * gb_node
Definition: TreeNode.h:225
GBDATA * gb_main
Definition: adname.cxx:32
GBT_LEN eliminate()
Definition: TreeNode.h:853
virtual void change_root(TreeNode *old, TreeNode *newroot)
Definition: TreeNode.cxx:28
void set_length(GBT_LEN len)
Definition: TreeNode.h:844
const char * get_remark() const
Definition: TreeNode.h:357
const SmartCharPtr & get_remark_ptr() const
Definition: TreeNode.h:362
void forget_relatives()
Definition: TreeNode.h:467
void(* WarningConsumer)(const char *message)
Definition: arbdbt.h:84
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1294
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:194
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:655
static int iteration_count(int leafs_in_tree)
Definition: TreeNode.h:917
#define max(a, b)
Definition: f2c.h:154