jbrowse-plugin-protein3d 0.0.3 → 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.
Files changed (189) hide show
  1. package/dist/AddHighlightModel/GenomeMouseoverHighlight.js +3 -9
  2. package/dist/AddHighlightModel/GenomeMouseoverHighlight.js.map +1 -1
  3. package/dist/AddHighlightModel/ProteinToGenomeClickHighlight.js +4 -3
  4. package/dist/AddHighlightModel/ProteinToGenomeClickHighlight.js.map +1 -1
  5. package/dist/AddHighlightModel/ProteinToGenomeHoverHighlight.d.ts +1 -2
  6. package/dist/AddHighlightModel/ProteinToGenomeHoverHighlight.js +4 -3
  7. package/dist/AddHighlightModel/ProteinToGenomeHoverHighlight.js.map +1 -1
  8. package/dist/AddHighlightModel/util.js +1 -1
  9. package/dist/AddHighlightModel/util.js.map +1 -1
  10. package/dist/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.d.ts +16 -0
  11. package/dist/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.js +43 -0
  12. package/dist/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.js.map +1 -0
  13. package/dist/AlphaFoldConfidenceAdapter/configSchema.d.ts +13 -0
  14. package/dist/AlphaFoldConfidenceAdapter/configSchema.js +16 -0
  15. package/dist/AlphaFoldConfidenceAdapter/configSchema.js.map +1 -0
  16. package/dist/AlphaFoldConfidenceAdapter/index.d.ts +2 -0
  17. package/dist/AlphaFoldConfidenceAdapter/index.js +11 -0
  18. package/dist/AlphaFoldConfidenceAdapter/index.js.map +1 -0
  19. package/dist/AlphaMissensePathogenicityAdapter/AlphaMissensePathogenicityAdapter.d.ts +30 -0
  20. package/dist/AlphaMissensePathogenicityAdapter/AlphaMissensePathogenicityAdapter.js +78 -0
  21. package/dist/AlphaMissensePathogenicityAdapter/AlphaMissensePathogenicityAdapter.js.map +1 -0
  22. package/dist/AlphaMissensePathogenicityAdapter/configSchema.d.ts +13 -0
  23. package/dist/AlphaMissensePathogenicityAdapter/configSchema.js +16 -0
  24. package/dist/AlphaMissensePathogenicityAdapter/configSchema.js.map +1 -0
  25. package/dist/AlphaMissensePathogenicityAdapter/index.d.ts +2 -0
  26. package/dist/AlphaMissensePathogenicityAdapter/index.js +11 -0
  27. package/dist/AlphaMissensePathogenicityAdapter/index.js.map +1 -0
  28. package/dist/LaunchProteinView/components/AlphaFoldDBSearch.js +161 -11
  29. package/dist/LaunchProteinView/components/AlphaFoldDBSearch.js.map +1 -1
  30. package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.js +8 -6
  31. package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.js.map +1 -1
  32. package/dist/LaunchProteinView/components/HelpButton.js +6 -2
  33. package/dist/LaunchProteinView/components/HelpButton.js.map +1 -1
  34. package/dist/LaunchProteinView/components/HelpDialog.js +3 -1
  35. package/dist/LaunchProteinView/components/HelpDialog.js.map +1 -1
  36. package/dist/LaunchProteinView/components/LaunchProteinViewDialog.js +6 -2
  37. package/dist/LaunchProteinView/components/LaunchProteinViewDialog.js.map +1 -1
  38. package/dist/LaunchProteinView/components/MSATable.js +3 -1
  39. package/dist/LaunchProteinView/components/MSATable.js.map +1 -1
  40. package/dist/LaunchProteinView/components/TranscriptSelector.js +3 -1
  41. package/dist/LaunchProteinView/components/TranscriptSelector.js.map +1 -1
  42. package/dist/LaunchProteinView/components/UserProvidedStructure.js +18 -11
  43. package/dist/LaunchProteinView/components/UserProvidedStructure.js.map +1 -1
  44. package/dist/LaunchProteinView/components/calculateProteinSequence.js +5 -3
  45. package/dist/LaunchProteinView/components/calculateProteinSequence.js.map +1 -1
  46. package/dist/LaunchProteinView/components/useLocalStructureFileSequence.d.ts +1 -1
  47. package/dist/LaunchProteinView/components/useLocalStructureFileSequence.js +29 -9
  48. package/dist/LaunchProteinView/components/useLocalStructureFileSequence.js.map +1 -1
  49. package/dist/LaunchProteinView/components/useRemoteStructureFileSequence.d.ts +1 -1
  50. package/dist/LaunchProteinView/components/useRemoteStructureFileSequence.js +25 -8
  51. package/dist/LaunchProteinView/components/useRemoteStructureFileSequence.js.map +1 -1
  52. package/dist/LaunchProteinView/components/util.js +1 -1
  53. package/dist/LaunchProteinView/index.js +7 -3
  54. package/dist/LaunchProteinView/index.js.map +1 -1
  55. package/dist/ProteinView/{loadStructureFromData.d.ts → addStructureFromData.d.ts} +2 -2
  56. package/dist/ProteinView/{loadStructureFromData.js → addStructureFromData.js} +3 -8
  57. package/dist/ProteinView/addStructureFromData.js.map +1 -0
  58. package/dist/ProteinView/{loadStructureFromURL.d.ts → addStructureFromURL.d.ts} +2 -2
  59. package/dist/ProteinView/{loadStructureFromURL.js → addStructureFromURL.js} +11 -9
  60. package/dist/ProteinView/addStructureFromURL.js.map +1 -0
  61. package/dist/ProteinView/clearSelection.js +1 -1
  62. package/dist/ProteinView/clearSelection.js.map +1 -1
  63. package/dist/ProteinView/components/ProteinAlignment.d.ts +2 -2
  64. package/dist/ProteinView/components/ProteinAlignment.js +37 -26
  65. package/dist/ProteinView/components/ProteinAlignment.js.map +1 -1
  66. package/dist/ProteinView/components/ProteinAlignmentHelpButton.d.ts +2 -2
  67. package/dist/ProteinView/components/ProteinAlignmentHelpButton.js +6 -4
  68. package/dist/ProteinView/components/ProteinAlignmentHelpButton.js.map +1 -1
  69. package/dist/ProteinView/components/ProteinAlignmentHelpDialog.js +6 -5
  70. package/dist/ProteinView/components/ProteinAlignmentHelpDialog.js.map +1 -1
  71. package/dist/ProteinView/components/ProteinView.js +18 -60
  72. package/dist/ProteinView/components/ProteinView.js.map +1 -1
  73. package/dist/ProteinView/components/{Header.js → ProteinViewHeader.js} +29 -12
  74. package/dist/ProteinView/components/ProteinViewHeader.js.map +1 -0
  75. package/dist/ProteinView/components/SplitString.d.ts +4 -4
  76. package/dist/ProteinView/components/SplitString.js +3 -3
  77. package/dist/ProteinView/components/SplitString.js.map +1 -1
  78. package/dist/ProteinView/genomeToProtein.d.ts +2 -2
  79. package/dist/ProteinView/genomeToProtein.js +4 -5
  80. package/dist/ProteinView/genomeToProtein.js.map +1 -1
  81. package/dist/ProteinView/highlightResidue.js +2 -2
  82. package/dist/ProteinView/highlightResidue.js.map +1 -1
  83. package/dist/ProteinView/launchRemotePairwiseAlignment.d.ts +2 -5
  84. package/dist/ProteinView/launchRemotePairwiseAlignment.js +7 -3
  85. package/dist/ProteinView/launchRemotePairwiseAlignment.js.map +1 -1
  86. package/dist/ProteinView/model.d.ts +496 -160
  87. package/dist/ProteinView/model.js +61 -246
  88. package/dist/ProteinView/model.js.map +1 -1
  89. package/dist/ProteinView/proteinToGenomeMapping.d.ts +6 -6
  90. package/dist/ProteinView/proteinToGenomeMapping.js +29 -28
  91. package/dist/ProteinView/proteinToGenomeMapping.js.map +1 -1
  92. package/dist/ProteinView/selectResidue.js +1 -1
  93. package/dist/ProteinView/selectResidue.js.map +1 -1
  94. package/dist/ProteinView/structureModel.d.ts +183 -0
  95. package/dist/ProteinView/structureModel.js +407 -0
  96. package/dist/ProteinView/structureModel.js.map +1 -0
  97. package/dist/ProteinView/useProteinView.d.ts +1 -4
  98. package/dist/ProteinView/useProteinView.js +3 -15
  99. package/dist/ProteinView/useProteinView.js.map +1 -1
  100. package/dist/ProteinView/util.d.ts +3 -3
  101. package/dist/ProteinView/util.js +8 -6
  102. package/dist/ProteinView/util.js.map +1 -1
  103. package/dist/UniProtVariationAdapter/UniProtVariationAdapter.d.ts +15 -0
  104. package/dist/UniProtVariationAdapter/UniProtVariationAdapter.js +55 -0
  105. package/dist/UniProtVariationAdapter/UniProtVariationAdapter.js.map +1 -0
  106. package/dist/UniProtVariationAdapter/configSchema.d.ts +17 -0
  107. package/dist/UniProtVariationAdapter/configSchema.js +20 -0
  108. package/dist/UniProtVariationAdapter/configSchema.js.map +1 -0
  109. package/dist/UniProtVariationAdapter/index.d.ts +2 -0
  110. package/dist/UniProtVariationAdapter/index.js +11 -0
  111. package/dist/UniProtVariationAdapter/index.js.map +1 -0
  112. package/dist/genomeToTranscriptMapping.d.ts +2 -2
  113. package/dist/genomeToTranscriptMapping.js +3 -3
  114. package/dist/genomeToTranscriptMapping.js.map +1 -1
  115. package/dist/index.js +6 -0
  116. package/dist/index.js.map +1 -1
  117. package/dist/jbrowse-plugin-protein3d.umd.production.min.js +1467 -1482
  118. package/dist/jbrowse-plugin-protein3d.umd.production.min.js.map +4 -4
  119. package/dist/mappings.d.ts +12 -10
  120. package/dist/mappings.js +7 -7
  121. package/dist/mappings.js.map +1 -1
  122. package/dist/mappings.test.js +7 -5
  123. package/dist/mappings.test.js.map +1 -1
  124. package/dist/test_data/gene.d.ts +577 -64
  125. package/dist/test_data/gene.js +1 -1
  126. package/dist/test_data/gene.js.map +1 -1
  127. package/package.json +16 -15
  128. package/src/AddHighlightModel/GenomeMouseoverHighlight.tsx +4 -17
  129. package/src/AddHighlightModel/ProteinToGenomeClickHighlight.tsx +17 -14
  130. package/src/AddHighlightModel/ProteinToGenomeHoverHighlight.tsx +18 -17
  131. package/src/AddHighlightModel/util.ts +1 -1
  132. package/src/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.ts +63 -0
  133. package/src/AlphaFoldConfidenceAdapter/configSchema.ts +21 -0
  134. package/src/AlphaFoldConfidenceAdapter/index.ts +19 -0
  135. package/src/AlphaMissensePathogenicityAdapter/AlphaMissensePathogenicityAdapter.ts +109 -0
  136. package/src/AlphaMissensePathogenicityAdapter/configSchema.ts +21 -0
  137. package/src/AlphaMissensePathogenicityAdapter/index.ts +19 -0
  138. package/src/LaunchProteinView/components/AlphaFoldDBSearch.tsx +172 -10
  139. package/src/LaunchProteinView/components/AlphaFoldDBSearchStatus.tsx +8 -6
  140. package/src/LaunchProteinView/components/HelpButton.tsx +10 -2
  141. package/src/LaunchProteinView/components/HelpDialog.tsx +6 -1
  142. package/src/LaunchProteinView/components/LaunchProteinViewDialog.tsx +9 -2
  143. package/src/LaunchProteinView/components/MSATable.tsx +3 -1
  144. package/src/LaunchProteinView/components/TranscriptSelector.tsx +9 -7
  145. package/src/LaunchProteinView/components/UserProvidedStructure.tsx +17 -12
  146. package/src/LaunchProteinView/components/calculateProteinSequence.ts +6 -4
  147. package/src/LaunchProteinView/components/useLocalStructureFileSequence.ts +28 -9
  148. package/src/LaunchProteinView/components/useRemoteStructureFileSequence.ts +23 -8
  149. package/src/LaunchProteinView/components/util.ts +1 -1
  150. package/src/LaunchProteinView/index.ts +36 -26
  151. package/src/ProteinView/{loadStructureFromData.ts → addStructureFromData.ts} +2 -8
  152. package/src/ProteinView/{loadStructureFromURL.ts → addStructureFromURL.ts} +11 -11
  153. package/src/ProteinView/clearSelection.ts +1 -1
  154. package/src/ProteinView/components/ProteinAlignment.tsx +51 -35
  155. package/src/ProteinView/components/ProteinAlignmentHelpButton.tsx +4 -4
  156. package/src/ProteinView/components/ProteinAlignmentHelpDialog.tsx +15 -11
  157. package/src/ProteinView/components/ProteinView.tsx +22 -82
  158. package/src/ProteinView/components/{Header.tsx → ProteinViewHeader.tsx} +44 -23
  159. package/src/ProteinView/components/SplitString.tsx +8 -8
  160. package/src/ProteinView/genomeToProtein.ts +5 -9
  161. package/src/ProteinView/highlightResidue.ts +2 -2
  162. package/src/ProteinView/launchRemotePairwiseAlignment.ts +6 -3
  163. package/src/ProteinView/model.ts +74 -287
  164. package/src/ProteinView/proteinToGenomeMapping.ts +40 -38
  165. package/src/ProteinView/selectResidue.ts +1 -1
  166. package/src/ProteinView/structureModel.ts +512 -0
  167. package/src/ProteinView/useProteinView.ts +2 -19
  168. package/src/ProteinView/util.ts +20 -9
  169. package/src/UniProtVariationAdapter/UniProtVariationAdapter.ts +99 -0
  170. package/src/UniProtVariationAdapter/configSchema.ts +25 -0
  171. package/src/UniProtVariationAdapter/index.ts +17 -0
  172. package/src/__snapshots__/mappings.test.ts.snap +224 -224
  173. package/src/genomeToTranscriptMapping.ts +9 -9
  174. package/src/index.ts +6 -0
  175. package/src/mappings.test.ts +7 -5
  176. package/src/mappings.ts +25 -23
  177. package/src/test_data/gene.ts +3 -3
  178. package/dist/ProteinView/components/Header.js.map +0 -1
  179. package/dist/ProteinView/loadStructureFromData.js.map +0 -1
  180. package/dist/ProteinView/loadStructureFromURL.js.map +0 -1
  181. package/dist/ProteinView/useProteinViewClickBehavior.d.ts +0 -8
  182. package/dist/ProteinView/useProteinViewClickBehavior.js +0 -34
  183. package/dist/ProteinView/useProteinViewClickBehavior.js.map +0 -1
  184. package/dist/ProteinView/useProteinViewHoverBehavior.d.ts +0 -6
  185. package/dist/ProteinView/useProteinViewHoverBehavior.js +0 -31
  186. package/dist/ProteinView/useProteinViewHoverBehavior.js.map +0 -1
  187. package/src/ProteinView/useProteinViewClickBehavior.ts +0 -48
  188. package/src/ProteinView/useProteinViewHoverBehavior.ts +0 -44
  189. /package/dist/ProteinView/components/{Header.d.ts → ProteinViewHeader.d.ts} +0 -0
