JAL-1767 unit test for save and restore PCA features/JAL-1767pcaInProject
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 7 May 2018 13:54:44 +0000 (14:54 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 7 May 2018 13:54:44 +0000 (14:54 +0100)
src/jalview/analysis/scoremodels/SimilarityParams.java
src/jalview/datamodel/Point.java
src/jalview/gui/PCAPanel.java
test/jalview/io/Jalview2xmlTests.java
test/jalview/math/MatrixTest.java

index 58b08dd..5c47703 100644 (file)
@@ -147,4 +147,57 @@ public class SimilarityParams implements SimilarityParamsI
   {
     return matchGaps;
   }
+
+  /**
+   * IDE-generated hashCode method
+   */
+  @Override
+  public int hashCode()
+  {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + (denominateByShortestLength ? 1231 : 1237);
+    result = prime * result + (includeGappedColumns ? 1231 : 1237);
+    result = prime * result + (includeGaps ? 1231 : 1237);
+    result = prime * result + (matchGaps ? 1231 : 1237);
+    return result;
+  }
+
+  /**
+   * IDE-generated equals method
+   */
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (this == obj)
+    {
+      return true;
+    }
+    if (obj == null)
+    {
+      return false;
+    }
+    if (getClass() != obj.getClass())
+    {
+      return false;
+    }
+    SimilarityParams other = (SimilarityParams) obj;
+    if (denominateByShortestLength != other.denominateByShortestLength)
+    {
+      return false;
+    }
+    if (includeGappedColumns != other.includeGappedColumns)
+    {
+      return false;
+    }
+    if (includeGaps != other.includeGaps)
+    {
+      return false;
+    }
+    if (matchGaps != other.matchGaps)
+    {
+      return false;
+    }
+    return true;
+  }
 }
index f1de8a1..e7c77c0 100644 (file)
@@ -26,4 +26,46 @@ public final class Point
   {
     return String.format("[%f, %f, %f]", x, y, z);
   }
+
+  @Override
+  public int hashCode()
+  {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + Float.floatToIntBits(x);
+    result = prime * result + Float.floatToIntBits(y);
+    result = prime * result + Float.floatToIntBits(z);
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (this == obj)
+    {
+      return true;
+    }
+    if (obj == null)
+    {
+      return false;
+    }
+    if (getClass() != obj.getClass())
+    {
+      return false;
+    }
+    Point other = (Point) obj;
+    if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x))
+    {
+      return false;
+    }
+    if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y))
+    {
+      return false;
+    }
+    if (Float.floatToIntBits(z) != Float.floatToIntBits(other.z))
+    {
+      return false;
+    }
+    return true;
+  }
 }
index caa2fc2..5ff0881 100644 (file)
@@ -162,6 +162,7 @@ public class PCAPanel extends GPCAPanel
   @Override
   public void run()
   {
+    working = true;
     long progId = System.currentTimeMillis();
     IProgressIndicator progress = this;
     String message = MessageManager.getString("label.pca_recalculating");
@@ -171,7 +172,6 @@ public class PCAPanel extends GPCAPanel
       message = MessageManager.getString("label.pca_calculating");
     }
     progress.setProgressBar(message, progId);
-    working = true;
     try
     {
       pcaModel.calculate();
index e9e0782..66d1aec 100644 (file)
@@ -26,32 +26,41 @@ import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
+import jalview.analysis.PCA;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureColourI;
 import jalview.api.ViewStyleI;
+import jalview.bin.Cache;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.PDBEntry.Type;
+import jalview.datamodel.Point;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequencePoint;
 import jalview.datamodel.features.FeatureMatcher;
 import jalview.datamodel.features.FeatureMatcherSet;
 import jalview.datamodel.features.FeatureMatcherSetI;
 import jalview.gui.AlignFrame;
 import jalview.gui.AlignViewport;
 import jalview.gui.AlignmentPanel;
+import jalview.gui.CalculationChooser;
 import jalview.gui.Desktop;
 import jalview.gui.FeatureRenderer;
 import jalview.gui.Jalview2XML;
 import jalview.gui.JvOptionPane;
+import jalview.gui.PCAPanel;
 import jalview.gui.PopupMenu;
+import jalview.gui.RotatableCanvas;
 import jalview.gui.SliderPanel;
+import jalview.math.MatrixTest;
 import jalview.renderer.ResidueShaderI;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.BuriedColourScheme;
@@ -65,6 +74,7 @@ import jalview.schemes.TCoffeeColourScheme;
 import jalview.structure.StructureImportSettings;
 import jalview.util.matcher.Condition;
 import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.PCAModel;
 
 import java.awt.Color;
 import java.io.File;
@@ -74,14 +84,31 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.swing.JInternalFrame;
+import javax.swing.JRadioButton;
+
 import org.testng.Assert;
 import org.testng.AssertJUnit;
 import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import junit.extensions.PA;
+
 @Test(singleThreaded = true)
 public class Jalview2xmlTests extends Jalview2xmlBase
 {
+  @BeforeClass(alwaysRun = true)
+  public void setUp()
+  {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+  }
+
+  @BeforeMethod(alwaysRun = true)
+  public void setUpMethod()
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+  }
 
   @Override
   @BeforeClass(alwaysRun = true)
@@ -1010,4 +1037,134 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     addFeature(seq, featureType, score++);
     addFeature(seq, featureType, score);
   }
