react-msaview 3.1.11 → 3.2.0

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 (191) hide show
  1. package/bundle/index.js +32 -31
  2. package/dist/colorSchemes.d.ts +2 -2
  3. package/dist/colorSchemes.js +3 -4
  4. package/dist/colorSchemes.js.map +1 -1
  5. package/dist/components/Loading.d.ts +1 -1
  6. package/dist/components/Loading.js +4 -4
  7. package/dist/components/Loading.js.map +1 -1
  8. package/dist/components/MSAView.d.ts +1 -1
  9. package/dist/components/MSAView.js +13 -9
  10. package/dist/components/MSAView.js.map +1 -1
  11. package/dist/components/ResizeHandles.d.ts +1 -1
  12. package/dist/components/ResizeHandles.js +2 -2
  13. package/dist/components/SequenceTextArea.js +4 -0
  14. package/dist/components/SequenceTextArea.js.map +1 -1
  15. package/dist/components/TextTrack.d.ts +1 -1
  16. package/dist/components/Track.d.ts +1 -1
  17. package/dist/components/VerticalScrollbar.d.ts +6 -0
  18. package/dist/components/VerticalScrollbar.js +65 -0
  19. package/dist/components/VerticalScrollbar.js.map +1 -0
  20. package/dist/components/dialogs/AddTrackDialog.d.ts +1 -1
  21. package/dist/components/dialogs/DomainDialog.d.ts +6 -0
  22. package/dist/components/dialogs/DomainDialog.js +19 -0
  23. package/dist/components/dialogs/DomainDialog.js.map +1 -0
  24. package/dist/components/dialogs/ExportSVGDialog.d.ts +1 -1
  25. package/dist/components/dialogs/FeatureDialog.d.ts +1 -1
  26. package/dist/components/dialogs/FeatureDialog.js.map +1 -1
  27. package/dist/components/dialogs/InterProScanDialog.d.ts +4 -4
  28. package/dist/components/dialogs/InterProScanDialog.js +37 -8
  29. package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
  30. package/dist/components/dialogs/MetadataDialog.d.ts +1 -1
  31. package/dist/components/dialogs/SettingsDialog.d.ts +1 -1
  32. package/dist/components/dialogs/SettingsDialog.js +10 -1
  33. package/dist/components/dialogs/SettingsDialog.js.map +1 -1
  34. package/dist/components/dialogs/TabPanel.d.ts +6 -0
  35. package/dist/components/dialogs/TabPanel.js +6 -0
  36. package/dist/components/dialogs/TabPanel.js.map +1 -0
  37. package/dist/components/dialogs/TracklistDialog.d.ts +1 -1
  38. package/dist/components/dialogs/UserProvidedDomainsDialog.d.ts +7 -0
  39. package/dist/components/dialogs/UserProvidedDomainsDialog.js +58 -0
  40. package/dist/components/dialogs/UserProvidedDomainsDialog.js.map +1 -0
  41. package/dist/components/header/Header.d.ts +1 -1
  42. package/dist/components/header/Header.js +8 -5
  43. package/dist/components/header/Header.js.map +1 -1
  44. package/dist/components/header/HeaderInfoArea.d.ts +1 -1
  45. package/dist/components/header/HeaderMenu.d.ts +1 -1
  46. package/dist/components/header/HeaderMenuExtra.d.ts +1 -1
  47. package/dist/components/header/HeaderMenuExtra.js +54 -41
  48. package/dist/components/header/HeaderMenuExtra.js.map +1 -1
  49. package/dist/components/header/HeaderStatusArea.d.ts +1 -1
  50. package/dist/components/header/HeaderStatusArea.js +2 -1
  51. package/dist/components/header/HeaderStatusArea.js.map +1 -1
  52. package/dist/components/header/MultiAlignmentSelector.d.ts +1 -1
  53. package/dist/components/header/ZoomControls.js +31 -1
  54. package/dist/components/header/ZoomControls.js.map +1 -1
  55. package/dist/components/import/ImportForm.d.ts +1 -1
  56. package/dist/components/import/ImportForm.js +1 -1
  57. package/dist/components/import/ImportForm.js.map +1 -1
  58. package/dist/components/import/ImportFormExamples.d.ts +1 -1
  59. package/dist/components/import/ImportFormExamples.js +10 -8
  60. package/dist/components/import/ImportFormExamples.js.map +1 -1
  61. package/dist/components/import/util.d.ts +2 -2
  62. package/dist/components/minimap/Minimap.d.ts +1 -1
  63. package/dist/components/minimap/Minimap.js +14 -15
  64. package/dist/components/minimap/Minimap.js.map +1 -1
  65. package/dist/components/minimap/MinimapSVG.d.ts +1 -1
  66. package/dist/components/minimap/MinimapSVG.js +1 -1
  67. package/dist/components/minimap/MinimapSVG.js.map +1 -1
  68. package/dist/components/msa/MSACanvas.d.ts +1 -1
  69. package/dist/components/msa/MSACanvas.js +3 -3
  70. package/dist/components/msa/MSACanvas.js.map +1 -1
  71. package/dist/components/msa/MSACanvasBlock.d.ts +3 -3
  72. package/dist/components/msa/MSACanvasBlock.js +4 -3
  73. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  74. package/dist/components/msa/MSAMouseoverCanvas.d.ts +2 -2
  75. package/dist/components/msa/MSAMouseoverCanvas.js +1 -1
  76. package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
  77. package/dist/components/msa/MSAPanel.d.ts +1 -1
  78. package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +1 -1
  79. package/dist/components/msa/renderBoxFeatureCanvasBlock.js +2 -3
  80. package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
  81. package/dist/components/msa/renderMSABlock.d.ts +2 -2
  82. package/dist/components/msa/renderMSABlock.js +12 -12
  83. package/dist/components/msa/renderMSABlock.js.map +1 -1
  84. package/dist/components/msa/renderMSAMouseover.d.ts +1 -1
  85. package/dist/components/tree/TreeBranchMenu.d.ts +1 -1
  86. package/dist/components/tree/TreeCanvas.d.ts +1 -1
  87. package/dist/components/tree/TreeCanvas.js +13 -12
  88. package/dist/components/tree/TreeCanvas.js.map +1 -1
  89. package/dist/components/tree/TreeCanvasBlock.d.ts +1 -1
  90. package/dist/components/tree/TreeCanvasBlock.js +2 -1
  91. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  92. package/dist/components/tree/TreeNodeMenu.d.ts +1 -1
  93. package/dist/components/tree/TreeNodeMenu.js +2 -2
  94. package/dist/components/tree/TreeNodeMenu.js.map +1 -1
  95. package/dist/components/tree/TreePanel.d.ts +1 -1
  96. package/dist/components/tree/TreeRuler.d.ts +1 -1
  97. package/dist/components/tree/dialogs/TreeNodeInfoDialog.d.ts +1 -1
  98. package/dist/components/tree/renderTreeCanvas.d.ts +3 -3
  99. package/dist/components/tree/renderTreeCanvas.js +25 -9
  100. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  101. package/dist/components/util.js +1 -1
  102. package/dist/components/util.js.map +1 -1
  103. package/dist/fetchUtils.d.ts +1 -1
  104. package/dist/fetchUtils.js.map +1 -1
  105. package/dist/launchInterProScan.d.ts +9 -3
  106. package/dist/launchInterProScan.js +57 -22
  107. package/dist/launchInterProScan.js.map +1 -1
  108. package/dist/model/DataModel.d.ts +5 -1
  109. package/dist/model/DataModel.js +10 -1
  110. package/dist/model/DataModel.js.map +1 -1
  111. package/dist/model/DialogQueue.d.ts +1 -1
  112. package/dist/model.d.ts +138 -43
  113. package/dist/model.js +235 -110
  114. package/dist/model.js.map +1 -1
  115. package/dist/parseNewick.js +1 -1
  116. package/dist/parseNewick.js.map +1 -1
  117. package/dist/parsers/ClustalMSA.d.ts +1 -1
  118. package/dist/parsers/FastaMSA.d.ts +1 -1
  119. package/dist/parsers/StockholmMSA.d.ts +1 -1
  120. package/dist/parsers/StockholmMSA.js.map +1 -1
  121. package/dist/renderToSvg.d.ts +2 -2
  122. package/dist/renderToSvg.js +3 -28
  123. package/dist/renderToSvg.js.map +1 -1
  124. package/dist/reparseTree.d.ts +1 -1
  125. package/dist/util.d.ts +2 -2
  126. package/dist/util.js +0 -2
  127. package/dist/util.js.map +1 -1
  128. package/dist/version.d.ts +1 -1
  129. package/dist/version.js +1 -1
  130. package/dist/version.js.map +1 -1
  131. package/package.json +5 -2
  132. package/src/colorSchemes.ts +3 -2
  133. package/src/components/Checkbox2.tsx +1 -1
  134. package/src/components/Loading.tsx +11 -5
  135. package/src/components/MSAView.tsx +27 -18
  136. package/src/components/ResizeHandles.tsx +3 -3
  137. package/src/components/SequenceTextArea.tsx +8 -0
  138. package/src/components/TextTrack.tsx +1 -1
  139. package/src/components/Track.tsx +1 -1
  140. package/src/components/VerticalScrollbar.tsx +85 -0
  141. package/src/components/dialogs/AddTrackDialog.tsx +2 -2
  142. package/src/components/dialogs/DomainDialog.tsx +38 -0
  143. package/src/components/dialogs/ExportSVGDialog.tsx +1 -1
  144. package/src/components/dialogs/FeatureDialog.tsx +3 -3
  145. package/src/components/dialogs/InterProScanDialog.tsx +49 -11
  146. package/src/components/dialogs/MetadataDialog.tsx +1 -1
  147. package/src/components/dialogs/SettingsDialog.tsx +38 -3
  148. package/src/components/dialogs/TabPanel.tsx +19 -0
  149. package/src/components/dialogs/TracklistDialog.tsx +1 -1
  150. package/src/components/dialogs/UserProvidedDomainsDialog.tsx +133 -0
  151. package/src/components/header/Header.tsx +9 -6
  152. package/src/components/header/HeaderInfoArea.tsx +1 -1
  153. package/src/components/header/HeaderMenu.tsx +1 -1
  154. package/src/components/header/HeaderMenuExtra.tsx +65 -48
  155. package/src/components/header/HeaderStatusArea.tsx +3 -2
  156. package/src/components/header/MultiAlignmentSelector.tsx +1 -1
  157. package/src/components/header/ZoomControls.tsx +34 -0
  158. package/src/components/import/ImportForm.tsx +3 -3
  159. package/src/components/import/ImportFormExamples.tsx +19 -17
  160. package/src/components/import/util.ts +2 -2
  161. package/src/components/minimap/Minimap.tsx +15 -22
  162. package/src/components/minimap/MinimapSVG.tsx +2 -2
  163. package/src/components/msa/MSACanvas.tsx +11 -4
  164. package/src/components/msa/MSACanvasBlock.tsx +5 -4
  165. package/src/components/msa/MSAMouseoverCanvas.tsx +2 -6
  166. package/src/components/msa/MSAPanel.tsx +1 -1
  167. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +5 -6
  168. package/src/components/msa/renderMSABlock.ts +37 -17
  169. package/src/components/msa/renderMSAMouseover.ts +1 -1
  170. package/src/components/tree/TreeBranchMenu.tsx +1 -1
  171. package/src/components/tree/TreeCanvas.tsx +15 -16
  172. package/src/components/tree/TreeCanvasBlock.tsx +3 -2
  173. package/src/components/tree/TreeNodeMenu.tsx +3 -3
  174. package/src/components/tree/TreePanel.tsx +1 -1
  175. package/src/components/tree/TreeRuler.tsx +1 -1
  176. package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +1 -1
  177. package/src/components/tree/renderTreeCanvas.ts +32 -12
  178. package/src/components/util.ts +1 -1
  179. package/src/fetchUtils.ts +2 -2
  180. package/src/launchInterProScan.ts +69 -24
  181. package/src/model/DataModel.ts +10 -0
  182. package/src/model/DialogQueue.ts +1 -1
  183. package/src/model.ts +262 -143
  184. package/src/parseNewick.ts +1 -1
  185. package/src/parsers/ClustalMSA.ts +1 -1
  186. package/src/parsers/FastaMSA.ts +1 -1
  187. package/src/parsers/StockholmMSA.ts +1 -1
  188. package/src/renderToSvg.tsx +6 -30
  189. package/src/reparseTree.ts +1 -1
  190. package/src/util.ts +2 -4
  191. package/src/version.ts +1 -1
