@jbrowse/bandage-core 0.1.4 → 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 CHANGED
@@ -269,12 +269,12 @@ function parseGFA(file) {
269
269
  });
270
270
  }
271
271
  } else if (line.startsWith("W")) {
272
- const [, sample, hap, contig, start, end, body, ...rest] = line.split(" ");
273
- if (sample && hap && contig && start && end && body) {
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);
@@ -5202,6 +5210,86 @@ function layoutLabels(m) {
5202
5210
  };
5203
5211
  }
5204
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
+
5205
5293
  // src/gbzWindow.ts
5206
5294
  var NoReferenceSampleError = class extends Error {
5207
5295
  constructor(anchor, referenceSamples) {
@@ -5374,6 +5462,7 @@ export {
5374
5462
  fitTransform,
5375
5463
  forceLayout,
5376
5464
  formatBp2 as formatBp,
5465
+ genePins,
5377
5466
  getDpr,
5378
5467
  haplotypeWanted,
5379
5468
  layoutExtent,
@@ -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.4",
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": {