]> git.donarmstrong.com Git - bamtools.git/blob - src/api/SamProgramChain.cpp
Brought API up to compliance with recent SAM Format Spec (v1.4-r962)
[bamtools.git] / src / api / SamProgramChain.cpp
1 // ***************************************************************************
2 // SamProgramChain.cpp (c) 2011 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // All rights reserved.
5 // ---------------------------------------------------------------------------
6 // Last modified: 19 April 2011 (DB)
7 // ---------------------------------------------------------------------------
8 // Provides methods for operating on a SamProgram record "chain"
9 // ***************************************************************************
10
11 #include <api/SamProgramChain.h>
12 using namespace BamTools;
13
14 #include <algorithm>
15 #include <iostream>
16 #include <cstdlib>
17 using namespace std;
18
19 /*! \class BamTools::SamProgramChain
20     \brief Sorted container "chain" of SamProgram records.
21
22     Provides methods for operating on a collection of SamProgram records.
23
24     N.B. - Underlying container is *NOT* ordered by linkage, but by order of
25     appearance in SamHeader and subsequent Add() calls. Using the current
26     iterators will not allow you to step through the header's program history.
27     Instead use First()/Last() to access oldest/newest records, respectively.
28 */
29
30 /*! \fn SamProgramChain::SamProgramChain(void)
31     \brief constructor
32 */
33 SamProgramChain::SamProgramChain(void) { }
34
35 /*! \fn SamProgramChain::SamProgramChain(const SamProgramChain& other)
36     \brief copy constructor
37 */
38 SamProgramChain::SamProgramChain(const SamProgramChain& other)
39     : m_data(other.m_data)
40 { }
41
42 /*! \fn SamProgramChain::~SamProgramChain(void)
43     \brief destructor
44 */
45 SamProgramChain::~SamProgramChain(void) { }
46
47 /*! \fn void SamProgramChain::Add(SamProgram& program)
48     \brief Appends a program to program chain.
49
50     Duplicate entries are silently discarded.
51
52     N.B. - Underlying container is *NOT* ordered by linkage, but by order of
53     appearance in SamHeader and subsequent Add() calls. Using the current
54     iterators will not allow you to step through the header's program history.
55     Instead use First()/Last() to access oldest/newest records, respectively.
56
57     \param program entry to be appended
58 */
59 void SamProgramChain::Add(SamProgram& program) {
60
61     // ignore duplicated records
62     if ( Contains(program) )
63         return;
64
65     // if other programs already in chain, try to find the "next" record
66     // tries to match another record's PPID with @program's ID
67     if ( !IsEmpty() )
68         program.NextProgramID = NextIdFor(program.ID);
69
70     // store program record
71     m_data.push_back(program);
72 }
73
74 /*! \fn void SamProgramChain::Add(const std::vector<SamProgram>& programs)
75     \brief Appends a batch of programs to the end of the chain.
76
77     This is an overloaded function.
78
79     \param programs batch of program records to append
80     \sa Add()
81 */
82 void SamProgramChain::Add(std::vector<SamProgram>& programs) {
83     vector<SamProgram>::iterator pgIter = programs.begin();
84     vector<SamProgram>::iterator pgEnd  = programs.end();
85     for ( ; pgIter != pgEnd; ++pgIter )
86         Add(*pgIter);
87 }
88
89 /*! \fn SamProgramIterator SamProgramChain::Begin(void)
90     \return an STL iterator pointing to the first (oldest) program record
91     \sa ConstBegin(), End(), First()
92 */
93 SamProgramIterator SamProgramChain::Begin(void) {
94     return m_data.begin();
95 }
96
97 /*! \fn SamProgramConstIterator SamProgramChain::Begin(void) const
98     \return an STL const_iterator pointing to the first (oldest) program record
99
100     This is an overloaded function.
101
102     \sa ConstBegin(), End(), First()
103 */
104 SamProgramConstIterator SamProgramChain::Begin(void) const {
105     return m_data.begin();
106 }
107
108 /*! \fn void SamProgramChain::Clear(void)
109     \brief Clears all program records.
110 */
111 void SamProgramChain::Clear(void) {
112     m_data.clear();
113 }
114
115 /*! \fn SamProgramConstIterator SamProgramChain::ConstBegin(void) const
116     \return an STL const_iterator pointing to the first (oldest) program record
117     \sa Begin(), ConstEnd(), First()
118 */
119 SamProgramConstIterator SamProgramChain::ConstBegin(void) const {
120     return m_data.begin();
121 }
122
123 /*! \fn SamProgramConstIterator SamProgramChain::ConstEnd(void) const
124     \return an STL const_iterator pointing to the imaginary entry after the last (newest) program record
125     \sa ConstBegin(), End(), Last()
126 */
127 SamProgramConstIterator SamProgramChain::ConstEnd(void) const {
128     return m_data.end();
129 }
130
131 /*! \fn bool SamProgramChain::Contains(const SamProgram& program) const
132     \brief Returns true if chains has this program record (matching on ID).
133
134     This is an overloaded function.
135
136     \param program SamProgram to search for
137     \return \c true if chain contains program (matching on ID)
138 */
139 bool SamProgramChain::Contains(const SamProgram& program) const {
140     return Contains(program.ID);
141 }
142
143 /*! \fn bool SamProgramChain::Contains(const std::string& programId) const
144     \brief Returns true if chains has a program record with this ID
145     \param programId search for program matching this ID
146     \return \c true if chain contains a program record with this ID
147 */
148 bool SamProgramChain::Contains(const std::string& programId) const {
149     return ( IndexOf(programId) != (int)m_data.size() );
150 }
151
152 /*! \fn SamProgramIterator SamProgramChain::End(void)
153     \return an STL iterator pointing to the imaginary entry after the last (newest) program record
154     \sa Begin(), ConstEnd(), Last()
155 */
156 SamProgramIterator SamProgramChain::End(void) {
157     return m_data.end();
158 }
159
160 /*! \fn SamProgramConstIterator SamProgramChain::End(void) const
161     \return an STL const_iterator pointing to the imaginary entry after the last (newest) program record
162
163     This is an overloaded function.
164
165     \sa Begin(), ConstEnd(), Last()
166 */
167 SamProgramConstIterator SamProgramChain::End(void) const {
168     return m_data.end();
169 }
170
171 /*! \fn SamProgram& SamProgramChain::First(void)
172     \brief Fetches first (oldest) record in the chain.
173
174     N.B. - This function will fail if the chain is empty. If this is possible,
175     check the result of IsEmpty() before calling this function.
176
177     \return a modifiable reference to the first (oldest) program entry
178     \sa Begin(), Last()
179 */
180 SamProgram& SamProgramChain::First(void) {
181
182     // find first record in container that has no PreviousProgramID entry
183     SamProgramIterator iter = Begin();
184     SamProgramIterator end  = End();
185     for ( ; iter != end; ++iter ) {
186         SamProgram& current = (*iter);
187         if ( !current.HasPreviousProgramID() )
188             return current;
189     }
190
191     // otherwise error
192     cerr << "SamProgramChain ERROR - could not find any record without a PP tag" << endl;
193     exit(1);
194 }
195
196 /*! \fn const SamProgram& SamProgramChain::First(void) const
197     \brief Fetches first (oldest) record in the chain.
198
199     This is an overloaded function.
200
201     N.B. - This function will fail if the chain is empty. If this is possible,
202     check the result of IsEmpty() before calling this function.
203
204     \return a read-only reference to the first (oldest) program entry
205     \sa Begin(), ConstBegin(), Last()
206 */
207 const SamProgram& SamProgramChain::First(void) const {
208
209     // find first record in container that has no PreviousProgramID entry
210     SamProgramConstIterator iter = ConstBegin();
211     SamProgramConstIterator end  = ConstEnd();
212     for ( ; iter != end; ++iter ) {
213         const SamProgram& current = (*iter);
214         if ( !current.HasPreviousProgramID() )
215             return current;
216     }
217
218     // otherwise error
219     cerr << "SamProgramChain ERROR - could not find any record without a PP tag" << endl;
220     exit(1);
221 }
222
223 /*! \fn int SamProgramChain::IndexOf(const std::string& programId) const
224     \internal
225     \return index of program record if found.
226     Otherwise, returns vector::size() (invalid index).
227 */
228 int SamProgramChain::IndexOf(const std::string& programId) const {
229     SamProgramConstIterator begin = ConstBegin();
230     SamProgramConstIterator iter  = begin;
231     SamProgramConstIterator end   = ConstEnd();
232     for ( ; iter != end; ++iter ) {
233         const SamProgram& current = (*iter);
234         if ( current.ID == programId )
235             break;
236     }
237     return distance( begin, iter );
238 }
239
240 /*! \fn bool SamProgramChain::IsEmpty(void) const
241     \brief Returns \c true if chain contains no records
242     \sa Size()
243 */
244 bool SamProgramChain::IsEmpty(void) const {
245     return m_data.empty();
246 }
247
248 /*! \fn SamProgram& SamProgramChain::Last(void)
249     \brief Fetches last (newest) record in the chain.
250
251     N.B. - This function will fail if the chain is empty. If this is possible,
252     check the result of IsEmpty() before calling this function.
253
254     \return a modifiable reference to the last (newest) program entry
255     \sa End(), First()
256 */
257 SamProgram& SamProgramChain::Last(void) {
258     // find first record in container that has no NextProgramID entry
259     SamProgramIterator iter = Begin();
260     SamProgramIterator end  = End();
261     for ( ; iter != end; ++iter ) {
262         SamProgram& current = (*iter);
263         if ( !current.HasNextProgramID() )
264             return current;
265     }
266
267     // otherwise error
268     cerr << "SamProgramChain ERROR - could not determine last record" << endl;
269     exit(1);
270 }
271
272 /*! \fn const SamProgram& SamProgramChain::Last(void) const
273     \brief Fetches last (newest) record in the chain.
274
275     This is an overloaded function.
276
277     N.B. - This function will fail if the chain is empty. If this is possible,
278     check the result of IsEmpty() before calling this function.
279
280     \return a read-only reference to the last (newest) program entry
281     \sa End(), ConstEnd(), First()
282 */
283 const SamProgram& SamProgramChain::Last(void) const {
284     // find first record in container that has no NextProgramID entry
285     SamProgramConstIterator iter = ConstBegin();
286     SamProgramConstIterator end  = ConstEnd();
287     for ( ; iter != end; ++iter ) {
288         const SamProgram& current = (*iter);
289         if ( !current.HasNextProgramID() )
290             return current;
291     }
292
293     // otherwise error
294     cerr << "SamProgramChain ERROR - could not determine last record" << endl;
295     exit(1);
296 }
297
298 /*! \fn const std::string SamProgramChain::NextIdFor(const std::string& programId) const
299     \internal
300     \return ID of program record, whose PreviousProgramID matches \a programId.
301     Otherwise, returns empty string if none found.
302 */
303 const std::string SamProgramChain::NextIdFor(const std::string& programId) const {
304
305     // find first record in container whose PreviousProgramID matches @programId
306     SamProgramConstIterator iter = ConstBegin();
307     SamProgramConstIterator end  = ConstEnd();
308     for ( ; iter != end; ++iter ) {
309         const SamProgram& current = (*iter);
310         if ( !current.HasPreviousProgramID() &&
311               current.PreviousProgramID == programId
312            )
313         {
314             return current.ID;
315         }
316     }
317
318     // none found
319     return string();
320 }
321
322 /*! \fn int SamProgramChain::Size(void) const
323     \brief Returns number of program records in the chain.
324     \sa IsEmpty()
325 */
326 int SamProgramChain::Size(void) const {
327     return m_data.size();
328 }
329
330 /*! \fn SamProgram& SamProgramChain::operator[](const std::string& programId)
331     \brief Retrieves the modifiable SamProgram record that matches \a programId.
332
333     NOTE - If the chain contains no read group matching this ID, this function will
334     print an error and terminate.
335
336     \param programId ID of program record to retrieve
337     \return a modifiable reference to the SamProgram associated with the ID
338 */
339 SamProgram& SamProgramChain::operator[](const std::string& programId) {
340
341     // look up program record matching this ID
342     int index = IndexOf(programId);
343
344     // if record not found
345     if ( index == (int)m_data.size() ) {
346         cerr << "SamProgramChain ERROR - unknown programId: " << programId << endl;
347         exit(1);
348     }
349
350     // otherwise return program record at index
351     return m_data.at(index);
352 }