net.maizegenetics.taxa.tree.SimpleTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tassel Show documentation
Show all versions of tassel Show documentation
TASSEL is a software package to evaluate traits associations, evolutionary patterns, and linkage
disequilibrium.
The newest version!
// SimpleTree.java
//
// (c) 1999-2001 PAL Development Core Team
//
// This package may be distributed under the
// terms of the Lesser GNU General Public License (LGPL)
package net.maizegenetics.taxa.tree;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Hashtable;
import net.maizegenetics.taxa.Taxon;
/**
* data structure for a binary/non-binary rooted/unrooted trees
*
* @author Alexei Drummond
* @author Korbinian Strimmer
*
*/
public class SimpleTree implements Tree, Serializable {
/**
* root node
*/
private Node root;
/**
* list of internal nodes (including root)
*/
private Node[] internalNode = null;
/**
* number of internal nodes (including root)
*/
private int numInternalNodes;
/**
* list of external nodes
*/
private Node[] externalNode = null;
/**
* number of external nodes
*/
private int numExternalNodes;
/**
* attributes attached to this tree.
*/
private Hashtable[] attributes = null;
/**
* holds the units of the trees branches.
*/
private int units = EXPECTED_SUBSTITUTIONS;
//
// Serialization Stuff
//
static final long serialVersionUID = -7330318631600898531L;
//serialver -classpath ./classes net.maizegenetics.pal.tree.SimpleTree
/**
* I like doing things my self!
*/
private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
out.writeByte(1); //Version number
out.writeObject(root);
out.writeObject(attributes);
out.writeInt(units);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
byte version = in.readByte();
switch (version) {
default: {
root = (Node) in.readObject();
createNodeList();
attributes = (Hashtable[]) in.readObject();
units = in.readInt();
}
}
}
/**
* constructor tree consisting solely of root node
*/
public SimpleTree() {
// Default configuration
root = new SimpleNode();
//root.setIdentifier(new Taxon("ROOT"));
root.setBranchLength(0.0);
root.setBranchLengthSE(0.0);
}
/**
* constructor taking a root node
*/
public SimpleTree(Node r) {
root = r;
createNodeList();
}
/**
* clone constructor
*/
public SimpleTree(Tree tree) {
root = new SimpleNode(tree.getRoot());
setUnits(tree.getUnits());
createNodeList();
}
/**
* clone constructor
*/
public SimpleTree(Tree tree, boolean keepIdentifiers) {
root = new SimpleNode(tree.getRoot(), keepIdentifiers);
setUnits(tree.getUnits());
createNodeList();
}
/**
* clone constructor
*
* @param lm - a label mapping use for translating the original label names
* into something else
*/
public SimpleTree(Tree tree, LabelMapping lm) {
root = new SimpleNode(tree.getRoot(), lm);
setUnits(tree.getUnits());
createNodeList();
}
/**
* Return the units that this tree is expressed in.
*/
public final int getUnits() {
return units;
}
/**
* Sets the units that this tree is expressed in.
*/
public final void setUnits(int units) {
this.units = units;
}
/**
* Returns the number of external nodes.
*/
public final int getExternalNodeCount() {
if (externalNode == null) {
createNodeList();
}
return numExternalNodes;
}
/**
* Returns the ith external node.
*/
public final Node getExternalNode(int i) {
if (externalNode == null) {
createNodeList();
}
return externalNode[i];
}
/**
* Returns the number of internal nodes.
*/
public final int getInternalNodeCount() {
if (internalNode == null) {
createNodeList();
}
return numInternalNodes;
}
/**
* Returns the ith internal node.
*/
public final Node getInternalNode(int i) {
if (internalNode == null) {
createNodeList();
}
return internalNode[i];
}
/**
* Returns the root node of this tree.
*/
public final Node getRoot() {
return root;
}
/**
* Set a new node as root node.
*/
public final void setRoot(Node r) {
root = r;
createNodeList();
}
/**
* count and list external and internal nodes and compute heights of each
* node
*/
public void createNodeList() {
numInternalNodes = 0;
numExternalNodes = 0;
Node node = root;
do {
node = NodeUtils.postorderSuccessor(node);
if (node.isLeaf()) {
node.setNumber(numExternalNodes);
numExternalNodes++;
} else {
node.setNumber(numInternalNodes);
numInternalNodes++;
}
} while (node != root);
internalNode = new Node[numInternalNodes];
externalNode = new Node[numExternalNodes];
node = root;
do {
node = NodeUtils.postorderSuccessor(node);
if (node.isLeaf()) {
externalNode[node.getNumber()] = node;
} else {
internalNode[node.getNumber()] = node;
}
} while (node != root);
// compute heights if it seems necessary
if (root.getNodeHeight() == 0.0) {
NodeUtils.lengths2Heights(root);
}
}
public String toString() {
StringWriter sw = new StringWriter();
try {
NodeUtils.printNH(new PrintWriter(sw), getRoot(), true, false, 0, false);
sw.write(";");
} catch (Exception e) {
e.printStackTrace();
}
return sw.toString();
}
/**
* return node with number num (as displayed in ASCII tree)
*
* @param num number of node
*
* @return node
*/
public Node findNode(int num) {
createNodeList();
if (num <= numExternalNodes) {
return externalNode[num - 1];
} else {
return internalNode[num - 1 - numExternalNodes];
}
}
private int getIndex(Node node) {
if (node.isLeaf()) {
return node.getNumber();
}
return getExternalNodeCount() + node.getNumber();
}
/**
* Sets an named attribute for a given node.
*
* @param node the node whose attribute is being set.
* @param name the name of the attribute.
* @param value the new value of the attribute.
*/
public void setAttribute(Node node, String name, Object value) {
if (node instanceof AttributeNode) {
((AttributeNode) node).setAttribute(name, value);
} else {
int index = getIndex(node);
if (attributes == null) {
attributes = new Hashtable[getExternalNodeCount() + getInternalNodeCount()];
}
if (attributes[index] == null) {
attributes[index] = new Hashtable();
}
attributes[index].put(name, value);
}
}
@Override
public int whichIdNumber(Taxon t) {
for (int i = 0; i < this.getExternalNodeCount(); i++) {
if (t.equals(getExternalNode(i).getIdentifier())) {
return i;
}
}
return -1;
}
/**
* @return an object representing the named attributed for the numbered
* node.
* @param node the node being interrogated.
* @param name the name of the attribute of interest.
*/
public Object getAttribute(Node node, String name) {
if (node instanceof AttributeNode) {
return ((AttributeNode) node).getAttribute(name);
} else {
int index = getIndex(node);
if (attributes == null || attributes[index] == null) {
return null;
}
return attributes[index].get(name);
}
}
/**
* make node with number num to root node
*
* @param num number of node
*/
public void reroot(int num) {
TreeUtils.reroot(this, findNode(num));
}
/**
* make provided node the root node
*
* @param node the node to make the root.
*/
public void reroot(Node node) {
TreeUtils.reroot(this, node);
}
public void report(Writer out) throws IOException {
TreeUtils.report(this, out);
}
public Tree getCopy() {
return new SimpleTree(this);
}
}