@jbrowse/bandage-core 11.8.0 → 11.9.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. package/dist/bubbles/bubbleHalos.js +6 -6
  2. package/dist/bubbles/classifyBubble.js +5 -5
  3. package/dist/bubbles/superbubbles.js +7 -7
  4. package/dist/chunks/{chunk-S4CH434Z.js → chunk-2A6Z2DHF.js} +1 -1
  5. package/dist/chunks/{chunk-6MD4VS2F.js → chunk-2MXFG3W7.js} +1 -1
  6. package/dist/chunks/{chunk-7GDNDQD7.js → chunk-3BDQQTXY.js} +163 -99
  7. package/dist/chunks/{chunk-MO4DIRHD.js → chunk-3BOREHCJ.js} +13 -13
  8. package/dist/chunks/{chunk-2RCKHCF7.js → chunk-3DHGSHC3.js} +1 -1
  9. package/dist/chunks/{chunk-3CXZUC2Y.js → chunk-3GORESBG.js} +1 -1
  10. package/dist/chunks/{chunk-R4XCTRIU.js → chunk-4BYGFDQB.js} +1 -1
  11. package/dist/chunks/{chunk-NHOXLUIL.js → chunk-4JDO7ZLN.js} +2 -2
  12. package/dist/chunks/{chunk-7PEYA3NA.js → chunk-7YSIP3O2.js} +2 -2
  13. package/dist/chunks/{chunk-3XYLEK4H.js → chunk-ARXDNQLF.js} +1 -1
  14. package/dist/chunks/{chunk-6CXLLJ2C.js → chunk-AURNOR27.js} +3 -3
  15. package/dist/chunks/{chunk-G4WQBRDS.js → chunk-BDS5VZYZ.js} +3 -3
  16. package/dist/chunks/{chunk-2H3ALI6L.js → chunk-GDZQFELP.js} +180 -159
  17. package/dist/chunks/{chunk-ZKIH2USC.js → chunk-GYJMPVOU.js} +1 -1
  18. package/dist/chunks/{chunk-X5ULFAMM.js → chunk-HEYIAMTC.js} +2 -2
  19. package/dist/chunks/{chunk-S7BCZVRK.js → chunk-HIN56TLA.js} +1 -1
  20. package/dist/chunks/{chunk-YIWN32ZX.js → chunk-HNNP5QUN.js} +1 -1
  21. package/dist/chunks/{chunk-XOIYBEU7.js → chunk-I53QYITQ.js} +1 -1
  22. package/dist/chunks/{chunk-R3NPBUKT.js → chunk-I5CHAYDZ.js} +7 -7
  23. package/dist/chunks/{chunk-LA6JHEVV.js → chunk-IXLT3JJX.js} +1 -1
  24. package/dist/chunks/{chunk-SDDMV2MM.js → chunk-IZKM4NY7.js} +1 -1
  25. package/dist/chunks/{chunk-SIXFXXRI.js → chunk-J7RNXBXA.js} +3 -3
  26. package/dist/chunks/{chunk-735MPLUL.js → chunk-JJV2GT2Z.js} +22 -14
  27. package/dist/chunks/{chunk-4OVIUCSB.js → chunk-JO2T77NW.js} +1 -1
  28. package/dist/chunks/{chunk-S3ICPPXC.js → chunk-JVT3XTKN.js} +3 -3
  29. package/dist/chunks/{chunk-J4PDHWP2.js → chunk-KKHXMJEE.js} +1 -1
  30. package/dist/chunks/{chunk-L2RQV23D.js → chunk-N3DCLT7M.js} +1 -1
  31. package/dist/chunks/{chunk-22ZMVREZ.js → chunk-NAYS472K.js} +1 -1
  32. package/dist/chunks/{chunk-OIOAK7BS.js → chunk-NWEVR2OQ.js} +1 -1
  33. package/dist/chunks/{chunk-VSRRIFRF.js → chunk-P2GJBFNA.js} +1 -1
  34. package/dist/chunks/{chunk-N2GAA7RB.js → chunk-RT4U3DH3.js} +1 -1
  35. package/dist/chunks/{chunk-AXE3RR7J.js → chunk-S6E3PMH7.js} +1 -1
  36. package/dist/chunks/{chunk-4YPCUVMC.js → chunk-SZYFZNCO.js} +2 -2
  37. package/dist/chunks/{chunk-U6JPSXJ3.js → chunk-T2UNTWU5.js} +9 -9
  38. package/dist/chunks/{chunk-G3GLGDKV.js → chunk-TQ26XEFL.js} +2 -2
  39. package/dist/chunks/{chunk-N4AJV4GH.js → chunk-UEWIGD52.js} +36 -10
  40. package/dist/chunks/{chunk-YEDZ37PH.js → chunk-VNCHWWLG.js} +1 -1
  41. package/dist/chunks/{chunk-JKIAHYAW.js → chunk-VQ353UDK.js} +1 -1
  42. package/dist/chunks/{chunk-NQWEYJDD.js → chunk-VTGQCLGI.js} +1 -1
  43. package/dist/chunks/{chunk-YF6T33PU.js → chunk-ZWBQ4RRK.js} +16 -10
  44. package/dist/cli/figure.js +28 -28
  45. package/dist/cli/fold.js +6 -6
  46. package/dist/deletionEdges.js +2 -2
  47. package/dist/figure.js +24 -24
  48. package/dist/figureData.js +22 -22
  49. package/dist/figureScene.js +15 -15
  50. package/dist/figureSettings.js +6 -6
  51. package/dist/foldVariants.js +2 -2
  52. package/dist/genes/genePins.js +3 -3
  53. package/dist/graphLabels.js +4 -4
  54. package/dist/index.js +38 -38
  55. package/dist/labelLayout.js +8 -8
  56. package/dist/layout/forceCache.js +6 -6
  57. package/dist/layout/mergeRuns.js +2 -2
  58. package/dist/layout/orientToReference.js +2 -2
  59. package/dist/layout/tubeMapLayout.js +7 -7
  60. package/dist/layout/walkRowDraw.js +9 -9
  61. package/dist/layout/walkStrip.js +10 -10
  62. package/dist/layoutModes.js +8 -8
  63. package/dist/pathColors.js +5 -5
  64. package/dist/pipeline.js +5 -5
  65. package/dist/referenceStrip.js +9 -9
  66. package/dist/renderer/GeometryBuilder.js +8 -8
  67. package/dist/renderer/walkLanes.js +4 -2
  68. package/dist/tubeMap/axis.js +5 -5
  69. package/dist/tubeMap/bundle.js +8 -8
  70. package/dist/tubeMap/coarsen.js +8 -8
  71. package/dist/tubeMap/deviations.js +9 -9
  72. package/dist/tubeMap/draw.js +3 -3
  73. package/dist/tubeMap/genes.js +6 -6
  74. package/dist/tubeMap/nodeColors.js +9 -9
  75. package/dist/tubeMap/reads.js +2 -2
  76. package/dist/types/renderer/walkLanes.d.ts +18 -2
  77. package/dist/types/util/geometry.d.ts +1 -1
  78. package/dist/types/version.d.ts +1 -1
  79. package/dist/types/walkEncoding.d.ts +4 -2
  80. package/dist/util/SpatialIndex.js +4 -4
  81. package/dist/util/edgeCurves.js +3 -3
  82. package/dist/util/geometry.js +1 -1
  83. package/dist/util/hitDetection.js +5 -5
  84. package/dist/version.js +1 -1
  85. package/dist/viewport.js +6 -6
  86. package/dist/walkEncoding.js +13 -11
  87. package/dist/walkHighlight.js +10 -10
  88. package/dist/walkKey.js +5 -5
  89. package/package.json +1 -1
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  bubbleHalos,
3
3
  coversGraph
