react-msaview 6.5.0 → 8.0.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 (414) hide show
  1. package/README.md +13 -11
  2. package/bundle/index.js +122 -112
  3. package/bundle/index.js.map +4 -4
  4. package/dist/colorSchemes.js +1 -2
  5. package/dist/colorSchemes.js.map +1 -1
  6. package/dist/columnStats.d.ts +28 -0
  7. package/dist/columnStats.js +34 -0
  8. package/dist/columnStats.js.map +1 -0
  9. package/dist/components/DragHandle.d.ts +3 -2
  10. package/dist/components/DragHandle.js +11 -5
  11. package/dist/components/DragHandle.js.map +1 -1
  12. package/dist/components/Loading.js +2 -2
  13. package/dist/components/Loading.js.map +1 -1
  14. package/dist/components/MSAView.js +17 -6
  15. package/dist/components/MSAView.js.map +1 -1
  16. package/dist/components/MSAViewer.d.ts +69 -4
  17. package/dist/components/MSAViewer.js +201 -8
  18. package/dist/components/MSAViewer.js.map +1 -1
  19. package/dist/components/PortalTooltip.d.ts +11 -0
  20. package/dist/components/PortalTooltip.js +29 -0
  21. package/dist/components/PortalTooltip.js.map +1 -0
  22. package/dist/components/ResizeHandles.d.ts +3 -3
  23. package/dist/components/ResizeHandles.js +13 -24
  24. package/dist/components/ResizeHandles.js.map +1 -1
  25. package/dist/components/SequenceTextArea.js +3 -3
  26. package/dist/components/SequenceTextArea.js.map +1 -1
  27. package/dist/components/Track.js +41 -22
  28. package/dist/components/Track.js.map +1 -1
  29. package/dist/components/dialogs/{InterProScanDialog.d.ts → AnnotationFileDialog.d.ts} +2 -2
  30. package/dist/components/dialogs/AnnotationFileDialog.js +92 -0
  31. package/dist/components/dialogs/AnnotationFileDialog.js.map +1 -0
  32. package/dist/components/dialogs/ExportSVGDialog.js +5 -3
  33. package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
  34. package/dist/components/dialogs/FeatureDialog.js +13 -9
  35. package/dist/components/dialogs/FeatureDialog.js.map +1 -1
  36. package/dist/components/dialogs/TrackInfoDialog.js +1 -1
  37. package/dist/components/dialogs/TrackInfoDialog.js.map +1 -1
  38. package/dist/components/header/GappynessSlider.js +6 -11
  39. package/dist/components/header/GappynessSlider.js.map +1 -1
  40. package/dist/components/header/Header.js +7 -0
  41. package/dist/components/header/Header.js.map +1 -1
  42. package/dist/components/header/HeaderStatusArea.js +0 -2
  43. package/dist/components/header/HeaderStatusArea.js.map +1 -1
  44. package/dist/components/header/LoadWarnings.d.ts +6 -0
  45. package/dist/components/header/LoadWarnings.js +35 -0
  46. package/dist/components/header/LoadWarnings.js.map +1 -0
  47. package/dist/components/header/MultiAlignmentSelector.js +0 -0
  48. package/dist/components/header/MultiAlignmentSelector.js.map +1 -1
  49. package/dist/components/header/ScrollZoomIcons.d.ts +6 -0
  50. package/dist/components/header/ScrollZoomIcons.js +35 -0
  51. package/dist/components/header/ScrollZoomIcons.js.map +1 -0
  52. package/dist/components/header/TreeSettingsMenu.js +7 -1
  53. package/dist/components/header/TreeSettingsMenu.js.map +1 -1
  54. package/dist/components/header/UnshareableDataWarning.d.ts +6 -0
  55. package/dist/components/header/UnshareableDataWarning.js +40 -0
  56. package/dist/components/header/UnshareableDataWarning.js.map +1 -0
  57. package/dist/components/header/ZoomControls.js +49 -6
  58. package/dist/components/header/ZoomControls.js.map +1 -1
  59. package/dist/components/header/getAnnotationsMenu.js +11 -14
  60. package/dist/components/header/getAnnotationsMenu.js.map +1 -1
  61. package/dist/components/header/settingsMenuItems.js +10 -7
  62. package/dist/components/header/settingsMenuItems.js.map +1 -1
  63. package/dist/components/import/ImportForm.js +1 -1
  64. package/dist/components/import/ImportForm.js.map +1 -1
  65. package/dist/components/import/ImportFormExamples.js +2 -6
  66. package/dist/components/import/ImportFormExamples.js.map +1 -1
  67. package/dist/components/import/util.js +2 -0
  68. package/dist/components/import/util.js.map +1 -1
  69. package/dist/components/minimap/Minimap.js +1 -2
  70. package/dist/components/minimap/Minimap.js.map +1 -1
  71. package/dist/components/msa/AnnotationLegend.js +27 -19
  72. package/dist/components/msa/AnnotationLegend.js.map +1 -1
  73. package/dist/components/msa/MSACanvas.js +1 -1
  74. package/dist/components/msa/MSACanvas.js.map +1 -1
  75. package/dist/components/msa/MSACanvasBlock.js +17 -20
  76. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  77. package/dist/components/msa/MSAMouseoverCanvas.js +2 -1
  78. package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
  79. package/dist/components/msa/domainBandCursor.d.ts +7 -11
  80. package/dist/components/msa/domainBandCursor.js +7 -11
  81. package/dist/components/msa/domainBandCursor.js.map +1 -1
  82. package/dist/components/msa/drawFeatureSpans.d.ts +53 -0
  83. package/dist/components/msa/drawFeatureSpans.js +78 -0
  84. package/dist/components/msa/drawFeatureSpans.js.map +1 -0
  85. package/dist/components/msa/legendRows.d.ts +8 -0
  86. package/dist/components/msa/legendRows.js +16 -0
  87. package/dist/components/msa/legendRows.js.map +1 -0
  88. package/dist/components/msa/msaRaster.d.ts +30 -27
  89. package/dist/components/msa/msaRaster.js +193 -90
  90. package/dist/components/msa/msaRaster.js.map +1 -1
  91. package/dist/components/msa/packDomainLanes.d.ts +20 -0
  92. package/dist/components/msa/packDomainLanes.js +33 -0
  93. package/dist/components/msa/packDomainLanes.js.map +1 -0
  94. package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +3 -1
  95. package/dist/components/msa/renderBoxFeatureCanvasBlock.js +51 -87
  96. package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
  97. package/dist/components/msa/renderHighlights.d.ts +44 -4
  98. package/dist/components/msa/renderHighlights.js +99 -11
  99. package/dist/components/msa/renderHighlights.js.map +1 -1
  100. package/dist/components/msa/renderMSABlock.d.ts +1 -2
  101. package/dist/components/msa/renderMSABlock.js +28 -31
  102. package/dist/components/msa/renderMSABlock.js.map +1 -1
  103. package/dist/components/msa/renderMSAMouseover.js +9 -30
  104. package/dist/components/msa/renderMSAMouseover.js.map +1 -1
  105. package/dist/components/msa/tileColor.js +4 -7
  106. package/dist/components/msa/tileColor.js.map +1 -1
  107. package/dist/components/msa/useMsaBlockMouse.d.ts +5 -3
  108. package/dist/components/msa/useMsaBlockMouse.js +6 -6
  109. package/dist/components/msa/useMsaBlockMouse.js.map +1 -1
  110. package/dist/components/renderCtx.d.ts +1 -1
  111. package/dist/components/rowpanels/RowPanelBlock.d.ts +9 -0
  112. package/dist/components/rowpanels/RowPanelBlock.js +86 -0
  113. package/dist/components/rowpanels/RowPanelBlock.js.map +1 -0
  114. package/dist/components/rowpanels/RowPanelHeaders.d.ts +12 -0
  115. package/dist/components/rowpanels/RowPanelHeaders.js +38 -0
  116. package/dist/components/rowpanels/RowPanelHeaders.js.map +1 -0
  117. package/dist/components/{msa/ColumnStats.d.ts → rowpanels/RowPanels.d.ts} +2 -2
  118. package/dist/components/rowpanels/RowPanels.js +32 -0
  119. package/dist/components/rowpanels/RowPanels.js.map +1 -0
  120. package/dist/components/rowpanels/headerLayout.d.ts +1 -0
  121. package/dist/components/rowpanels/headerLayout.js +5 -0
  122. package/dist/components/rowpanels/headerLayout.js.map +1 -0
  123. package/dist/components/rowpanels/renderFeaturePanel.d.ts +21 -0
  124. package/dist/components/rowpanels/renderFeaturePanel.js +37 -0
  125. package/dist/components/rowpanels/renderFeaturePanel.js.map +1 -0
  126. package/dist/components/rowpanels/renderRowPanel.d.ts +23 -0
  127. package/dist/components/rowpanels/renderRowPanel.js +22 -0
  128. package/dist/components/rowpanels/renderRowPanel.js.map +1 -0
  129. package/dist/components/rowpanels/renderStrip.d.ts +20 -0
  130. package/dist/components/rowpanels/renderStrip.js +26 -0
  131. package/dist/components/rowpanels/renderStrip.js.map +1 -0
  132. package/dist/components/tracks/TrackBlocks.js +13 -16
  133. package/dist/components/tracks/TrackBlocks.js.map +1 -1
  134. package/dist/components/tracks/TrackTooltipContent.d.ts +15 -0
  135. package/dist/components/tracks/TrackTooltipContent.js +109 -0
  136. package/dist/components/tracks/TrackTooltipContent.js.map +1 -0
  137. package/dist/components/tracks/drawTracks.d.ts +30 -12
  138. package/dist/components/tracks/drawTracks.js +127 -34
  139. package/dist/components/tracks/drawTracks.js.map +1 -1
  140. package/dist/components/tracks/useTrackHover.d.ts +22 -0
  141. package/dist/components/tracks/useTrackHover.js +30 -0
  142. package/dist/components/tracks/useTrackHover.js.map +1 -0
  143. package/dist/components/tree/CladeLabels.d.ts +12 -0
  144. package/dist/components/tree/CladeLabels.js +48 -0
  145. package/dist/components/tree/CladeLabels.js.map +1 -0
  146. package/dist/components/tree/TreeCanvas.js +6 -4
  147. package/dist/components/tree/TreeCanvas.js.map +1 -1
  148. package/dist/components/tree/TreeCanvasBlock.js +6 -21
  149. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  150. package/dist/components/tree/TreeOverview.d.ts +14 -0
  151. package/dist/components/tree/TreeOverview.js +75 -0
  152. package/dist/components/tree/TreeOverview.js.map +1 -0
  153. package/dist/components/tree/TreeRuler.js +11 -5
  154. package/dist/components/tree/TreeRuler.js.map +1 -1
  155. package/dist/components/tree/cladeBrackets.d.ts +25 -0
  156. package/dist/components/tree/cladeBrackets.js +51 -0
  157. package/dist/components/tree/cladeBrackets.js.map +1 -0
  158. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +2 -2
  159. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
  160. package/dist/components/tree/renderTreeCanvas.d.ts +0 -1
  161. package/dist/components/tree/renderTreeCanvas.js +221 -47
  162. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  163. package/dist/components/tree/renderTreeOverview.d.ts +52 -0
  164. package/dist/components/tree/renderTreeOverview.js +138 -0
  165. package/dist/components/tree/renderTreeOverview.js.map +1 -0
  166. package/dist/components/tree/scaleBar.d.ts +10 -0
  167. package/dist/components/tree/scaleBar.js +24 -0
  168. package/dist/components/tree/scaleBar.js.map +1 -0
  169. package/dist/components/tree/useTreeHover.js +2 -4
  170. package/dist/components/tree/useTreeHover.js.map +1 -1
  171. package/dist/constants.d.ts +18 -1
  172. package/dist/constants.js +51 -8
  173. package/dist/constants.js.map +1 -1
  174. package/dist/createPaletteMap.d.ts +7 -6
  175. package/dist/createPaletteMap.js +10 -9
  176. package/dist/createPaletteMap.js.map +1 -1
  177. package/dist/element.d.ts +13 -0
  178. package/dist/element.js +269 -0
  179. package/dist/element.js.map +1 -0
  180. package/dist/featureFields.d.ts +11 -0
  181. package/dist/featureFields.js +17 -0
  182. package/dist/featureFields.js.map +1 -0
  183. package/dist/fetchUtils.d.ts +7 -7
  184. package/dist/fetchUtils.js +4 -32
  185. package/dist/fetchUtils.js.map +1 -1
  186. package/dist/flatToTree.js +1 -2
  187. package/dist/flatToTree.js.map +1 -1
  188. package/dist/ggplotPalettes.d.ts +10 -0
  189. package/dist/ggplotPalettes.js +58 -0
  190. package/dist/ggplotPalettes.js.map +1 -1
  191. package/dist/hierarchy.d.ts +29 -1
  192. package/dist/hierarchy.js +82 -19
  193. package/dist/hierarchy.js.map +1 -1
  194. package/dist/index.d.ts +10 -1
  195. package/dist/index.js +10 -2
  196. package/dist/index.js.map +1 -1
  197. package/dist/model/DataModel.js +4 -4
  198. package/dist/model/DataModel.js.map +1 -1
  199. package/dist/model/msaModel.d.ts +3 -2
  200. package/dist/model/msaModel.js +3 -2
  201. package/dist/model/msaModel.js.map +1 -1
  202. package/dist/model/treeModel.d.ts +30 -0
  203. package/dist/model/treeModel.js +37 -1
  204. package/dist/model/treeModel.js.map +1 -1
  205. package/dist/model.d.ts +792 -259
  206. package/dist/model.js +2092 -675
  207. package/dist/model.js.map +1 -1
  208. package/dist/mount.d.ts +11 -0
  209. package/dist/mount.js +22 -0
  210. package/dist/mount.js.map +1 -0
  211. package/dist/neighborJoining.js +8 -32
  212. package/dist/neighborJoining.js.map +1 -1
  213. package/dist/renderToStaticMarkup.d.ts +15 -13
  214. package/dist/renderToStaticMarkup.js +37 -25
  215. package/dist/renderToStaticMarkup.js.map +1 -1
  216. package/dist/renderToSvg.js +198 -68
  217. package/dist/renderToSvg.js.map +1 -1
  218. package/dist/rowCoordinateCalculations.d.ts +26 -28
  219. package/dist/rowCoordinateCalculations.js +13 -39
  220. package/dist/rowCoordinateCalculations.js.map +1 -1
  221. package/dist/scales.d.ts +22 -0
  222. package/dist/scales.js +30 -0
  223. package/dist/scales.js.map +1 -0
  224. package/dist/seqPosToGlobalCol.d.ts +2 -3
  225. package/dist/seqPosToGlobalCol.js +5 -4
  226. package/dist/seqPosToGlobalCol.js.map +1 -1
  227. package/dist/sequenceLogo.d.ts +6 -11
  228. package/dist/sequenceLogo.js +6 -11
  229. package/dist/sequenceLogo.js.map +1 -1
  230. package/dist/stripDefault.d.ts +7 -14
  231. package/dist/stripDefault.js +7 -14
  232. package/dist/stripDefault.js.map +1 -1
  233. package/dist/svgTestUtil.d.ts +306 -124
  234. package/dist/types.d.ts +295 -3
  235. package/dist/umd.d.ts +2 -0
  236. package/dist/umd.js +4 -2
  237. package/dist/umd.js.map +1 -1
  238. package/dist/useCanvasAutorun.d.ts +5 -10
  239. package/dist/useCanvasAutorun.js +5 -10
  240. package/dist/useCanvasAutorun.js.map +1 -1
  241. package/dist/useMsaSvgFigure.d.ts +20 -0
  242. package/dist/useMsaSvgFigure.js +46 -0
  243. package/dist/useMsaSvgFigure.js.map +1 -0
  244. package/dist/util.d.ts +10 -4
  245. package/dist/util.js +37 -10
  246. package/dist/util.js.map +1 -1
  247. package/dist/version.d.ts +1 -1
  248. package/dist/version.js +1 -1
  249. package/dist/wuss.d.ts +14 -0
  250. package/dist/wuss.js +55 -0
  251. package/dist/wuss.js.map +1 -0
  252. package/package.json +23 -14
  253. package/src/colorSchemes.ts +1 -2
  254. package/src/columnStats.ts +58 -0
  255. package/src/components/DragHandle.tsx +18 -7
  256. package/src/components/Loading.tsx +14 -8
  257. package/src/components/MSAView.tsx +19 -5
  258. package/src/components/MSAViewer.tsx +326 -10
  259. package/src/components/PortalTooltip.tsx +47 -0
  260. package/src/components/ResizeHandles.tsx +21 -36
  261. package/src/components/SequenceTextArea.tsx +3 -3
  262. package/src/components/Track.tsx +55 -18
  263. package/src/components/dialogs/AnnotationFileDialog.tsx +162 -0
  264. package/src/components/dialogs/ExportSVGDialog.tsx +7 -2
  265. package/src/components/dialogs/FeatureDialog.tsx +13 -9
  266. package/src/components/dialogs/TrackInfoDialog.tsx +1 -1
  267. package/src/components/header/GappynessSlider.tsx +6 -11
  268. package/src/components/header/Header.tsx +10 -0
  269. package/src/components/header/HeaderStatusArea.tsx +0 -5
  270. package/src/components/header/LoadWarnings.tsx +48 -0
  271. package/src/components/header/MultiAlignmentSelector.tsx +0 -0
  272. package/src/components/header/ScrollZoomIcons.tsx +52 -0
  273. package/src/components/header/TreeSettingsMenu.tsx +7 -1
  274. package/src/components/header/UnshareableDataWarning.tsx +56 -0
  275. package/src/components/header/ZoomControls.tsx +74 -14
  276. package/src/components/header/getAnnotationsMenu.ts +13 -17
  277. package/src/components/header/settingsMenuItems.ts +11 -6
  278. package/src/components/import/ImportForm.tsx +2 -2
  279. package/src/components/import/ImportFormExamples.tsx +4 -8
  280. package/src/components/import/util.ts +2 -0
  281. package/src/components/minimap/Minimap.tsx +1 -2
  282. package/src/components/msa/AnnotationLegend.tsx +48 -38
  283. package/src/components/msa/MSACanvas.tsx +3 -5
  284. package/src/components/msa/MSACanvasBlock.tsx +17 -21
  285. package/src/components/msa/MSAMouseoverCanvas.tsx +2 -1
  286. package/src/components/msa/domainBandCursor.ts +7 -11
  287. package/src/components/msa/drawFeatureSpans.ts +150 -0
  288. package/src/components/msa/legendRows.ts +24 -0
  289. package/src/components/msa/msaRaster.ts +236 -88
  290. package/src/components/msa/packDomainLanes.ts +36 -0
  291. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +69 -123
  292. package/src/components/msa/renderHighlights.ts +141 -10
  293. package/src/components/msa/renderMSABlock.ts +29 -38
  294. package/src/components/msa/renderMSAMouseover.ts +9 -39
  295. package/src/components/msa/tileColor.ts +4 -7
  296. package/src/components/msa/useMsaBlockMouse.ts +6 -6
  297. package/src/components/renderCtx.ts +1 -0
  298. package/src/components/rowpanels/RowPanelBlock.tsx +139 -0
  299. package/src/components/rowpanels/RowPanelHeaders.tsx +57 -0
  300. package/src/components/rowpanels/RowPanels.tsx +77 -0
  301. package/src/components/rowpanels/headerLayout.ts +5 -0
  302. package/src/components/rowpanels/renderFeaturePanel.ts +66 -0
  303. package/src/components/rowpanels/renderRowPanel.ts +41 -0
  304. package/src/components/rowpanels/renderStrip.ts +46 -0
  305. package/src/components/tracks/TrackBlocks.tsx +13 -18
  306. package/src/components/tracks/TrackTooltipContent.tsx +156 -0
  307. package/src/components/tracks/drawTracks.ts +169 -38
  308. package/src/components/tracks/useTrackHover.ts +42 -0
  309. package/src/components/tree/CladeLabels.tsx +77 -0
  310. package/src/components/tree/TreeCanvas.tsx +4 -3
  311. package/src/components/tree/TreeCanvasBlock.tsx +10 -32
  312. package/src/components/tree/TreeOverview.tsx +106 -0
  313. package/src/components/tree/TreeRuler.tsx +29 -5
  314. package/src/components/tree/cladeBrackets.ts +73 -0
  315. package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +2 -2
  316. package/src/components/tree/renderTreeCanvas.ts +312 -48
  317. package/src/components/tree/renderTreeOverview.ts +212 -0
  318. package/src/components/tree/scaleBar.ts +23 -0
  319. package/src/components/tree/useTreeHover.ts +2 -4
  320. package/src/constants.ts +61 -8
  321. package/src/createPaletteMap.ts +10 -9
  322. package/src/element.ts +321 -0
  323. package/src/featureFields.ts +19 -0
  324. package/src/fetchUtils.ts +7 -40
  325. package/src/flatToTree.ts +1 -2
  326. package/src/ggplotPalettes.ts +60 -0
  327. package/src/hierarchy.ts +97 -20
  328. package/src/index.ts +46 -6
  329. package/src/model/DataModel.ts +5 -4
  330. package/src/model/msaModel.ts +3 -2
  331. package/src/model/treeModel.ts +42 -0
  332. package/src/model.ts +2492 -793
  333. package/src/mount.tsx +32 -0
  334. package/src/neighborJoining.ts +8 -32
  335. package/src/rawImports.d.ts +9 -0
  336. package/src/renderToStaticMarkup.ts +41 -25
  337. package/src/renderToSvg.tsx +365 -92
  338. package/src/rowCoordinateCalculations.ts +16 -62
  339. package/src/scales.ts +47 -0
  340. package/src/seqPosToGlobalCol.ts +5 -4
  341. package/src/sequenceLogo.ts +6 -11
  342. package/src/stripDefault.ts +7 -14
  343. package/src/types.ts +352 -12
  344. package/src/umd.ts +4 -2
  345. package/src/useCanvasAutorun.ts +5 -10
  346. package/src/useMsaSvgFigure.ts +72 -0
  347. package/src/util.ts +40 -14
  348. package/src/version.ts +1 -1
  349. package/src/wuss.ts +62 -0
  350. package/dist/components/dialogs/InterProScanDialog.js +0 -137
  351. package/dist/components/dialogs/InterProScanDialog.js.map +0 -1
  352. package/dist/components/dialogs/InterProScanFileDialog.d.ts +0 -7
  353. package/dist/components/dialogs/InterProScanFileDialog.js +0 -64
  354. package/dist/components/dialogs/InterProScanFileDialog.js.map +0 -1
  355. package/dist/components/msa/ColumnStats.js +0 -42
  356. package/dist/components/msa/ColumnStats.js.map +0 -1
  357. package/dist/launchInterProScan.d.ts +0 -13
  358. package/dist/launchInterProScan.js +0 -110
  359. package/dist/launchInterProScan.js.map +0 -1
  360. package/dist/useColorContrast.d.ts +0 -10
  361. package/dist/useColorContrast.js +0 -13
  362. package/dist/useColorContrast.js.map +0 -1
  363. package/src/clustalX.test.ts +0 -74
  364. package/src/colSpace.test.ts +0 -67
  365. package/src/collapseLogic.test.ts +0 -115
  366. package/src/colorSchemes.docs.test.ts +0 -57
  367. package/src/columnCounts.test.ts +0 -73
  368. package/src/columnStats.test.ts +0 -94
  369. package/src/columnTracks.test.ts +0 -97
  370. package/src/components/dialogs/InterProScanDialog.tsx +0 -214
  371. package/src/components/dialogs/InterProScanFileDialog.tsx +0 -138
  372. package/src/components/minimap/minimapLayout.test.ts +0 -71
  373. package/src/components/msa/ColumnStats.tsx +0 -54
  374. package/src/components/msa/msaRaster.test.ts +0 -145
  375. package/src/components/msa/renderBoxFeatureCanvasBlock.test.ts +0 -51
  376. package/src/components/tree/renderTreeCanvas.test.ts +0 -296
  377. package/src/dataInitialized.test.ts +0 -42
  378. package/src/domainBands.test.ts +0 -122
  379. package/src/domainLetterColor.test.ts +0 -80
  380. package/src/exportFileName.test.ts +0 -40
  381. package/src/fetchUtils.test.ts +0 -83
  382. package/src/flatToTree.test.ts +0 -51
  383. package/src/hierarchy.test.ts +0 -228
  384. package/src/highlights.test.ts +0 -70
  385. package/src/impgRender.test.tsx +0 -68
  386. package/src/largeTree.test.ts +0 -67
  387. package/src/launchInterProScan.ts +0 -167
  388. package/src/loadErrorDisplay.test.tsx +0 -102
  389. package/src/modelFilehandleLoaders.test.ts +0 -137
  390. package/src/modelReset.test.ts +0 -120
  391. package/src/neighborJoining.test.ts +0 -164
  392. package/src/parseAsn1.test.ts +0 -36
  393. package/src/propertyConservation.test.ts +0 -36
  394. package/src/renderColumnTracksSvg.test.tsx +0 -108
  395. package/src/renderDomainsSvg.test.tsx +0 -118
  396. package/src/renderHighlightsSvg.test.tsx +0 -85
  397. package/src/renderMinimapSvg.test.tsx +0 -62
  398. package/src/renderRasterSvg.test.tsx +0 -144
  399. package/src/renderSequenceLogoSvg.test.tsx +0 -165
  400. package/src/renderToSvg.test.tsx +0 -65
  401. package/src/reset.test.ts +0 -61
  402. package/src/rowCoordinateCalculations.test.ts +0 -211
  403. package/src/rowSpace.test.ts +0 -46
  404. package/src/segmentOverlay.test.ts +0 -70
  405. package/src/seqPosToGlobalCol.test.ts +0 -59
  406. package/src/sequenceLogo.test.ts +0 -88
  407. package/src/setFontSize.test.ts +0 -33
  408. package/src/stripDefault.test.ts +0 -48
  409. package/src/stripDefaultSnapshot.test.ts +0 -87
  410. package/src/treeMetadata.test.ts +0 -39
  411. package/src/useCanvasAutorun.test.tsx +0 -98
  412. package/src/useColorContrast.ts +0 -18
  413. package/src/viewChrome.test.tsx +0 -134
  414. package/src/wheelZoom.test.ts +0 -46
