JAL-3858 simple test for PAE matrix recovery
[jalview.git] / test / jalview / project / Jalview2xmlTests.java
index eb66416..84af3e4 100644 (file)
@@ -23,16 +23,19 @@ package jalview.project;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNotSame;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
 
 import java.awt.Color;
+import java.awt.Rectangle;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import javax.swing.JInternalFrame;
@@ -47,8 +50,12 @@ 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.Annotation;
+import jalview.datamodel.ContactListI;
+import jalview.datamodel.ContactMatrixI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.GeneLocus;
 import jalview.datamodel.HiddenSequences;
@@ -68,8 +75,10 @@ import jalview.gui.AlignViewport;
 import jalview.gui.AlignmentPanel;
 import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
+import jalview.gui.OverviewPanel;
 import jalview.gui.PCAPanel;
 import jalview.gui.PopupMenu;
+import jalview.gui.Preferences;
 import jalview.gui.SliderPanel;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
@@ -90,6 +99,7 @@ import jalview.util.MapList;
 import jalview.util.matcher.Condition;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
+import jalview.ws.datamodel.alphafold.PAEContactMatrix;
 
 @Test(singleThreaded = true)
 public class Jalview2xmlTests extends Jalview2xmlBase
@@ -159,8 +169,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     assertNotNull(
             ColourSchemeProperty.getColourScheme(viewport,
                     viewport.getAlignment(),
-                    viewport.getGlobalColourScheme()
-                            .getSchemeName()),
+                    viewport.getGlobalColourScheme().getSchemeName()),
             "Recognise T-Coffee score from string");
 
     af.saveAlignment(tfile, FileFormat.Jalview);
@@ -233,8 +242,9 @@ public class Jalview2xmlTests extends Jalview2xmlBase
 
     boolean diffseqcols = false, diffgseqcols = false;
     SequenceI[] sqs = af.getViewport().getAlignment().getSequencesArray();
