minibwa 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +119 -0
  4. data/ext/minibwa/extconf.rb +105 -0
  5. data/ext/minibwa/mb_buffer.c +113 -0
  6. data/ext/minibwa/mb_hit.c +192 -0
  7. data/ext/minibwa/mb_index.c +462 -0
  8. data/ext/minibwa/mb_index_build.c +174 -0
  9. data/ext/minibwa/mb_options.c +301 -0
  10. data/ext/minibwa/minibwa/LICENSE.txt +37 -0
  11. data/ext/minibwa/minibwa/align.c +930 -0
  12. data/ext/minibwa/minibwa/bseq.h +45 -0
  13. data/ext/minibwa/minibwa/bwt.c +715 -0
  14. data/ext/minibwa/minibwa/bwt.h +86 -0
  15. data/ext/minibwa/minibwa/cs.c +161 -0
  16. data/ext/minibwa/minibwa/format.c +356 -0
  17. data/ext/minibwa/minibwa/index.c +342 -0
  18. data/ext/minibwa/minibwa/kalloc.c +224 -0
  19. data/ext/minibwa/minibwa/kalloc.h +54 -0
  20. data/ext/minibwa/minibwa/ketopt.h +123 -0
  21. data/ext/minibwa/minibwa/kommon.c +374 -0
  22. data/ext/minibwa/minibwa/kommon.h +85 -0
  23. data/ext/minibwa/minibwa/kseq.h +256 -0
  24. data/ext/minibwa/minibwa/ksort.h +163 -0
  25. data/ext/minibwa/minibwa/ksw2.h +220 -0
  26. data/ext/minibwa/minibwa/ksw2_extd2_sse.c +403 -0
  27. data/ext/minibwa/minibwa/ksw2_extz2_sse.c +296 -0
  28. data/ext/minibwa/minibwa/ksw2_ll_sse.c +341 -0
  29. data/ext/minibwa/minibwa/kthread.h +15 -0
  30. data/ext/minibwa/minibwa/l2bit.c +479 -0
  31. data/ext/minibwa/minibwa/l2bit.h +72 -0
  32. data/ext/minibwa/minibwa/lchain.c +231 -0
  33. data/ext/minibwa/minibwa/libsais.c +6985 -0
  34. data/ext/minibwa/minibwa/libsais.h +106 -0
  35. data/ext/minibwa/minibwa/libsais64.c +7064 -0
  36. data/ext/minibwa/minibwa/libsais64.h +81 -0
  37. data/ext/minibwa/minibwa/map-algo.c +769 -0
  38. data/ext/minibwa/minibwa/mbpriv.h +148 -0
  39. data/ext/minibwa/minibwa/minibwa.h +176 -0
  40. data/ext/minibwa/minibwa/options.c +116 -0
  41. data/ext/minibwa/minibwa/pe.c +559 -0
  42. data/ext/minibwa/minibwa/s2n-lite.h +59 -0
  43. data/ext/minibwa/minibwa/seed.c +354 -0
  44. data/ext/minibwa/minibwa.c +67 -0
  45. data/ext/minibwa/minibwa.h +51 -0
  46. data/lib/minibwa/hit.rb +110 -0
  47. data/lib/minibwa/index.rb +77 -0
  48. data/lib/minibwa/options.rb +235 -0
  49. data/lib/minibwa/sam.rb +85 -0
  50. data/lib/minibwa/version.rb +6 -0
  51. data/lib/minibwa.rb +11 -0
  52. metadata +88 -0