@@ -1,108 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { createJBrowseTheme } from '@jbrowse/core/ui/theme'
3
- import { enableStaticRendering } from 'mobx-react'
4
- import { beforeAll, expect, test } from 'vitest'
5
-
6
- import { installHeadlessRenderEnv } from './headlessRenderEnv.ts'
7
- import MSAModelF from './model.ts'
8
- import { renderToSvg } from './renderToSvg.tsx'
9
-
10
- import type { ColumnTrackSpec } from './types.ts'
11
-
12
- beforeAll(() => {
13
- enableStaticRendering(true)
14
- installHeadlessRenderEnv()
15
- })
16
-
17
- const msa = '>s1\nACGT\n>s2\nACGT\n'
18
- const colWidth = 20
19
- const barColor = '#123456'
20
-
21
- function makeModel(columnTracks: ColumnTrackSpec[]) {
22
- const model = MSAModelF().create({
23
- type: 'MsaView',
24
- msaFormat: 'fasta',
25
- height: 400,
26
- colWidth,
27
- data: { msa },
28
- columnTracks,
29
- })
30
- model.setWidth(1000)
31
- model.toggleTrack('conservation')
32
- return model
33
- }
34
-
35
- async function exportSvg(model: ReturnType<typeof makeModel>) {
36
- return renderToSvg(model, {
37
- theme: createJBrowseTheme(),
38
- exportType: 'entire',
39
- includeTracks: true,
40
- })
41
- }
42
-
43
- function rectsFilled(svg: string, fill: string) {
44
- return [...svg.matchAll(/<rect ([^>]*)\/?>/g)]
45
- .map(m => m[1]!)
46
- .filter(attrs => attrs.includes(`fill="${fill}"`))
47
- .map(attrs => ({
48
- x: Number(/x="([\d.-]+)"/.exec(attrs)?.[1]),
49
- width: Number(/width="([\d.-]+)"/.exec(attrs)?.[1]),
50
- height: Number(/height="([\d.-]+)"/.exec(attrs)?.[1]),
51
- }))
52
- }
53
-
54
- test('a bar track from values exports one bar per column in its color', async () => {
55
- const model = makeModel([
56
- {
57
- id: 'dnds',
58
- name: 'dN/dS',
59
- kind: 'bar',
60
- values: [1, 0.5, 0, 0.25],
61
- color: barColor,
62
- },
63
- ])
64
- const bars = rectsFilled(await exportSvg(model), barColor).sort(
65
- (a, b) => a.x - b.x,
66
- )
67
- const trackHeight = model.conservationTrackHeight
68
- expect(bars.map(b => b.x)).toEqual([0, colWidth, colWidth * 2, colWidth * 3])
69
- expect(bars.map(b => b.height)).toEqual([
70
- trackHeight,
71
- trackHeight / 2,
72
- 0,
73
- trackHeight / 4,
74
- ])
75
- expect(svgNamesTrack(await exportSvg(model))).toContain('dN/dS')
76
- })
77
-
78
- test('a text track from data exports its letters and its own colors', async () => {
79
- const model = makeModel([
80
- {
81
- id: 'frame',
82
- name: 'Codon frame',
83
- kind: 'text',
84
- data: '1231',
85
- colors: { 1: '#aaaaaa', 2: '#bbbbbb', 3: '#cccccc' },
86
- },
87
- ])
88
- const svg = await exportSvg(model)
89
- expect(
90
- rectsFilled(svg, '#aaaaaa')
91
- .map(b => b.x)
92
- .sort((a, b) => a - b),
93
- ).toEqual([0, colWidth * 3])
94
- expect(rectsFilled(svg, '#bbbbbb').map(b => b.x)).toEqual([colWidth])
95
- expect(svgNamesTrack(svg)).toContain('Codon frame')
96
- })
97
-
98
- test('a data track that is toggled off stays out of the export', async () => {
99
- const model = makeModel([
100
- { id: 'dnds', name: 'dN/dS', kind: 'bar', values: [1], color: barColor },
101
- ])
102
- model.toggleTrack('dnds')
103
- expect(rectsFilled(await exportSvg(model), barColor)).toEqual([])
104
- })
105
-
106
- function svgNamesTrack(svg: string) {
107
- return [...svg.matchAll(/<text[^>]*>([^<]*)<\/text>/g)].map(m => m[1])
108
- }
@@ -1,118 +0,0 @@
1
- // @vitest-environment jsdom
2
- //
3
- // Verifies the SVG export draws the domain overlay: the boxes themselves across
4
- // the full alignment width, and the color-key legend as a reserved column on the
5
- // right. Polyfills mirror impgRender.test.tsx (svgcanvas needs
6
- // DOMMatrix/DOMPoint + a measureText).
7
- import { createJBrowseTheme } from '@jbrowse/core/ui/theme'
8
- import { beforeAll, expect, test } from 'vitest'
9
-
10
- import { renderToSvg } from './renderToSvg.tsx'
11
- import { createTestModel, installSvgTestEnv } from './svgTestUtil.ts'
12
-
13
- beforeAll(() => {
14
- installSvgTestEnv()
15
- })
16
-
17
- const msa = `>seq1
18
- ACDEFGHIKL
19
- >seq2
20
- ACDE-GHIKL`
21
-
22
- function makeModel({
23
- data = msa,
24
- start = 1,
25
- end = 5,
26
- }: { data?: string; start?: number; end?: number } = {}) {
27
- const model = createTestModel({
28
- id: 'domain-svg-test',
29
- data: { msa: data },
30
- })
31
- model.setDomains({
32
- seq1: {
33
- xref: [{ id: 'seq1' }],
34
- matches: [
35
- {
36
- signature: {
37
- entry: {
38
- name: 'Kinase',
39
- accession: 'PF00069',
40
- description: 'Protein kinase domain',
41
- },
42
- },
43
- locations: [{ start, end }],
44
- },
45
- ],
46
- },
47
- })
48
- return model
49
- }
50
-
51
- function exportEntire(model: ReturnType<typeof makeModel>) {
52
- return renderToSvg(model, {
53
- theme: createJBrowseTheme(),
54
- exportType: 'entire',
55
- includeMinimap: false,
56
- includeTracks: false,
57
- })
58
- }
59
-
60
- test('domain legend is drawn in the svg export when domains are shown', async () => {
61
- const model = makeModel()
62
- expect(model.actuallyShowDomains).toBe(true)
63
- expect(model.visibleDomainTypes.map(d => d.accession)).toEqual(['PF00069'])
64
-
65
- expect(await exportEntire(model)).toContain('Kinase')
66
- })
67
-
68
- test('no legend column when domains are hidden', async () => {
69
- const model = makeModel()
70
- model.setShowDomains(false)
71
- expect(model.actuallyShowDomains).toBe(false)
72
-
73
- expect(await exportEntire(model)).not.toContain('Kinase')
74
- })
75
-
76
- test('the page grows to hold a key taller than the alignment', async () => {
77
- const model = makeModel()
78
- model.setDomains({
79
- seq1: {
80
- xref: [{ id: 'seq1' }],
81
- matches: Array.from({ length: 12 }, (_, i) => ({
82
- signature: {
83
- entry: { name: `Dom${i}`, accession: `PF${i}`, description: '' },
84
- },
85
- locations: [{ start: 1, end: 5 }],
86
- })),
87
- },
88
- })
89
- expect(model.visibleDomainTypes).toHaveLength(12)
90
- const keyHeight = 16 + 12 * 16
91
- expect(model.totalHeight).toBeLessThan(keyHeight)
92
-
93
- const svg = await exportEntire(model)
94
- expect(svg).toContain(`height="${keyHeight}"`)
95
- expect(/<svg[^>]*height="(\d+)"/.exec(svg)?.[1]).toBe(String(keyHeight))
96
- })
97
-
98
- test('a domain box past the on-screen block size still draws', async () => {
99
- // the export renders the alignment in one pass, so the overlay has to be told
100
- // how wide that pass is; falling back to the 500px on-screen block size culled
101
- // every band to the left edge of a wide alignment
102
- const row = 'ACDEFGHIKL'.repeat(20)
103
- const model = makeModel({
104
- data: `>seq1\n${row}\n>seq2\n${row}`,
105
- start: 151,
106
- end: 190,
107
- })
108
- const band = model.domainBands.get('seq1')![0]!
109
- const x = band.startCol * model.colWidth
110
- expect(x).toBeGreaterThan(model.blockSize)
111
-
112
- const svg = await exportEntire(model)
113
- const fill = model.fillPalette.PF00069!
114
- const rects = [...svg.matchAll(/<rect[^>]*>/g)].map(m => m[0])
115
- expect(
116
- rects.some(r => r.includes(`fill="${fill}"`) && r.includes(`x="${x}"`)),
117
- ).toBe(true)
118
- })
@@ -1,85 +0,0 @@
1
- // @vitest-environment jsdom
2
- //
3
- // The SVG export draws the `highlights` layer: a bordered band with its label
4
- // over the alignment, a residue span at the column the row's gaps put it in,
5
- // and a row set tinted across both the tree and the alignment.
6
- import { createJBrowseTheme } from '@jbrowse/core/ui/theme'
7
- import { enableStaticRendering } from 'mobx-react'
8
- import { beforeAll, expect, test } from 'vitest'
9
-
10
- import { installHeadlessRenderEnv } from './headlessRenderEnv.ts'
11
- import MSAModelF from './model.ts'
12
- import { renderToSvg } from './renderToSvg.tsx'
13
-
14
- import type { Highlight } from './types.ts'
15
-
16
- beforeAll(() => {
17
- enableStaticRendering(true)
18
- installHeadlessRenderEnv()
19
- })
20
-
21
- const msa = `>seq1
22
- ACDEFGHIKL
23
- >seq2
24
- AC--FGHIKL
25
- >seq3
26
- ACDEFGHIKL`
27
-
28
- async function exportWith(highlights: Highlight[]) {
29
- const model = MSAModelF().create({
30
- id: 'highlight-svg-test',
31
- type: 'MsaView',
32
- height: 400,
33
- msaFormat: 'fasta',
34
- data: { msa },
35
- highlights,
36
- })
37
- model.setWidth(800)
38
- const svg = await renderToSvg(model, {
39
- theme: createJBrowseTheme(),
40
- exportType: 'entire',
41
- })
42
- return { model, svg }
43
- }
44
-
45
- const rects = (svg: string) => svg.match(/<rect[^>]*>/g) ?? []
46
-
47
- test('a labeled column span draws a band and its label', async () => {
48
- const { model, svg } = await exportWith([
49
- { start: 3, end: 5, label: 'motif', color: 'rgb(1, 2, 3)' },
50
- ])
51
- const { colWidth, totalHeight } = model
52
- const band = rects(svg).find(
53
- r => r.includes(`x="${2 * colWidth}"`) && r.includes('rgb(1, 2, 3)'),
54
- )
55
- expect(band).toBeDefined()
56
- expect(band).toContain(`width="${3 * colWidth}"`)
57
- expect(band).toContain(`height="${totalHeight}"`)
58
- expect(svg).toContain('>motif<')
59
- })
60
-
61
- test('a residue span lands where the row has its residues', async () => {
62
- const { model, svg } = await exportWith([
63
- { row: 'seq2', start: 3, end: 3, color: 'rgb(9, 9, 9)' },
64
- ])
65
- expect(model.resolvedHighlights[0]).toMatchObject({
66
- startCol: 4,
67
- endCol: 4,
68
- })
69
- const band = rects(svg).find(r => r.includes('rgb(9, 9, 9)'))
70
- expect(band).toContain(`x="${4 * model.colWidth}"`)
71
- })
72
-
73
- test('a row set tints the row in the tree and the alignment', async () => {
74
- const { model, svg } = await exportWith([
75
- { rows: ['seq3'], label: 'odd one out', color: 'rgb(7, 7, 7)' },
76
- ])
77
- const { rowHeight, treeAreaWidth, totalWidth } = model
78
- const tints = rects(svg).filter(
79
- r => r.includes('rgb(7, 7, 7)') && r.includes(`y="${2 * rowHeight}"`),
80
- )
81
- expect(tints.map(r => /width="([^"]+)"/.exec(r)?.[1])).toEqual(
82
- expect.arrayContaining([`${treeAreaWidth}`, `${totalWidth}`]),
83
- )
84
- expect(svg).toContain('>odd one out<')
85
- })
@@ -1,62 +0,0 @@
1
- // @vitest-environment jsdom
2
- //
3
- // The viewport export draws a minimap by default, and nothing covered it. It
4
- // spans the same alignment canvas the live minimap does, so its trapezoid has
5
- // to reach the right edge of the exported alignment column -- and it is drawn
6
- // only when the live view shows one at all.
7
- import { createJBrowseTheme } from '@jbrowse/core/ui/theme'
8
- import { beforeAll, expect, test } from 'vitest'
9
-
10
- import { renderToSvg } from './renderToSvg.tsx'
11
- import { createTestModel, installSvgTestEnv } from './svgTestUtil.ts'
12
-
13
- beforeAll(() => {
14
- installSvgTestEnv()
15
- })
16
-
17
- const width = 1000
18
-
19
- function makeModel(cols = 400) {
20
- const row = 'ACDEFGHIKL'.repeat(cols / 10)
21
- return createTestModel(
22
- { height: 300, data: { msa: `>seq1\n${row}\n>seq2\n${row}` } },
23
- width,
24
- )
25
- }
26
-
27
- function exportViewport(model: ReturnType<typeof makeModel>) {
28
- return renderToSvg(model, {
29
- theme: createJBrowseTheme(),
30
- exportType: 'viewport',
31
- includeMinimap: true,
32
- includeTracks: false,
33
- })
34
- }
35
-
36
- test('the exported minimap spans the exported alignment column', async () => {
37
- const model = makeModel()
38
- expect(model.showHorizontalScrollbar).toBe(true)
39
-
40
- const svg = await exportViewport(model)
41
-
42
- // the minimap column is the alignment canvas, which is what the export lays
43
- // out beside the tree
44
- const minimapWidth = model.msaCanvasWidth
45
- const polygon = /<polygon[^>]*points="([^"]*)"/.exec(svg)?.[1]
46
- expect(polygon).toBeDefined()
47
- // bottom edge of the trapezoid reaches the full width it was given
48
- expect(polygon!.endsWith(`${minimapWidth},${model.minimapHeight - 12}`)).toBe(
49
- true,
50
- )
51
- // and the bar outline is drawn to the same width
52
- expect(svg).toContain(`width="${minimapWidth}"`)
53
- })
54
-
55
- test('no minimap when the alignment already fits across', async () => {
56
- const model = makeModel(10)
57
- expect(model.showHorizontalScrollbar).toBe(false)
58
-
59
- // a minimap here would mark a viewport wider than the bar it sits in, and the
60
- // live view draws none either
61
- expect(await exportViewport(model)).not.toContain('<polygon')
62
- })
@@ -1,144 +0,0 @@
1
- // @vitest-environment jsdom
2
- //
3
- // The SVG export's raster background. jsdom has no canvas, so the export falls
4
- // back to a <rect> per cell there and every other export test exercises that
5
- // path; this file supplies the canvas the raster needs and checks the export
6
- // takes it instead.
7
- import { createJBrowseTheme } from '@jbrowse/core/ui/theme'
8
- import { beforeAll, expect, test } from 'vitest'
9
-
10
- import { renderToSvg } from './renderToSvg.tsx'
11
- import {
12
- createTestModel,
13
- installSvgTestEnv,
14
- syntheticProteinMsa,
15
- } from './svgTestUtil.ts'
16
-
17
- const dataUrl = 'data:image/png;base64,STUB'
18
-
19
- // enough of a 2d context for the raster: a color parser, an ImageData that is
20
- // really backed by bytes, and a canvas that reads back
21
- beforeAll(() => {
22
- installSvgTestEnv({
23
- fillStyle: '#000000',
24
- clearRect: () => {},
25
- fillRect: () => {},
26
- createImageData: ((width: number, height: number) => ({
27
- data: new Uint8ClampedArray(width * height * 4),
28
- width,
29
- height,
30
- })) as unknown as CanvasRenderingContext2D['createImageData'],
31
- putImageData: () => {},
32
- getImageData: (() => ({
33
- data: Uint8ClampedArray.from([1, 2, 3, 255]),
34
- })) as unknown as CanvasRenderingContext2D['getImageData'],
35
- })
36
- HTMLCanvasElement.prototype.toDataURL = () => dataUrl
37
- })
38
-
39
- function makeModel(rows: number, cols: number) {
40
- return createTestModel({
41
- id: 'raster',
42
- data: { msa: syntheticProteinMsa(rows, cols) },
43
- })
44
- }
45
-
46
- function exportEntire(model: ReturnType<typeof makeModel>) {
47
- return renderToSvg(model, {
48
- theme: createJBrowseTheme(),
49
- exportType: 'entire',
50
- })
51
- }
52
-
53
- test('the background is one image, not a rect per cell', async () => {
54
- const model = makeModel(40, 300)
55
- expect(model.bgColor).toBe(true)
56
- expect(model.actuallyShowDomains).toBe(false)
57
-
58
- const svg = await exportEntire(model)
59
- const images = [...svg.matchAll(/<image[^>]*>/g)].map(m => m[0])
60
-
61
- expect(images).toHaveLength(1)
62
- expect(images[0]).toContain(dataUrl)
63
- // the alignment's own rectangle, one pixel per cell scaled up by whole cells
64
- expect(images[0]).toContain(`width="${300 * model.colWidth}"`)
65
- expect(images[0]).toContain(`height="${40 * model.rowHeight}"`)
66
- expect(images[0]).toContain('image-rendering="pixelated"')
67
-
68
- // 12000 cells would have been 12000 rects
69
- expect((svg.match(/<rect/g) ?? []).length).toBeLessThan(10)
70
- })
71
-
72
- test('letters still draw on top of the raster', async () => {
73
- const model = makeModel(4, 10)
74
- expect(model.showMsaLetters).toBe(true)
75
-
76
- const svg = await exportEntire(model)
77
-
78
- expect(svg).toContain('<image')
79
- expect((svg.match(/<text/g) ?? []).length).toBeGreaterThanOrEqual(40)
80
- })
81
-
82
- test('the domain overlay keeps the vector path, which paints its own boxes', async () => {
83
- const model = makeModel(4, 10)
84
- model.setDomains({
85
- seq0: {
86
- xref: [{ id: 'seq0' }],
87
- matches: [
88
- {
89
- signature: {
90
- entry: { name: 'Kinase', accession: 'PF00069', description: '' },
91
- },
92
- locations: [{ start: 1, end: 5 }],
93
- },
94
- ],
95
- },
96
- })
97
- expect(model.actuallyShowDomains).toBe(true)
98
-
99
- expect(await exportEntire(model)).not.toContain('<image')
100
- })
101
-
102
- test('turning background color off leaves nothing for a raster to draw', async () => {
103
- const model = makeModel(4, 10)
104
- model.setBgColor(false)
105
-
106
- expect(await exportEntire(model)).not.toContain('<image')
107
- })
108
-
109
- test('the exported minimap carries the alignment thumbnail', async () => {
110
- const model = makeModel(20, 2000)
111
- expect(model.showHorizontalScrollbar).toBe(true)
112
-
113
- const svg = await renderToSvg(model, {
114
- theme: createJBrowseTheme(),
115
- exportType: 'viewport',
116
- includeMinimap: true,
117
- })
118
-
119
- // the bar is the same downsampled alignment the live minimap draws, rather
120
- // than the empty outline the export used to leave
121
- const bar = [...svg.matchAll(/<image[^>]*>/g)]
122
- .map(m => m[0])
123
- .find(i => i.includes('height="12"'))
124
- expect(bar).toBeDefined()
125
- expect(bar).toContain(dataUrl)
126
- expect(bar).toContain(`width="${model.msaCanvasWidth}"`)
127
- })
128
-
129
- test('each track is named in the tree column beside it', async () => {
130
- const model = makeModel(4, 40)
131
- model.toggleTrack('sequence-logo')
132
- const names = model.turnedOnTracks.map(t => t.model.name)
133
- expect(names.length).toBeGreaterThan(1)
134
-
135
- const svg = await renderToSvg(model, {
136
- theme: createJBrowseTheme(),
137
- exportType: 'entire',
138
- includeTracks: true,
139
- })
140
-
141
- for (const name of names) {
142
- expect(svg).toContain(`>${name}</text>`)
143
- }
144
- })
@@ -1,165 +0,0 @@
1
- // @vitest-environment jsdom
2
- //
3
- // The logo track is the first track kind whose letters are drawn under a
4
- // per-letter transform rather than at a fixed size, so it is also the first that
5
- // can silently draw nothing if the export context loses that transform. These
6
- // tests go through the real SVG export to pin the whole path: the track is off
7
- // until asked for, the stack is ordered and scaled, and the glyphs land inside
8
- // the track's own band.
9
- import { createJBrowseTheme } from '@jbrowse/core/ui/theme'
10
- import { beforeAll, expect, test } from 'vitest'
11
-
12
- import { CHAR_WIDTH_RATIO } from './headlessRenderEnv.ts'
13
- import { renderToSvg } from './renderToSvg.tsx'
14
- import { createTestModel, installSvgTestEnv } from './svgTestUtil.ts'
15
-
16
- beforeAll(() => {
17
- installSvgTestEnv()
18
- })
19
-
20
- // column 0 is fully conserved A, column 1 is a 3:1 split of C over G, and
21
- // column 2 is an even four-way split carrying no information at all
22
- const msa = `>s1\nACA\n>s2\nACC\n>s3\nACG\n>s4\nAGT\n`
23
- const colWidth = 40
24
-
25
- function makeModel() {
26
- return createTestModel({ colWidth, data: { msa } }, 1000)
27
- }
28
-
29
- async function exportSvg(model: ReturnType<typeof makeModel>) {
30
- return renderToSvg(model, {
31
- theme: createJBrowseTheme(),
32
- exportType: 'entire',
33
- includeTracks: true,
34
- })
35
- }
36
-
37
- // The logo's glyphs are the only <text> drawn at the track's own font size, and
38
- // the only ones carrying a non-unit vertical scale, which is what separates them
39
- // from the alignment letters and tree labels in the same document.
40
- function logoGlyphs(svg: string, fontSize: number) {
41
- return [
42
- ...svg.matchAll(
43
- /<text[^>]*font-size="([\d.]+)px"[^>]*transform="matrix\(([^)]*)\)"[^>]*>([A-Z])<\/text>/g,
44
- ),
45
- ]
46
- .filter(m => Number(m[1]) === fontSize)
47
- .map(m => {
48
- const [sx, , , sy, tx, ty] = m[2]!.split(/[\s,]+/).map(Number)
49
- return { letter: m[3]!, sx: sx!, sy: sy!, x: tx!, y: ty! }
50
- })
51
- }
52
-
53
- async function glyphsOf(model: ReturnType<typeof makeModel>) {
54
- return logoGlyphs(await exportSvg(model), model.sequenceLogoTrackHeight)
55
- }
56
-
57
- test('the logo track is hidden until it is asked for', () => {
58
- const model = makeModel()
59
- expect(model.tracks.map(t => t.model.id)).toContain('sequence-logo')
60
- expect(model.turnedOnTracks.map(t => t.model.id)).not.toContain(
61
- 'sequence-logo',
62
- )
63
- // and being default-off writes nothing into the shareable snapshot
64
- expect(model.turnedOffTracks.size).toBe(0)
65
- })
66
-
67
- test('toggling it on shows it, and off again hides it', () => {
68
- const model = makeModel()
69
- model.toggleTrack('sequence-logo')
70
- expect(model.turnedOnTracks.map(t => t.model.id)).toContain('sequence-logo')
71
- model.toggleTrack('sequence-logo')
72
- expect(model.turnedOnTracks.map(t => t.model.id)).not.toContain(
73
- 'sequence-logo',
74
- )
75
- })
76
-
77
- test('an on-by-default track still toggles off and back on', () => {
78
- const model = makeModel()
79
- expect(model.turnedOnTracks.map(t => t.model.id)).toContain('conservation')
80
- model.toggleTrack('conservation')
81
- expect(model.turnedOnTracks.map(t => t.model.id)).not.toContain(
82
- 'conservation',
83
- )
84
- model.toggleTrack('conservation')
85
- expect(model.turnedOnTracks.map(t => t.model.id)).toContain('conservation')
86
- })
87
-
88
- test('the conserved column draws one full-height letter', async () => {
89
- const model = makeModel()
90
- model.toggleTrack('sequence-logo')
91
- const col0 = (await glyphsOf(model)).filter(g => g.x === 0)
92
-
93
- expect(col0.map(g => g.letter)).toEqual(['A'])
94
- // a fully conserved nucleotide column is 2 of 2 bits, so the glyph stretches
95
- // to the whole track height over the cap height of the reference font
96
- expect(col0[0]!.sy).toBeCloseTo(1 / 0.72, 5)
97
- })
98
-
99
- test('a split column stacks the minor letter below the major one', async () => {
100
- const model = makeModel()
101
- model.toggleTrack('sequence-logo')
102
- const col1 = (await glyphsOf(model)).filter(g => g.x === colWidth)
103
-
104
- // ascending order means C (3 of 4) is drawn last, so it ends up on top
105
- expect(col1.map(g => g.letter)).toEqual(['G', 'C'])
106
- const [g, c] = col1
107
- expect(c!.sy).toBeGreaterThan(g!.sy)
108
- // and the taller letter sits higher up the track (smaller y is nearer the top)
109
- expect(c!.y).toBeLessThan(g!.y)
110
- })
111
-
112
- test('the uninformative column draws nothing', async () => {
113
- const model = makeModel()
114
- model.toggleTrack('sequence-logo')
115
- const glyphs = await glyphsOf(model)
116
- expect(glyphs.filter(g => g.x === colWidth * 2)).toEqual([])
117
- // the other two columns did draw, so an empty column 2 is the logo's own
118
- // verdict rather than the whole track missing
119
- expect(glyphs).toHaveLength(3)
120
- })
121
-
122
- test('every glyph stays inside the track band', async () => {
123
- const model = makeModel()
124
- model.toggleTrack('sequence-logo')
125
-
126
- // the export stacks the tracks, so the logo's band is offset by whatever is
127
- // drawn above it -- assert against that band rather than against 0..height,
128
- // which would pass only while the logo happened to be the first track
129
- const above = model.turnedOnTracks
130
- .slice(
131
- 0,
132
- model.turnedOnTracks.findIndex(t => t.model.id === 'sequence-logo'),
133
- )
134
- .reduce((a, t) => a + t.model.height, 0)
135
- const bandTop = above
136
- const bandBottom = above + model.sequenceLogoTrackHeight
137
-
138
- const glyphs = await glyphsOf(model)
139
- expect(glyphs.length).toBeGreaterThan(0)
140
- for (const glyph of glyphs) {
141
- // baselines run from the band's bottom edge upward, never past either end
142
- expect(glyph.y).toBeGreaterThan(bandTop)
143
- expect(glyph.y).toBeLessThanOrEqual(bandBottom)
144
- }
145
- })
146
-
147
- test('letters are stretched to fill their column', async () => {
148
- const model = makeModel()
149
- model.toggleTrack('sequence-logo')
150
- const glyphs = await glyphsOf(model)
151
-
152
- const expected = colWidth / (model.sequenceLogoTrackHeight * CHAR_WIDTH_RATIO)
153
- for (const glyph of glyphs) {
154
- expect(glyph.sx).toBeCloseTo(expected, 5)
155
- }
156
- })
157
-
158
- test('the logo appears in the export only when the track is on', async () => {
159
- const off = makeModel()
160
- expect(await glyphsOf(off)).toEqual([])
161
-
162
- const on = makeModel()
163
- on.toggleTrack('sequence-logo')
164
- expect((await glyphsOf(on)).length).toBeGreaterThan(0)
165
- })