import jalview.commands.EditCommand.Edit;
import jalview.commands.OrderCommand;
import jalview.datamodel.AlignedCodonFrame;
+import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.ColumnSelection;
for (AlignedCodonFrame acf : codonFrames)
{
- SequenceI mappedSequence = targetIsNucleotide
- ? acf.getDnaForAaSeq(selected)
- : acf.getAaForDnaSeq(selected);
- if (mappedSequence != null)
+ for (SequenceI seq : mapTo.getAlignment().getSequences())
{
- for (SequenceI seq : mapTo.getAlignment().getSequences())
+ SequenceI peptide = targetIsNucleotide ? selected : seq;
+ SequenceI cds = targetIsNucleotide ? seq : selected;
+ SequenceToSequenceMapping s2s = acf.getCoveringMapping(cds,
+ peptide);
+ if (s2s == null)
{
- int mappedStartResidue = 0;
- int mappedEndResidue = 0;
- if (seq.getDatasetSequence() == mappedSequence)
- {
- /*
- * Found a sequence mapping. Locate the start/end mapped residues.
- */
- List<AlignedCodonFrame> mapping = Arrays
- .asList(new AlignedCodonFrame[]
- { acf });
- SearchResultsI sr = buildSearchResults(selected,
- startResiduePos, mapping);
- for (SearchResultMatchI m : sr.getResults())
- {
- mappedStartResidue = m.getStart();
- mappedEndResidue = m.getEnd();
- }
- sr = buildSearchResults(selected, endResiduePos, mapping);
- for (SearchResultMatchI m : sr.getResults())
- {
- mappedStartResidue = Math.min(mappedStartResidue,
- m.getStart());
- mappedEndResidue = Math.max(mappedEndResidue, m.getEnd());
- }
-
- /*
- * Find the mapped aligned columns, save the range. Note findIndex
- * returns a base 1 position, SequenceGroup uses base 0
- */
- int mappedStartCol = seq.findIndex(mappedStartResidue) - 1;
- minStartCol = minStartCol == -1 ? mappedStartCol
- : Math.min(minStartCol, mappedStartCol);
- int mappedEndCol = seq.findIndex(mappedEndResidue) - 1;
- maxEndCol = maxEndCol == -1 ? mappedEndCol
- : Math.max(maxEndCol, mappedEndCol);
- mappedGroup.addSequence(seq, false);
- break;
- }
+ continue;
}
+ int mappedStartResidue = 0;
+ int mappedEndResidue = 0;
+ List<AlignedCodonFrame> mapping = Arrays.asList(acf);
+ SearchResultsI sr = buildSearchResults(selected, startResiduePos,
+ mapping);
+ for (SearchResultMatchI m : sr.getResults())
+ {
+ mappedStartResidue = m.getStart();
+ mappedEndResidue = m.getEnd();
+ }
+ sr = buildSearchResults(selected, endResiduePos, mapping);
+ for (SearchResultMatchI m : sr.getResults())
+ {
+ mappedStartResidue = Math.min(mappedStartResidue, m.getStart());
+ mappedEndResidue = Math.max(mappedEndResidue, m.getEnd());
+ }
+
+ /*
+ * Find the mapped aligned columns, save the range. Note findIndex
+ * returns a base 1 position, SequenceGroup uses base 0
+ */
+ int mappedStartCol = seq.findIndex(mappedStartResidue) - 1;
+ minStartCol = minStartCol == -1 ? mappedStartCol
+ : Math.min(minStartCol, mappedStartCol);
+ int mappedEndCol = seq.findIndex(mappedEndResidue) - 1;
+ maxEndCol = maxEndCol == -1 ? mappedEndCol
+ : Math.max(maxEndCol, mappedEndCol);
+ mappedGroup.addSequence(seq, false);
+ break;
}
}
}
{
for (AlignedCodonFrame acf : mappings)
{
- SequenceI mappedSeq = mappingToNucleotide ? acf.getDnaForAaSeq(seq)
- : acf.getAaForDnaSeq(seq);
- if (mappedSeq != null)
- {
for (SequenceI seq2 : mapTo.getSequences())
{
- if (seq2.getDatasetSequence() == mappedSeq)
+ /*
+ * the corresponding peptide / CDS is the one for which there is
+ * a complete ('covering') mapping to 'seq'
+ */
+ SequenceI peptide = mappingToNucleotide ? seq2 : seq;
+ SequenceI cds = mappingToNucleotide ? seq : seq2;
+ SequenceToSequenceMapping s2s = acf.getCoveringMapping(cds,
+ peptide);
+ if (s2s != null)
{
mappedOrder.add(seq2);
j++;
break;
}
}
- }
}
}
if (colsel == null)
{
- return; // mappedColumns;
+ return;
}
char fromGapChar = mapFrom.getAlignment().getGapCharacter();
mapHiddenColumns(regions.next(), codonFrames, newHidden,
fromSequences, toSequences, fromGapChar);
}
- return; // mappedColumns;
+ return;
}
/**
*/
for (SequenceI toSeq : toSequences)
{
- if (toSeq.getDatasetSequence() == mappedSeq)
+ if (toSeq.getDatasetSequence() == mappedSeq
+ && mappedStartResidue >= toSeq.getStart()
+ && mappedEndResidue <= toSeq.getEnd())
{
int mappedStartCol = toSeq.findIndex(mappedStartResidue);
int mappedEndCol = toSeq.findIndex(mappedEndResidue);
{
if (range.length % 2 != 0)
{
- System.err.println(
+ Cache.log.error(
"Error unbalance start/end ranges: " + ranges.toString());
return 0;
}
/*
* not coded for [start1, end1, start2, end2, ...]
*/
- System.err.println(
+ Cache.log.error(
"MappingUtils.removeEndPositions doesn't handle multiple ranges");
return;
}
/*
* not coded for a reverse strand range (end < start)
*/
- System.err.println(
+ Cache.log.error(
"MappingUtils.removeEndPositions doesn't handle reverse strand");
return;
}
}
return result;
}
+
+ /*
+ * Returns the maximal start-end positions in the given (ordered) list of
+ * ranges which is overlapped by the given begin-end range, or null if there
+ * is no overlap.
+ *
+ * <pre>
+ * Examples:
+ * if ranges is {[4, 8], [10, 12], [16, 19]}
+ * then
+ * findOverlap(ranges, 1, 20) == [4, 19]
+ * findOverlap(ranges, 6, 11) == [6, 11]
+ * findOverlap(ranges, 9, 15) == [10, 12]
+ * findOverlap(ranges, 13, 15) == null
+ * </pre>
+ *
+ * @param ranges
+ * @param begin
+ * @param end
+ * @return
+ */
+ protected static int[] findOverlap(List<int[]> ranges, final int begin,
+ final int end)
+ {
+ boolean foundStart = false;
+ int from = 0;
+ int to = 0;
+
+ /*
+ * traverse the ranges to find the first position (if any) >= begin,
+ * and the last position (if any) <= end
+ */
+ for (int[] range : ranges)
+ {
+ if (!foundStart)
+ {
+ if (range[0] >= begin)
+ {
+ /*
+ * first range that starts with, or follows, begin
+ */
+ foundStart = true;
+ from = Math.max(range[0], begin);
+ }
+ else if (range[1] >= begin)
+ {
+ /*
+ * first range that contains begin
+ */
+ foundStart = true;
+ from = begin;
+ }
+ }
+
+ if (range[0] <= end)
+ {
+ to = Math.min(end, range[1]);
+ }
+ }
+
+ return foundStart && to >= from ? new int[] { from, to } : null;
+ }
}
{
Cache.initLogger();
}
-
+
@BeforeClass(alwaysRun = true)
public void setUpJvOptionPane()
{
* no overlap
*/
assertNull(ml.locateInFrom(0, 0));
-
+
}
/**
assertEquals("[10, 10, 12, 12, 14, 14]",
Arrays.toString(ml.locateInFrom(3, 3)));
assertEquals("[16, 18]", Arrays.toString(ml.locateInFrom(4, 4)));
-
+
/*
* codons at 11-16, 21-26, 31-36 mapped to peptide positions 1, 3-4, 6-8
*/
}
/**
+ * Tests for method that locates the overlap of the ranges in the 'from' map
+ * for given range in the 'to' map
+ */
+ @Test(groups = { "Functional" })
+ public void testGetOverlapsInFrom_withIntrons()
+ {
+ /*
+ * Exons at positions [2, 3, 5] [6, 7, 9] [10, 12, 14] [16, 17, 18] i.e.
+ * 2-3, 5-7, 9-10, 12-12, 14-14, 16-18
+ */
+ int[] codons = { 2, 3, 5, 7, 9, 10, 12, 12, 14, 14, 16, 18 };
+ int[] protein = { 11, 14 };
+ MapList ml = new MapList(codons, protein, 3, 1);
+
+ assertEquals("[2, 3, 5, 5]",
+ Arrays.toString(ml.getOverlapsInFrom(11, 11)));
+ assertEquals("[2, 3, 5, 7, 9, 9]",
+ Arrays.toString(ml.getOverlapsInFrom(11, 12)));
+ // out of range 5' :
+ assertEquals("[2, 3, 5, 7, 9, 9]",
+ Arrays.toString(ml.getOverlapsInFrom(8, 12)));
+ // out of range 3' :
+ assertEquals("[10, 10, 12, 12, 14, 14, 16, 18]",
+ Arrays.toString(ml.getOverlapsInFrom(13, 16)));
+ // out of range both :
+ assertEquals("[2, 3, 5, 7, 9, 10, 12, 12, 14, 14, 16, 18]",
+ Arrays.toString(ml.getOverlapsInFrom(1, 16)));
+ // no overlap:
+ assertNull(ml.getOverlapsInFrom(20, 25));
+ }
+
+ /**
+ * Tests for method that locates the overlap of the ranges in the 'to' map for
+ * given range in the 'from' map
+ */
+ @Test(groups = { "Functional" })
+ public void testGetOverlapsInTo_withIntrons()
+ {
+ /*
+ * Exons at positions [2, 3, 5] [6, 7, 9] [10, 12, 14] [17, 18, 19] i.e.
+ * 2-3, 5-7, 9-10, 12-12, 14-14, 17-19
+ */
+ int[] codons = { 2, 3, 5, 7, 9, 10, 12, 12, 14, 14, 17, 19 };
+ /*
+ * Mapped proteins at positions 1, 3, 4, 6 in the sequence
+ */
+ int[] protein = { 1, 1, 3, 4, 6, 6 };
+ MapList ml = new MapList(codons, protein, 3, 1);
+
+ /*
+ * Can't map from an unmapped position
+ */
+ assertNull(ml.getOverlapsInTo(1, 1));
+ assertNull(ml.getOverlapsInTo(4, 4));
+ assertNull(ml.getOverlapsInTo(15, 16));
+
+ /*
+ * nor from a range that includes no mapped position (exon)
+ */
+ assertNull(ml.getOverlapsInTo(15, 16));
+
+ // end of codon 1 maps to first peptide
+ assertEquals("[1, 1]", Arrays.toString(ml.getOverlapsInTo(2, 2)));
+ // end of codon 1 and start of codon 2 maps to first 2 peptides
+ assertEquals("[1, 1, 3, 3]", Arrays.toString(ml.getOverlapsInTo(3, 7)));
+
+ // range overlaps 5' end of dna:
+ assertEquals("[1, 1, 3, 3]", Arrays.toString(ml.getOverlapsInTo(1, 6)));
+ assertEquals("[1, 1, 3, 3]", Arrays.toString(ml.getOverlapsInTo(1, 8)));
+
+ // range overlaps 3' end of dna:
+ assertEquals("[6, 6]", Arrays.toString(ml.getOverlapsInTo(17, 24)));
+ assertEquals("[6, 6]", Arrays.toString(ml.getOverlapsInTo(16, 24)));
+
+ // dna positions 8, 11 are intron but include end of exon 2 and start of
+ // exon 3
+ assertEquals("[3, 4]", Arrays.toString(ml.getOverlapsInTo(8, 11)));
+ }
+
+ /**
* 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, 13)));
assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(-1, 2)));
-
+
/*
* no 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
*/
assertArrayEquals(new int[] { 5, 6 }, merged.get(1));
assertArrayEquals(new int[] { 12, 8 }, merged.get(2));
assertArrayEquals(new int[] { 8, 7 }, merged.get(3));
-
+
// 'subsumed' ranges are preserved
ranges.clear();
ranges.add(new int[] { 10, 30 });
- ranges.add(new int[] { 15, 25 });
+ ranges.add(new int[] { 15, 25 });
+
merged = MapList.coalesceRanges(ranges);
assertEquals(2, merged.size());
assertArrayEquals(new int[] { 10, 30 }, merged.get(0));
toRanges = compound.getToRanges();
assertEquals(2, toRanges.size());
assertArrayEquals(new int[] { 931, 901 }, toRanges.get(0));
- assertArrayEquals(new int[] { 600, 582}, toRanges.get(1));
+ assertArrayEquals(new int[] { 600, 582 }, toRanges.get(1));
/*
* 1:1 plus 1:3 should result in 1:3
* no overlap
*/
assertNull(ml.locateInTo(0, 0));
-
+
/*
* partial overlap
*/
ml = new MapList(gene, cds, 1, 1);
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
public void testAddOffsetPositions()
{
List<int[]> mapped = new ArrayList<>();
- int[] range = new int[] {10, 20};
+ int[] range = new int[] { 10, 20 };
BitSet offsets = new BitSet();
MapList.addOffsetPositions(mapped, 0, range, offsets);
assertArrayEquals(new int[] { 14, 13 }, mapped.get(1));
assertArrayEquals(new int[] { 10, 10 }, mapped.get(2));
}
-
+
@Test(groups = { "Functional" })
public void testGetPositionsForOffsets()
{
BitSet offsets = new BitSet();
List<int[]> mapped = MapList.getPositionsForOffsets(ranges, offsets);
assertTrue(mapped.isEmpty()); // no ranges and no offsets!
-
+
offsets.set(5, 1000);
mapped = MapList.getPositionsForOffsets(ranges, offsets);
assertTrue(mapped.isEmpty()); // no ranges
-
+
/*
* one range with overlap of offsets
*/
- ranges.add(new int[] {15, 25});
+ ranges.add(new int[] { 15, 25 });
mapped = MapList.getPositionsForOffsets(ranges, offsets);
assertEquals(1, mapped.size());
- assertArrayEquals(new int[] {20, 25}, mapped.get(0));
-
+ assertArrayEquals(new int[] { 20, 25 }, mapped.get(0));
+
/*
* two ranges
*/
- ranges.add(new int[] {300, 320});
+ ranges.add(new int[] { 300, 320 });
mapped = MapList.getPositionsForOffsets(ranges, offsets);
assertEquals(2, mapped.size());
- assertArrayEquals(new int[] {20, 25}, mapped.get(0));
- assertArrayEquals(new int[] {300, 320}, mapped.get(1));
-
+ assertArrayEquals(new int[] { 20, 25 }, mapped.get(0));
+ assertArrayEquals(new int[] { 300, 320 }, mapped.get(1));
+
/*
* boundary case - right end of first range overlaps
*/
offsets.set(10);
mapped = MapList.getPositionsForOffsets(ranges, offsets);
assertEquals(1, mapped.size());
- assertArrayEquals(new int[] {25, 25}, mapped.get(0));
-
+ assertArrayEquals(new int[] { 25, 25 }, mapped.get(0));
+
/*
* boundary case - left end of second range overlaps
*/
offsets.set(11);
mapped = MapList.getPositionsForOffsets(ranges, offsets);
assertEquals(2, mapped.size());
- assertArrayEquals(new int[] {25, 25}, mapped.get(0));
- assertArrayEquals(new int[] {300, 300}, mapped.get(1));
-
+ assertArrayEquals(new int[] { 25, 25 }, mapped.get(0));
+ assertArrayEquals(new int[] { 300, 300 }, mapped.get(1));
+
/*
* offsets into a circular range are reported in
* the order in which they are traversed
*/
ranges.clear();
- ranges.add(new int[] {100, 150});
- ranges.add(new int[] {60, 80});
+ ranges.add(new int[] { 100, 150 });
+ ranges.add(new int[] { 60, 80 });
offsets.clear();
offsets.set(45, 55); // sets bits 45 to 54
mapped = MapList.getPositionsForOffsets(ranges, offsets);
assertEquals(2, mapped.size());
- assertArrayEquals(new int[] {145, 150}, mapped.get(0)); // offsets 45-50
- assertArrayEquals(new int[] {60, 63}, mapped.get(1)); // offsets 51-54
+ assertArrayEquals(new int[] { 145, 150 }, mapped.get(0)); // offsets 45-50
+ assertArrayEquals(new int[] { 60, 63 }, mapped.get(1)); // offsets 51-54
/*
* reverse range overlap is reported with start < end
*/
ranges.clear();
- ranges.add(new int[] {4321, 4000});
+ ranges.add(new int[] { 4321, 4000 });
offsets.clear();
offsets.set(20, 22); // sets bits 20 and 21
offsets.set(30);
mapped = MapList.getPositionsForOffsets(ranges, offsets);
assertEquals(2, mapped.size());
- assertArrayEquals(new int[] {4301, 4300}, mapped.get(0));
- assertArrayEquals(new int[] {4291, 4291}, mapped.get(1));
+ assertArrayEquals(new int[] { 4301, 4300 }, mapped.get(0));
+ assertArrayEquals(new int[] { 4291, 4291 }, mapped.get(1));
}
-
+
@Test(groups = { "Functional" })
public void testGetMappedOffsetsForPositions()
{
* start by verifying the examples in the method's Javadoc!
*/
List<int[]> ranges = new ArrayList<>();
- ranges.add(new int[] {10, 20});
- ranges.add(new int[] {31, 40});
- BitSet overlaps = MapList.getMappedOffsetsForPositions(1, 9, ranges, 1, 1);
+ ranges.add(new int[] { 10, 20 });
+ ranges.add(new int[] { 31, 40 });
+ BitSet overlaps = MapList.getMappedOffsetsForPositions(1, 9, ranges, 1,
+ 1);
assertTrue(overlaps.isEmpty());
overlaps = MapList.getMappedOffsetsForPositions(1, 11, ranges, 1, 1);
assertEquals(2, overlaps.cardinality());
assertTrue(overlaps.get(1));
overlaps = MapList.getMappedOffsetsForPositions(15, 35, ranges, 1, 1);
assertEquals(11, overlaps.cardinality());
- for (int i = 5 ; i <= 11 ; i++)
+ for (int i = 5; i <= 11; i++)
{
assertTrue(overlaps.get(i));
}
-
+
ranges.clear();
- ranges.add(new int[] {1, 200});
+ ranges.add(new int[] { 1, 200 });
overlaps = MapList.getMappedOffsetsForPositions(9, 9, ranges, 1, 3);
assertEquals(3, overlaps.cardinality());
assertTrue(overlaps.get(24));
assertTrue(overlaps.get(25));
assertTrue(overlaps.get(26));
-
+
ranges.clear();
- ranges.add(new int[] {101, 150});
- ranges.add(new int[] {171, 180});
+ ranges.add(new int[] { 101, 150 });
+ ranges.add(new int[] { 171, 180 });
overlaps = MapList.getMappedOffsetsForPositions(101, 102, ranges, 3, 1);
assertEquals(1, overlaps.cardinality());
assertTrue(overlaps.get(0));
overlaps = MapList.getMappedOffsetsForPositions(150, 171, ranges, 3, 1);
assertEquals(1, overlaps.cardinality());
assertTrue(overlaps.get(16));
-
+
ranges.clear();
- ranges.add(new int[] {101, 150});
- ranges.add(new int[] {21, 30});
+ ranges.add(new int[] { 101, 150 });
+ ranges.add(new int[] { 21, 30 });
overlaps = MapList.getMappedOffsetsForPositions(24, 40, ranges, 3, 1);
assertEquals(3, overlaps.cardinality());
assertTrue(overlaps.get(17));
assertTrue(overlaps.get(18));
assertTrue(overlaps.get(19));
-
+
/*
* reverse range 1:1 (e.g. reverse strand gene to transcript)
*/
ranges.clear();
- ranges.add(new int[] {20, 10});
+ ranges.add(new int[] { 20, 10 });
overlaps = MapList.getMappedOffsetsForPositions(12, 13, ranges, 1, 1);
assertEquals(2, overlaps.cardinality());
assertTrue(overlaps.get(7));
assertTrue(overlaps.get(8));
-
+
/*
* reverse range 3:1 (e.g. reverse strand gene to peptide)
* from EMBL:J03321 to P0CE20
*/
ranges.clear();
- ranges.add(new int[] {1480, 488});
- overlaps = MapList.getMappedOffsetsForPositions(1460, 1460, ranges, 3, 1);
+ ranges.add(new int[] { 1480, 488 });
+ overlaps = MapList.getMappedOffsetsForPositions(1460, 1460, ranges, 3,
+ 1);
// 1460 is the end of the 7th codon
assertEquals(1, overlaps.cardinality());
assertTrue(overlaps.get(6));
// add one base (part codon)
- overlaps = MapList.getMappedOffsetsForPositions(1459, 1460, ranges, 3, 1);
+ overlaps = MapList.getMappedOffsetsForPositions(1459, 1460, ranges, 3,
+ 1);
assertEquals(2, overlaps.cardinality());
assertTrue(overlaps.get(6));
assertTrue(overlaps.get(7));
// add second base (part codon)
- overlaps = MapList.getMappedOffsetsForPositions(1458, 1460, ranges, 3, 1);
+ overlaps = MapList.getMappedOffsetsForPositions(1458, 1460, ranges, 3,
+ 1);
assertEquals(2, overlaps.cardinality());
assertTrue(overlaps.get(6));
assertTrue(overlaps.get(7));
// add third base (whole codon)
- overlaps = MapList.getMappedOffsetsForPositions(1457, 1460, ranges, 3, 1);
+ overlaps = MapList.getMappedOffsetsForPositions(1457, 1460, ranges, 3,
+ 1);
assertEquals(2, overlaps.cardinality());
assertTrue(overlaps.get(6));
assertTrue(overlaps.get(7));
// add one more base (part codon)
- overlaps = MapList.getMappedOffsetsForPositions(1456, 1460, ranges, 3, 1);
+ overlaps = MapList.getMappedOffsetsForPositions(1456, 1460, ranges, 3,
+ 1);
assertEquals(3, overlaps.cardinality());
assertTrue(overlaps.get(6));
assertTrue(overlaps.get(7));
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
+ import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertSame;
import static org.testng.AssertJUnit.assertTrue;
- import static org.testng.AssertJUnit.fail;
+ import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
import java.awt.Color;
import java.io.IOException;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import java.awt.Color;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
import jalview.api.AlignViewportI;
import jalview.bin.Cache;
import jalview.commands.EditCommand;
protein.setCodonFrames(acfList);
/*
- * Select Seq1 and Seq3 in the protein (startRes=endRes=0)
+ * Select Seq1 and Seq3 in the protein
*/
SequenceGroup sg = new SequenceGroup();
sg.setColourText(true);
sg.setOutlineColour(Color.LIGHT_GRAY);
sg.addSequence(protein.getSequenceAt(0), false);
sg.addSequence(protein.getSequenceAt(2), false);
+ sg.setEndRes(protein.getWidth() - 1);
/*
* Verify the mapped sequence group in dna
assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(1));
assertEquals(0, mappedGroup.getStartRes());
- assertEquals(2, mappedGroup.getEndRes());
+ assertEquals(2, mappedGroup.getEndRes()); // 3 columns (1 codon)
/*
* Verify mapping sequence group from dna to protein
}
@Test(groups = "Functional")
- public void testListToArray()
+ public void testFindOverlap()
{
List<int[]> ranges = new ArrayList<>();
-
- int[] result = MappingUtils.rangeListToArray(ranges);
- assertEquals(result.length, 0);
- ranges.add(new int[] { 24, 12 });
- result = MappingUtils.rangeListToArray(ranges);
- assertEquals(result.length, 2);
- assertEquals(result[0], 24);
- assertEquals(result[1], 12);
- ranges.add(new int[] { -7, 30 });
- result = MappingUtils.rangeListToArray(ranges);
- assertEquals(result.length, 4);
- assertEquals(result[0], 24);
- assertEquals(result[1], 12);
- assertEquals(result[2], -7);
- assertEquals(result[3], 30);
- try
- {
- MappingUtils.rangeListToArray(null);
- fail("Expected exception");
- } catch (NullPointerException e)
- {
- // expected
- }
+ ranges.add(new int[] { 4, 8 });
+ ranges.add(new int[] { 10, 12 });
+ ranges.add(new int[] { 16, 19 });
+
+ int[] overlap = MappingUtils.findOverlap(ranges, 5, 13);
+ assertArrayEquals(overlap, new int[] { 5, 12 });
+ overlap = MappingUtils.findOverlap(ranges, -100, 100);
+ assertArrayEquals(overlap, new int[] { 4, 19 });
+ overlap = MappingUtils.findOverlap(ranges, 7, 17);
+ assertArrayEquals(overlap, new int[] { 7, 17 });
+ overlap = MappingUtils.findOverlap(ranges, 13, 15);
+ assertNull(overlap);
}
+
+ /**
+ * Test mapping a sequence group where sequences in and outside the group
+ * share a dataset sequence (e.g. alternative CDS for the same gene)
+ * <p>
+ * This scenario doesn't arise after JAL-3763 changes, but test left as still valid
+ * @throws IOException
+ */
+ @Test(groups = { "Functional" })
+ public void testMapSequenceGroup_sharedDataset() throws IOException
+ {
+ /*
+ * Set up dna and protein Seq1/2/3 with mappings (held on the protein
+ * viewport). CDS sequences share the same 'gene' dataset sequence.
+ */
+ SequenceI dna = new Sequence("dna", "aaatttgggcccaaatttgggccc");
+ SequenceI cds1 = new Sequence("cds1/1-6", "aaattt");
+ SequenceI cds2 = new Sequence("cds1/4-9", "tttggg");
+ SequenceI cds3 = new Sequence("cds1/19-24", "gggccc");
+
+ cds1.setDatasetSequence(dna);
+ cds2.setDatasetSequence(dna);
+ cds3.setDatasetSequence(dna);
+
+ SequenceI pep1 = new Sequence("pep1", "KF");
+ SequenceI pep2 = new Sequence("pep2", "FG");
+ SequenceI pep3 = new Sequence("pep3", "GP");
+ pep1.createDatasetSequence();
+ pep2.createDatasetSequence();
+ pep3.createDatasetSequence();
+
+ /*
+ * add mappings from coding positions of dna to respective peptides
+ */
+ AlignedCodonFrame acf = new AlignedCodonFrame();
+ acf.addMap(dna, pep1,
+ new MapList(new int[]
+ { 1, 6 }, new int[] { 1, 2 }, 3, 1));
+ acf.addMap(dna, pep2,
+ new MapList(new int[]
+ { 4, 9 }, new int[] { 1, 2 }, 3, 1));
+ acf.addMap(dna, pep3,
+ new MapList(new int[]
+ { 19, 24 }, new int[] { 1, 2 }, 3, 1));
+
+ List<AlignedCodonFrame> acfList = Arrays
+ .asList(new AlignedCodonFrame[]
+ { acf });
+
+ AlignmentI cdna = new Alignment(new SequenceI[] { cds1, cds2, cds3 });
+ AlignmentI protein = new Alignment(
+ new SequenceI[]
+ { pep1, pep2, pep3 });
+ AlignViewportI cdnaView = new AlignViewport(cdna);
+ AlignViewportI peptideView = new AlignViewport(protein);
+ protein.setCodonFrames(acfList);
+
+ /*
+ * Select pep1 and pep3 in the protein alignment
+ */
+ SequenceGroup sg = new SequenceGroup();
+ sg.setColourText(true);
+ sg.setIdColour(Color.GREEN);
+ sg.setOutlineColour(Color.LIGHT_GRAY);
+ sg.addSequence(pep1, false);
+ sg.addSequence(pep3, false);
+ sg.setEndRes(protein.getWidth() - 1);
+
+ /*
+ * Verify the mapped sequence group in dna is cds1 and cds3
+ */
+ SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
+ peptideView, cdnaView);
+ assertTrue(mappedGroup.getColourText());
+ assertSame(sg.getIdColour(), mappedGroup.getIdColour());
+ assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
+ assertEquals(2, mappedGroup.getSequences().size());
+ assertSame(cds1, mappedGroup.getSequences().get(0));
+ assertSame(cds3, mappedGroup.getSequences().get(1));
+ // columns 1-6 selected (0-5 base zero)
+ assertEquals(0, mappedGroup.getStartRes());
+ assertEquals(5, mappedGroup.getEndRes());
+
+ /*
+ * Select mapping sequence group from dna to protein
+ */
+ sg.clear();
+ sg.addSequence(cds2, false);
+ sg.addSequence(cds1, false);
+ sg.setStartRes(0);
+ sg.setEndRes(cdna.getWidth() - 1);
+ mappedGroup = MappingUtils.mapSequenceGroup(sg, cdnaView, peptideView);
+ assertTrue(mappedGroup.getColourText());
+ assertSame(sg.getIdColour(), mappedGroup.getIdColour());
+ assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
+ assertEquals(2, mappedGroup.getSequences().size());
+ assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
+ assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
+ assertEquals(0, mappedGroup.getStartRes());
+ assertEquals(1, mappedGroup.getEndRes()); // two columns
+ }
}