@jbrowse/bandage-core 6.0.1 → 6.0.3

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 (162) hide show
  1. package/README.md +23 -7
  2. package/dist/alleleProjection/projectAlleles.js +10 -0
  3. package/dist/anchoredNodes.js +24 -0
  4. package/dist/bubbleSpreads.js +11 -0
  5. package/dist/bubbles/bubbleHalos.js +11 -0
  6. package/dist/bubbles/bubbleLine.js +14 -0
  7. package/dist/bubbles/bubblesFromGraph.js +10 -0
  8. package/dist/bubbles/classifyBubble.js +15 -0
  9. package/dist/bubbles/popBubble.js +9 -0
  10. package/dist/chunks/chunk-2CVHXFK7.js +530 -0
  11. package/dist/chunks/chunk-3S3YVOJ7.js +69 -0
  12. package/dist/chunks/chunk-47DYCZOK.js +115 -0
  13. package/dist/chunks/chunk-4EMPBO7S.js +117 -0
  14. package/dist/chunks/chunk-4S47XRYA.js +149 -0
  15. package/dist/chunks/chunk-5XQDMQXU.js +431 -0
  16. package/dist/chunks/chunk-6JEWNXCQ.js +90 -0
  17. package/dist/chunks/chunk-6SBUFFTB.js +97 -0
  18. package/dist/chunks/chunk-6SXMCK6I.js +476 -0
  19. package/dist/chunks/chunk-72N5DJHZ.js +155 -0
  20. package/dist/chunks/chunk-73RSLGZT.js +73 -0
  21. package/dist/chunks/chunk-7XHHVYG7.js +13 -0
  22. package/dist/chunks/chunk-AB35TJST.js +67 -0
  23. package/dist/chunks/chunk-BPLIXMH7.js +52 -0
  24. package/dist/chunks/chunk-BUBZ32IC.js +101 -0
  25. package/dist/chunks/chunk-BXEPA4KS.js +179 -0
  26. package/dist/chunks/chunk-C44YRP5F.js +85 -0
  27. package/dist/chunks/chunk-CDLPYR5O.js +135 -0
  28. package/dist/chunks/chunk-CJ2EE4AF.js +40 -0
  29. package/dist/chunks/chunk-CPMHA4W5.js +6 -0
  30. package/dist/chunks/chunk-CR7EGAFE.js +241 -0
  31. package/dist/chunks/chunk-CS3E4ETM.js +202 -0
  32. package/dist/chunks/chunk-CTSBC2O6.js +90 -0
  33. package/dist/chunks/chunk-D3M7SBKL.js +210 -0
  34. package/dist/chunks/chunk-DKOB2OPC.js +177 -0
  35. package/dist/chunks/chunk-EJ5OZTCK.js +52 -0
  36. package/dist/chunks/chunk-EK4HGYO7.js +174 -0
  37. package/dist/chunks/chunk-EPZORFTI.js +23 -0
  38. package/dist/chunks/chunk-ES2N6V56.js +83 -0
  39. package/dist/chunks/chunk-EZPBJPK6.js +54 -0
  40. package/dist/chunks/chunk-FYQWPEEY.js +65 -0
  41. package/dist/chunks/chunk-GGQRADFS.js +170 -0
  42. package/dist/chunks/chunk-GOY6REMT.js +43 -0
  43. package/dist/chunks/chunk-GQ2AOHU4.js +112 -0
  44. package/dist/chunks/chunk-HNQPEMYE.js +297 -0
  45. package/dist/chunks/chunk-IGVV37VI.js +60 -0
  46. package/dist/chunks/chunk-IO2PCPZI.js +218 -0
  47. package/dist/chunks/chunk-ISEI2FH3.js +108 -0
  48. package/dist/chunks/chunk-JKJWSY4V.js +32 -0
  49. package/dist/chunks/chunk-KQFOCDFY.js +73 -0
  50. package/dist/chunks/chunk-L3O7AWLI.js +52 -0
  51. package/dist/chunks/chunk-LLJUG2H7.js +6 -0
  52. package/dist/chunks/chunk-LOEA5IHZ.js +71 -0
  53. package/dist/chunks/chunk-LTUWJKHD.js +112 -0
  54. package/dist/chunks/chunk-MFKORG3F.js +44 -0
  55. package/dist/chunks/chunk-MI35EUIE.js +76 -0
  56. package/dist/chunks/chunk-MNUSQCLG.js +29 -0
  57. package/dist/chunks/chunk-MQJUG2D2.js +53 -0
  58. package/dist/chunks/chunk-MREQ7GIA.js +181 -0
  59. package/dist/chunks/chunk-N62KBLFC.js +326 -0
  60. package/dist/chunks/chunk-NNODIW4U.js +26 -0
  61. package/dist/chunks/chunk-PBENCR5L.js +60 -0
  62. package/dist/chunks/chunk-PCZ4PTYC.js +726 -0
  63. package/dist/chunks/chunk-PUG7LXDF.js +70 -0
  64. package/dist/chunks/chunk-QYBZZI5H.js +0 -0
  65. package/dist/chunks/chunk-R6ZUK4Y3.js +232 -0
  66. package/dist/chunks/chunk-RAKOB6IV.js +169 -0
  67. package/dist/chunks/chunk-ROF2R3RF.js +205 -0
  68. package/dist/chunks/chunk-RVS2QCOX.js +135 -0
  69. package/dist/chunks/chunk-ST2IBUAN.js +119 -0
  70. package/dist/chunks/chunk-SZNZ2T6D.js +198 -0
  71. package/dist/chunks/chunk-T43W7NKK.js +122 -0
  72. package/dist/chunks/chunk-TAMCZHLW.js +190 -0
  73. package/dist/chunks/chunk-TDQLINVI.js +16 -0
  74. package/dist/chunks/chunk-TEDQJPMI.js +131 -0
  75. package/dist/chunks/chunk-TZFWUT2C.js +66 -0
  76. package/dist/chunks/chunk-UVBGRJQX.js +50 -0
  77. package/dist/chunks/chunk-VHW7FDHU.js +42 -0
  78. package/dist/chunks/chunk-VZQ4FKLR.js +38 -0
  79. package/dist/chunks/chunk-WFX3MAKA.js +102 -0
  80. package/dist/chunks/chunk-WOO7QYKB.js +121 -0
  81. package/dist/chunks/chunk-WSIFAZU7.js +132 -0
  82. package/dist/chunks/chunk-X5L37W4J.js +82 -0
  83. package/dist/chunks/chunk-Y3IOTZJA.js +61 -0
  84. package/dist/chunks/chunk-YMSSF2RK.js +257 -0
  85. package/dist/cli/figure.js +84 -17
  86. package/dist/colorSchemes.js +10 -0
  87. package/dist/deletionEdges.js +13 -0
  88. package/dist/el.js +8 -0
  89. package/dist/facetGrid.js +16 -0
  90. package/dist/figure.js +51 -0
  91. package/dist/gaf/parseGaf.js +12 -0
  92. package/dist/gbzCut.js +19 -0
  93. package/dist/gbzJoin.js +6 -0
  94. package/dist/gbzWindow.js +28 -0
  95. package/dist/genes/exonOutline.js +11 -0
  96. package/dist/genes/geneFiles.js +14 -0
  97. package/dist/genes/genePins.js +10 -0
  98. package/dist/gfa/gfaConverter.js +11 -0
  99. package/dist/gfa-core/gfaParser.js +8 -0
  100. package/dist/gfa-core/index.js +9 -0
  101. package/dist/graphLabels.js +24 -0
  102. package/dist/index.js +262 -1407
  103. package/dist/labelLayout.js +24 -0
  104. package/dist/layout/anchoredLayout.js +11 -0
  105. package/dist/layout/deletionRoutes.js +10 -0
  106. package/dist/layout/drawnScale.js +22 -0
  107. package/dist/layout/mergeRuns.js +15 -0
  108. package/dist/layout/orderedLayout.js +12 -0
  109. package/dist/layout/orientToReference.js +7 -0
  110. package/dist/layout/placeOffReference.js +9 -0
  111. package/dist/layout/referenceSeeds.js +11 -0
  112. package/dist/layout/rowSpacing.js +6 -0
  113. package/dist/layout/sampleRowLayout.js +11 -0
  114. package/dist/layout/trimToWindow.js +99 -0
  115. package/dist/layout/tubeMapLayout.js +28 -0
  116. package/dist/layout/walkRowDraw.js +65 -0
  117. package/dist/layout/walkRowLayout.js +13 -0
  118. package/dist/layout/walkRows.js +11 -0
  119. package/dist/layout/walkStrip.js +40 -0
  120. package/dist/layoutModes.js +35 -0
  121. package/dist/loadBandage.js +6 -0
  122. package/dist/nodeWidths.js +18 -0
  123. package/dist/overlayLabels.js +18 -0
  124. package/dist/pansn.js +18 -0
  125. package/dist/pathAnchoring.js +18 -0
  126. package/dist/pathColors.js +31 -0
  127. package/dist/pipeline.js +40 -0
  128. package/dist/reference.js +24 -0
  129. package/dist/referenceRampCss.js +29 -0
  130. package/dist/referenceSpan.js +11 -0
  131. package/dist/referenceStrip.js +35 -0
  132. package/dist/renderer/Canvas2DRenderer.js +9 -0
  133. package/dist/renderer/GeometryBuilder.js +42 -0
  134. package/dist/renderer/colorBits.js +8 -0
  135. package/dist/renderer/recordingCanvas.js +44 -0
  136. package/dist/renderer/svgCanvas.js +6 -0
  137. package/dist/renderer/types.js +0 -0
  138. package/dist/tubeMap/axis.js +25 -0
  139. package/dist/tubeMap/coarsen.js +361 -0
  140. package/dist/tubeMap/connectors.js +13 -0
  141. package/dist/tubeMap/deviations.js +85 -0
  142. package/dist/tubeMap/draw.js +15 -0
  143. package/dist/tubeMap/frame.js +9 -0
  144. package/dist/tubeMap/genes.js +20 -0
  145. package/dist/tubeMap/mismatches.js +6 -0
  146. package/dist/tubeMap/nodeColors.js +21 -0
  147. package/dist/tubeMap/reads.js +17 -0
  148. package/dist/tubeMap/warp.js +8 -0
  149. package/dist/types/version.d.ts +1 -1
  150. package/dist/types.js +0 -0
  151. package/dist/util/SpatialIndex.js +13 -0
  152. package/dist/util/edgeCurves.js +10 -0
  153. package/dist/util/geometry.js +39 -0
  154. package/dist/util/hitDetection.js +20 -0
  155. package/dist/util/wheelZoom.js +6 -0
  156. package/dist/version.js +6 -0
  157. package/dist/viewport.js +33 -0
  158. package/dist/walkEncoding.js +39 -0
  159. package/dist/walkHighlight.js +26 -0
  160. package/dist/walkKey.js +17 -0
  161. package/package.json +38 -5
  162. package/dist/chunks/chunk-EXSFRX2F.js +0 -7400
