@jbrowse/bandage-core 6.0.1 → 6.0.2

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-3C2LGJKY.js +108 -0
  11. package/dist/chunks/chunk-3PLYZLYV.js +513 -0
  12. package/dist/chunks/chunk-3S3YVOJ7.js +69 -0
  13. package/dist/chunks/chunk-3WHKR5TY.js +726 -0
  14. package/dist/chunks/chunk-47DYCZOK.js +115 -0
  15. package/dist/chunks/chunk-4S47XRYA.js +149 -0
  16. package/dist/chunks/chunk-527AI7CP.js +122 -0
  17. package/dist/chunks/chunk-57ZIXHZA.js +90 -0
  18. package/dist/chunks/chunk-5QT6NPSO.js +40 -0
  19. package/dist/chunks/chunk-6JEWNXCQ.js +90 -0
  20. package/dist/chunks/chunk-6Q6HFBJT.js +170 -0
  21. package/dist/chunks/chunk-6SBUFFTB.js +97 -0
  22. package/dist/chunks/chunk-6YRRNX2P.js +61 -0
  23. package/dist/chunks/chunk-72N5DJHZ.js +155 -0
  24. package/dist/chunks/chunk-73RSLGZT.js +73 -0
  25. package/dist/chunks/chunk-7CHJKABZ.js +82 -0
  26. package/dist/chunks/chunk-7XHHVYG7.js +13 -0
  27. package/dist/chunks/chunk-AB35TJST.js +67 -0
  28. package/dist/chunks/chunk-AE3UQZY3.js +43 -0
  29. package/dist/chunks/chunk-BJV2W4KZ.js +257 -0
  30. package/dist/chunks/chunk-BPLIXMH7.js +52 -0
  31. package/dist/chunks/chunk-BXEPA4KS.js +179 -0
  32. package/dist/chunks/chunk-C44YRP5F.js +85 -0
  33. package/dist/chunks/chunk-CDLPYR5O.js +135 -0
  34. package/dist/chunks/chunk-CPMHA4W5.js +6 -0
  35. package/dist/chunks/chunk-CR7EGAFE.js +241 -0
  36. package/dist/chunks/chunk-CZ54VG2H.js +431 -0
  37. package/dist/chunks/chunk-D3M7SBKL.js +210 -0
  38. package/dist/chunks/chunk-EJ5OZTCK.js +52 -0
  39. package/dist/chunks/chunk-ES2N6V56.js +83 -0
  40. package/dist/chunks/chunk-EZPBJPK6.js +54 -0
  41. package/dist/chunks/chunk-FYQWPEEY.js +65 -0
  42. package/dist/chunks/chunk-GQ2AOHU4.js +112 -0
  43. package/dist/chunks/chunk-HB6PDCOU.js +177 -0
  44. package/dist/chunks/chunk-HCANBJDD.js +326 -0
  45. package/dist/chunks/chunk-HIJVRRYE.js +174 -0
  46. package/dist/chunks/chunk-HNQPEMYE.js +297 -0
  47. package/dist/chunks/chunk-IGVV37VI.js +60 -0
  48. package/dist/chunks/chunk-IMW3AK27.js +102 -0
  49. package/dist/chunks/chunk-JKJWSY4V.js +32 -0
  50. package/dist/chunks/chunk-KCW7L3NV.js +6 -0
  51. package/dist/chunks/chunk-KQFOCDFY.js +73 -0
  52. package/dist/chunks/chunk-L3O7AWLI.js +52 -0
  53. package/dist/chunks/chunk-L5RYUPZI.js +53 -0
  54. package/dist/chunks/chunk-LOEA5IHZ.js +71 -0
  55. package/dist/chunks/chunk-LTUWJKHD.js +112 -0
  56. package/dist/chunks/chunk-LVZZH2NI.js +181 -0
  57. package/dist/chunks/chunk-MFKORG3F.js +44 -0
  58. package/dist/chunks/chunk-MHGHYHTL.js +205 -0
  59. package/dist/chunks/chunk-MI35EUIE.js +76 -0
  60. package/dist/chunks/chunk-MNUSQCLG.js +29 -0
  61. package/dist/chunks/chunk-NNODIW4U.js +26 -0
  62. package/dist/chunks/chunk-P7B3GDAY.js +232 -0
  63. package/dist/chunks/chunk-PBENCR5L.js +60 -0
  64. package/dist/chunks/chunk-PUG7LXDF.js +70 -0
  65. package/dist/chunks/chunk-Q3KCTA4N.js +202 -0
  66. package/dist/chunks/chunk-QCYM44UL.js +476 -0
  67. package/dist/chunks/chunk-QYBZZI5H.js +0 -0
  68. package/dist/chunks/chunk-RAKOB6IV.js +169 -0
  69. package/dist/chunks/chunk-RVS2QCOX.js +135 -0
  70. package/dist/chunks/chunk-SDGM243E.js +190 -0
  71. package/dist/chunks/chunk-ST2IBUAN.js +119 -0
  72. package/dist/chunks/chunk-SV27AJCC.js +101 -0
  73. package/dist/chunks/chunk-SZNZ2T6D.js +198 -0
  74. package/dist/chunks/chunk-TDQLINVI.js +16 -0
  75. package/dist/chunks/chunk-TEDQJPMI.js +131 -0
  76. package/dist/chunks/chunk-TZFWUT2C.js +66 -0
  77. package/dist/chunks/chunk-UVBGRJQX.js +50 -0
  78. package/dist/chunks/chunk-VHW7FDHU.js +42 -0
  79. package/dist/chunks/chunk-VKB57ZYE.js +218 -0
  80. package/dist/chunks/chunk-VZQ4FKLR.js +38 -0
  81. package/dist/chunks/chunk-WOO7QYKB.js +121 -0
  82. package/dist/chunks/chunk-WSIFAZU7.js +132 -0
  83. package/dist/chunks/chunk-X32PABB7.js +117 -0
  84. package/dist/chunks/chunk-YJQ7CT7F.js +23 -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,170 @@