4
- } from "../chunks/chunk-4YPCUVMC.js";
5
- import "../chunks/chunk-OIOAK7BS.js";
4
+ } from "../chunks/chunk-SZYFZNCO.js";
5
+ import "../chunks/chunk-NWEVR2OQ.js";
6
6
  import "../chunks/chunk-FX4RDMDN.js";
7
- import "../chunks/chunk-6CXLLJ2C.js";
7
+ import "../chunks/chunk-AURNOR27.js";
8
8
  import "../chunks/chunk-HMXCN6PG.js";
9
9
  import "../chunks/chunk-AB35TJST.js";
10
- import "../chunks/chunk-YIWN32ZX.js";
11
- import "../chunks/chunk-3CXZUC2Y.js";
10
+ import "../chunks/chunk-HNNP5QUN.js";
11
+ import "../chunks/chunk-3GORESBG.js";
12
12
  import "../chunks/chunk-TLWXLNLY.js";
13
13
  import "../chunks/chunk-3YBP46PB.js";
14
- import "../chunks/chunk-735MPLUL.js";
14
+ import "../chunks/chunk-JJV2GT2Z.js";
15
15
  import "../chunks/chunk-CPMHA4W5.js";
16
16
  import "../chunks/chunk-ZPZ7GNBT.js";
