@jbrowse/bandage-core 6.0.1 → 6.0.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 (162) hide show
  1. package/README.md +23 -7
  2. package/dist/alleleProjection/projectAlleles.js +10 -0
  3. package/dist/anchoredNodes.js +24 -0
  4. package/dist/bubbleSpreads.js +11 -0
  5. package/dist/bubbles/bubbleHalos.js +11 -0
  6. package/dist/bubbles/bubbleLine.js +14 -0
  7. package/dist/bubbles/bubblesFromGraph.js +10 -0
  8. package/dist/bubbles/classifyBubble.js +15 -0
  9. package/dist/bubbles/popBubble.js +9 -0
  10. package/dist/chunks/chunk-2CVHXFK7.js +530 -0
  11. package/dist/chunks/chunk-3S3YVOJ7.js +69 -0
  12. package/dist/chunks/chunk-47DYCZOK.js +115 -0
  13. package/dist/chunks/chunk-4EMPBO7S.js +117 -0
  14. package/dist/chunks/chunk-4S47XRYA.js +149 -0
  15. package/dist/chunks/chunk-5XQDMQXU.js +431 -0
  16. package/dist/chunks/chunk-6JEWNXCQ.js +90 -0
  17. package/dist/chunks/chunk-6SBUFFTB.js +97 -0
  18. package/dist/chunks/chunk-6SXMCK6I.js +476 -0
  19. package/dist/chunks/chunk-72N5DJHZ.js +155 -0
  20. package/dist/chunks/chunk-73RSLGZT.js +73 -0
  21. package/dist/chunks/chunk-7XHHVYG7.js +13 -0
  22. package/dist/chunks/chunk-AB35TJST.js +67 -0
  23. package/dist/chunks/chunk-BPLIXMH7.js +52 -0
  24. package/dist/chunks/chunk-BUBZ32IC.js +101 -0
  25. package/dist/chunks/chunk-BXEPA4KS.js +179 -0
  26. package/dist/chunks/chunk-C44YRP5F.js +85 -0
  27. package/dist/chunks/chunk-CDLPYR5O.js +135 -0
  28. package/dist/chunks/chunk-CJ2EE4AF.js +40 -0
  29. package/dist/chunks/chunk-CPMHA4W5.js +6 -0
  30. package/dist/chunks/chunk-CR7EGAFE.js +241 -0
  31. package/dist/chunks/chunk-CS3E4ETM.js +202 -0
  32. package/dist/chunks/chunk-CTSBC2O6.js +90 -0
  33. package/dist/chunks/chunk-D3M7SBKL.js +210 -0
  34. package/dist/chunks/chunk-DKOB2OPC.js +177 -0
  35. package/dist/chunks/chunk-EJ5OZTCK.js +52 -0
  36. package/dist/chunks/chunk-EK4HGYO7.js +174 -0
  37. package/dist/chunks/chunk-EPZORFTI.js +23 -0
  38. package/dist/chunks/chunk-ES2N6V56.js +83 -0
  39. package/dist/chunks/chunk-EZPBJPK6.js +54 -0
  40. package/dist/chunks/chunk-FYQWPEEY.js +65 -0
  41. package/dist/chunks/chunk-GGQRADFS.js +170 -0
  42. package/dist/chunks/chunk-GOY6REMT.js +43 -0
  43. package/dist/chunks/chunk-GQ2AOHU4.js +112 -0
  44. package/dist/chunks/chunk-HNQPEMYE.js +297 -0
  45. package/dist/chunks/chunk-IGVV37VI.js +60 -0
  46. package/dist/chunks/chunk-IO2PCPZI.js +218 -0
  47. package/dist/chunks/chunk-ISEI2FH3.js +108 -0
  48. package/dist/chunks/chunk-JKJWSY4V.js +32 -0
  49. package/dist/chunks/chunk-KQFOCDFY.js +73 -0
  50. package/dist/chunks/chunk-L3O7AWLI.js +52 -0
  51. package/dist/chunks/chunk-LLJUG2H7.js +6 -0
  52. package/dist/chunks/chunk-LOEA5IHZ.js +71 -0
  53. package/dist/chunks/chunk-LTUWJKHD.js +112 -0
  54. package/dist/chunks/chunk-MFKORG3F.js +44 -0
  55. package/dist/chunks/chunk-MI35EUIE.js +76 -0
  56. package/dist/chunks/chunk-MNUSQCLG.js +29 -0
  57. package/dist/chunks/chunk-MQJUG2D2.js +53 -0
  58. package/dist/chunks/chunk-MREQ7GIA.js +181 -0
  59. package/dist/chunks/chunk-N62KBLFC.js +326 -0
  60. package/dist/chunks/chunk-NNODIW4U.js +26 -0
  61. package/dist/chunks/chunk-PBENCR5L.js +60 -0
  62. package/dist/chunks/chunk-PCZ4PTYC.js +726 -0
  63. package/dist/chunks/chunk-PUG7LXDF.js +70 -0
  64. package/dist/chunks/chunk-QYBZZI5H.js +0 -0
  65. package/dist/chunks/chunk-R6ZUK4Y3.js +232 -0
  66. package/dist/chunks/chunk-RAKOB6IV.js +169 -0
  67. package/dist/chunks/chunk-ROF2R3RF.js +205 -0
  68. package/dist/chunks/chunk-RVS2QCOX.js +135 -0
  69. package/dist/chunks/chunk-ST2IBUAN.js +119 -0
  70. package/dist/chunks/chunk-SZNZ2T6D.js +198 -0
  71. package/dist/chunks/chunk-T43W7NKK.js +122 -0
  72. package/dist/chunks/chunk-TAMCZHLW.js +190 -0
  73. package/dist/chunks/chunk-TDQLINVI.js +16 -0
  74. package/dist/chunks/chunk-TEDQJPMI.js +131 -0
  75. package/dist/chunks/chunk-TZFWUT2C.js +66 -0
  76. package/dist/chunks/chunk-UVBGRJQX.js +50 -0
  77. package/dist/chunks/chunk-VHW7FDHU.js +42 -0
  78. package/dist/chunks/chunk-VZQ4FKLR.js +38 -0
  79. package/dist/chunks/chunk-WFX3MAKA.js +102 -0
  80. package/dist/chunks/chunk-WOO7QYKB.js +121 -0
  81. package/dist/chunks/chunk-WSIFAZU7.js +132 -0
  82. package/dist/chunks/chunk-X5L37W4J.js +82 -0
  83. package/dist/chunks/chunk-Y3IOTZJA.js +61 -0
  84. package/dist/chunks/chunk-YMSSF2RK.js +257 -0
  85. package/dist/cli/figure.js +84 -17
  86. package/dist/colorSchemes.js +10 -0
  87. package/dist/deletionEdges.js +13 -0
  88. package/dist/el.js +8 -0
  89. package/dist/facetGrid.js +16 -0
  90. package/dist/figure.js +51 -0
  91. package/dist/gaf/parseGaf.js +12 -0
  92. package/dist/gbzCut.js +19 -0
  93. package/dist/gbzJoin.js +6 -0
  94. package/dist/gbzWindow.js +28 -0
  95. package/dist/genes/exonOutline.js +11 -0
  96. package/dist/genes/geneFiles.js +14 -0
  97. package/dist/genes/genePins.js +10 -0
  98. package/dist/gfa/gfaConverter.js +11 -0
  99. package/dist/gfa-core/gfaParser.js +8 -0
  100. package/dist/gfa-core/index.js +9 -0
  101. package/dist/graphLabels.js +24 -0
  102. package/dist/index.js +262 -1407
  103. package/dist/labelLayout.js +24 -0
  104. package/dist/layout/anchoredLayout.js +11 -0
  105. package/dist/layout/deletionRoutes.js +10 -0
  106. package/dist/layout/drawnScale.js +22 -0
  107. package/dist/layout/mergeRuns.js +15 -0
  108. package/dist/layout/orderedLayout.js +12 -0
  109. package/dist/layout/orientToReference.js +7 -0
  110. package/dist/layout/placeOffReference.js +9 -0
  111. package/dist/layout/referenceSeeds.js +11 -0
  112. package/dist/layout/rowSpacing.js +6 -0
  113. package/dist/layout/sampleRowLayout.js +11 -0
  114. package/dist/layout/trimToWindow.js +99 -0
  115. package/dist/layout/tubeMapLayout.js +28 -0
  116. package/dist/layout/walkRowDraw.js +65 -0
  117. package/dist/layout/walkRowLayout.js +13 -0
  118. package/dist/layout/walkRows.js +11 -0
  119. package/dist/layout/walkStrip.js +40 -0
  120. package/dist/layoutModes.js +35 -0
  121. package/dist/loadBandage.js +6 -0
  122. package/dist/nodeWidths.js +18 -0
  123. package/dist/overlayLabels.js +18 -0
  124. package/dist/pansn.js +18 -0
  125. package/dist/pathAnchoring.js +18 -0
  126. package/dist/pathColors.js +31 -0
  127. package/dist/pipeline.js +40 -0
  128. package/dist/reference.js +24 -0
  129. package/dist/referenceRampCss.js +29 -0
  130. package/dist/referenceSpan.js +11 -0
  131. package/dist/referenceStrip.js +35 -0
  132. package/dist/renderer/Canvas2DRenderer.js +9 -0
  133. package/dist/renderer/GeometryBuilder.js +42 -0
  134. package/dist/renderer/colorBits.js +8 -0
  135. package/dist/renderer/recordingCanvas.js +44 -0
  136. package/dist/renderer/svgCanvas.js +6 -0
  137. package/dist/renderer/types.js +0 -0
  138. package/dist/tubeMap/axis.js +25 -0
  139. package/dist/tubeMap/coarsen.js +361 -0
  140. package/dist/tubeMap/connectors.js +13 -0
  141. package/dist/tubeMap/deviations.js +85 -0
  142. package/dist/tubeMap/draw.js +15 -0
  143. package/dist/tubeMap/frame.js +9 -0
  144. package/dist/tubeMap/genes.js +20 -0
  145. package/dist/tubeMap/mismatches.js +6 -0
  146. package/dist/tubeMap/nodeColors.js +21 -0
  147. package/dist/tubeMap/reads.js +17 -0
  148. package/dist/tubeMap/warp.js +8 -0
  149. package/dist/types/version.d.ts +1 -1
  150. package/dist/types.js +0 -0
  151. package/dist/util/SpatialIndex.js +13 -0
  152. package/dist/util/edgeCurves.js +10 -0
  153. package/dist/util/geometry.js +39 -0
  154. package/dist/util/hitDetection.js +20 -0
  155. package/dist/util/wheelZoom.js +6 -0
  156. package/dist/version.js +6 -0
  157. package/dist/viewport.js +33 -0
  158. package/dist/walkEncoding.js +39 -0
  159. package/dist/walkHighlight.js +26 -0
  160. package/dist/walkKey.js +17 -0
  161. package/package.json +38 -5
  162. package/dist/chunks/chunk-EXSFRX2F.js +0 -7400
