@jbrowse/bandage-core 10.2.2 → 10.2.3

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 (137) hide show
  1. package/README.md +6 -7
  2. package/dist/bubbles/bubbleHalos.js +7 -3
  3. package/dist/bubbles/bubblesFromGraph.js +4 -2
  4. package/dist/bubbles/classifyBubble.js +10 -5
  5. package/dist/bubbles/superbubbles.js +10 -6
  6. package/dist/chunks/{chunk-N6FECAXP.js → chunk-24WITXQY.js} +17 -8
  7. package/dist/chunks/{chunk-XTCNEKO5.js → chunk-2QLLQJ72.js} +15 -13
  8. package/dist/chunks/{chunk-ASSNZXCF.js → chunk-3AOGOCCQ.js} +44 -103
  9. package/dist/chunks/{chunk-TWRLC3KK.js → chunk-3XSM4OZU.js} +1 -1
  10. package/dist/chunks/{chunk-WEDZ76AK.js → chunk-4DRQTBBE.js} +1 -1
  11. package/dist/chunks/{chunk-2LQ5BWT7.js → chunk-4ETPXDO6.js} +1 -1
  12. package/dist/chunks/{chunk-FP4H7SFT.js → chunk-4HWM3FNK.js} +2 -2
  13. package/dist/chunks/{chunk-C7MZJSPT.js → chunk-54POIBVC.js} +2 -8
  14. package/dist/chunks/{chunk-PKFMP65V.js → chunk-5GMFEPWR.js} +1 -1
  15. package/dist/chunks/{chunk-CDLPYR5O.js → chunk-5I3K4R2G.js} +7 -6
  16. package/dist/chunks/{chunk-TICYLD5F.js → chunk-7CC7N3XC.js} +35 -78
  17. package/dist/chunks/{chunk-2CVHXFK7.js → chunk-7SRWJLSC.js} +19 -22
  18. package/dist/chunks/{chunk-SBMJNRTV.js → chunk-A4PFFC4Q.js} +37 -27
  19. package/dist/chunks/{chunk-IW6CYVX2.js → chunk-AR4BUBMU.js} +6 -1
  20. package/dist/chunks/{chunk-IUDJKOLB.js → chunk-B6IW3IRE.js} +15 -33
  21. package/dist/chunks/{chunk-JUIJI7RC.js → chunk-BAETMD3J.js} +9 -4
  22. package/dist/chunks/{chunk-L5WF4ZPS.js → chunk-BS4UZ44I.js} +1 -1
  23. package/dist/chunks/{chunk-HNQPEMYE.js → chunk-CM6LO6OC.js} +0 -1
  24. package/dist/chunks/{chunk-CLOP7UVD.js → chunk-CQHUZHET.js} +11 -8
  25. package/dist/chunks/{chunk-R456ME6J.js → chunk-CU6P5RUG.js} +17 -6
  26. package/dist/chunks/chunk-D5D36ZF6.js +107 -0
  27. package/dist/chunks/{chunk-AFP3NWSL.js → chunk-DY3JCAMX.js} +1 -1
  28. package/dist/chunks/{chunk-NRV7R36Q.js → chunk-EFQLEGWM.js} +3 -3
  29. package/dist/chunks/{chunk-BXEPA4KS.js → chunk-G6UIYQZR.js} +5 -2
  30. package/dist/chunks/{chunk-NNODIW4U.js → chunk-H2H4Y3TV.js} +1 -0
  31. package/dist/chunks/{chunk-MVFDSFV2.js → chunk-HNCXR2VS.js} +1 -1
  32. package/dist/chunks/{chunk-EYK7DJZV.js → chunk-J5FWKGOY.js} +1 -1
  33. package/dist/chunks/{chunk-PBENCR5L.js → chunk-JBCZIBFC.js} +0 -2
  34. package/dist/chunks/{chunk-EHUBJDDB.js → chunk-JFY5PWQC.js} +5 -3
  35. package/dist/chunks/{chunk-5BGP5Z64.js → chunk-JLSJMCDJ.js} +1 -1
  36. package/dist/chunks/{chunk-DT2GGH4D.js → chunk-JMABOQWL.js} +2 -6
  37. package/dist/chunks/{chunk-3S3YVOJ7.js → chunk-JSUCGZ6K.js} +1 -1
  38. package/dist/chunks/{chunk-MLSWIMZO.js → chunk-KBEP7VYK.js} +2 -2
  39. package/dist/chunks/{chunk-TAMCZHLW.js → chunk-N73TI3VG.js} +2 -2
  40. package/dist/chunks/chunk-O4EGE27I.js +10 -0
  41. package/dist/chunks/{chunk-3ZZSX5HN.js → chunk-PTABFYQ7.js} +10 -6
  42. package/dist/chunks/{chunk-WBCOREDZ.js → chunk-QLWI2PZ3.js} +16 -7
  43. package/dist/chunks/chunk-RBCE2OQH.js +32 -0
  44. package/dist/chunks/{chunk-BUBZ32IC.js → chunk-RPRHR56C.js} +4 -8
  45. package/dist/chunks/{chunk-47DYCZOK.js → chunk-RUCH6ZFL.js} +4 -0
  46. package/dist/chunks/{chunk-GNTTI6LA.js → chunk-T2PCSAFY.js} +1 -1
  47. package/dist/chunks/{chunk-XKWD2RY3.js → chunk-URZ3CH2R.js} +3 -10
  48. package/dist/chunks/{chunk-ALDGONEI.js → chunk-VQC7KELB.js} +1 -1
  49. package/dist/chunks/{chunk-FLFBYSJO.js → chunk-VQWHMWLF.js} +5 -1
  50. package/dist/chunks/{chunk-4R6QNG23.js → chunk-WL6ZKUVC.js} +3 -3
  51. package/dist/chunks/{chunk-CRTD2SBP.js → chunk-WZNPX7Q6.js} +6 -2
  52. package/dist/chunks/{chunk-FNGIQF43.js → chunk-XA5A27CS.js} +6 -14
  53. package/dist/chunks/{chunk-DK5P2YOL.js → chunk-XI3ZUTWF.js} +2 -2
  54. package/dist/chunks/{chunk-ZIUKZUPJ.js → chunk-XL472HHD.js} +1 -1
  55. package/dist/chunks/{chunk-BPRXQ2SS.js → chunk-XMW266WS.js} +1 -1
  56. package/dist/chunks/{chunk-DRG4236Y.js → chunk-YN6FDIBT.js} +2 -2
  57. package/dist/chunks/{chunk-WFB5TXRA.js → chunk-ZY2AFL4Y.js} +13 -31
  58. package/dist/cli/decodeText.js +6 -0
  59. package/dist/cli/figure.js +59 -60
  60. package/dist/cli/fold.js +13 -13
  61. package/dist/deletionEdges.js +6 -4
  62. package/dist/el.js +3 -1
  63. package/dist/figure.js +33 -31
  64. package/dist/figureData.js +32 -27
  65. package/dist/figureScene.js +43 -0
  66. package/dist/figureSettings.js +8 -8
  67. package/dist/foldVariants.js +2 -2
  68. package/dist/gbzCut.js +1 -1
  69. package/dist/genes/exonOutline.js +2 -2
  70. package/dist/genes/geneFiles.js +1 -1
  71. package/dist/genes/genePins.js +3 -3
  72. package/dist/gfa/gfaConverter.js +2 -2
  73. package/dist/gfa-core/gfaParser.js +1 -1
  74. package/dist/gfa-core/index.js +1 -1
  75. package/dist/graphLabels.js +4 -4
  76. package/dist/index.js +72 -73
  77. package/dist/labelLayout.js +8 -8
  78. package/dist/layout/forceCache.js +8 -8
  79. package/dist/layout/mergeRuns.js +2 -2
  80. package/dist/layout/orderedLayout.js +1 -3
  81. package/dist/layout/tubeMapLayout.js +6 -6
  82. package/dist/layout/walkRowDraw.js +11 -11
  83. package/dist/layout/walkRowLayout.js +3 -1
  84. package/dist/layout/walkStrip.js +14 -12
  85. package/dist/layoutEngines.js +1 -2
  86. package/dist/layoutModes.js +9 -9
  87. package/dist/nodeWidths.js +1 -3
  88. package/dist/pathColors.js +5 -5
  89. package/dist/pipeline.js +7 -7
  90. package/dist/referenceRampCss.js +9 -9
  91. package/dist/referenceStrip.js +9 -9
  92. package/dist/renderer/Canvas2DRenderer.js +2 -2
  93. package/dist/renderer/GeometryBuilder.js +8 -8
  94. package/dist/renderer/canvas.js +1 -1
  95. package/dist/renderer/svgCanvas.js +1 -1
  96. package/dist/tubeMap/axis.js +5 -5
  97. package/dist/tubeMap/bundle.js +7 -7
  98. package/dist/tubeMap/coarsen.js +6 -6
  99. package/dist/tubeMap/deviations.js +5 -5
  100. package/dist/tubeMap/draw.js +1 -1
  101. package/dist/tubeMap/genes.js +6 -6
  102. package/dist/tubeMap/nodeColors.js +9 -9
  103. package/dist/types/bubbles/bubblesFromGraph.d.ts +1 -0
  104. package/dist/types/bubbles/classifyBubble.d.ts +0 -1
  105. package/dist/types/cli/decodeText.d.ts +1 -0
  106. package/dist/types/cli/figure.d.ts +4 -15
  107. package/dist/types/deletionEdges.d.ts +3 -5
  108. package/dist/types/el.d.ts +1 -0
  109. package/dist/types/figureData.d.ts +7 -26
  110. package/dist/types/figureScene.d.ts +31 -0
  111. package/dist/types/genes/geneFiles.d.ts +2 -1
  112. package/dist/types/index.d.ts +1 -1
  113. package/dist/types/layout/deletionRoutes.d.ts +1 -1
  114. package/dist/types/layout/orderedLayout.d.ts +0 -6
  115. package/dist/types/layout/walkRowLayout.d.ts +1 -0
  116. package/dist/types/nodeWidths.d.ts +0 -1
  117. package/dist/types/renderer/Canvas2DRenderer.d.ts +1 -0
  118. package/dist/types/renderer/canvas.d.ts +2 -2
  119. package/dist/types/tubeMap/draw.d.ts +1 -0
  120. package/dist/types/util/geometry.d.ts +3 -3
  121. package/dist/types/version.d.ts +1 -1
  122. package/dist/util/SpatialIndex.js +4 -4
  123. package/dist/util/edgeCurves.js +3 -3
  124. package/dist/util/geometry.js +3 -3
  125. package/dist/util/hitDetection.js +5 -5
  126. package/dist/version.js +1 -1
  127. package/dist/viewport.js +8 -8
  128. package/dist/walkEncoding.js +9 -9
  129. package/dist/walkHighlight.js +10 -10
  130. package/dist/walkKey.js +5 -5
  131. package/package.json +3 -6
  132. package/dist/chunks/bandage-layout-3AR6BCUD.js +0 -4694
  133. package/dist/chunks/chunk-4BYTEJGW.js +0 -44
  134. package/dist/chunks/chunk-7XHHVYG7.js +0 -13
  135. package/dist/loadBandage.js +0 -6
  136. package/dist/types/bandage/bandage-layout.d.ts +0 -14
  137. package/dist/types/loadBandage.d.ts +0 -3
