@jbrowse/plugin-dotplot-view 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/ComparativeRenderer/index.d.ts +2 -2
- package/dist/DotplotDisplay/index.js +0 -1
- package/dist/DotplotDisplay/stateModelFactory.d.ts +3 -5
- package/dist/DotplotDisplay/stateModelFactory.js +0 -1
- package/dist/DotplotReadVsRef/index.js +3 -1
- package/dist/DotplotRenderer/ComparativeRenderRpc.d.ts +2 -2
- package/dist/DotplotRenderer/DotplotRenderer.d.ts +1 -0
- package/dist/DotplotRenderer/DotplotRenderer.js +4 -3
- package/dist/DotplotView/1dview.js +0 -2
- package/dist/DotplotView/components/Axes.js +1 -1
- package/dist/DotplotView/components/DotplotControls.js +30 -10
- package/dist/DotplotView/components/DotplotTooltip.js +2 -2
- package/dist/DotplotView/components/DotplotView.js +15 -27
- package/dist/DotplotView/components/DotplotWarnings.js +9 -3
- package/dist/DotplotView/components/ExportSvgDialog.js +13 -5
- package/dist/DotplotView/components/Grid.js +2 -2
- package/dist/DotplotView/components/ImportForm/ImportCustomTrack.js +14 -4
- package/dist/DotplotView/components/ImportForm/ImportSyntenyTrackSelector.js +3 -1
- package/dist/DotplotView/components/ImportForm/index.js +9 -3
- package/dist/DotplotView/components/WarningDialog.js +4 -3
- package/dist/DotplotView/components/util.js +4 -2
- package/dist/DotplotView/model.d.ts +1 -7
- package/dist/DotplotView/model.js +12 -13
- package/dist/DotplotView/svgcomponents/SVGDotplotView.js +3 -2
- package/dist/LaunchDotplotView.js +4 -2
- package/dist/ServerSideRenderedBlockContent.js +7 -3
- package/dist/ServerSideSyntenyRendering.d.ts +2 -2
- package/dist/ServerSideSyntenyRendering.js +1 -1
- package/esm/ComparativeRenderer/index.d.ts +2 -2
- package/esm/DotplotDisplay/index.js +0 -1
- package/esm/DotplotDisplay/stateModelFactory.d.ts +3 -5
- package/esm/DotplotDisplay/stateModelFactory.js +0 -1
- package/esm/DotplotReadVsRef/index.js +3 -1
- package/esm/DotplotRenderer/ComparativeRenderRpc.d.ts +2 -2
- package/esm/DotplotRenderer/DotplotRenderer.d.ts +1 -0
- package/esm/DotplotRenderer/DotplotRenderer.js +4 -3
- package/esm/DotplotView/1dview.js +0 -2
- package/esm/DotplotView/components/Axes.js +1 -1
- package/esm/DotplotView/components/DotplotControls.js +30 -10
- package/esm/DotplotView/components/DotplotTooltip.js +2 -2
- package/esm/DotplotView/components/DotplotView.js +15 -27
- package/esm/DotplotView/components/DotplotWarnings.js +9 -3
- package/esm/DotplotView/components/ExportSvgDialog.js +13 -5
- package/esm/DotplotView/components/Grid.js +2 -2
- package/esm/DotplotView/components/ImportForm/ImportCustomTrack.js +14 -4
- package/esm/DotplotView/components/ImportForm/ImportSyntenyTrackSelector.js +3 -1
- package/esm/DotplotView/components/ImportForm/index.js +9 -3
- package/esm/DotplotView/components/WarningDialog.js +4 -3
- package/esm/DotplotView/components/util.js +4 -2
- package/esm/DotplotView/model.d.ts +1 -7
- package/esm/DotplotView/model.js +12 -13
- package/esm/DotplotView/svgcomponents/SVGDotplotView.js +3 -2
- package/esm/LaunchDotplotView.js +4 -2
- package/esm/ServerSideRenderedBlockContent.js +7 -3
- package/esm/ServerSideSyntenyRendering.d.ts +2 -2
- package/esm/ServerSideSyntenyRendering.js +1 -1
- package/package.json +5 -5
|
@@ -18,7 +18,9 @@ function LaunchDotplotView(pluginManager) {
|
|
|
18
18
|
});
|
|
19
19
|
// http://localhost:3000/?config=test_data%2Fvolvox%2Fconfig.json&session=spec-{"views":[{"type":"DotplotView","views":[{"assembly":"volvox"},{"assembly":"volvox"}],"tracks":["volvox_fake_synteny"]}]}
|
|
20
20
|
const idsNotFound = [];
|
|
21
|
-
tracks.forEach(track =>
|
|
21
|
+
tracks.forEach(track => {
|
|
22
|
+
tryTrack(model, track, idsNotFound);
|
|
23
|
+
});
|
|
22
24
|
if (idsNotFound.length) {
|
|
23
25
|
throw new Error(`Could not resolve identifiers: ${idsNotFound.join(',')}`);
|
|
24
26
|
}
|
|
@@ -34,7 +36,7 @@ function tryTrack(model, trackId, idsNotFound) {
|
|
|
34
36
|
model.showTrack(trackId);
|
|
35
37
|
}
|
|
36
38
|
catch (e) {
|
|
37
|
-
if (
|
|
39
|
+
if (/Could not resolve identifier/.exec(`${e}`)) {
|
|
38
40
|
idsNotFound.push(trackId);
|
|
39
41
|
}
|
|
40
42
|
else {
|
|
@@ -53,8 +53,12 @@ function LoadingMessage() {
|
|
|
53
53
|
const [shown, setShown] = (0, react_1.useState)(false);
|
|
54
54
|
const { classes } = useStyles();
|
|
55
55
|
(0, react_1.useEffect)(() => {
|
|
56
|
-
const timeout = setTimeout(() =>
|
|
57
|
-
|
|
56
|
+
const timeout = setTimeout(() => {
|
|
57
|
+
setShown(true);
|
|
58
|
+
}, 300);
|
|
59
|
+
return () => {
|
|
60
|
+
clearTimeout(timeout);
|
|
61
|
+
};
|
|
58
62
|
}, []);
|
|
59
63
|
return shown ? (react_1.default.createElement("div", { className: classes.loading },
|
|
60
64
|
react_1.default.createElement(ui_1.LoadingEllipses, null))) : null;
|
|
@@ -62,7 +66,7 @@ function LoadingMessage() {
|
|
|
62
66
|
function BlockMessage({ messageText }) {
|
|
63
67
|
const { classes } = useStyles();
|
|
64
68
|
return (react_1.default.createElement("div", { className: classes.blockMessage },
|
|
65
|
-
react_1.default.createElement(material_1.Typography, null,
|
|
69
|
+
react_1.default.createElement(material_1.Typography, null, messageText)));
|
|
66
70
|
}
|
|
67
71
|
function BlockError({ error }) {
|
|
68
72
|
const { classes } = useStyles();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
/**
|
|
3
|
-
* A block whose content is rendered outside of the main thread and hydrated by
|
|
4
|
-
* component.
|
|
3
|
+
* A block whose content is rendered outside of the main thread and hydrated by
|
|
4
|
+
* this component.
|
|
5
5
|
*/
|
|
6
6
|
interface ModelType {
|
|
7
7
|
imageData: string;
|
|
@@ -39,7 +39,7 @@ const ServerSideSyntenyRendering = (0, mobx_react_1.observer)(function ({ model,
|
|
|
39
39
|
const context = canvas.getContext('2d');
|
|
40
40
|
(0, offscreenCanvasPonyfill_1.drawImageOntoCanvasContext)(imageData, context);
|
|
41
41
|
setDone(true);
|
|
42
|
-
}, [
|
|
42
|
+
}, [imageData]);
|
|
43
43
|
return (react_1.default.createElement("canvas", { "data-testid": `prerendered_canvas${done ? '_done' : ''}`, ref: featureCanvas, width: width * highResolutionScaling, height: height * highResolutionScaling, style: { width, height, ...style } }));
|
|
44
44
|
});
|
|
45
45
|
exports.default = ServerSideSyntenyRendering;
|
|
@@ -2,11 +2,11 @@ import RpcMethodType from '@jbrowse/core/pluggableElementTypes/RpcMethodType';
|
|
|
2
2
|
import ComparativeRenderer, { RenderArgs as ComparativeRenderArgs, RenderArgsSerialized as ComparativeRenderArgsSerialized, RenderResults, ResultsSerialized } from '@jbrowse/core/pluggableElementTypes/renderers/ComparativeServerSideRendererType';
|
|
3
3
|
import { RemoteAbortSignal } from '@jbrowse/core/rpc/remoteAbortSignals';
|
|
4
4
|
interface RenderArgs extends ComparativeRenderArgs {
|
|
5
|
-
adapterConfig:
|
|
5
|
+
adapterConfig: Record<string, unknown>;
|
|
6
6
|
rendererType: string;
|
|
7
7
|
}
|
|
8
8
|
interface RenderArgsSerialized extends ComparativeRenderArgsSerialized {
|
|
9
|
-
adapterConfig:
|
|
9
|
+
adapterConfig: Record<string, unknown>;
|
|
10
10
|
rendererType: string;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
@@ -43,7 +43,7 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
|
|
|
43
43
|
error: unknown;
|
|
44
44
|
message: string | undefined;
|
|
45
45
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
46
|
-
onHorizontalScroll?:
|
|
46
|
+
onHorizontalScroll?: () => void;
|
|
47
47
|
blockState?: Record<string, any>;
|
|
48
48
|
}>;
|
|
49
49
|
readonly DisplayBlurb: React.FC<{
|
|
@@ -56,9 +56,7 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
|
|
|
56
56
|
error: unknown;
|
|
57
57
|
message: string | undefined;
|
|
58
58
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
59
|
-
id: import("mobx-state-tree"
|
|
60
|
-
* #method
|
|
61
|
-
*/).IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
59
|
+
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
62
60
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
63
61
|
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
64
62
|
}, {
|
|
@@ -107,7 +105,7 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
|
|
|
107
105
|
* #method
|
|
108
106
|
*/
|
|
109
107
|
renderSvg(opts: ExportSvgOptions & {
|
|
110
|
-
theme
|
|
108
|
+
theme?: ThemeOptions;
|
|
111
109
|
}): Promise<React.JSX.Element | null>;
|
|
112
110
|
} & {
|
|
113
111
|
afterAttach(): void;
|
|
@@ -2,11 +2,11 @@ import RpcMethodType from '@jbrowse/core/pluggableElementTypes/RpcMethodType';
|
|
|
2
2
|
import ComparativeRenderer, { RenderArgs as ComparativeRenderArgs, RenderArgsSerialized as ComparativeRenderArgsSerialized, RenderResults, ResultsSerialized } from '@jbrowse/core/pluggableElementTypes/renderers/ComparativeServerSideRendererType';
|
|
3
3
|
import { RemoteAbortSignal } from '@jbrowse/core/rpc/remoteAbortSignals';
|
|
4
4
|
interface RenderArgs extends ComparativeRenderArgs {
|
|
5
|
-
adapterConfig:
|
|
5
|
+
adapterConfig: Record<string, unknown>;
|
|
6
6
|
rendererType: string;
|
|
7
7
|
}
|
|
8
8
|
interface RenderArgsSerialized extends ComparativeRenderArgsSerialized {
|
|
9
|
-
adapterConfig:
|
|
9
|
+
adapterConfig: Record<string, unknown>;
|
|
10
10
|
rendererType: string;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
@@ -3,6 +3,7 @@ import { Region } from '@jbrowse/core/util';
|
|
|
3
3
|
import ComparativeRenderer, { RenderArgsDeserialized, RenderArgs } from '@jbrowse/core/pluggableElementTypes/renderers/ComparativeServerSideRendererType';
|
|
4
4
|
import { Dotplot1DViewModel } from '../DotplotView/model';
|
|
5
5
|
export interface DotplotRenderArgsDeserialized extends RenderArgsDeserialized {
|
|
6
|
+
adapterConfig: AnyConfigurationModel;
|
|
6
7
|
height: number;
|
|
7
8
|
width: number;
|
|
8
9
|
highResolutionScaling: number;
|
|
@@ -53,7 +53,8 @@ export default class DotplotRenderer extends ComparativeRenderer {
|
|
|
53
53
|
const thresholds = readConfObject(config, 'thresholds');
|
|
54
54
|
const palette = readConfObject(config, 'thresholdsPalette');
|
|
55
55
|
const isCallback = config.color.isCallback;
|
|
56
|
-
const
|
|
56
|
+
const hview = views[0];
|
|
57
|
+
const vview = views[1];
|
|
57
58
|
const db1 = (_a = hview.dynamicBlocks.contentBlocks[0]) === null || _a === void 0 ? void 0 : _a.offsetPx;
|
|
58
59
|
const db2 = (_b = vview.dynamicBlocks.contentBlocks[0]) === null || _b === void 0 ? void 0 : _b.offsetPx;
|
|
59
60
|
const warnings = [];
|
|
@@ -134,12 +135,12 @@ export default class DotplotRenderer extends ComparativeRenderer {
|
|
|
134
135
|
const refName = feature.get('refName');
|
|
135
136
|
const mate = feature.get('mate');
|
|
136
137
|
const mateRef = mate.refName;
|
|
137
|
-
let r;
|
|
138
|
+
let r = 'black';
|
|
138
139
|
if (colorBy === 'identity') {
|
|
139
140
|
const identity = feature.get('identity');
|
|
140
141
|
for (let i = 0; i < thresholds.length; i++) {
|
|
141
142
|
if (identity > +thresholds[i]) {
|
|
142
|
-
r = palette[i];
|
|
143
|
+
r = palette[i] || 'black';
|
|
143
144
|
break;
|
|
144
145
|
}
|
|
145
146
|
}
|
|
@@ -70,7 +70,6 @@ const Dotplot1DView = Base1DView.extend(self => {
|
|
|
70
70
|
const DotplotHView = Dotplot1DView.extend(self => ({
|
|
71
71
|
views: {
|
|
72
72
|
get width() {
|
|
73
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
74
73
|
return getParent(self).viewWidth;
|
|
75
74
|
},
|
|
76
75
|
},
|
|
@@ -78,7 +77,6 @@ const DotplotHView = Dotplot1DView.extend(self => ({
|
|
|
78
77
|
const DotplotVView = Dotplot1DView.extend(self => ({
|
|
79
78
|
views: {
|
|
80
79
|
get width() {
|
|
81
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
80
|
return getParent(self).viewHeight;
|
|
83
81
|
},
|
|
84
82
|
},
|
|
@@ -64,7 +64,7 @@ export const HorizontalAxisRaw = observer(function ({ model, }) {
|
|
|
64
64
|
ticks.map(([tick, x]) => x > 0 && x < width ? (React.createElement("line", { key: `line-${JSON.stringify(tick)}`, x1: x, x2: x, y1: 0, y2: tick.type === 'major' ? 6 : 4, strokeWidth: 1, ...getFillProps(theme.palette.text.primary) })) : null),
|
|
65
65
|
ticks
|
|
66
66
|
.filter(t => t[0].type === 'major')
|
|
67
|
-
.map(([tick, x]) => x > 10 && x < width ? (React.createElement("text", { x: x - 7, y: 0, transform: `rotate(${htextRotation},${x}
|
|
67
|
+
.map(([tick, x]) => x > 10 && x < width ? (React.createElement("text", { x: x - 7, y: 0, transform: `rotate(${htextRotation},${x},0)`, key: `text-${JSON.stringify(tick)}`, fontSize: 11, dominantBaseline: "middle", textAnchor: "end", ...getFillProps(theme.palette.text.primary) }, getTickDisplayStr(tick.base + 1, bpPerPx))) : null),
|
|
68
68
|
React.createElement("text", { y: borderY - 12, x: (viewWidth - borderX) / 2, textAnchor: "middle", fontSize: 11, dominantBaseline: "hanging", ...getFillProps(theme.palette.text.primary) }, hview.assemblyNames.join(','))));
|
|
69
69
|
});
|
|
70
70
|
export const VerticalAxis = observer(function ({ model, }) {
|
|
@@ -18,25 +18,35 @@ const DotplotControls = observer(function ({ model, }) {
|
|
|
18
18
|
React.createElement(TrackSelectorIcon, null)),
|
|
19
19
|
React.createElement(CascadingMenuButton, { menuItems: [
|
|
20
20
|
{
|
|
21
|
-
onClick: () =>
|
|
21
|
+
onClick: () => {
|
|
22
|
+
model.squareView();
|
|
23
|
+
},
|
|
22
24
|
label: 'Square view - same base pairs per pixel',
|
|
23
25
|
},
|
|
24
26
|
{
|
|
25
|
-
onClick: () =>
|
|
27
|
+
onClick: () => {
|
|
28
|
+
model.squareViewProportional();
|
|
29
|
+
},
|
|
26
30
|
label: 'Rectanglularize view - same total bp',
|
|
27
31
|
},
|
|
28
32
|
{
|
|
29
|
-
onClick: () =>
|
|
33
|
+
onClick: () => {
|
|
34
|
+
model.showAllRegions();
|
|
35
|
+
},
|
|
30
36
|
label: 'Show all regions',
|
|
31
37
|
},
|
|
32
38
|
{
|
|
33
|
-
onClick: () =>
|
|
39
|
+
onClick: () => {
|
|
40
|
+
model.setDrawCigar(!model.drawCigar);
|
|
41
|
+
},
|
|
34
42
|
type: 'checkbox',
|
|
35
43
|
label: 'Draw CIGAR',
|
|
36
44
|
checked: model.drawCigar,
|
|
37
45
|
},
|
|
38
46
|
{
|
|
39
|
-
onClick: () =>
|
|
47
|
+
onClick: () => {
|
|
48
|
+
model.setShowPanButtons(!model.showPanButtons);
|
|
49
|
+
},
|
|
40
50
|
label: 'Show pan buttons',
|
|
41
51
|
type: 'checkbox',
|
|
42
52
|
checked: model.showPanButtons,
|
|
@@ -45,14 +55,18 @@ const DotplotControls = observer(function ({ model, }) {
|
|
|
45
55
|
label: 'Click and drag mode',
|
|
46
56
|
subMenu: [
|
|
47
57
|
{
|
|
48
|
-
onClick: () =>
|
|
58
|
+
onClick: () => {
|
|
59
|
+
model.setCursorMode('move');
|
|
60
|
+
},
|
|
49
61
|
label: 'Pan by default, select region when ctrl/cmd key is held',
|
|
50
62
|
icon: CursorMove,
|
|
51
63
|
type: 'radio',
|
|
52
64
|
checked: model.cursorMode === 'move',
|
|
53
65
|
},
|
|
54
66
|
{
|
|
55
|
-
onClick: () =>
|
|
67
|
+
onClick: () => {
|
|
68
|
+
model.setCursorMode('crosshair');
|
|
69
|
+
},
|
|
56
70
|
label: 'Select region by default, pan when ctrl/cmd key is held',
|
|
57
71
|
icon: CursorMouse,
|
|
58
72
|
type: 'radio',
|
|
@@ -64,19 +78,25 @@ const DotplotControls = observer(function ({ model, }) {
|
|
|
64
78
|
label: 'Wheel scroll mode',
|
|
65
79
|
subMenu: [
|
|
66
80
|
{
|
|
67
|
-
onClick: () =>
|
|
81
|
+
onClick: () => {
|
|
82
|
+
model.setWheelMode('pan');
|
|
83
|
+
},
|
|
68
84
|
label: 'Pans view',
|
|
69
85
|
type: 'radio',
|
|
70
86
|
checked: model.wheelMode === 'pan',
|
|
71
87
|
},
|
|
72
88
|
{
|
|
73
|
-
onClick: () =>
|
|
89
|
+
onClick: () => {
|
|
90
|
+
model.setWheelMode('zoom');
|
|
91
|
+
},
|
|
74
92
|
label: 'Zooms view',
|
|
75
93
|
type: 'radio',
|
|
76
94
|
checked: model.wheelMode === 'zoom',
|
|
77
95
|
},
|
|
78
96
|
{
|
|
79
|
-
onClick: () =>
|
|
97
|
+
onClick: () => {
|
|
98
|
+
model.setWheelMode('none');
|
|
99
|
+
},
|
|
80
100
|
label: 'Disable',
|
|
81
101
|
type: 'radio',
|
|
82
102
|
checked: model.wheelMode === 'none',
|
|
@@ -40,7 +40,7 @@ export const TooltipWhereMouseovered = observer(function ({ model, mouserect, mo
|
|
|
40
40
|
}
|
|
41
41
|
: undefined);
|
|
42
42
|
const { getFloatingProps } = useInteractions([clientPoint]);
|
|
43
|
-
const popperTheme = (_a = theme
|
|
43
|
+
const popperTheme = (_a = theme.components) === null || _a === void 0 ? void 0 : _a.MuiPopper;
|
|
44
44
|
return mouserect ? (React.createElement(Portal, { container: (_b = popperTheme === null || popperTheme === void 0 ? void 0 : popperTheme.defaultProps) === null || _b === void 0 ? void 0 : _b.container },
|
|
45
45
|
React.createElement("div", { className: classes.tooltip, ref: refs.setFloating, style: {
|
|
46
46
|
...floatingStyles,
|
|
@@ -64,7 +64,7 @@ export const TooltipWhereClicked = observer(function ({ model, mousedown, moused
|
|
|
64
64
|
});
|
|
65
65
|
const clientPoint = useClientPoint(context, { x, y });
|
|
66
66
|
const { getFloatingProps } = useInteractions([clientPoint]);
|
|
67
|
-
const popperTheme = (_a = theme
|
|
67
|
+
const popperTheme = (_a = theme.components) === null || _a === void 0 ? void 0 : _a.MuiPopper;
|
|
68
68
|
return mousedown && Math.abs(xdistance) > 3 && Math.abs(ydistance) > 3 ? (React.createElement(Portal, { container: (_b = popperTheme === null || popperTheme === void 0 ? void 0 : popperTheme.defaultProps) === null || _b === void 0 ? void 0 : _b.container },
|
|
69
69
|
React.createElement("div", { className: classes.tooltip, ref: refs.setFloating, style: {
|
|
70
70
|
...floatingStyles,
|
|
@@ -122,7 +122,9 @@ const DotplotViewInternal = observer(function ({ model, }) {
|
|
|
122
122
|
if (ref.current) {
|
|
123
123
|
const curr = ref.current;
|
|
124
124
|
curr.addEventListener('wheel', onWheel);
|
|
125
|
-
return () =>
|
|
125
|
+
return () => {
|
|
126
|
+
curr.removeEventListener('wheel', onWheel);
|
|
127
|
+
};
|
|
126
128
|
}
|
|
127
129
|
return () => { };
|
|
128
130
|
}, [hview, vview, wheelMode, mousecurr, rootRect.height]);
|
|
@@ -135,17 +137,10 @@ const DotplotViewInternal = observer(function ({ model, }) {
|
|
|
135
137
|
}
|
|
136
138
|
}
|
|
137
139
|
window.addEventListener('mousemove', globalMouseMove);
|
|
138
|
-
return () =>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
mousedownClient,
|
|
143
|
-
cursorMode,
|
|
144
|
-
ctrlKeyWasUsed,
|
|
145
|
-
mouseupClient,
|
|
146
|
-
hview,
|
|
147
|
-
vview,
|
|
148
|
-
]);
|
|
140
|
+
return () => {
|
|
141
|
+
window.removeEventListener('mousemove', globalMouseMove);
|
|
142
|
+
};
|
|
143
|
+
}, [validPan, mousecurrClient, mousedownClient, mouseupClient, hview, vview]);
|
|
149
144
|
useEffect(() => {
|
|
150
145
|
function globalCtrlKeyDown(event) {
|
|
151
146
|
if (event.metaKey || event.ctrlKey) {
|
|
@@ -181,19 +176,8 @@ const DotplotViewInternal = observer(function ({ model, }) {
|
|
|
181
176
|
window.removeEventListener('mouseup', globalMouseUp, true);
|
|
182
177
|
};
|
|
183
178
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
}, [
|
|
188
|
-
validSelect,
|
|
189
|
-
mousedown,
|
|
190
|
-
mousecurr,
|
|
191
|
-
mouseup,
|
|
192
|
-
xdistance,
|
|
193
|
-
ydistance,
|
|
194
|
-
ctrlKeyWasUsed,
|
|
195
|
-
cursorMode,
|
|
196
|
-
]);
|
|
179
|
+
return () => { };
|
|
180
|
+
}, [validSelect, mousedown, mouseup, xdistance, ydistance]);
|
|
197
181
|
return (React.createElement("div", null,
|
|
198
182
|
React.createElement(Header, { model: model, selection: !validSelect || !(mousedown && mouserect)
|
|
199
183
|
? undefined
|
|
@@ -201,7 +185,11 @@ const DotplotViewInternal = observer(function ({ model, }) {
|
|
|
201
185
|
width: Math.abs(xdistance),
|
|
202
186
|
height: Math.abs(ydistance),
|
|
203
187
|
} }),
|
|
204
|
-
React.createElement("div", { ref: root, className: classes.root, onMouseLeave: () =>
|
|
188
|
+
React.createElement("div", { ref: root, className: classes.root, onMouseLeave: () => {
|
|
189
|
+
setMouseOvered(false);
|
|
190
|
+
}, onMouseEnter: () => {
|
|
191
|
+
setMouseOvered(true);
|
|
192
|
+
} },
|
|
205
193
|
React.createElement("div", { className: classes.container },
|
|
206
194
|
React.createElement(VerticalAxis, { model: model }),
|
|
207
195
|
React.createElement(HorizontalAxis, { model: model }),
|
|
@@ -255,7 +243,7 @@ const DotplotViewInternal = observer(function ({ model, }) {
|
|
|
255
243
|
] })),
|
|
256
244
|
React.createElement(ResizeHandle, { onDrag: n => model.setHeight(model.height + n), className: classes.resizeHandle }))));
|
|
257
245
|
});
|
|
258
|
-
const DotplotView = observer(({ model })
|
|
246
|
+
const DotplotView = observer(function ({ model }) {
|
|
259
247
|
const { initialized, loading, error } = model;
|
|
260
248
|
if ((!initialized && !loading) || error) {
|
|
261
249
|
return React.createElement(ImportForm, { model: model });
|
|
@@ -10,8 +10,14 @@ const DotplotWarnings = observer(function ({ model, }) {
|
|
|
10
10
|
return trackWarnings.length && !hide ? (React.createElement(Alert, { severity: "warning" },
|
|
11
11
|
"Warnings during render",
|
|
12
12
|
' ',
|
|
13
|
-
React.createElement(Button, { onClick: () =>
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
React.createElement(Button, { onClick: () => {
|
|
14
|
+
setShown(true);
|
|
15
|
+
} }, "More info"),
|
|
16
|
+
shown ? (React.createElement(WarningDialog, { trackWarnings: trackWarnings, handleClose: () => {
|
|
17
|
+
setShown(false);
|
|
18
|
+
} })) : null,
|
|
19
|
+
React.createElement(Button, { variant: "contained", onClick: () => {
|
|
20
|
+
setHide(true);
|
|
21
|
+
} }, "Dismiss"))) : null;
|
|
16
22
|
});
|
|
17
23
|
export default DotplotWarnings;
|
|
@@ -12,7 +12,7 @@ function TextField2({ children, ...rest }) {
|
|
|
12
12
|
React.createElement(TextField, { ...rest }, children)));
|
|
13
13
|
}
|
|
14
14
|
function useSvgLocal(key, val) {
|
|
15
|
-
return useLocalStorage(
|
|
15
|
+
return useLocalStorage(`svg-${key}`, val);
|
|
16
16
|
}
|
|
17
17
|
export default function ExportSvgDialog({ model, handleClose, }) {
|
|
18
18
|
const session = getSession(model);
|
|
@@ -25,13 +25,21 @@ export default function ExportSvgDialog({ model, handleClose, }) {
|
|
|
25
25
|
return (React.createElement(Dialog, { open: true, onClose: handleClose, title: "Export SVG" },
|
|
26
26
|
React.createElement(DialogContent, null,
|
|
27
27
|
error ? (React.createElement(ErrorMessage, { error: error })) : loading ? (React.createElement(LoadingMessage, null)) : null,
|
|
28
|
-
React.createElement(TextField2, { helperText: "filename", value: filename, onChange: event =>
|
|
29
|
-
|
|
28
|
+
React.createElement(TextField2, { helperText: "filename", value: filename, onChange: event => {
|
|
29
|
+
setFilename(event.target.value);
|
|
30
|
+
} }),
|
|
31
|
+
session.allThemes ? (React.createElement(TextField2, { select: true, label: "Theme", value: themeName, onChange: event => {
|
|
32
|
+
setThemeName(event.target.value);
|
|
33
|
+
} }, Object.entries(session.allThemes()).map(([key, val]) => (React.createElement(MenuItem, { key: key, value: key },
|
|
30
34
|
// @ts-expect-error
|
|
31
35
|
val.name || '(Unknown name)'))))) : null,
|
|
32
|
-
offscreenCanvas ? (React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { checked: rasterizeLayers, onChange: () =>
|
|
36
|
+
offscreenCanvas ? (React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { checked: rasterizeLayers, onChange: () => {
|
|
37
|
+
setRasterizeLayers(val => !val);
|
|
38
|
+
} }), label: "Rasterize canvas based tracks? File may be much larger if this is turned off" })) : (React.createElement(Typography, null, "Note: rasterizing layers not yet supported in this browser, so SVG size may be large"))),
|
|
33
39
|
React.createElement(DialogActions, null,
|
|
34
|
-
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () =>
|
|
40
|
+
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
41
|
+
handleClose();
|
|
42
|
+
} }, "Cancel"),
|
|
35
43
|
React.createElement(Button, { variant: "contained", color: "primary", type: "submit", onClick: async () => {
|
|
36
44
|
setLoading(true);
|
|
37
45
|
setError(undefined);
|
|
@@ -21,8 +21,8 @@ export const GridRaw = observer(function ({ model, children, }) {
|
|
|
21
21
|
const ry = Math.max(viewHeight - vtop, 0);
|
|
22
22
|
const w = Math.min(htop - hbottom, viewWidth);
|
|
23
23
|
const h = Math.min(viewHeight - vbottom - ry, viewHeight);
|
|
24
|
-
let lastx =
|
|
25
|
-
let lasty =
|
|
24
|
+
let lastx = Number.POSITIVE_INFINITY;
|
|
25
|
+
let lasty = Number.POSITIVE_INFINITY;
|
|
26
26
|
return (React.createElement(React.Fragment, null,
|
|
27
27
|
React.createElement("rect", { x: rx, y: ry, width: w, height: h, ...getFillProps(theme.palette.background.default) }),
|
|
28
28
|
React.createElement("g", null,
|
|
@@ -105,7 +105,9 @@ const OpenTrack = observer(({ assembly1, assembly2, setSessionTrackData, }) => {
|
|
|
105
105
|
return (React.createElement(Paper, { style: { padding: 12 } },
|
|
106
106
|
error ? React.createElement(ErrorMessage, { error: error }) : null,
|
|
107
107
|
React.createElement(Typography, { style: { textAlign: 'center' } }, "Add a .paf, .out (MashMap), .delta (Mummer), .chain, .anchors or .anchors.simple (MCScan) file to view in the dotplot. These file types can also be gzipped. The first assembly should be the query sequence (e.g. left column of the PAF) and the second assembly should be the target sequence (e.g. right column of the PAF)"),
|
|
108
|
-
React.createElement(RadioGroup, { value: radioOption, onChange: event =>
|
|
108
|
+
React.createElement(RadioGroup, { value: radioOption, onChange: event => {
|
|
109
|
+
setValue(event.target.value);
|
|
110
|
+
} },
|
|
109
111
|
React.createElement(Grid, { container: true, justifyContent: "center" },
|
|
110
112
|
React.createElement(Grid, { item: true },
|
|
111
113
|
React.createElement(FormControlLabel, { value: ".paf", control: React.createElement(Radio, null), label: ".paf" })),
|
|
@@ -129,10 +131,18 @@ const OpenTrack = observer(({ assembly1, assembly2, setSessionTrackData, }) => {
|
|
|
129
131
|
React.createElement("a", { href: "https://github.com/tanghaibao/jcvi/wiki/MCscan-(Python-version)" }, "(more info)")),
|
|
130
132
|
React.createElement("div", { style: { display: 'flex' } },
|
|
131
133
|
React.createElement("div", null,
|
|
132
|
-
React.createElement(FileSelector, { name: ".anchors file", description: "", location: fileLocation, setLocation: loc =>
|
|
134
|
+
React.createElement(FileSelector, { name: ".anchors file", description: "", location: fileLocation, setLocation: loc => {
|
|
135
|
+
setFileLocation(loc);
|
|
136
|
+
} })),
|
|
133
137
|
React.createElement("div", null,
|
|
134
|
-
React.createElement(FileSelector, { name: "genome 1 .bed (left column of anchors file)", description: "", location: bed1Location, setLocation: loc =>
|
|
138
|
+
React.createElement(FileSelector, { name: "genome 1 .bed (left column of anchors file)", description: "", location: bed1Location, setLocation: loc => {
|
|
139
|
+
setBed1Location(loc);
|
|
140
|
+
} })),
|
|
135
141
|
React.createElement("div", null,
|
|
136
|
-
React.createElement(FileSelector, { name: "genome 2 .bed (right column of anchors file)", description: "", location: bed2Location, setLocation: loc =>
|
|
142
|
+
React.createElement(FileSelector, { name: "genome 2 .bed (right column of anchors file)", description: "", location: bed2Location, setLocation: loc => {
|
|
143
|
+
setBed2Location(loc);
|
|
144
|
+
} }))))) : (React.createElement(FileSelector, { name: value ? `${value} location` : '', description: "", location: fileLocation, setLocation: loc => {
|
|
145
|
+
setFileLocation(loc);
|
|
146
|
+
} }))))));
|
|
137
147
|
});
|
|
138
148
|
export default OpenTrack;
|
|
@@ -41,6 +41,8 @@ const Selector = observer(({ model, assembly1, assembly2, setShowTrackId, }) =>
|
|
|
41
41
|
React.createElement("i", null, "inside"),
|
|
42
42
|
" the DotplotView, which can turn on one or more SyntenyTracks (more than one can be displayed at once). Look for the track selector icon ",
|
|
43
43
|
React.createElement(TrackSelectorIcon, null)),
|
|
44
|
-
filteredTracks.length ? (React.createElement(Select, { value: value, onChange: event =>
|
|
44
|
+
filteredTracks.length ? (React.createElement(Select, { value: value, onChange: event => {
|
|
45
|
+
setValue(event.target.value);
|
|
46
|
+
} }, filteredTracks.map(track => (React.createElement(MenuItem, { key: track.trackId, value: track.trackId }, getTrackName(track, session)))))) : (React.createElement(ErrorMessage, { error: `No synteny tracks found for ${assembly1},${assembly2}` }))));
|
|
45
47
|
});
|
|
46
48
|
export default Selector;
|
|
@@ -28,7 +28,9 @@ function TrackSelector({ setSessionTrackData, setShowTrackId, sessionTrackData,
|
|
|
28
28
|
return (React.createElement(React.Fragment, null,
|
|
29
29
|
React.createElement(FormControl, null,
|
|
30
30
|
React.createElement(FormLabel, { id: "group-label" }, "(Optional) Select or add a synteny track"),
|
|
31
|
-
React.createElement(RadioGroup, { row: true, value: choice, onChange: event =>
|
|
31
|
+
React.createElement(RadioGroup, { row: true, value: choice, onChange: event => {
|
|
32
|
+
setChoice(event.target.value);
|
|
33
|
+
}, "aria-labelledby": "group-label" },
|
|
32
34
|
React.createElement(FormControlLabel, { value: "none", control: React.createElement(Radio, null), label: "None" }),
|
|
33
35
|
React.createElement(FormControlLabel, { value: "tracklist", control: React.createElement(Radio, null), label: "Existing track" }),
|
|
34
36
|
React.createElement(FormControlLabel, { value: "custom", control: React.createElement(Radio, null), label: "New track" }))),
|
|
@@ -81,9 +83,13 @@ const DotplotImportForm = observer(({ model }) => {
|
|
|
81
83
|
React.createElement(Typography, { style: { textAlign: 'center' } }, "Select assemblies for dotplot view"),
|
|
82
84
|
React.createElement(Grid, { container: true, spacing: 1, justifyContent: "center", alignItems: "center" },
|
|
83
85
|
React.createElement(Grid, { item: true },
|
|
84
|
-
React.createElement(AssemblySelector, { selected: assembly1, onChange: val =>
|
|
86
|
+
React.createElement(AssemblySelector, { selected: assembly1, onChange: val => {
|
|
87
|
+
setAssembly1(val);
|
|
88
|
+
}, session: session })),
|
|
85
89
|
React.createElement(Grid, { item: true },
|
|
86
|
-
React.createElement(AssemblySelector, { selected: assembly2, onChange: val =>
|
|
90
|
+
React.createElement(AssemblySelector, { selected: assembly2, onChange: val => {
|
|
91
|
+
setAssembly2(val);
|
|
92
|
+
}, session: session })),
|
|
87
93
|
React.createElement(Grid, { item: true },
|
|
88
94
|
React.createElement(FormControl, null,
|
|
89
95
|
React.createElement(Button, { onClick: onOpenClick, variant: "contained", color: "primary" }, "Launch"))))),
|
|
@@ -17,9 +17,10 @@ const WarningDialog = observer(function WarningDialog({ trackWarnings, handleClo
|
|
|
17
17
|
for (let i = 0; i < trackWarnings.length; i++) {
|
|
18
18
|
const track = trackWarnings[i];
|
|
19
19
|
const name = getConf(track, 'name');
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const d = track.displays[0];
|
|
21
|
+
for (let j = 0; j < d.warnings.length; j++) {
|
|
22
|
+
const warning = d.warnings[j];
|
|
23
|
+
rows.push({ name, ...warning, id: `${i}_${j}` });
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
const columns = [
|
|
@@ -3,7 +3,7 @@ export function locstr(px, view, includeAsm = true) {
|
|
|
3
3
|
const coord = Math.floor(start + offset);
|
|
4
4
|
return oob
|
|
5
5
|
? 'out of bounds'
|
|
6
|
-
: `${includeAsm ?
|
|
6
|
+
: `${includeAsm ? `{${assemblyName}}` : ''}${refName}:${coord.toLocaleString('en-US')}`;
|
|
7
7
|
}
|
|
8
8
|
export function getBlockLabelKeysToHide(blocks, length, viewOffsetPx) {
|
|
9
9
|
const blockLabelKeysToHide = new Set();
|
|
@@ -33,7 +33,9 @@ export function getBlockLabelKeysToHide(blocks, length, viewOffsetPx) {
|
|
|
33
33
|
export function chooseGridPitch(scale, minMajorPitchPx, minMinorPitchPx) {
|
|
34
34
|
scale = Math.abs(scale);
|
|
35
35
|
const minMajorPitchBp = minMajorPitchPx * scale;
|
|
36
|
-
const majorMagnitude = Number
|
|
36
|
+
const majorMagnitude = +Number(minMajorPitchBp)
|
|
37
|
+
.toExponential()
|
|
38
|
+
.split(/e/i)[1];
|
|
37
39
|
let majorPitch = 10 ** majorMagnitude;
|
|
38
40
|
while (majorPitch < minMajorPitchBp) {
|
|
39
41
|
majorPitch *= 2;
|
|
@@ -448,12 +448,6 @@ export default function stateModelFactory(pm: PluginManager): import("mobx-state
|
|
|
448
448
|
* #action
|
|
449
449
|
*/
|
|
450
450
|
setError(e: unknown): void;
|
|
451
|
-
/**
|
|
452
|
-
* #action
|
|
453
|
-
* removes the view itself from the state tree entirely by calling the
|
|
454
|
-
* parent removeView
|
|
455
|
-
*/
|
|
456
|
-
closeView(): void;
|
|
457
451
|
/**
|
|
458
452
|
* #action
|
|
459
453
|
*/
|
|
@@ -552,7 +546,7 @@ export default function stateModelFactory(pm: PluginManager): import("mobx-state
|
|
|
552
546
|
/**
|
|
553
547
|
* #getter
|
|
554
548
|
*/
|
|
555
|
-
readonly error:
|
|
549
|
+
readonly error: unknown;
|
|
556
550
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
|
|
557
551
|
export type DotplotViewStateModel = ReturnType<typeof stateModelFactory>;
|
|
558
552
|
export type DotplotViewModel = Instance<DotplotViewStateModel>;
|