X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2Fapi%2Finternal%2FBamRandomAccessController_p.cpp;h=c223ed762d9e5cb23b322fb6f90c4b7a3810e499;hb=19077d59154eeb244af96b1fd9658e535c24c1be;hp=a599f7c48704a7361576e47e7705d486813944b9;hpb=72f5b82ad353b4cc9d6f8153f1ad19cc387b9597;p=bamtools.git diff --git a/src/api/internal/BamRandomAccessController_p.cpp b/src/api/internal/BamRandomAccessController_p.cpp index a599f7c..c223ed7 100644 --- a/src/api/internal/BamRandomAccessController_p.cpp +++ b/src/api/internal/BamRandomAccessController_p.cpp @@ -2,24 +2,25 @@ // BamRandomAccessController_p.cpp (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 5 April 2011(DB) +// Last modified: 10 October 2011(DB) // --------------------------------------------------------------------------- // Manages random access operations in a BAM file // ************************************************************************** -#include -#include -#include -#include +#include "api/BamIndex.h" +#include "api/internal/BamException_p.h" +#include "api/internal/BamRandomAccessController_p.h" +#include "api/internal/BamReader_p.h" +#include "api/internal/BamIndexFactory_p.h" using namespace BamTools; using namespace BamTools::Internal; -#include +#include +#include using namespace std; BamRandomAccessController::BamRandomAccessController(void) : m_index(0) - , m_indexCacheMode(BamIndex::LimitedIndexCaching) , m_hasAlignmentsInRegion(true) { } @@ -77,9 +78,9 @@ BamRandomAccessController::AlignmentState(const BamAlignment& alignment) const { // if alignment starts at or after left bound position if ( alignment.Position >= m_region.LeftPosition) { - if ( m_region.isRightBoundSpecified() && // right bound is specified AND - m_region.LeftRefID == m_region.RightRefID && // left & right bounds on same reference AND - alignment.Position > m_region.RightPosition ) // alignment starts after right bound position + if ( m_region.isRightBoundSpecified() && // right bound is specified AND + m_region.LeftRefID == m_region.RightRefID && // left & right bounds on same reference AND + alignment.Position >= m_region.RightPosition ) // alignment starts on or after right bound position return AfterRegion; // otherwise, alignment overlaps region @@ -90,7 +91,7 @@ BamRandomAccessController::AlignmentState(const BamAlignment& alignment) const { else { // if alignment overlaps left bound position - if ( alignment.GetEndPosition() >= m_region.LeftPosition ) + if ( alignment.GetEndPosition() > m_region.LeftPosition ) return OverlapsRegion; else return BeforeRegion; @@ -114,15 +115,15 @@ BamRandomAccessController::AlignmentState(const BamAlignment& alignment) const { // alignment is on right bound reference else { - // if alignment starts on or before right bound position - if ( alignment.Position <= m_region.RightPosition ) + // if alignment starts before right bound position + if ( alignment.Position < m_region.RightPosition ) return OverlapsRegion; else return AfterRegion; } } - // otherwise, alignment starts after left bound and there is no right bound + // otherwise, alignment starts after left bound and there is no right bound given else return OverlapsRegion; } } @@ -133,8 +134,10 @@ void BamRandomAccessController::Close(void) { } void BamRandomAccessController::ClearIndex(void) { - delete m_index; - m_index = 0; + if ( m_index ) { + delete m_index; + m_index = 0; + } } void BamRandomAccessController::ClearRegion(void) { @@ -143,34 +146,42 @@ void BamRandomAccessController::ClearRegion(void) { } bool BamRandomAccessController::CreateIndex(BamReaderPrivate* reader, - const BamIndex::IndexType& type) { - + const BamIndex::IndexType& type) +{ // skip if reader is invalid - if ( reader == 0 ) + assert(reader); + if ( !reader->IsOpen() ) { + SetErrorString("BamRandomAccessController::CreateIndex", + "cannot create index for unopened reader"); return false; + } // create new index of requested type BamIndex* newIndex = BamIndexFactory::CreateIndexOfType(type, reader); if ( newIndex == 0 ) { - cerr << "BamRandomAccessController ERROR: could not create index of type " << type << endl; + stringstream s(""); + s << "could not create index of type: " << type; + SetErrorString("BamRandomAccessController::CreateIndex", s.str()); return false; } // attempt to build index from current BamReader file if ( !newIndex->Create() ) { - cerr << "BamRandomAccessController ERROR: could not create index for BAM file: " - << reader->Filename() << endl; + const string indexError = newIndex->GetErrorString(); + const string message = "could not create index: \n\t" + indexError; + SetErrorString("BamRandomAccessController::CreateIndex", message); return false; } - // save new index + // save new index & return success SetIndex(newIndex); - - // set new index's cache mode & return success - newIndex->SetCacheMode(m_indexCacheMode); return true; } +string BamRandomAccessController::GetErrorString(void) const { + return m_errorString; +} + bool BamRandomAccessController::HasIndex(void) const { return ( m_index != 0 ); } @@ -187,13 +198,13 @@ bool BamRandomAccessController::LocateIndex(BamReaderPrivate* reader, const BamIndex::IndexType& preferredType) { // look up index filename, deferring to preferredType if possible + assert(reader); const string& indexFilename = BamIndexFactory::FindIndexFilename(reader->Filename(), preferredType); // if no index file found (of any type) if ( indexFilename.empty() ) { - cerr << "BamRandomAccessController WARNING: " - << "could not find index file for BAM: " - << reader->Filename() << endl; + const string message = string("could not find index file for:") + reader->Filename(); + SetErrorString("BamRandomAccessController::LocateIndex", message); return false; } @@ -206,16 +217,17 @@ bool BamRandomAccessController::OpenIndex(const string& indexFilename, BamReader // attempt create new index of type based on filename BamIndex* index = BamIndexFactory::CreateIndexFromFilename(indexFilename, reader); if ( index == 0 ) { - cerr << "BamRandomAccessController ERROR: could not create index for file: " << indexFilename << endl; + const string message = string("could not open index file: ") + indexFilename; + SetErrorString("BamRandomAccessController::OpenIndex", message); return false; } - // set cache mode - index->SetCacheMode(m_indexCacheMode); - // attempt to load data from index file if ( !index->Load(indexFilename) ) { - cerr << "BamRandomAccessController ERROR: could not load index data from file: " << indexFilename << endl; + const string indexError = index->GetErrorString(); + const string message = string("could not load index data from file: ") + indexFilename + + "\n\t" + indexError; + SetErrorString("BamRandomAccessController::OpenIndex", message); return false; } @@ -228,28 +240,26 @@ bool BamRandomAccessController::RegionHasAlignments(void) const { return m_hasAlignmentsInRegion; } +void BamRandomAccessController::SetErrorString(const string& where, const string& what) { + m_errorString = where + ": " + what; +} + void BamRandomAccessController::SetIndex(BamIndex* index) { if ( m_index ) ClearIndex(); m_index = index; } -void BamRandomAccessController::SetIndexCacheMode(const BamIndex::IndexCacheMode& mode) { - m_indexCacheMode = mode; - if ( m_index ) - m_index->SetCacheMode(mode); -} +bool BamRandomAccessController::SetRegion(const BamRegion& region, const int& referenceCount) { -bool BamRandomAccessController::SetRegion(BamReaderPrivate* reader, - const BamRegion& region, - const int& referenceCount) -{ // store region m_region = region; // cannot jump when no index is available - if ( !HasIndex() ) + if ( !HasIndex() ) { + SetErrorString("BamRandomAccessController", "cannot jump if no index data available"); return false; + } // adjust region as necessary to reflect where data actually begins AdjustRegion(referenceCount); @@ -257,7 +267,7 @@ bool BamRandomAccessController::SetRegion(BamReaderPrivate* reader, // if no data present, return true // * Not an error, but future attempts to access alignments in this region will not return data // Returning true is useful in a BamMultiReader setting where some BAM files may - // lack alignments in regions where other BAMs do have data. + // lack alignments in regions where other files still have data available. if ( !m_hasAlignmentsInRegion ) return true; @@ -267,6 +277,13 @@ bool BamRandomAccessController::SetRegion(BamReaderPrivate* reader, // This covers 'corner case' where a region is requested that lies beyond the last // alignment on a reference. If this occurs, any subsequent calls to GetNextAlignment[Core] // will not return data. BamMultiReader will still be able to successfully pull alignments - // from a region from multiple files even if one or more have no data. - return m_index->Jump(m_region, &m_hasAlignmentsInRegion); + // from a region from other files even if this one has no data. + if ( !m_index->Jump(m_region, &m_hasAlignmentsInRegion) ) { + const string indexError = m_index->GetErrorString(); + const string message = string("could not set region\n\t") + indexError; + SetErrorString("BamRandomAccessController::OpenIndex", message); + return false; + } + else + return true; }