@@ -0,0 +1,107 @@
1
+ import {
2
+ layoutGeometryInputs
3
+ } from "./chunk-LOCJN3BZ.js";
4
+ import {
5
+ facetLifts,
6
+ walkLift
7
+ } from "./chunk-CU6P5RUG.js";
8
+ import {
9
+ buildGeometry,
10
+ computeReferenceRamp
11
+ } from "./chunk-A4PFFC4Q.js";
12
+ import {
13
+ walkRowsExtent
14
+ } from "./chunk-54POIBVC.js";
15
+ import {
16
+ pathLegend,
17
+ walkLabelsOf
18
+ } from "./chunk-3XSM4OZU.js";
19
+ import {
20
+ FIGURE_DEFAULTS
21
+ } from "./chunk-HNCXR2VS.js";
22
+ import {
23
+ drawingBounds
24
+ } from "./chunk-2QLLQJ72.js";
25
+ import {
26
+ referenceLabel
27
+ } from "./chunk-RAKOB6IV.js";
28
+ import {
29
+ resolveColorScheme
30
+ } from "./chunk-JKJWSY4V.js";
31
+ import {
32
+ deletionDrawing,
33
+ deletionEdges
34
+ } from "./chunk-24WITXQY.js";
35
+ import {
36
+ facetSettingOf
37
+ } from "./chunk-XV4P5KEQ.js";
38
+
39
+ // src/figureScene.ts
40
+ function figureScene(graph, layout, o) {
41
+ const region = o.region;
42
+ const rampDomain = o.colorDomain ?? region;
43
+ const rows = o.walkRows;
44
+ const bounds = drawingBounds(layout, {
45
+ region: o.fitToDrawing ? void 0 : region,
46
+ extent: rows && layout.extent ? walkRowsExtent(rows, o.walkRowPitch) : void 0
47
+ });
48
+ const nodeById = new Map(graph.nodes.map((node) => [node.id, node]));
49
+ const colorScheme = resolveColorScheme(
50
+ o.colorScheme ?? FIGURE_DEFAULTS.colorScheme,
51
+ graph
52
+ );
53
+ const referenceRamp = colorScheme === "reference-position" && !layout.tubeMap ? computeReferenceRamp(graph, rampDomain) : void 0;
54
+ const drawnDeletions = deletionDrawing(
55
+ graph,
56
+ layout.tubeMap ? [] : deletionEdges(graph),
57
+ o.showDeletionEdges
58
+ );
59
+ const layers = o.walks ?? [];
60
+ const walkRamp = layers.some((l) => l.color?.field === "reference") ? referenceRamp ?? computeReferenceRamp(graph, rampDomain) : void 0;
61
+ const lift = layers.length > 0 && !layout.tubeMap ? walkLift(graph, layers, walkRamp) : void 0;
62
+ const facet = facetSettingOf(o.facet);
63
+ const panels = facet.field && lift && lift.walks.length > 1 ? facetLifts(graph, lift, layers, walkRamp) : void 0;
64
+ const labels = walkLabelsOf(
65
+ graph.paths?.length ? pathLegend(graph.paths) : []
66
+ );
67
+ const referenceName = o.referenceName ?? referenceLabel(graph, region);
68
+ const contigThickness = o.contigThickness ?? FIGURE_DEFAULTS.contigThickness;
69
+ const nodeWidth = o.nodeWidth ?? FIGURE_DEFAULTS.nodeWidth;
70
+ return {
71
+ bounds,
72
+ nodeById,
73
+ colorScheme,
74
+ referenceRamp,
75
+ drawnDeletions,
76
+ layers,
77
+ lift,
78
+ facet,
79
+ panels,
80
+ labelOf: (name) => labels.get(name) ?? name,
81
+ referenceName,
82
+ reference: lift?.referenceDomain && {
83
+ ...lift.referenceDomain,
84
+ name: referenceName
85
+ },
86
+ contigThickness,
87
+ nodeWidth,
88
+ geometry: (highlight, axis) => buildGeometry({
89
+ ...layoutGeometryInputs(layout, drawnDeletions, { drawsRows: !!rows }),
90
+ graph,
91
+ nodeById,
92
+ colorScheme,
93
+ contigThickness,
94
+ connectorThickness: o.connectorThickness ?? FIGURE_DEFAULTS.connectorThickness,
95
+ drawPaths: false,
96
+ nodeWidth,
97
+ linearLayout: o.linearLayout,
98
+ highlight,
99
+ axis,
100
+ referenceRamp
101
+ })
102
+ };
103
+ }
104
+
105
+ export {
106
+ figureScene
107
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ownStrand
3
- } from "./chunk-2CVHXFK7.js";
3
+ } from "./chunk-7SRWJLSC.js";
4
4
  import {
5
5
  isBackbone
6
6
  } from "./chunk-FYQWPEEY.js";
