private boolean pickNarrow() {
    zNode = speciesTreeNodes[nLeafNodes + Randomizer.nextInt(nInternalNodes)];
    while (zNode.getLeft().isLeaf() && zNode.getRight().isLeaf()) {
      zNode = speciesTreeNodes[nLeafNodes + Randomizer.nextInt(nInternalNodes)];
    }

    yNode = zNode.getLeft();
    cNode = zNode.getRight();
    if (yNode.getHeight() < cNode.getHeight()) {
      yNode = zNode.getRight();
      cNode = zNode.getLeft();
    }

    if (yNode.isLeaf()) {
      return false;
    } else if (Randomizer.nextBoolean()) {
      aNode = yNode.getLeft();
      bNode = yNode.getRight();
    } else {
      aNode = yNode.getRight();
      bNode = yNode.getLeft();
    }

    return true;
  }
예제 #2
0
 /**
  * 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);
     }
   }
 }
예제 #3
0
 /**
  * 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);
   }
 }
  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 boolean pickWide() {
    final int nNodesExceptRoot = nSpeciesNodes - 1;
    final Node rootNode = speciesTreeNodes[nNodesExceptRoot];

    // pick an internal node at random (excluding the root)
    final int yNodeNumber = nLeafNodes + Randomizer.nextInt(nInternalNodes - 1);
    yNode = speciesTreeNodes[yNodeNumber];
    final double yNodeHeight = yNode.getHeight();
    if (Randomizer.nextBoolean()) {
      aNode = yNode.getLeft();
      bNode = yNode.getRight();
    } else {
      aNode = yNode.getRight();
      bNode = yNode.getLeft();
    }

    // for all internal nodes (excluding the root)
    final Node[] zNodes = new Node[nNodesExceptRoot];

    czNodeFinder(yNode, rootNode, yNodeHeight, zNodes);

    // pick a cousin from the available candidates
    int cousinNodeNumber = Randomizer.nextInt(nNodesExceptRoot);
    zNode = zNodes[cousinNodeNumber];
    while (zNode == null) {
      cousinNodeNumber = Randomizer.nextInt(nNodesExceptRoot);
      // System.out.println(String.format("%d/%d", cousinNodeNumber, nNodesExceptRoot));
      zNode = zNodes[cousinNodeNumber];
    }

    cNode = speciesTreeNodes[cousinNodeNumber];

    return true;
  }
예제 #6
0
 /**
  * extract coalescent times and tip information into array times from beast.tree.
  *
  * @param tree the beast.tree
  * @param times the times of the nodes in the beast.tree
  * @param childCounts the number of children of each node
  */
 protected static void collectTimes(Tree tree, double[] times, int[] childCounts) {
   Node[] nodes = tree.getNodesAsArray();
   for (int i = 0; i < nodes.length; i++) {
     Node node = nodes[i];
     times[i] = node.getHeight();
     childCounts[i] = node.isLeaf() ? 0 : 2;
   }
 }
 // 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;
   }
 }
  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;
      }
    }
  }
예제 #9
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);
  }
  // identify nodes to be moved as part of a coordinated exchange move
  private boolean findMovedPairs(
      Node geneTreeNode,
      Map<Node, Node> movedNodes,
      Set<String> chosenDescendants,
      double lowerHeight,
      double upperHeight) {
    if (geneTreeNode.isLeaf()) {
      final String descendantName = geneTreeNode.getID();
      // returns true if this leaf is a descendant of the chosen species
      return chosenDescendants.contains(descendantName);
    }

    final Node leftChild = geneTreeNode.getLeft();
    final Node rightChild = geneTreeNode.getRight();

    // left child descendants are exclusively descendants of the chosen species tree node
    final boolean leftExclusive =
        findMovedPairs(leftChild, movedNodes, chosenDescendants, lowerHeight, upperHeight);
    // right child descendants are exclusively descendants of the chosen species tree node
    final boolean rightExclusive =
        findMovedPairs(rightChild, movedNodes, chosenDescendants, lowerHeight, upperHeight);

    final double nodeHeight = geneTreeNode.getHeight();
    if (nodeHeight >= lowerHeight && nodeHeight < upperHeight) {
      if (leftExclusive ^ rightExclusive) {
        if (leftExclusive) { // leave right child attached to original parent
          movedNodes.put(geneTreeNode, rightChild);
        } else { // leaf left child attached to original parent
          movedNodes.put(geneTreeNode, leftChild);
        }
      }
    }

    // returns true if all descendants of this gene tree node are also descendants of the chosen
    // species tree node
    return leftExclusive && rightExclusive;
  }