jbrowse-plugin-protein3d 0.0.2 → 0.0.4
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/AddHighlightModel/GenomeMouseoverHighlight.js +3 -9
- package/dist/AddHighlightModel/GenomeMouseoverHighlight.js.map +1 -1
- package/dist/AddHighlightModel/ProteinToGenomeClickHighlight.js +4 -3
- package/dist/AddHighlightModel/ProteinToGenomeClickHighlight.js.map +1 -1
- package/dist/AddHighlightModel/ProteinToGenomeHoverHighlight.d.ts +1 -2
- package/dist/AddHighlightModel/ProteinToGenomeHoverHighlight.js +4 -3
- package/dist/AddHighlightModel/ProteinToGenomeHoverHighlight.js.map +1 -1
- package/dist/AddHighlightModel/util.js +1 -1
- package/dist/AddHighlightModel/util.js.map +1 -1
- package/dist/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.d.ts +16 -0
- package/dist/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.js +43 -0
- package/dist/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.js.map +1 -0
- package/dist/AlphaFoldConfidenceAdapter/configSchema.d.ts +13 -0
- package/dist/AlphaFoldConfidenceAdapter/configSchema.js +16 -0
- package/dist/AlphaFoldConfidenceAdapter/configSchema.js.map +1 -0
- package/dist/AlphaFoldConfidenceAdapter/index.d.ts +2 -0
- package/dist/AlphaFoldConfidenceAdapter/index.js +11 -0
- package/dist/AlphaFoldConfidenceAdapter/index.js.map +1 -0
- package/dist/AlphaMissensePathogenicityAdapter/AlphaMissensePathogenicityAdapter.d.ts +30 -0
- package/dist/AlphaMissensePathogenicityAdapter/AlphaMissensePathogenicityAdapter.js +78 -0
- package/dist/AlphaMissensePathogenicityAdapter/AlphaMissensePathogenicityAdapter.js.map +1 -0
- package/dist/AlphaMissensePathogenicityAdapter/configSchema.d.ts +13 -0
- package/dist/AlphaMissensePathogenicityAdapter/configSchema.js +16 -0
- package/dist/AlphaMissensePathogenicityAdapter/configSchema.js.map +1 -0
- package/dist/AlphaMissensePathogenicityAdapter/index.d.ts +2 -0
- package/dist/AlphaMissensePathogenicityAdapter/index.js +11 -0
- package/dist/AlphaMissensePathogenicityAdapter/index.js.map +1 -0
- package/dist/LaunchProteinView/components/AlphaFoldDBSearch.js +201 -34
- package/dist/LaunchProteinView/components/AlphaFoldDBSearch.js.map +1 -1
- package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.d.ts +7 -4
- package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.js +35 -14
- package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.js.map +1 -1
- package/dist/LaunchProteinView/components/HelpButton.js +6 -2
- package/dist/LaunchProteinView/components/HelpButton.js.map +1 -1
- package/dist/LaunchProteinView/components/HelpDialog.js +13 -4
- package/dist/LaunchProteinView/components/HelpDialog.js.map +1 -1
- package/dist/LaunchProteinView/components/LaunchProteinViewDialog.js +9 -9
- package/dist/LaunchProteinView/components/LaunchProteinViewDialog.js.map +1 -1
- package/dist/LaunchProteinView/components/MSATable.d.ts +10 -0
- package/dist/LaunchProteinView/components/MSATable.js +55 -0
- package/dist/LaunchProteinView/components/MSATable.js.map +1 -0
- package/dist/LaunchProteinView/components/TranscriptSelector.d.ts +7 -3
- package/dist/LaunchProteinView/components/TranscriptSelector.js +25 -8
- package/dist/LaunchProteinView/components/TranscriptSelector.js.map +1 -1
- package/dist/LaunchProteinView/components/UserProvidedStructure.js +67 -47
- package/dist/LaunchProteinView/components/UserProvidedStructure.js.map +1 -1
- package/dist/LaunchProteinView/{calculateProteinSequence.js → components/calculateProteinSequence.js} +5 -3
- package/dist/LaunchProteinView/components/calculateProteinSequence.js.map +1 -0
- package/dist/LaunchProteinView/components/useIsoformProteinSequences.d.ts +14 -0
- package/dist/LaunchProteinView/{useProteinSequences.js → components/useIsoformProteinSequences.js} +11 -6
- package/dist/LaunchProteinView/components/useIsoformProteinSequences.js.map +1 -0
- package/dist/LaunchProteinView/components/useLocalStructureFileSequence.d.ts +7 -0
- package/dist/LaunchProteinView/components/useLocalStructureFileSequence.js +64 -0
- package/dist/LaunchProteinView/components/useLocalStructureFileSequence.js.map +1 -0
- package/dist/LaunchProteinView/{useMyGeneInfo.d.ts → components/useMyGeneInfoUniprotIdLookup.d.ts} +2 -2
- package/dist/LaunchProteinView/{useMyGeneInfo.js → components/useMyGeneInfoUniprotIdLookup.js} +15 -10
- package/dist/LaunchProteinView/components/useMyGeneInfoUniprotIdLookup.js.map +1 -0
- package/dist/LaunchProteinView/components/useRemoteStructureFileSequence.d.ts +7 -0
- package/dist/LaunchProteinView/components/useRemoteStructureFileSequence.js +59 -0
- package/dist/LaunchProteinView/components/useRemoteStructureFileSequence.js.map +1 -0
- package/dist/LaunchProteinView/{util.d.ts → components/util.d.ts} +0 -10
- package/dist/LaunchProteinView/{util.js → components/util.js} +4 -25
- package/dist/LaunchProteinView/components/util.js.map +1 -0
- package/dist/LaunchProteinView/index.js +6 -2
- package/dist/LaunchProteinView/index.js.map +1 -1
- package/dist/ProteinView/{loadStructureFromData.d.ts → addStructureFromData.d.ts} +2 -2
- package/dist/ProteinView/{loadStructureFromData.js → addStructureFromData.js} +3 -8
- package/dist/ProteinView/addStructureFromData.js.map +1 -0
- package/dist/ProteinView/{loadStructureFromURL.d.ts → addStructureFromURL.d.ts} +2 -2
- package/dist/ProteinView/{loadStructureFromURL.js → addStructureFromURL.js} +11 -9
- package/dist/ProteinView/addStructureFromURL.js.map +1 -0
- package/dist/ProteinView/clearSelection.js +1 -1
- package/dist/ProteinView/clearSelection.js.map +1 -1
- package/dist/ProteinView/components/ProteinAlignment.d.ts +2 -2
- package/dist/ProteinView/components/ProteinAlignment.js +37 -26
- package/dist/ProteinView/components/ProteinAlignment.js.map +1 -1
- package/dist/ProteinView/components/ProteinAlignmentHelpButton.d.ts +2 -2
- package/dist/ProteinView/components/ProteinAlignmentHelpButton.js +6 -4
- package/dist/ProteinView/components/ProteinAlignmentHelpButton.js.map +1 -1
- package/dist/ProteinView/components/ProteinAlignmentHelpDialog.js +6 -5
- package/dist/ProteinView/components/ProteinAlignmentHelpDialog.js.map +1 -1
- package/dist/ProteinView/components/ProteinView.js +18 -60
- package/dist/ProteinView/components/ProteinView.js.map +1 -1
- package/dist/ProteinView/components/{Header.js → ProteinViewHeader.js} +29 -12
- package/dist/ProteinView/components/ProteinViewHeader.js.map +1 -0
- package/dist/ProteinView/components/SplitString.d.ts +4 -4
- package/dist/ProteinView/components/SplitString.js +4 -4
- package/dist/ProteinView/components/SplitString.js.map +1 -1
- package/dist/ProteinView/genomeToProtein.d.ts +2 -2
- package/dist/ProteinView/genomeToProtein.js +4 -5
- package/dist/ProteinView/genomeToProtein.js.map +1 -1
- package/dist/ProteinView/highlightResidue.js +2 -2
- package/dist/ProteinView/highlightResidue.js.map +1 -1
- package/dist/ProteinView/launchRemotePairwiseAlignment.d.ts +2 -5
- package/dist/ProteinView/launchRemotePairwiseAlignment.js +7 -3
- package/dist/ProteinView/launchRemotePairwiseAlignment.js.map +1 -1
- package/dist/ProteinView/model.d.ts +496 -156
- package/dist/ProteinView/model.js +66 -225
- package/dist/ProteinView/model.js.map +1 -1
- package/dist/ProteinView/proteinToGenomeMapping.d.ts +6 -6
- package/dist/ProteinView/proteinToGenomeMapping.js +29 -28
- package/dist/ProteinView/proteinToGenomeMapping.js.map +1 -1
- package/dist/ProteinView/selectResidue.js +1 -1
- package/dist/ProteinView/selectResidue.js.map +1 -1
- package/dist/ProteinView/structureModel.d.ts +183 -0
- package/dist/ProteinView/structureModel.js +407 -0
- package/dist/ProteinView/structureModel.js.map +1 -0
- package/dist/ProteinView/useProteinView.d.ts +1 -4
- package/dist/ProteinView/useProteinView.js +3 -15
- package/dist/ProteinView/useProteinView.js.map +1 -1
- package/dist/ProteinView/util.d.ts +3 -3
- package/dist/ProteinView/util.js +8 -6
- package/dist/ProteinView/util.js.map +1 -1
- package/dist/UniProtVariationAdapter/UniProtVariationAdapter.d.ts +15 -0
- package/dist/UniProtVariationAdapter/UniProtVariationAdapter.js +55 -0
- package/dist/UniProtVariationAdapter/UniProtVariationAdapter.js.map +1 -0
- package/dist/UniProtVariationAdapter/configSchema.d.ts +17 -0
- package/dist/UniProtVariationAdapter/configSchema.js +20 -0
- package/dist/UniProtVariationAdapter/configSchema.js.map +1 -0
- package/dist/UniProtVariationAdapter/index.d.ts +2 -0
- package/dist/UniProtVariationAdapter/index.js +11 -0
- package/dist/UniProtVariationAdapter/index.js.map +1 -0
- package/dist/genomeToTranscriptMapping.d.ts +2 -2
- package/dist/genomeToTranscriptMapping.js +3 -3
- package/dist/genomeToTranscriptMapping.js.map +1 -1
- package/dist/index.js +6 -9
- package/dist/index.js.map +1 -1
- package/dist/jbrowse-plugin-protein3d.umd.production.min.js +1473 -1489
- package/dist/jbrowse-plugin-protein3d.umd.production.min.js.map +4 -4
- package/dist/mappings.d.ts +12 -10
- package/dist/mappings.js +7 -7
- package/dist/mappings.js.map +1 -1
- package/dist/mappings.test.js +7 -5
- package/dist/mappings.test.js.map +1 -1
- package/dist/test_data/gene.d.ts +577 -64
- package/dist/test_data/gene.js +1 -1
- package/dist/test_data/gene.js.map +1 -1
- package/package.json +17 -16
- package/src/AddHighlightModel/GenomeMouseoverHighlight.tsx +4 -17
- package/src/AddHighlightModel/ProteinToGenomeClickHighlight.tsx +17 -14
- package/src/AddHighlightModel/ProteinToGenomeHoverHighlight.tsx +18 -17
- package/src/AddHighlightModel/util.ts +1 -1
- package/src/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.ts +63 -0
- package/src/AlphaFoldConfidenceAdapter/configSchema.ts +21 -0
- package/src/AlphaFoldConfidenceAdapter/index.ts +19 -0
- package/src/AlphaMissensePathogenicityAdapter/AlphaMissensePathogenicityAdapter.ts +109 -0
- package/src/AlphaMissensePathogenicityAdapter/configSchema.ts +21 -0
- package/src/AlphaMissensePathogenicityAdapter/index.ts +19 -0
- package/src/LaunchProteinView/components/AlphaFoldDBSearch.tsx +266 -53
- package/src/LaunchProteinView/components/AlphaFoldDBSearchStatus.tsx +71 -29
- package/src/LaunchProteinView/components/HelpButton.tsx +10 -2
- package/src/LaunchProteinView/components/HelpDialog.tsx +41 -8
- package/src/LaunchProteinView/components/LaunchProteinViewDialog.tsx +10 -12
- package/src/LaunchProteinView/components/MSATable.tsx +98 -0
- package/src/LaunchProteinView/components/TranscriptSelector.tsx +39 -11
- package/src/LaunchProteinView/components/UserProvidedStructure.tsx +119 -68
- package/src/LaunchProteinView/{calculateProteinSequence.ts → components/calculateProteinSequence.ts} +6 -4
- package/src/LaunchProteinView/{useProteinSequences.ts → components/useIsoformProteinSequences.ts} +12 -7
- package/src/LaunchProteinView/components/useLocalStructureFileSequence.ts +72 -0
- package/src/LaunchProteinView/{useMyGeneInfo.ts → components/useMyGeneInfoUniprotIdLookup.ts} +16 -11
- package/src/LaunchProteinView/components/useRemoteStructureFileSequence.ts +59 -0
- package/src/LaunchProteinView/{util.ts → components/util.ts} +4 -36
- package/src/LaunchProteinView/index.ts +36 -26
- package/src/ProteinView/{loadStructureFromData.ts → addStructureFromData.ts} +2 -8
- package/src/ProteinView/{loadStructureFromURL.ts → addStructureFromURL.ts} +11 -11
- package/src/ProteinView/clearSelection.ts +1 -1
- package/src/ProteinView/components/ProteinAlignment.tsx +51 -35
- package/src/ProteinView/components/ProteinAlignmentHelpButton.tsx +4 -4
- package/src/ProteinView/components/ProteinAlignmentHelpDialog.tsx +15 -11
- package/src/ProteinView/components/ProteinView.tsx +22 -82
- package/src/ProteinView/components/{Header.tsx → ProteinViewHeader.tsx} +44 -21
- package/src/ProteinView/components/SplitString.tsx +9 -9
- package/src/ProteinView/genomeToProtein.ts +5 -9
- package/src/ProteinView/highlightResidue.ts +2 -2
- package/src/ProteinView/launchRemotePairwiseAlignment.ts +6 -3
- package/src/ProteinView/model.ts +80 -265
- package/src/ProteinView/proteinToGenomeMapping.ts +40 -38
- package/src/ProteinView/selectResidue.ts +1 -1
- package/src/ProteinView/structureModel.ts +512 -0
- package/src/ProteinView/useProteinView.ts +2 -19
- package/src/ProteinView/util.ts +20 -9
- package/src/UniProtVariationAdapter/UniProtVariationAdapter.ts +99 -0
- package/src/UniProtVariationAdapter/configSchema.ts +25 -0
- package/src/UniProtVariationAdapter/index.ts +17 -0
- package/src/__snapshots__/mappings.test.ts.snap +224 -224
- package/src/genomeToTranscriptMapping.ts +9 -9
- package/src/index.ts +7 -12
- package/src/mappings.test.ts +7 -5
- package/src/mappings.ts +25 -23
- package/src/test_data/gene.ts +3 -3
- package/dist/LaunchProteinView/calculateProteinSequence.js.map +0 -1
- package/dist/LaunchProteinView/components/PreLoadedStructureMapping.d.ts +0 -8
- package/dist/LaunchProteinView/components/PreLoadedStructureMapping.js +0 -72
- package/dist/LaunchProteinView/components/PreLoadedStructureMapping.js.map +0 -1
- package/dist/LaunchProteinView/components/useCheckAlphaFoldDBExistence.d.ts +0 -7
- package/dist/LaunchProteinView/components/useCheckAlphaFoldDBExistence.js +0 -26
- package/dist/LaunchProteinView/components/useCheckAlphaFoldDBExistence.js.map +0 -1
- package/dist/LaunchProteinView/useMyGeneInfo.js.map +0 -1
- package/dist/LaunchProteinView/useProteinSequences.d.ts +0 -10
- package/dist/LaunchProteinView/useProteinSequences.js.map +0 -1
- package/dist/LaunchProteinView/util.js.map +0 -1
- package/dist/ProteinModelSessionExtension.d.ts +0 -11
- package/dist/ProteinModelSessionExtension.js +0 -53
- package/dist/ProteinModelSessionExtension.js.map +0 -1
- package/dist/ProteinView/components/Header.js.map +0 -1
- package/dist/ProteinView/loadStructureFromData.js.map +0 -1
- package/dist/ProteinView/loadStructureFromURL.js.map +0 -1
- package/dist/ProteinView/useProteinViewClickBehavior.d.ts +0 -8
- package/dist/ProteinView/useProteinViewClickBehavior.js +0 -34
- package/dist/ProteinView/useProteinViewClickBehavior.js.map +0 -1
- package/dist/ProteinView/useProteinViewHoverBehavior.d.ts +0 -6
- package/dist/ProteinView/useProteinViewHoverBehavior.js +0 -31
- package/dist/ProteinView/useProteinViewHoverBehavior.js.map +0 -1
- package/src/LaunchProteinView/components/PreLoadedStructureMapping.tsx +0 -153
- package/src/LaunchProteinView/components/useCheckAlphaFoldDBExistence.ts +0 -31
- package/src/ProteinModelSessionExtension.ts +0 -71
- package/src/ProteinView/useProteinViewClickBehavior.ts +0 -48
- package/src/ProteinView/useProteinViewHoverBehavior.ts +0 -44
- /package/dist/LaunchProteinView/{calculateProteinSequence.d.ts → components/calculateProteinSequence.d.ts} +0 -0
- /package/dist/ProteinView/components/{Header.d.ts → ProteinViewHeader.d.ts} +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { Checkbox, FormControlLabel, TextField } from '@mui/material'
|
|
3
|
+
import { Feature, max } from '@jbrowse/core/util'
|
|
4
|
+
import { makeStyles } from 'tss-react/mui'
|
|
5
|
+
|
|
6
|
+
// locals
|
|
7
|
+
import { getTranscriptDisplayName } from './util'
|
|
8
|
+
|
|
9
|
+
const useStyles = makeStyles()({
|
|
10
|
+
textAreaFont: {
|
|
11
|
+
fontFamily: 'Courier New',
|
|
12
|
+
whiteSpace: 'pre',
|
|
13
|
+
},
|
|
14
|
+
margin: {
|
|
15
|
+
marginLeft: 20,
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export default function MSATable({
|
|
20
|
+
structureName,
|
|
21
|
+
structureSequence,
|
|
22
|
+
isoformSequences,
|
|
23
|
+
}: {
|
|
24
|
+
structureName: string
|
|
25
|
+
structureSequence: string
|
|
26
|
+
isoformSequences: Record<string, { feature: Feature; seq: string }>
|
|
27
|
+
}) {
|
|
28
|
+
const { classes } = useStyles()
|
|
29
|
+
const [showInFastaFormat, setShowInFastaFormat] = useState(false)
|
|
30
|
+
const removedStars = Object.fromEntries(
|
|
31
|
+
Object.entries(isoformSequences).map(([key, val]) => [
|
|
32
|
+
key,
|
|
33
|
+
{ ...val, seq: val.seq.replaceAll('*', '') },
|
|
34
|
+
]),
|
|
35
|
+
)
|
|
36
|
+
const exactMatchIsoformAndStructureSeq = Object.entries(removedStars).find(
|
|
37
|
+
([_, val]) => structureSequence === val.seq,
|
|
38
|
+
)
|
|
39
|
+
const sname = `${structureName || ''} (structure residues)`
|
|
40
|
+
const maxKeyLen = max([
|
|
41
|
+
sname.length,
|
|
42
|
+
...Object.entries(removedStars).map(
|
|
43
|
+
([_, val]) => getTranscriptDisplayName(val.feature).length,
|
|
44
|
+
),
|
|
45
|
+
])
|
|
46
|
+
|
|
47
|
+
const l1 = [
|
|
48
|
+
`${sname.padEnd(maxKeyLen)}${exactMatchIsoformAndStructureSeq ? '*' : ' '} ${structureSequence}`,
|
|
49
|
+
exactMatchIsoformAndStructureSeq
|
|
50
|
+
? `${getTranscriptDisplayName(exactMatchIsoformAndStructureSeq[1].feature).padEnd(maxKeyLen)}* ${exactMatchIsoformAndStructureSeq[1].seq}`
|
|
51
|
+
: undefined,
|
|
52
|
+
...Object.entries(removedStars)
|
|
53
|
+
.map(
|
|
54
|
+
([_, val]) =>
|
|
55
|
+
`${getTranscriptDisplayName(val.feature).padEnd(maxKeyLen)} ${val.seq}`,
|
|
56
|
+
)
|
|
57
|
+
.filter(([k]) => k !== exactMatchIsoformAndStructureSeq?.[0]),
|
|
58
|
+
]
|
|
59
|
+
.filter(f => !!f)
|
|
60
|
+
.join('\n')
|
|
61
|
+
|
|
62
|
+
const l2 = [
|
|
63
|
+
`>${sname}\n${structureSequence}`,
|
|
64
|
+
...Object.values(removedStars).map(
|
|
65
|
+
({ feature, seq }) => `>${getTranscriptDisplayName(feature)}\n${seq}`,
|
|
66
|
+
),
|
|
67
|
+
].join('\n')
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
<FormControlLabel
|
|
71
|
+
className={classes.margin}
|
|
72
|
+
control={
|
|
73
|
+
<Checkbox
|
|
74
|
+
onChange={event => {
|
|
75
|
+
setShowInFastaFormat(event.target.checked)
|
|
76
|
+
}}
|
|
77
|
+
checked={showInFastaFormat}
|
|
78
|
+
/>
|
|
79
|
+
}
|
|
80
|
+
label="Show in FASTA format?"
|
|
81
|
+
/>
|
|
82
|
+
<TextField
|
|
83
|
+
variant="outlined"
|
|
84
|
+
multiline
|
|
85
|
+
minRows={5}
|
|
86
|
+
maxRows={10}
|
|
87
|
+
fullWidth
|
|
88
|
+
value={showInFastaFormat ? l2 : l1}
|
|
89
|
+
InputProps={{
|
|
90
|
+
readOnly: true,
|
|
91
|
+
classes: {
|
|
92
|
+
input: classes.textAreaFont,
|
|
93
|
+
},
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
</>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
@@ -3,7 +3,7 @@ import { MenuItem, TextField, TextFieldProps } from '@mui/material'
|
|
|
3
3
|
import { Feature } from '@jbrowse/core/util'
|
|
4
4
|
|
|
5
5
|
// locals
|
|
6
|
-
import { getGeneDisplayName, getTranscriptDisplayName } from '
|
|
6
|
+
import { getGeneDisplayName, getTranscriptDisplayName } from './util'
|
|
7
7
|
|
|
8
8
|
function TextField2({ children, ...rest }: TextFieldProps) {
|
|
9
9
|
return (
|
|
@@ -16,33 +16,61 @@ function TextField2({ children, ...rest }: TextFieldProps) {
|
|
|
16
16
|
export default function TranscriptSelector({
|
|
17
17
|
val,
|
|
18
18
|
setVal,
|
|
19
|
-
|
|
19
|
+
isoforms,
|
|
20
|
+
isoformSequences,
|
|
21
|
+
structureSequence,
|
|
20
22
|
feature,
|
|
21
|
-
seqs,
|
|
22
23
|
}: {
|
|
23
|
-
|
|
24
|
+
isoforms: Feature[]
|
|
24
25
|
feature: Feature
|
|
25
26
|
val: string
|
|
26
27
|
setVal: (str: string) => void
|
|
27
|
-
|
|
28
|
+
structureSequence: string
|
|
29
|
+
isoformSequences: Record<string, { feature: Feature; seq: string }>
|
|
28
30
|
}) {
|
|
29
31
|
return (
|
|
30
32
|
<TextField2
|
|
31
33
|
value={val}
|
|
32
|
-
onChange={event =>
|
|
34
|
+
onChange={event => {
|
|
35
|
+
setVal(event.target.value)
|
|
36
|
+
}}
|
|
33
37
|
label="Choose transcript isoform"
|
|
34
38
|
select
|
|
35
39
|
>
|
|
36
|
-
{
|
|
37
|
-
.filter(f => !!
|
|
40
|
+
{isoforms
|
|
41
|
+
.filter(f => !!isoformSequences[f.id()])
|
|
42
|
+
.filter(
|
|
43
|
+
f =>
|
|
44
|
+
isoformSequences[f.id()]!.seq.replaceAll('*', '') ===
|
|
45
|
+
structureSequence,
|
|
46
|
+
)
|
|
38
47
|
.map(f => (
|
|
39
48
|
<MenuItem value={f.id()} key={f.id()}>
|
|
40
49
|
{getGeneDisplayName(feature)} - {getTranscriptDisplayName(f)} (
|
|
41
|
-
{
|
|
50
|
+
{isoformSequences[f.id()]!.seq.length}aa) (matches structure
|
|
51
|
+
residues)
|
|
42
52
|
</MenuItem>
|
|
43
53
|
))}
|
|
44
|
-
{
|
|
45
|
-
.filter(f =>
|
|
54
|
+
{isoforms
|
|
55
|
+
.filter(f => !!isoformSequences[f.id()])
|
|
56
|
+
.filter(
|
|
57
|
+
f =>
|
|
58
|
+
isoformSequences[f.id()]!.seq.replaceAll('*', '') !==
|
|
59
|
+
structureSequence,
|
|
60
|
+
)
|
|
61
|
+
.sort(
|
|
62
|
+
(a, b) =>
|
|
63
|
+
isoformSequences[b.id()]!.seq.length -
|
|
64
|
+
isoformSequences[a.id()]!.seq.length,
|
|
65
|
+
)
|
|
66
|
+
.map(f => (
|
|
67
|
+
<MenuItem value={f.id()} key={f.id()}>
|
|
68
|
+
{getGeneDisplayName(feature)} - {getTranscriptDisplayName(f)} (
|
|
69
|
+
{isoformSequences[f.id()]!.seq.length}aa)
|
|
70
|
+
</MenuItem>
|
|
71
|
+
))}
|
|
72
|
+
{isoforms
|
|
73
|
+
.filter(f => !isoformSequences[f.id()])
|
|
46
74
|
.map(f => (
|
|
47
75
|
<MenuItem value={f.id()} key={f.id()} disabled>
|
|
48
76
|
{getGeneDisplayName(feature)} - {getTranscriptDisplayName(f)} (no
|
|
@@ -3,13 +3,13 @@ import { observer } from 'mobx-react'
|
|
|
3
3
|
import {
|
|
4
4
|
Button,
|
|
5
5
|
DialogActions,
|
|
6
|
-
Radio,
|
|
7
|
-
RadioGroup,
|
|
8
6
|
DialogContent,
|
|
9
|
-
TextField,
|
|
10
7
|
FormControlLabel,
|
|
11
8
|
FormControl,
|
|
12
9
|
Link,
|
|
10
|
+
Radio,
|
|
11
|
+
RadioGroup,
|
|
12
|
+
TextField,
|
|
13
13
|
Typography,
|
|
14
14
|
} from '@mui/material'
|
|
15
15
|
import { makeStyles } from 'tss-react/mui'
|
|
@@ -28,11 +28,17 @@ import {
|
|
|
28
28
|
getId,
|
|
29
29
|
getTranscriptDisplayName,
|
|
30
30
|
getTranscriptFeatures,
|
|
31
|
-
} from '
|
|
31
|
+
} from './util'
|
|
32
|
+
|
|
33
|
+
// components
|
|
32
34
|
import TranscriptSelector from './TranscriptSelector'
|
|
35
|
+
import MSATable from './MSATable'
|
|
36
|
+
import HelpButton from './HelpButton'
|
|
33
37
|
|
|
34
38
|
// hooks
|
|
35
|
-
import
|
|
39
|
+
import useIsoformProteinSequences from './useIsoformProteinSequences'
|
|
40
|
+
import useLocalStructureFileSequence from './useLocalStructureFileSequence'
|
|
41
|
+
import useRemoteStructureFileSequence from './useRemoteStructureFileSequence'
|
|
36
42
|
|
|
37
43
|
const useStyles = makeStyles()(theme => ({
|
|
38
44
|
dialogContent: {
|
|
@@ -73,69 +79,71 @@ const UserProvidedStructure = observer(function ({
|
|
|
73
79
|
const { classes } = useStyles()
|
|
74
80
|
const session = getSession(model)
|
|
75
81
|
const [file, setFile] = useState<File>()
|
|
82
|
+
const [pdbId, setPdbId] = useState('')
|
|
76
83
|
const [choice, setChoice] = useState('file')
|
|
77
84
|
const [error2, setError] = useState<unknown>()
|
|
78
85
|
const [structureURL, setStructureURL] = useState('')
|
|
79
|
-
const [
|
|
86
|
+
const [userSelection, setUserSelection] = useState<string>()
|
|
87
|
+
const [showAllProteinSequences, setShowAllProteinSequences] = useState(false)
|
|
80
88
|
|
|
81
89
|
// check if we are looking at a 'two-level' or 'three-level' feature by
|
|
82
90
|
// finding exon/CDS subfeatures. we want to select from transcript names
|
|
83
91
|
const options = getTranscriptFeatures(feature)
|
|
84
92
|
const view = getContainingView(model) as LGV
|
|
85
|
-
const selectedTranscript = options.find(val => getId(val) ===
|
|
86
|
-
const {
|
|
87
|
-
|
|
93
|
+
const selectedTranscript = options.find(val => getId(val) === userSelection)
|
|
94
|
+
const { isoformSequences, error } = useIsoformProteinSequences({
|
|
95
|
+
feature,
|
|
96
|
+
view,
|
|
97
|
+
})
|
|
98
|
+
const protein = isoformSequences?.[userSelection ?? '']
|
|
99
|
+
const { sequences: structureSequences1, error: error3 } =
|
|
100
|
+
useLocalStructureFileSequence({ file })
|
|
101
|
+
|
|
102
|
+
const { sequences: structureSequences2, error: error4 } =
|
|
103
|
+
useRemoteStructureFileSequence({ url: structureURL })
|
|
104
|
+
const structureName =
|
|
105
|
+
file?.name ?? structureURL.slice(structureURL.lastIndexOf('/') + 1)
|
|
106
|
+
const structureSequences = structureSequences1 ?? structureSequences2
|
|
107
|
+
const structureSequence = structureSequences?.[0]
|
|
108
|
+
|
|
88
109
|
useEffect(() => {
|
|
89
|
-
if (
|
|
90
|
-
|
|
110
|
+
if (isoformSequences !== undefined) {
|
|
111
|
+
const ret =
|
|
112
|
+
options.find(
|
|
113
|
+
f =>
|
|
114
|
+
isoformSequences[f.id()]?.seq.replaceAll('*', '') ==
|
|
115
|
+
structureSequence,
|
|
116
|
+
) ?? options.find(f => !!isoformSequences[f.id()])
|
|
117
|
+
setUserSelection(ret?.id())
|
|
91
118
|
}
|
|
92
|
-
}, [options,
|
|
119
|
+
}, [options, structureSequence, isoformSequences])
|
|
93
120
|
|
|
94
|
-
const e = error || error2
|
|
121
|
+
const e = error || error2 || error3 || error4
|
|
95
122
|
return (
|
|
96
123
|
<>
|
|
97
124
|
<DialogContent className={classes.dialogContent}>
|
|
98
125
|
{e ? <ErrorMessage error={e} /> : null}
|
|
99
126
|
<HelpText />
|
|
100
|
-
|
|
101
|
-
<>
|
|
102
|
-
<TranscriptSelector
|
|
103
|
-
val={selection ?? ''}
|
|
104
|
-
setVal={setSelection}
|
|
105
|
-
options={options}
|
|
106
|
-
feature={feature}
|
|
107
|
-
seqs={seqs}
|
|
108
|
-
/>
|
|
109
|
-
{selectedTranscript ? (
|
|
110
|
-
<TextField
|
|
111
|
-
variant="outlined"
|
|
112
|
-
multiline
|
|
113
|
-
minRows={5}
|
|
114
|
-
maxRows={10}
|
|
115
|
-
fullWidth
|
|
116
|
-
value={`>${selectedTranscript.get('name') || selectedTranscript.get('id')}\n${protein}`}
|
|
117
|
-
InputProps={{
|
|
118
|
-
readOnly: true,
|
|
119
|
-
classes: {
|
|
120
|
-
input: classes.textAreaFont,
|
|
121
|
-
},
|
|
122
|
-
}}
|
|
123
|
-
/>
|
|
124
|
-
) : null}
|
|
125
|
-
</>
|
|
126
|
-
) : (
|
|
127
|
-
<div style={{ margin: 20 }}>
|
|
128
|
-
<LoadingEllipses title="Loading protein sequences" variant="h6" />
|
|
129
|
-
</div>
|
|
130
|
-
)}
|
|
127
|
+
|
|
131
128
|
<div style={{ display: 'flex', margin: 30 }}>
|
|
129
|
+
<Typography>
|
|
130
|
+
Open your structure file <HelpButton />
|
|
131
|
+
</Typography>
|
|
132
|
+
|
|
132
133
|
<FormControl component="fieldset">
|
|
133
134
|
<RadioGroup
|
|
134
135
|
value={choice}
|
|
135
|
-
onChange={event =>
|
|
136
|
+
onChange={event => {
|
|
137
|
+
setChoice(event.target.value)
|
|
138
|
+
}}
|
|
136
139
|
>
|
|
137
140
|
<FormControlLabel value="url" control={<Radio />} label="URL" />
|
|
138
141
|
<FormControlLabel value="file" control={<Radio />} label="File" />
|
|
142
|
+
<FormControlLabel
|
|
143
|
+
value="pdb"
|
|
144
|
+
control={<Radio />}
|
|
145
|
+
label="PDB ID"
|
|
146
|
+
/>
|
|
139
147
|
</RadioGroup>
|
|
140
148
|
</FormControl>
|
|
141
149
|
{choice === 'url' ? (
|
|
@@ -146,7 +154,9 @@ const UserProvidedStructure = observer(function ({
|
|
|
146
154
|
<TextField
|
|
147
155
|
label="URL"
|
|
148
156
|
value={structureURL}
|
|
149
|
-
onChange={event =>
|
|
157
|
+
onChange={event => {
|
|
158
|
+
setStructureURL(event.target.value)
|
|
159
|
+
}}
|
|
150
160
|
/>
|
|
151
161
|
</div>
|
|
152
162
|
) : null}
|
|
@@ -161,7 +171,7 @@ const UserProvidedStructure = observer(function ({
|
|
|
161
171
|
type="file"
|
|
162
172
|
hidden
|
|
163
173
|
onChange={({ target }) => {
|
|
164
|
-
const file = target
|
|
174
|
+
const file = target.files?.[0]
|
|
165
175
|
if (file) {
|
|
166
176
|
setFile(file)
|
|
167
177
|
}
|
|
@@ -170,13 +180,65 @@ const UserProvidedStructure = observer(function ({
|
|
|
170
180
|
</Button>
|
|
171
181
|
</div>
|
|
172
182
|
) : null}
|
|
183
|
+
{choice === 'pdb' ? (
|
|
184
|
+
<TextField
|
|
185
|
+
value={pdbId}
|
|
186
|
+
onChange={event => {
|
|
187
|
+
const s = event.target.value
|
|
188
|
+
setPdbId(s)
|
|
189
|
+
setStructureURL(`https://files.rcsb.org/download/${s}.cif`)
|
|
190
|
+
}}
|
|
191
|
+
label="PDB ID"
|
|
192
|
+
/>
|
|
193
|
+
) : null}
|
|
194
|
+
</div>
|
|
195
|
+
<div style={{ margin: 20 }}>
|
|
196
|
+
{isoformSequences ? (
|
|
197
|
+
structureSequence ? (
|
|
198
|
+
<>
|
|
199
|
+
<TranscriptSelector
|
|
200
|
+
val={userSelection ?? ''}
|
|
201
|
+
setVal={setUserSelection}
|
|
202
|
+
structureSequence={structureSequence}
|
|
203
|
+
isoforms={options}
|
|
204
|
+
feature={feature}
|
|
205
|
+
isoformSequences={isoformSequences}
|
|
206
|
+
/>
|
|
207
|
+
<div style={{ margin: 10 }}>
|
|
208
|
+
<Button
|
|
209
|
+
variant="contained"
|
|
210
|
+
color="primary"
|
|
211
|
+
onClick={() => {
|
|
212
|
+
setShowAllProteinSequences(!showAllProteinSequences)
|
|
213
|
+
}}
|
|
214
|
+
>
|
|
215
|
+
{showAllProteinSequences
|
|
216
|
+
? 'Hide all isoform protein sequences'
|
|
217
|
+
: 'Show all isoform protein sequences'}
|
|
218
|
+
</Button>
|
|
219
|
+
|
|
220
|
+
{showAllProteinSequences ? (
|
|
221
|
+
<MSATable
|
|
222
|
+
structureSequence={structureSequence}
|
|
223
|
+
structureName={structureName}
|
|
224
|
+
isoformSequences={isoformSequences}
|
|
225
|
+
/>
|
|
226
|
+
) : null}
|
|
227
|
+
</div>
|
|
228
|
+
</>
|
|
229
|
+
) : null
|
|
230
|
+
) : (
|
|
231
|
+
<LoadingEllipses title="Loading protein sequences" variant="h6" />
|
|
232
|
+
)}
|
|
173
233
|
</div>
|
|
174
234
|
</DialogContent>
|
|
175
235
|
<DialogActions>
|
|
176
236
|
<Button
|
|
177
237
|
variant="contained"
|
|
178
238
|
color="secondary"
|
|
179
|
-
onClick={() =>
|
|
239
|
+
onClick={() => {
|
|
240
|
+
handleClose()
|
|
241
|
+
}}
|
|
180
242
|
>
|
|
181
243
|
Cancel
|
|
182
244
|
</Button>
|
|
@@ -188,26 +250,15 @@ const UserProvidedStructure = observer(function ({
|
|
|
188
250
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
189
251
|
;(async () => {
|
|
190
252
|
try {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
})
|
|
201
|
-
} else if (structureURL) {
|
|
202
|
-
session.addView('ProteinView', {
|
|
203
|
-
type: 'ProteinView',
|
|
204
|
-
url: structureURL,
|
|
205
|
-
seq2: protein,
|
|
206
|
-
feature: selectedTranscript?.toJSON(),
|
|
207
|
-
connectedViewId: view.id,
|
|
208
|
-
displayName: `Protein view ${getGeneDisplayName(feature)} - ${getTranscriptDisplayName(selectedTranscript)}`,
|
|
209
|
-
})
|
|
210
|
-
}
|
|
253
|
+
session.addView('ProteinView', {
|
|
254
|
+
type: 'ProteinView',
|
|
255
|
+
seq2: protein,
|
|
256
|
+
feature: selectedTranscript?.toJSON(),
|
|
257
|
+
connectedViewId: view.id,
|
|
258
|
+
displayName: `Protein view ${getGeneDisplayName(feature)} - ${getTranscriptDisplayName(selectedTranscript)}`,
|
|
259
|
+
...(file ? { data: await file.text() } : {}),
|
|
260
|
+
...(structureURL ? { url: structureURL } : {}),
|
|
261
|
+
})
|
|
211
262
|
handleClose()
|
|
212
263
|
} catch (e) {
|
|
213
264
|
console.error(e)
|
package/src/LaunchProteinView/{calculateProteinSequence.ts → components/calculateProteinSequence.ts}
RENAMED
|
@@ -30,7 +30,7 @@ export function calculateProteinSequence({
|
|
|
30
30
|
let protein = ''
|
|
31
31
|
for (let i = 0; i < str.length; i += 3) {
|
|
32
32
|
// use & symbol for undefined codon, or partial slice
|
|
33
|
-
protein += codonTable[str.slice(i, i + 3)]
|
|
33
|
+
protein += codonTable[str.slice(i, i + 3)] ?? '&'
|
|
34
34
|
}
|
|
35
35
|
return protein
|
|
36
36
|
}
|
|
@@ -53,7 +53,7 @@ function getItemId(feat: Feat) {
|
|
|
53
53
|
// filters if successive elements share same start/end
|
|
54
54
|
export function dedupe(list: Feat[]) {
|
|
55
55
|
return list.filter(
|
|
56
|
-
(item, pos, ary) => !pos || getItemId(item) !== getItemId(ary[pos - 1]),
|
|
56
|
+
(item, pos, ary) => !pos || getItemId(item) !== getItemId(ary[pos - 1]!),
|
|
57
57
|
)
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -102,8 +102,10 @@ export async function fetchProteinSeq({
|
|
|
102
102
|
const refName = feature.get('refName')
|
|
103
103
|
const session = getSession(view)
|
|
104
104
|
const { assemblyManager, rpcManager } = session
|
|
105
|
-
const
|
|
106
|
-
const assembly =
|
|
105
|
+
const assemblyName = view?.assemblyNames?.[0]
|
|
106
|
+
const assembly = assemblyName
|
|
107
|
+
? await assemblyManager.waitForAssembly(assemblyName)
|
|
108
|
+
: undefined
|
|
107
109
|
if (!assembly) {
|
|
108
110
|
throw new Error('assembly not found')
|
|
109
111
|
}
|
package/src/LaunchProteinView/{useProteinSequences.ts → components/useIsoformProteinSequences.ts}
RENAMED
|
@@ -5,32 +5,37 @@ import { Feature } from '@jbrowse/core/util'
|
|
|
5
5
|
import { getTranscriptFeatures } from './util'
|
|
6
6
|
import { fetchProteinSeq } from './calculateProteinSequence'
|
|
7
7
|
|
|
8
|
-
export default function
|
|
8
|
+
export default function useIsoformProteinSequences({
|
|
9
9
|
feature,
|
|
10
10
|
view,
|
|
11
11
|
}: {
|
|
12
12
|
feature: Feature
|
|
13
|
-
view
|
|
13
|
+
view?: { assemblyNames?: string[] }
|
|
14
14
|
}) {
|
|
15
15
|
const [error, setError] = useState<unknown>()
|
|
16
|
-
const [
|
|
16
|
+
const [isoformSequences, setIsoformSequences] =
|
|
17
|
+
useState<Record<string, { feature: Feature; seq: string }>>()
|
|
18
|
+
const [isLoading, setLoading] = useState(false)
|
|
17
19
|
useEffect(() => {
|
|
18
20
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
19
21
|
;(async () => {
|
|
20
22
|
try {
|
|
21
|
-
|
|
23
|
+
setLoading(true)
|
|
24
|
+
const ret = [] as [string, { feature: Feature; seq: string }][]
|
|
22
25
|
for (const f of getTranscriptFeatures(feature)) {
|
|
23
26
|
const seq = await fetchProteinSeq({ view, feature: f })
|
|
24
27
|
if (seq) {
|
|
25
|
-
ret.push([f.id(), seq])
|
|
28
|
+
ret.push([f.id(), { feature: f, seq }])
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
|
-
|
|
31
|
+
setIsoformSequences(Object.fromEntries(ret))
|
|
29
32
|
} catch (e) {
|
|
30
33
|
console.error(e)
|
|
31
34
|
setError(e)
|
|
35
|
+
} finally {
|
|
36
|
+
setLoading(false)
|
|
32
37
|
}
|
|
33
38
|
})()
|
|
34
39
|
}, [feature, view])
|
|
35
|
-
return {
|
|
40
|
+
return { isLoading, isoformSequences, error }
|
|
36
41
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
import { createPluginUI } from 'molstar/lib/mol-plugin-ui'
|
|
3
|
+
import { renderReact18 } from 'molstar/lib/mol-plugin-ui/react18'
|
|
4
|
+
import { addStructureFromData } from '../../ProteinView/addStructureFromData'
|
|
5
|
+
|
|
6
|
+
async function structureFileSequenceFetcher(
|
|
7
|
+
file: File,
|
|
8
|
+
format: 'pdb' | 'mmcif',
|
|
9
|
+
) {
|
|
10
|
+
const ret = document.createElement('div')
|
|
11
|
+
const p = await createPluginUI({
|
|
12
|
+
target: ret,
|
|
13
|
+
render: renderReact18,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const { model } = await addStructureFromData({
|
|
18
|
+
data: await file.text(),
|
|
19
|
+
plugin: p,
|
|
20
|
+
format,
|
|
21
|
+
})
|
|
22
|
+
return model.obj?.data.sequence.sequences.map(s => {
|
|
23
|
+
let seq = ''
|
|
24
|
+
const arr = s.sequence.label.toArray()
|
|
25
|
+
// eslint-disable-next-line unicorn/no-for-loop,@typescript-eslint/prefer-for-of
|
|
26
|
+
for (let i = 0; i < arr.length; i++) {
|
|
27
|
+
seq += arr[i]!
|
|
28
|
+
}
|
|
29
|
+
return seq
|
|
30
|
+
})
|
|
31
|
+
} finally {
|
|
32
|
+
p.unmount()
|
|
33
|
+
ret.remove()
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default function useLocalStructureFileSequence({
|
|
38
|
+
file,
|
|
39
|
+
}: {
|
|
40
|
+
file?: File
|
|
41
|
+
}) {
|
|
42
|
+
const [error, setError] = useState<unknown>()
|
|
43
|
+
const [isLoading, setLoading] = useState(false)
|
|
44
|
+
const [sequences, setSequences] = useState<string[]>()
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
47
|
+
;(async () => {
|
|
48
|
+
try {
|
|
49
|
+
if (file) {
|
|
50
|
+
setLoading(true)
|
|
51
|
+
|
|
52
|
+
const ext = file.name.slice(file.name.lastIndexOf('.') + 1) || 'pdb'
|
|
53
|
+
const seq = await structureFileSequenceFetcher(
|
|
54
|
+
file,
|
|
55
|
+
(ext === 'cif' ? 'mmcif' : ext) as 'pdb' | 'mmcif',
|
|
56
|
+
)
|
|
57
|
+
if (seq) {
|
|
58
|
+
setSequences(seq)
|
|
59
|
+
} else {
|
|
60
|
+
throw new Error('no sequences detected in file')
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.error(e)
|
|
65
|
+
setError(e)
|
|
66
|
+
} finally {
|
|
67
|
+
setLoading(false)
|
|
68
|
+
}
|
|
69
|
+
})()
|
|
70
|
+
}, [file])
|
|
71
|
+
return { error, isLoading, sequences }
|
|
72
|
+
}
|
package/src/LaunchProteinView/{useMyGeneInfo.ts → components/useMyGeneInfoUniprotIdLookup.ts}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react'
|
|
2
|
-
import { jsonfetch } from '
|
|
2
|
+
import { jsonfetch } from '../../fetchUtils'
|
|
3
3
|
import { stripTrailingVersion } from './util'
|
|
4
4
|
|
|
5
5
|
interface MyGeneInfoResults {
|
|
@@ -13,25 +13,30 @@ interface MyGeneInfoResults {
|
|
|
13
13
|
export default function useMyGeneInfo({ id }: { id: string }) {
|
|
14
14
|
const [result, setResult] = useState<MyGeneInfoResults>()
|
|
15
15
|
const [error, setError] = useState<unknown>()
|
|
16
|
-
const [
|
|
16
|
+
const [isLoading, setLoading] = useState(false)
|
|
17
17
|
useEffect(() => {
|
|
18
18
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
19
19
|
;(async () => {
|
|
20
20
|
try {
|
|
21
|
-
if (
|
|
22
|
-
|
|
21
|
+
if (id) {
|
|
22
|
+
setLoading(true)
|
|
23
|
+
const res = await jsonfetch(
|
|
24
|
+
`https://mygene.info/v3/query?q=${stripTrailingVersion(id)}&fields=uniprot,symbol`,
|
|
25
|
+
)
|
|
26
|
+
setResult(res)
|
|
23
27
|
}
|
|
24
|
-
setLoading(true)
|
|
25
|
-
const res = await jsonfetch(
|
|
26
|
-
`https://mygene.info/v3/query?q=${stripTrailingVersion(id)}&fields=uniprot,symbol`,
|
|
27
|
-
)
|
|
28
|
-
setLoading(false)
|
|
29
|
-
setResult(res)
|
|
30
28
|
} catch (e) {
|
|
31
29
|
console.error(e)
|
|
32
30
|
setError(e)
|
|
31
|
+
} finally {
|
|
32
|
+
setLoading(false)
|
|
33
33
|
}
|
|
34
34
|
})()
|
|
35
35
|
}, [id])
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
isLoading,
|
|
39
|
+
uniprotId: result?.hits[0]?.uniprot?.['Swiss-Prot'],
|
|
40
|
+
error,
|
|
41
|
+
}
|
|
37
42
|
}
|