@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);
  }
  // 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;
  }
Example #3
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;
   }
 }
Example #4
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);
  }
Example #5
0
  /** Ensure the class behaves properly, even when inputs are not specified. */
  @Override
  public void initAndValidate() throws Exception {
    boolean sortNodesAlphabetically = false;

    if (dataInput.get() != null) {
      labels = dataInput.get().getTaxaNames();
    } else if (m_taxonset.get() != null) {
      if (labels == null) {
        labels = m_taxonset.get().asStringList();
      } else { // else labels were set by TreeParser c'tor
        sortNodesAlphabetically = true;
      }
    } else {
      if (isLabelledNewickInput.get()) {
        if (m_initial.get() != null) {
          labels = m_initial.get().getTaxonset().asStringList();
        } else {
          labels = new ArrayList<>();
          createUnrecognizedTaxa = true;
          sortNodesAlphabetically = true;
        }
      } else {
        if (m_initial.get() != null) {
          // try to pick up taxa from initial tree
          final Tree tree = m_initial.get();
          if (tree.m_taxonset.get() != null) {
            labels = tree.m_taxonset.get().asStringList();
          } else {
            // m_sLabels = null;
          }
        } else {
          // m_sLabels = null;
        }
      }
      //            m_bIsLabelledNewick = false;
    }
    final String newick = newickInput.get();
    if (newick == null || newick.equals("")) {
      // can happen while initalising Beauti
      final Node dummy = new Node();
      setRoot(dummy);
    } else {
      try {
        setRoot(parseNewick(newickInput.get()));
      } catch (ParseCancellationException e) {
        throw new RuntimeException(
            "TreeParser cannot make sense of the Newick string "
                + "provided.  It gives the following clue:\n"
                + e.getMessage());
      }
    }

    super.initAndValidate();

    if (sortNodesAlphabetically) {
      // correct for node ordering: ensure order is alphabetical
      for (int i = 0; i < getNodeCount() && i < labels.size(); i++) {
        m_nodes[i].setID(labels.get(i));
      }

      Node[] nodes = new Node[labels.size()];
      System.arraycopy(m_nodes, 0, nodes, 0, labels.size());

      Arrays.sort(nodes, (o1, o2) -> o1.getID().compareTo(o2.getID()));
      for (int i = 0; i < labels.size(); i++) {
        m_nodes[i] = nodes[i];
        nodes[i].setNr(i);
      }
    }

    if (m_initial.get() != null) processTraits(m_initial.get().m_traitList.get());
    else processTraits(m_traitList.get());

    if (timeTraitSet != null) {
      adjustTreeNodeHeights(root);
    } else if (adjustTipHeightsInput.get()) {

      double treeLength = TreeUtils.getTreeLength(this, getRoot());

      double extraTreeLength = 0.0;
      double maxTipHeight = 0.0;

      // all nodes should be at zero height if no date-trait is available
      for (int i = 0; i < getLeafNodeCount(); i++) {
        double height = getNode(i).getHeight();
        if (maxTipHeight < height) {
          maxTipHeight = height;
        }
        extraTreeLength += height;
        getNode(i).setHeight(0);
      }

      double scaleFactor = (treeLength + extraTreeLength) / treeLength;

      final double SCALE_FACTOR_THRESHOLD = 0.001;

      // if the change in total tree length is more than 0.1% then give the user a warning!
      if (scaleFactor > 1.0 + SCALE_FACTOR_THRESHOLD) {

        DecimalFormat format = new DecimalFormat("#.##");

        Log.info.println(
            "WARNING: Adjust tip heights attribute set to 'true' in " + getClass().getSimpleName());
        Log.info.println(
            "         has resulted in significant (>"
                + format.format(SCALE_FACTOR_THRESHOLD * 100.0)
                + "%) change in tree length.");
        Log.info.println(
            "         Use "
                + adjustTipHeightsInput.getName()
                + "='false' to override this default.");
        Log.info.printf("  original max tip age = %8.3f\n", maxTipHeight);
        Log.info.printf("       new max tip age = %8.3f\n", 0.0);
        Log.info.printf("  original tree length = %8.3f\n", treeLength);
        Log.info.printf("       new tree length = %8.3f\n", treeLength + extraTreeLength);
        Log.info.printf("       TL scale factor = %8.3f\n", scaleFactor);
      }
    }

    if (m_taxonset.get() == null && labels != null && isLabelledNewickInput.get()) {
      m_taxonset.setValue(new TaxonSet(Taxon.createTaxonList(labels)), this);
    }

    initStateNodes();
  } // init
  /**
   * override this for proposals,
   *
   * @return log of Hastings Ratio, or Double.NEGATIVE_INFINITY if proposal should not be accepted *
   */
  @Override
  public double proposal() {
    testing = isTestInput.get();
    speciesTreeNodes = speciesTree.getNodesAsArray();
    nLeafNodes = speciesTree.getLeafNodeCount();
    nInternalNodes = speciesTree.getInternalNodeCount();
    nSpeciesNodes = speciesTree.getNodeCount();

    boolean isNarrow = isNarrowInput.get();
    double logHastingsRatio = 0.0;
    if (isNarrow) {
      // only proceed to rearrange gene trees if the species tree can be changed
      // doesn't execute if testing
      if (!testing && !pickNarrow()) return Double.NEGATIVE_INFINITY;

      int validGP = 0;
      for (int i = nLeafNodes; i < nSpeciesNodes; ++i) {
        validGP += isg(speciesTree.getNode(i));
      }

      final int c2 = sisg(yNode) + sisg(cNode);

      fillNodes(); // fills in movedNodes and graftNodes
      pruneAndRegraft(yNode, cNode, bNode);

      final int validGPafter = validGP - c2 + sisg(yNode) + sisg(cNode);

      logHastingsRatio += Math.log(validGP) - Math.log(validGPafter);
    } else {
      // only proceed to rearrange gene trees if the species tree can be changed
      // doesn't execute if testing
      if (!testing && !pickWide()) return Double.NEGATIVE_INFINITY;

      fillNodes(); // fills in movedNodes and graftNodes
      pruneAndRegraft(yNode, cNode, bNode);
    }

    for (final Tree geneTree : geneTreeInput.get())
      geneTree.startEditing(null); // hack to stop beast.core.State.Trie memory leak

    for (int i = 0; i < czBranchCount; i++) {
      final List<SortedMap<Node, Node>> perBranchMovedNodes = movedNodes.get(i);
      final SetMultimap<Integer, Node> perBranchGraftNodes = graftNodes.get(i);
      final double logForward = rearrangeGeneTrees(perBranchMovedNodes, perBranchGraftNodes, true);
      assert logForward != Double.NEGATIVE_INFINITY;
      if (logForward == Double.NEGATIVE_INFINITY) return Double.NEGATIVE_INFINITY;
      else logHastingsRatio += logForward;
    }

    // compute reverse move (Hastings ratio denominator)
    final Node bNodeTmp = bNode;
    final Node cNodeTmp = cNode;

    bNode = cNodeTmp;
    cNode = bNodeTmp;

    fillNodes(); // fills in movedNodes and graftNodes for reverse move

    for (int i = 0; i < czBranchCount; i++) {
      final List<SortedMap<Node, Node>> perBranchMovedNodes = movedNodes.get(i);
      final SetMultimap<Integer, Node> perBranchGraftNodes = graftNodes.get(i);
      final double logReverse = rearrangeGeneTrees(perBranchMovedNodes, perBranchGraftNodes, false);
      assert logReverse != Double.NEGATIVE_INFINITY;
      if (logReverse == Double.NEGATIVE_INFINITY) return Double.NEGATIVE_INFINITY;
      else logHastingsRatio -= logReverse;
    }

    return logHastingsRatio;
  }
