react-msaview 3.1.12 → 3.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/bundle/index.js +32 -31
- package/dist/colorSchemes.d.ts +2 -2
- package/dist/colorSchemes.js +3 -4
- package/dist/colorSchemes.js.map +1 -1
- package/dist/components/Loading.d.ts +1 -1
- package/dist/components/Loading.js +4 -4
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/MSAView.d.ts +1 -1
- package/dist/components/MSAView.js +13 -9
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/ResizeHandles.d.ts +1 -1
- package/dist/components/ResizeHandles.js +2 -2
- package/dist/components/TextTrack.d.ts +1 -1
- package/dist/components/Track.d.ts +1 -1
- package/dist/components/VerticalScrollbar.d.ts +6 -0
- package/dist/components/VerticalScrollbar.js +65 -0
- package/dist/components/VerticalScrollbar.js.map +1 -0
- package/dist/components/dialogs/AddTrackDialog.d.ts +1 -1
- package/dist/components/dialogs/DomainDialog.d.ts +1 -1
- package/dist/components/dialogs/DomainDialog.js +2 -2
- package/dist/components/dialogs/DomainDialog.js.map +1 -1
- package/dist/components/dialogs/ExportSVGDialog.d.ts +1 -1
- package/dist/components/dialogs/FeatureDialog.d.ts +1 -1
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/{InterProScanPanel.d.ts → InterProScanDialog.d.ts} +1 -1
- package/dist/components/dialogs/{InterProScanPanel.js → InterProScanDialog.js} +4 -3
- package/dist/components/dialogs/InterProScanDialog.js.map +1 -0
- package/dist/components/dialogs/MetadataDialog.d.ts +1 -1
- package/dist/components/dialogs/SettingsDialog.d.ts +1 -1
- package/dist/components/dialogs/SettingsDialog.js +10 -1
- package/dist/components/dialogs/SettingsDialog.js.map +1 -1
- package/dist/components/dialogs/TracklistDialog.d.ts +1 -1
- package/dist/components/dialogs/UserProvidedDomainsDialog.d.ts +7 -0
- package/dist/components/dialogs/UserProvidedDomainsDialog.js +58 -0
- package/dist/components/dialogs/UserProvidedDomainsDialog.js.map +1 -0
- package/dist/components/header/Header.d.ts +1 -1
- package/dist/components/header/Header.js +8 -3
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/HeaderInfoArea.d.ts +1 -1
- package/dist/components/header/HeaderMenu.d.ts +1 -1
- package/dist/components/header/HeaderMenuExtra.d.ts +1 -1
- package/dist/components/header/HeaderMenuExtra.js +30 -28
- package/dist/components/header/HeaderMenuExtra.js.map +1 -1
- package/dist/components/header/HeaderStatusArea.d.ts +2 -2
- package/dist/components/header/HeaderStatusArea.js +1 -1
- package/dist/components/header/HeaderStatusArea.js.map +1 -1
- package/dist/components/header/MultiAlignmentSelector.d.ts +1 -1
- package/dist/components/header/ZoomControls.js +31 -1
- package/dist/components/header/ZoomControls.js.map +1 -1
- package/dist/components/import/ImportForm.d.ts +1 -1
- package/dist/components/import/ImportForm.js +1 -1
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/import/ImportFormExamples.d.ts +1 -1
- package/dist/components/import/ImportFormExamples.js +10 -8
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/import/util.d.ts +2 -2
- package/dist/components/minimap/Minimap.d.ts +1 -1
- package/dist/components/minimap/Minimap.js +14 -15
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/minimap/MinimapSVG.d.ts +1 -1
- package/dist/components/minimap/MinimapSVG.js +1 -1
- package/dist/components/minimap/MinimapSVG.js.map +1 -1
- package/dist/components/msa/MSACanvas.d.ts +1 -1
- package/dist/components/msa/MSACanvas.js +3 -3
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.d.ts +3 -3
- package/dist/components/msa/MSACanvasBlock.js +4 -3
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.d.ts +2 -2
- package/dist/components/msa/MSAMouseoverCanvas.js +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/MSAPanel.d.ts +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +1 -2
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderMSABlock.d.ts +2 -2
- package/dist/components/msa/renderMSABlock.js +12 -12
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.d.ts +1 -1
- package/dist/components/tree/TreeBranchMenu.d.ts +1 -1
- package/dist/components/tree/TreeCanvas.d.ts +1 -1
- package/dist/components/tree/TreeCanvas.js +13 -12
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.d.ts +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +2 -1
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/TreeNodeMenu.d.ts +1 -1
- package/dist/components/tree/TreeNodeMenu.js +2 -2
- package/dist/components/tree/TreeNodeMenu.js.map +1 -1
- package/dist/components/tree/TreePanel.d.ts +1 -1
- package/dist/components/tree/TreeRuler.d.ts +1 -1
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.d.ts +1 -1
- package/dist/components/tree/renderTreeCanvas.d.ts +3 -3
- package/dist/components/tree/renderTreeCanvas.js +25 -9
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/components/util.js +1 -1
- package/dist/components/util.js.map +1 -1
- package/dist/launchInterProScan.d.ts +1 -1
- package/dist/launchInterProScan.js +7 -9
- package/dist/launchInterProScan.js.map +1 -1
- package/dist/model/DataModel.d.ts +5 -1
- package/dist/model/DataModel.js +10 -1
- package/dist/model/DataModel.js.map +1 -1
- package/dist/model/DialogQueue.d.ts +1 -1
- package/dist/model.d.ts +141 -24
- package/dist/model.js +236 -50
- package/dist/model.js.map +1 -1
- package/dist/parseNewick.js +1 -1
- package/dist/parseNewick.js.map +1 -1
- package/dist/parsers/ClustalMSA.d.ts +1 -1
- package/dist/parsers/FastaMSA.d.ts +1 -1
- package/dist/parsers/StockholmMSA.d.ts +1 -1
- package/dist/parsers/StockholmMSA.js.map +1 -1
- package/dist/renderToSvg.d.ts +2 -2
- package/dist/renderToSvg.js +3 -5
- package/dist/renderToSvg.js.map +1 -1
- package/dist/reparseTree.d.ts +1 -1
- package/dist/util.d.ts +2 -2
- package/dist/util.js +0 -2
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +5 -2
- package/src/colorSchemes.ts +3 -2
- package/src/components/Checkbox2.tsx +1 -1
- package/src/components/Loading.tsx +11 -5
- package/src/components/MSAView.tsx +27 -18
- package/src/components/ResizeHandles.tsx +3 -3
- package/src/components/TextTrack.tsx +1 -1
- package/src/components/Track.tsx +1 -1
- package/src/components/VerticalScrollbar.tsx +85 -0
- package/src/components/dialogs/AddTrackDialog.tsx +2 -2
- package/src/components/dialogs/DomainDialog.tsx +3 -3
- package/src/components/dialogs/ExportSVGDialog.tsx +1 -1
- package/src/components/dialogs/FeatureDialog.tsx +3 -3
- package/src/components/dialogs/{InterProScanPanel.tsx → InterProScanDialog.tsx} +11 -4
- package/src/components/dialogs/MetadataDialog.tsx +1 -1
- package/src/components/dialogs/SettingsDialog.tsx +38 -3
- package/src/components/dialogs/TracklistDialog.tsx +1 -1
- package/src/components/dialogs/UserProvidedDomainsDialog.tsx +133 -0
- package/src/components/header/Header.tsx +9 -4
- package/src/components/header/HeaderInfoArea.tsx +1 -1
- package/src/components/header/HeaderMenu.tsx +1 -1
- package/src/components/header/HeaderMenuExtra.tsx +36 -32
- package/src/components/header/HeaderStatusArea.tsx +2 -6
- package/src/components/header/MultiAlignmentSelector.tsx +1 -1
- package/src/components/header/ZoomControls.tsx +34 -0
- package/src/components/import/ImportForm.tsx +3 -3
- package/src/components/import/ImportFormExamples.tsx +19 -17
- package/src/components/import/util.ts +2 -2
- package/src/components/minimap/Minimap.tsx +15 -22
- package/src/components/minimap/MinimapSVG.tsx +2 -2
- package/src/components/msa/MSACanvas.tsx +11 -4
- package/src/components/msa/MSACanvasBlock.tsx +5 -4
- package/src/components/msa/MSAMouseoverCanvas.tsx +2 -6
- package/src/components/msa/MSAPanel.tsx +1 -1
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +4 -5
- package/src/components/msa/renderMSABlock.ts +37 -17
- package/src/components/msa/renderMSAMouseover.ts +1 -1
- package/src/components/tree/TreeBranchMenu.tsx +1 -1
- package/src/components/tree/TreeCanvas.tsx +15 -16
- package/src/components/tree/TreeCanvasBlock.tsx +3 -2
- package/src/components/tree/TreeNodeMenu.tsx +3 -3
- package/src/components/tree/TreePanel.tsx +1 -1
- package/src/components/tree/TreeRuler.tsx +1 -1
- package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +1 -1
- package/src/components/tree/renderTreeCanvas.ts +32 -12
- package/src/components/util.ts +1 -1
- package/src/launchInterProScan.ts +8 -10
- package/src/model/DataModel.ts +10 -0
- package/src/model/DialogQueue.ts +1 -1
- package/src/model.ts +262 -62
- package/src/parseNewick.ts +1 -1
- package/src/parsers/ClustalMSA.ts +1 -1
- package/src/parsers/FastaMSA.ts +1 -1
- package/src/parsers/StockholmMSA.ts +1 -1
- package/src/renderToSvg.tsx +6 -6
- package/src/reparseTree.ts +1 -1
- package/src/util.ts +2 -4
- package/src/version.ts +1 -1
- package/dist/components/dialogs/InterProScanPanel.js.map +0 -1
- package/dist/components/dialogs/UserProvidedResultPanel.d.ts +0 -7
- package/dist/components/dialogs/UserProvidedResultPanel.js +0 -56
- package/dist/components/dialogs/UserProvidedResultPanel.js.map +0 -1
- package/src/components/dialogs/UserProvidedResultPanel.tsx +0 -119
package/src/model.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
+
import type { Buffer } from 'buffer'
|
|
2
3
|
import { autorun, transaction } from 'mobx'
|
|
3
|
-
import { Instance, cast, types, addDisposer } from 'mobx-state-tree'
|
|
4
|
-
import { hierarchy, cluster, HierarchyNode } from 'd3-hierarchy'
|
|
4
|
+
import { type Instance, cast, types, addDisposer } from 'mobx-state-tree'
|
|
5
|
+
import { hierarchy, cluster, type HierarchyNode } from 'd3-hierarchy'
|
|
5
6
|
import { ascending } from 'd3-array'
|
|
6
7
|
import Stockholm from 'stockholm-js'
|
|
7
8
|
import { saveAs } from 'file-saver'
|
|
8
|
-
import { Theme } from '@mui/material'
|
|
9
|
+
import type { Theme } from '@mui/material'
|
|
10
|
+
import { ungzip } from 'pako'
|
|
9
11
|
|
|
10
12
|
// jbrowse
|
|
11
13
|
import { FileLocation, ElementId } from '@jbrowse/core/util/types/mst'
|
|
12
|
-
import { FileLocation as FileLocationType } from '@jbrowse/core/util/types'
|
|
14
|
+
import type { FileLocation as FileLocationType } from '@jbrowse/core/util/types'
|
|
13
15
|
import { openLocation } from '@jbrowse/core/util/io'
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
sum,
|
|
20
|
-
} from '@jbrowse/core/util'
|
|
16
|
+
import { groupBy, notEmpty, sum } from '@jbrowse/core/util'
|
|
17
|
+
|
|
18
|
+
export function isGzip(buf: Buffer) {
|
|
19
|
+
return buf[0] === 31 && buf[1] === 139 && buf[2] === 8
|
|
20
|
+
}
|
|
21
21
|
|
|
22
22
|
// locals
|
|
23
23
|
import {
|
|
@@ -27,8 +27,8 @@ import {
|
|
|
27
27
|
maxLength,
|
|
28
28
|
setBrLength,
|
|
29
29
|
skipBlanks,
|
|
30
|
-
NodeWithIds,
|
|
31
|
-
NodeWithIdsAndLength,
|
|
30
|
+
type NodeWithIds,
|
|
31
|
+
type NodeWithIdsAndLength,
|
|
32
32
|
len,
|
|
33
33
|
} from './util'
|
|
34
34
|
import { colord } from 'colord'
|
|
@@ -52,7 +52,7 @@ import { DataModelF } from './model/DataModel'
|
|
|
52
52
|
import { DialogQueueSessionMixin } from './model/DialogQueue'
|
|
53
53
|
import { TreeF } from './model/treeModel'
|
|
54
54
|
import { MSAModelF } from './model/msaModel'
|
|
55
|
-
import { InterProScanResults } from './launchInterProScan'
|
|
55
|
+
import type { InterProScanResults } from './launchInterProScan'
|
|
56
56
|
|
|
57
57
|
export interface Accession {
|
|
58
58
|
accession: string
|
|
@@ -98,10 +98,20 @@ function stateModelFactory() {
|
|
|
98
98
|
* id of view, randomly generated if not provided
|
|
99
99
|
*/
|
|
100
100
|
id: ElementId,
|
|
101
|
+
|
|
101
102
|
/**
|
|
102
103
|
* #property
|
|
103
104
|
*/
|
|
104
105
|
showDomains: false,
|
|
106
|
+
/**
|
|
107
|
+
* #property
|
|
108
|
+
*/
|
|
109
|
+
allowedGappyness: 100,
|
|
110
|
+
/**
|
|
111
|
+
* #property
|
|
112
|
+
*/
|
|
113
|
+
contrastLettering: true,
|
|
114
|
+
|
|
105
115
|
/**
|
|
106
116
|
* #property
|
|
107
117
|
*/
|
|
@@ -113,6 +123,20 @@ function stateModelFactory() {
|
|
|
113
123
|
*/
|
|
114
124
|
type: types.literal('MsaView'),
|
|
115
125
|
|
|
126
|
+
/**
|
|
127
|
+
* #property
|
|
128
|
+
*/
|
|
129
|
+
drawMsaLetters: true,
|
|
130
|
+
/**
|
|
131
|
+
* #property
|
|
132
|
+
*/
|
|
133
|
+
hideGaps: true,
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* #property
|
|
137
|
+
*/
|
|
138
|
+
drawTreeText: true,
|
|
139
|
+
|
|
116
140
|
/**
|
|
117
141
|
* #property
|
|
118
142
|
* height of the div containing the view, px
|
|
@@ -170,15 +194,17 @@ function stateModelFactory() {
|
|
|
170
194
|
|
|
171
195
|
/**
|
|
172
196
|
* #property
|
|
173
|
-
* array of tree parent nodes that are 'collapsed'
|
|
197
|
+
* array of tree parent nodes that are 'collapsed' (all children are
|
|
198
|
+
* hidden)
|
|
174
199
|
*/
|
|
175
200
|
collapsed: types.array(types.string),
|
|
176
201
|
|
|
177
202
|
/**
|
|
178
203
|
* #property
|
|
179
|
-
* array of tree leaf nodes that are 'collapsed'
|
|
204
|
+
* array of tree leaf nodes that are 'collapsed' (just that leaf node
|
|
205
|
+
* is hidden)
|
|
180
206
|
*/
|
|
181
|
-
|
|
207
|
+
collapsedLeaves: types.array(types.string),
|
|
182
208
|
/**
|
|
183
209
|
* #property
|
|
184
210
|
* focus on particular subtree
|
|
@@ -196,6 +222,7 @@ function stateModelFactory() {
|
|
|
196
222
|
* autorun
|
|
197
223
|
*/
|
|
198
224
|
data: types.optional(DataModelF(), { tree: '', msa: '' }),
|
|
225
|
+
|
|
199
226
|
/**
|
|
200
227
|
* #property
|
|
201
228
|
*/
|
|
@@ -203,6 +230,13 @@ function stateModelFactory() {
|
|
|
203
230
|
}),
|
|
204
231
|
)
|
|
205
232
|
.volatile(() => ({
|
|
233
|
+
/**
|
|
234
|
+
* #volatile
|
|
235
|
+
*/
|
|
236
|
+
headerHeight: 0,
|
|
237
|
+
/**
|
|
238
|
+
* #volatile
|
|
239
|
+
*/
|
|
206
240
|
status: undefined as { msg: string; url?: string } | undefined,
|
|
207
241
|
/**
|
|
208
242
|
* #volatile
|
|
@@ -221,7 +255,7 @@ function stateModelFactory() {
|
|
|
221
255
|
/**
|
|
222
256
|
* #volatile
|
|
223
257
|
*/
|
|
224
|
-
|
|
258
|
+
volatileWidth: undefined as number | undefined,
|
|
225
259
|
/**
|
|
226
260
|
* #volatile
|
|
227
261
|
* resize handle width between tree and msa area, px
|
|
@@ -232,7 +266,7 @@ function stateModelFactory() {
|
|
|
232
266
|
* #volatile
|
|
233
267
|
* size of blocks of content to be drawn, px
|
|
234
268
|
*/
|
|
235
|
-
blockSize:
|
|
269
|
+
blockSize: 500,
|
|
236
270
|
|
|
237
271
|
/**
|
|
238
272
|
* #volatile
|
|
@@ -289,11 +323,29 @@ function stateModelFactory() {
|
|
|
289
323
|
* #volatile
|
|
290
324
|
*
|
|
291
325
|
*/
|
|
292
|
-
|
|
326
|
+
interProAnnotations: undefined as
|
|
293
327
|
| undefined
|
|
294
328
|
| Record<string, InterProScanResults>,
|
|
295
329
|
}))
|
|
296
330
|
.actions(self => ({
|
|
331
|
+
/**
|
|
332
|
+
* #action
|
|
333
|
+
*/
|
|
334
|
+
setHideGaps(arg: boolean) {
|
|
335
|
+
self.hideGaps = arg
|
|
336
|
+
},
|
|
337
|
+
/**
|
|
338
|
+
* #action
|
|
339
|
+
*/
|
|
340
|
+
setAllowedGappyness(arg: number) {
|
|
341
|
+
self.allowedGappyness = arg
|
|
342
|
+
},
|
|
343
|
+
/**
|
|
344
|
+
* #action
|
|
345
|
+
*/
|
|
346
|
+
setContrastLettering(arg: boolean) {
|
|
347
|
+
self.contrastLettering = arg
|
|
348
|
+
},
|
|
297
349
|
/**
|
|
298
350
|
* #action
|
|
299
351
|
*/
|
|
@@ -310,7 +362,7 @@ function stateModelFactory() {
|
|
|
310
362
|
* #action
|
|
311
363
|
*/
|
|
312
364
|
setWidth(arg: number) {
|
|
313
|
-
self.
|
|
365
|
+
self.volatileWidth = arg
|
|
314
366
|
},
|
|
315
367
|
/**
|
|
316
368
|
* #action
|
|
@@ -405,10 +457,10 @@ function stateModelFactory() {
|
|
|
405
457
|
* #action
|
|
406
458
|
*/
|
|
407
459
|
toggleCollapsed2(node: string) {
|
|
408
|
-
if (self.
|
|
409
|
-
self.
|
|
460
|
+
if (self.collapsedLeaves.includes(node)) {
|
|
461
|
+
self.collapsedLeaves.remove(node)
|
|
410
462
|
} else {
|
|
411
|
-
self.
|
|
463
|
+
self.collapsedLeaves.push(node)
|
|
412
464
|
}
|
|
413
465
|
},
|
|
414
466
|
/**
|
|
@@ -461,6 +513,29 @@ function stateModelFactory() {
|
|
|
461
513
|
},
|
|
462
514
|
}))
|
|
463
515
|
|
|
516
|
+
.views(self => ({
|
|
517
|
+
/**
|
|
518
|
+
* #getter
|
|
519
|
+
*/
|
|
520
|
+
get actuallyShowDomains() {
|
|
521
|
+
return self.showDomains && !!self.interProAnnotations
|
|
522
|
+
},
|
|
523
|
+
/**
|
|
524
|
+
* #getter
|
|
525
|
+
*/
|
|
526
|
+
get viewInitialized() {
|
|
527
|
+
return self.volatileWidth !== undefined
|
|
528
|
+
},
|
|
529
|
+
/**
|
|
530
|
+
* #getter
|
|
531
|
+
*/
|
|
532
|
+
get width() {
|
|
533
|
+
if (self.volatileWidth === undefined) {
|
|
534
|
+
throw new Error('not initialized')
|
|
535
|
+
}
|
|
536
|
+
return self.volatileWidth
|
|
537
|
+
},
|
|
538
|
+
}))
|
|
464
539
|
.views(self => ({
|
|
465
540
|
/**
|
|
466
541
|
* #method
|
|
@@ -502,13 +577,13 @@ function stateModelFactory() {
|
|
|
502
577
|
* #getter
|
|
503
578
|
*/
|
|
504
579
|
get noTree() {
|
|
505
|
-
return !!this.
|
|
580
|
+
return !!this.tree.noTree
|
|
506
581
|
},
|
|
507
582
|
/**
|
|
508
583
|
* #getter
|
|
509
584
|
*/
|
|
510
|
-
get
|
|
511
|
-
return !self.
|
|
585
|
+
get noDomains() {
|
|
586
|
+
return !self.interProAnnotations
|
|
512
587
|
},
|
|
513
588
|
/**
|
|
514
589
|
* #getter
|
|
@@ -530,11 +605,11 @@ function stateModelFactory() {
|
|
|
530
605
|
if (text) {
|
|
531
606
|
if (Stockholm.sniff(text)) {
|
|
532
607
|
return new StockholmMSA(text, self.currentAlignment)
|
|
533
|
-
}
|
|
608
|
+
}
|
|
609
|
+
if (text.startsWith('>')) {
|
|
534
610
|
return new FastaMSA(text)
|
|
535
|
-
} else {
|
|
536
|
-
return new ClustalMSA(text)
|
|
537
611
|
}
|
|
612
|
+
return new ClustalMSA(text)
|
|
538
613
|
}
|
|
539
614
|
return null
|
|
540
615
|
},
|
|
@@ -548,7 +623,7 @@ function stateModelFactory() {
|
|
|
548
623
|
/**
|
|
549
624
|
* #getter
|
|
550
625
|
*/
|
|
551
|
-
get
|
|
626
|
+
get tree(): NodeWithIds {
|
|
552
627
|
const ret = self.data.tree
|
|
553
628
|
? generateNodeIds(parseNewick(self.data.tree))
|
|
554
629
|
: this.MSA?.getTree() || {
|
|
@@ -563,7 +638,7 @@ function stateModelFactory() {
|
|
|
563
638
|
* #getter
|
|
564
639
|
*/
|
|
565
640
|
get rowNames(): string[] {
|
|
566
|
-
return this.
|
|
641
|
+
return this.leaves.map(n => n.data.name)
|
|
567
642
|
},
|
|
568
643
|
/**
|
|
569
644
|
* #getter
|
|
@@ -577,7 +652,7 @@ function stateModelFactory() {
|
|
|
577
652
|
* #getter
|
|
578
653
|
*/
|
|
579
654
|
get root() {
|
|
580
|
-
let hier = hierarchy(this.
|
|
655
|
+
let hier = hierarchy(this.tree, d => d.branchset)
|
|
581
656
|
.sum(d => (d.branchset ? 0 : 1))
|
|
582
657
|
.sort((a, b) => ascending(a.data.length || 1, b.data.length || 1))
|
|
583
658
|
|
|
@@ -588,7 +663,7 @@ function stateModelFactory() {
|
|
|
588
663
|
}
|
|
589
664
|
}
|
|
590
665
|
|
|
591
|
-
;[...self.collapsed, ...self.
|
|
666
|
+
;[...self.collapsed, ...self.collapsedLeaves]
|
|
592
667
|
.map(collapsedId => hier.find(node => node.data.id === collapsedId))
|
|
593
668
|
.filter(notEmpty)
|
|
594
669
|
.map(node => collapse(node))
|
|
@@ -614,9 +689,9 @@ function stateModelFactory() {
|
|
|
614
689
|
* #getter
|
|
615
690
|
*/
|
|
616
691
|
get blanks() {
|
|
692
|
+
const { allowedGappyness } = self
|
|
617
693
|
const blanks = []
|
|
618
|
-
const strs = this.
|
|
619
|
-
.leaves()
|
|
694
|
+
const strs = this.leaves
|
|
620
695
|
.map(leaf => this.MSA?.getRow(leaf.data.name))
|
|
621
696
|
.filter((item): item is string => !!item)
|
|
622
697
|
|
|
@@ -627,7 +702,7 @@ function stateModelFactory() {
|
|
|
627
702
|
counter++
|
|
628
703
|
}
|
|
629
704
|
}
|
|
630
|
-
if (counter
|
|
705
|
+
if (counter / strs.length >= allowedGappyness / 100) {
|
|
631
706
|
blanks.push(i)
|
|
632
707
|
}
|
|
633
708
|
}
|
|
@@ -638,8 +713,7 @@ function stateModelFactory() {
|
|
|
638
713
|
*/
|
|
639
714
|
get rows() {
|
|
640
715
|
const MSA = this.MSA
|
|
641
|
-
return this.
|
|
642
|
-
.leaves()
|
|
716
|
+
return this.leaves
|
|
643
717
|
.map(leaf => [leaf.data.name, MSA?.getRow(leaf.data.name)] as const)
|
|
644
718
|
.filter((f): f is [string, string] => !!f[1])
|
|
645
719
|
},
|
|
@@ -683,6 +757,17 @@ function stateModelFactory() {
|
|
|
683
757
|
}
|
|
684
758
|
return r
|
|
685
759
|
},
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* #getter
|
|
763
|
+
*/
|
|
764
|
+
get colStatsSums() {
|
|
765
|
+
return Object.fromEntries(
|
|
766
|
+
Object.entries(this.colStats).map(([key, val]) => {
|
|
767
|
+
return [key, sum(Object.values(val))]
|
|
768
|
+
}),
|
|
769
|
+
)
|
|
770
|
+
},
|
|
686
771
|
/**
|
|
687
772
|
* #getter
|
|
688
773
|
* generates a new tree that is clustered with x,y positions
|
|
@@ -703,6 +788,13 @@ function stateModelFactory() {
|
|
|
703
788
|
get totalHeight() {
|
|
704
789
|
return this.root.leaves().length * self.rowHeight
|
|
705
790
|
},
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* #getter
|
|
794
|
+
*/
|
|
795
|
+
get leaves() {
|
|
796
|
+
return this.hierarchy.leaves()
|
|
797
|
+
},
|
|
706
798
|
}))
|
|
707
799
|
.views(self => ({
|
|
708
800
|
/**
|
|
@@ -717,7 +809,7 @@ function stateModelFactory() {
|
|
|
717
809
|
/**
|
|
718
810
|
* #getter
|
|
719
811
|
*/
|
|
720
|
-
get
|
|
812
|
+
get dataInitialized() {
|
|
721
813
|
return (self.data.msa || self.data.tree) && !self.error
|
|
722
814
|
},
|
|
723
815
|
/**
|
|
@@ -769,29 +861,78 @@ function stateModelFactory() {
|
|
|
769
861
|
get maxScrollX() {
|
|
770
862
|
return -self.totalWidth + (self.msaAreaWidth - 100)
|
|
771
863
|
},
|
|
864
|
+
/**
|
|
865
|
+
* #getter
|
|
866
|
+
*/
|
|
867
|
+
get showMsaLetters() {
|
|
868
|
+
return self.drawMsaLetters && self.rowHeight >= 5
|
|
869
|
+
},
|
|
870
|
+
/**
|
|
871
|
+
* #getter
|
|
872
|
+
*/
|
|
873
|
+
get showTreeText() {
|
|
874
|
+
return self.drawLabels && self.rowHeight >= 5
|
|
875
|
+
},
|
|
772
876
|
}))
|
|
773
877
|
.actions(self => ({
|
|
774
878
|
/**
|
|
775
879
|
* #action
|
|
776
880
|
*/
|
|
777
|
-
|
|
881
|
+
setDrawMsaLetters(arg: boolean) {
|
|
882
|
+
self.drawMsaLetters = arg
|
|
883
|
+
},
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* #action
|
|
887
|
+
*/
|
|
888
|
+
zoomOutHorizontal() {
|
|
889
|
+
self.colWidth = Math.max(1, Math.floor(self.colWidth * 0.75))
|
|
890
|
+
self.scrollX = clamp(self.maxScrollX, self.scrollX, 0)
|
|
891
|
+
},
|
|
892
|
+
/**
|
|
893
|
+
* #action
|
|
894
|
+
*/
|
|
895
|
+
zoomInHorizontal() {
|
|
778
896
|
self.colWidth = Math.ceil(self.colWidth * 1.5)
|
|
779
|
-
self.rowHeight = Math.ceil(self.rowHeight * 1.5)
|
|
780
897
|
self.scrollX = clamp(self.maxScrollX, self.scrollX, 0)
|
|
781
898
|
},
|
|
782
899
|
/**
|
|
783
900
|
* #action
|
|
784
901
|
*/
|
|
785
|
-
|
|
786
|
-
self.
|
|
902
|
+
zoomInVertical() {
|
|
903
|
+
self.rowHeight = Math.ceil(self.rowHeight * 1.5)
|
|
904
|
+
},
|
|
905
|
+
/**
|
|
906
|
+
* #action
|
|
907
|
+
*/
|
|
908
|
+
zoomOutVertical() {
|
|
787
909
|
self.rowHeight = Math.max(1.5, Math.floor(self.rowHeight * 0.75))
|
|
788
|
-
self.scrollX = clamp(self.maxScrollX, self.scrollX, 0)
|
|
789
910
|
},
|
|
790
911
|
/**
|
|
791
912
|
* #action
|
|
792
913
|
*/
|
|
793
|
-
|
|
794
|
-
|
|
914
|
+
zoomIn() {
|
|
915
|
+
transaction(() => {
|
|
916
|
+
self.colWidth = Math.ceil(self.colWidth * 1.5)
|
|
917
|
+
self.rowHeight = Math.ceil(self.rowHeight * 1.5)
|
|
918
|
+
self.scrollX = clamp(self.maxScrollX, self.scrollX, 0)
|
|
919
|
+
})
|
|
920
|
+
},
|
|
921
|
+
/**
|
|
922
|
+
* #action
|
|
923
|
+
*/
|
|
924
|
+
zoomOut() {
|
|
925
|
+
transaction(() => {
|
|
926
|
+
self.colWidth = Math.max(1, Math.floor(self.colWidth * 0.75))
|
|
927
|
+
self.rowHeight = Math.max(1.5, Math.floor(self.rowHeight * 0.75))
|
|
928
|
+
self.scrollX = clamp(self.maxScrollX, self.scrollX, 0)
|
|
929
|
+
})
|
|
930
|
+
},
|
|
931
|
+
/**
|
|
932
|
+
* #action
|
|
933
|
+
*/
|
|
934
|
+
setInterProAnnotations(data: Record<string, InterProScanResults>) {
|
|
935
|
+
self.interProAnnotations = data
|
|
795
936
|
},
|
|
796
937
|
|
|
797
938
|
/**
|
|
@@ -838,9 +979,9 @@ function stateModelFactory() {
|
|
|
838
979
|
*/
|
|
839
980
|
get labelsWidth() {
|
|
840
981
|
let x = 0
|
|
841
|
-
const { rowHeight,
|
|
982
|
+
const { rowHeight, leaves, treeMetadata, fontSize } = self
|
|
842
983
|
if (rowHeight > 5) {
|
|
843
|
-
for (const node of
|
|
984
|
+
for (const node of leaves) {
|
|
844
985
|
x = Math.max(
|
|
845
986
|
measureTextCanvas(
|
|
846
987
|
treeMetadata[node.data.name]?.genome || node.data.name,
|
|
@@ -912,6 +1053,13 @@ function stateModelFactory() {
|
|
|
912
1053
|
return this.tracks.filter(f => !self.turnedOffTracks.has(f.model.id))
|
|
913
1054
|
},
|
|
914
1055
|
|
|
1056
|
+
/**
|
|
1057
|
+
* #getter
|
|
1058
|
+
*/
|
|
1059
|
+
get showHorizontalScrollbar() {
|
|
1060
|
+
return self.msaAreaWidth < self.totalWidth
|
|
1061
|
+
},
|
|
1062
|
+
|
|
915
1063
|
/**
|
|
916
1064
|
* #method
|
|
917
1065
|
* return a row-specific sequence coordinate, skipping gaps, given a global
|
|
@@ -963,6 +1111,17 @@ function stateModelFactory() {
|
|
|
963
1111
|
}))
|
|
964
1112
|
|
|
965
1113
|
.views(self => ({
|
|
1114
|
+
/**
|
|
1115
|
+
* #getter
|
|
1116
|
+
* widget width minus the tree area gives the space for the MSA
|
|
1117
|
+
*/
|
|
1118
|
+
get msaAreaHeight() {
|
|
1119
|
+
return (
|
|
1120
|
+
self.height -
|
|
1121
|
+
(self.showHorizontalScrollbar ? self.minimapHeight : 0) -
|
|
1122
|
+
self.headerHeight
|
|
1123
|
+
)
|
|
1124
|
+
},
|
|
966
1125
|
/**
|
|
967
1126
|
* #getter
|
|
968
1127
|
* total height of track area (px)
|
|
@@ -982,11 +1141,14 @@ function stateModelFactory() {
|
|
|
982
1141
|
}
|
|
983
1142
|
return types
|
|
984
1143
|
},
|
|
1144
|
+
/**
|
|
1145
|
+
* #getter
|
|
1146
|
+
*/
|
|
985
1147
|
get tidyAnnotations() {
|
|
986
1148
|
const ret = []
|
|
987
|
-
const {
|
|
988
|
-
if (
|
|
989
|
-
for (const [id, val] of Object.entries(
|
|
1149
|
+
const { interProAnnotations } = self
|
|
1150
|
+
if (interProAnnotations) {
|
|
1151
|
+
for (const [id, val] of Object.entries(interProAnnotations)) {
|
|
990
1152
|
for (const { signature, locations } of val.matches) {
|
|
991
1153
|
const { entry } = signature
|
|
992
1154
|
if (entry) {
|
|
@@ -1023,6 +1185,23 @@ function stateModelFactory() {
|
|
|
1023
1185
|
},
|
|
1024
1186
|
}))
|
|
1025
1187
|
.views(self => ({
|
|
1188
|
+
/**
|
|
1189
|
+
* #getter
|
|
1190
|
+
*/
|
|
1191
|
+
get showVerticalScrollbar() {
|
|
1192
|
+
return self.msaAreaHeight < self.totalHeight
|
|
1193
|
+
},
|
|
1194
|
+
}))
|
|
1195
|
+
.views(self => ({
|
|
1196
|
+
/**
|
|
1197
|
+
* #getter
|
|
1198
|
+
*/
|
|
1199
|
+
get verticalScrollbarWidth() {
|
|
1200
|
+
return self.showVerticalScrollbar ? 20 : 0
|
|
1201
|
+
},
|
|
1202
|
+
/**
|
|
1203
|
+
* #getter
|
|
1204
|
+
*/
|
|
1026
1205
|
get fillPalette() {
|
|
1027
1206
|
const arr = [...self.tidyTypes.keys()]
|
|
1028
1207
|
let i = 0
|
|
@@ -1034,6 +1213,9 @@ function stateModelFactory() {
|
|
|
1034
1213
|
}
|
|
1035
1214
|
return map
|
|
1036
1215
|
},
|
|
1216
|
+
/**
|
|
1217
|
+
* #getter
|
|
1218
|
+
*/
|
|
1037
1219
|
get strokePalette() {
|
|
1038
1220
|
return Object.fromEntries(
|
|
1039
1221
|
Object.entries(this.fillPalette).map(([key, val]) => [
|
|
@@ -1044,18 +1226,23 @@ function stateModelFactory() {
|
|
|
1044
1226
|
},
|
|
1045
1227
|
}))
|
|
1046
1228
|
.actions(self => ({
|
|
1229
|
+
/**
|
|
1230
|
+
* #action
|
|
1231
|
+
*/
|
|
1232
|
+
setHeaderHeight(arg: number) {
|
|
1233
|
+
self.headerHeight = arg
|
|
1234
|
+
},
|
|
1047
1235
|
/**
|
|
1048
1236
|
* #action
|
|
1049
1237
|
*/
|
|
1050
1238
|
reset() {
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
})
|
|
1239
|
+
self.setData({ tree: '', msa: '' })
|
|
1240
|
+
self.setError(undefined)
|
|
1241
|
+
self.setScrollY(0)
|
|
1242
|
+
self.setScrollX(0)
|
|
1243
|
+
self.setCurrentAlignment(0)
|
|
1244
|
+
self.setTreeFilehandle(undefined)
|
|
1245
|
+
self.setMSAFilehandle(undefined)
|
|
1059
1246
|
},
|
|
1060
1247
|
/**
|
|
1061
1248
|
* #action
|
|
@@ -1154,9 +1341,11 @@ function stateModelFactory() {
|
|
|
1154
1341
|
if (msaFilehandle) {
|
|
1155
1342
|
try {
|
|
1156
1343
|
self.setLoadingMSA(true)
|
|
1157
|
-
const res = await openLocation(msaFilehandle).readFile(
|
|
1344
|
+
const res = await openLocation(msaFilehandle).readFile()
|
|
1345
|
+
const buf = isGzip(res) ? ungzip(res) : res
|
|
1346
|
+
const txt = new TextDecoder('utf8').decode(buf)
|
|
1158
1347
|
transaction(() => {
|
|
1159
|
-
self.setMSA(
|
|
1348
|
+
self.setMSA(txt)
|
|
1160
1349
|
if (msaFilehandle.locationType === 'BlobLocation') {
|
|
1161
1350
|
// clear filehandle after loading if from a local file
|
|
1162
1351
|
self.setMSAFilehandle(undefined)
|
|
@@ -1172,6 +1361,17 @@ function stateModelFactory() {
|
|
|
1172
1361
|
}),
|
|
1173
1362
|
)
|
|
1174
1363
|
|
|
1364
|
+
addDisposer(
|
|
1365
|
+
self,
|
|
1366
|
+
autorun(() => {
|
|
1367
|
+
// force colStats not to go stale,
|
|
1368
|
+
// xref solution https://github.com/mobxjs/mobx/issues/266#issuecomment-222007278
|
|
1369
|
+
// xref problem https://github.com/GMOD/react-msaview/issues/75
|
|
1370
|
+
self.colStats
|
|
1371
|
+
self.colStatsSums
|
|
1372
|
+
self.columns
|
|
1373
|
+
}),
|
|
1374
|
+
)
|
|
1175
1375
|
// autorun synchronizes treeWidth with treeAreaWidth
|
|
1176
1376
|
addDisposer(
|
|
1177
1377
|
self,
|
package/src/parseNewick.ts
CHANGED
package/src/parsers/FastaMSA.ts
CHANGED
package/src/renderToSvg.tsx
CHANGED
|
@@ -2,10 +2,10 @@ import React from 'react'
|
|
|
2
2
|
import { createRoot } from 'react-dom/client'
|
|
3
3
|
import { when } from 'mobx'
|
|
4
4
|
import { renderToStaticMarkup } from '@jbrowse/core/util'
|
|
5
|
-
import { Theme } from '@mui/material'
|
|
5
|
+
import type { Theme } from '@mui/material'
|
|
6
6
|
|
|
7
7
|
// locals
|
|
8
|
-
import { MsaViewModel } from './model'
|
|
8
|
+
import type { MsaViewModel } from './model'
|
|
9
9
|
import { renderTreeCanvas } from './components/tree/renderTreeCanvas'
|
|
10
10
|
import { renderMSABlock } from './components/msa/renderMSABlock'
|
|
11
11
|
import { colorContrast } from './util'
|
|
@@ -17,7 +17,7 @@ export async function renderToSvg(
|
|
|
17
17
|
model: MsaViewModel,
|
|
18
18
|
opts: { theme: Theme; includeMinimap?: boolean; exportType: string },
|
|
19
19
|
) {
|
|
20
|
-
await when(() => !!model.
|
|
20
|
+
await when(() => !!model.dataInitialized)
|
|
21
21
|
const { width, height, scrollX, scrollY } = model
|
|
22
22
|
const { exportType, theme, includeMinimap } = opts
|
|
23
23
|
|
|
@@ -31,7 +31,8 @@ export async function renderToSvg(
|
|
|
31
31
|
offsetX: 0,
|
|
32
32
|
includeMinimap,
|
|
33
33
|
})
|
|
34
|
-
}
|
|
34
|
+
}
|
|
35
|
+
if (exportType === 'viewport') {
|
|
35
36
|
return render({
|
|
36
37
|
width,
|
|
37
38
|
height,
|
|
@@ -41,9 +42,8 @@ export async function renderToSvg(
|
|
|
41
42
|
offsetX: -scrollX,
|
|
42
43
|
includeMinimap,
|
|
43
44
|
})
|
|
44
|
-
} else {
|
|
45
|
-
throw new Error('unknown export type')
|
|
46
45
|
}
|
|
46
|
+
throw new Error('unknown export type')
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
async function render({
|
package/src/reparseTree.ts
CHANGED