Merge branch 'kjvdh/features/PhylogenyViewer_tabbedsupport' into merge/2_11_2/kjvdh...
[jalview.git] / src / jalview / util / MappingUtils.java
index 33decb4..05fc1c6 100644 (file)
@@ -29,17 +29,19 @@ import java.util.Map;
 
 import jalview.analysis.AlignmentSorter;
 import jalview.api.AlignViewportI;
-import jalview.bin.Cache;
+import jalview.bin.Console;
 import jalview.commands.CommandI;
 import jalview.commands.EditCommand;
 import jalview.commands.EditCommand.Action;
 import jalview.commands.EditCommand.Edit;
 import jalview.commands.OrderCommand;
 import jalview.datamodel.AlignedCodonFrame;
+import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.Mapping;
 import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SearchResultsI;
@@ -79,7 +81,7 @@ public final class MappingUtils
       action = action.getUndoAction();
     }
     // TODO write this
-    Cache.log.error("MappingUtils.mapCutOrPaste not yet implemented");
+    Console.error("MappingUtils.mapCutOrPaste not yet implemented");
   }
 
   /**
@@ -362,19 +364,17 @@ public final class MappingUtils
        */
       int startResiduePos = selected.findPosition(firstUngappedPos);
       int endResiduePos = selected.findPosition(lastUngappedPos);
-
-      for (AlignedCodonFrame acf : codonFrames)
+      for (SequenceI seq : mapTo.getAlignment().getSequences())
       {
-        SequenceI mappedSequence = targetIsNucleotide
-                ? acf.getDnaForAaSeq(selected)
-                : acf.getAaForDnaSeq(selected);
-        if (mappedSequence != null)
+        int mappedStartResidue = 0;
+        int mappedEndResidue = 0;
+        for (AlignedCodonFrame acf : codonFrames)
         {
-          for (SequenceI seq : mapTo.getAlignment().getSequences())
+          // rather than use acf.getCoveringMapping() we iterate through all
+          // mappings to make sure all CDS are selected for a protein
+          for (SequenceToSequenceMapping map : acf.getMappings())
           {
-            int mappedStartResidue = 0;
-            int mappedEndResidue = 0;
-            if (seq.getDatasetSequence() == mappedSequence)
+            if (map.covers(selected) && map.covers(seq))
             {
               /*
                * Found a sequence mapping. Locate the start/end mapped residues.
@@ -382,6 +382,7 @@ public final class MappingUtils
               List<AlignedCodonFrame> mapping = Arrays
                       .asList(new AlignedCodonFrame[]
                       { acf });
+              // locate start
               SearchResultsI sr = buildSearchResults(selected,
                       startResiduePos, mapping);
               for (SearchResultMatchI m : sr.getResults())
@@ -389,6 +390,7 @@ public final class MappingUtils
                 mappedStartResidue = m.getStart();
                 mappedEndResidue = m.getEnd();
               }
+              // locate end - allowing for adjustment of start range
               sr = buildSearchResults(selected, endResiduePos, mapping);
               for (SearchResultMatchI m : sr.getResults())
               {
@@ -450,18 +452,21 @@ public final class MappingUtils
     {
       for (AlignedCodonFrame acf : mappings)
       {
-        SequenceI mappedSeq = mappingToNucleotide ? acf.getDnaForAaSeq(seq)
-                : acf.getAaForDnaSeq(seq);
-        if (mappedSeq != null)
+        for (SequenceI seq2 : mapTo.getSequences())
         {
-          for (SequenceI seq2 : mapTo.getSequences())
+          /*
+           * the corresponding peptide / CDS is the one for which there is
+           * a complete ('covering') mapping to 'seq'
+           */
+          SequenceI peptide = mappingToNucleotide ? seq2 : seq;
+          SequenceI cds = mappingToNucleotide ? seq : seq2;
+          SequenceToSequenceMapping s2s = acf.getCoveringMapping(cds,
+                  peptide);
+          if (s2s != null)
           {
-            if (seq2.getDatasetSequence() == mappedSeq)
-            {
-              mappedOrder.add(seq2);
-              j++;
-              break;
-            }
+            mappedOrder.add(seq2);
+            j++;
+            break;
           }
         }
       }
@@ -525,7 +530,7 @@ public final class MappingUtils
 
     if (colsel == null)
     {
-      return; // mappedColumns;
+      return;
     }
 
     char fromGapChar = mapFrom.getAlignment().getGapCharacter();
@@ -549,7 +554,7 @@ public final class MappingUtils
       mapHiddenColumns(regions.next(), codonFrames, newHidden,
               fromSequences, toSequences, fromGapChar);
     }
-    return; // mappedColumns;
+    return;
   }
 
   /**
@@ -667,7 +672,9 @@ public final class MappingUtils
          */
         for (SequenceI toSeq : toSequences)
         {
-          if (toSeq.getDatasetSequence() == mappedSeq)
+          if (toSeq.getDatasetSequence() == mappedSeq
+                  && mappedStartResidue >= toSeq.getStart()
+                  && mappedEndResidue <= toSeq.getEnd())
           {
             int mappedStartCol = toSeq.findIndex(mappedStartResidue);
             int mappedEndCol = toSeq.findIndex(mappedEndResidue);
@@ -836,7 +843,7 @@ public final class MappingUtils
     {
       if (range.length % 2 != 0)
       {
-        Cache.log.error(
+        Console.error(
                 "Error unbalance start/end ranges: " + ranges.toString());
         return 0;
       }
@@ -992,7 +999,7 @@ public final class MappingUtils
         /*
          * not coded for [start1, end1, start2, end2, ...]
          */
-        Cache.log.error(
+        Console.error(
                 "MappingUtils.removeEndPositions doesn't handle multiple  ranges");
         return;
       }
@@ -1003,7 +1010,7 @@ public final class MappingUtils
         /*
          * not coded for a reverse strand range (end < start)
          */
-        Cache.log.error(
+        Console.error(
                 "MappingUtils.removeEndPositions doesn't handle reverse strand");
         return;
       }
@@ -1102,4 +1109,21 @@ public final class MappingUtils
 
     return foundStart && to >= from ? new int[] { from, to } : null;
   }
+    
+  public static <K, V> Map<K, V> putWithDuplicationCheck(Map<K, V> map, K key,
+          V value)
+  {
+    if (!map.containsKey(key))
+    {
+      map.put(key, value);
+    }
+    else
+    {
+      jalview.bin.Cache.log.warn(
+              "Attempt to add duplicate entry detected for map with key: "
+                      + key.toString() + " and value: " + value.toString());
+    }
+  
+    return map;
+  }
 }