@Test public void testOperator2() throws Exception { Tree tree; int taxaSize = 3; // make a caterpillar Node left = new ZeroBranchSANode(); left.setNr(0); left.setHeight(0.0); for (int i = 1; i < taxaSize; i++) { Node right = new ZeroBranchSANode(); right.setNr(i); right.setHeight(i); Node parent = new ZeroBranchSANode(); parent.setNr(taxaSize + i - 1); parent.setHeight(i); left.setParent(parent); parent.setLeft(left); right.setParent(parent); parent.setRight(right); left = parent; } left.setHeight(left.getRight().getHeight() + 2); tree = new Tree(left); System.out.println("Tree was = " + tree.getRoot().toShortNewick(false)); TreeDimensionJump operator = new TreeDimensionJump(); operator.initByName("tree", tree); double logHastingsRatio = operator.proposal(); System.out.println("Proposed tree = " + tree.getRoot().toShortNewick(false)); System.out.println("Log Hastings ratio = " + logHastingsRatio); }
/** * Method used by convertLengthToHeight(node) to remove negative offset from node heights that * is produced by convertLengthToHeight(node, height). * * @param node node of clade to offset * @param delta offset */ private void offset(final Node node, final double delta) { node.setHeight(node.getHeight() + delta); if (node.isLeaf()) { if (node.getHeight() < thresholdInput.get()) { node.setHeight(0); } } if (!node.isLeaf()) { offset(node.getLeft(), delta); if (node.getRight() != null) { offset(node.getRight(), delta); } } }
/** * Recursive method used to convert lengths to heights. Applied to the root, results in heights * from 0 to -total_height_of_tree. * * @param node node of a clade to convert * @param height Parent height. * @return total height of clade */ private double convertLengthToHeight(final Node node, final double height) { final double length = node.getHeight(); node.setHeight((height - length) * scaleInput.get()); if (node.isLeaf()) { return node.getHeight(); } else { final double left = convertLengthToHeight(node.getLeft(), height - length); if (node.getRight() == null) { return left; } final double right = convertLengthToHeight(node.getRight(), height - length); return Math.min(left, right); } }
/** * 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); }
@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); }
@Override public Node visitNode(NewickParser.NodeContext ctx) { Node node = newNode(); for (NewickParser.NodeContext ctxChild : ctx.node()) { node.addChild(visit(ctxChild)); } NewickParser.PostContext postCtx = ctx.post(); // Process metadata if (postCtx.meta() != null) { node.metaDataString = ""; for (int i = 0; i < postCtx.meta().attrib().size(); i++) { if (i > 0) node.metaDataString += ","; node.metaDataString += postCtx.meta().attrib().get(i).getText(); } if (!suppressMetadata) { for (NewickParser.AttribContext attribctx : postCtx.meta().attrib()) { String key = attribctx.attribKey.getText(); if (attribctx.attribValue().number() != null) { node.setMetaData(key, Double.parseDouble(attribctx.attribValue().number().getText())); } else if (attribctx.attribValue().STRING() != null) { String stringValue = attribctx.attribValue().STRING().getText(); if (stringValue.startsWith("\"") || stringValue.startsWith("\'")) ; stringValue = stringValue.substring(1, stringValue.length() - 1); node.setMetaData(key, stringValue); } else { // BEAST doesn't do anything with vectors yet. } } } } // Process edge length if (postCtx.length != null) node.setHeight(Double.parseDouble(postCtx.length.getText())); else node.setHeight(DEFAULT_LENGTH); // Process label node.setNr(-1); if (postCtx.label() != null) { node.setID(postCtx.label().getText()); if (postCtx.label().number() == null || postCtx.label().number().INT() == null) integerLeafLabels = false; // RRB: next line is for debugging only? @SuppressWarnings("unused") String postText = postCtx.getText(); // Treat labels as node numbers in certain situations if (!isLabelledNewickInput.get() && postCtx.label().number() != null && postCtx.label().number().INT() != null) { int nodeNr = Integer.parseInt(postCtx.label().getText()) - offsetInput.get(); if (nodeNr < 0) throw new ParseCancellationException( "Node number given " + "is smaller than current offset (" + offsetInput.get() + "). Perhaps offset is " + "too high?"); node.setNr(nodeNr); numberedNodeCount += 1; } else { if (node.isLeaf()) { node.setNr(getLabelIndex(postCtx.label().getText())); numberedNodeCount += 1; } } } if (node.getChildCount() == 1 && !allowSingleChildInput.get()) throw new ParseCancellationException("Node with single child found."); if (node.getChildCount() > 2) throw new ParseCancellationException("Node with two or more children found."); return node; }