jbrowse-plugin-msaview 2.8.2 → 2.9.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/dist/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastRIDPanel.d.ts → BlastQuery/BlastAutomaticPanel.d.ts} +2 -3
- package/dist/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastAutomaticPanel.js → BlastQuery/BlastAutomaticPanel.js} +6 -25
- package/dist/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastManualPanel.d.ts → BlastQuery/BlastManualPanel.d.ts} +2 -3
- package/dist/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastManualPanel.js → BlastQuery/BlastManualPanel.js} +7 -4
- package/dist/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastMethodSelector.d.ts → BlastQuery/BlastMethodSelector.d.ts} +2 -2
- package/dist/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastMethodSelector.js → BlastQuery/BlastMethodSelector.js} +1 -2
- package/dist/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastPanel.d.ts → BlastQuery/BlastPanel.d.ts} +3 -12
- package/dist/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastPanel.js → BlastQuery/BlastPanel.js} +14 -16
- package/dist/LaunchMsaView/components/BlastQuery/BlastSettingsDialog.d.ts +8 -0
- package/dist/LaunchMsaView/components/{NCBIBlastQuery/NCBISettingsDialog.js → BlastQuery/BlastSettingsDialog.js} +13 -9
- package/dist/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/CachedBlastResults.js +1 -1
- package/dist/LaunchMsaView/components/BlastQuery/consts.d.ts +12 -0
- package/dist/LaunchMsaView/components/BlastQuery/consts.js +17 -0
- package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js +3 -3
- package/dist/LaunchMsaView/components/OrthologQuery/OrthologPanel.js +1 -1
- package/dist/MsaViewPanel/components/JobLink.d.ts +5 -0
- package/dist/MsaViewPanel/components/JobLink.js +13 -0
- package/dist/MsaViewPanel/components/LoadingBLAST.d.ts +1 -2
- package/dist/MsaViewPanel/components/LoadingBLAST.js +8 -15
- package/dist/MsaViewPanel/components/MsaViewPanel.js +1 -1
- package/dist/MsaViewPanel/doLaunchBlast.js +11 -19
- package/dist/MsaViewPanel/doLaunchOrthologs.test.d.ts +1 -0
- package/dist/MsaViewPanel/doLaunchOrthologs.test.js +127 -0
- package/dist/MsaViewPanel/model.d.ts +1 -4
- package/dist/jbrowse-plugin-msaview.umd.production.min.js +30 -30
- package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
- package/dist/utils/blastCache.d.ts +8 -4
- package/dist/utils/blastCache.js +4 -5
- package/dist/utils/ebiBlast.d.ts +52 -0
- package/dist/utils/ebiBlast.js +63 -0
- package/dist/utils/ebiJobDispatcher.d.ts +33 -0
- package/dist/utils/ebiJobDispatcher.js +55 -0
- package/dist/utils/fetch.js +24 -1
- package/dist/utils/msa.d.ts +1 -1
- package/dist/utils/msa.js +25 -32
- package/dist/utils/types.d.ts +9 -14
- package/dist/utils/useLocalStorage.d.ts +1 -0
- package/dist/utils/useLocalStorage.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastAutomaticPanel.tsx → BlastQuery/BlastAutomaticPanel.tsx} +13 -59
- package/src/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastManualPanel.tsx → BlastQuery/BlastManualPanel.tsx} +7 -6
- package/src/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastMethodSelector.tsx → BlastQuery/BlastMethodSelector.tsx} +2 -7
- package/src/LaunchMsaView/components/{NCBIBlastQuery/NCBIBlastPanel.tsx → BlastQuery/BlastPanel.tsx} +21 -25
- package/src/LaunchMsaView/components/{NCBIBlastQuery/NCBISettingsDialog.tsx → BlastQuery/BlastSettingsDialog.tsx} +26 -13
- package/src/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/CachedBlastResults.tsx +1 -1
- package/src/LaunchMsaView/components/BlastQuery/consts.ts +22 -0
- package/src/LaunchMsaView/components/LaunchMsaViewDialog.tsx +5 -7
- package/src/LaunchMsaView/components/OrthologQuery/OrthologPanel.tsx +2 -2
- package/src/MsaViewPanel/components/JobLink.tsx +17 -0
- package/src/MsaViewPanel/components/LoadingBLAST.tsx +10 -41
- package/src/MsaViewPanel/components/MsaViewPanel.tsx +1 -1
- package/src/MsaViewPanel/doLaunchBlast.ts +12 -28
- package/src/MsaViewPanel/doLaunchOrthologs.test.ts +159 -0
- package/src/MsaViewPanel/model.ts +1 -5
- package/src/utils/blastCache.ts +8 -9
- package/src/utils/ebiBlast.ts +114 -0
- package/src/utils/ebiJobDispatcher.ts +91 -0
- package/src/utils/fetch.ts +26 -1
- package/src/utils/msa.ts +26 -47
- package/src/utils/types.ts +8 -13
- package/src/utils/useLocalStorage.ts +1 -1
- package/src/version.ts +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.d.ts +0 -10
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js +0 -74
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.d.ts +0 -5
- package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.d.ts +0 -7
- package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.js +0 -4
- package/dist/MsaViewPanel/components/RIDLink.d.ts +0 -6
- package/dist/MsaViewPanel/components/RIDLink.js +0 -12
- package/dist/utils/ncbiBlast.d.ts +0 -30
- package/dist/utils/ncbiBlast.js +0 -84
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.tsx +0 -137
- package/src/LaunchMsaView/components/NCBIBlastQuery/consts.ts +0 -10
- package/src/MsaViewPanel/components/RIDLink.tsx +0 -19
- package/src/utils/ncbiBlast.ts +0 -143
- /package/dist/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/CachedBlastResults.d.ts +0 -0
- /package/dist/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/MsaAlgorithmSelect.d.ts +0 -0
- /package/dist/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/MsaAlgorithmSelect.js +0 -0
- /package/dist/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/blastLaunchView.d.ts +0 -0
- /package/dist/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/blastLaunchView.js +0 -0
- /package/dist/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/useCachedBlastResults.d.ts +0 -0
- /package/dist/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/useCachedBlastResults.js +0 -0
- /package/src/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/MsaAlgorithmSelect.tsx +0 -0
- /package/src/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/blastLaunchView.ts +0 -0
- /package/src/LaunchMsaView/components/{NCBIBlastQuery → BlastQuery}/useCachedBlastResults.ts +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import { doLaunchOrthologs } from './doLaunchOrthologs';
|
|
3
|
+
import { launchMSA } from '../utils/msa';
|
|
4
|
+
import { COMMON_SPECIES, fetchOrthologRows, fetchProteinForGene, resolveGeneId, } from '../utils/ncbiOrthologs';
|
|
5
|
+
// Every network call is mocked and nothing else is. What is under test is the
|
|
6
|
+
// argument shaping either side of those calls -- which taxa get asked for, what
|
|
7
|
+
// becomes the QUERY row, and whether the row earns the Accession that drives the
|
|
8
|
+
// CDD overlay -- so the real COMMON_SPECIES list and the real
|
|
9
|
+
// cleanProteinSequence stay in the picture.
|
|
10
|
+
vi.mock('../utils/ncbiOrthologs', async (importOriginal) => ({
|
|
11
|
+
...(await importOriginal()),
|
|
12
|
+
resolveGeneId: vi.fn(),
|
|
13
|
+
fetchProteinForGene: vi.fn(),
|
|
14
|
+
fetchOrthologRows: vi.fn(),
|
|
15
|
+
}));
|
|
16
|
+
vi.mock('../utils/msa', () => ({ launchMSA: vi.fn() }));
|
|
17
|
+
const mockResolveGeneId = vi.mocked(resolveGeneId);
|
|
18
|
+
const mockFetchProtein = vi.mocked(fetchProteinForGene);
|
|
19
|
+
const mockFetchRows = vi.mocked(fetchOrthologRows);
|
|
20
|
+
const mockLaunchMSA = vi.mocked(launchMSA);
|
|
21
|
+
const HUMAN = 9606;
|
|
22
|
+
const GENE_ID = '22861';
|
|
23
|
+
const REPRESENTATIVE = { accession: 'NP_127497.1', sequence: 'MAGGAWGRLACY' };
|
|
24
|
+
function makeModel(orthologParams) {
|
|
25
|
+
return {
|
|
26
|
+
orthologParams,
|
|
27
|
+
setProgress: () => { },
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function params(extra = {}) {
|
|
31
|
+
return {
|
|
32
|
+
taxId: HUMAN,
|
|
33
|
+
geneCandidates: ['NLRP1'],
|
|
34
|
+
msaAlgorithm: 'clustalo',
|
|
35
|
+
...extra,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// What fetchOrthologRows was asked for, which is the only place the taxa
|
|
39
|
+
// default is observable.
|
|
40
|
+
function taxaAskedFor() {
|
|
41
|
+
return [...mockFetchRows.mock.calls[0][0].taxa].sort((a, b) => a - b);
|
|
42
|
+
}
|
|
43
|
+
// The QUERY row as it went to the aligner, read back out of the FASTA rather
|
|
44
|
+
// than out of an intermediate, since the FASTA is what the alignment is of.
|
|
45
|
+
function queryRowSent() {
|
|
46
|
+
return mockLaunchMSA.mock.calls[0][0].sequence.split('\n')[1];
|
|
47
|
+
}
|
|
48
|
+
function queryMetadata(result) {
|
|
49
|
+
return JSON.parse(result.treeMetadata).QUERY;
|
|
50
|
+
}
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
vi.clearAllMocks();
|
|
53
|
+
mockResolveGeneId.mockResolvedValue({ geneId: GENE_ID, matched: 'NLRP1' });
|
|
54
|
+
mockFetchProtein.mockResolvedValue(REPRESENTATIVE);
|
|
55
|
+
mockFetchRows.mockResolvedValue([]);
|
|
56
|
+
mockLaunchMSA.mockResolvedValue({ msa: '', tree: '' });
|
|
57
|
+
});
|
|
58
|
+
describe('taxa', () => {
|
|
59
|
+
test('omitted asks for every species the dialog offers, less the query', async () => {
|
|
60
|
+
await doLaunchOrthologs({ self: makeModel(params()) });
|
|
61
|
+
expect(taxaAskedFor()).toEqual(COMMON_SPECIES.map(s => s.taxId)
|
|
62
|
+
.filter(t => t !== HUMAN)
|
|
63
|
+
.sort((a, b) => a - b));
|
|
64
|
+
});
|
|
65
|
+
test('given is taken as written, less the query', async () => {
|
|
66
|
+
await doLaunchOrthologs({
|
|
67
|
+
self: makeModel(params({ taxa: [HUMAN, 10090, 9615] })),
|
|
68
|
+
});
|
|
69
|
+
expect(taxaAskedFor()).toEqual([9615, 10090]);
|
|
70
|
+
});
|
|
71
|
+
test('an empty list is a request for no rows, not a request for all of them', async () => {
|
|
72
|
+
await doLaunchOrthologs({ self: makeModel(params({ taxa: [] })) });
|
|
73
|
+
expect(taxaAskedFor()).toEqual([]);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('the QUERY row', () => {
|
|
77
|
+
test('omitted proteinSequence falls back to the representative protein', async () => {
|
|
78
|
+
await doLaunchOrthologs({ self: makeModel(params()) });
|
|
79
|
+
expect(queryRowSent()).toBe(REPRESENTATIVE.sequence);
|
|
80
|
+
});
|
|
81
|
+
test('a supplied sequence is used, and is cleaned first', async () => {
|
|
82
|
+
await doLaunchOrthologs({
|
|
83
|
+
self: makeModel(params({ proteinSequence: 'MAGG*AWGR&' })),
|
|
84
|
+
});
|
|
85
|
+
expect(queryRowSent()).toBe('MAGGAWGR');
|
|
86
|
+
});
|
|
87
|
+
test('throws when neither a sequence nor a representative is available', async () => {
|
|
88
|
+
mockFetchProtein.mockResolvedValue(undefined);
|
|
89
|
+
await expect(doLaunchOrthologs({ self: makeModel(params()) })).rejects.toThrow(/No query protein/);
|
|
90
|
+
expect(mockLaunchMSA).not.toHaveBeenCalled();
|
|
91
|
+
});
|
|
92
|
+
test('a failed representative lookup does not take down a launch that brought its own sequence', async () => {
|
|
93
|
+
vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
94
|
+
mockFetchProtein.mockRejectedValue(new Error('429'));
|
|
95
|
+
await doLaunchOrthologs({
|
|
96
|
+
self: makeModel(params({ proteinSequence: REPRESENTATIVE.sequence })),
|
|
97
|
+
});
|
|
98
|
+
expect(queryRowSent()).toBe(REPRESENTATIVE.sequence);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
// The Accession is what afterCreateAutoruns.autoLoadProteinDomains keys the CDD
|
|
102
|
+
// overlay off, and attaching it to a row that is NOT the protein it names draws
|
|
103
|
+
// every domain box at an offset. So the byte-identity guard is the assertion
|
|
104
|
+
// here, in both directions.
|
|
105
|
+
describe('the Accession that drives the domain overlay', () => {
|
|
106
|
+
test('is attached when the query row IS the representative protein', async () => {
|
|
107
|
+
const result = await doLaunchOrthologs({ self: makeModel(params()) });
|
|
108
|
+
expect(queryMetadata(result)).toMatchObject({
|
|
109
|
+
'Gene ID': GENE_ID,
|
|
110
|
+
Accession: REPRESENTATIVE.accession,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
test('is withheld from a non-representative isoform', async () => {
|
|
114
|
+
const result = await doLaunchOrthologs({
|
|
115
|
+
self: makeModel(params({ proteinSequence: 'MDIFFERENTISOFORM' })),
|
|
116
|
+
});
|
|
117
|
+
expect(queryMetadata(result).Accession).toBeUndefined();
|
|
118
|
+
});
|
|
119
|
+
test('is withheld when the representative lookup failed', async () => {
|
|
120
|
+
vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
121
|
+
mockFetchProtein.mockRejectedValue(new Error('429'));
|
|
122
|
+
const result = await doLaunchOrthologs({
|
|
123
|
+
self: makeModel(params({ proteinSequence: REPRESENTATIVE.sequence })),
|
|
124
|
+
});
|
|
125
|
+
expect(queryMetadata(result).Accession).toBeUndefined();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { MSAFormat } from 'msa-parsers';
|
|
2
2
|
import type { MafRegion, MsaViewInitState } from './types';
|
|
3
|
-
import type { BlastDatabase,
|
|
3
|
+
import type { BlastDatabase, MsaAlgorithm } from '../LaunchMsaView/components/BlastQuery/consts';
|
|
4
4
|
import type { Feature } from '@jbrowse/core/util';
|
|
5
5
|
import type { Instance } from '@jbrowse/mobx-state-tree';
|
|
6
6
|
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view';
|
|
@@ -12,13 +12,10 @@ export interface IRegion {
|
|
|
12
12
|
end: number;
|
|
13
13
|
}
|
|
14
14
|
export interface BlastParams {
|
|
15
|
-
baseUrl: string;
|
|
16
15
|
blastDatabase: BlastDatabase;
|
|
17
16
|
msaAlgorithm: MsaAlgorithm;
|
|
18
|
-
blastProgram: BlastProgram;
|
|
19
17
|
selectedTranscript?: Feature;
|
|
20
18
|
proteinSequence: string;
|
|
21
|
-
rid?: string;
|
|
22
19
|
}
|
|
23
20
|
export interface OrthologParams {
|
|
24
21
|
/** NCBI taxon id of the assembly the query gene came from */
|