]> git.donarmstrong.com Git - bamtools.git/blob - src/api/SamSequenceDictionary.cpp
Fix: unmapped reads now pushed to end of coordinate-sorted BAM
[bamtools.git] / src / api / SamSequenceDictionary.cpp
1 // ***************************************************************************
2 // SamSequenceDictionary.cpp (c) 2010 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 18 April 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides methods for operating on a collection of SamSequence entries.
8 // *************************************************************************
9
10 #include <api/SamSequenceDictionary.h>
11 using namespace BamTools;
12
13 #include <iostream>
14 using namespace std;
15
16 /*! \class BamTools::SamSequenceDictionary
17     \brief Container of SamSequence entries.
18
19     Provides methods for operating on a collection of SamSequence entries.
20 */
21
22 /*! \fn SamSequenceDictionary::SamSequenceDictionary(void)
23     \brief constructor
24 */
25 SamSequenceDictionary::SamSequenceDictionary(void) { }
26
27 /*! \fn SamSequenceDictionary::SamSequenceDictionary(const SamSequenceDictionary& other)
28     \brief copy constructor
29 */
30 SamSequenceDictionary::SamSequenceDictionary(const SamSequenceDictionary& other)
31     : m_data(other.m_data)
32 { }
33
34 /*! \fn SamSequenceDictionary::~SamSequenceDictionary(void)
35     \brief destructor
36 */
37 SamSequenceDictionary::~SamSequenceDictionary(void) { }
38
39 /*! \fn void SamSequenceDictionary::Add(const SamSequence& sequence)
40     \brief Adds a sequence to the dictionary.
41
42     Duplicate entries are silently discarded.
43
44     \param sequence entry to be added
45 */
46 void SamSequenceDictionary::Add(const SamSequence& sequence) {
47
48     // TODO: report error on attempted duplicate?
49
50     if ( IsEmpty() || !Contains(sequence) )
51         m_data.push_back(sequence);
52 }
53
54 /*! \fn void SamSequenceDictionary::Add(const std::string& name, const int& length)
55     \brief Adds a sequence to the dictionary.
56
57     This is an overloaded function.
58
59     \param name name of sequence entry to be added
60     \param length length of sequence entry to be added
61     \sa Add()
62 */
63 void SamSequenceDictionary::Add(const std::string& name, const int& length) {
64     Add( SamSequence(name, length) );
65 }
66
67 /*! \fn void SamSequenceDictionary::Add(const std::vector<SamSequence>& sequences)
68     \brief Adds multiple sequences to the dictionary.
69
70     This is an overloaded function.
71
72     \param sequences entries to be added
73     \sa Add()
74 */
75 void SamSequenceDictionary::Add(const std::vector<SamSequence>& sequences) {
76     vector<SamSequence>::const_iterator seqIter = sequences.begin();
77     vector<SamSequence>::const_iterator seqEnd  = sequences.end();
78     for ( ; seqIter!= seqEnd; ++seqIter )
79         Add(*seqIter);
80 }
81
82 /*! \fn void SamSequenceDictionary::Add(const std::map<std::string, int>& sequenceMap)
83     \brief Adds multiple sequences to the dictionary.
84
85     This is an overloaded function.
86
87     \param sequenceMap map of sequence entries (name => length) to be added
88     \sa Add()
89 */
90 void SamSequenceDictionary::Add(const std::map<std::string, int>& sequenceMap) {
91     map<string, int>::const_iterator seqIter = sequenceMap.begin();
92     map<string, int>::const_iterator seqEnd  = sequenceMap.end();
93     for ( ; seqIter != seqEnd; ++seqIter ) {
94         const string& name = (*seqIter).first;
95         const int& length = (*seqIter).second;
96         Add( SamSequence(name, length) );
97     }
98 }
99
100 /*! \fn SamSequenceIterator SamSequenceDictionary::Begin(void)
101     \return an STL iterator pointing to the first sequence
102     \sa ConstBegin(), End()
103 */
104 SamSequenceIterator SamSequenceDictionary::Begin(void) {
105     return m_data.begin();
106 }
107
108 /*! \fn SamSequenceConstIterator SamSequenceDictionary::Begin(void) const
109     \return an STL const_iterator pointing to the first sequence
110
111     This is an overloaded function.
112
113     \sa ConstBegin(), End()
114 */
115 SamSequenceConstIterator SamSequenceDictionary::Begin(void) const {
116     return m_data.begin();
117 }
118
119 /*! \fn void SamSequenceDictionary::Clear(void)
120     \brief Clears all sequence entries.
121 */
122 void SamSequenceDictionary::Clear(void) {
123     m_data.clear();
124 }
125
126 /*! \fn SamSequenceConstIterator SamSequenceDictionary::ConstBegin(void) const
127     \return an STL const_iterator pointing to the first sequence
128     \sa Begin(), ConstEnd()
129 */
130 SamSequenceConstIterator SamSequenceDictionary::ConstBegin(void) const {
131     return m_data.begin();
132 }
133
134 /*! \fn SamSequenceConstIterator SamSequenceDictionary::ConstEnd(void) const
135     \return an STL const_iterator pointing to the imaginary entry after the last sequence
136     \sa End(), ConstBegin()
137 */
138 SamSequenceConstIterator SamSequenceDictionary::ConstEnd(void) const {
139     return m_data.end();
140 }
141
142 /*! \fn bool SamSequenceDictionary::Contains(const std::string& sequenceName) const
143     \brief Returns true if dictionary contains sequence.
144     \param sequenceName search for sequence matching this name
145     \return \c true if dictionary contains a sequence with this name
146 */
147 bool SamSequenceDictionary::Contains(const std::string& sequenceName) const {
148     return ( IndexOf(sequenceName) != (int)m_data.size() );
149 }
150
151 /*! \fn bool SamSequenceDictionary::Contains(const SamSequence& sequence) const
152     \brief Returns true if dictionary contains sequence (matches on name).
153
154     This is an overloaded function.
155
156     \param sequence search for this sequence
157     \return \c true if dictionary contains sequence (matching on name)
158 */
159 bool SamSequenceDictionary::Contains(const SamSequence& sequence) const {
160     return ( IndexOf(sequence.Name) != (int)m_data.size() );
161 }
162
163 /*! \fn SamSequenceIterator SamSequenceDictionary::End(void)
164     \return an STL iterator pointing to the imaginary entry after the last sequence
165     \sa Begin(), ConstEnd()
166 */
167 SamSequenceIterator SamSequenceDictionary::End(void) {
168     return m_data.end();
169 }
170
171 /*! \fn SamSequenceConstIterator SamSequenceDictionary::End(void) const
172     \return an STL const_iterator pointing to the imaginary entry after the last sequence
173
174     This is an overloaded function.
175
176     \sa Begin(), ConstEnd()
177 */
178 SamSequenceConstIterator SamSequenceDictionary::End(void) const {
179     return m_data.end();
180 }
181
182 /*! \fn int SamSequenceDictionary::IndexOf(const std::string& name) const
183     \internal
184     \return index of sequence if found (matching on name).  Otherwise, returns vector::size() (invalid index).
185 */
186 int SamSequenceDictionary::IndexOf(const std::string& name) const {
187     SamSequenceConstIterator begin = ConstBegin();
188     SamSequenceConstIterator iter  = begin;
189     SamSequenceConstIterator end   = ConstEnd();
190     for ( ; iter != end; ++iter ) {
191         const SamSequence& currentSeq = (*iter);
192         if ( currentSeq.Name == name )
193             break;
194     }
195     return distance( begin, iter );
196 }
197
198 /*! \fn bool SamSequenceDictionary::IsEmpty(void) const
199     \brief Returns \c true if dictionary contains no sequences
200     \sa Size()
201 */
202 bool SamSequenceDictionary::IsEmpty(void) const {
203     return m_data.empty();
204 }
205
206 /*! \fn void SamSequenceDictionary::Remove(const SamSequence& sequence)
207     \brief Removes sequence from dictionary, if found (matches on name).
208
209     This is an overloaded function.
210
211     \param sequence SamSequence to remove (matching on name)
212 */
213 void SamSequenceDictionary::Remove(const SamSequence& sequence) {
214     Remove( sequence.Name );
215 }
216
217 /*! \fn void SamSequenceDictionary::Remove(const std::string& sequenceName)
218     \brief Removes sequence from dictionary, if found.
219
220     \param sequenceName name of sequence to remove
221     \sa Remove()
222 */
223 void SamSequenceDictionary::Remove(const std::string& sequenceName) {
224     if ( Contains(sequenceName) )
225         m_data.erase( m_data.begin() + IndexOf(sequenceName) );
226 }
227
228 /*! \fn void SamSequenceDictionary::Remove(const std::vector<SamSequence>& sequences)
229     \brief Removes multiple sequences from dictionary.
230
231     This is an overloaded function.
232
233     \param sequences sequences to remove
234     \sa Remove()
235 */
236 void SamSequenceDictionary::Remove(const std::vector<SamSequence>& sequences) {
237     vector<SamSequence>::const_iterator rgIter = sequences.begin();
238     vector<SamSequence>::const_iterator rgEnd  = sequences.end();
239     for ( ; rgIter!= rgEnd; ++rgIter )
240         Remove(*rgIter);
241 }
242
243 /*! \fn void SamSequenceDictionary::Remove(const std::vector<std::string>& sequenceNames)
244     \brief Removes multiple sequences from dictionary.
245
246     This is an overloaded function.
247
248     \param sequenceNames names of the sequences to remove
249     \sa Remove()
250 */
251 void SamSequenceDictionary::Remove(const std::vector<std::string>& sequenceNames) {
252     vector<string>::const_iterator rgIter = sequenceNames.begin();
253     vector<string>::const_iterator rgEnd  = sequenceNames.end();
254     for ( ; rgIter!= rgEnd; ++rgIter )
255         Remove(*rgIter);
256 }
257
258 /*! \fn int SamSequenceDictionary::Size(void) const
259     \brief Returns number of sequences in dictionary.
260     \sa IsEmpty()
261 */
262 int SamSequenceDictionary::Size(void) const {
263     return m_data.size();
264 }
265
266 /*! \fn SamSequence& SamSequenceDictionary::operator[](const std::string& sequenceName)
267     \brief Retrieves the modifiable SamSequence that matches \a sequenceName.
268
269     NOTE - If the dictionary contains no sequence matching this name, this function inserts
270     a new one with this name (length:0), and returns a reference to it.
271
272     If you want to avoid this insertion behavior, check the result of Contains() before
273     using this operator.
274
275     \param sequenceName name of sequence to retrieve
276     \return a modifiable reference to the SamSequence associated with the name
277 */
278 SamSequence& SamSequenceDictionary::operator[](const std::string& sequenceName) {
279
280     // look up sequence ID
281     int index = IndexOf(sequenceName);
282
283     // if found, return sequence at index
284     if ( index != (int)m_data.size() )
285         return m_data[index];
286
287     // otherwise, append new sequence and return reference
288     else {
289         m_data.push_back( SamSequence(sequenceName, 0) );
290         return m_data.back();
291     }
292 }