@@ -3,13 +3,13 @@ import {
3
3
  RAMP_GRADIENT_STOPS,
4
4
  rampHueCss,
5
5
  rampStops
6
- } from "./chunk-ZIUKZUPJ.js";
6
+ } from "./chunk-XL472HHD.js";
7
7
  import {
8
8
  el
9
- } from "./chunk-NNODIW4U.js";
9
+ } from "./chunk-H2H4Y3TV.js";
10
10
  import {
11
11
  REFERENCE_RAMP_ALT_CSS
12
- } from "./chunk-SBMJNRTV.js";
12
+ } from "./chunk-A4PFFC4Q.js";
13
13
  import {
14
14
  LABEL_CHAR_PX
15
15
  } from "./chunk-AB35TJST.js";
@@ -164,10 +164,13 @@ function genesFromBed(text) {
164
164
  }
165
165
  return mergeOverlappingByName(rows);
166
166
  }
167
- function genesFromText(text) {
167
+ function sniffedFormat(text) {
168
168
  const first = text.split("\n", 1e3).find((l) => l.trim() !== "" && !/^(#|track|browser)/.test(l));
169
169
  const cols = first?.split(" ") ?? [];
170
- return /^\d+$/.test(cols[1] ?? "") && /^\d+$/.test(cols[2] ?? "") ? genesFromBed(text) : genesFromGff3Lines(text.split(/\r?\n/));
170
+ return /^\d+$/.test(cols[1] ?? "") && /^\d+$/.test(cols[2] ?? "") ? "bed" : "gff3";
171
+ }
172
+ function genesFromText(text, format = sniffedFormat(text)) {
173
+ return format === "bed" ? genesFromBed(text) : genesFromGff3Lines(text.split(/\r?\n/));
171
174
  }
172
175
 
173
176
  export {
@@ -22,5 +22,6 @@ function serializeEl(node) {
22
22
 
23
23
  export {
24
24
  el,
25
+ escapeAttr,
25
26
  serializeEl
26
27
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ENGINE_DEFAULTS
3
- } from "./chunk-XTCNEKO5.js";
3
+ } from "./chunk-2QLLQJ72.js";
4
4
 
5
5
  // src/figureSettings.ts
6
6
  var FIGURE_DEFAULTS = {
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var version = "10.2.2";
2
+ var version = "10.2.3";
3
3
 
4
4
  export {
5
5
  version
@@ -11,7 +11,6 @@ var NODE_WIDTHS = [
11
11
  description: "Every node the same thickness."
12
12
  }
13
13
  ];
14
- var NODE_WIDTH_VALUES = NODE_WIDTHS.map((w) => w.value);
15
14
  var MIN_FACTOR = 0.3;
16
15
  var MAX_FACTOR = 3;
17
16
  function meanDepth(graph) {
@@ -51,7 +50,6 @@ function nodeInk(graph, nodeById, contigThickness, nodeWidth) {
51
50
 
52
51
  export {
53
52
  NODE_WIDTHS,
54
- NODE_WIDTH_VALUES,
55
53
  meanDepth,
56
54
  depthWidthFactor,
57
55
  nodeWidthPx,
@@ -1,11 +1,13 @@
1
1
  import {
2
2
  bubbleSegmentIds,
3
- classifyBubble,
3
+ classifyBubble
4
+ } from "./chunk-URZ3CH2R.js";
5
+ import {
4
6
  formatBp
5
- } from "./chunk-XKWD2RY3.js";
7
+ } from "./chunk-PTABFYQ7.js";
6
8
  import {
7
9
  svgPath
8
- } from "./chunk-2CVHXFK7.js";
10
+ } from "./chunk-7SRWJLSC.js";
9
11
  import {
10
12
  isBackbone
11
13
  } from "./chunk-FYQWPEEY.js";
@@ -2,7 +2,7 @@ import {
2
2
  LIFT_BACKDROP_CSS,
3
3
  computeColorSchemeRange,
4
4
  getNodeColor
5
- } from "./chunk-SBMJNRTV.js";
5
+ } from "./chunk-A4PFFC4Q.js";
6
6
  import {
7
7
  abgrToCssRgba
8
8
  } from "./chunk-G2FD7S3C.js";
@@ -1,8 +1,5 @@
1
- import {
2
- loadBandage
3
- } from "./chunk-7XHHVYG7.js";
4
-
5
1
  // src/layoutEngines.ts
2
+ import { fmmmLayout } from "@jbrowse/graph-fmmm-layout";
6
3
  import { stressLayout } from "@jbrowse/graph-stress-layout";
7
4
  var LAYOUT_ENGINES = [
8
5
  {
@@ -26,9 +23,8 @@ var layoutEngine = async (request) => {
26
23
  const result2 = stressLayout(request);
27
24
  return { result: result2, duration: performance.now() - start2 };
28
25
  }
29
- const bandage = await loadBandage();
30
26
  const start = performance.now();
31
- const result = bandage.computeLayout(request.graph, request.options);
27
+ const result = await fmmmLayout(request);
32
28
  return { result, duration: performance.now() - start };
33
29
  };
34
30
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  el
3
- } from "./chunk-NNODIW4U.js";
3
+ } from "./chunk-H2H4Y3TV.js";
4
4
 
5
5
  // src/genes/exonOutline.ts
6
6
  var EXON_COLOR = "#daa520";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  baseEdgeCurves
3
- } from "./chunk-WFB5TXRA.js";
3
+ } from "./chunk-ZY2AFL4Y.js";
4
4
  import {
5
5
  curveBounds,
6
6
  pathRibbonOffsets
7
- } from "./chunk-2CVHXFK7.js";
7
+ } from "./chunk-7SRWJLSC.js";
8
8
 
9
9
  // src/util/SpatialIndex.ts
10
10
  var FALLBACK_CELL_SIZE = 50;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ownStrand,
3
3
  strandSides
4
- } from "./chunk-2CVHXFK7.js";
4
+ } from "./chunk-7SRWJLSC.js";
5
5
  import {
6
6
  isBackbone
7
7
  } from "./chunk-FYQWPEEY.js";
