int Bam2FastQ::execute(int argc, char **argv) { // Extract command line arguments. String inFile = ""; bool readName = false; String refFile = ""; String firstOut = ""; String secondOut = ""; String unpairedOut = ""; bool interleave = false; bool noeof = false; bool gzip = false; bool params = false; myOutBase = ""; myNumMateFailures = 0; myNumPairs = 0; myNumUnpaired = 0; mySplitRG = false; myQField = ""; myNumQualTagErrors = 0; myReverseComp = true; myRNPlus = false; myFirstRNExt = DEFAULT_FIRST_EXT; mySecondRNExt = DEFAULT_SECOND_EXT; myCompression = InputFile::DEFAULT; ParameterList inputParameters; BEGIN_LONG_PARAMETERS(longParameterList) LONG_PARAMETER_GROUP("Required Parameters") LONG_STRINGPARAMETER("in", &inFile) LONG_PARAMETER_GROUP("Optional Parameters") LONG_PARAMETER("readName", &readName) LONG_PARAMETER("splitRG", &mySplitRG) LONG_STRINGPARAMETER("qualField", &myQField) LONG_PARAMETER("merge", &interleave) LONG_STRINGPARAMETER("refFile", &refFile) LONG_STRINGPARAMETER("firstRNExt", &myFirstRNExt) LONG_STRINGPARAMETER("secondRNExt", &mySecondRNExt) LONG_PARAMETER("rnPlus", &myRNPlus) LONG_PARAMETER("noReverseComp", &myReverseComp) LONG_PARAMETER("gzip", &gzip) LONG_PARAMETER("noeof", &noeof) LONG_PARAMETER("params", ¶ms) LONG_PARAMETER_GROUP("Optional OutputFile Names") LONG_STRINGPARAMETER("outBase", &myOutBase) LONG_STRINGPARAMETER("firstOut", &firstOut) LONG_STRINGPARAMETER("secondOut", &secondOut) LONG_STRINGPARAMETER("unpairedOut", &unpairedOut) LONG_PHONEHOME(VERSION) END_LONG_PARAMETERS(); inputParameters.Add(new LongParameters ("Input Parameters", longParameterList)); // parameters start at index 2 rather than 1. inputParameters.Read(argc, argv, 2); // If no eof block is required for a bgzf file, set the bgzf file type to // not look for it. if(noeof) { // Set that the eof block is not required. BgzfFileType::setRequireEofBlock(false); } if(gzip) { myCompression = InputFile::GZIP; } // Check to see if the in file was specified, if not, report an error. if(inFile == "") { usage(); inputParameters.Status(); // In file was not specified but it is mandatory. std::cerr << "--in is a mandatory argument, " << "but was not specified" << std::endl; return(-1); } // Cannot specify both interleaved & secondOut since secondOut would be N/A. if(interleave && !secondOut.IsEmpty()) { usage(); inputParameters.Status(); std::cerr << "ERROR: Cannot specify --merge & --secondOut.\n"; return(-1); } // Cannot specify both interleaved & secondOut since secondOut would be N/A. if(interleave && !secondOut.IsEmpty()) { usage(); inputParameters.Status(); std::cerr << "ERROR: Cannot specify --merge & --secondOut.\n"; return(-1); } // Cannot specify both splitRG & firstOut/secondOut/unpairedOut // since it needs a different file for each RG. if(mySplitRG && (!firstOut.IsEmpty() || !secondOut.IsEmpty() || !unpairedOut.IsEmpty())) { usage(); inputParameters.Status(); std::cerr << "ERROR: Cannot specify --splitRG & --firstOut/--secondOut/--unpairedOut.\n"; std::cerr << "Use --outBase instead.\n"; return(-1); } // Cannot specify splitRG & output to stdout. if(mySplitRG && (myOutBase[0] == '-')) { usage(); inputParameters.Status(); std::cerr << "ERROR: Cannot specify --splitRG & write to stdout.\n"; return(-1); } // Check to see if the out file was specified, if not, generate it from // the input filename. if(myOutBase == "") { // Just remove the extension from the input filename. int extStart = inFile.FastFindLastChar('.'); if(extStart <= 0) { myOutBase = inFile; } else { myOutBase = inFile.Left(extStart); } } if(mySplitRG) { std::string fqList = myOutBase.c_str(); fqList += ".list"; myFqList = ifopen(fqList.c_str(), "w"); ifprintf(myFqList, "MERGE_NAME\tFASTQ1\tFASTQ2\tRG\n"); } // Check to see if the first/second/single-ended were specified and // if not, set them. myFirstFileNameExt = "_1.fastq"; mySecondFileNameExt = "_2.fastq"; myUnpairedFileNameExt = ".fastq"; if(interleave) { myFirstFileNameExt = "_interleaved.fastq"; myFirstFileNameExt = "_interleaved.fastq"; } getFileName(firstOut, myFirstFileNameExt); getFileName(secondOut, mySecondFileNameExt); getFileName(unpairedOut, myUnpairedFileNameExt); if(params) { inputParameters.Status(); } // Open the files for reading/writing. // Open prior to opening the output files, // so if there is an error, the outputs don't get created. SamFile samIn; samIn.OpenForRead(inFile, &mySamHeader); // Skip non-primary reads. samIn.SetReadFlags(0, 0x0100); // Open the output files if not splitting RG if(!mySplitRG) { myUnpairedFile = ifopen(unpairedOut, "w", myCompression); // Only open the first file if it is different than an already opened file. if(firstOut != unpairedOut) { myFirstFile = ifopen(firstOut, "w", myCompression); } else { myFirstFile = myUnpairedFile; } // If it is interleaved or the 2nd file is not a new name, set it appropriately. if(interleave || secondOut == firstOut) { mySecondFile = myFirstFile; } else if(secondOut == unpairedOut) { mySecondFile = myUnpairedFile; } else { mySecondFile = ifopen(secondOut, "w", myCompression); } if(myUnpairedFile == NULL) { std::cerr << "Failed to open " << unpairedOut << " so can't convert bam2FastQ.\n"; return(-1); } if(myFirstFile == NULL) { std::cerr << "Failed to open " << firstOut << " so can't convert bam2FastQ.\n"; return(-1); } if(mySecondFile == NULL) { std::cerr << "Failed to open " << secondOut << " so can't convert bam2FastQ.\n"; return(-1); } } if((readName) || (strcmp(mySamHeader.getSortOrder(), "queryname") == 0)) { readName = true; } else { // defaulting to coordinate sorted. samIn.setSortedValidation(SamFile::COORDINATE); } // Setup the '=' translation if the reference was specified. if(!refFile.IsEmpty()) { GenomeSequence* refPtr = new GenomeSequence(refFile); samIn.SetReadSequenceTranslation(SamRecord::BASES); samIn.SetReference(refPtr); } SamRecord* recordPtr; int16_t samFlag; SamStatus::Status returnStatus = SamStatus::SUCCESS; while(returnStatus == SamStatus::SUCCESS) { recordPtr = myPool.getRecord(); if(recordPtr == NULL) { // Failed to allocate a new record. throw(std::runtime_error("Failed to allocate a new SAM/BAM record")); } if(!samIn.ReadRecord(mySamHeader, *recordPtr)) { // Failed to read a record. returnStatus = samIn.GetStatus(); continue; } // Have a record. Check to see if it is a pair or unpaired read. samFlag = recordPtr->getFlag(); if(SamFlag::isPaired(samFlag)) { if(readName) { handlePairedRN(*recordPtr); } else { handlePairedCoord(*recordPtr); } } else { ++myNumUnpaired; writeFastQ(*recordPtr, myUnpairedFile, myUnpairedFileNameExt); } } // Flush All cleanUpMateMap(0, true); if(returnStatus == SamStatus::NO_MORE_RECS) { returnStatus = SamStatus::SUCCESS; } samIn.Close(); closeFiles(); // Output the results std::cerr << "\nFound " << myNumPairs << " read pairs.\n"; std::cerr << "Found " << myNumUnpaired << " unpaired reads.\n"; if(myNumMateFailures != 0) { std::cerr << "Failed to find mates for " << myNumMateFailures << " reads, so they were written as unpaired\n" << " (not included in either of the above counts).\n"; } if(myNumQualTagErrors != 0) { std::cerr << myNumQualTagErrors << " records did not have tag " << myQField.c_str() << " or it was invalid, so the quality field was used for those records.\n"; } return(returnStatus); }
int Dedup_LowMem::execute(int argc, char** argv) { /* -------------------------------- * process the arguments * -------------------------------*/ String inFile, outFile, logFile; myDoRecab = false; bool removeFlag = false; bool verboseFlag = false; myForceFlag = false; myNumMissingMate = 0; myMinQual = DEFAULT_MIN_QUAL; String excludeFlags = "0xB04"; uint16_t intExcludeFlags = 0; bool noeof = false; bool params = false; LongParamContainer parameters; parameters.addGroup("Required Parameters"); parameters.addString("in", &inFile); parameters.addString("out", &outFile); parameters.addGroup("Optional Parameters"); parameters.addInt("minQual", & myMinQual); parameters.addString("log", &logFile); parameters.addBool("oneChrom", &myOneChrom); parameters.addBool("recab", &myDoRecab); parameters.addBool("rmDups", &removeFlag); parameters.addBool("force", &myForceFlag); parameters.addString("excludeFlags", &excludeFlags); parameters.addBool("verbose", &verboseFlag); parameters.addBool("noeof", &noeof); parameters.addBool("params", ¶ms); parameters.addPhoneHome(VERSION); myRecab.addRecabSpecificParameters(parameters); ParameterList inputParameters; inputParameters.Add(new LongParameters ("Input Parameters", parameters.getLongParameterList())); // parameters start at index 2 rather than 1. inputParameters.Read(argc, argv, 2); // If no eof block is required for a bgzf file, set the bgzf file type to // not look for it. if(noeof) { // Set that the eof block is not required. BgzfFileType::setRequireEofBlock(false); } if(inFile.IsEmpty()) { printUsage(std::cerr); inputParameters.Status(); std::cerr << "Specify an input file" << std::endl; return EXIT_FAILURE; } if(outFile.IsEmpty()) { printUsage(std::cerr); inputParameters.Status(); std::cerr << "Specify an output file" << std::endl; return EXIT_FAILURE; } intExcludeFlags = excludeFlags.AsInteger(); if(myForceFlag && SamFlag::isDuplicate(intExcludeFlags)) { printUsage(std::cerr); inputParameters.Status(); std::cerr << "Cannot specify --force and Duplicate in the excludeFlags. Since --force indicates to override" << " previous duplicate setting and the excludeFlags says to skip those, you can't do both.\n"; return EXIT_FAILURE; } if(!SamFlag::isSecondary(intExcludeFlags)) { printUsage(std::cerr); inputParameters.Status(); std::cerr << "ERROR: Secondary reads must be excluded, edit --excludeFlags to include 0x0100\n"; return EXIT_FAILURE; } if(!(intExcludeFlags & SamFlag::SUPPLEMENTARY_ALIGNMENT)) { printUsage(std::cerr); inputParameters.Status(); std::cerr << "ERROR: Supplementary reads must be excluded, edit --excludeFlags to include 0x0800\n"; return EXIT_FAILURE; } if(logFile.IsEmpty()) { logFile = outFile + ".log"; } if(myDoRecab) { int status = myRecab.processRecabParam(); if(status != 0) { inputParameters.Status(); return(status); } } if(params) { inputParameters.Status(); } Logger::gLogger = new Logger(logFile.c_str(), verboseFlag); /* ------------------------------------------------------------------- * The arguments are processed. Prepare the input BAM file, * instantiate dedup_LowMem, and construct the read group library map * ------------------------------------------------------------------*/ SamFile samIn; samIn.OpenForRead(inFile.c_str()); // If the file isn't sorted it will throw an exception. samIn.setSortedValidation(SamFile::COORDINATE); SamFileHeader header; samIn.ReadHeader(header); buildReadGroupLibraryMap(header); lastReference = -1; lastCoordinate = -1; // for keeping some basic statistics uint32_t recordCount = 0; uint32_t pairedCount = 0; uint32_t properPairCount = 0; uint32_t unmappedCount = 0; uint32_t reverseCount = 0; uint32_t qualCheckFailCount = 0; uint32_t secondaryCount = 0; uint32_t supplementaryCount = 0; uint32_t excludedCount = 0; // Now we start reading records SamRecord* recordPtr; SamStatus::Status returnStatus = SamStatus::SUCCESS; while(returnStatus == SamStatus::SUCCESS) { recordPtr = mySamPool.getRecord(); if(recordPtr == NULL) { std::cerr << "Failed to allocate enough records\n"; return(-1); } if(!samIn.ReadRecord(header, *recordPtr)) { returnStatus = samIn.GetStatus(); continue; } // Take note of properties of this record int flag = recordPtr->getFlag(); if(SamFlag::isPaired(flag)) ++pairedCount; if(SamFlag::isProperPair(flag)) ++properPairCount; if(SamFlag::isReverse(flag)) ++reverseCount; if(SamFlag::isQCFailure(flag)) ++qualCheckFailCount; if(SamFlag::isSecondary(flag)) ++secondaryCount; if(flag & SamFlag::SUPPLEMENTARY_ALIGNMENT) ++supplementaryCount; if(!SamFlag::isMapped(flag)) ++unmappedCount; // put the record in the appropriate maps: // single reads go in myFragmentMap // paired reads go in myPairedMap recordCount = samIn.GetCurrentRecordCount(); // if we have moved to a new position, look back at previous reads for duplicates if (hasPositionChanged(*recordPtr)) { cleanupPriorReads(recordPtr); } // Determine if this read should be checked for duplicates. if((!SamFlag::isMapped(flag)) || ((flag & intExcludeFlags) != 0)) { ++excludedCount; // No deduping done on this record, but still build the recab table. if(myDoRecab) { myRecab.processReadBuildTable(*recordPtr); } // Nothing more to do with this record, so // release the pointer. mySamPool.releaseRecord(recordPtr); } else { if(SamFlag::isDuplicate(flag) && !myForceFlag) { // Error: Marked duplicates, and duplicates aren't excluded. Logger::gLogger->error("There are records already duplicate marked."); Logger::gLogger->error("Use -f to clear the duplicate flag and start the dedup_LowMem procedure over"); } checkDups(*recordPtr, recordCount); mySamPool.releaseRecord(recordPtr); } // let the user know we're not napping if (verboseFlag && (recordCount % 100000 == 0)) { Logger::gLogger->writeLog("recordCount=%u singleKeyMap=%u pairedKeyMap=%u, dictSize=%u", recordCount, myFragmentMap.size(), myPairedMap.size(), myMateMap.size()); } } // we're finished reading record so clean up the duplicate search and // close the input file cleanupPriorReads(NULL); samIn.Close(); // print some statistics Logger::gLogger->writeLog("--------------------------------------------------------------------------"); Logger::gLogger->writeLog("SUMMARY STATISTICS OF THE READS"); Logger::gLogger->writeLog("Total number of reads: %u",recordCount); Logger::gLogger->writeLog("Total number of paired-end reads: %u", pairedCount); Logger::gLogger->writeLog("Total number of properly paired reads: %u", properPairCount); Logger::gLogger->writeLog("Total number of unmapped reads: %u", unmappedCount); Logger::gLogger->writeLog("Total number of reverse strand mapped reads: %u", reverseCount); Logger::gLogger->writeLog("Total number of QC-failed reads: %u", qualCheckFailCount); Logger::gLogger->writeLog("Total number of secondary reads: %u", secondaryCount); Logger::gLogger->writeLog("Total number of supplementary reads: %u", supplementaryCount); Logger::gLogger->writeLog("Size of singleKeyMap (must be zero): %u", myFragmentMap.size()); Logger::gLogger->writeLog("Size of pairedKeyMap (must be zero): %u", myPairedMap.size()); Logger::gLogger->writeLog("Total number of missing mates: %u", myNumMissingMate); Logger::gLogger->writeLog("Total number of reads excluded from duplicate checking: %u", excludedCount); Logger::gLogger->writeLog("--------------------------------------------------------------------------"); Logger::gLogger->writeLog("Sorting the indices of %d duplicated records", myDupList.size()); // sort the indices of duplicate records std::sort(myDupList.begin(), myDupList.end(), std::less<uint32_t> ()); // get ready to write the output file by making a second pass // through the input file samIn.OpenForRead(inFile.c_str()); samIn.ReadHeader(header); SamFile samOut; samOut.OpenForWrite(outFile.c_str()); samOut.WriteHeader(header); // If we are recalibrating, output the model information. if(myDoRecab) { myRecab.modelFitPrediction(outFile); } // an iterator to run through the duplicate indices int currentDupIndex = 0; bool moreDups = !myDupList.empty(); // let the user know what we're doing Logger::gLogger->writeLog("\nWriting %s", outFile.c_str()); // count the duplicate records as a check uint32_t singleDuplicates(0), pairedDuplicates(0); // start reading records and writing them out SamRecord record; while(samIn.ReadRecord(header, record)) { uint32_t currentIndex = samIn.GetCurrentRecordCount(); bool foundDup = moreDups && (currentIndex == myDupList[currentDupIndex]); // modify the duplicate flag and write out the record, // if it's appropriate int flag = record.getFlag(); if (foundDup) { // this record is a duplicate, so mark it. record.setFlag( flag | 0x400 ); currentDupIndex++; // increment duplicate counters to verify we found them all if ( ( ( flag & 0x0001 ) == 0 ) || ( flag & 0x0008 ) ) { // unpaired or mate unmapped singleDuplicates++; } else { pairedDuplicates++; } // recalibrate if necessary. if(myDoRecab) { myRecab.processReadApplyTable(record); } // write the record if we are not removing duplicates if (!removeFlag ) samOut.WriteRecord(header, record); } else { if(myForceFlag) { // this is not a duplicate we've identified but we want to // remove any duplicate marking record.setFlag( flag & 0xfffffbff ); // unmark duplicate } // Not a duplicate, so recalibrate if necessary. if(myDoRecab) { myRecab.processReadApplyTable(record); } samOut.WriteRecord(header, record); } // Let the user know we're still here if (verboseFlag && (currentIndex % 100000 == 0)) { Logger::gLogger->writeLog("recordCount=%u", currentIndex); } } // We're done. Close the files and print triumphant messages. samIn.Close(); samOut.Close(); Logger::gLogger->writeLog("Successfully %s %u unpaired and %u paired duplicate reads", removeFlag ? "removed" : "marked" , singleDuplicates, pairedDuplicates/2); Logger::gLogger->writeLog("\nDedup_LowMem complete!"); return 0; }
void testIndex(BamIndex& bamIndex) { assert(bamIndex.getNumMappedReads(1) == 2); assert(bamIndex.getNumUnMappedReads(1) == 0); assert(bamIndex.getNumMappedReads(0) == 4); assert(bamIndex.getNumUnMappedReads(0) == 1); assert(bamIndex.getNumMappedReads(23) == -1); assert(bamIndex.getNumUnMappedReads(23) == -1); assert(bamIndex.getNumMappedReads(-1) == 0); assert(bamIndex.getNumUnMappedReads(-1) == 2); assert(bamIndex.getNumMappedReads(-2) == -1); assert(bamIndex.getNumUnMappedReads(-2) == -1); assert(bamIndex.getNumMappedReads(22) == 0); assert(bamIndex.getNumUnMappedReads(22) == 0); // Get the chunks for reference id 1. Chunk testChunk; SortedChunkList chunkList; assert(bamIndex.getChunksForRegion(1, -1, -1, chunkList) == true); assert(!chunkList.empty()); testChunk = chunkList.pop(); assert(chunkList.empty()); assert(testChunk.chunk_beg == 0x4e7); assert(testChunk.chunk_end == 0x599); // Get the chunks for reference id 0. assert(bamIndex.getChunksForRegion(0, -1, -1, chunkList) == true); assert(!chunkList.empty()); testChunk = chunkList.pop(); assert(chunkList.empty()); assert(testChunk.chunk_beg == 0x360); assert(testChunk.chunk_end == 0x4e7); // Get the chunks for reference id 2. assert(bamIndex.getChunksForRegion(2, -1, -1, chunkList) == true); assert(!chunkList.empty()); testChunk = chunkList.pop(); assert(chunkList.empty()); assert(testChunk.chunk_beg == 0x599); assert(testChunk.chunk_end == 0x5ea); // Get the chunks for reference id 3. // There isn't one for this ref id, but still successfully read the file, // so it should return true, but the list should be empty. assert(bamIndex.getChunksForRegion(3, -1, -1, chunkList) == true); assert(chunkList.empty()); // Test reading an indexed bam file. SamFile inFile; assert(inFile.OpenForRead("testFiles/sortedBam.bam")); inFile.setSortedValidation(SamFile::COORDINATE); assert(inFile.ReadBamIndex("testFiles/sortedBam.bam.bai")); SamFileHeader samHeader; assert(inFile.ReadHeader(samHeader)); SamRecord samRecord; // Test getting num mapped/unmapped reads. assert(inFile.getNumMappedReadsFromIndex(1) == 2); assert(inFile.getNumUnMappedReadsFromIndex(1) == 0); assert(inFile.getNumMappedReadsFromIndex(0) == 4); assert(inFile.getNumUnMappedReadsFromIndex(0) == 1); assert(inFile.getNumMappedReadsFromIndex(23) == -1); assert(inFile.getNumUnMappedReadsFromIndex(23) == -1); assert(inFile.getNumMappedReadsFromIndex(-1) == 0); assert(inFile.getNumUnMappedReadsFromIndex(-1) == 2); assert(inFile.getNumMappedReadsFromIndex(-2) == -1); assert(inFile.getNumUnMappedReadsFromIndex(-2) == -1); assert(inFile.getNumMappedReadsFromIndex(22) == 0); assert(inFile.getNumUnMappedReadsFromIndex(22) == 0); assert(inFile.getNumMappedReadsFromIndex("2", samHeader) == 2); assert(inFile.getNumUnMappedReadsFromIndex("2", samHeader) == 0); assert(inFile.getNumMappedReadsFromIndex("1", samHeader) == 4); assert(inFile.getNumUnMappedReadsFromIndex("1", samHeader) == 1); assert(inFile.getNumMappedReadsFromIndex("22", samHeader) == 0); assert(inFile.getNumUnMappedReadsFromIndex("22", samHeader) == 0); assert(inFile.getNumMappedReadsFromIndex("", samHeader) == 0); assert(inFile.getNumUnMappedReadsFromIndex("*", samHeader) == 2); assert(inFile.getNumMappedReadsFromIndex("unknown", samHeader) == -1); assert(inFile.getNumUnMappedReadsFromIndex("unknown", samHeader) == -1); assert(inFile.getNumMappedReadsFromIndex("X", samHeader) == 0); assert(inFile.getNumUnMappedReadsFromIndex("X", samHeader) == 0); // Section -1 = Ref *: 2 records (8 & 10 from testSam.sam that is reflected // in the validation. assert(inFile.SetReadSection(-1)); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead8(samRecord); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead10(samRecord); assert(inFile.ReadRecord(samHeader, samRecord) == false); // Section 2 = Ref 3: 1 records (9 from testSam.sam that is reflected // in the validation. assert(inFile.SetReadSection(2)); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead9(samRecord); assert(inFile.ReadRecord(samHeader, samRecord) == false); // Section 0 = Ref 1: 5 records (3, 4, 1, 2, & 6 from testSam.sam that is // reflected in the validation. assert(inFile.SetReadSection(0)); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead3(samRecord); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead4(samRecord); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead1(samRecord); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead2(samRecord); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead6(samRecord); assert(inFile.ReadRecord(samHeader, samRecord) == false); // Section 1 = Ref 2: 2 records (5 & 7 from testSam.sam that is reflected // in the validation. assert(inFile.SetReadSection(1)); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead5(samRecord); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead7(samRecord); assert(inFile.ReadRecord(samHeader, samRecord) == false); // Section 3 to 22 (ref 4 - 23): 0 records. for(int i = 3; i < 23; i++) { assert(inFile.SetReadSection(i)); assert(inFile.ReadRecord(samHeader, samRecord) == false); } // Set the read section. assert(inFile.SetReadSection("1", 1010, 1012)); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead1(samRecord); assert(inFile.GetNumOverlaps(samRecord) == 2); assert(samRecord.getNumOverlaps(1010, 1012) == 2); assert(samRecord.getNumOverlaps(1010, 1020) == 5); assert(samRecord.getNumOverlaps(1010, 1011) == 1); assert(samRecord.getNumOverlaps(1011, 1012) == 1); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead2(samRecord); assert(inFile.GetNumOverlaps(samRecord) == 0); assert(samRecord.getNumOverlaps(1010, 1012) == 0); assert(samRecord.getNumOverlaps(1010, 1020) == 0); assert(samRecord.getNumOverlaps(1010, 1011) == 0); assert(samRecord.getNumOverlaps(1011, 1012) == 0); assert(inFile.ReadRecord(samHeader, samRecord) == false); assert(inFile.SetReadSection("1", 1010, 1020)); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead1(samRecord); assert(inFile.GetNumOverlaps(samRecord) == 5); assert(samRecord.getNumOverlaps(1010, 1012) == 2); assert(samRecord.getNumOverlaps(1010, 1020) == 5); assert(samRecord.getNumOverlaps(1010, 1011) == 1); assert(samRecord.getNumOverlaps(1011, 1012) == 1); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead2(samRecord); assert(inFile.GetNumOverlaps(samRecord) == 0); assert(samRecord.getNumOverlaps(1010, 1012) == 0); assert(samRecord.getNumOverlaps(1010, 1020) == 0); assert(samRecord.getNumOverlaps(1010, 1011) == 0); assert(samRecord.getNumOverlaps(1011, 1012) == 0); assert(inFile.ReadRecord(samHeader, samRecord) == false); assert(inFile.SetReadSection("1", 1010, 1011)); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead1(samRecord); assert(inFile.GetNumOverlaps(samRecord) == 1); assert(samRecord.getNumOverlaps(1010, 1012) == 2); assert(samRecord.getNumOverlaps(1010, 1020) == 5); assert(samRecord.getNumOverlaps(1010, 1011) == 1); assert(samRecord.getNumOverlaps(1011, 1012) == 1); assert(inFile.ReadRecord(samHeader, samRecord) == false); assert(inFile.SetReadSection("1", 1011, 1012)); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead1(samRecord); assert(inFile.GetNumOverlaps(samRecord) == 1); assert(samRecord.getNumOverlaps(1010, 1012) == 2); assert(samRecord.getNumOverlaps(1010, 1020) == 5); assert(samRecord.getNumOverlaps(1010, 1011) == 1); assert(samRecord.getNumOverlaps(1011, 1012) == 1); assert(inFile.ReadRecord(samHeader, samRecord)); validateRead2(samRecord); assert(inFile.GetNumOverlaps(samRecord) == 0); assert(samRecord.getNumOverlaps(1010, 1012) == 0); assert(samRecord.getNumOverlaps(1010, 1020) == 0); assert(samRecord.getNumOverlaps(1010, 1011) == 0); assert(samRecord.getNumOverlaps(1011, 1012) == 0); assert(inFile.ReadRecord(samHeader, samRecord) == false); }