@@ -0,0 +1,86 @@
1
+ #ifndef MB_BWT_H
2
+ #define MB_BWT_H
3
+
4
+ #include <stdint.h>
5
+ #include <stddef.h>
6
+
7
+ #define MB_MAGIC "MBW\2"
8
+
9
+ typedef struct {
10
+ uint64_t x[2];
11
+ uint64_t size, info;
12
+ } mb_sai_t;
13
+
14
+ typedef struct {
15
+ uint64_t primary; // S^{-1}(0), or the primary index of BWT
16
+ uint64_t L2[5]; // C(), cumulative count
17
+ uint64_t seq_len; // sequence length
18
+ uint64_t data_len;
19
+ uint64_t *data; // BWT
20
+ uint32_t cnt_table[256];
21
+ uint32_t pre_len;
22
+ mb_sai_t *pre;
23
+ // suffix array
24
+ uint32_t sa_bit; // sample rate: 1/(1<<sa_bit)
25
+ uint64_t n_sa;
26
+ uint64_t *sa;
27
+ // mmap
28
+ void *mmap; // mmap pointer
29
+ size_t mmap_len; // mmap length (for munmap)
30
+ } mb_bwt_t;
31
+
32
+ typedef struct { size_t n, m; mb_sai_t *a; } mb_sai_v;
33
+
34
+ typedef struct {
35
+ // input before calling
36
+ int32_t min_len, min_occ;
37
+ int32_t st, en;
38
+ const uint8_t *q;
39
+ mb_sai_v *v; // output; v->n is not set to 0
40
+ // internal state
41
+ int32_t stage;
42
+ int32_t x, i;
43
+ uint32_t kmer; // for k-mer cache
44
+ mb_sai_t p;
45
+ } mb_smem_entry_t;
46
+
47
+ #ifdef __cplusplus
48
+ extern "C" {
49
+ #endif
50
+
51
+ extern int mb_verbose;
52
+
53
+ mb_bwt_t *mb_bwt_init(void);
54
+ void mb_bwt_destroy(mb_bwt_t *bwt);
55
+ mb_bwt_t *mb_bwt_load_raw(const char *fn); // from raw bwt_gen.c output
56
+ int mb_bwt_save(const char *fn, const mb_bwt_t *bwt);
57
+ mb_bwt_t *mb_bwt_load(const char *fn);
58
+ mb_bwt_t *mb_bwt_load_mmap(const char *fn, int preload);
59
+ mb_bwt_t *mb_bwt_init_from_raw(int is_byte, const void *raw_, uint64_t len, uint64_t primary);
60
+
61
+ void mb_bwt_cache(mb_bwt_t *bwt, int32_t len);
62
+ uint64_t mb_bwt_rank11(const mb_bwt_t *bwt, uint64_t k, uint8_t c);
63
+ void mb_bwt_rank1a(const mb_bwt_t *bwt, uint64_t k, uint64_t cnt[4]);
64
+ void mb_bwt_rank2a(const mb_bwt_t *bwt, uint64_t k, uint64_t l, uint64_t cntk[4], uint64_t cntl[4]);
65
+
66
+ void mb_bwt_extend(const mb_bwt_t *bwt, const mb_sai_t *ik, mb_sai_t ok[4], int is_back);
67
+ void mb_bwt_count_kmer(const mb_bwt_t *bwt, int32_t depth, mb_sai_t *a);
68
+ int64_t mb_bwt_smem(const mb_bwt_t *f, uint32_t len, const uint8_t *q, int64_t x, int64_t min_len, int64_t min_occ, mb_sai_t *p);
69
+ void mb_bwt_smem_batch(void *km, const mb_bwt_t *bwt, int32_t n, mb_smem_entry_t *a);
70
+
71
+ void mb_bwt_gen_sa(mb_bwt_t *bwt, uint32_t sa_bit);
72
+ uint64_t mb_bwt_sa(const mb_bwt_t *bwt, uint64_t k);
73
+ void mb_bwt_sa_batch(void *km, const mb_bwt_t *bwt, int64_t n, uint64_t *x);
74
+
75
+ static inline void mb_bwt_set_intv(const mb_bwt_t *bwt, int c, mb_sai_t *ik)
76
+ {
77
+ ik->x[0] = bwt->L2[c] + 1; // +1 for the missing sentinel
78
+ ik->x[1] = bwt->L2[3-c] + 1;
79
+ ik->size = bwt->L2[c+1] - bwt->L2[c];
80
+ ik->info = 0;
81
+ }
82
+ #ifdef __cplusplus
83
+ }
84
+ #endif
85
+
86
+ #endif
@@ -0,0 +1,161 @@
1
+ #include <assert.h>
2
+ #include <stdio.h>
3
+ #include "mbpriv.h"
4
+ #include "kalloc.h"
5
+ #include "kommon.h"
6
+
7
+ static char *alloc_tmp(void *km, const mb_hit_t *r)
8
+ {
9
+ int32_t i, min_tmp_len = 31;
10
+ for (i = 0; i < (int)r->p->n_cigar; ++i) {
11
+ int op = r->p->cigar[i]&0xf, len = r->p->cigar[i]>>4;
12
+ if (op == MB_CIGAR_INS || op == MB_CIGAR_DEL)
13
+ min_tmp_len = min_tmp_len > len + 5? min_tmp_len : len + 5;
14
+ }
15
+ return Kmalloc(km, char, min_tmp_len + 1);
16
+ }
17
+
18
+ static void write_indel_ds(void *km, kstring_t *str, int64_t len, const uint8_t *seq, int64_t ll, int64_t lr) // write an indel to ds; adapted from minigraph
19
+ {
20
+ int64_t i;
21
+ if (ll + lr >= len) {
22
+ km_sprintf_lite(km, str, "[");
23
+ for (i = 0; i < len; ++i)
24
+ km_sprintf_lite(km, str, "%c", "acgtn"[seq[i]]);
25
+ km_sprintf_lite(km, str, "]");
26
+ } else {
27
+ int64_t k = 0;
28
+ if (ll > 0) {
29
+ km_sprintf_lite(km, str, "[");
30
+ for (i = 0; i < ll; ++i)
31
+ km_sprintf_lite(km, str, "%c", "acgtn"[seq[k+i]]);
32
+ km_sprintf_lite(km, str, "]");
33
+ k += ll;
34
+ }
35
+ for (i = 0; i < len - lr - ll; ++i)
36
+ km_sprintf_lite(km, str, "%c", "acgtn"[seq[k+i]]);
37
+ k += len - lr - ll;
38
+ if (lr > 0) {
39
+ km_sprintf_lite(km, str, "[");
40
+ for (i = 0; i < lr; ++i)
41
+ km_sprintf_lite(km, str, "%c", "acgtn"[seq[k+i]]);
42
+ km_sprintf_lite(km, str, "]");
43
+ }
44
+ }
45
+ }
46
+
47
+ void mb_write_cs_ds(void *km, kstring_t *s, const uint8_t *tseq, const uint8_t *qseq, const mb_hit_t *r, int is_ds)
48
+ {
49
+ int i, q_off, t_off, q_len = 0, t_len = 0;
50
+ char *tmp;
51
+ km_sprintf_lite(km, s, "%cs:Z:", is_ds? 'd' : 'c');
52
+ for (i = 0; i < (int)r->p->n_cigar; ++i) {
53
+ int op = r->p->cigar[i]&0xf, len = r->p->cigar[i]>>4;
54
+ if (op == MB_CIGAR_MATCH || op == MB_CIGAR_EQ_MATCH || op == MB_CIGAR_X_MISMATCH) {
55
+ q_len += len, t_len += len;
56
+ } else if (op == MB_CIGAR_INS) {
57
+ q_len += len;
58
+ } else if (op == MB_CIGAR_DEL || op == MB_CIGAR_N_SKIP) {
59
+ t_len += len;
60
+ }
61
+ }
62
+ tmp = alloc_tmp(km, r);
63
+ for (i = q_off = t_off = 0; i < (int)r->p->n_cigar; ++i) {
64
+ int j, op = r->p->cigar[i]&0xf, len = r->p->cigar[i]>>4;
65
+ assert((op >= MB_CIGAR_MATCH && op <= MB_CIGAR_N_SKIP) || op == MB_CIGAR_EQ_MATCH || op == MB_CIGAR_X_MISMATCH);
66
+ if (op == MB_CIGAR_MATCH || op == MB_CIGAR_EQ_MATCH || op == MB_CIGAR_X_MISMATCH) {
67
+ int l_tmp = 0;
68
+ for (j = 0; j < len; ++j) {
69
+ if (qseq[q_off + j] != tseq[t_off + j]) {
70
+ if (l_tmp > 0) {
71
+ km_sprintf_lite(km, s, ":%d", l_tmp);
72
+ l_tmp = 0;
73
+ }
74
+ km_sprintf_lite(km, s, "*%c%c", "acgtn"[tseq[t_off + j]], "acgtn"[qseq[q_off + j]]);
75
+ } else ++l_tmp;
76
+ }
77
+ if (l_tmp > 0)
78
+ km_sprintf_lite(km, s, ":%d", l_tmp);
79
+ q_off += len, t_off += len;
80
+ } else if (op == MB_CIGAR_INS) {
81
+ if (is_ds) {
82
+ int z, ll, lr, y = q_off;
83
+ for (z = 1; z <= len; ++z)
84
+ if (y - z < 0 || qseq[y + len - z] != qseq[y - z])
85
+ break;
86
+ lr = z - 1;
87
+ for (z = 0; z < len; ++z)
88
+ if (y + len + z >= q_len || qseq[y + len + z] != qseq[y + z])
89
+ break;
90
+ ll = z;
91
+ km_sprintf_lite(km, s, "+");
92
+ write_indel_ds(km, s, len, &qseq[y], ll, lr);
93
+ } else {
94
+ for (j = 0, tmp[len] = 0; j < len; ++j)
95
+ tmp[j] = "acgtn"[qseq[q_off + j]];
96
+ km_sprintf_lite(km, s, "+%s", tmp);
97
+ }
98
+ q_off += len;
99
+ } else if (op == MB_CIGAR_DEL) {
100
+ if (is_ds) {
101
+ int z, ll, lr, x = t_off;
102
+ for (z = 1; z <= len; ++z)
103
+ if (x - z < 0 || tseq[x + len - z] != tseq[x - z])
104
+ break;
105
+ lr = z - 1;
106
+ for (z = 0; z < len; ++z)
107
+ if (x + len + z >= t_len || tseq[x + z] != tseq[x + len + z])
108
+ break;
109
+ ll = z;
110
+ km_sprintf_lite(km, s, "-");
111
+ write_indel_ds(km, s, len, &tseq[x], ll, lr);
112
+ } else {
113
+ for (j = 0, tmp[len] = 0; j < len; ++j)
114
+ tmp[j] = "acgtn"[tseq[t_off + j]];
115
+ km_sprintf_lite(km, s, "-%s", tmp);
116
+ }
117
+ t_off += len;
118
+ } else { // intron
119
+ assert(len >= 2);
120
+ km_sprintf_lite(km, s, "~%c%c%d%c%c", "acgtn"[tseq[t_off]], "acgtn"[tseq[t_off+1]],
121
+ len, "acgtn"[tseq[t_off+len-2]], "acgtn"[tseq[t_off+len-1]]);
122
+ t_off += len;
123
+ }
124
+ }
125
+ kfree(km, tmp);
126
+ assert(t_off == r->te - r->ts && q_off == r->qe - r->qs);
127
+ }
128
+
129
+ void mb_write_MD(void *km, kstring_t *s, const uint8_t *tseq, const uint8_t *qseq, const mb_hit_t *r)
130
+ {
131
+ int i, q_off, t_off, l_MD = 0;
132
+ char *tmp;
133
+ km_sprintf_lite(km, s, "MD:Z:");
134
+ tmp = alloc_tmp(km, r);
135
+ for (i = q_off = t_off = 0; i < (int)r->p->n_cigar; ++i) {
136
+ int j, op = r->p->cigar[i]&0xf, len = r->p->cigar[i]>>4;
137
+ assert((op >= MB_CIGAR_MATCH && op <= MB_CIGAR_N_SKIP) || op == MB_CIGAR_EQ_MATCH || op == MB_CIGAR_X_MISMATCH);
138
+ if (op == MB_CIGAR_MATCH || op == MB_CIGAR_EQ_MATCH || op == MB_CIGAR_X_MISMATCH) {
139
+ for (j = 0; j < len; ++j) {
140
+ if (qseq[q_off + j] != tseq[t_off + j]) {
141
+ km_sprintf_lite(km, s, "%d%c", l_MD, "ACGTN"[tseq[t_off + j]]);
142
+ l_MD = 0;
143
+ } else ++l_MD;
144
+ }
145
+ q_off += len, t_off += len;
146
+ } else if (op == MB_CIGAR_INS) {
147
+ q_off += len;
148
+ } else if (op == MB_CIGAR_DEL) {
149
+ for (j = 0, tmp[len] = 0; j < len; ++j)
150
+ tmp[j] = "ACGTN"[tseq[t_off + j]];
151
+ km_sprintf_lite(km, s, "%d^%s", l_MD, tmp);
152
+ l_MD = 0;
153
+ t_off += len;
154
+ } else if (op == MB_CIGAR_N_SKIP) {
155
+ t_off += len;
156
+ }
157
+ }
158
+ if (l_MD > 0) km_sprintf_lite(km, s, "%d", l_MD);
159
+ kfree(km, tmp);
160
+ assert(t_off == r->te - r->ts && q_off == r->qe - r->qs);
161
+ }
@@ -0,0 +1,356 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <assert.h>
4
+ #include "mbpriv.h"
5
+ #include "kommon.h"
6
+
7
+ static char mb_rg_id[256];
8
+
9
+ /**************
10
+ * PAF output *
11
+ **************/
12
+
13
+ static inline void write_tags(kstring_t *s, const mb_hit_t *p)
14
+ {
15
+ int32_t nm = p->blen - p->mlen + p->p->n_ambi;
16
+ kom_sprintf_lite(s, "\tNM:i:%d\tAS:i:%d\tms:i:%d\tmd:i:%d", nm, p->p->dp_score, p->p->dp_max0, p->p->dp_max - p->p->dp_max2);
17
+ }
18
+
19
+ void mb_fmt_paf(kstring_t *s, const l2b_t *l2b, const mb_bseq1_t *t, const mb_hit_t *p, uint64_t opt_flag, int n_seg, int seg_idx)
20
+ {
21
+ kom_sprintf_lite(s, "%s", t->name);
22
+ if (n_seg > 1 && seg_idx >= 0)
23
+ kom_sprintf_lite(s, "/%d", seg_idx + 1);
24
+ kom_sprintf_lite(s, "\t%ld", (long)t->l_seq);
25
+ if (p == 0) { // for unmapped reads
26
+ kom_sprintf_lite(s, "\t*\t*\t*\t*\t*\t*\t*\t0\t0\t0\n");
27
+ return;
28
+ }
29
+ kom_sprintf_lite(s, "\t%d\t%d\t%c\t%s\t%ld\t%ld\t%ld\t%d\t%d\t%d\ttp:A:%c\ts1:i:%d\tcm:i:%d",
30
+ p->qs, p->qe, p->rev? '-' : '+', l2b->ctg[p->tid].name, (long)l2b->ctg[p->tid].len, (long)p->ts, (long)p->te,
31
+ p->mlen, p->blen, p->mapq, p->parent == p->id? 'P' : 'S', p->score, p->cnt);
32
+ if (p->parent == p->id) kom_sprintf_lite(s, "\ts2:i:%d", p->subsc >= 0? p->subsc : 0);
33
+ if (p->p) {
34
+ write_tags(s, p);
35
+ if (p->p->n_cigar > 0) {
36
+ int32_t i;
37
+ kom_sprintf_lite(s, "\tcg:Z:");
38
+ for (i = 0; i < p->p->n_cigar; ++i)
39
+ kom_sprintf_lite(s, "%d%c", p->p->cigar[i]>>4, MB_CIGAR_STR[p->p->cigar[i]&0xf]);
40
+ }
41
+ if (p->p->cs) kom_sprintf_lite(s, "\t%s", (char*)&p->p->cigar[p->p->n_cigar]);
42
+ }
43
+ if ((opt_flag & MB_F_COPY_COMMENT) && t->comment)
44
+ kom_sprintf_lite(s, "\t%s", t->comment);
45
+ kom_sprintf_lite(s, "\n");
46
+ }
47
+
48
+ /**************
49
+ * SAM header *
50
+ **************/
51
+
52
+ char *mb_escape(char *s)
53
+ {
54
+ char *p, *q;
55
+ for (p = q = s; *p; ++p) {
56
+ if (*p == '\\') {
57
+ ++p;
58
+ if (*p == 't') *q++ = '\t';
59
+ else if (*p == 'n') *q++ = '\n';
60
+ else if (*p == 'r') *q++ = '\r';
61
+ else if (*p == '\\') *q++ = '\\';
62
+ else if (*p == '\0') break;
63
+ } else *q++ = *p;
64
+ }
65
+ *q = '\0';
66
+ return s;
67
+ }
68
+
69
+ static int sam_write_rg_line(kstring_t *str, const char *s)
70
+ {
71
+ char *p, *q, *r, *rg_line = 0;
72
+ memset(mb_rg_id, 0, 256);
73
+ if (s == 0) return 0;
74
+ if (strstr(s, "@RG") != s) {
75
+ if (kom_verbose >= 1) fprintf(stderr, "[ERROR] the read group line is not started with @RG\n");
76
+ goto err_set_rg;
77
+ }
78
+ if (strstr(s, "\t") != NULL) {
79
+ if (kom_verbose >= 1) fprintf(stderr, "[ERROR] the read group line contained literal <tab> characters -- replace with escaped tabs: \\t\n");
80
+ goto err_set_rg;
81
+ }
82
+ rg_line = kom_strdup(s);
83
+ mb_escape(rg_line);
84
+ if ((p = strstr(rg_line, "\tID:")) == 0) {
85
+ if (kom_verbose >= 1) fprintf(stderr, "[ERROR] no ID within the read group line\n");
86
+ goto err_set_rg;
87
+ }
88
+ p += 4;
89
+ for (q = p; *q && *q != '\t' && *q != '\n'; ++q);
90
+ if (q - p + 1 > 256) {
91
+ if (kom_verbose >= 1) fprintf(stderr, "[ERROR] @RG:ID is longer than 255 characters\n");
92
+ goto err_set_rg;
93
+ }
94
+ for (q = p, r = mb_rg_id; *q && *q != '\t' && *q != '\n'; ++q)
95
+ *r++ = *q;
96
+ kom_sprintf_lite(str, "%s\n", rg_line);
97
+ free(rg_line);
98
+ return 0;
99
+
100
+ err_set_rg:
101
+ free(rg_line);
102
+ return -1;
103
+ }
104
+
105
+ int mb_fmt_sam_hdr(kstring_t *str, const l2b_t *idx, const char *rg, const char *ver, int argc, char *argv[])
106
+ {
107
+ int i, ret = 0;
108
+ str->l = 0;
109
+ kom_sprintf_lite(str, "@HD\tVN:1.6\tSO:unsorted\tGO:query\n");
110
+ if (idx)
111
+ for (i = 0; i < idx->n_ctg; ++i)
112
+ kom_sprintf_lite(str, "@SQ\tSN:%s\tLN:%ld\n", idx->ctg[i].name, idx->ctg[i].len);
113
+ if (rg) ret = sam_write_rg_line(str, rg);
114
+ kom_sprintf_lite(str, "@PG\tID:minibwa\tPN:minibwa");
115
+ if (ver) kom_sprintf_lite(str, "\tVN:%s", ver);
116
+ if (argc > 1) {
117
+ kom_sprintf_lite(str, "\tCL:minibwa");
118
+ for (i = 0; i < argc; ++i)
119
+ kom_sprintf_lite(str, " %s", argv[i]);
120
+ }
121
+ kom_sprintf_lite(str, "\n");
122
+ return ret;
123
+ }
124
+
125
+ /**************
126
+ * SAM output *
127
+ **************/
128
+
129
+ static inline void str_enlarge(kstring_t *s, int l)
130
+ {
131
+ if (s->l + l + 1 > s->m) {
132
+ s->m = s->l + l + 1;
133
+ kom_roundup64(s->m);
134
+ s->s = kom_realloc(char, s->s, s->m);
135
+ }
136
+ }
137
+
138
+ static inline void str_copy(kstring_t *s, const char *st, const char *en)
139
+ {
140
+ str_enlarge(s, en - st);
141
+ memcpy(&s->s[s->l], st, en - st);
142
+ s->l += en - st;
143
+ }
144
+
145
+ static void sam_write_sq(kstring_t *s, char *seq, int l, int rev, int comp)
146
+ {
147
+ if (rev) {
148
+ int i;
149
+ str_enlarge(s, l);
150
+ for (i = 0; i < l; ++i) {
151
+ int c = seq[l - 1 - i];
152
+ s->s[s->l + i] = c < 128 && comp? kom_comp_table[c] : c;
153
+ }
154
+ s->l += l;
155
+ } else str_copy(s, seq, seq + l);
156
+ }
157
+
158
+ static inline const mb_hit_t *get_sam_pri(int n_hit, const mb_hit_t *hit)
159
+ {
160
+ int i;
161
+ for (i = 0; i < n_hit; ++i)
162
+ if (hit[i].sam_pri)
163
+ return &hit[i];
164
+ assert(n_hit == 0);
165
+ return NULL;
166
+ }
167
+
168
+ static void write_sam_cigar(kstring_t *s, int sam_flag, int in_tag, int qlen, const mb_hit_t *r, int64_t opt_flag)
169
+ {
170
+ if (r->p == 0) {
171
+ kom_sprintf_lite(s, "*");
172
+ } else {
173
+ uint32_t k, clip_len[2];
174
+ clip_len[0] = r->rev? qlen - r->qe : r->qs;
175
+ clip_len[1] = r->rev? r->qs : qlen - r->qe;
176
+ if (in_tag) {
177
+ int clip_char = (((sam_flag&0x800) || ((sam_flag&0x100) && (opt_flag&MB_F_2ND_SEQ))) &&
178
+ !(opt_flag&MB_F_SUPP_SOFT)) ? 5 : 4;
179
+ kom_sprintf_lite(s, "\tCG:B:I");
180
+ if (clip_len[0]) kom_sprintf_lite(s, ",%u", clip_len[0]<<4|clip_char);
181
+ for (k = 0; k < r->p->n_cigar; ++k)
182
+ kom_sprintf_lite(s, ",%u", r->p->cigar[k]);
183
+ if (clip_len[1]) kom_sprintf_lite(s, ",%u", clip_len[1]<<4|clip_char);
184
+ } else {
185
+ int clip_char = (((sam_flag&0x800) || ((sam_flag&0x100) && (opt_flag&MB_F_2ND_SEQ))) &&
186
+ !(opt_flag&MB_F_SUPP_SOFT)) ? 'H' : 'S';
187
+ assert(clip_len[0] < qlen && clip_len[1] < qlen);
188
+ if (clip_len[0]) kom_sprintf_lite(s, "%d%c", clip_len[0], clip_char);
189
+ for (k = 0; k < r->p->n_cigar; ++k)
190
+ kom_sprintf_lite(s, "%d%c", r->p->cigar[k]>>4, MB_CIGAR_STR[r->p->cigar[k]&0xf]);
191
+ if (clip_len[1]) kom_sprintf_lite(s, "%d%c", clip_len[1], clip_char);
192
+ }
193
+ }
194
+ }
195
+
196
+ void mb_fmt_sam(void *km, kstring_t *s, const l2b_t *l2b, const mb_bseq1_t *t, int32_t n_seg, const int32_t *n_hit, mb_hit_t *const*hit, int32_t hit_idx, const mb_opt_t *opt, int seg_idx, int32_t mate_qlen)
197
+ {
198
+ int flag, n_h = n_hit[seg_idx];
199
+ int this_tid = -1, this_pos = -1;
200
+ const mb_hit_t *h = hit[seg_idx], *r_prev = NULL, *r_next;
201
+ const mb_hit_t *r = n_h > 0 && hit_idx < n_h && hit_idx >= 0? &h[hit_idx] : NULL;
202
+
203
+ assert(n_seg == 1 || n_seg == 2);
204
+
205
+ // find the primary of the previous and the next segments, if they are mapped
206
+ if (n_seg > 1) {
207
+ int next_sid = (seg_idx + 1) % n_seg;
208
+ r_prev = r_next = get_sam_pri(n_hit[next_sid], hit[next_sid]);
209
+ } else r_prev = r_next = NULL;
210
+
211
+ // write QNAME and FLAG
212
+ kom_sprintf_lite(s, "%s", t->name);
213
+ flag = n_seg > 1? 0x1 : 0x0;
214
+ if (r == 0) {
215
+ flag |= 0x4;
216
+ } else {
217
+ if (r->rev) flag |= 0x10;
218
+ if (r->parent != r->id) flag |= 0x100;
219
+ else if (!r->sam_pri) flag |= 0x800;
220
+ }
221
+ if (n_seg > 1) {
222
+ if (r && r->proper_pair) flag |= 0x2;
223
+ if (seg_idx == 0) flag |= 0x40;
224
+ else if (seg_idx == n_seg - 1) flag |= 0x80;
225
+ if (r_next == NULL) flag |= 0x8;
226
+ else if (r_next->rev) flag |= 0x20;
227
+ }
228
+ kom_sprintf_lite(s, "\t%d", flag);
229
+
230
+ // write coordinate, MAPQ and CIGAR
231
+ if (r == 0) {
232
+ if (r_prev) {
233
+ this_tid = r_prev->tid, this_pos = r_prev->ts;
234
+ kom_sprintf_lite(s, "\t%s\t%d\t0\t*", l2b->ctg[this_tid].name, this_pos+1);
235
+ } else kom_sprintf_lite(s, "\t*\t0\t0\t*");
236
+ } else {
237
+ this_tid = r->tid, this_pos = r->ts;
238
+ kom_sprintf_lite(s, "\t%s\t%d\t%d\t", l2b->ctg[r->tid].name, r->ts+1, r->mapq);
239
+ write_sam_cigar(s, flag, 0, t->l_seq, r, opt->flag);
240
+ }
241
+
242
+ // write mate positions
243
+ if (n_seg > 1) {
244
+ int tlen = 0;
245
+ if (this_tid >= 0 && r_next) {
246
+ if (this_tid == r_next->tid) {
247
+ if (r) {
248
+ int this_pos5 = r->rev? r->te - 1 : this_pos;
249
+ int next_pos5 = r_next->rev? r_next->te - 1 : r_next->ts;
250
+ tlen = next_pos5 - this_pos5;
251
+ }
252
+ kom_sprintf_lite(s, "\t=\t");
253
+ } else kom_sprintf_lite(s, "\t%s\t", l2b->ctg[r_next->tid].name);
254
+ kom_sprintf_lite(s, "%d\t", r_next->ts + 1);
255
+ } else if (r_next) { // && this_tid < 0
256
+ kom_sprintf_lite(s, "\t%s\t%d\t", l2b->ctg[r_next->tid].name, r_next->ts + 1);
257
+ } else if (this_tid >= 0) { // && r_next == NULL
258
+ kom_sprintf_lite(s, "\t=\t%d\t", this_pos + 1); // next segment will take r's coordinate
259
+ } else kom_sprintf_lite(s, "\t*\t0\t"); // neither has coordinates
260
+ if (tlen > 0) ++tlen;
261
+ else if (tlen < 0) --tlen;
262
+ kom_sprintf_lite(s, "%d\t", tlen);
263
+ } else kom_sprintf_lite(s, "\t*\t0\t0\t");
264
+
265
+ // write SEQ and QUAL
266
+ if (r == 0) {
267
+ sam_write_sq(s, t->seq, t->l_seq, 0, 0);
268
+ kom_sprintf_lite(s, "\t");
269
+ if (t->qual) sam_write_sq(s, t->qual, t->l_seq, 0, 0);
270
+ else kom_sprintf_lite(s, "*");
271
+ } else {
272
+ if ((flag & 0x900) == 0 || (opt->flag & MB_F_SUPP_SOFT)) {
273
+ sam_write_sq(s, t->seq, t->l_seq, r->rev, r->rev);
274
+ kom_sprintf_lite(s, "\t");
275
+ if (t->qual) sam_write_sq(s, t->qual, t->l_seq, r->rev, 0);
276
+ else kom_sprintf_lite(s, "*");
277
+ } else if ((flag & 0x100) && !(opt->flag & MB_F_2ND_SEQ)){
278
+ kom_sprintf_lite(s, "*\t*");
279
+ } else {
280
+ sam_write_sq(s, t->seq + r->qs, r->qe - r->qs, r->rev, r->rev);
281
+ kom_sprintf_lite(s, "\t");
282
+ if (t->qual) sam_write_sq(s, t->qual + r->qs, r->qe - r->qs, r->rev, 0);
283
+ else kom_sprintf_lite(s, "*");
284
+ }
285
+ }
286
+
287
+ // write tags
288
+ if (mb_rg_id[0]) kom_sprintf_lite(s, "\tRG:Z:%s", mb_rg_id);
289
+ if (n_seg > 2) kom_sprintf_lite(s, "\tFI:i:%d", seg_idx);
290
+ if (r) {
291
+ write_tags(s, r);
292
+ // MC:Z mate CIGAR and MQ:i mate MAPQ; r_next is the mate's primary (see above).
293
+ if (n_seg > 1 && r_next && r_next->p && r_next->p->n_cigar > 0 && mate_qlen > 0) {
294
+ kom_sprintf_lite(s, "\tMC:Z:");
295
+ write_sam_cigar(s, 0, 0, mate_qlen, r_next, opt->flag);
296
+ kom_sprintf_lite(s, "\tMQ:i:%d", r_next->mapq);
297
+ }
298
+ if (r->p->cs) kom_sprintf_lite(s, "\t%s", (char*)&r->p->cigar[r->p->n_cigar]);
299
+ if (r->parent == r->id && r->p && n_h > 1 && h && r >= h && r - h < n_h) { // supplementary aln may exist
300
+ int i, n_sa = 0; // n_sa: number of SA fields
301
+ for (i = 0; i < n_h; ++i)
302
+ if (i != r - h && h[i].parent == h[i].id && h[i].p)
303
+ ++n_sa;
304
+ if (n_sa > 0) {
305
+ kom_sprintf_lite(s, "\tSA:Z:");
306
+ for (i = 0; i < n_h; ++i) {
307
+ const mb_hit_t *q = &h[i];
308
+ int l_M, l_I = 0, l_D = 0, clip5 = 0, clip3 = 0;
309
+ if (r == q || q->parent != q->id || q->p == 0) continue;
310
+ if (q->qe - q->qs < q->te - q->ts) l_M = q->qe - q->qs, l_D = (q->te - q->ts) - l_M;
311
+ else l_M = q->te - q->ts, l_I = (q->qe - q->qs) - l_M;
312
+ clip5 = q->rev? t->l_seq - q->qe : q->qs;
313
+ clip3 = q->rev? q->qs : t->l_seq - q->qe;
314
+ kom_sprintf_lite(s, "%s,%d,%c,", l2b->ctg[q->tid].name, q->ts+1, "+-"[q->rev]);
315
+ if (clip5) kom_sprintf_lite(s, "%dS", clip5);
316
+ if (l_M) kom_sprintf_lite(s, "%dM", l_M);
317
+ if (l_I) kom_sprintf_lite(s, "%dI", l_I);
318
+ if (l_D) kom_sprintf_lite(s, "%dD", l_D);
319
+ if (clip3) kom_sprintf_lite(s, "%dS", clip3);
320
+ kom_sprintf_lite(s, ",%d,%d;", q->mapq, q->blen - q->mlen + q->p->n_ambi);
321
+ }
322
+ }
323
+ if (opt->xa_max > 0) {
324
+ int i, n_xa = 0;
325
+ for (i = 0; i < n_h; ++i)
326
+ if (i != r - h && h[i].parent == r - h && h[i].p->dp_max >= (double)opt->out_s * r->p->dp_max)
327
+ ++n_xa;
328
+ if (n_xa > 0) kom_sprintf_lite(s, "\tn2:i:%d", n_xa);
329
+ if (n_xa > 0 && n_xa <= opt->xa_max) {
330
+ kom_sprintf_lite(s, "\tXA:Z:");
331
+ for (i = 0; i < n_h; ++i) {
332
+ const mb_hit_t *q = &h[i];
333
+ if (i != r - h && q->parent == r - h && q->p->dp_max >= (double)opt->out_s * r->p->dp_max) {
334
+ kom_sprintf_lite(s, "%s,%c%d,", l2b->ctg[q->tid].name, "+-"[q->rev], q->ts+1);
335
+ write_sam_cigar(s, 0, 0, t->l_seq, q, opt->flag);
336
+ kom_sprintf_lite(s, ",%d;", q->blen - q->mlen + q->p->n_ambi);
337
+ }
338
+ }
339
+ }
340
+ }
341
+ }
342
+ }
343
+
344
+ if ((opt->flag & MB_F_COPY_COMMENT) && t->comment)
345
+ kom_sprintf_lite(s, "\t%s", t->comment);
346
+ kom_sprintf_lite(s, "\n");
347
+ s->s[s->l] = 0; // we always have room for an extra byte
348
+ }
349
+
350
+ void mb_format(void *km, kstring_t *s, const l2b_t *l2b, const mb_bseq1_t *t, int32_t n_seg, const int32_t *n_hit, mb_hit_t *const*hit, int32_t hit_idx, const mb_opt_t *opt, int seg_idx, int32_t mate_qlen)
351
+ {
352
+ if (!(opt->flag & MB_F_PAF))
353
+ mb_fmt_sam(km, s, l2b, t, n_seg, n_hit, hit, hit_idx, opt, seg_idx, mate_qlen);
354
+ else
355
+ mb_fmt_paf(s, l2b, t, hit_idx >= 0? &hit[seg_idx][hit_idx] : 0, opt->flag, n_seg, seg_idx);
356
+ }