@jbrowse/plugin-linear-comparative-view 2.11.2 → 2.12.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/util.js +1 -1
- package/dist/LinearComparativeView/model.d.ts +10 -36
- package/dist/LinearComparativeView/model.js +0 -23
- package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +54 -101
- package/dist/LinearSyntenyDisplay/components/util.d.ts +10 -0
- package/dist/LinearSyntenyDisplay/components/util.js +87 -1
- package/dist/LinearSyntenyView/components/ImportForm/index.js +1 -0
- package/dist/LinearSyntenyView/model.d.ts +36 -139
- package/dist/LinearSyntenyView/model.js +0 -8
- package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +5 -3
- package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.js +2 -4
- package/esm/LGVSyntenyDisplay/components/util.js +1 -1
- package/esm/LinearComparativeView/model.d.ts +10 -36
- package/esm/LinearComparativeView/model.js +1 -24
- package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +54 -101
- package/esm/LinearSyntenyDisplay/components/util.d.ts +10 -0
- package/esm/LinearSyntenyDisplay/components/util.js +84 -1
- package/esm/LinearSyntenyView/components/ImportForm/index.js +1 -0
- package/esm/LinearSyntenyView/model.d.ts +36 -139
- package/esm/LinearSyntenyView/model.js +0 -8
- package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +5 -3
- package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.js +2 -4
- package/package.json +2 -2
|
@@ -17,7 +17,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
17
17
|
type: import("mobx-state-tree").ISimpleType<"LinearComparativeView">;
|
|
18
18
|
trackSelectorType: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
19
19
|
showIntraviewLinks: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
20
|
-
linkViews: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
21
20
|
interactToggled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
22
21
|
middleComparativeHeight: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
23
22
|
tracks: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IAnyType>;
|
|
@@ -30,16 +29,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
30
29
|
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
31
30
|
offsetPx: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
32
31
|
bpPerPx: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
33
|
-
displayedRegions: import("mobx-state-tree").
|
|
34
|
-
refName: import("mobx-state-tree").ISimpleType<string>;
|
|
35
|
-
start: import("mobx-state-tree").ISimpleType<number>;
|
|
36
|
-
end: import("mobx-state-tree").ISimpleType<number>;
|
|
37
|
-
reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
38
|
-
} & {
|
|
39
|
-
assemblyName: import("mobx-state-tree").ISimpleType<string>;
|
|
40
|
-
}, {
|
|
41
|
-
setRefName(newRefName: string): void;
|
|
42
|
-
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
32
|
+
displayedRegions: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IType<import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[]>, [undefined]>;
|
|
43
33
|
tracks: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IAnyType>;
|
|
44
34
|
hideHeader: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
45
35
|
hideHeaderOverview: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
@@ -198,14 +188,13 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
198
188
|
lowerCaseRefNameAliases: {
|
|
199
189
|
[x: string]: string | undefined;
|
|
200
190
|
} | undefined;
|
|
201
|
-
cytobands: import("@jbrowse/core/util").Feature[] | undefined;
|
|
191
|
+
cytobands: import("@jbrowse/core/util").Feature[] | undefined; /**
|
|
192
|
+
* #property
|
|
193
|
+
*/
|
|
202
194
|
} & {
|
|
203
195
|
getConf(arg: string): any;
|
|
204
196
|
} & {
|
|
205
197
|
readonly initialized: boolean;
|
|
206
|
-
/**
|
|
207
|
-
* #property
|
|
208
|
-
*/
|
|
209
198
|
readonly name: string;
|
|
210
199
|
readonly regions: import("@jbrowse/core/assemblyManager/assembly").BasicRegion[] | undefined;
|
|
211
200
|
readonly aliases: string[];
|
|
@@ -263,14 +252,13 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
263
252
|
lowerCaseRefNameAliases: {
|
|
264
253
|
[x: string]: string | undefined;
|
|
265
254
|
} | undefined;
|
|
266
|
-
cytobands: import("@jbrowse/core/util").Feature[] | undefined;
|
|
255
|
+
cytobands: import("@jbrowse/core/util").Feature[] | undefined; /**
|
|
256
|
+
* #property
|
|
257
|
+
*/
|
|
267
258
|
} & {
|
|
268
259
|
getConf(arg: string): any;
|
|
269
260
|
} & {
|
|
270
261
|
readonly initialized: boolean;
|
|
271
|
-
/**
|
|
272
|
-
* #property
|
|
273
|
-
*/
|
|
274
262
|
readonly name: string;
|
|
275
263
|
readonly regions: import("@jbrowse/core/assemblyManager/assembly").BasicRegion[] | undefined;
|
|
276
264
|
readonly aliases: string[];
|
|
@@ -340,7 +328,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
340
328
|
offset: number;
|
|
341
329
|
start: number;
|
|
342
330
|
end: number;
|
|
343
|
-
reversed
|
|
331
|
+
reversed?: boolean | undefined;
|
|
344
332
|
};
|
|
345
333
|
readonly centerLineInfo: {
|
|
346
334
|
coord: number;
|
|
@@ -351,7 +339,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
351
339
|
offset: number;
|
|
352
340
|
start: number;
|
|
353
341
|
end: number;
|
|
354
|
-
reversed
|
|
342
|
+
reversed?: boolean | undefined;
|
|
355
343
|
} | undefined;
|
|
356
344
|
} & {
|
|
357
345
|
afterCreate(): void;
|
|
@@ -364,16 +352,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
364
352
|
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
365
353
|
offsetPx: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
366
354
|
bpPerPx: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
367
|
-
displayedRegions: import("mobx-state-tree").
|
|
368
|
-
refName: import("mobx-state-tree").ISimpleType<string>;
|
|
369
|
-
start: import("mobx-state-tree").ISimpleType<number>;
|
|
370
|
-
end: import("mobx-state-tree").ISimpleType<number>;
|
|
371
|
-
reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
372
|
-
} & {
|
|
373
|
-
assemblyName: import("mobx-state-tree").ISimpleType<string>;
|
|
374
|
-
}, {
|
|
375
|
-
setRefName(newRefName: string): void;
|
|
376
|
-
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
355
|
+
displayedRegions: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IType<import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[]>, [undefined]>;
|
|
377
356
|
tracks: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IAnyType>;
|
|
378
357
|
hideHeader: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
379
358
|
hideHeaderOverview: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
@@ -415,7 +394,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
415
394
|
*/
|
|
416
395
|
readonly assemblyNames: string[];
|
|
417
396
|
} & {
|
|
418
|
-
afterAttach(): void;
|
|
419
397
|
beforeDestroy(): void;
|
|
420
398
|
onSubviewAction(actionName: string, path: string, args?: unknown[]): void;
|
|
421
399
|
/**
|
|
@@ -440,10 +418,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
440
418
|
* #action
|
|
441
419
|
*/
|
|
442
420
|
setMiddleComparativeHeight(n: number): number;
|
|
443
|
-
/**
|
|
444
|
-
* #action
|
|
445
|
-
*/
|
|
446
|
-
toggleLinkViews(): void;
|
|
447
421
|
/**
|
|
448
422
|
* #action
|
|
449
423
|
*/
|
|
@@ -62,10 +62,6 @@ function stateModelFactory(pluginManager) {
|
|
|
62
62
|
* #property
|
|
63
63
|
*/
|
|
64
64
|
showIntraviewLinks: true,
|
|
65
|
-
/**
|
|
66
|
-
* #property
|
|
67
|
-
*/
|
|
68
|
-
linkViews: false,
|
|
69
65
|
/**
|
|
70
66
|
* #property
|
|
71
67
|
*/
|
|
@@ -126,19 +122,6 @@ function stateModelFactory(pluginManager) {
|
|
|
126
122
|
},
|
|
127
123
|
}))
|
|
128
124
|
.actions(self => ({
|
|
129
|
-
afterAttach() {
|
|
130
|
-
(0, mobx_state_tree_1.addDisposer)(self, (0, mobx_state_tree_1.onAction)(self, param => {
|
|
131
|
-
if (self.linkViews) {
|
|
132
|
-
const { name, path, args } = param;
|
|
133
|
-
// doesn't link showTrack/hideTrack, doesn't make sense in
|
|
134
|
-
// synteny views most time
|
|
135
|
-
const actions = ['horizontalScroll', 'zoomTo', 'setScaleFactor'];
|
|
136
|
-
if (actions.includes(name) && path) {
|
|
137
|
-
this.onSubviewAction(name, path, args);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}));
|
|
141
|
-
},
|
|
142
125
|
// automatically removes session assemblies associated with this view
|
|
143
126
|
// e.g. read vs ref
|
|
144
127
|
beforeDestroy() {
|
|
@@ -191,12 +174,6 @@ function stateModelFactory(pluginManager) {
|
|
|
191
174
|
self.middleComparativeHeight = n;
|
|
192
175
|
return self.middleComparativeHeight;
|
|
193
176
|
},
|
|
194
|
-
/**
|
|
195
|
-
* #action
|
|
196
|
-
*/
|
|
197
|
-
toggleLinkViews() {
|
|
198
|
-
self.linkViews = !self.linkViews;
|
|
199
|
-
},
|
|
200
177
|
/**
|
|
201
178
|
* #action
|
|
202
179
|
*/
|
|
@@ -35,6 +35,7 @@ const mui_1 = require("tss-react/mui");
|
|
|
35
35
|
const SyntenyTooltip_1 = __importDefault(require("./SyntenyTooltip"));
|
|
36
36
|
const drawSynteny_1 = require("../drawSynteny");
|
|
37
37
|
const SyntenyContextMenu_1 = __importDefault(require("./SyntenyContextMenu"));
|
|
38
|
+
const util_2 = require("./util");
|
|
38
39
|
const useStyles = (0, mui_1.makeStyles)()({
|
|
39
40
|
pix: {
|
|
40
41
|
imageRendering: 'pixelated',
|
|
@@ -59,30 +60,44 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
59
60
|
const view = (0, util_1.getContainingView)(model);
|
|
60
61
|
const height = view.middleComparativeHeight;
|
|
61
62
|
const width = view.width;
|
|
63
|
+
const delta = (0, react_1.useRef)(0);
|
|
64
|
+
const timeout = (0, react_1.useRef)();
|
|
62
65
|
const [anchorEl, setAnchorEl] = (0, react_1.useState)();
|
|
63
66
|
const [tooltip, setTooltip] = (0, react_1.useState)('');
|
|
64
67
|
const [currX, setCurrX] = (0, react_1.useState)();
|
|
65
68
|
const [mouseCurrDownX, setMouseCurrDownX] = (0, react_1.useState)();
|
|
66
69
|
const [mouseInitialDownX, setMouseInitialDownX] = (0, react_1.useState)();
|
|
67
70
|
const [currY, setCurrY] = (0, react_1.useState)();
|
|
71
|
+
const { mouseoverId } = model;
|
|
68
72
|
// these useCallbacks avoid new refs from being created on any mouseover, etc.
|
|
69
73
|
const k1 = (0, react_1.useCallback)((ref) => model.setMouseoverCanvasRef(ref),
|
|
70
74
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
71
75
|
[model, height, width]);
|
|
72
|
-
const k2 = (0, react_1.useCallback)((ref) =>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
const k2 = (0, react_1.useCallback)((ref) => {
|
|
77
|
+
model.setMainCanvasRef(ref);
|
|
78
|
+
function onWheel(event) {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
if (event.ctrlKey === true) {
|
|
81
|
+
delta.current += event.deltaY / 500;
|
|
82
|
+
for (const v of view.views) {
|
|
83
|
+
v.setScaleFactor(delta.current < 0 ? 1 - delta.current : 1 / (1 + delta.current));
|
|
84
|
+
}
|
|
85
|
+
if (timeout.current) {
|
|
86
|
+
clearTimeout(timeout.current);
|
|
87
|
+
}
|
|
88
|
+
timeout.current = setTimeout(() => {
|
|
89
|
+
for (const v of view.views) {
|
|
90
|
+
v.setScaleFactor(1);
|
|
91
|
+
v.zoomTo(delta.current > 0
|
|
92
|
+
? v.bpPerPx * (1 + delta.current)
|
|
93
|
+
: v.bpPerPx / (1 - delta.current), event.clientX - ((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().left) || 0));
|
|
94
|
+
}
|
|
95
|
+
delta.current = 0;
|
|
96
|
+
}, 300);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
84
99
|
if (Math.abs(event.deltaY) < Math.abs(event.deltaX)) {
|
|
85
|
-
xOffset.current += event.deltaX;
|
|
100
|
+
xOffset.current += event.deltaX / 2;
|
|
86
101
|
}
|
|
87
102
|
if (currScrollFrame.current === undefined) {
|
|
88
103
|
currScrollFrame.current = requestAnimationFrame(() => {
|
|
@@ -95,7 +110,28 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
95
110
|
});
|
|
96
111
|
});
|
|
97
112
|
}
|
|
98
|
-
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (ref) {
|
|
116
|
+
ref.addEventListener('wheel', onWheel);
|
|
117
|
+
// this is a react 19-ism to have a cleanup in the ref callback
|
|
118
|
+
// https://react.dev/blog/2024/04/25/react-19#cleanup-functions-for-refs
|
|
119
|
+
// note: it warns in earlier versions of react
|
|
120
|
+
return () => ref.removeEventListener('wheel', onWheel);
|
|
121
|
+
}
|
|
122
|
+
return () => { };
|
|
123
|
+
},
|
|
124
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
125
|
+
[model, height, width]);
|
|
126
|
+
const k3 = (0, react_1.useCallback)((ref) => model.setClickMapCanvasRef(ref),
|
|
127
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
128
|
+
[model, height, width]);
|
|
129
|
+
const k4 = (0, react_1.useCallback)((ref) => model.setCigarClickMapCanvasRef(ref),
|
|
130
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
131
|
+
[model, height, width]);
|
|
132
|
+
return (react_1.default.createElement("div", { className: classes.rel },
|
|
133
|
+
react_1.default.createElement("canvas", { ref: k1, width: width, height: height, className: cx(classes.abs, classes.none) }),
|
|
134
|
+
react_1.default.createElement("canvas", { ref: k2, onMouseMove: event => {
|
|
99
135
|
var _a;
|
|
100
136
|
if (mouseCurrDownX !== undefined) {
|
|
101
137
|
xOffset.current += mouseCurrDownX - event.clientX;
|
|
@@ -141,7 +177,7 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
141
177
|
const { f, cigar } = model.featPositions[id];
|
|
142
178
|
const unitMultiplier2 = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / cigar.length);
|
|
143
179
|
const cigarIdx = (0, drawSynteny_1.getId)(r2, g2, b2, unitMultiplier2);
|
|
144
|
-
setTooltip(getTooltip(f, cigar[cigarIdx], cigar[cigarIdx + 1]));
|
|
180
|
+
setTooltip((0, util_2.getTooltip)(f, cigar[cigarIdx], cigar[cigarIdx + 1]));
|
|
145
181
|
}
|
|
146
182
|
}
|
|
147
183
|
}, onMouseLeave: () => {
|
|
@@ -155,95 +191,12 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
155
191
|
setMouseCurrDownX(undefined);
|
|
156
192
|
if (mouseInitialDownX !== undefined &&
|
|
157
193
|
Math.abs(evt.clientX - mouseInitialDownX) < 5) {
|
|
158
|
-
|
|
194
|
+
(0, util_2.onSynClick)(evt, model);
|
|
159
195
|
}
|
|
160
|
-
}, onContextMenu: evt =>
|
|
161
|
-
onSyntenyContextClick(evt, model, setAnchorEl);
|
|
162
|
-
}, "data-testid": "synteny_canvas", className: classes.abs, width: width, height: height }),
|
|
196
|
+
}, onContextMenu: evt => (0, util_2.onSynContextClick)(evt, model, setAnchorEl), "data-testid": "synteny_canvas", className: classes.abs, width: width, height: height }),
|
|
163
197
|
react_1.default.createElement("canvas", { ref: k3, className: classes.pix, width: width, height: height }),
|
|
164
198
|
react_1.default.createElement("canvas", { ref: k4, className: classes.pix, width: width, height: height }),
|
|
165
|
-
|
|
199
|
+
mouseoverId && tooltip && currX && currY ? (react_1.default.createElement(SyntenyTooltip_1.default, { title: tooltip })) : null,
|
|
166
200
|
anchorEl ? (react_1.default.createElement(SyntenyContextMenu_1.default, { model: model, anchorEl: anchorEl, onClose: () => setAnchorEl(undefined) })) : null));
|
|
167
201
|
});
|
|
168
|
-
function onSyntenyClick(event, model) {
|
|
169
|
-
const ref1 = model.clickMapCanvas;
|
|
170
|
-
const ref2 = model.cigarClickMapCanvas;
|
|
171
|
-
if (!ref1 || !ref2) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const rect = ref1.getBoundingClientRect();
|
|
175
|
-
const ctx1 = ref1.getContext('2d');
|
|
176
|
-
const ctx2 = ref2.getContext('2d');
|
|
177
|
-
if (!ctx1 || !ctx2) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
const x = event.clientX - rect.left;
|
|
181
|
-
const y = event.clientY - rect.top;
|
|
182
|
-
const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
|
|
183
|
-
const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / model.numFeats);
|
|
184
|
-
const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
|
|
185
|
-
const feat = model.featPositions[id];
|
|
186
|
-
if (feat) {
|
|
187
|
-
const { f } = feat;
|
|
188
|
-
model.setClickId(f.id());
|
|
189
|
-
const session = (0, util_1.getSession)(model);
|
|
190
|
-
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
191
|
-
session.showWidget(session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
|
|
192
|
-
featureData: {
|
|
193
|
-
feature1: f.toJSON(),
|
|
194
|
-
feature2: f.get('mate'),
|
|
195
|
-
},
|
|
196
|
-
}));
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return feat;
|
|
200
|
-
}
|
|
201
|
-
function onSyntenyContextClick(event, model, setAnchorEl) {
|
|
202
|
-
event.preventDefault();
|
|
203
|
-
const ref1 = model.clickMapCanvas;
|
|
204
|
-
const ref2 = model.cigarClickMapCanvas;
|
|
205
|
-
if (!ref1 || !ref2) {
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
const rect = ref1.getBoundingClientRect();
|
|
209
|
-
const ctx1 = ref1.getContext('2d');
|
|
210
|
-
const ctx2 = ref2.getContext('2d');
|
|
211
|
-
if (!ctx1 || !ctx2) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
const { clientX, clientY } = event;
|
|
215
|
-
const x = clientX - rect.left;
|
|
216
|
-
const y = clientY - rect.top;
|
|
217
|
-
const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
|
|
218
|
-
const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / model.numFeats);
|
|
219
|
-
const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
|
|
220
|
-
const f = model.featPositions[id];
|
|
221
|
-
if (f) {
|
|
222
|
-
model.setClickId(f.f.id());
|
|
223
|
-
setAnchorEl({ clientX, clientY, feature: f });
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
function getTooltip(f, cigarOp, cigarOpLen) {
|
|
227
|
-
// @ts-expect-error
|
|
228
|
-
const f1 = f.toJSON();
|
|
229
|
-
const f2 = f1.mate;
|
|
230
|
-
const l1 = f1.end - f1.start;
|
|
231
|
-
const l2 = f2.end - f2.start;
|
|
232
|
-
const identity = f1.identity;
|
|
233
|
-
const n1 = f1.name;
|
|
234
|
-
const n2 = f2.name;
|
|
235
|
-
return [
|
|
236
|
-
`Loc1: ${(0, util_1.assembleLocString)(f1)}`,
|
|
237
|
-
`Loc2: ${(0, util_1.assembleLocString)(f2)}`,
|
|
238
|
-
`Inverted: ${f1.strand === -1}`,
|
|
239
|
-
`Query len: ${l1.toLocaleString('en-US')}`,
|
|
240
|
-
`Target len: ${l2.toLocaleString('en-US')}`,
|
|
241
|
-
identity ? `Identity: ${identity.toPrecision(2)}` : '',
|
|
242
|
-
cigarOp ? `CIGAR operator: ${cigarOp}${cigarOpLen}` : '',
|
|
243
|
-
n1 ? `Name 1: ${n1}` : '',
|
|
244
|
-
n2 ? `Name 1: ${n2}` : '',
|
|
245
|
-
]
|
|
246
|
-
.filter(f => !!f)
|
|
247
|
-
.join('<br/>');
|
|
248
|
-
}
|
|
249
202
|
exports.default = LinearSyntenyRendering;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import { Feature } from '@jbrowse/core/util';
|
|
3
|
+
import { LinearSyntenyDisplayModel } from '../model';
|
|
2
4
|
interface Pos {
|
|
3
5
|
offsetPx: number;
|
|
4
6
|
}
|
|
7
|
+
export interface ClickCoord {
|
|
8
|
+
clientX: number;
|
|
9
|
+
clientY: number;
|
|
10
|
+
feature: any;
|
|
11
|
+
}
|
|
5
12
|
interface FeatPos {
|
|
6
13
|
p11: Pos;
|
|
7
14
|
p12: Pos;
|
|
@@ -24,4 +31,7 @@ export declare function drawMatchSimple({ feature, ctx, offsets, cb, height, dra
|
|
|
24
31
|
export declare function draw(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number, drawCurves?: boolean): void;
|
|
25
32
|
export declare function drawBox(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number): void;
|
|
26
33
|
export declare function drawBezierBox(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number): void;
|
|
34
|
+
export declare function onSynClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel): import("../model").FeatPos | undefined;
|
|
35
|
+
export declare function onSynContextClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel, setAnchorEl: (arg: ClickCoord) => void): void;
|
|
36
|
+
export declare function getTooltip(f: Feature, cigarOp?: string, cigarOpLen?: string): string;
|
|
27
37
|
export {};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.drawBezierBox = exports.drawBox = exports.draw = exports.drawMatchSimple = void 0;
|
|
3
|
+
exports.getTooltip = exports.onSynContextClick = exports.onSynClick = exports.drawBezierBox = exports.drawBox = exports.draw = exports.drawMatchSimple = void 0;
|
|
4
4
|
const util_1 = require("@jbrowse/core/util");
|
|
5
|
+
// locals
|
|
6
|
+
const drawSynteny_1 = require("../drawSynteny");
|
|
5
7
|
function drawMatchSimple({ feature, ctx, offsets, cb, height, drawCurves, oobLimit, viewWidth, hideTiny, }) {
|
|
6
8
|
const { p11, p12, p21, p22 } = feature;
|
|
7
9
|
const x11 = p11.offsetPx - offsets[0];
|
|
@@ -81,3 +83,87 @@ function drawBezierBox(ctx, x1, x2, y1, x3, x4, y2, mid) {
|
|
|
81
83
|
ctx.fill();
|
|
82
84
|
}
|
|
83
85
|
exports.drawBezierBox = drawBezierBox;
|
|
86
|
+
function onSynClick(event, model) {
|
|
87
|
+
const ref1 = model.clickMapCanvas;
|
|
88
|
+
const ref2 = model.cigarClickMapCanvas;
|
|
89
|
+
if (!ref1 || !ref2) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const rect = ref1.getBoundingClientRect();
|
|
93
|
+
const ctx1 = ref1.getContext('2d');
|
|
94
|
+
const ctx2 = ref2.getContext('2d');
|
|
95
|
+
if (!ctx1 || !ctx2) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const x = event.clientX - rect.left;
|
|
99
|
+
const y = event.clientY - rect.top;
|
|
100
|
+
const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
|
|
101
|
+
const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / model.numFeats);
|
|
102
|
+
const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
|
|
103
|
+
const feat = model.featPositions[id];
|
|
104
|
+
if (feat) {
|
|
105
|
+
const { f } = feat;
|
|
106
|
+
model.setClickId(f.id());
|
|
107
|
+
const session = (0, util_1.getSession)(model);
|
|
108
|
+
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
109
|
+
session.showWidget(session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
|
|
110
|
+
featureData: {
|
|
111
|
+
feature1: f.toJSON(),
|
|
112
|
+
feature2: f.get('mate'),
|
|
113
|
+
},
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return feat;
|
|
118
|
+
}
|
|
119
|
+
exports.onSynClick = onSynClick;
|
|
120
|
+
function onSynContextClick(event, model, setAnchorEl) {
|
|
121
|
+
event.preventDefault();
|
|
122
|
+
const ref1 = model.clickMapCanvas;
|
|
123
|
+
const ref2 = model.cigarClickMapCanvas;
|
|
124
|
+
if (!ref1 || !ref2) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const rect = ref1.getBoundingClientRect();
|
|
128
|
+
const ctx1 = ref1.getContext('2d');
|
|
129
|
+
const ctx2 = ref2.getContext('2d');
|
|
130
|
+
if (!ctx1 || !ctx2) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const { clientX, clientY } = event;
|
|
134
|
+
const x = clientX - rect.left;
|
|
135
|
+
const y = clientY - rect.top;
|
|
136
|
+
const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
|
|
137
|
+
const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / model.numFeats);
|
|
138
|
+
const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
|
|
139
|
+
const f = model.featPositions[id];
|
|
140
|
+
if (f) {
|
|
141
|
+
model.setClickId(f.f.id());
|
|
142
|
+
setAnchorEl({ clientX, clientY, feature: f });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
exports.onSynContextClick = onSynContextClick;
|
|
146
|
+
function getTooltip(f, cigarOp, cigarOpLen) {
|
|
147
|
+
// @ts-expect-error
|
|
148
|
+
const f1 = f.toJSON();
|
|
149
|
+
const f2 = f1.mate;
|
|
150
|
+
const l1 = f1.end - f1.start;
|
|
151
|
+
const l2 = f2.end - f2.start;
|
|
152
|
+
const identity = f1.identity;
|
|
153
|
+
const n1 = f1.name;
|
|
154
|
+
const n2 = f2.name;
|
|
155
|
+
return [
|
|
156
|
+
`Loc1: ${(0, util_1.assembleLocString)(f1)}`,
|
|
157
|
+
`Loc2: ${(0, util_1.assembleLocString)(f2)}`,
|
|
158
|
+
`Inverted: ${f1.strand === -1}`,
|
|
159
|
+
`Query len: ${l1.toLocaleString('en-US')}`,
|
|
160
|
+
`Target len: ${l2.toLocaleString('en-US')}`,
|
|
161
|
+
identity ? `Identity: ${identity.toPrecision(2)}` : '',
|
|
162
|
+
cigarOp ? `CIGAR operator: ${cigarOp}${cigarOpLen}` : '',
|
|
163
|
+
n1 ? `Name 1: ${n1}` : '',
|
|
164
|
+
n2 ? `Name 1: ${n2}` : '',
|
|
165
|
+
]
|
|
166
|
+
.filter(f => !!f)
|
|
167
|
+
.join('<br/>');
|
|
168
|
+
}
|
|
169
|
+
exports.getTooltip = getTooltip;
|
|
@@ -93,6 +93,7 @@ const LinearSyntenyViewImportForm = (0, mobx_react_1.observer)(function ({ model
|
|
|
93
93
|
};
|
|
94
94
|
})));
|
|
95
95
|
model.views.forEach(view => view.setWidth(model.width));
|
|
96
|
+
model.views.forEach(view => view.showAllRegions());
|
|
96
97
|
if (sessionTrackData) {
|
|
97
98
|
session.addTrackConf(sessionTrackData);
|
|
98
99
|
model.toggleTrack(sessionTrackData.trackId);
|