@jbrowse/plugin-linear-genome-view 2.1.6 → 2.2.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/BaseLinearDisplay/components/LinearBlocks.d.ts +2 -2
- package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +2 -22
- package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +146 -1
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +600 -464
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
- package/dist/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js +19 -1
- package/dist/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js.map +1 -1
- package/dist/BasicTrack/configSchema.d.ts +3 -0
- package/dist/BasicTrack/configSchema.js +18 -0
- package/dist/BasicTrack/configSchema.js.map +1 -0
- package/dist/BasicTrack/index.d.ts +3 -0
- package/dist/BasicTrack/index.js +18 -0
- package/dist/BasicTrack/index.js.map +1 -0
- package/dist/FeatureTrack/configSchema.d.ts +3 -0
- package/dist/FeatureTrack/configSchema.js +21 -0
- package/dist/FeatureTrack/configSchema.js.map +1 -0
- package/dist/FeatureTrack/index.d.ts +3 -0
- package/dist/FeatureTrack/index.js +18 -0
- package/dist/FeatureTrack/index.js.map +1 -0
- package/dist/LinearBareDisplay/configSchema.d.ts +5 -1
- package/dist/LinearBareDisplay/configSchema.js +12 -1
- package/dist/LinearBareDisplay/configSchema.js.map +1 -1
- package/dist/LinearBareDisplay/model.d.ts +16 -0
- package/dist/LinearBareDisplay/model.js +16 -0
- package/dist/LinearBareDisplay/model.js.map +1 -1
- package/dist/LinearBasicDisplay/configSchema.d.ts +5 -1
- package/dist/LinearBasicDisplay/configSchema.js +16 -1
- package/dist/LinearBasicDisplay/configSchema.js.map +1 -1
- package/dist/LinearBasicDisplay/model.d.ts +77 -6
- package/dist/LinearBasicDisplay/model.js +167 -111
- package/dist/LinearBasicDisplay/model.js.map +1 -1
- package/dist/LinearGenomeView/components/ImportForm.js +34 -28
- package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeView.js +1 -21
- package/dist/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js +7 -5
- package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js.map +1 -1
- package/dist/LinearGenomeView/components/OverviewScaleBar.d.ts +26 -34
- package/dist/LinearGenomeView/index.d.ts +189 -15
- package/dist/LinearGenomeView/index.js +266 -27
- package/dist/LinearGenomeView/index.js.map +1 -1
- package/dist/index.d.ts +12 -84
- package/dist/index.js +4 -25
- package/dist/index.js.map +1 -1
- package/esm/BaseLinearDisplay/components/LinearBlocks.d.ts +2 -2
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +2 -22
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +146 -1
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +600 -464
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
- package/esm/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js +19 -1
- package/esm/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js.map +1 -1
- package/esm/BasicTrack/configSchema.d.ts +3 -0
- package/esm/BasicTrack/configSchema.js +16 -0
- package/esm/BasicTrack/configSchema.js.map +1 -0
- package/esm/BasicTrack/index.d.ts +3 -0
- package/esm/BasicTrack/index.js +13 -0
- package/esm/BasicTrack/index.js.map +1 -0
- package/esm/FeatureTrack/configSchema.d.ts +3 -0
- package/esm/FeatureTrack/configSchema.js +19 -0
- package/esm/FeatureTrack/configSchema.js.map +1 -0
- package/esm/FeatureTrack/index.d.ts +3 -0
- package/esm/FeatureTrack/index.js +13 -0
- package/esm/FeatureTrack/index.js.map +1 -0
- package/esm/LinearBareDisplay/configSchema.d.ts +5 -1
- package/esm/LinearBareDisplay/configSchema.js +14 -2
- package/esm/LinearBareDisplay/configSchema.js.map +1 -1
- package/esm/LinearBareDisplay/model.d.ts +16 -0
- package/esm/LinearBareDisplay/model.js +16 -0
- package/esm/LinearBareDisplay/model.js.map +1 -1
- package/esm/LinearBasicDisplay/configSchema.d.ts +5 -1
- package/esm/LinearBasicDisplay/configSchema.js +18 -2
- package/esm/LinearBasicDisplay/configSchema.js.map +1 -1
- package/esm/LinearBasicDisplay/model.d.ts +77 -6
- package/esm/LinearBasicDisplay/model.js +167 -111
- package/esm/LinearBasicDisplay/model.js.map +1 -1
- package/esm/LinearGenomeView/components/ImportForm.js +36 -30
- package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.js +2 -22
- package/esm/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeViewSvg.js +7 -5
- package/esm/LinearGenomeView/components/LinearGenomeViewSvg.js.map +1 -1
- package/esm/LinearGenomeView/components/OverviewScaleBar.d.ts +26 -34
- package/esm/LinearGenomeView/index.d.ts +189 -15
- package/esm/LinearGenomeView/index.js +266 -27
- package/esm/LinearGenomeView/index.js.map +1 -1
- package/esm/index.d.ts +12 -84
- package/esm/index.js +4 -25
- package/esm/index.js.map +1 -1
- package/package.json +2 -2
- package/src/BaseLinearDisplay/components/ServerSideRenderedBlockContent.tsx +2 -24
- package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +695 -555
- package/src/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.ts +20 -1
- package/src/BasicTrack/configSchema.ts +23 -0
- package/src/BasicTrack/index.ts +22 -0
- package/src/FeatureTrack/configSchema.ts +27 -0
- package/src/FeatureTrack/index.ts +21 -0
- package/src/LinearBareDisplay/configSchema.ts +15 -2
- package/src/LinearBareDisplay/model.ts +16 -0
- package/src/LinearBasicDisplay/configSchema.ts +19 -2
- package/src/LinearBasicDisplay/model.ts +63 -11
- package/src/LinearGenomeView/components/ImportForm.tsx +79 -63
- package/src/LinearGenomeView/components/LinearGenomeView.tsx +2 -26
- package/src/LinearGenomeView/components/LinearGenomeViewSvg.tsx +21 -18
- package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.tsx.snap +204 -204
- package/src/LinearGenomeView/index.test.ts +33 -26
- package/src/LinearGenomeView/index.tsx +317 -60
- package/src/index.ts +6 -46
|
@@ -70,7 +70,7 @@ function calculateVisibleLocStrings(contentBlocks) {
|
|
|
70
70
|
if (!contentBlocks.length) {
|
|
71
71
|
return '';
|
|
72
72
|
}
|
|
73
|
-
const isSingleAssemblyName = contentBlocks.every(
|
|
73
|
+
const isSingleAssemblyName = contentBlocks.every(b => b.assemblyName === contentBlocks[0].assemblyName);
|
|
74
74
|
const locs = contentBlocks.map(block => (0, util_1.assembleLocString)({
|
|
75
75
|
...block,
|
|
76
76
|
start: Math.round(block.start),
|
|
@@ -91,30 +91,84 @@ function localStorageGetItem(item) {
|
|
|
91
91
|
? localStorage.getItem(item)
|
|
92
92
|
: undefined;
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* #stateModel LinearGenomeView
|
|
96
|
+
*/
|
|
94
97
|
function stateModelFactory(pluginManager) {
|
|
95
98
|
return mobx_state_tree_1.types
|
|
96
99
|
.compose(models_1.BaseViewModel, mobx_state_tree_1.types.model('LinearGenomeView', {
|
|
100
|
+
/**
|
|
101
|
+
* #property
|
|
102
|
+
*/
|
|
97
103
|
id: mst_1.ElementId,
|
|
104
|
+
/**
|
|
105
|
+
* #property
|
|
106
|
+
*/
|
|
98
107
|
type: mobx_state_tree_1.types.literal('LinearGenomeView'),
|
|
108
|
+
/**
|
|
109
|
+
* #property
|
|
110
|
+
* corresponds roughly to the horizontal scroll of the LGV
|
|
111
|
+
*/
|
|
99
112
|
offsetPx: 0,
|
|
113
|
+
/**
|
|
114
|
+
* #property
|
|
115
|
+
* corresponds roughly to the zoom level, base-pairs per pixel
|
|
116
|
+
*/
|
|
100
117
|
bpPerPx: 1,
|
|
118
|
+
/**
|
|
119
|
+
* #property
|
|
120
|
+
* currently displayed regions, can be a single chromosome, arbitrary subsections,
|
|
121
|
+
* or the entire set of chromosomes in the genome, but it not advised to use the
|
|
122
|
+
* entire set of chromosomes if your assembly is very fragmented
|
|
123
|
+
*/
|
|
101
124
|
displayedRegions: mobx_state_tree_1.types.array(mst_1.Region),
|
|
102
|
-
|
|
103
|
-
|
|
125
|
+
/**
|
|
126
|
+
* #property
|
|
127
|
+
* array of currently displayed tracks state models instances
|
|
128
|
+
*/
|
|
104
129
|
tracks: mobx_state_tree_1.types.array(pluginManager.pluggableMstType('track', 'stateModel')),
|
|
130
|
+
/**
|
|
131
|
+
* #property
|
|
132
|
+
* array of currently displayed tracks state model's
|
|
133
|
+
*/
|
|
105
134
|
hideHeader: false,
|
|
135
|
+
/**
|
|
136
|
+
* #property
|
|
137
|
+
*/
|
|
106
138
|
hideHeaderOverview: false,
|
|
139
|
+
/**
|
|
140
|
+
* #property
|
|
141
|
+
*/
|
|
107
142
|
hideNoTracksActive: false,
|
|
143
|
+
/**
|
|
144
|
+
* #property
|
|
145
|
+
*/
|
|
108
146
|
trackSelectorType: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.enumeration(['hierarchical']), 'hierarchical'),
|
|
147
|
+
/**
|
|
148
|
+
* #property
|
|
149
|
+
* how to display the track labels, can be "overlapping", "offset", or "hidden"
|
|
150
|
+
*/
|
|
109
151
|
trackLabels: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.string, () => localStorageGetItem('lgv-trackLabels') || 'overlapping'),
|
|
152
|
+
/**
|
|
153
|
+
* #property
|
|
154
|
+
* show the "center line"
|
|
155
|
+
*/
|
|
110
156
|
showCenterLine: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.boolean, () => {
|
|
111
157
|
const setting = localStorageGetItem('lgv-showCenterLine');
|
|
112
158
|
return setting !== undefined && setting !== null ? !!+setting : false;
|
|
113
159
|
}),
|
|
160
|
+
/**
|
|
161
|
+
* #property
|
|
162
|
+
* show the "cytobands" in the overview scale bar
|
|
163
|
+
*/
|
|
114
164
|
showCytobandsSetting: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.boolean, () => {
|
|
115
165
|
const setting = localStorageGetItem('lgv-showCytobands');
|
|
116
166
|
return setting !== undefined && setting !== null ? !!+setting : true;
|
|
117
167
|
}),
|
|
168
|
+
/**
|
|
169
|
+
* #property
|
|
170
|
+
* show the "gridlines" in the track area
|
|
171
|
+
*/
|
|
118
172
|
showGridlines: true,
|
|
119
173
|
}))
|
|
120
174
|
.volatile(() => ({
|
|
@@ -137,15 +191,24 @@ function stateModelFactory(pluginManager) {
|
|
|
137
191
|
seqDialogDisplayed: false,
|
|
138
192
|
}))
|
|
139
193
|
.views(self => ({
|
|
194
|
+
/**
|
|
195
|
+
* #getter
|
|
196
|
+
*/
|
|
140
197
|
get width() {
|
|
141
198
|
if (self.volatileWidth === undefined) {
|
|
142
199
|
throw new Error('width undefined, make sure to check for model.initialized');
|
|
143
200
|
}
|
|
144
201
|
return self.volatileWidth;
|
|
145
202
|
},
|
|
203
|
+
/**
|
|
204
|
+
* #getter
|
|
205
|
+
*/
|
|
146
206
|
get interRegionPaddingWidth() {
|
|
147
207
|
return exports.INTER_REGION_PADDING_WIDTH;
|
|
148
208
|
},
|
|
209
|
+
/**
|
|
210
|
+
* #getter
|
|
211
|
+
*/
|
|
149
212
|
get assemblyNames() {
|
|
150
213
|
return [
|
|
151
214
|
...new Set(self.displayedRegions.map(region => region.assemblyName)),
|
|
@@ -293,33 +356,60 @@ function stateModelFactory(pluginManager) {
|
|
|
293
356
|
},
|
|
294
357
|
}))
|
|
295
358
|
.actions(self => ({
|
|
359
|
+
/**
|
|
360
|
+
* #action
|
|
361
|
+
*/
|
|
296
362
|
setShowCytobands(flag) {
|
|
297
363
|
self.showCytobandsSetting = flag;
|
|
298
364
|
localStorage.setItem('lgv-showCytobands', `${+flag}`);
|
|
299
365
|
},
|
|
366
|
+
/**
|
|
367
|
+
* #action
|
|
368
|
+
*/
|
|
300
369
|
setWidth(newWidth) {
|
|
301
370
|
self.volatileWidth = newWidth;
|
|
302
371
|
},
|
|
372
|
+
/**
|
|
373
|
+
* #action
|
|
374
|
+
*/
|
|
303
375
|
setError(error) {
|
|
304
376
|
self.volatileError = error;
|
|
305
377
|
},
|
|
378
|
+
/**
|
|
379
|
+
* #action
|
|
380
|
+
*/
|
|
306
381
|
toggleHeader() {
|
|
307
382
|
self.hideHeader = !self.hideHeader;
|
|
308
383
|
},
|
|
384
|
+
/**
|
|
385
|
+
* #action
|
|
386
|
+
*/
|
|
309
387
|
toggleHeaderOverview() {
|
|
310
388
|
self.hideHeaderOverview = !self.hideHeaderOverview;
|
|
311
389
|
},
|
|
390
|
+
/**
|
|
391
|
+
* #action
|
|
392
|
+
*/
|
|
312
393
|
toggleNoTracksActive() {
|
|
313
394
|
self.hideNoTracksActive = !self.hideNoTracksActive;
|
|
314
395
|
},
|
|
396
|
+
/**
|
|
397
|
+
* #action
|
|
398
|
+
*/
|
|
315
399
|
toggleShowGridlines() {
|
|
316
400
|
self.showGridlines = !self.showGridlines;
|
|
317
401
|
},
|
|
402
|
+
/**
|
|
403
|
+
* #action
|
|
404
|
+
*/
|
|
318
405
|
scrollTo(offsetPx) {
|
|
319
406
|
const newOffsetPx = (0, util_1.clamp)(offsetPx, self.minOffset, self.maxOffset);
|
|
320
407
|
self.offsetPx = newOffsetPx;
|
|
321
408
|
return newOffsetPx;
|
|
322
409
|
},
|
|
410
|
+
/**
|
|
411
|
+
* #action
|
|
412
|
+
*/
|
|
323
413
|
zoomTo(bpPerPx) {
|
|
324
414
|
const newBpPerPx = (0, util_1.clamp)(bpPerPx, self.minBpPerPx, self.maxBpPerPx);
|
|
325
415
|
if (newBpPerPx === self.bpPerPx) {
|
|
@@ -337,22 +427,37 @@ function stateModelFactory(pluginManager) {
|
|
|
337
427
|
viewWidth / 2));
|
|
338
428
|
return newBpPerPx;
|
|
339
429
|
},
|
|
430
|
+
/**
|
|
431
|
+
* #action
|
|
432
|
+
* sets offsets used in the get sequence dialog
|
|
433
|
+
*/
|
|
340
434
|
setOffsets(left, right) {
|
|
341
|
-
// sets offsets used in the get sequence dialog
|
|
342
435
|
self.leftOffset = left;
|
|
343
436
|
self.rightOffset = right;
|
|
344
437
|
},
|
|
438
|
+
/**
|
|
439
|
+
* #action
|
|
440
|
+
*/
|
|
345
441
|
setSearchResults(results, query) {
|
|
346
442
|
self.searchResults = results;
|
|
347
443
|
self.searchQuery = query;
|
|
348
444
|
},
|
|
445
|
+
/**
|
|
446
|
+
* #action
|
|
447
|
+
*/
|
|
349
448
|
setGetSequenceDialogOpen(open) {
|
|
350
449
|
self.seqDialogDisplayed = open;
|
|
351
450
|
},
|
|
451
|
+
/**
|
|
452
|
+
* #action
|
|
453
|
+
*/
|
|
352
454
|
setNewView(bpPerPx, offsetPx) {
|
|
353
455
|
this.zoomTo(bpPerPx);
|
|
354
456
|
this.scrollTo(offsetPx);
|
|
355
457
|
},
|
|
458
|
+
/**
|
|
459
|
+
* #action
|
|
460
|
+
*/
|
|
356
461
|
horizontallyFlip() {
|
|
357
462
|
self.displayedRegions = (0, mobx_state_tree_1.cast)(self.displayedRegions
|
|
358
463
|
.slice()
|
|
@@ -360,6 +465,9 @@ function stateModelFactory(pluginManager) {
|
|
|
360
465
|
.map(region => ({ ...region, reversed: !region.reversed })));
|
|
361
466
|
this.scrollTo(self.totalBp / self.bpPerPx - self.offsetPx - self.width);
|
|
362
467
|
},
|
|
468
|
+
/**
|
|
469
|
+
* #action
|
|
470
|
+
*/
|
|
363
471
|
showTrack(trackId, initialSnapshot = {}, displayInitialSnapshot = {}) {
|
|
364
472
|
const schema = pluginManager.pluggableConfigSchemaType('track');
|
|
365
473
|
const conf = (0, mobx_state_tree_1.resolveIdentifier)(schema, (0, mobx_state_tree_1.getRoot)(self), trackId);
|
|
@@ -404,6 +512,9 @@ function stateModelFactory(pluginManager) {
|
|
|
404
512
|
},
|
|
405
513
|
}))
|
|
406
514
|
.actions(self => ({
|
|
515
|
+
/**
|
|
516
|
+
* #action
|
|
517
|
+
*/
|
|
407
518
|
moveTrack(movingId, targetId) {
|
|
408
519
|
const oldIndex = self.tracks.findIndex(track => track.id === movingId);
|
|
409
520
|
if (oldIndex === -1) {
|
|
@@ -417,6 +528,9 @@ function stateModelFactory(pluginManager) {
|
|
|
417
528
|
self.tracks.splice(oldIndex, 1);
|
|
418
529
|
self.tracks.splice(newIndex, 0, track);
|
|
419
530
|
},
|
|
531
|
+
/**
|
|
532
|
+
* #action
|
|
533
|
+
*/
|
|
420
534
|
closeView() {
|
|
421
535
|
const parent = (0, util_1.getContainingView)(self);
|
|
422
536
|
if (parent) {
|
|
@@ -430,6 +544,9 @@ function stateModelFactory(pluginManager) {
|
|
|
430
544
|
(0, util_1.getSession)(self).removeView(self);
|
|
431
545
|
}
|
|
432
546
|
},
|
|
547
|
+
/**
|
|
548
|
+
* #action
|
|
549
|
+
*/
|
|
433
550
|
toggleTrack(trackId) {
|
|
434
551
|
// if we have any tracks with that configuration, turn them off
|
|
435
552
|
const hiddenCount = self.hideTrack(trackId);
|
|
@@ -438,18 +555,30 @@ function stateModelFactory(pluginManager) {
|
|
|
438
555
|
self.showTrack(trackId);
|
|
439
556
|
}
|
|
440
557
|
},
|
|
558
|
+
/**
|
|
559
|
+
* #action
|
|
560
|
+
*/
|
|
441
561
|
setTrackLabels(setting) {
|
|
442
562
|
self.trackLabels = setting;
|
|
443
563
|
localStorage.setItem('lgv-trackLabels', setting);
|
|
444
564
|
},
|
|
565
|
+
/**
|
|
566
|
+
* #action
|
|
567
|
+
*/
|
|
445
568
|
toggleCenterLine() {
|
|
446
569
|
self.showCenterLine = !self.showCenterLine;
|
|
447
570
|
localStorage.setItem('lgv-showCenterLine', `${+self.showCenterLine}`);
|
|
448
571
|
},
|
|
572
|
+
/**
|
|
573
|
+
* #action
|
|
574
|
+
*/
|
|
449
575
|
setDisplayedRegions(regions) {
|
|
450
576
|
self.displayedRegions = (0, mobx_state_tree_1.cast)(regions);
|
|
451
577
|
self.zoomTo(self.bpPerPx);
|
|
452
578
|
},
|
|
579
|
+
/**
|
|
580
|
+
* #action
|
|
581
|
+
*/
|
|
453
582
|
activateTrackSelector() {
|
|
454
583
|
if (self.trackSelectorType === 'hierarchical') {
|
|
455
584
|
const session = (0, util_1.getSession)(self);
|
|
@@ -462,6 +591,7 @@ function stateModelFactory(pluginManager) {
|
|
|
462
591
|
throw new Error(`invalid track selector type ${self.trackSelectorType}`);
|
|
463
592
|
},
|
|
464
593
|
/**
|
|
594
|
+
* #method
|
|
465
595
|
* Helper method for the fetchSequence.
|
|
466
596
|
* Retrieves the corresponding regions that were selected by the rubberband
|
|
467
597
|
*
|
|
@@ -483,38 +613,51 @@ function stateModelFactory(pluginManager) {
|
|
|
483
613
|
end: Math.ceil(region.end),
|
|
484
614
|
}));
|
|
485
615
|
},
|
|
486
|
-
|
|
616
|
+
/**
|
|
617
|
+
* #action
|
|
618
|
+
* schedule something to be run after the next time displayedRegions is set
|
|
619
|
+
*/
|
|
487
620
|
afterDisplayedRegionsSet(cb) {
|
|
488
621
|
self.afterDisplayedRegionsSetCallbacks.push(cb);
|
|
489
622
|
},
|
|
623
|
+
/**
|
|
624
|
+
* #action
|
|
625
|
+
*/
|
|
490
626
|
horizontalScroll(distance) {
|
|
491
627
|
const oldOffsetPx = self.offsetPx;
|
|
492
628
|
// newOffsetPx is the actual offset after the scroll is clamped
|
|
493
629
|
const newOffsetPx = self.scrollTo(self.offsetPx + distance);
|
|
494
630
|
return newOffsetPx - oldOffsetPx;
|
|
495
631
|
},
|
|
632
|
+
/**
|
|
633
|
+
* #action
|
|
634
|
+
*/
|
|
496
635
|
center() {
|
|
497
636
|
const centerBp = self.totalBp / 2;
|
|
498
637
|
const centerPx = centerBp / self.bpPerPx;
|
|
499
638
|
self.scrollTo(Math.round(centerPx - self.width / 2));
|
|
500
639
|
},
|
|
640
|
+
/**
|
|
641
|
+
* #action
|
|
642
|
+
*/
|
|
501
643
|
showAllRegions() {
|
|
502
644
|
self.zoomTo(self.maxBpPerPx);
|
|
503
645
|
this.center();
|
|
504
646
|
},
|
|
647
|
+
/**
|
|
648
|
+
* #action
|
|
649
|
+
*/
|
|
505
650
|
showAllRegionsInAssembly(assemblyName) {
|
|
506
651
|
const session = (0, util_1.getSession)(self);
|
|
507
652
|
const { assemblyManager } = session;
|
|
508
653
|
if (!assemblyName) {
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
if (assemblyNames.length > 1) {
|
|
513
|
-
session.notify(`Can't perform this with multiple assemblies currently`);
|
|
654
|
+
const names = new Set(self.displayedRegions.map(r => r.assemblyName));
|
|
655
|
+
if (names.size > 1) {
|
|
656
|
+
session.notify(`Can't perform operation with multiple assemblies currently`);
|
|
514
657
|
return;
|
|
515
658
|
}
|
|
516
659
|
;
|
|
517
|
-
[assemblyName] =
|
|
660
|
+
[assemblyName] = [...names];
|
|
518
661
|
}
|
|
519
662
|
const assembly = assemblyManager.get(assemblyName);
|
|
520
663
|
if (assembly) {
|
|
@@ -526,13 +669,22 @@ function stateModelFactory(pluginManager) {
|
|
|
526
669
|
}
|
|
527
670
|
}
|
|
528
671
|
},
|
|
672
|
+
/**
|
|
673
|
+
* #action
|
|
674
|
+
*/
|
|
529
675
|
setDraggingTrackId(idx) {
|
|
530
676
|
self.draggingTrackId = idx;
|
|
531
677
|
},
|
|
678
|
+
/**
|
|
679
|
+
* #action
|
|
680
|
+
*/
|
|
532
681
|
setScaleFactor(factor) {
|
|
533
682
|
self.scaleFactor = factor;
|
|
534
683
|
},
|
|
535
|
-
|
|
684
|
+
/**
|
|
685
|
+
* #action
|
|
686
|
+
* this "clears the view" and makes the view return to the import form
|
|
687
|
+
*/
|
|
536
688
|
clearView() {
|
|
537
689
|
this.setDisplayedRegions([]);
|
|
538
690
|
self.tracks.clear();
|
|
@@ -542,6 +694,10 @@ function stateModelFactory(pluginManager) {
|
|
|
542
694
|
self.scrollTo(0);
|
|
543
695
|
self.zoomTo(10);
|
|
544
696
|
},
|
|
697
|
+
/**
|
|
698
|
+
* #action
|
|
699
|
+
* creates an svg export and save using FileSaver
|
|
700
|
+
*/
|
|
545
701
|
async exportSvg(opts = {}) {
|
|
546
702
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
547
703
|
const html = await (0, LinearGenomeViewSvg_1.renderToSvg)(self, opts);
|
|
@@ -551,6 +707,10 @@ function stateModelFactory(pluginManager) {
|
|
|
551
707
|
}))
|
|
552
708
|
.actions(self => {
|
|
553
709
|
let cancelLastAnimation = () => { };
|
|
710
|
+
/**
|
|
711
|
+
* #action
|
|
712
|
+
* perform animated slide
|
|
713
|
+
*/
|
|
554
714
|
function slide(viewWidths) {
|
|
555
715
|
const [animate, cancelAnimation] = (0, util_1.springAnimate)(self.offsetPx, self.offsetPx + self.width * viewWidths, self.scrollTo);
|
|
556
716
|
cancelLastAnimation();
|
|
@@ -561,6 +721,10 @@ function stateModelFactory(pluginManager) {
|
|
|
561
721
|
})
|
|
562
722
|
.actions(self => {
|
|
563
723
|
let cancelLastAnimation = () => { };
|
|
724
|
+
/**
|
|
725
|
+
* #action
|
|
726
|
+
* perform animated zoom
|
|
727
|
+
*/
|
|
564
728
|
function zoom(targetBpPerPx) {
|
|
565
729
|
self.zoomTo(self.bpPerPx);
|
|
566
730
|
if (
|
|
@@ -582,17 +746,30 @@ function stateModelFactory(pluginManager) {
|
|
|
582
746
|
return { zoom };
|
|
583
747
|
})
|
|
584
748
|
.views(self => ({
|
|
749
|
+
/**
|
|
750
|
+
* #getter
|
|
751
|
+
*/
|
|
585
752
|
get canShowCytobands() {
|
|
586
753
|
return self.displayedRegions.length === 1 && this.anyCytobandsExist;
|
|
587
754
|
},
|
|
755
|
+
/**
|
|
756
|
+
* #getter
|
|
757
|
+
*/
|
|
588
758
|
get showCytobands() {
|
|
589
759
|
return this.canShowCytobands && self.showCytobandsSetting;
|
|
590
760
|
},
|
|
761
|
+
/**
|
|
762
|
+
* #getter
|
|
763
|
+
*/
|
|
591
764
|
get anyCytobandsExist() {
|
|
592
765
|
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
593
|
-
|
|
594
|
-
return assemblyNames.some(asm => { var _a, _b; return (_b = (_a = assemblyManager.get(asm)) === null || _a === void 0 ? void 0 : _a.cytobands) === null || _b === void 0 ? void 0 : _b.length; });
|
|
766
|
+
return self.assemblyNames.some(a => { var _a, _b; return (_b = (_a = assemblyManager.get(a)) === null || _a === void 0 ? void 0 : _a.cytobands) === null || _b === void 0 ? void 0 : _b.length; });
|
|
595
767
|
},
|
|
768
|
+
/**
|
|
769
|
+
* #getter
|
|
770
|
+
* the cytoband is displayed to the right of the chromosome name,
|
|
771
|
+
* and that offset is calculated manually with this method
|
|
772
|
+
*/
|
|
596
773
|
get cytobandOffset() {
|
|
597
774
|
return this.showCytobands
|
|
598
775
|
? (0, util_1.measureText)(self.displayedRegions[0].refName, 12) + 15
|
|
@@ -600,6 +777,10 @@ function stateModelFactory(pluginManager) {
|
|
|
600
777
|
},
|
|
601
778
|
}))
|
|
602
779
|
.views(self => ({
|
|
780
|
+
/**
|
|
781
|
+
* #method
|
|
782
|
+
* return the view menu items
|
|
783
|
+
*/
|
|
603
784
|
menuItems() {
|
|
604
785
|
const { canShowCytobands, showCytobands } = self;
|
|
605
786
|
const session = (0, util_1.getSession)(self);
|
|
@@ -742,6 +923,15 @@ function stateModelFactory(pluginManager) {
|
|
|
742
923
|
let currentlyCalculatedStaticBlocks;
|
|
743
924
|
let stringifiedCurrentlyCalculatedStaticBlocks = '';
|
|
744
925
|
return {
|
|
926
|
+
/**
|
|
927
|
+
* #getter
|
|
928
|
+
* static blocks are an important concept jbrowse uses to avoid
|
|
929
|
+
* re-rendering when you scroll to the side. when you horizontally
|
|
930
|
+
* scroll to the right, old blocks to the left may be removed, and
|
|
931
|
+
* new blocks may be instantiated on the right. tracks may use the
|
|
932
|
+
* static blocks to render their data for the region represented by
|
|
933
|
+
* the block
|
|
934
|
+
*/
|
|
745
935
|
get staticBlocks() {
|
|
746
936
|
const ret = (0, calculateStaticBlocks_1.default)(self);
|
|
747
937
|
const sret = JSON.stringify(ret);
|
|
@@ -751,27 +941,48 @@ function stateModelFactory(pluginManager) {
|
|
|
751
941
|
}
|
|
752
942
|
return currentlyCalculatedStaticBlocks;
|
|
753
943
|
},
|
|
944
|
+
/**
|
|
945
|
+
* #getter
|
|
946
|
+
* dynamic blocks represent the exact coordinates of the currently
|
|
947
|
+
* visible genome regions on the screen. they are similar to static
|
|
948
|
+
* blocks, but statcic blocks can go offscreen while dynamic blocks
|
|
949
|
+
* represent exactly what is on screen
|
|
950
|
+
*/
|
|
754
951
|
get dynamicBlocks() {
|
|
755
952
|
return (0, calculateDynamicBlocks_1.default)(self);
|
|
756
953
|
},
|
|
954
|
+
/**
|
|
955
|
+
* #getter
|
|
956
|
+
* rounded dynamic blocks are dynamic blocks without fractions of bp
|
|
957
|
+
*/
|
|
757
958
|
get roundedDynamicBlocks() {
|
|
758
|
-
return this.dynamicBlocks.contentBlocks.map(block => {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
};
|
|
764
|
-
});
|
|
959
|
+
return this.dynamicBlocks.contentBlocks.map(block => ({
|
|
960
|
+
...block,
|
|
961
|
+
start: Math.floor(block.start),
|
|
962
|
+
end: Math.ceil(block.end),
|
|
963
|
+
}));
|
|
765
964
|
},
|
|
965
|
+
/**
|
|
966
|
+
* #getter
|
|
967
|
+
* a single "combo-locstring" representing all the regions visible
|
|
968
|
+
* on the screen
|
|
969
|
+
*/
|
|
766
970
|
get visibleLocStrings() {
|
|
767
971
|
return calculateVisibleLocStrings(this.dynamicBlocks.contentBlocks);
|
|
768
972
|
},
|
|
973
|
+
/**
|
|
974
|
+
* #getter
|
|
975
|
+
* same as visibleLocStrings, but only updated every 300ms
|
|
976
|
+
*/
|
|
769
977
|
get coarseVisibleLocStrings() {
|
|
770
978
|
return calculateVisibleLocStrings(self.coarseDynamicBlocks);
|
|
771
979
|
},
|
|
772
980
|
};
|
|
773
981
|
})
|
|
774
982
|
.actions(self => ({
|
|
983
|
+
/**
|
|
984
|
+
* #action
|
|
985
|
+
*/
|
|
775
986
|
setCoarseDynamicBlocks(blocks) {
|
|
776
987
|
self.coarseDynamicBlocks = blocks.contentBlocks;
|
|
777
988
|
self.coarseTotalBp = blocks.totalBp;
|
|
@@ -786,6 +997,7 @@ function stateModelFactory(pluginManager) {
|
|
|
786
997
|
}))
|
|
787
998
|
.actions(self => ({
|
|
788
999
|
/**
|
|
1000
|
+
* #action
|
|
789
1001
|
* offset is the base-pair-offset in the displayed region, index is the index of the
|
|
790
1002
|
* displayed region in the linear genome view
|
|
791
1003
|
*
|
|
@@ -795,7 +1007,14 @@ function stateModelFactory(pluginManager) {
|
|
|
795
1007
|
moveTo(start, end) {
|
|
796
1008
|
(0, Base1DUtils_1.moveTo)(self, start, end);
|
|
797
1009
|
},
|
|
798
|
-
|
|
1010
|
+
/**
|
|
1011
|
+
* #action
|
|
1012
|
+
* navigate to the given locstring
|
|
1013
|
+
*
|
|
1014
|
+
* @param locString - e.g. "chr1:1-100"
|
|
1015
|
+
* @param optAssemblyName - (optional) the assembly name to use when navigating to the locstring
|
|
1016
|
+
*/
|
|
1017
|
+
async navToLocString(locString, optAssemblyName) {
|
|
799
1018
|
const { assemblyNames } = self;
|
|
800
1019
|
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
801
1020
|
const { isValidRefName } = assemblyManager;
|
|
@@ -805,6 +1024,9 @@ function stateModelFactory(pluginManager) {
|
|
|
805
1024
|
.split(/(\s+)/)
|
|
806
1025
|
.map(f => f.trim())
|
|
807
1026
|
.filter(f => !!f);
|
|
1027
|
+
if (assemblyName) {
|
|
1028
|
+
await assemblyManager.waitForAssembly(assemblyName);
|
|
1029
|
+
}
|
|
808
1030
|
// first try interpreting as a whitespace-separated sequence of
|
|
809
1031
|
// multiple locstrings
|
|
810
1032
|
try {
|
|
@@ -825,9 +1047,9 @@ function stateModelFactory(pluginManager) {
|
|
|
825
1047
|
throw e;
|
|
826
1048
|
}
|
|
827
1049
|
}
|
|
828
|
-
const locations = parsedLocStrings === null || parsedLocStrings === void 0 ? void 0 : parsedLocStrings.map(region => {
|
|
1050
|
+
const locations = await Promise.all(parsedLocStrings === null || parsedLocStrings === void 0 ? void 0 : parsedLocStrings.map(async (region) => {
|
|
829
1051
|
const asmName = region.assemblyName || assemblyName;
|
|
830
|
-
const asm = assemblyManager.
|
|
1052
|
+
const asm = await assemblyManager.waitForAssembly(asmName);
|
|
831
1053
|
const { refName } = region;
|
|
832
1054
|
if (!asm) {
|
|
833
1055
|
throw new Error(`assembly ${asmName} not found`);
|
|
@@ -840,7 +1062,7 @@ function stateModelFactory(pluginManager) {
|
|
|
840
1062
|
if (!canonicalRefName) {
|
|
841
1063
|
throw new Error(`Could not find refName ${refName} in ${asm.name}`);
|
|
842
1064
|
}
|
|
843
|
-
const parentRegion = regions.find(
|
|
1065
|
+
const parentRegion = regions.find(r => r.refName === canonicalRefName);
|
|
844
1066
|
if (!parentRegion) {
|
|
845
1067
|
throw new Error(`Could not find refName ${refName} in ${asmName}`);
|
|
846
1068
|
}
|
|
@@ -849,7 +1071,7 @@ function stateModelFactory(pluginManager) {
|
|
|
849
1071
|
assemblyName: asmName,
|
|
850
1072
|
parentRegion,
|
|
851
1073
|
};
|
|
852
|
-
});
|
|
1074
|
+
}));
|
|
853
1075
|
if (locations.length === 1) {
|
|
854
1076
|
const loc = locations[0];
|
|
855
1077
|
self.setDisplayedRegions([
|
|
@@ -870,6 +1092,7 @@ function stateModelFactory(pluginManager) {
|
|
|
870
1092
|
}
|
|
871
1093
|
},
|
|
872
1094
|
/**
|
|
1095
|
+
* #action
|
|
873
1096
|
* Navigate to a location based on its refName and optionally start, end,
|
|
874
1097
|
* and assemblyName. Can handle if there are multiple displayedRegions
|
|
875
1098
|
* from same refName. Only navigates to a location if it is entirely
|
|
@@ -878,11 +1101,14 @@ function stateModelFactory(pluginManager) {
|
|
|
878
1101
|
*
|
|
879
1102
|
* Throws an error if navigation was unsuccessful
|
|
880
1103
|
*
|
|
881
|
-
* @param
|
|
1104
|
+
* @param query - a proposed location to navigate to
|
|
882
1105
|
*/
|
|
883
1106
|
navTo(query) {
|
|
884
1107
|
this.navToMultiple([query]);
|
|
885
1108
|
},
|
|
1109
|
+
/**
|
|
1110
|
+
* #action
|
|
1111
|
+
*/
|
|
886
1112
|
navToMultiple(locations) {
|
|
887
1113
|
const firstLocation = locations[0];
|
|
888
1114
|
let { refName } = firstLocation;
|
|
@@ -984,6 +1210,9 @@ function stateModelFactory(pluginManager) {
|
|
|
984
1210
|
},
|
|
985
1211
|
}))
|
|
986
1212
|
.views(self => ({
|
|
1213
|
+
/**
|
|
1214
|
+
* #method
|
|
1215
|
+
*/
|
|
987
1216
|
rubberBandMenuItems() {
|
|
988
1217
|
return [
|
|
989
1218
|
{
|
|
@@ -1001,10 +1230,14 @@ function stateModelFactory(pluginManager) {
|
|
|
1001
1230
|
},
|
|
1002
1231
|
];
|
|
1003
1232
|
},
|
|
1233
|
+
/**
|
|
1234
|
+
* #method
|
|
1235
|
+
*/
|
|
1004
1236
|
bpToPx({ refName, coord, regionNumber, }) {
|
|
1005
1237
|
return (0, Base1DUtils_1.bpToPx)({ refName, coord, regionNumber, self });
|
|
1006
1238
|
},
|
|
1007
1239
|
/**
|
|
1240
|
+
* #method
|
|
1008
1241
|
* scrolls the view to center on the given bp. if that is not in any
|
|
1009
1242
|
* of the displayed regions, does nothing
|
|
1010
1243
|
* @param coord - basepair at which you want to center the view
|
|
@@ -1021,9 +1254,15 @@ function stateModelFactory(pluginManager) {
|
|
|
1021
1254
|
self.scrollTo(Math.round(centerPx.offsetPx - self.width / 2));
|
|
1022
1255
|
}
|
|
1023
1256
|
},
|
|
1257
|
+
/**
|
|
1258
|
+
* #method
|
|
1259
|
+
*/
|
|
1024
1260
|
pxToBp(px) {
|
|
1025
1261
|
return (0, Base1DUtils_1.pxToBp)(self, px);
|
|
1026
1262
|
},
|
|
1263
|
+
/**
|
|
1264
|
+
* #getter
|
|
1265
|
+
*/
|
|
1027
1266
|
get centerLineInfo() {
|
|
1028
1267
|
return self.displayedRegions.length
|
|
1029
1268
|
? this.pxToBp(self.width / 2)
|