@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.
- package/README.md +23 -7
- package/dist/alleleProjection/projectAlleles.js +10 -0
- package/dist/anchoredNodes.js +24 -0
- package/dist/bubbleSpreads.js +11 -0
- package/dist/bubbles/bubbleHalos.js +11 -0
- package/dist/bubbles/bubbleLine.js +14 -0
- package/dist/bubbles/bubblesFromGraph.js +10 -0
- package/dist/bubbles/classifyBubble.js +15 -0
- package/dist/bubbles/popBubble.js +9 -0
- package/dist/chunks/chunk-2CVHXFK7.js +530 -0
- package/dist/chunks/chunk-3S3YVOJ7.js +69 -0
- package/dist/chunks/chunk-47DYCZOK.js +115 -0
- package/dist/chunks/chunk-4EMPBO7S.js +117 -0
- package/dist/chunks/chunk-4S47XRYA.js +149 -0
- package/dist/chunks/chunk-5XQDMQXU.js +431 -0
- package/dist/chunks/chunk-6JEWNXCQ.js +90 -0
- package/dist/chunks/chunk-6SBUFFTB.js +97 -0
- package/dist/chunks/chunk-6SXMCK6I.js +476 -0
- package/dist/chunks/chunk-72N5DJHZ.js +155 -0
- package/dist/chunks/chunk-73RSLGZT.js +73 -0
- package/dist/chunks/chunk-7XHHVYG7.js +13 -0
- package/dist/chunks/chunk-AB35TJST.js +67 -0
- package/dist/chunks/chunk-BPLIXMH7.js +52 -0
- package/dist/chunks/chunk-BUBZ32IC.js +101 -0
- package/dist/chunks/chunk-BXEPA4KS.js +179 -0
- package/dist/chunks/chunk-C44YRP5F.js +85 -0
- package/dist/chunks/chunk-CDLPYR5O.js +135 -0
- package/dist/chunks/chunk-CJ2EE4AF.js +40 -0
- package/dist/chunks/chunk-CPMHA4W5.js +6 -0
- package/dist/chunks/chunk-CR7EGAFE.js +241 -0
- package/dist/chunks/chunk-CS3E4ETM.js +202 -0
- package/dist/chunks/chunk-CTSBC2O6.js +90 -0
- package/dist/chunks/chunk-D3M7SBKL.js +210 -0
- package/dist/chunks/chunk-DKOB2OPC.js +177 -0
- package/dist/chunks/chunk-EJ5OZTCK.js +52 -0
- package/dist/chunks/chunk-EK4HGYO7.js +174 -0
- package/dist/chunks/chunk-EPZORFTI.js +23 -0
- package/dist/chunks/chunk-ES2N6V56.js +83 -0
- package/dist/chunks/chunk-EZPBJPK6.js +54 -0
- package/dist/chunks/chunk-FYQWPEEY.js +65 -0
- package/dist/chunks/chunk-GGQRADFS.js +170 -0
- package/dist/chunks/chunk-GOY6REMT.js +43 -0
- package/dist/chunks/chunk-GQ2AOHU4.js +112 -0
- package/dist/chunks/chunk-HNQPEMYE.js +297 -0
- package/dist/chunks/chunk-IGVV37VI.js +60 -0
- package/dist/chunks/chunk-IO2PCPZI.js +218 -0
- package/dist/chunks/chunk-ISEI2FH3.js +108 -0
- package/dist/chunks/chunk-JKJWSY4V.js +32 -0
- package/dist/chunks/chunk-KQFOCDFY.js +73 -0
- package/dist/chunks/chunk-L3O7AWLI.js +52 -0
- package/dist/chunks/chunk-LLJUG2H7.js +6 -0
- package/dist/chunks/chunk-LOEA5IHZ.js +71 -0
- package/dist/chunks/chunk-LTUWJKHD.js +112 -0
- package/dist/chunks/chunk-MFKORG3F.js +44 -0
- package/dist/chunks/chunk-MI35EUIE.js +76 -0
- package/dist/chunks/chunk-MNUSQCLG.js +29 -0
- package/dist/chunks/chunk-MQJUG2D2.js +53 -0
- package/dist/chunks/chunk-MREQ7GIA.js +181 -0
- package/dist/chunks/chunk-N62KBLFC.js +326 -0
- package/dist/chunks/chunk-NNODIW4U.js +26 -0
- package/dist/chunks/chunk-PBENCR5L.js +60 -0
- package/dist/chunks/chunk-PCZ4PTYC.js +726 -0
- package/dist/chunks/chunk-PUG7LXDF.js +70 -0
- package/dist/chunks/chunk-QYBZZI5H.js +0 -0
- package/dist/chunks/chunk-R6ZUK4Y3.js +232 -0
- package/dist/chunks/chunk-RAKOB6IV.js +169 -0
- package/dist/chunks/chunk-ROF2R3RF.js +205 -0
- package/dist/chunks/chunk-RVS2QCOX.js +135 -0
- package/dist/chunks/chunk-ST2IBUAN.js +119 -0
- package/dist/chunks/chunk-SZNZ2T6D.js +198 -0
- package/dist/chunks/chunk-T43W7NKK.js +122 -0
- package/dist/chunks/chunk-TAMCZHLW.js +190 -0
- package/dist/chunks/chunk-TDQLINVI.js +16 -0
- package/dist/chunks/chunk-TEDQJPMI.js +131 -0
- package/dist/chunks/chunk-TZFWUT2C.js +66 -0
- package/dist/chunks/chunk-UVBGRJQX.js +50 -0
- package/dist/chunks/chunk-VHW7FDHU.js +42 -0
- package/dist/chunks/chunk-VZQ4FKLR.js +38 -0
- package/dist/chunks/chunk-WFX3MAKA.js +102 -0
- package/dist/chunks/chunk-WOO7QYKB.js +121 -0
- package/dist/chunks/chunk-WSIFAZU7.js +132 -0
- package/dist/chunks/chunk-X5L37W4J.js +82 -0
- package/dist/chunks/chunk-Y3IOTZJA.js +61 -0
- package/dist/chunks/chunk-YMSSF2RK.js +257 -0
- package/dist/cli/figure.js +84 -17
- package/dist/colorSchemes.js +10 -0
- package/dist/deletionEdges.js +13 -0
- package/dist/el.js +8 -0
- package/dist/facetGrid.js +16 -0
- package/dist/figure.js +51 -0
- package/dist/gaf/parseGaf.js +12 -0
- package/dist/gbzCut.js +19 -0
- package/dist/gbzJoin.js +6 -0
- package/dist/gbzWindow.js +28 -0
- package/dist/genes/exonOutline.js +11 -0
- package/dist/genes/geneFiles.js +14 -0
- package/dist/genes/genePins.js +10 -0
- package/dist/gfa/gfaConverter.js +11 -0
- package/dist/gfa-core/gfaParser.js +8 -0
- package/dist/gfa-core/index.js +9 -0
- package/dist/graphLabels.js +24 -0
- package/dist/index.js +262 -1407
- package/dist/labelLayout.js +24 -0
- package/dist/layout/anchoredLayout.js +11 -0
- package/dist/layout/deletionRoutes.js +10 -0
- package/dist/layout/drawnScale.js +22 -0
- package/dist/layout/mergeRuns.js +15 -0
- package/dist/layout/orderedLayout.js +12 -0
- package/dist/layout/orientToReference.js +7 -0
- package/dist/layout/placeOffReference.js +9 -0
- package/dist/layout/referenceSeeds.js +11 -0
- package/dist/layout/rowSpacing.js +6 -0
- package/dist/layout/sampleRowLayout.js +11 -0
- package/dist/layout/trimToWindow.js +99 -0
- package/dist/layout/tubeMapLayout.js +28 -0
- package/dist/layout/walkRowDraw.js +65 -0
- package/dist/layout/walkRowLayout.js +13 -0
- package/dist/layout/walkRows.js +11 -0
- package/dist/layout/walkStrip.js +40 -0
- package/dist/layoutModes.js +35 -0
- package/dist/loadBandage.js +6 -0
- package/dist/nodeWidths.js +18 -0
- package/dist/overlayLabels.js +18 -0
- package/dist/pansn.js +18 -0
- package/dist/pathAnchoring.js +18 -0
- package/dist/pathColors.js +31 -0
- package/dist/pipeline.js +40 -0
- package/dist/reference.js +24 -0
- package/dist/referenceRampCss.js +29 -0
- package/dist/referenceSpan.js +11 -0
- package/dist/referenceStrip.js +35 -0
- package/dist/renderer/Canvas2DRenderer.js +9 -0
- package/dist/renderer/GeometryBuilder.js +42 -0
- package/dist/renderer/colorBits.js +8 -0
- package/dist/renderer/recordingCanvas.js +44 -0
- package/dist/renderer/svgCanvas.js +6 -0
- package/dist/renderer/types.js +0 -0
- package/dist/tubeMap/axis.js +25 -0
- package/dist/tubeMap/coarsen.js +361 -0
- package/dist/tubeMap/connectors.js +13 -0
- package/dist/tubeMap/deviations.js +85 -0
- package/dist/tubeMap/draw.js +15 -0
- package/dist/tubeMap/frame.js +9 -0
- package/dist/tubeMap/genes.js +20 -0
- package/dist/tubeMap/mismatches.js +6 -0
- package/dist/tubeMap/nodeColors.js +21 -0
- package/dist/tubeMap/reads.js +17 -0
- package/dist/tubeMap/warp.js +8 -0
- package/dist/types/version.d.ts +1 -1
- package/dist/types.js +0 -0
- package/dist/util/SpatialIndex.js +13 -0
- package/dist/util/edgeCurves.js +10 -0
- package/dist/util/geometry.js +39 -0
- package/dist/util/hitDetection.js +20 -0
- package/dist/util/wheelZoom.js +6 -0
- package/dist/version.js +6 -0
- package/dist/viewport.js +33 -0
- package/dist/walkEncoding.js +39 -0
- package/dist/walkHighlight.js +26 -0
- package/dist/walkKey.js +17 -0
- package/package.json +38 -5
- package/dist/chunks/chunk-EXSFRX2F.js +0 -7400
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isBackbone
|
|
3
|
+
} from "./chunk-FYQWPEEY.js";
|
|
4
|
+
|
|
5
|
+
// src/referenceSpan.ts
|
|
6
|
+
var MAX_BACKBONE_HOPS = 4;
|
|
7
|
+
function buildNeighbors(graph) {
|
|
8
|
+
const neighbors = /* @__PURE__ */ new Map();
|
|
9
|
+
function add(from, to) {
|
|
10
|
+
const list = neighbors.get(from);
|
|
11
|
+
if (list) {
|
|
12
|
+
list.push(to);
|
|
13
|
+
} else {
|
|
14
|
+
neighbors.set(from, [to]);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
for (const edge of graph.edges) {
|
|
18
|
+
add(edge.from, edge.to);
|
|
19
|
+
add(edge.to, edge.from);
|
|
20
|
+
}
|
|
21
|
+
return neighbors;
|
|
22
|
+
}
|
|
23
|
+
function flankingSpan({
|
|
24
|
+
nodeId,
|
|
25
|
+
nodeById,
|
|
26
|
+
neighbors
|
|
27
|
+
}) {
|
|
28
|
+
const seen = /* @__PURE__ */ new Set([nodeId]);
|
|
29
|
+
let frontier = [nodeId];
|
|
30
|
+
let minEnd = Infinity;
|
|
31
|
+
let maxStart = -Infinity;
|
|
32
|
+
for (let hop = 0; hop < MAX_BACKBONE_HOPS && frontier.length > 0; hop++) {
|
|
33
|
+
const next = [];
|
|
34
|
+
for (const id of frontier) {
|
|
35
|
+
const adjacent = neighbors.get(id);
|
|
36
|
+
if (adjacent) {
|
|
37
|
+
for (const neighborId of adjacent) {
|
|
38
|
+
if (!seen.has(neighborId)) {
|
|
39
|
+
seen.add(neighborId);
|
|
40
|
+
const neighbor = nodeById.get(neighborId);
|
|
41
|
+
if (neighbor && isBackbone(neighbor)) {
|
|
42
|
+
minEnd = Math.min(minEnd, neighbor.stable.start + neighbor.length);
|
|
43
|
+
maxStart = Math.max(maxStart, neighbor.stable.start);
|
|
44
|
+
} else {
|
|
45
|
+
next.push(neighborId);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
frontier = next;
|
|
52
|
+
}
|
|
53
|
+
return minEnd === Infinity ? void 0 : {
|
|
54
|
+
start: Math.min(minEnd, maxStart),
|
|
55
|
+
end: Math.max(minEnd, maxStart)
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function nodeReferenceSpan({
|
|
59
|
+
nodeId,
|
|
60
|
+
nodeById,
|
|
61
|
+
neighbors
|
|
62
|
+
}) {
|
|
63
|
+
const node = nodeById.get(nodeId);
|
|
64
|
+
return node === void 0 ? void 0 : isBackbone(node) ? { start: node.stable.start, end: node.stable.start + node.length } : flankingSpan({ nodeId, nodeById, neighbors });
|
|
65
|
+
}
|
|
66
|
+
function referenceMidpoints(graph) {
|
|
67
|
+
const nodeById = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
68
|
+
const neighbors = buildNeighbors(graph);
|
|
69
|
+
const midpoints = /* @__PURE__ */ new Map();
|
|
70
|
+
for (const node of graph.nodes) {
|
|
71
|
+
const span = nodeReferenceSpan({ nodeId: node.id, nodeById, neighbors });
|
|
72
|
+
if (span) {
|
|
73
|
+
midpoints.set(node.id, (span.start + span.end) / 2);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return midpoints;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
buildNeighbors,
|
|
81
|
+
nodeReferenceSpan,
|
|
82
|
+
referenceMidpoints
|
|
83
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
walkRows
|
|
3
|
+
} from "./chunk-SZNZ2T6D.js";
|
|
4
|
+
import {
|
|
5
|
+
ROW_HEIGHT_PX
|
|
6
|
+
} from "./chunk-CPMHA4W5.js";
|
|
7
|
+
import {
|
|
8
|
+
backboneNodes,
|
|
9
|
+
backbonePositions,
|
|
10
|
+
overlapsWindow
|
|
11
|
+
} from "./chunk-FYQWPEEY.js";
|
|
12
|
+
|
|
13
|
+
// src/layout/walkRowLayout.ts
|
|
14
|
+
var READOUT_ROOM = 1.3;
|
|
15
|
+
function walkRowsExtent(walks) {
|
|
16
|
+
let longest = walks.reference.bp;
|
|
17
|
+
for (const row of walks.rows) {
|
|
18
|
+
longest = Math.max(longest, row.bp);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
maxX: walks.origin + longest * READOUT_ROOM,
|
|
22
|
+
maxY: walks.rows.length * ROW_HEIGHT_PX
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function walkRowLayout(graph, region) {
|
|
26
|
+
const backbone = backboneNodes(graph);
|
|
27
|
+
const walks = walkRows(graph, region);
|
|
28
|
+
if (backbone.length === 0 || !walks) {
|
|
29
|
+
return void 0;
|
|
30
|
+
}
|
|
31
|
+
const overWindow = region ? backbone.filter((n) => overlapsWindow(n, region)) : backbone;
|
|
32
|
+
const nodePositions = backbonePositions(
|
|
33
|
+
overWindow.length > 0 ? overWindow : backbone
|
|
34
|
+
);
|
|
35
|
+
const rowLabels = [
|
|
36
|
+
{ label: walks.reference.label, y: 0 },
|
|
37
|
+
...walks.rows.map((row, i) => ({
|
|
38
|
+
label: row.label,
|
|
39
|
+
y: (i + 1) * ROW_HEIGHT_PX
|
|
40
|
+
}))
|
|
41
|
+
];
|
|
42
|
+
return {
|
|
43
|
+
nodePositions,
|
|
44
|
+
rowLabels,
|
|
45
|
+
referenceAxis: true,
|
|
46
|
+
pixelRows: true,
|
|
47
|
+
extent: walkRowsExtent(walks)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
walkRowsExtent,
|
|
53
|
+
walkRowLayout
|
|
54
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// src/anchoredNodes.ts
|
|
2
|
+
var REFERENCE_RANK = 0;
|
|
3
|
+
function isAnchored(node) {
|
|
4
|
+
return node.stable !== void 0;
|
|
5
|
+
}
|
|
6
|
+
function isBackbone(node) {
|
|
7
|
+
return node.stable?.rank === REFERENCE_RANK;
|
|
8
|
+
}
|
|
9
|
+
function isOffReference(node) {
|
|
10
|
+
return node.stable !== void 0 && node.stable.rank > REFERENCE_RANK;
|
|
11
|
+
}
|
|
12
|
+
function backboneNodes(graph) {
|
|
13
|
+
return graph.nodes.filter(isBackbone);
|
|
14
|
+
}
|
|
15
|
+
function overlapsWindow(node, window) {
|
|
16
|
+
return node.stable.start < window.end && node.stable.start + node.length > window.start;
|
|
17
|
+
}
|
|
18
|
+
function backbonePositions(backbone) {
|
|
19
|
+
const positions = {};
|
|
20
|
+
for (const node of backbone) {
|
|
21
|
+
positions[node.id] = [
|
|
22
|
+
{ x: node.stable.start, y: 0 },
|
|
23
|
+
{ x: node.stable.start + node.length, y: 0 }
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
return positions;
|
|
27
|
+
}
|
|
28
|
+
function firstNodeAtOrAfter(nodes, bp) {
|
|
29
|
+
let lo = 0;
|
|
30
|
+
let hi = nodes.length;
|
|
31
|
+
while (lo < hi) {
|
|
32
|
+
const mid = lo + hi >> 1;
|
|
33
|
+
if (nodes[mid].stable.start < bp) {
|
|
34
|
+
lo = mid + 1;
|
|
35
|
+
} else {
|
|
36
|
+
hi = mid;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return lo;
|
|
40
|
+
}
|
|
41
|
+
function backboneSpan(backbone) {
|
|
42
|
+
let min = Infinity;
|
|
43
|
+
let max = -Infinity;
|
|
44
|
+
for (const node of backbone) {
|
|
45
|
+
min = Math.min(min, node.stable.start);
|
|
46
|
+
max = Math.max(max, node.stable.start + node.length);
|
|
47
|
+
}
|
|
48
|
+
return max - min;
|
|
49
|
+
}
|
|
50
|
+
function referenceSpan(backbone, region) {
|
|
51
|
+
return region && region.end > region.start ? region.end - region.start : backboneSpan(backbone);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
REFERENCE_RANK,
|
|
56
|
+
isAnchored,
|
|
57
|
+
isBackbone,
|
|
58
|
+
isOffReference,
|
|
59
|
+
backboneNodes,
|
|
60
|
+
overlapsWindow,
|
|
61
|
+
backbonePositions,
|
|
62
|
+
firstNodeAtOrAfter,
|
|
63
|
+
backboneSpan,
|
|
64
|
+
referenceSpan
|
|
65
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import {
|
|
2
|
+
encodedColor,
|
|
3
|
+
resolveEncoding
|
|
4
|
+
} from "./chunk-WFX3MAKA.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,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatBp,
|
|
3
|
+
groupDigits
|
|
4
|
+
} from "./chunk-N62KBLFC.js";
|
|
5
|
+
|
|
6
|
+
// src/walkKey.ts
|
|
7
|
+
function rangeText(contig, start, end) {
|
|
8
|
+
const s = Math.round(start);
|
|
9
|
+
const e = Math.round(end);
|
|
10
|
+
return `${contig ? `${contig}:` : ""}${groupDigits(s)}-${groupDigits(e)} (${formatBp(e - s)})`;
|
|
11
|
+
}
|
|
12
|
+
function walkKey(walk, reference) {
|
|
13
|
+
const { field } = walk.encoding;
|
|
14
|
+
const own = walk.range ? rangeText(walk.range.contig, walk.range.start, walk.range.end) : void 0;
|
|
15
|
+
const scale = field === "progress" ? own : field === "reference" && reference ? rangeText(reference.name, reference.start, reference.end) : void 0;
|
|
16
|
+
const spanned = walk.range ? walk.range.end - walk.range.start : walk.bp;
|
|
17
|
+
const outside = spanned - walk.bp;
|
|
18
|
+
return {
|
|
19
|
+
delta: walk.referenceBp === void 0 || spanned === walk.referenceBp ? "" : ` ${spanned > walk.referenceBp ? "+" : "\u2212"}${formatBp(Math.abs(spanned - walk.referenceBp))}`,
|
|
20
|
+
outside: outside > 0 ? `, ${formatBp(outside)} outside the cut` : "",
|
|
21
|
+
reversed: walk.reversedBp > 0 ? `, ${formatBp(walk.reversedBp)} reversed` : "",
|
|
22
|
+
shades: field !== "walk",
|
|
23
|
+
scale,
|
|
24
|
+
hover: scale === own ? void 0 : own
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function walkPosition(walk, nodeId, length) {
|
|
28
|
+
const progress = walk.progress.get(nodeId);
|
|
29
|
+
const range = walk.range;
|
|
30
|
+
if (progress === void 0 || !range) {
|
|
31
|
+
return void 0;
|
|
32
|
+
}
|
|
33
|
+
const start = Math.round(
|
|
34
|
+
range.start + progress * (range.end - range.start) - length / 2
|
|
35
|
+
);
|
|
36
|
+
return `${range.contig}:${groupDigits(start)}-${groupDigits(start + length)}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
rangeText,
|
|
41
|
+
walkKey,
|
|
42
|
+
walkPosition
|
|
43
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isBackbone
|
|
3
|
+
} from "./chunk-FYQWPEEY.js";
|
|
4
|
+
|
|
5
|
+
// src/tubeMap/connectors.ts
|
|
6
|
+
function referenceNodes(graph, layout) {
|
|
7
|
+
const nodeById = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
8
|
+
const out = [];
|
|
9
|
+
layout.nodes.forEach((node) => {
|
|
10
|
+
const graphNode = nodeById.get(node.name);
|
|
11
|
+
if (node.order >= 0 && graphNode && isBackbone(graphNode)) {
|
|
12
|
+
out.push({
|
|
13
|
+
node: node.name,
|
|
14
|
+
bp0: graphNode.stable.start,
|
|
15
|
+
bp1: graphNode.stable.start + node.sequenceLength,
|
|
16
|
+
x0: node.x,
|
|
17
|
+
x1: node.x + node.pixelWidth
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
function tubeMapConnectors(nodes, bpToScreen, tubeToScreen, width) {
|
|
24
|
+
const out = [];
|
|
25
|
+
for (const n of nodes) {
|
|
26
|
+
const bottom0 = tubeToScreen(n.x0);
|
|
27
|
+
const bottom1 = tubeToScreen(n.x1);
|
|
28
|
+
if (bottom1 >= 0 && bottom0 <= width) {
|
|
29
|
+
out.push({
|
|
30
|
+
node: n.node,
|
|
31
|
+
top0: bpToScreen(n.bp0),
|
|
32
|
+
top1: bpToScreen(n.bp1),
|
|
33
|
+
bottom0,
|
|
34
|
+
bottom1
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
var HIT_SLOP_PX = 3;
|
|
41
|
+
function connectorAt(connectors, zoneBottom, sx, sy) {
|
|
42
|
+
if (zoneBottom <= 0 || sy < 0 || sy > zoneBottom) {
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
const t = sy / zoneBottom;
|
|
46
|
+
let hit;
|
|
47
|
+
let best = HIT_SLOP_PX;
|
|
48
|
+
for (const c of connectors) {
|
|
49
|
+
const a = c.top0 + (c.bottom0 - c.top0) * t;
|
|
50
|
+
const b = c.top1 + (c.bottom1 - c.top1) * t;
|
|
51
|
+
const dist = Math.max(0, Math.min(a, b) - sx, sx - Math.max(a, b));
|
|
52
|
+
if (dist < best) {
|
|
53
|
+
best = dist;
|
|
54
|
+
hit = c.node;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return hit;
|
|
58
|
+
}
|
|
59
|
+
function band(ctx, c, bottom) {
|
|
60
|
+
ctx.moveTo(c.top0, 0);
|
|
61
|
+
ctx.lineTo(c.top1, 0);
|
|
62
|
+
ctx.lineTo(c.bottom1, bottom);
|
|
63
|
+
ctx.lineTo(c.bottom0, bottom);
|
|
64
|
+
ctx.closePath();
|
|
65
|
+
}
|
|
66
|
+
function sides(ctx, c, bottom) {
|
|
67
|
+
ctx.moveTo(c.top0, 0);
|
|
68
|
+
ctx.lineTo(c.bottom0, bottom);
|
|
69
|
+
ctx.moveTo(c.top1, 0);
|
|
70
|
+
ctx.lineTo(c.bottom1, bottom);
|
|
71
|
+
}
|
|
72
|
+
function drawTubeMapConnectors(ctx, connectors, bottom, {
|
|
73
|
+
highlightNode,
|
|
74
|
+
darkMode
|
|
75
|
+
}) {
|
|
76
|
+
if (bottom <= 0 || connectors.length === 0) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const ink = darkMode ? "255,255,255" : "0,0,0";
|
|
80
|
+
ctx.beginPath();
|
|
81
|
+
for (const c of connectors) {
|
|
82
|
+
band(ctx, c, bottom);
|
|
83
|
+
}
|
|
84
|
+
ctx.fillStyle = `rgba(${ink},0.07)`;
|
|
85
|
+
ctx.fill();
|
|
86
|
+
ctx.beginPath();
|
|
87
|
+
for (const c of connectors) {
|
|
88
|
+
sides(ctx, c, bottom);
|
|
89
|
+
}
|
|
90
|
+
ctx.strokeStyle = `rgba(${ink},0.35)`;
|
|
91
|
+
ctx.lineWidth = 0.5;
|
|
92
|
+
ctx.stroke();
|
|
93
|
+
const lit = connectors.find((c) => c.node === highlightNode);
|
|
94
|
+
if (lit) {
|
|
95
|
+
ctx.beginPath();
|
|
96
|
+
band(ctx, lit, bottom);
|
|
97
|
+
ctx.fillStyle = "rgba(255,192,203,0.5)";
|
|
98
|
+
ctx.fill();
|
|
99
|
+
ctx.beginPath();
|
|
100
|
+
sides(ctx, lit, bottom);
|
|
101
|
+
ctx.strokeStyle = "#ff0000";
|
|
102
|
+
ctx.lineWidth = 1;
|
|
103
|
+
ctx.stroke();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
referenceNodes,
|
|
109
|
+
tubeMapConnectors,
|
|
110
|
+
connectorAt,
|
|
111
|
+
drawTubeMapConnectors
|
|
112
|
+
};
|