@jbrowse/bandage-core 11.4.0 → 11.6.1

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 (142) hide show
  1. package/dist/alleleProjection/projectAlleles.js +1 -1
  2. package/dist/bubbles/bubbleHalos.js +9 -6
  3. package/dist/bubbles/classifyBubble.js +8 -5
  4. package/dist/bubbles/popBubble.js +3 -3
  5. package/dist/bubbles/superbubbles.js +11 -11
  6. package/dist/chunks/{chunk-FFHJGWDK.js → chunk-2C5SATRZ.js} +5 -5
  7. package/dist/chunks/{chunk-4XWZNPQ2.js → chunk-2JL2JVZ2.js} +1 -1
  8. package/dist/chunks/{chunk-BZFOFC4D.js → chunk-2VMKQKVO.js} +17 -7
  9. package/dist/chunks/{chunk-GM7M25NW.js → chunk-2XEAITWM.js} +15 -5
  10. package/dist/chunks/{chunk-7BTO7MZS.js → chunk-376YFQOY.js} +2 -2
  11. package/dist/chunks/{chunk-EFD753MS.js → chunk-3FWNQNF7.js} +1 -1
  12. package/dist/chunks/{chunk-B5X2RLJG.js → chunk-3YBP46PB.js} +27 -2
  13. package/dist/chunks/{chunk-EJRJAAN7.js → chunk-4DMSPNYV.js} +47 -27
  14. package/dist/chunks/{chunk-I4BYUNJN.js → chunk-4WXFQOYV.js} +5 -5
  15. package/dist/chunks/{chunk-OMUPUB4J.js → chunk-56L6R6D2.js} +2 -2
  16. package/dist/chunks/{chunk-C44YRP5F.js → chunk-5OJZV6YT.js} +3 -2
  17. package/dist/chunks/{chunk-234NFZS4.js → chunk-5ORP7EFJ.js} +1 -1
  18. package/dist/chunks/{chunk-TUQKGAK3.js → chunk-5WB7O7IT.js} +4 -4
  19. package/dist/chunks/{chunk-3VCKBSML.js → chunk-6YRSOL4K.js} +2 -2
  20. package/dist/chunks/{chunk-REOWLPH4.js → chunk-7OTWJQGA.js} +13 -13
  21. package/dist/chunks/{chunk-77EGQQJU.js → chunk-BFUS3ENH.js} +2 -2
  22. package/dist/chunks/{chunk-TGUFT6KK.js → chunk-BLUEFYIR.js} +4 -1
  23. package/dist/chunks/{chunk-JQ52XYD2.js → chunk-BVWMVWLJ.js} +12 -12
  24. package/dist/chunks/{chunk-3GP3KT5L.js → chunk-BW2NMXRV.js} +5 -5
  25. package/dist/chunks/{chunk-2Q22S52W.js → chunk-C6E6HXP5.js} +8 -8
  26. package/dist/chunks/{chunk-5I3K4R2G.js → chunk-CFXXFHRK.js} +2 -1
  27. package/dist/chunks/{chunk-JMABOQWL.js → chunk-CO6RGQAD.js} +1 -6
  28. package/dist/chunks/{chunk-M75QPZNJ.js → chunk-D3E7AXBB.js} +68 -26
  29. package/dist/chunks/{chunk-CGMSKIEO.js → chunk-DV5B5UU7.js} +55 -8
  30. package/dist/chunks/{chunk-G6UIYQZR.js → chunk-EQDQ7P4Y.js} +3 -2
  31. package/dist/chunks/{chunk-FRTYQQDI.js → chunk-EVXXFMZ7.js} +9 -9
  32. package/dist/chunks/{chunk-BXLLMWC3.js → chunk-F3KQQDKP.js} +1 -1
  33. package/dist/chunks/{chunk-6EOB6ANX.js → chunk-GZ36HNPJ.js} +1 -1
  34. package/dist/chunks/{chunk-3HGYGISG.js → chunk-HV35LDYH.js} +3 -3
  35. package/dist/chunks/{chunk-XSF4RQRP.js → chunk-JGHZ3N34.js} +22 -15
  36. package/dist/chunks/{chunk-D4ZFRBB4.js → chunk-JGQQAUVL.js} +3 -3
  37. package/dist/chunks/{chunk-PSCSZSVK.js → chunk-KA4F3N55.js} +4 -4
  38. package/dist/chunks/{chunk-SOMZGDVS.js → chunk-KJDERUQF.js} +1 -1
  39. package/dist/chunks/{chunk-E4ZM4OOJ.js → chunk-KZMSSPS6.js} +2 -2
  40. package/dist/chunks/{chunk-JDZ5GTZT.js → chunk-MEVTV4FI.js} +1 -1
  41. package/dist/chunks/{chunk-PNMJFFNB.js → chunk-MHZTTLBU.js} +1 -1
  42. package/dist/chunks/{chunk-VIQL7GZ4.js → chunk-MXLYBDOX.js} +14 -13
  43. package/dist/chunks/{chunk-3LZ334X4.js → chunk-NXBW6KY6.js} +6 -7
  44. package/dist/chunks/{chunk-7O7EGTYG.js → chunk-OUM54ZSQ.js} +2 -2
  45. package/dist/chunks/{chunk-WA5WNP6V.js → chunk-OYCQVJYY.js} +1 -1
  46. package/dist/chunks/{chunk-TZLEHZVC.js → chunk-P5PBJONQ.js} +1 -1
  47. package/dist/chunks/chunk-PQIFYQVI.js +21 -0
  48. package/dist/chunks/{chunk-6VVGFQ7S.js → chunk-QCOVHLJO.js} +1 -1
  49. package/dist/chunks/{chunk-TEXAKEJX.js → chunk-QD35GH4C.js} +3 -3
  50. package/dist/chunks/{chunk-CE6ZIKJX.js → chunk-RLCYVZ4B.js} +1 -1
  51. package/dist/chunks/{chunk-6YJESZND.js → chunk-ROLACYCO.js} +20 -20
  52. package/dist/chunks/{chunk-A7H753BA.js → chunk-SDI6BVG7.js} +5 -6
  53. package/dist/chunks/{chunk-A4JDEUAI.js → chunk-SNF2MIEF.js} +1 -1
  54. package/dist/chunks/{chunk-NMWQUFPF.js → chunk-SVVFWTG4.js} +2 -2
  55. package/dist/chunks/{chunk-PFRQBCGC.js → chunk-T3H5ELLA.js} +4 -4
  56. package/dist/chunks/{chunk-QM7KEWWT.js → chunk-TXTSE44S.js} +1 -1
  57. package/dist/chunks/{chunk-UBQSRCWR.js → chunk-VACK24HF.js} +43 -3
  58. package/dist/chunks/{chunk-HSVFCA2J.js → chunk-VO6FKNZE.js} +1 -1
  59. package/dist/chunks/{chunk-B5ARSBOH.js → chunk-W2YAW36J.js} +8 -7
  60. package/dist/chunks/{chunk-TJOOHTJ6.js → chunk-WI6SUU5B.js} +2 -2
  61. package/dist/chunks/{chunk-GJU6BJJA.js → chunk-XR2HMGAS.js} +1 -1
  62. package/dist/chunks/{chunk-N7G5ROIV.js → chunk-XXOBCANT.js} +26 -12
  63. package/dist/chunks/{chunk-G3I4TCEZ.js → chunk-YEYQFNFQ.js} +1 -1
  64. package/dist/chunks/{chunk-UFUSPK2A.js → chunk-YYIU7P73.js} +4 -1
  65. package/dist/chunks/{chunk-CRCD3ODN.js → chunk-ZANALBSX.js} +11 -3
  66. package/dist/cli/figure.js +52 -47
  67. package/dist/cli/fold.js +12 -12
  68. package/dist/deletionEdges.js +5 -2
  69. package/dist/facetGrid.js +2 -2
  70. package/dist/figure.js +36 -36
  71. package/dist/figureData.js +38 -38
  72. package/dist/figureScene.js +26 -26
  73. package/dist/figureSettings.js +12 -12
  74. package/dist/foldVariants.js +2 -2
  75. package/dist/gaf/parseGaf.js +1 -1
  76. package/dist/gbzCut.js +4 -4
  77. package/dist/gbzWindow.js +3 -3
  78. package/dist/genes/backboneGenes.js +4 -4
  79. package/dist/genes/geneFiles.js +1 -1
  80. package/dist/genes/genePins.js +3 -3
  81. package/dist/gfa/gfaConverter.js +4 -4
  82. package/dist/gfa/graphTables.js +2 -2
  83. package/dist/gfa-core/gfaParser.js +1 -1
  84. package/dist/gfa-core/index.js +1 -1
  85. package/dist/graphLabels.js +7 -4
  86. package/dist/index.js +96 -90
  87. package/dist/labelLayout.js +11 -8
  88. package/dist/layout/anchoredLayout.js +1 -1
  89. package/dist/layout/forceCache.js +12 -12
  90. package/dist/layout/mergeRuns.js +2 -2
  91. package/dist/layout/placeOffReference.js +1 -1
  92. package/dist/layout/sampleRowLayout.js +2 -2
  93. package/dist/layout/trimToWindow.js +2 -2
  94. package/dist/layout/tubeMapLayout.js +14 -14
  95. package/dist/layout/walkRowDraw.js +12 -12
  96. package/dist/layout/walkRowLayout.js +7 -7
  97. package/dist/layout/walkRowLinks.js +1 -1
  98. package/dist/layout/walkRowRuns.js +4 -4
  99. package/dist/layout/walkRows.js +5 -5
  100. package/dist/layout/walkStrip.js +17 -17
  101. package/dist/layoutEngines.js +1 -1
  102. package/dist/layoutModes.js +17 -17
  103. package/dist/locus.js +8 -0
  104. package/dist/nodeWidths.js +5 -3
  105. package/dist/pansn.js +1 -1
  106. package/dist/pathAnchoring.js +4 -2
  107. package/dist/pathColors.js +8 -8
  108. package/dist/pipeline.js +11 -11
  109. package/dist/reference.js +2 -2
  110. package/dist/referenceStrip.js +12 -12
  111. package/dist/renderer/Canvas2DRenderer.js +1 -1
  112. package/dist/renderer/GeometryBuilder.js +15 -13
  113. package/dist/tubeMap/axis.js +8 -5
  114. package/dist/tubeMap/bundle.js +15 -15
  115. package/dist/tubeMap/coarsen.js +15 -15
  116. package/dist/tubeMap/deviations.js +18 -18
  117. package/dist/tubeMap/draw.js +10 -8
  118. package/dist/tubeMap/genes.js +9 -6
  119. package/dist/tubeMap/nodeColors.js +12 -12
  120. package/dist/tubeMap/reads.js +4 -4
  121. package/dist/types/figureData.d.ts +12 -0
  122. package/dist/types/gaf/parseGaf.d.ts +1 -1
  123. package/dist/types/gfa/graphTables.d.ts +3 -2
  124. package/dist/types/index.d.ts +1 -0
  125. package/dist/types/locus.d.ts +10 -0
  126. package/dist/types/nodeWidths.d.ts +2 -1
  127. package/dist/types/pathAnchoring.d.ts +2 -0
  128. package/dist/types/renderer/Canvas2DRenderer.d.ts +2 -0
  129. package/dist/types/renderer/GeometryBuilder.d.ts +1 -0
  130. package/dist/types/tubeMap/reads.d.ts +0 -1
  131. package/dist/types/util/geometry.d.ts +7 -1
  132. package/dist/types/version.d.ts +1 -1
  133. package/dist/util/SpatialIndex.js +7 -4
  134. package/dist/util/edgeCurves.js +6 -3
  135. package/dist/util/geometry.js +1 -1
  136. package/dist/util/hitDetection.js +8 -5
  137. package/dist/version.js +1 -1
  138. package/dist/viewport.js +12 -12
  139. package/dist/walkEncoding.js +12 -12
  140. package/dist/walkHighlight.js +13 -13
  141. package/dist/walkKey.js +8 -5
  142. package/package.json +1 -1
