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.
- package/README.md +13 -11
- package/bundle/index.js +122 -112
- package/bundle/index.js.map +4 -4
- package/dist/colorSchemes.js +1 -2
- package/dist/colorSchemes.js.map +1 -1
- package/dist/columnStats.d.ts +28 -0
- package/dist/columnStats.js +34 -0
- package/dist/columnStats.js.map +1 -0
- package/dist/components/DragHandle.d.ts +3 -2
- package/dist/components/DragHandle.js +11 -5
- package/dist/components/DragHandle.js.map +1 -1
- package/dist/components/Loading.js +2 -2
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/MSAView.js +17 -6
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/MSAViewer.d.ts +69 -4
- package/dist/components/MSAViewer.js +201 -8
- package/dist/components/MSAViewer.js.map +1 -1
- package/dist/components/PortalTooltip.d.ts +11 -0
- package/dist/components/PortalTooltip.js +29 -0
- package/dist/components/PortalTooltip.js.map +1 -0
- package/dist/components/ResizeHandles.d.ts +3 -3
- package/dist/components/ResizeHandles.js +13 -24
- package/dist/components/ResizeHandles.js.map +1 -1
- package/dist/components/SequenceTextArea.js +3 -3
- package/dist/components/SequenceTextArea.js.map +1 -1
- package/dist/components/Track.js +41 -22
- package/dist/components/Track.js.map +1 -1
- package/dist/components/dialogs/{InterProScanDialog.d.ts → AnnotationFileDialog.d.ts} +2 -2
- package/dist/components/dialogs/AnnotationFileDialog.js +92 -0
- package/dist/components/dialogs/AnnotationFileDialog.js.map +1 -0
- package/dist/components/dialogs/ExportSVGDialog.js +5 -3
- package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
- package/dist/components/dialogs/FeatureDialog.js +13 -9
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/TrackInfoDialog.js +1 -1
- package/dist/components/dialogs/TrackInfoDialog.js.map +1 -1
- package/dist/components/header/GappynessSlider.js +6 -11
- package/dist/components/header/GappynessSlider.js.map +1 -1
- package/dist/components/header/Header.js +7 -0
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/HeaderStatusArea.js +0 -2
- package/dist/components/header/HeaderStatusArea.js.map +1 -1
- package/dist/components/header/LoadWarnings.d.ts +6 -0
- package/dist/components/header/LoadWarnings.js +35 -0
- package/dist/components/header/LoadWarnings.js.map +1 -0
- package/dist/components/header/MultiAlignmentSelector.js +0 -0
- package/dist/components/header/MultiAlignmentSelector.js.map +1 -1
- package/dist/components/header/ScrollZoomIcons.d.ts +6 -0
- package/dist/components/header/ScrollZoomIcons.js +35 -0
- package/dist/components/header/ScrollZoomIcons.js.map +1 -0
- package/dist/components/header/TreeSettingsMenu.js +7 -1
- package/dist/components/header/TreeSettingsMenu.js.map +1 -1
- package/dist/components/header/UnshareableDataWarning.d.ts +6 -0
- package/dist/components/header/UnshareableDataWarning.js +40 -0
- package/dist/components/header/UnshareableDataWarning.js.map +1 -0
- package/dist/components/header/ZoomControls.js +49 -6
- package/dist/components/header/ZoomControls.js.map +1 -1
- package/dist/components/header/getAnnotationsMenu.js +11 -14
- package/dist/components/header/getAnnotationsMenu.js.map +1 -1
- package/dist/components/header/settingsMenuItems.js +10 -7
- package/dist/components/header/settingsMenuItems.js.map +1 -1
- package/dist/components/import/ImportForm.js +1 -1
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/import/ImportFormExamples.js +2 -6
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/import/util.js +2 -0
- package/dist/components/import/util.js.map +1 -1
- package/dist/components/minimap/Minimap.js +1 -2
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/msa/AnnotationLegend.js +27 -19
- package/dist/components/msa/AnnotationLegend.js.map +1 -1
- package/dist/components/msa/MSACanvas.js +1 -1
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +17 -20
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js +2 -1
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/domainBandCursor.d.ts +7 -11
- package/dist/components/msa/domainBandCursor.js +7 -11
- package/dist/components/msa/domainBandCursor.js.map +1 -1
- package/dist/components/msa/drawFeatureSpans.d.ts +53 -0
- package/dist/components/msa/drawFeatureSpans.js +78 -0
- package/dist/components/msa/drawFeatureSpans.js.map +1 -0
- package/dist/components/msa/legendRows.d.ts +8 -0
- package/dist/components/msa/legendRows.js +16 -0
- package/dist/components/msa/legendRows.js.map +1 -0
- package/dist/components/msa/msaRaster.d.ts +30 -27
- package/dist/components/msa/msaRaster.js +193 -90
- package/dist/components/msa/msaRaster.js.map +1 -1
- package/dist/components/msa/packDomainLanes.d.ts +20 -0
- package/dist/components/msa/packDomainLanes.js +33 -0
- package/dist/components/msa/packDomainLanes.js.map +1 -0
- package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +3 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +51 -87
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderHighlights.d.ts +44 -4
- package/dist/components/msa/renderHighlights.js +99 -11
- package/dist/components/msa/renderHighlights.js.map +1 -1
- package/dist/components/msa/renderMSABlock.d.ts +1 -2
- package/dist/components/msa/renderMSABlock.js +28 -31
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.js +9 -30
- package/dist/components/msa/renderMSAMouseover.js.map +1 -1
- package/dist/components/msa/tileColor.js +4 -7
- package/dist/components/msa/tileColor.js.map +1 -1
- package/dist/components/msa/useMsaBlockMouse.d.ts +5 -3
- package/dist/components/msa/useMsaBlockMouse.js +6 -6
- package/dist/components/msa/useMsaBlockMouse.js.map +1 -1
- package/dist/components/renderCtx.d.ts +1 -1
- package/dist/components/rowpanels/RowPanelBlock.d.ts +9 -0
- package/dist/components/rowpanels/RowPanelBlock.js +86 -0
- package/dist/components/rowpanels/RowPanelBlock.js.map +1 -0
- package/dist/components/rowpanels/RowPanelHeaders.d.ts +12 -0
- package/dist/components/rowpanels/RowPanelHeaders.js +38 -0
- package/dist/components/rowpanels/RowPanelHeaders.js.map +1 -0
- package/dist/components/{msa/ColumnStats.d.ts → rowpanels/RowPanels.d.ts} +2 -2
- package/dist/components/rowpanels/RowPanels.js +32 -0
- package/dist/components/rowpanels/RowPanels.js.map +1 -0
- package/dist/components/rowpanels/headerLayout.d.ts +1 -0
- package/dist/components/rowpanels/headerLayout.js +5 -0
- package/dist/components/rowpanels/headerLayout.js.map +1 -0
- package/dist/components/rowpanels/renderFeaturePanel.d.ts +21 -0
- package/dist/components/rowpanels/renderFeaturePanel.js +37 -0
- package/dist/components/rowpanels/renderFeaturePanel.js.map +1 -0
- package/dist/components/rowpanels/renderRowPanel.d.ts +23 -0
- package/dist/components/rowpanels/renderRowPanel.js +22 -0
- package/dist/components/rowpanels/renderRowPanel.js.map +1 -0
- package/dist/components/rowpanels/renderStrip.d.ts +20 -0
- package/dist/components/rowpanels/renderStrip.js +26 -0
- package/dist/components/rowpanels/renderStrip.js.map +1 -0
- package/dist/components/tracks/TrackBlocks.js +13 -16
- package/dist/components/tracks/TrackBlocks.js.map +1 -1
- package/dist/components/tracks/TrackTooltipContent.d.ts +15 -0
- package/dist/components/tracks/TrackTooltipContent.js +109 -0
- package/dist/components/tracks/TrackTooltipContent.js.map +1 -0
- package/dist/components/tracks/drawTracks.d.ts +30 -12
- package/dist/components/tracks/drawTracks.js +127 -34
- package/dist/components/tracks/drawTracks.js.map +1 -1
- package/dist/components/tracks/useTrackHover.d.ts +22 -0
- package/dist/components/tracks/useTrackHover.js +30 -0
- package/dist/components/tracks/useTrackHover.js.map +1 -0
- package/dist/components/tree/CladeLabels.d.ts +12 -0
- package/dist/components/tree/CladeLabels.js +48 -0
- package/dist/components/tree/CladeLabels.js.map +1 -0
- package/dist/components/tree/TreeCanvas.js +6 -4
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +6 -21
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/TreeOverview.d.ts +14 -0
- package/dist/components/tree/TreeOverview.js +75 -0
- package/dist/components/tree/TreeOverview.js.map +1 -0
- package/dist/components/tree/TreeRuler.js +11 -5
- package/dist/components/tree/TreeRuler.js.map +1 -1
- package/dist/components/tree/cladeBrackets.d.ts +25 -0
- package/dist/components/tree/cladeBrackets.js +51 -0
- package/dist/components/tree/cladeBrackets.js.map +1 -0
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +2 -2
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
- package/dist/components/tree/renderTreeCanvas.d.ts +0 -1
- package/dist/components/tree/renderTreeCanvas.js +221 -47
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/components/tree/renderTreeOverview.d.ts +52 -0
- package/dist/components/tree/renderTreeOverview.js +138 -0
- package/dist/components/tree/renderTreeOverview.js.map +1 -0
- package/dist/components/tree/scaleBar.d.ts +10 -0
- package/dist/components/tree/scaleBar.js +24 -0
- package/dist/components/tree/scaleBar.js.map +1 -0
- package/dist/components/tree/useTreeHover.js +2 -4
- package/dist/components/tree/useTreeHover.js.map +1 -1
- package/dist/constants.d.ts +18 -1
- package/dist/constants.js +51 -8
- package/dist/constants.js.map +1 -1
- package/dist/createPaletteMap.d.ts +7 -6
- package/dist/createPaletteMap.js +10 -9
- package/dist/createPaletteMap.js.map +1 -1
- package/dist/element.d.ts +13 -0
- package/dist/element.js +269 -0
- package/dist/element.js.map +1 -0
- package/dist/featureFields.d.ts +11 -0
- package/dist/featureFields.js +17 -0
- package/dist/featureFields.js.map +1 -0
- package/dist/fetchUtils.d.ts +7 -7
- package/dist/fetchUtils.js +4 -32
- package/dist/fetchUtils.js.map +1 -1
- package/dist/flatToTree.js +1 -2
- package/dist/flatToTree.js.map +1 -1
- package/dist/ggplotPalettes.d.ts +10 -0
- package/dist/ggplotPalettes.js +58 -0
- package/dist/ggplotPalettes.js.map +1 -1
- package/dist/hierarchy.d.ts +29 -1
- package/dist/hierarchy.js +82 -19
- package/dist/hierarchy.js.map +1 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/model/DataModel.js +4 -4
- package/dist/model/DataModel.js.map +1 -1
- package/dist/model/msaModel.d.ts +3 -2
- package/dist/model/msaModel.js +3 -2
- package/dist/model/msaModel.js.map +1 -1
- package/dist/model/treeModel.d.ts +30 -0
- package/dist/model/treeModel.js +37 -1
- package/dist/model/treeModel.js.map +1 -1
- package/dist/model.d.ts +792 -259
- package/dist/model.js +2092 -675
- package/dist/model.js.map +1 -1
- package/dist/mount.d.ts +11 -0
- package/dist/mount.js +22 -0
- package/dist/mount.js.map +1 -0
- package/dist/neighborJoining.js +8 -32
- package/dist/neighborJoining.js.map +1 -1
- package/dist/renderToStaticMarkup.d.ts +15 -13
- package/dist/renderToStaticMarkup.js +37 -25
- package/dist/renderToStaticMarkup.js.map +1 -1
- package/dist/renderToSvg.js +198 -68
- package/dist/renderToSvg.js.map +1 -1
- package/dist/rowCoordinateCalculations.d.ts +26 -28
- package/dist/rowCoordinateCalculations.js +13 -39
- package/dist/rowCoordinateCalculations.js.map +1 -1
- package/dist/scales.d.ts +22 -0
- package/dist/scales.js +30 -0
- package/dist/scales.js.map +1 -0
- package/dist/seqPosToGlobalCol.d.ts +2 -3
- package/dist/seqPosToGlobalCol.js +5 -4
- package/dist/seqPosToGlobalCol.js.map +1 -1
- package/dist/sequenceLogo.d.ts +6 -11
- package/dist/sequenceLogo.js +6 -11
- package/dist/sequenceLogo.js.map +1 -1
- package/dist/stripDefault.d.ts +7 -14
- package/dist/stripDefault.js +7 -14
- package/dist/stripDefault.js.map +1 -1
- package/dist/svgTestUtil.d.ts +306 -124
- package/dist/types.d.ts +295 -3
- package/dist/umd.d.ts +2 -0
- package/dist/umd.js +4 -2
- package/dist/umd.js.map +1 -1
- package/dist/useCanvasAutorun.d.ts +5 -10
- package/dist/useCanvasAutorun.js +5 -10
- package/dist/useCanvasAutorun.js.map +1 -1
- package/dist/useMsaSvgFigure.d.ts +20 -0
- package/dist/useMsaSvgFigure.js +46 -0
- package/dist/useMsaSvgFigure.js.map +1 -0
- package/dist/util.d.ts +10 -4
- package/dist/util.js +37 -10
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/wuss.d.ts +14 -0
- package/dist/wuss.js +55 -0
- package/dist/wuss.js.map +1 -0
- package/package.json +23 -14
- package/src/colorSchemes.ts +1 -2
- package/src/columnStats.ts +58 -0
- package/src/components/DragHandle.tsx +18 -7
- package/src/components/Loading.tsx +14 -8
- package/src/components/MSAView.tsx +19 -5
- package/src/components/MSAViewer.tsx +326 -10
- package/src/components/PortalTooltip.tsx +47 -0
- package/src/components/ResizeHandles.tsx +21 -36
- package/src/components/SequenceTextArea.tsx +3 -3
- package/src/components/Track.tsx +55 -18
- package/src/components/dialogs/AnnotationFileDialog.tsx +162 -0
- package/src/components/dialogs/ExportSVGDialog.tsx +7 -2
- package/src/components/dialogs/FeatureDialog.tsx +13 -9
- package/src/components/dialogs/TrackInfoDialog.tsx +1 -1
- package/src/components/header/GappynessSlider.tsx +6 -11
- package/src/components/header/Header.tsx +10 -0
- package/src/components/header/HeaderStatusArea.tsx +0 -5
- package/src/components/header/LoadWarnings.tsx +48 -0
- package/src/components/header/MultiAlignmentSelector.tsx +0 -0
- package/src/components/header/ScrollZoomIcons.tsx +52 -0
- package/src/components/header/TreeSettingsMenu.tsx +7 -1
- package/src/components/header/UnshareableDataWarning.tsx +56 -0
- package/src/components/header/ZoomControls.tsx +74 -14
- package/src/components/header/getAnnotationsMenu.ts +13 -17
- package/src/components/header/settingsMenuItems.ts +11 -6
- package/src/components/import/ImportForm.tsx +2 -2
- package/src/components/import/ImportFormExamples.tsx +4 -8
- package/src/components/import/util.ts +2 -0
- package/src/components/minimap/Minimap.tsx +1 -2
- package/src/components/msa/AnnotationLegend.tsx +48 -38
- package/src/components/msa/MSACanvas.tsx +3 -5
- package/src/components/msa/MSACanvasBlock.tsx +17 -21
- package/src/components/msa/MSAMouseoverCanvas.tsx +2 -1
- package/src/components/msa/domainBandCursor.ts +7 -11
- package/src/components/msa/drawFeatureSpans.ts +150 -0
- package/src/components/msa/legendRows.ts +24 -0
- package/src/components/msa/msaRaster.ts +236 -88
- package/src/components/msa/packDomainLanes.ts +36 -0
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +69 -123
- package/src/components/msa/renderHighlights.ts +141 -10
- package/src/components/msa/renderMSABlock.ts +29 -38
- package/src/components/msa/renderMSAMouseover.ts +9 -39
- package/src/components/msa/tileColor.ts +4 -7
- package/src/components/msa/useMsaBlockMouse.ts +6 -6
- package/src/components/renderCtx.ts +1 -0
- package/src/components/rowpanels/RowPanelBlock.tsx +139 -0
- package/src/components/rowpanels/RowPanelHeaders.tsx +57 -0
- package/src/components/rowpanels/RowPanels.tsx +77 -0
- package/src/components/rowpanels/headerLayout.ts +5 -0
- package/src/components/rowpanels/renderFeaturePanel.ts +66 -0
- package/src/components/rowpanels/renderRowPanel.ts +41 -0
- package/src/components/rowpanels/renderStrip.ts +46 -0
- package/src/components/tracks/TrackBlocks.tsx +13 -18
- package/src/components/tracks/TrackTooltipContent.tsx +156 -0
- package/src/components/tracks/drawTracks.ts +169 -38
- package/src/components/tracks/useTrackHover.ts +42 -0
- package/src/components/tree/CladeLabels.tsx +77 -0
- package/src/components/tree/TreeCanvas.tsx +4 -3
- package/src/components/tree/TreeCanvasBlock.tsx +10 -32
- package/src/components/tree/TreeOverview.tsx +106 -0
- package/src/components/tree/TreeRuler.tsx +29 -5
- package/src/components/tree/cladeBrackets.ts +73 -0
- package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +2 -2
- package/src/components/tree/renderTreeCanvas.ts +312 -48
- package/src/components/tree/renderTreeOverview.ts +212 -0
- package/src/components/tree/scaleBar.ts +23 -0
- package/src/components/tree/useTreeHover.ts +2 -4
- package/src/constants.ts +61 -8
- package/src/createPaletteMap.ts +10 -9
- package/src/element.ts +321 -0
- package/src/featureFields.ts +19 -0
- package/src/fetchUtils.ts +7 -40
- package/src/flatToTree.ts +1 -2
- package/src/ggplotPalettes.ts +60 -0
- package/src/hierarchy.ts +97 -20
- package/src/index.ts +46 -6
- package/src/model/DataModel.ts +5 -4
- package/src/model/msaModel.ts +3 -2
- package/src/model/treeModel.ts +42 -0
- package/src/model.ts +2492 -793
- package/src/mount.tsx +32 -0
- package/src/neighborJoining.ts +8 -32
- package/src/rawImports.d.ts +9 -0
- package/src/renderToStaticMarkup.ts +41 -25
- package/src/renderToSvg.tsx +365 -92
- package/src/rowCoordinateCalculations.ts +16 -62
- package/src/scales.ts +47 -0
- package/src/seqPosToGlobalCol.ts +5 -4
- package/src/sequenceLogo.ts +6 -11
- package/src/stripDefault.ts +7 -14
- package/src/types.ts +352 -12
- package/src/umd.ts +4 -2
- package/src/useCanvasAutorun.ts +5 -10
- package/src/useMsaSvgFigure.ts +72 -0
- package/src/util.ts +40 -14
- package/src/version.ts +1 -1
- package/src/wuss.ts +62 -0
- package/dist/components/dialogs/InterProScanDialog.js +0 -137
- package/dist/components/dialogs/InterProScanDialog.js.map +0 -1
- package/dist/components/dialogs/InterProScanFileDialog.d.ts +0 -7
- package/dist/components/dialogs/InterProScanFileDialog.js +0 -64
- package/dist/components/dialogs/InterProScanFileDialog.js.map +0 -1
- package/dist/components/msa/ColumnStats.js +0 -42
- package/dist/components/msa/ColumnStats.js.map +0 -1
- package/dist/launchInterProScan.d.ts +0 -13
- package/dist/launchInterProScan.js +0 -110
- package/dist/launchInterProScan.js.map +0 -1
- package/dist/useColorContrast.d.ts +0 -10
- package/dist/useColorContrast.js +0 -13
- package/dist/useColorContrast.js.map +0 -1
- package/src/clustalX.test.ts +0 -74
- package/src/colSpace.test.ts +0 -67
- package/src/collapseLogic.test.ts +0 -115
- package/src/colorSchemes.docs.test.ts +0 -57
- package/src/columnCounts.test.ts +0 -73
- package/src/columnStats.test.ts +0 -94
- package/src/columnTracks.test.ts +0 -97
- package/src/components/dialogs/InterProScanDialog.tsx +0 -214
- package/src/components/dialogs/InterProScanFileDialog.tsx +0 -138
- package/src/components/minimap/minimapLayout.test.ts +0 -71
- package/src/components/msa/ColumnStats.tsx +0 -54
- package/src/components/msa/msaRaster.test.ts +0 -145
- package/src/components/msa/renderBoxFeatureCanvasBlock.test.ts +0 -51
- package/src/components/tree/renderTreeCanvas.test.ts +0 -296
- package/src/dataInitialized.test.ts +0 -42
- package/src/domainBands.test.ts +0 -122
- package/src/domainLetterColor.test.ts +0 -80
- package/src/exportFileName.test.ts +0 -40
- package/src/fetchUtils.test.ts +0 -83
- package/src/flatToTree.test.ts +0 -51
- package/src/hierarchy.test.ts +0 -228
- package/src/highlights.test.ts +0 -70
- package/src/impgRender.test.tsx +0 -68
- package/src/largeTree.test.ts +0 -67
- package/src/launchInterProScan.ts +0 -167
- package/src/loadErrorDisplay.test.tsx +0 -102
- package/src/modelFilehandleLoaders.test.ts +0 -137
- package/src/modelReset.test.ts +0 -120
- package/src/neighborJoining.test.ts +0 -164
- package/src/parseAsn1.test.ts +0 -36
- package/src/propertyConservation.test.ts +0 -36
- package/src/renderColumnTracksSvg.test.tsx +0 -108
- package/src/renderDomainsSvg.test.tsx +0 -118
- package/src/renderHighlightsSvg.test.tsx +0 -85
- package/src/renderMinimapSvg.test.tsx +0 -62
- package/src/renderRasterSvg.test.tsx +0 -144
- package/src/renderSequenceLogoSvg.test.tsx +0 -165
- package/src/renderToSvg.test.tsx +0 -65
- package/src/reset.test.ts +0 -61
- package/src/rowCoordinateCalculations.test.ts +0 -211
- package/src/rowSpace.test.ts +0 -46
- package/src/segmentOverlay.test.ts +0 -70
- package/src/seqPosToGlobalCol.test.ts +0 -59
- package/src/sequenceLogo.test.ts +0 -88
- package/src/setFontSize.test.ts +0 -33
- package/src/stripDefault.test.ts +0 -48
- package/src/stripDefaultSnapshot.test.ts +0 -87
- package/src/treeMetadata.test.ts +0 -39
- package/src/useCanvasAutorun.test.tsx +0 -98
- package/src/useColorContrast.ts +0 -18
- package/src/viewChrome.test.tsx +0 -134
- package/src/wheelZoom.test.ts +0 -46
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { calcDepthToLeaf, findMaxBranchLen } from '../../hierarchy.ts'
|
|
4
|
-
import stateModelFactory from '../../model.ts'
|
|
5
|
-
import { ClickMapIndex } from './clickMap.ts'
|
|
6
|
-
import { getNodeX, renderTreeCanvas } from './renderTreeCanvas.ts'
|
|
7
|
-
|
|
8
|
-
import type { HierarchyNode } from '../../hierarchy.ts'
|
|
9
|
-
import type { RenderCtx } from '../renderCtx.ts'
|
|
10
|
-
import type { Theme } from '@mui/material'
|
|
11
|
-
|
|
12
|
-
function leaf(id: string, len?: number): HierarchyNode {
|
|
13
|
-
return {
|
|
14
|
-
data: { id, name: id, children: [] },
|
|
15
|
-
children: null,
|
|
16
|
-
parent: null,
|
|
17
|
-
depth: 0,
|
|
18
|
-
height: 0,
|
|
19
|
-
len,
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function internal(
|
|
24
|
-
id: string,
|
|
25
|
-
children: HierarchyNode[],
|
|
26
|
-
len?: number,
|
|
27
|
-
): HierarchyNode {
|
|
28
|
-
const node: HierarchyNode = {
|
|
29
|
-
data: { id, name: id, children: children.map(c => c.data) },
|
|
30
|
-
children,
|
|
31
|
-
parent: null,
|
|
32
|
-
depth: 0,
|
|
33
|
-
height: 1,
|
|
34
|
-
len,
|
|
35
|
-
}
|
|
36
|
-
for (const child of children) {
|
|
37
|
-
child.parent = node
|
|
38
|
-
}
|
|
39
|
-
return node
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
describe('calcDepthToLeaf', () => {
|
|
43
|
-
it('is 0 for a leaf', () => {
|
|
44
|
-
expect(calcDepthToLeaf(leaf('a'))).toBe(0)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
it('counts steps to the deepest tip', () => {
|
|
48
|
-
const tips = [leaf('a'), leaf('b')]
|
|
49
|
-
const intermediate = internal('int', tips)
|
|
50
|
-
const root = internal('root', [intermediate])
|
|
51
|
-
|
|
52
|
-
expect(calcDepthToLeaf(tips[0]!)).toBe(0)
|
|
53
|
-
expect(calcDepthToLeaf(intermediate)).toBe(1)
|
|
54
|
-
expect(calcDepthToLeaf(root)).toBe(2)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('memoizes without re-walking the subtree', () => {
|
|
58
|
-
// the renderer asks for every node's depth on every pass, so the memo has to
|
|
59
|
-
// short-circuit the traversal itself, not just the arithmetic. A sentinel
|
|
60
|
-
// planted on an already-computed child must survive a second root call.
|
|
61
|
-
const child = leaf('a')
|
|
62
|
-
const root = internal('root', [child])
|
|
63
|
-
expect(calcDepthToLeaf(root)).toBe(1)
|
|
64
|
-
|
|
65
|
-
child.depthToLeaf = 99
|
|
66
|
-
expect(calcDepthToLeaf(root)).toBe(1)
|
|
67
|
-
expect(child.depthToLeaf).toBe(99)
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
describe('findMaxBranchLen', () => {
|
|
72
|
-
it('uses the node itself when it is a leaf', () => {
|
|
73
|
-
expect(findMaxBranchLen(leaf('a', 1.5))).toBe(1.5)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('takes the max across descendants', () => {
|
|
77
|
-
expect(
|
|
78
|
-
findMaxBranchLen(internal('p', [leaf('a', 0.5), leaf('b', 1.5)], 0.3)),
|
|
79
|
-
).toBe(1.5)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('treats a missing len as 0', () => {
|
|
83
|
-
expect(findMaxBranchLen(leaf('a'))).toBe(0)
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
describe('getNodeX cladogram positioning', () => {
|
|
88
|
-
it('aligns every tip at the rightmost x', () => {
|
|
89
|
-
const tips = [leaf('a'), leaf('b')]
|
|
90
|
-
calcDepthToLeaf(internal('root', tips))
|
|
91
|
-
|
|
92
|
-
const xs = tips.map(tip => getNodeX(tip, false, 100, 1))
|
|
93
|
-
expect(xs).toEqual([100, 100])
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('puts the root at the leftmost x and internal nodes in between', () => {
|
|
97
|
-
const tips = [leaf('a'), leaf('b')]
|
|
98
|
-
const intermediate = internal('int', tips)
|
|
99
|
-
const root = internal('root', [intermediate])
|
|
100
|
-
calcDepthToLeaf(root)
|
|
101
|
-
|
|
102
|
-
const xRoot = getNodeX(root, false, 100, 2)!
|
|
103
|
-
const xInt = getNodeX(intermediate, false, 100, 2)!
|
|
104
|
-
const xTip = getNodeX(tips[0]!, false, 100, 2)!
|
|
105
|
-
|
|
106
|
-
expect(xRoot).toBe(0)
|
|
107
|
-
expect(xInt).toBeGreaterThan(xRoot)
|
|
108
|
-
expect(xTip).toBeGreaterThan(xInt)
|
|
109
|
-
expect(xTip).toBe(100)
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
it('collapses to the root x when there is no topological depth', () => {
|
|
113
|
-
expect(getNodeX(leaf('a'), false, 100, 0)).toBe(0)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
it('uses branch length in phylogram mode', () => {
|
|
117
|
-
expect(getNodeX(leaf('a', 2.5), true, 100, 1)).toBe(2.5)
|
|
118
|
-
})
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
// the x values the tree pass actually strokes, for a model built from newick,
|
|
122
|
-
// alongside the tree width they are expected to span
|
|
123
|
-
function drawnTree(newick: string) {
|
|
124
|
-
const model = stateModelFactory().create({
|
|
125
|
-
type: 'MsaView',
|
|
126
|
-
data: { msa: '>a\nA\n>b\nA\n>c\nA\n>d\nA', tree: newick },
|
|
127
|
-
})
|
|
128
|
-
model.setWidth(1000)
|
|
129
|
-
// labels would need a canvas to measure; the branch geometry is the subject
|
|
130
|
-
model.setDrawLabels(false)
|
|
131
|
-
model.setDrawNodeBubbles(false)
|
|
132
|
-
|
|
133
|
-
const xs: number[] = []
|
|
134
|
-
const ctx = {
|
|
135
|
-
font: '12px sans-serif',
|
|
136
|
-
beginPath() {},
|
|
137
|
-
stroke() {},
|
|
138
|
-
resetTransform() {},
|
|
139
|
-
scale() {},
|
|
140
|
-
translate() {},
|
|
141
|
-
moveTo(x: number) {
|
|
142
|
-
xs.push(x)
|
|
143
|
-
},
|
|
144
|
-
lineTo(x: number) {
|
|
145
|
-
xs.push(x)
|
|
146
|
-
},
|
|
147
|
-
} as unknown as RenderCtx
|
|
148
|
-
|
|
149
|
-
renderTreeCanvas({
|
|
150
|
-
model,
|
|
151
|
-
ctx,
|
|
152
|
-
offsetY: 0,
|
|
153
|
-
theme: { palette: { text: { primary: '#000' } } } as Theme,
|
|
154
|
-
})
|
|
155
|
-
return { xs, model }
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
describe('renderTreeCanvas horizontal extent', () => {
|
|
159
|
-
it('spreads a cladogram across the tree area when branch lengths are absent', () => {
|
|
160
|
-
// a lengthless newick forces cladogram mode; scaling it by the (zero) max
|
|
161
|
-
// branch length would stack every node on x=0 as one vertical line
|
|
162
|
-
const { xs, model } = drawnTree('((a,b),(c,d));')
|
|
163
|
-
expect(Math.max(...xs)).toBe(model.treeWidth)
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
it('scales a phylogram by branch length', () => {
|
|
167
|
-
const { xs, model } = drawnTree('((a:0.1,b:0.2):0.3,(c:0.4,d:0.5):0.6);')
|
|
168
|
-
expect(Math.max(...xs)).toBeCloseTo(model.treeWidth)
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
// labels off means no label gutter to reserve, so the tips reach the far edge
|
|
172
|
-
// of the tree area rather than stopping at the default treeWidth
|
|
173
|
-
it('hands the label gutter to the tree when labels are off', () => {
|
|
174
|
-
const { model } = drawnTree('((a,b),(c,d));')
|
|
175
|
-
expect(model.treeWidth).toBe(model.treeAreaWidth - 10 - model.marginLeft)
|
|
176
|
-
})
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
describe('node bubble click targets', () => {
|
|
180
|
-
const bounds = { minX: 0, minY: 0, maxX: 10000, maxY: 10000 }
|
|
181
|
-
|
|
182
|
-
// "draw clickable bubbles" only controls the painting; the branches have to
|
|
183
|
-
// stay clickable with it off
|
|
184
|
-
function renderWithBubbles(drawNodeBubbles: boolean) {
|
|
185
|
-
const model = stateModelFactory().create({
|
|
186
|
-
type: 'MsaView',
|
|
187
|
-
data: { msa: '>a\nA\n>b\nA\n>c\nA\n>d\nA', tree: '((a,b),(c,d));' },
|
|
188
|
-
})
|
|
189
|
-
model.setWidth(1000)
|
|
190
|
-
model.setDrawLabels(false)
|
|
191
|
-
model.setDrawNodeBubbles(drawNodeBubbles)
|
|
192
|
-
|
|
193
|
-
let arcs = 0
|
|
194
|
-
const ctx = {
|
|
195
|
-
font: '12px sans-serif',
|
|
196
|
-
beginPath() {},
|
|
197
|
-
stroke() {},
|
|
198
|
-
fill() {},
|
|
199
|
-
resetTransform() {},
|
|
200
|
-
scale() {},
|
|
201
|
-
translate() {},
|
|
202
|
-
moveTo() {},
|
|
203
|
-
lineTo() {},
|
|
204
|
-
arc() {
|
|
205
|
-
arcs++
|
|
206
|
-
},
|
|
207
|
-
} as unknown as RenderCtx
|
|
208
|
-
|
|
209
|
-
const clickMap = new ClickMapIndex()
|
|
210
|
-
renderTreeCanvas({
|
|
211
|
-
model,
|
|
212
|
-
ctx,
|
|
213
|
-
clickMap,
|
|
214
|
-
offsetY: 0,
|
|
215
|
-
theme: { palette: { text: { primary: '#000' } } } as Theme,
|
|
216
|
-
})
|
|
217
|
-
return { arcs, hits: clickMap.search(bounds) }
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
it('indexes the internal nodes when the bubbles are drawn', () => {
|
|
221
|
-
const { arcs, hits } = renderWithBubbles(true)
|
|
222
|
-
expect(arcs).toBe(3)
|
|
223
|
-
expect(hits.filter(h => h.branch).length).toBe(3)
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
it('indexes them just the same when the bubbles are off', () => {
|
|
227
|
-
const { arcs, hits } = renderWithBubbles(false)
|
|
228
|
-
expect(arcs).toBe(0)
|
|
229
|
-
expect(hits.filter(h => h.branch).length).toBe(3)
|
|
230
|
-
})
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
describe('leaf label click targets', () => {
|
|
234
|
-
const bounds = { minX: 0, minY: 0, maxX: 10000, maxY: 10000 }
|
|
235
|
-
// the recorded fillText x is in content coordinates -- the fake ctx applies
|
|
236
|
-
// the same translate the real one does -- so it is directly comparable to the
|
|
237
|
-
// clickMap box, which is what the hit test searches
|
|
238
|
-
function renderLabels(labelsAlignRight: boolean) {
|
|
239
|
-
const model = stateModelFactory().create({
|
|
240
|
-
type: 'MsaView',
|
|
241
|
-
data: { msa: '>a\nA\n>b\nA', tree: '(a,b);' },
|
|
242
|
-
})
|
|
243
|
-
model.setWidth(1000)
|
|
244
|
-
model.setDrawTree(false)
|
|
245
|
-
model.setLabelsAlignRight(labelsAlignRight)
|
|
246
|
-
|
|
247
|
-
let tx = 0
|
|
248
|
-
const drawn: number[] = []
|
|
249
|
-
const ctx = {
|
|
250
|
-
font: '12px sans-serif',
|
|
251
|
-
measureText: (text: string) => ({ width: text.length * 6 }),
|
|
252
|
-
beginPath() {},
|
|
253
|
-
stroke() {},
|
|
254
|
-
setLineDash() {},
|
|
255
|
-
resetTransform() {
|
|
256
|
-
tx = 0
|
|
257
|
-
},
|
|
258
|
-
scale() {},
|
|
259
|
-
translate(x: number) {
|
|
260
|
-
tx += x
|
|
261
|
-
},
|
|
262
|
-
moveTo() {},
|
|
263
|
-
lineTo() {},
|
|
264
|
-
fillText(_text: string, x: number) {
|
|
265
|
-
drawn.push(x + tx)
|
|
266
|
-
},
|
|
267
|
-
} as unknown as RenderCtx
|
|
268
|
-
|
|
269
|
-
const clickMap = new ClickMapIndex()
|
|
270
|
-
renderTreeCanvas({
|
|
271
|
-
model,
|
|
272
|
-
ctx,
|
|
273
|
-
clickMap,
|
|
274
|
-
offsetY: 0,
|
|
275
|
-
theme: { palette: { text: { primary: '#000' } } } as Theme,
|
|
276
|
-
})
|
|
277
|
-
return { drawn, hits: clickMap.search(bounds).filter(h => !h.branch) }
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
it('boxes a right-aligned label at the edge it is drawn against', () => {
|
|
281
|
-
const { drawn, hits } = renderLabels(true)
|
|
282
|
-
expect(hits.length).toBe(drawn.length)
|
|
283
|
-
// textAlign is 'right' here, so the drawn x is the label's right edge
|
|
284
|
-
for (const hit of hits) {
|
|
285
|
-
expect(drawn).toContain(hit.maxX)
|
|
286
|
-
}
|
|
287
|
-
})
|
|
288
|
-
|
|
289
|
-
it('boxes a left-aligned label at the edge it is drawn from', () => {
|
|
290
|
-
const { drawn, hits } = renderLabels(false)
|
|
291
|
-
expect(hits.length).toBe(drawn.length)
|
|
292
|
-
for (const hit of hits) {
|
|
293
|
-
expect(drawn).toContain(hit.minX)
|
|
294
|
-
}
|
|
295
|
-
})
|
|
296
|
-
})
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { getSnapshot } from '@jbrowse/mobx-state-tree'
|
|
2
|
-
import { expect, test } from 'vitest'
|
|
3
|
-
|
|
4
|
-
import stateModelFactory from './model.ts'
|
|
5
|
-
|
|
6
|
-
const MsaView = stateModelFactory()
|
|
7
|
-
|
|
8
|
-
test('an empty model is not initialized', () => {
|
|
9
|
-
expect(MsaView.create({ type: 'MsaView' }).dataInitialized).toBe(false)
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
test('inline data initializes the view', () => {
|
|
13
|
-
const model = MsaView.create({
|
|
14
|
-
type: 'MsaView',
|
|
15
|
-
data: { msa: '>a\nACGT\n>b\nACGA\n', tree: '' },
|
|
16
|
-
})
|
|
17
|
-
expect(model.dataInitialized).toBe(true)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
// DataModel's postProcessSnapshot drops a document over 50kb rather than
|
|
21
|
-
// inlining it into a session or a shared URL, so it comes back `undefined`
|
|
22
|
-
// rather than ''. That has to read as "no data" -- otherwise the restored
|
|
23
|
-
// session renders an empty alignment instead of the import form
|
|
24
|
-
test('a dropped oversize inline msa restores as uninitialized', () => {
|
|
25
|
-
const msa = `>a\n${'A'.repeat(60_000)}\n>b\n${'C'.repeat(60_000)}\n`
|
|
26
|
-
const model = MsaView.create({ type: 'MsaView', data: { msa, tree: '' } })
|
|
27
|
-
expect(model.dataInitialized).toBe(true)
|
|
28
|
-
|
|
29
|
-
const restored = MsaView.create(getSnapshot(model))
|
|
30
|
-
expect(restored.data.msa).toBeUndefined()
|
|
31
|
-
expect(restored.MSA).toBe(null)
|
|
32
|
-
expect(restored.dataInitialized).toBe(false)
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
test('an error keeps the view uninitialized', () => {
|
|
36
|
-
const model = MsaView.create({
|
|
37
|
-
type: 'MsaView',
|
|
38
|
-
data: { msa: '>a\nACGT\n', tree: '' },
|
|
39
|
-
})
|
|
40
|
-
model.setError(new Error('boom'))
|
|
41
|
-
expect(model.dataInitialized).toBe(false)
|
|
42
|
-
})
|
package/src/domainBands.test.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
// The domain overlay resolves each annotation to the visible column span it is
|
|
3
|
-
// drawn across once, on the model, instead of converting sequence positions
|
|
4
|
-
// inside every canvas block. These tests pin that span (including across hidden
|
|
5
|
-
// gappy columns) and the hit-test built on top of it.
|
|
6
|
-
import { expect, test } from 'vitest'
|
|
7
|
-
|
|
8
|
-
import MSAModelF from './model.ts'
|
|
9
|
-
|
|
10
|
-
// row `b` has a 4-residue insertion relative to `a`, which becomes a run of
|
|
11
|
-
// mostly-gap columns that gap hiding can remove
|
|
12
|
-
const msa = `>a
|
|
13
|
-
MKLV----WYAC
|
|
14
|
-
>b
|
|
15
|
-
MKLVQQQQWYAC`
|
|
16
|
-
|
|
17
|
-
const gff = `##gff-version 3
|
|
18
|
-
a Pfam protein_match 1 4 . . . Name=PF00001;signature_desc=First
|
|
19
|
-
a Pfam protein_match 5 8 . . . Name=PF00002;signature_desc=Second`
|
|
20
|
-
|
|
21
|
-
// row `b` only: PF00003 ends inside the insertion, PF00004 lies entirely within
|
|
22
|
-
// it, so gap hiding puts one end and then both ends into hidden columns
|
|
23
|
-
const insertionGff = `##gff-version 3
|
|
24
|
-
b Pfam protein_match 4 8 . . . Name=PF00003;signature_desc=Overlapping
|
|
25
|
-
b Pfam protein_match 5 8 . . . Name=PF00004;signature_desc=Inside`
|
|
26
|
-
|
|
27
|
-
function makeModel() {
|
|
28
|
-
const model = MSAModelF().create({
|
|
29
|
-
id: 'domain-bands-test',
|
|
30
|
-
type: 'MsaView',
|
|
31
|
-
msaFormat: 'fasta',
|
|
32
|
-
height: 400,
|
|
33
|
-
data: { msa },
|
|
34
|
-
})
|
|
35
|
-
model.setWidth(800)
|
|
36
|
-
model.applyGFFText(gff)
|
|
37
|
-
return model
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
test('bands span the columns their residues occupy', () => {
|
|
41
|
-
const model = makeModel()
|
|
42
|
-
const bands = model.domainBands.get('a')!
|
|
43
|
-
expect(
|
|
44
|
-
bands.map(b => [b.annotation.accession, b.startCol, b.endCol]),
|
|
45
|
-
).toEqual([
|
|
46
|
-
['PF00001', 0, 4],
|
|
47
|
-
['PF00002', 8, 12],
|
|
48
|
-
])
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
test('bands follow the columns when gappy columns are hidden', () => {
|
|
52
|
-
const model = makeModel()
|
|
53
|
-
model.setHideGaps(true)
|
|
54
|
-
model.setAllowedGappyness(50)
|
|
55
|
-
// the 4 insertion columns are gaps in half the rows, so they are hidden and
|
|
56
|
-
// everything to their right shifts left by 4
|
|
57
|
-
expect(model.blanks).toEqual([4, 5, 6, 7])
|
|
58
|
-
const bands = model.domainBands.get('a')!
|
|
59
|
-
expect(bands.map(b => [b.startCol, b.endCol])).toEqual([
|
|
60
|
-
[0, 4],
|
|
61
|
-
[4, 8],
|
|
62
|
-
])
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
test('a band whose end lands in a hidden column keeps its visible part', () => {
|
|
66
|
-
const model = makeModel()
|
|
67
|
-
model.applyGFFText(insertionGff)
|
|
68
|
-
expect(model.domainBands.get('b')!.map(b => [b.startCol, b.endCol])).toEqual([
|
|
69
|
-
[3, 8],
|
|
70
|
-
[4, 8],
|
|
71
|
-
])
|
|
72
|
-
|
|
73
|
-
model.setHideGaps(true)
|
|
74
|
-
model.setAllowedGappyness(50)
|
|
75
|
-
expect(model.blanks).toEqual([4, 5, 6, 7])
|
|
76
|
-
// PF00003 covers V + the 4 hidden Qs, so only the V column survives; PF00004
|
|
77
|
-
// is nothing but hidden columns and drops out entirely
|
|
78
|
-
expect(model.domainBands.get('b')!.map(b => [b.startCol, b.endCol])).toEqual([
|
|
79
|
-
[3, 4],
|
|
80
|
-
])
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
test('mouseOverDomains hit-tests against the drawn span', () => {
|
|
84
|
-
const model = makeModel()
|
|
85
|
-
const rowIndex = model.rowNames.indexOf('a')
|
|
86
|
-
|
|
87
|
-
model.setMousePos(0, rowIndex)
|
|
88
|
-
expect(model.mouseOverDomains.map(d => d.accession)).toEqual(['PF00001'])
|
|
89
|
-
|
|
90
|
-
// the columns between the two domains are the insertion gap: no domain there
|
|
91
|
-
model.setMousePos(5, rowIndex)
|
|
92
|
-
expect(model.mouseOverDomains).toEqual([])
|
|
93
|
-
|
|
94
|
-
model.setMousePos(8, rowIndex)
|
|
95
|
-
expect(model.mouseOverDomains.map(d => d.accession)).toEqual(['PF00002'])
|
|
96
|
-
|
|
97
|
-
// end column is exclusive
|
|
98
|
-
model.setMousePos(12, rowIndex)
|
|
99
|
-
expect(model.mouseOverDomains).toEqual([])
|
|
100
|
-
|
|
101
|
-
// the other row has no annotations of its own
|
|
102
|
-
model.setMousePos(0, model.rowNames.indexOf('b'))
|
|
103
|
-
expect(model.mouseOverDomains).toEqual([])
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
test('filtering a domain off removes its band', () => {
|
|
107
|
-
const model = makeModel()
|
|
108
|
-
model.setFilter('PF00001', false)
|
|
109
|
-
expect(model.domainBands.get('a')!.map(b => b.annotation.accession)).toEqual([
|
|
110
|
-
'PF00002',
|
|
111
|
-
])
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
test('highlighted columns collapse into contiguous runs', () => {
|
|
115
|
-
const model = makeModel()
|
|
116
|
-
model.setHighlightedColumns([5, 1, 2, 3, 9])
|
|
117
|
-
expect(model.highlightedColumnRuns).toEqual([
|
|
118
|
-
{ start: 1, end: 3 },
|
|
119
|
-
{ start: 5, end: 5 },
|
|
120
|
-
{ start: 9, end: 9 },
|
|
121
|
-
])
|
|
122
|
-
})
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
//
|
|
3
|
-
// Letters drawn on top of the domain overlay take their color from the box
|
|
4
|
-
// underneath them. The overlay paints bands largest-first, so with nested
|
|
5
|
-
// signatures -- routine in InterProScan output, where a family encloses a
|
|
6
|
-
// domain -- the box actually visible at a column is the *last* one painted,
|
|
7
|
-
// not the first one covering it.
|
|
8
|
-
import { expect, test } from 'vitest'
|
|
9
|
-
|
|
10
|
-
import { domainBandCursor } from './components/msa/domainBandCursor.ts'
|
|
11
|
-
import MSAModelF from './model.ts'
|
|
12
|
-
|
|
13
|
-
const row = 'ACDEFGHIKLMNPQRSTVWY'
|
|
14
|
-
const msa = `>seq1\n${row}\n>seq2\n${row}`
|
|
15
|
-
|
|
16
|
-
// PF_OUTER spans the whole row, PF_INNER sits inside it. tidyInterProAnnotations
|
|
17
|
-
// orders by length descending, so the outer band paints first and the inner one
|
|
18
|
-
// covers it.
|
|
19
|
-
const gff = `##gff-version 3
|
|
20
|
-
seq1\tPfam\tprotein_match\t1\t20\t.\t.\t.\tName=PF_OUTER;signature_desc=Outer
|
|
21
|
-
seq1\tPfam\tprotein_match\t8\t12\t.\t.\t.\tName=PF_INNER;signature_desc=Inner`
|
|
22
|
-
|
|
23
|
-
function makeModel() {
|
|
24
|
-
const model = MSAModelF().create({
|
|
25
|
-
type: 'MsaView',
|
|
26
|
-
msaFormat: 'fasta',
|
|
27
|
-
data: { msa },
|
|
28
|
-
})
|
|
29
|
-
model.setWidth(800)
|
|
30
|
-
model.applyGFFText(gff)
|
|
31
|
-
return model
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function sweep(model: ReturnType<typeof makeModel>, from = 0) {
|
|
35
|
-
const bandAt = domainBandCursor(model.domainBandsByStart.get('seq1'))
|
|
36
|
-
const out: (string | undefined)[] = []
|
|
37
|
-
for (let col = from; col < 20; col++) {
|
|
38
|
-
out.push(bandAt(col)?.annotation.accession)
|
|
39
|
-
}
|
|
40
|
-
return out
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
test('the overlay paints largest-first, so stackIndex is paint order', () => {
|
|
44
|
-
const bands = makeModel().domainBands.get('seq1')!
|
|
45
|
-
expect(bands.map(b => [b.annotation.accession, b.stackIndex])).toEqual([
|
|
46
|
-
['PF_OUTER', 0],
|
|
47
|
-
['PF_INNER', 1],
|
|
48
|
-
])
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
test('a nested band wins the columns it covers', () => {
|
|
52
|
-
const model = makeModel()
|
|
53
|
-
// PF_INNER is seq positions 8-12 (1-based), i.e. columns 7..11
|
|
54
|
-
expect(sweep(model)).toEqual([
|
|
55
|
-
...Array.from({ length: 7 }, () => 'PF_OUTER'),
|
|
56
|
-
...Array.from({ length: 5 }, () => 'PF_INNER'),
|
|
57
|
-
...Array.from({ length: 8 }, () => 'PF_OUTER'),
|
|
58
|
-
])
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test('a sweep starting mid-block picks up bands opened before it', () => {
|
|
62
|
-
// canvas blocks start at arbitrary columns, so the cursor has to catch up on
|
|
63
|
-
// its first call rather than assuming it began at column 0
|
|
64
|
-
const model = makeModel()
|
|
65
|
-
expect(sweep(model, 9)).toEqual([
|
|
66
|
-
'PF_INNER',
|
|
67
|
-
'PF_INNER',
|
|
68
|
-
'PF_INNER',
|
|
69
|
-
...Array.from({ length: 8 }, () => 'PF_OUTER'),
|
|
70
|
-
])
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
test('columns outside every band have no covering band', () => {
|
|
74
|
-
const model = makeModel()
|
|
75
|
-
model.setFilter('PF_OUTER', false)
|
|
76
|
-
const bandAt = domainBandCursor(model.domainBandsByStart.get('seq1'))
|
|
77
|
-
expect(bandAt(0)).toBeUndefined()
|
|
78
|
-
expect(bandAt(9)?.annotation.accession).toBe('PF_INNER')
|
|
79
|
-
expect(bandAt(19)).toBeUndefined()
|
|
80
|
-
})
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { expect, test } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { exportFileName } from './exportFileName.ts'
|
|
4
|
-
|
|
5
|
-
test('takes the alignment file name and swaps the extension', () => {
|
|
6
|
-
expect(
|
|
7
|
-
exportFileName(
|
|
8
|
-
{
|
|
9
|
-
uri: 'https://example.org/data/PF00069.stock?dl=1',
|
|
10
|
-
locationType: 'UriLocation',
|
|
11
|
-
},
|
|
12
|
-
'svg',
|
|
13
|
-
),
|
|
14
|
-
).toBe('PF00069.svg')
|
|
15
|
-
expect(
|
|
16
|
-
exportFileName(
|
|
17
|
-
{
|
|
18
|
-
localPath: 'C:\\aligns\\hemoglobin.fa',
|
|
19
|
-
locationType: 'LocalPathLocation',
|
|
20
|
-
},
|
|
21
|
-
'svg',
|
|
22
|
-
),
|
|
23
|
-
).toBe('hemoglobin.svg')
|
|
24
|
-
expect(
|
|
25
|
-
exportFileName(
|
|
26
|
-
{ blobId: 'b1', name: 'pasted.aln', locationType: 'BlobLocation' },
|
|
27
|
-
'svg',
|
|
28
|
-
),
|
|
29
|
-
).toBe('pasted.svg')
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
test('falls back to a plain name without a file', () => {
|
|
33
|
-
expect(exportFileName(undefined, 'svg')).toBe('image.svg')
|
|
34
|
-
expect(
|
|
35
|
-
exportFileName(
|
|
36
|
-
{ uri: 'https://example.org/', locationType: 'UriLocation' },
|
|
37
|
-
'svg',
|
|
38
|
-
),
|
|
39
|
-
).toBe('image.svg')
|
|
40
|
-
})
|
package/src/fetchUtils.test.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { openLocation } from '@jbrowse/core/util/io'
|
|
2
|
-
import { describe, expect, test } from 'vitest'
|
|
3
|
-
|
|
4
|
-
import { fetchTextWithProgress, isAbortError } from './fetchUtils.ts'
|
|
5
|
-
|
|
6
|
-
import type { FetchStatus } from './fetchUtils.ts'
|
|
7
|
-
|
|
8
|
-
const loc = openLocation({
|
|
9
|
-
uri: 'http://example.com/data.fa',
|
|
10
|
-
locationType: 'UriLocation',
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
describe('fetchTextWithProgress', () => {
|
|
14
|
-
test('reports progress messages then clears status', async () => {
|
|
15
|
-
const statuses: (FetchStatus | undefined)[] = []
|
|
16
|
-
const result = await fetchTextWithProgress(
|
|
17
|
-
loc,
|
|
18
|
-
s => statuses.push(s),
|
|
19
|
-
async (_loc, opts) => {
|
|
20
|
-
opts.statusCallback('Downloading file')
|
|
21
|
-
opts.statusCallback('')
|
|
22
|
-
return 'GREETINGS'
|
|
23
|
-
},
|
|
24
|
-
)
|
|
25
|
-
expect(result).toBe('GREETINGS')
|
|
26
|
-
expect(statuses.map(s => s?.msg)).toEqual([
|
|
27
|
-
'Downloading file',
|
|
28
|
-
undefined,
|
|
29
|
-
undefined,
|
|
30
|
-
])
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
test('reports the message from a determinate progress status', async () => {
|
|
34
|
-
const statuses: (FetchStatus | undefined)[] = []
|
|
35
|
-
await fetchTextWithProgress(
|
|
36
|
-
loc,
|
|
37
|
-
s => statuses.push(s),
|
|
38
|
-
async (_loc, opts) => {
|
|
39
|
-
opts.statusCallback({
|
|
40
|
-
message: 'Downloading file',
|
|
41
|
-
current: 5,
|
|
42
|
-
total: 10,
|
|
43
|
-
})
|
|
44
|
-
return 'GREETINGS'
|
|
45
|
-
},
|
|
46
|
-
)
|
|
47
|
-
expect(statuses[0]?.msg).toBe('Downloading file')
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
test('clears status even when the fetch throws', async () => {
|
|
51
|
-
const statuses: (FetchStatus | undefined)[] = []
|
|
52
|
-
await expect(
|
|
53
|
-
fetchTextWithProgress(
|
|
54
|
-
loc,
|
|
55
|
-
s => statuses.push(s),
|
|
56
|
-
async () => {
|
|
57
|
-
throw new Error('network down')
|
|
58
|
-
},
|
|
59
|
-
),
|
|
60
|
-
).rejects.toThrow('network down')
|
|
61
|
-
expect(statuses.at(-1)).toBeUndefined()
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
test('onCancel aborts the underlying request', async () => {
|
|
65
|
-
const statuses: (FetchStatus | undefined)[] = []
|
|
66
|
-
const promise = fetchTextWithProgress(
|
|
67
|
-
loc,
|
|
68
|
-
s => statuses.push(s),
|
|
69
|
-
(_loc, opts) =>
|
|
70
|
-
new Promise<string>((_resolve, reject) => {
|
|
71
|
-
opts.statusCallback('Downloading file')
|
|
72
|
-
opts.signal.addEventListener('abort', () => {
|
|
73
|
-
reject(new DOMException('Aborted', 'AbortError'))
|
|
74
|
-
})
|
|
75
|
-
}),
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
statuses.find(s => s?.onCancel)?.onCancel?.()
|
|
79
|
-
|
|
80
|
-
await expect(promise).rejects.toSatisfy(isAbortError)
|
|
81
|
-
expect(statuses.at(-1)).toBeUndefined()
|
|
82
|
-
})
|
|
83
|
-
})
|