@jbrowse/plugin-linear-comparative-view 2.13.1 → 2.14.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/components/LaunchSyntenyViewDialog.js +9 -3
- package/dist/LGVSyntenyDisplay/components/util.js +4 -3
- package/dist/LGVSyntenyDisplay/model.d.ts +4 -3
- package/dist/LaunchLinearSyntenyView.js +7 -3
- package/dist/LinearComparativeDisplay/configSchemaF.js +0 -1
- package/dist/LinearComparativeDisplay/stateModelFactory.d.ts +3 -3
- package/dist/LinearComparativeDisplay/stateModelFactory.js +2 -2
- package/dist/LinearComparativeView/components/Header.js +6 -2
- package/dist/LinearComparativeView/components/Rubberband.js +9 -9
- package/dist/LinearComparativeView/model.d.ts +9 -16
- package/dist/LinearComparativeView/model.js +10 -14
- package/dist/LinearReadVsRef/LinearReadVsRef.js +6 -4
- package/dist/LinearSyntenyDisplay/afterAttach.js +2 -2
- package/dist/LinearSyntenyDisplay/components/Component.js +6 -2
- package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +29 -15
- package/dist/LinearSyntenyDisplay/components/SyntenyContextMenu.d.ts +4 -1
- package/dist/LinearSyntenyDisplay/components/SyntenyContextMenu.js +2 -6
- package/dist/LinearSyntenyDisplay/components/SyntenyTooltip.js +1 -1
- package/dist/LinearSyntenyDisplay/components/util.d.ts +3 -1
- package/dist/LinearSyntenyDisplay/drawSynteny.d.ts +1 -1
- package/dist/LinearSyntenyDisplay/drawSynteny.js +16 -8
- package/dist/LinearSyntenyDisplay/model.d.ts +9 -5
- package/dist/LinearSyntenyView/components/ExportSvgDialog.js +16 -6
- package/dist/LinearSyntenyView/components/ImportForm/ImportCustomTrack.js +14 -4
- package/dist/LinearSyntenyView/components/ImportForm/ImportSyntenyTrackSelector.js +3 -1
- package/dist/LinearSyntenyView/components/ImportForm/index.js +15 -5
- package/dist/LinearSyntenyView/model.d.ts +9 -11
- package/dist/LinearSyntenyView/model.js +3 -1
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +9 -7
- package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.js +3 -1
- package/dist/util.js +4 -3
- package/esm/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.js +9 -3
- package/esm/LGVSyntenyDisplay/components/util.js +4 -3
- package/esm/LGVSyntenyDisplay/model.d.ts +4 -3
- package/esm/LaunchLinearSyntenyView.js +7 -3
- package/esm/LinearComparativeDisplay/configSchemaF.js +0 -1
- package/esm/LinearComparativeDisplay/stateModelFactory.d.ts +3 -3
- package/esm/LinearComparativeDisplay/stateModelFactory.js +2 -2
- package/esm/LinearComparativeView/components/Header.js +6 -2
- package/esm/LinearComparativeView/components/Rubberband.js +9 -9
- package/esm/LinearComparativeView/model.d.ts +9 -16
- package/esm/LinearComparativeView/model.js +11 -15
- package/esm/LinearReadVsRef/LinearReadVsRef.js +6 -4
- package/esm/LinearSyntenyDisplay/afterAttach.js +2 -2
- package/esm/LinearSyntenyDisplay/components/Component.js +6 -2
- package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +29 -15
- package/esm/LinearSyntenyDisplay/components/SyntenyContextMenu.d.ts +4 -1
- package/esm/LinearSyntenyDisplay/components/SyntenyContextMenu.js +2 -6
- package/esm/LinearSyntenyDisplay/components/SyntenyTooltip.js +1 -1
- package/esm/LinearSyntenyDisplay/components/util.d.ts +3 -1
- package/esm/LinearSyntenyDisplay/drawSynteny.d.ts +1 -1
- package/esm/LinearSyntenyDisplay/drawSynteny.js +16 -8
- package/esm/LinearSyntenyDisplay/model.d.ts +9 -5
- package/esm/LinearSyntenyView/components/ExportSvgDialog.js +16 -6
- package/esm/LinearSyntenyView/components/ImportForm/ImportCustomTrack.js +14 -4
- package/esm/LinearSyntenyView/components/ImportForm/ImportSyntenyTrackSelector.js +3 -1
- package/esm/LinearSyntenyView/components/ImportForm/index.js +15 -5
- package/esm/LinearSyntenyView/model.d.ts +9 -11
- package/esm/LinearSyntenyView/model.js +3 -1
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +9 -7
- package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.js +3 -1
- package/esm/util.js +4 -3
- package/package.json +3 -3
|
@@ -6,14 +6,10 @@ import { stringify } from '@jbrowse/core/util';
|
|
|
6
6
|
import { Menu } from '@jbrowse/core/ui';
|
|
7
7
|
import VerticalGuide from './VerticalGuide';
|
|
8
8
|
const useStyles = makeStyles()(theme => {
|
|
9
|
-
const { tertiary, primary } = theme.palette;
|
|
10
|
-
const background = tertiary
|
|
11
|
-
? alpha(tertiary.main, 0.7)
|
|
12
|
-
: alpha(primary.main, 0.7);
|
|
13
9
|
return {
|
|
14
10
|
rubberband: {
|
|
15
11
|
height: '100%',
|
|
16
|
-
background,
|
|
12
|
+
background: alpha(theme.palette.tertiary.main, 0.7),
|
|
17
13
|
position: 'absolute',
|
|
18
14
|
zIndex: 10,
|
|
19
15
|
textAlign: 'center',
|
|
@@ -25,7 +21,7 @@ const useStyles = makeStyles()(theme => {
|
|
|
25
21
|
minHeight: 8,
|
|
26
22
|
},
|
|
27
23
|
rubberbandText: {
|
|
28
|
-
color: tertiary
|
|
24
|
+
color: theme.palette.tertiary.contrastText,
|
|
29
25
|
},
|
|
30
26
|
popover: {
|
|
31
27
|
mouseEvents: 'none',
|
|
@@ -101,7 +97,7 @@ const LinearComparativeRubberband = observer(function Rubberband({ model, Contro
|
|
|
101
97
|
};
|
|
102
98
|
}
|
|
103
99
|
return () => { };
|
|
104
|
-
}, [startX, mouseDragging,
|
|
100
|
+
}, [startX, mouseDragging, model]);
|
|
105
101
|
useEffect(() => {
|
|
106
102
|
if (!mouseDragging &&
|
|
107
103
|
currentX !== undefined &&
|
|
@@ -124,7 +120,9 @@ const LinearComparativeRubberband = observer(function Rubberband({ model, Contro
|
|
|
124
120
|
}
|
|
125
121
|
function mouseOut() {
|
|
126
122
|
setGuideX(undefined);
|
|
127
|
-
model.views.forEach(view =>
|
|
123
|
+
model.views.forEach(view => {
|
|
124
|
+
view.setOffsets(undefined, undefined);
|
|
125
|
+
});
|
|
128
126
|
}
|
|
129
127
|
function handleClose() {
|
|
130
128
|
setAnchorPosition(undefined);
|
|
@@ -165,7 +163,9 @@ const LinearComparativeRubberband = observer(function Rubberband({ model, Contro
|
|
|
165
163
|
horizontal: 'left',
|
|
166
164
|
}, keepMounted: true, disableRestoreFocus: true }, rightBpOffset.map((l, idx) => (React.createElement(Typography, { key: [JSON.stringify(l), idx, 'right'].join('-') }, stringify(l, true))))))) : null,
|
|
167
165
|
React.createElement("div", { ref: rubberbandRef, className: classes.rubberband, style: { left, width } },
|
|
168
|
-
React.createElement(Typography, { variant: "h6", className: classes.rubberbandText }, numOfBpSelected.map((n, i) => (
|
|
166
|
+
React.createElement(Typography, { variant: "h6", className: classes.rubberbandText }, numOfBpSelected.map((n, i) => (
|
|
167
|
+
/* biome-ignore lint/suspicious/noArrayIndexKey: */
|
|
168
|
+
React.createElement(Typography, { key: `${n}_${i}` }, `${n.toLocaleString('en-US')}bp`))))),
|
|
169
169
|
React.createElement("div", { className: classes.rubberbandControl, ref: controlsRef, onMouseDown: mouseDown, onMouseOut: mouseOut, onMouseMove: mouseMove }, ControlComponent),
|
|
170
170
|
anchorPosition ? (React.createElement(Menu, { anchorReference: "anchorPosition", anchorPosition: {
|
|
171
171
|
left: anchorPosition.clientX,
|
|
@@ -38,7 +38,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
38
38
|
showCytobandsSetting: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
39
39
|
trackLabels: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
40
40
|
showGridlines: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
41
|
-
highlight: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IArrayType<import("mobx-state-tree").IType<
|
|
41
|
+
highlight: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IArrayType<import("mobx-state-tree").IType<import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").HighlightType, import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").HighlightType, import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").HighlightType>>, [undefined]>;
|
|
42
42
|
colorByCDS: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
43
43
|
showTrackOutlines: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
44
44
|
}, {
|
|
@@ -54,7 +54,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
54
54
|
minimumBlockWidth: number;
|
|
55
55
|
draggingTrackId: undefined | string;
|
|
56
56
|
volatileError: unknown;
|
|
57
|
-
afterDisplayedRegionsSetCallbacks:
|
|
57
|
+
afterDisplayedRegionsSetCallbacks: (() => void)[];
|
|
58
58
|
scaleFactor: number;
|
|
59
59
|
trackRefs: Record<string, HTMLDivElement>;
|
|
60
60
|
coarseDynamicBlocks: import("@jbrowse/core/util/blockTypes").BaseBlock[];
|
|
@@ -67,7 +67,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
67
67
|
readonly interRegionPaddingWidth: number;
|
|
68
68
|
readonly assemblyNames: string[];
|
|
69
69
|
} & {
|
|
70
|
-
scaleBarDisplayPrefix(): string;
|
|
70
|
+
scaleBarDisplayPrefix(): string | undefined;
|
|
71
71
|
MiniControlsComponent(): import("react").FC<any>;
|
|
72
72
|
HeaderComponent(): import("react").FC<any>;
|
|
73
73
|
readonly assemblyErrors: string;
|
|
@@ -82,7 +82,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
82
82
|
readonly totalBp: number;
|
|
83
83
|
readonly maxBpPerPx: number;
|
|
84
84
|
readonly minBpPerPx: number;
|
|
85
|
-
readonly error:
|
|
85
|
+
readonly error: unknown;
|
|
86
86
|
readonly maxOffset: number;
|
|
87
87
|
readonly minOffset: number;
|
|
88
88
|
readonly displayedRegionsTotalPx: number;
|
|
@@ -106,9 +106,9 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
106
106
|
setHideHeaderOverview(b: boolean): void;
|
|
107
107
|
setHideNoTracksActive(b: boolean): void;
|
|
108
108
|
setShowGridlines(b: boolean): void;
|
|
109
|
-
addToHighlights(highlight:
|
|
110
|
-
setHighlight(highlight
|
|
111
|
-
removeHighlight(highlight:
|
|
109
|
+
addToHighlights(highlight: import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").HighlightType): void;
|
|
110
|
+
setHighlight(highlight?: import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").HighlightType[]): void;
|
|
111
|
+
removeHighlight(highlight: import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").HighlightType): void;
|
|
112
112
|
scrollTo(offsetPx: number): number;
|
|
113
113
|
zoomTo(bpPerPx: number, offset?: number, centerAtOffset?: boolean): number;
|
|
114
114
|
setOffsets(left?: import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").BpOffset, right?: import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").BpOffset): void;
|
|
@@ -123,7 +123,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
123
123
|
moveTrackToTop(id: string): void;
|
|
124
124
|
moveTrackToBottom(id: string): void;
|
|
125
125
|
moveTrack(movingId: string, targetId: string): void;
|
|
126
|
-
closeView(): void;
|
|
127
126
|
toggleTrack(trackId: string): boolean;
|
|
128
127
|
setTrackLabels(setting: "overlapping" | "offset" | "hidden"): void;
|
|
129
128
|
setShowCenterLine(b: boolean): void;
|
|
@@ -143,7 +142,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
143
142
|
variant?: string;
|
|
144
143
|
isLeftEndOfDisplayedRegion?: boolean;
|
|
145
144
|
}[];
|
|
146
|
-
afterDisplayedRegionsSet(cb:
|
|
145
|
+
afterDisplayedRegionsSet(cb: () => void): void;
|
|
147
146
|
horizontalScroll(distance: number): number;
|
|
148
147
|
center(): void;
|
|
149
148
|
showAllRegions(): void;
|
|
@@ -236,7 +235,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
236
235
|
showCytobandsSetting: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
237
236
|
trackLabels: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
238
237
|
showGridlines: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
239
|
-
highlight: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IArrayType<import("mobx-state-tree").IType<
|
|
238
|
+
highlight: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IArrayType<import("mobx-state-tree").IType<import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").HighlightType, import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").HighlightType, import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").HighlightType>>, [undefined]>;
|
|
240
239
|
colorByCDS: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
241
240
|
showTrackOutlines: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
242
241
|
}>>, import("mobx-state-tree")._NotCustomized>>;
|
|
@@ -286,12 +285,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
286
285
|
* #action
|
|
287
286
|
*/
|
|
288
287
|
removeView(view: LinearGenomeViewModel): void;
|
|
289
|
-
/**
|
|
290
|
-
* #action
|
|
291
|
-
* removes the view itself from the state tree entirely by calling the
|
|
292
|
-
* parent removeView
|
|
293
|
-
*/
|
|
294
|
-
closeView(): void;
|
|
295
288
|
/**
|
|
296
289
|
* #action
|
|
297
290
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { lazy } from 'react';
|
|
2
|
-
import { addDisposer, cast,
|
|
2
|
+
import { addDisposer, cast, getPath, getRoot, resolveIdentifier, types, } from 'mobx-state-tree';
|
|
3
3
|
import { autorun, transaction } from 'mobx';
|
|
4
4
|
// jbrowse
|
|
5
5
|
import BaseViewModel from '@jbrowse/core/pluggableElementTypes/models/BaseViewModel';
|
|
@@ -77,7 +77,9 @@ function stateModelFactory(pluginManager) {
|
|
|
77
77
|
* #getter
|
|
78
78
|
*/
|
|
79
79
|
get initialized() {
|
|
80
|
-
return (
|
|
80
|
+
return (
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
82
|
+
self.width !== undefined &&
|
|
81
83
|
self.views.length > 0 &&
|
|
82
84
|
self.views.every(view => view.initialized));
|
|
83
85
|
},
|
|
@@ -133,15 +135,6 @@ function stateModelFactory(pluginManager) {
|
|
|
133
135
|
removeView(view) {
|
|
134
136
|
self.views.remove(view);
|
|
135
137
|
},
|
|
136
|
-
/**
|
|
137
|
-
* #action
|
|
138
|
-
* removes the view itself from the state tree entirely by calling the
|
|
139
|
-
* parent removeView
|
|
140
|
-
*/
|
|
141
|
-
closeView() {
|
|
142
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
143
|
-
getParent(self, 2).removeView(self);
|
|
144
|
-
},
|
|
145
138
|
/**
|
|
146
139
|
* #action
|
|
147
140
|
*/
|
|
@@ -208,7 +201,9 @@ function stateModelFactory(pluginManager) {
|
|
|
208
201
|
const schema = pluginManager.pluggableConfigSchemaType('track');
|
|
209
202
|
const config = resolveIdentifier(schema, getRoot(self), trackId);
|
|
210
203
|
const shownTracks = self.tracks.filter(t => t.configuration === config);
|
|
211
|
-
transaction(() =>
|
|
204
|
+
transaction(() => {
|
|
205
|
+
shownTracks.forEach(t => self.tracks.remove(t));
|
|
206
|
+
});
|
|
212
207
|
return shownTracks.length;
|
|
213
208
|
},
|
|
214
209
|
/**
|
|
@@ -250,8 +245,7 @@ function stateModelFactory(pluginManager) {
|
|
|
250
245
|
menuItems() {
|
|
251
246
|
return [
|
|
252
247
|
...self.views
|
|
253
|
-
.map((view, idx) =>
|
|
254
|
-
.filter(f => !!f[1])
|
|
248
|
+
.map((view, idx) => [idx, view.menuItems()])
|
|
255
249
|
.map(f => ({ label: `View ${f[0] + 1} Menu`, subMenu: f[1] })),
|
|
256
250
|
{
|
|
257
251
|
label: 'Return to import form',
|
|
@@ -293,7 +287,9 @@ function stateModelFactory(pluginManager) {
|
|
|
293
287
|
afterAttach() {
|
|
294
288
|
addDisposer(self, autorun(() => {
|
|
295
289
|
if (self.width) {
|
|
296
|
-
self.views.forEach(v =>
|
|
290
|
+
self.views.forEach(v => {
|
|
291
|
+
v.setWidth(self.width);
|
|
292
|
+
});
|
|
297
293
|
}
|
|
298
294
|
}));
|
|
299
295
|
},
|
|
@@ -110,7 +110,7 @@ export default function ReadVsRefDialog({ track, feature: preFeature, handleClos
|
|
|
110
110
|
const totalLength = flags & 2048 ? getLength(suppAlns[0].CIGAR) : getLength(cigar);
|
|
111
111
|
const features = [feat, ...suppAlns];
|
|
112
112
|
features.forEach((f, idx) => {
|
|
113
|
-
f.refName =
|
|
113
|
+
f.refName = assembly.getCanonicalRefName(f.refName) || f.refName;
|
|
114
114
|
f.syntenyId = idx;
|
|
115
115
|
f.mate.syntenyId = idx;
|
|
116
116
|
f.mate.uniqueId = `${f.uniqueId}_mate`;
|
|
@@ -131,10 +131,10 @@ export default function ReadVsRefDialog({ track, feature: preFeature, handleClos
|
|
|
131
131
|
assemblyName: trackAssembly,
|
|
132
132
|
})));
|
|
133
133
|
(_a = session.addTemporaryAssembly) === null || _a === void 0 ? void 0 : _a.call(session, {
|
|
134
|
-
name:
|
|
134
|
+
name: readAssembly,
|
|
135
135
|
sequence: {
|
|
136
136
|
type: 'ReferenceSequenceTrack',
|
|
137
|
-
name:
|
|
137
|
+
name: 'Read sequence',
|
|
138
138
|
trackId: seqTrackId,
|
|
139
139
|
assemblyNames: [readAssembly],
|
|
140
140
|
adapter: {
|
|
@@ -251,7 +251,9 @@ export default function ReadVsRefDialog({ track, feature: preFeature, handleClos
|
|
|
251
251
|
React.createElement(CircularProgress, null))) : (React.createElement("div", { className: classes.root },
|
|
252
252
|
primaryFeature.get('flags') & 256 ? (React.createElement(Typography, { style: { color: 'orange' } }, "Note: You selected a secondary alignment (which generally does not have SA tags or SEQ fields) so do a full reconstruction of the alignment")) : null,
|
|
253
253
|
React.createElement(Typography, null, "Show an extra window size around each part of the split alignment. Using a larger value can allow you to see more genomic context."),
|
|
254
|
-
React.createElement(TextField, { value: windowSize, onChange: event =>
|
|
254
|
+
React.createElement(TextField, { value: windowSize, onChange: event => {
|
|
255
|
+
setWindowSize(event.target.value);
|
|
256
|
+
}, label: "Set window size" })))),
|
|
255
257
|
React.createElement(DialogActions, null,
|
|
256
258
|
React.createElement(Button, { variant: "contained", color: "secondary", onClick: handleClose }, "Cancel"),
|
|
257
259
|
React.createElement(Button, { disabled: !primaryFeature, variant: "contained", color: "primary", onClick: onSubmit }, "Submit"))));
|
|
@@ -69,8 +69,8 @@ export function doAfterAttach(self) {
|
|
|
69
69
|
;
|
|
70
70
|
[f1e, f1s] = [f1s, f1e];
|
|
71
71
|
}
|
|
72
|
-
const a1 = assemblyManager
|
|
73
|
-
const a2 = assemblyManager
|
|
72
|
+
const a1 = assemblyManager.get(f.get('assemblyName'));
|
|
73
|
+
const a2 = assemblyManager.get(mate.assemblyName);
|
|
74
74
|
const r1 = f.get('refName');
|
|
75
75
|
const r2 = mate.refName;
|
|
76
76
|
const ref1 = (a1 === null || a1 === void 0 ? void 0 : a1.getCanonicalRefName(r1)) || r1;
|
|
@@ -29,8 +29,12 @@ function LoadingMessage() {
|
|
|
29
29
|
const [shown, setShown] = useState(false);
|
|
30
30
|
const { classes } = useStyles();
|
|
31
31
|
useEffect(() => {
|
|
32
|
-
const timeout = setTimeout(() =>
|
|
33
|
-
|
|
32
|
+
const timeout = setTimeout(() => {
|
|
33
|
+
setShown(true);
|
|
34
|
+
}, 300);
|
|
35
|
+
return () => {
|
|
36
|
+
clearTimeout(timeout);
|
|
37
|
+
};
|
|
34
38
|
});
|
|
35
39
|
return shown ? (React.createElement("div", { className: classes.loading },
|
|
36
40
|
React.createElement(LoadingEllipses, null))) : null;
|
|
@@ -41,15 +41,20 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
|
|
|
41
41
|
const [mouseInitialDownX, setMouseInitialDownX] = useState();
|
|
42
42
|
const [currY, setCurrY] = useState();
|
|
43
43
|
const { mouseoverId } = model;
|
|
44
|
-
// these useCallbacks avoid new refs from being created on any mouseover,
|
|
45
|
-
|
|
44
|
+
// these useCallbacks avoid new refs from being created on any mouseover,
|
|
45
|
+
// etc.
|
|
46
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
47
|
+
const k1 = useCallback((ref) => {
|
|
48
|
+
model.setMouseoverCanvasRef(ref);
|
|
49
|
+
},
|
|
46
50
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
47
51
|
[model, height, width]);
|
|
52
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
48
53
|
const k2 = useCallback((ref) => {
|
|
49
54
|
model.setMainCanvasRef(ref);
|
|
50
55
|
function onWheel(event) {
|
|
51
56
|
event.preventDefault();
|
|
52
|
-
if (event.ctrlKey
|
|
57
|
+
if (event.ctrlKey) {
|
|
53
58
|
delta.current += event.deltaY / 500;
|
|
54
59
|
for (const v of view.views) {
|
|
55
60
|
v.setScaleFactor(delta.current < 0 ? 1 - delta.current : 1 / (1 + delta.current));
|
|
@@ -84,21 +89,26 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
|
|
|
84
89
|
}
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
return () => { };
|
|
92
|
+
ref === null || ref === void 0 ? void 0 : ref.addEventListener('wheel', onWheel);
|
|
93
|
+
// this is a react 19-ism to have a cleanup in the ref callback
|
|
94
|
+
// https://react.dev/blog/2024/04/25/react-19#cleanup-functions-for-refs
|
|
95
|
+
// note: it warns in earlier versions of react
|
|
96
|
+
return () => {
|
|
97
|
+
ref === null || ref === void 0 ? void 0 : ref.removeEventListener('wheel', onWheel);
|
|
98
|
+
};
|
|
95
99
|
},
|
|
96
100
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
97
101
|
[model, height, width]);
|
|
98
|
-
|
|
102
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
103
|
+
const k3 = useCallback((ref) => {
|
|
104
|
+
model.setClickMapCanvasRef(ref);
|
|
105
|
+
},
|
|
99
106
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
100
107
|
[model, height, width]);
|
|
101
|
-
|
|
108
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
109
|
+
const k4 = useCallback((ref) => {
|
|
110
|
+
model.setCigarClickMapCanvasRef(ref);
|
|
111
|
+
},
|
|
102
112
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
103
113
|
[model, height, width]);
|
|
104
114
|
return (React.createElement("div", { className: classes.rel },
|
|
@@ -165,10 +175,14 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
|
|
|
165
175
|
Math.abs(evt.clientX - mouseInitialDownX) < 5) {
|
|
166
176
|
onSynClick(evt, model);
|
|
167
177
|
}
|
|
168
|
-
}, onContextMenu: evt =>
|
|
178
|
+
}, onContextMenu: evt => {
|
|
179
|
+
onSynContextClick(evt, model, setAnchorEl);
|
|
180
|
+
}, "data-testid": "synteny_canvas", className: classes.abs, width: width, height: height }),
|
|
169
181
|
React.createElement("canvas", { ref: k3, className: classes.pix, width: width, height: height }),
|
|
170
182
|
React.createElement("canvas", { ref: k4, className: classes.pix, width: width, height: height }),
|
|
171
183
|
mouseoverId && tooltip && currX && currY ? (React.createElement(SyntenyTooltip, { title: tooltip })) : null,
|
|
172
|
-
anchorEl ? (React.createElement(SyntenyContextMenu, { model: model, anchorEl: anchorEl, onClose: () =>
|
|
184
|
+
anchorEl ? (React.createElement(SyntenyContextMenu, { model: model, anchorEl: anchorEl, onClose: () => {
|
|
185
|
+
setAnchorEl(undefined);
|
|
186
|
+
} })) : null));
|
|
173
187
|
});
|
|
174
188
|
export default LinearSyntenyRendering;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { Feature } from '@jbrowse/core/util';
|
|
2
3
|
import { LinearSyntenyDisplayModel } from '../model';
|
|
3
4
|
interface ClickCoord {
|
|
4
5
|
clientX: number;
|
|
5
6
|
clientY: number;
|
|
6
|
-
feature:
|
|
7
|
+
feature: {
|
|
8
|
+
f: Feature;
|
|
9
|
+
};
|
|
7
10
|
}
|
|
8
11
|
export default function SyntenyContextMenu({ model, onClose, anchorEl, }: {
|
|
9
12
|
onClose: () => void;
|
|
@@ -33,15 +33,11 @@ export default function SyntenyContextMenu({ model, onClose, anchorEl, }) {
|
|
|
33
33
|
const end = f.get('end');
|
|
34
34
|
const refName = f.get('refName');
|
|
35
35
|
const mate = f.get('mate');
|
|
36
|
-
view.views[0]
|
|
37
|
-
.navToLocString(`${refName}:${start}-${end}`)
|
|
38
|
-
.catch(e => {
|
|
36
|
+
view.views[0].navToLocString(`${refName}:${start}-${end}`).catch((e) => {
|
|
39
37
|
console.error(e);
|
|
40
38
|
getSession(model).notifyError(`${e}`, e);
|
|
41
39
|
});
|
|
42
|
-
view.views[1]
|
|
43
|
-
.navToLocString(`${mate.refName}:${mate.start}-${mate.end}`)
|
|
44
|
-
.catch(e => {
|
|
40
|
+
view.views[1].navToLocString(`${mate.refName}:${mate.start}-${mate.end}`).catch((e) => {
|
|
45
41
|
console.error(e);
|
|
46
42
|
getSession(model).notifyError(`${e}`, e);
|
|
47
43
|
});
|
|
@@ -34,7 +34,7 @@ const SyntenyTooltip = observer(function ({ title }) {
|
|
|
34
34
|
});
|
|
35
35
|
const clientPoint = useClientPoint(context);
|
|
36
36
|
const { getFloatingProps } = useInteractions([clientPoint]);
|
|
37
|
-
const popperTheme = (_a = theme
|
|
37
|
+
const popperTheme = (_a = theme.components) === null || _a === void 0 ? void 0 : _a.MuiPopper;
|
|
38
38
|
return title ? (React.createElement(Portal, { container: (_b = popperTheme === null || popperTheme === void 0 ? void 0 : popperTheme.defaultProps) === null || _b === void 0 ? void 0 : _b.container },
|
|
39
39
|
React.createElement("div", { className: classes.tooltip, ref: refs.setFloating, style: {
|
|
40
40
|
...floatingStyles,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { 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 drawRef(model: LinearSyntenyDisplayModel, ctx1: CanvasRenderingContext2D, ctx3?: CanvasRenderingContext2D):
|
|
4
|
+
export declare function drawRef(model: LinearSyntenyDisplayModel, ctx1: CanvasRenderingContext2D, ctx3?: CanvasRenderingContext2D): undefined;
|
|
5
5
|
export declare function drawMouseoverSynteny(model: LinearSyntenyDisplayModel): void;
|
|
@@ -93,7 +93,7 @@ export function drawRef(model, ctx1, ctx3) {
|
|
|
93
93
|
// cx1/cx2 are the current x positions on top and bottom rows
|
|
94
94
|
let cx1 = k1;
|
|
95
95
|
let cx2 = s1 === -1 ? x22 : x21;
|
|
96
|
-
if (
|
|
96
|
+
if (cigar.length && drawCIGAR) {
|
|
97
97
|
// continuingFlag skips drawing commands on very small CIGAR features
|
|
98
98
|
let continuingFlag = false;
|
|
99
99
|
// px1/px2 are the previous x positions on the top and bottom rows
|
|
@@ -117,6 +117,7 @@ export function drawRef(model, ctx1, ctx3) {
|
|
|
117
117
|
else if (op === 'D' || op === 'N') {
|
|
118
118
|
cx1 += d1 * rev1;
|
|
119
119
|
}
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
120
121
|
else if (op === 'I') {
|
|
121
122
|
cx2 += d2 * rev2;
|
|
122
123
|
}
|
|
@@ -134,12 +135,12 @@ export function drawRef(model, ctx1, ctx3) {
|
|
|
134
135
|
continuingFlag = true;
|
|
135
136
|
}
|
|
136
137
|
else {
|
|
137
|
-
|
|
138
|
-
//
|
|
139
|
-
//
|
|
140
|
-
// feature, else just use match
|
|
138
|
+
// allow rendering the dominant color when using continuing flag
|
|
139
|
+
// if the last element of continuing was a large feature, else
|
|
140
|
+
// just use match
|
|
141
141
|
ctx1.fillStyle =
|
|
142
142
|
colorMap[(continuingFlag && d1 > 1) || d2 > 1 ? op : 'M'];
|
|
143
|
+
continuingFlag = false;
|
|
143
144
|
draw(ctx1, px1, cx1, y1, cx2, px2, y2, mid, drawCurves);
|
|
144
145
|
if (ctx3) {
|
|
145
146
|
ctx3.fillStyle = makeColor(idx);
|
|
@@ -167,7 +168,9 @@ export function drawRef(model, ctx1, ctx3) {
|
|
|
167
168
|
ctx2.fillStyle = makeColor(idx);
|
|
168
169
|
// too many click map false positives with colored stroked lines
|
|
169
170
|
drawMatchSimple({
|
|
170
|
-
cb: ctx =>
|
|
171
|
+
cb: ctx => {
|
|
172
|
+
ctx.fill();
|
|
173
|
+
},
|
|
171
174
|
feature,
|
|
172
175
|
ctx: ctx2,
|
|
173
176
|
drawCurves,
|
|
@@ -178,6 +181,7 @@ export function drawRef(model, ctx1, ctx3) {
|
|
|
178
181
|
height,
|
|
179
182
|
});
|
|
180
183
|
}
|
|
184
|
+
return undefined;
|
|
181
185
|
}
|
|
182
186
|
export function drawMouseoverSynteny(model) {
|
|
183
187
|
var _a;
|
|
@@ -199,7 +203,9 @@ export function drawMouseoverSynteny(model) {
|
|
|
199
203
|
if (feature1) {
|
|
200
204
|
ctx.fillStyle = 'rgb(0,0,0,0.1)';
|
|
201
205
|
drawMatchSimple({
|
|
202
|
-
cb: ctx =>
|
|
206
|
+
cb: ctx => {
|
|
207
|
+
ctx.fill();
|
|
208
|
+
},
|
|
203
209
|
feature: feature1,
|
|
204
210
|
ctx,
|
|
205
211
|
oobLimit,
|
|
@@ -213,7 +219,9 @@ export function drawMouseoverSynteny(model) {
|
|
|
213
219
|
if (feature2) {
|
|
214
220
|
ctx.strokeStyle = 'rgb(0, 0, 0, 0.9)';
|
|
215
221
|
drawMatchSimple({
|
|
216
|
-
cb: ctx =>
|
|
222
|
+
cb: ctx => {
|
|
223
|
+
ctx.stroke();
|
|
224
|
+
},
|
|
217
225
|
feature: feature2,
|
|
218
226
|
ctx,
|
|
219
227
|
oobLimit,
|
|
@@ -57,7 +57,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
57
57
|
error: unknown;
|
|
58
58
|
message: string | undefined;
|
|
59
59
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
60
|
-
onHorizontalScroll?:
|
|
60
|
+
onHorizontalScroll?: () => void;
|
|
61
61
|
blockState?: Record<string, any>;
|
|
62
62
|
}>;
|
|
63
63
|
readonly DisplayBlurb: import("react").FC<{
|
|
@@ -77,7 +77,9 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
77
77
|
rendererTypeName: string;
|
|
78
78
|
error: unknown;
|
|
79
79
|
message: string | undefined;
|
|
80
|
-
}, import("mobx-state-tree"
|
|
80
|
+
}, import("mobx-state-tree" /**
|
|
81
|
+
* #action
|
|
82
|
+
*/)._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
81
83
|
}> | null;
|
|
82
84
|
readonly adapterConfig: any;
|
|
83
85
|
readonly parentTrack: any;
|
|
@@ -138,7 +140,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
138
140
|
error: unknown;
|
|
139
141
|
message: string | undefined;
|
|
140
142
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
141
|
-
onHorizontalScroll?:
|
|
143
|
+
onHorizontalScroll?: () => void;
|
|
142
144
|
blockState?: Record<string, any>;
|
|
143
145
|
}>;
|
|
144
146
|
readonly DisplayBlurb: import("react").FC<{
|
|
@@ -158,7 +160,9 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
158
160
|
rendererTypeName: string;
|
|
159
161
|
error: unknown;
|
|
160
162
|
message: string | undefined;
|
|
161
|
-
}, import("mobx-state-tree"
|
|
163
|
+
}, import("mobx-state-tree" /**
|
|
164
|
+
* #action
|
|
165
|
+
*/)._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
162
166
|
}> | null;
|
|
163
167
|
readonly adapterConfig: any;
|
|
164
168
|
readonly parentTrack: any;
|
|
@@ -208,7 +212,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
208
212
|
error: unknown;
|
|
209
213
|
message: string | undefined;
|
|
210
214
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
211
|
-
onHorizontalScroll?:
|
|
215
|
+
onHorizontalScroll?: () => void;
|
|
212
216
|
blockState?: Record<string, any>;
|
|
213
217
|
}>;
|
|
214
218
|
readonly DisplayBlurb: import("react").FC<{
|
|
@@ -8,7 +8,7 @@ function LoadingMessage() {
|
|
|
8
8
|
React.createElement(Typography, { display: "inline" }, "Creating SVG")));
|
|
9
9
|
}
|
|
10
10
|
function useSvgLocal(key, val) {
|
|
11
|
-
return useLocalStorage(
|
|
11
|
+
return useLocalStorage(`svg-${key}`, val);
|
|
12
12
|
}
|
|
13
13
|
function TextField2({ children, ...rest }) {
|
|
14
14
|
return (React.createElement("div", null,
|
|
@@ -26,19 +26,29 @@ export default function ExportSvgDialog({ model, handleClose, }) {
|
|
|
26
26
|
return (React.createElement(Dialog, { open: true, onClose: handleClose, title: "Export SVG" },
|
|
27
27
|
React.createElement(DialogContent, null,
|
|
28
28
|
error ? (React.createElement(ErrorMessage, { error: error })) : loading ? (React.createElement(LoadingMessage, null)) : null,
|
|
29
|
-
React.createElement(TextField2, { helperText: "filename", value: filename, onChange: event =>
|
|
30
|
-
|
|
29
|
+
React.createElement(TextField2, { helperText: "filename", value: filename, onChange: event => {
|
|
30
|
+
setFilename(event.target.value);
|
|
31
|
+
} }),
|
|
32
|
+
React.createElement(TextField2, { select: true, label: "Track label positioning", variant: "outlined", value: trackLabels, style: { width: 150 }, onChange: event => {
|
|
33
|
+
setTrackLabels(event.target.value);
|
|
34
|
+
} },
|
|
31
35
|
React.createElement(MenuItem, { value: "offset" }, "Offset"),
|
|
32
36
|
React.createElement(MenuItem, { value: "overlay" }, "Overlay"),
|
|
33
37
|
React.createElement(MenuItem, { value: "left" }, "Left"),
|
|
34
38
|
React.createElement(MenuItem, { value: "none" }, "None")),
|
|
35
39
|
React.createElement("br", null),
|
|
36
|
-
session.allThemes ? (React.createElement(TextField2, { select: true, label: "Theme", variant: "outlined", value: themeName, onChange: event =>
|
|
40
|
+
session.allThemes ? (React.createElement(TextField2, { select: true, label: "Theme", variant: "outlined", value: themeName, onChange: event => {
|
|
41
|
+
setThemeName(event.target.value);
|
|
42
|
+
} }, Object.entries(session.allThemes()).map(([key, val]) => (React.createElement(MenuItem, { key: key, value: key },
|
|
37
43
|
// @ts-expect-error
|
|
38
44
|
val.name || '(Unknown name)'))))) : null,
|
|
39
|
-
offscreenCanvas ? (React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { checked: rasterizeLayers, onChange: () =>
|
|
45
|
+
offscreenCanvas ? (React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { checked: rasterizeLayers, onChange: () => {
|
|
46
|
+
setRasterizeLayers(val => !val);
|
|
47
|
+
} }), 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"))),
|
|
40
48
|
React.createElement(DialogActions, null,
|
|
41
|
-
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () =>
|
|
49
|
+
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
50
|
+
handleClose();
|
|
51
|
+
} }, "Cancel"),
|
|
42
52
|
React.createElement(Button, { variant: "contained", color: "primary", type: "submit", onClick: async () => {
|
|
43
53
|
setLoading(true);
|
|
44
54
|
setError(undefined);
|
|
@@ -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;
|
|
@@ -32,6 +32,8 @@ const Selector = observer(({ model, assembly1, assembly2, setShowTrackId, }) =>
|
|
|
32
32
|
}, [value, setShowTrackId]);
|
|
33
33
|
return (React.createElement(Paper, { style: { padding: 12 } },
|
|
34
34
|
React.createElement(Typography, { paragraph: true }, "Select a track from the select box below, the track will be shown when you hit \"Launch\"."),
|
|
35
|
-
filteredTracks.length ? (React.createElement(Select, { value: value, onChange: event =>
|
|
35
|
+
filteredTracks.length ? (React.createElement(Select, { value: value, onChange: event => {
|
|
36
|
+
setValue(event.target.value);
|
|
37
|
+
} }, 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}` }))));
|
|
36
38
|
});
|
|
37
39
|
export default Selector;
|