17
17
  import "../chunks/chunk-BSOZW3FC.js";
@@ -3,16 +3,16 @@ import {
3
3
  BUBBLE_KIND_NAMES,
4
4
  bubbleSegmentIds,
5
5
  classifyBubble
6
- } from "../chunks/chunk-OIOAK7BS.js";
6
+ } from "../chunks/chunk-NWEVR2OQ.js";
7
7
  import "../chunks/chunk-FX4RDMDN.js";
8
- import "../chunks/chunk-6CXLLJ2C.js";
8
+ import "../chunks/chunk-AURNOR27.js";
9
9
  import "../chunks/chunk-HMXCN6PG.js";
10
10
  import "../chunks/chunk-AB35TJST.js";
11
- import "../chunks/chunk-YIWN32ZX.js";
12
- import "../chunks/chunk-3CXZUC2Y.js";
11
+ import "../chunks/chunk-HNNP5QUN.js";
12
+ import "../chunks/chunk-3GORESBG.js";
13
13
  import "../chunks/chunk-TLWXLNLY.js";
14
14
  import "../chunks/chunk-3YBP46PB.js";
15
- import "../chunks/chunk-735MPLUL.js";
15
+ import "../chunks/chunk-JJV2GT2Z.js";
16
16
  import "../chunks/chunk-CPMHA4W5.js";
17
17
  import "../chunks/chunk-ZPZ7GNBT.js";
18
18
  import "../chunks/chunk-BSOZW3FC.js";
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  graphBubbles,
3
3
  superbubblesFromGraph
4
- } from "../chunks/chunk-SIXFXXRI.js";
5
- import "../chunks/chunk-4YPCUVMC.js";
4
+ } from "../chunks/chunk-J7RNXBXA.js";
5
+ import "../chunks/chunk-SZYFZNCO.js";
6
6
  import "../chunks/chunk-RFG42VIO.js";
7
- import "../chunks/chunk-OIOAK7BS.js";
7
+ import "../chunks/chunk-NWEVR2OQ.js";
8
8
  import "../chunks/chunk-FX4RDMDN.js";
9
9
  import "../chunks/chunk-MHZTTLBU.js";
10
10
  import "../chunks/chunk-UAFATXYA.js";
11
11
  import "../chunks/chunk-VX656OAZ.js";
12
- import "../chunks/chunk-6CXLLJ2C.js";
12
+ import "../chunks/chunk-AURNOR27.js";
13
13
  import "../chunks/chunk-HMXCN6PG.js";
14
14
  import "../chunks/chunk-AB35TJST.js";
15
- import "../chunks/chunk-YIWN32ZX.js";
16
- import "../chunks/chunk-3CXZUC2Y.js";
15
+ import "../chunks/chunk-HNNP5QUN.js";
16
+ import "../chunks/chunk-3GORESBG.js";
17
17
  import "../chunks/chunk-TLWXLNLY.js";
18
18
  import "../chunks/chunk-3YBP46PB.js";
19
- import "../chunks/chunk-735MPLUL.js";
19
+ import "../chunks/chunk-JJV2GT2Z.js";
20
20
  import "../chunks/chunk-CPMHA4W5.js";
21
21
  import "../chunks/chunk-ZPZ7GNBT.js";
22
22
  import "../chunks/chunk-BSOZW3FC.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  engineKey,
3
3
  forceLayout
4
- } from "./chunk-S3ICPPXC.js";
4
+ } from "./chunk-JVT3XTKN.js";
5
5
 
6
6
  // src/layout/forceCache.ts
7
7
  var DEFAULT_SIZE = 4;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ENGINE_DEFAULTS
3
- } from "./chunk-S3ICPPXC.js";
3
+ } from "./chunk-JVT3XTKN.js";
4
4
 
5
5
  // src/figureSettings.ts
6
6
  var FIGURE_DEFAULTS = {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  slideAt
3
- } from "./chunk-735MPLUL.js";
3
+ } from "./chunk-JJV2GT2Z.js";
4
4
 
5
5
  // src/renderer/walkLanes.ts
6
6
  var THREAD_PX = 2;
@@ -53,9 +53,9 @@ function laneSlideAt(start, end, along) {
53
53
  }
