Merge Eric's LocusIteratorByStateUnitTest changes into LocusIteratorByStateExperimentalUnitTest
This commit is contained in:
parent
e25e617d1a
commit
6fad0f25bb
|
|
@ -1,8 +1,6 @@
|
|||
package org.broadinstitute.sting.gatk.iterators;
|
||||
|
||||
import net.sf.samtools.SAMFileHeader;
|
||||
import net.sf.samtools.SAMFileReader;
|
||||
import net.sf.samtools.SAMRecord;
|
||||
import net.sf.samtools.*;
|
||||
import net.sf.samtools.util.CloseableIterator;
|
||||
import org.broadinstitute.sting.BaseTest;
|
||||
import org.broadinstitute.sting.gatk.ReadProperties;
|
||||
|
|
@ -39,57 +37,10 @@ public class LocusIteratorByStateExperimentalUnitTest extends BaseTest {
|
|||
genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
|
||||
}
|
||||
|
||||
private final LocusIteratorByStateExperimental makeLTBS(List<SAMRecord> reads, ReadProperties readAttributes) {
|
||||
private LocusIteratorByStateExperimental makeLTBS(List<SAMRecord> reads, ReadProperties readAttributes) {
|
||||
return new LocusIteratorByStateExperimental(new FakeCloseableIterator<SAMRecord>(reads.iterator()), readAttributes, genomeLocParser, LocusIteratorByStateExperimental.sampleListForSAMWithoutReadGroups());
|
||||
}
|
||||
|
||||
private static ReadProperties createTestReadProperties() {
|
||||
return createTestReadProperties(null);
|
||||
}
|
||||
|
||||
private static ReadProperties createTestReadProperties( DownsamplingMethod downsamplingMethod ) {
|
||||
return new ReadProperties(
|
||||
Collections.<SAMReaderID>emptyList(),
|
||||
new SAMFileHeader(),
|
||||
false,
|
||||
SAMFileReader.ValidationStringency.STRICT,
|
||||
downsamplingMethod,
|
||||
new ValidationExclusion(),
|
||||
Collections.<ReadFilter>emptyList(),
|
||||
Collections.<ReadTransformer>emptyList(),
|
||||
false,
|
||||
(byte) -1
|
||||
);
|
||||
}
|
||||
|
||||
private static class FakeCloseableIterator<T> implements CloseableIterator<T> {
|
||||
Iterator<T> iterator;
|
||||
|
||||
public FakeCloseableIterator(Iterator<T> it) {
|
||||
iterator = it;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return iterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Don't remove!");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXandEQOperators() {
|
||||
final byte[] bases1 = new byte[] {'A','A','A','A','A','A','A','A','A','A'};
|
||||
|
|
@ -308,45 +259,36 @@ public class LocusIteratorByStateExperimentalUnitTest extends BaseTest {
|
|||
// comprehensive LIBS/PileupElement tests //
|
||||
////////////////////////////////////////////
|
||||
|
||||
private static final int IS_BEFORE_DELETED_BASE_FLAG = 1;
|
||||
private static final int IS_BEFORE_DELETION_START_FLAG = 2;
|
||||
private static final int IS_AFTER_DELETED_BASE_FLAG = 4;
|
||||
private static final int IS_AFTER_DELETION_END_FLAG = 8;
|
||||
private static final int IS_BEFORE_INSERTION_FLAG = 16;
|
||||
private static final int IS_AFTER_INSERTION_FLAG = 32;
|
||||
private static final int IS_NEXT_TO_SOFTCLIP_FLAG = 64;
|
||||
|
||||
private static class LIBSTest {
|
||||
|
||||
|
||||
final String cigar;
|
||||
final int readLength;
|
||||
final List<Integer> offsets;
|
||||
final List<Integer> flags;
|
||||
|
||||
private LIBSTest(final String cigar, final int readLength, final List<Integer> offsets, final List<Integer> flags) {
|
||||
private LIBSTest(final String cigar, final int readLength) {
|
||||
this.cigar = cigar;
|
||||
this.readLength = readLength;
|
||||
this.offsets = offsets;
|
||||
this.flags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider(name = "LIBSTest")
|
||||
public Object[][] createLIBSTestData() {
|
||||
|
||||
//TODO -- when LIBS is fixed this should be replaced to provide all possible permutations of CIGAR strings
|
||||
|
||||
return new Object[][]{
|
||||
{new LIBSTest("1I", 1, Arrays.asList(0), Arrays.asList(IS_BEFORE_INSERTION_FLAG))},
|
||||
{new LIBSTest("10I", 10, Arrays.asList(0), Arrays.asList(IS_BEFORE_INSERTION_FLAG))},
|
||||
{new LIBSTest("2M2I2M", 6, Arrays.asList(0,1,4,5), Arrays.asList(0,IS_BEFORE_INSERTION_FLAG,IS_AFTER_INSERTION_FLAG,0))},
|
||||
{new LIBSTest("2M2I", 4, Arrays.asList(0,1), Arrays.asList(0,IS_BEFORE_INSERTION_FLAG))},
|
||||
{new LIBSTest("1I", 1)},
|
||||
{new LIBSTest("10I", 10)},
|
||||
{new LIBSTest("2M2I2M", 6)},
|
||||
{new LIBSTest("2M2I", 4)},
|
||||
//TODO -- uncomment these when LIBS is fixed
|
||||
//{new LIBSTest("2I2M", 4, Arrays.asList(2,3), Arrays.asList(IS_AFTER_INSERTION_FLAG,0))},
|
||||
//{new LIBSTest("1I1M1D1M", 3, Arrays.asList(0,1), Arrays.asList(IS_AFTER_INSERTION_FLAG | IS_BEFORE_DELETION_START_FLAG | IS_BEFORE_DELETED_BASE_FLAG,IS_AFTER_DELETED_BASE_FLAG | IS_AFTER_DELETION_END_FLAG))},
|
||||
//{new LIBSTest("1S1I1M", 3, Arrays.asList(2), Arrays.asList(IS_AFTER_INSERTION_FLAG))},
|
||||
{new LIBSTest("1M2D2M", 3, Arrays.asList(0,1,2), Arrays.asList(IS_BEFORE_DELETION_START_FLAG | IS_BEFORE_DELETED_BASE_FLAG,IS_AFTER_DELETED_BASE_FLAG | IS_AFTER_DELETION_END_FLAG,0))},
|
||||
{new LIBSTest("1S1M", 2, Arrays.asList(1), Arrays.asList(IS_NEXT_TO_SOFTCLIP_FLAG))},
|
||||
{new LIBSTest("1M1S", 2, Arrays.asList(0), Arrays.asList(IS_NEXT_TO_SOFTCLIP_FLAG))},
|
||||
{new LIBSTest("1S1M1I", 3, Arrays.asList(1), Arrays.asList(IS_BEFORE_INSERTION_FLAG | IS_NEXT_TO_SOFTCLIP_FLAG))}
|
||||
//{new LIBSTest("1M2D2M", 3)},
|
||||
{new LIBSTest("1S1M", 2)},
|
||||
{new LIBSTest("1M1S", 2)},
|
||||
{new LIBSTest("1S1M1I", 3)}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -361,26 +303,24 @@ public class LocusIteratorByStateExperimentalUnitTest extends BaseTest {
|
|||
|
||||
// create the iterator by state with the fake reads and fake records
|
||||
li = makeLTBS(Arrays.asList(read), createTestReadProperties());
|
||||
final LIBS_position tester = new LIBS_position(read);
|
||||
|
||||
int offset = 0;
|
||||
while ( li.hasNext() ) {
|
||||
AlignmentContext alignmentContext = li.next();
|
||||
ReadBackedPileup p = alignmentContext.getBasePileup();
|
||||
Assert.assertTrue(p.getNumberOfElements() == 1);
|
||||
PileupElement pe = p.iterator().next();
|
||||
|
||||
final int flag = params.flags.get(offset);
|
||||
Assert.assertEquals(pe.isBeforeDeletedBase(), (flag & IS_BEFORE_DELETED_BASE_FLAG) != 0);
|
||||
Assert.assertEquals(pe.isBeforeDeletionStart(), (flag & IS_BEFORE_DELETION_START_FLAG) != 0);
|
||||
Assert.assertEquals(pe.isAfterDeletedBase(), (flag & IS_AFTER_DELETED_BASE_FLAG) != 0);
|
||||
Assert.assertEquals(pe.isAfterDeletionEnd(), (flag & IS_AFTER_DELETION_END_FLAG) != 0);
|
||||
Assert.assertEquals(pe.isBeforeInsertion(), (flag & IS_BEFORE_INSERTION_FLAG) != 0);
|
||||
Assert.assertEquals(pe.isAfterInsertion(), (flag & IS_AFTER_INSERTION_FLAG) != 0);
|
||||
Assert.assertEquals(pe.isNextToSoftClip(), (flag & IS_NEXT_TO_SOFTCLIP_FLAG) != 0);
|
||||
tester.stepForwardOnGenome();
|
||||
|
||||
Assert.assertEquals(pe.getOffset(), params.offsets.get(offset).intValue());
|
||||
|
||||
offset++;
|
||||
Assert.assertEquals(pe.isBeforeDeletedBase(), tester.isBeforeDeletedBase);
|
||||
Assert.assertEquals(pe.isBeforeDeletionStart(), tester.isBeforeDeletionStart);
|
||||
Assert.assertEquals(pe.isAfterDeletedBase(), tester.isAfterDeletedBase);
|
||||
Assert.assertEquals(pe.isAfterDeletionEnd(), tester.isAfterDeletionEnd);
|
||||
Assert.assertEquals(pe.isBeforeInsertion(), tester.isBeforeInsertion);
|
||||
Assert.assertEquals(pe.isAfterInsertion(), tester.isAfterInsertion);
|
||||
Assert.assertEquals(pe.isNextToSoftClip(), tester.isNextToSoftClip);
|
||||
Assert.assertEquals(pe.getOffset(), tester.getCurrentReadOffset());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -543,4 +483,165 @@ public class LocusIteratorByStateExperimentalUnitTest extends BaseTest {
|
|||
|
||||
test.run();
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// End Read State Manager Tests //
|
||||
///////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Helper methods / classes //
|
||||
///////////////////////////////////////
|
||||
|
||||
private static ReadProperties createTestReadProperties() {
|
||||
return createTestReadProperties(null);
|
||||
}
|
||||
|
||||
private static ReadProperties createTestReadProperties( DownsamplingMethod downsamplingMethod ) {
|
||||
return new ReadProperties(
|
||||
Collections.<SAMReaderID>emptyList(),
|
||||
new SAMFileHeader(),
|
||||
false,
|
||||
SAMFileReader.ValidationStringency.STRICT,
|
||||
downsamplingMethod,
|
||||
new ValidationExclusion(),
|
||||
Collections.<ReadFilter>emptyList(),
|
||||
Collections.<ReadTransformer>emptyList(),
|
||||
false,
|
||||
(byte) -1
|
||||
);
|
||||
}
|
||||
|
||||
private static class FakeCloseableIterator<T> implements CloseableIterator<T> {
|
||||
Iterator<T> iterator;
|
||||
|
||||
public FakeCloseableIterator(Iterator<T> it) {
|
||||
iterator = it;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return iterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Don't remove!");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class LIBS_position {
|
||||
|
||||
SAMRecord read;
|
||||
|
||||
final int numOperators;
|
||||
int currentOperatorIndex = 0;
|
||||
int currentPositionOnOperator = 0;
|
||||
int currentReadOffset = 0;
|
||||
|
||||
boolean isBeforeDeletionStart = false;
|
||||
boolean isBeforeDeletedBase = false;
|
||||
boolean isAfterDeletionEnd = false;
|
||||
boolean isAfterDeletedBase = false;
|
||||
boolean isBeforeInsertion = false;
|
||||
boolean isAfterInsertion = false;
|
||||
boolean isNextToSoftClip = false;
|
||||
|
||||
boolean sawMop = false;
|
||||
|
||||
public LIBS_position(final SAMRecord read) {
|
||||
this.read = read;
|
||||
numOperators = read.getCigar().numCigarElements();
|
||||
}
|
||||
|
||||
public int getCurrentReadOffset() {
|
||||
return Math.max(0, currentReadOffset - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps forward on the genome. Returns false when done reading the read, true otherwise.
|
||||
*/
|
||||
public boolean stepForwardOnGenome() {
|
||||
if ( currentOperatorIndex == numOperators )
|
||||
return false;
|
||||
|
||||
CigarElement curElement = read.getCigar().getCigarElement(currentOperatorIndex);
|
||||
if ( currentPositionOnOperator >= curElement.getLength() ) {
|
||||
if ( ++currentOperatorIndex == numOperators )
|
||||
return false;
|
||||
|
||||
curElement = read.getCigar().getCigarElement(currentOperatorIndex);
|
||||
currentPositionOnOperator = 0;
|
||||
}
|
||||
|
||||
switch ( curElement.getOperator() ) {
|
||||
case I: // insertion w.r.t. the reference
|
||||
if ( !sawMop )
|
||||
break;
|
||||
case S: // soft clip
|
||||
currentReadOffset += curElement.getLength();
|
||||
case H: // hard clip
|
||||
case P: // padding
|
||||
currentOperatorIndex++;
|
||||
return stepForwardOnGenome();
|
||||
|
||||
case D: // deletion w.r.t. the reference
|
||||
case N: // reference skip (looks and gets processed just like a "deletion", just different logical meaning)
|
||||
currentPositionOnOperator++;
|
||||
break;
|
||||
|
||||
case M:
|
||||
case EQ:
|
||||
case X:
|
||||
sawMop = true;
|
||||
currentReadOffset++;
|
||||
currentPositionOnOperator++;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("No support for cigar op: " + curElement.getOperator());
|
||||
}
|
||||
|
||||
final boolean isFirstOp = currentOperatorIndex == 0;
|
||||
final boolean isLastOp = currentOperatorIndex == numOperators - 1;
|
||||
final boolean isFirstBaseOfOp = currentPositionOnOperator == 1;
|
||||
final boolean isLastBaseOfOp = currentPositionOnOperator == curElement.getLength();
|
||||
|
||||
isBeforeDeletionStart = isBeforeOp(read.getCigar(), currentOperatorIndex, CigarOperator.D, isLastOp, isLastBaseOfOp);
|
||||
isBeforeDeletedBase = isBeforeDeletionStart || (!isLastBaseOfOp && curElement.getOperator() == CigarOperator.D);
|
||||
isAfterDeletionEnd = isAfterOp(read.getCigar(), currentOperatorIndex, CigarOperator.D, isFirstOp, isFirstBaseOfOp);
|
||||
isAfterDeletedBase = isAfterDeletionEnd || (!isFirstBaseOfOp && curElement.getOperator() == CigarOperator.D);
|
||||
isBeforeInsertion = isBeforeOp(read.getCigar(), currentOperatorIndex, CigarOperator.I, isLastOp, isLastBaseOfOp)
|
||||
|| (!sawMop && curElement.getOperator() == CigarOperator.I);
|
||||
isAfterInsertion = isAfterOp(read.getCigar(), currentOperatorIndex, CigarOperator.I, isFirstOp, isFirstBaseOfOp);
|
||||
isNextToSoftClip = isBeforeOp(read.getCigar(), currentOperatorIndex, CigarOperator.S, isLastOp, isLastBaseOfOp)
|
||||
|| isAfterOp(read.getCigar(), currentOperatorIndex, CigarOperator.S, isFirstOp, isFirstBaseOfOp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isBeforeOp(final Cigar cigar,
|
||||
final int currentOperatorIndex,
|
||||
final CigarOperator op,
|
||||
final boolean isLastOp,
|
||||
final boolean isLastBaseOfOp) {
|
||||
return !isLastOp && isLastBaseOfOp && cigar.getCigarElement(currentOperatorIndex+1).getOperator() == op;
|
||||
}
|
||||
|
||||
private static boolean isAfterOp(final Cigar cigar,
|
||||
final int currentOperatorIndex,
|
||||
final CigarOperator op,
|
||||
final boolean isFirstOp,
|
||||
final boolean isFirstBaseOfOp) {
|
||||
return !isFirstOp && isFirstBaseOfOp && cigar.getCigarElement(currentOperatorIndex-1).getOperator() == op;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue