react-msaview 5.0.7 → 5.0.13
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 +25 -25
- package/bundle/index.js.map +1 -1
- package/dist/components/Checkbox2.js +3 -6
- package/dist/components/Checkbox2.js.map +1 -1
- package/dist/components/MSAViewer.d.ts +14 -0
- package/dist/components/MSAViewer.js +34 -0
- package/dist/components/MSAViewer.js.map +1 -0
- package/dist/components/Track.js +5 -24
- package/dist/components/Track.js.map +1 -1
- package/dist/components/dialogs/DomainDialog.js +2 -5
- package/dist/components/dialogs/DomainDialog.js.map +1 -1
- package/dist/components/dialogs/InterProScanDialog.js +7 -7
- package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
- package/dist/components/dialogs/SettingsDialog.js +3 -19
- package/dist/components/dialogs/SettingsDialog.js.map +1 -1
- package/dist/components/header/ColorSchemeMenu.d.ts +6 -0
- package/dist/components/header/ColorSchemeMenu.js +19 -0
- package/dist/components/header/ColorSchemeMenu.js.map +1 -0
- package/dist/components/header/{ZoomStar.d.ts → FileMenu.d.ts} +2 -2
- package/dist/components/header/FileMenu.js +71 -0
- package/dist/components/header/FileMenu.js.map +1 -0
- package/dist/components/header/Header.js +8 -6
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/HeaderMenu.js +3 -145
- package/dist/components/header/HeaderMenu.js.map +1 -1
- package/dist/components/header/MSASettingsMenu.d.ts +6 -0
- package/dist/components/header/MSASettingsMenu.js +36 -0
- package/dist/components/header/MSASettingsMenu.js.map +1 -0
- package/dist/components/header/SettingsMenu.js +1 -21
- package/dist/components/header/SettingsMenu.js.map +1 -1
- package/dist/components/header/TreeSettingsMenu.d.ts +6 -0
- package/dist/components/header/TreeSettingsMenu.js +74 -0
- package/dist/components/header/TreeSettingsMenu.js.map +1 -0
- package/dist/components/header/ZoomMenu.js +0 -8
- package/dist/components/header/ZoomMenu.js.map +1 -1
- package/dist/components/header/getDomainsMenu.d.ts +31 -0
- package/dist/components/header/getDomainsMenu.js +75 -0
- package/dist/components/header/getDomainsMenu.js.map +1 -0
- package/dist/components/import/ImportFormExamples.js +21 -19
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/msa/MSACanvas.js +13 -84
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +1 -3
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/renderMSABlock.js +2 -4
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.js +1 -7
- package/dist/components/msa/renderMSAMouseover.js.map +1 -1
- package/dist/components/tree/TreeCanvas.js +14 -91
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeNodeMenu.js +5 -16
- package/dist/components/tree/TreeNodeMenu.js.map +1 -1
- package/dist/components/tree/renderTreeCanvas.js +4 -12
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/constants.d.ts +0 -2
- package/dist/constants.js +0 -2
- package/dist/constants.js.map +1 -1
- package/dist/fetchUtils.d.ts +0 -1
- package/dist/fetchUtils.js +0 -4
- package/dist/fetchUtils.js.map +1 -1
- package/dist/flatToTree.d.ts +0 -5
- package/dist/flatToTree.js +13 -30
- package/dist/flatToTree.js.map +1 -1
- package/dist/hierarchy.d.ts +28 -0
- package/dist/hierarchy.js +164 -0
- package/dist/hierarchy.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/launchInterProScan.d.ts +0 -5
- package/dist/launchInterProScan.js +5 -3
- package/dist/launchInterProScan.js.map +1 -1
- package/dist/model/DataModel.d.ts +9 -0
- package/dist/model/DataModel.js +12 -1
- package/dist/model/DataModel.js.map +1 -1
- package/dist/model/msaModel.d.ts +3 -0
- package/dist/model/msaModel.js +0 -1
- package/dist/model/msaModel.js.map +1 -1
- package/dist/model/treeModel.d.ts +3 -6
- package/dist/model/treeModel.js +3 -15
- package/dist/model/treeModel.js.map +1 -1
- package/dist/model.d.ts +24 -77
- package/dist/model.js +117 -239
- package/dist/model.js.map +1 -1
- package/dist/neighborJoining.js +38 -629
- package/dist/neighborJoining.js.map +1 -1
- package/dist/parseAsn1.d.ts +0 -12
- package/dist/parseAsn1.js +125 -332
- package/dist/parseAsn1.js.map +1 -1
- package/dist/useWheelScroll.d.ts +8 -0
- package/dist/useWheelScroll.js +93 -0
- package/dist/useWheelScroll.js.map +1 -0
- package/dist/util.d.ts +1 -6
- package/dist/util.js +5 -34
- package/dist/util.js.map +1 -1
- package/dist/vendor/copyToClipboard.d.ts +1 -10
- package/dist/vendor/copyToClipboard.js +14 -109
- package/dist/vendor/copyToClipboard.js.map +1 -1
- package/dist/vendor/fileSaver.d.ts +1 -11
- package/dist/vendor/fileSaver.js +7 -76
- package/dist/vendor/fileSaver.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 +10 -13
- package/src/collapseLogic.test.ts +115 -0
- package/src/components/Checkbox2.tsx +9 -18
- package/src/components/MSAViewer.tsx +67 -0
- package/src/components/Track.tsx +10 -26
- package/src/components/dialogs/DomainDialog.tsx +4 -5
- package/src/components/dialogs/InterProScanDialog.tsx +7 -7
- package/src/components/dialogs/SettingsDialog.tsx +0 -37
- package/src/components/header/ColorSchemeMenu.tsx +35 -0
- package/src/components/header/FileMenu.tsx +84 -0
- package/src/components/header/Header.tsx +8 -6
- package/src/components/header/HeaderMenu.tsx +4 -155
- package/src/components/header/MSASettingsMenu.tsx +48 -0
- package/src/components/header/SettingsMenu.tsx +0 -23
- package/src/components/header/TreeSettingsMenu.tsx +96 -0
- package/src/components/header/ZoomMenu.tsx +0 -8
- package/src/components/header/getDomainsMenu.ts +83 -0
- package/src/components/import/ImportFormExamples.tsx +37 -34
- package/src/components/msa/MSACanvas.tsx +21 -91
- package/src/components/msa/MSACanvasBlock.tsx +1 -3
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +1 -1
- package/src/components/msa/renderMSABlock.ts +2 -5
- package/src/components/msa/renderMSAMouseover.ts +0 -6
- package/src/components/tree/TreeCanvas.tsx +35 -100
- package/src/components/tree/TreeNodeMenu.tsx +5 -14
- package/src/components/tree/renderTreeCanvas.ts +8 -21
- package/src/constants.ts +0 -2
- package/src/fetchUtils.ts +0 -5
- package/src/flatToTree.ts +20 -38
- package/src/hierarchy.test.ts +120 -0
- package/src/hierarchy.ts +220 -0
- package/src/index.ts +2 -0
- package/src/launchInterProScan.ts +4 -3
- package/src/model/DataModel.ts +12 -1
- package/src/model/msaModel.ts +0 -2
- package/src/model/treeModel.ts +2 -18
- package/src/model.ts +179 -278
- package/src/neighborJoining.ts +38 -628
- package/src/parseAsn1.test.ts +4 -1
- package/src/parseAsn1.ts +135 -405
- package/src/useWheelScroll.ts +109 -0
- package/src/util.ts +5 -50
- package/src/vendor/copyToClipboard.ts +14 -122
- package/src/vendor/fileSaver.ts +8 -105
- package/src/version.ts +1 -1
- package/dist/components/dialogs/AddTrackDialog.d.ts +0 -8
- package/dist/components/dialogs/AddTrackDialog.js +0 -30
- package/dist/components/dialogs/AddTrackDialog.js.map +0 -1
- package/dist/components/dialogs/TabPanel.d.ts +0 -6
- package/dist/components/dialogs/TabPanel.js +0 -6
- package/dist/components/dialogs/TabPanel.js.map +0 -1
- package/dist/components/header/ZoomStar.js +0 -40
- package/dist/components/header/ZoomStar.js.map +0 -1
- package/dist/layout.d.ts +0 -26
- package/dist/layout.js +0 -74
- package/dist/layout.js.map +0 -1
- package/dist/reparseTree.d.ts +0 -2
- package/dist/reparseTree.js +0 -15
- package/dist/reparseTree.js.map +0 -1
- package/src/components/dialogs/AddTrackDialog.tsx +0 -85
- package/src/components/dialogs/TabPanel.tsx +0 -19
- package/src/components/header/ZoomStar.tsx +0 -74
- package/src/createPaletteMap.test.ts +0 -57
- package/src/layout.ts +0 -118
- package/src/reparseTree.ts +0 -18
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { collapse, find, hierarchy, leaves, sort, sum } from './hierarchy.ts'
|
|
4
|
+
|
|
5
|
+
import type { NodeWithIds } from './types.ts'
|
|
6
|
+
|
|
7
|
+
function makeTree(): NodeWithIds {
|
|
8
|
+
return {
|
|
9
|
+
id: 'root',
|
|
10
|
+
name: 'root',
|
|
11
|
+
children: [
|
|
12
|
+
{
|
|
13
|
+
id: 'A',
|
|
14
|
+
name: 'A',
|
|
15
|
+
children: [
|
|
16
|
+
{ id: 'A1', name: 'A1', children: [] },
|
|
17
|
+
{ id: 'A2', name: 'A2', children: [] },
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: 'B',
|
|
22
|
+
name: 'B',
|
|
23
|
+
children: [
|
|
24
|
+
{ id: 'B1', name: 'B1', children: [] },
|
|
25
|
+
{ id: 'B2', name: 'B2', children: [] },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('hierarchy', () => {
|
|
33
|
+
test('builds hierarchy from tree data', () => {
|
|
34
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
35
|
+
expect(h.data.id).toBe('root')
|
|
36
|
+
expect(h.children?.length).toBe(2)
|
|
37
|
+
expect(h.height).toBe(2)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('sets parent references', () => {
|
|
41
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
42
|
+
expect(h.parent).toBeNull()
|
|
43
|
+
expect(h.children![0]!.parent).toBe(h)
|
|
44
|
+
expect(h.children![0]!.children![0]!.parent).toBe(h.children![0])
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
describe('leaves', () => {
|
|
49
|
+
test('returns leaf nodes', () => {
|
|
50
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
51
|
+
const l = leaves(h)
|
|
52
|
+
expect(l.map(n => n.data.name)).toEqual(['A1', 'A2', 'B1', 'B2'])
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
describe('find', () => {
|
|
57
|
+
test('finds node by id', () => {
|
|
58
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
59
|
+
const node = find(h, n => n.data.id === 'B1')
|
|
60
|
+
expect(node?.data.name).toBe('B1')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('returns undefined for missing id', () => {
|
|
64
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
65
|
+
expect(find(h, n => n.data.id === 'Z')).toBeUndefined()
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
describe('collapse', () => {
|
|
70
|
+
test('hides children of a branch node', () => {
|
|
71
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
72
|
+
const nodeA = find(h, n => n.data.id === 'A')!
|
|
73
|
+
collapse(nodeA)
|
|
74
|
+
expect(nodeA.children).toBeNull()
|
|
75
|
+
expect(nodeA._children?.length).toBe(2)
|
|
76
|
+
expect(leaves(h).map(n => n.data.name)).toEqual(['A', 'B1', 'B2'])
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('does nothing on a leaf node', () => {
|
|
80
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
81
|
+
const leaf = find(h, n => n.data.id === 'A1')!
|
|
82
|
+
collapse(leaf)
|
|
83
|
+
expect(leaves(h).map(n => n.data.name)).toEqual(['A1', 'A2', 'B1', 'B2'])
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
describe('leaf removal via parent.children filter', () => {
|
|
88
|
+
test('removing a leaf from its parent hides it from leaves()', () => {
|
|
89
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
90
|
+
const leaf = find(h, n => n.data.id === 'A1')!
|
|
91
|
+
leaf.parent!.children = leaf.parent!.children!.filter(
|
|
92
|
+
c => c.data.id !== 'A1',
|
|
93
|
+
)
|
|
94
|
+
expect(leaves(h).map(n => n.data.name)).toEqual(['A2', 'B1', 'B2'])
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('removing all leaves from a branch makes the branch a leaf', () => {
|
|
98
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
99
|
+
const nodeA = find(h, n => n.data.id === 'A')!
|
|
100
|
+
nodeA.children = []
|
|
101
|
+
expect(leaves(h).map(n => n.data.name)).toEqual(['B1', 'B2'])
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
describe('sort', () => {
|
|
106
|
+
test('sorts children', () => {
|
|
107
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
108
|
+
sort(h, (a, b) => b.data.name.localeCompare(a.data.name))
|
|
109
|
+
expect(h.children!.map(c => c.data.name)).toEqual(['B', 'A'])
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
describe('sum', () => {
|
|
114
|
+
test('computes leaf counts', () => {
|
|
115
|
+
const h = hierarchy(makeTree(), d => d.children)
|
|
116
|
+
sum(h, d => (d.children.length > 0 ? 0 : 1))
|
|
117
|
+
expect(h.value).toBe(4)
|
|
118
|
+
expect(find(h, n => n.data.id === 'A')?.value).toBe(2)
|
|
119
|
+
})
|
|
120
|
+
})
|
package/src/hierarchy.ts
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import type { NodeWithIds } from './types.ts'
|
|
2
|
+
|
|
3
|
+
export interface HierarchyNode<T = NodeWithIds> {
|
|
4
|
+
data: T
|
|
5
|
+
children: HierarchyNode<T>[] | null
|
|
6
|
+
parent: HierarchyNode<T> | null
|
|
7
|
+
depth: number
|
|
8
|
+
height: number
|
|
9
|
+
value?: number
|
|
10
|
+
x?: number
|
|
11
|
+
y?: number
|
|
12
|
+
len?: number
|
|
13
|
+
_children?: HierarchyNode<T>[] | null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface HierarchyLink<T = NodeWithIds> {
|
|
17
|
+
source: HierarchyNode<T>
|
|
18
|
+
target: HierarchyNode<T>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function computeHeight<T>(node: HierarchyNode<T>): number {
|
|
22
|
+
let h = 0
|
|
23
|
+
if (node.children) {
|
|
24
|
+
for (const child of node.children) {
|
|
25
|
+
const ch = computeHeight(child) + 1
|
|
26
|
+
if (ch > h) {
|
|
27
|
+
h = ch
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
node.height = h
|
|
32
|
+
return h
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function wrap<T>(
|
|
36
|
+
data: T,
|
|
37
|
+
childrenAccessor: (d: T) => T[] | undefined,
|
|
38
|
+
parent: HierarchyNode<T> | null,
|
|
39
|
+
depth: number,
|
|
40
|
+
): HierarchyNode<T> {
|
|
41
|
+
const kids = childrenAccessor(data)
|
|
42
|
+
const node: HierarchyNode<T> = {
|
|
43
|
+
data,
|
|
44
|
+
children: null,
|
|
45
|
+
parent,
|
|
46
|
+
depth,
|
|
47
|
+
height: 0,
|
|
48
|
+
}
|
|
49
|
+
if (kids?.length) {
|
|
50
|
+
node.children = kids.map(d => wrap(d, childrenAccessor, node, depth + 1))
|
|
51
|
+
}
|
|
52
|
+
return node
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function hierarchy<T>(
|
|
56
|
+
data: T,
|
|
57
|
+
childrenAccessor: (d: T) => T[] | undefined,
|
|
58
|
+
): HierarchyNode<T> {
|
|
59
|
+
const root = wrap(data, childrenAccessor, null, 0)
|
|
60
|
+
computeHeight(root)
|
|
61
|
+
return root
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function sum<T>(
|
|
65
|
+
node: HierarchyNode<T>,
|
|
66
|
+
valueFn: (d: T) => number,
|
|
67
|
+
): HierarchyNode<T> {
|
|
68
|
+
function visit(n: HierarchyNode<T>): number {
|
|
69
|
+
let s = valueFn(n.data)
|
|
70
|
+
if (n.children) {
|
|
71
|
+
for (const child of n.children) {
|
|
72
|
+
s += visit(child)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
n.value = s
|
|
76
|
+
return s
|
|
77
|
+
}
|
|
78
|
+
visit(node)
|
|
79
|
+
return node
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function sort<T>(
|
|
83
|
+
node: HierarchyNode<T>,
|
|
84
|
+
compareFn: (a: HierarchyNode<T>, b: HierarchyNode<T>) => number,
|
|
85
|
+
): HierarchyNode<T> {
|
|
86
|
+
function visit(n: HierarchyNode<T>) {
|
|
87
|
+
if (n.children) {
|
|
88
|
+
n.children.sort(compareFn)
|
|
89
|
+
for (const child of n.children) {
|
|
90
|
+
visit(child)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
visit(node)
|
|
95
|
+
return node
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function find<T>(
|
|
99
|
+
node: HierarchyNode<T>,
|
|
100
|
+
predicate: (n: HierarchyNode<T>) => boolean,
|
|
101
|
+
): HierarchyNode<T> | undefined {
|
|
102
|
+
if (predicate(node)) {
|
|
103
|
+
return node
|
|
104
|
+
}
|
|
105
|
+
if (node.children) {
|
|
106
|
+
for (const child of node.children) {
|
|
107
|
+
const result = find(child, predicate)
|
|
108
|
+
if (result) {
|
|
109
|
+
return result
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return undefined
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function leaves<T>(node: HierarchyNode<T>): HierarchyNode<T>[] {
|
|
117
|
+
const result: HierarchyNode<T>[] = []
|
|
118
|
+
function visit(n: HierarchyNode<T>) {
|
|
119
|
+
if (n.children) {
|
|
120
|
+
for (const child of n.children) {
|
|
121
|
+
visit(child)
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
result.push(n)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
visit(node)
|
|
128
|
+
return result
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function descendants<T>(node: HierarchyNode<T>): HierarchyNode<T>[] {
|
|
132
|
+
const result: HierarchyNode<T>[] = []
|
|
133
|
+
function visit(n: HierarchyNode<T>) {
|
|
134
|
+
result.push(n)
|
|
135
|
+
if (n.children) {
|
|
136
|
+
for (const child of n.children) {
|
|
137
|
+
visit(child)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
visit(node)
|
|
142
|
+
return result
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function links<T>(node: HierarchyNode<T>): HierarchyLink<T>[] {
|
|
146
|
+
const result: HierarchyLink<T>[] = []
|
|
147
|
+
function visit(n: HierarchyNode<T>) {
|
|
148
|
+
if (n.children) {
|
|
149
|
+
for (const child of n.children) {
|
|
150
|
+
result.push({ source: n, target: child })
|
|
151
|
+
visit(child)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
visit(node)
|
|
156
|
+
return result
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function clusterLayout<T>(
|
|
160
|
+
root: HierarchyNode<T>,
|
|
161
|
+
sizeX: number,
|
|
162
|
+
sizeY: number,
|
|
163
|
+
) {
|
|
164
|
+
const leafNodes = leaves(root)
|
|
165
|
+
const n = leafNodes.length
|
|
166
|
+
const step = sizeX / n
|
|
167
|
+
|
|
168
|
+
for (let i = 0; i < n; i++) {
|
|
169
|
+
leafNodes[i]!.x = (i + 0.5) * step
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function assignX(node: HierarchyNode<T>) {
|
|
173
|
+
if (!node.children) {
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
for (const child of node.children) {
|
|
177
|
+
assignX(child)
|
|
178
|
+
}
|
|
179
|
+
let sum = 0
|
|
180
|
+
for (const child of node.children) {
|
|
181
|
+
sum += child.x!
|
|
182
|
+
}
|
|
183
|
+
node.x = sum / node.children.length
|
|
184
|
+
}
|
|
185
|
+
assignX(root)
|
|
186
|
+
|
|
187
|
+
const rootHeight = root.height
|
|
188
|
+
function assignY(node: HierarchyNode<T>, depth: number) {
|
|
189
|
+
node.y = rootHeight === 0 ? sizeY : (depth / rootHeight) * sizeY
|
|
190
|
+
if (node.children) {
|
|
191
|
+
for (const child of node.children) {
|
|
192
|
+
assignY(child, depth + 1)
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
assignY(root, 0)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function collapse<T>(node: HierarchyNode<T>) {
|
|
200
|
+
if (node.children) {
|
|
201
|
+
node._children = node.children
|
|
202
|
+
node.children = null
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function maxLength(d: HierarchyNode): number {
|
|
207
|
+
return (
|
|
208
|
+
(d.data.length || 0) +
|
|
209
|
+
(d.children ? d.children.reduce((m, c) => Math.max(m, maxLength(c)), 0) : 0)
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function setBrLength(d: HierarchyNode, y0: number, k: number) {
|
|
214
|
+
d.len = (y0 += Math.max(d.data.length || 0, 0)) * k
|
|
215
|
+
if (d.children) {
|
|
216
|
+
for (const child of d.children) {
|
|
217
|
+
setBrLength(child, y0, k)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { default as MSAView } from './components/Loading.tsx'
|
|
2
|
+
export { default as MSAViewer } from './components/MSAViewer.tsx'
|
|
2
3
|
export { type MsaViewModel, default as MSAModelF } from './model.ts'
|
|
3
4
|
export type { MSAParserType } from 'msa-parsers'
|
|
5
|
+
export type { HierarchyNode } from './hierarchy.ts'
|
|
4
6
|
export type { InterProScanResults } from './launchInterProScan.ts'
|
|
5
7
|
export type {
|
|
6
8
|
Accession,
|
|
@@ -52,7 +52,7 @@ async function runInterProScan({
|
|
|
52
52
|
await loadInterProScanResultsWithStatus({ jobId, model })
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
function loadInterProScanResults(jobId: string) {
|
|
56
56
|
return jsonfetch<InterProScanResponse>(
|
|
57
57
|
`${base}/iprscan5/result/${jobId}/json`,
|
|
58
58
|
)
|
|
@@ -111,14 +111,15 @@ export async function launchInterProScan({
|
|
|
111
111
|
programs,
|
|
112
112
|
model,
|
|
113
113
|
})
|
|
114
|
+
} else {
|
|
115
|
+
throw new Error('unknown algorithm')
|
|
114
116
|
}
|
|
115
|
-
throw new Error('unknown algorithm')
|
|
116
117
|
} finally {
|
|
117
118
|
onProgress()
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
|
|
122
|
+
async function loadInterProScanResultsWithStatus({
|
|
122
123
|
jobId,
|
|
123
124
|
model,
|
|
124
125
|
}: {
|
package/src/model/DataModel.ts
CHANGED
|
@@ -22,6 +22,10 @@ export function DataModelF() {
|
|
|
22
22
|
* #property
|
|
23
23
|
*/
|
|
24
24
|
treeMetadata: types.maybe(types.string),
|
|
25
|
+
/**
|
|
26
|
+
* #property
|
|
27
|
+
*/
|
|
28
|
+
gff: types.maybe(types.string),
|
|
25
29
|
})
|
|
26
30
|
.actions(self => ({
|
|
27
31
|
/**
|
|
@@ -42,15 +46,22 @@ export function DataModelF() {
|
|
|
42
46
|
setTreeMetadata(treeMetadata?: string) {
|
|
43
47
|
self.treeMetadata = treeMetadata
|
|
44
48
|
},
|
|
49
|
+
/**
|
|
50
|
+
* #action
|
|
51
|
+
*/
|
|
52
|
+
setGFF(gff?: string) {
|
|
53
|
+
self.gff = gff
|
|
54
|
+
},
|
|
45
55
|
}))
|
|
46
56
|
.postProcessSnapshot(snap => {
|
|
47
|
-
const { tree, msa, treeMetadata } = snap
|
|
57
|
+
const { tree, msa, treeMetadata, gff } = snap
|
|
48
58
|
const max = 50_000
|
|
49
59
|
return {
|
|
50
60
|
tree: tree && tree.length > max ? undefined : tree,
|
|
51
61
|
msa: msa && msa.length > max ? undefined : msa,
|
|
52
62
|
treeMetadata:
|
|
53
63
|
treeMetadata && treeMetadata.length > max ? undefined : treeMetadata,
|
|
64
|
+
gff: gff && gff.length > max ? undefined : gff,
|
|
54
65
|
}
|
|
55
66
|
})
|
|
56
67
|
}
|
package/src/model/msaModel.ts
CHANGED
package/src/model/treeModel.ts
CHANGED
|
@@ -8,14 +8,11 @@ import {
|
|
|
8
8
|
defaultShowBranchLen,
|
|
9
9
|
defaultTreeAreaWidth,
|
|
10
10
|
defaultTreeWidth,
|
|
11
|
-
defaultTreeWidthMatchesArea,
|
|
12
11
|
} from '../constants.ts'
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
14
|
* #stateModel Tree
|
|
16
15
|
*/
|
|
17
|
-
function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
18
|
-
|
|
19
16
|
export function TreeModelF() {
|
|
20
17
|
return types
|
|
21
18
|
.model({
|
|
@@ -37,16 +34,11 @@ export function TreeModelF() {
|
|
|
37
34
|
|
|
38
35
|
/**
|
|
39
36
|
* #property
|
|
40
|
-
* width of the tree within the treeArea, px
|
|
37
|
+
* width of the tree within the treeArea, px. automatically synced to
|
|
38
|
+
* fit within treeAreaWidth
|
|
41
39
|
*/
|
|
42
40
|
treeWidth: types.optional(types.number, defaultTreeWidth),
|
|
43
41
|
|
|
44
|
-
/**
|
|
45
|
-
* #getter
|
|
46
|
-
* synchronization that matches treeWidth to treeAreaWidth
|
|
47
|
-
*/
|
|
48
|
-
treeWidthMatchesArea: defaultTreeWidthMatchesArea,
|
|
49
|
-
|
|
50
42
|
/**
|
|
51
43
|
* #property
|
|
52
44
|
* use "branch length" e.g. evolutionary distance to draw tree branch
|
|
@@ -68,14 +60,6 @@ export function TreeModelF() {
|
|
|
68
60
|
drawNodeBubbles: defaultDrawNodeBubbles,
|
|
69
61
|
})
|
|
70
62
|
.actions(self => ({
|
|
71
|
-
/**
|
|
72
|
-
* #action
|
|
73
|
-
* synchronize the treewidth and treeareawidth
|
|
74
|
-
*/
|
|
75
|
-
setTreeWidthMatchesArea(arg: boolean) {
|
|
76
|
-
self.treeWidthMatchesArea = arg
|
|
77
|
-
},
|
|
78
|
-
|
|
79
63
|
/**
|
|
80
64
|
* #action
|
|
81
65
|
* set tree area width (px)
|