00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __PILEUP_H__
00019 #define __PILEUP_H__
00020
00021 template <class PILEUP_TYPE>
00022 class defaultPileup
00023 {
00024 public:
00025 bool operator() (PILEUP_TYPE& element)
00026 {
00027 element.analyze();
00028 return(true);
00029 }
00030 void analyze(PILEUP_TYPE element)
00031 {
00032 element.analyze();
00033 }
00034 };
00035
00036 template <class PILEUP_TYPE>
00037 void defaultPileupAnalyze(PILEUP_TYPE& element)
00038 {
00039 element.analyze();
00040 }
00041
00042
00043 template <class PILEUP_TYPE,
00044 class FUNC_CLASS = defaultPileup<PILEUP_TYPE> >
00045 class Pileup
00046 {
00047 public:
00048 Pileup(const FUNC_CLASS& fp = FUNC_CLASS());
00049
00050 Pileup(int window, const FUNC_CLASS& fp = FUNC_CLASS());
00051
00052
00053 Pileup(const std::string& refSeqFileName,
00054 const FUNC_CLASS& fp = FUNC_CLASS());
00055
00056
00057 Pileup(int window, const std::string& refSeqFileName,
00058 const FUNC_CLASS& fp = FUNC_CLASS());
00059
00060 ~Pileup();
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 virtual int processFile(const std::string& fileName,
00074 uint16_t excludeFlag = 0x0704,
00075 uint16_t includeFlag = 0);
00076
00077
00078
00079 virtual void processAlignment(SamRecord& record);
00080
00081
00082 void flushPileup();
00083
00084 protected:
00085 FUNC_CLASS myAnalyzeFuncPtr;
00086
00087
00088 void addAlignmentPosition(int refPosition, SamRecord& record);
00089
00090
00091 void flushPileup(int refID, int refPosition);
00092 void flushPileup(int refPosition);
00093
00094
00095
00096
00097 int pileupPosition(int refPosition);
00098
00099 virtual void resetElement(PILEUP_TYPE& element, int position);
00100 virtual void addElement(PILEUP_TYPE& element, SamRecord& record);
00101 virtual void analyzeElement(PILEUP_TYPE& element);
00102
00103 std::vector<PILEUP_TYPE> myElements;
00104
00105 int pileupStart;
00106 int pileupHead;
00107 int pileupTail;
00108 int pileupWindow;
00109
00110 int myCurrentRefID;
00111
00112 GenomeSequence* myRefPtr;
00113 };
00114
00115
00116 template <class PILEUP_TYPE, class FUNC_CLASS>
00117 Pileup<PILEUP_TYPE, FUNC_CLASS>::Pileup(const FUNC_CLASS& fp)
00118 : myAnalyzeFuncPtr(fp),
00119 myElements(),
00120 pileupStart(0),
00121 pileupHead(0),
00122 pileupTail(-1),
00123 pileupWindow(1024),
00124 myCurrentRefID(-2),
00125 myRefPtr(NULL)
00126 {
00127
00128 myElements.resize(pileupWindow);
00129 }
00130
00131
00132 template <class PILEUP_TYPE, class FUNC_CLASS>
00133 Pileup<PILEUP_TYPE, FUNC_CLASS>::Pileup(int window, const FUNC_CLASS& fp)
00134 : myAnalyzeFuncPtr(fp),
00135 myElements(),
00136 pileupStart(0),
00137 pileupHead(0),
00138 pileupTail(-1),
00139 pileupWindow(window),
00140 myCurrentRefID(-2),
00141 myRefPtr(NULL)
00142 {
00143
00144 myElements.resize(window);
00145 }
00146
00147
00148 template <class PILEUP_TYPE, class FUNC_CLASS>
00149 Pileup<PILEUP_TYPE, FUNC_CLASS>::Pileup(const std::string& refSeqFileName, const FUNC_CLASS& fp)
00150 : myAnalyzeFuncPtr(fp),
00151 myElements(),
00152 pileupStart(0),
00153 pileupHead(0),
00154 pileupTail(-1),
00155 pileupWindow(1024),
00156 myCurrentRefID(-2),
00157 myRefPtr(NULL)
00158 {
00159 myRefPtr = new GenomeSequence(refSeqFileName.c_str());
00160
00161
00162 myElements.resize(pileupWindow);
00163
00164 PILEUP_TYPE::setReference(myRefPtr);
00165 }
00166
00167
00168 template <class PILEUP_TYPE, class FUNC_CLASS>
00169 Pileup<PILEUP_TYPE, FUNC_CLASS>::Pileup(int window, const std::string& refSeqFileName, const FUNC_CLASS& fp)
00170 : myAnalyzeFuncPtr(fp),
00171 myElements(),
00172 pileupStart(0),
00173 pileupHead(0),
00174 pileupTail(-1),
00175 pileupWindow(window),
00176 myCurrentRefID(-2),
00177 myRefPtr(NULL)
00178 {
00179 myRefPtr = new GenomeSequence(refSeqFileName.c_str());
00180
00181
00182 myElements.resize(window);
00183
00184 PILEUP_TYPE::setReference(myRefPtr);
00185 }
00186
00187
00188 template <class PILEUP_TYPE, class FUNC_CLASS>
00189 Pileup<PILEUP_TYPE, FUNC_CLASS>::~Pileup()
00190 {
00191 if(myRefPtr != NULL)
00192 {
00193 delete myRefPtr;
00194 myRefPtr = NULL;
00195 }
00196 }
00197
00198 template <class PILEUP_TYPE, class FUNC_CLASS>
00199 int Pileup<PILEUP_TYPE, FUNC_CLASS>::processFile(const std::string& fileName,
00200 uint16_t excludeFlag,
00201 uint16_t includeFlag)
00202 {
00203 SamFile samIn;
00204 SamFileHeader header;
00205 SamRecord record;
00206
00207 if(myRefPtr != NULL)
00208 {
00209 samIn.SetReference(myRefPtr);
00210 }
00211
00212 if(!samIn.OpenForRead(fileName.c_str()))
00213 {
00214 fprintf(stderr, "%s\n", samIn.GetStatusMessage());
00215 return(samIn.GetStatus());
00216 }
00217
00218 if(!samIn.ReadHeader(header))
00219 {
00220 fprintf(stderr, "%s\n", samIn.GetStatusMessage());
00221 return(samIn.GetStatus());
00222 }
00223
00224
00225 samIn.setSortedValidation(SamFile::COORDINATE);
00226
00227
00228 while (samIn.ReadRecord(header, record))
00229 {
00230 uint16_t flag = record.getFlag();
00231 if(flag & excludeFlag)
00232 {
00233
00234
00235 continue;
00236 }
00237 if((flag & includeFlag) != includeFlag)
00238 {
00239
00240
00241 continue;
00242 }
00243 processAlignment(record);
00244 }
00245
00246 flushPileup();
00247
00248 int returnValue = 0;
00249 if(samIn.GetStatus() != SamStatus::NO_MORE_RECS)
00250 {
00251
00252 fprintf(stderr, "%s\n", samIn.GetStatusMessage());
00253 returnValue = samIn.GetStatus();
00254 }
00255 return(returnValue);
00256 }
00257
00258
00259 template <class PILEUP_TYPE, class FUNC_CLASS>
00260 void Pileup<PILEUP_TYPE, FUNC_CLASS>::processAlignment(SamRecord& record)
00261 {
00262 int refPosition = record.get0BasedPosition();
00263 int refID = record.getReferenceID();
00264
00265
00266
00267 flushPileup(refID, refPosition);
00268
00269
00270
00271
00272 for(; refPosition <= record.get0BasedAlignmentEnd(); ++refPosition)
00273 {
00274 addAlignmentPosition(refPosition, record);
00275 }
00276 }
00277
00278
00279 template <class PILEUP_TYPE, class FUNC_CLASS>
00280 void Pileup<PILEUP_TYPE, FUNC_CLASS>::flushPileup()
00281 {
00282
00283
00284
00285 while ((pileupHead <= pileupTail) && (pileupTail != -1))
00286 {
00287 flushPileup(pileupHead+1);
00288 }
00289 pileupStart = pileupHead = 0;
00290 pileupTail = -1;
00291 }
00292
00293
00294
00295 template <class PILEUP_TYPE, class FUNC_CLASS>
00296 void Pileup<PILEUP_TYPE, FUNC_CLASS>::addAlignmentPosition(int refPosition,
00297 SamRecord& record)
00298 {
00299 int offset = pileupPosition(refPosition);
00300
00301 if((offset < 0) || (offset >= pileupWindow))
00302 {
00303 std::cerr << "Pileup Buffer Overflow: position = " << refPosition
00304 << "; refID = " << record.getReferenceID()
00305 << "; recStartPos = " << record.get1BasedPosition()
00306 << "; pileupStart = " << pileupStart
00307 << "; pileupHead = " << pileupHead
00308 << "; pileupTail = " << pileupTail;
00309 }
00310
00311 addElement(myElements[offset], record);
00312 }
00313
00314
00315 template <class PILEUP_TYPE, class FUNC_CLASS>
00316 void Pileup<PILEUP_TYPE, FUNC_CLASS>::flushPileup(int refID, int position)
00317 {
00318
00319 if(refID != myCurrentRefID)
00320 {
00321
00322 flushPileup();
00323 myCurrentRefID = refID;
00324
00325
00326 pileupStart = pileupHead = position;
00327 }
00328 else
00329 {
00330
00331 flushPileup(position);
00332 }
00333 }
00334
00335
00336 template <class PILEUP_TYPE, class FUNC_CLASS>
00337 void Pileup<PILEUP_TYPE, FUNC_CLASS>::flushPileup(int position)
00338 {
00339
00340
00341 while((pileupHead < position) && (pileupHead <= pileupTail))
00342 {
00343 analyzeElement(myElements[pileupHead - pileupStart]);
00344
00345 pileupHead++;
00346
00347 if(pileupHead - pileupStart >= pileupWindow)
00348 pileupStart += pileupWindow;
00349 }
00350
00351
00352
00353 if(pileupHead != position)
00354 {
00355 pileupHead = pileupStart = position;
00356 }
00357 }
00358
00359
00360
00361
00362
00363 template <class PILEUP_TYPE, class FUNC_CLASS>
00364 int Pileup<PILEUP_TYPE, FUNC_CLASS>::pileupPosition(int position)
00365 {
00366 if((position < pileupHead) || (position > (pileupHead + pileupWindow)))
00367 {
00368 return -1;
00369 error("Pileup Buffer Overflow");
00370 }
00371
00372 int offset = position - pileupStart;
00373
00374 if(offset >= pileupWindow)
00375 {
00376 offset -= pileupWindow;
00377 }
00378
00379 if(position > pileupTail)
00380 {
00381
00382
00383 resetElement(myElements[offset], position);
00384 pileupTail = position;
00385 }
00386
00387 return(offset);
00388 }
00389
00390
00391 template <class PILEUP_TYPE, class FUNC_CLASS>
00392 void Pileup<PILEUP_TYPE, FUNC_CLASS>::resetElement(PILEUP_TYPE& element,
00393 int position)
00394 {
00395 element.reset(position);
00396 }
00397
00398
00399 template <class PILEUP_TYPE, class FUNC_CLASS>
00400 void Pileup<PILEUP_TYPE, FUNC_CLASS>::addElement(PILEUP_TYPE& element,
00401 SamRecord& record)
00402 {
00403 element.addEntry(record);
00404 }
00405
00406
00407 template <class PILEUP_TYPE, class FUNC_CLASS>
00408 void Pileup<PILEUP_TYPE, FUNC_CLASS>::analyzeElement(PILEUP_TYPE& element)
00409 {
00410 myAnalyzeFuncPtr(element);
00411 }
00412
00413
00414
00415
00416 #endif