source: trunk/yat/omic/BamRead.cc @ 3028

Last change on this file since 3028 was 3028, checked in by Peter, 10 years ago

functions to access, append, and remove aux field. refs #746

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.5 KB
Line 
1// $Id: BamRead.cc 3028 2013-04-21 00:37:31Z peter $
2
3/*
4  Copyright (C) 2012, 2013 Peter Johansson
5
6  This file is part of the yat library, http://dev.thep.lu.se/yat
7
8  The yat library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 3 of the
11  License, or (at your option) any later version.
12
13  The yat library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include <config.h>
23
24#include "BamRead.h"
25#include "config_bam.h"
26
27#include YAT_BAM_HEADER
28
29#include <algorithm>
30#include <cassert>
31#include <sstream>
32
33// bam1_seq_seti is not defined in 0.1.18 (or older), so
34// backport. Code is taken bam.h in version 0.1.19-dev.
35#ifndef bam1_seq_seti
36#define bam1_seq_seti(s, i, c) ( (s)[(i)>>1] = \
37  ((s)[(i)>>1] & 0xf<<(((i)&1)<<2)) | (c)<<((~(i)&1)<<2) )
38#endif
39
40namespace theplu {
41namespace yat {
42namespace omic {
43
44  BamRead::BamRead(void)
45    : bam_(bam_init1())
46  {}
47
48
49  BamRead::BamRead(const BamRead& other)
50    : bam_(bam_dup1(other.bam_))
51  {
52  }
53
54
55  BamRead::~BamRead(void)
56  {
57    bam_destroy1(bam_);
58  }
59
60
61  const BamRead& BamRead::operator=(const BamRead& rhs)
62  {
63    if (bam_!=rhs.bam_)
64      bam_copy1(bam_, rhs.bam_);
65    return *this;
66  }
67
68
69  const uint8_t* BamRead::aux(void) const
70  {
71    assert(bam_);
72    return bam1_aux(bam_);
73  }
74
75
76  const uint8_t* BamRead::aux(const char tag[2]) const
77  {
78    assert(bam_);
79    return bam_aux_get(bam_, tag);
80  }
81
82
83  void BamRead::aux_append(const char tag[2], char type,int len,uint8_t* data)
84  {
85    assert(bam_);
86    bam_aux_append(bam_, tag, type, len, data);
87  }
88
89
90  void BamRead::aux_del(const char tag[2])
91  {
92    assert(bam_);
93    bam_aux_del(bam_, bam_aux_get(bam_, tag));
94  }
95
96
97  int BamRead::aux_size(void) const
98  {
99    assert(bam_);
100    return bam_->l_aux;
101  }
102
103
104  const uint32_t* BamRead::cigar(void) const
105  {
106    return bam1_cigar(bam_);
107  }
108
109
110  uint32_t BamRead::cigar(size_t i) const
111  {
112    assert(i<core().n_cigar);
113    return bam1_cigar(bam_)[i];
114  }
115
116
117  uint32_t BamRead::cigar_op(size_t i) const
118  {
119    assert(i<core().n_cigar);
120    return bam_cigar_op(cigar(i));
121  }
122
123
124  uint32_t BamRead::cigar_oplen(size_t i) const
125  {
126    assert(i<core().n_cigar);
127    return bam_cigar_oplen(cigar(i));
128  }
129
130
131  std::string BamRead::cigar_str(void) const
132  {
133    std::ostringstream os;
134    std::string str = BAM_CIGAR_STR;
135    for (uint32_t i=0; i<core().n_cigar; ++i) {
136      os << bam_cigar_oplen(bam1_cigar(bam_)[i])
137         << str[bam_cigar_op(bam1_cigar(bam_)[i])];
138    }
139    return os.str();
140  }
141
142
143  void BamRead::cigar(const std::vector<uint32_t>& c)
144  {
145    // special case when cigar size is not changed
146    if (c.size() == core().n_cigar) {
147      if (c.size())
148        memcpy(bam1_cigar(bam_), &c[0], 4*c.size());
149      return;
150    }
151
152    int m_data = bam_->m_data;
153    int data_len = bam_->data_len + 4*c.size() - 4*core().n_cigar;
154    // double capacity if needed
155    if (m_data < data_len) {
156      m_data = data_len;
157      kroundup32(m_data);
158    }
159    uint8_t* data = (uint8_t*)calloc(m_data, 1);
160    /*
161      data comes as qname, cigar, rest
162     */
163    // first copy qname
164    memcpy(data, bam_->data, core().l_qname);
165    // copy new cigar
166    if (c.size())
167      // each cigar element is 4 bytes
168      memcpy(data + core().l_qname, &c[0], 4*c.size());
169    // copy remaining data
170    memcpy(data + core().l_qname + 4*c.size(), bam1_seq(bam_),
171           data_len - 4*c.size() - core().l_qname);
172    bam_->m_data = m_data;
173    bam_->data_len = data_len;
174    core().n_cigar = c.size();
175    free(bam_->data);
176    bam_->data = data;
177  }
178
179
180  const bam1_core_t& BamRead::core(void) const
181  { return bam_->core; }
182
183
184  bam1_core_t& BamRead::core(void)
185  { return bam_->core; }
186
187
188  const char* BamRead::name(void) const
189  { return bam1_qname(bam_); }
190
191
192  uint8_t BamRead::qual(size_t i) const
193  { return *(bam1_qual(bam_)+i); }
194
195
196  void BamRead::qual(size_t i, uint8_t q)
197  { *(bam1_qual(bam_)+i)=q; }
198
199
200  std::string BamRead::sequence(void) const
201  {
202    std::string result(sequence_length(), ' ');
203#ifdef HAVE_BAM_NT16_REV_TABLE
204    for (size_t i=0; i<result.size(); ++i)
205      result[i] = bam_nt16_rev_table[sequence(i)];
206#else
207    std::string table = "=ACMGRSVTWYHKDBN";
208    for (size_t i=0; i<result.size(); ++i)
209      result[i] = table[sequence(i)];
210#endif
211    return result;
212  }
213
214
215  void BamRead::sequence(size_t i, uint8_t seq)
216  {
217    assert(bam_);
218    assert(seq < 16);
219    bam1_seq_seti(bam1_seq(bam_), i, seq);
220  }
221
222
223  uint8_t BamRead::sequence(size_t index) const
224  {
225    assert(bam_);
226    return bam1_seqi(bam1_seq(bam_),index);
227  }
228
229
230  uint32_t BamRead::sequence_length(void) const
231  {
232    assert(bam_);
233    return bam_->core.l_qseq;
234  }
235
236
237  int32_t BamRead::pos(void) const
238  {
239    assert(bam_);
240    return bam_->core.pos;
241  }
242
243
244  int32_t BamRead::tid(void) const
245  {
246    assert(bam_);
247    return bam_->core.tid;
248  }
249
250
251  int32_t BamRead::mtid(void) const
252  {
253    assert(bam_);
254    return bam_->core.mtid;
255  }
256
257
258  int32_t BamRead::mpos(void) const
259  {
260    assert(bam_);
261    return bam_->core.mpos;
262  }
263
264
265  int32_t BamRead::end(void) const
266  {
267    assert(bam_);
268    return bam_calend(&core(), bam1_cigar(bam_));
269  }
270
271
272  void BamRead::swap(BamRead& other)
273  {
274    std::swap(bam_, other.bam_);
275  }
276
277
278  void swap(BamRead& lhs, BamRead& rhs)
279  {
280    lhs.swap(rhs);
281  }
282
283  bool same_query_name(const BamRead& lhs, const BamRead& rhs)
284  {
285    if (lhs.core().l_qname != rhs.core().l_qname)
286      return false;
287
288    return std::equal(lhs.name(),
289                      lhs.name() + lhs.core().l_qname,
290                      rhs.name());
291  }
292
293
294  bool soft_clipped(const BamRead& bam)
295  {
296    return left_soft_clipped(bam) || right_soft_clipped(bam);
297  }
298
299
300  uint32_t left_soft_clipped(const BamRead& bam)
301  {
302    for (size_t i=0; i<bam.core().n_cigar; ++i) {
303      if (bam.cigar_op(i) == BAM_CSOFT_CLIP)
304        return bam.cigar_oplen(i);
305      if (bam_cigar_type(bam.cigar_op(i))&1)
306        return 0;
307    }
308    return 0;
309  }
310
311
312  uint32_t right_soft_clipped(const BamRead& bam)
313  {
314    if (bam.core().n_cigar==0)
315      return 0;
316    // right clip can't be at first (most left cigar element)
317    for (size_t i=bam.core().n_cigar-1; i>0; --i) {
318      if (bam.cigar_op(i) == BAM_CSOFT_CLIP)
319        return bam.cigar_oplen(i);
320      if (bam_cigar_type(bam.cigar_op(i))&1)
321        return 0;
322    }
323    return 0;
324  }
325
326
327  bool BamLessPos::operator()(const BamRead& lhs, const BamRead& rhs) const
328  {
329    return lhs.tid() < rhs.tid() ||
330      (lhs.tid() == rhs.tid() && lhs.pos() < rhs.pos());
331  }
332
333
334  bool BamLessEnd::operator()(const BamRead& lhs, const BamRead& rhs) const
335  {
336    return lhs.tid() < rhs.tid() ||
337      (lhs.tid() == rhs.tid() && lhs.end() < rhs.end());
338  }
339
340}}}
Note: See TracBrowser for help on using the repository browser.