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,617 @@
|
|
1
|
+
#include <assert.h>
|
2
|
+
#include <string.h>
|
3
|
+
#include <stdio.h>
|
4
|
+
#include "gfa-priv.h"
|
5
|
+
#include "kalloc.h"
|
6
|
+
#include "ksort.h"
|
7
|
+
#include "khashl.h" // make it compatible with kalloc
|
8
|
+
#include "kdq.h"
|
9
|
+
#include "kvec-km.h"
|
10
|
+
|
11
|
+
int gfa_ed_dbg = 0;
|
12
|
+
|
13
|
+
/***************
|
14
|
+
* Preparation *
|
15
|
+
***************/
|
16
|
+
|
17
|
+
void gfa_edopt_init(gfa_edopt_t *opt)
|
18
|
+
{
|
19
|
+
memset(opt, 0, sizeof(gfa_edopt_t));
|
20
|
+
opt->bw_dyn = opt->max_lag = opt->s_term = -1;
|
21
|
+
opt->max_chk = 1000;
|
22
|
+
}
|
23
|
+
|
24
|
+
gfa_edseq_t *gfa_edseq_init(const gfa_t *g)
|
25
|
+
{
|
26
|
+
uint32_t i, n_vtx = gfa_n_vtx(g);
|
27
|
+
gfa_edseq_t *es;
|
28
|
+
GFA_MALLOC(es, n_vtx);
|
29
|
+
for (i = 0; i < g->n_seg; ++i) {
|
30
|
+
const gfa_seg_t *s = &g->seg[i];
|
31
|
+
char *t;
|
32
|
+
int32_t j;
|
33
|
+
GFA_MALLOC(t, s->len + 1);
|
34
|
+
for (j = 0; j < s->len; ++j)
|
35
|
+
t[s->len - j - 1] = gfa_comp_table[(uint8_t)s->seq[j]];
|
36
|
+
t[s->len] = 0;
|
37
|
+
es[i<<1].seq = (char*)s->seq;
|
38
|
+
es[i<<1|1].seq = t;
|
39
|
+
es[i<<1].len = es[i<<1|1].len = s->len;
|
40
|
+
}
|
41
|
+
return es;
|
42
|
+
}
|
43
|
+
|
44
|
+
void gfa_edseq_destroy(int32_t n_seg, gfa_edseq_t *es)
|
45
|
+
{
|
46
|
+
int32_t i;
|
47
|
+
for (i = 0; i < n_seg; ++i)
|
48
|
+
free((char*)es[i<<1|1].seq);
|
49
|
+
free(es);
|
50
|
+
}
|
51
|
+
|
52
|
+
/*****************
|
53
|
+
* Edit distance *
|
54
|
+
*****************/
|
55
|
+
|
56
|
+
#define GWF_DIAG_SHIFT 0x40000000
|
57
|
+
|
58
|
+
static inline uint64_t gwf_gen_vd(uint32_t v, int32_t d)
|
59
|
+
{
|
60
|
+
return (uint64_t)v<<32 | (GWF_DIAG_SHIFT + d);
|
61
|
+
}
|
62
|
+
|
63
|
+
/*
|
64
|
+
* Diagonal interval
|
65
|
+
*/
|
66
|
+
typedef struct {
|
67
|
+
uint64_t vd0, vd1;
|
68
|
+
} gwf_intv_t;
|
69
|
+
|
70
|
+
typedef kvec_t(gwf_intv_t) gwf_intv_v;
|
71
|
+
|
72
|
+
#define intvd_key(x) ((x).vd0)
|
73
|
+
KRADIX_SORT_INIT(gwf_intv, gwf_intv_t, intvd_key, 8)
|
74
|
+
|
75
|
+
static int gwf_intv_is_sorted(int32_t n_a, const gwf_intv_t *a)
|
76
|
+
{
|
77
|
+
int32_t i;
|
78
|
+
for (i = 1; i < n_a; ++i)
|
79
|
+
if (a[i-1].vd0 > a[i].vd0) break;
|
80
|
+
return (i == n_a);
|
81
|
+
}
|
82
|
+
|
83
|
+
// merge overlapping intervals; input must be sorted
|
84
|
+
static size_t gwf_intv_merge_adj(size_t n, gwf_intv_t *a)
|
85
|
+
{
|
86
|
+
size_t i, k;
|
87
|
+
uint64_t st, en;
|
88
|
+
if (n == 0) return 0;
|
89
|
+
st = a[0].vd0, en = a[0].vd1;
|
90
|
+
for (i = 1, k = 0; i < n; ++i) {
|
91
|
+
if (a[i].vd0 > en) {
|
92
|
+
a[k].vd0 = st, a[k++].vd1 = en;
|
93
|
+
st = a[i].vd0, en = a[i].vd1;
|
94
|
+
} else en = en > a[i].vd1? en : a[i].vd1;
|
95
|
+
}
|
96
|
+
a[k].vd0 = st, a[k++].vd1 = en;
|
97
|
+
return k;
|
98
|
+
}
|
99
|
+
|
100
|
+
// merge two sorted interval lists
|
101
|
+
static size_t gwf_intv_merge2(gwf_intv_t *a, size_t n_b, const gwf_intv_t *b, size_t n_c, const gwf_intv_t *c)
|
102
|
+
{
|
103
|
+
size_t i = 0, j = 0, k = 0;
|
104
|
+
while (i < n_b && j < n_c) {
|
105
|
+
if (b[i].vd0 <= c[j].vd0)
|
106
|
+
a[k++] = b[i++];
|
107
|
+
else a[k++] = c[j++];
|
108
|
+
}
|
109
|
+
while (i < n_b) a[k++] = b[i++];
|
110
|
+
while (j < n_c) a[k++] = c[j++];
|
111
|
+
return gwf_intv_merge_adj(k, a);
|
112
|
+
}
|
113
|
+
|
114
|
+
/*
|
115
|
+
* Diagonal
|
116
|
+
*/
|
117
|
+
typedef struct { // a diagonal
|
118
|
+
uint64_t vd; // higher 32 bits: vertex ID; lower 32 bits: diagonal+0x4000000
|
119
|
+
int32_t k;
|
120
|
+
int32_t len;
|
121
|
+
uint32_t xo; // higher 31 bits: anti diagonal; lower 1 bit: out-of-order or not
|
122
|
+
int32_t t;
|
123
|
+
} gwf_diag_t;
|
124
|
+
|
125
|
+
typedef kvec_t(gwf_diag_t) gwf_diag_v;
|
126
|
+
|
127
|
+
#define ed_key(x) ((x).vd)
|
128
|
+
KRADIX_SORT_INIT(gwf_ed, gwf_diag_t, ed_key, 8)
|
129
|
+
|
130
|
+
KDQ_INIT(gwf_diag_t)
|
131
|
+
|
132
|
+
// push (v,d,k) to the end of the queue
|
133
|
+
static inline void gwf_diag_push(void *km, gwf_diag_v *a, uint32_t v, int32_t d, int32_t k, uint32_t x, uint32_t ooo, int32_t t)
|
134
|
+
{
|
135
|
+
gwf_diag_t *p;
|
136
|
+
kv_pushp(gwf_diag_t, km, *a, &p);
|
137
|
+
p->vd = gwf_gen_vd(v, d), p->k = k, p->xo = x<<1|ooo, p->t = t;
|
138
|
+
}
|
139
|
+
|
140
|
+
// determine the wavefront on diagonal (v,d)
|
141
|
+
static inline int32_t gwf_diag_update(gwf_diag_t *p, uint32_t v, int32_t d, int32_t k, uint32_t x, uint32_t ooo, int32_t t)
|
142
|
+
{
|
143
|
+
uint64_t vd = gwf_gen_vd(v, d);
|
144
|
+
if (p->vd == vd) {
|
145
|
+
p->xo = p->k > k? p->xo : x<<1|ooo;
|
146
|
+
p->t = p->k > k? p->t : t;
|
147
|
+
p->k = p->k > k? p->k : k;
|
148
|
+
return 0;
|
149
|
+
}
|
150
|
+
return 1;
|
151
|
+
}
|
152
|
+
|
153
|
+
static int gwf_diag_is_sorted(int32_t n_a, const gwf_diag_t *a)
|
154
|
+
{
|
155
|
+
int32_t i;
|
156
|
+
for (i = 1; i < n_a; ++i)
|
157
|
+
if (a[i-1].vd > a[i].vd) break;
|
158
|
+
return (i == n_a);
|
159
|
+
}
|
160
|
+
|
161
|
+
// sort a[]. This uses the gwf_diag_t::ooo field to speed up sorting.
|
162
|
+
static void gwf_diag_sort(int32_t n_a, gwf_diag_t *a, void *km, gwf_diag_v *ooo)
|
163
|
+
{
|
164
|
+
int32_t i, j, k, n_b, n_c;
|
165
|
+
gwf_diag_t *b, *c;
|
166
|
+
|
167
|
+
kv_resize(gwf_diag_t, km, *ooo, n_a);
|
168
|
+
for (i = 0, n_c = 0; i < n_a; ++i)
|
169
|
+
if (a[i].xo&1) ++n_c;
|
170
|
+
n_b = n_a - n_c;
|
171
|
+
b = ooo->a, c = b + n_b;
|
172
|
+
for (i = j = k = 0; i < n_a; ++i) {
|
173
|
+
if (a[i].xo&1) c[k++] = a[i];
|
174
|
+
else b[j++] = a[i];
|
175
|
+
}
|
176
|
+
radix_sort_gwf_ed(c, c + n_c);
|
177
|
+
for (k = 0; k < n_c; ++k) c[k].xo &= 0xfffffffeU;
|
178
|
+
|
179
|
+
i = j = k = 0;
|
180
|
+
while (i < n_b && j < n_c) {
|
181
|
+
if (b[i].vd <= c[j].vd)
|
182
|
+
a[k++] = b[i++];
|
183
|
+
else a[k++] = c[j++];
|
184
|
+
}
|
185
|
+
while (i < n_b) a[k++] = b[i++];
|
186
|
+
while (j < n_c) a[k++] = c[j++];
|
187
|
+
}
|
188
|
+
|
189
|
+
// remove diagonals not on the wavefront
|
190
|
+
static int32_t gwf_diag_dedup(int32_t n_a, gwf_diag_t *a, void *km, gwf_diag_v *ooo)
|
191
|
+
{
|
192
|
+
int32_t i, n, st;
|
193
|
+
if (!gwf_diag_is_sorted(n_a, a))
|
194
|
+
gwf_diag_sort(n_a, a, km, ooo);
|
195
|
+
for (i = 1, st = 0, n = 0; i <= n_a; ++i) {
|
196
|
+
if (i == n_a || a[i].vd != a[st].vd) {
|
197
|
+
int32_t j, max_j = st;
|
198
|
+
if (st + 1 < i)
|
199
|
+
for (j = st + 1; j < i; ++j) // choose the far end (i.e. the wavefront)
|
200
|
+
if (a[max_j].k < a[j].k) max_j = j;
|
201
|
+
a[n++] = a[max_j];
|
202
|
+
st = i;
|
203
|
+
}
|
204
|
+
}
|
205
|
+
return n;
|
206
|
+
}
|
207
|
+
|
208
|
+
// use forbidden bands to remove diagonals not on the wavefront
|
209
|
+
static int32_t gwf_mixed_dedup(int32_t n_a, gwf_diag_t *a, int32_t n_b, gwf_intv_t *b)
|
210
|
+
{
|
211
|
+
int32_t i = 0, j = 0, k = 0;
|
212
|
+
while (i < n_a && j < n_b) {
|
213
|
+
if (a[i].vd >= b[j].vd0 && a[i].vd < b[j].vd1) ++i;
|
214
|
+
else if (a[i].vd >= b[j].vd1) ++j;
|
215
|
+
else a[k++] = a[i++];
|
216
|
+
}
|
217
|
+
while (i < n_a) a[k++] = a[i++];
|
218
|
+
return k;
|
219
|
+
}
|
220
|
+
|
221
|
+
/*
|
222
|
+
* Traceback stack
|
223
|
+
*/
|
224
|
+
KHASHL_MAP_INIT(KH_LOCAL, gwf_map64_t, gwf_map64, uint64_t, int32_t, kh_hash_uint64, kh_eq_generic)
|
225
|
+
|
226
|
+
typedef struct {
|
227
|
+
int32_t v;
|
228
|
+
int32_t pre;
|
229
|
+
} gwf_trace_t;
|
230
|
+
|
231
|
+
typedef kvec_t(gwf_trace_t) gwf_trace_v;
|
232
|
+
|
233
|
+
static int32_t gwf_trace_push(void *km, gwf_trace_v *a, int32_t v, int32_t pre, gwf_map64_t *h)
|
234
|
+
{
|
235
|
+
uint64_t key = (uint64_t)v << 32 | (uint32_t)pre;
|
236
|
+
khint_t k;
|
237
|
+
int absent;
|
238
|
+
k = gwf_map64_put(h, key, &absent);
|
239
|
+
if (absent) {
|
240
|
+
gwf_trace_t *p;
|
241
|
+
kv_pushp(gwf_trace_t, km, *a, &p);
|
242
|
+
p->v = v, p->pre = pre;
|
243
|
+
kh_val(h, k) = a->n - 1;
|
244
|
+
return a->n - 1;
|
245
|
+
}
|
246
|
+
return kh_val(h, k);
|
247
|
+
}
|
248
|
+
|
249
|
+
/*
|
250
|
+
* Core GWFA routine
|
251
|
+
*/
|
252
|
+
KHASHL_INIT(KH_LOCAL, gwf_set64_t, gwf_set64, uint64_t, kh_hash_dummy, kh_eq_generic)
|
253
|
+
|
254
|
+
typedef struct {
|
255
|
+
void *km;
|
256
|
+
gwf_set64_t *ha; // hash table for adjacency
|
257
|
+
gwf_map64_t *ht; // hash table for traceback
|
258
|
+
gwf_intv_v intv;
|
259
|
+
gwf_intv_v tmp, swap;
|
260
|
+
gwf_diag_v ooo;
|
261
|
+
gwf_trace_v t;
|
262
|
+
} gwf_edbuf_t;
|
263
|
+
|
264
|
+
// remove diagonals not on the wavefront
|
265
|
+
static int32_t gwf_dedup(gwf_edbuf_t *buf, int32_t n_a, gwf_diag_t *a)
|
266
|
+
{
|
267
|
+
if (buf->intv.n + buf->tmp.n > 0) {
|
268
|
+
if (!gwf_intv_is_sorted(buf->tmp.n, buf->tmp.a))
|
269
|
+
radix_sort_gwf_intv(buf->tmp.a, buf->tmp.a + buf->tmp.n);
|
270
|
+
kv_copy(gwf_intv_t, buf->km, buf->swap, buf->intv);
|
271
|
+
kv_resize(gwf_intv_t, buf->km, buf->intv, buf->intv.n + buf->tmp.n);
|
272
|
+
buf->intv.n = gwf_intv_merge2(buf->intv.a, buf->swap.n, buf->swap.a, buf->tmp.n, buf->tmp.a);
|
273
|
+
}
|
274
|
+
n_a = gwf_diag_dedup(n_a, a, buf->km, &buf->ooo);
|
275
|
+
if (buf->intv.n > 0)
|
276
|
+
n_a = gwf_mixed_dedup(n_a, a, buf->intv.n, buf->intv.a);
|
277
|
+
return n_a;
|
278
|
+
}
|
279
|
+
|
280
|
+
// remove diagonals that lag far behind the furthest wavefront
|
281
|
+
static int32_t gwf_prune(int32_t n_a, gwf_diag_t *a, uint32_t max_lag, int32_t bw_dyn)
|
282
|
+
{
|
283
|
+
int32_t i, j, iq, dq, max_i = -1;
|
284
|
+
uint32_t max_x = 0;
|
285
|
+
gwf_diag_t *q;
|
286
|
+
for (i = 0; i < n_a; ++i)
|
287
|
+
if (a[i].xo>>1 > max_x)
|
288
|
+
max_x = a[i].xo>>1, max_i = i;
|
289
|
+
q = &a[max_i];
|
290
|
+
iq = (int32_t)q->vd - GWF_DIAG_SHIFT + q->k;
|
291
|
+
dq = (int32_t)(q->xo>>1) - iq - iq;
|
292
|
+
for (i = j = 0; i < n_a; ++i) {
|
293
|
+
gwf_diag_t *p = &a[i];
|
294
|
+
int32_t ip = (int32_t)p->vd - GWF_DIAG_SHIFT + p->k;
|
295
|
+
int32_t dp = (int32_t)(p->xo>>1) - ip - ip;
|
296
|
+
int32_t w = dp > dq? dp - dq : dq - dp;
|
297
|
+
if (bw_dyn >= 0 && w > bw_dyn) continue;
|
298
|
+
if ((p->xo>>1) + max_lag < max_x) continue;
|
299
|
+
a[j++] = *p;
|
300
|
+
}
|
301
|
+
return j;
|
302
|
+
}
|
303
|
+
|
304
|
+
// reach the wavefront
|
305
|
+
static inline int32_t gwf_extend1(int32_t d, int32_t k, int32_t vl, const char *ts, int32_t ql, const char *qs)
|
306
|
+
{
|
307
|
+
int32_t max_k = (ql - d < vl? ql - d : vl) - 1;
|
308
|
+
const char *ts_ = ts + 1, *qs_ = qs + d + 1;
|
309
|
+
#if 0
|
310
|
+
// int32_t i = k + d; while (k + 1 < vl && i + 1 < ql && ts[k+1] == q[i+1]) ++k, ++i;
|
311
|
+
while (k < max_k && *(ts_ + k) == *(qs_ + k))
|
312
|
+
++k;
|
313
|
+
#else
|
314
|
+
uint64_t cmp = 0;
|
315
|
+
while (k + 7 < max_k) {
|
316
|
+
uint64_t x = *(uint64_t*)(ts_ + k); // warning: unaligned memory access
|
317
|
+
uint64_t y = *(uint64_t*)(qs_ + k);
|
318
|
+
cmp = x ^ y;
|
319
|
+
if (cmp == 0) k += 8;
|
320
|
+
else break;
|
321
|
+
}
|
322
|
+
if (cmp)
|
323
|
+
k += __builtin_ctzl(cmp) >> 3; // on x86, this is done via the BSR instruction: https://www.felixcloutier.com/x86/bsr
|
324
|
+
else if (k + 7 >= max_k)
|
325
|
+
while (k < max_k && *(ts_ + k) == *(qs_ + k)) // use this for generic CPUs. It is slightly faster than the unoptimized version
|
326
|
+
++k;
|
327
|
+
#endif
|
328
|
+
return k;
|
329
|
+
}
|
330
|
+
|
331
|
+
// This is essentially Landau-Vishkin for linear sequences. The function speeds up alignment to long vertices. Not really necessary.
|
332
|
+
static void gwf_ed_extend_batch(void *km, const gfa_t *g, const gfa_edseq_t *es, int32_t ql, const char *q, int32_t n, gwf_diag_t *a, gwf_diag_v *B,
|
333
|
+
kdq_t(gwf_diag_t) *A, gwf_intv_v *tmp_intv, gfa_edrst_t *r)
|
334
|
+
{
|
335
|
+
int32_t j, m;
|
336
|
+
int32_t v = a->vd>>32;
|
337
|
+
int32_t vl = es[v].len;
|
338
|
+
const char *ts = es[v].seq;
|
339
|
+
gwf_diag_t *b;
|
340
|
+
|
341
|
+
// wfa_extend
|
342
|
+
for (j = 0; j < n; ++j) {
|
343
|
+
int32_t k;
|
344
|
+
k = gwf_extend1((int32_t)a[j].vd - GWF_DIAG_SHIFT, a[j].k, vl, ts, ql, q);
|
345
|
+
a[j].len = k - a[j].k;
|
346
|
+
a[j].xo += a[j].len << 2;
|
347
|
+
a[j].k = k;
|
348
|
+
}
|
349
|
+
|
350
|
+
// wfa_next
|
351
|
+
kv_resize(gwf_diag_t, km, *B, B->n + n + 2);
|
352
|
+
b = &B->a[B->n];
|
353
|
+
b[0].vd = a[0].vd - 1;
|
354
|
+
b[0].xo = a[0].xo + 2; // 2 == 1<<1
|
355
|
+
b[0].k = a[0].k + 1;
|
356
|
+
b[0].t = a[0].t;
|
357
|
+
b[1].vd = a[0].vd;
|
358
|
+
b[1].xo = n == 1 || a[0].k > a[1].k? a[0].xo + 4 : a[1].xo + 2;
|
359
|
+
b[1].t = n == 1 || a[0].k > a[1].k? a[0].t : a[1].t;
|
360
|
+
b[1].k = (n == 1 || a[0].k > a[1].k? a[0].k : a[1].k) + 1;
|
361
|
+
for (j = 1; j < n - 1; ++j) {
|
362
|
+
uint32_t x = a[j-1].xo + 2;
|
363
|
+
int32_t k = a[j-1].k, t = a[j-1].t;
|
364
|
+
x = k > a[j].k + 1? x : a[j].xo + 4;
|
365
|
+
t = k > a[j].k + 1? t : a[j].t;
|
366
|
+
k = k > a[j].k + 1? k : a[j].k + 1;
|
367
|
+
x = k > a[j+1].k + 1? x : a[j+1].xo + 2;
|
368
|
+
t = k > a[j+1].k + 1? t : a[j+1].t;
|
369
|
+
k = k > a[j+1].k + 1? k : a[j+1].k + 1;
|
370
|
+
b[j+1].vd = a[j].vd, b[j+1].k = k, b[j+1].xo = x, b[j+1].t = t;
|
371
|
+
}
|
372
|
+
if (n >= 2) {
|
373
|
+
b[n].vd = a[n-1].vd;
|
374
|
+
b[n].xo = a[n-2].k > a[n-1].k + 1? a[n-2].xo + 2 : a[n-1].xo + 4;
|
375
|
+
b[n].t = a[n-2].k > a[n-1].k + 1? a[n-2].t : a[n-1].t;
|
376
|
+
b[n].k = a[n-2].k > a[n-1].k + 1? a[n-2].k : a[n-1].k + 1;
|
377
|
+
}
|
378
|
+
b[n+1].vd = a[n-1].vd + 1;
|
379
|
+
b[n+1].xo = a[n-1].xo + 2;
|
380
|
+
b[n+1].t = a[n-1].t;
|
381
|
+
b[n+1].k = a[n-1].k;
|
382
|
+
|
383
|
+
// drop out-of-bound cells
|
384
|
+
//if (a[n-1].k == vl - 1) b[n+1].k = vl; // insertion to the end of a vertex is handled elsewhere. FIXME: this line leads to wrong result for MHC-57 and MHC-HG002.2
|
385
|
+
for (j = 0; j < n; ++j) {
|
386
|
+
gwf_diag_t *p = &a[j];
|
387
|
+
if (p->k == vl - 1 || (int32_t)p->vd - GWF_DIAG_SHIFT + p->k == ql - 1)
|
388
|
+
p->xo |= 1, *kdq_pushp(gwf_diag_t, A) = *p;
|
389
|
+
}
|
390
|
+
for (j = 0, m = 0; j < n + 2; ++j) {
|
391
|
+
gwf_diag_t *p = &b[j];
|
392
|
+
int32_t d = (int32_t)p->vd - GWF_DIAG_SHIFT;
|
393
|
+
if (d + p->k < ql && p->k < vl) {
|
394
|
+
b[m++] = *p;
|
395
|
+
} else if (p->k == vl) {
|
396
|
+
gwf_intv_t *q;
|
397
|
+
kv_pushp(gwf_intv_t, km, *tmp_intv, &q);
|
398
|
+
q->vd0 = gwf_gen_vd(v, d), q->vd1 = q->vd0 + 1;
|
399
|
+
}
|
400
|
+
}
|
401
|
+
B->n += m;
|
402
|
+
}
|
403
|
+
|
404
|
+
// wfa_extend and wfa_next combined
|
405
|
+
static gwf_diag_t *gwf_ed_extend(gwf_edbuf_t *buf, const gfa_edopt_t *opt, const gfa_t *g, const gfa_edseq_t *es, int32_t s, int32_t ql, const char *q,
|
406
|
+
uint32_t v1, int32_t off1, int32_t *end_tb, int32_t *n_a_, gwf_diag_t *a, gfa_edrst_t *r)
|
407
|
+
{
|
408
|
+
int32_t i, x, n = *n_a_, do_dedup = 1;
|
409
|
+
kdq_t(gwf_diag_t) *A;
|
410
|
+
gwf_diag_v B = {0,0,0};
|
411
|
+
gwf_diag_t *b;
|
412
|
+
|
413
|
+
r->end_v = (uint32_t)-1;
|
414
|
+
r->end_off = *end_tb = -1;
|
415
|
+
buf->tmp.n = 0;
|
416
|
+
gwf_set64_clear(buf->ha); // hash table $h to avoid visiting a vertex twice
|
417
|
+
for (i = 0, x = 1; i < 32; ++i, x <<= 1)
|
418
|
+
if (x >= n) break;
|
419
|
+
if (i < 4) i = 4;
|
420
|
+
A = kdq_init2(gwf_diag_t, buf->km, i); // $A is a queue
|
421
|
+
kv_resize(gwf_diag_t, buf->km, B, n * 2);
|
422
|
+
#if 0 // unoptimized version without calling gwf_ed_extend_batch() at all. The final result will be the same.
|
423
|
+
A->count = n;
|
424
|
+
memcpy(A->a, a, n * sizeof(*a));
|
425
|
+
#else // optimized for long vertices.
|
426
|
+
for (x = 0, i = 1; i <= n; ++i) {
|
427
|
+
if (i == n || a[i].vd != a[i-1].vd + 1) {
|
428
|
+
gwf_ed_extend_batch(buf->km, g, es, ql, q, i - x, &a[x], &B, A, &buf->tmp, r);
|
429
|
+
x = i;
|
430
|
+
}
|
431
|
+
}
|
432
|
+
if (kdq_size(A) == 0) do_dedup = 0;
|
433
|
+
#endif
|
434
|
+
kfree(buf->km, a); // $a is not used as it has been copied to $A
|
435
|
+
|
436
|
+
while (kdq_size(A)) {
|
437
|
+
gwf_diag_t t;
|
438
|
+
uint32_t v, x0;
|
439
|
+
int32_t ooo, d, k, i, vl;
|
440
|
+
|
441
|
+
t = *kdq_shift(gwf_diag_t, A);
|
442
|
+
ooo = t.xo&1, v = t.vd >> 32; // vertex
|
443
|
+
d = (int32_t)t.vd - GWF_DIAG_SHIFT; // diagonal
|
444
|
+
k = t.k; // wavefront position on the vertex
|
445
|
+
vl = es[v].len; // $vl is the vertex length
|
446
|
+
k = gwf_extend1(d, k, vl, es[v].seq, ql, q);
|
447
|
+
i = k + d; // query position
|
448
|
+
x0 = (t.xo >> 1) + ((k - t.k) << 1); // current anti diagonal
|
449
|
+
|
450
|
+
if (k + 1 < vl && i + 1 < ql) { // the most common case: the wavefront is in the middle
|
451
|
+
int32_t push1 = 1, push2 = 1;
|
452
|
+
if (B.n >= 2) push1 = gwf_diag_update(&B.a[B.n - 2], v, d-1, k+1, x0 + 1, ooo, t.t);
|
453
|
+
if (B.n >= 1) push2 = gwf_diag_update(&B.a[B.n - 1], v, d, k+1, x0 + 2, ooo, t.t);
|
454
|
+
if (push1) gwf_diag_push(buf->km, &B, v, d-1, k+1, x0 + 1, 1, t.t);
|
455
|
+
if (push2 || push1) gwf_diag_push(buf->km, &B, v, d, k+1, x0 + 2, 1, t.t);
|
456
|
+
gwf_diag_push(buf->km, &B, v, d+1, k, x0 + 1, ooo, t.t);
|
457
|
+
} else if (i + 1 < ql) { // k + 1 == g->len[v]; reaching the end of the vertex but not the end of query
|
458
|
+
int32_t nv = gfa_arc_n(g, v), j, n_ext = 0, tw = -1;
|
459
|
+
gfa_arc_t *av = gfa_arc_a(g, v);
|
460
|
+
gwf_intv_t *p;
|
461
|
+
kv_pushp(gwf_intv_t, buf->km, buf->tmp, &p);
|
462
|
+
p->vd0 = gwf_gen_vd(v, d), p->vd1 = p->vd0 + 1;
|
463
|
+
if (opt->traceback) tw = gwf_trace_push(buf->km, &buf->t, v, t.t, buf->ht);
|
464
|
+
for (j = 0; j < nv; ++j) { // traverse $v's neighbors
|
465
|
+
uint32_t w = av[j].w; // $w is next to $v
|
466
|
+
int32_t ol = av[j].ow;
|
467
|
+
int absent;
|
468
|
+
gwf_set64_put(buf->ha, (uint64_t)w<<32 | (i + 1), &absent); // test if ($w,$i) has been visited
|
469
|
+
if (q[i + 1] == es[w].seq[ol]) { // can be extended to the next vertex without a mismatch
|
470
|
+
++n_ext;
|
471
|
+
if (absent) {
|
472
|
+
gwf_diag_t *p;
|
473
|
+
p = kdq_pushp(gwf_diag_t, A);
|
474
|
+
p->vd = gwf_gen_vd(w, i + 1 - ol), p->k = ol, p->xo = (x0+2)<<1 | 1, p->t = tw;
|
475
|
+
}
|
476
|
+
} else if (absent) {
|
477
|
+
gwf_diag_push(buf->km, &B, w, i - ol, ol, x0 + 1, 1, tw);
|
478
|
+
gwf_diag_push(buf->km, &B, w, i + 1 - ol, ol, x0 + 2, 1, tw);
|
479
|
+
}
|
480
|
+
}
|
481
|
+
if (nv == 0 || n_ext != nv) // add an insertion to the target; this *might* cause a duplicate in corner cases
|
482
|
+
gwf_diag_push(buf->km, &B, v, d+1, k, x0 + 1, 1, t.t);
|
483
|
+
} else if (v1 == (uint32_t)-1 || (v == v1 && k == off1)) { // i + 1 == ql
|
484
|
+
r->end_v = v, r->end_off = k, r->wlen = x0 - i - 1, *end_tb = t.t, *n_a_ = 0;
|
485
|
+
kdq_destroy(gwf_diag_t, A);
|
486
|
+
kfree(buf->km, B.a);
|
487
|
+
return 0;
|
488
|
+
} else if (k + 1 < vl) { // i + 1 == ql; reaching the end of the query but not the end of the vertex
|
489
|
+
gwf_diag_push(buf->km, &B, v, d-1, k+1, x0 + 1, ooo, t.t); // add an deletion; this *might* case a duplicate in corner cases
|
490
|
+
} else if (v != v1) { // i + 1 == ql && k + 1 == g->len[v]; not reaching the last vertex $v1
|
491
|
+
int32_t nv = gfa_arc_n(g, v), j, tw = -1;
|
492
|
+
const gfa_arc_t *av = gfa_arc_a(g, v);
|
493
|
+
if (opt->traceback) tw = gwf_trace_push(buf->km, &buf->t, v, t.t, buf->ht);
|
494
|
+
for (j = 0; j < nv; ++j)
|
495
|
+
gwf_diag_push(buf->km, &B, av[j].w, i - av[j].ow, av[j].ow, x0 + 1, 1, tw); // deleting the first base on the next vertex
|
496
|
+
} else { // may come here when k>off1 (due to banding); do nothing in this case
|
497
|
+
}
|
498
|
+
}
|
499
|
+
|
500
|
+
kdq_destroy(gwf_diag_t, A);
|
501
|
+
*n_a_ = n = B.n, b = B.a;
|
502
|
+
|
503
|
+
if (do_dedup) *n_a_ = n = gwf_dedup(buf, n, b);
|
504
|
+
if (opt->max_lag > 0 && n > opt->max_chk && ((s+1)&0xf) == 0)
|
505
|
+
*n_a_ = n = gwf_prune(n, b, opt->max_lag, opt->bw_dyn);
|
506
|
+
return b;
|
507
|
+
}
|
508
|
+
|
509
|
+
static void gwf_traceback(gwf_edbuf_t *buf, int32_t end_v, int32_t end_tb, gfa_edrst_t *path)
|
510
|
+
{
|
511
|
+
int32_t i = end_tb, n = 1;
|
512
|
+
while (i >= 0 && buf->t.a[i].v >= 0)
|
513
|
+
++n, i = buf->t.a[i].pre;
|
514
|
+
KMALLOC(buf->km, path->v, n);
|
515
|
+
i = end_tb, n = 0;
|
516
|
+
path->v[n++] = end_v;
|
517
|
+
while (i >= 0 && buf->t.a[i].v >= 0)
|
518
|
+
path->v[n++] = buf->t.a[i].v, i = buf->t.a[i].pre;
|
519
|
+
path->nv = n;
|
520
|
+
for (i = 0; i < path->nv>>1; ++i)
|
521
|
+
n = path->v[i], path->v[i] = path->v[path->nv - 1 - i], path->v[path->nv - 1 - i] = n;
|
522
|
+
}
|
523
|
+
|
524
|
+
static void gwf_ed_print_diag(const gfa_t *g, size_t n, gwf_diag_t *a) // for debugging only
|
525
|
+
{
|
526
|
+
size_t i;
|
527
|
+
for (i = 0; i < n; ++i) {
|
528
|
+
int32_t d = (int32_t)a[i].vd - GWF_DIAG_SHIFT;
|
529
|
+
printf("Z\t%d\t%s\t%d\t%d\t%d\n", d + a[i].k, g->seg[(a[i].vd>>32)>>1].name, d, a[i].k, a[i].xo>>1);
|
530
|
+
}
|
531
|
+
}
|
532
|
+
|
533
|
+
static void gwf_ed_print_intv(size_t n, gwf_intv_t *a) // for debugging only
|
534
|
+
{
|
535
|
+
size_t i;
|
536
|
+
for (i = 0; i < n; ++i)
|
537
|
+
printf("Z\t%d\t%d\t%d\n", (int32_t)(a[i].vd0>>32), (int32_t)a[i].vd0 - GWF_DIAG_SHIFT, (int32_t)a[i].vd1 - GWF_DIAG_SHIFT);
|
538
|
+
}
|
539
|
+
|
540
|
+
typedef struct {
|
541
|
+
const gfa_t *g;
|
542
|
+
const gfa_edseq_t *es;
|
543
|
+
const gfa_edopt_t *opt;
|
544
|
+
int32_t ql;
|
545
|
+
const char *q;
|
546
|
+
gwf_edbuf_t buf;
|
547
|
+
int32_t s, n_a;
|
548
|
+
gwf_diag_t *a;
|
549
|
+
int32_t end_tb;
|
550
|
+
} gfa_edbuf_t;
|
551
|
+
|
552
|
+
void *gfa_ed_init(void *km, const gfa_edopt_t *opt, const gfa_t *g, const gfa_edseq_t *es, int32_t ql, const char *q, uint32_t v0, int32_t off0)
|
553
|
+
{
|
554
|
+
gfa_edbuf_t *z;
|
555
|
+
KCALLOC(km, z, 1);
|
556
|
+
z->buf.km = km;
|
557
|
+
z->opt = opt;
|
558
|
+
z->g = g, z->es = es;
|
559
|
+
z->ql = ql, z->q = q;
|
560
|
+
z->buf.ha = gwf_set64_init2(km);
|
561
|
+
z->buf.ht = gwf_map64_init2(km);
|
562
|
+
kv_resize(gwf_trace_t, km, z->buf.t, 16);
|
563
|
+
KCALLOC(km, z->a, 1);
|
564
|
+
z->a[0].vd = gwf_gen_vd(v0, -off0), z->a[0].k = off0 - 1, z->a[0].xo = 0;
|
565
|
+
if (z->opt->traceback) z->a[0].t = gwf_trace_push(km, &z->buf.t, -1, -1, z->buf.ht);
|
566
|
+
z->n_a = 1;
|
567
|
+
return z;
|
568
|
+
}
|
569
|
+
|
570
|
+
void gfa_ed_step(void *z_, uint32_t v1, int32_t off1, int32_t s_term, gfa_edrst_t *r)
|
571
|
+
{
|
572
|
+
gfa_edbuf_t *z = (gfa_edbuf_t*)z_;
|
573
|
+
const gfa_edopt_t *opt = z->opt;
|
574
|
+
if (s_term < 0 && z->opt->s_term >= 0) s_term = z->opt->s_term;
|
575
|
+
r->n_end = 0, r->n_iter = 0;
|
576
|
+
while (z->n_a > 0) {
|
577
|
+
z->a = gwf_ed_extend(&z->buf, opt, z->g, z->es, z->s, z->ql, z->q, v1, off1, &z->end_tb, &z->n_a, z->a, r);
|
578
|
+
r->n_iter += z->n_a; // + z->buf.intv.n;
|
579
|
+
if (r->end_off >= 0 || z->n_a == 0) break;
|
580
|
+
if (r->n_end > 0) break;
|
581
|
+
if (s_term >= 0 && z->s >= s_term) break;
|
582
|
+
if (z->opt->i_term > 0 && r->n_iter > z->opt->i_term) break;
|
583
|
+
++z->s;
|
584
|
+
if (gfa_ed_dbg >= 1) {
|
585
|
+
printf("[%s] dist=%d, n=%d, n_intv=%ld, n_tb=%ld\n", __func__, z->s, z->n_a, z->buf.intv.n, z->buf.t.n);
|
586
|
+
if (gfa_ed_dbg == 2) gwf_ed_print_diag(z->g, z->n_a, z->a);
|
587
|
+
if (gfa_ed_dbg == 3) gwf_ed_print_intv(z->buf.intv.n, z->buf.intv.a);
|
588
|
+
}
|
589
|
+
}
|
590
|
+
if (opt->traceback && r->end_off >= 0)
|
591
|
+
gwf_traceback(&z->buf, r->end_v, z->end_tb, r);
|
592
|
+
r->s = r->end_v != (uint32_t)-1? z->s : -1;
|
593
|
+
}
|
594
|
+
|
595
|
+
void gfa_ed_destroy(void *z_)
|
596
|
+
{
|
597
|
+
gfa_edbuf_t *z = (gfa_edbuf_t*)z_;
|
598
|
+
void *km = z->buf.km;
|
599
|
+
kfree(km, z->a);
|
600
|
+
gwf_set64_destroy(z->buf.ha);
|
601
|
+
gwf_map64_destroy(z->buf.ht);
|
602
|
+
kfree(km, z->buf.ooo.a);
|
603
|
+
kfree(km, z->buf.intv.a);
|
604
|
+
kfree(km, z->buf.tmp.a);
|
605
|
+
kfree(km, z->buf.swap.a);
|
606
|
+
kfree(km, z->buf.t.a);
|
607
|
+
kfree(km, z);
|
608
|
+
}
|
609
|
+
|
610
|
+
int32_t gfa_edit_dist(void *km, const gfa_edopt_t *opt, const gfa_t *g, const gfa_edseq_t *es, int32_t ql, const char *q, uint32_t v0, int32_t off0, gfa_edrst_t *rst)
|
611
|
+
{
|
612
|
+
void *z;
|
613
|
+
z = gfa_ed_init(km, opt, g, es, ql, q, v0, off0);
|
614
|
+
gfa_ed_step(z, (uint32_t)-1, -1, -1, rst);
|
615
|
+
gfa_ed_destroy(z);
|
616
|
+
return rst->s;
|
617
|
+
}
|