SamFile.cpp
/*
* Copyright (C) 2010 Regents of the University of Michigan
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdexcept>
#include "SamFile.h"
#include "SamFileHeader.h"
#include "SamRecord.h"
#include "BamInterface.h"
#include "SamInterface.h"
#include "BgzfFileType.h"
// Constructor, init variables.
SamFile::SamFile()
: myStatus()
{
init();
resetFile();
}
// Constructor, init variables.
SamFile::SamFile(ErrorHandler::HandlingType errorHandlingType)
: myStatus(errorHandlingType)
{
init();
resetFile();
}
// Constructor, init variables and open the specified file based on the
// specified mode (READ/WRITE).
SamFile::SamFile(const char* filename, OpenType mode)
: myStatus()
{
init(filename, mode, NULL);
}
// Constructor, init variables and open the specified file based on the
// specified mode (READ/WRITE). Default is READ..
SamFile::SamFile(const char* filename, OpenType mode,
ErrorHandler::HandlingType errorHandlingType)
: myStatus(errorHandlingType)
{
init(filename, mode, NULL);
}
// Constructor, init variables and open the specified file based on the
// specified mode (READ/WRITE).
SamFile::SamFile(const char* filename, OpenType mode, SamFileHeader* header)
: myStatus()
{
init(filename, mode, header);
}
// Constructor, init variables and open the specified file based on the
// specified mode (READ/WRITE). Default is READ..
SamFile::SamFile(const char* filename, OpenType mode,
ErrorHandler::HandlingType errorHandlingType,
SamFileHeader* header)
: myStatus(errorHandlingType)
{
init(filename, mode, header);
}
SamFile::~SamFile()
{
resetFile();
if(myStatistics != NULL)
{
delete myStatistics;
}
}
// Open a sam/bam file for reading with the specified filename.
bool SamFile::OpenForRead(const char * filename, SamFileHeader* header)
{
// Reset for any previously operated on files.
resetFile();
int lastchar = 0;
while (filename[lastchar] != 0) lastchar++;
// If at least one character, check for '-'.
if((lastchar >= 1) && (filename[0] == '-'))
{
// Read from stdin - determine type of file to read.
// Determine if compressed bam.
if(strcmp(filename, "-.bam") == 0)
{
// Compressed bam - open as bgzf.
// -.bam is the filename, read compressed bam from stdin
filename = "-";
myFilePtr = new InputFile;
// support recover mode - this switches in a reader
// capable of recovering from bad BGZF compression blocks.
myFilePtr->setAttemptRecovery(myAttemptRecovery);
myFilePtr->openFile(filename, "rb", InputFile::BGZF);
myInterfacePtr = new BamInterface;
// Read the magic string.
char magic[4];
ifread(myFilePtr, magic, 4);
}
else if(strcmp(filename, "-.ubam") == 0)
{
// uncompressed BAM File.
// -.ubam is the filename, read uncompressed bam from stdin.
// uncompressed BAM is still compressed with BGZF, but using
// compression level 0, so still open as BGZF since it has a
// BGZF header.
filename = "-";
// Uncompressed, so do not require the eof block.
#ifdef __ZLIB_AVAILABLE__
BgzfFileType::setRequireEofBlock(false);
#endif
myFilePtr = ifopen(filename, "rb", InputFile::BGZF);
myInterfacePtr = new BamInterface;
// Read the magic string.
char magic[4];
ifread(myFilePtr, magic, 4);
}
else if((strcmp(filename, "-") == 0) || (strcmp(filename, "-.sam") == 0))
{
// SAM File.
// read sam from stdin
filename = "-";
myFilePtr = ifopen(filename, "rb", InputFile::UNCOMPRESSED);
myInterfacePtr = new SamInterface;
}
else
{
std::string errorMessage = "Invalid SAM/BAM filename, ";
errorMessage += filename;
errorMessage += ". From stdin, can only be '-', '-.sam', '-.bam', or '-.ubam'";
myStatus.setStatus(SamStatus::FAIL_IO, errorMessage.c_str());
delete myFilePtr;
myFilePtr = NULL;
return(false);
}
}
else
{
// Not from stdin. Read the file to determine the type.
myFilePtr = new InputFile;
// support recovery mode - this conditionally enables a reader
// capable of recovering from bad BGZF compression blocks.
myFilePtr->setAttemptRecovery(myAttemptRecovery);
bool rc = myFilePtr->openFile(filename, "rb", InputFile::DEFAULT);
if (rc == false)
{
std::string errorMessage = "Failed to Open ";
errorMessage += filename;
errorMessage += " for reading";
myStatus.setStatus(SamStatus::FAIL_IO, errorMessage.c_str());
delete myFilePtr;
myFilePtr = NULL;
return(false);
}
char magic[4];
ifread(myFilePtr, magic, 4);
if (magic[0] == 'B' && magic[1] == 'A' && magic[2] == 'M' &&
magic[3] == 1)
{
myInterfacePtr = new BamInterface;
// Set that it is a bam file open for reading. This is needed to
// determine if an index file can be used.
myIsBamOpenForRead = true;
}
else
{
// Not a bam, so rewind to the beginning of the file so it
// can be read.
ifrewind(myFilePtr);
myInterfacePtr = new SamInterface;
}
}
// File is open for reading.
myIsOpenForRead = true;
// Read the header if one was passed in.
if(header != NULL)
{
return(ReadHeader(*header));
}
// Successfully opened the file.
myStatus = SamStatus::SUCCESS;
return(true);
}
// Open a sam/bam file for writing with the specified filename.
bool SamFile::OpenForWrite(const char * filename, SamFileHeader* header)
{
// Reset for any previously operated on files.
resetFile();
int lastchar = 0;
while (filename[lastchar] != 0) lastchar++;
if (lastchar >= 4 &&
filename[lastchar - 4] == 'u' &&
filename[lastchar - 3] == 'b' &&
filename[lastchar - 2] == 'a' &&
filename[lastchar - 1] == 'm')
{
// BAM File.
// if -.ubam is the filename, write uncompressed bam to stdout
if((lastchar == 6) && (filename[0] == '-') && (filename[1] == '.'))
{
filename = "-";
}
myFilePtr = ifopen(filename, "wb0", InputFile::BGZF);
myInterfacePtr = new BamInterface;
}
else if (lastchar >= 3 &&
filename[lastchar - 3] == 'b' &&
filename[lastchar - 2] == 'a' &&
filename[lastchar - 1] == 'm')
{
// BAM File.
// if -.bam is the filename, write compressed bam to stdout
if((lastchar == 5) && (filename[0] == '-') && (filename[1] == '.'))
{
filename = "-";
}
myFilePtr = ifopen(filename, "wb", InputFile::BGZF);
myInterfacePtr = new BamInterface;
}
else
{
// SAM File
// if - (followed by anything is the filename,
// write uncompressed sam to stdout
if((lastchar >= 1) && (filename[0] == '-'))
{
filename = "-";
}
myFilePtr = ifopen(filename, "wb", InputFile::UNCOMPRESSED);
myInterfacePtr = new SamInterface;
}
if (myFilePtr == NULL)
{
std::string errorMessage = "Failed to Open ";
errorMessage += filename;
errorMessage += " for writing";
myStatus.setStatus(SamStatus::FAIL_IO, errorMessage.c_str());
return(false);
}
myIsOpenForWrite = true;
// Write the header if one was passed in.
if(header != NULL)
{
return(WriteHeader(*header));
}
// Successfully opened the file.
myStatus = SamStatus::SUCCESS;
return(true);
}
// Read BAM Index file.
bool SamFile::ReadBamIndex(const char* bamIndexFilename)
{
// Cleanup a previously setup index.
if(myBamIndex != NULL)
{
delete myBamIndex;
myBamIndex = NULL;
}
// Create a new bam index.
myBamIndex = new BamIndex();
SamStatus::Status indexStat = myBamIndex->readIndex(bamIndexFilename);
if(indexStat != SamStatus::SUCCESS)
{
std::string errorMessage = "Failed to read the bam Index file: ";
errorMessage += bamIndexFilename;
myStatus.setStatus(indexStat, errorMessage.c_str());
delete myBamIndex;
myBamIndex = NULL;
return(false);
}
myStatus = SamStatus::SUCCESS;
return(true);
}
// Read BAM Index file.
bool SamFile::ReadBamIndex()
{
if(myFilePtr == NULL)
{
// Can't read the bam index file because the BAM file has not yet been
// opened, so we don't know the base filename for the index file.
std::string errorMessage = "Failed to read the bam Index file -"
" the BAM file needs to be read first in order to determine"
" the index filename.";
myStatus.setStatus(SamStatus::FAIL_ORDER, errorMessage.c_str());
return(false);
}
const char* bamBaseName = myFilePtr->getFileName();
std::string indexName = bamBaseName;
indexName += ".bai";
bool foundFile = true;
try
{
if(ReadBamIndex(indexName.c_str()) == false)
{
foundFile = false;
}
}
catch (std::exception&)
{
foundFile = false;
}
// Check to see if the index file was found.
if(!foundFile)
{
// Not found - try without the bam extension.
// Locate the start of the bam extension
size_t startExt = indexName.find(".bam");
if(startExt == std::string::npos)
{
// Could not find the .bam extension, so just return false since the
// call to ReadBamIndex set the status.
return(false);
}
// Remove ".bam" and try reading the index again.
indexName.erase(startExt, 4);
return(ReadBamIndex(indexName.c_str()));
}
return(true);
}
// Sets the reference to the specified genome sequence object.
void SamFile::SetReference(GenomeSequence* reference)
{
myRefPtr = reference;
}
// Set the type of sequence translation to use when reading the sequence.
void SamFile::SetReadSequenceTranslation(SamRecord::SequenceTranslation translation)
{
myReadTranslation = translation;
}
// Set the type of sequence translation to use when writing the sequence.
void SamFile::SetWriteSequenceTranslation(SamRecord::SequenceTranslation translation)
{
myWriteTranslation = translation;
}
// Close the file if there is one open.
void SamFile::Close()
{
// Resetting the file will close it if it is open, and
// will reset all other variables.
resetFile();
}
// Returns whether or not the file has been opened.
// return: int - true = open; false = not open.
bool SamFile::IsOpen()
{
if (myFilePtr != NULL)
{
// File Pointer is set, so return if it is open.
return(myFilePtr->isOpen());
}
// File pointer is not set, so return false, not open.
return false;
}
// Returns whether or not the end of the file has been reached.
// return: int - true = EOF; false = not eof.
bool SamFile::IsEOF()
{
if (myFilePtr != NULL)
{
// File Pointer is set, so return if eof.
return(ifeof(myFilePtr));
}
// File pointer is not set, so return true, eof.
return true;
}
// Read the header from the currently opened file.
bool SamFile::ReadHeader(SamFileHeader& header)
{
myStatus = SamStatus::SUCCESS;
if(myIsOpenForRead == false)
{
// File is not open for read
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot read header since the file is not open for reading");
return(false);
}
if(myHasHeader == true)
{
// The header has already been read.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot read header since it has already been read.");
return(false);
}
if(myInterfacePtr->readHeader(myFilePtr, header, myStatus))
{
// The header has now been successfully read.
myHasHeader = true;
return(true);
}
return(false);
}
// Write the header to the currently opened file.
bool SamFile::WriteHeader(SamFileHeader& header)
{
myStatus = SamStatus::SUCCESS;
if(myIsOpenForWrite == false)
{
// File is not open for write
// -OR-
// The header has already been written.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot write header since the file is not open for writing");
return(false);
}
if(myHasHeader == true)
{
// The header has already been written.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot write header since it has already been written");
return(false);
}
if(myInterfacePtr->writeHeader(myFilePtr, header, myStatus))
{
// The header has now been successfully written.
myHasHeader = true;
return(true);
}
// return the status.
return(false);
}
// Read a record from the currently opened file.
bool SamFile::ReadRecord(SamFileHeader& header,
SamRecord& record)
{
myStatus = SamStatus::SUCCESS;
if(myIsOpenForRead == false)
{
// File is not open for read
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot read record since the file is not open for reading");
throw(std::runtime_error("SOFTWARE BUG: trying to read a SAM/BAM record prior to opening the file."));
return(false);
}
if(myHasHeader == false)
{
// The header has not yet been read.
// TODO - maybe just read the header.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot read record since the header has not been read.");
throw(std::runtime_error("SOFTWARE BUG: trying to read a SAM/BAM record prior to reading the header."));
return(false);
}
// Check to see if a new region has been set. If so, determine the
// chunks for that region.
if(myNewSection)
{
if(!processNewSection(header))
{
// Failed processing a new section. Could be an
// order issue like the file not being open or the
// indexed file not having been read.
// processNewSection sets myStatus with the failure reason.
return(false);
}
}
// Read until a record is not successfully read or there are no more
// requested records.
while(myStatus == SamStatus::SUCCESS)
{
record.setReference(myRefPtr);
record.setSequenceTranslation(myReadTranslation);
// If reading by index, this method will setup to ensure it is in
// the correct position for the next record (if not already there).
// Sets myStatus if it could not move to a good section.
// Just returns true if it is not setup to read by index.
if(!ensureIndexedReadPosition())
{
// Either there are no more records in the section
// or it failed to move to the right section, so there
// is nothing more to read, stop looping.
break;
}
// File is open for reading and the header has been read, so read the
// next record.
myInterfacePtr->readRecord(myFilePtr, header, record, myStatus);
if(myStatus != SamStatus::SUCCESS)
{
// Failed to read the record, so break out of the loop.
break;
}
// Successfully read a record, so check if we should filter it.
// First check if it is out of the section. Returns true
// if not reading by sections, returns false if the record
// is outside of the section. Sets status to NO_MORE_RECS if
// there is nothing left ot read in the section.
if(!checkRecordInSection(record))
{
// The record is not in the section.
// The while loop will detect if NO_MORE_RECS was set.
continue;
}
// Check the flag for required/excluded flags.
uint16_t flag = record.getFlag();
if((flag & myRequiredFlags) != myRequiredFlags)
{
// The record does not conatain all required flags, so
// continue looking.
continue;
}
if((flag & myExcludedFlags) != 0)
{
// The record contains an excluded flag, so continue looking.
continue;
}
//increment the record count.
myRecordCount++;
if(myStatistics != NULL)
{
// Statistics should be updated.
myStatistics->updateStatistics(record);
}
// Successfully read the record, so check the sort order.
if(!validateSortOrder(record, header))
{
// ValidateSortOrder sets the status on a failure.
return(false);
}
return(true);
} // End while loop that checks if a desired record is found or failure.
// Return true if a record was found.
return(myStatus == SamStatus::SUCCESS);
}
// Write a record to the currently opened file.
bool SamFile::WriteRecord(SamFileHeader& header,
SamRecord& record)
{
if(myIsOpenForWrite == false)
{
// File is not open for writing
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot write record since the file is not open for writing");
return(false);
}
if(myHasHeader == false)
{
// The header has not yet been written.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot write record since the header has not been written");
return(false);
}
// Before trying to write the record, validate the sort order.
if(!validateSortOrder(record, header))
{
// Not sorted like it is supposed to be, do not write the record
myStatus.setStatus(SamStatus::INVALID_SORT,
"Cannot write the record since the file is not properly sorted.");
return(false);
}
if(myRefPtr != NULL)
{
record.setReference(myRefPtr);
}
// File is open for writing and the header has been written, so write the
// record.
myStatus = myInterfacePtr->writeRecord(myFilePtr, header, record,
myWriteTranslation);
if(myStatus == SamStatus::SUCCESS)
{
// A record was successfully written, so increment the record count.
myRecordCount++;
return(true);
}
return(false);
}
// Set the flag to validate that the file is sorted as it is read/written.
// Must be called after the file has been opened.
void SamFile::setSortedValidation(SortedType sortType)
{
mySortedType = sortType;
}
// Return the number of records that have been read/written so far.
uint32_t SamFile::GetCurrentRecordCount()
{
return(myRecordCount);
}
// Sets what part of the SamFile should be read.
bool SamFile::SetReadSection(int32_t refID)
{
// No start/end specified, so set back to default -1.
return(SetReadSection(refID, -1, -1));
}
// Sets what part of the SamFile should be read.
bool SamFile::SetReadSection(const char* refName)
{
// No start/end specified, so set back to default -1.
return(SetReadSection(refName, -1, -1));
}
// Sets what part of the BAM file should be read.
bool SamFile::SetReadSection(int32_t refID, int32_t start, int32_t end,
bool overlap)
{
// If there is not a BAM file open for reading, return failure.
// Opening a new file clears the read section, so it must be
// set after the file is opened.
if(!myIsBamOpenForRead)
{
// There is not a BAM file open for reading.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot set section since there is no bam file open");
return(false);
}
myNewSection = true;
myOverlapSection = overlap;
myStartPos = start;
myEndPos = end;
myRefID = refID;
myRefName.clear();
myChunksToRead.clear();
// Reset the end of the current chunk. We are resetting our read, so
// we no longer have a "current chunk" that we are reading.
myCurrentChunkEnd = 0;
myStatus = SamStatus::SUCCESS;
// Reset the sort order criteria since we moved around in the file.
myPrevCoord = -1;
myPrevRefID = 0;
myPrevReadName.Clear();
return(true);
}
// Sets what part of the BAM file should be read.
bool SamFile::SetReadSection(const char* refName, int32_t start, int32_t end,
bool overlap)
{
// If there is not a BAM file open for reading, return failure.
// Opening a new file clears the read section, so it must be
// set after the file is opened.
if(!myIsBamOpenForRead)
{
// There is not a BAM file open for reading.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot set section since there is no bam file open");
return(false);
}
myNewSection = true;
myOverlapSection = overlap;
myStartPos = start;
myEndPos = end;
if((strcmp(refName, "") == 0) || (strcmp(refName, "*") == 0))
{
// No Reference name specified, so read just the "-1" entries.
myRefID = BamIndex::REF_ID_UNMAPPED;
}
else
{
// save the reference name and revert the reference ID to unknown
// so it will be calculated later.
myRefName = refName;
myRefID = BamIndex::REF_ID_ALL;
}
myChunksToRead.clear();
// Reset the end of the current chunk. We are resetting our read, so
// we no longer have a "current chunk" that we are reading.
myCurrentChunkEnd = 0;
myStatus = SamStatus::SUCCESS;
// Reset the sort order criteria since we moved around in the file.
myPrevCoord = -1;
myPrevRefID = 0;
myPrevReadName.Clear();
return(true);
}
void SamFile::SetReadFlags(uint16_t requiredFlags, uint16_t excludedFlags)
{
myRequiredFlags = requiredFlags;
myExcludedFlags = excludedFlags;
}
// Get the number of mapped reads in the specified reference id.
// Returns -1 for out of range refIDs.
int32_t SamFile::getNumMappedReadsFromIndex(int32_t refID)
{
// The bam index must have already been read.
if(myBamIndex == NULL)
{
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot get num mapped reads from the index until it has been read.");
return(false);
}
return(myBamIndex->getNumMappedReads(refID));
}
// Get the number of unmapped reads in the specified reference id.
// Returns -1 for out of range refIDs.
int32_t SamFile::getNumUnMappedReadsFromIndex(int32_t refID)
{
// The bam index must have already been read.
if(myBamIndex == NULL)
{
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot get num unmapped reads from the index until it has been read.");
return(false);
}
return(myBamIndex->getNumUnMappedReads(refID));
}
// Get the number of mapped reads in the specified reference id.
// Returns -1 for out of range references.
int32_t SamFile::getNumMappedReadsFromIndex(const char* refName,
SamFileHeader& header)
{
// The bam index must have already been read.
if(myBamIndex == NULL)
{
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot get num mapped reads from the index until it has been read.");
return(false);
}
int32_t refID = BamIndex::REF_ID_UNMAPPED;
if((strcmp(refName, "") != 0) && (strcmp(refName, "*") != 0))
{
// Reference name specified, so read just the "-1" entries.
refID = header.getReferenceID(refName);
}
return(myBamIndex->getNumMappedReads(refID));
}
// Get the number of unmapped reads in the specified reference id.
// Returns -1 for out of range refIDs.
int32_t SamFile::getNumUnMappedReadsFromIndex(const char* refName,
SamFileHeader& header)
{
// The bam index must have already been read.
if(myBamIndex == NULL)
{
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot get num unmapped reads from the index until it has been read.");
return(false);
}
int32_t refID = BamIndex::REF_ID_UNMAPPED;
if((strcmp(refName, "") != 0) && (strcmp(refName, "*") != 0))
{
// Reference name specified, so read just the "-1" entries.
refID = header.getReferenceID(refName);
}
return(myBamIndex->getNumUnMappedReads(refID));
}
// Returns the number of bases in the passed in read that overlap the
// region that is currently set.
uint32_t SamFile::GetNumOverlaps(SamRecord& samRecord)
{
if(myRefPtr != NULL)
{
samRecord.setReference(myRefPtr);
}
samRecord.setSequenceTranslation(myReadTranslation);
// Get the overlaps in the sam record for the region currently set
// for this file.
return(samRecord.getNumOverlaps(myStartPos, myEndPos));
}
void SamFile::GenerateStatistics(bool genStats)
{
if(genStats)
{
if(myStatistics == NULL)
{
// Want to generate statistics, but do not yet have the
// structure for them, so create one.
myStatistics = new SamStatistics();
}
}
else
{
// Do not generate statistics, so if myStatistics is not NULL,
// delete it.
if(myStatistics != NULL)
{
delete myStatistics;
myStatistics = NULL;
}
}
}
const BamIndex* SamFile::GetBamIndex()
{
return(myBamIndex);
}
// initialize.
void SamFile::init()
{
myFilePtr = NULL;
myInterfacePtr = NULL;
myStatistics = NULL;
myBamIndex = NULL;
myRefPtr = NULL;
myReadTranslation = SamRecord::NONE;
myWriteTranslation = SamRecord::NONE;
myAttemptRecovery = false;
myRequiredFlags = 0;
myExcludedFlags = 0;
}
void SamFile::init(const char* filename, OpenType mode, SamFileHeader* header)
{
init();
resetFile();
bool openStatus = true;
if(mode == READ)
{
// open the file for read.
openStatus = OpenForRead(filename, header);
}
else
{
// open the file for write.
openStatus = OpenForWrite(filename, header);
}
if(!openStatus)
{
// Failed to open the file - print error and abort.
fprintf(stderr, "%s\n", GetStatusMessage());
std::cerr << "FAILURE - EXITING!!!" << std::endl;
exit(-1);
}
}
// Reset variables for each file.
void SamFile::resetFile()
{
// Close the file.
if (myFilePtr != NULL)
{
// If we already have an open file, close it.
ifclose(myFilePtr);
myFilePtr = NULL;
}
if(myInterfacePtr != NULL)
{
delete myInterfacePtr;
myInterfacePtr = NULL;
}
myIsOpenForRead = false;
myIsOpenForWrite = false;
myHasHeader = false;
mySortedType = UNSORTED;
myPrevReadName.Clear();
myPrevCoord = -1;
myPrevRefID = 0;
myRecordCount = 0;
myStatus = SamStatus::SUCCESS;
// Reset indexed bam values.
myIsBamOpenForRead = false;
myRefID = BamIndex::REF_ID_ALL;
myStartPos = -1;
myEndPos = -1;
myNewSection = false;
myOverlapSection = true;
myCurrentChunkEnd = 0;
myChunksToRead.clear();
if(myBamIndex != NULL)
{
delete myBamIndex;
myBamIndex = NULL;
}
// If statistics are being generated, reset them.
if(myStatistics != NULL)
{
myStatistics->reset();
}
myRefName.clear();
}
// Validate that the record is sorted compared to the previously read record
// if there is one, according to the specified sort order.
// If the sort order is UNSORTED, true is returned.
bool SamFile::validateSortOrder(SamRecord& record, SamFileHeader& header)
{
if(myRefPtr != NULL)
{
record.setReference(myRefPtr);
}
record.setSequenceTranslation(myReadTranslation);
bool status = false;
if(mySortedType == UNSORTED)
{
// Unsorted, so nothing to validate, just return true.
status = true;
}
else
{
// Check to see if mySortedType is based on the header.
if(mySortedType == FLAG)
{
// Determine the sorted type from what was read out of the header.
mySortedType = getSortOrderFromHeader(header);
}
if(mySortedType == QUERY_NAME)
{
// Validate that it is sorted by query name.
// Get the query name from the record.
const char* readName = record.getReadName();
// Check if it is sorted either in samtools way or picard's way.
if((myPrevReadName.Compare(readName) > 0) &&
(strcmp(myPrevReadName.c_str(), readName) > 0))
{
// return false.
String errorMessage = "ERROR: File is not sorted by read name at record ";
errorMessage += myRecordCount;
errorMessage += "\n\tPrevious record was ";
errorMessage += myPrevReadName;
errorMessage += ", but this record is ";
errorMessage += readName;
myStatus.setStatus(SamStatus::INVALID_SORT,
errorMessage.c_str());
status = false;
}
else
{
myPrevReadName = readName;
status = true;
}
}
else
{
// Validate that it is sorted by COORDINATES.
// Get the leftmost coordinate and the reference index.
int32_t refID = record.getReferenceID();
int32_t coord = record.get0BasedPosition();
// The unmapped reference id is at the end of a sorted file.
if(refID == BamIndex::REF_ID_UNMAPPED)
{
// A new reference ID that is for the unmapped reads
// is always valid.
status = true;
myPrevRefID = refID;
myPrevCoord = coord;
}
else if(myPrevRefID == BamIndex::REF_ID_UNMAPPED)
{
// Previous reference ID was for unmapped reads, but the
// current one is not, so this is not sorted.
String errorMessage = "ERROR: File is not coordinate sorted at record ";
errorMessage += myRecordCount;
errorMessage += "\n\tPrevious record was unmapped, but this record is ";
errorMessage += header.getReferenceLabel(refID) + ":" + coord;
myStatus.setStatus(SamStatus::INVALID_SORT,
errorMessage.c_str());
status = false;
}
else if(refID < myPrevRefID)
{
// Current reference id is less than the previous one,
//meaning that it is not sorted.
String errorMessage = "ERROR: File is not coordinate sorted at record ";
errorMessage += myRecordCount;
errorMessage += "\n\tPrevious record was ";
errorMessage += header.getReferenceLabel(myPrevRefID) + ":" + myPrevCoord;
errorMessage += ", but this record is ";
errorMessage += header.getReferenceLabel(refID) + ":" + coord;
myStatus.setStatus(SamStatus::INVALID_SORT,
errorMessage.c_str());
status = false;
}
else
{
// The reference IDs are in the correct order.
if(refID > myPrevRefID)
{
// New reference id, so set the previous coordinate to -1
myPrevCoord = -1;
}
// Check the coordinates.
if(coord < myPrevCoord)
{
// New Coord is less than the previous position.
String errorMessage = "ERROR: File is not coordinate sorted at record ";
errorMessage += myRecordCount;
errorMessage += "\n\tPreviousRecord was ";
errorMessage += header.getReferenceLabel(myPrevRefID) + ":" + myPrevCoord;
errorMessage += ", but this record is ";
errorMessage += header.getReferenceLabel(refID) + ":" + coord;
myStatus.setStatus(SamStatus::INVALID_SORT,
errorMessage.c_str());
status = false;
}
else
{
myPrevRefID = refID;
myPrevCoord = coord;
status = true;
}
}
}
}
return(status);
}
SamFile::SortedType SamFile::getSortOrderFromHeader(SamFileHeader& header)
{
const char* tag = header.getSortOrder();
// Default to unsorted since if it is not specified in the header
// that is the value that should be used.
SortedType headerSortOrder = UNSORTED;
if(strcmp(tag, "queryname") == 0)
{
headerSortOrder = QUERY_NAME;
}
else if(strcmp(tag, "coordinate") == 0)
{
headerSortOrder = COORDINATE;
}
return(headerSortOrder);
}
bool SamFile::ensureIndexedReadPosition()
{
// If no sections are specified, return true.
if(myRefID == BamIndex::REF_ID_ALL)
{
return(true);
}
// Check to see if we have more to read out of the current chunk.
// By checking the current position in relation to the current
// end chunk. If the current position is >= the end of the
// current chunk, then we must see to the next chunk.
uint64_t currentPos = iftell(myFilePtr);
if(currentPos >= myCurrentChunkEnd)
{
// If there are no more chunks to process, return failure.
if(myChunksToRead.empty())
{
myStatus = SamStatus::NO_MORE_RECS;
return(false);
}
// There are more chunks left, so get the next chunk.
Chunk newChunk = myChunksToRead.pop();
// Move to the location of the new chunk if it is not adjacent
// to the current chunk.
if(newChunk.chunk_beg != currentPos)
{
// New chunk is not adjacent, so move to it.
if(ifseek(myFilePtr, newChunk.chunk_beg, SEEK_SET) != true)
{
// seek failed, cannot retrieve next record, return failure.
myStatus.setStatus(SamStatus::FAIL_IO,
"Failed to seek to the next record");
return(false);
}
}
// Seek succeeded, set the end of the new chunk.
myCurrentChunkEnd = newChunk.chunk_end;
}
return(true);
}
bool SamFile::checkRecordInSection(SamRecord& record)
{
bool recordFound = true;
if(myRefID == BamIndex::REF_ID_ALL)
{
return(true);
}
// Check to see if it is in the correct reference/position.
if(record.getReferenceID() != myRefID)
{
// Incorrect reference ID, return no more records.
myStatus = SamStatus::NO_MORE_RECS;
return(false);
}
// Found a record.
recordFound = true;
// If start/end position are set, verify that the alignment falls
// within those.
// If the alignment start is greater than the end of the region,
// return NO_MORE_RECS.
// Since myEndPos is Exclusive 0-based, anything >= myEndPos is outside
// of the region.
if((myEndPos != -1) && (record.get0BasedPosition() >= myEndPos))
{
myStatus = SamStatus::NO_MORE_RECS;
return(false);
}
// We know the start is less than the end position, so the alignment
// overlaps the region if the alignment end position is greater than the
// start of the region.
if((myStartPos != -1) && (record.get0BasedAlignmentEnd() < myStartPos))
{
// If it does not overlap the region, so go to the next
// record...set recordFound back to false.
recordFound = false;
}
if(!myOverlapSection)
{
// Needs to be fully contained. Not fully contained if
// 1) the record start position is < the region start position.
// or
// 2) the end position is specified and the record end position
// is greater than or equal to the region end position.
// (equal to since the region is exclusive.
if((record.get0BasedPosition() < myStartPos) ||
((myEndPos != -1) &&
(record.get0BasedAlignmentEnd() >= myEndPos)))
{
// This record is not fully contained, so move on to the next
// record.
recordFound = false;
}
}
return(recordFound);
}
bool SamFile::processNewSection(SamFileHeader &header)
{
myNewSection = false;
// If there is no index file, return failure.
if(myBamIndex == NULL)
{
// No bam index has been read.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot read section since there is no index file open");
throw(std::runtime_error("SOFTWARE BUG: trying to read a BAM record by section prior to opening the BAM Index file."));
return(false);
}
// If there is not a BAM file open for reading, return failure.
if(!myIsBamOpenForRead)
{
// There is not a BAM file open for reading.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot read section since there is no bam file open");
throw(std::runtime_error("SOFTWARE BUG: trying to read a BAM record by section without opening a BAM file."));
return(false);
}
if(myHasHeader == false)
{
// The header has not yet been read.
myStatus.setStatus(SamStatus::FAIL_ORDER,
"Cannot read record since the header has not been read.");
throw(std::runtime_error("SOFTWARE BUG: trying to read a BAM record by section prior to opening the header."));
return(false);
}
// Indexed Bam open for read, so disable read buffering because iftell
// will be used.
// Needs to be done here after we already know that the header has been
// read.
myFilePtr->disableBuffering();
myChunksToRead.clear();
// Reset the end of the current chunk. We are resetting our read, so
// we no longer have a "current chunk" that we are reading.
myCurrentChunkEnd = 0;
// Check to see if the read section was set based on the reference name
// but not yet converted to reference id.
if(!myRefName.empty())
{
myRefID = header.getReferenceID(myRefName.c_str());
// Clear the myRefName length so this code is only executed once.
myRefName.clear();
// Check to see if a reference id was found.
if(myRefID == SamReferenceInfo::NO_REF_ID)
{
myStatus = SamStatus::NO_MORE_RECS;
return(false);
}
}
// Get the chunks associated with this reference region.
if(myBamIndex->getChunksForRegion(myRefID, myStartPos, myEndPos,
myChunksToRead) == true)
{
myStatus = SamStatus::SUCCESS;
}
else
{
String errorMsg = "Failed to get the specified region, refID = ";
errorMsg += myRefID;
errorMsg += "; startPos = ";
errorMsg += myStartPos;
errorMsg += "; endPos = ";
errorMsg += myEndPos;
myStatus.setStatus(SamStatus::FAIL_PARSE,
errorMsg);
}
return(true);
}
//
// When the caller to SamFile::ReadRecord() catches an
// exception, it may choose to call this method to resync
// on the underlying binary stream.
//
// Arguments: a callback function that will requires length bytes
// of data to validate a record header.
//
// The expected use case is to re-sync on the next probably valid
// BAM record, so that we can resume reading even after detecting
// a corrupted BAM file.
//
bool SamFile::attemptRecoverySync(bool (*checkSignature)(void *data) , int length)
{
if(myFilePtr==NULL) return false;
// non-recovery aware objects will just return false:
return myFilePtr->attemptRecoverySync(checkSignature, length);
}
// Default Constructor.
SamFileReader::SamFileReader()
: SamFile()
{
}
// Constructor that opens the specified file for read.
SamFileReader::SamFileReader(const char* filename)
: SamFile(filename, READ)
{
}
// Constructor that opens the specified file for read.
SamFileReader::SamFileReader(const char* filename,
ErrorHandler::HandlingType errorHandlingType)
: SamFile(filename, READ, errorHandlingType)
{
}
// Constructor that opens the specified file for read.
SamFileReader::SamFileReader(const char* filename,
SamFileHeader* header)
: SamFile(filename, READ, header)
{
}
// Constructor that opens the specified file for read.
SamFileReader::SamFileReader(const char* filename,
ErrorHandler::HandlingType errorHandlingType,
SamFileHeader* header)
: SamFile(filename, READ, errorHandlingType, header)
{
}
SamFileReader::~SamFileReader()
{
}
// Default Constructor.
SamFileWriter::SamFileWriter()
: SamFile()
{
}
// Constructor that opens the specified file for write.
SamFileWriter::SamFileWriter(const char* filename)
: SamFile(filename, WRITE)
{
}
// Constructor that opens the specified file for write.
SamFileWriter::SamFileWriter(const char* filename,
ErrorHandler::HandlingType errorHandlingType)
: SamFile(filename, WRITE, errorHandlingType)
{
}
// Constructor that opens the specified file for write.
SamFileWriter::SamFileWriter(const char* filename,
SamFileHeader* header)
: SamFile(filename, WRITE, header)
{
}
// Constructor that opens the specified file for write.
SamFileWriter::SamFileWriter(const char* filename,
ErrorHandler::HandlingType errorHandlingType,
SamFileHeader* header)
: SamFile(filename, WRITE, errorHandlingType, header)
{
}
SamFileWriter::~SamFileWriter()
{
}
SamFile::myIsOpenForWrite
bool myIsOpenForWrite
Flag to indicate if a file is open for writing.
Definition: SamFile.h:396
BamInterface
Definition: BamInterface.h:23
SamRecord::setSequenceTranslation
void setSequenceTranslation(SequenceTranslation translation)
Set the type of sequence translation to use when getting the sequence.
Definition: SamRecord.cpp:187
SamFile::COORDINATE
file is sorted by coordinate.
Definition: SamFile.h:49
SamRecord::get0BasedPosition
int32_t get0BasedPosition()
Get the 0-based(BAM) leftmost position of the record.
Definition: SamRecord.cpp:1307
BamIndex
Definition: BamIndex.h:31
SamFile::FLAG
SO flag from the header indicates the sort type.
Definition: SamFile.h:48
SamFile::IsEOF
bool IsEOF()
Returns whether or not the end of the file has been reached.
Definition: SamFile.cpp:424
SamRecord::SequenceTranslation
SequenceTranslation
Enum containing the settings on how to translate the sequence if a reference is available.
Definition: SamRecord.h:57
SamRecord::get0BasedAlignmentEnd
int32_t get0BasedAlignmentEnd()
Returns the 0-based inclusive rightmost position of the clipped sequence.
Definition: SamRecord.cpp:1455
SamFile::ReadBamIndex
bool ReadBamIndex()
Read the bam index file using the BAM filename as a base.
Definition: SamFile.cpp:328
InputFile::setAttemptRecovery
void setAttemptRecovery(bool flag=false)
Enable (default) or disable recovery.
Definition: InputFile.h:485
SamFile::myPrevCoord
int32_t myPrevCoord
Previous values used for checking if the file is sorted.
Definition: SamFile.h:404
ifseek
bool ifseek(IFILE file, int64_t offset, int origin)
Seek to the specified position (result from an iftell), but cannot be done for stdin/stdout.
Definition: InputFile.h:701
SamFile::WriteRecord
bool WriteRecord(SamFileHeader &header, SamRecord &record)
Writes the specified record into the file.
Definition: SamFile.cpp:619
SamRecord::getReferenceID
int32_t getReferenceID()
Get the reference sequence id of the record (BAM format rid).
Definition: SamRecord.cpp:1293
String
Definition: StringBasics.h:38
SamFile::READ
open for reading.
Definition: SamFile.h:40
InputFile::DEFAULT
Check the extension, if it is ".gz", treat as gzip, otherwise treat it as UNCOMPRESSED.
Definition: InputFile.h:45
BamIndex::getChunksForRegion
bool getChunksForRegion(int32_t refID, int32_t start, int32_t end, SortedChunkList &chunkList)
Get the list of chunks associated with this region.
Definition: BamIndex.cpp:218
SamFile::GetStatusMessage
const char * GetStatusMessage()
Get the Status Message of the last call that sets status.
Definition: SamFile.h:213
SamFile::myIsOpenForRead
bool myIsOpenForRead
Flag to indicate if a file is open for reading.
Definition: SamFile.h:394
StatGenStatus::NO_MORE_RECS
NO_MORE_RECS: failed to read a record since there are no more to read either in the file or section i...
Definition: StatGenStatus.h:36
SamFile::resetFile
void resetFile()
Resets the file prepping for a new file.
Definition: SamFile.cpp:953
SamFile::getNumUnMappedReadsFromIndex
int32_t getNumUnMappedReadsFromIndex(int32_t refID)
Get the number of unmapped reads in the specified reference id.
Definition: SamFile.cpp:805
GenomeSequence
Create/Access/Modify/Load Genome Sequences stored as binary mapped files.
Definition: GenomeSequence.h:99
SamFile::IsOpen
bool IsOpen()
Returns whether or not the file has been opened successfully.
Definition: SamFile.cpp:410
ifopen
IFILE ifopen(const char *filename, const char *mode, InputFile::ifileCompression compressionMode=InputFile::DEFAULT)
Open a file with the specified name and mode, using a filename of "-" to indicate stdin/stdout.
Definition: InputFile.h:562
BamIndex::getNumMappedReads
int32_t getNumMappedReads(int32_t refID)
Get the number of mapped reads for this reference id.
Definition: BamIndex.cpp:355
SamReferenceInfo::NO_REF_ID
static const int NO_REF_ID
Constant for the value returned if a reference id does not exist for a queried reference name.
Definition: SamReferenceInfo.h:77
SamFile::ReadRecord
bool ReadRecord(SamFileHeader &header, SamRecord &record)
Reads the next record from the file & stores it in the passed in record.
Definition: SamFile.cpp:501
InputFile::UNCOMPRESSED
uncompressed file.
Definition: InputFile.h:46
SamFile::QUERY_NAME
file is sorted by queryname.
Definition: SamFile.h:50
StatGenStatus::SUCCESS
method completed successfully.
Definition: StatGenStatus.h:32
SamFileReader::SamFileReader
SamFileReader()
Default Constructor.
Definition: SamFile.cpp:1360
SamFile::OpenType
OpenType
Enum for indicating whether to open the file for read or write.
Definition: SamFile.h:39
SamFile::GenerateStatistics
void GenerateStatistics(bool genStats)
Whether or not statistics should be generated for this file.
Definition: SamFile.cpp:878
SamFile::getNumMappedReadsFromIndex
int32_t getNumMappedReadsFromIndex(int32_t refID)
Get the number of mapped reads in the specified reference id.
Definition: SamFile.cpp:790
ErrorHandler::HandlingType
HandlingType
This specifies how this class should respond to errors.
Definition: ErrorHandler.h:29
SamFile::SortedType
SortedType
Enum for indicating the type of sort expected in the file.
Definition: SamFile.h:46
SamRecord::getFlag
uint16_t getFlag()
Get the flag (FLAG).
Definition: SamRecord.cpp:1372
InputFile::isOpen
bool isOpen() const
Returns whether or not the file was successfully opened.
Definition: InputFile.h:423
SamFile::myStatistics
SamStatistics * myStatistics
Pointer to the statistics for this file.
Definition: SamFile.h:412
SamFile::myHasHeader
bool myHasHeader
Flag to indicate if a header has been read/written - required before being able to read/write a recor...
Definition: SamFile.h:399
SamFile::SetReadFlags
void SetReadFlags(uint16_t requiredFlags, uint16_t excludedFlags)
Specify which reads should be returned by ReadRecord.
Definition: SamFile.cpp:781
BamIndex::REF_ID_ALL
static const int32_t REF_ID_ALL
The number used to indicate that all reference ids should be used.
Definition: BamIndex.h:89
StatGenStatus::FAIL_PARSE
failed to parse a record/header - invalid format.
Definition: StatGenStatus.h:42
InputFile::getFileName
const char * getFileName() const
Get the filename that is currently opened.
Definition: InputFile.h:473
SamFile::OpenForWrite
bool OpenForWrite(const char *filename, SamFileHeader *header=NULL)
Open a sam/bam file for writing with the specified filename, determining SAM/BAM from the extension (...
Definition: SamFile.cpp:223
StatGenStatus::INVALID_SORT
record is invalid due to it not being sorted.
Definition: StatGenStatus.h:43
ifeof
int ifeof(IFILE file)
Check to see if we have reached the EOF (returns 0 if not EOF).
Definition: InputFile.h:654
BamIndex::getNumUnMappedReads
int32_t getNumUnMappedReads(int32_t refID)
Get the number of unmapped reads for this reference id.
Definition: BamIndex.cpp:377
SamFile::SamFile
SamFile()
Default Constructor, initializes the variables, but does not open any files.
Definition: SamFile.cpp:26
StatGenStatus::setStatus
void setStatus(Status newStatus, const char *newMessage)
Set the status with the specified status enum and message.
Definition: StatGenStatus.cpp:83
SamFile::myRecordCount
uint32_t myRecordCount
Keep a count of the number of records that have been read/written so far.
Definition: SamFile.h:409
SamRecord::getReadName
const char * getReadName()
Returns the SAM formatted Read Name (QNAME).
Definition: SamRecord.cpp:1530
StatGenStatus::Status
Status
Return value enum for StatGenFile methods.
Definition: StatGenStatus.h:31
ifrewind
void ifrewind(IFILE file)
Reset to the beginning of the file (cannot be done for stdin/stdout).
Definition: InputFile.h:642
SamFileHeader::getReferenceLabel
const String & getReferenceLabel(int id) const
Return the reference name (chromosome) for the specified reference id.
Definition: SamFileHeader.cpp:158
ifread
unsigned int ifread(IFILE file, void *buffer, unsigned int size)
Read up to size bytes from the file into the buffer.
Definition: InputFile.h:600
SamFile::myIsBamOpenForRead
bool myIsBamOpenForRead
Values for reading Sorted BAM files via the index.
Definition: SamFile.h:418
SamFile::SetReadSection
bool SetReadSection(int32_t refID)
Sets which reference id (index into the BAM list of reference information) of the BAM file should be ...
Definition: SamFile.cpp:683
SamFileHeader
This class allows a user to get/set the fields in a SAM/BAM Header.
Definition: SamFileHeader.h:34
SamFile::UNSORTED
file is not sorted.
Definition: SamFile.h:47
SamFileHeader::getSortOrder
const char * getSortOrder()
Return the Sort Order value that is set in the Header, returning "" if this field does not exist.
Definition: SamFileHeader.cpp:797
SamFile::setSortedValidation
void setSortedValidation(SortedType sortType)
Set the flag to validate that the file is sorted as it is read/written.
Definition: SamFile.cpp:669
SamRecord
Class providing an easy to use interface to get/set/operate on the fields in a SAM/BAM record.
Definition: SamRecord.h:51
SamFile::~SamFile
virtual ~SamFile()
Destructor.
Definition: SamFile.cpp:82
SamFile::OpenForRead
bool OpenForRead(const char *filename, SamFileHeader *header=NULL)
Open a sam/bam file for reading with the specified filename, determing the type of file and SAM/BAM b...
Definition: SamFile.cpp:93
SamStatistics
Definition: SamStatistics.h:24
SamFile::WriteHeader
bool WriteHeader(SamFileHeader &header)
Writes the specified header into the file.
Definition: SamFile.cpp:467
SamFile::GetNumOverlaps
uint32_t GetNumOverlaps(SamRecord &samRecord)
Returns the number of bases in the passed in read that overlap the region that is currently set.
Definition: SamFile.cpp:864
SamInterface
Definition: SamInterface.h:23
InputFile
Class for easily reading/writing files without having to worry about file type (uncompressed,...
Definition: InputFile.h:36
StatGenStatus::FAIL_IO
method failed due to an I/O issue.
Definition: StatGenStatus.h:37
SamRecord::getNumOverlaps
uint32_t getNumOverlaps(int32_t start, int32_t end)
Return the number of bases in this read that overlap the passed in region.
Definition: SamRecord.cpp:1841
SamFile::GetCurrentRecordCount
uint32_t GetCurrentRecordCount()
Return the number of records that have been read/written so far.
Definition: SamFile.cpp:676
StatGenStatus::FAIL_ORDER
FAIL_ORDER: method failed because it was called out of order, like trying to read a file without open...
Definition: StatGenStatus.h:41
SamFileWriter::SamFileWriter
SamFileWriter()
Default Constructor.
Definition: SamFile.cpp:1406
Chunk
Definition: IndexBase.h:30
SamFile::ReadHeader
bool ReadHeader(SamFileHeader &header)
Reads the header section from the file and stores it in the passed in header.
Definition: SamFile.cpp:437
SamRecord::NONE
Leave the sequence as is.
Definition: SamRecord.h:58
SamFile::SetReadSequenceTranslation
void SetReadSequenceTranslation(SamRecord::SequenceTranslation translation)
Set the type of sequence translation to use when reading the sequence.
Definition: SamFile.cpp:387
SamFileHeader::getReferenceID
int getReferenceID(const String &referenceName, bool addID=false)
Get the reference ID for the specified reference name (chromosome).
Definition: SamFileHeader.cpp:146
InputFile::disableBuffering
void disableBuffering()
Disable read buffering.
Definition: InputFile.h:121
SamFile::GetBamIndex
const BamIndex * GetBamIndex()
Return the bam index if one has been opened.
Definition: SamFile.cpp:903
SamFile::Close
void Close()
Close the file if there is one open.
Definition: SamFile.cpp:400
SamFile::validateSortOrder
bool validateSortOrder(SamRecord &record, SamFileHeader &header)
Validate that the record is sorted compared to the previously read record if there is one,...
Definition: SamFile.cpp:1006
SamRecord::setReference
void setReference(GenomeSequence *reference)
Set the reference to the specified genome sequence object.
Definition: SamRecord.cpp:178
SamFile
Allows the user to easily read/write a SAM/BAM file.
Definition: SamFile.h:35
SamFile::SetReference
void SetReference(GenomeSequence *reference)
Sets the reference to the specified genome sequence object.
Definition: SamFile.cpp:380
BamIndex::readIndex
SamStatus::Status readIndex(const char *filename)
Definition: BamIndex.cpp:45
ifclose
int ifclose(IFILE &file)
Close the file.
Definition: InputFile.h:580
SamFile::SetWriteSequenceTranslation
void SetWriteSequenceTranslation(SamRecord::SequenceTranslation translation)
Set the type of sequence translation to use when writing the sequence.
Definition: SamFile.cpp:394
InputFile::BGZF
bgzf file.
Definition: InputFile.h:48
SamFile::myStatus
SamStatus myStatus
The status of the last SamFile command.
Definition: SamFile.h:415
iftell
int64_t iftell(IFILE file)
Get current position in the file.
Definition: InputFile.h:682
BamIndex::REF_ID_UNMAPPED
static const int32_t REF_ID_UNMAPPED
The number used for the reference id of unmapped reads.
Definition: BamIndex.h:86