@@ -122,7 +122,7 @@ function splitRuns(positions, runs, weightOf) {
122
122
  const arc = arcPrefix(line);
123
123
  const total = arc.at(-1);
124
124
  const weights = members.map((m) => Math.max(weightOf(m), 0));
125
- const weightSum = weights.reduce((a, b) => a + b, 0) || members.length;
125
+ const weightSum = weights.reduce((a, b) => a + b, 0);
126
126
  let from = 0;
127
127
  members.forEach((member, k) => {
128
128
  const share = weightSum ? weights[k] / weightSum * total : total / members.length;
@@ -0,0 +1,10 @@
1
+ // src/cli/decodeText.ts
2
+ import { gunzipSync } from "node:zlib";
3
+ function decodeText(bytes) {
4
+ const gzipped = bytes[0] === 31 && bytes[1] === 139;
5
+ return new TextDecoder().decode(gzipped ? gunzipSync(bytes) : bytes);
6
+ }
7
+
8
+ export {
9
+ decodeText
10
+ };
@@ -3,14 +3,14 @@ import {
3
3
  } from "./chunk-AB35TJST.js";
4
4
  import {
5
5
  polylineMidpoint
6
- } from "./chunk-TAMCZHLW.js";
6
+ } from "./chunk-N73TI3VG.js";
7
7
  import {
8
8
  deletionArcCurves
9
- } from "./chunk-N6FECAXP.js";
9
+ } from "./chunk-24WITXQY.js";
10
10
  import {
11
11
  curveBounds,
12
12
  curveMidpoint
13
- } from "./chunk-2CVHXFK7.js";
13
+ } from "./chunk-7SRWJLSC.js";
14
14
 
