@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,135 @@
1
+ import {
2
+ buildNeighbors
3
+ } from "./chunk-ES2N6V56.js";
4
+ import {
5
+ REFERENCE_RANK,
6
+ isAnchored
7
+ } from "./chunk-FYQWPEEY.js";
8
+
9
+ // src/alleleProjection/projectAlleles.ts
10
+ function parsePanSN(refName) {
11
+ const parts = refName.split("#");
12
+ const haplotype = parts.length >= 2 ? Number(parts[1]) : Number.NaN;
13
+ return {
14
+ sample: parts[0] ?? refName,
15
+ haplotype: Number.isFinite(haplotype) ? haplotype : void 0
16
+ };
17
+ }
18
+ function collectRun(seed, byId, adj, claimed) {
19
+ const members = [];
20
+ const anchors = [];
21
+ const queue = [seed];
22
+ claimed.add(seed);
23
+ while (queue.length > 0) {
24
+ const id = queue.pop();
25
+ const node = byId.get(id);
26
+ if (node) {
27
+ members.push(node);
28
+ for (const neighborId of adj.get(id) ?? []) {
29
+ const neighbor = byId.get(neighborId);
30
+ if (neighbor) {
31
+ if (neighbor.stable.rank === REFERENCE_RANK) {
32
+ anchors.push(neighbor);
33
+ } else if (!claimed.has(neighborId)) {
34
+ claimed.add(neighborId);
35
+ queue.push(neighborId);
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ return { members, anchors };
42
+ }
43
+ function anchorSpan(anchors) {
44
+ const refNames = new Set(anchors.map((a) => a.stable.refName));
45
+ if (refNames.size !== 1 || anchors.length < 2) {
46
+ return void 0;
47
+ }
48
+ const sorted = [...anchors].sort((a, b) => a.stable.start - b.stable.start);
49
+ const first = sorted[0];
50
+ const last = sorted.at(-1);
51
+ const start = first.stable.start + first.length;
52
+ const end = last.stable.start;
53
+ return end >= start ? { start, end, entry: first } : void 0;
54
+ }
55
+ function runDistances(members, entry, adj) {
56
+ const byId = new Map(members.map((m) => [m.id, m]));
57
+ const dist = /* @__PURE__ */ new Map();
58
+ const queue = [];
59
+ for (const neighborId of adj.get(entry.id) ?? []) {
60
+ if (byId.has(neighborId)) {
61
+ dist.set(neighborId, 0);
62
+ queue.push(neighborId);
63
+ }
64
+ }
65
+ if (queue.length === 0) {
66
+ for (const member of members) {
67
+ dist.set(member.id, 0);
68
+ queue.push(member.id);
69
+ }
70
+ }
71
+ for (const id of queue) {
72
+ const reach = dist.get(id) + byId.get(id).length;
73
+ for (const neighborId of adj.get(id) ?? []) {
74
+ if (byId.has(neighborId)) {
75
+ const known = dist.get(neighborId);
76
+ if (known === void 0 || reach < known) {
77
+ dist.set(neighborId, reach);
78
+ queue.push(neighborId);
79
+ }
80
+ }
81
+ }
82
+ }
83
+ return dist;
84
+ }
85
+ function runOffsets(members, entry, adj) {
86
+ const dist = runDistances(members, entry, adj);
87
+ const ordered = [...members].sort((a, b) => dist.get(a.id) - dist.get(b.id));
88
+ const rank = new Map(ordered.map((m, i) => [m.id, i]));
89
+ const byId = new Map(members.map((m) => [m.id, m]));
90
+ const offsets = /* @__PURE__ */ new Map();
91
+ for (const [i, member] of ordered.entries()) {
92
+ let offset = 0;
93
+ for (const neighborId of adj.get(member.id) ?? []) {
94
+ const neighbor = byId.get(neighborId);
95
+ if (neighbor && rank.get(neighborId) < i) {
96
+ offset = Math.max(offset, offsets.get(neighborId) + neighbor.length);
97
+ }
98
+ }
99
+ offsets.set(member.id, offset);
100
+ }
101
+ return { offsets, ordered };
102
+ }
103
+ function projectAlleles(graph) {
104
+ const byId = new Map(
105
+ graph.nodes.filter(isAnchored).map((n) => [n.id, n])
106
+ );
107
+ const adj = buildNeighbors(graph);
108
+ const claimed = /* @__PURE__ */ new Set();
109
+ const alleles = [];
110
+ for (const node of byId.values()) {
111
+ if (node.stable.rank !== REFERENCE_RANK && !claimed.has(node.id)) {
112
+ const { members, anchors } = collectRun(node.id, byId, adj, claimed);
113
+ const span = anchorSpan(anchors);
114
+ if (span) {
115
+ const { offsets, ordered } = runOffsets(members, span.entry, adj);
116
+ alleles.push({
117
+ start: span.start,
118
+ refSpan: span.end - span.start,
119
+ nodeIds: ordered.map((m) => m.id),
120
+ nodeOffsets: ordered.map((m) => offsets.get(m.id)),
121
+ pathLength: ordered.reduce(
122
+ (max, m) => Math.max(max, offsets.get(m.id) + m.length),
123
+ 0
124
+ )
125
+ });
126
+ }
127
+ }
128
+ }
129
+ return alleles.sort((a, b) => a.start - b.start);
130
+ }
131
+
132
+ export {
133
+ parsePanSN,
134
+ projectAlleles
135
+ };
@@ -0,0 +1,119 @@
1
+ import {
2
+ panSNSample
3
+ } from "./chunk-BPLIXMH7.js";
4
+ import {
5
+ REFERENCE_RANK
6
+ } from "./chunk-FYQWPEEY.js";
7
+
8
+ // src/pathAnchoring.ts
9
+ var RANGE_SUFFIX = /:(\d+)-\d+$/;
10
+ function pathOrigin(pathName) {
11
+ const match = RANGE_SUFFIX.exec(pathName);
12
+ return match ? { name: pathName.slice(0, match.index), start: +match[1] } : { name: pathName, start: 0 };
13
+ }
14
+ function surveyPaths(paths, lengthOf) {
15
+ const anchorPaths = [];
16
+ const pathVisits = /* @__PURE__ */ new Map();
17
+ for (const path of paths) {
18
+ const sample = panSNSample(path.name);
19
+ let pos = path.start;
20
+ for (const step of path.steps) {
21
+ const visit = {
22
+ path: path.name,
23
+ sample,
24
+ start: pos,
25
+ strand: step.strand
26
+ };
27
+ const existing = pathVisits.get(step.id);
28
+ if (existing) {
29
+ existing.push(visit);
30
+ } else {
31
+ pathVisits.set(step.id, [visit]);
32
+ }
33
+ pos += lengthOf(step.id);
34
+ }
35
+ anchorPaths.push({
36
+ name: path.name,
37
+ sample,
38
+ start: path.start,
39
+ length: pos - path.start
40
+ });
41
+ }
42
+ return { anchorPaths, pathVisits };
43
+ }
44
+ function chooseReferencePath(anchorPaths, preferred) {
45
+ const named = anchorPaths.find(
46
+ (p) => p.sample === preferred || p.name === preferred
47
+ );
48
+ return named ?? anchorPaths[0];
49
+ }
50
+ var OFF_REFERENCE_RANK = 1;
51
+ function anchorNode(node, visits, reference) {
52
+ let anchored = node;
53
+ if (visits && visits.length > 0) {
54
+ const anchor = visits.find((v) => v.path === reference) ?? visits[0];
55
+ anchored = {
56
+ ...node,
57
+ stable: {
58
+ refName: anchor.path,
59
+ start: anchor.start,
60
+ rank: anchor.path === reference ? REFERENCE_RANK : OFF_REFERENCE_RANK,
61
+ strand: anchor.strand
62
+ },
63
+ samples: [...new Set(visits.map((v) => v.sample))].sort()
64
+ };
65
+ }
66
+ return anchored;
67
+ }
68
+ function anchorFromPaths(graph, preferred) {
69
+ const { anchorPaths, pathVisits } = graph;
70
+ const reference = anchorPaths && pathVisits ? chooseReferencePath(anchorPaths, preferred) : void 0;
71
+ return reference && pathVisits ? {
72
+ ...graph,
73
+ nodes: graph.nodes.map(
74
+ (node) => anchorNode(node, pathVisits.get(node.name), reference.name)
75
+ ),
76
+ anchoredBy: "paths",
77
+ referencePath: reference.name
78
+ } : graph;
79
+ }
80
+ function anchorGraph(graph, preferred) {
81
+ return graph.anchoredBy === "tags" ? graph : anchorFromPaths(graph, preferred);
82
+ }
83
+ function trimOrigins(graph, kept) {
84
+ if (!graph.anchorPaths) {
85
+ return void 0;
86
+ }
87
+ const lengthOf = new Map(graph.nodes.map((n) => [n.id, n.length]));
88
+ const bp = (ids, end = ids.length) => {
89
+ let sum = 0;
90
+ for (let i = 0; i < end; i++) {
91
+ sum += lengthOf.get(ids[i]) ?? 0;
92
+ }
93
+ return sum;
94
+ };
95
+ const byOrigin = /* @__PURE__ */ new Map();
96
+ for (const path of graph.paths ?? []) {
97
+ const origin = pathOrigin(path.name).name;
98
+ byOrigin.set(origin, [...byOrigin.get(origin) ?? [], path]);
99
+ }
100
+ return graph.anchorPaths.map((o) => {
101
+ const pieces = byOrigin.get(o.name);
102
+ const path = pieces?.length === 1 ? pieces[0] : void 0;
103
+ const stretch = path && kept.get(path.name);
104
+ return path && stretch ? {
105
+ ...o,
106
+ start: o.start + bp(path.nodeIds, stretch.first),
107
+ length: bp(stretch.nodeIds)
108
+ } : o;
109
+ });
110
+ }
111
+
112
+ export {
113
+ pathOrigin,
114
+ surveyPaths,
115
+ chooseReferencePath,
116
+ anchorFromPaths,
117
+ anchorGraph,
118
+ trimOrigins
119
+ };
@@ -0,0 +1,198 @@
1
+ import {
2
+ pathOrigin
3
+ } from "./chunk-ST2IBUAN.js";
4
+ import {
5
+ panSNContig,
6
+ panSNSample
7
+ } from "./chunk-BPLIXMH7.js";
8
+
9
+ // src/layout/walkRows.ts
10
+ function sampleOf(path) {
11
+ return path.sample ?? panSNSample(path.name);
12
+ }
13
+ function labelOf(path) {
14
+ return path.haplotype !== void 0 && path.sample !== void 0 ? `${path.sample}#${path.haplotype}` : sampleOf(path);
15
+ }
16
+ function stepsOf(pieces, lengthOf) {
17
+ const steps = [];
18
+ let end;
19
+ for (const piece of pieces) {
20
+ if (end !== void 0 && piece.start !== void 0 && piece.start > end) {
21
+ steps.push(piece.start - end);
22
+ }
23
+ steps.push(...piece.nodeIds);
24
+ const bp = piece.nodeIds.reduce(
25
+ (sum, id) => sum + (lengthOf.get(id) ?? 0),
26
+ 0
27
+ );
28
+ end = piece.start === void 0 ? void 0 : piece.start + bp;
29
+ }
30
+ return steps;
31
+ }
32
+ function stepSpans(pieces, lengthOf) {
33
+ const spans = [];
34
+ let end;
35
+ for (const piece of pieces) {
36
+ if (piece.start === void 0 || end !== void 0 && piece.start < end) {
37
+ return void 0;
38
+ }
39
+ if (end !== void 0 && piece.start > end) {
40
+ spans.push({ start: end, end: piece.start });
41
+ }
42
+ let pos = piece.start;
43
+ for (const id of piece.nodeIds) {
44
+ const len = lengthOf.get(id) ?? 0;
45
+ spans.push({ start: pos, end: pos + len });
46
+ pos += len;
47
+ }
48
+ end = pos;
49
+ }
50
+ return spans;
51
+ }
52
+ function sliceBetween(steps, span, region, flanked = true) {
53
+ if (!region || !flanked) {
54
+ return { ids: steps, complete: true, from: -1, to: -1 };
55
+ }
56
+ let i0 = -1;
57
+ let i1 = -1;
58
+ let bestEnd = -Infinity;
59
+ let bestStart = Infinity;
60
+ steps.forEach((id, i) => {
61
+ const s = typeof id === "string" ? span.get(id) : void 0;
62
+ if (s) {
63
+ if (s.end <= region.start && s.end > bestEnd) {
64
+ bestEnd = s.end;
65
+ i0 = i;
66
+ }
67
+ if (s.start >= region.end && s.start < bestStart) {
68
+ bestStart = s.start;
69
+ i1 = i;
70
+ }
71
+ }
72
+ });
73
+ if (i0 < 0 || i1 < 0) {
74
+ return { ids: steps, complete: false, from: -1, to: -1 };
75
+ }
76
+ const ids = steps.slice(Math.min(i0, i1) + 1, Math.max(i0, i1));
77
+ return {
78
+ ids: i0 < i1 ? ids : ids.reverse(),
79
+ complete: true,
80
+ from: i0,
81
+ to: i1
82
+ };
83
+ }
84
+ function filterSamples(rows, samples) {
85
+ return samples ? rows.filter((r) => samples.includes(r.sample)).sort(
86
+ (a, b) => samples.indexOf(a.sample) - samples.indexOf(b.sample) || a.label.localeCompare(b.label)
87
+ ) : rows;
88
+ }
89
+ function walkRows(graph, region, unit) {
90
+ const paths = graph.paths ?? [];
91
+ const isReference = (p) => pathOrigin(p.name).name === graph.referencePath;
92
+ const referencePieces = paths.some(isReference) ? paths.filter(isReference).sort((a, b) => (a.start ?? 0) - (b.start ?? 0)) : paths.slice(0, 1);
93
+ const first = referencePieces[0];
94
+ const others = paths.filter((p) => !referencePieces.includes(p));
95
+ if (!first || others.length === 0) {
96
+ return void 0;
97
+ }
98
+ const walks = /* @__PURE__ */ new Map();
99
+ for (const path of others) {
100
+ walks.set(path.name, [...walks.get(path.name) ?? [], path]);
101
+ }
102
+ const lengthOf = new Map(graph.nodes.map((n) => [n.id, n.length]));
103
+ const referenceStart = first.start ?? 0;
104
+ const cut = region && region.end > region.start ? region : void 0;
105
+ const span = /* @__PURE__ */ new Map();
106
+ for (const piece of referencePieces) {
107
+ let pos = piece.start ?? 0;
108
+ for (const id of piece.nodeIds) {
109
+ const len = lengthOf.get(id) ?? 0;
110
+ if (!span.has(id)) {
111
+ span.set(id, { start: pos, end: pos + len });
112
+ }
113
+ pos += len;
114
+ }
115
+ }
116
+ const flanked = cut === void 0 || [...span.values()].some((s) => s.end <= cut.start) && [...span.values()].some((s) => s.start >= cut.end);
117
+ const rowOf = (pieces) => {
118
+ const path = pieces[0];
119
+ const ordered = [...pieces].sort((a, b) => (a.start ?? 0) - (b.start ?? 0));
120
+ const { ids, complete, from, to } = sliceBetween(
121
+ stepsOf(ordered, lengthOf),
122
+ span,
123
+ cut,
124
+ flanked
125
+ );
126
+ const spans = stepSpans(ordered, lengthOf);
127
+ const contig = path.contig ?? panSNContig(pathOrigin(path.name).name);
128
+ const axis = !spans?.length ? void 0 : from < 0 ? { contig, start: spans[0].start, reversed: false } : from < to ? { contig, start: spans[from].end, reversed: false } : { contig, start: spans[from].start, reversed: true };
129
+ const runs = [];
130
+ let bp = 0;
131
+ let offReferenceBp = 0;
132
+ let gapBp = 0;
133
+ let step = 0;
134
+ for (const id of ids) {
135
+ if (typeof id === "number") {
136
+ runs.push({ start: bp, bp: id, onReference: false, gap: true });
137
+ bp += id;
138
+ gapBp += id;
139
+ step = 0;
140
+ continue;
141
+ }
142
+ const len = lengthOf.get(id) ?? 0;
143
+ const s = span.get(id);
144
+ const last = runs.at(-1);
145
+ const at = last?.referenceStart;
146
+ const forward = s && at !== void 0 && step >= 0 && at + last.bp === s.start;
147
+ const backward = s && at !== void 0 && step <= 0 && s.end === at;
148
+ if (!s && last && !last.onReference && !last.gap) {
149
+ last.bp += len;
150
+ } else if (forward || backward) {
151
+ last.bp += len;
152
+ if (!forward) {
153
+ last.referenceStart = s.start;
154
+ last.reversed = true;
155
+ }
156
+ step = forward ? 1 : -1;
157
+ } else {
158
+ runs.push({
159
+ start: bp,
160
+ bp: len,
161
+ onReference: s !== void 0,
162
+ referenceStart: s?.start
163
+ });
164
+ step = 0;
165
+ }
166
+ bp += len;
167
+ if (!s) {
168
+ offReferenceBp += len;
169
+ }
170
+ }
171
+ return {
172
+ name: path.name,
173
+ label: labelOf(path),
174
+ sample: sampleOf(path),
175
+ haplotype: path.haplotype,
176
+ bp,
177
+ offReferenceBp,
178
+ gapBp,
179
+ complete,
180
+ runs,
181
+ axis
182
+ };
183
+ };
184
+ const origin = cut ? cut.start : referenceStart;
185
+ return {
186
+ origin,
187
+ unit,
188
+ reference: rowOf(referencePieces),
189
+ rows: [...walks.values()].map(rowOf).sort(
190
+ (a, b) => Number(b.complete) - Number(a.complete) || b.bp - a.bp || a.label.localeCompare(b.label)
191
+ )
192
+ };
193
+ }
194
+
195
+ export {
196
+ filterSamples,
197
+ walkRows
198
+ };
@@ -0,0 +1,122 @@
1
+ import {
2
+ hasTubeMapPaths,
3
+ tubeMapLayout,
4
+ tubeMapReferenceLayout
5
+ } from "./chunk-R6ZUK4Y3.js";
6
+ import {
7
+ sampleRowLayout
8
+ } from "./chunk-LOEA5IHZ.js";
9
+ import {
10
+ anchoredLayout
11
+ } from "./chunk-L3O7AWLI.js";
12
+ import {
13
+ orderedLayout
14
+ } from "./chunk-HNQPEMYE.js";
15
+ import {
16
+ walkRowLayout
17
+ } from "./chunk-EZPBJPK6.js";
18
+ import {
19
+ isBackbone,
20
+ isOffReference
21
+ } from "./chunk-FYQWPEEY.js";
22
+
23
+ // src/layoutModes.ts
24
+ var FORCE_LAYOUT_LABEL = "Force-directed layout";
25
+ var hasBackbone = (graph) => graph.nodes.some(isBackbone);
26
+ var hasWalks = (graph) => hasBackbone(graph) && (graph.paths?.length ?? 0) > 1;
27
+ var hasTubeMapBackbone = (graph) => hasBackbone(graph) && hasTubeMapPaths(graph);
28
+ var hasAlleles = (graph) => hasBackbone(graph) && graph.nodes.some(isOffReference);
29
+ var LAYOUT_MODES = [
30
+ {
31
+ value: "auto",
32
+ label: "Anchored",
33
+ description: "x is reference bp, one row per stable rank. Needs rGFA tags or a reference path.",
34
+ run: anchoredLayout,
35
+ cutMargins: true,
36
+ wholeWalks: false,
37
+ available: hasBackbone,
38
+ drawsLocally: hasBackbone,
39
+ drawsNodes: true
40
+ },
41
+ {
42
+ value: "samplerows",
43
+ label: "Sample rows",
44
+ description: "x is reference bp, one row per contributing assembly. Needs rGFA tags or a reference path.",
45
+ run: sampleRowLayout,
46
+ cutMargins: true,
47
+ wholeWalks: false,
48
+ available: hasAlleles,
49
+ drawsLocally: hasAlleles,
50
+ drawsNodes: true
51
+ },
52
+ {
53
+ value: "walkrows",
54
+ label: "Walk rows",
55
+ description: "x is each walk's own bp: one bar per haplotype, blue on the reference's path and purple off it, so a repeat expansion reads as bar length, and each bar boxes its haplotype's own genes where the session has them. Needs W or P lines.",
56
+ run: walkRowLayout,
57
+ cutMargins: false,
58
+ wholeWalks: true,
59
+ available: hasWalks,
60
+ drawsLocally: hasWalks,
61
+ drawsNodes: false
62
+ },
63
+ {
64
+ value: "ordered",
65
+ label: "Ordered",
66
+ description: "x is reference order, not bp: every node gets room, bubbles read as lenses. Needs rGFA tags or a reference path.",
67
+ run: orderedLayout,
68
+ cutMargins: false,
69
+ wholeWalks: false,
70
+ available: hasBackbone,
71
+ drawsLocally: hasBackbone,
72
+ drawsNodes: true
73
+ },
74
+ {
75
+ value: "tubemap",
76
+ label: "Tube map",
77
+ description: "sequenceTubeMap: every path a coloured tube through boxed nodes, columns in node order and node widths log-scaled. Needs P or W lines.",
78
+ run: tubeMapLayout,
79
+ cutMargins: false,
80
+ wholeWalks: false,
81
+ available: hasTubeMapPaths,
82
+ drawsLocally: hasTubeMapPaths,
83
+ drawsNodes: false
84
+ },
85
+ {
86
+ value: "tubemapref",
87
+ label: "Tube map on reference",
88
+ description: "The tube map with each column at the reference bp it covers, so the tubes line up with the tracks around them. Needs P or W lines and a reference path.",
89
+ run: tubeMapReferenceLayout,
90
+ cutMargins: true,
91
+ wholeWalks: false,
92
+ available: hasTubeMapBackbone,
93
+ drawsLocally: hasTubeMapBackbone,
94
+ drawsNodes: false
95
+ },
96
+ {
97
+ value: "force",
98
+ label: FORCE_LAYOUT_LABEL,
99
+ description: "OGDF FMMM, via the external Bandage engine.",
100
+ run: () => void 0,
101
+ cutMargins: false,
102
+ wholeWalks: false,
103
+ available: () => true,
104
+ drawsLocally: () => false,
105
+ drawsNodes: true
106
+ }
107
+ ];
108
+ var LAYOUT_MODE_VALUES = LAYOUT_MODES.map((m) => m.value);
109
+ function modeUsesLayoutEngine(value, graph) {
110
+ return !layoutModeByValue(value).drawsLocally(graph);
111
+ }
112
+ function layoutModeByValue(value) {
113
+ return LAYOUT_MODES.find((m) => m.value === value) ?? LAYOUT_MODES[0];
114
+ }
115
+
116
+ export {
117
+ FORCE_LAYOUT_LABEL,
118
+ LAYOUT_MODES,
119
+ LAYOUT_MODE_VALUES,
120
+ modeUsesLayoutEngine,
121
+ layoutModeByValue
122
+ };