@jbrowse/bandage-core 10.2.7 → 10.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/alleleProjection/projectAlleles.js +8 -4
- package/dist/anchoredNodes.js +2 -1
- package/dist/bubbleSpreads.js +2 -2
- package/dist/bubbles/bubbleHalos.js +10 -11
- package/dist/bubbles/bubblesFromGraph.js +8 -3
- package/dist/bubbles/classifyBubble.js +9 -6
- package/dist/bubbles/popBubble.js +7 -5
- package/dist/bubbles/superbubbles.js +18 -14
- package/dist/chunks/{chunk-RAKOB6IV.js → chunk-234NFZS4.js} +8 -6
- package/dist/chunks/{chunk-ABUIN5AK.js → chunk-2Q22S52W.js} +29 -24
- package/dist/chunks/{chunk-6JEWNXCQ.js → chunk-34BOZKIE.js} +0 -2
- package/dist/chunks/{chunk-RVS2QCOX.js → chunk-3GLG3ZLE.js} +2 -11
- package/dist/chunks/{chunk-3XSM4OZU.js → chunk-3GP3KT5L.js} +5 -5
- package/dist/chunks/{chunk-PUG7LXDF.js → chunk-3PZSBNLI.js} +4 -1
- package/dist/chunks/{chunk-JLSJMCDJ.js → chunk-3UST3ZQE.js} +3 -3
- package/dist/chunks/{chunk-KBEP7VYK.js → chunk-3VCKBSML.js} +4 -4
- package/dist/chunks/{chunk-BPLIXMH7.js → chunk-4XWZNPQ2.js} +14 -0
- package/dist/chunks/{chunk-4DRQTBBE.js → chunk-6EOB6ANX.js} +1 -1
- package/dist/chunks/{chunk-L2HDM2R3.js → chunk-A2TJ5UX6.js} +7 -7
- package/dist/chunks/{chunk-URZ3CH2R.js → chunk-A4JDEUAI.js} +1 -1
- package/dist/chunks/{chunk-CWFNEKST.js → chunk-A7H753BA.js} +3 -3
- package/dist/chunks/{chunk-CG35S2S2.js → chunk-AQCOIE5R.js} +1 -1
- package/dist/chunks/{chunk-TKIJ5535.js → chunk-AZ4EEF6Q.js} +6 -6
- package/dist/chunks/{chunk-M6LK4GII.js → chunk-B5X2RLJG.js} +17 -10
- package/dist/chunks/{chunk-A7CFWFQS.js → chunk-BKEZLETL.js} +1 -1
- package/dist/chunks/{chunk-RPRHR56C.js → chunk-BS6HPYCZ.js} +3 -3
- package/dist/chunks/chunk-BSOZW3FC.js +30 -0
- package/dist/chunks/{chunk-XXT2JCAC.js → chunk-BX4AUMZE.js} +11 -13
- package/dist/chunks/{chunk-N73TI3VG.js → chunk-BZFOFC4D.js} +6 -9
- package/dist/chunks/{chunk-4ETPXDO6.js → chunk-CGFPFBT2.js} +1 -1
- package/dist/chunks/{chunk-24WITXQY.js → chunk-CGMSKIEO.js} +9 -25
- package/dist/chunks/{chunk-VV6KGJ7M.js → chunk-CHNESV7L.js} +18 -27
- package/dist/chunks/{chunk-IGVV37VI.js → chunk-CKUVEHSS.js} +3 -3
- package/dist/chunks/{chunk-JBCZIBFC.js → chunk-CRCD3ODN.js} +0 -1
- package/dist/chunks/{chunk-AUFAPUO4.js → chunk-D7WIYPG3.js} +3 -1
- package/dist/chunks/{chunk-OIV2GBAJ.js → chunk-DBLV7PGG.js} +27 -17
- package/dist/chunks/{chunk-VQC7KELB.js → chunk-DO62DG26.js} +11 -3
- package/dist/chunks/{chunk-JA2HJIYS.js → chunk-E4ZM4OOJ.js} +3 -5
- package/dist/chunks/{chunk-QLWI2PZ3.js → chunk-EJRJAAN7.js} +24 -21
- package/dist/chunks/{chunk-QBHPHLAQ.js → chunk-EWLXU3UG.js} +41 -36
- package/dist/chunks/{chunk-XI3ZUTWF.js → chunk-FW2R7UDZ.js} +14 -20
- package/dist/chunks/{chunk-Q7LYHGGQ.js → chunk-GIHTHYXY.js} +5 -4
- package/dist/chunks/{chunk-L3O7AWLI.js → chunk-GJLZ2MKE.js} +2 -2
- package/dist/chunks/{chunk-LOEA5IHZ.js → chunk-GJU6BJJA.js} +8 -8
- package/dist/chunks/{chunk-XL472HHD.js → chunk-GQZVR5DW.js} +12 -7
- package/dist/chunks/{chunk-UVBGRJQX.js → chunk-HKYXWZQS.js} +1 -1
- package/dist/chunks/chunk-HMXCN6PG.js +17 -0
- package/dist/chunks/{chunk-WSIFAZU7.js → chunk-HNWJ4B7S.js} +12 -13
- package/dist/chunks/chunk-HOAIOEI7.js +18 -0
- package/dist/chunks/{chunk-XMW266WS.js → chunk-HSVFCA2J.js} +18 -20
- package/dist/chunks/{chunk-QXUEF3AJ.js → chunk-KMBE2Q42.js} +22 -17
- package/dist/chunks/{chunk-VQWHMWLF.js → chunk-M5NPD55W.js} +18 -14
- package/dist/chunks/chunk-MWOVW4AH.js +327 -0
- package/dist/chunks/{chunk-HK5Y2YWV.js → chunk-MYDHU2UV.js} +6 -11
- package/dist/chunks/{chunk-TZFWUT2C.js → chunk-MYLAJDKB.js} +2 -2
- package/dist/chunks/{chunk-AR4BUBMU.js → chunk-NZTYV3JL.js} +34 -35
- package/dist/chunks/{chunk-4HWM3FNK.js → chunk-OMUPUB4J.js} +39 -56
- package/dist/chunks/{chunk-LKW2TP4N.js → chunk-OOIOX36I.js} +18 -16
- package/dist/chunks/{chunk-EQ2NIFRH.js → chunk-OXRUPNSV.js} +1 -1
- package/dist/chunks/{chunk-PTABFYQ7.js → chunk-PFRQBCGC.js} +49 -60
- package/dist/chunks/{chunk-T6V4KI2L.js → chunk-PNMJFFNB.js} +1 -1
- package/dist/chunks/{chunk-KC7T5RWG.js → chunk-PSCSZSVK.js} +9 -16
- package/dist/chunks/{chunk-23YFB5BB.js → chunk-QH2MIXBA.js} +29 -13
- package/dist/chunks/{chunk-5GMFEPWR.js → chunk-R2PJKD3Y.js} +16 -28
- package/dist/chunks/{chunk-CQHUZHET.js → chunk-RFG42VIO.js} +46 -30
- package/dist/chunks/{chunk-FYQWPEEY.js → chunk-RJWPJCIB.js} +5 -11
- package/dist/chunks/{chunk-WBSWROE6.js → chunk-SFP3E4RI.js} +14 -18
- package/dist/chunks/{chunk-2CMYNW3E.js → chunk-SI3BB4DO.js} +1 -1
- package/dist/chunks/{chunk-DY3JCAMX.js → chunk-SOMZGDVS.js} +7 -16
- package/dist/chunks/{chunk-A4PFFC4Q.js → chunk-SWCULW6S.js} +60 -102
- package/dist/chunks/{chunk-XV4P5KEQ.js → chunk-TGUFT6KK.js} +6 -3
- package/dist/chunks/{chunk-CM6LO6OC.js → chunk-UAFATXYA.js} +10 -14
- package/dist/chunks/{chunk-7SRWJLSC.js → chunk-UBQSRCWR.js} +11 -8
- package/dist/chunks/{chunk-RUCH6ZFL.js → chunk-V4YML3GR.js} +2 -1
- package/dist/chunks/{chunk-ES2N6V56.js → chunk-VX656OAZ.js} +6 -11
- package/dist/chunks/chunk-WA5WNP6V.js +37 -0
- package/dist/chunks/{chunk-B6IW3IRE.js → chunk-WYJQIC75.js} +14 -15
- package/dist/chunks/{chunk-T2PCSAFY.js → chunk-XVS52NMZ.js} +2 -2
- package/dist/chunks/{chunk-CU6P5RUG.js → chunk-YZQI35UJ.js} +22 -16
- package/dist/chunks/{chunk-G45YY72K.js → chunk-Z6XZWPXK.js} +17 -25
- package/dist/chunks/{chunk-EFQLEGWM.js → chunk-ZJBOM73S.js} +7 -8
- package/dist/chunks/{chunk-RAEABQNW.js → chunk-ZPZ7GNBT.js} +1 -0
- package/dist/cli/figure.js +59 -56
- package/dist/cli/fold.js +19 -17
- package/dist/deletionEdges.js +5 -7
- package/dist/facetGrid.js +2 -1
- package/dist/figure.js +45 -42
- package/dist/figureData.js +48 -44
- package/dist/figureScene.js +34 -29
- package/dist/figureSettings.js +19 -17
- package/dist/foldVariants.js +5 -3
- package/dist/gbzCut.js +12 -7
- package/dist/gbzJoin.js +2 -1
- package/dist/gbzWindow.js +11 -6
- package/dist/genes/genePins.js +6 -4
- package/dist/gfa/gfaConverter.js +7 -5
- package/dist/gfa/gfaTables.js +2 -1
- package/dist/gfa/graphTables.js +3 -3
- package/dist/graphLabels.js +8 -5
- package/dist/index.js +88 -85
- package/dist/labelLayout.js +12 -9
- package/dist/layout/anchoredLayout.js +8 -5
- package/dist/layout/drawnScale.js +1 -5
- package/dist/layout/forceCache.js +19 -17
- package/dist/layout/mergeRuns.js +5 -3
- package/dist/layout/orderedLayout.js +5 -2
- package/dist/layout/orientToReference.js +3 -2
- package/dist/layout/placeOffReference.js +7 -4
- package/dist/layout/referenceSeeds.js +6 -4
- package/dist/layout/sampleRowLayout.js +8 -5
- package/dist/layout/trimToWindow.js +6 -4
- package/dist/layout/tubeMapLayout.js +17 -19
- package/dist/layout/walkRowDraw.js +18 -17
- package/dist/layout/walkRowLayout.js +10 -6
- package/dist/layout/walkRows.js +9 -5
- package/dist/layout/walkStrip.js +21 -18
- package/dist/layoutModes.js +23 -20
- package/dist/nodeWidths.js +1 -3
- package/dist/pansn.js +5 -1
- package/dist/pathAnchoring.js +6 -4
- package/dist/pathColors.js +12 -9
- package/dist/pathVisits.js +3 -1
- package/dist/pipeline.js +18 -16
- package/dist/reference.js +5 -3
- package/dist/referenceRampCss.js +9 -17
- package/dist/referenceSpan.js +4 -2
- package/dist/referenceStrip.js +18 -14
- package/dist/renderer/Canvas2DRenderer.js +1 -1
- package/dist/renderer/GeometryBuilder.js +19 -14
- package/dist/renderer/svgCanvas.js +1 -1
- package/dist/tubeMap/axis.js +11 -6
- package/dist/tubeMap/bundle.js +16 -12
- package/dist/tubeMap/coarsen.js +20 -345
- package/dist/tubeMap/deviations.js +53 -23
- package/dist/tubeMap/draw.js +11 -8
- package/dist/tubeMap/frame.js +3 -2
- package/dist/tubeMap/genes.js +10 -7
- package/dist/tubeMap/mismatches.js +1 -1
- package/dist/tubeMap/nodeColors.js +18 -14
- package/dist/tubeMap/reads.js +1 -1
- package/dist/tubeMap/warp.js +2 -1
- package/dist/types/alleleProjection/projectAlleles.d.ts +1 -4
- package/dist/types/bubbles/bubbleHalos.d.ts +0 -2
- package/dist/types/bubbles/bubblesFromGraph.d.ts +6 -4
- package/dist/types/bubbles/classifyBubble.d.ts +2 -1
- package/dist/types/deletionEdges.d.ts +0 -8
- package/dist/types/figureScene.d.ts +17 -7
- package/dist/types/figureSettings.d.ts +2 -0
- package/dist/types/gbzCut.d.ts +4 -0
- package/dist/types/gbzWindow.d.ts +1 -0
- package/dist/types/gfa-core/gfaParser.d.ts +1 -1
- package/dist/types/graphLabels.d.ts +2 -1
- package/dist/types/layout/drawnScale.d.ts +0 -2
- package/dist/types/layout/referenceSeeds.d.ts +2 -1
- package/dist/types/layout/tubeMapLayout.d.ts +0 -7
- package/dist/types/layout/walkRowDraw.d.ts +0 -1
- package/dist/types/layout/walkRowLayout.d.ts +1 -0
- package/dist/types/layout/walkRows.d.ts +1 -0
- package/dist/types/nodeWidths.d.ts +0 -1
- package/dist/types/pansn.d.ts +9 -0
- package/dist/types/pathVisits.d.ts +6 -0
- package/dist/types/referenceRampCss.d.ts +4 -0
- package/dist/types/renderer/Canvas2DRenderer.d.ts +1 -0
- package/dist/types/renderer/GeometryBuilder.d.ts +3 -2
- package/dist/types/tubeMap/axis.d.ts +3 -1
- package/dist/types/tubeMap/coarsen.d.ts +3 -1
- package/dist/types/tubeMap/deviations.d.ts +2 -1
- package/dist/types/tubeMap/mismatches.d.ts +0 -1
- package/dist/types/tubeMap/warp.d.ts +2 -1
- package/dist/types/util/SpatialIndex.d.ts +1 -1
- package/dist/types/util/geometry.d.ts +4 -0
- package/dist/types/util/groups.d.ts +3 -0
- package/dist/types/util/hitDetection.d.ts +2 -2
- package/dist/types/util/partitionPoint.d.ts +1 -0
- package/dist/types/util/weakMemo.d.ts +1 -0
- package/dist/types/version.d.ts +1 -1
- package/dist/util/SpatialIndex.js +8 -5
- package/dist/util/edgeCurves.js +7 -4
- package/dist/util/geometry.js +3 -1
- package/dist/util/groups.js +10 -0
- package/dist/util/hitDetection.js +9 -6
- package/dist/util/partitionPoint.js +6 -0
- package/dist/util/weakMemo.js +6 -0
- package/dist/version.js +1 -1
- package/dist/viewport.js +19 -17
- package/dist/walkEncoding.js +18 -14
- package/dist/walkHighlight.js +19 -15
- package/dist/walkKey.js +9 -6
- package/package.json +2 -2
- package/dist/chunks/chunk-ZY2AFL4Y.js +0 -43
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GBZ_CUT_DEFAULTS,
|
|
3
|
+
NoReferenceSampleError,
|
|
4
|
+
aliasedSample,
|
|
3
5
|
cutWindowGFA,
|
|
4
6
|
haplotypeWanted,
|
|
5
7
|
referencePathQuery,
|
|
6
|
-
referenceSamplesOf
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
referenceSamplesOf
|
|
9
|
+
} from "./chunk-GIHTHYXY.js";
|
|
10
|
+
import {
|
|
11
|
+
panSNSample
|
|
12
|
+
} from "./chunk-4XWZNPQ2.js";
|
|
9
13
|
|
|
10
14
|
// src/gbzCut.ts
|
|
11
15
|
import { GBZBase } from "@gmod/gbz-base";
|
|
@@ -13,6 +17,9 @@ var HPRC_GBZ = {
|
|
|
13
17
|
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
18
|
index: "https://jbrowse.org/demos/hprc/hprc-v2.1-mc-grch38.haplotype-index.f3.db"
|
|
15
19
|
};
|
|
20
|
+
function gbzLocations({ db, index }) {
|
|
21
|
+
return db === "hprc" ? { db: HPRC_GBZ.db, index: index ?? HPRC_GBZ.index } : { db, index };
|
|
22
|
+
}
|
|
16
23
|
function haplotypeIndexBeside(db) {
|
|
17
24
|
const GBZ_DB = /\.gbz\.db$/i;
|
|
18
25
|
return GBZ_DB.test(db) ? db.replace(GBZ_DB, ".haplotype-index.db") : void 0;
|
|
@@ -36,18 +43,14 @@ async function openGbz(db, index) {
|
|
|
36
43
|
return { base, referenceSamples: await referenceSamplesOf(base) };
|
|
37
44
|
}
|
|
38
45
|
function referenceSample(ref, samples) {
|
|
39
|
-
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
} catch (e) {
|
|
46
|
-
if (ref) {
|
|
47
|
-
return ref;
|
|
48
|
-
}
|
|
49
|
-
throw e;
|
|
46
|
+
if (ref) {
|
|
47
|
+
return aliasedSample(panSNSample(ref), samples) ?? ref;
|
|
48
|
+
}
|
|
49
|
+
const first = samples[0];
|
|
50
|
+
if (first === void 0) {
|
|
51
|
+
throw new NoReferenceSampleError("", samples);
|
|
50
52
|
}
|
|
53
|
+
return first;
|
|
51
54
|
}
|
|
52
55
|
async function cutGbzRegion({ base, referenceSamples }, src, signal) {
|
|
53
56
|
const region = parseRegion(src.region);
|
|
@@ -70,6 +73,7 @@ async function cutGbzRegion({ base, referenceSamples }, src, signal) {
|
|
|
70
73
|
|
|
71
74
|
export {
|
|
72
75
|
HPRC_GBZ,
|
|
76
|
+
gbzLocations,
|
|
73
77
|
haplotypeIndexBeside,
|
|
74
78
|
parseRegion,
|
|
75
79
|
openGbz,
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import {
|
|
2
|
+
pathSteps
|
|
3
|
+
} from "./chunk-FW2R7UDZ.js";
|
|
4
|
+
import {
|
|
5
|
+
pathOrigin
|
|
6
|
+
} from "./chunk-B5X2RLJG.js";
|
|
7
|
+
import {
|
|
8
|
+
PathVisitsBuilder
|
|
9
|
+
} from "./chunk-ZPZ7GNBT.js";
|
|
10
|
+
import {
|
|
11
|
+
isBackbone
|
|
12
|
+
} from "./chunk-RJWPJCIB.js";
|
|
13
|
+
import {
|
|
14
|
+
partitionPoint
|
|
15
|
+
} from "./chunk-HOAIOEI7.js";
|
|
16
|
+
|
|
17
|
+
// src/tubeMap/coarsen.ts
|
|
18
|
+
function readWalk(path, steps) {
|
|
19
|
+
const runs = [];
|
|
20
|
+
const open = () => ({ a: -Infinity, b: Infinity, detour: [], bp: 0 });
|
|
21
|
+
const gaps = [open()];
|
|
22
|
+
for (const { node, strand } of steps) {
|
|
23
|
+
const gap = gaps.at(-1);
|
|
24
|
+
const last = runs.at(-1);
|
|
25
|
+
if (isBackbone(node)) {
|
|
26
|
+
const start = node.stable.start;
|
|
27
|
+
const end = start + node.length;
|
|
28
|
+
const inverted = strand !== (node.stable.strand ?? "+");
|
|
29
|
+
const joins = last !== void 0 && gap.detour.length === 0;
|
|
30
|
+
if (joins && !last.inverted && !inverted && last.end === start) {
|
|
31
|
+
last.end = end;
|
|
32
|
+
} else if (joins && last.inverted && inverted && last.start === end) {
|
|
33
|
+
last.start = start;
|
|
34
|
+
} else {
|
|
35
|
+
runs.push({ start, end, inverted });
|
|
36
|
+
gaps.push(open());
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
gap.detour.push({ node, strand });
|
|
40
|
+
gap.bp += node.length;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
runs.forEach((run, i) => {
|
|
44
|
+
gaps[i].b = run.start;
|
|
45
|
+
gaps[i + 1].a = run.end;
|
|
46
|
+
});
|
|
47
|
+
return { path, runs, gaps };
|
|
48
|
+
}
|
|
49
|
+
function isSmall(gap, sigma) {
|
|
50
|
+
return Number.isFinite(gap.a) && Number.isFinite(gap.b) && gap.b >= gap.a && Math.max(gap.b - gap.a, gap.bp) < sigma;
|
|
51
|
+
}
|
|
52
|
+
function strictlyInside(cuts, a, b) {
|
|
53
|
+
const i = partitionPoint(cuts.length, (j) => cuts[j] <= a);
|
|
54
|
+
return i < cuts.length && cuts[i] < b;
|
|
55
|
+
}
|
|
56
|
+
function referenceGaps(backbone) {
|
|
57
|
+
const cuts = /* @__PURE__ */ new Map();
|
|
58
|
+
for (let i = 1; i < backbone.length; i++) {
|
|
59
|
+
const prev = backbone[i - 1];
|
|
60
|
+
const node = backbone[i];
|
|
61
|
+
const end = prev.stable.start + prev.length;
|
|
62
|
+
if (end !== node.stable.start) {
|
|
63
|
+
cuts.set(end, "reference-gap");
|
|
64
|
+
cuts.set(node.stable.start, "reference-gap");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return cuts;
|
|
68
|
+
}
|
|
69
|
+
function findCuts(walks, sigma, cuts) {
|
|
70
|
+
const cut = (bp, cause) => {
|
|
71
|
+
if (Number.isFinite(bp) && !cuts.has(bp)) {
|
|
72
|
+
cuts.set(bp, cause);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
for (const { runs, gaps } of walks) {
|
|
76
|
+
const first = runs[0];
|
|
77
|
+
const last = runs.at(-1);
|
|
78
|
+
if (first && last) {
|
|
79
|
+
cut(first.start, "walk-end");
|
|
80
|
+
cut(last.end, "walk-end");
|
|
81
|
+
}
|
|
82
|
+
for (const run of runs) {
|
|
83
|
+
if (run.inverted && run.end - run.start >= sigma) {
|
|
84
|
+
cut(run.start, "inversion");
|
|
85
|
+
cut(run.end, "inversion");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const gap of gaps) {
|
|
89
|
+
if (gap.b < gap.a) {
|
|
90
|
+
cut(gap.a, "backward");
|
|
91
|
+
cut(gap.b, "backward");
|
|
92
|
+
} else if (!isSmall(gap, sigma)) {
|
|
93
|
+
cut(gap.a, "variant");
|
|
94
|
+
cut(gap.b, "variant");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const spans = walks.flatMap(({ runs, gaps }) => [
|
|
99
|
+
...gaps.filter((g) => isSmall(g, sigma)).map((g) => [g.a, g.b]),
|
|
100
|
+
...runs.filter((r) => r.inverted && r.end - r.start < sigma).map((r) => [r.start, r.end])
|
|
101
|
+
]);
|
|
102
|
+
for (let changed = true; changed; ) {
|
|
103
|
+
changed = false;
|
|
104
|
+
const sorted = [...cuts.keys()].sort((x, y) => x - y);
|
|
105
|
+
for (const [a, b] of spans) {
|
|
106
|
+
if (strictlyInside(sorted, a, b)) {
|
|
107
|
+
changed ||= !cuts.has(a) || !cuts.has(b);
|
|
108
|
+
cut(a, "overlap");
|
|
109
|
+
cut(b, "overlap");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return cuts;
|
|
114
|
+
}
|
|
115
|
+
function mergeReference(backbone, cuts) {
|
|
116
|
+
const merged = [];
|
|
117
|
+
let group = [];
|
|
118
|
+
const close = () => {
|
|
119
|
+
const first = group[0];
|
|
120
|
+
const last = group.at(-1);
|
|
121
|
+
if (first && last) {
|
|
122
|
+
const bp0 = first.stable.start;
|
|
123
|
+
const bp1 = last.stable.start + last.length;
|
|
124
|
+
const name = `${bp0}-${bp1}`;
|
|
125
|
+
merged.push({
|
|
126
|
+
node: {
|
|
127
|
+
id: `${name}+`,
|
|
128
|
+
name,
|
|
129
|
+
length: bp1 - bp0,
|
|
130
|
+
depth: 0,
|
|
131
|
+
stable: {
|
|
132
|
+
refName: first.stable.refName,
|
|
133
|
+
start: bp0,
|
|
134
|
+
rank: 0,
|
|
135
|
+
strand: "+"
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
members: group
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
group = [];
|
|
142
|
+
};
|
|
143
|
+
for (const node of backbone) {
|
|
144
|
+
if (cuts.has(node.stable.start)) {
|
|
145
|
+
close();
|
|
146
|
+
}
|
|
147
|
+
group.push(node);
|
|
148
|
+
}
|
|
149
|
+
close();
|
|
150
|
+
return merged;
|
|
151
|
+
}
|
|
152
|
+
function lastAtMost(items, key, x) {
|
|
153
|
+
return Math.max(0, partitionPoint(items.length, (i) => key(items[i]) <= x) - 1);
|
|
154
|
+
}
|
|
155
|
+
function coarsenTubeMap(graph, sigma) {
|
|
156
|
+
const backbone = graph.nodes.filter(isBackbone).sort((a, b) => a.stable.start - b.stable.start);
|
|
157
|
+
const paths = graph.paths ?? [];
|
|
158
|
+
if (backbone.length === 0 || paths.length === 0) {
|
|
159
|
+
return void 0;
|
|
160
|
+
}
|
|
161
|
+
const stepsOf = pathSteps(graph);
|
|
162
|
+
const walks = paths.map((p, i) => readWalk(p, stepsOf[i]));
|
|
163
|
+
const cuts = findCuts(walks, sigma, referenceGaps(backbone));
|
|
164
|
+
const sortedCuts = [...cuts.keys()].sort((x, y) => x - y);
|
|
165
|
+
const merged = mergeReference(backbone, cuts);
|
|
166
|
+
const mergedAt = (bp) => lastAtMost(merged, (m) => m.node.stable.start, bp);
|
|
167
|
+
const members = /* @__PURE__ */ new Map();
|
|
168
|
+
const coarseOf = /* @__PURE__ */ new Map();
|
|
169
|
+
for (const m of merged) {
|
|
170
|
+
members.set(
|
|
171
|
+
m.node.id,
|
|
172
|
+
m.members.map((n) => n.id)
|
|
173
|
+
);
|
|
174
|
+
for (const n of m.members) {
|
|
175
|
+
coarseOf.set(n.id, m.node.id);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const routes = /* @__PURE__ */ new Map();
|
|
179
|
+
const routeFor = (gap) => {
|
|
180
|
+
const key = `${gap.a} ${gap.b} ${gap.detour.map((s) => s.node.id + s.strand).join(",")}`;
|
|
181
|
+
let node = routes.get(key);
|
|
182
|
+
if (!node) {
|
|
183
|
+
const name = `r${routes.size}`;
|
|
184
|
+
node = {
|
|
185
|
+
id: `${name}+`,
|
|
186
|
+
name,
|
|
187
|
+
length: gap.bp,
|
|
188
|
+
depth: 0,
|
|
189
|
+
stable: {
|
|
190
|
+
refName: backbone[0].stable.refName,
|
|
191
|
+
start: Number.isFinite(gap.a) ? gap.a : gap.b,
|
|
192
|
+
rank: 1,
|
|
193
|
+
strand: "+"
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
routes.set(key, node);
|
|
197
|
+
members.set(
|
|
198
|
+
node.id,
|
|
199
|
+
gap.detour.map((s) => s.node.id)
|
|
200
|
+
);
|
|
201
|
+
for (const s of gap.detour) {
|
|
202
|
+
if (!coarseOf.has(s.node.id)) {
|
|
203
|
+
coarseOf.set(s.node.id, node.id);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return node;
|
|
208
|
+
};
|
|
209
|
+
const deviations = /* @__PURE__ */ new Map();
|
|
210
|
+
const coarsePaths = [];
|
|
211
|
+
const pathVisits = new PathVisitsBuilder();
|
|
212
|
+
const edges = /* @__PURE__ */ new Map();
|
|
213
|
+
const depth = /* @__PURE__ */ new Map();
|
|
214
|
+
for (const { path, runs, gaps } of walks) {
|
|
215
|
+
const steps = [];
|
|
216
|
+
const devs = [];
|
|
217
|
+
let continuing = false;
|
|
218
|
+
const append = (node, strand) => {
|
|
219
|
+
const last = steps.at(-1);
|
|
220
|
+
if (!(continuing && last?.node === node && last.strand === strand)) {
|
|
221
|
+
steps.push({ node, strand });
|
|
222
|
+
}
|
|
223
|
+
continuing = true;
|
|
224
|
+
};
|
|
225
|
+
const structural = (gap) => {
|
|
226
|
+
continuing = false;
|
|
227
|
+
if (gap.detour.length > 0) {
|
|
228
|
+
append(routeFor(gap), "+");
|
|
229
|
+
continuing = false;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
const fold = (gap) => {
|
|
233
|
+
if (gap.bp > 0 || gap.b > gap.a) {
|
|
234
|
+
devs.push({ start: gap.a, end: gap.b, bp: gap.bp });
|
|
235
|
+
}
|
|
236
|
+
const home = merged[mergedAt(gap.b > gap.a ? gap.a : gap.a - 1)];
|
|
237
|
+
for (const s of gap.detour) {
|
|
238
|
+
if (!coarseOf.has(s.node.id)) {
|
|
239
|
+
coarseOf.set(s.node.id, home.node.id);
|
|
240
|
+
members.get(home.node.id).push(s.node.id);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
runs.forEach((run, i) => {
|
|
245
|
+
const gap = gaps[i];
|
|
246
|
+
if (isSmall(gap, sigma) && !strictlyInside(sortedCuts, gap.a, gap.b)) {
|
|
247
|
+
fold(gap);
|
|
248
|
+
} else {
|
|
249
|
+
structural(gap);
|
|
250
|
+
}
|
|
251
|
+
const i0 = mergedAt(run.start);
|
|
252
|
+
const i1 = mergedAt(run.end - 1);
|
|
253
|
+
const small = run.end - run.start < sigma;
|
|
254
|
+
if (run.inverted && !small) {
|
|
255
|
+
continuing = false;
|
|
256
|
+
for (let j = i1; j >= i0; j--) {
|
|
257
|
+
append(merged[j].node, "-");
|
|
258
|
+
}
|
|
259
|
+
continuing = false;
|
|
260
|
+
} else {
|
|
261
|
+
if (run.inverted) {
|
|
262
|
+
devs.push({
|
|
263
|
+
start: run.start,
|
|
264
|
+
end: run.end,
|
|
265
|
+
bp: run.end - run.start,
|
|
266
|
+
inverted: true
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
for (let j = i0; j <= i1; j++) {
|
|
270
|
+
append(merged[j].node, "+");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
structural(gaps.at(-1));
|
|
275
|
+
const visitName = pathOrigin(path.name).name;
|
|
276
|
+
let pos = 0;
|
|
277
|
+
steps.forEach(({ node, strand }, i) => {
|
|
278
|
+
depth.set(node.id, (depth.get(node.id) ?? 0) + 1);
|
|
279
|
+
pathVisits.add(
|
|
280
|
+
node.name,
|
|
281
|
+
visitName,
|
|
282
|
+
path.sample ?? visitName,
|
|
283
|
+
pos,
|
|
284
|
+
strand === "-"
|
|
285
|
+
);
|
|
286
|
+
pos += node.length;
|
|
287
|
+
const next = steps[i + 1];
|
|
288
|
+
if (next) {
|
|
289
|
+
const key = `${node.id}${strand} ${next.node.id}${next.strand}`;
|
|
290
|
+
const edge = edges.get(key);
|
|
291
|
+
if (edge) {
|
|
292
|
+
edge.pathIds.push(path.name);
|
|
293
|
+
} else {
|
|
294
|
+
edges.set(key, {
|
|
295
|
+
from: node.id,
|
|
296
|
+
to: next.node.id,
|
|
297
|
+
fromStrand: strand,
|
|
298
|
+
toStrand: next.strand,
|
|
299
|
+
pathIds: [path.name]
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
coarsePaths.push({ ...path, nodeIds: steps.map((s) => s.node.id) });
|
|
305
|
+
deviations.set(path.name, devs);
|
|
306
|
+
}
|
|
307
|
+
const nodes = [...merged.map((m) => m.node), ...routes.values()].filter((n) => depth.has(n.id)).map((n) => ({ ...n, depth: depth.get(n.id) }));
|
|
308
|
+
return {
|
|
309
|
+
graph: {
|
|
310
|
+
...graph,
|
|
311
|
+
nodes,
|
|
312
|
+
edges: [...edges.values()],
|
|
313
|
+
paths: coarsePaths,
|
|
314
|
+
pathVisits: pathVisits.build(),
|
|
315
|
+
reads: void 0
|
|
316
|
+
},
|
|
317
|
+
members,
|
|
318
|
+
coarseOf,
|
|
319
|
+
deviations,
|
|
320
|
+
cuts
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export {
|
|
325
|
+
lastAtMost,
|
|
326
|
+
coarsenTubeMap
|
|
327
|
+
};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
partitionPoint
|
|
3
|
+
} from "./chunk-HOAIOEI7.js";
|
|
4
|
+
|
|
1
5
|
// src/tubeMap/warp.ts
|
|
2
6
|
var MAX_GAP_PX = 24;
|
|
3
7
|
var MAX_GAP_SHARE = 0.5;
|
|
@@ -55,17 +59,8 @@ function warpX(knots, tx) {
|
|
|
55
59
|
if (tx >= last.tx) {
|
|
56
60
|
return last.sx + (tx - last.tx);
|
|
57
61
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
while (hi - lo > 1) {
|
|
61
|
-
const mid = lo + hi >> 1;
|
|
62
|
-
if (knots[mid].tx <= tx) {
|
|
63
|
-
lo = mid;
|
|
64
|
-
} else {
|
|
65
|
-
hi = mid;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
const a = knots[lo];
|
|
62
|
+
const hi = 1 + partitionPoint(n - 2, (i) => knots[i + 1].tx <= tx);
|
|
63
|
+
const a = knots[hi - 1];
|
|
69
64
|
const b = knots[hi];
|
|
70
65
|
const span = b.tx - a.tx;
|
|
71
66
|
return span > 0 ? a.sx + (tx - a.tx) / span * (b.sx - a.sx) : a.sx;
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
pathOrigin,
|
|
6
6
|
surveyPaths
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-B5X2RLJG.js";
|
|
8
8
|
|
|
9
9
|
// src/gfa/gfaConverter.ts
|
|
10
|
-
function surveySegments(gfaGraph) {
|
|
10
|
+
function surveySegments(gfaGraph, pathSteps) {
|
|
11
11
|
const canonical = /* @__PURE__ */ new Map();
|
|
12
12
|
const traversals = /* @__PURE__ */ new Map();
|
|
13
13
|
function claim(id, strand) {
|
|
@@ -26,36 +26,35 @@ function surveySegments(gfaGraph) {
|
|
|
26
26
|
claim(link.source, link.strand1 === "-" ? "-" : "+");
|
|
27
27
|
claim(link.target, link.strand2 === "-" ? "-" : "+");
|
|
28
28
|
}
|
|
29
|
-
for (const
|
|
30
|
-
for (const
|
|
31
|
-
traverse(
|
|
29
|
+
for (const { steps } of pathSteps) {
|
|
30
|
+
for (const step of steps) {
|
|
31
|
+
traverse(step.id, step.strand);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
for (const walk of gfaGraph.walks) {
|
|
35
|
-
for (const
|
|
36
|
-
traverse(
|
|
35
|
+
for (const step of walk.segments) {
|
|
36
|
+
traverse(step.id, step.strand);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
return { canonical, traversals };
|
|
40
40
|
}
|
|
41
41
|
var walkStart = (w) => w.start === -1 ? 0 : w.start;
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
function stepsOfPath(p) {
|
|
43
|
+
return {
|
|
44
|
+
...pathOrigin(p.name),
|
|
45
|
+
steps: p.path.split(",").map((segment) => ({
|
|
46
|
+
id: segment.slice(0, -1),
|
|
47
|
+
strand: segment.endsWith("-") ? "-" : "+"
|
|
48
|
+
}))
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function anchorablePaths(gfaGraph, pathSteps) {
|
|
44
52
|
return [
|
|
45
|
-
...
|
|
46
|
-
...pathOrigin(p.name),
|
|
47
|
-
steps: p.path.split(",").map((segment) => ({
|
|
48
|
-
id: segment.slice(0, -1),
|
|
49
|
-
strand: segment.endsWith("-") ? "-" : "+"
|
|
50
|
-
}))
|
|
51
|
-
})),
|
|
53
|
+
...pathSteps,
|
|
52
54
|
...gfaGraph.walks.map((w) => ({
|
|
53
55
|
name: `${w.sample}#${w.haplotype}#${w.contig}`,
|
|
54
56
|
start: walkStart(w),
|
|
55
|
-
steps: w.segments
|
|
56
|
-
id: s.id,
|
|
57
|
-
strand: s.strand === "-" ? "-" : "+"
|
|
58
|
-
}))
|
|
57
|
+
steps: w.segments
|
|
59
58
|
}))
|
|
60
59
|
];
|
|
61
60
|
}
|
|
@@ -85,7 +84,8 @@ function makeNode(gfaNode, strand, depth) {
|
|
|
85
84
|
function convertGFAToGraph(gfaGraph, name = "Imported GFA") {
|
|
86
85
|
const nodes = [];
|
|
87
86
|
const edges = [];
|
|
88
|
-
const
|
|
87
|
+
const pathSteps = gfaGraph.paths.map(stepsOfPath);
|
|
88
|
+
const { canonical, traversals } = surveySegments(gfaGraph, pathSteps);
|
|
89
89
|
const nodeIds = /* @__PURE__ */ new Map();
|
|
90
90
|
const nodeId = (segmentId) => {
|
|
91
91
|
let id = nodeIds.get(segmentId);
|
|
@@ -95,12 +95,12 @@ function convertGFAToGraph(gfaGraph, name = "Imported GFA") {
|
|
|
95
95
|
}
|
|
96
96
|
return id;
|
|
97
97
|
};
|
|
98
|
-
const
|
|
98
|
+
const lengths = /* @__PURE__ */ new Map();
|
|
99
99
|
for (const gfaNode of gfaGraph.nodes) {
|
|
100
|
-
if (
|
|
100
|
+
if (lengths.has(gfaNode.id)) {
|
|
101
101
|
continue;
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
lengths.set(gfaNode.id, gfaNode.length);
|
|
104
104
|
const depth = statedDepth(gfaNode) ?? Math.max(traversals.get(gfaNode.id) ?? 1, 1);
|
|
105
105
|
nodes.push(makeNode(gfaNode, canonical.get(gfaNode.id) ?? "+", depth));
|
|
106
106
|
}
|
|
@@ -137,15 +137,12 @@ function convertGFAToGraph(gfaGraph, name = "Imported GFA") {
|
|
|
137
137
|
pairPaths(nodeIds2[i], nodeIds2[i + 1])?.add(name2);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
});
|
|
147
|
-
recordPathEdges(nodeIds2, gfaPath.name);
|
|
148
|
-
}
|
|
140
|
+
gfaGraph.paths.forEach(({ name: name2 }, i) => {
|
|
141
|
+
const { start, steps } = pathSteps[i];
|
|
142
|
+
const nodeIds2 = steps.map((step) => nodeId(step.id));
|
|
143
|
+
paths.push({ name: name2, nodeIds: nodeIds2, start });
|
|
144
|
+
recordPathEdges(nodeIds2, name2);
|
|
145
|
+
});
|
|
149
146
|
for (const walk of gfaGraph.walks) {
|
|
150
147
|
const nodeIds2 = walk.segments.map((seg) => nodeId(seg.id));
|
|
151
148
|
const name2 = `${walk.sample}#${walk.haplotype}#${walk.contig}`;
|
|
@@ -165,8 +162,10 @@ function convertGFAToGraph(gfaGraph, name = "Imported GFA") {
|
|
|
165
162
|
edge.pathIds = [...pathIds];
|
|
166
163
|
}
|
|
167
164
|
});
|
|
168
|
-
const
|
|
169
|
-
|
|
165
|
+
const anchoring = gfaGraph.paths.length > 0 || gfaGraph.walks.length > 0 ? surveyPaths(
|
|
166
|
+
anchorablePaths(gfaGraph, pathSteps),
|
|
167
|
+
(id) => lengths.get(id) ?? 0
|
|
168
|
+
) : void 0;
|
|
170
169
|
return {
|
|
171
170
|
name,
|
|
172
171
|
nodes,
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EdgeSpatialIndex,
|
|
3
3
|
SpatialIndex
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3VCKBSML.js";
|
|
5
|
+
import {
|
|
6
|
+
weakMemo
|
|
7
|
+
} from "./chunk-HMXCN6PG.js";
|
|
5
8
|
import {
|
|
6
9
|
pathRibbonOffsets,
|
|
7
10
|
translateCurves,
|
|
8
11
|
yToXOf
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-UBQSRCWR.js";
|
|
10
13
|
|
|
11
14
|
// src/util/hitDetection.ts
|
|
12
15
|
function distanceToSegment(px, py, x1, y1, x2, y2) {
|
|
@@ -19,40 +22,26 @@ function distanceToSegment(px, py, x1, y1, x2, y2) {
|
|
|
19
22
|
const t = Math.max(0, Math.min(1, ((px - x1) * dx + (py - y1) * dy) / lenSq));
|
|
20
23
|
return Math.hypot(px - (x1 + t * dx), py - (y1 + t * dy));
|
|
21
24
|
}
|
|
22
|
-
function distanceToCubicBezier(px, py,
|
|
25
|
+
function distanceToCubicBezier(px, py, c) {
|
|
23
26
|
let minDist = Infinity;
|
|
24
27
|
const samples = 20;
|
|
25
|
-
let lastX =
|
|
26
|
-
let lastY =
|
|
28
|
+
let lastX = c.x0;
|
|
29
|
+
let lastY = c.y0;
|
|
27
30
|
for (let i = 1; i <= samples; i++) {
|
|
28
31
|
const t = i / samples;
|
|
29
32
|
const u = 1 - t;
|
|
30
|
-
const bx = u * u * u *
|
|
31
|
-
const by = u * u * u *
|
|
33
|
+
const bx = u * u * u * c.x0 + 3 * u * u * t * c.cx0 + 3 * u * t * t * c.cx1 + t * t * t * c.x1;
|
|
34
|
+
const by = u * u * u * c.y0 + 3 * u * u * t * c.cy0 + 3 * u * t * t * c.cy1 + t * t * t * c.y1;
|
|
32
35
|
minDist = Math.min(minDist, distanceToSegment(px, py, lastX, lastY, bx, by));
|
|
33
36
|
lastX = bx;
|
|
34
37
|
lastY = by;
|
|
35
38
|
}
|
|
36
39
|
return minDist;
|
|
37
40
|
}
|
|
38
|
-
function distanceToBezierCurve(px, py, c) {
|
|
39
|
-
return distanceToCubicBezier(
|
|
40
|
-
px,
|
|
41
|
-
py,
|
|
42
|
-
c.x0,
|
|
43
|
-
c.y0,
|
|
44
|
-
c.cx0,
|
|
45
|
-
c.cy0,
|
|
46
|
-
c.cx1,
|
|
47
|
-
c.cy1,
|
|
48
|
-
c.x1,
|
|
49
|
-
c.y1
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
41
|
function distanceToEdgeCurves(px, py, curves, yToX = 1) {
|
|
53
42
|
let minDist = Infinity;
|
|
54
43
|
for (const c of curves) {
|
|
55
|
-
const d =
|
|
44
|
+
const d = distanceToCubicBezier(
|
|
56
45
|
px,
|
|
57
46
|
py,
|
|
58
47
|
yToX === 1 ? c : {
|
|
@@ -72,45 +61,39 @@ function distanceToEdgeCurves(px, py, curves, yToX = 1) {
|
|
|
72
61
|
}
|
|
73
62
|
return minDist;
|
|
74
63
|
}
|
|
75
|
-
var nodeCache =
|
|
64
|
+
var nodeCache = weakMemo();
|
|
76
65
|
function getSpatialIndex(nodePositions, version) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
nodeCache.set(nodePositions, { version, index });
|
|
83
|
-
return index;
|
|
66
|
+
return nodeCache(
|
|
67
|
+
nodePositions,
|
|
68
|
+
[version],
|
|
69
|
+
() => new SpatialIndex(nodePositions)
|
|
70
|
+
);
|
|
84
71
|
}
|
|
85
|
-
var edgeCache =
|
|
72
|
+
var edgeCache = weakMemo();
|
|
86
73
|
function getEdgeSpatialIndex(nodePositions, graph, drawPaths, axis, version, deletions, routes, stranded = false) {
|
|
87
|
-
|
|
88
|
-
if (cached?.graph === graph && cached.drawPaths === drawPaths && cached.scaleX === axis.scaleX && cached.scaleY === axis.scaleY && cached.version === version && cached.deletions === deletions && cached.routes === routes && cached.stranded === stranded) {
|
|
89
|
-
return cached.index;
|
|
90
|
-
}
|
|
91
|
-
const index = new EdgeSpatialIndex(
|
|
74
|
+
return edgeCache(
|
|
92
75
|
nodePositions,
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
76
|
+
[
|
|
77
|
+
graph,
|
|
78
|
+
drawPaths,
|
|
79
|
+
axis.scaleX,
|
|
80
|
+
axis.scaleY,
|
|
81
|
+
version,
|
|
82
|
+
deletions,
|
|
83
|
+
routes,
|
|
84
|
+
stranded
|
|
85
|
+
],
|
|
86
|
+
() => new EdgeSpatialIndex(
|
|
87
|
+
nodePositions,
|
|
88
|
+
graph,
|
|
89
|
+
drawPaths,
|
|
90
|
+
axis,
|
|
91
|
+
deletions,
|
|
92
|
+
version,
|
|
93
|
+
routes,
|
|
94
|
+
stranded
|
|
95
|
+
)
|
|
101
96
|
);
|
|
102
|
-
edgeCache.set(nodePositions, {
|
|
103
|
-
graph,
|
|
104
|
-
drawPaths,
|
|
105
|
-
scaleX: axis.scaleX,
|
|
106
|
-
scaleY: axis.scaleY,
|
|
107
|
-
version,
|
|
108
|
-
index,
|
|
109
|
-
deletions,
|
|
110
|
-
routes,
|
|
111
|
-
stranded
|
|
112
|
-
});
|
|
113
|
-
return index;
|
|
114
97
|
}
|
|
115
98
|
var MIN_NODE_REACH_PX = 5;
|
|
116
99
|
function findHoveredNode(nodePositions, graphX, graphY, axis, version = 0, ink) {
|