JAL-3949 - refactor logging from jalview.bin.Cache to jalview.bin.Console
[jalview.git] / src / jalview / util / MapList.java
index 198066d..d6a125b 100644 (file)
@@ -25,6 +25,8 @@ import java.util.Arrays;
 import java.util.BitSet;
 import java.util.List;
 
+import jalview.bin.Console;
+
 /**
  * A simple way of bijectively mapping a non-contiguous linear range to another
  * non-contiguous linear range.
@@ -307,7 +309,7 @@ public class MapList
       if (range.length != 2)
       {
         // throw new IllegalArgumentException(range);
-        System.err.println("Invalid format for fromRange "
+        Console.error("Invalid format for fromRange "
                 + Arrays.toString(range) + " may cause errors");
       }
       fromLowest = Math.min(fromLowest, Math.min(range[0], range[1]));
@@ -321,7 +323,7 @@ public class MapList
       if (range.length != 2)
       {
         // throw new IllegalArgumentException(range);
-        System.err.println("Invalid format for toRange "
+        Console.error("Invalid format for toRange "
                 + Arrays.toString(range) + " may cause errors");
       }
       toLowest = Math.min(toLowest, Math.min(range[0], range[1]));
@@ -427,8 +429,8 @@ public class MapList
    * @return int[] { from, to pos in range }, int[range.to-range.from+1]
    *         returning mapped position
    */
