@jbrowse/bandage-core 4.0.30 → 4.1.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/chunks/{chunk-P7UDDVHK.js → chunk-QWZLIWOJ.js} +553 -80
- package/dist/cli/figure.js +1 -8
- package/dist/index.js +51 -1
- package/dist/types/el.d.ts +8 -0
- package/dist/types/figure.d.ts +4 -0
- package/dist/types/gbzCut.d.ts +2 -2
- package/dist/types/gbzWindow.d.ts +6 -10
- package/dist/types/genes/geneFiles.d.ts +1 -0
- package/dist/types/index.d.ts +7 -2
- package/dist/types/layout/walkRowDraw.d.ts +125 -0
- package/dist/types/layout/walkRows.d.ts +6 -0
- package/dist/types/layoutModes.d.ts +2 -2
- package/dist/types/referenceRampCss.d.ts +14 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +2 -2
|
@@ -1962,9 +1962,29 @@ function stepsOf(pieces, lengthOf) {
|
|
|
1962
1962
|
}
|
|
1963
1963
|
return steps;
|
|
1964
1964
|
}
|
|
1965
|
+
function stepSpans(pieces, lengthOf) {
|
|
1966
|
+
const spans = [];
|
|
1967
|
+
let end;
|
|
1968
|
+
for (const piece of pieces) {
|
|
1969
|
+
if (piece.start === void 0 || end !== void 0 && piece.start < end) {
|
|
1970
|
+
return void 0;
|
|
1971
|
+
}
|
|
1972
|
+
if (end !== void 0 && piece.start > end) {
|
|
1973
|
+
spans.push({ start: end, end: piece.start });
|
|
1974
|
+
}
|
|
1975
|
+
let pos = piece.start;
|
|
1976
|
+
for (const id of piece.nodeIds) {
|
|
1977
|
+
const len = lengthOf.get(id) ?? 0;
|
|
1978
|
+
spans.push({ start: pos, end: pos + len });
|
|
1979
|
+
pos += len;
|
|
1980
|
+
}
|
|
1981
|
+
end = pos;
|
|
1982
|
+
}
|
|
1983
|
+
return spans;
|
|
1984
|
+
}
|
|
1965
1985
|
function sliceBetween(steps, span, region, flanked = true) {
|
|
1966
1986
|
if (!region || !flanked) {
|
|
1967
|
-
return { ids: steps, complete: true };
|
|
1987
|
+
return { ids: steps, complete: true, from: -1, to: -1 };
|
|
1968
1988
|
}
|
|
1969
1989
|
let i0 = -1;
|
|
1970
1990
|
let i1 = -1;
|
|
@@ -1984,17 +2004,22 @@ function sliceBetween(steps, span, region, flanked = true) {
|
|
|
1984
2004
|
}
|
|
1985
2005
|
});
|
|
1986
2006
|
if (i0 < 0 || i1 < 0) {
|
|
1987
|
-
return { ids: steps, complete: false };
|
|
2007
|
+
return { ids: steps, complete: false, from: -1, to: -1 };
|
|
1988
2008
|
}
|
|
1989
2009
|
const ids = steps.slice(Math.min(i0, i1) + 1, Math.max(i0, i1));
|
|
1990
|
-
return {
|
|
2010
|
+
return {
|
|
2011
|
+
ids: i0 < i1 ? ids : ids.reverse(),
|
|
2012
|
+
complete: true,
|
|
2013
|
+
from: i0,
|
|
2014
|
+
to: i1
|
|
2015
|
+
};
|
|
1991
2016
|
}
|
|
1992
2017
|
function walkRows(graph, region, unit) {
|
|
1993
2018
|
const paths = graph.paths ?? [];
|
|
1994
2019
|
const isReference2 = (p) => pathOrigin(p.name).name === graph.referencePath;
|
|
1995
|
-
const
|
|
1996
|
-
const first =
|
|
1997
|
-
const others = paths.filter((p) => !
|
|
2020
|
+
const referencePieces = paths.some(isReference2) ? paths.filter(isReference2).sort((a, b) => (a.start ?? 0) - (b.start ?? 0)) : paths.slice(0, 1);
|
|
2021
|
+
const first = referencePieces[0];
|
|
2022
|
+
const others = paths.filter((p) => !referencePieces.includes(p));
|
|
1998
2023
|
if (!first || others.length === 0) {
|
|
1999
2024
|
return void 0;
|
|
2000
2025
|
}
|
|
@@ -2006,7 +2031,7 @@ function walkRows(graph, region, unit) {
|
|
|
2006
2031
|
const referenceStart = first.start ?? 0;
|
|
2007
2032
|
const cut = region && region.end > region.start ? region : void 0;
|
|
2008
2033
|
const span = /* @__PURE__ */ new Map();
|
|
2009
|
-
for (const piece of
|
|
2034
|
+
for (const piece of referencePieces) {
|
|
2010
2035
|
let pos = piece.start ?? 0;
|
|
2011
2036
|
for (const id of piece.nodeIds) {
|
|
2012
2037
|
const len = lengthOf.get(id) ?? 0;
|
|
@@ -2020,12 +2045,15 @@ function walkRows(graph, region, unit) {
|
|
|
2020
2045
|
const rowOf = (pieces) => {
|
|
2021
2046
|
const path = pieces[0];
|
|
2022
2047
|
const ordered = [...pieces].sort((a, b) => (a.start ?? 0) - (b.start ?? 0));
|
|
2023
|
-
const { ids, complete } = sliceBetween(
|
|
2048
|
+
const { ids, complete, from, to } = sliceBetween(
|
|
2024
2049
|
stepsOf(ordered, lengthOf),
|
|
2025
2050
|
span,
|
|
2026
2051
|
cut,
|
|
2027
2052
|
flanked
|
|
2028
2053
|
);
|
|
2054
|
+
const spans = stepSpans(ordered, lengthOf);
|
|
2055
|
+
const contig = path.contig ?? panSNContig(pathOrigin(path.name).name);
|
|
2056
|
+
const axis = !spans?.length ? void 0 : from < 0 ? { contig, start: spans[0].start, reversed: false } : from < to ? { contig, start: spans[from].end, reversed: false } : { contig, start: spans[from].start, reversed: true };
|
|
2029
2057
|
const runs = [];
|
|
2030
2058
|
let bp = 0;
|
|
2031
2059
|
let offReferenceBp = 0;
|
|
@@ -2077,14 +2105,15 @@ function walkRows(graph, region, unit) {
|
|
|
2077
2105
|
offReferenceBp,
|
|
2078
2106
|
gapBp,
|
|
2079
2107
|
complete,
|
|
2080
|
-
runs
|
|
2108
|
+
runs,
|
|
2109
|
+
axis
|
|
2081
2110
|
};
|
|
2082
2111
|
};
|
|
2083
2112
|
const origin = cut ? cut.start : referenceStart;
|
|
2084
2113
|
return {
|
|
2085
2114
|
origin,
|
|
2086
2115
|
unit,
|
|
2087
|
-
reference: rowOf(
|
|
2116
|
+
reference: rowOf(referencePieces),
|
|
2088
2117
|
rows: [...walks.values()].map(rowOf).sort(
|
|
2089
2118
|
(a, b) => Number(b.complete) - Number(a.complete) || b.bp - a.bp || a.label.localeCompare(b.label)
|
|
2090
2119
|
)
|
|
@@ -2440,7 +2469,7 @@ function placeByWalks(graph, backbone) {
|
|
|
2440
2469
|
return placed;
|
|
2441
2470
|
}
|
|
2442
2471
|
function placeBySearch(adjacent, key) {
|
|
2443
|
-
const queue = [...key.entries()].sort(([a, ka], [b,
|
|
2472
|
+
const queue = [...key.entries()].sort(([a, ka], [b, kb2]) => compareKeys(ka, kb2) || compare(a, b)).map(([id]) => id);
|
|
2444
2473
|
const placed = queue.length;
|
|
2445
2474
|
for (const id of queue) {
|
|
2446
2475
|
const from = key.get(id);
|
|
@@ -3064,7 +3093,7 @@ var LAYOUT_MODES = [
|
|
|
3064
3093
|
{
|
|
3065
3094
|
value: "walkrows",
|
|
3066
3095
|
label: "Walk rows",
|
|
3067
|
-
description: "x is each walk's own bp: one bar per haplotype,
|
|
3096
|
+
description: "x is each walk's own bp: one bar per haplotype, blue on the reference's path and purple off it, so a repeat expansion reads as bar length, and each bar boxes its haplotype's own genes where the session has them. Needs W or P lines.",
|
|
3068
3097
|
run: walkRowLayout,
|
|
3069
3098
|
cutMargins: false,
|
|
3070
3099
|
wholeWalks: true,
|
|
@@ -4268,7 +4297,7 @@ function walkHighlight(graph, name) {
|
|
|
4268
4297
|
});
|
|
4269
4298
|
}
|
|
4270
4299
|
const reference = isReference(graph, name);
|
|
4271
|
-
const
|
|
4300
|
+
const referencePieces = reference ? [] : (graph.paths ?? []).filter((p) => isReference(graph, p.name));
|
|
4272
4301
|
return {
|
|
4273
4302
|
name,
|
|
4274
4303
|
reference,
|
|
@@ -4278,7 +4307,7 @@ function walkHighlight(graph, name) {
|
|
|
4278
4307
|
progress,
|
|
4279
4308
|
steps: pieces.reduce((sum, piece) => sum + piece.nodeIds.length, 0),
|
|
4280
4309
|
bp,
|
|
4281
|
-
referenceBp:
|
|
4310
|
+
referenceBp: referencePieces.length > 0 ? referencePieces.reduce((sum, piece) => sum + bpOf(piece), 0) : void 0
|
|
4282
4311
|
};
|
|
4283
4312
|
}
|
|
4284
4313
|
function laneColors(graph, walk, encoding, ramp) {
|
|
@@ -4405,6 +4434,28 @@ function walkPosition(walk, nodeId, length) {
|
|
|
4405
4434
|
return `${range.contig}:${groupDigits(start)}-${groupDigits(start + length)}`;
|
|
4406
4435
|
}
|
|
4407
4436
|
|
|
4437
|
+
// src/el.ts
|
|
4438
|
+
function el(tag, attrs = {}, ...children) {
|
|
4439
|
+
return {
|
|
4440
|
+
tag,
|
|
4441
|
+
attrs,
|
|
4442
|
+
children: children.filter((c) => !!c || c === "")
|
|
4443
|
+
};
|
|
4444
|
+
}
|
|
4445
|
+
function escapeText(s) {
|
|
4446
|
+
return s.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
4447
|
+
}
|
|
4448
|
+
function escapeAttr(s) {
|
|
4449
|
+
return escapeText(s).replaceAll('"', """);
|
|
4450
|
+
}
|
|
4451
|
+
function serializeEl(node) {
|
|
4452
|
+
if (typeof node === "string") {
|
|
4453
|
+
return escapeText(node);
|
|
4454
|
+
}
|
|
4455
|
+
const attrs = Object.entries(node.attrs).filter(([, v]) => v !== void 0).map(([k, v]) => ` ${k}="${escapeAttr(String(v))}"`).join("");
|
|
4456
|
+
return `<${node.tag}${attrs}>${node.children.map(serializeEl).join("")}</${node.tag}>`;
|
|
4457
|
+
}
|
|
4458
|
+
|
|
4408
4459
|
// src/facetGrid.ts
|
|
4409
4460
|
var FACET_GAP_PX = 8;
|
|
4410
4461
|
var FACET_TITLE_PX = 34;
|
|
@@ -4711,6 +4762,385 @@ function layoutLabels(m) {
|
|
|
4711
4762
|
};
|
|
4712
4763
|
}
|
|
4713
4764
|
|
|
4765
|
+
// src/referenceRampCss.ts
|
|
4766
|
+
function rampHueCss(hue) {
|
|
4767
|
+
return `hsl(${hue}, 70%, 50%)`;
|
|
4768
|
+
}
|
|
4769
|
+
function rampHue(bp, domain) {
|
|
4770
|
+
const frac = (bp - domain.start) / (domain.end - domain.start);
|
|
4771
|
+
return Math.max(0, Math.min(1, frac)) * REFERENCE_RAMP_MAX_HUE;
|
|
4772
|
+
}
|
|
4773
|
+
var HUE_STOP_DEG = 30;
|
|
4774
|
+
function rampStops({ start, bp, reversed }, domain) {
|
|
4775
|
+
const low = rampHue(start, domain);
|
|
4776
|
+
const high = rampHue(start + bp, domain);
|
|
4777
|
+
if (high - low < 1) {
|
|
4778
|
+
return [(low + high) / 2];
|
|
4779
|
+
}
|
|
4780
|
+
const n2 = Math.ceil((high - low) / HUE_STOP_DEG);
|
|
4781
|
+
return Array.from(
|
|
4782
|
+
{ length: n2 + 1 },
|
|
4783
|
+
(_, i) => rampHue(start + bp * (reversed ? n2 - i : i) / n2, domain)
|
|
4784
|
+
);
|
|
4785
|
+
}
|
|
4786
|
+
var RAMP_GRADIENT_CSS = `linear-gradient(to right, ${Array.from(
|
|
4787
|
+
{ length: 7 },
|
|
4788
|
+
(_, i) => `${rampHueCss(i / 6 * REFERENCE_RAMP_MAX_HUE)} ${i / 6 * 100}%`
|
|
4789
|
+
).join(", ")})`;
|
|
4790
|
+
|
|
4791
|
+
// src/layout/walkRowDraw.ts
|
|
4792
|
+
var ON_REFERENCE = "#2f8fd6";
|
|
4793
|
+
var OFF_REFERENCE = "#8e3fbf";
|
|
4794
|
+
var OUTSIDE_CUT = "#bdbdbd";
|
|
4795
|
+
var GENE_INK = "#1c1c22";
|
|
4796
|
+
var BAR_PX = 12;
|
|
4797
|
+
var GAP_PX = 4;
|
|
4798
|
+
var MIN_TILE_PX = 3;
|
|
4799
|
+
function kb(bp) {
|
|
4800
|
+
return `${(bp / 1e3).toFixed(bp < 1e4 ? 1 : 0)} kb`;
|
|
4801
|
+
}
|
|
4802
|
+
function units(bp, unit) {
|
|
4803
|
+
return unit ? ` \u2248 ${Math.round(bp / unit)} units` : "";
|
|
4804
|
+
}
|
|
4805
|
+
function walkRowReadout(row, reference, unit, call) {
|
|
4806
|
+
const { bp, gapBp, complete } = row;
|
|
4807
|
+
if (!reference) {
|
|
4808
|
+
return `${kb(bp)}${units(bp, unit)}`;
|
|
4809
|
+
}
|
|
4810
|
+
const delta = bp - reference.bp;
|
|
4811
|
+
const against = delta === 0 ? "" : ` (${delta > 0 ? "+" : "\u2212"}${kb(Math.abs(delta))})`;
|
|
4812
|
+
const outside = gapBp > 0 ? ` \xB7 ${kb(gapBp)} outside the cut` : "";
|
|
4813
|
+
const called = call ? ` \xB7 called ${kb(call.bp)}${call.spanningReads === 0 ? " \xB7 no spanning read" : ""}` : "";
|
|
4814
|
+
return `${kb(bp)}${units(bp, unit)}${against}${outside}${complete ? "" : " \xB7 partial walk"}${called}`;
|
|
4815
|
+
}
|
|
4816
|
+
function readoutPlacement(text, endX, width) {
|
|
4817
|
+
const x = endX + 6;
|
|
4818
|
+
const fits = x + text.length * LABEL_CHAR_PX < width;
|
|
4819
|
+
return fits ? { x, anchor: "start", halo: false } : { x: endX - 6, anchor: "end", halo: true };
|
|
4820
|
+
}
|
|
4821
|
+
function unitTicks(bp, unit, pxPerBp) {
|
|
4822
|
+
if (unit * pxPerBp < MIN_TILE_PX) {
|
|
4823
|
+
return [];
|
|
4824
|
+
}
|
|
4825
|
+
const ticks = [];
|
|
4826
|
+
for (let k = unit; k < bp; k += unit) {
|
|
4827
|
+
ticks.push(k);
|
|
4828
|
+
}
|
|
4829
|
+
return ticks;
|
|
4830
|
+
}
|
|
4831
|
+
function runPaint(run, ramp) {
|
|
4832
|
+
if (run.gap) {
|
|
4833
|
+
return { fill: OUTSIDE_CUT };
|
|
4834
|
+
}
|
|
4835
|
+
if (!ramp) {
|
|
4836
|
+
return { fill: run.onReference ? ON_REFERENCE : OFF_REFERENCE };
|
|
4837
|
+
}
|
|
4838
|
+
if (run.referenceStart === void 0) {
|
|
4839
|
+
return { fill: REFERENCE_RAMP_ALT_CSS };
|
|
4840
|
+
}
|
|
4841
|
+
const stops = rampStops({ ...run, start: run.referenceStart }, ramp);
|
|
4842
|
+
return stops.length === 1 ? { fill: rampHueCss(stops[0]) } : { stops: stops.map(rampHueCss) };
|
|
4843
|
+
}
|
|
4844
|
+
function alongRow(axis, start, end) {
|
|
4845
|
+
return axis.reversed ? { start: axis.start - end, end: axis.start - start } : { start: start - axis.start, end: end - axis.start };
|
|
4846
|
+
}
|
|
4847
|
+
function rowSpan(axis, bp) {
|
|
4848
|
+
return axis.reversed ? { start: axis.start - bp, end: axis.start } : { start: axis.start, end: axis.start + bp };
|
|
4849
|
+
}
|
|
4850
|
+
function placeRowGenes(rows, byRow) {
|
|
4851
|
+
const placed = /* @__PURE__ */ new Map();
|
|
4852
|
+
for (const row of rows) {
|
|
4853
|
+
const genes = byRow.get(row.name);
|
|
4854
|
+
if (!row.axis || !genes) {
|
|
4855
|
+
continue;
|
|
4856
|
+
}
|
|
4857
|
+
const axis = row.axis;
|
|
4858
|
+
const clip = ({ start, end }) => ({
|
|
4859
|
+
start: Math.max(0, start),
|
|
4860
|
+
end: Math.min(row.bp, end)
|
|
4861
|
+
});
|
|
4862
|
+
placed.set(
|
|
4863
|
+
row.name,
|
|
4864
|
+
genes.map((g) => ({
|
|
4865
|
+
name: g.name,
|
|
4866
|
+
...clip(alongRow(axis, g.start, g.end)),
|
|
4867
|
+
exons: g.exons.map((e) => clip(alongRow(axis, e.start, e.end))).filter((e) => e.end > e.start)
|
|
4868
|
+
})).filter((g) => g.end > g.start).sort((a, b) => a.start - b.start)
|
|
4869
|
+
);
|
|
4870
|
+
}
|
|
4871
|
+
return placed;
|
|
4872
|
+
}
|
|
4873
|
+
var GENE_FONT_PX = 9;
|
|
4874
|
+
var GENE_CHAR_PX = 5.2;
|
|
4875
|
+
function rowGeneBoxes(genes, X, y) {
|
|
4876
|
+
const boxes = genes.map((g) => {
|
|
4877
|
+
const x = X(g.start);
|
|
4878
|
+
return {
|
|
4879
|
+
g,
|
|
4880
|
+
x,
|
|
4881
|
+
w: Math.max(2, X(g.end) - x)
|
|
4882
|
+
};
|
|
4883
|
+
});
|
|
4884
|
+
const taken = [];
|
|
4885
|
+
const named = new Set(
|
|
4886
|
+
[...boxes].sort((a, b) => a.w - b.w).filter(({ g, x, w }) => {
|
|
4887
|
+
const half = g.name.length * GENE_CHAR_PX / 2;
|
|
4888
|
+
const at = [x + w / 2 - half, x + w / 2 + half];
|
|
4889
|
+
if (2 * half > w + 6 || taken.some(([a, b]) => at[0] < b + 2 && at[1] > a - 2)) {
|
|
4890
|
+
return false;
|
|
4891
|
+
}
|
|
4892
|
+
taken.push(at);
|
|
4893
|
+
return true;
|
|
4894
|
+
})
|
|
4895
|
+
);
|
|
4896
|
+
return boxes.map((box) => ({
|
|
4897
|
+
name: box.g.name,
|
|
4898
|
+
x: box.x,
|
|
4899
|
+
y: y - BAR_PX / 2 - 2,
|
|
4900
|
+
w: box.w,
|
|
4901
|
+
h: BAR_PX + 4,
|
|
4902
|
+
exons: box.g.exons.map((e) => ({
|
|
4903
|
+
x: X(e.start),
|
|
4904
|
+
w: Math.max(1, X(e.end) - X(e.start))
|
|
4905
|
+
})),
|
|
4906
|
+
label: named.has(box) ? { x: box.x + box.w / 2, y: y + 3, size: GENE_FONT_PX } : void 0
|
|
4907
|
+
}));
|
|
4908
|
+
}
|
|
4909
|
+
var rowsText = (n2) => `${n2} row${n2 === 1 ? "" : "s"}`;
|
|
4910
|
+
function walkRowsKey(bars, o = {}) {
|
|
4911
|
+
const entries = [
|
|
4912
|
+
{
|
|
4913
|
+
swatch: {
|
|
4914
|
+
kind: "bar",
|
|
4915
|
+
fill: o.ramp ? o.rampCss ?? ON_REFERENCE : ON_REFERENCE
|
|
4916
|
+
},
|
|
4917
|
+
label: `on ${bars.reference.label}'s path`
|
|
4918
|
+
},
|
|
4919
|
+
{
|
|
4920
|
+
swatch: {
|
|
4921
|
+
kind: "bar",
|
|
4922
|
+
fill: o.ramp ? REFERENCE_RAMP_ALT_CSS : OFF_REFERENCE
|
|
4923
|
+
},
|
|
4924
|
+
label: `off ${bars.reference.label}'s path`
|
|
4925
|
+
}
|
|
4926
|
+
];
|
|
4927
|
+
if ([bars.reference, ...bars.rows].some((row) => row.gapBp > 0)) {
|
|
4928
|
+
entries.push({
|
|
4929
|
+
swatch: { kind: "gap", fill: OUTSIDE_CUT },
|
|
4930
|
+
label: "walked outside the cut"
|
|
4931
|
+
});
|
|
4932
|
+
}
|
|
4933
|
+
if (o.genes) {
|
|
4934
|
+
entries.push({
|
|
4935
|
+
swatch: { kind: "gene" },
|
|
4936
|
+
label: "genes, each row's own annotation"
|
|
4937
|
+
});
|
|
4938
|
+
if (o.genes.untracked) {
|
|
4939
|
+
entries.push({
|
|
4940
|
+
swatch: { kind: "gene" },
|
|
4941
|
+
label: `no gene track for ${rowsText(o.genes.untracked)}`,
|
|
4942
|
+
note: true
|
|
4943
|
+
});
|
|
4944
|
+
}
|
|
4945
|
+
if (o.genes.unplaced) {
|
|
4946
|
+
entries.push({
|
|
4947
|
+
swatch: { kind: "gene" },
|
|
4948
|
+
label: `no contig coordinates for ${rowsText(o.genes.unplaced)}`,
|
|
4949
|
+
note: true
|
|
4950
|
+
});
|
|
4951
|
+
}
|
|
4952
|
+
if (o.genes.unread) {
|
|
4953
|
+
entries.push({
|
|
4954
|
+
swatch: { kind: "gene" },
|
|
4955
|
+
label: `genes not read for the last ${rowsText(o.genes.unread)}`,
|
|
4956
|
+
note: true
|
|
4957
|
+
});
|
|
4958
|
+
}
|
|
4959
|
+
}
|
|
4960
|
+
return entries;
|
|
4961
|
+
}
|
|
4962
|
+
var CALL_TICK = "#111";
|
|
4963
|
+
var UNBACKED_TICK = "#9e9e9e";
|
|
4964
|
+
var DISAGREES = "#c62828";
|
|
4965
|
+
function walkRowsKeyTree(entries, x, y) {
|
|
4966
|
+
let at = 0;
|
|
4967
|
+
const parts = entries.flatMap((e) => {
|
|
4968
|
+
const swatch = e.note ? void 0 : e.swatch.kind === "gene" ? el("rect", {
|
|
4969
|
+
x: at,
|
|
4970
|
+
y: 5,
|
|
4971
|
+
width: 18,
|
|
4972
|
+
height: 8,
|
|
4973
|
+
fill: "none",
|
|
4974
|
+
stroke: GENE_INK,
|
|
4975
|
+
"stroke-width": 1.5
|
|
4976
|
+
}) : el("rect", {
|
|
4977
|
+
x: at,
|
|
4978
|
+
y: e.swatch.kind === "gap" ? 7 : 5,
|
|
4979
|
+
width: 18,
|
|
4980
|
+
height: e.swatch.kind === "gap" ? GAP_PX : 8,
|
|
4981
|
+
rx: 2,
|
|
4982
|
+
fill: e.swatch.fill
|
|
4983
|
+
});
|
|
4984
|
+
const text = el(
|
|
4985
|
+
"text",
|
|
4986
|
+
{
|
|
4987
|
+
x: e.note ? at : at + 23,
|
|
4988
|
+
y: 13,
|
|
4989
|
+
"font-style": e.note ? "italic" : void 0,
|
|
4990
|
+
fill: e.note ? "#666" : void 0
|
|
4991
|
+
},
|
|
4992
|
+
e.label
|
|
4993
|
+
);
|
|
4994
|
+
at += (e.note ? 0 : 23) + e.label.length * LABEL_CHAR_PX + 16;
|
|
4995
|
+
return swatch ? [swatch, text] : [text];
|
|
4996
|
+
});
|
|
4997
|
+
return {
|
|
4998
|
+
width: at,
|
|
4999
|
+
tree: el(
|
|
5000
|
+
"g",
|
|
5001
|
+
{
|
|
5002
|
+
transform: `translate(${x} ${y})`,
|
|
5003
|
+
"font-family": "Helvetica, Arial, sans-serif",
|
|
5004
|
+
"font-size": 11
|
|
5005
|
+
},
|
|
5006
|
+
...parts
|
|
5007
|
+
)
|
|
5008
|
+
};
|
|
5009
|
+
}
|
|
5010
|
+
function geneTree(box, y) {
|
|
5011
|
+
return el(
|
|
5012
|
+
"g",
|
|
5013
|
+
{ class: "row-gene", "data-testid": "graph-walk-gene" },
|
|
5014
|
+
el("title", {}, box.name),
|
|
5015
|
+
...box.exons.map(
|
|
5016
|
+
(e) => el("rect", {
|
|
5017
|
+
x: e.x,
|
|
5018
|
+
y: y - BAR_PX / 2,
|
|
5019
|
+
width: e.w,
|
|
5020
|
+
height: BAR_PX,
|
|
5021
|
+
fill: GENE_INK,
|
|
5022
|
+
opacity: 0.35
|
|
5023
|
+
})
|
|
5024
|
+
),
|
|
5025
|
+
el("rect", {
|
|
5026
|
+
x: box.x,
|
|
5027
|
+
y: box.y,
|
|
5028
|
+
width: box.w,
|
|
5029
|
+
height: box.h,
|
|
5030
|
+
fill: "none",
|
|
5031
|
+
stroke: GENE_INK,
|
|
5032
|
+
"stroke-width": 1.5
|
|
5033
|
+
}),
|
|
5034
|
+
box.label && el(
|
|
5035
|
+
"text",
|
|
5036
|
+
{
|
|
5037
|
+
x: box.label.x,
|
|
5038
|
+
y: box.label.y,
|
|
5039
|
+
"font-family": "sans-serif",
|
|
5040
|
+
"font-size": box.label.size,
|
|
5041
|
+
"font-weight": 600,
|
|
5042
|
+
"text-anchor": "middle",
|
|
5043
|
+
fill: GENE_INK,
|
|
5044
|
+
stroke: "white",
|
|
5045
|
+
"stroke-width": 2.5,
|
|
5046
|
+
"paint-order": "stroke"
|
|
5047
|
+
},
|
|
5048
|
+
box.name
|
|
5049
|
+
)
|
|
5050
|
+
);
|
|
5051
|
+
}
|
|
5052
|
+
function walkRowsTree(bars, frame, o = {}) {
|
|
5053
|
+
const X = (bp) => bp * frame.scaleX + frame.translateX;
|
|
5054
|
+
const Y = (row) => row * ROW_HEIGHT_PX * frame.scaleY + frame.translateY;
|
|
5055
|
+
const { origin, unit, reference, rows } = bars;
|
|
5056
|
+
const along = (offset) => X(origin + offset);
|
|
5057
|
+
const prefix = o.idPrefix ?? "walkrow";
|
|
5058
|
+
const rowTree = (row, i) => {
|
|
5059
|
+
const y = Y(i);
|
|
5060
|
+
if (y < -BAR_PX || y > frame.height + BAR_PX) {
|
|
5061
|
+
return void 0;
|
|
5062
|
+
}
|
|
5063
|
+
const runs = row.runs.flatMap((run) => {
|
|
5064
|
+
const paint2 = runPaint(run, o.ramp);
|
|
5065
|
+
const h = run.gap ? GAP_PX : BAR_PX;
|
|
5066
|
+
const id = `${prefix}-${i}-${run.start}`;
|
|
5067
|
+
const rect = el("rect", {
|
|
5068
|
+
x: along(run.start),
|
|
5069
|
+
y: y - h / 2,
|
|
5070
|
+
width: Math.max(1, run.bp * frame.scaleX),
|
|
5071
|
+
height: h,
|
|
5072
|
+
fill: "stops" in paint2 ? `url(#${id})` : paint2.fill
|
|
5073
|
+
});
|
|
5074
|
+
return "stops" in paint2 ? [
|
|
5075
|
+
el(
|
|
5076
|
+
"linearGradient",
|
|
5077
|
+
{ id },
|
|
5078
|
+
...paint2.stops.map(
|
|
5079
|
+
(color, k) => el("stop", {
|
|
5080
|
+
offset: k / (paint2.stops.length - 1),
|
|
5081
|
+
"stop-color": color
|
|
5082
|
+
})
|
|
5083
|
+
)
|
|
5084
|
+
),
|
|
5085
|
+
rect
|
|
5086
|
+
] : [rect];
|
|
5087
|
+
});
|
|
5088
|
+
const ticks = unit ? unitTicks(row.bp, unit, frame.scaleX).map(
|
|
5089
|
+
(k) => el("line", {
|
|
5090
|
+
x1: along(k),
|
|
5091
|
+
x2: along(k),
|
|
5092
|
+
y1: y - BAR_PX / 2,
|
|
5093
|
+
y2: y + BAR_PX / 2,
|
|
5094
|
+
stroke: "white",
|
|
5095
|
+
"stroke-width": 1
|
|
5096
|
+
})
|
|
5097
|
+
) : [];
|
|
5098
|
+
const { call } = row;
|
|
5099
|
+
const text = walkRowReadout(
|
|
5100
|
+
row,
|
|
5101
|
+
i === 0 ? void 0 : reference,
|
|
5102
|
+
unit,
|
|
5103
|
+
call
|
|
5104
|
+
);
|
|
5105
|
+
const at = readoutPlacement(text, along(row.bp), frame.width);
|
|
5106
|
+
return el(
|
|
5107
|
+
"g",
|
|
5108
|
+
{
|
|
5109
|
+
"data-testid": i === 0 ? "graph-walk-reference" : "graph-walk-row"
|
|
5110
|
+
},
|
|
5111
|
+
...runs,
|
|
5112
|
+
...ticks,
|
|
5113
|
+
...rowGeneBoxes(o.rowGenes?.get(row.name) ?? [], along, y).map(
|
|
5114
|
+
(box) => geneTree(box, y)
|
|
5115
|
+
),
|
|
5116
|
+
call && el("rect", {
|
|
5117
|
+
"data-testid": "graph-walk-call",
|
|
5118
|
+
x: along(call.bp) - 1,
|
|
5119
|
+
y: y - BAR_PX / 2 - 3,
|
|
5120
|
+
width: 2,
|
|
5121
|
+
height: BAR_PX + 6,
|
|
5122
|
+
fill: call.spanningReads === 0 ? UNBACKED_TICK : CALL_TICK
|
|
5123
|
+
}),
|
|
5124
|
+
el(
|
|
5125
|
+
"text",
|
|
5126
|
+
{
|
|
5127
|
+
x: at.x,
|
|
5128
|
+
y: y + 4,
|
|
5129
|
+
"font-family": "sans-serif",
|
|
5130
|
+
"font-size": 11,
|
|
5131
|
+
fill: call?.agrees === false ? DISAGREES : "#333",
|
|
5132
|
+
stroke: at.halo ? "white" : void 0,
|
|
5133
|
+
"stroke-width": at.halo ? 3 : void 0,
|
|
5134
|
+
"paint-order": "stroke",
|
|
5135
|
+
"text-anchor": at.anchor
|
|
5136
|
+
},
|
|
5137
|
+
text
|
|
5138
|
+
)
|
|
5139
|
+
);
|
|
5140
|
+
};
|
|
5141
|
+
return el("g", {}, ...[reference, ...rows].map(rowTree));
|
|
5142
|
+
}
|
|
5143
|
+
|
|
4714
5144
|
// src/renderer/svgCanvas.ts
|
|
4715
5145
|
var n = (v) => +v.toFixed(1);
|
|
4716
5146
|
function paint(css) {
|
|
@@ -4824,7 +5254,7 @@ function svgCanvas(width, height) {
|
|
|
4824
5254
|
}
|
|
4825
5255
|
|
|
4826
5256
|
// src/version.ts
|
|
4827
|
-
var version = "4.
|
|
5257
|
+
var version = "4.1.1";
|
|
4828
5258
|
|
|
4829
5259
|
// src/viewport.ts
|
|
4830
5260
|
function axisScaleOf(scale, pixelRows) {
|
|
@@ -4869,12 +5299,12 @@ function screenToLayout(x, y, t, axis) {
|
|
|
4869
5299
|
|
|
4870
5300
|
// src/figure.ts
|
|
4871
5301
|
var FONT = 'font-family="Helvetica, Arial, sans-serif" font-size="11"';
|
|
4872
|
-
var
|
|
5302
|
+
var BAR_PX2 = 48;
|
|
4873
5303
|
var SWATCH_PX = 18;
|
|
4874
5304
|
var KEY_GAP_PX = 16;
|
|
4875
5305
|
var FADED = "rgb(160,160,160)";
|
|
4876
5306
|
var EXON_COLOR = "#daa520";
|
|
4877
|
-
var
|
|
5307
|
+
var GENE_INK2 = "#1c1c22";
|
|
4878
5308
|
var MIN_LANE_PX = 4;
|
|
4879
5309
|
var EXON_GAP_PX = 1;
|
|
4880
5310
|
var EXON_LINE_PX = 2;
|
|
@@ -4882,7 +5312,7 @@ function esc(s) {
|
|
|
4882
5312
|
return s.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
4883
5313
|
}
|
|
4884
5314
|
function keySvg(id, x, y, stops, label, after, under, opacity = 1) {
|
|
4885
|
-
const bar = stops.length > 1 ?
|
|
5315
|
+
const bar = stops.length > 1 ? BAR_PX2 : SWATCH_PX;
|
|
4886
5316
|
const fill = stops.length > 1 ? `fill="url(#${id})"` : `fill="${stops[0].color}"${opacity < 1 ? ` fill-opacity="${opacity}"` : ""}`;
|
|
4887
5317
|
const defs = stops.length > 1 ? `<linearGradient id="${id}">${stops.map((s) => `<stop offset="${s.offset}" stop-color="${s.color}"/>`).join("")}</linearGradient>` : "";
|
|
4888
5318
|
const width = Math.max(
|
|
@@ -4913,15 +5343,17 @@ function screenPath(d, t) {
|
|
|
4913
5343
|
);
|
|
4914
5344
|
}
|
|
4915
5345
|
function chip(x, y, w, name, note) {
|
|
4916
|
-
return `<rect x="${x - w / 2}" y="${y - LABEL_PX - LABEL_PAD + 2}" width="${w}" height="${LABEL_PX + LABEL_PAD * 2 - 2}" rx="3" fill="#fff" fill-opacity="0.85" stroke="${EXON_COLOR}"/><text x="${x}" y="${y}" font-family="Helvetica, Arial, sans-serif" font-size="${LABEL_PX}" fill="${
|
|
5346
|
+
return `<rect x="${x - w / 2}" y="${y - LABEL_PX - LABEL_PAD + 2}" width="${w}" height="${LABEL_PX + LABEL_PAD * 2 - 2}" rx="3" fill="#fff" fill-opacity="0.85" stroke="${EXON_COLOR}"/><text x="${x}" y="${y}" font-family="Helvetica, Arial, sans-serif" font-size="${LABEL_PX}" fill="${GENE_INK2}" text-anchor="middle"><tspan font-style="italic" font-weight="600">${esc(name)}</tspan>${note ? esc(note) : ""}</text>`;
|
|
4917
5347
|
}
|
|
4918
5348
|
function figureSvg(graph, layout, o = {}) {
|
|
4919
5349
|
const width = o.width ?? 1200;
|
|
4920
5350
|
const room = o.height ?? 800;
|
|
4921
5351
|
const region = o.region;
|
|
4922
5352
|
const rampDomain = o.colorDomain ?? region;
|
|
5353
|
+
const rows = o.walkRows;
|
|
4923
5354
|
const bounds = drawingBounds(layout, {
|
|
4924
|
-
region: o.fitToDrawing ? void 0 : region
|
|
5355
|
+
region: o.fitToDrawing ? void 0 : region,
|
|
5356
|
+
extent: rows && layout.extent ? walkRowsExtent(rows) : void 0
|
|
4925
5357
|
});
|
|
4926
5358
|
const pixelRows = layout.pixelRows ?? false;
|
|
4927
5359
|
const nodeById = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
@@ -4946,7 +5378,7 @@ function figureSvg(graph, layout, o = {}) {
|
|
|
4946
5378
|
};
|
|
4947
5379
|
const contigThickness = o.contigThickness ?? 6;
|
|
4948
5380
|
const nodeWidth2 = o.nodeWidth ?? "depth";
|
|
4949
|
-
const pins = o.genes?.length && !layout.tubeMap ? genePins(graph, o.genes, layout.nodePositions) : [];
|
|
5381
|
+
const pins = o.genes?.length && !layout.tubeMap && !rows ? genePins(graph, o.genes, layout.nodePositions) : [];
|
|
4950
5382
|
const ink = nodeInk(graph, nodeById, contigThickness, nodeWidth2);
|
|
4951
5383
|
let masks = 0;
|
|
4952
5384
|
function overlays(highlight, t, w, h) {
|
|
@@ -4982,11 +5414,32 @@ function figureSvg(graph, layout, o = {}) {
|
|
|
4982
5414
|
)) {
|
|
4983
5415
|
const pinY = screen(pin.at).y + contigThickness / 2;
|
|
4984
5416
|
out.push(
|
|
4985
|
-
`<line x1="${x}" x2="${x}" y1="${y - LABEL_PX - 2}" y2="${pinY}" stroke="${
|
|
5417
|
+
`<line x1="${x}" x2="${x}" y1="${y - LABEL_PX - 2}" y2="${pinY}" stroke="${GENE_INK2}" stroke-width="0.8" stroke-opacity="0.6"/>`,
|
|
4986
5418
|
chip(x, y, cw, pin.gene.name, text.slice(pin.gene.name.length))
|
|
4987
5419
|
);
|
|
4988
5420
|
}
|
|
4989
|
-
|
|
5421
|
+
if (rows) {
|
|
5422
|
+
out.push(
|
|
5423
|
+
serializeEl(
|
|
5424
|
+
walkRowsTree(
|
|
5425
|
+
rows,
|
|
5426
|
+
{ ...t, width: w, height: h },
|
|
5427
|
+
{
|
|
5428
|
+
ramp: referenceRamp && {
|
|
5429
|
+
start: referenceRamp.start,
|
|
5430
|
+
end: referenceRamp.start + referenceRamp.span
|
|
5431
|
+
},
|
|
5432
|
+
rowGenes: o.rowGenes
|
|
5433
|
+
}
|
|
5434
|
+
)
|
|
5435
|
+
)
|
|
5436
|
+
);
|
|
5437
|
+
}
|
|
5438
|
+
const rowLabels = rows ? [rows.reference, ...rows.rows].map((r, i) => ({
|
|
5439
|
+
label: r.label,
|
|
5440
|
+
y: i * ROW_HEIGHT_PX
|
|
5441
|
+
})) : layout.rowLabels ?? [];
|
|
5442
|
+
for (const { label, y } of rowLabels) {
|
|
4990
5443
|
const sy = y * t.scaleY + t.translateY;
|
|
4991
5444
|
if (sy >= 0 && sy <= h) {
|
|
4992
5445
|
out.push(
|
|
@@ -5017,7 +5470,7 @@ function figureSvg(graph, layout, o = {}) {
|
|
|
5017
5470
|
const renderer = new Canvas2DRenderer(canvas);
|
|
5018
5471
|
renderer.uploadGeometry(
|
|
5019
5472
|
buildGeometry({
|
|
5020
|
-
nodePositions: layout.nodePositions,
|
|
5473
|
+
nodePositions: rows ? {} : layout.nodePositions,
|
|
5021
5474
|
graph,
|
|
5022
5475
|
nodeById,
|
|
5023
5476
|
colorScheme,
|
|
@@ -5093,7 +5546,21 @@ function figureSvg(graph, layout, o = {}) {
|
|
|
5093
5546
|
0.3
|
|
5094
5547
|
)
|
|
5095
5548
|
);
|
|
5096
|
-
}
|
|
5549
|
+
}
|
|
5550
|
+
if (rows) {
|
|
5551
|
+
const key = walkRowsKeyTree(
|
|
5552
|
+
walkRowsKey(rows, {
|
|
5553
|
+
ramp: referenceRamp && {
|
|
5554
|
+
start: referenceRamp.start,
|
|
5555
|
+
end: referenceRamp.start + referenceRamp.span
|
|
5556
|
+
},
|
|
5557
|
+
genes: o.rowGenes?.size ? o.rowGeneGaps : void 0
|
|
5558
|
+
}),
|
|
5559
|
+
x,
|
|
5560
|
+
2
|
|
5561
|
+
);
|
|
5562
|
+
push({ width: key.width, markup: serializeEl(key.tree) });
|
|
5563
|
+
} else if (!lift && referenceRamp) {
|
|
5097
5564
|
push(
|
|
5098
5565
|
keySvg(
|
|
5099
5566
|
"ramp",
|
|
@@ -5243,8 +5710,25 @@ function genesFromGff3Lines(lines) {
|
|
|
5243
5710
|
}
|
|
5244
5711
|
return genes;
|
|
5245
5712
|
}
|
|
5713
|
+
function mergeOverlappingByName(genes) {
|
|
5714
|
+
const out = [];
|
|
5715
|
+
const open = /* @__PURE__ */ new Map();
|
|
5716
|
+
for (const g of [...genes].sort((a, b) => a.start - b.start)) {
|
|
5717
|
+
const key = `${g.refName} ${g.strand} ${g.name}`;
|
|
5718
|
+
const last = open.get(key);
|
|
5719
|
+
if (last && g.start < last.end) {
|
|
5720
|
+
last.end = Math.max(last.end, g.end);
|
|
5721
|
+
last.exons = mergedIntervals([...last.exons, ...g.exons]);
|
|
5722
|
+
} else {
|
|
5723
|
+
const gene = { ...g, exons: mergedIntervals(g.exons) };
|
|
5724
|
+
out.push(gene);
|
|
5725
|
+
open.set(key, gene);
|
|
5726
|
+
}
|
|
5727
|
+
}
|
|
5728
|
+
return out;
|
|
5729
|
+
}
|
|
5246
5730
|
function genesFromBed(text) {
|
|
5247
|
-
const
|
|
5731
|
+
const rows = [];
|
|
5248
5732
|
for (const line of text.split("\n")) {
|
|
5249
5733
|
const cols = line.replace(/\r$/, "").split(" ");
|
|
5250
5734
|
const start = Number(cols[1]);
|
|
@@ -5260,24 +5744,16 @@ function genesFromBed(text) {
|
|
|
5260
5744
|
start: start + starts[i],
|
|
5261
5745
|
end: start + starts[i] + size
|
|
5262
5746
|
})) : [{ start, end }];
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
name,
|
|
5272
|
-
refName,
|
|
5273
|
-
start,
|
|
5274
|
-
end,
|
|
5275
|
-
strand: strandOf(cols[5]),
|
|
5276
|
-
exons: mergedIntervals(blocks)
|
|
5277
|
-
});
|
|
5278
|
-
}
|
|
5747
|
+
rows.push({
|
|
5748
|
+
name,
|
|
5749
|
+
refName,
|
|
5750
|
+
start,
|
|
5751
|
+
end,
|
|
5752
|
+
strand: strandOf(cols[5]),
|
|
5753
|
+
exons: blocks
|
|
5754
|
+
});
|
|
5279
5755
|
}
|
|
5280
|
-
return
|
|
5756
|
+
return mergeOverlappingByName(rows);
|
|
5281
5757
|
}
|
|
5282
5758
|
function genesFromText(text) {
|
|
5283
5759
|
const first = text.split("\n", 1e3).find((l) => l.trim() !== "" && !/^(#|track|browser)/.test(l));
|
|
@@ -5612,13 +6088,13 @@ async function referencePathQuery(db, referenceSample2, refName) {
|
|
|
5612
6088
|
haplotype: path.name.haplotype
|
|
5613
6089
|
} : void 0;
|
|
5614
6090
|
}
|
|
5615
|
-
function nodeLimitError(error, limit, windowBp
|
|
6091
|
+
function nodeLimitError(error, limit, windowBp) {
|
|
5616
6092
|
const isLimit = error instanceof Error && (error.name === "SubgraphLimitError" || /^Subgraph size limit of \d+ nodes exceeded/.test(error.message));
|
|
5617
6093
|
if (!isLimit) {
|
|
5618
6094
|
return void 0;
|
|
5619
6095
|
} else {
|
|
5620
6096
|
const walked = error.walkedBp;
|
|
5621
|
-
const fits = typeof walked === "number" && walked > 0 ? Math.floor(
|
|
6097
|
+
const fits = typeof walked === "number" && walked > 0 ? Math.floor(walked * 0.8) : Math.floor(windowBp / 2);
|
|
5622
6098
|
return new NodeLimitError(limit, windowBp, Math.max(fits, 1));
|
|
5623
6099
|
}
|
|
5624
6100
|
}
|
|
@@ -5627,44 +6103,16 @@ var GBZ_CUT_DEFAULTS = {
|
|
|
5627
6103
|
snarls: "contained",
|
|
5628
6104
|
limit: 1e5
|
|
5629
6105
|
};
|
|
5630
|
-
async function
|
|
5631
|
-
const inside = (await db.paths()).filter(
|
|
5632
|
-
({ isIndexed, name }) => isIndexed && name.sample === query.sample && name.haplotype === query.haplotype && name.contig === query.contig && name.fragment > start && name.fragment < end
|
|
5633
|
-
).map((path) => path.name.fragment);
|
|
5634
|
-
const bounds = [start, ...[...new Set(inside)].sort((a, b) => a - b), end];
|
|
5635
|
-
return bounds.slice(1).map((pieceEnd, i) => ({
|
|
5636
|
-
start: bounds[i],
|
|
5637
|
-
end: pieceEnd
|
|
5638
|
-
}));
|
|
5639
|
-
}
|
|
5640
|
-
async function cutWindowGFA(db, query, start, end, { keep, ...opts }) {
|
|
6106
|
+
async function cutWindowGFA(db, query, start, end, opts) {
|
|
5641
6107
|
if (!query) {
|
|
5642
6108
|
return "";
|
|
5643
6109
|
}
|
|
5644
|
-
const
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
(piece) => db.getSubgraphForRange(query, piece.start, piece.end, {
|
|
5648
|
-
...opts,
|
|
5649
|
-
haplotypes: "all",
|
|
5650
|
-
...keep === void 0 ? {} : { keep }
|
|
5651
|
-
}).catch((error) => {
|
|
5652
|
-
throw nodeLimitError(
|
|
5653
|
-
error,
|
|
5654
|
-
opts.limit,
|
|
5655
|
-
end - start,
|
|
5656
|
-
piece.start - start
|
|
5657
|
-
) ?? error;
|
|
5658
|
-
})
|
|
5659
|
-
)
|
|
5660
|
-
);
|
|
6110
|
+
const subgraphs = await db.getSubgraphs({ ...opts, path: query, start, end, haplotypes: "all" }).catch((error) => {
|
|
6111
|
+
throw nodeLimitError(error, opts.limit, end - start) ?? error;
|
|
6112
|
+
});
|
|
5661
6113
|
const paths = await db.paths();
|
|
5662
6114
|
return joinCuts(
|
|
5663
|
-
await Promise.all(
|
|
5664
|
-
subgraphs.flatMap(
|
|
5665
|
-
(subgraph) => subgraph ? [subgraph.toGFA({ names: "resolved" })] : []
|
|
5666
|
-
)
|
|
5667
|
-
),
|
|
6115
|
+
await Promise.all(subgraphs.map((subgraph) => subgraph.toGFA())),
|
|
5668
6116
|
(sample, haplotype, contig, at) => paths.some(
|
|
5669
6117
|
({ name }) => name.sample === sample && name.haplotype === haplotype && name.contig === contig && name.fragment === at
|
|
5670
6118
|
)
|
|
@@ -5692,7 +6140,7 @@ function parseRegion(text) {
|
|
|
5692
6140
|
return { refName: m[1], start: n2(m[2]), end: n2(m[3]) };
|
|
5693
6141
|
}
|
|
5694
6142
|
async function openGbz(db, index) {
|
|
5695
|
-
const base = await GBZBase.open(db,
|
|
6143
|
+
const base = await GBZBase.open({ source: db, haplotypeIndex: index });
|
|
5696
6144
|
return { base, referenceSamples: await referenceSamplesOf(base) };
|
|
5697
6145
|
}
|
|
5698
6146
|
function referenceSample(ref, samples) {
|
|
@@ -5723,7 +6171,7 @@ async function cutGbzRegion({ base, referenceSamples }, src, signal) {
|
|
|
5723
6171
|
snarls: src.snarls ?? GBZ_CUT_DEFAULTS.snarls,
|
|
5724
6172
|
limit: GBZ_CUT_DEFAULTS.limit,
|
|
5725
6173
|
signal,
|
|
5726
|
-
|
|
6174
|
+
keep: wanted ? (name) => haplotypeWanted(name, wanted) : void 0
|
|
5727
6175
|
});
|
|
5728
6176
|
return { text, region, sample };
|
|
5729
6177
|
}
|
|
@@ -5801,6 +6249,8 @@ export {
|
|
|
5801
6249
|
rangeText,
|
|
5802
6250
|
walkKey,
|
|
5803
6251
|
walkPosition,
|
|
6252
|
+
el,
|
|
6253
|
+
serializeEl,
|
|
5804
6254
|
FACET_GAP_PX,
|
|
5805
6255
|
FACET_TITLE_PX,
|
|
5806
6256
|
FACET_PAD_PX,
|
|
@@ -5812,6 +6262,28 @@ export {
|
|
|
5812
6262
|
LEGEND_INSET_PX,
|
|
5813
6263
|
geneCoverageNote,
|
|
5814
6264
|
layoutLabels,
|
|
6265
|
+
rampHueCss,
|
|
6266
|
+
rampHue,
|
|
6267
|
+
rampStops,
|
|
6268
|
+
RAMP_GRADIENT_CSS,
|
|
6269
|
+
ON_REFERENCE,
|
|
6270
|
+
OFF_REFERENCE,
|
|
6271
|
+
OUTSIDE_CUT,
|
|
6272
|
+
GENE_INK,
|
|
6273
|
+
BAR_PX,
|
|
6274
|
+
GAP_PX,
|
|
6275
|
+
walkRowReadout,
|
|
6276
|
+
readoutPlacement,
|
|
6277
|
+
unitTicks,
|
|
6278
|
+
runPaint,
|
|
6279
|
+
alongRow,
|
|
6280
|
+
rowSpan,
|
|
6281
|
+
placeRowGenes,
|
|
6282
|
+
rowGeneBoxes,
|
|
6283
|
+
walkRowsKey,
|
|
6284
|
+
DISAGREES,
|
|
6285
|
+
walkRowsKeyTree,
|
|
6286
|
+
walkRowsTree,
|
|
5815
6287
|
svgCanvas,
|
|
5816
6288
|
version,
|
|
5817
6289
|
axisScaleOf,
|
|
@@ -5822,6 +6294,7 @@ export {
|
|
|
5822
6294
|
screenToLayout,
|
|
5823
6295
|
figureSvg,
|
|
5824
6296
|
genesFromGff3Lines,
|
|
6297
|
+
mergeOverlappingByName,
|
|
5825
6298
|
genesFromBed,
|
|
5826
6299
|
genesFromText,
|
|
5827
6300
|
WELL_KNOWN_SAMPLES,
|