/**
   * 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;
   }
 }
Example #7
0
  @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);
  }