// Path: src/beast/evolution/tree/TreeWOffset.java
// public class TreeWOffset extends CalculationNode {
// 	
// 	public Input<Tree> treeInput = new Input<Tree> ("tree", "tree topology", Validate.REQUIRED);
// 	public Input<Double> offsetInput = new Input<Double>("offset", "Starting offset to present, default 0", 0.0);
// 	
// 	Tree tree;
// 	Double oldOffset, offset;
// 	Double[] oldHeights, leaves_heights;
// 	int oldMin_leaf, min_leaf;
// 	private boolean stored = false;
// 	
// 	@Override
// 	public void initAndValidate() {
// 		tree = treeInput.get();
// 		offset = offsetInput.get();
// 		
// 		leaves_heights = new Double[tree.getLeafNodeCount()];
// 		for(int i = 0; i < tree.getLeafNodeCount(); i++) {
// 			double h = tree.getNode(i).getHeight();
// 			if(h == 0) min_leaf = i;
// 			leaves_heights[i] = h + offset;
// 		}
// 	}
// 	
// 	public double getHeightOfNode(int nr) {
// 		return tree.getNode(nr).getHeight() + offset;
// 	}
// 	
// 	public void setHeightOfLeaf(int nr, double height) {
// 		store();
// 		
// 		double oldOffset = offset;
// 		if(height < offset) {
// 			offset = height;
// 			min_leaf = nr;
// 		}
// 		leaves_heights[nr] = height;
// 		// if we increased the height of the minimum leaf then which one it is may have changed
// 		if(height > offset && nr == min_leaf) {
// 			offset = height;
// 			for(int i = 0; i < leaves_heights.length; i++) {
// 				if(leaves_heights[i] < offset) {
// 					min_leaf = i;
// 					offset = leaves_heights[i];
// 				}
// 			}
// 		}
// 		// if offset has changed then all heights need to be updated to keep true heights the same
// 		if(Math.abs(oldOffset - offset) > 0) {
// 			for(Node n : tree.getNodesAsArray()) n.setHeight(n.getHeight() + oldOffset - offset);
// 		}
// 	}
// 	
// 	public double getOffset() {
// 		return offset;
// 	}
// 
// 	public Tree getTree() {
// 		return tree;
// 	}
// 
// 	public void setHeightOfNode(int nr, double height) {
// 		Node n = tree.getNode(nr);
// 		if(n.isLeaf()) this.setHeightOfLeaf(nr, height);
// 		n.setHeight(height - offset);
// 	}
// 	
// 	// for testing purposes
// 	public double getStoredHeightOfLeaf(int nr) {
// 		return leaves_heights[nr];
// 	}
// 	
// 	/* This entire section is to work around the fact that this class is modified DURING the operator proposal of SampledNodeDateRandomWalker
// 	 * whereas Beast2 assumes that only state nodes are modified, and that calculation nodes are only updated afterwards
// 	 * So, using the default mechanic will store/restore the modified state not the original one
// 	 * There is probably a better way to do this
// 	 */ 
// 	
// 	@Override
// 	public void store() {
// 		super.store();
// 		if(stored) return;
// 		oldMin_leaf = min_leaf;
// 		oldOffset = offset;
// 		oldHeights = leaves_heights.clone();
// 		stored = true;
// 	}
// 	
// 	@Override
// 	public void restore() {
// 		super.restore();
// 		min_leaf = oldMin_leaf;
// 		offset = oldOffset;
// 		leaves_heights = oldHeights.clone();
// 		stored = false;
// 	}
// 	
// 	@Override
// 	public void accept() {
// 		super.accept();
// 		stored = false;
// 	}
// }


import beast.core.*;
import beast.core.parameter.IntegerParameter;
import beast.core.parameter.RealParameter;
import beast.core.util.Log;
import beast.evolution.alignment.Taxon;
import beast.evolution.operators.*;
import beast.evolution.tree.Node;
import beast.evolution.tree.Tree;
import beast.evolution.tree.TreeDistribution;
import beast.evolution.tree.TreeInterface;
import beast.evolution.tree.TreeWOffset;
import java.util.List;
package beast.evolution.speciation;



/**
 * @author Alexandra Gavryushkina
 */

//The tree density is from: Tanja Stadler et al. "Estimating the Basic Reproductive Number from Viral Sequence Data"

@Description("Calculate tree density under Birth Death Sampling Through Time Model for Epidemics " +
        "that is the BDM where an individual is sampled at a time with a constant rate psi" +
        " and where an individual becomes noninfectious immediately after the sampling" +
        "with a constant probability r")
@Citation(value = "Gavryushkina A, Welch D, Stadler T, Drummond AJ (2014) \n" +
        "Bayesian inference of sampled ancestor trees for epidemiology and fossil calibration. \n" +
        "PLoS Comput Biol 10(12): e1003919. doi:10.1371/journal.pcbi.1003919",
        year = 2014, firstAuthorSurname = "Gavryushkina", DOI="10.1371/journal.pcbi.1003919")
public class SABirthDeathModel extends TreeDistribution {

	public Input<TreeWOffset> treeWOffsetInput =
            new Input<TreeWOffset>("treeWOffset", "Optional fully extinct tree", (TreeWOffset)null);
	
