JAL-3904 failing test
[jalview.git] / test / jalview / ext / rbvi / chimera / JalviewChimeraView.java
index 6ea377f..e8b5bea 100644 (file)
@@ -25,41 +25,52 @@ import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Vector;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
 import jalview.api.FeatureRenderer;
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
 import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.PDBEntry;
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
 import jalview.gui.Preferences;
 import jalview.gui.StructureViewer;
 import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
-import jalview.io.FormatAdapter;
+import jalview.structure.StructureCommand;
 import jalview.structure.StructureMapping;
 import jalview.structure.StructureSelectionManager;
 import jalview.ws.sifts.SiftsClient;
 import jalview.ws.sifts.SiftsException;
 import jalview.ws.sifts.SiftsSettings;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.Vector;
-
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
 @Test(singleThreaded = true)
 public class JalviewChimeraView
 {
 
+  @BeforeClass(alwaysRun = true)
+  public void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+  }
+
   private JalviewStructureDisplayI chimeraViewer;
 
   /**
@@ -109,9 +120,10 @@ public class JalviewChimeraView
   @Test(groups = { "External" })
   public void testSingleSeqViewChimera()
   {
+
     String inFile = "examples/1gaq.txt";
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile,
-            FormatAdapter.FILE);
+            DataSourceType.FILE);
     assertNotNull(af, "Failed to create AlignFrame");
     SequenceI sq = af.getViewport().getAlignment().getSequenceAt(0);
     assertEquals(sq.getName(), "1GAQ|A");
@@ -130,7 +142,7 @@ public class JalviewChimeraView
     /*
      * Wait for viewer load thread to complete
      */
-    while (!binding.isFinishedInit())
+    do
     {
       try
       {
@@ -138,11 +150,36 @@ public class JalviewChimeraView
       } catch (InterruptedException e)
       {
       }
-    }
+    } while (!binding.isFinishedInit()  ||  !chimeraViewer.isVisible());
+
+    assertTrue(binding.isViewerRunning(), "Failed to start Chimera");
 
-    assertTrue(binding.isChimeraRunning(), "Failed to start Chimera");
+    assertEquals(chimeraViewer.getBinding().getPdbCount(), 1);
+    assertTrue(chimeraViewer.hasViewerActionsMenu());
+
+    // now add another sequence and bind to view
+    // 
+    AlignmentI al = af.getViewport().getAlignment();
+    PDBEntry xpdb = al.getSequenceAt(0).getPDBEntry("1GAQ");
+    sq = new Sequence("1GAQ", al.getSequenceAt(0).getSequence(25, 95).toString());
+    al.addSequence(sq);
+    structureViewer.viewStructures(new PDBEntry[] { xpdb }, new SequenceI[] { sq }, af.getCurrentView().getAlignPanel());
 
+    /*
+     * Wait for viewer load thread to complete
+     */
+    do 
+    {
+      try {
+        Thread.sleep(1500);
+      } catch (InterruptedException q) {};
+    } while (!binding.isLoadingFinished());
+    
+    // still just one PDB structure shown
     assertEquals(chimeraViewer.getBinding().getPdbCount(), 1);
+    // and the viewer action menu should still be visible
+    assertTrue(chimeraViewer.hasViewerActionsMenu());
+
     chimeraViewer.closeViewer(true);
     chimeraViewer = null;
     return;
@@ -162,7 +199,7 @@ public class JalviewChimeraView
   {
     String inFile = "examples/uniref50.fa";
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile,
-            FormatAdapter.FILE);
+            DataSourceType.FILE);
     assertNotNull(af, "Failed to create AlignFrame");
     SequenceI sq = af.getViewport().getAlignment().findName("FER2_ARATH");
     assertNotNull(sq, "Didn't find FER2_ARATH");
@@ -200,7 +237,7 @@ public class JalviewChimeraView
       }
     } while (!binding.isFinishedInit());
 
-    assertTrue(binding.isChimeraRunning(), "Failed to launch Chimera");
+    assertTrue(binding.isViewerRunning(), "Failed to launch Chimera");
 
     assertEquals(binding.getPdbCount(), 1);
 
@@ -209,7 +246,7 @@ public class JalviewChimeraView
      * (or possibly 52-145 to 1-94 - see JAL-2319)
      */
     StructureSelectionManager ssm = binding.getSsm();
-    String pdbFile = binding.getPdbFile()[0];
+    String pdbFile = binding.getStructureFiles()[0];
     StructureMapping[] mappings = ssm.getMapping(pdbFile);
     assertTrue(mappings[0].getMappingDetailsOutput().contains("SIFTS"),
             "Failed to perform SIFTS mapping");
