ruby-minigraph 0.0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +62 -0
  4. data/ext/Rakefile +56 -0
  5. data/ext/cmappy/cmappy.c +7 -0
  6. data/ext/cmappy/cmappy.h +8 -0
  7. data/ext/minigraph/LICENSE.txt +23 -0
  8. data/ext/minigraph/Makefile +66 -0
  9. data/ext/minigraph/NEWS.md +317 -0
  10. data/ext/minigraph/README.md +207 -0
  11. data/ext/minigraph/algo.c +194 -0
  12. data/ext/minigraph/algo.h +33 -0
  13. data/ext/minigraph/asm-call.c +147 -0
  14. data/ext/minigraph/bseq.c +133 -0
  15. data/ext/minigraph/bseq.h +76 -0
  16. data/ext/minigraph/cal_cov.c +139 -0
  17. data/ext/minigraph/doc/example1.png +0 -0
  18. data/ext/minigraph/doc/example2.png +0 -0
  19. data/ext/minigraph/doc/examples.graffle +0 -0
  20. data/ext/minigraph/format.c +241 -0
  21. data/ext/minigraph/galign.c +140 -0
  22. data/ext/minigraph/gchain1.c +532 -0
  23. data/ext/minigraph/gcmisc.c +223 -0
  24. data/ext/minigraph/gfa-aug.c +260 -0
  25. data/ext/minigraph/gfa-base.c +526 -0
  26. data/ext/minigraph/gfa-bbl.c +372 -0
  27. data/ext/minigraph/gfa-ed.c +617 -0
  28. data/ext/minigraph/gfa-io.c +395 -0
  29. data/ext/minigraph/gfa-priv.h +154 -0
  30. data/ext/minigraph/gfa.h +166 -0
  31. data/ext/minigraph/ggen.c +182 -0
  32. data/ext/minigraph/ggen.h +21 -0
  33. data/ext/minigraph/ggsimple.c +570 -0
  34. data/ext/minigraph/gmap.c +211 -0
  35. data/ext/minigraph/index.c +230 -0
  36. data/ext/minigraph/kalloc.c +224 -0
  37. data/ext/minigraph/kalloc.h +82 -0
  38. data/ext/minigraph/kavl.h +414 -0
  39. data/ext/minigraph/kdq.h +134 -0
  40. data/ext/minigraph/ketopt.h +116 -0
  41. data/ext/minigraph/khashl.h +348 -0
  42. data/ext/minigraph/krmq.h +474 -0
  43. data/ext/minigraph/kseq.h +256 -0
  44. data/ext/minigraph/ksort.h +164 -0
  45. data/ext/minigraph/kstring.h +165 -0
  46. data/ext/minigraph/kthread.c +159 -0
  47. data/ext/minigraph/kthread.h +15 -0
  48. data/ext/minigraph/kvec-km.h +105 -0
  49. data/ext/minigraph/kvec.h +110 -0
  50. data/ext/minigraph/lchain.c +441 -0
  51. data/ext/minigraph/main.c +301 -0
  52. data/ext/minigraph/map-algo.c +500 -0
  53. data/ext/minigraph/mgpriv.h +128 -0
  54. data/ext/minigraph/minigraph.1 +359 -0
  55. data/ext/minigraph/minigraph.h +176 -0
  56. data/ext/minigraph/miniwfa.c +834 -0
  57. data/ext/minigraph/miniwfa.h +95 -0
  58. data/ext/minigraph/misc/mgutils.js +1451 -0
  59. data/ext/minigraph/misc.c +12 -0
  60. data/ext/minigraph/options.c +134 -0
  61. data/ext/minigraph/shortk.c +251 -0
  62. data/ext/minigraph/sketch.c +109 -0
  63. data/ext/minigraph/sys.c +147 -0
  64. data/ext/minigraph/sys.h +20 -0
  65. data/ext/minigraph/test/MT-chimp.fa +277 -0
  66. data/ext/minigraph/test/MT-human.fa +239 -0
  67. data/ext/minigraph/test/MT-orangA.fa +276 -0
  68. data/ext/minigraph/test/MT.gfa +19 -0
  69. data/ext/minigraph/tex/Makefile +13 -0
  70. data/ext/minigraph/tex/minigraph.bib +676 -0
  71. data/ext/minigraph/tex/minigraph.tex +986 -0
  72. data/ext/minigraph/tex/plots/CHM13-f1-90.bb.anno.gp +42 -0
  73. data/ext/minigraph/tex/plots/CHM13-f1-90.bb.anno.tbl +13 -0
  74. data/ext/minigraph/tex/plots/CHM13-f1-90.bb.mini-inter-none.win.gp +269 -0
  75. data/ext/minigraph/tex/plots/CHM13-f1-90.bb.mini-inter-none.win.sh +7 -0
  76. data/ext/minigraph/tex/plots/CHM13v1.cen.bed +23 -0
  77. data/ext/minigraph/tex/plots/CHM13v1.size +23 -0
  78. data/ext/minigraph/tex/plots/anno2tbl.js +40 -0
  79. data/ext/minigraph/tex/plots/bedutils.js +367 -0
  80. data/ext/minigraph/tex/plots/chr-plot.js +130 -0
  81. data/ext/minigraph/tex/plots/gen-anno.mak +24 -0
  82. data/ext/minigraph.patch +21 -0
  83. data/lib/minigraph/ffi/constants.rb +230 -0
  84. data/lib/minigraph/ffi/functions.rb +70 -0
  85. data/lib/minigraph/ffi/mappy.rb +8 -0
  86. data/lib/minigraph/ffi.rb +27 -0
  87. data/lib/minigraph/version.rb +5 -0
  88. data/lib/minigraph.rb +72 -0
  89. 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
+ }