54
54
  var gapOf = (a, b) => Math.hypot(b.x - a.x, b.y - a.y);
55
55
  function arcOf(run) {
56
- const s = [0];
56
+ const s = new Float64Array(run.length);
57
57
  for (let i = 1; i < run.length; i++) {
58
- s.push(s[i - 1] + gapOf(run[i - 1], run[i]));
58
+ s[i] = s[i - 1] + gapOf(run[i - 1], run[i]);
59
59
  }
60
60
  return s;
61
61
  }
@@ -63,9 +63,11 @@ function laneRuns(routes, nodePositions, yToX, jump) {
63
63
  const seen = /* @__PURE__ */ new Set();
64
64
  const owns = routes.map(
65
65
  (route) => route.map((id) => {
66
- const first = !!nodePositions[id]?.length && !seen.has(id);
66
+ if (seen.has(id)) {
67
+ return false;
68
+ }
67
69
  seen.add(id);
68
- return first;
70
+ return !!nodePositions[id]?.length;
69
71
  })
70
72
  );
71
73
  const gap = (a, b) => Math.hypot(b.x - a.x, b.y * yToX - a.y);
@@ -221,43 +223,46 @@ function cutCurls(run, close, length) {
221
223
  return out;
222
224
  }
223
225
  function rounded(run, half) {
226
+ const n = run.length;
224
227
  const s = arcOf(run);
225
- const end = s.at(-1);
226
- const sums = [{ w: 0, x: 0, y: 0 }];
227
- run.forEach((p, i) => {
228
- const w = (s[Math.min(i + 1, run.length - 1)] - s[Math.max(i - 1, 0)]) / 2;
229
- const last = sums[i];
230
- sums.push({ w: last.w + w, x: last.x + w * p.x, y: last.y + w * p.y });
231
- });
232
- const firstAtOrAfter = (at) => {
233
- let lo = 0;
234
- let hi = s.length;
235
- while (lo < hi) {
236
- const mid = lo + hi >> 1;
237
- if (s[mid] < at) {
238
- lo = mid + 1;
239
- } else {
240
- hi = mid;
241
- }
242
- }
243
- return lo;
244
- };
245
- return run.map((p, i) => {
228
+ const end = s[n - 1];
229
+ const sumW = new Float64Array(n + 1);
230
+ const sumX = new Float64Array(n + 1);
231
+ const sumY = new Float64Array(n + 1);
232
+ for (let i = 0; i < n; i++) {
233
+ const p = run[i];
234
+ const w = (s[Math.min(i + 1, n - 1)] - s[Math.max(i - 1, 0)]) / 2;
235
+ sumW[i + 1] = sumW[i] + w;
236
+ sumX[i + 1] = sumX[i] + w * p.x;
237
+ sumY[i + 1] = sumY[i] + w * p.y;
238
+ }
239
+ const out = new Array(n);
240
+ let lo = 0;
241
+ let hi = 0;
242
+ for (let i = 0; i < n; i++) {
243
+ const p = run[i];
246
244
  const reach = Math.min(half, s[i], end - s[i]);
247
- const lo = firstAtOrAfter(s[i] - reach);
248
- const hi = firstAtOrAfter(s[i] + reach + 1e-9 * (1 + end));
249
- const w = sums[hi].w - sums[lo].w;
250
- return w > 0 ? {
251
- x: (sums[hi].x - sums[lo].x) / w,
252
- y: (sums[hi].y - sums[lo].y) / w
253
- } : { x: p.x, y: p.y };
254
- });
245
+ const from = s[i] - reach;
246
+ const to = s[i] + reach + 1e-9 * (1 + end);
247
+ while (lo < n && s[lo] < from) {
248
+ lo++;
249
+ }
250
+ while (hi < n && s[hi] < to) {
251
+ hi++;
252
+ }
253
+ const w = sumW[hi] - sumW[lo];
254
+ out[i] = w > 0 ? { x: (sumX[hi] - sumX[lo]) / w, y: (sumY[hi] - sumY[lo]) / w } : { x: p.x, y: p.y };
255
+ }
256
+ return out;
255
257
  }
256
258
  function fieldSetter(field, nodePositions) {
257
259
  return ({ id, index }, value) => {
258
- const own = field.get(id) ?? new Array(nodePositions[id].length);
260
+ let own = field.get(id);
261
+ if (!own) {
262
+ own = new Array(nodePositions[id].length);
263
+ field.set(id, own);
264
+ }
259
265
  own[index] = value;
260
- field.set(id, own);
261
266
  };
262
267
  }
263
268
  function laneLines(lanes, nodePositions, yToX, reach, band, smooth = true) {
@@ -351,17 +356,39 @@ function windowMean(s, v, half, counted = () => true) {
351
356
  return w > 0 ? (sumWV[hi] - sumWV[lo]) / w : value;
352
357
  });
353
358
  }