15
15
  // src/graphLabels.ts
16
16
  var MIN_DELETION_LABEL_PX = 26;
@@ -50,10 +50,11 @@ function groupDigits(n) {
50
50
  return String(n).replace(/\B(?=(\d{3})+$)/g, ",");
51
51
  }
52
52
  function formatBp(bp) {
53
- if (bp >= 1e6) {
54
- return `${+(bp / 1e6).toFixed(1)} Mb`;
53
+ const [value, unit] = bp >= 1e6 ? [bp / 1e6, "Mb"] : bp >= 1e3 ? [bp / 1e3, "kb"] : [];
54
+ if (value === void 0) {
55
+ return `${bp} bp`;
55
56
  }
56
- return bp >= 1e3 ? `${+(bp / 1e3).toFixed(1)} kb` : `${bp} bp`;
57
+ return `${+value.toFixed(value >= 100 ? 0 : 1)} ${unit}`;
57
58
  }
58
59
  function deletionText(bp) {
59
60
  return `${formatBp(bp)} del`;
@@ -181,6 +182,9 @@ function sizeLabelCandidates({
181
182
  const box = boxAt(halfW, 0, 0);
182
183
  const arcX = apex.x * scaleX + translateX;
183
184
  const arcY = apex.y * scaleY + translateY;
185
+ if (arcX < 0 || arcX > width || arcY < 0 || arcY > height) {
186
+ continue;
187
+ }
184
188
  const fits = extent >= halfW * 2 / MAX_LABEL_OVERHANG;
185
189
  const bow = arcOutward(curves, apex, scaleX, scaleY);
186
190
  const offset = boxSupport(box, bow) + LEADER_GAP_PX;
@@ -1,6 +1,7 @@
1
1
  import {
2
+ getDpr,
2
3
  syncCanvasSize
3
- } from "./chunk-4BYTEJGW.js";
4
+ } from "./chunk-RBCE2OQH.js";
4
5
  import {
5
6
  abgrToCssRgba,
6
7
  brightenAbgr,
@@ -15,6 +16,7 @@ var Canvas2DRenderer = class {
15
16
  this.nodeHighlights = /* @__PURE__ */ new Map();
16
17
  this.highlightedEdge = null;
17
18
  this.highlightFactor = 1;
19
+ this.fit = 1;
18
20
  const ctx = canvas.getContext("2d");
19
21
  if (!ctx) {
20
22
  throw new Error("Canvas 2D context not available");
@@ -26,12 +28,11 @@ var Canvas2DRenderer = class {
26
28
  }
27
29
  releaseOffscreenTargets() {
28
30
  }
29
- // Not a local `width * devicePixelRatio`: syncCanvasSize clamps the backing
30
- // store at MAX_CANVAS_DIM_PX, reads the ratio through `getDpr()` so this
31
- // agrees with the transform the model builds, and writes the css size
32
- // independently of the backing size.
31
+ // A host builds its transform at `getDpr()`. Where syncCanvasSize had to
32
+ // shrink the ratio to stay under MAX_CANVAS_DIM_PX, `fit` shrinks the
33
+ // transform to match, so the picture still fills the css box.
33
34
  resize(width, height) {
34
- syncCanvasSize(this.canvas, width, height);
35
+ this.fit = syncCanvasSize(this.canvas, width, height) / getDpr();
35
36
  }
36
37
  uploadGeometry(batch) {
37
38
  this.batch = batch;
@@ -45,7 +46,15 @@ var Canvas2DRenderer = class {
45
46
  this.highlightFactor = factor;
46
47
  }
47
48
  updateTransform(transform) {
48
- this.transform = transform;
49
+ const k = this.fit;
50
+ this.transform = k === 1 ? transform : {
51
+ ...transform,
52
+ scaleX: transform.scaleX * k,
53
+ scaleY: transform.scaleY * k,
54
+ translateX: transform.translateX * k,
55
+ translateY: transform.translateY * k,
56
+ dpr: transform.dpr * k
57
+ };
49
58
  }
50
59
  render(clearColor) {
51
60
  const t = this.transform;
@@ -0,0 +1,32 @@
1
+ // src/renderer/canvas.ts
2
+ var MAX_DPR = 2;
3
+ var MAX_CANVAS_DIM_PX = 8192;
4
+ function getDpr(width = 0, height = 0) {
5
+ const dpr = typeof devicePixelRatio === "undefined" ? 1 : Math.min(devicePixelRatio, MAX_DPR);
6
+ return Math.min(dpr, MAX_CANVAS_DIM_PX / Math.max(width, height, 1));
7
+ }
8
+ function syncCanvasSize(canvas, width, height) {
9
+ const dpr = getDpr(width, height);
10
+ const pw = Math.round(width * dpr);
11
+ const ph = Math.round(height * dpr);
12
+ if (canvas.width !== pw || canvas.height !== ph) {
13
+ canvas.width = pw;
14
+ canvas.height = ph;
15
+ }
16
+ const cssWidth = `${width}px`;
17
+ const cssHeight = `${height}px`;
18
+ if (canvas.style.width !== cssWidth) {
19
+ canvas.style.width = cssWidth;
20
+ }
21
+ if (canvas.style.height !== cssHeight) {
22
+ canvas.style.height = cssHeight;
23
+ }
24
+ return dpr;
25
+ }
26
+
27
+ export {
28
+ MAX_DPR,
29
+ MAX_CANVAS_DIM_PX,
30
+ getDpr,
31
+ syncCanvasSize
32
+ };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  polylineSlice
3
- } from "./chunk-TAMCZHLW.js";
3
+ } from "./chunk-N73TI3VG.js";
4
4
  import {
5
5
  svgPath
6
- } from "./chunk-2CVHXFK7.js";
6
+ } from "./chunk-7SRWJLSC.js";
7
7
  import {
8
8
  firstNodeAtOrAfter,
9
9
  isAnchored
@@ -74,12 +74,8 @@ function genePins(graph, genes, positions) {
74
74
  const distance = Math.abs(pinBp - mid);
75
75
  if (distance < atDistance) {
76
76
  atDistance = distance;
77
- const [p] = polylineSlice(
78
- line,
79
- (pinBp - nodeStart) / node.length,
80
- (pinBp - nodeStart) / node.length
81
- );
82
- at = p;
77
+ const along = node.length ? (pinBp - nodeStart) / node.length : 0;
78
+ at = polylineSlice(line, along, along)[0];
83
79
  }
84
80
  }
85
81
  if (at) {
@@ -90,6 +90,10 @@ function svgCanvas(width, height) {
90
90
  out.push(`<path d="${d}" ${paintAttrs("fill", ctx.fillStyle)}/>`);
91
91
  }
92
92
  },
93
+ // the renderer only ever clears the whole canvas
94
+ clearRect() {
95
+ out.length = 0;
96
+ },
93
97
  fillRect(x, y, w, h) {
94
98
  out.push(
95
99
  `<rect x="${n(x)}" y="${n(y)}" width="${n(w)}" height="${n(h)}" ${paintAttrs("fill", ctx.fillStyle)}/>`
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  computeColorSchemeRange,
3
3
  getNodeColor
4
- } from "./chunk-SBMJNRTV.js";
4
+ } from "./chunk-A4PFFC4Q.js";
5
5
  import {
6
6
  abgrToCssRgba
7
7
  } from "./chunk-G2FD7S3C.js";
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  SATURATED_PATH_COUNT
3
3
  } from "./chunk-FX4RDMDN.js";
4
+ import {
5
+ formatBp
6
+ } from "./chunk-PTABFYQ7.js";
4
7
 
5
8
  // src/bubbles/classifyBubble.ts
6
9
  var REPEAT_GROWTH = 10;
@@ -12,15 +15,6 @@ function coveringRepeat(b, repeats) {
12
15
  );
13
16
  }
14
17
  var SUPERBUBBLE_SEGMENTS = 40;
15
- function formatBp(bp) {
16
- if (bp >= 1e4) {
17
- return `${(bp / 1e3).toFixed(0)} kb`;
18
- }
19
- if (bp >= 1e3) {
20
- return `${(bp / 1e3).toFixed(1)} kb`;
21
- }
22
- return `${bp} bp`;
23
- }
24
18
  function formatBpRange(shortest, longest) {
25
19
  const low = formatBp(shortest);
26
20
  const high = formatBp(longest);
@@ -119,7 +113,6 @@ function bubbleSegmentIds(b) {
119
113
  }
120
114
 
121
115
  export {
122
- formatBp,
123
116
  classifyBubble,
124
117
  BUBBLE_KIND_COLORS,
125
118
  BUBBLE_KIND_NAMES,
@@ -2,7 +2,7 @@ import {
2
2
  REFERENCE_RAMP_ALT_COLOR,
3
3
  REFERENCE_RAMP_MAX_HUE,
4
4
  hslToRgb
5
- } from "./chunk-SBMJNRTV.js";
5
+ } from "./chunk-A4PFFC4Q.js";
6
6
  import {
7
7
  packAbgr
8
8
  } from "./chunk-G2FD7S3C.js";
@@ -25,7 +25,11 @@ function parseRegion(text) {
25
25
  );
26
26
  }
27
27
  const n = (s) => Number(s.replaceAll(",", ""));
28
- return { refName: m[1], start: n(m[2]), end: n(m[3]) };
28
+ const region = { refName: m[1], start: n(m[2]), end: n(m[3]) };
29
+ if (region.end <= region.start) {
30
+ throw new Error(`"${text}" ends at or before it starts`);
31
+ }
32
+ return region;
29
33
  }
30
34
  async function openGbz(db, index) {
31
35
  const base = await GBZBase.open({ source: db, haplotypeIndex: index });
@@ -6,16 +6,16 @@ import {
6
6
  hasTubeMapPaths,
7
7
  tubeMapLayout,
8
8
  tubeMapReferenceLayout
9
- } from "./chunk-DK5P2YOL.js";
9
+ } from "./chunk-XI3ZUTWF.js";
10
10
  import {
11
11
  anchoredLayout
12
12
  } from "./chunk-L3O7AWLI.js";
13
13
  import {
14
14
  orderedLayout
15
- } from "./chunk-HNQPEMYE.js";
15
+ } from "./chunk-CM6LO6OC.js";
16
16
  import {
17
17
  walkRowLayout
18
- } from "./chunk-C7MZJSPT.js";
18
+ } from "./chunk-54POIBVC.js";
19
19
  import {
20
20
  isBackbone,
21
21
  isOffReference
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  engineKey,
3
3
  forceLayout
4
- } from "./chunk-XTCNEKO5.js";
4
+ } from "./chunk-2QLLQJ72.js";
5
5
 
