@jbrowse/plugin-alignments 2.6.2 → 2.6.3
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/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +492 -0
- package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +529 -0
- package/dist/LinearPileupDisplay/index.d.ts +1 -0
- package/dist/LinearPileupDisplay/index.js +3 -1
- package/dist/LinearPileupDisplay/model.d.ts +106 -219
- package/dist/LinearPileupDisplay/model.js +47 -444
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/shared/color.d.ts +10 -0
- package/dist/shared/color.js +7 -1
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +492 -0
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +499 -0
- package/esm/LinearPileupDisplay/index.d.ts +1 -0
- package/esm/LinearPileupDisplay/index.js +1 -0
- package/esm/LinearPileupDisplay/model.d.ts +106 -219
- package/esm/LinearPileupDisplay/model.js +48 -445
- package/esm/index.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/shared/color.d.ts +10 -0
- package/esm/shared/color.js +6 -0
- package/package.json +2 -2
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { lazy } from 'react';
|
|
2
|
+
import { autorun, observable } from 'mobx';
|
|
3
|
+
import { cast, types, addDisposer, getSnapshot } from 'mobx-state-tree';
|
|
4
|
+
import copy from 'copy-to-clipboard';
|
|
5
|
+
import { ConfigurationReference, readConfObject, getConf, } from '@jbrowse/core/configuration';
|
|
6
|
+
import { getRpcSessionId } from '@jbrowse/core/util/tracks';
|
|
7
|
+
import { getEnv, getSession, isSessionModelWithWidgets, getContainingView, SimpleFeature, } from '@jbrowse/core/util';
|
|
8
|
+
import { BaseLinearDisplay, } from '@jbrowse/plugin-linear-genome-view';
|
|
9
|
+
// icons
|
|
10
|
+
import { ContentCopy as ContentCopyIcon } from '@jbrowse/core/ui/Icons';
|
|
11
|
+
import MenuOpenIcon from '@mui/icons-material/MenuOpen';
|
|
12
|
+
import FilterListIcon from '@mui/icons-material/ClearAll';
|
|
13
|
+
// locals
|
|
14
|
+
import LinearPileupDisplayBlurb from './components/LinearPileupDisplayBlurb';
|
|
15
|
+
import { getUniqueTagValues, FilterModel } from '../shared';
|
|
16
|
+
import { createAutorun } from '../util';
|
|
17
|
+
import { ColorByModel } from '../shared/color';
|
|
18
|
+
// async
|
|
19
|
+
const FilterByTagDlg = lazy(() => import('../shared/FilterByTag'));
|
|
20
|
+
const ColorByTagDlg = lazy(() => import('./components/ColorByTag'));
|
|
21
|
+
const SetFeatureHeightDlg = lazy(() => import('./components/SetFeatureHeight'));
|
|
22
|
+
const SetMaxHeightDlg = lazy(() => import('./components/SetMaxHeight'));
|
|
23
|
+
// using a map because it preserves order
|
|
24
|
+
const rendererTypes = new Map([
|
|
25
|
+
['pileup', 'PileupRenderer'],
|
|
26
|
+
['svg', 'SvgFeatureRenderer'],
|
|
27
|
+
]);
|
|
28
|
+
/**
|
|
29
|
+
* #stateModel SharedLinearPileupDisplayMixin
|
|
30
|
+
* #category display
|
|
31
|
+
* extends `BaseLinearDisplay`
|
|
32
|
+
*/
|
|
33
|
+
export function SharedLinearPileupDisplayMixin(configSchema) {
|
|
34
|
+
return types
|
|
35
|
+
.compose(BaseLinearDisplay, types.model({
|
|
36
|
+
/**
|
|
37
|
+
* #property
|
|
38
|
+
*/
|
|
39
|
+
configuration: ConfigurationReference(configSchema),
|
|
40
|
+
/**
|
|
41
|
+
* #property
|
|
42
|
+
*/
|
|
43
|
+
featureHeight: types.maybe(types.number),
|
|
44
|
+
/**
|
|
45
|
+
* #property
|
|
46
|
+
*/
|
|
47
|
+
noSpacing: types.maybe(types.boolean),
|
|
48
|
+
/**
|
|
49
|
+
* #property
|
|
50
|
+
*/
|
|
51
|
+
fadeLikelihood: types.maybe(types.boolean),
|
|
52
|
+
/**
|
|
53
|
+
* #property
|
|
54
|
+
*/
|
|
55
|
+
trackMaxHeight: types.maybe(types.number),
|
|
56
|
+
/**
|
|
57
|
+
* #property
|
|
58
|
+
*/
|
|
59
|
+
colorBy: ColorByModel,
|
|
60
|
+
/**
|
|
61
|
+
* #property
|
|
62
|
+
*/
|
|
63
|
+
filterBy: types.optional(FilterModel, {}),
|
|
64
|
+
}))
|
|
65
|
+
.volatile(() => ({
|
|
66
|
+
colorTagMap: observable.map({}),
|
|
67
|
+
featureUnderMouseVolatile: undefined,
|
|
68
|
+
tagsReady: false,
|
|
69
|
+
}))
|
|
70
|
+
.views(self => ({
|
|
71
|
+
get autorunReady() {
|
|
72
|
+
const view = getContainingView(self);
|
|
73
|
+
return (view.initialized &&
|
|
74
|
+
self.featureDensityStatsReady &&
|
|
75
|
+
!self.regionTooLarge);
|
|
76
|
+
},
|
|
77
|
+
}))
|
|
78
|
+
.actions(self => ({
|
|
79
|
+
/**
|
|
80
|
+
* #action
|
|
81
|
+
*/
|
|
82
|
+
setTagsReady(flag) {
|
|
83
|
+
self.tagsReady = flag;
|
|
84
|
+
},
|
|
85
|
+
/**
|
|
86
|
+
* #action
|
|
87
|
+
*/
|
|
88
|
+
setMaxHeight(n) {
|
|
89
|
+
self.trackMaxHeight = n;
|
|
90
|
+
},
|
|
91
|
+
/**
|
|
92
|
+
* #action
|
|
93
|
+
*/
|
|
94
|
+
setFeatureHeight(n) {
|
|
95
|
+
self.featureHeight = n;
|
|
96
|
+
},
|
|
97
|
+
/**
|
|
98
|
+
* #action
|
|
99
|
+
*/
|
|
100
|
+
setNoSpacing(flag) {
|
|
101
|
+
self.noSpacing = flag;
|
|
102
|
+
},
|
|
103
|
+
/**
|
|
104
|
+
* #action
|
|
105
|
+
*/
|
|
106
|
+
setColorScheme(colorScheme) {
|
|
107
|
+
self.colorTagMap = observable.map({}); // clear existing mapping
|
|
108
|
+
self.colorBy = cast(colorScheme);
|
|
109
|
+
if (colorScheme.tag) {
|
|
110
|
+
self.tagsReady = false;
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
/**
|
|
114
|
+
* #action
|
|
115
|
+
*/
|
|
116
|
+
updateColorTagMap(uniqueTag) {
|
|
117
|
+
// pale color scheme
|
|
118
|
+
// https://cran.r-project.org/web/packages/khroma/vignettes/tol.html
|
|
119
|
+
// e.g. "tol_light"
|
|
120
|
+
const colorPalette = [
|
|
121
|
+
'#BBCCEE',
|
|
122
|
+
'pink',
|
|
123
|
+
'#CCDDAA',
|
|
124
|
+
'#EEEEBB',
|
|
125
|
+
'#FFCCCC',
|
|
126
|
+
'lightblue',
|
|
127
|
+
'lightgreen',
|
|
128
|
+
'tan',
|
|
129
|
+
'#CCEEFF',
|
|
130
|
+
'lightsalmon',
|
|
131
|
+
];
|
|
132
|
+
uniqueTag.forEach(value => {
|
|
133
|
+
if (!self.colorTagMap.has(value)) {
|
|
134
|
+
const totalKeys = [...self.colorTagMap.keys()].length;
|
|
135
|
+
self.colorTagMap.set(value, colorPalette[totalKeys]);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
/**
|
|
140
|
+
* #action
|
|
141
|
+
*/
|
|
142
|
+
setFeatureUnderMouse(feat) {
|
|
143
|
+
self.featureUnderMouseVolatile = feat;
|
|
144
|
+
},
|
|
145
|
+
/**
|
|
146
|
+
* #action
|
|
147
|
+
*/
|
|
148
|
+
selectFeature(feature) {
|
|
149
|
+
const session = getSession(self);
|
|
150
|
+
if (isSessionModelWithWidgets(session)) {
|
|
151
|
+
const featureWidget = session.addWidget('AlignmentsFeatureWidget', 'alignmentFeature', { featureData: feature.toJSON(), view: getContainingView(self) });
|
|
152
|
+
session.showWidget(featureWidget);
|
|
153
|
+
}
|
|
154
|
+
session.setSelection(feature);
|
|
155
|
+
},
|
|
156
|
+
/**
|
|
157
|
+
* #action
|
|
158
|
+
* uses copy-to-clipboard and generates notification
|
|
159
|
+
*/
|
|
160
|
+
copyFeatureToClipboard(feature) {
|
|
161
|
+
const { uniqueId, ...rest } = feature.toJSON();
|
|
162
|
+
const session = getSession(self);
|
|
163
|
+
copy(JSON.stringify(rest, null, 4));
|
|
164
|
+
session.notify('Copied to clipboard', 'success');
|
|
165
|
+
},
|
|
166
|
+
/**
|
|
167
|
+
* #action
|
|
168
|
+
*/
|
|
169
|
+
setConfig(conf) {
|
|
170
|
+
self.configuration = conf;
|
|
171
|
+
},
|
|
172
|
+
/**
|
|
173
|
+
* #action
|
|
174
|
+
*/
|
|
175
|
+
setFilterBy(filter) {
|
|
176
|
+
self.filterBy = cast(filter);
|
|
177
|
+
},
|
|
178
|
+
}))
|
|
179
|
+
.views(self => ({
|
|
180
|
+
/**
|
|
181
|
+
* #getter
|
|
182
|
+
*/
|
|
183
|
+
get rendererConfig() {
|
|
184
|
+
const { featureHeight, noSpacing, trackMaxHeight, rendererTypeName } = self;
|
|
185
|
+
const configBlob = getConf(self, ['renderers', rendererTypeName]) || {};
|
|
186
|
+
return self.rendererType.configSchema.create({
|
|
187
|
+
...configBlob,
|
|
188
|
+
...(featureHeight !== undefined ? { height: featureHeight } : {}),
|
|
189
|
+
...(noSpacing !== undefined ? { noSpacing } : {}),
|
|
190
|
+
...(trackMaxHeight !== undefined
|
|
191
|
+
? { maxHeight: trackMaxHeight }
|
|
192
|
+
: {}),
|
|
193
|
+
}, getEnv(self));
|
|
194
|
+
},
|
|
195
|
+
}))
|
|
196
|
+
.views(self => ({
|
|
197
|
+
/**
|
|
198
|
+
* #getter
|
|
199
|
+
*/
|
|
200
|
+
get maxHeight() {
|
|
201
|
+
return readConfObject(self.rendererConfig, 'maxHeight');
|
|
202
|
+
},
|
|
203
|
+
/**
|
|
204
|
+
* #getter
|
|
205
|
+
*/
|
|
206
|
+
get featureHeightSetting() {
|
|
207
|
+
return readConfObject(self.rendererConfig, 'height');
|
|
208
|
+
},
|
|
209
|
+
/**
|
|
210
|
+
* #getter
|
|
211
|
+
*/
|
|
212
|
+
get featureUnderMouse() {
|
|
213
|
+
return self.featureUnderMouseVolatile;
|
|
214
|
+
},
|
|
215
|
+
/**
|
|
216
|
+
* #getter
|
|
217
|
+
*/
|
|
218
|
+
renderReady() {
|
|
219
|
+
return self.tagsReady;
|
|
220
|
+
},
|
|
221
|
+
}))
|
|
222
|
+
.views(self => {
|
|
223
|
+
const { trackMenuItems: superTrackMenuItems, renderProps: superRenderProps, } = self;
|
|
224
|
+
return {
|
|
225
|
+
/**
|
|
226
|
+
* #getter
|
|
227
|
+
*/
|
|
228
|
+
get rendererTypeName() {
|
|
229
|
+
const viewName = getConf(self, 'defaultRendering');
|
|
230
|
+
const rendererType = rendererTypes.get(viewName);
|
|
231
|
+
if (!rendererType) {
|
|
232
|
+
throw new Error(`unknown alignments view name ${viewName}`);
|
|
233
|
+
}
|
|
234
|
+
return rendererType;
|
|
235
|
+
},
|
|
236
|
+
/**
|
|
237
|
+
* #method
|
|
238
|
+
*/
|
|
239
|
+
contextMenuItems() {
|
|
240
|
+
const feat = self.contextMenuFeature;
|
|
241
|
+
return feat
|
|
242
|
+
? [
|
|
243
|
+
{
|
|
244
|
+
label: 'Open feature details',
|
|
245
|
+
icon: MenuOpenIcon,
|
|
246
|
+
onClick: () => {
|
|
247
|
+
self.clearFeatureSelection();
|
|
248
|
+
if (feat) {
|
|
249
|
+
self.selectFeature(feat);
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
label: 'Copy info to clipboard',
|
|
255
|
+
icon: ContentCopyIcon,
|
|
256
|
+
onClick: () => {
|
|
257
|
+
if (feat) {
|
|
258
|
+
self.copyFeatureToClipboard(feat);
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
]
|
|
263
|
+
: [];
|
|
264
|
+
},
|
|
265
|
+
/**
|
|
266
|
+
* #getter
|
|
267
|
+
*/
|
|
268
|
+
get DisplayBlurb() {
|
|
269
|
+
return LinearPileupDisplayBlurb;
|
|
270
|
+
},
|
|
271
|
+
/**
|
|
272
|
+
* #method
|
|
273
|
+
*/
|
|
274
|
+
renderPropsPre() {
|
|
275
|
+
const { colorTagMap, colorBy, filterBy, rpcDriverName } = self;
|
|
276
|
+
const superProps = superRenderProps();
|
|
277
|
+
return {
|
|
278
|
+
...superProps,
|
|
279
|
+
notReady: superProps.notReady || !self.renderReady(),
|
|
280
|
+
rpcDriverName,
|
|
281
|
+
displayModel: self,
|
|
282
|
+
colorBy: colorBy ? getSnapshot(colorBy) : undefined,
|
|
283
|
+
filterBy: JSON.parse(JSON.stringify(filterBy)),
|
|
284
|
+
colorTagMap: Object.fromEntries(colorTagMap.toJSON()),
|
|
285
|
+
config: self.rendererConfig,
|
|
286
|
+
async onFeatureClick(_, featureId) {
|
|
287
|
+
const session = getSession(self);
|
|
288
|
+
const { rpcManager } = session;
|
|
289
|
+
try {
|
|
290
|
+
const f = featureId || self.featureIdUnderMouse;
|
|
291
|
+
if (!f) {
|
|
292
|
+
self.clearFeatureSelection();
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
const sessionId = getRpcSessionId(self);
|
|
296
|
+
const { feature } = (await rpcManager.call(sessionId, 'CoreGetFeatureDetails', {
|
|
297
|
+
featureId: f,
|
|
298
|
+
sessionId,
|
|
299
|
+
layoutId: getContainingView(self).id,
|
|
300
|
+
rendererType: 'PileupRenderer',
|
|
301
|
+
}));
|
|
302
|
+
if (feature) {
|
|
303
|
+
self.selectFeature(new SimpleFeature(feature));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch (e) {
|
|
308
|
+
console.error(e);
|
|
309
|
+
session.notify(`${e}`);
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
onClick() {
|
|
313
|
+
self.clearFeatureSelection();
|
|
314
|
+
},
|
|
315
|
+
// similar to click but opens a menu with further options
|
|
316
|
+
async onFeatureContextMenu(_, featureId) {
|
|
317
|
+
const session = getSession(self);
|
|
318
|
+
const { rpcManager } = session;
|
|
319
|
+
try {
|
|
320
|
+
const f = featureId || self.featureIdUnderMouse;
|
|
321
|
+
if (!f) {
|
|
322
|
+
self.clearFeatureSelection();
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
const sessionId = getRpcSessionId(self);
|
|
326
|
+
const { feature } = (await rpcManager.call(sessionId, 'CoreGetFeatureDetails', {
|
|
327
|
+
featureId: f,
|
|
328
|
+
sessionId,
|
|
329
|
+
layoutId: getContainingView(self).id,
|
|
330
|
+
rendererType: 'PileupRenderer',
|
|
331
|
+
}));
|
|
332
|
+
if (feature) {
|
|
333
|
+
self.setContextMenuFeature(new SimpleFeature(feature));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch (e) {
|
|
338
|
+
console.error(e);
|
|
339
|
+
session.notify(`${e}`);
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
},
|
|
344
|
+
/**
|
|
345
|
+
* #method
|
|
346
|
+
*/
|
|
347
|
+
colorSchemeSubMenuItems() {
|
|
348
|
+
return [
|
|
349
|
+
{
|
|
350
|
+
label: 'Normal',
|
|
351
|
+
onClick: () => self.setColorScheme({ type: 'normal' }),
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
label: 'Mapping quality',
|
|
355
|
+
onClick: () => self.setColorScheme({ type: 'mappingQuality' }),
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
label: 'Strand',
|
|
359
|
+
onClick: () => self.setColorScheme({ type: 'strand' }),
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
label: 'Per-base quality',
|
|
363
|
+
onClick: () => self.setColorScheme({ type: 'perBaseQuality' }),
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
label: 'Per-base lettering',
|
|
367
|
+
onClick: () => self.setColorScheme({ type: 'perBaseLettering' }),
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
label: 'First-of-pair strand',
|
|
371
|
+
onClick: () => self.setColorScheme({ type: 'stranded' }),
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
label: 'Color by tag...',
|
|
375
|
+
onClick: () => {
|
|
376
|
+
getSession(self).queueDialog(doneCallback => [
|
|
377
|
+
ColorByTagDlg,
|
|
378
|
+
{ model: self, handleClose: doneCallback },
|
|
379
|
+
]);
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
];
|
|
383
|
+
},
|
|
384
|
+
/**
|
|
385
|
+
* #method
|
|
386
|
+
*/
|
|
387
|
+
trackMenuItems() {
|
|
388
|
+
return [
|
|
389
|
+
...superTrackMenuItems(),
|
|
390
|
+
{
|
|
391
|
+
label: 'Filter by',
|
|
392
|
+
icon: FilterListIcon,
|
|
393
|
+
onClick: () => {
|
|
394
|
+
getSession(self).queueDialog(doneCallback => [
|
|
395
|
+
FilterByTagDlg,
|
|
396
|
+
{ model: self, handleClose: doneCallback },
|
|
397
|
+
]);
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
label: 'Set feature height',
|
|
402
|
+
subMenu: [
|
|
403
|
+
{
|
|
404
|
+
label: 'Normal',
|
|
405
|
+
onClick: () => {
|
|
406
|
+
self.setFeatureHeight(7);
|
|
407
|
+
self.setNoSpacing(false);
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
label: 'Compact',
|
|
412
|
+
onClick: () => {
|
|
413
|
+
self.setFeatureHeight(2);
|
|
414
|
+
self.setNoSpacing(true);
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
label: 'Manually set height',
|
|
419
|
+
onClick: () => {
|
|
420
|
+
getSession(self).queueDialog(doneCallback => [
|
|
421
|
+
SetFeatureHeightDlg,
|
|
422
|
+
{ model: self, handleClose: doneCallback },
|
|
423
|
+
]);
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
],
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
label: 'Set max height...',
|
|
430
|
+
onClick: () => {
|
|
431
|
+
getSession(self).queueDialog(doneCallback => [
|
|
432
|
+
SetMaxHeightDlg,
|
|
433
|
+
{ model: self, handleClose: doneCallback },
|
|
434
|
+
]);
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
];
|
|
438
|
+
},
|
|
439
|
+
};
|
|
440
|
+
})
|
|
441
|
+
.views(self => ({
|
|
442
|
+
renderProps() {
|
|
443
|
+
return self.renderPropsPre();
|
|
444
|
+
},
|
|
445
|
+
}))
|
|
446
|
+
.actions(self => ({
|
|
447
|
+
afterAttach() {
|
|
448
|
+
createAutorun(self, async () => {
|
|
449
|
+
const view = getContainingView(self);
|
|
450
|
+
if (!self.autorunReady) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const { colorBy } = self;
|
|
454
|
+
const { staticBlocks } = view;
|
|
455
|
+
if (colorBy === null || colorBy === void 0 ? void 0 : colorBy.tag) {
|
|
456
|
+
const vals = await getUniqueTagValues(self, colorBy, staticBlocks);
|
|
457
|
+
self.updateColorTagMap(vals);
|
|
458
|
+
}
|
|
459
|
+
self.setTagsReady(true);
|
|
460
|
+
}, { delay: 1000 });
|
|
461
|
+
// autorun synchronizes featureUnderMouse with featureIdUnderMouse
|
|
462
|
+
// asynchronously. this is needed due to how we do not serialize all
|
|
463
|
+
// features from the BAM/CRAM over the rpc
|
|
464
|
+
addDisposer(self, autorun(async () => {
|
|
465
|
+
var _a;
|
|
466
|
+
const session = getSession(self);
|
|
467
|
+
try {
|
|
468
|
+
const featureId = self.featureIdUnderMouse;
|
|
469
|
+
if (((_a = self.featureUnderMouse) === null || _a === void 0 ? void 0 : _a.id()) !== featureId) {
|
|
470
|
+
if (!featureId) {
|
|
471
|
+
self.setFeatureUnderMouse(undefined);
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
const sessionId = getRpcSessionId(self);
|
|
475
|
+
const view = getContainingView(self);
|
|
476
|
+
const { feature } = (await session.rpcManager.call(sessionId, 'CoreGetFeatureDetails', {
|
|
477
|
+
featureId,
|
|
478
|
+
sessionId,
|
|
479
|
+
layoutId: view.id,
|
|
480
|
+
rendererType: 'PileupRenderer',
|
|
481
|
+
}));
|
|
482
|
+
// check featureIdUnderMouse is still the same as the
|
|
483
|
+
// feature.id that was returned e.g. that the user hasn't
|
|
484
|
+
// moused over to a new position during the async operation
|
|
485
|
+
// above
|
|
486
|
+
if (self.featureIdUnderMouse === feature.uniqueId) {
|
|
487
|
+
self.setFeatureUnderMouse(new SimpleFeature(feature));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
catch (e) {
|
|
493
|
+
console.error(e);
|
|
494
|
+
session.notify(`${e}`, 'error');
|
|
495
|
+
}
|
|
496
|
+
}));
|
|
497
|
+
},
|
|
498
|
+
}));
|
|
499
|
+
}
|
|
@@ -2,3 +2,4 @@ import PluginManager from '@jbrowse/core/PluginManager';
|
|
|
2
2
|
export default function register(pluginManager: PluginManager): void;
|
|
3
3
|
export { default as linearPileupDisplayStateModelFactory } from './model';
|
|
4
4
|
export { default as linearPileupDisplayConfigSchemaFactory } from './configSchema';
|
|
5
|
+
export { SharedLinearPileupDisplayMixin } from './SharedLinearPileupDisplayMixin';
|
|
@@ -19,3 +19,4 @@ export default function register(pluginManager) {
|
|
|
19
19
|
}
|
|
20
20
|
export { default as linearPileupDisplayStateModelFactory } from './model';
|
|
21
21
|
export { default as linearPileupDisplayConfigSchemaFactory } from './configSchema';
|
|
22
|
+
export { SharedLinearPileupDisplayMixin } from './SharedLinearPileupDisplayMixin';
|