@jbrowse/bandage-core 10.3.1 → 11.1.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 (75) hide show
  1. package/README.md +5 -0
  2. package/dist/chunks/{chunk-DBLV7PGG.js → chunk-3XSRT7RQ.js} +16 -2
  3. package/dist/chunks/{chunk-BS6HPYCZ.js → chunk-77EGQQJU.js} +3 -1
  4. package/dist/chunks/chunk-7BTO7MZS.js +46 -0
  5. package/dist/chunks/{chunk-BKEZLETL.js → chunk-AI5PTOSV.js} +1 -1
  6. package/dist/chunks/{chunk-CGFPFBT2.js → chunk-D4ZFRBB4.js} +11 -2
  7. package/dist/chunks/{chunk-OOIOX36I.js → chunk-DEDD7TFJ.js} +40 -9
  8. package/dist/chunks/{chunk-YZQI35UJ.js → chunk-DR24UTRS.js} +23 -2
  9. package/dist/chunks/{chunk-Z6XZWPXK.js → chunk-DZR37KXT.js} +51 -2
  10. package/dist/chunks/chunk-EIY2SKD3.js +164 -0
  11. package/dist/chunks/{chunk-NZTYV3JL.js → chunk-FFHJGWDK.js} +5 -1
  12. package/dist/chunks/{chunk-QH2MIXBA.js → chunk-IVOK5V3H.js} +6 -6
  13. package/dist/chunks/{chunk-SFP3E4RI.js → chunk-IZ6Y5D23.js} +2 -2
  14. package/dist/chunks/{chunk-EWLXU3UG.js → chunk-JFHYG25O.js} +13 -13
  15. package/dist/chunks/{chunk-KMBE2Q42.js → chunk-KDU4EF66.js} +3 -3
  16. package/dist/chunks/{chunk-FW2R7UDZ.js → chunk-LMH5KVJZ.js} +1 -1
  17. package/dist/chunks/{chunk-AZ4EEF6Q.js → chunk-NGUM77EP.js} +5 -5
  18. package/dist/chunks/{chunk-GIHTHYXY.js → chunk-NMWQUFPF.js} +1 -1
  19. package/dist/chunks/{chunk-CHNESV7L.js → chunk-OI4YVAMM.js} +56 -9
  20. package/dist/chunks/{chunk-R2PJKD3Y.js → chunk-RETNT73O.js} +1 -1
  21. package/dist/chunks/{chunk-OXRUPNSV.js → chunk-RNYPCQZ3.js} +1 -1
  22. package/dist/chunks/{chunk-DO62DG26.js → chunk-TABI4JEU.js} +6 -4
  23. package/dist/chunks/{chunk-M5NPD55W.js → chunk-TUQKGAK3.js} +1 -1
  24. package/dist/chunks/{chunk-MWOVW4AH.js → chunk-V5MAL7LU.js} +1 -1
  25. package/dist/chunks/{chunk-D7WIYPG3.js → chunk-W6EXQDV5.js} +1 -1
  26. package/dist/chunks/{chunk-ZJBOM73S.js → chunk-XZ6PQBU6.js} +58 -12
  27. package/dist/chunks/{chunk-AQCOIE5R.js → chunk-Y3FDMDNT.js} +1 -1
  28. package/dist/chunks/{chunk-A2TJ5UX6.js → chunk-YHJ5JLBI.js} +1 -1
  29. package/dist/chunks/{chunk-WYJQIC75.js → chunk-ZUL52ZX2.js} +4 -4
  30. package/dist/cli/figure.js +42 -67
  31. package/dist/cli/fold.js +5 -4
  32. package/dist/figure.js +18 -17
  33. package/dist/figureData.js +21 -19
  34. package/dist/figureScene.js +12 -11
  35. package/dist/figureSettings.js +6 -5
  36. package/dist/gbzCut.js +4 -3
  37. package/dist/gbzWindow.js +3 -2
  38. package/dist/genes/backboneGenes.js +12 -0
  39. package/dist/genes/genePins.js +1 -1
  40. package/dist/gfa/gfaConverter.js +2 -1
  41. package/dist/gfa/gfaTables.js +2 -1
  42. package/dist/gfa/graphTables.js +2 -1
  43. package/dist/gfa/walkStops.js +28 -0
  44. package/dist/index.js +60 -38
  45. package/dist/layout/forceCache.js +6 -5
  46. package/dist/layout/tubeMapLayout.js +3 -2
  47. package/dist/layout/walkRowDraw.js +10 -1
  48. package/dist/layout/walkRowLayout.js +3 -2
  49. package/dist/layout/walkRows.js +2 -1
  50. package/dist/layout/walkStrip.js +5 -4
  51. package/dist/layoutModes.js +6 -5
  52. package/dist/pipeline.js +5 -4
  53. package/dist/tubeMap/bundle.js +4 -3
  54. package/dist/tubeMap/coarsen.js +4 -3
  55. package/dist/tubeMap/deviations.js +4 -3
  56. package/dist/tubeMap/draw.js +4 -3
  57. package/dist/types/figureData.d.ts +31 -2
  58. package/dist/types/genes/backboneGenes.d.ts +25 -0
  59. package/dist/types/genes/genePins.d.ts +1 -0
  60. package/dist/types/gfa/graphTables.d.ts +3 -0
  61. package/dist/types/gfa/walkStops.d.ts +59 -0
  62. package/dist/types/index.d.ts +7 -3
  63. package/dist/types/layout/walkRowDraw.d.ts +14 -1
  64. package/dist/types/layout/walkRows.d.ts +10 -1
  65. package/dist/types/types.d.ts +19 -0
  66. package/dist/types/version.d.ts +1 -1
  67. package/dist/types/walkEncoding.d.ts +1 -0
  68. package/dist/types/walkHighlight.d.ts +2 -0
  69. package/dist/types/walkKey.d.ts +1 -1
  70. package/dist/version.js +1 -1
  71. package/dist/viewport.js +6 -5
  72. package/dist/walkEncoding.js +1 -1
  73. package/dist/walkHighlight.js +3 -2
  74. package/dist/walkKey.js +2 -1
  75. 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({ name: pathName, nodeIds, start, ...fields });
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");
@@ -50,6 +50,7 @@ function genePins(graph, genes, positions) {
50
50
  nodeIds.add(node.id);
51
51
  covered += Math.min(nodeEnd, gene.end) - Math.max(nodeStart, gene.start);
52
52
  const nodeParts = [];
53
+ const stretches = [];
53
54
  for (const exon of gene.exons) {
54
55
  const a = Math.max(exon.start, nodeStart);
55
56
  const b = Math.min(exon.end, nodeEnd);
@@ -65,10 +66,11 @@ function genePins(graph, genes, positions) {
65
66
  stretch.push({ ...stretch[0] });
66
67
  }
67
68
  nodeParts.push(svgPath(stretch));
69
+ stretches.push(stretch);
68
70
  }
69
71
  if (nodeParts.length > 0) {
70
72
  parts.push(...nodeParts);
71
- exonsByNode.push({ nodeId: node.id, d: nodeParts.join("") });
73
+ exonsByNode.push({ nodeId: node.id, d: nodeParts.join(""), stretches });
72
74
  }
73
75
  const pinBp = Math.min(Math.max(mid, nodeStart), nodeEnd);
74
76
  const distance = Math.abs(pinBp - mid);
@@ -0,0 +1,46 @@
1
+ import {
2
+ genesFromText
3
+ } from "./chunk-G6UIYQZR.js";
4
+ import {
5
+ featuresOnBackbone,
6
+ graphBackbone,
7
+ refNameBinding
8
+ } from "./chunk-234NFZS4.js";
9
+
10
+ // src/genes/backboneGenes.ts
11
+ async function backboneGenes(graph, source) {
12
+ const backbone = graphBackbone(graph);
13
+ if (!backbone) {
14
+ return { genes: [] };
15
+ }
16
+ const bind = refNameBinding(
17
+ backbone.contigs.map((c) => c.refName),
18
+ source.refNames
19
+ );
20
+ let names;
21
+ let features;
22
+ if ("indexed" in source) {
23
+ names = await source.indexed.getReferenceSequenceNames();
24
+ const lines = [];
25
+ for (const contig of backbone.contigs) {
26
+ const name = names.find((n) => bind(n) === contig.refName);
27
+ if (name !== void 0) {
28
+ await source.indexed.getLines(name, contig.start, contig.end, {
29
+ lineCallback: (line) => lines.push(line)
30
+ });
31
+ }
32
+ }
33
+ features = genesFromText(lines.join("\n"), source.format);
34
+ } else {
35
+ features = genesFromText(source.text, source.format);
36
+ names = [...new Set(features.map((f) => f.refName))];
37
+ }
38
+ return {
39
+ genes: featuresOnBackbone(features, backbone, source.refNames),
40
+ unbound: names.some((name) => bind(name) !== void 0) ? void 0 : { names, contigs: backbone.contigs.map((c) => c.contig) }
41
+ };
42
+ }
43
+
44
+ export {
45
+ backboneGenes
46
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clampZoom
3
- } from "./chunk-KMBE2Q42.js";
3
+ } from "./chunk-KDU4EF66.js";
4
4
 