-  private int[][] posMap(List<int[]> shiftTo, int ratio,
-          List<int[]> shiftFrom, int toRatio)
+  private int[][] posMap(List<int[]> shiftTo, int sourceRatio,
+          List<int[]> shiftFrom, int targetRatio)
   {
     // TODO only used for test - remove??
     int iv = 0, ivSize = shiftTo.size();
@@ -467,7 +469,8 @@ public class MapList
     int mp[][] = new int[to - from + 2][];
     for (int i = 0; i < mp.length; i++)
     {
-      int[] m = shift(i + from, shiftTo, ratio, shiftFrom, toRatio);
+      int[] m = shift(i + from, shiftTo, sourceRatio, shiftFrom,
+              targetRatio);
       if (m != null)
       {
         if (i == 0)
@@ -1144,10 +1147,11 @@ public class MapList
   }
 
   /**
-   * Returns the [start1, end1, start2, end2, ...] positions in the 'from' range
-   * that map to positions between {@code start} and {@code end} in the 'to'
-   * range. Note that for a reverse strand mapping this will return ranges with
-   * end < start. Returns null if no mapped positions are found in start-end.
+   * <<<<<<< HEAD Returns the [start1, end1, start2, end2, ...] positions in the
+   * 'from' range that map to positions between {@code start} and {@code end} in
+   * the 'to' range. Note that for a reverse strand mapping this will return
+   * ranges with end < start. Returns null if no mapped positions are found in
+   * start-end.
    * 
    * @param start
    * @param end
@@ -1155,27 +1159,8 @@ public class MapList
    */
   public int[] locateInFrom(int start, int end)
   {
-    if (end < start)
-    {
-      int tmp = end;
-      end = start;
-      start = tmp;
-    }
-
-    /*
-     * traverse toShifts and mark offsets in fromShifts 
-     * of any positions that lie in [start, end]
-     */
-    BitSet offsets = getMappedOffsetsForPositions(start, end, toShifts,
-            toRatio, fromRatio);
-
-    /*
-     * traverse fromShifts and collect positions at the marked offsets
-     */
-    List<int[]> mapped = getPositionsForOffsets(fromShifts, offsets);
-
-    // TODO: or just return the List and adjust calling code to match
-    return mapped.isEmpty() ? null : MappingUtils.rangeListToArray(mapped);
+    return mapPositions(start, end, toShifts, fromShifts, toRatio,
+            fromRatio);
   }
 
   /**
@@ -1190,6 +1175,29 @@ public class MapList
    */
   public int[] locateInTo(int start, int end)
   {
+    return mapPositions(start, end, fromShifts, toShifts, fromRatio,
+            toRatio);
+  }
+
+  /**
+   * Helper method that returns the [start1, end1, start2, end2, ...] positions
+   * in {@code targetRange} that map to positions between {@code start} and
+   * {@code end} in {@code sourceRange}. Note that for a reverse strand mapping
+   * this will return ranges with end < start. Returns null if no mapped
+   * positions are found in start-end.
+   * 
+   * @param start
+   * @param end
+   * @param sourceRange
+   * @param targetRange
+   * @param sourceWordLength
+   * @param targetWordLength
+   * @return
+   */
+  final static int[] mapPositions(int start, int end,
+          List<int[]> sourceRange, List<int[]> targetRange,
+          int sourceWordLength, int targetWordLength)
+  {
     if (end < start)
     {
       int tmp = end;
@@ -1198,17 +1206,18 @@ public class MapList
     }
 
     /*
-     * traverse fromShifts and mark offsets in toShifts 
+     * traverse sourceRange and mark offsets in targetRange 
      * of any positions that lie in [start, end]
      */
-    BitSet offsets = getMappedOffsetsForPositions(start, end, fromShifts,
-            fromRatio, toRatio);
+    BitSet offsets = getMappedOffsetsForPositions(start, end, sourceRange,
+            sourceWordLength, targetWordLength);
 
     /*
-     * traverse toShifts and collect positions at the marked offsets
+     * traverse targetRange and collect positions at the marked offsets
      */
-    List<int[]> mapped = getPositionsForOffsets(toShifts, offsets);
+    List<int[]> mapped = getPositionsForOffsets(targetRange, offsets);
 
+    // TODO: or just return the List and adjust calling code to match
     return mapped.isEmpty() ? null : MappingUtils.rangeListToArray(mapped);
   }
 
@@ -1239,20 +1248,21 @@ public class MapList
    * 
    * @param start
    * @param end
-   * @param ranges
-   * @param wordLengthFrom
-   * @param wordLengthTo
+   * @param sourceRange
+   * @param sourceWordLength
+   * @param targetWordLength
    * @return
    */
   protected final static BitSet getMappedOffsetsForPositions(int start,
-          int end, List<int[]> ranges, int wordLengthFrom, int wordLengthTo)
+          int end, List<int[]> sourceRange, int sourceWordLength,
+          int targetWordLength)
   {
     BitSet overlaps = new BitSet();
     int offset = 0;
-    final int s1 = ranges.size();
+    final int s1 = sourceRange.size();
     for (int i = 0; i < s1; i++)
     {
-      int[] range = ranges.get(i);
+      int[] range = sourceRange.get(i);
       final int offset1 = offset;
       int overlapStartOffset = -1;
       int overlapEndOffset = -1;
@@ -1295,24 +1305,24 @@ public class MapList
         /*
          * found an overlap
          */
-        if (wordLengthFrom != wordLengthTo)
+        if (sourceWordLength != targetWordLength)
         {
           /*
            * convert any overlap found to whole words in the target range
            * (e.g. treat any partial codon overlap as if the whole codon)
            */
-          overlapStartOffset -= overlapStartOffset % wordLengthFrom;
-          overlapStartOffset = overlapStartOffset / wordLengthFrom
-                  * wordLengthTo;
+          overlapStartOffset -= overlapStartOffset % sourceWordLength;
+          overlapStartOffset = overlapStartOffset / sourceWordLength
+                  * targetWordLength;
 
           /*
            * similar calculation for range end, adding 
            * (wordLength2 - 1) for end of mapped word
            */
-          overlapEndOffset -= overlapEndOffset % wordLengthFrom;
-          overlapEndOffset = overlapEndOffset / wordLengthFrom
-                  * wordLengthTo;
-          overlapEndOffset += wordLengthTo - 1;
+          overlapEndOffset -= overlapEndOffset % sourceWordLength;
+          overlapEndOffset = overlapEndOffset / sourceWordLength
+                  * targetWordLength;
+          overlapEndOffset += targetWordLength - 1;
         }
         overlaps.set(overlapStartOffset, overlapEndOffset + 1);
       }
@@ -1323,15 +1333,15 @@ public class MapList
 
   /**
    * Returns a (possibly empty) list of the [start-end] values (positions) at
-   * offsets in the {@code ranges} list that are marked by 'on' bits in the
+   * offsets in the {@code targetRange} list that are marked by 'on' bits in the
    * {@code offsets} bitset.
    * 
-   * @param ranges
+   * @param targetRange
    * @param offsets
    * @return
    */
   protected final static List<int[]> getPositionsForOffsets(
-          List<int[]> ranges, BitSet offsets)
+          List<int[]> targetRange, BitSet offsets)
   {
     List<int[]> mapped = new ArrayList<>();
     if (offsets.isEmpty())
@@ -1351,10 +1361,10 @@ public class MapList
      */
     final int toAdd = offsets.cardinality();
     int added = 0;
-    final int s2 = ranges.size();
+    final int s2 = targetRange.size();
     for (int i = 0; added < toAdd && i < s2; i++)
     {
-      int[] range = ranges.get(i);
+      int[] range = targetRange.get(i);
       added += addOffsetPositions(mapped, traversed, range, offsets);
       traversed += Math.abs(range[1] - range[0]) + 1;
     }
@@ -1414,4 +1424,36 @@ public class MapList
 
     return added;
   }
+
+  /*
+   * Returns the [start, end...] positions in the range mapped from, that are
+   * mapped to by part or all of the given begin-end of the range mapped to.
+   * Returns null if begin-end does not overlap any position mapped to.
+   * 
+   * @param begin
+   * @param end
+   * @return
+   */
+  public int[] getOverlapsInFrom(final int begin, final int end)
+  {
+    int[] overlaps = MappingUtils.findOverlap(toShifts, begin, end);
+
+    return overlaps == null ? null : locateInFrom(overlaps[0], overlaps[1]);
+  }
+
+  /**
+   * Returns the [start, end...] positions in the range mapped to, that are
+   * mapped to by part or all of the given begin-end of the range mapped from.
+   * Returns null if begin-end does not overlap any position mapped from.
+   * 
+   * @param begin
+   * @param end
+   * @return
+   */
+  public int[] getOverlapsInTo(final int begin, final int end)
+  {
+    int[] overlaps = MappingUtils.findOverlap(fromShifts, begin, end);
+
+    return overlaps == null ? null : locateInTo(overlaps[0], overlaps[1]);
+  }
 }