@jbrowse/bandage-core 11.8.0 → 11.10.0
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/bubbles/bubbleHalos.js +6 -6
- package/dist/bubbles/classifyBubble.js +5 -5
- package/dist/bubbles/superbubbles.js +7 -7
- package/dist/chunks/{chunk-S4CH434Z.js → chunk-2A6Z2DHF.js} +1 -1
- package/dist/chunks/{chunk-6MD4VS2F.js → chunk-2MXFG3W7.js} +1 -1
- package/dist/chunks/{chunk-L2RQV23D.js → chunk-2NCZ5YYN.js} +1 -1
- package/dist/chunks/{chunk-ZKIH2USC.js → chunk-337LZP7C.js} +1 -1
- package/dist/chunks/{chunk-2RCKHCF7.js → chunk-3DHGSHC3.js} +1 -1
- package/dist/chunks/{chunk-3CXZUC2Y.js → chunk-3GORESBG.js} +1 -1
- package/dist/chunks/{chunk-R4XCTRIU.js → chunk-4BYGFDQB.js} +1 -1
- package/dist/chunks/{chunk-NHOXLUIL.js → chunk-4JDO7ZLN.js} +2 -2
- package/dist/chunks/{chunk-7GDNDQD7.js → chunk-4KBZ7WPP.js} +176 -101
- package/dist/chunks/{chunk-2H3ALI6L.js → chunk-53DZE3SA.js} +184 -161
- package/dist/chunks/{chunk-YF6T33PU.js → chunk-54C73ICS.js} +37 -17
- package/dist/chunks/{chunk-U6JPSXJ3.js → chunk-55DRWHBF.js} +9 -9
- package/dist/chunks/{chunk-4OVIUCSB.js → chunk-77O67GIB.js} +1 -1
- package/dist/chunks/{chunk-7PEYA3NA.js → chunk-7YSIP3O2.js} +2 -2
- package/dist/chunks/{chunk-LA6JHEVV.js → chunk-ALOF5SOT.js} +1 -1
- package/dist/chunks/{chunk-3XYLEK4H.js → chunk-ARXDNQLF.js} +1 -1
- package/dist/chunks/{chunk-6CXLLJ2C.js → chunk-AURNOR27.js} +3 -3
- package/dist/chunks/{chunk-G4WQBRDS.js → chunk-BDS5VZYZ.js} +3 -3
- package/dist/chunks/{chunk-MO4DIRHD.js → chunk-CHGTUO3C.js} +13 -13
- package/dist/chunks/{chunk-X5ULFAMM.js → chunk-HEYIAMTC.js} +2 -2
- package/dist/chunks/{chunk-S7BCZVRK.js → chunk-HIN56TLA.js} +1 -1
- package/dist/chunks/{chunk-YIWN32ZX.js → chunk-HNNP5QUN.js} +1 -1
- package/dist/chunks/{chunk-XOIYBEU7.js → chunk-I53QYITQ.js} +1 -1
- package/dist/chunks/{chunk-SDDMV2MM.js → chunk-IZKM4NY7.js} +1 -1
- package/dist/chunks/{chunk-SIXFXXRI.js → chunk-J7RNXBXA.js} +3 -3
- package/dist/chunks/{chunk-735MPLUL.js → chunk-JJV2GT2Z.js} +22 -14
- package/dist/chunks/{chunk-S3ICPPXC.js → chunk-JVT3XTKN.js} +3 -3
- package/dist/chunks/{chunk-J4PDHWP2.js → chunk-KKHXMJEE.js} +1 -1
- package/dist/chunks/{chunk-22ZMVREZ.js → chunk-NAYS472K.js} +1 -1
- package/dist/chunks/{chunk-OIOAK7BS.js → chunk-NWEVR2OQ.js} +1 -1
- package/dist/chunks/{chunk-VSRRIFRF.js → chunk-P2GJBFNA.js} +1 -1
- package/dist/chunks/{chunk-N2GAA7RB.js → chunk-RT4U3DH3.js} +1 -1
- package/dist/chunks/{chunk-AXE3RR7J.js → chunk-S6E3PMH7.js} +1 -1
- package/dist/chunks/{chunk-NQWEYJDD.js → chunk-SPEB75UH.js} +1 -1
- package/dist/chunks/{chunk-4YPCUVMC.js → chunk-SZYFZNCO.js} +2 -2
- package/dist/chunks/{chunk-G3GLGDKV.js → chunk-TQ26XEFL.js} +2 -2
- package/dist/chunks/{chunk-N4AJV4GH.js → chunk-UVRCXTBY.js} +37 -10
- package/dist/chunks/{chunk-YEDZ37PH.js → chunk-VNCHWWLG.js} +1 -1
- package/dist/chunks/{chunk-JKIAHYAW.js → chunk-VQ353UDK.js} +1 -1
- package/dist/chunks/{chunk-R3NPBUKT.js → chunk-YQAZNH37.js} +7 -7
- package/dist/cli/figure.js +28 -28
- package/dist/cli/fold.js +6 -6
- package/dist/deletionEdges.js +2 -2
- package/dist/figure.js +24 -24
- package/dist/figureData.js +22 -22
- package/dist/figureScene.js +15 -15
- package/dist/figureSettings.js +6 -6
- package/dist/foldVariants.js +2 -2
- package/dist/genes/genePins.js +3 -3
- package/dist/graphLabels.js +4 -4
- package/dist/index.js +38 -38
- package/dist/labelLayout.js +8 -8
- package/dist/layout/forceCache.js +6 -6
- package/dist/layout/mergeRuns.js +2 -2
- package/dist/layout/orientToReference.js +2 -2
- package/dist/layout/tubeMapLayout.js +7 -7
- package/dist/layout/walkRowDraw.js +9 -9
- package/dist/layout/walkStrip.js +10 -10
- package/dist/layoutModes.js +8 -8
- package/dist/pathColors.js +5 -5
- package/dist/pipeline.js +5 -5
- package/dist/referenceStrip.js +9 -9
- package/dist/renderer/GeometryBuilder.js +8 -8
- package/dist/renderer/walkLanes.js +4 -2
- package/dist/tubeMap/axis.js +5 -5
- package/dist/tubeMap/bundle.js +8 -8
- package/dist/tubeMap/coarsen.js +8 -8
- package/dist/tubeMap/deviations.js +9 -9
- package/dist/tubeMap/draw.js +3 -3
- package/dist/tubeMap/genes.js +6 -6
- package/dist/tubeMap/nodeColors.js +9 -9
- package/dist/tubeMap/reads.js +2 -2
- package/dist/types/renderer/walkLanes.d.ts +19 -2
- package/dist/types/util/geometry.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/walkEncoding.d.ts +8 -2
- package/dist/types/walkHighlight.d.ts +2 -0
- package/dist/util/SpatialIndex.js +4 -4
- package/dist/util/edgeCurves.js +3 -3
- package/dist/util/geometry.js +1 -1
- package/dist/util/hitDetection.js +5 -5
- package/dist/version.js +1 -1
- package/dist/viewport.js +6 -6
- package/dist/walkEncoding.js +13 -11
- package/dist/walkHighlight.js +10 -10
- package/dist/walkKey.js +5 -5
- package/package.json +1 -1
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
LANE_SMOOTHING_PX,
|
|
3
2
|
THREAD_PITCH_PX,
|
|
4
3
|
THREAD_PX,
|
|
5
|
-
THREAD_REACH_PX,
|
|
6
|
-
THREAD_TAPER_PX,
|
|
7
4
|
bandScale,
|
|
8
|
-
bandSpans,
|
|
9
5
|
bandWidthPx,
|
|
10
|
-
laneLines,
|
|
11
|
-
laneRuns,
|
|
12
6
|
laneSlideAt,
|
|
7
|
+
liftLanes,
|
|
13
8
|
slotCentres,
|
|
14
|
-
threadsPasses
|
|
15
|
-
|
|
16
|
-
} from "./chunk-7GDNDQD7.js";
|
|
9
|
+
threadsPasses
|
|
10
|
+
} from "./chunk-4KBZ7WPP.js";
|
|
17
11
|
import {
|
|
18
12
|
abgrToCssRgba,
|
|
19
13
|
fadeAbgr,
|
|
@@ -26,13 +20,13 @@ import {
|
|
|
26
20
|
} from "./chunk-GQZVR5DW.js";
|
|
27
21
|
import {
|
|
28
22
|
baseEdgeCurves
|
|
29
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-P2GJBFNA.js";
|
|
30
24
|
import {
|
|
31
25
|
PATH_LIGHTNESS,
|
|
32
26
|
PATH_SATURATION,
|
|
33
27
|
nameHue,
|
|
34
28
|
pathHueAt
|
|
35
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-VQ353UDK.js";
|
|
36
30
|
import {
|
|
37
31
|
meanDepth,
|
|
38
32
|
nodeWidthPx,
|
|
@@ -41,6 +35,9 @@ import {
|
|
|
41
35
|
import {
|
|
42
36
|
referenceMidpoints
|
|
43
37
|
} from "./chunk-VX656OAZ.js";
|
|
38
|
+
import {
|
|
39
|
+
weakMemo
|
|
40
|
+
} from "./chunk-HMXCN6PG.js";
|
|
44
41
|
import {
|
|
45
42
|
dashSpans,
|
|
46
43
|
pathRibbonOffsets,
|
|
@@ -49,7 +46,7 @@ import {
|
|
|
49
46
|
strandSides,
|
|
50
47
|
translateCurves,
|
|
51
48
|
yToXOf
|
|
52
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-JJV2GT2Z.js";
|
|
53
50
|
import {
|
|
54
51
|
pushTo
|
|
55
52
|
} from "./chunk-BSOZW3FC.js";
|
|
@@ -194,6 +191,8 @@ function normal(a, b) {
|
|
|
194
191
|
const len = Math.hypot(dx, dy);
|
|
195
192
|
return len > 0 ? { nx: -dy / len, ny: dx / len } : void 0;
|
|
196
193
|
}
|
|
194
|
+
var MITRE_LIMIT = 0.1;
|
|
195
|
+
var LONGEST_NORMAL = 1 / Math.sqrt(MITRE_LIMIT);
|
|
197
196
|
function pointNormalsOf(rawPoints, yToX = 1) {
|
|
198
197
|
const points = yToX === 1 ? rawPoints : rawPoints.map((p) => ({ x: p.x, y: p.y * yToX }));
|
|
199
198
|
return points.map((p, i) => {
|
|
@@ -203,16 +202,20 @@ function pointNormalsOf(rawPoints, yToX = 1) {
|
|
|
203
202
|
const nx = (before.nx + after.nx) / 2;
|
|
204
203
|
const ny = (before.ny + after.ny) / 2;
|
|
205
204
|
const dot = before.nx * nx + before.ny * ny;
|
|
206
|
-
return dot >
|
|
205
|
+
return dot > MITRE_LIMIT ? { nx: nx / dot, ny: ny / dot } : { nx, ny };
|
|
207
206
|
}
|
|
208
207
|
return before ?? after ?? { nx: 0, ny: 0 };
|
|
209
208
|
});
|
|
210
209
|
}
|
|
211
210
|
function offsetPolyline(points, normals, distance, yToX = 1) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
211
|
+
const out = new Array(points.length);
|
|
212
|
+
for (let i = 0; i < points.length; i++) {
|
|
213
|
+
out[i] = {
|
|
214
|
+
x: points[i].x + normals[i].nx * distance,
|
|
215
|
+
y: points[i].y + normals[i].ny * distance / yToX
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return out;
|
|
216
219
|
}
|
|
217
220
|
function hslToRgb(h, s, l) {
|
|
218
221
|
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
@@ -413,13 +416,13 @@ function isPolylineInBounds(segments, bounds) {
|
|
|
413
416
|
}
|
|
414
417
|
return hit;
|
|
415
418
|
}
|
|
416
|
-
function isBezierInBounds(curves, bounds) {
|
|
419
|
+
function isBezierInBounds(curves, bounds, growX = 0, growY = 0) {
|
|
417
420
|
for (const c of curves) {
|
|
418
421
|
const cMinX = Math.min(c.x0, c.cx0, c.cx1, c.x1);
|
|
419
422
|
const cMaxX = Math.max(c.x0, c.cx0, c.cx1, c.x1);
|
|
420
423
|
const cMinY = Math.min(c.y0, c.cy0, c.cy1, c.y1);
|
|
421
424
|
const cMaxY = Math.max(c.y0, c.cy0, c.cy1, c.y1);
|
|
422
|
-
if (cMaxX >= bounds.minX && cMinX <= bounds.maxX && cMaxY >= bounds.minY && cMinY <= bounds.maxY) {
|
|
425
|
+
if (cMaxX >= bounds.minX - growX && cMinX <= bounds.maxX + growX && cMaxY >= bounds.minY - growY && cMinY <= bounds.maxY + growY) {
|
|
423
426
|
return true;
|
|
424
427
|
}
|
|
425
428
|
}
|
|
@@ -465,6 +468,24 @@ function pathSlotsOf(graph) {
|
|
|
465
468
|
}
|
|
466
469
|
return slots;
|
|
467
470
|
}
|
|
471
|
+
var lanesCache = weakMemo();
|
|
472
|
+
var linksCache = /* @__PURE__ */ new WeakMap();
|
|
473
|
+
function linksOf(graph) {
|
|
474
|
+
let links = linksCache.get(graph);
|
|
475
|
+
if (!links) {
|
|
476
|
+
links = /* @__PURE__ */ new Map();
|
|
477
|
+
for (const { from, to } of graph.edges) {
|
|
478
|
+
let out = links.get(from);
|
|
479
|
+
if (!out) {
|
|
480
|
+
out = /* @__PURE__ */ new Set();
|
|
481
|
+
links.set(from, out);
|
|
482
|
+
}
|
|
483
|
+
out.add(to);
|
|
484
|
+
}
|
|
485
|
+
linksCache.set(graph, links);
|
|
486
|
+
}
|
|
487
|
+
return links;
|
|
488
|
+
}
|
|
468
489
|
function buildGeometry(options) {
|
|
469
490
|
const {
|
|
470
491
|
nodePositions,
|
|
@@ -520,53 +541,26 @@ function buildGeometry(options) {
|
|
|
520
541
|
const threaded = threadsPasses(liftedWalks);
|
|
521
542
|
const lanePasses = liftedWalks.map((w) => w.mostPasses);
|
|
522
543
|
const thinned = threaded ? bandScale(lanePasses) : 1;
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
nodePositions,
|
|
526
|
-
yToX,
|
|
527
|
-
LANE_SMOOTHING_PX * worldPerScreenPx
|
|
528
|
-
) : void 0;
|
|
529
|
-
const lines = runs ? laneLines(
|
|
530
|
-
runs,
|
|
531
|
-
nodePositions,
|
|
532
|
-
yToX,
|
|
533
|
-
LANE_SMOOTHING_PX * worldPerScreenPx,
|
|
534
|
-
bandWidthPx(lanePasses) * thinned * worldPerScreenPx,
|
|
535
|
-
threaded
|
|
536
|
-
) : void 0;
|
|
537
|
-
const threads = threaded ? liftedWalks.map(
|
|
538
|
-
(w) => walkThreads(
|
|
539
|
-
w.route,
|
|
540
|
-
w.passes,
|
|
541
|
-
nodePositions,
|
|
542
|
-
yToX,
|
|
543
|
-
THREAD_REACH_PX * worldPerScreenPx
|
|
544
|
-
)
|
|
545
|
-
) : void 0;
|
|
546
|
-
const spanField = runs && threads ? bandSpans(
|
|
547
|
-
runs,
|
|
548
|
-
threads.map((t) => t.span),
|
|
549
|
-
{
|
|
550
|
-
reach: THREAD_REACH_PX * worldPerScreenPx,
|
|
551
|
-
taper: THREAD_TAPER_PX * worldPerScreenPx
|
|
552
|
-
}
|
|
544
|
+
const fields = highlight && liftedWalks.length > 1 ? lanesCache(
|
|
545
|
+
highlight,
|
|
546
|
+
[nodePositions, version, axis.scaleX, axis.scaleY],
|
|
547
|
+
() => liftLanes(liftedWalks, nodePositions, yToX, worldPerScreenPx)
|
|
553
548
|
) : void 0;
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
|
|
549
|
+
const lines = fields?.lines;
|
|
550
|
+
const threads = fields?.threads;
|
|
551
|
+
const spanField = fields?.spans;
|
|
552
|
+
const plainCentres = threaded ? slotCentres(lanePasses, lanePasses) : [];
|
|
557
553
|
const centresByNode = /* @__PURE__ */ new Map();
|
|
558
|
-
const
|
|
559
|
-
if (!threaded) {
|
|
560
|
-
return (lane - (liftedWalks.length - 1) / 2) * laneWidth;
|
|
561
|
-
}
|
|
554
|
+
const centresOf = (nodeId) => {
|
|
562
555
|
let centres = centresByNode.get(nodeId);
|
|
563
556
|
if (!centres) {
|
|
564
557
|
const spans = spanField?.get(nodeId);
|
|
565
|
-
centres = slotCentres(spans
|
|
558
|
+
centres = spans ? slotCentres(spans.slot, lanePasses, spans.held) : plainCentres;
|
|
566
559
|
centresByNode.set(nodeId, centres);
|
|
567
560
|
}
|
|
568
|
-
return
|
|
561
|
+
return centres;
|
|
569
562
|
};
|
|
563
|
+
const laneOffset = (nodeId, laneWidth, lane, pass) => threaded ? (centresOf(nodeId)[lane] + pass * THREAD_PITCH_PX) * thinned : (lane - (liftedWalks.length - 1) / 2) * laneWidth;
|
|
570
564
|
const laneHalfWidth = (laneWidth) => threaded ? THREAD_PX / 2 * thinned : laneWidth / 2;
|
|
571
565
|
const laneNormals = /* @__PURE__ */ new Map();
|
|
572
566
|
const laneNormalsOf = (nodeId, segments) => {
|
|
@@ -579,7 +573,55 @@ function buildGeometry(options) {
|
|
|
579
573
|
return normals;
|
|
580
574
|
};
|
|
581
575
|
const laneWidths = /* @__PURE__ */ new Map();
|
|
576
|
+
const laneWidthOf = (id) => {
|
|
577
|
+
let width = laneWidths.get(id);
|
|
578
|
+
if (width === void 0) {
|
|
579
|
+
const node = nodeById.get(id);
|
|
580
|
+
width = walkLaneWidthPx(
|
|
581
|
+
node ? nodeWidthPx(node, contigThickness, nodeWidth, depthNorm) : contigThickness,
|
|
582
|
+
liftedWalks.length
|
|
583
|
+
);
|
|
584
|
+
laneWidths.set(id, width);
|
|
585
|
+
}
|
|
586
|
+
return width;
|
|
587
|
+
};
|
|
582
588
|
const laneShiftOf = (nodeId, index) => lines?.shifts.get(nodeId)?.[index] ?? NO_SHIFT;
|
|
589
|
+
const laneEndOf = (id, segments, atStart) => {
|
|
590
|
+
const at = atStart ? 0 : segments.length - 1;
|
|
591
|
+
return {
|
|
592
|
+
id,
|
|
593
|
+
laneWidth: laneWidthOf(id),
|
|
594
|
+
normal: laneNormalsOf(id, segments)[at] ?? { nx: 0, ny: 0 },
|
|
595
|
+
shift: laneShiftOf(id, at)
|
|
596
|
+
};
|
|
597
|
+
};
|
|
598
|
+
const lanesMayShow = (curves, fromId) => {
|
|
599
|
+
if (!viewportBounds) {
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
const offset = threaded ? bandWidthPx(lanePasses) * thinned : (liftedWalks.length - 1) / 2 * laneWidthOf(fromId);
|
|
603
|
+
const reach = LONGEST_NORMAL * offset * worldPerScreenPx;
|
|
604
|
+
return isBezierInBounds(
|
|
605
|
+
curves,
|
|
606
|
+
viewportBounds,
|
|
607
|
+
reach + (fields?.furthestShift.dx ?? 0),
|
|
608
|
+
reach / yToX + (fields?.furthestShift.dy ?? 0)
|
|
609
|
+
);
|
|
610
|
+
};
|
|
611
|
+
const threadPairs = (lane, from, to) => {
|
|
612
|
+
const own = threads?.[lane]?.linkThreads;
|
|
613
|
+
if (!own?.size) {
|
|
614
|
+
return FIRST_THREADS;
|
|
615
|
+
}
|
|
616
|
+
const ahead = own.get(from)?.get(to);
|
|
617
|
+
const back = linksOf(graph).get(to)?.has(from) ? void 0 : own.get(to)?.get(from);
|
|
618
|
+
if (!back) {
|
|
619
|
+
return ahead ?? FIRST_THREADS;
|
|
620
|
+
}
|
|
621
|
+
const turned = back.map(([a, b]) => [b, a]);
|
|
622
|
+
return ahead ? [...ahead, ...turned] : turned;
|
|
623
|
+
};
|
|
624
|
+
const threadColor = (lane, nodeId, thread) => liftedWalks[lane]?.passColors.get(nodeId)?.[threads?.[lane]?.threadPasses.get(nodeId)?.[thread] ?? 0];
|
|
583
625
|
const lanePointsOf = (nodeId, segments) => lines?.shifts.has(nodeId) ? segments.map((p, i) => {
|
|
584
626
|
const { dx, dy } = laneShiftOf(nodeId, i);
|
|
585
627
|
return { ...p, x: p.x + dx, y: p.y + dy };
|
|
@@ -604,37 +646,47 @@ function buildGeometry(options) {
|
|
|
604
646
|
const toNode = nodeById.get(edge.to);
|
|
605
647
|
const intoHalfWidth = (toNode ? nodeWidthPx(toNode, contigThickness, nodeWidth, depthNorm) : contigThickness) / 2;
|
|
606
648
|
const inView = (curves) => !viewportBounds || isBezierInBounds(curves, viewportBounds);
|
|
607
|
-
const
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
649
|
+
const dashesOf = (curves) => dashSpans(curves, DELETION_DASH_PX / scale, yToX, viewportBounds);
|
|
650
|
+
const stroke = (curves, thickness, color) => {
|
|
651
|
+
if (!isDeletion) {
|
|
652
|
+
edgeCurves.push({ curves, thickness, color });
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
for (const dash of dashesOf(curves)) {
|
|
656
|
+
edgeCurves.push({ curves: dash.curves, thickness, color });
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
const laneStroke = (curves, thickness, color, walk, pass, normal2, offsetX, endNormal, endOffsetX) => {
|
|
660
|
+
if (!isDeletion) {
|
|
615
661
|
edgeCurves.push({
|
|
616
|
-
curves
|
|
662
|
+
curves,
|
|
617
663
|
thickness,
|
|
618
664
|
color,
|
|
619
|
-
walk
|
|
620
|
-
pass
|
|
621
|
-
normal:
|
|
622
|
-
offsetX
|
|
623
|
-
endNormal
|
|
624
|
-
endOffsetX
|
|
665
|
+
walk,
|
|
666
|
+
pass,
|
|
667
|
+
normal: normal2,
|
|
668
|
+
offsetX,
|
|
669
|
+
endNormal,
|
|
670
|
+
endOffsetX
|
|
625
671
|
});
|
|
626
|
-
};
|
|
627
|
-
if (!isDeletion) {
|
|
628
|
-
push(curves);
|
|
629
672
|
return;
|
|
630
673
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
674
|
+
const start = { normal: normal2, offsetX };
|
|
675
|
+
const end = { normal: endNormal, offsetX: endOffsetX };
|
|
676
|
+
for (const dash of dashesOf(curves)) {
|
|
677
|
+
const a = dash.startAlong === 0 ? start : laneSlideAt(start, end, dash.startAlong);
|
|
678
|
+
const b = dash.endAlong === 1 ? end : laneSlideAt(start, end, dash.endAlong);
|
|
679
|
+
edgeCurves.push({
|
|
680
|
+
curves: dash.curves,
|
|
681
|
+
thickness,
|
|
682
|
+
color,
|
|
683
|
+
walk,
|
|
684
|
+
pass,
|
|
685
|
+
normal: a.normal,
|
|
686
|
+
offsetX: a.offsetX,
|
|
687
|
+
endNormal: b.normal,
|
|
688
|
+
endOffsetX: b.offsetX
|
|
689
|
+
});
|
|
638
690
|
}
|
|
639
691
|
};
|
|
640
692
|
const arrowOn = (curves) => {
|
|
@@ -655,89 +707,57 @@ function buildGeometry(options) {
|
|
|
655
707
|
const edgeCurveStart = edgeCurves.length;
|
|
656
708
|
const arrowStart = arrows.length;
|
|
657
709
|
const laneWalks = highlight?.walks.length && onWalk && !ribbons ? highlight.walks : void 0;
|
|
710
|
+
if (laneWalks && !lanesMayShow(baseCurves, edge.from)) {
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
658
713
|
if (laneWalks) {
|
|
659
|
-
const
|
|
660
|
-
let width = laneWidths.get(id);
|
|
661
|
-
if (width === void 0) {
|
|
662
|
-
const node = nodeById.get(id);
|
|
663
|
-
width = walkLaneWidthPx(
|
|
664
|
-
node ? nodeWidthPx(node, contigThickness, nodeWidth, depthNorm) : contigThickness,
|
|
665
|
-
laneWalks.length
|
|
666
|
-
);
|
|
667
|
-
laneWidths.set(id, width);
|
|
668
|
-
}
|
|
669
|
-
return width;
|
|
670
|
-
};
|
|
671
|
-
const endOf = (id, segments, atStart) => {
|
|
672
|
-
const at = atStart ? 0 : segments.length - 1;
|
|
673
|
-
return {
|
|
674
|
-
id,
|
|
675
|
-
laneWidth: laneWidthOf(id),
|
|
676
|
-
normal: laneNormalsOf(id, segments)[at] ?? { nx: 0, ny: 0 },
|
|
677
|
-
shift: laneShiftOf(id, at)
|
|
678
|
-
};
|
|
679
|
-
};
|
|
680
|
-
const from = endOf(
|
|
714
|
+
const from = laneEndOf(
|
|
681
715
|
edge.from,
|
|
682
716
|
fromSegments,
|
|
683
717
|
leavesStart(edge, fromSegments, baseCurves[0], stranded, yToX)
|
|
684
718
|
);
|
|
685
719
|
const last = baseCurves.at(-1);
|
|
686
|
-
const to = threaded ?
|
|
720
|
+
const to = threaded ? laneEndOf(
|
|
687
721
|
edge.to,
|
|
688
722
|
toSegments,
|
|
689
723
|
nearerStart({ x: last.x1, y: last.y1 }, toSegments, yToX)
|
|
690
724
|
) : from;
|
|
691
|
-
const slideOf = (end, offsetX) => ({
|
|
692
|
-
dx: end.shift.dx + end.normal.nx * offsetX,
|
|
693
|
-
dy: end.shift.dy + end.normal.ny * offsetX / yToX
|
|
694
|
-
});
|
|
695
|
-
const aheadKey = threads ? `${edge.from}>${edge.to}` : "";
|
|
696
|
-
const backKey = threads ? `${edge.to}>${edge.from}` : "";
|
|
697
|
-
const pairsOf = (lane) => {
|
|
698
|
-
const own = threads?.[lane]?.linkThreads;
|
|
699
|
-
if (!own?.size) {
|
|
700
|
-
return FIRST_THREADS;
|
|
701
|
-
}
|
|
702
|
-
const ahead = own.get(aheadKey);
|
|
703
|
-
const back = edgeKeys.has(backKey) ? void 0 : own.get(backKey);
|
|
704
|
-
if (!back) {
|
|
705
|
-
return ahead ?? FIRST_THREADS;
|
|
706
|
-
}
|
|
707
|
-
const turned = back.map(([a, b]) => [b, a]);
|
|
708
|
-
return ahead ? [...ahead, ...turned] : turned;
|
|
709
|
-
};
|
|
710
725
|
const single = laneWalks.length === 1;
|
|
711
|
-
|
|
726
|
+
const thickness = laneHalfWidth(from.laneWidth);
|
|
727
|
+
for (let lane = 0; lane < laneWalks.length; lane++) {
|
|
728
|
+
const walk = laneWalks[lane];
|
|
712
729
|
if (!walk.edgeIndexes.has(ei)) {
|
|
713
|
-
|
|
730
|
+
continue;
|
|
714
731
|
}
|
|
715
|
-
for (const [pass, toPass] of
|
|
732
|
+
for (const [pass, toPass] of threadPairs(lane, edge.from, edge.to)) {
|
|
716
733
|
const offsetX = single ? 0 : laneOffset(from.id, from.laneWidth, lane, pass) * worldPerScreenPx;
|
|
717
|
-
const
|
|
718
|
-
const end = threaded ? {
|
|
719
|
-
normal: to.normal,
|
|
720
|
-
offsetX: laneOffset(to.id, to.laneWidth, lane, toPass) * worldPerScreenPx
|
|
721
|
-
} : start;
|
|
734
|
+
const endOffsetX = threaded ? laneOffset(to.id, to.laneWidth, lane, toPass) * worldPerScreenPx : offsetX;
|
|
722
735
|
const curves = threaded ? slideCurves(
|
|
723
736
|
baseCurves,
|
|
724
|
-
|
|
725
|
-
|
|
737
|
+
from.shift.dx + from.normal.nx * offsetX,
|
|
738
|
+
from.shift.dy + from.normal.ny * offsetX / yToX,
|
|
739
|
+
to.shift.dx + to.normal.nx * endOffsetX,
|
|
740
|
+
to.shift.dy + to.normal.ny * endOffsetX / yToX
|
|
726
741
|
) : offsetX === 0 ? baseCurves : translateCurves(
|
|
727
742
|
baseCurves,
|
|
728
743
|
from.normal.nx * offsetX,
|
|
729
744
|
from.normal.ny * offsetX / yToX
|
|
730
745
|
);
|
|
731
746
|
if (inView(curves)) {
|
|
732
|
-
|
|
747
|
+
laneStroke(
|
|
733
748
|
curves,
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
749
|
+
thickness,
|
|
750
|
+
threadColor(lane, edge.from, pass) ?? threadColor(lane, edge.to, toPass) ?? plainEdgeColor,
|
|
751
|
+
lane,
|
|
752
|
+
pass,
|
|
753
|
+
from.normal,
|
|
754
|
+
offsetX,
|
|
755
|
+
to.normal,
|
|
756
|
+
endOffsetX
|
|
737
757
|
);
|
|
738
758
|
}
|
|
739
759
|
}
|
|
740
|
-
}
|
|
760
|
+
}
|
|
741
761
|
if (edgeCurves.length > edgeCurveStart) {
|
|
742
762
|
arrowOn(baseCurves);
|
|
743
763
|
}
|
|
@@ -807,34 +827,37 @@ function buildGeometry(options) {
|
|
|
807
827
|
const laneWidth = walkLaneWidthPx(width, lanes.length);
|
|
808
828
|
const normals = lanes.length > 1 ? laneNormalsOf(nodeId, segments) : [];
|
|
809
829
|
const points = lanes.length > 1 ? lanePointsOf(nodeId, segments) : segments;
|
|
810
|
-
|
|
811
|
-
|
|
830
|
+
const thickness = laneHalfWidth(laneWidth);
|
|
831
|
+
for (let lane = 0; lane < lanes.length; lane++) {
|
|
832
|
+
const laneColor = lanes[lane].colors.get(nodeId);
|
|
812
833
|
if (laneColor === void 0) {
|
|
813
|
-
|
|
834
|
+
continue;
|
|
814
835
|
}
|
|
815
836
|
const onThreads = threads?.[lane]?.nodeThreads.get(nodeId) ?? ONE_PASS;
|
|
816
|
-
const
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
lanes.length === 1 ? {
|
|
837
|
+
for (const pass of onThreads) {
|
|
838
|
+
const color2 = threadColor(lane, nodeId, pass) ?? laneColor;
|
|
839
|
+
if (lanes.length === 1) {
|
|
840
|
+
nodeStrokes.push({
|
|
821
841
|
points: segments,
|
|
822
842
|
thickness,
|
|
823
|
-
color:
|
|
843
|
+
color: color2,
|
|
824
844
|
walk: lane,
|
|
825
845
|
pass
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
846
|
+
});
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
const offsetX = laneOffset(nodeId, laneWidth, lane, pass) * worldPerScreenPx;
|
|
850
|
+
nodeStrokes.push({
|
|
851
|
+
points: offsetPolyline(points, normals, offsetX, yToX),
|
|
852
|
+
thickness,
|
|
853
|
+
color: color2,
|
|
854
|
+
walk: lane,
|
|
855
|
+
pass,
|
|
856
|
+
normals,
|
|
857
|
+
offsetX
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
}
|
|
838
861
|
} else if (drawable && slots?.length && slotWidth >= MIN_PATH_STRIPE_PX) {
|
|
839
862
|
const normals = pointNormalsOf(segments, yToX);
|
|
840
863
|
for (const slot of slots) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
encodedColor,
|
|
3
|
-
resolveEncoding
|
|
4
|
-
|
|
3
|
+
resolveEncoding,
|
|
4
|
+
splitFamilies
|
|
5
|
+
} from "./chunk-UVRCXTBY.js";
|
|
5
6
|
import {
|
|
6
7
|
rampFraction
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-53DZE3SA.js";
|
|
8
9
|
import {
|
|
9
10
|
gapParts
|
|
10
11
|
} from "./chunk-LG2UK4MB.js";
|
|
@@ -54,6 +55,7 @@ function highlightOf(graph, name, { byId, edgeAt }) {
|
|
|
54
55
|
const nodeIds = /* @__PURE__ */ new Set();
|
|
55
56
|
const edgeIndexes = /* @__PURE__ */ new Set();
|
|
56
57
|
const progress = /* @__PURE__ */ new Map();
|
|
58
|
+
const passProgress = /* @__PURE__ */ new Map();
|
|
57
59
|
const passes = /* @__PURE__ */ new Map();
|
|
58
60
|
let mostPasses = 1;
|
|
59
61
|
let before = 0;
|
|
@@ -74,8 +76,15 @@ function highlightOf(graph, name, { byId, edgeAt }) {
|
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
const length = lengthOf(id);
|
|
79
|
+
const at = span > 0 ? (before + length / 2) / span : 0;
|
|
77
80
|
if (!progress.has(id)) {
|
|
78
|
-
progress.set(id,
|
|
81
|
+
progress.set(id, at);
|
|
82
|
+
}
|
|
83
|
+
const seen = passProgress.get(id);
|
|
84
|
+
if (seen) {
|
|
85
|
+
seen.push(at);
|
|
86
|
+
} else {
|
|
87
|
+
passProgress.set(id, [at]);
|
|
79
88
|
}
|
|
80
89
|
before += length;
|
|
81
90
|
});
|
|
@@ -112,6 +121,7 @@ function highlightOf(graph, name, { byId, edgeAt }) {
|
|
|
112
121
|
nodeIds,
|
|
113
122
|
edgeIndexes,
|
|
114
123
|
progress,
|
|
124
|
+
passProgress,
|
|
115
125
|
passes,
|
|
116
126
|
mostPasses,
|
|
117
127
|
route: pieces.map((piece) => piece.nodeIds),
|
|
@@ -124,12 +134,17 @@ function highlightOf(graph, name, { byId, edgeAt }) {
|
|
|
124
134
|
}
|
|
125
135
|
function laneColors(byId, walk, encoding, ramp) {
|
|
126
136
|
const colors = /* @__PURE__ */ new Map();
|
|
127
|
-
|
|
137
|
+
const passColors = /* @__PURE__ */ new Map();
|
|
138
|
+
for (const [id, progress] of walk.passProgress) {
|
|
128
139
|
const node = byId.get(id);
|
|
129
|
-
const
|
|
130
|
-
|
|
140
|
+
const atNode = ramp && node ? rampFraction(node, ramp) : void 0;
|
|
141
|
+
const each = progress.map(
|
|
142
|
+
(t) => encodedColor(encoding, encoding.field === "progress" ? t : atNode)
|
|
143
|
+
);
|
|
144
|
+
colors.set(id, each[0]);
|
|
145
|
+
passColors.set(id, each);
|
|
131
146
|
}
|
|
132
|
-
return colors;
|
|
147
|
+
return { colors, passColors };
|
|
133
148
|
}
|
|
134
149
|
function reversedNodes(graph, byId, walk) {
|
|
135
150
|
const reversed = /* @__PURE__ */ new Set();
|
|
@@ -167,18 +182,23 @@ function walkLift(graph, layers, ramp) {
|
|
|
167
182
|
return void 0;
|
|
168
183
|
}
|
|
169
184
|
let picked = 0;
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
layer
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
185
|
+
const encodings = splitFamilies(
|
|
186
|
+
lifted.map(
|
|
187
|
+
({ walk, layer }) => resolveEncoding(
|
|
188
|
+
layer,
|
|
189
|
+
walk.reference,
|
|
190
|
+
walk.reference ? 0 : picked++,
|
|
191
|
+
lifted.length === 1
|
|
192
|
+
)
|
|
193
|
+
)
|
|
194
|
+
);
|
|
195
|
+
const walks = lifted.map(({ walk }, i) => {
|
|
196
|
+
const encoding = encodings[i];
|
|
177
197
|
const { reversed, bp } = reversedNodes(graph, index.byId, walk);
|
|
178
198
|
return {
|
|
179
199
|
...walk,
|
|
180
200
|
encoding,
|
|
181
|
-
|
|
201
|
+
...laneColors(index.byId, walk, encoding, ramp),
|
|
182
202
|
reversed,
|
|
183
203
|
reversedBp: bp
|
|
184
204
|
};
|
|
@@ -200,7 +220,7 @@ function facetLifts(graph, lift, layers, ramp) {
|
|
|
200
220
|
{
|
|
201
221
|
...walk,
|
|
202
222
|
encoding,
|
|
203
|
-
|
|
223
|
+
...laneColors(byId, walk, encoding, ramp)
|
|
204
224
|
}
|
|
205
225
|
],
|
|
206
226
|
ramp
|
|
@@ -3,30 +3,30 @@ import {
|
|
|
3
3
|
} from "./chunk-CO6RGQAD.js";
|
|
4
4
|
import {
|
|
5
5
|
layoutModeByValue
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ARXDNQLF.js";
|
|
7
7
|
import {
|
|
8
8
|
parseRegion
|
|
9
9
|
} from "./chunk-FNDNSDKW.js";
|
|
10
10
|
import {
|
|
11
11
|
genePins
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HEYIAMTC.js";
|
|
13
13
|
import {
|
|
14
14
|
version
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-2NCZ5YYN.js";
|
|
16
16
|
import {
|
|
17
17
|
axisScaleOf
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-3DHGSHC3.js";
|
|
19
19
|
import {
|
|
20
20
|
figureScene
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-YQAZNH37.js";
|
|
22
22
|
import {
|
|
23
23
|
encodingStops
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-UVRCXTBY.js";
|
|
25
25
|
import {
|
|
26
26
|
laneSlideAt,
|
|
27
27
|
passesKey,
|
|
28
28
|
threadsPasses
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-4KBZ7WPP.js";
|
|
30
30
|
import {
|
|
31
31
|
abgrAlpha,
|
|
32
32
|
abgrBlue,
|
|
@@ -35,13 +35,13 @@ import {
|
|
|
35
35
|
} from "./chunk-G2FD7S3C.js";
|
|
36
36
|
import {
|
|
37
37
|
FIGURE_DEFAULTS
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-2MXFG3W7.js";
|
|
39
39
|
import {
|
|
40
40
|
engineSettingsOf,
|
|
41
41
|
fitTransform,
|
|
42
42
|
forceLayout,
|
|
43
43
|
loadGraph
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-JVT3XTKN.js";
|
|
45
45
|
import {
|
|
46
46
|
referenceVisitStarts
|
|
47
47
|
} from "./chunk-3YBP46PB.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
baseEdgeCurves
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-P2GJBFNA.js";
|
|
4
4
|
import {
|
|
5
5
|
curveBounds,
|
|
6
6
|
pathRibbonOffsets
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JJV2GT2Z.js";
|
|
8
8
|
|
|
9
9
|
// src/util/SpatialIndex.ts
|
|
10
10
|
var FALLBACK_CELL_SIZE = 50;
|