JAL-2780 JAL-2781 first pass at failing test for incorrect colouring of structure...
authorJim Procter <jprocter@issues.jalview.org>
Wed, 7 Feb 2018 13:10:18 +0000 (13:10 +0000)
committerJim Procter <jprocter@issues.jalview.org>
Wed, 7 Feb 2018 13:10:29 +0000 (13:10 +0000)
test/jalview/structure/StructureSelectionManagerTest.java

index 96d36ba..5b5c4a2 100644 (file)
@@ -35,9 +35,11 @@ import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.ext.jmol.JmolCommands;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
+import jalview.gui.SequenceRenderer;
 import jalview.gui.StructureChooser;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
@@ -181,6 +183,160 @@ public class StructureSelectionManagerTest extends Jalview2xmlBase
     assertEquals("ALA:   1  1gaqB", sf.getDescription());
   }
 
+  /**
+   * Verify that RESNUM sequence features are present after creating a PDB
+   * mapping from a local file, then that everything stays in the same place
+   * when the file is viewed. The corner case is that 4IM2 is a fragment of a
+   * PDB file, which still includes the 'ID' field - a bug in Jalview 2.10.3
+   * causes features, annotation and positions to be remapped to the wrong place
+   * on viewing the structure
+   */
+  @Test(groups = { "Functional" })
+  public void testMapping_EqualsFeatures()
+  {
+    SequenceI seq = new Sequence("4IM2|A",
+            "LDFCIRNIEKTVMGEISDIHTKLLRLSSSQGTIE");
+    String P4IM2_MISSING = "examples/testdata/4IM2_missing.pdb";
+    StructureSelectionManager sm = new StructureSelectionManager();
+    sm.setProcessSecondaryStructure(true);
+    sm.setAddTempFacAnnot(true);
+    StructureFile pmap = sm.setMapping(true, new SequenceI[] { seq },
+            new String[]
+            { null }, P4IM2_MISSING,
+            DataSourceType.FILE);
+    assertTrue(pmap != null);
+
+    assertEquals(1, pmap.getSeqs().size());
+    assertEquals("4IM2|A", pmap.getSeqs().get(0).getName());
+
+    List<int[]> structuremap1 = new ArrayList(
+            sm.getMapping(P4IM2_MISSING)[0]
+                    .getPDBResNumRanges(seq.getStart(), seq.getEnd()));
+
+    /*
+     * Verify a RESNUM sequence feature in the PDBfile sequence
+     * LEU468 - start+0 
+     * VAL479 - start+11
+     * MET486 - start+12
+     * GLY496 - start+13
+     * GLU516 - start+33 (last)
+     * 
+     * Expect features and mapping to resolve to same residues.
+     * Also try creating a view and test again
+     *   
+     */
+    String[] feats = new String[] { "LEU", "468", "VAL", "479", "MET",
+        "486", "GLY", "496", "GLU", "516" };
+    int[] offset = new int[] { 0, 11, 12, 13, 33 };
+
+    List<String> fdesc = new ArrayList<>();
+    for (int f = 0; f < feats.length; f += 2)
+    {
+      fdesc.add(feats[f] + ": " + feats[f + 1] + "  4im2A");
+    }
+    SequenceI pdbseq = pmap.getSeqs().get(0);
+    verifySeqFeats(pdbseq, offset, fdesc);
+
+    /// Now load as a view
+
+    AlignFrame alf = new FileLoader(false).LoadFileWaitTillLoaded(
+            "examples/testdata/4IM2_missing.pdb", DataSourceType.FILE);
+    AlignmentI pdbal = alf.getViewport().getAlignment();
+    SequenceI pdb_viewseq = pdbal.getSequenceAt(0);
+    assertEquals(pdb_viewseq.getSequenceAsString(),
+            seq.getSequenceAsString());
+    // verify the feature location on the sequence when pdb imported as an
+    // alignment
+    verifySeqFeats(pdb_viewseq, offset, fdesc);
+
+
+    JalviewStructureDisplayI viewr = openStructureViaChooser(alf,
+            pdb_viewseq, "4IM2");
+
+    // and check all is good with feature location still
+    verifySeqFeats(pdb_viewseq, offset, fdesc);
+
+    // finally check positional mapping for sequence and structure
+    PDBEntry pdbe = seq.getPDBEntry("4IM2");
+    StructureSelectionManager apssm = alf.alignPanel
+            .getStructureSelectionManager();
+    StructureMapping[] smap = apssm
+            .getMapping(pdbe.getFile());
+    assertNotNull(smap);
+    assertNotNull(smap[0]);
+    // find the last position in the alignment sequence - this is not
+    // 'SequenceI.getEnd()' - which gets the last PDBRESNUM rather than
+    // SequenceI.getStart() + number of residues in file...
+    int realSeqEnd = pdb_viewseq.findPosition(pdb_viewseq.getLength());
+    List<int[]> ranges = smap[0].getPDBResNumRanges(pdb_viewseq.getStart(),
+            realSeqEnd);
+    assertEquals(structuremap1.size(), ranges.size());
+    int tot_mapped = 0;
+    for (int p = 0; p < ranges.size(); p++)
+    {
+      assertArrayEquals(structuremap1.get(p), ranges.get(p));
+      tot_mapped += 1 + (structuremap1.get(p)[1] - structuremap1.get(p)[0]);
+    }
+
+    assertEquals(pdb_viewseq.getLength(), tot_mapped);
+
+    int lastmappedp = StructureMapping.UNASSIGNED_VALUE;
+    for (int rp = pdb_viewseq.getStart(), rpEnd = pdb_viewseq
+            .findPosition(pdb_viewseq.getLength() - 1); rp <= rpEnd; rp++)
+    {
+      int mappedp = smap[0].getPDBResNum(rp);
+      if (mappedp != StructureMapping.UNASSIGNED_VALUE)
+      {
+        tot_mapped--;
+        if (lastmappedp == mappedp)
+        {
+          Assert.fail("Duplicate mapped position at " + rp + " (dupe = "
+                  + mappedp + ")");
+        }
+      }
+    }
+
+    Assert.assertEquals(tot_mapped, 0,
+            "Different number of mapped residues compared to ranges of mapped residues");
+
+    // positional mapping to atoms for color by structure is still wrong, even
+    // though panel looks correct.
+
+    StructureMappingcommandSet smcr[] = JmolCommands
+            .getColourBySequenceCommand(apssm,
+            new String[]
+            { pdbe.getFile() },
+            new SequenceI[][]
+            { new SequenceI[] { pdb_viewseq } },
+                    new SequenceRenderer(alf.alignPanel.getAlignViewport()),
+                    alf.alignPanel);
+    // Expected - all residues are white
+    for (StructureMappingcommandSet smm : smcr)
+    {
+      for (String c : smm.commands)
+      {
+        System.out.println(c);
+      }
+    }
+
+  }
+
+  private void verifySeqFeats(SequenceI pdbseq, int[] offset,
+          List<String> fdesc)
+  {
+    for (int o = 0; o < offset.length; o++)
+    {
+      int res = pdbseq.findPosition(offset[o]);
+      List<SequenceFeature> sf = pdbseq.getFeatures().findFeatures(res, res,
+              "RESNUM");
+      assertEquals("Expected sequence feature at position " + res + "("
+              + offset[o] + ")", 1, sf.size());
+      assertEquals("Wrong description at " + res + "(" + offset[o] + ")",
+              fdesc.get(o), sf.get(0).getDescription());
+    }
+
+  }
+
   @Test(groups= {"Network"})
   public void testAssociatedMappingToSubSeq() throws Exception
   {