ruby-minigraph 0.0.20.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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +62 -0
- data/ext/Rakefile +56 -0
- data/ext/cmappy/cmappy.c +7 -0
- data/ext/cmappy/cmappy.h +8 -0
- data/ext/minigraph/LICENSE.txt +23 -0
- data/ext/minigraph/Makefile +66 -0
- data/ext/minigraph/NEWS.md +317 -0
- data/ext/minigraph/README.md +207 -0
- data/ext/minigraph/algo.c +194 -0
- data/ext/minigraph/algo.h +33 -0
- data/ext/minigraph/asm-call.c +147 -0
- data/ext/minigraph/bseq.c +133 -0
- data/ext/minigraph/bseq.h +76 -0
- data/ext/minigraph/cal_cov.c +139 -0
- data/ext/minigraph/doc/example1.png +0 -0
- data/ext/minigraph/doc/example2.png +0 -0
- data/ext/minigraph/doc/examples.graffle +0 -0
- data/ext/minigraph/format.c +241 -0
- data/ext/minigraph/galign.c +140 -0
- data/ext/minigraph/gchain1.c +532 -0
- data/ext/minigraph/gcmisc.c +223 -0
- data/ext/minigraph/gfa-aug.c +260 -0
- data/ext/minigraph/gfa-base.c +526 -0
- data/ext/minigraph/gfa-bbl.c +372 -0
- data/ext/minigraph/gfa-ed.c +617 -0
- data/ext/minigraph/gfa-io.c +395 -0
- data/ext/minigraph/gfa-priv.h +154 -0
- data/ext/minigraph/gfa.h +166 -0
- data/ext/minigraph/ggen.c +182 -0
- data/ext/minigraph/ggen.h +21 -0
- data/ext/minigraph/ggsimple.c +570 -0
- data/ext/minigraph/gmap.c +211 -0
- data/ext/minigraph/index.c +230 -0
- data/ext/minigraph/kalloc.c +224 -0
- data/ext/minigraph/kalloc.h +82 -0
- data/ext/minigraph/kavl.h +414 -0
- data/ext/minigraph/kdq.h +134 -0
- data/ext/minigraph/ketopt.h +116 -0
- data/ext/minigraph/khashl.h +348 -0
- data/ext/minigraph/krmq.h +474 -0
- data/ext/minigraph/kseq.h +256 -0
- data/ext/minigraph/ksort.h +164 -0
- data/ext/minigraph/kstring.h +165 -0
- data/ext/minigraph/kthread.c +159 -0
- data/ext/minigraph/kthread.h +15 -0
- data/ext/minigraph/kvec-km.h +105 -0
- data/ext/minigraph/kvec.h +110 -0
- data/ext/minigraph/lchain.c +441 -0
- data/ext/minigraph/main.c +301 -0
- data/ext/minigraph/map-algo.c +500 -0
- data/ext/minigraph/mgpriv.h +128 -0
- data/ext/minigraph/minigraph.1 +359 -0
- data/ext/minigraph/minigraph.h +176 -0
- data/ext/minigraph/miniwfa.c +834 -0
- data/ext/minigraph/miniwfa.h +95 -0
- data/ext/minigraph/misc/mgutils.js +1451 -0
- data/ext/minigraph/misc.c +12 -0
- data/ext/minigraph/options.c +134 -0
- data/ext/minigraph/shortk.c +251 -0
- data/ext/minigraph/sketch.c +109 -0
- data/ext/minigraph/sys.c +147 -0
- data/ext/minigraph/sys.h +20 -0
- data/ext/minigraph/test/MT-chimp.fa +277 -0
- data/ext/minigraph/test/MT-human.fa +239 -0
- data/ext/minigraph/test/MT-orangA.fa +276 -0
- data/ext/minigraph/test/MT.gfa +19 -0
- data/ext/minigraph/tex/Makefile +13 -0
- data/ext/minigraph/tex/minigraph.bib +676 -0
- data/ext/minigraph/tex/minigraph.tex +986 -0
- data/ext/minigraph/tex/plots/CHM13-f1-90.bb.anno.gp +42 -0
- data/ext/minigraph/tex/plots/CHM13-f1-90.bb.anno.tbl +13 -0
- data/ext/minigraph/tex/plots/CHM13-f1-90.bb.mini-inter-none.win.gp +269 -0
- data/ext/minigraph/tex/plots/CHM13-f1-90.bb.mini-inter-none.win.sh +7 -0
- data/ext/minigraph/tex/plots/CHM13v1.cen.bed +23 -0
- data/ext/minigraph/tex/plots/CHM13v1.size +23 -0
- data/ext/minigraph/tex/plots/anno2tbl.js +40 -0
- data/ext/minigraph/tex/plots/bedutils.js +367 -0
- data/ext/minigraph/tex/plots/chr-plot.js +130 -0
- data/ext/minigraph/tex/plots/gen-anno.mak +24 -0
- data/ext/minigraph.patch +21 -0
- data/lib/minigraph/ffi/constants.rb +230 -0
- data/lib/minigraph/ffi/functions.rb +70 -0
- data/lib/minigraph/ffi/mappy.rb +8 -0
- data/lib/minigraph/ffi.rb +27 -0
- data/lib/minigraph/version.rb +5 -0
- data/lib/minigraph.rb +72 -0
- metadata +159 -0
@@ -0,0 +1,834 @@
|
|
1
|
+
#include <string.h>
|
2
|
+
#include <assert.h>
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <stdio.h>
|
5
|
+
#include "miniwfa.h"
|
6
|
+
#include "kalloc.h"
|
7
|
+
|
8
|
+
/*
|
9
|
+
* Default setting
|
10
|
+
*/
|
11
|
+
void mwf_opt_init(mwf_opt_t *opt)
|
12
|
+
{
|
13
|
+
memset(opt, 0, sizeof(*opt));
|
14
|
+
opt->x = 4; // corresponding SW score: m=1, x=3, o1=4, e1=3/2, o2=15, e2=1/2
|
15
|
+
opt->o1 = 4, opt->e1 = 2;
|
16
|
+
opt->o2 = 15, opt->e2 = 1;
|
17
|
+
opt->kmer = 13, opt->max_occ = 2, opt->min_len = 30;
|
18
|
+
}
|
19
|
+
|
20
|
+
/*
|
21
|
+
* Structs and simple functions for traceback
|
22
|
+
*/
|
23
|
+
typedef struct {
|
24
|
+
int32_t lo, hi;
|
25
|
+
uint8_t *x;
|
26
|
+
} wf_tb1_t;
|
27
|
+
|
28
|
+
typedef struct {
|
29
|
+
int32_t m, n;
|
30
|
+
wf_tb1_t *a;
|
31
|
+
} wf_tb_t;
|
32
|
+
|
33
|
+
static wf_tb1_t *wf_tb_add(void *km, wf_tb_t *tb, int32_t lo, int32_t hi)
|
34
|
+
{
|
35
|
+
wf_tb1_t *p;
|
36
|
+
if (tb->n == tb->m) {
|
37
|
+
tb->m += (tb->m>>1) + 4;
|
38
|
+
tb->a = Krealloc(km, wf_tb1_t, tb->a, tb->m);
|
39
|
+
}
|
40
|
+
p = &tb->a[tb->n++];
|
41
|
+
p->lo = lo, p->hi = hi;
|
42
|
+
p->x = Kcalloc(km, uint8_t, hi - lo + 1);
|
43
|
+
return p;
|
44
|
+
}
|
45
|
+
|
46
|
+
typedef struct {
|
47
|
+
int32_t m, n;
|
48
|
+
uint32_t *cigar;
|
49
|
+
} wf_cigar_t;
|
50
|
+
|
51
|
+
static void wf_cigar_push1(void *km, wf_cigar_t *c, int32_t op, int32_t len)
|
52
|
+
{
|
53
|
+
if (c->n && op == (c->cigar[c->n-1]&0xf)) {
|
54
|
+
c->cigar[c->n-1] += len<<4;
|
55
|
+
} else {
|
56
|
+
if (c->n == c->m) {
|
57
|
+
c->m = c->m + (c->m>>1) + 4;
|
58
|
+
c->cigar = Krealloc(km, uint32_t, c->cigar, c->m);
|
59
|
+
}
|
60
|
+
c->cigar[c->n++] = len<<4 | op;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
/*
|
65
|
+
* The stripe data structure
|
66
|
+
*/
|
67
|
+
#define WF_NEG_INF (-0x40000000)
|
68
|
+
|
69
|
+
typedef struct {
|
70
|
+
int32_t lo, hi;
|
71
|
+
int32_t *mem, *H, *E1, *E2, *F1, *F2;
|
72
|
+
} wf_slice_t;
|
73
|
+
|
74
|
+
typedef struct {
|
75
|
+
int32_t s, top, n, max_pen, lo, hi;
|
76
|
+
wf_slice_t *a;
|
77
|
+
} wf_stripe_t;
|
78
|
+
|
79
|
+
void wf_stripe_add(void *km, wf_stripe_t *wf, int32_t lo, int32_t hi)
|
80
|
+
{
|
81
|
+
int32_t i, n, m1 = wf->max_pen + 1, m2 = m1 * 2;
|
82
|
+
wf_slice_t *f;
|
83
|
+
++wf->s;
|
84
|
+
++wf->top;
|
85
|
+
if (wf->top == wf->n) wf->top = 0;
|
86
|
+
f = &wf->a[wf->top];
|
87
|
+
f->lo = lo, f->hi = hi;
|
88
|
+
n = hi - lo + 1;
|
89
|
+
kfree(km, f->mem);
|
90
|
+
f->mem = Kmalloc(km, int32_t, 5 * (n + m2));
|
91
|
+
f->H = f->mem + m1;
|
92
|
+
f->E1 = f->H + n + m2;
|
93
|
+
f->F1 = f->E1 + n + m2;
|
94
|
+
f->E2 = f->F1 + n + m2;
|
95
|
+
f->F2 = f->E2 + n + m2;
|
96
|
+
for (i = -m1; i < 0; ++i)
|
97
|
+
f->H[i] = f->E1[i] = f->E2[i] = f->F1[i] = f->F2[i] = WF_NEG_INF;
|
98
|
+
for (i = n; i < n + m1; ++i)
|
99
|
+
f->H[i] = f->E1[i] = f->E2[i] = f->F1[i] = f->F2[i] = WF_NEG_INF;
|
100
|
+
f->H -= lo, f->E1 -= lo, f->E2 -= lo, f->F1 -= lo, f->F2 -= lo; // such that f->H[lo] points to 0
|
101
|
+
}
|
102
|
+
|
103
|
+
static wf_stripe_t *wf_stripe_init(void *km, int32_t max_pen)
|
104
|
+
{
|
105
|
+
int32_t i;
|
106
|
+
wf_stripe_t *wf;
|
107
|
+
wf = Kcalloc(km, wf_stripe_t, 1);
|
108
|
+
wf->max_pen = max_pen;
|
109
|
+
wf->n = max_pen + 1;
|
110
|
+
wf->a = Kcalloc(km, wf_slice_t, wf->n);
|
111
|
+
wf->lo = wf->hi = 0;
|
112
|
+
for (i = 0; i < wf->n; ++i) {
|
113
|
+
wf_slice_t *f;
|
114
|
+
wf_stripe_add(km, wf, 0, 0);
|
115
|
+
f = &wf->a[wf->top];
|
116
|
+
f->H[0] = f->E1[0] = f->E2[0] = f->F1[0] = f->F2[0] = WF_NEG_INF;
|
117
|
+
}
|
118
|
+
wf->s = 0;
|
119
|
+
wf->a[wf->top].H[0] = -1;
|
120
|
+
return wf;
|
121
|
+
}
|
122
|
+
|
123
|
+
static void wf_stripe_destroy(void *km, wf_stripe_t *wf)
|
124
|
+
{
|
125
|
+
int32_t i;
|
126
|
+
for (i = 0; i < wf->n; ++i)
|
127
|
+
kfree(km, wf->a[i].mem);
|
128
|
+
kfree(km, wf->a);
|
129
|
+
kfree(km, wf);
|
130
|
+
}
|
131
|
+
|
132
|
+
static inline wf_slice_t *wf_stripe_get(const wf_stripe_t *wf, int32_t x)
|
133
|
+
{
|
134
|
+
int32_t y = wf->top - x;
|
135
|
+
if (y < 0) y += wf->n;
|
136
|
+
return &wf->a[y];
|
137
|
+
}
|
138
|
+
|
139
|
+
static inline int good_diag(int32_t d, int32_t k, int32_t tl, int32_t ql) // check if (d,k) falls within the DP matrix
|
140
|
+
{
|
141
|
+
return ((k >= -1 && k < tl) && (d + k >= -1 && d + k < ql));
|
142
|
+
}
|
143
|
+
|
144
|
+
static void wf_stripe_shrink(wf_stripe_t *wf, int32_t tl, int32_t ql)
|
145
|
+
{
|
146
|
+
int32_t j, d;
|
147
|
+
for (d = wf->lo; d <= wf->hi; ++d) {
|
148
|
+
for (j = 0; j < wf->n; ++j) {
|
149
|
+
wf_slice_t *p = &wf->a[(wf->top + 1 + j) % wf->n];
|
150
|
+
if (d < p->lo || d > p->hi) continue;
|
151
|
+
if (good_diag(d, p->H[d], tl, ql)) break;
|
152
|
+
if (good_diag(d, p->E1[d], tl, ql) || good_diag(d, p->F1[d], tl, ql)) break;
|
153
|
+
if (good_diag(d, p->E2[d], tl, ql) || good_diag(d, p->F2[d], tl, ql)) break;
|
154
|
+
}
|
155
|
+
if (j < wf->n) break; // stop when we see a "good diagonal" in the stripe
|
156
|
+
}
|
157
|
+
assert(d <= wf->hi); // should never happen
|
158
|
+
wf->lo = d;
|
159
|
+
for (d = wf->hi; d >= wf->lo; --d) {
|
160
|
+
for (j = 0; j < wf->n; ++j) {
|
161
|
+
wf_slice_t *p = &wf->a[(wf->top + 1 + j) % wf->n];
|
162
|
+
if (d < p->lo || d > p->hi) continue;
|
163
|
+
if (good_diag(d, p->H[d], tl, ql)) break;
|
164
|
+
if (good_diag(d, p->E1[d], tl, ql) || good_diag(d, p->F1[d], tl, ql)) break;
|
165
|
+
if (good_diag(d, p->E2[d], tl, ql) || good_diag(d, p->F2[d], tl, ql)) break;
|
166
|
+
}
|
167
|
+
if (j < wf->n) break;
|
168
|
+
}
|
169
|
+
assert(d >= wf->lo);
|
170
|
+
wf->hi = d;
|
171
|
+
}
|
172
|
+
|
173
|
+
typedef struct {
|
174
|
+
int32_t s, d;
|
175
|
+
} wf_chkpt_t;
|
176
|
+
|
177
|
+
/*
|
178
|
+
* Extend a diagonal along exact matches
|
179
|
+
*/
|
180
|
+
|
181
|
+
// pad strings with distinct characters
|
182
|
+
static void wf_pad_str(void *km, int32_t tl, const char *ts, int32_t ql, const char *qs, char **pts, char **pqs)
|
183
|
+
{
|
184
|
+
uint8_t t[256];
|
185
|
+
int32_t i, c1 = -1, c2 = -1;
|
186
|
+
char *s1, *s2;
|
187
|
+
*pts = *pqs = 0;
|
188
|
+
// collect all used characters
|
189
|
+
memset(t, 0, 256);
|
190
|
+
for (i = 0; i < tl; ++i)
|
191
|
+
if (t[(uint8_t)ts[i]] == 0)
|
192
|
+
t[(uint8_t)ts[i]] = 1;
|
193
|
+
for (i = 0; i < ql; ++i)
|
194
|
+
if (t[(uint8_t)qs[i]] == 0)
|
195
|
+
t[(uint8_t)qs[i]] = 1;
|
196
|
+
for (i = 0; i < 256; ++i)
|
197
|
+
if (t[i] == 0) {
|
198
|
+
if (c1 < 0) c1 = i;
|
199
|
+
else if (c2 < 0) c2 = i;
|
200
|
+
}
|
201
|
+
if (c1 < 0 || c2 < 0) return; // The two strings use >=255 characters. Unlikely for bio strings.
|
202
|
+
s1 = Kmalloc(km, char, tl + ql + 16); // the two strings are allocated together
|
203
|
+
s2 = s1 + tl + 8;
|
204
|
+
memcpy(s1, ts, tl);
|
205
|
+
for (i = tl; i < tl + 8; ++i) s1[i] = c1; // pad with c1
|
206
|
+
memcpy(s2, qs, ql);
|
207
|
+
for (i = ql; i < ql + 8; ++i) s2[i] = c2; // pad with c2
|
208
|
+
*pts = s1, *pqs = s2;
|
209
|
+
}
|
210
|
+
|
211
|
+
// Extend a diagonal along exact matches.
|
212
|
+
static inline int32_t wf_extend1_padded(const char *ts, const char *qs, int32_t k, int32_t d)
|
213
|
+
{
|
214
|
+
uint64_t cmp = 0;
|
215
|
+
const char *ts_ = ts + 1;
|
216
|
+
const char *qs_ = qs + d + 1;
|
217
|
+
while (1) {
|
218
|
+
uint64_t x = *(uint64_t*)(ts_ + k); // warning: unaligned memory access
|
219
|
+
uint64_t y = *(uint64_t*)(qs_ + k);
|
220
|
+
cmp = x ^ y;
|
221
|
+
if (cmp == 0) k += 8;
|
222
|
+
else break;
|
223
|
+
}
|
224
|
+
k += __builtin_ctzl(cmp) >> 3;
|
225
|
+
return k;
|
226
|
+
}
|
227
|
+
|
228
|
+
/*
|
229
|
+
* Core wf_next() routines
|
230
|
+
*/
|
231
|
+
|
232
|
+
// Force loop vectorization. Learned from WFA.
|
233
|
+
#if defined(__clang__)
|
234
|
+
#define PRAGMA_LOOP_VECTORIZE _Pragma("clang loop vectorize(enable)")
|
235
|
+
#elif defined(__GNUC__)
|
236
|
+
#define PRAGMA_LOOP_VECTORIZE _Pragma("GCC ivdep")
|
237
|
+
#else
|
238
|
+
#define PRAGMA_LOOP_VECTORIZE _Pragma("ivdep")
|
239
|
+
#endif
|
240
|
+
|
241
|
+
#define wf_max(a, b) ((a) >= (b)? (a) : (b))
|
242
|
+
|
243
|
+
static void wf_next_prep(void *km, const mwf_opt_t *opt, wf_stripe_t *wf, int32_t lo, int32_t hi,
|
244
|
+
int32_t **H, int32_t **E1, int32_t **F1, int32_t **E2, int32_t **F2,
|
245
|
+
const int32_t **pHx, const int32_t **pHo1, const int32_t **pHo2,
|
246
|
+
const int32_t **pE1, const int32_t **pF1, const int32_t **pE2, const int32_t **pF2)
|
247
|
+
{
|
248
|
+
const wf_slice_t *fx, *fo1, *fo2, *fe1, *fe2;
|
249
|
+
wf_slice_t *ft;
|
250
|
+
wf_stripe_add(km, wf, lo, hi);
|
251
|
+
ft = &wf->a[wf->top];
|
252
|
+
fx = wf_stripe_get(wf, opt->x);
|
253
|
+
fo1 = wf_stripe_get(wf, opt->o1 + opt->e1);
|
254
|
+
fo2 = wf_stripe_get(wf, opt->o2 + opt->e2);
|
255
|
+
fe1 = wf_stripe_get(wf, opt->e1);
|
256
|
+
fe2 = wf_stripe_get(wf, opt->e2);
|
257
|
+
*pHx = fx->H, *pHo1 = fo1->H, *pHo2 = fo2->H, *pE1 = fe1->E1, *pE2 = fe2->E2, *pF1 = fe1->F1, *pF2 = fe2->F2;
|
258
|
+
*H = ft->H, *E1 = ft->E1, *E2 = ft->E2, *F1 = ft->F1, *F2 = ft->F2;
|
259
|
+
}
|
260
|
+
|
261
|
+
static void wf_next_score(int32_t lo, int32_t hi, int32_t *H, int32_t *E1, int32_t *F1, int32_t *E2, int32_t *F2,
|
262
|
+
const int32_t *pHx, const int32_t *pHo1, const int32_t *pHo2,
|
263
|
+
const int32_t *pE1, const int32_t *pF1, const int32_t *pE2, const int32_t *pF2)
|
264
|
+
{
|
265
|
+
int32_t d;
|
266
|
+
PRAGMA_LOOP_VECTORIZE
|
267
|
+
for (d = lo; d <= hi; ++d) {
|
268
|
+
int32_t h, f, e;
|
269
|
+
E1[d] = wf_max(pHo1[d-1], pE1[d-1]);
|
270
|
+
E2[d] = wf_max(pHo2[d-1], pE2[d-1]);
|
271
|
+
e = wf_max(E1[d], E2[d]);
|
272
|
+
F1[d] = wf_max(pHo1[d+1], pF1[d+1]) + 1;
|
273
|
+
F2[d] = wf_max(pHo2[d+1], pF2[d+1]) + 1;
|
274
|
+
f = wf_max(F1[d], F2[d]);
|
275
|
+
h = wf_max(e, f);
|
276
|
+
H[d] = wf_max(pHx[d] + 1, h);
|
277
|
+
// if (H[d] >= -1) fprintf(stderr, "s=%d, d=%d, k=%d, (%d,%d)\n", wf->s, d, H[d], E1[d], F1[d]);
|
278
|
+
}
|
279
|
+
}
|
280
|
+
|
281
|
+
static void wf_next_tb(int32_t lo, int32_t hi, int32_t *H, int32_t *E1, int32_t *F1, int32_t *E2, int32_t *F2, uint8_t *ax,
|
282
|
+
const int32_t *pHx, const int32_t *pHo1, const int32_t *pHo2,
|
283
|
+
const int32_t *pE1, const int32_t *pF1, const int32_t *pE2, const int32_t *pF2)
|
284
|
+
{
|
285
|
+
int32_t d;
|
286
|
+
PRAGMA_LOOP_VECTORIZE
|
287
|
+
for (d = lo; d <= hi; ++d) {
|
288
|
+
int32_t h, f, e;
|
289
|
+
uint8_t x = 0, ze, zf, z;
|
290
|
+
x |= pHo1[d-1] >= pE1[d-1]? 0 : 0x08;
|
291
|
+
E1[d] = wf_max(pHo1[d-1], pE1[d-1]);
|
292
|
+
x |= pHo2[d-1] >= pE2[d-1]? 0 : 0x20;
|
293
|
+
E2[d] = wf_max(pHo2[d-1], pE2[d-1]);
|
294
|
+
ze = E1[d] >= E2[d]? 1 : 3;
|
295
|
+
e = wf_max(E1[d], E2[d]);
|
296
|
+
x |= pHo1[d+1] >= pF1[d+1]? 0 : 0x10;
|
297
|
+
F1[d] = wf_max(pHo1[d+1], pF1[d+1]) + 1;
|
298
|
+
x |= pHo2[d+1] >= pF2[d+1]? 0 : 0x40;
|
299
|
+
F2[d] = wf_max(pHo2[d+1], pF2[d+1]) + 1;
|
300
|
+
zf = F1[d] >= F2[d]? 2 : 4;
|
301
|
+
f = wf_max(F1[d], F2[d]);
|
302
|
+
z = e >= f? ze : zf;
|
303
|
+
h = wf_max(e, f);
|
304
|
+
z = pHx[d] + 1 >= h? 0 : z;
|
305
|
+
H[d] = wf_max(pHx[d] + 1, h);
|
306
|
+
ax[d] = x | z;
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
/*
|
311
|
+
* Core algorithm
|
312
|
+
*/
|
313
|
+
static void wf_next_basic(void *km, void *km_tb, const mwf_opt_t *opt, wf_stripe_t *wf, wf_tb_t *tb, int32_t lo, int32_t hi)
|
314
|
+
{
|
315
|
+
int32_t *H, *E1, *E2, *F1, *F2;
|
316
|
+
const int32_t *pHx, *pHo1, *pHo2, *pE1, *pE2, *pF1, *pF2;
|
317
|
+
wf_next_prep(km, opt, wf, lo, hi, &H, &E1, &F1, &E2, &F2, &pHx, &pHo1, &pHo2, &pE1, &pF1, &pE2, &pF2);
|
318
|
+
if (tb) {
|
319
|
+
uint8_t *ax;
|
320
|
+
ax = wf_tb_add(km_tb, tb, lo, hi)->x - lo;
|
321
|
+
wf_next_tb(lo, hi, H, E1, F1, E2, F2, ax, pHx, pHo1, pHo2, pE1, pF1, pE2, pF2);
|
322
|
+
} else {
|
323
|
+
wf_next_score(lo, hi, H, E1, F1, E2, F2, pHx, pHo1, pHo2, pE1, pF1, pE2, pF2);
|
324
|
+
}
|
325
|
+
if (H[lo] >= -1 || E1[lo] >= -1 || F1[lo] >= -1 || E2[lo] >= -1 || F2[lo] >= -1) wf->lo = lo;
|
326
|
+
if (H[hi] >= -1 || E1[hi] >= -1 || F1[hi] >= -1 || E2[hi] >= -1 || F2[hi] >= -1) wf->hi = hi;
|
327
|
+
}
|
328
|
+
|
329
|
+
static uint32_t *wf_traceback(void *km, const mwf_opt_t *opt, wf_tb_t *tb, int32_t t_end, const char *ts, int32_t q_end, const char *qs, int32_t last, int32_t *n_cigar)
|
330
|
+
{
|
331
|
+
wf_cigar_t cigar = {0,0,0};
|
332
|
+
int32_t i = q_end, k = t_end, s = tb->n - 1;
|
333
|
+
while (i >= 0 && k >= 0) {
|
334
|
+
int32_t k0 = k, j, x, state, ext;
|
335
|
+
if (last == 0) { // if the previous state is 0, check exact matches
|
336
|
+
while (i >= 0 && k >= 0 && qs[i] == ts[k])
|
337
|
+
--i, --k;
|
338
|
+
if (k0 - k > 0)
|
339
|
+
wf_cigar_push1(km, &cigar, 7, k0 - k);
|
340
|
+
if (i < 0 || k < 0) break;
|
341
|
+
}
|
342
|
+
assert(s >= 0);
|
343
|
+
j = i - k - tb->a[s].lo;
|
344
|
+
assert(j <= tb->a[s].hi - tb->a[s].lo);
|
345
|
+
x = tb->a[s].x[j];
|
346
|
+
state = last == 0? x&7 : last;
|
347
|
+
ext = state > 0? x>>(state+2)&1 : 0; // whether an extension
|
348
|
+
//fprintf(stderr, "s=%d, %d->%d, ext=%d%d%d%d, i=%d, k=%d\n", s, last, state, x>>3&1, x>>4&1, x>>5&1, x>>6&1, i, k);
|
349
|
+
if (state == 0) {
|
350
|
+
wf_cigar_push1(km, &cigar, 8, 1);
|
351
|
+
--i, --k, s -= opt->x;
|
352
|
+
} else if (state == 1) {
|
353
|
+
wf_cigar_push1(km, &cigar, 1, 1);
|
354
|
+
--i, s -= ext? opt->e1 : opt->o1 + opt->e1;
|
355
|
+
} else if (state == 3) {
|
356
|
+
wf_cigar_push1(km, &cigar, 1, 1);
|
357
|
+
--i, s -= ext? opt->e2 : opt->o2 + opt->e2;
|
358
|
+
} else if (state == 2) {
|
359
|
+
wf_cigar_push1(km, &cigar, 2, 1);
|
360
|
+
--k, s -= ext? opt->e1 : opt->o1 + opt->e1;
|
361
|
+
} else if (state == 4) {
|
362
|
+
wf_cigar_push1(km, &cigar, 2, 1);
|
363
|
+
--k, s -= ext? opt->e2 : opt->o2 + opt->e2;
|
364
|
+
} else abort();
|
365
|
+
last = state > 0 && ext? state : 0;
|
366
|
+
}
|
367
|
+
if (opt->flag&MWF_F_DEBUG) fprintf(stderr, "s0=%d, s=%d, i=%d, k=%d\n", tb->n-1, s, i, k);
|
368
|
+
if (i >= 0) wf_cigar_push1(km, &cigar, 1, i + 1);
|
369
|
+
else if (k >= 0) wf_cigar_push1(km, &cigar, 2, k + 1);
|
370
|
+
for (i = 0; i < cigar.n>>1; ++i) { // reverse to the input order
|
371
|
+
uint32_t t = cigar.cigar[i];
|
372
|
+
cigar.cigar[i] = cigar.cigar[cigar.n - i - 1];
|
373
|
+
cigar.cigar[cigar.n - i - 1] = t;
|
374
|
+
}
|
375
|
+
*n_cigar = cigar.n;
|
376
|
+
return cigar.cigar;
|
377
|
+
}
|
378
|
+
|
379
|
+
// pts and pqs MUST BE padded with wf_pad_str()
|
380
|
+
static void mwf_wfa_core(void *km, const mwf_opt_t *opt, int32_t tl, const char *pts, int32_t ql, const char *pqs, int32_t n_seg, wf_chkpt_t *seg, mwf_rst_t *r)
|
381
|
+
{
|
382
|
+
int32_t max_pen, sid, is_tb = !!(opt->flag&MWF_F_CIGAR), last_state = 0, stopped = 0;
|
383
|
+
wf_stripe_t *wf;
|
384
|
+
wf_tb_t tb = {0,0,0};
|
385
|
+
void *km_tb, *km_st;
|
386
|
+
|
387
|
+
memset(r, 0, sizeof(*r));
|
388
|
+
km_tb = is_tb && !(opt->flag&MWF_F_NO_KALLOC)? km_init2(km, 0) : 0;
|
389
|
+
km_st = !(opt->flag&MWF_F_NO_KALLOC)? km_init2(km, 0) : 0;
|
390
|
+
max_pen = opt->x;
|
391
|
+
max_pen = max_pen > opt->o1 + opt->e1? max_pen : opt->o1 + opt->e1;
|
392
|
+
max_pen = max_pen > opt->o2 + opt->e2? max_pen : opt->o2 + opt->e2;
|
393
|
+
wf = wf_stripe_init(km_st, max_pen);
|
394
|
+
assert(pts);
|
395
|
+
|
396
|
+
sid = 0;
|
397
|
+
while (1) {
|
398
|
+
wf_slice_t *p = &wf->a[wf->top];
|
399
|
+
int32_t d, lo, hi, *H = p->H;
|
400
|
+
for (d = p->lo; d <= p->hi; ++d) {
|
401
|
+
int32_t k = 0;
|
402
|
+
if (H[d] < -1 || d + H[d] < -1 || H[d] >= tl || d + H[d] >= ql) continue;
|
403
|
+
k = wf_extend1_padded(pts, pqs, H[d], d);
|
404
|
+
//fprintf(stderr, "[s=%d] [%d,%d]:%d %d->%d,%d,%d,%d,%d\n", wf->s, p->lo, p->hi, d, H[d], k, wf->a[wf->top].E1[d], wf->a[wf->top].F1[d], wf->a[wf->top].E2[d], wf->a[wf->top].F2[d]);
|
405
|
+
if (k == tl - 1 && d + k == ql - 1) {
|
406
|
+
if (k == H[d] && is_tb)
|
407
|
+
last_state = tb.a[tb.n-1].x[d - tb.a[tb.n-1].lo] & 7;
|
408
|
+
break;
|
409
|
+
}
|
410
|
+
H[d] = k;
|
411
|
+
}
|
412
|
+
if (d <= p->hi) break;
|
413
|
+
if (is_tb && seg && sid < n_seg && seg[sid].s == wf->s) {
|
414
|
+
assert(seg[sid].d >= wf->lo && seg[sid].d <= wf->hi);
|
415
|
+
wf->lo = wf->hi = seg[sid++].d;
|
416
|
+
}
|
417
|
+
lo = wf->lo > -tl? wf->lo - 1 : -tl;
|
418
|
+
hi = wf->hi < ql? wf->hi + 1 : ql;
|
419
|
+
wf_next_basic(km_st, km_tb, opt, wf, is_tb? &tb : 0, lo, hi);
|
420
|
+
if ((wf->s&0xff) == 0) wf_stripe_shrink(wf, tl, ql);
|
421
|
+
r->n_iter += hi - lo + 1;
|
422
|
+
if ((opt->max_iter > 0 && r->n_iter > opt->max_iter) || (opt->max_s > 0 && wf->s > opt->max_s)) {
|
423
|
+
stopped = 1;
|
424
|
+
break;
|
425
|
+
}
|
426
|
+
}
|
427
|
+
r->s = stopped? -1 : wf->s;
|
428
|
+
if (is_tb && !stopped)
|
429
|
+
r->cigar = wf_traceback(km, opt, &tb, tl-1, pts, ql-1, pqs, last_state, &r->n_cigar);
|
430
|
+
if (km_st == 0) wf_stripe_destroy(km_st, wf);
|
431
|
+
else km_destroy(km_st);
|
432
|
+
km_destroy(km_tb);
|
433
|
+
if (is_tb && !stopped)
|
434
|
+
r->cigar = (uint32_t*)krelocate(km, r->cigar, r->n_cigar * sizeof(*r->cigar));
|
435
|
+
}
|
436
|
+
|
437
|
+
/*
|
438
|
+
* Low-memory mode
|
439
|
+
*/
|
440
|
+
typedef struct {
|
441
|
+
int32_t n, n_intv, max_s;
|
442
|
+
int32_t *x;
|
443
|
+
uint64_t *intv;
|
444
|
+
} wf_ss_t; // snapshot
|
445
|
+
|
446
|
+
typedef struct {
|
447
|
+
int32_t n, m;
|
448
|
+
wf_ss_t *a;
|
449
|
+
} wf_sss_t;
|
450
|
+
|
451
|
+
static void wf_snapshot1(void *km, wf_stripe_t *sf, wf_ss_t *ss)
|
452
|
+
{
|
453
|
+
int32_t j, k, t;
|
454
|
+
ss->n = 0, ss->max_s = sf->s;
|
455
|
+
for (j = 0; j < sf->n; ++j)
|
456
|
+
ss->n += 5 * (sf->a[j].hi - sf->a[j].lo + 1);
|
457
|
+
ss->x = Kmalloc(km, int32_t, ss->n);
|
458
|
+
ss->n_intv = sf->n;
|
459
|
+
ss->intv = Kmalloc(km, uint64_t, ss->n_intv);
|
460
|
+
for (j = 0, t = 0; j < sf->n; ++j) {
|
461
|
+
wf_slice_t *p;
|
462
|
+
k = (sf->top + 1 + j) % sf->n;
|
463
|
+
p = &sf->a[k];
|
464
|
+
ss->intv[j] = (uint64_t)p->lo << 32 | (p->hi - p->lo + 1) * 5;
|
465
|
+
for (k = p->lo; k <= p->hi; ++k) {
|
466
|
+
ss->x[t] = p->H[k], p->H[k] = t++;
|
467
|
+
ss->x[t] = p->E1[k], p->E1[k] = t++;
|
468
|
+
ss->x[t] = p->F1[k], p->F1[k] = t++;
|
469
|
+
ss->x[t] = p->E2[k], p->E2[k] = t++;
|
470
|
+
ss->x[t] = p->F2[k], p->F2[k] = t++;
|
471
|
+
}
|
472
|
+
}
|
473
|
+
assert(t == ss->n);
|
474
|
+
}
|
475
|
+
|
476
|
+
static void wf_snapshot(void *km, wf_sss_t *sss, wf_stripe_t *sf)
|
477
|
+
{
|
478
|
+
if (sss->n == sss->m) {
|
479
|
+
sss->m += (sss->m>>1) + 8;
|
480
|
+
sss->a = Krealloc(km, wf_ss_t, sss->a, sss->m);
|
481
|
+
}
|
482
|
+
wf_snapshot1(km, sf, &sss->a[sss->n++]);
|
483
|
+
}
|
484
|
+
|
485
|
+
static void wf_snapshot_free(void *km, wf_sss_t *sss)
|
486
|
+
{
|
487
|
+
int32_t j;
|
488
|
+
for (j = 0; j < sss->n; ++j) {
|
489
|
+
kfree(km, sss->a[j].x);
|
490
|
+
kfree(km, sss->a[j].intv);
|
491
|
+
}
|
492
|
+
kfree(km, sss->a);
|
493
|
+
}
|
494
|
+
|
495
|
+
static void wf_next_seg(void *km, const mwf_opt_t *opt, uint8_t *xbuf, wf_stripe_t *wf, wf_stripe_t *sf, int32_t lo, int32_t hi)
|
496
|
+
{
|
497
|
+
int32_t d, *H, *E1, *E2, *F1, *F2;
|
498
|
+
const int32_t *pHx, *pHo1, *pHo2, *pE1, *pE2, *pF1, *pF2;
|
499
|
+
uint8_t *ax = xbuf - lo;
|
500
|
+
|
501
|
+
wf_next_prep(km, opt, wf, lo, hi, &H, &E1, &F1, &E2, &F2, &pHx, &pHo1, &pHo2, &pE1, &pF1, &pE2, &pF2);
|
502
|
+
wf_next_tb(lo, hi, H, E1, F1, E2, F2, ax, pHx, pHo1, pHo2, pE1, pF1, pE2, pF2);
|
503
|
+
wf_next_prep(km, opt, sf, lo, hi, &H, &E1, &F1, &E2, &F2, &pHx, &pHo1, &pHo2, &pE1, &pF1, &pE2, &pF2);
|
504
|
+
PRAGMA_LOOP_VECTORIZE
|
505
|
+
for (d = lo; d <= hi; ++d) { // FIXME: merge this loop into the loop in wf_next_tb(). I tried but couldn't make clang vectorize.
|
506
|
+
uint8_t x = ax[d];
|
507
|
+
int32_t a, b, e1, f1, e2, f2, h;
|
508
|
+
a = pHo1[d-1], b = pE1[d-1];
|
509
|
+
e1 = E1[d] = (x&0x08) == 0? a : b;
|
510
|
+
a = pHo1[d+1], b = pF1[d+1];
|
511
|
+
f1 = F1[d] = (x&0x10) == 0? a : b;
|
512
|
+
a = pHo2[d-1], b = pE2[d-1];
|
513
|
+
e2 = E2[d] = (x&0x20) == 0? a : b;
|
514
|
+
a = pHo2[d+1], b = pF2[d+1];
|
515
|
+
f2 = F2[d] = (x&0x40) == 0? a : b;
|
516
|
+
x &= 7;
|
517
|
+
h = pHx[d];
|
518
|
+
h = x == 1? e1 : h;
|
519
|
+
h = x == 2? f1 : h;
|
520
|
+
h = x == 3? e2 : h;
|
521
|
+
h = x == 4? f2 : h;
|
522
|
+
H[d] = h;
|
523
|
+
}
|
524
|
+
if (H[lo] >= -1 || E1[lo] >= -1 || F1[lo] >= -1 || E2[lo] >= -1 || F2[lo] >= -1) wf->lo = lo;
|
525
|
+
if (H[hi] >= -1 || E1[hi] >= -1 || F1[hi] >= -1 || E2[hi] >= -1 || F2[hi] >= -1) wf->hi = hi;
|
526
|
+
}
|
527
|
+
|
528
|
+
static wf_chkpt_t *wf_traceback_seg(void *km, wf_sss_t *sss, int32_t last, int32_t *n_seg)
|
529
|
+
{
|
530
|
+
int32_t j;
|
531
|
+
wf_chkpt_t *seg;
|
532
|
+
*n_seg = sss->n;
|
533
|
+
seg = Kmalloc(km, wf_chkpt_t, sss->n);
|
534
|
+
for (j = sss->n - 1; j >= 0; --j) {
|
535
|
+
int32_t k, m;
|
536
|
+
wf_ss_t *p = &sss->a[j];
|
537
|
+
for (k = 0, m = 0; k < p->n_intv; ++k) {
|
538
|
+
if (last >= m && last < m + (int32_t)p->intv[k])
|
539
|
+
break;
|
540
|
+
m += (int32_t)p->intv[k];
|
541
|
+
}
|
542
|
+
assert(k < p->n_intv);
|
543
|
+
seg[j].s = p->max_s - (p->n_intv - k - 1);
|
544
|
+
seg[j].d = (int32_t)(p->intv[k]>>32) + (last - m) / 5;
|
545
|
+
last = p->x[last];
|
546
|
+
}
|
547
|
+
assert(last == -1);
|
548
|
+
return seg;
|
549
|
+
}
|
550
|
+
|
551
|
+
wf_chkpt_t *mwf_wfa_seg(void *km, const mwf_opt_t *opt, int32_t tl, const char *pts, int32_t ql, const char *pqs, int32_t *n_seg_)
|
552
|
+
{
|
553
|
+
int32_t max_pen, last, n_seg;
|
554
|
+
wf_stripe_t *wf, *sf;
|
555
|
+
wf_sss_t sss = {0,0,0};
|
556
|
+
uint8_t *xbuf;
|
557
|
+
wf_chkpt_t *seg;
|
558
|
+
void *km_st;
|
559
|
+
|
560
|
+
km_st = !(opt->flag&MWF_F_NO_KALLOC)? km_init2(km, 0) : 0;
|
561
|
+
max_pen = opt->x;
|
562
|
+
max_pen = max_pen > opt->o1 + opt->e1? max_pen : opt->o1 + opt->e1;
|
563
|
+
max_pen = max_pen > opt->o2 + opt->e2? max_pen : opt->o2 + opt->e2;
|
564
|
+
xbuf = Kcalloc(km_st, uint8_t, tl + ql + 1);
|
565
|
+
wf = wf_stripe_init(km_st, max_pen);
|
566
|
+
sf = wf_stripe_init(km_st, max_pen);
|
567
|
+
assert(pts);
|
568
|
+
|
569
|
+
while (1) {
|
570
|
+
wf_slice_t *p = &wf->a[wf->top];
|
571
|
+
int32_t d, lo, hi, *H = p->H;
|
572
|
+
for (d = p->lo; d <= p->hi; ++d) {
|
573
|
+
int32_t k;
|
574
|
+
if (H[d] < -1 || d + H[d] < -1 || H[d] >= tl || d + H[d] >= ql) continue;
|
575
|
+
k = wf_extend1_padded(pts, pqs, H[d], d);
|
576
|
+
if (k == tl - 1 && d + k == ql - 1) {
|
577
|
+
last = sf->a[sf->top].H[d];
|
578
|
+
break;
|
579
|
+
}
|
580
|
+
H[d] = k;
|
581
|
+
}
|
582
|
+
if (d <= p->hi) break;
|
583
|
+
lo = wf->lo > -tl? wf->lo - 1 : -tl;
|
584
|
+
hi = wf->hi < ql? wf->hi + 1 : ql;
|
585
|
+
if ((wf->s + 1) % opt->step == 0)
|
586
|
+
wf_snapshot(km_st, &sss, sf);
|
587
|
+
wf_next_seg(km_st, opt, xbuf, wf, sf, lo, hi);
|
588
|
+
if ((wf->s&0xff) == 0) wf_stripe_shrink(wf, tl, ql);
|
589
|
+
}
|
590
|
+
seg = wf_traceback_seg(km, &sss, last, &n_seg);
|
591
|
+
if (km_st == 0) {
|
592
|
+
wf_snapshot_free(km_st, &sss);
|
593
|
+
wf_stripe_destroy(km_st, wf);
|
594
|
+
wf_stripe_destroy(km_st, sf);
|
595
|
+
kfree(km_st, xbuf);
|
596
|
+
} else km_destroy(km_st);
|
597
|
+
|
598
|
+
seg = (wf_chkpt_t*)krelocate(km, seg, n_seg * sizeof(*seg));
|
599
|
+
*n_seg_ = n_seg;
|
600
|
+
return seg;
|
601
|
+
}
|
602
|
+
|
603
|
+
void mwf_wfa_exact(void *km, const mwf_opt_t *opt, int32_t tl, const char *ts, int32_t ql, const char *qs, mwf_rst_t *r)
|
604
|
+
{
|
605
|
+
int32_t n_seg = 0;
|
606
|
+
wf_chkpt_t *seg = 0;
|
607
|
+
char *pts, *pqs;
|
608
|
+
|
609
|
+
wf_pad_str(km, tl, ts, ql, qs, &pts, &pqs);
|
610
|
+
if (opt->step > 0)
|
611
|
+
seg = mwf_wfa_seg(km, opt, tl, pts, ql, pqs, &n_seg);
|
612
|
+
mwf_wfa_core(km, opt, tl, pts, ql, pqs, n_seg, seg, r);
|
613
|
+
kfree(km, seg);
|
614
|
+
kfree(km, pts);
|
615
|
+
}
|
616
|
+
|
617
|
+
/*
|
618
|
+
* Heuristics
|
619
|
+
*/
|
620
|
+
static int32_t mg_lis_64(void *km, int32_t n, const uint64_t *a, int32_t *b)
|
621
|
+
{
|
622
|
+
int32_t i, k, L = 0, *M, *P = b;
|
623
|
+
KMALLOC(km, M, n+1);
|
624
|
+
for (i = 0; i < n; ++i) {
|
625
|
+
int32_t lo = 1, hi = L, newL;
|
626
|
+
while (lo <= hi) {
|
627
|
+
int32_t mid = (lo + hi + 1) >> 1;
|
628
|
+
if (a[M[mid]] < a[i]) lo = mid + 1;
|
629
|
+
else hi = mid - 1;
|
630
|
+
}
|
631
|
+
newL = lo, P[i] = M[newL - 1], M[newL] = i;
|
632
|
+
if (newL > L) L = newL;
|
633
|
+
}
|
634
|
+
k = M[L];
|
635
|
+
memcpy(M, P, n * sizeof(int32_t));
|
636
|
+
for (i = L - 1; i >= 0; --i) b[i] = k, k = M[k];
|
637
|
+
kfree(km, M);
|
638
|
+
return L;
|
639
|
+
}
|
640
|
+
|
641
|
+
extern void radix_sort_gfa64(uint64_t*, uint64_t*);
|
642
|
+
extern unsigned char seq_nt4_table[256];
|
643
|
+
|
644
|
+
static int32_t mg_fc_kmer(int32_t len, const char *seq, int32_t rid, int32_t k, uint64_t *a)
|
645
|
+
{
|
646
|
+
int32_t i, l, n;
|
647
|
+
uint64_t x, mask = (1ULL<<k*2) - 1;
|
648
|
+
for (i = l = 0, x = 0, n = 0; i < len; ++i) {
|
649
|
+
int32_t c = seq_nt4_table[(uint8_t)seq[i]];
|
650
|
+
if (c < 4) {
|
651
|
+
x = (x << 2 | c) & mask;
|
652
|
+
if (++l >= k) a[n++] = (x<<1|rid) << 32 | i;
|
653
|
+
} else l = 0, x = 0;
|
654
|
+
}
|
655
|
+
return n;
|
656
|
+
}
|
657
|
+
|
658
|
+
static uint64_t *mg_chain(void *km, int32_t l1, const char *s1, int32_t l2, const char *s2, int32_t k, int32_t max_occ, int32_t *n_lis_)
|
659
|
+
{
|
660
|
+
int32_t i, n_a, n_b, m_b, i0, n_lis, *lis;
|
661
|
+
uint64_t *a, *b;
|
662
|
+
|
663
|
+
*n_lis_ = 0;
|
664
|
+
if (l1 < k || l2 < k) return 0;
|
665
|
+
assert(k >= 2 && k <= 15);
|
666
|
+
|
667
|
+
// collect k-mers
|
668
|
+
KMALLOC(km, a, l1 + l2);
|
669
|
+
n_a = mg_fc_kmer(l1, s1, 0, k, a);
|
670
|
+
n_a += mg_fc_kmer(l2, s2, 1, k, &a[n_a]);
|
671
|
+
radix_sort_gfa64(a, a + n_a);
|
672
|
+
|
673
|
+
// collect k-mer matches
|
674
|
+
n_b = m_b = 0, b = 0;
|
675
|
+
for (i0 = 0, i = 1; i <= n_a; ++i) {
|
676
|
+
if (i == n_a || a[i0]>>33 != a[i]>>33) {
|
677
|
+
if (i - i0 >= 2) {
|
678
|
+
int32_t j, s, t;
|
679
|
+
for (j = i0; j < i && (a[j]>>32&1) == 0; ++j) {}
|
680
|
+
if (j > i0 && j < i && j - i0 <= max_occ && i - j <= max_occ) {
|
681
|
+
for (s = i0; s < j; ++s)
|
682
|
+
for (t = j; t < i; ++t) {
|
683
|
+
if (n_b == m_b) KEXPAND(km, b, m_b);
|
684
|
+
b[n_b++] = a[s]<<32 | (uint32_t)a[t];
|
685
|
+
}
|
686
|
+
}
|
687
|
+
}
|
688
|
+
i0 = i;
|
689
|
+
}
|
690
|
+
}
|
691
|
+
kfree(km, a);
|
692
|
+
|
693
|
+
// find co-linear chain with LIS
|
694
|
+
radix_sort_gfa64(b, b + n_b);
|
695
|
+
for (i = 0; i < n_b; ++i)
|
696
|
+
b[i] = b[i]>>32 | b[i]<<32;
|
697
|
+
KMALLOC(km, lis, n_b);
|
698
|
+
n_lis = mg_lis_64(km, n_b, b, lis);
|
699
|
+
a = Kmalloc(km, uint64_t, n_lis);
|
700
|
+
for (i = 0; i < n_lis; ++i) a[i] = b[lis[i]];
|
701
|
+
kfree(km, lis);
|
702
|
+
kfree(km, b);
|
703
|
+
b = Kmalloc(km, uint64_t, n_lis);
|
704
|
+
memcpy(b, a, sizeof(uint64_t) * n_lis);
|
705
|
+
kfree(km, a);
|
706
|
+
*n_lis_ = n_lis;
|
707
|
+
for (i = 0; i < n_lis; ++i) // switch back, such that seq1 on the high bits
|
708
|
+
b[i] = b[i]>>32 | b[i]<<32;
|
709
|
+
return b;
|
710
|
+
}
|
711
|
+
|
712
|
+
static double mwf_ksim(void *km, int32_t l1, const char *s1, int32_t l2, const char *s2, int32_t k)
|
713
|
+
{
|
714
|
+
int32_t i, i0, j, n_a, n1 = 0, n2 = 0, t1 = 0, t2 = 0;
|
715
|
+
double p1, p2;
|
716
|
+
uint64_t *a;
|
717
|
+
if (l1 < k || l2 < k) return 0;
|
718
|
+
assert(k >= 2 && k <= 15);
|
719
|
+
KMALLOC(km, a, l1 + l2);
|
720
|
+
n_a = mg_fc_kmer(l1, s1, 0, k, a);
|
721
|
+
n_a += mg_fc_kmer(l2, s2, 1, k, &a[n_a]);
|
722
|
+
radix_sort_gfa64(a, a + n_a);
|
723
|
+
for (i0 = 0, i = 1; i <= n_a; ++i) {
|
724
|
+
if (i == n_a || a[i0]>>33 != a[i]>>33) {
|
725
|
+
int32_t m1, m2, min;
|
726
|
+
for (j = i0; j < i && (a[j]>>32&1) == 0; ++j) {}
|
727
|
+
m1 = j - i0, m2 = i - j;
|
728
|
+
min = m1 < m2? m1 : m2;
|
729
|
+
n1 += m1, n2 += m2;
|
730
|
+
if (m1 > 0 && m2 > 0)
|
731
|
+
t1 += min, t2 += min;
|
732
|
+
i0 = i;
|
733
|
+
}
|
734
|
+
}
|
735
|
+
kfree(km, a);
|
736
|
+
p1 = (double)t1 / n1, p2 = (double)t2 / n2;
|
737
|
+
return p1 > p2? p1 : p2;
|
738
|
+
}
|
739
|
+
|
740
|
+
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
|
741
|
+
|
742
|
+
static void wf_cigar_push(void *km, wf_cigar_t *c, int32_t n_cigar, const uint32_t *cigar)
|
743
|
+
{
|
744
|
+
if (n_cigar == 0) return;
|
745
|
+
wf_cigar_push1(km, c, cigar[0]&0xf, cigar[0]>>4);
|
746
|
+
if (c->n + n_cigar - 1 > c->m) {
|
747
|
+
c->m = c->n + n_cigar - 1;
|
748
|
+
kroundup32(c->m);
|
749
|
+
c->cigar = Krealloc(km, uint32_t, c->cigar, c->m);
|
750
|
+
}
|
751
|
+
memcpy(&c->cigar[c->n], &cigar[1], sizeof(*cigar) * (n_cigar - 1));
|
752
|
+
c->n += n_cigar - 1;
|
753
|
+
}
|
754
|
+
|
755
|
+
static int32_t wf_anchor_filter(int32_t n, uint64_t *a, int32_t tl, int32_t ql, int32_t k, int32_t min_l)
|
756
|
+
{
|
757
|
+
int32_t i, st, x0, y0, x1, y1, j, l, m;
|
758
|
+
for (i = 0, x0 = y0 = x1 = y1 = 0, st = -1, l = 0; i <= n; ++i) {
|
759
|
+
int32_t x, y;
|
760
|
+
if (i == n) x = tl, y = ql;
|
761
|
+
else x = (int32_t)(a[i]>>32) + 1, y = (int32_t)a[i] + 1;
|
762
|
+
if (x - x0 != y - y0) {
|
763
|
+
//fprintf(stderr, "X\t%d\t(%d,%d) -> (%d,%d)\n", l, x0, y0, x, y);
|
764
|
+
if (l < min_l)
|
765
|
+
for (j = st > 0? st : 0; j < i; ++j)
|
766
|
+
a[j] = 0;
|
767
|
+
x0 = x, y0 = y, st = i, l = k;
|
768
|
+
} else l += x - x1;
|
769
|
+
x1 = x, y1 = y;
|
770
|
+
}
|
771
|
+
for (i = 0, m = 0; i < n; ++i)
|
772
|
+
if (a[i] != 0) a[m++] = a[i];
|
773
|
+
return m;
|
774
|
+
}
|
775
|
+
|
776
|
+
void mwf_wfa_chain(void *km, const mwf_opt_t *opt, int32_t tl, const char *ts, int32_t ql, const char *qs, mwf_rst_t *r)
|
777
|
+
{
|
778
|
+
int32_t n_a, i, x0, y0;
|
779
|
+
uint64_t *a;
|
780
|
+
void *km_wfa;
|
781
|
+
wf_cigar_t c = {0,0,0};
|
782
|
+
|
783
|
+
km_wfa = !(opt->flag&MWF_F_NO_KALLOC)? km_init2(km, 0) : 0;
|
784
|
+
a = mg_chain(km_wfa, tl, ts, ql, qs, opt->kmer, opt->max_occ, &n_a);
|
785
|
+
n_a = wf_anchor_filter(n_a, a, tl, ql, opt->kmer, opt->min_len);
|
786
|
+
r->s = 0;
|
787
|
+
for (i = 0, x0 = y0 = 0; i <= n_a; ++i) {
|
788
|
+
int32_t x1, y1;
|
789
|
+
if (i == n_a) x1 = tl, y1 = ql;
|
790
|
+
else x1 = (int32_t)(a[i]>>32) + 1, y1 = (int32_t)a[i] + 1;
|
791
|
+
if (i < n_a && x1 - x0 == y1 - y0 && x1 - x0 <= opt->kmer) {
|
792
|
+
if (opt->flag&MWF_F_CIGAR)
|
793
|
+
wf_cigar_push1(km, &c, 7, x1 - x0);
|
794
|
+
} else if (x0 < x1 && y0 < y1) {
|
795
|
+
if (x1 - x0 >= 10000 && y1 - y0 >= 10000 && mwf_ksim(km, x1 - x0, &ts[x0], y1 - y0, &qs[y0], opt->kmer) < 0.02) {
|
796
|
+
if (opt->flag&MWF_F_CIGAR) {
|
797
|
+
wf_cigar_push1(km, &c, 2, x1 - x0);
|
798
|
+
wf_cigar_push1(km, &c, 1, y1 - y0);
|
799
|
+
}
|
800
|
+
r->s += opt->o2 * 2 + opt->e2 * ((x1 - x0) + (y1 - y0));
|
801
|
+
} else {
|
802
|
+
mwf_rst_t q;
|
803
|
+
mwf_wfa_exact(km_wfa, opt, x1 - x0, &ts[x0], y1 - y0, &qs[y0], &q);
|
804
|
+
if (opt->flag&MWF_F_CIGAR)
|
805
|
+
wf_cigar_push(km, &c, q.n_cigar, q.cigar);
|
806
|
+
r->s += q.s;
|
807
|
+
kfree(km_wfa, q.cigar);
|
808
|
+
}
|
809
|
+
} else if (x0 < x1) {
|
810
|
+
wf_cigar_push1(km, &c, 2, x1 - x0);
|
811
|
+
r->s += opt->o2 + (x1 - x0) * opt->e2 < opt->o1 + (x1 - x0) * opt->e1? opt->o2 + (x1 - x0) * opt->e2 : opt->o1 + (x1 - x0) * opt->e1;
|
812
|
+
} else if (y0 < y1) {
|
813
|
+
wf_cigar_push1(km, &c, 1, y1 - y0);
|
814
|
+
r->s += opt->o2 + (y1 - y0) * opt->e2 < opt->o1 + (y1 - y0) * opt->e1? opt->o2 + (y1 - y0) * opt->e2 : opt->o1 + (y1 - y0) * opt->e1;
|
815
|
+
}
|
816
|
+
x0 = x1, y0 = y1;
|
817
|
+
}
|
818
|
+
if (km_wfa == 0) kfree(km_wfa, a);
|
819
|
+
km_destroy(km_wfa);
|
820
|
+
r->n_cigar = c.n, r->cigar = c.cigar;
|
821
|
+
r->cigar = (uint32_t*)krelocate(km, r->cigar, r->n_cigar * sizeof(*r->cigar));
|
822
|
+
}
|
823
|
+
|
824
|
+
void mwf_wfa_auto(void *km, const mwf_opt_t *opt0, int32_t tl, const char *ts, int32_t ql, const char *qs, mwf_rst_t *r)
|
825
|
+
{
|
826
|
+
mwf_opt_t opt = *opt0;
|
827
|
+
opt.step = 0, opt.max_iter = 100000000;
|
828
|
+
mwf_wfa_exact(km, &opt, tl, ts, ql, qs, r);
|
829
|
+
if (r->s < 0) {
|
830
|
+
if (opt.flag & MWF_F_CIGAR) opt.step = 5000;
|
831
|
+
opt.max_iter = -1;
|
832
|
+
mwf_wfa_chain(km, &opt, tl, ts, ql, qs, r);
|
833
|
+
}
|
834
|
+
}
|