JAL-845 smarter test for 'mappability' when adding sequences to an
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 11 Mar 2015 10:55:08 +0000 (10:55 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 11 Mar 2015 10:55:08 +0000 (10:55 +0000)
alignment

src/jalview/analysis/AlignmentUtils.java
src/jalview/gui/AlignViewport.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;
+  }
 }
index 430f373..6b16d94 100644 (file)
@@ -951,17 +951,11 @@ public class AlignViewport extends AlignmentViewport implements
      * If one alignment is protein and one nucleotide, with at least one
      * sequence name in common, offer to open a linked alignment.
      */
-    if (getAlignment().isNucleotide() != al.isNucleotide())
+    if (AlignmentUtils.isMappable(al, getAlignment()))
     {
-      // TODO: JAL-845 try a bit harder to link up imported sequences
-      final Set<String> sequenceNames = getAlignment().getSequenceNames();
-      sequenceNames.retainAll(al.getSequenceNames());
-      if (!sequenceNames.isEmpty()) // at least one sequence name in both
+      if (openLinkedAlignment(al, title))
       {
-        if (openLinkedAlignment(al, title))
-        {
-          return;
-        }
+        return;
       }
     }
     // TODO: JAL-407 regardless of above - identical sequences (based on ID and