@@ -0,0 +1,73 @@
1
+ // src/tubeMap/warp.ts
2
+ var MAX_GAP_PX = 24;
3
+ var isReal = (c) => c.bp1 > c.bp0;
4
+ function referenceKnots(columns, bpToScreen) {
5
+ const real = columns.filter(isReal);
6
+ if (real.length === 0) {
7
+ const first = columns[0];
8
+ return first ? [{ tx: first.x0, sx: bpToScreen(first.bp0) }] : [];
9
+ }
10
+ const screen = real.map((c) => ({
11
+ c,
12
+ s0: bpToScreen(c.bp0),
13
+ s1: bpToScreen(c.bp1),
14
+ trimLeft: 0,
15
+ trimRight: 0
16
+ }));
17
+ for (let i = 0; i + 1 < screen.length; i++) {
18
+ const left = screen[i];
19
+ const right = screen[i + 1];
20
+ const demand = Math.min(right.c.x0 - left.c.x1, MAX_GAP_PX);
21
+ const short = demand - (right.s0 - left.s1);
22
+ if (short > 0) {
23
+ const capLeft = (left.s1 - left.s0) / 2;
24
+ const capRight = (right.s1 - right.s0) / 2;
25
+ let fromLeft = Math.min(short / 2, capLeft);
26
+ const fromRight = Math.min(short - fromLeft, capRight);
27
+ fromLeft = Math.min(short - fromRight, capLeft);
28
+ left.trimRight = fromLeft;
29
+ right.trimLeft = fromRight;
30
+ }
31
+ }
32
+ const knots = [];
33
+ for (const { c, s0, s1, trimLeft, trimRight } of screen) {
34
+ knots.push(
35
+ { tx: c.x0, sx: s0 + trimLeft },
36
+ { tx: c.x1, sx: s1 - trimRight }
37
+ );
38
+ }
39
+ return knots;
40
+ }
41
+ function warpX(knots, tx) {
42
+ const n = knots.length;
43
+ if (n === 0) {
44
+ return tx;
45
+ }
46
+ const first = knots[0];
47
+ const last = knots[n - 1];
48
+ if (tx <= first.tx) {
49
+ return first.sx + (tx - first.tx);
50
+ }
51
+ if (tx >= last.tx) {
52
+ return last.sx + (tx - last.tx);
53
+ }
54
+ let lo = 0;
55
+ let hi = n - 1;
56
+ while (hi - lo > 1) {
57
+ const mid = lo + hi >> 1;
58
+ if (knots[mid].tx <= tx) {
59
+ lo = mid;
60
+ } else {
61
+ hi = mid;
62
+ }
63
+ }
64
+ const a = knots[lo];
65
+ const b = knots[hi];
66
+ const span = b.tx - a.tx;
67
+ return span > 0 ? a.sx + (tx - a.tx) / span * (b.sx - a.sx) : a.sx;
68
+ }
69
+
70
+ export {
71
+ referenceKnots,
72
+ warpX
73
+ };
@@ -0,0 +1,52 @@
1
+ import {
2
+ placeOffReference
3
+ } from "./chunk-TZFWUT2C.js";
4
+ import {
5
+ ROW_HEIGHT_PX
6
+ } from "./chunk-CPMHA4W5.js";
7
+ import {
8
+ backboneNodes,
9
+ backbonePositions,
10
+ referenceSpan
11
+ } from "./chunk-FYQWPEEY.js";
12
+
13
+ // src/layout/anchoredLayout.ts
14
+ function rankRows(graph) {
15
+ const present = /* @__PURE__ */ new Set();
16
+ for (const node of graph.nodes) {
17
+ if (node.stable) {
18
+ present.add(node.stable.rank);
19
+ }
20
+ }
21
+ return new Map([...present].sort((a, b) => a - b).map((r, i) => [r, i]));
22
+ }
23
+ function anchoredLayout(graph, region) {
24
+ const backbone = backboneNodes(graph);
25
+ if (backbone.length === 0) {
26
+ return void 0;
27
+ }
28
+ const span = referenceSpan(backbone, region);
29
+ const rows = rankRows(graph);
30
+ const nodePositions = backbonePositions(backbone);
31
+ const alleleDeletions = placeOffReference({
32
+ graph,
33
+ span,
34
+ rowY: (node) => (node.stable ? rows.get(node.stable.rank) ?? rows.size : rows.size) * ROW_HEIGHT_PX,
35
+ positions: nodePositions
36
+ });
37
+ const rowLabels = [...rows].map(([rank, row]) => ({
38
+ label: rank === 0 ? "Reference (rank 0)" : `Rank ${rank}`,
39
+ y: row * ROW_HEIGHT_PX
40
+ }));
41
+ return {
42
+ nodePositions,
43
+ rowLabels,
44
+ referenceAxis: true,
45
+ pixelRows: true,
46
+ alleleDeletions
47
+ };
48
+ }
49
+
50
+ export {
51
+ anchoredLayout
52
+ };
@@ -0,0 +1,6 @@
1
+ // src/version.ts
2
+ var version = "6.0.3";
3
+
4
+ export {
5
+ version
6
+ };
@@ -0,0 +1,71 @@
1
+ import {
2
+ placeOffReference
3
+ } from "./chunk-TZFWUT2C.js";
4
+ import {
5
+ parsePanSN
6
+ } from "./chunk-RVS2QCOX.js";
7
+ import {
8
+ ROW_HEIGHT_PX
9
+ } from "./chunk-CPMHA4W5.js";
10
+ import {
11
+ backboneNodes,
12
+ backbonePositions,
13
+ isOffReference,
14
+ referenceSpan
15
+ } from "./chunk-FYQWPEEY.js";
16
+
17
+ // src/layout/sampleRowLayout.ts
18
+ function contributingSamples(graph, keep) {
19
+ const carried = /* @__PURE__ */ new Map();
20
+ for (const node of graph.nodes) {
21
+ if (isOffReference(node)) {
22
+ const { sample } = parsePanSN(node.stable.refName);
23
+ carried.set(sample, (carried.get(sample) ?? 0) + node.length);
24
+ }
25
+ }
26
+ const held = new Map(keep.map((sample, row) => [sample, row]));
27
+ return [...carried.keys()].sort(
28
+ (a, b) => (held.get(a) ?? Infinity) - (held.get(b) ?? Infinity) || carried.get(b) - carried.get(a) || a.localeCompare(b)
29
+ );
30
+ }
31
+ function sampleRowLayout(graph, region, keep = []) {
32
+ const backbone = backboneNodes(graph);
33
+ const samples = contributingSamples(graph, keep);
34
+ if (backbone.length === 0 || samples.length === 0) {
35
+ return void 0;
36
+ }
37
+ const span = referenceSpan(backbone, region);
38
+ const rowOf = new Map(samples.map((s, i) => [s, i + 1]));
39
+ const nodePositions = backbonePositions(backbone);
40
+ const spareRow = samples.length + 1;
41
+ const alleleDeletions = placeOffReference({
42
+ graph,
43
+ span,
44
+ rowY: (node) => {
45
+ const stable = node.stable;
46
+ const row = stable ? rowOf.get(parsePanSN(stable.refName).sample) : void 0;
47
+ return (row ?? spareRow) * ROW_HEIGHT_PX;
48
+ },
49
+ positions: nodePositions
50
+ });
51
+ const referenceSample = parsePanSN(backbone[0].stable.refName).sample;
52
+ const rowLabels = [
53
+ { label: referenceSample, y: 0 },
54
+ ...samples.map((sample) => ({
55
+ label: sample,
56
+ y: rowOf.get(sample) * ROW_HEIGHT_PX
57
+ }))
58
+ ];
59
+ return {
60
+ nodePositions,
61
+ rowLabels,
62
+ sampleRows: samples,
63
+ referenceAxis: true,
64
+ pixelRows: true,
65
+ alleleDeletions
66
+ };
67
+ }
68
+
69
+ export {
70
+ sampleRowLayout
71
+ };
@@ -0,0 +1,112 @@
1
+ import {
2
+ joinCuts
3
+ } from "./chunk-WSIFAZU7.js";
4
+ import {
5
+ wellKnownSample
6
+ } from "./chunk-RAKOB6IV.js";
7
+ import {
8
+ panSNMatchesPrefix,
9
+ panSNSample
10
+ } from "./chunk-BPLIXMH7.js";
11
+
12
+ // src/gbzWindow.ts
13
+ var NoReferenceSampleError = class extends Error {
14
+ constructor(anchor, referenceSamples) {
15
+ super(
16
+ referenceSamples.length === 0 ? `the graph names no reference sample (gbwt_reference_samples) and the anchor "${anchor}" maps to none; set referenceSample` : `the anchor "${anchor}" is none of the graph's reference samples (${referenceSamples.join(", ")}); set referenceSample or map it through assemblyNameToPanSN`
17
+ );
18
+ this.name = "NoReferenceSampleError";
19
+ }
20
+ };
21
+ var NodeLimitError = class extends Error {
22
+ constructor(limit, windowBp, fitsBp) {
23
+ super(
24
+ `this ${windowBp.toLocaleString()} bp window reads more than nodeLimit (${limit.toLocaleString()}) graph nodes; zoom in to about ${fitsBp.toLocaleString()} bp or raise nodeLimit`
25
+ );
26
+ this.fitsBp = fitsBp;
27
+ this.name = "NodeLimitError";
28
+ this.regionTooLarge = true;
29
+ }
30
+ };
31
+ function haplotypePrefix(name) {
32
+ return `${name.sample}#${name.haplotype}`;
33
+ }
34
+ function haplotypeWanted(name, wanted) {
35
+ const prefix = haplotypePrefix(name);
36
+ return wanted === void 0 || wanted.some((candidate) => panSNMatchesPrefix(prefix, candidate));
37
+ }
38
+ async function referenceSamplesOf(db) {
39
+ return (await db.tag("gbwt_reference_samples") ?? "").split(/\s+/).filter((sample) => sample !== "");
40
+ }
41
+ function aliasedSample(anchorSample, referenceSamples) {
42
+ const lower = anchorSample.toLowerCase();
43
+ const alias = wellKnownSample(anchorSample)?.toLowerCase();
44
+ return referenceSamples.find((s) => s === anchorSample) ?? referenceSamples.find((s) => s.toLowerCase() === lower) ?? referenceSamples.find((s) => s.toLowerCase() === alias);
45
+ }
46
+ function resolveReferenceSample({
47
+ configured,
48
+ anchorPrefix,
49
+ referenceSamples
50
+ }) {
51
+ if (configured !== "") {
52
+ return configured;
53
+ }
54
+ const sample = aliasedSample(panSNSample(anchorPrefix), referenceSamples) ?? (referenceSamples.length === 1 ? referenceSamples[0] : void 0);
55
+ if (sample === void 0) {
56
+ throw new NoReferenceSampleError(anchorPrefix, referenceSamples);
57
+ }
58
+ return sample;
59
+ }
60
+ async function referencePathQuery(db, referenceSample, refName) {
61
+ const path = (await db.paths()).find(
62
+ (p) => p.isIndexed && p.name.sample === referenceSample && p.name.contig === refName
63
+ );
64
+ return path ? {
65
+ sample: path.name.sample,
66
+ contig: refName,
67
+ haplotype: path.name.haplotype
68
+ } : void 0;
69
+ }
70
+ function nodeLimitError(error, limit, windowBp) {
71
+ const isLimit = error instanceof Error && (error.name === "SubgraphLimitError" || /^Subgraph size limit of \d+ nodes exceeded/.test(error.message));
72
+ if (!isLimit) {
73
+ return void 0;
74
+ } else {
75
+ const walked = error.walkedBp;
76
+ const fits = typeof walked === "number" && walked > 0 ? Math.floor(walked * 0.8) : Math.floor(windowBp / 2);
77
+ return new NodeLimitError(limit, windowBp, Math.max(fits, 1));
78
+ }
79
+ }
80
+ var GBZ_CUT_DEFAULTS = {
81
+ context: 1e3,
82
+ snarls: "contained",
83
+ limit: 1e5
84
+ };
85
+ async function cutWindowGFA(db, query, start, end, opts) {
86
+ if (!query) {
87
+ return "";
88
+ }
89
+ const subgraphs = await db.getSubgraphs({ ...opts, path: query, start, end, haplotypes: "all" }).catch((error) => {
90
+ throw nodeLimitError(error, opts.limit, end - start) ?? error;
91
+ });
92
+ const paths = await db.paths();
93
+ return joinCuts(
94
+ await Promise.all(subgraphs.map((subgraph) => subgraph.toGFA())),
95
+ (sample, haplotype, contig, at) => paths.some(
96
+ ({ name }) => name.sample === sample && name.haplotype === haplotype && name.contig === contig && name.fragment === at
97
+ )
98
+ );
99
+ }
100
+
101
+ export {
102
+ NoReferenceSampleError,
103
+ NodeLimitError,
104
+ haplotypePrefix,
105
+ haplotypeWanted,
106
+ referenceSamplesOf,
107
+ resolveReferenceSample,
108
+ referencePathQuery,
109
+ nodeLimitError,
110
+ GBZ_CUT_DEFAULTS,
111
+ cutWindowGFA
112
+ };
@@ -0,0 +1,44 @@
1
+ // src/bubbles/bubbleLine.ts
2
+ function sequence(field) {
3
+ return field === void 0 || field === "*" ? void 0 : field;
4
+ }
5
+ function parseBubbleLine(line) {
6
+ const cols = line.split(" ");
7
+ return {
8
+ refName: cols[0],
9
+ start: +cols[1],
10
+ end: +cols[2],
11
+ segmentCount: +cols[3],
12
+ pathCount: +cols[4],
13
+ inversion: cols[5] === "1",
14
+ shortestAlleleLength: +cols[6],
15
+ longestAlleleLength: +cols[7],
16
+ segments: cols[11],
17
+ shortestAllele: sequence(cols[12]),
18
+ longestAllele: sequence(cols[13])
19
+ };
20
+ }
21
+ function sameBubble(a, b) {
22
+ return a.refName === b.refName && a.start === b.start && a.end === b.end;
23
+ }
24
+ function bubbleLabel(bubble) {
25
+ const { shortestAlleleLength: min, longestAlleleLength: max } = bubble;
26
+ return min === max ? `${max.toLocaleString()} bp` : `${min.toLocaleString()}-${max.toLocaleString()} bp`;
27
+ }
28
+ var SATURATED_PATH_COUNT = 2147483647;
29
+ function bubbleDescription(bubble) {
30
+ const { pathCount, segmentCount, inversion } = bubble;
31
+ return [
32
+ `${segmentCount} segments`,
33
+ pathCount === SATURATED_PATH_COUNT ? "more paths than gfatools counts" : `up to ${pathCount.toLocaleString()} paths`,
34
+ ...inversion ? ["inversion"] : []
35
+ ].join(", ");
36
+ }
37
+
38
+ export {
39
+ parseBubbleLine,
40
+ sameBubble,
41
+ bubbleLabel,
42
+ SATURATED_PATH_COUNT,
43
+ bubbleDescription
44
+ };
@@ -0,0 +1,76 @@
1
+ // src/layout/deletionRoutes.ts
2
+ var ROUTE_ID = "\0deletion:";
3
+ var ROUTE_FRACTION = 0.5;
4
+ function withDeletionRoutes(graph, deletions) {
5
+ const routes = new Map(
6
+ deletions.map((d) => [d.edgeIndex, `${ROUTE_ID}${d.edgeIndex}`])
7
+ );
8
+ const edges = [];
9
+ graph.edges.forEach((edge, ei) => {
10
+ const id = routes.get(ei);
11
+ if (id === void 0) {
12
+ edges.push(edge);
13
+ } else {
14
+ const { fromStrand, toStrand } = edge;
15
+ edges.push(
16
+ { from: edge.from, to: id, ...fromStrand ? { fromStrand } : {} },
17
+ { from: id, to: edge.to, ...toStrand ? { toStrand } : {} }
18
+ );
19
+ }
20
+ });
21
+ return {
22
+ graph: {
23
+ ...graph,
24
+ nodes: [
25
+ ...graph.nodes,
26
+ ...[...routes.values()].map((id) => ({
27
+ id,
28
+ name: id,
29
+ length: 0,
30
+ depth: 0
31
+ }))
32
+ ],
33
+ edges
34
+ },
35
+ routes,
36
+ ids: new Set(routes.values())
37
+ };
38
+ }
39
+ function routeNodes(graph, deletions, routes, drawnOf, opts) {
40
+ const lengths = new Map(graph.nodes.map((n) => [n.id, n.length]));
41
+ return deletions.map((d) => {
42
+ const skipped = d.bypassed.reduce(
43
+ (sum, id2) => sum + (lengths.get(id2) ?? 0),
44
+ 0
45
+ );
46
+ const drawn = Math.max(
47
+ opts.minimumNodeLength,
48
+ drawnOf(skipped) * ROUTE_FRACTION
49
+ );
50
+ const id = routes.get(d.edgeIndex);
51
+ return {
52
+ id,
53
+ name: id,
54
+ length: Math.round(drawn * 1e6 / opts.nodeLengthPerMegabase),
55
+ depth: 0
56
+ };
57
+ });
58
+ }
59
+ function takeRoutes(positions, routes) {
60
+ const nodePositions = { ...positions };
61
+ const deletionRoutes = {};
62
+ for (const [edgeIndex, id] of routes) {
63
+ const route = nodePositions[id];
64
+ delete nodePositions[id];
65
+ if (route?.length) {
66
+ deletionRoutes[edgeIndex] = route;
67
+ }
68
+ }
69
+ return { nodePositions, deletionRoutes };
70
+ }
71
+
72
+ export {
73
+ withDeletionRoutes,
74
+ routeNodes,
75
+ takeRoutes
76
+ };
@@ -0,0 +1,29 @@
1
+ // src/renderer/colorBits.ts
2
+ import {
3
+ abgrAlpha,
4
+ abgrBlue,
5
+ abgrGreen,
6
+ abgrRed,
7
+ packAbgr
8
+ } from "@jbrowse/core/util/colorBits";
9
+ function fadeAbgr(c, alpha) {
10
+ return packAbgr(
11
+ abgrRed(c),
12
+ abgrGreen(c),
13
+ abgrBlue(c),
14
+ Math.round(abgrAlpha(c) * alpha)
15
+ );
16
+ }
17
+ function brightenAbgr(c, factor) {
18
+ return packAbgr(
19
+ Math.min(255, Math.round(abgrRed(c) * factor)),
20
+ Math.min(255, Math.round(abgrGreen(c) * factor)),
21
+ Math.min(255, Math.round(abgrBlue(c) * factor)),
22
+ abgrAlpha(c)
23
+ );
24
+ }
25
+
26
+ export {
27
+ fadeAbgr,
28
+ brightenAbgr
29
+ };
@@ -0,0 +1,53 @@
1
+ import {
2
+ clampZoom
3
+ } from "./chunk-IO2PCPZI.js";
4
+
5
+ // src/viewport.ts
6
+ function axisScaleOf(scale, pixelRows) {
7
+ return { scaleX: scale, scaleY: pixelRows ? 1 : scale, pixelRows };
8
+ }
9
+ function viewportOf(t, axis, width, height) {
10
+ return {
11
+ minX: -t.translateX / axis.scaleX,
12
+ minY: -t.translateY / axis.scaleY,
13
+ maxX: (width - t.translateX) / axis.scaleX,
14
+ maxY: (height - t.translateY) / axis.scaleY
15
+ };
16
+ }
17
+ function padded(v, panes) {
18
+ const w = (v.maxX - v.minX) * panes;
19
+ const h = (v.maxY - v.minY) * panes;
20
+ return {
21
+ minX: v.minX - w,
22
+ minY: v.minY - h,
23
+ maxX: v.maxX + w,
24
+ maxY: v.maxY + h
25
+ };
26
+ }
27
+ function contains(outer, inner) {
28
+ return inner.minX >= outer.minX && inner.maxX <= outer.maxX && inner.minY >= outer.minY && inner.maxY <= outer.maxY;
29
+ }
30
+ function zoomAbout(t, factor, centerX, centerY, pixelRows) {
31
+ const scale = clampZoom(t.scale * factor);
32
+ const ratio = scale / t.scale;
33
+ return {
34
+ scale,
35
+ translateX: centerX - (centerX - t.translateX) * ratio,
36
+ translateY: pixelRows ? t.translateY : centerY - (centerY - t.translateY) * ratio
37
+ };
38
+ }
39
+ function screenToLayout(x, y, t, axis) {
40
+ return {
41
+ x: (x - t.translateX) / axis.scaleX,
42
+ y: (y - t.translateY) / axis.scaleY
43
+ };
44
+ }
45
+
46
+ export {
47
+ axisScaleOf,
48
+ viewportOf,
49
+ padded,
50
+ contains,
51
+ zoomAbout,
52
+ screenToLayout
53
+ };
@@ -0,0 +1,181 @@
1
+ import {
2
+ baseEdgeCurves
3
+ } from "./chunk-Y3IOTZJA.js";
4
+ import {
5
+ curveBounds,
6
+ pathRibbonOffsets
7
+ } from "./chunk-2CVHXFK7.js";
8
+
9
+ // src/util/SpatialIndex.ts
10
+ var FALLBACK_CELL_SIZE = 50;
11
+ function meanExtentCellSize(extentTotal, count) {
12
+ return count > 0 ? Math.max(1, extentTotal / count) : FALLBACK_CELL_SIZE;
13
+ }
14
+ function rowPitchOf(boxes) {
15
+ const distinct = /* @__PURE__ */ new Set();
16
+ let min = Infinity;
17
+ let max = -Infinity;
18
+ for (const box of boxes) {
19
+ distinct.add(box.minY);
20
+ min = Math.min(min, box.minY);
21
+ max = Math.max(max, box.minY);
22
+ }
23
+ return distinct.size > 1 ? (max - min) / (distinct.size - 1) : void 0;
24
+ }
25
+ function cellSizeFrom(boxes, extentX, extentY) {
26
+ const x = meanExtentCellSize(extentX, boxes.length);
27
+ return {
28
+ x,
29
+ y: extentY > 0 ? meanExtentCellSize(extentY, boxes.length) : rowPitchOf(boxes) ?? x
30
+ };
31
+ }
32
+ function resolveCellSize(given, boxes, extentX, extentY) {
33
+ return given === void 0 ? cellSizeFrom(boxes, extentX, extentY) : typeof given === "number" ? { x: given, y: given } : given;
34
+ }
35
+ function getOrCreateCell(cells, cx, cy) {
36
+ let row = cells.get(cx);
37
+ if (!row) {
38
+ row = /* @__PURE__ */ new Map();
39
+ cells.set(cx, row);
40
+ }
41
+ let cell = row.get(cy);
42
+ if (!cell) {
43
+ cell = [];
44
+ row.set(cy, cell);
45
+ }
46
+ return cell;
47
+ }
48
+ function addToGrid(cells, cellSize, minX, minY, maxX, maxY, entry) {
49
+ const cx0 = Math.floor(minX / cellSize.x);
50
+ const cx1 = Math.floor(maxX / cellSize.x);
51
+ const cy0 = Math.floor(minY / cellSize.y);
52
+ const cy1 = Math.floor(maxY / cellSize.y);
53
+ for (let cx = cx0; cx <= cx1; cx++) {
54
+ for (let cy = cy0; cy <= cy1; cy++) {
55
+ getOrCreateCell(cells, cx, cy).push(entry);
56
+ }
57
+ }
58
+ }
59
+ function queryGrid(cells, cellSize, x, y, radiusX, radiusY) {
60
+ const cx0 = Math.floor((x - radiusX) / cellSize.x);
61
+ const cx1 = Math.floor((x + radiusX) / cellSize.x);
62
+ const cy0 = Math.floor((y - radiusY) / cellSize.y);
63
+ const cy1 = Math.floor((y + radiusY) / cellSize.y);
64
+ const results = [];
65
+ const seen = /* @__PURE__ */ new Set();
66
+ for (let cx = cx0; cx <= cx1; cx++) {
67
+ const row = cells.get(cx);
68
+ if (row) {
69
+ for (let cy = cy0; cy <= cy1; cy++) {
70
+ const cell = row.get(cy);
71
+ if (cell) {
72
+ for (const entry of cell) {
73
+ if (!seen.has(entry)) {
74
+ seen.add(entry);
75
+ results.push(entry);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ }
82
+ return results;
83
+ }
84
+ var SpatialIndex = class {
85
+ constructor(nodePositions, cellSize) {
86
+ this.cells = /* @__PURE__ */ new Map();
87
+ const boxes = [];
88
+ let extentX = 0;
89
+ let extentY = 0;
90
+ for (const [nodeId, segments] of Object.entries(nodePositions)) {
91
+ for (let i = 0; i < segments.length - 1; i++) {
92
+ const seg = segments[i];
93
+ const next = segments[i + 1];
94
+ const minX = Math.min(seg.x, next.x);
95
+ const minY = Math.min(seg.y, next.y);
96
+ const maxX = Math.max(seg.x, next.x);
97
+ const maxY = Math.max(seg.y, next.y);
98
+ extentX += maxX - minX;
99
+ extentY += maxY - minY;
100
+ boxes.push({ entry: { nodeId, segmentIdx: i }, minX, minY, maxX, maxY });
101
+ }
102
+ }
103
+ this.cellSize = resolveCellSize(cellSize, boxes, extentX, extentY);
104
+ for (const b of boxes) {
105
+ addToGrid(
106
+ this.cells,
107
+ this.cellSize,
108
+ b.minX,
109
+ b.minY,
110
+ b.maxX,
111
+ b.maxY,
112
+ b.entry
113
+ );
114
+ }
115
+ }
116
+ query(x, y, radiusX, radiusY = radiusX) {
117
+ return queryGrid(this.cells, this.cellSize, x, y, radiusX, radiusY);
118
+ }
119
+ };
120
+ var EdgeSpatialIndex = class {
121
+ constructor(nodePositions, graph, drawPaths, axis, cellSize, deletions, version = 0, routes, stranded = false) {
122
+ this.cells = /* @__PURE__ */ new Map();
123
+ this.edgeCurves = baseEdgeCurves(
124
+ nodePositions,
125
+ graph,
126
+ axis,
127
+ deletions,
128
+ version,
129
+ routes,
130
+ stranded
131
+ );
132
+ const boxes = [];
133
+ let extentX = 0;
134
+ let extentY = 0;
135
+ for (let ei = 0; ei < graph.edges.length; ei++) {
136
+ const edge = graph.edges[ei];
137
+ const fromSegments = nodePositions[edge.from];
138
+ const toSegments = nodePositions[edge.to];
139
+ const curves = this.edgeCurves.get(ei);
140
+ if (fromSegments?.length && toSegments?.length && curves) {
141
+ let { minX, minY, maxX, maxY } = curveBounds(curves);
142
+ const numPaths = edge.pathIds?.length ?? 0;
143
+ if (drawPaths && numPaths > 0) {
144
+ let padX = 0;
145
+ let padY = 0;
146
+ for (const o of pathRibbonOffsets(
147
+ fromSegments,
148
+ toSegments,
149
+ numPaths,
150
+ axis
151
+ )) {
152
+ padX = Math.max(padX, Math.abs(o.x));
153
+ padY = Math.max(padY, Math.abs(o.y));
154
+ }
155
+ minX -= padX;
156
+ minY -= padY;
157
+ maxX += padX;
158
+ maxY += padY;
159
+ }
160
+ extentX += maxX - minX;
161
+ extentY += maxY - minY;
162
+ boxes.push({ ei, minX, minY, maxX, maxY });
163
+ }
164
+ }
165
+ this.cellSize = resolveCellSize(cellSize, boxes, extentX, extentY);
166
+ for (const b of boxes) {
167
+ addToGrid(this.cells, this.cellSize, b.minX, b.minY, b.maxX, b.maxY, b.ei);
168
+ }
169
+ }
170
+ getCurves(ei) {
171
+ return this.edgeCurves.get(ei);
172
+ }
173
+ query(x, y, radiusX, radiusY = radiusX) {
174
+ return queryGrid(this.cells, this.cellSize, x, y, radiusX, radiusY);
175
+ }
176
+ };
177
+
178
+ export {
179
+ SpatialIndex,
180
+ EdgeSpatialIndex
181
+ };