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.
Files changed (199) hide show
  1. package/bundle/index.js +37 -255
  2. package/dist/DialogQueue.d.ts +25 -0
  3. package/dist/DialogQueue.js +46 -0
  4. package/dist/DialogQueue.js.map +1 -0
  5. package/dist/UniprotTrack.js.map +1 -1
  6. package/dist/colorSchemes.js.map +1 -1
  7. package/dist/components/BoxTrackBlock.js +3 -2
  8. package/dist/components/BoxTrackBlock.js.map +1 -1
  9. package/dist/components/Header.js +12 -20
  10. package/dist/components/Header.js.map +1 -1
  11. package/dist/components/HeaderInfoArea.d.ts +6 -0
  12. package/dist/components/HeaderInfoArea.js +12 -0
  13. package/dist/components/HeaderInfoArea.js.map +1 -0
  14. package/dist/components/ImportForm/ImportFormExamples.d.ts +6 -0
  15. package/dist/components/ImportForm/ImportFormExamples.js +50 -0
  16. package/dist/components/ImportForm/ImportFormExamples.js.map +1 -0
  17. package/dist/components/ImportForm/data/seq2.js.map +1 -0
  18. package/dist/components/{ImportForm.d.ts → ImportForm/index.d.ts} +1 -1
  19. package/dist/components/ImportForm/index.js +31 -0
  20. package/dist/components/ImportForm/index.js.map +1 -0
  21. package/dist/components/ImportForm/util.d.ts +3 -0
  22. package/dist/components/ImportForm/util.js +15 -0
  23. package/dist/components/ImportForm/util.js.map +1 -0
  24. package/dist/components/MSAPanel/Loading.d.ts +2 -0
  25. package/dist/components/MSAPanel/Loading.js +12 -0
  26. package/dist/components/MSAPanel/Loading.js.map +1 -0
  27. package/dist/components/{MSABlock.d.ts → MSAPanel/MSABlock.d.ts} +1 -1
  28. package/dist/components/MSAPanel/MSABlock.js +46 -0
  29. package/dist/components/MSAPanel/MSABlock.js.map +1 -0
  30. package/dist/components/{MSACanvas.d.ts → MSAPanel/MSACanvas.d.ts} +1 -1
  31. package/dist/components/{MSACanvas.js → MSAPanel/MSACanvas.js} +2 -4
  32. package/dist/components/MSAPanel/MSACanvas.js.map +1 -0
  33. package/dist/components/{MSAMouseoverCanvas.d.ts → MSAPanel/MSAMouseoverCanvas.d.ts} +1 -1
  34. package/dist/components/MSAPanel/MSAMouseoverCanvas.js +29 -0
  35. package/dist/components/MSAPanel/MSAMouseoverCanvas.js.map +1 -0
  36. package/dist/components/MSAPanel/index.d.ts +5 -0
  37. package/dist/components/MSAPanel/index.js +9 -0
  38. package/dist/components/MSAPanel/index.js.map +1 -0
  39. package/dist/components/MSAPanel/renderMSABlock.d.ts +8 -0
  40. package/dist/components/MSAPanel/renderMSABlock.js +80 -0
  41. package/dist/components/MSAPanel/renderMSABlock.js.map +1 -0
  42. package/dist/components/MSAPanel/renderMSAMouseover.d.ts +5 -0
  43. package/dist/components/MSAPanel/renderMSAMouseover.js +24 -0
  44. package/dist/components/MSAPanel/renderMSAMouseover.js.map +1 -0
  45. package/dist/components/MSAView.d.ts +2 -2
  46. package/dist/components/MSAView.js +26 -31
  47. package/dist/components/MSAView.js.map +1 -1
  48. package/dist/components/Minimap.d.ts +6 -0
  49. package/dist/components/Minimap.js +72 -0
  50. package/dist/components/Minimap.js.map +1 -0
  51. package/dist/components/ResizeHandles.js.map +1 -1
  52. package/dist/components/TextTrack.js +3 -2
  53. package/dist/components/TextTrack.js.map +1 -1
  54. package/dist/components/Track.js +5 -5
  55. package/dist/components/Track.js.map +1 -1
  56. package/dist/components/{TreeBranchMenu.d.ts → TreePanel/TreeBranchMenu.d.ts} +1 -1
  57. package/dist/components/TreePanel/TreeBranchMenu.js.map +1 -0
  58. package/dist/components/{TreeCanvas.d.ts → TreePanel/TreeCanvas.d.ts} +1 -1
  59. package/dist/components/{TreeCanvas.js → TreePanel/TreeCanvas.js} +1 -1
  60. package/dist/components/TreePanel/TreeCanvas.js.map +1 -0
  61. package/dist/components/{TreeCanvasBlock.d.ts → TreePanel/TreeCanvasBlock.d.ts} +1 -1
  62. package/dist/components/TreePanel/TreeCanvasBlock.js +121 -0
  63. package/dist/components/TreePanel/TreeCanvasBlock.js.map +1 -0
  64. package/dist/components/{TreeMenu.d.ts → TreePanel/TreeNodeMenu.d.ts} +2 -1
  65. package/dist/components/{TreeMenu.js → TreePanel/TreeNodeMenu.js} +16 -8
  66. package/dist/components/TreePanel/TreeNodeMenu.js.map +1 -0
  67. package/dist/components/{TreeRuler.d.ts → TreePanel/TreeRuler.d.ts} +1 -1
  68. package/dist/components/TreePanel/TreeRuler.js +8 -0
  69. package/dist/components/TreePanel/TreeRuler.js.map +1 -0
  70. package/dist/components/{dialogs/TreeNodeInfoDlg.d.ts → TreePanel/dialogs/TreeNodeInfoDialog.d.ts} +1 -1
  71. package/dist/components/{dialogs/TreeNodeInfoDlg.js → TreePanel/dialogs/TreeNodeInfoDialog.js} +2 -2
  72. package/dist/components/TreePanel/dialogs/TreeNodeInfoDialog.js.map +1 -0
  73. package/dist/components/TreePanel/index.d.ts +6 -0
  74. package/dist/components/TreePanel/index.js +10 -0
  75. package/dist/components/TreePanel/index.js.map +1 -0
  76. package/dist/components/TreePanel/renderTreeCanvas.d.ts +41 -0
  77. package/dist/components/TreePanel/renderTreeCanvas.js +154 -0
  78. package/dist/components/TreePanel/renderTreeCanvas.js.map +1 -0
  79. package/dist/components/dialogs/{AboutDlg.js → AboutDialog.js} +1 -1
  80. package/dist/components/dialogs/AboutDialog.js.map +1 -0
  81. package/dist/components/dialogs/{AddTrackDlg.js → AddTrackDialog.js} +1 -1
  82. package/dist/components/dialogs/AddTrackDialog.js.map +1 -0
  83. package/dist/components/dialogs/{MetadataDlg.js → MetadataDialog.js} +1 -1
  84. package/dist/components/dialogs/MetadataDialog.js.map +1 -0
  85. package/dist/components/dialogs/SettingsDialog.js +63 -0
  86. package/dist/components/dialogs/SettingsDialog.js.map +1 -0
  87. package/dist/components/dialogs/{TrackInfoDlg.js → TrackInfoDialog.js} +1 -1
  88. package/dist/components/dialogs/TrackInfoDialog.js.map +1 -0
  89. package/dist/components/dialogs/{TracklistDlg.js → TracklistDialog.js} +1 -1
  90. package/dist/components/dialogs/TracklistDialog.js.map +1 -0
  91. package/dist/components/util.js.map +1 -1
  92. package/dist/layout.js.map +1 -1
  93. package/dist/model.d.ts +179 -88
  94. package/dist/model.js +287 -175
  95. package/dist/model.js.map +1 -1
  96. package/dist/parseNewick.js.map +1 -1
  97. package/dist/parsers/ClustalMSA.d.ts +1 -1
  98. package/dist/parsers/ClustalMSA.js +1 -1
  99. package/dist/parsers/ClustalMSA.js.map +1 -1
  100. package/dist/parsers/FastaMSA.d.ts +1 -1
  101. package/dist/parsers/FastaMSA.js +2 -2
  102. package/dist/parsers/FastaMSA.js.map +1 -1
  103. package/dist/parsers/StockholmMSA.d.ts +1 -1
  104. package/dist/parsers/StockholmMSA.js +2 -2
  105. package/dist/parsers/StockholmMSA.js.map +1 -1
  106. package/dist/util.d.ts +1 -0
  107. package/dist/util.js +15 -7
  108. package/dist/util.js.map +1 -1
  109. package/dist/version.d.ts +1 -1
  110. package/dist/version.js +1 -1
  111. package/package.json +6 -4
  112. package/src/DialogQueue.ts +47 -0
  113. package/src/components/BoxTrackBlock.tsx +3 -1
  114. package/src/components/Header.tsx +13 -20
  115. package/src/components/HeaderInfoArea.tsx +21 -0
  116. package/src/components/ImportForm/ImportFormExamples.tsx +133 -0
  117. package/src/components/ImportForm/index.tsx +63 -0
  118. package/src/components/ImportForm/util.ts +20 -0
  119. package/src/components/MSAPanel/Loading.tsx +16 -0
  120. package/src/components/MSAPanel/MSABlock.tsx +81 -0
  121. package/src/components/{MSACanvas.tsx → MSAPanel/MSACanvas.tsx} +3 -6
  122. package/src/components/MSAPanel/MSAMouseoverCanvas.tsx +44 -0
  123. package/src/components/MSAPanel/index.tsx +13 -0
  124. package/src/components/MSAPanel/renderMSABlock.ts +158 -0
  125. package/src/components/MSAPanel/renderMSAMouseover.ts +51 -0
  126. package/src/components/MSAView.tsx +36 -56
  127. package/src/components/Minimap.tsx +102 -0
  128. package/src/components/TextTrack.tsx +3 -1
  129. package/src/components/Track.tsx +5 -5
  130. package/src/components/{TreeBranchMenu.tsx → TreePanel/TreeBranchMenu.tsx} +1 -1
  131. package/src/components/{TreeCanvas.tsx → TreePanel/TreeCanvas.tsx} +2 -3
  132. package/src/components/TreePanel/TreeCanvasBlock.tsx +195 -0
  133. package/src/components/{TreeMenu.tsx → TreePanel/TreeNodeMenu.tsx} +21 -8
  134. package/src/components/{TreeRuler.tsx → TreePanel/TreeRuler.tsx} +3 -3
  135. package/src/components/{dialogs/TreeNodeInfoDlg.tsx → TreePanel/dialogs/TreeNodeInfoDialog.tsx} +2 -2
  136. package/src/components/TreePanel/index.tsx +16 -0
  137. package/src/components/TreePanel/renderTreeCanvas.ts +254 -0
  138. package/src/components/dialogs/SettingsDialog.tsx +196 -0
  139. package/src/model.ts +414 -211
  140. package/src/parsers/ClustalMSA.ts +1 -1
  141. package/src/parsers/FastaMSA.ts +1 -1
  142. package/src/parsers/StockholmMSA.ts +1 -1
  143. package/src/util.ts +19 -6
  144. package/src/version.ts +1 -1
  145. package/dist/components/ImportForm.js +0 -84
  146. package/dist/components/ImportForm.js.map +0 -1
  147. package/dist/components/MSABlock.js +0 -103
  148. package/dist/components/MSABlock.js.map +0 -1
  149. package/dist/components/MSACanvas.js.map +0 -1
  150. package/dist/components/MSAMouseoverCanvas.js +0 -61
  151. package/dist/components/MSAMouseoverCanvas.js.map +0 -1
  152. package/dist/components/Rubberband.d.ts +0 -8
  153. package/dist/components/Rubberband.js +0 -173
  154. package/dist/components/Rubberband.js.map +0 -1
  155. package/dist/components/Ruler.d.ts +0 -6
  156. package/dist/components/Ruler.js +0 -52
  157. package/dist/components/Ruler.js.map +0 -1
  158. package/dist/components/TreeBranchMenu.js.map +0 -1
  159. package/dist/components/TreeCanvas.js.map +0 -1
  160. package/dist/components/TreeCanvasBlock.js +0 -255
  161. package/dist/components/TreeCanvasBlock.js.map +0 -1
  162. package/dist/components/TreeMenu.js.map +0 -1
  163. package/dist/components/TreeRuler.js +0 -8
  164. package/dist/components/TreeRuler.js.map +0 -1
  165. package/dist/components/data/seq2.js.map +0 -1
  166. package/dist/components/dialogs/AboutDlg.js.map +0 -1
  167. package/dist/components/dialogs/AddTrackDlg.js.map +0 -1
  168. package/dist/components/dialogs/AnnotationDlg.d.ts +0 -11
  169. package/dist/components/dialogs/AnnotationDlg.js +0 -65
  170. package/dist/components/dialogs/AnnotationDlg.js.map +0 -1
  171. package/dist/components/dialogs/MetadataDlg.js.map +0 -1
  172. package/dist/components/dialogs/SettingsDlg.js +0 -48
  173. package/dist/components/dialogs/SettingsDlg.js.map +0 -1
  174. package/dist/components/dialogs/TrackInfoDlg.js.map +0 -1
  175. package/dist/components/dialogs/TracklistDlg.js.map +0 -1
  176. package/dist/components/dialogs/TreeNodeInfoDlg.js.map +0 -1
  177. package/src/components/ImportForm.tsx +0 -192
  178. package/src/components/MSABlock.tsx +0 -164
  179. package/src/components/MSAMouseoverCanvas.tsx +0 -99
  180. package/src/components/Rubberband.tsx +0 -270
  181. package/src/components/Ruler.tsx +0 -123
  182. package/src/components/TreeCanvasBlock.tsx +0 -363
  183. package/src/components/dialogs/AnnotationDlg.tsx +0 -144
  184. package/src/components/dialogs/SettingsDlg.tsx +0 -154
  185. /package/dist/components/{data → ImportForm/data}/seq2.d.ts +0 -0
  186. /package/dist/components/{data → ImportForm/data}/seq2.js +0 -0
  187. /package/dist/components/{TreeBranchMenu.js → TreePanel/TreeBranchMenu.js} +0 -0
  188. /package/dist/components/dialogs/{AboutDlg.d.ts → AboutDialog.d.ts} +0 -0
  189. /package/dist/components/dialogs/{AddTrackDlg.d.ts → AddTrackDialog.d.ts} +0 -0
  190. /package/dist/components/dialogs/{MetadataDlg.d.ts → MetadataDialog.d.ts} +0 -0
  191. /package/dist/components/dialogs/{SettingsDlg.d.ts → SettingsDialog.d.ts} +0 -0
  192. /package/dist/components/dialogs/{TrackInfoDlg.d.ts → TrackInfoDialog.d.ts} +0 -0
  193. /package/dist/components/dialogs/{TracklistDlg.d.ts → TracklistDialog.d.ts} +0 -0
  194. /package/src/components/{data → ImportForm/data}/seq2.ts +0 -0
  195. /package/src/components/dialogs/{AboutDlg.tsx → AboutDialog.tsx} +0 -0
  196. /package/src/components/dialogs/{AddTrackDlg.tsx → AddTrackDialog.tsx} +0 -0
  197. /package/src/components/dialogs/{MetadataDlg.tsx → MetadataDialog.tsx} +0 -0
  198. /package/src/components/dialogs/{TrackInfoDlg.tsx → TrackInfoDialog.tsx} +0 -0
  199. /package/src/components/dialogs/{TracklistDlg.tsx → TracklistDialog.tsx} +0 -0