+
+  /**
+   * Test save and reload of a PCA viewer
+   * 
+   * @throws IOException
+   */
+  @Test(groups = { "Functional" })
+  public void testSaveLoadPCA() throws IOException
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    assertEquals(af.getViewport().getAlignment().getHeight(), 15);
+
+    /*
+     * calculate and open PCA (calculates in a separate thread)
+     */
+    CalculationChooser chooser = new CalculationChooser(af);
+    ((JRadioButton) PA.getValue(chooser, "pca")).setSelected(true);
+    PA.invokeMethod(chooser, "calculate_actionPerformed()");
+    PCAPanel pcaPanel = (PCAPanel) PA.getValue(chooser, "pcaPanel");
+    assertNotNull(pcaPanel);
+    waitFor(50); // let it get started!!
+    while (pcaPanel.isWorking())
+    {
+      waitFor(50);
+    }
+    PA.invokeMethod(chooser, "close_actionPerformed()");
+
+    /*
+     * rotate, zoom in, change background colour
+     */
+    RotatableCanvas rc = (RotatableCanvas) PA.getValue(pcaPanel, "rc");
+    PA.setValue(rc, "bgColour", Color.PINK);
+    rc.zoom(1.9f);
+    rc.rotate(20, 40f);
+
+    /*
+     * save as Jalview project
+     */
+    File tfile = File.createTempFile("JalviewTest", ".jvp");
+    tfile.deleteOnExit();
+    String filePath = tfile.getAbsolutePath();
+    assertTrue(af.saveAlignment(filePath, FileFormat.Jalview),
+            "Failed to store as a project.");
+  
+    /*
+     * load the saved project and locate the restored PCA panel
+     */
+    new FileLoader().LoadFileWaitTillLoaded(filePath, DataSourceType.FILE);
+    JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+    PCAPanel pcaPanel2 = null;
+    for (JInternalFrame frame : frames)
+    {
+      if (frame instanceof PCAPanel && frame != pcaPanel)
+      {
+        pcaPanel2 = (PCAPanel) frame;
+      }
+    }
+    assertNotNull(pcaPanel2);
+
+    /*
+     * compare restored and original PCA
+     */
+    PCAModel pcaModel = (PCAModel) PA.getValue(pcaPanel, "pcaModel");
+    PCAModel pcaModel2 = (PCAModel) PA.getValue(pcaPanel2, "pcaModel");
+    RotatableCanvas rc2 = (RotatableCanvas) PA.getValue(pcaPanel2, "rc");
+    assertNotNull(pcaModel);
+    assertNotNull(pcaModel2);
+    assertNotNull(rc2);
+    assertEquals(rc2.getBackgroundColour(), Color.PINK);
+    assertEquals(PA.getValue(rc2, "scaleFactor"), 1.9f);
+
+    // original has input data
+    assertNotNull(pcaModel.getInputData());
+    // restored has no input data (JAL-2647 to do)
+    assertNull(pcaModel2.getInputData());
+
+    // verify sequence points are at the same positions
+    List<SequencePoint> seqPts = pcaModel.getSequencePoints();
+    List<SequencePoint> seqPts2 = pcaModel2.getSequencePoints();
+    assertEquals(seqPts.size(), seqPts2.size());
+    for (int i = 0; i < seqPts.size(); i++)
+    {
+      SequencePoint sp = seqPts.get(i);
+      SequencePoint sp2 = seqPts2.get(i);
+      assertEquals(sp.getSequence().getName(), sp2.getSequence().getName());
+      assertEquals(sp.coord, sp2.coord);
+    }
+
+    // verify axis end points are at the same positions
+    Point[] axes = (Point[]) PA.getValue(rc, "axisEndPoints");
+    Point[] axes2 = (Point[]) PA.getValue(rc2, "axisEndPoints");
+    assertEquals(axes.length, 3);
+    assertEquals(axes2.length, 3);
+    for (int i = 0; i < 3; i++)
+    {
+      assertEquals(axes[i], axes2[i]);
+    }
+
+    // compare PCA data
+    PCA pca = (PCA) PA.getValue(pcaModel, "pca");
+    PCA pca2 = (PCA) PA.getValue(pcaModel2, "pca");
+    assertNotNull(pca);
+    assertNotNull(pca2);
+    // same (BLOSUM62) score model (a singleton object)
+    assertSame(PA.getValue(pca, "scoreModel"),
+            PA.getValue(pca2, "scoreModel"));
+    assertEquals(PA.getValue(pca, "similarityParams"),
+            PA.getValue(pca2, "similarityParams"));
+    MatrixTest.assertMatricesMatch(pca.getPairwiseScores(),
+            pca2.getPairwiseScores());
+    MatrixTest.assertMatricesMatch(pca.getTridiagonal(),
+            pca2.getTridiagonal());
+    MatrixTest.assertMatricesMatch(pca.getEigenmatrix(),
+            pca2.getEigenmatrix());
+  }
+
+  protected void waitFor(long t)
+  {
+    synchronized (this)
+    {
+      try
+      {
+        wait(t);
+      } catch (InterruptedException e)
+      {
+        fail(e.getMessage());
+      }
+    }
+  }
 }
index 6e9c0f1..2cde593 100644 (file)
@@ -370,7 +370,7 @@ public class MatrixTest
     assertMatricesMatch(m1, m2);
   }
 
-  private void assertMatricesMatch(MatrixI m1, MatrixI m2)
+  public static void assertMatricesMatch(MatrixI m1, MatrixI m2)
   {
     if (m1.height() != m2.height())
     {
@@ -392,8 +392,10 @@ public class MatrixTest
         }
       }
     }
-    ArrayAsserts.assertArrayEquals(m1.getD(), m2.getD(), 0.00001d);
-    ArrayAsserts.assertArrayEquals(m1.getE(), m2.getE(), 0.00001d);
+    ArrayAsserts.assertArrayEquals("D vector", m1.getD(), m2.getD(),
+            0.00001d);
+    ArrayAsserts.assertArrayEquals("E vector", m1.getE(), m2.getE(),
+            0.00001d);
   }
 
   @Test(groups = "Functional")