/**
* Copyright Copyright 2015 Simon Andrews
*
* This file is part of BamQC.
*
* BamQC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* BamQC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with BamQC; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Changelog:
* - Piero Dalle Pezze: Class creation.
*/
package uk.ac.babraham.BamQC.Modules;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import javax.swing.JPanel;
import javax.xml.stream.XMLStreamException;
import org.apache.log4j.Logger;
import net.sf.samtools.SAMRecord;
import uk.ac.babraham.BamQC.DataTypes.Genome.AnnotationSet;
import uk.ac.babraham.BamQC.Report.HTMLReportArchive;
import uk.ac.babraham.BamQC.Sequence.SequenceFile;
import uk.ac.babraham.BamQC.Utilities.CigarMD.CigarMD;
import uk.ac.babraham.BamQC.Utilities.CigarMD.CigarMDElement;
import uk.ac.babraham.BamQC.Utilities.CigarMD.CigarMDGenerator;
import uk.ac.babraham.BamQC.Utilities.CigarMD.CigarMDOperator;
/**
* This module is used for computing the statistics for all the variant calls.
* @author Piero Dalle Pezze
*/
public class VariantCallDetection extends AbstractQCModule {
// logger
private static Logger log = Logger.getLogger(VariantCallDetection.class);
// data fields for statistics
// first or second indicate whether the read is the first or second segment. If the read is not paired,
// it is treated as a first.
private HashMap<String, Long> firstSNPs = new HashMap<String, Long>();
private HashMap<String, Long> secondSNPs = new HashMap<String, Long>();
// To reduce computational time let's not collect data regarding indel type.
//private HashMap<String, Long> insertions = new HashMap<String, Long>();
//private HashMap<String, Long> deletions = new HashMap<String, Long>();
private boolean totalsComputed = false;
private long totalMutations = 0;
private long totalInsertions = 0;
private long totalDeletions = 0;
private long totalMatches = 0;
private long totalSkippedRegions = 0;
private long totalSoftClips = 0;
private long totalHardClips = 0;
private long totalPaddings = 0;
private long total = 0;
private long readUnknownBases = 0;
private long referenceUnknownBases = 0;
private long skippedReads = 0;
private long readWithoutMDString = 0;
private long readWithoutCigarString = 0;
private long inconsistentCigarMDStrings = 0;
private long totalReads = 0;
private long splicedReads = 0;
// These arrays are used to store the density of SNP and Indels at each read position.
private final static int VC_POSITION_ARRAY_SIZE = 150;
private long[] firstSNPPos = new long[VC_POSITION_ARRAY_SIZE];
private long[] firstInsertionPos = new long[VC_POSITION_ARRAY_SIZE];
private long[] firstDeletionPos = new long[VC_POSITION_ARRAY_SIZE];
private long[] secondSNPPos = new long[VC_POSITION_ARRAY_SIZE];
private long[] secondInsertionPos = new long[VC_POSITION_ARRAY_SIZE];
private long[] secondDeletionPos = new long[VC_POSITION_ARRAY_SIZE];
private long[] matchPos = new long[VC_POSITION_ARRAY_SIZE];
private long[] totalPos = new long[VC_POSITION_ARRAY_SIZE];
// currentPosition is the current position used to record changes in the arrays above. This class processes
// the CigarMD string, not the read, which is instead processed by class CigarMDGenerator.
private int currentPosition = 0;
// This array reports how many reads are included for computing the statistics for each position. It is used for filtering
// statistics for positions having less then a defined percentage of reads.
// key: the read lengths, value: the number of reads with that length.
private HashMap<Integer, Long> contributingReadsPerPos = new HashMap<Integer, Long>();
private int readLength = 0;
// temporary variable created here to limit variable declarations.
// these are initialised inside the method processSequence()
private boolean isReadSpliced = false;
private int cigarMDElementsSize = 0;
// Used for computing the statistics
private CigarMDGenerator cigarMDGenerator = new CigarMDGenerator();
private CigarMD cigarMD = new CigarMD();
private CigarMDElement currentCigarMDElement = null;
private boolean existPairedReads = false;
// Constructors
/**
* Default constructor
*/
public VariantCallDetection() {
firstSNPs.put("AC", 0L);
firstSNPs.put("AG", 0L);
firstSNPs.put("AT", 0L);
firstSNPs.put("CA", 0L);
firstSNPs.put("CG", 0L);
firstSNPs.put("CT", 0L);
firstSNPs.put("GA", 0L);
firstSNPs.put("GC", 0L);
firstSNPs.put("GT", 0L);
firstSNPs.put("TA", 0L);
firstSNPs.put("TC", 0L);
firstSNPs.put("TG", 0L);
secondSNPs.put("AC", 0L);
secondSNPs.put("AG", 0L);
secondSNPs.put("AT", 0L);
secondSNPs.put("CA", 0L);
secondSNPs.put("CG", 0L);
secondSNPs.put("CT", 0L);
secondSNPs.put("GA", 0L);
secondSNPs.put("GC", 0L);
secondSNPs.put("GT", 0L);
secondSNPs.put("TA", 0L);
secondSNPs.put("TC", 0L);
secondSNPs.put("TG", 0L);
// To reduce computational time let's not collect data regarding indel type.
// insertions.put("A", 0L);
// insertions.put("C", 0L);
// insertions.put("G", 0L);
// insertions.put("T", 0L);
// insertions.put("N", 0L);
//
// deletions.put("A", 0L);
// deletions.put("C", 0L);
// deletions.put("G", 0L);
// deletions.put("T", 0L);
// deletions.put("N", 0L);
}
/**
* Compute the totals. For improving efficiency, this method is not invoked
* inside void processSequence(SAMRecord read), but must be invoked
* later.
*/
public void computeTotals() {
if(totalsComputed) return;
// if(totalMutations != 0 || totalInsertions != 0 || totalDeletions != 0) {
// return;
// }
// // NOTE: nInsertions and nDeletions are not counted in the totals.
totalMutations = 0;
totalInsertions = 0;
totalDeletions = 0;
for(int i=0; i< totalPos.length; i++) {
totalMutations = totalMutations + firstSNPPos[i] + secondSNPPos[i];
totalInsertions = totalInsertions + firstInsertionPos[i] + secondInsertionPos[i];
totalDeletions = totalDeletions + firstDeletionPos[i] + secondDeletionPos[i];
totalPos[i] = firstSNPPos[i] + firstInsertionPos[i] + firstDeletionPos[i] +
secondSNPPos[i] + secondInsertionPos[i] + secondDeletionPos[i] +
matchPos[i];
// not very elegant but better here than inside processSequence()
if(secondSNPPos[i] > 0 || secondInsertionPos[i] > 0 || secondDeletionPos[i] > 0) {
existPairedReads = true;
}
}
// we do not consider totalSkippedRegions, totalHardClips and totalPaddings because they are not
// recorded in the read.
total = totalMatches + totalMutations + totalInsertions + totalDeletions + totalSoftClips;
totalsComputed = true;
}
// @Override methods
@Override
public void processSequence(SAMRecord read) {
isReadSpliced = false;
totalReads++;
// Compute and get the CigarMD object combining the strings Cigar and MD tag
cigarMDGenerator.generateCigarMD(read);
cigarMD = cigarMDGenerator.getCigarMD();
int errorType = cigarMDGenerator.getErrorType();
switch(errorType) {
//case 0: // no error
case 1: skippedReads++; return; // unmapped read. we cannot carry on here.. The number of unmapped reads is already calculated in the BasicStatistics module
case 2: readWithoutMDString++; break; // we won't have SNPs, but we compute statistics for the other operators.
case 3: readWithoutCigarString++; skippedReads++; return; // we cannot carry on here..
case 4: inconsistentCigarMDStrings++; skippedReads++; return; // we cannot carry on here..
}
readLength = read.getReadLength();
// Iterate the CigarMDElements list to collect statistics
List<CigarMDElement> cigarMDElements = cigarMD.getCigarMDElements();
CigarMDOperator currentCigarMDElementOperator;
// restart the counter for computing SNP/Indels per read position.
currentPosition = 0;
// Use the old c-style for loop for memory (garbage collector) and CPU efficiency
cigarMDElementsSize = cigarMDElements.size();
for(int i=0; i<cigarMDElementsSize; i++) {
currentCigarMDElement = cigarMDElements.get(i);
currentCigarMDElementOperator = currentCigarMDElement.getOperator();
//log.debug("Parsing CigarMDElement: " + currentCigarMDElement.toString());
if(currentCigarMDElementOperator == CigarMDOperator.MATCH) {
processMDtagCigarOperatorM();
} else if(currentCigarMDElementOperator == CigarMDOperator.MISMATCH) {
processMDtagCigarOperatorU();
} else if(currentCigarMDElementOperator == CigarMDOperator.INSERTION) {
processMDtagCigarOperatorI();
} else if(currentCigarMDElementOperator == CigarMDOperator.DELETION) {
processMDtagCigarOperatorD();
} else if(currentCigarMDElementOperator == CigarMDOperator.SKIPPED_REGION) {
processMDtagCigarOperatorN();
if(!isReadSpliced) {
isReadSpliced = true;
splicedReads++;
}
} else if(currentCigarMDElementOperator == CigarMDOperator.SOFT_CLIP) {
processMDtagCigarOperatorS();
} else if(currentCigarMDElementOperator == CigarMDOperator.HARD_CLIP) {
processMDtagCigarOperatorH();
} else if(currentCigarMDElementOperator == CigarMDOperator.PADDING) {
processMDtagCigarOperatorP();
} else if(currentCigarMDElementOperator == CigarMDOperator.eq) {
log.debug("Extended CIGAR element = is not currently supported.");
skippedReads++;
return;
} else if(currentCigarMDElementOperator == CigarMDOperator.x) {
log.debug("Extended CIGAR element X is not currently supported.");
skippedReads++;
return;
} else {
log.debug("Unknown operator in the CIGAR string.");
skippedReads++;
return;
}
}
if(contributingReadsPerPos.containsKey(readLength)) {
contributingReadsPerPos.put(readLength, contributingReadsPerPos.get(readLength) + 1L);
} else {
contributingReadsPerPos.put(readLength, 1L);
}
//log.debug("key, value:" + readLength + ", " + contributingReadsPerPos.get(readLength));
//log.debug("Combined Cigar MDtag: " + cigarMD.toString());
}
@Override
public void processFile(SequenceFile file) {}
@Override
public void processAnnotationSet(AnnotationSet annotation) { }
@Override
public JPanel getResultsPanel() {
return new JPanel();
}
@Override
public String name() {
return "Variant Call Detection";
}
@Override
public String description() {
return "Looks at the variant calls in the data";
}
@Override
public void reset() {
firstSNPs.put("AC", 0L);
firstSNPs.put("AG", 0L);
firstSNPs.put("AT", 0L);
firstSNPs.put("CA", 0L);
firstSNPs.put("CG", 0L);
firstSNPs.put("CT", 0L);
firstSNPs.put("GA", 0L);
firstSNPs.put("GC", 0L);
firstSNPs.put("GT", 0L);
firstSNPs.put("TA", 0L);
firstSNPs.put("TC", 0L);
firstSNPs.put("TG", 0L);
secondSNPs.put("AC", 0L);
secondSNPs.put("AG", 0L);
secondSNPs.put("AT", 0L);
secondSNPs.put("CA", 0L);
secondSNPs.put("CG", 0L);
secondSNPs.put("CT", 0L);
secondSNPs.put("GA", 0L);
secondSNPs.put("GC", 0L);
secondSNPs.put("GT", 0L);
secondSNPs.put("TA", 0L);
secondSNPs.put("TC", 0L);
secondSNPs.put("TG", 0L);
totalMutations = 0;
// To reduce computational time let's not collect data regarding indel type.
// insertions.put("A", 0L);
// insertions.put("C", 0L);
// insertions.put("G", 0L);
// insertions.put("T", 0L);
// insertions.put("N", 0L);
//
// totalInsertions = 0;
// deletions.put("A", 0L);
// deletions.put("C", 0L);
// deletions.put("G", 0L);
// deletions.put("T", 0L);
// deletions.put("N", 0L);
totalDeletions = 0;
totalMatches = 0;
totalSkippedRegions = 0;
totalSoftClips = 0;
totalHardClips = 0;
totalPaddings = 0;
total = 0;
skippedReads = 0;
totalReads = 0;
splicedReads = 0;
readUnknownBases = 0;
referenceUnknownBases = 0;
firstSNPPos = new long[VC_POSITION_ARRAY_SIZE];
firstInsertionPos = new long[VC_POSITION_ARRAY_SIZE];
firstDeletionPos = new long[VC_POSITION_ARRAY_SIZE];
secondSNPPos = new long[VC_POSITION_ARRAY_SIZE];
secondInsertionPos = new long[VC_POSITION_ARRAY_SIZE];
secondDeletionPos = new long[VC_POSITION_ARRAY_SIZE];
matchPos = new long[VC_POSITION_ARRAY_SIZE];
totalPos = new long[VC_POSITION_ARRAY_SIZE];
currentPosition = 0;
contributingReadsPerPos = new HashMap<Integer, Long>();
readLength = 0;
cigarMD = new CigarMD();
}
@Override
public boolean raisesError() {
return false;
}
@Override
public boolean raisesWarning() {
return false;
}
@Override
public boolean needsToSeeSequences() {
return true;
}
@Override
public boolean needsToSeeAnnotation() {
return false;
}
@Override
public boolean ignoreInReport() {
return true;
}
@Override
public void makeReport(HTMLReportArchive report) throws XMLStreamException, IOException { }
// Private methods here
/**
* Extend the density arrays storing the positions for SNPs, Indels, matches and totals if and only if newSize is greater or equal than the
* current size of these arrays. As this method can be time consuming, if newSize is < than two times the current size of a density array,
* the double of the current size will be used instead of newSize.
* @param newSize A suggested new size.
*/
private void extendDensityArrays(int newSize) {
if(newSize < totalPos.length) {
// we still have space left.
return;
}
// As we do not want to call this method too often, it is better to extend it
// 2 times the current length if newSize is a small increase
if(newSize < totalPos.length*2) {
newSize = totalPos.length*2;
}
long[] oldFirstSNPPos = firstSNPPos;
long[] oldFirstInsertionPos = firstInsertionPos;
long[] oldFirstDeletionPos = firstDeletionPos;
long[] oldSecondSNPPos = secondSNPPos;
long[] oldSecondInsertionPos = secondInsertionPos;
long[] oldSecondDeletionPos = secondDeletionPos;
long[] oldMatchPos = matchPos;
long[] oldTotalPos = totalPos;
firstSNPPos = new long[newSize];
firstInsertionPos = new long[newSize];
firstDeletionPos = new long[newSize];
secondSNPPos = new long[newSize];
secondInsertionPos = new long[newSize];
secondDeletionPos = new long[newSize];
matchPos = new long[newSize];
totalPos = new long[newSize];
System.arraycopy(oldFirstSNPPos, 0, firstSNPPos, 0, oldFirstSNPPos.length);
System.arraycopy(oldFirstInsertionPos, 0, firstInsertionPos, 0, oldFirstSNPPos.length);
System.arraycopy(oldFirstDeletionPos, 0, firstDeletionPos, 0, oldFirstSNPPos.length);
System.arraycopy(oldSecondSNPPos, 0, secondSNPPos, 0, oldFirstSNPPos.length);
System.arraycopy(oldSecondInsertionPos, 0, secondInsertionPos, 0, oldFirstSNPPos.length);
System.arraycopy(oldSecondDeletionPos, 0, secondDeletionPos, 0, oldFirstSNPPos.length);
System.arraycopy(oldMatchPos, 0, matchPos, 0, oldFirstSNPPos.length);
System.arraycopy(oldTotalPos, 0, totalPos, 0, oldFirstSNPPos.length);
}
// These methods process the combined CigarMD object.
/** Process the MD string once found the CigarMD operator m (match). */
private void processMDtagCigarOperatorM() {
int numMatches = currentCigarMDElement.getLength();
totalMatches = totalMatches + numMatches;
// if the read.length is longer than what we supposed to be, here we increase the length of our *Pos arrays.
extendDensityArrays(currentPosition+numMatches);
for(int i=0; i<numMatches; i++) {
matchPos[currentPosition+i]++;
}
currentPosition = currentPosition + numMatches;
}
/** Process the MD string once found the CigarMD operator u (mismatch).
* So far this element is indicated as 1u{ACGT}ref{ACGT}read
* to indicate a mutation from reference to read.
* In the future the length will correspond to the number of adjacent mutations.
* e.g. 3uACGTAT will indicate that the substring AGA on the reference has been
* mutated in CTT.
*/
private void processMDtagCigarOperatorU() {
int numMutations = currentCigarMDElement.getLength();
String mutatedBases = currentCigarMDElement.getBases();
String basePair;
if(mutatedBases.length() == 0) {
log.error("Mutated bases not reported. currentCigarMDElement: " + currentCigarMDElement + ", cigarMD: " + cigarMD.toString() +
", mutatedBases: " + mutatedBases);
// if we are in this case, the following for loop will cause a java.lang.StringIndexOutOfBoundsException .
// This would be a bug in the computation of the CigarMD string. mutatedBases should never be empty.
// For now, leave this test as it is useful.
}
// if the read.length is longer than what we supposed to be, here we increase the length of our *Pos arrays.
extendDensityArrays(currentPosition+numMutations);
if(cigarMDGenerator.isFirst()) {
for(int i = 0; i < numMutations; i++) {
basePair = mutatedBases.substring(i*2, i*2+2);
if(basePair.charAt(0) == 'N') {
referenceUnknownBases++;
if(basePair.charAt(1) == 'N') { readUnknownBases++; }
}
else if(basePair.charAt(1) == 'N') { readUnknownBases++; }
else {
firstSNPs.put(basePair, firstSNPs.get(basePair) + 1L);
firstSNPPos[currentPosition+i]++;
}
}
} else {
for(int i = 0; i < numMutations; i++) {
basePair = mutatedBases.substring(i*2, i*2+2);
if(basePair.charAt(0) == 'N') {
referenceUnknownBases++;
if(basePair.charAt(1) == 'N') { readUnknownBases++; }
}
else if(basePair.charAt(1) == 'N') { readUnknownBases++; }
else {
secondSNPs.put(basePair, secondSNPs.get(basePair) + 1L);
secondSNPPos[currentPosition+i]++;
}
}
}
currentPosition = currentPosition + numMutations;
}
/** Process the MD string once found the CigarMD operator i (insertion). */
private void processMDtagCigarOperatorI() {
int numInsertions = currentCigarMDElement.getLength();
String insertedBases = currentCigarMDElement.getBases();
// To reduce computational time let's not collect data regarding indel type.
// String base;
// if the read.length is longer than what we supposed to be, here we increase the length of our *Pos arrays..
extendDensityArrays(currentPosition+numInsertions);
if(cigarMDGenerator.isFirst()) {
for(int i = 0; i < numInsertions; i++) {
// To reduce computational time let's not collect data regarding indel type.
// base = insertedBases.substring(i, i+1);
// insertions.put(base, insertions.get(base) + 1L);
if(insertedBases.charAt(i) != 'N') {
firstInsertionPos[currentPosition+i]++;
}
}
} else {
for(int i = 0; i < numInsertions; i++) {
// To reduce computational time let's not collect data regarding indel type.
// base = insertedBases.substring(i, i+1);
// insertions.put(base, insertions.get(base) + 1L);
if(insertedBases.charAt(i) != 'N') {
secondInsertionPos[currentPosition+i]++;
}
}
}
currentPosition = currentPosition + numInsertions;
}
/** Process the MD string once found the CigarMD operator d (deletion). */
private void processMDtagCigarOperatorD() {
int numDeletions = currentCigarMDElement.getLength();
String deletedBases = currentCigarMDElement.getBases();
// if the read.length is longer than what we supposed to be, here we increase the length of our *Pos arrays..
extendDensityArrays(currentPosition+numDeletions);
if(!deletedBases.isEmpty()) {
// To reduce computational time let's not collect data regarding indel type.
// String base;
if(cigarMDGenerator.isFirst()) {
for(int i = 0; i < numDeletions; i++) {
// To reduce computational time let's not collect data regarding indel type.
// base = deletedBases.substring(i, i+1);
// deletions.put(base, deletions.get(base) + 1L);
if(deletedBases.charAt(i) != 'N') {
firstDeletionPos[currentPosition+i]++;
}
}
} else {
for(int i = 0; i < numDeletions; i++) {
// To reduce computational time let's not collect data regarding indel type.
// base = deletedBases.substring(i, i+1);
// deletions.put(base, deletions.get(base) + 1L);
if(deletedBases.charAt(i) != 'N') {
secondDeletionPos[currentPosition+i]++;
}
}
}
} else {
// we do not have deleted bases because we do not have the mdString for this read!
if(cigarMDGenerator.isFirst()) {
for(int i = 0; i < numDeletions; i++) {
firstDeletionPos[currentPosition+i]++;
}
} else {
for(int i = 0; i < numDeletions; i++) {
secondDeletionPos[currentPosition+i]++;
}
}
}
currentPosition = currentPosition + numDeletions;
}
// Have to test the following code.
/** Process the MD string once found the CigarMD operator n. */
private void processMDtagCigarOperatorN() {
int numSkipped = currentCigarMDElement.getLength();
totalSkippedRegions = totalSkippedRegions + numSkipped;
// currentPosition = currentPosition + numSkipped;
// // if the read.length is longer than what we supposed to be, here we increase the length of our *Pos arrays.
// extendDensityArrays(currentPosition);
//
}
/** Process the MD string once found the CigarMD operator s. */
private void processMDtagCigarOperatorS() {
int numSoftClips = currentCigarMDElement.getLength();
totalSoftClips = totalSoftClips + numSoftClips;
// currentPosition = currentPosition + numSoftClips;
// // if the read.length is longer than what we supposed to be, here we increase the length of our *Pos arrays.
// extendDensityArrays(currentPosition);
//
}
/** Process the MD string once found the CigarMD operator h. */
private void processMDtagCigarOperatorH() {
int numHardClips = currentCigarMDElement.getLength();
totalHardClips = totalHardClips + numHardClips;
// currentPosition = currentPosition + numHardClips;
// // if the read.length is longer than what we supposed to be, here we increase the length of our *Pos arrays.
// extendDensityArrays(currentPosition);
//
}
/** Process the MD string once found the CigarMD operator p. */
private void processMDtagCigarOperatorP() {
int numPaddings = currentCigarMDElement.getLength();
totalPaddings = totalPaddings + numPaddings;
// currentPosition = currentPosition + numPaddings;
// // if the read.length is longer than what we supposed to be, here we increase the length of our *Pos arrays.
// extendDensityArrays(currentPosition);
//
}
/** Process the MD string once found the CigarMD operator =. */
private void processMDtagCigarOperatorEQ() {
// is this operator used?
}
/** Process the MD string once found the CigarMD operator X. */
private void processMDtagCigarOperatorNEQ() {
// is this operator used?
}
// Getter methods
/**
* Return the calculated CigarMD or null if this is empty
* @return CigarMD or null
*/
public CigarMD getCigarMD() {
return cigarMD;
}
/**
* Return the number of contributing reads per position.
* @return the number of contributing reads per position.
*/
public HashMap<Integer, Long> getContributingReadsPerPos() {
return contributingReadsPerPos;
}
/**
* Return true if paired reads exist.
* @return true if paired reads exist.
*/
public boolean existPairedReads() {
return existPairedReads;
}
/**
* The SNPs computed from the first reads.
* @return SNPs for the first reads.
*/
public HashMap<String, Long> getFirstSNPs() {
return firstSNPs;
}
/**
* The SNPs computed from the second reads.
* @return SNPs for the second reads.
*/
public HashMap<String, Long> getSecondSNPs() {
return secondSNPs;
}
// To reduce computational time let's not collect data regarding indel type.
// public HashMap<String, Long> getInsertions() {
// return insertions;
// }
//
// public HashMap<String, Long> getDeletions() {
// return deletions;
// }
/**
* The total number of mutations (SNPs).
* @return The total number of SNPs.
*/
public long getTotalMutations() {
return totalMutations;
}
/**
* The total number of insertions.
* @return The total number of insertions.
*/
public long getTotalInsertions() {
return totalInsertions;
}
/**
* The total number of deletions.
* @return The total number of deletions.
*/
public long getTotalDeletions() {
return totalDeletions;
}
/**
* The total number of matches.
* @return The total number of matches.
*/
public long getTotalMatches() {
return totalMatches;
}
/**
* The total number of skipped regions.
* @return The total number of skipped regions.
*/
public long getTotalSkippedRegions() {
return totalSkippedRegions;
}
/**
* The total number of soft clips.
* @return The total number of soft clips.
*/
public long getTotalSoftClips() {
return totalSoftClips;
}
/**
* The total number of hard clips.
* @return The total number of hard clips.
*/
public long getTotalHardClips() {
return totalHardClips;
}
/**
* The total number of paddings.
* @return The total number of paddings.
*/
public long getTotalPaddings() {
return totalPaddings;
}
/**
* The total number of bases.
* @return The total number of bases.
*/
public long getTotal() {
return total;
}
/**
* The total number of spliced reads.
* @return The total number of spliced reads.
*/
public long getTotalSplicedReads() {
return splicedReads;
}
/**
* The number of unknown bases in the read.
* @return The number of unknown bases.
*/
public long getReadUnknownBases() {
return readUnknownBases;
}
/**
* The number of unknown bases in the reference.
* @return The number of unknown bases.
*/
public long getReferenceUnknownBases() {
return referenceUnknownBases;
}
/**
* The number of skipped reads.
* @return The number of skipped reads.
*/
public long getSkippedReads() {
return skippedReads;
}
/**
* The number of reads without MD String.
* @return The number of reads without MD String.
*/
public long getReadWithoutMDString() {
return readWithoutMDString;
}
/**
* The number of reads without Cigar String.
* @return The number of reads without Cigar String.
*/
public long getReadWithoutCigarString() {
return readWithoutCigarString;
}
/**
* The number of reads with inconsistencies between Cigar and MD String.
* @return The number of reads with inconsistencies between Cigar and MD String.
*/
public long getInconsistentCigarMDStrings() {
return inconsistentCigarMDStrings;
}
/**
* The total number of reads.
* @return The total number of reads.
*/
public long getTotalReads() {
return totalReads;
}
/**
* The SNP positions for the first reads.
* @return The SNP positions for the first reads.
*/
public long[] getFirstSNPPos() {
return firstSNPPos;
}
/**
* The SNP positions for the second reads.
* @return The SNP positions for the second reads.
*/
public long[] getSecondSNPPos() {
return secondSNPPos;
}
/**
* The insertion positions for the first reads.
* @return The insertion positions for the first reads.
*/
public long[] getFirstInsertionPos() {
return firstInsertionPos;
}
/**
* The deletion positions for the first reads.
* @return The deletion positions for the first reads.
*/
public long[] getFirstDeletionPos() {
return firstDeletionPos;
}
/**
* The insertion positions for the second reads.
* @return The insertion positions for the second reads.
*/
public long[] getSecondInsertionPos() {
return secondInsertionPos;
}
/**
* The deletion positions for the second reads.
* @return The deletion positions for the second reads.
*/
public long[] getSecondDeletionPos() {
return secondDeletionPos;
}
/**
* The match positions.
* @return The match positions.
*/
public long[] getMatchPos() {
return matchPos;
}
/**
* The positions for all reads.
* @return The positions for all reads.
*/
public long[] getTotalPos() {
return totalPos;
}
}