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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getSession } from '@jbrowse/core/util';
|
|
2
|
+
import { untracked } from 'mobx';
|
|
2
3
|
import { isAbortError } from '../utils/fetch';
|
|
3
4
|
/**
|
|
4
5
|
* The in-browser aligner and a search hand back rows and no tree;
|
|
@@ -33,11 +34,21 @@ function buildTree(self) {
|
|
|
33
34
|
* Run one launch attempt, owning the AbortController that ties it to the view.
|
|
34
35
|
*
|
|
35
36
|
* The controller lives on the model because two things end a launch and neither
|
|
36
|
-
* is here: the Cancel button, and the disposer `afterCreate` registers.
|
|
37
|
-
* it
|
|
38
|
-
*
|
|
37
|
+
* is here: the Cancel button, and the disposer `afterCreate` registers. A launch
|
|
38
|
+
* already holding it is aborted first, so a re-fired autorun replaces the
|
|
39
|
+
* attempt rather than orphaning one that nothing can cancel.
|
|
40
|
+
*
|
|
41
|
+
* Runs untracked: it is called from the launch autoruns, and whatever the
|
|
42
|
+
* launch body reads before its first await would otherwise become a reason to
|
|
43
|
+
* launch again.
|
|
39
44
|
*/
|
|
40
|
-
export function runLaunch(
|
|
45
|
+
export function runLaunch(args) {
|
|
46
|
+
untracked(() => {
|
|
47
|
+
startLaunch(args);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function startLaunch({ self, message, launch, onLaunched, }) {
|
|
51
|
+
self.launchController?.abort();
|
|
41
52
|
const controller = new AbortController();
|
|
42
53
|
const { signal } = controller;
|
|
43
54
|
self.setLaunchController(controller);
|
|
@@ -112,6 +112,22 @@ describe('a launch that is abandoned', () => {
|
|
|
112
112
|
expect(writes.some(w => w.startsWith('setError:Aborted'))).toBe(false);
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
|
+
describe('a launch started while another holds the controller', () => {
|
|
116
|
+
test('aborts the first, so nothing is left polling that Cancel cannot reach', async () => {
|
|
117
|
+
const { model } = makeModel();
|
|
118
|
+
const signals = [];
|
|
119
|
+
const launch = (scope) => {
|
|
120
|
+
signals.push(scope.signal);
|
|
121
|
+
return new Promise(() => { });
|
|
122
|
+
};
|
|
123
|
+
runLaunch({ self: model, message: 'a', onLaunched: () => { }, launch });
|
|
124
|
+
runLaunch({ self: model, message: 'b', onLaunched: () => { }, launch });
|
|
125
|
+
await settle();
|
|
126
|
+
expect(signals.map(s => s.aborted)).toEqual([true, false]);
|
|
127
|
+
model.launchController.abort();
|
|
128
|
+
expect(signals[1].aborted).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
115
131
|
describe('a launch that fails', () => {
|
|
116
132
|
test('records the error and stops the spinner', async () => {
|
|
117
133
|
vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
@@ -49,6 +49,9 @@ function makeModel(over = {}) {
|
|
|
49
49
|
setTreeMetadata(arg) {
|
|
50
50
|
model.data.treeMetadata = arg;
|
|
51
51
|
},
|
|
52
|
+
setGFF(arg) {
|
|
53
|
+
model.data.gff = arg;
|
|
54
|
+
},
|
|
52
55
|
...over,
|
|
53
56
|
};
|
|
54
57
|
return model;
|
|
@@ -82,6 +85,14 @@ describe('restoring a view from IndexedDB', () => {
|
|
|
82
85
|
storeDataToIndexedDB(model);
|
|
83
86
|
expect(mockStore).not.toHaveBeenCalled();
|
|
84
87
|
});
|
|
88
|
+
// react-msaview drops a GFF over 50kB from the snapshot too
|
|
89
|
+
test('a stored GFF comes back with the alignment', async () => {
|
|
90
|
+
mockRetrieve.mockResolvedValue({ msa: MSA, gff: 'a\t.\tdomain\t1\t2' });
|
|
91
|
+
const model = makeModel({ dataStoreId: 'msa-1' });
|
|
92
|
+
loadStoredData(model);
|
|
93
|
+
await settle();
|
|
94
|
+
expect(model.data.gff).toBe('a\t.\tdomain\t1\t2');
|
|
95
|
+
});
|
|
85
96
|
// the row expires or the user clears site data, and the view used to reopen as
|
|
86
97
|
// a blank import form with no hint that anything had been lost
|
|
87
98
|
test('a row that is gone says so, in words that name the policy', async () => {
|
|
@@ -95,6 +106,26 @@ describe('restoring a view from IndexedDB', () => {
|
|
|
95
106
|
// to import form" lands straight back on this error
|
|
96
107
|
expect(model.dataStoreId).toBeUndefined();
|
|
97
108
|
});
|
|
109
|
+
// the request that built the alignment is kept past the launch, so the view
|
|
110
|
+
// can offer to run it again instead of sending the user back to the gene
|
|
111
|
+
test('a row that is gone points at Retry when the search is still known', async () => {
|
|
112
|
+
mockRetrieve.mockResolvedValue(undefined);
|
|
113
|
+
const model = makeModel({
|
|
114
|
+
dataStoreId: 'msa-1',
|
|
115
|
+
blastParams: { blastDatabase: 'uniprotkb_swissprot' },
|
|
116
|
+
});
|
|
117
|
+
loadStoredData(model);
|
|
118
|
+
await settle();
|
|
119
|
+
expect(model.error.message).toMatch(/Retry/);
|
|
120
|
+
expect(model.blastParams).toBeDefined();
|
|
121
|
+
});
|
|
122
|
+
test('a row that is gone with no search behind it says to relaunch', async () => {
|
|
123
|
+
mockRetrieve.mockResolvedValue(undefined);
|
|
124
|
+
const model = makeModel({ dataStoreId: 'msa-1' });
|
|
125
|
+
loadStoredData(model);
|
|
126
|
+
await settle();
|
|
127
|
+
expect(model.error.message).toMatch(/Relaunch it from the gene/);
|
|
128
|
+
});
|
|
98
129
|
});
|
|
99
130
|
describe('keeping IndexedDB up to date', () => {
|
|
100
131
|
test('the first alignment is written under a fresh id', async () => {
|
|
@@ -127,6 +158,18 @@ describe('keeping IndexedDB up to date', () => {
|
|
|
127
158
|
});
|
|
128
159
|
expect(model.dataStoreId).toBe('msa-1');
|
|
129
160
|
});
|
|
161
|
+
test('a GFF loaded after the first write updates the row', async () => {
|
|
162
|
+
const model = makeModel({
|
|
163
|
+
dataStoreId: 'msa-1',
|
|
164
|
+
rows: [['a', 'MK']],
|
|
165
|
+
data: { msa: MSA },
|
|
166
|
+
lastStoredData: { msa: MSA },
|
|
167
|
+
});
|
|
168
|
+
model.data.gff = 'a\t.\tdomain\t1\t2';
|
|
169
|
+
storeDataToIndexedDB(model);
|
|
170
|
+
await settle();
|
|
171
|
+
expect(mockStore).toHaveBeenCalledWith('msa-1', expect.objectContaining({ gff: 'a\t.\tdomain\t1\t2' }));
|
|
172
|
+
});
|
|
130
173
|
// a browser that refuses IndexedDB (private mode) answers every write the same
|
|
131
174
|
// way, and the autorun reruns on its own isStoringData flag -- so a write that
|
|
132
175
|
// is not recorded as attempted is a write that retries forever
|
|
@@ -15,32 +15,40 @@ const mafRegion = {
|
|
|
15
15
|
assemblyName: 'hg38',
|
|
16
16
|
};
|
|
17
17
|
// A model wired through the real genomeToMSA path: a connected genome view
|
|
18
|
-
// over a maf region, with
|
|
18
|
+
// over a maf region, with the column converters as identity so the asserted
|
|
19
19
|
// column equals the ungapped offset into the region.
|
|
20
20
|
function makeModel() {
|
|
21
21
|
const calls = [];
|
|
22
22
|
const model = {
|
|
23
23
|
querySeqName: 'hg38.chr1',
|
|
24
|
-
|
|
24
|
+
rowMap: new Map([['hg38.chr1', 'ACGTACGTAC']]),
|
|
25
25
|
transcriptToMsaMap: undefined,
|
|
26
26
|
mafRegion,
|
|
27
27
|
connectedView: { initialized: true, assemblyNames: ['hg38'] },
|
|
28
28
|
seqPosToVisibleCol: (_name, pos) => pos,
|
|
29
|
+
visibleColToSeqPos: (_name, col) => col,
|
|
29
30
|
setMousePos: (col) => {
|
|
30
31
|
calls.push(col);
|
|
31
32
|
},
|
|
32
33
|
};
|
|
33
34
|
return { model, calls };
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
// this config spells the refName the same way on both sides, so the assembly
|
|
37
|
+
// hands every name straight back
|
|
38
|
+
const assemblyManager = {
|
|
39
|
+
get: () => ({ getCanonicalRefName: (refName) => refName }),
|
|
40
|
+
};
|
|
41
|
+
function mockSession(hovered) {
|
|
36
42
|
mockGetSession.mockReturnValue({
|
|
37
|
-
|
|
43
|
+
assemblyManager,
|
|
44
|
+
hovered,
|
|
38
45
|
});
|
|
39
46
|
}
|
|
47
|
+
function hoverGenome(coord) {
|
|
48
|
+
mockSession({ hoverFeature: {}, hoverPosition: { coord, refName: 'chr1' } });
|
|
49
|
+
}
|
|
40
50
|
function clearGenomeHover() {
|
|
41
|
-
|
|
42
|
-
hovered: null,
|
|
43
|
-
});
|
|
51
|
+
mockSession(null);
|
|
44
52
|
}
|
|
45
53
|
describe('syncGenomeHoverToMsaColumn (real genomeToMSA mapping)', () => {
|
|
46
54
|
beforeEach(() => {
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Whether `querySeqName` names a row this alignment actually has.
|
|
2
|
+
* Whether `querySeqName` names a row this alignment actually has. The name
|
|
3
|
+
* defaults to `QUERY`, which an uploaded alignment has no reason to carry, so
|
|
4
|
+
* the genome and structure hovers ask this before mapping anything.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* name is wrong more often than it looks: it defaults to `QUERY`, which an
|
|
8
|
-
* uploaded alignment has no reason to carry, and the manual panel leaves it
|
|
9
|
-
* empty when it cannot match the protein to a row.
|
|
10
|
-
*
|
|
11
|
-
* The other direction has no such hole: msaCoordToGenomeRegions needs the query
|
|
12
|
-
* row's sequence to map a column at all, so a missing row is already nothing
|
|
13
|
-
* there.
|
|
6
|
+
* `rowMap`, not `rows`: `rows` is what is on screen, and a query row folded
|
|
7
|
+
* into a collapsed clade is still in the alignment, still has its columns, and
|
|
8
|
+
* still maps.
|
|
14
9
|
*/
|
|
15
10
|
export declare function hasQueryRow(model: {
|
|
16
|
-
|
|
11
|
+
rowMap: ReadonlyMap<string, string>;
|
|
17
12
|
querySeqName: string;
|
|
18
13
|
}): boolean;
|
|
19
14
|
/**
|
|
@@ -35,23 +30,28 @@ interface LiveFeature {
|
|
|
35
30
|
export declare function transcriptFields(transcript?: TranscriptRef): Record<string, unknown>;
|
|
36
31
|
/** what a transcript is called, preferring its name over its id */
|
|
37
32
|
export declare function transcriptName(transcript?: TranscriptRef): string | undefined;
|
|
38
|
-
|
|
33
|
+
interface QueryRowColumns {
|
|
39
34
|
querySeqName: string;
|
|
40
|
-
querySeqOffset: number;
|
|
41
35
|
seqPosToVisibleCol: (rowName: string, seqPos: number) => number | undefined;
|
|
42
36
|
visibleColToSeqPos: (rowName: string, visibleCol: number) => number | undefined;
|
|
43
37
|
}
|
|
38
|
+
export interface QueryRowModel extends QueryRowColumns {
|
|
39
|
+
querySeqOffset: number;
|
|
40
|
+
}
|
|
44
41
|
/**
|
|
45
|
-
* The visible column showing residue `
|
|
46
|
-
*
|
|
47
|
-
*
|
|
42
|
+
* The visible column showing residue `seqPos` (0-based) of the query row, or
|
|
43
|
+
* undefined when the row does not carry that residue or react-msaview is
|
|
44
|
+
* hiding its column.
|
|
48
45
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
46
|
+
* react-msaview answers one column past the end for a position the row does not
|
|
47
|
+
* have, which would light the last column for every residue beyond the row, so
|
|
48
|
+
* the round trip back through visibleColToSeqPos is what rejects those.
|
|
49
|
+
*/
|
|
50
|
+
export declare function querySeqPosToVisibleCol(model: QueryRowColumns, seqPos: number): number | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* The visible column showing residue `proteinPos` (0-based) of the transcript.
|
|
53
|
+
* `querySeqOffset` is what separates the two: a pasted BLAST alignment carries
|
|
54
|
+
* the aligned region, not the whole protein.
|
|
55
55
|
*/
|
|
56
56
|
export declare function transcriptPosToVisibleCol(model: QueryRowModel, proteinPos: number): number | undefined;
|
|
57
57
|
export declare function hasHoverPosition(hovered: unknown): hovered is {
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Whether `querySeqName` names a row this alignment actually has.
|
|
2
|
+
* Whether `querySeqName` names a row this alignment actually has. The name
|
|
3
|
+
* defaults to `QUERY`, which an uploaded alignment has no reason to carry, so
|
|
4
|
+
* the genome and structure hovers ask this before mapping anything.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* name is wrong more often than it looks: it defaults to `QUERY`, which an
|
|
8
|
-
* uploaded alignment has no reason to carry, and the manual panel leaves it
|
|
9
|
-
* empty when it cannot match the protein to a row.
|
|
10
|
-
*
|
|
11
|
-
* The other direction has no such hole: msaCoordToGenomeRegions needs the query
|
|
12
|
-
* row's sequence to map a column at all, so a missing row is already nothing
|
|
13
|
-
* there.
|
|
6
|
+
* `rowMap`, not `rows`: `rows` is what is on screen, and a query row folded
|
|
7
|
+
* into a collapsed clade is still in the alignment, still has its columns, and
|
|
8
|
+
* still maps.
|
|
14
9
|
*/
|
|
15
10
|
export function hasQueryRow(model) {
|
|
16
|
-
return model.
|
|
11
|
+
return model.rowMap.has(model.querySeqName);
|
|
17
12
|
}
|
|
18
13
|
/**
|
|
19
14
|
* Read the transcript's fields whichever shape it arrived in: a caller inside
|
|
@@ -36,20 +31,16 @@ export function transcriptName(transcript) {
|
|
|
36
31
|
return str(fields.name) ?? str(fields.id);
|
|
37
32
|
}
|
|
38
33
|
/**
|
|
39
|
-
* The visible column showing residue `
|
|
40
|
-
*
|
|
41
|
-
*
|
|
34
|
+
* The visible column showing residue `seqPos` (0-based) of the query row, or
|
|
35
|
+
* undefined when the row does not carry that residue or react-msaview is
|
|
36
|
+
* hiding its column.
|
|
42
37
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* past the end for a position it does not have, which would light the last
|
|
47
|
-
* column for every residue beyond the row, so the round trip back through
|
|
48
|
-
* visibleColToSeqPos is what rejects those.
|
|
38
|
+
* react-msaview answers one column past the end for a position the row does not
|
|
39
|
+
* have, which would light the last column for every residue beyond the row, so
|
|
40
|
+
* the round trip back through visibleColToSeqPos is what rejects those.
|
|
49
41
|
*/
|
|
50
|
-
export function
|
|
51
|
-
const { querySeqName
|
|
52
|
-
const seqPos = proteinPos - querySeqOffset;
|
|
42
|
+
export function querySeqPosToVisibleCol(model, seqPos) {
|
|
43
|
+
const { querySeqName } = model;
|
|
53
44
|
if (seqPos < 0) {
|
|
54
45
|
return undefined;
|
|
55
46
|
}
|
|
@@ -59,6 +50,14 @@ export function transcriptPosToVisibleCol(model, proteinPos) {
|
|
|
59
50
|
? col
|
|
60
51
|
: undefined;
|
|
61
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* The visible column showing residue `proteinPos` (0-based) of the transcript.
|
|
55
|
+
* `querySeqOffset` is what separates the two: a pasted BLAST alignment carries
|
|
56
|
+
* the aligned region, not the whole protein.
|
|
57
|
+
*/
|
|
58
|
+
export function transcriptPosToVisibleCol(model, proteinPos) {
|
|
59
|
+
return querySeqPosToVisibleCol(model, proteinPos - model.querySeqOffset);
|
|
60
|
+
}
|
|
62
61
|
export function hasHoverPosition(hovered) {
|
|
63
62
|
return (!!hovered &&
|
|
64
63
|
typeof hovered === 'object' &&
|
package/dist/index.d.ts
CHANGED
|
@@ -7,20 +7,20 @@ export default class MsaViewPlugin extends Plugin {
|
|
|
7
7
|
configure(pluginManager: PluginManager): void;
|
|
8
8
|
rootConfigurationSchema: (pluginManager: PluginManager) => {
|
|
9
9
|
msa: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
10
|
-
datasets: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
11
|
-
datasetId: {
|
|
12
|
-
type: string;
|
|
13
|
-
defaultValue:
|
|
10
|
+
readonly datasets: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
11
|
+
readonly datasetId: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
readonly defaultValue: "";
|
|
14
14
|
};
|
|
15
|
-
description: {
|
|
16
|
-
type: string;
|
|
17
|
-
defaultValue:
|
|
15
|
+
readonly description: {
|
|
16
|
+
readonly type: "string";
|
|
17
|
+
readonly defaultValue: "";
|
|
18
18
|
};
|
|
19
|
-
name: {
|
|
20
|
-
type: string;
|
|
21
|
-
defaultValue:
|
|
19
|
+
readonly name: {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
readonly defaultValue: "";
|
|
22
22
|
};
|
|
23
|
-
adapter: import("@jbrowse/mobx-state-tree").
|
|
23
|
+
readonly adapter: import("@jbrowse/mobx-state-tree").IAnyType;
|
|
24
24
|
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>>>;
|
|
25
25
|
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
|
|
26
26
|
};
|
package/dist/index.js
CHANGED
|
@@ -45,16 +45,23 @@ export default class MsaViewPlugin extends Plugin {
|
|
|
45
45
|
BgzipFastaMsaAdapterF(pluginManager);
|
|
46
46
|
}
|
|
47
47
|
configure(pluginManager) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
// a throw here error-pages the whole app, and a menu entry is not worth a
|
|
49
|
+
// session: every released host's File menu already throws on append
|
|
50
|
+
try {
|
|
51
|
+
if (isAbstractMenuManager(pluginManager.rootModel)) {
|
|
52
|
+
pluginManager.rootModel.appendToSubMenu(['Add'], {
|
|
53
|
+
label: 'Multiple sequence alignment view',
|
|
54
|
+
icon: GridOn,
|
|
55
|
+
onClick: (session) => {
|
|
56
|
+
// stacked, by default: nothing was launched from, so there is no
|
|
57
|
+
// connected view for it to sit beside
|
|
58
|
+
launchMsaView(session, {});
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
console.error('jbrowse-plugin-msaview: could not add the Add menu item', e);
|
|
58
65
|
}
|
|
59
66
|
}
|
|
60
67
|
}
|