package/dist/model.js CHANGED
@@ -1,13 +1,15 @@
1
+ import { autorun } from 'mobx';
1
2
  import { cast, types, addDisposer } from 'mobx-state-tree';
2
3
  import { hierarchy, cluster } from 'd3-hierarchy';
3
4
  import { ascending } from 'd3-array';
5
+ import Stockholm from 'stockholm-js';
6
+ // jbrowse
4
7
  import { FileLocation, ElementId } from '@jbrowse/core/util/types/mst';
5
8
  import { openLocation } from '@jbrowse/core/util/io';
6
- import { autorun } from 'mobx';
9
+ import { measureText, notEmpty, sum } from '@jbrowse/core/util';
7
10
  import BaseViewModel from '@jbrowse/core/pluggableElementTypes/models/BaseViewModel';
8
- import Stockholm from 'stockholm-js';
9
11
  // locals
10
- import { collapse, generateNodeIds, maxLength, setBrLength, skipBlanks, clamp, } from './util';
12
+ import { clamp, collapse, filterHiddenLeafNodes, generateNodeIds, maxLength, setBrLength, skipBlanks, } from './util';
11
13
  import TextTrack from './components/TextTrack';
12
14
  import BoxTrack from './components/BoxTrack';
13
15
  import ClustalMSA from './parsers/ClustalMSA';
