net.maizegenetics.taxa.tree.SimpleNode Maven / Gradle / Ivy
// SimpleNode.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 net.maizegenetics.taxa.Taxon;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* data structure for a node (includes branch) in a binary/non-binary
* rooted/unrooted tree
*
* @version $Id: SimpleNode.java,v 1.1 2007/01/12 03:26:17 tcasstevens Exp $
*
* @author Korbinian Strimmer
* @author Alexei Drummond
*/
public class SimpleNode implements AttributeNode {
/**
* parent node
*/
private Node parent;
/**
* number of node as displayed
*/
private int number;
/**
* sequences associated with node
*/
private byte[] sequence;
/**
* length of branch to parent node
*/
private double length;
/**
* standard error of length of branch to parent node
*/
private double lengthSE;
/**
* height of this node
*/
private double height;
/**
* identifier of node/associated branch
*/
private Taxon identifier;
/**
* the attributes associated with this node.
*/
private Hashtable attributes = null;
//
// Private stuff
//
private Node[] child;
//
// Serialization Stuff
//
static final long serialVersionUID = 3472432765038556717L;
//serialver -classpath ./classes net.maizegenetics.pal.tree.SimpleNode
/**
* I like doing things my self!
*/
private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
out.writeByte(3); //Version number
out.writeObject(parent);
out.writeInt(number);
out.writeObject(sequence);
out.writeDouble(length);
out.writeDouble(lengthSE);
out.writeDouble(height);
out.writeObject(identifier);
out.writeObject(child);
out.writeObject(attributes);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
byte version = in.readByte();
switch (version) {
case 1: {
parent = (Node) in.readObject();
number = in.readInt();
sequence = (byte[]) in.readObject();
Object partial = (double[][][]) in.readObject();
length = in.readDouble();
lengthSE = in.readDouble();
height = in.readDouble();
in.readDouble();
identifier = (Taxon) in.readObject();
child = (Node[]) in.readObject();
break;
}
case 2: {
//attributes are transient
parent = (Node) in.readObject();
number = in.readInt();
sequence = (byte[]) in.readObject();
length = in.readDouble();
lengthSE = in.readDouble();
height = in.readDouble();
identifier = (Taxon) in.readObject();
child = (Node[]) in.readObject();
break;
}
default: {
//attributes are not transient!
parent = (Node) in.readObject();
number = in.readInt();
sequence = (byte[]) in.readObject();
length = in.readDouble();
lengthSE = in.readDouble();
height = in.readDouble();
identifier = (Taxon) in.readObject();
child = (Node[]) in.readObject();
attributes = (Hashtable) in.readObject();
}
}
}
// the following constructors should eventually become
// "friendly" to prevent anyone calling them directly.
// Instead, the NodeFactory should be used!
/**
* constructor default node
*/
public SimpleNode() {
parent = null;
child = null;
length = 0.0;
lengthSE = 0.0;
height = 0.0;
identifier = Taxon.ANONYMOUS;
number = 0;
sequence = null;
}
public SimpleNode(String name, double branchLength) {
this();
identifier = new Taxon(name);
length = branchLength;
}
/**
* Constructor
*
* @param children
* @param branchLength
* @throws IllegalArgumentException if only one child!
*/
protected SimpleNode(Node[] children, double branchLength) {
this();
this.child = children;
if (children.length == 1) {
throw new IllegalArgumentException("Must have more than one child!");
}
for (int i = 0; i < child.length; i++) {
child[i].setParent(this);
}
this.length = branchLength;
}
protected SimpleNode(Node[] children) {
this(children, BranchLimits.MINARC);
}
/**
* constructor used to clone a node and all children
*/
public SimpleNode(Node n) {
this(n, true);
}
public void reset() {
parent = null;
child = null;
length = 0.0;
lengthSE = 0.0;
height = 0.0;
identifier = Taxon.ANONYMOUS;
number = 0;
sequence = null;
}
public SimpleNode(Node n, boolean keepIds) {
init(n, keepIds);
for (int i = 0; i < n.getChildCount(); i++) {
addChild(new SimpleNode(n.getChild(i), keepIds));
}
}
public SimpleNode(Node n, LabelMapping lm) {
init(n, true, lm);
for (int i = 0; i < n.getChildCount(); i++) {
addChild(new SimpleNode(n.getChild(i), lm));
}
}
protected void init(Node n) {
init(n, true);
}
/**
* Initialized node instance variables based on given Node. children are
* ignored.
*/
protected void init(Node n, boolean keepId) {
init(n, keepId, null);
}
/**
* Initialized node instance variables based on given Node. children are
* ignored.
*
* @param lm - may be null
*/
protected void init(Node n, boolean keepId, LabelMapping lm) {
parent = null;
length = n.getBranchLength();
lengthSE = n.getBranchLengthSE();
height = n.getNodeHeight();
if (keepId) {
if (lm != null) {
identifier = lm.getLabelIdentifier(n.getIdentifier());
} else {
identifier = n.getIdentifier();
}
} else {
identifier = Taxon.ANONYMOUS;
}
number = n.getNumber();
sequence = n.getSequence();
if (n instanceof AttributeNode) {
AttributeNode attNode = (AttributeNode) n;
Enumeration e = attNode.getAttributeNames();
while ((e != null) && e.hasMoreElements()) {
String name = (String) e.nextElement();
setAttribute(name, attNode.getAttribute(name));
}
}
child = null;
}
/**
* Returns the parent node of this node.
*/
public final Node getParent() {
return parent;
}
/**
* Set the parent node of this node.
*/
public void setParent(Node node) {
parent = node;
}
/**
* removes parent.
*/
public final void removeParent() {
parent = null;
}
/**
* Returns the sequence at this node, in the form of a String.
*/
public String getSequenceString() {
return new String(sequence);
}
/**
* Returns the sequence at this node, in the form of an array of bytes.
*/
public byte[] getSequence() {
return sequence;
}
/**
* Sets the sequence at this node, in the form of an array of bytes.
*/
public void setSequence(byte[] s) {
sequence = s;
}
/**
* Get the length of the branch attaching this node to its parent.
*/
public final double getBranchLength() {
return length;
}
/**
* Set the length of the branch attaching this node to its parent.
*/
public final void setBranchLength(double value) {
length = value;
}
/**
* Get the length SE of the branch attaching this node to its parent.
*/
public final double getBranchLengthSE() {
return lengthSE;
}
/**
* Set the length SE of the branch attaching this node to its parent.
*/
public final void setBranchLengthSE(double value) {
lengthSE = value;
}
/**
* Get the height of this node relative to the most recent node.
*/
public final double getNodeHeight() {
return height;
}
/**
* Set the height of this node relative to the most recent node.
*
* @note corrects children branch lengths
*/
public final void setNodeHeight(double value) {
if (value < 0) {
height = -value;
} else {
height = value;
}
/*if(child!=null) {
for(int i = 0 ; i= numChildren) {
throw new IllegalArgumentException("Nonexistent child");
}
Node[] newChild = new Node[numChildren - 1];
for (int i = 0; i < n; i++) {
newChild[i] = child[i];
}
for (int i = n; i < numChildren - 1; i++) {
newChild[i] = child[i + 1];
}
Node removed = child[n];
//remove parent link from removed child!
removed.setParent(null);
child = newChild;
return removed;
}
/**
* determines the height of this node and its descendants from branch
* lengths, assuming contemporaneous tips.
*/
public void lengths2HeightsContemp() {
double largestHeight = 0.0;
if (!isLeaf()) {
for (int i = 0; i < getChildCount(); i++) {
NodeUtils.lengths2Heights(getChild(i));
double newHeight
= getChild(i).getNodeHeight() + getChild(i).getBranchLength();
if (newHeight > largestHeight) {
largestHeight = newHeight;
}
}
}
setNodeHeight(largestHeight);
}
/**
* Sets a named attribute to the given value.
*
* @param name the name of the attribute
* @param value the value to set the attribute
*/
public final void setAttribute(String name, Object value) {
if (attributes == null) {
attributes = new Hashtable();
}
attributes.put(name, value);
}
/**
* @return the attribute with the given name or null if it doesn't exist.
* @param name the name of the attribute.
*/
public final Object getAttribute(String name) {
if (attributes == null) {
return null;
}
return attributes.get(name);
}
/**
* @return an enumeration of the attributes that this node has or null if
* the node has no attributes.
*/
public final Enumeration getAttributeNames() {
if (attributes == null) {
return null;
}
return attributes.keys();
}
/**
* Returns the number of children this node has.
*/
public final int getChildCount() {
if (child == null) {
return 0;
}
return child.length;
}
public String toString() {
StringWriter sw = new StringWriter();
try {
NodeUtils.printNH(new PrintWriter(sw), this, true, false, 0, false);
} catch (Exception e) {
e.printStackTrace();
}
return sw.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy