*/
public int[] locateInFrom(int start, int end)
{
+ return locateInFrom2(start, end);
+
// inefficient implementation
- int fromStart[] = shiftTo(start);
+ // int fromStart[] = shiftTo(start);
// needs to be inclusive of end of symbol position
- int fromEnd[] = shiftTo(end);
- System.out.println("locateInFrom");
- return getIntervals(fromShifts, fromStart, fromEnd, fromRatio);
+ // int fromEnd[] = shiftTo(end);
+ // return getIntervals(fromShifts, fromStart, fromEnd, fromRatio);
}
/**
*/
public int[] locateInTo(int start, int end)
{
- int toStart[] = shiftFrom(start);
- int toEnd[] = shiftFrom(end);
- return getIntervals(toShifts, toStart, toEnd, toRatio);
+ return locateInTo2(start, end);
+
+ // int toStart[] = shiftFrom(start);
+ // int toEnd[] = shiftFrom(end);
+ // return getIntervals(toShifts, toStart, toEnd, toRatio);
}
/**
List<int[]> toRanges = new ArrayList<>();
for (int[] range : getToRanges())
{
+ int fromLength = Math.abs(range[1] - range[0]) + 1;
int[] transferred = map.locateInTo(range[0], range[1]);
if (transferred == null || transferred.length % 2 != 0)
{
* convert [start1, end1, start2, end2, ...]
* to [[start1, end1], [start2, end2], ...]
*/
+ int toLength = 0;
for (int i = 0; i < transferred.length;)
{
toRanges.add(new int[] { transferred[i], transferred[i + 1] });
+ toLength += Math.abs(transferred[i + 1] - transferred[i]) + 1;
i += 2;
}
+
+ /*
+ * check we mapped the full range - if not, abort
+ */
+ if (fromLength * map.getToRatio() != toLength * map.getFromRatio())
+ {
+ return null;
+ }
}
return new MapList(getFromRanges(), toRanges, outFromRatio, outToRatio);
/**
* Returns the [start, end, start, end, ...] ranges in the 'from' range that
- * map to the given start-end in the 'to' range. Returns null if either
- * {@code start} or {@code end} is not a mapped 'to' range position.
+ * map to positions between {@code start} and {@code end} in the 'to' range.
+ * Returns null if no mapped positions are found in start-end.
*
* @param start
* @param end
List<int[]> ranges1, List<int[]> ranges2, int wordLength1,
int wordLength2)
{
+ if (end < start)
+ {
+ int tmp = end;
+ end = start;
+ start = tmp;
+ }
+
/*
* first traverse ranges1 and record count of mapped positions
* to any that overlap start-end
}
/*
- * convert positions to equivalent 'word' positions in ranges
+ * convert positions to equivalent 'word' positions in ranges2
*/
mapWords(overlaps, wordLength1, wordLength2);
List<int[]> mapped = new ArrayList<>();
final int s1 = overlaps.size();
final int s2 = ranges2.size();
- int rangeIndex = 0;
- int rangeOffset = 0;
- int mappedCount = 0;
+ int ranges2Index = 0;
- for (int i = 0 ; i < s1 ; i++)
+ /*
+ * count of mapped positions preceding ranges2[ranges2Index]
+ */
+ int traversed = 0;
+
+ /*
+ * for each [from-to] range in overlaps:
+ * - walk (what remains of) ranges2
+ * - record the values at offsets [from-to]
+ * - stop when past 'to' positions (or at end of ranges2)
+ */
+ for (int i = 0; i < s1; i++)
{
- /*
- * for each range in overlaps, walk ranges2 and record the values
- * at the offsets, advancing rangeIndex / Offset
- */
- int [] mappedRange = ranges2.get(rangeIndex);
- int [] overlap = overlaps.get(s1);
- while (mappedCount < overlap[1])
+ int[] overlap = overlaps.get(i);
+ final int toAdd = overlap[1] - overlap[0] + 1;
+ int added = 0; // how much of overlap has been 'found'
+ for (; added < toAdd && ranges2Index < s2; ranges2Index++)
{
-
+ int[] range2 = ranges2.get(ranges2Index);
+ int rangeStart = range2[0];
+ int rangeEnd = range2[1];
+ boolean reverseStrand = range2[1] < range2[0];
+ int rangeLength = Math.abs(rangeEnd - rangeStart) + 1;
+ if (traversed + rangeLength <= overlap[0])
+ {
+ /*
+ * precedes overlap - keep looking
+ */
+ traversed += rangeLength;
+ continue;
+ }
+ int overlapStart = overlap[0] - traversed;
+ int overlapEnd = Math.min(overlapStart + toAdd - added - 1,
+ rangeLength - 1);
+ int mappedFrom = range2[0] + (reverseStrand ? - overlapStart : overlapStart);
+ int mappedTo = range2[0] + (reverseStrand ? - overlapEnd : overlapEnd);
+ mapped.add(new int[] { mappedFrom, mappedTo });
+ int found = overlapEnd - overlapStart + 1;
+ added += found;
+ overlap[0] += found;
+ traversed += rangeLength;
}
}
-
+
return mapped;
}
/**
* Helper method that returns a (possibly empty) list of offsets in
- * {@code ranges} to subranges that overlap {@code start-end}. The list
- * returned holds counts of the number of positions traversed (inclusive) to
- * reach the overlapping positions, not the overlapping values. Returns null
- * if there are no overlaps.
+ * {@code ranges} to subranges that overlap {@code start-end} (where start <=
+ * end}. The list returned holds counts of the number of positions traversed
+ * (exclusive) to reach the overlapping positions, not the overlapping values.
+ * Returns null if there are no overlaps.
*
* @param ranges
* @param start
/**
* A helper method that checks whether {@code range} overlaps
- * {@code start-end}, and if so adds the positional offset of the overlap to
- * {@code positions}.
+ * {@code start-end}, and if so adds the offset of the overlap in
+ * {@code range}, plus {@code pos}, to {@code positions}.
*
* @param positions
* a list of map offsets to add to
* overlap
*/
int overlapStart = Math.max(start, range[0]);
+ int overlapStartOffset = pos + overlapStart - range[0];
int overlapEnd = Math.min(end, range[1]);
- positions
- .add(new int[]
- { 1 + overlapStart - range[0], 1 + overlapEnd - range[0] });
+ int overlapEndOffset = pos + overlapEnd - range[0];
+ int[] lastOverlap = positions.isEmpty() ? null
+ : positions.get(positions.size() - 1);
+ if (lastOverlap != null && overlapStartOffset == lastOverlap[1] + 1)
+ {
+ /*
+ * just extending the last overlap range
+ */
+ lastOverlap[1] = overlapEndOffset;
+ }
+ else
+ {
+ /*
+ * add a new (discontiguous) overlap range
+ */
+ positions.add(new int[] { overlapStartOffset, overlapEndOffset });
+ }
}
}
else
int overlapEnd = Math.min(end, range[0]);
positions
.add(new int[]
- { 1 + range[0] - overlapStart, 1 + range[0] - overlapEnd });
+ { pos + range[0] - overlapEnd,
+ pos + range[0] - overlapStart });
}
}
}
JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Functional" }, enabled = false)
public void testSomething()
{
MapList ml = new MapList(new int[] { 1, 5, 10, 15, 25, 20 },
assertEquals("[10, 12]", Arrays.toString(ml.locateInFrom(4, 4)));
assertEquals("[1, 6]", Arrays.toString(ml.locateInFrom(1, 2)));
assertEquals("[1, 9]", Arrays.toString(ml.locateInFrom(1, 3)));
+ // reversed range treated as if forwards:
+ assertEquals("[1, 9]", Arrays.toString(ml.locateInFrom(3, 1)));
assertEquals("[1, 12]", Arrays.toString(ml.locateInFrom(1, 4)));
assertEquals("[4, 9]", Arrays.toString(ml.locateInFrom(2, 3)));
assertEquals("[4, 12]", Arrays.toString(ml.locateInFrom(2, 4)));
assertEquals("[7, 12]", Arrays.toString(ml.locateInFrom(3, 4)));
assertEquals("[10, 12]", Arrays.toString(ml.locateInFrom(4, 4)));
- // reversing the range reverses the result:
- assertEquals("[12, 7]", Arrays.toString(ml.locateInFrom(4, 3))); // fails with [10, 9] !
+ /*
+ * partial overlap
+ */
+ assertEquals("[1, 12]", Arrays.toString(ml.locateInFrom(1, 5)));
+ assertEquals("[1, 3]", Arrays.toString(ml.locateInFrom(-1, 1)));
+
+ /*
+ * no overlap
+ */
assertNull(ml.locateInFrom(0, 0));
- assertNull(ml.locateInFrom(1, 5));
- assertNull(ml.locateInFrom(-1, 1));
}
/**
assertEquals("[12, 10]", Arrays.toString(ml.locateInFrom(1, 1)));
assertEquals("[9, 4]", Arrays.toString(ml.locateInFrom(2, 3)));
}
-
- /**
+
+ /**
* Tests for method that locates ranges in the 'to' map for given range in the
* 'from' map.
*/
assertEquals("[1, 4]", Arrays.toString(ml.locateInTo(1, 12)));
assertEquals("[2, 2]", Arrays.toString(ml.locateInTo(4, 6)));
assertEquals("[2, 4]", Arrays.toString(ml.locateInTo(4, 12)));
- // reversing the 'from' range reverses the result
- assertEquals("[4, 2]", Arrays.toString(ml.locateInTo(12, 4)));
+ // reverse range treated as if forwards:
+ assertEquals("[2, 4]", Arrays.toString(ml.locateInTo(12, 4)));
/*
* A part codon is treated as if a whole one.
assertEquals("[1, 4]", Arrays.toString(ml.locateInTo(3, 11)));
assertEquals("[2, 4]", Arrays.toString(ml.locateInTo(5, 11)));
+ /*
+ * partial overlap
+ */
+ assertEquals("[1, 4]", Arrays.toString(ml.locateInTo(1, 13)));
+ assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(-1, 2)));
+
+ /*
+ * no overlap
+ */
assertNull(ml.locateInTo(0, 0));
- assertNull(ml.locateInTo(1, 13));
- assertNull(ml.locateInTo(-1, 1));
}
/**
MapList ml = new MapList(codons, protein, 3, 1);
/*
- * Can't map from an unmapped position
- */
- assertNull(ml.locateInTo(1, 2));
- assertNull(ml.locateInTo(1, 4));
- assertNull(ml.locateInTo(2, 4));
- assertNull(ml.locateInTo(4, 4));
-
- /*
* Valid range or subrange of codon1 maps to protein1
*/
assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(2, 2)));
// codon positions 7 to 17 (part) cover proteins 2/3/4 at positions 3/4/6
assertEquals("[3, 4, 6, 6]", Arrays.toString(ml.locateInTo(7, 17)));
+
+ /*
+ * partial overlap
+ */
+ assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(1, 2)));
+ assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(1, 4)));
+ assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(2, 4)));
+
+ /*
+ * no overlap
+ */
+ assertNull(ml.locateInTo(4, 4));
}
/**
assertArrayEquals(new int[] { 71, 126 }, toRanges.get(1));
/*
- * method returns null if not all regions are mapped through
+ * if not all regions are mapped through, returns what is
*/
ml1 = new MapList(new int[] { 1, 50 }, new int[] { 101, 150 }, 1, 1);
- ml2 = new MapList(new int[] { 131, 180 }, new int[] { 201, 250 }, 1, 3);
+ ml2 = new MapList(new int[] { 131, 180 }, new int[] { 201, 250 }, 1, 1);
compound = ml1.traverse(ml2);
assertNull(compound);
}
assertEquals("[4, 9]", Arrays.toString(ml.locateInFrom(2, 3)));
assertEquals("[7, 12, 12, 17]", Arrays.toString(ml.locateInFrom(3, 6)));
+ /*
+ * partial overlap of range
+ */
+ assertEquals("[4, 12, 12, 17]", Arrays.toString(ml.locateInFrom(2, 7)));
+ assertEquals("[1, 3]", Arrays.toString(ml.locateInFrom(-1, 1)));
+
+ /*
+ * no overlap in range
+ */
assertNull(ml.locateInFrom(0, 0));
- assertNull(ml.locateInFrom(1, 7));
- assertNull(ml.locateInFrom(-1, 1));
/*
* gene to CDS...from EMBL:MN908947
*/
- int [] gene = new int[] { 266, 13468, 13468, 21555 };
- int [] cds = new int[] { 1, 21291 };
+ int[] gene = new int[] { 266, 13468, 13468, 21555 };
+ int[] cds = new int[] { 1, 21291 };
ml = new MapList(gene, cds, 1, 1);
- assertEquals("[13468, 13468]", Arrays.toString(ml.locateInFrom(13203, 13203)));
- assertEquals("[13468, 13468]", Arrays.toString(ml.locateInFrom(13204, 13204)));
- assertEquals("[13468, 13468]", Arrays.toString(ml.locateInFrom(13203, 13204)));
+ assertEquals("[13468, 13468]",
+ Arrays.toString(ml.locateInFrom(13203, 13203)));
+ assertEquals("[13468, 13468]",
+ Arrays.toString(ml.locateInFrom(13204, 13204)));
+ assertEquals("[13468, 13468, 13468, 13468]",
+ Arrays.toString(ml.locateInFrom(13203, 13204)));
}
/**
assertEquals("[4, 6]", Arrays.toString(ml.locateInTo(11, 15)));
assertEquals("[6, 6]", Arrays.toString(ml.locateInTo(15, 17)));
+ /*
+ * no overlap
+ */
assertNull(ml.locateInTo(0, 0));
- assertNull(ml.locateInTo(1, 18));
- assertNull(ml.locateInTo(-1, 1));
+
+ /*
+ * partial overlap
+ */
+ assertEquals("[1, 6]", Arrays.toString(ml.locateInTo(1, 18)));
+ assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(-1, 1)));
/*
* gene to CDS...from EMBL:MN908947
+ * the base at 13468 is used twice in transcription
*/
- int [] gene = new int[] { 266, 13468, 13468, 21555 };
- int [] cds = new int[] { 1, 21291 };
+ int[] gene = new int[] { 266, 13468, 13468, 21555 };
+ int[] cds = new int[] { 1, 21291 };
ml = new MapList(gene, cds, 1, 1);
- assertEquals("[13203, 13204]", Arrays.toString(ml.locateInTo(13468, 13468)));
+ assertEquals("[13203, 13204]",
+ Arrays.toString(ml.locateInTo(13468, 13468)));
+
+ /*
+ * gene to protein
+ * the base at 13468 is in the codon for 4401N and also 4402R
+ */
+ gene = new int[] { 266, 13468, 13468, 21552 }; // stop codon excluded
+ protein = new int[] { 1, 7096 };
+ ml = new MapList(gene, protein, 3, 1);
+ assertEquals("[4401, 4402]",
+ Arrays.toString(ml.locateInTo(13468, 13468)));
}
@Test(groups = { "Functional" })
}
List<int[]> intervals = new ArrayList<>();
- assertNull(MapList.countPositions(intervals, 1));
-
+ assertNull(MapList.countPositions(intervals, 1));
+
/*
* forward strand
*/
- intervals.add(new int[] {10, 20});
- assertNull(MapList.countPositions(intervals, 9));
- assertNull(MapList.countPositions(intervals, 21));
- assertArrayEquals(new int[] {1, 1}, MapList.countPositions(intervals, 10));
- assertArrayEquals(new int[] {6, 1}, MapList.countPositions(intervals, 15));
- assertArrayEquals(new int[] {11, 1}, MapList.countPositions(intervals, 20));
-
- intervals.add(new int[] {25, 25});
- assertArrayEquals(new int[] {12, 1}, MapList.countPositions(intervals, 25));
-
- // next interval repeats position 25 - which should be counted twice if traversed
- intervals.add(new int[] {25, 26});
- assertArrayEquals(new int[] {12, 1}, MapList.countPositions(intervals, 25));
- assertArrayEquals(new int[] {14, 1}, MapList.countPositions(intervals, 26));
-
+ intervals.add(new int[] { 10, 20 });
+ assertNull(MapList.countPositions(intervals, 9));
+ assertNull(MapList.countPositions(intervals, 21));
+ assertArrayEquals(new int[] { 1, 1 },
+ MapList.countPositions(intervals, 10));
+ assertArrayEquals(new int[] { 6, 1 },
+ MapList.countPositions(intervals, 15));
+ assertArrayEquals(new int[] { 11, 1 },
+ MapList.countPositions(intervals, 20));
+
+ intervals.add(new int[] { 25, 25 });
+ assertArrayEquals(new int[] { 12, 1 },
+ MapList.countPositions(intervals, 25));
+
+ // next interval repeats position 25 - which should be counted twice if
+ // traversed
+ intervals.add(new int[] { 25, 26 });
+ assertArrayEquals(new int[] { 12, 1 },
+ MapList.countPositions(intervals, 25));
+ assertArrayEquals(new int[] { 14, 1 },
+ MapList.countPositions(intervals, 26));
+
/*
* reverse strand
*/
intervals.clear();
- intervals.add(new int[] {5, -5});
- assertNull(MapList.countPositions(intervals, 6));
- assertNull(MapList.countPositions(intervals, -6));
- assertArrayEquals(new int[] {1, -1}, MapList.countPositions(intervals, 5));
- assertArrayEquals(new int[] {7, -1}, MapList.countPositions(intervals, -1));
- assertArrayEquals(new int[] {11, -1}, MapList.countPositions(intervals, -5));
-
+ intervals.add(new int[] { 5, -5 });
+ assertNull(MapList.countPositions(intervals, 6));
+ assertNull(MapList.countPositions(intervals, -6));
+ assertArrayEquals(new int[] { 1, -1 },
+ MapList.countPositions(intervals, 5));
+ assertArrayEquals(new int[] { 7, -1 },
+ MapList.countPositions(intervals, -1));
+ assertArrayEquals(new int[] { 11, -1 },
+ MapList.countPositions(intervals, -5));
+
/*
* reverse then forward
*/
- intervals.add(new int[] {5, 10});
- assertArrayEquals(new int[] {13, 1}, MapList.countPositions(intervals, 6));
-
+ intervals.add(new int[] { 5, 10 });
+ assertArrayEquals(new int[] { 13, 1 },
+ MapList.countPositions(intervals, 6));
+
/*
* reverse then forward then reverse
*/
- intervals.add(new int[] {-10, -20});
- assertArrayEquals(new int[] {20, -1}, MapList.countPositions(intervals, -12));
-
+ intervals.add(new int[] { -10, -20 });
+ assertArrayEquals(new int[] { 20, -1 },
+ MapList.countPositions(intervals, -12));
+
/*
* an interval [x, x] is treated as forward
*/
- intervals.add(new int[] {30, 30});
- assertArrayEquals(new int[] {29, 1}, MapList.countPositions(intervals, 30));
-
+ intervals.add(new int[] { 30, 30 });
+ assertArrayEquals(new int[] { 29, 1 },
+ MapList.countPositions(intervals, 30));
+
/*
* it is the first matched occurrence that is returned
*/
intervals.clear();
- intervals.add(new int[] {1, 2});
- intervals.add(new int[] {2, 3});
- assertArrayEquals(new int[] {2, 1}, MapList.countPositions(intervals, 2));
- intervals.add(new int[] {-1, -2});
- intervals.add(new int[] {-2, -3});
- assertArrayEquals(new int[] {6, -1}, MapList.countPositions(intervals, -2));
+ intervals.add(new int[] { 1, 2 });
+ intervals.add(new int[] { 2, 3 });
+ assertArrayEquals(new int[] { 2, 1 },
+ MapList.countPositions(intervals, 2));
+ intervals.add(new int[] { -1, -2 });
+ intervals.add(new int[] { -2, -3 });
+ assertArrayEquals(new int[] { 6, -1 },
+ MapList.countPositions(intervals, -2));
+ }
+
+ /**
+ * Tests for helper method that adds any overlap (plus offset) to a list of
+ * overlaps
+ */
+ @Test(groups = { "Functional" })
+ public void testAddOverlap()
+ {
+ List<int[]> overlaps = new ArrayList<>();
+ int[] candidate = new int[] { 10, 19 };
+ MapList.addOverlap(overlaps, 5, candidate, 20, 30); // doesn't overlap
+ assertTrue(overlaps.isEmpty());
+ MapList.addOverlap(overlaps, 5, candidate, 31, 40); // doesn't overlap
+ assertTrue(overlaps.isEmpty());
+
+ /*
+ * 10-19 overlaps 15-25 at 15-19, which is offset 5-9 in 10-19
+ * + 5 initial offset
+ */
+ MapList.addOverlap(overlaps, 5, candidate, 15, 25);
+ assertEquals(1, overlaps.size());
+ assertArrayEquals(new int[] { 10, 14 }, overlaps.get(0));
+
+ /*
+ * reverse range overlap:
+ * 300-20 overlaps 15-25 at 25-20, which is offset 275-280 in 300-20
+ * + 8 initial offset
+ */
+ overlaps.clear();
+ candidate = new int[] { 300, 20 };
+ MapList.addOverlap(overlaps, 8, candidate, 15, 25);
+ assertEquals(1, overlaps.size());
+ assertArrayEquals(new int[] { 283, 288 }, overlaps.get(0));
}
@Test(groups = { "Functional" })
public void testFindOverlapPositions()
{
List<int[]> ranges = new ArrayList<>();
- List<int[]> overlaps = MapList.findOverlapPositions(ranges, 20, 30);
+ List<int[]> overlaps = MapList.findOverlapPositions(ranges, 20, 30);
+ assertTrue(overlaps.isEmpty()); // nothing to overlap
+
+ ranges.add(new int[] { 15, 25 });
+ overlaps = MapList.findOverlapPositions(ranges, 5, 10);
+ assertTrue(overlaps.isEmpty()); // no overlap
+
+ overlaps = MapList.findOverlapPositions(ranges, 20, 20);
+ assertEquals(1, overlaps.size());
+ assertArrayEquals(new int[] { 5, 5 }, overlaps.get(0));
+
+ overlaps = MapList.findOverlapPositions(ranges, 5, 19);
+ assertEquals(1, overlaps.size());
+ assertArrayEquals(new int[] { 0, 4 }, overlaps.get(0));
+
+ ranges.add(new int[] { 35, 45 });
+ overlaps = MapList.findOverlapPositions(ranges, 26, 34);
assertTrue(overlaps.isEmpty());
- ranges.add(new int[] {15, 25});
- overlaps = MapList.findOverlapPositions(ranges, 20, 30);
+
+ /*
+ * 24-37 overlaps the end of 15-25 and the start of 35-45
+ * - offset positions are contiguous in the map so merged
+ */
+ overlaps = MapList.findOverlapPositions(ranges, 24, 37);
assertEquals(1, overlaps.size());
- assertArrayEquals(new int[] {6, 11}, overlaps.get(0));
+ assertArrayEquals(new int[] { 9, 13 }, overlaps.get(0));
+
+ /*
+ * EMBL:MN908947 https://www.ebi.ac.uk/ena/browser/api/embl/MN908947
+ * (Covid-SARS-2) CDS mapping with 'slippage'
+ * (base 13468 is used twice in transcription)
+ */
+ ranges.clear();
+ ranges.add(new int[] { 266, 13468 });
+ ranges.add(new int[] { 13468, 21555 });
+
+ // 13468 occupies two offsets in the range list
+ overlaps = MapList.findOverlapPositions(ranges, 13468, 13468);
+ assertEquals(1, overlaps.size());
+ assertArrayEquals(new int[] { 13202, 13203 }, overlaps.get(0));
+ overlaps = MapList.findOverlapPositions(ranges, 13469, 13470);
+ assertEquals(1, overlaps.size());
+ assertArrayEquals(new int[] { 13204, 13205 }, overlaps.get(0));
+
+ /*
+ * EMBL:J03321 https://www.ebi.ac.uk/ena/browser/api/embl/J03321
+ * circular dna: CDS at [7022-7502, 1-437]
+ * = 481 + 437 = 918 bases = 305 aa's + stop codon
+ */
+ ranges.clear();
+ ranges.add(new int[] { 7022, 7502 });
+ ranges.add(new int[] { 1, 437 });
+
+ overlaps = MapList.findOverlapPositions(ranges, 438, 7021);
+ assertTrue(overlaps.isEmpty());
+
+ // overlap first exon only:
+ overlaps = MapList.findOverlapPositions(ranges, 7000, 7100);
+ assertEquals(1, overlaps.size());
+ assertArrayEquals(new int[] { 0, 78 }, overlaps.get(0));
+
+ // overlap second exon only: offset to mapping includes first exon
+ overlaps = MapList.findOverlapPositions(ranges, 400, 500);
+ assertEquals(1, overlaps.size());
+ assertArrayEquals(new int[] { 880, 917 }, overlaps.get(0));
+
+ // overlap both exons: first exon overlap precedes second exon overlap
+ // offsets of overlaps are not contiguous
+ overlaps = MapList.findOverlapPositions(ranges, 200, 7500);
+ assertEquals(2, overlaps.size());
+ // first overlap is offsets of 7022-7500 in exon 1 (7022-7502):
+ assertArrayEquals(new int[] { 0, 478 }, overlaps.get(0));
+ // second overlap offsets is (first exon length = 481) + (200-437)
+ assertArrayEquals(new int[] { 680, 917 }, overlaps.get(1));
}
@Test(groups = { "Functional" })
public void testMapWords()
{
List<int[]> ranges = new ArrayList<>();
-
+
/*
* 1:1 (trivial) case
*/
- ranges.add(new int[] {2, 4});
- ranges.add(new int[] {6, 9});
- MapList.mapWords(ranges, 1, 1);
+ ranges.add(new int[] { 2, 4 });
+ ranges.add(new int[] { 6, 9 });
+ MapList.mapWords(ranges, 1, 1);
assertEquals(ranges.size(), 2);
- assertArrayEquals(new int[] {2, 4}, ranges.get(0));
- assertArrayEquals(new int[] {6, 9}, ranges.get(1));
-
+ assertArrayEquals(new int[] { 2, 4 }, ranges.get(0));
+ assertArrayEquals(new int[] { 6, 9 }, ranges.get(1));
+
/*
* 1:3 case (peptide to codon ranges)
*/
- MapList.mapWords(ranges, 1, 3);
+ MapList.mapWords(ranges, 1, 3);
assertEquals(ranges.size(), 2);
- assertArrayEquals(new int[] {6, 14}, ranges.get(0));
- assertArrayEquals(new int[] {18, 29}, ranges.get(1));
-
+ assertArrayEquals(new int[] { 6, 14 }, ranges.get(0));
+ assertArrayEquals(new int[] { 18, 29 }, ranges.get(1));
+
/*
* 3:1 case (codon or part codon to peptide)
*/
ranges.clear();
- ranges.add(new int[] {0, 5}); // 2 whole codons
- ranges.add(new int[] {7, 11}); // part + whole codon
- ranges.add(new int[] {15, 19}); // whole + part codon
- ranges.add(new int[] {23, 27}); // part + part codon
- ranges.add(new int[] {30, 30}); // first base of codon
- ranges.add(new int[] {31, 31}); // second base of codon
- ranges.add(new int[] {32, 32}); // third base of codon
- MapList.mapWords(ranges, 3, 1);
+ ranges.add(new int[] { 0, 5 }); // 2 whole codons
+ ranges.add(new int[] { 7, 11 }); // part + whole codon
+ ranges.add(new int[] { 15, 19 }); // whole + part codon
+ ranges.add(new int[] { 23, 27 }); // part + part codon
+ ranges.add(new int[] { 30, 30 }); // first base of codon
+ ranges.add(new int[] { 31, 31 }); // second base of codon
+ ranges.add(new int[] { 32, 32 }); // third base of codon
+ MapList.mapWords(ranges, 3, 1);
assertEquals(ranges.size(), 7);
- assertArrayEquals(new int[] {0, 1}, ranges.get(0));
- assertArrayEquals(new int[] {2, 3}, ranges.get(1));
- assertArrayEquals(new int[] {5, 6}, ranges.get(2));
- assertArrayEquals(new int[] {7, 9}, ranges.get(3));
- assertArrayEquals(new int[] {10, 10}, ranges.get(4));
- assertArrayEquals(new int[] {10, 10}, ranges.get(5));
- assertArrayEquals(new int[] {10, 10}, ranges.get(6));
+ assertArrayEquals(new int[] { 0, 1 }, ranges.get(0));
+ assertArrayEquals(new int[] { 2, 3 }, ranges.get(1));
+ assertArrayEquals(new int[] { 5, 6 }, ranges.get(2));
+ assertArrayEquals(new int[] { 7, 9 }, ranges.get(3));
+ assertArrayEquals(new int[] { 10, 10 }, ranges.get(4));
+ assertArrayEquals(new int[] { 10, 10 }, ranges.get(5));
+ assertArrayEquals(new int[] { 10, 10 }, ranges.get(6));
+ }
+
+ @Test(groups = { "Functional" })
+ public void testLocateInFrom2()
+ {
+ /*
+ * codons at 11-16, 21-26, 31-36 mapped to peptide positions 1, 3-4, 6-8
+ */
+ MapList ml = new MapList(new int[] { 11, 16, 21, 26, 31, 36 },
+ new int[]
+ { 1, 1, 3, 4, 6, 8 }, 3, 1);
+ assertArrayEquals(new int[] { 11, 13 }, ml.locateInFrom2(1, 1));
+ assertArrayEquals(new int[] { 11, 16 }, ml.locateInFrom2(1, 3));
+ assertArrayEquals(new int[] { 11, 16, 21, 23 }, ml.locateInFrom2(1, 4));
+ assertArrayEquals(new int[] { 14, 16, 21, 23 }, ml.locateInFrom2(3, 4));
}
}