@jbrowse/bandage-core 10.2.7 → 10.3.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 (190) hide show
  1. package/dist/alleleProjection/projectAlleles.js +8 -4
  2. package/dist/anchoredNodes.js +2 -1
  3. package/dist/bubbleSpreads.js +2 -2
  4. package/dist/bubbles/bubbleHalos.js +10 -11
  5. package/dist/bubbles/bubblesFromGraph.js +8 -3
  6. package/dist/bubbles/classifyBubble.js +9 -6
  7. package/dist/bubbles/popBubble.js +7 -5
  8. package/dist/bubbles/superbubbles.js +18 -14
  9. package/dist/chunks/{chunk-RAKOB6IV.js → chunk-234NFZS4.js} +8 -6
  10. package/dist/chunks/{chunk-ABUIN5AK.js → chunk-2Q22S52W.js} +29 -24
  11. package/dist/chunks/{chunk-6JEWNXCQ.js → chunk-34BOZKIE.js} +0 -2
  12. package/dist/chunks/{chunk-RVS2QCOX.js → chunk-3GLG3ZLE.js} +2 -11
  13. package/dist/chunks/{chunk-3XSM4OZU.js → chunk-3GP3KT5L.js} +5 -5
  14. package/dist/chunks/{chunk-PUG7LXDF.js → chunk-3PZSBNLI.js} +4 -1
  15. package/dist/chunks/{chunk-JLSJMCDJ.js → chunk-3UST3ZQE.js} +3 -3
  16. package/dist/chunks/{chunk-KBEP7VYK.js → chunk-3VCKBSML.js} +4 -4
  17. package/dist/chunks/{chunk-BPLIXMH7.js → chunk-4XWZNPQ2.js} +14 -0
  18. package/dist/chunks/{chunk-4DRQTBBE.js → chunk-6EOB6ANX.js} +1 -1
  19. package/dist/chunks/{chunk-L2HDM2R3.js → chunk-A2TJ5UX6.js} +7 -7
  20. package/dist/chunks/{chunk-URZ3CH2R.js → chunk-A4JDEUAI.js} +1 -1
  21. package/dist/chunks/{chunk-CWFNEKST.js → chunk-A7H753BA.js} +3 -3
  22. package/dist/chunks/{chunk-CG35S2S2.js → chunk-AQCOIE5R.js} +1 -1
  23. package/dist/chunks/{chunk-TKIJ5535.js → chunk-AZ4EEF6Q.js} +6 -6
  24. package/dist/chunks/{chunk-M6LK4GII.js → chunk-B5X2RLJG.js} +17 -10
  25. package/dist/chunks/{chunk-A7CFWFQS.js → chunk-BKEZLETL.js} +1 -1
  26. package/dist/chunks/{chunk-RPRHR56C.js → chunk-BS6HPYCZ.js} +3 -3
  27. package/dist/chunks/chunk-BSOZW3FC.js +30 -0
  28. package/dist/chunks/{chunk-XXT2JCAC.js → chunk-BX4AUMZE.js} +11 -13
  29. package/dist/chunks/{chunk-N73TI3VG.js → chunk-BZFOFC4D.js} +6 -9
  30. package/dist/chunks/{chunk-4ETPXDO6.js → chunk-CGFPFBT2.js} +1 -1
  31. package/dist/chunks/{chunk-24WITXQY.js → chunk-CGMSKIEO.js} +9 -25
  32. package/dist/chunks/{chunk-VV6KGJ7M.js → chunk-CHNESV7L.js} +18 -27
  33. package/dist/chunks/{chunk-IGVV37VI.js → chunk-CKUVEHSS.js} +3 -3
  34. package/dist/chunks/{chunk-JBCZIBFC.js → chunk-CRCD3ODN.js} +0 -1
  35. package/dist/chunks/{chunk-AUFAPUO4.js → chunk-D7WIYPG3.js} +3 -1
  36. package/dist/chunks/{chunk-OIV2GBAJ.js → chunk-DBLV7PGG.js} +27 -17
  37. package/dist/chunks/{chunk-VQC7KELB.js → chunk-DO62DG26.js} +11 -3
  38. package/dist/chunks/{chunk-JA2HJIYS.js → chunk-E4ZM4OOJ.js} +3 -5
  39. package/dist/chunks/{chunk-QLWI2PZ3.js → chunk-EJRJAAN7.js} +24 -21
  40. package/dist/chunks/{chunk-QBHPHLAQ.js → chunk-EWLXU3UG.js} +41 -36
  41. package/dist/chunks/{chunk-XI3ZUTWF.js → chunk-FW2R7UDZ.js} +14 -20
  42. package/dist/chunks/{chunk-Q7LYHGGQ.js → chunk-GIHTHYXY.js} +5 -4
  43. package/dist/chunks/{chunk-L3O7AWLI.js → chunk-GJLZ2MKE.js} +2 -2
  44. package/dist/chunks/{chunk-LOEA5IHZ.js → chunk-GJU6BJJA.js} +8 -8
  45. package/dist/chunks/{chunk-XL472HHD.js → chunk-GQZVR5DW.js} +12 -7
  46. package/dist/chunks/{chunk-UVBGRJQX.js → chunk-HKYXWZQS.js} +1 -1
  47. package/dist/chunks/chunk-HMXCN6PG.js +17 -0
  48. package/dist/chunks/{chunk-WSIFAZU7.js → chunk-HNWJ4B7S.js} +12 -13
  49. package/dist/chunks/chunk-HOAIOEI7.js +18 -0
  50. package/dist/chunks/{chunk-XMW266WS.js → chunk-HSVFCA2J.js} +18 -20
  51. package/dist/chunks/{chunk-QXUEF3AJ.js → chunk-KMBE2Q42.js} +22 -17
  52. package/dist/chunks/{chunk-VQWHMWLF.js → chunk-M5NPD55W.js} +18 -14
  53. package/dist/chunks/chunk-MWOVW4AH.js +327 -0
  54. package/dist/chunks/{chunk-HK5Y2YWV.js → chunk-MYDHU2UV.js} +6 -11
  55. package/dist/chunks/{chunk-TZFWUT2C.js → chunk-MYLAJDKB.js} +2 -2
  56. package/dist/chunks/{chunk-AR4BUBMU.js → chunk-NZTYV3JL.js} +34 -35
  57. package/dist/chunks/{chunk-4HWM3FNK.js → chunk-OMUPUB4J.js} +39 -56
  58. package/dist/chunks/{chunk-LKW2TP4N.js → chunk-OOIOX36I.js} +18 -16
  59. package/dist/chunks/{chunk-EQ2NIFRH.js → chunk-OXRUPNSV.js} +1 -1
  60. package/dist/chunks/{chunk-PTABFYQ7.js → chunk-PFRQBCGC.js} +49 -60
  61. package/dist/chunks/{chunk-T6V4KI2L.js → chunk-PNMJFFNB.js} +1 -1
  62. package/dist/chunks/{chunk-KC7T5RWG.js → chunk-PSCSZSVK.js} +9 -16
  63. package/dist/chunks/{chunk-23YFB5BB.js → chunk-QH2MIXBA.js} +29 -13
  64. package/dist/chunks/{chunk-5GMFEPWR.js → chunk-R2PJKD3Y.js} +16 -28
  65. package/dist/chunks/{chunk-CQHUZHET.js → chunk-RFG42VIO.js} +46 -30
  66. package/dist/chunks/{chunk-FYQWPEEY.js → chunk-RJWPJCIB.js} +5 -11
  67. package/dist/chunks/{chunk-WBSWROE6.js → chunk-SFP3E4RI.js} +14 -18
  68. package/dist/chunks/{chunk-2CMYNW3E.js → chunk-SI3BB4DO.js} +1 -1
  69. package/dist/chunks/{chunk-DY3JCAMX.js → chunk-SOMZGDVS.js} +7 -16
  70. package/dist/chunks/{chunk-A4PFFC4Q.js → chunk-SWCULW6S.js} +60 -102
  71. package/dist/chunks/{chunk-XV4P5KEQ.js → chunk-TGUFT6KK.js} +6 -3
  72. package/dist/chunks/{chunk-CM6LO6OC.js → chunk-UAFATXYA.js} +10 -14
  73. package/dist/chunks/{chunk-7SRWJLSC.js → chunk-UBQSRCWR.js} +11 -8
  74. package/dist/chunks/{chunk-RUCH6ZFL.js → chunk-V4YML3GR.js} +2 -1
  75. package/dist/chunks/{chunk-ES2N6V56.js → chunk-VX656OAZ.js} +6 -11
  76. package/dist/chunks/chunk-WA5WNP6V.js +37 -0
  77. package/dist/chunks/{chunk-B6IW3IRE.js → chunk-WYJQIC75.js} +14 -15
  78. package/dist/chunks/{chunk-T2PCSAFY.js → chunk-XVS52NMZ.js} +2 -2
  79. package/dist/chunks/{chunk-CU6P5RUG.js → chunk-YZQI35UJ.js} +22 -16
  80. package/dist/chunks/{chunk-G45YY72K.js → chunk-Z6XZWPXK.js} +17 -25
  81. package/dist/chunks/{chunk-EFQLEGWM.js → chunk-ZJBOM73S.js} +7 -8
  82. package/dist/chunks/{chunk-RAEABQNW.js → chunk-ZPZ7GNBT.js} +1 -0
  83. package/dist/cli/figure.js +59 -56
  84. package/dist/cli/fold.js +19 -17
  85. package/dist/deletionEdges.js +5 -7
  86. package/dist/facetGrid.js +2 -1
  87. package/dist/figure.js +45 -42
  88. package/dist/figureData.js +48 -44
  89. package/dist/figureScene.js +34 -29
  90. package/dist/figureSettings.js +19 -17
  91. package/dist/foldVariants.js +5 -3
  92. package/dist/gbzCut.js +12 -7
  93. package/dist/gbzJoin.js +2 -1
  94. package/dist/gbzWindow.js +11 -6
  95. package/dist/genes/genePins.js +6 -4
  96. package/dist/gfa/gfaConverter.js +7 -5
  97. package/dist/gfa/gfaTables.js +2 -1
  98. package/dist/gfa/graphTables.js +3 -3
  99. package/dist/graphLabels.js +8 -5
  100. package/dist/index.js +88 -85
  101. package/dist/labelLayout.js +12 -9
  102. package/dist/layout/anchoredLayout.js +8 -5
  103. package/dist/layout/drawnScale.js +1 -5
  104. package/dist/layout/forceCache.js +19 -17
  105. package/dist/layout/mergeRuns.js +5 -3
  106. package/dist/layout/orderedLayout.js +5 -2
  107. package/dist/layout/orientToReference.js +3 -2
  108. package/dist/layout/placeOffReference.js +7 -4
  109. package/dist/layout/referenceSeeds.js +6 -4
  110. package/dist/layout/sampleRowLayout.js +8 -5
  111. package/dist/layout/trimToWindow.js +6 -4
  112. package/dist/layout/tubeMapLayout.js +17 -19
  113. package/dist/layout/walkRowDraw.js +18 -17
  114. package/dist/layout/walkRowLayout.js +10 -6
  115. package/dist/layout/walkRows.js +9 -5
  116. package/dist/layout/walkStrip.js +21 -18
  117. package/dist/layoutModes.js +23 -20
  118. package/dist/nodeWidths.js +1 -3
  119. package/dist/pansn.js +5 -1
  120. package/dist/pathAnchoring.js +6 -4
  121. package/dist/pathColors.js +12 -9
  122. package/dist/pathVisits.js +3 -1
  123. package/dist/pipeline.js +18 -16
  124. package/dist/reference.js +5 -3
  125. package/dist/referenceRampCss.js +9 -17
  126. package/dist/referenceSpan.js +4 -2
  127. package/dist/referenceStrip.js +18 -14
  128. package/dist/renderer/Canvas2DRenderer.js +1 -1
  129. package/dist/renderer/GeometryBuilder.js +19 -14
  130. package/dist/renderer/svgCanvas.js +1 -1
  131. package/dist/tubeMap/axis.js +11 -6
  132. package/dist/tubeMap/bundle.js +16 -12
  133. package/dist/tubeMap/coarsen.js +20 -345
  134. package/dist/tubeMap/deviations.js +53 -23
  135. package/dist/tubeMap/draw.js +11 -8
  136. package/dist/tubeMap/frame.js +3 -2
  137. package/dist/tubeMap/genes.js +10 -7
  138. package/dist/tubeMap/mismatches.js +1 -1
  139. package/dist/tubeMap/nodeColors.js +18 -14
  140. package/dist/tubeMap/reads.js +1 -1
  141. package/dist/tubeMap/warp.js +2 -1
  142. package/dist/types/alleleProjection/projectAlleles.d.ts +1 -4
  143. package/dist/types/bubbles/bubbleHalos.d.ts +0 -2
  144. package/dist/types/bubbles/bubblesFromGraph.d.ts +6 -4
  145. package/dist/types/bubbles/classifyBubble.d.ts +2 -1
  146. package/dist/types/deletionEdges.d.ts +0 -8
  147. package/dist/types/figureScene.d.ts +17 -7
  148. package/dist/types/figureSettings.d.ts +2 -0
  149. package/dist/types/gbzCut.d.ts +4 -0
  150. package/dist/types/gbzWindow.d.ts +1 -0
  151. package/dist/types/gfa-core/gfaParser.d.ts +1 -1
  152. package/dist/types/graphLabels.d.ts +2 -1
  153. package/dist/types/layout/drawnScale.d.ts +0 -2
  154. package/dist/types/layout/referenceSeeds.d.ts +2 -1
  155. package/dist/types/layout/tubeMapLayout.d.ts +0 -7
  156. package/dist/types/layout/walkRowDraw.d.ts +0 -1
  157. package/dist/types/layout/walkRowLayout.d.ts +1 -0
  158. package/dist/types/layout/walkRows.d.ts +1 -0
  159. package/dist/types/nodeWidths.d.ts +0 -1
  160. package/dist/types/pansn.d.ts +9 -0
  161. package/dist/types/pathVisits.d.ts +6 -0
  162. package/dist/types/referenceRampCss.d.ts +4 -0
  163. package/dist/types/renderer/Canvas2DRenderer.d.ts +1 -0
  164. package/dist/types/renderer/GeometryBuilder.d.ts +3 -2
  165. package/dist/types/tubeMap/axis.d.ts +3 -1
  166. package/dist/types/tubeMap/coarsen.d.ts +3 -1
  167. package/dist/types/tubeMap/deviations.d.ts +2 -1
  168. package/dist/types/tubeMap/mismatches.d.ts +0 -1
  169. package/dist/types/tubeMap/warp.d.ts +2 -1
  170. package/dist/types/util/SpatialIndex.d.ts +1 -1
  171. package/dist/types/util/geometry.d.ts +4 -0
  172. package/dist/types/util/groups.d.ts +3 -0
  173. package/dist/types/util/hitDetection.d.ts +2 -2
  174. package/dist/types/util/partitionPoint.d.ts +1 -0
  175. package/dist/types/util/weakMemo.d.ts +1 -0
  176. package/dist/types/version.d.ts +1 -1
  177. package/dist/util/SpatialIndex.js +8 -5
  178. package/dist/util/edgeCurves.js +7 -4
  179. package/dist/util/geometry.js +3 -1
  180. package/dist/util/groups.js +10 -0
  181. package/dist/util/hitDetection.js +9 -6
  182. package/dist/util/partitionPoint.js +6 -0
  183. package/dist/util/weakMemo.js +6 -0
  184. package/dist/version.js +1 -1
  185. package/dist/viewport.js +19 -17
  186. package/dist/walkEncoding.js +18 -14
  187. package/dist/walkHighlight.js +19 -15
  188. package/dist/walkKey.js +9 -6
  189. package/package.json +2 -2
  190. package/dist/chunks/chunk-ZY2AFL4Y.js +0 -43