@@ -4,41 +4,41 @@ import {
4
4
  import {
5
5
  facetLifts,
6
6
  walkLift
7
- } from "./chunk-FRTYQQDI.js";
8
- import {
9
- walkKey
10
- } from "./chunk-D4ZFRBB4.js";
7
+ } from "./chunk-EVXXFMZ7.js";
11
8
  import {
12
9
  buildGeometry,
13
10
  computeReferenceRamp
14
- } from "./chunk-XSF4RQRP.js";
11
+ } from "./chunk-JGHZ3N34.js";
12
+ import {
13
+ walkKey
14
+ } from "./chunk-JGQQAUVL.js";
15
15
  import {
16
16
  walkRowsExtent
17
- } from "./chunk-TZLEHZVC.js";
17
+ } from "./chunk-P5PBJONQ.js";
18
18
  import {
19
19
  pathLegend,
20
20
  walkLabelsOf
21
- } from "./chunk-3GP3KT5L.js";
21
+ } from "./chunk-BW2NMXRV.js";
22
22
  import {
23
23
  FIGURE_DEFAULTS
24
- } from "./chunk-EFD753MS.js";
24
+ } from "./chunk-3FWNQNF7.js";
25
25
  import {
26
26
  drawingBounds
27
- } from "./chunk-REOWLPH4.js";
27
+ } from "./chunk-7OTWJQGA.js";
28
28
  import {
29
29
  referenceLabel
30
- } from "./chunk-234NFZS4.js";
30
+ } from "./chunk-5ORP7EFJ.js";
31
31
  import {
32
32
  resolveColorScheme
33
33
  } from "./chunk-JKJWSY4V.js";
