// Marth Lab, Department of Biology, Boston College
// All rights reserved.
// ---------------------------------------------------------------------------
-// Last modified: 22 November 2010 (DB)
+// Last modified: 23 March 2011 (DB)
// ---------------------------------------------------------------------------
// Provides index functionality - both for the default (standardized) BAM
// index format (.bai) as well as a BamTools-specific (nonstandard) index
#include <api/BamIndex.h>
#include <api/BamReader.h>
-#include <api/BGZF.h>
#include <api/internal/BamStandardIndex_p.h>
#include <api/internal/BamToolsIndex_p.h>
using namespace BamTools;
#include <map>
using namespace std;
-// --------------------------------------------------
-// BamIndex factory methods
-
-// returns index based on BAM filename 'stub'
-// checks first for preferred type, returns that type if found
-// (if not found, attmempts to load other type(s), returns 0 if NONE found)
-//
-// ** default preferred type is BamToolsIndex ** use this anytime it exists
-BamIndex* BamIndex::FromBamFilename(const std::string& bamFilename,
- BamTools::BgzfData* bgzf,
- BamTools::BamReader* reader,
- const BamIndex::PreferredIndexType& type)
-{
- // ---------------------------------------------------
- // attempt to load preferred type first
-
- const std::string bamtoolsIndexFilename = bamFilename + ".bti";
- const bool bamtoolsIndexExists = BamTools::FileExists(bamtoolsIndexFilename);
- if ( (type == BamIndex::BAMTOOLS) && bamtoolsIndexExists )
- return new BamToolsIndex(bgzf, reader);
-
- const std::string standardIndexFilename = bamFilename + ".bai";
- const bool standardIndexExists = BamTools::FileExists(standardIndexFilename);
- if ( (type == BamIndex::STANDARD) && standardIndexExists )
- return new BamStandardIndex(bgzf, reader);
-
- // ----------------------------------------------------
- // preferred type could not be found, try other (non-preferred) types
- // if none found, return 0
-
- if ( bamtoolsIndexExists ) return new BamToolsIndex(bgzf, reader);
- if ( standardIndexExists ) return new BamStandardIndex(bgzf, reader);
- return 0;
-}
-
-// returns index based on explicitly named index file (or 0 if not found)
-BamIndex* BamIndex::FromIndexFilename(const std::string& indexFilename,
- BamTools::BgzfData* bgzf,
- BamTools::BamReader* reader)
-{
- // see if specified file exists
- const bool indexExists = BamTools::FileExists(indexFilename);
- if ( !indexExists ) return 0;
+/*! \class BamTools::BamIndex
+ \brief Provides methods for generating & loading BAM index files.
- const std::string bamtoolsIndexExtension(".bti");
- const std::string standardIndexExtension(".bai");
+ This class straddles the line between public API and internal
+ implementation detail. Most client code should never have to use this
+ class directly.
- // if has bamtoolsIndexExtension
- if ( indexFilename.find(bamtoolsIndexExtension) == (indexFilename.length() - bamtoolsIndexExtension.length()) )
- return new BamToolsIndex(bgzf, reader);
+ It is exposed to the public API to allow advanced users to implement
+ their own custom indexing schemes.
- // if has standardIndexExtension
- if ( indexFilename.find(standardIndexExtension) == (indexFilename.length() - standardIndexExtension.length()) )
- return new BamStandardIndex(bgzf, reader);
-
- // otherwise, unsupported file type
- return 0;
-}
-
-// -------------------------------
-// BamIndex implementation
+ N.B. - Please note that if you wish to derive your own subclass, you are
+ entering waters that are not well-documented at the moment and are
+ likely to be changing soon anyway. Implementing a custom index is
+ technically do-able at the moment, but the learning curve is (at the
+ moment) overly steep. Changes will be coming soon to alleviate some
+ of this headache.
+*/
// ctor
-BamIndex::BamIndex(BamTools::BgzfData* bgzf, BamTools::BamReader* reader)
- : m_BGZF(bgzf)
- , m_reader(reader)
+BamIndex::BamIndex(void)
+ : m_indexStream(0)
+ , m_indexFilename("")
, m_cacheMode(BamIndex::LimitedIndexCaching)
- , m_indexStream(0)
-{
- if ( m_reader && m_reader->IsOpen() )
- m_references = m_reader->GetReferenceData();
-}
+{ }
// dtor
BamIndex::~BamIndex(void) {
- if ( IsOpen() )
- fclose(m_indexStream);
+ if ( IsOpen() ) fclose(m_indexStream);
+ m_indexFilename = "";
}
// return true if FILE* is open
// open index file, abort on error
if ( !OpenIndexFile(filename, "rb") ) {
- fprintf(stderr, "ERROR: Unable to open the BAM index file %s for reading.\n", filename.c_str());
+ fprintf(stderr, "BamIndex ERROR: unable to open the BAM index file %s for reading.\n", filename.c_str());
return false;
}
// opens index file for reading/writing, return true if opened OK
bool BamIndex::OpenIndexFile(const string& filename, const string& mode) {
+
+ // attempt to open file, return false if error
m_indexStream = fopen(filename.c_str(), mode.c_str());
- return ( m_indexStream != 0 );
+ if ( m_indexStream == 0 ) return false;
+
+ // otherwise save filename & return sucess
+ m_indexFilename = filename;
+ return true;
}
// rewind index file to beginning of index data, return true if rewound OK
}
// change the index caching behavior
-void BamIndex::SetCacheMode(const BamIndexCacheMode mode) {
+void BamIndex::SetCacheMode(const BamIndex::IndexCacheMode& mode) {
if ( mode != m_cacheMode ) {
m_cacheMode = mode;
UpdateCache();
LoadFirstReference(true);
}
break;
+
case(BamIndex::NoIndexCaching) :
ClearAllData();
break;
+
default :
// unreachable
;
// open index file for writing
string indexFilename = bamFilename + Extension();
if ( !OpenIndexFile(indexFilename, "wb") ) {
- fprintf(stderr, "ERROR: Could not open file to save index.\n");
+ fprintf(stderr, "BamIndex ERROR: could not open file to save index data.\n");
return false;
}
// write index header data
if ( !WriteHeader() ) {
- fprintf(stderr, "ERROR: There was a problem writing index metadata to new index file.\n");
+ fprintf(stderr, "BamIndex ERROR: there was a problem writing index metadata to the new index file.\n");
fflush(m_indexStream);
fclose(m_indexStream);
exit(1);
// write main index data
if ( !WriteAllReferences() ) {
- fprintf(stderr, "ERROR: There was a problem writing index data to new index file.\n");
+ fprintf(stderr, "BamIndex ERROR: there was a problem writing index data to the new index file.\n");
fflush(m_indexStream);
fclose(m_indexStream);
exit(1);
}
- // flush any remaining output, rewind file, and return success
+ // flush any remaining output
fflush(m_indexStream);
fclose(m_indexStream);
// re-open index file for later reading
if ( !OpenIndexFile(indexFilename, "rb") ) {
- fprintf(stderr, "ERROR: Could not open newly created index file for reading.\n");
+ fprintf(stderr, "BamIndex ERROR: could not open newly created index file for reading.\n");
return false;
}
- // return success/failure of write
+ // save index filename & return success
+ m_indexFilename = indexFilename;
return true;
}