annotate spp/src/BamReader_p.cpp @ 6:ce08b0efa3fd draft

Uploaded
author zzhou
date Tue, 27 Nov 2012 16:11:40 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
1 // ***************************************************************************
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
2 // BamReader_p.cpp (c) 2009 Derek Barnett
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
3 // Marth Lab, Department of Biology, Boston College
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
4 // All rights reserved.
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
5 // ---------------------------------------------------------------------------
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
6 // Last modified: 22 November 2010 (DB)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
7 // ---------------------------------------------------------------------------
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
8 // Provides the basic functionality for reading BAM files
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
9 // ***************************************************************************
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
10
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
11 #include <BamReader.h>
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
12 #include <BGZF.h>
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
13 #include <BamReader_p.h>
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
14 #include <BamStandardIndex_p.h>
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
15 #include <BamToolsIndex_p.h>
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
16 using namespace BamTools;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
17 using namespace BamTools::Internal;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
18
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
19 #include <algorithm>
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
20 #include <iostream>
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
21 #include <iterator>
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
22 #include <vector>
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
23 using namespace std;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
24
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
25 // constructor
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
26 BamReaderPrivate::BamReaderPrivate(BamReader* parent)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
27 : HeaderText("")
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
28 , Index(0)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
29 , HasIndex(false)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
30 , AlignmentsBeginOffset(0)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
31 // , m_header(0)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
32 , IndexCacheMode(BamIndex::LimitedIndexCaching)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
33 , HasAlignmentsInRegion(true)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
34 , Parent(parent)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
35 , DNA_LOOKUP("=ACMGRSVTWYHKDBN")
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
36 , CIGAR_LOOKUP("MIDNSHP")
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
37 {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
38 IsBigEndian = SystemIsBigEndian();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
39 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
40
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
41 // destructor
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
42 BamReaderPrivate::~BamReaderPrivate(void) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
43 Close();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
44 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
45
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
46 // adjusts requested region if necessary (depending on where data actually begins)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
47 void BamReaderPrivate::AdjustRegion(BamRegion& region) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
48
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
49 // check for valid index first
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
50 if ( Index == 0 ) return;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
51
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
52 // see if any references in region have alignments
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
53 HasAlignmentsInRegion = false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
54 int currentId = region.LeftRefID;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
55
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
56 const int rightBoundRefId = ( region.isRightBoundSpecified() ? region.RightRefID : References.size() - 1 );
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
57 while ( currentId <= rightBoundRefId ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
58 HasAlignmentsInRegion = Index->HasAlignments(currentId);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
59 if ( HasAlignmentsInRegion ) break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
60 ++currentId;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
61 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
62
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
63 // if no data found on any reference in region
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
64 if ( !HasAlignmentsInRegion ) return;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
65
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
66 // if left bound of desired region had no data, use first reference that had data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
67 // otherwise, leave requested region as-is
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
68 if ( currentId != region.LeftRefID ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
69 region.LeftRefID = currentId;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
70 region.LeftPosition = 0;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
71 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
72 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
73
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
74 // fills out character data for BamAlignment data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
75 bool BamReaderPrivate::BuildCharData(BamAlignment& bAlignment) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
76
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
77 // calculate character lengths/offsets
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
78 const unsigned int dataLength = bAlignment.SupportData.BlockLength - BAM_CORE_SIZE;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
79 const unsigned int seqDataOffset = bAlignment.SupportData.QueryNameLength + (bAlignment.SupportData.NumCigarOperations * 4);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
80 const unsigned int qualDataOffset = seqDataOffset + (bAlignment.SupportData.QuerySequenceLength+1)/2;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
81 const unsigned int tagDataOffset = qualDataOffset + bAlignment.SupportData.QuerySequenceLength;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
82 const unsigned int tagDataLength = dataLength - tagDataOffset;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
83
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
84 // check offsets to see what char data exists
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
85 const bool hasSeqData = ( seqDataOffset < dataLength );
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
86 const bool hasQualData = ( qualDataOffset < dataLength );
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
87 const bool hasTagData = ( tagDataOffset < dataLength );
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
88
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
89 // set up char buffers
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
90 const char* allCharData = bAlignment.SupportData.AllCharData.data();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
91 const char* seqData = ( hasSeqData ? (((const char*)allCharData) + seqDataOffset) : (const char*)0 );
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
92 const char* qualData = ( hasQualData ? (((const char*)allCharData) + qualDataOffset) : (const char*)0 );
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
93 char* tagData = ( hasTagData ? (((char*)allCharData) + tagDataOffset) : (char*)0 );
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
94
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
95 // store alignment name (relies on null char in name as terminator)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
96 bAlignment.Name.assign((const char*)(allCharData));
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
97
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
98 // save query sequence
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
99 bAlignment.QueryBases.clear();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
100 if ( hasSeqData ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
101 bAlignment.QueryBases.reserve(bAlignment.SupportData.QuerySequenceLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
102 for (unsigned int i = 0; i < bAlignment.SupportData.QuerySequenceLength; ++i) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
103 char singleBase = DNA_LOOKUP[ ( (seqData[(i/2)] >> (4*(1-(i%2)))) & 0xf ) ];
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
104 bAlignment.QueryBases.append(1, singleBase);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
105 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
106 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
107
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
108 // save qualities, converting from numeric QV to 'FASTQ-style' ASCII character
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
109 bAlignment.Qualities.clear();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
110 if ( hasQualData ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
111 bAlignment.Qualities.reserve(bAlignment.SupportData.QuerySequenceLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
112 for (unsigned int i = 0; i < bAlignment.SupportData.QuerySequenceLength; ++i) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
113 char singleQuality = (char)(qualData[i]+33);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
114 bAlignment.Qualities.append(1, singleQuality);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
115 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
116 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
117
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
118 // if QueryBases is empty (and this is a allowed case)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
119 if ( bAlignment.QueryBases.empty() )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
120 bAlignment.AlignedBases = bAlignment.QueryBases;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
121
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
122 // if QueryBases contains data, then build AlignedBases using CIGAR data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
123 else {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
124
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
125 // resize AlignedBases
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
126 bAlignment.AlignedBases.clear();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
127 bAlignment.AlignedBases.reserve(bAlignment.SupportData.QuerySequenceLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
128
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
129 // iterate over CigarOps
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
130 int k = 0;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
131 vector<CigarOp>::const_iterator cigarIter = bAlignment.CigarData.begin();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
132 vector<CigarOp>::const_iterator cigarEnd = bAlignment.CigarData.end();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
133 for ( ; cigarIter != cigarEnd; ++cigarIter ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
134
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
135 const CigarOp& op = (*cigarIter);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
136 switch(op.Type) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
137
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
138 case ('M') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
139 case ('I') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
140 bAlignment.AlignedBases.append(bAlignment.QueryBases.substr(k, op.Length)); // for 'M', 'I' - write bases
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
141 // fall through
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
142
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
143 case ('S') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
144 k += op.Length; // for 'S' - soft clip, skip over query bases
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
145 break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
146
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
147 case ('D') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
148 bAlignment.AlignedBases.append(op.Length, '-'); // for 'D' - write gap character
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
149 break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
150
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
151 case ('P') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
152 bAlignment.AlignedBases.append( op.Length, '*' ); // for 'P' - write padding character
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
153 break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
154
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
155 case ('N') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
156 bAlignment.AlignedBases.append( op.Length, 'N' ); // for 'N' - write N's, skip bases in original query sequence
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
157 break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
158
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
159 case ('H') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
160 break; // for 'H' - hard clip, do nothing to AlignedBases, move to next op
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
161
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
162 default:
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
163 fprintf(stderr, "ERROR: Invalid Cigar op type\n"); // shouldn't get here
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
164 exit(1);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
165 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
166 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
167 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
168
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
169 // save tag data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
170 bAlignment.TagData.clear();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
171 if ( hasTagData ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
172 if ( IsBigEndian ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
173 int i = 0;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
174 while ( (unsigned int)i < tagDataLength ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
175
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
176 i += 2; // skip tag type (e.g. "RG", "NM", etc)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
177 uint8_t type = toupper(tagData[i]); // lower & upper case letters have same meaning
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
178 ++i; // skip value type
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
179
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
180 switch (type) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
181
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
182 case('A') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
183 case('C') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
184 ++i;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
185 break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
186
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
187 case('S') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
188 SwapEndian_16p(&tagData[i]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
189 i += sizeof(uint16_t);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
190 break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
191
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
192 case('F') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
193 case('I') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
194 SwapEndian_32p(&tagData[i]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
195 i += sizeof(uint32_t);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
196 break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
197
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
198 case('D') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
199 SwapEndian_64p(&tagData[i]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
200 i += sizeof(uint64_t);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
201 break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
202
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
203 case('H') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
204 case('Z') :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
205 while (tagData[i]) { ++i; }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
206 ++i; // increment one more for null terminator
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
207 break;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
208
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
209 default :
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
210 fprintf(stderr, "ERROR: Invalid tag value type\n"); // shouldn't get here
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
211 exit(1);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
212 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
213 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
214 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
215
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
216 // store tagData in alignment
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
217 bAlignment.TagData.resize(tagDataLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
218 memcpy((char*)bAlignment.TagData.data(), tagData, tagDataLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
219 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
220
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
221 // clear the core-only flag
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
222 bAlignment.SupportData.HasCoreOnly = false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
223
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
224 // return success
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
225 return true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
226 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
227
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
228 // clear index data structure
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
229 void BamReaderPrivate::ClearIndex(void) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
230 delete Index;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
231 Index = 0;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
232 HasIndex = false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
233 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
234
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
235 // closes the BAM file
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
236 void BamReaderPrivate::Close(void) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
237
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
238 // close BGZF file stream
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
239 mBGZF.Close();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
240
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
241 // clear out index data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
242 ClearIndex();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
243
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
244 // clear out header data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
245 HeaderText.clear();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
246 // if ( m_header ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
247 // delete m_header;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
248 // m_header = 0;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
249 // }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
250
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
251 // clear out region flags
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
252 Region.clear();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
253 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
254
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
255 // creates index for BAM file, saves to file
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
256 // default behavior is to create the BAM standard index (".bai")
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
257 // set flag to false to create the BamTools-specific index (".bti")
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
258 bool BamReaderPrivate::CreateIndex(bool useStandardIndex) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
259
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
260 // clear out prior index data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
261 ClearIndex();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
262
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
263 // create index based on type requested
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
264 if ( useStandardIndex )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
265 Index = new BamStandardIndex(&mBGZF, Parent);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
266 else
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
267 Index = new BamToolsIndex(&mBGZF, Parent);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
268
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
269 // set index cache mode to full for writing
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
270 Index->SetCacheMode(BamIndex::FullIndexCaching);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
271
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
272 // build new index
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
273 bool ok = true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
274 ok &= Index->Build();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
275 HasIndex = ok;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
276
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
277 // mark empty references
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
278 MarkReferences();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
279
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
280 // attempt to save index data to file
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
281 ok &= Index->Write(Filename);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
282
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
283 // set client's desired index cache mode
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
284 Index->SetCacheMode(IndexCacheMode);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
285
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
286 // return success/fail of both building & writing index
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
287 return ok;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
288 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
289
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
290 const string BamReaderPrivate::GetHeaderText(void) const {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
291
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
292 return HeaderText;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
293
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
294 // if ( m_header )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
295 // return m_header->Text();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
296 // else
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
297 // return string("");
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
298 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
299
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
300 // get next alignment (from specified region, if given)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
301 bool BamReaderPrivate::GetNextAlignment(BamAlignment& bAlignment) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
302
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
303 // if valid alignment found, attempt to parse char data, and return success/failure
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
304 if ( GetNextAlignmentCore(bAlignment) )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
305 return BuildCharData(bAlignment);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
306
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
307 // no valid alignment found
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
308 else return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
309 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
310
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
311 // retrieves next available alignment core data (returns success/fail)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
312 // ** DOES NOT parse any character data (read name, bases, qualities, tag data)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
313 // these can be accessed, if necessary, from the supportData
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
314 // useful for operations requiring ONLY positional or other alignment-related information
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
315 bool BamReaderPrivate::GetNextAlignmentCore(BamAlignment& bAlignment) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
316
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
317 // if region is set but has no alignments
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
318 if ( !Region.isNull() && !HasAlignmentsInRegion )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
319 return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
320
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
321 // if valid alignment available
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
322 if ( LoadNextAlignment(bAlignment) ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
323
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
324 // set core-only flag
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
325 bAlignment.SupportData.HasCoreOnly = true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
326
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
327 // if region not specified with at least a left boundary, return success
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
328 if ( !Region.isLeftBoundSpecified() ) return true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
329
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
330 // determine region state (before, within, after)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
331 BamReaderPrivate::RegionState state = IsOverlap(bAlignment);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
332
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
333 // if alignment lies after region, return false
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
334 if ( state == AFTER_REGION ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
335
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
336 while ( state != WITHIN_REGION ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
337 // if no valid alignment available (likely EOF) return failure
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
338 if ( !LoadNextAlignment(bAlignment) ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
339 // if alignment lies after region, return false (no available read within region)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
340 state = IsOverlap(bAlignment);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
341 if ( state == AFTER_REGION ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
342 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
343
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
344 // return success (alignment found that overlaps region)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
345 return true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
346 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
347
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
348 // no valid alignment
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
349 else return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
350 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
351
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
352 // returns RefID for given RefName (returns References.size() if not found)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
353 int BamReaderPrivate::GetReferenceID(const string& refName) const {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
354
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
355 // retrieve names from reference data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
356 vector<string> refNames;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
357 RefVector::const_iterator refIter = References.begin();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
358 RefVector::const_iterator refEnd = References.end();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
359 for ( ; refIter != refEnd; ++refIter)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
360 refNames.push_back( (*refIter).RefName );
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
361
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
362 // return 'index-of' refName ( if not found, returns refNames.size() )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
363 return distance(refNames.begin(), find(refNames.begin(), refNames.end(), refName));
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
364 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
365
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
366 // returns region state - whether alignment ends before, overlaps, or starts after currently specified region
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
367 // this *internal* method should ONLY called when (at least) IsLeftBoundSpecified == true
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
368 BamReaderPrivate::RegionState BamReaderPrivate::IsOverlap(BamAlignment& bAlignment) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
369
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
370 // if alignment is on any reference sequence before left bound
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
371 if ( bAlignment.RefID < Region.LeftRefID ) return BEFORE_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
372
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
373 // if alignment starts on left bound reference
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
374 else if ( bAlignment.RefID == Region.LeftRefID ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
375
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
376 // if alignment starts at or after left boundary
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
377 if ( bAlignment.Position >= Region.LeftPosition) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
378
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
379 // if right boundary is specified AND
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
380 // left/right boundaries are on same reference AND
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
381 // alignment starts past right boundary
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
382 if ( Region.isRightBoundSpecified() &&
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
383 Region.LeftRefID == Region.RightRefID &&
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
384 bAlignment.Position > Region.RightPosition )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
385 return AFTER_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
386
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
387 // otherwise, alignment is within region
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
388 return WITHIN_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
389 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
390
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
391 // alignment starts before left boundary
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
392 else {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
393 // check if alignment overlaps left boundary
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
394 if ( bAlignment.GetEndPosition() >= Region.LeftPosition ) return WITHIN_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
395 else return BEFORE_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
396 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
397 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
398
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
399 // alignment starts on a reference after the left bound
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
400 else {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
401
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
402 // if region has a right boundary
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
403 if ( Region.isRightBoundSpecified() ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
404
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
405 // alignment is on reference between boundaries
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
406 if ( bAlignment.RefID < Region.RightRefID ) return WITHIN_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
407
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
408 // alignment is on reference after right boundary
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
409 else if ( bAlignment.RefID > Region.RightRefID ) return AFTER_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
410
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
411 // alignment is on right bound reference
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
412 else {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
413 // check if alignment starts before or at right boundary
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
414 if ( bAlignment.Position <= Region.RightPosition ) return WITHIN_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
415 else return AFTER_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
416 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
417 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
418
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
419 // otherwise, alignment is after left bound reference, but there is no right boundary
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
420 else return WITHIN_REGION;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
421 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
422 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
423
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
424 // load BAM header data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
425 void BamReaderPrivate::LoadHeaderData(void) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
426
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
427 // m_header = new BamHeader(&mBGZF);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
428 // bool headerLoadedOk = m_header->Load();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
429 // if ( !headerLoadedOk )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
430 // cerr << "BamReader could not load header" << endl;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
431
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
432 // check to see if proper BAM header
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
433 char buffer[4];
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
434 if (mBGZF.Read(buffer, 4) != 4) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
435 fprintf(stderr, "Could not read header type\n");
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
436 exit(1);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
437 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
438
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
439 if (strncmp(buffer, "BAM\001", 4)) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
440 fprintf(stderr, "wrong header type!\n");
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
441 exit(1);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
442 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
443
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
444 // get BAM header text length
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
445 mBGZF.Read(buffer, 4);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
446 unsigned int headerTextLength = BgzfData::UnpackUnsignedInt(buffer);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
447 if ( IsBigEndian ) SwapEndian_32(headerTextLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
448
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
449 // get BAM header text
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
450 char* headerText = (char*)calloc(headerTextLength + 1, 1);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
451 mBGZF.Read(headerText, headerTextLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
452 HeaderText = (string)((const char*)headerText);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
453
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
454 // clean up calloc-ed temp variable
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
455 free(headerText);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
456 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
457
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
458 // load existing index data from BAM index file (".bti" OR ".bai"), return success/fail
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
459 bool BamReaderPrivate::LoadIndex(const bool lookForIndex, const bool preferStandardIndex) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
460
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
461 // clear out any existing index data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
462 ClearIndex();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
463
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
464 // if no index filename provided, so we need to look for available index files
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
465 if ( IndexFilename.empty() ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
466
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
467 // attempt to load BamIndex based on current Filename provided & preferStandardIndex flag
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
468 const BamIndex::PreferredIndexType type = (preferStandardIndex ? BamIndex::STANDARD : BamIndex::BAMTOOLS);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
469 Index = BamIndex::FromBamFilename(Filename, &mBGZF, Parent, type);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
470
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
471 // if null, return failure
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
472 if ( Index == 0 ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
473
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
474 // generate proper IndexFilename based on type of index created
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
475 IndexFilename = Filename + Index->Extension();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
476 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
477
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
478 else {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
479
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
480 // attempt to load BamIndex based on IndexFilename provided by client
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
481 Index = BamIndex::FromIndexFilename(IndexFilename, &mBGZF, Parent);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
482
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
483 // if null, return failure
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
484 if ( Index == 0 ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
485 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
486
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
487 // set cache mode for BamIndex
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
488 Index->SetCacheMode(IndexCacheMode);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
489
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
490 // loading the index data from file
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
491 HasIndex = Index->Load(IndexFilename);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
492
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
493 // mark empty references
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
494 MarkReferences();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
495
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
496 // return index status
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
497 return HasIndex;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
498 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
499
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
500 // populates BamAlignment with alignment data under file pointer, returns success/fail
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
501 bool BamReaderPrivate::LoadNextAlignment(BamAlignment& bAlignment) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
502
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
503 // read in the 'block length' value, make sure it's not zero
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
504 char buffer[4];
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
505 mBGZF.Read(buffer, 4);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
506 bAlignment.SupportData.BlockLength = BgzfData::UnpackUnsignedInt(buffer);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
507 if ( IsBigEndian ) { SwapEndian_32(bAlignment.SupportData.BlockLength); }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
508 if ( bAlignment.SupportData.BlockLength == 0 ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
509
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
510 // read in core alignment data, make sure the right size of data was read
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
511 char x[BAM_CORE_SIZE];
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
512 if ( mBGZF.Read(x, BAM_CORE_SIZE) != BAM_CORE_SIZE ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
513
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
514 if ( IsBigEndian ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
515 for ( int i = 0; i < BAM_CORE_SIZE; i+=sizeof(uint32_t) )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
516 SwapEndian_32p(&x[i]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
517 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
518
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
519 // set BamAlignment 'core' and 'support' data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
520 bAlignment.RefID = BgzfData::UnpackSignedInt(&x[0]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
521 bAlignment.Position = BgzfData::UnpackSignedInt(&x[4]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
522
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
523 unsigned int tempValue = BgzfData::UnpackUnsignedInt(&x[8]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
524 bAlignment.Bin = tempValue >> 16;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
525 bAlignment.MapQuality = tempValue >> 8 & 0xff;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
526 bAlignment.SupportData.QueryNameLength = tempValue & 0xff;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
527
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
528 tempValue = BgzfData::UnpackUnsignedInt(&x[12]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
529 bAlignment.AlignmentFlag = tempValue >> 16;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
530 bAlignment.SupportData.NumCigarOperations = tempValue & 0xffff;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
531
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
532 bAlignment.SupportData.QuerySequenceLength = BgzfData::UnpackUnsignedInt(&x[16]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
533 bAlignment.MateRefID = BgzfData::UnpackSignedInt(&x[20]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
534 bAlignment.MatePosition = BgzfData::UnpackSignedInt(&x[24]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
535 bAlignment.InsertSize = BgzfData::UnpackSignedInt(&x[28]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
536
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
537 // set BamAlignment length
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
538 bAlignment.Length = bAlignment.SupportData.QuerySequenceLength;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
539
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
540 // read in character data - make sure proper data size was read
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
541 bool readCharDataOK = false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
542 const unsigned int dataLength = bAlignment.SupportData.BlockLength - BAM_CORE_SIZE;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
543 char* allCharData = (char*)calloc(sizeof(char), dataLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
544
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
545 if ( mBGZF.Read(allCharData, dataLength) == (signed int)dataLength) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
546
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
547 // store 'allCharData' in supportData structure
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
548 bAlignment.SupportData.AllCharData.assign((const char*)allCharData, dataLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
549
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
550 // set success flag
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
551 readCharDataOK = true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
552
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
553 // save CIGAR ops
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
554 // need to calculate this here so that BamAlignment::GetEndPosition() performs correctly,
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
555 // even when GetNextAlignmentCore() is called
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
556 const unsigned int cigarDataOffset = bAlignment.SupportData.QueryNameLength;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
557 uint32_t* cigarData = (uint32_t*)(allCharData + cigarDataOffset);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
558 CigarOp op;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
559 bAlignment.CigarData.clear();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
560 bAlignment.CigarData.reserve(bAlignment.SupportData.NumCigarOperations);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
561 for (unsigned int i = 0; i < bAlignment.SupportData.NumCigarOperations; ++i) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
562
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
563 // swap if necessary
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
564 if ( IsBigEndian ) SwapEndian_32(cigarData[i]);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
565
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
566 // build CigarOp structure
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
567 op.Length = (cigarData[i] >> BAM_CIGAR_SHIFT);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
568 op.Type = CIGAR_LOOKUP[ (cigarData[i] & BAM_CIGAR_MASK) ];
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
569
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
570 // save CigarOp
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
571 bAlignment.CigarData.push_back(op);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
572 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
573 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
574
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
575 free(allCharData);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
576 return readCharDataOK;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
577 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
578
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
579 // loads reference data from BAM file
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
580 void BamReaderPrivate::LoadReferenceData(void) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
581
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
582 // get number of reference sequences
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
583 char buffer[4];
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
584 mBGZF.Read(buffer, 4);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
585 unsigned int numberRefSeqs = BgzfData::UnpackUnsignedInt(buffer);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
586 if ( IsBigEndian ) SwapEndian_32(numberRefSeqs);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
587 if ( numberRefSeqs == 0 ) return;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
588 References.reserve((int)numberRefSeqs);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
589
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
590 // iterate over all references in header
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
591 for (unsigned int i = 0; i != numberRefSeqs; ++i) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
592
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
593 // get length of reference name
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
594 mBGZF.Read(buffer, 4);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
595 unsigned int refNameLength = BgzfData::UnpackUnsignedInt(buffer);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
596 if ( IsBigEndian ) SwapEndian_32(refNameLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
597 char* refName = (char*)calloc(refNameLength, 1);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
598
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
599 // get reference name and reference sequence length
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
600 mBGZF.Read(refName, refNameLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
601 mBGZF.Read(buffer, 4);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
602 int refLength = BgzfData::UnpackSignedInt(buffer);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
603 if ( IsBigEndian ) SwapEndian_32(refLength);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
604
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
605 // store data for reference
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
606 RefData aReference;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
607 aReference.RefName = (string)((const char*)refName);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
608 aReference.RefLength = refLength;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
609 References.push_back(aReference);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
610
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
611 // clean up calloc-ed temp variable
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
612 free(refName);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
613 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
614 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
615
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
616 // mark references with no alignment data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
617 void BamReaderPrivate::MarkReferences(void) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
618
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
619 // ensure index is available
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
620 if ( !HasIndex ) return;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
621
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
622 // mark empty references
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
623 for ( int i = 0; i < (int)References.size(); ++i )
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
624 References.at(i).RefHasAlignments = Index->HasAlignments(i);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
625 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
626
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
627 // opens BAM file (and index)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
628 bool BamReaderPrivate::Open(const string& filename, const string& indexFilename, const bool lookForIndex, const bool preferStandardIndex) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
629
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
630 // store filenames
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
631 Filename = filename;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
632 IndexFilename = indexFilename;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
633
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
634 // open the BGZF file for reading, return false on failure
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
635 if ( !mBGZF.Open(filename, "rb") ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
636
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
637 // retrieve header text & reference data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
638 LoadHeaderData();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
639 LoadReferenceData();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
640
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
641 // store file offset of first alignment
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
642 AlignmentsBeginOffset = mBGZF.Tell();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
643
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
644 // if no index filename provided
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
645 if ( IndexFilename.empty() ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
646
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
647 // client did not specify that index SHOULD be found
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
648 // useful for cases where sequential access is all that is required
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
649 if ( !lookForIndex ) return true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
650
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
651 // otherwise, look for index file, return success/fail
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
652 return LoadIndex(lookForIndex, preferStandardIndex) ;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
653 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
654
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
655 // client supplied an index filename
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
656 // attempt to load index data, return success/fail
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
657 return LoadIndex(lookForIndex, preferStandardIndex);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
658 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
659
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
660 // returns BAM file pointer to beginning of alignment data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
661 bool BamReaderPrivate::Rewind(void) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
662
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
663 // rewind to first alignment, return false if unable to seek
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
664 if ( !mBGZF.Seek(AlignmentsBeginOffset) ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
665
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
666 // retrieve first alignment data, return false if unable to read
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
667 BamAlignment al;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
668 if ( !LoadNextAlignment(al) ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
669
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
670 // reset default region info using first alignment in file
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
671 Region.clear();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
672 HasAlignmentsInRegion = true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
673
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
674 // rewind back to beginning of first alignment
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
675 // return success/fail of seek
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
676 return mBGZF.Seek(AlignmentsBeginOffset);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
677 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
678
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
679 // change the index caching behavior
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
680 void BamReaderPrivate::SetIndexCacheMode(const BamIndex::BamIndexCacheMode mode) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
681 IndexCacheMode = mode;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
682 if ( Index == 0 ) return;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
683 Index->SetCacheMode(mode);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
684 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
685
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
686 // asks Index to attempt a Jump() to specified region
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
687 // returns success/failure
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
688 bool BamReaderPrivate::SetRegion(const BamRegion& region) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
689
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
690 // clear out any prior BamReader region data
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
691 //
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
692 // N.B. - this is cleared so that BamIndex now has free reign to call
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
693 // GetNextAlignmentCore() and do overlap checking without worrying about BamReader
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
694 // performing any overlap checking of its own and moving on to the next read... Calls
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
695 // to GetNextAlignmentCore() with no Region set, simply return the next alignment.
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
696 // This ensures that the Index is able to do just that. (All without exposing
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
697 // LoadNextAlignment() to the public API, and potentially confusing clients with the nomenclature)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
698 Region.clear();
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
699
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
700 // check for existing index
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
701 if ( !HasIndex ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
702
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
703 // adjust region if necessary to reflect where data actually begins
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
704 BamRegion adjustedRegion(region);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
705 AdjustRegion(adjustedRegion);
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
706
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
707 // if no data present, return true
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
708 // not an error, but BamReader knows that no data is there for future alignment access
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
709 // (this is useful in a MultiBamReader setting where some BAM files may lack data in regions
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
710 // that other BAMs have data)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
711 if ( !HasAlignmentsInRegion ) {
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
712 Region = adjustedRegion;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
713 return true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
714 }
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
715
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
716 // attempt jump to user-specified region return false if jump could not be performed at all
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
717 // (invalid index, unknown reference, etc)
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
718 //
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
719 // Index::Jump() is allowed to modify the HasAlignmentsInRegion flag
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
720 // * This covers case where a region is requested that lies beyond the last alignment on a reference
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
721 // If this occurs, any subsequent calls to GetNexAlignment[Core] simply return false
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
722 // BamMultiReader is then able to successfully pull alignments from a region from multiple files
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
723 // even if one or more have no data.
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
724 if ( !Index->Jump(adjustedRegion, &HasAlignmentsInRegion) ) return false;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
725
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
726 // save region and return success
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
727 Region = adjustedRegion;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
728 return true;
ce08b0efa3fd Uploaded
zzhou
parents:
diff changeset
729 }