JAL-3748 allow AlignedCodonFrame.covers to optionally only require coverage for eithe...
authorJim Procter <jprocter@issues.jalview.org>
Wed, 23 Sep 2020 15:35:18 +0000 (16:35 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Wed, 23 Sep 2020 15:35:18 +0000 (16:35 +0100)
src/jalview/datamodel/AlignedCodonFrame.java

index c3d17dc..1b3c334 100644 (file)
@@ -118,19 +118,20 @@ public class AlignedCodonFrame
      */
     public boolean covers(SequenceI seq)
     {
-      return covers(seq,false);
+      return covers(seq,false,false);
     }
     /**
      * 
      * @param seq
-     * @param localCover - when true - compare extent of seq's dataset sequence rather than the local extent 
-     * @return true if mapping covers full length of given sequence 
+     * @param localCover - when true - compare extent of seq's dataset sequence rather than the local extent
+     * @param either - when true coverage is required for either seq or the mapped sequence 
+     * @return true if mapping covers full length of given sequence (or the other if either==true)
      */
-    public boolean covers(SequenceI seq, boolean localCover)
+    public boolean covers(SequenceI seq, boolean localCover,boolean either)
     {
-      List<int[]> mappedRanges = null;
+      List<int[]> mappedRanges = null,otherRanges=null;
       MapList mapList = mapping.getMap();
-      int mstart=seq.getStart(),mend=seq.getEnd()
+      int mstart=seq.getStart(),mend=seq.getEnd(),ostart,oend;
               ;
       if (fromSeq == seq || fromSeq == seq.getDatasetSequence())
       {
@@ -140,6 +141,9 @@ public class AlignedCodonFrame
           mend=fromSeq.getEnd();
         }
         mappedRanges = mapList.getFromRanges();
+        otherRanges=mapList.getToRanges();
+        ostart=mapping.to.getStart();
+        oend=mapping.to.getEnd();
       }
       else if (mapping.to == seq || mapping.to == seq.getDatasetSequence())
       {
@@ -149,6 +153,9 @@ public class AlignedCodonFrame
           mend=mapping.to.getEnd();
         }
         mappedRanges = mapList.getToRanges();
+        otherRanges=mapList.getFromRanges();
+        ostart=fromSeq.getStart();
+        oend=fromSeq.getEnd();
       }
       else
       {
@@ -160,23 +167,45 @@ public class AlignedCodonFrame
        * (necessary for circular CDS - example EMBL:J03321:AAA91567)
        * and mapped length covers (at least) sequence length
        */
-      int length = 0;
+      int length = countRange(mappedRanges,mstart,mend);
+
+      if (length != -1)
+      {
+        // add 1 to mapped length to allow for a mapped stop codon
+        if (length + 1 >= (mend - mstart + 1))
+        {
+          return true;
+        }
+      }
+      if (either)
+      {
+        // also check coverage of the other range
+        length = countRange(otherRanges, ostart, oend);
+        if (length != -1)
+        {
+          if (length + 1 >= (oend - ostart + 1))
+          {
+            return true;
+          }
+        }
+      }
+      return false;
+    }
+    private int countRange(List<int[]> mappedRanges,int mstart,int mend)
+    {
+      int length=0;
       for (int[] range : mappedRanges)
       {
         int from = Math.min(range[0], range[1]);
         int to = Math.max(range[0], range[1]);
         if (from < mstart || to > mend)
         {
-          return false;
+          return -1;
         }
         length += (to - from + 1);
       }
-      // add 1 to mapped length to allow for a mapped stop codon
-      if (length + 1 < (mend - mstart + 1))
-      {
-        return false;
-      }
-      return true;
+      return length;
+    }
     }
   }
 
@@ -480,7 +509,7 @@ public class AlignedCodonFrame
       {
         for (SequenceI sourceAligned : al.getSequences())
         {
-          if (ssm.covers(sourceAligned,true))
+          if (ssm.covers(sourceAligned,true,false))
           {
             if (map != null)
             {
@@ -504,7 +533,7 @@ public class AlignedCodonFrame
       {
         for (SequenceI sourceAligned : al.getSequences())
         {
-          if (ssm.covers(sourceAligned,true))
+          if (ssm.covers(sourceAligned,true,true))
           {
             if (map != null)
             {