private void assertNoLowQualBases(GATKSAMRecord read, byte low_qual) { if (!read.isEmpty()) { byte[] quals = read.getBaseQualities(); for (int i = 0; i < quals.length; i++) Assert.assertFalse(quals[i] <= low_qual, String.format("Found low qual (%d) base after hard clipping. Position: %d -- %s", low_qual, i, read.getCigarString())); } }
@Test(enabled = true) public void testWonkyCigars() { for (String cigarString : BAD_CIGAR_LIST) { GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigarString, 0); Assert.assertTrue(filter.filterOut(read), read.getCigarString()); } }
@Test(enabled = true) public void testReadCigarLengthMismatch() { GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar("4M", 1); Assert.assertTrue(filter.filterOut(read), read.getCigarString()); }
@Test(enabled = !DEBUG) public void testHardClipBothEndsByReferenceCoordinates() { for (Cigar cigar : cigarList) { GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); int alnStart = read.getAlignmentStart(); int alnEnd = read.getAlignmentEnd(); int readLength = alnStart - alnEnd; for (int i = 0; i < readLength / 2; i++) { GATKSAMRecord clippedRead = ReadClipper.hardClipBothEndsByReferenceCoordinates(read, alnStart + i, alnEnd - i); Assert.assertTrue(clippedRead.getAlignmentStart() >= alnStart + i, String.format("Clipped alignment start is less than original read (minus %d): %s -> %s", i, read.getCigarString(), clippedRead.getCigarString())); Assert.assertTrue(clippedRead.getAlignmentEnd() <= alnEnd + i, String.format("Clipped alignment end is greater than original read (minus %d): %s -> %s", i, read.getCigarString(), clippedRead.getCigarString())); assertUnclippedLimits(read, clippedRead); } } }
@Test(enabled = !DEBUG) public void testHardClipByReadCoordinates() { for (Cigar cigar : cigarList) { GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); int readLength = read.getReadLength(); for (int i = 0; i < readLength; i++) { GATKSAMRecord clipLeft = ReadClipper.hardClipByReadCoordinates(read, 0, i); Assert.assertTrue(clipLeft.getReadLength() <= readLength - i, String.format("Clipped read length is greater than original read length (minus %d): %s -> %s", i, read.getCigarString(), clipLeft.getCigarString())); assertUnclippedLimits(read, clipLeft); GATKSAMRecord clipRight = ReadClipper.hardClipByReadCoordinates(read, i, readLength - 1); Assert.assertTrue(clipRight.getReadLength() <= i, String.format("Clipped read length is greater than original read length (minus %d): %s -> %s", i, read.getCigarString(), clipRight.getCigarString())); assertUnclippedLimits(read, clipRight); } } }
@Test(enabled = true) public void testGoodCigars() { List<Cigar> cigarList = ReadClipperTestUtils.generateCigarList(10); for (Cigar cigar : cigarList) { GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); Assert.assertFalse(filter.filterOut(read), read.getCigarString()); } } }
@Test(enabled = true, dataProvider = "RevertSoftClipsBeforeContig") public void testRevertSoftClippedBasesBeforeStartOfContig(final int softStart, final int alignmentStart) { final int nMatches = 10; final int nSoft = -1 * (softStart - alignmentStart); final String cigar = nSoft + "S" + nMatches + "M"; final GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); read.setAlignmentStart(alignmentStart); Assert.assertEquals(read.getSoftStart(), softStart); Assert.assertEquals(read.getAlignmentStart(), alignmentStart); Assert.assertEquals(read.getCigarString(), cigar); final GATKSAMRecord reverted = ReadClipper.revertSoftClippedBases(read); final int expectedAlignmentStart = 1; final String expectedCigar = (1 - softStart) + "H" + read.getAlignmentEnd() + "M"; Assert.assertEquals(reverted.getSoftStart(), expectedAlignmentStart); Assert.assertEquals(reverted.getAlignmentStart(), expectedAlignmentStart); Assert.assertEquals(reverted.getCigarString(), expectedCigar); }
@Test(enabled = !DEBUG, dataProvider = "MergeFragmentsTest") public void testMergingTwoReads(final String name, final GATKSAMRecord read1, final GATKSAMRecord read2, final GATKSAMRecord expectedMerged) { final GATKSAMRecord actual = FragmentUtils.mergeOverlappingPairedFragments(read1, read2); if ( expectedMerged == null ) { Assert.assertNull(actual, "Expected reads not to merge, but got non-null result from merging"); } else { Assert.assertTrue(actual.isStrandless(), "Merged reads should be strandless"); Assert.assertNotNull(actual, "Expected reads to merge, but got null result from merging"); // I really care about the bases, the quals, the CIGAR, and the read group tag Assert.assertEquals(actual.getCigarString(), expectedMerged.getCigarString()); Assert.assertEquals(actual.getReadBases(), expectedMerged.getReadBases()); Assert.assertEquals(actual.getReadGroup(), expectedMerged.getReadGroup()); Assert.assertEquals(actual.getMappingQuality(), expectedMerged.getMappingQuality()); for ( final EventType type : EventType.values() ) Assert.assertEquals(actual.getBaseQualities(type), expectedMerged.getBaseQualities(type), "Failed base qualities for event type " + type); } }
/** * Asserts that the two reads have the same bases, qualities and cigar strings * * @param actual the calculated read * @param expected the expected read */ public static void assertEqualReads(GATKSAMRecord actual, GATKSAMRecord expected) { // If they're both not empty, test their contents if(!actual.isEmpty() && !expected.isEmpty()) { Assert.assertEquals(actual.getReadBases(), expected.getReadBases()); Assert.assertEquals(actual.getBaseQualities(), expected.getBaseQualities()); Assert.assertEquals(actual.getCigarString(), expected.getCigarString()); } // Otherwise test if they're both empty else Assert.assertEquals(actual.isEmpty(), expected.isEmpty()); } }
@Test(enabled = !DEBUG) public void testRevertSoftClippedBasesWithThreshold() { for (Cigar cigar : cigarList) { final int leadingSoftClips = leadingCigarElementLength(cigar, CigarOperator.SOFT_CLIP); final int tailSoftClips = leadingCigarElementLength(CigarUtils.invertCigar(cigar), CigarOperator.SOFT_CLIP); final GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); final GATKSAMRecord unclipped = ReadClipper.revertSoftClippedBases(read); assertUnclippedLimits(read, unclipped); // Make sure limits haven't changed Assert.assertNull(read.getCigar().isValid(null, -1)); Assert.assertNull(unclipped.getCigar().isValid(null, -1)); if (!(leadingSoftClips > 0 || tailSoftClips > 0)) Assert.assertEquals(read.getCigarString(), unclipped.getCigarString()); } }
@Test(enabled = !DEBUG) public void testHardClipByReferenceCoordinatesLeftTail() { for (Cigar cigar : cigarList) { GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); int alnStart = read.getAlignmentStart(); int alnEnd = read.getAlignmentEnd(); if (read.getSoftStart() == alnStart) { // we can't test left clipping if the read has hanging soft clips on the left side for (int i = alnStart; i <= alnEnd; i++) { GATKSAMRecord clipLeft = ReadClipper.hardClipByReferenceCoordinatesLeftTail(read, i); if (!clipLeft.isEmpty()) { Assert.assertTrue(clipLeft.getAlignmentStart() >= i + 1, String.format("Clipped alignment start (%d) is less the expected (%d): %s -> %s", clipLeft.getAlignmentStart(), i + 1, read.getCigarString(), clipLeft.getCigarString())); assertUnclippedLimits(read, clipLeft); } } } } }
@Test(enabled = !DEBUG) public void testRevertSoftClippedBases() { for (Cigar cigar : cigarList) { final int leadingSoftClips = leadingCigarElementLength(cigar, CigarOperator.SOFT_CLIP); final int tailSoftClips = leadingCigarElementLength(CigarUtils.invertCigar(cigar), CigarOperator.SOFT_CLIP); final GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); final GATKSAMRecord unclipped = ReadClipper.revertSoftClippedBases(read); assertUnclippedLimits(read, unclipped); // Make sure limits haven't changed if (leadingSoftClips > 0 || tailSoftClips > 0) { final int expectedStart = read.getAlignmentStart() - leadingSoftClips; final int expectedEnd = read.getAlignmentEnd() + tailSoftClips; Assert.assertEquals(unclipped.getAlignmentStart(), expectedStart); Assert.assertEquals(unclipped.getAlignmentEnd(), expectedEnd); } else Assert.assertEquals(read.getCigarString(), unclipped.getCigarString()); } }
throw new ReviewedGATKException(String.format("START (%d) > (%d) STOP -- this should never happen, please check read: %s (CIGAR: %s)", start, stop, read, read.getCigarString())); throw new ReviewedGATKException(String.format("Trying to clip the middle of the read: start %d, stop %d, cigar: %s", start, stop, read.getCigarString()));
@Test(enabled = !DEBUG) public void testHardClipByReferenceCoordinates() { for (Cigar cigar : cigarList) { GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); int start = read.getSoftStart(); int stop = read.getSoftEnd(); for (int i = start; i <= stop; i++) { GATKSAMRecord clipLeft = (new ReadClipper(read)).hardClipByReferenceCoordinates(-1, i); if (!clipLeft.isEmpty()) { Assert.assertTrue(clipLeft.getAlignmentStart() >= Math.min(read.getAlignmentEnd(), i + 1), String.format("Clipped alignment start (%d) is less the expected (%d): %s -> %s", clipLeft.getAlignmentStart(), i + 1, read.getCigarString(), clipLeft.getCigarString())); assertUnclippedLimits(read, clipLeft); } GATKSAMRecord clipRight = (new ReadClipper(read)).hardClipByReferenceCoordinates(i, -1); if (!clipRight.isEmpty() && clipRight.getAlignmentStart() <= clipRight.getAlignmentEnd()) { // alnStart > alnEnd if the entire read is a soft clip now. We can't test those. Assert.assertTrue(clipRight.getAlignmentEnd() <= Math.max(read.getAlignmentStart(), i - 1), String.format("Clipped alignment end (%d) is greater than expected (%d): %s -> %s", clipRight.getAlignmentEnd(), i - 1, read.getCigarString(), clipRight.getCigarString())); assertUnclippedLimits(read, clipRight); } } } }
@Test(enabled = !DEBUG) public void testHardClipByReferenceCoordinatesRightTail() { for (Cigar cigar : cigarList) { GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); int alnStart = read.getAlignmentStart(); int alnEnd = read.getAlignmentEnd(); if (read.getSoftEnd() == alnEnd) { // we can't test right clipping if the read has hanging soft clips on the right side for (int i = alnStart; i <= alnEnd; i++) { GATKSAMRecord clipRight = ReadClipper.hardClipByReferenceCoordinatesRightTail(read, i); if (!clipRight.isEmpty() && clipRight.getAlignmentStart() <= clipRight.getAlignmentEnd()) { // alnStart > alnEnd if the entire read is a soft clip now. We can't test those. Assert.assertTrue(clipRight.getAlignmentEnd() <= i - 1, String.format("Clipped alignment end (%d) is greater than expected (%d): %s -> %s", clipRight.getAlignmentEnd(), i - 1, read.getCigarString(), clipRight.getCigarString())); assertUnclippedLimits(read, clipRight); } } } } }
@Test(dataProvider = "ComplexReadAlignedToRef", enabled = !DEBUG) public void testReadAlignedToRefComplexAlignment(final int testIndex, final GATKSAMRecord read, final String reference, final Haplotype haplotype, final int expectedMaxMismatches) throws Exception { final HaplotypeBAMWriter writer = new CalledHaplotypeBAMWriter(new MockDestination()); final GATKSAMRecord alignedRead = AlignmentUtils.createReadAlignedToRef(read, haplotype, new Haplotype(reference.getBytes(),true), 1, true); if ( alignedRead != null ) { final int mismatches = AlignmentUtils.getMismatchCount(alignedRead, reference.getBytes(), alignedRead.getAlignmentStart() - 1).numMismatches; Assert.assertTrue(mismatches <= expectedMaxMismatches, "Alignment of read to ref looks broken. Expected at most " + expectedMaxMismatches + " but saw " + mismatches + " for readBases " + new String(read.getReadBases()) + " with cigar " + read.getCigar() + " reference " + reference + " haplotype " + haplotype + " with cigar " + haplotype.getCigar() + " aligned read cigar " + alignedRead.getCigarString() + " @ " + alignedRead.getAlignmentStart()); } } }
@Test(enabled = false) public void testHardClipLeadingInsertions() { for (Cigar cigar : cigarList) { if (startsWithInsertion(cigar)) { GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar, 0); GATKSAMRecord clippedRead = ReadClipper.hardClipLeadingInsertions(read); assertUnclippedLimits(read, clippedRead); // Make sure limits haven't changed int expectedLength = read.getReadLength() - leadingCigarElementLength(read.getCigar(), CigarOperator.INSERTION); if (cigarHasElementsDifferentThanInsertionsAndHardClips(read.getCigar())) expectedLength -= leadingCigarElementLength(CigarUtils.invertCigar(read.getCigar()), CigarOperator.INSERTION); 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 } } }
Assert.assertEquals(actual.getCigarString(), expectedMerged.getCigarString()); Assert.assertEquals(actual.getReadBases(), expectedMerged.getReadBases()); Assert.assertEquals(actual.getReadGroup(), expectedMerged.getReadGroup());
for ( final GATKSAMRecord read : bamBuilder.makeReads() ) { Assert.assertTrue(readNamesInRegion.contains(read.getReadName()), "Region " + region + " should contain read " + read + " with cigar " + read.getCigarString() + " but it wasn't"); nReadsExpectedInRegion++;
cigarSecondIndex--; if(cigarFirstIndex > cigarSecondIndex) throw new UserException.BadInput("Cannot split this read (might be an empty section between Ns, for example 1N1D1N): "+read.getCigarString());