@jbrowse/plugin-linear-genome-view 2.1.7 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/components/Tooltip.d.ts +1 -1
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +149 -4
- 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/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -2
- 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 +79 -8
- package/dist/LinearBasicDisplay/model.js +167 -111
- package/dist/LinearBasicDisplay/model.js.map +1 -1
- package/dist/LinearGenomeView/components/CenterLine.d.ts +1 -1
- package/dist/LinearGenomeView/components/GetSequenceDialog.d.ts +1 -1
- package/dist/LinearGenomeView/components/Gridlines.d.ts +1 -1
- package/dist/LinearGenomeView/components/Header.d.ts +1 -1
- package/dist/LinearGenomeView/components/ImportForm.d.ts +1 -1
- package/dist/LinearGenomeView/components/ImportForm.js +38 -31
- package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeView.d.ts +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeView.js +2 -24
- package/dist/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeViewSvg.d.ts +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js +7 -5
- package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js.map +1 -1
- package/dist/LinearGenomeView/components/OverviewRubberBand.d.ts +1 -1
- package/dist/LinearGenomeView/components/OverviewScaleBar.d.ts +27 -35
- package/dist/LinearGenomeView/components/RubberBand.d.ts +1 -1
- package/dist/LinearGenomeView/components/ScaleBar.d.ts +1 -1
- package/dist/LinearGenomeView/components/TrackContainer.d.ts +1 -1
- package/dist/LinearGenomeView/components/TrackContainer.js +12 -9
- package/dist/LinearGenomeView/components/TrackContainer.js.map +1 -1
- package/dist/LinearGenomeView/components/TrackLabel.js +9 -1
- package/dist/LinearGenomeView/components/TrackLabel.js.map +1 -1
- package/dist/LinearGenomeView/components/TracksContainer.d.ts +1 -1
- package/dist/LinearGenomeView/index.d.ts +273 -18
- package/dist/LinearGenomeView/index.js +409 -90
- package/dist/LinearGenomeView/index.js.map +1 -1
- package/dist/index.d.ts +30 -90
- 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/components/Tooltip.d.ts +1 -1
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +149 -4
- 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/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -2
- 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 +79 -8
- package/esm/LinearBasicDisplay/model.js +167 -111
- package/esm/LinearBasicDisplay/model.js.map +1 -1
- package/esm/LinearGenomeView/components/CenterLine.d.ts +1 -1
- package/esm/LinearGenomeView/components/GetSequenceDialog.d.ts +1 -1
- package/esm/LinearGenomeView/components/Gridlines.d.ts +1 -1
- package/esm/LinearGenomeView/components/Header.d.ts +1 -1
- package/esm/LinearGenomeView/components/ImportForm.d.ts +1 -1
- package/esm/LinearGenomeView/components/ImportForm.js +40 -33
- package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.d.ts +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.js +3 -25
- package/esm/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeViewSvg.d.ts +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeViewSvg.js +7 -5
- package/esm/LinearGenomeView/components/LinearGenomeViewSvg.js.map +1 -1
- package/esm/LinearGenomeView/components/OverviewRubberBand.d.ts +1 -1
- package/esm/LinearGenomeView/components/OverviewScaleBar.d.ts +27 -35
- package/esm/LinearGenomeView/components/RubberBand.d.ts +1 -1
- package/esm/LinearGenomeView/components/ScaleBar.d.ts +1 -1
- package/esm/LinearGenomeView/components/TrackContainer.d.ts +1 -1
- package/esm/LinearGenomeView/components/TrackContainer.js +13 -10
- package/esm/LinearGenomeView/components/TrackContainer.js.map +1 -1
- package/esm/LinearGenomeView/components/TrackLabel.js +9 -1
- package/esm/LinearGenomeView/components/TrackLabel.js.map +1 -1
- package/esm/LinearGenomeView/components/TracksContainer.d.ts +1 -1
- package/esm/LinearGenomeView/index.d.ts +273 -18
- package/esm/LinearGenomeView/index.js +409 -90
- package/esm/LinearGenomeView/index.js.map +1 -1
- package/esm/index.d.ts +30 -90
- 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 +18 -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 +85 -67
- package/src/LinearGenomeView/components/LinearGenomeView.tsx +3 -33
- package/src/LinearGenomeView/components/LinearGenomeViewSvg.tsx +21 -18
- package/src/LinearGenomeView/components/TrackContainer.tsx +38 -27
- package/src/LinearGenomeView/components/TrackLabel.tsx +10 -1
- package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.tsx.snap +204 -204
- package/src/LinearGenomeView/index.test.ts +33 -26
- package/src/LinearGenomeView/index.tsx +471 -133
- package/src/index.ts +6 -46
|
@@ -65,12 +65,13 @@ const ZoomControls_1 = __importDefault(require("./components/ZoomControls"));
|
|
|
65
65
|
exports.ZoomControls = ZoomControls_1.default;
|
|
66
66
|
const LinearGenomeView_1 = __importDefault(require("./components/LinearGenomeView"));
|
|
67
67
|
exports.LinearGenomeView = LinearGenomeView_1.default;
|
|
68
|
+
// lazies
|
|
68
69
|
const SequenceSearchDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/SequenceSearchDialog'))));
|
|
69
70
|
function calculateVisibleLocStrings(contentBlocks) {
|
|
70
71
|
if (!contentBlocks.length) {
|
|
71
72
|
return '';
|
|
72
73
|
}
|
|
73
|
-
const isSingleAssemblyName = contentBlocks.every(
|
|
74
|
+
const isSingleAssemblyName = contentBlocks.every(b => b.assemblyName === contentBlocks[0].assemblyName);
|
|
74
75
|
const locs = contentBlocks.map(block => (0, util_1.assembleLocString)({
|
|
75
76
|
...block,
|
|
76
77
|
start: Math.round(block.start),
|
|
@@ -91,30 +92,87 @@ function localStorageGetItem(item) {
|
|
|
91
92
|
? localStorage.getItem(item)
|
|
92
93
|
: undefined;
|
|
93
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* #stateModel LinearGenomeView
|
|
97
|
+
*/
|
|
94
98
|
function stateModelFactory(pluginManager) {
|
|
95
99
|
return mobx_state_tree_1.types
|
|
96
100
|
.compose(models_1.BaseViewModel, mobx_state_tree_1.types.model('LinearGenomeView', {
|
|
101
|
+
/**
|
|
102
|
+
* #property
|
|
103
|
+
*/
|
|
97
104
|
id: mst_1.ElementId,
|
|
105
|
+
/**
|
|
106
|
+
* #property
|
|
107
|
+
* this is a string instead of the const literal 'LinearGenomeView' to reduce some
|
|
108
|
+
* typescripting strictness, but you should pass the string 'LinearGenomeView' to
|
|
109
|
+
* the model explicitly
|
|
110
|
+
*/
|
|
98
111
|
type: mobx_state_tree_1.types.literal('LinearGenomeView'),
|
|
112
|
+
/**
|
|
113
|
+
* #property
|
|
114
|
+
* corresponds roughly to the horizontal scroll of the LGV
|
|
115
|
+
*/
|
|
99
116
|
offsetPx: 0,
|
|
117
|
+
/**
|
|
118
|
+
* #property
|
|
119
|
+
* corresponds roughly to the zoom level, base-pairs per pixel
|
|
120
|
+
*/
|
|
100
121
|
bpPerPx: 1,
|
|
122
|
+
/**
|
|
123
|
+
* #property
|
|
124
|
+
* currently displayed regions, can be a single chromosome, arbitrary subsections,
|
|
125
|
+
* or the entire set of chromosomes in the genome, but it not advised to use the
|
|
126
|
+
* entire set of chromosomes if your assembly is very fragmented
|
|
127
|
+
*/
|
|
101
128
|
displayedRegions: mobx_state_tree_1.types.array(mst_1.Region),
|
|
102
|
-
|
|
103
|
-
|
|
129
|
+
/**
|
|
130
|
+
* #property
|
|
131
|
+
* array of currently displayed tracks state models instances
|
|
132
|
+
*/
|
|
104
133
|
tracks: mobx_state_tree_1.types.array(pluginManager.pluggableMstType('track', 'stateModel')),
|
|
134
|
+
/**
|
|
135
|
+
* #property
|
|
136
|
+
* array of currently displayed tracks state model's
|
|
137
|
+
*/
|
|
105
138
|
hideHeader: false,
|
|
139
|
+
/**
|
|
140
|
+
* #property
|
|
141
|
+
*/
|
|
106
142
|
hideHeaderOverview: false,
|
|
143
|
+
/**
|
|
144
|
+
* #property
|
|
145
|
+
*/
|
|
107
146
|
hideNoTracksActive: false,
|
|
147
|
+
/**
|
|
148
|
+
* #property
|
|
149
|
+
*/
|
|
108
150
|
trackSelectorType: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.enumeration(['hierarchical']), 'hierarchical'),
|
|
151
|
+
/**
|
|
152
|
+
* #property
|
|
153
|
+
* how to display the track labels, can be "overlapping", "offset", or "hidden"
|
|
154
|
+
*/
|
|
109
155
|
trackLabels: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.string, () => localStorageGetItem('lgv-trackLabels') || 'overlapping'),
|
|
156
|
+
/**
|
|
157
|
+
* #property
|
|
158
|
+
* show the "center line"
|
|
159
|
+
*/
|
|
110
160
|
showCenterLine: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.boolean, () => {
|
|
111
161
|
const setting = localStorageGetItem('lgv-showCenterLine');
|
|
112
162
|
return setting !== undefined && setting !== null ? !!+setting : false;
|
|
113
163
|
}),
|
|
164
|
+
/**
|
|
165
|
+
* #property
|
|
166
|
+
* show the "cytobands" in the overview scale bar
|
|
167
|
+
*/
|
|
114
168
|
showCytobandsSetting: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.boolean, () => {
|
|
115
169
|
const setting = localStorageGetItem('lgv-showCytobands');
|
|
116
170
|
return setting !== undefined && setting !== null ? !!+setting : true;
|
|
117
171
|
}),
|
|
172
|
+
/**
|
|
173
|
+
* #property
|
|
174
|
+
* show the "gridlines" in the track area
|
|
175
|
+
*/
|
|
118
176
|
showGridlines: true,
|
|
119
177
|
}))
|
|
120
178
|
.volatile(() => ({
|
|
@@ -137,15 +195,24 @@ function stateModelFactory(pluginManager) {
|
|
|
137
195
|
seqDialogDisplayed: false,
|
|
138
196
|
}))
|
|
139
197
|
.views(self => ({
|
|
198
|
+
/**
|
|
199
|
+
* #getter
|
|
200
|
+
*/
|
|
140
201
|
get width() {
|
|
141
202
|
if (self.volatileWidth === undefined) {
|
|
142
203
|
throw new Error('width undefined, make sure to check for model.initialized');
|
|
143
204
|
}
|
|
144
205
|
return self.volatileWidth;
|
|
145
206
|
},
|
|
207
|
+
/**
|
|
208
|
+
* #getter
|
|
209
|
+
*/
|
|
146
210
|
get interRegionPaddingWidth() {
|
|
147
211
|
return exports.INTER_REGION_PADDING_WIDTH;
|
|
148
212
|
},
|
|
213
|
+
/**
|
|
214
|
+
* #getter
|
|
215
|
+
*/
|
|
149
216
|
get assemblyNames() {
|
|
150
217
|
return [
|
|
151
218
|
...new Set(self.displayedRegions.map(region => region.assemblyName)),
|
|
@@ -153,14 +220,23 @@ function stateModelFactory(pluginManager) {
|
|
|
153
220
|
},
|
|
154
221
|
}))
|
|
155
222
|
.views(self => ({
|
|
223
|
+
/**
|
|
224
|
+
* #method
|
|
225
|
+
*/
|
|
156
226
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
157
227
|
MiniControlsComponent() {
|
|
158
228
|
return MiniControls_1.default;
|
|
159
229
|
},
|
|
230
|
+
/**
|
|
231
|
+
* #method
|
|
232
|
+
*/
|
|
160
233
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
161
234
|
HeaderComponent() {
|
|
162
235
|
return Header_1.default;
|
|
163
236
|
},
|
|
237
|
+
/**
|
|
238
|
+
* #getter
|
|
239
|
+
*/
|
|
164
240
|
get assemblyErrors() {
|
|
165
241
|
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
166
242
|
const { assemblyNames } = self;
|
|
@@ -169,23 +245,41 @@ function stateModelFactory(pluginManager) {
|
|
|
169
245
|
.filter(f => !!f)
|
|
170
246
|
.join(', ');
|
|
171
247
|
},
|
|
248
|
+
/**
|
|
249
|
+
* #getter
|
|
250
|
+
*/
|
|
172
251
|
get assembliesInitialized() {
|
|
173
252
|
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
174
253
|
const { assemblyNames } = self;
|
|
175
254
|
return assemblyNames.every(a => { var _a; return (_a = assemblyManager.get(a)) === null || _a === void 0 ? void 0 : _a.initialized; });
|
|
176
255
|
},
|
|
256
|
+
/**
|
|
257
|
+
* #getter
|
|
258
|
+
*/
|
|
177
259
|
get initialized() {
|
|
178
260
|
return self.volatileWidth !== undefined && this.assembliesInitialized;
|
|
179
261
|
},
|
|
262
|
+
/**
|
|
263
|
+
* #getter
|
|
264
|
+
*/
|
|
180
265
|
get hasDisplayedRegions() {
|
|
181
266
|
return self.displayedRegions.length > 0;
|
|
182
267
|
},
|
|
268
|
+
/**
|
|
269
|
+
* #getter
|
|
270
|
+
*/
|
|
183
271
|
get isSearchDialogDisplayed() {
|
|
184
272
|
return self.searchResults !== undefined;
|
|
185
273
|
},
|
|
274
|
+
/**
|
|
275
|
+
* #getter
|
|
276
|
+
*/
|
|
186
277
|
get scaleBarHeight() {
|
|
187
278
|
return exports.SCALE_BAR_HEIGHT + exports.RESIZE_HANDLE_HEIGHT;
|
|
188
279
|
},
|
|
280
|
+
/**
|
|
281
|
+
* #getter
|
|
282
|
+
*/
|
|
189
283
|
get headerHeight() {
|
|
190
284
|
if (self.hideHeader) {
|
|
191
285
|
return 0;
|
|
@@ -195,44 +289,77 @@ function stateModelFactory(pluginManager) {
|
|
|
195
289
|
}
|
|
196
290
|
return exports.HEADER_BAR_HEIGHT + exports.HEADER_OVERVIEW_HEIGHT;
|
|
197
291
|
},
|
|
292
|
+
/**
|
|
293
|
+
* #getter
|
|
294
|
+
*/
|
|
198
295
|
get trackHeights() {
|
|
199
296
|
return self.tracks
|
|
200
297
|
.map(t => t.displays[0].height)
|
|
201
298
|
.reduce((a, b) => a + b, 0);
|
|
202
299
|
},
|
|
300
|
+
/**
|
|
301
|
+
* #getter
|
|
302
|
+
*/
|
|
203
303
|
get trackHeightsWithResizeHandles() {
|
|
204
304
|
return this.trackHeights + self.tracks.length * exports.RESIZE_HANDLE_HEIGHT;
|
|
205
305
|
},
|
|
306
|
+
/**
|
|
307
|
+
* #getter
|
|
308
|
+
*/
|
|
206
309
|
get height() {
|
|
207
310
|
return (this.trackHeightsWithResizeHandles +
|
|
208
311
|
this.headerHeight +
|
|
209
312
|
this.scaleBarHeight);
|
|
210
313
|
},
|
|
314
|
+
/**
|
|
315
|
+
* #getter
|
|
316
|
+
*/
|
|
211
317
|
get totalBp() {
|
|
212
318
|
return self.displayedRegions.reduce((a, b) => a + b.end - b.start, 0);
|
|
213
319
|
},
|
|
320
|
+
/**
|
|
321
|
+
* #getter
|
|
322
|
+
*/
|
|
214
323
|
get maxBpPerPx() {
|
|
215
324
|
return this.totalBp / (self.width * 0.9);
|
|
216
325
|
},
|
|
326
|
+
/**
|
|
327
|
+
* #getter
|
|
328
|
+
*/
|
|
217
329
|
get minBpPerPx() {
|
|
218
330
|
return 1 / 50;
|
|
219
331
|
},
|
|
332
|
+
/**
|
|
333
|
+
* #getter
|
|
334
|
+
*/
|
|
220
335
|
get error() {
|
|
221
336
|
return self.volatileError || this.assemblyErrors;
|
|
222
337
|
},
|
|
338
|
+
/**
|
|
339
|
+
* #getter
|
|
340
|
+
*/
|
|
223
341
|
get maxOffset() {
|
|
224
342
|
// objectively determined to keep the linear genome on the main screen
|
|
225
343
|
const leftPadding = 10;
|
|
226
344
|
return this.displayedRegionsTotalPx - leftPadding;
|
|
227
345
|
},
|
|
346
|
+
/**
|
|
347
|
+
* #getter
|
|
348
|
+
*/
|
|
228
349
|
get minOffset() {
|
|
229
350
|
// objectively determined to keep the linear genome on the main screen
|
|
230
351
|
const rightPadding = 30;
|
|
231
352
|
return -self.width + rightPadding;
|
|
232
353
|
},
|
|
354
|
+
/**
|
|
355
|
+
* #getter
|
|
356
|
+
*/
|
|
233
357
|
get displayedRegionsTotalPx() {
|
|
234
358
|
return this.totalBp / self.bpPerPx;
|
|
235
359
|
},
|
|
360
|
+
/**
|
|
361
|
+
* #method
|
|
362
|
+
*/
|
|
236
363
|
renderProps() {
|
|
237
364
|
return {
|
|
238
365
|
...(0, tracks_1.getParentRenderProps)(self),
|
|
@@ -240,6 +367,9 @@ function stateModelFactory(pluginManager) {
|
|
|
240
367
|
highResolutionScaling: (0, configuration_1.getConf)((0, util_1.getSession)(self), 'highResolutionScaling'),
|
|
241
368
|
};
|
|
242
369
|
},
|
|
370
|
+
/**
|
|
371
|
+
* #method
|
|
372
|
+
*/
|
|
243
373
|
searchScope(assemblyName) {
|
|
244
374
|
return {
|
|
245
375
|
assemblyName,
|
|
@@ -247,9 +377,15 @@ function stateModelFactory(pluginManager) {
|
|
|
247
377
|
tracks: self.tracks,
|
|
248
378
|
};
|
|
249
379
|
},
|
|
380
|
+
/**
|
|
381
|
+
* #method
|
|
382
|
+
*/
|
|
250
383
|
getTrack(id) {
|
|
251
384
|
return self.tracks.find(t => t.configuration.trackId === id);
|
|
252
385
|
},
|
|
386
|
+
/**
|
|
387
|
+
* #method
|
|
388
|
+
*/
|
|
253
389
|
rankSearchResults(results) {
|
|
254
390
|
// order of rank
|
|
255
391
|
const openTrackIds = self.tracks.map(track => track.configuration.trackId);
|
|
@@ -260,7 +396,10 @@ function stateModelFactory(pluginManager) {
|
|
|
260
396
|
});
|
|
261
397
|
return results;
|
|
262
398
|
},
|
|
263
|
-
|
|
399
|
+
/**
|
|
400
|
+
* #method
|
|
401
|
+
* modifies view menu action onClick to apply to all tracks of same type
|
|
402
|
+
*/
|
|
264
403
|
rewriteOnClicks(trackType, viewMenuActions) {
|
|
265
404
|
viewMenuActions.forEach(action => {
|
|
266
405
|
// go to lowest level menu
|
|
@@ -279,6 +418,9 @@ function stateModelFactory(pluginManager) {
|
|
|
279
418
|
}
|
|
280
419
|
});
|
|
281
420
|
},
|
|
421
|
+
/**
|
|
422
|
+
* #getter
|
|
423
|
+
*/
|
|
282
424
|
get trackTypeActions() {
|
|
283
425
|
const allActions = new Map();
|
|
284
426
|
self.tracks.forEach(track => {
|
|
@@ -293,33 +435,60 @@ function stateModelFactory(pluginManager) {
|
|
|
293
435
|
},
|
|
294
436
|
}))
|
|
295
437
|
.actions(self => ({
|
|
438
|
+
/**
|
|
439
|
+
* #action
|
|
440
|
+
*/
|
|
296
441
|
setShowCytobands(flag) {
|
|
297
442
|
self.showCytobandsSetting = flag;
|
|
298
443
|
localStorage.setItem('lgv-showCytobands', `${+flag}`);
|
|
299
444
|
},
|
|
445
|
+
/**
|
|
446
|
+
* #action
|
|
447
|
+
*/
|
|
300
448
|
setWidth(newWidth) {
|
|
301
449
|
self.volatileWidth = newWidth;
|
|
302
450
|
},
|
|
451
|
+
/**
|
|
452
|
+
* #action
|
|
453
|
+
*/
|
|
303
454
|
setError(error) {
|
|
304
455
|
self.volatileError = error;
|
|
305
456
|
},
|
|
457
|
+
/**
|
|
458
|
+
* #action
|
|
459
|
+
*/
|
|
306
460
|
toggleHeader() {
|
|
307
461
|
self.hideHeader = !self.hideHeader;
|
|
308
462
|
},
|
|
463
|
+
/**
|
|
464
|
+
* #action
|
|
465
|
+
*/
|
|
309
466
|
toggleHeaderOverview() {
|
|
310
467
|
self.hideHeaderOverview = !self.hideHeaderOverview;
|
|
311
468
|
},
|
|
469
|
+
/**
|
|
470
|
+
* #action
|
|
471
|
+
*/
|
|
312
472
|
toggleNoTracksActive() {
|
|
313
473
|
self.hideNoTracksActive = !self.hideNoTracksActive;
|
|
314
474
|
},
|
|
475
|
+
/**
|
|
476
|
+
* #action
|
|
477
|
+
*/
|
|
315
478
|
toggleShowGridlines() {
|
|
316
479
|
self.showGridlines = !self.showGridlines;
|
|
317
480
|
},
|
|
481
|
+
/**
|
|
482
|
+
* #action
|
|
483
|
+
*/
|
|
318
484
|
scrollTo(offsetPx) {
|
|
319
485
|
const newOffsetPx = (0, util_1.clamp)(offsetPx, self.minOffset, self.maxOffset);
|
|
320
486
|
self.offsetPx = newOffsetPx;
|
|
321
487
|
return newOffsetPx;
|
|
322
488
|
},
|
|
489
|
+
/**
|
|
490
|
+
* #action
|
|
491
|
+
*/
|
|
323
492
|
zoomTo(bpPerPx) {
|
|
324
493
|
const newBpPerPx = (0, util_1.clamp)(bpPerPx, self.minBpPerPx, self.maxBpPerPx);
|
|
325
494
|
if (newBpPerPx === self.bpPerPx) {
|
|
@@ -337,22 +506,37 @@ function stateModelFactory(pluginManager) {
|
|
|
337
506
|
viewWidth / 2));
|
|
338
507
|
return newBpPerPx;
|
|
339
508
|
},
|
|
509
|
+
/**
|
|
510
|
+
* #action
|
|
511
|
+
* sets offsets used in the get sequence dialog
|
|
512
|
+
*/
|
|
340
513
|
setOffsets(left, right) {
|
|
341
|
-
// sets offsets used in the get sequence dialog
|
|
342
514
|
self.leftOffset = left;
|
|
343
515
|
self.rightOffset = right;
|
|
344
516
|
},
|
|
517
|
+
/**
|
|
518
|
+
* #action
|
|
519
|
+
*/
|
|
345
520
|
setSearchResults(results, query) {
|
|
346
521
|
self.searchResults = results;
|
|
347
522
|
self.searchQuery = query;
|
|
348
523
|
},
|
|
524
|
+
/**
|
|
525
|
+
* #action
|
|
526
|
+
*/
|
|
349
527
|
setGetSequenceDialogOpen(open) {
|
|
350
528
|
self.seqDialogDisplayed = open;
|
|
351
529
|
},
|
|
530
|
+
/**
|
|
531
|
+
* #action
|
|
532
|
+
*/
|
|
352
533
|
setNewView(bpPerPx, offsetPx) {
|
|
353
534
|
this.zoomTo(bpPerPx);
|
|
354
535
|
this.scrollTo(offsetPx);
|
|
355
536
|
},
|
|
537
|
+
/**
|
|
538
|
+
* #action
|
|
539
|
+
*/
|
|
356
540
|
horizontallyFlip() {
|
|
357
541
|
self.displayedRegions = (0, mobx_state_tree_1.cast)(self.displayedRegions
|
|
358
542
|
.slice()
|
|
@@ -360,6 +544,9 @@ function stateModelFactory(pluginManager) {
|
|
|
360
544
|
.map(region => ({ ...region, reversed: !region.reversed })));
|
|
361
545
|
this.scrollTo(self.totalBp / self.bpPerPx - self.offsetPx - self.width);
|
|
362
546
|
},
|
|
547
|
+
/**
|
|
548
|
+
* #action
|
|
549
|
+
*/
|
|
363
550
|
showTrack(trackId, initialSnapshot = {}, displayInitialSnapshot = {}) {
|
|
364
551
|
const schema = pluginManager.pluggableConfigSchemaType('track');
|
|
365
552
|
const conf = (0, mobx_state_tree_1.resolveIdentifier)(schema, (0, mobx_state_tree_1.getRoot)(self), trackId);
|
|
@@ -395,6 +582,9 @@ function stateModelFactory(pluginManager) {
|
|
|
395
582
|
}
|
|
396
583
|
return t[0];
|
|
397
584
|
},
|
|
585
|
+
/**
|
|
586
|
+
* #action
|
|
587
|
+
*/
|
|
398
588
|
hideTrack(trackId) {
|
|
399
589
|
const schema = pluginManager.pluggableConfigSchemaType('track');
|
|
400
590
|
const conf = (0, mobx_state_tree_1.resolveIdentifier)(schema, (0, mobx_state_tree_1.getRoot)(self), trackId);
|
|
@@ -404,6 +594,9 @@ function stateModelFactory(pluginManager) {
|
|
|
404
594
|
},
|
|
405
595
|
}))
|
|
406
596
|
.actions(self => ({
|
|
597
|
+
/**
|
|
598
|
+
* #action
|
|
599
|
+
*/
|
|
407
600
|
moveTrack(movingId, targetId) {
|
|
408
601
|
const oldIndex = self.tracks.findIndex(track => track.id === movingId);
|
|
409
602
|
if (oldIndex === -1) {
|
|
@@ -417,6 +610,9 @@ function stateModelFactory(pluginManager) {
|
|
|
417
610
|
self.tracks.splice(oldIndex, 1);
|
|
418
611
|
self.tracks.splice(newIndex, 0, track);
|
|
419
612
|
},
|
|
613
|
+
/**
|
|
614
|
+
* #action
|
|
615
|
+
*/
|
|
420
616
|
closeView() {
|
|
421
617
|
const parent = (0, util_1.getContainingView)(self);
|
|
422
618
|
if (parent) {
|
|
@@ -430,6 +626,9 @@ function stateModelFactory(pluginManager) {
|
|
|
430
626
|
(0, util_1.getSession)(self).removeView(self);
|
|
431
627
|
}
|
|
432
628
|
},
|
|
629
|
+
/**
|
|
630
|
+
* #action
|
|
631
|
+
*/
|
|
433
632
|
toggleTrack(trackId) {
|
|
434
633
|
// if we have any tracks with that configuration, turn them off
|
|
435
634
|
const hiddenCount = self.hideTrack(trackId);
|
|
@@ -438,18 +637,30 @@ function stateModelFactory(pluginManager) {
|
|
|
438
637
|
self.showTrack(trackId);
|
|
439
638
|
}
|
|
440
639
|
},
|
|
640
|
+
/**
|
|
641
|
+
* #action
|
|
642
|
+
*/
|
|
441
643
|
setTrackLabels(setting) {
|
|
442
644
|
self.trackLabels = setting;
|
|
443
645
|
localStorage.setItem('lgv-trackLabels', setting);
|
|
444
646
|
},
|
|
647
|
+
/**
|
|
648
|
+
* #action
|
|
649
|
+
*/
|
|
445
650
|
toggleCenterLine() {
|
|
446
651
|
self.showCenterLine = !self.showCenterLine;
|
|
447
652
|
localStorage.setItem('lgv-showCenterLine', `${+self.showCenterLine}`);
|
|
448
653
|
},
|
|
654
|
+
/**
|
|
655
|
+
* #action
|
|
656
|
+
*/
|
|
449
657
|
setDisplayedRegions(regions) {
|
|
450
658
|
self.displayedRegions = (0, mobx_state_tree_1.cast)(regions);
|
|
451
659
|
self.zoomTo(self.bpPerPx);
|
|
452
660
|
},
|
|
661
|
+
/**
|
|
662
|
+
* #action
|
|
663
|
+
*/
|
|
453
664
|
activateTrackSelector() {
|
|
454
665
|
if (self.trackSelectorType === 'hierarchical') {
|
|
455
666
|
const session = (0, util_1.getSession)(self);
|
|
@@ -462,6 +673,7 @@ function stateModelFactory(pluginManager) {
|
|
|
462
673
|
throw new Error(`invalid track selector type ${self.trackSelectorType}`);
|
|
463
674
|
},
|
|
464
675
|
/**
|
|
676
|
+
* #method
|
|
465
677
|
* Helper method for the fetchSequence.
|
|
466
678
|
* Retrieves the corresponding regions that were selected by the rubberband
|
|
467
679
|
*
|
|
@@ -483,38 +695,51 @@ function stateModelFactory(pluginManager) {
|
|
|
483
695
|
end: Math.ceil(region.end),
|
|
484
696
|
}));
|
|
485
697
|
},
|
|
486
|
-
|
|
698
|
+
/**
|
|
699
|
+
* #action
|
|
700
|
+
* schedule something to be run after the next time displayedRegions is set
|
|
701
|
+
*/
|
|
487
702
|
afterDisplayedRegionsSet(cb) {
|
|
488
703
|
self.afterDisplayedRegionsSetCallbacks.push(cb);
|
|
489
704
|
},
|
|
705
|
+
/**
|
|
706
|
+
* #action
|
|
707
|
+
*/
|
|
490
708
|
horizontalScroll(distance) {
|
|
491
709
|
const oldOffsetPx = self.offsetPx;
|
|
492
710
|
// newOffsetPx is the actual offset after the scroll is clamped
|
|
493
711
|
const newOffsetPx = self.scrollTo(self.offsetPx + distance);
|
|
494
712
|
return newOffsetPx - oldOffsetPx;
|
|
495
713
|
},
|
|
714
|
+
/**
|
|
715
|
+
* #action
|
|
716
|
+
*/
|
|
496
717
|
center() {
|
|
497
718
|
const centerBp = self.totalBp / 2;
|
|
498
719
|
const centerPx = centerBp / self.bpPerPx;
|
|
499
720
|
self.scrollTo(Math.round(centerPx - self.width / 2));
|
|
500
721
|
},
|
|
722
|
+
/**
|
|
723
|
+
* #action
|
|
724
|
+
*/
|
|
501
725
|
showAllRegions() {
|
|
502
726
|
self.zoomTo(self.maxBpPerPx);
|
|
503
727
|
this.center();
|
|
504
728
|
},
|
|
729
|
+
/**
|
|
730
|
+
* #action
|
|
731
|
+
*/
|
|
505
732
|
showAllRegionsInAssembly(assemblyName) {
|
|
506
733
|
const session = (0, util_1.getSession)(self);
|
|
507
734
|
const { assemblyManager } = session;
|
|
508
735
|
if (!assemblyName) {
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
if (assemblyNames.length > 1) {
|
|
513
|
-
session.notify(`Can't perform this with multiple assemblies currently`);
|
|
736
|
+
const names = new Set(self.displayedRegions.map(r => r.assemblyName));
|
|
737
|
+
if (names.size > 1) {
|
|
738
|
+
session.notify(`Can't perform operation with multiple assemblies currently`);
|
|
514
739
|
return;
|
|
515
740
|
}
|
|
516
741
|
;
|
|
517
|
-
[assemblyName] =
|
|
742
|
+
[assemblyName] = [...names];
|
|
518
743
|
}
|
|
519
744
|
const assembly = assemblyManager.get(assemblyName);
|
|
520
745
|
if (assembly) {
|
|
@@ -526,15 +751,24 @@ function stateModelFactory(pluginManager) {
|
|
|
526
751
|
}
|
|
527
752
|
}
|
|
528
753
|
},
|
|
754
|
+
/**
|
|
755
|
+
* #action
|
|
756
|
+
*/
|
|
529
757
|
setDraggingTrackId(idx) {
|
|
530
758
|
self.draggingTrackId = idx;
|
|
531
759
|
},
|
|
760
|
+
/**
|
|
761
|
+
* #action
|
|
762
|
+
*/
|
|
532
763
|
setScaleFactor(factor) {
|
|
533
764
|
self.scaleFactor = factor;
|
|
534
765
|
},
|
|
535
|
-
|
|
766
|
+
/**
|
|
767
|
+
* #action
|
|
768
|
+
* this "clears the view" and makes the view return to the import form
|
|
769
|
+
*/
|
|
536
770
|
clearView() {
|
|
537
|
-
|
|
771
|
+
self.displayedRegions.clear();
|
|
538
772
|
self.tracks.clear();
|
|
539
773
|
// it is necessary to run these after setting displayed regions empty
|
|
540
774
|
// or else model.offsetPx gets set to Infinity and breaks
|
|
@@ -542,6 +776,10 @@ function stateModelFactory(pluginManager) {
|
|
|
542
776
|
self.scrollTo(0);
|
|
543
777
|
self.zoomTo(10);
|
|
544
778
|
},
|
|
779
|
+
/**
|
|
780
|
+
* #action
|
|
781
|
+
* creates an svg export and save using FileSaver
|
|
782
|
+
*/
|
|
545
783
|
async exportSvg(opts = {}) {
|
|
546
784
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
547
785
|
const html = await (0, LinearGenomeViewSvg_1.renderToSvg)(self, opts);
|
|
@@ -551,6 +789,10 @@ function stateModelFactory(pluginManager) {
|
|
|
551
789
|
}))
|
|
552
790
|
.actions(self => {
|
|
553
791
|
let cancelLastAnimation = () => { };
|
|
792
|
+
/**
|
|
793
|
+
* #action
|
|
794
|
+
* perform animated slide
|
|
795
|
+
*/
|
|
554
796
|
function slide(viewWidths) {
|
|
555
797
|
const [animate, cancelAnimation] = (0, util_1.springAnimate)(self.offsetPx, self.offsetPx + self.width * viewWidths, self.scrollTo);
|
|
556
798
|
cancelLastAnimation();
|
|
@@ -561,6 +803,10 @@ function stateModelFactory(pluginManager) {
|
|
|
561
803
|
})
|
|
562
804
|
.actions(self => {
|
|
563
805
|
let cancelLastAnimation = () => { };
|
|
806
|
+
/**
|
|
807
|
+
* #action
|
|
808
|
+
* perform animated zoom
|
|
809
|
+
*/
|
|
564
810
|
function zoom(targetBpPerPx) {
|
|
565
811
|
self.zoomTo(self.bpPerPx);
|
|
566
812
|
if (
|
|
@@ -582,17 +828,30 @@ function stateModelFactory(pluginManager) {
|
|
|
582
828
|
return { zoom };
|
|
583
829
|
})
|
|
584
830
|
.views(self => ({
|
|
831
|
+
/**
|
|
832
|
+
* #getter
|
|
833
|
+
*/
|
|
585
834
|
get canShowCytobands() {
|
|
586
835
|
return self.displayedRegions.length === 1 && this.anyCytobandsExist;
|
|
587
836
|
},
|
|
837
|
+
/**
|
|
838
|
+
* #getter
|
|
839
|
+
*/
|
|
588
840
|
get showCytobands() {
|
|
589
841
|
return this.canShowCytobands && self.showCytobandsSetting;
|
|
590
842
|
},
|
|
843
|
+
/**
|
|
844
|
+
* #getter
|
|
845
|
+
*/
|
|
591
846
|
get anyCytobandsExist() {
|
|
592
847
|
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; });
|
|
848
|
+
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
849
|
},
|
|
850
|
+
/**
|
|
851
|
+
* #getter
|
|
852
|
+
* the cytoband is displayed to the right of the chromosome name,
|
|
853
|
+
* and that offset is calculated manually with this method
|
|
854
|
+
*/
|
|
596
855
|
get cytobandOffset() {
|
|
597
856
|
return this.showCytobands
|
|
598
857
|
? (0, util_1.measureText)(self.displayedRegions[0].refName, 12) + 15
|
|
@@ -600,6 +859,10 @@ function stateModelFactory(pluginManager) {
|
|
|
600
859
|
},
|
|
601
860
|
}))
|
|
602
861
|
.views(self => ({
|
|
862
|
+
/**
|
|
863
|
+
* #method
|
|
864
|
+
* return the view menu items
|
|
865
|
+
*/
|
|
603
866
|
menuItems() {
|
|
604
867
|
const { canShowCytobands, showCytobands } = self;
|
|
605
868
|
const session = (0, util_1.getSession)(self);
|
|
@@ -647,59 +910,57 @@ function stateModelFactory(pluginManager) {
|
|
|
647
910
|
icon: SyncAlt_1.default,
|
|
648
911
|
onClick: self.horizontallyFlip,
|
|
649
912
|
},
|
|
650
|
-
{ type: 'divider' },
|
|
651
|
-
{
|
|
652
|
-
label: 'Show all regions in assembly',
|
|
653
|
-
icon: Visibility_1.default,
|
|
654
|
-
onClick: self.showAllRegionsInAssembly,
|
|
655
|
-
},
|
|
656
|
-
{
|
|
657
|
-
label: 'Show center line',
|
|
658
|
-
icon: Visibility_1.default,
|
|
659
|
-
type: 'checkbox',
|
|
660
|
-
checked: self.showCenterLine,
|
|
661
|
-
onClick: self.toggleCenterLine,
|
|
662
|
-
},
|
|
663
|
-
{
|
|
664
|
-
label: 'Show header',
|
|
665
|
-
icon: Visibility_1.default,
|
|
666
|
-
type: 'checkbox',
|
|
667
|
-
checked: !self.hideHeader,
|
|
668
|
-
onClick: self.toggleHeader,
|
|
669
|
-
},
|
|
670
913
|
{
|
|
671
|
-
label: 'Show
|
|
914
|
+
label: 'Show...',
|
|
672
915
|
icon: Visibility_1.default,
|
|
673
|
-
|
|
674
|
-
checked: !self.hideHeaderOverview,
|
|
675
|
-
onClick: self.toggleHeaderOverview,
|
|
676
|
-
disabled: self.hideHeader,
|
|
677
|
-
},
|
|
678
|
-
{
|
|
679
|
-
label: 'Show no tracks active button',
|
|
680
|
-
icon: Visibility_1.default,
|
|
681
|
-
type: 'checkbox',
|
|
682
|
-
checked: !self.hideNoTracksActive,
|
|
683
|
-
onClick: self.toggleNoTracksActive,
|
|
684
|
-
},
|
|
685
|
-
{
|
|
686
|
-
label: 'Show guidelines',
|
|
687
|
-
icon: Visibility_1.default,
|
|
688
|
-
type: 'checkbox',
|
|
689
|
-
checked: self.showGridlines,
|
|
690
|
-
onClick: self.toggleShowGridlines,
|
|
691
|
-
},
|
|
692
|
-
...(canShowCytobands
|
|
693
|
-
? [
|
|
916
|
+
subMenu: [
|
|
694
917
|
{
|
|
695
|
-
label: 'Show
|
|
696
|
-
|
|
918
|
+
label: 'Show all regions in assembly',
|
|
919
|
+
onClick: self.showAllRegionsInAssembly,
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
label: 'Show center line',
|
|
697
923
|
type: 'checkbox',
|
|
698
|
-
checked: self.
|
|
699
|
-
onClick:
|
|
924
|
+
checked: self.showCenterLine,
|
|
925
|
+
onClick: self.toggleCenterLine,
|
|
700
926
|
},
|
|
701
|
-
|
|
702
|
-
|
|
927
|
+
{
|
|
928
|
+
label: 'Show header',
|
|
929
|
+
type: 'checkbox',
|
|
930
|
+
checked: !self.hideHeader,
|
|
931
|
+
onClick: self.toggleHeader,
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
label: 'Show header overview',
|
|
935
|
+
type: 'checkbox',
|
|
936
|
+
checked: !self.hideHeaderOverview,
|
|
937
|
+
onClick: self.toggleHeaderOverview,
|
|
938
|
+
disabled: self.hideHeader,
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
label: 'Show no tracks active button',
|
|
942
|
+
type: 'checkbox',
|
|
943
|
+
checked: !self.hideNoTracksActive,
|
|
944
|
+
onClick: self.toggleNoTracksActive,
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
label: 'Show guidelines',
|
|
948
|
+
type: 'checkbox',
|
|
949
|
+
checked: self.showGridlines,
|
|
950
|
+
onClick: self.toggleShowGridlines,
|
|
951
|
+
},
|
|
952
|
+
...(canShowCytobands
|
|
953
|
+
? [
|
|
954
|
+
{
|
|
955
|
+
label: 'Show ideogram',
|
|
956
|
+
type: 'checkbox',
|
|
957
|
+
checked: self.showCytobands,
|
|
958
|
+
onClick: () => self.setShowCytobands(!showCytobands),
|
|
959
|
+
},
|
|
960
|
+
]
|
|
961
|
+
: []),
|
|
962
|
+
],
|
|
963
|
+
},
|
|
703
964
|
{
|
|
704
965
|
label: 'Track labels',
|
|
705
966
|
icon: Label_1.default,
|
|
@@ -742,6 +1003,15 @@ function stateModelFactory(pluginManager) {
|
|
|
742
1003
|
let currentlyCalculatedStaticBlocks;
|
|
743
1004
|
let stringifiedCurrentlyCalculatedStaticBlocks = '';
|
|
744
1005
|
return {
|
|
1006
|
+
/**
|
|
1007
|
+
* #getter
|
|
1008
|
+
* static blocks are an important concept jbrowse uses to avoid
|
|
1009
|
+
* re-rendering when you scroll to the side. when you horizontally
|
|
1010
|
+
* scroll to the right, old blocks to the left may be removed, and
|
|
1011
|
+
* new blocks may be instantiated on the right. tracks may use the
|
|
1012
|
+
* static blocks to render their data for the region represented by
|
|
1013
|
+
* the block
|
|
1014
|
+
*/
|
|
745
1015
|
get staticBlocks() {
|
|
746
1016
|
const ret = (0, calculateStaticBlocks_1.default)(self);
|
|
747
1017
|
const sret = JSON.stringify(ret);
|
|
@@ -751,27 +1021,48 @@ function stateModelFactory(pluginManager) {
|
|
|
751
1021
|
}
|
|
752
1022
|
return currentlyCalculatedStaticBlocks;
|
|
753
1023
|
},
|
|
1024
|
+
/**
|
|
1025
|
+
* #getter
|
|
1026
|
+
* dynamic blocks represent the exact coordinates of the currently
|
|
1027
|
+
* visible genome regions on the screen. they are similar to static
|
|
1028
|
+
* blocks, but statcic blocks can go offscreen while dynamic blocks
|
|
1029
|
+
* represent exactly what is on screen
|
|
1030
|
+
*/
|
|
754
1031
|
get dynamicBlocks() {
|
|
755
1032
|
return (0, calculateDynamicBlocks_1.default)(self);
|
|
756
1033
|
},
|
|
1034
|
+
/**
|
|
1035
|
+
* #getter
|
|
1036
|
+
* rounded dynamic blocks are dynamic blocks without fractions of bp
|
|
1037
|
+
*/
|
|
757
1038
|
get roundedDynamicBlocks() {
|
|
758
|
-
return this.dynamicBlocks.contentBlocks.map(block => {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
};
|
|
764
|
-
});
|
|
1039
|
+
return this.dynamicBlocks.contentBlocks.map(block => ({
|
|
1040
|
+
...block,
|
|
1041
|
+
start: Math.floor(block.start),
|
|
1042
|
+
end: Math.ceil(block.end),
|
|
1043
|
+
}));
|
|
765
1044
|
},
|
|
1045
|
+
/**
|
|
1046
|
+
* #getter
|
|
1047
|
+
* a single "combo-locstring" representing all the regions visible
|
|
1048
|
+
* on the screen
|
|
1049
|
+
*/
|
|
766
1050
|
get visibleLocStrings() {
|
|
767
1051
|
return calculateVisibleLocStrings(this.dynamicBlocks.contentBlocks);
|
|
768
1052
|
},
|
|
1053
|
+
/**
|
|
1054
|
+
* #getter
|
|
1055
|
+
* same as visibleLocStrings, but only updated every 300ms
|
|
1056
|
+
*/
|
|
769
1057
|
get coarseVisibleLocStrings() {
|
|
770
1058
|
return calculateVisibleLocStrings(self.coarseDynamicBlocks);
|
|
771
1059
|
},
|
|
772
1060
|
};
|
|
773
1061
|
})
|
|
774
1062
|
.actions(self => ({
|
|
1063
|
+
/**
|
|
1064
|
+
* #action
|
|
1065
|
+
*/
|
|
775
1066
|
setCoarseDynamicBlocks(blocks) {
|
|
776
1067
|
self.coarseDynamicBlocks = blocks.contentBlocks;
|
|
777
1068
|
self.coarseTotalBp = blocks.totalBp;
|
|
@@ -786,6 +1077,7 @@ function stateModelFactory(pluginManager) {
|
|
|
786
1077
|
}))
|
|
787
1078
|
.actions(self => ({
|
|
788
1079
|
/**
|
|
1080
|
+
* #action
|
|
789
1081
|
* offset is the base-pair-offset in the displayed region, index is the index of the
|
|
790
1082
|
* displayed region in the linear genome view
|
|
791
1083
|
*
|
|
@@ -795,7 +1087,14 @@ function stateModelFactory(pluginManager) {
|
|
|
795
1087
|
moveTo(start, end) {
|
|
796
1088
|
(0, Base1DUtils_1.moveTo)(self, start, end);
|
|
797
1089
|
},
|
|
798
|
-
|
|
1090
|
+
/**
|
|
1091
|
+
* #action
|
|
1092
|
+
* navigate to the given locstring
|
|
1093
|
+
*
|
|
1094
|
+
* @param locString - e.g. "chr1:1-100"
|
|
1095
|
+
* @param optAssemblyName - (optional) the assembly name to use when navigating to the locstring
|
|
1096
|
+
*/
|
|
1097
|
+
async navToLocString(locString, optAssemblyName) {
|
|
799
1098
|
const { assemblyNames } = self;
|
|
800
1099
|
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
801
1100
|
const { isValidRefName } = assemblyManager;
|
|
@@ -805,6 +1104,9 @@ function stateModelFactory(pluginManager) {
|
|
|
805
1104
|
.split(/(\s+)/)
|
|
806
1105
|
.map(f => f.trim())
|
|
807
1106
|
.filter(f => !!f);
|
|
1107
|
+
if (assemblyName) {
|
|
1108
|
+
await assemblyManager.waitForAssembly(assemblyName);
|
|
1109
|
+
}
|
|
808
1110
|
// first try interpreting as a whitespace-separated sequence of
|
|
809
1111
|
// multiple locstrings
|
|
810
1112
|
try {
|
|
@@ -825,9 +1127,9 @@ function stateModelFactory(pluginManager) {
|
|
|
825
1127
|
throw e;
|
|
826
1128
|
}
|
|
827
1129
|
}
|
|
828
|
-
const locations = parsedLocStrings === null || parsedLocStrings === void 0 ? void 0 : parsedLocStrings.map(region => {
|
|
1130
|
+
const locations = await Promise.all(parsedLocStrings === null || parsedLocStrings === void 0 ? void 0 : parsedLocStrings.map(async (region) => {
|
|
829
1131
|
const asmName = region.assemblyName || assemblyName;
|
|
830
|
-
const asm = assemblyManager.
|
|
1132
|
+
const asm = await assemblyManager.waitForAssembly(asmName);
|
|
831
1133
|
const { refName } = region;
|
|
832
1134
|
if (!asm) {
|
|
833
1135
|
throw new Error(`assembly ${asmName} not found`);
|
|
@@ -840,7 +1142,7 @@ function stateModelFactory(pluginManager) {
|
|
|
840
1142
|
if (!canonicalRefName) {
|
|
841
1143
|
throw new Error(`Could not find refName ${refName} in ${asm.name}`);
|
|
842
1144
|
}
|
|
843
|
-
const parentRegion = regions.find(
|
|
1145
|
+
const parentRegion = regions.find(r => r.refName === canonicalRefName);
|
|
844
1146
|
if (!parentRegion) {
|
|
845
1147
|
throw new Error(`Could not find refName ${refName} in ${asmName}`);
|
|
846
1148
|
}
|
|
@@ -849,7 +1151,7 @@ function stateModelFactory(pluginManager) {
|
|
|
849
1151
|
assemblyName: asmName,
|
|
850
1152
|
parentRegion,
|
|
851
1153
|
};
|
|
852
|
-
});
|
|
1154
|
+
}));
|
|
853
1155
|
if (locations.length === 1) {
|
|
854
1156
|
const loc = locations[0];
|
|
855
1157
|
self.setDisplayedRegions([
|
|
@@ -870,6 +1172,7 @@ function stateModelFactory(pluginManager) {
|
|
|
870
1172
|
}
|
|
871
1173
|
},
|
|
872
1174
|
/**
|
|
1175
|
+
* #action
|
|
873
1176
|
* Navigate to a location based on its refName and optionally start, end,
|
|
874
1177
|
* and assemblyName. Can handle if there are multiple displayedRegions
|
|
875
1178
|
* from same refName. Only navigates to a location if it is entirely
|
|
@@ -878,11 +1181,14 @@ function stateModelFactory(pluginManager) {
|
|
|
878
1181
|
*
|
|
879
1182
|
* Throws an error if navigation was unsuccessful
|
|
880
1183
|
*
|
|
881
|
-
* @param
|
|
1184
|
+
* @param query - a proposed location to navigate to
|
|
882
1185
|
*/
|
|
883
1186
|
navTo(query) {
|
|
884
1187
|
this.navToMultiple([query]);
|
|
885
1188
|
},
|
|
1189
|
+
/**
|
|
1190
|
+
* #action
|
|
1191
|
+
*/
|
|
886
1192
|
navToMultiple(locations) {
|
|
887
1193
|
const firstLocation = locations[0];
|
|
888
1194
|
let { refName } = firstLocation;
|
|
@@ -947,31 +1253,31 @@ function stateModelFactory(pluginManager) {
|
|
|
947
1253
|
this.moveTo({ index, offset: f.reversed ? f.end - e : s - f.start }, { index, offset: f.reversed ? f.end - s : e - f.start });
|
|
948
1254
|
return;
|
|
949
1255
|
}
|
|
950
|
-
let
|
|
951
|
-
let
|
|
952
|
-
let
|
|
953
|
-
for (
|
|
954
|
-
const location = locations[
|
|
955
|
-
const region = self.displayedRegions[index +
|
|
956
|
-
|
|
957
|
-
|
|
1256
|
+
let idx = 0;
|
|
1257
|
+
let start = 0;
|
|
1258
|
+
let end = 0;
|
|
1259
|
+
for (idx; idx < locations.length; idx++) {
|
|
1260
|
+
const location = locations[idx];
|
|
1261
|
+
const region = self.displayedRegions[index + idx];
|
|
1262
|
+
start = location.start || region.start;
|
|
1263
|
+
end = location.end || region.end;
|
|
958
1264
|
if (location.refName !== region.refName) {
|
|
959
1265
|
throw new Error(`Entered location ${(0, util_1.assembleLocString)(location)} does not match with displayed regions`);
|
|
960
1266
|
}
|
|
961
1267
|
}
|
|
962
|
-
|
|
1268
|
+
idx -= 1;
|
|
963
1269
|
const startDisplayedRegion = self.displayedRegions[index];
|
|
964
|
-
const endDisplayedRegion = self.displayedRegions[index +
|
|
1270
|
+
const endDisplayedRegion = self.displayedRegions[index + idx];
|
|
965
1271
|
this.moveTo({
|
|
966
1272
|
index,
|
|
967
1273
|
offset: startDisplayedRegion.reversed
|
|
968
1274
|
? startDisplayedRegion.end - e
|
|
969
1275
|
: s - startDisplayedRegion.start,
|
|
970
1276
|
}, {
|
|
971
|
-
index: index +
|
|
1277
|
+
index: index + idx,
|
|
972
1278
|
offset: endDisplayedRegion.reversed
|
|
973
|
-
? endDisplayedRegion.end -
|
|
974
|
-
:
|
|
1279
|
+
? endDisplayedRegion.end - start
|
|
1280
|
+
: end - endDisplayedRegion.start,
|
|
975
1281
|
});
|
|
976
1282
|
return;
|
|
977
1283
|
}
|
|
@@ -984,6 +1290,9 @@ function stateModelFactory(pluginManager) {
|
|
|
984
1290
|
},
|
|
985
1291
|
}))
|
|
986
1292
|
.views(self => ({
|
|
1293
|
+
/**
|
|
1294
|
+
* #method
|
|
1295
|
+
*/
|
|
987
1296
|
rubberBandMenuItems() {
|
|
988
1297
|
return [
|
|
989
1298
|
{
|
|
@@ -1001,10 +1310,14 @@ function stateModelFactory(pluginManager) {
|
|
|
1001
1310
|
},
|
|
1002
1311
|
];
|
|
1003
1312
|
},
|
|
1313
|
+
/**
|
|
1314
|
+
* #method
|
|
1315
|
+
*/
|
|
1004
1316
|
bpToPx({ refName, coord, regionNumber, }) {
|
|
1005
1317
|
return (0, Base1DUtils_1.bpToPx)({ refName, coord, regionNumber, self });
|
|
1006
1318
|
},
|
|
1007
1319
|
/**
|
|
1320
|
+
* #method
|
|
1008
1321
|
* scrolls the view to center on the given bp. if that is not in any
|
|
1009
1322
|
* of the displayed regions, does nothing
|
|
1010
1323
|
* @param coord - basepair at which you want to center the view
|
|
@@ -1021,9 +1334,15 @@ function stateModelFactory(pluginManager) {
|
|
|
1021
1334
|
self.scrollTo(Math.round(centerPx.offsetPx - self.width / 2));
|
|
1022
1335
|
}
|
|
1023
1336
|
},
|
|
1337
|
+
/**
|
|
1338
|
+
* #method
|
|
1339
|
+
*/
|
|
1024
1340
|
pxToBp(px) {
|
|
1025
1341
|
return (0, Base1DUtils_1.pxToBp)(self, px);
|
|
1026
1342
|
},
|
|
1343
|
+
/**
|
|
1344
|
+
* #getter
|
|
1345
|
+
*/
|
|
1027
1346
|
get centerLineInfo() {
|
|
1028
1347
|
return self.displayedRegions.length
|
|
1029
1348
|
? this.pxToBp(self.width / 2)
|