@@ -17,138 +19,160 @@ import parseNewick from './parseNewick';
17
19
  import colorSchemes from './colorSchemes';
18
20
  import { UniprotTrack } from './UniprotTrack';
19
21
  import { StructureModel } from './StructureModel';
22
+ import { DialogQueueSessionMixin } from './DialogQueue';
20
23
  /**
21
24
  * #stateModel MsaView
25
+ * extends
26
+ * - BaseViewModel
27
+ * - DialogQueueSessionMixin
22
28
  */
23
29
  function x() { } // eslint-disable-line @typescript-eslint/no-unused-vars
24
30
  const model = types
25
- .compose(BaseViewModel, types.model('MsaView', {
31
+ .compose(BaseViewModel, DialogQueueSessionMixin(), types.model('MsaView', {
26
32
  /**
27
33
  * #property
34
+ * id of view, randomly generated if not provided
28
35
  */
29
36
  id: ElementId,
30
37
  /**
31
38
  * #property
39
+ * hardcoded view type
32
40
  */
33
41
  type: types.literal('MsaView'),
34
42
  /**
35
43
  * #property
44
+ * height of the div containing the view, px
36
45
  */
37
46
  height: types.optional(types.number, 550),
38
47
  /**
39
48
  * #property
49
+ * width of the area the tree is drawn in, px
40
50
  */
41
51
  treeAreaWidth: types.optional(types.number, 400),
42
52
  /**
43
53
  * #property
54
+ * width of the tree within the treeArea, px
44
55
  */
45
56
  treeWidth: types.optional(types.number, 300),
57
+ /**
58
+ * #getter
59
+ * synchronization that matches treeWidth to treeAreaWidth
60
+ */
61
+ treeWidthMatchesArea: true,
46
62
  /**
47
63
  * #property
64
+ * height of each row, px
48
65
  */
49
66
  rowHeight: 20,
50
67
  /**
51
68
  * #property
69
+ * scroll position, Y-offset, px
52
70
  */
53
71
  scrollY: 0,
54
72
  /**
55
73
  * #property
74
+ * scroll position, X-offset, px
56
75
  */
57
76
  scrollX: 0,
58
77
  /**
59
78
  * #property
60
- */
61
- resizeHandleWidth: 5,
62
- /**
63
- * #property
64
- */
65
- blockSize: 1000,
66
- /**
67
- * #property
68
- */
69
- mouseRow: types.maybe(types.number),
70
- /**
71
- * #property
72
- */
73
- mouseCol: types.maybe(types.number),
74
- /**
75
- * #property
79
+ * currently "selected" structures, generally PDB 3-D protein structures
76
80
  */
77
81
  selectedStructures: types.array(StructureModel),
78
82
  /**
79
83
  * #property
84
+ * right-align the labels
80
85
  */
81
86
  labelsAlignRight: false,
82
87
  /**
83
88
  * #property
89
+ * width of columns, px
84
90
  */
85
91
  colWidth: 16,
86
92
  /**
87
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
88
97
  */
89
98
  showBranchLen: true,
90
99
  /**
91
100
  * #property
101
+ * draw MSA tiles with a background color
92
102
  */
93
103
  bgColor: true,
94
104
  /**
95
105
  * #property
106
+ * draw tree, boolean
96
107
  */
97
108
  drawTree: true,
98
109
  /**
99
110
  * #property
111
+ * draw clickable node bubbles on the tree
100
112
  */
101
113
  drawNodeBubbles: true,
102
114
  /**
103
115
  * #property
116
+ * high resolution scale factor, helps make canvas look better on hi-dpi
117
+ * screens
104
118
  */
105
119
  highResScaleFactor: 2,
106
120
  /**
107
121
  * #property
122
+ * default color scheme name
108
123
  */
109
124
  colorSchemeName: 'maeditor',
110
125
  /**
111
126
  * #property
127
+ * filehandle object for the tree
112
128
  */
113
129
  treeFilehandle: types.maybe(FileLocation),
114
130
  /**
115
131
  * #property
132
+ * filehandle object for the MSA (which could contain a tree e.g. with
133
+ * stockholm files)
116
134
  */
117
135
  msaFilehandle: types.maybe(FileLocation),
118
136
  /**
119
137
  * #property
138
+ * filehandle object for tree metadata
120
139
  */
121
140
  treeMetadataFilehandle: types.maybe(FileLocation),
122
141
  /**
123
142
  * #property
143
+ *
124
144
  */
125
145
  currentAlignment: 0,
126
146
  /**
127
147
  * #property
148
+ * array of tree nodes that are 'collapsed'
128
149
  */
129
150
  collapsed: types.array(types.string),
130
151
  /**
131
152
  * #property
153
+ * array of leaf nodes that are 'hidden', similar to collapsed but for leaf nodes
132
154
  */
133
- showOnly: types.maybe(types.string),
155
+ hidden: types.array(types.string),
134
156
  /**
135
157
  * #property
158
+ * focus on particular subtree
136
159
  */
137
- boxTracks: types.array(UniprotTrack),
160
+ showOnly: types.maybe(types.string),
138
161
  /**
139
162
  * #property
163
+ * a list of "tracks" to display, as box-like glyphs (e.g. protein
164
+ * domains)
140
165
  */
141
- turnedOffTracks: types.map(types.boolean),
166
+ boxTracks: types.array(UniprotTrack),
142
167
  /**
143
168
  * #property
169
+ * turned off tracks
144
170
  */
145
- annotatedRegions: types.array(types.model({
146
- start: types.number,
147
- end: types.number,
148
- attributes: types.frozen(),
149
- })),
171
+ turnedOffTracks: types.map(types.boolean),
150
172
  /**
151
173
  * #property
174
+ * data from the loaded tree/msa/treeMetadata, generally loaded by
175
+ * autorun
152
176
  */
153
177
  data: types.optional(types
154
178
  .model({
@@ -169,42 +193,70 @@ const model = types
169
193
  })), { tree: '', msa: '' }),
170
194
  }))
171
195
  .volatile(() => ({
172
- rulerHeight: 20,
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,
216
+ /**
217
+ * #volatile
218
+ * a dummy variable that is incremented when ref changes so autorun for
219
+ * drawing canvas commands will run
220
+ */
221
+ nref: 0,
222
+ /**
223
+ * #volatile
224
+ */
225
+ minimapHeight: 56,
226
+ /**
227
+ * #volatile
228
+ */
173
229
  error: undefined,
230
+ /**
231
+ * #volatile
232
+ */
174
233
  margin: {
175
234
  left: 20,
176
235
  top: 20,
177
236
  },
178
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
179
- DialogComponent: undefined,
180
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
181
- DialogProps: undefined,
182
- // annotations
237
+ /**
238
+ * #volatile
239
+ */
183
240
  annotPos: undefined,
184
241
  }))
185
242
  .actions(self => ({
186
243
  /**
187
244
  * #action
188
- */
189
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
190
- setDialogComponent(dlg, props) {
191
- self.DialogComponent = dlg;
192
- self.DialogProps = props;
193
- },
194
- /**
195
- * #action
245
+ * set the height of the view in px
196
246
  */
197
247
  setHeight(height) {
198
248
  self.height = height;
199
249
  },
200
250
  /**
201
251
  * #action
252
+ * add to the selected structures
202
253
  */
203
254
  addStructureToSelection(elt) {
204
255
  self.selectedStructures.push(elt);
205
256
  },
206
257
  /**
207
258
  * #action
259
+ * remove from the selected structures
208
260
  */
209
261
  removeStructureFromSelection(elt) {
210
262
  const r = self.selectedStructures.find(node => node.id === elt.id);
@@ -214,6 +266,7 @@ const model = types
214
266
  },
215
267
  /**
216
268
  * #action
269
+ * toggle a structure from the selected structures list
217
270
  */
218
271
  toggleStructureSelection(elt) {
219
272
  const r = self.selectedStructures.find(node => node.id === elt.id);
@@ -226,18 +279,21 @@ const model = types
226
279
  },
227
280
  /**
228
281
  * #action
282
+ * clear all selected structures
229
283
  */
230
284
  clearSelectedStructures() {
231
285
  self.selectedStructures = cast([]);
232
286
  },
233
287
  /**
234
288
  * #action
289
+ * set error state
235
290
  */
236
291
  setError(error) {
237
292
  self.error = error;
238
293
  },
239
294
  /**
240
295
  * #action
296
+ * set mouse position (row, column) in the MSA
241
297
  */
242
298
  setMousePos(col, row) {
243
299
  self.mouseCol = col;
@@ -245,48 +301,56 @@ const model = types
245
301
  },
246
302
  /**
247
303
  * #action
304
+ * set row height (px)
248
305
  */
249
306
  setRowHeight(n) {
250
307
  self.rowHeight = n;
251
308
  },
252
309
  /**
253
310
  * #action
311
+ * set col width (px)
254
312
  */
255
313
  setColWidth(n) {
256
314
  self.colWidth = n;
257
315
  },
258
316
  /**
259
317
  * #action
318
+ * set color scheme name
260
319
  */
261
320
  setColorSchemeName(name) {
262
321
  self.colorSchemeName = name;
263
322
  },
264
323
  /**
265
324
  * #action
325
+ * synchronize the treewidth and treeareawidth
266
326
  */
267
- setScrollY(n) {
268
- self.scrollY = n;
327
+ setTreeWidthMatchesArea(arg) {
328
+ self.treeWidthMatchesArea = arg;
269
329
  },
270
330
  /**
271
331
  * #action
332
+ * set scroll Y-offset (px)
272
333
  */
273
- setScrollX(n) {
274
- self.scrollX = n;
334
+ setScrollY(n) {
335
+ self.scrollY = n;
275
336
  },
276
337
  /**
277
338
  * #action
339
+ * set tree area width (px)
278
340
  */
279
341
  setTreeAreaWidth(n) {
280
342
  self.treeAreaWidth = n;
281
343
  },
282
344
  /**
283
345
  * #action
346
+ * set tree width (px)
284
347
  */
285
348
  setTreeWidth(n) {
286
349
  self.treeWidth = n;
287
350
  },
288
351
  /**
289
352
  * #action
353
+ *
290
354
  */
291
355
  setCurrentAlignment(n) {
292
356
  self.currentAlignment = n;
@@ -294,14 +358,26 @@ const model = types
294
358
  /**
295
359
  * #action
296
360
  */
297
- toggleLabelsAlignRight() {
298
- self.labelsAlignRight = !self.labelsAlignRight;
361
+ setLabelsAlignRight(arg) {
362
+ self.labelsAlignRight = arg;
363
+ },
364
+ /**
365
+ * #action
366
+ */
367
+ setDrawTree(arg) {
368
+ self.drawTree = arg;
299
369
  },
300
370
  /**
301
371
  * #action
302
372
  */
303
- toggleDrawTree() {
304
- self.drawTree = !self.drawTree;
373
+ hideNode(arg) {
374
+ self.hidden.push(arg);
375
+ },
376
+ /**
377
+ * #action
378
+ */
379
+ clearHidden() {
380
+ self.hidden.clear();
305
381
  },
306
382
  /**
307
383
  * #action
@@ -323,20 +399,20 @@ const model = types
323
399
  /**
324
400
  * #action
325
401
  */
326
- toggleBranchLen() {
327
- self.showBranchLen = !self.showBranchLen;
402
+ setShowBranchLen(arg) {
403
+ self.showBranchLen = arg;
328
404
  },
329
405
  /**
330
406
  * #action
331
407
  */
332
- toggleBgColor() {
333
- self.bgColor = !self.bgColor;
408
+ setBgColor(arg) {
409
+ self.bgColor = arg;
334
410
  },
335
411
  /**
336
412
  * #action
337
413
  */
338
- toggleNodeBubbles() {
339
- self.drawNodeBubbles = !self.drawNodeBubbles;
414
+ setDrawNodeBubbles(arg) {
415
+ self.drawNodeBubbles = arg;
340
416
  },
341
417
  /**
342
418
  * #action
@@ -380,44 +456,6 @@ const model = types
380
456
  setTreeMetadata(result) {
381
457
  self.data.setTreeMetadata(result);
382
458
  },
383
- afterCreate() {
384
- addDisposer(self, autorun(async () => {
385
- const { treeFilehandle } = self;
386
- if (treeFilehandle) {
387
- try {
388
- this.setTree(await openLocation(treeFilehandle).readFile('utf8'));
389
- }
390
- catch (e) {
391
- console.error(e);
392
- this.setError(e);
393
- }
394
- }
395
- }));
396
- addDisposer(self, autorun(async () => {
397
- const { treeMetadataFilehandle } = self;
398
- if (treeMetadataFilehandle) {
399
- try {
400
- this.setTreeMetadata(await openLocation(treeMetadataFilehandle).readFile('utf8'));
401
- }
402
- catch (e) {
403
- console.error(e);
404
- this.setError(e);
405
- }
406
- }
407
- }));
408
- addDisposer(self, autorun(async () => {
409
- const { msaFilehandle } = self;
410
- if (msaFilehandle) {
411
- try {
412
- this.setMSA(await openLocation(msaFilehandle).readFile('utf8'));
413
- }
414
- catch (e) {
415
- console.error(e);
416
- this.setError(e);
417
- }
418
- }
419
- }));
420
- },
421
459
  }))
422
460
  .views(self => {
423
461
  let oldBlocksX = [];
@@ -509,7 +547,12 @@ const model = types
509
547
  const matches = name.match(/\S+\/(\d+)-(\d+)/);
510
548
  return {
511
549
  data: ((_a = this.MSA) === null || _a === void 0 ? void 0 : _a.getRowData(name)) || {},
512
- ...(matches && { range: { start: +matches[1], end: +matches[2] } }),
550
+ ...(matches && {
551
+ range: {
552
+ start: +matches[1],
553
+ end: +matches[2],
554
+ },
555
+ }),
513
556
  };
514
557
  },
515
558
  /**
@@ -529,7 +572,7 @@ const model = types
529
572
  * #getter
530
573
  */
531
574
  get noTree() {
532
- return !!this.tree.noTree;
575
+ return !!this._tree.noTree;
533
576
  },
534
577
  /**
535
578
  * #getter
@@ -566,12 +609,12 @@ const model = types
566
609
  */
567
610
  get numColumns() {
568
611
  var _a;
569
- return ((((_a = this.MSA) === null || _a === void 0 ? void 0 : _a.getWidth()) || 0) - this.blanks.length) * self.colWidth;
612
+ return (((_a = this.MSA) === null || _a === void 0 ? void 0 : _a.getWidth()) || 0) - this.blanks.length;
570
613
  },
571
614
  /**
572
615
  * #getter
573
616
  */
574
- get tree() {
617
+ get _tree() {
575
618
  var _a;
576
619
  return self.data.tree
577
620
  ? generateNodeIds(parseNewick(self.data.tree))
@@ -590,7 +633,8 @@ const model = types
590
633
  },
591
634
  /**
592
635
  * #getter
593
- */ get mouseOverRowName() {
636
+ */
637
+ get mouseOverRowName() {
594
638
  return self.mouseRow !== undefined
595
639
  ? this.rowNames[self.mouseRow]
596
640
  : undefined;
@@ -605,7 +649,7 @@ const model = types
605
649
  * #getter
606
650
  */
607
651
  get root() {
608
- let hier = hierarchy(this.tree, d => d.branchset)
652
+ let hier = hierarchy(this._tree, d => d.branchset)
609
653
  .sum(d => (d.branchset ? 0 : 1))
610
654
  .sort((a, b) => ascending(a.data.length || 1, b.data.length || 1));
611
655
  if (self.showOnly) {
@@ -617,9 +661,15 @@ const model = types
617
661
  if (self.collapsed.length) {
618
662
  self.collapsed
619
663
  .map(collapsedId => hier.find(node => node.data.id === collapsedId))
620
- .filter((f) => !!f)
664
+ .filter(notEmpty)
621
665
  .map(node => collapse(node));
622
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
+ }
623
673
  return hier;
624
674
  },
625
675
  /**
@@ -637,6 +687,7 @@ const model = types
637
687
  },
638
688
  /**
639
689
  * #getter
690
+ * widget width minus the tree area gives the space for the MSA
640
691
  */
641
692
  get msaAreaWidth() {
642
693
  return self.width - self.treeAreaWidth;
@@ -649,7 +700,7 @@ const model = types
649
700
  const blanks = [];
650
701
  const strs = this.hierarchy
651
702
  .leaves()
652
- .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); })
653
704
  .filter((item) => !!item);
654
705
  for (let i = 0; i < ((_a = strs[0]) === null || _a === void 0 ? void 0 : _a.length); i++) {
655
706
  let counter = 0;
@@ -668,9 +719,10 @@ const model = types
668
719
  * #getter
669
720
  */
670
721
  get rows() {
722
+ const MSA = this.MSA;
671
723
  return this.hierarchy
672
724
  .leaves()
673
- .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)])
674
726
  .filter((f) => !!f[1]);
675
727
  },
676
728
  /**
@@ -685,6 +737,12 @@ const model = types
685
737
  get columns2d() {
686
738
  return this.rows.map(r => r[1]).map(str => skipBlanks(this.blanks, str));
687
739
  },
740
+ /**
741
+ * #getter
742
+ */
743
+ get fontSize() {
744
+ return Math.max(8, self.rowHeight - 8);
745
+ },
688
746
  /**
689
747
  * #getter
690
748
  */
@@ -708,13 +766,13 @@ const model = types
708
766
  * generates a new tree that is clustered with x,y positions
709
767
  */
710
768
  get hierarchy() {
711
- const root = this.root;
769
+ const r = this.root;
712
770
  const clust = cluster()
713
771
  .size([this.totalHeight, self.treeWidth])
714
772
  .separation(() => 1);
715
- clust(root);
716
- setBrLength(root, (root.data.length = 0), self.treeWidth / maxLength(root));
717
- return root;
773
+ clust(r);
774
+ setBrLength(r, (r.data.length = 0), self.treeWidth / maxLength(r));
775
+ return r;
718
776
  },
719
777
  /**
720
778
  * #getter
@@ -751,7 +809,13 @@ const model = types
751
809
  * #action
752
810
  */
753
811
  doScrollX(deltaX) {
754
- self.scrollX = clamp(-self.numColumns + (self.msaAreaWidth - 100), self.scrollX + deltaX, 0);
812
+ self.scrollX = clamp(-(self.numColumns * self.colWidth) + (self.msaAreaWidth - 100), self.scrollX + deltaX, 0);
813
+ },
814
+ /**
815
+ * #action
816
+ */
817
+ setScrollX(n) {
818
+ self.scrollX = clamp(-(self.numColumns * self.colWidth) + (self.msaAreaWidth - 100), n, 0);
755
819
  },
756
820
  /**
757
821
  * #action
@@ -787,6 +851,20 @@ const model = types
787
851
  },
788
852
  }))
789
853
  .views(self => ({
854
+ /**
855
+ * #getter
856
+ */
857
+ get labelsWidth() {
858
+ var _a;
859
+ let x = 0;
860
+ const { rowHeight, hierarchy, treeMetadata, fontSize } = self;
861
+ if (rowHeight > 5) {
862
+ for (const node of hierarchy.leaves()) {
863
+ x = Math.max(measureText(((_a = treeMetadata[node.data.name]) === null || _a === void 0 ? void 0 : _a.genome) || node.data.name, fontSize), x);
864
+ }
865
+ }
866
+ return x;
867
+ },
790
868
  /**
791
869
  * #getter
792
870
  */
@@ -818,62 +896,33 @@ const model = types
818
896
  /**
819
897
  * #getter
820
898
  */
821
- get tracks() {
822
- const blanks = self.blanks;
823
- const adapterTracks = self.MSA
824
- ? self.MSA.tracks.map(track => {
825
- const { data } = track;
826
- return {
827
- model: {
828
- ...track,
829
- data: data ? skipBlanks(blanks, data) : undefined,
830
- height: self.rowHeight,
831
- },
832
- ReactComponent: TextTrack,
833
- };
834
- })
835
- : [];
836
- const boxTracks = self.boxTracks
837
- // filter out tracks that are associated with hidden rows
838
- .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))
839
916
  .map(track => ({
840
917
  model: track,
841
918
  ReactComponent: BoxTrack,
842
919
  }));
843
- const annotationTracks = self.annotatedRegions.length > 0
844
- ? [
845
- {
846
- model: {
847
- features: self.annotatedRegions,
848
- height: 100,
849
- id: 'annotations',
850
- name: 'User-created annotations',
851
- data: self.annotatedRegions
852
- .map(region => {
853
- const attrs = region.attributes
854
- ? Object.entries(region.attributes)
855
- .map(([k, v]) => `${k}=${v.join(',')}`)
856
- .join(';')
857
- : '.';
858
- return [
859
- 'MSA_refcoord',
860
- '.',
861
- '.',
862
- region.start,
863
- region.end,
864
- '.',
865
- '.',
866
- '.',
867
- attrs,
868
- ].join('\t');
869
- })
870
- .join('\n'),
871
- },
872
- ReactComponent: BoxTrack,
873
- },
874
- ]
875
- : [];
876
- return [...adapterTracks, ...boxTracks, ...annotationTracks];
920
+ },
921
+ /**
922
+ * #getter
923
+ */
924
+ get tracks() {
925
+ return [...this.adapterTrackModels, ...this.boxTrackModels];
877
926
  },
878
927
  /**
879
928
  * #getter
@@ -953,6 +1002,28 @@ const model = types
953
1002
  }
954
1003
  return 0;
955
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
+ },
956
1027
  /**
957
1028
  * #method
958
1029
  */
@@ -967,28 +1038,69 @@ const model = types
967
1038
  return j;
968
1039
  },
969
1040
  }))
970
- .actions(self => ({
1041
+ .views(self => ({
971
1042
  /**
972
- * #action
1043
+ * #getter
1044
+ * total height of track area (px)
973
1045
  */
974
- addAnnotation(start, end, attributes) {
975
- self.annotatedRegions.push({
976
- start: self.getPos(start),
977
- end: self.getPos(end),
978
- attributes,
979
- });
1046
+ get totalTrackAreaHeight() {
1047
+ return sum(self.turnedOnTracks.map(r => r.model.height));
980
1048
  },
1049
+ }))
1050
+ .actions(self => ({
981
1051
  /**
982
1052
  * #action
1053
+ * internal, used for drawing to canvas
983
1054
  */
984
- setAnnotationClickBoundaries(left, right) {
985
- self.annotPos = { left, right };
1055
+ incrementRef() {
1056
+ self.nref++;
986
1057
  },
987
- /**
988
- * #action
989
- */
990
- clearAnnotationClickBoundaries() {
991
- self.annotPos = undefined;
1058
+ afterCreate() {
1059
+ // autorun opens treeFilehandle
1060
+ addDisposer(self, autorun(async () => {
1061
+ const { treeFilehandle } = self;
1062
+ if (treeFilehandle) {
1063
+ try {
1064
+ self.setTree(await openLocation(treeFilehandle).readFile('utf8'));
1065
+ }
1066
+ catch (e) {
1067
+ console.error(e);
1068
+ self.setError(e);
1069
+ }
1070
+ }
1071
+ }));
1072
+ // autorun opens treeMetadataFilehandle
1073
+ addDisposer(self, autorun(async () => {
1074
+ const { treeMetadataFilehandle } = self;
1075
+ if (treeMetadataFilehandle) {
1076
+ try {
1077
+ self.setTreeMetadata(await openLocation(treeMetadataFilehandle).readFile('utf8'));
1078
+ }
1079
+ catch (e) {
1080
+ console.error(e);
1081
+ self.setError(e);
1082
+ }
1083
+ }
1084
+ }));
1085
+ // autorun opens msaFilehandle
1086
+ addDisposer(self, autorun(async () => {
1087
+ const { msaFilehandle } = self;
1088
+ if (msaFilehandle) {
1089
+ try {
1090
+ self.setMSA(await openLocation(msaFilehandle).readFile('utf8'));
1091
+ }
1092
+ catch (e) {
1093
+ console.error(e);
1094
+ self.setError(e);
1095
+ }
1096
+ }
1097
+ }));
1098
+ // autorun synchronizes treeWidth with treeAreaWidth
1099
+ addDisposer(self, autorun(async () => {
1100
+ if (self.treeWidthMatchesArea) {
1101
+ self.setTreeWidth(Math.max(50, self.treeAreaWidth - self.labelsWidth - 20));
1102
+ }
1103
+ }));
992
1104
  },
993
1105
  }))
994
1106
  .postProcessSnapshot(result => {