@jbrowse/bandage-core 8.2.0 → 9.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.
Files changed (61) hide show
  1. package/dist/bubbles/bubbleHalos.js +9 -5
  2. package/dist/bubbles/bubbleLine.js +3 -1
  3. package/dist/bubbles/bubblesFromGraph.js +8 -4
  4. package/dist/bubbles/classifyBubble.js +2 -2
  5. package/dist/bubbles/superbubbles.js +21 -0
  6. package/dist/chunks/{chunk-ISEI2FH3.js → chunk-2AWUWGAD.js} +10 -4
  7. package/dist/chunks/{chunk-GQ2AOHU4.js → chunk-2ZT7ZF7A.js} +13 -31
  8. package/dist/chunks/{chunk-DE4UFDUZ.js → chunk-3TGUKQWQ.js} +4 -4
  9. package/dist/chunks/{chunk-KCRL5JB2.js → chunk-75HR3756.js} +55 -17
  10. package/dist/chunks/{chunk-DRA7733Q.js → chunk-BPRXQ2SS.js} +8 -3
  11. package/dist/chunks/{chunk-TEDQJPMI.js → chunk-CWFNEKST.js} +22 -7
  12. package/dist/chunks/chunk-FUVI4WQP.js +273 -0
  13. package/dist/chunks/{chunk-MFKORG3F.js → chunk-FX4RDMDN.js} +5 -1
  14. package/dist/chunks/{chunk-4S47XRYA.js → chunk-GOZYKNQ2.js} +16 -11
  15. package/dist/chunks/chunk-INJ2UVOT.js +370 -0
  16. package/dist/chunks/{chunk-TL4B342F.js → chunk-MXDQGA7A.js} +1 -1
  17. package/dist/chunks/{chunk-SKKYLBRA.js → chunk-RRZMMYBG.js} +1 -1
  18. package/dist/chunks/{chunk-3FXPFVKJ.js → chunk-UID3QBWH.js} +1 -1
  19. package/dist/chunks/{chunk-2WNBVB55.js → chunk-WBCOREDZ.js} +121 -74
  20. package/dist/chunks/{chunk-OWFPAIJI.js → chunk-WEDZ76AK.js} +1 -1
  21. package/dist/chunks/{chunk-CF62U3QS.js → chunk-WNUZP3WQ.js} +2 -2
  22. package/dist/chunks/{chunk-WOO7QYKB.js → chunk-XKWD2RY3.js} +8 -2
  23. package/dist/chunks/{chunk-6VBDMZBZ.js → chunk-XLCTQHBE.js} +1 -1
  24. package/dist/chunks/{chunk-733L2TS6.js → chunk-XXT2JCAC.js} +10 -7
  25. package/dist/cli/figure.js +9 -9
  26. package/dist/figure.js +6 -6
  27. package/dist/figureSettings.js +3 -3
  28. package/dist/index.js +45 -33
  29. package/dist/layout/forceCache.js +3 -3
  30. package/dist/layout/tubeMapLayout.js +12 -6
  31. package/dist/layoutModes.js +3 -3
  32. package/dist/pipeline.js +2 -2
  33. package/dist/renderer/Canvas2DRenderer.js +1 -1
  34. package/dist/renderer/recordingCanvas.js +12 -1
  35. package/dist/tubeMap/axis.js +1 -1
  36. package/dist/tubeMap/coarsen.js +11 -23
  37. package/dist/tubeMap/connectors.js +3 -4
  38. package/dist/tubeMap/deviations.js +15 -19
  39. package/dist/tubeMap/draw.js +11 -5
  40. package/dist/tubeMap/genes.js +2 -2
  41. package/dist/tubeMap/mismatches.js +1 -1
  42. package/dist/tubeMap/reads.js +1 -1
  43. package/dist/types/bubbles/bubbleHalos.d.ts +2 -0
  44. package/dist/types/bubbles/bubbleLine.d.ts +3 -0
  45. package/dist/types/bubbles/bubblesFromGraph.d.ts +12 -2
  46. package/dist/types/bubbles/superbubbles.d.ts +5 -0
  47. package/dist/types/index.d.ts +5 -4
  48. package/dist/types/layout/tubeMapLayout.d.ts +15 -2
  49. package/dist/types/layoutModes.d.ts +5 -5
  50. package/dist/types/renderer/Canvas2DRenderer.d.ts +6 -3
  51. package/dist/types/tubeMap/axis.d.ts +6 -3
  52. package/dist/types/tubeMap/connectors.d.ts +3 -11
  53. package/dist/types/tubeMap/deviations.d.ts +2 -3
  54. package/dist/types/tubeMap/draw.d.ts +5 -1
  55. package/dist/types/tubeMap/mismatches.d.ts +1 -1
  56. package/dist/types/version.d.ts +1 -1
  57. package/dist/version.js +1 -1
  58. package/dist/viewport.js +3 -3
  59. package/package.json +1 -1
  60. package/dist/chunks/chunk-W2I4DOL4.js +0 -230
  61. package/dist/chunks/{chunk-5OIVTEF7.js → chunk-OOXIMURX.js} +3 -3
