/** * Disconnect edge <node,node.getParent()> by joining node's sister directly to node's grandmother * and adding all colour changes previously on <node.getParent(),node.getParent().getParent()> to * the new branch. * * @param node */ public void disconnectBranch(Node node) { // Check argument validity: Node parent = node.getParent(); if (node.isRoot() || parent.isRoot()) throw new IllegalArgumentException("Illegal argument to " + "disconnectBranch()."); Node sister = getOtherChild(parent, node); // Add colour changes originally attached to parent to those attached // to node's sister: for (int idx = 0; idx < ((MultiTypeNode) parent).getChangeCount(); idx++) { int colour = ((MultiTypeNode) parent).getChangeType(idx); double time = ((MultiTypeNode) parent).getChangeTime(idx); ((MultiTypeNode) sister).addChange(colour, time); } // Implement topology change. replace(parent.getParent(), parent, sister); // Clear colour changes from parent: ((MultiTypeNode) parent).clearChanges(); // Ensure BEAST knows to update affected likelihoods: parent.makeDirty(Tree.IS_FILTHY); sister.makeDirty(Tree.IS_FILTHY); node.makeDirty(Tree.IS_FILTHY); }
/** * Disconnect node from root, discarding all colouring on <node,root> and <node's sister,root>. * * @param node */ public void disconnectBranchFromRoot(Node node) { // Check argument validity: if (node.isRoot() || !node.getParent().isRoot()) throw new IllegalArgumentException("Illegal argument to" + " disconnectBranchFromRoot()."); // Implement topology change: Node parent = node.getParent(); Node sister = getOtherChild(parent, node); sister.setParent(null); parent.getChildren().remove(sister); // Clear colour changes on new root: ((MultiTypeNode) sister).clearChanges(); // Ensure BEAST knows to update affected likelihoods: parent.makeDirty(Tree.IS_FILTHY); sister.makeDirty(Tree.IS_FILTHY); node.makeDirty(Tree.IS_FILTHY); }
/** * Creates a new branch between node and a new node at time destTime between destBranchBase and * its parent. Colour changes are divided between the two new branches created by the split. * * @param node * @param destBranchBase * @param destTime */ public void connectBranch(Node node, Node destBranchBase, double destTime) { // Check argument validity: if (node.isRoot() || destBranchBase.isRoot()) throw new IllegalArgumentException("Illegal argument to " + "connectBranch()."); // Obtain existing parent of node and set new time: Node parent = node.getParent(); parent.setHeight(destTime); MultiTypeNode mtParent = (MultiTypeNode) parent; MultiTypeNode mtDestBranchBase = (MultiTypeNode) destBranchBase; // Determine where the split comes in the list of colour changes // attached to destBranchBase: int split; for (split = 0; split < mtDestBranchBase.getChangeCount(); split++) if (mtDestBranchBase.getChangeTime(split) > destTime) break; // Divide colour changes between new branches: mtParent.clearChanges(); for (int idx = split; idx < mtDestBranchBase.getChangeCount(); idx++) mtParent.addChange(mtDestBranchBase.getChangeType(idx), mtDestBranchBase.getChangeTime(idx)); mtDestBranchBase.truncateChanges(split); // Set colour at split: mtParent.setNodeType(mtDestBranchBase.getFinalType()); // Implement topology changes: replace(destBranchBase.getParent(), destBranchBase, parent); destBranchBase.setParent(parent); if (parent.getLeft() == node) parent.setRight(destBranchBase); else if (parent.getRight() == node) parent.setLeft(destBranchBase); // Ensure BEAST knows to update affected likelihoods: node.makeDirty(Tree.IS_FILTHY); parent.makeDirty(Tree.IS_FILTHY); destBranchBase.makeDirty(Tree.IS_FILTHY); }
private double rearrangeGeneTrees( List<SortedMap<Node, Node>> branchMovedNodes, SetMultimap<Integer, Node> branchGraftNodes, boolean forwardMove) { double logHastingsRatio = 0.0; for (int j = 0; j < nGeneTrees; j++) { final Set<Node> jForwardGraftNodes = branchGraftNodes.get(j); final SortedMap<Node, Node> jForwardMovedNodes = branchMovedNodes.get(j); for (final Entry<Node, Node> nodePair : jForwardMovedNodes.entrySet()) { final Node movedNode = nodePair.getKey(); final Node disownedChild = nodePair.getValue(); final double movedNodeHeight = movedNode.getHeight(); final List<Node> validGraftBranches = new ArrayList<>(); int forwardGraftCount = 0; for (Node potentialGraft : jForwardGraftNodes) { final double potentialGraftBottom = potentialGraft.getHeight(); double potentialGraftTop; if (potentialGraft.isRoot()) { potentialGraftTop = Double.POSITIVE_INFINITY; } else { potentialGraftTop = potentialGraft.getParent().getHeight(); } if (movedNodeHeight > potentialGraftBottom && movedNodeHeight < potentialGraftTop) { forwardGraftCount++; validGraftBranches.add(potentialGraft); } } // no compatible branches to graft this node on to // this only occurs when there is missing data and the gene tree root is in the "parent" // branch // or if two gene tree nodes which need moving are of equal height if (forwardGraftCount == 0) { return Double.NEGATIVE_INFINITY; } else { logHastingsRatio += Math.log(forwardGraftCount); if (forwardMove) { // only actually change gene trees if this is the forward move final Node chosenGraft = validGraftBranches.get(Randomizer.nextInt(forwardGraftCount)); pruneAndRegraft(movedNode, chosenGraft, disownedChild); } } } } return logHastingsRatio; }
private static void pruneAndRegraft( final Node nodeToMove, final Node newChild, final Node disownedChild) { final Node sourceParent = nodeToMove.getParent(); final Node destinationParent = newChild.getParent(); // debug string // System.out.println(String.format("%d-%d-%d > %d-%d", parent.getNr(), nodeToMove.getNr(), // disownedChild.getNr(), destinationParent.getNr(), newChild.getNr())); nodeToMove.removeChild(disownedChild); sourceParent.removeChild(nodeToMove); destinationParent.removeChild(newChild); nodeToMove.addChild(newChild); sourceParent.addChild(disownedChild); destinationParent.addChild(nodeToMove); nodeToMove.makeDirty(Tree.IS_FILTHY); sourceParent.makeDirty(Tree.IS_FILTHY); destinationParent.makeDirty(Tree.IS_FILTHY); newChild.makeDirty(Tree.IS_FILTHY); disownedChild.makeDirty(Tree.IS_FILTHY); }
// fills forward nodes by destination branch (c through z) private void fillNodes() { // must be done before any changes are made to the gene or species trees Node childNode = cNode; movedNodes = new ArrayList<>(); graftNodes = new ArrayList<>(); czBranchCount = 0; while (childNode != zNode) { czBranchCount++; final Node parentNode = childNode.getParent(); final double childNodeHeight = childNode.getHeight(); final double parentNodeHeight = parentNode.getHeight(); final List<SortedMap<Node, Node>> perBranchMovedNodes = getMovedPairs(childNodeHeight, parentNodeHeight); final SetMultimap<Integer, Node> perBranchGraftNodes = getGraftBranches(childNode); movedNodes.add(0, perBranchMovedNodes); // needs to be added in reverse order graftNodes.add(0, perBranchGraftNodes); // because nodes must be grafted oldest to youngest childNode = parentNode; } }
@Override public double proposal() { Tree tree = treeInput.get(this); // randomly select leaf node int i = Randomizer.nextInt(taxonIndices.length); Node node = tree.getNode(taxonIndices[i]); double upper = node.getParent().getHeight(); // double lower = 0.0; // final double newValue = (Randomizer.nextDouble() * (upper -lower)) + lower; // scale node double scale = (scaleFactor + (Randomizer.nextDouble() * ((1.0 / scaleFactor) - scaleFactor))); final double newValue = node.getHeight() * scale; // check the tree does not get negative branch lengths if (newValue > upper) { return Double.NEGATIVE_INFINITY; } node.setHeight(newValue); return -Math.log(scale); }
/** * Set up node's parent as the new root with a height of destTime, with oldRoot as node's new * sister. * * @param node * @param oldRoot * @param destTime */ public void connectBranchToRoot(Node node, Node oldRoot, double destTime) { // Check argument validity: if (node.isRoot() || !oldRoot.isRoot()) throw new IllegalArgumentException("Illegal argument " + "to connectBranchToRoot()."); // Obtain existing parent of node and set new time: Node newRoot = node.getParent(); newRoot.setHeight(destTime); // Implement topology changes: newRoot.setParent(null); if (newRoot.getLeft() == node) newRoot.setRight(oldRoot); else if (newRoot.getRight() == node) newRoot.setLeft(oldRoot); oldRoot.setParent(newRoot); // Ensure BEAST knows to recalculate affected likelihood: newRoot.makeDirty(Tree.IS_FILTHY); oldRoot.makeDirty(Tree.IS_FILTHY); node.makeDirty(Tree.IS_FILTHY); }