1 package org.broadinstitute.hellbender.tools; 2 3 import htsjdk.samtools.SAMFileHeader; 4 import org.broadinstitute.hellbender.GATKBaseTest; 5 import org.broadinstitute.hellbender.tools.AnalyzeSaturationMutagenesis.*; 6 import org.broadinstitute.hellbender.utils.read.ArtificialReadUtils; 7 import org.broadinstitute.hellbender.utils.read.GATKRead; 8 import org.testng.Assert; 9 import org.testng.annotations.Test; 10 11 import java.util.ArrayList; 12 import java.util.Arrays; 13 import java.util.Collections; 14 import java.util.List; 15 16 import static org.broadinstitute.hellbender.tools.AnalyzeSaturationMutagenesis.CodonTracker.NO_FRAME_SHIFT_CODON; 17 import static org.broadinstitute.hellbender.tools.AnalyzeSaturationMutagenesis.*; 18 19 public class AnalyzeSaturationMutagenesisUnitTest extends GATKBaseTest { 20 final private static byte CALL_A = (byte)'A'; 21 final private static byte CALL_C = (byte)'C'; 22 final private static byte CALL_G = (byte)'G'; 23 final private static byte CALL_T = (byte)'T'; 24 final private static byte NO_CALL = (byte)'-'; 25 final private static byte QUAL_10 = (byte)10; 26 final private static byte QUAL_20 = (byte)20; 27 final private static byte QUAL_30 = (byte)30; 28 final private static byte[] refSeq = "ACATGCGTCTAGTACGT".getBytes(); 29 final private static String orfCoords = "3-6,8-12"; 30 final private static CodonTracker localCodonTracker = new CodonTracker(orfCoords, refSeq, logger); 31 32 @Test testInterval()33 public void testInterval() { 34 final Interval interval1 = new Interval(1, 3); 35 Assert.assertEquals(interval1.size(), 2); 36 final Interval interval2 = new Interval(1, 3); 37 Assert.assertEquals(interval1, interval2); 38 Assert.assertEquals(interval1.hashCode(), interval2.hashCode()); 39 final Interval interval3 = new Interval(1, 4); 40 Assert.assertNotEquals(interval1, interval3); 41 Assert.assertNotEquals(interval1.hashCode(), interval3.hashCode()); 42 } 43 44 @Test testSNV()45 public void testSNV() { 46 final SNV snv1 = new SNV(0, CALL_A, CALL_C, QUAL_30); 47 final SNV snv2 = new SNV(0, CALL_A, CALL_C, QUAL_20); 48 Assert.assertEquals(snv1.hashCode(), snv2.hashCode()); 49 Assert.assertEquals(snv1, snv2); 50 Assert.assertEquals(snv1.compareTo(snv2), 0); 51 final SNV snv3 = new SNV(1, CALL_A, CALL_C, QUAL_30); 52 Assert.assertNotEquals(snv1.hashCode(), snv3.hashCode()); 53 Assert.assertNotEquals(snv1, snv3); 54 Assert.assertTrue(snv1.compareTo(snv3) < 0); 55 Assert.assertTrue(snv3.compareTo(snv2) > 0); 56 final SNV snv4 = new SNV(0, CALL_G, CALL_C, QUAL_30); 57 Assert.assertNotEquals(snv1.hashCode(), snv4.hashCode()); 58 Assert.assertNotEquals(snv1, snv4); 59 Assert.assertTrue(snv1.compareTo(snv4) < 0); 60 Assert.assertTrue(snv4.compareTo(snv1) > 0); 61 final SNV snv5 = new SNV(0, CALL_A, CALL_G, QUAL_30); 62 Assert.assertNotEquals(snv1.hashCode(), snv5.hashCode()); 63 Assert.assertNotEquals(snv1, snv5); 64 Assert.assertTrue(snv1.compareTo(snv5) < 0); 65 Assert.assertTrue(snv5.compareTo(snv1) > 0); 66 Assert.assertEquals(snv5.toString(), "1:A>G"); 67 } 68 69 @Test testIntervalCounter()70 public void testIntervalCounter() { 71 final IntervalCounter intervalCounter = new IntervalCounter(10); 72 intervalCounter.addCount(new Interval(0, 10)); 73 intervalCounter.addCount(new Interval(1, 9)); 74 intervalCounter.addCount(new Interval(2, 8)); 75 intervalCounter.addCount(new Interval(3, 7)); 76 intervalCounter.addCount(new Interval(4, 6)); 77 Assert.assertEquals(intervalCounter.countSpanners(0, 10), 1); 78 Assert.assertEquals(intervalCounter.countSpanners(5, 5), 5); 79 Assert.assertEquals(intervalCounter.countSpanners(2, 5), 3); 80 Assert.assertEquals(intervalCounter.countSpanners(5, 8), 3); 81 intervalCounter.addCount(new Interval(0, 10)); 82 Assert.assertEquals(intervalCounter.countSpanners(0, 10), 2); 83 } 84 85 @Test testSNVCollection()86 public void testSNVCollection() { 87 final List<SNV> snvList1 = new ArrayList<>(Arrays.asList( 88 new SNV(0, CALL_A, CALL_C, QUAL_30), 89 new SNV(1, CALL_A, CALL_C, QUAL_20))); 90 final SNVCollectionCount cc1 = new SNVCollectionCount(snvList1, 10); 91 92 // equality, key, compare, and hash should be independent of count and coverage 93 final List<SNV> snvList2 = Arrays.asList( 94 new SNV(0, CALL_A, CALL_C, QUAL_30), 95 new SNV(1, CALL_A, CALL_C, QUAL_20)); 96 final SNVCollectionCount cc2 = new SNVCollectionCount(snvList2, 20); 97 Assert.assertEquals(cc1.hashCode(), cc2.hashCode()); 98 Assert.assertEquals(cc1, cc2); 99 Assert.assertEquals(cc1.compareTo(cc2), 0); 100 cc2.bumpCount(30); 101 Assert.assertEquals(cc1.hashCode(), cc2.hashCode()); 102 Assert.assertEquals(cc1, cc2); 103 Assert.assertEquals(cc1.compareTo(cc2), 0); 104 105 Assert.assertEquals(cc2.getCount(), 2); 106 Assert.assertEquals(cc2.getMeanRefCoverage(), 25., .0000001); 107 108 // changing the list shouldn't change the hash or the key 109 final int cc1Hash = cc1.hashCode(); 110 final List<SNV> key1 = cc1.getSNVs(); 111 snvList1.add(new SNV(2, CALL_A, CALL_C, QUAL_10)); 112 Assert.assertEquals(cc1.hashCode(), cc1Hash); 113 Assert.assertEquals(cc1.getSNVs(), key1); 114 115 // different lists should mean unequal to each other, unequal hashes, and non-zero compare 116 final SNVCollectionCount cc3 = new SNVCollectionCount(snvList1, 20); 117 Assert.assertNotEquals(cc1.hashCode(), cc3.hashCode()); 118 Assert.assertNotEquals(cc1, cc3); 119 Assert.assertTrue(cc1.compareTo(cc3) < 0); 120 Assert.assertTrue(cc3.compareTo(cc1) > 0); 121 } 122 123 @Test testCodonVariationBasics()124 public void testCodonVariationBasics() { 125 Assert.assertTrue(CodonVariation.createDeletion(0).isDeletion()); 126 Assert.assertTrue(CodonVariation.createFrameshift(0).isFrameshift()); 127 Assert.assertTrue(CodonVariation.createInsertion(0,0).isInsertion()); 128 Assert.assertTrue(CodonVariation.createModification(0,0).isModification()); 129 Assert.assertFalse(CodonVariation.createDeletion(0).isModification()); 130 131 Assert.assertEquals(CodonVariation.createDeletion(1), CodonVariation.createDeletion(1)); 132 Assert.assertNotEquals(CodonVariation.createDeletion(0), CodonVariation.createDeletion(1)); 133 Assert.assertEquals(CodonVariation.createFrameshift(1), CodonVariation.createFrameshift(1)); 134 Assert.assertNotEquals(CodonVariation.createFrameshift(0), CodonVariation.createFrameshift(1)); 135 Assert.assertNotEquals(CodonVariation.createFrameshift(0), CodonVariation.createDeletion(0)); 136 Assert.assertEquals(CodonVariation.createInsertion(1, 0), 137 CodonVariation.createInsertion(1, 0)); 138 Assert.assertNotEquals(CodonVariation.createInsertion(0, 0), 139 CodonVariation.createInsertion(1, 0)); 140 Assert.assertNotEquals(CodonVariation.createInsertion(0, 0), 141 CodonVariation.createInsertion(0, 1)); 142 Assert.assertEquals(CodonVariation.createModification(1, 0), 143 CodonVariation.createModification(1, 0)); 144 Assert.assertNotEquals(CodonVariation.createModification(0, 0), 145 CodonVariation.createModification(1, 0)); 146 Assert.assertNotEquals(CodonVariation.createModification(0, 0), 147 CodonVariation.createModification(0, 1)); 148 149 Assert.assertEquals(CodonVariation.createDeletion(1).hashCode(), CodonVariation.createDeletion(1).hashCode()); 150 Assert.assertNotEquals(CodonVariation.createDeletion(0).hashCode(), CodonVariation.createDeletion(1).hashCode()); 151 Assert.assertEquals(CodonVariation.createFrameshift(1).hashCode(), CodonVariation.createFrameshift(1).hashCode()); 152 Assert.assertNotEquals(CodonVariation.createFrameshift(0).hashCode(), CodonVariation.createFrameshift(1).hashCode()); 153 Assert.assertNotEquals(CodonVariation.createFrameshift(0).hashCode(), CodonVariation.createDeletion(0).hashCode()); 154 Assert.assertEquals(CodonVariation.createInsertion(1, 0).hashCode(), 155 CodonVariation.createInsertion(1, 0).hashCode()); 156 Assert.assertNotEquals(CodonVariation.createInsertion(0, 0).hashCode(), 157 CodonVariation.createInsertion(1, 0).hashCode()); 158 Assert.assertNotEquals(CodonVariation.createInsertion(0, 0).hashCode(), 159 CodonVariation.createInsertion(0, 1).hashCode()); 160 Assert.assertEquals(CodonVariation.createModification(1, 0).hashCode(), 161 CodonVariation.createModification(1, 0).hashCode()); 162 Assert.assertNotEquals(CodonVariation.createModification(0, 0).hashCode(), 163 CodonVariation.createModification(1, 0).hashCode()); 164 Assert.assertNotEquals(CodonVariation.createModification(0, 0).hashCode(), 165 CodonVariation.createModification(0, 1).hashCode()); 166 } 167 168 @Test testEncodingModifications()169 public void testEncodingModifications() { 170 // no SNVs implies no codon variations 171 Assert.assertTrue(localCodonTracker.encodeSNVsAsCodons(Collections.emptyList()).isEmpty()); 172 173 // changes outside the ORF shouldn't produce codon variations 174 Assert.assertTrue(localCodonTracker 175 .encodeSNVsAsCodons(Collections.singletonList(new SNV(1, CALL_C, CALL_G, QUAL_30))) 176 .isEmpty()); 177 Assert.assertTrue(localCodonTracker 178 .encodeSNVsAsCodons(Collections.singletonList(new SNV(6, CALL_G, CALL_A, QUAL_30))) 179 .isEmpty()); 180 Assert.assertTrue(localCodonTracker 181 .encodeSNVsAsCodons(Collections.singletonList(new SNV(12, CALL_T, CALL_C, QUAL_30))) 182 .isEmpty()); 183 184 // changes to a single codon should produce a single-codon variations 185 Assert.assertEquals( 186 localCodonTracker.encodeSNVsAsCodons(Collections.singletonList(new SNV(2, CALL_A, CALL_C, QUAL_30))), 187 Collections.singletonList(CodonVariation.createModification(0, 30))); 188 Assert.assertEquals( 189 localCodonTracker.encodeSNVsAsCodons(Collections.singletonList(new SNV(5, CALL_C, CALL_G, QUAL_30))), 190 Collections.singletonList(CodonVariation.createModification(1, 45))); 191 Assert.assertEquals( 192 localCodonTracker.encodeSNVsAsCodons(Collections.singletonList(new SNV(7, CALL_T, CALL_G, QUAL_30))), 193 Collections.singletonList(CodonVariation.createModification(1, 25))); 194 Assert.assertEquals( 195 localCodonTracker.encodeSNVsAsCodons(Collections.singletonList(new SNV(8, CALL_C, CALL_A, QUAL_30))), 196 Collections.singletonList(CodonVariation.createModification(1, 28))); 197 Assert.assertEquals( 198 localCodonTracker.encodeSNVsAsCodons(Collections.singletonList(new SNV(11, CALL_G, CALL_A, QUAL_30))), 199 Collections.singletonList(CodonVariation.createModification(2, 48))); 200 Assert.assertEquals( 201 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 202 new SNV(5, CALL_C, CALL_G, QUAL_30), 203 new SNV(7, CALL_T, CALL_G, QUAL_30), 204 new SNV(8, CALL_C, CALL_A, QUAL_30))), 205 Collections.singletonList(CodonVariation.createModification(1, 40))); 206 207 // even if the change produces a nonsense codon 208 Assert.assertEquals( 209 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 210 new SNV(5, CALL_C, CALL_T, QUAL_30), 211 new SNV(7, CALL_T, CALL_A, QUAL_30), 212 new SNV(8, CALL_C, CALL_A, QUAL_30))), 213 Collections.singletonList(CodonVariation.createModification(1, 48))); 214 } 215 216 @Test testEncodingDeletions()217 public void testEncodingDeletions() { 218 Assert.assertEquals( 219 localCodonTracker.encodeSNVsAsCodons(Collections.singletonList(new SNV(2, CALL_A, NO_CALL, QUAL_30))), 220 Arrays.asList( 221 CodonVariation.createFrameshift(0), 222 CodonVariation.createModification(0, 57), 223 CodonVariation.createModification(1, 55), 224 CodonVariation.createModification(2, 11))); 225 Assert.assertEquals( 226 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 227 new SNV(10, CALL_A, NO_CALL, QUAL_30), 228 new SNV(12, CALL_T, NO_CALL, QUAL_30))), 229 Arrays.asList( 230 CodonVariation.createFrameshift(2), 231 CodonVariation.createModification(2, 56))); 232 Assert.assertEquals( 233 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 234 new SNV(5, CALL_C, NO_CALL, QUAL_30), 235 new SNV(7, CALL_T, NO_CALL, QUAL_30), 236 new SNV(8, CALL_C, NO_CALL, QUAL_30))), 237 Collections.singletonList(CodonVariation.createDeletion(1))); 238 Assert.assertEquals( 239 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 240 new SNV(3, CALL_T, NO_CALL, QUAL_30), 241 new SNV(5, CALL_C, NO_CALL, QUAL_30), 242 new SNV(8, CALL_C, NO_CALL, QUAL_30))), 243 Arrays.asList( 244 CodonVariation.createModification(0, 11), 245 CodonVariation.createDeletion(1))); 246 247 } 248 249 @Test testEncodingInsertions()250 public void testEncodingInsertions() { 251 Assert.assertEquals( 252 localCodonTracker.encodeSNVsAsCodons(Collections.singletonList( 253 new SNV(5, NO_CALL, CALL_T, QUAL_30))), 254 Arrays.asList( 255 CodonVariation.createFrameshift(1), 256 CodonVariation.createModification(1, 55), 257 CodonVariation.createModification(2, 28))); 258 Assert.assertEquals( 259 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 260 new SNV(2, NO_CALL, CALL_T, QUAL_30), 261 new SNV(2, NO_CALL, CALL_T, QUAL_30), 262 new SNV(2, NO_CALL, CALL_T, QUAL_30))), 263 Collections.emptyList()); 264 Assert.assertEquals( 265 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 266 new SNV(5, NO_CALL, CALL_T, QUAL_30), 267 new SNV(5, NO_CALL, CALL_T, QUAL_30), 268 new SNV(5, NO_CALL, CALL_T, QUAL_30))), 269 Collections.singletonList( 270 CodonVariation.createInsertion(1, 63))); 271 Assert.assertEquals( 272 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 273 new SNV(4, NO_CALL, CALL_G, QUAL_30), 274 new SNV(4, NO_CALL, CALL_C, QUAL_30), 275 new SNV(4, NO_CALL, CALL_T, QUAL_30), 276 new SNV(4, NO_CALL, CALL_G, QUAL_30), 277 new SNV(4, NO_CALL, CALL_C, QUAL_30), 278 new SNV(4, NO_CALL, CALL_T, QUAL_30))), 279 Arrays.asList( 280 CodonVariation.createInsertion(1, 30), 281 CodonVariation.createInsertion(1, 30))); 282 } 283 284 @Test testFrameRecoveringIndels()285 public void testFrameRecoveringIndels() { 286 Assert.assertEquals( 287 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 288 new SNV(3, CALL_T, NO_CALL, QUAL_30), 289 new SNV(7, NO_CALL, CALL_A, QUAL_30))), 290 Arrays.asList( 291 CodonVariation.createModification(0, 9), 292 CodonVariation.createModification(1, 13))); 293 Assert.assertEquals( 294 localCodonTracker.encodeSNVsAsCodons(Arrays.asList( 295 new SNV(3, NO_CALL, CALL_T, QUAL_30), 296 new SNV(7, CALL_T, NO_CALL, QUAL_30))), 297 Arrays.asList( 298 CodonVariation.createModification(0, 15), 299 CodonVariation.createModification(1, 37))); 300 } 301 302 @Test testWildTypeCodonCounts()303 public void testWildTypeCodonCounts() { 304 final CodonTracker codonTracker = new CodonTracker(orfCoords, refSeq, logger); 305 codonTracker.reportWildCodonCounts(new Interval(0, 17)); 306 codonTracker.reportWildCodonCounts(new Interval(0, 17)); 307 final int[] wildTypeCodonValues = codonTracker.getRefCodonValues(); 308 final long[][] codonCounts = codonTracker.getCodonCounts(); 309 for ( int codonId = 0; codonId != wildTypeCodonValues.length; ++codonId ) { 310 final long[] row = codonCounts[codonId]; 311 final int wtValue = wildTypeCodonValues[codonId]; 312 for ( int codonValue = 0; codonValue != 64; ++codonValue ) { 313 Assert.assertEquals(row[codonValue], codonValue==wtValue ? 2 : 0); 314 } 315 } 316 codonTracker.reportWildCodonCounts(new Interval(6, 12)); 317 Assert.assertEquals(codonCounts[1][wildTypeCodonValues[1]], 2); 318 Assert.assertEquals(codonCounts[2][wildTypeCodonValues[2]], 3); 319 } 320 321 @Test testVariantCodonCounts()322 public void testVariantCodonCounts() { 323 final CodonTracker codonTracker = new CodonTracker(orfCoords, refSeq, null); 324 codonTracker.reportVariantCodonCounts(new Interval(0, 17), Arrays.asList( 325 CodonVariation.createModification(0, 0), 326 CodonVariation.createModification(1, 1), 327 CodonVariation.createDeletion(1), 328 CodonVariation.createInsertion(2, 2), 329 CodonVariation.createFrameshift(2), 330 CodonVariation.createModification(2, 6))); 331 final long[][] codonCounts = codonTracker.getCodonCounts(); 332 Assert.assertEquals(codonCounts[0][0], 1); 333 Assert.assertEquals(codonCounts[1][1], 1); 334 Assert.assertEquals(codonCounts[1][CodonTracker.FRAME_PRESERVING_INDEL_INDEX], 1); 335 Assert.assertEquals(codonCounts[2][6], 1); 336 Assert.assertEquals(codonCounts[2][CodonTracker.FRAME_PRESERVING_INDEL_INDEX], 1); 337 Assert.assertEquals(codonCounts[2][CodonTracker.FRAME_SHIFTING_INDEL_INDEX], 1); 338 Assert.assertEquals(Arrays.stream(codonCounts).mapToLong(row -> Arrays.stream(row).sum()).sum(), 6L); 339 } 340 341 @Test testWildTypeCodonValuesAndExons()342 public void testWildTypeCodonValuesAndExons() { 343 final List<Interval> exons = CodonTracker.getExons(orfCoords, refSeq.length); 344 Assert.assertEquals(exons, Arrays.asList(new Interval(2, 6), new Interval(7, 12))); 345 final int[] expectedCodonValues = {14, 29, 50}; 346 Assert.assertTrue(Arrays.equals(CodonTracker.parseReferenceIntoCodons(refSeq, exons, null), expectedCodonValues)); 347 } 348 349 @Test testFindFrameShift()350 public void testFindFrameShift() { 351 Assert.assertEquals( 352 localCodonTracker.findFrameShift(Collections.singletonList(new SNV(1, CALL_A, NO_CALL, QUAL_30))), 353 NO_FRAME_SHIFT_CODON); 354 Assert.assertEquals( 355 localCodonTracker.findFrameShift(Collections.singletonList(new SNV(2, CALL_A, NO_CALL, QUAL_30))), 356 0); 357 Assert.assertEquals( 358 localCodonTracker.findFrameShift(Collections.singletonList(new SNV(4, NO_CALL, CALL_C, QUAL_30))), 359 0); 360 Assert.assertEquals( 361 localCodonTracker.findFrameShift(Collections.singletonList(new SNV(6, CALL_G, NO_CALL, QUAL_30))), 362 NO_FRAME_SHIFT_CODON); 363 Assert.assertEquals( 364 localCodonTracker.findFrameShift(Collections.singletonList(new SNV(12, NO_CALL, CALL_C, QUAL_30))), 365 NO_FRAME_SHIFT_CODON); 366 Assert.assertEquals( 367 localCodonTracker.findFrameShift(Arrays.asList( 368 new SNV(5, CALL_C, NO_CALL, QUAL_30), 369 new SNV(6, CALL_G, NO_CALL, QUAL_30), 370 new SNV(7, CALL_T, NO_CALL, QUAL_30), 371 new SNV(8, CALL_C, NO_CALL, QUAL_30))), 372 NO_FRAME_SHIFT_CODON); 373 } 374 375 @Test testIsStop()376 public void testIsStop() { 377 Assert.assertFalse(CodonTracker.isStop(-1)); 378 Assert.assertFalse(CodonTracker.isStop(47)); 379 Assert.assertTrue(CodonTracker.isStop(48)); 380 Assert.assertFalse(CodonTracker.isStop(49)); 381 Assert.assertTrue(CodonTracker.isStop(50)); 382 Assert.assertTrue(CodonTracker.isStop(56)); 383 Assert.assertFalse(CodonTracker.isStop(57)); 384 Assert.assertFalse(CodonTracker.isStop(99)); 385 } 386 387 @Test testIsExonic()388 public void testIsExonic() { 389 Assert.assertFalse(localCodonTracker.isExonic(-1)); 390 Assert.assertFalse(localCodonTracker.isExonic(0)); 391 Assert.assertFalse(localCodonTracker.isExonic(1)); 392 Assert.assertTrue(localCodonTracker.isExonic(2)); 393 Assert.assertTrue(localCodonTracker.isExonic(3)); 394 Assert.assertTrue(localCodonTracker.isExonic(4)); 395 Assert.assertTrue(localCodonTracker.isExonic(5)); 396 Assert.assertFalse(localCodonTracker.isExonic(6)); 397 Assert.assertTrue(localCodonTracker.isExonic(7)); 398 Assert.assertTrue(localCodonTracker.isExonic(8)); 399 Assert.assertTrue(localCodonTracker.isExonic(9)); 400 Assert.assertTrue(localCodonTracker.isExonic(10)); 401 Assert.assertTrue(localCodonTracker.isExonic(11)); 402 Assert.assertFalse(localCodonTracker.isExonic(12)); 403 Assert.assertFalse(localCodonTracker.isExonic(99)); 404 } 405 406 @Test testExonicBaseCount()407 public void testExonicBaseCount() { 408 Assert.assertEquals(localCodonTracker.exonicBaseIndex(-1), 0); 409 Assert.assertEquals(localCodonTracker.exonicBaseIndex(0), 0); 410 Assert.assertEquals(localCodonTracker.exonicBaseIndex(1), 0); 411 Assert.assertEquals(localCodonTracker.exonicBaseIndex(2), 0); 412 Assert.assertEquals(localCodonTracker.exonicBaseIndex(3), 1); 413 Assert.assertEquals(localCodonTracker.exonicBaseIndex(4), 2); 414 Assert.assertEquals(localCodonTracker.exonicBaseIndex(5), 3); 415 Assert.assertEquals(localCodonTracker.exonicBaseIndex(6), 4); 416 Assert.assertEquals(localCodonTracker.exonicBaseIndex(7), 4); 417 Assert.assertEquals(localCodonTracker.exonicBaseIndex(8), 5); 418 Assert.assertEquals(localCodonTracker.exonicBaseIndex(9), 6); 419 Assert.assertEquals(localCodonTracker.exonicBaseIndex(10), 7); 420 Assert.assertEquals(localCodonTracker.exonicBaseIndex(11), 8); 421 Assert.assertEquals(localCodonTracker.exonicBaseIndex(12), 9); 422 Assert.assertEquals(localCodonTracker.exonicBaseIndex(13), 9); 423 Assert.assertEquals(localCodonTracker.exonicBaseIndex(99), 9); 424 } 425 426 @Test testReadReportFlanks()427 public void testReadReportFlanks() { 428 final List<SNV> snvList = Collections.singletonList(new SNV(8, CALL_C, CALL_A, QUAL_30)); 429 final ReadReport readReport1 = 430 new ReadReport(Collections.singletonList(new Interval(2,15)), snvList); 431 Assert.assertTrue(readReport1.hasCleanLeftFlank(6)); 432 Assert.assertFalse(readReport1.hasCleanLeftFlank(7)); 433 Assert.assertTrue(readReport1.hasCleanRightFlank(6, refSeq.length)); 434 Assert.assertFalse(readReport1.hasCleanRightFlank(7, refSeq.length)); 435 436 // unpenalized for going off the end of the reference 437 final ReadReport readReport2 = 438 new ReadReport(Collections.singletonList(new Interval(0,17)), snvList); 439 Assert.assertTrue(readReport2.hasCleanLeftFlank(9)); 440 Assert.assertTrue(readReport2.hasCleanRightFlank(9, refSeq.length)); 441 } 442 443 @Test testCombiningCoverage()444 public void testCombiningCoverage() { 445 final ReadReport report1 = new ReadReport(Arrays.asList( 446 new Interval(0, 9), new Interval(20, 40), new Interval(60,70), new Interval(100, 120)), 447 Collections.emptyList()); 448 final ReadReport report2 = new ReadReport(Arrays.asList( 449 new Interval(17, 21), new Interval(22, 27), new Interval(38, 50), new Interval(58, 60), new Interval(70, 72)), 450 Collections.emptyList()); 451 Assert.assertEquals(new ReadReport(report1, report2).getRefCoverage(), 452 Arrays.asList(new Interval(0, 9), new Interval(17, 50), new Interval(58, 72), new Interval(100, 120))); 453 } 454 455 @Test testCombiningSNVLists()456 public void testCombiningSNVLists() { 457 final List<SNV> list1 = Arrays.asList( 458 new SNV(10, CALL_A, CALL_C, QUAL_30), 459 new SNV(20, CALL_C, CALL_A, QUAL_30), 460 new SNV(30, CALL_C, CALL_G, QUAL_30)); 461 final List<SNV> list2 = Arrays.asList( 462 new SNV(35, CALL_T, CALL_C, QUAL_30), 463 new SNV(45, CALL_G, CALL_A, QUAL_30), 464 new SNV(55, CALL_C, CALL_A, QUAL_30)); 465 final ReadReport report1 = new ReadReport(Collections.singletonList(new Interval(0, 32)), list1); 466 final ReadReport report2 = new ReadReport(Collections.singletonList(new Interval(33, 60)), list2); 467 final List<SNV> combinedList = new ArrayList<>(list1); 468 combinedList.addAll(list2); 469 Assert.assertEquals(new ReadReport(report1, report2).getVariations(), combinedList); 470 471 // region of overlap has no conflicting SNVs 472 final ReadReport report3 = new ReadReport(Collections.singletonList(new Interval(0, 35)), list1); 473 final ReadReport report4 = new ReadReport(Collections.singletonList(new Interval(33, 60)), list2); 474 Assert.assertEquals(new ReadReport(report3, report4).getVariations(), combinedList); 475 476 // region of overlap has conflicting SNV: SNV at 35 is missing from report5 477 final ReadReport report5 = new ReadReport(Collections.singletonList(new Interval(0, 36)), list1); 478 final ReadReport report6 = new ReadReport(Collections.singletonList(new Interval(33, 60)), list2); 479 Assert.assertNull(new ReadReport(report5, report6).getVariations()); 480 481 // repair flaw above 482 final List<SNV> list1Plus = new ArrayList<>(list1); 483 list1Plus.add(new SNV(35, CALL_T, CALL_C, QUAL_10)); 484 final ReadReport report7 = new ReadReport(Collections.singletonList(new Interval(0, 36)), list1Plus); 485 Assert.assertEquals(new ReadReport(report7, report6).getVariations(), combinedList); 486 487 // now mess it up again by making the SNVs unequal 488 list1Plus.set(3, new SNV(35, CALL_T, CALL_A, QUAL_30)); 489 Assert.assertNull(new ReadReport(report7, report6).getVariations()); 490 } 491 492 @Test testPairedApplication()493 public void testPairedApplication() { 494 final byte[] longRefSeq = "TTTTTTTTTTAAAAAAAAAACCCCCCCCCCCCCCCTTTTTTTTTTGGGGGGGGGGCCCCCCCCCC".getBytes(); 495 reference = new Reference(longRefSeq); 496 codonTracker = new CodonTracker("5-25", longRefSeq, logger); 497 498 final List<SNV> list1 = Arrays.asList( 499 new SNV(10, CALL_A, CALL_C, QUAL_30), 500 new SNV(20, CALL_C, CALL_A, QUAL_30), 501 new SNV(30, CALL_C, CALL_G, QUAL_30)); 502 final List<SNV> list2 = Arrays.asList( 503 new SNV(35, CALL_T, CALL_C, QUAL_30), 504 new SNV(45, CALL_G, CALL_A, QUAL_30), 505 new SNV(55, CALL_C, CALL_A, QUAL_30)); 506 507 final SAMFileHeader header = ArtificialReadUtils.createArtificialSamHeader(); 508 final List<GATKRead> reads = 509 ArtificialReadUtils.createPair(header, "blahBlah", 150, 1, 151, true, false); 510 final GATKRead read1 = reads.get(0); 511 final GATKRead read2 = reads.get(1); 512 final ReadReport report1 = new ReadReport(Collections.singletonList(new Interval(0, 32)), list1); 513 final ReadReport report2 = new ReadReport(Collections.singletonList(new Interval(33, 60)), list2); 514 updateCountsForPair(read1, report1, read2, report2); 515 516 // shouldn't be applied -- fails flanking bases test 517 Assert.assertEquals(reference.countSpanners(0, 32), 0); 518 Assert.assertEquals(reference.countSpanners(32, 33), 0); 519 Assert.assertEquals(reference.countSpanners(33, 60), 0); 520 521 // only read1 should be applied 522 minFlankingLength = 1; 523 updateCountsForPair(read1, report1, read2, report2); 524 Assert.assertEquals(reference.countSpanners(0, 32), 1); 525 Assert.assertEquals(reference.countSpanners(32, 33), 0); 526 Assert.assertEquals(reference.countSpanners(33, 60), 0); 527 528 // should be applied as one 529 final ReadReport report3 = new ReadReport(Collections.singletonList(new Interval(0, 35)), list1); 530 final ReadReport report4 = new ReadReport(Collections.singletonList(new Interval(33, 60)), list2); 531 updateCountsForPair(read1, report3, read2, report4); 532 Assert.assertEquals(reference.countSpanners(0, 32), 2); 533 Assert.assertEquals(reference.countSpanners(32, 33), 1); 534 Assert.assertEquals(reference.countSpanners(33, 60), 1); 535 } 536 537 @Test testCalculateTrim()538 public void testCalculateTrim() { 539 final byte BAD_Q = (byte)(minQ - 1); 540 final byte GOOD_Q = (byte)minQ; 541 final byte[] quals = new byte[100]; 542 Arrays.fill(quals, BAD_Q); 543 Assert.assertEquals(calculateQualityTrim(quals).size(), 0); 544 Arrays.fill(quals, GOOD_Q); 545 Assert.assertEquals(calculateQualityTrim(quals), new Interval(0, 100)); 546 quals[minLength] = BAD_Q; 547 Assert.assertEquals(calculateQualityTrim(quals), new Interval(0, 100)); 548 quals[minLength - 1] = BAD_Q; 549 Assert.assertEquals(calculateQualityTrim(quals), new Interval(minLength + 1, 100)); 550 quals[quals.length - minLength] = BAD_Q; 551 Assert.assertEquals(calculateQualityTrim(quals), new Interval(minLength + 1, quals.length - minLength)); 552 Arrays.fill(quals, GOOD_Q); 553 for ( int idx = minLength - 1; idx < quals.length; idx += minLength ) { 554 quals[idx] = BAD_Q; 555 } 556 Assert.assertEquals(calculateQualityTrim(quals).size(), 0); 557 } 558 559 @Test testGetReadReport()560 public void testGetReadReport() { 561 final SAMFileHeader header = 562 ArtificialReadUtils.createArtificialSamHeader(1, 0, 17); 563 final byte[] bases = Arrays.copyOf(refSeq, refSeq.length); 564 final byte[] quals = new byte[17]; 565 Arrays.fill(quals, QUAL_30); 566 final GATKRead read = ArtificialReadUtils.createArtificialRead(header, "read1", 0, 1, 567 bases, quals, "17M"); 568 read.setMappingQuality(0); 569 reference = new Reference(refSeq); 570 Assert.assertEquals(getReadReport(read).getRefCoverage(), Collections.emptyList()); 571 572 read.setMappingQuality(60); 573 final ReadReport readReport = getReadReport(read); 574 Assert.assertEquals(readReport.getRefCoverage(), Collections.singletonList(new Interval(0, 17))); 575 Assert.assertEquals(readReport.getVariations().size(), 0); 576 read.getBasesNoCopy()[3] = CALL_A; 577 final ReadReport readReport2 = getReadReport(read); 578 Assert.assertEquals(readReport2.getVariations(), 579 Collections.singletonList(new SNV(3, CALL_T, CALL_A, QUAL_30))); 580 } 581 582 @Test testFindLargeDeletions()583 public void testFindLargeDeletions() { 584 AnalyzeSaturationMutagenesis.minAltLength = 2; 585 AnalyzeSaturationMutagenesis.findLargeDels = true; 586 final SAMFileHeader header = 587 ArtificialReadUtils.createArtificialSamHeader(1, 0, 17); 588 final byte[] bases = new byte[10]; 589 System.arraycopy(refSeq, 0, bases, 0, 5); 590 System.arraycopy(refSeq, 12, bases, 5, 5); 591 final byte[] quals = new byte[10]; 592 Arrays.fill(quals, QUAL_30); 593 594 // OK: primary preceeds supplementary 595 final GATKRead read1 = ArtificialReadUtils.createArtificialRead(header, "read1", 0, 1, 596 bases, quals, "5M5S"); 597 read1.setAttribute("SA", "0,13,+,5S5M,60,0;"); 598 Assert.assertEquals(AnalyzeSaturationMutagenesis.ReadReport.findLargeDeletions(read1).toString(), "5M7D5M"); 599 600 // OK: supplementary preceeds primary 601 final GATKRead read2 = ArtificialReadUtils.createArtificialRead(header, "read1", 0, 13, 602 bases, quals, "5S5M"); 603 read2.setAttribute("SA", "0,1,+,5M5S,60,0;"); 604 Assert.assertEquals(AnalyzeSaturationMutagenesis.ReadReport.findLargeDeletions(read2).toString(), "5M7D5M"); 605 606 // too much overlap on read 607 final GATKRead read3 = ArtificialReadUtils.createArtificialRead(header, "read1", 0, 1, 608 bases, quals, "6M4S"); 609 read3.setAttribute("SA", "0,11,+,3S7M,60,0;"); 610 Assert.assertEquals(AnalyzeSaturationMutagenesis.ReadReport.findLargeDeletions(read3).toString(), "6M4S"); 611 612 // too far apart on read 613 final GATKRead read4 = ArtificialReadUtils.createArtificialRead(header, "read1", 0, 1, 614 bases, quals, "3M7S"); 615 read4.setAttribute("SA", "0,14,+,6S4M,60,0;"); 616 Assert.assertEquals(AnalyzeSaturationMutagenesis.ReadReport.findLargeDeletions(read4).toString(), "3M7S"); 617 618 // wrong strand 619 final GATKRead read5 = ArtificialReadUtils.createArtificialRead(header, "read1", 0, 1, 620 bases, quals, "5M5S"); 621 read5.setAttribute("SA", "0,13,-,5S5M,60,0;"); 622 Assert.assertEquals(AnalyzeSaturationMutagenesis.ReadReport.findLargeDeletions(read5).toString(), "5M5S"); 623 624 // wrong order 625 final GATKRead read6 = ArtificialReadUtils.createArtificialRead(header, "read1", 0, 13, 626 bases, quals, "5M5S"); 627 read6.setAttribute("SA", "0,1,+,5S5M,60,0;"); 628 Assert.assertEquals(AnalyzeSaturationMutagenesis.ReadReport.findLargeDeletions(read6).toString(), "5M5S"); 629 630 // OK: 1-base overlap on read 631 final GATKRead read7 = ArtificialReadUtils.createArtificialRead(header, "read1", 0, 1, 632 bases, quals, "6M4S"); 633 read7.setAttribute("SA", "0,13,+,5S5M,60,0;"); 634 Assert.assertEquals(AnalyzeSaturationMutagenesis.ReadReport.findLargeDeletions(read7).toString(), "6M7D4M"); 635 636 // OK: 1-base separation on read 637 final GATKRead read8 = ArtificialReadUtils.createArtificialRead(header, "read1", 0, 1, 638 bases, quals, "4M6S"); 639 read8.setAttribute("SA", "0,13,+,5S5M,60,0;"); 640 Assert.assertEquals(AnalyzeSaturationMutagenesis.ReadReport.findLargeDeletions(read8).toString(), "4M7D6M"); 641 } 642 } 643