package com.ppfold.algo; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * Definition of a node of the phylogenetic tree. * * @author Z.Sukosd * @see Tree */ public class Node implements Serializable { private static final long serialVersionUID = 5971946683590961841L; // represents a node in the phylogenetic tree private double[] Vector; private double[] DownBottomVector; private double[] DownTopVector; private double[] UpBottomVector; private double[] UpTopVector; private double[] tmpvector; private double[] tmpvector1; private double[][] Matrix; private double[] tmpntvector = new double[16]; private double[][] tmpntmatrix = new double[4][4]; private double DistanceFromParent; private double NewDistanceFromParent; //to store the better distance in MLE calculations List<Node> Children = new ArrayList<Node>(); private String name; private int id; public Node() { Vector = MatrixTools.createVector(4, 1); } public boolean isLeaf() { if (Children.size() == 0) { return true; } else return false; } public void printChildren() { for (Node n : this.Children) { n.printChildren(); } System.out.format("Id of node: " + id + ",\t name: " + ((name == null || name.equals("")) ? "N/A" : name) + ",\t distance from parent = " + "%.4f" + ",\t has " + Children.size() + " children", DistanceFromParent); if (Children.size() > 0) { System.out.print("\t with ids: "); for (int i = 0; i < this.Children.size(); i++) { Node child = Children.get(i); System.out.print(child.id + (i == Children.size() - 1 ? "" : ", ")); } } System.out.println(); } public int countTotalChildren() { int totaloffspringsize = 0; for (Node n : this.Children) { totaloffspringsize += n.countTotalChildren(); } return this.Children.size() + totaloffspringsize; } public boolean setChildrenNewBranches(boolean currentvalue) { boolean childrensvalue = true; for (Node n : this.Children) { childrensvalue = childrensvalue&&n.setChildrenNewBranches(currentvalue); } //currentvalue should be true IF AND ONLY IF: //1) this node has finished iterations (ie. value didn't change) //2) all its children have finished iterations (ie. n.setChildrenNewBranches() ALWAYS // returns true) currentvalue = (Math.abs(DistanceFromParent-NewDistanceFromParent)<1e-4)&&childrensvalue; // if(!currentvalue){ // System.out.println("Node " + id + " needs more iterations: " // + DistanceFromParent + " vs " + NewDistanceFromParent ); // System.out.println("Its childrens value " + childrensvalue); // System.out.println("Its own value " + (Math.abs(DistanceFromParent-NewDistanceFromParent)<1e-10)); // } // else{ // System.out.println("Node " + id + " is finished" // + DistanceFromParent + " vs " + NewDistanceFromParent ); // System.out.println("Its childrens value " + childrensvalue); // System.out.println("Its own value " + (Math.abs(DistanceFromParent-NewDistanceFromParent)<1e-10)); // // } this.DistanceFromParent = this.NewDistanceFromParent; return currentvalue; } public void printChildrenMatrix() { for (Node n : this.Children) { n.printChildrenMatrix(); } System.out.println("Id of node: " + id + ",\t name: " + ((name == null || name.equals("")) ? "N/A" : name) + " the matrix is: "); MatrixTools.print(this.Matrix); } public void calculateChildrenMatrix(double[][] D, double[][] V, double[][] V1) { for (Node n : this.Children) { n.calculateChildrenMatrix(D, V, V1); } Matrix = calculateMatrix(D, V, V1); } public double[][] calculateMatrix(double[][] D, double[][] V, double[][] V1) { double[][] result = MatrixTools.expRT(D, DistanceFromParent, V, V1); return result; } public void calculateChildrenDownVectors(){ //this will recursively calculate the vector of all nodes //in POSTORDER traversal for(Node n:this.Children){ n.calculateChildrenDownVectors(); MatrixTools.resetVector(tmpvector,0); MatrixTools.resetVector(tmpvector1,0); MatrixTools.copyFromTo(n.DownBottomVector, tmpvector); MatrixTools.multiplyMatrixVector(n.Matrix,tmpvector,tmpvector1); MatrixTools.multiplySeries(DownBottomVector, tmpvector); } MatrixTools.copyFromTo(DownBottomVector, DownTopVector); MatrixTools.resetVector(tmpvector,0); MatrixTools.multiplyMatrixVector(Matrix,DownTopVector,tmpvector); } public void calculateChildrenUpVectors(Node parent) { // this will recursively calculate the vector of all nodes // in preorder traversal, so first fill in the value, then visit children calculateUpVector(parent); for (Node n : this.Children) { n.calculateChildrenUpVectors(this); } } public void calculateUpVector(Node parent) { if(parent!=null){ //IF NOT ROOT (ie. if it has a parent) //up-top is combination of parent's up-bottom.... MatrixTools.multiplySeries(UpTopVector, parent.UpBottomVector); for(Node sibling:parent.getChildren()){ //...and all siblings' down-top if(sibling!=this){ MatrixTools.multiplySeries(UpTopVector, sibling.DownTopVector); } } } //Finally calculate UpBottomVector by doing expRt on UpTop. MatrixTools.copyFromTo(UpTopVector, UpBottomVector); MatrixTools.resetVector(tmpvector,0); //MatrixTools.multiplyMatrixVector(Matrix,UpBottomVector,tmpvector); MatrixTools.multiplyMatrixVector(Matrix,UpBottomVector, tmpvector); } public void calculateChildrenVector() { // this will recursively calculate the vector of all nodes for (Node n : this.Children) { n.calculateChildrenVector(); // Vector = MatrixTools.multiplySeries(Vector, n.getVector()); MatrixTools.multiplySeries(Vector, n.getVector()); } calculateVector(); } private void calculateVector() { // this will calculate the vector of one node MatrixTools.multiplyMatrixVector(Matrix, Vector, tmpvector); // System.out.println("VECTOR of Node " + this.getId() + " is " ); // MatrixTools.prints(Vector); } public void resetChildrenVector(double val) { for (Node n : this.Children) { n.resetChildrenVector(val); } for (int i = 0; i < this.Vector.length; i++) { Vector[i] = val; tmpvector[i] = 0; } } public void resetChildrenVector(int m, double val) { for (Node n : this.Children) { n.resetChildrenVector(m, val); } double[] vector = new double[m]; for (int i = 0; i < m; i++) { vector[i] = val; } this.Vector = vector; this.tmpvector = new double[m]; } public void initializeChildrenUpDownVectors(){ for (Node n : this.Children) { n.initializeChildrenUpDownVectors(); } this.DownBottomVector = new double[4]; this.DownTopVector = new double[4]; this.UpBottomVector = new double[4]; this.UpTopVector = new double[4]; this.tmpvector = new double[4]; this.tmpvector1 = new double[4]; } public void resetChildrenDownVectors() { for (Node n : this.Children) { n.resetChildrenDownVectors(); } for (int i = 0; i < 4; i++) { DownBottomVector[i] = 1; DownTopVector[i] = 1; tmpvector[i] = 1; } } public void resetChildrenUpVectors() { for (Node n : this.Children) { n.resetChildrenUpVectors(); } for (int i = 0; i < 4; i++) { UpBottomVector[i] = 1; UpTopVector[i] = 1; tmpvector[i] = 1; } } public void printChildrenVector() { for (Node n : this.Children) { n.printChildrenVector(); } System.out.println("Id of node: " + id + ",\t name: " + ((name == null || name.equals("")) ? "N/A" : name) + " the vector is: "); MatrixTools.prints(this.Vector); } public void printChildrenUpDownVectors() { for (Node n : this.Children) { n.printChildrenUpDownVectors(); } System.out.println("Id of node: " + id + ",\t name: " + ((name == null || name.equals("")) ? "N/A" : name) + " the vectors are (down-bottom, down-top, up-bottom, up-top): "); MatrixTools.prints(this.DownBottomVector); MatrixTools.prints(this.DownTopVector); MatrixTools.prints(this.UpBottomVector); MatrixTools.prints(this.UpTopVector); MatrixTools.print(this.Matrix); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Node(double distance) { DistanceFromParent = distance; } public void addChild(Node child) { Children.add(child); } public List<Node> getChildren() { return this.Children; } public double getDistanceFromParent() { return DistanceFromParent; } public void setDistanceFromParent(double distanceFromParent) { DistanceFromParent = distanceFromParent; } public double getNewDistanceFromParent() { return NewDistanceFromParent; } public double[][] getMatrix() { return Matrix; } public void setMatrix(double[][] matrix) { Matrix = matrix; } public double[] getVector() { return Vector; } public void setVector(double[] vector) { Vector = vector; } public double[][] getTmpNtMatrix() { return tmpntmatrix; } public double[] getTmpNtVector() { return tmpntvector; } public int getId() { return id; } public void setId(int id) { this.id = id; } public void setDownBottomVector(double[] ds) { DownBottomVector = ds; } public void setUpTopVector(double[] ds) { UpTopVector = ds; } public double[] getDownBottomVector(){ return DownBottomVector; } public double[] getUpTopVector(){ return UpTopVector; } public void setDownTopVector(double[][] D, double[][] V, double[][] V1){ //this sets the DownTopVector to exp(Rt)DownBottomVector, where //t = DistanceFromParent. DownTopVector = MatrixTools.multiplyMatrixVector (MatrixTools.expRT(D, DistanceFromParent, V, V1), DownBottomVector); } public void setNewDistanceFromParent(double newDistanceFromParent) { NewDistanceFromParent = newDistanceFromParent; } public void setDistanceToOptimum(double distance){ DistanceFromParent = NewDistanceFromParent; } }