@@ -1,20 +1,25 @@
1
1
  import {
2
2
  alongRow,
3
3
  boxesGenes,
4
- rowPitch
5
- } from "./chunk-EFQLEGWM.js";
4
+ rowPitch,
5
+ rowSpan
6
+ } from "./chunk-ZJBOM73S.js";
6
7
  import {
7
8
  el
8
9
  } from "./chunk-H2H4Y3TV.js";
9
10
  import {
10
- READOUT_ROOM
11
- } from "./chunk-L2HDM2R3.js";
11
+ READOUT_ROOM,
12
+ longestBar
13
+ } from "./chunk-A2TJ5UX6.js";
12
14
  import {
13
15
  pathOrigin
14
- } from "./chunk-M6LK4GII.js";
16
+ } from "./chunk-B5X2RLJG.js";
15
17
  import {
16
18
  LABEL_CHAR_PX
17
19
  } from "./chunk-AB35TJST.js";
20
+ import {
21
+ partitionPoint
22
+ } from "./chunk-HOAIOEI7.js";
18
23
 
19
24
  // src/layout/walkStrip.ts
20
25
  function walkStripApplies(o) {
@@ -63,7 +68,7 @@ function spansOf(graph, name) {
63
68
  const lengthOf = new Map(graph.nodes.map((n) => [n.id, n.length]));
64
69
  const origin = pathOrigin(name).name;
65
70
  const pieces = (graph.paths ?? []).filter(
66
- (p) => origin === graph.referencePath ? pathOrigin(p.name).name === origin : p.name === name
71
+ (p) => pathOrigin(p.name).name === origin
67
72
  );
68
73
  let spans;
69
74
  if (pieces.every((p) => p.start !== void 0)) {
@@ -90,19 +95,10 @@ function segmentAt(graph, row, offset, pxPerBp) {
90
95
  }
91
96
  const at = axis.reversed ? axis.start - offset : axis.start + offset;
92
97
  const tol = 0.5 / pxPerBp;
93
- const bar = axis.reversed ? { start: axis.start - row.bp, end: axis.start } : { start: axis.start, end: axis.start + row.bp };
98
+ const bar = rowSpan(axis, row.bp);
94
99
  const from = Math.max(at - tol, bar.start);
95
100
  const to = Math.min(at + tol, bar.end);
96
- let lo = 0;
97
- let hi = spans.starts.length;
98
- while (lo < hi) {
99
- const mid = lo + hi >> 1;
100
- if (spans.ends[mid] <= from) {
101
- lo = mid + 1;
102
- } else {
103
- hi = mid;
104
- }
105
- }
101
+ const lo = partitionPoint(spans.starts.length, (i) => spans.ends[i] <= from);
106
102
  let best;
107
103
  let bestLen = -1;
108
104
  let bestHolds = false;
@@ -126,7 +122,7 @@ function walkStripFrame(bars, o) {
126
122
  maxHeight - 2 * PAD_PX,
127
123
  MIN_ROW_PX
128
124
  );
129
- const longest = Math.max(bars.reference.bp, ...bars.rows.map((r) => r.bp), 1);
125
+ const longest = Math.max(longestBar(bars), 1);
130
126
  const left = labelled ? labelPx : PAD_PX;
131
127
  const usable = Math.max(1, o.width - left - PAD_PX);
132
128
  const scaleX = usable / (longest * (readouts ? READOUT_ROOM : 1));
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  referenceKnots,
3
3
  warpX
4
- } from "./chunk-HK5Y2YWV.js";
4
+ } from "./chunk-MYDHU2UV.js";
5
5
 
6
6
  // src/tubeMap/frame.ts
7
7
  var MIN_TUBE_Y_SCALE = 0.05;
@@ -1,9 +1,12 @@
1
1
  import {
2
2
  ownStrand
3
- } from "./chunk-7SRWJLSC.js";
3
+ } from "./chunk-UBQSRCWR.js";
4
+ import {
5
+ groupBy
6
+ } from "./chunk-BSOZW3FC.js";
4
7
  import {
5
8
  isBackbone
6
- } from "./chunk-FYQWPEEY.js";
9
+ } from "./chunk-RJWPJCIB.js";
7
10
 
