JAL-535 refactored core code from PCA viewer to viewmodel.
authorjprocter <jprocter@compbio.dundee.ac.uk>
Fri, 15 Jun 2012 14:54:28 +0000 (15:54 +0100)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Fri, 15 Jun 2012 14:58:08 +0000 (15:58 +0100)
src/jalview/api/RotatableCanvasI.java [new file with mode: 0644]
src/jalview/appletgui/RotatableCanvas.java
src/jalview/gui/PCAPanel.java
src/jalview/gui/RotatableCanvas.java
src/jalview/viewmodel/PCAModel.java [new file with mode: 0644]

diff --git a/src/jalview/api/RotatableCanvasI.java b/src/jalview/api/RotatableCanvasI.java
new file mode 100644 (file)
index 0000000..0d3d184
--- /dev/null
@@ -0,0 +1,17 @@
+package jalview.api;
+
+import jalview.datamodel.SequencePoint;
+
+import java.util.Vector;
+
+/**
+ * interface implemented by RotatatableCanvas GUI elements (such as point clouds and simple structure views)
+ * @author jimp
+ *
+ */
+public interface RotatableCanvasI
+{
+
+  void setPoints(Vector<SequencePoint> points, int rows);
+
+}
index ce03ef0..177e5ad 100755 (executable)
@@ -22,12 +22,13 @@ import java.util.*;
 import java.awt.*;
 import java.awt.event.*;
 
+import jalview.api.RotatableCanvasI;
 import jalview.datamodel.*;
 import jalview.math.*;
 import jalview.util.*;
 
 public class RotatableCanvas extends Panel implements MouseListener,
