react-msaview 2.1.1 → 2.1.3
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 +3 -3
- package/dist/components/Header.js +4 -4
- package/dist/components/Header.js.map +1 -1
- package/dist/components/MSAView.js +2 -4
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/Rubberband.js +2 -2
- package/dist/components/Rubberband.js.map +1 -1
- package/dist/components/TreeCanvasBlock.js +9 -6
- package/dist/components/TreeCanvasBlock.js.map +1 -1
- package/dist/components/TreeMenu.js +4 -2
- package/dist/components/TreeMenu.js.map +1 -1
- package/dist/components/dialogs/{DetailsDlg.d.ts → MetadataDlg.d.ts} +2 -2
- package/dist/components/dialogs/{DetailsDlg.js → MetadataDlg.js} +5 -4
- package/dist/components/dialogs/MetadataDlg.js.map +1 -0
- package/dist/components/dialogs/TreeNodeInfoDlg.d.ts +9 -0
- package/dist/components/dialogs/TreeNodeInfoDlg.js +16 -0
- package/dist/components/dialogs/TreeNodeInfoDlg.js.map +1 -0
- package/dist/model.d.ts +336 -13
- package/dist/model.js +382 -30
- package/dist/model.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -2
- package/src/components/Header.tsx +5 -5
- package/src/components/MSAView.tsx +2 -4
- package/src/components/Rubberband.tsx +2 -2
- package/src/components/TreeCanvasBlock.tsx +9 -5
- package/src/components/TreeMenu.tsx +4 -2
- package/src/components/dialogs/{DetailsDlg.tsx → MetadataDlg.tsx} +7 -3
- package/src/components/dialogs/TreeNodeInfoDlg.tsx +38 -0
- package/src/model.ts +440 -113
- package/src/version.ts +1 -1
- package/dist/components/dialogs/DetailsDlg.js.map +0 -1
- package/dist/components/dialogs/MoreInfoDlg.d.ts +0 -6
- package/dist/components/dialogs/MoreInfoDlg.js +0 -11
- package/dist/components/dialogs/MoreInfoDlg.js.map +0 -1
- package/src/components/dialogs/MoreInfoDlg.tsx +0 -21
package/src/model.ts
CHANGED
|
@@ -49,7 +49,10 @@ export interface TextTrackModel extends BasicTrackModel {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export interface BoxTrackModel extends BasicTrackModel {
|
|
52
|
-
features: {
|
|
52
|
+
features: {
|
|
53
|
+
start: number
|
|
54
|
+
end: number
|
|
55
|
+
}[]
|
|
53
56
|
}
|
|
54
57
|
export interface ITextTrack {
|
|
55
58
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -64,65 +67,175 @@ export interface IBoxTrack {
|
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
type BasicTrack = IBoxTrack | ITextTrack
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
70
|
+
type StructureSnap = SnapshotIn<typeof StructureModel>
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* #stateModel MsaView
|
|
74
|
+
*/
|
|
75
|
+
function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
76
|
+
|
|
77
|
+
const model = types
|
|
78
|
+
.compose(
|
|
79
|
+
BaseViewModel,
|
|
80
|
+
types.model('MsaView', {
|
|
81
|
+
/**
|
|
82
|
+
* #property
|
|
83
|
+
*/
|
|
84
|
+
id: ElementId,
|
|
85
|
+
/**
|
|
86
|
+
* #property
|
|
87
|
+
*/
|
|
88
|
+
type: types.literal('MsaView'),
|
|
89
|
+
/**
|
|
90
|
+
* #property
|
|
91
|
+
*/
|
|
92
|
+
height: types.optional(types.number, 550),
|
|
93
|
+
/**
|
|
94
|
+
* #property
|
|
95
|
+
*/
|
|
96
|
+
treeAreaWidth: types.optional(types.number, 400),
|
|
97
|
+
/**
|
|
98
|
+
* #property
|
|
99
|
+
*/
|
|
100
|
+
treeWidth: types.optional(types.number, 300),
|
|
101
|
+
/**
|
|
102
|
+
* #property
|
|
103
|
+
*/
|
|
104
|
+
rowHeight: 20,
|
|
105
|
+
/**
|
|
106
|
+
* #property
|
|
107
|
+
*/
|
|
108
|
+
scrollY: 0,
|
|
109
|
+
/**
|
|
110
|
+
* #property
|
|
111
|
+
*/
|
|
112
|
+
scrollX: 0,
|
|
113
|
+
/**
|
|
114
|
+
* #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
|
|
131
|
+
*/
|
|
132
|
+
selectedStructures: types.array(StructureModel),
|
|
133
|
+
/**
|
|
134
|
+
* #property
|
|
135
|
+
*/
|
|
136
|
+
labelsAlignRight: false,
|
|
137
|
+
/**
|
|
138
|
+
* #property
|
|
139
|
+
*/
|
|
140
|
+
colWidth: 16,
|
|
141
|
+
/**
|
|
142
|
+
* #property
|
|
143
|
+
*/
|
|
144
|
+
showBranchLen: true,
|
|
145
|
+
/**
|
|
146
|
+
* #property
|
|
147
|
+
*/
|
|
148
|
+
bgColor: true,
|
|
149
|
+
/**
|
|
150
|
+
* #property
|
|
151
|
+
*/
|
|
152
|
+
drawTree: true,
|
|
153
|
+
/**
|
|
154
|
+
* #property
|
|
155
|
+
*/
|
|
156
|
+
drawNodeBubbles: true,
|
|
157
|
+
/**
|
|
158
|
+
* #property
|
|
159
|
+
*/
|
|
160
|
+
highResScaleFactor: 2,
|
|
161
|
+
/**
|
|
162
|
+
* #property
|
|
163
|
+
*/
|
|
164
|
+
colorSchemeName: 'maeditor',
|
|
165
|
+
/**
|
|
166
|
+
* #property
|
|
167
|
+
*/
|
|
168
|
+
treeFilehandle: types.maybe(FileLocation),
|
|
169
|
+
/**
|
|
170
|
+
* #property
|
|
171
|
+
*/
|
|
172
|
+
msaFilehandle: types.maybe(FileLocation),
|
|
173
|
+
/**
|
|
174
|
+
* #property
|
|
175
|
+
*/
|
|
176
|
+
treeMetadataFilehandle: types.maybe(FileLocation),
|
|
177
|
+
/**
|
|
178
|
+
* #property
|
|
179
|
+
*/
|
|
180
|
+
currentAlignment: 0,
|
|
181
|
+
/**
|
|
182
|
+
* #property
|
|
183
|
+
*/
|
|
184
|
+
collapsed: types.array(types.string),
|
|
185
|
+
/**
|
|
186
|
+
* #property
|
|
187
|
+
*/
|
|
188
|
+
showOnly: types.maybe(types.string),
|
|
189
|
+
/**
|
|
190
|
+
* #property
|
|
191
|
+
*/
|
|
192
|
+
boxTracks: types.array(UniprotTrack),
|
|
193
|
+
/**
|
|
194
|
+
* #property
|
|
195
|
+
*/
|
|
196
|
+
turnedOffTracks: types.map(types.boolean),
|
|
197
|
+
/**
|
|
198
|
+
* #property
|
|
199
|
+
*/
|
|
200
|
+
annotatedRegions: types.array(
|
|
201
|
+
types.model({
|
|
202
|
+
start: types.number,
|
|
203
|
+
end: types.number,
|
|
204
|
+
attributes: types.frozen<Record<string, string[]>>(),
|
|
205
|
+
}),
|
|
206
|
+
),
|
|
207
|
+
/**
|
|
208
|
+
* #property
|
|
209
|
+
*/
|
|
210
|
+
data: types.optional(
|
|
211
|
+
types
|
|
212
|
+
.model({
|
|
213
|
+
tree: types.maybe(types.string),
|
|
214
|
+
msa: types.maybe(types.string),
|
|
215
|
+
treeMetadata: types.maybe(types.string),
|
|
216
|
+
})
|
|
217
|
+
.actions(self => ({
|
|
218
|
+
setTree(tree?: string) {
|
|
219
|
+
self.tree = tree
|
|
220
|
+
},
|
|
221
|
+
setMSA(msa?: string) {
|
|
222
|
+
self.msa = msa
|
|
223
|
+
},
|
|
224
|
+
setTreeMetadata(treeMetadata?: string) {
|
|
225
|
+
self.treeMetadata = treeMetadata
|
|
226
|
+
},
|
|
227
|
+
})),
|
|
228
|
+
{ tree: '', msa: '' },
|
|
229
|
+
),
|
|
230
|
+
}),
|
|
231
|
+
)
|
|
122
232
|
.volatile(() => ({
|
|
123
233
|
rulerHeight: 20,
|
|
124
234
|
error: undefined as unknown,
|
|
125
|
-
margin: {
|
|
235
|
+
margin: {
|
|
236
|
+
left: 20,
|
|
237
|
+
top: 20,
|
|
238
|
+
},
|
|
126
239
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
127
240
|
DialogComponent: undefined as undefined | React.FC<any>,
|
|
128
241
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -132,23 +245,38 @@ const MSAModel = types
|
|
|
132
245
|
annotPos: undefined as { left: number; right: number } | undefined,
|
|
133
246
|
}))
|
|
134
247
|
.actions(self => ({
|
|
248
|
+
/**
|
|
249
|
+
* #action
|
|
250
|
+
*/
|
|
135
251
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
136
|
-
setDialogComponent(dlg
|
|
252
|
+
setDialogComponent(dlg?: React.FC<any>, props?: any) {
|
|
137
253
|
self.DialogComponent = dlg
|
|
138
254
|
self.DialogProps = props
|
|
139
255
|
},
|
|
256
|
+
/**
|
|
257
|
+
* #action
|
|
258
|
+
*/
|
|
140
259
|
setHeight(height: number) {
|
|
141
260
|
self.height = height
|
|
142
261
|
},
|
|
143
|
-
|
|
262
|
+
/**
|
|
263
|
+
* #action
|
|
264
|
+
*/
|
|
265
|
+
addStructureToSelection(elt: StructureSnap) {
|
|
144
266
|
self.selectedStructures.push(elt)
|
|
145
267
|
},
|
|
146
|
-
|
|
268
|
+
/**
|
|
269
|
+
* #action
|
|
270
|
+
*/
|
|
271
|
+
removeStructureFromSelection(elt: StructureSnap) {
|
|
147
272
|
const r = self.selectedStructures.find(node => node.id === elt.id)
|
|
148
273
|
if (r) {
|
|
149
274
|
self.selectedStructures.remove(r)
|
|
150
275
|
}
|
|
151
276
|
},
|
|
277
|
+
/**
|
|
278
|
+
* #action
|
|
279
|
+
*/
|
|
152
280
|
toggleStructureSelection(elt: {
|
|
153
281
|
id: string
|
|
154
282
|
structure: { startPos: number; endPos: number; pdb: string }
|
|
@@ -160,47 +288,88 @@ const MSAModel = types
|
|
|
160
288
|
self.selectedStructures.push(elt)
|
|
161
289
|
}
|
|
162
290
|
},
|
|
291
|
+
/**
|
|
292
|
+
* #action
|
|
293
|
+
*/
|
|
163
294
|
clearSelectedStructures() {
|
|
164
|
-
|
|
165
|
-
self.selectedStructures = []
|
|
295
|
+
self.selectedStructures = cast([])
|
|
166
296
|
},
|
|
297
|
+
/**
|
|
298
|
+
* #action
|
|
299
|
+
*/
|
|
167
300
|
setError(error?: unknown) {
|
|
168
301
|
self.error = error
|
|
169
302
|
},
|
|
303
|
+
/**
|
|
304
|
+
* #action
|
|
305
|
+
*/
|
|
170
306
|
setMousePos(col?: number, row?: number) {
|
|
171
307
|
self.mouseCol = col
|
|
172
308
|
self.mouseRow = row
|
|
173
309
|
},
|
|
310
|
+
/**
|
|
311
|
+
* #action
|
|
312
|
+
*/
|
|
174
313
|
setRowHeight(n: number) {
|
|
175
314
|
self.rowHeight = n
|
|
176
315
|
},
|
|
316
|
+
/**
|
|
317
|
+
* #action
|
|
318
|
+
*/
|
|
177
319
|
setColWidth(n: number) {
|
|
178
320
|
self.colWidth = n
|
|
179
321
|
},
|
|
322
|
+
/**
|
|
323
|
+
* #action
|
|
324
|
+
*/
|
|
180
325
|
setColorSchemeName(name: string) {
|
|
181
326
|
self.colorSchemeName = name
|
|
182
327
|
},
|
|
328
|
+
/**
|
|
329
|
+
* #action
|
|
330
|
+
*/
|
|
183
331
|
setScrollY(n: number) {
|
|
184
332
|
self.scrollY = n
|
|
185
333
|
},
|
|
334
|
+
/**
|
|
335
|
+
* #action
|
|
336
|
+
*/
|
|
186
337
|
setScrollX(n: number) {
|
|
187
338
|
self.scrollX = n
|
|
188
339
|
},
|
|
340
|
+
/**
|
|
341
|
+
* #action
|
|
342
|
+
*/
|
|
189
343
|
setTreeAreaWidth(n: number) {
|
|
190
344
|
self.treeAreaWidth = n
|
|
191
345
|
},
|
|
346
|
+
/**
|
|
347
|
+
* #action
|
|
348
|
+
*/
|
|
192
349
|
setTreeWidth(n: number) {
|
|
193
350
|
self.treeWidth = n
|
|
194
351
|
},
|
|
352
|
+
/**
|
|
353
|
+
* #action
|
|
354
|
+
*/
|
|
195
355
|
setCurrentAlignment(n: number) {
|
|
196
356
|
self.currentAlignment = n
|
|
197
357
|
},
|
|
358
|
+
/**
|
|
359
|
+
* #action
|
|
360
|
+
*/
|
|
198
361
|
toggleLabelsAlignRight() {
|
|
199
362
|
self.labelsAlignRight = !self.labelsAlignRight
|
|
200
363
|
},
|
|
364
|
+
/**
|
|
365
|
+
* #action
|
|
366
|
+
*/
|
|
201
367
|
toggleDrawTree() {
|
|
202
368
|
self.drawTree = !self.drawTree
|
|
203
369
|
},
|
|
370
|
+
/**
|
|
371
|
+
* #action
|
|
372
|
+
*/
|
|
204
373
|
toggleCollapsed(node: string) {
|
|
205
374
|
if (self.collapsed.includes(node)) {
|
|
206
375
|
self.collapsed.remove(node)
|
|
@@ -208,24 +377,45 @@ const MSAModel = types
|
|
|
208
377
|
self.collapsed.push(node)
|
|
209
378
|
}
|
|
210
379
|
},
|
|
380
|
+
/**
|
|
381
|
+
* #action
|
|
382
|
+
*/
|
|
211
383
|
setShowOnly(node?: string) {
|
|
212
384
|
self.showOnly = node
|
|
213
385
|
},
|
|
386
|
+
/**
|
|
387
|
+
* #action
|
|
388
|
+
*/
|
|
214
389
|
toggleBranchLen() {
|
|
215
390
|
self.showBranchLen = !self.showBranchLen
|
|
216
391
|
},
|
|
392
|
+
/**
|
|
393
|
+
* #action
|
|
394
|
+
*/
|
|
217
395
|
toggleBgColor() {
|
|
218
396
|
self.bgColor = !self.bgColor
|
|
219
397
|
},
|
|
398
|
+
/**
|
|
399
|
+
* #action
|
|
400
|
+
*/
|
|
220
401
|
toggleNodeBubbles() {
|
|
221
402
|
self.drawNodeBubbles = !self.drawNodeBubbles
|
|
222
403
|
},
|
|
404
|
+
/**
|
|
405
|
+
* #action
|
|
406
|
+
*/
|
|
223
407
|
setData(data: { msa?: string; tree?: string }) {
|
|
224
408
|
self.data = cast(data)
|
|
225
409
|
},
|
|
410
|
+
/**
|
|
411
|
+
* #action
|
|
412
|
+
*/
|
|
226
413
|
async setMSAFilehandle(msaFilehandle?: FileLocationType) {
|
|
227
414
|
self.msaFilehandle = msaFilehandle
|
|
228
415
|
},
|
|
416
|
+
/**
|
|
417
|
+
* #action
|
|
418
|
+
*/
|
|
229
419
|
async setTreeFilehandle(treeFilehandle?: FileLocationType) {
|
|
230
420
|
if (treeFilehandle && 'blobId' in treeFilehandle) {
|
|
231
421
|
const r = await openLocation(treeFilehandle).readFile('utf8')
|
|
@@ -234,12 +424,24 @@ const MSAModel = types
|
|
|
234
424
|
self.treeFilehandle = treeFilehandle
|
|
235
425
|
}
|
|
236
426
|
},
|
|
427
|
+
/**
|
|
428
|
+
* #action
|
|
429
|
+
*/
|
|
237
430
|
setMSA(result: string) {
|
|
238
431
|
self.data.setMSA(result)
|
|
239
432
|
},
|
|
433
|
+
/**
|
|
434
|
+
* #action
|
|
435
|
+
*/
|
|
240
436
|
setTree(result: string) {
|
|
241
437
|
self.data.setTree(result)
|
|
242
438
|
},
|
|
439
|
+
/**
|
|
440
|
+
* #action
|
|
441
|
+
*/
|
|
442
|
+
setTreeMetadata(result: string) {
|
|
443
|
+
self.data.setTreeMetadata(result)
|
|
444
|
+
},
|
|
243
445
|
|
|
244
446
|
afterCreate() {
|
|
245
447
|
addDisposer(
|
|
@@ -256,6 +458,22 @@ const MSAModel = types
|
|
|
256
458
|
}
|
|
257
459
|
}),
|
|
258
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
|
+
)
|
|
259
477
|
addDisposer(
|
|
260
478
|
self,
|
|
261
479
|
autorun(async () => {
|
|
@@ -278,6 +496,9 @@ const MSAModel = types
|
|
|
278
496
|
let oldValX = 0
|
|
279
497
|
let oldValY = 0
|
|
280
498
|
return {
|
|
499
|
+
/**
|
|
500
|
+
* #getter
|
|
501
|
+
*/
|
|
281
502
|
get initialized() {
|
|
282
503
|
return (
|
|
283
504
|
(self.data.msa ||
|
|
@@ -287,7 +508,9 @@ const MSAModel = types
|
|
|
287
508
|
!self.error
|
|
288
509
|
)
|
|
289
510
|
},
|
|
290
|
-
|
|
511
|
+
/**
|
|
512
|
+
* #getter
|
|
513
|
+
*/
|
|
291
514
|
get blocksX() {
|
|
292
515
|
const { scrollX, blockSize: size, colWidth } = self
|
|
293
516
|
const ret = -(size * Math.floor(scrollX / size)) - size
|
|
@@ -307,7 +530,9 @@ const MSAModel = types
|
|
|
307
530
|
}
|
|
308
531
|
return oldBlocksX
|
|
309
532
|
},
|
|
310
|
-
|
|
533
|
+
/**
|
|
534
|
+
* #getter
|
|
535
|
+
*/
|
|
311
536
|
get blocksY() {
|
|
312
537
|
const { scrollY, blockSize: size, rowHeight } = self
|
|
313
538
|
const ret = -(size * Math.floor(scrollY / size)) - 2 * size
|
|
@@ -330,21 +555,33 @@ const MSAModel = types
|
|
|
330
555
|
}
|
|
331
556
|
})
|
|
332
557
|
.views(self => ({
|
|
558
|
+
/**
|
|
559
|
+
* #getter
|
|
560
|
+
*/
|
|
333
561
|
get blocks2d() {
|
|
334
562
|
return self.blocksY.flatMap(by => self.blocksX.map(bx => [bx, by]))
|
|
335
563
|
},
|
|
564
|
+
/**
|
|
565
|
+
* #getter
|
|
566
|
+
*/
|
|
336
567
|
get done() {
|
|
337
568
|
return self.initialized && (self.data.msa || self.data.tree)
|
|
338
569
|
},
|
|
339
|
-
|
|
570
|
+
/**
|
|
571
|
+
* #getter
|
|
572
|
+
*/
|
|
340
573
|
get colorScheme() {
|
|
341
574
|
return colorSchemes[self.colorSchemeName]
|
|
342
575
|
},
|
|
343
|
-
|
|
576
|
+
/**
|
|
577
|
+
* #getter
|
|
578
|
+
*/
|
|
344
579
|
get header() {
|
|
345
580
|
return this.MSA?.getHeader() || {}
|
|
346
581
|
},
|
|
347
|
-
|
|
582
|
+
/**
|
|
583
|
+
* #method
|
|
584
|
+
*/
|
|
348
585
|
getRowData(name: string) {
|
|
349
586
|
const matches = name.match(/\S+\/(\d+)-(\d+)/)
|
|
350
587
|
return {
|
|
@@ -352,23 +589,39 @@ const MSAModel = types
|
|
|
352
589
|
...(matches && { range: { start: +matches[1], end: +matches[2] } }),
|
|
353
590
|
}
|
|
354
591
|
},
|
|
355
|
-
|
|
592
|
+
/**
|
|
593
|
+
* #getter
|
|
594
|
+
*/
|
|
356
595
|
get currentAlignmentName() {
|
|
357
596
|
return this.alignmentNames[self.currentAlignment]
|
|
358
597
|
},
|
|
359
|
-
|
|
598
|
+
/**
|
|
599
|
+
* #getter
|
|
600
|
+
*/
|
|
360
601
|
get alignmentNames() {
|
|
361
602
|
return this.MSA?.alignmentNames || []
|
|
362
603
|
},
|
|
363
|
-
|
|
604
|
+
/**
|
|
605
|
+
* #getter
|
|
606
|
+
*/
|
|
364
607
|
get noTree() {
|
|
365
608
|
return !!this.tree.noTree
|
|
366
609
|
},
|
|
367
|
-
|
|
610
|
+
/**
|
|
611
|
+
* #getter
|
|
612
|
+
*/
|
|
368
613
|
get menuItems() {
|
|
369
614
|
return []
|
|
370
615
|
},
|
|
371
|
-
|
|
616
|
+
/**
|
|
617
|
+
* #getter
|
|
618
|
+
*/
|
|
619
|
+
get treeMetadata() {
|
|
620
|
+
return self.data.treeMetadata ? JSON.parse(self.data.treeMetadata) : {}
|
|
621
|
+
},
|
|
622
|
+
/**
|
|
623
|
+
* #getter
|
|
624
|
+
*/
|
|
372
625
|
get MSA() {
|
|
373
626
|
const text = self.data.msa
|
|
374
627
|
if (text) {
|
|
@@ -382,11 +635,15 @@ const MSAModel = types
|
|
|
382
635
|
}
|
|
383
636
|
return null
|
|
384
637
|
},
|
|
385
|
-
|
|
638
|
+
/**
|
|
639
|
+
* #getter
|
|
640
|
+
*/
|
|
386
641
|
get numColumns() {
|
|
387
642
|
return ((this.MSA?.getWidth() || 0) - this.blanks.length) * self.colWidth
|
|
388
643
|
},
|
|
389
|
-
|
|
644
|
+
/**
|
|
645
|
+
* #getter
|
|
646
|
+
*/
|
|
390
647
|
get tree(): NodeWithIds {
|
|
391
648
|
return self.data.tree
|
|
392
649
|
? generateNodeIds(parseNewick(self.data.tree))
|
|
@@ -397,21 +654,30 @@ const MSAModel = types
|
|
|
397
654
|
name: 'empty',
|
|
398
655
|
}
|
|
399
656
|
},
|
|
400
|
-
|
|
657
|
+
/**
|
|
658
|
+
* #getter
|
|
659
|
+
*/
|
|
401
660
|
get rowNames(): string[] {
|
|
402
661
|
return this.hierarchy.leaves().map(node => node.data.name)
|
|
403
662
|
},
|
|
404
|
-
|
|
405
|
-
|
|
663
|
+
/**
|
|
664
|
+
* #getter
|
|
665
|
+
*/ get mouseOverRowName() {
|
|
406
666
|
return self.mouseRow !== undefined
|
|
407
667
|
? this.rowNames[self.mouseRow]
|
|
408
668
|
: undefined
|
|
409
669
|
},
|
|
410
670
|
|
|
671
|
+
/**
|
|
672
|
+
* #method
|
|
673
|
+
*/
|
|
411
674
|
getMouseOverResidue(rowName: string) {
|
|
412
675
|
return this.columns[rowName]
|
|
413
676
|
},
|
|
414
677
|
|
|
678
|
+
/**
|
|
679
|
+
* #getter
|
|
680
|
+
*/
|
|
415
681
|
get root() {
|
|
416
682
|
let hier = hierarchy(this.tree, d => d.branchset)
|
|
417
683
|
.sum(d => (d.branchset ? 0 : 1))
|
|
@@ -431,7 +697,9 @@ const MSAModel = types
|
|
|
431
697
|
}
|
|
432
698
|
return hier
|
|
433
699
|
},
|
|
434
|
-
|
|
700
|
+
/**
|
|
701
|
+
* #getter
|
|
702
|
+
*/
|
|
435
703
|
get structures(): Record<
|
|
436
704
|
string,
|
|
437
705
|
{
|
|
@@ -442,7 +710,9 @@ const MSAModel = types
|
|
|
442
710
|
> {
|
|
443
711
|
return this.MSA?.getStructures() || {}
|
|
444
712
|
},
|
|
445
|
-
|
|
713
|
+
/**
|
|
714
|
+
* #getter
|
|
715
|
+
*/
|
|
446
716
|
get inverseStructures() {
|
|
447
717
|
return Object.fromEntries(
|
|
448
718
|
Object.entries(this.structures).flatMap(([key, val]) =>
|
|
@@ -450,12 +720,15 @@ const MSAModel = types
|
|
|
450
720
|
),
|
|
451
721
|
)
|
|
452
722
|
},
|
|
453
|
-
|
|
723
|
+
/**
|
|
724
|
+
* #getter
|
|
725
|
+
*/
|
|
454
726
|
get msaAreaWidth() {
|
|
455
|
-
// @ts-expect-error
|
|
456
727
|
return self.width - self.treeAreaWidth
|
|
457
728
|
},
|
|
458
|
-
|
|
729
|
+
/**
|
|
730
|
+
* #getter
|
|
731
|
+
*/
|
|
459
732
|
get blanks() {
|
|
460
733
|
const blanks = []
|
|
461
734
|
const strs = this.hierarchy
|
|
@@ -476,24 +749,32 @@ const MSAModel = types
|
|
|
476
749
|
}
|
|
477
750
|
return blanks
|
|
478
751
|
},
|
|
479
|
-
|
|
752
|
+
/**
|
|
753
|
+
* #getter
|
|
754
|
+
*/
|
|
480
755
|
get rows() {
|
|
481
756
|
return this.hierarchy
|
|
482
757
|
.leaves()
|
|
483
758
|
.map(({ data }) => [data.name, this.MSA?.getRow(data.name)] as const)
|
|
484
759
|
.filter((f): f is [string, string[]] => !!f[1])
|
|
485
760
|
},
|
|
486
|
-
|
|
761
|
+
/**
|
|
762
|
+
* #getter
|
|
763
|
+
*/
|
|
487
764
|
get columns() {
|
|
488
765
|
return Object.fromEntries(
|
|
489
766
|
this.rows.map((row, index) => [row[0], this.columns2d[index]] as const),
|
|
490
767
|
)
|
|
491
768
|
},
|
|
492
|
-
|
|
769
|
+
/**
|
|
770
|
+
* #getter
|
|
771
|
+
*/
|
|
493
772
|
get columns2d() {
|
|
494
773
|
return this.rows.map(r => r[1]).map(str => skipBlanks(this.blanks, str))
|
|
495
774
|
},
|
|
496
|
-
|
|
775
|
+
/**
|
|
776
|
+
* #getter
|
|
777
|
+
*/
|
|
497
778
|
get colStats() {
|
|
498
779
|
const r = [] as Record<string, number>[]
|
|
499
780
|
const columns = this.columns2d
|
|
@@ -509,8 +790,10 @@ const MSAModel = types
|
|
|
509
790
|
}
|
|
510
791
|
return r
|
|
511
792
|
},
|
|
512
|
-
|
|
513
|
-
|
|
793
|
+
/**
|
|
794
|
+
* #getter
|
|
795
|
+
* generates a new tree that is clustered with x,y positions
|
|
796
|
+
*/
|
|
514
797
|
get hierarchy(): HierarchyNode<NodeWithIdsAndLength> {
|
|
515
798
|
const root = this.root
|
|
516
799
|
const clust = cluster<NodeWithIds>()
|
|
@@ -524,12 +807,17 @@ const MSAModel = types
|
|
|
524
807
|
)
|
|
525
808
|
return root as HierarchyNode<NodeWithIdsAndLength>
|
|
526
809
|
},
|
|
527
|
-
|
|
810
|
+
/**
|
|
811
|
+
* #getter
|
|
812
|
+
*/
|
|
528
813
|
get totalHeight() {
|
|
529
814
|
return this.root.leaves().length * self.rowHeight
|
|
530
815
|
},
|
|
531
816
|
}))
|
|
532
817
|
.actions(self => ({
|
|
818
|
+
/**
|
|
819
|
+
* #action
|
|
820
|
+
*/
|
|
533
821
|
addUniprotTrack(node: { name: string; accession: string }) {
|
|
534
822
|
if (self.boxTracks.some(t => t.name === node.name)) {
|
|
535
823
|
if (self.turnedOffTracks.has(node.name)) {
|
|
@@ -543,11 +831,15 @@ const MSAModel = types
|
|
|
543
831
|
})
|
|
544
832
|
}
|
|
545
833
|
},
|
|
546
|
-
|
|
834
|
+
/**
|
|
835
|
+
* #action
|
|
836
|
+
*/
|
|
547
837
|
doScrollY(deltaY: number) {
|
|
548
838
|
self.scrollY = clamp(-self.totalHeight + 10, self.scrollY + deltaY, 0)
|
|
549
839
|
},
|
|
550
|
-
|
|
840
|
+
/**
|
|
841
|
+
* #action
|
|
842
|
+
*/
|
|
551
843
|
doScrollX(deltaX: number) {
|
|
552
844
|
self.scrollX = clamp(
|
|
553
845
|
-self.numColumns + (self.msaAreaWidth - 100),
|
|
@@ -555,6 +847,9 @@ const MSAModel = types
|
|
|
555
847
|
0,
|
|
556
848
|
)
|
|
557
849
|
},
|
|
850
|
+
/**
|
|
851
|
+
* #action
|
|
852
|
+
*/
|
|
558
853
|
setMouseoveredColumn(n: number, chain: string, file: string) {
|
|
559
854
|
let j = 0
|
|
560
855
|
let i = 0
|
|
@@ -572,7 +867,9 @@ const MSAModel = types
|
|
|
572
867
|
self.mouseCol = undefined
|
|
573
868
|
}
|
|
574
869
|
},
|
|
575
|
-
|
|
870
|
+
/**
|
|
871
|
+
* #action
|
|
872
|
+
*/
|
|
576
873
|
toggleTrack(id: string) {
|
|
577
874
|
if (self.turnedOffTracks.has(id)) {
|
|
578
875
|
self.turnedOffTracks.delete(id)
|
|
@@ -582,14 +879,21 @@ const MSAModel = types
|
|
|
582
879
|
},
|
|
583
880
|
}))
|
|
584
881
|
.views(self => ({
|
|
882
|
+
/**
|
|
883
|
+
* #getter
|
|
884
|
+
*/
|
|
585
885
|
get secondaryStructureConsensus() {
|
|
586
886
|
return self.MSA?.secondaryStructureConsensus
|
|
587
887
|
},
|
|
588
|
-
|
|
888
|
+
/**
|
|
889
|
+
* #getter
|
|
890
|
+
*/
|
|
589
891
|
get seqConsensus() {
|
|
590
892
|
return self.MSA?.seqConsensus
|
|
591
893
|
},
|
|
592
|
-
|
|
894
|
+
/**
|
|
895
|
+
* #getter
|
|
896
|
+
*/
|
|
593
897
|
get conservation() {
|
|
594
898
|
if (self.columns2d.length) {
|
|
595
899
|
for (let i = 0; i < self.columns2d[0].length; i++) {
|
|
@@ -601,7 +905,9 @@ const MSAModel = types
|
|
|
601
905
|
}
|
|
602
906
|
return ['a']
|
|
603
907
|
},
|
|
604
|
-
|
|
908
|
+
/**
|
|
909
|
+
* #getter
|
|
910
|
+
*/
|
|
605
911
|
get tracks(): BasicTrack[] {
|
|
606
912
|
const blanks = self.blanks
|
|
607
913
|
const adapterTracks = self.MSA
|
|
@@ -663,16 +969,22 @@ const MSAModel = types
|
|
|
663
969
|
|
|
664
970
|
return [...adapterTracks, ...boxTracks, ...annotationTracks]
|
|
665
971
|
},
|
|
666
|
-
|
|
972
|
+
/**
|
|
973
|
+
* #getter
|
|
974
|
+
*/
|
|
667
975
|
get turnedOnTracks() {
|
|
668
976
|
return this.tracks.filter(f => !self.turnedOffTracks.has(f.model.id))
|
|
669
977
|
},
|
|
670
|
-
|
|
671
|
-
|
|
978
|
+
/**
|
|
979
|
+
* #method
|
|
980
|
+
* returns coordinate in the current relative coordinate scheme
|
|
981
|
+
*/
|
|
672
982
|
pxToBp(coord: number) {
|
|
673
983
|
return Math.floor((coord - self.scrollX) / self.colWidth)
|
|
674
984
|
},
|
|
675
|
-
|
|
985
|
+
/**
|
|
986
|
+
* #method
|
|
987
|
+
*/
|
|
676
988
|
rowSpecificBpToPx(rowName: string, position: number) {
|
|
677
989
|
const { rowNames, rows, blanks } = self
|
|
678
990
|
const index = rowNames.indexOf(rowName)
|
|
@@ -680,6 +992,7 @@ const MSAModel = types
|
|
|
680
992
|
const details = self.getRowData(rowName)
|
|
681
993
|
const offset = details.range?.start || 0
|
|
682
994
|
const current = position - offset
|
|
995
|
+
const s = new Set(self.blanks)
|
|
683
996
|
|
|
684
997
|
if (current < 0) {
|
|
685
998
|
return 0
|
|
@@ -696,24 +1009,31 @@ const MSAModel = types
|
|
|
696
1009
|
|
|
697
1010
|
let count = 0
|
|
698
1011
|
for (let k = 0; k < row.length; k++) {
|
|
699
|
-
if (
|
|
1012
|
+
if (s.has(k) && k < i + 1) {
|
|
700
1013
|
count++
|
|
701
1014
|
}
|
|
702
1015
|
}
|
|
703
1016
|
|
|
704
1017
|
return i - count
|
|
705
1018
|
},
|
|
1019
|
+
/**
|
|
1020
|
+
* #method
|
|
1021
|
+
*/
|
|
706
1022
|
globalBpToPx(position: number) {
|
|
707
1023
|
let count = 0
|
|
1024
|
+
const s = new Set(self.blanks)
|
|
1025
|
+
|
|
708
1026
|
for (let k = 0; k < self.rows[0]?.[1].length; k++) {
|
|
709
|
-
if (
|
|
1027
|
+
if (s.has(k) && k < position + 1) {
|
|
710
1028
|
count++
|
|
711
1029
|
}
|
|
712
1030
|
}
|
|
713
1031
|
|
|
714
1032
|
return position - count
|
|
715
1033
|
},
|
|
716
|
-
|
|
1034
|
+
/**
|
|
1035
|
+
* #method
|
|
1036
|
+
*/
|
|
717
1037
|
relativePxToBp(rowName: string, position: number) {
|
|
718
1038
|
const { rowNames, rows } = self
|
|
719
1039
|
const index = rowNames.indexOf(rowName)
|
|
@@ -732,7 +1052,9 @@ const MSAModel = types
|
|
|
732
1052
|
}
|
|
733
1053
|
return 0
|
|
734
1054
|
},
|
|
735
|
-
|
|
1055
|
+
/**
|
|
1056
|
+
* #method
|
|
1057
|
+
*/
|
|
736
1058
|
getPos(pos: number) {
|
|
737
1059
|
let j = 0
|
|
738
1060
|
for (let i = 0, k = 0; i < pos; i++, j++) {
|
|
@@ -745,6 +1067,9 @@ const MSAModel = types
|
|
|
745
1067
|
},
|
|
746
1068
|
}))
|
|
747
1069
|
.actions(self => ({
|
|
1070
|
+
/**
|
|
1071
|
+
* #action
|
|
1072
|
+
*/
|
|
748
1073
|
addAnnotation(
|
|
749
1074
|
start: number,
|
|
750
1075
|
end: number,
|
|
@@ -756,21 +1081,23 @@ const MSAModel = types
|
|
|
756
1081
|
attributes,
|
|
757
1082
|
})
|
|
758
1083
|
},
|
|
759
|
-
|
|
760
|
-
|
|
1084
|
+
/**
|
|
1085
|
+
* #action
|
|
1086
|
+
*/
|
|
1087
|
+
setAnnotationClickBoundaries(left: number, right: number) {
|
|
761
1088
|
self.annotPos = { left, right }
|
|
762
1089
|
},
|
|
763
|
-
|
|
764
|
-
|
|
1090
|
+
/**
|
|
1091
|
+
* #action
|
|
1092
|
+
*/
|
|
1093
|
+
clearAnnotationClickBoundaries() {
|
|
765
1094
|
self.annotPos = undefined
|
|
766
1095
|
},
|
|
767
1096
|
}))
|
|
768
|
-
|
|
769
|
-
const model = types.snapshotProcessor(types.compose(BaseViewModel, MSAModel), {
|
|
770
|
-
postProcessor(result) {
|
|
1097
|
+
.postProcessSnapshot(result => {
|
|
771
1098
|
const snap = result as Omit<typeof result, symbol>
|
|
772
1099
|
const {
|
|
773
|
-
data: { tree, msa },
|
|
1100
|
+
data: { tree, msa, treeMetadata },
|
|
774
1101
|
...rest
|
|
775
1102
|
} = snap
|
|
776
1103
|
|
|
@@ -781,11 +1108,11 @@ const model = types.snapshotProcessor(types.compose(BaseViewModel, MSAModel), {
|
|
|
781
1108
|
// https://andreasimonecosta.dev/posts/the-shortest-way-to-conditionally-insert-properties-into-an-object-literal/
|
|
782
1109
|
...(!result.treeFilehandle && { tree }),
|
|
783
1110
|
...(!result.msaFilehandle && { msa }),
|
|
1111
|
+
...(!result.treeMetadataFilehandle && { treeMetadata }),
|
|
784
1112
|
},
|
|
785
1113
|
...rest,
|
|
786
1114
|
}
|
|
787
|
-
}
|
|
788
|
-
})
|
|
1115
|
+
})
|
|
789
1116
|
|
|
790
1117
|
export default model
|
|
791
1118
|
|