    //'direct' parameters
    public Input<RealParameter> originInput =
            new Input<RealParameter>("origin", "The time when the process started", (RealParameter)null);
// Path: src/beast/evolution/tree/TreeWOffset.java
// public class TreeWOffset extends CalculationNode {
// 	
// 	public Input<Tree> treeInput = new Input<Tree> ("tree", "tree topology", Validate.REQUIRED);
// 	public Input<Double> offsetInput = new Input<Double>("offset", "Starting offset to present, default 0", 0.0);
// 	
// 	Tree tree;
// 	Double oldOffset, offset;
// 	Double[] oldHeights, leaves_heights;
// 	int oldMin_leaf, min_leaf;
// 	private boolean stored = false;
// 	
// 	@Override
// 	public void initAndValidate() {
// 		tree = treeInput.get();
// 		offset = offsetInput.get();
// 		
// 		leaves_heights = new Double[tree.getLeafNodeCount()];
// 		for(int i = 0; i < tree.getLeafNodeCount(); i++) {
// 			double h = tree.getNode(i).getHeight();
// 			if(h == 0) min_leaf = i;
// 			leaves_heights[i] = h + offset;
// 		}
// 	}
// 	
// 	public double getHeightOfNode(int nr) {
// 		return tree.getNode(nr).getHeight() + offset;
// 	}
// 	
// 	public void setHeightOfLeaf(int nr, double height) {
// 		store();
// 		
// 		double oldOffset = offset;
// 		if(height < offset) {
// 			offset = height;
// 			min_leaf = nr;
// 		}
// 		leaves_heights[nr] = height;
// 		// if we increased the height of the minimum leaf then which one it is may have changed
// 		if(height > offset && nr == min_leaf) {
// 			offset = height;
// 			for(int i = 0; i < leaves_heights.length; i++) {
// 				if(leaves_heights[i] < offset) {
// 					min_leaf = i;
// 					offset = leaves_heights[i];
// 				}
// 			}
// 		}
// 		// if offset has changed then all heights need to be updated to keep true heights the same
// 		if(Math.abs(oldOffset - offset) > 0) {
// 			for(Node n : tree.getNodesAsArray()) n.setHeight(n.getHeight() + oldOffset - offset);
// 		}
// 	}
// 	
// 	public double getOffset() {
// 		return offset;
// 	}
// 
// 	public Tree getTree() {
// 		return tree;
// 	}
// 
// 	public void setHeightOfNode(int nr, double height) {
// 		Node n = tree.getNode(nr);
// 		if(n.isLeaf()) this.setHeightOfLeaf(nr, height);
// 		n.setHeight(height - offset);
// 	}
// 	
// 	// for testing purposes
// 	public double getStoredHeightOfLeaf(int nr) {
// 		return leaves_heights[nr];
// 	}
// 	
// 	/* This entire section is to work around the fact that this class is modified DURING the operator proposal of SampledNodeDateRandomWalker
// 	 * whereas Beast2 assumes that only state nodes are modified, and that calculation nodes are only updated afterwards
// 	 * So, using the default mechanic will store/restore the modified state not the original one
// 	 * There is probably a better way to do this
// 	 */ 
// 	
// 	@Override
// 	public void store() {
// 		super.store();
// 		if(stored) return;
// 		oldMin_leaf = min_leaf;
// 		oldOffset = offset;
// 		oldHeights = leaves_heights.clone();
// 		stored = true;
// 	}
// 	
// 	@Override
// 	public void restore() {
// 		super.restore();
// 		min_leaf = oldMin_leaf;
// 		offset = oldOffset;
// 		leaves_heights = oldHeights.clone();
// 		stored = false;
// 	}
// 	
// 	@Override
// 	public void accept() {
// 		super.accept();
// 		stored = false;
// 	}
// }


// Path: src/beast/evolution/speciation/SABirthDeathModel.java
import beast.core.*;
import beast.core.parameter.IntegerParameter;
import beast.core.parameter.RealParameter;
import beast.core.util.Log;
import beast.evolution.alignment.Taxon;
import beast.evolution.operators.*;
import beast.evolution.tree.Node;
import beast.evolution.tree.Tree;
import beast.evolution.tree.TreeDistribution;
import beast.evolution.tree.TreeInterface;
import beast.evolution.tree.TreeWOffset;
import java.util.List;

package beast.evolution.speciation;



/**
 * @author Alexandra Gavryushkina
 */

//The tree density is from: Tanja Stadler et al. "Estimating the Basic Reproductive Number from Viral Sequence Data"

@Description("Calculate tree density under Birth Death Sampling Through Time Model for Epidemics " +
        "that is the BDM where an individual is sampled at a time with a constant rate psi" +
        " and where an individual becomes noninfectious immediately after the sampling" +
        "with a constant probability r")
@Citation(value = "Gavryushkina A, Welch D, Stadler T, Drummond AJ (2014) \n" +
        "Bayesian inference of sampled ancestor trees for epidemiology and fossil calibration. \n" +
        "PLoS Comput Biol 10(12): e1003919. doi:10.1371/journal.pcbi.1003919",
        year = 2014, firstAuthorSurname = "Gavryushkina", DOI="10.1371/journal.pcbi.1003919")
public class SABirthDeathModel extends TreeDistribution {

	public Input<TreeWOffset> treeWOffsetInput =
            new Input<TreeWOffset>("treeWOffset", "Optional fully extinct tree", (TreeWOffset)null);
	
    //'direct' parameters
    public Input<RealParameter> originInput =
            new Input<RealParameter>("origin", "The time when the process started", (RealParameter)null);
    public Input<RealParameter> birthRateInput =