@@ -1,7 +1,7 @@
1
1
  import { anchoredLayout } from './layout/anchoredLayout.js';
2
2
  import { orderedLayout } from './layout/orderedLayout.js';
3
3
  import { sampleRowLayout } from './layout/sampleRowLayout.js';
4
- import { hasTubeMapPaths, tubeMapLayout, tubeMapReferenceLayout } from './layout/tubeMapLayout.js';
4
+ import { hasTubeMapBackbone, hasTubeMapPaths, tubeMapLayout, tubeMapReferenceLayout } from './layout/tubeMapLayout.js';
5
5
  import { walkRowLayout } from './layout/walkRowLayout.js';
6
6
  import type { Graph, LayoutResult } from './types.js';
7
7
  export declare const FORCE_LAYOUT_LABEL = "Force-directed layout";
@@ -76,8 +76,8 @@ export declare const LAYOUT_MODES: readonly [{
76
76
  readonly run: typeof tubeMapReferenceLayout;
77
77
  readonly cutMargins: true;
78
78
  readonly wholeWalks: false;
79
- readonly available: (graph: Graph) => boolean;
80
- readonly drawsLocally: (graph: Graph) => boolean;
79
+ readonly available: typeof hasTubeMapBackbone;
80
+ readonly drawsLocally: typeof hasTubeMapBackbone;
81
81
  readonly drawsNodes: false;
82
82
  }, {
83
83
  readonly value: "force";
@@ -150,8 +150,8 @@ export declare function layoutModeByValue(value: string): {
150
150
  readonly run: typeof tubeMapReferenceLayout;
151
151
  readonly cutMargins: true;
152
152
  readonly wholeWalks: false;
153
- readonly available: (graph: Graph) => boolean;
154
- readonly drawsLocally: (graph: Graph) => boolean;
153
+ readonly available: typeof hasTubeMapBackbone;
154
+ readonly drawsLocally: typeof hasTubeMapBackbone;
155
155
  readonly drawsNodes: false;
156
156
  } | {
157
157
  readonly value: "force";
@@ -16,9 +16,12 @@ export declare class Canvas2DRenderer implements Renderer {
16
16
  setEdgeHighlight(edgeIndex: number | null, factor: number): void;
17
17
  updateTransform(transform: TransformUniform): void;
18
18
  render(clearColor: [number, number, number, number]): void;
19
- private renderEdges;
20
- private renderNodes;
21
- private renderArrows;
19
+ renderHighlights(): void;
20
+ private edgeRun;
21
+ private liftedStrokes;
22
+ private strokeCurves;
23
+ private strokeNodes;
24
+ private fillArrows;
22
25
  dispose(): void;
23
26
  }
24
27
  export declare function arrowheadOutline(a: Arrowhead, t: TransformUniform): readonly [{
@@ -1,13 +1,16 @@
1
1
  import type { TubeMapFrame } from './draw.js';
2
- import type { Graph } from '../types.js';
3
- import type { TubeMapLayout } from '@jbrowse/tubemap-core';
2
+ import type { TubeMapDrawing } from '../layout/tubeMapLayout.js';
4
3
  export interface Box {
5
4
  bp0: number;
6
5
  bp1: number;
7
6
  x0: number;
8
7
  x1: number;
9
8
  }
10
- export declare function referenceBoxes(graph: Graph, layout: TubeMapLayout): Map<string, Box[]>;
9
+ export interface ReferenceBox extends Box {
10
+ name: string;
11
+ index: number;
12
+ }
13
+ export declare function referenceBoxes({ graph, layout, }: Pick<TubeMapDrawing, 'graph' | 'layout'>): Map<string, ReferenceBox[]>;
11
14
  export type ReferenceBoxes = ReturnType<typeof referenceBoxes>;
12
15
  export declare function tubeX(boxes: readonly Box[], bp: number, isEnd?: boolean): number;
13
16
  export declare function tubeSpan(boxes: readonly Box[], start: number, end: number): {
@@ -1,12 +1,4 @@
1
- import type { Graph } from '../types.js';
2
- import type { TubeMapLayout } from '@jbrowse/tubemap-core';
3
- export interface ReferenceNode {
4
- node: string;
5
- bp0: number;
6
- bp1: number;
7
- x0: number;
8
- x1: number;
9
- }
1
+ import type { ReferenceBox } from './axis.js';
10
2
  export interface Connector {
11
3
  node: string;
12
4
  top0: number;
@@ -14,10 +6,10 @@ export interface Connector {
14
6
  bottom0: number;
15
7
  bottom1: number;
16
8
  }
17
- export declare function referenceNodes(graph: Graph, layout: TubeMapLayout): ReferenceNode[];
18
- export declare function tubeMapConnectors(nodes: readonly ReferenceNode[], bpToScreen: (bp: number) => number, tubeToScreen: (tx: number) => number, width: number): Connector[];
9
+ export declare function tubeMapConnectors(boxes: readonly ReferenceBox[], bpToScreen: (bp: number) => number, tubeToScreen: (tx: number) => number, width: number): Connector[];
19
10
  export declare function connectorAt(connectors: readonly Connector[], zoneBottom: number, sx: number, sy: number): string | undefined;
20
11
  export declare function drawTubeMapConnectors(ctx: CanvasRenderingContext2D, connectors: readonly Connector[], bottom: number, { highlightNode, darkMode, }: {
21
12
  highlightNode?: string | null;
22
13
  darkMode?: boolean;
23
14
  }): void;
15
+ export declare function drawLitConnector(ctx: CanvasRenderingContext2D, connectors: readonly Connector[], bottom: number, node: string | null | undefined): void;
@@ -1,13 +1,12 @@
1
1
  import type { Deviation } from './coarsen.js';
2
2
  import type { TubeMapFrame } from './draw.js';
3
- import type { Graph } from '../types.js';
4
- import type { TubeMapLayout } from '@jbrowse/tubemap-core';
3
+ import type { TubeMapDrawing } from '../layout/tubeMapLayout.js';
5
4
  export interface DeviationMark {
6
5
  x0: number;
7
6
  x1: number;
8
7
  y: number;
9
8
  height: number;
10
9
  }
11
- export declare function deviationMarks(graph: Graph, layout: TubeMapLayout, deviations: Map<string, Deviation[]>): DeviationMark[];
10
+ export declare function deviationMarks(drawing: Pick<TubeMapDrawing, 'graph' | 'layout'>, deviations: Map<string, Deviation[]>): DeviationMark[];
12
11
  export declare function deviationInk(darkMode?: boolean): "rgba(255,255,255,0.9)" | "rgba(0,0,0,0.8)";
13
12
  export declare function drawDeviationMarks(ctx: CanvasRenderingContext2D, marks: readonly DeviationMark[], { x, y, width, darkMode }: TubeMapFrame): void;
@@ -32,7 +32,8 @@ type Command = {
32
32
  export declare function parsePath(d: string): Command[];
33
33
  interface Filled {
34
34
  color: string;
35
- track?: number;
35
+ id: number;
36
+ haplotype: boolean;
36
37
  x0: number;
37
38
  x1: number;
38
39
  }
@@ -68,6 +69,9 @@ export interface TubeMapFrame extends TubeMapTransform {
68
69
  nodeColors?: ReadonlyMap<string, string>;
69
70
  }
70
71
  export declare function drawTubeMap(ctx: CanvasRenderingContext2D, picture: TubeMapPicture, frame: TubeMapFrame): void;
72
+ export declare function drawTubeMapHighlight(ctx: CanvasRenderingContext2D, picture: TubeMapPicture, frame: TubeMapFrame): void;
71
73
  export declare function mismatchesLegible(yScale: number): boolean;
72
74
  export declare function mismatchOnScreen(m: TubeMapMismatch, { x, width }: Pick<TubeMapFrame, 'x' | 'width'>): boolean;
75
+ export declare function tubeMapTrackAt(picture: TubeMapPicture, { x, y }: TubeMapTransform, sx: number, sy: number): number | undefined;
76
+ export declare function tubeMapMismatchAt(picture: TubeMapPicture, frame: TubeMapTransform, sx: number, sy: number): TubeMapMismatch | undefined;
73
77
  export {};
@@ -3,7 +3,6 @@ interface MarkBase {
3
3
  readId: number;
4
4
  y: number;
5
5
  height: number;
6
- nodeY: number;
7
6
  }
8
7
  export type TubeMapMismatch = (MarkBase & {
9
8
  kind: 'insertion';
@@ -14,6 +13,7 @@ export type TubeMapMismatch = (MarkBase & {
14
13
  kind: 'deletion';
15
14
  x0: number;
16
15
  x1: number;
16
+ length: number;
17
17
  }) | (MarkBase & {
18
18
  kind: 'substitution';
19
19
  x0: number;
@@ -1 +1 @@
1
- export declare const version = "8.2.0";
1
+ export declare const version = "9.1.0";
package/dist/version.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  version
3
- } from "./chunks/chunk-3FXPFVKJ.js";
3
+ } from "./chunks/chunk-UID3QBWH.js";
4
4
  export {
5
5
  version
6
6
  };
package/dist/viewport.js CHANGED
@@ -5,14 +5,14 @@ import {
5
5
  screenToLayout,
6
6
  viewportOf,
7
7
  zoomAbout
8
- } from "./chunks/chunk-TL4B342F.js";
9
- import "./chunks/chunk-5OIVTEF7.js";
8
+ } from "./chunks/chunk-MXDQGA7A.js";
9
+ import "./chunks/chunk-OOXIMURX.js";
10
10
  import "./chunks/chunk-PUG7LXDF.js";
11
11
  import "./chunks/chunk-IGVV37VI.js";
12
+ import "./chunks/chunk-OA7RIMZ2.js";
12
13
  import "./chunks/chunk-OCMBULGN.js";
13
14
  import "./chunks/chunk-QYBZZI5H.js";
14
15
  import "./chunks/chunk-CDLPYR5O.js";
15
- import "./chunks/chunk-OA7RIMZ2.js";
16
16
  import "./chunks/chunk-ES2N6V56.js";
17
17
  import "./chunks/chunk-ST2IBUAN.js";
18
18
  import "./chunks/chunk-BPLIXMH7.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/bandage-core",
3
- "version": "8.2.0",
3
+ "version": "9.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": {
@@ -1,230 +0,0 @@
1
- import {
2
- canonicalStrand,
3
- stepName,
4
- tubeMapReads
5
- } from "./chunk-TEDQJPMI.js";
6
- import {
7
- pathCssColor,
8
- pathGreyCssColor
9
- } from "./chunk-7GBL7SJY.js";
10
- import {
11
- pathOrigin
12
- } from "./chunk-ST2IBUAN.js";
13
- import {
14
- isBackbone
15
- } from "./chunk-FYQWPEEY.js";
16
-
17
- // src/layout/tubeMapLayout.ts
18
- import { layoutTubeMap } from "@jbrowse/tubemap-core";
19
- function visitStrands(graph) {
20
- const strands = /* @__PURE__ */ new Map();
21
- for (const [segment, visits] of graph.pathVisits ?? []) {
22
- for (const visit of visits) {
23
- const key = `${visit.path} ${segment}`;
24
- const list = strands.get(key);
25
- if (list) {
26
- list.push(visit.strand);
27
- } else {
28
- strands.set(key, [visit.strand]);
29
- }
30
- }
31
- }
32
- return strands;
33
- }
34
- function tubeMapTracks(graph) {
35
- const nodeById = new Map(graph.nodes.map((n) => [n.id, n]));
36
- const strands = visitStrands(graph);
37
- const paths = (graph.paths ?? []).map((path, index) => ({ path, index }));
38
- const reference = paths.findIndex(
39
- (p) => pathOrigin(p.path.name).name === graph.referencePath
40
- );
41
- if (reference > 0) {
42
- paths.unshift(...paths.splice(reference, 1));
43
- }
44
- return paths.flatMap(({ path, index }) => {
45
- const visitName = pathOrigin(path.name).name;
46
- const seen = /* @__PURE__ */ new Map();
47
- const sequence = path.nodeIds.flatMap((id) => {
48
- const node = nodeById.get(id);
49
- if (!node) {
50
- return [];
51
- }
52
- const k = seen.get(node.name) ?? 0;
53
- seen.set(node.name, k + 1);
54
- const strand = strands.get(`${visitName} ${node.name}`)?.[k] ?? canonicalStrand(node);
55
- return [stepName(node, strand)];
56
- });
57
- return sequence.length > 0 ? [
58
- {
59
- id: index,
60
- name: path.name,
61
- sequence,
62
- sourceTrackID: 0,
63
- type: "haplotype"
64
- }
65
- ] : [];
66
- });
67
- }
68
- function tubeMapNodes(graph) {
69
- return graph.nodes.map((n) => ({
70
- name: n.id,
71
- seq: "",
72
- sequenceLength: Math.max(1, n.length)
73
- }));
74
- }
75
- function hasTubeMapPaths(graph) {
76
- return (graph.paths?.length ?? 0) > 0;
77
- }
78
- var STACK_PX = 600;
79
- var MIN_TUBE_PX = 3;
80
- var MAX_TUBE_PX = 15;
81
- function tubeWidth(trackCount) {
82
- return Math.max(
83
- MIN_TUBE_PX,
84
- Math.min(MAX_TUBE_PX, Math.floor(STACK_PX / Math.max(1, trackCount)))
85
- );
86
- }
87
- function runTubeMap(graph) {
88
- const paths = graph.paths ?? [];
89
- const tracks = tubeMapTracks(graph);
90
- const reads = graph.reads ? tubeMapReads(graph, graph.reads, paths.length) : [];
91
- const tubeColor = reads.length > 0 ? pathGreyCssColor : pathCssColor;
92
- const pathColors = paths.map((_, i) => tubeColor(i, paths.length));
93
- const layout = layoutTubeMap(tubeMapNodes(graph), tracks, reads, {
94
- nodeWidthOption: "compressed",
95
- trackWidth: tubeWidth(tracks.length)
96
- });
97
- return layout ? { layout, pathColors } : void 0;
98
- }
99
- function drawnNodes(layout) {
100
- const nodes = [];
101
- layout.nodes.forEach((node) => {
102
- if (node.order >= 0) {
103
- nodes.push(node);
104
- }
105
- });
106
- return nodes;
107
- }
108
- function centreline(node, yOffset, x0, x1) {
109
- const y = node.y + node.contentHeight / 2 - yOffset;
110
- return [
111
- { x: x0, y },
112
- { x: x1, y }
113
- ];
114
- }
115
- function extentOf(layout, yOffset) {
116
- return {
117
- minY: layout.bounds.minY - yOffset,
118
- maxY: layout.bounds.maxY - yOffset
119
- };
120
- }
121
- function tubeMapLayout(graph) {
122
- const run = hasTubeMapPaths(graph) ? runTubeMap(graph) : void 0;
123
- if (!run) {
124
- return void 0;
125
- }
126
- const { layout, pathColors } = run;
127
- const yOffset = layout.bounds.minY;
128
- const nodePositions = {};
129
- for (const node of drawnNodes(layout)) {
130
- nodePositions[node.name] = centreline(
131
- node,
132
- yOffset,
133
- node.x,
134
- node.x + node.pixelWidth
135
- );
136
- }
137
- const { minY, maxY } = extentOf(layout, yOffset);
138
- return {
139
- nodePositions,
140
- tubeMap: { layout, yOffset, pathColors },
141
- extent: {
142
- minX: layout.bounds.minX,
143
- maxX: layout.bounds.maxX,
144
- minY,
145
- maxY
146
- }
147
- };
148
- }
149
- function tubeMapColumns(graph, layout) {
150
- const nodeById = new Map(graph.nodes.map((n) => [n.id, n]));
151
- const byOrder = /* @__PURE__ */ new Map();
152
- for (const node of drawnNodes(layout)) {
153
- const list = byOrder.get(node.order);
154
- if (list) {
155
- list.push(node);
156
- } else {
157
- byOrder.set(node.order, [node]);
158
- }
159
- }
160
- const columns = [];
161
- let end = -Infinity;
162
- for (const order of [...byOrder.keys()].sort((a, b) => a - b)) {
163
- const nodes = byOrder.get(order);
164
- let bp0 = Infinity;
165
- let bp1 = -Infinity;
166
- for (const node of nodes) {
167
- const graphNode = nodeById.get(node.name);
168
- if (graphNode && isBackbone(graphNode)) {
169
- bp0 = Math.min(bp0, graphNode.stable.start);
170
- bp1 = Math.max(bp1, graphNode.stable.start + node.sequenceLength);
171
- }
172
- }
173
- if (bp0 === Infinity) {
174
- bp0 = bp1 = end;
175
- }
176
- if (bp0 < end) {
177
- bp0 = end;
178
- bp1 = Math.max(end, bp1);
179
- }
180
- end = Math.max(end, bp1);
181
- columns.push({
182
- order,
183
- x0: Math.min(...nodes.map((n) => n.x)),
184
- x1: Math.max(...nodes.map((n) => n.x + n.pixelWidth)),
185
- bp0,
186
- bp1
187
- });
188
- }
189
- const first = columns.find((c) => c.bp0 !== -Infinity);
190
- for (const column of columns) {
191
- if (column.bp0 === -Infinity) {
192
- column.bp0 = column.bp1 = first?.bp0 ?? 0;
193
- }
194
- }
195
- return columns;
196
- }
197
- function pathsReachBackbone(graph) {
198
- return graph.nodes.some(isBackbone) && hasTubeMapPaths(graph);
199
- }
200
- function tubeMapReferenceLayout(graph) {
201
- const run = pathsReachBackbone(graph) ? runTubeMap(graph) : void 0;
202
- if (!run) {
203
- return void 0;
204
- }
205
- const { layout, pathColors } = run;
206
- const columns = tubeMapColumns(graph, layout);
207
- const byOrder = new Map(columns.map((c) => [c.order, c]));
208
- const yOffset = layout.bounds.minY;
209
- const nodePositions = {};
210
- for (const node of drawnNodes(layout)) {
211
- const column = byOrder.get(node.order);
212
- nodePositions[node.name] = centreline(node, yOffset, column.bp0, column.bp1);
213
- }
214
- return {
215
- nodePositions,
216
- tubeMap: { layout, yOffset, columns, pathColors },
217
- referenceAxis: true,
218
- pixelRows: true,
219
- extent: extentOf(layout, yOffset)
220
- };
221
- }
222
-
223
- export {
224
- visitStrands,
225
- tubeMapTracks,
226
- hasTubeMapPaths,
227
- tubeWidth,
228
- tubeMapLayout,
229
- tubeMapReferenceLayout
230
- };
@@ -4,15 +4,15 @@ import {
4
4
  import {
5
5
  seededNodes
6
6
  } from "./chunk-IGVV37VI.js";
7
+ import {
8
+ graphFromTables
9
+ } from "./chunk-OA7RIMZ2.js";
7
10
  import {
8
11
  convertGFAToGraph
9
12
  } from "./chunk-OCMBULGN.js";
10
13
  import {
11
14
  parseGFA
12
15
  } from "./chunk-CDLPYR5O.js";
13
- import {
14
- graphFromTables
15
- } from "./chunk-OA7RIMZ2.js";
16
16
  import {
17
17
  anchorGraph
18
18
  } from "./chunk-ST2IBUAN.js";