yat  0.14.5pre
Pileup.h
1 #ifndef theplu_yat_omic_pileup
2 #define theplu_yat_omic_pileup
3 
4 // $Id: Pileup.h 3550 2017-01-03 05:41:02Z peter $
5 
6 /*
7  Copyright (C) 2014, 2016 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/iterator/iterator_concepts.hpp>
32 #include <boost/concept/assert.hpp>
33 #include <boost/shared_ptr.hpp>
34 
35 #include <algorithm>
36 #include <list>
37 
38 namespace theplu {
39 namespace yat {
40 namespace omic {
41 
56  template<typename Iterator>
57  class Pileup
58  {
59  public:
64  class Entry
65  {
66  public:
70  Entry(void) {}
71 
76  Entry(const BamRead& b);
77 
81  const BamRead& bam(void) const
82  {
83  YAT_ASSERT(bam_.get());
84  return *bam_;
85  }
86 
90  uint8_t cigar_op(void) const { return *cigar_; }
91 
92 
96  uint32_t cigar_oplen(void) const
97  {
98  YAT_ASSERT(bam_.get());
99  YAT_ASSERT(cigar_.base() >= bam_->cigar());
100  return bam_cigar_oplen(*cigar_.base());
101  }
102 
103 
107  unsigned short qual(void) const
108  {
109  YAT_ASSERT(bam_.get());
110  YAT_ASSERT(qpos_ < bam_->sequence_length());
111  return bam_->qual(qpos_);
112  }
113 
117  uint8_t sequence(void) const;
118 
123  void increment(void);
124 
128  bool is_del(void) const
129  {
130  return cigar_type()==2;
131  }
132 
136  size_t qpos(void) const { return qpos_; }
137  private:
138  boost::shared_ptr<BamRead> bam_;
139  // index of base pointed to
140  size_t qpos_;
142  size_t skip_;
143  // return 0, 1, 2, or 3 see bam_cigar_type in yat/utility/Cigar.h
144  uint8_t cigar_type(void) const { return bam_cigar_type(cigar_op()); }
145  friend class Pileup;
146  };
147 
148  public:
153  typedef typename std::list<Entry>::const_iterator const_iterator;
154 
158  Pileup(void) {}
159 
166  Pileup(Iterator first, Iterator last);
167 
175  const_iterator begin(void) const;
176 
181  const_iterator end(void) const;
182 
186  bool good(void) const { return !(bam_ == bam_end_ && data_.empty()); }
187 
198  void increment(void);
199 
203  int32_t tid(void) const { return tid_; }
204 
208  int32_t pos(void) const { return pos_; }
209 
214  bool skip_ref(void) const;
215  private:
216  typedef typename std::list<Entry>::iterator iterator;
217 
218  Iterator bam_;
219  Iterator bam_end_;
220  int32_t pos_;
221  int32_t tid_;
222  std::list<Entry> data_;
223  uint32_t skip_ref_;
224  };
225 
226 
232  template<typename Iterator>
233  Pileup<Iterator> make_pileup(Iterator first, Iterator last)
234  {
235  return Pileup<Iterator>(first, last);
236  }
237 
238  // implementations
239 
240  template<typename Iterator>
241  Pileup<Iterator>::Pileup(Iterator first, Iterator last)
242  : bam_(first), bam_end_(last), pos_(0), tid_(0), skip_ref_(0)
243  {
244  BOOST_CONCEPT_ASSERT((boost_concepts::ReadableIterator<Iterator>));
245  BOOST_CONCEPT_ASSERT((boost_concepts::SinglePassIterator<Iterator>));
246  using boost::Convertible;
247  typedef typename boost::iterator_value<Iterator>::type value_type;
248  BOOST_CONCEPT_ASSERT((Convertible<value_type, BamRead>));
249  increment();
250  }
251 
252 
253  template<typename Iterator>
255  {
256  return data_.begin();
257  }
258 
259 
260  template<typename Iterator>
262  {
263  return data_.end();
264  }
265 
266 
267  template<typename Iterator>
269  {
270  if (!data_.empty()) {
271  // in insertion
272  if (skip_ref()) {
273  for (iterator it = data_.begin(); it!=data_.end(); ++it) {
274  if (it->cigar_type() == 1) {
275  it->increment();
276  }
277  --it->skip_;
278  }
279  --skip_ref_;
280  }
281  // walk one base forward on reference
282  else {
283  ++pos_;
284  typename std::list<Entry>::iterator read = data_.begin();
285  while (read != data_.end()) {
286  read->increment();
287  // remove entry if read is entirely left of pos
288  if (read->bam().end() <= pos_) { // FIXME speedup possible
289  data_.erase(read++);
290  continue;
291  }
292  // check if we're stepping into insertion
293  if (read->cigar_op() == BAM_CINS) {
294  skip_ref_ = std::max(skip_ref_, read->cigar_oplen());
295  }
296  ++read;
297  }
298 
299  // stepped into an insertion
300  if (skip_ref_)
301  for (iterator iter=data_.begin(); iter!=data_.end(); ++iter)
302  iter->skip_ = skip_ref_;
303  }
304  }
305 
306 
307  // fast forward to next covered locus
308  if (data_.empty()) {
309  if (bam_==bam_end_)
310  return;
311  tid_ = bam_->core().tid;
312  pos_ = bam_->core().pos;
313  }
314 
315  // read data
316  while (bam_!=bam_end_ && bam_->core().tid==tid_ && bam_->pos()<=pos_) {
317  // skip unmapped reads
318  if (!(bam_->core().flag & BAM_FUNMAP)) {
319  data_.push_back(Entry(*bam_));
320  }
321  ++bam_;
322  }
323  }
324 
325 
326  template<typename Iterator>
327  bool Pileup<Iterator>::skip_ref(void) const
328  {
329  return skip_ref_;
330  }
331 
332 
333  template<typename Iterator>
335  : bam_(new BamRead(b)), qpos_(0), cigar_(bam_->cigar()), skip_(0)
336  {
337  YAT_ASSERT(cigar_.base() == bam_->cigar());
338  if (bam_->core().n_cigar==0)
339  return;
340  // iterate cigar to first match
341  while (qpos_ < bam_->sequence_length() && cigar_type() != 3) {
342  // type is either 0 (hardclipped) or 1 (softclipped)
343  YAT_ASSERT(cigar_type()!=2);
344  if (cigar_type() == 1)
345  ++qpos_;
346  ++cigar_;
347  }
348  }
349 
350 
351  template<typename Iterator>
353  {
354  YAT_ASSERT(cigar_.base() >= bam_->cigar());
355  if (cigar_type() & 1)
356  ++qpos_;
357  ++cigar_;
358  YAT_ASSERT(cigar_.base() >= bam_->cigar());
359  }
360 
361 
362  template<typename Iterator>
364  {
365  if (skip_==0) {
366  if (cigar_type() & 1)
367  return bam_->sequence(qpos_);
368  return 0;
369  }
370  if (cigar_op()!=BAM_CINS)
371  return 0;
372  return bam_->sequence(qpos_);
373  }
374 
375 }}}
376 #endif
std::list< Entry >::const_iterator const_iterator
Definition: Pileup.h:153
void increment(void)
step to next position.
Definition: Pileup.h:268
Class holding a bam query.
Definition: BamRead.h:53
uint8_t cigar_op(void) const
Definition: Pileup.h:90
Pileup< Iterator > make_pileup(Iterator first, Iterator last)
Definition: Pileup.h:233
T max(const T &a, const T &b, const T &c)
Definition: stl_utility.h:697
bool is_del(void) const
Definition: Pileup.h:128
int32_t tid(void) const
Definition: Pileup.h:203
Definition: Pileup.h:57
BASE base(void) const
Definition: CigarIterator.h:119
size_t qpos(void) const
Definition: Pileup.h:136
Definition: Pileup.h:64
bool good(void) const
Definition: Pileup.h:186
Entry(void)
default constructor
Definition: Pileup.h:70
uint32_t cigar_oplen(void) const
Definition: Pileup.h:96
bool skip_ref(void) const
Definition: Pileup.h:327
uint8_t sequence(void) const
Definition: Pileup.h:363
int32_t pos(void) const
Definition: Pileup.h:208
const_iterator begin(void) const
Definition: Pileup.h:254
void increment(void)
Definition: Pileup.h:352
const BamRead & bam(void) const
Definition: Pileup.h:81
const_iterator end(void) const
Definition: Pileup.h:261
unsigned short qual(void) const
Definition: Pileup.h:107
Pileup(void)
Definition: Pileup.h:158

Generated on Tue Sep 26 2017 02:33:29 for yat by  doxygen 1.8.5