@jbrowse/bandage-core 0.1.3 → 0.1.5
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/index.js +95 -4
- package/dist/types/index.d.ts +2 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -269,12 +269,12 @@ function parseGFA(file) {
|
|
|
269
269
|
});
|
|
270
270
|
}
|
|
271
271
|
} else if (line.startsWith("W")) {
|
|
272
|
-
const [, sample, hap,
|
|
273
|
-
if (sample && hap &&
|
|
272
|
+
const [, sample, hap, contig2, start, end, body, ...rest] = line.split(" ");
|
|
273
|
+
if (sample && hap && contig2 && start && end && body) {
|
|
274
274
|
graph.walks.push({
|
|
275
275
|
sample,
|
|
276
276
|
haplotype: +hap,
|
|
277
|
-
contig,
|
|
277
|
+
contig: contig2,
|
|
278
278
|
start: start === "*" ? -1 : +start,
|
|
279
279
|
end: end === "*" ? -1 : +end,
|
|
280
280
|
segments: parseWalkBody(body),
|
|
@@ -660,6 +660,14 @@ function splitRuns(positions, runs, weightOf) {
|
|
|
660
660
|
}
|
|
661
661
|
return out;
|
|
662
662
|
}
|
|
663
|
+
function polylineSlice(line, from, to) {
|
|
664
|
+
if (line.length === 0) {
|
|
665
|
+
return [];
|
|
666
|
+
}
|
|
667
|
+
const arc = arcPrefix(line);
|
|
668
|
+
const total = arc.at(-1);
|
|
669
|
+
return slice(line, arc, from * total, to * total);
|
|
670
|
+
}
|
|
663
671
|
function polylineMidpoint(line) {
|
|
664
672
|
const arc = arcPrefix(line);
|
|
665
673
|
return pointAt(line, arc, arc.at(-1) / 2);
|
|
@@ -5063,6 +5071,7 @@ var HALO_FACTOR = 3.4;
|
|
|
5063
5071
|
var LEGEND_INSET_PX = 6;
|
|
5064
5072
|
var ROUTE_STACK = 8;
|
|
5065
5073
|
var GENE_PIN_DROP_PX = 18;
|
|
5074
|
+
var GENE_STACK = 2;
|
|
5066
5075
|
var GLYPH_ROOM_PX = 60;
|
|
5067
5076
|
var MAX_GLYPH_LABEL_ROWS = 8;
|
|
5068
5077
|
var TOPMOST_BASELINE = LABEL_PX + LABEL_PAD;
|
|
@@ -5151,7 +5160,8 @@ function layoutLabels(m) {
|
|
|
5151
5160
|
item: pin,
|
|
5152
5161
|
x,
|
|
5153
5162
|
y: y + m.contigThickness + GENE_PIN_DROP_PX,
|
|
5154
|
-
text: pin.covered < 0.98 ? `${pin.gene.name} \u2026` : pin.gene.name
|
|
5163
|
+
text: pin.covered < 0.98 ? `${pin.gene.name} \u2026` : pin.gene.name,
|
|
5164
|
+
stack: GENE_STACK
|
|
5155
5165
|
};
|
|
5156
5166
|
}),
|
|
5157
5167
|
frame,
|
|
@@ -5200,6 +5210,86 @@ function layoutLabels(m) {
|
|
|
5200
5210
|
};
|
|
5201
5211
|
}
|
|
5202
5212
|
|
|
5213
|
+
// src/genes/genePins.ts
|
|
5214
|
+
function contig(name) {
|
|
5215
|
+
return name.split("#").at(-1);
|
|
5216
|
+
}
|
|
5217
|
+
function genePins(graph, genes, positions) {
|
|
5218
|
+
const byContig = /* @__PURE__ */ new Map();
|
|
5219
|
+
const contigOf = /* @__PURE__ */ new Map();
|
|
5220
|
+
for (const node of graph.nodes) {
|
|
5221
|
+
if (isBackbone(node) && positions[node.id]?.length) {
|
|
5222
|
+
const { refName } = node.stable;
|
|
5223
|
+
const name = contigOf.get(refName) ?? contigOf.set(refName, contig(refName)).get(refName);
|
|
5224
|
+
const entry = byContig.get(name) ?? byContig.set(name, { nodes: [], reach: 0 }).get(name);
|
|
5225
|
+
entry.nodes.push(node);
|
|
5226
|
+
entry.reach = Math.max(entry.reach, node.length);
|
|
5227
|
+
}
|
|
5228
|
+
}
|
|
5229
|
+
for (const { nodes } of byContig.values()) {
|
|
5230
|
+
nodes.sort((a, b) => a.stable.start - b.stable.start);
|
|
5231
|
+
}
|
|
5232
|
+
const pins = [];
|
|
5233
|
+
for (const gene of genes) {
|
|
5234
|
+
const backbone = byContig.get(contig(gene.refName));
|
|
5235
|
+
if (!backbone) {
|
|
5236
|
+
continue;
|
|
5237
|
+
}
|
|
5238
|
+
const parts = [];
|
|
5239
|
+
let at;
|
|
5240
|
+
let atDistance = Infinity;
|
|
5241
|
+
let covered = 0;
|
|
5242
|
+
const mid = (gene.start + gene.end) / 2;
|
|
5243
|
+
const { nodes, reach } = backbone;
|
|
5244
|
+
for (let i = firstNodeAtOrAfter(nodes, gene.start - reach); i < nodes.length && nodes[i].stable.start < gene.end; i++) {
|
|
5245
|
+
const node = nodes[i];
|
|
5246
|
+
const nodeStart = node.stable.start;
|
|
5247
|
+
const nodeEnd = nodeStart + node.length;
|
|
5248
|
+
if (nodeEnd <= gene.start) {
|
|
5249
|
+
continue;
|
|
5250
|
+
}
|
|
5251
|
+
const line = positions[node.id];
|
|
5252
|
+
covered += Math.min(nodeEnd, gene.end) - Math.max(nodeStart, gene.start);
|
|
5253
|
+
for (const exon of gene.exons) {
|
|
5254
|
+
const a = Math.max(exon.start, nodeStart);
|
|
5255
|
+
const b = Math.min(exon.end, nodeEnd);
|
|
5256
|
+
if (b <= a) {
|
|
5257
|
+
continue;
|
|
5258
|
+
}
|
|
5259
|
+
const stretch = polylineSlice(
|
|
5260
|
+
line,
|
|
5261
|
+
(a - nodeStart) / node.length,
|
|
5262
|
+
(b - nodeStart) / node.length
|
|
5263
|
+
);
|
|
5264
|
+
if (stretch.length === 1) {
|
|
5265
|
+
stretch.push({ ...stretch[0] });
|
|
5266
|
+
}
|
|
5267
|
+
parts.push(svgPath(stretch));
|
|
5268
|
+
}
|
|
5269
|
+
const pinBp = Math.min(Math.max(mid, nodeStart), nodeEnd);
|
|
5270
|
+
const distance = Math.abs(pinBp - mid);
|
|
5271
|
+
if (distance < atDistance) {
|
|
5272
|
+
atDistance = distance;
|
|
5273
|
+
const [p] = polylineSlice(
|
|
5274
|
+
line,
|
|
5275
|
+
(pinBp - nodeStart) / node.length,
|
|
5276
|
+
(pinBp - nodeStart) / node.length
|
|
5277
|
+
);
|
|
5278
|
+
at = p;
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
5281
|
+
if (at) {
|
|
5282
|
+
pins.push({
|
|
5283
|
+
gene,
|
|
5284
|
+
exons: parts.join(""),
|
|
5285
|
+
at,
|
|
5286
|
+
covered: covered / (gene.end - gene.start)
|
|
5287
|
+
});
|
|
5288
|
+
}
|
|
5289
|
+
}
|
|
5290
|
+
return pins;
|
|
5291
|
+
}
|
|
5292
|
+
|
|
5203
5293
|
// src/gbzWindow.ts
|
|
5204
5294
|
var NoReferenceSampleError = class extends Error {
|
|
5205
5295
|
constructor(anchor, referenceSamples) {
|
|
@@ -5372,6 +5462,7 @@ export {
|
|
|
5372
5462
|
fitTransform,
|
|
5373
5463
|
forceLayout,
|
|
5374
5464
|
formatBp2 as formatBp,
|
|
5465
|
+
genePins,
|
|
5375
5466
|
getDpr,
|
|
5376
5467
|
haplotypeWanted,
|
|
5377
5468
|
layoutExtent,
|
package/dist/types/index.d.ts
CHANGED
|
@@ -39,6 +39,8 @@ export { ROW_HEIGHT_PX } from './layout/rowSpacing.js';
|
|
|
39
39
|
export { HALO_FACTOR, LEGEND_INSET_PX, layoutLabels } from './labelLayout.js';
|
|
40
40
|
export type { BubbleGlyph, LabelLayout, LabelLayoutSource } from './labelLayout.js';
|
|
41
41
|
export { formatBp } from './graphLabels.js';
|
|
42
|
+
export { genePins } from './genes/genePins.js';
|
|
43
|
+
export type { GeneModel, GenePin } from './genes/genePins.js';
|
|
42
44
|
export { LABEL_CHAR_PX, LABEL_PAD, LABEL_PX } from './overlayLabels.js';
|
|
43
45
|
export type { Graph, GraphEdge, GraphNode, LayoutResult, NodeSegment, } from './types.js';
|
|
44
46
|
export { cutWindowGFA, haplotypeWanted, referencePathQuery, referenceSamplesOf, resolveReferenceSample, } from './gbzWindow.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/bandage-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
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": {
|