@jbrowse/plugin-linear-comparative-view 3.6.4 → 3.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/LGVSyntenyDisplay/configSchemaF.js +1 -1
- package/dist/LGVSyntenyDisplay/model.d.ts +17 -2
- package/dist/LinearComparativeView/components/ColorBySelector.d.ts +5 -0
- package/dist/LinearComparativeView/components/ColorBySelector.js +54 -0
- package/dist/LinearComparativeView/components/Header.js +7 -2
- package/dist/LinearComparativeView/components/MinLengthSlider.d.ts +5 -0
- package/dist/LinearComparativeView/components/MinLengthSlider.js +47 -0
- package/dist/LinearComparativeView/components/OpacitySlider.d.ts +5 -0
- package/dist/LinearComparativeView/components/OpacitySlider.js +46 -0
- package/dist/LinearComparativeView/components/RubberbandSpan.js +2 -2
- package/dist/LinearComparativeView/components/SliderTooltip.d.ts +2 -0
- package/dist/LinearComparativeView/components/SliderTooltip.js +9 -0
- package/dist/LinearComparativeView/components/useRangeSelect.js +10 -14
- package/dist/LinearComparativeView/model.d.ts +7 -4
- package/dist/LinearComparativeView/model.js +4 -0
- package/dist/LinearSyntenyDisplay/afterAttach.js +5 -3
- package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +10 -5
- package/dist/LinearSyntenyDisplay/components/util.d.ts +2 -1
- package/dist/LinearSyntenyDisplay/components/util.js +43 -2
- package/dist/LinearSyntenyDisplay/drawSynteny.d.ts +3 -2
- package/dist/LinearSyntenyDisplay/drawSynteny.js +284 -45
- package/dist/LinearSyntenyDisplay/model.d.ts +6 -0
- package/dist/LinearSyntenyDisplay/model.js +12 -0
- package/dist/LinearSyntenyView/components/DiagonalizationProgressDialog.d.ts +6 -0
- package/dist/LinearSyntenyView/components/DiagonalizationProgressDialog.js +87 -0
- package/dist/LinearSyntenyView/model.d.ts +46 -15
- package/dist/LinearSyntenyView/model.js +70 -18
- package/dist/LinearSyntenyView/util/diagonalize.d.ts +27 -0
- package/dist/LinearSyntenyView/util/diagonalize.js +91 -0
- package/esm/LGVSyntenyDisplay/configSchemaF.js +1 -1
- package/esm/LGVSyntenyDisplay/model.d.ts +17 -2
- package/esm/LinearComparativeView/components/ColorBySelector.d.ts +5 -0
- package/esm/LinearComparativeView/components/ColorBySelector.js +49 -0
- package/esm/LinearComparativeView/components/Header.js +8 -3
- package/esm/LinearComparativeView/components/MinLengthSlider.d.ts +5 -0
- package/esm/LinearComparativeView/components/MinLengthSlider.js +42 -0
- package/esm/LinearComparativeView/components/OpacitySlider.d.ts +5 -0
- package/esm/LinearComparativeView/components/OpacitySlider.js +41 -0
- package/esm/LinearComparativeView/components/RubberbandSpan.js +2 -2
- package/esm/LinearComparativeView/components/SliderTooltip.d.ts +2 -0
- package/esm/LinearComparativeView/components/SliderTooltip.js +6 -0
- package/esm/LinearComparativeView/components/useRangeSelect.js +11 -15
- package/esm/LinearComparativeView/model.d.ts +7 -4
- package/esm/LinearComparativeView/model.js +4 -0
- package/esm/LinearSyntenyDisplay/afterAttach.js +6 -4
- package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +10 -5
- package/esm/LinearSyntenyDisplay/components/util.d.ts +2 -1
- package/esm/LinearSyntenyDisplay/components/util.js +43 -3
- package/esm/LinearSyntenyDisplay/drawSynteny.d.ts +3 -2
- package/esm/LinearSyntenyDisplay/drawSynteny.js +283 -45
- package/esm/LinearSyntenyDisplay/model.d.ts +6 -0
- package/esm/LinearSyntenyDisplay/model.js +12 -0
- package/esm/LinearSyntenyView/components/DiagonalizationProgressDialog.d.ts +6 -0
- package/esm/LinearSyntenyView/components/DiagonalizationProgressDialog.js +85 -0
- package/esm/LinearSyntenyView/model.d.ts +46 -15
- package/esm/LinearSyntenyView/model.js +70 -18
- package/esm/LinearSyntenyView/util/diagonalize.d.ts +27 -0
- package/esm/LinearSyntenyView/util/diagonalize.js +88 -0
- package/package.json +5 -5
|
@@ -10,7 +10,7 @@ function configSchemaF(pluginManager) {
|
|
|
10
10
|
const l2name = (mate === null || mate === void 0 ? void 0 : mate.name) || (mate === null || mate === void 0 ? void 0 : mate.id);
|
|
11
11
|
return [
|
|
12
12
|
l1name ? `Name1: ${l1name}` : '',
|
|
13
|
-
l2name ? `
|
|
13
|
+
l2name ? `Name2: ${l2name}` : '',
|
|
14
14
|
`Loc1: ${(0, util_1.assembleLocString)({
|
|
15
15
|
refName: f.get('refName'),
|
|
16
16
|
start: f.get('start'),
|
|
@@ -182,6 +182,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
182
182
|
regionCannotBeRenderedText(_region: import("@jbrowse/core/util").Region): "" | "Force load to see features";
|
|
183
183
|
regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react/jsx-runtime").JSX.Element | null;
|
|
184
184
|
} & {
|
|
185
|
+
mouseoverExtraInformation: string | undefined;
|
|
185
186
|
featureIdUnderMouse: undefined | string;
|
|
186
187
|
contextMenuFeature: undefined | Feature;
|
|
187
188
|
} & {
|
|
@@ -196,9 +197,22 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
196
197
|
} & {
|
|
197
198
|
readonly features: import("@jbrowse/core/util/compositeMap").default<string, Feature>;
|
|
198
199
|
readonly featureUnderMouse: Feature | undefined;
|
|
200
|
+
readonly layoutFeatures: import("@jbrowse/core/util/compositeMap").default<string, [number, number, number, number] | [number, number, number, number, {
|
|
201
|
+
label?: string;
|
|
202
|
+
description?: string;
|
|
203
|
+
refName: string;
|
|
204
|
+
}]>;
|
|
199
205
|
getFeatureOverlapping(blockKey: string, x: number, y: number): string | undefined;
|
|
200
|
-
getFeatureByID(blockKey: string, id: string): [number, number, number, number] |
|
|
201
|
-
|
|
206
|
+
getFeatureByID(blockKey: string, id: string): ([number, number, number, number] | [number, number, number, number, {
|
|
207
|
+
label?: string;
|
|
208
|
+
description?: string;
|
|
209
|
+
refName: string;
|
|
210
|
+
}]) | undefined;
|
|
211
|
+
searchFeatureByID(id: string): ([number, number, number, number] | [number, number, number, number, {
|
|
212
|
+
label?: string;
|
|
213
|
+
description?: string;
|
|
214
|
+
refName: string;
|
|
215
|
+
}]) | undefined;
|
|
202
216
|
} & {
|
|
203
217
|
addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
|
|
204
218
|
deleteBlock(key: string): void;
|
|
@@ -207,6 +221,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
207
221
|
clearFeatureSelection(): void;
|
|
208
222
|
setFeatureIdUnderMouse(feature?: string): void;
|
|
209
223
|
setContextMenuFeature(feature?: Feature): void;
|
|
224
|
+
setMouseoverExtraInformation(extra?: string): void;
|
|
210
225
|
} & {
|
|
211
226
|
reload(): Promise<void>;
|
|
212
227
|
} & {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const CascadingMenuButton_1 = __importDefault(require("@jbrowse/core/ui/CascadingMenuButton"));
|
|
8
|
+
const Palette_1 = __importDefault(require("@mui/icons-material/Palette"));
|
|
9
|
+
const mobx_react_1 = require("mobx-react");
|
|
10
|
+
const ColorBySelector = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
11
|
+
var _a, _b, _c;
|
|
12
|
+
const firstDisplay = (_b = (_a = model.levels[0]) === null || _a === void 0 ? void 0 : _a.tracks[0]) === null || _b === void 0 ? void 0 : _b.displays[0];
|
|
13
|
+
const colorBy = (_c = firstDisplay === null || firstDisplay === void 0 ? void 0 : firstDisplay.colorBy) !== null && _c !== void 0 ? _c : 'default';
|
|
14
|
+
const setColorBy = (value) => {
|
|
15
|
+
for (const level of model.levels) {
|
|
16
|
+
for (const track of level.tracks) {
|
|
17
|
+
for (const display of track.displays) {
|
|
18
|
+
;
|
|
19
|
+
display.setColorBy(value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
return ((0, jsx_runtime_1.jsx)(CascadingMenuButton_1.default, { menuItems: [
|
|
25
|
+
{
|
|
26
|
+
label: 'Default',
|
|
27
|
+
type: 'radio',
|
|
28
|
+
checked: colorBy === 'default',
|
|
29
|
+
onClick: () => {
|
|
30
|
+
setColorBy('default');
|
|
31
|
+
},
|
|
32
|
+
helpText: 'Use the default color scheme with CIGAR operation coloring. Insertions, deletions, matches, and mismatches are shown in different colors with transparency.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'Strand',
|
|
36
|
+
type: 'radio',
|
|
37
|
+
checked: colorBy === 'strand',
|
|
38
|
+
onClick: () => {
|
|
39
|
+
setColorBy('strand');
|
|
40
|
+
},
|
|
41
|
+
helpText: 'Color alignments by strand orientation. Forward strand alignments and reverse strand alignments are shown in different colors, making it easy to identify inversions and strand-specific patterns.',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
label: 'Query',
|
|
45
|
+
type: 'radio',
|
|
46
|
+
checked: colorBy === 'query',
|
|
47
|
+
onClick: () => {
|
|
48
|
+
setColorBy('query');
|
|
49
|
+
},
|
|
50
|
+
helpText: 'Color alignments by query sequence name. Each unique query sequence is assigned a consistent color based on its name, making it easy to visually distinguish between different sequences.',
|
|
51
|
+
},
|
|
52
|
+
], children: (0, jsx_runtime_1.jsx)(Palette_1.default, {}) }));
|
|
53
|
+
});
|
|
54
|
+
exports.default = ColorBySelector;
|
|
@@ -12,17 +12,22 @@ const Search_1 = __importDefault(require("@mui/icons-material/Search"));
|
|
|
12
12
|
const material_1 = require("@mui/material");
|
|
13
13
|
const mobx_react_1 = require("mobx-react");
|
|
14
14
|
const mui_1 = require("tss-react/mui");
|
|
15
|
+
const ColorBySelector_1 = __importDefault(require("./ColorBySelector"));
|
|
15
16
|
const HeaderSearchBoxes_1 = __importDefault(require("./HeaderSearchBoxes"));
|
|
17
|
+
const MinLengthSlider_1 = __importDefault(require("./MinLengthSlider"));
|
|
18
|
+
const OpacitySlider_1 = __importDefault(require("./OpacitySlider"));
|
|
16
19
|
const useStyles = (0, mui_1.makeStyles)()({
|
|
17
20
|
inline: {
|
|
18
21
|
display: 'inline-flex',
|
|
19
22
|
},
|
|
20
23
|
});
|
|
21
24
|
const Header = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
25
|
+
var _a, _b;
|
|
22
26
|
const { classes } = useStyles();
|
|
23
|
-
const { views } = model;
|
|
27
|
+
const { views, levels, showDynamicControls } = model;
|
|
24
28
|
const [showSearchBoxes, setShowSearchBoxes] = (0, react_1.useState)(views.length <= 3);
|
|
25
29
|
const [sideBySide, setSideBySide] = (0, react_1.useState)(views.length <= 3);
|
|
30
|
+
const hasDisplays = (_b = (_a = levels[0]) === null || _a === void 0 ? void 0 : _a.tracks[0]) === null || _b === void 0 ? void 0 : _b.displays[0];
|
|
26
31
|
return ((0, jsx_runtime_1.jsxs)(material_1.FormGroup, { row: true, children: [(0, jsx_runtime_1.jsx)(CascadingMenuButton_1.default, { menuItems: [
|
|
27
32
|
{
|
|
28
33
|
label: 'Synteny track selectors',
|
|
@@ -77,6 +82,6 @@ const Header = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
|
77
82
|
setSideBySide(!sideBySide);
|
|
78
83
|
},
|
|
79
84
|
},
|
|
80
|
-
], children: (0, jsx_runtime_1.jsx)(Search_1.default, {}) }), showSearchBoxes ? ((0, jsx_runtime_1.jsx)("span", { className: sideBySide ? classes.inline : undefined, children: views.map(view => ((0, jsx_runtime_1.jsx)(HeaderSearchBoxes_1.default, { view: view }, view.id))) })) : null] }));
|
|
85
|
+
], children: (0, jsx_runtime_1.jsx)(Search_1.default, {}) }), hasDisplays && showDynamicControls ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ColorBySelector_1.default, { model: model }), (0, jsx_runtime_1.jsx)(OpacitySlider_1.default, { model: model }), (0, jsx_runtime_1.jsx)(MinLengthSlider_1.default, { model: model })] })) : null, showSearchBoxes ? ((0, jsx_runtime_1.jsx)("span", { className: sideBySide ? classes.inline : undefined, children: views.map(view => ((0, jsx_runtime_1.jsx)(HeaderSearchBoxes_1.default, { view: view }, view.id))) })) : null] }));
|
|
81
86
|
});
|
|
82
87
|
exports.default = Header;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const material_1 = require("@mui/material");
|
|
9
|
+
const mobx_react_1 = require("mobx-react");
|
|
10
|
+
const mui_1 = require("tss-react/mui");
|
|
11
|
+
const SliderTooltip_1 = __importDefault(require("./SliderTooltip"));
|
|
12
|
+
const useStyles = (0, mui_1.makeStyles)()({
|
|
13
|
+
container: {
|
|
14
|
+
display: 'flex',
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
marginLeft: 16,
|
|
17
|
+
marginRight: 16,
|
|
18
|
+
minWidth: 150,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
const MinLengthSlider = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
22
|
+
var _a, _b, _c;
|
|
23
|
+
const { classes } = useStyles();
|
|
24
|
+
const { levels } = model;
|
|
25
|
+
const firstDisplay = (_b = (_a = levels[0]) === null || _a === void 0 ? void 0 : _a.tracks[0]) === null || _b === void 0 ? void 0 : _b.displays[0];
|
|
26
|
+
const minAlignmentLength = (_c = firstDisplay === null || firstDisplay === void 0 ? void 0 : firstDisplay.minAlignmentLength) !== null && _c !== void 0 ? _c : 0;
|
|
27
|
+
const [minLengthValue, setMinLengthValue] = (0, react_1.useState)(Math.log2(Math.max(1, minAlignmentLength)) * 100);
|
|
28
|
+
(0, react_1.useEffect)(() => {
|
|
29
|
+
setMinLengthValue(Math.log2(Math.max(1, minAlignmentLength)) * 100);
|
|
30
|
+
}, [minAlignmentLength]);
|
|
31
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Box, { className: classes.container, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", style: { marginRight: 8 }, children: "Min length:" }), (0, jsx_runtime_1.jsx)(material_1.Slider, { value: minLengthValue, onChange: (_, val) => {
|
|
32
|
+
setMinLengthValue(val);
|
|
33
|
+
}, onChangeCommitted: () => {
|
|
34
|
+
const newMinLength = Math.round(2 ** (minLengthValue / 100));
|
|
35
|
+
for (const level of levels) {
|
|
36
|
+
for (const track of level.tracks) {
|
|
37
|
+
for (const display of track.displays) {
|
|
38
|
+
;
|
|
39
|
+
display.setMinAlignmentLength(newMinLength);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}, min: 0, max: Math.log2(1000000) * 100, valueLabelDisplay: "auto", valueLabelFormat: newValue => Math.round(2 ** (newValue / 100)).toLocaleString(), size: "small", style: { minWidth: 100 }, slots: {
|
|
44
|
+
valueLabel: SliderTooltip_1.default,
|
|
45
|
+
} })] }));
|
|
46
|
+
});
|
|
47
|
+
exports.default = MinLengthSlider;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const material_1 = require("@mui/material");
|
|
8
|
+
const mobx_react_1 = require("mobx-react");
|
|
9
|
+
const mui_1 = require("tss-react/mui");
|
|
10
|
+
const SliderTooltip_1 = __importDefault(require("./SliderTooltip"));
|
|
11
|
+
const useStyles = (0, mui_1.makeStyles)()({
|
|
12
|
+
container: {
|
|
13
|
+
display: 'flex',
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
marginLeft: 16,
|
|
16
|
+
marginRight: 16,
|
|
17
|
+
minWidth: 150,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const OpacitySlider = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
21
|
+
var _a, _b, _c;
|
|
22
|
+
const { classes } = useStyles();
|
|
23
|
+
const { levels } = model;
|
|
24
|
+
const firstDisplay = (_b = (_a = levels[0]) === null || _a === void 0 ? void 0 : _a.tracks[0]) === null || _b === void 0 ? void 0 : _b.displays[0];
|
|
25
|
+
const alpha = (_c = firstDisplay === null || firstDisplay === void 0 ? void 0 : firstDisplay.alpha) !== null && _c !== void 0 ? _c : 1;
|
|
26
|
+
const exponent = 3;
|
|
27
|
+
const alphaToSlider = (a) => Math.pow(a, 1 / exponent);
|
|
28
|
+
const sliderToAlpha = (s) => Math.pow(s, exponent);
|
|
29
|
+
const sliderValue = alphaToSlider(alpha);
|
|
30
|
+
const handleAlphaChange = (_event, value) => {
|
|
31
|
+
const sliderVal = typeof value === 'number' ? value : value[0];
|
|
32
|
+
const newAlpha = sliderToAlpha(sliderVal);
|
|
33
|
+
for (const level of levels) {
|
|
34
|
+
for (const track of level.tracks) {
|
|
35
|
+
for (const display of track.displays) {
|
|
36
|
+
;
|
|
37
|
+
display.setAlpha(newAlpha);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Box, { className: classes.container, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", style: { marginRight: 8 }, children: "Opacity:" }), (0, jsx_runtime_1.jsx)(material_1.Slider, { value: sliderValue, onChange: handleAlphaChange, min: 0, max: 1, step: 0.01, valueLabelDisplay: "auto", size: "small", style: { minWidth: 100 }, slots: {
|
|
43
|
+
valueLabel: SliderTooltip_1.default,
|
|
44
|
+
}, valueLabelFormat: (value) => sliderToAlpha(value).toFixed(3) })] }));
|
|
45
|
+
});
|
|
46
|
+
exports.default = OpacitySlider;
|
|
@@ -29,10 +29,10 @@ const useStyles = (0, mui_1.makeStyles)()(theme => {
|
|
|
29
29
|
function RubberbandSpan({ leftBpOffset, rightBpOffset, numOfBpSelected, left, width, top = 0, sticky = false, }) {
|
|
30
30
|
const { classes } = useStyles();
|
|
31
31
|
const [anchorEl, setAnchorEl] = (0, react_1.useState)(null);
|
|
32
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [anchorEl ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(RubberbandTooltip_1.default, { side: "left", anchorEl: anchorEl, text: leftBpOffset.map((l, idx) => ((0, jsx_runtime_1.jsx)("div", { children: (0, util_1.stringify)(l, true) },
|
|
32
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [anchorEl ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(RubberbandTooltip_1.default, { side: "left", anchorEl: anchorEl, text: leftBpOffset.map((l, idx) => ((0, jsx_runtime_1.jsx)("div", { children: (0, util_1.stringify)(l, true) }, `${JSON.stringify(l)}-left-${idx}`))) }), (0, jsx_runtime_1.jsx)(RubberbandTooltip_1.default, { side: "right", anchorEl: anchorEl, text: rightBpOffset.map((l, idx) => ((0, jsx_runtime_1.jsx)("div", { children: (0, util_1.stringify)(l, true) }, `${JSON.stringify(l)}-right-${idx}`))) })] })) : null, (0, jsx_runtime_1.jsx)("div", { className: classes.rubberband, style: { left, width }, children: numOfBpSelected ? ((0, jsx_runtime_1.jsx)(material_1.Typography, { ref: el => {
|
|
33
33
|
setAnchorEl(el);
|
|
34
34
|
}, variant: "h6", className: classes.rubberbandText, style: {
|
|
35
35
|
top,
|
|
36
36
|
position: sticky ? 'sticky' : undefined,
|
|
37
|
-
}, children: numOfBpSelected.map((n, i) => ((0, jsx_runtime_1.jsx)("div", { children: (0, util_1.getBpDisplayStr)(n) }, i))) })) : null })] }));
|
|
37
|
+
}, children: numOfBpSelected.map((n, i) => ((0, jsx_runtime_1.jsx)("div", { children: (0, util_1.getBpDisplayStr)(n) }, `bpSelectedRow-${i}`))) })) : null })] }));
|
|
38
38
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = SliderTooltip;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const material_1 = require("@mui/material");
|
|
6
|
+
function SliderTooltip(props) {
|
|
7
|
+
const { children, open, value } = props;
|
|
8
|
+
return ((0, jsx_runtime_1.jsx)(material_1.Tooltip, { open: open, enterTouchDelay: 0, placement: "top", title: value, arrow: true, children: children }));
|
|
9
|
+
}
|
|
@@ -10,6 +10,11 @@ function useRangeSelect(ref, model) {
|
|
|
10
10
|
const [anchorPosition, setAnchorPosition] = (0, react_1.useState)();
|
|
11
11
|
const [guideX, setGuideX] = (0, react_1.useState)();
|
|
12
12
|
const mouseDragging = startX !== undefined && anchorPosition === undefined;
|
|
13
|
+
const handleClose = (0, react_1.useCallback)(() => {
|
|
14
|
+
setAnchorPosition(undefined);
|
|
15
|
+
setStartX(undefined);
|
|
16
|
+
setCurrentX(undefined);
|
|
17
|
+
}, []);
|
|
13
18
|
(0, react_1.useEffect)(() => {
|
|
14
19
|
function computeOffsets(offsetX) {
|
|
15
20
|
if (startX === undefined) {
|
|
@@ -32,6 +37,10 @@ function useRangeSelect(ref, model) {
|
|
|
32
37
|
if (startX !== undefined && ref.current) {
|
|
33
38
|
const { clientX, clientY } = event;
|
|
34
39
|
const offsetX = (0, util_1.getRelativeX)(event, ref.current);
|
|
40
|
+
if (Math.abs(offsetX - startX) <= 3) {
|
|
41
|
+
handleClose();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
35
44
|
setAnchorPosition({
|
|
36
45
|
offsetX,
|
|
37
46
|
clientX,
|
|
@@ -57,15 +66,7 @@ function useRangeSelect(ref, model) {
|
|
|
57
66
|
};
|
|
58
67
|
}
|
|
59
68
|
return () => { };
|
|
60
|
-
}, [startX, mouseDragging, model, ref]);
|
|
61
|
-
(0, react_1.useEffect)(() => {
|
|
62
|
-
if (!mouseDragging &&
|
|
63
|
-
currentX !== undefined &&
|
|
64
|
-
startX !== undefined &&
|
|
65
|
-
Math.abs(currentX - startX) <= 3) {
|
|
66
|
-
handleClose();
|
|
67
|
-
}
|
|
68
|
-
}, [mouseDragging, currentX, startX]);
|
|
69
|
+
}, [startX, mouseDragging, model, ref, handleClose]);
|
|
69
70
|
function mouseDown(event) {
|
|
70
71
|
event.preventDefault();
|
|
71
72
|
event.stopPropagation();
|
|
@@ -84,11 +85,6 @@ function useRangeSelect(ref, model) {
|
|
|
84
85
|
}
|
|
85
86
|
});
|
|
86
87
|
}
|
|
87
|
-
function handleClose() {
|
|
88
|
-
setAnchorPosition(undefined);
|
|
89
|
-
setStartX(undefined);
|
|
90
|
-
setCurrentX(undefined);
|
|
91
|
-
}
|
|
92
88
|
function handleMenuItemClick(_, callback) {
|
|
93
89
|
callback();
|
|
94
90
|
handleClose();
|
|
@@ -13,6 +13,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
13
13
|
showIntraviewLinks: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
14
14
|
linkViews: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
15
15
|
interactiveOverlay: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
16
|
+
showDynamicControls: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
16
17
|
levels: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
|
|
17
18
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
18
19
|
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
@@ -78,8 +79,8 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
78
79
|
readonly interRegionPaddingWidth: number;
|
|
79
80
|
readonly assemblyNames: string[];
|
|
80
81
|
readonly assemblyDisplayNames: string[];
|
|
81
|
-
readonly isTopLevelView:
|
|
82
|
-
readonly stickyViewHeaders: boolean
|
|
82
|
+
readonly isTopLevelView: boolean;
|
|
83
|
+
readonly stickyViewHeaders: boolean;
|
|
83
84
|
readonly rubberbandTop: number;
|
|
84
85
|
readonly pinnedTracksTop: number;
|
|
85
86
|
} & {
|
|
@@ -303,6 +304,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
303
304
|
removeView(view: LinearGenomeViewModel): void;
|
|
304
305
|
setLevelHeight(newHeight: number, level?: number): number;
|
|
305
306
|
setLinkViews(arg: boolean): void;
|
|
307
|
+
setShowDynamicControls(arg: boolean): void;
|
|
306
308
|
activateTrackSelector(level: number): import("@jbrowse/core/util").Widget;
|
|
307
309
|
toggleTrack(trackId: string, level?: number): void;
|
|
308
310
|
showTrack(trackId: string, level?: number, initialSnapshot?: {}): void;
|
|
@@ -330,6 +332,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
330
332
|
showIntraviewLinks: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
331
333
|
linkViews: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
332
334
|
interactiveOverlay: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
335
|
+
showDynamicControls: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
333
336
|
levels: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
|
|
334
337
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
335
338
|
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
@@ -395,8 +398,8 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
395
398
|
readonly interRegionPaddingWidth: number;
|
|
396
399
|
readonly assemblyNames: string[];
|
|
397
400
|
readonly assemblyDisplayNames: string[];
|
|
398
|
-
readonly isTopLevelView:
|
|
399
|
-
readonly stickyViewHeaders: boolean
|
|
401
|
+
readonly isTopLevelView: boolean;
|
|
402
|
+
readonly stickyViewHeaders: boolean;
|
|
400
403
|
readonly rubberbandTop: number;
|
|
401
404
|
readonly pinnedTracksTop: number;
|
|
402
405
|
} & {
|
|
@@ -55,6 +55,7 @@ function stateModelFactory(pluginManager) {
|
|
|
55
55
|
showIntraviewLinks: true,
|
|
56
56
|
linkViews: false,
|
|
57
57
|
interactiveOverlay: false,
|
|
58
|
+
showDynamicControls: true,
|
|
58
59
|
levels: mobx_state_tree_1.types.array(LinearSyntenyViewHelper),
|
|
59
60
|
views: mobx_state_tree_1.types.array(pluginManager.getViewType('LinearGenomeView')
|
|
60
61
|
.stateModel),
|
|
@@ -131,6 +132,9 @@ function stateModelFactory(pluginManager) {
|
|
|
131
132
|
setLinkViews(arg) {
|
|
132
133
|
self.linkViews = arg;
|
|
133
134
|
},
|
|
135
|
+
setShowDynamicControls(arg) {
|
|
136
|
+
self.showDynamicControls = arg;
|
|
137
|
+
},
|
|
134
138
|
activateTrackSelector(level) {
|
|
135
139
|
if (self.trackSelectorType === 'hierarchical') {
|
|
136
140
|
const session = (0, util_1.getSession)(self);
|
|
@@ -20,11 +20,12 @@ function doAfterAttach(self) {
|
|
|
20
20
|
if (!ctx1 || !ctx3) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
+
const { alpha } = self;
|
|
23
24
|
const height = self.height;
|
|
24
25
|
const width = view.width;
|
|
25
26
|
ctx1.clearRect(0, 0, width, height);
|
|
26
|
-
|
|
27
|
-
(0, drawSynteny_1.
|
|
27
|
+
(0, drawSynteny_1.drawRef)(self, ctx1);
|
|
28
|
+
(0, drawSynteny_1.drawCigarClickMap)(self, ctx3);
|
|
28
29
|
}));
|
|
29
30
|
(0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(() => {
|
|
30
31
|
const view = (0, util_1.getContainingView)(self);
|
|
@@ -32,7 +33,8 @@ function doAfterAttach(self) {
|
|
|
32
33
|
!view.views.every(a => a.displayedRegions.length > 0 && a.initialized)) {
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
const { clickId, mouseoverId } = self;
|
|
37
|
+
(0, drawSynteny_1.drawMouseoverClickMap)(self);
|
|
36
38
|
}));
|
|
37
39
|
(0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.reaction)(() => {
|
|
38
40
|
const view = (0, util_1.getContainingView)(self);
|
|
@@ -189,11 +189,16 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
189
189
|
const { f, cigar } = model.featPositions[id];
|
|
190
190
|
const unitMultiplier2 = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / cigar.length);
|
|
191
191
|
const cigarIdx = (0, drawSynteny_1.getId)(r2, g2, b2, unitMultiplier2);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
192
|
+
if (cigarIdx % 2 === 0 && (r2 !== 0 || g2 !== 0 || b2 !== 0)) {
|
|
193
|
+
setTooltip((0, util_2.getTooltip)({
|
|
194
|
+
feature: f,
|
|
195
|
+
cigarOp: cigar[cigarIdx + 1],
|
|
196
|
+
cigarOpLen: cigar[cigarIdx],
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
setTooltip('');
|
|
201
|
+
}
|
|
197
202
|
}
|
|
198
203
|
}
|
|
199
204
|
}, onMouseLeave: () => {
|
|
@@ -32,13 +32,14 @@ export declare function drawMatchSimple({ feature, ctx, offsets, level, cb, heig
|
|
|
32
32
|
hideTiny?: boolean;
|
|
33
33
|
}): void;
|
|
34
34
|
export declare function draw(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number, drawCurves?: boolean): void;
|
|
35
|
+
export declare function drawLocationMarkers(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number, bpPerPx1: number, bpPerPx2: number, drawCurves?: boolean): void;
|
|
35
36
|
export declare function drawBox(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number): void;
|
|
36
37
|
export declare function drawBezierBox(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number): void;
|
|
37
38
|
export declare function onSynClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel): import("../model").FeatPos | undefined;
|
|
38
39
|
export declare function onSynContextClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel, setAnchorEl: (arg: ClickCoord) => void): void;
|
|
39
40
|
export declare function getTooltip({ feature, cigarOp, cigarOpLen, }: {
|
|
40
41
|
feature: Feature;
|
|
41
|
-
cigarOp?: string;
|
|
42
42
|
cigarOpLen?: string;
|
|
43
|
+
cigarOp?: string;
|
|
43
44
|
}): string;
|
|
44
45
|
export {};
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.drawMatchSimple = drawMatchSimple;
|
|
4
4
|
exports.draw = draw;
|
|
5
|
+
exports.drawLocationMarkers = drawLocationMarkers;
|
|
5
6
|
exports.drawBox = drawBox;
|
|
6
7
|
exports.drawBezierBox = drawBezierBox;
|
|
7
8
|
exports.onSynClick = onSynClick;
|
|
@@ -51,6 +52,42 @@ function draw(ctx, x1, x2, y1, x3, x4, y2, mid, drawCurves) {
|
|
|
51
52
|
drawBox(ctx, x1, x2, y1, x3, x4, y2);
|
|
52
53
|
}
|
|
53
54
|
}
|
|
55
|
+
function drawLocationMarkers(ctx, x1, x2, y1, x3, x4, y2, mid, bpPerPx1, bpPerPx2, drawCurves) {
|
|
56
|
+
const width1 = Math.abs(x2 - x1);
|
|
57
|
+
const width2 = Math.abs(x4 - x3);
|
|
58
|
+
const averageWidth = (width1 + width2) / 2;
|
|
59
|
+
if (averageWidth < 30) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const targetPixelSpacing = 20;
|
|
63
|
+
const numMarkers = Math.max(2, Math.floor(averageWidth / targetPixelSpacing) + 1);
|
|
64
|
+
const prevStrokeStyle = ctx.strokeStyle;
|
|
65
|
+
const prevLineWidth = ctx.lineWidth;
|
|
66
|
+
ctx.strokeStyle = 'rgba(0, 0, 0, 0.25)';
|
|
67
|
+
ctx.lineWidth = 0.5;
|
|
68
|
+
ctx.beginPath();
|
|
69
|
+
if (drawCurves) {
|
|
70
|
+
for (let step = 0; step < numMarkers; step++) {
|
|
71
|
+
const t = step / numMarkers;
|
|
72
|
+
const topX = x1 + (x2 - x1) * t;
|
|
73
|
+
const bottomX = x4 + (x3 - x4) * t;
|
|
74
|
+
ctx.moveTo(topX, y1);
|
|
75
|
+
ctx.bezierCurveTo(topX, mid, bottomX, mid, bottomX, y2);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
for (let step = 0; step < numMarkers; step++) {
|
|
80
|
+
const t = step / numMarkers;
|
|
81
|
+
const topX = x1 + (x2 - x1) * t;
|
|
82
|
+
const bottomX = x4 + (x3 - x4) * t;
|
|
83
|
+
ctx.moveTo(topX, y1);
|
|
84
|
+
ctx.lineTo(bottomX, y2);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
ctx.stroke();
|
|
88
|
+
ctx.strokeStyle = prevStrokeStyle;
|
|
89
|
+
ctx.lineWidth = prevLineWidth;
|
|
90
|
+
}
|
|
54
91
|
function drawBox(ctx, x1, x2, y1, x3, x4, y2) {
|
|
55
92
|
ctx.beginPath();
|
|
56
93
|
ctx.moveTo(x1, y1);
|
|
@@ -131,7 +168,11 @@ function onSynContextClick(event, model, setAnchorEl) {
|
|
|
131
168
|
const f = model.featPositions[id];
|
|
132
169
|
if (f) {
|
|
133
170
|
model.setClickId(f.f.id());
|
|
134
|
-
setAnchorEl({
|
|
171
|
+
setAnchorEl({
|
|
172
|
+
clientX,
|
|
173
|
+
clientY,
|
|
174
|
+
feature: f,
|
|
175
|
+
});
|
|
135
176
|
}
|
|
136
177
|
}
|
|
137
178
|
function getTooltip({ feature, cigarOp, cigarOpLen, }) {
|
|
@@ -149,7 +190,7 @@ function getTooltip({ feature, cigarOp, cigarOpLen, }) {
|
|
|
149
190
|
`Query len: ${l1.toLocaleString('en-US')}`,
|
|
150
191
|
`Target len: ${l2.toLocaleString('en-US')}`,
|
|
151
192
|
identity ? `Identity: ${identity.toPrecision(2)}` : '',
|
|
152
|
-
cigarOp ? `CIGAR operator: ${
|
|
193
|
+
cigarOp ? `CIGAR operator: ${(0, util_1.toLocale)(+cigarOpLen)}${cigarOp}` : '',
|
|
153
194
|
n1 ? `Name 1: ${n1}` : '',
|
|
154
195
|
n2 ? `Name 2: ${n2}` : '',
|
|
155
196
|
]
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LinearSyntenyDisplayModel } from './model';
|
|
2
2
|
export declare const MAX_COLOR_RANGE: number;
|
|
3
3
|
export declare function getId(r: number, g: number, b: number, unitMultiplier: number): number;
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
4
|
+
export declare function drawCigarClickMap(model: LinearSyntenyDisplayModel, cigarClickMapCanvas: CanvasRenderingContext2D): void;
|
|
5
|
+
export declare function drawRef(model: LinearSyntenyDisplayModel, mainCanvas: CanvasRenderingContext2D): void;
|
|
6
|
+
export declare function drawMouseoverClickMap(model: LinearSyntenyDisplayModel): void;
|