@jbrowse/plugin-alignments 2.6.2 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.d.ts +2 -2
- package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +2 -1
- package/dist/AlignmentsFeatureDetail/util.d.ts +1 -3
- package/dist/BamAdapter/BamAdapter.d.ts +2 -9
- package/dist/CramAdapter/CramAdapter.d.ts +3 -11
- package/dist/CramAdapter/CramAdapter.js +2 -1
- package/dist/CramAdapter/util.js +3 -6
- package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +3 -4
- package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.js +3 -3
- package/dist/LinearAlignmentsDisplay/models/model.d.ts +5 -9
- package/dist/LinearAlignmentsDisplay/models/model.js +1 -0
- package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +514 -0
- package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +547 -0
- package/dist/LinearPileupDisplay/components/ColorByModifications.d.ts +4 -5
- package/dist/LinearPileupDisplay/components/ColorByModifications.js +3 -4
- package/dist/LinearPileupDisplay/components/ColorByTag.d.ts +7 -5
- package/dist/LinearPileupDisplay/components/ColorByTag.js +4 -7
- package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.d.ts +3 -4
- package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +2 -2
- package/dist/LinearPileupDisplay/components/SetFeatureHeight.d.ts +4 -5
- package/dist/LinearPileupDisplay/components/SetFeatureHeight.js +3 -3
- package/dist/LinearPileupDisplay/components/SetMaxHeight.d.ts +3 -4
- package/dist/LinearPileupDisplay/components/SetMaxHeight.js +3 -3
- package/dist/LinearPileupDisplay/components/SortByTag.d.ts +3 -4
- package/dist/LinearPileupDisplay/components/SortByTag.js +3 -3
- package/dist/LinearPileupDisplay/index.d.ts +1 -0
- package/dist/LinearPileupDisplay/index.js +3 -1
- package/dist/LinearPileupDisplay/model.d.ts +142 -234
- package/dist/LinearPileupDisplay/model.js +50 -446
- package/dist/LinearReadArcsDisplay/components/ReactComponent.d.ts +2 -2
- package/dist/LinearReadArcsDisplay/components/ReactComponent.js +2 -1
- package/dist/LinearReadArcsDisplay/model.d.ts +9 -14
- package/dist/LinearReadCloudDisplay/components/ReactComponent.d.ts +2 -2
- package/dist/LinearReadCloudDisplay/components/ReactComponent.js +2 -1
- package/dist/LinearReadCloudDisplay/drawPairChains.js +1 -2
- package/dist/LinearReadCloudDisplay/model.d.ts +13 -15
- package/dist/LinearSNPCoverageDisplay/components/Tooltip.js +1 -1
- package/dist/LinearSNPCoverageDisplay/models/model.d.ts +18 -423
- package/dist/LinearSNPCoverageDisplay/models/model.js +18 -0
- package/dist/MismatchParser/index.js +6 -8
- package/dist/PileupRenderer/PileupRenderer.js +0 -25
- package/dist/PileupRenderer/colorBy.js +1 -1
- package/dist/PileupRenderer/components/PileupRendering.d.ts +9 -10
- package/dist/PileupRenderer/components/PileupRendering.js +3 -5
- package/dist/PileupRenderer/getAlignmentShapeColor.js +1 -1
- package/dist/PileupRenderer/layoutFeature.js +1 -2
- package/dist/PileupRenderer/makeImageData.d.ts +1 -3
- package/dist/PileupRenderer/renderMethylation.js +5 -10
- package/dist/PileupRenderer/renderMismatches.d.ts +2 -6
- package/dist/PileupRenderer/renderMismatches.js +8 -11
- package/dist/PileupRenderer/renderModifications.js +4 -8
- package/dist/PileupRenderer/renderSoftClipping.js +26 -25
- package/dist/PileupRenderer/sortUtil.js +2 -2
- package/dist/SNPCoverageAdapter/util.d.ts +9 -13
- package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js +6 -12
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/shared/BaseDisplayComponent.d.ts +2 -2
- package/dist/shared/BaseDisplayComponent.js +2 -1
- package/dist/shared/FilterByTag.d.ts +6 -15
- package/dist/shared/FilterByTag.js +4 -6
- package/dist/shared/color.d.ts +10 -0
- package/dist/shared/color.js +7 -1
- package/dist/shared/fetchChains.js +1 -0
- package/dist/shared/index.d.ts +9 -0
- package/dist/util.d.ts +3 -9
- package/esm/AlignmentsFeatureDetail/AlignmentsFeatureDetail.d.ts +2 -2
- package/esm/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +2 -1
- package/esm/AlignmentsFeatureDetail/util.d.ts +1 -3
- package/esm/BamAdapter/BamAdapter.d.ts +2 -9
- package/esm/CramAdapter/CramAdapter.d.ts +3 -11
- package/esm/CramAdapter/CramAdapter.js +2 -1
- package/esm/CramAdapter/util.js +3 -6
- package/esm/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +3 -4
- package/esm/LinearAlignmentsDisplay/components/AlignmentsDisplay.js +3 -3
- package/esm/LinearAlignmentsDisplay/models/model.d.ts +5 -9
- package/esm/LinearAlignmentsDisplay/models/model.js +1 -0
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +514 -0
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +517 -0
- package/esm/LinearPileupDisplay/components/ColorByModifications.d.ts +4 -5
- package/esm/LinearPileupDisplay/components/ColorByModifications.js +3 -4
- package/esm/LinearPileupDisplay/components/ColorByTag.d.ts +7 -5
- package/esm/LinearPileupDisplay/components/ColorByTag.js +4 -7
- package/esm/LinearPileupDisplay/components/LinearPileupDisplayBlurb.d.ts +3 -4
- package/esm/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +2 -2
- package/esm/LinearPileupDisplay/components/SetFeatureHeight.d.ts +4 -5
- package/esm/LinearPileupDisplay/components/SetFeatureHeight.js +3 -3
- package/esm/LinearPileupDisplay/components/SetMaxHeight.d.ts +3 -4
- package/esm/LinearPileupDisplay/components/SetMaxHeight.js +3 -3
- package/esm/LinearPileupDisplay/components/SortByTag.d.ts +3 -4
- package/esm/LinearPileupDisplay/components/SortByTag.js +3 -3
- package/esm/LinearPileupDisplay/index.d.ts +1 -0
- package/esm/LinearPileupDisplay/index.js +1 -0
- package/esm/LinearPileupDisplay/model.d.ts +142 -234
- package/esm/LinearPileupDisplay/model.js +51 -447
- package/esm/LinearReadArcsDisplay/components/ReactComponent.d.ts +2 -2
- package/esm/LinearReadArcsDisplay/components/ReactComponent.js +2 -1
- package/esm/LinearReadArcsDisplay/model.d.ts +9 -14
- package/esm/LinearReadCloudDisplay/components/ReactComponent.d.ts +2 -2
- package/esm/LinearReadCloudDisplay/components/ReactComponent.js +2 -1
- package/esm/LinearReadCloudDisplay/drawPairChains.js +1 -2
- package/esm/LinearReadCloudDisplay/model.d.ts +13 -15
- package/esm/LinearSNPCoverageDisplay/components/Tooltip.js +1 -1
- package/esm/LinearSNPCoverageDisplay/models/model.d.ts +18 -423
- package/esm/LinearSNPCoverageDisplay/models/model.js +18 -0
- package/esm/MismatchParser/index.js +6 -8
- package/esm/PileupRenderer/PileupRenderer.js +0 -2
- package/esm/PileupRenderer/colorBy.js +1 -1
- package/esm/PileupRenderer/components/PileupRendering.d.ts +9 -10
- package/esm/PileupRenderer/components/PileupRendering.js +3 -5
- package/esm/PileupRenderer/getAlignmentShapeColor.js +1 -1
- package/esm/PileupRenderer/layoutFeature.js +1 -2
- package/esm/PileupRenderer/makeImageData.d.ts +1 -3
- package/esm/PileupRenderer/renderMethylation.js +5 -10
- package/esm/PileupRenderer/renderMismatches.d.ts +2 -6
- package/esm/PileupRenderer/renderMismatches.js +8 -11
- package/esm/PileupRenderer/renderModifications.js +4 -8
- package/esm/PileupRenderer/renderSoftClipping.js +26 -25
- package/esm/PileupRenderer/sortUtil.js +2 -2
- package/esm/SNPCoverageAdapter/util.d.ts +9 -13
- package/esm/SNPCoverageRenderer/SNPCoverageRenderer.js +6 -12
- package/esm/index.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/shared/BaseDisplayComponent.d.ts +2 -2
- package/esm/shared/BaseDisplayComponent.js +3 -2
- package/esm/shared/FilterByTag.d.ts +6 -15
- package/esm/shared/FilterByTag.js +4 -6
- package/esm/shared/color.d.ts +10 -0
- package/esm/shared/color.js +6 -0
- package/esm/shared/fetchChains.js +1 -0
- package/esm/shared/index.d.ts +9 -0
- package/esm/util.d.ts +3 -9
- package/package.json +3 -4
|
@@ -3,6 +3,7 @@ import { observable } from 'mobx';
|
|
|
3
3
|
import { getConf, readConfObject, } from '@jbrowse/core/configuration';
|
|
4
4
|
import { linearWiggleDisplayModelFactory } from '@jbrowse/plugin-wiggle';
|
|
5
5
|
import { getContainingView } from '@jbrowse/core/util';
|
|
6
|
+
import SerializableFilterChain from '@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain';
|
|
6
7
|
// locals
|
|
7
8
|
import Tooltip from '../components/Tooltip';
|
|
8
9
|
import { FilterModel, getUniqueModificationValues } from '../../shared';
|
|
@@ -44,6 +45,10 @@ function stateModelFactory(pluginManager, configSchema) {
|
|
|
44
45
|
type: types.string,
|
|
45
46
|
tag: types.maybe(types.string),
|
|
46
47
|
})),
|
|
48
|
+
/**
|
|
49
|
+
* #property
|
|
50
|
+
*/
|
|
51
|
+
jexlFilters: types.optional(types.array(types.string), []),
|
|
47
52
|
}))
|
|
48
53
|
.volatile(() => ({
|
|
49
54
|
modificationTagMap: observable.map({}),
|
|
@@ -68,6 +73,12 @@ function stateModelFactory(pluginManager, configSchema) {
|
|
|
68
73
|
setColorBy(colorBy) {
|
|
69
74
|
self.colorBy = cast(colorBy);
|
|
70
75
|
},
|
|
76
|
+
/**
|
|
77
|
+
* #action
|
|
78
|
+
*/
|
|
79
|
+
setJexlFilters(filters) {
|
|
80
|
+
self.jexlFilters = cast(filters);
|
|
81
|
+
},
|
|
71
82
|
/**
|
|
72
83
|
* #action
|
|
73
84
|
*/
|
|
@@ -142,6 +153,7 @@ function stateModelFactory(pluginManager, configSchema) {
|
|
|
142
153
|
return {
|
|
143
154
|
...superProps,
|
|
144
155
|
notReady: !this.ready,
|
|
156
|
+
filters: self.filters,
|
|
145
157
|
modificationTagMap: Object.fromEntries(modificationTagMap.toJSON()),
|
|
146
158
|
// must use getSnapshot because otherwise changes to e.g. just the
|
|
147
159
|
// colorBy.type are not read
|
|
@@ -264,6 +276,12 @@ function stateModelFactory(pluginManager, configSchema) {
|
|
|
264
276
|
},
|
|
265
277
|
];
|
|
266
278
|
},
|
|
279
|
+
/**
|
|
280
|
+
* #getter
|
|
281
|
+
*/
|
|
282
|
+
get filters() {
|
|
283
|
+
return new SerializableFilterChain({ filters: self.jexlFilters });
|
|
284
|
+
},
|
|
267
285
|
};
|
|
268
286
|
});
|
|
269
287
|
}
|
|
@@ -146,8 +146,7 @@ export function mdToMismatches(mdstring, ops, cigarMismatches, seq, qual) {
|
|
|
146
146
|
}
|
|
147
147
|
// now actually parse the MD string
|
|
148
148
|
const md = mdstring.match(mdRegex) || [];
|
|
149
|
-
for (
|
|
150
|
-
const token = md[i];
|
|
149
|
+
for (const token of md) {
|
|
151
150
|
const num = +token;
|
|
152
151
|
if (!Number.isNaN(num)) {
|
|
153
152
|
curr.start += num;
|
|
@@ -157,6 +156,7 @@ export function mdToMismatches(mdstring, ops, cigarMismatches, seq, qual) {
|
|
|
157
156
|
}
|
|
158
157
|
else {
|
|
159
158
|
// mismatch
|
|
159
|
+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
160
160
|
for (let j = 0; j < token.length; j += 1) {
|
|
161
161
|
curr.length = 1;
|
|
162
162
|
while (lastSkipPos < skips.length) {
|
|
@@ -264,8 +264,7 @@ export function getModificationPositions(mm, fseq, fstrand) {
|
|
|
264
264
|
const seq = fstrand === -1 ? revcom(fseq) : fseq;
|
|
265
265
|
const mods = mm.split(';').filter(mod => !!mod);
|
|
266
266
|
const result = [];
|
|
267
|
-
for (
|
|
268
|
-
const mod = mods[i];
|
|
267
|
+
for (const mod of mods) {
|
|
269
268
|
const [basemod, ...skips] = mod.split(',');
|
|
270
269
|
// regexes based on parse_mm.pl from hts-specs
|
|
271
270
|
const matches = basemod.match(modificationRegex);
|
|
@@ -285,12 +284,11 @@ export function getModificationPositions(mm, fseq, fstrand) {
|
|
|
285
284
|
// sequence of the read, if we have a modification type e.g. C+m;2 and a
|
|
286
285
|
// sequence ACGTACGTAC we skip the two instances of C and go to the last
|
|
287
286
|
// C
|
|
288
|
-
for (
|
|
289
|
-
const type = types[j];
|
|
287
|
+
for (const type of types) {
|
|
290
288
|
let i = 0;
|
|
291
289
|
const positions = [];
|
|
292
|
-
for (
|
|
293
|
-
let delta = +
|
|
290
|
+
for (const d of skips) {
|
|
291
|
+
let delta = +d;
|
|
294
292
|
do {
|
|
295
293
|
if (base === 'N' || base === seq[i]) {
|
|
296
294
|
delta--;
|
|
@@ -53,7 +53,6 @@ export default class PileupRenderer extends BoxRendererType {
|
|
|
53
53
|
: undefined;
|
|
54
54
|
const width = (region.end - region.start) / bpPerPx;
|
|
55
55
|
const height = Math.max(layout.getTotalHeight(), 1);
|
|
56
|
-
const Color = await import('color').then(f => f.default);
|
|
57
56
|
const res = await renderToAbstractCanvas(width, height, renderProps, ctx => makeImageData({
|
|
58
57
|
ctx,
|
|
59
58
|
layoutRecords: layoutRecords.filter(notEmpty),
|
|
@@ -63,7 +62,6 @@ export default class PileupRenderer extends BoxRendererType {
|
|
|
63
62
|
layout,
|
|
64
63
|
features,
|
|
65
64
|
regionSequence,
|
|
66
|
-
Color,
|
|
67
65
|
},
|
|
68
66
|
}));
|
|
69
67
|
const results = await super.render({
|
|
@@ -8,7 +8,7 @@ export function colorByInsertSize(feature) {
|
|
|
8
8
|
: `hsl(${Math.abs(feature.get('template_length')) / 10},50%,50%)`;
|
|
9
9
|
}
|
|
10
10
|
export function colorByMappingQuality(feature) {
|
|
11
|
-
return `hsl(${feature.get('
|
|
11
|
+
return `hsl(${feature.get('score')},50%,50%)`;
|
|
12
12
|
}
|
|
13
13
|
function getOrientation(feature, config) {
|
|
14
14
|
const orientationType = readConfObject(config, 'orientationType');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Region } from '@jbrowse/core/util/types';
|
|
3
3
|
import type { BaseLinearDisplayModel } from '@jbrowse/plugin-linear-genome-view';
|
|
4
|
-
declare
|
|
4
|
+
declare const PileupRendering: (props: {
|
|
5
5
|
blockKey: string;
|
|
6
6
|
displayModel: BaseLinearDisplayModel;
|
|
7
7
|
width: number;
|
|
@@ -12,17 +12,16 @@ declare function PileupRendering(props: {
|
|
|
12
12
|
type: string;
|
|
13
13
|
pos: number;
|
|
14
14
|
refName: string;
|
|
15
|
-
};
|
|
15
|
+
} | undefined;
|
|
16
16
|
colorBy?: {
|
|
17
17
|
type: string;
|
|
18
|
-
tag?: string;
|
|
19
|
-
};
|
|
18
|
+
tag?: string | undefined;
|
|
19
|
+
} | undefined;
|
|
20
20
|
filterBy?: {
|
|
21
21
|
tagFilter?: {
|
|
22
22
|
tag: string;
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
onMouseMove?: (event: React.MouseEvent, featureId?: string) => void;
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
export default _default;
|
|
23
|
+
} | undefined;
|
|
24
|
+
} | undefined;
|
|
25
|
+
onMouseMove?: ((event: React.MouseEvent, featureId?: string) => void) | undefined;
|
|
26
|
+
}) => React.JSX.Element;
|
|
27
|
+
export default PileupRendering;
|
|
@@ -5,7 +5,7 @@ import { observer } from 'mobx-react';
|
|
|
5
5
|
// used so that user can click-away-from-feature below the laid out features
|
|
6
6
|
// (issue #1248)
|
|
7
7
|
const canvasPadding = 100;
|
|
8
|
-
|
|
8
|
+
const PileupRendering = observer(function (props) {
|
|
9
9
|
var _a;
|
|
10
10
|
const { onMouseMove, blockKey, displayModel, width, height, regions, bpPerPx, sortedBy, colorBy, filterBy, } = props;
|
|
11
11
|
const { selectedFeatureId, featureIdUnderMouse, contextMenuFeature } = displayModel;
|
|
@@ -108,10 +108,8 @@ function PileupRendering(props) {
|
|
|
108
108
|
}
|
|
109
109
|
function callMouseHandler(handlerName, event) {
|
|
110
110
|
// @ts-expect-error
|
|
111
|
-
// eslint-disable-next-line react/destructuring-assignment
|
|
112
111
|
const featureHandler = props[`onFeature${handlerName}`];
|
|
113
112
|
// @ts-expect-error
|
|
114
|
-
// eslint-disable-next-line react/destructuring-assignment
|
|
115
113
|
const canvasHandler = props[`on${handlerName}`];
|
|
116
114
|
if (featureHandler && featureIdUnderMouse) {
|
|
117
115
|
featureHandler(event, featureIdUnderMouse);
|
|
@@ -132,5 +130,5 @@ function PileupRendering(props) {
|
|
|
132
130
|
.join('-')}`, style: { position: 'relative', width: canvasWidth, height } },
|
|
133
131
|
React.createElement(PrerenderedCanvas, { ...props, style: { position: 'absolute', left: 0, top: 0 } }),
|
|
134
132
|
React.createElement("canvas", { "data-testid": "pileup_overlay_canvas", width: canvasWidth, height: height + canvasPadding, style: { position: 'absolute', left: 0, top: 0 }, className: "highlightOverlayCanvas", ref: highlightOverlayCanvas, onMouseDown: event => onMouseDown(event), onMouseEnter: event => onMouseEnter(event), onMouseOut: event => onMouseOut(event), onMouseOver: event => onMouseOver(event), onMouseUp: event => onMouseUp(event), onMouseLeave: event => onMouseLeave(event), onMouseMove: event => mouseMove(event), onClick: event => onClick(event), onContextMenu: event => onContextMenu(event), onFocus: () => { }, onBlur: () => { } })));
|
|
135
|
-
}
|
|
136
|
-
export default
|
|
133
|
+
});
|
|
134
|
+
export default PileupRendering;
|
|
@@ -36,7 +36,7 @@ export function getAlignmentShapeColor({ colorType, tag, feature, config, defaul
|
|
|
36
36
|
}[val] || 'color_nostrand'];
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
|
-
return colorTagMap[val] || fillColor
|
|
39
|
+
return colorTagMap[val] || fillColor.color_nostrand;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
case 'insertSizeAndPairOrientation':
|
|
@@ -7,8 +7,7 @@ export function layoutFeature({ feature, layout, bpPerPx, region, showSoftClip,
|
|
|
7
7
|
const mismatches = feature.get('mismatches');
|
|
8
8
|
const seq = feature.get('seq');
|
|
9
9
|
if (seq) {
|
|
10
|
-
for (
|
|
11
|
-
const { type, start, cliplen = 0 } = mismatches[i];
|
|
10
|
+
for (const { type, start, cliplen = 0 } of mismatches) {
|
|
12
11
|
if (type === 'softclip') {
|
|
13
12
|
start === 0 ? (expansionBefore = cliplen) : (expansionAfter = cliplen);
|
|
14
13
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Feature } from '@jbrowse/core/util';
|
|
2
2
|
import { RenderArgsDeserializedWithFeaturesAndLayout } from './PileupRenderer';
|
|
3
|
-
export
|
|
4
|
-
Color: Awaited<typeof import('color')>;
|
|
5
|
-
}
|
|
3
|
+
export type RenderArgsWithColor = RenderArgsDeserializedWithFeaturesAndLayout;
|
|
6
4
|
interface LayoutFeature {
|
|
7
5
|
heightPx: number;
|
|
8
6
|
topPx: number;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { bpSpanPx } from '@jbrowse/core/util';
|
|
2
2
|
import { getMethBins } from '../MismatchParser';
|
|
3
3
|
import { fillRect } from './util';
|
|
4
|
+
import { colord } from '@jbrowse/core/util/colord';
|
|
4
5
|
// Color by methylation is slightly modified version of color by
|
|
5
6
|
// modifications that focuses on CpG sites, with non-methylated CpG colored
|
|
6
7
|
export function renderMethylation({ ctx, feat, region, bpPerPx, renderArgs, canvasWidth, }) {
|
|
7
8
|
var _a, _b;
|
|
8
|
-
const { regionSequence
|
|
9
|
+
const { regionSequence } = renderArgs;
|
|
9
10
|
const { feature, topPx, heightPx } = feat;
|
|
10
11
|
if (!regionSequence) {
|
|
11
12
|
throw new Error('region sequence required for methylation');
|
|
@@ -20,15 +21,9 @@ export function renderMethylation({ ctx, feat, region, bpPerPx, renderArgs, canv
|
|
|
20
21
|
function getCol(k) {
|
|
21
22
|
if (methBins[k]) {
|
|
22
23
|
const p = methProbs[k] || 0;
|
|
23
|
-
return p > 0.5
|
|
24
|
-
?
|
|
25
|
-
|
|
26
|
-
.hsl()
|
|
27
|
-
.string()
|
|
28
|
-
: Color('blue')
|
|
29
|
-
.alpha(1 - p * 2)
|
|
30
|
-
.hsl()
|
|
31
|
-
.string();
|
|
24
|
+
return (p > 0.5
|
|
25
|
+
? colord('red').alpha((p - 0.5) * 2)
|
|
26
|
+
: colord('blue').alpha(1 - p * 2)).toHslString();
|
|
32
27
|
}
|
|
33
28
|
return undefined;
|
|
34
29
|
}
|
|
@@ -4,12 +4,8 @@ export declare function renderMismatches({ ctx, feat, renderArgs, minSubfeatureW
|
|
|
4
4
|
ctx: CanvasRenderingContext2D;
|
|
5
5
|
feat: LayoutFeature;
|
|
6
6
|
renderArgs: RenderArgsWithColor;
|
|
7
|
-
colorForBase:
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
contrastForBase: {
|
|
11
|
-
[key: string]: string;
|
|
12
|
-
};
|
|
7
|
+
colorForBase: Record<string, string>;
|
|
8
|
+
contrastForBase: Record<string, string>;
|
|
13
9
|
mismatchAlpha?: boolean;
|
|
14
10
|
drawIndels?: boolean;
|
|
15
11
|
drawSNPsMuted?: boolean;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { bpSpanPx, measureText } from '@jbrowse/core/util';
|
|
2
2
|
import { fillRect } from './util';
|
|
3
|
+
import { colord } from '@jbrowse/core/util/colord';
|
|
3
4
|
export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, largeInsertionIndicatorScale, mismatchAlpha, charWidth, charHeight, colorForBase, contrastForBase, canvasWidth, drawSNPsMuted, drawIndels = true, }) {
|
|
4
|
-
const {
|
|
5
|
+
const { bpPerPx, regions } = renderArgs;
|
|
5
6
|
const { heightPx, topPx, feature } = feat;
|
|
6
7
|
const [region] = regions;
|
|
7
8
|
const start = feature.get('start');
|
|
@@ -16,8 +17,7 @@ export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, la
|
|
|
16
17
|
}
|
|
17
18
|
// two pass rendering: first pass, draw all the mismatches except wide
|
|
18
19
|
// insertion markers
|
|
19
|
-
for (
|
|
20
|
-
const mismatch = mismatches[i];
|
|
20
|
+
for (const mismatch of mismatches) {
|
|
21
21
|
const mstart = start + mismatch.start;
|
|
22
22
|
const mlen = mismatch.length;
|
|
23
23
|
const mbase = mismatch.base;
|
|
@@ -29,10 +29,9 @@ export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, la
|
|
|
29
29
|
const c = mismatchAlpha
|
|
30
30
|
? mismatch.qual === undefined
|
|
31
31
|
? baseColor
|
|
32
|
-
:
|
|
32
|
+
: colord(baseColor)
|
|
33
33
|
.alpha(Math.min(1, mismatch.qual / 50))
|
|
34
|
-
.
|
|
35
|
-
.string()
|
|
34
|
+
.toHslString()
|
|
36
35
|
: baseColor;
|
|
37
36
|
fillRect(ctx, Math.round(leftPx), topPx, widthPx, heightPx, canvasWidth, c);
|
|
38
37
|
}
|
|
@@ -44,10 +43,9 @@ export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, la
|
|
|
44
43
|
ctx.fillStyle = mismatchAlpha
|
|
45
44
|
? mismatch.qual === undefined
|
|
46
45
|
? contrastColor
|
|
47
|
-
:
|
|
46
|
+
: colord(contrastColor)
|
|
48
47
|
.alpha(Math.min(1, mismatch.qual / 50))
|
|
49
|
-
.
|
|
50
|
-
.string()
|
|
48
|
+
.toHslString()
|
|
51
49
|
: contrastColor;
|
|
52
50
|
ctx.fillText(mbase, leftPx + (widthPx - charWidth) / 2 + 1, topPx + heightPx);
|
|
53
51
|
}
|
|
@@ -102,8 +100,7 @@ export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, la
|
|
|
102
100
|
}
|
|
103
101
|
// second pass, draw wide insertion markers on top
|
|
104
102
|
if (drawIndels) {
|
|
105
|
-
for (
|
|
106
|
-
const mismatch = mismatches[i];
|
|
103
|
+
for (const mismatch of mismatches) {
|
|
107
104
|
const mstart = start + mismatch.start;
|
|
108
105
|
const mlen = mismatch.length;
|
|
109
106
|
const [leftPx] = bpSpanPx(mstart, mstart + mlen, region, bpPerPx);
|
|
@@ -2,6 +2,7 @@ import { bpSpanPx } from '@jbrowse/core/util';
|
|
|
2
2
|
import { getModificationPositions, getModificationProbabilities, getNextRefPos, parseCigar, } from '../MismatchParser';
|
|
3
3
|
import { getTagAlt } from '../util';
|
|
4
4
|
import { fillRect } from './util';
|
|
5
|
+
import { colord } from '@jbrowse/core/util/colord';
|
|
5
6
|
// render modifications stored in MM tag in BAM
|
|
6
7
|
//
|
|
7
8
|
// ML stores probabilities as array of numerics and MP is scaled phred scores
|
|
@@ -14,7 +15,7 @@ import { fillRect } from './util';
|
|
|
14
15
|
// about low qual calls <20 approx
|
|
15
16
|
export function renderModifications({ ctx, feat, region, bpPerPx, renderArgs, canvasWidth, }) {
|
|
16
17
|
const { feature, topPx, heightPx } = feat;
|
|
17
|
-
const {
|
|
18
|
+
const { modificationTagMap = {} } = renderArgs;
|
|
18
19
|
const seq = feature.get('seq');
|
|
19
20
|
if (!seq) {
|
|
20
21
|
return;
|
|
@@ -30,17 +31,12 @@ export function renderModifications({ ctx, feat, region, bpPerPx, renderArgs, ca
|
|
|
30
31
|
let probIndex = 0;
|
|
31
32
|
for (const { type, positions } of modifications) {
|
|
32
33
|
const col = modificationTagMap[type] || 'black';
|
|
33
|
-
const base =
|
|
34
|
+
const base = colord(col);
|
|
34
35
|
for (const readPos of getNextRefPos(cigarOps, positions)) {
|
|
35
36
|
const r = start + readPos;
|
|
36
37
|
const [leftPx, rightPx] = bpSpanPx(r, r + 1, region, bpPerPx);
|
|
37
38
|
const prob = (probabilities === null || probabilities === void 0 ? void 0 : probabilities[probIndex]) || 0;
|
|
38
|
-
const c = prob !== 1
|
|
39
|
-
? base
|
|
40
|
-
.alpha(prob + 0.1)
|
|
41
|
-
.hsl()
|
|
42
|
-
.string()
|
|
43
|
-
: col;
|
|
39
|
+
const c = prob !== 1 ? base.alpha(prob + 0.1).toHslString() : col;
|
|
44
40
|
const w = rightPx - leftPx + 0.5;
|
|
45
41
|
fillRect(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
|
|
46
42
|
probIndex++;
|
|
@@ -13,31 +13,32 @@ export function renderSoftClipping({ ctx, feat, renderArgs, config, theme, color
|
|
|
13
13
|
if (!(seq && mismatches)) {
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
16
|
+
const heightLim = charHeight - 2;
|
|
17
|
+
for (const mismatch of mismatches) {
|
|
18
|
+
if (mismatch.type === 'softclip') {
|
|
19
|
+
const len = mismatch.cliplen || 0;
|
|
20
|
+
const s = feature.get('start');
|
|
21
|
+
const start = mismatch.start === 0 ? s - len : s + mismatch.start;
|
|
22
|
+
for (let k = 0; k < len; k += 1) {
|
|
23
|
+
const base = seq.charAt(k + mismatch.start);
|
|
24
|
+
// If softclip length+start is longer than sequence, no need to
|
|
25
|
+
// continue showing base
|
|
26
|
+
if (!base) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const s0 = start + k;
|
|
30
|
+
const [leftPx, rightPx] = bpSpanPx(s0, s0 + 1, region, bpPerPx);
|
|
31
|
+
const widthPx = Math.max(minFeatWidth, rightPx - leftPx);
|
|
32
|
+
// Black accounts for IUPAC ambiguity code bases such as N that
|
|
33
|
+
// show in soft clipping
|
|
34
|
+
const baseColor = colorForBase[base] || '#000000';
|
|
35
|
+
ctx.fillStyle = baseColor;
|
|
36
|
+
fillRect(ctx, leftPx, topPx, widthPx, heightPx, canvasWidth);
|
|
37
|
+
if (widthPx >= charWidth && heightPx >= heightLim) {
|
|
38
|
+
ctx.fillStyle = theme.palette.getContrastText(baseColor);
|
|
39
|
+
ctx.fillText(base, leftPx + (widthPx - charWidth) / 2 + 1, topPx + heightPx);
|
|
40
|
+
}
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
|
-
}
|
|
43
|
+
}
|
|
43
44
|
}
|
|
@@ -56,8 +56,8 @@ export const sortFeature = (features, sortedBy) => {
|
|
|
56
56
|
featuresInCenterLine.sort((a, b) => {
|
|
57
57
|
const aMismatch = baseMap.get(a.id());
|
|
58
58
|
const bMismatch = baseMap.get(b.id());
|
|
59
|
-
const acode = bMismatch
|
|
60
|
-
const bcode = aMismatch
|
|
59
|
+
const acode = bMismatch === null || bMismatch === void 0 ? void 0 : bMismatch.base.toUpperCase();
|
|
60
|
+
const bcode = aMismatch === null || aMismatch === void 0 ? void 0 : aMismatch.base.toUpperCase();
|
|
61
61
|
if (acode === bcode && acode === '*') {
|
|
62
62
|
// @ts-expect-error
|
|
63
63
|
return aMismatch.length - bMismatch.length;
|
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
}
|
|
1
|
+
export type SkipMap = Record<string, {
|
|
2
|
+
score: number;
|
|
3
|
+
feature: unknown;
|
|
4
|
+
start: number;
|
|
5
|
+
end: number;
|
|
6
|
+
strand: number;
|
|
7
|
+
xs: string;
|
|
8
|
+
}>;
|
|
11
9
|
export interface BinType {
|
|
12
10
|
total?: number;
|
|
13
|
-
strands?:
|
|
14
|
-
[key: string]: number;
|
|
15
|
-
};
|
|
11
|
+
strands?: Record<string, number>;
|
|
16
12
|
}
|
|
17
13
|
export interface Bin {
|
|
18
14
|
refbase?: string;
|
|
@@ -59,8 +59,7 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
59
59
|
// Use two pass rendering, which helps in visualizing the SNPs at higher
|
|
60
60
|
// bpPerPx First pass: draw the gray background
|
|
61
61
|
ctx.fillStyle = colorForBase.total;
|
|
62
|
-
for (
|
|
63
|
-
const feature = coverage[i];
|
|
62
|
+
for (const feature of coverage) {
|
|
64
63
|
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
|
|
65
64
|
const w = rightPx - leftPx + fudgeFactor;
|
|
66
65
|
const score = feature.get('score');
|
|
@@ -78,8 +77,7 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
78
77
|
// Second pass: draw the SNP data, and add a minimum feature width of 1px
|
|
79
78
|
// which can be wider than the actual bpPerPx This reduces overdrawing of
|
|
80
79
|
// the grey background over the SNPs
|
|
81
|
-
for (
|
|
82
|
-
const feature = coverage[i];
|
|
80
|
+
for (const feature of coverage) {
|
|
83
81
|
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
|
|
84
82
|
const score = feature.get('score');
|
|
85
83
|
const snpinfo = feature.get('snpinfo');
|
|
@@ -87,8 +85,7 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
87
85
|
const totalScore = snpinfo.total;
|
|
88
86
|
const keys = Object.keys(snpinfo.cov).sort();
|
|
89
87
|
let curr = 0;
|
|
90
|
-
for (
|
|
91
|
-
const base = keys[i];
|
|
88
|
+
for (const base of keys) {
|
|
92
89
|
const { total } = snpinfo.cov[base];
|
|
93
90
|
ctx.fillStyle =
|
|
94
91
|
colorForBase[base] ||
|
|
@@ -103,8 +100,7 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
103
100
|
const indicatorHeight = 4.5;
|
|
104
101
|
if (drawInterbaseCounts) {
|
|
105
102
|
let curr = 0;
|
|
106
|
-
for (
|
|
107
|
-
const base = interbaseEvents[i];
|
|
103
|
+
for (const base of interbaseEvents) {
|
|
108
104
|
const { total } = snpinfo.noncov[base];
|
|
109
105
|
const r = 0.6;
|
|
110
106
|
ctx.fillStyle = colorForBase[base];
|
|
@@ -116,8 +112,7 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
116
112
|
let accum = 0;
|
|
117
113
|
let max = 0;
|
|
118
114
|
let maxBase = '';
|
|
119
|
-
for (
|
|
120
|
-
const base = interbaseEvents[i];
|
|
115
|
+
for (const base of interbaseEvents) {
|
|
121
116
|
const { total } = snpinfo.noncov[base];
|
|
122
117
|
accum += total;
|
|
123
118
|
if (total > max) {
|
|
@@ -142,8 +137,7 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
142
137
|
prevTotal = totalScore;
|
|
143
138
|
}
|
|
144
139
|
if (drawArcs) {
|
|
145
|
-
for (
|
|
146
|
-
const f = skips[i];
|
|
140
|
+
for (const f of skips) {
|
|
147
141
|
const [left, right] = bpSpanPx(f.get('start'), f.get('end'), region, bpPerPx);
|
|
148
142
|
ctx.beginPath();
|
|
149
143
|
const str = f.get('strand');
|
package/esm/index.d.ts
CHANGED
|
@@ -4,6 +4,6 @@ export default class AlignmentsPlugin extends Plugin {
|
|
|
4
4
|
name: string;
|
|
5
5
|
install(pluginManager: PluginManager): void;
|
|
6
6
|
}
|
|
7
|
-
export { linearPileupDisplayStateModelFactory, linearPileupDisplayConfigSchemaFactory, } from './LinearPileupDisplay';
|
|
7
|
+
export { linearPileupDisplayStateModelFactory, linearPileupDisplayConfigSchemaFactory, SharedLinearPileupDisplayMixin, } from './LinearPileupDisplay';
|
|
8
8
|
export { type LinearPileupDisplayModel } from './LinearPileupDisplay/model';
|
|
9
9
|
export * as MismatchParser from './MismatchParser';
|
package/esm/index.js
CHANGED
|
@@ -40,5 +40,5 @@ export default class AlignmentsPlugin extends Plugin {
|
|
|
40
40
|
].map(f => f(pluginManager));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
export { linearPileupDisplayStateModelFactory, linearPileupDisplayConfigSchemaFactory, } from './LinearPileupDisplay';
|
|
43
|
+
export { linearPileupDisplayStateModelFactory, linearPileupDisplayConfigSchemaFactory, SharedLinearPileupDisplayMixin, } from './LinearPileupDisplay';
|
|
44
44
|
export * as MismatchParser from './MismatchParser';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { LinearReadCloudDisplayModel } from '../LinearReadCloudDisplay/model';
|
|
3
3
|
import { LinearReadArcsDisplayModel } from '../LinearReadArcsDisplay/model';
|
|
4
|
-
declare const
|
|
4
|
+
declare const BaseDisplayComponent: ({ model, children, }: {
|
|
5
5
|
model: LinearReadArcsDisplayModel | LinearReadCloudDisplayModel;
|
|
6
6
|
children?: React.ReactNode;
|
|
7
7
|
}) => React.JSX.Element | null;
|
|
8
|
-
export default
|
|
8
|
+
export default BaseDisplayComponent;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { LoadingEllipses } from '@jbrowse/core/ui';
|
|
3
|
-
import { BlockMsg } from '@jbrowse/plugin-linear-genome-view';
|
|
3
|
+
import { BlockMsg, } from '@jbrowse/plugin-linear-genome-view';
|
|
4
4
|
import { makeStyles } from 'tss-react/mui';
|
|
5
5
|
import { observer } from 'mobx-react';
|
|
6
6
|
import { getContainingView } from '@jbrowse/core/util';
|
|
@@ -20,7 +20,7 @@ const useStyles = makeStyles()(theme => {
|
|
|
20
20
|
},
|
|
21
21
|
};
|
|
22
22
|
});
|
|
23
|
-
|
|
23
|
+
const BaseDisplayComponent = observer(function ({ model, children, }) {
|
|
24
24
|
const { error, regionTooLarge } = model;
|
|
25
25
|
return error ? (React.createElement(BlockMsg, { message: `${error}`, severity: "error", buttonText: "Reload", action: model.reload })) : regionTooLarge ? (model.regionCannotBeRendered()) : (React.createElement(DataDisplay, { model: model }, children));
|
|
26
26
|
});
|
|
@@ -41,3 +41,4 @@ const LoadingBar = observer(function ({ model, }) {
|
|
|
41
41
|
return (React.createElement("div", { className: classes.loading },
|
|
42
42
|
React.createElement(LoadingEllipses, { message: message })));
|
|
43
43
|
});
|
|
44
|
+
export default BaseDisplayComponent;
|
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
flagInclude: number;
|
|
5
|
-
readName?: string;
|
|
6
|
-
tagFilter?: {
|
|
7
|
-
tag: string;
|
|
8
|
-
value: string;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
declare function FilterByTagDlg(props: {
|
|
2
|
+
import { IFilter } from '.';
|
|
3
|
+
declare const FilterByTagDialog: (props: {
|
|
12
4
|
model: {
|
|
13
|
-
filterBy:
|
|
14
|
-
setFilterBy: (arg:
|
|
5
|
+
filterBy: IFilter;
|
|
6
|
+
setFilterBy: (arg: IFilter) => void;
|
|
15
7
|
};
|
|
16
8
|
handleClose: () => void;
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
export default _default;
|
|
9
|
+
}) => React.JSX.Element;
|
|
10
|
+
export default FilterByTagDialog;
|
|
@@ -45,7 +45,7 @@ function Bitmask(props) {
|
|
|
45
45
|
React.createElement("label", { htmlFor: key }, name)));
|
|
46
46
|
})));
|
|
47
47
|
}
|
|
48
|
-
function
|
|
48
|
+
const FilterByTagDialog = observer(function (props) {
|
|
49
49
|
var _a, _b;
|
|
50
50
|
const { model, handleClose } = props;
|
|
51
51
|
const { classes } = useStyles();
|
|
@@ -74,9 +74,7 @@ function FilterByTagDlg(props) {
|
|
|
74
74
|
React.createElement(Bitmask, { flag: flagExclude, setFlag: setFlagExclude })))),
|
|
75
75
|
React.createElement(Paper, { className: classes.paper, variant: "outlined" },
|
|
76
76
|
React.createElement(Typography, null, "Filter by tag name and value. Use * in the value field to get all reads containing any value for that tag. Example: filter tag name SA with value * to get all split/supplementary reads. Other examples include HP for haplotype, or RG for read group"),
|
|
77
|
-
React.createElement(TextField, { className: classes.field, value: tag, onChange: event => setTag(event.target.value), placeholder: "Enter tag name", inputProps: {
|
|
78
|
-
maxLength: 2,
|
|
79
|
-
}, error: tag.length === 2 && !validTag, helperText: tag.length === 2 && !validTag ? 'Not a valid tag' : '' }),
|
|
77
|
+
React.createElement(TextField, { className: classes.field, value: tag, onChange: event => setTag(event.target.value), placeholder: "Enter tag name", inputProps: { maxLength: 2 }, error: tag.length === 2 && !validTag, helperText: tag.length === 2 && !validTag ? 'Not a valid tag' : '' }),
|
|
80
78
|
React.createElement(TextField, { className: classes.field, value: tagValue, onChange: event => setTagValue(event.target.value), placeholder: "Enter tag value" })),
|
|
81
79
|
React.createElement(Paper, { className: classes.paper, variant: "outlined" },
|
|
82
80
|
React.createElement(Typography, null, "Filter by read name"),
|
|
@@ -97,5 +95,5 @@ function FilterByTagDlg(props) {
|
|
|
97
95
|
handleClose();
|
|
98
96
|
} }, "Submit"),
|
|
99
97
|
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => handleClose() }, "Cancel")))));
|
|
100
|
-
}
|
|
101
|
-
export default
|
|
98
|
+
});
|
|
99
|
+
export default FilterByTagDialog;
|