react-msaview 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/bundle/index.js +31 -31
  2. package/dist/components/Header.js +4 -9
  3. package/dist/components/Header.js.map +1 -1
  4. package/dist/components/HeaderInfoArea.d.ts +6 -0
  5. package/dist/components/HeaderInfoArea.js +12 -0
  6. package/dist/components/HeaderInfoArea.js.map +1 -0
  7. package/dist/components/MSAPanel/Loading.d.ts +2 -0
  8. package/dist/components/MSAPanel/Loading.js +12 -0
  9. package/dist/components/MSAPanel/Loading.js.map +1 -0
  10. package/dist/components/MSAPanel/MSACanvas.js +1 -10
  11. package/dist/components/MSAPanel/MSACanvas.js.map +1 -1
  12. package/dist/components/MSAPanel/MSAMouseoverCanvas.js +1 -22
  13. package/dist/components/MSAPanel/MSAMouseoverCanvas.js.map +1 -1
  14. package/dist/components/MSAPanel/renderMSABlock.js +0 -1
  15. package/dist/components/MSAPanel/renderMSABlock.js.map +1 -1
  16. package/dist/components/MSAPanel/renderMSAMouseover.d.ts +5 -0
  17. package/dist/components/MSAPanel/renderMSAMouseover.js +24 -0
  18. package/dist/components/MSAPanel/renderMSAMouseover.js.map +1 -0
  19. package/dist/components/Minimap.js +13 -13
  20. package/dist/components/Minimap.js.map +1 -1
  21. package/dist/components/TreePanel/TreeCanvasBlock.js +8 -4
  22. package/dist/components/TreePanel/TreeCanvasBlock.js.map +1 -1
  23. package/dist/components/TreePanel/{TreeMenu.d.ts → TreeNodeMenu.d.ts} +1 -0
  24. package/dist/components/TreePanel/{TreeMenu.js → TreeNodeMenu.js} +8 -4
  25. package/dist/components/TreePanel/TreeNodeMenu.js.map +1 -0
  26. package/dist/components/TreePanel/dialogs/{TreeNodeInfoDlg.js → TreeNodeInfoDialog.js} +2 -2
  27. package/dist/components/TreePanel/dialogs/TreeNodeInfoDialog.js.map +1 -0
  28. package/dist/components/TreePanel/renderTreeCanvas.d.ts +8 -3
  29. package/dist/components/TreePanel/renderTreeCanvas.js +8 -7
  30. package/dist/components/TreePanel/renderTreeCanvas.js.map +1 -1
  31. package/dist/components/dialogs/SettingsDialog.js +31 -22
  32. package/dist/components/dialogs/SettingsDialog.js.map +1 -1
  33. package/dist/model.d.ts +120 -62
  34. package/dist/model.js +176 -124
  35. package/dist/model.js.map +1 -1
  36. package/dist/parsers/ClustalMSA.d.ts +18 -5
  37. package/dist/parsers/ClustalMSA.js +1 -1
  38. package/dist/parsers/ClustalMSA.js.map +1 -1
  39. package/dist/parsers/FastaMSA.d.ts +1 -1
  40. package/dist/parsers/FastaMSA.js +2 -2
  41. package/dist/parsers/FastaMSA.js.map +1 -1
  42. package/dist/parsers/StockholmMSA.d.ts +1 -1
  43. package/dist/parsers/StockholmMSA.js +2 -2
  44. package/dist/parsers/StockholmMSA.js.map +1 -1
  45. package/dist/util.d.ts +1 -0
  46. package/dist/util.js +15 -7
  47. package/dist/util.js.map +1 -1
  48. package/dist/version.d.ts +1 -1
  49. package/dist/version.js +1 -1
  50. package/package.json +9 -7
  51. package/src/components/Header.tsx +5 -11
  52. package/src/components/HeaderInfoArea.tsx +21 -0
  53. package/src/components/MSAPanel/Loading.tsx +16 -0
  54. package/src/components/MSAPanel/MSACanvas.tsx +1 -16
  55. package/src/components/MSAPanel/MSAMouseoverCanvas.tsx +2 -50
  56. package/src/components/MSAPanel/renderMSABlock.ts +0 -2
  57. package/src/components/MSAPanel/renderMSAMouseover.ts +51 -0
  58. package/src/components/Minimap.tsx +15 -15
  59. package/src/components/TreePanel/TreeCanvasBlock.tsx +8 -3
  60. package/src/components/TreePanel/{TreeMenu.tsx → TreeNodeMenu.tsx} +12 -3
  61. package/src/components/TreePanel/dialogs/{TreeNodeInfoDlg.tsx → TreeNodeInfoDialog.tsx} +1 -1
  62. package/src/components/TreePanel/renderTreeCanvas.ts +13 -4
  63. package/src/components/dialogs/SettingsDialog.tsx +61 -44
  64. package/src/model.ts +279 -154
  65. package/src/parsers/ClustalMSA.ts +1 -1
  66. package/src/parsers/FastaMSA.ts +1 -1
  67. package/src/parsers/StockholmMSA.ts +1 -1
  68. package/src/util.ts +19 -6
  69. package/src/version.ts +1 -1
  70. package/dist/components/OverviewRubberband.d.ts +0 -8
  71. package/dist/components/OverviewRubberband.js +0 -185
  72. package/dist/components/OverviewRubberband.js.map +0 -1
  73. package/dist/components/Rubberband.d.ts +0 -8
  74. package/dist/components/Rubberband.js +0 -185
  75. package/dist/components/Rubberband.js.map +0 -1
  76. package/dist/components/TreePanel/TreeMenu.js.map +0 -1
  77. package/dist/components/TreePanel/dialogs/TreeNodeInfoDlg.js.map +0 -1
  78. package/dist/components/dialogs/AnnotationDialog.d.ts +0 -11
  79. package/dist/components/dialogs/AnnotationDialog.js +0 -65
  80. package/dist/components/dialogs/AnnotationDialog.js.map +0 -1
  81. package/src/components/OverviewRubberband.tsx +0 -283
  82. package/src/components/Rubberband.tsx +0 -283
  83. package/src/components/dialogs/AnnotationDialog.tsx +0 -144
  84. /package/dist/components/TreePanel/dialogs/{TreeNodeInfoDlg.d.ts → TreeNodeInfoDialog.d.ts} +0 -0
