package beast.evolution.speciation;
import java.util.List;
import beast.core.Description;
import beast.core.Input;
import beast.core.Input.Validate;
import beast.evolution.tree.Node;
import beast.evolution.tree.RandomTree;
import beast.evolution.tree.Tree;
import beast.evolution.tree.coalescent.PopulationFunction;
@Description("Generates a random gene tree conditioned on a species tree, such " +
"that the root of the species tree is lower than any coalescent events in " +
"the gene tree")
public class RandomGeneTree extends RandomTree {
final public Input<Tree> speciesTreeInput = new Input<>("speciesTree", "The species tree in which this random gene tree needs to fit", Validate.REQUIRED);
@Override
public void initAndValidate() {
super.initAndValidate();
}
@Override
public Node simulateCoalescentWithMax(List<Node> nodes, PopulationFunction demographic, final double maxHeight) {
// sanity check - disjoint trees
// if( ! Tree.Utils.allDisjoint(nodes) ) {
// throw new RuntimeException("non disjoint trees");
// }
if (nodes.size() == 0) {
throw new IllegalArgumentException("empty nodes set");
}
final double lowestHeight = speciesTreeInput.get().getRoot().getHeight();
for (int attempts = 0; attempts < 1000; ++attempts) {
try {
final List<Node> rootNode = simulateCoalescent(nodes, demographic, lowestHeight, maxHeight);
if (rootNode.size() == 1) {
return rootNode.get(0);
}
} catch (ConstraintViolatedException e) {
// TODO: handle exception
}
}
throw new RuntimeException("failed to merge trees after 1000 tries!");
}
}