jbrowse-plugin-msaview 2.3.5 → 2.4.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 +15 -216
- package/dist/AddHighlightModel/GenomeMouseoverHighlight.js +4 -15
- package/dist/AddHighlightModel/GenomeMouseoverHighlight.js.map +1 -1
- package/dist/AddHighlightModel/MsaToGenomeHighlight.js +5 -8
- package/dist/AddHighlightModel/MsaToGenomeHighlight.js.map +1 -1
- package/dist/AddHighlightModel/util.d.ts +3 -0
- package/dist/AddHighlightModel/util.js +3 -0
- package/dist/AddHighlightModel/util.js.map +1 -1
- package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js +3 -8
- package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js.map +1 -1
- package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +26 -14
- package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js +16 -7
- package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js +6 -7
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js +4 -4
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js +8 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js +15 -7
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.js +8 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.d.ts +4 -4
- package/dist/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.js +2 -2
- package/dist/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.d.ts +4 -0
- package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.js +2 -0
- package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.js.map +1 -1
- package/dist/LaunchMsaView/components/NCBIBlastQuery/useCachedBlastResults.js +3 -0
- package/dist/LaunchMsaView/components/NCBIBlastQuery/useCachedBlastResults.js.map +1 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +17 -23
- package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/types.d.ts +1 -0
- package/dist/LaunchMsaView/components/PreLoadedMSA/types.js +4 -1
- package/dist/LaunchMsaView/components/PreLoadedMSA/types.js.map +1 -1
- package/dist/LaunchMsaView/components/TabPanel.js +1 -1
- package/dist/LaunchMsaView/components/TabPanel.js.map +1 -1
- package/dist/LaunchMsaView/components/TranscriptSelector.js +7 -3
- package/dist/LaunchMsaView/components/TranscriptSelector.js.map +1 -1
- package/dist/LaunchMsaView/components/types.d.ts +0 -3
- package/dist/LaunchMsaView/components/useFeatureSequence.d.ts +4 -4
- package/dist/LaunchMsaView/components/useFeatureSequence.js +2 -4
- package/dist/LaunchMsaView/components/useFeatureSequence.js.map +1 -1
- package/dist/LaunchMsaView/components/useSWRFeatureSequence.d.ts +4 -5
- package/dist/LaunchMsaView/components/useSWRFeatureSequence.js +11 -30
- package/dist/LaunchMsaView/components/useSWRFeatureSequence.js.map +1 -1
- package/dist/MsaViewPanel/afterCreateAutoruns.js +10 -25
- package/dist/MsaViewPanel/afterCreateAutoruns.js.map +1 -1
- package/dist/MsaViewPanel/components/ConnectStructureDialog.js +15 -10
- package/dist/MsaViewPanel/components/ConnectStructureDialog.js.map +1 -1
- package/dist/MsaViewPanel/components/LoadingBLAST.js +2 -3
- package/dist/MsaViewPanel/components/LoadingBLAST.js.map +1 -1
- package/dist/MsaViewPanel/components/MsaViewPanel.js +8 -1
- package/dist/MsaViewPanel/components/MsaViewPanel.js.map +1 -1
- package/dist/MsaViewPanel/model.d.ts +6 -13
- package/dist/MsaViewPanel/model.js +15 -26
- package/dist/MsaViewPanel/model.js.map +1 -1
- package/dist/MsaViewPanel/msaDataStore.d.ts +0 -1
- package/dist/MsaViewPanel/msaDataStore.js +0 -9
- package/dist/MsaViewPanel/msaDataStore.js.map +1 -1
- package/dist/MsaViewPanel/pairwiseAlignment.js +6 -6
- package/dist/MsaViewPanel/pairwiseAlignment.js.map +1 -1
- package/dist/MsaViewPanel/structureConnection.d.ts +28 -4
- package/dist/MsaViewPanel/structureConnection.js +10 -6
- package/dist/MsaViewPanel/structureConnection.js.map +1 -1
- package/dist/MsaViewPanel/structureConnection.test.js +1 -19
- package/dist/MsaViewPanel/structureConnection.test.js.map +1 -1
- package/dist/jbrowse-plugin-msaview.umd.production.min.js +25 -27
- package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
- package/dist/utils/blastCache.d.ts +7 -13
- package/dist/utils/blastCache.js +0 -12
- package/dist/utils/blastCache.js.map +1 -1
- package/dist/utils/msa.d.ts +2 -1
- package/dist/utils/msa.js +0 -3
- package/dist/utils/msa.js.map +1 -1
- package/dist/utils/ncbiBlast.d.ts +3 -2
- package/dist/utils/ncbiBlast.js +1 -1
- package/dist/utils/ncbiBlast.js.map +1 -1
- package/dist/utils/taxonomyNames.js +9 -4
- package/dist/utils/taxonomyNames.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +19 -19
- package/src/AddHighlightModel/GenomeMouseoverHighlight.tsx +7 -22
- package/src/AddHighlightModel/MsaToGenomeHighlight.tsx +10 -10
- package/src/AddHighlightModel/util.ts +6 -0
- package/src/LaunchMsaView/components/LaunchMsaViewDialog.tsx +3 -16
- package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +30 -19
- package/src/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.tsx +17 -9
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.tsx +14 -18
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.tsx +4 -10
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.tsx +9 -1
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.tsx +15 -8
- package/src/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.tsx +9 -1
- package/src/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.ts +6 -6
- package/src/LaunchMsaView/components/NCBIBlastQuery/consts.ts +7 -0
- package/src/LaunchMsaView/components/NCBIBlastQuery/useCachedBlastResults.ts +3 -0
- package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +23 -29
- package/src/LaunchMsaView/components/PreLoadedMSA/types.ts +6 -0
- package/src/LaunchMsaView/components/TabPanel.tsx +1 -1
- package/src/LaunchMsaView/components/TranscriptSelector.tsx +7 -3
- package/src/LaunchMsaView/components/types.ts +0 -3
- package/src/LaunchMsaView/components/useFeatureSequence.ts +1 -7
- package/src/LaunchMsaView/components/useSWRFeatureSequence.ts +10 -37
- package/src/MsaViewPanel/afterCreateAutoruns.ts +13 -39
- package/src/MsaViewPanel/components/ConnectStructureDialog.tsx +23 -25
- package/src/MsaViewPanel/components/LoadingBLAST.tsx +4 -3
- package/src/MsaViewPanel/components/MsaViewPanel.tsx +9 -1
- package/src/MsaViewPanel/model.ts +31 -39
- package/src/MsaViewPanel/msaDataStore.ts +0 -9
- package/src/MsaViewPanel/pairwiseAlignment.ts +6 -6
- package/src/MsaViewPanel/structureConnection.test.ts +0 -21
- package/src/MsaViewPanel/structureConnection.ts +30 -7
- package/src/utils/blastCache.ts +14 -37
- package/src/utils/msa.ts +5 -6
- package/src/utils/ncbiBlast.ts +9 -5
- package/src/utils/taxonomyNames.ts +13 -4
- package/src/version.ts +1 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.d.ts +0 -8
- package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js +0 -70
- package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js.map +0 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeLaunchView.d.ts +0 -13
- package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeLaunchView.js +0 -12
- package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeLaunchView.js.map +0 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.d.ts +0 -6
- package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.js +0 -25
- package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.js.map +0 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/gatherSequencesFromTree.d.ts +0 -2
- package/dist/LaunchMsaView/components/EnsemblGeneTree/gatherSequencesFromTree.js +0 -20
- package/dist/LaunchMsaView/components/EnsemblGeneTree/gatherSequencesFromTree.js.map +0 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/types.d.ts +0 -24
- package/dist/LaunchMsaView/components/EnsemblGeneTree/types.js +0 -2
- package/dist/LaunchMsaView/components/EnsemblGeneTree/types.js.map +0 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.d.ts +0 -10
- package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.js +0 -11
- package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.js.map +0 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/util.d.ts +0 -1
- package/dist/LaunchMsaView/components/EnsemblGeneTree/util.js +0 -2
- package/dist/LaunchMsaView/components/EnsemblGeneTree/util.js.map +0 -1
- package/src/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.tsx +0 -123
- package/src/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeLaunchView.ts +0 -30
- package/src/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.ts +0 -47
- package/src/LaunchMsaView/components/EnsemblGeneTree/gatherSequencesFromTree.ts +0 -22
- package/src/LaunchMsaView/components/EnsemblGeneTree/types.ts +0 -28
- package/src/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.ts +0 -17
- package/src/LaunchMsaView/components/EnsemblGeneTree/util.ts +0 -6
|
@@ -8,27 +8,14 @@ import {
|
|
|
8
8
|
retrieveMsaData,
|
|
9
9
|
storeMsaData,
|
|
10
10
|
} from './msaDataStore'
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
gappedToUngappedPosition,
|
|
13
|
+
getProteinViews,
|
|
14
|
+
} from './structureConnection'
|
|
12
15
|
import { getUniprotIdFromAlphaFoldUrl } from './util'
|
|
13
16
|
|
|
14
17
|
import type { JBrowsePluginMsaViewModel } from './model'
|
|
15
18
|
|
|
16
|
-
interface ProteinView {
|
|
17
|
-
type: 'ProteinView'
|
|
18
|
-
id: string
|
|
19
|
-
structures: {
|
|
20
|
-
connectedViewId?: string
|
|
21
|
-
uniprotId?: string
|
|
22
|
-
structureSequences?: unknown[]
|
|
23
|
-
hoverGenomeHighlights?: { start: number; end: number }[]
|
|
24
|
-
}[]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function isProteinView(view: unknown): view is ProteinView {
|
|
28
|
-
const v = view as Record<string, unknown>
|
|
29
|
-
return v.type === 'ProteinView' && Array.isArray(v.structures)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
19
|
export function loadStoredData(self: JBrowsePluginMsaViewModel) {
|
|
33
20
|
const { dataStoreId, rows } = self
|
|
34
21
|
if (dataStoreId && rows.length === 0) {
|
|
@@ -57,8 +44,7 @@ export function loadStoredData(self: JBrowsePluginMsaViewModel) {
|
|
|
57
44
|
export function storeDataToIndexedDB(self: JBrowsePluginMsaViewModel) {
|
|
58
45
|
const { rows, dataStoreId } = self
|
|
59
46
|
if (rows.length > 0 && !dataStoreId) {
|
|
60
|
-
|
|
61
|
-
if (hasFilehandle) {
|
|
47
|
+
if (self.msaFilehandle || self.treeFilehandle) {
|
|
62
48
|
return
|
|
63
49
|
}
|
|
64
50
|
|
|
@@ -179,7 +165,7 @@ export function highlightConnectedStructures(self: JBrowsePluginMsaViewModel) {
|
|
|
179
165
|
}
|
|
180
166
|
|
|
181
167
|
for (const conn of connectedProteinViews) {
|
|
182
|
-
const structure = conn.proteinView
|
|
168
|
+
const structure = conn.proteinView.structures[conn.structureIdx]
|
|
183
169
|
if (!structure) {
|
|
184
170
|
continue
|
|
185
171
|
}
|
|
@@ -210,25 +196,19 @@ export function highlightConnectedStructures(self: JBrowsePluginMsaViewModel) {
|
|
|
210
196
|
}
|
|
211
197
|
|
|
212
198
|
export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
|
|
213
|
-
const { views } = getSession(self)
|
|
214
199
|
const { connectedViewId, uniprotId, rows, connectedStructures } = self
|
|
215
200
|
|
|
216
201
|
if (!uniprotId || rows.length === 0) {
|
|
217
202
|
return
|
|
218
203
|
}
|
|
219
204
|
|
|
220
|
-
for (const view of views) {
|
|
221
|
-
if (!isProteinView(view)) {
|
|
222
|
-
continue
|
|
223
|
-
}
|
|
224
|
-
const v = view
|
|
225
|
-
|
|
205
|
+
for (const view of getProteinViews(getSession(self).views)) {
|
|
226
206
|
for (
|
|
227
207
|
let structureIdx = 0;
|
|
228
|
-
structureIdx <
|
|
208
|
+
structureIdx < view.structures.length;
|
|
229
209
|
structureIdx++
|
|
230
210
|
) {
|
|
231
|
-
const structure =
|
|
211
|
+
const structure = view.structures[structureIdx]
|
|
232
212
|
if (!structure) {
|
|
233
213
|
continue
|
|
234
214
|
}
|
|
@@ -242,7 +222,7 @@ export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
|
|
|
242
222
|
}
|
|
243
223
|
|
|
244
224
|
const alreadyConnected = connectedStructures.some(
|
|
245
|
-
c => c.proteinViewId ===
|
|
225
|
+
c => c.proteinViewId === view.id && c.structureIdx === structureIdx,
|
|
246
226
|
)
|
|
247
227
|
if (alreadyConnected) {
|
|
248
228
|
continue
|
|
@@ -253,7 +233,7 @@ export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
|
|
|
253
233
|
}
|
|
254
234
|
|
|
255
235
|
try {
|
|
256
|
-
self.connectToStructure(
|
|
236
|
+
self.connectToStructure(view.id, structureIdx)
|
|
257
237
|
} catch (e) {
|
|
258
238
|
console.error('Failed to auto-connect to ProteinView:', e)
|
|
259
239
|
}
|
|
@@ -262,7 +242,6 @@ export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
|
|
|
262
242
|
}
|
|
263
243
|
|
|
264
244
|
export function observeProteinHighlights(self: JBrowsePluginMsaViewModel) {
|
|
265
|
-
const { views } = getSession(self)
|
|
266
245
|
const { connectedViewId, transcriptToMsaMap, querySeqName } = self
|
|
267
246
|
|
|
268
247
|
if (!connectedViewId || !transcriptToMsaMap) {
|
|
@@ -271,13 +250,8 @@ export function observeProteinHighlights(self: JBrowsePluginMsaViewModel) {
|
|
|
271
250
|
|
|
272
251
|
const columns = new Set<number>()
|
|
273
252
|
|
|
274
|
-
for (const view of views) {
|
|
275
|
-
|
|
276
|
-
continue
|
|
277
|
-
}
|
|
278
|
-
const v = view
|
|
279
|
-
|
|
280
|
-
for (const structure of v.structures) {
|
|
253
|
+
for (const view of getProteinViews(getSession(self).views)) {
|
|
254
|
+
for (const structure of view.structures) {
|
|
281
255
|
if (structure.connectedViewId !== connectedViewId) {
|
|
282
256
|
continue
|
|
283
257
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
|
|
3
|
-
import { Dialog } from '@jbrowse/core/ui'
|
|
3
|
+
import { Dialog, ErrorMessage } from '@jbrowse/core/ui'
|
|
4
4
|
import { getSession } from '@jbrowse/core/util'
|
|
5
5
|
import {
|
|
6
6
|
Button,
|
|
@@ -13,9 +13,18 @@ import {
|
|
|
13
13
|
Typography,
|
|
14
14
|
} from '@mui/material'
|
|
15
15
|
import { observer } from 'mobx-react'
|
|
16
|
+
import { makeStyles } from 'tss-react/mui'
|
|
17
|
+
|
|
18
|
+
import { getProteinViews } from '../structureConnection'
|
|
16
19
|
|
|
17
20
|
import type { JBrowsePluginMsaViewModel } from '../model'
|
|
18
21
|
|
|
22
|
+
const useStyles = makeStyles()(theme => ({
|
|
23
|
+
formControl: {
|
|
24
|
+
marginBottom: theme.spacing(2),
|
|
25
|
+
},
|
|
26
|
+
}))
|
|
27
|
+
|
|
19
28
|
const ConnectStructureDialog = observer(function ConnectStructureDialog({
|
|
20
29
|
model,
|
|
21
30
|
handleClose,
|
|
@@ -23,23 +32,18 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
|
|
|
23
32
|
model: JBrowsePluginMsaViewModel
|
|
24
33
|
handleClose: () => void
|
|
25
34
|
}) {
|
|
35
|
+
const { classes } = useStyles()
|
|
26
36
|
const session = getSession(model)
|
|
27
37
|
const [selectedViewId, setSelectedViewId] = useState('')
|
|
28
38
|
const [selectedStructureIdx, setSelectedStructureIdx] = useState(0)
|
|
29
39
|
const [selectedMsaRow, setSelectedMsaRow] = useState(model.querySeqName)
|
|
30
40
|
const [error, setError] = useState<string>()
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const proteinViews = session.views.filter(
|
|
35
|
-
(v: any) => v.type === 'ProteinView',
|
|
36
|
-
) as any[]
|
|
42
|
+
const proteinViews = getProteinViews(session.views)
|
|
37
43
|
|
|
38
|
-
// Get structures for the selected view
|
|
39
44
|
const selectedView = proteinViews.find(v => v.id === selectedViewId)
|
|
40
45
|
const structures = selectedView?.structures ?? []
|
|
41
46
|
|
|
42
|
-
// Get MSA row names
|
|
43
47
|
const msaRowNames = model.rows.map(r => r[0])
|
|
44
48
|
|
|
45
49
|
const handleConnect = () => {
|
|
@@ -75,7 +79,7 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
|
|
|
75
79
|
</Typography>
|
|
76
80
|
) : (
|
|
77
81
|
<>
|
|
78
|
-
<FormControl fullWidth
|
|
82
|
+
<FormControl fullWidth className={classes.formControl}>
|
|
79
83
|
<InputLabel>Protein View</InputLabel>
|
|
80
84
|
<Select
|
|
81
85
|
value={selectedViewId}
|
|
@@ -93,8 +97,8 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
|
|
|
93
97
|
</Select>
|
|
94
98
|
</FormControl>
|
|
95
99
|
|
|
96
|
-
{structures.length > 1
|
|
97
|
-
<FormControl fullWidth
|
|
100
|
+
{structures.length > 1 ? (
|
|
101
|
+
<FormControl fullWidth className={classes.formControl}>
|
|
98
102
|
<InputLabel>Structure</InputLabel>
|
|
99
103
|
<Select
|
|
100
104
|
value={selectedStructureIdx}
|
|
@@ -103,18 +107,16 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
|
|
|
103
107
|
setSelectedStructureIdx(e.target.value)
|
|
104
108
|
}}
|
|
105
109
|
>
|
|
106
|
-
{structures.map(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
),
|
|
112
|
-
)}
|
|
110
|
+
{structures.map((structure, idx) => (
|
|
111
|
+
<MenuItem key={idx} value={idx}>
|
|
112
|
+
{structure.url ?? `Structure ${idx + 1}`}
|
|
113
|
+
</MenuItem>
|
|
114
|
+
))}
|
|
113
115
|
</Select>
|
|
114
116
|
</FormControl>
|
|
115
|
-
)}
|
|
117
|
+
) : null}
|
|
116
118
|
|
|
117
|
-
<FormControl fullWidth
|
|
119
|
+
<FormControl fullWidth className={classes.formControl}>
|
|
118
120
|
<InputLabel>MSA Row</InputLabel>
|
|
119
121
|
<Select
|
|
120
122
|
value={selectedMsaRow}
|
|
@@ -131,11 +133,7 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
|
|
|
131
133
|
</Select>
|
|
132
134
|
</FormControl>
|
|
133
135
|
|
|
134
|
-
{error
|
|
135
|
-
<Typography color="error" sx={{ mt: 1 }}>
|
|
136
|
-
{error}
|
|
137
|
-
</Typography>
|
|
138
|
-
)}
|
|
136
|
+
{error ? <ErrorMessage error={error} /> : null}
|
|
139
137
|
</>
|
|
140
138
|
)}
|
|
141
139
|
</DialogContent>
|
|
@@ -60,7 +60,7 @@ const LoadingBLAST = observer(function LoadingBLAST2({
|
|
|
60
60
|
model: JBrowsePluginMsaViewModel
|
|
61
61
|
baseUrl: string
|
|
62
62
|
}) {
|
|
63
|
-
const { progress, rid, error
|
|
63
|
+
const { progress, rid, error } = model
|
|
64
64
|
const { classes } = useStyles()
|
|
65
65
|
return (
|
|
66
66
|
<div className={classes.margin}>
|
|
@@ -69,8 +69,9 @@ const LoadingBLAST = observer(function LoadingBLAST2({
|
|
|
69
69
|
<RIDError baseUrl={baseUrl} rid={rid} error={error} />
|
|
70
70
|
) : rid ? (
|
|
71
71
|
<RIDProgress baseUrl={baseUrl} rid={rid} progress={progress} />
|
|
72
|
-
) :
|
|
73
|
-
|
|
72
|
+
) : (
|
|
73
|
+
<Typography>{progress || 'Initializing BLAST query'}</Typography>
|
|
74
|
+
)}
|
|
74
75
|
</div>
|
|
75
76
|
)
|
|
76
77
|
})
|
|
@@ -3,17 +3,25 @@ import React from 'react'
|
|
|
3
3
|
import { LoadingEllipses } from '@jbrowse/core/ui'
|
|
4
4
|
import { observer } from 'mobx-react'
|
|
5
5
|
import { MSAView } from 'react-msaview'
|
|
6
|
+
import { makeStyles } from 'tss-react/mui'
|
|
6
7
|
|
|
7
8
|
import { ErrorBoundary } from './ErrorBoundary'
|
|
8
9
|
import LoadingBLAST from './LoadingBLAST'
|
|
9
10
|
|
|
10
11
|
import type { JBrowsePluginMsaViewModel } from '../model'
|
|
11
12
|
|
|
13
|
+
const useStyles = makeStyles()({
|
|
14
|
+
loadingContainer: {
|
|
15
|
+
padding: 20,
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
12
19
|
const MsaViewPanel = observer(function MsaViewPanel2({
|
|
13
20
|
model,
|
|
14
21
|
}: {
|
|
15
22
|
model: JBrowsePluginMsaViewModel
|
|
16
23
|
}) {
|
|
24
|
+
const { classes } = useStyles()
|
|
17
25
|
const { blastParams, loadingStoredData } = model
|
|
18
26
|
return (
|
|
19
27
|
<ErrorBoundary>
|
|
@@ -21,7 +29,7 @@ const MsaViewPanel = observer(function MsaViewPanel2({
|
|
|
21
29
|
{blastParams ? (
|
|
22
30
|
<LoadingBLAST model={model} baseUrl={blastParams.baseUrl} />
|
|
23
31
|
) : loadingStoredData ? (
|
|
24
|
-
<div
|
|
32
|
+
<div className={classes.loadingContainer}>
|
|
25
33
|
<LoadingEllipses message="Loading MSA data" variant="h6" />
|
|
26
34
|
</div>
|
|
27
35
|
) : (
|
|
@@ -21,10 +21,18 @@ import {
|
|
|
21
21
|
import { genomeToMSA } from './genomeToMSA'
|
|
22
22
|
import { msaCoordToGenomeCoord } from './msaCoordToGenomeCoord'
|
|
23
23
|
import { buildAlignmentMaps, runPairwiseAlignment } from './pairwiseAlignment'
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
getProteinViews,
|
|
26
|
+
ungappedToGappedPosition,
|
|
27
|
+
} from './structureConnection'
|
|
25
28
|
|
|
26
|
-
import type { StructureConnection } from './structureConnection'
|
|
29
|
+
import type { ProteinView, StructureConnection } from './structureConnection'
|
|
27
30
|
import type { MafRegion, MsaViewInitState } from './types'
|
|
31
|
+
import type {
|
|
32
|
+
BlastDatabase,
|
|
33
|
+
BlastProgram,
|
|
34
|
+
MsaAlgorithm,
|
|
35
|
+
} from '../LaunchMsaView/components/NCBIBlastQuery/consts'
|
|
28
36
|
import type { Feature } from '@jbrowse/core/util'
|
|
29
37
|
import type { Instance } from '@jbrowse/mobx-state-tree'
|
|
30
38
|
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
@@ -45,9 +53,9 @@ export interface IRegion {
|
|
|
45
53
|
|
|
46
54
|
export interface BlastParams {
|
|
47
55
|
baseUrl: string
|
|
48
|
-
blastDatabase:
|
|
49
|
-
msaAlgorithm:
|
|
50
|
-
blastProgram:
|
|
56
|
+
blastDatabase: BlastDatabase
|
|
57
|
+
msaAlgorithm: MsaAlgorithm
|
|
58
|
+
blastProgram: BlastProgram
|
|
51
59
|
selectedTranscript?: Feature
|
|
52
60
|
proteinSequence: string
|
|
53
61
|
rid?: string
|
|
@@ -175,13 +183,6 @@ export default function stateModelFactory() {
|
|
|
175
183
|
: undefined
|
|
176
184
|
},
|
|
177
185
|
|
|
178
|
-
/**
|
|
179
|
-
* #getter
|
|
180
|
-
*/
|
|
181
|
-
get processing() {
|
|
182
|
-
return !!self.progress
|
|
183
|
-
},
|
|
184
|
-
|
|
185
186
|
/**
|
|
186
187
|
* #getter
|
|
187
188
|
*/
|
|
@@ -194,19 +195,18 @@ export default function stateModelFactory() {
|
|
|
194
195
|
* #getter
|
|
195
196
|
*/
|
|
196
197
|
get connectedProteinViews() {
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
)
|
|
204
|
-
return proteinView ? { ...conn, proteinView } : undefined
|
|
205
|
-
})
|
|
206
|
-
.filter(
|
|
207
|
-
(c): c is StructureConnection & { proteinView: any } =>
|
|
208
|
-
c !== undefined,
|
|
198
|
+
const proteinViews = getProteinViews(getSession(self).views)
|
|
199
|
+
const result: (StructureConnection & { proteinView: ProteinView })[] =
|
|
200
|
+
[]
|
|
201
|
+
for (const conn of self.connectedStructures) {
|
|
202
|
+
const proteinView = proteinViews.find(
|
|
203
|
+
v => v.id === conn.proteinViewId,
|
|
209
204
|
)
|
|
205
|
+
if (proteinView) {
|
|
206
|
+
result.push({ ...conn, proteinView })
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return result
|
|
210
210
|
},
|
|
211
211
|
}))
|
|
212
212
|
|
|
@@ -216,7 +216,7 @@ export default function stateModelFactory() {
|
|
|
216
216
|
*/
|
|
217
217
|
get structureHoverCol(): number | undefined {
|
|
218
218
|
for (const conn of self.connectedProteinViews) {
|
|
219
|
-
const structure = conn.proteinView
|
|
219
|
+
const structure = conn.proteinView.structures[conn.structureIdx]
|
|
220
220
|
const structurePos = structure?.hoverPosition?.structureSeqPos
|
|
221
221
|
if (structurePos !== undefined) {
|
|
222
222
|
const msaUngapped = conn.structureToMsa[structurePos]
|
|
@@ -246,12 +246,6 @@ export default function stateModelFactory() {
|
|
|
246
246
|
}
|
|
247
247
|
return genomeToMSA({ model: self as JBrowsePluginMsaViewModel })
|
|
248
248
|
},
|
|
249
|
-
/**
|
|
250
|
-
* #getter
|
|
251
|
-
*/
|
|
252
|
-
get clickCol2() {
|
|
253
|
-
return undefined
|
|
254
|
-
},
|
|
255
249
|
}))
|
|
256
250
|
|
|
257
251
|
.actions(self => ({
|
|
@@ -378,16 +372,14 @@ export default function stateModelFactory() {
|
|
|
378
372
|
|
|
379
373
|
const ungappedMsaSequence = msaSequence.replaceAll('-', '')
|
|
380
374
|
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
(v: any) => v.id === proteinViewId,
|
|
385
|
-
) as any
|
|
375
|
+
const proteinView = getProteinViews(getSession(self).views).find(
|
|
376
|
+
v => v.id === proteinViewId,
|
|
377
|
+
)
|
|
386
378
|
if (!proteinView) {
|
|
387
379
|
throw new Error(`ProteinView "${proteinViewId}" not found`)
|
|
388
380
|
}
|
|
389
381
|
|
|
390
|
-
const structure = proteinView.structures
|
|
382
|
+
const structure = proteinView.structures[structureIdx]
|
|
391
383
|
if (!structure) {
|
|
392
384
|
throw new Error(`Structure at index ${structureIdx} not found`)
|
|
393
385
|
}
|
|
@@ -407,8 +399,8 @@ export default function stateModelFactory() {
|
|
|
407
399
|
proteinViewId,
|
|
408
400
|
structureIdx,
|
|
409
401
|
msaRowName: rowName,
|
|
410
|
-
msaToStructure:
|
|
411
|
-
structureToMsa:
|
|
402
|
+
msaToStructure: Object.fromEntries(seq1ToSeq2),
|
|
403
|
+
structureToMsa: Object.fromEntries(seq2ToSeq1),
|
|
412
404
|
}
|
|
413
405
|
|
|
414
406
|
self.connectedStructures.push(connection)
|
|
@@ -66,15 +66,6 @@ export async function retrieveMsaData(id: string) {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
export async function deleteMsaData(id: string) {
|
|
70
|
-
try {
|
|
71
|
-
const db = await getDB()
|
|
72
|
-
await db.delete(STORE_NAME, id)
|
|
73
|
-
} catch (e) {
|
|
74
|
-
console.warn('Failed to delete MSA data:', e)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
69
|
export async function cleanupOldData(maxAgeMs = 7 * 24 * 60 * 60 * 1000) {
|
|
79
70
|
try {
|
|
80
71
|
const db = await getDB()
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import BLOSUM62 from './blosum62'
|
|
2
2
|
|
|
3
3
|
function getScore(a: string, b: string) {
|
|
4
|
-
|
|
5
|
-
const upper_b = b.toUpperCase()
|
|
6
|
-
return BLOSUM62[upper_a]?.[upper_b] ?? -4
|
|
4
|
+
return BLOSUM62[a.toUpperCase()]?.[b.toUpperCase()] ?? -4
|
|
7
5
|
}
|
|
8
6
|
|
|
9
7
|
const GAP_OPEN = -10
|
|
@@ -75,10 +73,12 @@ export function needlemanWunsch(
|
|
|
75
73
|
let i = m
|
|
76
74
|
let j = n
|
|
77
75
|
|
|
78
|
-
const
|
|
79
|
-
const
|
|
76
|
+
const mScore = M[m]![n]!
|
|
77
|
+
const ixScore = Ix[m]![n]!
|
|
78
|
+
const iyScore = Iy[m]![n]!
|
|
79
|
+
const score = Math.max(mScore, ixScore, iyScore)
|
|
80
80
|
let currentMatrix: 'M' | 'Ix' | 'Iy' =
|
|
81
|
-
score ===
|
|
81
|
+
score === mScore ? 'M' : score === ixScore ? 'Ix' : 'Iy'
|
|
82
82
|
|
|
83
83
|
while (i > 0 || j > 0) {
|
|
84
84
|
if (currentMatrix === 'M' && i > 0 && j > 0) {
|
|
@@ -2,7 +2,6 @@ import { describe, expect, test } from 'vitest'
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
gappedToUngappedPosition,
|
|
5
|
-
mapToRecord,
|
|
6
5
|
ungappedToGappedPosition,
|
|
7
6
|
} from './structureConnection'
|
|
8
7
|
|
|
@@ -121,23 +120,3 @@ describe('gappedToUngappedPosition and ungappedToGappedPosition are inverses', (
|
|
|
121
120
|
}
|
|
122
121
|
})
|
|
123
122
|
})
|
|
124
|
-
|
|
125
|
-
describe('mapToRecord', () => {
|
|
126
|
-
test('converts Map to Record', () => {
|
|
127
|
-
const map = new Map<number, number>([
|
|
128
|
-
[0, 5],
|
|
129
|
-
[1, 10],
|
|
130
|
-
[2, 15],
|
|
131
|
-
])
|
|
132
|
-
const record = mapToRecord(map)
|
|
133
|
-
expect(record[0]).toBe(5)
|
|
134
|
-
expect(record[1]).toBe(10)
|
|
135
|
-
expect(record[2]).toBe(15)
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
test('handles empty Map', () => {
|
|
139
|
-
const map = new Map<number, number>()
|
|
140
|
-
const record = mapToRecord(map)
|
|
141
|
-
expect(Object.keys(record)).toHaveLength(0)
|
|
142
|
-
})
|
|
143
|
-
})
|
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
export interface ProteinViewStructure {
|
|
2
|
+
url?: string
|
|
3
|
+
connectedViewId?: string
|
|
4
|
+
uniprotId?: string
|
|
5
|
+
structureSequences?: string[]
|
|
6
|
+
hoverGenomeHighlights?: { start: number; end: number }[]
|
|
7
|
+
hoverPosition?: { structureSeqPos?: number }
|
|
8
|
+
clearHighlightFromExternal?: () => void
|
|
9
|
+
highlightFromExternal?: (pos: number) => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ProteinView {
|
|
13
|
+
type: 'ProteinView'
|
|
14
|
+
id: string
|
|
15
|
+
displayName?: string
|
|
16
|
+
structures: ProteinViewStructure[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isProteinView(view: unknown): view is ProteinView {
|
|
20
|
+
const v = view as Record<string, unknown>
|
|
21
|
+
return v.type === 'ProteinView' && Array.isArray(v.structures)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Extract all ProteinView instances from a session's views array.
|
|
26
|
+
*/
|
|
27
|
+
export function getProteinViews(views: { type: string }[]): ProteinView[] {
|
|
28
|
+
return (views as unknown[]).filter(isProteinView)
|
|
29
|
+
}
|
|
30
|
+
|
|
1
31
|
/**
|
|
2
32
|
* Represents a connection between the MSA view and a protein structure
|
|
3
33
|
*/
|
|
@@ -59,10 +89,3 @@ export function ungappedToGappedPosition(
|
|
|
59
89
|
}
|
|
60
90
|
return undefined
|
|
61
91
|
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Convert Map to plain object for MST frozen storage
|
|
65
|
-
*/
|
|
66
|
-
export function mapToRecord(map: Map<number, number>): Record<number, number> {
|
|
67
|
-
return Object.fromEntries(map)
|
|
68
|
-
}
|
package/src/utils/blastCache.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { openDB } from 'idb'
|
|
2
2
|
|
|
3
|
+
import type {
|
|
4
|
+
BlastDatabase,
|
|
5
|
+
BlastProgram,
|
|
6
|
+
MsaAlgorithm,
|
|
7
|
+
} from '../LaunchMsaView/components/NCBIBlastQuery/consts'
|
|
8
|
+
|
|
3
9
|
const DB_NAME = 'jbrowse-msaview-blast-cache'
|
|
4
10
|
const STORE_NAME = 'blast-results'
|
|
5
11
|
const DB_VERSION = 2
|
|
@@ -7,9 +13,9 @@ const DB_VERSION = 2
|
|
|
7
13
|
export interface CachedBlastResult {
|
|
8
14
|
id: string
|
|
9
15
|
proteinSequence: string
|
|
10
|
-
blastDatabase:
|
|
11
|
-
blastProgram:
|
|
12
|
-
msaAlgorithm:
|
|
16
|
+
blastDatabase: BlastDatabase
|
|
17
|
+
blastProgram: BlastProgram
|
|
18
|
+
msaAlgorithm: MsaAlgorithm
|
|
13
19
|
msa: string
|
|
14
20
|
tree: string
|
|
15
21
|
treeMetadata: string
|
|
@@ -36,8 +42,8 @@ async function getDB() {
|
|
|
36
42
|
|
|
37
43
|
function createCacheKey(
|
|
38
44
|
proteinSequence: string,
|
|
39
|
-
blastDatabase:
|
|
40
|
-
blastProgram:
|
|
45
|
+
blastDatabase: BlastDatabase,
|
|
46
|
+
blastProgram: BlastProgram,
|
|
41
47
|
transcriptId?: string,
|
|
42
48
|
) {
|
|
43
49
|
if (transcriptId) {
|
|
@@ -46,27 +52,6 @@ function createCacheKey(
|
|
|
46
52
|
return `${blastDatabase}:${blastProgram}:${proteinSequence}`
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
export async function getCachedBlastResult({
|
|
50
|
-
proteinSequence,
|
|
51
|
-
blastDatabase,
|
|
52
|
-
blastProgram,
|
|
53
|
-
transcriptId,
|
|
54
|
-
}: {
|
|
55
|
-
proteinSequence: string
|
|
56
|
-
blastDatabase: string
|
|
57
|
-
blastProgram: string
|
|
58
|
-
transcriptId?: string
|
|
59
|
-
}) {
|
|
60
|
-
const db = await getDB()
|
|
61
|
-
const id = createCacheKey(
|
|
62
|
-
proteinSequence,
|
|
63
|
-
blastDatabase,
|
|
64
|
-
blastProgram,
|
|
65
|
-
transcriptId,
|
|
66
|
-
)
|
|
67
|
-
return db.get(STORE_NAME, id)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
55
|
export async function saveBlastResult({
|
|
71
56
|
proteinSequence,
|
|
72
57
|
blastDatabase,
|
|
@@ -82,9 +67,9 @@ export async function saveBlastResult({
|
|
|
82
67
|
geneName,
|
|
83
68
|
}: {
|
|
84
69
|
proteinSequence: string
|
|
85
|
-
blastDatabase:
|
|
86
|
-
blastProgram:
|
|
87
|
-
msaAlgorithm:
|
|
70
|
+
blastDatabase: BlastDatabase
|
|
71
|
+
blastProgram: BlastProgram
|
|
72
|
+
msaAlgorithm: MsaAlgorithm
|
|
88
73
|
msa: string
|
|
89
74
|
tree: string
|
|
90
75
|
treeMetadata: string
|
|
@@ -127,14 +112,6 @@ export async function getAllCachedResults() {
|
|
|
127
112
|
return results.toSorted((a, b) => b.timestamp - a.timestamp)
|
|
128
113
|
}
|
|
129
114
|
|
|
130
|
-
export async function getCachedResultsByGeneId(geneId: string) {
|
|
131
|
-
const db = await getDB()
|
|
132
|
-
const results = await db.getAll(STORE_NAME)
|
|
133
|
-
return results
|
|
134
|
-
.filter(r => r.geneId === geneId)
|
|
135
|
-
.toSorted((a, b) => b.timestamp - a.timestamp)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
115
|
export async function deleteCachedResult(id: string) {
|
|
139
116
|
const db = await getDB()
|
|
140
117
|
await db.delete(STORE_NAME, id)
|
package/src/utils/msa.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { textfetch, timeout } from './fetch'
|
|
2
2
|
|
|
3
|
+
import type { MsaAlgorithm } from '../LaunchMsaView/components/NCBIBlastQuery/consts'
|
|
4
|
+
|
|
3
5
|
const base = `https://www.ebi.ac.uk/Tools/services/rest`
|
|
4
6
|
|
|
5
7
|
const algorithms: Record<
|
|
6
|
-
|
|
8
|
+
MsaAlgorithm,
|
|
7
9
|
{
|
|
8
10
|
params: Record<string, string>
|
|
9
11
|
msaResult: string
|
|
@@ -38,7 +40,7 @@ async function wait({
|
|
|
38
40
|
algorithm,
|
|
39
41
|
}: {
|
|
40
42
|
jobId: string
|
|
41
|
-
algorithm:
|
|
43
|
+
algorithm: MsaAlgorithm
|
|
42
44
|
onProgress: (arg: string) => void
|
|
43
45
|
}) {
|
|
44
46
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -62,14 +64,11 @@ export async function launchMSA({
|
|
|
62
64
|
sequence,
|
|
63
65
|
onProgress,
|
|
64
66
|
}: {
|
|
65
|
-
algorithm:
|
|
67
|
+
algorithm: MsaAlgorithm
|
|
66
68
|
sequence: string
|
|
67
69
|
onProgress: (arg: string) => void
|
|
68
70
|
}) {
|
|
69
71
|
const config = algorithms[algorithm]
|
|
70
|
-
if (!config) {
|
|
71
|
-
throw new Error(`unknown algorithm: ${algorithm}`)
|
|
72
|
-
}
|
|
73
72
|
|
|
74
73
|
onProgress(`Launching ${algorithm} MSA...`)
|
|
75
74
|
|