package/dist/model.js CHANGED
@@ -2,13 +2,14 @@ import { autorun } from 'mobx';
2
2
  import { cast, types, addDisposer } from 'mobx-state-tree';
3
3
  import { hierarchy, cluster } from 'd3-hierarchy';
4
4
  import { ascending } from 'd3-array';
5
+ import Stockholm from 'stockholm-js';
6
+ // jbrowse
5
7
  import { FileLocation, ElementId } from '@jbrowse/core/util/types/mst';
6
8
  import { openLocation } from '@jbrowse/core/util/io';
7
- import { measureText, sum } from '@jbrowse/core/util';
9
+ import { measureText, notEmpty, sum } from '@jbrowse/core/util';
8
10
  import BaseViewModel from '@jbrowse/core/pluggableElementTypes/models/BaseViewModel';
9
- import Stockholm from 'stockholm-js';
10
11
  // locals
11
- import { collapse, generateNodeIds, maxLength, setBrLength, skipBlanks, clamp, } from './util';
12
+ import { clamp, collapse, filterHiddenLeafNodes, generateNodeIds, maxLength, setBrLength, skipBlanks, } from './util';
12
13
  import TextTrack from './components/TextTrack';
13
14
  import BoxTrack from './components/BoxTrack';
14
15
  import ClustalMSA from './parsers/ClustalMSA';
@@ -21,140 +22,157 @@ import { StructureModel } from './StructureModel';
21
22
  import { DialogQueueSessionMixin } from './DialogQueue';
22
23
  /**
23
24
  * #stateModel MsaView
25
+ * extends
26
+ * - BaseViewModel
27
+ * - DialogQueueSessionMixin
24
28
  */
25
29
  function x() { } // eslint-disable-line @typescript-eslint/no-unused-vars
26
30
  const model = types
