react-msaview 2.1.5 → 3.0.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/bundle/index.js +37 -255
- package/dist/DialogQueue.d.ts +25 -0
- package/dist/DialogQueue.js +46 -0
- package/dist/DialogQueue.js.map +1 -0
- package/dist/UniprotTrack.js.map +1 -1
- package/dist/colorSchemes.js.map +1 -1
- package/dist/components/BoxTrackBlock.js +3 -2
- package/dist/components/BoxTrackBlock.js.map +1 -1
- package/dist/components/Header.js +12 -20
- package/dist/components/Header.js.map +1 -1
- package/dist/components/HeaderInfoArea.d.ts +6 -0
- package/dist/components/HeaderInfoArea.js +12 -0
- package/dist/components/HeaderInfoArea.js.map +1 -0
- package/dist/components/ImportForm/ImportFormExamples.d.ts +6 -0
- package/dist/components/ImportForm/ImportFormExamples.js +50 -0
- package/dist/components/ImportForm/ImportFormExamples.js.map +1 -0
- package/dist/components/ImportForm/data/seq2.js.map +1 -0
- package/dist/components/{ImportForm.d.ts → ImportForm/index.d.ts} +1 -1
- package/dist/components/ImportForm/index.js +31 -0
- package/dist/components/ImportForm/index.js.map +1 -0
- package/dist/components/ImportForm/util.d.ts +3 -0
- package/dist/components/ImportForm/util.js +15 -0
- package/dist/components/ImportForm/util.js.map +1 -0
- package/dist/components/MSAPanel/Loading.d.ts +2 -0
- package/dist/components/MSAPanel/Loading.js +12 -0
- package/dist/components/MSAPanel/Loading.js.map +1 -0
- package/dist/components/{MSABlock.d.ts → MSAPanel/MSABlock.d.ts} +1 -1
- package/dist/components/MSAPanel/MSABlock.js +46 -0
- package/dist/components/MSAPanel/MSABlock.js.map +1 -0
- package/dist/components/{MSACanvas.d.ts → MSAPanel/MSACanvas.d.ts} +1 -1
- package/dist/components/{MSACanvas.js → MSAPanel/MSACanvas.js} +2 -4
- package/dist/components/MSAPanel/MSACanvas.js.map +1 -0
- package/dist/components/{MSAMouseoverCanvas.d.ts → MSAPanel/MSAMouseoverCanvas.d.ts} +1 -1
- package/dist/components/MSAPanel/MSAMouseoverCanvas.js +29 -0
- package/dist/components/MSAPanel/MSAMouseoverCanvas.js.map +1 -0
- package/dist/components/MSAPanel/index.d.ts +5 -0
- package/dist/components/MSAPanel/index.js +9 -0
- package/dist/components/MSAPanel/index.js.map +1 -0
- package/dist/components/MSAPanel/renderMSABlock.d.ts +8 -0
- package/dist/components/MSAPanel/renderMSABlock.js +80 -0
- package/dist/components/MSAPanel/renderMSABlock.js.map +1 -0
- package/dist/components/MSAPanel/renderMSAMouseover.d.ts +5 -0
- package/dist/components/MSAPanel/renderMSAMouseover.js +24 -0
- package/dist/components/MSAPanel/renderMSAMouseover.js.map +1 -0
- package/dist/components/MSAView.d.ts +2 -2
- package/dist/components/MSAView.js +26 -31
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/Minimap.d.ts +6 -0
- package/dist/components/Minimap.js +72 -0
- package/dist/components/Minimap.js.map +1 -0
- package/dist/components/ResizeHandles.js.map +1 -1
- package/dist/components/TextTrack.js +3 -2
- package/dist/components/TextTrack.js.map +1 -1
- package/dist/components/Track.js +5 -5
- package/dist/components/Track.js.map +1 -1
- package/dist/components/{TreeBranchMenu.d.ts → TreePanel/TreeBranchMenu.d.ts} +1 -1
- package/dist/components/TreePanel/TreeBranchMenu.js.map +1 -0
- package/dist/components/{TreeCanvas.d.ts → TreePanel/TreeCanvas.d.ts} +1 -1
- package/dist/components/{TreeCanvas.js → TreePanel/TreeCanvas.js} +1 -1
- package/dist/components/TreePanel/TreeCanvas.js.map +1 -0
- package/dist/components/{TreeCanvasBlock.d.ts → TreePanel/TreeCanvasBlock.d.ts} +1 -1
- package/dist/components/TreePanel/TreeCanvasBlock.js +121 -0
- package/dist/components/TreePanel/TreeCanvasBlock.js.map +1 -0
- package/dist/components/{TreeMenu.d.ts → TreePanel/TreeNodeMenu.d.ts} +2 -1
- package/dist/components/{TreeMenu.js → TreePanel/TreeNodeMenu.js} +16 -8
- package/dist/components/TreePanel/TreeNodeMenu.js.map +1 -0
- package/dist/components/{TreeRuler.d.ts → TreePanel/TreeRuler.d.ts} +1 -1
- package/dist/components/TreePanel/TreeRuler.js +8 -0
- package/dist/components/TreePanel/TreeRuler.js.map +1 -0
- package/dist/components/{dialogs/TreeNodeInfoDlg.d.ts → TreePanel/dialogs/TreeNodeInfoDialog.d.ts} +1 -1
- package/dist/components/{dialogs/TreeNodeInfoDlg.js → TreePanel/dialogs/TreeNodeInfoDialog.js} +2 -2
- package/dist/components/TreePanel/dialogs/TreeNodeInfoDialog.js.map +1 -0
- package/dist/components/TreePanel/index.d.ts +6 -0
- package/dist/components/TreePanel/index.js +10 -0
- package/dist/components/TreePanel/index.js.map +1 -0
- package/dist/components/TreePanel/renderTreeCanvas.d.ts +41 -0
- package/dist/components/TreePanel/renderTreeCanvas.js +154 -0
- package/dist/components/TreePanel/renderTreeCanvas.js.map +1 -0
- package/dist/components/dialogs/{AboutDlg.js → AboutDialog.js} +1 -1
- package/dist/components/dialogs/AboutDialog.js.map +1 -0
- package/dist/components/dialogs/{AddTrackDlg.js → AddTrackDialog.js} +1 -1
- package/dist/components/dialogs/AddTrackDialog.js.map +1 -0
- package/dist/components/dialogs/{MetadataDlg.js → MetadataDialog.js} +1 -1
- package/dist/components/dialogs/MetadataDialog.js.map +1 -0
- package/dist/components/dialogs/SettingsDialog.js +63 -0
- package/dist/components/dialogs/SettingsDialog.js.map +1 -0
- package/dist/components/dialogs/{TrackInfoDlg.js → TrackInfoDialog.js} +1 -1
- package/dist/components/dialogs/TrackInfoDialog.js.map +1 -0
- package/dist/components/dialogs/{TracklistDlg.js → TracklistDialog.js} +1 -1
- package/dist/components/dialogs/TracklistDialog.js.map +1 -0
- package/dist/components/util.js.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/model.d.ts +179 -88
- package/dist/model.js +287 -175
- package/dist/model.js.map +1 -1
- package/dist/parseNewick.js.map +1 -1
- package/dist/parsers/ClustalMSA.d.ts +1 -1
- package/dist/parsers/ClustalMSA.js +1 -1
- package/dist/parsers/ClustalMSA.js.map +1 -1
- package/dist/parsers/FastaMSA.d.ts +1 -1
- package/dist/parsers/FastaMSA.js +2 -2
- package/dist/parsers/FastaMSA.js.map +1 -1
- package/dist/parsers/StockholmMSA.d.ts +1 -1
- package/dist/parsers/StockholmMSA.js +2 -2
- package/dist/parsers/StockholmMSA.js.map +1 -1
- package/dist/util.d.ts +1 -0
- package/dist/util.js +15 -7
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -4
- package/src/DialogQueue.ts +47 -0
- package/src/components/BoxTrackBlock.tsx +3 -1
- package/src/components/Header.tsx +13 -20
- package/src/components/HeaderInfoArea.tsx +21 -0
- package/src/components/ImportForm/ImportFormExamples.tsx +133 -0
- package/src/components/ImportForm/index.tsx +63 -0
- package/src/components/ImportForm/util.ts +20 -0
- package/src/components/MSAPanel/Loading.tsx +16 -0
- package/src/components/MSAPanel/MSABlock.tsx +81 -0
- package/src/components/{MSACanvas.tsx → MSAPanel/MSACanvas.tsx} +3 -6
- package/src/components/MSAPanel/MSAMouseoverCanvas.tsx +44 -0
- package/src/components/MSAPanel/index.tsx +13 -0
- package/src/components/MSAPanel/renderMSABlock.ts +158 -0
- package/src/components/MSAPanel/renderMSAMouseover.ts +51 -0
- package/src/components/MSAView.tsx +36 -56
- package/src/components/Minimap.tsx +102 -0
- package/src/components/TextTrack.tsx +3 -1
- package/src/components/Track.tsx +5 -5
- package/src/components/{TreeBranchMenu.tsx → TreePanel/TreeBranchMenu.tsx} +1 -1
- package/src/components/{TreeCanvas.tsx → TreePanel/TreeCanvas.tsx} +2 -3
- package/src/components/TreePanel/TreeCanvasBlock.tsx +195 -0
- package/src/components/{TreeMenu.tsx → TreePanel/TreeNodeMenu.tsx} +21 -8
- package/src/components/{TreeRuler.tsx → TreePanel/TreeRuler.tsx} +3 -3
- package/src/components/{dialogs/TreeNodeInfoDlg.tsx → TreePanel/dialogs/TreeNodeInfoDialog.tsx} +2 -2
- package/src/components/TreePanel/index.tsx +16 -0
- package/src/components/TreePanel/renderTreeCanvas.ts +254 -0
- package/src/components/dialogs/SettingsDialog.tsx +196 -0
- package/src/model.ts +414 -211
- package/src/parsers/ClustalMSA.ts +1 -1
- package/src/parsers/FastaMSA.ts +1 -1
- package/src/parsers/StockholmMSA.ts +1 -1
- package/src/util.ts +19 -6
- package/src/version.ts +1 -1
- package/dist/components/ImportForm.js +0 -84
- package/dist/components/ImportForm.js.map +0 -1
- package/dist/components/MSABlock.js +0 -103
- package/dist/components/MSABlock.js.map +0 -1
- package/dist/components/MSACanvas.js.map +0 -1
- package/dist/components/MSAMouseoverCanvas.js +0 -61
- package/dist/components/MSAMouseoverCanvas.js.map +0 -1
- package/dist/components/Rubberband.d.ts +0 -8
- package/dist/components/Rubberband.js +0 -173
- package/dist/components/Rubberband.js.map +0 -1
- package/dist/components/Ruler.d.ts +0 -6
- package/dist/components/Ruler.js +0 -52
- package/dist/components/Ruler.js.map +0 -1
- package/dist/components/TreeBranchMenu.js.map +0 -1
- package/dist/components/TreeCanvas.js.map +0 -1
- package/dist/components/TreeCanvasBlock.js +0 -255
- package/dist/components/TreeCanvasBlock.js.map +0 -1
- package/dist/components/TreeMenu.js.map +0 -1
- package/dist/components/TreeRuler.js +0 -8
- package/dist/components/TreeRuler.js.map +0 -1
- package/dist/components/data/seq2.js.map +0 -1
- package/dist/components/dialogs/AboutDlg.js.map +0 -1
- package/dist/components/dialogs/AddTrackDlg.js.map +0 -1
- package/dist/components/dialogs/AnnotationDlg.d.ts +0 -11
- package/dist/components/dialogs/AnnotationDlg.js +0 -65
- package/dist/components/dialogs/AnnotationDlg.js.map +0 -1
- package/dist/components/dialogs/MetadataDlg.js.map +0 -1
- package/dist/components/dialogs/SettingsDlg.js +0 -48
- package/dist/components/dialogs/SettingsDlg.js.map +0 -1
- package/dist/components/dialogs/TrackInfoDlg.js.map +0 -1
- package/dist/components/dialogs/TracklistDlg.js.map +0 -1
- package/dist/components/dialogs/TreeNodeInfoDlg.js.map +0 -1
- package/src/components/ImportForm.tsx +0 -192
- package/src/components/MSABlock.tsx +0 -164
- package/src/components/MSAMouseoverCanvas.tsx +0 -99
- package/src/components/Rubberband.tsx +0 -270
- package/src/components/Ruler.tsx +0 -123
- package/src/components/TreeCanvasBlock.tsx +0 -363
- package/src/components/dialogs/AnnotationDlg.tsx +0 -144
- package/src/components/dialogs/SettingsDlg.tsx +0 -154
- /package/dist/components/{data → ImportForm/data}/seq2.d.ts +0 -0
- /package/dist/components/{data → ImportForm/data}/seq2.js +0 -0
- /package/dist/components/{TreeBranchMenu.js → TreePanel/TreeBranchMenu.js} +0 -0
- /package/dist/components/dialogs/{AboutDlg.d.ts → AboutDialog.d.ts} +0 -0
- /package/dist/components/dialogs/{AddTrackDlg.d.ts → AddTrackDialog.d.ts} +0 -0
- /package/dist/components/dialogs/{MetadataDlg.d.ts → MetadataDialog.d.ts} +0 -0
- /package/dist/components/dialogs/{SettingsDlg.d.ts → SettingsDialog.d.ts} +0 -0
- /package/dist/components/dialogs/{TrackInfoDlg.d.ts → TrackInfoDialog.d.ts} +0 -0
- /package/dist/components/dialogs/{TracklistDlg.d.ts → TracklistDialog.d.ts} +0 -0
- /package/src/components/{data → ImportForm/data}/seq2.ts +0 -0
- /package/src/components/dialogs/{AboutDlg.tsx → AboutDialog.tsx} +0 -0
- /package/src/components/dialogs/{AddTrackDlg.tsx → AddTrackDialog.tsx} +0 -0
- /package/src/components/dialogs/{MetadataDlg.tsx → MetadataDialog.tsx} +0 -0
- /package/src/components/dialogs/{TrackInfoDlg.tsx → TrackInfoDialog.tsx} +0 -0
- /package/src/components/dialogs/{TracklistDlg.tsx → TracklistDialog.tsx} +0 -0
package/src/model.ts
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
+
import { autorun } from 'mobx'
|
|
2
3
|
import { Instance, cast, types, addDisposer, SnapshotIn } from 'mobx-state-tree'
|
|
3
4
|
import { hierarchy, cluster, HierarchyNode } from 'd3-hierarchy'
|
|
4
5
|
import { ascending } from 'd3-array'
|
|
6
|
+
import Stockholm from 'stockholm-js'
|
|
7
|
+
// jbrowse
|
|
5
8
|
import { FileLocation, ElementId } from '@jbrowse/core/util/types/mst'
|
|
6
9
|
import { FileLocation as FileLocationType } from '@jbrowse/core/util/types'
|
|
7
10
|
import { openLocation } from '@jbrowse/core/util/io'
|
|
8
|
-
import {
|
|
11
|
+
import { measureText, notEmpty, sum } from '@jbrowse/core/util'
|
|
9
12
|
import BaseViewModel from '@jbrowse/core/pluggableElementTypes/models/BaseViewModel'
|
|
10
|
-
import Stockholm from 'stockholm-js'
|
|
11
|
-
|
|
12
|
-
export interface RowDetails {
|
|
13
|
-
[key: string]: unknown
|
|
14
|
-
name: string
|
|
15
|
-
range?: { start: number; end: number }
|
|
16
|
-
}
|
|
17
13
|
|
|
18
14
|
// locals
|
|
19
15
|
import {
|
|
16
|
+
clamp,
|
|
20
17
|
collapse,
|
|
18
|
+
filterHiddenLeafNodes,
|
|
21
19
|
generateNodeIds,
|
|
22
20
|
maxLength,
|
|
23
21
|
setBrLength,
|
|
24
22
|
skipBlanks,
|
|
25
|
-
clamp,
|
|
26
23
|
NodeWithIds,
|
|
27
24
|
NodeWithIdsAndLength,
|
|
28
25
|
} from './util'
|
|
@@ -35,6 +32,13 @@ import parseNewick from './parseNewick'
|
|
|
35
32
|
import colorSchemes from './colorSchemes'
|
|
36
33
|
import { UniprotTrack } from './UniprotTrack'
|
|
37
34
|
import { StructureModel } from './StructureModel'
|
|
35
|
+
import { DialogQueueSessionMixin } from './DialogQueue'
|
|
36
|
+
|
|
37
|
+
export interface RowDetails {
|
|
38
|
+
[key: string]: unknown
|
|
39
|
+
name: string
|
|
40
|
+
range?: { start: number; end: number }
|
|
41
|
+
}
|
|
38
42
|
|
|
39
43
|
interface BasicTrackModel {
|
|
40
44
|
id: string
|
|
@@ -42,6 +46,11 @@ interface BasicTrackModel {
|
|
|
42
46
|
associatedRowName?: string
|
|
43
47
|
height: number
|
|
44
48
|
}
|
|
49
|
+
interface Structure {
|
|
50
|
+
pdb: string
|
|
51
|
+
startPos: number
|
|
52
|
+
endPos: number
|
|
53
|
+
}
|
|
45
54
|
|
|
46
55
|
export interface TextTrackModel extends BasicTrackModel {
|
|
47
56
|
customColorScheme?: Record<string, string>
|
|
@@ -71,141 +80,193 @@ type StructureSnap = SnapshotIn<typeof StructureModel>
|
|
|
71
80
|
|
|
72
81
|
/**
|
|
73
82
|
* #stateModel MsaView
|
|
83
|
+
* extends
|
|
84
|
+
* - BaseViewModel
|
|
85
|
+
* - DialogQueueSessionMixin
|
|
74
86
|
*/
|
|
75
87
|
function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
76
88
|
|
|
89
|
+
export type DialogComponentType =
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
91
|
+
| React.LazyExoticComponent<React.FC<any>>
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
93
|
+
| React.FC<any>
|
|
94
|
+
|
|
77
95
|
const model = types
|
|
78
96
|
.compose(
|
|
79
97
|
BaseViewModel,
|
|
98
|
+
DialogQueueSessionMixin(),
|
|
80
99
|
types.model('MsaView', {
|
|
81
100
|
/**
|
|
82
101
|
* #property
|
|
102
|
+
* id of view, randomly generated if not provided
|
|
83
103
|
*/
|
|
84
104
|
id: ElementId,
|
|
105
|
+
|
|
85
106
|
/**
|
|
86
107
|
* #property
|
|
108
|
+
* hardcoded view type
|
|
87
109
|
*/
|
|
88
110
|
type: types.literal('MsaView'),
|
|
111
|
+
|
|
89
112
|
/**
|
|
90
113
|
* #property
|
|
114
|
+
* height of the div containing the view, px
|
|
91
115
|
*/
|
|
92
116
|
height: types.optional(types.number, 550),
|
|
117
|
+
|
|
93
118
|
/**
|
|
94
119
|
* #property
|
|
120
|
+
* width of the area the tree is drawn in, px
|
|
95
121
|
*/
|
|
96
122
|
treeAreaWidth: types.optional(types.number, 400),
|
|
123
|
+
|
|
97
124
|
/**
|
|
98
125
|
* #property
|
|
126
|
+
* width of the tree within the treeArea, px
|
|
99
127
|
*/
|
|
100
128
|
treeWidth: types.optional(types.number, 300),
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* #getter
|
|
132
|
+
* synchronization that matches treeWidth to treeAreaWidth
|
|
133
|
+
*/
|
|
134
|
+
treeWidthMatchesArea: true,
|
|
135
|
+
|
|
101
136
|
/**
|
|
102
137
|
* #property
|
|
138
|
+
* height of each row, px
|
|
103
139
|
*/
|
|
104
140
|
rowHeight: 20,
|
|
141
|
+
|
|
105
142
|
/**
|
|
106
143
|
* #property
|
|
144
|
+
* scroll position, Y-offset, px
|
|
107
145
|
*/
|
|
108
146
|
scrollY: 0,
|
|
147
|
+
|
|
109
148
|
/**
|
|
110
149
|
* #property
|
|
150
|
+
* scroll position, X-offset, px
|
|
111
151
|
*/
|
|
112
152
|
scrollX: 0,
|
|
153
|
+
|
|
113
154
|
/**
|
|
114
155
|
* #property
|
|
115
|
-
|
|
116
|
-
resizeHandleWidth: 5,
|
|
117
|
-
/**
|
|
118
|
-
* #property
|
|
119
|
-
*/
|
|
120
|
-
blockSize: 1000,
|
|
121
|
-
/**
|
|
122
|
-
* #property
|
|
123
|
-
*/
|
|
124
|
-
mouseRow: types.maybe(types.number),
|
|
125
|
-
/**
|
|
126
|
-
* #property
|
|
127
|
-
*/
|
|
128
|
-
mouseCol: types.maybe(types.number),
|
|
129
|
-
/**
|
|
130
|
-
* #property
|
|
156
|
+
* currently "selected" structures, generally PDB 3-D protein structures
|
|
131
157
|
*/
|
|
132
158
|
selectedStructures: types.array(StructureModel),
|
|
159
|
+
|
|
133
160
|
/**
|
|
134
161
|
* #property
|
|
162
|
+
* right-align the labels
|
|
135
163
|
*/
|
|
136
164
|
labelsAlignRight: false,
|
|
165
|
+
|
|
137
166
|
/**
|
|
138
167
|
* #property
|
|
168
|
+
* width of columns, px
|
|
139
169
|
*/
|
|
140
170
|
colWidth: 16,
|
|
171
|
+
|
|
141
172
|
/**
|
|
142
173
|
* #property
|
|
174
|
+
* use "branch length" e.g. evolutionary distance to draw tree branch
|
|
175
|
+
* lengths. if false, the layout is a "cladogram" that does not take into
|
|
176
|
+
* account evolutionary distances
|
|
143
177
|
*/
|
|
144
178
|
showBranchLen: true,
|
|
145
179
|
/**
|
|
146
180
|
* #property
|
|
181
|
+
* draw MSA tiles with a background color
|
|
147
182
|
*/
|
|
148
183
|
bgColor: true,
|
|
184
|
+
|
|
149
185
|
/**
|
|
150
186
|
* #property
|
|
187
|
+
* draw tree, boolean
|
|
151
188
|
*/
|
|
152
189
|
drawTree: true,
|
|
190
|
+
|
|
153
191
|
/**
|
|
154
192
|
* #property
|
|
193
|
+
* draw clickable node bubbles on the tree
|
|
155
194
|
*/
|
|
156
195
|
drawNodeBubbles: true,
|
|
196
|
+
|
|
157
197
|
/**
|
|
158
198
|
* #property
|
|
199
|
+
* high resolution scale factor, helps make canvas look better on hi-dpi
|
|
200
|
+
* screens
|
|
159
201
|
*/
|
|
160
202
|
highResScaleFactor: 2,
|
|
203
|
+
|
|
161
204
|
/**
|
|
162
205
|
* #property
|
|
206
|
+
* default color scheme name
|
|
163
207
|
*/
|
|
164
208
|
colorSchemeName: 'maeditor',
|
|
209
|
+
|
|
165
210
|
/**
|
|
166
211
|
* #property
|
|
212
|
+
* filehandle object for the tree
|
|
167
213
|
*/
|
|
168
214
|
treeFilehandle: types.maybe(FileLocation),
|
|
215
|
+
|
|
169
216
|
/**
|
|
170
217
|
* #property
|
|
218
|
+
* filehandle object for the MSA (which could contain a tree e.g. with
|
|
219
|
+
* stockholm files)
|
|
171
220
|
*/
|
|
172
221
|
msaFilehandle: types.maybe(FileLocation),
|
|
222
|
+
|
|
173
223
|
/**
|
|
174
224
|
* #property
|
|
225
|
+
* filehandle object for tree metadata
|
|
175
226
|
*/
|
|
176
227
|
treeMetadataFilehandle: types.maybe(FileLocation),
|
|
228
|
+
|
|
177
229
|
/**
|
|
178
230
|
* #property
|
|
231
|
+
*
|
|
179
232
|
*/
|
|
180
233
|
currentAlignment: 0,
|
|
234
|
+
|
|
181
235
|
/**
|
|
182
236
|
* #property
|
|
237
|
+
* array of tree nodes that are 'collapsed'
|
|
183
238
|
*/
|
|
184
239
|
collapsed: types.array(types.string),
|
|
240
|
+
|
|
185
241
|
/**
|
|
186
242
|
* #property
|
|
243
|
+
* array of leaf nodes that are 'hidden', similar to collapsed but for leaf nodes
|
|
187
244
|
*/
|
|
188
|
-
|
|
245
|
+
hidden: types.array(types.string),
|
|
246
|
+
|
|
189
247
|
/**
|
|
190
248
|
* #property
|
|
249
|
+
* focus on particular subtree
|
|
191
250
|
*/
|
|
192
|
-
|
|
251
|
+
showOnly: types.maybe(types.string),
|
|
252
|
+
|
|
193
253
|
/**
|
|
194
254
|
* #property
|
|
255
|
+
* a list of "tracks" to display, as box-like glyphs (e.g. protein
|
|
256
|
+
* domains)
|
|
195
257
|
*/
|
|
196
|
-
|
|
258
|
+
boxTracks: types.array(UniprotTrack),
|
|
259
|
+
|
|
197
260
|
/**
|
|
198
261
|
* #property
|
|
262
|
+
* turned off tracks
|
|
199
263
|
*/
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
start: types.number,
|
|
203
|
-
end: types.number,
|
|
204
|
-
attributes: types.frozen<Record<string, string[]>>(),
|
|
205
|
-
}),
|
|
206
|
-
),
|
|
264
|
+
turnedOffTracks: types.map(types.boolean),
|
|
265
|
+
|
|
207
266
|
/**
|
|
208
267
|
* #property
|
|
268
|
+
* data from the loaded tree/msa/treeMetadata, generally loaded by
|
|
269
|
+
* autorun
|
|
209
270
|
*/
|
|
210
271
|
data: types.optional(
|
|
211
272
|
types
|
|
@@ -230,43 +291,80 @@ const model = types
|
|
|
230
291
|
}),
|
|
231
292
|
)
|
|
232
293
|
.volatile(() => ({
|
|
233
|
-
|
|
294
|
+
/**
|
|
295
|
+
* #volatile
|
|
296
|
+
* resize handle width between tree and msa area, px
|
|
297
|
+
*/
|
|
298
|
+
resizeHandleWidth: 5,
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* #volatile
|
|
302
|
+
* size of blocks of content to be drawn, px
|
|
303
|
+
*/
|
|
304
|
+
blockSize: 1000,
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* #volatile
|
|
308
|
+
* the currently mouse-hovered row
|
|
309
|
+
*/
|
|
310
|
+
mouseRow: undefined as number | undefined,
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* #volatile
|
|
314
|
+
* the currently mouse-hovered column
|
|
315
|
+
*/
|
|
316
|
+
mouseCol: undefined as number | undefined,
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* #volatile
|
|
320
|
+
* a dummy variable that is incremented when ref changes so autorun for
|
|
321
|
+
* drawing canvas commands will run
|
|
322
|
+
*/
|
|
323
|
+
nref: 0,
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* #volatile
|
|
327
|
+
*/
|
|
328
|
+
minimapHeight: 56,
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* #volatile
|
|
332
|
+
*/
|
|
234
333
|
error: undefined as unknown,
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* #volatile
|
|
337
|
+
*/
|
|
235
338
|
margin: {
|
|
236
339
|
left: 20,
|
|
237
340
|
top: 20,
|
|
238
341
|
},
|
|
239
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
240
|
-
DialogComponent: undefined as undefined | React.FC<any>,
|
|
241
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
242
|
-
DialogProps: undefined as any,
|
|
243
342
|
|
|
244
|
-
|
|
343
|
+
/**
|
|
344
|
+
* #volatile
|
|
345
|
+
*/
|
|
245
346
|
annotPos: undefined as { left: number; right: number } | undefined,
|
|
246
347
|
}))
|
|
247
348
|
.actions(self => ({
|
|
248
349
|
/**
|
|
249
350
|
* #action
|
|
250
|
-
|
|
251
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
252
|
-
setDialogComponent(dlg?: React.FC<any>, props?: any) {
|
|
253
|
-
self.DialogComponent = dlg
|
|
254
|
-
self.DialogProps = props
|
|
255
|
-
},
|
|
256
|
-
/**
|
|
257
|
-
* #action
|
|
351
|
+
* set the height of the view in px
|
|
258
352
|
*/
|
|
259
353
|
setHeight(height: number) {
|
|
260
354
|
self.height = height
|
|
261
355
|
},
|
|
356
|
+
|
|
262
357
|
/**
|
|
263
358
|
* #action
|
|
359
|
+
* add to the selected structures
|
|
264
360
|
*/
|
|
265
361
|
addStructureToSelection(elt: StructureSnap) {
|
|
266
362
|
self.selectedStructures.push(elt)
|
|
267
363
|
},
|
|
364
|
+
|
|
268
365
|
/**
|
|
269
366
|
* #action
|
|
367
|
+
* remove from the selected structures
|
|
270
368
|
*/
|
|
271
369
|
removeStructureFromSelection(elt: StructureSnap) {
|
|
272
370
|
const r = self.selectedStructures.find(node => node.id === elt.id)
|
|
@@ -274,8 +372,10 @@ const model = types
|
|
|
274
372
|
self.selectedStructures.remove(r)
|
|
275
373
|
}
|
|
276
374
|
},
|
|
375
|
+
|
|
277
376
|
/**
|
|
278
377
|
* #action
|
|
378
|
+
* toggle a structure from the selected structures list
|
|
279
379
|
*/
|
|
280
380
|
toggleStructureSelection(elt: {
|
|
281
381
|
id: string
|
|
@@ -288,85 +388,122 @@ const model = types
|
|
|
288
388
|
self.selectedStructures.push(elt)
|
|
289
389
|
}
|
|
290
390
|
},
|
|
391
|
+
|
|
291
392
|
/**
|
|
292
393
|
* #action
|
|
394
|
+
* clear all selected structures
|
|
293
395
|
*/
|
|
294
396
|
clearSelectedStructures() {
|
|
295
397
|
self.selectedStructures = cast([])
|
|
296
398
|
},
|
|
399
|
+
|
|
297
400
|
/**
|
|
298
401
|
* #action
|
|
402
|
+
* set error state
|
|
299
403
|
*/
|
|
300
404
|
setError(error?: unknown) {
|
|
301
405
|
self.error = error
|
|
302
406
|
},
|
|
407
|
+
|
|
303
408
|
/**
|
|
304
409
|
* #action
|
|
410
|
+
* set mouse position (row, column) in the MSA
|
|
305
411
|
*/
|
|
306
412
|
setMousePos(col?: number, row?: number) {
|
|
307
413
|
self.mouseCol = col
|
|
308
414
|
self.mouseRow = row
|
|
309
415
|
},
|
|
416
|
+
|
|
310
417
|
/**
|
|
311
418
|
* #action
|
|
419
|
+
* set row height (px)
|
|
312
420
|
*/
|
|
313
421
|
setRowHeight(n: number) {
|
|
314
422
|
self.rowHeight = n
|
|
315
423
|
},
|
|
424
|
+
|
|
316
425
|
/**
|
|
317
426
|
* #action
|
|
427
|
+
* set col width (px)
|
|
318
428
|
*/
|
|
319
429
|
setColWidth(n: number) {
|
|
320
430
|
self.colWidth = n
|
|
321
431
|
},
|
|
432
|
+
|
|
322
433
|
/**
|
|
323
434
|
* #action
|
|
435
|
+
* set color scheme name
|
|
324
436
|
*/
|
|
325
437
|
setColorSchemeName(name: string) {
|
|
326
438
|
self.colorSchemeName = name
|
|
327
439
|
},
|
|
440
|
+
|
|
328
441
|
/**
|
|
329
442
|
* #action
|
|
443
|
+
* synchronize the treewidth and treeareawidth
|
|
330
444
|
*/
|
|
331
|
-
|
|
332
|
-
self.
|
|
445
|
+
setTreeWidthMatchesArea(arg: boolean) {
|
|
446
|
+
self.treeWidthMatchesArea = arg
|
|
333
447
|
},
|
|
448
|
+
|
|
334
449
|
/**
|
|
335
450
|
* #action
|
|
451
|
+
* set scroll Y-offset (px)
|
|
336
452
|
*/
|
|
337
|
-
|
|
338
|
-
self.
|
|
453
|
+
setScrollY(n: number) {
|
|
454
|
+
self.scrollY = n
|
|
339
455
|
},
|
|
456
|
+
|
|
340
457
|
/**
|
|
341
458
|
* #action
|
|
459
|
+
* set tree area width (px)
|
|
342
460
|
*/
|
|
343
461
|
setTreeAreaWidth(n: number) {
|
|
344
462
|
self.treeAreaWidth = n
|
|
345
463
|
},
|
|
346
464
|
/**
|
|
347
465
|
* #action
|
|
466
|
+
* set tree width (px)
|
|
348
467
|
*/
|
|
349
468
|
setTreeWidth(n: number) {
|
|
350
469
|
self.treeWidth = n
|
|
351
470
|
},
|
|
471
|
+
|
|
352
472
|
/**
|
|
353
473
|
* #action
|
|
474
|
+
*
|
|
354
475
|
*/
|
|
355
476
|
setCurrentAlignment(n: number) {
|
|
356
477
|
self.currentAlignment = n
|
|
357
478
|
},
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* #action
|
|
482
|
+
*/
|
|
483
|
+
setLabelsAlignRight(arg: boolean) {
|
|
484
|
+
self.labelsAlignRight = arg
|
|
485
|
+
},
|
|
486
|
+
/**
|
|
487
|
+
* #action
|
|
488
|
+
*/
|
|
489
|
+
setDrawTree(arg: boolean) {
|
|
490
|
+
self.drawTree = arg
|
|
491
|
+
},
|
|
492
|
+
|
|
358
493
|
/**
|
|
359
494
|
* #action
|
|
360
495
|
*/
|
|
361
|
-
|
|
362
|
-
self.
|
|
496
|
+
hideNode(arg: string) {
|
|
497
|
+
self.hidden.push(arg)
|
|
363
498
|
},
|
|
499
|
+
|
|
364
500
|
/**
|
|
365
501
|
* #action
|
|
366
502
|
*/
|
|
367
|
-
|
|
368
|
-
self.
|
|
503
|
+
clearHidden() {
|
|
504
|
+
self.hidden.clear()
|
|
369
505
|
},
|
|
506
|
+
|
|
370
507
|
/**
|
|
371
508
|
* #action
|
|
372
509
|
*/
|
|
@@ -377,42 +514,49 @@ const model = types
|
|
|
377
514
|
self.collapsed.push(node)
|
|
378
515
|
}
|
|
379
516
|
},
|
|
517
|
+
|
|
380
518
|
/**
|
|
381
519
|
* #action
|
|
382
520
|
*/
|
|
383
521
|
setShowOnly(node?: string) {
|
|
384
522
|
self.showOnly = node
|
|
385
523
|
},
|
|
524
|
+
|
|
386
525
|
/**
|
|
387
526
|
* #action
|
|
388
527
|
*/
|
|
389
|
-
|
|
390
|
-
self.showBranchLen =
|
|
528
|
+
setShowBranchLen(arg: boolean) {
|
|
529
|
+
self.showBranchLen = arg
|
|
391
530
|
},
|
|
531
|
+
|
|
392
532
|
/**
|
|
393
533
|
* #action
|
|
394
534
|
*/
|
|
395
|
-
|
|
396
|
-
self.bgColor =
|
|
535
|
+
setBgColor(arg: boolean) {
|
|
536
|
+
self.bgColor = arg
|
|
397
537
|
},
|
|
538
|
+
|
|
398
539
|
/**
|
|
399
540
|
* #action
|
|
400
541
|
*/
|
|
401
|
-
|
|
402
|
-
self.drawNodeBubbles =
|
|
542
|
+
setDrawNodeBubbles(arg: boolean) {
|
|
543
|
+
self.drawNodeBubbles = arg
|
|
403
544
|
},
|
|
545
|
+
|
|
404
546
|
/**
|
|
405
547
|
* #action
|
|
406
548
|
*/
|
|
407
549
|
setData(data: { msa?: string; tree?: string }) {
|
|
408
550
|
self.data = cast(data)
|
|
409
551
|
},
|
|
552
|
+
|
|
410
553
|
/**
|
|
411
554
|
* #action
|
|
412
555
|
*/
|
|
413
556
|
async setMSAFilehandle(msaFilehandle?: FileLocationType) {
|
|
414
557
|
self.msaFilehandle = msaFilehandle
|
|
415
558
|
},
|
|
559
|
+
|
|
416
560
|
/**
|
|
417
561
|
* #action
|
|
418
562
|
*/
|
|
@@ -424,72 +568,29 @@ const model = types
|
|
|
424
568
|
self.treeFilehandle = treeFilehandle
|
|
425
569
|
}
|
|
426
570
|
},
|
|
571
|
+
|
|
427
572
|
/**
|
|
428
573
|
* #action
|
|
429
574
|
*/
|
|
430
575
|
setMSA(result: string) {
|
|
431
576
|
self.data.setMSA(result)
|
|
432
577
|
},
|
|
578
|
+
|
|
433
579
|
/**
|
|
434
580
|
* #action
|
|
435
581
|
*/
|
|
436
582
|
setTree(result: string) {
|
|
437
583
|
self.data.setTree(result)
|
|
438
584
|
},
|
|
585
|
+
|
|
439
586
|
/**
|
|
440
587
|
* #action
|
|
441
588
|
*/
|
|
442
589
|
setTreeMetadata(result: string) {
|
|
443
590
|
self.data.setTreeMetadata(result)
|
|
444
591
|
},
|
|
445
|
-
|
|
446
|
-
afterCreate() {
|
|
447
|
-
addDisposer(
|
|
448
|
-
self,
|
|
449
|
-
autorun(async () => {
|
|
450
|
-
const { treeFilehandle } = self
|
|
451
|
-
if (treeFilehandle) {
|
|
452
|
-
try {
|
|
453
|
-
this.setTree(await openLocation(treeFilehandle).readFile('utf8'))
|
|
454
|
-
} catch (e) {
|
|
455
|
-
console.error(e)
|
|
456
|
-
this.setError(e)
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}),
|
|
460
|
-
)
|
|
461
|
-
addDisposer(
|
|
462
|
-
self,
|
|
463
|
-
autorun(async () => {
|
|
464
|
-
const { treeMetadataFilehandle } = self
|
|
465
|
-
if (treeMetadataFilehandle) {
|
|
466
|
-
try {
|
|
467
|
-
this.setTreeMetadata(
|
|
468
|
-
await openLocation(treeMetadataFilehandle).readFile('utf8'),
|
|
469
|
-
)
|
|
470
|
-
} catch (e) {
|
|
471
|
-
console.error(e)
|
|
472
|
-
this.setError(e)
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}),
|
|
476
|
-
)
|
|
477
|
-
addDisposer(
|
|
478
|
-
self,
|
|
479
|
-
autorun(async () => {
|
|
480
|
-
const { msaFilehandle } = self
|
|
481
|
-
if (msaFilehandle) {
|
|
482
|
-
try {
|
|
483
|
-
this.setMSA(await openLocation(msaFilehandle).readFile('utf8'))
|
|
484
|
-
} catch (e) {
|
|
485
|
-
console.error(e)
|
|
486
|
-
this.setError(e)
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}),
|
|
490
|
-
)
|
|
491
|
-
},
|
|
492
592
|
}))
|
|
593
|
+
|
|
493
594
|
.views(self => {
|
|
494
595
|
let oldBlocksX: number[] = []
|
|
495
596
|
let oldBlocksY: number[] = []
|
|
@@ -561,24 +662,28 @@ const model = types
|
|
|
561
662
|
get blocks2d() {
|
|
562
663
|
return self.blocksY.flatMap(by => self.blocksX.map(bx => [bx, by]))
|
|
563
664
|
},
|
|
665
|
+
|
|
564
666
|
/**
|
|
565
667
|
* #getter
|
|
566
668
|
*/
|
|
567
669
|
get done() {
|
|
568
670
|
return self.initialized && (self.data.msa || self.data.tree)
|
|
569
671
|
},
|
|
672
|
+
|
|
570
673
|
/**
|
|
571
674
|
* #getter
|
|
572
675
|
*/
|
|
573
676
|
get colorScheme() {
|
|
574
677
|
return colorSchemes[self.colorSchemeName]
|
|
575
678
|
},
|
|
679
|
+
|
|
576
680
|
/**
|
|
577
681
|
* #getter
|
|
578
682
|
*/
|
|
579
683
|
get header() {
|
|
580
684
|
return this.MSA?.getHeader() || {}
|
|
581
685
|
},
|
|
686
|
+
|
|
582
687
|
/**
|
|
583
688
|
* #method
|
|
584
689
|
*/
|
|
@@ -586,7 +691,12 @@ const model = types
|
|
|
586
691
|
const matches = name.match(/\S+\/(\d+)-(\d+)/)
|
|
587
692
|
return {
|
|
588
693
|
data: this.MSA?.getRowData(name) || ({} as Record<string, unknown>),
|
|
589
|
-
...(matches && {
|
|
694
|
+
...(matches && {
|
|
695
|
+
range: {
|
|
696
|
+
start: +matches[1],
|
|
697
|
+
end: +matches[2],
|
|
698
|
+
},
|
|
699
|
+
}),
|
|
590
700
|
}
|
|
591
701
|
},
|
|
592
702
|
/**
|
|
@@ -605,7 +715,7 @@ const model = types
|
|
|
605
715
|
* #getter
|
|
606
716
|
*/
|
|
607
717
|
get noTree() {
|
|
608
|
-
return !!this.
|
|
718
|
+
return !!this._tree.noTree
|
|
609
719
|
},
|
|
610
720
|
/**
|
|
611
721
|
* #getter
|
|
@@ -639,12 +749,12 @@ const model = types
|
|
|
639
749
|
* #getter
|
|
640
750
|
*/
|
|
641
751
|
get numColumns() {
|
|
642
|
-
return (
|
|
752
|
+
return (this.MSA?.getWidth() || 0) - this.blanks.length
|
|
643
753
|
},
|
|
644
754
|
/**
|
|
645
755
|
* #getter
|
|
646
756
|
*/
|
|
647
|
-
get
|
|
757
|
+
get _tree(): NodeWithIds {
|
|
648
758
|
return self.data.tree
|
|
649
759
|
? generateNodeIds(parseNewick(self.data.tree))
|
|
650
760
|
: this.MSA?.getTree() || {
|
|
@@ -662,7 +772,8 @@ const model = types
|
|
|
662
772
|
},
|
|
663
773
|
/**
|
|
664
774
|
* #getter
|
|
665
|
-
*/
|
|
775
|
+
*/
|
|
776
|
+
get mouseOverRowName() {
|
|
666
777
|
return self.mouseRow !== undefined
|
|
667
778
|
? this.rowNames[self.mouseRow]
|
|
668
779
|
: undefined
|
|
@@ -679,9 +790,10 @@ const model = types
|
|
|
679
790
|
* #getter
|
|
680
791
|
*/
|
|
681
792
|
get root() {
|
|
682
|
-
let hier = hierarchy(this.
|
|
793
|
+
let hier = hierarchy(this._tree, d => d.branchset)
|
|
683
794
|
.sum(d => (d.branchset ? 0 : 1))
|
|
684
795
|
.sort((a, b) => ascending(a.data.length || 1, b.data.length || 1))
|
|
796
|
+
|
|
685
797
|
if (self.showOnly) {
|
|
686
798
|
const res = hier.find(node => node.data.id === self.showOnly)
|
|
687
799
|
if (res) {
|
|
@@ -692,22 +804,21 @@ const model = types
|
|
|
692
804
|
if (self.collapsed.length) {
|
|
693
805
|
self.collapsed
|
|
694
806
|
.map(collapsedId => hier.find(node => node.data.id === collapsedId))
|
|
695
|
-
.filter(
|
|
807
|
+
.filter(notEmpty)
|
|
696
808
|
.map(node => collapse(node))
|
|
697
809
|
}
|
|
810
|
+
if (self.hidden.length) {
|
|
811
|
+
self.hidden
|
|
812
|
+
.map(hiddenId => hier.find(node => node.data.id === hiddenId))
|
|
813
|
+
.filter(notEmpty)
|
|
814
|
+
.map(node => filterHiddenLeafNodes(node.parent, node.id))
|
|
815
|
+
}
|
|
698
816
|
return hier
|
|
699
817
|
},
|
|
700
818
|
/**
|
|
701
819
|
* #getter
|
|
702
820
|
*/
|
|
703
|
-
get structures(): Record<
|
|
704
|
-
string,
|
|
705
|
-
{
|
|
706
|
-
pdb: string
|
|
707
|
-
startPos: number
|
|
708
|
-
endPos: number
|
|
709
|
-
}[]
|
|
710
|
-
> {
|
|
821
|
+
get structures(): Record<string, Structure[]> {
|
|
711
822
|
return this.MSA?.getStructures() || {}
|
|
712
823
|
},
|
|
713
824
|
/**
|
|
@@ -722,6 +833,7 @@ const model = types
|
|
|
722
833
|
},
|
|
723
834
|
/**
|
|
724
835
|
* #getter
|
|
836
|
+
* widget width minus the tree area gives the space for the MSA
|
|
725
837
|
*/
|
|
726
838
|
get msaAreaWidth() {
|
|
727
839
|
return self.width - self.treeAreaWidth
|
|
@@ -733,8 +845,8 @@ const model = types
|
|
|
733
845
|
const blanks = []
|
|
734
846
|
const strs = this.hierarchy
|
|
735
847
|
.leaves()
|
|
736
|
-
.map(
|
|
737
|
-
.filter((item): item is string
|
|
848
|
+
.map(leaf => this.MSA?.getRow(leaf.data.name))
|
|
849
|
+
.filter((item): item is string => !!item)
|
|
738
850
|
|
|
739
851
|
for (let i = 0; i < strs[0]?.length; i++) {
|
|
740
852
|
let counter = 0
|
|
@@ -753,10 +865,11 @@ const model = types
|
|
|
753
865
|
* #getter
|
|
754
866
|
*/
|
|
755
867
|
get rows() {
|
|
868
|
+
const MSA = this.MSA
|
|
756
869
|
return this.hierarchy
|
|
757
870
|
.leaves()
|
|
758
|
-
.map(
|
|
759
|
-
.filter((f): f is [string, string
|
|
871
|
+
.map(leaf => [leaf.data.name, MSA?.getRow(leaf.data.name)] as const)
|
|
872
|
+
.filter((f): f is [string, string] => !!f[1])
|
|
760
873
|
},
|
|
761
874
|
/**
|
|
762
875
|
* #getter
|
|
@@ -772,6 +885,12 @@ const model = types
|
|
|
772
885
|
get columns2d() {
|
|
773
886
|
return this.rows.map(r => r[1]).map(str => skipBlanks(this.blanks, str))
|
|
774
887
|
},
|
|
888
|
+
/**
|
|
889
|
+
* #getter
|
|
890
|
+
*/
|
|
891
|
+
get fontSize() {
|
|
892
|
+
return Math.max(8, self.rowHeight - 8)
|
|
893
|
+
},
|
|
775
894
|
/**
|
|
776
895
|
* #getter
|
|
777
896
|
*/
|
|
@@ -795,18 +914,15 @@ const model = types
|
|
|
795
914
|
* generates a new tree that is clustered with x,y positions
|
|
796
915
|
*/
|
|
797
916
|
get hierarchy(): HierarchyNode<NodeWithIdsAndLength> {
|
|
798
|
-
const
|
|
917
|
+
const r = this.root
|
|
799
918
|
const clust = cluster<NodeWithIds>()
|
|
800
919
|
.size([this.totalHeight, self.treeWidth])
|
|
801
920
|
.separation(() => 1)
|
|
802
|
-
clust(
|
|
803
|
-
setBrLength(
|
|
804
|
-
|
|
805
|
-
(root.data.length = 0),
|
|
806
|
-
self.treeWidth / maxLength(root),
|
|
807
|
-
)
|
|
808
|
-
return root as HierarchyNode<NodeWithIdsAndLength>
|
|
921
|
+
clust(r)
|
|
922
|
+
setBrLength(r, (r.data.length = 0), self.treeWidth / maxLength(r))
|
|
923
|
+
return r as HierarchyNode<NodeWithIdsAndLength>
|
|
809
924
|
},
|
|
925
|
+
|
|
810
926
|
/**
|
|
811
927
|
* #getter
|
|
812
928
|
*/
|
|
@@ -831,22 +947,36 @@ const model = types
|
|
|
831
947
|
})
|
|
832
948
|
}
|
|
833
949
|
},
|
|
950
|
+
|
|
834
951
|
/**
|
|
835
952
|
* #action
|
|
836
953
|
*/
|
|
837
954
|
doScrollY(deltaY: number) {
|
|
838
955
|
self.scrollY = clamp(-self.totalHeight + 10, self.scrollY + deltaY, 0)
|
|
839
956
|
},
|
|
957
|
+
|
|
840
958
|
/**
|
|
841
959
|
* #action
|
|
842
960
|
*/
|
|
843
961
|
doScrollX(deltaX: number) {
|
|
844
962
|
self.scrollX = clamp(
|
|
845
|
-
-self.numColumns + (self.msaAreaWidth - 100),
|
|
963
|
+
-(self.numColumns * self.colWidth) + (self.msaAreaWidth - 100),
|
|
846
964
|
self.scrollX + deltaX,
|
|
847
965
|
0,
|
|
848
966
|
)
|
|
849
967
|
},
|
|
968
|
+
|
|
969
|
+
/**
|
|
970
|
+
* #action
|
|
971
|
+
*/
|
|
972
|
+
setScrollX(n: number) {
|
|
973
|
+
self.scrollX = clamp(
|
|
974
|
+
-(self.numColumns * self.colWidth) + (self.msaAreaWidth - 100),
|
|
975
|
+
n,
|
|
976
|
+
0,
|
|
977
|
+
)
|
|
978
|
+
},
|
|
979
|
+
|
|
850
980
|
/**
|
|
851
981
|
* #action
|
|
852
982
|
*/
|
|
@@ -879,18 +1009,40 @@ const model = types
|
|
|
879
1009
|
},
|
|
880
1010
|
}))
|
|
881
1011
|
.views(self => ({
|
|
1012
|
+
/**
|
|
1013
|
+
* #getter
|
|
1014
|
+
*/
|
|
1015
|
+
get labelsWidth() {
|
|
1016
|
+
let x = 0
|
|
1017
|
+
const { rowHeight, hierarchy, treeMetadata, fontSize } = self
|
|
1018
|
+
if (rowHeight > 5) {
|
|
1019
|
+
for (const node of hierarchy.leaves()) {
|
|
1020
|
+
x = Math.max(
|
|
1021
|
+
measureText(
|
|
1022
|
+
treeMetadata[node.data.name]?.genome || node.data.name,
|
|
1023
|
+
fontSize,
|
|
1024
|
+
),
|
|
1025
|
+
x,
|
|
1026
|
+
)
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
return x
|
|
1030
|
+
},
|
|
1031
|
+
|
|
882
1032
|
/**
|
|
883
1033
|
* #getter
|
|
884
1034
|
*/
|
|
885
1035
|
get secondaryStructureConsensus() {
|
|
886
1036
|
return self.MSA?.secondaryStructureConsensus
|
|
887
1037
|
},
|
|
1038
|
+
|
|
888
1039
|
/**
|
|
889
1040
|
* #getter
|
|
890
1041
|
*/
|
|
891
1042
|
get seqConsensus() {
|
|
892
1043
|
return self.MSA?.seqConsensus
|
|
893
1044
|
},
|
|
1045
|
+
|
|
894
1046
|
/**
|
|
895
1047
|
* #getter
|
|
896
1048
|
*/
|
|
@@ -905,69 +1057,40 @@ const model = types
|
|
|
905
1057
|
}
|
|
906
1058
|
return ['a']
|
|
907
1059
|
},
|
|
1060
|
+
|
|
908
1061
|
/**
|
|
909
1062
|
* #getter
|
|
910
1063
|
*/
|
|
911
|
-
get
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
}
|
|
924
|
-
})
|
|
925
|
-
: ([] as BasicTrack[])
|
|
1064
|
+
get adapterTrackModels(): BasicTrack[] {
|
|
1065
|
+
return (
|
|
1066
|
+
self.MSA?.tracks.map(t => ({
|
|
1067
|
+
model: {
|
|
1068
|
+
...t,
|
|
1069
|
+
data: t.data ? skipBlanks(self.blanks, t.data) : undefined,
|
|
1070
|
+
height: self.rowHeight,
|
|
1071
|
+
} as TextTrackModel,
|
|
1072
|
+
ReactComponent: TextTrack,
|
|
1073
|
+
})) || []
|
|
1074
|
+
)
|
|
1075
|
+
},
|
|
926
1076
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1077
|
+
/**
|
|
1078
|
+
* #getter
|
|
1079
|
+
*/
|
|
1080
|
+
get boxTrackModels(): BasicTrack[] {
|
|
1081
|
+
return self.boxTracks
|
|
1082
|
+
.filter(track => self.rows.some(row => row[0] === track.name))
|
|
930
1083
|
.map(track => ({
|
|
931
1084
|
model: track as BoxTrackModel,
|
|
932
1085
|
ReactComponent: BoxTrack,
|
|
933
1086
|
}))
|
|
1087
|
+
},
|
|
934
1088
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
features: self.annotatedRegions,
|
|
941
|
-
height: 100,
|
|
942
|
-
id: 'annotations',
|
|
943
|
-
name: 'User-created annotations',
|
|
944
|
-
data: self.annotatedRegions
|
|
945
|
-
.map(region => {
|
|
946
|
-
const attrs = region.attributes
|
|
947
|
-
? Object.entries(region.attributes)
|
|
948
|
-
.map(([k, v]) => `${k}=${v.join(',')}`)
|
|
949
|
-
.join(';')
|
|
950
|
-
: '.'
|
|
951
|
-
return [
|
|
952
|
-
'MSA_refcoord',
|
|
953
|
-
'.',
|
|
954
|
-
'.',
|
|
955
|
-
region.start,
|
|
956
|
-
region.end,
|
|
957
|
-
'.',
|
|
958
|
-
'.',
|
|
959
|
-
'.',
|
|
960
|
-
attrs,
|
|
961
|
-
].join('\t')
|
|
962
|
-
})
|
|
963
|
-
.join('\n'),
|
|
964
|
-
} as BoxTrackModel,
|
|
965
|
-
ReactComponent: BoxTrack,
|
|
966
|
-
},
|
|
967
|
-
]
|
|
968
|
-
: ([] as BasicTrack[])
|
|
969
|
-
|
|
970
|
-
return [...adapterTracks, ...boxTracks, ...annotationTracks]
|
|
1089
|
+
/**
|
|
1090
|
+
* #getter
|
|
1091
|
+
*/
|
|
1092
|
+
get tracks(): BasicTrack[] {
|
|
1093
|
+
return [...this.adapterTrackModels, ...this.boxTrackModels]
|
|
971
1094
|
},
|
|
972
1095
|
/**
|
|
973
1096
|
* #getter
|
|
@@ -975,6 +1098,7 @@ const model = types
|
|
|
975
1098
|
get turnedOnTracks() {
|
|
976
1099
|
return this.tracks.filter(f => !self.turnedOffTracks.has(f.model.id))
|
|
977
1100
|
},
|
|
1101
|
+
|
|
978
1102
|
/**
|
|
979
1103
|
* #method
|
|
980
1104
|
* returns coordinate in the current relative coordinate scheme
|
|
@@ -982,6 +1106,7 @@ const model = types
|
|
|
982
1106
|
pxToBp(coord: number) {
|
|
983
1107
|
return Math.floor((coord - self.scrollX) / self.colWidth)
|
|
984
1108
|
},
|
|
1109
|
+
|
|
985
1110
|
/**
|
|
986
1111
|
* #method
|
|
987
1112
|
*/
|
|
@@ -1016,6 +1141,7 @@ const model = types
|
|
|
1016
1141
|
|
|
1017
1142
|
return i - count
|
|
1018
1143
|
},
|
|
1144
|
+
|
|
1019
1145
|
/**
|
|
1020
1146
|
* #method
|
|
1021
1147
|
*/
|
|
@@ -1031,6 +1157,7 @@ const model = types
|
|
|
1031
1157
|
|
|
1032
1158
|
return position - count
|
|
1033
1159
|
},
|
|
1160
|
+
|
|
1034
1161
|
/**
|
|
1035
1162
|
* #method
|
|
1036
1163
|
*/
|
|
@@ -1052,6 +1179,29 @@ const model = types
|
|
|
1052
1179
|
}
|
|
1053
1180
|
return 0
|
|
1054
1181
|
},
|
|
1182
|
+
|
|
1183
|
+
/**
|
|
1184
|
+
* #method
|
|
1185
|
+
*/
|
|
1186
|
+
relativePxToBp2(rowName: string, position: number) {
|
|
1187
|
+
const { rowNames, rows } = self
|
|
1188
|
+
const index = rowNames.indexOf(rowName)
|
|
1189
|
+
if (index !== -1) {
|
|
1190
|
+
const row = rows[index][1]
|
|
1191
|
+
|
|
1192
|
+
let k = 0
|
|
1193
|
+
let i = 0
|
|
1194
|
+
for (; k < position; i++) {
|
|
1195
|
+
if (row[i] !== '-') {
|
|
1196
|
+
k++
|
|
1197
|
+
} else if (k >= position) {
|
|
1198
|
+
break
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
return i
|
|
1202
|
+
}
|
|
1203
|
+
return 0
|
|
1204
|
+
},
|
|
1055
1205
|
/**
|
|
1056
1206
|
* #method
|
|
1057
1207
|
*/
|
|
@@ -1066,32 +1216,85 @@ const model = types
|
|
|
1066
1216
|
return j
|
|
1067
1217
|
},
|
|
1068
1218
|
}))
|
|
1069
|
-
|
|
1219
|
+
|
|
1220
|
+
.views(self => ({
|
|
1070
1221
|
/**
|
|
1071
|
-
* #
|
|
1222
|
+
* #getter
|
|
1223
|
+
* total height of track area (px)
|
|
1072
1224
|
*/
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
end: number,
|
|
1076
|
-
attributes: Record<string, string[]>,
|
|
1077
|
-
) {
|
|
1078
|
-
self.annotatedRegions.push({
|
|
1079
|
-
start: self.getPos(start),
|
|
1080
|
-
end: self.getPos(end),
|
|
1081
|
-
attributes,
|
|
1082
|
-
})
|
|
1225
|
+
get totalTrackAreaHeight() {
|
|
1226
|
+
return sum(self.turnedOnTracks.map(r => r.model.height))
|
|
1083
1227
|
},
|
|
1228
|
+
}))
|
|
1229
|
+
.actions(self => ({
|
|
1084
1230
|
/**
|
|
1085
1231
|
* #action
|
|
1232
|
+
* internal, used for drawing to canvas
|
|
1086
1233
|
*/
|
|
1087
|
-
|
|
1088
|
-
self.
|
|
1234
|
+
incrementRef() {
|
|
1235
|
+
self.nref++
|
|
1089
1236
|
},
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1237
|
+
afterCreate() {
|
|
1238
|
+
// autorun opens treeFilehandle
|
|
1239
|
+
addDisposer(
|
|
1240
|
+
self,
|
|
1241
|
+
autorun(async () => {
|
|
1242
|
+
const { treeFilehandle } = self
|
|
1243
|
+
if (treeFilehandle) {
|
|
1244
|
+
try {
|
|
1245
|
+
self.setTree(await openLocation(treeFilehandle).readFile('utf8'))
|
|
1246
|
+
} catch (e) {
|
|
1247
|
+
console.error(e)
|
|
1248
|
+
self.setError(e)
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
}),
|
|
1252
|
+
)
|
|
1253
|
+
// autorun opens treeMetadataFilehandle
|
|
1254
|
+
addDisposer(
|
|
1255
|
+
self,
|
|
1256
|
+
autorun(async () => {
|
|
1257
|
+
const { treeMetadataFilehandle } = self
|
|
1258
|
+
if (treeMetadataFilehandle) {
|
|
1259
|
+
try {
|
|
1260
|
+
self.setTreeMetadata(
|
|
1261
|
+
await openLocation(treeMetadataFilehandle).readFile('utf8'),
|
|
1262
|
+
)
|
|
1263
|
+
} catch (e) {
|
|
1264
|
+
console.error(e)
|
|
1265
|
+
self.setError(e)
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
}),
|
|
1269
|
+
)
|
|
1270
|
+
|
|
1271
|
+
// autorun opens msaFilehandle
|
|
1272
|
+
addDisposer(
|
|
1273
|
+
self,
|
|
1274
|
+
autorun(async () => {
|
|
1275
|
+
const { msaFilehandle } = self
|
|
1276
|
+
if (msaFilehandle) {
|
|
1277
|
+
try {
|
|
1278
|
+
self.setMSA(await openLocation(msaFilehandle).readFile('utf8'))
|
|
1279
|
+
} catch (e) {
|
|
1280
|
+
console.error(e)
|
|
1281
|
+
self.setError(e)
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
}),
|
|
1285
|
+
)
|
|
1286
|
+
|
|
1287
|
+
// autorun synchronizes treeWidth with treeAreaWidth
|
|
1288
|
+
addDisposer(
|
|
1289
|
+
self,
|
|
1290
|
+
autorun(async () => {
|
|
1291
|
+
if (self.treeWidthMatchesArea) {
|
|
1292
|
+
self.setTreeWidth(
|
|
1293
|
+
Math.max(50, self.treeAreaWidth - self.labelsWidth - 20),
|
|
1294
|
+
)
|
|
1295
|
+
}
|
|
1296
|
+
}),
|
|
1297
|
+
)
|
|
1095
1298
|
},
|
|
1096
1299
|
}))
|
|
1097
1300
|
.postProcessSnapshot(result => {
|