package beast.evolution.tree; import java.io.PrintStream; import beast.core.CalculationNode; import beast.core.Description; import beast.core.Function; import beast.core.Input; import beast.core.Input.Validate; import beast.core.util.Log; import beast.core.Loggable; @Description("Logger to report statistics of a tree") public class TreeStatLogger extends CalculationNode implements Loggable, Function { final public Input<Tree> treeInput = new Input<>("tree", "tree to report height for.", Validate.REQUIRED); @Deprecated final public Input<Boolean> logHeigthInput = new Input<>("logHeigth", "If true, tree height will be logged (unless logHeight input = false).", true); final public Input<Boolean> logHeightInput = new Input<>("logHeight", "If true, tree height will be logged.", true); final public Input<Boolean> logLengthInput = new Input<>("logLength", "If true, tree length will be logged.", true); @Override public void initAndValidate() { if ((!logHeigthInput.get() || !logHeightInput.get()) && !logLengthInput.get()) { Log.warning.println("TreeStatLogger " + getID() + "logs nothing. Set logHeight=true or logLength=true to log at least something"); } } @Override public void init(PrintStream out) { final Tree tree = treeInput.get(); if (logHeigthInput.get() && logHeightInput.get()) { out.print(tree.getID() + ".height\t"); } if (logLengthInput.get()) { out.print(tree.getID() + ".treeLength\t"); } } @Override public void log(int sample, PrintStream out) { final Tree tree = treeInput.get(); if (logHeigthInput.get() && logHeightInput.get()) { out.print(tree.getRoot().getHeight() + "\t"); } if (logLengthInput.get()) { out.print(getLength(tree) + "\t"); } } private double getLength(Tree tree) { double length = 0; for (Node node : tree.getNodesAsArray()) { if (!node.isRoot()) { length += node.getLength(); } } return length; } @Override public void close(PrintStream out) { // nothing to do } @Override public int getDimension() { return 2; } @Override public double getArrayValue() { return treeInput.get().getRoot().getHeight(); } @Override public double getArrayValue(int dim) { if (dim == 0) { return treeInput.get().getRoot().getHeight(); } return getLength(treeInput.get()); } }