@@ -1,10 +1,10 @@
1
- import { HierarchyNode } from 'd3-hierarchy'
2
- import { Theme } from '@mui/material'
1
+ import type { HierarchyNode } from 'd3-hierarchy'
2
+ import type { Theme } from '@mui/material'
3
3
 
4
4
  // locals
5
- import { MsaViewModel } from '../../model'
5
+ import type { MsaViewModel } from '../../model'
6
6
  import { getClustalXColor, getPercentIdentityColor } from '../../colorSchemes'
7
- import { NodeWithIdsAndLength } from '../../util'
7
+ import type { NodeWithIdsAndLength } from '../../util'
8
8
 
9
9
  export function renderMSABlock({
10
10
  model,
@@ -28,13 +28,13 @@ export function renderMSABlock({
28
28
  blockSizeYOverride?: number
29
29
  }) {
30
30
  const {
31
- hierarchy,
32
31
  colWidth,
33
32
  blockSize,
34
33
  rowHeight,
35
34
  fontSize,
36
35
  highResScaleFactor,
37
- featureMode,
36
+ actuallyShowDomains,
37
+ leaves,
38
38
  } = model
39
39
  const k = highResScaleFactorOverride || highResScaleFactor
40
40
  const bx = blockSizeXOverride || blockSize
@@ -45,15 +45,13 @@ export function renderMSABlock({
45
45
  ctx.textAlign = 'center'
46
46
  ctx.font = ctx.font.replace(/\d+px/, `${fontSize}px`)
47
47
 
48
- const leaves = hierarchy.leaves()
49
-
50
48
  const yStart = Math.max(0, Math.floor((offsetY - rowHeight) / rowHeight))
51
49
  const yEnd = Math.max(0, Math.ceil((offsetY + by + rowHeight) / rowHeight))
52
50
  const xStart = Math.max(0, Math.floor(offsetX / colWidth))
53
51
  const xEnd = Math.max(0, Math.ceil((offsetX + bx) / colWidth))
54
52
  const visibleLeaves = leaves.slice(yStart, yEnd)
55
53
 
56
- if (!featureMode) {
54
+ if (!actuallyShowDomains) {
57
55
  drawTiles({
58
56
  model,
59
57
  ctx,
@@ -101,6 +99,7 @@ function drawTiles({
101
99
  colorSchemeName,
102
100
  colorScheme,
103
101
  colStats,
102
+ colStatsSums,
104
103
  columns,
105
104
  colWidth,
106
105
  rowHeight,
@@ -116,19 +115,30 @@ function drawTiles({
116
115
  const letter = str[i]
117
116
  const color =
118
117
  colorSchemeName === 'clustalx_protein_dynamic'
119
- ? getClustalXColor(colStats[xStart + i], model, name, xStart + i)
118
+ ? getClustalXColor(
119
+ colStats[xStart + i],
120
+ colStatsSums[xStart + i],
121
+ model,
122
+ name,
123
+ xStart + i,
124
+ )
120
125
  : colorSchemeName === 'percent_identity_dynamic'
121
126
  ? getPercentIdentityColor(
122
127
  colStats[xStart + i],
128
+ colStatsSums[xStart + i],
123
129
  model,
124
130
  name,
125
131
  xStart + i,
126
132
  )
127
133
  : colorScheme[letter.toUpperCase()]
128
134
  if (bgColor) {
129
- const x = i * colWidth + offsetX - (offsetX % colWidth)
130
135
  ctx.fillStyle = color || theme.palette.background.default
131
- ctx.fillRect(x, y - rowHeight, colWidth, rowHeight)
136
+ ctx.fillRect(
137
+ i * colWidth + offsetX - (offsetX % colWidth),
138
+ y - rowHeight,
139
+ colWidth,
140
+ rowHeight,
141
+ )
132
142
  }
133
143
  }
134
144
  }
@@ -152,9 +162,17 @@ function drawText({
152
162
  xStart: number
153
163
  xEnd: number
154
164
  }) {
155
- const { bgColor, featureMode, colorScheme, columns, colWidth, rowHeight } =
156
- model
157
- if (rowHeight >= 5 && colWidth > rowHeight / 2) {
165
+ const {
166
+ bgColor,
167
+ actuallyShowDomains,
168
+ showMsaLetters,
169
+ colorScheme,
170
+ columns,
171
+ colWidth,
172
+ contrastLettering,
173
+ rowHeight,
174
+ } = model
175
+ if (showMsaLetters) {
158
176
  for (const node of visibleLeaves) {
159
177
  const {
160
178
  data: { name },
@@ -164,11 +182,13 @@ function drawText({
164
182
  for (let i = 0; i < str?.length; i++) {
165
183
  const letter = str[i]
166
184
  const color = colorScheme[letter.toUpperCase()]
167
- const contrast = contrastScheme[letter.toUpperCase()] || 'black'
185
+ const contrast = contrastLettering
186
+ ? contrastScheme[letter.toUpperCase()] || 'black'
187
+ : 'black'
168
188
  const x = i * colWidth + offsetX - (offsetX % colWidth)
169
189
 
170
190
  // note: -rowHeight/4 matches +rowHeight/4 in tree
171
- ctx.fillStyle = featureMode
191
+ ctx.fillStyle = actuallyShowDomains
172
192
  ? 'black'
173
193
  : bgColor
174
194
  ? contrast
@@ -1,4 +1,4 @@
1
- import { MsaViewModel } from '../../model'
1
+ import type { MsaViewModel } from '../../model'
2
2
 
3
3
  const hoverColor = 'rgba(0,0,0,0.15)'
4
4
  const highlightColor = 'rgba(128,128,0,0.2)'
@@ -3,7 +3,7 @@ import { Menu, MenuItem } from '@mui/material'
3
3
  import { observer } from 'mobx-react'
4
4
 
5
5
  // locals
6
- import { MsaViewModel } from '../../model'
6
+ import type { MsaViewModel } from '../../model'
7
7
 
8
8
  interface Node {
9
9
  x: number
@@ -1,8 +1,9 @@
1
- import React, { useEffect, useRef, useState } from 'react'
1
+ import React from 'react'
2
+ import { useEffect, useRef, useState } from 'react'
2
3
  import { observer } from 'mobx-react'
3
4
 
4
5
  // locals
5
- import { MsaViewModel } from '../../model'
6
+ import type { MsaViewModel } from '../../model'
6
7
  import TreeCanvasBlock from './TreeCanvasBlock'
7
8
  import { padding } from './renderTreeCanvas'
8
9
 
@@ -48,7 +49,8 @@ const TreeCanvas = observer(function ({ model }: { model: MsaViewModel }) {
48
49
  const distanceY = currY - prevY.current
49
50
  if (distanceY) {
50
51
  // use rAF to make it so multiple event handlers aren't fired per-frame
51
- // see https://calendar.perfplanet.com/2013/the-runtime-performance-checklist/
52
+ // see
53
+ // https://calendar.perfplanet.com/2013/the-runtime-performance-checklist/
52
54
  if (!scheduled.current) {
53
55
  scheduled.current = true
54
56
  window.requestAnimationFrame(() => {
@@ -92,23 +94,20 @@ const TreeCanvas = observer(function ({ model }: { model: MsaViewModel }) {
92
94
  }
93
95
  }
94
96
 
95
- // this local mouseup is used in addition to the global because sometimes
96
- // the global add/remove are not called in time, resulting in issue #533
97
- function mouseUp(event: React.MouseEvent) {
98
- event.preventDefault()
99
- setMouseDragging(false)
100
- }
101
-
102
- function mouseLeave(event: React.MouseEvent) {
103
- event.preventDefault()
104
- }
105
-
106
97
  return (
107
98
  <div
108
99
  ref={ref}
109
100
  onMouseDown={mouseDown}
110
- onMouseUp={mouseUp}
111
- onMouseLeave={mouseLeave}
101
+ onMouseUp={event => {
102
+ // this local mouseup is used in addition to the global because
103
+ // sometimes the global add/remove are not called in time, resulting in
104
+ // issue #533
105
+ event.preventDefault()
106
+ setMouseDragging(false)
107
+ }}
108
+ onMouseLeave={event => {
109
+ event.preventDefault()
110
+ }}
112
111
  style={{
113
112
  height,
114
113
  position: 'relative',
@@ -1,11 +1,12 @@
1
- import React, { useCallback, useEffect, useRef, useState } from 'react'
1
+ import React from 'react'
2
+ import { useCallback, useEffect, useRef, useState } from 'react'
2
3
  import { autorun } from 'mobx'
3
4
  import { observer } from 'mobx-react'
4
5
  import { useTheme } from '@mui/material'
5
6
  import RBush from 'rbush'
6
7
 
7
8
  // locals
8
- import { MsaViewModel } from '../../model'
9
+ import type { MsaViewModel } from '../../model'
9
10
  import TreeNodeMenu from './TreeNodeMenu'
10
11
  import TreeBranchMenu from './TreeBranchMenu'
11
12
  import { padding, renderTreeCanvas } from './renderTreeCanvas'
@@ -3,7 +3,7 @@ import { Menu, MenuItem } from '@mui/material'
3
3
  import { observer } from 'mobx-react'
4
4
 
5
5
  // locals
6
- import { MsaViewModel } from '../../model'
6
+ import type { MsaViewModel } from '../../model'
7
7
 
8
8
  // lazies
9
9
  const TreeNodeInfoDialog = lazy(() => import('./dialogs/TreeNodeInfoDialog'))
@@ -17,7 +17,7 @@ const TreeMenu = observer(function ({
17
17
  model: MsaViewModel
18
18
  onClose: () => void
19
19
  }) {
20
- const { collapsed, collapsed2 } = model
20
+ const { collapsed, collapsedLeaves } = model
21
21
  return (
22
22
  <Menu
23
23
  anchorReference="anchorPosition"
@@ -66,7 +66,7 @@ const TreeMenu = observer(function ({
66
66
  onClose()
67
67
  }}
68
68
  >
69
- {collapsed.includes(node.id) || collapsed2.includes(node.id)
69
+ {collapsed.includes(node.id) || collapsedLeaves.includes(node.id)
70
70
  ? 'Show node'
71
71
  : 'Hide node'}
72
72
  </MenuItem>
@@ -1,7 +1,7 @@
1
1
  import React from 'react'
2
2
  import { observer } from 'mobx-react'
3
3
 
4
- import { MsaViewModel } from '../../model'
4
+ import type { MsaViewModel } from '../../model'
5
5
  import TreeCanvas from './TreeCanvas'
6
6
 
7
7
  const TreePanel = observer(function ({ model }: { model: MsaViewModel }) {
@@ -2,7 +2,7 @@ import React from 'react'
2
2
  import { observer } from 'mobx-react'
3
3
 
4
4
  // locals
5
- import { MsaViewModel } from '../../model'
5
+ import type { MsaViewModel } from '../../model'
6
6
 
7
7
  const TreeRuler = observer(({ model }: { model: MsaViewModel }) => {
8
8
  const { treeAreaWidth } = model
@@ -8,7 +8,7 @@ import {
8
8
  } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
9
9
 
10
10
  // locals
11
- import { MsaViewModel } from '../../../model'
11
+ import type { MsaViewModel } from '../../../model'
12
12
  import SequenceTextArea from '../../SequenceTextArea'
13
13
 
14
14
  export default observer(function ({
@@ -1,8 +1,8 @@
1
- import RBush from 'rbush'
2
- import { Theme } from '@mui/material'
1
+ import type RBush from 'rbush'
2
+ import type { Theme } from '@mui/material'
3
3
 
4
4
  // locals
5
- import { MsaViewModel } from '../../model'
5
+ import type { MsaViewModel } from '../../model'
6
6
 
7
7
  export const padding = 600
8
8
 
@@ -38,6 +38,9 @@ export function renderTree({
38
38
  ctx.strokeStyle = theme.palette.text.primary
39
39
  for (const link of hierarchy.links()) {
40
40
  const { source, target } = link
41
+ if (target.height === 0 && !showBranchLen) {
42
+ continue
43
+ }
41
44
  const sy = source.x!
42
45
  const ty = target.x!
43
46
  // @ts-expect-error
@@ -87,10 +90,9 @@ export function renderNodeBubbles({
87
90
  // @ts-expect-error
88
91
  const { [val]: x, data } = node
89
92
  const y = node.x!
90
- const { branchset, id = '', name = '' } = data
93
+ const { id = '', name = '' } = data
91
94
  if (
92
- !id.endsWith('-leafnode') &&
93
- branchset.length &&
95
+ node.height > 1 &&
94
96
  y > offsetY - extendBounds &&
95
97
  y < offsetY + by + extendBounds
96
98
  ) {
@@ -134,13 +136,19 @@ export function renderTreeLabels({
134
136
  showBranchLen,
135
137
  treeMetadata,
136
138
  hierarchy,
139
+ collapsed,
140
+ collapsedLeaves,
137
141
  blockSize,
138
142
  labelsAlignRight,
139
143
  drawTree,
140
144
  treeAreaWidth,
145
+ treeWidth,
141
146
  treeAreaWidthMinusMargin,
142
147
  marginLeft,
148
+ leaves,
143
149
  noTree,
150
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
151
+ rowHeight: _rowHeight, // this is needed for redrawing after zoom change
144
152
  } = model
145
153
  const by = blockSizeYOverride || blockSize
146
154
  if (labelsAlignRight) {
@@ -149,7 +157,7 @@ export function renderTreeLabels({
149
157
  } else {
150
158
  ctx.textAlign = 'start'
151
159
  }
152
- for (const node of hierarchy.leaves()) {
160
+ for (const node of leaves) {
153
161
  const {
154
162
  data: { name, id },
155
163
  // @ts-expect-error
@@ -162,7 +170,18 @@ export function renderTreeLabels({
162
170
  if (y > offsetY - extendBounds && y < offsetY + by + extendBounds) {
163
171
  // note: +rowHeight/4 matches with -rowHeight/4 in msa
164
172
  const yp = y + fontSize / 4
165
- const xp = (showBranchLen ? len : x) || 0
173
+ let xp = (showBranchLen ? len : x) || 0
174
+ if (
175
+ !showBranchLen &&
176
+ !collapsed.includes(id) &&
177
+ !collapsedLeaves.includes(id)
178
+ ) {
179
+ // this subtraction is a hack to compensate for the leafnode rendering
180
+ // glitch (issue #71). the context is that an extra leaf node is added
181
+ // so that 'collapsing/hiding leaf nodes is possible' but this causes
182
+ // weird workarounds
183
+ xp -= treeWidth / hierarchy.height
184
+ }
166
185
 
167
186
  const { width } = ctx.measureText(displayName)
168
187
  const height = ctx.measureText('M').width // use an 'em' for height
@@ -223,13 +242,12 @@ export function renderTreeCanvas({
223
242
  const {
224
243
  noTree,
225
244
  drawTree,
226
- drawLabels,
227
245
  drawNodeBubbles,
228
246
  treeWidth,
229
247
  highResScaleFactor,
230
248
  blockSize,
231
249
  fontSize,
232
- rowHeight,
250
+ showTreeText,
233
251
  marginLeft,
234
252
  nref,
235
253
  } = model
@@ -243,7 +261,9 @@ export function renderTreeCanvas({
243
261
  // is updated and in order to convince bundlers like not to delete unused
244
262
  // usage with propertyReadSideEffects
245
263
  const k =
246
- nref < 0 ? -Infinity : highResScaleFactorOverride || highResScaleFactor
264
+ nref < 0
265
+ ? Number.NEGATIVE_INFINITY
266
+ : highResScaleFactorOverride || highResScaleFactor
247
267
  ctx.scale(k, k)
248
268
  ctx.clearRect(0, 0, treeWidth + padding, by)
249
269
  ctx.translate(marginLeft, -offsetY)
@@ -272,7 +292,7 @@ export function renderTreeCanvas({
272
292
  }
273
293
  }
274
294
 
275
- if (rowHeight >= 5 && drawLabels) {
295
+ if (showTreeText) {
276
296
  renderTreeLabels({
277
297
  ctx,
278
298
  offsetY,
@@ -10,7 +10,7 @@ export function chooseGridPitch(
10
10
  ) {
11
11
  scale = Math.abs(scale)
12
12
  const minMajorPitchBp = minMajorPitchPx * scale
13
- const majorMagnitude = parseInt(
13
+ const majorMagnitude = Number.parseInt(
14
14
  Number(minMajorPitchBp).toExponential().split(/e/i)[1],
15
15
  10,
16
16
  )
package/src/fetchUtils.ts CHANGED
@@ -15,9 +15,9 @@ export async function textfetch(url: string, args?: RequestInit) {
15
15
  return response.text()
16
16
  }
17
17
 
18
- export async function jsonfetch(url: string, args?: RequestInit) {
18
+ export async function jsonfetch<T>(url: string, args?: RequestInit) {
19
19
  const response = await myfetch(url, args)
20
- return response.json()
20
+ return response.json() as T
21
21
  }
22
22
 
23
23
  export async function arraybufferfetch(url: string) {
@@ -1,6 +1,8 @@
1
+ import { getSession } from '@jbrowse/core/util'
1
2
  import { jsonfetch, textfetch, timeout } from './fetchUtils'
3
+ import type { MsaViewModel } from './model'
2
4
 
3
- const base = `https://www.ebi.ac.uk/Tools/services/rest`
5
+ const base = 'https://www.ebi.ac.uk/Tools/services/rest'
4
6
 
5
7
  export interface InterProScanResults {
6
8
  matches: {
@@ -24,11 +26,13 @@ async function runInterProScan({
24
26
  onProgress,
25
27
  onJobId,
26
28
  programs,
29
+ model,
27
30
  }: {
28
31
  seq: string
29
32
  programs: string[]
30
33
  onProgress: (arg?: { msg: string; url?: string }) => void
31
- onJobId: (arg: string) => void
34
+ onJobId?: (arg: string) => void
35
+ model: MsaViewModel
32
36
  }) {
33
37
  const jobId = await textfetch(`${base}/iprscan5/run`, {
34
38
  method: 'POST',
@@ -38,18 +42,18 @@ async function runInterProScan({
38
42
  programs: programs.join(','),
39
43
  }),
40
44
  })
41
- onJobId(jobId)
45
+ onJobId?.(jobId)
42
46
  await wait({
43
47
  jobId,
44
48
  onProgress,
45
49
  })
46
- return loadInterProScanResults(jobId)
50
+ return loadInterProScanResultsWithStatus({ jobId, model })
47
51
  }
48
52
 
49
- export async function loadInterProScanResults(jobId: string) {
50
- return (await jsonfetch(
53
+ export function loadInterProScanResults(jobId: string) {
54
+ return jsonfetch<InterProScanResponse>(
51
55
  `${base}/iprscan5/result/${jobId}/json`,
52
- )) as InterProScanResponse
56
+ )
53
57
  }
54
58
 
55
59
  async function wait({
@@ -60,17 +64,22 @@ async function wait({
60
64
  onProgress: (arg?: { msg: string; url?: string }) => void
61
65
  }) {
62
66
  const url = `${base}/iprscan5/status/${jobId}`
63
- // eslint-disable-next-line no-constant-condition
64
- while (true) {
65
- for (let i = 0; i < 10; i++) {
66
- await timeout(1000)
67
- onProgress({ msg: `Checking status... ${10 - i}`, url })
68
- }
69
- const result = await textfetch(url)
70
-
71
- if (result === 'FINISHED') {
72
- break
67
+ try {
68
+ while (true) {
69
+ for (let i = 0; i < 10; i++) {
70
+ await timeout(1000)
71
+ onProgress({ msg: `Checking status ${10 - i}`, url })
72
+ }
73
+ const result = await textfetch(url)
74
+ if (result.includes('FINISHED')) {
75
+ break
76
+ }
77
+ if (result.includes('FAILURE')) {
78
+ throw new Error(`Failed to run: jobId ${jobId}`)
79
+ }
73
80
  }
81
+ } finally {
82
+ onProgress()
74
83
  }
75
84
  }
76
85
 
@@ -80,19 +89,55 @@ export async function launchInterProScan({
80
89
  programs,
81
90
  onJobId,
82
91
  onProgress,
92
+ model,
83
93
  }: {
84
94
  algorithm: string
85
95
  seq: string
86
96
  programs: string[]
87
97
  onProgress: (arg?: { msg: string; url?: string }) => void
88
- onJobId: (arg: string) => void
98
+ onJobId?: (arg: string) => void
99
+ model: MsaViewModel
89
100
  }) {
90
- onProgress({ msg: `Launching ${algorithm} MSA...` })
91
- if (algorithm === 'interproscan') {
92
- const result = await runInterProScan({ seq, onJobId, onProgress, programs })
93
- onProgress()
94
- return result
95
- } else {
101
+ try {
102
+ onProgress({ msg: `Launching ${algorithm} MSA` })
103
+ if (algorithm === 'interproscan') {
104
+ const result = await runInterProScan({
105
+ seq,
106
+ onJobId,
107
+ onProgress,
108
+ programs,
109
+ model,
110
+ })
111
+ return result
112
+ }
96
113
  throw new Error('unknown algorithm')
114
+ } finally {
115
+ onProgress()
116
+ }
117
+ }
118
+
119
+ export async function loadInterProScanResultsWithStatus({
120
+ jobId,
121
+ model,
122
+ }: {
123
+ jobId: string
124
+ model: MsaViewModel
125
+ }) {
126
+ try {
127
+ model.setStatus({
128
+ msg: `Downloading results of ${jobId} (for larger sequences this can be slow, click status to download and upload in the manual tab)`,
129
+ url: `https://www.ebi.ac.uk/Tools/services/rest/iprscan5/result/${jobId}/json`,
130
+ })
131
+ const ret = await loadInterProScanResults(jobId)
132
+ model.setInterProAnnotations(
133
+ Object.fromEntries(ret.results.map(r => [r.xref[0].id, r])),
134
+ )
135
+ model.setShowDomains(true)
136
+ getSession(model).notify(`Loaded interproscan ${jobId} results`, 'success')
137
+ } catch (e) {
138
+ console.error(e)
139
+ getSession(model).notifyError(`${e}`, e)
140
+ } finally {
141
+ model.setStatus()
97
142
  }
98
143
  }
@@ -43,4 +43,14 @@ export function DataModelF() {
43
43
  self.treeMetadata = treeMetadata
44
44
  },
45
45
  }))
46
+ .postProcessSnapshot(snap => {
47
+ const { tree, msa, treeMetadata } = snap
48
+ const max = 50_000
49
+ return {
50
+ tree: tree && tree.length > max ? undefined : tree,
51
+ msa: msa && msa.length > max ? undefined : msa,
52
+ treeMetadata:
53
+ treeMetadata && treeMetadata.length > max ? undefined : treeMetadata,
54
+ }
55
+ })
46
56
  }
@@ -1,4 +1,4 @@
1
- import { DialogComponentType } from '@jbrowse/core/util'
1
+ import type { DialogComponentType } from '@jbrowse/core/util'
2
2
  import { types } from 'mobx-state-tree'
3
3
 
4
4
  /**