Root any tree by locating the "center" of tree and adding a new root node at that point for any point on the tree x let D(x) = Max{distance between x and t : for all tips t} The "center" c is the point with the smallest distance, i.e. D(c) = min{ D(x) : x in tree } @param tree to root @return
(RootedTree tree)
| 607 | * @return rooted tree |
| 608 | */ |
| 609 | public static RootedTree rootTreeAtCenter(RootedTree tree) { |
| 610 | // Method - find the pair of tips with the longest distance. It is easy to see that the center |
| 611 | // is at the midpoint of the path between them. |
| 612 | |
| 613 | HashMap<HashPair<Node>, Double> dists = new LinkedHashMap<HashPair<Node>, Double>(); |
| 614 | try { |
| 615 | double maxDistance = -Double.MAX_VALUE; |
| 616 | // node on maximal path |
| 617 | Node current = null; |
| 618 | // next node on maximal path |
| 619 | Node direction = null; |
| 620 | |
| 621 | // locate one terminal node of longest path |
| 622 | for (Node e : tree.getExternalNodes()) { |
| 623 | for (Node n : tree.getAdjacencies(e)) { |
| 624 | final double d = dist(tree, e, n, dists); |
| 625 | if (d > maxDistance) { |
| 626 | maxDistance = d; |
| 627 | current = e; |
| 628 | direction = n; |
| 629 | } |
| 630 | } |
| 631 | } |
| 632 | |
| 633 | // traverse along maximal path to it's middle |
| 634 | double distanceLeft = maxDistance / 2.0; |
| 635 | |
| 636 | while (true) { |
| 637 | final double len = tree.getEdgeLength(current, direction); |
| 638 | if (distanceLeft <= len) { |
| 639 | //System.out.println(toNewick(rtree)); |
| 640 | return new ReRootedTree(tree, current, direction, distanceLeft); |
| 641 | } |
| 642 | distanceLeft -= len; |
| 643 | |
| 644 | maxDistance = -Double.MAX_VALUE; |
| 645 | Node next = null; |
| 646 | for (Node n : tree.getAdjacencies(direction)) { |
| 647 | if (n == current) continue; |
| 648 | final double d = dist(tree, direction, n, dists); |
| 649 | if (d > maxDistance) { |
| 650 | maxDistance = d; |
| 651 | next = n; |
| 652 | } |
| 653 | } |
| 654 | current = direction; |
| 655 | direction = next; |
| 656 | } |
| 657 | } catch (Graph.NoEdgeException e1) { |
| 658 | return null; // serious bug, should not happen |
| 659 | } |
| 660 | } |
| 661 | |
| 662 | private static double dist(Tree tree, Node root, Node node, Map<HashPair<Node>, Double> dists) throws Graph.NoEdgeException { |
| 663 | HashPair<Node> p = new HashPair<Node>(root, node); |
no test coverage detected