// 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 de.ugoe.cs.autoquest.tasktrees.alignment.pal.tree; import java.util.ArrayList; import java.util.logging.Level; import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.NumberSequence; import de.ugoe.cs.autoquest.tasktrees.alignment.pal.misc.Identifier; import de.ugoe.cs.util.console.Console; /** * * @version $Id: SimpleNode.java,v 1.20 2002/01/14 04:16:53 matt Exp $ * * @author Korbinian Strimmer * @author Alexei Drummond */ public class FengDoolittleNode implements Node { /** parent node */ private Node parent; /** number of node as displayed */ private int number; /** sequences associated with node */ private ArrayList sequences; /** 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 Identifier identifier; private Node[] child; // the following constructors should eventually become // "friendly" to prevent anyone calling them directly. // Instead, the NodeFactory should be used! /** constructor default node */ public FengDoolittleNode() { parent = null; child = null; length = 0.0; lengthSE = 0.0; height = 0.0; identifier = Identifier.ANONYMOUS; number = 0; sequences = new ArrayList(); } public FengDoolittleNode(String name, double branchLength) { this(); identifier = new Identifier(name); length = branchLength; } public void reset() { parent = null; child = null; length = 0.0; lengthSE = 0.0; height = 0.0; identifier = Identifier.ANONYMOUS; number = 0; sequences = 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; } public void addSequence(NumberSequence s) { sequences.add(s); } /** * Returns the sequence at this node, in the form of a String. */ public String getSequenceString(int index) { return sequences.get(index).getSequence().toString(); } /** * Returns the sequence at this node, in the form of an array of bytes. */ public NumberSequence getSequence(int index) { return sequences.get(index); } /** * Sets the sequence at this node, in the form of an array of bytes. */ public void setSequence(int index,NumberSequence s) { sequences.set(index, 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. */ public final void setNodeHeight(double value) { height = Math.abs(value); } /** * Returns the identifier for this node. */ public final Identifier getIdentifier() { return identifier; } /** * Set identifier for this node. */ public final Identifier setIdentifier(Identifier id) { identifier = id; return identifier; } public void setNumber(int n) { number = n; } public int getNumber() { return number; } /** * get child node * * @param n number of child * * @return child node */ public Node getChild(int n) { return child[n]; } /** * set child node * * @param n number * @node node new child node */ public void setChild(int n, Node node) { child[n] = node; child[n].setParent(this); } /** * check whether this node is an internal node * * @return result (true or false) */ public boolean hasChildren() { return !isLeaf(); } /** * check whether this node is an external node * * @return result (true or false) */ public boolean isLeaf() { return (getChildCount() == 0); } /** * check whether this node is a root node * * @return result (true or false) */ public boolean isRoot() { if (parent == null) { return true; } else { return false; } } /** * add new child node * * @param n new child node */ public void addChild(Node n) { insertChild(n, getChildCount()); } /** * add new child node (insertion at a specific position) * * @param n new child node + @param pos position */ public void insertChild(Node n, int pos) { int numChildren = getChildCount(); Node[] newChild = new Node[numChildren + 1]; for (int i = 0; i < pos; i++) { newChild[i] = child[i]; } newChild[pos] = n; for (int i = pos; i < numChildren; i++) { newChild[i+1] = child[i]; } child = newChild; n.setParent(this); } /** * remove child * * @param n number of child to be removed */ public Node removeChild(int n) { int numChildren = getChildCount(); if (n >= 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; } /** * join two children, introducing a new node/branch in the tree * that replaces the first child * * @param n1 number of first child * @param n2 number of second child */ public Node joinChildren( int n1, int n2) { if (n1 == n2) { throw new IllegalArgumentException("CHILDREN MUST BE DIFFERENT"); } int c1, c2; if (n2 < n1) { c1 = n2; c2 = n1; } else { c1 = n1; c2 = n2; } Node newNode = NodeFactory.createNode(); Node child1 = this.getChild(c1); Node child2 = this.getChild(c2); setChild(c1, newNode); newNode.setParent(this); this.removeChild(c2); // now parent of child2 = null newNode.addChild(child1); newNode.addChild(child2); newNode.setIdentifier(new Identifier(child1.getIdentifier().getName() + " " + child2.getIdentifier().getName())); //System.out.println("Merging " + child1.getIdentifier() + " with " + child2.getIdentifier()); return newNode; } /** * Returns the number of children this node has. */ public final int getChildCount() { if (child == null) return 0; return child.length; } public ArrayList getSequences() { return sequences; } public void setSequences(ArrayList alignSequences) { this.sequences = alignSequences; } }