@jbrowse/plugin-alignments 2.18.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.d.ts +1 -2
- package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +20 -13
- package/dist/AlignmentsFeatureDetail/Flags.d.ts +1 -2
- package/dist/AlignmentsFeatureDetail/Flags.js +6 -8
- package/dist/AlignmentsFeatureDetail/Formatter.d.ts +1 -2
- package/dist/AlignmentsFeatureDetail/Formatter.js +11 -36
- package/dist/AlignmentsFeatureDetail/LaunchPairedEndBreakpointSplitViewPanel.d.ts +1 -2
- package/dist/AlignmentsFeatureDetail/LaunchPairedEndBreakpointSplitViewPanel.js +44 -47
- package/dist/AlignmentsFeatureDetail/LaunchSupplementaryAlignmentBreakpointSplitViewPanel.d.ts +1 -2
- package/dist/AlignmentsFeatureDetail/LaunchSupplementaryAlignmentBreakpointSplitViewPanel.js +27 -31
- package/dist/AlignmentsFeatureDetail/LinkedPairedAlignments.d.ts +1 -2
- package/dist/AlignmentsFeatureDetail/LinkedPairedAlignments.js +2 -2
- package/dist/AlignmentsFeatureDetail/PairLink.d.ts +1 -2
- package/dist/AlignmentsFeatureDetail/PairLink.js +3 -6
- package/dist/AlignmentsFeatureDetail/SupplementaryAlignments.d.ts +1 -2
- package/dist/AlignmentsFeatureDetail/SupplementaryAlignments.js +2 -4
- package/dist/AlignmentsFeatureDetail/SupplementaryAlignmentsLocStrings.d.ts +1 -2
- package/dist/AlignmentsFeatureDetail/SupplementaryAlignmentsLocStrings.js +21 -27
- package/dist/AlignmentsFeatureDetail/index.js +17 -7
- package/dist/BamAdapter/index.js +17 -7
- package/dist/CramAdapter/CramAdapter.js +7 -2
- package/dist/CramAdapter/CramTestAdapters.d.ts +1 -1
- package/dist/CramAdapter/CramTestAdapters.js +2 -1
- package/dist/CramAdapter/index.js +17 -7
- package/dist/GuessAlignmentsTypes/index.js +19 -34
- package/dist/HtsgetBamAdapter/index.js +17 -7
- package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +1 -2
- package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.js +8 -16
- package/dist/LinearAlignmentsDisplay/model.d.ts +1 -2
- package/dist/LinearAlignmentsDisplay/model.js +5 -7
- package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +21 -7
- package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +40 -15
- package/dist/LinearPileupDisplay/components/ColorByTagDialog.d.ts +1 -2
- package/dist/LinearPileupDisplay/components/ColorByTagDialog.js +10 -39
- package/dist/LinearPileupDisplay/components/GroupByDialog.d.ts +1 -2
- package/dist/LinearPileupDisplay/components/GroupByDialog.js +82 -121
- package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.d.ts +1 -2
- package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +2 -6
- package/dist/LinearPileupDisplay/components/SetFeatureHeightDialog.d.ts +1 -2
- package/dist/LinearPileupDisplay/components/SetFeatureHeightDialog.js +13 -42
- package/dist/LinearPileupDisplay/components/SetMaxHeightDialog.d.ts +1 -2
- package/dist/LinearPileupDisplay/components/SetMaxHeightDialog.js +10 -38
- package/dist/LinearPileupDisplay/components/SortByTagDialog.d.ts +1 -2
- package/dist/LinearPileupDisplay/components/SortByTagDialog.js +15 -44
- package/dist/LinearPileupDisplay/model.d.ts +21 -7
- package/dist/LinearPileupDisplay/model.js +19 -8
- package/dist/LinearReadArcsDisplay/components/ReactComponent.d.ts +1 -2
- package/dist/LinearReadArcsDisplay/components/ReactComponent.js +4 -27
- package/dist/LinearReadArcsDisplay/index.js +17 -7
- package/dist/LinearReadArcsDisplay/model.d.ts +1 -1
- package/dist/LinearReadArcsDisplay/model.js +17 -7
- package/dist/LinearReadCloudDisplay/components/ReactComponent.d.ts +1 -2
- package/dist/LinearReadCloudDisplay/components/ReactComponent.js +4 -27
- package/dist/LinearReadCloudDisplay/index.js +17 -7
- package/dist/LinearReadCloudDisplay/model.d.ts +1 -1
- package/dist/LinearReadCloudDisplay/model.js +17 -7
- package/dist/LinearSNPCoverageDisplay/components/Tooltip.d.ts +1 -2
- package/dist/LinearSNPCoverageDisplay/components/Tooltip.js +15 -54
- package/dist/LinearSNPCoverageDisplay/model.d.ts +4 -4
- package/dist/LinearSNPCoverageDisplay/model.js +49 -35
- package/dist/MismatchParser/cigarToMismatches.d.ts +1 -2
- package/dist/MismatchParser/index.d.ts +1 -2
- package/dist/MismatchParser/mdToMismatches.d.ts +1 -2
- package/dist/PileupRenderer/PileupRenderer.d.ts +4 -4
- package/dist/PileupRenderer/PileupRenderer.js +17 -7
- package/dist/PileupRenderer/components/PileupRendering.d.ts +1 -2
- package/dist/PileupRenderer/components/PileupRendering.js +15 -40
- package/dist/PileupRenderer/configSchema.d.ts +5 -0
- package/dist/PileupRenderer/configSchema.js +5 -0
- package/dist/PileupRenderer/makeImageData.js +2 -0
- package/dist/PileupRenderer/renderMismatches.d.ts +2 -1
- package/dist/PileupRenderer/renderMismatches.js +18 -13
- package/dist/SNPCoverageAdapter/index.js +17 -7
- package/dist/SNPCoverageAdapter/processModifications.js +1 -1
- package/dist/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +1 -18
- package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js +35 -264
- package/dist/SNPCoverageRenderer/configSchema.d.ts +3 -3
- package/dist/SNPCoverageRenderer/configSchema.js +3 -3
- package/dist/SNPCoverageRenderer/makeImage.d.ts +2 -0
- package/dist/SNPCoverageRenderer/makeImage.js +270 -0
- package/dist/SNPCoverageRenderer/types.d.ts +19 -0
- package/dist/SNPCoverageRenderer/types.js +2 -0
- package/dist/index.js +17 -7
- package/dist/shared/components/BaseDisplayComponent.d.ts +1 -2
- package/dist/shared/components/BaseDisplayComponent.js +6 -13
- package/dist/shared/components/FilterByTagDialog.d.ts +1 -2
- package/dist/shared/components/FilterByTagDialog.js +42 -92
- package/dist/shared/renderSvgUtil.d.ts +1 -2
- package/dist/shared/renderSvgUtil.js +20 -17
- package/esm/AlignmentsFeatureDetail/AlignmentsFeatureDetail.d.ts +1 -2
- package/esm/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +3 -6
- package/esm/AlignmentsFeatureDetail/Flags.d.ts +1 -2
- package/esm/AlignmentsFeatureDetail/Flags.js +6 -8
- package/esm/AlignmentsFeatureDetail/Formatter.d.ts +1 -2
- package/esm/AlignmentsFeatureDetail/Formatter.js +11 -13
- package/esm/AlignmentsFeatureDetail/LaunchPairedEndBreakpointSplitViewPanel.d.ts +1 -2
- package/esm/AlignmentsFeatureDetail/LaunchPairedEndBreakpointSplitViewPanel.js +27 -40
- package/esm/AlignmentsFeatureDetail/LaunchSupplementaryAlignmentBreakpointSplitViewPanel.d.ts +1 -2
- package/esm/AlignmentsFeatureDetail/LaunchSupplementaryAlignmentBreakpointSplitViewPanel.js +10 -24
- package/esm/AlignmentsFeatureDetail/LinkedPairedAlignments.d.ts +1 -2
- package/esm/AlignmentsFeatureDetail/LinkedPairedAlignments.js +2 -2
- package/esm/AlignmentsFeatureDetail/PairLink.d.ts +1 -2
- package/esm/AlignmentsFeatureDetail/PairLink.js +3 -3
- package/esm/AlignmentsFeatureDetail/SupplementaryAlignments.d.ts +1 -2
- package/esm/AlignmentsFeatureDetail/SupplementaryAlignments.js +2 -4
- package/esm/AlignmentsFeatureDetail/SupplementaryAlignmentsLocStrings.d.ts +1 -2
- package/esm/AlignmentsFeatureDetail/SupplementaryAlignmentsLocStrings.js +21 -24
- package/esm/CramAdapter/CramAdapter.js +7 -2
- package/esm/CramAdapter/CramTestAdapters.d.ts +1 -1
- package/esm/CramAdapter/CramTestAdapters.js +2 -1
- package/esm/GuessAlignmentsTypes/index.js +19 -34
- package/esm/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +1 -2
- package/esm/LinearAlignmentsDisplay/components/AlignmentsDisplay.js +8 -13
- package/esm/LinearAlignmentsDisplay/model.d.ts +1 -2
- package/esm/LinearAlignmentsDisplay/model.js +5 -7
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +21 -7
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +23 -8
- package/esm/LinearPileupDisplay/components/ColorByTagDialog.d.ts +1 -2
- package/esm/LinearPileupDisplay/components/ColorByTagDialog.js +10 -16
- package/esm/LinearPileupDisplay/components/GroupByDialog.d.ts +1 -2
- package/esm/LinearPileupDisplay/components/GroupByDialog.js +82 -98
- package/esm/LinearPileupDisplay/components/LinearPileupDisplayBlurb.d.ts +1 -2
- package/esm/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +2 -3
- package/esm/LinearPileupDisplay/components/SetFeatureHeightDialog.d.ts +1 -2
- package/esm/LinearPileupDisplay/components/SetFeatureHeightDialog.js +13 -19
- package/esm/LinearPileupDisplay/components/SetMaxHeightDialog.d.ts +1 -2
- package/esm/LinearPileupDisplay/components/SetMaxHeightDialog.js +10 -15
- package/esm/LinearPileupDisplay/components/SortByTagDialog.d.ts +1 -2
- package/esm/LinearPileupDisplay/components/SortByTagDialog.js +15 -21
- package/esm/LinearPileupDisplay/model.d.ts +21 -7
- package/esm/LinearPileupDisplay/model.js +2 -1
- package/esm/LinearReadArcsDisplay/components/ReactComponent.d.ts +1 -2
- package/esm/LinearReadArcsDisplay/components/ReactComponent.js +4 -4
- package/esm/LinearReadArcsDisplay/model.d.ts +1 -1
- package/esm/LinearReadCloudDisplay/components/ReactComponent.d.ts +1 -2
- package/esm/LinearReadCloudDisplay/components/ReactComponent.js +4 -4
- package/esm/LinearReadCloudDisplay/model.d.ts +1 -1
- package/esm/LinearSNPCoverageDisplay/components/Tooltip.d.ts +1 -2
- package/esm/LinearSNPCoverageDisplay/components/Tooltip.js +15 -51
- package/esm/LinearSNPCoverageDisplay/model.d.ts +4 -4
- package/esm/LinearSNPCoverageDisplay/model.js +32 -28
- package/esm/MismatchParser/cigarToMismatches.d.ts +1 -2
- package/esm/MismatchParser/index.d.ts +1 -2
- package/esm/MismatchParser/mdToMismatches.d.ts +1 -2
- package/esm/PileupRenderer/PileupRenderer.d.ts +4 -4
- package/esm/PileupRenderer/components/PileupRendering.d.ts +1 -2
- package/esm/PileupRenderer/components/PileupRendering.js +15 -17
- package/esm/PileupRenderer/configSchema.d.ts +5 -0
- package/esm/PileupRenderer/configSchema.js +5 -0
- package/esm/PileupRenderer/makeImageData.js +2 -0
- package/esm/PileupRenderer/renderMismatches.d.ts +2 -1
- package/esm/PileupRenderer/renderMismatches.js +18 -13
- package/esm/SNPCoverageAdapter/processModifications.js +1 -1
- package/esm/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +1 -18
- package/esm/SNPCoverageRenderer/SNPCoverageRenderer.js +3 -265
- package/esm/SNPCoverageRenderer/configSchema.d.ts +3 -3
- package/esm/SNPCoverageRenderer/configSchema.js +3 -3
- package/esm/SNPCoverageRenderer/makeImage.d.ts +2 -0
- package/esm/SNPCoverageRenderer/makeImage.js +267 -0
- package/esm/SNPCoverageRenderer/types.d.ts +19 -0
- package/esm/SNPCoverageRenderer/types.js +1 -0
- package/esm/shared/components/BaseDisplayComponent.d.ts +1 -2
- package/esm/shared/components/BaseDisplayComponent.js +6 -10
- package/esm/shared/components/FilterByTagDialog.d.ts +1 -2
- package/esm/shared/components/FilterByTagDialog.js +42 -69
- package/esm/shared/renderSvgUtil.d.ts +1 -2
- package/esm/shared/renderSvgUtil.js +3 -7
- package/package.json +13 -13
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
3
|
import { PrerenderedCanvas } from '@jbrowse/core/ui';
|
|
3
4
|
import { bpSpanPx } from '@jbrowse/core/util';
|
|
4
5
|
import { observer } from 'mobx-react';
|
|
@@ -91,7 +92,7 @@ const PileupRendering = observer(function (props) {
|
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
const canvasWidth = Math.ceil(width);
|
|
94
|
-
return (
|
|
95
|
+
return (_jsxs("div", { ref: ref, "data-testid": [
|
|
95
96
|
'pileup-overlay',
|
|
96
97
|
sortedBy === null || sortedBy === void 0 ? void 0 : sortedBy.type,
|
|
97
98
|
colorBy === null || colorBy === void 0 ? void 0 : colorBy.type,
|
|
@@ -117,20 +118,17 @@ const PileupRendering = observer(function (props) {
|
|
|
117
118
|
onClick(event);
|
|
118
119
|
}, onContextMenu: event => {
|
|
119
120
|
onContextMenu(event);
|
|
120
|
-
}, onFocus: () => { }, onBlur: () => { } },
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
pointerEvents: 'none',
|
|
133
|
-
...selected,
|
|
134
|
-
} })) : null));
|
|
121
|
+
}, onFocus: () => { }, onBlur: () => { }, children: [_jsx(PrerenderedCanvas, { ...props, style: { position: 'absolute', left: 0, top: 0 } }), firstRender && highlight ? (_jsx("div", { style: {
|
|
122
|
+
position: 'absolute',
|
|
123
|
+
backgroundColor: '#0003',
|
|
124
|
+
pointerEvents: 'none',
|
|
125
|
+
...highlight,
|
|
126
|
+
} })) : null, firstRender && selected ? (_jsx("div", { style: {
|
|
127
|
+
position: 'absolute',
|
|
128
|
+
border: '2px solid #00b8ff',
|
|
129
|
+
boxSizing: 'content-box',
|
|
130
|
+
pointerEvents: 'none',
|
|
131
|
+
...selected,
|
|
132
|
+
} })) : null] }));
|
|
135
133
|
});
|
|
136
134
|
export default PileupRendering;
|
|
@@ -22,6 +22,11 @@ declare const PileupRenderer: import("@jbrowse/core/configuration/configurationS
|
|
|
22
22
|
description: string;
|
|
23
23
|
defaultValue: number;
|
|
24
24
|
};
|
|
25
|
+
hideSmallIndels: {
|
|
26
|
+
type: string;
|
|
27
|
+
description: string;
|
|
28
|
+
defaultValue: boolean;
|
|
29
|
+
};
|
|
25
30
|
maxHeight: {
|
|
26
31
|
type: string;
|
|
27
32
|
description: string;
|
|
@@ -29,6 +29,11 @@ const PileupRenderer = ConfigurationSchema('PileupRenderer', {
|
|
|
29
29
|
description: 'the minimum width in px for a pileup mismatch feature. use for increasing/decreasing mismatch marker widths when zoomed out, e.g. 0 or 1',
|
|
30
30
|
defaultValue: 1,
|
|
31
31
|
},
|
|
32
|
+
hideSmallIndels: {
|
|
33
|
+
type: 'boolean',
|
|
34
|
+
description: 'Hides small indels, sometimes occurring in long read sequencing',
|
|
35
|
+
defaultValue: false,
|
|
36
|
+
},
|
|
32
37
|
maxHeight: {
|
|
33
38
|
type: 'integer',
|
|
34
39
|
description: 'the maximum height to be used in a pileup rendering',
|
|
@@ -10,6 +10,7 @@ export function makeImageData({ ctx, layoutRecords, canvasWidth, renderArgs, })
|
|
|
10
10
|
const mismatchAlpha = readConfObject(config, 'mismatchAlpha');
|
|
11
11
|
const minSubfeatureWidth = readConfObject(config, 'minSubfeatureWidth');
|
|
12
12
|
const largeInsertionIndicatorScale = readConfObject(config, 'largeInsertionIndicatorScale');
|
|
13
|
+
const hideSmallIndels = readConfObject(config, 'hideSmallIndels');
|
|
13
14
|
const defaultColor = readConfObject(config, 'color') === '#f0f';
|
|
14
15
|
const theme = createJBrowseTheme(configTheme);
|
|
15
16
|
const colorForBase = getColorBaseMap(theme);
|
|
@@ -39,6 +40,7 @@ export function makeImageData({ ctx, layoutRecords, canvasWidth, renderArgs, })
|
|
|
39
40
|
ctx,
|
|
40
41
|
feat,
|
|
41
42
|
renderArgs,
|
|
43
|
+
hideSmallIndels,
|
|
42
44
|
mismatchAlpha,
|
|
43
45
|
drawSNPsMuted,
|
|
44
46
|
drawIndels,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ProcessedRenderArgs } from './types';
|
|
2
2
|
import type { LayoutFeature } from './util';
|
|
3
|
-
export declare function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, largeInsertionIndicatorScale, mismatchAlpha, charWidth, charHeight, colorForBase, contrastForBase, canvasWidth, drawSNPsMuted, drawIndels, }: {
|
|
3
|
+
export declare function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, largeInsertionIndicatorScale, mismatchAlpha, charWidth, charHeight, colorForBase, contrastForBase, hideSmallIndels, canvasWidth, drawSNPsMuted, drawIndels, }: {
|
|
4
4
|
ctx: CanvasRenderingContext2D;
|
|
5
5
|
feat: LayoutFeature;
|
|
6
6
|
renderArgs: ProcessedRenderArgs;
|
|
@@ -11,6 +11,7 @@ export declare function renderMismatches({ ctx, feat, renderArgs, minSubfeatureW
|
|
|
11
11
|
drawSNPsMuted?: boolean;
|
|
12
12
|
minSubfeatureWidth: number;
|
|
13
13
|
largeInsertionIndicatorScale: number;
|
|
14
|
+
hideSmallIndels: boolean;
|
|
14
15
|
charWidth: number;
|
|
15
16
|
charHeight: number;
|
|
16
17
|
canvasWidth: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { bpSpanPx, measureText } from '@jbrowse/core/util';
|
|
2
2
|
import { colord } from '@jbrowse/core/util/colord';
|
|
3
3
|
import { fillRect } from './util';
|
|
4
|
-
export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, largeInsertionIndicatorScale, mismatchAlpha, charWidth, charHeight, colorForBase, contrastForBase, canvasWidth, drawSNPsMuted, drawIndels = true, }) {
|
|
4
|
+
export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, largeInsertionIndicatorScale, mismatchAlpha, charWidth, charHeight, colorForBase, contrastForBase, hideSmallIndels, canvasWidth, drawSNPsMuted, drawIndels = true, }) {
|
|
5
5
|
const { bpPerPx, regions } = renderArgs;
|
|
6
6
|
const { heightPx, topPx, feature } = feat;
|
|
7
7
|
const region = regions[0];
|
|
@@ -43,12 +43,15 @@ export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, la
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
else if (mismatch.type === 'deletion' && drawIndels) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
const len = mismatch.length;
|
|
47
|
+
if (!hideSmallIndels || len >= 10) {
|
|
48
|
+
fillRect(ctx, leftPx, topPx, Math.abs(leftPx - rightPx), heightPx, canvasWidth, colorForBase.deletion);
|
|
49
|
+
const txt = `${mismatch.length}`;
|
|
50
|
+
const rwidth = measureText(txt, 10);
|
|
51
|
+
if (widthPx >= rwidth && heightPx >= heightLim) {
|
|
52
|
+
ctx.fillStyle = contrastForBase.deletion;
|
|
53
|
+
ctx.fillText(txt, (leftPx + rightPx) / 2 - rwidth / 2, topPx + heightPx);
|
|
54
|
+
}
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
else if (mismatch.type === 'insertion' && drawIndels) {
|
|
@@ -56,12 +59,14 @@ export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, la
|
|
|
56
59
|
const len = +mismatch.base || mismatch.length;
|
|
57
60
|
const insW = Math.max(0, Math.min(1.2, 1 / bpPerPx));
|
|
58
61
|
if (len < 10) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
if (!hideSmallIndels) {
|
|
63
|
+
fillRect(ctx, pos, topPx, insW, heightPx, canvasWidth, 'purple');
|
|
64
|
+
if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
|
|
65
|
+
const l = Math.round(pos - insW);
|
|
66
|
+
fillRect(ctx, l, topPx, insW * 3, 1, canvasWidth);
|
|
67
|
+
fillRect(ctx, l, topPx + heightPx - 1, insW * 3, 1, canvasWidth);
|
|
68
|
+
ctx.fillText(`(${mismatch.base})`, pos + 3, topPx + heightPx);
|
|
69
|
+
}
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
}
|
|
@@ -18,7 +18,6 @@ export function processModifications({ feature, colorBy, region, bins, regionSeq
|
|
|
18
18
|
bins[epos] = {
|
|
19
19
|
depth: 0,
|
|
20
20
|
readsCounted: 0,
|
|
21
|
-
refbase: regionSequence[epos],
|
|
22
21
|
snps: {},
|
|
23
22
|
ref: {
|
|
24
23
|
probabilities: [],
|
|
@@ -35,6 +34,7 @@ export function processModifications({ feature, colorBy, region, bins, regionSeq
|
|
|
35
34
|
}
|
|
36
35
|
const s = 1 - sum(allProbs);
|
|
37
36
|
const bin = bins[epos];
|
|
37
|
+
bin.refbase = regionSequence[epos];
|
|
38
38
|
if (twoColor && s > max(allProbs)) {
|
|
39
39
|
incWithProbabilities(bin, fstrand, 'nonmods', `nonmod_${type}`, s);
|
|
40
40
|
}
|
|
@@ -1,22 +1,5 @@
|
|
|
1
1
|
import { WiggleBaseRenderer } from '@jbrowse/plugin-wiggle';
|
|
2
|
-
import type {
|
|
3
|
-
import type { RenderArgsDeserialized as FeatureRenderArgsDeserialized } from '@jbrowse/core/pluggableElementTypes/renderers/FeatureRendererType';
|
|
4
|
-
import type { Feature } from '@jbrowse/core/util';
|
|
5
|
-
import type { ScaleOpts } from '@jbrowse/plugin-wiggle';
|
|
6
|
-
export interface RenderArgsDeserialized extends FeatureRenderArgsDeserialized {
|
|
7
|
-
bpPerPx: number;
|
|
8
|
-
height: number;
|
|
9
|
-
highResolutionScaling: number;
|
|
10
|
-
scaleOpts: ScaleOpts;
|
|
11
|
-
}
|
|
12
|
-
export interface RenderArgsDeserializedWithFeatures extends RenderArgsDeserialized {
|
|
13
|
-
features: Map<string, Feature>;
|
|
14
|
-
ticks: {
|
|
15
|
-
values: number[];
|
|
16
|
-
};
|
|
17
|
-
displayCrossHatches: boolean;
|
|
18
|
-
visibleModifications?: Record<string, ModificationTypeWithColor>;
|
|
19
|
-
}
|
|
2
|
+
import type { RenderArgsDeserializedWithFeatures } from './types';
|
|
20
3
|
export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
21
4
|
draw(ctx: CanvasRenderingContext2D, props: RenderArgsDeserializedWithFeatures): Promise<undefined>;
|
|
22
5
|
}
|
|
@@ -1,270 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createJBrowseTheme } from '@jbrowse/core/ui';
|
|
3
|
-
import { bpSpanPx, featureSpanPx } from '@jbrowse/core/util';
|
|
4
|
-
import { checkStopToken } from '@jbrowse/core/util/stopToken';
|
|
5
|
-
import { WiggleBaseRenderer, YSCALEBAR_LABEL_OFFSET, getOrigin, getScale, } from '@jbrowse/plugin-wiggle';
|
|
6
|
-
import { alphaColor } from '../shared/util';
|
|
7
|
-
const INTERBASE_INDICATOR_WIDTH = 7;
|
|
8
|
-
const INTERBASE_INDICATOR_HEIGHT = 4.5;
|
|
9
|
-
const MINIMUM_INTERBASE_INDICATOR_READ_DEPTH = 7;
|
|
10
|
-
const complementBase = {
|
|
11
|
-
C: 'G',
|
|
12
|
-
G: 'C',
|
|
13
|
-
A: 'T',
|
|
14
|
-
T: 'A',
|
|
15
|
-
};
|
|
16
|
-
const fudgeFactor = 0.6;
|
|
1
|
+
import { WiggleBaseRenderer } from '@jbrowse/plugin-wiggle';
|
|
17
2
|
export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
18
3
|
async draw(ctx, props) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const theme = createJBrowseTheme(configTheme);
|
|
22
|
-
const region = regions[0];
|
|
23
|
-
const width = (region.end - region.start) / bpPerPx;
|
|
24
|
-
const offset = YSCALEBAR_LABEL_OFFSET;
|
|
25
|
-
const height = unadjustedHeight - offset * 2;
|
|
26
|
-
const opts = { ...scaleOpts, range: [0, height] };
|
|
27
|
-
const viewScale = getScale(opts);
|
|
28
|
-
const indicatorViewScale = getScale({
|
|
29
|
-
...opts,
|
|
30
|
-
range: [0, height / 2],
|
|
31
|
-
scaleType: 'linear',
|
|
32
|
-
});
|
|
33
|
-
const originY = getOrigin(scaleOpts.scaleType);
|
|
34
|
-
const originLinear = getOrigin('linear');
|
|
35
|
-
const indicatorThreshold = readConfObject(cfg, 'indicatorThreshold');
|
|
36
|
-
const drawInterbaseCounts = readConfObject(cfg, 'drawInterbaseCounts');
|
|
37
|
-
const drawArcs = readConfObject(cfg, 'drawArcs');
|
|
38
|
-
const drawIndicators = readConfObject(cfg, 'drawIndicators');
|
|
39
|
-
const toY = (n) => height - (viewScale(n) || 0) + offset;
|
|
40
|
-
const toHeight = (n) => toY(originY) - toY(n);
|
|
41
|
-
const toY2 = (n) => height - (indicatorViewScale(n) || 0) + offset;
|
|
42
|
-
const toHeight2 = (n) => toY2(originLinear) - toY2(n);
|
|
43
|
-
const { bases } = theme.palette;
|
|
44
|
-
const colorForBase = {
|
|
45
|
-
A: bases.A.main,
|
|
46
|
-
C: bases.C.main,
|
|
47
|
-
G: bases.G.main,
|
|
48
|
-
T: bases.T.main,
|
|
49
|
-
insertion: 'purple',
|
|
50
|
-
softclip: 'blue',
|
|
51
|
-
hardclip: 'red',
|
|
52
|
-
total: readConfObject(cfg, 'color'),
|
|
53
|
-
mod_NONE: 'blue',
|
|
54
|
-
cpg_meth: 'red',
|
|
55
|
-
cpg_unmeth: 'blue',
|
|
56
|
-
};
|
|
57
|
-
const feats = [...features.values()];
|
|
58
|
-
ctx.fillStyle = colorForBase.total;
|
|
59
|
-
let start = performance.now();
|
|
60
|
-
for (const feature of feats) {
|
|
61
|
-
if (feature.get('type') === 'skip') {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
|
|
65
|
-
const w = rightPx - leftPx + fudgeFactor;
|
|
66
|
-
const score = feature.get('score');
|
|
67
|
-
ctx.fillRect(leftPx, toY(score), w, toHeight(score));
|
|
68
|
-
if (performance.now() - start > 400) {
|
|
69
|
-
checkStopToken(stopToken);
|
|
70
|
-
start = performance.now();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
let prevTotal = 0;
|
|
74
|
-
const extraHorizontallyFlippedOffset = region.reversed ? 1 / bpPerPx : 0;
|
|
75
|
-
const drawingModifications = (colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'modifications';
|
|
76
|
-
const drawingMethylation = (colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'methylation';
|
|
77
|
-
const isolatedModification = (_a = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _a === void 0 ? void 0 : _a.isolatedModification;
|
|
78
|
-
start = performance.now();
|
|
79
|
-
for (const feature of feats) {
|
|
80
|
-
const now = performance.now();
|
|
81
|
-
if (now - start > 400) {
|
|
82
|
-
checkStopToken(stopToken);
|
|
83
|
-
}
|
|
84
|
-
if (feature.get('type') === 'skip') {
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
|
|
88
|
-
const snpinfo = feature.get('snpinfo');
|
|
89
|
-
const w = Math.max(rightPx - leftPx, 1);
|
|
90
|
-
const score0 = feature.get('score');
|
|
91
|
-
if (drawingModifications) {
|
|
92
|
-
let curr = 0;
|
|
93
|
-
const refbase = (_b = snpinfo.refbase) === null || _b === void 0 ? void 0 : _b.toUpperCase();
|
|
94
|
-
const { nonmods, mods, snps, ref } = snpinfo;
|
|
95
|
-
for (const m of Object.keys(nonmods).sort().reverse()) {
|
|
96
|
-
const mod = visibleModifications[m.replace('nonmod_', '')] ||
|
|
97
|
-
visibleModifications[m.replace('mod_', '')];
|
|
98
|
-
if (!mod) {
|
|
99
|
-
console.warn(`${m} not known yet`);
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
if (isolatedModification && mod.type !== isolatedModification) {
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
const cmp = complementBase[mod.base];
|
|
106
|
-
const detectable = mod.base === 'N'
|
|
107
|
-
? score0
|
|
108
|
-
: (((_c = snps[mod.base]) === null || _c === void 0 ? void 0 : _c.entryDepth) || 0) +
|
|
109
|
-
(((_d = snps[cmp]) === null || _d === void 0 ? void 0 : _d.entryDepth) || 0) +
|
|
110
|
-
(refbase === mod.base ? ref['1'] : 0) +
|
|
111
|
-
(refbase === cmp ? ref['-1'] : 0);
|
|
112
|
-
const modifiable = mod.base === 'N'
|
|
113
|
-
? score0
|
|
114
|
-
: (((_e = snps[mod.base]) === null || _e === void 0 ? void 0 : _e.entryDepth) || 0) +
|
|
115
|
-
(((_f = snps[cmp]) === null || _f === void 0 ? void 0 : _f.entryDepth) || 0) +
|
|
116
|
-
(refbase === mod.base ? ref.entryDepth : 0) +
|
|
117
|
-
(refbase === cmp ? ref.entryDepth : 0);
|
|
118
|
-
const { entryDepth, avgProbability = 0 } = snpinfo.nonmods[m];
|
|
119
|
-
const modFraction = (modifiable / score0) * (entryDepth / detectable);
|
|
120
|
-
const nonModColor = 'blue';
|
|
121
|
-
const c = alphaColor(nonModColor, avgProbability);
|
|
122
|
-
const height = toHeight(score0);
|
|
123
|
-
const bottom = toY(score0) + height;
|
|
124
|
-
ctx.fillStyle = c;
|
|
125
|
-
ctx.fillRect(Math.round(leftPx), bottom - (curr + modFraction * height), w, modFraction * height);
|
|
126
|
-
curr += modFraction * height;
|
|
127
|
-
}
|
|
128
|
-
for (const m of Object.keys(mods).sort().reverse()) {
|
|
129
|
-
const mod = visibleModifications[m.replace('mod_', '')];
|
|
130
|
-
if (!mod) {
|
|
131
|
-
console.warn(`${m} not known yet`);
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
if (isolatedModification && mod.type !== isolatedModification) {
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
const cmp = complementBase[mod.base];
|
|
138
|
-
const detectable = mod.base === 'N'
|
|
139
|
-
? score0
|
|
140
|
-
: (((_g = snps[mod.base]) === null || _g === void 0 ? void 0 : _g.entryDepth) || 0) +
|
|
141
|
-
(((_h = snps[cmp]) === null || _h === void 0 ? void 0 : _h.entryDepth) || 0) +
|
|
142
|
-
(refbase === mod.base ? ref['1'] : 0) +
|
|
143
|
-
(refbase === cmp ? ref['-1'] : 0);
|
|
144
|
-
const modifiable = mod.base === 'N'
|
|
145
|
-
? score0
|
|
146
|
-
: (((_j = snps[mod.base]) === null || _j === void 0 ? void 0 : _j.entryDepth) || 0) +
|
|
147
|
-
(((_k = snps[cmp]) === null || _k === void 0 ? void 0 : _k.entryDepth) || 0) +
|
|
148
|
-
(refbase === mod.base ? ref.entryDepth : 0) +
|
|
149
|
-
(refbase === cmp ? ref.entryDepth : 0);
|
|
150
|
-
const { entryDepth, avgProbability = 0 } = mods[m];
|
|
151
|
-
const modFraction = (modifiable / score0) * (entryDepth / detectable);
|
|
152
|
-
const baseColor = mod.color || 'black';
|
|
153
|
-
const c = alphaColor(baseColor, avgProbability);
|
|
154
|
-
const height = toHeight(score0);
|
|
155
|
-
const bottom = toY(score0) + height;
|
|
156
|
-
ctx.fillStyle = c;
|
|
157
|
-
ctx.fillRect(Math.round(leftPx), bottom - (curr + modFraction * height), w, modFraction * height);
|
|
158
|
-
curr += modFraction * height;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
else if (drawingMethylation) {
|
|
162
|
-
const { depth, nonmods, mods } = snpinfo;
|
|
163
|
-
let curr = 0;
|
|
164
|
-
for (const base of Object.keys(mods).sort().reverse()) {
|
|
165
|
-
const { entryDepth } = mods[base];
|
|
166
|
-
const height = toHeight(score0);
|
|
167
|
-
const bottom = toY(score0) + height;
|
|
168
|
-
ctx.fillStyle = colorForBase[base] || 'black';
|
|
169
|
-
ctx.fillRect(Math.round(leftPx), bottom - ((entryDepth + curr) / depth) * height, w, (entryDepth / depth) * height);
|
|
170
|
-
curr += entryDepth;
|
|
171
|
-
}
|
|
172
|
-
for (const base of Object.keys(nonmods).sort().reverse()) {
|
|
173
|
-
const { entryDepth } = nonmods[base];
|
|
174
|
-
const height = toHeight(score0);
|
|
175
|
-
const bottom = toY(score0) + height;
|
|
176
|
-
ctx.fillStyle = colorForBase[base] || 'black';
|
|
177
|
-
ctx.fillRect(Math.round(leftPx), bottom - ((entryDepth + curr) / depth) * height, w, (entryDepth / depth) * height);
|
|
178
|
-
curr += entryDepth;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
const { depth, snps } = snpinfo;
|
|
183
|
-
let curr = 0;
|
|
184
|
-
for (const base of Object.keys(snps).sort().reverse()) {
|
|
185
|
-
const { entryDepth } = snps[base];
|
|
186
|
-
const height = toHeight(score0);
|
|
187
|
-
const bottom = toY(score0) + height;
|
|
188
|
-
ctx.fillStyle = colorForBase[base] || 'black';
|
|
189
|
-
ctx.fillRect(Math.round(leftPx), bottom - ((entryDepth + curr) / depth) * height, w, (entryDepth / depth) * height);
|
|
190
|
-
curr += entryDepth;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
const interbaseEvents = Object.keys(snpinfo.noncov);
|
|
194
|
-
if (drawInterbaseCounts) {
|
|
195
|
-
let curr = 0;
|
|
196
|
-
for (const base of interbaseEvents) {
|
|
197
|
-
const { entryDepth } = snpinfo.noncov[base];
|
|
198
|
-
const r = 0.6;
|
|
199
|
-
ctx.fillStyle = colorForBase[base];
|
|
200
|
-
ctx.fillRect(leftPx - r + extraHorizontallyFlippedOffset, INTERBASE_INDICATOR_HEIGHT + toHeight2(curr), r * 2, toHeight2(entryDepth));
|
|
201
|
-
curr += entryDepth;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
if (drawIndicators) {
|
|
205
|
-
let accum = 0;
|
|
206
|
-
let max = 0;
|
|
207
|
-
let maxBase = '';
|
|
208
|
-
for (const base of interbaseEvents) {
|
|
209
|
-
const { entryDepth } = snpinfo.noncov[base];
|
|
210
|
-
accum += entryDepth;
|
|
211
|
-
if (entryDepth > max) {
|
|
212
|
-
max = entryDepth;
|
|
213
|
-
maxBase = base;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
const indicatorComparatorScore = Math.max(score0, prevTotal);
|
|
217
|
-
if (accum > indicatorComparatorScore * indicatorThreshold &&
|
|
218
|
-
indicatorComparatorScore > MINIMUM_INTERBASE_INDICATOR_READ_DEPTH) {
|
|
219
|
-
ctx.fillStyle = colorForBase[maxBase];
|
|
220
|
-
ctx.beginPath();
|
|
221
|
-
const l = leftPx + extraHorizontallyFlippedOffset;
|
|
222
|
-
ctx.moveTo(l - INTERBASE_INDICATOR_WIDTH / 2, 0);
|
|
223
|
-
ctx.lineTo(l + INTERBASE_INDICATOR_WIDTH / 2, 0);
|
|
224
|
-
ctx.lineTo(l, INTERBASE_INDICATOR_HEIGHT);
|
|
225
|
-
ctx.fill();
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
prevTotal = score0;
|
|
229
|
-
}
|
|
230
|
-
if (drawArcs) {
|
|
231
|
-
for (const f of feats) {
|
|
232
|
-
if (f.get('type') !== 'skip') {
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
const s = f.get('start');
|
|
236
|
-
const e = f.get('end');
|
|
237
|
-
const [left, right] = bpSpanPx(s, e, region, bpPerPx);
|
|
238
|
-
ctx.beginPath();
|
|
239
|
-
const effectiveStrand = f.get('effectiveStrand');
|
|
240
|
-
const pos = 'rgba(255,200,200,0.7)';
|
|
241
|
-
const neg = 'rgba(200,200,255,0.7)';
|
|
242
|
-
const neutral = 'rgba(200,200,200,0.7)';
|
|
243
|
-
if (effectiveStrand === 1) {
|
|
244
|
-
ctx.strokeStyle = pos;
|
|
245
|
-
}
|
|
246
|
-
else if (effectiveStrand === -1) {
|
|
247
|
-
ctx.strokeStyle = neg;
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
ctx.strokeStyle = neutral;
|
|
251
|
-
}
|
|
252
|
-
ctx.lineWidth = Math.log(f.get('score') + 1);
|
|
253
|
-
ctx.moveTo(left, height - offset * 2);
|
|
254
|
-
ctx.bezierCurveTo(left, 0, right, 0, right, height - offset * 2);
|
|
255
|
-
ctx.stroke();
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
if (displayCrossHatches) {
|
|
259
|
-
ctx.lineWidth = 1;
|
|
260
|
-
ctx.strokeStyle = 'rgba(140,140,140,0.8)';
|
|
261
|
-
for (const tick of ticks.values) {
|
|
262
|
-
ctx.beginPath();
|
|
263
|
-
ctx.moveTo(0, Math.round(toY(tick)));
|
|
264
|
-
ctx.lineTo(width, Math.round(toY(tick)));
|
|
265
|
-
ctx.stroke();
|
|
266
|
-
}
|
|
267
|
-
}
|
|
4
|
+
const { makeImage } = await import('./makeImage');
|
|
5
|
+
await makeImage(ctx, props);
|
|
268
6
|
return undefined;
|
|
269
7
|
}
|
|
270
8
|
}
|
|
@@ -9,17 +9,17 @@ declare const SNPCoverageRenderer: import("@jbrowse/core/configuration/configura
|
|
|
9
9
|
description: string;
|
|
10
10
|
defaultValue: number;
|
|
11
11
|
};
|
|
12
|
-
|
|
12
|
+
showArcs: {
|
|
13
13
|
type: string;
|
|
14
14
|
description: string;
|
|
15
15
|
defaultValue: boolean;
|
|
16
16
|
};
|
|
17
|
-
|
|
17
|
+
showInterbaseCounts: {
|
|
18
18
|
type: string;
|
|
19
19
|
description: string;
|
|
20
20
|
defaultValue: boolean;
|
|
21
21
|
};
|
|
22
|
-
|
|
22
|
+
showInterbaseIndicators: {
|
|
23
23
|
type: string;
|
|
24
24
|
description: string;
|
|
25
25
|
defaultValue: boolean;
|
|
@@ -11,17 +11,17 @@ const SNPCoverageRenderer = ConfigurationSchema('SNPCoverageRenderer', {
|
|
|
11
11
|
description: 'the proportion of reads containing a insertion/clip indicator',
|
|
12
12
|
defaultValue: 0.4,
|
|
13
13
|
},
|
|
14
|
-
|
|
14
|
+
showArcs: {
|
|
15
15
|
type: 'boolean',
|
|
16
16
|
description: 'Draw sashimi-style arcs for intron features',
|
|
17
17
|
defaultValue: true,
|
|
18
18
|
},
|
|
19
|
-
|
|
19
|
+
showInterbaseCounts: {
|
|
20
20
|
type: 'boolean',
|
|
21
21
|
description: 'draw count "upsidedown histogram" of the interbase events that don\'t contribute to the coverage count so are not drawn in the normal histogram',
|
|
22
22
|
defaultValue: true,
|
|
23
23
|
},
|
|
24
|
-
|
|
24
|
+
showInterbaseIndicators: {
|
|
25
25
|
type: 'boolean',
|
|
26
26
|
description: 'draw a triangular indicator where an event has been detected',
|
|
27
27
|
defaultValue: true,
|