jbrowse-plugin-protein3d 0.0.3 → 0.0.5
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/HighlightComponents.d.ts +1 -2
- package/dist/AddHighlightModel/HighlightComponents.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 +162 -13
- package/dist/LaunchProteinView/components/AlphaFoldDBSearch.js.map +1 -1
- package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.js +8 -6
- 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 +3 -1
- package/dist/LaunchProteinView/components/HelpDialog.js.map +1 -1
- package/dist/LaunchProteinView/components/LaunchProteinViewDialog.js +12 -4
- package/dist/LaunchProteinView/components/LaunchProteinViewDialog.js.map +1 -1
- package/dist/LaunchProteinView/components/MSATable.js +3 -1
- package/dist/LaunchProteinView/components/MSATable.js.map +1 -1
- package/dist/LaunchProteinView/components/ManualUniProtIDEntry.d.ts +8 -0
- package/dist/LaunchProteinView/components/ManualUniProtIDEntry.js +225 -0
- package/dist/LaunchProteinView/components/ManualUniProtIDEntry.js.map +1 -0
- package/dist/LaunchProteinView/components/TranscriptSelector.js +3 -1
- package/dist/LaunchProteinView/components/TranscriptSelector.js.map +1 -1
- package/dist/LaunchProteinView/components/UserProvidedStructure.js +19 -12
- package/dist/LaunchProteinView/components/UserProvidedStructure.js.map +1 -1
- package/dist/LaunchProteinView/components/calculateProteinSequence.js +5 -3
- package/dist/LaunchProteinView/components/calculateProteinSequence.js.map +1 -1
- package/dist/LaunchProteinView/components/useLocalStructureFileSequence.d.ts +1 -1
- package/dist/LaunchProteinView/components/useLocalStructureFileSequence.js +29 -9
- package/dist/LaunchProteinView/components/useLocalStructureFileSequence.js.map +1 -1
- package/dist/LaunchProteinView/components/useRemoteStructureFileSequence.d.ts +1 -1
- package/dist/LaunchProteinView/components/useRemoteStructureFileSequence.js +25 -8
- package/dist/LaunchProteinView/components/useRemoteStructureFileSequence.js.map +1 -1
- package/dist/LaunchProteinView/components/util.js +1 -1
- package/dist/LaunchProteinView/index.js +7 -3
- 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 +3 -3
- 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 +492 -160
- package/dist/ProteinView/model.js +62 -246
- 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 -0
- package/dist/index.js.map +1 -1
- package/dist/jbrowse-plugin-protein3d.umd.production.min.js +2506 -1658
- 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 +20 -19
- package/src/AddHighlightModel/GenomeMouseoverHighlight.tsx +4 -17
- package/src/AddHighlightModel/HighlightComponents.tsx +1 -3
- 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 +173 -12
- package/src/LaunchProteinView/components/AlphaFoldDBSearchStatus.tsx +8 -6
- package/src/LaunchProteinView/components/HelpButton.tsx +10 -2
- package/src/LaunchProteinView/components/HelpDialog.tsx +6 -1
- package/src/LaunchProteinView/components/LaunchProteinViewDialog.tsx +20 -4
- package/src/LaunchProteinView/components/MSATable.tsx +3 -1
- package/src/LaunchProteinView/components/ManualUniProtIDEntry.tsx +332 -0
- package/src/LaunchProteinView/components/TranscriptSelector.tsx +9 -7
- package/src/LaunchProteinView/components/UserProvidedStructure.tsx +18 -13
- package/src/LaunchProteinView/components/calculateProteinSequence.ts +6 -4
- package/src/LaunchProteinView/components/useLocalStructureFileSequence.ts +28 -9
- package/src/LaunchProteinView/components/useRemoteStructureFileSequence.ts +23 -8
- package/src/LaunchProteinView/components/util.ts +1 -1
- 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 -23
- package/src/ProteinView/components/SplitString.tsx +8 -8
- 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 +75 -287
- 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 +6 -0
- package/src/mappings.test.ts +7 -5
- package/src/mappings.ts +25 -23
- package/src/test_data/gene.ts +3 -3
- 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/ProteinView/useProteinViewClickBehavior.ts +0 -48
- package/src/ProteinView/useProteinViewHoverBehavior.ts +0 -44
- /package/dist/ProteinView/components/{Header.d.ts → ProteinViewHeader.d.ts} +0 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
|
+
import { observer } from 'mobx-react'
|
|
3
|
+
import {
|
|
4
|
+
Button,
|
|
5
|
+
DialogActions,
|
|
6
|
+
DialogContent,
|
|
7
|
+
TextField,
|
|
8
|
+
Typography,
|
|
9
|
+
} from '@mui/material'
|
|
10
|
+
import { makeStyles } from 'tss-react/mui'
|
|
11
|
+
import {
|
|
12
|
+
AbstractTrackModel,
|
|
13
|
+
Feature,
|
|
14
|
+
getContainingView,
|
|
15
|
+
getSession,
|
|
16
|
+
isSessionWithAddTracks,
|
|
17
|
+
} from '@jbrowse/core/util'
|
|
18
|
+
import { ErrorMessage, LoadingEllipses } from '@jbrowse/core/ui'
|
|
19
|
+
import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
20
|
+
|
|
21
|
+
// locals
|
|
22
|
+
import {
|
|
23
|
+
getId,
|
|
24
|
+
getGeneDisplayName,
|
|
25
|
+
getTranscriptDisplayName,
|
|
26
|
+
getTranscriptFeatures,
|
|
27
|
+
} from './util'
|
|
28
|
+
|
|
29
|
+
// components
|
|
30
|
+
import TranscriptSelector from './TranscriptSelector'
|
|
31
|
+
import AlphaFoldDBSearchStatus from './AlphaFoldDBSearchStatus'
|
|
32
|
+
|
|
33
|
+
// hooks
|
|
34
|
+
import useRemoteStructureFileSequence from './useRemoteStructureFileSequence'
|
|
35
|
+
import useIsoformProteinSequences from './useIsoformProteinSequences'
|
|
36
|
+
|
|
37
|
+
const useStyles = makeStyles()(theme => ({
|
|
38
|
+
dialogContent: {
|
|
39
|
+
marginTop: theme.spacing(6),
|
|
40
|
+
width: '80em',
|
|
41
|
+
},
|
|
42
|
+
}))
|
|
43
|
+
|
|
44
|
+
const ManualUniProtIDEntry = observer(function ({
|
|
45
|
+
feature,
|
|
46
|
+
model,
|
|
47
|
+
handleClose,
|
|
48
|
+
}: {
|
|
49
|
+
feature: Feature
|
|
50
|
+
model: AbstractTrackModel
|
|
51
|
+
handleClose: () => void
|
|
52
|
+
}) {
|
|
53
|
+
const { classes } = useStyles()
|
|
54
|
+
const session = getSession(model)
|
|
55
|
+
|
|
56
|
+
// check if we are looking at a 'two-level' or 'three-level' feature by
|
|
57
|
+
// finding exon/CDS subfeatures. we want to select from transcript names
|
|
58
|
+
const options = getTranscriptFeatures(feature)
|
|
59
|
+
const [userSelection, setUserSelection] = useState<string>()
|
|
60
|
+
const view = getContainingView(model) as LinearGenomeViewModel
|
|
61
|
+
const selectedTranscript = options.find(val => getId(val) === userSelection)
|
|
62
|
+
const {
|
|
63
|
+
isoformSequences,
|
|
64
|
+
isLoading: isIsoformProteinSequencesLoading,
|
|
65
|
+
error: isoformProteinSequencesError,
|
|
66
|
+
} = useIsoformProteinSequences({
|
|
67
|
+
feature,
|
|
68
|
+
view,
|
|
69
|
+
})
|
|
70
|
+
const userSelectedProteinSequence = isoformSequences?.[userSelection ?? '']
|
|
71
|
+
const [uniprotId, setUniprotId] = useState('')
|
|
72
|
+
const url = uniprotId
|
|
73
|
+
? `https://alphafold.ebi.ac.uk/files/AF-${uniprotId}-F1-model_v4.cif`
|
|
74
|
+
: undefined
|
|
75
|
+
const {
|
|
76
|
+
sequences: structureSequences,
|
|
77
|
+
isLoading: isRemoteStructureSequenceLoading,
|
|
78
|
+
error: remoteStructureSequenceError,
|
|
79
|
+
} = useRemoteStructureFileSequence({ url })
|
|
80
|
+
const e = isoformProteinSequencesError || remoteStructureSequenceError
|
|
81
|
+
|
|
82
|
+
const structureSequence = structureSequences?.[0]
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (isoformSequences !== undefined) {
|
|
85
|
+
const ret =
|
|
86
|
+
options.find(
|
|
87
|
+
f =>
|
|
88
|
+
isoformSequences[f.id()]?.seq.replaceAll('*', '') ==
|
|
89
|
+
structureSequence,
|
|
90
|
+
) ?? options.find(f => !!isoformSequences[f.id()])
|
|
91
|
+
setUserSelection(ret?.id())
|
|
92
|
+
}
|
|
93
|
+
}, [options, structureSequence, isoformSequences])
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<>
|
|
97
|
+
<DialogContent className={classes.dialogContent}>
|
|
98
|
+
{e ? <ErrorMessage error={e} /> : null}
|
|
99
|
+
<Typography>Manually enter a UniProt ID</Typography>
|
|
100
|
+
{isRemoteStructureSequenceLoading ? (
|
|
101
|
+
<LoadingEllipses
|
|
102
|
+
variant="h6"
|
|
103
|
+
message="Loading sequence from remote structure file"
|
|
104
|
+
/>
|
|
105
|
+
) : null}
|
|
106
|
+
|
|
107
|
+
<TextField
|
|
108
|
+
label="UniProt ID"
|
|
109
|
+
value={uniprotId}
|
|
110
|
+
onChange={event => {
|
|
111
|
+
setUniprotId(event.target.value)
|
|
112
|
+
}}
|
|
113
|
+
/>
|
|
114
|
+
{isIsoformProteinSequencesLoading ? (
|
|
115
|
+
<LoadingEllipses
|
|
116
|
+
variant="h6"
|
|
117
|
+
message="Loading protein sequences from transcript isoforms"
|
|
118
|
+
/>
|
|
119
|
+
) : null}
|
|
120
|
+
{isoformSequences && structureSequence && selectedTranscript ? (
|
|
121
|
+
<>
|
|
122
|
+
<TranscriptSelector
|
|
123
|
+
val={userSelection ?? ''}
|
|
124
|
+
setVal={setUserSelection}
|
|
125
|
+
structureSequence={structureSequence}
|
|
126
|
+
feature={feature}
|
|
127
|
+
isoforms={options}
|
|
128
|
+
isoformSequences={isoformSequences}
|
|
129
|
+
/>
|
|
130
|
+
<AlphaFoldDBSearchStatus
|
|
131
|
+
uniprotId={uniprotId}
|
|
132
|
+
selectedTranscript={selectedTranscript}
|
|
133
|
+
structureSequence={structureSequence}
|
|
134
|
+
isoformSequences={isoformSequences}
|
|
135
|
+
/>
|
|
136
|
+
</>
|
|
137
|
+
) : null}
|
|
138
|
+
</DialogContent>
|
|
139
|
+
<DialogActions>
|
|
140
|
+
<Button
|
|
141
|
+
variant="contained"
|
|
142
|
+
color="secondary"
|
|
143
|
+
onClick={() => {
|
|
144
|
+
handleClose()
|
|
145
|
+
}}
|
|
146
|
+
>
|
|
147
|
+
Cancel
|
|
148
|
+
</Button>
|
|
149
|
+
<Button
|
|
150
|
+
variant="contained"
|
|
151
|
+
color="primary"
|
|
152
|
+
disabled={
|
|
153
|
+
!uniprotId || !userSelectedProteinSequence || !selectedTranscript
|
|
154
|
+
}
|
|
155
|
+
onClick={() => {
|
|
156
|
+
session.addView('ProteinView', {
|
|
157
|
+
type: 'ProteinView',
|
|
158
|
+
isFloating: true,
|
|
159
|
+
structures: [
|
|
160
|
+
{
|
|
161
|
+
url,
|
|
162
|
+
userProvidedTranscriptSequence:
|
|
163
|
+
userSelectedProteinSequence?.seq,
|
|
164
|
+
feature: selectedTranscript?.toJSON(),
|
|
165
|
+
connectedViewId: view.id,
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
displayName: [
|
|
169
|
+
'Protein view',
|
|
170
|
+
uniprotId,
|
|
171
|
+
getGeneDisplayName(feature),
|
|
172
|
+
getTranscriptDisplayName(selectedTranscript),
|
|
173
|
+
].join(' - '),
|
|
174
|
+
})
|
|
175
|
+
handleClose()
|
|
176
|
+
}}
|
|
177
|
+
>
|
|
178
|
+
Launch 3-D protein structure view
|
|
179
|
+
</Button>
|
|
180
|
+
<Button
|
|
181
|
+
variant="contained"
|
|
182
|
+
disabled={
|
|
183
|
+
!uniprotId || !userSelectedProteinSequence || !selectedTranscript
|
|
184
|
+
}
|
|
185
|
+
onClick={() => {
|
|
186
|
+
if (uniprotId && isSessionWithAddTracks(session)) {
|
|
187
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
188
|
+
;(async () => {
|
|
189
|
+
try {
|
|
190
|
+
session.addTemporaryAssembly?.({
|
|
191
|
+
name: uniprotId,
|
|
192
|
+
sequence: {
|
|
193
|
+
type: 'ReferenceSequenceTrack',
|
|
194
|
+
trackId: `${uniprotId}-ReferenceSequenceTrack`,
|
|
195
|
+
sequenceType: 'pep',
|
|
196
|
+
adapter: {
|
|
197
|
+
type: 'UnindexedFastaAdapter',
|
|
198
|
+
rewriteRefNames: "jexl:split(refName,'|')[1]",
|
|
199
|
+
fastaLocation: {
|
|
200
|
+
uri: `https://rest.uniprot.org/uniprotkb/${uniprotId}.fasta`,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
})
|
|
205
|
+
const url = `https://rest.uniprot.org/uniprotkb/${uniprotId}.gff`
|
|
206
|
+
const res = await fetch(url)
|
|
207
|
+
if (!res.ok) {
|
|
208
|
+
throw new Error(`HTTP ${res.status} fetching ${url}`)
|
|
209
|
+
}
|
|
210
|
+
const data = await res.text()
|
|
211
|
+
|
|
212
|
+
const types = [
|
|
213
|
+
...new Set(
|
|
214
|
+
data
|
|
215
|
+
.split('\n')
|
|
216
|
+
.filter(f => !f.startsWith('#'))
|
|
217
|
+
.map(f => f.trim())
|
|
218
|
+
.filter(f => !!f)
|
|
219
|
+
.map(f => f.split('\t')[2]),
|
|
220
|
+
),
|
|
221
|
+
]
|
|
222
|
+
types.forEach(type => {
|
|
223
|
+
const s = `${uniprotId}-${type}`
|
|
224
|
+
session.addTrackConf({
|
|
225
|
+
type: 'FeatureTrack',
|
|
226
|
+
trackId: s,
|
|
227
|
+
name: type,
|
|
228
|
+
adapter: {
|
|
229
|
+
type: 'Gff3Adapter',
|
|
230
|
+
gffLocation: {
|
|
231
|
+
uri: `https://rest.uniprot.org/uniprotkb/${uniprotId}.gff`,
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
assemblyNames: [uniprotId],
|
|
235
|
+
displays: [
|
|
236
|
+
{
|
|
237
|
+
displayId: `${type}-LinearBasicDisplay`,
|
|
238
|
+
type: 'LinearBasicDisplay',
|
|
239
|
+
jexlFilters: [`get(feature,'type')=='${type}'`],
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
})
|
|
243
|
+
})
|
|
244
|
+
session.addTrackConf({
|
|
245
|
+
type: 'FeatureTrack',
|
|
246
|
+
trackId: 'Antigen',
|
|
247
|
+
name: 'Antigen',
|
|
248
|
+
adapter: {
|
|
249
|
+
type: 'Gff3Adapter',
|
|
250
|
+
gffLocation: {
|
|
251
|
+
uri: `https://www.ebi.ac.uk/proteins/api/antigen/${uniprotId}?format=gff`,
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
assemblyNames: [uniprotId],
|
|
255
|
+
})
|
|
256
|
+
session.addTrackConf({
|
|
257
|
+
type: 'FeatureTrack',
|
|
258
|
+
trackId: 'Variation',
|
|
259
|
+
name: 'Variation',
|
|
260
|
+
adapter: {
|
|
261
|
+
type: 'UniProtVariationAdapter',
|
|
262
|
+
location: {
|
|
263
|
+
uri: `https://www.ebi.ac.uk/proteins/api/variation/${uniprotId}.json`,
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
assemblyNames: [uniprotId],
|
|
267
|
+
})
|
|
268
|
+
session.addTrackConf({
|
|
269
|
+
type: 'QuantitativeTrack',
|
|
270
|
+
trackId: 'AlphaFold confidence',
|
|
271
|
+
name: 'AlphaFold confidence',
|
|
272
|
+
adapter: {
|
|
273
|
+
type: 'AlphaFoldConfidenceAdapter',
|
|
274
|
+
location: {
|
|
275
|
+
uri: `https://alphafold.ebi.ac.uk/files/AF-${uniprotId}-F1-confidence_v4.json`,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
assemblyNames: [uniprotId],
|
|
279
|
+
})
|
|
280
|
+
session.addTrackConf({
|
|
281
|
+
type: 'MultiQuantitativeTrack',
|
|
282
|
+
trackId: 'AlphaMissense scores',
|
|
283
|
+
name: 'AlphaMissense scores',
|
|
284
|
+
assemblyNames: [uniprotId],
|
|
285
|
+
adapter: {
|
|
286
|
+
type: 'AlphaMissensePathogenicityAdapter',
|
|
287
|
+
location: {
|
|
288
|
+
uri: `https://alphafold.ebi.ac.uk/files/AF-${uniprotId}-F1-aa-substitutions.csv`,
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
displays: [
|
|
292
|
+
{
|
|
293
|
+
type: 'MultiLinearWiggleDisplay',
|
|
294
|
+
displayId:
|
|
295
|
+
'AlphaMissense scores-MultiLinearWiggleDisplay',
|
|
296
|
+
defaultRendering: 'multirowdensity',
|
|
297
|
+
renderers: {
|
|
298
|
+
MultiDensityRenderer: {
|
|
299
|
+
type: 'MultiDensityRenderer',
|
|
300
|
+
bicolorPivotValue: 0.5,
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
})
|
|
306
|
+
const view = session.addView('LinearGenomeView', {
|
|
307
|
+
type: 'LinearGenomeView',
|
|
308
|
+
displayName: [
|
|
309
|
+
'Protein view',
|
|
310
|
+
uniprotId,
|
|
311
|
+
getGeneDisplayName(feature),
|
|
312
|
+
getTranscriptDisplayName(selectedTranscript),
|
|
313
|
+
].join(' - '),
|
|
314
|
+
}) as LinearGenomeViewModel
|
|
315
|
+
await view.navToLocString(uniprotId, uniprotId)
|
|
316
|
+
} catch (e) {
|
|
317
|
+
console.error(e)
|
|
318
|
+
session.notifyError(`${e}`, e)
|
|
319
|
+
}
|
|
320
|
+
})()
|
|
321
|
+
}
|
|
322
|
+
handleClose()
|
|
323
|
+
}}
|
|
324
|
+
>
|
|
325
|
+
Launch linear protein annotation view
|
|
326
|
+
</Button>
|
|
327
|
+
</DialogActions>
|
|
328
|
+
</>
|
|
329
|
+
)
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
export default ManualUniProtIDEntry
|
|
@@ -31,7 +31,9 @@ export default function TranscriptSelector({
|
|
|
31
31
|
return (
|
|
32
32
|
<TextField2
|
|
33
33
|
value={val}
|
|
34
|
-
onChange={event =>
|
|
34
|
+
onChange={event => {
|
|
35
|
+
setVal(event.target.value)
|
|
36
|
+
}}
|
|
35
37
|
label="Choose transcript isoform"
|
|
36
38
|
select
|
|
37
39
|
>
|
|
@@ -39,13 +41,13 @@ export default function TranscriptSelector({
|
|
|
39
41
|
.filter(f => !!isoformSequences[f.id()])
|
|
40
42
|
.filter(
|
|
41
43
|
f =>
|
|
42
|
-
isoformSequences[f.id()]
|
|
44
|
+
isoformSequences[f.id()]!.seq.replaceAll('*', '') ===
|
|
43
45
|
structureSequence,
|
|
44
46
|
)
|
|
45
47
|
.map(f => (
|
|
46
48
|
<MenuItem value={f.id()} key={f.id()}>
|
|
47
49
|
{getGeneDisplayName(feature)} - {getTranscriptDisplayName(f)} (
|
|
48
|
-
{isoformSequences[f.id()]
|
|
50
|
+
{isoformSequences[f.id()]!.seq.length}aa) (matches structure
|
|
49
51
|
residues)
|
|
50
52
|
</MenuItem>
|
|
51
53
|
))}
|
|
@@ -53,18 +55,18 @@ export default function TranscriptSelector({
|
|
|
53
55
|
.filter(f => !!isoformSequences[f.id()])
|
|
54
56
|
.filter(
|
|
55
57
|
f =>
|
|
56
|
-
isoformSequences[f.id()]
|
|
58
|
+
isoformSequences[f.id()]!.seq.replaceAll('*', '') !==
|
|
57
59
|
structureSequence,
|
|
58
60
|
)
|
|
59
61
|
.sort(
|
|
60
62
|
(a, b) =>
|
|
61
|
-
isoformSequences[b.id()]
|
|
62
|
-
isoformSequences[a.id()]
|
|
63
|
+
isoformSequences[b.id()]!.seq.length -
|
|
64
|
+
isoformSequences[a.id()]!.seq.length,
|
|
63
65
|
)
|
|
64
66
|
.map(f => (
|
|
65
67
|
<MenuItem value={f.id()} key={f.id()}>
|
|
66
68
|
{getGeneDisplayName(feature)} - {getTranscriptDisplayName(f)} (
|
|
67
|
-
{isoformSequences[f.id()]
|
|
69
|
+
{isoformSequences[f.id()]!.seq.length}aa)
|
|
68
70
|
</MenuItem>
|
|
69
71
|
))}
|
|
70
72
|
{isoforms
|
|
@@ -96,16 +96,15 @@ const UserProvidedStructure = observer(function ({
|
|
|
96
96
|
view,
|
|
97
97
|
})
|
|
98
98
|
const protein = isoformSequences?.[userSelection ?? '']
|
|
99
|
-
const {
|
|
99
|
+
const { sequences: structureSequences1, error: error3 } =
|
|
100
100
|
useLocalStructureFileSequence({ file })
|
|
101
101
|
|
|
102
|
-
const {
|
|
102
|
+
const { sequences: structureSequences2, error: error4 } =
|
|
103
103
|
useRemoteStructureFileSequence({ url: structureURL })
|
|
104
104
|
const structureName =
|
|
105
|
-
file?.name ??
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const structureSequence = structureSequence1 ?? structureSequence2
|
|
105
|
+
file?.name ?? structureURL.slice(structureURL.lastIndexOf('/') + 1)
|
|
106
|
+
const structureSequences = structureSequences1 ?? structureSequences2
|
|
107
|
+
const structureSequence = structureSequences?.[0]
|
|
109
108
|
|
|
110
109
|
useEffect(() => {
|
|
111
110
|
if (isoformSequences !== undefined) {
|
|
@@ -134,7 +133,9 @@ const UserProvidedStructure = observer(function ({
|
|
|
134
133
|
<FormControl component="fieldset">
|
|
135
134
|
<RadioGroup
|
|
136
135
|
value={choice}
|
|
137
|
-
onChange={event =>
|
|
136
|
+
onChange={event => {
|
|
137
|
+
setChoice(event.target.value)
|
|
138
|
+
}}
|
|
138
139
|
>
|
|
139
140
|
<FormControlLabel value="url" control={<Radio />} label="URL" />
|
|
140
141
|
<FormControlLabel value="file" control={<Radio />} label="File" />
|
|
@@ -153,7 +154,9 @@ const UserProvidedStructure = observer(function ({
|
|
|
153
154
|
<TextField
|
|
154
155
|
label="URL"
|
|
155
156
|
value={structureURL}
|
|
156
|
-
onChange={event =>
|
|
157
|
+
onChange={event => {
|
|
158
|
+
setStructureURL(event.target.value)
|
|
159
|
+
}}
|
|
157
160
|
/>
|
|
158
161
|
</div>
|
|
159
162
|
) : null}
|
|
@@ -168,7 +171,7 @@ const UserProvidedStructure = observer(function ({
|
|
|
168
171
|
type="file"
|
|
169
172
|
hidden
|
|
170
173
|
onChange={({ target }) => {
|
|
171
|
-
const file = target
|
|
174
|
+
const file = target.files?.[0]
|
|
172
175
|
if (file) {
|
|
173
176
|
setFile(file)
|
|
174
177
|
}
|
|
@@ -205,9 +208,9 @@ const UserProvidedStructure = observer(function ({
|
|
|
205
208
|
<Button
|
|
206
209
|
variant="contained"
|
|
207
210
|
color="primary"
|
|
208
|
-
onClick={() =>
|
|
211
|
+
onClick={() => {
|
|
209
212
|
setShowAllProteinSequences(!showAllProteinSequences)
|
|
210
|
-
}
|
|
213
|
+
}}
|
|
211
214
|
>
|
|
212
215
|
{showAllProteinSequences
|
|
213
216
|
? 'Hide all isoform protein sequences'
|
|
@@ -233,7 +236,9 @@ const UserProvidedStructure = observer(function ({
|
|
|
233
236
|
<Button
|
|
234
237
|
variant="contained"
|
|
235
238
|
color="secondary"
|
|
236
|
-
onClick={() =>
|
|
239
|
+
onClick={() => {
|
|
240
|
+
handleClose()
|
|
241
|
+
}}
|
|
237
242
|
>
|
|
238
243
|
Cancel
|
|
239
244
|
</Button>
|
|
@@ -262,7 +267,7 @@ const UserProvidedStructure = observer(function ({
|
|
|
262
267
|
})()
|
|
263
268
|
}}
|
|
264
269
|
>
|
|
265
|
-
|
|
270
|
+
Launch 3-D protein structure view
|
|
266
271
|
</Button>
|
|
267
272
|
</DialogActions>
|
|
268
273
|
</>
|
|
@@ -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
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react'
|
|
2
2
|
import { createPluginUI } from 'molstar/lib/mol-plugin-ui'
|
|
3
3
|
import { renderReact18 } from 'molstar/lib/mol-plugin-ui/react18'
|
|
4
|
-
import {
|
|
4
|
+
import { addStructureFromData } from '../../ProteinView/addStructureFromData'
|
|
5
5
|
|
|
6
6
|
async function structureFileSequenceFetcher(
|
|
7
7
|
file: File,
|
|
@@ -12,11 +12,26 @@ async function structureFileSequenceFetcher(
|
|
|
12
12
|
target: ret,
|
|
13
13
|
render: renderReact18,
|
|
14
14
|
})
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
+
}
|
|
20
35
|
}
|
|
21
36
|
|
|
22
37
|
export default function useLocalStructureFileSequence({
|
|
@@ -26,7 +41,7 @@ export default function useLocalStructureFileSequence({
|
|
|
26
41
|
}) {
|
|
27
42
|
const [error, setError] = useState<unknown>()
|
|
28
43
|
const [isLoading, setLoading] = useState(false)
|
|
29
|
-
const [
|
|
44
|
+
const [sequences, setSequences] = useState<string[]>()
|
|
30
45
|
useEffect(() => {
|
|
31
46
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
32
47
|
;(async () => {
|
|
@@ -39,7 +54,11 @@ export default function useLocalStructureFileSequence({
|
|
|
39
54
|
file,
|
|
40
55
|
(ext === 'cif' ? 'mmcif' : ext) as 'pdb' | 'mmcif',
|
|
41
56
|
)
|
|
42
|
-
|
|
57
|
+
if (seq) {
|
|
58
|
+
setSequences(seq)
|
|
59
|
+
} else {
|
|
60
|
+
throw new Error('no sequences detected in file')
|
|
61
|
+
}
|
|
43
62
|
}
|
|
44
63
|
} catch (e) {
|
|
45
64
|
console.error(e)
|
|
@@ -49,5 +68,5 @@ export default function useLocalStructureFileSequence({
|
|
|
49
68
|
}
|
|
50
69
|
})()
|
|
51
70
|
}, [file])
|
|
52
|
-
return { error, isLoading,
|
|
71
|
+
return { error, isLoading, sequences }
|
|
53
72
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react'
|
|
2
2
|
import { createPluginUI } from 'molstar/lib/mol-plugin-ui'
|
|
3
3
|
import { renderReact18 } from 'molstar/lib/mol-plugin-ui/react18'
|
|
4
|
-
import {
|
|
4
|
+
import { addStructureFromURL } from '../../ProteinView/addStructureFromURL'
|
|
5
5
|
|
|
6
6
|
async function structureFileSequenceFetcher(url: string) {
|
|
7
7
|
const ret = document.createElement('div')
|
|
@@ -9,10 +9,21 @@ async function structureFileSequenceFetcher(url: string) {
|
|
|
9
9
|
target: ret,
|
|
10
10
|
render: renderReact18,
|
|
11
11
|
})
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
try {
|
|
13
|
+
const { model } = await addStructureFromURL({ url, plugin: p })
|
|
14
|
+
return model.obj?.data.sequence.sequences.map(s => {
|
|
15
|
+
let seq = ''
|
|
16
|
+
const arr = s.sequence.label.toArray()
|
|
17
|
+
// eslint-disable-next-line unicorn/no-for-loop,@typescript-eslint/prefer-for-of
|
|
18
|
+
for (let i = 0; i < arr.length; i++) {
|
|
19
|
+
seq += arr[i]!
|
|
20
|
+
}
|
|
21
|
+
return seq
|
|
22
|
+
})
|
|
23
|
+
} finally {
|
|
24
|
+
p.unmount()
|
|
25
|
+
ret.remove()
|
|
26
|
+
}
|
|
16
27
|
}
|
|
17
28
|
|
|
18
29
|
export default function useRemoteStructureFileSequence({
|
|
@@ -22,7 +33,7 @@ export default function useRemoteStructureFileSequence({
|
|
|
22
33
|
}) {
|
|
23
34
|
const [error, setError] = useState<unknown>()
|
|
24
35
|
const [isLoading, setLoading] = useState(false)
|
|
25
|
-
const [
|
|
36
|
+
const [sequences, setSequences] = useState<string[]>()
|
|
26
37
|
useEffect(() => {
|
|
27
38
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
28
39
|
;(async () => {
|
|
@@ -30,7 +41,11 @@ export default function useRemoteStructureFileSequence({
|
|
|
30
41
|
if (url) {
|
|
31
42
|
setLoading(true)
|
|
32
43
|
const seq = await structureFileSequenceFetcher(url)
|
|
33
|
-
|
|
44
|
+
if (seq) {
|
|
45
|
+
setSequences(seq)
|
|
46
|
+
} else {
|
|
47
|
+
throw new Error('no sequences detected in file')
|
|
48
|
+
}
|
|
34
49
|
}
|
|
35
50
|
} catch (e) {
|
|
36
51
|
console.error(e)
|
|
@@ -40,5 +55,5 @@ export default function useRemoteStructureFileSequence({
|
|
|
40
55
|
}
|
|
41
56
|
})()
|
|
42
57
|
}, [url])
|
|
43
|
-
return { error, isLoading,
|
|
58
|
+
return { error, isLoading, sequences }
|
|
44
59
|
}
|