34
34
  import {
35
35
  deletionDrawing,
36
36
  deletionEdges
37
- } from "./chunk-CGMSKIEO.js";
37
+ } from "./chunk-DV5B5UU7.js";
38
38
  import {
39
39
  facetCells,
40
40
  facetSettingOf
41
- } from "./chunk-TGUFT6KK.js";
41
+ } from "./chunk-BLUEFYIR.js";
42
42
 
43
43
  // src/figureScene.ts
44
44
  function figureScene(graph, layout, o) {
@@ -1,12 +1,12 @@
1
- import {
2
- pathOrigin
3
- } from "./chunk-B5X2RLJG.js";
4
1
  import {
5
2
  groupDigits
6
- } from "./chunk-PFRQBCGC.js";
3
+ } from "./chunk-T3H5ELLA.js";
4
+ import {
5
+ pathOrigin
6
+ } from "./chunk-3YBP46PB.js";
7
7
  import {
8
8
  isGenericSample
9
- } from "./chunk-4XWZNPQ2.js";
9
+ } from "./chunk-2JL2JVZ2.js";
10
10
 
11
11
  // src/pathColors.ts
12
12
  function nameHue(name) {
@@ -1,3 +1,6 @@
1
+ import {
2
+ coversGraph
3
+ } from "./chunk-KZMSSPS6.js";
1
4
  import {
2
5
  bubblesFromGraph,
3
6
  derivedBubble,
@@ -5,18 +8,15 @@ import {
5
8
  walkIndexOf,
6
9
  walkRoutes
7
10
  } from "./chunk-RFG42VIO.js";
8
- import {
9
- bubbleSubgraph
10
- } from "./chunk-PNMJFFNB.js";
11
- import {
12
- coversGraph
13
- } from "./chunk-E4ZM4OOJ.js";
14
11
  import {
15
12
  bubbleSegmentIds
16
- } from "./chunk-A4JDEUAI.js";
13
+ } from "./chunk-SNF2MIEF.js";
14
+ import {
15
+ bubbleSubgraph
16
+ } from "./chunk-MHZTTLBU.js";
17
17
  import {
18
18
  strandSides
19
- } from "./chunk-UBQSRCWR.js";
19
+ } from "./chunk-VACK24HF.js";
20
20
  import {
21
21
  pushTo
22
22
  } from "./chunk-BSOZW3FC.js";
