1 // ***************************************************************************
2 // BamIndex.cpp (c) 2009 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // All rights reserved.
5 // ---------------------------------------------------------------------------
6 // Last modified: 23 March 2011 (DB)
7 // ---------------------------------------------------------------------------
8 // Provides index functionality - both for the default (standardized) BAM
9 // index format (.bai) as well as a BamTools-specific (nonstandard) index
11 // ***************************************************************************
13 #include <api/BamIndex.h>
14 #include <api/BamReader.h>
15 #include <api/internal/BamStandardIndex_p.h>
16 #include <api/internal/BamToolsIndex_p.h>
17 using namespace BamTools;
18 using namespace BamTools::Internal;
27 /*! \class BamTools::BamIndex
28 \brief Provides methods for generating & loading BAM index files.
30 This class straddles the line between public API and internal
31 implementation detail. Most client code should never have to use this
34 It is exposed to the public API to allow advanced users to implement
35 their own custom indexing schemes.
37 N.B. - Please note that if you wish to derive your own subclass, you are
38 entering waters that are not well-documented at the moment and are
39 likely to be changing soon anyway. Implementing a custom index is
40 technically do-able at the moment, but the learning curve is (at the
41 moment) overly steep. Changes will be coming soon to alleviate some
46 BamIndex::BamIndex(void)
49 , m_cacheMode(BamIndex::LimitedIndexCaching)
53 BamIndex::~BamIndex(void) {
54 if ( IsOpen() ) fclose(m_indexStream);
58 // return true if FILE* is open
59 bool BamIndex::IsOpen(void) const {
60 return ( m_indexStream != 0 );
63 // loads existing data from file into memory
64 bool BamIndex::Load(const string& filename) {
66 // open index file, abort on error
67 if ( !OpenIndexFile(filename, "rb") ) {
68 fprintf(stderr, "BamIndex ERROR: unable to open the BAM index file %s for reading.\n", filename.c_str());
73 if ( !LoadHeader() ) {
74 fclose(m_indexStream);
78 // load reference data (but only keep in memory if full caching requested)
79 bool saveInitialLoad = ( m_cacheMode == BamIndex::FullIndexCaching );
80 if ( !LoadAllReferences(saveInitialLoad) ) {
81 fclose(m_indexStream);
85 // update index cache based on selected mode
92 // opens index file for reading/writing, return true if opened OK
93 bool BamIndex::OpenIndexFile(const string& filename, const string& mode) {
95 // attempt to open file, return false if error
96 m_indexStream = fopen(filename.c_str(), mode.c_str());
97 if ( m_indexStream == 0 ) return false;
99 // otherwise save filename & return sucess
100 m_indexFilename = filename;
104 // rewind index file to beginning of index data, return true if rewound OK
105 bool BamIndex::Rewind(void) {
106 return ( fseek64(m_indexStream, DataBeginOffset(), SEEK_SET) == 0 );
109 // change the index caching behavior
110 void BamIndex::SetCacheMode(const BamIndex::IndexCacheMode& mode) {
111 if ( mode != m_cacheMode ) {
117 // updates in-memory cache of index data, depending on current cache mode
118 void BamIndex::UpdateCache(void) {
120 // skip if file not open
121 if ( !IsOpen() ) return;
123 // reflect requested cache mode behavior
124 switch ( m_cacheMode ) {
126 case (BamIndex::FullIndexCaching) :
128 LoadAllReferences(true);
131 case (BamIndex::LimitedIndexCaching) :
132 if ( HasFullDataCache() )
133 KeepOnlyFirstReferenceOffsets();
136 SkipToFirstReference();
137 LoadFirstReference(true);
141 case(BamIndex::NoIndexCaching) :
151 // writes in-memory index data out to file
152 bool BamIndex::Write(const string& bamFilename) {
154 // open index file for writing
155 string indexFilename = bamFilename + Extension();
156 if ( !OpenIndexFile(indexFilename, "wb") ) {
157 fprintf(stderr, "BamIndex ERROR: could not open file to save index data.\n");
161 // write index header data
162 if ( !WriteHeader() ) {
163 fprintf(stderr, "BamIndex ERROR: there was a problem writing index metadata to the new index file.\n");
164 fflush(m_indexStream);
165 fclose(m_indexStream);
169 // write main index data
170 if ( !WriteAllReferences() ) {
171 fprintf(stderr, "BamIndex ERROR: there was a problem writing index data to the new index file.\n");
172 fflush(m_indexStream);
173 fclose(m_indexStream);
177 // flush any remaining output
178 fflush(m_indexStream);
179 fclose(m_indexStream);
181 // re-open index file for later reading
182 if ( !OpenIndexFile(indexFilename, "rb") ) {
183 fprintf(stderr, "BamIndex ERROR: could not open newly created index file for reading.\n");
187 // save index filename & return success
188 m_indexFilename = indexFilename;