5
5
  // src/viewport.ts
6
6
  function axisScaleOf(scale, pixelRows) {
@@ -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
- outside: outside > 0 ? `, ${formatBp(outside)} outside the cut` : "",
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,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";
@@ -19,6 +22,7 @@ function labelOf(path) {
19
22
  var NodeTable = class {
20
23
  constructor(graph) {
21
24
  this.index = /* @__PURE__ */ new Map();
25
+ this.ids = [];
22
26
  this.lengths = [];
23
27
  this.onReference = new Uint8Array(0);
24
28
  this.referenceStart = new Float64Array(0);
@@ -32,6 +36,7 @@ var NodeTable = class {
32
36
  if (i === void 0) {
33
37
  i = this.lengths.length;
34
38
  this.index.set(id, i);
39
+ this.ids.push(id);
35
40
  this.lengths.push(0);
36
41
  }
37
42
  return i;
@@ -50,10 +55,13 @@ var NodeTable = class {
50
55
  };
51
56
  function stepsOf(pieces, table) {
52
57
  const out = [];
58
+ const gaps = [];
53
59
  let end;
60
+ let previous;
54
61
  for (const piece of pieces) {
55
62
  if (end !== void 0 && piece.start !== void 0 && piece.start > end) {
56
- out.push(end - piece.start);
63
+ gaps.push(gapParts(piece.start - end, previous?.after, piece.before));
64
+ out.push(-gaps.length);
57
65
  }
58
66
  let bp = 0;
59
67
  for (const node of piece.nodes) {
@@ -61,8 +69,9 @@ function stepsOf(pieces, table) {
61
69
  bp += table.lengths[node];
62
70
  }
63
71
  end = piece.start === void 0 ? void 0 : piece.start + bp;
72
+ previous = piece;
64
73
  }
65
- return Float64Array.from(out);
74
+ return { steps: Float64Array.from(out), gaps };
66
75
  }
67
76
  function stepSpan(pieces, table, k) {
68
77
  let end;
@@ -203,10 +212,13 @@ function walkRows(graph, region, unit) {
203
212
  const path = paths2[0];
204
213
  const pieces = paths2.map((piece, p) => ({
205
214
  start: piece.start,
206
- nodes: nodes?.[p] ?? table.nodesOf(piece)
215
+ nodes: nodes?.[p] ?? table.nodesOf(piece),
216
+ before: piece.before,
217
+ after: piece.after
207
218
  })).sort((a, b) => (a.start ?? 0) - (b.start ?? 0));
219
+ const { steps, gaps } = stepsOf(pieces, table);
208
220
  const { ids, complete, from, to, stop } = sliceBetween(
209
- stepsOf(pieces, table),
221
+ steps,
210
222
  table,
211
223
  cut,
212
224
  flanked
@@ -214,24 +226,42 @@ function walkRows(graph, region, unit) {
214
226
  const contig = path.contig ?? panSNContig(pathOrigin(path.name).name);
215
227
  const axisSpan = stepSpan(pieces, table, from < 0 ? 0 : from);
216
228
  const axis = !axisSpan ? void 0 : from < 0 ? { contig, start: axisSpan.start, reversed: false } : from < to ? { contig, start: axisSpan.end, reversed: false } : { contig, start: axisSpan.start, reversed: true };
217
- const { lengths, onReference, referenceStart: referenceStart2, referenceEnd } = table;
229
+ const {
230
+ ids: nodeIds,
231
+ lengths,
232
+ onReference,
233
+ referenceStart: referenceStart2,
234
+ referenceEnd
235
+ } = table;
218
236
  const runs = [];
237
+ const visits = [];
219
238
  let last;
220
239
  let bp = 0;
221
240
  let offReferenceBp = 0;
222
241
  let gapBp = 0;
223
242
  let step = 0;
243
+ const backwards = from >= 0 && from > to;
224
244
  for (const node of ids) {
225
245
  if (node < 0) {
226
- last = { start: bp, bp: -node, onReference: false, gap: true };
227
- runs.push(last);
228
- bp -= node;
229
- gapBp -= node;
246
+ const parts = gaps[-node - 1];
247
+ for (const { bp: partBp, ...why } of backwards ? [...parts].reverse() : parts) {
248
+ last = {
249
+ start: bp,
250
+ bp: partBp,
251
+ onReference: false,
252
+ gap: true,
253
+ ...why
254
+ };
255
+ runs.push(last);
256
+ bp += partBp;
257
+ gapBp += partBp;
258
+ }
230
259
  step = 0;
231
260
  continue;
232
261
  }
233
262
  const len = lengths[node];
234
263
  const on = onReference[node] === 1;
264
+ visits.push({ node: nodeIds[node], start: bp, onReference: on });
235
265
  const at = last?.referenceStart;
236
266
  const forward = on && at !== void 0 && step >= 0 && at + last.bp === referenceStart2[node];
237
267
  const backward = on && at !== void 0 && step <= 0 && referenceEnd[node] === at;
@@ -270,6 +300,7 @@ function walkRows(graph, region, unit) {
270
300
  complete,
271
301
  stop,
272
302
  runs,
303
+ visits,
273
304
  axis
274
305
  };
275
306
  };
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  encodedColor,
3
3
  resolveEncoding
4
- } from "./chunk-DO62DG26.js";
4
+ } from "./chunk-TABI4JEU.js";
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,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
 
@@ -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
  }
@@ -4,27 +4,27 @@ import {
4
4
  import {
5
5
  facetLifts,
6
6
  walkLift
7
- } from "./chunk-YZQI35UJ.js";
7
+ } from "./chunk-DR24UTRS.js";
8
8
  import {
9
9
  walkKey
10
- } from "./chunk-CGFPFBT2.js";
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-A2TJ5UX6.js";
17
+ } from "./chunk-YHJ5JLBI.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-D7WIYPG3.js";
24
+ } from "./chunk-W6EXQDV5.js";
25
25
  import {
26
26
  drawingBounds
27
- } from "./chunk-KMBE2Q42.js";
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.outside + key.reversed, scale: key.scale };
100
+ return { note: key.delta + key.gaps + key.reversed, scale: key.scale };
101
101
  },
102
102
  contigThickness,
103
103
  nodeWidth,
@@ -3,14 +3,14 @@ import {
3
3
  boxesGenes,
4
4
  rowPitch,
5
5
  rowSpan
6
- } from "./chunk-ZJBOM73S.js";
6
+ } from "./chunk-XZ6PQBU6.js";
7
7
  import {
8
8
  el
9
9
  } from "./chunk-H2H4Y3TV.js";
10
10
  import {
11
11
  READOUT_ROOM,
12
12
  longestBar
13
- } from "./chunk-A2TJ5UX6.js";
13
+ } from "./chunk-YHJ5JLBI.js";
14
14
  import {
15
15
  pathOrigin
16
16
  } from "./chunk-B5X2RLJG.js";