@@ -246,6 +283,8 @@ public class JalviewChimeraView
             62, -2.1f, null));
     sq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 65,
             65, 3.6f, null));
+    sq.addSequenceFeature(new SequenceFeature("RESNUM", "ALA:   2  4zhoA",
+            53, 53, Float.NaN, null));
 
     /*
      * set all features visible except for chain
@@ -257,6 +296,7 @@ public class JalviewChimeraView
     fr.setVisible("metal ion-binding site");
     fr.setVisible("helix");
     fr.setVisible("kd");
+    fr.setVisible("RESNUM");
 
     /*
      * 'perform' menu action to copy visible features to
@@ -264,7 +304,7 @@ public class JalviewChimeraView
      */
     // TODO rename and pull up method to binding interface
     // once functionality is added for Jmol as well
-    binding.sendFeaturesToChimera(af.getViewport().getAlignPanel());
+    binding.sendFeaturesToViewer(af.getViewport().getAlignPanel());
 
     /*
      * give Chimera time to open the commands file and execute it
@@ -279,12 +319,14 @@ public class JalviewChimeraView
     /*
      * ask Chimera for its residue attribute names
      */
-    List<String> reply = binding.sendChimeraCommand("list resattr", true);
+    List<String> reply = binding
+            .executeCommand(new StructureCommand("list resattr"), true);
     // prefixed and sanitised attribute names for Jalview features:
     assertTrue(reply.contains("resattr jv_domain"));
     assertTrue(reply.contains("resattr jv_metal_ion_binding_site"));
     assertTrue(reply.contains("resattr jv_helix"));
     assertTrue(reply.contains("resattr jv_kd"));
+    assertTrue(reply.contains("resattr jv_RESNUM"));
     // feature is not on a mapped region - no attribute created
     assertFalse(reply.contains("resattr jv_transit_peptide"));
     // feature is not visible - no attribute created
@@ -294,8 +336,9 @@ public class JalviewChimeraView
      * ask Chimera for residues with an attribute
      * 91 and 96 on sequence --> residues 40 and 45 on chains A and B
      */
-    reply = binding.sendChimeraCommand(
-            "list resi att jv_metal_ion_binding_site", true);
+    reply = binding.executeCommand(
+            new StructureCommand("list resi att jv_metal_ion_binding_site"),
+            true);
     assertEquals(reply.size(), 4);
     assertTrue(reply
             .contains("residue id #0:40.A jv_metal_ion_binding_site \"Iron-Sulfur (2Fe-2S)\" index 40"));
@@ -310,7 +353,8 @@ public class JalviewChimeraView
      * check attributes with score values
      * sequence positions 62 and 65 --> residues 11 and 14 on chains A and B
      */
-    reply = binding.sendChimeraCommand("list resi att jv_kd", true);
+    reply = binding.executeCommand(
+            new StructureCommand("list resi att jv_kd"), true);
     assertEquals(reply.size(), 4);
     assertTrue(reply.contains("residue id #0:11.A jv_kd -2.1 index 11"));
     assertTrue(reply.contains("residue id #0:14.A jv_kd 3.6 index 14"));
@@ -320,8 +364,9 @@ public class JalviewChimeraView
     /*
      * list residues with positive kd score 
      */
-    reply = binding.sendChimeraCommand(
-            "list resi spec :*/jv_kd>0 attr jv_kd", true);
+    reply = binding.executeCommand(
+            new StructureCommand("list resi spec :*/jv_kd>0 attr jv_kd"),
+            true);
     assertEquals(reply.size(), 2);
     assertTrue(reply.contains("residue id #0:14.A jv_kd 3.6 index 14"));
     assertTrue(reply.contains("residue id #0:14.B jv_kd 3.6 index 14"));
@@ -330,4 +375,140 @@ public class JalviewChimeraView
     chimeraViewer.closeViewer(true);
     chimeraViewer = null;
   }
