@jbrowse/plugin-alignments 4.0.4 → 4.1.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.
- package/esm/AlignmentsFeatureDetail/stateModelFactory.d.ts +1 -1
- package/esm/CramAdapter/CramSlightlyLazyFeature.d.ts +1 -1
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +2 -2
- package/esm/LinearPileupDisplay/components/GroupByDialog.js +127 -93
- package/esm/LinearReadArcsDisplay/model.d.ts +5 -0
- package/esm/LinearReadCloudDisplay/components/LinearReadCloudReactComponent.js +6 -7
- package/esm/LinearReadCloudDisplay/model.d.ts +5 -2
- package/esm/LinearReadCloudDisplay/model.js +4 -11
- package/esm/LinearReadCloudDisplay/renderSvg.js +4 -5
- package/esm/LinearSNPCoverageDisplay/model.js +2 -2
- package/esm/PileupRenderer/makeImageData.js +3 -4
- package/esm/RenderLinearReadArcsDisplayRPC/drawFeatsRPC.d.ts +2 -1
- package/esm/RenderLinearReadArcsDisplayRPC/drawFeatsRPC.js +3 -4
- package/esm/RenderLinearReadArcsDisplayRPC/executeRenderLinearReadArcsDisplay.js +5 -4
- package/esm/RenderLinearReadCloudDisplayRPC/RenderLinearReadCloudDisplay.d.ts +0 -1
- package/esm/RenderLinearReadCloudDisplayRPC/drawFeatsCloud.d.ts +3 -4
- package/esm/RenderLinearReadCloudDisplayRPC/drawFeatsCloud.js +7 -20
- package/esm/RenderLinearReadCloudDisplayRPC/drawFeatsCommon.d.ts +2 -2
- package/esm/RenderLinearReadCloudDisplayRPC/drawFeatsCommon.js +3 -3
- package/esm/RenderLinearReadCloudDisplayRPC/drawLongReadChains.d.ts +3 -2
- package/esm/RenderLinearReadCloudDisplayRPC/drawLongReadChains.js +3 -4
- package/esm/RenderLinearReadCloudDisplayRPC/drawPairChains.d.ts +3 -2
- package/esm/RenderLinearReadCloudDisplayRPC/drawPairChains.js +4 -5
- package/esm/RenderLinearReadCloudDisplayRPC/executeRenderLinearReadCloudDisplay.js +7 -6
- package/esm/SNPCoverageRenderer/buildClickMap.d.ts +5 -0
- package/esm/SNPCoverageRenderer/buildClickMap.js +17 -0
- package/esm/SNPCoverageRenderer/calculateModificationCounts.d.ts +1 -19
- package/esm/SNPCoverageRenderer/calculateModificationCounts.js +1 -6
- package/esm/SNPCoverageRenderer/constants.d.ts +12 -0
- package/esm/SNPCoverageRenderer/constants.js +12 -0
- package/esm/SNPCoverageRenderer/createInterbaseItem.d.ts +7 -0
- package/esm/SNPCoverageRenderer/createInterbaseItem.js +13 -0
- package/esm/SNPCoverageRenderer/drawCrossHatches.d.ts +3 -0
- package/esm/SNPCoverageRenderer/drawCrossHatches.js +10 -0
- package/esm/SNPCoverageRenderer/drawNoncovEvents.d.ts +3 -0
- package/esm/SNPCoverageRenderer/drawNoncovEvents.js +56 -0
- package/esm/SNPCoverageRenderer/drawSecondPassMethylation.d.ts +2 -0
- package/esm/SNPCoverageRenderer/drawSecondPassMethylation.js +30 -0
- package/esm/SNPCoverageRenderer/drawSecondPassModifications.d.ts +6 -0
- package/esm/SNPCoverageRenderer/drawSecondPassModifications.js +85 -0
- package/esm/SNPCoverageRenderer/drawSecondPassSNPs.d.ts +2 -0
- package/esm/SNPCoverageRenderer/drawSecondPassSNPs.js +64 -0
- package/esm/SNPCoverageRenderer/drawStackedBars.d.ts +3 -0
- package/esm/SNPCoverageRenderer/drawStackedBars.js +10 -0
- package/esm/SNPCoverageRenderer/makeImage.d.ts +1 -1
- package/esm/SNPCoverageRenderer/makeImage.js +10 -306
- package/esm/SNPCoverageRenderer/types.d.ts +62 -1
- package/esm/shared/LinearReadDisplayBaseMixin.d.ts +5 -0
- package/esm/shared/createRPCRenderingSetup.d.ts +1 -0
- package/esm/shared/createRPCRenderingSetup.js +6 -1
- package/esm/shared/menuItems.js +3 -3
- package/package.json +10 -9
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function drawStackedBars(ctx, entries, colorMap, x, bottom, w, h, depth, startCurr) {
|
|
2
|
+
let curr = startCurr;
|
|
3
|
+
for (const base in entries) {
|
|
4
|
+
const { entryDepth } = entries[base];
|
|
5
|
+
ctx.fillStyle = colorMap[base] || 'black';
|
|
6
|
+
ctx.fillRect(x, bottom - ((entryDepth + curr) / depth) * h, w, (entryDepth / depth) * h);
|
|
7
|
+
curr += entryDepth;
|
|
8
|
+
}
|
|
9
|
+
return curr;
|
|
10
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { RenderArgsDeserializedWithFeatures } from './types
|
|
1
|
+
import type { RenderArgsDeserializedWithFeatures } from './types';
|
|
2
2
|
export declare function renderSNPCoverageToCanvas(props: RenderArgsDeserializedWithFeatures): Promise<import("librpc-web-mod").RpcResult>;
|
|
@@ -1,310 +1,15 @@
|
|
|
1
1
|
import { readConfObject } from '@jbrowse/core/configuration';
|
|
2
2
|
import { createJBrowseTheme } from '@jbrowse/core/ui';
|
|
3
|
-
import { checkStopToken2,
|
|
4
|
-
import Flatbush from '@jbrowse/core/util/flatbush';
|
|
3
|
+
import { checkStopToken2, featureSpanPx, renderToAbstractCanvas, } from '@jbrowse/core/util';
|
|
5
4
|
import { rpcResult } from '@jbrowse/core/util/librpc';
|
|
6
5
|
import { collectTransferables } from '@jbrowse/core/util/offscreenCanvasPonyfill';
|
|
7
6
|
import { YSCALEBAR_LABEL_OFFSET, getOrigin, getScale, } from '@jbrowse/plugin-wiggle';
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
C: 'G',
|
|
15
|
-
G: 'C',
|
|
16
|
-
A: 'T',
|
|
17
|
-
T: 'A',
|
|
18
|
-
};
|
|
19
|
-
const fudgeFactor = 0.6;
|
|
20
|
-
const SNP_CLICKMAP_THRESHOLD = 0.04;
|
|
21
|
-
function createInterbaseItem(maxBase, count, total, start, maxEntry) {
|
|
22
|
-
return {
|
|
23
|
-
type: maxBase,
|
|
24
|
-
base: maxBase,
|
|
25
|
-
count,
|
|
26
|
-
total,
|
|
27
|
-
avgLength: maxEntry?.avgLength,
|
|
28
|
-
minLength: maxEntry?.minLength,
|
|
29
|
-
maxLength: maxEntry?.maxLength,
|
|
30
|
-
topSequence: maxEntry?.topSequence,
|
|
31
|
-
start,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
function drawStackedBars(ctx, entries, colorMap, x, bottom, w, h, depth, startCurr) {
|
|
35
|
-
let curr = startCurr;
|
|
36
|
-
for (const base in entries) {
|
|
37
|
-
const { entryDepth } = entries[base];
|
|
38
|
-
ctx.fillStyle = colorMap[base] || 'black';
|
|
39
|
-
ctx.fillRect(x, bottom - ((entryDepth + curr) / depth) * h, w, (entryDepth / depth) * h);
|
|
40
|
-
curr += entryDepth;
|
|
41
|
-
}
|
|
42
|
-
return curr;
|
|
43
|
-
}
|
|
44
|
-
function drawCrossHatches(ctx, ticks, width, toY) {
|
|
45
|
-
ctx.lineWidth = 1;
|
|
46
|
-
ctx.strokeStyle = 'rgba(140,140,140,0.8)';
|
|
47
|
-
for (const tick of ticks.values) {
|
|
48
|
-
ctx.beginPath();
|
|
49
|
-
ctx.moveTo(0, Math.round(toY(tick)));
|
|
50
|
-
ctx.lineTo(width, Math.round(toY(tick)));
|
|
51
|
-
ctx.stroke();
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
function calculateModificationCounts({ base, isSimplex, refbase, snps, ref, score0, }) {
|
|
55
|
-
if (base === 'N') {
|
|
56
|
-
return { modifiable: score0, detectable: score0 };
|
|
57
|
-
}
|
|
58
|
-
const cmp = complementBase[base];
|
|
59
|
-
const baseCount = (snps[base]?.entryDepth || 0) + (refbase === base ? ref.entryDepth : 0);
|
|
60
|
-
const complCount = (snps[cmp]?.entryDepth || 0) + (refbase === cmp ? ref.entryDepth : 0);
|
|
61
|
-
const modifiable = baseCount + complCount;
|
|
62
|
-
const detectable = isSimplex
|
|
63
|
-
? (snps[base]?.['1'] || 0) +
|
|
64
|
-
(snps[cmp]?.['-1'] || 0) +
|
|
65
|
-
(refbase === base ? ref['1'] : 0) +
|
|
66
|
-
(refbase === cmp ? ref['-1'] : 0)
|
|
67
|
-
: modifiable;
|
|
68
|
-
return { modifiable, detectable };
|
|
69
|
-
}
|
|
70
|
-
function buildClickMap(coords, items) {
|
|
71
|
-
const flatbush = new Flatbush(Math.max(items.length, 1));
|
|
72
|
-
if (coords.length) {
|
|
73
|
-
for (let i = 0; i < coords.length; i += 4) {
|
|
74
|
-
flatbush.add(coords[i], coords[i + 1], coords[i + 2], coords[i + 3]);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
flatbush.add(0, 0);
|
|
79
|
-
}
|
|
80
|
-
flatbush.finish();
|
|
81
|
-
return {
|
|
82
|
-
flatbush: flatbush.data,
|
|
83
|
-
items,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
function drawNoncovEvents(passCtx, snpinfo, leftPx, score0, prevTotal, skipDraw, fstart) {
|
|
87
|
-
const { ctx, colorMap, toHeight2, extraHorizontallyFlippedOffset, coords, items, bpPerPx, indicatorThreshold, showInterbaseCounts, showInterbaseIndicators, } = passCtx;
|
|
88
|
-
let totalCount = 0;
|
|
89
|
-
let maxDepth = 0;
|
|
90
|
-
let maxBase = '';
|
|
91
|
-
let totalHeight = 0;
|
|
92
|
-
const r = 0.6;
|
|
93
|
-
const x = leftPx - r + extraHorizontallyFlippedOffset;
|
|
94
|
-
for (const base in snpinfo.noncov) {
|
|
95
|
-
const { entryDepth } = snpinfo.noncov[base];
|
|
96
|
-
totalCount += entryDepth;
|
|
97
|
-
if (entryDepth > maxDepth) {
|
|
98
|
-
maxDepth = entryDepth;
|
|
99
|
-
maxBase = base;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
const isSignificant = score0 > 0 && totalCount > score0 * INTERBASE_DRAW_THRESHOLD;
|
|
103
|
-
const showCounts = showInterbaseCounts && (!skipDraw || isSignificant);
|
|
104
|
-
if (showCounts) {
|
|
105
|
-
for (const base in snpinfo.noncov) {
|
|
106
|
-
const { entryDepth } = snpinfo.noncov[base];
|
|
107
|
-
const barHeight = toHeight2(entryDepth);
|
|
108
|
-
ctx.fillStyle = colorMap[base];
|
|
109
|
-
ctx.fillRect(x, INTERBASE_INDICATOR_HEIGHT + totalHeight, r * 2, barHeight);
|
|
110
|
-
totalHeight += barHeight;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (totalCount > 0) {
|
|
114
|
-
const maxEntry = snpinfo.noncov[maxBase];
|
|
115
|
-
if (showCounts) {
|
|
116
|
-
if (bpPerPx < 50 || isSignificant) {
|
|
117
|
-
const clickWidth = Math.max(r * 2, 2);
|
|
118
|
-
coords.push(x, INTERBASE_INDICATOR_HEIGHT, x + clickWidth, INTERBASE_INDICATOR_HEIGHT + totalHeight);
|
|
119
|
-
items.push(createInterbaseItem(maxBase, totalCount, score0, fstart, maxEntry));
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (showInterbaseIndicators && (!skipDraw || isSignificant)) {
|
|
123
|
-
const indicatorComparatorScore = Math.max(score0, prevTotal);
|
|
124
|
-
if (totalCount > indicatorComparatorScore * indicatorThreshold &&
|
|
125
|
-
indicatorComparatorScore > MINIMUM_INTERBASE_INDICATOR_READ_DEPTH) {
|
|
126
|
-
ctx.fillStyle = colorMap[maxBase];
|
|
127
|
-
ctx.beginPath();
|
|
128
|
-
const l = leftPx + extraHorizontallyFlippedOffset;
|
|
129
|
-
ctx.moveTo(l - INTERBASE_INDICATOR_WIDTH / 2, 0);
|
|
130
|
-
ctx.lineTo(l + INTERBASE_INDICATOR_WIDTH / 2, 0);
|
|
131
|
-
ctx.lineTo(l, INTERBASE_INDICATOR_HEIGHT);
|
|
132
|
-
ctx.fill();
|
|
133
|
-
const hitboxPadding = 1;
|
|
134
|
-
coords.push(l - INTERBASE_INDICATOR_WIDTH / 2 - hitboxPadding, 0, l + INTERBASE_INDICATOR_WIDTH / 2 + hitboxPadding, INTERBASE_INDICATOR_HEIGHT + hitboxPadding);
|
|
135
|
-
items.push(createInterbaseItem(maxBase, totalCount, indicatorComparatorScore, fstart, maxEntry));
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
function drawSecondPassModifications(passCtx, visibleModifications, isolatedModification, simplexSet) {
|
|
141
|
-
const { ctx, coverageFeatures, region, bpPerPx, toY, toHeight, lastCheck } = passCtx;
|
|
142
|
-
let snpDrawn = 0;
|
|
143
|
-
let snpSkipped = 0;
|
|
144
|
-
let lastDrawnX = Number.NEGATIVE_INFINITY;
|
|
145
|
-
let prevTotal = 0;
|
|
146
|
-
for (let i = 0, l = coverageFeatures.length; i < l; i++) {
|
|
147
|
-
checkStopToken2(lastCheck);
|
|
148
|
-
const feature = coverageFeatures[i];
|
|
149
|
-
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
|
|
150
|
-
const snpinfo = feature.get('snpinfo');
|
|
151
|
-
const w = Math.max(rightPx - leftPx, 1);
|
|
152
|
-
const score0 = feature.get('score');
|
|
153
|
-
const drawX = Math.round(leftPx);
|
|
154
|
-
const skipDraw = drawX === lastDrawnX;
|
|
155
|
-
let curr = 0;
|
|
156
|
-
const refbase = snpinfo.refbase?.toUpperCase();
|
|
157
|
-
const { nonmods, mods, snps, ref } = snpinfo;
|
|
158
|
-
const h = toHeight(score0);
|
|
159
|
-
const bottom = toY(score0) + h;
|
|
160
|
-
for (const key in nonmods) {
|
|
161
|
-
const modKey = key.slice(7);
|
|
162
|
-
const mod = visibleModifications[modKey];
|
|
163
|
-
if (!mod || (isolatedModification && mod.type !== isolatedModification)) {
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
const { modifiable, detectable } = calculateModificationCounts({
|
|
167
|
-
base: mod.base,
|
|
168
|
-
isSimplex: simplexSet.has(mod.type),
|
|
169
|
-
refbase,
|
|
170
|
-
snps,
|
|
171
|
-
ref,
|
|
172
|
-
score0,
|
|
173
|
-
});
|
|
174
|
-
const { entryDepth, avgProbability = 0 } = nonmods[key];
|
|
175
|
-
const modFraction = (modifiable / score0) * (entryDepth / detectable);
|
|
176
|
-
const barHeight = modFraction * h;
|
|
177
|
-
if (skipDraw) {
|
|
178
|
-
snpSkipped++;
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
ctx.fillStyle = alphaColor('blue', avgProbability);
|
|
182
|
-
ctx.fillRect(drawX, bottom - (curr + barHeight), w, barHeight);
|
|
183
|
-
snpDrawn++;
|
|
184
|
-
lastDrawnX = drawX;
|
|
185
|
-
}
|
|
186
|
-
curr += barHeight;
|
|
187
|
-
}
|
|
188
|
-
for (const key in mods) {
|
|
189
|
-
const modKey = key.slice(4);
|
|
190
|
-
const mod = visibleModifications[modKey];
|
|
191
|
-
if (!mod || (isolatedModification && mod.type !== isolatedModification)) {
|
|
192
|
-
continue;
|
|
193
|
-
}
|
|
194
|
-
const { modifiable, detectable } = calculateModificationCounts({
|
|
195
|
-
base: mod.base,
|
|
196
|
-
isSimplex: simplexSet.has(mod.type),
|
|
197
|
-
refbase,
|
|
198
|
-
snps,
|
|
199
|
-
ref,
|
|
200
|
-
score0,
|
|
201
|
-
});
|
|
202
|
-
const { entryDepth, avgProbability = 0 } = mods[key];
|
|
203
|
-
const modFraction = (modifiable / score0) * (entryDepth / detectable);
|
|
204
|
-
const barHeight = modFraction * h;
|
|
205
|
-
if (skipDraw) {
|
|
206
|
-
snpSkipped++;
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
ctx.fillStyle = alphaColor(mod.color || 'black', avgProbability);
|
|
210
|
-
ctx.fillRect(drawX, bottom - (curr + barHeight), w, barHeight);
|
|
211
|
-
snpDrawn++;
|
|
212
|
-
lastDrawnX = drawX;
|
|
213
|
-
}
|
|
214
|
-
curr += barHeight;
|
|
215
|
-
}
|
|
216
|
-
drawNoncovEvents(passCtx, snpinfo, leftPx, score0, prevTotal, skipDraw, feature.get('start'));
|
|
217
|
-
prevTotal = score0;
|
|
218
|
-
}
|
|
219
|
-
return { snpDrawn, snpSkipped };
|
|
220
|
-
}
|
|
221
|
-
function drawSecondPassMethylation(passCtx) {
|
|
222
|
-
const { ctx, coverageFeatures, region, bpPerPx, colorMap, toY, toHeight, lastCheck, } = passCtx;
|
|
223
|
-
let lastDrawnX = Number.NEGATIVE_INFINITY;
|
|
224
|
-
let prevTotal = 0;
|
|
225
|
-
for (let i = 0, l = coverageFeatures.length; i < l; i++) {
|
|
226
|
-
checkStopToken2(lastCheck);
|
|
227
|
-
const feature = coverageFeatures[i];
|
|
228
|
-
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
|
|
229
|
-
const snpinfo = feature.get('snpinfo');
|
|
230
|
-
const w = Math.max(rightPx - leftPx, 1);
|
|
231
|
-
const score0 = feature.get('score');
|
|
232
|
-
const drawX = Math.round(leftPx);
|
|
233
|
-
const skipDraw = drawX === lastDrawnX;
|
|
234
|
-
if (!skipDraw) {
|
|
235
|
-
const { depth, nonmods, mods } = snpinfo;
|
|
236
|
-
const h = toHeight(score0);
|
|
237
|
-
const bottom = toY(score0) + h;
|
|
238
|
-
const curr = drawStackedBars(ctx, mods, colorMap, drawX, bottom, w, h, depth, 0);
|
|
239
|
-
drawStackedBars(ctx, nonmods, colorMap, drawX, bottom, w, h, depth, curr);
|
|
240
|
-
lastDrawnX = drawX;
|
|
241
|
-
}
|
|
242
|
-
drawNoncovEvents(passCtx, snpinfo, leftPx, score0, prevTotal, skipDraw, feature.get('start'));
|
|
243
|
-
prevTotal = score0;
|
|
244
|
-
}
|
|
245
|
-
return { snpDrawn: 0, snpSkipped: 0 };
|
|
246
|
-
}
|
|
247
|
-
function drawSecondPassSNPs(passCtx) {
|
|
248
|
-
const { ctx, coverageFeatures, region, bpPerPx, colorMap, toY, toHeight, lastCheck, coords, items, } = passCtx;
|
|
249
|
-
let snpDrawn = 0;
|
|
250
|
-
let snpSkipped = 0;
|
|
251
|
-
let lastDrawnX = Number.NEGATIVE_INFINITY;
|
|
252
|
-
let lastDrawnDepth = -1;
|
|
253
|
-
let prevTotal = 0;
|
|
254
|
-
for (let i = 0, l = coverageFeatures.length; i < l; i++) {
|
|
255
|
-
checkStopToken2(lastCheck);
|
|
256
|
-
const feature = coverageFeatures[i];
|
|
257
|
-
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
|
|
258
|
-
const snpinfo = feature.get('snpinfo');
|
|
259
|
-
const w = Math.max(rightPx - leftPx, 1);
|
|
260
|
-
const score0 = feature.get('score');
|
|
261
|
-
const drawX = Math.round(leftPx);
|
|
262
|
-
const skipDraw = drawX === lastDrawnX;
|
|
263
|
-
const { depth, snps, refbase } = snpinfo;
|
|
264
|
-
const refbaseUpper = refbase?.toUpperCase();
|
|
265
|
-
const h = toHeight(score0);
|
|
266
|
-
const bottom = toY(score0) + h;
|
|
267
|
-
let curr = 0;
|
|
268
|
-
for (const base in snps) {
|
|
269
|
-
const entry = snps[base];
|
|
270
|
-
const { entryDepth } = entry;
|
|
271
|
-
const y1 = bottom - ((entryDepth + curr) / depth) * h;
|
|
272
|
-
const barHeight = (entryDepth / depth) * h;
|
|
273
|
-
const isSignificant = entryDepth / score0 >= SNP_CLICKMAP_THRESHOLD;
|
|
274
|
-
const sameDepthAtSameX = skipDraw && entryDepth === lastDrawnDepth;
|
|
275
|
-
if ((skipDraw && !isSignificant) || sameDepthAtSameX) {
|
|
276
|
-
snpSkipped++;
|
|
277
|
-
}
|
|
278
|
-
else {
|
|
279
|
-
ctx.fillStyle = colorMap[base] || 'black';
|
|
280
|
-
ctx.fillRect(drawX, y1, w, barHeight);
|
|
281
|
-
snpDrawn++;
|
|
282
|
-
lastDrawnX = drawX;
|
|
283
|
-
lastDrawnDepth = entryDepth;
|
|
284
|
-
}
|
|
285
|
-
if (isSignificant) {
|
|
286
|
-
coords.push(drawX, y1, drawX + w, y1 + barHeight);
|
|
287
|
-
items.push({
|
|
288
|
-
type: 'snp',
|
|
289
|
-
base,
|
|
290
|
-
count: entryDepth,
|
|
291
|
-
total: score0,
|
|
292
|
-
refbase: refbaseUpper,
|
|
293
|
-
avgQual: entry.avgProbability,
|
|
294
|
-
fwdCount: entry['1'] || 0,
|
|
295
|
-
revCount: entry['-1'] || 0,
|
|
296
|
-
bin: snpinfo,
|
|
297
|
-
start: feature.get('start'),
|
|
298
|
-
end: feature.get('end'),
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
curr += entryDepth;
|
|
302
|
-
}
|
|
303
|
-
drawNoncovEvents(passCtx, snpinfo, leftPx, score0, prevTotal, skipDraw, feature.get('start'));
|
|
304
|
-
prevTotal = score0;
|
|
305
|
-
}
|
|
306
|
-
return { snpDrawn, snpSkipped };
|
|
307
|
-
}
|
|
7
|
+
import { buildClickMap } from "./buildClickMap.js";
|
|
8
|
+
import { fudgeFactor } from "./constants.js";
|
|
9
|
+
import { drawCrossHatches } from "./drawCrossHatches.js";
|
|
10
|
+
import { drawSecondPassMethylation } from "./drawSecondPassMethylation.js";
|
|
11
|
+
import { drawSecondPassModifications } from "./drawSecondPassModifications.js";
|
|
12
|
+
import { drawSecondPassSNPs } from "./drawSecondPassSNPs.js";
|
|
308
13
|
export async function renderSNPCoverageToCanvas(props) {
|
|
309
14
|
const { features, regions, bpPerPx, adapterConfig } = props;
|
|
310
15
|
const region = regions[0];
|
|
@@ -345,7 +50,7 @@ export async function renderSNPCoverageToCanvas(props) {
|
|
|
345
50
|
return rpcResult(serialized, collectTransferables(rest));
|
|
346
51
|
}
|
|
347
52
|
function drawSNPCoverage(ctx, props, coverageFeatures) {
|
|
348
|
-
const { regions, bpPerPx, colorBy, displayCrossHatches, visibleModifications = {}, simplexModifications = [], scaleOpts, height: unadjustedHeight, theme: configTheme, config: cfg, ticks,
|
|
53
|
+
const { regions, bpPerPx, colorBy, displayCrossHatches, visibleModifications = {}, simplexModifications = [], scaleOpts, height: unadjustedHeight, theme: configTheme, config: cfg, ticks, stopTokenCheck, } = props;
|
|
349
54
|
const theme = createJBrowseTheme(configTheme);
|
|
350
55
|
const region = regions[0];
|
|
351
56
|
const width = (region.end - region.start) / bpPerPx;
|
|
@@ -384,9 +89,8 @@ function drawSNPCoverage(ctx, props, coverageFeatures) {
|
|
|
384
89
|
const coords = [];
|
|
385
90
|
const items = [];
|
|
386
91
|
ctx.fillStyle = colorMap.total;
|
|
387
|
-
const lastCheck = createStopTokenChecker(stopToken);
|
|
388
92
|
for (let i = 0, l = coverageFeatures.length; i < l; i++) {
|
|
389
|
-
checkStopToken2(
|
|
93
|
+
checkStopToken2(stopTokenCheck);
|
|
390
94
|
const feature = coverageFeatures[i];
|
|
391
95
|
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
|
|
392
96
|
const w = rightPx - leftPx + fudgeFactor;
|
|
@@ -413,7 +117,7 @@ function drawSNPCoverage(ctx, props, coverageFeatures) {
|
|
|
413
117
|
toY,
|
|
414
118
|
toHeight,
|
|
415
119
|
toHeight2,
|
|
416
|
-
|
|
120
|
+
stopTokenCheck,
|
|
417
121
|
extraHorizontallyFlippedOffset,
|
|
418
122
|
coords,
|
|
419
123
|
items,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BaseCoverageBin, ColorBy, ModificationTypeWithColor } from '../shared/types.ts';
|
|
2
2
|
import type { RenderArgsDeserialized as FeatureRenderArgsDeserialized } from '@jbrowse/core/pluggableElementTypes/renderers/FeatureRendererType';
|
|
3
|
-
import type { Feature } from '@jbrowse/core/util';
|
|
3
|
+
import type { Feature, LastStopTokenCheck } from '@jbrowse/core/util';
|
|
4
4
|
import type { ScaleOpts } from '@jbrowse/plugin-wiggle';
|
|
5
5
|
export interface InterbaseIndicatorItem {
|
|
6
6
|
type: 'insertion' | 'softclip' | 'hardclip';
|
|
@@ -67,4 +67,65 @@ export interface RenderArgsDeserialized extends FeatureRenderArgsDeserialized {
|
|
|
67
67
|
export interface RenderArgsDeserializedWithFeatures extends RenderArgsDeserialized {
|
|
68
68
|
features: Map<string, Feature>;
|
|
69
69
|
}
|
|
70
|
+
export interface SecondPassContext {
|
|
71
|
+
ctx: CanvasRenderingContext2D;
|
|
72
|
+
coverageFeatures: Feature[];
|
|
73
|
+
region: {
|
|
74
|
+
start: number;
|
|
75
|
+
end: number;
|
|
76
|
+
refName: string;
|
|
77
|
+
reversed?: boolean;
|
|
78
|
+
};
|
|
79
|
+
bpPerPx: number;
|
|
80
|
+
colorMap: Record<string, string>;
|
|
81
|
+
toY: (n: number) => number;
|
|
82
|
+
toHeight: (n: number) => number;
|
|
83
|
+
toHeight2: (n: number) => number;
|
|
84
|
+
stopTokenCheck?: LastStopTokenCheck;
|
|
85
|
+
extraHorizontallyFlippedOffset: number;
|
|
86
|
+
coords: number[];
|
|
87
|
+
items: ClickMapItem[];
|
|
88
|
+
indicatorThreshold: number;
|
|
89
|
+
showInterbaseCounts: boolean;
|
|
90
|
+
showInterbaseIndicators: boolean;
|
|
91
|
+
}
|
|
92
|
+
export interface SecondPassStats {
|
|
93
|
+
snpDrawn: number;
|
|
94
|
+
snpSkipped: number;
|
|
95
|
+
}
|
|
96
|
+
export interface StrandCounts {
|
|
97
|
+
readonly entryDepth: number;
|
|
98
|
+
readonly '1': number;
|
|
99
|
+
readonly '-1': number;
|
|
100
|
+
readonly '0': number;
|
|
101
|
+
}
|
|
102
|
+
export interface ModificationCountsParams {
|
|
103
|
+
readonly base: string;
|
|
104
|
+
readonly isSimplex: boolean;
|
|
105
|
+
readonly refbase: string | undefined;
|
|
106
|
+
readonly snps: Readonly<Record<string, Partial<StrandCounts>>>;
|
|
107
|
+
readonly ref: StrandCounts;
|
|
108
|
+
readonly score0: number;
|
|
109
|
+
}
|
|
110
|
+
export interface ModificationCountsResult {
|
|
111
|
+
readonly modifiable: number;
|
|
112
|
+
readonly detectable: number;
|
|
113
|
+
}
|
|
114
|
+
export interface ReducedFeature {
|
|
115
|
+
start: number;
|
|
116
|
+
end: number;
|
|
117
|
+
score: number;
|
|
118
|
+
snpinfo: BaseCoverageBin;
|
|
119
|
+
refName: string;
|
|
120
|
+
}
|
|
121
|
+
export interface SkipFeatureSerialized {
|
|
122
|
+
uniqueId: string;
|
|
123
|
+
type: 'skip';
|
|
124
|
+
refName: string;
|
|
125
|
+
start: number;
|
|
126
|
+
end: number;
|
|
127
|
+
strand: number;
|
|
128
|
+
score: number;
|
|
129
|
+
effectiveStrand: number;
|
|
130
|
+
}
|
|
70
131
|
export {};
|
|
@@ -5,19 +5,24 @@ export declare function LinearReadDisplayBaseMixin(): import("@jbrowse/mobx-stat
|
|
|
5
5
|
}, {
|
|
6
6
|
loading: boolean;
|
|
7
7
|
lastDrawnOffsetPx: number | undefined;
|
|
8
|
+
lastDrawnBpPerPx: number | undefined;
|
|
8
9
|
ref: HTMLCanvasElement | null;
|
|
9
10
|
renderingImageData: ImageBitmap | undefined;
|
|
10
11
|
renderingStopToken: import("@jbrowse/core/util").StopToken | undefined;
|
|
11
12
|
statusMessage: string | undefined;
|
|
13
|
+
canvasDrawn: boolean;
|
|
12
14
|
} & {
|
|
13
15
|
readonly drawn: boolean;
|
|
16
|
+
readonly fullyDrawn: boolean;
|
|
14
17
|
} & {
|
|
15
18
|
setLastDrawnOffsetPx(n: number): void;
|
|
19
|
+
setLastDrawnBpPerPx(n: number): void;
|
|
16
20
|
setLoading(f: boolean): void;
|
|
17
21
|
setRef(ref: HTMLCanvasElement | null): void;
|
|
18
22
|
setRenderingImageData(imageData: ImageBitmap | undefined): void;
|
|
19
23
|
setRenderingStopToken(token?: import("@jbrowse/core/util").StopToken): void;
|
|
20
24
|
setStatusMessage(msg?: string): void;
|
|
25
|
+
setCanvasDrawn(drawn: boolean): void;
|
|
21
26
|
} & {
|
|
22
27
|
beforeDestroy(): void;
|
|
23
28
|
} & {
|
|
@@ -20,6 +20,7 @@ export interface RPCRenderableModel {
|
|
|
20
20
|
ref: HTMLCanvasElement | null;
|
|
21
21
|
renderingImageData?: ImageBitmap;
|
|
22
22
|
setStatusMessage?: (msg: string) => void;
|
|
23
|
+
setCanvasDrawn?: (drawn: boolean) => void;
|
|
23
24
|
}
|
|
24
25
|
export interface RPCRenderSetupParams<T extends RPCRenderableModel, R = Record<string, unknown>> {
|
|
25
26
|
self: T;
|
|
@@ -33,6 +33,7 @@ export function createRPCRenderFunction({ self, rpcMethodName, getRPCParams, onR
|
|
|
33
33
|
const stopToken = createStopToken();
|
|
34
34
|
self.setRenderingStopToken(stopToken);
|
|
35
35
|
self.setLoading(true);
|
|
36
|
+
self.setCanvasDrawn?.(false);
|
|
36
37
|
const viewSnapshot = {
|
|
37
38
|
displayedRegions: structuredClone(view.displayedRegions),
|
|
38
39
|
bpPerPx: view.bpPerPx,
|
|
@@ -69,6 +70,7 @@ export function createRPCRenderFunction({ self, rpcMethodName, getRPCParams, onR
|
|
|
69
70
|
}
|
|
70
71
|
catch (error) {
|
|
71
72
|
if (!isAbortException(error)) {
|
|
73
|
+
console.error(error);
|
|
72
74
|
self.setError(error);
|
|
73
75
|
}
|
|
74
76
|
}
|
|
@@ -80,7 +82,10 @@ export function createRPCRenderFunction({ self, rpcMethodName, getRPCParams, onR
|
|
|
80
82
|
}
|
|
81
83
|
export function setupCanvasRenderingAutorun(self) {
|
|
82
84
|
createAutorun(self, async () => {
|
|
83
|
-
drawCanvasImageData(self.ref, self.renderingImageData);
|
|
85
|
+
const success = drawCanvasImageData(self.ref, self.renderingImageData);
|
|
86
|
+
if (isAlive(self)) {
|
|
87
|
+
self.setCanvasDrawn?.(success);
|
|
88
|
+
}
|
|
84
89
|
}, {
|
|
85
90
|
name: 'CanvasRenderAutorun',
|
|
86
91
|
});
|
package/esm/shared/menuItems.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { lazy } from 'react';
|
|
2
2
|
import { getSession } from '@jbrowse/core/util';
|
|
3
|
-
import
|
|
3
|
+
import ClearAllIcon from '@mui/icons-material/ClearAll';
|
|
4
4
|
import PaletteIcon from '@mui/icons-material/Palette';
|
|
5
5
|
import { modificationData } from "./modificationData.js";
|
|
6
6
|
const FilterByTagDialog = lazy(() => import("./components/FilterByTagDialog.js"));
|
|
@@ -150,7 +150,7 @@ export function getColorSchemeMenuItem(model) {
|
|
|
150
150
|
export function getFilterByMenuItem(model) {
|
|
151
151
|
return {
|
|
152
152
|
label: 'Filter by',
|
|
153
|
-
icon:
|
|
153
|
+
icon: ClearAllIcon,
|
|
154
154
|
onClick: () => {
|
|
155
155
|
getSession(model).queueDialog((handleClose) => [
|
|
156
156
|
FilterByTagDialog,
|
|
@@ -162,7 +162,7 @@ export function getFilterByMenuItem(model) {
|
|
|
162
162
|
export function getEditFiltersMenuItem(model) {
|
|
163
163
|
return {
|
|
164
164
|
label: 'Edit filters',
|
|
165
|
-
icon:
|
|
165
|
+
icon: ClearAllIcon,
|
|
166
166
|
type: 'subMenu',
|
|
167
167
|
subMenu: [
|
|
168
168
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-alignments",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.3",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "JBrowse 2 alignments adapters, tracks, etc.",
|
|
5
6
|
"keywords": [
|
|
6
7
|
"jbrowse",
|
|
@@ -21,11 +22,11 @@
|
|
|
21
22
|
],
|
|
22
23
|
"dependencies": {
|
|
23
24
|
"@gmod/bam": "^7.1.15",
|
|
24
|
-
"@gmod/cram": "^
|
|
25
|
+
"@gmod/cram": "^8.0.0",
|
|
25
26
|
"@jbrowse/mobx-state-tree": "^5.5.0",
|
|
26
|
-
"@mui/icons-material": "^7.3.
|
|
27
|
-
"@mui/material": "^7.3.
|
|
28
|
-
"@mui/x-charts-vendor": "^8.
|
|
27
|
+
"@mui/icons-material": "^7.3.7",
|
|
28
|
+
"@mui/material": "^7.3.7",
|
|
29
|
+
"@mui/x-charts-vendor": "^8.26.0",
|
|
29
30
|
"canvas2svg": "^1.0.16",
|
|
30
31
|
"copy-to-clipboard": "^3.3.3",
|
|
31
32
|
"fast-deep-equal": "^3.1.3",
|
|
@@ -33,10 +34,10 @@
|
|
|
33
34
|
"mobx": "^6.15.0",
|
|
34
35
|
"mobx-react": "^9.2.1",
|
|
35
36
|
"rxjs": "^7.8.2",
|
|
36
|
-
"@jbrowse/core": "^4.
|
|
37
|
-
"@jbrowse/plugin-linear-genome-view": "^4.
|
|
38
|
-
"@jbrowse/
|
|
39
|
-
"@jbrowse/
|
|
37
|
+
"@jbrowse/core": "^4.1.3",
|
|
38
|
+
"@jbrowse/plugin-linear-genome-view": "^4.1.3",
|
|
39
|
+
"@jbrowse/sv-core": "^4.1.3",
|
|
40
|
+
"@jbrowse/plugin-wiggle": "^4.1.3"
|
|
40
41
|
},
|
|
41
42
|
"peerDependencies": {
|
|
42
43
|
"react": ">=18.0.0"
|