359
+ var ONE_THREAD = [0];
360
+ function repeats(passes) {
361
+ for (const p of passes.values()) {
362
+ if (p > 1) {
363
+ return true;
364
+ }
365
+ }
366
+ return false;
367
+ }
354
368
  function walkThreads(route, passes, nodePositions, yToX, reach) {
355
- if (![...passes.values()].some((p) => p > 1)) {
369
+ if (!repeats(passes)) {
356
370
  return { span: passes, nodeThreads: /* @__PURE__ */ new Map(), linkThreads: /* @__PURE__ */ new Map() };
357
371
  }
358
- const span = /* @__PURE__ */ new Map();
359
- const visits = /* @__PURE__ */ new Map();
360
- const wanted = /* @__PURE__ */ new Map();
372
+ const index = /* @__PURE__ */ new Map();
373
+ const ids = [];
374
+ const widths = [];
375
+ const visits = [];
361
376
  const steps = [];
377
+ const stepVisits = [];
378
+ const stepWants = [];
362
379
  for (const piece of route) {
363
380
  const points = [];
381
+ const nodes = [];
364
382
  for (const id of piece) {
383
+ let k = index.get(id);
384
+ if (k === void 0) {
385
+ k = ids.length;
386
+ index.set(id, k);
387
+ ids.push(id);
388
+ widths.push(0);
389
+ visits.push(0);
390
+ }
391
+ nodes.push(k);
365
392
  const segments = nodePositions[id];
366
393
  const mid = segments?.[Math.floor(segments.length / 2)];
367
394
  points.push(
@@ -371,84 +398,87 @@ function walkThreads(route, passes, nodePositions, yToX, reach) {
371
398
  const s = arcOf(points);
372
399
  const p = piece.map((id) => passes.get(id) ?? 1);
373
400
  const most = windowed(s, p, reach / 2, 1);
374
- const copy = piece.map((id) => {
375
- const visit = (visits.get(id) ?? 0) + 1;
376
- visits.set(id, visit);
377
- return visit;
378
- });
379
- const full = p.map((v, i) => v === most[i]);
380
- const before = [];
401
+ const copy = nodes.map((k) => ++visits[k]);
402
+ const n = piece.length;
403
+ const before = new Int32Array(n);
381
404
  let last = -1;
382
- for (let i = 0; i < piece.length; i++) {
383
- last = full[i] ? i : last;
384
- before.push(last);
405
+ for (let i = 0; i < n; i++) {
406
+ last = p[i] === most[i] ? i : last;
407
+ before[i] = last;
385
408
  }
386
- const after = new Array(piece.length);
409
+ const after = new Int32Array(n);
387
410
  last = -1;
388
- for (let i = piece.length - 1; i >= 0; i--) {
389
- last = full[i] ? i : last;
411
+ for (let i = n - 1; i >= 0; i--) {
412
+ last = p[i] === most[i] ? i : last;
390
413
  after[i] = last;
391
414
  }
392
- const own = [];
393
- piece.forEach((id, i) => {
415
+ const wants = new Array(n);
416
+ for (let i = 0; i < n; i++) {
394
417
  const b = before[i];
395
418
  const a = after[i];
396
419
  const nearest = b < 0 ? a : a < 0 ? b : s[i] - s[b] <= s[a] - s[i] ? b : a;
397
- const thread = Math.min(copy[nearest], most[i]) - 1;
398
- span.set(id, Math.max(span.get(id) ?? 0, most[i]));
399
- const list = wanted.get(id) ?? [];
400
- list.push({ visit: copy[i], thread });
401
- wanted.set(id, list);
402
- own.push({ id, visit: copy[i] });
403
- });
404
- steps.push(own);
420
+ wants[i] = Math.min(copy[nearest], most[i]) - 1;
421
+ widths[nodes[i]] = Math.max(widths[nodes[i]], most[i]);
422
+ }
423
+ steps.push(nodes);
424
+ stepVisits.push(copy);
425
+ stepWants.push(wants);
405
426
  }
406
- const threadOf = /* @__PURE__ */ new Map();
407
- const nodeThreads = /* @__PURE__ */ new Map();
408
- for (const [id, list] of wanted) {
409
- const width = span.get(id);
410
- const taken = /* @__PURE__ */ new Set();
411
- const free = (want) => {
412
- for (let d = 0; d < width; d++) {
413
- for (const c of [want - d, want + d]) {
414
- if (c >= 0 && c < width && !taken.has(c)) {
415
- return c;
416
- }
427
+ const taken = [];
428
+ const threadOf = [];
429
+ const free = (k, want) => {
430
+ const width = widths[k];
431
+ const own = taken[k] ??= /* @__PURE__ */ new Set();
432
+ for (let d = 0; d < width; d++) {
433
+ for (const c of [want - d, want + d]) {
434
+ if (c >= 0 && c < width && !own.has(c)) {
435
+ return c;
417
436
  }
418
437
  }
419
- return want;
420
- };
421
- const byVisit = [];
422
- for (const { visit, thread } of list) {
423
- const t = free(thread);
424
- taken.add(t);
425
- byVisit[visit] = t;
426
438
  }
427
- threadOf.set(id, byVisit);
439
+ return want;
440
+ };
441
+ steps.forEach((nodes, piece) => {
442
+ nodes.forEach((k, i) => {
443
+ if (widths[k] > 1) {
444
+ const t = free(k, stepWants[piece][i]);
445
+ taken[k].add(t);
446
+ (threadOf[k] ??= [])[stepVisits[piece][i]] = t;
447
+ }
448
+ });
449
+ });
450
+ const span = /* @__PURE__ */ new Map();
451
+ const nodeThreads = /* @__PURE__ */ new Map();
452
+ ids.forEach((id, k) => {
453
+ span.set(id, widths[k]);
428
454
  nodeThreads.set(
429
455
  id,
430
- [...taken].sort((a, b) => a - b)
456
+ taken[k] ? [...taken[k]].sort((a, b) => a - b) : ONE_THREAD
431
457
  );
432
- }
458
+ });
433
459
  const linkThreads = /* @__PURE__ */ new Map();
434
- for (const own of steps) {
435
- own.forEach((cur, i) => {
436
- const prev = own[i - 1];
437
- if (!prev) {
438
- return;
439
- }
440
- const key = `${prev.id}>${cur.id}`;
460
+ steps.forEach((nodes, piece) => {
461
+ const visit = stepVisits[piece];
462
+ for (let i = 1; i < nodes.length; i++) {
463
+ const from = nodes[i - 1];
464
+ const to = nodes[i];
441
465
  const pair = [
442
- threadOf.get(prev.id)[prev.visit],
443
- threadOf.get(cur.id)[cur.visit]
466
+ threadOf[from]?.[visit[i - 1]] ?? 0,
467
+ threadOf[to]?.[visit[i]] ?? 0
444
468
  ];
445
- const list = linkThreads.get(key) ?? [];
446
- if (!list.some(([a, b]) => a === pair[0] && b === pair[1])) {
469
+ let ahead = linkThreads.get(ids[from]);
470
+ if (!ahead) {
471
+ ahead = /* @__PURE__ */ new Map();
472
+ linkThreads.set(ids[from], ahead);
473
+ }
474
+ const list = ahead.get(ids[to]);
475
+ if (!list) {
476
+ ahead.set(ids[to], [pair]);
477
+ } else if (!list.some(([a, b]) => a === pair[0] && b === pair[1])) {
447
478
  list.push(pair);
448
479
  }
449
- linkThreads.set(key, list);
450
- });
451
- }
480
+ }
481
+ });
452
482
  return { span, nodeThreads, linkThreads };
453
483
  }
454
484
  function bandSpans(lanes, spans, { reach, taper }) {
@@ -480,6 +510,39 @@ function bandSpans(lanes, spans, { reach, taper }) {
480
510
  });
481
511
  return out;
482
512
  }
513
+ function liftLanes(walks, nodePositions, yToX, worldPerScreenPx) {
514
+ const threaded = threadsPasses(walks);
515
+ const passes = walks.map((w) => w.mostPasses);
516
+ const reach = THREAD_REACH_PX * worldPerScreenPx;
517
+ const runs = laneRuns(
518
+ walks.flatMap((w) => w.route),
519
+ nodePositions,
520
+ yToX,
521
+ LANE_SMOOTHING_PX * worldPerScreenPx
522
+ );
523
+ const lines = laneLines(
524
+ runs,
525
+ nodePositions,
526
+ yToX,
527
+ LANE_SMOOTHING_PX * worldPerScreenPx,
528
+ bandWidthPx(passes) * (threaded ? bandScale(passes) : 1) * worldPerScreenPx,
529
+ threaded
530
+ );
531
+ const threads = threaded ? walks.map((w) => walkThreads(w.route, w.passes, nodePositions, yToX, reach)) : void 0;
532
+ const spans = threads ? bandSpans(
533
+ runs,
534
+ threads.map((t) => t.span),
535
+ { reach, taper: THREAD_TAPER_PX * worldPerScreenPx }
536
+ ) : void 0;
537
+ const furthestShift = { dx: 0, dy: 0 };
538
+ for (const own of lines.shifts.values()) {
539
+ for (const shift of own) {
540
+ furthestShift.dx = Math.max(furthestShift.dx, Math.abs(shift?.dx ?? 0));
541
+ furthestShift.dy = Math.max(furthestShift.dy, Math.abs(shift?.dy ?? 0));
542
+ }
543
+ }
544
+ return { lines, threads, spans, furthestShift };
545
+ }
483
546
 
484
547
  export {
485
548
  THREAD_PX,
@@ -500,5 +563,6 @@ export {
500
563
  laneRuns,
501
564
  laneLines,
502
565
  walkThreads,
503
- bandSpans
566
+ bandSpans,
567
+ liftLanes
504
568
  };
@@ -2,7 +2,7 @@ import {
2
2
  stripGeneGaps,
3
3
  walkStripFrame,
4
4
  walkStripLabelsTree
5
- } from "./chunk-4OVIUCSB.js";
5
+ } from "./chunk-JO2T77NW.js";
6
6
  import {
7
7
  Canvas2DRenderer
8
8
  } from "./chunk-4DMSPNYV.js";
@@ -13,7 +13,7 @@ import {
13
13
  walkRowsKey,
14
14
  walkRowsKeyTree,
15
15
  walkRowsTree
16
- } from "./chunk-LA6JHEVV.js";
16
+ } from "./chunk-IXLT3JJX.js";
17
17
  import {
18
18
  EXON_COLOR,
19
19
  exonOutlineTree,
@@ -21,37 +21,37 @@ import {
21
21
  } from "./chunk-JSUCGZ6K.js";
22
22
  import {
23
23
  geneLabelCandidates
24
- } from "./chunk-G3GLGDKV.js";
24
+ } from "./chunk-TQ26XEFL.js";
25
25
  import {
26
26
  nodesUnderBox
27
- } from "./chunk-NHOXLUIL.js";
27
+ } from "./chunk-4JDO7ZLN.js";
28
28
  import {
29
29
  escapeAttr,
30
30
  serializeEl
31
31
  } from "./chunk-H2H4Y3TV.js";
32
32
  import {
33
33
  genePins
34
- } from "./chunk-X5ULFAMM.js";
34
+ } from "./chunk-HEYIAMTC.js";
35
35
  import {
36
36
  version
37
- } from "./chunk-L2RQV23D.js";
37
+ } from "./chunk-N3DCLT7M.js";
38
38
  import {
39
39
  axisScaleOf
40
- } from "./chunk-2RCKHCF7.js";
40
+ } from "./chunk-3DHGSHC3.js";
41
41
  import {
42
42
  figureScene
43
- } from "./chunk-R3NPBUKT.js";
43
+ } from "./chunk-I5CHAYDZ.js";
44
44
  import {
45
45
  encodingStops
46
- } from "./chunk-N4AJV4GH.js";
46
+ } from "./chunk-UEWIGD52.js";
47
47
  import {
48
48
  THREAD_PX,
49
49
  passesKey,
50
50
  threadsPasses
51
- } from "./chunk-7GDNDQD7.js";
51
+ } from "./chunk-3BDQQTXY.js";
52
52
  import {
53
53
  rangeText
54
- } from "./chunk-SDDMV2MM.js";
54
+ } from "./chunk-IZKM4NY7.js";
55
55
  import {
56
56
  walkRowLabels
57
57
  } from "./chunk-VCUOYVLC.js";
