Merge branch 'develop' into improvement/JAL-3830_install4j9_macos_setup_application
[jalview.git] / src / jalview / analysis / PCA.java
index d11d322..4a3cfec 100755 (executable)
@@ -22,7 +22,9 @@ package jalview.analysis;
 
 import jalview.api.analysis.ScoreModelI;
 import jalview.api.analysis.SimilarityParamsI;
+import jalview.bin.Console;
 import jalview.datamodel.AlignmentView;
+import jalview.datamodel.Point;
 import jalview.math.MatrixI;
 
 import java.io.PrintStream;
@@ -44,11 +46,11 @@ public class PCA implements Runnable
   /*
    * outputs
    */
-  private MatrixI symm;
+  private MatrixI pairwiseScores;
 
-  private MatrixI eigenvector;
+  private MatrixI tridiagonal;
 
-  private String details;
+  private MatrixI eigenMatrix;
 
   /**
    * Constructor given the sequences to compute for, the similarity model to
@@ -75,7 +77,7 @@ public class PCA implements Runnable
    */
   public double getEigenvalue(int i)
   {
-    return eigenvector.getD()[i];
+    return eigenMatrix.getD()[i];
   }
 
   /**
@@ -92,15 +94,16 @@ public class PCA implements Runnable
    * 
    * @return DOCUMENT ME!
    */
-  public float[][] getComponents(int l, int n, int mm, float factor)
+  public Point[] getComponents(int l, int n, int mm, float factor)
   {
-    float[][] out = new float[getHeight()][3];
+    Point[] out = new Point[getHeight()];
 
     for (int i = 0; i < getHeight(); i++)
     {
-      out[i][0] = (float) component(i, l) * factor;
-      out[i][1] = (float) component(i, n) * factor;
-      out[i][2] = (float) component(i, mm) * factor;
+      float x = (float) component(i, l) * factor;
+      float y = (float) component(i, n) * factor;
+      float z = (float) component(i, mm) * factor;
+      out[i] = new Point(x, y, z);
     }
 
     return out;
@@ -141,12 +144,12 @@ public class PCA implements Runnable
   {
     double out = 0.0;
 
-    for (int i = 0; i < symm.width(); i++)
+    for (int i = 0; i < pairwiseScores.width(); i++)
     {
-      out += (symm.getValue(row, i) * eigenvector.getValue(i, n));
+      out += (pairwiseScores.getValue(row, i) * eigenMatrix.getValue(i, n));
     }
 
-    return out / eigenvector.getD()[n];
+    return out / eigenMatrix.getD()[n];
   }
 
   /**
@@ -157,7 +160,38 @@ public class PCA implements Runnable
    */
   public String getDetails()
   {
-    return details;
+    StringBuilder sb = new StringBuilder(1024);
+    sb.append("PCA calculation using ").append(scoreModel.getName())
+            .append(" sequence similarity matrix\n========\n\n");
+    PrintStream ps = wrapOutputBuffer(sb);
+    
+    /*
+     * pairwise similarity scores
+     */
+    sb.append(" --- OrigT * Orig ---- \n");
+    pairwiseScores.print(ps, "%8.2f");
+    
+    /*
+     * tridiagonal matrix, with D and E vectors
+     */
+    sb.append(" ---Tridiag transform matrix ---\n");
+    sb.append(" --- D vector ---\n");
+    tridiagonal.printD(ps, "%15.4e");
+    ps.println();
+    sb.append("--- E vector ---\n");
+    tridiagonal.printE(ps, "%15.4e");
+    ps.println();
+    
+    /*
+     * eigenvalues matrix, with D vector
+     */
+    sb.append(" --- New diagonalization matrix ---\n");
+    eigenMatrix.print(ps, "%8.2f");
+    sb.append(" --- Eigenvalues ---\n");
+    eigenMatrix.printD(ps, "%15.4e");
+    ps.println();
+    
+    return sb.toString();
   }
 
   /**
@@ -166,55 +200,33 @@ public class PCA implements Runnable
   @Override
   public void run()
   {
-    /*
-     * print details to a string buffer as they are computed
-     */
-    StringBuilder sb = new StringBuilder(1024);
-    sb.append("PCA calculation using ").append(scoreModel.getName())
-            .append(" sequence similarity matrix\n========\n\n");
-    PrintStream ps = wrapOutputBuffer(sb);
-
     try
     {
-      eigenvector = scoreModel.findSimilarities(seqs, similarityParams);
-
-      sb.append(" --- OrigT * Orig ---- \n");
-      eigenvector.print(ps, "%8.2f");
-
-      symm = eigenvector.copy();
-
-      eigenvector.tred();
-
-      sb.append(" ---Tridiag transform matrix ---\n");
-      sb.append(" --- D vector ---\n");
-      eigenvector.printD(ps, "%15.4e");
-      ps.println();
-      sb.append("--- E vector ---\n");
-      eigenvector.printE(ps, "%15.4e");
-      ps.println();
-
-      // Now produce the diagonalization matrix
-      eigenvector.tqli();
+      /*
+       * sequence pairwise similarity scores
+       */
+      pairwiseScores = scoreModel.findSimilarities(seqs, similarityParams);
+
+      /*
+       * tridiagonal matrix
+       */
+      tridiagonal = pairwiseScores.copy();
+      tridiagonal.tred();
+
+      /*
+       * the diagonalization matrix
+       */
+      eigenMatrix = tridiagonal.copy();
+      eigenMatrix.tqli();
     } catch (Exception q)
     {
+      Console.error("Error computing PCA:  " + q.getMessage());
       q.printStackTrace();
-      sb.append("\n*** Unexpected exception when performing PCA ***\n"
-              + q.getLocalizedMessage());
-      sb.append(
-              "*** Matrices below may not be fully diagonalised. ***\n");
     }
-
-    sb.append(" --- New diagonalization matrix ---\n");
-    eigenvector.print(ps, "%8.2f");
-    sb.append(" --- Eigenvalues ---\n");
-    eigenvector.printD(ps, "%15.4e");
-    ps.println();
-
-    details = sb.toString();
   }
 
   /**
-   * Returns a PrintStream that wraps (sends its output to) the given
+   * Returns a PrintStream that wraps (appends its output to) the given
    * StringBuilder
    * 
    * @param sb
@@ -248,6 +260,42 @@ public class PCA implements Runnable
   public int getHeight()
   {
     // TODO can any of seqs[] be null?
-    return seqs.getSequences().length;
+    return pairwiseScores.height();// seqs.getSequences().length;
+  }
+
+  /**
+   * Answers the sequence pairwise similarity scores which were the first step
+   * of the PCA calculation
+   * 
+   * @return
+   */
+  public MatrixI getPairwiseScores()
+  {
+    return pairwiseScores;
+  }
+
+  public void setPairwiseScores(MatrixI m)
+  {
+    pairwiseScores = m;
+  }
+
+  public MatrixI getEigenmatrix()
+  {
+    return eigenMatrix;
+  }
+
+  public void setEigenmatrix(MatrixI m)
+  {
+    eigenMatrix = m;
+  }
+
+  public MatrixI getTridiagonal()
+  {
+    return tridiagonal;
+  }
+
+  public void setTridiagonal(MatrixI tridiagonal)
+  {
+    this.tridiagonal = tridiagonal;
   }
 }