JAL-845 smarter test for 'mappability' when adding sequences to an
[jalview.git] / src / jalview / analysis / AlignmentUtils.java
index 99ad525..ffd0c6b 100644 (file)
@@ -946,4 +946,77 @@ public class AlignmentUtils
       seqProduct.put(protein, codon.product);
     }
   }
+
+  /**
+   * Returns true if a cDNA/Protein mapping either exists, or could be made,
+   * between at least one pair of sequences in the two alignments. Currently,
+   * the logic is:
+   * <ul>
+   * <li>One alignment must be nucleotide, and the other protein</li>
+   * <li>At least one pair of sequences must be already mapped, or mappable</li>
+   * <li>Mappable means the nucleotide translation matches the protein sequence</li>
+   * <li>The translation may ignore start and stop codons if present in the
+   * nucleotide</li>
+   * </ul>
+   * 
+   * @param al1
+   * @param al2
+   * @return
+   */
+  public static boolean isMappable(AlignmentI al1, AlignmentI al2)
+  {
+    /*
+     * Require one nucleotide and one protein
+     */
+    if (al1.isNucleotide() == al2.isNucleotide())
+    {
+      return false;
+    }
+    AlignmentI dna = al1.isNucleotide() ? al1 : al2;
+    AlignmentI protein = dna == al1 ? al2 : al1;
+    Set<AlignedCodonFrame> mappings = protein.getCodonFrames();
+    for (SequenceI dnaSeq : dna.getSequences())
+    {
+      for (SequenceI proteinSeq : protein.getSequences())
+      {
+        if (isMappable(dnaSeq, proteinSeq, mappings))
+        {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Returns true if the dna sequence is mapped, or could be mapped, to the
+   * protein sequence.
+   * 
+   * @param dnaSeq
+   * @param proteinSeq
+   * @param mappings
+   * @return
+   */
+  public static boolean isMappable(SequenceI dnaSeq, SequenceI proteinSeq,
+          Set<AlignedCodonFrame> mappings)
+  {
+    SequenceI dnaDs = dnaSeq.getDatasetSequence() == null ? dnaSeq : dnaSeq.getDatasetSequence();
+    SequenceI proteinDs = proteinSeq.getDatasetSequence() == null ? proteinSeq
+            : proteinSeq.getDatasetSequence();
+    
+    /*
+     * Already mapped?
+     */
+    for (AlignedCodonFrame mapping : mappings) {
+      if ( proteinDs == mapping.getAaForDnaSeq(dnaDs)) {
+        return true;
+      }
+    }
+
+    /*
+     * Just try to make a mapping (it is not yet stored), test whether
+     * successful.
+     */
+    return mapProteinToCdna(proteinDs, dnaDs) != null;
+  }
 }