@@ -60,11 +60,11 @@ import {
60
60
  } from "./chunk-ZANALBSX.js";
61
61
  import {
62
62
  FIGURE_DEFAULTS
63
- } from "./chunk-6MD4VS2F.js";
63
+ } from "./chunk-2MXFG3W7.js";
64
64
  import {
65
65
  FIT_PADDING,
66
66
  fitTransform
67
- } from "./chunk-S3ICPPXC.js";
67
+ } from "./chunk-JVT3XTKN.js";
68
68
  import {
69
69
  LABEL_CHAR_PX,
70
70
  LABEL_PAD,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clampZoom
3
- } from "./chunk-S3ICPPXC.js";
3
+ } from "./chunk-JVT3XTKN.js";
4
4
 
5
5
  // src/viewport.ts
6
6
  function axisScaleOf(scale, pixelRows) {
@@ -9,7 +9,7 @@ import {
9
9
  edgeJoinOf,
10
10
  routedEdgeCurves,
11
11
  strandSides
12
- } from "./chunk-735MPLUL.js";
12
+ } from "./chunk-JJV2GT2Z.js";
13
13
  import {
14
14
  groupBy
15
15
  } from "./chunk-BSOZW3FC.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ownStrand
3
- } from "./chunk-735MPLUL.js";
3
+ } from "./chunk-JJV2GT2Z.js";
4
4
  import {
5
5
  groupBy
6
6
  } from "./chunk-BSOZW3FC.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  EdgeSpatialIndex,