27
31
  .compose(BaseViewModel, DialogQueueSessionMixin(), types.model('MsaView', {
28
32
  /**
29
33
  * #property
34
+ * id of view, randomly generated if not provided
30
35
  */
31
36
  id: ElementId,
32
37
  /**
33
38
  * #property
39
+ * hardcoded view type
34
40
  */
35
41
  type: types.literal('MsaView'),
36
42
  /**
37
43
  * #property
44
+ * height of the div containing the view, px
38
45
  */
39
46
  height: types.optional(types.number, 550),
40
47
  /**
41
48
  * #property
49
+ * width of the area the tree is drawn in, px
42
50
  */
43
51
  treeAreaWidth: types.optional(types.number, 400),
44
52
  /**
45
53
  * #property
54
+ * width of the tree within the treeArea, px
46
55
  */
47
56
  treeWidth: types.optional(types.number, 300),
48
57
  /**
49
58
  * #getter
59
+ * synchronization that matches treeWidth to treeAreaWidth
50
60
  */
51
61
  treeWidthMatchesArea: true,
52
62
  /**
53
63
  * #property
64
+ * height of each row, px
54
65
  */
55
66
  rowHeight: 20,
56
67
  /**
57
68
  * #property
69
+ * scroll position, Y-offset, px
58
70
  */
59
71
  scrollY: 0,
60
72
  /**
61
73
  * #property
74
+ * scroll position, X-offset, px
62
75
  */
63
76
  scrollX: 0,
64
77
  /**
65
78
  * #property
66
- */
67
- resizeHandleWidth: 5,
68
- /**
69
- * #property
70
- */
71
- blockSize: 1000,
72
- /**
73
- * #property
74
- */
75
- mouseRow: types.maybe(types.number),
76
- /**
77
- * #property
78
- */
79
- mouseCol: types.maybe(types.number),
80
- /**
81
- * #property
79
+ * currently "selected" structures, generally PDB 3-D protein structures
82
80
  */
83
81
  selectedStructures: types.array(StructureModel),
84
82
  /**
85
83
  * #property
84
+ * right-align the labels
86
85
  */
87
86
  labelsAlignRight: false,
88
87
  /**
89
88
  * #property
89
+ * width of columns, px
90
90
  */
91
91
  colWidth: 16,
92
92
  /**
93
93
  * #property
94
+ * use "branch length" e.g. evolutionary distance to draw tree branch
95
+ * lengths. if false, the layout is a "cladogram" that does not take into
96
+ * account evolutionary distances
94
97
  */
95
98
  showBranchLen: true,
96
99
  /**
97
100
  * #property
101
+ * draw MSA tiles with a background color
98
102
  */
99
103
  bgColor: true,
100
104
  /**
101
105
  * #property
106
+ * draw tree, boolean
102
107
  */
103
108
  drawTree: true,
104
109
  /**
105
110
  * #property
111
+ * draw clickable node bubbles on the tree
106
112
  */
107
113
  drawNodeBubbles: true,
108
114
  /**
109
115
  * #property
116
+ * high resolution scale factor, helps make canvas look better on hi-dpi
117
+ * screens
110
118
  */
111
119
  highResScaleFactor: 2,
112
120
  /**
113
121
  * #property
122
+ * default color scheme name
114
123
  */
115
124
  colorSchemeName: 'maeditor',
116
125
  /**
117
126
  * #property
127
+ * filehandle object for the tree
118
128
  */
119
129
  treeFilehandle: types.maybe(FileLocation),
120
130
  /**
121
131
  * #property
132
+ * filehandle object for the MSA (which could contain a tree e.g. with
133
+ * stockholm files)
122
134
  */
123
135
  msaFilehandle: types.maybe(FileLocation),
124
136
  /**
125
137
  * #property
138
+ * filehandle object for tree metadata
126
139
  */
127
140
  treeMetadataFilehandle: types.maybe(FileLocation),
128
141
  /**
129
142
  * #property
143
+ *
130
144
  */
131
145
  currentAlignment: 0,
132
146
  /**
133
147
  * #property
148
+ * array of tree nodes that are 'collapsed'
134
149
  */
135
150
  collapsed: types.array(types.string),
136
151
  /**
137
152
  * #property
153
+ * array of leaf nodes that are 'hidden', similar to collapsed but for leaf nodes
138
154
  */
139
- showOnly: types.maybe(types.string),
155
+ hidden: types.array(types.string),
140
156
  /**
141
157
  * #property
158
+ * focus on particular subtree
142
159
  */
143
- boxTracks: types.array(UniprotTrack),
160
+ showOnly: types.maybe(types.string),
144
161
  /**
145
162
  * #property
163
+ * a list of "tracks" to display, as box-like glyphs (e.g. protein
164
+ * domains)
146
165
  */
147
- turnedOffTracks: types.map(types.boolean),
166
+ boxTracks: types.array(UniprotTrack),
148
167
  /**
149
168
  * #property
169
+ * turned off tracks
150
170
  */
151
- annotatedRegions: types.array(types.model({
152
- start: types.number,
153
- end: types.number,
154
- attributes: types.frozen(),
155
- })),
171
+ turnedOffTracks: types.map(types.boolean),
156
172
  /**
157
173
  * #property
174
+ * data from the loaded tree/msa/treeMetadata, generally loaded by
175
+ * autorun
158
176
  */
159
177
  data: types.optional(types
160
178
  .model({
@@ -175,6 +193,26 @@ const model = types
175
193
  })), { tree: '', msa: '' }),
176
194
  }))
