jbrowse-plugin-msaview 2.2.7 → 2.2.11
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/BgzipFastaMsaAdapter/configSchema.d.ts +2 -2
- package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js +1 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js.map +1 -1
- package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +2 -2
- package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js +29 -6
- package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js +16 -6
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js +2 -2
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.js +3 -2
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js +7 -3
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.d.ts +10 -0
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js +77 -0
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js.map +1 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +1 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/TranscriptSelector.d.ts +2 -1
- package/dist/LaunchMsaView/components/TranscriptSelector.js +7 -6
- package/dist/LaunchMsaView/components/TranscriptSelector.js.map +1 -1
- package/dist/LaunchMsaView/components/useTranscriptSelection.js +13 -7
- package/dist/LaunchMsaView/components/useTranscriptSelection.js.map +1 -1
- package/dist/LaunchMsaView/util.d.ts +2 -0
- package/dist/LaunchMsaView/util.js +18 -2
- package/dist/LaunchMsaView/util.js.map +1 -1
- package/dist/MsaViewPanel/doLaunchBlast.js +36 -15
- package/dist/MsaViewPanel/doLaunchBlast.js.map +1 -1
- package/dist/MsaViewPanel/model.d.ts +7 -0
- package/dist/MsaViewPanel/model.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +21 -22
- package/dist/index.js.map +1 -1
- package/dist/jbrowse-plugin-msaview.umd.production.min.js +27 -27
- package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
- package/dist/utils/blastCache.d.ts +8 -2
- package/dist/utils/blastCache.js +19 -6
- package/dist/utils/blastCache.js.map +1 -1
- package/dist/utils/ncbiBlast.d.ts +13 -0
- package/dist/utils/ncbiBlast.js +13 -0
- package/dist/utils/ncbiBlast.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +7 -7
- package/src/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.tsx +1 -0
- package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +2 -0
- package/src/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.tsx +32 -6
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.tsx +19 -4
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.tsx +9 -2
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.tsx +4 -3
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.tsx +8 -4
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.tsx +187 -0
- package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +1 -0
- package/src/LaunchMsaView/components/TranscriptSelector.tsx +10 -6
- package/src/LaunchMsaView/components/useTranscriptSelection.ts +16 -7
- package/src/LaunchMsaView/util.ts +20 -2
- package/src/MsaViewPanel/doLaunchBlast.ts +37 -14
- package/src/MsaViewPanel/model.ts +1 -0
- package/src/index.ts +1 -2
- package/src/utils/blastCache.ts +36 -3
- package/src/utils/ncbiBlast.ts +24 -0
- package/src/version.ts +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
|
|
3
3
|
import { Feature } from '@jbrowse/core/util'
|
|
4
|
-
import { Button, MenuItem } from '@mui/material'
|
|
4
|
+
import { Button, MenuItem, TextField } from '@mui/material'
|
|
5
5
|
import { makeStyles } from 'tss-react/mui'
|
|
6
6
|
|
|
7
7
|
import ReadOnlyTextField2 from '../../components/ReadOnlyTextField2'
|
|
8
|
-
import TextField2 from '../../components/TextField2'
|
|
9
8
|
import {
|
|
9
|
+
featureMatchesId,
|
|
10
10
|
getGeneDisplayName,
|
|
11
11
|
getId,
|
|
12
12
|
getTranscriptDisplayName,
|
|
@@ -25,6 +25,7 @@ const useStyles = makeStyles()({
|
|
|
25
25
|
export default function TranscriptSelector({
|
|
26
26
|
feature,
|
|
27
27
|
options,
|
|
28
|
+
selectedId,
|
|
28
29
|
selectedTranscript,
|
|
29
30
|
onTranscriptChange,
|
|
30
31
|
proteinSequence,
|
|
@@ -32,6 +33,7 @@ export default function TranscriptSelector({
|
|
|
32
33
|
}: {
|
|
33
34
|
feature: Feature
|
|
34
35
|
options: Feature[]
|
|
36
|
+
selectedId: string
|
|
35
37
|
selectedTranscript: Feature | undefined
|
|
36
38
|
onTranscriptChange: (transcriptId: string) => void
|
|
37
39
|
proteinSequence: string | undefined
|
|
@@ -43,18 +45,20 @@ export default function TranscriptSelector({
|
|
|
43
45
|
return (
|
|
44
46
|
<>
|
|
45
47
|
<div className={classes.flex}>
|
|
46
|
-
<
|
|
48
|
+
<TextField
|
|
47
49
|
variant="outlined"
|
|
48
50
|
label={`Choose isoform of ${getGeneDisplayName(feature)}`}
|
|
49
51
|
select
|
|
50
52
|
className={classes.minWidth}
|
|
51
|
-
value={
|
|
53
|
+
value={selectedId}
|
|
52
54
|
onChange={event => {
|
|
53
55
|
onTranscriptChange(event.target.value)
|
|
54
56
|
}}
|
|
55
57
|
>
|
|
56
58
|
{options.map(val => {
|
|
57
|
-
const inSet = validSet
|
|
59
|
+
const inSet = validSet
|
|
60
|
+
? [...validSet].some(id => featureMatchesId(val, id))
|
|
61
|
+
: true
|
|
58
62
|
const { len, mod } = getTranscriptLength(val)
|
|
59
63
|
return (
|
|
60
64
|
<MenuItem value={getId(val)} key={val.id()} disabled={!inSet}>
|
|
@@ -64,7 +68,7 @@ export default function TranscriptSelector({
|
|
|
64
68
|
</MenuItem>
|
|
65
69
|
)
|
|
66
70
|
})}
|
|
67
|
-
</
|
|
71
|
+
</TextField>
|
|
68
72
|
<div style={{ alignContent: 'center', marginLeft: 20 }}>
|
|
69
73
|
<Button
|
|
70
74
|
variant="contained"
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { useEffect, useMemo, useState } from 'react'
|
|
2
2
|
|
|
3
|
-
import { getId, getSortedTranscriptFeatures } from '../util'
|
|
3
|
+
import { featureMatchesId, getId, getSortedTranscriptFeatures } from '../util'
|
|
4
4
|
import { useFeatureSequence } from './useFeatureSequence'
|
|
5
5
|
|
|
6
6
|
import type { Feature } from '@jbrowse/core/util'
|
|
7
7
|
|
|
8
|
+
function featureInValidIds(feature: Feature, validIds: string[]): boolean {
|
|
9
|
+
return validIds.some(id => featureMatchesId(feature, id))
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
export function useTranscriptSelection({
|
|
9
13
|
feature,
|
|
10
14
|
view,
|
|
@@ -14,8 +18,8 @@ export function useTranscriptSelection({
|
|
|
14
18
|
view: { assemblyNames?: string[] } | undefined
|
|
15
19
|
validIds?: string[]
|
|
16
20
|
}) {
|
|
17
|
-
const options = getSortedTranscriptFeatures(feature)
|
|
18
|
-
const [selectedId, setSelectedId] = useState(getId(options[0]))
|
|
21
|
+
const options = useMemo(() => getSortedTranscriptFeatures(feature), [feature])
|
|
22
|
+
const [selectedId, setSelectedId] = useState(() => getId(options[0]))
|
|
19
23
|
const selectedTranscript = options.find(val => getId(val) === selectedId)
|
|
20
24
|
const { proteinSequence, error } = useFeatureSequence({
|
|
21
25
|
view,
|
|
@@ -28,10 +32,15 @@ export function useTranscriptSelection({
|
|
|
28
32
|
)
|
|
29
33
|
|
|
30
34
|
useEffect(() => {
|
|
31
|
-
if (validIds && validIds.length > 0
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
+
if (validIds && validIds.length > 0) {
|
|
36
|
+
const currentFeature = options.find(opt => getId(opt) === selectedId)
|
|
37
|
+
if (currentFeature && !featureInValidIds(currentFeature, validIds)) {
|
|
38
|
+
const validOption = options.find(opt =>
|
|
39
|
+
featureInValidIds(opt, validIds),
|
|
40
|
+
)
|
|
41
|
+
if (validOption) {
|
|
42
|
+
setSelectedId(getId(validOption))
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
}, [validIds, options, selectedId])
|
|
@@ -38,7 +38,24 @@ export function getTranscriptLength(feature: Feature) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
export function getId(val?: Feature): string {
|
|
41
|
-
return val?.
|
|
41
|
+
return val?.id() ?? ''
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getMatchableIds(val?: Feature): string[] {
|
|
45
|
+
if (!val) {
|
|
46
|
+
return []
|
|
47
|
+
}
|
|
48
|
+
const ids = [
|
|
49
|
+
val.id(),
|
|
50
|
+
val.get('name'),
|
|
51
|
+
val.get('id'),
|
|
52
|
+
val.get('transcript_id'),
|
|
53
|
+
].filter((id): id is string => !!id)
|
|
54
|
+
return [...new Set(ids)]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function featureMatchesId(feature: Feature, id: string): boolean {
|
|
58
|
+
return getMatchableIds(feature).includes(id)
|
|
42
59
|
}
|
|
43
60
|
|
|
44
61
|
export function getTranscriptDisplayName(val?: Feature) {
|
|
@@ -59,7 +76,8 @@ export function getGeneDisplayName(val?: Feature) {
|
|
|
59
76
|
}
|
|
60
77
|
|
|
61
78
|
export function getSortedTranscriptFeatures(feature: Feature) {
|
|
62
|
-
|
|
79
|
+
const transcripts = getTranscriptFeatures(feature)
|
|
80
|
+
return transcripts.toSorted(
|
|
63
81
|
(a, b) => getTranscriptLength(b).len - getTranscriptLength(a).len,
|
|
64
82
|
)
|
|
65
83
|
}
|
|
@@ -3,7 +3,7 @@ import { makeId, strip } from '../LaunchMsaView/components/util'
|
|
|
3
3
|
import { cleanProteinSequence } from '../LaunchMsaView/util'
|
|
4
4
|
import { saveBlastResult } from '../utils/blastCache'
|
|
5
5
|
import { launchMSA } from '../utils/msa'
|
|
6
|
-
import { queryBlast } from '../utils/ncbiBlast'
|
|
6
|
+
import { queryBlast, queryBlastFromRid } from '../utils/ncbiBlast'
|
|
7
7
|
import { fetchTaxonomyInfo } from '../utils/taxonomyNames'
|
|
8
8
|
|
|
9
9
|
import type { TaxonomyInfo } from '../utils/taxonomyNames'
|
|
@@ -21,21 +21,39 @@ export async function doLaunchBlast({
|
|
|
21
21
|
msaAlgorithm,
|
|
22
22
|
proteinSequence,
|
|
23
23
|
selectedTranscript,
|
|
24
|
+
rid: existingRid,
|
|
24
25
|
} = self.blastParams!
|
|
25
26
|
const cleanedSeq = cleanProteinSequence(proteinSequence)
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
28
|
+
let hits
|
|
29
|
+
let rid: string
|
|
30
|
+
if (existingRid) {
|
|
31
|
+
self.setRid(existingRid)
|
|
32
|
+
const result = await queryBlastFromRid({
|
|
33
|
+
rid: existingRid,
|
|
34
|
+
baseUrl,
|
|
35
|
+
onProgress: arg => {
|
|
36
|
+
self.setProgress(arg)
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
hits = result.hits
|
|
40
|
+
rid = result.rid
|
|
41
|
+
} else {
|
|
42
|
+
const result = await queryBlast({
|
|
43
|
+
query: cleanedSeq,
|
|
44
|
+
blastDatabase,
|
|
45
|
+
blastProgram,
|
|
46
|
+
baseUrl,
|
|
47
|
+
onProgress: arg => {
|
|
48
|
+
self.setProgress(arg)
|
|
49
|
+
},
|
|
50
|
+
onRid: r => {
|
|
51
|
+
self.setRid(r)
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
hits = result.hits
|
|
55
|
+
rid = result.rid
|
|
56
|
+
}
|
|
39
57
|
|
|
40
58
|
self.setProgress('Fetching species taxonomy info...')
|
|
41
59
|
const taxids = hits
|
|
@@ -79,7 +97,12 @@ export async function doLaunchBlast({
|
|
|
79
97
|
treeMetadata: treeMetadataJson,
|
|
80
98
|
rid,
|
|
81
99
|
geneId: selectedTranscript?.get('parentId'),
|
|
82
|
-
transcriptId: selectedTranscript?.
|
|
100
|
+
transcriptId: selectedTranscript?.id(),
|
|
101
|
+
transcriptName:
|
|
102
|
+
selectedTranscript?.get('name') ?? selectedTranscript?.get('id'),
|
|
103
|
+
geneName:
|
|
104
|
+
selectedTranscript?.get('gene_name') ??
|
|
105
|
+
selectedTranscript?.get('parentId'),
|
|
83
106
|
})
|
|
84
107
|
|
|
85
108
|
return {
|
package/src/index.ts
CHANGED
|
@@ -36,8 +36,7 @@ export default class MsaViewPlugin extends Plugin {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
rootConfigurationSchema(pluginManager: PluginManager) {
|
|
39
|
+
rootConfigurationSchema = (pluginManager: PluginManager) => {
|
|
41
40
|
return {
|
|
42
41
|
msa: ConfigurationSchema('MSA', {
|
|
43
42
|
datasets: types.maybe(
|
package/src/utils/blastCache.ts
CHANGED
|
@@ -17,6 +17,8 @@ export interface CachedBlastResult {
|
|
|
17
17
|
timestamp: number
|
|
18
18
|
geneId?: string
|
|
19
19
|
transcriptId?: string
|
|
20
|
+
transcriptName?: string
|
|
21
|
+
geneName?: string
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
async function getDB() {
|
|
@@ -36,21 +38,33 @@ function createCacheKey(
|
|
|
36
38
|
proteinSequence: string,
|
|
37
39
|
blastDatabase: string,
|
|
38
40
|
blastProgram: string,
|
|
41
|
+
transcriptId?: string,
|
|
39
42
|
) {
|
|
40
|
-
|
|
43
|
+
const seqKey = proteinSequence.slice(0, 100)
|
|
44
|
+
if (transcriptId) {
|
|
45
|
+
return `${blastDatabase}:${blastProgram}:${transcriptId}:${seqKey}`
|
|
46
|
+
}
|
|
47
|
+
return `${blastDatabase}:${blastProgram}:${seqKey}`
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
export async function getCachedBlastResult({
|
|
44
51
|
proteinSequence,
|
|
45
52
|
blastDatabase,
|
|
46
53
|
blastProgram,
|
|
54
|
+
transcriptId,
|
|
47
55
|
}: {
|
|
48
56
|
proteinSequence: string
|
|
49
57
|
blastDatabase: string
|
|
50
58
|
blastProgram: string
|
|
59
|
+
transcriptId?: string
|
|
51
60
|
}) {
|
|
52
61
|
const db = await getDB()
|
|
53
|
-
const id = createCacheKey(
|
|
62
|
+
const id = createCacheKey(
|
|
63
|
+
proteinSequence,
|
|
64
|
+
blastDatabase,
|
|
65
|
+
blastProgram,
|
|
66
|
+
transcriptId,
|
|
67
|
+
)
|
|
54
68
|
return db.get(STORE_NAME, id)
|
|
55
69
|
}
|
|
56
70
|
|
|
@@ -65,6 +79,8 @@ export async function saveBlastResult({
|
|
|
65
79
|
rid,
|
|
66
80
|
geneId,
|
|
67
81
|
transcriptId,
|
|
82
|
+
transcriptName,
|
|
83
|
+
geneName,
|
|
68
84
|
}: {
|
|
69
85
|
proteinSequence: string
|
|
70
86
|
blastDatabase: string
|
|
@@ -76,9 +92,16 @@ export async function saveBlastResult({
|
|
|
76
92
|
rid: string
|
|
77
93
|
geneId?: string
|
|
78
94
|
transcriptId?: string
|
|
95
|
+
transcriptName?: string
|
|
96
|
+
geneName?: string
|
|
79
97
|
}) {
|
|
80
98
|
const db = await getDB()
|
|
81
|
-
const id = createCacheKey(
|
|
99
|
+
const id = createCacheKey(
|
|
100
|
+
proteinSequence,
|
|
101
|
+
blastDatabase,
|
|
102
|
+
blastProgram,
|
|
103
|
+
transcriptId,
|
|
104
|
+
)
|
|
82
105
|
const entry: CachedBlastResult = {
|
|
83
106
|
id,
|
|
84
107
|
proteinSequence,
|
|
@@ -92,6 +115,8 @@ export async function saveBlastResult({
|
|
|
92
115
|
timestamp: Date.now(),
|
|
93
116
|
geneId,
|
|
94
117
|
transcriptId,
|
|
118
|
+
transcriptName,
|
|
119
|
+
geneName,
|
|
95
120
|
}
|
|
96
121
|
await db.put(STORE_NAME, entry)
|
|
97
122
|
return entry
|
|
@@ -103,6 +128,14 @@ export async function getAllCachedResults() {
|
|
|
103
128
|
return results.toSorted((a, b) => b.timestamp - a.timestamp)
|
|
104
129
|
}
|
|
105
130
|
|
|
131
|
+
export async function getCachedResultsByGeneId(geneId: string) {
|
|
132
|
+
const db = await getDB()
|
|
133
|
+
const results = await db.getAll(STORE_NAME)
|
|
134
|
+
return results
|
|
135
|
+
.filter(r => r.geneId === geneId)
|
|
136
|
+
.toSorted((a, b) => b.timestamp - a.timestamp)
|
|
137
|
+
}
|
|
138
|
+
|
|
106
139
|
export async function deleteCachedResult(id: string) {
|
|
107
140
|
const db = await getDB()
|
|
108
141
|
await db.delete(STORE_NAME, id)
|
package/src/utils/ncbiBlast.ts
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import { jsonfetch, textfetch, timeout } from './fetch'
|
|
2
2
|
import { BlastResults } from './types'
|
|
3
3
|
|
|
4
|
+
export async function queryBlastFromRid({
|
|
5
|
+
rid,
|
|
6
|
+
baseUrl,
|
|
7
|
+
onProgress,
|
|
8
|
+
}: {
|
|
9
|
+
rid: string
|
|
10
|
+
baseUrl: string
|
|
11
|
+
onProgress: (arg: string) => void
|
|
12
|
+
}) {
|
|
13
|
+
onProgress(`Checking BLAST status for RID: ${rid}...`)
|
|
14
|
+
await waitForRid({
|
|
15
|
+
rid,
|
|
16
|
+
onProgress,
|
|
17
|
+
baseUrl,
|
|
18
|
+
})
|
|
19
|
+
const ret = await jsonfetch<BlastResults>(
|
|
20
|
+
`${baseUrl}?CMD=Get&RID=${rid}&FORMAT_TYPE=JSON2_S&FORMAT_OBJECT=Alignment`,
|
|
21
|
+
)
|
|
22
|
+
return {
|
|
23
|
+
rid,
|
|
24
|
+
hits: ret.BlastOutput2[0]?.report.results.search.hits ?? [],
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
4
28
|
export async function queryBlast({
|
|
5
29
|
query,
|
|
6
30
|
blastDatabase,
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.2.
|
|
1
|
+
export const version = '2.2.11'
|