@@ -57,7 +57,8 @@ function parseGFA(file) {
57
57
  };
58
58
  for (const rawLine of file.split("\n")) {
59
59
  const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
60
- const type = line.split(" ", 1)[0];
60
+ const tab = line.indexOf(" ");
61
+ const type = tab === -1 ? line : line.slice(0, tab);
61
62
  if (type === "H") {
62
63
  const [, ...rest] = line.split(" ");
63
64
  graph.header.push(parseTags(rest));
@@ -18,13 +18,8 @@ function isLayoutEngineKind(value) {
18
18
  return LAYOUT_ENGINE_VALUES.includes(value);
19
19
  }
20
20
  var layoutEngine = async (request) => {
21
- if (request.options.engine === "stress") {
22
- const start2 = performance.now();
23
- const result2 = stressLayout(request);
24
- return { result: result2, duration: performance.now() - start2 };
25
- }
26
21
  const start = performance.now();
27
- const result = await fmmmLayout(request);
22
+ const result = request.options.engine === "stress" ? stressLayout(request) : await fmmmLayout(request);
28
23
  return { result, duration: performance.now() - start };
29
24
  };
30
25
 
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  tableNodeIds,
3
3
  tablePath
4
- } from "./chunk-B5ARSBOH.js";
5
- import {
6
- pathOrigin
7
- } from "./chunk-B5X2RLJG.js";
4
+ } from "./chunk-W2YAW36J.js";
8
5
  import {
9
6
  gapParts
10
7
  } from "./chunk-EIY2SKD3.js";
8
+ import {
9
+ pathOrigin
10
+ } from "./chunk-3YBP46PB.js";
11
11
  import {
12
12
  groupBy
13
13
  } from "./chunk-BSOZW3FC.js";
14
14
  import {
15
15
  panSNContig,
16
16
  panSNSample
17
- } from "./chunk-4XWZNPQ2.js";
17
+ } from "./chunk-2JL2JVZ2.js";
18
18
 
19
19
  // src/layout/walkRowRuns.ts
20
20
  var RUN_ON_REFERENCE = 1;
@@ -69,8 +69,8 @@ function graphPieces(graph) {
69
69
  heads,
70
70
  from,
71
71
  to,
72
- steps,
73
- lengths,
72
+ steps: Int32Array.from(steps),
73
+ lengths: Int32Array.from(lengths),
74
74
  names,
75
75
  reference: referenceWalkName(graph)
76
76
  };
@@ -92,8 +92,8 @@ function tablePieces(tables, referencePath, visits) {
92
92
  }
