@jbrowse/bandage-core 5.0.0 → 5.1.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/chunks/{chunk-WWH65AAB.js → chunk-Y2MDXT4O.js} +275 -195
- package/dist/cli/figure.js +4 -2
- package/dist/index.js +15 -9
- package/dist/types/cli/figure.d.ts +2 -0
- package/dist/types/colorSchemes.d.ts +1 -1
- package/dist/types/deletionEdges.d.ts +3 -1
- package/dist/types/figure.d.ts +1 -0
- package/dist/types/graphLabels.d.ts +2 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/labelLayout.d.ts +1 -0
- package/dist/types/pipeline.d.ts +3 -0
- package/dist/types/reference.d.ts +3 -0
- package/dist/types/renderer/GeometryBuilder.d.ts +1 -0
- package/dist/types/types.d.ts +1 -0
- package/dist/types/util/SpatialIndex.d.ts +1 -1
- package/dist/types/util/edgeCurves.d.ts +1 -1
- package/dist/types/util/geometry.d.ts +10 -2
- package/dist/types/util/hitDetection.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -297,6 +297,16 @@ function attachment(segments, side) {
|
|
|
297
297
|
}
|
|
298
298
|
var TANGENT_SPAN_FACTOR = 0.5;
|
|
299
299
|
var MAX_TANGENT = 80;
|
|
300
|
+
function ownStrand(id) {
|
|
301
|
+
return id.endsWith("-") ? "-" : "+";
|
|
302
|
+
}
|
|
303
|
+
function strandSides(edge) {
|
|
304
|
+
const own = (id, strand) => (strand ?? ownStrand(id)) === ownStrand(id);
|
|
305
|
+
return {
|
|
306
|
+
from: own(edge.from, edge.fromStrand) ? "end" : "start",
|
|
307
|
+
to: own(edge.to, edge.toStrand) ? "start" : "end"
|
|
308
|
+
};
|
|
309
|
+
}
|
|
300
310
|
function spanOf(segments) {
|
|
301
311
|
let min = Infinity;
|
|
302
312
|
let max = -Infinity;
|
|
@@ -409,6 +419,14 @@ function selfLinkOf(edge) {
|
|
|
409
419
|
}
|
|
410
420
|
return edge.fromStrand && edge.toStrand && edge.fromStrand !== edge.toStrand ? edge.fromStrand === "+" ? "end" : "start" : true;
|
|
411
421
|
}
|
|
422
|
+
function edgeJoinOf(edge, stranded = false) {
|
|
423
|
+
const self = selfLinkOf(edge);
|
|
424
|
+
if (!stranded) {
|
|
425
|
+
return self;
|
|
426
|
+
}
|
|
427
|
+
const sides = strandSides(edge);
|
|
428
|
+
return self === false ? sides : sides.from === sides.to ? sides.from : true;
|
|
429
|
+
}
|
|
412
430
|
function hairpinCurves(attach, reach, offsetX, offsetY) {
|
|
413
431
|
const { at, inward } = attach;
|
|
414
432
|
const dx = inward ? at.x - inward.x : 1;
|
|
@@ -447,7 +465,7 @@ function hairpinCurves(attach, reach, offsetX, offsetY) {
|
|
|
447
465
|
}
|
|
448
466
|
];
|
|
449
467
|
}
|
|
450
|
-
function computeEdgeCurves(fromSegments, toSegments,
|
|
468
|
+
function computeEdgeCurves(fromSegments, toSegments, join, offsetX, offsetY, axis, bypassed = [], maxBowIn) {
|
|
451
469
|
const scale = axis.scaleX;
|
|
452
470
|
const yToX = yToXOf(axis);
|
|
453
471
|
const maxBow = maxBowIn ?? (axis.pixelRows ? MAX_ROW_BOW_PX : void 0);
|
|
@@ -456,7 +474,7 @@ function computeEdgeCurves(fromSegments, toSegments, selfLink, offsetX, offsetY,
|
|
|
456
474
|
computeEdgeCurves(
|
|
457
475
|
scaleYOf(fromSegments, yToX),
|
|
458
476
|
scaleYOf(toSegments, yToX),
|
|
459
|
-
|
|
477
|
+
join,
|
|
460
478
|
offsetX,
|
|
461
479
|
offsetY * yToX,
|
|
462
480
|
{ scaleX: scale, scaleY: scale },
|
|
@@ -468,15 +486,16 @@ function computeEdgeCurves(fromSegments, toSegments, selfLink, offsetX, offsetY,
|
|
|
468
486
|
yToX
|
|
469
487
|
);
|
|
470
488
|
}
|
|
471
|
-
if (typeof
|
|
489
|
+
if (typeof join === "string") {
|
|
472
490
|
return hairpinCurves(
|
|
473
|
-
attachment(fromSegments,
|
|
491
|
+
attachment(fromSegments, join),
|
|
474
492
|
selfLoopReach(fromSegments, scale),
|
|
475
493
|
offsetX,
|
|
476
494
|
offsetY
|
|
477
495
|
);
|
|
478
496
|
}
|
|
479
|
-
const
|
|
497
|
+
const loop = join === true;
|
|
498
|
+
const sides = loop ? { from: "end", to: "start" } : join || facingSides(fromSegments, toSegments);
|
|
480
499
|
const fromAttach = attachment(fromSegments, sides.from);
|
|
481
500
|
const toAttach = attachment(toSegments, sides.to);
|
|
482
501
|
const fromEnd = fromAttach.at;
|
|
@@ -485,7 +504,7 @@ function computeEdgeCurves(fromSegments, toSegments, selfLink, offsetX, offsetY,
|
|
|
485
504
|
const p1y = fromEnd.y + offsetY;
|
|
486
505
|
const p2x = toStart.x + offsetX;
|
|
487
506
|
const p2y = toStart.y + offsetY;
|
|
488
|
-
if (
|
|
507
|
+
if (loop) {
|
|
489
508
|
let segDirX = 1;
|
|
490
509
|
let segDirY = 0;
|
|
491
510
|
if (fromAttach.inward) {
|
|
@@ -591,12 +610,15 @@ function nearerEnd(segments, to) {
|
|
|
591
610
|
const end = segments.at(-1);
|
|
592
611
|
return Math.hypot(start.x - to.x, start.y - to.y) < Math.hypot(end.x - to.x, end.y - to.y) ? "start" : "end";
|
|
593
612
|
}
|
|
594
|
-
function routedEdgeCurves(fromSegments, toSegments, route) {
|
|
613
|
+
function routedEdgeCurves(fromSegments, toSegments, route, sides) {
|
|
595
614
|
const fromAttach = attachment(
|
|
596
615
|
fromSegments,
|
|
597
|
-
nearerEnd(fromSegments, route[0])
|
|
616
|
+
sides?.from ?? nearerEnd(fromSegments, route[0])
|
|
617
|
+
);
|
|
618
|
+
const toAttach = attachment(
|
|
619
|
+
toSegments,
|
|
620
|
+
sides?.to ?? nearerEnd(toSegments, route.at(-1))
|
|
598
621
|
);
|
|
599
|
-
const toAttach = attachment(toSegments, nearerEnd(toSegments, route.at(-1)));
|
|
600
622
|
const points = [fromAttach.at, ...route, toAttach.at];
|
|
601
623
|
const tangent = (i) => {
|
|
602
624
|
const p = points[i];
|
|
@@ -646,16 +668,21 @@ var MIN_DELETION_BP = 1;
|
|
|
646
668
|
function bypassedPoints(nodePositions, bypassed) {
|
|
647
669
|
return bypassed.flatMap((id) => nodePositions[id] ?? []);
|
|
648
670
|
}
|
|
649
|
-
function deletionArcCurves(nodePositions, deletion, axis, route) {
|
|
671
|
+
function deletionArcCurves(nodePositions, deletion, axis, route, stranded = false) {
|
|
650
672
|
const from = nodePositions[deletion.from];
|
|
651
673
|
const to = nodePositions[deletion.to];
|
|
652
674
|
if (!from?.length || !to?.length) {
|
|
653
675
|
return void 0;
|
|
654
676
|
}
|
|
655
|
-
return route ? routedEdgeCurves(
|
|
677
|
+
return route ? routedEdgeCurves(
|
|
678
|
+
from,
|
|
679
|
+
to,
|
|
680
|
+
route,
|
|
681
|
+
stranded ? strandSides(deletion) : void 0
|
|
682
|
+
) : computeEdgeCurves(
|
|
656
683
|
from,
|
|
657
684
|
to,
|
|
658
|
-
deletion
|
|
685
|
+
edgeJoinOf(deletion, stranded),
|
|
659
686
|
0,
|
|
660
687
|
0,
|
|
661
688
|
axis,
|
|
@@ -723,6 +750,8 @@ function deletionEdges(graph) {
|
|
|
723
750
|
edgeIndex,
|
|
724
751
|
from: edge.from,
|
|
725
752
|
to: edge.to,
|
|
753
|
+
...edge.fromStrand ? { fromStrand: edge.fromStrand } : {},
|
|
754
|
+
...edge.toStrand ? { toStrand: edge.toStrand } : {},
|
|
726
755
|
refName,
|
|
727
756
|
start,
|
|
728
757
|
end,
|
|
@@ -1207,19 +1236,11 @@ function takeRoutes(positions, routes) {
|
|
|
1207
1236
|
}
|
|
1208
1237
|
|
|
1209
1238
|
// src/layout/mergeRuns.ts
|
|
1210
|
-
function ownStrand(id) {
|
|
1211
|
-
return id.endsWith("-") ? "-" : "+";
|
|
1212
|
-
}
|
|
1213
1239
|
function flip(strand) {
|
|
1214
1240
|
return strand === "+" ? "-" : "+";
|
|
1215
1241
|
}
|
|
1216
|
-
function sidesOf(edge) {
|
|
1217
|
-
const from = (edge.fromStrand ?? ownStrand(edge.from)) === ownStrand(edge.from) ? "end" : "start";
|
|
1218
|
-
const to = (edge.toStrand ?? ownStrand(edge.to)) === ownStrand(edge.to) ? "start" : "end";
|
|
1219
|
-
return { from, to };
|
|
1220
|
-
}
|
|
1221
1242
|
function mergeRuns(graph, alone = /* @__PURE__ */ new Set()) {
|
|
1222
|
-
const sides = graph.edges.map(
|
|
1243
|
+
const sides = graph.edges.map(strandSides);
|
|
1223
1244
|
const at = /* @__PURE__ */ new Map();
|
|
1224
1245
|
const attach = (id, side, ei) => {
|
|
1225
1246
|
const key = `${id}|${side}`;
|
|
@@ -1589,24 +1610,33 @@ function loadGraph(text, name, opts = {}) {
|
|
|
1589
1610
|
}
|
|
1590
1611
|
return graph;
|
|
1591
1612
|
}
|
|
1613
|
+
var COMPONENT_SEPARATION = 15;
|
|
1592
1614
|
function engineRequest(graph, scaling, settings) {
|
|
1593
1615
|
const anchored = graph.nodes.some(isBackbone);
|
|
1616
|
+
const spaced = {
|
|
1617
|
+
...scaling,
|
|
1618
|
+
opts: {
|
|
1619
|
+
...scaling.opts,
|
|
1620
|
+
edgeLength: scaling.opts.edgeLength * (settings.spacing ?? 1)
|
|
1621
|
+
}
|
|
1622
|
+
};
|
|
1594
1623
|
return {
|
|
1595
1624
|
graph: {
|
|
1596
|
-
nodes: anchored ? seededNodes(graph,
|
|
1625
|
+
nodes: anchored ? seededNodes(graph, spaced) : spaced.nodes,
|
|
1597
1626
|
edges: graph.edges
|
|
1598
1627
|
},
|
|
1599
1628
|
options: {
|
|
1600
1629
|
quality: settings.quality,
|
|
1601
1630
|
linearLayout: settings.linearLayout,
|
|
1602
|
-
...
|
|
1631
|
+
...spaced.opts,
|
|
1632
|
+
componentSeparation: COMPONENT_SEPARATION * (settings.componentSeparation ?? 1),
|
|
1603
1633
|
...anchored ? { rotateComponents: false } : {}
|
|
1604
1634
|
}
|
|
1605
1635
|
};
|
|
1606
1636
|
}
|
|
1607
1637
|
function engineKey(graph, settings) {
|
|
1608
1638
|
const anchored = graph.nodes.some(isBackbone);
|
|
1609
|
-
return `${settings.quality}|${settings.linearLayout}|${settings.bubbleSpread}|${anchored}|${graph.referencePath ?? ""}`;
|
|
1639
|
+
return `${settings.quality}|${settings.linearLayout}|${settings.bubbleSpread}|${settings.spacing ?? 1}|${settings.componentSeparation ?? 1}|${anchored}|${graph.referencePath ?? ""}`;
|
|
1610
1640
|
}
|
|
1611
1641
|
async function forceLayout(graph, settings, engine) {
|
|
1612
1642
|
const spread = spreadFor(settings.bubbleSpread);
|
|
@@ -1654,6 +1684,7 @@ async function forceLayout(graph, settings, engine) {
|
|
|
1654
1684
|
result: {
|
|
1655
1685
|
...result,
|
|
1656
1686
|
nodePositions,
|
|
1687
|
+
stranded: true,
|
|
1657
1688
|
...deletions.length ? { deletionRoutes, extent: layoutExtent(deletionRoutes) } : {}
|
|
1658
1689
|
},
|
|
1659
1690
|
duration
|
|
@@ -1888,10 +1919,10 @@ function labelOrder(nodePositions, nodeLengths) {
|
|
|
1888
1919
|
return order;
|
|
1889
1920
|
}
|
|
1890
1921
|
var arcCache = /* @__PURE__ */ new WeakMap();
|
|
1891
|
-
function arcPlacements(nodePositions, deletions, axis, version2, routes) {
|
|
1922
|
+
function arcPlacements(nodePositions, deletions, axis, version2, routes, stranded) {
|
|
1892
1923
|
const { scaleX, scaleY } = axis;
|
|
1893
1924
|
const cached2 = arcCache.get(nodePositions);
|
|
1894
|
-
if (cached2?.deletions === deletions && cached2.routes === routes && cached2.scaleX === scaleX && cached2.scaleY === scaleY && cached2.version === version2) {
|
|
1925
|
+
if (cached2?.deletions === deletions && cached2.routes === routes && cached2.stranded === stranded && cached2.scaleX === scaleX && cached2.scaleY === scaleY && cached2.version === version2) {
|
|
1895
1926
|
return cached2.arcs;
|
|
1896
1927
|
}
|
|
1897
1928
|
const arcs = [];
|
|
@@ -1900,7 +1931,8 @@ function arcPlacements(nodePositions, deletions, axis, version2, routes) {
|
|
|
1900
1931
|
nodePositions,
|
|
1901
1932
|
deletion,
|
|
1902
1933
|
axis,
|
|
1903
|
-
routes?.[deletion.edgeIndex]
|
|
1934
|
+
routes?.[deletion.edgeIndex],
|
|
1935
|
+
stranded
|
|
1904
1936
|
);
|
|
1905
1937
|
const apex = curves ? curveMidpoint(curves) : void 0;
|
|
1906
1938
|
if (curves && apex) {
|
|
@@ -1917,6 +1949,7 @@ function arcPlacements(nodePositions, deletions, axis, version2, routes) {
|
|
|
1917
1949
|
arcCache.set(nodePositions, {
|
|
1918
1950
|
deletions,
|
|
1919
1951
|
routes,
|
|
1952
|
+
stranded,
|
|
1920
1953
|
scaleX,
|
|
1921
1954
|
scaleY,
|
|
1922
1955
|
version: version2,
|
|
@@ -1929,6 +1962,7 @@ function sizeLabelCandidates({
|
|
|
1929
1962
|
nodeLengths,
|
|
1930
1963
|
deletions,
|
|
1931
1964
|
deletionRoutes,
|
|
1965
|
+
stranded = false,
|
|
1932
1966
|
alleleDeletions,
|
|
1933
1967
|
axis,
|
|
1934
1968
|
translateX,
|
|
@@ -1945,7 +1979,8 @@ function sizeLabelCandidates({
|
|
|
1945
1979
|
deletions,
|
|
1946
1980
|
axis,
|
|
1947
1981
|
version2,
|
|
1948
|
-
deletionRoutes
|
|
1982
|
+
deletionRoutes,
|
|
1983
|
+
stranded
|
|
1949
1984
|
)) {
|
|
1950
1985
|
if (extent >= MIN_DELETION_LABEL_PX) {
|
|
1951
1986
|
const text = deletionText(deletion.bp);
|
|
@@ -3374,7 +3409,7 @@ var COLOR_SCHEMES = [
|
|
|
3374
3409
|
{ value: "random", label: "Random" },
|
|
3375
3410
|
{ value: "rainbow", label: "Rainbow" },
|
|
3376
3411
|
{ value: "depth", label: "Depth" },
|
|
3377
|
-
{ value: "node-length", label: "Node
|
|
3412
|
+
{ value: "node-length", label: "Node length" },
|
|
3378
3413
|
{ value: "stable-rank", label: "Stable rank" },
|
|
3379
3414
|
{ value: "reference-position", label: "Reference position" },
|
|
3380
3415
|
{ value: "grey", label: "Grey" }
|
|
@@ -3465,10 +3500,10 @@ function brightenAbgr(c, factor) {
|
|
|
3465
3500
|
|
|
3466
3501
|
// src/util/edgeCurves.ts
|
|
3467
3502
|
var cache = /* @__PURE__ */ new WeakMap();
|
|
3468
|
-
function baseEdgeCurves(nodePositions, graph, axis, deletions, version2, routes) {
|
|
3503
|
+
function baseEdgeCurves(nodePositions, graph, axis, deletions, version2, routes, stranded = false) {
|
|
3469
3504
|
const { scaleX, scaleY } = axis;
|
|
3470
3505
|
const cached2 = cache.get(nodePositions);
|
|
3471
|
-
if (cached2?.graph === graph && cached2.scaleX === scaleX && cached2.scaleY === scaleY && cached2.deletions === deletions && cached2.routes === routes && cached2.version === version2) {
|
|
3506
|
+
if (cached2?.graph === graph && cached2.scaleX === scaleX && cached2.scaleY === scaleY && cached2.deletions === deletions && cached2.routes === routes && cached2.stranded === stranded && cached2.version === version2) {
|
|
3472
3507
|
return cached2.curves;
|
|
3473
3508
|
}
|
|
3474
3509
|
const curves = /* @__PURE__ */ new Map();
|
|
@@ -3481,10 +3516,15 @@ function baseEdgeCurves(nodePositions, graph, axis, deletions, version2, routes)
|
|
|
3481
3516
|
const route = bypassed && routes?.[ei];
|
|
3482
3517
|
curves.set(
|
|
3483
3518
|
ei,
|
|
3484
|
-
route ? routedEdgeCurves(
|
|
3519
|
+
route ? routedEdgeCurves(
|
|
3485
3520
|
from,
|
|
3486
3521
|
to,
|
|
3487
|
-
|
|
3522
|
+
route,
|
|
3523
|
+
stranded ? strandSides(edge) : void 0
|
|
3524
|
+
) : computeEdgeCurves(
|
|
3525
|
+
from,
|
|
3526
|
+
to,
|
|
3527
|
+
edgeJoinOf(edge, stranded),
|
|
3488
3528
|
0,
|
|
3489
3529
|
0,
|
|
3490
3530
|
axis,
|
|
@@ -3499,6 +3539,7 @@ function baseEdgeCurves(nodePositions, graph, axis, deletions, version2, routes)
|
|
|
3499
3539
|
scaleY,
|
|
3500
3540
|
deletions,
|
|
3501
3541
|
routes,
|
|
3542
|
+
stranded,
|
|
3502
3543
|
version: version2,
|
|
3503
3544
|
curves
|
|
3504
3545
|
});
|
|
@@ -3523,6 +3564,7 @@ var ARROW_LENGTH_BASE_PX = 7;
|
|
|
3523
3564
|
var ARROW_LENGTH_PER_EDGE_PX = 3;
|
|
3524
3565
|
var ARROW_HALF_WIDTH_BASE_PX = 3;
|
|
3525
3566
|
var ARROW_HALF_WIDTH_PER_EDGE_PX = 1.5;
|
|
3567
|
+
var MIN_LINK_HEADS = 3;
|
|
3526
3568
|
var MIN_ARROW_FIT = 0.5;
|
|
3527
3569
|
var MIN_ARROW_SCALE = 0.45;
|
|
3528
3570
|
var ARROW_CURVE_STEPS = 12;
|
|
@@ -3587,12 +3629,17 @@ function arrowheadFor({
|
|
|
3587
3629
|
toSegments
|
|
3588
3630
|
}) {
|
|
3589
3631
|
const length = ARROW_LENGTH_BASE_PX + ARROW_LENGTH_PER_EDGE_PX * edgeHalfWidth;
|
|
3590
|
-
const n2 = backFromEnd(
|
|
3632
|
+
const n2 = backFromEnd(
|
|
3633
|
+
curves,
|
|
3634
|
+
scale,
|
|
3635
|
+
yToX,
|
|
3636
|
+
nodeHalfWidth + MIN_LINK_HEADS * length
|
|
3637
|
+
);
|
|
3591
3638
|
const lengthPx = walkPx[n2 - 1];
|
|
3639
|
+
const abutting = lengthPx < ABUTTING_PX;
|
|
3592
3640
|
const inset = Math.min(nodeHalfWidth, lengthPx);
|
|
3593
|
-
const
|
|
3594
|
-
|
|
3595
|
-
if (fit < MIN_ARROW_FIT) {
|
|
3641
|
+
const fit = abutting ? Math.min(1, polylinePx(fromSegments, scale, yToX) / length) : 1;
|
|
3642
|
+
if (abutting ? fit < MIN_ARROW_FIT : lengthPx < MIN_LINK_HEADS * length) {
|
|
3596
3643
|
return void 0;
|
|
3597
3644
|
}
|
|
3598
3645
|
const tip = walkPointAt(n2, inset);
|
|
@@ -3619,6 +3666,13 @@ function polylinePx(segments, scale, yToX) {
|
|
|
3619
3666
|
}
|
|
3620
3667
|
return length * scale;
|
|
3621
3668
|
}
|
|
3669
|
+
function leavesStart(edge, segments, first, stranded, yToX) {
|
|
3670
|
+
if (stranded) {
|
|
3671
|
+
return strandSides(edge).from === "start";
|
|
3672
|
+
}
|
|
3673
|
+
const gap = (p) => Math.hypot(p.x - first.x0, (p.y - first.y0) * yToX);
|
|
3674
|
+
return gap(segments[0]) < gap(segments.at(-1));
|
|
3675
|
+
}
|
|
3622
3676
|
function intoDirection(last, toSegments) {
|
|
3623
3677
|
if (toSegments.length < 2) {
|
|
3624
3678
|
return void 0;
|
|
@@ -3964,6 +4018,7 @@ function buildGeometry(options) {
|
|
|
3964
4018
|
referenceRamp,
|
|
3965
4019
|
deletions,
|
|
3966
4020
|
deletionRoutes,
|
|
4021
|
+
stranded,
|
|
3967
4022
|
hiddenEdges,
|
|
3968
4023
|
version: version2 = 0
|
|
3969
4024
|
} = options;
|
|
@@ -3976,7 +4031,8 @@ function buildGeometry(options) {
|
|
|
3976
4031
|
axis,
|
|
3977
4032
|
deletions,
|
|
3978
4033
|
version2,
|
|
3979
|
-
deletionRoutes
|
|
4034
|
+
deletionRoutes,
|
|
4035
|
+
stranded
|
|
3980
4036
|
);
|
|
3981
4037
|
const nodeStrokes = [];
|
|
3982
4038
|
const nodeStrokeRuns = /* @__PURE__ */ new Map();
|
|
@@ -4028,7 +4084,7 @@ function buildGeometry(options) {
|
|
|
4028
4084
|
}
|
|
4029
4085
|
const head = showArrows && arrowColor !== void 0 ? arrowheadFor({
|
|
4030
4086
|
curves,
|
|
4031
|
-
edgeHalfWidth:
|
|
4087
|
+
edgeHalfWidth: connectorThickness / 2,
|
|
4032
4088
|
nodeHalfWidth: intoHalfWidth,
|
|
4033
4089
|
scale,
|
|
4034
4090
|
yToX,
|
|
@@ -4048,7 +4104,13 @@ function buildGeometry(options) {
|
|
|
4048
4104
|
const width = fromNode ? nodeWidthPx(fromNode, contigThickness, nodeWidth2, depthNorm) : contigThickness;
|
|
4049
4105
|
const laneWidth = Math.max(width / laneWalks.length, MIN_WALK_LANE_PX);
|
|
4050
4106
|
const normals = pointNormalsOf(fromSegments, yToX);
|
|
4051
|
-
const { nx, ny } = (
|
|
4107
|
+
const { nx, ny } = (leavesStart(
|
|
4108
|
+
edge,
|
|
4109
|
+
fromSegments,
|
|
4110
|
+
baseCurves[0],
|
|
4111
|
+
stranded,
|
|
4112
|
+
yToX
|
|
4113
|
+
) ? normals[0] : normals.at(-1)) ?? {
|
|
4052
4114
|
nx: 0,
|
|
4053
4115
|
ny: 0
|
|
4054
4116
|
};
|
|
@@ -4932,6 +4994,7 @@ function layoutLabels(m) {
|
|
|
4932
4994
|
nodeLengths: m.nodeLengths,
|
|
4933
4995
|
deletions: m.showDeletionEdges ? m.deletions : [],
|
|
4934
4996
|
deletionRoutes: m.deletionRoutes,
|
|
4997
|
+
stranded: m.stranded,
|
|
4935
4998
|
alleleDeletions: m.alleleDeletions,
|
|
4936
4999
|
axis: m.axisScale,
|
|
4937
5000
|
translateX,
|
|
@@ -5609,6 +5672,154 @@ function stripGeneGaps(frame, rowGenes, gaps) {
|
|
|
5609
5672
|
return frame.boxesGenes ? gaps : { untracked: 0, unread: 0, ...gaps, crowded: true };
|
|
5610
5673
|
}
|
|
5611
5674
|
|
|
5675
|
+
// src/reference.ts
|
|
5676
|
+
var WELL_KNOWN_SAMPLES = /* @__PURE__ */ new Map([
|
|
5677
|
+
["hg38", "GRCh38"],
|
|
5678
|
+
["hg19", "GRCh37"],
|
|
5679
|
+
["hs1", "CHM13"],
|
|
5680
|
+
["t2t-chm13", "CHM13"],
|
|
5681
|
+
["chm13v2", "CHM13"]
|
|
5682
|
+
]);
|
|
5683
|
+
function wellKnownSample(assemblyName) {
|
|
5684
|
+
return WELL_KNOWN_SAMPLES.get(assemblyName.toLowerCase());
|
|
5685
|
+
}
|
|
5686
|
+
function sampleOf2(refName) {
|
|
5687
|
+
const sample = refName.includes("#") ? panSNSample(refName) : void 0;
|
|
5688
|
+
return sample === void 0 || isGenericSample(sample) ? void 0 : sample;
|
|
5689
|
+
}
|
|
5690
|
+
function haplotypeOf(refName) {
|
|
5691
|
+
return panSNHaplotype(refName) ?? panSNSample(refName);
|
|
5692
|
+
}
|
|
5693
|
+
function graphHaplotypes(graph) {
|
|
5694
|
+
const refNames = new Set((graph.anchorPaths ?? []).map((p) => p.name));
|
|
5695
|
+
for (const node of graph.nodes) {
|
|
5696
|
+
if (node.stable) {
|
|
5697
|
+
refNames.add(node.stable.refName);
|
|
5698
|
+
}
|
|
5699
|
+
}
|
|
5700
|
+
const bySample = /* @__PURE__ */ new Map();
|
|
5701
|
+
for (const refName of refNames) {
|
|
5702
|
+
const sample = sampleOf2(refName);
|
|
5703
|
+
if (sample !== void 0) {
|
|
5704
|
+
const haplotypes = bySample.get(sample) ?? bySample.set(sample, /* @__PURE__ */ new Set()).get(sample);
|
|
5705
|
+
haplotypes.add(haplotypeOf(refName));
|
|
5706
|
+
}
|
|
5707
|
+
}
|
|
5708
|
+
return bySample;
|
|
5709
|
+
}
|
|
5710
|
+
function backboneFrom(contigs, haplotypes) {
|
|
5711
|
+
const samples = new Set(contigs.map((c) => sampleOf2(c.refName)));
|
|
5712
|
+
const [sample] = samples;
|
|
5713
|
+
if (samples.size !== 1 || sample === void 0) {
|
|
5714
|
+
return { contigs, prefixes: [], named: false };
|
|
5715
|
+
}
|
|
5716
|
+
const own = new Set(contigs.map((c) => haplotypeOf(c.refName)));
|
|
5717
|
+
const unique = [...haplotypes.get(sample) ?? []].every((h) => own.has(h));
|
|
5718
|
+
const shared = new Set(contigs.map((c) => panSNHaplotype(c.refName)));
|
|
5719
|
+
const [haplotype] = shared;
|
|
5720
|
+
return {
|
|
5721
|
+
contigs,
|
|
5722
|
+
prefixes: [
|
|
5723
|
+
...unique ? [sample] : [],
|
|
5724
|
+
...shared.size === 1 && haplotype ? [haplotype] : []
|
|
5725
|
+
],
|
|
5726
|
+
named: true
|
|
5727
|
+
};
|
|
5728
|
+
}
|
|
5729
|
+
function graphBackbone(graph) {
|
|
5730
|
+
const spans = /* @__PURE__ */ new Map();
|
|
5731
|
+
for (const node of graph.nodes) {
|
|
5732
|
+
if (isBackbone(node)) {
|
|
5733
|
+
const { refName, start } = node.stable;
|
|
5734
|
+
const end = start + node.length;
|
|
5735
|
+
const span = spans.get(refName);
|
|
5736
|
+
if (span) {
|
|
5737
|
+
span.start = Math.min(span.start, start);
|
|
5738
|
+
span.end = Math.max(span.end, end);
|
|
5739
|
+
} else {
|
|
5740
|
+
spans.set(refName, {
|
|
5741
|
+
refName,
|
|
5742
|
+
contig: panSNContig(refName),
|
|
5743
|
+
start,
|
|
5744
|
+
end
|
|
5745
|
+
});
|
|
5746
|
+
}
|
|
5747
|
+
}
|
|
5748
|
+
}
|
|
5749
|
+
const contigs = [...spans.values()];
|
|
5750
|
+
return contigs.length ? backboneFrom(contigs, graphHaplotypes(graph)) : void 0;
|
|
5751
|
+
}
|
|
5752
|
+
function referenceLabel(graph, region) {
|
|
5753
|
+
const backbone = graphBackbone(graph);
|
|
5754
|
+
const contig = region ? panSNContig(region.refName) : backbone?.contigs.length === 1 ? backbone.contigs[0].contig : void 0;
|
|
5755
|
+
const sample = backbone?.named ? panSNSample(backbone.contigs[0].refName) : void 0;
|
|
5756
|
+
return contig && (sample ? `${sample} ${contig}` : contig);
|
|
5757
|
+
}
|
|
5758
|
+
function backboneAssembly(backbone, assemblies) {
|
|
5759
|
+
const names = (a) => [a.name, ...a.aliases ?? []];
|
|
5760
|
+
const naming = (prefix) => (a) => names(a).some((n2) => n2.toLowerCase() === prefix.toLowerCase());
|
|
5761
|
+
const prefixes = [...backbone?.prefixes ?? []].reverse();
|
|
5762
|
+
const sample = backbone?.prefixes.find((p) => !p.includes("#"))?.toLowerCase();
|
|
5763
|
+
for (const prefix of prefixes) {
|
|
5764
|
+
const assembly = assemblies.find(naming(prefix));
|
|
5765
|
+
if (assembly) {
|
|
5766
|
+
return assembly;
|
|
5767
|
+
}
|
|
5768
|
+
}
|
|
5769
|
+
return sample === void 0 ? void 0 : assemblies.find(
|
|
5770
|
+
(a) => names(a).some((n2) => wellKnownSample(n2)?.toLowerCase() === sample)
|
|
5771
|
+
);
|
|
5772
|
+
}
|
|
5773
|
+
function assemblyWalk(graph, assembly) {
|
|
5774
|
+
const haplotypes = graphHaplotypes(graph);
|
|
5775
|
+
return graph.anchorPaths?.find(
|
|
5776
|
+
(walk) => backboneAssembly(
|
|
5777
|
+
backboneFrom(
|
|
5778
|
+
[
|
|
5779
|
+
{
|
|
5780
|
+
refName: walk.name,
|
|
5781
|
+
contig: panSNContig(walk.name),
|
|
5782
|
+
start: walk.start,
|
|
5783
|
+
end: walk.start + walk.length
|
|
5784
|
+
}
|
|
5785
|
+
],
|
|
5786
|
+
haplotypes
|
|
5787
|
+
),
|
|
5788
|
+
[assembly]
|
|
5789
|
+
)
|
|
5790
|
+
);
|
|
5791
|
+
}
|
|
5792
|
+
function contigNames(contig) {
|
|
5793
|
+
const bare = contig.replace(/^chr/i, "");
|
|
5794
|
+
const forms = !bare ? [] : /^(M|MT)$/i.test(bare) ? ["M", "MT"] : [bare];
|
|
5795
|
+
return [.../* @__PURE__ */ new Set([contig, ...forms.flatMap((f) => [f, `chr${f}`])])];
|
|
5796
|
+
}
|
|
5797
|
+
function refNameBinding(refNames, aliases = {}) {
|
|
5798
|
+
const exact = new Set(refNames);
|
|
5799
|
+
const byName = /* @__PURE__ */ new Map();
|
|
5800
|
+
for (const refName of exact) {
|
|
5801
|
+
const contig = panSNContig(refName);
|
|
5802
|
+
const alias = aliases[contig];
|
|
5803
|
+
for (const name of /* @__PURE__ */ new Set([
|
|
5804
|
+
...contigNames(contig),
|
|
5805
|
+
...alias ? [alias] : []
|
|
5806
|
+
])) {
|
|
5807
|
+
byName.set(name, byName.has(name) ? void 0 : refName);
|
|
5808
|
+
}
|
|
5809
|
+
}
|
|
5810
|
+
return (name) => exact.has(name) ? name : byName.get(name);
|
|
5811
|
+
}
|
|
5812
|
+
function featuresOnBackbone(features, backbone, aliases) {
|
|
5813
|
+
const bind = refNameBinding(
|
|
5814
|
+
backbone.contigs.map((c) => c.refName),
|
|
5815
|
+
aliases
|
|
5816
|
+
);
|
|
5817
|
+
return features.flatMap((f) => {
|
|
5818
|
+
const refName = bind(f.refName);
|
|
5819
|
+
return refName === void 0 ? [] : [refName === f.refName ? f : { ...f, refName }];
|
|
5820
|
+
});
|
|
5821
|
+
}
|
|
5822
|
+
|
|
5612
5823
|
// src/renderer/svgCanvas.ts
|
|
5613
5824
|
var n = (v) => +v.toFixed(1);
|
|
5614
5825
|
function paint(css) {
|
|
@@ -5722,7 +5933,7 @@ function svgCanvas(width, height) {
|
|
|
5722
5933
|
}
|
|
5723
5934
|
|
|
5724
5935
|
// src/version.ts
|
|
5725
|
-
var version = "5.
|
|
5936
|
+
var version = "5.1.0";
|
|
5726
5937
|
|
|
5727
5938
|
// src/viewport.ts
|
|
5728
5939
|
function axisScaleOf(scale, pixelRows) {
|
|
@@ -5845,9 +6056,10 @@ function figureSvg(graph, layout, o = {}) {
|
|
|
5845
6056
|
])
|
|
5846
6057
|
);
|
|
5847
6058
|
const labelOf2 = (name) => labels.get(name) ?? name;
|
|
6059
|
+
const referenceName = o.referenceName ?? referenceLabel(graph, region);
|
|
5848
6060
|
const reference = lift?.referenceDomain && {
|
|
5849
6061
|
...lift.referenceDomain,
|
|
5850
|
-
name:
|
|
6062
|
+
name: referenceName
|
|
5851
6063
|
};
|
|
5852
6064
|
const contigThickness = o.contigThickness ?? 6;
|
|
5853
6065
|
const nodeWidth2 = o.nodeWidth ?? "depth";
|
|
@@ -5953,6 +6165,7 @@ function figureSvg(graph, layout, o = {}) {
|
|
|
5953
6165
|
referenceRamp,
|
|
5954
6166
|
deletions: new Map(deletions.map((d) => [d.edgeIndex, d.bypassed])),
|
|
5955
6167
|
deletionRoutes: layout.deletionRoutes,
|
|
6168
|
+
stranded: layout.stranded,
|
|
5956
6169
|
hiddenEdges: new Set(
|
|
5957
6170
|
o.showDeletionEdges ? [] : deletions.map((d) => d.edgeIndex)
|
|
5958
6171
|
)
|
|
@@ -6036,10 +6249,10 @@ function figureSvg(graph, layout, o = {}) {
|
|
|
6036
6249
|
x,
|
|
6037
6250
|
2,
|
|
6038
6251
|
encodingStops({ field: "reference", scheme: "rainbow" }),
|
|
6039
|
-
"Reference position",
|
|
6252
|
+
referenceName ? `${referenceName} position` : "Reference position",
|
|
6040
6253
|
"",
|
|
6041
6254
|
rangeText(
|
|
6042
|
-
|
|
6255
|
+
referenceName,
|
|
6043
6256
|
referenceRamp.start,
|
|
6044
6257
|
referenceRamp.start + referenceRamp.span
|
|
6045
6258
|
)
|
|
@@ -6198,14 +6411,22 @@ function genesFromGff3Lines(lines) {
|
|
|
6198
6411
|
const start = top?.start ?? Math.min(...rows2.map((r) => r.start));
|
|
6199
6412
|
const end = top?.end ?? Math.max(...rows2.map((r) => r.end));
|
|
6200
6413
|
const a = first.attrs;
|
|
6201
|
-
const
|
|
6414
|
+
const spans = (type) => rows2.filter((r) => r.type === type).map((r) => ({ start: r.start, end: r.end }));
|
|
6415
|
+
const exons = spans("exon");
|
|
6416
|
+
const coding = spans("CDS");
|
|
6417
|
+
const transcribed = rows2.some(
|
|
6418
|
+
(r) => r !== top && r.type !== "exon" && r.type !== "CDS"
|
|
6419
|
+
);
|
|
6202
6420
|
genes.push({
|
|
6203
6421
|
name: a.get("Name") ?? a.get("gene_name") ?? a.get("gene") ?? a.get("gene_id") ?? key.split(" ")[1],
|
|
6204
6422
|
refName: first.refName,
|
|
6205
6423
|
start,
|
|
6206
6424
|
end,
|
|
6207
6425
|
strand: first.strand,
|
|
6208
|
-
|
|
6426
|
+
// A range read holds only the rows over its window, so a gene with
|
|
6427
|
+
// transcripts but no exon or CDS there is intronic in it. Only a gene
|
|
6428
|
+
// with no transcripts, as a bacterium's gene and CDS, is one exon.
|
|
6429
|
+
exons: exons.length ? mergedIntervals(exons) : transcribed ? mergedIntervals(coding) : [{ start, end }]
|
|
6209
6430
|
});
|
|
6210
6431
|
}
|
|
6211
6432
|
return genes;
|
|
@@ -6261,148 +6482,6 @@ function genesFromText(text) {
|
|
|
6261
6482
|
return /^\d+$/.test(cols[1] ?? "") && /^\d+$/.test(cols[2] ?? "") ? genesFromBed(text) : genesFromGff3Lines(text.split(/\r?\n/));
|
|
6262
6483
|
}
|
|
6263
6484
|
|
|
6264
|
-
// src/reference.ts
|
|
6265
|
-
var WELL_KNOWN_SAMPLES = /* @__PURE__ */ new Map([
|
|
6266
|
-
["hg38", "GRCh38"],
|
|
6267
|
-
["hg19", "GRCh37"],
|
|
6268
|
-
["hs1", "CHM13"],
|
|
6269
|
-
["t2t-chm13", "CHM13"],
|
|
6270
|
-
["chm13v2", "CHM13"]
|
|
6271
|
-
]);
|
|
6272
|
-
function wellKnownSample(assemblyName) {
|
|
6273
|
-
return WELL_KNOWN_SAMPLES.get(assemblyName.toLowerCase());
|
|
6274
|
-
}
|
|
6275
|
-
function sampleOf2(refName) {
|
|
6276
|
-
const sample = refName.includes("#") ? panSNSample(refName) : void 0;
|
|
6277
|
-
return sample === void 0 || isGenericSample(sample) ? void 0 : sample;
|
|
6278
|
-
}
|
|
6279
|
-
function haplotypeOf(refName) {
|
|
6280
|
-
return panSNHaplotype(refName) ?? panSNSample(refName);
|
|
6281
|
-
}
|
|
6282
|
-
function graphHaplotypes(graph) {
|
|
6283
|
-
const refNames = new Set((graph.anchorPaths ?? []).map((p) => p.name));
|
|
6284
|
-
for (const node of graph.nodes) {
|
|
6285
|
-
if (node.stable) {
|
|
6286
|
-
refNames.add(node.stable.refName);
|
|
6287
|
-
}
|
|
6288
|
-
}
|
|
6289
|
-
const bySample = /* @__PURE__ */ new Map();
|
|
6290
|
-
for (const refName of refNames) {
|
|
6291
|
-
const sample = sampleOf2(refName);
|
|
6292
|
-
if (sample !== void 0) {
|
|
6293
|
-
const haplotypes = bySample.get(sample) ?? bySample.set(sample, /* @__PURE__ */ new Set()).get(sample);
|
|
6294
|
-
haplotypes.add(haplotypeOf(refName));
|
|
6295
|
-
}
|
|
6296
|
-
}
|
|
6297
|
-
return bySample;
|
|
6298
|
-
}
|
|
6299
|
-
function backboneFrom(contigs, haplotypes) {
|
|
6300
|
-
const samples = new Set(contigs.map((c) => sampleOf2(c.refName)));
|
|
6301
|
-
const [sample] = samples;
|
|
6302
|
-
if (samples.size !== 1 || sample === void 0) {
|
|
6303
|
-
return { contigs, prefixes: [], named: false };
|
|
6304
|
-
}
|
|
6305
|
-
const own = new Set(contigs.map((c) => haplotypeOf(c.refName)));
|
|
6306
|
-
const unique = [...haplotypes.get(sample) ?? []].every((h) => own.has(h));
|
|
6307
|
-
const shared = new Set(contigs.map((c) => panSNHaplotype(c.refName)));
|
|
6308
|
-
const [haplotype] = shared;
|
|
6309
|
-
return {
|
|
6310
|
-
contigs,
|
|
6311
|
-
prefixes: [
|
|
6312
|
-
...unique ? [sample] : [],
|
|
6313
|
-
...shared.size === 1 && haplotype ? [haplotype] : []
|
|
6314
|
-
],
|
|
6315
|
-
named: true
|
|
6316
|
-
};
|
|
6317
|
-
}
|
|
6318
|
-
function graphBackbone(graph) {
|
|
6319
|
-
const spans = /* @__PURE__ */ new Map();
|
|
6320
|
-
for (const node of graph.nodes) {
|
|
6321
|
-
if (isBackbone(node)) {
|
|
6322
|
-
const { refName, start } = node.stable;
|
|
6323
|
-
const end = start + node.length;
|
|
6324
|
-
const span = spans.get(refName);
|
|
6325
|
-
if (span) {
|
|
6326
|
-
span.start = Math.min(span.start, start);
|
|
6327
|
-
span.end = Math.max(span.end, end);
|
|
6328
|
-
} else {
|
|
6329
|
-
spans.set(refName, {
|
|
6330
|
-
refName,
|
|
6331
|
-
contig: panSNContig(refName),
|
|
6332
|
-
start,
|
|
6333
|
-
end
|
|
6334
|
-
});
|
|
6335
|
-
}
|
|
6336
|
-
}
|
|
6337
|
-
}
|
|
6338
|
-
const contigs = [...spans.values()];
|
|
6339
|
-
return contigs.length ? backboneFrom(contigs, graphHaplotypes(graph)) : void 0;
|
|
6340
|
-
}
|
|
6341
|
-
function backboneAssembly(backbone, assemblies) {
|
|
6342
|
-
const names = (a) => [a.name, ...a.aliases ?? []];
|
|
6343
|
-
const naming = (prefix) => (a) => names(a).some((n2) => n2.toLowerCase() === prefix.toLowerCase());
|
|
6344
|
-
const prefixes = [...backbone?.prefixes ?? []].reverse();
|
|
6345
|
-
const sample = backbone?.prefixes.find((p) => !p.includes("#"))?.toLowerCase();
|
|
6346
|
-
for (const prefix of prefixes) {
|
|
6347
|
-
const assembly = assemblies.find(naming(prefix));
|
|
6348
|
-
if (assembly) {
|
|
6349
|
-
return assembly;
|
|
6350
|
-
}
|
|
6351
|
-
}
|
|
6352
|
-
return sample === void 0 ? void 0 : assemblies.find(
|
|
6353
|
-
(a) => names(a).some((n2) => wellKnownSample(n2)?.toLowerCase() === sample)
|
|
6354
|
-
);
|
|
6355
|
-
}
|
|
6356
|
-
function assemblyWalk(graph, assembly) {
|
|
6357
|
-
const haplotypes = graphHaplotypes(graph);
|
|
6358
|
-
return graph.anchorPaths?.find(
|
|
6359
|
-
(walk) => backboneAssembly(
|
|
6360
|
-
backboneFrom(
|
|
6361
|
-
[
|
|
6362
|
-
{
|
|
6363
|
-
refName: walk.name,
|
|
6364
|
-
contig: panSNContig(walk.name),
|
|
6365
|
-
start: walk.start,
|
|
6366
|
-
end: walk.start + walk.length
|
|
6367
|
-
}
|
|
6368
|
-
],
|
|
6369
|
-
haplotypes
|
|
6370
|
-
),
|
|
6371
|
-
[assembly]
|
|
6372
|
-
)
|
|
6373
|
-
);
|
|
6374
|
-
}
|
|
6375
|
-
function contigNames(contig) {
|
|
6376
|
-
const bare = contig.replace(/^chr/i, "");
|
|
6377
|
-
const forms = !bare ? [] : /^(M|MT)$/i.test(bare) ? ["M", "MT"] : [bare];
|
|
6378
|
-
return [.../* @__PURE__ */ new Set([contig, ...forms.flatMap((f) => [f, `chr${f}`])])];
|
|
6379
|
-
}
|
|
6380
|
-
function refNameBinding(refNames, aliases = {}) {
|
|
6381
|
-
const exact = new Set(refNames);
|
|
6382
|
-
const byName = /* @__PURE__ */ new Map();
|
|
6383
|
-
for (const refName of exact) {
|
|
6384
|
-
const contig = panSNContig(refName);
|
|
6385
|
-
const alias = aliases[contig];
|
|
6386
|
-
for (const name of /* @__PURE__ */ new Set([
|
|
6387
|
-
...contigNames(contig),
|
|
6388
|
-
...alias ? [alias] : []
|
|
6389
|
-
])) {
|
|
6390
|
-
byName.set(name, byName.has(name) ? void 0 : refName);
|
|
6391
|
-
}
|
|
6392
|
-
}
|
|
6393
|
-
return (name) => exact.has(name) ? name : byName.get(name);
|
|
6394
|
-
}
|
|
6395
|
-
function featuresOnBackbone(features, backbone, aliases) {
|
|
6396
|
-
const bind = refNameBinding(
|
|
6397
|
-
backbone.contigs.map((c) => c.refName),
|
|
6398
|
-
aliases
|
|
6399
|
-
);
|
|
6400
|
-
return features.flatMap((f) => {
|
|
6401
|
-
const refName = bind(f.refName);
|
|
6402
|
-
return refName === void 0 ? [] : [refName === f.refName ? f : { ...f, refName }];
|
|
6403
|
-
});
|
|
6404
|
-
}
|
|
6405
|
-
|
|
6406
6485
|
// src/gbzJoin.ts
|
|
6407
6486
|
var UNKNOWN_SAMPLE = "unknown";
|
|
6408
6487
|
function parseWalk(line) {
|
|
@@ -6796,6 +6875,14 @@ export {
|
|
|
6796
6875
|
walkMarksTree,
|
|
6797
6876
|
walkStripLabelsTree,
|
|
6798
6877
|
stripGeneGaps,
|
|
6878
|
+
WELL_KNOWN_SAMPLES,
|
|
6879
|
+
wellKnownSample,
|
|
6880
|
+
graphBackbone,
|
|
6881
|
+
referenceLabel,
|
|
6882
|
+
backboneAssembly,
|
|
6883
|
+
assemblyWalk,
|
|
6884
|
+
refNameBinding,
|
|
6885
|
+
featuresOnBackbone,
|
|
6799
6886
|
svgCanvas,
|
|
6800
6887
|
version,
|
|
6801
6888
|
axisScaleOf,
|
|
@@ -6809,13 +6896,6 @@ export {
|
|
|
6809
6896
|
mergeOverlappingByName,
|
|
6810
6897
|
genesFromBed,
|
|
6811
6898
|
genesFromText,
|
|
6812
|
-
WELL_KNOWN_SAMPLES,
|
|
6813
|
-
wellKnownSample,
|
|
6814
|
-
graphBackbone,
|
|
6815
|
-
backboneAssembly,
|
|
6816
|
-
assemblyWalk,
|
|
6817
|
-
refNameBinding,
|
|
6818
|
-
featuresOnBackbone,
|
|
6819
6899
|
haplotypeWanted,
|
|
6820
6900
|
referenceSamplesOf,
|
|
6821
6901
|
resolveReferenceSample,
|
package/dist/cli/figure.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
placeRowGenes,
|
|
22
22
|
refNameBinding,
|
|
23
23
|
walkRows
|
|
24
|
-
} from "../chunks/chunk-
|
|
24
|
+
} from "../chunks/chunk-Y2MDXT4O.js";
|
|
25
25
|
|
|
26
26
|
// src/cli/figure.ts
|
|
27
27
|
import { access, open, readFile, writeFile } from "node:fs/promises";
|
|
@@ -171,7 +171,9 @@ async function renderSpec(spec, base) {
|
|
|
171
171
|
{
|
|
172
172
|
quality: spec.quality ?? 2,
|
|
173
173
|
linearLayout: false,
|
|
174
|
-
bubbleSpread: spec.bubbleSpread ?? "auto"
|
|
174
|
+
bubbleSpread: spec.bubbleSpread ?? "auto",
|
|
175
|
+
spacing: spec.spacing,
|
|
176
|
+
componentSeparation: spec.componentSeparation
|
|
175
177
|
},
|
|
176
178
|
engine
|
|
177
179
|
)).result;
|
package/dist/index.js
CHANGED
|
@@ -99,6 +99,7 @@ import {
|
|
|
99
99
|
rangeText,
|
|
100
100
|
readoutPlacement,
|
|
101
101
|
refNameBinding,
|
|
102
|
+
referenceLabel,
|
|
102
103
|
referenceOrder,
|
|
103
104
|
referencePathQuery,
|
|
104
105
|
referenceSamplesOf,
|
|
@@ -138,7 +139,7 @@ import {
|
|
|
138
139
|
wellKnownSample,
|
|
139
140
|
yToXOf,
|
|
140
141
|
zoomAbout
|
|
141
|
-
} from "./chunks/chunk-
|
|
142
|
+
} from "./chunks/chunk-Y2MDXT4O.js";
|
|
142
143
|
|
|
143
144
|
// src/index.ts
|
|
144
145
|
import { getDpr } from "@jbrowse/render-core/canvas2dUtils";
|
|
@@ -255,7 +256,7 @@ var SpatialIndex = class {
|
|
|
255
256
|
}
|
|
256
257
|
};
|
|
257
258
|
var EdgeSpatialIndex = class {
|
|
258
|
-
constructor(nodePositions, graph, drawPaths, axis, cellSize, deletions, version2 = 0, routes2) {
|
|
259
|
+
constructor(nodePositions, graph, drawPaths, axis, cellSize, deletions, version2 = 0, routes2, stranded = false) {
|
|
259
260
|
this.cells = /* @__PURE__ */ new Map();
|
|
260
261
|
this.edgeCurves = baseEdgeCurves(
|
|
261
262
|
nodePositions,
|
|
@@ -263,7 +264,8 @@ var EdgeSpatialIndex = class {
|
|
|
263
264
|
axis,
|
|
264
265
|
deletions,
|
|
265
266
|
version2,
|
|
266
|
-
routes2
|
|
267
|
+
routes2,
|
|
268
|
+
stranded
|
|
267
269
|
);
|
|
268
270
|
const boxes = [];
|
|
269
271
|
let extentX = 0;
|
|
@@ -386,9 +388,9 @@ function getSpatialIndex(nodePositions, version2) {
|
|
|
386
388
|
return index;
|
|
387
389
|
}
|
|
388
390
|
var edgeCache = /* @__PURE__ */ new WeakMap();
|
|
389
|
-
function getEdgeSpatialIndex(nodePositions, graph, drawPaths, axis, version2, deletions, routes2) {
|
|
391
|
+
function getEdgeSpatialIndex(nodePositions, graph, drawPaths, axis, version2, deletions, routes2, stranded = false) {
|
|
390
392
|
const cached = edgeCache.get(nodePositions);
|
|
391
|
-
if (cached?.graph === graph && cached.drawPaths === drawPaths && cached.scaleX === axis.scaleX && cached.scaleY === axis.scaleY && cached.version === version2 && cached.deletions === deletions && cached.routes === routes2) {
|
|
393
|
+
if (cached?.graph === graph && cached.drawPaths === drawPaths && cached.scaleX === axis.scaleX && cached.scaleY === axis.scaleY && cached.version === version2 && cached.deletions === deletions && cached.routes === routes2 && cached.stranded === stranded) {
|
|
392
394
|
return cached.index;
|
|
393
395
|
}
|
|
394
396
|
const index = new EdgeSpatialIndex(
|
|
@@ -399,7 +401,8 @@ function getEdgeSpatialIndex(nodePositions, graph, drawPaths, axis, version2, de
|
|
|
399
401
|
void 0,
|
|
400
402
|
deletions,
|
|
401
403
|
version2,
|
|
402
|
-
routes2
|
|
404
|
+
routes2,
|
|
405
|
+
stranded
|
|
403
406
|
);
|
|
404
407
|
edgeCache.set(nodePositions, {
|
|
405
408
|
graph,
|
|
@@ -409,7 +412,8 @@ function getEdgeSpatialIndex(nodePositions, graph, drawPaths, axis, version2, de
|
|
|
409
412
|
version: version2,
|
|
410
413
|
index,
|
|
411
414
|
deletions,
|
|
412
|
-
routes: routes2
|
|
415
|
+
routes: routes2,
|
|
416
|
+
stranded
|
|
413
417
|
});
|
|
414
418
|
return index;
|
|
415
419
|
}
|
|
@@ -439,7 +443,7 @@ function findHoveredNode(nodePositions, graphX, graphY, axis, version2 = 0, ink)
|
|
|
439
443
|
}
|
|
440
444
|
return hovered;
|
|
441
445
|
}
|
|
442
|
-
function findHoveredEdge(nodePositions, graph, graphX, graphY, axis, drawPaths, version2 = 0, deletions, hiddenEdges, deletionRoutes) {
|
|
446
|
+
function findHoveredEdge(nodePositions, graph, graphX, graphY, axis, drawPaths, version2 = 0, deletions, hiddenEdges, deletionRoutes, stranded = false) {
|
|
443
447
|
const yToX = yToXOf(axis);
|
|
444
448
|
const edgeThreshold = 10 / axis.scaleX;
|
|
445
449
|
const edgeIndex = getEdgeSpatialIndex(
|
|
@@ -449,7 +453,8 @@ function findHoveredEdge(nodePositions, graph, graphX, graphY, axis, drawPaths,
|
|
|
449
453
|
axis,
|
|
450
454
|
version2,
|
|
451
455
|
deletions,
|
|
452
|
-
deletionRoutes
|
|
456
|
+
deletionRoutes,
|
|
457
|
+
stranded
|
|
453
458
|
);
|
|
454
459
|
const candidates = edgeIndex.query(
|
|
455
460
|
graphX,
|
|
@@ -1899,6 +1904,7 @@ export {
|
|
|
1899
1904
|
refNameBinding,
|
|
1900
1905
|
referenceBoxes,
|
|
1901
1906
|
referenceKnots,
|
|
1907
|
+
referenceLabel,
|
|
1902
1908
|
referenceNodes,
|
|
1903
1909
|
referencePathQuery,
|
|
1904
1910
|
referenceSamplesOf,
|
|
@@ -11,6 +11,8 @@ export interface FigureSpec extends Omit<FigureOptions, 'walks' | 'region' | 'ge
|
|
|
11
11
|
layout?: LayoutModeValue;
|
|
12
12
|
quality?: number;
|
|
13
13
|
bubbleSpread?: BubbleSpread;
|
|
14
|
+
spacing?: number;
|
|
15
|
+
componentSeparation?: number;
|
|
14
16
|
walks?: (string | WalkLayer)[];
|
|
15
17
|
walkStrip?: boolean;
|
|
16
18
|
walkRowSamples?: string[];
|
|
@@ -16,7 +16,7 @@ export declare const COLOR_SCHEMES: readonly [{
|
|
|
16
16
|
readonly label: "Depth";
|
|
17
17
|
}, {
|
|
18
18
|
readonly value: "node-length";
|
|
19
|
-
readonly label: "Node
|
|
19
|
+
readonly label: "Node length";
|
|
20
20
|
}, {
|
|
21
21
|
readonly value: "stable-rank";
|
|
22
22
|
readonly label: "Stable rank";
|
|
@@ -4,6 +4,8 @@ export interface DeletionEdge {
|
|
|
4
4
|
edgeIndex: number;
|
|
5
5
|
from: string;
|
|
6
6
|
to: string;
|
|
7
|
+
fromStrand?: '+' | '-';
|
|
8
|
+
toStrand?: '+' | '-';
|
|
7
9
|
refName: string;
|
|
8
10
|
start: number;
|
|
9
11
|
end: number;
|
|
@@ -20,5 +22,5 @@ export declare function bypassedPoints(nodePositions: Record<string, {
|
|
|
20
22
|
export declare function deletionArcCurves(nodePositions: Record<string, {
|
|
21
23
|
x: number;
|
|
22
24
|
y: number;
|
|
23
|
-
}[]>, deletion: DeletionEdge, axis: AxisScale, route?: NodeSegment[]): import("./util/geometry.js").BezierCurve[] | undefined;
|
|
25
|
+
}[]>, deletion: DeletionEdge, axis: AxisScale, route?: NodeSegment[], stranded?: boolean): import("./util/geometry.js").BezierCurve[] | undefined;
|
|
24
26
|
export declare function deletionEdges(graph: Graph): DeletionEdge[];
|
package/dist/types/figure.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ interface SizeLabelArgs {
|
|
|
25
25
|
nodeLengths: Map<string, number>;
|
|
26
26
|
deletions: DeletionEdge[];
|
|
27
27
|
deletionRoutes?: DeletionRoutes;
|
|
28
|
+
stranded?: boolean;
|
|
28
29
|
alleleDeletions?: AlleleDeletion[];
|
|
29
30
|
axis: AxisScale;
|
|
30
31
|
translateX: number;
|
|
@@ -37,7 +38,7 @@ export interface SizeLabelCandidate {
|
|
|
37
38
|
label: GraphLabel;
|
|
38
39
|
box: Box;
|
|
39
40
|
}
|
|
40
|
-
export declare function sizeLabelCandidates({ nodePositions, nodeLengths, deletions, deletionRoutes, alleleDeletions, axis, translateX, translateY, width, height, version, }: SizeLabelArgs): {
|
|
41
|
+
export declare function sizeLabelCandidates({ nodePositions, nodeLengths, deletions, deletionRoutes, stranded, alleleDeletions, axis, translateX, translateY, width, height, version, }: SizeLabelArgs): {
|
|
41
42
|
deletions: SizeLabelCandidate[];
|
|
42
43
|
nodes: SizeLabelCandidate[];
|
|
43
44
|
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export type { LabelLayout, LabelLayoutSource } from './labelLayout.js';
|
|
|
70
70
|
export { formatBp } from './graphLabels.js';
|
|
71
71
|
export { genePins } from './genes/genePins.js';
|
|
72
72
|
export type { GeneModel, GenePin } from './genes/genePins.js';
|
|
73
|
-
export { WELL_KNOWN_SAMPLES, assemblyWalk, backboneAssembly, featuresOnBackbone, graphBackbone, refNameBinding, wellKnownSample, } from './reference.js';
|
|
73
|
+
export { WELL_KNOWN_SAMPLES, assemblyWalk, backboneAssembly, featuresOnBackbone, graphBackbone, refNameBinding, referenceLabel, wellKnownSample, } from './reference.js';
|
|
74
74
|
export type { AssemblyNames, Backbone, BackboneContig } from './reference.js';
|
|
75
75
|
export { LABEL_CHAR_PX, LABEL_PAD, LABEL_PX } from './overlayLabels.js';
|
|
76
76
|
export type { Graph, GraphEdge, GraphNode, LayoutResult, NodeSegment, } from './types.js';
|
package/dist/types/pipeline.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface EngineSettings {
|
|
|
27
27
|
quality: number;
|
|
28
28
|
linearLayout: boolean;
|
|
29
29
|
bubbleSpread: BubbleSpread;
|
|
30
|
+
spacing?: number;
|
|
31
|
+
componentSeparation?: number;
|
|
30
32
|
}
|
|
31
33
|
export declare function engineRequest(graph: Graph, scaling: LayoutScaling, settings: EngineSettings): EngineRequest;
|
|
32
34
|
export declare function engineKey(graph: Graph, settings: EngineSettings): string;
|
|
@@ -42,6 +44,7 @@ export declare function forceLayout(graph: Graph, settings: EngineSettings, engi
|
|
|
42
44
|
nodePositions: {
|
|
43
45
|
[x: string]: NodeSegment[];
|
|
44
46
|
};
|
|
47
|
+
stranded: boolean;
|
|
45
48
|
rowLabels?: import("./types.js").RowLabel[];
|
|
46
49
|
sampleRows?: string[];
|
|
47
50
|
alleleDeletions?: import("./types.js").AlleleDeletion[];
|
|
@@ -17,6 +17,9 @@ export interface AssemblyNames {
|
|
|
17
17
|
export declare const WELL_KNOWN_SAMPLES: ReadonlyMap<string, string>;
|
|
18
18
|
export declare function wellKnownSample(assemblyName: string): string | undefined;
|
|
19
19
|
export declare function graphBackbone(graph: Graph): Backbone | undefined;
|
|
20
|
+
export declare function referenceLabel(graph: Graph, region?: {
|
|
21
|
+
refName: string;
|
|
22
|
+
}): string | undefined;
|
|
20
23
|
export declare function backboneAssembly<T extends AssemblyNames>(backbone: Backbone | undefined, assemblies: T[]): T | undefined;
|
|
21
24
|
export declare function assemblyWalk(graph: Graph, assembly: AssemblyNames): PathOrigin | undefined;
|
|
22
25
|
export declare function contigNames(contig: string): string[];
|
package/dist/types/types.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare class EdgeSpatialIndex {
|
|
|
19
19
|
private cellSize;
|
|
20
20
|
private cells;
|
|
21
21
|
private edgeCurves;
|
|
22
|
-
constructor(nodePositions: Record<string, NodeSegment[]>, graph: Graph, drawPaths: boolean, axis: AxisScale, cellSize?: number | CellSize, deletions?: Map<number, string[]>, version?: number, routes?: DeletionRoutes);
|
|
22
|
+
constructor(nodePositions: Record<string, NodeSegment[]>, graph: Graph, drawPaths: boolean, axis: AxisScale, cellSize?: number | CellSize, deletions?: Map<number, string[]>, version?: number, routes?: DeletionRoutes, stranded?: boolean);
|
|
23
23
|
getCurves(ei: number): import("./geometry.js").BezierCurve[] | undefined;
|
|
24
24
|
query(x: number, y: number, radiusX: number, radiusY?: number): number[];
|
|
25
25
|
}
|
|
@@ -2,4 +2,4 @@ import type { DeletionRoutes } from '../layout/deletionRoutes.js';
|
|
|
2
2
|
import type { Graph, NodeSegment } from '../types.js';
|
|
3
3
|
import type { AxisScale, BezierCurve } from './geometry.js';
|
|
4
4
|
export type EdgeCurves = Map<number, BezierCurve[]>;
|
|
5
|
-
export declare function baseEdgeCurves(nodePositions: Record<string, NodeSegment[]>, graph: Graph, axis: AxisScale, deletions: Map<number, string[]> | undefined, version: number, routes?: DeletionRoutes): EdgeCurves;
|
|
5
|
+
export declare function baseEdgeCurves(nodePositions: Record<string, NodeSegment[]>, graph: Graph, axis: AxisScale, deletions: Map<number, string[]> | undefined, version: number, routes?: DeletionRoutes, stranded?: boolean): EdgeCurves;
|
|
@@ -28,6 +28,12 @@ export declare function curveBounds(curves: BezierCurve[]): {
|
|
|
28
28
|
export declare function dashCurves(curves: BezierCurve[], dashWorld: number): BezierCurve[][];
|
|
29
29
|
export declare function translateCurves(curves: BezierCurve[], dx: number, dy: number): BezierCurve[];
|
|
30
30
|
type Side = 'start' | 'end';
|
|
31
|
+
export interface EdgeSides {
|
|
32
|
+
from: Side;
|
|
33
|
+
to: Side;
|
|
34
|
+
}
|
|
35
|
+
export declare function ownStrand(id: string): "+" | "-";
|
|
36
|
+
export declare function strandSides(edge: GraphEdge): EdgeSides;
|
|
31
37
|
export declare function bowAround(p1x: number, p1y: number, p2x: number, p2y: number, toward: NodeSegment[], maxBow?: number): number;
|
|
32
38
|
export interface AxisScale {
|
|
33
39
|
scaleX: number;
|
|
@@ -42,6 +48,8 @@ export declare function pathRibbonOffsets(fromSegments: NodeSegment[], toSegment
|
|
|
42
48
|
}[];
|
|
43
49
|
export type SelfLink = boolean | Side;
|
|
44
50
|
export declare function selfLinkOf(edge: GraphEdge): SelfLink;
|
|
45
|
-
export
|
|
46
|
-
export declare function
|
|
51
|
+
export type EdgeJoin = SelfLink | EdgeSides;
|
|
52
|
+
export declare function edgeJoinOf(edge: GraphEdge, stranded?: boolean): EdgeJoin;
|
|
53
|
+
export declare function computeEdgeCurves(fromSegments: NodeSegment[], toSegments: NodeSegment[], join: EdgeJoin, offsetX: number, offsetY: number, axis: AxisScale, bypassed?: NodeSegment[], maxBowIn?: number): BezierCurve[];
|
|
54
|
+
export declare function routedEdgeCurves(fromSegments: NodeSegment[], toSegments: NodeSegment[], route: NodeSegment[], sides?: EdgeSides): BezierCurve[];
|
|
47
55
|
export {};
|
|
@@ -8,4 +8,4 @@ export interface NodeInk {
|
|
|
8
8
|
maxHalfWidthPx: number;
|
|
9
9
|
}
|
|
10
10
|
export declare function findHoveredNode(nodePositions: Record<string, NodeSegment[]>, graphX: number, graphY: number, axis: AxisScale, version?: number, ink?: NodeInk): string | null;
|
|
11
|
-
export declare function findHoveredEdge(nodePositions: Record<string, NodeSegment[]>, graph: Graph, graphX: number, graphY: number, axis: AxisScale, drawPaths: boolean, version?: number, deletions?: Map<number, string[]>, hiddenEdges?: ReadonlySet<number>, deletionRoutes?: DeletionRoutes): number | null;
|
|
11
|
+
export declare function findHoveredEdge(nodePositions: Record<string, NodeSegment[]>, graph: Graph, graphX: number, graphY: number, axis: AxisScale, drawPaths: boolean, version?: number, deletions?: Map<number, string[]>, hiddenEdges?: ReadonlySet<number>, deletionRoutes?: DeletionRoutes, stranded?: boolean): number | null;
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "5.
|
|
1
|
+
export declare const version = "5.1.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/bandage-core",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "Pangenome graph layout and drawing with no host: GFA in, the Bandage force-directed engine and reference-anchored layouts, a Canvas2D renderer, hit testing and labels out",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"repository": {
|