-        MouseMotionListener, KeyListener
+        MouseMotionListener, KeyListener, RotatableCanvasI
 {
   RotatableMatrix idmat = new RotatableMatrix(3, 3);
 
index 4c8a251..eb7806f 100755 (executable)
@@ -27,6 +27,7 @@ import javax.swing.*;
 import jalview.analysis.*;
 import jalview.datamodel.*;
 import jalview.jbgui.*;
+import jalview.viewmodel.PCAModel;
 
 /**
  * DOCUMENT ME!
@@ -37,24 +38,14 @@ import jalview.jbgui.*;
 public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
 {
 
-  PCA pca;
-
-  int top;
 
   RotatableCanvas rc;
 
   AlignmentPanel ap;
 
   AlignViewport av;
-
-  AlignmentView seqstrings;
-
-  SequenceI[] seqs;
-
-  /**
-   * use the identity matrix for calculating similarity between sequences. 
-   */
-  private boolean nucleotide=false;
+  PCAModel pcaModel;
+  int top=0;
 
   /**
    * Creates a new PCAPanel object.
@@ -71,8 +62,9 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
 
     boolean sameLength = true;
 
-    seqstrings = av.getAlignmentView(av.getSelectionGroup() != null);
-    nucleotide=av.getAlignment().isNucleotide();
+    AlignmentView seqstrings = av.getAlignmentView(av.getSelectionGroup() != null);
+    boolean nucleotide=av.getAlignment().isNucleotide();
+    SequenceI[] seqs;
     if (av.getSelectionGroup() == null)
     {
       seqs = av.getAlignment().getSequencesArray();
@@ -105,9 +97,9 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
 
       return;
     }
-
+    pcaModel = new PCAModel(seqstrings, seqs, nucleotide);
     PaintRefresher.Register(this, av.getSequenceSetId());
-
+    
     rc = new RotatableCanvas(ap);
     this.getContentPane().add(rc, BorderLayout.CENTER);
     Thread worker = new Thread(this);
@@ -142,48 +134,17 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
     try
     {
       calcSettings.setEnabled(false);
-      
-      pca = new PCA(seqstrings.getSequenceStrings(' '), nucleotide);
-      pca.run();
-
-      // Now find the component coordinates
-      int ii = 0;
-
-      while ((ii < seqs.length) && (seqs[ii] != null))
-      {
-        ii++;
-      }
-
-      double[][] comps = new double[ii][ii];
-
-      for (int i = 0; i < ii; i++)
-      {
-        if (pca.getEigenvalue(i) > 1e-4)
-        {
-          comps[i] = pca.component(i);
-        }
-      }
-
+      pcaModel.run();
       // ////////////////
       xCombobox.setSelectedIndex(0);
       yCombobox.setSelectedIndex(1);
       zCombobox.setSelectedIndex(2);
-
-      top = pca.getM().rows - 1;
-
-      Vector points = new Vector();
-      float[][] scores = pca.getComponents(top - 1, top - 2, top - 3, 100);
-
-      for (int i = 0; i < pca.getM().rows; i++)
-      {
-        SequencePoint sp = new SequencePoint(seqs[i], scores[i]);
-        points.addElement(sp);
-      }
-
-      rc.setPoints(points, pca.getM().rows);
+      
+      pcaModel.updateRc(rc);
       // rc.invalidate();
-      nuclSetting.setSelected(nucleotide);
-      protSetting.setSelected(!nucleotide);
+      nuclSetting.setSelected(pcaModel.isNucleotide());
+      protSetting.setSelected(!pcaModel.isNucleotide());
+      top=pcaModel.getTop();
 
     } catch (OutOfMemoryError er)
     {
@@ -204,9 +165,9 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
   @Override
   protected void nuclSetting_actionPerfomed(ActionEvent arg0)
   {
-    if (!nucleotide)
+    if (!pcaModel.isNucleotide())
     {
-    nucleotide=true;
+      pcaModel.setNucleotide(true);
     Thread worker = new Thread(this);
     worker.start();
     }
@@ -216,9 +177,9 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
   protected void protSetting_actionPerfomed(ActionEvent arg0)
   {
     
-    if (nucleotide)
+    if (pcaModel.isNucleotide())
     {
-    nucleotide=false;
+      pcaModel.setNucleotide(false);
     Thread worker = new Thread(this);
     worker.start();
     }
@@ -236,14 +197,7 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
     int dim1 = top - xCombobox.getSelectedIndex();
     int dim2 = top - yCombobox.getSelectedIndex();
     int dim3 = top - zCombobox.getSelectedIndex();
-
-    float[][] scores = pca.getComponents(dim1, dim2, dim3, 100);
-
-    for (int i = 0; i < pca.getM().rows; i++)
-    {
-      ((SequencePoint) rc.points.elementAt(i)).coord = scores[i];
-    }
-
+    pcaModel.updateRcView(dim1, dim2, dim3);
     rc.img = null;
     rc.rotmat.setIdentity();
     rc.initAxes();
@@ -288,7 +242,7 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
     CutAndPasteTransfer cap = new CutAndPasteTransfer();
     try
     {
-      cap.setText(pca.getDetails());
+      cap.setText(pcaModel.getDetails());
       Desktop.addInternalFrame(cap, "PCA details", 500, 500);
     } catch (OutOfMemoryError oom)
     {
@@ -312,7 +266,7 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
   {
     // this was cut'n'pasted from the equivalent TreePanel method - we should
     // make this an abstract function of all jalview analysis windows
-    if (seqstrings == null)
+    if (pcaModel.getSeqtrings() == null)
     {
       jalview.bin.Cache.log
               .info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
@@ -334,7 +288,7 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
     {
     }
     ;
-    Object[] alAndColsel = seqstrings.getAlignmentAndColumnSelection(gc);
+    Object[] alAndColsel = pcaModel.getSeqtrings().getAlignmentAndColumnSelection(gc);
 
     if (alAndColsel != null && alAndColsel[0] != null)
     {
@@ -548,7 +502,7 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
     CutAndPasteTransfer cap = new CutAndPasteTransfer();
     try
     {
-      cap.setText(getPointsasCsv(false));
+      cap.setText(pcaModel.getPointsasCsv(false, xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(), zCombobox.getSelectedIndex()));
       Desktop.addInternalFrame(cap, "Points for " + getTitle(), 500, 500);
     } catch (OutOfMemoryError oom)
     {
@@ -557,55 +511,7 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
     }
   }
 
-  private String getPointsasCsv(boolean transformed)
-  {
-    StringBuffer csv = new StringBuffer();
-    csv.append("\"Sequence\"");
-    if (transformed)
-    {
-      csv.append(",");
-      csv.append(xCombobox.getSelectedIndex());
-      csv.append(",");
-      csv.append(yCombobox.getSelectedIndex());
-      csv.append(",");
-      csv.append(zCombobox.getSelectedIndex());
-    }
-    else
-    {
-      for (int d = 1, dmax = pca.component(1).length; d <= dmax; d++)
-      {
-        csv.append("," + d);
-      }
-    }
-    csv.append("\n");
-    for (int s = 0; s < seqs.length; s++)
-    {
-      csv.append("\"" + seqs[s].getName() + "\"");
-      double fl[];
-      if (!transformed)
-      {
-        // output pca in correct order
-        fl = pca.component(s);
-        for (int d = fl.length - 1; d >= 0; d--)
-        {
-          csv.append(",");
-          csv.append(fl[d]);
-        }
-      }
-      else
-      {
-        // output current x,y,z coords for points
-        fl = rc.getPointPosition(s);
-        for (int d = 0; d < fl.length; d++)
-        {
-          csv.append(",");
-          csv.append(fl[d]);
-        }
-      }
-      csv.append("\n");
-    }
-    return csv.toString();
-  }
+  
 
   /*
    * (non-Javadoc)
@@ -619,7 +525,7 @@ public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
     CutAndPasteTransfer cap = new CutAndPasteTransfer();
     try
     {
-      cap.setText(getPointsasCsv(true));
+      cap.setText(pcaModel.getPointsasCsv(true, xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(), zCombobox.getSelectedIndex()));
       Desktop.addInternalFrame(cap, "Transformed points for " + getTitle(),
               500, 500);
     } catch (OutOfMemoryError oom)
index 458a29d..266eedb 100755 (executable)
@@ -23,6 +23,7 @@ import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 
+import jalview.api.RotatableCanvasI;
 import jalview.datamodel.*;
 import jalview.math.*;
 
@@ -33,7 +34,7 @@ import jalview.math.*;
  * @version $Revision$
  */
 public class RotatableCanvas extends JPanel implements MouseListener,
-        MouseMotionListener, KeyListener
+        MouseMotionListener, KeyListener, RotatableCanvasI
 {
   RotatableMatrix idmat = new RotatableMatrix(3, 3);
 
diff --git a/src/jalview/viewmodel/PCAModel.java b/src/jalview/viewmodel/PCAModel.java
new file mode 100644 (file)
index 0000000..30f8783
--- /dev/null
@@ -0,0 +1,190 @@
+package jalview.viewmodel;
+
+import java.util.Vector;
+
+import jalview.analysis.PCA;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequencePoint;
+import jalview.api.RotatableCanvasI;
+
+public class PCAModel
+{
+
+  public PCAModel(AlignmentView seqstrings2, SequenceI[] seqs2,
+          boolean nucleotide2)
+  {
+    seqstrings=seqstrings2;
+    seqs=seqs2;
+    nucleotide=nucleotide2;
+  }
+
+  PCA pca;
+  
+  int top;
+  
+  AlignmentView seqstrings;
+
+  SequenceI[] seqs;
+
+  /**
+   * use the identity matrix for calculating similarity between sequences. 
+   */
+  private boolean nucleotide=false;
+
+  private Vector<SequencePoint> points;
+
+  public void run()
+  {
+    
+    pca = new PCA(seqstrings.getSequenceStrings(' '), nucleotide);
+    pca.run();
+
+    // Now find the component coordinates
+    int ii = 0;
+
+    while ((ii < seqs.length) && (seqs[ii] != null))
+    {
+      ii++;
+    }
+
+    double[][] comps = new double[ii][ii];
+
+    for (int i = 0; i < ii; i++)
+    {
+      if (pca.getEigenvalue(i) > 1e-4)
+      {
+        comps[i] = pca.component(i);
+      }
+    }
+
+    top = pca.getM().rows - 1;
+
+    points = new Vector<SequencePoint>();
+    float[][] scores = pca.getComponents(top - 1, top - 2, top - 3, 100);
+
+    for (int i = 0; i < pca.getM().rows; i++)
+    {
+      SequencePoint sp = new SequencePoint(seqs[i], scores[i]);
+      points.addElement(sp);
+    }
+    
+  }
+
+  public void updateRc(RotatableCanvasI rc)
+  {
+    rc.setPoints(points, pca.getM().rows);
+  }
+
+  public boolean isNucleotide()
+  {
+    return nucleotide;
+  }
+  public void setNucleotide(boolean nucleotide)
+  {
+    this.nucleotide=nucleotide;
+  }
+
+  /**
+   * 
+   * 
+   * @return index of principle dimension of PCA
+   */
+  public int getTop()
+  {
+    return top;
+  }
+
+  /**
+   * update the 2d coordinates for the list of points to the given dimensions
+   * Principal dimension is getTop(). Next greated eigenvector is getTop()-1.
+   * Note - pca.getComponents starts counting the spectrum from zero rather than one, so getComponents(dimN ...)  == updateRcView(dimN+1 ..)  
+   * @param dim1 
+   * @param dim2
+   * @param dim3
+   */
+  public void updateRcView(int dim1, int dim2, int dim3)
+  {
+    float[][] scores = pca.getComponents(dim1-1, dim2-1, dim3-1, 100);
+
+    for (int i = 0; i < pca.getM().rows; i++)
+    {
+      ((SequencePoint) points.elementAt(i)).coord = scores[i];
+    }
+  }
+
+  public String getDetails()
+  {
+    return pca.getDetails();
+  }
+
+  public AlignmentView getSeqtrings()
+  {
+    return seqstrings;
+  }
+  public String getPointsasCsv(boolean transformed, int xdim, int ydim, int zdim)
+  {
+    StringBuffer csv = new StringBuffer();
+    csv.append("\"Sequence\"");
+    if (transformed)
+    {
+      csv.append(",");
+      csv.append(xdim);
+      csv.append(",");
+      csv.append(ydim);
+      csv.append(",");
+      csv.append(zdim);
+    }
+    else
+    {
+      for (int d = 1, dmax = pca.component(1).length; d <= dmax; d++)
+      {
+        csv.append("," + d);
+      }
+    }
+    csv.append("\n");
+    for (int s = 0; s < seqs.length; s++)
+    {
+      csv.append("\"" + seqs[s].getName() + "\"");
+      double fl[];
+      if (!transformed)
+      {
+        // output pca in correct order
+        fl = pca.component(s);
+        for (int d = fl.length - 1; d >= 0; d--)
+        {
+          csv.append(",");
+          csv.append(fl[d]);
+        }
+      }
+      else
+      {
+        // output current x,y,z coords for points
+        fl = getPointPosition(s);
+        for (int d = 0; d < fl.length; d++)
+        {
+          csv.append(",");
+          csv.append(fl[d]);
+        }
+      }
+      csv.append("\n");
+    }
+    return csv.toString();
+  }
+
+  /**
+   * 
+   * @return x,y,z positions of point s (index into points) under current
+   *         transform.
+   */
+  public double[] getPointPosition(int s)
+  {
+    double pts[] = new double[3];
+    float[] p = points.elementAt(s).coord;
+    pts[0] = p[0];
+    pts[1] = p[1];
+    pts[2] = p[2];
+    return pts;
+  }
+
+}