1
+ import {
2
+ encodedColor,
3
+ resolveEncoding
4
+ } from "./chunk-IMW3AK27.js";
5
+ import {
6
+ pathOrigin
7
+ } from "./chunk-ST2IBUAN.js";
8
+ import {
9
+ panSNContig
10
+ } from "./chunk-BPLIXMH7.js";
11
+
12
+ // src/walkHighlight.ts
13
+ var isReference = (graph, name) => !!graph.referencePath && pathOrigin(name).name === graph.referencePath;
14
+ function piecesOf(graph, name) {
15
+ return (graph.paths ?? []).filter((p) => p.name === name).sort((a, b) => (a.start ?? 0) - (b.start ?? 0));
16
+ }
17
+ function walkHighlight(graph, name) {
18
+ const pieces = piecesOf(graph, name);
19
+ const first = pieces[0];
20
+ if (!first) {
21
+ return void 0;
22
+ }
23
+ const byId = new Map(graph.nodes.map((n) => [n.id, n]));
24
+ const edgeAt = /* @__PURE__ */ new Map();
25
+ graph.edges.forEach((e, i) => {
26
+ edgeAt.set(`${e.from}>${e.to}`, i);
27
+ });
28
+ const lengthOf = (id) => byId.get(id)?.length ?? 0;
29
+ const bpOf = (path) => path.nodeIds.reduce((sum, id) => sum + lengthOf(id), 0);
30
+ const bp = pieces.reduce((sum, piece) => sum + bpOf(piece), 0);
31
+ const range = first.start === void 0 ? void 0 : {
32
+ contig: first.contig ?? panSNContig(pathOrigin(name).name),
33
+ start: first.start,
34
+ end: Math.max(...pieces.map((p) => (p.start ?? 0) + bpOf(p)))
35
+ };
36
+ const span = range ? range.end - range.start : bp;
37
+ const nodeIds = /* @__PURE__ */ new Set();
38
+ const edgeIndexes = /* @__PURE__ */ new Set();
39
+ const progress = /* @__PURE__ */ new Map();
40
+ let before = 0;
41
+ for (const piece of pieces) {
42
+ if (range) {
43
+ before = Math.max(before, (piece.start ?? 0) - range.start);
44
+ }
45
+ piece.nodeIds.forEach((id, i) => {
46
+ nodeIds.add(id);
47
+ if (i > 0) {
48
+ const a = piece.nodeIds[i - 1];
49
+ const index = edgeAt.get(`${a}>${id}`) ?? edgeAt.get(`${id}>${a}`);
50
+ if (index !== void 0) {
51
+ edgeIndexes.add(index);
52
+ }
53
+ }
54
+ const length = lengthOf(id);
55
+ if (!progress.has(id)) {
56
+ progress.set(id, span > 0 ? (before + length / 2) / span : 0);
57
+ }
58
+ before += length;
59
+ });
60
+ }
61
+ const reference = isReference(graph, name);
62
+ const referencePieces = reference ? [] : (graph.paths ?? []).filter((p) => isReference(graph, p.name));
63
+ return {
64
+ name,
65
+ reference,
66
+ range,
67
+ nodeIds,
68
+ edgeIndexes,
69
+ progress,
70
+ steps: pieces.reduce((sum, piece) => sum + piece.nodeIds.length, 0),
71
+ bp,
72
+ referenceBp: referencePieces.length > 0 ? referencePieces.reduce((sum, piece) => sum + bpOf(piece), 0) : void 0
73
+ };
74
+ }
75
+ function laneColors(graph, walk, encoding, ramp) {
76
+ const byId = new Map(graph.nodes.map((n) => [n.id, n]));
77
+ const colors = /* @__PURE__ */ new Map();
78
+ for (const [id, progress] of walk.progress) {
79
+ const node = byId.get(id);
80
+ const mid = ramp?.midpoints.get(id);
81
+ const t = encoding.field === "progress" ? progress : ramp && mid !== void 0 && !(node?.stable && node.stable.rank > 0) ? (mid - ramp.start) / ramp.span : void 0;
82
+ colors.set(id, encodedColor(encoding, t));
83
+ }
84
+ return colors;
85
+ }
86
+ function reversedNodes(graph, walk) {
87
+ const reversed = /* @__PURE__ */ new Set();
88
+ let bp = 0;
89
+ const referencePath = graph.referencePath;
90
+ if (!referencePath || walk.reference) {
91
+ return { reversed, bp };
92
+ }
93
+ const walkPath = pathOrigin(walk.name).name;
94
+ const byId = new Map(graph.nodes.map((n) => [n.id, n]));
95
+ for (const id of walk.progress.keys()) {
96
+ const node = byId.get(id);
97
+ const visits = node ? graph.pathVisits?.get(node.name) : void 0;
98
+ const own = visits?.find((v) => v.path === walkPath)?.strand;
99
+ const theirs = visits?.find((v) => v.path === referencePath)?.strand;
100
+ if (own && theirs && own !== theirs) {
101
+ reversed.add(id);
102
+ bp += node.length;
103
+ }
104
+ }
105
+ return { reversed, bp };
106
+ }
107
+ function walkLift(graph, layers, ramp) {
108
+ const seen = /* @__PURE__ */ new Set();
109
+ const lifted = layers.filter((layer) => !seen.has(layer.walk) && seen.add(layer.walk)).flatMap((layer) => {
110
+ const walk = walkHighlight(graph, layer.walk);
111
+ return walk ? [{ walk, layer }] : [];
112
+ }).sort((a, b) => Number(b.walk.reference) - Number(a.walk.reference));
113
+ if (lifted.length === 0) {
114
+ return void 0;
115
+ }
116
+ let picked = 0;
117
+ const walks = lifted.map(({ walk, layer }) => {
118
+ const encoding = resolveEncoding(
119
+ layer,
120
+ walk.reference,
121
+ walk.reference ? 0 : picked++,
122
+ lifted.length === 1
123
+ );
124
+ const { reversed, bp } = reversedNodes(graph, walk);
125
+ return {
126
+ ...walk,
127
+ encoding,
128
+ colors: laneColors(graph, walk, encoding, ramp),
129
+ reversed,
130
+ reversedBp: bp
131
+ };
132
+ });
133
+ return liftOf(walks, ramp);
134
+ }
135
+ var FACET_COLOR = { field: "progress", scheme: "red" };
136
+ function facetLifts(graph, lift, layers, ramp) {
137
+ return lift.walks.map((walk) => {
138
+ const stated = layers.find((l) => l.walk === walk.name)?.color;
139
+ const encoding = resolveEncoding(
140
+ { walk: walk.name, color: { ...FACET_COLOR, ...stated } },
141
+ walk.reference,
142
+ 0
143
+ );
144
+ return liftOf(
145
+ [
146
+ {
147
+ ...walk,
148
+ encoding,
149
+ colors: laneColors(graph, walk, encoding, ramp)
150
+ }
151
+ ],
152
+ ramp
153
+ );
154
+ });
155
+ }
156
+ function liftOf(walks, ramp) {
157
+ return {
158
+ walks,
159
+ referenceDomain: ramp ? { start: ramp.start, end: ramp.start + ramp.span } : void 0,
160
+ nodeIds: new Set(walks.flatMap((w) => [...w.nodeIds])),
161
+ edgeIndexes: new Set(walks.flatMap((w) => [...w.edgeIndexes])),
162
+ names: new Set(walks.map((w) => w.name))
163
+ };
164
+ }
165
+
166
+ export {
167
+ walkHighlight,
168
+ walkLift,
169
+ facetLifts
170
+ };
@@ -0,0 +1,97 @@
1
+ // src/facetGrid.ts
2
+ var FACET_GAP_PX = 8;
3
+ var FACET_TITLE_PX = 34;
4
+ var FACET_PAD_PX = 12;
5
+ var MIN_FACET_PANEL_PX = 60;
6
+ function facetGrid({
7
+ count,
8
+ bounds,
9
+ pixelRows,
10
+ width,
11
+ room,
12
+ columns
13
+ }) {
14
+ function tile(across) {
15
+ const rows = Math.ceil(count / across);
16
+ const panelWidth = Math.floor(
17
+ (width - (across - 1) * FACET_GAP_PX) / across
18
+ );
19
+ const panelRoom = (room - rows * FACET_TITLE_PX - (rows - 1) * FACET_GAP_PX) / rows;
20
+ const fitX = (panelWidth - 2 * FACET_PAD_PX) / bounds.w;
21
+ const fitY = bounds.h > 0 ? (panelRoom - 2 * FACET_PAD_PX) / bounds.h : Infinity;
22
+ const scale = pixelRows ? fitX : Math.min(fitX, fitY);
23
+ const drawn = pixelRows ? bounds.h : bounds.h * scale;
24
+ const height = Math.floor(
25
+ Math.max(
26
+ MIN_FACET_PANEL_PX,
27
+ Math.min(drawn + 2 * FACET_PAD_PX, panelRoom)
28
+ )
29
+ );
30
+ return {
31
+ columns: across,
32
+ width: panelWidth,
33
+ height,
34
+ scale,
35
+ total: rows * (height + FACET_TITLE_PX) + (rows - 1) * FACET_GAP_PX
36
+ };
37
+ }
38
+ if (columns !== void 0) {
39
+ return tile(Math.max(1, Math.min(count, Math.round(columns))));
40
+ }
41
+ let best = tile(1);
42
+ for (let across = 2; across <= count; across++) {
43
+ const grid = tile(across);
44
+ if (grid.scale > best.scale) {
45
+ best = grid;
46
+ }
47
+ }
48
+ return best;
49
+ }
50
+ function facetSettingOf(facet) {
51
+ const raw = typeof facet === "string" ? { field: facet } : facet ?? {};
52
+ const field = raw.field === "walk" || raw.field === "sample" ? raw.field : "";
53
+ return {
54
+ field,
55
+ domain: [...raw.domain ?? []],
56
+ ...raw.columns === void 0 ? {} : { columns: raw.columns }
57
+ };
58
+ }
59
+ function domainFirst(names, domain) {
60
+ const rank = new Map(domain.map((name, i) => [name, i]));
61
+ const listed = (name) => rank.get(name) ?? domain.length;
62
+ return names.map((name, i) => ({ name, i })).sort((a, b) => listed(a.name) - listed(b.name) || a.i - b.i).map(({ name }) => name);
63
+ }
64
+ function facetCells(names, by, domain = []) {
65
+ const wrapOrder = domainFirst(names, domain);
66
+ const wrap = {
67
+ columns: void 0,
68
+ count: names.length,
69
+ cells: names.map((name) => wrapOrder.indexOf(name))
70
+ };
71
+ if (by === "walk") {
72
+ return wrap;
73
+ }
74
+ const places = names.map((name) => {
75
+ const [sample, haplotype, contig] = name.split("#");
76
+ const n = Number(haplotype);
77
+ return contig !== void 0 && Number.isInteger(n) && n >= 0 ? { sample, column: Math.max(0, n - 1) } : void 0;
78
+ });
79
+ const rows = domainFirst(
80
+ [...new Set(places.flatMap((p) => p ? [p.sample] : []))],
81
+ domain
82
+ );
83
+ const columns = Math.max(1, ...places.map((p) => p ? p.column + 1 : 1));
84
+ const cells = places.map(
85
+ (p) => p ? rows.indexOf(p.sample) * columns + p.column : -1
86
+ );
87
+ return cells.includes(-1) || new Set(cells).size < cells.length ? wrap : { columns, count: rows.length * columns, cells };
88
+ }
89
+
90
+ export {
91
+ FACET_GAP_PX,
92
+ FACET_TITLE_PX,
93
+ FACET_PAD_PX,
94
+ facetGrid,
95
+ facetSettingOf,
96
+ facetCells
97
+ };
@@ -0,0 +1,61 @@
1
+ import {
2
+ bypassedPoints
3
+ } from "./chunk-X32PABB7.js";
4
+ import {
5
+ computeEdgeCurves,
6
+ edgeJoinOf,
7
+ routedEdgeCurves,
8
+ strandSides
9
+ } from "./chunk-3PLYZLYV.js";
10
+
11
+ // src/util/edgeCurves.ts
12
+ var cache = /* @__PURE__ */ new WeakMap();
13
+ function baseEdgeCurves(nodePositions, graph, axis, deletions, version, routes, stranded = false) {
14
+ const { scaleX, scaleY } = axis;
15
+ const cached = cache.get(nodePositions);
16
+ if (cached?.graph === graph && cached.scaleX === scaleX && cached.scaleY === scaleY && cached.deletions === deletions && cached.routes === routes && cached.stranded === stranded && cached.version === version) {
17
+ return cached.curves;
18
+ }
19
+ const curves = /* @__PURE__ */ new Map();
20
+ for (let ei = 0; ei < graph.edges.length; ei++) {
21
+ const edge = graph.edges[ei];
22
+ const from = nodePositions[edge.from];
23
+ const to = nodePositions[edge.to];
24
+ if (from?.length && to?.length) {
25
+ const bypassed = deletions?.get(ei);
26
+ const route = bypassed && routes?.[ei];
27
+ curves.set(
28
+ ei,
29
+ route ? routedEdgeCurves(
30
+ from,
31
+ to,
32
+ route,
33
+ stranded ? strandSides(edge) : void 0
34
+ ) : computeEdgeCurves(
35
+ from,
36
+ to,
37
+ edgeJoinOf(edge, stranded),
38
+ 0,
39
+ 0,
40
+ axis,
41
+ bypassed ? bypassedPoints(nodePositions, bypassed) : []
42
+ )
43
+ );
44
+ }
45
+ }
46
+ cache.set(nodePositions, {
47
+ graph,
48
+ scaleX,
49
+ scaleY,
50
+ deletions,
51
+ routes,
52
+ stranded,
53
+ version,
54
+ curves
55
+ });
56
+ return curves;
57
+ }
58
+
59
+ export {
60
+ baseEdgeCurves
61
+ };
@@ -0,0 +1,155 @@
1
+ import {
2
+ stableCoordinate
3
+ } from "./chunk-CDLPYR5O.js";
4
+ import {
5
+ pathOrigin,
6
+ surveyPaths
7
+ } from "./chunk-ST2IBUAN.js";
8
+
9
+ // src/gfa/gfaConverter.ts
10
+ function surveySegments(gfaGraph) {
11
+ const canonical = /* @__PURE__ */ new Map();
12
+ const traversals = /* @__PURE__ */ new Map();
13
+ function claim(id, strand) {
14
+ if (!canonical.has(id)) {
15
+ canonical.set(id, strand);
16
+ }
17
+ }
18
+ function traverse(id, strand) {
19
+ claim(id, strand);
20
+ traversals.set(id, (traversals.get(id) ?? 0) + 1);
21
+ }
22
+ for (const link of gfaGraph.links) {
23
+ claim(link.source, link.strand1 === "-" ? "-" : "+");
24
+ claim(link.target, link.strand2 === "-" ? "-" : "+");
25
+ }
26
+ for (const gfaPath of gfaGraph.paths) {
27
+ for (const segment of gfaPath.path.split(",")) {
28
+ traverse(segment.slice(0, -1), segment.endsWith("-") ? "-" : "+");
29
+ }
30
+ }
31
+ for (const walk of gfaGraph.walks) {
32
+ for (const seg of walk.segments) {
33
+ traverse(seg.id, seg.strand === "-" ? "-" : "+");
34
+ }
35
+ }
36
+ return { canonical, traversals };
37
+ }
38
+ var walkStart = (w) => w.start === -1 ? 0 : w.start;
39
+ function anchorablePaths(gfaGraph) {
40
+ return [
41
+ ...gfaGraph.paths.map((p) => ({
42
+ ...pathOrigin(p.name),
43
+ steps: p.path.split(",").map((segment) => ({
44
+ id: segment.slice(0, -1),
45
+ strand: segment.endsWith("-") ? "-" : "+"
46
+ }))
47
+ })),
48
+ ...gfaGraph.walks.map((w) => ({
49
+ name: `${w.sample}#${w.haplotype}#${w.contig}`,
50
+ start: walkStart(w),
51
+ steps: w.segments.map((s) => ({
52
+ id: s.id,
53
+ strand: s.strand === "-" ? "-" : "+"
54
+ }))
55
+ }))
56
+ ];
57
+ }
58
+ function carriedSamples(gfaNode) {
59
+ const sm = gfaNode.tags.SM;
60
+ if (typeof sm !== "string") {
61
+ return void 0;
62
+ }
63
+ const samples = sm.split(",").map((s) => s.trim()).filter(Boolean);
64
+ return samples.length > 0 ? samples : void 0;
65
+ }
66
+ var positive = (v) => typeof v === "number" && v > 0 ? v : void 0;
67
+ function statedDepth({ tags, length }) {
68
+ const count = positive(tags.RC) ?? positive(tags.FC) ?? positive(tags.KC);
69
+ return positive(tags.dp) ?? positive(tags.DP) ?? (count !== void 0 && length > 0 ? count / length : void 0);
70
+ }
71
+ function makeNode(gfaNode, strand, depth) {
72
+ return {
73
+ id: `${gfaNode.id}${strand}`,
74
+ name: gfaNode.id,
75
+ length: gfaNode.length,
76
+ depth,
77
+ stable: stableCoordinate(gfaNode),
78
+ samples: carriedSamples(gfaNode)
79
+ };
80
+ }
81
+ function convertGFAToGraph(gfaGraph, name = "Imported GFA") {
82
+ const nodes = [];
83
+ const edges = [];
84
+ const { canonical, traversals } = surveySegments(gfaGraph);
85
+ const nodeId = (segmentId) => `${segmentId}${canonical.get(segmentId) ?? "+"}`;
86
+ for (const gfaNode of gfaGraph.nodes) {
87
+ const depth = statedDepth(gfaNode) ?? Math.max(traversals.get(gfaNode.id) ?? 1, 1);
88
+ nodes.push(makeNode(gfaNode, canonical.get(gfaNode.id) ?? "+", depth));
89
+ }
90
+ for (const link of gfaGraph.links) {
91
+ edges.push({
92
+ from: nodeId(link.source),
93
+ to: nodeId(link.target),
94
+ fromStrand: link.strand1 === "-" ? "-" : "+",
95
+ toStrand: link.strand2 === "-" ? "-" : "+"
96
+ });
97
+ }
98
+ const paths = [];
99
+ const edgeToPathsMap = /* @__PURE__ */ new Map();
100
+ const edgeKey = (a, b) => [a, b].sort().join("--");
101
+ function recordPathEdges(nodeIds, name2) {
102
+ for (let i = 0; i < nodeIds.length - 1; i++) {
103
+ const key = edgeKey(nodeIds[i], nodeIds[i + 1]);
104
+ if (!edgeToPathsMap.has(key)) {
105
+ edgeToPathsMap.set(key, /* @__PURE__ */ new Set());
106
+ }
107
+ edgeToPathsMap.get(key).add(name2);
108
+ }
109
+ }
110
+ for (const gfaPath of gfaGraph.paths) {
111
+ const nodeIds = gfaPath.path.split(",").map((segment) => nodeId(segment.slice(0, -1)));
112
+ paths.push({
113
+ name: gfaPath.name,
114
+ nodeIds,
115
+ start: pathOrigin(gfaPath.name).start
116
+ });
117
+ recordPathEdges(nodeIds, gfaPath.name);
118
+ }
119
+ for (const walk of gfaGraph.walks) {
120
+ const nodeIds = walk.segments.map((seg) => nodeId(seg.id));
121
+ const name2 = `${walk.sample}#${walk.haplotype}#${walk.contig}`;
122
+ paths.push({
123
+ name: name2,
124
+ nodeIds,
125
+ start: walkStart(walk),
126
+ sample: walk.sample,
127
+ haplotype: walk.haplotype,
128
+ contig: walk.contig
129
+ });
130
+ recordPathEdges(nodeIds, name2);
131
+ }
132
+ for (const edge of edges) {
133
+ const pathIds = edgeToPathsMap.get(edgeKey(edge.from, edge.to));
134
+ if (pathIds && pathIds.size > 0) {
135
+ edge.pathIds = [...pathIds];
136
+ }
137
+ }
138
+ const lengths = new Map(gfaGraph.nodes.map((n) => [n.id, n.length]));
139
+ const anchoring = gfaGraph.paths.length > 0 || gfaGraph.walks.length > 0 ? surveyPaths(anchorablePaths(gfaGraph), (id) => lengths.get(id) ?? 0) : void 0;
140
+ return {
141
+ name,
142
+ nodes,
143
+ edges,
144
+ paths: paths.length > 0 ? paths : void 0,
145
+ anchorPaths: anchoring?.anchorPaths,
146
+ pathVisits: anchoring?.pathVisits,
147
+ // rGFA's own tags win wherever they are present; pathAnchoring only ever
148
+ // fills in for a graph that carries none.
149
+ anchoredBy: nodes.some((n) => n.stable) ? "tags" : void 0
150
+ };
151
+ }
152
+
153
+ export {
154
+ convertGFAToGraph
155
+ };
@@ -0,0 +1,73 @@
1
+ import {
2
+ GBZ_CUT_DEFAULTS,
3
+ cutWindowGFA,
4
+ haplotypeWanted,
5
+ referencePathQuery,
6
+ referenceSamplesOf,
7
+ resolveReferenceSample
8
+ } from "./chunk-LTUWJKHD.js";
9
+
10
+ // src/gbzCut.ts
11
+ import { GBZBase } from "@gmod/gbz-base";
12
+ var HPRC_GBZ = {
13
+ db: "https://s3-us-west-2.amazonaws.com/human-pangenomics/pangenomes/freeze/release2/minigraph-cactus/v2.1/hprc-v2.1-mc-grch38/hprc-v2.1-mc-grch38.gbz.db",
14
+ index: "https://jbrowse.org/demos/hprc/hprc-v2.1-mc-grch38.haplotype-index.f3.db"
15
+ };
16
+ function haplotypeIndexBeside(db) {
17
+ const GBZ_DB = /\.gbz\.db$/i;
18
+ return GBZ_DB.test(db) ? db.replace(GBZ_DB, ".haplotype-index.db") : void 0;
19
+ }
20
+ function parseRegion(text) {
21
+ const m = /^\s*([^:\s]+):([\d,]+)-([\d,]+)\s*$/.exec(text);
22
+ if (!m) {
23
+ throw new Error(
24
+ `"${text}" is not a region like chr6:160,614,798-160,647,758`
25
+ );
26
+ }
27
+ const n = (s) => Number(s.replaceAll(",", ""));
28
+ return { refName: m[1], start: n(m[2]), end: n(m[3]) };
29
+ }
30
+ async function openGbz(db, index) {
31
+ const base = await GBZBase.open({ source: db, haplotypeIndex: index });
32
+ return { base, referenceSamples: await referenceSamplesOf(base) };
33
+ }
34
+ function referenceSample(ref, samples) {
35
+ try {
36
+ return resolveReferenceSample({
37
+ configured: "",
38
+ anchorPrefix: ref ?? samples[0] ?? "",
39
+ referenceSamples: samples
40
+ });
41
+ } catch (e) {
42
+ if (ref) {
43
+ return ref;
44
+ }
45
+ throw e;
46
+ }
47
+ }
48
+ async function cutGbzRegion({ base, referenceSamples }, src, signal) {
49
+ const region = parseRegion(src.region);
50
+ const sample = referenceSample(src.referenceSample, referenceSamples);
51
+ const query = await referencePathQuery(base, sample, region.refName);
52
+ if (!query) {
53
+ throw new Error(`${sample} has no indexed path named ${region.refName}`);
54
+ }
55
+ signal?.throwIfAborted();
56
+ const wanted = src.haplotypes?.length ? src.haplotypes : void 0;
57
+ const text = await cutWindowGFA(base, query, region.start, region.end, {
58
+ context: src.context ?? GBZ_CUT_DEFAULTS.context,
59
+ snarls: src.snarls ?? GBZ_CUT_DEFAULTS.snarls,
60
+ limit: GBZ_CUT_DEFAULTS.limit,
61
+ signal,
62
+ keep: wanted ? (name) => haplotypeWanted(name, wanted) : void 0
63
+ });
64
+ return { text, region, sample };
65
+ }
66
+
67
+ export {
68
+ HPRC_GBZ,
69
+ haplotypeIndexBeside,
70
+ parseRegion,
71
+ openGbz,
72
+ cutGbzRegion
73
+ };
@@ -0,0 +1,82 @@
1
+ import {
2
+ pathOrigin
3
+ } from "./chunk-ST2IBUAN.js";
4
+ import {
5
+ groupDigits
6
+ } from "./chunk-HCANBJDD.js";
7
+ import {
8
+ isGenericSample
9
+ } from "./chunk-BPLIXMH7.js";
10
+
11
+ // src/pathColors.ts
12
+ function nameHue(name) {
13
+ let hash = 0;
14
+ for (let i = 0; i < name.length; i++) {
15
+ hash = name.charCodeAt(i) + ((hash << 5) - hash);
16
+ }
17
+ return Math.abs(hash % 360);
18
+ }
19
+ function pathHueAt(index, count) {
20
+ return index * 360 / count;
21
+ }
22
+ var PATH_SATURATION = 0.7;
23
+ var PATH_LIGHTNESS = 0.5;
24
+ var MAX_PATH_COLORS = 16;
25
+ function pathColorsLegible(pathCount) {
26
+ return pathCount > 0 && pathCount <= MAX_PATH_COLORS;
27
+ }
28
+ function pathCssColor(index, count) {
29
+ return `hsl(${pathHueAt(index, count)}, ${PATH_SATURATION * 100}%, ${PATH_LIGHTNESS * 100}%)`;
30
+ }
31
+ function pathGreyCssColor(index, count) {
32
+ const lightness = count > 1 ? 25 + 45 * index / (count - 1) : 45;
33
+ return `hsl(0, 0%, ${lightness}%)`;
34
+ }
35
+ function labelTiers(name) {
36
+ const parts = pathOrigin(name).name.split("#");
37
+ const full = parts.join("#");
38
+ if (parts.length >= 3 && isGenericSample(parts[0])) {
39
+ const contig = parts.slice(2).join("#");
40
+ return [contig, contig, full];
41
+ }
42
+ return [parts[0], parts.slice(0, 2).join("#"), full];
43
+ }
44
+ function offsetTiers(name, tiers) {
45
+ const { start } = pathOrigin(name);
46
+ return tiers.map((t) => `${t} @${groupDigits(start)}`);
47
+ }
48
+ function pathLegend(paths, colors) {
49
+ const firstOf = /* @__PURE__ */ new Map();
50
+ paths.forEach((path, i) => {
51
+ if (!firstOf.has(path.name)) {
52
+ firstOf.set(path.name, i);
53
+ }
54
+ });
55
+ const entries = [...firstOf].map(([name, i]) => ({ name, i }));
56
+ const named = entries.map((e) => labelTiers(e.name));
57
+ const candidates = [0, 1, 2].flatMap((t) => [
58
+ entries.map((_, k) => named[k][t]),
59
+ entries.map((e, k) => offsetTiers(e.name, named[k])[t])
60
+ ]);
61
+ const distinct = candidates.find(
62
+ (labels2) => new Set(labels2).size === entries.length
63
+ );
64
+ const labels = distinct ?? candidates.at(-1);
65
+ return entries.map(({ name, i }, k) => ({
66
+ name,
67
+ label: labels[k],
68
+ color: colors?.[i] ?? pathCssColor(i, paths.length)
69
+ }));
70
+ }
71
+
72
+ export {
73
+ nameHue,
74
+ pathHueAt,
75
+ PATH_SATURATION,
76
+ PATH_LIGHTNESS,
77
+ MAX_PATH_COLORS,
78
+ pathColorsLegible,
79
+ pathCssColor,
80
+ pathGreyCssColor,
81
+ pathLegend
82
+ };
@@ -0,0 +1,13 @@
1
+ // src/loadBandage.ts
2
+ var cached;
3
+ function loadBandage() {
4
+ cached ??= import("./bandage-layout-3AR6BCUD.js").then((mod) => mod.default()).catch((e) => {
5
+ cached = void 0;
6
+ throw e;
7
+ });
8
+ return cached;
9
+ }
10
+
11
+ export {
12
+ loadBandage
13
+ };