1 BamConversionMain.cpp
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000001656
\011307517135
\0015027
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#include <iostream>
4 using namespace BamTools;
7 int main(int argc, char* argv[]) {
10 cout << "USAGE: " << argv[0] << " <input BAM file> <output BAM file>" << endl;
14 // localize our arguments
15 const char* inputFilename = argv[1];
16 const char* outputFilename = argv[2];
18 // open our BAM reader
20 reader.Open(inputFilename);
22 // retrieve the SAM header text
23 string samHeader = reader.GetHeaderText();
25 // retrieve the reference sequence vector
26 RefVector referenceSequences = reader.GetReferenceData();
28 // open the BAM writer
30 writer.Open(outputFilename, samHeader, referenceSequences);
32 // copy all of the reads from the input file to the output file
34 while(reader.GetNextAlignment(al)) writer.SaveAlignment(al);
42 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0BamDumpMain.cpp
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000003172
\011307517135
\0013602
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0// ***************************************************************************
\r
43 // BamDump.cpp (c) 2009 Derek Barnett
\r
44 // Marth Lab, Department of Biology, Boston College
\r
45 // All rights reserved.
\r
46 // ---------------------------------------------------------------------------
\r
47 // Last modified: 15 July 2009 (DB)
\r
48 // ---------------------------------------------------------------------------
\r
49 // Spits out all alignments in BAM file.
\r
51 // N.B. - Could result in HUGE text file. This is mostly a debugging tool
\r
52 // for small files. You have been warned.
\r
53 // ***************************************************************************
\r
55 // Std C/C++ includes
\r
59 using namespace std;
\r
61 // BamTools includes
\r
62 #include "BamReader.h"
\r
63 #include "BamWriter.h"
\r
64 using namespace BamTools;
\r
66 void PrintAlignment(const BamAlignment&);
\r
68 int main(int argc, char* argv[]) {
\r
70 // validate argument count
\r
72 cerr << "USAGE: " << argv[0] << " <input BAM file> " << endl;
\r
76 string filename = argv[1];
\r
77 cout << "Printing alignments from file: " << filename << endl;
\r
80 reader.Open(filename);
\r
82 BamAlignment bAlignment;
\r
83 while (reader.GetNextAlignment(bAlignment)) {
\r
84 PrintAlignment(bAlignment);
\r
91 // Spit out basic BamAlignment data
\r
92 void PrintAlignment(const BamAlignment& alignment) {
\r
93 cout << "---------------------------------" << endl;
\r
94 cout << "Name: " << alignment.Name << endl;
\r
95 cout << "Aligned to: " << alignment.RefID;
\r
96 cout << ":" << alignment.Position << endl;
\r
98 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0BamReader.cpp
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000107374
\011307521263
\0013300
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0// ***************************************************************************
\r
99 // BamReader.cpp (c) 2009 Derek Barnett, Michael Strömberg
\r
100 // Marth Lab, Department of Biology, Boston College
\r
101 // All rights reserved.
\r
102 // ---------------------------------------------------------------------------
\r
103 // Last modified: 8 December 2009 (DB)
\r
104 // ---------------------------------------------------------------------------
\r
105 // Uses BGZF routines were adapted from the bgzf.c code developed at the Broad
\r
107 // ---------------------------------------------------------------------------
\r
108 // Provides the basic functionality for reading BAM files
\r
109 // ***************************************************************************
\r
112 #include <algorithm>
\r
113 #include <iterator>
\r
117 // BamTools includes
\r
119 #include "BamReader.h"
\r
120 using namespace BamTools;
\r
121 using namespace std;
\r
123 struct BamReader::BamReaderPrivate {
\r
125 // -------------------------------
\r
127 // -------------------------------
\r
133 RefVector References;
\r
134 bool IsIndexLoaded;
\r
135 int64_t AlignmentsBeginOffset;
\r
137 string IndexFilename;
\r
139 // user-specified region values
\r
140 bool IsRegionSpecified;
\r
144 // BAM character constants
\r
145 const char* DNA_LOOKUP;
\r
146 const char* CIGAR_LOOKUP;
\r
148 // -------------------------------
\r
149 // constructor & destructor
\r
150 // -------------------------------
\r
151 BamReaderPrivate(void);
\r
152 ~BamReaderPrivate(void);
\r
154 // -------------------------------
\r
155 // "public" interface
\r
156 // -------------------------------
\r
160 bool Jump(int refID, int position = 0);
\r
161 void Open(const string& filename, const string& indexFilename = "");
\r
164 // access alignment data
\r
165 bool GetNextAlignment(BamAlignment& bAlignment);
\r
167 // access auxiliary data
\r
168 const string GetHeaderText(void) const;
\r
169 const int GetReferenceCount(void) const;
\r
170 const RefVector GetReferenceData(void) const;
\r
171 const int GetReferenceID(const string& refName) const;
\r
173 // index operations
\r
174 bool CreateIndex(void);
\r
176 // -------------------------------
\r
177 // internal methods
\r
178 // -------------------------------
\r
180 // *** reading alignments and auxiliary data *** //
\r
182 // calculate bins that overlap region ( left to reference end for now )
\r
183 int BinsFromRegion(int refID, int left, uint16_t[MAX_BIN]);
\r
184 // calculates alignment end position based on starting position and provided CIGAR operations
\r
185 int CalculateAlignmentEnd(const int& position, const std::vector<CigarOp>& cigarData);
\r
186 // calculate file offset for first alignment chunk overlapping 'left'
\r
187 int64_t GetOffset(int refID, int left);
\r
188 // checks to see if alignment overlaps current region
\r
189 bool IsOverlap(BamAlignment& bAlignment);
\r
190 // retrieves header text from BAM file
\r
191 void LoadHeaderData(void);
\r
192 // retrieves BAM alignment under file pointer
\r
193 bool LoadNextAlignment(BamAlignment& bAlignment);
\r
194 // builds reference data structure from BAM file
\r
195 void LoadReferenceData(void);
\r
197 // *** index file handling *** //
\r
199 // calculates index for BAM file
\r
200 bool BuildIndex(void);
\r
201 // clear out inernal index data structure
\r
202 void ClearIndex(void);
\r
203 // saves BAM bin entry for index
\r
204 void InsertBinEntry(BamBinMap& binMap, const uint32_t& saveBin, const uint64_t& saveOffset, const uint64_t& lastOffset);
\r
205 // saves linear offset entry for index
\r
206 void InsertLinearOffset(LinearOffsetVector& offsets, const BamAlignment& bAlignment, const uint64_t& lastOffset);
\r
207 // loads index from BAM index file
\r
208 bool LoadIndex(void);
\r
209 // simplifies index by merging 'chunks'
\r
210 void MergeChunks(void);
\r
211 // round-up 32-bit integer to next power-of-2
\r
212 void Roundup32(int& value);
\r
213 // saves index to BAM index file
\r
214 bool WriteIndex(void);
\r
217 // -----------------------------------------------------
\r
218 // BamReader implementation (wrapper around BRPrivate)
\r
219 // -----------------------------------------------------
\r
222 BamReader::BamReader(void) {
\r
223 d = new BamReaderPrivate;
\r
227 BamReader::~BamReader(void) {
\r
233 void BamReader::Close(void) { d->Close(); }
\r
234 bool BamReader::Jump(int refID, int position) { return d->Jump(refID, position); }
\r
235 void BamReader::Open(const string& filename, const string& indexFilename) { d->Open(filename, indexFilename); }
\r
236 bool BamReader::Rewind(void) { return d->Rewind(); }
\r
238 // access alignment data
\r
239 bool BamReader::GetNextAlignment(BamAlignment& bAlignment) { return d->GetNextAlignment(bAlignment); }
\r
241 // access auxiliary data
\r
242 const string BamReader::GetHeaderText(void) const { return d->HeaderText; }
\r
243 const int BamReader::GetReferenceCount(void) const { return d->References.size(); }
\r
244 const RefVector BamReader::GetReferenceData(void) const { return d->References; }
\r
245 const int BamReader::GetReferenceID(const string& refName) const { return d->GetReferenceID(refName); }
\r
247 // index operations
\r
248 bool BamReader::CreateIndex(void) { return d->CreateIndex(); }
\r
250 // -----------------------------------------------------
\r
251 // BamReaderPrivate implementation
\r
252 // -----------------------------------------------------
\r
255 BamReader::BamReaderPrivate::BamReaderPrivate(void)
\r
256 : IsIndexLoaded(false)
\r
257 , AlignmentsBeginOffset(0)
\r
258 , IsRegionSpecified(false)
\r
261 , DNA_LOOKUP("=ACMGRSVTWYHKDBN")
\r
262 , CIGAR_LOOKUP("MIDNSHP")
\r
266 BamReader::BamReaderPrivate::~BamReaderPrivate(void) {
\r
270 // calculate bins that overlap region ( left to reference end for now )
\r
271 int BamReader::BamReaderPrivate::BinsFromRegion(int refID, int left, uint16_t list[MAX_BIN]) {
\r
273 // get region boundaries
\r
274 uint32_t begin = (unsigned int)left;
\r
275 uint32_t end = (unsigned int)References.at(refID).RefLength - 1;
\r
277 // initialize list, bin '0' always a valid bin
\r
281 // get rest of bins that contain this region
\r
283 for (k = 1 + (begin>>26); k <= 1 + (end>>26); ++k) { list[i++] = k; }
\r
284 for (k = 9 + (begin>>23); k <= 9 + (end>>23); ++k) { list[i++] = k; }
\r
285 for (k = 73 + (begin>>20); k <= 73 + (end>>20); ++k) { list[i++] = k; }
\r
286 for (k = 585 + (begin>>17); k <= 585 + (end>>17); ++k) { list[i++] = k; }
\r
287 for (k = 4681 + (begin>>14); k <= 4681 + (end>>14); ++k) { list[i++] = k; }
\r
289 // return number of bins stored
\r
293 // populates BAM index data structure from BAM file data
\r
294 bool BamReader::BamReaderPrivate::BuildIndex(void) {
\r
296 // check to be sure file is open
\r
297 if (!mBGZF.IsOpen) { return false; }
\r
299 // move file pointer to beginning of alignments
\r
302 // get reference count, reserve index space
\r
303 int numReferences = References.size();
\r
304 for ( int i = 0; i < numReferences; ++i ) {
\r
305 Index.push_back(ReferenceIndex());
\r
308 // sets default constant for bin, ID, offset, coordinate variables
\r
309 const uint32_t defaultValue = 0xffffffffu;
\r
312 uint32_t saveBin(defaultValue);
\r
313 uint32_t lastBin(defaultValue);
\r
315 // reference ID data
\r
316 int32_t saveRefID(defaultValue);
\r
317 int32_t lastRefID(defaultValue);
\r
320 uint64_t saveOffset = mBGZF.Tell();
\r
321 uint64_t lastOffset = saveOffset;
\r
324 int32_t lastCoordinate = defaultValue;
\r
326 BamAlignment bAlignment;
\r
327 while( GetNextAlignment(bAlignment) ) {
\r
329 // change of chromosome, save ID, reset bin
\r
330 if ( lastRefID != bAlignment.RefID ) {
\r
331 lastRefID = bAlignment.RefID;
\r
332 lastBin = defaultValue;
\r
335 // if lastCoordinate greater than BAM position - file not sorted properly
\r
336 else if ( lastCoordinate > bAlignment.Position ) {
\r
337 printf("BAM file not properly sorted:\n");
\r
338 printf("Alignment %s : %d > %d on reference (id = %d)", bAlignment.Name.c_str(), lastCoordinate, bAlignment.Position, bAlignment.RefID);
\r
342 // if valid reference && BAM bin spans some minimum cutoff (smaller bin ids span larger regions)
\r
343 if ( (bAlignment.RefID >= 0) && (bAlignment.Bin < 4681) ) {
\r
345 // save linear offset entry (matched to BAM entry refID)
\r
346 ReferenceIndex& refIndex = Index.at(bAlignment.RefID);
\r
347 LinearOffsetVector& offsets = refIndex.Offsets;
\r
348 InsertLinearOffset(offsets, bAlignment, lastOffset);
\r
351 // if current BamAlignment bin != lastBin, "then possibly write the binning index"
\r
352 if ( bAlignment.Bin != lastBin ) {
\r
354 // if not first time through
\r
355 if ( saveBin != defaultValue ) {
\r
357 // save Bam bin entry
\r
358 ReferenceIndex& refIndex = Index.at(saveRefID);
\r
359 BamBinMap& binMap = refIndex.Bins;
\r
360 InsertBinEntry(binMap, saveBin, saveOffset, lastOffset);
\r
363 // update saveOffset
\r
364 saveOffset = lastOffset;
\r
366 // update bin values
\r
367 saveBin = bAlignment.Bin;
\r
368 lastBin = bAlignment.Bin;
\r
370 // update saveRefID
\r
371 saveRefID = bAlignment.RefID;
\r
373 // if invalid RefID, break out (why?)
\r
374 if ( saveRefID < 0 ) { break; }
\r
377 // make sure that current file pointer is beyond lastOffset
\r
378 if ( mBGZF.Tell() <= (int64_t)lastOffset ) {
\r
379 printf("Error in BGZF offsets.\n");
\r
383 // update lastOffset
\r
384 lastOffset = mBGZF.Tell();
\r
386 // update lastCoordinate
\r
387 lastCoordinate = bAlignment.Position;
\r
390 // save any leftover BAM data (as long as refID is valid)
\r
391 if ( saveRefID >= 0 ) {
\r
392 // save Bam bin entry
\r
393 ReferenceIndex& refIndex = Index.at(saveRefID);
\r
394 BamBinMap& binMap = refIndex.Bins;
\r
395 InsertBinEntry(binMap, saveBin, saveOffset, lastOffset);
\r
398 // simplify index by merging chunks
\r
401 // iterate over references
\r
402 BamIndex::iterator indexIter = Index.begin();
\r
403 BamIndex::iterator indexEnd = Index.end();
\r
404 for ( int i = 0; indexIter != indexEnd; ++indexIter, ++i ) {
\r
406 // get reference index data
\r
407 ReferenceIndex& refIndex = (*indexIter);
\r
408 BamBinMap& binMap = refIndex.Bins;
\r
409 LinearOffsetVector& offsets = refIndex.Offsets;
\r
411 // store whether reference has alignments or no
\r
412 References[i].RefHasAlignments = ( binMap.size() > 0 );
\r
414 // sort linear offsets
\r
415 sort(offsets.begin(), offsets.end());
\r
419 // rewind file pointer to beginning of alignments, return success/fail
\r
423 // calculates alignment end position based on starting position and provided CIGAR operations
\r
424 int BamReader::BamReaderPrivate::CalculateAlignmentEnd(const int& position, const vector<CigarOp>& cigarData) {
\r
426 // initialize alignment end to starting position
\r
427 int alignEnd = position;
\r
429 // iterate over cigar operations
\r
430 vector<CigarOp>::const_iterator cigarIter = cigarData.begin();
\r
431 vector<CigarOp>::const_iterator cigarEnd = cigarData.end();
\r
432 for ( ; cigarIter != cigarEnd; ++cigarIter) {
\r
433 char cigarType = (*cigarIter).Type;
\r
434 if ( cigarType == 'M' || cigarType == 'D' || cigarType == 'N' ) {
\r
435 alignEnd += (*cigarIter).Length;
\r
442 // clear index data structure
\r
443 void BamReader::BamReaderPrivate::ClearIndex(void) {
\r
444 Index.clear(); // sufficient ??
\r
447 // closes the BAM file
\r
448 void BamReader::BamReaderPrivate::Close(void) {
\r
451 HeaderText.clear();
\r
452 IsRegionSpecified = false;
\r
455 // create BAM index from BAM file (keep structure in memory) and write to default index output file
\r
456 bool BamReader::BamReaderPrivate::CreateIndex(void) {
\r
461 // build (& save) index from BAM file
\r
463 ok &= BuildIndex();
\r
464 ok &= WriteIndex();
\r
466 // return success/fail
\r
470 // returns RefID for given RefName (returns References.size() if not found)
\r
471 const int BamReader::BamReaderPrivate::GetReferenceID(const string& refName) const {
\r
473 // retrieve names from reference data
\r
474 vector<string> refNames;
\r
475 RefVector::const_iterator refIter = References.begin();
\r
476 RefVector::const_iterator refEnd = References.end();
\r
477 for ( ; refIter != refEnd; ++refIter) {
\r
478 refNames.push_back( (*refIter).RefName );
\r
481 // return 'index-of' refName ( if not found, returns refNames.size() )
\r
482 return distance(refNames.begin(), find(refNames.begin(), refNames.end(), refName));
\r
485 // get next alignment (from specified region, if given)
\r
486 bool BamReader::BamReaderPrivate::GetNextAlignment(BamAlignment& bAlignment) {
\r
488 // if valid alignment available
\r
489 if ( LoadNextAlignment(bAlignment) ) {
\r
491 // if region not specified, return success
\r
492 if ( !IsRegionSpecified ) { return true; }
\r
494 // load next alignment until region overlap is found
\r
495 while ( !IsOverlap(bAlignment) ) {
\r
496 // if no valid alignment available (likely EOF) return failure
\r
497 if ( !LoadNextAlignment(bAlignment) ) { return false; }
\r
500 // return success (alignment found that overlaps region)
\r
504 // no valid alignment
\r
505 else { return false; }
\r
508 // calculate closest indexed file offset for region specified
\r
509 int64_t BamReader::BamReaderPrivate::GetOffset(int refID, int left) {
\r
511 // calculate which bins overlap this region
\r
512 uint16_t* bins = (uint16_t*)calloc(MAX_BIN, 2);
\r
513 int numBins = BinsFromRegion(refID, left, bins);
\r
515 // get bins for this reference
\r
516 const ReferenceIndex& refIndex = Index.at(refID);
\r
517 const BamBinMap& binMap = refIndex.Bins;
\r
519 // get minimum offset to consider
\r
520 const LinearOffsetVector& offsets = refIndex.Offsets;
\r
521 uint64_t minOffset = ( (unsigned int)(left>>BAM_LIDX_SHIFT) >= offsets.size() ) ? 0 : offsets.at(left>>BAM_LIDX_SHIFT);
\r
523 // store offsets to beginning of alignment 'chunks'
\r
524 std::vector<int64_t> chunkStarts;
\r
526 // store all alignment 'chunk' starts for bins in this region
\r
527 for (int i = 0; i < numBins; ++i ) {
\r
528 uint16_t binKey = bins[i];
\r
530 map<uint32_t, ChunkVector>::const_iterator binIter = binMap.find(binKey);
\r
531 if ( (binIter != binMap.end()) && ((*binIter).first == binKey) ) {
\r
533 const ChunkVector& chunks = (*binIter).second;
\r
534 std::vector<Chunk>::const_iterator chunksIter = chunks.begin();
\r
535 std::vector<Chunk>::const_iterator chunksEnd = chunks.end();
\r
536 for ( ; chunksIter != chunksEnd; ++chunksIter) {
\r
537 const Chunk& chunk = (*chunksIter);
\r
538 if ( chunk.Stop > minOffset ) {
\r
539 chunkStarts.push_back( chunk.Start );
\r
548 // if no alignments found, else return smallest offset for alignment starts
\r
549 if ( chunkStarts.size() == 0 ) { return -1; }
\r
550 else { return *min_element(chunkStarts.begin(), chunkStarts.end()); }
\r
553 // saves BAM bin entry for index
\r
554 void BamReader::BamReaderPrivate::InsertBinEntry(BamBinMap& binMap,
\r
555 const uint32_t& saveBin,
\r
556 const uint64_t& saveOffset,
\r
557 const uint64_t& lastOffset)
\r
560 BamBinMap::iterator binIter = binMap.find(saveBin);
\r
562 // create new chunk
\r
563 Chunk newChunk(saveOffset, lastOffset);
\r
565 // if entry doesn't exist
\r
566 if ( binIter == binMap.end() ) {
\r
567 ChunkVector newChunks;
\r
568 newChunks.push_back(newChunk);
\r
569 binMap.insert( pair<uint32_t, ChunkVector>(saveBin, newChunks));
\r
574 ChunkVector& binChunks = (*binIter).second;
\r
575 binChunks.push_back( newChunk );
\r
579 // saves linear offset entry for index
\r
580 void BamReader::BamReaderPrivate::InsertLinearOffset(LinearOffsetVector& offsets,
\r
581 const BamAlignment& bAlignment,
\r
582 const uint64_t& lastOffset)
\r
584 // get converted offsets
\r
585 int beginOffset = bAlignment.Position >> BAM_LIDX_SHIFT;
\r
586 int endOffset = ( CalculateAlignmentEnd(bAlignment.Position, bAlignment.CigarData) - 1) >> BAM_LIDX_SHIFT;
\r
588 // resize vector if necessary
\r
589 int oldSize = offsets.size();
\r
590 int newSize = endOffset + 1;
\r
591 if ( oldSize < newSize ) {
\r
592 Roundup32(newSize);
\r
593 offsets.resize(newSize, 0);
\r
597 for(int i = beginOffset + 1; i <= endOffset ; ++i) {
\r
598 if ( offsets[i] == 0) {
\r
599 offsets[i] = lastOffset;
\r
604 // returns whether alignment overlaps currently specified region (refID, leftBound)
\r
605 bool BamReader::BamReaderPrivate::IsOverlap(BamAlignment& bAlignment) {
\r
607 // if on different reference sequence, quit
\r
608 if ( bAlignment.RefID != CurrentRefID ) { return false; }
\r
610 // read starts after left boundary
\r
611 if ( bAlignment.Position >= CurrentLeft) { return true; }
\r
613 // return whether alignment end overlaps left boundary
\r
614 return ( CalculateAlignmentEnd(bAlignment.Position, bAlignment.CigarData) >= CurrentLeft );
\r
617 // jumps to specified region(refID, leftBound) in BAM file, returns success/fail
\r
618 bool BamReader::BamReaderPrivate::Jump(int refID, int position) {
\r
620 // if data exists for this reference and position is valid
\r
621 if ( References.at(refID).RefHasAlignments && (position <= References.at(refID).RefLength) ) {
\r
623 // set current region
\r
624 CurrentRefID = refID;
\r
625 CurrentLeft = position;
\r
626 IsRegionSpecified = true;
\r
628 // calculate offset
\r
629 int64_t offset = GetOffset(CurrentRefID, CurrentLeft);
\r
631 // if in valid offset, return failure
\r
632 if ( offset == -1 ) { return false; }
\r
634 // otherwise return success of seek operation
\r
635 else { return mBGZF.Seek(offset); }
\r
638 // invalid jump request parameters, return failure
\r
642 // load BAM header data
\r
643 void BamReader::BamReaderPrivate::LoadHeaderData(void) {
\r
645 // check to see if proper BAM header
\r
647 if (mBGZF.Read(buffer, 4) != 4) {
\r
648 printf("Could not read header type\n");
\r
652 if (strncmp(buffer, "BAM\001", 4)) {
\r
653 printf("wrong header type!\n");
\r
657 // get BAM header text length
\r
658 mBGZF.Read(buffer, 4);
\r
659 const unsigned int headerTextLength = BgzfData::UnpackUnsignedInt(buffer);
\r
661 // get BAM header text
\r
662 char* headerText = (char*)calloc(headerTextLength + 1, 1);
\r
663 mBGZF.Read(headerText, headerTextLength);
\r
664 HeaderText = (string)((const char*)headerText);
\r
666 // clean up calloc-ed temp variable
\r
670 // load existing index data from BAM index file (".bai"), return success/fail
\r
671 bool BamReader::BamReaderPrivate::LoadIndex(void) {
\r
673 // clear out index data
\r
676 // skip if index file empty
\r
677 if ( IndexFilename.empty() ) { return false; }
\r
679 // open index file, abort on error
\r
680 FILE* indexStream = fopen(IndexFilename.c_str(), "rb");
\r
682 printf("ERROR: Unable to open the BAM index file %s for reading.\n", IndexFilename.c_str() );
\r
686 // see if index is valid BAM index
\r
688 fread(magic, 1, 4, indexStream);
\r
689 if (strncmp(magic, "BAI\1", 4)) {
\r
690 printf("Problem with index file - invalid format.\n");
\r
691 fclose(indexStream);
\r
695 // get number of reference sequences
\r
696 uint32_t numRefSeqs;
\r
697 fread(&numRefSeqs, 4, 1, indexStream);
\r
699 // intialize space for BamIndex data structure
\r
700 Index.reserve(numRefSeqs);
\r
702 // iterate over reference sequences
\r
703 for (unsigned int i = 0; i < numRefSeqs; ++i) {
\r
705 // get number of bins for this reference sequence
\r
707 fread(&numBins, 4, 1, indexStream);
\r
710 RefData& refEntry = References[i];
\r
711 refEntry.RefHasAlignments = true;
\r
714 // intialize BinVector
\r
717 // iterate over bins for that reference sequence
\r
718 for (int j = 0; j < numBins; ++j) {
\r
722 fread(&binID, 4, 1, indexStream);
\r
724 // get number of regionChunks in this bin
\r
725 uint32_t numChunks;
\r
726 fread(&numChunks, 4, 1, indexStream);
\r
728 // intialize ChunkVector
\r
729 ChunkVector regionChunks;
\r
730 regionChunks.reserve(numChunks);
\r
732 // iterate over regionChunks in this bin
\r
733 for (unsigned int k = 0; k < numChunks; ++k) {
\r
735 // get chunk boundaries (left, right)
\r
738 fread(&left, 8, 1, indexStream);
\r
739 fread(&right, 8, 1, indexStream);
\r
742 regionChunks.push_back( Chunk(left, right) );
\r
745 // sort chunks for this bin
\r
746 sort( regionChunks.begin(), regionChunks.end(), ChunkLessThan );
\r
748 // save binID, chunkVector for this bin
\r
749 binMap.insert( pair<uint32_t, ChunkVector>(binID, regionChunks) );
\r
752 // load linear index for this reference sequence
\r
754 // get number of linear offsets
\r
755 int32_t numLinearOffsets;
\r
756 fread(&numLinearOffsets, 4, 1, indexStream);
\r
758 // intialize LinearOffsetVector
\r
759 LinearOffsetVector offsets;
\r
760 offsets.reserve(numLinearOffsets);
\r
762 // iterate over linear offsets for this reference sequeence
\r
763 uint64_t linearOffset;
\r
764 for (int j = 0; j < numLinearOffsets; ++j) {
\r
765 // read a linear offset & store
\r
766 fread(&linearOffset, 8, 1, indexStream);
\r
767 offsets.push_back(linearOffset);
\r
770 // sort linear offsets
\r
771 sort( offsets.begin(), offsets.end() );
\r
773 // store index data for that reference sequence
\r
774 Index.push_back( ReferenceIndex(binMap, offsets) );
\r
777 // close index file (.bai) and return
\r
778 fclose(indexStream);
\r
782 // populates BamAlignment with alignment data under file pointer, returns success/fail
\r
783 bool BamReader::BamReaderPrivate::LoadNextAlignment(BamAlignment& bAlignment) {
\r
785 // read in the 'block length' value, make sure it's not zero
\r
787 mBGZF.Read(buffer, 4);
\r
788 const unsigned int blockLength = BgzfData::UnpackUnsignedInt(buffer);
\r
789 if ( blockLength == 0 ) { return false; }
\r
791 // keep track of bytes read as method progresses
\r
794 // read in core alignment data, make sure the right size of data was read
\r
795 char x[BAM_CORE_SIZE];
\r
796 if ( mBGZF.Read(x, BAM_CORE_SIZE) != BAM_CORE_SIZE ) { return false; }
\r
797 bytesRead += BAM_CORE_SIZE;
\r
799 // set BamAlignment 'core' data and character data lengths
\r
800 unsigned int tempValue;
\r
801 unsigned int queryNameLength;
\r
802 unsigned int numCigarOperations;
\r
803 unsigned int querySequenceLength;
\r
805 bAlignment.RefID = BgzfData::UnpackSignedInt(&x[0]);
\r
806 bAlignment.Position = BgzfData::UnpackSignedInt(&x[4]);
\r
808 tempValue = BgzfData::UnpackUnsignedInt(&x[8]);
\r
809 bAlignment.Bin = tempValue >> 16;
\r
810 bAlignment.MapQuality = tempValue >> 8 & 0xff;
\r
811 queryNameLength = tempValue & 0xff;
\r
813 tempValue = BgzfData::UnpackUnsignedInt(&x[12]);
\r
814 bAlignment.AlignmentFlag = tempValue >> 16;
\r
815 numCigarOperations = tempValue & 0xffff;
\r
817 querySequenceLength = BgzfData::UnpackUnsignedInt(&x[16]);
\r
818 bAlignment.MateRefID = BgzfData::UnpackSignedInt(&x[20]);
\r
819 bAlignment.MatePosition = BgzfData::UnpackSignedInt(&x[24]);
\r
820 bAlignment.InsertSize = BgzfData::UnpackSignedInt(&x[28]);
\r
822 // calculate lengths/offsets
\r
823 const unsigned int dataLength = blockLength - BAM_CORE_SIZE;
\r
824 const unsigned int cigarDataOffset = queryNameLength;
\r
825 const unsigned int seqDataOffset = cigarDataOffset + (numCigarOperations * 4);
\r
826 const unsigned int qualDataOffset = seqDataOffset + (querySequenceLength+1)/2;
\r
827 const unsigned int tagDataOffset = qualDataOffset + querySequenceLength;
\r
828 const unsigned int tagDataLen = dataLength - tagDataOffset;
\r
830 // set up destination buffers for character data
\r
831 char* allCharData = (char*)calloc(sizeof(char), dataLength);
\r
832 uint32_t* cigarData = (uint32_t*)(allCharData + cigarDataOffset);
\r
833 char* seqData = ((char*)allCharData) + seqDataOffset;
\r
834 char* qualData = ((char*)allCharData) + qualDataOffset;
\r
835 char* tagData = ((char*)allCharData) + tagDataOffset;
\r
837 // get character data - make sure proper data size was read
\r
838 if ( mBGZF.Read(allCharData, dataLength) != (signed int)dataLength) { return false; }
\r
841 bytesRead += dataLength;
\r
843 // clear out any previous string data
\r
844 bAlignment.Name.clear();
\r
845 bAlignment.QueryBases.clear();
\r
846 bAlignment.Qualities.clear();
\r
847 bAlignment.AlignedBases.clear();
\r
848 bAlignment.CigarData.clear();
\r
849 bAlignment.TagData.clear();
\r
852 bAlignment.Name = (string)((const char*)(allCharData));
\r
854 // save query sequence
\r
855 for (unsigned int i = 0; i < querySequenceLength; ++i) {
\r
856 char singleBase = DNA_LOOKUP[ ( ( seqData[(i/2)] >> (4*(1-(i%2)))) & 0xf ) ];
\r
857 bAlignment.QueryBases.append( 1, singleBase );
\r
860 // save sequence length
\r
861 bAlignment.Length = bAlignment.QueryBases.length();
\r
863 // save qualities, convert from numeric QV to FASTQ character
\r
864 for (unsigned int i = 0; i < querySequenceLength; ++i) {
\r
865 char singleQuality = (char)(qualData[i]+33);
\r
866 bAlignment.Qualities.append( 1, singleQuality );
\r
869 // save CIGAR-related data;
\r
871 for (unsigned int i = 0; i < numCigarOperations; ++i) {
\r
873 // build CigarOp struct
\r
875 op.Length = (cigarData[i] >> BAM_CIGAR_SHIFT);
\r
876 op.Type = CIGAR_LOOKUP[ (cigarData[i] & BAM_CIGAR_MASK) ];
\r
879 bAlignment.CigarData.push_back(op);
\r
881 // build AlignedBases string
\r
885 case ('I') : bAlignment.AlignedBases.append( bAlignment.QueryBases.substr(k, op.Length) ); // for 'M', 'I' - write bases
\r
886 case ('S') : k += op.Length; // for 'S' - skip over query bases
\r
889 case ('D') : bAlignment.AlignedBases.append( op.Length, '-' ); // for 'D' - write gap character
\r
892 case ('P') : bAlignment.AlignedBases.append( op.Length, '*' ); // for 'P' - write padding character;
\r
895 case ('N') : bAlignment.AlignedBases.append( op.Length, 'N' ); // for 'N' - write N's, skip bases in query sequence
\r
899 case ('H') : break; // for 'H' - do nothing, move to next op
\r
901 default : printf("ERROR: Invalid Cigar op type\n"); // shouldn't get here
\r
906 // read in the tag data
\r
907 bAlignment.TagData.resize(tagDataLen);
\r
908 memcpy((char*)bAlignment.TagData.data(), tagData, tagDataLen);
\r
915 // loads reference data from BAM file
\r
916 void BamReader::BamReaderPrivate::LoadReferenceData(void) {
\r
918 // get number of reference sequences
\r
920 mBGZF.Read(buffer, 4);
\r
921 const unsigned int numberRefSeqs = BgzfData::UnpackUnsignedInt(buffer);
\r
922 if (numberRefSeqs == 0) { return; }
\r
923 References.reserve((int)numberRefSeqs);
\r
925 // iterate over all references in header
\r
926 for (unsigned int i = 0; i != numberRefSeqs; ++i) {
\r
928 // get length of reference name
\r
929 mBGZF.Read(buffer, 4);
\r
930 const unsigned int refNameLength = BgzfData::UnpackUnsignedInt(buffer);
\r
931 char* refName = (char*)calloc(refNameLength, 1);
\r
933 // get reference name and reference sequence length
\r
934 mBGZF.Read(refName, refNameLength);
\r
935 mBGZF.Read(buffer, 4);
\r
936 const int refLength = BgzfData::UnpackSignedInt(buffer);
\r
938 // store data for reference
\r
939 RefData aReference;
\r
940 aReference.RefName = (string)((const char*)refName);
\r
941 aReference.RefLength = refLength;
\r
942 References.push_back(aReference);
\r
944 // clean up calloc-ed temp variable
\r
949 // merges 'alignment chunks' in BAM bin (used for index building)
\r
950 void BamReader::BamReaderPrivate::MergeChunks(void) {
\r
952 // iterate over reference enties
\r
953 BamIndex::iterator indexIter = Index.begin();
\r
954 BamIndex::iterator indexEnd = Index.end();
\r
955 for ( ; indexIter != indexEnd; ++indexIter ) {
\r
957 // get BAM bin map for this reference
\r
958 ReferenceIndex& refIndex = (*indexIter);
\r
959 BamBinMap& bamBinMap = refIndex.Bins;
\r
961 // iterate over BAM bins
\r
962 BamBinMap::iterator binIter = bamBinMap.begin();
\r
963 BamBinMap::iterator binEnd = bamBinMap.end();
\r
964 for ( ; binIter != binEnd; ++binIter ) {
\r
966 // get chunk vector for this bin
\r
967 ChunkVector& binChunks = (*binIter).second;
\r
968 if ( binChunks.size() == 0 ) { continue; }
\r
970 ChunkVector mergedChunks;
\r
971 mergedChunks.push_back( binChunks[0] );
\r
973 // iterate over chunks
\r
975 ChunkVector::iterator chunkIter = binChunks.begin();
\r
976 ChunkVector::iterator chunkEnd = binChunks.end();
\r
977 for ( ++chunkIter; chunkIter != chunkEnd; ++chunkIter) {
\r
979 // get 'currentChunk' based on numeric index
\r
980 Chunk& currentChunk = mergedChunks[i];
\r
982 // get iteratorChunk based on vector iterator
\r
983 Chunk& iteratorChunk = (*chunkIter);
\r
985 // if currentChunk.Stop(shifted) == iterator Chunk.Start(shifted)
\r
986 if ( currentChunk.Stop>>16 == iteratorChunk.Start>>16 ) {
\r
988 // set currentChunk.Stop to iteratorChunk.Stop
\r
989 currentChunk.Stop = iteratorChunk.Stop;
\r
994 // set currentChunk + 1 to iteratorChunk
\r
995 mergedChunks.push_back(iteratorChunk);
\r
1000 // saved merged chunk vector
\r
1001 (*binIter).second = mergedChunks;
\r
1006 // opens BAM file (and index)
\r
1007 void BamReader::BamReaderPrivate::Open(const string& filename, const string& indexFilename) {
\r
1009 Filename = filename;
\r
1010 IndexFilename = indexFilename;
\r
1012 // open the BGZF file for reading, retrieve header text & reference data
\r
1013 mBGZF.Open(filename, "rb");
\r
1015 LoadReferenceData();
\r
1017 // store file offset of first alignment
\r
1018 AlignmentsBeginOffset = mBGZF.Tell();
\r
1020 // open index file & load index data (if exists)
\r
1021 if ( !IndexFilename.empty() ) {
\r
1026 // returns BAM file pointer to beginning of alignment data
\r
1027 bool BamReader::BamReaderPrivate::Rewind(void) {
\r
1029 // find first reference that has alignments in the BAM file
\r
1031 int refCount = References.size();
\r
1032 for ( ; refID < refCount; ++refID ) {
\r
1033 if ( References.at(refID).RefHasAlignments ) { break; }
\r
1036 // store default bounds for first alignment
\r
1037 CurrentRefID = refID;
\r
1039 IsRegionSpecified = false;
\r
1041 // return success/failure of seek
\r
1042 return mBGZF.Seek(AlignmentsBeginOffset);
\r
1045 // rounds value up to next power-of-2 (used in index building)
\r
1046 void BamReader::BamReaderPrivate::Roundup32(int& value) {
\r
1048 value |= value >> 1;
\r
1049 value |= value >> 2;
\r
1050 value |= value >> 4;
\r
1051 value |= value >> 8;
\r
1052 value |= value >> 16;
\r
1056 // saves index data to BAM index file (".bai"), returns success/fail
\r
1057 bool BamReader::BamReaderPrivate::WriteIndex(void) {
\r
1059 IndexFilename = Filename + ".bai";
\r
1060 FILE* indexStream = fopen(IndexFilename.c_str(), "wb");
\r
1061 if ( indexStream == 0 ) {
\r
1062 printf("ERROR: Could not open file to save index\n");
\r
1066 // write BAM index header
\r
1067 fwrite("BAI\1", 1, 4, indexStream);
\r
1069 // write number of reference sequences
\r
1070 int32_t numReferenceSeqs = Index.size();
\r
1071 fwrite(&numReferenceSeqs, 4, 1, indexStream);
\r
1073 // iterate over reference sequences
\r
1074 BamIndex::const_iterator indexIter = Index.begin();
\r
1075 BamIndex::const_iterator indexEnd = Index.end();
\r
1076 for ( ; indexIter != indexEnd; ++ indexIter ) {
\r
1078 // get reference index data
\r
1079 const ReferenceIndex& refIndex = (*indexIter);
\r
1080 const BamBinMap& binMap = refIndex.Bins;
\r
1081 const LinearOffsetVector& offsets = refIndex.Offsets;
\r
1083 // write number of bins
\r
1084 int32_t binCount = binMap.size();
\r
1085 fwrite(&binCount, 4, 1, indexStream);
\r
1087 // iterate over bins
\r
1088 BamBinMap::const_iterator binIter = binMap.begin();
\r
1089 BamBinMap::const_iterator binEnd = binMap.end();
\r
1090 for ( ; binIter != binEnd; ++binIter ) {
\r
1092 // get bin data (key and chunk vector)
\r
1093 const uint32_t& binKey = (*binIter).first;
\r
1094 const ChunkVector& binChunks = (*binIter).second;
\r
1096 // save BAM bin key
\r
1097 fwrite(&binKey, 4, 1, indexStream);
\r
1099 // save chunk count
\r
1100 int32_t chunkCount = binChunks.size();
\r
1101 fwrite(&chunkCount, 4, 1, indexStream);
\r
1103 // iterate over chunks
\r
1104 ChunkVector::const_iterator chunkIter = binChunks.begin();
\r
1105 ChunkVector::const_iterator chunkEnd = binChunks.end();
\r
1106 for ( ; chunkIter != chunkEnd; ++chunkIter ) {
\r
1108 // get current chunk data
\r
1109 const Chunk& chunk = (*chunkIter);
\r
1110 const uint64_t& start = chunk.Start;
\r
1111 const uint64_t& stop = chunk.Stop;
\r
1113 // save chunk offsets
\r
1114 fwrite(&start, 8, 1, indexStream);
\r
1115 fwrite(&stop, 8, 1, indexStream);
\r
1119 // write linear offsets size
\r
1120 int32_t offsetSize = offsets.size();
\r
1121 fwrite(&offsetSize, 4, 1, indexStream);
\r
1123 // iterate over linear offsets
\r
1124 LinearOffsetVector::const_iterator offsetIter = offsets.begin();
\r
1125 LinearOffsetVector::const_iterator offsetEnd = offsets.end();
\r
1126 for ( ; offsetIter != offsetEnd; ++offsetIter ) {
\r
1128 // write linear offset value
\r
1129 const uint64_t& linearOffset = (*offsetIter);
\r
1130 fwrite(&linearOffset, 8, 1, indexStream);
\r
1134 // flush buffer, close file, and return success
\r
1135 fflush(indexStream);
\r
1136 fclose(indexStream);
\r
1139 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0BamReader.h
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000005312
\011307520655
\0012736
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0// ***************************************************************************
\r
1140 // BamReader.h (c) 2009 Derek Barnett, Michael Strömberg
\r
1141 // Marth Lab, Department of Biology, Boston College
\r
1142 // All rights reserved.
\r
1143 // ---------------------------------------------------------------------------
\r
1144 // Last modified: 8 December 2009 (DB)
\r
1145 // ---------------------------------------------------------------------------
\r
1146 // Uses BGZF routines were adapted from the bgzf.c code developed at the Broad
\r
1148 // ---------------------------------------------------------------------------
\r
1149 // Provides the basic functionality for reading BAM files
\r
1150 // ***************************************************************************
\r
1152 #ifndef BAMREADER_H
\r
1153 #define BAMREADER_H
\r
1158 // BamTools includes
\r
1159 #include "BamAux.h"
\r
1161 namespace BamTools {
\r
1165 // constructor / destructor
\r
1170 // public interface
\r
1173 // ----------------------
\r
1174 // BAM file operations
\r
1175 // ----------------------
\r
1179 // performs random-access jump to reference, position
\r
1180 bool Jump(int refID, int position = 0);
\r
1181 // opens BAM file (and optional BAM index file, if provided)
\r
1182 void Open(const std::string& filename, const std::string& indexFilename = "");
\r
1183 // returns file pointer to beginning of alignments
\r
1184 bool Rewind(void);
\r
1186 // ----------------------
\r
1187 // access alignment data
\r
1188 // ----------------------
\r
1190 // retrieves next available alignment (returns success/fail)
\r
1191 bool GetNextAlignment(BamAlignment& bAlignment);
\r
1193 // ----------------------
\r
1194 // access auxiliary data
\r
1195 // ----------------------
\r
1197 // returns SAM header text
\r
1198 const std::string GetHeaderText(void) const;
\r
1199 // returns number of reference sequences
\r
1200 const int GetReferenceCount(void) const;
\r
1201 // returns vector of reference objects
\r
1202 const BamTools::RefVector GetReferenceData(void) const;
\r
1203 // returns reference id (used for BamReader::Jump()) for the given reference name
\r
1204 const int GetReferenceID(const std::string& refName) const;
\r
1206 // ----------------------
\r
1207 // BAM index operations
\r
1208 // ----------------------
\r
1210 // creates index for BAM file, saves to file (default = bamFilename + ".bai")
\r
1211 bool CreateIndex(void);
\r
1213 // private implementation
\r
1215 struct BamReaderPrivate;
\r
1216 BamReaderPrivate* d;
\r
1219 } // namespace BamTools
\r
1221 #endif // BAMREADER_H
\r
1222 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0BamTrimMain.cpp
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000005351
\011307520655
\0013612
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0// ***************************************************************************
\r
1223 // BamTrimMain.cpp (c) 2009 Derek Barnett
\r
1224 // Marth Lab, Department of Biology, Boston College
\r
1225 // All rights reserved.
\r
1226 // ---------------------------------------------------------------------------
\r
1227 // Last modified: 15 July 2009 (DB)
\r
1228 // ---------------------------------------------------------------------------
\r
1229 // Basic example of reading/writing BAM files. Pulls alignments overlapping
\r
1230 // the range specified by user from one BAM file and writes to a new BAM file.
\r
1231 // ***************************************************************************
\r
1233 // Std C/C++ includes
\r
1234 #include <cstdlib>
\r
1235 #include <iostream>
\r
1237 using namespace std;
\r
1239 // BamTools includes
\r
1240 #include "BamReader.h"
\r
1241 #include "BamWriter.h"
\r
1242 using namespace BamTools;
\r
1244 int main(int argc, char* argv[]) {
\r
1246 // validate argument count
\r
1248 cerr << "USAGE: " << argv[0] << " <input BAM file> <input BAM index file> <output BAM file> <reference name> <leftBound> <rightBound> " << endl;
\r
1252 // store arguments
\r
1253 string inBamFilename = argv[1];
\r
1254 string indexFilename = argv[2];
\r
1255 string outBamFilename = argv[3];
\r
1256 string referenceName = argv[4];
\r
1257 string leftBound_str = argv[5];
\r
1258 string rightBound_str = argv[6];
\r
1260 // open our BAM reader
\r
1262 reader.Open(inBamFilename, indexFilename);
\r
1264 // get header & reference information
\r
1265 string header = reader.GetHeaderText();
\r
1266 RefVector references = reader.GetReferenceData();
\r
1268 // open our BAM writer
\r
1270 writer.Open(outBamFilename, header, references);
\r
1272 // get reference ID from name
\r
1274 RefVector::const_iterator refIter = references.begin();
\r
1275 RefVector::const_iterator refEnd = references.end();
\r
1276 for ( ; refIter != refEnd; ++refIter ) {
\r
1277 if ( (*refIter).RefName == referenceName ) { break; }
\r
1282 if ( refIter == refEnd ) {
\r
1283 cerr << "Reference: " << referenceName << " not found." << endl;
\r
1287 // convert boundary arguments to numeric values
\r
1288 int leftBound = (int) atoi( leftBound_str.c_str() );
\r
1289 int rightBound = (int) atoi( rightBound_str.c_str() );
\r
1291 // attempt jump to range of interest
\r
1292 if ( reader.Jump(refID, leftBound) ) {
\r
1294 // while data exists and alignment begin before right bound
\r
1295 BamAlignment bAlignment;
\r
1296 while ( reader.GetNextAlignment(bAlignment) && (bAlignment.Position <= rightBound) ) {
\r
1297 // save alignment to archive
\r
1298 writer.SaveAlignment(bAlignment);
\r
1304 cerr << "Could not jump to ref:pos " << referenceName << ":" << leftBound << endl;
\r
1308 // clean up and exit
\r
1312 }
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0BamWriter.cpp
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000022463
\011307516613
\0013350
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0// ***************************************************************************
\r
1313 // BamWriter.cpp (c) 2009 Michael Strömberg, Derek Barnett
\r
1314 // Marth Lab, Department of Biology, Boston College
\r
1315 // All rights reserved.
\r
1316 // ---------------------------------------------------------------------------
\r
1317 // Last modified: 8 December 2009 (DB)
\r
1318 // ---------------------------------------------------------------------------
\r
1319 // Uses BGZF routines were adapted from the bgzf.c code developed at the Broad
\r
1321 // ---------------------------------------------------------------------------
\r
1322 // Provides the basic functionality for producing BAM files
\r
1323 // ***************************************************************************
\r
1327 #include "BamWriter.h"
\r
1328 using namespace BamTools;
\r
1329 using namespace std;
\r
1331 struct BamWriter::BamWriterPrivate {
\r
1336 // constructor / destructor
\r
1337 BamWriterPrivate(void) { }
\r
1338 ~BamWriterPrivate(void) {
\r
1342 // "public" interface
\r
1344 void Open(const std::string& filename, const std::string& samHeader, const BamTools::RefVector& referenceSequences);
\r
1345 void SaveAlignment(const BamTools::BamAlignment& al);
\r
1347 // internal methods
\r
1348 void CreatePackedCigar(const std::vector<CigarOp>& cigarOperations, std::string& packedCigar);
\r
1349 void EncodeQuerySequence(const std::string& query, std::string& encodedQuery);
\r
1352 // -----------------------------------------------------
\r
1353 // BamWriter implementation
\r
1354 // -----------------------------------------------------
\r
1357 BamWriter::BamWriter(void) {
\r
1358 d = new BamWriterPrivate;
\r
1362 BamWriter::~BamWriter(void) {
\r
1367 // closes the alignment archive
\r
1368 void BamWriter::Close(void) {
\r
1372 // opens the alignment archive
\r
1373 void BamWriter::Open(const string& filename, const string& samHeader, const RefVector& referenceSequences) {
\r
1374 d->Open(filename, samHeader, referenceSequences);
\r
1377 // saves the alignment to the alignment archive
\r
1378 void BamWriter::SaveAlignment(const BamAlignment& al) {
\r
1379 d->SaveAlignment(al);
\r
1382 // -----------------------------------------------------
\r
1383 // BamWriterPrivate implementation
\r
1384 // -----------------------------------------------------
\r
1386 // closes the alignment archive
\r
1387 void BamWriter::BamWriterPrivate::Close(void) {
\r
1391 // creates a cigar string from the supplied alignment
\r
1392 void BamWriter::BamWriterPrivate::CreatePackedCigar(const vector<CigarOp>& cigarOperations, string& packedCigar) {
\r
1395 const unsigned int numCigarOperations = cigarOperations.size();
\r
1396 packedCigar.resize(numCigarOperations * BT_SIZEOF_INT);
\r
1398 // pack the cigar data into the string
\r
1399 unsigned int* pPackedCigar = (unsigned int*)packedCigar.data();
\r
1401 unsigned int cigarOp;
\r
1402 vector<CigarOp>::const_iterator coIter;
\r
1403 for(coIter = cigarOperations.begin(); coIter != cigarOperations.end(); coIter++) {
\r
1405 switch(coIter->Type) {
\r
1407 cigarOp = BAM_CMATCH;
\r
1410 cigarOp = BAM_CINS;
\r
1413 cigarOp = BAM_CDEL;
\r
1416 cigarOp = BAM_CREF_SKIP;
\r
1419 cigarOp = BAM_CSOFT_CLIP;
\r
1422 cigarOp = BAM_CHARD_CLIP;
\r
1425 cigarOp = BAM_CPAD;
\r
1428 printf("ERROR: Unknown cigar operation found: %c\n", coIter->Type);
\r
1432 *pPackedCigar = coIter->Length << BAM_CIGAR_SHIFT | cigarOp;
\r
1437 // encodes the supplied query sequence into 4-bit notation
\r
1438 void BamWriter::BamWriterPrivate::EncodeQuerySequence(const string& query, string& encodedQuery) {
\r
1440 // prepare the encoded query string
\r
1441 const unsigned int queryLen = query.size();
\r
1442 const unsigned int encodedQueryLen = (unsigned int)((queryLen / 2.0) + 0.5);
\r
1443 encodedQuery.resize(encodedQueryLen);
\r
1444 char* pEncodedQuery = (char*)encodedQuery.data();
\r
1445 const char* pQuery = (const char*)query.data();
\r
1447 unsigned char nucleotideCode;
\r
1448 bool useHighWord = true;
\r
1454 nucleotideCode = 0;
\r
1457 nucleotideCode = 1;
\r
1460 nucleotideCode = 2;
\r
1463 nucleotideCode = 4;
\r
1466 nucleotideCode = 8;
\r
1469 nucleotideCode = 15;
\r
1472 printf("ERROR: Only the following bases are supported in the BAM format: {=, A, C, G, T, N}. Found [%c]\n", *pQuery);
\r
1476 // pack the nucleotide code
\r
1478 *pEncodedQuery = nucleotideCode << 4;
\r
1479 useHighWord = false;
\r
1481 *pEncodedQuery |= nucleotideCode;
\r
1483 useHighWord = true;
\r
1486 // increment the query position
\r
1491 // opens the alignment archive
\r
1492 void BamWriter::BamWriterPrivate::Open(const string& filename, const string& samHeader, const RefVector& referenceSequences) {
\r
1494 // open the BGZF file for writing
\r
1495 mBGZF.Open(filename, "wb");
\r
1497 // ================
\r
1498 // write the header
\r
1499 // ================
\r
1501 // write the BAM signature
\r
1502 const unsigned char SIGNATURE_LENGTH = 4;
\r
1503 const char* BAM_SIGNATURE = "BAM\1";
\r
1504 mBGZF.Write(BAM_SIGNATURE, SIGNATURE_LENGTH);
\r
1506 // write the SAM header text length
\r
1507 const unsigned int samHeaderLen = samHeader.size();
\r
1508 mBGZF.Write((char*)&samHeaderLen, BT_SIZEOF_INT);
\r
1510 // write the SAM header text
\r
1511 if(samHeaderLen > 0) {
\r
1512 mBGZF.Write(samHeader.data(), samHeaderLen);
\r
1515 // write the number of reference sequences
\r
1516 const unsigned int numReferenceSequences = referenceSequences.size();
\r
1517 mBGZF.Write((char*)&numReferenceSequences, BT_SIZEOF_INT);
\r
1519 // =============================
\r
1520 // write the sequence dictionary
\r
1521 // =============================
\r
1523 RefVector::const_iterator rsIter;
\r
1524 for(rsIter = referenceSequences.begin(); rsIter != referenceSequences.end(); rsIter++) {
\r
1526 // write the reference sequence name length
\r
1527 const unsigned int referenceSequenceNameLen = rsIter->RefName.size() + 1;
\r
1528 mBGZF.Write((char*)&referenceSequenceNameLen, BT_SIZEOF_INT);
\r
1530 // write the reference sequence name
\r
1531 mBGZF.Write(rsIter->RefName.c_str(), referenceSequenceNameLen);
\r
1533 // write the reference sequence length
\r
1534 mBGZF.Write((char*)&rsIter->RefLength, BT_SIZEOF_INT);
\r
1538 // saves the alignment to the alignment archive
\r
1539 void BamWriter::BamWriterPrivate::SaveAlignment(const BamAlignment& al) {
\r
1542 const unsigned int nameLen = al.Name.size() + 1;
\r
1543 const unsigned int queryLen = al.QueryBases.size();
\r
1544 const unsigned int numCigarOperations = al.CigarData.size();
\r
1546 // create our packed cigar string
\r
1547 string packedCigar;
\r
1548 CreatePackedCigar(al.CigarData, packedCigar);
\r
1549 const unsigned int packedCigarLen = packedCigar.size();
\r
1551 // encode the query
\r
1552 string encodedQuery;
\r
1553 EncodeQuerySequence(al.QueryBases, encodedQuery);
\r
1554 const unsigned int encodedQueryLen = encodedQuery.size();
\r
1556 // store the tag data length
\r
1557 const unsigned int tagDataLength = al.TagData.size() + 1;
\r
1559 // assign the BAM core data
\r
1560 unsigned int buffer[8];
\r
1561 buffer[0] = al.RefID;
\r
1562 buffer[1] = al.Position;
\r
1563 buffer[2] = (al.Bin << 16) | (al.MapQuality << 8) | nameLen;
\r
1564 buffer[3] = (al.AlignmentFlag << 16) | numCigarOperations;
\r
1565 buffer[4] = queryLen;
\r
1566 buffer[5] = al.MateRefID;
\r
1567 buffer[6] = al.MatePosition;
\r
1568 buffer[7] = al.InsertSize;
\r
1570 // write the block size
\r
1571 const unsigned int dataBlockSize = nameLen + packedCigarLen + encodedQueryLen + queryLen + tagDataLength;
\r
1572 const unsigned int blockSize = BAM_CORE_SIZE + dataBlockSize;
\r
1573 mBGZF.Write((char*)&blockSize, BT_SIZEOF_INT);
\r
1575 // write the BAM core
\r
1576 mBGZF.Write((char*)&buffer, BAM_CORE_SIZE);
\r
1578 // write the query name
\r
1579 mBGZF.Write(al.Name.c_str(), nameLen);
\r
1581 // write the packed cigar
\r
1582 mBGZF.Write(packedCigar.data(), packedCigarLen);
\r
1584 // write the encoded query sequence
\r
1585 mBGZF.Write(encodedQuery.data(), encodedQueryLen);
\r
1587 // write the base qualities
\r
1588 string baseQualities = al.Qualities;
\r
1589 char* pBaseQualities = (char*)al.Qualities.data();
\r
1590 for(unsigned int i = 0; i < queryLen; i++) { pBaseQualities[i] -= 33; }
\r
1591 mBGZF.Write(pBaseQualities, queryLen);
\r
1593 // write the read group tag
\r
1594 mBGZF.Write(al.TagData.data(), tagDataLength);
\r
1596 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0BamWriter.h
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000003034
\011307516613
\0013006
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0// ***************************************************************************
\r
1597 // BamWriter.h (c) 2009 Michael Strömberg, Derek Barnett
\r
1598 // Marth Lab, Department of Biology, Boston College
\r
1599 // All rights reserved.
\r
1600 // ---------------------------------------------------------------------------
\r
1601 // Last modified: 8 December 2009 (DB)
\r
1602 // ---------------------------------------------------------------------------
\r
1603 // Uses BGZF routines were adapted from the bgzf.c code developed at the Broad
\r
1605 // ---------------------------------------------------------------------------
\r
1606 // Provides the basic functionality for producing BAM files
\r
1607 // ***************************************************************************
\r
1609 #ifndef BAMWRITER_H
\r
1610 #define BAMWRITER_H
\r
1615 // BamTools includes
\r
1616 #include "BamAux.h"
\r
1618 namespace BamTools {
\r
1622 // constructor/destructor
\r
1627 // public interface
\r
1629 // closes the alignment archive
\r
1631 // opens the alignment archive
\r
1632 void Open(const std::string& filename, const std::string& samHeader, const BamTools::RefVector& referenceSequences);
\r
1633 // saves the alignment to the alignment archive
\r
1634 void SaveAlignment(const BamTools::BamAlignment& al);
\r
1636 // private implementation
\r
1638 struct BamWriterPrivate;
\r
1639 BamWriterPrivate* d;
\r
1642 } // namespace BamTools
\r
1644 #endif // BAMWRITER_H
\r
1645 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0BGZF.cpp
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000024215
\011307516613
\0012201
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0// ***************************************************************************
\r
1646 // BGZF.cpp (c) 2009 Derek Barnett, Michael Strömberg
\r
1647 // Marth Lab, Department of Biology, Boston College
\r
1648 // All rights reserved.
\r
1649 // ---------------------------------------------------------------------------
\r
1650 // Last modified: 8 December 2009 (DB)
\r
1651 // ---------------------------------------------------------------------------
\r
1652 // BGZF routines were adapted from the bgzf.c code developed at the Broad
\r
1654 // ---------------------------------------------------------------------------
\r
1655 // Provides the basic functionality for reading & writing BGZF files
\r
1656 // ***************************************************************************
\r
1658 #include <algorithm>
\r
1660 using namespace BamTools;
\r
1661 using std::string;
\r
1664 BgzfData::BgzfData(void)
\r
1665 : UncompressedBlockSize(DEFAULT_BLOCK_SIZE)
\r
1666 , CompressedBlockSize(MAX_BLOCK_SIZE)
\r
1671 , IsWriteOnly(false)
\r
1673 , UncompressedBlock(NULL)
\r
1674 , CompressedBlock(NULL)
\r
1677 CompressedBlock = new char[CompressedBlockSize];
\r
1678 UncompressedBlock = new char[UncompressedBlockSize];
\r
1679 } catch( std::bad_alloc& ba ) {
\r
1680 printf("ERROR: Unable to allocate memory for our BGZF object.\n");
\r
1686 BgzfData::~BgzfData(void) {
\r
1687 if(CompressedBlock) delete [] CompressedBlock;
\r
1688 if(UncompressedBlock) delete [] UncompressedBlock;
\r
1691 // closes BGZF file
\r
1692 void BgzfData::Close(void) {
\r
1694 if (!IsOpen) { return; }
\r
1697 // flush the BGZF block
\r
1698 if ( IsWriteOnly ) { FlushBlock(); }
\r
1700 // flush and close
\r
1705 // compresses the current block
\r
1706 int BgzfData::DeflateBlock(void) {
\r
1708 // initialize the gzip header
\r
1709 char* buffer = CompressedBlock;
\r
1710 unsigned int bufferSize = CompressedBlockSize;
\r
1712 memset(buffer, 0, 18);
\r
1713 buffer[0] = GZIP_ID1;
\r
1714 buffer[1] = (char)GZIP_ID2;
\r
1715 buffer[2] = CM_DEFLATE;
\r
1716 buffer[3] = FLG_FEXTRA;
\r
1717 buffer[9] = (char)OS_UNKNOWN;
\r
1718 buffer[10] = BGZF_XLEN;
\r
1719 buffer[12] = BGZF_ID1;
\r
1720 buffer[13] = BGZF_ID2;
\r
1721 buffer[14] = BGZF_LEN;
\r
1723 // loop to retry for blocks that do not compress enough
\r
1724 int inputLength = BlockOffset;
\r
1725 int compressedLength = 0;
\r
1732 zs.next_in = (Bytef*)UncompressedBlock;
\r
1733 zs.avail_in = inputLength;
\r
1734 zs.next_out = (Bytef*)&buffer[BLOCK_HEADER_LENGTH];
\r
1735 zs.avail_out = bufferSize - BLOCK_HEADER_LENGTH - BLOCK_FOOTER_LENGTH;
\r
1737 // initialize the zlib compression algorithm
\r
1738 if(deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, GZIP_WINDOW_BITS, Z_DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
\r
1739 printf("ERROR: zlib deflate initialization failed.\n");
\r
1743 // compress the data
\r
1744 int status = deflate(&zs, Z_FINISH);
\r
1745 if(status != Z_STREAM_END) {
\r
1749 // reduce the input length and try again
\r
1750 if(status == Z_OK) {
\r
1751 inputLength -= 1024;
\r
1752 if(inputLength < 0) {
\r
1753 printf("ERROR: input reduction failed.\n");
\r
1759 printf("ERROR: zlib deflate failed.\n");
\r
1763 // finalize the compression routine
\r
1764 if(deflateEnd(&zs) != Z_OK) {
\r
1765 printf("ERROR: deflate end failed.\n");
\r
1769 compressedLength = zs.total_out;
\r
1770 compressedLength += BLOCK_HEADER_LENGTH + BLOCK_FOOTER_LENGTH;
\r
1772 if(compressedLength > MAX_BLOCK_SIZE) {
\r
1773 printf("ERROR: deflate overflow.\n");
\r
1780 // store the compressed length
\r
1781 BgzfData::PackUnsignedShort(&buffer[16], (unsigned short)(compressedLength - 1));
\r
1783 // store the CRC32 checksum
\r
1784 unsigned int crc = crc32(0, NULL, 0);
\r
1785 crc = crc32(crc, (Bytef*)UncompressedBlock, inputLength);
\r
1786 BgzfData::PackUnsignedInt(&buffer[compressedLength - 8], crc);
\r
1787 BgzfData::PackUnsignedInt(&buffer[compressedLength - 4], inputLength);
\r
1789 // ensure that we have less than a block of data left
\r
1790 int remaining = BlockOffset - inputLength;
\r
1791 if(remaining > 0) {
\r
1792 if(remaining > inputLength) {
\r
1793 printf("ERROR: remainder too large.\n");
\r
1796 memcpy(UncompressedBlock, UncompressedBlock + inputLength, remaining);
\r
1799 BlockOffset = remaining;
\r
1800 return compressedLength;
\r
1803 // flushes the data in the BGZF block
\r
1804 void BgzfData::FlushBlock(void) {
\r
1806 // flush all of the remaining blocks
\r
1807 while(BlockOffset > 0) {
\r
1809 // compress the data block
\r
1810 int blockLength = DeflateBlock();
\r
1812 // flush the data to our output stream
\r
1813 int numBytesWritten = fwrite(CompressedBlock, 1, blockLength, Stream);
\r
1815 if(numBytesWritten != blockLength) {
\r
1816 printf("ERROR: Expected to write %u bytes during flushing, but wrote %u bytes.\n", blockLength, numBytesWritten);
\r
1820 BlockAddress += blockLength;
\r
1824 // de-compresses the current block
\r
1825 int BgzfData::InflateBlock(const int& blockLength) {
\r
1827 // Inflate the block in m_BGZF.CompressedBlock into m_BGZF.UncompressedBlock
\r
1831 zs.next_in = (Bytef*)CompressedBlock + 18;
\r
1832 zs.avail_in = blockLength - 16;
\r
1833 zs.next_out = (Bytef*)UncompressedBlock;
\r
1834 zs.avail_out = UncompressedBlockSize;
\r
1836 int status = inflateInit2(&zs, GZIP_WINDOW_BITS);
\r
1837 if (status != Z_OK) {
\r
1838 printf("inflateInit failed\n");
\r
1842 status = inflate(&zs, Z_FINISH);
\r
1843 if (status != Z_STREAM_END) {
\r
1845 printf("inflate failed\n");
\r
1849 status = inflateEnd(&zs);
\r
1850 if (status != Z_OK) {
\r
1851 printf("inflateEnd failed\n");
\r
1855 return zs.total_out;
\r
1858 void BgzfData::Open(const string& filename, const char* mode) {
\r
1860 if ( strcmp(mode, "rb") == 0 ) {
\r
1861 IsWriteOnly = false;
\r
1862 } else if ( strcmp(mode, "wb") == 0) {
\r
1863 IsWriteOnly = true;
\r
1865 printf("ERROR: Unknown file mode: %s\n", mode);
\r
1869 Stream = fopen(filename.c_str(), mode);
\r
1871 printf("ERROR: Unable to open the BAM file %s\n", filename.c_str() );
\r
1877 int BgzfData::Read(char* data, const unsigned int dataLength) {
\r
1879 if (dataLength == 0) { return 0; }
\r
1881 char* output = data;
\r
1882 unsigned int numBytesRead = 0;
\r
1883 while (numBytesRead < dataLength) {
\r
1885 int bytesAvailable = BlockLength - BlockOffset;
\r
1886 if (bytesAvailable <= 0) {
\r
1887 if ( ReadBlock() != 0 ) { return -1; }
\r
1888 bytesAvailable = BlockLength - BlockOffset;
\r
1889 if ( bytesAvailable <= 0 ) { break; }
\r
1892 char* buffer = UncompressedBlock;
\r
1893 int copyLength = min( (int)(dataLength-numBytesRead), bytesAvailable );
\r
1894 memcpy(output, buffer + BlockOffset, copyLength);
\r
1896 BlockOffset += copyLength;
\r
1897 output += copyLength;
\r
1898 numBytesRead += copyLength;
\r
1901 if ( BlockOffset == BlockLength ) {
\r
1902 BlockAddress = ftell(Stream);
\r
1907 return numBytesRead;
\r
1910 int BgzfData::ReadBlock(void) {
\r
1912 char header[BLOCK_HEADER_LENGTH];
\r
1913 int64_t blockAddress = ftell(Stream);
\r
1915 int count = fread(header, 1, sizeof(header), Stream);
\r
1921 if (count != sizeof(header)) {
\r
1922 printf("read block failed - count != sizeof(header)\n");
\r
1926 if (!BgzfData::CheckBlockHeader(header)) {
\r
1927 printf("read block failed - CheckBlockHeader() returned false\n");
\r
1931 int blockLength = BgzfData::UnpackUnsignedShort(&header[16]) + 1;
\r
1932 char* compressedBlock = CompressedBlock;
\r
1933 memcpy(compressedBlock, header, BLOCK_HEADER_LENGTH);
\r
1934 int remaining = blockLength - BLOCK_HEADER_LENGTH;
\r
1936 count = fread(&compressedBlock[BLOCK_HEADER_LENGTH], 1, remaining, Stream);
\r
1937 if (count != remaining) {
\r
1938 printf("read block failed - count != remaining\n");
\r
1942 count = InflateBlock(blockLength);
\r
1943 if (count < 0) { return -1; }
\r
1945 if ( BlockLength != 0 ) {
\r
1949 BlockAddress = blockAddress;
\r
1950 BlockLength = count;
\r
1954 bool BgzfData::Seek(int64_t position) {
\r
1956 int blockOffset = (position & 0xFFFF);
\r
1957 int64_t blockAddress = (position >> 16) & 0xFFFFFFFFFFFFLL;
\r
1959 if (fseek(Stream, blockAddress, SEEK_SET) != 0) {
\r
1960 printf("ERROR: Unable to seek in BAM file\n");
\r
1965 BlockAddress = blockAddress;
\r
1966 BlockOffset = blockOffset;
\r
1970 int64_t BgzfData::Tell(void) {
\r
1971 return ( (BlockAddress << 16) | (BlockOffset & 0xFFFF) );
\r
1974 // writes the supplied data into the BGZF buffer
\r
1975 unsigned int BgzfData::Write(const char* data, const unsigned int dataLen) {
\r
1978 unsigned int numBytesWritten = 0;
\r
1979 const char* input = data;
\r
1980 unsigned int blockLength = UncompressedBlockSize;
\r
1982 // copy the data to the buffer
\r
1983 while(numBytesWritten < dataLen) {
\r
1984 unsigned int copyLength = min(blockLength - BlockOffset, dataLen - numBytesWritten);
\r
1985 char* buffer = UncompressedBlock;
\r
1986 memcpy(buffer + BlockOffset, input, copyLength);
\r
1988 BlockOffset += copyLength;
\r
1989 input += copyLength;
\r
1990 numBytesWritten += copyLength;
\r
1992 if(BlockOffset == blockLength) {
\r
1997 return numBytesWritten;
\r
1999 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0BGZF.h
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000013625
\011307516613
\0011651
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0// ***************************************************************************
\r
2000 // BGZF.h (c) 2009 Derek Barnett, Michael Strömberg
\r
2001 // Marth Lab, Department of Biology, Boston College
\r
2002 // All rights reserved.
\r
2003 // ---------------------------------------------------------------------------
\r
2004 // Last modified: 8 December 2009 (DB)
\r
2005 // ---------------------------------------------------------------------------
\r
2006 // BGZF routines were adapted from the bgzf.c code developed at the Broad
\r
2008 // ---------------------------------------------------------------------------
\r
2009 // Provides the basic functionality for reading & writing BGZF files
\r
2010 // ***************************************************************************
\r
2017 #include <cstdlib>
\r
2018 #include <cstring>
\r
2026 // Platform-specific type definitions
\r
2028 typedef char int8_t;
\r
2029 typedef unsigned char uint8_t;
\r
2030 typedef short int16_t;
\r
2031 typedef unsigned short uint16_t;
\r
2032 typedef int int32_t;
\r
2033 typedef unsigned int uint32_t;
\r
2034 typedef long long int64_t;
\r
2035 typedef unsigned long long uint64_t;
\r
2037 #include <stdint.h>
\r
2040 namespace BamTools {
\r
2043 const int GZIP_ID1 = 31;
\r
2044 const int GZIP_ID2 = 139;
\r
2045 const int CM_DEFLATE = 8;
\r
2046 const int FLG_FEXTRA = 4;
\r
2047 const int OS_UNKNOWN = 255;
\r
2048 const int BGZF_XLEN = 6;
\r
2049 const int BGZF_ID1 = 66;
\r
2050 const int BGZF_ID2 = 67;
\r
2051 const int BGZF_LEN = 2;
\r
2052 const int GZIP_WINDOW_BITS = -15;
\r
2053 const int Z_DEFAULT_MEM_LEVEL = 8;
\r
2056 const int BLOCK_HEADER_LENGTH = 18;
\r
2057 const int BLOCK_FOOTER_LENGTH = 8;
\r
2058 const int MAX_BLOCK_SIZE = 65536;
\r
2059 const int DEFAULT_BLOCK_SIZE = 65536;
\r
2064 unsigned int UncompressedBlockSize;
\r
2065 unsigned int CompressedBlockSize;
\r
2066 unsigned int BlockLength;
\r
2067 unsigned int BlockOffset;
\r
2068 uint64_t BlockAddress;
\r
2072 char* UncompressedBlock;
\r
2073 char* CompressedBlock;
\r
2075 // constructor & destructor
\r
2079 // closes BGZF file
\r
2081 // compresses the current block
\r
2082 int DeflateBlock(void);
\r
2083 // flushes the data in the BGZF block
\r
2084 void FlushBlock(void);
\r
2085 // de-compresses the current block
\r
2086 int InflateBlock(const int& blockLength);
\r
2087 // opens the BGZF file for reading (mode is either "rb" for reading, or "wb" for writing
\r
2088 void Open(const std::string& filename, const char* mode);
\r
2089 // reads BGZF data into a byte buffer
\r
2090 int Read(char* data, const unsigned int dataLength);
\r
2091 // reads BGZF block
\r
2092 int ReadBlock(void);
\r
2093 // seek to position in BAM file
\r
2094 bool Seek(int64_t position);
\r
2095 // get file position in BAM file
\r
2096 int64_t Tell(void);
\r
2097 // writes the supplied data into the BGZF buffer
\r
2098 unsigned int Write(const char* data, const unsigned int dataLen);
\r
2100 // checks BGZF block header
\r
2101 static inline bool CheckBlockHeader(char* header);
\r
2102 // packs an unsigned integer into the specified buffer
\r
2103 static inline void PackUnsignedInt(char* buffer, unsigned int value);
\r
2104 // packs an unsigned short into the specified buffer
\r
2105 static inline void PackUnsignedShort(char* buffer, unsigned short value);
\r
2106 // unpacks a buffer into a signed int
\r
2107 static inline signed int UnpackSignedInt(char* buffer);
\r
2108 // unpacks a buffer into a unsigned int
\r
2109 static inline unsigned int UnpackUnsignedInt(char* buffer);
\r
2110 // unpacks a buffer into a unsigned short
\r
2111 static inline unsigned short UnpackUnsignedShort(char* buffer);
\r
2114 // -------------------------------------------------------------
\r
2117 bool BgzfData::CheckBlockHeader(char* header) {
\r
2119 return (header[0] == GZIP_ID1 &&
\r
2120 header[1] == (char)GZIP_ID2 &&
\r
2121 header[2] == Z_DEFLATED &&
\r
2122 (header[3] & FLG_FEXTRA) != 0 &&
\r
2123 BgzfData::UnpackUnsignedShort(&header[10]) == BGZF_XLEN &&
\r
2124 header[12] == BGZF_ID1 &&
\r
2125 header[13] == BGZF_ID2 &&
\r
2126 BgzfData::UnpackUnsignedShort(&header[14]) == BGZF_LEN );
\r
2129 // packs an unsigned integer into the specified buffer
\r
2131 void BgzfData::PackUnsignedInt(char* buffer, unsigned int value) {
\r
2132 buffer[0] = (char)value;
\r
2133 buffer[1] = (char)(value >> 8);
\r
2134 buffer[2] = (char)(value >> 16);
\r
2135 buffer[3] = (char)(value >> 24);
\r
2138 // packs an unsigned short into the specified buffer
\r
2140 void BgzfData::PackUnsignedShort(char* buffer, unsigned short value) {
\r
2141 buffer[0] = (char)value;
\r
2142 buffer[1] = (char)(value >> 8);
\r
2145 // unpacks a buffer into a signed int
\r
2147 signed int BgzfData::UnpackSignedInt(char* buffer) {
\r
2148 union { signed int value; unsigned char valueBuffer[sizeof(signed int)]; } un;
\r
2150 un.valueBuffer[0] = buffer[0];
\r
2151 un.valueBuffer[1] = buffer[1];
\r
2152 un.valueBuffer[2] = buffer[2];
\r
2153 un.valueBuffer[3] = buffer[3];
\r
2157 // unpacks a buffer into an unsigned int
\r
2159 unsigned int BgzfData::UnpackUnsignedInt(char* buffer) {
\r
2160 union { unsigned int value; unsigned char valueBuffer[sizeof(unsigned int)]; } un;
\r
2162 un.valueBuffer[0] = buffer[0];
\r
2163 un.valueBuffer[1] = buffer[1];
\r
2164 un.valueBuffer[2] = buffer[2];
\r
2165 un.valueBuffer[3] = buffer[3];
\r
2169 // unpacks a buffer into an unsigned short
\r
2171 unsigned short BgzfData::UnpackUnsignedShort(char* buffer) {
\r
2172 union { unsigned short value; unsigned char valueBuffer[sizeof(unsigned short)];} un;
\r
2174 un.valueBuffer[0] = buffer[0];
\r
2175 un.valueBuffer[1] = buffer[1];
\r
2179 } // namespace BamTools
\r
2182 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Makefile
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000001044
\011307517214
\0012376
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0CXX= g++
\r
2183 CXXFLAGS= -Wall -O3
\r
2184 PROG= BamConversion BamDump BamTrim
\r
2189 BamConversion: BGZF.o BamReader.o BamWriter.o BamConversionMain.o
\r
2190 $(CXX) $(CXXFLAGS) -o $@ BGZF.o BamReader.o BamWriter.o BamConversionMain.o $(LIBS)
\r
2192 BamDump: BGZF.o BamReader.o BamDumpMain.o
\r
2193 $(CXX) $(CXXFLAGS) -o $@ BGZF.o BamReader.o BamDumpMain.o $(LIBS)
\r
2195 BamTrim: BGZF.o BamReader.o BamWriter.o BamTrimMain.o
\r
2196 $(CXX) $(CXXFLAGS) -o $@ BGZF.o BamReader.o BamWriter.o BamTrimMain.o $(LIBS)
\r
2199 rm -fr gmon.out *.o *.a a.out *~
\r
2200 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0README
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000664
\00001074
\00001074
\000000003607
\011307522302
\0011617
\0 0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar
\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0barnett
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0------------------------------------------------------------
2202 ------------------------------------------------------------
2204 BamTools: a C++ API for reading/writing BAM files.
2210 ------------------------------------------------------------
2214 The API consists of 2 main modules - BamReader and BamWriter. As you would expect,
2215 BamReader provides read-access to BAM files, while BamWriter does the writing of BAM
2216 files. BamReader provides an interface for random-access (jumping) in a BAM file,
2217 as well as generating BAM index files.
2219 An additional file, BamAux.h, is included as well.
2220 This file contains the common data structures and typedefs used throught the API.
2222 BGZF.h & BGZF.cpp contain our implementation of the Broad Institute's
2223 BGZF compression format.
2225 BamConversion, BamDump, and BamTrim are 3 'toy' examples on how the API can be used.
2227 ------------------------------------------------------------
2231 To use this API, you simply need to do 3 things:
2233 1 - Drop the BamTools files somewhere the compiler can find them.
2234 (i.e. in your source tree, or somewhere else in your include path)
2236 2 - Import BamTools API with the following lines of code
2237 #include "BamReader.h" // as needed
2238 #include "BamWriter.h" // as needed
2239 using namespace BamTools;
2241 3 - Compile with '-lz' ('l' as in Lima) to access ZLIB compression library
2242 (For VS users, I can provide you zlib headers - just contact me).
2244 See any included programs and Makefile for more specific compiling/usage examples.
2245 See comments in the header files for more detailed API documentation.
2247 ------------------------------------------------------------
2251 Feel free to contact me with any questions, comments, suggestions, bug reports, etc.
2254 http://sourceforge.net/projects/bamtools
2255 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0