}
/**
- * Remove the last 3 mapped positions from the given ranges
- *
- * @param ranges
- * @param mappedLength
- */
- public static void unmapStopCodon(List<int[]> ranges,
- int mappedLength)
- {
- if (mappedLength < 3)
- {
- return;
- }
- boolean done = false;
- int targetLength = mappedLength - 3;
- int mapped = 0;
- Iterator<int[]> it = ranges.iterator();
- while (!done && it.hasNext())
- {
- int[] range = it.next();
- int length = Math.abs(range[1] - range[0]) + 1;
- if (mapped + length == targetLength)
- {
- done = true;
- }
- else if (mapped + length < targetLength)
- {
- mapped += length;
- continue;
- }
- else
- {
- /*
- * need just a bit of this range
- */
- int needed = targetLength - mapped;
- int sense = range[1] >= range[0] ? 1 : -1;
- range[1] = range[0] + (sense * (needed - 1));
- done = true;
- }
- }
- /*
- * remove any trailing ranges
- */
- while (it.hasNext())
- {
- it.next();
- it.remove();
- }
- }
-
- /**
- * Returns the total length of the supplied ranges
+ * Returns the total length of the supplied ranges, which may be as single
+ * [start, end] or multiple [start, end, start, end ...]
*
* @param ranges
* @return
int length = 0;
for (int[] range : ranges)
{
- length += Math.abs(range[1] - range[0]) + 1;
+ if (range.length % 2 != 0)
+ {
+ System.err.println("Error unbalance start/end ranges: "
+ + ranges.toString());
+ return 0;
+ }
+ for (int i = 0; i < range.length - 1; i += 2)
+ {
+ length += Math.abs(range[i + 1] - range[i]) + 1;
+ }
}
return length;
}
}
return false;
}
+
+ /**
+ * Removes a specified number of positions from the start of a ranges list.
+ * For example, could be used to adjust cds ranges to allow for an incomplete
+ * start codon. Subranges are removed completely, or their start positions
+ * adjusted, until the required number of positions has been removed from the
+ * range. Reverse strand ranges are supported. The input array is not
+ * modified.
+ *
+ * @param removeCount
+ * @param ranges
+ * an array of [start, end, start, end...] positions
+ * @return a new array with the first removeCount positions removed
+ */
+ public static int[] removeStartPositions(int removeCount,
+ final int[] ranges)
+ {
+ if (removeCount <= 0)
+ {
+ return ranges;
+ }
+
+ int[] copy = Arrays.copyOf(ranges, ranges.length);
+ int sxpos = -1;
+ int cdspos = 0;
+ for (int x = 0; x < copy.length && sxpos == -1; x += 2)
+ {
+ cdspos += Math.abs(copy[x + 1] - copy[x]) + 1;
+ if (removeCount < cdspos)
+ {
+ /*
+ * we have removed enough, time to finish
+ */
+ sxpos = x;
+
+ /*
+ * increment start of first exon, or decrement if reverse strand
+ */
+ if (copy[x] <= copy[x + 1])
+ {
+ copy[x] = copy[x + 1] - cdspos + removeCount + 1;
+ }
+ else
+ {
+ copy[x] = copy[x + 1] + cdspos - removeCount - 1;
+ }
+ break;
+ }
+ }
+
+ if (sxpos > 0)
+ {
+ /*
+ * we dropped at least one entire sub-range - compact the array
+ */
+ int[] nxon = new int[copy.length - sxpos];
+ System.arraycopy(copy, sxpos, nxon, 0, copy.length - sxpos);
+ return nxon;
+ }
+ return copy;
+ }
}