JAL-3613 check sequence overlap when matching search results
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 1 May 2020 11:36:58 +0000 (12:36 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 1 May 2020 11:36:58 +0000 (12:36 +0100)
src/jalview/datamodel/SearchResults.java
src/jalview/gui/SeqPanel.java
src/jalview/util/BrowserLauncher.java
test/jalview/datamodel/SearchResultsTest.java

index 31736e5..0074d2a 100755 (executable)
@@ -175,11 +175,15 @@ public class SearchResults implements SearchResultsI
   @Override
   public boolean involvesSequence(SequenceI sequence)
   {
+    final int start = sequence.getStart();
+    final int end = sequence.getEnd();
+
     SequenceI ds = sequence.getDatasetSequence();
-    for (SearchResultMatchI _m : matches)
+    for (SearchResultMatchI m : matches)
     {
-      SequenceI matched = _m.getSequence();
-      if (matched != null && (matched == sequence || matched == ds))
+      SequenceI matched = m.getSequence();
+      if (matched != null && (matched == sequence || matched == ds)
+              && (m.getEnd() >= start) && (m.getStart() <= end))
       {
         return true;
       }
index f28217d..d7d4af0 100644 (file)
@@ -1199,7 +1199,7 @@ public class SeqPanel extends JPanel
   {
     char sequenceChar = sequence.getCharAt(column);
     int pos = sequence.findPosition(column);
-    setStatusMessage(sequence, seqIndex, sequenceChar, pos);
+    setStatusMessage(sequence.getName(), seqIndex, sequenceChar, pos);
 
     return pos;
   }
@@ -1215,7 +1215,7 @@ public class SeqPanel extends JPanel
    * Sequence 6 ID: O.niloticus.3 Nucleotide: Uracil (2)
    * </pre>
    * 
-   * @param sequence
+   * @param seqName
    * @param seqIndex
    *          sequence position in the alignment (1..)
    * @param sequenceChar
@@ -1223,7 +1223,7 @@ public class SeqPanel extends JPanel
    * @param residuePos
    *          the sequence residue position (if not over a gap)
    */
-  protected void setStatusMessage(SequenceI sequence, int seqIndex,
+  protected void setStatusMessage(String seqName, int seqIndex,
           char sequenceChar, int residuePos)
   {
     StringBuilder text = new StringBuilder(32);
@@ -1233,7 +1233,7 @@ public class SeqPanel extends JPanel
      */
     String seqno = seqIndex == -1 ? "" : " " + (seqIndex + 1);
     text.append("Sequence").append(seqno).append(" ID: ")
-            .append(sequence.getName());
+            .append(seqName);
 
     String residue = null;
 
@@ -1278,7 +1278,8 @@ public class SeqPanel extends JPanel
     {
       return;
     }
-    SequenceI ds = al.getSequenceAt(sequenceIndex).getDatasetSequence();
+    SequenceI alignedSeq = al.getSequenceAt(sequenceIndex);
+    SequenceI ds = alignedSeq.getDatasetSequence();
     for (SearchResultMatchI m : results.getResults())
     {
       SequenceI seq = m.getSequence();
@@ -1290,8 +1291,8 @@ public class SeqPanel extends JPanel
       if (seq == ds)
       {
         int start = m.getStart();
-        setStatusMessage(seq, sequenceIndex, seq.getCharAt(start - 1),
-                start);
+        setStatusMessage(alignedSeq.getName(), sequenceIndex,
+                seq.getCharAt(start - 1), start);
         return;
       }
     }
index 0bc09cc..87e57fd 100755 (executable)
@@ -523,6 +523,10 @@ public class BrowserLauncher
    */
   private static Object locateBrowser()
   {
+    if (true)
+    {
+      return "/Volumes/Macintosh HD/Applications/Firefox.app/Contents/MacOS/firefox";
+    }
     if (browser != null)
     {
       return browser;
@@ -711,7 +715,7 @@ public class BrowserLauncher
    */
   public static void openURL(String url) throws IOException
   {
-    if (!loadedWithoutErrors)
+    if (false && !loadedWithoutErrors)
     {
       throw new IOException(MessageManager
               .formatMessage("exception.browser_not_found", new String[]
index 349b5d1..a302d6e 100644 (file)
@@ -25,14 +25,14 @@ import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
 
-import jalview.gui.JvOptionPane;
-
 import java.util.BitSet;
 
 import org.junit.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import jalview.gui.JvOptionPane;
+
 public class SearchResultsTest
 {
 
@@ -303,4 +303,68 @@ public class SearchResultsTest
     sr.addResult(seq1, 3, 6);
     assertEquals(2, sr.getSize());
   }
+
+  /**
+   * Test for method that checks if search results matches a sequence region
+   */
+  @Test(groups = { "Functional" })
+  public void testInvolvesSequence()
+  {
+    SequenceI dataset = new Sequence("genome", "ATGGCCCTTTAAGCAACATTT");
+    // first 'exon':
+    SequenceI cds1 = new Sequence("cds1/1-12", "ATGGCCCTTTAA");
+    cds1.setDatasetSequence(dataset);
+    // overlapping second 'exon':
+    SequenceI cds2 = new Sequence("cds2/7-18", "CTTTAAGCAACA");
+    cds2.setDatasetSequence(dataset);
+    // unrelated sequence
+    SequenceI cds3 = new Sequence("cds3", "ATGGCCCTTTAAGCAACA");
+
+    SearchResults sr = new SearchResults();
+    assertFalse(sr.involvesSequence(cds1));
+
+    /*
+     * cds1 and cds2 share the same dataset sequence, but
+     * only cds1 overlaps match 4:6 (fixes bug JAL-3613)
+     */
+    sr.addResult(dataset, 4, 6);
+    assertTrue(sr.involvesSequence(cds1));
+    assertFalse(sr.involvesSequence(cds2));
+    assertFalse(sr.involvesSequence(cds3));
+
+    /*
+     * search results overlap cds2 only
+     */
+    sr = new SearchResults();
+    sr.addResult(dataset, 18, 18);
+    assertFalse(sr.involvesSequence(cds1));
+    assertTrue(sr.involvesSequence(cds2));
+
+    /*
+     * add a search result overlapping cds1
+     */
+    sr.addResult(dataset, 1, 1);
+    assertTrue(sr.involvesSequence(cds1));
+    assertTrue(sr.involvesSequence(cds2));
+
+    /*
+     * single search result overlapping both
+     */
+    sr = new SearchResults();
+    sr.addResult(dataset, 10, 12);
+    assertTrue(sr.involvesSequence(cds1));
+    assertTrue(sr.involvesSequence(cds2));
+
+    /*
+     * search results matching aligned sequence
+     */
+    sr = new SearchResults();
+    sr.addResult(cds1, 10, 12);
+    assertTrue(sr.involvesSequence(cds1));
+    assertFalse(sr.involvesSequence(cds2));
+    sr.addResult(cds2, 1, 3); // no start-end overlap
+    assertFalse(sr.involvesSequence(cds2));
+    sr.addResult(cds2, 7, 9); // start-end overlap
+    assertTrue(sr.involvesSequence(cds2));
+  }
 }