@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.
Files changed (52) hide show
  1. package/esm/AlignmentsFeatureDetail/stateModelFactory.d.ts +1 -1
  2. package/esm/CramAdapter/CramSlightlyLazyFeature.d.ts +1 -1
  3. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +2 -2
  4. package/esm/LinearPileupDisplay/components/GroupByDialog.js +127 -93
  5. package/esm/LinearReadArcsDisplay/model.d.ts +5 -0
  6. package/esm/LinearReadCloudDisplay/components/LinearReadCloudReactComponent.js +6 -7
  7. package/esm/LinearReadCloudDisplay/model.d.ts +5 -2
  8. package/esm/LinearReadCloudDisplay/model.js +4 -11
  9. package/esm/LinearReadCloudDisplay/renderSvg.js +4 -5
  10. package/esm/LinearSNPCoverageDisplay/model.js +2 -2
  11. package/esm/PileupRenderer/makeImageData.js +3 -4
  12. package/esm/RenderLinearReadArcsDisplayRPC/drawFeatsRPC.d.ts +2 -1
  13. package/esm/RenderLinearReadArcsDisplayRPC/drawFeatsRPC.js +3 -4
  14. package/esm/RenderLinearReadArcsDisplayRPC/executeRenderLinearReadArcsDisplay.js +5 -4
  15. package/esm/RenderLinearReadCloudDisplayRPC/RenderLinearReadCloudDisplay.d.ts +0 -1
  16. package/esm/RenderLinearReadCloudDisplayRPC/drawFeatsCloud.d.ts +3 -4
  17. package/esm/RenderLinearReadCloudDisplayRPC/drawFeatsCloud.js +7 -20
  18. package/esm/RenderLinearReadCloudDisplayRPC/drawFeatsCommon.d.ts +2 -2
  19. package/esm/RenderLinearReadCloudDisplayRPC/drawFeatsCommon.js +3 -3
  20. package/esm/RenderLinearReadCloudDisplayRPC/drawLongReadChains.d.ts +3 -2
  21. package/esm/RenderLinearReadCloudDisplayRPC/drawLongReadChains.js +3 -4
  22. package/esm/RenderLinearReadCloudDisplayRPC/drawPairChains.d.ts +3 -2
  23. package/esm/RenderLinearReadCloudDisplayRPC/drawPairChains.js +4 -5
  24. package/esm/RenderLinearReadCloudDisplayRPC/executeRenderLinearReadCloudDisplay.js +7 -6
  25. package/esm/SNPCoverageRenderer/buildClickMap.d.ts +5 -0
  26. package/esm/SNPCoverageRenderer/buildClickMap.js +17 -0
  27. package/esm/SNPCoverageRenderer/calculateModificationCounts.d.ts +1 -19
  28. package/esm/SNPCoverageRenderer/calculateModificationCounts.js +1 -6
  29. package/esm/SNPCoverageRenderer/constants.d.ts +12 -0
  30. package/esm/SNPCoverageRenderer/constants.js +12 -0
  31. package/esm/SNPCoverageRenderer/createInterbaseItem.d.ts +7 -0
  32. package/esm/SNPCoverageRenderer/createInterbaseItem.js +13 -0
  33. package/esm/SNPCoverageRenderer/drawCrossHatches.d.ts +3 -0
  34. package/esm/SNPCoverageRenderer/drawCrossHatches.js +10 -0
  35. package/esm/SNPCoverageRenderer/drawNoncovEvents.d.ts +3 -0
  36. package/esm/SNPCoverageRenderer/drawNoncovEvents.js +56 -0
  37. package/esm/SNPCoverageRenderer/drawSecondPassMethylation.d.ts +2 -0
  38. package/esm/SNPCoverageRenderer/drawSecondPassMethylation.js +30 -0
  39. package/esm/SNPCoverageRenderer/drawSecondPassModifications.d.ts +6 -0
  40. package/esm/SNPCoverageRenderer/drawSecondPassModifications.js +85 -0
  41. package/esm/SNPCoverageRenderer/drawSecondPassSNPs.d.ts +2 -0
  42. package/esm/SNPCoverageRenderer/drawSecondPassSNPs.js +64 -0
  43. package/esm/SNPCoverageRenderer/drawStackedBars.d.ts +3 -0
  44. package/esm/SNPCoverageRenderer/drawStackedBars.js +10 -0
  45. package/esm/SNPCoverageRenderer/makeImage.d.ts +1 -1
  46. package/esm/SNPCoverageRenderer/makeImage.js +10 -306
  47. package/esm/SNPCoverageRenderer/types.d.ts +62 -1
  48. package/esm/shared/LinearReadDisplayBaseMixin.d.ts +5 -0
  49. package/esm/shared/createRPCRenderingSetup.d.ts +1 -0
  50. package/esm/shared/createRPCRenderingSetup.js +6 -1
  51. package/esm/shared/menuItems.js +3 -3
  52. 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.ts';
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, createStopTokenChecker, featureSpanPx, renderToAbstractCanvas, } from '@jbrowse/core/util';
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 { alphaColor } from "../shared/util.js";
9
- const INTERBASE_INDICATOR_WIDTH = 7;
10
- const INTERBASE_INDICATOR_HEIGHT = 4.5;
11
- const MINIMUM_INTERBASE_INDICATOR_READ_DEPTH = 7;
12
- const INTERBASE_DRAW_THRESHOLD = 0.1;
13
- const complementBase = {
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, stopToken, } = props;
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(lastCheck);
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
- lastCheck,
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
  });
@@ -1,6 +1,6 @@
1
1
  import { lazy } from 'react';
2
2
  import { getSession } from '@jbrowse/core/util';
3
- import FilterListIcon from '@mui/icons-material/ClearAll';
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: FilterListIcon,
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: FilterListIcon,
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.0.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": "^7.0.3",
25
+ "@gmod/cram": "^8.0.0",
25
26
  "@jbrowse/mobx-state-tree": "^5.5.0",
26
- "@mui/icons-material": "^7.3.6",
27
- "@mui/material": "^7.3.6",
28
- "@mui/x-charts-vendor": "^8.25.0",
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.0.4",
37
- "@jbrowse/plugin-linear-genome-view": "^4.0.4",
38
- "@jbrowse/plugin-wiggle": "^4.0.4",
39
- "@jbrowse/sv-core": "^4.0.4"
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"