1 // ***************************************************************************
2 // BamMultiMerger_p.h (c) 2010 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 28 September 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides merging functionality for BamMultiReader. At this point, supports
8 // sorting results by (refId, position) or by read name.
9 // ***************************************************************************
11 #ifndef BAMMULTIMERGER_P_H
12 #define BAMMULTIMERGER_P_H
18 // This file is not part of the BamTools API. It exists purely as an
19 // implementation detail. This header file may change from version to version
20 // without notice, or even be removed.
24 #include <api/BamAlignment.h>
25 #include <api/BamReader.h>
34 typedef std::pair<BamReader*, BamAlignment*> ReaderAlignment;
36 // generic MultiMerger interface
37 class IBamMultiMerger {
40 IBamMultiMerger(void) { }
41 virtual ~IBamMultiMerger(void) { }
44 virtual void Add(ReaderAlignment value) =0;
45 virtual void Clear(void) =0;
46 virtual const ReaderAlignment& First(void) const =0;
47 virtual bool IsEmpty(void) const =0;
48 virtual void Remove(BamReader* reader) =0;
49 virtual int Size(void) const =0;
50 virtual ReaderAlignment TakeFirst(void) =0;
53 // IBamMultiMerger implementation - sorted on BamAlignment: (RefId, Position)
54 class PositionMultiMerger : public IBamMultiMerger {
57 PositionMultiMerger(void) : IBamMultiMerger() { }
58 ~PositionMultiMerger(void) { }
61 void Add(ReaderAlignment value);
63 const ReaderAlignment& First(void) const;
64 bool IsEmpty(void) const;
65 void Remove(BamReader* reader);
67 ReaderAlignment TakeFirst(void);
70 typedef std::pair<int, int> KeyType;
71 typedef ReaderAlignment ValueType;
72 typedef std::pair<KeyType, ValueType> ElementType;
74 struct SortLessThanPosition {
75 bool operator() (const KeyType& lhs, const KeyType& rhs) {
77 // force unmapped alignments to end
78 if ( lhs.first == -1 ) return false;
79 if ( rhs.first == -1 ) return true;
81 // sort first on RefID, then by Position
82 if ( lhs.first != rhs.first )
83 return lhs.first < rhs.first;
85 return lhs.second < rhs.second;
89 typedef SortLessThanPosition Compare;
91 typedef std::multimap<KeyType, ValueType, Compare> ContainerType;
92 typedef ContainerType::iterator DataIterator;
93 typedef ContainerType::const_iterator DataConstIterator;
98 // IBamMultiMerger implementation - sorted on BamAlignment: Name
99 class ReadNameMultiMerger : public IBamMultiMerger {
102 ReadNameMultiMerger(void) : IBamMultiMerger() { }
103 ~ReadNameMultiMerger(void) { }
106 void Add(ReaderAlignment value);
108 const ReaderAlignment& First(void) const;
109 bool IsEmpty(void) const;
110 void Remove(BamReader* reader);
111 int Size(void) const;
112 ReaderAlignment TakeFirst(void);
115 typedef std::string KeyType;
116 typedef ReaderAlignment ValueType;
117 typedef std::pair<KeyType, ValueType> ElementType;
119 typedef std::multimap<KeyType, ValueType> ContainerType;
120 typedef ContainerType::iterator DataIterator;
121 typedef ContainerType::const_iterator DataConstIterator;
123 ContainerType m_data;
126 // IBamMultiMerger implementation - unsorted BAM file(s)
127 class UnsortedMultiMerger : public IBamMultiMerger {
130 UnsortedMultiMerger(void) : IBamMultiMerger() { }
131 ~UnsortedMultiMerger(void) { }
134 void Add(ReaderAlignment value);
136 const ReaderAlignment& First(void) const;
137 bool IsEmpty(void) const;
138 void Remove(BamReader* reader);
139 int Size(void) const;
140 ReaderAlignment TakeFirst(void);
143 typedef ReaderAlignment ElementType;
144 typedef std::vector<ReaderAlignment> ContainerType;
145 typedef ContainerType::iterator DataIterator;
146 typedef ContainerType::const_iterator DataConstIterator;
148 ContainerType m_data;
151 // ------------------------------------------
152 // PositionMultiMerger implementation
154 inline void PositionMultiMerger::Add(ReaderAlignment value) {
155 const KeyType key( value.second->RefID, value.second->Position );
156 m_data.insert( ElementType(key, value) );
159 inline void PositionMultiMerger::Clear(void) {
163 inline const ReaderAlignment& PositionMultiMerger::First(void) const {
164 const ElementType& entry = (*m_data.begin());
168 inline bool PositionMultiMerger::IsEmpty(void) const {
169 return m_data.empty();
172 inline void PositionMultiMerger::Remove(BamReader* reader) {
174 if ( reader == 0 ) return;
175 const std::string filenameToRemove = reader->GetFilename();
177 // iterate over readers in cache
178 DataIterator dataIter = m_data.begin();
179 DataIterator dataEnd = m_data.end();
180 for ( ; dataIter != dataEnd; ++dataIter ) {
181 const ValueType& entry = (*dataIter).second;
182 const BamReader* entryReader = entry.first;
183 if ( entryReader == 0 ) continue;
185 // remove iterator on match
186 if ( entryReader->GetFilename() == filenameToRemove ) {
187 m_data.erase(dataIter);
193 inline int PositionMultiMerger::Size(void) const {
194 return m_data.size();
197 inline ReaderAlignment PositionMultiMerger::TakeFirst(void) {
198 DataIterator first = m_data.begin();
199 ReaderAlignment next = (*first).second;
204 // ------------------------------------------
205 // ReadNameMultiMerger implementation
207 inline void ReadNameMultiMerger::Add(ReaderAlignment value) {
208 BamAlignment* al = value.second;
209 if ( al->BuildCharData() ) {
210 const KeyType key(al->Name);
211 m_data.insert( ElementType(key, value) );
215 inline void ReadNameMultiMerger::Clear(void) {
219 inline const ReaderAlignment& ReadNameMultiMerger::First(void) const {
220 const ElementType& entry = (*m_data.begin());
224 inline bool ReadNameMultiMerger::IsEmpty(void) const {
225 return m_data.empty();
228 inline void ReadNameMultiMerger::Remove(BamReader* reader) {
230 if ( reader == 0 ) return;
231 const std::string filenameToRemove = reader->GetFilename();
233 // iterate over readers in cache
234 DataIterator dataIter = m_data.begin();
235 DataIterator dataEnd = m_data.end();
236 for ( ; dataIter != dataEnd; ++dataIter ) {
237 const ValueType& entry = (*dataIter).second;
238 const BamReader* entryReader = entry.first;
239 if ( entryReader == 0 ) continue;
241 // remove iterator on match
242 if ( entryReader->GetFilename() == filenameToRemove ) {
243 m_data.erase(dataIter);
250 inline int ReadNameMultiMerger::Size(void) const {
251 return m_data.size();
254 inline ReaderAlignment ReadNameMultiMerger::TakeFirst(void) {
255 DataIterator first = m_data.begin();
256 ReaderAlignment next = (*first).second;
261 // ------------------------------------------
262 // UnsortedMultiMerger implementation
264 inline void UnsortedMultiMerger::Add(ReaderAlignment value) {
265 m_data.push_back(value);
268 inline void UnsortedMultiMerger::Clear(void) {
269 for (size_t i = 0; i < m_data.size(); ++i )
273 inline const ReaderAlignment& UnsortedMultiMerger::First(void) const {
274 return m_data.front();
277 inline bool UnsortedMultiMerger::IsEmpty(void) const {
278 return m_data.empty();
281 inline void UnsortedMultiMerger::Remove(BamReader* reader) {
283 if ( reader == 0 ) return;
284 const std::string filenameToRemove = reader->GetFilename();
286 // iterate over readers in cache
287 DataIterator dataIter = m_data.begin();
288 DataIterator dataEnd = m_data.end();
289 for ( ; dataIter != dataEnd; ++dataIter ) {
290 const BamReader* entryReader = (*dataIter).first;
291 if ( entryReader == 0 ) continue;
293 // remove iterator on match
294 if ( entryReader->GetFilename() == filenameToRemove ) {
295 m_data.erase(dataIter);
301 inline int UnsortedMultiMerger::Size(void) const {
302 return m_data.size();
305 inline ReaderAlignment UnsortedMultiMerger::TakeFirst(void) {
306 ReaderAlignment first = m_data.front();
307 m_data.erase( m_data.begin() );
311 } // namespace Internal
312 } // namespace BamTools
314 #endif // BAMMULTIMERGER_P_H