X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Futil%2FMapList.java;fp=src%2Fjalview%2Futil%2FMapList.java;h=c5654fbee62fd697f85c53ebb55e44302eb28b29;hb=39b4859e1a1b011af5d06058461db4d075acb578;hp=731e976ecb1686b62ef2037c60fc3b9e0328360b;hpb=f3dcb2f8f602117ac390799b1f310dcaa9918592;p=jalview.git diff --git a/src/jalview/util/MapList.java b/src/jalview/util/MapList.java index 731e976..c5654fb 100644 --- a/src/jalview/util/MapList.java +++ b/src/jalview/util/MapList.java @@ -24,6 +24,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import jalview.bin.Cache; + /** * A simple way of bijectively mapping a non-contiguous linear range to another * non-contiguous linear range. @@ -209,8 +211,7 @@ public class MapList /** * Constructor given from and to ranges as [start1, end1, start2, end2,...]. - * If any end is equal to the next start, the ranges will be merged. There is - * no validation check that the ranges do not overlap each other. + * There is no validation check that the ranges do not overlap each other. * * @param from * contiguous regions as [start1, end1, start2, end2, ...] @@ -228,7 +229,6 @@ public class MapList this.toRatio = toRatio; fromLowest = Integer.MAX_VALUE; fromHighest = Integer.MIN_VALUE; - int added = 0; for (int i = 0; i < from.length; i += 2) { @@ -238,36 +238,16 @@ public class MapList */ fromLowest = Math.min(fromLowest, Math.min(from[i], from[i + 1])); fromHighest = Math.max(fromHighest, Math.max(from[i], from[i + 1])); - if (added > 0 && from[i] == fromShifts.get(added - 1)[1]) - { - /* - * this range starts where the last ended - just extend it - */ - fromShifts.get(added - 1)[1] = from[i + 1]; - } - else - { - fromShifts.add(new int[] { from[i], from[i + 1] }); - added++; - } + fromShifts.add(new int[] { from[i], from[i + 1] }); } toLowest = Integer.MAX_VALUE; toHighest = Integer.MIN_VALUE; - added = 0; for (int i = 0; i < to.length; i += 2) { toLowest = Math.min(toLowest, Math.min(to[i], to[i + 1])); toHighest = Math.max(toHighest, Math.max(to[i], to[i + 1])); - if (added > 0 && to[i] == toShifts.get(added - 1)[1]) - { - toShifts.get(added - 1)[1] = to[i + 1]; - } - else - { - toShifts.add(new int[] { to[i], to[i + 1] }); - added++; - } + toShifts.add(new int[] { to[i], to[i + 1] }); } } @@ -330,9 +310,8 @@ public class MapList if (range.length != 2) { // throw new IllegalArgumentException(range); - System.err.println( - "Invalid format for fromRange " + Arrays.toString(range) - + " may cause errors"); + Cache.log.error("Invalid format for fromRange " + + Arrays.toString(range) + " may cause errors"); } fromLowest = Math.min(fromLowest, Math.min(range[0], range[1])); fromHighest = Math.max(fromHighest, Math.max(range[0], range[1])); @@ -345,9 +324,8 @@ public class MapList if (range.length != 2) { // throw new IllegalArgumentException(range); - System.err.println("Invalid format for toRange " - + Arrays.toString(range) - + " may cause errors"); + Cache.log.error("Invalid format for toRange " + + Arrays.toString(range) + " may cause errors"); } toLowest = Math.min(toLowest, Math.min(range[0], range[1])); toHighest = Math.max(toHighest, Math.max(range[0], range[1])); @@ -357,6 +335,16 @@ public class MapList /** * Consolidates a list of ranges so that any contiguous ranges are merged. * This assumes the ranges are already in start order (does not sort them). + *

+ * The main use case for this method is when mapping cDNA sequence to its + * protein product, based on CDS feature ranges which derive from spliced + * exons, but are contiguous on the cDNA sequence. For example + *

+   *   CDS 1-20  // from exon1
+   *   CDS 21-35 // from exon2
+   *   CDS 36-71 // from exon3
+   * 'coalesce' to range 1-71
+   * 
* * @param ranges * @return the same list (if unchanged), else a new merged list, leaving the @@ -384,27 +372,6 @@ public class MapList first = false; continue; } - if (range[0] == lastRange[0] && range[1] == lastRange[1]) - { - // drop duplicate range - changed = true; - continue; - } - - /* - * drop this range if it lies within the last range - */ - if ((lastDirection == 1 && range[0] >= lastRange[0] - && range[0] <= lastRange[1] && range[1] >= lastRange[0] - && range[1] <= lastRange[1]) - || (lastDirection == -1 && range[0] <= lastRange[0] - && range[0] >= lastRange[1] - && range[1] <= lastRange[0] - && range[1] >= lastRange[1])) - { - changed = true; - continue; - } int direction = range[1] >= range[0] ? 1 : -1; @@ -415,11 +382,7 @@ public class MapList boolean sameDirection = range[1] == range[0] || direction == lastDirection; boolean extending = range[0] == lastRange[1] + lastDirection; - boolean overlapping = (lastDirection == 1 && range[0] >= lastRange[0] - && range[0] <= lastRange[1]) - || (lastDirection == -1 && range[0] <= lastRange[0] - && range[0] >= lastRange[1]); - if (sameDirection && (overlapping || extending)) + if (sameDirection && extending) { lastRange[1] = range[1]; changed = true; @@ -1134,8 +1097,8 @@ public class MapList } /** - * A helper method that returns true unless at least one range has start > end. - * Behaviour is undefined for a mixture of forward and reverse ranges. + * A helper method that returns true unless at least one range has start > + * end. Behaviour is undefined for a mixture of forward and reverse ranges. * * @param ranges * @return @@ -1246,4 +1209,36 @@ public class MapList { return fromShifts.size() == 1 && toShifts.size() == 1; } + + /** + * 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]); + } }