6
6
  // src/layout/forceCache.ts
7
7
  var DEFAULT_SIZE = 4;
@@ -33,7 +33,11 @@ function createForceLayoutCache(size = DEFAULT_SIZE) {
33
33
  return { ...r, duration: r.duration || performance.now() - started };
34
34
  })
35
35
  };
36
- entry.run.catch(() => cache.delete(key));
36
+ entry.run.catch(() => {
37
+ if (cache.get(key) === entry) {
38
+ cache.delete(key);
39
+ }
40
+ });
37
41
  cache.set(key, entry);
38
42
  return entry.run;
39
43
  },
@@ -1,23 +1,21 @@
1
1
  import {
2
2
  bubblesFromGraph,
3
+ relax,
3
4
  walkIndexOf,
4
5
  walkRoutes
5
- } from "./chunk-CLOP7UVD.js";
6
+ } from "./chunk-CQHUZHET.js";
6
7
  import {
7
8
  bubbleSubgraph
8
9
  } from "./chunk-T6V4KI2L.js";
9
10
  import {
10
11
  coversGraph
11
- } from "./chunk-EHUBJDDB.js";
12
+ } from "./chunk-JFY5PWQC.js";
12
13
  import {
13
14
  bubbleSegmentIds
14
- } from "./chunk-XKWD2RY3.js";
15
- import {
16
- SATURATED_PATH_COUNT
17
- } from "./chunk-FX4RDMDN.js";
15
+ } from "./chunk-URZ3CH2R.js";
18
16
  import {
19
17
  strandSides
20
- } from "./chunk-2CVHXFK7.js";
18
+ } from "./chunk-7SRWJLSC.js";
21
19
  import {
22
20
  isBackbone
23
21
  } from "./chunk-FYQWPEEY.js";
