@Override public Node visitTree(@NotNull NewickParser.TreeContext ctx) { Node root = visit(ctx.node()); // Ensure tree is properly sorted in terms of node numbers. root.sort(); // Replace lengths read from Newick with heights. convertLengthToHeight(root); // Make sure internal nodes are numbered correctly numberUnnumberedNodes(root); // Check for duplicate taxa BitSet nodeNrSeen = new BitSet(); for (Node leaf : root.getAllLeafNodes()) { if (leaf.getNr() < 0) continue; // Skip unnumbered leaves if (nodeNrSeen.get(leaf.getNr())) throw new ParseCancellationException( "Duplicate taxon found: " + labels.get(leaf.getNr())); else nodeNrSeen.set(leaf.getNr()); } return root; }
/** * Obtain the sister of node "child" having parent "parent". * * @param parent the parent * @param child the child that you want the sister of * @return the other child of the given parent. */ protected Node getOtherChild(Node parent, Node child) { if (parent.getLeft().getNr() == child.getNr()) { return parent.getRight(); } else { return parent.getLeft(); } }
@Override public double getRateForBranch(Node node) { if (needsUpdate) { update(); } return branchRates[node.getNr()]; }
/** * Number any nodes in a clade which were not explicitly numbered by the parsed string. * * @param node clade parent */ private void numberUnnumberedNodes(Node node) { if (node.isLeaf()) return; for (Node child : node.getChildren()) { numberUnnumberedNodes(child); } if (node.getNr() < 0) node.setNr(numberedNodeCount); numberedNodeCount += 1; }
/** * Given a map of name translations (string to string), rewrites all leaf ids that match a key in * the map to the respective value in the matching key/value pair. If current leaf id is null, * then interpret translation keys as node numbers (origin 1) and set leaf id of node n to * map.get(n-1). * * @param translationMap map of name translations */ public void translateLeafIds(final Map<String, String> translationMap) { for (final Node leaf : getExternalNodes()) { String id = leaf.getID(); if (id == null || !integerLeafLabels) { id = Integer.toString(leaf.getNr() + 1); } final String newId = translationMap.get(id); if (newId != null) { leaf.setID(newId); } } }
// identify nodes to be grafted in a narrow move, and children to be "disowned" (joined directly // to their grandparent) private List<SortedMap<Node, Node>> getMovedPairs( final double lowerHeight, final double upperHeight) { final int aNodeNumber = aNode.getNr(); final Set<String> chosenDescendants = findDescendants(aNode, aNodeNumber); final List<SortedMap<Node, Node>> allMovedNodes = new ArrayList<>(); final List<Tree> geneTrees = geneTreeInput.get(); for (int j = 0; j < nGeneTrees; j++) { final Node geneTreeRootNode = geneTrees.get(j).getRoot(); final SortedMap<Node, Node> jMovedNodes = new TreeMap<>(nhc); findMovedPairs(geneTreeRootNode, jMovedNodes, chosenDescendants, lowerHeight, upperHeight); allMovedNodes.add(jMovedNodes); } return allMovedNodes; }
// identify nodes that can serve as graft branches as part of a coordinated exchange move protected SetMultimap<Integer, Node> getGraftBranches(Node yNode) { final int yNumber = yNode.getNr(); final Set<String> cousinDescendants = findDescendants(yNode, yNumber); final SetMultimap<Integer, Node> allGraftBranches = HashMultimap.create(); final List<Tree> geneTrees = geneTreeInput.get(); for (int j = 0; j < nGeneTrees; j++) { final Tree geneTree = geneTrees.get(j); final Node geneTreeRootNode = geneTree.getRoot(); final Set<Node> jGraftBranches = new LinkedHashSet<>(); findGraftBranches(geneTreeRootNode, jGraftBranches, cousinDescendants); allGraftBranches.putAll(j, jGraftBranches); } return allGraftBranches; }
private List<Integer> czNodeFinder( final Node parentNode, final Node currentNode, final double parentNodeHeight, final Node[] zNodes) { // valid graft nodes (nodes defining branches which include the height of the parent node) final List<Integer> candidateList = new ArrayList<>(); final double currentNodeHeight = currentNode.getHeight(); if (parentNode == currentNode) { return null; } else if (parentNodeHeight >= currentNodeHeight) { // this is a candidate node (would be a valid choice to graft parentNode to) candidateList.add(currentNode.getNr()); return candidateList; } else { final List<Integer> leftCandidateNodeNumbers = czNodeFinder(parentNode, currentNode.getLeft(), parentNodeHeight, zNodes); final List<Integer> rightCandidateNodeNumbers = czNodeFinder(parentNode, currentNode.getRight(), parentNodeHeight, zNodes); if (leftCandidateNodeNumbers == null) { // parent is the left child or descendant of the left child // therefore the current node is the most recent common ancestor connecting the parent and // right candidates for (final Integer candidateNodeNumber : rightCandidateNodeNumbers) { zNodes[candidateNodeNumber] = currentNode; } return null; } else if (rightCandidateNodeNumbers == null) { // parent is the right child or descendant of the right child // therefore the current node is the most recent common ancestor connecting the parent and // left candidates for (final Integer candidateNodeNumber : leftCandidateNodeNumbers) { zNodes[candidateNodeNumber] = currentNode; } return null; } else { candidateList.addAll(leftCandidateNodeNumbers); candidateList.addAll(rightCandidateNodeNumbers); return candidateList; } } }