From: gmungoc Date: Mon, 7 May 2018 13:54:44 +0000 (+0100) Subject: JAL-1767 unit test for save and restore PCA X-Git-Tag: Release_2_11_1_0~78^2~9^2 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=55d8ed2824ef1e2f5a8ea30f43d14980119f8c43;p=jalview.git JAL-1767 unit test for save and restore PCA --- diff --git a/src/jalview/analysis/scoremodels/SimilarityParams.java b/src/jalview/analysis/scoremodels/SimilarityParams.java index 58b08dd..5c47703 100644 --- a/src/jalview/analysis/scoremodels/SimilarityParams.java +++ b/src/jalview/analysis/scoremodels/SimilarityParams.java @@ -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; + } } diff --git a/src/jalview/datamodel/Point.java b/src/jalview/datamodel/Point.java index f1de8a1..e7c77c0 100644 --- a/src/jalview/datamodel/Point.java +++ b/src/jalview/datamodel/Point.java @@ -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; + } } diff --git a/src/jalview/gui/PCAPanel.java b/src/jalview/gui/PCAPanel.java index caa2fc2..5ff0881 100644 --- a/src/jalview/gui/PCAPanel.java +++ b/src/jalview/gui/PCAPanel.java @@ -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(); diff --git a/test/jalview/io/Jalview2xmlTests.java b/test/jalview/io/Jalview2xmlTests.java index e9e0782..66d1aec 100644 --- a/test/jalview/io/Jalview2xmlTests.java +++ b/test/jalview/io/Jalview2xmlTests.java @@ -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 seqPts = pcaModel.getSequencePoints(); + List 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()); + } + } + } } diff --git a/test/jalview/math/MatrixTest.java b/test/jalview/math/MatrixTest.java index 6e9c0f1..2cde593 100644 --- a/test/jalview/math/MatrixTest.java +++ b/test/jalview/math/MatrixTest.java @@ -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")