@@ -0,0 +1,210 @@
1
+ import {
2
+ brightenAbgr
3
+ } from "./chunk-MNUSQCLG.js";
4
+
5
+ // src/renderer/Canvas2DRenderer.ts
6
+ import {
7
+ abgrToCssRgba,
8
+ normalizedRgbToCssRgba
9
+ } from "@jbrowse/core/util/colorBits";
10
+ import { syncCanvasSize } from "@jbrowse/render-core/canvas2dUtils";
11
+ import { Canvas2DRenderingBackendBase } from "@jbrowse/render-core/renderingBackendBase";
12
+ var Canvas2DRenderer = class extends Canvas2DRenderingBackendBase {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.transform = null;
16
+ this.batch = null;
17
+ this.nodeHighlights = /* @__PURE__ */ new Map();
18
+ this.highlightedEdge = null;
19
+ this.highlightFactor = 1;
20
+ }
21
+ // render-core's, not a local `width * devicePixelRatio`: it clamps the
22
+ // backing store at MAX_CANVAS_DIM_PX, reads the ratio through `getDpr()` so
23
+ // this agrees with the transform the model builds, and writes the css size
24
+ // independently of the backing size.
25
+ resize(width, height) {
26
+ syncCanvasSize(this.ctx.canvas, width, height);
27
+ }
28
+ uploadGeometry(batch) {
29
+ this.batch = batch;
30
+ this.highlightedEdge = null;
31
+ }
32
+ setNodeHighlights(factors) {
33
+ this.nodeHighlights = factors;
34
+ }
35
+ setEdgeHighlight(edgeIndex, factor) {
36
+ this.highlightedEdge = edgeIndex;
37
+ this.highlightFactor = factor;
38
+ }
39
+ updateTransform(transform) {
40
+ this.transform = transform;
41
+ }
42
+ render(clearColor) {
43
+ const t = this.transform;
44
+ if (!t) {
45
+ return;
46
+ }
47
+ const ctx = this.ctx;
48
+ const { width, height } = ctx.canvas;
49
+ if (clearColor[3] < 1) {
50
+ ctx.clearRect(0, 0, width, height);
51
+ }
52
+ ctx.fillStyle = normalizedRgbToCssRgba(
53
+ [clearColor[0], clearColor[1], clearColor[2]],
54
+ clearColor[3]
55
+ );
56
+ ctx.fillRect(0, 0, width, height);
57
+ const batch = this.batch;
58
+ if (!batch) {
59
+ return;
60
+ }
61
+ ctx.lineCap = "round";
62
+ ctx.lineJoin = "round";
63
+ this.renderEdges(batch);
64
+ this.renderNodes(batch);
65
+ this.renderArrows(batch);
66
+ }
67
+ renderEdges(batch) {
68
+ const t = this.transform;
69
+ const ctx = this.ctx;
70
+ const hl = this.highlightedEdge === null ? void 0 : batch.edgeCurveRuns.get(this.highlightedEdge);
71
+ for (const { color, items } of groupByPaint(batch.edgeCurves, (e, i) => ({
72
+ color: inRun(hl, i) ? brightenAbgr(e.color, this.highlightFactor) : e.color,
73
+ weight: e.thickness,
74
+ last: inRun(hl, i)
75
+ }))) {
76
+ ctx.strokeStyle = abgrToCssRgba(color);
77
+ ctx.lineWidth = items[0].thickness * 2 * t.dpr;
78
+ ctx.beginPath();
79
+ for (const e of items) {
80
+ const first = e.curves[0];
81
+ ctx.moveTo(
82
+ first.x0 * t.scaleX + t.translateX,
83
+ first.y0 * t.scaleY + t.translateY
84
+ );
85
+ for (const c of e.curves) {
86
+ ctx.bezierCurveTo(
87
+ c.cx0 * t.scaleX + t.translateX,
88
+ c.cy0 * t.scaleY + t.translateY,
89
+ c.cx1 * t.scaleX + t.translateX,
90
+ c.cy1 * t.scaleY + t.translateY,
91
+ c.x1 * t.scaleX + t.translateX,
92
+ c.y1 * t.scaleY + t.translateY
93
+ );
94
+ }
95
+ }
96
+ ctx.stroke();
97
+ }
98
+ }
99
+ renderNodes(batch) {
100
+ const t = this.transform;
101
+ const ctx = this.ctx;
102
+ const lifted = /* @__PURE__ */ new Map();
103
+ for (const [nodeId, factor] of this.nodeHighlights) {
104
+ const run = batch.nodeStrokeRuns.get(nodeId);
105
+ if (run) {
106
+ for (let i = run.start; i < run.start + run.count; i++) {
107
+ lifted.set(i, factor);
108
+ }
109
+ }
110
+ }
111
+ for (const { color, items } of groupByPaint(batch.nodeStrokes, (s, i) => {
112
+ const factor = lifted.get(i);
113
+ return {
114
+ color: factor === void 0 ? s.color : brightenAbgr(s.color, factor),
115
+ weight: s.thickness,
116
+ last: factor !== void 0
117
+ };
118
+ })) {
119
+ ctx.strokeStyle = abgrToCssRgba(color);
120
+ ctx.lineWidth = items[0].thickness * 2 * t.dpr;
121
+ ctx.beginPath();
122
+ for (const s of items) {
123
+ const p0 = s.points[0];
124
+ ctx.moveTo(
125
+ p0.x * t.scaleX + t.translateX,
126
+ p0.y * t.scaleY + t.translateY
127
+ );
128
+ for (let i = 1, l = s.points.length; i < l; i++) {
129
+ const p = s.points[i];
130
+ ctx.lineTo(
131
+ p.x * t.scaleX + t.translateX,
132
+ p.y * t.scaleY + t.translateY
133
+ );
134
+ }
135
+ }
136
+ ctx.stroke();
137
+ }
138
+ }
139
+ renderArrows(batch) {
140
+ const t = this.transform;
141
+ const ctx = this.ctx;
142
+ const hl = this.highlightedEdge === null ? void 0 : batch.arrowRuns.get(this.highlightedEdge);
143
+ for (const { color, items } of groupByPaint(batch.arrows, (a, i) => ({
144
+ color: inRun(hl, i) ? brightenAbgr(a.color, this.highlightFactor) : a.color,
145
+ weight: 0,
146
+ last: inRun(hl, i)
147
+ }))) {
148
+ ctx.fillStyle = abgrToCssRgba(color);
149
+ ctx.beginPath();
150
+ for (const a of items) {
151
+ const [tip, left, notch, right] = arrowheadOutline(a, t);
152
+ ctx.moveTo(tip.x, tip.y);
153
+ ctx.lineTo(left.x, left.y);
154
+ ctx.lineTo(notch.x, notch.y);
155
+ ctx.lineTo(right.x, right.y);
156
+ ctx.closePath();
157
+ }
158
+ ctx.fill();
159
+ }
160
+ }
161
+ dispose() {
162
+ super.dispose();
163
+ this.batch = null;
164
+ this.nodeHighlights = /* @__PURE__ */ new Map();
165
+ this.highlightedEdge = null;
166
+ }
167
+ };
168
+ var ARROW_NOTCH = 0.25;
169
+ function arrowheadOutline(a, t) {
170
+ const ux = Math.cos(a.angle);
171
+ const uy = Math.sin(a.angle);
172
+ const tipX = a.x * t.scaleX + t.translateX;
173
+ const tipY = a.y * t.scaleY + t.translateY;
174
+ const length = a.length * t.dpr;
175
+ const halfWidth = a.halfWidth * t.dpr;
176
+ const backX = tipX - ux * length;
177
+ const backY = tipY - uy * length;
178
+ const notchBack = length * (1 - ARROW_NOTCH);
179
+ return [
180
+ { x: tipX, y: tipY },
181
+ { x: backX - uy * halfWidth, y: backY + ux * halfWidth },
182
+ { x: tipX - ux * notchBack, y: tipY - uy * notchBack },
183
+ { x: backX + uy * halfWidth, y: backY - ux * halfWidth }
184
+ ];
185
+ }
186
+ function inRun(run, i) {
187
+ return run !== void 0 && i >= run.start && i < run.start + run.count;
188
+ }
189
+ function groupByPaint(items, paintOf) {
190
+ const groups = /* @__PURE__ */ new Map();
191
+ const deferred = /* @__PURE__ */ new Map();
192
+ for (let i = 0, l = items.length; i < l; i++) {
193
+ const item = items[i];
194
+ const { color, weight, last } = paintOf(item, i);
195
+ const into = last ? deferred : groups;
196
+ const key = `${color}:${weight}`;
197
+ const group = into.get(key);
198
+ if (group) {
199
+ group.items.push(item);
200
+ } else {
201
+ into.set(key, { color, items: [item] });
202
+ }
203
+ }
204
+ return [...groups.values(), ...deferred.values()];
205
+ }
206
+
207
+ export {
208
+ Canvas2DRenderer,
209
+ arrowheadOutline
210
+ };
@@ -0,0 +1,177 @@
1
+ import {
2
+ nodesUnderBox
3
+ } from "./chunk-YMSSF2RK.js";
4
+ import {
5
+ nodeLabelBudget,
6
+ placeSizeLabels,
7
+ rowLabelBox,
8
+ sizeLabelCandidates
9
+ } from "./chunk-N62KBLFC.js";
10
+ import {
11
+ LABEL_CHAR_PX,
12
+ LABEL_PAD,
13
+ LABEL_PX,
14
+ occupancy,
15
+ placeLabels
16
+ } from "./chunk-AB35TJST.js";
17
+
18
+ // src/labelLayout.ts
19
+ var HALO_FACTOR = 3.4;
20
+ var LEGEND_INSET_PX = 6;
21
+ var ROUTE_STACK = 8;
22
+ var GENE_PIN_DROP_PX = 18;
23
+ var GENE_STACK = 2;
24
+ var TOPMOST_BASELINE = LABEL_PX + LABEL_PAD;
25
+ function geneCoverageNote(pin) {
26
+ const length = pin.gene.end - pin.gene.start;
27
+ if (pin.covered >= 0.98) {
28
+ return void 0;
29
+ }
30
+ const [per, unit] = length >= 1e6 ? [1e6, "Mb"] : length >= 1e3 ? [1e3, "kb"] : [1, "bp"];
31
+ const amount = (bp) => +(bp / per).toFixed(per === 1 ? 0 : 1);
32
+ return `${amount(pin.covered * length)} of ${amount(length)} ${unit}`;
33
+ }
34
+ function geneLabelCandidates(pins, screen, contigThickness, nodesUnder) {
35
+ const ink = contigThickness / 2;
36
+ return byExtent(pins, (pin) => pin.gene.end - pin.gene.start).map((pin) => {
37
+ const { x, y } = screen(pin.at);
38
+ const note = geneCoverageNote(pin);
39
+ return {
40
+ item: pin,
41
+ x,
42
+ y: y + contigThickness + GENE_PIN_DROP_PX,
43
+ text: note ? `${pin.gene.name} \xB7 ${note}` : pin.gene.name,
44
+ fallback: note ? `${pin.gene.name} \u2026` : void 0,
45
+ stack: GENE_STACK,
46
+ fits: (box) => [
47
+ ...nodesUnder({
48
+ x0: box.x0 - ink,
49
+ x1: box.x1 + ink,
50
+ y0: box.y0 - ink,
51
+ y1: box.y1 + ink
52
+ })
53
+ ].every((id) => pin.nodeIds.has(id))
54
+ };
55
+ });
56
+ }
57
+ function byExtent(items, extent) {
58
+ return [...items].sort((a, b) => extent(b) - extent(a));
59
+ }
60
+ function layoutLabels(m) {
61
+ const { paneWidth: width, canvasHeight: height, translateX, translateY } = m;
62
+ const { scaleX, scaleY } = m.axisScale;
63
+ const frame = { width, height };
64
+ const screen = (p) => ({
65
+ x: p.x * scaleX + translateX,
66
+ y: p.y * scaleY + translateY
67
+ });
68
+ const reserved = m.drawnRowLabels.map(
69
+ ({ label, y }) => rowLabelBox(label, y * scaleY + translateY)
70
+ );
71
+ const stripPx = m.referenceStripZonePx ?? 0;
72
+ if (stripPx > 0) {
73
+ reserved.push({ x0: 0, x1: width, y0: 0, y1: stripPx });
74
+ }
75
+ if (m.legendSize.width > 0) {
76
+ reserved.push({
77
+ x0: width - LEGEND_INSET_PX - m.legendSize.width,
78
+ x1: width,
79
+ y0: 0,
80
+ y1: stripPx + LEGEND_INSET_PX + m.legendSize.height
81
+ });
82
+ }
83
+ if (m.poppedFrom) {
84
+ reserved.push({
85
+ x0: 0,
86
+ x1: 60 + m.poppedFrom.label.length * LABEL_CHAR_PX * 1.2,
87
+ y0: 0,
88
+ y1: 44
89
+ });
90
+ }
91
+ const take = occupancy(frame, reserved);
92
+ const onRows = m.drawnRowLabels.length > 0;
93
+ const rowsTop = onRows ? Math.min(...m.drawnRowLabels.map((r) => r.y)) : Infinity;
94
+ const halo = m.contigThickness * HALO_FACTOR;
95
+ const byBubble = byExtent(m.bubbleHalos, (h) => h.members);
96
+ const bubbles = placeLabels(
97
+ byBubble.map((h) => {
98
+ const { x, y } = screen({
99
+ x: h.labelAt.x,
100
+ y: Math.min(h.labelAt.y, rowsTop)
101
+ });
102
+ const baseline = y - halo / 2 - 6;
103
+ return {
104
+ item: h,
105
+ x,
106
+ y: onRows ? Math.max(baseline, TOPMOST_BASELINE) : baseline,
107
+ text: h.label
108
+ };
109
+ }),
110
+ frame,
111
+ take
112
+ );
113
+ const genes = placeLabels(
114
+ geneLabelCandidates(
115
+ m.genePins,
116
+ screen,
117
+ m.contigThickness,
118
+ nodesUnderBox(
119
+ m.nodePositions ?? {},
120
+ { scaleX, scaleY, translateX, translateY },
121
+ m.positionsVersion
122
+ )
123
+ ),
124
+ frame,
125
+ take
126
+ );
127
+ const sizeCandidates = m.nodePositions && m.labelsNodeSizes ? sizeLabelCandidates({
128
+ nodePositions: m.nodePositions,
129
+ nodeLengths: m.nodeLengths,
130
+ deletions: m.showDeletionEdges ? m.deletions : [],
131
+ deletionRoutes: m.deletionRoutes,
132
+ stranded: m.stranded,
133
+ alleleDeletions: m.alleleDeletions,
134
+ axis: m.axisScale,
135
+ translateX,
136
+ translateY,
137
+ width,
138
+ height,
139
+ version: m.positionsVersion
140
+ }) : { deletions: [], nodes: [] };
141
+ const deletionLabels = placeSizeLabels(sizeCandidates.deletions, take);
142
+ const routes = placeLabels(
143
+ byBubble.flatMap(
144
+ (h) => h.routes.map((route) => {
145
+ const { x, y } = screen(route.at);
146
+ return {
147
+ item: { halo: h, route },
148
+ x,
149
+ y: y + 4,
150
+ text: route.text,
151
+ stack: ROUTE_STACK
152
+ };
153
+ })
154
+ ),
155
+ frame,
156
+ take
157
+ );
158
+ const nodeLabels = placeSizeLabels(
159
+ sizeCandidates.nodes,
160
+ take,
161
+ nodeLabelBudget(width, height)
162
+ );
163
+ return {
164
+ bubbles,
165
+ genes,
166
+ routes,
167
+ sizes: [...deletionLabels, ...nodeLabels]
168
+ };
169
+ }
170
+
171
+ export {
172
+ HALO_FACTOR,
173
+ LEGEND_INSET_PX,
174
+ geneCoverageNote,
175
+ geneLabelCandidates,
176
+ layoutLabels
177
+ };
@@ -0,0 +1,52 @@
1
+ // src/tubeMap/mismatches.ts
2
+ import { forward, getXCoordinateOfBaseWithinNode } from "@gmod/tubemap-core";
3
+ function readMismatches(read, layout) {
4
+ const marks = [];
5
+ const entries = read.sequenceNew ?? [];
6
+ entries.forEach((entry, i) => {
7
+ const nodeIndex = layout.nodeMap.get(forward(entry.nodeName));
8
+ const node = nodeIndex === void 0 ? void 0 : layout.nodes[nodeIndex];
9
+ let pathIndex = i;
10
+ while (pathIndex < read.path.length && read.path[pathIndex].node !== nodeIndex) {
11
+ pathIndex += 1;
12
+ }
13
+ const y = read.path[pathIndex]?.y;
14
+ if (node && y !== void 0) {
15
+ const base = { readId: read.id, y, height: read.width, nodeY: node.y };
16
+ const at = (pos) => getXCoordinateOfBaseWithinNode(node, pos);
17
+ for (const mm of entry.mismatches) {
18
+ const x0 = at(mm.pos);
19
+ if (x0 !== null) {
20
+ if (mm.type === "insertion") {
21
+ const softClip = i === 0 && mm.pos === read.firstNodeOffset || i === entries.length - 1 && mm.pos === read.finalNodeCoverLength;
22
+ marks.push({
23
+ ...base,
24
+ kind: "insertion",
25
+ x: x0,
26
+ seq: mm.seq,
27
+ softClip
28
+ });
29
+ } else if (mm.type === "deletion" && mm.length !== void 0) {
30
+ const x1 = at(mm.pos + mm.length);
31
+ if (x1 !== null) {
32
+ marks.push({ ...base, kind: "deletion", x0, x1 });
33
+ }
34
+ } else if (mm.type === "substitution" && mm.seq !== void 0) {
35
+ const x1 = at(mm.pos + mm.seq.length);
36
+ if (x1 !== null) {
37
+ marks.push({ ...base, kind: "substitution", x0, x1, seq: mm.seq });
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ });
44
+ return marks;
45
+ }
46
+ function tubeMapMismatches(layout) {
47
+ return layout.reads.flatMap((read) => readMismatches(read, layout));
48
+ }
49
+
50
+ export {
51
+ tubeMapMismatches
52
+ };
@@ -0,0 +1,174 @@
1
+ import {
2
+ LIFT_BACKDROP_CSS,
3
+ computeColorSchemeRange,
4
+ getNodeColor
5
+ } from "./chunk-PCZ4PTYC.js";
6
+ import {
7
+ isBackbone
8
+ } from "./chunk-FYQWPEEY.js";
9
+
10
+ // src/referenceStrip.ts
11
+ import { abgrToCssRgba } from "@jbrowse/core/util/colorBits";
12
+ var REFERENCE_STRIP_PX = 12;
13
+ var REFERENCE_STRIP_ZONE_PX = REFERENCE_STRIP_PX + 8;
14
+ var OVERHANG_PX = 8;
15
+ var OVERHANG_CAP_PX = OVERHANG_PX + 3;
16
+ var MIN_STAGGER_PX = 12;
17
+ function referenceStripBlocks(graph, {
18
+ colorScheme,
19
+ referenceRamp,
20
+ walks
21
+ }) {
22
+ const range = { ...computeColorSchemeRange(graph), referenceRamp };
23
+ const out = [];
24
+ graph.nodes.forEach((node, index) => {
25
+ if (isBackbone(node)) {
26
+ const colors = walks ? walks.map((w) => {
27
+ const lane = w.colors.get(node.id);
28
+ return lane === void 0 ? LIFT_BACKDROP_CSS : abgrToCssRgba(lane);
29
+ }) : [abgrToCssRgba(getNodeColor(node, index, colorScheme, range))];
30
+ out.push({
31
+ node: node.id,
32
+ bp0: node.stable.start,
33
+ bp1: node.stable.start + node.length,
34
+ colors,
35
+ faded: colors.includes(LIFT_BACKDROP_CSS)
36
+ });
37
+ }
38
+ });
39
+ return out.sort((a, b) => a.bp0 - b.bp0);
40
+ }
41
+ function span(frame, bp0, bp1) {
42
+ const a = bp0 * frame.scale + frame.translateX;
43
+ const b = bp1 * frame.scale + frame.translateX;
44
+ return a < b ? [a, b] : [b, a];
45
+ }
46
+ var HIT_SLOP_PX = 2;
47
+ function stripOverhang(blocks, frame, width) {
48
+ const a = -frame.translateX / frame.scale;
49
+ const b = (width - frame.translateX) / frame.scale;
50
+ const lo = Math.min(a, b);
51
+ const hi = Math.max(a, b);
52
+ let below = 0;
53
+ let above = 0;
54
+ for (const block of blocks) {
55
+ below += Math.max(0, Math.min(block.bp1, lo) - block.bp0);
56
+ above += Math.max(0, block.bp1 - Math.max(block.bp0, hi));
57
+ }
58
+ return frame.scale >= 0 ? { left: Math.round(below), right: Math.round(above) } : { left: Math.round(above), right: Math.round(below) };
59
+ }
60
+ function stripBlockAt(blocks, frame, sx, sy) {
61
+ if (sy < 0 || sy > REFERENCE_STRIP_PX + HIT_SLOP_PX) {
62
+ return void 0;
63
+ }
64
+ let hit;
65
+ let best = HIT_SLOP_PX;
66
+ for (const b of blocks) {
67
+ const [x0, x1] = span(frame, b.bp0, b.bp1);
68
+ const dist = Math.max(0, x0 - sx, sx - x1);
69
+ if (dist <= best) {
70
+ best = dist;
71
+ hit = b.node;
72
+ }
73
+ }
74
+ return hit;
75
+ }
76
+ function nodeAnchor(segments, toScreen) {
77
+ const p = segments?.[Math.floor(segments.length / 2)];
78
+ return p ? toScreen(p) : void 0;
79
+ }
80
+ function stripPixels(blocks, frame, width, dpr) {
81
+ const placed = blocks.map((b) => {
82
+ const [x0, x1] = span(frame, b.bp0, b.bp1);
83
+ const px0 = Math.round(x0 * dpr);
84
+ return {
85
+ colors: b.colors,
86
+ x0,
87
+ px0,
88
+ px1: Math.max(Math.round(x1 * dpr), px0 + 1)
89
+ };
90
+ }).filter((b) => b.px1 > 0 && b.px0 < width * dpr).sort((a, b) => a.x0 - b.x0);
91
+ const out = [];
92
+ let claimed = -Infinity;
93
+ const tierEnds = [-Infinity, -Infinity];
94
+ for (const { colors, px0, px1 } of placed) {
95
+ const start = Math.max(px0, claimed);
96
+ if (px1 > start) {
97
+ const tier = tierEnds[0] < start ? 0 : 1;
98
+ tierEnds[tier] = px1;
99
+ out.push({ colors, x0: start / dpr, x1: px1 / dpr, tier });
100
+ claimed = px1;
101
+ }
102
+ }
103
+ const covered = out.length > 0 ? out.at(-1).x1 - out[0].x0 : 0;
104
+ return covered >= out.length * MIN_STAGGER_PX ? out : out.map(({ tier: _, ...b }) => b);
105
+ }
106
+ function drawOverhang(ctx, edgeX, inward, ink) {
107
+ const capX = inward > 0 ? edgeX : edgeX - OVERHANG_CAP_PX;
108
+ ctx.clearRect(capX, 0, OVERHANG_CAP_PX, REFERENCE_STRIP_PX);
109
+ const tipX = edgeX + inward;
110
+ const baseX = tipX + inward * OVERHANG_PX;
111
+ ctx.beginPath();
112
+ ctx.moveTo(tipX, REFERENCE_STRIP_PX / 2);
113
+ ctx.lineTo(baseX, 0);
114
+ ctx.lineTo(baseX, REFERENCE_STRIP_PX);
115
+ ctx.closePath();
116
+ ctx.fillStyle = ink;
117
+ ctx.fill();
118
+ }
119
+ function rowEdge(row, rows, dpr) {
120
+ return Math.round(row * REFERENCE_STRIP_PX * dpr / rows) / dpr;
121
+ }
122
+ function drawReferenceStrip(ctx, blocks, frame, {
123
+ width,
124
+ lit,
125
+ darkMode,
126
+ dpr = 1
127
+ }) {
128
+ const ink = darkMode ? "#ffffff" : "#18181c";
129
+ ctx.clearRect(0, 0, width, REFERENCE_STRIP_ZONE_PX);
130
+ for (const b of stripPixels(blocks, frame, width, dpr)) {
131
+ const { tier } = b;
132
+ const staggered = tier !== void 0 && b.colors.length === 1;
133
+ const rows = staggered ? 2 : b.colors.length;
134
+ b.colors.forEach((color, i) => {
135
+ const row = staggered ? tier : i;
136
+ const y0 = rowEdge(row, rows, dpr);
137
+ ctx.fillStyle = color;
138
+ ctx.fillRect(b.x0, y0, b.x1 - b.x0, rowEdge(row + 1, rows, dpr) - y0);
139
+ });
140
+ }
141
+ const overhang = stripOverhang(blocks, frame, width);
142
+ if (overhang.left > 0) {
143
+ drawOverhang(ctx, 0, 1, ink);
144
+ }
145
+ if (overhang.right > 0) {
146
+ drawOverhang(ctx, width, -1, ink);
147
+ }
148
+ if (lit) {
149
+ const [x0, x1] = span(frame, lit.start, lit.end);
150
+ const w = Math.max(x1 - x0, 3);
151
+ const left = (x0 + x1) / 2 - w / 2;
152
+ ctx.strokeStyle = ink;
153
+ ctx.lineWidth = 1.5;
154
+ ctx.strokeRect(left, 0.75, w, REFERENCE_STRIP_PX - 1.5);
155
+ if (lit.anchor) {
156
+ ctx.beginPath();
157
+ ctx.moveTo(left + w / 2, REFERENCE_STRIP_PX);
158
+ ctx.lineTo(lit.anchor.x, lit.anchor.y);
159
+ ctx.lineWidth = 1;
160
+ ctx.stroke();
161
+ }
162
+ }
163
+ }
164
+
165
+ export {
166
+ REFERENCE_STRIP_PX,
167
+ REFERENCE_STRIP_ZONE_PX,
168
+ referenceStripBlocks,
169
+ stripOverhang,
170
+ stripBlockAt,
171
+ nodeAnchor,
172
+ stripPixels,
173
+ drawReferenceStrip
174
+ };
@@ -0,0 +1,23 @@
1
+ import {
2
+ computeColorSchemeRange,
3
+ getNodeColor
4
+ } from "./chunk-PCZ4PTYC.js";
5
+
6
+ // src/tubeMap/nodeColors.ts
7
+ import { abgrToCssRgba } from "@jbrowse/core/util/colorBits";
8
+ function tubeMapNodeColors(graph, colorScheme, referenceRamp) {
9
+ if (colorScheme === "uniform" || colorScheme === "grey") {
10
+ return void 0;
11
+ }
12
+ const range = { ...computeColorSchemeRange(graph), referenceRamp };
13
+ return new Map(
14
+ graph.nodes.map((node, index) => [
15
+ node.id,
16
+ abgrToCssRgba(getNodeColor(node, index, colorScheme, range))
17
+ ])
18
+ );
19
+ }
20
+
21
+ export {
22
+ tubeMapNodeColors
23
+ };