@jbrowse/bandage-core 10.3.1 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/chunks/{chunk-DBLV7PGG.js → chunk-3XSRT7RQ.js} +16 -2
- package/dist/chunks/{chunk-EWLXU3UG.js → chunk-5LTZVKZQ.js} +9 -9
- package/dist/chunks/{chunk-AQCOIE5R.js → chunk-6OP4HPXG.js} +1 -1
- package/dist/chunks/{chunk-BKEZLETL.js → chunk-AI5PTOSV.js} +1 -1
- package/dist/chunks/{chunk-R2PJKD3Y.js → chunk-BIOKXS3M.js} +1 -1
- package/dist/chunks/{chunk-YZQI35UJ.js → chunk-C3NT37C3.js} +22 -1
- package/dist/chunks/{chunk-OOIOX36I.js → chunk-CIDSF47D.js} +28 -8
- package/dist/chunks/{chunk-CHNESV7L.js → chunk-CTZRIDMY.js} +7 -7
- package/dist/chunks/{chunk-QH2MIXBA.js → chunk-CZT33FZG.js} +6 -6
- package/dist/chunks/{chunk-CGFPFBT2.js → chunk-D4ZFRBB4.js} +11 -2
- package/dist/chunks/{chunk-Z6XZWPXK.js → chunk-DZR37KXT.js} +51 -2
- package/dist/chunks/{chunk-AZ4EEF6Q.js → chunk-EDWU7OM4.js} +5 -5
- package/dist/chunks/chunk-EIY2SKD3.js +164 -0
- package/dist/chunks/{chunk-MWOVW4AH.js → chunk-EY2ZGSCP.js} +1 -1
- package/dist/chunks/{chunk-NZTYV3JL.js → chunk-FFHJGWDK.js} +5 -1
- package/dist/chunks/{chunk-KMBE2Q42.js → chunk-KDU4EF66.js} +3 -3
- package/dist/chunks/{chunk-WYJQIC75.js → chunk-L5IETLWP.js} +4 -4
- package/dist/chunks/{chunk-GIHTHYXY.js → chunk-NMWQUFPF.js} +1 -1
- package/dist/chunks/{chunk-A2TJ5UX6.js → chunk-OLKXMZ6J.js} +1 -1
- package/dist/chunks/{chunk-FW2R7UDZ.js → chunk-PK5QQOMN.js} +1 -1
- package/dist/chunks/{chunk-OXRUPNSV.js → chunk-RNYPCQZ3.js} +1 -1
- package/dist/chunks/{chunk-SFP3E4RI.js → chunk-TEF3NBG3.js} +2 -2
- package/dist/chunks/{chunk-M5NPD55W.js → chunk-TUQKGAK3.js} +1 -1
- package/dist/chunks/{chunk-D7WIYPG3.js → chunk-W6EXQDV5.js} +1 -1
- package/dist/chunks/{chunk-ZJBOM73S.js → chunk-XZ6PQBU6.js} +58 -12
- package/dist/cli/figure.js +22 -21
- package/dist/cli/fold.js +5 -4
- package/dist/figure.js +16 -15
- package/dist/figureData.js +19 -18
- package/dist/figureScene.js +11 -10
- package/dist/figureSettings.js +6 -5
- package/dist/gbzCut.js +4 -3
- package/dist/gbzWindow.js +3 -2
- package/dist/gfa/gfaConverter.js +2 -1
- package/dist/gfa/gfaTables.js +2 -1
- package/dist/gfa/graphTables.js +2 -1
- package/dist/gfa/walkStops.js +28 -0
- package/dist/index.js +52 -34
- package/dist/layout/forceCache.js +6 -5
- package/dist/layout/tubeMapLayout.js +3 -2
- package/dist/layout/walkRowDraw.js +10 -1
- package/dist/layout/walkRowLayout.js +3 -2
- package/dist/layout/walkRows.js +2 -1
- package/dist/layout/walkStrip.js +5 -4
- package/dist/layoutModes.js +6 -5
- package/dist/pipeline.js +5 -4
- package/dist/tubeMap/bundle.js +4 -3
- package/dist/tubeMap/coarsen.js +4 -3
- package/dist/tubeMap/deviations.js +4 -3
- package/dist/tubeMap/draw.js +4 -3
- package/dist/types/gfa/graphTables.d.ts +3 -0
- package/dist/types/gfa/walkStops.d.ts +59 -0
- package/dist/types/index.d.ts +4 -2
- package/dist/types/layout/walkRowDraw.d.ts +14 -1
- package/dist/types/layout/walkRows.d.ts +4 -1
- package/dist/types/types.d.ts +19 -0
- package/dist/types/version.d.ts +1 -1
- package/dist/types/walkHighlight.d.ts +2 -0
- package/dist/types/walkKey.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/viewport.js +6 -5
- package/dist/walkHighlight.js +2 -1
- package/dist/walkKey.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,11 @@ npm install @jbrowse/bandage-core
|
|
|
10
10
|
|
|
11
11
|
- GFA and rGFA text in (`loadGraph`), or the same graph as typed arrays a worker
|
|
12
12
|
can transfer (`GraphTables`)
|
|
13
|
+
- A walk-file cut's W lines tag what lies past each fragment's start and end as
|
|
14
|
+
`ws:Z:`/`we:Z:`, such as `break,bp=19021` or
|
|
15
|
+
`elsewhere,trimmed=400,chunk=GRCh38#0#chr22:20316160`
|
|
16
|
+
(`src/gfa/walkStops.ts`). Walk rows split each gap by those stops into parts
|
|
17
|
+
that name their cause
|
|
13
18
|
- Layouts: Bandage's FMMM engine as WASM from
|
|
14
19
|
[@jbrowse/graph-fmmm-layout](https://github.com/GMOD/graph-fmmm-layout)
|
|
15
20
|
(`loadBandage`, `forceLayout`), ordered, anchored, sample rows, walk rows,
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
stopAt,
|
|
3
|
+
stopFields,
|
|
4
|
+
walkStopTags
|
|
5
|
+
} from "./chunk-EIY2SKD3.js";
|
|
1
6
|
import {
|
|
2
7
|
PathVisits
|
|
3
8
|
} from "./chunk-ZPZ7GNBT.js";
|
|
@@ -209,7 +214,16 @@ function graphFromTables({ nodes: n, links: l, walks: w }, name = "Imported GFA"
|
|
|
209
214
|
}
|
|
210
215
|
prev = node;
|
|
211
216
|
}
|
|
212
|
-
paths.push({
|
|
217
|
+
paths.push({
|
|
218
|
+
name: pathName,
|
|
219
|
+
nodeIds,
|
|
220
|
+
start,
|
|
221
|
+
...fields,
|
|
222
|
+
...fields ? stopFields(
|
|
223
|
+
w.before && stopAt(w.before, p),
|
|
224
|
+
w.after && stopAt(w.after, p)
|
|
225
|
+
) : {}
|
|
226
|
+
});
|
|
213
227
|
anchorPaths.push({
|
|
214
228
|
name: visitName,
|
|
215
229
|
sample: visitSample,
|
|
@@ -272,7 +286,7 @@ function graphTablesGFA({ nodes, links, walks }) {
|
|
|
272
286
|
steps.push([names[walks.steps[s]], walks.reversed[s]]);
|
|
273
287
|
}
|
|
274
288
|
lines.push(
|
|
275
|
-
fields ? `W ${fields.sample} ${fields.haplotype} ${fields.contig} ${start} ${end} ${steps.map(([id, rev]) => (rev ? "<" : ">") + id).join("")}` : `P ${pLineName(name, start, end)} ${steps.map(([id, rev]) => id + (rev ? "-" : "+")).join(",")} *`
|
|
289
|
+
fields ? `W ${fields.sample} ${fields.haplotype} ${fields.contig} ${start} ${end} ${steps.map(([id, rev]) => (rev ? "<" : ">") + id).join("")}${walkStopTags(walks, p)}` : `P ${pLineName(name, start, end)} ${steps.map(([id, rev]) => id + (rev ? "-" : "+")).join(",")} *`
|
|
276
290
|
);
|
|
277
291
|
}
|
|
278
292
|
return lines.join("\n");
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
stripGeneGaps,
|
|
6
6
|
walkStripFrame,
|
|
7
7
|
walkStripLabelsTree
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-TEF3NBG3.js";
|
|
9
9
|
import {
|
|
10
10
|
walkRowsKey,
|
|
11
11
|
walkRowsKeyTree,
|
|
12
12
|
walkRowsTree
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XZ6PQBU6.js";
|
|
14
14
|
import {
|
|
15
15
|
Canvas2DRenderer
|
|
16
16
|
} from "./chunk-EJRJAAN7.js";
|
|
@@ -34,32 +34,32 @@ import {
|
|
|
34
34
|
} from "./chunk-H2H4Y3TV.js";
|
|
35
35
|
import {
|
|
36
36
|
version
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-6OP4HPXG.js";
|
|
38
38
|
import {
|
|
39
39
|
axisScaleOf
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-AI5PTOSV.js";
|
|
41
41
|
import {
|
|
42
42
|
figureScene
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-CZT33FZG.js";
|
|
44
44
|
import {
|
|
45
45
|
encodingStops
|
|
46
46
|
} from "./chunk-DO62DG26.js";
|
|
47
47
|
import {
|
|
48
48
|
rangeText
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-D4ZFRBB4.js";
|
|
50
50
|
import {
|
|
51
51
|
walkRowLabels
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-OLKXMZ6J.js";
|
|
53
53
|
import {
|
|
54
54
|
nodeInk
|
|
55
55
|
} from "./chunk-CRCD3ODN.js";
|
|
56
56
|
import {
|
|
57
57
|
FIGURE_DEFAULTS
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-W6EXQDV5.js";
|
|
59
59
|
import {
|
|
60
60
|
FIT_PADDING,
|
|
61
61
|
fitTransform
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-KDU4EF66.js";
|
|
63
63
|
import {
|
|
64
64
|
LABEL_CHAR_PX,
|
|
65
65
|
LABEL_PAD,
|
|
@@ -5,6 +5,9 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
pathOrigin
|
|
7
7
|
} from "./chunk-B5X2RLJG.js";
|
|
8
|
+
import {
|
|
9
|
+
gapParts
|
|
10
|
+
} from "./chunk-EIY2SKD3.js";
|
|
8
11
|
import {
|
|
9
12
|
panSNContig
|
|
10
13
|
} from "./chunk-4XWZNPQ2.js";
|
|
@@ -68,6 +71,22 @@ function highlightOf(graph, name, { byId, edgeAt }) {
|
|
|
68
71
|
before += length;
|
|
69
72
|
});
|
|
70
73
|
}
|
|
74
|
+
let missingBp = 0;
|
|
75
|
+
let unknownBp = 0;
|
|
76
|
+
let end;
|
|
77
|
+
pieces.forEach((piece, p) => {
|
|
78
|
+
if (end !== void 0 && piece.start !== void 0 && piece.start > end) {
|
|
79
|
+
for (const part of gapParts(
|
|
80
|
+
piece.start - end,
|
|
81
|
+
pieces[p - 1].after,
|
|
82
|
+
piece.before
|
|
83
|
+
)) {
|
|
84
|
+
missingBp += part.cause === "missing" ? part.bp : 0;
|
|
85
|
+
unknownBp += part.cause === "unknown" ? part.bp : 0;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
end = piece.start === void 0 ? void 0 : piece.start + bpOf(piece);
|
|
89
|
+
});
|
|
71
90
|
const reference = isReference(graph, name);
|
|
72
91
|
const referenceSpan = () => {
|
|
73
92
|
const referencePieces = reference ? [] : (graph.paths ?? []).filter((p) => isReference(graph, p.name));
|
|
@@ -86,7 +105,9 @@ function highlightOf(graph, name, { byId, edgeAt }) {
|
|
|
86
105
|
progress,
|
|
87
106
|
steps: pieces.reduce((sum, piece) => sum + piece.nodeIds.length, 0),
|
|
88
107
|
bp,
|
|
89
|
-
referenceBp: referenceSpan()
|
|
108
|
+
referenceBp: referenceSpan(),
|
|
109
|
+
missingBp,
|
|
110
|
+
unknownBp
|
|
90
111
|
};
|
|
91
112
|
}
|
|
92
113
|
function laneColors(byId, walk, encoding, ramp) {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pathOrigin
|
|
3
3
|
} from "./chunk-B5X2RLJG.js";
|
|
4
|
+
import {
|
|
5
|
+
gapParts
|
|
6
|
+
} from "./chunk-EIY2SKD3.js";
|
|
4
7
|
import {
|
|
5
8
|
groupBy
|
|
6
9
|
} from "./chunk-BSOZW3FC.js";
|
|
@@ -50,10 +53,13 @@ var NodeTable = class {
|
|
|
50
53
|
};
|
|
51
54
|
function stepsOf(pieces, table) {
|
|
52
55
|
const out = [];
|
|
56
|
+
const gaps = [];
|
|
53
57
|
let end;
|
|
58
|
+
let previous;
|
|
54
59
|
for (const piece of pieces) {
|
|
55
60
|
if (end !== void 0 && piece.start !== void 0 && piece.start > end) {
|
|
56
|
-
|
|
61
|
+
gaps.push(gapParts(piece.start - end, previous?.after, piece.before));
|
|
62
|
+
out.push(-gaps.length);
|
|
57
63
|
}
|
|
58
64
|
let bp = 0;
|
|
59
65
|
for (const node of piece.nodes) {
|
|
@@ -61,8 +67,9 @@ function stepsOf(pieces, table) {
|
|
|
61
67
|
bp += table.lengths[node];
|
|
62
68
|
}
|
|
63
69
|
end = piece.start === void 0 ? void 0 : piece.start + bp;
|
|
70
|
+
previous = piece;
|
|
64
71
|
}
|
|
65
|
-
return Float64Array.from(out);
|
|
72
|
+
return { steps: Float64Array.from(out), gaps };
|
|
66
73
|
}
|
|
67
74
|
function stepSpan(pieces, table, k) {
|
|
68
75
|
let end;
|
|
@@ -203,10 +210,13 @@ function walkRows(graph, region, unit) {
|
|
|
203
210
|
const path = paths2[0];
|
|
204
211
|
const pieces = paths2.map((piece, p) => ({
|
|
205
212
|
start: piece.start,
|
|
206
|
-
nodes: nodes?.[p] ?? table.nodesOf(piece)
|
|
213
|
+
nodes: nodes?.[p] ?? table.nodesOf(piece),
|
|
214
|
+
before: piece.before,
|
|
215
|
+
after: piece.after
|
|
207
216
|
})).sort((a, b) => (a.start ?? 0) - (b.start ?? 0));
|
|
217
|
+
const { steps, gaps } = stepsOf(pieces, table);
|
|
208
218
|
const { ids, complete, from, to, stop } = sliceBetween(
|
|
209
|
-
|
|
219
|
+
steps,
|
|
210
220
|
table,
|
|
211
221
|
cut,
|
|
212
222
|
flanked
|
|
@@ -221,12 +231,22 @@ function walkRows(graph, region, unit) {
|
|
|
221
231
|
let offReferenceBp = 0;
|
|
222
232
|
let gapBp = 0;
|
|
223
233
|
let step = 0;
|
|
234
|
+
const backwards = from >= 0 && from > to;
|
|
224
235
|
for (const node of ids) {
|
|
225
236
|
if (node < 0) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
237
|
+
const parts = gaps[-node - 1];
|
|
238
|
+
for (const { bp: partBp, ...why } of backwards ? [...parts].reverse() : parts) {
|
|
239
|
+
last = {
|
|
240
|
+
start: bp,
|
|
241
|
+
bp: partBp,
|
|
242
|
+
onReference: false,
|
|
243
|
+
gap: true,
|
|
244
|
+
...why
|
|
245
|
+
};
|
|
246
|
+
runs.push(last);
|
|
247
|
+
bp += partBp;
|
|
248
|
+
gapBp += partBp;
|
|
249
|
+
}
|
|
230
250
|
step = 0;
|
|
231
251
|
continue;
|
|
232
252
|
}
|
|
@@ -3,19 +3,19 @@ import {
|
|
|
3
3
|
} from "./chunk-JMABOQWL.js";
|
|
4
4
|
import {
|
|
5
5
|
layoutModeByValue
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-EDWU7OM4.js";
|
|
7
7
|
import {
|
|
8
8
|
parseRegion
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-TUQKGAK3.js";
|
|
10
10
|
import {
|
|
11
11
|
version
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-6OP4HPXG.js";
|
|
13
13
|
import {
|
|
14
14
|
axisScaleOf
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-AI5PTOSV.js";
|
|
16
16
|
import {
|
|
17
17
|
figureScene
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-CZT33FZG.js";
|
|
19
19
|
import {
|
|
20
20
|
abgrAlpha,
|
|
21
21
|
abgrBlue,
|
|
@@ -24,13 +24,13 @@ import {
|
|
|
24
24
|
} from "./chunk-G2FD7S3C.js";
|
|
25
25
|
import {
|
|
26
26
|
FIGURE_DEFAULTS
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-W6EXQDV5.js";
|
|
28
28
|
import {
|
|
29
29
|
engineSettingsOf,
|
|
30
30
|
fitTransform,
|
|
31
31
|
forceLayout,
|
|
32
32
|
loadGraph
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-KDU4EF66.js";
|
|
34
34
|
import {
|
|
35
35
|
isBackbone
|
|
36
36
|
} from "./chunk-RJWPJCIB.js";
|
|
@@ -4,27 +4,27 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
facetLifts,
|
|
6
6
|
walkLift
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-C3NT37C3.js";
|
|
8
8
|
import {
|
|
9
9
|
walkKey
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-D4ZFRBB4.js";
|
|
11
11
|
import {
|
|
12
12
|
buildGeometry,
|
|
13
13
|
computeReferenceRamp
|
|
14
14
|
} from "./chunk-SWCULW6S.js";
|
|
15
15
|
import {
|
|
16
16
|
walkRowsExtent
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-OLKXMZ6J.js";
|
|
18
18
|
import {
|
|
19
19
|
pathLegend,
|
|
20
20
|
walkLabelsOf
|
|
21
21
|
} from "./chunk-3GP3KT5L.js";
|
|
22
22
|
import {
|
|
23
23
|
FIGURE_DEFAULTS
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-W6EXQDV5.js";
|
|
25
25
|
import {
|
|
26
26
|
drawingBounds
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-KDU4EF66.js";
|
|
28
28
|
import {
|
|
29
29
|
referenceLabel
|
|
30
30
|
} from "./chunk-234NFZS4.js";
|
|
@@ -97,7 +97,7 @@ function figureScene(graph, layout, o) {
|
|
|
97
97
|
referenceName,
|
|
98
98
|
keyText: (walk) => {
|
|
99
99
|
const key = walkKey(walk, reference);
|
|
100
|
-
return { note: key.delta + key.
|
|
100
|
+
return { note: key.delta + key.gaps + key.reversed, scale: key.scale };
|
|
101
101
|
},
|
|
102
102
|
contigThickness,
|
|
103
103
|
nodeWidth,
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GAP_CAUSE_TEXT,
|
|
3
|
+
OUTSIDE_TEXT
|
|
4
|
+
} from "./chunk-EIY2SKD3.js";
|
|
1
5
|
import {
|
|
2
6
|
formatBp,
|
|
3
7
|
groupDigits
|
|
@@ -14,10 +18,15 @@ function walkKey(walk, reference) {
|
|
|
14
18
|
const own = walk.range ? rangeText(walk.range.contig, walk.range.start, walk.range.end) : void 0;
|
|
15
19
|
const scale = field === "progress" ? own : field === "reference" && reference ? rangeText(reference.name, reference.start, reference.end) : void 0;
|
|
16
20
|
const spanned = walk.range ? walk.range.end - walk.range.start : walk.bp;
|
|
17
|
-
const outside = spanned - walk.bp;
|
|
21
|
+
const outside = spanned - walk.bp - walk.missingBp - walk.unknownBp;
|
|
22
|
+
const gaps = [
|
|
23
|
+
[walk.missingBp, GAP_CAUSE_TEXT.missing],
|
|
24
|
+
[walk.unknownBp, GAP_CAUSE_TEXT.unknown],
|
|
25
|
+
[outside, OUTSIDE_TEXT]
|
|
26
|
+
];
|
|
18
27
|
return {
|
|
19
28
|
delta: walk.referenceBp === void 0 || spanned === walk.referenceBp ? "" : ` ${spanned > walk.referenceBp ? "+" : "\u2212"}${formatBp(Math.abs(spanned - walk.referenceBp))}`,
|
|
20
|
-
|
|
29
|
+
gaps: gaps.filter(([bp]) => bp > 0).map(([bp, text]) => `, ${formatBp(bp)} ${text}`).join(""),
|
|
21
30
|
reversed: walk.reversedBp > 0 ? `, ${formatBp(walk.reversedBp)} reversed` : "",
|
|
22
31
|
shades: field !== "walk",
|
|
23
32
|
scale,
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
END_STOP_TAG,
|
|
3
|
+
START_STOP_TAG,
|
|
4
|
+
StopColumns,
|
|
5
|
+
parseStopTag
|
|
6
|
+
} from "./chunk-EIY2SKD3.js";
|
|
1
7
|
import {
|
|
2
8
|
Column
|
|
3
9
|
} from "./chunk-ZPZ7GNBT.js";
|
|
@@ -103,6 +109,7 @@ function readWalkBody(line, from, segments, steps) {
|
|
|
103
109
|
}
|
|
104
110
|
}
|
|
105
111
|
finish(i);
|
|
112
|
+
return i;
|
|
106
113
|
}
|
|
107
114
|
function walkFields(line) {
|
|
108
115
|
const fields = [];
|
|
@@ -159,6 +166,8 @@ function gfaTables(text) {
|
|
|
159
166
|
const walkEnds = [];
|
|
160
167
|
const offsets = [0];
|
|
161
168
|
const steps = stepColumns();
|
|
169
|
+
const before = new StopColumns();
|
|
170
|
+
const after = new StopColumns();
|
|
162
171
|
for (const raw of lines) {
|
|
163
172
|
if (raw.startsWith("L ")) {
|
|
164
173
|
const [, source, strand1, target, strand2] = trimCR(raw).split(" ");
|
|
@@ -174,7 +183,17 @@ function gfaTables(text) {
|
|
|
174
183
|
names.push(`${w.sample}#${w.haplotype}#${w.contig}`);
|
|
175
184
|
walkStarts.push(w.start === "*" ? 0 : +w.start);
|
|
176
185
|
walkEnds.push(w.end === "*" ? -1 : +w.end);
|
|
177
|
-
readWalkBody(line, w.body, segments, steps);
|
|
186
|
+
const end = readWalkBody(line, w.body, segments, steps);
|
|
187
|
+
const tags = walkTags(line, end);
|
|
188
|
+
if (tags === void 0) {
|
|
189
|
+
return void 0;
|
|
190
|
+
}
|
|
191
|
+
if (tags.before) {
|
|
192
|
+
before.push(tags.before);
|
|
193
|
+
}
|
|
194
|
+
if (tags.after) {
|
|
195
|
+
after.push(tags.after);
|
|
196
|
+
}
|
|
178
197
|
if (steps.nodes.length === offsets.at(-1)) {
|
|
179
198
|
return void 0;
|
|
180
199
|
}
|
|
@@ -182,6 +201,11 @@ function gfaTables(text) {
|
|
|
182
201
|
}
|
|
183
202
|
}
|
|
184
203
|
}
|
|
204
|
+
if ([before.kinds.length, after.kinds.length].some(
|
|
205
|
+
(n) => n > 0 && n < names.length
|
|
206
|
+
)) {
|
|
207
|
+
return void 0;
|
|
208
|
+
}
|
|
185
209
|
return {
|
|
186
210
|
nodes: {
|
|
187
211
|
names: segments.names,
|
|
@@ -202,8 +226,33 @@ function gfaTables(text) {
|
|
|
202
226
|
ends: Float64Array.from(walkEnds),
|
|
203
227
|
offsets: Int32Array.from(offsets),
|
|
204
228
|
steps: steps.nodes.data.slice(0, steps.nodes.length),
|
|
205
|
-
reversed: steps.reversed.data.slice(0, steps.reversed.length)
|
|
229
|
+
reversed: steps.reversed.data.slice(0, steps.reversed.length),
|
|
230
|
+
...stopColumns(names.length, before, after)
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function walkTags(line, from) {
|
|
235
|
+
const out = {};
|
|
236
|
+
for (const tag of from < line.length ? line.slice(from + 1).split(" ") : []) {
|
|
237
|
+
const value = tag.slice(5);
|
|
238
|
+
if (tag.startsWith(`${START_STOP_TAG}:Z:`)) {
|
|
239
|
+
out.before = parseStopTag(value);
|
|
240
|
+
if (!out.before) {
|
|
241
|
+
return void 0;
|
|
242
|
+
}
|
|
243
|
+
} else if (tag.startsWith(`${END_STOP_TAG}:Z:`)) {
|
|
244
|
+
out.after = parseStopTag(value);
|
|
245
|
+
if (!out.after) {
|
|
246
|
+
return void 0;
|
|
247
|
+
}
|
|
206
248
|
}
|
|
249
|
+
}
|
|
250
|
+
return out;
|
|
251
|
+
}
|
|
252
|
+
function stopColumns(walks, before, after) {
|
|
253
|
+
return {
|
|
254
|
+
...before.kinds.length === walks && walks > 0 ? { before: before.table() } : {},
|
|
255
|
+
...after.kinds.length === walks && walks > 0 ? { after: after.table() } : {}
|
|
207
256
|
};
|
|
208
257
|
}
|
|
209
258
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
sampleRowLayout
|
|
3
|
-
} from "./chunk-GJU6BJJA.js";
|
|
4
1
|
import {
|
|
5
2
|
hasTubeMapBackbone,
|
|
6
3
|
hasTubeMapPaths,
|
|
7
4
|
tubeMapLayout,
|
|
8
5
|
tubeMapReferenceLayout
|
|
9
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PK5QQOMN.js";
|
|
7
|
+
import {
|
|
8
|
+
sampleRowLayout
|
|
9
|
+
} from "./chunk-GJU6BJJA.js";
|
|
10
10
|
import {
|
|
11
11
|
anchoredLayout
|
|
12
12
|
} from "./chunk-GJLZ2MKE.js";
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "./chunk-UAFATXYA.js";
|
|
16
16
|
import {
|
|
17
17
|
walkRowLayout
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-OLKXMZ6J.js";
|
|
19
19
|
import {
|
|
20
20
|
isBackbone,
|
|
21
21
|
isOffReference
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// src/gfa/walkStops.ts
|
|
2
|
+
var START_STOP_TAG = "ws";
|
|
3
|
+
var END_STOP_TAG = "we";
|
|
4
|
+
var STOP_KINDS = ["elsewhere", "break", "end"];
|
|
5
|
+
var GAP_CAUSE_TEXT = {
|
|
6
|
+
missing: "not in the graph",
|
|
7
|
+
elsewhere: "on nodes filed elsewhere",
|
|
8
|
+
unknown: "gap, cause unknown"
|
|
9
|
+
};
|
|
10
|
+
var OUTSIDE_TEXT = "outside the extracted subgraph";
|
|
11
|
+
function gapParts(bp, after, before) {
|
|
12
|
+
if (!after && !before) {
|
|
13
|
+
return [{ bp }];
|
|
14
|
+
}
|
|
15
|
+
const left = Math.min(after?.trimmed ?? 0, bp);
|
|
16
|
+
const right = Math.min(before?.trimmed ?? 0, bp - left);
|
|
17
|
+
let rest = bp - left - right;
|
|
18
|
+
const lead = after?.kind === "break" ? Math.min(after.bp, rest) : 0;
|
|
19
|
+
rest -= lead;
|
|
20
|
+
const trail = before?.kind === "break" ? Math.min(before.bp, rest) : 0;
|
|
21
|
+
rest -= trail;
|
|
22
|
+
const elsewhere = [after, before].find((s) => s?.kind === "elsewhere");
|
|
23
|
+
const parts = [
|
|
24
|
+
{ bp: left },
|
|
25
|
+
{ bp: lead, cause: "missing" },
|
|
26
|
+
elsewhere?.kind === "elsewhere" ? { bp: rest, cause: "elsewhere", chunk: elsewhere.chunk } : { bp: rest, cause: "unknown" },
|
|
27
|
+
{ bp: trail, cause: "missing" },
|
|
28
|
+
{ bp: right }
|
|
29
|
+
];
|
|
30
|
+
return parts.filter((part) => part.bp > 0);
|
|
31
|
+
}
|
|
32
|
+
function stopAt(table, i) {
|
|
33
|
+
const bp = table.bp[i];
|
|
34
|
+
const ref = table.chunkRefs[i];
|
|
35
|
+
return stopOf(
|
|
36
|
+
table.kindNames[table.kinds[i]],
|
|
37
|
+
Number.isNaN(bp) ? void 0 : bp,
|
|
38
|
+
table.trimmed[i],
|
|
39
|
+
ref < 0 ? void 0 : { refName: table.chunkRefNames[ref], start: table.chunkStarts[i] }
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
function stopOf(kind, bp, trimmed, chunk) {
|
|
43
|
+
const cut = trimmed > 0 ? { trimmed } : {};
|
|
44
|
+
if (kind === "elsewhere" && chunk) {
|
|
45
|
+
return { kind, chunk, ...bp === void 0 ? {} : { bp }, ...cut };
|
|
46
|
+
}
|
|
47
|
+
if (kind === "break" && bp !== void 0) {
|
|
48
|
+
return { kind, bp, ...chunk ? { chunk } : {}, ...cut };
|
|
49
|
+
}
|
|
50
|
+
return kind === "end" ? { kind, ...cut } : void 0;
|
|
51
|
+
}
|
|
52
|
+
function stopTag(stop) {
|
|
53
|
+
const parts = [stop.kind];
|
|
54
|
+
if ("bp" in stop && stop.bp !== void 0) {
|
|
55
|
+
parts.push(`bp=${stop.bp}`);
|
|
56
|
+
}
|
|
57
|
+
if (stop.trimmed) {
|
|
58
|
+
parts.push(`trimmed=${stop.trimmed}`);
|
|
59
|
+
}
|
|
60
|
+
if ("chunk" in stop && stop.chunk) {
|
|
61
|
+
parts.push(`chunk=${stop.chunk.refName}:${stop.chunk.start}`);
|
|
62
|
+
}
|
|
63
|
+
return parts.join(",");
|
|
64
|
+
}
|
|
65
|
+
function parseStopTag(value) {
|
|
66
|
+
const [kind, ...fields] = value.split(",");
|
|
67
|
+
let bp;
|
|
68
|
+
let trimmed = 0;
|
|
69
|
+
let chunk;
|
|
70
|
+
for (const field of fields) {
|
|
71
|
+
if (field.startsWith("bp=")) {
|
|
72
|
+
bp = +field.slice(3);
|
|
73
|
+
} else if (field.startsWith("trimmed=")) {
|
|
74
|
+
trimmed = +field.slice(8);
|
|
75
|
+
} else if (field.startsWith("chunk=")) {
|
|
76
|
+
const at = field.lastIndexOf(":");
|
|
77
|
+
chunk = { refName: field.slice(6, at), start: +field.slice(at + 1) };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return stopOf(kind, bp, trimmed, chunk);
|
|
81
|
+
}
|
|
82
|
+
function stopFields(before, after) {
|
|
83
|
+
return {
|
|
84
|
+
...before ? { before } : {},
|
|
85
|
+
...after ? { after } : {}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function walkStopFields(tags) {
|
|
89
|
+
const before = tags[START_STOP_TAG];
|
|
90
|
+
const after = tags[END_STOP_TAG];
|
|
91
|
+
return stopFields(
|
|
92
|
+
typeof before === "string" ? parseStopTag(before) : void 0,
|
|
93
|
+
typeof after === "string" ? parseStopTag(after) : void 0
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
function walkStopTags(walks, p) {
|
|
97
|
+
const tags = [];
|
|
98
|
+
for (const [tag, table] of [
|
|
99
|
+
[START_STOP_TAG, walks.before],
|
|
100
|
+
[END_STOP_TAG, walks.after]
|
|
101
|
+
]) {
|
|
102
|
+
const stop = table && stopAt(table, p);
|
|
103
|
+
if (stop) {
|
|
104
|
+
tags.push(` ${tag}:Z:${stopTag(stop)}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return tags.join("");
|
|
108
|
+
}
|
|
109
|
+
var StopColumns = class {
|
|
110
|
+
constructor() {
|
|
111
|
+
this.kinds = [];
|
|
112
|
+
this.bp = [];
|
|
113
|
+
this.trimmed = [];
|
|
114
|
+
this.chunkRefs = [];
|
|
115
|
+
this.chunkStarts = [];
|
|
116
|
+
this.chunkRefNames = [];
|
|
117
|
+
this.refIndex = /* @__PURE__ */ new Map();
|
|
118
|
+
}
|
|
119
|
+
push(stop) {
|
|
120
|
+
this.kinds.push(STOP_KINDS.indexOf(stop.kind));
|
|
121
|
+
this.bp.push("bp" in stop && stop.bp !== void 0 ? stop.bp : NaN);
|
|
122
|
+
this.trimmed.push(stop.trimmed ?? 0);
|
|
123
|
+
const chunk = "chunk" in stop ? stop.chunk : void 0;
|
|
124
|
+
if (chunk) {
|
|
125
|
+
let ref = this.refIndex.get(chunk.refName);
|
|
126
|
+
if (ref === void 0) {
|
|
127
|
+
ref = this.chunkRefNames.length;
|
|
128
|
+
this.refIndex.set(chunk.refName, ref);
|
|
129
|
+
this.chunkRefNames.push(chunk.refName);
|
|
130
|
+
}
|
|
131
|
+
this.chunkRefs.push(ref);
|
|
132
|
+
this.chunkStarts.push(chunk.start);
|
|
133
|
+
} else {
|
|
134
|
+
this.chunkRefs.push(-1);
|
|
135
|
+
this.chunkStarts.push(NaN);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
table() {
|
|
139
|
+
return {
|
|
140
|
+
kinds: Uint8Array.from(this.kinds),
|
|
141
|
+
kindNames: [...STOP_KINDS],
|
|
142
|
+
bp: Float64Array.from(this.bp),
|
|
143
|
+
trimmed: Float64Array.from(this.trimmed),
|
|
144
|
+
chunkRefs: Int32Array.from(this.chunkRefs),
|
|
145
|
+
chunkStarts: Float64Array.from(this.chunkStarts),
|
|
146
|
+
chunkRefNames: this.chunkRefNames
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export {
|
|
152
|
+
START_STOP_TAG,
|
|
153
|
+
END_STOP_TAG,
|
|
154
|
+
GAP_CAUSE_TEXT,
|
|
155
|
+
OUTSIDE_TEXT,
|
|
156
|
+
gapParts,
|
|
157
|
+
stopAt,
|
|
158
|
+
stopTag,
|
|
159
|
+
parseStopTag,
|
|
160
|
+
stopFields,
|
|
161
|
+
walkStopFields,
|
|
162
|
+
walkStopTags,
|
|
163
|
+
StopColumns
|
|
164
|
+
};
|
|
@@ -5,6 +5,9 @@ import {
|
|
|
5
5
|
pathOrigin,
|
|
6
6
|
surveyPaths
|
|
7
7
|
} from "./chunk-B5X2RLJG.js";
|
|
8
|
+
import {
|
|
9
|
+
walkStopFields
|
|
10
|
+
} from "./chunk-EIY2SKD3.js";
|
|
8
11
|
|
|
9
12
|
// src/gfa/gfaConverter.ts
|
|
10
13
|
function surveySegments(gfaGraph, pathSteps) {
|
|
@@ -152,7 +155,8 @@ function convertGFAToGraph(gfaGraph, name = "Imported GFA") {
|
|
|
152
155
|
start: walkStart(walk),
|
|
153
156
|
sample: walk.sample,
|
|
154
157
|
haplotype: walk.haplotype,
|
|
155
|
-
contig: walk.contig
|
|
158
|
+
contig: walk.contig,
|
|
159
|
+
...walkStopFields(walk.tags)
|
|
156
160
|
});
|
|
157
161
|
recordPathEdges(nodeIds2, name2);
|
|
158
162
|
}
|