93
93
  return {
94
94
  heads,
95
- from: kept.map((p) => w.offsets[p]),
96
- to: kept.map((p) => w.offsets[p + 1]),
95
+ from: Int32Array.from(kept, (p) => w.offsets[p]),
96
+ to: Int32Array.from(kept, (p) => w.offsets[p + 1]),
97
97
  steps: w.steps,
98
98
  lengths: n.lengths,
99
99
  // a visit names its node as the Graph does, which costs a pass over the
@@ -120,24 +120,35 @@ var Columns = class {
120
120
  get length() {
121
121
  return this.values[0].length;
122
122
  }
123
- push(...row) {
124
- row.forEach((v, i) => this.values[i].push(v));
123
+ push(a, b, c, d, e) {
124
+ const v = this.values;
125
+ v[0].push(a);
126
+ v[1].push(b);
127
+ v[2].push(c);
128
+ v[3].push(d);
129
+ if (e !== void 0) {
130
+ v[4].push(e);
131
+ }
125
132
  }
126
133
  endRow() {
127
134
  this.offsets.push(this.length);
128
135
  }
129
136
  // the rows in `order`, column i in the array `make[i]` makes
130
137
  reorder(order, make) {
131
- const columns = make.map((m) => m(this.length));
132
138
  const offsets = new Uint32Array(order.length + 1);
133
- let at = 0;
134
139
  order.forEach((row, i) => {
135
- for (let k = this.offsets[row]; k < this.offsets[row + 1]; k++, at++) {
136
- columns.forEach((column, c) => {
137
- column[at] = this.values[c][k];
138
- });
140
+ offsets[i + 1] = offsets[i] + this.offsets[row + 1] - this.offsets[row];
141
+ });
142
+ const columns = make.map((m, c) => {
143
+ const from = this.values[c];
144
+ const out = m(this.length);
145
+ let at = 0;
146
+ for (const row of order) {
147
+ for (let k = this.offsets[row]; k < this.offsets[row + 1]; k++) {
148
+ out[at++] = from[k];
149
+ }
139
150
  }
140
- offsets[i + 1] = at;
151
+ return out;
141
152
  });
142
153
  return { offsets, columns };
143
154
  }
@@ -168,15 +179,23 @@ function walkRowRuns(source, region, o = {}) {
168
179
  const walks = groupBy(others, nameOf);
169
180
  const spanStart = new Float64Array(names.length).fill(Number.NaN);
170
181
  const spanEnd = new Float64Array(names.length);
182
+ const revisits = /* @__PURE__ */ new Map();
171
183
  let reachesBefore = false;
172
184
  let reachesAfter = false;
173
185
  const cut = region && region.end > region.start ? region : void 0;
174
186
  for (const piece of referencePieces) {
175
187
  let pos = startOf(piece) ?? 0;
176
- for (let s = from[piece]; s < to[piece]; s++) {
188
+ for (let s = from[piece], stop = to[piece]; s < stop; s++) {
177
189
  const node = all[s];
178
190
  const len = lengthOf(node);
179
- if (Number.isNaN(spanStart[node])) {
191
+ if (!Number.isNaN(spanStart[node])) {
192
+ const starts = revisits.get(node);
193
+ if (starts) {
194
+ starts.push(pos);
195
+ } else {
196
+ revisits.set(node, [spanStart[node], pos]);
197
+ }
198
+ } else {
180
199
  spanStart[node] = pos;
181
200
  spanEnd[node] = pos + len;
182
201
  if (cut) {
@@ -241,7 +260,7 @@ function walkRowRuns(source, region, o = {}) {
241
260
  stepStart[length++] = end;
242
261
  }
243
262
  let pos = start2 ?? 0;
244
- for (let s = from[piece]; s < to[piece]; s++) {
263
+ for (let s = from[piece], stop2 = to[piece]; s < stop2; s++) {
245
264
  const node = all[s];
246
265
  steps[length] = node;
247
266
  stepStart[length++] = pos;
@@ -298,8 +317,8 @@ function walkRowRuns(source, region, o = {}) {
298
317
  let bestEnd = -Infinity;
299
318
  let bestStart = Infinity;
300
319
  for (let i = 0; i < length; i++) {
301
- if (onReference(i)) {
302
- const id = steps[i];
320
+ const id = steps[i];
321
+ if (id >= 0 && !Number.isNaN(spanStart[id])) {
303
322
  if (spanEnd[id] <= cut.start && spanEnd[id] > bestEnd) {
304
323
  bestEnd = spanEnd[id];
305
324
  i0 = i;
@@ -334,6 +353,27 @@ function walkRowRuns(source, region, o = {}) {
334
353
  let last = -1;
335
354
  let lastFlags = 0;
336
355
  let lastRef = Number.NaN;
356
+ let cursor = Number.NaN;
357
+ const placeOf = (id) => {
358
+ const starts = revisits.get(id);
359
+ if (!starts || Number.isNaN(cursor)) {
360
+ return spanStart[id];
361
+ }
362
+ const len = lengthOf(id);
363
+ let best = starts[0];
364
+ let bestGap = Infinity;
365
+ for (const start2 of starts) {
366
+ const gap = Math.min(
367
+ Math.abs(start2 - cursor),
368
+ Math.abs(start2 + len - cursor)
369
+ );
370
+ if (gap < bestGap) {
371
+ best = start2;
372
+ bestGap = gap;
373
+ }
374
+ }
375
+ return best;
376
+ };
337
377
  const [, runBp, runRef, runFlags] = runs.values;
338
378
  for (let k = lo; k < hi; k++) {
339
379
  const index = backward ? hi - 1 - (k - lo) : k;
@@ -358,12 +398,12 @@ function walkRowRuns(source, region, o = {}) {
358
398
  continue;
359
399
  }
360
400
  const len = lengthOf(id);
361
- const at = spanStart[id];
401
+ const at = placeOf(id);
362
402
  const on = !Number.isNaN(at);
363
403
  visits?.push(id, bp2, len, on ? 1 : 0);
364
404
  const placed = last >= 0 && !Number.isNaN(lastRef);
365
405
  const forward = on && placed && step >= 0 && lastRef + (runBp[last] ?? 0) === at;
366
- const back = on && placed && step <= 0 && spanEnd[id] === lastRef;
406
+ const back = on && placed && step <= 0 && at + len === lastRef;
367
407
  if (!on && last >= 0 && !(lastFlags & (RUN_ON_REFERENCE | RUN_GAP))) {
368
408
  runBp[last] += len;
369
409
  } else if (forward || back) {
@@ -383,7 +423,9 @@ function walkRowRuns(source, region, o = {}) {
383
423
  step = 0;
384
424
  }
385
425
  bp2 += len;
386
- if (!on) {
426
+ if (on) {
427
+ cursor = step < 0 ? at : at + len;
428
+ } else {
387
429
  offReferenceBp += len;
388
430
  }
389
431
  }
@@ -1,9 +1,12 @@
1
+ import {
2
+ referenceVisitStarts
3
+ } from "./chunk-3YBP46PB.js";
1
4
  import {
2
5
  computeEdgeCurves,
3
6
  edgeJoinOf,
4
7
  routedEdgeCurves,
5
8
  strandSides
6
- } from "./chunk-UBQSRCWR.js";
9
+ } from "./chunk-VACK24HF.js";
7
10
  import {
8
11
  groupBy
9
12
  } from "./chunk-BSOZW3FC.js";
@@ -11,6 +14,9 @@ import {
11
14
  firstNodeAtOrAfter,
12
15
  isBackbone
13
16
  } from "./chunk-RJWPJCIB.js";
17
+ import {
18
+ partitionPoint
19
+ } from "./chunk-HOAIOEI7.js";
14
20
 
15
21
  // src/deletionEdges.ts
16
22
  var MIN_DELETION_BP = 1;
@@ -70,22 +76,63 @@ function skipsBetween(edge, from, to, forwards) {
70
76
  const arrivesLeft = toStrand === (to.stable.strand ?? "+");
71
77
  return forwards ? leavesRight && arrivesLeft : !leavesRight && !arrivesLeft;
72
78
  }
79
+ function skippedSpan(edge, from, to, startsOf) {
80
+ let best;
81
+ for (const a of startsOf(from)) {
82
+ for (const b of startsOf(to)) {
83
+ const forwards = a <= b;
84
+ const span = forwards ? { start: a + from.length, end: b } : { start: b + to.length, end: a };
85
+ if (skipsBetween(edge, from, to, forwards) && (!best || Math.abs(span.end - span.start) < Math.abs(best.end - best.start))) {
86
+ best = span;
87
+ }
88
+ }
89
+ }
90
+ return best;
91
+ }
92
+ var COPY_SWITCH_SHARE = 0.01;
93
+ function repeatCopies(backbone, startsOf) {
94
+ const bySequence = /* @__PURE__ */ new Map();
95
+ for (const [refName, nodes] of backbone) {
96
+ const copies = nodes.flatMap((node) => {
97
+ const starts = startsOf(node);
98
+ return starts.slice(1).map((next, i) => ({
99
+ at: starts[i],
100
+ copy: next - starts[i]
101
+ }));
102
+ });
103
+ if (copies.length) {
104
+ bySequence.set(
105
+ refName,
106
+ copies.sort((a, b) => a.at - b.at)
107
+ );
108
+ }
109
+ }
110
+ return bySequence;
111
+ }
112
+ function switchesCopy(copies, start, bp) {
113
+ if (!copies) {
114
+ return false;
115
+ }
116
+ const i = partitionPoint(copies.length, (k) => copies[k].at < start);
117
+ const near = [copies[i - 1], copies[i]].filter((c) => c !== void 0).sort((a, b) => Math.abs(a.at - start) - Math.abs(b.at - start))[0];
118
+ return near !== void 0 && Math.abs(near.at - start) <= near.copy && Math.abs(bp - near.copy) <= near.copy * COPY_SWITCH_SHARE;
119
+ }
73
120
  function deletionEdges(graph) {
74
121
  const byId = new Map(graph.nodes.map((n) => [n.id, n]));
75
122
  const backbone = backboneBySequence(graph);
123
+ const startsOf = referenceVisitStarts(graph);
124
+ const copies = repeatCopies(backbone, startsOf);
76
125
  const found = [];
77
126
  for (let edgeIndex = 0; edgeIndex < graph.edges.length; edgeIndex++) {
78
127
  const edge = graph.edges[edgeIndex];
79
128
  const from = byId.get(edge.from);
80
129
  const to = byId.get(edge.to);
81
130
  if (from !== void 0 && to !== void 0 && isBackbone(from) && isBackbone(to) && from.stable.refName === to.stable.refName) {
82
- const forwards = from.stable.start <= to.stable.start;
83
- const [left, right] = forwards ? [from, to] : [to, from];
84
- const start = left.stable.start + left.length;
85
- const end = right.stable.start;
86
- const bp = end - start;
87
- if (bp >= MIN_DELETION_BP && skipsBetween(edge, from, to, forwards)) {
88
- const refName = left.stable.refName;
131
+ const span = skippedSpan(edge, from, to, startsOf);
132
+ const refName = from.stable.refName;
133
+ const bp = span ? span.end - span.start : 0;
134
+ if (span && bp >= MIN_DELETION_BP && !switchesCopy(copies.get(refName), span.start, bp)) {
135
+ const { start, end } = span;
89
136
  found.push({
90
137
  edgeIndex,
91
138
  from: edge.from,
@@ -136,13 +136,14 @@ function mergeOverlappingByName(genes) {
136
136
  }
137
137
  return out;
138
138
  }
139
+ var BED_HEADER = /^(#|track\s|browser\s)/;
139
140
  function genesFromBed(text) {
140
141
  const rows = [];
141
142
  for (const line of text.split("\n")) {
142
143
  const cols = line.replace(/\r$/, "").split(" ");
143
144
  const start = Number(cols[1]);
144
145
  const end = Number(cols[2]);
145
- if (/^(#|track|browser)/.test(line) || cols.length < 3 || !Number.isInteger(start) || !(end > start)) {
146
+ if (BED_HEADER.test(line) || cols.length < 3 || !Number.isInteger(start) || !(end > start)) {
146
147
  continue;
147
148
  }
148
149
  const refName = cols[0];
@@ -165,7 +166,7 @@ function genesFromBed(text) {
165
166
  return mergeOverlappingByName(rows);
166
167
  }
167
168
  function sniffedFormat(text) {
168
- const first = text.split("\n", 1e3).find((l) => l.trim() !== "" && !/^(#|track|browser)/.test(l));
169
+ const first = text.split("\n", 1e3).find((l) => l.trim() !== "" && !BED_HEADER.test(l));
169
170
  const cols = first?.split(" ") ?? [];
170
171
  return /^\d+$/.test(cols[1] ?? "") && /^\d+$/.test(cols[2] ?? "") ? "bed" : "gff3";
171
172
  }
@@ -1,24 +1,25 @@
1
1
  import {
2
2
  encodedColor,
3
3
  resolveEncoding
4
- } from "./chunk-GM7M25NW.js";
4
+ } from "./chunk-2XEAITWM.js";
5
5
  import {
6
- pathOrigin
7
- } from "./chunk-B5X2RLJG.js";
6
+ rampFraction
7
+ } from "./chunk-JGHZ3N34.js";
8
8
  import {
9
9
  gapParts
10
10
  } from "./chunk-EIY2SKD3.js";
11
11
  import {
12
- isBackbone
13
- } from "./chunk-RJWPJCIB.js";
12
+ pathOrigin
13
+ } from "./chunk-3YBP46PB.js";
14
14
  import {
15
15
  panSNContig
16
- } from "./chunk-4XWZNPQ2.js";
16
+ } from "./chunk-2JL2JVZ2.js";
17
17
 
18
18
  // src/walkHighlight.ts
19
19
  var isReference = (graph, name) => !!graph.referencePath && pathOrigin(name).name === graph.referencePath;
20
20
  function piecesOf(graph, name) {
21
- return (graph.paths ?? []).filter((p) => p.name === name).sort((a, b) => (a.start ?? 0) - (b.start ?? 0));
21
+ const origin = pathOrigin(name).name;
22
+ return (graph.paths ?? []).filter((p) => pathOrigin(p.name).name === origin).sort((a, b) => (a.start ?? 0) - (b.start ?? 0));
22
23
  }
23
24
  var nodesById = (graph) => new Map(graph.nodes.map((n) => [n.id, n]));
24
25
  function graphIndex(graph) {
@@ -117,8 +118,7 @@ function laneColors(byId, walk, encoding, ramp) {
117
118
  const colors = /* @__PURE__ */ new Map();
118
119
  for (const [id, progress] of walk.progress) {
119
120
  const node = byId.get(id);
120
- const mid = ramp?.midpoints.get(id);
121
- const t = encoding.field === "progress" ? progress : ramp && mid !== void 0 && node && isBackbone(node) ? (mid - ramp.start) / ramp.span : void 0;
121
+ const t = encoding.field === "progress" ? progress : ramp && node ? rampFraction(node, ramp) : void 0;
122
122
  colors.set(id, encodedColor(encoding, t));
123
123
  }
124
124
  return colors;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  engineKey,
3
3
  forceLayout
4
- } from "./chunk-REOWLPH4.js";
4
+ } from "./chunk-7OTWJQGA.js";
5
5
 
6
6
  // src/layout/forceCache.ts
7
7
  var DEFAULT_SIZE = 4;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  tubeSpan
3
- } from "./chunk-HSVFCA2J.js";
3
+ } from "./chunk-VO6FKNZE.js";
4
4
 
5
5
  // src/tubeMap/genes.ts
6
6
  function tubeMapGenes(byRefName, genes) {
@@ -6,13 +6,13 @@ import {
6
6
  } from "./chunk-MYDHU2UV.js";
7
7
  import {
8
8
  readColor
9
- } from "./chunk-A7H753BA.js";
9
+ } from "./chunk-SDI6BVG7.js";
10
10
  import {
11
11
  referenceWalkName
12
- } from "./chunk-M75QPZNJ.js";
12
+ } from "./chunk-D3E7AXBB.js";
13
13
  import {
14
14
  pathOrigin
15
- } from "./chunk-B5X2RLJG.js";
15
+ } from "./chunk-3YBP46PB.js";
16
16
  import {
17
17
  pushTo
18
18
  } from "./chunk-BSOZW3FC.js";
@@ -10,17 +10,18 @@ import {
10
10
  } from "./chunk-GQZVR5DW.js";
11
11
  import {
12
12
  baseEdgeCurves
13
- } from "./chunk-WA5WNP6V.js";
13
+ } from "./chunk-OYCQVJYY.js";
14
14
  import {
15
15
  PATH_LIGHTNESS,
16
16
  PATH_SATURATION,
17
17
  nameHue,
18
18
  pathHueAt
19
- } from "./chunk-3GP3KT5L.js";
19
+ } from "./chunk-BW2NMXRV.js";
20
20
  import {
21
21
  meanDepth,
22
- nodeWidthPx
23
- } from "./chunk-CRCD3ODN.js";
22
+ nodeWidthPx,
23
+ walkLaneWidthPx
24
+ } from "./chunk-ZANALBSX.js";
24
25
  import {
25
26
  referenceMidpoints
26
27
  } from "./chunk-VX656OAZ.js";
@@ -31,7 +32,7 @@ import {
31
32
  strandSides,
32
33
  translateCurves,
33
34
  yToXOf
34
- } from "./chunk-UBQSRCWR.js";
35
+ } from "./chunk-VACK24HF.js";
35
36
  import {
36
37
  pushTo
37
38
  } from "./chunk-BSOZW3FC.js";
@@ -51,7 +52,6 @@ var LIFT_BACKDROP_CSS = abgrToCssRgba(
51
52
  );
52
53
  var DELETION_DASH_PX = 11;
53
54
  var MIN_PATH_STRIPE_PX = 1.2;
54
- var MIN_WALK_LANE_PX = 4;
55
55
  var MIN_SCALE_FOR_OFFSET = 1e-6;
56
56
  var ARROW_LENGTH_BASE_PX = 7;
57
57
  var ARROW_LENGTH_PER_EDGE_PX = 3;
@@ -265,6 +265,10 @@ function hashColor(str, alpha) {
265
265
  var REFERENCE_RAMP_ALT_RGB = [60, 65, 72];
266
266
  var REFERENCE_RAMP_ALT_COLOR = packAbgr(...REFERENCE_RAMP_ALT_RGB, 255);
267
267
  var REFERENCE_RAMP_ALT_CSS = `rgb(${REFERENCE_RAMP_ALT_RGB.join(", ")})`;
268
+ function rampFraction(node, ramp) {
269
+ const mid = ramp.midpoints.get(node.id);
270
+ return isBackbone(node) && mid !== void 0 ? (mid - ramp.start) / ramp.span : void 0;
271
+ }
268
272
  function computeReferenceRamp(graph, domain) {
269
273
  const midpoints = referenceMidpoints(graph);
270
274
  if (domain && domain.end > domain.start) {
@@ -348,12 +352,9 @@ function getNodeColor(node, nodeIndex, colorScheme, range) {
348
352
  if (ramp === void 0) {
349
353
  return packAbgr(160, 160, 160, 255);
350
354
  }
351
- const mid = ramp.midpoints.get(node.id);
352
- if (!isBackbone(node) || mid === void 0) {
353
- return REFERENCE_RAMP_ALT_COLOR;
354
- }
355
- return packHsl(
356
- rampHueAt((mid - ramp.start) / ramp.span),
355
+ const t = rampFraction(node, ramp);
356
+ return t === void 0 ? REFERENCE_RAMP_ALT_COLOR : packHsl(
357
+ rampHueAt(t),
357
358
  REFERENCE_RAMP_SATURATION,
358
359
  REFERENCE_RAMP_LIGHTNESS
359
360
  );
@@ -517,7 +518,12 @@ function buildGeometry(options) {
517
518
  const inView = (curves) => !viewportBounds || isBezierInBounds(curves, viewportBounds);
518
519
  const stroke = (curves, thickness, color) => {
519
520
  if (isDeletion) {
520
- for (const dash of dashCurves(curves, DELETION_DASH_PX / scale)) {
521
+ for (const dash of dashCurves(
522
+ curves,
523
+ DELETION_DASH_PX / scale,
524
+ yToX,
525
+ viewportBounds
526
+ )) {
521
527
  edgeCurves.push({ curves: dash, thickness, color });
522
528
  }
523
529
  } else {
@@ -545,7 +551,7 @@ function buildGeometry(options) {
545
551
  if (laneWalks) {
546
552
  const fromNode = nodeById.get(edge.from);
547
553
  const width = fromNode ? nodeWidthPx(fromNode, contigThickness, nodeWidth, depthNorm) : contigThickness;
548
- const laneWidth = Math.max(width / laneWalks.length, MIN_WALK_LANE_PX);
554
+ const laneWidth = walkLaneWidthPx(width, laneWalks.length);
549
555
  const normals = pointNormalsOf(fromSegments, yToX);
550
556
  const { nx, ny } = (leavesStart(
551
557
  edge,
@@ -637,7 +643,7 @@ function buildGeometry(options) {
637
643
  const drawable = segments.length >= 2;
638
644
  const lanes = highlight?.walks.length && !faded && !slots?.length ? highlight.walks : void 0;
639
645
  if (drawable && lanes) {
640
- const laneWidth = Math.max(width / lanes.length, MIN_WALK_LANE_PX);
646
+ const laneWidth = walkLaneWidthPx(width, lanes.length);
641
647
  const normals = pointNormalsOf(segments, yToX);
642
648
  lanes.forEach((walk, lane) => {
643
649
  const laneColor = walk.colors.get(nodeId);
@@ -688,6 +694,7 @@ export {
688
694
  hslToRgb,
689
695
  REFERENCE_RAMP_ALT_COLOR,
690
696
  REFERENCE_RAMP_ALT_CSS,
697
+ rampFraction,
691
698
  computeReferenceRamp,
692
699
  computeColorSchemeRange,
693
700
  getNodeColor,
@@ -5,13 +5,13 @@ import {
5
5
  import {
6
6
  formatBp,
7
7
  groupDigits
8
- } from "./chunk-PFRQBCGC.js";
8
+ } from "./chunk-T3H5ELLA.js";
9
9
 
10
10
  // src/walkKey.ts
11
11
  function rangeText(contig, start, end) {
12
12
  const s = Math.round(start);
13
13
  const e = Math.round(end);
14
- return `${contig ? `${contig}:` : ""}${groupDigits(s)}-${groupDigits(e)} (${formatBp(e - s)})`;
14
+ return `${contig ? `${contig}:` : ""}${groupDigits(s + 1)}-${groupDigits(e)} (${formatBp(e - s)})`;
15
15
  }
16
16
  function walkKey(walk, reference) {
17
17
  const { field } = walk.encoding;
@@ -42,7 +42,7 @@ function walkPosition(walk, nodeId, length) {
42
42
  const start = Math.round(
43
43
  range.start + progress * (range.end - range.start) - length / 2
44
44
  );
45
- return `${range.contig}:${groupDigits(start)}-${groupDigits(start + length)}`;
45
+ return `${range.contig}:${groupDigits(start + 1)}-${groupDigits(start + length)}`;
46
46
  }
47
47
 
48
48
  export {