int toRatio)
{
this();
+ fromRange = coalesceRanges(fromRange);
+ toRange = coalesceRanges(toRange);
this.fromShifts = fromRange;
this.toShifts = toRange;
this.fromRatio = fromRatio;
}
/**
+ * Consolidates a list of ranges so that any contiguous ranges are merged
+ *
+ * @param ranges
+ * @return
+ */
+ public static List<int[]> coalesceRanges(List<int[]> ranges)
+ {
+ if (ranges == null || ranges.size() < 2) {
+ return ranges;
+ }
+
+ boolean changed = false;
+ List<int[]> merged = new ArrayList<int[]>();
+ int[] lastRange = ranges.get(0);
+ int lastDirection = lastRange[1] >= lastRange[0] ? 1 : -1;
+ merged.add(lastRange);
+
+ for (int[] range : ranges)
+ {
+ if (range == lastRange)
+ {
+ continue;
+ }
+ int direction = range[1] >= range[0] ? 1 : -1;
+
+ /*
+ * if next range is in the same direction as last and contiguous,
+ * just update the end position of the last range
+ */
+ if ((range[1] == range[0] || direction == lastDirection)
+ && (range[0] == lastRange[1] || range[0] == lastRange[1]
+ + lastDirection))
+ {
+ lastRange[1] = range[1];
+ changed = true;
+ }
+ else
+ {
+ merged.add(range);
+ lastRange = range;
+ // careful: merging [5, 5] after [7, 6] should keep negative direction
+ lastDirection = (range[1] == range[0]) ? lastDirection : direction;
+ }
+ }
+
+ return changed ? merged : ranges;
+ }
+
+ /**
* get all mapped positions from 'from' to 'to'
*
* @return int[][] { int[] { fromStart, fromFinish, toStart, toFinish }, int
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertSame;
import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
import java.util.ArrayList;
import java.util.Arrays;
1);
assertTrue(ml.isFromForwardStrand());
}
+
+ /**
+ * Test the method that merges a list of ranges where possible
+ */
+ @Test(groups = { "Functional" })
+ public void testCoalesceRanges()
+ {
+ assertNull(MapList.coalesceRanges(null));
+ List<int[]> ranges = new ArrayList<int[]>();
+ assertSame(ranges, MapList.coalesceRanges(ranges));
+ ranges.add(new int[] { 1, 3 });
+ assertSame(ranges, MapList.coalesceRanges(ranges));
+
+ // add non-contiguous range:
+ ranges.add(new int[] { 5, 6 });
+ assertSame(ranges, MapList.coalesceRanges(ranges));
+
+ // 'contiguous' range in opposite direction is not merged:
+ ranges.add(new int[] { 7, 6 });
+ assertSame(ranges, MapList.coalesceRanges(ranges));
+
+ // merging in forward direction:
+ ranges.clear();
+ ranges.add(new int[] { 1, 3 });
+ ranges.add(new int[] { 4, 5 });
+ ranges.add(new int[] { 5, 5 });
+ ranges.add(new int[] { 5, 7 });
+ List<int[]> merged = MapList.coalesceRanges(ranges);
+ assertEquals(1, merged.size());
+ assertArrayEquals(new int[] { 1, 7 }, merged.get(0));
+
+ // merging in reverse direction:
+ ranges.clear();
+ ranges.add(new int[] { 7, 5 });
+ ranges.add(new int[] { 5, 4 });
+ ranges.add(new int[] { 4, 4 });
+ ranges.add(new int[] { 3, 1 });
+ merged = MapList.coalesceRanges(ranges);
+ assertEquals(1, merged.size());
+ assertArrayEquals(new int[] { 7, 1 }, merged.get(0));
+
+ // merging with switches of direction:
+ ranges.clear();
+ ranges.add(new int[] { 1, 3 });
+ ranges.add(new int[] { 4, 5 });
+ ranges.add(new int[] { 5, 5 });
+ ranges.add(new int[] { 6, 6 });
+ ranges.add(new int[] { 12, 10 });
+ ranges.add(new int[] { 9, 8 });
+ ranges.add(new int[] { 8, 8 });
+ ranges.add(new int[] { 7, 7 });
+ merged = MapList.coalesceRanges(ranges);
+ assertEquals(2, merged.size());
+ assertArrayEquals(new int[] { 1, 6 }, merged.get(0));
+ assertArrayEquals(new int[] { 12, 7 }, merged.get(1));
+ }
}