@jbrowse/plugin-linear-comparative-view 2.9.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LGVSyntenyDisplay/configSchemaF.d.ts +2 -0
- package/dist/LGVSyntenyDisplay/configSchemaF.js +2 -0
- package/dist/LGVSyntenyDisplay/model.d.ts +18 -7
- package/dist/LGVSyntenyDisplay/model.js +13 -3
- package/dist/LinearComparativeDisplay/stateModelFactory.d.ts +35 -27
- package/dist/LinearComparativeDisplay/stateModelFactory.js +2 -0
- package/dist/LinearComparativeView/model.d.ts +27 -12
- package/dist/LinearComparativeView/model.js +2 -0
- package/dist/LinearReadVsRef/index.js +26 -2
- package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +185 -96
- package/dist/LinearSyntenyDisplay/components/SyntenyContextMenu.d.ts +13 -0
- package/dist/LinearSyntenyDisplay/components/SyntenyContextMenu.js +57 -0
- package/dist/LinearSyntenyDisplay/components/SyntenyTooltip.d.ts +1 -3
- package/dist/LinearSyntenyDisplay/components/SyntenyTooltip.js +19 -51
- package/dist/LinearSyntenyDisplay/model.d.ts +27 -17
- package/dist/LinearSyntenyDisplay/model.js +2 -1
- package/dist/LinearSyntenyView/model.d.ts +119 -54
- package/dist/LinearSyntenyView/model.js +8 -1
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +6 -6
- package/dist/SyntenyTrack/configSchema.js +2 -0
- package/esm/LGVSyntenyDisplay/configSchemaF.d.ts +2 -0
- package/esm/LGVSyntenyDisplay/configSchemaF.js +2 -0
- package/esm/LGVSyntenyDisplay/model.d.ts +18 -7
- package/esm/LGVSyntenyDisplay/model.js +13 -3
- package/esm/LinearComparativeDisplay/stateModelFactory.d.ts +35 -27
- package/esm/LinearComparativeDisplay/stateModelFactory.js +2 -0
- package/esm/LinearComparativeView/model.d.ts +27 -12
- package/esm/LinearComparativeView/model.js +2 -0
- package/esm/LinearReadVsRef/index.js +2 -1
- package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +186 -97
- package/esm/LinearSyntenyDisplay/components/SyntenyContextMenu.d.ts +13 -0
- package/esm/LinearSyntenyDisplay/components/SyntenyContextMenu.js +51 -0
- package/esm/LinearSyntenyDisplay/components/SyntenyTooltip.d.ts +1 -3
- package/esm/LinearSyntenyDisplay/components/SyntenyTooltip.js +18 -30
- package/esm/LinearSyntenyDisplay/model.d.ts +27 -17
- package/esm/LinearSyntenyDisplay/model.js +2 -1
- package/esm/LinearSyntenyView/model.d.ts +119 -54
- package/esm/LinearSyntenyView/model.js +8 -1
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +6 -6
- package/esm/SyntenyTrack/configSchema.js +2 -0
- package/package.json +4 -5
|
@@ -4,6 +4,8 @@ import { Instance } from 'mobx-state-tree';
|
|
|
4
4
|
import { Feature } from '@jbrowse/core/util';
|
|
5
5
|
/**
|
|
6
6
|
* #stateModel LinearComparativeDisplay
|
|
7
|
+
* extends
|
|
8
|
+
* - [BaseDisplay](../basedisplay)
|
|
7
9
|
*/
|
|
8
10
|
declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): import("mobx-state-tree").IModelType<{
|
|
9
11
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
@@ -21,7 +23,9 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
21
23
|
readonly RenderingComponent: import("react").FC<{
|
|
22
24
|
model: {
|
|
23
25
|
id: string;
|
|
24
|
-
type: string;
|
|
26
|
+
type: string; /**
|
|
27
|
+
* #property
|
|
28
|
+
*/
|
|
25
29
|
rpcDriverName: string | undefined;
|
|
26
30
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
27
31
|
rendererTypeName: string;
|
|
@@ -30,12 +34,12 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
30
34
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
31
35
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
32
36
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
33
|
-
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
37
|
+
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
38
|
+
}, {
|
|
39
|
+
rendererTypeName: string; /**
|
|
34
40
|
* #action
|
|
35
41
|
* controlled by a reaction
|
|
36
42
|
*/
|
|
37
|
-
}, {
|
|
38
|
-
rendererTypeName: string;
|
|
39
43
|
error: unknown;
|
|
40
44
|
message: string | undefined;
|
|
41
45
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
@@ -48,10 +52,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
48
52
|
type: string;
|
|
49
53
|
rpcDriverName: string | undefined;
|
|
50
54
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
51
|
-
rendererTypeName: string;
|
|
52
|
-
* #action
|
|
53
|
-
* controlled by a reaction
|
|
54
|
-
*/
|
|
55
|
+
rendererTypeName: string;
|
|
55
56
|
error: unknown;
|
|
56
57
|
message: string | undefined;
|
|
57
58
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
@@ -67,7 +68,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
67
68
|
readonly adapterConfig: any;
|
|
68
69
|
readonly parentTrack: any;
|
|
69
70
|
renderProps(): any;
|
|
70
|
-
readonly rendererType: import("@jbrowse/core/pluggableElementTypes").RendererType;
|
|
71
|
+
readonly rendererType: import("@jbrowse/core/pluggableElementTypes").RendererType; /**
|
|
72
|
+
* #action
|
|
73
|
+
* controlled by a reaction
|
|
74
|
+
*/
|
|
71
75
|
readonly DisplayMessageComponent: import("react").FC<any> | undefined;
|
|
72
76
|
trackMenuItems(): import("@jbrowse/core/ui").MenuItem[];
|
|
73
77
|
readonly viewMenuActions: import("@jbrowse/core/ui").MenuItem[];
|
|
@@ -105,7 +109,9 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
105
109
|
readonly RenderingComponent: import("react").FC<{
|
|
106
110
|
model: {
|
|
107
111
|
id: string;
|
|
108
|
-
type: string;
|
|
112
|
+
type: string; /**
|
|
113
|
+
* #property
|
|
114
|
+
*/
|
|
109
115
|
rpcDriverName: string | undefined;
|
|
110
116
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
111
117
|
rendererTypeName: string;
|
|
@@ -114,12 +120,12 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
114
120
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
115
121
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
116
122
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
117
|
-
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
123
|
+
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
124
|
+
}, {
|
|
125
|
+
rendererTypeName: string; /**
|
|
118
126
|
* #action
|
|
119
127
|
* controlled by a reaction
|
|
120
128
|
*/
|
|
121
|
-
}, {
|
|
122
|
-
rendererTypeName: string;
|
|
123
129
|
error: unknown;
|
|
124
130
|
message: string | undefined;
|
|
125
131
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
@@ -132,10 +138,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
132
138
|
type: string;
|
|
133
139
|
rpcDriverName: string | undefined;
|
|
134
140
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
135
|
-
rendererTypeName: string;
|
|
136
|
-
* #action
|
|
137
|
-
* controlled by a reaction
|
|
138
|
-
*/
|
|
141
|
+
rendererTypeName: string;
|
|
139
142
|
error: unknown;
|
|
140
143
|
message: string | undefined;
|
|
141
144
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
@@ -151,7 +154,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
151
154
|
readonly adapterConfig: any;
|
|
152
155
|
readonly parentTrack: any;
|
|
153
156
|
renderProps(): any;
|
|
154
|
-
readonly rendererType: import("@jbrowse/core/pluggableElementTypes").RendererType;
|
|
157
|
+
readonly rendererType: import("@jbrowse/core/pluggableElementTypes").RendererType; /**
|
|
158
|
+
* #action
|
|
159
|
+
* controlled by a reaction
|
|
160
|
+
*/
|
|
155
161
|
readonly DisplayMessageComponent: import("react").FC<any> | undefined;
|
|
156
162
|
trackMenuItems(): import("@jbrowse/core/ui").MenuItem[];
|
|
157
163
|
readonly viewMenuActions: import("@jbrowse/core/ui").MenuItem[];
|
|
@@ -181,7 +187,9 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
181
187
|
readonly RenderingComponent: import("react").FC<{
|
|
182
188
|
model: {
|
|
183
189
|
id: string;
|
|
184
|
-
type: string;
|
|
190
|
+
type: string; /**
|
|
191
|
+
* #property
|
|
192
|
+
*/
|
|
185
193
|
rpcDriverName: string | undefined;
|
|
186
194
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
187
195
|
rendererTypeName: string;
|
|
@@ -190,12 +198,12 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
190
198
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
191
199
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
192
200
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
193
|
-
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
201
|
+
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
202
|
+
}, {
|
|
203
|
+
rendererTypeName: string; /**
|
|
194
204
|
* #action
|
|
195
205
|
* controlled by a reaction
|
|
196
206
|
*/
|
|
197
|
-
}, {
|
|
198
|
-
rendererTypeName: string;
|
|
199
207
|
error: unknown;
|
|
200
208
|
message: string | undefined;
|
|
201
209
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
@@ -208,10 +216,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
208
216
|
type: string;
|
|
209
217
|
rpcDriverName: string | undefined;
|
|
210
218
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
211
|
-
rendererTypeName: string;
|
|
212
|
-
* #action
|
|
213
|
-
* controlled by a reaction
|
|
214
|
-
*/
|
|
219
|
+
rendererTypeName: string;
|
|
215
220
|
error: unknown;
|
|
216
221
|
message: string | undefined;
|
|
217
222
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
@@ -227,7 +232,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
227
232
|
readonly adapterConfig: any;
|
|
228
233
|
readonly parentTrack: any;
|
|
229
234
|
renderProps(): any;
|
|
230
|
-
readonly rendererType: import("@jbrowse/core/pluggableElementTypes").RendererType;
|
|
235
|
+
readonly rendererType: import("@jbrowse/core/pluggableElementTypes").RendererType; /**
|
|
236
|
+
* #action
|
|
237
|
+
* controlled by a reaction
|
|
238
|
+
*/
|
|
231
239
|
readonly DisplayMessageComponent: import("react").FC<any> | undefined;
|
|
232
240
|
trackMenuItems(): import("@jbrowse/core/ui").MenuItem[];
|
|
233
241
|
readonly viewMenuActions: import("@jbrowse/core/ui").MenuItem[];
|
|
@@ -5,6 +5,8 @@ import { getRpcSessionId } from '@jbrowse/core/util/tracks';
|
|
|
5
5
|
import { BaseDisplay } from '@jbrowse/core/pluggableElementTypes/models';
|
|
6
6
|
/**
|
|
7
7
|
* #stateModel LinearComparativeDisplay
|
|
8
|
+
* extends
|
|
9
|
+
* - [BaseDisplay](../basedisplay)
|
|
8
10
|
*/
|
|
9
11
|
function stateModelFactory(configSchema) {
|
|
10
12
|
return types
|
|
@@ -5,6 +5,8 @@ import PluginManager from '@jbrowse/core/PluginManager';
|
|
|
5
5
|
import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view';
|
|
6
6
|
/**
|
|
7
7
|
* #stateModel LinearComparativeView
|
|
8
|
+
* extends
|
|
9
|
+
* - [BaseViewModel](../baseviewmodel)
|
|
8
10
|
*/
|
|
9
11
|
declare function stateModelFactory(pluginManager: PluginManager): import("mobx-state-tree").IModelType<{
|
|
10
12
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
@@ -34,9 +36,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
34
36
|
end: import("mobx-state-tree").ISimpleType<number>;
|
|
35
37
|
reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
36
38
|
} & {
|
|
37
|
-
/**
|
|
38
|
-
* #property
|
|
39
|
-
*/
|
|
40
39
|
assemblyName: import("mobx-state-tree").ISimpleType<string>;
|
|
41
40
|
}, {
|
|
42
41
|
setRefName(newRefName: string): void;
|
|
@@ -64,7 +63,9 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
64
63
|
draggingTrackId: string | undefined;
|
|
65
64
|
volatileError: unknown;
|
|
66
65
|
afterDisplayedRegionsSetCallbacks: Function[];
|
|
67
|
-
scaleFactor: number;
|
|
66
|
+
scaleFactor: number; /**
|
|
67
|
+
* #action
|
|
68
|
+
*/
|
|
68
69
|
trackRefs: Record<string, HTMLDivElement>;
|
|
69
70
|
coarseDynamicBlocks: import("@jbrowse/core/util/blockTypes").BaseBlock[];
|
|
70
71
|
coarseTotalBp: number;
|
|
@@ -192,7 +193,8 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
192
193
|
} & {
|
|
193
194
|
getConf(arg: string): any;
|
|
194
195
|
} & {
|
|
195
|
-
readonly initialized: boolean;
|
|
196
|
+
readonly initialized: boolean;
|
|
197
|
+
/**
|
|
196
198
|
* #property
|
|
197
199
|
*/
|
|
198
200
|
readonly name: string;
|
|
@@ -226,11 +228,17 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
226
228
|
load(): Promise<void>;
|
|
227
229
|
loadPre(): Promise<void>;
|
|
228
230
|
} & {
|
|
229
|
-
getAdapterMapEntry(adapterConf:
|
|
230
|
-
|
|
231
|
+
getAdapterMapEntry(adapterConf: {
|
|
232
|
+
[x: string]: unknown;
|
|
233
|
+
}, options: import("@jbrowse/core/data_adapters/BaseAdapter").BaseOptions): Promise<import("@jbrowse/core/assemblyManager/assembly").RefNameMap>;
|
|
234
|
+
getRefNameMapForAdapter(adapterConf: {
|
|
235
|
+
[x: string]: unknown;
|
|
236
|
+
}, opts: import("@jbrowse/core/data_adapters/BaseAdapter").BaseOptions): Promise<{
|
|
231
237
|
[x: string]: string | undefined;
|
|
232
238
|
}>;
|
|
233
|
-
getReverseRefNameMapForAdapter(adapterConf:
|
|
239
|
+
getReverseRefNameMapForAdapter(adapterConf: {
|
|
240
|
+
[x: string]: unknown;
|
|
241
|
+
}, opts: import("@jbrowse/core/data_adapters/BaseAdapter").BaseOptions): Promise<{
|
|
234
242
|
[x: string]: string | undefined;
|
|
235
243
|
}>;
|
|
236
244
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
@@ -250,7 +258,8 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
250
258
|
} & {
|
|
251
259
|
getConf(arg: string): any;
|
|
252
260
|
} & {
|
|
253
|
-
readonly initialized: boolean;
|
|
261
|
+
readonly initialized: boolean;
|
|
262
|
+
/**
|
|
254
263
|
* #property
|
|
255
264
|
*/
|
|
256
265
|
readonly name: string;
|
|
@@ -284,11 +293,17 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
284
293
|
load(): Promise<void>;
|
|
285
294
|
loadPre(): Promise<void>;
|
|
286
295
|
} & {
|
|
287
|
-
getAdapterMapEntry(adapterConf:
|
|
288
|
-
|
|
296
|
+
getAdapterMapEntry(adapterConf: {
|
|
297
|
+
[x: string]: unknown;
|
|
298
|
+
}, options: import("@jbrowse/core/data_adapters/BaseAdapter").BaseOptions): Promise<import("@jbrowse/core/assemblyManager/assembly").RefNameMap>;
|
|
299
|
+
getRefNameMapForAdapter(adapterConf: {
|
|
300
|
+
[x: string]: unknown;
|
|
301
|
+
}, opts: import("@jbrowse/core/data_adapters/BaseAdapter").BaseOptions): Promise<{
|
|
289
302
|
[x: string]: string | undefined;
|
|
290
303
|
}>;
|
|
291
|
-
getReverseRefNameMapForAdapter(adapterConf:
|
|
304
|
+
getReverseRefNameMapForAdapter(adapterConf: {
|
|
305
|
+
[x: string]: unknown;
|
|
306
|
+
}, opts: import("@jbrowse/core/data_adapters/BaseAdapter").BaseOptions): Promise<{
|
|
292
307
|
[x: string]: string | undefined;
|
|
293
308
|
}>;
|
|
294
309
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
@@ -12,6 +12,8 @@ import FolderOpenIcon from '@mui/icons-material/FolderOpen';
|
|
|
12
12
|
const ReturnToImportFormDialog = lazy(() => import('@jbrowse/core/ui/ReturnToImportFormDialog'));
|
|
13
13
|
/**
|
|
14
14
|
* #stateModel LinearComparativeView
|
|
15
|
+
* extends
|
|
16
|
+
* - [BaseViewModel](../baseviewmodel)
|
|
15
17
|
*/
|
|
16
18
|
function stateModelFactory(pluginManager) {
|
|
17
19
|
return types
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { lazy } from 'react';
|
|
1
2
|
import { getSession, getContainingTrack } from '@jbrowse/core/util';
|
|
2
3
|
// icons
|
|
3
4
|
import AddIcon from '@mui/icons-material/Add';
|
|
4
5
|
// locals
|
|
5
|
-
|
|
6
|
+
const ReadVsRefDialog = lazy(() => import('./LinearReadVsRef'));
|
|
6
7
|
function isDisplay(elt) {
|
|
7
8
|
return elt.name === 'LinearPileupDisplay';
|
|
8
9
|
}
|
|
@@ -1,16 +1,41 @@
|
|
|
1
|
-
import React, { useState, useCallback } from 'react';
|
|
1
|
+
import React, { useState, useCallback, useRef } from 'react';
|
|
2
2
|
import { observer } from 'mobx-react';
|
|
3
3
|
import { assembleLocString, getContainingView, getSession, isSessionModelWithWidgets, } from '@jbrowse/core/util';
|
|
4
|
+
import { transaction } from 'mobx';
|
|
5
|
+
import { makeStyles } from 'tss-react/mui';
|
|
4
6
|
// locals
|
|
5
7
|
import SyntenyTooltip from './SyntenyTooltip';
|
|
6
8
|
import { getId, MAX_COLOR_RANGE } from '../drawSynteny';
|
|
9
|
+
import SyntenyContextMenu from './SyntenyContextMenu';
|
|
10
|
+
const useStyles = makeStyles()({
|
|
11
|
+
pix: {
|
|
12
|
+
imageRendering: 'pixelated',
|
|
13
|
+
pointerEvents: 'none',
|
|
14
|
+
visibility: 'hidden',
|
|
15
|
+
position: 'absolute',
|
|
16
|
+
},
|
|
17
|
+
rel: {
|
|
18
|
+
position: 'relative',
|
|
19
|
+
},
|
|
20
|
+
abs: {
|
|
21
|
+
position: 'absolute',
|
|
22
|
+
},
|
|
23
|
+
none: {
|
|
24
|
+
pointEvents: 'none',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
7
27
|
const LinearSyntenyRendering = observer(function ({ model, }) {
|
|
8
|
-
const
|
|
28
|
+
const { classes, cx } = useStyles();
|
|
29
|
+
const xOffset = useRef(0);
|
|
30
|
+
const currScrollFrame = useRef();
|
|
9
31
|
const view = getContainingView(model);
|
|
10
32
|
const height = view.middleComparativeHeight;
|
|
11
33
|
const width = view.width;
|
|
34
|
+
const [anchorEl, setAnchorEl] = useState();
|
|
12
35
|
const [tooltip, setTooltip] = useState('');
|
|
13
36
|
const [currX, setCurrX] = useState();
|
|
37
|
+
const [mouseCurrDownX, setMouseCurrDownX] = useState();
|
|
38
|
+
const [mouseInitialDownX, setMouseInitialDownX] = useState();
|
|
14
39
|
const [currY, setCurrY] = useState();
|
|
15
40
|
// these useCallbacks avoid new refs from being created on any mouseover, etc.
|
|
16
41
|
const k1 = useCallback((ref) => model.setMouseoverCanvasRef(ref),
|
|
@@ -25,108 +50,172 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
|
|
|
25
50
|
const k4 = useCallback((ref) => model.setCigarClickMapCanvasRef(ref),
|
|
26
51
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
27
52
|
[model, height, width]);
|
|
28
|
-
return (React.createElement("div", {
|
|
29
|
-
React.createElement("canvas", { ref: k1, width: width, height: height,
|
|
30
|
-
React.createElement("canvas", { ref: k2,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const ref2 = model.cigarClickMapCanvas;
|
|
34
|
-
if (!ref1 || !ref2) {
|
|
35
|
-
return;
|
|
53
|
+
return (React.createElement("div", { className: classes.rel },
|
|
54
|
+
React.createElement("canvas", { ref: k1, width: width, height: height, className: cx(classes.abs, classes.none) }),
|
|
55
|
+
React.createElement("canvas", { ref: k2, onWheel: event => {
|
|
56
|
+
if (Math.abs(event.deltaY) < Math.abs(event.deltaX)) {
|
|
57
|
+
xOffset.current += event.deltaX;
|
|
36
58
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
59
|
+
if (currScrollFrame.current === undefined) {
|
|
60
|
+
currScrollFrame.current = requestAnimationFrame(() => {
|
|
61
|
+
transaction(() => {
|
|
62
|
+
for (const v of view.views) {
|
|
63
|
+
v.horizontalScroll(xOffset.current);
|
|
64
|
+
}
|
|
65
|
+
xOffset.current = 0;
|
|
66
|
+
currScrollFrame.current = undefined;
|
|
67
|
+
});
|
|
68
|
+
});
|
|
42
69
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
70
|
+
}, onMouseMove: event => {
|
|
71
|
+
var _a;
|
|
72
|
+
if (mouseCurrDownX !== undefined) {
|
|
73
|
+
xOffset.current += mouseCurrDownX - event.clientX;
|
|
74
|
+
setMouseCurrDownX(event.clientX);
|
|
75
|
+
if (currScrollFrame.current === undefined) {
|
|
76
|
+
currScrollFrame.current = requestAnimationFrame(() => {
|
|
77
|
+
transaction(() => {
|
|
78
|
+
for (const v of view.views) {
|
|
79
|
+
v.horizontalScroll(xOffset.current);
|
|
80
|
+
}
|
|
81
|
+
xOffset.current = 0;
|
|
82
|
+
currScrollFrame.current = undefined;
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
55
86
|
}
|
|
56
|
-
else
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const unitMultiplier2 = Math.floor(MAX_COLOR_RANGE / cigar.length);
|
|
62
|
-
const cigarIdx = getId(r2, g2, b2, unitMultiplier2);
|
|
63
|
-
const l1 = f1.end - f1.start;
|
|
64
|
-
const l2 = f2.end - f2.start;
|
|
65
|
-
const identity = f1.identity;
|
|
66
|
-
const n1 = f1.name;
|
|
67
|
-
const n2 = f2.name;
|
|
68
|
-
const tooltip = [
|
|
69
|
-
`Loc1: ${assembleLocString(f1)}`,
|
|
70
|
-
`Loc2: ${assembleLocString(f2)}`,
|
|
71
|
-
`Inverted: ${f1.strand === -1}`,
|
|
72
|
-
`Query len: ${l1}`,
|
|
73
|
-
`Target len: ${l2}`,
|
|
74
|
-
];
|
|
75
|
-
if (identity) {
|
|
76
|
-
tooltip.push(`Identity: ${identity}`);
|
|
87
|
+
else {
|
|
88
|
+
const ref1 = model.clickMapCanvas;
|
|
89
|
+
const ref2 = model.cigarClickMapCanvas;
|
|
90
|
+
if (!ref1 || !ref2) {
|
|
91
|
+
return;
|
|
77
92
|
}
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
const rect = ref1.getBoundingClientRect();
|
|
94
|
+
const ctx1 = ref1.getContext('2d');
|
|
95
|
+
const ctx2 = ref2.getContext('2d');
|
|
96
|
+
if (!ctx1 || !ctx2) {
|
|
97
|
+
return;
|
|
80
98
|
}
|
|
81
|
-
|
|
82
|
-
|
|
99
|
+
const { clientX, clientY } = event;
|
|
100
|
+
const x = clientX - rect.left;
|
|
101
|
+
const y = clientY - rect.top;
|
|
102
|
+
setCurrX(clientX);
|
|
103
|
+
setCurrY(clientY);
|
|
104
|
+
const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
|
|
105
|
+
const [r2, g2, b2] = ctx2.getImageData(x, y, 1, 1).data;
|
|
106
|
+
const unitMultiplier = Math.floor(MAX_COLOR_RANGE / model.numFeats);
|
|
107
|
+
const id = getId(r1, g1, b1, unitMultiplier);
|
|
108
|
+
model.setMouseoverId((_a = model.featPositions[id]) === null || _a === void 0 ? void 0 : _a.f.id());
|
|
109
|
+
if (id === -1) {
|
|
110
|
+
setTooltip('');
|
|
111
|
+
}
|
|
112
|
+
else if (model.featPositions[id]) {
|
|
113
|
+
const { f, cigar } = model.featPositions[id];
|
|
114
|
+
const unitMultiplier2 = Math.floor(MAX_COLOR_RANGE / cigar.length);
|
|
115
|
+
const cigarIdx = getId(r2, g2, b2, unitMultiplier2);
|
|
116
|
+
setTooltip(getTooltip(f, cigar[cigarIdx], cigar[cigarIdx + 1]));
|
|
83
117
|
}
|
|
84
|
-
setTooltip(tooltip.join('<br/>'));
|
|
85
|
-
}
|
|
86
|
-
}, onMouseLeave: () => model.setMouseoverId(undefined), onClick: event => {
|
|
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(MAX_COLOR_RANGE / model.numFeats);
|
|
102
|
-
const id = getId(r1, g1, b1, unitMultiplier);
|
|
103
|
-
const f = model.featPositions[id];
|
|
104
|
-
if (!f) {
|
|
105
|
-
return;
|
|
106
118
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
119
|
+
}, onMouseLeave: () => {
|
|
120
|
+
model.setMouseoverId(undefined);
|
|
121
|
+
setMouseInitialDownX(undefined);
|
|
122
|
+
setMouseCurrDownX(undefined);
|
|
123
|
+
}, onMouseDown: evt => {
|
|
124
|
+
setMouseCurrDownX(evt.clientX);
|
|
125
|
+
setMouseInitialDownX(evt.clientX);
|
|
126
|
+
}, onMouseUp: evt => {
|
|
127
|
+
setMouseCurrDownX(undefined);
|
|
128
|
+
if (mouseInitialDownX !== undefined &&
|
|
129
|
+
Math.abs(evt.clientX - mouseInitialDownX) < 5) {
|
|
130
|
+
onSyntenyClick(evt, model);
|
|
116
131
|
}
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
React.createElement("canvas", { ref: k4, style: {
|
|
125
|
-
imageRendering: 'pixelated',
|
|
126
|
-
pointerEvents: 'none',
|
|
127
|
-
visibility: 'hidden',
|
|
128
|
-
position: 'absolute',
|
|
129
|
-
}, width: width, height: height }),
|
|
130
|
-
model.mouseoverId && tooltip && currX && currY ? (React.createElement(SyntenyTooltip, { x: currX, y: currY, title: tooltip })) : null));
|
|
132
|
+
}, onContextMenu: evt => {
|
|
133
|
+
onSyntenyContextClick(evt, model, setAnchorEl);
|
|
134
|
+
}, "data-testid": "synteny_canvas", className: classes.abs, width: width, height: height }),
|
|
135
|
+
React.createElement("canvas", { ref: k3, className: classes.pix, width: width, height: height }),
|
|
136
|
+
React.createElement("canvas", { ref: k4, className: classes.pix, width: width, height: height }),
|
|
137
|
+
model.mouseoverId && tooltip && currX && currY ? (React.createElement(SyntenyTooltip, { title: tooltip })) : null,
|
|
138
|
+
anchorEl ? (React.createElement(SyntenyContextMenu, { model: model, anchorEl: anchorEl, onClose: () => setAnchorEl(undefined) })) : null));
|
|
131
139
|
});
|
|
140
|
+
function onSyntenyClick(event, model) {
|
|
141
|
+
const ref1 = model.clickMapCanvas;
|
|
142
|
+
const ref2 = model.cigarClickMapCanvas;
|
|
143
|
+
if (!ref1 || !ref2) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const rect = ref1.getBoundingClientRect();
|
|
147
|
+
const ctx1 = ref1.getContext('2d');
|
|
148
|
+
const ctx2 = ref2.getContext('2d');
|
|
149
|
+
if (!ctx1 || !ctx2) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const x = event.clientX - rect.left;
|
|
153
|
+
const y = event.clientY - rect.top;
|
|
154
|
+
const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
|
|
155
|
+
const unitMultiplier = Math.floor(MAX_COLOR_RANGE / model.numFeats);
|
|
156
|
+
const id = getId(r1, g1, b1, unitMultiplier);
|
|
157
|
+
const feat = model.featPositions[id];
|
|
158
|
+
if (feat) {
|
|
159
|
+
const { f } = feat;
|
|
160
|
+
model.setClickId(f.id());
|
|
161
|
+
const session = getSession(model);
|
|
162
|
+
if (isSessionModelWithWidgets(session)) {
|
|
163
|
+
session.showWidget(session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
|
|
164
|
+
featureData: {
|
|
165
|
+
feature1: f.toJSON(),
|
|
166
|
+
feature2: f.get('mate'),
|
|
167
|
+
},
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return feat;
|
|
172
|
+
}
|
|
173
|
+
function onSyntenyContextClick(event, model, setAnchorEl) {
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
const ref1 = model.clickMapCanvas;
|
|
176
|
+
const ref2 = model.cigarClickMapCanvas;
|
|
177
|
+
if (!ref1 || !ref2) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const rect = ref1.getBoundingClientRect();
|
|
181
|
+
const ctx1 = ref1.getContext('2d');
|
|
182
|
+
const ctx2 = ref2.getContext('2d');
|
|
183
|
+
if (!ctx1 || !ctx2) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const { clientX, clientY } = event;
|
|
187
|
+
const x = clientX - rect.left;
|
|
188
|
+
const y = clientY - rect.top;
|
|
189
|
+
const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
|
|
190
|
+
const unitMultiplier = Math.floor(MAX_COLOR_RANGE / model.numFeats);
|
|
191
|
+
const id = getId(r1, g1, b1, unitMultiplier);
|
|
192
|
+
const f = model.featPositions[id];
|
|
193
|
+
if (f) {
|
|
194
|
+
model.setClickId(f.f.id());
|
|
195
|
+
setAnchorEl({ clientX, clientY, feature: f });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function getTooltip(f, cigarOp, cigarOpLen) {
|
|
199
|
+
// @ts-expect-error
|
|
200
|
+
const f1 = f.toJSON();
|
|
201
|
+
const f2 = f1.mate;
|
|
202
|
+
const l1 = f1.end - f1.start;
|
|
203
|
+
const l2 = f2.end - f2.start;
|
|
204
|
+
const identity = f1.identity;
|
|
205
|
+
const n1 = f1.name;
|
|
206
|
+
const n2 = f2.name;
|
|
207
|
+
return [
|
|
208
|
+
`Loc1: ${assembleLocString(f1)}`,
|
|
209
|
+
`Loc2: ${assembleLocString(f2)}`,
|
|
210
|
+
`Inverted: ${f1.strand === -1}`,
|
|
211
|
+
`Query len: ${l1.toLocaleString('en-US')}`,
|
|
212
|
+
`Target len: ${l2.toLocaleString('en-US')}`,
|
|
213
|
+
identity ? `Identity: ${identity.toPrecision(2)}` : '',
|
|
214
|
+
cigarOp ? `CIGAR operator: ${cigarOp}${cigarOpLen}` : '',
|
|
215
|
+
n1 ? `Name 1: ${n1}` : '',
|
|
216
|
+
n2 ? `Name 1: ${n2}` : '',
|
|
217
|
+
]
|
|
218
|
+
.filter(f => !!f)
|
|
219
|
+
.join('<br/>');
|
|
220
|
+
}
|
|
132
221
|
export default LinearSyntenyRendering;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { LinearSyntenyDisplayModel } from '../model';
|
|
3
|
+
interface ClickCoord {
|
|
4
|
+
clientX: number;
|
|
5
|
+
clientY: number;
|
|
6
|
+
feature: any;
|
|
7
|
+
}
|
|
8
|
+
export default function SyntenyContextMenu({ model, onClose, anchorEl, }: {
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
model: LinearSyntenyDisplayModel;
|
|
11
|
+
anchorEl: ClickCoord;
|
|
12
|
+
}): React.JSX.Element;
|
|
13
|
+
export {};
|