@@ -7,6 +7,7 @@ import {
7
7
  Feature,
8
8
  getContainingView,
9
9
  getSession,
10
+ isSessionWithAddTracks,
10
11
  } from '@jbrowse/core/util'
11
12
  import { ErrorMessage, LoadingEllipses } from '@jbrowse/core/ui'
12
13
  import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
@@ -78,13 +79,14 @@ const AlphaFoldDBSearch = observer(function ({
78
79
  ? `https://alphafold.ebi.ac.uk/files/AF-${uniprotId}-F1-model_v4.cif`
79
80
  : undefined
80
81
  const {
81
- seq: structureSequence,
82
+ sequences: structureSequences,
82
83
  isLoading: isRemoteStructureSequenceLoading,
83
84
  error: remoteStructureSequenceError,
84
85
  } = useRemoteStructureFileSequence({ url })
85
86
  const e =
86
87
  myGeneError || isoformProteinSequencesError || remoteStructureSequenceError
87
88
 
89
+ const structureSequence = structureSequences?.[0]
88
90
  useEffect(() => {
89
91
  if (isoformSequences !== undefined) {
90
92
  const ret =
@@ -116,7 +118,7 @@ const AlphaFoldDBSearch = observer(function ({
116
118
  variant="h6"
117
119
  message="Looking up UniProt ID from mygene.info"
118
120
  />
119
- ) : !uniprotId ? (
121
+ ) : uniprotId ? null : (
120
122
  <div>
121
123
  UniProt ID not found. Search sequence on AlphaFoldDB{' '}
122
124
  <a
@@ -130,7 +132,7 @@ const AlphaFoldDBSearch = observer(function ({
130
132
  After visiting the above link, then paste the structure URL into the
131
133
  Manual tab
132
134
  </div>
133
- ) : null}
135
+ )}
134
136
  {isIsoformProteinSequencesLoading ? (
135
137
  <LoadingEllipses
136
138
  variant="h6"
@@ -160,7 +162,9 @@ const AlphaFoldDBSearch = observer(function ({
160
162
  <Button
161
163
  variant="contained"
162
164
  color="secondary"
163
- onClick={() => handleClose()}
165
+ onClick={() => {
166
+ handleClose()
167
+ }}
164
168
  >
165
169
  Cancel
166
170
  </Button>
@@ -173,16 +177,174 @@ const AlphaFoldDBSearch = observer(function ({
173
177
  onClick={() => {
174
178
  session.addView('ProteinView', {
175
179
  type: 'ProteinView',
176
- url,
177
- seq2: userSelectedProteinSequence?.seq,
178
- feature: selectedTranscript?.toJSON(),
179
- connectedViewId: view.id,
180
- displayName: `Protein view ${getGeneDisplayName(feature)} - ${getTranscriptDisplayName(selectedTranscript)}`,
180
+ isFloating: true,
181
+ structures: [
182
+ {
183
+ url,
184
+ userProvidedTranscriptSequence:
185
+ userSelectedProteinSequence?.seq,
186
+ feature: selectedTranscript?.toJSON(),
187
+ connectedViewId: view.id,
188
+ },
189
+ ],
190
+ displayName: [
191
+ 'Protein view',
192
+ uniprotId,
193
+ getGeneDisplayName(feature),
194
+ getTranscriptDisplayName(selectedTranscript),
195
+ ].join(' - '),
181
196
  })
182
197
  handleClose()
183
198
  }}
184
199
  >
185
- Submit
200
+ Launch 3-D protein structure view
201
+ </Button>
202
+ <Button
203
+ variant="contained"
204
+ disabled={
205
+ !uniprotId || !userSelectedProteinSequence || !selectedTranscript
206
+ }
207
+ onClick={() => {
208
+ if (uniprotId && isSessionWithAddTracks(session)) {
209
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
210
+ ;(async () => {
211
+ try {
212
+ session.addTemporaryAssembly?.({
213
+ name: uniprotId,
214
+ sequence: {
215
+ type: 'ReferenceSequenceTrack',
216
+ trackId: `${uniprotId}-ReferenceSequenceTrack`,
217
+ sequenceType: 'pep',
218
+ adapter: {
219
+ type: 'UnindexedFastaAdapter',
220
+ rewriteRefNames: "jexl:split(refName,'|')[1]",
221
+ fastaLocation: {
222
+ uri: `https://rest.uniprot.org/uniprotkb/${uniprotId}.fasta`,
223
+ },
224
+ },
225
+ },
226
+ })
227
+ const url = `https://rest.uniprot.org/uniprotkb/${uniprotId}.gff`
228
+ const res = await fetch(url)
229
+ if (!res.ok) {
230
+ throw new Error(`HTTP ${res.status} fetching ${url}`)
231
+ }
232
+ const data = await res.text()
233
+
234
+ const types = [
235
+ ...new Set(
236
+ data
237
+ .split('\n')
238
+ .filter(f => !f.startsWith('#'))
239
+ .map(f => f.trim())
240
+ .filter(f => !!f)
241
+ .map(f => f.split('\t')[2]),
242
+ ),
243
+ ]
244
+ types.forEach(type => {
245
+ const s = `${uniprotId}-${type}`
246
+ session.addTrackConf({
247
+ type: 'FeatureTrack',
248
+ trackId: s,
249
+ name: type,
250
+ adapter: {
251
+ type: 'Gff3Adapter',
252
+ gffLocation: {
253
+ uri: `https://rest.uniprot.org/uniprotkb/${uniprotId}.gff`,
254
+ },
255
+ },
256
+ assemblyNames: [uniprotId],
257
+ displays: [
258
+ {
259
+ displayId: `${type}-LinearBasicDisplay`,
260
+ type: 'LinearBasicDisplay',
261
+ jexlFilters: [`get(feature,'type')=='${type}'`],
262
+ },
263
+ ],
264
+ })
265
+ })
266
+ session.addTrackConf({
267
+ type: 'FeatureTrack',
268
+ trackId: 'Antigen',
269
+ name: 'Antigen',
270
+ adapter: {
271
+ type: 'Gff3Adapter',
272
+ gffLocation: {
273
+ uri: `https://www.ebi.ac.uk/proteins/api/antigen/${uniprotId}?format=gff`,
274
+ },
275
+ },
276
+ assemblyNames: [uniprotId],
277
+ })
278
+ session.addTrackConf({
279
+ type: 'FeatureTrack',
280
+ trackId: 'Variation',
281
+ name: 'Variation',
282
+ adapter: {
283
+ type: 'UniProtVariationAdapter',
284
+ location: {
285
+ uri: `https://www.ebi.ac.uk/proteins/api/variation/${uniprotId}.json`,
286
+ },
287
+ },
288
+ assemblyNames: [uniprotId],
289
+ })
290
+ session.addTrackConf({
291
+ type: 'QuantitativeTrack',
292
+ trackId: 'AlphaFold confidence',
293
+ name: 'AlphaFold confidence',
294
+ adapter: {
295
+ type: 'AlphaFoldConfidenceAdapter',
296
+ location: {
297
+ uri: `https://alphafold.ebi.ac.uk/files/AF-${uniprotId}-F1-confidence_v4.json`,
298
+ },
299
+ },
300
+ assemblyNames: [uniprotId],
301
+ })
302
+ session.addTrackConf({
303
+ type: 'MultiQuantitativeTrack',
304
+ trackId: 'AlphaMissense scores',
305
+ name: 'AlphaMissense scores',
306
+ assemblyNames: [uniprotId],
307
+ adapter: {
308
+ type: 'AlphaMissensePathogenicityAdapter',
309
+ location: {
310
+ uri: `https://alphafold.ebi.ac.uk/files/AF-${uniprotId}-F1-aa-substitutions.csv`,
311
+ },
312
+ },
313
+ displays: [
314
+ {
315
+ type: 'MultiLinearWiggleDisplay',
316
+ displayId:
317
+ 'AlphaMissense scores-MultiLinearWiggleDisplay',
318
+ defaultRendering: 'multirowdensity',
319
+ renderers: {
320
+ MultiDensityRenderer: {
321
+ type: 'MultiDensityRenderer',
322
+ bicolorPivotValue: 0.5,
323
+ },
324
+ },
325
+ },
326
+ ],
327
+ })
328
+ const view = session.addView('LinearGenomeView', {
329
+ type: 'LinearGenomeView',
330
+ displayName: [
331
+ 'Protein view',
332
+ uniprotId,
333
+ getGeneDisplayName(feature),
334
+ getTranscriptDisplayName(selectedTranscript),
335
+ ].join(' - '),
336
+ }) as LinearGenomeViewModel
337
+ await view.navToLocString(uniprotId, uniprotId)
338
+ } catch (e) {
339
+ console.error(e)
340
+ session.notifyError(`${e}`, e)
341
+ }
342
+ })()
343
+ }
344
+ handleClose()
345
+ }}
346
+ >
347
+ Launch linear protein annotation view
186
348
  </Button>
187
349
  </DialogActions>
188
350
  </>
@@ -39,11 +39,7 @@ export default function AlphaFoldDBSearchStatus({
39
39
  : undefined
40
40
  const [showAllProteinSequences, setShowAllProteinSequences] = useState(false)
41
41
 
42
- return !uniprotId ? (
43
- <Typography>
44
- Searching {getDisplayName(selectedTranscript)} for UniProt ID
45
- </Typography>
46
- ) : (
42
+ return uniprotId ? (
47
43
  <>
48
44
  <Typography>
49
45
  Found Uniprot ID:{' '}
@@ -62,7 +58,9 @@ export default function AlphaFoldDBSearchStatus({
62
58
  <Button
63
59
  variant="contained"
64
60
  color="primary"
65
- onClick={() => setShowAllProteinSequences(!showAllProteinSequences)}
61
+ onClick={() => {
62
+ setShowAllProteinSequences(!showAllProteinSequences)
63
+ }}
66
64
  >
67
65
  {showAllProteinSequences
68
66
  ? 'Hide all isoform protein sequences'
@@ -80,5 +78,9 @@ export default function AlphaFoldDBSearchStatus({
80
78
  <NotFound uniprotId={uniprotId} />
81
79
  )}
82
80
  </>
81
+ ) : (
82
+ <Typography>
83
+ Searching {getDisplayName(selectedTranscript)} for UniProt ID
84
+ </Typography>
83
85
  )
84
86
  }
@@ -10,12 +10,20 @@ export default function HelpButton() {
10
10
  const [show, setShow] = useState(false)
11
11
  return (
12
12
  <>
13
- <IconButton onClick={() => setShow(true)}>
13
+ <IconButton
14
+ onClick={() => {
15
+ setShow(true)
16
+ }}
17
+ >
14
18
  <Help />
15
19
  </IconButton>
16
20
  {show ? (
17
21
  <Suspense fallback={null}>
18
- <HelpDialog handleClose={() => setShow(false)} />
22
+ <HelpDialog
23
+ handleClose={() => {
24
+ setShow(false)
25
+ }}
26
+ />
19
27
  </Suspense>
20
28
  ) : null}
21
29
  </>
@@ -62,7 +62,12 @@ export default function HelpDialog({
62
62
  </DialogContent>
63
63
  <Divider />
64
64
  <DialogActions>
65
- <Button onClick={() => handleClose()} color="primary">
65
+ <Button
66
+ onClick={() => {
67
+ handleClose()
68
+ }}
69
+ color="primary"
70
+ >
66
71
  Close
67
72
  </Button>
68
73
  </DialogActions>
@@ -22,10 +22,17 @@ export default function LaunchProteinViewDialog({
22
22
  <Dialog
23
23
  maxWidth="xl"
24
24
  title="Launch protein view"
25
- onClose={() => handleClose()}
25
+ onClose={() => {
26
+ handleClose()
27
+ }}
26
28
  open
27
29
  >
28
- <Tabs value={choice} onChange={(_, val) => setChoice(val)}>
30
+ <Tabs
31
+ value={choice}
32
+ onChange={(_, val) => {
33
+ setChoice(val)
34
+ }}
35
+ >
29
36
  <Tab value={0} label="Automatic lookup" />
30
37
  <Tab value={1} label="Manual" />
31
38
  </Tabs>
@@ -71,7 +71,9 @@ export default function MSATable({
71
71
  className={classes.margin}
72
72
  control={
73
73
  <Checkbox
74
- onChange={event => setShowInFastaFormat(event.target.checked)}
74
+ onChange={event => {
75
+ setShowInFastaFormat(event.target.checked)
76
+ }}
75
77
  checked={showInFastaFormat}
76
78
  />
77
79
  }
@@ -31,7 +31,9 @@ export default function TranscriptSelector({
31
31
  return (
32
32
  <TextField2
33
33
  value={val}
34
- onChange={event => setVal(event.target.value)}
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()].seq.replaceAll('*', '') ===
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()].seq.length}aa) (matches structure
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()].seq.replaceAll('*', '') !==
58
+ isoformSequences[f.id()]!.seq.replaceAll('*', '') !==
57
59
  structureSequence,
58
60
  )
59
61
  .sort(
60
62
  (a, b) =>
61
- isoformSequences[b.id()].seq.length -
62
- isoformSequences[a.id()].seq.length,
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()].seq.length}aa)
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 { seq: structureSequence1, error: error3 } =
99
+ const { sequences: structureSequences1, error: error3 } =
100
100
  useLocalStructureFileSequence({ file })
101
101
 
102
- const { seq: structureSequence2, error: error4 } =
102
+ const { sequences: structureSequences2, error: error4 } =
103
103
  useRemoteStructureFileSequence({ url: structureURL })
104
104
  const structureName =
105
- file?.name ??
106
- structureURL.slice(structureURL.lastIndexOf('/') + 1) ??
107
- 'structureSequence'
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 => setChoice(event.target.value)}
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 => setStructureURL(event.target.value)}
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?.files?.[0]
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={() => handleClose()}
239
+ onClick={() => {
240
+ handleClose()
241
+ }}
237
242
  >
238
243
  Cancel
239
244
  </Button>
@@ -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 [assemblyName] = view?.assemblyNames ?? []
106
- const assembly = await assemblyManager.waitForAssembly(assemblyName)
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 { loadStructureFromData } from '../../ProteinView/loadStructureFromData'
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
- const data = await file.text()
16
- const { seq } = await loadStructureFromData({ data, plugin: p, format })
17
- p.unmount()
18
- ret.remove()
19
- return seq
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 [seq, setSeq] = useState<string>()
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
- setSeq(seq)
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, seq }
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 { loadStructureFromURL } from '../../ProteinView/loadStructureFromURL'
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
- const { seq } = await loadStructureFromURL({ url, plugin: p })
13
- p.unmount()
14
- ret.remove()
15
- return seq
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 [seq, setSeq] = useState<string>()
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
- setSeq(seq)
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, seq }
58
+ return { error, isLoading, sequences }
44
59
  }
@@ -12,7 +12,7 @@ export function getTranscriptFeatures(feature: Feature) {
12
12
  }
13
13
 
14
14
  export function stripTrailingVersion(s?: string) {
15
- return s?.replace(/\.[^/.]+$/, '')
15
+ return s?.replace(/\.[^./]+$/, '')
16
16
  }
17
17
 
18
18
  export function z(n: number) {