jbrowse-plugin-msaview 3.5.0 → 3.7.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 +8 -0
- package/dist/AddHighlightModel/index.js +3 -3
- package/dist/BgzipFastaMsaAdapter/BgzipFastaMsaAdapter.d.ts +8 -2
- package/dist/BgzipFastaMsaAdapter/configSchema.d.ts +3 -3
- package/dist/BgzipFastaMsaAdapter/configSchema.js +1 -1
- package/dist/LaunchMsaView/cleanProteinSequence.test.d.ts +1 -0
- package/dist/LaunchMsaView/cleanProteinSequence.test.js +77 -0
- package/dist/LaunchMsaView/codingFeature.d.ts +14 -0
- package/dist/LaunchMsaView/codingFeature.js +38 -0
- package/dist/LaunchMsaView/codingFeature.test.d.ts +1 -0
- package/dist/LaunchMsaView/codingFeature.test.js +75 -0
- package/dist/LaunchMsaView/components/BlastQuery/BlastAutomaticPanel.d.ts +3 -1
- package/dist/LaunchMsaView/components/BlastQuery/BlastAutomaticPanel.js +47 -55
- package/dist/LaunchMsaView/components/BlastQuery/BlastManualPanel.d.ts +3 -1
- package/dist/LaunchMsaView/components/BlastQuery/BlastManualPanel.js +16 -17
- package/dist/LaunchMsaView/components/BlastQuery/BlastPanel.d.ts +7 -3
- package/dist/LaunchMsaView/components/BlastQuery/BlastPanel.js +8 -7
- package/dist/LaunchMsaView/components/BlastQuery/BlastSettingsDialog.js +2 -2
- package/dist/LaunchMsaView/components/BlastQuery/CachedBlastResults.js +14 -13
- package/dist/LaunchMsaView/components/BlastQuery/consts.d.ts +2 -0
- package/dist/LaunchMsaView/components/BlastQuery/consts.js +28 -4
- package/dist/LaunchMsaView/components/HelpButton.d.ts +2 -0
- package/dist/LaunchMsaView/components/HelpButton.js +17 -0
- package/dist/LaunchMsaView/components/HelpDialog.d.ts +4 -0
- package/dist/LaunchMsaView/components/HelpDialog.js +18 -0
- package/dist/LaunchMsaView/components/LaunchMsaViewDialog.d.ts +3 -1
- package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js +21 -16
- package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.d.ts +3 -1
- package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +34 -26
- package/dist/LaunchMsaView/components/OrthologQuery/OrthologPanel.d.ts +3 -1
- package/dist/LaunchMsaView/components/OrthologQuery/OrthologPanel.js +30 -26
- package/dist/LaunchMsaView/components/OrthologQuery/OrthologSourceSelect.d.ts +2 -1
- package/dist/LaunchMsaView/components/OrthologQuery/OrthologSourceSelect.js +18 -2
- package/dist/LaunchMsaView/components/OrthologQuery/OrthologSourceSelect.test.d.ts +1 -0
- package/dist/LaunchMsaView/components/OrthologQuery/OrthologSourceSelect.test.js +13 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.d.ts +3 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +50 -27
- package/dist/LaunchMsaView/components/SequenceStatus.d.ts +14 -0
- package/dist/LaunchMsaView/components/SequenceStatus.js +15 -0
- package/dist/LaunchMsaView/components/SubmitCancelActions.d.ts +6 -2
- package/dist/LaunchMsaView/components/SubmitCancelActions.js +28 -13
- package/dist/LaunchMsaView/components/SubmitCancelActions.test.js +52 -4
- package/dist/LaunchMsaView/components/TabPanel.js +15 -3
- package/dist/LaunchMsaView/components/TabPanel.test.d.ts +1 -0
- package/dist/LaunchMsaView/components/TabPanel.test.js +36 -0
- package/dist/LaunchMsaView/components/TranscriptSelector.d.ts +3 -1
- package/dist/LaunchMsaView/components/TranscriptSelector.js +4 -2
- package/dist/LaunchMsaView/components/calculateProteinSequence.d.ts +12 -2
- package/dist/LaunchMsaView/components/calculateProteinSequence.js +38 -23
- package/dist/LaunchMsaView/components/fetchSeq.d.ts +4 -1
- package/dist/LaunchMsaView/components/fetchSeq.js +14 -4
- package/dist/LaunchMsaView/components/launchConnectedView.d.ts +23 -0
- package/dist/LaunchMsaView/components/launchConnectedView.js +39 -0
- package/dist/LaunchMsaView/components/launchPlacement.d.ts +8 -0
- package/dist/LaunchMsaView/components/launchPlacement.js +25 -0
- package/dist/LaunchMsaView/components/useFeatureSequence.d.ts +2 -0
- package/dist/LaunchMsaView/components/useFeatureSequence.js +14 -11
- package/dist/LaunchMsaView/components/useTranscriptSelection.d.ts +10 -1
- package/dist/LaunchMsaView/components/useTranscriptSelection.js +21 -3
- package/dist/LaunchMsaView/components/useTranscriptSelection.test.d.ts +1 -0
- package/dist/LaunchMsaView/components/useTranscriptSelection.test.js +57 -0
- package/dist/LaunchMsaView/detectQueryRow.js +4 -7
- package/dist/LaunchMsaView/index.js +28 -9
- package/dist/LaunchMsaView/launchTarget.d.ts +36 -8
- package/dist/LaunchMsaView/launchTarget.js +23 -13
- package/dist/LaunchMsaView/launchTarget.test.js +80 -15
- package/dist/LaunchMsaView/useQueryRowName.d.ts +12 -0
- package/dist/LaunchMsaView/useQueryRowName.js +11 -0
- package/dist/LaunchMsaView/useQueryRowName.test.js +18 -1
- package/dist/LaunchMsaView/util.d.ts +6 -0
- package/dist/LaunchMsaView/util.js +12 -3
- package/dist/LaunchMsaViewExtensionPoint/index.test.js +15 -0
- package/dist/MsaViewPanel/afterCreateAutoruns.d.ts +6 -4
- package/dist/MsaViewPanel/afterCreateAutoruns.js +38 -14
- package/dist/MsaViewPanel/applyRegion.d.ts +23 -0
- package/dist/MsaViewPanel/applyRegion.js +19 -0
- package/dist/MsaViewPanel/applyRegion.test.d.ts +1 -0
- package/dist/MsaViewPanel/applyRegion.test.js +45 -0
- package/dist/MsaViewPanel/components/LaunchProgress.d.ts +4 -3
- package/dist/MsaViewPanel/components/LaunchProgress.js +10 -7
- package/dist/MsaViewPanel/components/MsaViewPanel.js +7 -3
- package/dist/MsaViewPanel/components/MsaViewPanel.test.js +24 -0
- package/dist/MsaViewPanel/doLaunchBlast.js +2 -1
- package/dist/MsaViewPanel/doLaunchBlast.test.js +12 -0
- package/dist/MsaViewPanel/doLaunchOrthologs.test.js +1 -1
- package/dist/MsaViewPanel/genomeToMSA.js +24 -6
- package/dist/MsaViewPanel/genomeToMSA.test.js +218 -44
- package/dist/MsaViewPanel/launchAutoruns.test.d.ts +1 -0
- package/dist/MsaViewPanel/launchAutoruns.test.js +36 -0
- package/dist/MsaViewPanel/model.d.ts +156 -61
- package/dist/MsaViewPanel/model.js +69 -3
- package/dist/MsaViewPanel/model.test.js +66 -0
- package/dist/MsaViewPanel/msaDataStore.d.ts +5 -3
- package/dist/MsaViewPanel/msaDataStore.js +3 -12
- package/dist/MsaViewPanel/msaDataStore.test.js +8 -1
- package/dist/MsaViewPanel/observeProteinHighlights.test.js +4 -4
- package/dist/MsaViewPanel/regionSnapshot.test.d.ts +1 -0
- package/dist/MsaViewPanel/regionSnapshot.test.js +29 -0
- package/dist/MsaViewPanel/resolveConnectedTranscript.d.ts +41 -4
- package/dist/MsaViewPanel/resolveConnectedTranscript.js +109 -68
- package/dist/MsaViewPanel/resolveConnectedTranscript.test.d.ts +1 -0
- package/dist/MsaViewPanel/resolveConnectedTranscript.test.js +149 -0
- package/dist/MsaViewPanel/runLaunch.d.ts +8 -4
- package/dist/MsaViewPanel/runLaunch.js +15 -4
- package/dist/MsaViewPanel/runLaunch.test.js +16 -0
- package/dist/MsaViewPanel/storedData.test.js +43 -0
- package/dist/MsaViewPanel/syncGenomeHoverToMsaColumn.test.js +15 -7
- package/dist/MsaViewPanel/util.d.ts +23 -23
- package/dist/MsaViewPanel/util.js +23 -24
- package/dist/index.d.ts +11 -11
- package/dist/index.js +17 -10
- package/dist/jbrowse-plugin-msaview.umd.production.min.js +54 -67
- package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
- package/dist/utils/blastCache.d.ts +26 -2
- package/dist/utils/blastCache.js +51 -39
- package/dist/utils/blastCache.test.js +46 -19
- package/dist/utils/domainCache.d.ts +1 -1
- package/dist/utils/domainCache.js +18 -14
- package/dist/utils/ebiJobDispatcher.d.ts +11 -0
- package/dist/utils/ebiJobDispatcher.js +12 -13
- package/dist/utils/ebiJobDispatcher.test.js +17 -3
- package/dist/utils/eutils.d.ts +14 -0
- package/dist/utils/eutils.js +48 -14
- package/dist/utils/eutils.test.d.ts +1 -0
- package/dist/utils/eutils.test.js +31 -0
- package/dist/utils/idb.d.ts +16 -3
- package/dist/utils/idb.js +51 -5
- package/dist/utils/idb.test.d.ts +1 -0
- package/dist/utils/idb.test.js +78 -0
- package/dist/utils/ncbiDomains.js +4 -4
- package/dist/utils/ncbiOrthologs.d.ts +1 -1
- package/dist/utils/ncbiOrthologs.js +18 -17
- package/dist/utils/ncbiOrthologs.test.js +17 -1
- package/dist/utils/ncbiTaxonomy.js +14 -15
- package/dist/utils/taxonomyNames.js +23 -19
- package/dist/utils/taxonomyNames.test.d.ts +1 -0
- package/dist/utils/taxonomyNames.test.js +33 -0
- package/dist/utils/unirefHomologs.js +2 -2
- package/dist/utils/unirefHomologs.test.js +8 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +23 -23
- package/src/AddHighlightModel/index.tsx +1 -1
- package/src/BgzipFastaMsaAdapter/configSchema.ts +1 -1
- package/src/LaunchMsaView/cleanProteinSequence.test.ts +91 -0
- package/src/LaunchMsaView/codingFeature.test.ts +96 -0
- package/src/LaunchMsaView/codingFeature.ts +49 -0
- package/src/LaunchMsaView/components/BlastQuery/BlastAutomaticPanel.tsx +60 -56
- package/src/LaunchMsaView/components/BlastQuery/BlastManualPanel.tsx +18 -15
- package/src/LaunchMsaView/components/BlastQuery/BlastPanel.tsx +24 -11
- package/src/LaunchMsaView/components/BlastQuery/BlastSettingsDialog.tsx +4 -4
- package/src/LaunchMsaView/components/BlastQuery/CachedBlastResults.tsx +16 -15
- package/src/LaunchMsaView/components/BlastQuery/consts.ts +31 -4
- package/src/LaunchMsaView/components/HelpButton.tsx +33 -0
- package/src/LaunchMsaView/components/HelpDialog.tsx +78 -0
- package/src/LaunchMsaView/components/LaunchMsaViewDialog.tsx +54 -34
- package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +46 -23
- package/src/LaunchMsaView/components/OrthologQuery/OrthologPanel.tsx +41 -28
- package/src/LaunchMsaView/components/OrthologQuery/OrthologSourceSelect.test.ts +16 -0
- package/src/LaunchMsaView/components/OrthologQuery/OrthologSourceSelect.tsx +24 -2
- package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +81 -25
- package/src/LaunchMsaView/components/SequenceStatus.tsx +29 -0
- package/src/LaunchMsaView/components/SubmitCancelActions.test.tsx +88 -4
- package/src/LaunchMsaView/components/SubmitCancelActions.tsx +43 -16
- package/src/LaunchMsaView/components/TabPanel.test.tsx +51 -0
- package/src/LaunchMsaView/components/TabPanel.tsx +16 -4
- package/src/LaunchMsaView/components/TranscriptSelector.tsx +6 -1
- package/src/LaunchMsaView/components/calculateProteinSequence.ts +51 -22
- package/src/LaunchMsaView/components/fetchSeq.ts +25 -5
- package/src/LaunchMsaView/components/launchConnectedView.ts +56 -0
- package/src/LaunchMsaView/components/launchPlacement.tsx +41 -0
- package/src/LaunchMsaView/components/useFeatureSequence.ts +18 -11
- package/src/LaunchMsaView/components/useTranscriptSelection.test.tsx +66 -0
- package/src/LaunchMsaView/components/useTranscriptSelection.ts +41 -2
- package/src/LaunchMsaView/detectQueryRow.ts +5 -7
- package/src/LaunchMsaView/index.ts +32 -13
- package/src/LaunchMsaView/launchTarget.test.ts +88 -15
- package/src/LaunchMsaView/launchTarget.ts +49 -14
- package/src/LaunchMsaView/useQueryRowName.test.ts +28 -1
- package/src/LaunchMsaView/useQueryRowName.ts +17 -0
- package/src/LaunchMsaView/util.ts +15 -5
- package/src/LaunchMsaViewExtensionPoint/index.test.ts +16 -0
- package/src/LaunchMsaViewExtensionPoint/index.ts +28 -1
- package/src/MsaViewPanel/afterCreateAutoruns.ts +46 -14
- package/src/MsaViewPanel/applyRegion.test.ts +55 -0
- package/src/MsaViewPanel/applyRegion.ts +33 -0
- package/src/MsaViewPanel/components/LaunchProgress.tsx +12 -5
- package/src/MsaViewPanel/components/MsaViewPanel.test.tsx +26 -0
- package/src/MsaViewPanel/components/MsaViewPanel.tsx +7 -5
- package/src/MsaViewPanel/doLaunchBlast.test.ts +20 -1
- package/src/MsaViewPanel/doLaunchBlast.ts +2 -1
- package/src/MsaViewPanel/doLaunchOrthologs.test.ts +1 -1
- package/src/MsaViewPanel/genomeToMSA.test.ts +255 -59
- package/src/MsaViewPanel/genomeToMSA.ts +30 -5
- package/src/MsaViewPanel/launchAutoruns.test.ts +45 -0
- package/src/MsaViewPanel/model.test.ts +75 -0
- package/src/MsaViewPanel/model.ts +76 -3
- package/src/MsaViewPanel/msaDataStore.test.ts +14 -2
- package/src/MsaViewPanel/msaDataStore.ts +4 -12
- package/src/MsaViewPanel/observeProteinHighlights.test.ts +4 -4
- package/src/MsaViewPanel/regionSnapshot.test.ts +34 -0
- package/src/MsaViewPanel/resolveConnectedTranscript.test.ts +183 -0
- package/src/MsaViewPanel/resolveConnectedTranscript.ts +160 -67
- package/src/MsaViewPanel/runLaunch.test.ts +19 -0
- package/src/MsaViewPanel/runLaunch.ts +21 -4
- package/src/MsaViewPanel/storedData.test.ts +58 -0
- package/src/MsaViewPanel/syncGenomeHoverToMsaColumn.test.ts +17 -7
- package/src/MsaViewPanel/util.ts +38 -29
- package/src/index.ts +19 -10
- package/src/utils/blastCache.test.ts +59 -20
- package/src/utils/blastCache.ts +62 -39
- package/src/utils/domainCache.ts +27 -15
- package/src/utils/ebiJobDispatcher.test.ts +18 -3
- package/src/utils/ebiJobDispatcher.ts +12 -16
- package/src/utils/eutils.test.ts +39 -0
- package/src/utils/eutils.ts +64 -14
- package/src/utils/idb.test.ts +106 -0
- package/src/utils/idb.ts +57 -5
- package/src/utils/ncbiDomains.ts +4 -4
- package/src/utils/ncbiOrthologs.test.ts +20 -0
- package/src/utils/ncbiOrthologs.ts +26 -28
- package/src/utils/ncbiTaxonomy.ts +17 -20
- package/src/utils/taxonomyNames.test.ts +41 -0
- package/src/utils/taxonomyNames.ts +33 -19
- package/src/utils/unirefHomologs.test.ts +11 -1
- package/src/utils/unirefHomologs.ts +2 -2
- package/src/version.ts +1 -1
- package/dist/LaunchMsaView/components/BlastQuery/blastLaunchView.d.ts +0 -16
- package/dist/LaunchMsaView/components/BlastQuery/blastLaunchView.js +0 -31
- package/dist/LaunchMsaView/components/ManualMSALoader/launchView.d.ts +0 -16
- package/dist/LaunchMsaView/components/ManualMSALoader/launchView.js +0 -16
- package/dist/LaunchMsaView/components/OrthologQuery/orthologLaunchView.d.ts +0 -9
- package/dist/LaunchMsaView/components/OrthologQuery/orthologLaunchView.js +0 -15
- package/dist/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.d.ts +0 -11
- package/dist/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.js +0 -21
- package/dist/LaunchMsaView/components/geneticCodes.d.ts +0 -15
- package/dist/LaunchMsaView/components/geneticCodes.js +0 -227
- package/src/LaunchMsaView/components/BlastQuery/blastLaunchView.ts +0 -59
- package/src/LaunchMsaView/components/ManualMSALoader/launchView.ts +0 -43
- package/src/LaunchMsaView/components/OrthologQuery/orthologLaunchView.ts +0 -31
- package/src/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.ts +0 -38
- package/src/LaunchMsaView/components/geneticCodes.ts +0 -298
package/README.md
CHANGED
|
@@ -14,6 +14,14 @@ MSAView plugin running in JBrowse 2
|
|
|
14
14
|
|
|
15
15
|
## Demo
|
|
16
16
|
|
|
17
|
+
[p53 across vertebrates, linked to the genome and the structure](https://jbrowse.org/code/jb2/main/?config=https://jbrowse.org/ucsc/hg38/config.json&session=spec-{%22views%22:[{%22type%22:%22LinearGenomeView%22,%22id%22:%22lgv1%22,%22assembly%22:%22hg38%22,%22loc%22:%22chr17:7,661,779-7,687,538%22,%22tracks%22:[%22hg38-ncbiRefSeqSelect%22,%22hg38-clinvarMain%22]},{%22type%22:%22MsaView%22,%22displayName%22:%22p53%20across%20vertebrates%22,%22msaFileLocation%22:{%22uri%22:%22https://gmod.org/JBrowseMSA/demo/data/p53/p53-vertebrates.afa%22},%22treeFileLocation%22:{%22uri%22:%22https://gmod.org/JBrowseMSA/demo/data/p53/p53-vertebrates.nh%22},%22querySeqName%22:%22Human%22,%22relativeTo%22:%22Human%22,%22connectedViewId%22:%22lgv1%22,%22connectedTranscript%22:%22NM_000546.6%22,%22placement%22:%22splitRight%22,%22colorSchemeName%22:%22clustalx_protein_dynamic%22,%22highlights%22:[{%22row%22:%22Human%22,%22start%22:102,%22end%22:292,%22label%22:%22DNA-binding%22,%22color%22:%22rgba%28255,140,0,0.15%29%22},{%22row%22:%22Human%22,%22start%22:175,%22end%22:175,%22label%22:%22R175%22},{%22row%22:%22Human%22,%22start%22:245,%22end%22:245,%22label%22:%22G245%22},{%22row%22:%22Human%22,%22start%22:248,%22end%22:248,%22label%22:%22R248%22},{%22row%22:%22Human%22,%22start%22:249,%22end%22:249,%22label%22:%22R249%22},{%22row%22:%22Human%22,%22start%22:273,%22end%22:273,%22label%22:%22R273%22},{%22row%22:%22Human%22,%22start%22:282,%22end%22:282,%22label%22:%22R282%22}],%22columnTracks%22:[{%22id%22:%22clinvar%22,%22name%22:%22ClinVar%20pathogenic%20missense%22,%22kind%22:%22bar%22,%22row%22:%22Human%22,%22color%22:%22%23c0392b%22,%22height%22:60,%22max%22:8,%22values%22:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,2,4,3,0,6,0,0,0,0,0,0,0,0,0,0,1,2,1,5,0,0,2,2,3,1,1,4,0,0,2,0,0,2,0,3,0,0,0,1,0,0,0,6,2,0,0,1,1,3,6,2,0,1,0,2,1,1,0,0,2,0,0,2,1,3,0,3,3,1,3,5,1,3,0,0,0,0,0,0,0,0,1,0,0,4,3,1,1,1,0,1,0,0,0,0,0,3,0,0,0,0,0,0,0,3,2,1,1,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,3,0,4,0,2,4,6,2,3,5,2,0,4,5,4,1,6,2,1,2,0,1,3,0,0,0,2,1,0,0,0,0,0,2,3,3,0,1,4,1,3,6,0,2,1,1,3,0,3,8,3,1,0,2,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,5,0,0,0,1,1,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},{%22id%22:%22alphamissense%22,%22name%22:%22AlphaMissense%20mean%20%28x100%29%22,%22kind%22:%22bar%22,%22row%22:%22Human%22,%22color%22:%22%231565c0%22,%22height%22:60,%22max%22:100,%22values%22:[49,27,19,11,12,14,18,10,12,14,28,17,40,57,73,65,65,68,95,29,30,72,95,21,24,60,39,21,18,17,18,16,17,12,11,13,14,13,14,21,22,20,17,20,16,16,15,14,17,17,15,13,37,29,11,19,16,11,11,12,14,20,14,12,11,20,13,19,15,14,12,13,15,17,14,17,15,19,20,17,15,15,22,22,19,22,20,24,17,23,67,41,46,66,63,37,90,98,63,35,36,20,76,15,99,13,58,48,98,26,81,57,97,43,17,64,87,68,90,98,96,92,73,81,98,91,95,23,13,81,56,97,84,97,98,87,86,81,91,84,94,93,89,66,81,57,77,26,20,13,90,69,17,52,70,49,91,98,87,88,94,87,95,89,48,54,52,76,76,68,92,87,98,78,99,100,98,97,100,96,85,50,38,52,32,74,52,32,83,87,71,47,99,95,89,95,91,96,95,81,20,25,69,48,98,24,64,93,17,23,84,56,99,92,91,93,70,89,76,91,77,27,92,87,57,92,58,35,54,68,75,87,85,87,74,93,96,100,95,98,99,100,94,100,100,98,97,100,99,93,93,59,91,91,87,92,93,99,87,22,21,94,24,76,83,99,98,36,61,97,93,93,99,95,100,97,100,100,99,100,100,97,84,60,98,96,47,62,13,18,56,34,17,17,11,9,9,16,11,15,13,18,20,17,81,75,26,26,23,13,12,14,16,18,18,14,15,15,47,54,46,19,13,34,24,50,56,88,36,87,48,93,63,98,73,40,89,90,45,60,88,51,36,81,77,55,79,75,87,31,54,67,23,18,17,16,25,22,13,15,15,16,20,18,15,20,25,13,15,56,21,47,45,21,16,16,15,21,16,20,66,47,13,26,19,66,13,28,18,16,47,54,66]},{%22id%22:%22mavedb%22,%22name%22:%22MaveDB%20nutlin-3,%20p53WT%22,%22kind%22:%22bar%22,%22row%22:%22Human%22,%22color%22:%22%232e7d32%22,%22height%22:60,%22max%22:2,%22values%22:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.6,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0.2,0.4,0,0,0,0,0.1,0,0.8,0,0.7,0.3,1.6,0.1,1.4,0.1,1.3,0,0,0,0.1,0,0.1,0.5,0.2,0.4,0.4,0.8,0.8,1.4,1.5,0.1,0.1,1.2,1,1.7,1.1,1.4,1.3,0.8,0.5,0.5,0.8,0.4,1.2,0.4,1.4,0.7,1.2,0.6,1.1,0.5,0.4,0.6,1.5,1.3,0,0.7,1.3,0.3,1.4,1,1.4,0.8,1.4,0.8,1.8,0.8,0.3,0,0.2,0.8,0.4,0,0.6,0.7,1.7,1,1.2,2,1.1,0.6,2,0.8,0.7,0.3,0.1,0.4,0.2,0.3,0.1,0.1,0.5,0.8,0.1,0.1,1.4,1.6,1.4,0.7,1.3,0.1,0.1,0,0,0,0.9,0.3,1.8,0,0,1,0,0.1,0.9,0.7,1.2,1.1,1.5,1.4,0.6,1.3,0.5,1.5,0.4,0.3,0.6,0.3,0.1,0.4,0.3,0.2,0.7,0.5,0.6,1.4,0.5,1.4,0.6,1.7,1.1,1.9,0.8,1.3,1.3,1.7,0.9,1.7,2.2,2,0.9,1.5,2.1,1,1.4,0.3,1.3,1.2,1.4,0.8,1.4,1.4,0.9,0.5,0.5,0.7,0.5,0.5,0.8,1.6,1,0.9,0.8,1.5,1.3,1.5,1.5,1.7,1.8,0.5,0.4,2,0,0.9,0.6,1,0,0,1,1.8,0,0.1,0.2,0.1,0.2,0,0.1,0.4,0.4,0.3,0.4,0.6,0.4,0.6,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}],%22region%22:{%22row%22:%22Human%22,%22start%22:170,%22end%22:290}},{%22type%22:%22ProteinView%22,%22uniprotId%22:%22P04637%22,%22transcriptId%22:%22NM_000546.6%22,%22connectedViewId%22:%22lgv1%22,%22connectedView%22:{%22assembly%22:%22hg38%22,%22loc%22:%22chr17:7,661,779-7,687,538%22,%22tracks%22:[%22hg38-ncbiRefSeqSelect%22]}}]}):
|
|
18
|
+
TP53 in hg38 with ClinVar, a vertebrate p53 alignment carrying ClinVar,
|
|
19
|
+
AlphaMissense and MaveDB per-residue tracks, and the AlphaFold model of P04637.
|
|
20
|
+
Hovering a codon, a column or a residue lights the other two views. See
|
|
21
|
+
[DEVELOPERS.md](DEVELOPERS.md#demo-p53-variant-evidence) for how the link is
|
|
22
|
+
built.
|
|
23
|
+
|
|
24
|
+
An older shared session:
|
|
17
25
|
https://jbrowse.org/code/jb2/main/index.html?config=https://unpkg.com/jbrowse-plugin-msaview/dist/config.json&session=share-BVmmEYAoAv&password=SuQaN
|
|
18
26
|
|
|
19
27
|
## Features
|
|
@@ -3,9 +3,9 @@ import { getSession } from '@jbrowse/core/util';
|
|
|
3
3
|
import { isMsaView } from '../MsaViewPanel/model';
|
|
4
4
|
import HighlightComponents from './HighlightComponents';
|
|
5
5
|
export default function AddHighlightComponentsModelF(pluginManager) {
|
|
6
|
-
pluginManager.addToExtensionPoint(
|
|
7
|
-
// @ts-expect-error
|
|
8
|
-
(rest, { model }) => {
|
|
6
|
+
pluginManager.addToExtensionPoint(
|
|
7
|
+
// @ts-expect-error v4 hosts have no contributeToExtensionPoint
|
|
8
|
+
'LinearGenomeView-TracksContainerComponent', (rest, { model }) => {
|
|
9
9
|
// Quick check: don't add any components if no MSA view exists
|
|
10
10
|
const { views } = getSession(model);
|
|
11
11
|
const hasMsaView = views.some(v => isMsaView(v) && v.connectedViewId === model.id);
|
|
@@ -3,8 +3,14 @@ import type { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAda
|
|
|
3
3
|
export default class BgzipFastaMsaAdapter extends BaseAdapter {
|
|
4
4
|
configureP: Promise<BaseFeatureDataAdapter> | undefined;
|
|
5
5
|
refNamesP: Promise<string[]> | undefined;
|
|
6
|
-
configurePre(): Promise<BaseFeatureDataAdapter
|
|
7
|
-
|
|
6
|
+
configurePre(): Promise<BaseFeatureDataAdapter<import("@jbrowse/mobx-state-tree").ModelInstanceTypeProps<Record<string, any>> & {
|
|
7
|
+
setSubschema(slotName: string, data: Record<string, unknown>): any;
|
|
8
|
+
setSlot(slotName: string, value: unknown): void;
|
|
9
|
+
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>>>;
|
|
10
|
+
configure(): Promise<BaseFeatureDataAdapter<import("@jbrowse/mobx-state-tree").ModelInstanceTypeProps<Record<string, any>> & {
|
|
11
|
+
setSubschema(slotName: string, data: Record<string, unknown>): any;
|
|
12
|
+
setSlot(slotName: string, value: unknown): void;
|
|
13
|
+
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>>>;
|
|
8
14
|
getMSARefs(): Promise<string[]>;
|
|
9
15
|
getMsaRegex(): RegExp;
|
|
10
16
|
refNameToMsaId(refName: string): string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
2
2
|
export default function configSchemaF(pluginManager: PluginManager): import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
3
|
-
msaRegex: {
|
|
4
|
-
type: string;
|
|
5
|
-
defaultValue:
|
|
3
|
+
readonly msaRegex: {
|
|
4
|
+
readonly type: "string";
|
|
5
|
+
readonly defaultValue: "_";
|
|
6
6
|
};
|
|
7
7
|
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<import("@jbrowse/core/configuration").AnyConfigurationSchemaType, undefined>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { SimpleFeature } from '@jbrowse/core/util';
|
|
2
|
+
import { genomeToTranscriptSeqMapping } from 'g2p_mapper';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
import { transcriptPosToVisibleCol } from '../MsaViewPanel/util';
|
|
5
|
+
import { getProteinSequenceFromFeature } from './components/calculateProteinSequence';
|
|
6
|
+
import { findQueryRow } from './detectQueryRow';
|
|
7
|
+
import { cleanProteinSequence } from './util';
|
|
8
|
+
describe('cleanProteinSequence', () => {
|
|
9
|
+
test('drops the stop and a trailing partial codon', () => {
|
|
10
|
+
expect(cleanProteinSequence('MAWK*')).toBe('MAWK');
|
|
11
|
+
expect(cleanProteinSequence('MAWK&')).toBe('MAWK');
|
|
12
|
+
});
|
|
13
|
+
test('keeps a residue for every other codon', () => {
|
|
14
|
+
expect(cleanProteinSequence('&MAWK*')).toBe('XMAWK');
|
|
15
|
+
expect(cleanProteinSequence('MA*WK*')).toBe('MAXWK');
|
|
16
|
+
expect(cleanProteinSequence('MA&WK')).toBe('MAXWK');
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
// what the genome view hovers is a codon, and what lights is the query row's
|
|
20
|
+
// residue at g2p's number for that codon, so the two have to count alike
|
|
21
|
+
describe('a launched query row read through g2p', () => {
|
|
22
|
+
function rowResidueUnder(genomePos, json) {
|
|
23
|
+
const seq = json.seq;
|
|
24
|
+
const feature = new SimpleFeature(json);
|
|
25
|
+
const row = cleanProteinSequence(getProteinSequenceFromFeature({ seq, feature }));
|
|
26
|
+
const { g2p } = genomeToTranscriptSeqMapping(feature.toJSON());
|
|
27
|
+
const col = transcriptPosToVisibleCol({
|
|
28
|
+
querySeqName: 'QUERY',
|
|
29
|
+
querySeqOffset: 0,
|
|
30
|
+
seqPosToVisibleCol: (_, p) => (p < row.length ? p : row.length),
|
|
31
|
+
visibleColToSeqPos: (_, c) => (c < row.length ? c : undefined),
|
|
32
|
+
}, g2p[genomePos]);
|
|
33
|
+
return row[col];
|
|
34
|
+
}
|
|
35
|
+
function transcript(seq, cds) {
|
|
36
|
+
return {
|
|
37
|
+
uniqueId: 't1',
|
|
38
|
+
refName: 'chr1',
|
|
39
|
+
start: 0,
|
|
40
|
+
end: seq.length,
|
|
41
|
+
strand: 1,
|
|
42
|
+
type: 'mRNA',
|
|
43
|
+
seq,
|
|
44
|
+
subfeatures: [
|
|
45
|
+
{ uniqueId: 'c1', refName: 'chr1', start: 0, end: seq.length, ...cds },
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
test('after a partial first codon', () => {
|
|
50
|
+
// G | ATG GCC TGG AAA TAA: base 4 opens GCC, alanine
|
|
51
|
+
const json = transcript('GATGGCCTGGAAATAA', { type: 'CDS', phase: 1 });
|
|
52
|
+
expect(rowResidueUnder(4, json)).toBe('A');
|
|
53
|
+
expect(rowResidueUnder(10, json)).toBe('K');
|
|
54
|
+
});
|
|
55
|
+
test('after an internal stop', () => {
|
|
56
|
+
// ATG TGA GCC TGG TAA: a selenocysteine GENCODE does not annotate
|
|
57
|
+
const json = transcript('ATGTGAGCCTGGTAA', { type: 'CDS' });
|
|
58
|
+
expect(rowResidueUnder(6, json)).toBe('A');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('query row detection', () => {
|
|
62
|
+
test('matches a row a search launch built from a partial transcript', () => {
|
|
63
|
+
const msa = '>QUERY\nXMAWK\n>other\nMAWR-';
|
|
64
|
+
expect(findQueryRow(msa, '&MAWK*').match).toMatchObject({
|
|
65
|
+
name: 'QUERY',
|
|
66
|
+
quality: 'exact',
|
|
67
|
+
offset: 0,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
test('still places a row that starts at the first whole codon', () => {
|
|
71
|
+
const msa = '>Query_1\nMAWK\n>other\nMAWR';
|
|
72
|
+
expect(findQueryRow(msa, '&MAWK*').match).toMatchObject({
|
|
73
|
+
name: 'Query_1',
|
|
74
|
+
offset: 1,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Feature } from '@jbrowse/core/util';
|
|
2
|
+
export declare function isGeneLikeType(type: unknown): boolean;
|
|
3
|
+
export declare function isCodingFeature(feature: Feature): boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Whether the feature is known not to code for anything.
|
|
6
|
+
*
|
|
7
|
+
* Not simply `!isCodingFeature`: a feature that arrived with no subfeatures at
|
|
8
|
+
* all says nothing either way, and a host is free to hand one over that way.
|
|
9
|
+
* Reading that as "no protein here" takes the menu item off a perfectly
|
|
10
|
+
* ordinary gene, silently, which is worse than opening a dialog that then has
|
|
11
|
+
* nothing to translate.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isKnownNonCoding(feature: Feature): boolean;
|
|
14
|
+
export declare function geneLikeRoot(feature: Feature): Feature;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copied from @jbrowse/core's featureTypes rather than imported: the barrel
|
|
2
|
+
// only exports it from v5, and a bundle resolving it on a v4 host reads
|
|
3
|
+
// undefined.
|
|
4
|
+
const GENE_LIKE_TYPE = /gene(_segment)?$|rna$|transcript/;
|
|
5
|
+
// `unknown` rather than `string | undefined`, because the type comes off a
|
|
6
|
+
// host's hit-test item and nothing here built it.
|
|
7
|
+
export function isGeneLikeType(type) {
|
|
8
|
+
return typeof type === 'string' && GENE_LIKE_TYPE.test(type.toLowerCase());
|
|
9
|
+
}
|
|
10
|
+
function isCDS(feature) {
|
|
11
|
+
return feature.get('type')?.toLowerCase() === 'cds';
|
|
12
|
+
}
|
|
13
|
+
// The feature itself counts: a viral polyprotein hangs its cleavage products
|
|
14
|
+
// off its CDS rather than off further CDSs.
|
|
15
|
+
export function isCodingFeature(feature) {
|
|
16
|
+
return isCDS(feature) || !!feature.get('subfeatures')?.some(isCodingFeature);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Whether the feature is known not to code for anything.
|
|
20
|
+
*
|
|
21
|
+
* Not simply `!isCodingFeature`: a feature that arrived with no subfeatures at
|
|
22
|
+
* all says nothing either way, and a host is free to hand one over that way.
|
|
23
|
+
* Reading that as "no protein here" takes the menu item off a perfectly
|
|
24
|
+
* ordinary gene, silently, which is worse than opening a dialog that then has
|
|
25
|
+
* nothing to translate.
|
|
26
|
+
*/
|
|
27
|
+
export function isKnownNonCoding(feature) {
|
|
28
|
+
return !!feature.get('subfeatures')?.length && !isCodingFeature(feature);
|
|
29
|
+
}
|
|
30
|
+
// The outermost gene-like ancestor, so a click on an isoform opens the dialog
|
|
31
|
+
// on the gene with every transcript to choose from, as the canvas host does.
|
|
32
|
+
export function geneLikeRoot(feature) {
|
|
33
|
+
let root = feature;
|
|
34
|
+
for (let parent = root.parent?.(); parent && isGeneLikeType(parent.get('type')); parent = parent.parent?.()) {
|
|
35
|
+
root = parent;
|
|
36
|
+
}
|
|
37
|
+
return root;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { SimpleFeature } from '@jbrowse/core/util';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { geneLikeRoot, isCodingFeature, isGeneLikeType, isKnownNonCoding, } from './codingFeature';
|
|
4
|
+
function feature(type, subfeatures = []) {
|
|
5
|
+
return new SimpleFeature({
|
|
6
|
+
uniqueId: `${type}-${Math.random()}`,
|
|
7
|
+
refName: 'chr1',
|
|
8
|
+
start: 0,
|
|
9
|
+
end: 100,
|
|
10
|
+
type,
|
|
11
|
+
subfeatures: subfeatures.map(s => s.toJSON()),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
describe('isGeneLikeType', () => {
|
|
15
|
+
it('accepts the SO spellings of gene, transcript and RNA', () => {
|
|
16
|
+
for (const t of [
|
|
17
|
+
'gene',
|
|
18
|
+
'mRNA',
|
|
19
|
+
'transcript',
|
|
20
|
+
'ncRNA_gene',
|
|
21
|
+
'protein_coding_gene',
|
|
22
|
+
'V_gene_segment',
|
|
23
|
+
'primary_transcript',
|
|
24
|
+
'pseudogenic_transcript',
|
|
25
|
+
'lnc_RNA',
|
|
26
|
+
]) {
|
|
27
|
+
expect(isGeneLikeType(t)).toBe(true);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
it('rejects regions, matches and CDS', () => {
|
|
31
|
+
for (const t of ['intergenic_region', 'cDNA_match', 'CDS', 'exon']) {
|
|
32
|
+
expect(isGeneLikeType(t)).toBe(false);
|
|
33
|
+
}
|
|
34
|
+
expect(isGeneLikeType(undefined)).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('isCodingFeature', () => {
|
|
38
|
+
it('finds a CDS anywhere below the feature', () => {
|
|
39
|
+
const gene = feature('gene', [
|
|
40
|
+
feature('mRNA', [feature('exon'), feature('CDS')]),
|
|
41
|
+
]);
|
|
42
|
+
expect(isCodingFeature(gene)).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
it('is false for a transcript with exons only', () => {
|
|
45
|
+
const lnc = feature('lnc_RNA', [feature('exon'), feature('exon')]);
|
|
46
|
+
expect(isCodingFeature(lnc)).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
it('counts the feature itself', () => {
|
|
49
|
+
expect(isCodingFeature(feature('CDS'))).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('isKnownNonCoding', () => {
|
|
53
|
+
it('is true for a transcript whose subfeatures are all exons', () => {
|
|
54
|
+
expect(isKnownNonCoding(feature('lnc_RNA', [feature('exon'), feature('exon')]))).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
// a host is free to hand over a bare record, and reading that as "no protein
|
|
57
|
+
// here" takes the menu item off an ordinary gene without a word
|
|
58
|
+
it('is false for a feature that arrived with no subfeatures at all', () => {
|
|
59
|
+
expect(isKnownNonCoding(feature('gene'))).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
it('is false when a CDS is somewhere below', () => {
|
|
62
|
+
expect(isKnownNonCoding(feature('gene', [feature('mRNA', [feature('CDS')])]))).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('geneLikeRoot', () => {
|
|
66
|
+
it('climbs from an isoform to its gene', () => {
|
|
67
|
+
const gene = feature('gene', [feature('mRNA', [feature('CDS')])]);
|
|
68
|
+
const mrna = gene.get('subfeatures')[0];
|
|
69
|
+
expect(geneLikeRoot(mrna)).toBe(gene);
|
|
70
|
+
});
|
|
71
|
+
it('stays put with no gene-like parent', () => {
|
|
72
|
+
const mrna = feature('mRNA', [feature('CDS')]);
|
|
73
|
+
expect(geneLikeRoot(mrna)).toBe(mrna);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { AbstractTrackModel, Feature } from '@jbrowse/core/util';
|
|
3
|
-
declare const BlastAutomaticPanel: ({ handleClose, feature, model, children, }: {
|
|
3
|
+
declare const BlastAutomaticPanel: ({ handleClose, feature, model, children, preferredTranscriptId, }: {
|
|
4
4
|
model: AbstractTrackModel;
|
|
5
5
|
feature: Feature;
|
|
6
6
|
handleClose: () => void;
|
|
7
7
|
children: React.ReactNode;
|
|
8
|
+
/** the isoform the user right-clicked, preselected in the picker */
|
|
9
|
+
preferredTranscriptId?: string;
|
|
8
10
|
}) => React.JSX.Element;
|
|
9
11
|
export default BlastAutomaticPanel;
|
|
@@ -6,24 +6,24 @@ import { makeStyles } from 'tss-react/mui';
|
|
|
6
6
|
import TextField2 from '../../../components/TextField2';
|
|
7
7
|
import { getBlastViewTitle, getGeneIdentifiers, getLinearGenomeView, } from '../../util';
|
|
8
8
|
import LaunchPanelContent from '../LaunchPanelContent';
|
|
9
|
+
import SequenceStatusMessage from '../SequenceStatus';
|
|
9
10
|
import SubmitCancelActions from '../SubmitCancelActions';
|
|
10
11
|
import TranscriptSelector from '../TranscriptSelector';
|
|
12
|
+
import { builtAlignmentLook, launchConnectedView, useLaunchSubmit, } from '../launchConnectedView';
|
|
11
13
|
import { useTranscriptSelection } from '../useTranscriptSelection';
|
|
12
14
|
import CachedBlastResults from './CachedBlastResults';
|
|
13
15
|
import MsaAlgorithmSelect from './MsaAlgorithmSelect';
|
|
14
|
-
import {
|
|
15
|
-
import { databaseOptionsFor, defaultMaxHits, defaultSearchFor, searchPrograms, } from './consts';
|
|
16
|
+
import { databaseLabel, databaseOptionsFor, defaultMaxHits, defaultSearchFor, searchProgramLabels, searchPrograms, } from './consts';
|
|
16
17
|
import { useStoredMsaAlgorithm, useStoredSearchChoice, } from './searchChoiceStorage';
|
|
17
18
|
import { useCachedBlastResults } from './useCachedBlastResults';
|
|
18
19
|
const useStyles = makeStyles()({
|
|
19
20
|
selectField: {
|
|
20
21
|
width: 150,
|
|
21
22
|
},
|
|
22
|
-
// wider than the rest because the
|
|
23
|
-
//
|
|
24
|
-
// `uniprotkb_swis…`, which does not distinguish it from `uniprotkb_trembl`
|
|
23
|
+
// wider than the rest because the collection names are what the user came to
|
|
24
|
+
// read, and truncating them does not distinguish Swiss-Prot from TrEMBL
|
|
25
25
|
databaseField: {
|
|
26
|
-
width:
|
|
26
|
+
width: 260,
|
|
27
27
|
},
|
|
28
28
|
cachedResultsAccordion: {
|
|
29
29
|
marginTop: 20,
|
|
@@ -32,10 +32,10 @@ const useStyles = makeStyles()({
|
|
|
32
32
|
marginTop: 20,
|
|
33
33
|
},
|
|
34
34
|
});
|
|
35
|
-
const BlastAutomaticPanel = observer(function ({ handleClose, feature, model, children, }) {
|
|
35
|
+
const BlastAutomaticPanel = observer(function ({ handleClose, feature, model, children, preferredTranscriptId, }) {
|
|
36
36
|
const { classes } = useStyles();
|
|
37
37
|
const view = getLinearGenomeView(model);
|
|
38
|
-
const
|
|
38
|
+
const { launchError, submit } = useLaunchSubmit(handleClose);
|
|
39
39
|
// one piece of state, not two: a program and a database that program does not
|
|
40
40
|
// have is a 400 from EBI minutes after Submit, and holding them apart is what
|
|
41
41
|
// would let them drift into that
|
|
@@ -47,9 +47,13 @@ const BlastAutomaticPanel = observer(function ({ handleClose, feature, model, ch
|
|
|
47
47
|
const isPhmmer = search.program === 'phmmer';
|
|
48
48
|
const geneIds = useMemo(() => getGeneIdentifiers(feature), [feature]);
|
|
49
49
|
const { results: cachedResults, error: cachedResultsError } = useCachedBlastResults(geneIds);
|
|
50
|
-
const transcriptSelection = useTranscriptSelection({
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
const transcriptSelection = useTranscriptSelection({
|
|
51
|
+
feature,
|
|
52
|
+
view,
|
|
53
|
+
preferredTranscriptId,
|
|
54
|
+
});
|
|
55
|
+
const { selectedTranscript, proteinSequence, sequenceStatus } = transcriptSelection;
|
|
56
|
+
const e = transcriptSelection.error ?? launchError ?? cachedResultsError;
|
|
53
57
|
return (React.createElement(React.Fragment, null,
|
|
54
58
|
React.createElement(LaunchPanelContent, { error: e },
|
|
55
59
|
children,
|
|
@@ -58,69 +62,57 @@ const BlastAutomaticPanel = observer(function ({ handleClose, feature, model, ch
|
|
|
58
62
|
// program replaces the database rather than keeping a name the new
|
|
59
63
|
// one has never heard of
|
|
60
64
|
setSearch(defaultSearchFor(event.target.value));
|
|
61
|
-
} }, searchPrograms.map(val => (React.createElement(MenuItem, { value: val, key: val }, val)))),
|
|
65
|
+
} }, searchPrograms.map(val => (React.createElement(MenuItem, { value: val, key: val }, searchProgramLabels[val])))),
|
|
62
66
|
React.createElement(TextField2, { variant: "outlined", label: "Database", className: classes.databaseField, select: true, value: search.database, onChange: event => {
|
|
63
67
|
setSearch({
|
|
64
68
|
program: search.program,
|
|
65
69
|
database: event.target.value,
|
|
66
70
|
});
|
|
67
|
-
} }, databaseOptionsFor(search.program).map(val => (React.createElement(MenuItem, { value: val, key: val }, val)))),
|
|
71
|
+
} }, databaseOptionsFor(search.program).map(val => (React.createElement(MenuItem, { value: val, key: val }, databaseLabel(val))))),
|
|
68
72
|
isPhmmer ? null : (React.createElement(MsaAlgorithmSelect, { className: classes.selectField, value: selectedMsaAlgorithm, onChange: setSelectedMsaAlgorithm })),
|
|
69
73
|
React.createElement(TextField2, { variant: "outlined", label: "Hits", className: classes.selectField, type: "number", value: maxHits, onChange: event => {
|
|
70
74
|
setMaxHits(event.target.value);
|
|
71
75
|
}, error: !hitCountValid, helperText: "best-scoring sequences to keep" }),
|
|
72
76
|
React.createElement(TranscriptSelector, { feature: feature, ...transcriptSelection }),
|
|
73
|
-
React.createElement(Typography, { className: classes.infoText },
|
|
77
|
+
React.createElement(Typography, { variant: "body2", className: classes.infoText },
|
|
74
78
|
isPhmmer
|
|
75
|
-
?
|
|
76
|
-
|
|
77
|
-
directly — nothing is realigned afterwards. The tree is then built
|
|
78
|
-
from it in the browser. A hit matching the query in more than one
|
|
79
|
-
place appears once per matched region. rp15 spreads the hits
|
|
80
|
-
across all of life; swissprot keeps to the curated set.`
|
|
81
|
-
: `This panel will automatically submit a blastp query to EBI, which
|
|
82
|
-
searches UniProtKB. swissprot returns curated sequences that align
|
|
83
|
-
more cleanly than the many near-identical entries a TrEMBL search
|
|
84
|
-
brings back. After completion, all the hits will be run through
|
|
85
|
-
the chosen aligner; "in browser" needs no second EBI job.`,
|
|
79
|
+
? 'phmmer aligns the hits as it finds them, so nothing is realigned afterwards.'
|
|
80
|
+
: 'The hits come back from EBI and are then run through the chosen aligner.',
|
|
86
81
|
' ',
|
|
87
|
-
"EBI
|
|
82
|
+
"The EBI queue is the wait, and it runs from seconds to many minutes."),
|
|
88
83
|
cachedResults.length > 0 ? (React.createElement(Accordion, { className: classes.cachedResultsAccordion },
|
|
89
84
|
React.createElement(AccordionSummary, { expandIcon: React.createElement(ExpandMoreIcon, null) },
|
|
90
85
|
React.createElement(Typography, null, "Previous BLAST Results")),
|
|
91
86
|
React.createElement(AccordionDetails, null,
|
|
92
87
|
React.createElement(CachedBlastResults, { model: model, handleClose: handleClose, feature: feature })))) : null),
|
|
93
|
-
React.createElement(SubmitCancelActions, { model: model, submitDisabled: !proteinSequence || !hitCountValid, onSubmit:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
88
|
+
React.createElement(SubmitCancelActions, { model: model, hint: React.createElement(SequenceStatusMessage, { status: sequenceStatus }), submitDisabled: !proteinSequence || !hitCountValid, onSubmit: placement => {
|
|
89
|
+
if (selectedTranscript) {
|
|
90
|
+
const blastParams = search.program === 'phmmer'
|
|
91
|
+
? {
|
|
92
|
+
searchProgram: 'phmmer',
|
|
93
|
+
blastDatabase: search.database,
|
|
94
|
+
maxHits: hitCount,
|
|
95
|
+
selectedTranscript: selectedTranscript.toJSON(),
|
|
96
|
+
proteinSequence,
|
|
97
|
+
}
|
|
98
|
+
: {
|
|
99
|
+
searchProgram: 'blastp',
|
|
100
|
+
blastDatabase: search.database,
|
|
101
|
+
msaAlgorithm: selectedMsaAlgorithm,
|
|
102
|
+
maxHits: hitCount,
|
|
103
|
+
selectedTranscript: selectedTranscript.toJSON(),
|
|
104
|
+
proteinSequence,
|
|
105
|
+
};
|
|
106
|
+
submit(() => {
|
|
107
|
+
launchConnectedView({
|
|
99
108
|
view,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
maxHits: hitCount,
|
|
106
|
-
selectedTranscript: selectedTranscript.toJSON(),
|
|
107
|
-
proteinSequence,
|
|
108
|
-
}
|
|
109
|
-
: {
|
|
110
|
-
searchProgram: 'blastp',
|
|
111
|
-
blastDatabase: search.database,
|
|
112
|
-
msaAlgorithm: selectedMsaAlgorithm,
|
|
113
|
-
maxHits: hitCount,
|
|
114
|
-
selectedTranscript: selectedTranscript.toJSON(),
|
|
115
|
-
proteinSequence,
|
|
116
|
-
},
|
|
109
|
+
feature: selectedTranscript,
|
|
110
|
+
placement,
|
|
111
|
+
displayName: getBlastViewTitle(feature, selectedTranscript),
|
|
112
|
+
...builtAlignmentLook,
|
|
113
|
+
blastParams,
|
|
117
114
|
});
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
catch (e) {
|
|
122
|
-
console.error(e);
|
|
123
|
-
setLaunchViewError(e);
|
|
115
|
+
});
|
|
124
116
|
}
|
|
125
117
|
}, onCancel: handleClose })));
|
|
126
118
|
});
|
|
@@ -11,10 +11,12 @@ import type { AbstractTrackModel, Feature } from '@jbrowse/core/util';
|
|
|
11
11
|
* button -- leaving them to find the Manual upload tab, re-pick the transcript
|
|
12
12
|
* they had already chosen here, and hand-type the row name.
|
|
13
13
|
*/
|
|
14
|
-
declare const BlastManualPanel: ({ handleClose, feature, model, children, }: {
|
|
14
|
+
declare const BlastManualPanel: ({ handleClose, feature, model, children, preferredTranscriptId, }: {
|
|
15
15
|
children: React.ReactNode;
|
|
16
16
|
model: AbstractTrackModel;
|
|
17
17
|
feature: Feature;
|
|
18
18
|
handleClose: () => void;
|
|
19
|
+
/** the isoform the user right-clicked, preselected in the picker */
|
|
20
|
+
preferredTranscriptId?: string;
|
|
19
21
|
}) => React.JSX.Element;
|
|
20
22
|
export default BlastManualPanel;
|
|
@@ -8,10 +8,10 @@ import TextField2 from '../../../components/TextField2';
|
|
|
8
8
|
import { useQueryRowName } from '../../useQueryRowName';
|
|
9
9
|
import { cleanProteinSequence, getGeneDisplayName, getLinearGenomeView, } from '../../util';
|
|
10
10
|
import LaunchPanelContent from '../LaunchPanelContent';
|
|
11
|
-
import { launchView } from '../ManualMSALoader/launchView';
|
|
12
11
|
import QueryRowSelector from '../QueryRowSelector';
|
|
13
12
|
import SubmitCancelActions from '../SubmitCancelActions';
|
|
14
13
|
import TranscriptSelector from '../TranscriptSelector';
|
|
14
|
+
import { launchConnectedView, useLaunchSubmit } from '../launchConnectedView';
|
|
15
15
|
import { useTranscriptSelection } from '../useTranscriptSelection';
|
|
16
16
|
import { BASE_BLAST_URL } from './consts';
|
|
17
17
|
const useStyles = makeStyles()({
|
|
@@ -43,13 +43,17 @@ const useStyles = makeStyles()({
|
|
|
43
43
|
* button -- leaving them to find the Manual upload tab, re-pick the transcript
|
|
44
44
|
* they had already chosen here, and hand-type the row name.
|
|
45
45
|
*/
|
|
46
|
-
const BlastManualPanel = observer(function ({ handleClose, feature, model, children, }) {
|
|
46
|
+
const BlastManualPanel = observer(function ({ handleClose, feature, model, children, preferredTranscriptId, }) {
|
|
47
47
|
const { classes } = useStyles();
|
|
48
48
|
const view = getLinearGenomeView(model);
|
|
49
|
-
const
|
|
49
|
+
const { launchError, submit } = useLaunchSubmit(handleClose);
|
|
50
50
|
const [msaText, setMsaText] = useState('');
|
|
51
51
|
const [treeText, setTreeText] = useState('');
|
|
52
|
-
const transcriptSelection = useTranscriptSelection({
|
|
52
|
+
const transcriptSelection = useTranscriptSelection({
|
|
53
|
+
feature,
|
|
54
|
+
view,
|
|
55
|
+
preferredTranscriptId,
|
|
56
|
+
});
|
|
53
57
|
const { proteinSequence, selectedTranscript, error } = transcriptSelection;
|
|
54
58
|
const queryRow = useQueryRowName(msaText, proteinSequence);
|
|
55
59
|
const s2 = cleanProteinSequence(proteinSequence);
|
|
@@ -58,7 +62,7 @@ const BlastManualPanel = observer(function ({ handleClose, feature, model, child
|
|
|
58
62
|
const link = `${BASE_BLAST_URL}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${s2}`;
|
|
59
63
|
const link2 = `${BASE_BLAST_URL}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${shorten2(s2, 10)}`;
|
|
60
64
|
return (React.createElement(React.Fragment, null,
|
|
61
|
-
React.createElement(LaunchPanelContent, { error:
|
|
65
|
+
React.createElement(LaunchPanelContent, { error: launchError ?? error },
|
|
62
66
|
children,
|
|
63
67
|
React.createElement(TranscriptSelector, { feature: feature, ...transcriptSelection }),
|
|
64
68
|
React.createElement("div", { className: classes.step },
|
|
@@ -79,24 +83,19 @@ const BlastManualPanel = observer(function ({ handleClose, feature, model, child
|
|
|
79
83
|
setTreeText(event.target.value);
|
|
80
84
|
} }),
|
|
81
85
|
React.createElement(QueryRowSelector, { ...queryRow })))),
|
|
82
|
-
React.createElement(SubmitCancelActions, { model: model, submitDisabled: !selectedTranscript || !msaText.trim(), onSubmit:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
launchView({
|
|
87
|
-
newViewTitle: getGeneDisplayName(selectedTranscript),
|
|
86
|
+
React.createElement(SubmitCancelActions, { model: model, submitDisabled: !selectedTranscript || !msaText.trim(), onSubmit: placement => {
|
|
87
|
+
if (selectedTranscript) {
|
|
88
|
+
submit(() => {
|
|
89
|
+
launchConnectedView({
|
|
88
90
|
view,
|
|
89
91
|
feature: selectedTranscript,
|
|
92
|
+
placement,
|
|
93
|
+
displayName: getGeneDisplayName(selectedTranscript),
|
|
90
94
|
querySeqName: queryRow.querySeqName,
|
|
91
95
|
querySeqOffset: queryRow.querySeqOffset,
|
|
92
96
|
data: { msa: msaText, tree: treeText },
|
|
93
97
|
});
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
catch (e) {
|
|
98
|
-
console.error(e);
|
|
99
|
-
setLaunchViewError(e);
|
|
98
|
+
});
|
|
100
99
|
}
|
|
101
100
|
}, onCancel: handleClose })));
|
|
102
101
|
});
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { AbstractTrackModel, Feature } from '@jbrowse/core/util';
|
|
3
3
|
declare const panelMap: {
|
|
4
|
-
readonly automatic: ({ handleClose, feature, model, children, }: {
|
|
4
|
+
readonly automatic: ({ handleClose, feature, model, children, preferredTranscriptId, }: {
|
|
5
5
|
model: AbstractTrackModel;
|
|
6
6
|
feature: Feature;
|
|
7
7
|
handleClose: () => void;
|
|
8
8
|
children: React.ReactNode;
|
|
9
|
+
preferredTranscriptId?: string;
|
|
9
10
|
}) => React.JSX.Element;
|
|
10
|
-
readonly manual: ({ handleClose, feature, model, children, }: {
|
|
11
|
+
readonly manual: ({ handleClose, feature, model, children, preferredTranscriptId, }: {
|
|
11
12
|
children: React.ReactNode;
|
|
12
13
|
model: AbstractTrackModel;
|
|
13
14
|
feature: Feature;
|
|
14
15
|
handleClose: () => void;
|
|
16
|
+
preferredTranscriptId?: string;
|
|
15
17
|
}) => React.JSX.Element;
|
|
16
18
|
};
|
|
17
19
|
export type BlastLookupMethod = keyof typeof panelMap;
|
|
18
|
-
export default function BlastPanel({ handleClose, model, feature, }: {
|
|
20
|
+
export default function BlastPanel({ handleClose, model, feature, preferredTranscriptId, }: {
|
|
19
21
|
handleClose: () => void;
|
|
20
22
|
model: AbstractTrackModel;
|
|
21
23
|
feature: Feature;
|
|
24
|
+
/** the isoform the user right-clicked, preselected in the picker */
|
|
25
|
+
preferredTranscriptId?: string;
|
|
22
26
|
}): React.JSX.Element;
|
|
23
27
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import SettingsIcon from '@mui/icons-material/Settings';
|
|
3
|
-
import { IconButton } from '@mui/material';
|
|
3
|
+
import { IconButton, Tooltip } from '@mui/material';
|
|
4
4
|
import { makeStyles } from 'tss-react/mui';
|
|
5
5
|
import { DEFAULT_EBI_EMAIL, EBI_EMAIL_STORAGE_KEY, } from '../../../utils/ebiJobDispatcher';
|
|
6
6
|
import { useLocalStorage } from '../../../utils/useLocalStorage';
|
|
@@ -17,18 +17,19 @@ const panelMap = {
|
|
|
17
17
|
automatic: BlastAutomaticPanel,
|
|
18
18
|
manual: BlastManualPanel,
|
|
19
19
|
};
|
|
20
|
-
export default function BlastPanel({ handleClose, model, feature, }) {
|
|
20
|
+
export default function BlastPanel({ handleClose, model, feature, preferredTranscriptId, }) {
|
|
21
21
|
const [lookupMethod, setLookupMethod] = useState('automatic');
|
|
22
22
|
const [ebiEmail, setEbiEmail] = useLocalStorage(EBI_EMAIL_STORAGE_KEY, DEFAULT_EBI_EMAIL);
|
|
23
23
|
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
24
24
|
const { classes } = useStyles();
|
|
25
25
|
const Panel = panelMap[lookupMethod];
|
|
26
26
|
return (React.createElement(React.Fragment, null,
|
|
27
|
-
React.createElement(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
React.createElement(Tooltip, { title: `EBI settings — jobs are submitted with ${ebiEmail}` },
|
|
28
|
+
React.createElement(IconButton, { className: classes.settingsButton, "aria-label": "EBI settings", size: "small", onClick: () => {
|
|
29
|
+
setSettingsOpen(true);
|
|
30
|
+
} },
|
|
31
|
+
React.createElement(SettingsIcon, null))),
|
|
32
|
+
React.createElement(Panel, { model: model, feature: feature, handleClose: handleClose, preferredTranscriptId: preferredTranscriptId },
|
|
32
33
|
React.createElement(BlastMethodSelector, { lookupMethod: lookupMethod, setLookupMethod: setLookupMethod })),
|
|
33
34
|
settingsOpen ? (React.createElement(BlastSettingsDialog, { ebiEmail: ebiEmail, handleClose: settings => {
|
|
34
35
|
if (settings) {
|