-    for (int p = 0, pSize = af.getViewport().getAlignment()
-            .getWidth(); p < pSize && (!diffseqcols || !diffgseqcols); p++)
+    for (int p = 0,
+            pSize = af.getViewport().getAlignment().getWidth(); p < pSize
+                    && (!diffseqcols || !diffgseqcols); p++)
     {
       if (_rcs.findColour(sqs[0].getCharAt(p), p, sqs[0], null, 0f) != _rcs
               .findColour(sqs[5].getCharAt(p), p, sqs[5], null, 0f))
@@ -253,8 +263,9 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     assertTrue(__rcs.isSeqAssociated(),
             "Group Annotation colourscheme wasn't sequence associated");
 
-    for (int p = 0, pSize = af.getViewport().getAlignment()
-            .getWidth(); p < pSize && (!diffseqcols || !diffgseqcols); p++)
+    for (int p = 0,
+            pSize = af.getViewport().getAlignment().getWidth(); p < pSize
+                    && (!diffseqcols || !diffgseqcols); p++)
     {
       if (_rgcs.findColour(sqs[1].getCharAt(p), p, sqs[1], null,
               0f) != _rgcs.findColour(sqs[2].getCharAt(p), p, sqs[2], null,
@@ -449,9 +460,8 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     Assert.assertEquals(Desktop.getAlignFrames().length,
             Desktop.getAlignmentPanels(
                     af.getViewport().getSequenceSetId()).length);
-    Assert.assertEquals(
-            Desktop.getAlignmentPanels(
-                    af.getViewport().getSequenceSetId()).length,
+    Assert.assertEquals(Desktop
+            .getAlignmentPanels(af.getViewport().getSequenceSetId()).length,
             oldviews);
   }
 
@@ -586,6 +596,14 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     assertFalse(Jalview2XML.isVersionStringLaterThan("2.8.3b1", "2.8.3"));
     assertFalse(Jalview2XML.isVersionStringLaterThan("2.8.3", "2.8.2b1"));
     assertFalse(Jalview2XML.isVersionStringLaterThan("2.8.0b2", "2.8.0b1"));
+    /*
+     * test for patch release versions
+     */
+    assertFalse(Jalview2XML.isVersionStringLaterThan("2.11.3.0", "2.11.2"));
+    assertTrue(Jalview2XML.isVersionStringLaterThan("2.11.3.0","2.11.4"));
+    assertFalse(Jalview2XML.isVersionStringLaterThan("2.12.2.0b1","2.12.2.0"));
+    assertFalse(Jalview2XML.isVersionStringLaterThan("2.12.2.3","2.12.2.2"));
+
   }
 
   /**
@@ -804,7 +822,94 @@ public class Jalview2xmlTests extends Jalview2xmlBase
               "Mismatch PDBEntry 'Type'");
       Assert.assertNotNull(recov.getFile(),
               "Recovered PDBEntry should have a non-null file entry");
+      Assert.assertEquals(
+              recov.getFile().toLowerCase(Locale.ENGLISH)
+                      .lastIndexOf("pdb"),
+              recov.getFile().length() - 3,
+              "Recovered PDBEntry file should have PDB suffix");
+    }
+  }
+
+  /**
+   * Configure an alignment and a sub-group each with distinct colour schemes,
+   * Conservation and PID thresholds, and confirm these are restored from the
+   * saved project.
+   * 
+   * @throws IOException
+   */
+  @Test(groups = { "Functional" })
+  public void testStoreAndRecoverAnnotationRowElementColours()
+          throws IOException
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded("SEQ\tMNQ",
+            DataSourceType.PASTE);
+
+    AlignViewport av = af.getViewport();
+    AlignmentI al = av.getAlignment();
+    SequenceI fsq;
+    fsq = al.getSequenceAt(0);
+    Annotation annots[] = new Annotation[fsq.getLength()];
+    AlignmentAnnotation ala = new AlignmentAnnotation("Colour", "Annots",
+            annots);
+    annots[0] = new Annotation(1.0f);
+    annots[1] = new Annotation(2.0f);
+    annots[2] = new Annotation(3.0f);
+    annots[0].colour = Color.RED;
+    annots[1].colour = Color.GREEN;
+    annots[2].colour = Color.BLUE;
+    ala.validateRangeAndDisplay();
+    al.getSequenceAt(0).addAlignmentAnnotation(ala);
+    al.addAnnotation(ala);
+    /*
+     * and colour by annotation
+     */
+    AnnotationColourGradient acg = new AnnotationColourGradient(ala,
+            af.alignPanel.av.getGlobalColourScheme(), 0);
+    acg.setSeqAssociated(true);
+    acg.setPredefinedColours(true);
+    af.changeColour(acg);
+    Color seqcol[] = new Color[3];
+    for (int iStart=fsq.findIndex(fsq.getStart()),i=0;i<3;i++) {
+      seqcol[i] = af.alignPanel.getSeqPanel().seqCanvas.getSequenceRenderer().getResidueColour(fsq, iStart+i, null);
+    }
+    /*
+     * save project, close windows, reload project, verify
+     */
+    File tfile = File.createTempFile(
+            "testStoreAndRecoverAnnotRowElemColors", ".jvp");
+    tfile.deleteOnExit();
+    new Jalview2XML(false).saveState(tfile);
+    //Desktop.instance.closeAll_actionPerformed(null);
+    af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
+    Assert.assertNotNull(af, "Failed to reload project");
+    /*
+     * verify alignment annotation has colors
+     */
+    av = af.getViewport();
+    
+    ColourSchemeI loadedCscheme = av.getGlobalColourScheme();
+    Assert.assertTrue(loadedCscheme instanceof AnnotationColourGradient,"Didn't apply Annotation colour gradient");
+    acg = (AnnotationColourGradient) loadedCscheme;
+    assertTrue(acg.isSeqAssociated());
+    assertTrue(acg.isPredefinedColours());
+
+    al = av.getAlignment();
+    fsq = al.getSequenceAt(0);
+    ala = fsq.getAnnotation()[0];
+    Assert.assertNotNull(ala, "No annotation row recovered");
+    Assert.assertNotNull(ala.annotations);
+    for (int iStart = al.getSequenceAt(0)
+            .findIndex(al.getSequenceAt(0).getStart()), i = 0; i < 3; i++)
+    {
+      Assert.assertTrue(ala.annotations[i].colour!=null);
+      Assert.assertTrue(ala.annotations[i].colour.equals(annots[i].colour));
+      Color newseqcol = af.alignPanel.getSeqPanel().seqCanvas.getSequenceRenderer().getResidueColour(fsq, iStart+i, null);
+      Assert.assertTrue(seqcol[i].equals(newseqcol),"Sequence shading is different");
+
     }
+    
   }
 
   /**
@@ -1205,7 +1310,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqData,
             DataSourceType.PASTE);
     assertNotNull(af, "Didn't read in the example file correctly.");
-  
+
     AlignmentViewPanel ap = Desktop.getAlignmentPanels(null)[0];
     SequenceI pep = ap.getAlignment().getSequenceAt(0);
     SequenceI cds = ap.getAlignment().getSequenceAt(1);
@@ -1237,7 +1342,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
       Assert.fail("Didn't save the state", e);
     }
     Desktop.instance.closeAll_actionPerformed(null);
-  
+
     new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
             DataSourceType.FILE);
     AlignmentViewPanel rap = Desktop.getAlignmentPanels(null)[0];
@@ -1270,4 +1375,211 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     assertTrue(dbRef instanceof GeneLocus);
     assertEquals(dbRef, dbref3);
   }
+
+  /**
+   * test store and recovery of Overview windows
+   * 
+   * @throws Exception
+   */
+  @Test(groups = { "Functional" }, enabled = true)
+  public void testStoreAndRecoverOverview() throws Exception
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+
+    Cache.setProperty("SHOW_OVERVIEW", "false");
+    Cache.setProperty(Preferences.USE_LEGACY_GAP, "false");
+    Cache.setColourProperty(Preferences.GAP_COLOUR, Color.green);
+    Cache.setColourProperty(Preferences.HIDDEN_COLOUR, Color.yellow);
+    Cache.setProperty(Preferences.SHOW_OV_HIDDEN_AT_START, "true");
+
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+
+    /*
+     * open and resize / reposition overview 
+     */
+    af.overviewMenuItem_actionPerformed(null);
+    OverviewPanel ov1 = af.alignPanel.getOverviewPanel();
+    assertNotNull(ov1);
+    ov1.setFrameBounds(20, 30, 200, 400);
+    assertEquals(ov1.getTitle(), "Overview examples/uniref50.fa");
+    assertTrue(ov1.isShowHiddenRegions());
+
+    /*
+     * open a New View and its Overview and reposition it
+     */
+    af.newView_actionPerformed(null);
+    af.overviewMenuItem_actionPerformed(null);
+    OverviewPanel ov2 = af.alignPanel.getOverviewPanel();
+    assertNotNull(ov2);
+    assertNotSame(ov1, ov2);
+    ov2.setFrameBounds(25, 35, 205, 405);
+    assertEquals(ov1.getTitle(), "Overview examples/uniref50.fa Original");
+    assertEquals(ov2.getTitle(), "Overview examples/uniref50.fa View 1");
+
+    File tfile = File.createTempFile("testStoreAndRecoverOverview", ".jvp");
+    new Jalview2XML(false).saveState(tfile);
+    Desktop.instance.closeAll_actionPerformed(null);
+
+    /*
+     * change preferences (should _not_ affect reloaded Overviews)
+     */
+    Cache.setProperty("SHOW_OVERVIEW", "true");
+    Cache.setProperty(Preferences.USE_LEGACY_GAP, "true");
+    Cache.setColourProperty(Preferences.GAP_COLOUR, Color.blue);
+    Cache.setColourProperty(Preferences.HIDDEN_COLOUR, Color.orange);
+    Cache.setProperty(Preferences.SHOW_OV_HIDDEN_AT_START, "false");
+
+    af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
+
+    /*
+     * workaround: explicitly select View 1 (not in focus after restore)
+     */
+    af.tabSelectionChanged(1);
+
+    /*
+     * verify restored overview for View 1
+     */
+    ov2 = af.alignPanel.getOverviewPanel();
+    assertEquals(ov2.getCanvas().getGapColour(), Color.green);
+    // 'non-legacy' colouring uses white for non-gapped residues
+    assertEquals(ov2.getCanvas().getResidueColour(), Color.white);
+    assertEquals(ov2.getCanvas().getHiddenColour(), Color.yellow);
+    assertEquals(ov2.getTitle(), "Overview examples/uniref50.fa View 1");
+    assertEquals(ov2.getFrameBounds(), new Rectangle(25, 35, 205, 405));
+    assertTrue(ov2.isShowHiddenRegions());
+
+    /*
+     * verify restored overview for Original view
+     */
+    af.tabSelectionChanged(0);
+    ov1 = af.alignPanel.getOverviewPanel();
+    assertEquals(ov1.getCanvas().getGapColour(), Color.green);
+    // 'non-legacy' colouring uses white for non-gapped residues
+    assertEquals(ov1.getCanvas().getResidueColour(), Color.white);
+    assertEquals(ov1.getCanvas().getHiddenColour(), Color.yellow);
+    assertEquals(ov1.getTitle(), "Overview examples/uniref50.fa Original");
+    assertEquals(ov1.getFrameBounds(), new Rectangle(20, 30, 200, 400));
+    assertTrue(ov1.isShowHiddenRegions());
+  }
+
+  /**
+   * Test that a view with no Overview is restored with no Overview, even if
+   * 'Open Overview' is selected in Preferences
+   * 
+   * @throws Exception
+   */
+  @Test(groups = { "Functional" }, enabled = true)
+  public void testStoreAndRecoverNoOverview() throws Exception
+  {
+    Cache.setProperty("SHOW_OVERVIEW", "false");
+    Desktop.instance.closeAll_actionPerformed(null);
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            ">seq1\nMATRSQFLVNF\n", DataSourceType.PASTE);
+
+    File tfile = File.createTempFile("testStoreAndRecoverOverview", ".jvp");
+    new Jalview2XML(false).saveState(tfile);
+    Desktop.instance.closeAll_actionPerformed(null);
+
+    Cache.setProperty("SHOW_OVERVIEW", "true");
+    af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
+
+    assertNull(af.alignPanel.getOverviewPanel());
+  }
+
+  /**
+   * Test that a view from an older version of Jalview is restored with Overview automatically shown when the preference is set
+   * 
+   * @throws Exception
+   */
+  @Test(groups = { "Functional" }, enabled = true)
+  public void testAutoShowOverviewForLegacyProjects() throws Exception
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+    Cache.setProperty("SHOW_OVERVIEW", "true");
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/exampleFile.jvp", DataSourceType.FILE);
+
+    Cache.setProperty("SHOW_OVERVIEW", "false");
+    assertNotNull(af.alignPanel.getOverviewPanel());
+  }
+
+  /**
+   * Test that loading example.jvp, doing some stuff, then hitting reload
+   * doesn't leave the modified window still open
+   * 
+   * See JAL-4127 - interactively performing the same actions and reloading
+   * works fine, but programmatically they do not
+   * 
+   * @throws Exception
+   */
+  @Test(groups = {"Functional"}, enabled=false)
+  public void testReloadActuallyReloads() throws Exception
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/exampleFile.jvp", DataSourceType.FILE);
+    af.getViewport().getColumnSelection().addElement(3);
+    af.hideSelColumns_actionPerformed(null);
+    af.newView("new", true);
+    af.reload_actionPerformed(null);
+    Thread.sleep(30);
+    // af exists still but isn't shown
+    assertTrue(af.isClosed());
+  }
+
+  @Test(groups = { "Functional" })
+  public void testPAEsaveRestore() throws Exception
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            ">seq1\nMATRSQFLVNF\n", DataSourceType.PASTE);
+    AlignmentI al = af.getViewport().getAlignment();
+    SequenceI sq = al.getSequenceAt(0);
+    int i = sq.getLength();
+    float[][] paevals = new float[i][i];
+    for (i = i - 1; i >= 0; i--)
+    {
+      for (int j = 0; j <= i; j++)
+      {
+        paevals[i][j] = ((i - j < 2)
+                || ((i > 1 && i < 5) && (j > 1 && i < 5))) ? 1 : 0f;
+        paevals[j][i] = paevals[i][j];
+      }
+    }
+    PAEContactMatrix dummyMat = new PAEContactMatrix(sq, paevals);
+    AlignmentAnnotation paeCm = sq.addContactList(dummyMat);
+    al.addAnnotation(paeCm);
+    File tfile = File.createTempFile("testStoreAndRecoverPAEmatrix",
+            ".jvp");
+    new Jalview2XML(false).saveState(tfile);
+    Desktop.instance.closeAll_actionPerformed(null);
+
+    af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
+    AlignmentI newAl = af.getViewport().getAlignment();
+    SequenceI newSeq = newAl.getSequenceAt(0);
+    // check annotation of the expected type exists
+    Assert.assertEquals(newSeq.getAnnotation().length, 1);
+    Assert.assertEquals(newSeq.getAnnotation()[0].graph, paeCm.graph);
+
+    // check a contact matrix was recovered
+    Assert.assertEquals(newSeq.getContactMaps().size(), 1);
+    // and can be found for the annotation
+    ContactMatrixI restoredMat = al
+            .getContactMatrixFor(newSeq.getAnnotation()[0]);
+    Assert.assertNotNull(restoredMat);
+    for (i = sq.getLength() - 1; i >= 0; i--)
+    {
+      ContactListI oldCM = dummyMat.getContactList(i),
+              newCM = restoredMat.getContactList(i);
+      for (int j = oldCM.getContactHeight(); j >= 0; j--)
+      {
+        Assert.assertEquals(oldCM.getContactAt(j), newCM.getContactAt(j));
+      }
+    }
+  }
+
 }