Merge branch 'master' into dev

Conflicts:
	main.c
This commit is contained in:
Heng Li 2014-03-17 00:03:52 -04:00
commit 8f9aeef4ec
6 changed files with 48 additions and 25 deletions

View File

@ -1,6 +1,6 @@
CC= gcc CC= gcc
#CC= clang --analyze #CC= clang --analyze
CFLAGS= -g -Wall -O2 CFLAGS= -g -Wall -O2 -Wno-unused-function
WRAP_MALLOC=-DUSE_MALLOC_WRAPPERS WRAP_MALLOC=-DUSE_MALLOC_WRAPPERS
AR= ar AR= ar
DFLAGS= -DHAVE_PTHREAD $(WRAP_MALLOC) DFLAGS= -DHAVE_PTHREAD $(WRAP_MALLOC)

8
bwa.c
View File

@ -106,6 +106,7 @@ uint32_t *bwa_gen_cigar(const int8_t mat[25], int q, int r, int w_, int64_t l_pa
tmp = rseq[i], rseq[i] = rseq[rlen - 1 - i], rseq[rlen - 1 - i] = tmp; tmp = rseq[i], rseq[i] = rseq[rlen - 1 - i], rseq[rlen - 1 - i] = tmp;
} }
if (l_query == re - rb && w_ == 0) { // no gap; no need to do DP if (l_query == re - rb && w_ == 0) { // no gap; no need to do DP
// FIXME: due to an issue in mem_reg2aln(), we never come to this block. This does not affect accuracy, but it hurts performance.
cigar = malloc(4); cigar = malloc(4);
cigar[0] = l_query<<4 | 0; cigar[0] = l_query<<4 | 0;
*n_cigar = 1; *n_cigar = 1;
@ -113,8 +114,6 @@ uint32_t *bwa_gen_cigar(const int8_t mat[25], int q, int r, int w_, int64_t l_pa
*score += mat[rseq[i]*5 + query[i]]; *score += mat[rseq[i]*5 + query[i]];
} else { } else {
int w, max_gap, min_w; int w, max_gap, min_w;
//printf("[Q] "); for (i = 0; i < l_query; ++i) putchar("ACGTN"[(int)query[i]]); putchar('\n');
//printf("[R] "); for (i = 0; i < re - rb; ++i) putchar("ACGTN"[(int)rseq[i]]); putchar('\n');
// set the band-width // set the band-width
max_gap = (int)((double)(((l_query+1)>>1) * mat[0] - q) / r + 1.); max_gap = (int)((double)(((l_query+1)>>1) * mat[0] - q) / r + 1.);
max_gap = max_gap > 1? max_gap : 1; max_gap = max_gap > 1? max_gap : 1;
@ -123,6 +122,11 @@ uint32_t *bwa_gen_cigar(const int8_t mat[25], int q, int r, int w_, int64_t l_pa
min_w = abs(rlen - l_query) + 3; min_w = abs(rlen - l_query) + 3;
w = w > min_w? w : min_w; w = w > min_w? w : min_w;
// NW alignment // NW alignment
if (bwa_verbose >= 4) {
printf("* Global bandwidth: %d\n", w);
printf("* Global ref: "); for (i = 0; i < rlen; ++i) putchar("ACGTN"[(int)rseq[i]]); putchar('\n');
printf("* Global query: "); for (i = 0; i < l_query; ++i) putchar("ACGTN"[(int)query[i]]); putchar('\n');
}
*score = ksw_global(l_query, query, rlen, rseq, 5, mat, q, r, w, n_cigar, &cigar); *score = ksw_global(l_query, query, rlen, rseq, 5, mat, q, r, w, n_cigar, &cigar);
} }
{// compute NM and MD {// compute NM and MD

View File

@ -221,7 +221,7 @@ static void mem_insert_seed(const mem_opt_t *opt, int64_t l_pac, kbtree_t(chn) *
s.rbeg = tmp.pos = bwt_sa(itr->bwt, p->x[0] + k); // this is the base coordinate in the forward-reverse reference s.rbeg = tmp.pos = bwt_sa(itr->bwt, p->x[0] + k); // this is the base coordinate in the forward-reverse reference
s.qbeg = p->info>>32; s.qbeg = p->info>>32;
s.len = slen; s.len = slen;
if (bwa_verbose >= 5) printf("SEED l=%d,qb=%d,rb=%ld\n", s.len, s.qbeg, (long)s.rbeg); if (bwa_verbose >= 5) printf("* Found SEED: length=%d,query_beg=%d,ref_beg=%ld\n", s.len, s.qbeg, (long)s.rbeg);
if (s.rbeg < l_pac && l_pac < s.rbeg + s.len) continue; // bridging forward-reverse boundary; skip if (s.rbeg < l_pac && l_pac < s.rbeg + s.len) continue; // bridging forward-reverse boundary; skip
if (kb_size(tree)) { if (kb_size(tree)) {
kb_intervalp(chn, tree, &tmp, &lower, &upper); // find the closest chain kb_intervalp(chn, tree, &tmp, &lower, &upper); // find the closest chain
@ -263,14 +263,14 @@ void mem_print_chain(const bntseq_t *bns, mem_chain_v *chn)
int i, j; int i, j;
for (i = 0; i < chn->n; ++i) { for (i = 0; i < chn->n; ++i) {
mem_chain_t *p = &chn->a[i]; mem_chain_t *p = &chn->a[i];
err_printf("CHAIN(%d) n=%d w=%d", i, p->n, mem_chain_weight(p)); err_printf("* Found CHAIN(%d): n=%d; weight=%d", i, p->n, mem_chain_weight(p));
for (j = 0; j < p->n; ++j) { for (j = 0; j < p->n; ++j) {
bwtint_t pos; bwtint_t pos;
int is_rev, ref_id; int is_rev, ref_id;
pos = bns_depos(bns, p->seeds[j].rbeg, &is_rev); pos = bns_depos(bns, p->seeds[j].rbeg, &is_rev);
if (is_rev) pos -= p->seeds[j].len - 1; if (is_rev) pos -= p->seeds[j].len - 1;
bns_cnt_ambi(bns, pos, p->seeds[j].len, &ref_id); bns_cnt_ambi(bns, pos, p->seeds[j].len, &ref_id);
err_printf("\t%d,%d,%ld(%s:%c%ld)", p->seeds[j].len, p->seeds[j].qbeg, (long)p->seeds[j].rbeg, bns->anns[ref_id].name, "+-"[is_rev], (long)(pos - bns->anns[ref_id].offset) + 1); err_printf("\t%d;%d,%ld(%s:%c%ld)", p->seeds[j].len, p->seeds[j].qbeg, (long)p->seeds[j].rbeg, bns->anns[ref_id].name, "+-"[is_rev], (long)(pos - bns->anns[ref_id].offset) + 1);
} }
err_putchar('\n'); err_putchar('\n');
} }
@ -531,7 +531,7 @@ int mem_chain2aln_short(const mem_opt_t *opt, int64_t l_pac, const uint8_t *pac,
a.score = x.score; a.score = x.score;
a.csub = x.score2; a.csub = x.score2;
kv_push(mem_alnreg_t, *av, a); kv_push(mem_alnreg_t, *av, a);
if (bwa_verbose >= 4) printf("chain2aln(short): [%d,%d) <=> [%ld,%ld)\n", a.qb, a.qe, (long)a.rb, (long)a.re); if (bwa_verbose >= 4) printf("** Added alignment region via mem_chain2aln_short(): [%d,%d) <=> [%ld,%ld)\n", a.qb, a.qe, (long)a.rb, (long)a.re);
return 0; return 0;
} }
@ -597,7 +597,9 @@ void mem_chain2aln(const mem_opt_t *opt, int64_t l_pac, const uint8_t *pac, int
w = max_gap < opt->w? max_gap : opt->w; w = max_gap < opt->w? max_gap : opt->w;
if (qd - rd < w && rd - qd < w) break; if (qd - rd < w && rd - qd < w) break;
} }
if (i < av->n) { // the seed is (almost) contained in an existing alignment if (i < av->n) { // the seed is (almost) contained in an existing alignment; further testing is needed to confirm it is not leading to a different aln
if (bwa_verbose >= 4)
printf("** Seed(%d) [%ld;%ld,%ld] is almost contained in an existing alignment. Confirming whether extension is needed...\n", k, (long)s->len, (long)s->qbeg, (long)s->rbeg);
for (i = k + 1; i < c->n; ++i) { // check overlapping seeds in the same chain for (i = k + 1; i < c->n; ++i) { // check overlapping seeds in the same chain
const mem_seed_t *t; const mem_seed_t *t;
if (srt[i] == 0) continue; if (srt[i] == 0) continue;
@ -610,6 +612,8 @@ void mem_chain2aln(const mem_opt_t *opt, int64_t l_pac, const uint8_t *pac, int
srt[k] = 0; // mark that seed extension has not been performed srt[k] = 0; // mark that seed extension has not been performed
continue; continue;
} }
if (bwa_verbose >= 4)
printf("** Seed(%d) might lead to a different alignment even though it is contained. Extension will be performed.\n", k);
} }
a = kv_pushp(mem_alnreg_t, *av); a = kv_pushp(mem_alnreg_t, *av);
@ -617,7 +621,7 @@ void mem_chain2aln(const mem_opt_t *opt, int64_t l_pac, const uint8_t *pac, int
a->w = aw[0] = aw[1] = opt->w; a->w = aw[0] = aw[1] = opt->w;
a->score = a->truesc = -1; a->score = a->truesc = -1;
if (bwa_verbose >= 4) err_printf("Extending from seed [%ld,%ld,%ld]\n", (long)s->len, (long)s->qbeg, (long)s->rbeg); if (bwa_verbose >= 4) err_printf("** ---> Extending from seed(%d) [%ld;%ld,%ld] <---\n", k, (long)s->len, (long)s->qbeg, (long)s->rbeg);
if (s->qbeg) { // left extension if (s->qbeg) { // left extension
uint8_t *rs, *qs; uint8_t *rs, *qs;
int qle, tle, gtle, gscore; int qle, tle, gtle, gscore;
@ -629,8 +633,13 @@ void mem_chain2aln(const mem_opt_t *opt, int64_t l_pac, const uint8_t *pac, int
for (i = 0; i < MAX_BAND_TRY; ++i) { for (i = 0; i < MAX_BAND_TRY; ++i) {
int prev = a->score; int prev = a->score;
aw[0] = opt->w << i; aw[0] = opt->w << i;
if (bwa_verbose >= 4) {
int j;
printf("*** Left ref: "); for (j = 0; j < tmp; ++j) putchar("ACGTN"[(int)rs[j]]); putchar('\n');
printf("*** Left query: "); for (j = 0; j < s->qbeg; ++j) putchar("ACGTN"[(int)qs[j]]); putchar('\n');
}
a->score = ksw_extend(s->qbeg, qs, tmp, rs, 5, opt->mat, opt->q, opt->r, aw[0], opt->pen_clip5, opt->zdrop, s->len * opt->a, &qle, &tle, &gtle, &gscore, &max_off[0]); a->score = ksw_extend(s->qbeg, qs, tmp, rs, 5, opt->mat, opt->q, opt->r, aw[0], opt->pen_clip5, opt->zdrop, s->len * opt->a, &qle, &tle, &gtle, &gscore, &max_off[0]);
if (bwa_verbose >= 4) { printf("L\t%d < %d; w=%d; max_off=%d\n", prev, a->score, aw[0], max_off[0]); fflush(stdout); } if (bwa_verbose >= 4) { printf("*** Left extension: prev_score=%d; score=%d; bandwidth=%d; max_off_diagonal_dist=%d\n", prev, a->score, aw[0], max_off[0]); fflush(stdout); }
if (a->score == prev || max_off[0] < (aw[0]>>1) + (aw[0]>>2)) break; if (a->score == prev || max_off[0] < (aw[0]>>1) + (aw[0]>>2)) break;
} }
// check whether we prefer to reach the end of the query // check whether we prefer to reach the end of the query
@ -652,8 +661,13 @@ void mem_chain2aln(const mem_opt_t *opt, int64_t l_pac, const uint8_t *pac, int
for (i = 0; i < MAX_BAND_TRY; ++i) { for (i = 0; i < MAX_BAND_TRY; ++i) {
int prev = a->score; int prev = a->score;
aw[1] = opt->w << i; aw[1] = opt->w << i;
if (bwa_verbose >= 4) {
int j;
printf("*** Right ref: "); for (j = 0; j < rmax[1] - rmax[0] - re; ++j) putchar("ACGTN"[(int)rseq[re+j]]); putchar('\n');
printf("*** Right query: "); for (j = 0; j < l_query - qe; ++j) putchar("ACGTN"[(int)query[qe+j]]); putchar('\n');
}
a->score = ksw_extend(l_query - qe, query + qe, rmax[1] - rmax[0] - re, rseq + re, 5, opt->mat, opt->q, opt->r, aw[1], opt->pen_clip3, opt->zdrop, sc0, &qle, &tle, &gtle, &gscore, &max_off[1]); a->score = ksw_extend(l_query - qe, query + qe, rmax[1] - rmax[0] - re, rseq + re, 5, opt->mat, opt->q, opt->r, aw[1], opt->pen_clip3, opt->zdrop, sc0, &qle, &tle, &gtle, &gscore, &max_off[1]);
if (bwa_verbose >= 4) { printf("R\t%d < %d; w=%d; max_off=%d\n", prev, a->score, aw[1], max_off[1]); fflush(stdout); } if (bwa_verbose >= 4) { printf("*** Right extension: prev_score=%d; score=%d; bandwidth=%d; max_off_diagonal_dist=%d\n", prev, a->score, aw[1], max_off[1]); fflush(stdout); }
if (a->score == prev || max_off[1] < (aw[1]>>1) + (aw[1]>>2)) break; if (a->score == prev || max_off[1] < (aw[1]>>1) + (aw[1]>>2)) break;
} }
// similar to the above // similar to the above
@ -665,7 +679,7 @@ void mem_chain2aln(const mem_opt_t *opt, int64_t l_pac, const uint8_t *pac, int
a->truesc += gscore - sc0; a->truesc += gscore - sc0;
} }
} else a->qe = l_query, a->re = s->rbeg + s->len; } else a->qe = l_query, a->re = s->rbeg + s->len;
if (bwa_verbose >= 4) { printf("[%d]\taw={%d,%d}\tscore=%d\t[%d,%d) <=> [%ld,%ld)\n", k, aw[0], aw[1], a->score, a->qb, a->qe, (long)a->rb, (long)a->re); fflush(stdout); } if (bwa_verbose >= 4) printf("*** Added alignment region: [%d,%d) <=> [%ld,%ld); score=%d; {left,right}_bandwidth={%d,%d}\n", a->qb, a->qe, (long)a->rb, (long)a->re, a->score, aw[0], aw[1]);
// compute seedcov // compute seedcov
for (i = 0, a->seedcov = 0; i < c->n; ++i) { for (i = 0, a->seedcov = 0; i < c->n; ++i) {
@ -686,7 +700,7 @@ static inline int infer_bw(int l1, int l2, int score, int a, int q, int r)
{ {
int w; int w;
if (l1 == l2 && l1 * a - score < (q + r - a)<<1) return 0; // to get equal alignment length, we need at least two gaps if (l1 == l2 && l1 * a - score < (q + r - a)<<1) return 0; // to get equal alignment length, we need at least two gaps
w = ((double)((l1 < l2? l1 : l2) * a - score - q) / r + 1.); w = ((double)((l1 < l2? l1 : l2) * a - score - q) / r + 2.);
if (w < abs(l1 - l2)) w = abs(l1 - l2); if (w < abs(l1 - l2)) w = abs(l1 - l2);
return w; return w;
} }
@ -900,7 +914,7 @@ mem_alnreg_v mem_align1_core(const mem_opt_t *opt, const bwt_t *bwt, const bntse
for (i = 0; i < chn.n; ++i) { for (i = 0; i < chn.n; ++i) {
mem_chain_t *p = &chn.a[i]; mem_chain_t *p = &chn.a[i];
int ret; int ret;
if (bwa_verbose >= 4) err_printf("===> Processing chain(%d) <===\n", i); if (bwa_verbose >= 4) err_printf("* ---> Processing chain(%d) <---\n", i);
ret = mem_chain2aln_short(opt, bns->l_pac, pac, l_seq, (uint8_t*)seq, p, &regs); ret = mem_chain2aln_short(opt, bns->l_pac, pac, l_seq, (uint8_t*)seq, p, &regs);
if (ret > 0) mem_chain2aln(opt, bns->l_pac, pac, l_seq, (uint8_t*)seq, p, &regs); if (ret > 0) mem_chain2aln(opt, bns->l_pac, pac, l_seq, (uint8_t*)seq, p, &regs);
free(chn.a[i].seeds); free(chn.a[i].seeds);
@ -949,14 +963,14 @@ mem_aln_t mem_reg2aln(const mem_opt_t *opt, const bntseq_t *bns, const uint8_t *
exit(1); exit(1);
} }
w2 = infer_bw(qe - qb, re - rb, ar->truesc, opt->a, opt->q, opt->r); w2 = infer_bw(qe - qb, re - rb, ar->truesc, opt->a, opt->q, opt->r);
if (bwa_verbose >= 4) printf("Band width: infer=%d, opt=%d, alnreg=%d\n", w2, opt->w, ar->w); if (bwa_verbose >= 4) printf("* Band width: inferred=%d, cmd_opt=%d, alnreg=%d\n", w2, opt->w, ar->w);
if (w2 > opt->w) w2 = w2 < ar->w? w2 : ar->w; if (w2 > opt->w) w2 = w2 < ar->w? w2 : ar->w;
else w2 = opt->w; // else w2 = opt->w; // TODO: check if we need this line on long reads. On 1-800bp reads, it does not matter and it should be.
i = 0; a.cigar = 0; i = 0; a.cigar = 0;
do { do {
free(a.cigar); free(a.cigar);
a.cigar = bwa_gen_cigar(opt->mat, opt->q, opt->r, w2, bns->l_pac, pac, qe - qb, (uint8_t*)&query[qb], rb, re, &score, &a.n_cigar, &NM); a.cigar = bwa_gen_cigar(opt->mat, opt->q, opt->r, w2, bns->l_pac, pac, qe - qb, (uint8_t*)&query[qb], rb, re, &score, &a.n_cigar, &NM);
if (bwa_verbose >= 4) printf("Final alignment: w2=%d, global_sc=%d, local_sc=%d\n", w2, score, ar->truesc); if (bwa_verbose >= 4) printf("* Final alignment: w2=%d, global_sc=%d, local_sc=%d\n", w2, score, ar->truesc);
if (score == last_sc) break; // it is possible that global alignment and local alignment give different scores if (score == last_sc) break; // it is possible that global alignment and local alignment give different scores
last_sc = score; last_sc = score;
w2 <<= 1; w2 <<= 1;
@ -1012,9 +1026,12 @@ static void worker1(void *data, int i, int tid)
{ {
worker_t *w = (worker_t*)data; worker_t *w = (worker_t*)data;
if (!(w->opt->flag&MEM_F_PE)) { if (!(w->opt->flag&MEM_F_PE)) {
if (bwa_verbose >= 4) printf("=====> Processing read '%s' <=====\n", w->seqs[i].name);
w->regs[i] = mem_align1_core(w->opt, w->bwt, w->bns, w->pac, w->seqs[i].l_seq, w->seqs[i].seq); w->regs[i] = mem_align1_core(w->opt, w->bwt, w->bns, w->pac, w->seqs[i].l_seq, w->seqs[i].seq);
} else { } else {
if (bwa_verbose >= 4) printf("=====> Processing read '%s'/1 <=====\n", w->seqs[i<<1|0].name);
w->regs[i<<1|0] = mem_align1_core(w->opt, w->bwt, w->bns, w->pac, w->seqs[i<<1|0].l_seq, w->seqs[i<<1|0].seq); w->regs[i<<1|0] = mem_align1_core(w->opt, w->bwt, w->bns, w->pac, w->seqs[i<<1|0].l_seq, w->seqs[i<<1|0].seq);
if (bwa_verbose >= 4) printf("=====> Processing read '%s'/2 <=====\n", w->seqs[i<<1|1].name);
w->regs[i<<1|1] = mem_align1_core(w->opt, w->bwt, w->bns, w->pac, w->seqs[i<<1|1].l_seq, w->seqs[i<<1|1].seq); w->regs[i<<1|1] = mem_align1_core(w->opt, w->bwt, w->bns, w->pac, w->seqs[i<<1|1].l_seq, w->seqs[i<<1|1].seq);
} }
} }
@ -1024,10 +1041,12 @@ static void worker2(void *data, int i, int tid)
extern int mem_sam_pe(const mem_opt_t *opt, const bntseq_t *bns, const uint8_t *pac, const mem_pestat_t pes[4], uint64_t id, bseq1_t s[2], mem_alnreg_v a[2]); extern int mem_sam_pe(const mem_opt_t *opt, const bntseq_t *bns, const uint8_t *pac, const mem_pestat_t pes[4], uint64_t id, bseq1_t s[2], mem_alnreg_v a[2]);
worker_t *w = (worker_t*)data; worker_t *w = (worker_t*)data;
if (!(w->opt->flag&MEM_F_PE)) { if (!(w->opt->flag&MEM_F_PE)) {
if (bwa_verbose >= 4) printf("=====> Finalizing read '%s' <=====\n", w->seqs[i].name);
mem_mark_primary_se(w->opt, w->regs[i].n, w->regs[i].a, w->n_processed + i); mem_mark_primary_se(w->opt, w->regs[i].n, w->regs[i].a, w->n_processed + i);
mem_reg2sam_se(w->opt, w->bns, w->pac, &w->seqs[i], &w->regs[i], 0, 0); mem_reg2sam_se(w->opt, w->bns, w->pac, &w->seqs[i], &w->regs[i], 0, 0);
free(w->regs[i].a); free(w->regs[i].a);
} else { } else {
if (bwa_verbose >= 4) printf("=====> Finalizing read pair '%s' <=====\n", w->seqs[i<<1|0].name);
mem_sam_pe(w->opt, w->bns, w->pac, w->pes, (w->n_processed>>1) + i, &w->seqs[i<<1], &w->regs[i<<1]); mem_sam_pe(w->opt, w->bns, w->pac, w->pes, (w->n_processed>>1) + i, &w->seqs[i<<1], &w->regs[i<<1]);
free(w->regs[i<<1|0].a); free(w->regs[i<<1|1].a); free(w->regs[i<<1|0].a); free(w->regs[i<<1|1].a);
} }

8
bwt.h
View File

@ -96,14 +96,14 @@ extern "C" {
void bwt_bwtupdate_core(bwt_t *bwt); void bwt_bwtupdate_core(bwt_t *bwt);
inline bwtint_t bwt_occ(const bwt_t *bwt, bwtint_t k, ubyte_t c); bwtint_t bwt_occ(const bwt_t *bwt, bwtint_t k, ubyte_t c);
inline void bwt_occ4(const bwt_t *bwt, bwtint_t k, bwtint_t cnt[4]); void bwt_occ4(const bwt_t *bwt, bwtint_t k, bwtint_t cnt[4]);
bwtint_t bwt_sa(const bwt_t *bwt, bwtint_t k); bwtint_t bwt_sa(const bwt_t *bwt, bwtint_t k);
// more efficient version of bwt_occ/bwt_occ4 for retrieving two close Occ values // more efficient version of bwt_occ/bwt_occ4 for retrieving two close Occ values
void bwt_gen_cnt_table(bwt_t *bwt); void bwt_gen_cnt_table(bwt_t *bwt);
inline void bwt_2occ(const bwt_t *bwt, bwtint_t k, bwtint_t l, ubyte_t c, bwtint_t *ok, bwtint_t *ol); void bwt_2occ(const bwt_t *bwt, bwtint_t k, bwtint_t l, ubyte_t c, bwtint_t *ok, bwtint_t *ol);
inline void bwt_2occ4(const bwt_t *bwt, bwtint_t k, bwtint_t l, bwtint_t cntk[4], bwtint_t cntl[4]); void bwt_2occ4(const bwt_t *bwt, bwtint_t k, bwtint_t l, bwtint_t cntk[4], bwtint_t cntl[4]);
int bwt_match_exact(const bwt_t *bwt, int len, const ubyte_t *str, bwtint_t *sa_begin, bwtint_t *sa_end); int bwt_match_exact(const bwt_t *bwt, int len, const ubyte_t *str, bwtint_t *sa_begin, bwtint_t *sa_end);
int bwt_match_exact_alt(const bwt_t *bwt, int len, const ubyte_t *str, bwtint_t *k0, bwtint_t *l0); int bwt_match_exact_alt(const bwt_t *bwt, int len, const ubyte_t *str, bwtint_t *k0, bwtint_t *l0);

View File

@ -56,7 +56,7 @@ bwtl_t *bwtl_seq2bwtl(int len, const uint8_t *seq)
} }
return b; return b;
} }
inline uint32_t bwtl_occ(const bwtl_t *bwt, uint32_t k, uint8_t c) uint32_t bwtl_occ(const bwtl_t *bwt, uint32_t k, uint8_t c)
{ {
uint32_t n, b; uint32_t n, b;
if (k == bwt->seq_len) return bwt->L2[c+1] - bwt->L2[c]; if (k == bwt->seq_len) return bwt->L2[c+1] - bwt->L2[c];

View File

@ -17,9 +17,9 @@ extern "C" {
#endif #endif
bwtl_t *bwtl_seq2bwtl(int len, const uint8_t *seq); bwtl_t *bwtl_seq2bwtl(int len, const uint8_t *seq);
inline uint32_t bwtl_occ(const bwtl_t *bwt, uint32_t k, uint8_t c); uint32_t bwtl_occ(const bwtl_t *bwt, uint32_t k, uint8_t c);
inline void bwtl_occ4(const bwtl_t *bwt, uint32_t k, uint32_t cnt[4]); void bwtl_occ4(const bwtl_t *bwt, uint32_t k, uint32_t cnt[4]);
inline void bwtl_2occ4(const bwtl_t *bwt, uint32_t k, uint32_t l, uint32_t cntk[4], uint32_t cntl[4]); void bwtl_2occ4(const bwtl_t *bwt, uint32_t k, uint32_t l, uint32_t cntk[4], uint32_t cntl[4]);
void bwtl_destroy(bwtl_t *bwt); void bwtl_destroy(bwtl_t *bwt);
#ifdef __cplusplus #ifdef __cplusplus