Example #7
0
  /** Recalculates all the intervals for the given beast.tree. */
  @SuppressWarnings("unchecked")
  protected void calculateIntervals() {
    Tree tree = treeInput.get();

    final int nodeCount = tree.getNodeCount();

    times = new double[nodeCount];
    int[] childCounts = new int[nodeCount];

    collectTimes(tree, times, childCounts);

    indices = new int[nodeCount];

    HeapSort.sort(times, indices);

    if (intervals == null || intervals.length != nodeCount) {
      intervals = new double[nodeCount];
      lineageCounts = new int[nodeCount];
      lineagesAdded = new List[nodeCount];
      lineagesRemoved = new List[nodeCount];
      //            lineages = new List[nodeCount];

      storedIntervals = new double[nodeCount];
      storedLineageCounts = new int[nodeCount];

    } else {
      for (List<Node> l : lineagesAdded) {
        if (l != null) {
          l.clear();
        }
      }
      for (List<Node> l : lineagesRemoved) {
        if (l != null) {
          l.clear();
        }
      }
    }

    // start is the time of the first tip
    double start = times[indices[0]];
    int numLines = 0;
    int nodeNo = 0;
    intervalCount = 0;
    while (nodeNo < nodeCount) {

      int lineagesRemoved = 0;
      int lineagesAdded = 0;

      double finish = times[indices[nodeNo]];
      double next;

      do {
        final int childIndex = indices[nodeNo];
        final int childCount = childCounts[childIndex];
        // don't use nodeNo from here on in do loop
        nodeNo += 1;
        if (childCount == 0) {
          addLineage(intervalCount, tree.getNode(childIndex));
          lineagesAdded += 1;
        } else {
          lineagesRemoved += (childCount - 1);

          // record removed lineages
          final Node parent = tree.getNode(childIndex);
          // assert childCounts[indices[nodeNo]] == beast.tree.getChildCount(parent);
          // for (int j = 0; j < lineagesRemoved + 1; j++) {
          for (int j = 0; j < childCount; j++) {
            Node child = j == 0 ? parent.getLeft() : parent.getRight();
            removeLineage(intervalCount, child);
          }

          // record added lineages
          addLineage(intervalCount, parent);
          // no mix of removed lineages when 0 th
          if (multifurcationLimit == 0.0) {
            break;
          }
        }

        if (nodeNo < nodeCount) {
          next = times[indices[nodeNo]];
        } else break;
      } while (Math.abs(next - finish) <= multifurcationLimit);

      if (lineagesAdded > 0) {

        if (intervalCount > 0 || ((finish - start) > multifurcationLimit)) {
          intervals[intervalCount] = finish - start;
          lineageCounts[intervalCount] = numLines;
          intervalCount += 1;
        }

        start = finish;
      }

      // add sample event
      numLines += lineagesAdded;

      if (lineagesRemoved > 0) {

        intervals[intervalCount] = finish - start;
        lineageCounts[intervalCount] = numLines;
        intervalCount += 1;
        start = finish;
      }
      // coalescent event
      numLines -= lineagesRemoved;
    }

    intervalsKnown = true;
  }