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.
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
+ }