* @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();
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)
for (int[] range : map.getFromRanges())
{
- addRange(range, fromShifts);
+ MappingUtils.addRange(range, fromShifts);
}
for (int[] range : map.getToRanges())
{
- addRange(range, toShifts);
+ MappingUtils.addRange(range, toShifts);
}
}
/**
- * Adds the given range to a list of ranges. If the new range just extends
- * existing ranges, the current endpoint is updated instead.
- *
- * @param range
- * @param addTo
- */
- static void addRange(int[] range, List<int[]> addTo)
- {
- /*
- * list is empty - add to it!
- */
- if (addTo.size() == 0)
- {
- addTo.add(range);
- return;
- }
-
- int[] last = addTo.get(addTo.size() - 1);
- boolean lastForward = last[1] >= last[0];
- boolean newForward = range[1] >= range[0];
-
- /*
- * contiguous range in the same direction - just update endpoint
- */
- if (lastForward == newForward && last[1] == range[0])
- {
- last[1] = range[1];
- return;
- }
-
- /*
- * next range starts at +1 in forward sense - update endpoint
- */
- if (lastForward && newForward && range[0] == last[1] + 1)
- {
- last[1] = range[1];
- return;
- }
-
- /*
- * next range starts at -1 in reverse sense - update endpoint
- */
- if (!lastForward && !newForward && range[0] == last[1] - 1)
- {
- last[1] = range[1];
- return;
- }
-
- /*
- * just add the new range
- */
- addTo.add(range);
- }
-
- /**
* Returns true if mapping is from forward strand, false if from reverse
* strand. Result is just based on the first 'from' range that is not a single
* position. Default is true unless proven to be false. Behaviour is not well
*/
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,
+ return mapPositions(start, end, toShifts, fromShifts,
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);
}
/**
*/
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;
}
/*
- * 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);
}
*
* @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;
/*
* 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);
}
/**
* 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())
*/
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;
}