177
195
  .volatile(() => ({
196
+ /**
197
+ * #volatile
198
+ * resize handle width between tree and msa area, px
199
+ */
200
+ resizeHandleWidth: 5,
201
+ /**
202
+ * #volatile
203
+ * size of blocks of content to be drawn, px
204
+ */
205
+ blockSize: 1000,
206
+ /**
207
+ * #volatile
208
+ * the currently mouse-hovered row
209
+ */
210
+ mouseRow: undefined,
211
+ /**
212
+ * #volatile
213
+ * the currently mouse-hovered column
214
+ */
215
+ mouseCol: undefined,
178
216
  /**
179
217
  * #volatile
180
218
  * a dummy variable that is incremented when ref changes so autorun for
@@ -204,18 +242,21 @@ const model = types
204
242
  .actions(self => ({
205
243
  /**
206
244
  * #action
245
+ * set the height of the view in px
207
246
  */
208
247
  setHeight(height) {
209
248
  self.height = height;
210
249
  },
211
250
  /**
212
251
  * #action
252
+ * add to the selected structures
213
253
  */
214
254
  addStructureToSelection(elt) {
215
255
  self.selectedStructures.push(elt);
216
256
  },
217
257
  /**
218
258
  * #action
259
+ * remove from the selected structures
219
260
  */
220
261
  removeStructureFromSelection(elt) {
221
262
  const r = self.selectedStructures.find(node => node.id === elt.id);
@@ -225,6 +266,7 @@ const model = types
225
266
  },
226
267
  /**
227
268
  * #action
269
+ * toggle a structure from the selected structures list
228
270
  */
229
271
  toggleStructureSelection(elt) {
230
272
  const r = self.selectedStructures.find(node => node.id === elt.id);
@@ -237,18 +279,21 @@ const model = types
237
279
  },
238
280
  /**
239
281
  * #action
282
+ * clear all selected structures
240
283
  */
241
284
  clearSelectedStructures() {
242
285
  self.selectedStructures = cast([]);
243
286
  },
244
287
  /**
245
288
  * #action
289
+ * set error state
246
290
  */
247
291
  setError(error) {
248
292
  self.error = error;
249
293
  },
250
294
  /**
251
295
  * #action
296
+ * set mouse position (row, column) in the MSA
252
297
  */
253
298
  setMousePos(col, row) {
254
299
  self.mouseCol = col;
@@ -256,48 +301,56 @@ const model = types
256
301
  },
257
302
  /**
258
303
  * #action
304
+ * set row height (px)
259
305
  */
260
306
  setRowHeight(n) {
261
307
  self.rowHeight = n;
262
308
  },
263
309
  /**
264
310
  * #action
311
+ * set col width (px)
265
312
  */
266
313
  setColWidth(n) {
267
314
  self.colWidth = n;
268
315
  },
269
316
  /**
270
317
  * #action
318
+ * set color scheme name
271
319
  */
272
320
  setColorSchemeName(name) {
273
321
  self.colorSchemeName = name;
274
322
  },
275
323
  /**
276
324
  * #action
325
+ * synchronize the treewidth and treeareawidth
277
326
  */
278
327
  setTreeWidthMatchesArea(arg) {
279
328
  self.treeWidthMatchesArea = arg;
280
329
  },
281
330
  /**
282
331
  * #action
332
+ * set scroll Y-offset (px)
283
333
  */
284
334
  setScrollY(n) {
285
335
  self.scrollY = n;
286
336
  },
287
337
  /**
288
338
  * #action
339
+ * set tree area width (px)
289
340
  */
290
341
  setTreeAreaWidth(n) {
291
342
  self.treeAreaWidth = n;
292
343
  },
293
344
  /**
294
345
  * #action
346
+ * set tree width (px)
295
347
  */
296
348
  setTreeWidth(n) {
297
349
  self.treeWidth = n;
298
350
  },
299
351
  /**
300
352
  * #action
353
+ *
301
354
  */
302
355
  setCurrentAlignment(n) {
303
356
  self.currentAlignment = n;
@@ -314,6 +367,18 @@ const model = types
314
367
  setDrawTree(arg) {
315
368
  self.drawTree = arg;
316
369
  },
370
+ /**
371
+ * #action
372
+ */
373
+ hideNode(arg) {
374
+ self.hidden.push(arg);
375
+ },
376
+ /**
377
+ * #action
378
+ */
379
+ clearHidden() {
380
+ self.hidden.clear();
381
+ },
317
382
  /**
318
383
  * #action
319
384
  */
@@ -482,7 +547,12 @@ const model = types
482
547
  const matches = name.match(/\S+\/(\d+)-(\d+)/);
483
548
  return {
484
549
  data: ((_a = this.MSA) === null || _a === void 0 ? void 0 : _a.getRowData(name)) || {},
485
- ...(matches && { range: { start: +matches[1], end: +matches[2] } }),
550
+ ...(matches && {
551
+ range: {
552
+ start: +matches[1],
553
+ end: +matches[2],
554
+ },
555
+ }),
486
556
  };
487
557
  },
488
558
  /**
@@ -502,7 +572,7 @@ const model = types
502
572
  * #getter
503
573
  */
504
574
  get noTree() {
505
- return !!this.tree.noTree;
575
+ return !!this._tree.noTree;
506
576
  },
507
577
  /**
508
578
  * #getter
@@ -544,7 +614,7 @@ const model = types
544
614
  /**
545
615
  * #getter
546
616
  */
547
- get tree() {
617
+ get _tree() {
548
618
  var _a;
549
619
  return self.data.tree
550
620
  ? generateNodeIds(parseNewick(self.data.tree))
@@ -563,7 +633,8 @@ const model = types
563
633
  },
564
634
  /**
565
635
  * #getter
566
- */ get mouseOverRowName() {
636
+ */
637
+ get mouseOverRowName() {
567
638
  return self.mouseRow !== undefined
568
639
  ? this.rowNames[self.mouseRow]
569
640
  : undefined;
@@ -578,7 +649,7 @@ const model = types
578
649
  * #getter
579
650
  */
580
651
  get root() {
581
- let hier = hierarchy(this.tree, d => d.branchset)
652
+ let hier = hierarchy(this._tree, d => d.branchset)
582
653
  .sum(d => (d.branchset ? 0 : 1))
583
654
  .sort((a, b) => ascending(a.data.length || 1, b.data.length || 1));
584
655
  if (self.showOnly) {
@@ -590,9 +661,15 @@ const model = types
590
661
  if (self.collapsed.length) {
591
662
  self.collapsed
592
663
  .map(collapsedId => hier.find(node => node.data.id === collapsedId))
593
- .filter((f) => !!f)
664
+ .filter(notEmpty)
594
665
  .map(node => collapse(node));
595
666
  }
667
+ if (self.hidden.length) {
668
+ self.hidden
669
+ .map(hiddenId => hier.find(node => node.data.id === hiddenId))
670
+ .filter(notEmpty)
671
+ .map(node => filterHiddenLeafNodes(node.parent, node.id));
672
+ }
596
673
  return hier;
597
674
  },
598
675
  /**
@@ -610,6 +687,7 @@ const model = types
610
687
  },
611
688
  /**
612
689
  * #getter
690
+ * widget width minus the tree area gives the space for the MSA
613
691
  */
614
692
  get msaAreaWidth() {
615
693
  return self.width - self.treeAreaWidth;
@@ -622,7 +700,7 @@ const model = types
622
700
  const blanks = [];
623
701
  const strs = this.hierarchy
624
702
  .leaves()
625
- .map(({ data }) => { var _a; return (_a = this.MSA) === null || _a === void 0 ? void 0 : _a.getRow(data.name); })
703
+ .map(leaf => { var _a; return (_a = this.MSA) === null || _a === void 0 ? void 0 : _a.getRow(leaf.data.name); })
626
704
  .filter((item) => !!item);
627
705
  for (let i = 0; i < ((_a = strs[0]) === null || _a === void 0 ? void 0 : _a.length); i++) {
628
706
  let counter = 0;
@@ -641,9 +719,10 @@ const model = types
641
719
  * #getter
642
720
  */
643
721
  get rows() {
722
+ const MSA = this.MSA;
644
723
  return this.hierarchy
645
724
  .leaves()
646
- .map(({ data }) => { var _a; return [data.name, (_a = this.MSA) === null || _a === void 0 ? void 0 : _a.getRow(data.name)]; })
725
+ .map(leaf => [leaf.data.name, MSA === null || MSA === void 0 ? void 0 : MSA.getRow(leaf.data.name)])
647
726
  .filter((f) => !!f[1]);
648
727
  },
649
728
  /**
@@ -687,13 +766,13 @@ const model = types
687
766
  * generates a new tree that is clustered with x,y positions
688
767
  */
689
768
  get hierarchy() {
690
- const root = this.root;
769
+ const r = this.root;
691
770
  const clust = cluster()
692
771
  .size([this.totalHeight, self.treeWidth])
693
772
  .separation(() => 1);
694
- clust(root);
695
- setBrLength(root, (root.data.length = 0), self.treeWidth / maxLength(root));
696
- return root;
773
+ clust(r);
774
+ setBrLength(r, (r.data.length = 0), self.treeWidth / maxLength(r));
775
+ return r;
697
776
  },
698
777
  /**
699
778
  * #getter
@@ -781,9 +860,7 @@ const model = types
781
860
  const { rowHeight, hierarchy, treeMetadata, fontSize } = self;
782
861
  if (rowHeight > 5) {
783
862
  for (const node of hierarchy.leaves()) {
784
- const { data: { name }, } = node;
785
- const displayName = ((_a = treeMetadata[name]) === null || _a === void 0 ? void 0 : _a.genome) || name;
786
- x = Math.max(measureText(displayName, fontSize), x);
863
+ x = Math.max(measureText(((_a = treeMetadata[node.data.name]) === null || _a === void 0 ? void 0 : _a.genome) || node.data.name, fontSize), x);
787
864
  }
788
865
  }
789
866
  return x;
@@ -819,62 +896,33 @@ const model = types
819
896
  /**
820
897
  * #getter
821
898
  */
822
- get tracks() {
823
- const blanks = self.blanks;
824
- const adapterTracks = self.MSA
825
- ? self.MSA.tracks.map(track => {
826
- const { data } = track;
827
- return {
828
- model: {
829
- ...track,
830
- data: data ? skipBlanks(blanks, data) : undefined,
831
- height: self.rowHeight,
832
- },
833
- ReactComponent: TextTrack,
834
- };
835
- })
836
- : [];
837
- const boxTracks = self.boxTracks
838
- // filter out tracks that are associated with hidden rows
839
- .filter(track => !!self.rows.some(row => row[0] === track.name))
899
+ get adapterTrackModels() {
900
+ var _a;
901
+ return (((_a = self.MSA) === null || _a === void 0 ? void 0 : _a.tracks.map(t => ({
902
+ model: {
903
+ ...t,
904
+ data: t.data ? skipBlanks(self.blanks, t.data) : undefined,
905
+ height: self.rowHeight,
906
+ },
907
+ ReactComponent: TextTrack,
908
+ }))) || []);
909
+ },
910
+ /**
911
+ * #getter
912
+ */
913
+ get boxTrackModels() {
914
+ return self.boxTracks
915
+ .filter(track => self.rows.some(row => row[0] === track.name))
840
916
  .map(track => ({
841
917
  model: track,
842
918
  ReactComponent: BoxTrack,
843
919
  }));
844
- const annotationTracks = self.annotatedRegions.length > 0
845
- ? [
846
- {
847
- model: {
848
- features: self.annotatedRegions,
849
- height: 100,
850
- id: 'annotations',
851
- name: 'User-created annotations',
852
- data: self.annotatedRegions
853
- .map(region => {
854
- const attrs = region.attributes
855
- ? Object.entries(region.attributes)
856
- .map(([k, v]) => `${k}=${v.join(',')}`)
857
- .join(';')
858
- : '.';
859
- return [
860
- 'MSA_refcoord',
861
- '.',
862
- '.',
863
- region.start,
864
- region.end,
865
- '.',
866
- '.',
867
- '.',
868
- attrs,
869
- ].join('\t');
870
- })
871
- .join('\n'),
872
- },
873
- ReactComponent: BoxTrack,
874
- },
875
- ]
876
- : [];
877
- return [...adapterTracks, ...boxTracks, ...annotationTracks];
920
+ },
921
+ /**
922
+ * #getter
923
+ */
924
+ get tracks() {
925
+ return [...this.adapterTrackModels, ...this.boxTrackModels];
878
926
  },
879
927
  /**
880
928
  * #getter
@@ -954,6 +1002,28 @@ const model = types
954
1002
  }
955
1003
  return 0;
956
1004
  },
1005
+ /**
1006
+ * #method
1007
+ */
1008
+ relativePxToBp2(rowName, position) {
1009
+ const { rowNames, rows } = self;
1010
+ const index = rowNames.indexOf(rowName);
1011
+ if (index !== -1) {
1012
+ const row = rows[index][1];
1013
+ let k = 0;
1014
+ let i = 0;
1015
+ for (; k < position; i++) {
1016
+ if (row[i] !== '-') {
1017
+ k++;
1018
+ }
1019
+ else if (k >= position) {
1020
+ break;
1021
+ }
1022
+ }
1023
+ return i;
1024
+ }
1025
+ return 0;
1026
+ },
957
1027
  /**
958
1028
  * #method
959
1029
  */
@@ -967,47 +1037,26 @@ const model = types
967
1037
  }
968
1038
  return j;
969
1039
  },
970
- }))
971
- .actions(self => ({
972
- /**
973
- * #action
974
- */
975
- addAnnotation(start, end, attributes) {
976
- self.annotatedRegions.push({
977
- start: self.getPos(start),
978
- end: self.getPos(end),
979
- attributes,
980
- });
981
- },
982
- /**
983
- * #action
984
- */
985
- setAnnotationClickBoundaries(left, right) {
986
- self.annotPos = { left, right };
987
- },
988
- /**
989
- * #action
990
- */
991
- clearAnnotationClickBoundaries() {
992
- self.annotPos = undefined;
993
- },
994
- /**
995
- * #action
996
- */
997
- incrementRef() {
998
- self.nref++;
999
- },
1000
1040
  }))
1001
1041
  .views(self => ({
1002
1042
  /**
1003
1043
  * #getter
1044
+ * total height of track area (px)
1004
1045
  */
1005
1046
  get totalTrackAreaHeight() {
1006
1047
  return sum(self.turnedOnTracks.map(r => r.model.height));
1007
1048
  },
1008
1049
  }))
1009
1050
  .actions(self => ({
1051
+ /**
1052
+ * #action
1053
+ * internal, used for drawing to canvas
1054
+ */
1055
+ incrementRef() {
1056
+ self.nref++;
1057
+ },
1010
1058
  afterCreate() {
1059
+ // autorun opens treeFilehandle
1011
1060
  addDisposer(self, autorun(async () => {
1012
1061
  const { treeFilehandle } = self;
1013
1062
  if (treeFilehandle) {
@@ -1020,6 +1069,7 @@ const model = types
1020
1069
  }
1021
1070
  }
1022
1071
  }));
1072
+ // autorun opens treeMetadataFilehandle
1023
1073
  addDisposer(self, autorun(async () => {
1024
1074
  const { treeMetadataFilehandle } = self;
1025
1075
  if (treeMetadataFilehandle) {
@@ -1032,6 +1082,7 @@ const model = types
1032
1082
  }
1033
1083
  }
1034
1084
  }));
1085
+ // autorun opens msaFilehandle
1035
1086
  addDisposer(self, autorun(async () => {
1036
1087
  const { msaFilehandle } = self;
1037
1088
  if (msaFilehandle) {
@@ -1044,6 +1095,7 @@ const model = types
1044
1095
  }
1045
1096
  }
1046
1097
  }));
1098
+ // autorun synchronizes treeWidth with treeAreaWidth
1047
1099
  addDisposer(self, autorun(async () => {
1048
1100
  if (self.treeWidthMatchesArea) {
1049
1101
  self.setTreeWidth(Math.max(50, self.treeAreaWidth - self.labelsWidth - 20));