Merge branch 'kjvdh/features/PhylogenyViewer_tabbedsupport' into merge/2_11_2/kjvdh...
[jalview.git] / src / jalview / analysis / TreeBuilder.java
index 6d5b0fe..c4a94eb 100644 (file)
@@ -1,9 +1,27 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis;
 
-import jalview.api.analysis.DistanceScoreModelI;
 import jalview.api.analysis.ScoreModelI;
 import jalview.api.analysis.SimilarityParamsI;
-import jalview.api.analysis.SimilarityScoreModelI;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.CigarArray;
 import jalview.datamodel.SeqCigar;
@@ -49,12 +67,20 @@ public abstract class TreeBuilder
 
   double maxDistValue;
 
-  double maxheight;
+  double maxHeight;
 
   int ycount;
 
   Vector<SequenceNode> node;
 
+  protected ScoreModelI scoreModel;
+
+  protected SimilarityParamsI scoreParams;
+
+  private AlignmentViewport avport;
+
+  private AlignmentView seqStrings; // redundant? (see seqData)
+
   /**
    * Constructor
    * 
@@ -66,9 +92,10 @@ public abstract class TreeBuilder
           SimilarityParamsI scoreParameters)
   {
     int start, end;
+    avport = av;
     boolean selview = av.getSelectionGroup() != null
             && av.getSelectionGroup().getSize() > 1;
-    AlignmentView seqStrings = av.getAlignmentView(selview);
+    seqStrings = av.getAlignmentView(selview);
     if (!selview)
     {
       start = 0;
@@ -79,8 +106,8 @@ public abstract class TreeBuilder
     {
       start = av.getSelectionGroup().getStartRes();
       end = av.getSelectionGroup().getEndRes() + 1;
-      this.sequences = av.getSelectionGroup().getSequencesInOrder(
-              av.getAlignment());
+      this.sequences = av.getSelectionGroup()
+              .getSequencesInOrder(av.getAlignment());
     }
 
     init(seqStrings, start, end);
@@ -105,20 +132,20 @@ public abstract class TreeBuilder
   {
     if (nd == null)
     {
-      return maxheight;
+      return maxHeight;
     }
-  
+
     if ((nd.left() == null) && (nd.right() == null))
     {
       nd.height = ((SequenceNode) nd.parent()).height + nd.dist;
-  
-      if (nd.height > maxheight)
+
+      if (nd.height > maxHeight)
       {
         return nd.height;
       }
       else
       {
-        return maxheight;
+        return maxHeight;
       }
     }
     else
@@ -129,15 +156,15 @@ public abstract class TreeBuilder
       }
       else
       {
-        maxheight = 0;
+        maxHeight = 0;
         nd.height = (float) 0.0;
       }
-  
-      maxheight = findHeight((SequenceNode) (nd.left()));
-      maxheight = findHeight((SequenceNode) (nd.right()));
+
+      maxHeight = findHeight((SequenceNode) (nd.left()));
+      maxHeight = findHeight((SequenceNode) (nd.right()));
     }
-  
-    return maxheight;
+
+    return maxHeight;
   }
 
   /**
@@ -164,23 +191,24 @@ public abstract class TreeBuilder
   {
     // if (_lycount<_lylimit)
     // {
-    // System.err.println("Warning: depth of _recount greater than number of nodes.");
+    // System.err.println("Warning: depth of _recount greater than number of
+    // nodes.");
     // }
     if (nd == null)
     {
       return;
     }
     // _lycount++;
-  
+
     if ((nd.left() != null) && (nd.right() != null))
     {
-  
+
       _reCount((SequenceNode) nd.left());
       _reCount((SequenceNode) nd.right());
-  
+
       SequenceNode l = (SequenceNode) nd.left();
       SequenceNode r = (SequenceNode) nd.right();
-  
+
       nd.count = l.count + r.count;
       nd.ycount = (l.ycount + r.ycount) / 2;
     }
@@ -234,23 +262,29 @@ public abstract class TreeBuilder
     while (noClus > 2)
     {
       findMinDistance();
-  
+
       joinClusters(mini, minj);
-  
+
       noClus--;
     }
-  
+
     int rightChild = done.nextClearBit(0);
     int leftChild = done.nextClearBit(rightChild + 1);
-  
+
     joinClusters(leftChild, rightChild);
     top = (node.elementAt(leftChild));
-  
+
     reCount(top);
     findHeight(top);
     findMaxDist(top);
   }
 
+  /**
+   * Returns the minimum distance between two clusters, and also sets the
+   * indices of the clusters in fields mini and minj
+   * 
+   * @return
+   */
   protected abstract double findMinDistance();
 
   /**
@@ -268,35 +302,24 @@ public abstract class TreeBuilder
    */
   protected void computeTree(ScoreModelI sm, SimilarityParamsI scoreOptions)
   {
-    if (sm instanceof DistanceScoreModelI)
-    {
-      distances = ((DistanceScoreModelI) sm).findDistances(seqData,
-              scoreOptions);
-    }
-    else if (sm instanceof SimilarityScoreModelI)
-    {
-      /*
-       * compute similarity and invert it to give a distance measure
-       * reverseRange(true) converts maximum similarity to zero distance
-       */
-      MatrixI result = ((SimilarityScoreModelI) sm).findSimilarities(
-              seqData, scoreOptions);
-      result.reverseRange(true);
-      distances = result;
-    }
-  
+
+    this.scoreModel = sm;
+    this.scoreParams = scoreOptions;
+
+    distances = scoreModel.findDistances(seqData, scoreParams);
+
     makeLeaves();
-  
+
     noClus = clusters.size();
-  
+
     cluster();
   }
 
   /**
-   * DOCUMENT ME!
+   * Finds the node, at or below the given node, with the maximum distance, and
+   * saves the node and the distance value
    * 
    * @param nd
-   *          DOCUMENT ME!
    */
   void findMaxDist(SequenceNode nd)
   {
@@ -304,11 +327,11 @@ public abstract class TreeBuilder
     {
       return;
     }
-  
+
     if ((nd.left() == null) && (nd.right() == null))
     {
       double dist = nd.dist;
-  
+
       if (dist > maxDistValue)
       {
         maxdist = nd;
@@ -323,19 +346,17 @@ public abstract class TreeBuilder
   }
 
   /**
-   * DOCUMENT ME!
+   * Calculates and returns r, whatever that is
    * 
    * @param i
-   *          DOCUMENT ME!
    * @param j
-   *          DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
   protected double findr(int i, int j)
   {
     double tmp = 1;
-  
+
     for (int k = 0; k < noseqs; k++)
     {
       if ((k != i) && (k != j) && (!done.get(k)))
@@ -343,18 +364,18 @@ public abstract class TreeBuilder
         tmp = tmp + distances.getValue(i, k);
       }
     }
-  
+
     if (noClus > 2)
     {
       tmp = tmp / (noClus - 2);
     }
-  
+
     return tmp;
   }
 
   protected void init(AlignmentView seqView, int start, int end)
   {
-    this.node = new Vector<SequenceNode>();
+    this.node = new Vector<>();
     if (seqView != null)
     {
       this.seqData = seqView;
@@ -370,14 +391,14 @@ public abstract class TreeBuilder
       sdata.addOperation(CigarArray.M, end - start + 1);
       this.seqData = new AlignmentView(sdata, start);
     }
-  
+
     /*
      * count the non-null sequences
      */
     noseqs = 0;
-  
+
     done = new BitSet();
-  
+
     for (SequenceI seq : sequences)
     {
       if (seq != null)
@@ -396,27 +417,27 @@ public abstract class TreeBuilder
   void joinClusters(final int i, final int j)
   {
     double dist = distances.getValue(i, j);
-  
+
     ri = findr(i, j);
     rj = findr(j, i);
-  
+
     findClusterDistance(i, j);
-  
+
     SequenceNode sn = new SequenceNode();
-  
+
     sn.setLeft((node.elementAt(i)));
     sn.setRight((node.elementAt(j)));
-  
+
     SequenceNode tmpi = (node.elementAt(i));
     SequenceNode tmpj = (node.elementAt(j));
-  
+
     findNewDistances(tmpi, tmpj, dist);
-  
+
     tmpi.setParent(sn);
     tmpj.setParent(sn);
-  
+
     node.setElementAt(sn, i);
-  
+
     /*
      * move the members of cluster(j) to cluster(i)
      * and mark cluster j as out of the game
@@ -426,8 +447,12 @@ public abstract class TreeBuilder
     done.set(j);
   }
 
-  protected abstract void findNewDistances(SequenceNode tmpi, SequenceNode tmpj,
-          double dist);
+  /*
+   * Computes and stores new distances for nodei and nodej, given the previous
+   * distance between them
+   */
+  protected abstract void findNewDistances(SequenceNode nodei,
+          SequenceNode nodej, double previousDistance);
 
   /**
    * Calculates and saves the distance between the combination of cluster(i) and
@@ -444,19 +469,45 @@ public abstract class TreeBuilder
    */
   void makeLeaves()
   {
-    clusters = new Vector<BitSet>();
-  
+    clusters = new Vector<>();
+
     for (int i = 0; i < noseqs; i++)
     {
       SequenceNode sn = new SequenceNode();
-  
+
       sn.setElement(sequences[i]);
       sn.setName(sequences[i].getName());
       node.addElement(sn);
+
       BitSet bs = new BitSet();
       bs.set(i);
       clusters.addElement(bs);
     }
   }
 
+  public AlignmentView getOriginalData()
+  {
+    return seqStrings;
+  }
+
+  public MatrixI getDistances()
+  {
+    return distances;
+  }
+
+  public ScoreModelI getScoreModel()
+  {
+    return scoreModel;
+  }
+
+  public SimilarityParamsI getScoreParams()
+  {
+    return scoreParams;
+  }
+
+  public AlignmentViewport getAvport()
+  {
+    return avport;
+  }
+
 }