+
+  /**
+   * Test for creating Jalview features from attributes on mapped residues in
+   * Chimera. Note this uses local copies of PDB and SIFTS file, no network
+   * connection required.
+   * 
+   * @throws IOException
+   * @throws SiftsException
+   */
+  // External as this requires a local install of Chimera
+  @Test(groups = { "External" })
+  public void testGetAttributes() throws IOException, SiftsException
+  {
+    String inFile = "examples/uniref50.fa";
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile,
+            DataSourceType.FILE);
+    assertNotNull(af, "Failed to create AlignFrame");
+    SequenceI fer2Arath = af.getViewport().getAlignment()
+            .findName("FER2_ARATH");
+    assertNotNull(fer2Arath, "Didn't find FER2_ARATH");
+  
+    /*
+     * need a Uniprot dbref for SIFTS mapping to work!!
+     */
+    fer2Arath.addDBRef(new DBRefEntry("UNIPROT", "0", "P16972", null));
+  
+    /*
+     * use local test PDB and SIFTS files
+     */
+    String pdbFilePath = new File(
+            "test/jalview/ext/rbvi/chimera/4zho.pdb").getPath();
+    PDBEntry pdbEntry = new PDBEntry("4ZHO", null, null, pdbFilePath);
+    String siftsFilePath = new File(
+            "test/jalview/ext/rbvi/chimera/4zho.xml.gz")
+            .getPath();
+    SiftsClient.setMockSiftsFile(new File(siftsFilePath));
+  
+    StructureViewer structureViewer = new StructureViewer(af.getViewport()
+            .getStructureSelectionManager());
+    chimeraViewer = structureViewer.viewStructures(pdbEntry,
+            new SequenceI[] { fer2Arath }, af.getCurrentView()
+                    .getAlignPanel());
+  
+    JalviewChimeraBinding binding = (JalviewChimeraBinding) chimeraViewer
+            .getBinding();
+    do
+    {
+      try
+      {
+        Thread.sleep(500);
+      } catch (InterruptedException e)
+      {
+      }
+    } while (!binding.isFinishedInit());
+  
+    assertTrue(binding.isViewerRunning(), "Failed to launch Chimera");
+  
+    assertEquals(binding.getPdbCount(), 1);
+  
+    /*
+     * 'perform' menu action to copy Chimera attributes
+     * to features in Jalview
+     */
+    // TODO rename and pull up method to binding interface
+    // once functionality is added for Jmol as well
+    binding.copyStructureAttributesToFeatures("isHelix", af.getViewport()
+            .getAlignPanel());
+
+    /*
+     * verify 22 residues have isHelix feature
+     * (may merge into ranges in future)
+     */
+    af.setShowSeqFeatures(true);
+    FeatureRenderer fr = af.getFeatureRenderer();
+    fr.setVisible("isHelix");
+    for (int res = 75; res <= 83; res++)
+    {
+      checkFeaturesAtRes(fer2Arath, fr, res, "isHelix");
+    }
+    for (int res = 117; res <= 123; res++)
+    {
+      checkFeaturesAtRes(fer2Arath, fr, res, "isHelix");
+    }
+    for (int res = 129; res <= 131; res++)
+    {
+      checkFeaturesAtRes(fer2Arath, fr, res, "isHelix");
+    }
+    for (int res = 143; res <= 145; res++)
+    {
+      checkFeaturesAtRes(fer2Arath, fr, res, "isHelix");
+    }
+
+    /*
+     * fetch a numeric valued attribute
+     */
+    binding.copyStructureAttributesToFeatures("phi", af.getViewport()
+            .getAlignPanel());
+    fr.setVisible("phi");
+    List<SequenceFeature> fs = fer2Arath.getFeatures().findFeatures(54, 54,
+            "phi");
+    assertEquals(fs.size(), 2);
+    assertTrue(fs.contains(new SequenceFeature("phi", "A", 54, 54,
+            -131.0713f, "Chimera")));
+    assertTrue(fs.contains(new SequenceFeature("phi", "B", 54, 54,
+            -127.39512f, "Chimera")));
+
+    /*
+     * tear down - also in AfterMethod
+     */
+    SiftsClient.setMockSiftsFile(null);
+    chimeraViewer.closeViewer(true);
+    chimeraViewer = null;
+  }
+
+  /**
+   * Helper method to verify new feature at a sequence position
+   * 
+   * @param seq
+   * @param fr
+   * @param res
+   * @param featureType
+   */
+  protected void checkFeaturesAtRes(SequenceI seq, FeatureRenderer fr,
+          int res, String featureType)
+  {
+    String where = "at position " + res;
+    List<SequenceFeature> fs = seq.getFeatures().findFeatures(res, res,
+            featureType);
+
+    assertEquals(fs.size(), 1, where);
+    SequenceFeature sf = fs.get(0);
+    assertEquals(sf.getType(), featureType, where);
+    assertEquals(sf.getFeatureGroup(), "Chimera", where);
+    assertEquals(sf.getDescription(), "True", where);
+    assertEquals(sf.getScore(), Float.NaN, where);
+  }
 }