@jbrowse/plugin-alignments 2.13.1 → 2.15.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.js +5 -3
- package/dist/AlignmentsFeatureDetail/BreakendOptionDialog.js +12 -4
- package/dist/AlignmentsFeatureDetail/Formatter.js +6 -2
- package/dist/AlignmentsFeatureDetail/SuppAlignmentsLocStrings.js +4 -2
- package/dist/AlignmentsFeatureDetail/getSAFeatures.js +4 -4
- package/dist/AlignmentsFeatureDetail/launchBreakpointSplitView.js +2 -2
- package/dist/BamAdapter/BamAdapter.js +12 -18
- package/dist/BamAdapter/BamSlightlyLazyFeature.js +0 -1
- package/dist/CramAdapter/CramAdapter.d.ts +1 -1
- package/dist/CramAdapter/CramAdapter.js +7 -6
- package/dist/CramAdapter/CramTestAdapters.js +8 -2
- package/dist/GuessAlignmentsTypes/index.js +2 -2
- package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +2 -2
- package/dist/LinearAlignmentsDisplay/models/model.d.ts +13 -20
- package/dist/LinearAlignmentsDisplay/models/model.js +13 -3
- package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +9 -4
- package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +41 -22
- package/dist/LinearPileupDisplay/components/{ColorByModifications.js → ColorByModificationsDialog.js} +3 -1
- package/dist/LinearPileupDisplay/components/{ColorByTag.js → ColorByTagDialog.js} +4 -2
- package/dist/LinearPileupDisplay/components/GroupByDialog.d.ts +11 -0
- package/dist/LinearPileupDisplay/components/GroupByDialog.js +129 -0
- package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +1 -3
- package/dist/LinearPileupDisplay/components/{SetFeatureHeight.js → SetFeatureHeightDialog.js} +9 -3
- package/{esm/LinearPileupDisplay/components/SetMaxHeight.d.ts → dist/LinearPileupDisplay/components/SetMaxHeightDialog.d.ts} +1 -1
- package/dist/LinearPileupDisplay/components/{SetMaxHeight.js → SetMaxHeightDialog.js} +7 -3
- package/dist/LinearPileupDisplay/components/{SortByTag.d.ts → SortByTagDialog.d.ts} +1 -1
- package/dist/LinearPileupDisplay/components/{SortByTag.js → SortByTagDialog.js} +7 -3
- package/dist/LinearPileupDisplay/configSchema.js +0 -1
- package/dist/LinearPileupDisplay/model.d.ts +58 -46
- package/dist/LinearPileupDisplay/model.js +69 -41
- package/dist/LinearReadArcsDisplay/components/ReactComponent.js +1 -0
- package/dist/LinearReadArcsDisplay/model.d.ts +2 -2
- package/dist/LinearReadArcsDisplay/model.js +37 -13
- package/dist/LinearReadCloudDisplay/components/ReactComponent.js +4 -1
- package/dist/LinearReadCloudDisplay/drawPairChains.js +3 -3
- package/dist/LinearReadCloudDisplay/model.d.ts +4 -8
- package/dist/LinearReadCloudDisplay/model.js +16 -6
- package/dist/LinearSNPCoverageDisplay/components/Tooltip.d.ts +1 -1
- package/dist/LinearSNPCoverageDisplay/components/Tooltip.js +1 -1
- package/dist/LinearSNPCoverageDisplay/models/model.d.ts +1 -1
- package/dist/LinearSNPCoverageDisplay/models/model.js +15 -5
- package/dist/MismatchParser/index.js +12 -10
- package/dist/PileupRPC/base.d.ts +1 -1
- package/dist/PileupRPC/methods/GetGlobalValueForTag.d.ts +1 -1
- package/dist/PileupRPC/methods/GetReducedFeatures.d.ts +3 -3
- package/dist/PileupRPC/methods/GetVisibleModifications.d.ts +1 -1
- package/dist/PileupRenderer/PileupLayoutSession.d.ts +1 -1
- package/dist/PileupRenderer/PileupLayoutSession.js +3 -2
- package/dist/PileupRenderer/PileupRenderer.d.ts +1 -1
- package/dist/PileupRenderer/PileupRenderer.js +16 -13
- package/dist/PileupRenderer/colorBy.js +3 -5
- package/dist/PileupRenderer/components/PileupRendering.d.ts +1 -1
- package/dist/PileupRenderer/components/PileupRendering.js +65 -60
- package/dist/PileupRenderer/getAlignmentShapeColor.js +24 -16
- package/dist/PileupRenderer/layoutFeature.js +6 -1
- package/dist/PileupRenderer/layoutFeatures.js +1 -7
- package/dist/PileupRenderer/makeImageData.d.ts +1 -1
- package/dist/PileupRenderer/makeImageData.js +1 -0
- package/dist/PileupRenderer/renderAlignmentShape.js +1 -1
- package/dist/PileupRenderer/renderMismatches.js +1 -1
- package/dist/PileupRenderer/renderSoftClipping.js +1 -1
- package/dist/PileupRenderer/util.js +3 -5
- package/dist/SNPCoverageAdapter/generateCoverageBins.js +4 -10
- package/dist/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +2 -2
- package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js +2 -5
- package/dist/index.js +3 -1
- package/dist/shared/BaseDisplayComponent.js +3 -1
- package/dist/shared/{FilterByTag.js → FilterByTagDialog.js} +16 -6
- package/dist/shared/color.js +2 -2
- package/dist/shared/index.d.ts +24 -20
- package/dist/shared/index.js +4 -5
- package/dist/shared/renderSvg.js +1 -3
- package/dist/util.d.ts +1 -1
- package/esm/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +5 -3
- package/esm/AlignmentsFeatureDetail/BreakendOptionDialog.js +12 -4
- package/esm/AlignmentsFeatureDetail/Formatter.js +6 -2
- package/esm/AlignmentsFeatureDetail/SuppAlignmentsLocStrings.js +4 -2
- package/esm/AlignmentsFeatureDetail/getSAFeatures.js +4 -4
- package/esm/AlignmentsFeatureDetail/launchBreakpointSplitView.js +2 -2
- package/esm/BamAdapter/BamAdapter.js +12 -18
- package/esm/BamAdapter/BamSlightlyLazyFeature.js +0 -1
- package/esm/CramAdapter/CramAdapter.d.ts +1 -1
- package/esm/CramAdapter/CramAdapter.js +7 -6
- package/esm/CramAdapter/CramTestAdapters.js +8 -2
- package/esm/GuessAlignmentsTypes/index.js +2 -2
- package/esm/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +2 -2
- package/esm/LinearAlignmentsDisplay/models/model.d.ts +13 -20
- package/esm/LinearAlignmentsDisplay/models/model.js +13 -3
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +9 -4
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +42 -23
- package/esm/LinearPileupDisplay/components/{ColorByModifications.js → ColorByModificationsDialog.js} +3 -1
- package/esm/LinearPileupDisplay/components/{ColorByTag.js → ColorByTagDialog.js} +4 -2
- package/esm/LinearPileupDisplay/components/GroupByDialog.d.ts +11 -0
- package/esm/LinearPileupDisplay/components/GroupByDialog.js +104 -0
- package/esm/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +1 -3
- package/esm/LinearPileupDisplay/components/{SetFeatureHeight.js → SetFeatureHeightDialog.js} +9 -3
- package/{dist/LinearPileupDisplay/components/SetMaxHeight.d.ts → esm/LinearPileupDisplay/components/SetMaxHeightDialog.d.ts} +1 -1
- package/esm/LinearPileupDisplay/components/{SetMaxHeight.js → SetMaxHeightDialog.js} +7 -3
- package/esm/LinearPileupDisplay/components/{SortByTag.d.ts → SortByTagDialog.d.ts} +1 -1
- package/esm/LinearPileupDisplay/components/{SortByTag.js → SortByTagDialog.js} +7 -3
- package/esm/LinearPileupDisplay/configSchema.js +0 -1
- package/esm/LinearPileupDisplay/model.d.ts +58 -46
- package/esm/LinearPileupDisplay/model.js +69 -41
- package/esm/LinearReadArcsDisplay/components/ReactComponent.js +1 -0
- package/esm/LinearReadArcsDisplay/model.d.ts +2 -2
- package/esm/LinearReadArcsDisplay/model.js +37 -13
- package/esm/LinearReadCloudDisplay/components/ReactComponent.js +4 -1
- package/esm/LinearReadCloudDisplay/drawPairChains.js +3 -3
- package/esm/LinearReadCloudDisplay/model.d.ts +4 -8
- package/esm/LinearReadCloudDisplay/model.js +16 -6
- package/esm/LinearSNPCoverageDisplay/components/Tooltip.d.ts +1 -1
- package/esm/LinearSNPCoverageDisplay/components/Tooltip.js +1 -1
- package/esm/LinearSNPCoverageDisplay/models/model.d.ts +1 -1
- package/esm/LinearSNPCoverageDisplay/models/model.js +15 -5
- package/esm/MismatchParser/index.js +12 -10
- package/esm/PileupRPC/base.d.ts +1 -1
- package/esm/PileupRPC/methods/GetGlobalValueForTag.d.ts +1 -1
- package/esm/PileupRPC/methods/GetReducedFeatures.d.ts +3 -3
- package/esm/PileupRPC/methods/GetVisibleModifications.d.ts +1 -1
- package/esm/PileupRenderer/PileupLayoutSession.d.ts +1 -1
- package/esm/PileupRenderer/PileupLayoutSession.js +3 -2
- package/esm/PileupRenderer/PileupRenderer.d.ts +1 -1
- package/esm/PileupRenderer/PileupRenderer.js +16 -13
- package/esm/PileupRenderer/colorBy.js +3 -5
- package/esm/PileupRenderer/components/PileupRendering.d.ts +1 -1
- package/esm/PileupRenderer/components/PileupRendering.js +65 -60
- package/esm/PileupRenderer/getAlignmentShapeColor.js +24 -16
- package/esm/PileupRenderer/layoutFeature.js +6 -1
- package/esm/PileupRenderer/layoutFeatures.js +1 -7
- package/esm/PileupRenderer/makeImageData.d.ts +1 -1
- package/esm/PileupRenderer/makeImageData.js +1 -0
- package/esm/PileupRenderer/renderAlignmentShape.js +1 -1
- package/esm/PileupRenderer/renderMismatches.js +1 -1
- package/esm/PileupRenderer/renderSoftClipping.js +1 -1
- package/esm/PileupRenderer/util.js +3 -5
- package/esm/SNPCoverageAdapter/generateCoverageBins.js +4 -10
- package/esm/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +2 -2
- package/esm/SNPCoverageRenderer/SNPCoverageRenderer.js +2 -5
- package/esm/index.js +3 -1
- package/esm/shared/BaseDisplayComponent.js +3 -1
- package/esm/shared/{FilterByTag.js → FilterByTagDialog.js} +16 -6
- package/esm/shared/color.js +2 -2
- package/esm/shared/index.d.ts +24 -20
- package/esm/shared/index.js +4 -5
- package/esm/shared/renderSvg.js +1 -3
- package/esm/util.d.ts +1 -1
- package/package.json +6 -6
- /package/dist/LinearPileupDisplay/components/{ColorByModifications.d.ts → ColorByModificationsDialog.d.ts} +0 -0
- /package/dist/LinearPileupDisplay/components/{ColorByTag.d.ts → ColorByTagDialog.d.ts} +0 -0
- /package/dist/LinearPileupDisplay/components/{SetFeatureHeight.d.ts → SetFeatureHeightDialog.d.ts} +0 -0
- /package/dist/shared/{FilterByTag.d.ts → FilterByTagDialog.d.ts} +0 -0
- /package/esm/LinearPileupDisplay/components/{ColorByModifications.d.ts → ColorByModificationsDialog.d.ts} +0 -0
- /package/esm/LinearPileupDisplay/components/{ColorByTag.d.ts → ColorByTagDialog.d.ts} +0 -0
- /package/esm/LinearPileupDisplay/components/{SetFeatureHeight.d.ts → SetFeatureHeightDialog.d.ts} +0 -0
- /package/esm/shared/{FilterByTag.d.ts → FilterByTagDialog.d.ts} +0 -0
|
@@ -2,65 +2,39 @@ import React, { useRef, useState, useEffect } from 'react';
|
|
|
2
2
|
import { PrerenderedCanvas } from '@jbrowse/core/ui';
|
|
3
3
|
import { bpSpanPx } from '@jbrowse/core/util';
|
|
4
4
|
import { observer } from 'mobx-react';
|
|
5
|
-
// used so that user can click-away-from-feature below the laid out features
|
|
6
|
-
// (issue #1248)
|
|
7
|
-
const canvasPadding = 100;
|
|
8
5
|
const PileupRendering = observer(function (props) {
|
|
9
6
|
var _a;
|
|
10
7
|
const { onMouseMove, blockKey, displayModel, width, height, regions, bpPerPx, sortedBy, colorBy, filterBy, } = props;
|
|
11
|
-
const { selectedFeatureId, featureIdUnderMouse, contextMenuFeature } = displayModel;
|
|
12
|
-
const [
|
|
13
|
-
|
|
8
|
+
const { selectedFeatureId, featureIdUnderMouse, contextMenuFeature } = displayModel || {};
|
|
9
|
+
const [firstRender, setFirstRender] = useState(false);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
setFirstRender(true);
|
|
12
|
+
}, []);
|
|
13
|
+
const region = regions[0];
|
|
14
|
+
const ref = useRef(null);
|
|
14
15
|
const [mouseIsDown, setMouseIsDown] = useState(false);
|
|
15
16
|
const [movedDuringLastMouseDown, setMovedDuringLastMouseDown] = useState(false);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
ctx.lineJoin = 'bevel';
|
|
38
|
-
ctx.lineWidth = 2;
|
|
39
|
-
ctx.strokeStyle = '#00b8ff';
|
|
40
|
-
ctx.strokeRect(leftPx - 2, rectTop - 2, rightPx - leftPx + 4, rectHeight + 4);
|
|
41
|
-
ctx.clearRect(leftPx, rectTop, rightPx - leftPx, rectHeight);
|
|
42
|
-
}
|
|
43
|
-
const highlightedFeature = featureIdUnderMouse || (contextMenuFeature === null || contextMenuFeature === void 0 ? void 0 : contextMenuFeature.id());
|
|
44
|
-
const highlightedRect = highlightedFeature
|
|
45
|
-
? (_b = displayModel.getFeatureByID) === null || _b === void 0 ? void 0 : _b.call(displayModel, blockKey, highlightedFeature)
|
|
46
|
-
: undefined;
|
|
47
|
-
if (highlightedRect) {
|
|
48
|
-
const [leftBp, topPx, rightBp, bottomPx] = highlightedRect;
|
|
49
|
-
const [leftPx, rightPx] = bpSpanPx(leftBp, rightBp, region, bpPerPx);
|
|
50
|
-
const rectTop = Math.round(topPx);
|
|
51
|
-
const rectHeight = Math.round(bottomPx - topPx);
|
|
52
|
-
ctx.fillStyle = '#0003';
|
|
53
|
-
ctx.fillRect(leftPx, rectTop, rightPx - leftPx, rectHeight);
|
|
54
|
-
}
|
|
55
|
-
}, [
|
|
56
|
-
bpPerPx,
|
|
57
|
-
region,
|
|
58
|
-
blockKey,
|
|
59
|
-
selectedFeatureId,
|
|
60
|
-
displayModel,
|
|
61
|
-
featureIdUnderMouse,
|
|
62
|
-
contextMenuFeature,
|
|
63
|
-
]);
|
|
17
|
+
const selectedRect = selectedFeatureId
|
|
18
|
+
? displayModel === null || displayModel === void 0 ? void 0 : displayModel.getFeatureByID(blockKey, selectedFeatureId)
|
|
19
|
+
: undefined;
|
|
20
|
+
const highlightedFeature = featureIdUnderMouse || (contextMenuFeature === null || contextMenuFeature === void 0 ? void 0 : contextMenuFeature.id());
|
|
21
|
+
const highlightedRect = highlightedFeature
|
|
22
|
+
? displayModel === null || displayModel === void 0 ? void 0 : displayModel.getFeatureByID(blockKey, highlightedFeature)
|
|
23
|
+
: undefined;
|
|
24
|
+
function makeRect(r, offset = 2) {
|
|
25
|
+
const [leftBp, topPx, rightBp, bottomPx] = r;
|
|
26
|
+
const [leftPx, rightPx] = bpSpanPx(leftBp, rightBp, region, bpPerPx);
|
|
27
|
+
const rectTop = Math.round(topPx);
|
|
28
|
+
const rectHeight = Math.round(bottomPx - topPx);
|
|
29
|
+
return {
|
|
30
|
+
left: leftPx - offset,
|
|
31
|
+
top: rectTop - offset,
|
|
32
|
+
width: rightPx - leftPx,
|
|
33
|
+
height: rectHeight,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const selected = selectedRect ? makeRect(selectedRect) : undefined;
|
|
37
|
+
const highlight = highlightedRect ? makeRect(highlightedRect, 0) : undefined;
|
|
64
38
|
function onMouseDown(event) {
|
|
65
39
|
setMouseIsDown(true);
|
|
66
40
|
setMovedDuringLastMouseDown(false);
|
|
@@ -93,18 +67,18 @@ const PileupRendering = observer(function (props) {
|
|
|
93
67
|
callMouseHandler('ContextMenu', event);
|
|
94
68
|
}
|
|
95
69
|
function mouseMove(event) {
|
|
96
|
-
if (!
|
|
70
|
+
if (!ref.current) {
|
|
97
71
|
return;
|
|
98
72
|
}
|
|
99
73
|
if (mouseIsDown) {
|
|
100
74
|
setMovedDuringLastMouseDown(true);
|
|
101
75
|
}
|
|
102
|
-
const rect =
|
|
76
|
+
const rect = ref.current.getBoundingClientRect();
|
|
103
77
|
const offsetX = event.clientX - rect.left;
|
|
104
78
|
const offsetY = event.clientY - rect.top;
|
|
105
79
|
const px = region.reversed ? width - offsetX : offsetX;
|
|
106
80
|
const clientBp = region.start + bpPerPx * px;
|
|
107
|
-
onMouseMove === null || onMouseMove === void 0 ? void 0 : onMouseMove(event, displayModel.getFeatureOverlapping(blockKey, clientBp, offsetY));
|
|
81
|
+
onMouseMove === null || onMouseMove === void 0 ? void 0 : onMouseMove(event, displayModel === null || displayModel === void 0 ? void 0 : displayModel.getFeatureOverlapping(blockKey, clientBp, offsetY));
|
|
108
82
|
}
|
|
109
83
|
function callMouseHandler(handlerName, event) {
|
|
110
84
|
// @ts-expect-error
|
|
@@ -120,15 +94,46 @@ const PileupRendering = observer(function (props) {
|
|
|
120
94
|
}
|
|
121
95
|
const canvasWidth = Math.ceil(width);
|
|
122
96
|
// need to call this in render so we get the right observer behavior
|
|
123
|
-
return (React.createElement("div", { "data-testid":
|
|
97
|
+
return (React.createElement("div", { ref: ref, "data-testid": [
|
|
98
|
+
'pileup-overlay',
|
|
124
99
|
sortedBy === null || sortedBy === void 0 ? void 0 : sortedBy.type,
|
|
125
100
|
colorBy === null || colorBy === void 0 ? void 0 : colorBy.type,
|
|
126
101
|
colorBy === null || colorBy === void 0 ? void 0 : colorBy.tag,
|
|
127
102
|
(_a = filterBy === null || filterBy === void 0 ? void 0 : filterBy.tagFilter) === null || _a === void 0 ? void 0 : _a.tag,
|
|
128
103
|
]
|
|
129
104
|
.filter(f => !!f)
|
|
130
|
-
.join('-')
|
|
105
|
+
.join('-'), style: { position: 'relative', width: canvasWidth, height }, onMouseDown: event => {
|
|
106
|
+
onMouseDown(event);
|
|
107
|
+
}, onMouseEnter: event => {
|
|
108
|
+
onMouseEnter(event);
|
|
109
|
+
}, onMouseOut: event => {
|
|
110
|
+
onMouseOut(event);
|
|
111
|
+
}, onMouseOver: event => {
|
|
112
|
+
onMouseOver(event);
|
|
113
|
+
}, onMouseUp: event => {
|
|
114
|
+
onMouseUp(event);
|
|
115
|
+
}, onMouseLeave: event => {
|
|
116
|
+
onMouseLeave(event);
|
|
117
|
+
}, onMouseMove: event => {
|
|
118
|
+
mouseMove(event);
|
|
119
|
+
}, onClick: event => {
|
|
120
|
+
onClick(event);
|
|
121
|
+
}, onContextMenu: event => {
|
|
122
|
+
onContextMenu(event);
|
|
123
|
+
}, onFocus: () => { }, onBlur: () => { } },
|
|
131
124
|
React.createElement(PrerenderedCanvas, { ...props, style: { position: 'absolute', left: 0, top: 0 } }),
|
|
132
|
-
React.createElement("
|
|
125
|
+
firstRender && highlight ? (React.createElement("div", { style: {
|
|
126
|
+
position: 'absolute',
|
|
127
|
+
backgroundColor: '#0003',
|
|
128
|
+
pointerEvents: 'none',
|
|
129
|
+
...highlight,
|
|
130
|
+
} })) : null,
|
|
131
|
+
firstRender && selected ? (React.createElement("div", { style: {
|
|
132
|
+
position: 'absolute',
|
|
133
|
+
border: '2px solid #00b8ff',
|
|
134
|
+
boxSizing: 'content-box',
|
|
135
|
+
pointerEvents: 'none',
|
|
136
|
+
...selected,
|
|
137
|
+
} })) : null));
|
|
133
138
|
});
|
|
134
139
|
export default PileupRendering;
|
|
@@ -20,24 +20,32 @@ export function getAlignmentShapeColor({ colorType, tag, feature, config, defaul
|
|
|
20
20
|
const tags = feature.get('tags');
|
|
21
21
|
const val = tags ? tags[tag] : feature.get(tag);
|
|
22
22
|
if (tag === 'XS' || tag === 'TS') {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
if (val === '-') {
|
|
24
|
+
return fillColor.color_rev_strand;
|
|
25
|
+
}
|
|
26
|
+
else if (val === '+') {
|
|
27
|
+
return fillColor.color_fwd_strand;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return fillColor.color_nostrand;
|
|
31
|
+
}
|
|
27
32
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
?
|
|
32
|
-
:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
if (tag === 'ts') {
|
|
34
|
+
if (val === '-') {
|
|
35
|
+
return feature.get('strand') === -1
|
|
36
|
+
? fillColor.color_fwd_strand
|
|
37
|
+
: fillColor.color_rev_strand;
|
|
38
|
+
}
|
|
39
|
+
else if (val === '+') {
|
|
40
|
+
return feature.get('strand') === -1
|
|
41
|
+
? fillColor.color_rev_strand
|
|
42
|
+
: fillColor.color_fwd_strand;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return fillColor.color_nostrand;
|
|
46
|
+
}
|
|
40
47
|
}
|
|
48
|
+
return colorTagMap[val] || fillColor.color_nostrand;
|
|
41
49
|
}
|
|
42
50
|
case 'insertSizeAndPairOrientation':
|
|
43
51
|
break;
|
|
@@ -9,7 +9,12 @@ export function layoutFeature({ feature, layout, bpPerPx, region, showSoftClip,
|
|
|
9
9
|
if (seq) {
|
|
10
10
|
for (const { type, start, cliplen = 0 } of mismatches) {
|
|
11
11
|
if (type === 'softclip') {
|
|
12
|
-
start === 0
|
|
12
|
+
if (start === 0) {
|
|
13
|
+
expansionBefore = cliplen;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
expansionAfter = cliplen;
|
|
17
|
+
}
|
|
13
18
|
}
|
|
14
19
|
}
|
|
15
20
|
}
|
|
@@ -6,13 +6,7 @@ import { sortFeature } from './sortUtil';
|
|
|
6
6
|
// layout determines the height of the canvas that we use to render
|
|
7
7
|
export function layoutFeats(props) {
|
|
8
8
|
const { layout, features, sortedBy, config, bpPerPx, showSoftClip, regions } = props;
|
|
9
|
-
const
|
|
10
|
-
if (!layout) {
|
|
11
|
-
throw new Error(`layout required`);
|
|
12
|
-
}
|
|
13
|
-
if (!layout.addRect) {
|
|
14
|
-
throw new Error('invalid layout object');
|
|
15
|
-
}
|
|
9
|
+
const region = regions[0];
|
|
16
10
|
const featureMap = (sortedBy === null || sortedBy === void 0 ? void 0 : sortedBy.type) && region.start === sortedBy.pos
|
|
17
11
|
? sortFeature(features, sortedBy)
|
|
18
12
|
: features;
|
|
@@ -2,7 +2,7 @@ import { bpSpanPx } from '@jbrowse/core/util';
|
|
|
2
2
|
export function renderAlignmentShape({ ctx, feat, renderArgs, }) {
|
|
3
3
|
const { regions, bpPerPx } = renderArgs;
|
|
4
4
|
const { heightPx, topPx, feature } = feat;
|
|
5
|
-
const
|
|
5
|
+
const region = regions[0];
|
|
6
6
|
const s = feature.get('start');
|
|
7
7
|
const e = feature.get('end');
|
|
8
8
|
const [leftPx, rightPx] = bpSpanPx(s, e, region, bpPerPx);
|
|
@@ -4,7 +4,7 @@ import { colord } from '@jbrowse/core/util/colord';
|
|
|
4
4
|
export function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, largeInsertionIndicatorScale, mismatchAlpha, charWidth, charHeight, colorForBase, contrastForBase, canvasWidth, drawSNPsMuted, drawIndels = true, }) {
|
|
5
5
|
const { bpPerPx, regions } = renderArgs;
|
|
6
6
|
const { heightPx, topPx, feature } = feat;
|
|
7
|
-
const
|
|
7
|
+
const region = regions[0];
|
|
8
8
|
const start = feature.get('start');
|
|
9
9
|
const pxPerBp = Math.min(1 / bpPerPx, 2);
|
|
10
10
|
const mismatches = feature.get('mismatches');
|
|
@@ -6,7 +6,7 @@ import { fillRect, getCharWidthHeight } from './util';
|
|
|
6
6
|
export function renderSoftClipping({ ctx, feat, renderArgs, config, theme, colorForBase, canvasWidth, }) {
|
|
7
7
|
const { feature, topPx, heightPx } = feat;
|
|
8
8
|
const { regions, bpPerPx } = renderArgs;
|
|
9
|
-
const
|
|
9
|
+
const region = regions[0];
|
|
10
10
|
const minFeatWidth = readConfObject(config, 'minSubfeatureWidth');
|
|
11
11
|
const mismatches = feature.get('mismatches');
|
|
12
12
|
const seq = feature.get('seq');
|
|
@@ -3,12 +3,10 @@ export function fillRect(ctx, l, t, w, h, cw, color) {
|
|
|
3
3
|
if (l + w < 0 || l > cw) {
|
|
4
4
|
return;
|
|
5
5
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
ctx.fillStyle = color;
|
|
9
|
-
}
|
|
10
|
-
ctx.fillRect(l, t, w, h);
|
|
6
|
+
if (color) {
|
|
7
|
+
ctx.fillStyle = color;
|
|
11
8
|
}
|
|
9
|
+
ctx.fillRect(l, t, w, h);
|
|
12
10
|
}
|
|
13
11
|
export function getColorBaseMap(theme) {
|
|
14
12
|
const { bases } = theme.palette;
|
|
@@ -7,7 +7,6 @@ function mismatchLen(mismatch) {
|
|
|
7
7
|
function isInterbase(type) {
|
|
8
8
|
return type === 'softclip' || type === 'hardclip' || type === 'insertion';
|
|
9
9
|
}
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
10
|
function inc(bin, strand, type, field) {
|
|
12
11
|
let thisBin = bin[type][field];
|
|
13
12
|
if (thisBin === undefined) {
|
|
@@ -92,12 +91,7 @@ export default async function generateCoverageBins(features, region, opts, fetch
|
|
|
92
91
|
};
|
|
93
92
|
}
|
|
94
93
|
const bin = bins[epos];
|
|
95
|
-
|
|
96
|
-
inc(bin, fstrand, 'cov', mod);
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
console.warn('Undefined position in modifications snpcoverage encountered');
|
|
100
|
-
}
|
|
94
|
+
inc(bin, fstrand, 'cov', mod);
|
|
101
95
|
}
|
|
102
96
|
}
|
|
103
97
|
}
|
|
@@ -142,14 +136,14 @@ export default async function generateCoverageBins(features, region, opts, fetch
|
|
|
142
136
|
}
|
|
143
137
|
else {
|
|
144
138
|
if (bin0) {
|
|
145
|
-
if (!
|
|
139
|
+
if (!dels.some(d => doesIntersect2(j, j + 1, d.start + fstart, d.start + fstart + d.length))) {
|
|
146
140
|
inc(bin0, fstrand, 'cov', 'unmeth');
|
|
147
141
|
bin0.ref--;
|
|
148
|
-
bin0[fstrand]
|
|
142
|
+
bin0[fstrand]--;
|
|
149
143
|
}
|
|
150
144
|
}
|
|
151
145
|
if (bin1) {
|
|
152
|
-
if (!
|
|
146
|
+
if (!dels.some(d => doesIntersect2(j + 1, j + 2, d.start + fstart, d.start + fstart + d.length))) {
|
|
153
147
|
inc(bin1, fstrand, 'cov', 'unmeth');
|
|
154
148
|
bin1.ref--;
|
|
155
149
|
bin1[fstrand]--;
|
|
@@ -13,8 +13,8 @@ export interface RenderArgsDeserializedWithFeatures extends RenderArgsDeserializ
|
|
|
13
13
|
values: number[];
|
|
14
14
|
};
|
|
15
15
|
displayCrossHatches: boolean;
|
|
16
|
-
modificationTagMap?: Record<string, string
|
|
16
|
+
modificationTagMap?: Record<string, string>;
|
|
17
17
|
}
|
|
18
18
|
export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
19
|
-
draw(ctx: CanvasRenderingContext2D, props: RenderArgsDeserializedWithFeatures): Promise<
|
|
19
|
+
draw(ctx: CanvasRenderingContext2D, props: RenderArgsDeserializedWithFeatures): Promise<undefined>;
|
|
20
20
|
}
|
|
@@ -9,17 +9,13 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
9
9
|
async draw(ctx, props) {
|
|
10
10
|
const { features, regions, bpPerPx, displayCrossHatches, modificationTagMap = {}, scaleOpts, height: unadjustedHeight, theme: configTheme, config: cfg, ticks, } = props;
|
|
11
11
|
const theme = createJBrowseTheme(configTheme);
|
|
12
|
-
const
|
|
12
|
+
const region = regions[0];
|
|
13
13
|
const width = (region.end - region.start) / bpPerPx;
|
|
14
14
|
// the adjusted height takes into account YSCALEBAR_LABEL_OFFSET from the
|
|
15
15
|
// wiggle display, and makes the height of the actual drawn area add
|
|
16
16
|
// "padding" to the top and bottom of the display
|
|
17
17
|
const offset = YSCALEBAR_LABEL_OFFSET;
|
|
18
18
|
const height = unadjustedHeight - offset * 2;
|
|
19
|
-
const { domain } = scaleOpts;
|
|
20
|
-
if (!domain) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
19
|
const opts = { ...scaleOpts, range: [0, height] };
|
|
24
20
|
const viewScale = getScale(opts);
|
|
25
21
|
// clipping and insertion indicators, uses a smaller height/2 scale
|
|
@@ -176,5 +172,6 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
176
172
|
ctx.stroke();
|
|
177
173
|
});
|
|
178
174
|
}
|
|
175
|
+
return undefined;
|
|
179
176
|
}
|
|
180
177
|
}
|
package/esm/index.js
CHANGED
|
@@ -37,7 +37,9 @@ export default class AlignmentsPlugin extends Plugin {
|
|
|
37
37
|
LinearAlignmentsDisplayF,
|
|
38
38
|
AlignmentsFeatureWidgetF,
|
|
39
39
|
GuessAlignmentsTypesF,
|
|
40
|
-
].map(f =>
|
|
40
|
+
].map(f => {
|
|
41
|
+
f(pluginManager);
|
|
42
|
+
});
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
export { linearPileupDisplayStateModelFactory, linearPileupDisplayConfigSchemaFactory, SharedLinearPileupDisplayMixin, } from './LinearPileupDisplay';
|
|
@@ -21,7 +21,9 @@ const useStyles = makeStyles()(theme => ({
|
|
|
21
21
|
const BaseDisplayComponent = observer(function ({ model, children, }) {
|
|
22
22
|
const { error, regionTooLarge } = model;
|
|
23
23
|
return error ? (React.createElement(BlockMsg, { message: `${error}`, severity: "error", action: React.createElement(Tooltip, { title: "Reload" },
|
|
24
|
-
React.createElement(Button, { "data-testid": "reload_button", onClick: () =>
|
|
24
|
+
React.createElement(Button, { "data-testid": "reload_button", onClick: () => {
|
|
25
|
+
model.reload();
|
|
26
|
+
} }, "Reload")) })) : regionTooLarge ? (model.regionCannotBeRendered()) : (React.createElement(DataDisplay, { model: model }, children));
|
|
25
27
|
});
|
|
26
28
|
const DataDisplay = observer(function ({ model, children, }) {
|
|
27
29
|
const { drawn, loading } = model;
|
|
@@ -29,7 +29,9 @@ const flagNames = [
|
|
|
29
29
|
function Bitmask(props) {
|
|
30
30
|
const { flag = 0, setFlag } = props;
|
|
31
31
|
return (React.createElement(React.Fragment, null,
|
|
32
|
-
React.createElement(TextField, { type: "number", value: flag, onChange: event =>
|
|
32
|
+
React.createElement(TextField, { type: "number", value: flag, onChange: event => {
|
|
33
|
+
setFlag(+event.target.value);
|
|
34
|
+
} }),
|
|
33
35
|
flagNames.map((name, index) => {
|
|
34
36
|
const val = flag & (1 << index);
|
|
35
37
|
const key = `${name}_${val}`;
|
|
@@ -55,7 +57,7 @@ const FilterByTagDialog = observer(function (props) {
|
|
|
55
57
|
const [tag, setTag] = useState(((_a = filterBy.tagFilter) === null || _a === void 0 ? void 0 : _a.tag) || '');
|
|
56
58
|
const [tagValue, setTagValue] = useState(((_b = filterBy.tagFilter) === null || _b === void 0 ? void 0 : _b.value) || '');
|
|
57
59
|
const [readName, setReadName] = useState(filterBy.readName || '');
|
|
58
|
-
const validTag =
|
|
60
|
+
const validTag = /^[A-Za-z][A-Za-z0-9]$/.exec(tag);
|
|
59
61
|
const site = 'https://broadinstitute.github.io/picard/explain-flags.html';
|
|
60
62
|
return (React.createElement(Dialog, { open: true, onClose: handleClose, title: "Filter options" },
|
|
61
63
|
React.createElement(DialogContent, null,
|
|
@@ -74,11 +76,17 @@ const FilterByTagDialog = observer(function (props) {
|
|
|
74
76
|
React.createElement(Bitmask, { flag: flagExclude, setFlag: setFlagExclude })))),
|
|
75
77
|
React.createElement(Paper, { className: classes.paper, variant: "outlined" },
|
|
76
78
|
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 =>
|
|
78
|
-
|
|
79
|
+
React.createElement(TextField, { className: classes.field, value: tag, onChange: event => {
|
|
80
|
+
setTag(event.target.value);
|
|
81
|
+
}, placeholder: "Enter tag name", inputProps: { maxLength: 2 }, error: tag.length === 2 && !validTag, helperText: tag.length === 2 && !validTag ? 'Not a valid tag' : '' }),
|
|
82
|
+
React.createElement(TextField, { className: classes.field, value: tagValue, onChange: event => {
|
|
83
|
+
setTagValue(event.target.value);
|
|
84
|
+
}, placeholder: "Enter tag value" })),
|
|
79
85
|
React.createElement(Paper, { className: classes.paper, variant: "outlined" },
|
|
80
86
|
React.createElement(Typography, null, "Filter by read name"),
|
|
81
|
-
React.createElement(TextField, { className: classes.field, value: readName, onChange: event =>
|
|
87
|
+
React.createElement(TextField, { className: classes.field, value: readName, onChange: event => {
|
|
88
|
+
setReadName(event.target.value);
|
|
89
|
+
}, placeholder: "Enter read name" })),
|
|
82
90
|
React.createElement(DialogActions, null,
|
|
83
91
|
React.createElement(Button, { variant: "contained", color: "primary", autoFocus: true, type: "submit", onClick: () => {
|
|
84
92
|
model.setFilterBy({
|
|
@@ -94,6 +102,8 @@ const FilterByTagDialog = observer(function (props) {
|
|
|
94
102
|
});
|
|
95
103
|
handleClose();
|
|
96
104
|
} }, "Submit"),
|
|
97
|
-
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () =>
|
|
105
|
+
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
106
|
+
handleClose();
|
|
107
|
+
} }, "Cancel")))));
|
|
98
108
|
});
|
|
99
109
|
export default FilterByTagDialog;
|
package/esm/shared/color.js
CHANGED
|
@@ -50,10 +50,10 @@ export function getPairedInsertSizeColor(f1, f2, stats) {
|
|
|
50
50
|
if (sameRef && tlen > ((stats === null || stats === void 0 ? void 0 : stats.upper) || 0)) {
|
|
51
51
|
return [fillColor.color_longinsert, strokeColor.color_longinsert];
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
if (sameRef && tlen < ((stats === null || stats === void 0 ? void 0 : stats.lower) || 0)) {
|
|
54
54
|
return [fillColor.color_shortinsert, strokeColor.color_shortinsert];
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
if (!sameRef) {
|
|
57
57
|
return [fillColor.color_interchrom, strokeColor.color_interchrom];
|
|
58
58
|
}
|
|
59
59
|
return undefined;
|
package/esm/shared/index.d.ts
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
import { IAnyStateTreeNode } from 'mobx-state-tree';
|
|
2
2
|
import { BlockSet } from '@jbrowse/core/util/blockTypes';
|
|
3
3
|
import { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
4
|
-
export declare function getUniqueTagValues(self
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
tag
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
export declare function getUniqueTagValues({ self, tag, blocks, opts, }: {
|
|
5
|
+
self: IAnyStateTreeNode & {
|
|
6
|
+
adapterConfig: AnyConfigurationModel;
|
|
7
|
+
};
|
|
8
|
+
tag: string;
|
|
9
|
+
blocks: BlockSet;
|
|
10
|
+
opts?: {
|
|
11
|
+
headers?: Record<string, string>;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
filters: string[];
|
|
14
|
+
};
|
|
13
15
|
}): Promise<string[]>;
|
|
14
16
|
type Track = IAnyStateTreeNode & {
|
|
15
17
|
configuration: AnyConfigurationModel;
|
|
16
18
|
};
|
|
17
|
-
export declare function getUniqueModificationValues(self
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
export declare function getUniqueModificationValues({ self, adapterConfig, blocks, opts, }: {
|
|
20
|
+
self: IAnyStateTreeNode & {
|
|
21
|
+
parentTrack: Track;
|
|
22
|
+
};
|
|
23
|
+
adapterConfig: AnyConfigurationModel;
|
|
24
|
+
blocks: BlockSet;
|
|
25
|
+
opts?: {
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
filters: string[];
|
|
29
|
+
};
|
|
26
30
|
}): Promise<string[]>;
|
|
27
31
|
export declare const FilterModel: import("mobx-state-tree").IModelType<{
|
|
28
32
|
flagInclude: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<number>, [undefined]>;
|
|
@@ -30,7 +34,7 @@ export declare const FilterModel: import("mobx-state-tree").IModelType<{
|
|
|
30
34
|
readName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
31
35
|
tagFilter: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IModelType<{
|
|
32
36
|
tag: import("mobx-state-tree").ISimpleType<string>;
|
|
33
|
-
value: import("mobx-state-tree").ISimpleType<string
|
|
37
|
+
value: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
34
38
|
}, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
35
39
|
}, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
|
|
36
40
|
export interface IFilter {
|
|
@@ -39,7 +43,7 @@ export interface IFilter {
|
|
|
39
43
|
readName?: string;
|
|
40
44
|
tagFilter?: {
|
|
41
45
|
tag: string;
|
|
42
|
-
value
|
|
46
|
+
value?: string;
|
|
43
47
|
};
|
|
44
48
|
}
|
|
45
49
|
export {};
|
package/esm/shared/index.js
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
import { types } from 'mobx-state-tree';
|
|
2
2
|
import { getSession } from '@jbrowse/core/util';
|
|
3
3
|
import { getRpcSessionId } from '@jbrowse/core/util/tracks';
|
|
4
|
-
export async function getUniqueTagValues(self,
|
|
4
|
+
export async function getUniqueTagValues({ self, tag, blocks, opts, }) {
|
|
5
5
|
const { rpcManager } = getSession(self);
|
|
6
6
|
const { adapterConfig } = self;
|
|
7
7
|
const sessionId = getRpcSessionId(self);
|
|
8
8
|
const values = await rpcManager.call(getRpcSessionId(self), 'PileupGetGlobalValueForTag', {
|
|
9
9
|
adapterConfig,
|
|
10
|
-
tag
|
|
10
|
+
tag,
|
|
11
11
|
sessionId,
|
|
12
12
|
regions: blocks.contentBlocks,
|
|
13
13
|
...opts,
|
|
14
14
|
});
|
|
15
15
|
return values;
|
|
16
16
|
}
|
|
17
|
-
export async function getUniqueModificationValues(self, adapterConfig,
|
|
17
|
+
export async function getUniqueModificationValues({ self, adapterConfig, blocks, opts, }) {
|
|
18
18
|
const { rpcManager } = getSession(self);
|
|
19
19
|
const sessionId = getRpcSessionId(self);
|
|
20
20
|
const values = await rpcManager.call(sessionId, 'PileupGetVisibleModifications', {
|
|
21
21
|
adapterConfig,
|
|
22
|
-
tag: colorScheme.tag,
|
|
23
22
|
sessionId,
|
|
24
23
|
regions: blocks.contentBlocks,
|
|
25
24
|
...opts,
|
|
@@ -32,6 +31,6 @@ export const FilterModel = types.model({
|
|
|
32
31
|
readName: types.maybe(types.string),
|
|
33
32
|
tagFilter: types.maybe(types.model({
|
|
34
33
|
tag: types.string,
|
|
35
|
-
value: types.string,
|
|
34
|
+
value: types.maybe(types.string),
|
|
36
35
|
})),
|
|
37
36
|
});
|
package/esm/shared/renderSvg.js
CHANGED
|
@@ -31,8 +31,6 @@ export async function renderSvg(self, opts, cb) {
|
|
|
31
31
|
React.createElement("defs", null,
|
|
32
32
|
React.createElement("clipPath", { id: clipid },
|
|
33
33
|
React.createElement("rect", { x: 0, y: 0, width: width, height: height }))),
|
|
34
|
-
React.createElement("g", {
|
|
35
|
-
/* eslint-disable-next-line react/no-danger */
|
|
36
|
-
dangerouslySetInnerHTML: { __html: ctx.getSvg().innerHTML }, clipPath: `url(#${clipid})` })));
|
|
34
|
+
React.createElement("g", { dangerouslySetInnerHTML: { __html: ctx.getSvg().innerHTML }, clipPath: `url(#${clipid})` })));
|
|
37
35
|
}
|
|
38
36
|
}
|
package/esm/util.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export declare const pairMap: {
|
|
|
18
18
|
export declare function getColorWGBS(strand: number, base: string): "#f00" | "#00f" | "#888";
|
|
19
19
|
export declare function fetchSequence(region: AugmentedRegion, adapter: BaseFeatureDataAdapter): Promise<any>;
|
|
20
20
|
export declare function shouldFetchReferenceSequence(type?: string): type is "methylation";
|
|
21
|
-
export declare const modificationColors: Record<string, string
|
|
21
|
+
export declare const modificationColors: Record<string, string>;
|
|
22
22
|
type DisplayModel = IAnyStateTreeNode & {
|
|
23
23
|
setError: (arg: unknown) => void;
|
|
24
24
|
};
|