Added hardClipLeadingInsertions UnitTest for the ReadClipper
fixed issue where a read starting with an insertion followed by a deletion would break, clipper can now safely clip the insertion and the deletion if that's the case. note: test is turned off until contract changes to allow hanging insertions (left/right).
This commit is contained in:
parent
075be52adc
commit
fcc21180e8
|
|
@ -204,16 +204,12 @@ public class ReadClipper {
|
||||||
|
|
||||||
for(CigarElement cigarElement : read.getCigar().getCigarElements()) {
|
for(CigarElement cigarElement : read.getCigar().getCigarElements()) {
|
||||||
if (cigarElement.getOperator() != CigarOperator.HARD_CLIP && cigarElement.getOperator() != CigarOperator.SOFT_CLIP &&
|
if (cigarElement.getOperator() != CigarOperator.HARD_CLIP && cigarElement.getOperator() != CigarOperator.SOFT_CLIP &&
|
||||||
cigarElement.getOperator() != CigarOperator.INSERTION && cigarElement.getOperator() != CigarOperator.DELETION)
|
cigarElement.getOperator() != CigarOperator.INSERTION)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
else if (cigarElement.getOperator() == CigarOperator.INSERTION) {
|
else if (cigarElement.getOperator() == CigarOperator.INSERTION)
|
||||||
this.addOp(new ClippingOp(0, cigarElement.getLength() - 1));
|
this.addOp(new ClippingOp(0, cigarElement.getLength() - 1));
|
||||||
}
|
|
||||||
|
|
||||||
else if (cigarElement.getOperator() == CigarOperator.DELETION) {
|
|
||||||
throw new ReviewedStingException("No read should start with a deletion. Aligner bug?");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return clipRead(ClippingRepresentation.HARDCLIP_BASES);
|
return clipRead(ClippingRepresentation.HARDCLIP_BASES);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -176,4 +176,16 @@ public class ClipReadsTestUtils {
|
||||||
Assert.assertEquals(actual.isEmpty(), expected.isEmpty());
|
Assert.assertEquals(actual.isEmpty(), expected.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Cigar invertCigar (Cigar cigar) {
|
||||||
|
Stack<CigarElement> cigarStack = new Stack<CigarElement>();
|
||||||
|
for (CigarElement cigarElement : cigar.getCigarElements())
|
||||||
|
cigarStack.push(cigarElement);
|
||||||
|
|
||||||
|
Cigar invertedCigar = new Cigar();
|
||||||
|
while (!cigarStack.isEmpty())
|
||||||
|
invertedCigar.add(cigarStack.pop());
|
||||||
|
|
||||||
|
return invertedCigar;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ import java.util.List;
|
||||||
public class ReadClipperUnitTest extends BaseTest {
|
public class ReadClipperUnitTest extends BaseTest {
|
||||||
|
|
||||||
List<Cigar> cigarList;
|
List<Cigar> cigarList;
|
||||||
int maximumCigarSize = 10;
|
int maximumCigarSize = 6; // 6 is the minimum necessary number to try all combinations of cigar types with guarantee of clipping an element with length = 2
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public void init() {
|
public void init() {
|
||||||
|
|
@ -277,10 +277,31 @@ public class ReadClipperUnitTest extends BaseTest {
|
||||||
|
|
||||||
// logger.warn(String.format("Cigar %s -> %s -- PASSED!", read.getCigarString(), clippedRead.getCigarString()));
|
// logger.warn(String.format("Cigar %s -> %s -- PASSED!", read.getCigarString(), clippedRead.getCigarString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.warn("PASSED");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(enabled = false)
|
||||||
|
public void testHardClipLeadingInsertions() {
|
||||||
|
for (Cigar cigar : cigarList) {
|
||||||
|
if (startsWithInsertion(cigar)) {
|
||||||
|
GATKSAMRecord read = ClipReadsTestUtils.makeReadFromCigar(cigar);
|
||||||
|
GATKSAMRecord clippedRead = (new ReadClipper(read)).hardClipLeadingInsertions();
|
||||||
|
|
||||||
|
int expectedLength = read.getReadLength() - leadingInsertionLength(read.getCigar());
|
||||||
|
if (cigarHasElementsDifferentThanInsertionsAndHardClips(read.getCigar()))
|
||||||
|
expectedLength -= leadingInsertionLength(ClipReadsTestUtils.invertCigar(read.getCigar()));
|
||||||
|
|
||||||
|
if (! clippedRead.isEmpty()) {
|
||||||
|
Assert.assertEquals(expectedLength, clippedRead.getReadLength(), String.format("%s -> %s", read.getCigarString(), clippedRead.getCigarString())); // check that everything else is still there
|
||||||
|
Assert.assertFalse(startsWithInsertion(clippedRead.getCigar())); // check that the insertions are gone
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Assert.assertTrue(expectedLength == 0, String.format("expected length: %d", expectedLength)); // check that the read was expected to be fully clipped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void assertNoLowQualBases(GATKSAMRecord read, byte low_qual) {
|
private void assertNoLowQualBases(GATKSAMRecord read, byte low_qual) {
|
||||||
if (!read.isEmpty()) {
|
if (!read.isEmpty()) {
|
||||||
byte [] quals = read.getBaseQualities();
|
byte [] quals = read.getBaseQualities();
|
||||||
|
|
@ -289,5 +310,24 @@ public class ReadClipperUnitTest extends BaseTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean startsWithInsertion(Cigar cigar) {
|
||||||
|
return leadingInsertionLength(cigar) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int leadingInsertionLength(Cigar cigar) {
|
||||||
|
for (CigarElement cigarElement : cigar.getCigarElements()) {
|
||||||
|
if (cigarElement.getOperator() == CigarOperator.INSERTION)
|
||||||
|
return cigarElement.getLength();
|
||||||
|
if (cigarElement.getOperator() != CigarOperator.HARD_CLIP)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cigarHasElementsDifferentThanInsertionsAndHardClips (Cigar cigar) {
|
||||||
|
for (CigarElement cigarElement : cigar.getCigarElements())
|
||||||
|
if (cigarElement.getOperator() != CigarOperator.INSERTION && cigarElement.getOperator() != CigarOperator.HARD_CLIP)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue