yat  0.13.2pre
Pileup.h
1 #ifndef theplu_yat_omic_pileup
2 #define theplu_yat_omic_pileup
3 
4 // $Id: Pileup.h 3336 2014-10-24 23:27:45Z peter $
5 
6 /*
7  Copyright (C) 2014 Peter Johansson
8 
9  This file is part of the yat library, http://dev.thep.lu.se/yat
10 
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 3 of the
14  License, or (at your option) any later version.
15 
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24 
25 #include "BamRead.h"
26 
27 #include "yat/utility/CigarIterator.h"
28 #include "yat/utility/yat_assert.h"
29 
30 #include <boost/iterator/iterator_traits.hpp>
31 #include <boost/concept/assert.hpp>
32 #include <boost/shared_ptr.hpp>
33 
34 #include <algorithm>
35 #include <list>
36 
37 namespace theplu {
38 namespace yat {
39 namespace omic {
40 
54  template<typename Iterator>
55  class Pileup
56  {
57  public:
62  class Entry
63  {
64  public:
68  Entry(void) {}
69 
74  Entry(const BamRead& b);
75 
79  const BamRead& bam(void) const
80  {
81  YAT_ASSERT(bam_.get());
82  return *bam_;
83  }
84 
88  uint8_t cigar_op(void) const { return *cigar_; }
89 
90 
94  uint32_t cigar_oplen(void) const
95  {
96  YAT_ASSERT(bam_.get());
97  YAT_ASSERT(cigar_.base() >= bam_->cigar());
98  return bam_cigar_oplen(*cigar_.base());
99  }
100 
101 
105  unsigned short qual(void) const
106  {
107  YAT_ASSERT(bam_.get());
108  YAT_ASSERT(qpos_ < bam_->sequence_length());
109  return bam_->qual(qpos_);
110  }
111 
115  uint8_t sequence(void) const;
116 
121  void increment(void);
122 
126  bool is_del(void) const
127  {
128  return cigar_type()==2;
129  }
130 
134  size_t qpos(void) const { return qpos_; }
135  private:
136  boost::shared_ptr<BamRead> bam_;
137  // index of base pointed to
138  size_t qpos_;
140  size_t skip_;
141  // return 0, 1, 2, or 3 see bam_cigar_type in yat/utility/Cigar.h
142  uint8_t cigar_type(void) const { return bam_cigar_type(cigar_op()); }
143  friend class Pileup;
144  };
145 
146  public:
151  typedef typename std::list<Entry>::const_iterator const_iterator;
152 
156  Pileup(void) {}
157 
164  Pileup(Iterator first, Iterator last);
165 
173  const_iterator begin(void) const;
174 
179  const_iterator end(void) const;
180 
184  bool good(void) const { return !(bam_ == bam_end_ && data_.empty()); }
185 
196  void increment(void);
197 
201  int32_t tid(void) const { return tid_; }
202 
206  int32_t pos(void) const { return pos_; }
207 
212  bool skip_ref(void) const;
213  private:
214  typedef typename std::list<Entry>::iterator iterator;
215 
216  Iterator bam_;
217  Iterator bam_end_;
218  int32_t pos_;
219  int32_t tid_;
220  std::list<Entry> data_;
221  uint32_t skip_ref_;
222  };
223 
224 
230  template<typename Iterator>
231  Pileup<Iterator> make_pileup(Iterator first, Iterator last)
232  {
233  return Pileup<Iterator>(first, last);
234  }
235 
236  // implementations
237 
238  template<typename Iterator>
239  Pileup<Iterator>::Pileup(Iterator first, Iterator last)
240  : bam_(first), bam_end_(last), pos_(0), tid_(0), skip_ref_(0)
241  {
242  BOOST_CONCEPT_ASSERT((boost::InputIterator<Iterator>));
243  using boost::Convertible;
244  typedef typename boost::iterator_value<Iterator>::type value_type;
245  BOOST_CONCEPT_ASSERT((Convertible<value_type, BamRead>));
246  increment();
247  }
248 
249 
250  template<typename Iterator>
252  {
253  return data_.begin();
254  }
255 
256 
257  template<typename Iterator>
259  {
260  return data_.end();
261  }
262 
263 
264  template<typename Iterator>
266  {
267  if (!data_.empty()) {
268  // in insertion
269  if (skip_ref()) {
270  for (iterator it = data_.begin(); it!=data_.end(); ++it) {
271  if (it->cigar_type() == 1) {
272  it->increment();
273  }
274  --it->skip_;
275  }
276  --skip_ref_;
277  }
278  // walk one base forward on reference
279  else {
280  ++pos_;
281  typename std::list<Entry>::iterator read = data_.begin();
282  while (read != data_.end()) {
283  read->increment();
284  // remove entry if read is entirely left of pos
285  if (read->bam().end() <= pos_) { // FIXME speedup possible
286  data_.erase(read++);
287  continue;
288  }
289  // check if we're stepping into insertion
290  if (read->cigar_op() == BAM_CINS) {
291  skip_ref_ = std::max(skip_ref_, read->cigar_oplen());
292  }
293  ++read;
294  }
295 
296  // stepped into an insertion
297  if (skip_ref_)
298  for (iterator iter=data_.begin(); iter!=data_.end(); ++iter)
299  iter->skip_ = skip_ref_;
300  }
301  }
302 
303 
304  // fast forward to next covered locus
305  if (data_.empty()) {
306  if (bam_==bam_end_)
307  return;
308  tid_ = bam_->core().tid;
309  pos_ = bam_->core().pos;
310  }
311 
312  // read data
313  while (bam_!=bam_end_ && bam_->core().tid==tid_ && bam_->pos()<=pos_) {
314  // skip unmapped reads
315  if (!(bam_->core().flag & BAM_FUNMAP)) {
316  data_.push_back(Entry(*bam_));
317  }
318  ++bam_;
319  }
320  }
321 
322 
323  template<typename Iterator>
324  bool Pileup<Iterator>::skip_ref(void) const
325  {
326  return skip_ref_;
327  }
328 
329 
330  template<typename Iterator>
332  : bam_(new BamRead(b)), qpos_(0), cigar_(bam_->cigar()), skip_(0)
333  {
334  YAT_ASSERT(cigar_.base() == bam_->cigar());
335  if (bam_->core().n_cigar==0)
336  return;
337  // iterate cigar to first match
338  while (qpos_ < bam_->sequence_length() && cigar_type() != 3) {
339  // type is either 0 (hardclipped) or 1 (softclipped)
340  YAT_ASSERT(cigar_type()!=2);
341  if (cigar_type() == 1)
342  ++qpos_;
343  ++cigar_;
344  }
345  }
346 
347 
348  template<typename Iterator>
350  {
351  YAT_ASSERT(cigar_.base() >= bam_->cigar());
352  if (cigar_type() & 1)
353  ++qpos_;
354  ++cigar_;
355  YAT_ASSERT(cigar_.base() >= bam_->cigar());
356  }
357 
358 
359  template<typename Iterator>
361  {
362  if (skip_==0) {
363  if (cigar_type() & 1)
364  return bam_->sequence(qpos_);
365  return 0;
366  }
367  if (cigar_op()!=BAM_CINS)
368  return 0;
369  return bam_->sequence(qpos_);
370  }
371 
372 }}}
373 #endif
std::list< Entry >::const_iterator const_iterator
Definition: Pileup.h:151
void increment(void)
step to next position.
Definition: Pileup.h:265
Class holding a bam query.
Definition: BamRead.h:53
uint8_t cigar_op(void) const
Definition: Pileup.h:88
Pileup< Iterator > make_pileup(Iterator first, Iterator last)
Definition: Pileup.h:231
T max(const T &a, const T &b, const T &c)
Definition: stl_utility.h:683
bool is_del(void) const
Definition: Pileup.h:126
int32_t tid(void) const
Definition: Pileup.h:201
Definition: Pileup.h:55
BASE base(void) const
Definition: CigarIterator.h:115
size_t qpos(void) const
Definition: Pileup.h:134
Definition: Pileup.h:62
bool good(void) const
Definition: Pileup.h:184
Entry(void)
default constructor
Definition: Pileup.h:68
uint32_t cigar_oplen(void) const
Definition: Pileup.h:94
bool skip_ref(void) const
Definition: Pileup.h:324
uint8_t sequence(void) const
Definition: Pileup.h:360
int32_t pos(void) const
Definition: Pileup.h:206
const_iterator begin(void) const
Definition: Pileup.h:251
void increment(void)
Definition: Pileup.h:349
const BamRead & bam(void) const
Definition: Pileup.h:79
const_iterator end(void) const
Definition: Pileup.h:258
unsigned short qual(void) const
Definition: Pileup.h:105
Pileup(void)
Definition: Pileup.h:156

Generated on Wed Jan 4 2017 02:23:07 for yat by  doxygen 1.8.5