JAL-3700 check for 'covering' mapping when matching CDS to peptides
[jalview.git] / src / jalview / datamodel / AlignedCodonFrame.java
index fffa137..7fa8b29 100644 (file)
@@ -107,6 +107,55 @@ public class AlignedCodonFrame
     {
       return mapping;
     }
+
+    /**
+     * Returns true if the mapping covers the full length of the given sequence.
+     * This allows us to distinguish the CDS that codes for a protein from
+     * another overlapping CDS in the parent dna sequence.
+     * 
+     * @param seq
+     * @return
+     */
+    public boolean covers(SequenceI seq)
+    {
+      List<int[]> mappedRanges = null;
+      MapList mapList = mapping.getMap();
+      if (fromSeq == seq || fromSeq == seq.getDatasetSequence())
+      {
+        mappedRanges = mapList.getFromRanges();
+      }
+      else if (mapping.to == seq || mapping.to == seq.getDatasetSequence())
+      {
+        mappedRanges = mapList.getToRanges();
+      }
+      else
+      {
+        return false;
+      }
+
+      /*
+       * check that each mapped range lieS with the sequence range
+       * (necessary for circular CDS - example EMBL:J03321:AAA91567)
+       * and mapped length covers (at least) sequence length
+       */
+      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 < seq.getStart() || to > seq.getEnd())
+        {
+          return false;
+        }
+        length += (to - from + 1);
+      }
+      // add 1 to mapped length to allow for a mapped stop codon
+      if (length + 1 < (seq.getEnd() - seq.getStart() + 1))
+      {
+        return false;
+      }
+      return true;
+    }
   }
 
   private List<SequenceToSequenceMapping> mappings;
@@ -261,9 +310,12 @@ public class AlignedCodonFrame
   }
 
   /**
+   * Return the corresponding aligned or dataset dna sequence for given amino
+   * acid sequence, or null if not found. returns the sequence from
+   * the first mapping found that involves the protein sequence.
    * 
-   * @param sequenceRef
-   * @return null or corresponding aaSeq entry for dnaSeq entry
+   * @param aaSeqRef
+   * @return
    */
   public SequenceI getDnaForAaSeq(SequenceI aaSeqRef)
   {
@@ -783,4 +835,17 @@ public class AlignedCodonFrame
   {
     return mappings;
   }
+
+  public SequenceToSequenceMapping getCoveringMapping(SequenceI cds,
+          SequenceI peptide)
+  {
+    for (SequenceToSequenceMapping mapping : mappings)
+    {
+      if (mapping.covers(peptide) && mapping.covers(cds))
+      {
+        return mapping;
+      }
+    }
+    return null;
+  }
 }