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,479 @@
1
+ #include <zlib.h>
2
+ #include <stdio.h>
3
+ #include <assert.h>
4
+ #include "kommon.h"
5
+ #include "l2bit.h"
6
+ #include "kseq.h"
7
+ KSEQ_INIT(gzFile, gzread)
8
+
9
+ static int64_t l2b_pos2cid(const l2b_t *l2b, int64_t s, int64_t len, int64_t *cst)
10
+ {
11
+ int64_t lo = 0, hi = l2b->n_ctg, mid;
12
+ while (lo < hi) {
13
+ const l2b_ctg_t *ctg;
14
+ mid = (lo + hi) / 2;
15
+ ctg = &l2b->ctg[mid];
16
+ if (ctg->off <= s && s < ctg->off + ctg->len) {
17
+ *cst = s - ctg->off;
18
+ return s + len <= ctg->off + ctg->len? mid : -1;
19
+ } else if (s < ctg->off) hi = mid;
20
+ else lo = mid + 1;
21
+ }
22
+ return -1; // s is in no contig
23
+ }
24
+
25
+ int64_t l2b_intv2cid(const l2b_t *l2b, uint64_t st, uint64_t en, int64_t *cst, int *rev)
26
+ {
27
+ int64_t s;
28
+ assert(st < en);
29
+ if (en > l2b->tot_len * 2) return -3;
30
+ if (st < l2b->tot_len && l2b->tot_len < en) return -2;
31
+ *rev = (st >= l2b->tot_len);
32
+ s = st < l2b->tot_len? st : l2b->tot_len * 2 - en;
33
+ return l2b_pos2cid(l2b, s, en - st, cst);
34
+ }
35
+
36
+ int64_t l2b_intv2cid_meth(const l2b_t *l2b, uint64_t st, uint64_t en, l2b_meth_t *mt, int64_t *cst, int *rev)
37
+ {
38
+ int64_t s, len = en - st;
39
+ int32_t copy;
40
+ uint64_t tot_len = l2b->tot_len;
41
+
42
+ assert(st < en);
43
+ if (en > tot_len * 4) return -3;
44
+ copy = st / tot_len; // 0: c2t_f, 1: g2a_f, 2: g2a_r, 3: c2t_r
45
+ *mt = (copy == 0 || copy == 3)? L2B_METH_C2T : L2B_METH_G2A;
46
+ *rev = (copy >= 2);
47
+ s = st - tot_len * copy;
48
+ if (copy >= 2) s = tot_len - len - s; // flip for reverse copies
49
+ return s < 0? -2 : l2b_pos2cid(l2b, s, len, cst);
50
+ }
51
+
52
+ int64_t l2b_getseq(const l2b_t *l2b, int64_t tid, int64_t st, int64_t en, uint8_t *seq)
53
+ {
54
+ const l2b_ctg_t *ctg;
55
+ int64_t i, aid;
56
+ int32_t n_ambi;
57
+ if (tid < 0 || tid >= l2b->n_ctg) return -1;
58
+ ctg = &l2b->ctg[tid];
59
+ if (st < 0) st = 0;
60
+ if (en > ctg->len) en = ctg->len;
61
+ st += ctg->off;
62
+ en += ctg->off;
63
+ for (i = st; i < en; ++i)
64
+ seq[i - st] = l2b_get0(l2b, i);
65
+ // retrieve ambiguous bases
66
+ aid = l2b_getambi(l2b, tid, st - ctg->off, en - ctg->off, &n_ambi);
67
+ if (aid >= 0) {
68
+ for (i = 0; i < n_ambi; ++i) {
69
+ const l2b_intv_t *iv = &l2b->ambi[aid + i];
70
+ int64_t s = iv->st, e = iv->en;
71
+ if (s < st) s = st;
72
+ if (e > en) e = en;
73
+ if (s < e) memset(&seq[s - st], 4, e - s);
74
+ }
75
+ }
76
+ return en - st;
77
+ }
78
+
79
+ void l2b_meth_convert(l2b_meth_t mt, int64_t len, uint8_t *seq)
80
+ {
81
+ int64_t i;
82
+ if (mt == L2B_METH_C2T) {
83
+ for (i = 0; i < len; ++i)
84
+ if (seq[i] == 1) seq[i] = 3;
85
+ } else if (mt == L2B_METH_G2A) {
86
+ for (i = 0; i < len; ++i)
87
+ if (seq[i] == 2) seq[i] = 0;
88
+ }
89
+ }
90
+
91
+ int64_t l2b_getambi(const l2b_t *l2b, int64_t tid, int64_t st, int64_t en, int32_t *n_ambi)
92
+ {
93
+ int64_t g_beg, g_end, lo, hi, mid, i_st, i_en;
94
+ *n_ambi = 0;
95
+ if (tid < 0 || tid >= l2b->n_ctg) return -1;
96
+ if (st < 0) st = 0;
97
+ if (en > l2b->ctg[tid].len) en = l2b->ctg[tid].len;
98
+ if (st >= en) return -1;
99
+ g_beg = l2b->ctg[tid].off + st;
100
+ g_end = l2b->ctg[tid].off + en;
101
+
102
+ lo = 0, hi = l2b->n_ambi;
103
+ while (lo < hi) {
104
+ mid = (lo + hi) / 2;
105
+ if (l2b->ambi[mid].en > g_beg) hi = mid;
106
+ else lo = mid + 1;
107
+ }
108
+ i_st = lo;
109
+
110
+ lo = i_st, hi = l2b->n_ambi;
111
+ while (lo < hi) {
112
+ mid = (lo + hi) / 2;
113
+ if (l2b->ambi[mid].st >= g_end) hi = mid;
114
+ else lo = mid + 1;
115
+ }
116
+ i_en = lo;
117
+
118
+ *n_ambi = i_en - i_st;
119
+ if (*n_ambi == 0) return -1;
120
+ return i_st;
121
+ }
122
+
123
+ static void l2b_format_seq(uint64_t len, char *seq, uint64_t *rng)
124
+ {
125
+ uint64_t i;
126
+ for (i = 0; i < len; ++i) {
127
+ int b = (uint8_t)seq[i];
128
+ uint8_t c = kom_nt4_table[b];
129
+ if (c > 4) c = 4;
130
+ if (c == 4) c |= kom_splitmix64(rng) & 3;
131
+ if (b < 'A' || b > 'Z') c |= 1<<3;
132
+ seq[i] = c;
133
+ }
134
+ }
135
+
136
+ static void l2b_add_seq(l2b_t *l2b, uint64_t len, const char *seq, const char *name, const char *comm, uint64_t *rng)
137
+ {
138
+ uint64_t i, ambi_len, mask_len, off, m_pac_old;
139
+ l2b_ctg_t *ctg;
140
+
141
+ off = l2b->tot_len;
142
+ kom_grow(l2b_ctg_t, l2b->ctg, l2b->n_ctg, l2b->m_ctg);
143
+ ctg = &l2b->ctg[l2b->n_ctg++];
144
+ ctg->name = kom_strdup(name);
145
+ ctg->comm = comm? kom_strdup(comm) : 0;
146
+ ctg->len = len;
147
+ ctg->off = l2b->tot_len;
148
+ l2b->tot_len += len;
149
+
150
+ m_pac_old = l2b->m_pac;
151
+ l2b->n_pac = (l2b->tot_len + 31) / 32;
152
+ kom_grow(uint64_t, l2b->pac, l2b->n_pac, l2b->m_pac);
153
+ if (m_pac_old < l2b->m_pac) // zero out newly allocated part
154
+ memset(&l2b->pac[m_pac_old], 0, (l2b->m_pac - m_pac_old) * 8);
155
+
156
+ for (i = 0, ambi_len = mask_len = 0; i < len; ++i) {
157
+ uint64_t c = (uint8_t)seq[i], x = off + i;
158
+ if (c & 1<<3) { // soft-masked base
159
+ ++mask_len;
160
+ } else if (mask_len > 0) {
161
+ kom_grow(l2b_intv_t, l2b->mask, l2b->n_mask, l2b->m_mask);
162
+ l2b->mask[l2b->n_mask].st = x - mask_len;
163
+ l2b->mask[l2b->n_mask].en = x;
164
+ l2b->n_mask++;
165
+ mask_len = 0;
166
+ }
167
+ if (c & 1<<2) { // ambiguous base
168
+ ++ambi_len;
169
+ } else if (ambi_len > 0) {
170
+ kom_grow(l2b_intv_t, l2b->ambi, l2b->n_ambi, l2b->m_ambi);
171
+ l2b->ambi[l2b->n_ambi].st = x - ambi_len;
172
+ l2b->ambi[l2b->n_ambi].en = x;
173
+ l2b->n_ambi++;
174
+ ambi_len = 0;
175
+ }
176
+ l2b->pac[x>>5] |= (c&3) << (x&0x1f)*2;
177
+ }
178
+ }
179
+
180
+ static void l2b_collate_str(l2b_t *l2b)
181
+ {
182
+ uint64_t i, tot_name = 0, tot_comm = 0;
183
+ char *p_name, *p_comm;
184
+ if (l2b->cat_name || l2b->cat_comm) return;
185
+ for (i = 0; i < l2b->n_ctg; ++i) {
186
+ l2b_ctg_t *ctg = &l2b->ctg[i];
187
+ tot_name += strlen(ctg->name) + 1;
188
+ tot_comm += ctg->comm? strlen(ctg->comm) + 1 : 1;
189
+ }
190
+ p_name = l2b->cat_name = kom_calloc(char, tot_name);
191
+ p_comm = l2b->cat_comm = kom_calloc(char, tot_comm);
192
+ for (i = 0; i < l2b->n_ctg; ++i) {
193
+ l2b_ctg_t *ctg = &l2b->ctg[i];
194
+ uint64_t len;
195
+ len = strlen(ctg->name);
196
+ memcpy(p_name, ctg->name, len + 1);
197
+ free(ctg->name);
198
+ ctg->name = p_name;
199
+ p_name += len + 1;
200
+ if (ctg->comm) {
201
+ len = strlen(ctg->comm);
202
+ memcpy(p_comm, ctg->comm, len + 1);
203
+ free(ctg->comm);
204
+ ctg->comm = p_comm;
205
+ } else len = 0;
206
+ p_comm += len + 1;
207
+ }
208
+ }
209
+
210
+ l2b_t *l2b_import(const char *fn, uint64_t seed)
211
+ {
212
+ gzFile fp;
213
+ kseq_t *ks;
214
+ l2b_t *l2b;
215
+ uint64_t rng = seed;
216
+
217
+ fp = fn == 0 || strcmp(fn, "-") == 0? gzdopen(0, "r") : gzopen(fn, "r");
218
+ if (fp == 0) return 0;
219
+ ks = kseq_init(fp);
220
+ l2b = kom_calloc(l2b_t, 1);
221
+ while (kseq_read(ks) >= 0) {
222
+ l2b_format_seq(ks->seq.l, ks->seq.s, &rng);
223
+ l2b_add_seq(l2b, ks->seq.l, ks->seq.s, ks->name.s, ks->comment.l? ks->comment.s : 0, &rng);
224
+ }
225
+ kseq_destroy(ks);
226
+ gzclose(fp);
227
+ l2b_collate_str(l2b);
228
+ return l2b;
229
+ }
230
+
231
+ void l2b_destroy(l2b_t *l2b)
232
+ {
233
+ if (l2b->mmap) { // ambi/mask/pac/cat_name/cat_comm point into the mapped file
234
+ free(l2b->ctg); // ctg[] is always heap-allocated
235
+ kom_munmap(l2b->mmap, l2b->mmap_len);
236
+ } else {
237
+ free(l2b->cat_name); free(l2b->cat_comm);
238
+ free(l2b->pac); free(l2b->ambi); free(l2b->mask); free(l2b->ctg);
239
+ }
240
+ free(l2b);
241
+ }
242
+
243
+ int l2b_save(const char *fn, const l2b_t *l2b)
244
+ {
245
+ FILE *fp;
246
+ uint64_t i, len_name = 0, len_comm = 0;
247
+ uint32_t dummy = 0;
248
+ fp = fn == 0 || strcmp(fn, "-") == 0? stdout : fopen(fn, "wb");
249
+ if (fp == 0) return -1;
250
+ for (i = 0; i < l2b->n_ctg; ++i) {
251
+ const l2b_ctg_t *ctg = &l2b->ctg[i];
252
+ len_name += strlen(ctg->name) + 1;
253
+ len_comm += ctg->comm? strlen(ctg->comm) + 1 : 1;
254
+ }
255
+ fwrite(L2B_MAGIC, 1, 4, fp);
256
+ fwrite(&dummy, 4, 1, fp);
257
+ fwrite(&l2b->n_ctg, 8, 1, fp);
258
+ fwrite(&l2b->tot_len, 8, 1, fp);
259
+ fwrite(&l2b->n_ambi, 8, 1, fp);
260
+ fwrite(&l2b->n_mask, 8, 1, fp);
261
+ fwrite(&len_name, 8, 1, fp);
262
+ fwrite(&len_comm, 8, 1, fp);
263
+ fwrite(&l2b->n_pac, 8, 1, fp);
264
+ for (i = 0; i < l2b->n_ctg; ++i)
265
+ fwrite(&l2b->ctg[i].len, 8, 1, fp);
266
+ fwrite(l2b->ambi, 16, l2b->n_ambi, fp);
267
+ fwrite(l2b->mask, 16, l2b->n_mask, fp);
268
+ fwrite(l2b->pac, 8, l2b->n_pac, fp);
269
+ fwrite(l2b->cat_name, 1, len_name, fp); // put strings at the end to make sure uint64_t are all aligned
270
+ fwrite(l2b->cat_comm, 1, len_comm, fp);
271
+ fclose(fp);
272
+ return 0;
273
+ }
274
+
275
+ l2b_t *l2b_load(const char *fn)
276
+ {
277
+ FILE *fp;
278
+ char magic[4], *p_name, *p_comm;
279
+ uint32_t dummy;
280
+ uint64_t off, i, len_name, len_comm;
281
+ l2b_t *l2b;
282
+ fp = fn == 0 || strcmp(fn, "-") == 0? stdin : fopen(fn, "rb");
283
+ if (fp == 0) return 0;
284
+ fread(magic, 1, 4, fp);
285
+ if (strncmp(magic, L2B_MAGIC, 4) != 0) {
286
+ if (fp != stdin) fclose(fp);
287
+ return 0;
288
+ }
289
+ l2b = kom_calloc(l2b_t, 1);
290
+ fread(&dummy, 4, 1, fp);
291
+ fread(&l2b->n_ctg, 8, 1, fp);
292
+ fread(&l2b->tot_len, 8, 1, fp);
293
+ fread(&l2b->n_ambi, 8, 1, fp);
294
+ fread(&l2b->n_mask, 8, 1, fp);
295
+ fread(&len_name, 8, 1, fp);
296
+ fread(&len_comm, 8, 1, fp);
297
+ fread(&l2b->n_pac, 8, 1, fp);
298
+ l2b->ctg = kom_calloc(l2b_ctg_t, l2b->n_ctg);
299
+ for (i = 0, off = 0; i < l2b->n_ctg; ++i) { // read contig lengths
300
+ fread(&l2b->ctg[i].len, 8, 1, fp);
301
+ l2b->ctg[i].off = off;
302
+ off += l2b->ctg[i].len;
303
+ }
304
+ if (off != l2b->tot_len) goto load_failure;
305
+ l2b->ambi = kom_malloc(l2b_intv_t, l2b->n_ambi);
306
+ l2b->mask = kom_malloc(l2b_intv_t, l2b->n_mask);
307
+ l2b->pac = kom_malloc(uint64_t, l2b->n_pac);
308
+ l2b->cat_name = kom_malloc(char, len_name);
309
+ l2b->cat_comm = kom_malloc(char, len_comm);
310
+ fread(l2b->ambi, 16, l2b->n_ambi, fp);
311
+ fread(l2b->mask, 16, l2b->n_mask, fp);
312
+ fread(l2b->pac, 8, l2b->n_pac, fp);
313
+ fread(l2b->cat_name, 1, len_name, fp);
314
+ fread(l2b->cat_comm, 1, len_comm, fp);
315
+ p_name = l2b->cat_name, p_comm = l2b->cat_comm;
316
+ for (i = 0; i < l2b->n_ctg; ++i) { // synchronize contig names and comments
317
+ l2b_ctg_t *ctg = &l2b->ctg[i];
318
+ ctg->name = p_name;
319
+ p_name += strlen(p_name) + 1;
320
+ ctg->comm = *p_comm? p_comm : 0;
321
+ p_comm += *p_comm? strlen(p_comm) + 1 : 1;
322
+ }
323
+ if (p_name - l2b->cat_name != len_name || p_comm - l2b->cat_comm != len_comm) goto load_failure;
324
+ if (fp != stdin) fclose(fp);
325
+ return l2b;
326
+ load_failure:
327
+ if (fp != stdin) fclose(fp);
328
+ l2b_destroy(l2b);
329
+ return 0;
330
+ }
331
+
332
+ l2b_t *l2b_load_mmap(const char *fn, int preload)
333
+ {
334
+ uint8_t *base;
335
+ const uint64_t *hdr, *lens;
336
+ uint64_t off, i, len_name, len_comm, foff;
337
+ size_t map_len;
338
+ char *p_name, *p_comm;
339
+ l2b_t *l2b;
340
+
341
+ base = (uint8_t*)kom_mmap_file(fn, &map_len, preload);
342
+ if (base == 0) return 0;
343
+ if (map_len < 64 || strncmp((const char*)base, L2B_MAGIC, 4) != 0) { kom_munmap(base, map_len); return 0; }
344
+
345
+ l2b = kom_calloc(l2b_t, 1);
346
+ l2b->mmap = base;
347
+ l2b->mmap_len = map_len;
348
+ hdr = (const uint64_t*)base; // hdr[0] is magic+dummy; fields start at hdr[1]
349
+ l2b->n_ctg = hdr[1];
350
+ l2b->tot_len = hdr[2];
351
+ l2b->n_ambi = hdr[3];
352
+ l2b->n_mask = hdr[4];
353
+ len_name = hdr[5];
354
+ len_comm = hdr[6];
355
+ l2b->n_pac = hdr[7];
356
+
357
+ l2b->ctg = kom_calloc(l2b_ctg_t, l2b->n_ctg); // ctg[] is not stored in the file
358
+ lens = &hdr[8]; // contig lengths follow the 64-byte header
359
+ for (i = 0, off = 0; i < l2b->n_ctg; ++i) {
360
+ l2b->ctg[i].len = lens[i];
361
+ l2b->ctg[i].off = off;
362
+ off += lens[i];
363
+ }
364
+ if (off != l2b->tot_len) goto mmap_failure;
365
+
366
+ foff = 64 + l2b->n_ctg * 8; // point large arrays into the mapped file
367
+ l2b->ambi = (l2b_intv_t*)(base + foff); foff += l2b->n_ambi * 16;
368
+ l2b->mask = (l2b_intv_t*)(base + foff); foff += l2b->n_mask * 16;
369
+ l2b->pac = (uint64_t*) (base + foff); foff += l2b->n_pac * 8;
370
+ l2b->cat_name = (char*)(base + foff); foff += len_name;
371
+ l2b->cat_comm = (char*)(base + foff); foff += len_comm;
372
+ if (foff != map_len) goto mmap_failure;
373
+
374
+ p_name = l2b->cat_name, p_comm = l2b->cat_comm;
375
+ for (i = 0; i < l2b->n_ctg; ++i) { // synchronize contig names and comments
376
+ l2b_ctg_t *ctg = &l2b->ctg[i];
377
+ ctg->name = p_name;
378
+ p_name += strlen(p_name) + 1;
379
+ ctg->comm = *p_comm? p_comm : 0;
380
+ p_comm += *p_comm? strlen(p_comm) + 1 : 1;
381
+ }
382
+ if (p_name - l2b->cat_name != len_name || p_comm - l2b->cat_comm != len_comm) goto mmap_failure;
383
+ return l2b;
384
+ mmap_failure:
385
+ l2b_destroy(l2b);
386
+ return 0;
387
+ }
388
+
389
+ /******************************
390
+ * Save .paf files for bwtgen *
391
+ ******************************/
392
+
393
+ int l2b_save_pac(const char *fn, const l2b_t *l2b, int both_strand)
394
+ {
395
+ FILE *fp;
396
+ uint64_t n_pac, x;
397
+ int64_t i;
398
+ uint8_t *pac, ct;
399
+
400
+ fp = fn == 0 || strcmp(fn, "-") == 0? stdout : fopen(fn, "wb");
401
+ if (fp == 0) return -1;
402
+
403
+ // fill pac[]
404
+ n_pac = ((both_strand? l2b->tot_len * 2 : l2b->tot_len) + 3) / 4;
405
+ pac = kom_calloc(uint8_t, n_pac);
406
+ for (i = 0, x = 0; i < l2b->tot_len; ++i, ++x)
407
+ pac[x>>2] |= l2b_get0(l2b, i) << (~x&3) * 2;
408
+ if (both_strand)
409
+ for (i = l2b->tot_len - 1; i >= 0; --i, ++x)
410
+ pac[x>>2] |= (3 - l2b_get0(l2b, i)) << (~x&3) * 2;
411
+
412
+ // write pac
413
+ fwrite(pac, 1, (x>>2) + ((x&3) == 0? 0 : 1), fp);
414
+ // the following codes make the pac file size always (x/4+1+1)
415
+ if (x % 4 == 0) {
416
+ ct = 0;
417
+ fwrite(&ct, 1, 1, fp);
418
+ }
419
+ ct = x % 4;
420
+ fwrite(&ct, 1, 1, fp);
421
+
422
+ fclose(fp);
423
+ free(pac);
424
+ return 0;
425
+ }
426
+
427
+ static inline uint8_t l2b_c2t(uint8_t b) { return b == 1? 3 : b; } // C(1) -> T(3)
428
+ static inline uint8_t l2b_g2a(uint8_t b) { return b == 2? 0 : b; } // G(2) -> A(0)
429
+
430
+ int l2b_save_pac_meth(const char *fn, const l2b_t *l2b, int both_strand)
431
+ {
432
+ FILE *fp;
433
+ uint64_t n_pac, x, len;
434
+ int64_t i;
435
+ uint8_t *pac, ct, b;
436
+
437
+ fp = fn == 0 || strcmp(fn, "-") == 0? stdout : fopen(fn, "wb");
438
+ if (fp == 0) return -1;
439
+
440
+ len = l2b->tot_len * 2; // c2t + g2a
441
+ if (both_strand) len *= 2; // forward + reverse
442
+ n_pac = (len + 3) / 4;
443
+ pac = kom_calloc(uint8_t, n_pac);
444
+
445
+ // c2t forward
446
+ for (i = 0, x = 0; i < l2b->tot_len; ++i, ++x) {
447
+ b = l2b_c2t(l2b_get0(l2b, i));
448
+ pac[x>>2] |= b << ((~x&3) * 2);
449
+ }
450
+ // g2a forward
451
+ for (i = 0; i < l2b->tot_len; ++i, ++x) {
452
+ b = l2b_g2a(l2b_get0(l2b, i));
453
+ pac[x>>2] |= b << ((~x&3) * 2);
454
+ }
455
+ if (both_strand) {
456
+ // g2a reverse (reverse complement of g2a converted sequence)
457
+ for (i = l2b->tot_len - 1; i >= 0; --i, ++x) {
458
+ b = 3 - l2b_g2a(l2b_get0(l2b, i));
459
+ pac[x>>2] |= b << ((~x&3) * 2);
460
+ }
461
+ // c2t reverse (reverse complement of c2t converted sequence)
462
+ for (i = l2b->tot_len - 1; i >= 0; --i, ++x) {
463
+ b = 3 - l2b_c2t(l2b_get0(l2b, i));
464
+ pac[x>>2] |= b << ((~x&3) * 2);
465
+ }
466
+ }
467
+
468
+ fwrite(pac, 1, (x>>2) + ((x&3) == 0? 0 : 1), fp);
469
+ if (x % 4 == 0) {
470
+ ct = 0;
471
+ fwrite(&ct, 1, 1, fp);
472
+ }
473
+ ct = x % 4;
474
+ fwrite(&ct, 1, 1, fp);
475
+
476
+ fclose(fp);
477
+ free(pac);
478
+ return 0;
479
+ }
@@ -0,0 +1,72 @@
1
+ #ifndef L2BIT_H
2
+ #define L2BIT_H
3
+
4
+ #include <stdint.h>
5
+ #include <stddef.h>
6
+
7
+ #define L2B_MAGIC "L2B\1"
8
+
9
+ typedef enum { L2B_METH_NONE=0, L2B_METH_C2T, L2B_METH_G2A } l2b_meth_t;
10
+
11
+ typedef struct {
12
+ char *name, *comm;
13
+ uint64_t len, off;
14
+ } l2b_ctg_t;
15
+
16
+ typedef struct {
17
+ uint64_t st, en;
18
+ } l2b_intv_t;
19
+
20
+ typedef struct {
21
+ uint64_t tot_len;
22
+ uint64_t n_ctg, m_ctg;
23
+ l2b_ctg_t *ctg;
24
+ uint64_t n_pac, m_pac;
25
+ uint64_t n_ambi, m_ambi;
26
+ uint64_t n_mask, m_mask;
27
+ l2b_intv_t *ambi, *mask;
28
+ uint64_t *pac;
29
+ char *cat_name, *cat_comm;
30
+ void *mmap; // mmap pointer
31
+ size_t mmap_len; // mmap length (for munmap)
32
+ } l2b_t;
33
+
34
+ #ifdef __cplusplus
35
+ extern "C" {
36
+ #endif
37
+
38
+ l2b_t *l2b_load(const char *fn);
39
+ l2b_t *l2b_load_mmap(const char *fn, int preload);
40
+ void l2b_destroy(l2b_t *l2b);
41
+ int64_t l2b_intv2cid(const l2b_t *l2b, uint64_t st, uint64_t en, int64_t *cst, int *rev);
42
+ int64_t l2b_intv2cid_meth(const l2b_t *l2b, uint64_t st, uint64_t en, l2b_meth_t *mt, int64_t *cst, int *rev);
43
+ int64_t l2b_getseq(const l2b_t *l2b, int64_t tid, int64_t st, int64_t en, uint8_t *seq);
44
+ int64_t l2b_getambi(const l2b_t *l2b, int64_t tid, int64_t st, int64_t en, int32_t *n_ambi);
45
+ void l2b_meth_convert(l2b_meth_t mt, int64_t len, uint8_t *seq);
46
+
47
+ l2b_t *l2b_import(const char *fn, uint64_t seed);
48
+ int l2b_save(const char *fn, const l2b_t *l2b);
49
+ int l2b_save_pac(const char *fn, const l2b_t *l2b, int both_strand);
50
+ int l2b_save_pac_meth(const char *fn, const l2b_t *l2b, int both_strand);
51
+
52
+ static inline int l2b_get0(const l2b_t *l2b, uint64_t i)
53
+ {
54
+ return l2b->pac[i>>5] >> ((i&31)<<1) & 3;
55
+ }
56
+
57
+ static inline void l2b_seq_prefetch(const l2b_t *l2b, int64_t tid, int64_t st)
58
+ {
59
+ if (tid >= 0 && tid < l2b->n_ctg && st >= 0 && st < l2b->ctg[tid].len)
60
+ __builtin_prefetch(&l2b->pac[(st + l2b->ctg[tid].off) >> 5]);
61
+ }
62
+
63
+ static inline l2b_meth_t l2b_meth_rev(l2b_meth_t mt)
64
+ {
65
+ return mt == L2B_METH_NONE? L2B_METH_NONE : mt == L2B_METH_C2T? L2B_METH_G2A : L2B_METH_C2T;
66
+ }
67
+
68
+ #ifdef __cplusplus
69
+ }
70
+ #endif
71
+
72
+ #endif