jbrowse-plugin-msaview 2.2.0 → 2.2.2
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/BgzipFastaMsaAdapter.d.ts +10 -0
- package/dist/BgzipFastaMsaAdapter/BgzipFastaMsaAdapter.js +64 -0
- package/dist/BgzipFastaMsaAdapter/BgzipFastaMsaAdapter.js.map +1 -0
- package/dist/BgzipFastaMsaAdapter/configSchema.d.ts +7 -0
- package/dist/BgzipFastaMsaAdapter/configSchema.js +13 -0
- package/dist/BgzipFastaMsaAdapter/configSchema.js.map +1 -0
- package/dist/BgzipFastaMsaAdapter/index.d.ts +2 -0
- package/dist/BgzipFastaMsaAdapter/index.js +15 -0
- package/dist/BgzipFastaMsaAdapter/index.js.map +1 -0
- package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js.map +1 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.d.ts +1 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.js +3 -23
- package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.js.map +1 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/util.d.ts +1 -4
- package/dist/LaunchMsaView/components/EnsemblGeneTree/util.js +1 -37
- package/dist/LaunchMsaView/components/EnsemblGeneTree/util.js.map +1 -1
- package/dist/LaunchMsaView/components/LaunchMsaViewDialog.d.ts +1 -1
- package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js +21 -16
- package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js.map +1 -1
- package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +1 -1
- package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js +12 -8
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js +8 -7
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.js +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.js.map +1 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +87 -63
- package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/consts.d.ts +7 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/consts.js +8 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/consts.js.map +1 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/fetchMSAData.d.ts +12 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/fetchMSAData.js +12 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/fetchMSAData.js.map +1 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/findValidTranscriptId.d.ts +5 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/findValidTranscriptId.js +16 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/findValidTranscriptId.js.map +1 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.d.ts +6 -3
- package/dist/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.js +3 -20
- package/dist/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.js.map +1 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/types.d.ts +7 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/types.js +2 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/types.js.map +1 -0
- package/dist/LaunchMsaView/components/TranscriptSelector.js +2 -2
- package/dist/LaunchMsaView/components/TranscriptSelector.js.map +1 -1
- package/dist/LaunchMsaView/components/calculateProteinSequence.d.ts +2 -2
- package/dist/LaunchMsaView/components/calculateProteinSequence.js +2 -2
- package/dist/LaunchMsaView/components/calculateProteinSequence.js.map +1 -1
- package/dist/LaunchMsaView/components/types.d.ts +1 -0
- package/dist/LaunchMsaView/components/useFeatureSequence.d.ts +3 -7
- package/dist/LaunchMsaView/components/useFeatureSequence.js +9 -62
- package/dist/LaunchMsaView/components/useFeatureSequence.js.map +1 -1
- package/dist/LaunchMsaView/components/useSWRFeatureSequence.d.ts +13 -0
- package/dist/LaunchMsaView/components/useSWRFeatureSequence.js +53 -0
- package/dist/LaunchMsaView/components/useSWRFeatureSequence.js.map +1 -0
- package/dist/LaunchMsaView/index.js +3 -1
- package/dist/LaunchMsaView/index.js.map +1 -1
- package/dist/MsaViewPanel/components/RIDLink.js +1 -1
- package/dist/MsaViewPanel/components/RIDLink.js.map +1 -1
- package/dist/MsaViewPanel/genomeToMSA.js +2 -2
- package/dist/MsaViewPanel/genomeToMSA.js.map +1 -1
- package/dist/MsaViewPanel/model.d.ts +13 -84
- package/dist/MsaViewPanel/model.js +6 -2
- package/dist/MsaViewPanel/model.js.map +1 -1
- package/dist/MsaViewPanel/msaCoordToGenomeCoord.js +39 -14
- package/dist/MsaViewPanel/msaCoordToGenomeCoord.js.map +1 -1
- package/dist/MsaViewPanel/util.js +2 -2
- package/dist/MsaViewPanel/util.js.map +1 -1
- package/dist/components/ExternalLink.js.map +1 -0
- package/dist/components/ReadOnlyTextField2.js.map +1 -0
- package/dist/components/TextField2.js.map +1 -0
- package/dist/index.d.ts +9 -5
- package/dist/index.js +24 -15
- package/dist/index.js.map +1 -1
- package/dist/jbrowse-plugin-msaview.umd.production.min.js +46 -33
- package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
- package/dist/out.js +55367 -0
- package/dist/utils/fetch.d.ts +3 -1
- package/dist/utils/fetch.js +24 -3
- package/dist/utils/fetch.js.map +1 -1
- package/package.json +7 -6
- package/src/BgzipFastaMsaAdapter/BgzipFastaMsaAdapter.ts +78 -0
- package/src/BgzipFastaMsaAdapter/configSchema.ts +18 -0
- package/src/BgzipFastaMsaAdapter/index.ts +18 -0
- package/src/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.tsx +0 -1
- package/src/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.ts +6 -24
- package/src/LaunchMsaView/components/EnsemblGeneTree/util.ts +6 -45
- package/src/LaunchMsaView/components/LaunchMsaViewDialog.tsx +23 -24
- package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +1 -1
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.tsx +13 -8
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.tsx +1 -1
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.tsx +20 -29
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.tsx +1 -1
- package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +154 -68
- package/src/LaunchMsaView/components/PreLoadedMSA/consts.ts +7 -0
- package/src/LaunchMsaView/components/PreLoadedMSA/fetchMSAData.ts +33 -0
- package/src/LaunchMsaView/components/PreLoadedMSA/findValidTranscriptId.ts +25 -0
- package/src/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.ts +7 -26
- package/src/LaunchMsaView/components/PreLoadedMSA/types.ts +8 -0
- package/src/LaunchMsaView/components/TranscriptSelector.tsx +2 -2
- package/src/LaunchMsaView/components/calculateProteinSequence.ts +3 -3
- package/src/LaunchMsaView/components/types.ts +1 -0
- package/src/LaunchMsaView/components/useFeatureSequence.ts +10 -71
- package/src/LaunchMsaView/components/useSWRFeatureSequence.ts +90 -0
- package/src/LaunchMsaView/index.ts +4 -1
- package/src/MsaViewPanel/components/RIDLink.tsx +1 -1
- package/src/MsaViewPanel/genomeToMSA.ts +2 -2
- package/src/MsaViewPanel/model.ts +6 -2
- package/src/MsaViewPanel/msaCoordToGenomeCoord.ts +43 -16
- package/src/MsaViewPanel/util.ts +2 -2
- package/src/index.ts +26 -18
- package/src/utils/fetch.ts +31 -3
- package/dist/ExternalLink.js.map +0 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/fetchGeneList.d.ts +0 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/fetchGeneList.js +0 -12
- package/dist/LaunchMsaView/components/PreLoadedMSA/fetchGeneList.js.map +0 -1
- package/dist/ReadOnlyTextField2.js.map +0 -1
- package/dist/TextField2.js.map +0 -1
- package/src/LaunchMsaView/components/PreLoadedMSA/fetchGeneList.ts +0 -13
- /package/dist/{ExternalLink.d.ts → components/ExternalLink.d.ts} +0 -0
- /package/dist/{ExternalLink.js → components/ExternalLink.js} +0 -0
- /package/dist/{ReadOnlyTextField2.d.ts → components/ReadOnlyTextField2.d.ts} +0 -0
- /package/dist/{ReadOnlyTextField2.js → components/ReadOnlyTextField2.js} +0 -0
- /package/dist/{TextField2.d.ts → components/TextField2.d.ts} +0 -0
- /package/dist/{TextField2.js → components/TextField2.js} +0 -0
- /package/src/{ExternalLink.tsx → components/ExternalLink.tsx} +0 -0
- /package/src/{ReadOnlyTextField2.tsx → components/ReadOnlyTextField2.tsx} +0 -0
- /package/src/{TextField2.tsx → components/TextField2.tsx} +0 -0
|
@@ -1,26 +1,31 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react'
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { readConfObject } from '@jbrowse/core/configuration'
|
|
4
|
+
import { ErrorMessage, LoadingEllipses, SanitizedHTML } from '@jbrowse/core/ui'
|
|
4
5
|
import {
|
|
5
6
|
AbstractTrackModel,
|
|
6
7
|
Feature,
|
|
7
8
|
getContainingView,
|
|
9
|
+
getEnv,
|
|
8
10
|
getSession,
|
|
9
11
|
} from '@jbrowse/core/util'
|
|
10
|
-
import { Button, DialogActions, DialogContent,
|
|
12
|
+
import { Button, DialogActions, DialogContent, MenuItem } from '@mui/material'
|
|
11
13
|
import { observer } from 'mobx-react'
|
|
14
|
+
import useSWR from 'swr'
|
|
12
15
|
import { makeStyles } from 'tss-react/mui'
|
|
13
16
|
|
|
14
|
-
import
|
|
15
|
-
import { preCalculatedLaunchView } from './preCalculatedLaunchView'
|
|
16
|
-
import ExternalLink from '../../../ExternalLink'
|
|
17
|
+
import TextField2 from '../../../components/TextField2'
|
|
17
18
|
import { getGeneDisplayName, getId, getTranscriptFeatures } from '../../util'
|
|
18
19
|
import TranscriptSelector from '../TranscriptSelector'
|
|
19
20
|
import { useFeatureSequence } from '../useFeatureSequence'
|
|
21
|
+
import { swrFlags } from './consts'
|
|
22
|
+
import { fetchMSA, fetchMSAList } from './fetchMSAData'
|
|
23
|
+
import { findValidTranscriptId } from './findValidTranscriptId'
|
|
24
|
+
import { preCalculatedLaunchView } from './preCalculatedLaunchView'
|
|
25
|
+
import { Dataset } from './types'
|
|
20
26
|
|
|
21
27
|
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
22
28
|
|
|
23
|
-
|
|
24
29
|
const useStyles = makeStyles()({
|
|
25
30
|
dialogContent: {
|
|
26
31
|
width: '80em',
|
|
@@ -39,85 +44,166 @@ const PreLoadedMSA = observer(function PreLoadedMSA2({
|
|
|
39
44
|
const session = getSession(model)
|
|
40
45
|
const view = getContainingView(model) as LinearGenomeViewModel
|
|
41
46
|
const { classes } = useStyles()
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (ret) {
|
|
54
|
-
setUserSelection(getId(ret))
|
|
55
|
-
}
|
|
56
|
-
} catch (e) {
|
|
57
|
-
console.error(e)
|
|
58
|
-
setError(e)
|
|
59
|
-
}
|
|
60
|
-
})()
|
|
61
|
-
}, [feature])
|
|
62
|
-
const validSet = new Set(geneNameList)
|
|
63
|
-
const options = getTranscriptFeatures(feature)
|
|
64
|
-
const ret = options.find(val => validSet.has(getId(val)))
|
|
65
|
-
const [userSelection, setUserSelection] = useState(getId(options[0]))
|
|
66
|
-
const selectedTranscript = options.find(val => getId(val) === userSelection)!
|
|
67
|
-
const { proteinSequence, error: error2 } = useFeatureSequence({
|
|
47
|
+
const { pluginManager } = getEnv(model)
|
|
48
|
+
const { assemblyNames } = view
|
|
49
|
+
const transcripts = getTranscriptFeatures(feature)
|
|
50
|
+
const [selectedTranscriptId, setSelectedTranscriptId] = useState(
|
|
51
|
+
getId(transcripts[0]),
|
|
52
|
+
)
|
|
53
|
+
const [viewError, setViewError] = useState<unknown>()
|
|
54
|
+
const selectedTranscript = selectedTranscriptId
|
|
55
|
+
? transcripts.find(val => getId(val) === selectedTranscriptId)
|
|
56
|
+
: undefined
|
|
57
|
+
const { proteinSequence, error: proteinSequenceError } = useFeatureSequence({
|
|
68
58
|
view,
|
|
69
59
|
feature: selectedTranscript,
|
|
70
60
|
})
|
|
71
61
|
|
|
72
|
-
const
|
|
62
|
+
const { jbrowse } = session
|
|
63
|
+
const datasets = readConfObject(jbrowse, ['msa', 'datasets']) as
|
|
64
|
+
| Dataset[]
|
|
65
|
+
| undefined
|
|
66
|
+
const [selectedDatasetId, setSelectedDatasetId] = useState(
|
|
67
|
+
datasets?.[0]?.datasetId,
|
|
68
|
+
)
|
|
69
|
+
const selectedDataset = datasets?.find(d => d.datasetId === selectedDatasetId)
|
|
70
|
+
const {
|
|
71
|
+
data: msaList,
|
|
72
|
+
isLoading: msaListLoading,
|
|
73
|
+
error: msaListFetchError,
|
|
74
|
+
} = useSWR(
|
|
75
|
+
selectedDatasetId ? `${selectedDatasetId}-msa-list` : 'none-msa-list',
|
|
76
|
+
() =>
|
|
77
|
+
selectedDataset
|
|
78
|
+
? fetchMSAList({
|
|
79
|
+
config: selectedDataset.adapter,
|
|
80
|
+
pluginManager,
|
|
81
|
+
})
|
|
82
|
+
: undefined,
|
|
83
|
+
swrFlags,
|
|
84
|
+
)
|
|
85
|
+
const {
|
|
86
|
+
data: msaData,
|
|
87
|
+
isLoading: msaDataLoading,
|
|
88
|
+
error: msaDataFetchError,
|
|
89
|
+
} = useSWR(
|
|
90
|
+
selectedTranscriptId && selectedDatasetId
|
|
91
|
+
? `${selectedTranscriptId}-${selectedTranscriptId}-${msaList?.length}-msa`
|
|
92
|
+
: 'none-msa',
|
|
93
|
+
() =>
|
|
94
|
+
selectedTranscriptId && selectedDataset && msaList
|
|
95
|
+
? fetchMSA({
|
|
96
|
+
msaId: selectedTranscriptId,
|
|
97
|
+
config: selectedDataset.adapter,
|
|
98
|
+
pluginManager,
|
|
99
|
+
})
|
|
100
|
+
: undefined,
|
|
101
|
+
swrFlags,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const validSet = useMemo(() => new Set(msaList), [msaList])
|
|
73
105
|
|
|
106
|
+
// Update selectedTranscriptId when msaList changes
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (msaList && msaList.length > 0) {
|
|
109
|
+
const validId = findValidTranscriptId({
|
|
110
|
+
transcriptsList: transcripts,
|
|
111
|
+
validMsaList: msaList,
|
|
112
|
+
})
|
|
113
|
+
if (validId && validId !== selectedTranscriptId) {
|
|
114
|
+
setSelectedTranscriptId(validId)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}, [msaList, transcripts, selectedTranscriptId])
|
|
118
|
+
|
|
119
|
+
const e =
|
|
120
|
+
msaListFetchError ?? msaDataFetchError ?? proteinSequenceError ?? viewError
|
|
121
|
+
if (e) {
|
|
122
|
+
console.error(e)
|
|
123
|
+
}
|
|
74
124
|
return (
|
|
75
125
|
<>
|
|
76
126
|
<DialogContent className={classes.dialogContent}>
|
|
77
127
|
{e ? <ErrorMessage error={e} /> : null}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
128
|
+
|
|
129
|
+
<TextField2
|
|
130
|
+
select
|
|
131
|
+
label="Select MSA dataset"
|
|
132
|
+
value={selectedDatasetId}
|
|
133
|
+
onChange={event => {
|
|
134
|
+
setSelectedDatasetId(event.target.value)
|
|
135
|
+
}}
|
|
136
|
+
>
|
|
137
|
+
{datasets && datasets.length > 0 ? (
|
|
138
|
+
datasets.map(d => (
|
|
139
|
+
<MenuItem key={d.datasetId} value={d.datasetId}>
|
|
140
|
+
{d.name}
|
|
141
|
+
</MenuItem>
|
|
142
|
+
))
|
|
143
|
+
) : (
|
|
144
|
+
<MenuItem>No MSA datasets found</MenuItem>
|
|
145
|
+
)}
|
|
146
|
+
</TextField2>
|
|
147
|
+
|
|
148
|
+
{selectedDataset ? (
|
|
149
|
+
<div style={{ marginTop: 50 }}>
|
|
150
|
+
{!msaListLoading && msaDataLoading ? (
|
|
151
|
+
<LoadingEllipses
|
|
152
|
+
variant="h6"
|
|
153
|
+
message={`Loading MSA for (${selectedTranscriptId})`}
|
|
154
|
+
/>
|
|
155
|
+
) : null}
|
|
156
|
+
{msaListLoading ? (
|
|
157
|
+
<LoadingEllipses
|
|
158
|
+
variant="h6"
|
|
159
|
+
message={`Loading available MSAs for (${selectedDataset.name})`}
|
|
160
|
+
/>
|
|
161
|
+
) : null}
|
|
162
|
+
|
|
163
|
+
{msaList ? (
|
|
164
|
+
<div>
|
|
165
|
+
<SanitizedHTML html={selectedDataset.description} />
|
|
166
|
+
<TranscriptSelector
|
|
167
|
+
feature={feature}
|
|
168
|
+
options={transcripts}
|
|
169
|
+
selectedTranscriptId={selectedTranscriptId}
|
|
170
|
+
onTranscriptChange={setSelectedTranscriptId}
|
|
171
|
+
proteinSequence={proteinSequence}
|
|
172
|
+
validSet={validSet}
|
|
173
|
+
/>
|
|
174
|
+
</div>
|
|
175
|
+
) : null}
|
|
176
|
+
</div>
|
|
86
177
|
) : null}
|
|
87
|
-
<TranscriptSelector
|
|
88
|
-
feature={feature}
|
|
89
|
-
options={options}
|
|
90
|
-
selectedTranscriptId={userSelection}
|
|
91
|
-
onTranscriptChange={setUserSelection}
|
|
92
|
-
proteinSequence={proteinSequence}
|
|
93
|
-
validSet={validSet}
|
|
94
|
-
/>
|
|
95
178
|
</DialogContent>
|
|
96
179
|
|
|
97
180
|
<DialogActions>
|
|
98
181
|
<Button
|
|
99
182
|
color="primary"
|
|
100
183
|
variant="contained"
|
|
184
|
+
disabled={!selectedTranscript || !msaData?.length}
|
|
101
185
|
onClick={() => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (!ret) {
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
await preCalculatedLaunchView({
|
|
109
|
-
userSelection,
|
|
110
|
-
session,
|
|
111
|
-
newViewTitle: getGeneDisplayName(ret),
|
|
112
|
-
view,
|
|
113
|
-
feature: ret,
|
|
114
|
-
})
|
|
115
|
-
handleClose()
|
|
116
|
-
} catch (e) {
|
|
117
|
-
console.error(e)
|
|
118
|
-
setError(e)
|
|
186
|
+
try {
|
|
187
|
+
if (!selectedTranscript || !msaData) {
|
|
188
|
+
return
|
|
119
189
|
}
|
|
120
|
-
|
|
190
|
+
const querySeqName = `${selectedTranscriptId}_${assemblyNames[0]}`
|
|
191
|
+
preCalculatedLaunchView({
|
|
192
|
+
session,
|
|
193
|
+
newViewTitle: getGeneDisplayName(selectedTranscript),
|
|
194
|
+
view,
|
|
195
|
+
querySeqName,
|
|
196
|
+
feature: selectedTranscript,
|
|
197
|
+
data: {
|
|
198
|
+
msa: msaData
|
|
199
|
+
.map(r => `>${r.get('refName')}\n${r.get('seq')}`)
|
|
200
|
+
.join('\n'),
|
|
201
|
+
},
|
|
202
|
+
})
|
|
203
|
+
handleClose()
|
|
204
|
+
} catch (e) {
|
|
205
|
+
setViewError(e)
|
|
206
|
+
}
|
|
121
207
|
}}
|
|
122
208
|
>
|
|
123
209
|
Submit
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AnyConfigurationModel } from '@jbrowse/core/configuration'
|
|
2
|
+
import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache'
|
|
3
|
+
import { Feature } from '@jbrowse/core/util'
|
|
4
|
+
|
|
5
|
+
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
6
|
+
|
|
7
|
+
export async function fetchMSAList({
|
|
8
|
+
config,
|
|
9
|
+
pluginManager,
|
|
10
|
+
}: {
|
|
11
|
+
config: AnyConfigurationModel
|
|
12
|
+
pluginManager: PluginManager
|
|
13
|
+
}): Promise<string[]> {
|
|
14
|
+
const result = await getAdapter(pluginManager, 'msa', config)
|
|
15
|
+
|
|
16
|
+
// @ts-expect-error
|
|
17
|
+
return result.dataAdapter.getMSAList()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function fetchMSA({
|
|
21
|
+
config,
|
|
22
|
+
pluginManager,
|
|
23
|
+
msaId,
|
|
24
|
+
}: {
|
|
25
|
+
config: AnyConfigurationModel
|
|
26
|
+
pluginManager: PluginManager
|
|
27
|
+
msaId: string
|
|
28
|
+
}): Promise<Feature[]> {
|
|
29
|
+
const result = await getAdapter(pluginManager, 'msa', config)
|
|
30
|
+
|
|
31
|
+
// @ts-expect-error
|
|
32
|
+
return result.dataAdapter.getMSA(msaId)
|
|
33
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getId } from '../../util'
|
|
2
|
+
|
|
3
|
+
import type { Feature } from '@jbrowse/core/util'
|
|
4
|
+
|
|
5
|
+
// Function to find a valid transcript ID that exists in the MSA list
|
|
6
|
+
export function findValidTranscriptId({
|
|
7
|
+
transcriptsList,
|
|
8
|
+
validMsaList,
|
|
9
|
+
}: {
|
|
10
|
+
transcriptsList: Feature[]
|
|
11
|
+
validMsaList?: string[]
|
|
12
|
+
}) {
|
|
13
|
+
if (!validMsaList || validMsaList.length === 0) {
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Try to find a transcript ID that exists in the MSA list
|
|
18
|
+
for (const transcript of transcriptsList) {
|
|
19
|
+
const id = getId(transcript)
|
|
20
|
+
if (id && validMsaList.includes(id)) {
|
|
21
|
+
return id
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
@@ -1,38 +1,27 @@
|
|
|
1
1
|
import { AbstractSessionModel, Feature } from '@jbrowse/core/util'
|
|
2
|
-
import { ungzip } from 'pako'
|
|
3
2
|
|
|
4
3
|
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
const res = await fetch(url)
|
|
8
|
-
if (!res.ok) {
|
|
9
|
-
throw new Error(`HTTP ${res.status} fetching ${await res.text()}`)
|
|
10
|
-
}
|
|
11
|
-
const data = await res.arrayBuffer()
|
|
12
|
-
return new TextDecoder().decode(ungzip(data))
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export async function preCalculatedLaunchView({
|
|
16
|
-
userSelection,
|
|
5
|
+
export function preCalculatedLaunchView({
|
|
17
6
|
session,
|
|
18
7
|
newViewTitle,
|
|
19
8
|
view,
|
|
20
9
|
feature,
|
|
10
|
+
data,
|
|
11
|
+
querySeqName,
|
|
21
12
|
}: {
|
|
13
|
+
data: { msa: string }
|
|
22
14
|
session: AbstractSessionModel
|
|
23
|
-
userSelection: string
|
|
24
15
|
newViewTitle: string
|
|
25
16
|
view: LinearGenomeViewModel
|
|
26
17
|
feature: Feature
|
|
18
|
+
querySeqName: string
|
|
27
19
|
}) {
|
|
28
|
-
const d = await myfetch(
|
|
29
|
-
`https://jbrowse.org/demos/msaview/knownCanonical/${userSelection}.mfa.gz`,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
20
|
session.addView('MsaView', {
|
|
33
21
|
type: 'MsaView',
|
|
34
22
|
displayName: newViewTitle,
|
|
35
23
|
treeAreaWidth: 200,
|
|
24
|
+
querySeqName,
|
|
36
25
|
treeWidth: 100,
|
|
37
26
|
drawNodeBubbles: false,
|
|
38
27
|
labelsAlignRight: true,
|
|
@@ -40,15 +29,7 @@ export async function preCalculatedLaunchView({
|
|
|
40
29
|
colWidth: 10,
|
|
41
30
|
rowHeight: 12,
|
|
42
31
|
colorSchemeName: 'percent_identity_dynamic',
|
|
43
|
-
|
|
44
|
-
uri: 'https://hgdownload.soe.ucsc.edu/goldenPath/hg38/multiz100way/hg38.100way.nh',
|
|
45
|
-
},
|
|
46
|
-
treeMetadataFilehandle: {
|
|
47
|
-
uri: 'https://s3.amazonaws.com/jbrowse.org/demos/app/species.json',
|
|
48
|
-
},
|
|
49
|
-
data: {
|
|
50
|
-
msa: d,
|
|
51
|
-
},
|
|
32
|
+
data,
|
|
52
33
|
connectedViewId: view.id,
|
|
53
34
|
connectedFeature: feature.toJSON(),
|
|
54
35
|
})
|
|
@@ -4,8 +4,8 @@ import { Feature } from '@jbrowse/core/util'
|
|
|
4
4
|
import { Button, MenuItem } from '@mui/material'
|
|
5
5
|
import { makeStyles } from 'tss-react/mui'
|
|
6
6
|
|
|
7
|
-
import ReadOnlyTextField2 from '../../ReadOnlyTextField2'
|
|
8
|
-
import TextField2 from '../../TextField2'
|
|
7
|
+
import ReadOnlyTextField2 from '../../components/ReadOnlyTextField2'
|
|
8
|
+
import TextField2 from '../../components/TextField2'
|
|
9
9
|
import {
|
|
10
10
|
getGeneDisplayName,
|
|
11
11
|
getId,
|
|
@@ -41,13 +41,13 @@ export function revlist(list: Feat[], seqlen: number) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export function getProteinSequenceFromFeature({
|
|
44
|
-
|
|
44
|
+
feature,
|
|
45
45
|
seq,
|
|
46
46
|
}: {
|
|
47
47
|
seq: string
|
|
48
|
-
|
|
48
|
+
feature: Feature
|
|
49
49
|
}) {
|
|
50
|
-
const { subfeatures, start, strand } =
|
|
50
|
+
const { subfeatures, start, strand } = feature.toJSON()
|
|
51
51
|
const cds = dedupe(
|
|
52
52
|
subfeatures
|
|
53
53
|
?.toSorted((a, b) => a.start - b.start)
|
|
@@ -1,18 +1,8 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react'
|
|
2
|
-
|
|
3
|
-
import { getSession } from '@jbrowse/core/util'
|
|
4
|
-
|
|
5
1
|
import { getProteinSequenceFromFeature } from './calculateProteinSequence'
|
|
6
|
-
import {
|
|
2
|
+
import { useSWRFeatureSequence } from './useSWRFeatureSequence'
|
|
7
3
|
|
|
8
|
-
import type { SeqState } from './types'
|
|
9
4
|
import type { Feature } from '@jbrowse/core/util'
|
|
10
5
|
|
|
11
|
-
export interface ErrorState {
|
|
12
|
-
error: string
|
|
13
|
-
}
|
|
14
|
-
const BPLIMIT = 500_000
|
|
15
|
-
|
|
16
6
|
export function useFeatureSequence({
|
|
17
7
|
view,
|
|
18
8
|
feature,
|
|
@@ -20,73 +10,22 @@ export function useFeatureSequence({
|
|
|
20
10
|
forceLoad = true,
|
|
21
11
|
}: {
|
|
22
12
|
view: { assemblyNames?: string[] } | undefined
|
|
23
|
-
feature
|
|
13
|
+
feature?: Feature
|
|
24
14
|
upDownBp?: number
|
|
25
15
|
forceLoad?: boolean
|
|
26
16
|
}) {
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
;(async () => {
|
|
34
|
-
try {
|
|
35
|
-
setError(undefined)
|
|
36
|
-
setSequence(undefined)
|
|
37
|
-
const session = getSession(view)
|
|
38
|
-
const { start, end, refName } = feature.toJSON() as {
|
|
39
|
-
start: number
|
|
40
|
-
end: number
|
|
41
|
-
refName: string
|
|
42
|
-
}
|
|
43
|
-
if (!assemblyName) {
|
|
44
|
-
throw new Error('No assembly found')
|
|
45
|
-
}
|
|
46
|
-
if (!forceLoad && end - start > BPLIMIT) {
|
|
47
|
-
setSequence({
|
|
48
|
-
error: `Genomic sequence larger than ${BPLIMIT}bp, use "force load" button to display`,
|
|
49
|
-
})
|
|
50
|
-
} else {
|
|
51
|
-
const b = start - upDownBp
|
|
52
|
-
const e = end + upDownBp
|
|
53
|
-
setSequence({
|
|
54
|
-
seq: await fetchSeq({
|
|
55
|
-
start,
|
|
56
|
-
end,
|
|
57
|
-
refName,
|
|
58
|
-
assemblyName,
|
|
59
|
-
session,
|
|
60
|
-
}),
|
|
61
|
-
upstream: await fetchSeq({
|
|
62
|
-
start: Math.max(0, b),
|
|
63
|
-
end: start,
|
|
64
|
-
refName,
|
|
65
|
-
assemblyName,
|
|
66
|
-
session,
|
|
67
|
-
}),
|
|
68
|
-
downstream: await fetchSeq({
|
|
69
|
-
start: end,
|
|
70
|
-
end: e,
|
|
71
|
-
refName,
|
|
72
|
-
assemblyName,
|
|
73
|
-
session,
|
|
74
|
-
}),
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
} catch (e) {
|
|
78
|
-
console.error(e)
|
|
79
|
-
setError(e)
|
|
80
|
-
}
|
|
81
|
-
})()
|
|
82
|
-
}
|
|
83
|
-
}, [feature, view, upDownBp, assemblyName, forceLoad])
|
|
17
|
+
const { sequence, error } = useSWRFeatureSequence({
|
|
18
|
+
view,
|
|
19
|
+
feature,
|
|
20
|
+
upDownBp,
|
|
21
|
+
forceLoad,
|
|
22
|
+
})
|
|
84
23
|
|
|
85
24
|
const proteinSequence =
|
|
86
|
-
sequence && !('error' in sequence)
|
|
25
|
+
sequence && !('error' in sequence) && feature
|
|
87
26
|
? getProteinSequenceFromFeature({
|
|
88
27
|
seq: sequence.seq,
|
|
89
|
-
|
|
28
|
+
feature,
|
|
90
29
|
})
|
|
91
30
|
: ''
|
|
92
31
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { getSession } from '@jbrowse/core/util'
|
|
2
|
+
import useSWR from 'swr'
|
|
3
|
+
|
|
4
|
+
import { fetchSeq } from './fetchSeq'
|
|
5
|
+
|
|
6
|
+
import type { SeqState } from './types'
|
|
7
|
+
import type { Feature } from '@jbrowse/core/util'
|
|
8
|
+
|
|
9
|
+
const BPLIMIT = 500_000
|
|
10
|
+
|
|
11
|
+
async function featureSequenceFetcher({
|
|
12
|
+
feature,
|
|
13
|
+
assemblyName,
|
|
14
|
+
upDownBp,
|
|
15
|
+
view,
|
|
16
|
+
forceLoad,
|
|
17
|
+
}: {
|
|
18
|
+
feature: Feature
|
|
19
|
+
assemblyName: string
|
|
20
|
+
upDownBp: number
|
|
21
|
+
view: { assemblyNames?: string[] }
|
|
22
|
+
forceLoad: boolean
|
|
23
|
+
}): Promise<SeqState | undefined> {
|
|
24
|
+
const session = getSession(view)
|
|
25
|
+
const { start, end, refName } = feature.toJSON() as {
|
|
26
|
+
start: number
|
|
27
|
+
end: number
|
|
28
|
+
refName: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const b = start - upDownBp
|
|
32
|
+
const e = end + upDownBp
|
|
33
|
+
const [seq, upstream, downstream] = await Promise.all([
|
|
34
|
+
fetchSeq({
|
|
35
|
+
start,
|
|
36
|
+
end,
|
|
37
|
+
refName,
|
|
38
|
+
assemblyName,
|
|
39
|
+
session,
|
|
40
|
+
}),
|
|
41
|
+
fetchSeq({
|
|
42
|
+
start: Math.max(0, b),
|
|
43
|
+
end: start,
|
|
44
|
+
refName,
|
|
45
|
+
assemblyName,
|
|
46
|
+
session,
|
|
47
|
+
}),
|
|
48
|
+
fetchSeq({
|
|
49
|
+
start: end,
|
|
50
|
+
end: e,
|
|
51
|
+
refName,
|
|
52
|
+
assemblyName,
|
|
53
|
+
session,
|
|
54
|
+
}),
|
|
55
|
+
])
|
|
56
|
+
return { seq, upstream, downstream }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function useSWRFeatureSequence({
|
|
60
|
+
view,
|
|
61
|
+
feature,
|
|
62
|
+
upDownBp = 0,
|
|
63
|
+
forceLoad = true,
|
|
64
|
+
}: {
|
|
65
|
+
view: { assemblyNames?: string[] } | undefined
|
|
66
|
+
feature?: Feature
|
|
67
|
+
upDownBp?: number
|
|
68
|
+
forceLoad?: boolean
|
|
69
|
+
}) {
|
|
70
|
+
const assemblyName = view?.assemblyNames?.[0]
|
|
71
|
+
const { data, error } = useSWR(
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
73
|
+
feature && assemblyName && view
|
|
74
|
+
? [feature.id(), assemblyName, upDownBp, forceLoad, 'feature-sequence']
|
|
75
|
+
: null,
|
|
76
|
+
() =>
|
|
77
|
+
featureSequenceFetcher({
|
|
78
|
+
feature: feature!,
|
|
79
|
+
assemblyName: assemblyName!,
|
|
80
|
+
upDownBp,
|
|
81
|
+
view: view!,
|
|
82
|
+
forceLoad,
|
|
83
|
+
}),
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
sequence: data,
|
|
88
|
+
error,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -24,9 +24,12 @@ function extendStateModel(stateModel: IAnyModelType) {
|
|
|
24
24
|
contextMenuItems() {
|
|
25
25
|
const feature = self.contextMenuFeature
|
|
26
26
|
const track = getContainingTrack(self)
|
|
27
|
+
const featureType = feature?.get('type')
|
|
28
|
+
const showMsaMenuItem =
|
|
29
|
+
feature && ['gene', 'mRNA', 'transcript'].includes(featureType)
|
|
27
30
|
return [
|
|
28
31
|
...superContextMenuItems(),
|
|
29
|
-
...(
|
|
32
|
+
...(showMsaMenuItem
|
|
30
33
|
? [
|
|
31
34
|
{
|
|
32
35
|
label: 'Launch MSA view',
|
|
@@ -5,7 +5,7 @@ import { checkHovered } from './util'
|
|
|
5
5
|
|
|
6
6
|
export function genomeToMSA({ model }: { model: JBrowsePluginMsaViewModel }) {
|
|
7
7
|
const { hovered } = getSession(model)
|
|
8
|
-
const { transcriptToMsaMap, connectedView } = model
|
|
8
|
+
const { querySeqName, transcriptToMsaMap, connectedView } = model
|
|
9
9
|
if (
|
|
10
10
|
connectedView?.initialized &&
|
|
11
11
|
transcriptToMsaMap &&
|
|
@@ -15,7 +15,7 @@ export function genomeToMSA({ model }: { model: JBrowsePluginMsaViewModel }) {
|
|
|
15
15
|
const { g2p } = transcriptToMsaMap
|
|
16
16
|
const ret = g2p[hoverCoord]
|
|
17
17
|
if (ret !== undefined) {
|
|
18
|
-
return model.seqCoordToRowSpecificGlobalCoord(
|
|
18
|
+
return model.seqCoordToRowSpecificGlobalCoord(querySeqName, ret + 1)
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
return undefined
|