3
3
  SpatialIndex
4
- } from "./chunk-7PEYA3NA.js";
4
+ } from "./chunk-7YSIP3O2.js";
5
5
  import {
6
6
  weakMemo
7
7
  } from "./chunk-HMXCN6PG.js";
@@ -9,7 +9,7 @@ import {
9
9
  pathRibbonOffsets,
10
10
  translateCurves,
11
11
  yToXOf
12
- } from "./chunk-735MPLUL.js";
12
+ } from "./chunk-JJV2GT2Z.js";
13
13
 
14
14
  // src/util/hitDetection.ts
15
15
  function distanceToSegment(px, py, x1, y1, x2, y2) {
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  baseEdgeCurves
3
- } from "./chunk-VSRRIFRF.js";
3
+ } from "./chunk-P2GJBFNA.js";
4
4
  import {
5
5
  curveBounds,
6
6
  pathRibbonOffsets
7
- } from "./chunk-735MPLUL.js";
7
+ } from "./chunk-JJV2GT2Z.js";
8
8
 
9
9
  // src/util/SpatialIndex.ts
10
10
  var FALLBACK_CELL_SIZE = 50;
@@ -3,7 +3,7 @@ import {
3
3
  hasTubeMapPaths,
4
4
  tubeMapLayout,
5
5
  tubeMapReferenceLayout
6
- } from "./chunk-G4WQBRDS.js";
6
+ } from "./chunk-BDS5VZYZ.js";
7
7
  import {
8
8
  sampleRowLayout
9
9
  } from "./chunk-XR2HMGAS.js";
