X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2Fapi%2Finternal%2FBamMultiMerger_p.h;h=3000097dd972e66456fb9eb7fffe668c9afbf054;hb=9f1ce8c47aeadb6dc1320b52ee671c3341b97935;hp=15ae437dc44ba1f55d5dd54b37ee3c39e6f9f23e;hpb=72f5b82ad353b4cc9d6f8153f1ad19cc387b9597;p=bamtools.git diff --git a/src/api/internal/BamMultiMerger_p.h b/src/api/internal/BamMultiMerger_p.h index 15ae437..3000097 100644 --- a/src/api/internal/BamMultiMerger_p.h +++ b/src/api/internal/BamMultiMerger_p.h @@ -2,7 +2,7 @@ // BamMultiMerger_p.h (c) 2010 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 9 September 2011 (DB) +// Last modified: 10 October 2011 (DB) // --------------------------------------------------------------------------- // Provides merging functionality for BamMultiReader. At this point, supports // sorting results by (refId, position) or by read name. @@ -21,247 +21,213 @@ // // We mean it. -#include -#include -#include -#include +#include "api/BamAlignment.h" +#include "api/BamReader.h" +#include "api/algorithms/Sort.h" +#include +#include +#include #include -#include namespace BamTools { namespace Internal { -typedef std::pair ReaderAlignment; +struct MergeItem { -// generic MultiMerger interface -class IBamMultiMerger { + // data members + BamReader* Reader; + BamAlignment* Alignment; - public: - IBamMultiMerger(void) { } - virtual ~IBamMultiMerger(void) { } + // ctors & dtor + MergeItem(BamReader* reader = 0, + BamAlignment* alignment = 0) + : Reader(reader) + , Alignment(alignment) + { } - public: - virtual void Add(ReaderAlignment value) =0; - virtual void Clear(void) =0; - virtual const ReaderAlignment& First(void) const =0; - virtual bool IsEmpty(void) const =0; - virtual void Remove(BamReader* reader) =0; - virtual int Size(void) const =0; - virtual ReaderAlignment TakeFirst(void) =0; -}; + MergeItem(const MergeItem& other) + : Reader(other.Reader) + , Alignment(other.Alignment) + { } -// IBamMultiMerger implementation - sorted on BamAlignment: (RefId, Position) -class PositionMultiMerger : public IBamMultiMerger { + ~MergeItem(void) { } +}; - public: - PositionMultiMerger(void) : IBamMultiMerger() { } - ~PositionMultiMerger(void) { } +template +struct MergeItemSorter : public std::binary_function { public: - void Add(ReaderAlignment value); - void Clear(void); - const ReaderAlignment& First(void) const; - bool IsEmpty(void) const; - void Remove(BamReader* reader); - int Size(void) const; - ReaderAlignment TakeFirst(void); + MergeItemSorter(const Compare& comp = Compare()) + : m_comp(comp) + { } + + bool operator()(const MergeItem& lhs, const MergeItem& rhs) { + const BamAlignment& l = *lhs.Alignment; + const BamAlignment& r = *rhs.Alignment; + return m_comp(l,r); + } private: - typedef std::pair KeyType; - typedef ReaderAlignment ValueType; - typedef std::pair ElementType; - - typedef std::multimap ContainerType; - typedef ContainerType::iterator DataIterator; - typedef ContainerType::const_iterator DataConstIterator; - - ContainerType m_data; + Compare m_comp; }; -// IBamMultiMerger implementation - sorted on BamAlignment: Name -class ReadNameMultiMerger : public IBamMultiMerger { +// pure ABC so we can just work polymorphically with any specific merger implementation +class IMultiMerger { public: - ReadNameMultiMerger(void) : IBamMultiMerger() { } - ~ReadNameMultiMerger(void) { } - + IMultiMerger(void) { } + virtual ~IMultiMerger(void) { } public: - void Add(ReaderAlignment value); - void Clear(void); - const ReaderAlignment& First(void) const; - bool IsEmpty(void) const; - void Remove(BamReader* reader); - int Size(void) const; - ReaderAlignment TakeFirst(void); - - private: - typedef std::string KeyType; - typedef ReaderAlignment ValueType; - typedef std::pair ElementType; - - typedef std::multimap ContainerType; - typedef ContainerType::iterator DataIterator; - typedef ContainerType::const_iterator DataConstIterator; - - ContainerType m_data; + virtual void Add(MergeItem item) =0; + virtual void Clear(void) =0; + virtual const MergeItem& First(void) const =0; + virtual bool IsEmpty(void) const =0; + virtual void Remove(BamReader* reader) =0; + virtual int Size(void) const =0; + virtual MergeItem TakeFirst(void) =0; }; -// IBamMultiMerger implementation - unsorted BAM file(s) -class UnsortedMultiMerger : public IBamMultiMerger { +// general merger +template +class MultiMerger : public IMultiMerger { public: - UnsortedMultiMerger(void) : IBamMultiMerger() { } - ~UnsortedMultiMerger(void) { } + typedef Compare CompareType; + typedef MergeItemSorter MergeType; public: - void Add(ReaderAlignment value); + explicit MultiMerger(const Compare& comp = Compare()) + : IMultiMerger() + , m_data( MergeType(comp) ) + { } + ~MultiMerger(void) { } + + public: + void Add(MergeItem item); void Clear(void); - const ReaderAlignment& First(void) const; + const MergeItem& First(void) const; bool IsEmpty(void) const; void Remove(BamReader* reader); int Size(void) const; - ReaderAlignment TakeFirst(void); + MergeItem TakeFirst(void); private: - typedef ReaderAlignment ElementType; - typedef std::vector ContainerType; - typedef ContainerType::iterator DataIterator; - typedef ContainerType::const_iterator DataConstIterator; - + typedef MergeItem ValueType; + typedef std::multiset ContainerType; + typedef typename ContainerType::iterator DataIterator; + typedef typename ContainerType::const_iterator DataConstIterator; ContainerType m_data; }; -// ------------------------------------------ -// PositionMultiMerger implementation +template +inline void MultiMerger::Add(MergeItem item) { + + // N.B. - any future custom Compare types must define this method + // see algorithms/Sort.h -inline void PositionMultiMerger::Add(ReaderAlignment value) { - const KeyType key( value.second->RefID, value.second->Position ); - m_data.insert( ElementType(key, value) ); + if ( CompareType::UsesCharData() ) + item.Alignment->BuildCharData(); + m_data.insert(item); } -inline void PositionMultiMerger::Clear(void) { +template +inline void MultiMerger::Clear(void) { m_data.clear(); } -inline const ReaderAlignment& PositionMultiMerger::First(void) const { - const ElementType& entry = (*m_data.begin()); - return entry.second; +template +inline const MergeItem& MultiMerger::First(void) const { + const ValueType& entry = (*m_data.begin()); + return entry; } -inline bool PositionMultiMerger::IsEmpty(void) const { +template +inline bool MultiMerger::IsEmpty(void) const { return m_data.empty(); } - -inline void PositionMultiMerger::Remove(BamReader* reader) { +template +inline void MultiMerger::Remove(BamReader* reader) { if ( reader == 0 ) return; - const std::string filenameToRemove = reader->GetFilename(); + const std::string& filenameToRemove = reader->GetFilename(); // iterate over readers in cache DataIterator dataIter = m_data.begin(); DataIterator dataEnd = m_data.end(); for ( ; dataIter != dataEnd; ++dataIter ) { - const ValueType& entry = (*dataIter).second; - const BamReader* entryReader = entry.first; - if ( entryReader == 0 ) continue; + const MergeItem& item = (*dataIter); + const BamReader* itemReader = item.Reader; + if ( itemReader == 0 ) continue; // remove iterator on match - if ( entryReader->GetFilename() == filenameToRemove ) { + if ( itemReader->GetFilename() == filenameToRemove ) { m_data.erase(dataIter); return; } } } - -inline int PositionMultiMerger::Size(void) const { +template +inline int MultiMerger::Size(void) const { return m_data.size(); } -inline ReaderAlignment PositionMultiMerger::TakeFirst(void) { - DataIterator first = m_data.begin(); - ReaderAlignment next = (*first).second; - m_data.erase(first); - return next; +template +inline MergeItem MultiMerger::TakeFirst(void) { + DataIterator firstIter = m_data.begin(); + MergeItem firstItem = (*firstIter); + m_data.erase(firstIter); + return firstItem; } -// ------------------------------------------ -// ReadNameMultiMerger implementation +// unsorted "merger" +template<> +class MultiMerger : public IMultiMerger { -inline void ReadNameMultiMerger::Add(ReaderAlignment value) { - BamAlignment* al = value.second; - if ( al->BuildCharData() ) { - const KeyType key(al->Name); - m_data.insert( ElementType(key, value) ); - } -} - -inline void ReadNameMultiMerger::Clear(void) { - m_data.clear(); -} - -inline const ReaderAlignment& ReadNameMultiMerger::First(void) const { - const ElementType& entry = (*m_data.begin()); - return entry.second; -} - -inline bool ReadNameMultiMerger::IsEmpty(void) const { - return m_data.empty(); -} - -inline void ReadNameMultiMerger::Remove(BamReader* reader) { - - if ( reader == 0 ) return; - const std::string filenameToRemove = reader->GetFilename(); - - // iterate over readers in cache - DataIterator dataIter = m_data.begin(); - DataIterator dataEnd = m_data.end(); - for ( ; dataIter != dataEnd; ++dataIter ) { - const ValueType& entry = (*dataIter).second; - const BamReader* entryReader = entry.first; - if ( entryReader == 0 ) continue; - - // remove iterator on match - if ( entryReader->GetFilename() == filenameToRemove ) { - m_data.erase(dataIter); - return; - } - } - -} - -inline int ReadNameMultiMerger::Size(void) const { - return m_data.size(); -} + public: + explicit MultiMerger(const Algorithms::Sort::Unsorted& comp = Algorithms::Sort::Unsorted()) + : IMultiMerger() + { } + ~MultiMerger(void) { } -inline ReaderAlignment ReadNameMultiMerger::TakeFirst(void) { - DataIterator first = m_data.begin(); - ReaderAlignment next = (*first).second; - m_data.erase(first); - return next; -} + public: + void Add(MergeItem item); + void Clear(void); + const MergeItem& First(void) const; + bool IsEmpty(void) const; + void Remove(BamReader* reader); + int Size(void) const; + MergeItem TakeFirst(void); -// ------------------------------------------ -// UnsortedMultiMerger implementation + private: + typedef MergeItem ValueType; + typedef std::deque ContainerType; + typedef ContainerType::iterator DataIterator; + typedef ContainerType::const_iterator DataConstIterator; + ContainerType m_data; +}; -inline void UnsortedMultiMerger::Add(ReaderAlignment value) { - m_data.push_back(value); +inline +void MultiMerger::Add(MergeItem item) { + m_data.push_back(item); } -inline void UnsortedMultiMerger::Clear(void) { - for (size_t i = 0; i < m_data.size(); ++i ) - m_data.pop_back(); +inline +void MultiMerger::Clear(void) { + m_data.clear(); } -inline const ReaderAlignment& UnsortedMultiMerger::First(void) const { +inline +const MergeItem& MultiMerger::First(void) const { return m_data.front(); } -inline bool UnsortedMultiMerger::IsEmpty(void) const { +inline +bool MultiMerger::IsEmpty(void) const { return m_data.empty(); } -inline void UnsortedMultiMerger::Remove(BamReader* reader) { +inline +void MultiMerger::Remove(BamReader* reader) { if ( reader == 0 ) return; const std::string filenameToRemove = reader->GetFilename(); @@ -270,25 +236,28 @@ inline void UnsortedMultiMerger::Remove(BamReader* reader) { DataIterator dataIter = m_data.begin(); DataIterator dataEnd = m_data.end(); for ( ; dataIter != dataEnd; ++dataIter ) { - const BamReader* entryReader = (*dataIter).first; - if ( entryReader == 0 ) continue; + const MergeItem& item = (*dataIter); + const BamReader* itemReader = item.Reader; + if ( itemReader == 0 ) continue; // remove iterator on match - if ( entryReader->GetFilename() == filenameToRemove ) { + if ( itemReader->GetFilename() == filenameToRemove ) { m_data.erase(dataIter); return; } } } -inline int UnsortedMultiMerger::Size(void) const { +inline +int MultiMerger::Size(void) const { return m_data.size(); } -inline ReaderAlignment UnsortedMultiMerger::TakeFirst(void) { - ReaderAlignment first = m_data.front(); - m_data.erase( m_data.begin() ); - return first; +inline +MergeItem MultiMerger::TakeFirst(void) { + MergeItem firstItem = m_data.front(); + m_data.pop_front(); + return firstItem; } } // namespace Internal