X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Futil%2FMapList.java;h=d6a125bc3460ca2727bbf76151e7ade3cb64bf2b;hb=cb8e52fbbc5f725e3f7f48c672cdddb0690bd978;hp=198066d7bcdcee7809445cc71934cf7aed08e55a;hpb=1e507c915398542fe6e206e7a6f2620283243f1e;p=jalview.git diff --git a/src/jalview/util/MapList.java b/src/jalview/util/MapList.java index 198066d..d6a125b 100644 --- a/src/jalview/util/MapList.java +++ b/src/jalview/util/MapList.java @@ -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 shiftTo, int ratio, - List shiftFrom, int toRatio) + private int[][] posMap(List shiftTo, int sourceRatio, + List 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 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 sourceRange, List 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 mapped = getPositionsForOffsets(toShifts, offsets); + List 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 ranges, int wordLengthFrom, int wordLengthTo) + int end, List 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 getPositionsForOffsets( - List ranges, BitSet offsets) + List targetRange, BitSet offsets) { List 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]); + } }