8
11
  // src/foldVariants.ts
9
12
  function foldVariants(graph, belowBp) {
@@ -15,7 +18,7 @@ function foldVariants(graph, belowBp) {
15
18
  const sides = edges.map(forwardSides);
16
19
  const links = linksAt(nodes.length, edges, sides, index);
17
20
  const allele = alleleOf(nodes, edges, sides, index);
18
- const members = groupBy(allele);
21
+ const members = groupBy(allele.keys(), (i) => allele[i]);
19
22
  const kept = new Uint8Array(nodes.length);
20
23
  const big = [];
21
24
  for (const group of members.values()) {
@@ -137,18 +140,6 @@ function alleleOf(nodes, edges, sides, index) {
137
140
  });
138
141
  return nodes.map((_, i) => find(i));
139
142
  }
140
- function groupBy(allele) {
141
- const groups = /* @__PURE__ */ new Map();
142
- allele.forEach((root, i) => {
143
- const group = groups.get(root);
144
- if (group) {
145
- group.push(i);
146
- } else {
147
- groups.set(root, [i]);
148
- }
149
- });
150
- return groups;
151
- }
152
143
  function alleleContent(group, nodes, links, allele) {
153
144
  if (isBackbone(nodes[group[0]])) {
154
145
  return Infinity;
@@ -311,7 +302,7 @@ function mergeAlleleRuns(graph, kept, allele) {
311
302
  const internal = /* @__PURE__ */ new Set();
312
303
  ends.forEach(([a, b], k) => {
313
304
  if (a.i !== b.i && allele[a.i] === allele[b.i] && continues(nodes[a.i], a.side, nodes[b.i], b.side) && degree.get(sideKey(a.i, a.side)) === 1 && degree.get(sideKey(b.i, b.side)) === 1) {
314
- const [left, right] = nodes[a.i].stable.start < nodes[b.i].stable.start ? [a, b] : [b, a];
305
+ const [left, right] = a.side === "e" ? [a, b] : [b, a];
315
306
  next.set(left.i, { j: right.i, out: left.side, in: right.side });
316
307
  hasPrev.add(right.i);
317
308
  internal.add(k);
@@ -3,29 +3,38 @@ import {
3
3
  fadeAbgr,
4
4
  packAbgr
5
5
  } from "./chunk-G2FD7S3C.js";
6
+ import {
7
+ REFERENCE_RAMP_LIGHTNESS,
8
+ REFERENCE_RAMP_SATURATION,
9
+ rampHueAt
10
+ } from "./chunk-GQZVR5DW.js";
6
11
  import {
7
12
  baseEdgeCurves
8
- } from "./chunk-ZY2AFL4Y.js";
13
+ } from "./chunk-WA5WNP6V.js";
9
14
  import {
10
15
  PATH_LIGHTNESS,
11
16
  PATH_SATURATION,
12
17
  nameHue,
13
18
  pathHueAt
14
- } from "./chunk-3XSM4OZU.js";
19
+ } from "./chunk-3GP3KT5L.js";
15
20
  import {
16
21
  meanDepth,
17
22
  nodeWidthPx
18
- } from "./chunk-JBCZIBFC.js";
23
+ } from "./chunk-CRCD3ODN.js";
19
24
  import {
20
25
  referenceMidpoints
21
- } from "./chunk-ES2N6V56.js";
26
+ } from "./chunk-VX656OAZ.js";
22
27
  import {
23
28
  dashCurves,
24
29
  pathRibbonOffsets,
30
+ polylinePx,
25
31
  strandSides,
26
32
  translateCurves,
27
33
  yToXOf
28
- } from "./chunk-7SRWJLSC.js";
34
+ } from "./chunk-UBQSRCWR.js";
35
+ import {
36
+ pushTo
37
+ } from "./chunk-BSOZW3FC.js";
29
38
 
30
39
  // src/renderer/GeometryBuilder.ts
31
40
  var EDGE_DEFAULT_COLOR = packAbgr(119, 119, 119, 217);
@@ -119,7 +128,7 @@ function arrowheadFor({
119
128
  const lengthPx = walkPx[n - 1];
120
129
  const abutting = lengthPx < ABUTTING_PX;
121
130
  const inset = Math.min(nodeHalfWidth, lengthPx);
122
- const fit = abutting ? Math.min(1, polylinePx(fromSegments, scale, yToX) / length) : 1;
131
+ const fit = abutting ? Math.min(1, polylinePx(fromSegments, scale, scale * yToX) / length) : 1;
123
132
  if (abutting ? fit < MIN_ARROW_FIT : lengthPx < MIN_LINK_HEADS * length) {
124
133
  return void 0;
125
134
  }
@@ -137,16 +146,6 @@ function arrowheadFor({
137
146
  color
138
147
  };
139
148
  }
140
- function polylinePx(segments, scale, yToX) {
141
- let length = 0;
142
- for (let i = 1; i < segments.length; i++) {
143
- length += Math.hypot(
144
- segments[i].x - segments[i - 1].x,
145
- (segments[i].y - segments[i - 1].y) * yToX
146
- );
147
- }
148
- return length * scale;
149
- }
150
149
  function leavesStart(edge, segments, first, stranded, yToX) {
151
150
  if (stranded) {
152
151
  return strandSides(edge).from === "start";
@@ -163,58 +162,28 @@ function intoDirection(last, toSegments) {
163
162
  const atStart = Math.hypot(last.x1 - first.x, last.y1 - first.y) <= Math.hypot(last.x1 - final.x, last.y1 - final.y);
164
163
  return atStart ? { from: first, to: toSegments[1] } : { from: final, to: toSegments[toSegments.length - 2] };
165
164
  }
165
+ function normal(a, b) {
166
+ if (!a || !b) {
167
+ return void 0;
168
+ }
169
+ const dx = b.x - a.x;
170
+ const dy = b.y - a.y;
171
+ const len = Math.hypot(dx, dy);
172
+ return len > 0 ? { nx: -dy / len, ny: dx / len } : void 0;
173
+ }
166
174
  function pointNormalsOf(rawPoints, yToX = 1) {
167
175
  const points = yToX === 1 ? rawPoints : rawPoints.map((p) => ({ x: p.x, y: p.y * yToX }));
168
- const pointNormals = [];
169
- for (let i = 0; i < points.length; i++) {
170
- let nx = 0;
171
- let ny = 0;
172
- if (i === 0) {
173
- const dx = points[1].x - points[0].x;
174
- const dy = points[1].y - points[0].y;
175
- const len = Math.hypot(dx, dy);
176
- if (len > 0) {
177
- nx = -dy / len;
178
- ny = dx / len;
179
- }
180
- } else if (i === points.length - 1) {
181
- const dx = points[i].x - points[i - 1].x;
182
- const dy = points[i].y - points[i - 1].y;
183
- const len = Math.hypot(dx, dy);
184
- if (len > 0) {
185
- nx = -dy / len;
186
- ny = dx / len;
187
- }
188
- } else {
189
- const dx1 = points[i].x - points[i - 1].x;
190
- const dy1 = points[i].y - points[i - 1].y;
191
- const len1 = Math.hypot(dx1, dy1);
192
- const dx2 = points[i + 1].x - points[i].x;
193
- const dy2 = points[i + 1].y - points[i].y;
194
- const len2 = Math.hypot(dx2, dy2);
195
- if (len1 > 0 && len2 > 0) {
196
- const nx1 = -dy1 / len1;
197
- const ny1 = dx1 / len1;
198
- const nx2 = -dy2 / len2;
199
- const ny2 = dx2 / len2;
200
- nx = (nx1 + nx2) / 2;
201
- ny = (ny1 + ny2) / 2;
202
- const dot = nx1 * nx + ny1 * ny;
203
- if (dot > 0.1) {
204
- nx /= dot;
205
- ny /= dot;
206
- }
207
- } else if (len1 > 0) {
208
- nx = -dy1 / len1;
209
- ny = dx1 / len1;
210
- } else if (len2 > 0) {
211
- nx = -dy2 / len2;
212
- ny = dx2 / len2;
213
- }
176
+ return points.map((p, i) => {
177
+ const before = normal(points[i - 1], p);
178
+ const after = normal(p, points[i + 1]);
179
+ if (before && after) {
180
+ const nx = (before.nx + after.nx) / 2;
181
+ const ny = (before.ny + after.ny) / 2;
182
+ const dot = before.nx * nx + before.ny * ny;
183
+ return dot > 0.1 ? { nx: nx / dot, ny: ny / dot } : { nx, ny };
214
184
  }
215
- pointNormals.push({ nx, ny });
216
- }
217
- return pointNormals;
185
+ return before ?? after ?? { nx: 0, ny: 0 };
186
+ });
218
187
  }
219
188
  function offsetPolyline(points, normals, distance, yToX = 1) {
220
189
  return points.map((p, i) => ({
@@ -222,14 +191,6 @@ function offsetPolyline(points, normals, distance, yToX = 1) {
222
191
  y: p.y + normals[i].ny * distance / yToX
223
192
  }));
224
193
  }
225
- function packNorm(r, g, b, a) {
226
- return packAbgr(
227
- Math.round(r * 255),
228
- Math.round(g * 255),
229
- Math.round(b * 255),
230
- Math.round(a * 255)
231
- );
232
- }
233
194
  function hslToRgb(h, s, l) {
234
195
  const c = (1 - Math.abs(2 * l - 1)) * s;
235
196
  const x = c * (1 - Math.abs(h / 60 % 2 - 1));
@@ -258,6 +219,15 @@ function hslToRgb(h, s, l) {
258
219
  }
259
220
  return [r + m, g + m, b + m];
260
221
  }
222
+ function packHsl(h, s, l, a = 1) {
223
+ const [r, g, b] = hslToRgb(h, s, l);
224
+ return packAbgr(
225
+ Math.round(r * 255),
226
+ Math.round(g * 255),
227
+ Math.round(b * 255),
228
+ Math.round(a * 255)
229
+ );
230
+ }
261
231
  var DEPTH_GRADIENT = [
262
232
  [68, 1, 84],
263
233
  [59, 82, 139],
@@ -287,12 +257,8 @@ function sampleGradient(stops, t) {
287
257
  );
288
258
  }
289
259
  function hashColor(str, alpha) {
290
- const [r, g, b] = hslToRgb(nameHue(str), PATH_SATURATION, PATH_LIGHTNESS);
291
- return packNorm(r, g, b, alpha);
260
+ return packHsl(nameHue(str), PATH_SATURATION, PATH_LIGHTNESS, alpha);
292
261
  }
293
- var REFERENCE_RAMP_MAX_HUE = 300;
294
- var REFERENCE_RAMP_SATURATION = 0.7;
295
- var REFERENCE_RAMP_LIGHTNESS = 0.5;
296
262
  var REFERENCE_RAMP_ALT_RGB = [60, 65, 72];
297
263
  var REFERENCE_RAMP_ALT_COLOR = packAbgr(...REFERENCE_RAMP_ALT_RGB, 255);
298
264
  var REFERENCE_RAMP_ALT_CSS = `rgb(${REFERENCE_RAMP_ALT_RGB.join(", ")})`;
@@ -317,7 +283,7 @@ function computeReferenceRamp(graph, domain) {
317
283
  midpoints
318
284
  };
319
285
  }
320
- function computeColorSchemeRange(graph) {
286
+ function computeColorSchemeRange(graph, referenceRamp) {
321
287
  let minDepth = Infinity;
322
288
  let maxDepth = -Infinity;
323
289
  let minLength = Infinity;
@@ -346,7 +312,8 @@ function computeColorSchemeRange(graph) {
346
312
  minLength,
347
313
  maxLength,
348
314
  maxRank,
349
- nodeCount: graph.nodes.length
315
+ nodeCount: graph.nodes.length,
316
+ referenceRamp
350
317
  };
351
318
  }
352
319
  function getNodeColor(node, nodeIndex, colorScheme, range) {
@@ -384,20 +351,17 @@ function getNodeColor(node, nodeIndex, colorScheme, range) {
384
351
  if (node.stable !== void 0 && node.stable.rank > 0) {
385
352
  return REFERENCE_RAMP_ALT_COLOR;
386
353
  }
387
- const frac = Math.max(0, Math.min(1, (mid - ramp.start) / ramp.span));
388
- const [r, g, b] = hslToRgb(
389
- frac * REFERENCE_RAMP_MAX_HUE,
354
+ return packHsl(
355
+ rampHueAt((mid - ramp.start) / ramp.span),
390
356
  REFERENCE_RAMP_SATURATION,
391
357
  REFERENCE_RAMP_LIGHTNESS
392
358
  );
393
- return packNorm(r, g, b, 1);
394
359
  }
395
360
  case "grey":
396
361
  return packAbgr(160, 160, 160, 255);
397
362
  case "rainbow": {
398
363
  const hue = range.nodeCount > 1 ? nodeIndex / range.nodeCount * 360 : 0;
399
- const [r, g, b] = hslToRgb(hue, 0.75, 0.5);
400
- return packNorm(r, g, b, 1);
364
+ return packHsl(hue, 0.75, 0.5);
401
365
  }
402
366
  default:
403
367
  return packAbgr(52, 152, 219, 255);
@@ -447,12 +411,14 @@ function pathPaletteOf(graph) {
447
411
  const pathIndexByName = /* @__PURE__ */ new Map();
448
412
  const paths = graph.paths ?? [];
449
413
  for (let i = 0; i < paths.length; i++) {
450
- const [r, g, b] = hslToRgb(
451
- pathHueAt(i, paths.length),
452
- PATH_SATURATION,
453
- PATH_LIGHTNESS
414
+ pathColorByIndex.push(
415
+ packHsl(
416
+ pathHueAt(i, paths.length),
417
+ PATH_SATURATION,
418
+ PATH_LIGHTNESS,
419
+ 0.85
420
+ )
454
421
  );
455
- pathColorByIndex.push(packNorm(r, g, b, 0.85));
456
422
  if (!pathIndexByName.has(paths[i].name)) {
457
423
  pathIndexByName.set(paths[i].name, i);
458
424
  }
@@ -470,12 +436,7 @@ function pathSlotsOf(graph) {
470
436
  slots = /* @__PURE__ */ new Map();
471
437
  for (const [pathIdx, path] of (graph.paths ?? []).entries()) {
472
438
  for (const nodeId of new Set(path.nodeIds)) {
473
- const visits = slots.get(nodeId);
474
- if (visits) {
475
- visits.push(pathIdx);
476
- } else {
477
- slots.set(nodeId, [pathIdx]);
478
- }
439
+ pushTo(slots, nodeId, pathIdx);
479
440
  }
480
441
  }
481
442
  slotsCache.set(graph, slots);
@@ -505,6 +466,7 @@ function buildGeometry(options) {
505
466
  } = options;
506
467
  const depthNorm = nodeWidth === "depth" ? meanDepth(graph) : 0;
507
468
  const scale = axis.scaleX;
469
+ const worldPerScreenPx = 1 / Math.max(scale, MIN_SCALE_FOR_OFFSET);
508
470
  const yToX = yToXOf(axis);
509
471
  const sharedCurves = baseEdgeCurves(
510
472
  nodePositions,
@@ -521,7 +483,7 @@ function buildGeometry(options) {
521
483
  const arrowRuns = /* @__PURE__ */ new Map();
522
484
  const edgeCurves = [];
523
485
  const edgeCurveRuns = /* @__PURE__ */ new Map();
524
- const colorRange = { ...computeColorSchemeRange(graph), referenceRamp };
486
+ const colorRange = computeColorSchemeRange(graph, referenceRamp);
525
487
  const nodeIndexMap = /* @__PURE__ */ new Map();
526
488
  if (colorScheme === "rainbow") {
527
489
  for (let i = 0; i < graph.nodes.length; i++) {
@@ -594,7 +556,6 @@ function buildGeometry(options) {
594
556
  nx: 0,
595
557
  ny: 0
596
558
  };
597
- const worldPerScreenPx = 1 / Math.max(scale, MIN_SCALE_FOR_OFFSET);
598
559
  laneWalks.forEach((walk, lane) => {
599
560
  if (!walk.edgeIndexes.has(ei)) {
600
561
  return;
@@ -677,7 +638,6 @@ function buildGeometry(options) {
677
638
  if (drawable && lanes) {
678
639
  const laneWidth = Math.max(width / lanes.length, MIN_WALK_LANE_PX);
679
640
  const normals = pointNormalsOf(segments, yToX);
680
- const worldPerScreenPx = 1 / Math.max(scale, MIN_SCALE_FOR_OFFSET);
681
641
  lanes.forEach((walk, lane) => {
682
642
  const laneColor = walk.colors.get(nodeId);
683
643
  if (laneColor === void 0) {
@@ -692,7 +652,6 @@ function buildGeometry(options) {
692
652
  });
693
653
  } else if (drawable && slots?.length && slotWidth >= MIN_PATH_STRIPE_PX) {
694
654
  const normals = pointNormalsOf(segments, yToX);
695
- const worldPerScreenPx = 1 / Math.max(scale, MIN_SCALE_FOR_OFFSET);
696
655
  for (const slot of slots) {
697
656
  const offset = (slot - (pathCount - 1) / 2) * slotWidth * worldPerScreenPx;
698
657
  const stripe = pathColorByIndex[slot] ?? EDGE_PATH_FALLBACK_COLOR;
@@ -726,7 +685,6 @@ export {
726
685
  FADED_ALPHA,
727
686
  LIFT_BACKDROP_CSS,
728
687
  hslToRgb,
729
- REFERENCE_RAMP_MAX_HUE,
730
688
  REFERENCE_RAMP_ALT_COLOR,
731
689
  REFERENCE_RAMP_ALT_CSS,
732
690
  computeReferenceRamp,
@@ -1,3 +1,7 @@
1
+ import {
2
+ panSNFields
3
+ } from "./chunk-4XWZNPQ2.js";
4
+
1
5
  // src/facetGrid.ts
2
6
  var FACET_GAP_PX = 8;
3
7
  var FACET_TITLE_PX = 34;
@@ -85,9 +89,8 @@ function facetCells(names, by, domain = []) {
85
89
  return wrap;
86
90
  }
87
91
  const places = names.map((name) => {
88
- const [sample, haplotype, contig] = name.split("#");
89
- const n = Number(haplotype);
90
- return contig !== void 0 && Number.isInteger(n) && n >= 0 ? { sample, column: Math.max(0, n - 1) } : void 0;
92
+ const fields = panSNFields(name);
93
+ return fields && Number.isInteger(fields.haplotype) && fields.haplotype >= 0 ? { sample: fields.sample, column: Math.max(0, fields.haplotype - 1) } : void 0;
91
94
  });
92
95
  const rows = domainFirst(
93
96
  [...new Set(places.flatMap((p) => p ? [p.sample] : []))],
@@ -1,9 +1,12 @@
1
+ import {
2
+ buildNeighbors
3
+ } from "./chunk-VX656OAZ.js";
1
4
  import {
2
5
  ROW_HEIGHT_PX
3
6
  } from "./chunk-CPMHA4W5.js";
4
7
  import {
5
8
  isBackbone
6
- } from "./chunk-FYQWPEEY.js";
9
+ } from "./chunk-RJWPJCIB.js";
7
10
 
8
11
  // src/layout/orderedLayout.ts
9
12
  var GUTTER = 12;
@@ -99,13 +102,13 @@ function placeByWalks(graph, backbone) {
99
102
  }
100
103
  return placed;
101
104
  }
102
- function placeBySearch(adjacent, key) {
105
+ function placeBySearch(adjacent, key, isNode) {
103
106
  const queue = [...key.entries()].sort(([a, ka], [b, kb]) => compareKeys(ka, kb) || compare(a, b)).map(([id]) => id);
104
107
  const placed = queue.length;
105
108
  for (const id of queue) {
106
109
  const from = key.get(id);
107
110
  for (const nb of adjacent.get(id) ?? []) {
108
- if (!key.has(nb)) {
111
+ if (isNode.has(nb) && !key.has(nb)) {
109
112
  key.set(nb, { at: from.at, side: 1, hops: from.hops + 1 });
110
113
  queue.push(nb);
111
114
  }
@@ -127,6 +130,9 @@ function placeBySearch(adjacent, key) {
127
130
  let touchesLeft = false;
128
131
  for (const nb of adjacent.get(id) ?? []) {
129
132
  const other = key.get(nb);
133
+ if (!other) {
134
+ continue;
135
+ }
130
136
  if (other.at === at && searched.has(nb)) {
131
137
  deadEnd &&= other.hops <= hops;
132
138
  if (!sided.has(nb)) {
@@ -149,16 +155,6 @@ function placeBySearch(adjacent, key) {
149
155
  }
150
156
  }
151
157
  function orderKeys(graph) {
152
- const ids = new Set(graph.nodes.map((n) => n.id));
153
- const adjacent = /* @__PURE__ */ new Map();
154
- for (const e of graph.edges) {
155
- if (!ids.has(e.from) || !ids.has(e.to)) {
156
- continue;
157
- }
158
- ;
159
- (adjacent.get(e.from) ?? adjacent.set(e.from, []).get(e.from)).push(e.to);
160
- (adjacent.get(e.to) ?? adjacent.set(e.to, []).get(e.to)).push(e.from);
161
- }
162
158
  const backbone = graph.nodes.filter(isBackbone).sort(
163
159
  (a, b) => compare(a.stable.start, b.stable.start) || compare(a.name, b.name)
164
160
  );
@@ -166,7 +162,7 @@ function orderKeys(graph) {
166
162
  placeByWalks(graph, backbone).forEach((id, rank) => {
167
163
  key.set(id, { at: rank, side: 0, hops: 0 });
168
164
  });
169
- placeBySearch(adjacent, key);
165
+ placeBySearch(buildNeighbors(graph), key, new Set(graph.nodes.map((n) => n.id)));
170
166
  return key;
171
167
  }
172
168
  function layerGraph(graph) {
@@ -240,17 +240,19 @@ function unscaleYOf(curves, yToX) {
240
240
  }
241
241
  return curves;
242
242
  }
243
+ function polylinePx(points, scaleX, scaleY) {
244
+ let total = 0;
245
+ for (let i = 1; i < points.length; i++) {
246
+ const a = points[i - 1];
247
+ const b = points[i];
248
+ total += Math.hypot((b.x - a.x) * scaleX, (b.y - a.y) * scaleY);
249
+ }
250
+ return total;
251
+ }
243
252
  var SELF_LOOP_MIN_PX = 12;
244
253
  var SELF_LOOP_MAX_PX = 40;
245
254
  function selfLoopReach(segments, scale) {
246
- let length = 0;
247
- for (let i = 1; i < segments.length; i++) {
248
- length += Math.hypot(
249
- segments[i].x - segments[i - 1].x,
250
- segments[i].y - segments[i - 1].y
251
- );
252
- }
253
- const nodePx = length * scale;
255
+ const nodePx = polylinePx(segments, scale, scale);
254
256
  const reachPx = Math.min(
255
257
  SELF_LOOP_MAX_PX,
256
258
  Math.max(SELF_LOOP_MIN_PX, nodePx / 2)
@@ -520,6 +522,7 @@ export {
520
522
  yToXOf,
521
523
  PATH_RIBBON_SPACING_PX,
522
524
  pathRibbonOffsets,
525
+ polylinePx,
523
526
  selfLinkOf,
524
527
  edgeJoinOf,
525
528
  computeEdgeCurves,
@@ -1,5 +1,6 @@
1
1
  // src/renderer/svgCanvas.ts
2
2
  var n = (v) => +v.toFixed(1);
3
+ var alpha = (v) => +v.toFixed(3);
3
4
  function paint(css) {
4
5
  const m = /^rgba?\(([^,]+),([^,]+),([^,)]+)(?:,([^)]+))?\)$/.exec(
5
6
  css.replaceAll(" ", "")
@@ -12,7 +13,7 @@ function paint(css) {
12
13
  }
13
14
  function paintAttrs(kind, css) {
14
15
  const { color, opacity } = paint(css);
15
- return `${kind}="${color}"${opacity < 1 ? ` ${kind}-opacity="${n(opacity)}"` : ""}`;
16
+ return `${kind}="${color}"${opacity < 1 ? ` ${kind}-opacity="${alpha(opacity)}"` : ""}`;
16
17
  }
17
18
  var DOT_PX = 0.5;
18
19
  var DOT_CELL_PX = 0.25;
@@ -1,22 +1,17 @@
1
+ import {
2
+ pushTo
3
+ } from "./chunk-BSOZW3FC.js";
1
4
  import {
2
5
  isBackbone
3
- } from "./chunk-FYQWPEEY.js";
6
+ } from "./chunk-RJWPJCIB.js";
4
7
 
5
8
  // src/referenceSpan.ts
6
9
  var MAX_BACKBONE_HOPS = 4;
7
10
  function buildNeighbors(graph) {
8
11
  const neighbors = /* @__PURE__ */ new Map();
9
- function add(from, to) {
10
- const list = neighbors.get(from);
11
- if (list) {
12
- list.push(to);
13
- } else {
14
- neighbors.set(from, [to]);
15
- }
16
- }
17
12
  for (const edge of graph.edges) {
18
- add(edge.from, edge.to);
19
- add(edge.to, edge.from);
13
+ pushTo(neighbors, edge.from, edge.to);
14
+ pushTo(neighbors, edge.to, edge.from);
20
15
  }
21
16
  return neighbors;
22
17
  }
@@ -0,0 +1,37 @@
1
+ import {
2
+ weakMemo
3
+ } from "./chunk-HMXCN6PG.js";
4
+ import {
5
+ edgeCurvesOf
6
+ } from "./chunk-CGMSKIEO.js";
7
+
8
+ // src/util/edgeCurves.ts
9
+ var cache = weakMemo();
10
+ function baseEdgeCurves(nodePositions, graph, axis, deletions, version, routes, stranded = false) {
11
+ return cache(
12
+ nodePositions,
13
+ [graph, axis.scaleX, axis.scaleY, deletions, routes, stranded, version],
14
+ () => {
15
+ const curves = /* @__PURE__ */ new Map();
16
+ for (let ei = 0; ei < graph.edges.length; ei++) {
17
+ const bypassed = deletions?.get(ei);
18
+ const edgeCurves = edgeCurvesOf(
19
+ nodePositions,
20
+ graph.edges[ei],
21
+ axis,
22
+ bypassed,
23
+ bypassed && routes?.[ei],
24
+ stranded
25
+ );
26
+ if (edgeCurves) {
27
+ curves.set(ei, edgeCurves);
28
+ }
29
+ }
30
+ return curves;
31
+ }
32
+ );
33
+ }
34
+
35
+ export {
36
+ baseEdgeCurves
37
+ };