]> git.donarmstrong.com Git - bamtools.git/blob - src/api/BamReader.cpp
58a2f3fa6893c4c20c3edab6c121720083436b29
[bamtools.git] / src / api / BamReader.cpp
1 // ***************************************************************************
2 // BamReader.cpp (c) 2009 Derek Barnett, Michael Str�mberg
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 10 October 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides read access to BAM files.
8 // ***************************************************************************
9
10 #include <api/BamReader.h>
11 #include <api/internal/BamReader_p.h>
12 using namespace BamTools;
13 using namespace BamTools::Internal;
14
15 #include <algorithm>
16 #include <iostream>
17 #include <iterator>
18 #include <string>
19 #include <vector>
20 using namespace std;
21
22 /*! \class BamTools::BamReader
23     \brief Provides read access to BAM files.
24 */
25
26 /*! \fn BamReader::BamReader(void)
27     \brief constructor
28 */
29 BamReader::BamReader(void)
30     : d(new BamReaderPrivate(this))
31 { }
32
33 /*! \fn BamReader::~BamReader(void)
34     \brief destructor
35 */
36 BamReader::~BamReader(void) {
37     delete d;
38     d = 0;
39 }
40
41 /*! \fn bool BamReader::Close(void)
42     \brief Closes the current BAM file.
43
44     Also clears out all header and reference data.
45
46     \return \c true if file closed OK
47     \sa IsOpen(), Open()
48 */
49 bool BamReader::Close(void) {
50     return d->Close();
51 }
52
53 /*! \fn bool BamReader::CreateIndex(const BamIndex::IndexType& type)
54     \brief Creates an index file for current BAM file.
55
56     \param[in] type file format to create, see BamIndex::IndexType for available formats
57     \return \c true if index created OK
58     \sa LocateIndex(), OpenIndex()
59 */
60 bool BamReader::CreateIndex(const BamIndex::IndexType& type) {
61     return d->CreateIndex(type);
62 }
63
64 /*! \fn std::string BamReader::GetErrorString(void) const
65     \brief Returns a human-readable description of the last error that occurred
66
67     This method allows elimination of STDERR pollution. Developers of client code
68     may choose how the messages are displayed to the user, if at all.
69
70     \return error description
71 */
72 string BamReader::GetErrorString(void) const {
73     return d->GetErrorString();
74 }
75
76 /*! \fn const std::string BamReader::GetFilename(void) const
77     \brief Returns name of current BAM file.
78
79     Retrieved filename will contain whatever was passed via Open().
80     If you need full directory paths here, be sure to include them
81     when you open the BAM file.
82
83     \returns name of open BAM file. If no file is open, returns an empty string.
84     \sa IsOpen()
85 */
86 const std::string BamReader::GetFilename(void) const {
87     return d->Filename();
88 }
89
90 /*! \fn SamHeader BamReader::GetHeader(void) const
91     \brief Returns SAM header data.
92
93     Header data is wrapped in a SamHeader object that can be conveniently queried & modified.
94
95     \note Modifying the retrieved SamHeader object does NOT affect the
96     current BAM file. This file has been opened in a read-only mode.
97     However, your modified SamHeader object can be used in conjunction with
98     BamWriter to generate a new BAM file with the appropriate header information.
99
100     \returns header data object
101     \sa GetHeaderText()
102 */
103 SamHeader BamReader::GetHeader(void) const {
104     return d->GetSamHeader();
105 }
106
107 /*! \fn std::string BamReader::GetHeaderText(void) const
108     \brief Returns SAM header data, as SAM-formatted text.
109
110     \note Modifying the retrieved text does NOT affect the current
111     BAM file. This file has been opened in a read-only mode. However,
112     your modified header text can be used in conjunction with BamWriter
113     to generate a new BAM file with the appropriate header information.
114
115     \returns SAM-formatted header text
116     \sa GetHeader()
117 */
118 std::string BamReader::GetHeaderText(void) const {
119     return d->GetHeaderText();
120 }
121
122 /*! \fn bool BamReader::GetNextAlignment(BamAlignment& alignment)
123     \brief Retrieves next available alignment.
124
125     Attempts to read the next alignment record from BAM file, and checks to see
126     if it overlaps the current region. If no region is currently set, then the
127     next alignment available is always considered valid.
128
129     If a region has been set, via Jump() or SetRegion(), an alignment is only
130     considered valid if it overlaps the region. If the actual 'next' alignment record
131     in the BAM file does not overlap this region, then this function will read sequentially
132     through the file until the next alignment that overlaps this region is found.
133     Once the region has been exhausted (i.e. the next alignment loaded is beyond the region),
134     the function aborts and returns \c false. In this case, there is no point to continue
135     reading, assuming properly sorted alignments.
136
137     This function fully populates all of the alignment's available data fields,
138     including the string data fields (read name, bases, qualities, tags, filename).
139     If only positional data (refID, position, CIGAR ops, alignment flags, etc.)
140     are required, consider using GetNextAlignmentCore() for a significant
141     performance boost.
142
143     \param[out] alignment destination for alignment record data
144     \returns \c true if a valid alignment was found
145 */
146 bool BamReader::GetNextAlignment(BamAlignment& alignment) {
147     return d->GetNextAlignment(alignment);
148 }
149
150 /*! \fn bool BamReader::GetNextAlignmentCore(BamAlignment& alignment)
151     \brief Retrieves next available alignment, without populating the alignment's string data fields.
152
153     Equivalent to GetNextAlignment() with respect to what is a valid overlapping alignment.
154
155     However, this method does NOT populate the alignment's string data fields
156     (read name, bases, qualities, tags, filename). This provides a boost in speed
157     when these fields are not required for every alignment. These fields can be
158     populated 'lazily' (as needed) by calling BamAlignment::BuildCharData() later.
159
160     \param[out] alignment destination for alignment record data
161     \returns \c true if a valid alignment was found
162     \sa SetRegion()
163 */
164 bool BamReader::GetNextAlignmentCore(BamAlignment& alignment) {
165     return d->GetNextAlignmentCore(alignment);
166 }
167
168 /*! \fn int BamReader::GetReferenceCount(void) const
169     \brief Returns number of reference sequences.
170 */
171 int BamReader::GetReferenceCount(void) const {
172     return d->GetReferenceCount();
173 }
174
175 /*! \fn const RefVector& BamReader::GetReferenceData(void) const
176     \brief Returns all reference sequence entries.
177     \sa RefData
178 */
179 const RefVector& BamReader::GetReferenceData(void) const {
180     return d->GetReferenceData();
181 }
182
183 /*! \fn int BamReader::GetReferenceID(const std::string& refName) const
184     \brief Returns the ID of the reference with this name.
185
186     If \a refName is not found, returns -1.
187
188     \param[in] refName name of reference to look up
189 */
190 int BamReader::GetReferenceID(const std::string& refName) const {
191     return d->GetReferenceID(refName);
192 }
193
194 /*! \fn bool BamReader::HasIndex(void) const
195     \brief Returns \c true if index data is available.
196 */
197 bool BamReader::HasIndex(void) const {
198     return d->HasIndex();
199 }
200
201 /*! \fn bool BamReader::IsOpen(void) const
202     \brief Returns \c true if a BAM file is open for reading.
203 */
204 bool BamReader::IsOpen(void) const {
205     return d->IsOpen();
206 }
207
208 /*! \fn bool BamReader::Jump(int refID, int position)
209     \brief Performs a random-access jump within BAM file.
210
211     This is a convenience method, equivalent to calling SetRegion()
212     with only a left boundary specified.
213
214     \param[in] refID    left-bound reference ID
215     \param[in] position left-bound position
216
217     \returns \c true if jump was successful
218     \sa HasIndex()
219 */
220 bool BamReader::Jump(int refID, int position) {
221     return d->SetRegion( BamRegion(refID, position) );
222 }
223
224 /*! \fn bool BamReader::LocateIndex(const BamIndex::IndexType& preferredType)
225     \brief Looks in BAM file's directory for a matching index file.
226
227     Use this function when you need an index file, and perhaps have a
228     preferred index format, but do not depend heavily on which format
229     actually gets loaded at runtime.
230
231     This function will defer to your \a preferredType whenever possible.
232     However, if an index file of \a preferredType can not be found, then
233     it will look for any other index file that corresponds to this BAM file.
234
235     If you want precise control over which index file is loaded, use OpenIndex()
236     with the desired index filename. If that function returns false, you can use
237     CreateIndex() to then build an index of the exact requested format.
238
239     \param[in] preferredType desired index file format, see BamIndex::IndexType for available formats
240
241     \returns \c true if (any) index file could be found
242 */
243 bool BamReader::LocateIndex(const BamIndex::IndexType& preferredType) {
244     return d->LocateIndex(preferredType);
245 }
246
247 /*! \fn bool BamReader::Open(const std::string& filename)
248     \brief Opens a BAM file.
249
250     If BamReader is already opened on another file, this function closes
251     that file, then attempts to open requested \a filename.
252
253     \param[in] filename name of BAM file to open
254
255     \returns \c true if BAM file was opened successfully
256     \sa Close(), IsOpen(), OpenIndex()
257 */
258 bool BamReader::Open(const std::string& filename) {
259     return d->Open(filename);
260 }
261
262 /*! \fn bool BamReader::OpenIndex(const std::string& indexFilename)
263     \brief Opens a BAM index file.
264
265     \param[in] indexFilename name of BAM index file to open
266
267     \returns \c true if BAM index file was opened & data loaded successfully
268     \sa LocateIndex(), Open(), SetIndex()
269 */
270 bool BamReader::OpenIndex(const std::string& indexFilename) {
271     return d->OpenIndex(indexFilename);
272 }
273
274 /*! \fn bool BamReader::Rewind(void)
275     \brief Returns the internal file pointer to the first alignment record.
276
277     Useful for performing multiple sequential passes through a BAM file.
278     Calling this function clears any prior region that may have been set.
279
280     \note This function sets the file pointer to first alignment record
281     in the BAM file, NOT the beginning of the file.
282
283     \returns \c true if rewind operation was successful
284     \sa Jump(), SetRegion()
285 */
286 bool BamReader::Rewind(void) {
287     return d->Rewind();
288 }
289
290 /*! \fn void BamReader::SetIndex(BamIndex* index)
291     \brief Sets a custom BamIndex on this reader.
292
293     Only necessary for custom BamIndex subclasses. Most clients should
294     never have to use this function.
295
296     Example:
297     \code
298         BamReader reader;
299         reader.SetIndex(new MyCustomBamIndex);
300     \endcode
301
302     \note BamReader takes ownership of \a index - i.e. the BamReader will
303     take care of deleting it when the reader is destructed, when the current
304     BAM file is closed, or when a new index is requested.
305
306     \param[in] index custom BamIndex subclass created by client
307     \sa CreateIndex(), LocateIndex(), OpenIndex()
308 */
309 void BamReader::SetIndex(BamIndex* index) {
310     d->SetIndex(index);
311 }
312
313 /*! \fn void BamReader::SetIndexCacheMode(const BamIndex::IndexCacheMode& mode)
314     \brief Changes the caching behavior of the index data.
315
316     Default mode is BamIndex::LimitedIndexCaching.
317
318     \param[in] mode desired cache mode for index, see BamIndex::IndexCacheMode for
319                     description of the available cache modes
320     \sa HasIndex()
321 */
322 void BamReader::SetIndexCacheMode(const BamIndex::IndexCacheMode& mode) {
323     d->SetIndexCacheMode(mode);
324 }
325
326 /*! \fn bool BamReader::SetRegion(const BamRegion& region)
327     \brief Sets a target region of interest
328
329     Requires that index data be available. Attempts a random-access
330     jump in the BAM file, near \a region left boundary position.
331
332     Subsequent calls to GetNextAlignment() or GetNextAlignmentCore()
333     will only return \c true when alignments can be found that overlap
334     this \a region.
335
336     A \a region with no right boundary is considered open-ended, meaning
337     that all alignments that lie downstream of the left boundary are
338     considered valid, continuing to the end of the BAM file.
339
340     \warning BamRegion now represents a zero-based, HALF-OPEN interval.
341     In previous versions of BamTools (0.x & 1.x) all intervals were treated
342     as zero-based, CLOSED.
343
344     \param[in] region desired region-of-interest to activate
345
346     \returns \c true if reader was able to jump successfully to the region's left boundary
347     \sa HasIndex(), Jump()
348 */
349 bool BamReader::SetRegion(const BamRegion& region) {
350     return d->SetRegion(region);
351 }
352
353 /*! \fn bool BamReader::SetRegion(const int& leftRefID,
354                                   const int& leftPosition,
355                                   const int& rightRefID,
356                                   const int& rightPosition)
357     \brief Sets a target region of interest.
358
359     This is an overloaded function.
360
361     \warning This function expects a zero-based, HALF-OPEN interval.
362     In previous versions of BamTools (0.x & 1.x) all intervals were treated
363     as zero-based, CLOSED.
364
365     \param[in] leftRefID     referenceID of region's left boundary
366     \param[in] leftPosition  position of region's left boundary
367     \param[in] rightRefID    reference ID of region's right boundary
368     \param[in] rightPosition position of region's right boundary
369
370     \returns \c true if reader was able to jump successfully to the region's left boundary
371     \sa HasIndex(), Jump()
372 */
373 bool BamReader::SetRegion(const int& leftRefID,
374                           const int& leftBound,
375                           const int& rightRefID,
376                           const int& rightBound)
377 {
378     return d->SetRegion( BamRegion(leftRefID, leftBound, rightRefID, rightBound) );
379 }