@@ -196,13 +194,7 @@ function routesThrough(nodes, offset, next, f) {
196
194
  }
197
195
  for (let p = offset[k]; p < offset[k + 1]; p++) {
198
196
  const u = next[p] >> 1;
199
- const add = u === sink ? 0 : nodes[u].length;
200
- const prev = best.get(u);
201
- best.set(u, {
202
- min: Math.min(prev?.min ?? Infinity, cur.min + add),
203
- max: Math.max(prev?.max ?? -Infinity, cur.max + add),
204
- n: Math.min(SATURATED_PATH_COUNT, cur.n + (prev?.n ?? 0))
205
- });
197
+ relax(best, u, cur, u === sink ? 0 : nodes[u].length);
206
198
  }
207
199
  }
208
200
  return best.get(sink) ?? { min: 0, max: 0, n: 0 };
@@ -6,14 +6,14 @@ import {
6
6
  import {
7
7
  pathCssColor,
8
8
  pathGreyCssColor
9
- } from "./chunk-TWRLC3KK.js";
9
+ } from "./chunk-3XSM4OZU.js";
10
10
  import {
11
11
  pathOrigin
12
12
  } from "./chunk-M6LK4GII.js";
13
13
  import {
14
14
  ownStrand,
15
15
  strandSides
16
- } from "./chunk-2CVHXFK7.js";
16
+ } from "./chunk-7SRWJLSC.js";
17
17
  import {
18
18
  isBackbone
19
19
  } from "./chunk-FYQWPEEY.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  REFERENCE_RAMP_MAX_HUE
3
- } from "./chunk-SBMJNRTV.js";
3
+ } from "./chunk-A4PFFC4Q.js";
4
4
 
5
5
  // src/referenceRampCss.ts
6
6
  function rampHueCss(hue) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  formatBp
3
- } from "./chunk-3ZZSX5HN.js";
3
+ } from "./chunk-PTABFYQ7.js";
4
4
  import {
5
5
  isBackbone
6
6
  } from "./chunk-FYQWPEEY.js";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  nodesUnderBox
3
- } from "./chunk-FP4H7SFT.js";
3
+ } from "./chunk-4HWM3FNK.js";
4
4
  import {
5
5
  nodeLabelBudget,
6
6
  placeSizeLabels,
7
7
  rowLabelBox,
8
8
  sizeLabelCandidates
9
- } from "./chunk-3ZZSX5HN.js";
9
+ } from "./chunk-PTABFYQ7.js";
10
10
  import {
11
11
  LABEL_CHAR_PX,
12
12
  LABEL_PAD,