@@ -7,15 +7,15 @@ import {
7
7
  } from "./chunk-AB35TJST.js";
8
8
  import {
9
9
  polylineMidpoint
10
- } from "./chunk-YIWN32ZX.js";
10
+ } from "./chunk-HNNP5QUN.js";
11
11
  import {
12
12
  edgeCurvesOf
13
- } from "./chunk-3CXZUC2Y.js";
13
+ } from "./chunk-3GORESBG.js";
14
14
  import {
15
15
  curveBounds,
16
16
  curveMidpoint,
17
17
  polylinePx
18
- } from "./chunk-735MPLUL.js";
18
+ } from "./chunk-JJV2GT2Z.js";
19
19
 
20
20
  // src/graphLabels.ts
21
21
  var MIN_DELETION_LABEL_PX = 26;
@@ -1,21 +1,21 @@
1
1
  import {
2
2
  stepName,
3
3
  tubeMapReads
4
- } from "./chunk-J4PDHWP2.js";
4
+ } from "./chunk-KKHXMJEE.js";
5
5
  import {
6
6
  referenceWalkName
7
7
  } from "./chunk-LODKC7PJ.js";
8
8
  import {
9
9
  pathCssColor,
10
10
  pathGreyCssColor
11
- } from "./chunk-JKIAHYAW.js";
11
+ } from "./chunk-VQ353UDK.js";
12
12
  import {
13
13
  pathOrigin
14
14
  } from "./chunk-3YBP46PB.js";
15
15
  import {
16
16
  ownStrand,
17
17
  strandSides
18
- } from "./chunk-735MPLUL.js";
18
+ } from "./chunk-JJV2GT2Z.js";
19
19
  import {
20
20
  groupBy
21
21
  } from "./chunk-BSOZW3FC.js";