react-msaview 3.2.0 → 3.2.2
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 +13 -13
- package/dist/colorSchemes.js +2 -2
- package/dist/colorSchemes.js.map +1 -1
- package/dist/components/Loading.js +3 -1
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/ResizeHandles.js +6 -2
- package/dist/components/ResizeHandles.js.map +1 -1
- package/dist/components/SequenceTextArea.js +9 -3
- package/dist/components/SequenceTextArea.js.map +1 -1
- package/dist/components/TextTrack.js +1 -1
- package/dist/components/TextTrack.js.map +1 -1
- package/dist/components/Track.js +6 -2
- package/dist/components/Track.js.map +1 -1
- package/dist/components/VerticalScrollbar.js +5 -1
- package/dist/components/VerticalScrollbar.js.map +1 -1
- package/dist/components/dialogs/AboutDialog.js +3 -1
- package/dist/components/dialogs/AboutDialog.js.map +1 -1
- package/dist/components/dialogs/AddTrackDialog.d.ts +2 -2
- package/dist/components/dialogs/AddTrackDialog.js +8 -3
- package/dist/components/dialogs/AddTrackDialog.js.map +1 -1
- package/dist/components/dialogs/DomainDialog.js +6 -2
- package/dist/components/dialogs/DomainDialog.js.map +1 -1
- package/dist/components/dialogs/ExportSVGDialog.js +29 -17
- package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
- package/dist/components/dialogs/FeatureDialog.js +8 -4
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/InterProScanDialog.js +23 -9
- package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
- package/dist/components/dialogs/MetadataDialog.js +3 -1
- package/dist/components/dialogs/MetadataDialog.js.map +1 -1
- package/dist/components/dialogs/SettingsDialog.js +61 -23
- package/dist/components/dialogs/SettingsDialog.js.map +1 -1
- package/dist/components/dialogs/TracklistDialog.d.ts +2 -2
- package/dist/components/dialogs/TracklistDialog.js +8 -3
- package/dist/components/dialogs/TracklistDialog.js.map +1 -1
- package/dist/components/dialogs/UserProvidedDomainsDialog.js +10 -4
- package/dist/components/dialogs/UserProvidedDomainsDialog.js.map +1 -1
- package/dist/components/header/Header.js +3 -1
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/HeaderInfoArea.js +5 -2
- package/dist/components/header/HeaderInfoArea.js.map +1 -1
- package/dist/components/header/HeaderMenu.js +12 -4
- package/dist/components/header/HeaderMenu.js.map +1 -1
- package/dist/components/header/HeaderMenuExtra.js +34 -16
- package/dist/components/header/HeaderMenuExtra.js.map +1 -1
- package/dist/components/header/ZoomControls.js +18 -6
- package/dist/components/header/ZoomControls.js.map +1 -1
- package/dist/components/import/ImportForm.d.ts +2 -2
- package/dist/components/import/ImportForm.js +15 -2
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/import/ImportFormExamples.js +44 -31
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/minimap/Minimap.js +12 -4
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +5 -3
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.d.ts +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +2 -2
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderMSABlock.js +28 -24
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.js +3 -3
- package/dist/components/msa/renderMSAMouseover.js.map +1 -1
- package/dist/components/tree/TreeBranchMenu.js +6 -3
- package/dist/components/tree/TreeBranchMenu.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +11 -4
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/TreeNodeMenu.js +1 -1
- package/dist/components/tree/TreeNodeMenu.js.map +1 -1
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.d.ts +2 -2
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +7 -5
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
- package/dist/components/tree/renderTreeCanvas.js +5 -5
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/components/util.js +0 -3
- package/dist/components/util.js.map +1 -1
- package/dist/ggplotPalettes.js.map +1 -1
- package/dist/launchInterProScan.js +4 -4
- package/dist/launchInterProScan.js.map +1 -1
- package/dist/model/DialogQueue.d.ts +1 -1
- package/dist/model/DialogQueue.js +0 -1
- package/dist/model/DialogQueue.js.map +1 -1
- package/dist/model.d.ts +59 -25
- package/dist/model.js +123 -62
- package/dist/model.js.map +1 -1
- package/dist/parseGFF.js +8 -6
- package/dist/parseGFF.js.map +1 -1
- package/dist/parseNewick.d.ts +4 -4
- package/dist/parseNewick.js +7 -8
- package/dist/parseNewick.js.map +1 -1
- package/dist/parsers/ClustalMSA.d.ts +5 -5
- package/dist/parsers/ClustalMSA.js +2 -2
- package/dist/parsers/ClustalMSA.js.map +1 -1
- package/dist/parsers/EmfMSA.d.ts +27 -0
- package/dist/parsers/EmfMSA.js +53 -0
- package/dist/parsers/EmfMSA.js.map +1 -0
- package/dist/parsers/EmfTree.d.ts +5 -0
- package/dist/parsers/EmfTree.js +8 -0
- package/dist/parsers/EmfTree.js.map +1 -0
- package/dist/parsers/FastaMSA.js +5 -5
- package/dist/parsers/FastaMSA.js.map +1 -1
- package/dist/parsers/StockholmMSA.d.ts +6 -6
- package/dist/parsers/StockholmMSA.js +6 -6
- package/dist/parsers/StockholmMSA.js.map +1 -1
- package/dist/renderToSvg.js +3 -6
- package/dist/renderToSvg.js.map +1 -1
- package/dist/reparseTree.js +2 -2
- package/dist/reparseTree.js.map +1 -1
- package/dist/rowCoordinateCalculations.d.ts +2 -0
- package/dist/rowCoordinateCalculations.js +26 -0
- package/dist/rowCoordinateCalculations.js.map +1 -0
- package/dist/rowCoordinateCalculations.test.d.ts +1 -0
- package/dist/rowCoordinateCalculations.test.js +18 -0
- package/dist/rowCoordinateCalculations.test.js.map +1 -0
- package/dist/util.d.ts +3 -3
- package/dist/util.js +1 -1
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -3
- package/src/colorSchemes.ts +4 -4
- package/src/components/Loading.tsx +7 -1
- package/src/components/ResizeHandles.tsx +6 -2
- package/src/components/SequenceTextArea.tsx +10 -4
- package/src/components/TextTrack.tsx +2 -2
- package/src/components/Track.tsx +8 -4
- package/src/components/VerticalScrollbar.tsx +6 -2
- package/src/components/dialogs/AboutDialog.tsx +7 -1
- package/src/components/dialogs/AddTrackDialog.tsx +13 -3
- package/src/components/dialogs/DomainDialog.tsx +9 -2
- package/src/components/dialogs/ExportSVGDialog.tsx +36 -17
- package/src/components/dialogs/FeatureDialog.tsx +7 -5
- package/src/components/dialogs/InterProScanDialog.tsx +20 -10
- package/src/components/dialogs/MetadataDialog.tsx +8 -1
- package/src/components/dialogs/SettingsDialog.tsx +76 -32
- package/src/components/dialogs/TracklistDialog.tsx +17 -3
- package/src/components/dialogs/UserProvidedDomainsDialog.tsx +11 -5
- package/src/components/header/Header.tsx +3 -1
- package/src/components/header/HeaderInfoArea.tsx +3 -2
- package/src/components/header/HeaderMenu.tsx +12 -7
- package/src/components/header/HeaderMenuExtra.tsx +28 -16
- package/src/components/header/ZoomControls.tsx +22 -6
- package/src/components/import/ImportForm.tsx +14 -2
- package/src/components/import/ImportFormExamples.tsx +59 -48
- package/src/components/minimap/Minimap.tsx +21 -9
- package/src/components/msa/MSACanvasBlock.tsx +5 -3
- package/src/components/msa/MSAMouseoverCanvas.tsx +5 -1
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +4 -4
- package/src/components/msa/renderMSABlock.ts +42 -38
- package/src/components/msa/renderMSAMouseover.ts +3 -3
- package/src/components/tree/TreeBranchMenu.tsx +5 -3
- package/src/components/tree/TreeCanvasBlock.tsx +11 -4
- package/src/components/tree/TreeNodeMenu.tsx +1 -1
- package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +17 -4
- package/src/components/tree/renderTreeCanvas.ts +2 -2
- package/src/components/util.ts +1 -4
- package/src/ggplotPalettes.ts +1 -1
- package/src/launchInterProScan.ts +5 -5
- package/src/model/DialogQueue.ts +0 -1
- package/src/model.ts +136 -74
- package/src/parseGFF.ts +13 -11
- package/src/parseNewick.ts +10 -10
- package/src/parsers/ClustalMSA.ts +4 -4
- package/src/parsers/EmfMSA.ts +66 -0
- package/src/parsers/EmfTree.ts +9 -0
- package/src/parsers/FastaMSA.ts +6 -6
- package/src/parsers/StockholmMSA.ts +12 -12
- package/src/renderToSvg.tsx +1 -2
- package/src/reparseTree.ts +3 -3
- package/src/rowCoordinateCalculations.test.ts +19 -0
- package/src/rowCoordinateCalculations.ts +26 -0
- package/src/util.ts +5 -5
- package/src/version.ts +1 -1
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import type { MsaViewModel } from '../../../model'
|
|
12
12
|
import SequenceTextArea from '../../SequenceTextArea'
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const TreeNodeInfoDialog = observer(function ({
|
|
15
15
|
info,
|
|
16
16
|
model,
|
|
17
17
|
nodeName,
|
|
@@ -24,15 +24,26 @@ export default observer(function ({
|
|
|
24
24
|
}) {
|
|
25
25
|
const { treeMetadata, rows } = model
|
|
26
26
|
const metadata = treeMetadata[nodeName]
|
|
27
|
-
const
|
|
27
|
+
const res = rows.find(f => f[0] === nodeName)
|
|
28
28
|
return (
|
|
29
|
-
<Dialog
|
|
29
|
+
<Dialog
|
|
30
|
+
onClose={() => {
|
|
31
|
+
onClose()
|
|
32
|
+
}}
|
|
33
|
+
open
|
|
34
|
+
title="Tree node info"
|
|
35
|
+
maxWidth="xl"
|
|
36
|
+
>
|
|
30
37
|
<DialogContent>
|
|
31
38
|
<BaseCard title="Attributes">
|
|
32
39
|
<Attributes attributes={{ nodeName, ...info }} />
|
|
33
40
|
</BaseCard>
|
|
34
41
|
<BaseCard title="Sequence">
|
|
35
|
-
|
|
42
|
+
{res ? (
|
|
43
|
+
<SequenceTextArea str={[res]} />
|
|
44
|
+
) : (
|
|
45
|
+
<div>Sequence not found</div>
|
|
46
|
+
)}
|
|
36
47
|
</BaseCard>
|
|
37
48
|
{metadata ? (
|
|
38
49
|
<BaseCard title="Extra metadata">
|
|
@@ -43,3 +54,5 @@ export default observer(function ({
|
|
|
43
54
|
</Dialog>
|
|
44
55
|
)
|
|
45
56
|
})
|
|
57
|
+
|
|
58
|
+
export default TreeNodeInfoDialog
|
|
@@ -147,8 +147,6 @@ export function renderTreeLabels({
|
|
|
147
147
|
marginLeft,
|
|
148
148
|
leaves,
|
|
149
149
|
noTree,
|
|
150
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
151
|
-
rowHeight: _rowHeight, // this is needed for redrawing after zoom change
|
|
152
150
|
} = model
|
|
153
151
|
const by = blockSizeYOverride || blockSize
|
|
154
152
|
if (labelsAlignRight) {
|
|
@@ -250,6 +248,8 @@ export function renderTreeCanvas({
|
|
|
250
248
|
showTreeText,
|
|
251
249
|
marginLeft,
|
|
252
250
|
nref,
|
|
251
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
252
|
+
rowHeight: _rowHeight, // this is needed for redrawing after zoom change
|
|
253
253
|
} = model
|
|
254
254
|
const by = blockSizeYOverride || blockSize
|
|
255
255
|
|
package/src/components/util.ts
CHANGED
|
@@ -11,7 +11,7 @@ export function chooseGridPitch(
|
|
|
11
11
|
scale = Math.abs(scale)
|
|
12
12
|
const minMajorPitchBp = minMajorPitchPx * scale
|
|
13
13
|
const majorMagnitude = Number.parseInt(
|
|
14
|
-
Number(minMajorPitchBp).toExponential().split(/e/i)[1]
|
|
14
|
+
Number(minMajorPitchBp).toExponential().split(/e/i)[1]!,
|
|
15
15
|
10,
|
|
16
16
|
)
|
|
17
17
|
|
|
@@ -50,9 +50,6 @@ export function makeTicks(
|
|
|
50
50
|
|
|
51
51
|
let minBase = start
|
|
52
52
|
let maxBase = end
|
|
53
|
-
if (minBase === null || maxBase === null) {
|
|
54
|
-
return []
|
|
55
|
-
}
|
|
56
53
|
|
|
57
54
|
if (bpPerPx < 0) {
|
|
58
55
|
;[minBase, maxBase] = [maxBase, minBase]
|
package/src/ggplotPalettes.ts
CHANGED
|
@@ -38,7 +38,7 @@ async function runInterProScan({
|
|
|
38
38
|
method: 'POST',
|
|
39
39
|
body: new URLSearchParams({
|
|
40
40
|
email: 'colin.diesh@gmail.com',
|
|
41
|
-
sequence:
|
|
41
|
+
sequence: seq,
|
|
42
42
|
programs: programs.join(','),
|
|
43
43
|
}),
|
|
44
44
|
})
|
|
@@ -47,7 +47,7 @@ async function runInterProScan({
|
|
|
47
47
|
jobId,
|
|
48
48
|
onProgress,
|
|
49
49
|
})
|
|
50
|
-
|
|
50
|
+
await loadInterProScanResultsWithStatus({ jobId, model })
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export function loadInterProScanResults(jobId: string) {
|
|
@@ -65,6 +65,7 @@ async function wait({
|
|
|
65
65
|
}) {
|
|
66
66
|
const url = `${base}/iprscan5/status/${jobId}`
|
|
67
67
|
try {
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
68
69
|
while (true) {
|
|
69
70
|
for (let i = 0; i < 10; i++) {
|
|
70
71
|
await timeout(1000)
|
|
@@ -101,14 +102,13 @@ export async function launchInterProScan({
|
|
|
101
102
|
try {
|
|
102
103
|
onProgress({ msg: `Launching ${algorithm} MSA` })
|
|
103
104
|
if (algorithm === 'interproscan') {
|
|
104
|
-
|
|
105
|
+
await runInterProScan({
|
|
105
106
|
seq,
|
|
106
107
|
onJobId,
|
|
107
108
|
onProgress,
|
|
108
109
|
programs,
|
|
109
110
|
model,
|
|
110
111
|
})
|
|
111
|
-
return result
|
|
112
112
|
}
|
|
113
113
|
throw new Error('unknown algorithm')
|
|
114
114
|
} finally {
|
|
@@ -130,7 +130,7 @@ export async function loadInterProScanResultsWithStatus({
|
|
|
130
130
|
})
|
|
131
131
|
const ret = await loadInterProScanResults(jobId)
|
|
132
132
|
model.setInterProAnnotations(
|
|
133
|
-
Object.fromEntries(ret.results.map(r => [r.xref[0]
|
|
133
|
+
Object.fromEntries(ret.results.map(r => [r.xref[0]!.id, r])),
|
|
134
134
|
)
|
|
135
135
|
model.setShowDomains(true)
|
|
136
136
|
getSession(model).notify(`Loaded interproscan ${jobId} results`, 'success')
|
package/src/model/DialogQueue.ts
CHANGED
|
@@ -8,7 +8,6 @@ export function DialogQueueSessionMixin() {
|
|
|
8
8
|
return types
|
|
9
9
|
.model('DialogQueueSessionMixin', {})
|
|
10
10
|
.volatile(() => ({
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
11
|
queueOfDialogs: [] as [DialogComponentType, any][],
|
|
13
12
|
}))
|
|
14
13
|
.views(self => ({
|
package/src/model.ts
CHANGED
|
@@ -42,6 +42,7 @@ import TextTrack from './components/TextTrack'
|
|
|
42
42
|
|
|
43
43
|
// parsers
|
|
44
44
|
import ClustalMSA from './parsers/ClustalMSA'
|
|
45
|
+
import EmfMSA from './parsers/EmfMSA'
|
|
45
46
|
import StockholmMSA from './parsers/StockholmMSA'
|
|
46
47
|
import FastaMSA from './parsers/FastaMSA'
|
|
47
48
|
import parseNewick from './parseNewick'
|
|
@@ -53,6 +54,11 @@ import { DialogQueueSessionMixin } from './model/DialogQueue'
|
|
|
53
54
|
import { TreeF } from './model/treeModel'
|
|
54
55
|
import { MSAModelF } from './model/msaModel'
|
|
55
56
|
import type { InterProScanResults } from './launchInterProScan'
|
|
57
|
+
import {
|
|
58
|
+
mouseOverCoordToGlobalCoord,
|
|
59
|
+
globalCoordToRowSpecificCoord,
|
|
60
|
+
} from './rowCoordinateCalculations'
|
|
61
|
+
import EmfTree from './parsers/EmfTree'
|
|
56
62
|
|
|
57
63
|
export interface Accession {
|
|
58
64
|
accession: string
|
|
@@ -72,7 +78,6 @@ export interface TextTrackModel extends BasicTrackModel {
|
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
export interface ITextTrack {
|
|
75
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
81
|
ReactComponent: React.FC<any>
|
|
77
82
|
model: TextTrackModel
|
|
78
83
|
}
|
|
@@ -147,7 +152,7 @@ function stateModelFactory() {
|
|
|
147
152
|
* #property
|
|
148
153
|
* height of each row, px
|
|
149
154
|
*/
|
|
150
|
-
rowHeight:
|
|
155
|
+
rowHeight: 18,
|
|
151
156
|
|
|
152
157
|
/**
|
|
153
158
|
* #property
|
|
@@ -165,7 +170,7 @@ function stateModelFactory() {
|
|
|
165
170
|
* #property
|
|
166
171
|
* width of columns, px
|
|
167
172
|
*/
|
|
168
|
-
colWidth:
|
|
173
|
+
colWidth: 14,
|
|
169
174
|
|
|
170
175
|
/**
|
|
171
176
|
* #property
|
|
@@ -221,7 +226,11 @@ function stateModelFactory() {
|
|
|
221
226
|
* data from the loaded tree/msa/treeMetadata, generally loaded by
|
|
222
227
|
* autorun
|
|
223
228
|
*/
|
|
224
|
-
data: types.optional(DataModelF(), {
|
|
229
|
+
data: types.optional(DataModelF(), {
|
|
230
|
+
tree: '',
|
|
231
|
+
msa: '',
|
|
232
|
+
treeMetadata: '',
|
|
233
|
+
}),
|
|
225
234
|
|
|
226
235
|
/**
|
|
227
236
|
* #property
|
|
@@ -473,7 +482,7 @@ function stateModelFactory() {
|
|
|
473
482
|
/**
|
|
474
483
|
* #action
|
|
475
484
|
*/
|
|
476
|
-
setData(data: { msa?: string; tree?: string }) {
|
|
485
|
+
setData(data: { msa?: string; tree?: string; treeMetadata?: string }) {
|
|
477
486
|
self.data = cast(data)
|
|
478
487
|
},
|
|
479
488
|
|
|
@@ -514,6 +523,12 @@ function stateModelFactory() {
|
|
|
514
523
|
}))
|
|
515
524
|
|
|
516
525
|
.views(self => ({
|
|
526
|
+
/**
|
|
527
|
+
* #getter
|
|
528
|
+
*/
|
|
529
|
+
get realAllowedGappyness() {
|
|
530
|
+
return self.hideGaps ? self.allowedGappyness : 100
|
|
531
|
+
},
|
|
517
532
|
/**
|
|
518
533
|
* #getter
|
|
519
534
|
*/
|
|
@@ -548,7 +563,7 @@ function stateModelFactory() {
|
|
|
548
563
|
* #getter
|
|
549
564
|
*/
|
|
550
565
|
get colorScheme() {
|
|
551
|
-
return colorSchemes[self.colorSchemeName]
|
|
566
|
+
return colorSchemes[self.colorSchemeName]!
|
|
552
567
|
},
|
|
553
568
|
|
|
554
569
|
/**
|
|
@@ -588,7 +603,7 @@ function stateModelFactory() {
|
|
|
588
603
|
/**
|
|
589
604
|
* #getter
|
|
590
605
|
*/
|
|
591
|
-
|
|
606
|
+
menuItems() {
|
|
592
607
|
return []
|
|
593
608
|
},
|
|
594
609
|
/**
|
|
@@ -605,11 +620,13 @@ function stateModelFactory() {
|
|
|
605
620
|
if (text) {
|
|
606
621
|
if (Stockholm.sniff(text)) {
|
|
607
622
|
return new StockholmMSA(text, self.currentAlignment)
|
|
608
|
-
}
|
|
609
|
-
if (text.startsWith('>')) {
|
|
623
|
+
} else if (text.startsWith('>')) {
|
|
610
624
|
return new FastaMSA(text)
|
|
625
|
+
} else if (text.startsWith('SEQ')) {
|
|
626
|
+
return new EmfMSA(text)
|
|
627
|
+
} else {
|
|
628
|
+
return new ClustalMSA(text)
|
|
611
629
|
}
|
|
612
|
-
return new ClustalMSA(text)
|
|
613
630
|
}
|
|
614
631
|
return null
|
|
615
632
|
},
|
|
@@ -624,14 +641,25 @@ function stateModelFactory() {
|
|
|
624
641
|
* #getter
|
|
625
642
|
*/
|
|
626
643
|
get tree(): NodeWithIds {
|
|
627
|
-
const
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
644
|
+
const text = self.data.tree
|
|
645
|
+
let ret: NodeWithIds
|
|
646
|
+
if (text) {
|
|
647
|
+
let t: string
|
|
648
|
+
if (text.startsWith('SEQ')) {
|
|
649
|
+
const r = new EmfTree(text)
|
|
650
|
+
t = r.data.tree
|
|
651
|
+
} else {
|
|
652
|
+
t = text
|
|
653
|
+
}
|
|
654
|
+
ret = generateNodeIds(parseNewick(t))
|
|
655
|
+
} else {
|
|
656
|
+
ret = this.MSA?.getTree() || {
|
|
657
|
+
noTree: true,
|
|
658
|
+
children: [],
|
|
659
|
+
id: 'empty',
|
|
660
|
+
name: 'empty',
|
|
661
|
+
}
|
|
662
|
+
}
|
|
635
663
|
return reparseTree(ret)
|
|
636
664
|
},
|
|
637
665
|
/**
|
|
@@ -652,8 +680,10 @@ function stateModelFactory() {
|
|
|
652
680
|
* #getter
|
|
653
681
|
*/
|
|
654
682
|
get root() {
|
|
655
|
-
let hier = hierarchy(this.tree, d => d.
|
|
656
|
-
|
|
683
|
+
let hier = hierarchy(this.tree, d => d.children)
|
|
684
|
+
// todo: investigate whether needed, typescript says children always true
|
|
685
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
686
|
+
.sum(d => (d.children ? 0 : 1))
|
|
657
687
|
.sort((a, b) => ascending(a.data.length || 1, b.data.length || 1))
|
|
658
688
|
|
|
659
689
|
if (self.showOnly) {
|
|
@@ -666,7 +696,9 @@ function stateModelFactory() {
|
|
|
666
696
|
;[...self.collapsed, ...self.collapsedLeaves]
|
|
667
697
|
.map(collapsedId => hier.find(node => node.data.id === collapsedId))
|
|
668
698
|
.filter(notEmpty)
|
|
669
|
-
.map(node =>
|
|
699
|
+
.map(node => {
|
|
700
|
+
collapse(node)
|
|
701
|
+
})
|
|
670
702
|
|
|
671
703
|
return hier
|
|
672
704
|
},
|
|
@@ -689,25 +721,34 @@ function stateModelFactory() {
|
|
|
689
721
|
* #getter
|
|
690
722
|
*/
|
|
691
723
|
get blanks() {
|
|
692
|
-
const {
|
|
724
|
+
const { hideGaps, realAllowedGappyness } = self
|
|
693
725
|
const blanks = []
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
726
|
+
if (hideGaps) {
|
|
727
|
+
const strs = this.leaves
|
|
728
|
+
.map(leaf => this.MSA?.getRow(leaf.data.name))
|
|
729
|
+
.filter((item): item is string => !!item)
|
|
730
|
+
if (strs.length) {
|
|
731
|
+
for (let i = 0; i < strs[0]!.length; i++) {
|
|
732
|
+
let counter = 0
|
|
733
|
+
for (const str of strs) {
|
|
734
|
+
if (str[i] === '-') {
|
|
735
|
+
counter++
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
if (counter / strs.length >= realAllowedGappyness / 100) {
|
|
739
|
+
blanks.push(i)
|
|
740
|
+
}
|
|
703
741
|
}
|
|
704
742
|
}
|
|
705
|
-
if (counter / strs.length >= allowedGappyness / 100) {
|
|
706
|
-
blanks.push(i)
|
|
707
|
-
}
|
|
708
743
|
}
|
|
709
744
|
return blanks
|
|
710
745
|
},
|
|
746
|
+
/**
|
|
747
|
+
* #getter
|
|
748
|
+
*/
|
|
749
|
+
get blanksSet() {
|
|
750
|
+
return new Set(this.blanks)
|
|
751
|
+
},
|
|
711
752
|
/**
|
|
712
753
|
* #getter
|
|
713
754
|
*/
|
|
@@ -717,13 +758,20 @@ function stateModelFactory() {
|
|
|
717
758
|
.map(leaf => [leaf.data.name, MSA?.getRow(leaf.data.name)] as const)
|
|
718
759
|
.filter((f): f is [string, string] => !!f[1])
|
|
719
760
|
},
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* #getter
|
|
764
|
+
*/
|
|
765
|
+
get rowMap() {
|
|
766
|
+
return new Map(this.rows)
|
|
767
|
+
},
|
|
720
768
|
/**
|
|
721
769
|
* #getter
|
|
722
770
|
*/
|
|
723
771
|
get columns() {
|
|
724
772
|
return Object.fromEntries(
|
|
725
773
|
this.rows.map(
|
|
726
|
-
(row, index) => [row[0], this.columns2d[index]] as const,
|
|
774
|
+
(row, index) => [row[0], this.columns2d[index]!] as const,
|
|
727
775
|
),
|
|
728
776
|
)
|
|
729
777
|
},
|
|
@@ -737,7 +785,7 @@ function stateModelFactory() {
|
|
|
737
785
|
* #getter
|
|
738
786
|
*/
|
|
739
787
|
get fontSize() {
|
|
740
|
-
return Math.min(Math.max(6, self.rowHeight -
|
|
788
|
+
return Math.min(Math.max(6, self.rowHeight - 3), 18)
|
|
741
789
|
},
|
|
742
790
|
/**
|
|
743
791
|
* #getter
|
|
@@ -748,10 +796,11 @@ function stateModelFactory() {
|
|
|
748
796
|
for (const column of columns) {
|
|
749
797
|
for (let j = 0; j < column.length; j++) {
|
|
750
798
|
const l = r[j] || {}
|
|
751
|
-
|
|
752
|
-
|
|
799
|
+
const cj = column[j]!
|
|
800
|
+
if (!l[cj]) {
|
|
801
|
+
l[cj] = 0
|
|
753
802
|
}
|
|
754
|
-
l[
|
|
803
|
+
l[cj]++
|
|
755
804
|
r[j] = l
|
|
756
805
|
}
|
|
757
806
|
}
|
|
@@ -843,7 +892,7 @@ function stateModelFactory() {
|
|
|
843
892
|
const ret = []
|
|
844
893
|
for (const by of self.blocksY) {
|
|
845
894
|
for (const bx of self.blocksX) {
|
|
846
|
-
ret.push([bx, by])
|
|
895
|
+
ret.push([bx, by] as const)
|
|
847
896
|
}
|
|
848
897
|
}
|
|
849
898
|
return ret
|
|
@@ -1013,7 +1062,7 @@ function stateModelFactory() {
|
|
|
1013
1062
|
*/
|
|
1014
1063
|
get conservation() {
|
|
1015
1064
|
if (self.columns2d.length) {
|
|
1016
|
-
for (let i = 0; i < self.columns2d[0]
|
|
1065
|
+
for (let i = 0; i < self.columns2d[0]!.length; i++) {
|
|
1017
1066
|
const col = []
|
|
1018
1067
|
for (const column of self.columns2d) {
|
|
1019
1068
|
col.push(column[i])
|
|
@@ -1060,28 +1109,39 @@ function stateModelFactory() {
|
|
|
1060
1109
|
return self.msaAreaWidth < self.totalWidth
|
|
1061
1110
|
},
|
|
1062
1111
|
|
|
1112
|
+
/**
|
|
1113
|
+
* #getter
|
|
1114
|
+
*/
|
|
1115
|
+
get rowNamesSet() {
|
|
1116
|
+
return new Map(self.rowNames.map((r, idx) => [r, idx]))
|
|
1117
|
+
},
|
|
1118
|
+
|
|
1063
1119
|
/**
|
|
1064
1120
|
* #method
|
|
1065
|
-
* return a row-specific
|
|
1066
|
-
* coordinate
|
|
1121
|
+
* return a row-specific letter, or undefined if gap
|
|
1067
1122
|
*/
|
|
1068
|
-
|
|
1069
|
-
const {
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1123
|
+
mouseOverCoordToRowLetter(rowName: string, position: number) {
|
|
1124
|
+
const { rowMap, blanks } = self
|
|
1125
|
+
return rowMap.get(rowName)?.[
|
|
1126
|
+
mouseOverCoordToGlobalCoord(blanks, position)
|
|
1127
|
+
]
|
|
1128
|
+
},
|
|
1073
1129
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1130
|
+
/**
|
|
1131
|
+
* #method
|
|
1132
|
+
* return a row-specific sequence coordinate, skipping gaps, given a
|
|
1133
|
+
* global coordinate
|
|
1134
|
+
*/
|
|
1135
|
+
mouseOverCoordToGapRemovedRowCoord(rowName: string, position: number) {
|
|
1136
|
+
const { rowMap, blanks } = self
|
|
1137
|
+
const seq = rowMap.get(rowName)
|
|
1138
|
+
if (seq !== undefined) {
|
|
1139
|
+
const pos2 = mouseOverCoordToGlobalCoord(blanks, position)
|
|
1140
|
+
const pos1 = globalCoordToRowSpecificCoord(seq, pos2)
|
|
1141
|
+
return seq[pos1] === '-' || !seq[pos1] ? undefined : pos1
|
|
1142
|
+
} else {
|
|
1143
|
+
return undefined
|
|
1083
1144
|
}
|
|
1084
|
-
return 0
|
|
1085
1145
|
},
|
|
1086
1146
|
|
|
1087
1147
|
/**
|
|
@@ -1132,19 +1192,17 @@ function stateModelFactory() {
|
|
|
1132
1192
|
/**
|
|
1133
1193
|
* #getter
|
|
1134
1194
|
*/
|
|
1135
|
-
get
|
|
1195
|
+
get tidyInterProAnnotationTypes() {
|
|
1136
1196
|
const types = new Map<string, Accession>()
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
types.set(accession, { name, accession, description })
|
|
1140
|
-
}
|
|
1197
|
+
for (const annot of this.tidyInterProAnnotations) {
|
|
1198
|
+
types.set(annot.accession, annot)
|
|
1141
1199
|
}
|
|
1142
1200
|
return types
|
|
1143
1201
|
},
|
|
1144
1202
|
/**
|
|
1145
1203
|
* #getter
|
|
1146
1204
|
*/
|
|
1147
|
-
get
|
|
1205
|
+
get tidyInterProAnnotations() {
|
|
1148
1206
|
const ret = []
|
|
1149
1207
|
const { interProAnnotations } = self
|
|
1150
1208
|
if (interProAnnotations) {
|
|
@@ -1172,16 +1230,16 @@ function stateModelFactory() {
|
|
|
1172
1230
|
/**
|
|
1173
1231
|
* #getter
|
|
1174
1232
|
*/
|
|
1175
|
-
get
|
|
1176
|
-
return this.
|
|
1233
|
+
get tidyFilteredInterProAnnotations() {
|
|
1234
|
+
return this.tidyInterProAnnotations.filter(r =>
|
|
1177
1235
|
self.featureFilters.get(r.accession),
|
|
1178
1236
|
)
|
|
1179
1237
|
},
|
|
1180
1238
|
/**
|
|
1181
1239
|
* #getter
|
|
1182
1240
|
*/
|
|
1183
|
-
get
|
|
1184
|
-
return groupBy(this.
|
|
1241
|
+
get tidyFilteredGatheredInterProAnnotations() {
|
|
1242
|
+
return groupBy(this.tidyFilteredInterProAnnotations, r => r.id)
|
|
1185
1243
|
},
|
|
1186
1244
|
}))
|
|
1187
1245
|
.views(self => ({
|
|
@@ -1203,12 +1261,12 @@ function stateModelFactory() {
|
|
|
1203
1261
|
* #getter
|
|
1204
1262
|
*/
|
|
1205
1263
|
get fillPalette() {
|
|
1206
|
-
const arr = [...self.
|
|
1264
|
+
const arr = [...self.tidyInterProAnnotationTypes.keys()]
|
|
1207
1265
|
let i = 0
|
|
1208
1266
|
const map = {} as Record<string, string>
|
|
1209
1267
|
for (const key of arr) {
|
|
1210
1268
|
const k = Math.min(arr.length - 1, palettes.length - 1)
|
|
1211
|
-
map[key] = palettes[k][i]
|
|
1269
|
+
map[key] = palettes[k]![i]!
|
|
1212
1270
|
i++
|
|
1213
1271
|
}
|
|
1214
1272
|
return map
|
|
@@ -1285,7 +1343,7 @@ function stateModelFactory() {
|
|
|
1285
1343
|
addDisposer(
|
|
1286
1344
|
self,
|
|
1287
1345
|
autorun(() => {
|
|
1288
|
-
for (const key of self.
|
|
1346
|
+
for (const key of self.tidyInterProAnnotationTypes.keys()) {
|
|
1289
1347
|
this.initFilter(key)
|
|
1290
1348
|
}
|
|
1291
1349
|
}),
|
|
@@ -1361,17 +1419,21 @@ function stateModelFactory() {
|
|
|
1361
1419
|
}),
|
|
1362
1420
|
)
|
|
1363
1421
|
|
|
1422
|
+
// force colStats not to go stale
|
|
1423
|
+
// xref solution https://github.com/mobxjs/mobx/issues/266#issuecomment-222007278
|
|
1424
|
+
// xref problem https://github.com/GMOD/react-msaview/issues/75
|
|
1364
1425
|
addDisposer(
|
|
1365
1426
|
self,
|
|
1366
1427
|
autorun(() => {
|
|
1367
|
-
//
|
|
1368
|
-
// xref solution https://github.com/mobxjs/mobx/issues/266#issuecomment-222007278
|
|
1369
|
-
// xref problem https://github.com/GMOD/react-msaview/issues/75
|
|
1428
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
1370
1429
|
self.colStats
|
|
1430
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
1371
1431
|
self.colStatsSums
|
|
1432
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
1372
1433
|
self.columns
|
|
1373
1434
|
}),
|
|
1374
1435
|
)
|
|
1436
|
+
|
|
1375
1437
|
// autorun synchronizes treeWidth with treeAreaWidth
|
|
1376
1438
|
addDisposer(
|
|
1377
1439
|
self,
|
package/src/parseGFF.ts
CHANGED
|
@@ -8,23 +8,25 @@ export function parseGFF(str?: string) {
|
|
|
8
8
|
f.split('\t')
|
|
9
9
|
|
|
10
10
|
return {
|
|
11
|
-
seq_id
|
|
12
|
-
source
|
|
13
|
-
type
|
|
14
|
-
start: +start
|
|
15
|
-
end: +end
|
|
16
|
-
score: +score
|
|
17
|
-
strand
|
|
18
|
-
phase
|
|
11
|
+
seq_id: seq_id!,
|
|
12
|
+
source: source!,
|
|
13
|
+
type: type!,
|
|
14
|
+
start: +start!,
|
|
15
|
+
end: +end!,
|
|
16
|
+
score: +score!,
|
|
17
|
+
strand: strand!,
|
|
18
|
+
phase: phase!,
|
|
19
19
|
...Object.fromEntries(
|
|
20
|
-
col9
|
|
20
|
+
col9!
|
|
21
21
|
.split(';')
|
|
22
22
|
.map(f => f.trim())
|
|
23
23
|
.filter(f => !!f)
|
|
24
24
|
.map(f => f.split('='))
|
|
25
25
|
.map(([key, val]) => [
|
|
26
|
-
key
|
|
27
|
-
|
|
26
|
+
key!.trim(),
|
|
27
|
+
val
|
|
28
|
+
? decodeURIComponent(val).trim().split(',').join(' ')
|
|
29
|
+
: undefined,
|
|
28
30
|
]),
|
|
29
31
|
),
|
|
30
32
|
}
|
package/src/parseNewick.ts
CHANGED
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
* Converted to JSON:
|
|
35
35
|
* {
|
|
36
36
|
* name: "F",
|
|
37
|
-
*
|
|
37
|
+
* children: [
|
|
38
38
|
* {name: "A", length: 0.1},
|
|
39
39
|
* {name: "B", length: 0.2},
|
|
40
40
|
* {
|
|
41
41
|
* name: "E",
|
|
42
42
|
* length: 0.5,
|
|
43
|
-
*
|
|
43
|
+
* children: [
|
|
44
44
|
* {name: "C", length: 0.3},
|
|
45
45
|
* {name: "D", length: 0.4}
|
|
46
46
|
* ]
|
|
@@ -50,29 +50,29 @@
|
|
|
50
50
|
*
|
|
51
51
|
* Converted to JSON, but with no names or lengths:
|
|
52
52
|
* {
|
|
53
|
-
*
|
|
53
|
+
* children: [
|
|
54
54
|
* {}, {}, {
|
|
55
|
-
*
|
|
55
|
+
* children: [{}, {}]
|
|
56
56
|
* }
|
|
57
57
|
* ]
|
|
58
58
|
* }
|
|
59
59
|
*/
|
|
60
60
|
export default function parse(s: string) {
|
|
61
61
|
const ancestors = []
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
let tree = {} as Record<string, any>
|
|
64
64
|
const tokens = s.split(/\s*(;|\(|\)|,|:)\s*/)
|
|
65
65
|
for (let i = 0; i < tokens.length; i++) {
|
|
66
|
-
const token = tokens[i]
|
|
66
|
+
const token = tokens[i]!
|
|
67
67
|
const subtree = {}
|
|
68
68
|
switch (token) {
|
|
69
|
-
case '(': // new
|
|
70
|
-
tree.
|
|
69
|
+
case '(': // new children
|
|
70
|
+
tree.children = [subtree]
|
|
71
71
|
ancestors.push(tree)
|
|
72
72
|
tree = subtree
|
|
73
73
|
break
|
|
74
74
|
case ',': // another branch
|
|
75
|
-
ancestors.at(-1)?.
|
|
75
|
+
ancestors.at(-1)?.children.push(subtree)
|
|
76
76
|
tree = subtree
|
|
77
77
|
break
|
|
78
78
|
case ')': // optional name next
|
|
@@ -81,7 +81,7 @@ export default function parse(s: string) {
|
|
|
81
81
|
case ':': // optional length next
|
|
82
82
|
break
|
|
83
83
|
default: {
|
|
84
|
-
const x = tokens[i - 1]
|
|
84
|
+
const x = tokens[i - 1]!
|
|
85
85
|
if (x === ')' || x === '(' || x === ',') {
|
|
86
86
|
tree.name = token
|
|
87
87
|
} else if (x === ':') {
|