@jbrowse/bandage-core 0.1.20 → 4.0.25

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.
package/dist/index.js CHANGED
@@ -8,10 +8,13 @@ import {
8
8
  FADED_ALPHA,
9
9
  FIT_PADDING,
10
10
  FORCE_LAYOUT_LABEL,
11
+ HALO_FACTOR,
12
+ HPRC_GBZ,
11
13
  LABEL_CHAR_PX,
12
14
  LABEL_PAD,
13
15
  LABEL_PX,
14
16
  LAYOUT_MODES,
17
+ LEGEND_INSET_PX,
15
18
  LIFT_BACKDROP_COLOR,
16
19
  NODE_WIDTHS,
17
20
  REFERENCE_RAMP_MAX_HUE,
@@ -29,6 +32,7 @@ import {
29
32
  computeReferenceRamp,
30
33
  contains,
31
34
  curveBounds,
35
+ cutGbzRegion,
32
36
  cutWindowGFA,
33
37
  deletionEdges,
34
38
  drawingBounds,
@@ -42,15 +46,20 @@ import {
42
46
  fadeAbgr,
43
47
  featuresOnBackbone,
44
48
  figureSvg,
45
- firstNodeAtOrAfter,
46
49
  fitTransform,
47
50
  forceLayout,
48
51
  formatBp,
52
+ geneCoverageNote,
53
+ genePins,
54
+ genesFromBed,
55
+ genesFromGff3Lines,
56
+ genesFromText,
49
57
  getNodeColor,
50
58
  graphBackbone,
51
59
  haplotypeWanted,
52
60
  isBackbone,
53
61
  layoutExtent,
62
+ layoutLabels,
54
63
  layoutModeByValue,
55
64
  loadBandage,
56
65
  loadGraph,
@@ -58,19 +67,16 @@ import {
58
67
  meanDepth,
59
68
  modeUsesLayoutEngine,
60
69
  nodeInk,
61
- nodeLabelBudget,
62
70
  nodeWidthPx,
63
- occupancy,
71
+ openGbz,
64
72
  padded,
65
73
  panSNContig,
66
74
  panSNHaplotype,
67
75
  panSNSample,
76
+ parseRegion,
68
77
  pathColorsLegible,
69
78
  pathLegend,
70
79
  pathRibbonOffsets,
71
- placeLabels,
72
- placeSizeLabels,
73
- polylineSlice,
74
80
  rangeText,
75
81
  refNameBinding,
76
82
  referenceOrder,
@@ -79,23 +85,23 @@ import {
79
85
  resolveColorScheme,
80
86
  resolveEncoding,
81
87
  resolveReferenceSample,
82
- rowLabelBox,
83
88
  schemeCss,
84
89
  screenToLayout,
85
- sizeLabelCandidates,
86
90
  svgCanvas,
87
91
  svgPath,
88
92
  translateCurves,
93
+ version,
89
94
  viewportOf,
90
95
  walkHighlight,
91
96
  walkKey,
92
97
  walkLift,
98
+ walkPosition,
93
99
  walkRows,
94
100
  walkRowsExtent,
95
101
  wellKnownSample,
96
102
  yToXOf,
97
103
  zoomAbout
98
- } from "./chunks/chunk-3XDR3ZBS.js";
104
+ } from "./chunks/chunk-B5ZHLU4N.js";
99
105
 
100
106
  // src/index.ts
101
107
  import { getDpr } from "@jbrowse/render-core/canvas2dUtils";
@@ -212,14 +218,14 @@ var SpatialIndex = class {
212
218
  }
213
219
  };
214
220
  var EdgeSpatialIndex = class {
215
- constructor(nodePositions, graph, drawPaths, axis, cellSize, deletions, version = 0) {
221
+ constructor(nodePositions, graph, drawPaths, axis, cellSize, deletions, version2 = 0) {
216
222
  this.cells = /* @__PURE__ */ new Map();
217
223
  this.edgeCurves = baseEdgeCurves(
218
224
  nodePositions,
219
225
  graph,
220
226
  axis,
221
227
  deletions,
222
- version
228
+ version2
223
229
  );
224
230
  const boxes = [];
225
231
  let extentX = 0;
@@ -332,19 +338,19 @@ function distanceToEdgeCurves(px, py, curves, yToX = 1) {
332
338
  return minDist;
333
339
  }
334
340
  var nodeCache = /* @__PURE__ */ new WeakMap();
335
- function getSpatialIndex(nodePositions, version) {
341
+ function getSpatialIndex(nodePositions, version2) {
336
342
  const cached = nodeCache.get(nodePositions);
337
- if (cached?.version === version) {
343
+ if (cached?.version === version2) {
338
344
  return cached.index;
339
345
  }
340
346
  const index = new SpatialIndex(nodePositions);
341
- nodeCache.set(nodePositions, { version, index });
347
+ nodeCache.set(nodePositions, { version: version2, index });
342
348
  return index;
343
349
  }
344
350
  var edgeCache = /* @__PURE__ */ new WeakMap();
345
- function getEdgeSpatialIndex(nodePositions, graph, drawPaths, axis, version, deletions) {
351
+ function getEdgeSpatialIndex(nodePositions, graph, drawPaths, axis, version2, deletions) {
346
352
  const cached = edgeCache.get(nodePositions);
347
- if (cached?.graph === graph && cached.drawPaths === drawPaths && cached.scaleX === axis.scaleX && cached.scaleY === axis.scaleY && cached.version === version && cached.deletions === deletions) {
353
+ if (cached?.graph === graph && cached.drawPaths === drawPaths && cached.scaleX === axis.scaleX && cached.scaleY === axis.scaleY && cached.version === version2 && cached.deletions === deletions) {
348
354
  return cached.index;
349
355
  }
350
356
  const index = new EdgeSpatialIndex(
@@ -354,23 +360,23 @@ function getEdgeSpatialIndex(nodePositions, graph, drawPaths, axis, version, del
354
360
  axis,
355
361
  void 0,
356
362
  deletions,
357
- version
363
+ version2
358
364
  );
359
365
  edgeCache.set(nodePositions, {
360
366
  graph,
361
367
  drawPaths,
362
368
  scaleX: axis.scaleX,
363
369
  scaleY: axis.scaleY,
364
- version,
370
+ version: version2,
365
371
  index,
366
372
  deletions
367
373
  });
368
374
  return index;
369
375
  }
370
376
  var MIN_NODE_REACH_PX = 5;
371
- function findHoveredNode(nodePositions, graphX, graphY, axis, version = 0, ink) {
377
+ function findHoveredNode(nodePositions, graphX, graphY, axis, version2 = 0, ink) {
372
378
  const yToX = yToXOf(axis);
373
- const index = getSpatialIndex(nodePositions, version);
379
+ const index = getSpatialIndex(nodePositions, version2);
374
380
  const reach = (px) => Math.max(MIN_NODE_REACH_PX, px) / axis.scaleX;
375
381
  const queryReach = reach(ink?.maxHalfWidthPx ?? 0);
376
382
  const candidates = index.query(graphX, graphY, queryReach, queryReach / yToX);
@@ -393,7 +399,7 @@ function findHoveredNode(nodePositions, graphX, graphY, axis, version = 0, ink)
393
399
  }
394
400
  return hovered;
395
401
  }
396
- function findHoveredEdge(nodePositions, graph, graphX, graphY, axis, drawPaths, version = 0, deletions, hiddenEdges) {
402
+ function findHoveredEdge(nodePositions, graph, graphX, graphY, axis, drawPaths, version2 = 0, deletions, hiddenEdges) {
397
403
  const yToX = yToXOf(axis);
398
404
  const edgeThreshold = 10 / axis.scaleX;
399
405
  const edgeIndex = getEdgeSpatialIndex(
@@ -401,7 +407,7 @@ function findHoveredEdge(nodePositions, graph, graphX, graphY, axis, drawPaths,
401
407
  graph,
402
408
  drawPaths,
403
409
  axis,
404
- version,
410
+ version2,
405
411
  deletions
406
412
  );
407
413
  const candidates = edgeIndex.query(
@@ -466,27 +472,31 @@ function wheelZoomFactor(e) {
466
472
 
467
473
  // src/referenceStrip.ts
468
474
  import { abgrToCssRgba } from "@jbrowse/core/util/colorBits";
469
- var REFERENCE_STRIP_PX = 10;
475
+ var REFERENCE_STRIP_PX = 12;
470
476
  var REFERENCE_STRIP_ZONE_PX = REFERENCE_STRIP_PX + 8;
471
- var OVERHANG_PX = 5;
477
+ var OVERHANG_PX = 8;
478
+ var OVERHANG_CAP_PX = OVERHANG_PX + 3;
479
+ var MIN_STAGGER_PX = 12;
480
+ var PALE = abgrToCssRgba(fadeAbgr(LIFT_BACKDROP_COLOR, FADED_ALPHA));
472
481
  function referenceStripBlocks(graph, {
473
482
  colorScheme,
474
483
  referenceRamp,
475
- walkNodes,
476
- walkColors
484
+ walks
477
485
  }) {
478
486
  const range = { ...computeColorSchemeRange(graph), referenceRamp };
479
487
  const out = [];
480
488
  graph.nodes.forEach((node, index) => {
481
489
  if (isBackbone(node)) {
482
- const own = walkNodes ? walkColors?.get(node.id) ?? LIFT_BACKDROP_COLOR : getNodeColor(node, index, colorScheme, range);
483
- const faded = !!walkNodes && !walkNodes.has(node.id);
490
+ const colors = walks ? walks.map((w) => {
491
+ const lane = w.colors.get(node.id);
492
+ return lane === void 0 ? PALE : abgrToCssRgba(lane);
493
+ }) : [abgrToCssRgba(getNodeColor(node, index, colorScheme, range))];
484
494
  out.push({
485
495
  node: node.id,
486
496
  bp0: node.stable.start,
487
497
  bp1: node.stable.start + node.length,
488
- color: abgrToCssRgba(faded ? fadeAbgr(own, FADED_ALPHA) : own),
489
- faded
498
+ colors,
499
+ faded: colors.includes(PALE)
490
500
  });
491
501
  }
492
502
  });
@@ -532,7 +542,7 @@ function stripPixels(blocks, frame, width, dpr) {
532
542
  const [x0, x1] = span(frame, b.bp0, b.bp1);
533
543
  const px0 = Math.round(x0 * dpr);
534
544
  return {
535
- color: b.color,
545
+ colors: b.colors,
536
546
  x0,
537
547
  px0,
538
548
  px1: Math.max(Math.round(x1 * dpr), px0 + 1)
@@ -540,22 +550,34 @@ function stripPixels(blocks, frame, width, dpr) {
540
550
  }).filter((b) => b.px1 > 0 && b.px0 < width * dpr).sort((a, b) => a.x0 - b.x0);
541
551
  const out = [];
542
552
  let claimed = -Infinity;
543
- for (const { color, px0, px1 } of placed) {
553
+ const tierEnds = [-Infinity, -Infinity];
554
+ for (const { colors, px0, px1 } of placed) {
544
555
  const start = Math.max(px0, claimed);
545
556
  if (px1 > start) {
546
- out.push({ color, x0: start / dpr, x1: px1 / dpr });
557
+ const tier = tierEnds[0] < start ? 0 : 1;
558
+ tierEnds[tier] = px1;
559
+ out.push({ colors, x0: start / dpr, x1: px1 / dpr, tier });
547
560
  claimed = px1;
548
561
  }
549
562
  }
550
- return out;
563
+ const covered = out.length > 0 ? out.at(-1).x1 - out[0].x0 : 0;
564
+ return covered >= out.length * MIN_STAGGER_PX ? out : out.map(({ tier: _, ...b }) => b);
551
565
  }
552
- function drawOverhang(ctx, tipX, inward) {
553
- const mid = REFERENCE_STRIP_PX / 2;
554
- const baseX = tipX + inward * (OVERHANG_PX + 1);
555
- ctx.moveTo(tipX + inward, mid);
556
- ctx.lineTo(baseX, mid - OVERHANG_PX / 1.4);
557
- ctx.lineTo(baseX, mid + OVERHANG_PX / 1.4);
566
+ function drawOverhang(ctx, edgeX, inward, ink) {
567
+ const capX = inward > 0 ? edgeX : edgeX - OVERHANG_CAP_PX;
568
+ ctx.clearRect(capX, 0, OVERHANG_CAP_PX, REFERENCE_STRIP_PX);
569
+ const tipX = edgeX + inward;
570
+ const baseX = tipX + inward * OVERHANG_PX;
571
+ ctx.beginPath();
572
+ ctx.moveTo(tipX, REFERENCE_STRIP_PX / 2);
573
+ ctx.lineTo(baseX, 0);
574
+ ctx.lineTo(baseX, REFERENCE_STRIP_PX);
558
575
  ctx.closePath();
576
+ ctx.fillStyle = ink;
577
+ ctx.fill();
578
+ }
579
+ function rowEdge(row, rows, dpr) {
580
+ return Math.round(row * REFERENCE_STRIP_PX * dpr / rows) / dpr;
559
581
  }
560
582
  function drawReferenceStrip(ctx, blocks, frame, {
561
583
  width,
@@ -564,26 +586,24 @@ function drawReferenceStrip(ctx, blocks, frame, {
564
586
  dpr = 1
565
587
  }) {
566
588
  const ink = darkMode ? "#ffffff" : "#18181c";
567
- ctx.fillStyle = darkMode ? "#1f1f1f" : "#ffffff";
568
- ctx.fillRect(0, 0, width, REFERENCE_STRIP_ZONE_PX);
589
+ ctx.clearRect(0, 0, width, REFERENCE_STRIP_ZONE_PX);
569
590
  for (const b of stripPixels(blocks, frame, width, dpr)) {
570
- ctx.fillStyle = b.color;
571
- ctx.fillRect(b.x0, 0, b.x1 - b.x0, REFERENCE_STRIP_PX);
591
+ const { tier } = b;
592
+ const staggered = tier !== void 0 && b.colors.length === 1;
593
+ const rows = staggered ? 2 : b.colors.length;
594
+ b.colors.forEach((color, i) => {
595
+ const row = staggered ? tier : i;
596
+ const y0 = rowEdge(row, rows, dpr);
597
+ ctx.fillStyle = color;
598
+ ctx.fillRect(b.x0, y0, b.x1 - b.x0, rowEdge(row + 1, rows, dpr) - y0);
599
+ });
572
600
  }
573
601
  const overhang = stripOverhang(blocks, frame, width);
574
- if (overhang.left > 0 || overhang.right > 0) {
575
- ctx.beginPath();
576
- if (overhang.left > 0) {
577
- drawOverhang(ctx, 0, 1);
578
- }
579
- if (overhang.right > 0) {
580
- drawOverhang(ctx, width, -1);
581
- }
582
- ctx.fillStyle = ink;
583
- ctx.fill();
584
- ctx.strokeStyle = darkMode ? "#1f1f1f" : "#ffffff";
585
- ctx.lineWidth = 1;
586
- ctx.stroke();
602
+ if (overhang.left > 0) {
603
+ drawOverhang(ctx, 0, 1, ink);
604
+ }
605
+ if (overhang.right > 0) {
606
+ drawOverhang(ctx, width, -1, ink);
587
607
  }
588
608
  if (lit) {
589
609
  const [x0, x1] = span(frame, lit.start, lit.end);
@@ -1042,7 +1062,7 @@ function niceStep(raw) {
1042
1062
  const m = raw / pow;
1043
1063
  return (m <= 1 ? 1 : m <= 2 ? 2 : m <= 5 ? 5 : 10) * pow;
1044
1064
  }
1045
- function placeLabels2(candidates) {
1065
+ function placeLabels(candidates) {
1046
1066
  const placed = [];
1047
1067
  for (const a of candidates) {
1048
1068
  if (placed.every(
@@ -1079,7 +1099,7 @@ function scaleMarks(boxes, x, width, measure) {
1079
1099
  return {
1080
1100
  spans: [{ x0: from, x1: to }],
1081
1101
  ticks,
1082
- labels: placeLabels2(positions)
1102
+ labels: placeLabels(positions)
1083
1103
  };
1084
1104
  }
1085
1105
  function boxMarks(boxes, x, width, measure) {
@@ -1120,7 +1140,7 @@ function boxMarks(boxes, x, width, measure) {
1120
1140
  return {
1121
1141
  spans,
1122
1142
  ticks,
1123
- labels: placeLabels2([...ends, ...lengths, ...boundaries])
1143
+ labels: placeLabels([...ends, ...lengths, ...boundaries])
1124
1144
  };
1125
1145
  }
1126
1146
  function rulerMarks(boxes, x, width, measure, referenceAxis = false) {
@@ -1688,219 +1708,6 @@ function bubbleSubgraph(graph, segmentIds) {
1688
1708
  referencePath: graph.referencePath
1689
1709
  };
1690
1710
  }
1691
-
1692
- // src/labelLayout.ts
1693
- var HALO_FACTOR = 3.4;
1694
- var LEGEND_INSET_PX = 6;
1695
- var ROUTE_STACK = 8;
1696
- var GENE_PIN_DROP_PX = 18;
1697
- var GENE_STACK = 2;
1698
- var TOPMOST_BASELINE = LABEL_PX + LABEL_PAD;
1699
- function geneCoverageNote(pin) {
1700
- const length = pin.gene.end - pin.gene.start;
1701
- if (pin.covered >= 0.98) {
1702
- return void 0;
1703
- }
1704
- const [per, unit] = length >= 1e6 ? [1e6, "Mb"] : length >= 1e3 ? [1e3, "kb"] : [1, "bp"];
1705
- const amount = (bp) => +(bp / per).toFixed(per === 1 ? 0 : 1);
1706
- return `${amount(pin.covered * length)} of ${amount(length)} ${unit}`;
1707
- }
1708
- function byExtent(items, extent) {
1709
- return [...items].sort((a, b) => extent(b) - extent(a));
1710
- }
1711
- function layoutLabels(m) {
1712
- const { paneWidth: width, canvasHeight: height, translateX, translateY } = m;
1713
- const { scaleX, scaleY } = m.axisScale;
1714
- const frame = { width, height };
1715
- const screen = (p) => ({
1716
- x: p.x * scaleX + translateX,
1717
- y: p.y * scaleY + translateY
1718
- });
1719
- const reserved = m.drawnRowLabels.map(
1720
- ({ label, y }) => rowLabelBox(label, y * scaleY + translateY)
1721
- );
1722
- const stripPx = m.referenceStripZonePx ?? 0;
1723
- if (stripPx > 0) {
1724
- reserved.push({ x0: 0, x1: width, y0: 0, y1: stripPx });
1725
- }
1726
- if (m.legendSize.width > 0) {
1727
- reserved.push({
1728
- x0: width - LEGEND_INSET_PX - m.legendSize.width,
1729
- x1: width,
1730
- y0: 0,
1731
- y1: stripPx + LEGEND_INSET_PX + m.legendSize.height
1732
- });
1733
- }
1734
- if (m.poppedFrom) {
1735
- reserved.push({
1736
- x0: 0,
1737
- x1: 60 + m.poppedFrom.label.length * LABEL_CHAR_PX * 1.2,
1738
- y0: 0,
1739
- y1: 44
1740
- });
1741
- }
1742
- const take = occupancy(frame, reserved);
1743
- const onRows = m.drawnRowLabels.length > 0;
1744
- const rowsTop = onRows ? Math.min(...m.drawnRowLabels.map((r) => r.y)) : Infinity;
1745
- const halo = m.contigThickness * HALO_FACTOR;
1746
- const byBubble = byExtent(m.bubbleHalos, (h) => h.members);
1747
- const bubbles = placeLabels(
1748
- byBubble.map((h) => {
1749
- const { x, y } = screen({
1750
- x: h.labelAt.x,
1751
- y: Math.min(h.labelAt.y, rowsTop)
1752
- });
1753
- const baseline = y - halo / 2 - 6;
1754
- return {
1755
- item: h,
1756
- x,
1757
- y: onRows ? Math.max(baseline, TOPMOST_BASELINE) : baseline,
1758
- text: h.label
1759
- };
1760
- }),
1761
- frame,
1762
- take
1763
- );
1764
- const genes = placeLabels(
1765
- byExtent(m.genePins, (pin) => pin.gene.end - pin.gene.start).map((pin) => {
1766
- const { x, y } = screen(pin.at);
1767
- const note = geneCoverageNote(pin);
1768
- return {
1769
- item: pin,
1770
- x,
1771
- y: y + m.contigThickness + GENE_PIN_DROP_PX,
1772
- text: note ? `${pin.gene.name} \xB7 ${note}` : pin.gene.name,
1773
- stack: GENE_STACK
1774
- };
1775
- }),
1776
- frame,
1777
- take
1778
- );
1779
- const sizeCandidates = m.nodePositions && m.labelsNodeSizes ? sizeLabelCandidates({
1780
- nodePositions: m.nodePositions,
1781
- nodeLengths: m.nodeLengths,
1782
- deletions: m.showDeletionEdges ? m.deletions : [],
1783
- alleleDeletions: m.alleleDeletions,
1784
- axis: m.axisScale,
1785
- translateX,
1786
- translateY,
1787
- width,
1788
- height,
1789
- version: m.positionsVersion
1790
- }) : { deletions: [], nodes: [] };
1791
- const deletionLabels = placeSizeLabels(sizeCandidates.deletions, take);
1792
- const routes2 = placeLabels(
1793
- byBubble.flatMap(
1794
- (h) => h.routes.map((route) => {
1795
- const { x, y } = screen(route.at);
1796
- return {
1797
- item: { halo: h, route },
1798
- x,
1799
- y: y + 4,
1800
- text: route.text,
1801
- stack: ROUTE_STACK
1802
- };
1803
- })
1804
- ),
1805
- frame,
1806
- take
1807
- );
1808
- const nodeLabels = placeSizeLabels(
1809
- sizeCandidates.nodes,
1810
- take,
1811
- nodeLabelBudget(width, height)
1812
- );
1813
- return {
1814
- bubbles,
1815
- genes,
1816
- routes: routes2,
1817
- sizes: [...deletionLabels, ...nodeLabels]
1818
- };
1819
- }
1820
-
1821
- // src/genes/genePins.ts
1822
- function genePins(graph, genes, positions) {
1823
- const byRefName = /* @__PURE__ */ new Map();
1824
- for (const node of graph.nodes) {
1825
- if (isBackbone(node)) {
1826
- const { refName } = node.stable;
1827
- if (positions[node.id]?.length) {
1828
- const entry = byRefName.get(refName) ?? byRefName.set(refName, { nodes: [], reach: 0 }).get(refName);
1829
- entry.nodes.push(node);
1830
- entry.reach = Math.max(entry.reach, node.length);
1831
- }
1832
- }
1833
- }
1834
- for (const { nodes } of byRefName.values()) {
1835
- nodes.sort((a, b) => a.stable.start - b.stable.start);
1836
- }
1837
- const pins = [];
1838
- for (const gene of genes) {
1839
- const backbone = byRefName.get(gene.refName);
1840
- if (!backbone) {
1841
- continue;
1842
- }
1843
- const parts = [];
1844
- const exonsByNode = [];
1845
- let at;
1846
- let atDistance = Infinity;
1847
- let covered = 0;
1848
- const mid = (gene.start + gene.end) / 2;
1849
- const { nodes, reach } = backbone;
1850
- for (let i = firstNodeAtOrAfter(nodes, gene.start - reach); i < nodes.length && nodes[i].stable.start < gene.end; i++) {
1851
- const node = nodes[i];
1852
- const nodeStart = node.stable.start;
1853
- const nodeEnd = nodeStart + node.length;
1854
- if (nodeEnd <= gene.start) {
1855
- continue;
1856
- }
1857
- const line = positions[node.id];
1858
- covered += Math.min(nodeEnd, gene.end) - Math.max(nodeStart, gene.start);
1859
- const nodeParts = [];
1860
- for (const exon of gene.exons) {
1861
- const a = Math.max(exon.start, nodeStart);
1862
- const b = Math.min(exon.end, nodeEnd);
1863
- if (b <= a) {
1864
- continue;
1865
- }
1866
- const stretch = polylineSlice(
1867
- line,
1868
- (a - nodeStart) / node.length,
1869
- (b - nodeStart) / node.length
1870
- );
1871
- if (stretch.length === 1) {
1872
- stretch.push({ ...stretch[0] });
1873
- }
1874
- nodeParts.push(svgPath(stretch));
1875
- }
1876
- if (nodeParts.length > 0) {
1877
- parts.push(...nodeParts);
1878
- exonsByNode.push({ nodeId: node.id, d: nodeParts.join("") });
1879
- }
1880
- const pinBp = Math.min(Math.max(mid, nodeStart), nodeEnd);
1881
- const distance = Math.abs(pinBp - mid);
1882
- if (distance < atDistance) {
1883
- atDistance = distance;
1884
- const [p] = polylineSlice(
1885
- line,
1886
- (pinBp - nodeStart) / node.length,
1887
- (pinBp - nodeStart) / node.length
1888
- );
1889
- at = p;
1890
- }
1891
- }
1892
- if (at) {
1893
- pins.push({
1894
- gene,
1895
- exons: parts.join(""),
1896
- exonsByNode,
1897
- at,
1898
- covered: covered / (gene.end - gene.start)
1899
- });
1900
- }
1901
- }
1902
- return pins;
1903
- }
1904
1711
  export {
1905
1712
  BUBBLE_KIND_COLORS,
1906
1713
  BUBBLE_KIND_NAMES,
@@ -1913,6 +1720,7 @@ export {
1913
1720
  FIT_PADDING,
1914
1721
  FORCE_LAYOUT_LABEL,
1915
1722
  HALO_FACTOR,
1723
+ HPRC_GBZ,
1916
1724
  LABEL_CHAR_PX,
1917
1725
  LABEL_PAD,
1918
1726
  LABEL_PX,
@@ -1938,6 +1746,7 @@ export {
1938
1746
  computeReferenceRamp,
1939
1747
  connectorAt,
1940
1748
  contains,
1749
+ cutGbzRegion,
1941
1750
  cutWindowGFA,
1942
1751
  deletionEdges,
1943
1752
  drawReferenceStrip,
@@ -1962,6 +1771,9 @@ export {
1962
1771
  formatBp,
1963
1772
  geneCoverageNote,
1964
1773
  genePins,
1774
+ genesFromBed,
1775
+ genesFromGff3Lines,
1776
+ genesFromText,
1965
1777
  getDpr,
1966
1778
  graphBackbone,
1967
1779
  haplotypeWanted,
@@ -1975,10 +1787,12 @@ export {
1975
1787
  modeUsesLayoutEngine,
1976
1788
  nodeInk,
1977
1789
  nodeWidthPx,
1790
+ openGbz,
1978
1791
  padded,
1979
1792
  panSNContig,
1980
1793
  panSNHaplotype,
1981
1794
  panSNSample,
1795
+ parseRegion,
1982
1796
  pathColorsLegible,
1983
1797
  pathLegend,
1984
1798
  rangeText,
@@ -2003,10 +1817,12 @@ export {
2003
1817
  tubeMapNodeAt,
2004
1818
  tubeMapPicture,
2005
1819
  tubeX,
1820
+ version,
2006
1821
  viewportOf,
2007
1822
  walkHighlight,
2008
1823
  walkKey,
2009
1824
  walkLift,
1825
+ walkPosition,
2010
1826
  walkRows,
2011
1827
  walkRowsExtent,
2012
1828
  warpX,
@@ -1,20 +1,20 @@
1
1
  import type { BubbleSpread } from '../bubbleSpreads.js';
2
2
  import type { FigureOptions } from '../figure.js';
3
+ import type { GbzSource } from '../gbzCut.js';
3
4
  import type { LayoutModeValue } from '../layoutModes.js';
4
5
  import type { WalkLayer } from '../walkEncoding.js';
5
- export interface FigureSpec extends Omit<FigureOptions, 'walks' | 'region'> {
6
+ export interface FigureSpec extends Omit<FigureOptions, 'walks' | 'region' | 'genes' | 'spec'> {
6
7
  gfa?: string;
7
- gbz?: {
8
- db: string;
9
- index?: string;
10
- region: string;
11
- haplotypes?: string[];
12
- referenceSample?: string;
13
- };
8
+ gbz?: GbzSource;
14
9
  region?: string;
15
10
  referencePath?: string;
16
11
  layout?: LayoutModeValue;
17
12
  quality?: number;
18
13
  bubbleSpread?: BubbleSpread;
19
14
  walks?: (string | WalkLayer)[];
15
+ genes?: {
16
+ file: string;
17
+ index?: string;
18
+ format?: 'gff3' | 'bed';
19
+ };
20
20
  }
@@ -1,5 +1,6 @@
1
1
  import type { ColorScheme } from './colorSchemes.js';
2
2
  import type { FacetBy } from './facetGrid.js';
3
+ import type { GeneModel } from './genes/genePins.js';
3
4
  import type { NodeWidth } from './nodeWidths.js';
4
5
  import type { Graph, LayoutResult } from './types.js';
5
6
  import type { WalkLayer } from './walkEncoding.js';
@@ -19,6 +20,7 @@ export interface FigureOptions {
19
20
  start: number;
20
21
  end: number;
21
22
  };
22
- metadata?: string;
23
+ genes?: GeneModel[];
24
+ spec?: unknown;
23
25
  }
24
26
  export declare function figureSvg(graph: Graph, layout: LayoutResult, o?: FigureOptions): string;
@@ -0,0 +1,33 @@
1
+ import { GBZBase } from '@gmod/gbz-base';
2
+ import type { ByteSource, RangeOptions } from '@gmod/gbz-base';
3
+ export interface GbzSource {
4
+ db: string;
5
+ index?: string;
6
+ region: string;
7
+ haplotypes?: string[];
8
+ referenceSample?: string;
9
+ context?: number;
10
+ snarls?: RangeOptions['snarls'];
11
+ }
12
+ export declare const HPRC_GBZ: {
13
+ db: string;
14
+ index: string;
15
+ };
16
+ export declare function parseRegion(text: string): {
17
+ refName: string;
18
+ start: number;
19
+ end: number;
20
+ };
21
+ export declare function openGbz(db: ByteSource, index?: ByteSource): Promise<{
22
+ base: GBZBase;
23
+ referenceSamples: string[];
24
+ }>;
25
+ export declare function cutGbzRegion({ base, referenceSamples }: Awaited<ReturnType<typeof openGbz>>, src: Omit<GbzSource, 'db' | 'index'>, signal?: AbortSignal): Promise<{
26
+ text: string;
27
+ region: {
28
+ refName: string;
29
+ start: number;
30
+ end: number;
31
+ };
32
+ sample: string;
33
+ }>;
@@ -0,0 +1,10 @@
1
+ import type { GeneModel } from './genePins.js';
2
+ type Interval = GeneModel['exons'][number];
3
+ export declare function mergedIntervals(intervals: Interval[]): {
4
+ start: number;
5
+ end: number;
6
+ }[];
7
+ export declare function genesFromGff3Lines(lines: Iterable<string>): GeneModel[];
8
+ export declare function genesFromBed(text: string): GeneModel[];
9
+ export declare function genesFromText(text: string): GeneModel[];
10
+ export {};