/*
* TreeUtils.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* BEAST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.app.beauti.util;
import dr.evolution.tree.MutableTree;
import dr.evolution.tree.NodeRef;
import dr.evolution.tree.Tree;
import dr.evolution.util.Date;
import dr.evolution.util.Taxon;
import dr.evolution.util.TimeScale;
import dr.stats.Variate;
/**
* Class for getting information from trees.
*
* @author Andrew Rambaut
* @author Alexei Drummond
* @version $Id: TreeUtils.java,v 1.7 2005/07/11 14:07:25 rambaut Exp $
*/
public class TreeUtils {
/**
* Gets the root to tip distances from a tree.
*/
public static void getRootToTipDistances(Tree tree, Variate distances) {
double rootHeight = tree.getNodeHeight(tree.getRoot());
double height;
for (int i = 0; i < tree.getExternalNodeCount(); i++) {
height = tree.getNodeHeight(tree.getExternalNode(i));
distances.add(rootHeight - height);
}
}
/**
* Gets the tip dates from a tree.
*/
public static void getTipDates(Tree tree, Variate dates) {
for (int i = 0; i < tree.getExternalNodeCount(); i++) {
Taxon taxon = tree.getNodeTaxon(tree.getExternalNode(i));
Object date = taxon.getAttribute("date");
if (date != null) {
if (date instanceof Date) {
dates.add(((Date) date).getTimeValue());
} else {
try {
dates.add(Double.parseDouble(date.toString()));
} catch (NumberFormatException nfe) {
dates.add(0.0);
}
}
} else {
dates.add(0.0);
}
}
}
/**
* Gets the root to tip distances from a node.
*/
public static void getRootToTipDistances(Tree tree, NodeRef node, double rootHeight,
Variate distances) {
if (tree.isExternal(node)) {
double height = tree.getNodeHeight(node);
distances.add(rootHeight - height);
} else {
getRootToTipDistances(tree, tree.getChild(node, 0), rootHeight, distances);
getRootToTipDistances(tree, tree.getChild(node, 1), rootHeight, distances);
}
}
/**
* Gets the tip dates from a node.
*/
public static void getTipDates(Tree tree, NodeRef node, Variate dates) {
if (tree.isExternal(node)) {
String date = (String) tree.getNodeTaxon(node).getAttribute("date");
if (date != null) {
dates.add(Double.parseDouble(date));
} else {
dates.add(0.0);
}
} else {
getTipDates(tree, tree.getChild(node, 0), dates);
getTipDates(tree, tree.getChild(node, 1), dates);
}
}
/**
* Returns -1 if there is no number suffix
*/
public static double guessDate(String s) {
int i = s.length();
char c;
do {
i--;
c = s.charAt(i);
} while (i >= 0 && (Character.isDigit(c) || c == '.'));
if (i == s.length()) {
return 0.0;
}
return Double.parseDouble(s.substring(i + 1));
}
/**
* Sets the tip heights from the tip dates
*/
public static void setHeightsFromDates(MutableTree tree) {
dr.evolution.util.Date mostRecent = null;
for (int i = 0; i < tree.getExternalNodeCount(); i++) {
Taxon taxon = tree.getNodeTaxon(tree.getExternalNode(i));
dr.evolution.util.Date date = (dr.evolution.util.Date) taxon.getAttribute("date");
if (date != null) {
if ((mostRecent == null) || date.after(mostRecent)) {
mostRecent = date;
}
}
}
TimeScale timeScale = new TimeScale(mostRecent.getUnits(), true, mostRecent.getAbsoluteTimeValue());
for (int i = 0; i < tree.getExternalNodeCount(); i++) {
NodeRef node = tree.getExternalNode(i);
Taxon taxon = tree.getNodeTaxon(node);
dr.evolution.util.Date date = (dr.evolution.util.Date) taxon.getAttribute("date");
if (date != null) {
double height = timeScale.convertTime(date.getTimeValue(), date);
tree.setNodeHeight(node, height);
} else {
tree.setNodeHeight(node, 0.0);
}
}
adjustInternalHeights(tree, tree.getRoot());
if (mostRecent != null) {
tree.setUnits(mostRecent.getUnits());
}
}
// **************************************************************
// Private static methods
// **************************************************************
private static void adjustInternalHeights(MutableTree tree, NodeRef node) {
if (!tree.isExternal(node)) {
// pre-order recursion
for (int i = 0; i < tree.getChildCount(node); i++) {
adjustInternalHeights(tree, tree.getChild(node, i));
}
}
NodeRef parent = tree.getParent(node);
if (parent != null) {
if (tree.getNodeHeight(parent) < tree.getNodeHeight(node)) {
tree.setNodeHeight(parent, tree.getNodeHeight(node));
}
}
}
}