@Override protected void finish() { final MetricsFile<PreAdapterSummaryMetrics, Integer> preAdapterSummaryMetricsFile = getMetricsFile(); final MetricsFile<PreAdapterDetailMetrics, Integer> preAdapterDetailMetricsFile = getMetricsFile(); final MetricsFile<BaitBiasSummaryMetrics, Integer> baitBiasSummaryMetricsFile = getMetricsFile(); final MetricsFile<BaitBiasDetailMetrics, Integer> baitBiasDetailMetricsFile = getMetricsFile(); for (final ArtifactCounter counter : artifactCounters.values()) { // build metrics counter.finish(); // write metrics preAdapterSummaryMetricsFile.addAllMetrics(counter.getPreAdapterSummaryMetrics()); baitBiasSummaryMetricsFile.addAllMetrics(counter.getBaitBiasSummaryMetrics()); for (final PreAdapterDetailMetrics preAdapterDetailMetrics : counter.getPreAdapterDetailMetrics()) { if (CONTEXTS_TO_PRINT.isEmpty() || CONTEXTS_TO_PRINT.contains(preAdapterDetailMetrics.CONTEXT)) { preAdapterDetailMetricsFile.addMetric(preAdapterDetailMetrics); } } for (final BaitBiasDetailMetrics baitBiasDetailMetrics : counter.getBaitBiasDetailMetrics()) { if (CONTEXTS_TO_PRINT.isEmpty() || CONTEXTS_TO_PRINT.contains(baitBiasDetailMetrics.CONTEXT)) { baitBiasDetailMetricsFile.addMetric(baitBiasDetailMetrics); } } } preAdapterDetailMetricsFile.write(preAdapterDetailsOut); preAdapterSummaryMetricsFile.write(preAdapterSummaryOut); baitBiasDetailMetricsFile.write(baitBiasDetailsOut); baitBiasSummaryMetricsFile.write(baitBiasSummaryOut); }
@Override protected void acceptRead(final SAMRecord rec, final ReferenceSequence ref) { // see if the whole read should be skipped if (recordFilter.filterOut(rec)) return; // check read group + library final String library = (rec.getReadGroup() == null) ? UNKNOWN_LIBRARY : getOrElse(rec.getReadGroup().getLibrary(), UNKNOWN_LIBRARY); if (!libraries.contains(library)) { // should never happen if SAM is valid throw new PicardException("Record contains library that is missing from header: " + library); } // set up some constants that don't change in the loop below final int contextFullLength = 2 * CONTEXT_SIZE + 1; final ArtifactCounter counter = artifactCounters.get(library); final byte[] readBases = rec.getReadBases(); final byte[] readQuals; if (USE_OQ) { final byte[] tmp = rec.getOriginalBaseQualities(); readQuals = tmp == null ? rec.getBaseQualities() : tmp; } else { readQuals = rec.getBaseQualities(); } // iterate over aligned positions for (final AlignmentBlock block : rec.getAlignmentBlocks()) { for (int offset = 0; offset < block.getLength(); offset++) { // remember, these are 1-based! final int readPos = block.getReadStart() + offset; final int refPos = block.getReferenceStart() + offset; // skip low BQ sites final byte qual = readQuals[readPos - 1]; if (qual < MINIMUM_QUALITY_SCORE) continue; // skip N bases in read final char readBase = Character.toUpperCase((char) readBases[readPos - 1]); if (readBase == 'N') continue; /** * Skip regions outside of intervals. * * <p>NB: IntervalListReferenceSequenceMask.get() has side-effects which assume that * successive ReferenceSequence's passed to this method will be in-order (e.g. it will break * if you call acceptRead() with chr1, then chr2, then chr1 again). So this only works if * the underlying iteration is coordinate-sorted. */ if (intervalMask != null && !intervalMask.get(ref.getContigIndex(), refPos)) continue; // skip dbSNP sites if (dbSnpMask != null && dbSnpMask.isDbSnpSite(ref.getName(), refPos)) continue; // skip the ends of the reference final int contextStartIndex = refPos - CONTEXT_SIZE - 1; if (contextStartIndex < 0 || contextStartIndex + contextFullLength > ref.length()) continue; // skip contexts with N bases final String context = getRefContext(ref, contextStartIndex, contextFullLength); if (context.contains("N")) continue; // count the base! counter.countRecord(context, readBase, rec); } } }