@jbrowse/plugin-linear-comparative-view 2.16.0 → 2.16.1
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.d.ts +2 -1
- package/dist/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.js +4 -2
- package/dist/LGVSyntenyDisplay/components/util.d.ts +4 -1
- package/dist/LGVSyntenyDisplay/components/util.js +7 -15
- package/dist/LGVSyntenyDisplay/model.d.ts +26 -14
- package/dist/LGVSyntenyDisplay/model.js +23 -1
- package/dist/LinearComparativeDisplay/stateModelFactory.d.ts +28 -5
- package/dist/LinearComparativeDisplay/stateModelFactory.js +14 -3
- package/dist/LinearSyntenyDisplay/afterAttach.js +2 -3
- package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +22 -15
- package/dist/LinearSyntenyDisplay/components/SyntenyContextMenu.js +2 -4
- package/dist/LinearSyntenyDisplay/components/util.d.ts +5 -1
- package/dist/LinearSyntenyDisplay/components/util.js +7 -9
- package/dist/LinearSyntenyDisplay/drawSynteny.js +7 -9
- package/dist/LinearSyntenyDisplay/model.d.ts +48 -11
- package/dist/LinearSyntenyDisplay/model.js +38 -22
- package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +14 -0
- package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.js +100 -0
- package/dist/SyntenyFeatureDetail/index.d.ts +2 -0
- package/dist/SyntenyFeatureDetail/index.js +56 -0
- package/dist/index.js +2 -0
- package/esm/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.d.ts +2 -1
- package/esm/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.js +4 -2
- package/esm/LGVSyntenyDisplay/components/util.d.ts +4 -1
- package/esm/LGVSyntenyDisplay/components/util.js +8 -16
- package/esm/LGVSyntenyDisplay/model.d.ts +26 -14
- package/esm/LGVSyntenyDisplay/model.js +25 -3
- package/esm/LinearComparativeDisplay/stateModelFactory.d.ts +28 -5
- package/esm/LinearComparativeDisplay/stateModelFactory.js +14 -3
- package/esm/LinearSyntenyDisplay/afterAttach.js +3 -4
- package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +22 -15
- package/esm/LinearSyntenyDisplay/components/SyntenyContextMenu.js +2 -4
- package/esm/LinearSyntenyDisplay/components/util.d.ts +5 -1
- package/esm/LinearSyntenyDisplay/components/util.js +7 -9
- package/esm/LinearSyntenyDisplay/drawSynteny.js +7 -9
- package/esm/LinearSyntenyDisplay/model.d.ts +48 -11
- package/esm/LinearSyntenyDisplay/model.js +39 -23
- package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +14 -0
- package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.js +72 -0
- package/esm/SyntenyFeatureDetail/index.d.ts +2 -0
- package/esm/SyntenyFeatureDetail/index.js +27 -0
- package/esm/index.js +2 -0
- package/package.json +3 -3
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Feature } from '@jbrowse/core/util';
|
|
3
|
-
export default function LaunchSyntenyViewDialog({ model, feature, handleClose, }: {
|
|
3
|
+
export default function LaunchSyntenyViewDialog({ model, feature, trackId, handleClose, }: {
|
|
4
4
|
model: unknown;
|
|
5
5
|
feature: Feature;
|
|
6
|
+
trackId: string;
|
|
6
7
|
handleClose: () => void;
|
|
7
8
|
}): React.JSX.Element;
|
|
@@ -28,15 +28,16 @@ const react_1 = __importStar(require("react"));
|
|
|
28
28
|
const ui_1 = require("@jbrowse/core/ui");
|
|
29
29
|
const util_1 = require("@jbrowse/core/util");
|
|
30
30
|
const material_1 = require("@mui/material");
|
|
31
|
-
const util_2 = require("./util");
|
|
32
31
|
const mui_1 = require("tss-react/mui");
|
|
32
|
+
// locals
|
|
33
|
+
const util_2 = require("./util");
|
|
33
34
|
const useStyles = (0, mui_1.makeStyles)()({
|
|
34
35
|
padding: {
|
|
35
36
|
margin: 10,
|
|
36
37
|
border: '1px solid #ccc',
|
|
37
38
|
},
|
|
38
39
|
});
|
|
39
|
-
function LaunchSyntenyViewDialog({ model, feature, handleClose, }) {
|
|
40
|
+
function LaunchSyntenyViewDialog({ model, feature, trackId, handleClose, }) {
|
|
40
41
|
const { classes } = useStyles();
|
|
41
42
|
const inverted = feature.get('strand') === -1;
|
|
42
43
|
const [horizontallyFlip, setHorizontallyFlip] = (0, react_1.useState)(inverted);
|
|
@@ -59,6 +60,7 @@ function LaunchSyntenyViewDialog({ model, feature, handleClose, }) {
|
|
|
59
60
|
feature,
|
|
60
61
|
windowSize: +windowSize,
|
|
61
62
|
horizontallyFlip,
|
|
63
|
+
trackId,
|
|
62
64
|
model,
|
|
63
65
|
});
|
|
64
66
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Feature } from '@jbrowse/core/util';
|
|
2
2
|
import { IAnyStateTreeNode } from 'mobx-state-tree';
|
|
3
|
-
|
|
3
|
+
import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view';
|
|
4
|
+
export declare function navToSynteny({ feature, windowSize: ws, model, trackId, view, horizontallyFlip, }: {
|
|
4
5
|
windowSize: number;
|
|
6
|
+
trackId: string;
|
|
5
7
|
horizontallyFlip: boolean;
|
|
6
8
|
feature: Feature;
|
|
9
|
+
view?: LinearGenomeViewModel;
|
|
7
10
|
model: IAnyStateTreeNode;
|
|
8
11
|
}): Promise<void>;
|
|
@@ -30,18 +30,13 @@ function findPosInCigar(cigar, startX) {
|
|
|
30
30
|
}
|
|
31
31
|
return [featX, mateX];
|
|
32
32
|
}
|
|
33
|
-
async function navToSynteny({ feature, windowSize: ws, model, horizontallyFlip, }) {
|
|
33
|
+
async function navToSynteny({ feature, windowSize: ws, model, trackId, view, horizontallyFlip, }) {
|
|
34
34
|
const session = (0, util_1.getSession)(model);
|
|
35
|
-
const
|
|
36
|
-
const view = (0, util_1.getContainingView)(model);
|
|
37
|
-
const reg = view.dynamicBlocks.contentBlocks[0];
|
|
38
|
-
if (!reg) {
|
|
39
|
-
throw new Error('no visible region');
|
|
40
|
-
}
|
|
35
|
+
const reg = view === null || view === void 0 ? void 0 : view.dynamicBlocks.contentBlocks[0];
|
|
41
36
|
const cigar = feature.get('CIGAR');
|
|
42
37
|
const strand = feature.get('strand');
|
|
43
|
-
const
|
|
44
|
-
const
|
|
38
|
+
const featRef = feature.get('refName');
|
|
39
|
+
const featAsm = feature.get('assemblyName');
|
|
45
40
|
const featStart = feature.get('start');
|
|
46
41
|
const featEnd = feature.get('end');
|
|
47
42
|
const mate = feature.get('mate');
|
|
@@ -49,13 +44,13 @@ async function navToSynteny({ feature, windowSize: ws, model, horizontallyFlip,
|
|
|
49
44
|
const mateEnd = mate.end;
|
|
50
45
|
const mateAsm = mate.assemblyName;
|
|
51
46
|
const mateRef = mate.refName;
|
|
52
|
-
const featAsm = reg.assemblyName;
|
|
53
|
-
const featRef = reg.refName;
|
|
54
47
|
let rMateStart;
|
|
55
48
|
let rMateEnd;
|
|
56
49
|
let rFeatStart;
|
|
57
50
|
let rFeatEnd;
|
|
58
|
-
if (cigar) {
|
|
51
|
+
if (reg && cigar) {
|
|
52
|
+
const regStart = reg.start;
|
|
53
|
+
const regEnd = reg.end;
|
|
59
54
|
const p = parseCigar(cigar);
|
|
60
55
|
const [fStartX, mStartX] = findPosInCigar(p, regStart - featStart);
|
|
61
56
|
const [fEndX, mEndX] = findPosInCigar(p, regEnd - featStart);
|
|
@@ -72,17 +67,14 @@ async function navToSynteny({ feature, windowSize: ws, model, horizontallyFlip,
|
|
|
72
67
|
rMateStart = mateStart;
|
|
73
68
|
rMateEnd = mateEnd;
|
|
74
69
|
}
|
|
75
|
-
const trackId = track.configuration.trackId;
|
|
76
70
|
const view2 = session.addView('LinearSyntenyView', {
|
|
77
71
|
type: 'LinearSyntenyView',
|
|
78
72
|
views: [
|
|
79
73
|
{
|
|
80
|
-
id: `${Math.random()}`,
|
|
81
74
|
type: 'LinearGenomeView',
|
|
82
75
|
hideHeader: true,
|
|
83
76
|
},
|
|
84
77
|
{
|
|
85
|
-
id: `${Math.random()}`,
|
|
86
78
|
type: 'LinearGenomeView',
|
|
87
79
|
hideHeader: true,
|
|
88
80
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
|
|
2
|
+
import { Feature } from '@jbrowse/core/util';
|
|
2
3
|
/**
|
|
3
4
|
* #stateModel LGVSyntenyDisplay
|
|
4
5
|
* displays location of "synteny" feature in a plain LGV, allowing linking out
|
|
@@ -10,7 +11,14 @@ import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
|
|
|
10
11
|
declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("mobx-state-tree").IModelType<{
|
|
11
12
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
12
13
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
13
|
-
rpcDriverName: import("mobx-state-tree"
|
|
14
|
+
rpcDriverName: import("mobx-state-tree" /**
|
|
15
|
+
* #stateModel LGVSyntenyDisplay
|
|
16
|
+
* displays location of "synteny" feature in a plain LGV, allowing linking out
|
|
17
|
+
* to external synteny views
|
|
18
|
+
*
|
|
19
|
+
* extends
|
|
20
|
+
* - [SharedLinearPileupDisplayMixin](../sharedlinearpileupdisplaymixin)
|
|
21
|
+
*/).IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
14
22
|
} & {
|
|
15
23
|
heightPreConfig: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
|
|
16
24
|
} & {
|
|
@@ -38,7 +46,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
38
46
|
renderInProgress: AbortController | undefined;
|
|
39
47
|
filled: boolean;
|
|
40
48
|
reactElement: React.ReactElement | undefined;
|
|
41
|
-
features: Map<string,
|
|
49
|
+
features: Map<string, Feature> | undefined;
|
|
42
50
|
layout: any;
|
|
43
51
|
status: string;
|
|
44
52
|
error: unknown;
|
|
@@ -63,7 +71,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
63
71
|
setMessage(messageText: string): void;
|
|
64
72
|
setRendered(props: {
|
|
65
73
|
reactElement: React.ReactElement;
|
|
66
|
-
features: Map<string,
|
|
74
|
+
features: Map<string, Feature>;
|
|
67
75
|
layout: any;
|
|
68
76
|
maxHeightReached: boolean;
|
|
69
77
|
renderProps: any;
|
|
@@ -223,7 +231,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
223
231
|
regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react").JSX.Element | null;
|
|
224
232
|
} & {
|
|
225
233
|
featureIdUnderMouse: undefined | string;
|
|
226
|
-
contextMenuFeature: undefined |
|
|
234
|
+
contextMenuFeature: undefined | Feature;
|
|
227
235
|
} & {
|
|
228
236
|
readonly DisplayMessageComponent: import("react").FC<any> | undefined;
|
|
229
237
|
readonly blockType: "dynamicBlocks" | "staticBlocks";
|
|
@@ -233,19 +241,19 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
233
241
|
readonly TooltipComponent: import("@jbrowse/core/util").AnyReactComponentType;
|
|
234
242
|
readonly selectedFeatureId: string | undefined;
|
|
235
243
|
} & {
|
|
236
|
-
readonly features: import("@jbrowse/core/util/compositeMap").default<string,
|
|
237
|
-
readonly featureUnderMouse:
|
|
244
|
+
readonly features: import("@jbrowse/core/util/compositeMap").default<string, Feature>;
|
|
245
|
+
readonly featureUnderMouse: Feature | undefined;
|
|
238
246
|
getFeatureOverlapping(blockKey: string, x: number, y: number): string | undefined;
|
|
239
247
|
getFeatureByID(blockKey: string, id: string): [number, number, number, number] | undefined;
|
|
240
248
|
searchFeatureByID(id: string): [number, number, number, number] | undefined;
|
|
241
249
|
} & {
|
|
242
250
|
addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
|
|
243
251
|
deleteBlock(key: string): void;
|
|
244
|
-
selectFeature(feature:
|
|
245
|
-
navToFeature(feature:
|
|
252
|
+
selectFeature(feature: Feature): void;
|
|
253
|
+
navToFeature(feature: Feature): void;
|
|
246
254
|
clearFeatureSelection(): void;
|
|
247
255
|
setFeatureIdUnderMouse(feature?: string): void;
|
|
248
|
-
setContextMenuFeature(feature?:
|
|
256
|
+
setContextMenuFeature(feature?: Feature): void;
|
|
249
257
|
} & {
|
|
250
258
|
reload(): Promise<void>;
|
|
251
259
|
} & {
|
|
@@ -257,7 +265,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
257
265
|
afterAttach(): void;
|
|
258
266
|
} & {
|
|
259
267
|
colorTagMap: import("mobx").ObservableMap<string, string>;
|
|
260
|
-
featureUnderMouseVolatile: undefined |
|
|
268
|
+
featureUnderMouseVolatile: undefined | Feature;
|
|
261
269
|
tagsReady: boolean;
|
|
262
270
|
} & {
|
|
263
271
|
readonly autorunReady: boolean;
|
|
@@ -272,9 +280,9 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
272
280
|
extra?: import("@jbrowse/plugin-alignments/src/shared/color").ExtraColorBy;
|
|
273
281
|
}): void;
|
|
274
282
|
updateColorTagMap(uniqueTag: string[]): void;
|
|
275
|
-
setFeatureUnderMouse(feat?:
|
|
276
|
-
selectFeature(feature:
|
|
277
|
-
copyFeatureToClipboard(feature:
|
|
283
|
+
setFeatureUnderMouse(feat?: Feature): void;
|
|
284
|
+
selectFeature(feature: Feature): void;
|
|
285
|
+
copyFeatureToClipboard(feature: Feature): void;
|
|
278
286
|
setConfig(conf: import("@jbrowse/core/configuration").AnyConfigurationModel): void;
|
|
279
287
|
setFilterBy(filter: import("@jbrowse/plugin-alignments/src/shared").IFilter): void;
|
|
280
288
|
setJexlFilters(filters: string[]): void;
|
|
@@ -293,7 +301,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
293
301
|
} & {
|
|
294
302
|
readonly maxHeight: any;
|
|
295
303
|
readonly featureHeightSetting: any;
|
|
296
|
-
readonly featureUnderMouse:
|
|
304
|
+
readonly featureUnderMouse: Feature | undefined;
|
|
297
305
|
renderReady(): boolean;
|
|
298
306
|
readonly filters: import("@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain").default;
|
|
299
307
|
} & {
|
|
@@ -352,6 +360,10 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
352
360
|
}[];
|
|
353
361
|
})[];
|
|
354
362
|
} & {
|
|
363
|
+
/**
|
|
364
|
+
* #action
|
|
365
|
+
*/
|
|
366
|
+
selectFeature(feature: Feature): void;
|
|
355
367
|
afterCreate(): void;
|
|
356
368
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
|
|
357
369
|
export default stateModelFactory;
|
|
@@ -62,12 +62,13 @@ function stateModelFactory(schema) {
|
|
|
62
62
|
...(feature
|
|
63
63
|
? [
|
|
64
64
|
{
|
|
65
|
-
label: '
|
|
65
|
+
label: 'Launch synteny view for this position',
|
|
66
66
|
onClick: () => {
|
|
67
67
|
(0, util_1.getSession)(self).queueDialog(handleClose => [
|
|
68
68
|
LaunchSyntenyViewDialog,
|
|
69
69
|
{
|
|
70
70
|
model: self,
|
|
71
|
+
trackId: (0, configuration_1.getConf)((0, util_1.getContainingTrack)(self), 'trackId'),
|
|
71
72
|
handleClose,
|
|
72
73
|
feature,
|
|
73
74
|
},
|
|
@@ -98,6 +99,27 @@ function stateModelFactory(schema) {
|
|
|
98
99
|
};
|
|
99
100
|
})
|
|
100
101
|
.actions(self => ({
|
|
102
|
+
/**
|
|
103
|
+
* #action
|
|
104
|
+
*/
|
|
105
|
+
selectFeature(feature) {
|
|
106
|
+
const session = (0, util_1.getSession)(self);
|
|
107
|
+
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
108
|
+
const r2 = (0, util_1.getContainingView)(self);
|
|
109
|
+
let r3 = r2;
|
|
110
|
+
try {
|
|
111
|
+
r3 = (0, util_1.getContainingView)(r3);
|
|
112
|
+
}
|
|
113
|
+
catch (e) { }
|
|
114
|
+
const featureWidget = session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
|
|
115
|
+
featureData: feature.toJSON(),
|
|
116
|
+
view: r3,
|
|
117
|
+
track: (0, util_1.getContainingTrack)(self),
|
|
118
|
+
});
|
|
119
|
+
session.showWidget(featureWidget);
|
|
120
|
+
}
|
|
121
|
+
session.setSelection(feature);
|
|
122
|
+
},
|
|
101
123
|
afterCreate() {
|
|
102
124
|
// use color by stand to help indicate inversions better on first load,
|
|
103
125
|
// otherwise use selected orientation
|
|
@@ -43,7 +43,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
43
43
|
message: string | undefined;
|
|
44
44
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
45
45
|
onHorizontalScroll?: () => void;
|
|
46
|
-
blockState
|
|
46
|
+
blockState? /**
|
|
47
|
+
* #action
|
|
48
|
+
* controlled by a reaction
|
|
49
|
+
*/: Record<string, any>;
|
|
47
50
|
}>;
|
|
48
51
|
readonly DisplayBlurb: React.FC<{
|
|
49
52
|
model: {
|
|
@@ -55,7 +58,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
55
58
|
error: unknown;
|
|
56
59
|
message: string | undefined;
|
|
57
60
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
58
|
-
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree"
|
|
61
|
+
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree" /**
|
|
62
|
+
* #action
|
|
63
|
+
* controlled by a reaction
|
|
64
|
+
*/).ISimpleType<string>, [undefined]>;
|
|
59
65
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
60
66
|
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
61
67
|
}, {
|
|
@@ -82,6 +88,14 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
82
88
|
features: Feature[] | undefined;
|
|
83
89
|
message: string | undefined;
|
|
84
90
|
} & {
|
|
91
|
+
/**
|
|
92
|
+
* #getter
|
|
93
|
+
*/
|
|
94
|
+
readonly level: number;
|
|
95
|
+
/**
|
|
96
|
+
* #getter
|
|
97
|
+
*/
|
|
98
|
+
readonly height: number;
|
|
85
99
|
/**
|
|
86
100
|
* #getter
|
|
87
101
|
*/
|
|
@@ -126,7 +140,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
126
140
|
message: string | undefined;
|
|
127
141
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
128
142
|
onHorizontalScroll?: () => void;
|
|
129
|
-
blockState
|
|
143
|
+
blockState? /**
|
|
144
|
+
* #action
|
|
145
|
+
* controlled by a reaction
|
|
146
|
+
*/: Record<string, any>;
|
|
130
147
|
}>;
|
|
131
148
|
readonly DisplayBlurb: React.FC<{
|
|
132
149
|
model: {
|
|
@@ -138,7 +155,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
138
155
|
error: unknown;
|
|
139
156
|
message: string | undefined;
|
|
140
157
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
141
|
-
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree"
|
|
158
|
+
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree" /**
|
|
159
|
+
* #action
|
|
160
|
+
* controlled by a reaction
|
|
161
|
+
*/).ISimpleType<string>, [undefined]>;
|
|
142
162
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
143
163
|
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
144
164
|
}, {
|
|
@@ -201,7 +221,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
201
221
|
message: string | undefined;
|
|
202
222
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
203
223
|
onHorizontalScroll?: () => void;
|
|
204
|
-
blockState
|
|
224
|
+
blockState? /**
|
|
225
|
+
* #action
|
|
226
|
+
* controlled by a reaction
|
|
227
|
+
*/: Record<string, any>;
|
|
205
228
|
}>;
|
|
206
229
|
readonly DisplayBlurb: React.FC<{
|
|
207
230
|
model: {
|
|
@@ -28,6 +28,18 @@ function stateModelFactory(configSchema) {
|
|
|
28
28
|
message: undefined,
|
|
29
29
|
}))
|
|
30
30
|
.views(self => ({
|
|
31
|
+
/**
|
|
32
|
+
* #getter
|
|
33
|
+
*/
|
|
34
|
+
get level() {
|
|
35
|
+
return (0, mobx_state_tree_1.getParent)(self, 4).level;
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* #getter
|
|
39
|
+
*/
|
|
40
|
+
get height() {
|
|
41
|
+
return (0, mobx_state_tree_1.getParent)(self, 4).height;
|
|
42
|
+
},
|
|
31
43
|
/**
|
|
32
44
|
* #getter
|
|
33
45
|
*/
|
|
@@ -133,7 +145,7 @@ function renderBlockData(self) {
|
|
|
133
145
|
// renderProps is something under our control. Compare to
|
|
134
146
|
// serverSideRenderedBlock
|
|
135
147
|
(0, configuration_1.readConfObject)(self.configuration);
|
|
136
|
-
const { adapterConfig } = self;
|
|
148
|
+
const { level, adapterConfig } = self;
|
|
137
149
|
const parent = (0, util_1.getContainingView)(self);
|
|
138
150
|
const sessionId = (0, tracks_1.getRpcSessionId)(self);
|
|
139
151
|
(0, mobx_state_tree_1.getSnapshot)(parent);
|
|
@@ -142,8 +154,7 @@ function renderBlockData(self) {
|
|
|
142
154
|
rpcManager,
|
|
143
155
|
renderProps: {
|
|
144
156
|
...display.renderProps(),
|
|
145
|
-
|
|
146
|
-
level: (0, mobx_state_tree_1.getParent)(self, 4).level,
|
|
157
|
+
level,
|
|
147
158
|
view: parent,
|
|
148
159
|
adapterConfig,
|
|
149
160
|
sessionId,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.doAfterAttach = doAfterAttach;
|
|
4
|
+
const mobx_1 = require("mobx");
|
|
4
5
|
const mobx_state_tree_1 = require("mobx-state-tree");
|
|
5
6
|
const util_1 = require("@jbrowse/core/util");
|
|
6
7
|
const Base1DUtils_1 = require("@jbrowse/core/util/Base1DUtils");
|
|
7
8
|
const plugin_alignments_1 = require("@jbrowse/plugin-alignments");
|
|
8
|
-
const mobx_1 = require("mobx");
|
|
9
9
|
const drawSynteny_1 = require("./drawSynteny");
|
|
10
10
|
function doAfterAttach(self) {
|
|
11
11
|
(0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(() => {
|
|
@@ -51,10 +51,9 @@ function doAfterAttach(self) {
|
|
|
51
51
|
if (!initialized) {
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
+
const { level } = self;
|
|
54
55
|
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
55
56
|
const view = (0, util_1.getContainingView)(self);
|
|
56
|
-
// @ts-expect-error
|
|
57
|
-
const level = (0, mobx_state_tree_1.getParent)(self, 4).level;
|
|
58
57
|
const viewSnaps = view.views.map(view => ({
|
|
59
58
|
...(0, mobx_state_tree_1.getSnapshot)(view),
|
|
60
59
|
width: view.width,
|
|
@@ -46,6 +46,7 @@ const useStyles = (0, mui_1.makeStyles)()({
|
|
|
46
46
|
position: 'relative',
|
|
47
47
|
},
|
|
48
48
|
mouseoverCanvas: {
|
|
49
|
+
imageRendering: 'pixelated',
|
|
49
50
|
position: 'absolute',
|
|
50
51
|
pointEvents: 'none',
|
|
51
52
|
},
|
|
@@ -55,6 +56,7 @@ const useStyles = (0, mui_1.makeStyles)()({
|
|
|
55
56
|
});
|
|
56
57
|
const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
57
58
|
const { classes } = useStyles();
|
|
59
|
+
const { mouseoverId, height } = model;
|
|
58
60
|
const xOffset = (0, react_1.useRef)(0);
|
|
59
61
|
const view = (0, util_1.getContainingView)(model);
|
|
60
62
|
const width = view.width;
|
|
@@ -67,20 +69,19 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
67
69
|
const [mouseCurrDownX, setMouseCurrDownX] = (0, react_1.useState)();
|
|
68
70
|
const [mouseInitialDownX, setMouseInitialDownX] = (0, react_1.useState)();
|
|
69
71
|
const [currY, setCurrY] = (0, react_1.useState)();
|
|
70
|
-
const
|
|
71
|
-
const k2p = (0, react_1.useRef)();
|
|
72
|
+
const mainSyntenyCanvasRefp = (0, react_1.useRef)();
|
|
72
73
|
// these useCallbacks avoid new refs from being created on any mouseover,
|
|
73
74
|
// etc.
|
|
74
75
|
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
75
|
-
const
|
|
76
|
+
const mouseoverDetectionCanvasRef = (0, react_1.useCallback)((ref) => {
|
|
76
77
|
model.setMouseoverCanvasRef(ref);
|
|
77
78
|
},
|
|
78
79
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
79
80
|
[model, height, width]);
|
|
80
81
|
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
81
|
-
const
|
|
82
|
+
const mainSyntenyCanvasRef = (0, react_1.useCallback)((ref) => {
|
|
82
83
|
model.setMainCanvasRef(ref);
|
|
83
|
-
|
|
84
|
+
mainSyntenyCanvasRefp.current = ref; // this ref is additionally used in useEffect below
|
|
84
85
|
},
|
|
85
86
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
86
87
|
[model, height, width]);
|
|
@@ -103,7 +104,9 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
103
104
|
v.setScaleFactor(1);
|
|
104
105
|
v.zoomTo(delta.current > 0
|
|
105
106
|
? v.bpPerPx * (1 + delta.current)
|
|
106
|
-
: v.bpPerPx / (1 - delta.current), event.clientX -
|
|
107
|
+
: v.bpPerPx / (1 - delta.current), event.clientX -
|
|
108
|
+
(((_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) ||
|
|
109
|
+
0));
|
|
107
110
|
}
|
|
108
111
|
delta.current = 0;
|
|
109
112
|
}, 300);
|
|
@@ -126,28 +129,28 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
131
|
}
|
|
129
|
-
(_a =
|
|
132
|
+
(_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.addEventListener('wheel', onWheel);
|
|
130
133
|
return () => {
|
|
131
134
|
var _a;
|
|
132
|
-
(_a =
|
|
135
|
+
(_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('wheel', onWheel);
|
|
133
136
|
};
|
|
134
137
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
135
138
|
}, [model, height, width]);
|
|
136
139
|
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
137
|
-
const
|
|
140
|
+
const clickMapCanvasRef = (0, react_1.useCallback)((ref) => {
|
|
138
141
|
model.setClickMapCanvasRef(ref);
|
|
139
142
|
},
|
|
140
143
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
141
144
|
[model, height, width]);
|
|
142
145
|
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
143
|
-
const
|
|
146
|
+
const cigarClickMapCanvasRef = (0, react_1.useCallback)((ref) => {
|
|
144
147
|
model.setCigarClickMapCanvasRef(ref);
|
|
145
148
|
},
|
|
146
149
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
147
150
|
[model, height, width]);
|
|
148
151
|
return (react_1.default.createElement("div", { className: classes.rel },
|
|
149
|
-
react_1.default.createElement("canvas", { ref:
|
|
150
|
-
react_1.default.createElement("canvas", { ref:
|
|
152
|
+
react_1.default.createElement("canvas", { ref: mouseoverDetectionCanvasRef, width: width, height: height, className: classes.mouseoverCanvas }),
|
|
153
|
+
react_1.default.createElement("canvas", { ref: mainSyntenyCanvasRef, onMouseMove: event => {
|
|
151
154
|
var _a;
|
|
152
155
|
if (mouseCurrDownX !== undefined) {
|
|
153
156
|
xOffset.current += mouseCurrDownX - event.clientX;
|
|
@@ -194,7 +197,11 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
194
197
|
const { f, cigar } = model.featPositions[id];
|
|
195
198
|
const unitMultiplier2 = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / cigar.length);
|
|
196
199
|
const cigarIdx = (0, drawSynteny_1.getId)(r2, g2, b2, unitMultiplier2);
|
|
197
|
-
setTooltip((0, util_2.getTooltip)(
|
|
200
|
+
setTooltip((0, util_2.getTooltip)({
|
|
201
|
+
feature: f,
|
|
202
|
+
cigarOp: cigar[cigarIdx],
|
|
203
|
+
cigarOpLen: cigar[cigarIdx + 1],
|
|
204
|
+
}));
|
|
198
205
|
}
|
|
199
206
|
}
|
|
200
207
|
}, onMouseLeave: () => {
|
|
@@ -213,8 +220,8 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
213
220
|
}, onContextMenu: evt => {
|
|
214
221
|
(0, util_2.onSynContextClick)(evt, model, setAnchorEl);
|
|
215
222
|
}, "data-testid": "synteny_canvas", className: classes.mainCanvas, width: width, height: height }),
|
|
216
|
-
react_1.default.createElement("canvas", { ref:
|
|
217
|
-
react_1.default.createElement("canvas", { ref:
|
|
223
|
+
react_1.default.createElement("canvas", { ref: clickMapCanvasRef, className: classes.pix, width: width, height: height }),
|
|
224
|
+
react_1.default.createElement("canvas", { ref: cigarClickMapCanvasRef, className: classes.pix, width: width, height: height }),
|
|
218
225
|
mouseoverId && tooltip && currX && currY ? (react_1.default.createElement(SyntenyTooltip, { title: tooltip })) : null,
|
|
219
226
|
anchorEl ? (react_1.default.createElement(SyntenyContextMenu_1.default, { model: model, anchorEl: anchorEl, onClose: () => {
|
|
220
227
|
setAnchorEl(undefined);
|
|
@@ -7,7 +7,6 @@ exports.default = SyntenyContextMenu;
|
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const util_1 = require("@jbrowse/core/util");
|
|
9
9
|
const ui_1 = require("@jbrowse/core/ui");
|
|
10
|
-
const mobx_state_tree_1 = require("mobx-state-tree");
|
|
11
10
|
function SyntenyContextMenu({ model, onClose, anchorEl, }) {
|
|
12
11
|
const view = (0, util_1.getContainingView)(model);
|
|
13
12
|
const { clientX, clientY, feature } = anchorEl;
|
|
@@ -36,13 +35,12 @@ function SyntenyContextMenu({ model, onClose, anchorEl, }) {
|
|
|
36
35
|
label: 'Center on feature',
|
|
37
36
|
onClick: () => {
|
|
38
37
|
const { f } = feature;
|
|
39
|
-
const track = (0, mobx_state_tree_1.getParent)(model, 4);
|
|
40
38
|
const start = f.get('start');
|
|
41
39
|
const end = f.get('end');
|
|
42
40
|
const refName = f.get('refName');
|
|
43
41
|
const mate = f.get('mate');
|
|
44
|
-
const l1 = view.views[
|
|
45
|
-
const l2 = view.views[
|
|
42
|
+
const l1 = view.views[model.level];
|
|
43
|
+
const l2 = view.views[model.level + 1];
|
|
46
44
|
l1.navToLocString(`${refName}:${start}-${end}`).catch((e) => {
|
|
47
45
|
const err = `${l1.assemblyNames[0]}:${e}`;
|
|
48
46
|
console.error(err);
|
|
@@ -36,5 +36,9 @@ export declare function drawBox(ctx: CanvasRenderingContext2D, x1: number, x2: n
|
|
|
36
36
|
export declare function drawBezierBox(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number): void;
|
|
37
37
|
export declare function onSynClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel): import("../model").FeatPos | undefined;
|
|
38
38
|
export declare function onSynContextClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel, setAnchorEl: (arg: ClickCoord) => void): void;
|
|
39
|
-
export declare function getTooltip(
|
|
39
|
+
export declare function getTooltip({ feature, cigarOp, cigarOpLen, }: {
|
|
40
|
+
feature: Feature;
|
|
41
|
+
cigarOp?: string;
|
|
42
|
+
cigarOpLen?: string;
|
|
43
|
+
}): string;
|
|
40
44
|
export {};
|
|
@@ -63,7 +63,6 @@ function drawBox(ctx, x1, x2, y1, x3, x4, y2) {
|
|
|
63
63
|
ctx.lineTo(x3, y2);
|
|
64
64
|
ctx.lineTo(x4, y2);
|
|
65
65
|
ctx.closePath();
|
|
66
|
-
ctx.fill();
|
|
67
66
|
}
|
|
68
67
|
function drawBezierBox(ctx, x1, x2, y1, x3, x4, y2, mid) {
|
|
69
68
|
const len1 = Math.abs(x1 - x2);
|
|
@@ -83,13 +82,11 @@ function drawBezierBox(ctx, x1, x2, y1, x3, x4, y2, mid) {
|
|
|
83
82
|
ctx.lineTo(x4, y2);
|
|
84
83
|
ctx.bezierCurveTo(x4, mid, x1, mid, x1, y1);
|
|
85
84
|
ctx.closePath();
|
|
86
|
-
ctx.fill();
|
|
87
85
|
}
|
|
88
86
|
function onSynClick(event, model) {
|
|
89
87
|
const view = (0, util_1.getContainingView)(model);
|
|
90
88
|
const track = (0, util_1.getContainingTrack)(model);
|
|
91
|
-
const ref1 = model
|
|
92
|
-
const ref2 = model.cigarClickMapCanvas;
|
|
89
|
+
const { featPositions, numFeats, clickMapCanvas: ref1, cigarClickMapCanvas: ref2, level, } = model;
|
|
93
90
|
if (!ref1 || !ref2) {
|
|
94
91
|
return;
|
|
95
92
|
}
|
|
@@ -102,18 +99,19 @@ function onSynClick(event, model) {
|
|
|
102
99
|
const x = event.clientX - rect.left;
|
|
103
100
|
const y = event.clientY - rect.top;
|
|
104
101
|
const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
|
|
105
|
-
const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE /
|
|
102
|
+
const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / numFeats);
|
|
106
103
|
const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
|
|
107
|
-
const feat =
|
|
104
|
+
const feat = featPositions[id];
|
|
108
105
|
if (feat) {
|
|
109
106
|
const { f } = feat;
|
|
110
107
|
model.setClickId(f.id());
|
|
111
108
|
const session = (0, util_1.getSession)(model);
|
|
112
109
|
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
113
|
-
session.showWidget(session.addWidget('
|
|
110
|
+
session.showWidget(session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
|
|
114
111
|
view,
|
|
115
112
|
track,
|
|
116
113
|
featureData: f.toJSON(),
|
|
114
|
+
level,
|
|
117
115
|
}));
|
|
118
116
|
}
|
|
119
117
|
}
|
|
@@ -144,9 +142,9 @@ function onSynContextClick(event, model, setAnchorEl) {
|
|
|
144
142
|
setAnchorEl({ clientX, clientY, feature: f });
|
|
145
143
|
}
|
|
146
144
|
}
|
|
147
|
-
function getTooltip(
|
|
145
|
+
function getTooltip({ feature, cigarOp, cigarOpLen, }) {
|
|
148
146
|
// @ts-expect-error
|
|
149
|
-
const f1 =
|
|
147
|
+
const f1 = feature.toJSON();
|
|
150
148
|
const f2 = f1.mate;
|
|
151
149
|
const l1 = f1.end - f1.start;
|
|
152
150
|
const l2 = f2.end - f2.start;
|