jbrowse-plugin-protein3d 0.11.0 → 0.11.1

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 (201) hide show
  1. package/README.md +11 -0
  2. package/dist/AddHighlightModel/HighlightComponents.js +1 -3
  3. package/dist/AddHighlightModel/proteinViewLookup.d.ts +0 -10
  4. package/dist/AddHighlightModel/proteinViewLookup.js +0 -10
  5. package/dist/LaunchProteinView/components/AlphaFoldDBSearch.js +12 -7
  6. package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.d.ts +3 -5
  7. package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.js +3 -17
  8. package/dist/LaunchProteinView/components/FoldseekSearch.js +1 -1
  9. package/dist/LaunchProteinView/components/ProteinViewActions.js +3 -3
  10. package/dist/LaunchProteinView/components/TranscriptSelector.js +8 -2
  11. package/dist/LaunchProteinView/components/UniProtIdInput.d.ts +2 -6
  12. package/dist/LaunchProteinView/components/UniProtIdInput.js +9 -14
  13. package/dist/LaunchProteinView/components/proteinTrackSetup.js +7 -4
  14. package/dist/LaunchProteinView/hooks/useAlphaFoldDBSearch.d.ts +3 -10
  15. package/dist/LaunchProteinView/hooks/useAlphaFoldDBSearch.js +24 -55
  16. package/dist/LaunchProteinView/hooks/useAlphaFoldData.d.ts +9 -4
  17. package/dist/LaunchProteinView/hooks/useAlphaFoldData.js +13 -11
  18. package/dist/LaunchProteinView/hooks/useFoldseekSearch.js +3 -0
  19. package/dist/LaunchProteinView/hooks/useTranscriptIsoformSelection.js +5 -2
  20. package/dist/LaunchProteinView/hooks/useTranscriptSelection.js +1 -1
  21. package/dist/LaunchProteinView/hooks/useUniProtIdLookup.d.ts +1 -4
  22. package/dist/LaunchProteinView/hooks/useUniProtIdLookup.js +9 -10
  23. package/dist/LaunchProteinView/services/alphaFoldModels.d.ts +24 -0
  24. package/dist/LaunchProteinView/services/alphaFoldModels.js +49 -0
  25. package/dist/LaunchProteinView/utils/calculateProteinSequence.d.ts +7 -0
  26. package/dist/LaunchProteinView/utils/calculateProteinSequence.js +19 -6
  27. package/dist/LaunchProteinView/utils/isoformRanking.d.ts +44 -0
  28. package/dist/LaunchProteinView/utils/isoformRanking.js +85 -0
  29. package/dist/LaunchProteinView/utils/launchViewUtils.d.ts +1 -2
  30. package/dist/LaunchProteinView/utils/launchViewUtils.js +1 -2
  31. package/dist/LaunchProteinView/utils/structureUrls.d.ts +2 -1
  32. package/dist/LaunchProteinView/utils/structureUrls.js +9 -13
  33. package/dist/LaunchProteinView/utils/util.d.ts +0 -29
  34. package/dist/LaunchProteinView/utils/util.js +0 -46
  35. package/dist/LaunchProteinViewExtensionPoint/index.js +27 -17
  36. package/dist/ProteinView/__fixtures__/structureFixtures.d.ts +3 -0
  37. package/dist/ProteinView/__fixtures__/structureFixtures.js +6 -0
  38. package/dist/ProteinView/addStructureFromData.d.ts +1 -0
  39. package/dist/ProteinView/addStructureFromURL.d.ts +1 -0
  40. package/dist/ProteinView/alignmentQuality.d.ts +44 -0
  41. package/dist/ProteinView/alignmentQuality.js +75 -0
  42. package/dist/ProteinView/applyColorTheme.d.ts +2 -0
  43. package/dist/ProteinView/applyColorTheme.js +4 -0
  44. package/dist/ProteinView/applyLociInteractivity.d.ts +42 -16
  45. package/dist/ProteinView/applyLociInteractivity.js +40 -34
  46. package/dist/ProteinView/chooseMappedEntity.d.ts +8 -5
  47. package/dist/ProteinView/chooseMappedEntity.js +34 -18
  48. package/dist/ProteinView/components/HeaderStructureInfo.js +9 -5
  49. package/dist/ProteinView/components/ManualAlignmentDialog.js +10 -3
  50. package/dist/ProteinView/components/ProteinAlignment.js +14 -4
  51. package/dist/ProteinView/components/ProteinAlignmentHelpDialog.js +1 -1
  52. package/dist/ProteinView/components/ProteinView.js +3 -6
  53. package/dist/ProteinView/components/ProteinViewHeader.js +3 -2
  54. package/dist/ProteinView/connectedHover.d.ts +36 -0
  55. package/dist/ProteinView/connectedHover.js +28 -0
  56. package/dist/ProteinView/coordinates.d.ts +14 -0
  57. package/dist/ProteinView/coordinates.js +21 -0
  58. package/dist/ProteinView/extractStructureSequences.d.ts +15 -3
  59. package/dist/ProteinView/extractStructureSequences.js +32 -4
  60. package/dist/ProteinView/frameSelection.d.ts +32 -0
  61. package/dist/ProteinView/frameSelection.js +46 -0
  62. package/dist/ProteinView/hooks/useProteinFeatureTrackData.js +1 -1
  63. package/dist/ProteinView/hooks/useStructureUniProt.d.ts +9 -5
  64. package/dist/ProteinView/hooks/useStructureUniProt.js +9 -17
  65. package/dist/ProteinView/loadStructureData.d.ts +3 -0
  66. package/dist/ProteinView/loadStructureData.js +13 -3
  67. package/dist/ProteinView/lociChannel.d.ts +27 -0
  68. package/dist/ProteinView/lociChannel.js +31 -0
  69. package/dist/ProteinView/model.d.ts +96 -37
  70. package/dist/ProteinView/model.js +50 -83
  71. package/dist/ProteinView/molstarExports.d.ts +1 -0
  72. package/dist/ProteinView/molstarExports.js +1 -0
  73. package/dist/ProteinView/pairwiseAlignment.d.ts +6 -0
  74. package/dist/ProteinView/pairwiseAlignment.js +21 -7
  75. package/dist/ProteinView/pdbUniProtMapping.d.ts +28 -1
  76. package/dist/ProteinView/pdbUniProtMapping.js +90 -3
  77. package/dist/ProteinView/proteinViewSpec.d.ts +16 -2
  78. package/dist/ProteinView/proteinViewSpec.js +16 -0
  79. package/dist/ProteinView/showLoading.d.ts +1 -1
  80. package/dist/ProteinView/showLoading.js +6 -6
  81. package/dist/ProteinView/storedSettings.d.ts +4 -2
  82. package/dist/ProteinView/storedSettings.js +3 -2
  83. package/dist/ProteinView/structureLoader.js +10 -1
  84. package/dist/ProteinView/structureModel.d.ts +109 -15
  85. package/dist/ProteinView/structureModel.js +199 -82
  86. package/dist/ProteinView/structurePipeline.d.ts +1 -0
  87. package/dist/ProteinView/structurePipeline.js +12 -4
  88. package/dist/ProteinView/structureSuperposer.d.ts +4 -0
  89. package/dist/ProteinView/structureSuperposer.js +10 -6
  90. package/dist/ProteinView/subscribeMolstarInteraction.d.ts +4 -0
  91. package/dist/ProteinView/subscribeMolstarInteraction.js +1 -0
  92. package/dist/ProteinView/superposeStructures.js +15 -12
  93. package/dist/jbrowse-plugin-protein3d.umd.production.min.js +16 -15
  94. package/dist/jbrowse-plugin-protein3d.umd.production.min.js.map +4 -4
  95. package/dist/mappings.d.ts +21 -0
  96. package/dist/mappings.js +106 -10
  97. package/dist/{molstar-chunk-3W2VYRSS.js → molstar-chunk-2XBGYTCA.js} +11 -11
  98. package/dist/test_data/molstarStructure.d.ts +12 -0
  99. package/dist/test_data/molstarStructure.js +37 -0
  100. package/dist/version.d.ts +1 -1
  101. package/dist/version.js +1 -1
  102. package/package.json +2 -1
  103. package/src/AddHighlightModel/HighlightComponents.tsx +0 -2
  104. package/src/AddHighlightModel/proteinViewLookup.ts +0 -15
  105. package/src/LaunchProteinView/components/AlphaFoldDBSearch.tsx +18 -26
  106. package/src/LaunchProteinView/components/AlphaFoldDBSearchStatus.tsx +8 -37
  107. package/src/LaunchProteinView/components/FoldseekSearch.tsx +1 -1
  108. package/src/LaunchProteinView/components/ProteinViewActions.tsx +3 -3
  109. package/src/LaunchProteinView/components/TranscriptSelector.tsx +13 -3
  110. package/src/LaunchProteinView/components/UniProtIdInput.tsx +9 -48
  111. package/src/LaunchProteinView/components/proteinTrackSetup.ts +7 -4
  112. package/src/LaunchProteinView/hooks/useAlphaFoldDBSearch.ts +30 -75
  113. package/src/LaunchProteinView/hooks/useAlphaFoldData.ts +30 -15
  114. package/src/LaunchProteinView/hooks/useFoldseekSearch.ts +3 -0
  115. package/src/LaunchProteinView/hooks/useTranscriptIsoformSelection.ts +9 -9
  116. package/src/LaunchProteinView/hooks/useTranscriptSelection.ts +1 -1
  117. package/src/LaunchProteinView/hooks/useUniProtIdLookup.ts +11 -10
  118. package/src/LaunchProteinView/services/alphaFoldModels.test.ts +76 -0
  119. package/src/LaunchProteinView/services/alphaFoldModels.ts +87 -0
  120. package/src/LaunchProteinView/utils/calculateProteinSequence.ts +26 -6
  121. package/src/LaunchProteinView/utils/isoformRanking.ts +138 -0
  122. package/src/LaunchProteinView/utils/launchViewUtils.ts +0 -3
  123. package/src/LaunchProteinView/utils/pickStructureSequence.test.ts +36 -7
  124. package/src/LaunchProteinView/utils/selectBestTranscript.test.ts +48 -1
  125. package/src/LaunchProteinView/utils/structureUrls.test.ts +27 -0
  126. package/src/LaunchProteinView/utils/structureUrls.ts +10 -17
  127. package/src/LaunchProteinView/utils/util.ts +0 -81
  128. package/src/LaunchProteinViewExtensionPoint/index.ts +44 -20
  129. package/src/ProteinView/__fixtures__/structureFixtures.ts +12 -0
  130. package/src/ProteinView/alignmentQuality.test.ts +101 -0
  131. package/src/ProteinView/alignmentQuality.ts +101 -0
  132. package/src/ProteinView/applyColorTheme.ts +5 -0
  133. package/src/ProteinView/applyLociInteractivity.ts +81 -49
  134. package/src/ProteinView/chooseMappedEntity.test.ts +26 -0
  135. package/src/ProteinView/chooseMappedEntity.ts +48 -20
  136. package/src/ProteinView/components/HeaderStructureInfo.tsx +10 -6
  137. package/src/ProteinView/components/ManualAlignmentDialog.tsx +18 -3
  138. package/src/ProteinView/components/ProteinAlignment.tsx +41 -7
  139. package/src/ProteinView/components/ProteinAlignmentHelpDialog.tsx +6 -1
  140. package/src/ProteinView/components/ProteinView.tsx +3 -6
  141. package/src/ProteinView/components/ProteinViewHeader.tsx +9 -1
  142. package/src/ProteinView/connectedHover.test.ts +96 -0
  143. package/src/ProteinView/connectedHover.ts +59 -0
  144. package/src/ProteinView/coordinates.test.ts +20 -0
  145. package/src/ProteinView/coordinates.ts +25 -0
  146. package/src/ProteinView/extractStructureSequences.test.ts +48 -2
  147. package/src/ProteinView/extractStructureSequences.ts +58 -5
  148. package/src/ProteinView/frameSelection.test.ts +147 -0
  149. package/src/ProteinView/frameSelection.ts +71 -0
  150. package/src/ProteinView/hooks/useProteinFeatureTrackData.ts +1 -1
  151. package/src/ProteinView/hooks/useStructureUniProt.ts +19 -34
  152. package/src/ProteinView/loadStructureData.ts +22 -3
  153. package/src/ProteinView/lociChannel.test.ts +102 -0
  154. package/src/ProteinView/lociChannel.ts +54 -0
  155. package/src/ProteinView/model.ts +66 -94
  156. package/src/ProteinView/molstarExports.ts +1 -0
  157. package/src/ProteinView/molstarSelectionQuery.test.ts +20 -75
  158. package/src/ProteinView/pairwiseAlignment.ts +28 -8
  159. package/src/ProteinView/pdbUniProtMapping.test.ts +148 -5
  160. package/src/ProteinView/pdbUniProtMapping.ts +120 -5
  161. package/src/ProteinView/proteinViewSpec.test.ts +23 -3
  162. package/src/ProteinView/proteinViewSpec.ts +30 -1
  163. package/src/ProteinView/showLoading.test.ts +5 -5
  164. package/src/ProteinView/showLoading.ts +7 -9
  165. package/src/ProteinView/storedSettings.ts +9 -5
  166. package/src/ProteinView/structureLoader.test.ts +20 -0
  167. package/src/ProteinView/structureLoader.ts +9 -1
  168. package/src/ProteinView/structureModel.test.ts +210 -1
  169. package/src/ProteinView/structureModel.ts +254 -105
  170. package/src/ProteinView/structurePipeline.ts +14 -6
  171. package/src/ProteinView/structureSuperposer.test.ts +4 -0
  172. package/src/ProteinView/structureSuperposer.ts +14 -6
  173. package/src/ProteinView/subscribeMolstarInteraction.ts +5 -0
  174. package/src/ProteinView/superposeStructures.ts +17 -22
  175. package/src/ProteinView/withStoredSettings.test.ts +21 -2
  176. package/src/mappings.test.ts +77 -0
  177. package/src/mappings.ts +118 -9
  178. package/src/test_data/molstarStructure.ts +51 -0
  179. package/src/version.ts +1 -1
  180. package/dist/AddHighlightModel/ProteinToMsaHoverSync.d.ts +0 -5
  181. package/dist/AddHighlightModel/ProteinToMsaHoverSync.js +0 -84
  182. package/dist/AddHighlightModel/findConnectedMsaView.d.ts +0 -23
  183. package/dist/AddHighlightModel/findConnectedMsaView.js +0 -23
  184. package/dist/AddHighlightModel/msaRowMatch.d.ts +0 -10
  185. package/dist/AddHighlightModel/msaRowMatch.js +0 -16
  186. package/dist/LaunchProteinView/components/SequenceSearchStatus.d.ts +0 -11
  187. package/dist/LaunchProteinView/components/SequenceSearchStatus.js +0 -16
  188. package/dist/LaunchProteinView/hooks/useAlphaFoldSequenceSearch.d.ts +0 -30
  189. package/dist/LaunchProteinView/hooks/useAlphaFoldSequenceSearch.js +0 -31
  190. package/dist/LaunchProteinView/utils/md5.d.ts +0 -1
  191. package/dist/LaunchProteinView/utils/md5.js +0 -130
  192. package/src/AddHighlightModel/ProteinToMsaHoverSync.tsx +0 -150
  193. package/src/AddHighlightModel/findConnectedMsaView.test.ts +0 -53
  194. package/src/AddHighlightModel/findConnectedMsaView.ts +0 -35
  195. package/src/AddHighlightModel/msaHoverSyncGuard.test.ts +0 -153
  196. package/src/AddHighlightModel/msaRowMatch.test.ts +0 -27
  197. package/src/AddHighlightModel/msaRowMatch.ts +0 -20
  198. package/src/LaunchProteinView/components/SequenceSearchStatus.tsx +0 -41
  199. package/src/LaunchProteinView/hooks/useAlphaFoldSequenceSearch.ts +0 -66
  200. package/src/LaunchProteinView/utils/md5.ts +0 -187
  201. /package/dist/{molstar-chunk-3W2VYRSS.js.map → molstar-chunk-2XBGYTCA.js.map} +0 -0
package/README.md CHANGED
@@ -29,6 +29,13 @@ Source and details in [harness/](harness/).
29
29
  Example at
30
30
  https://jbrowse.org/code/jb2/latest/?config=%2Fucsc%2Fhg38%2Fconfig.json&session=share-aZOIjR_qs4&password=NT4sa
31
31
 
32
+ ## Demos
33
+
34
+ [Structures that are easy to map wrong](docs/demos.md), each one link away: a
35
+ peptide bound to a larger partner, a protein bound to DNA, a receptor with
36
+ another protein fused into it, a phosphorylated residue, and a mitochondrial
37
+ protein.
38
+
32
39
  ## Publication
33
40
 
34
41
  If you find this tool useful please cite our work
@@ -54,6 +61,10 @@ See [DEVELOPERS.md](DEVELOPERS.md)
54
61
  Notes on the parts that are easy to get subtly wrong, written for someone
55
62
  extending the plugin or checking what a number on screen means:
56
63
 
64
+ - [Genome to structure alignment](docs/genome-to-structure-alignment.md): why
65
+ the plugin aligns the transcript's translation to the structure on the fly,
66
+ the precedent for that in SIFTS and G2S, how it picks the chain and isoform,
67
+ and what sequence alignment cannot decide.
57
68
  - [Residue numbering](docs/residue-numbering.md): how a paper's R248 becomes
58
69
  position 154 in the file, `label_seq_id` 155 for Mol\*, and the codon on
59
70
  chr17, and how a session spec names a residue the literature's way.
@@ -4,14 +4,12 @@ import GenomeMouseoverHighlight from './GenomeMouseoverHighlight';
4
4
  import GenomeTo1DProteinHoverHighlight from './GenomeTo1DProteinHoverHighlight';
5
5
  import Protein1DToGenomeHoverHighlight from './Protein1DToGenomeHoverHighlight';
6
6
  import { ProteinToGenomeClickHighlight, ProteinToGenomeHoverHighlight, } from './ProteinToGenomeHighlight';
7
- import ProteinToMsaHoverSync from './ProteinToMsaHoverSync';
8
7
  const HighlightComponents = observer(function Highlight({ model, }) {
9
8
  return (React.createElement(React.Fragment, null,
10
9
  React.createElement(ProteinToGenomeClickHighlight, { model: model }),
11
10
  React.createElement(ProteinToGenomeHoverHighlight, { model: model }),
12
11
  React.createElement(Protein1DToGenomeHoverHighlight, { model: model }),
13
12
  React.createElement(GenomeTo1DProteinHoverHighlight, { model: model }),
14
- React.createElement(GenomeMouseoverHighlight, { model: model }),
15
- React.createElement(ProteinToMsaHoverSync, { model: model })));
13
+ React.createElement(GenomeMouseoverHighlight, { model: model })));
16
14
  });
17
15
  export default HighlightComponents;
@@ -8,19 +8,9 @@ import type { AbstractSessionModel } from '@jbrowse/core/util';
8
8
  */
9
9
  export interface HighlightSourceProteinView {
10
10
  id: string;
11
- connectedMsaViewId?: string;
12
11
  structures: JBrowsePluginProteinStructureModel[];
13
- primaryStructure?: JBrowsePluginProteinStructureModel;
14
12
  }
15
13
  export declare function getProteinViews(session: AbstractSessionModel): HighlightSourceProteinView[];
16
- /**
17
- * NOTE: assumes a single ProteinView. Unlike the genome-highlight bridge (which
18
- * pairs by the declared `connectedViewId`, see getStructuresConnectedTo), a
19
- * second ProteinView's MSA hover sync is skipped — pairing an MSA to one of
20
- * several protein views has no reliable rule when the protein view declares
21
- * neither a connectedMsaViewId nor a connectedViewId.
22
- */
23
- export declare function getProteinView(session: AbstractSessionModel): HighlightSourceProteinView | undefined;
24
14
  interface ConnectableStructure {
25
15
  connectedViewId?: string;
26
16
  }
@@ -1,16 +1,6 @@
1
1
  export function getProteinViews(session) {
2
2
  return session.views.filter(v => v.type === 'ProteinView');
3
3
  }
4
- /**
5
- * NOTE: assumes a single ProteinView. Unlike the genome-highlight bridge (which
6
- * pairs by the declared `connectedViewId`, see getStructuresConnectedTo), a
7
- * second ProteinView's MSA hover sync is skipped — pairing an MSA to one of
8
- * several protein views has no reliable rule when the protein view declares
9
- * neither a connectedMsaViewId nor a connectedViewId.
10
- */
11
- export function getProteinView(session) {
12
- return getProteinViews(session)[0];
13
- }
14
4
  /**
15
5
  * Every structure across all ProteinViews that declares this genome view as its
16
6
  * connection. Structures are paired to a genome view explicitly, so a second
@@ -6,7 +6,6 @@ import { makeStyles } from 'tss-react/mui';
6
6
  import AlphaFoldDBSearchStatus from './AlphaFoldDBSearchStatus';
7
7
  import IdentifierSelector from './IdentifierSelector';
8
8
  import ProteinViewActions from './ProteinViewActions';
9
- import SequenceSearchStatus from './SequenceSearchStatus';
10
9
  import TranscriptSelector from './TranscriptSelector';
11
10
  import UniProtIdInput from './UniProtIdInput';
12
11
  import UniProtResultsTable from './UniProtResultsTable';
@@ -41,7 +40,11 @@ const AlphaFoldDBSearch = observer(function AlphaFoldDBSearch({ feature, session
41
40
  return (React.createElement(React.Fragment, null,
42
41
  React.createElement(DialogContent, { className: classes.dialogContent },
43
42
  state.error ? React.createElement(ErrorMessage, { error: state.error }) : null,
44
- React.createElement(UniProtIdInput, { lookupMode: state.lookupMode, onLookupModeChange: state.setLookupMode, manualUniprotId: state.manualUniprotId, onManualUniprotIdChange: state.setManualUniprotId, featureUniprotId: state.featureUniprotId, hasProteinSequence: !!state.userSelectedProteinSequence?.seq, sequenceSearchType: state.sequenceSearchType, onSequenceSearchTypeChange: state.setSequenceSearchType, endContent: state.showIdentifierSelector ? (React.createElement("div", { className: classes.endRow },
43
+ state.noModel ? (React.createElement(Typography, null,
44
+ "AlphaFold DB has no model for ",
45
+ state.uniprotId,
46
+ ". The PDB and Foldseek tabs may have a structure.")) : null,
47
+ React.createElement(UniProtIdInput, { lookupMode: state.lookupMode, onLookupModeChange: state.setLookupMode, manualUniprotId: state.manualUniprotId, onManualUniprotIdChange: state.setManualUniprotId, featureUniprotId: state.featureUniprotId, endContent: state.showIdentifierSelector ? (React.createElement("div", { className: classes.endRow },
45
48
  React.createElement(IdentifierSelector, { recognizedIds: state.recognizedIds, geneName: state.geneName, selectedId: state.selectedQueryId, onSelectedIdChange: state.setSelectedQueryId }),
46
49
  React.createElement(TextField, { size: "small", label: "Organism (NCBI taxon)", helperText: "Scopes the gene-name search", value: state.taxonId, onChange: event => {
47
50
  state.setTaxonId(event.target.value);
@@ -65,13 +68,15 @@ const AlphaFoldDBSearch = observer(function AlphaFoldDBSearch({ feature, session
65
68
  ' ',
66
69
  React.createElement(ExternalLink, { href: "https://www.uniprot.org/" }, "UniProt"),
67
70
  ' ',
68
- "directly and use \"Enter manually\" above, or use \"Search sequence against AlphaFoldDB API\" if available.")),
69
- state.showStructureSelectors && state.isoformSequences ? (React.createElement(React.Fragment, null,
71
+ "directly and use \"Enter manually\" above.")),
72
+ state.isoformSequences &&
73
+ state.selectedTranscript &&
74
+ state.structureSequence &&
75
+ state.uniprotId ? (React.createElement(React.Fragment, null,
70
76
  React.createElement("div", { className: classes.selectorsRow },
71
77
  React.createElement(TranscriptSelector, { val: state.userSelection, setVal: state.setUserSelection, structureSequence: state.structureSequence, feature: feature, isoforms: state.transcriptOptions, isoformSequences: state.isoformSequences })),
72
- state.showSequenceSearchStatus && (React.createElement(SequenceSearchStatus, { isLoading: state.isSequenceSearchLoading, uniprotId: state.uniprotId, url: state.url, hasProteinSequence: !!state.userSelectedProteinSequence?.seq, sequenceSearchType: state.sequenceSearchType })),
73
- state.showAlphaFoldDBSearchStatus && (React.createElement(AlphaFoldDBSearchStatus, { uniprotId: state.uniprotId, selectedTranscript: state.selectedTranscript, structureSequence: state.structureSequence, isoformSequences: state.isoformSequences, url: state.url })))) : null),
78
+ React.createElement(AlphaFoldDBSearchStatus, { uniprotId: state.modelAccession ?? state.uniprotId, structureSequence: state.structureSequence, isoformSequences: state.isoformSequences, url: state.url }))) : null),
74
79
  React.createElement(DialogActions, null,
75
- React.createElement(ProteinViewActions, { handleClose: handleClose, uniprotId: state.uniprotId, userSelectedProteinSequence: state.userSelectedProteinSequence, selectedTranscript: state.selectedTranscript, url: state.url, confidenceUrl: state.confidenceUrl, feature: feature, view: view, session: session, alignmentAlgorithm: alignmentAlgorithm, onAlignmentAlgorithmChange: onAlignmentAlgorithmChange, sequencesMatch: state.sequencesMatch, isLoading: state.isLoading, error: state.error }))));
80
+ React.createElement(ProteinViewActions, { handleClose: handleClose, uniprotId: state.modelAccession ?? state.uniprotId, userSelectedProteinSequence: state.userSelectedProteinSequence, selectedTranscript: state.selectedTranscript, url: state.url, confidenceUrl: state.confidenceUrl, feature: feature, view: view, session: session, alignmentAlgorithm: alignmentAlgorithm, onAlignmentAlgorithmChange: onAlignmentAlgorithmChange, sequencesMatch: state.sequencesMatch, isLoading: state.isLoading, error: state.error }))));
76
81
  });
77
82
  export default AlphaFoldDBSearch;
@@ -1,10 +1,8 @@
1
1
  import React from 'react';
2
2
  import type { IsoformSequences } from '../utils/util';
3
- import type { Feature } from '@jbrowse/core/util';
4
- export default function AlphaFoldDBSearchStatus({ uniprotId, selectedTranscript, structureSequence, isoformSequences, url, }: {
5
- uniprotId?: string;
6
- selectedTranscript?: Feature;
7
- structureSequence?: string;
3
+ export default function AlphaFoldDBSearchStatus({ uniprotId, structureSequence, isoformSequences, url, }: {
4
+ uniprotId: string;
5
+ structureSequence: string;
8
6
  isoformSequences: IsoformSequences;
9
7
  url?: string;
10
8
  }): React.JSX.Element;
@@ -3,15 +3,8 @@ import { Typography } from '@mui/material';
3
3
  import IsoformSequencesToggle from './IsoformSequencesToggle';
4
4
  import ExternalLink from '../../components/ExternalLink';
5
5
  import { uniprotEntryUrl } from '../utils/structureUrls';
6
- import { getTranscriptDisplayName } from '../utils/util';
7
- function NotFound({ uniprotId }) {
8
- return (React.createElement(Typography, null,
9
- "No structure found for this UniProtID in AlphaFoldDB",
10
- ' ',
11
- React.createElement(ExternalLink, { href: `https://alphafold.ebi.ac.uk/search/text/${uniprotId}` }, "(search for results)")));
12
- }
13
- export default function AlphaFoldDBSearchStatus({ uniprotId, selectedTranscript, structureSequence, isoformSequences, url, }) {
14
- return uniprotId ? (React.createElement(React.Fragment, null,
6
+ export default function AlphaFoldDBSearchStatus({ uniprotId, structureSequence, isoformSequences, url, }) {
7
+ return (React.createElement(React.Fragment, null,
15
8
  React.createElement("div", null,
16
9
  React.createElement(Typography, null,
17
10
  "UniProt link:",
@@ -20,12 +13,5 @@ export default function AlphaFoldDBSearchStatus({ uniprotId, selectedTranscript,
20
13
  React.createElement(Typography, null,
21
14
  "AlphaFoldDB link: ",
22
15
  React.createElement(ExternalLink, { href: url }, url))),
23
- structureSequence ? (React.createElement(IsoformSequencesToggle, { structureSequence: structureSequence, structureName: uniprotId, isoformSequences: isoformSequences })) : (React.createElement(NotFound, { uniprotId: uniprotId })))) : (React.createElement(Typography, null,
24
- "Searching",
25
- ' ',
26
- selectedTranscript
27
- ? getTranscriptDisplayName(selectedTranscript)
28
- : 'transcript',
29
- ' ',
30
- "for UniProt ID"));
16
+ React.createElement(IsoformSequencesToggle, { structureSequence: structureSequence, structureName: uniprotId, isoformSequences: isoformSequences })));
31
17
  }
@@ -77,7 +77,7 @@ const FoldseekSearch = observer(function FoldseekSearch({ feature, session, view
77
77
  } }))) : null,
78
78
  React.createElement(FoldseekDatabaseSelector, { selected: selectedDatabases, onChange: setSelectedDatabases, disabled: isBusy }),
79
79
  statusMessage ? (React.createElement(LoadingEllipses, { variant: "subtitle2", message: statusMessage })) : null,
80
- results ? (React.createElement(FoldseekResultsTable, { results: results, session: session, view: view, feature: feature, selectedTranscript: selectedTranscript, userProvidedTranscriptSequence: sequence, onClose: handleClose })) : null),
80
+ results ? (React.createElement(FoldseekResultsTable, { results: results, session: session, view: view, feature: feature, selectedTranscript: selectedTranscript, userProvidedTranscriptSequence: selectedIsoformData?.seq, onClose: handleClose })) : null),
81
81
  React.createElement(DialogActions, null,
82
82
  React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => {
83
83
  handleClose();
@@ -18,9 +18,9 @@ export default function ProteinViewActions({ handleClose, uniprotId, userSelecte
18
18
  selectedTranscript,
19
19
  url,
20
20
  });
21
- // Disable launch while loading — SWR's keepPreviousData would otherwise let
22
- // a user click Launch on stale results (wrong UniProt ID) during a refetch.
23
- const canLaunch = !isLoading && missingReasons.length === 0;
21
+ // Loading or errored, SWR's keepPreviousData can still hold the previous
22
+ // accession's structure, which Launch would open under the new name.
23
+ const canLaunch = !isLoading && !error && missingReasons.length === 0;
24
24
  // Suppress the derived reasons while loading or while a real upstream error
25
25
  // is displayed above via <ErrorMessage> — a duplicate hint would mislead.
26
26
  const showMissingReasons = !isLoading && !error && missingReasons.length > 0;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { MenuItem, TextField } from '@mui/material';
3
- import { classifyIsoforms, getGeneDisplayName, getTranscriptDisplayName, } from '../utils/util';
3
+ import { classifyIsoforms } from '../utils/isoformRanking';
4
+ import { getGeneDisplayName, getTranscriptDisplayName, stripStopCodon, } from '../utils/util';
4
5
  export default function TranscriptSelector({ val, setVal, isoforms, isoformSequences, structureSequence, feature, disabled, }) {
5
6
  const geneName = getGeneDisplayName(feature);
6
7
  const { matches, nonMatches, noData } = classifyIsoforms({
@@ -8,7 +9,12 @@ export default function TranscriptSelector({ val, setVal, isoforms, isoformSeque
8
9
  isoformSequences,
9
10
  structureSequence,
10
11
  });
11
- const renderOption = ({ feature: f, length }, note = '') => (React.createElement(MenuItem, { value: f.id(), key: f.id() },
12
+ const structureLength = structureSequence
13
+ ? stripStopCodon(structureSequence).length
14
+ : undefined;
15
+ const renderOption = ({ feature: f, length, identical }, note = identical === undefined
16
+ ? ''
17
+ : ` (${identical}/${structureLength} structure residues identical)`) => (React.createElement(MenuItem, { value: f.id(), key: f.id() },
12
18
  geneName,
13
19
  " - ",
14
20
  getTranscriptDisplayName(f),
@@ -1,16 +1,12 @@
1
1
  import React from 'react';
2
- import type { SequenceSearchType } from '../hooks/useAlphaFoldSequenceSearch';
3
- export type LookupMode = 'auto' | 'manual' | 'feature' | 'sequence';
2
+ export type LookupMode = 'auto' | 'manual' | 'feature';
4
3
  interface UniProtIdInputProps {
5
4
  lookupMode: LookupMode;
6
5
  onLookupModeChange: (mode: LookupMode) => void;
7
6
  manualUniprotId: string;
8
7
  onManualUniprotIdChange: (id: string) => void;
9
8
  featureUniprotId?: string;
10
- hasProteinSequence?: boolean;
11
- sequenceSearchType?: SequenceSearchType;
12
- onSequenceSearchTypeChange?: (type: SequenceSearchType) => void;
13
9
  endContent?: React.ReactNode;
14
10
  }
15
- export default function UniProtIdInput({ lookupMode, onLookupModeChange, manualUniprotId, onManualUniprotIdChange, featureUniprotId, hasProteinSequence, sequenceSearchType, onSequenceSearchTypeChange, endContent, }: UniProtIdInputProps): React.JSX.Element;
11
+ export default function UniProtIdInput({ lookupMode, onLookupModeChange, manualUniprotId, onManualUniprotIdChange, featureUniprotId, endContent, }: UniProtIdInputProps): React.JSX.Element;
16
12
  export {};
@@ -1,32 +1,27 @@
1
1
  import React from 'react';
2
2
  import { FormControl, FormControlLabel, Radio, RadioGroup, TextField, Typography, } from '@mui/material';
3
3
  import ExternalLink from '../../components/ExternalLink';
4
- export default function UniProtIdInput({ lookupMode, onLookupModeChange, manualUniprotId, onManualUniprotIdChange, featureUniprotId, hasProteinSequence, sequenceSearchType, onSequenceSearchTypeChange, endContent, }) {
4
+ const LOOKUP_MODES = ['auto', 'manual', 'feature'];
5
+ function isLookupMode(value) {
6
+ return LOOKUP_MODES.some(mode => mode === value);
7
+ }
8
+ export default function UniProtIdInput({ lookupMode, onLookupModeChange, manualUniprotId, onManualUniprotIdChange, featureUniprotId, endContent, }) {
5
9
  return (React.createElement(React.Fragment, null,
6
10
  React.createElement("div", { style: { display: 'flex', alignItems: 'center', flexWrap: 'wrap' } },
7
11
  React.createElement(FormControl, { component: "fieldset" },
8
12
  React.createElement(RadioGroup, { row: true, value: lookupMode, onChange: event => {
9
- onLookupModeChange(event.target.value);
13
+ if (isLookupMode(event.target.value)) {
14
+ onLookupModeChange(event.target.value);
15
+ }
10
16
  } },
11
17
  featureUniprotId && (React.createElement(FormControlLabel, { value: "feature", control: React.createElement(Radio, null), label: `From feature (${featureUniprotId})` })),
12
18
  React.createElement(FormControlLabel, { value: "auto", control: React.createElement(Radio, null), label: "Auto-detect using UniProt ID mapping API" }),
13
- React.createElement(FormControlLabel, { value: "manual", control: React.createElement(Radio, null), label: "Enter manually" }),
14
- hasProteinSequence && (React.createElement(FormControlLabel, { value: "sequence", control: React.createElement(Radio, null), label: "Search sequence against AlphaFoldDB API" })))),
19
+ React.createElement(FormControlLabel, { value: "manual", control: React.createElement(Radio, null), label: "Enter manually" }))),
15
20
  endContent),
16
21
  lookupMode === 'manual' && (React.createElement("div", null,
17
22
  React.createElement(TextField, { label: "UniProt ID", variant: "outlined", placeholder: "e.g. P68871", size: "small", value: manualUniprotId, onChange: e => {
18
23
  onManualUniprotIdChange(e.target.value);
19
24
  } }))),
20
- lookupMode === 'sequence' &&
21
- sequenceSearchType &&
22
- onSequenceSearchTypeChange && (React.createElement("div", null,
23
- React.createElement(FormControl, { component: "fieldset" },
24
- React.createElement(RadioGroup, { row: true, value: sequenceSearchType, onChange: event => {
25
- onSequenceSearchTypeChange(event.target.value);
26
- } },
27
- React.createElement(FormControlLabel, { value: "md5", control: React.createElement(Radio, null), label: "Exact match" }),
28
- React.createElement(FormControlLabel, { value: "sequence", control: React.createElement(Radio, null), label: "Fuzzy match" }))),
29
- React.createElement(Typography, { variant: "body2", color: "text.secondary" }, "May not find the canonical UniProt entry."))),
30
25
  lookupMode === 'manual' && !manualUniprotId && (React.createElement(Typography, { variant: "body2", color: "text.secondary" },
31
26
  "Search",
32
27
  ' ',
@@ -150,8 +150,11 @@ export async function addAllProteinTracks({ session, uniprotId, confidenceUrl, }
150
150
  uniprotId,
151
151
  confidenceUrl,
152
152
  });
153
- addAlphaMissenseTrack({
154
- session,
155
- uniprotId,
156
- });
153
+ // AlphaFold DB publishes substitution scores for canonical entries only
154
+ if (!uniprotId.includes('-')) {
155
+ addAlphaMissenseTrack({
156
+ session,
157
+ uniprotId,
158
+ });
159
+ }
157
160
  }
@@ -1,31 +1,25 @@
1
- import type { SequenceSearchType } from './useAlphaFoldSequenceSearch';
2
1
  import type { Feature } from '@jbrowse/core/util';
3
2
  import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view';
4
3
  export default function useAlphaFoldDBSearch({ feature, view, }: {
5
4
  feature: Feature;
6
5
  view: LinearGenomeViewModel;
7
6
  }): {
8
- sequenceSearchType: SequenceSearchType;
9
- setSequenceSearchType: import("react").Dispatch<import("react").SetStateAction<SequenceSearchType>>;
10
7
  userSelection: string | undefined;
11
8
  setUserSelection: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
12
9
  transcriptOptions: Feature[];
13
10
  selectedTranscript: Feature | undefined;
14
11
  isoformSequences: import("../utils/util").IsoformSequences | undefined;
15
12
  userSelectedProteinSequence: import("../utils/util").IsoformSequence | undefined;
16
- uniprotId: string | undefined;
17
13
  url: string | undefined;
18
14
  confidenceUrl: string | undefined;
15
+ modelAccession: string | undefined;
19
16
  structureSequence: string | undefined;
17
+ noModel: boolean;
20
18
  error: any;
21
19
  loadingStatuses: string[];
22
- isSequenceSearchLoading: boolean;
23
- showStructureSelectors: boolean;
24
20
  sequencesMatch: boolean | undefined;
25
21
  showUniprotResults: boolean;
26
22
  showNoResults: boolean;
27
- showSequenceSearchStatus: boolean;
28
- showAlphaFoldDBSearchStatus: boolean;
29
23
  isLoading: boolean;
30
24
  lookupMode: import("../components/UniProtIdInput").LookupMode;
31
25
  setLookupMode: import("react").Dispatch<import("react").SetStateAction<import("../components/UniProtIdInput").LookupMode>>;
@@ -36,17 +30,16 @@ export default function useAlphaFoldDBSearch({ feature, view, }: {
36
30
  effectiveTaxonId: number;
37
31
  selectedQueryId: string;
38
32
  setSelectedQueryId: import("react").Dispatch<import("react").SetStateAction<string>>;
39
- selectedUniprotId: string | undefined;
40
33
  setSelectedUniprotId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
41
34
  selectedTableAccession: string | undefined;
42
35
  uniprotEntries: import("../services/lookupMethods").UniProtEntry[];
43
36
  isLookupLoading: boolean;
44
37
  lookupError: any;
38
+ uniprotId: string | undefined;
45
39
  featureUniprotId: string | undefined;
46
40
  recognizedIds: string[];
47
41
  geneName: string | undefined;
48
42
  isAutoMode: boolean;
49
- isSequenceMode: boolean;
50
43
  showIdentifierSelector: boolean;
51
44
  searchDescription: string;
52
45
  searchDescriptionOr: string;
@@ -1,80 +1,51 @@
1
- import { useState } from 'react';
1
+ import { useMemo } from 'react';
2
2
  import useAlphaFoldData from './useAlphaFoldData';
3
- import useAlphaFoldSequenceSearch from './useAlphaFoldSequenceSearch';
4
3
  import useTranscriptIsoformSelection from './useTranscriptIsoformSelection';
5
4
  import useUniProtIdLookup from './useUniProtIdLookup';
6
5
  import { stripStopCodon } from '../utils/util';
7
6
  export default function useAlphaFoldDBSearch({ feature, view, }) {
8
7
  const lookup = useUniProtIdLookup({ feature, view });
9
- const { uniprotId, isSequenceMode, isAutoMode, isLookupLoading } = lookup;
10
- const [sequenceSearchType, setSequenceSearchType] = useState('md5');
11
- const { isLoading: isAlphaFoldLoading, isValidating: isAlphaFoldValidating, error: alphaFoldError, url: alphaFoldUrl, confidenceUrl: alphaFoldConfidenceUrl, structureSequences: alphaFoldStructureSequences, } = useAlphaFoldData({ uniprotId });
12
- const { transcripts: transcriptOptions, isoformSequences, structureSequence: alphaFoldStructureSequence, isLoading: isIsoformLoading, error: isoformError, selectedTranscriptId: effectiveTranscriptId, setSelectedTranscriptId: setUserSelection, selectedTranscript, selectedIsoform: userSelectedProteinSequence, } = useTranscriptIsoformSelection({
8
+ const { uniprotId, isAutoMode, isLookupLoading } = lookup;
9
+ const { isLoading: isAlphaFoldLoading, isValidating: isAlphaFoldValidating, error: alphaFoldError, model, noModel, } = useAlphaFoldData({ uniprotId, feature, view });
10
+ // a stable array, or the isoform picker realigns on every render
11
+ const modelSequence = model?.sequence;
12
+ const structureSequences = useMemo(() => (modelSequence ? [modelSequence] : undefined), [modelSequence]);
13
+ const { transcripts: transcriptOptions, isoformSequences, structureSequence, isLoading: isIsoformLoading, error: isoformError, selectedTranscriptId: userSelection, setSelectedTranscriptId: setUserSelection, selectedTranscript, selectedIsoform: userSelectedProteinSequence, } = useTranscriptIsoformSelection({
13
14
  feature,
14
15
  view,
15
- structureSequences: alphaFoldStructureSequences,
16
- resetKey: uniprotId,
16
+ structureSequences,
17
+ resetKey: model?.url,
17
18
  });
18
- const { uniprotId: seqSearchUniprotId, cifUrl: seqSearchUrl, plddtDocUrl: seqSearchConfidenceUrl, structureSequence: seqSearchStructureSequence, isLoading: isSequenceSearchLoading, isValidating: isSequenceSearchValidating, error: sequenceSearchError, } = useAlphaFoldSequenceSearch({
19
- sequence: userSelectedProteinSequence?.seq,
20
- searchType: sequenceSearchType,
21
- enabled: isSequenceMode,
22
- });
23
- // Merge alphafold / sequence-search results
24
- const finalUrl = isSequenceMode ? seqSearchUrl : alphaFoldUrl;
25
- const finalConfidenceUrl = isSequenceMode
26
- ? seqSearchConfidenceUrl
27
- : alphaFoldConfidenceUrl;
28
- const finalStructureSequence = isSequenceMode
29
- ? seqSearchStructureSequence
30
- : alphaFoldStructureSequence;
31
- const finalUniprotId = isSequenceMode ? seqSearchUniprotId : uniprotId;
32
- // While a structure fetch is in flight, finalStructureSequence may still be
33
- // the previous selection's sequence (keepPreviousData). Comparing that stale
34
- // sequence to the freshly-selected transcript would give a wrong match, so
35
- // the match is treated as unknown until the fetch settles.
36
- const isStructureValidating = isSequenceMode
37
- ? isSequenceSearchValidating
38
- : isAlphaFoldValidating;
39
19
  const loadingStatuses = [
40
20
  isLookupLoading && 'Looking up UniProt ID',
41
21
  isIsoformLoading && 'Loading protein sequences from transcript isoforms',
42
- !isSequenceMode && isAlphaFoldLoading && 'Fetching AlphaFold structure URL',
43
- isSequenceMode &&
44
- isSequenceSearchLoading &&
45
- 'Searching AlphaFoldDB by sequence',
46
- ].filter((s) => !!s);
22
+ isAlphaFoldLoading && 'Asking AlphaFold DB for models',
23
+ ].filter(s => typeof s === 'string');
47
24
  const isLoading = loadingStatuses.length > 0;
48
- // Only show errors once all loading is done — the synchronous
49
- // effectiveLookupMode and autoTranscriptId computations prevent the
50
- // one-frame gaps that previously caused brief error flashes
51
- const rawError = isoformError ?? lookup.lookupError ?? alphaFoldError ?? sequenceSearchError;
25
+ // errors wait for loading to finish, so a lookup in flight doesn't flash one
26
+ const rawError = isoformError ?? lookup.lookupError ?? alphaFoldError;
52
27
  const error = isLoading ? undefined : rawError;
53
28
  return {
54
29
  ...lookup,
55
- sequenceSearchType,
56
- setSequenceSearchType,
57
- userSelection: effectiveTranscriptId,
30
+ userSelection,
58
31
  setUserSelection,
59
32
  transcriptOptions,
60
33
  selectedTranscript,
61
34
  isoformSequences,
62
35
  userSelectedProteinSequence,
63
- uniprotId: finalUniprotId,
64
- url: finalUrl,
65
- confidenceUrl: finalConfidenceUrl,
66
- structureSequence: finalStructureSequence,
36
+ url: model?.url,
37
+ confidenceUrl: model?.confidenceUrl,
38
+ modelAccession: model?.accession,
39
+ structureSequence,
40
+ noModel,
67
41
  error,
68
42
  loadingStatuses,
69
- isSequenceSearchLoading,
70
- showStructureSelectors: !!isoformSequences &&
71
- !!selectedTranscript &&
72
- (isSequenceMode || !!(finalStructureSequence && finalUniprotId)),
73
- sequencesMatch: !isStructureValidating &&
43
+ // While the structure is refetched, structureSequence is still the previous
44
+ // selection's (keepPreviousData), so a match is unknown until it settles.
45
+ sequencesMatch: !isAlphaFoldValidating &&
74
46
  userSelectedProteinSequence?.seq &&
75
- finalStructureSequence
76
- ? stripStopCodon(userSelectedProteinSequence.seq) ===
77
- finalStructureSequence
47
+ structureSequence
48
+ ? stripStopCodon(userSelectedProteinSequence.seq) === structureSequence
78
49
  : undefined,
79
50
  showUniprotResults: !!isoformSequences &&
80
51
  isAutoMode &&
@@ -83,8 +54,6 @@ export default function useAlphaFoldDBSearch({ feature, view, }) {
83
54
  isAutoMode &&
84
55
  !isLookupLoading &&
85
56
  lookup.uniprotEntries.length === 0,
86
- showSequenceSearchStatus: isSequenceMode,
87
- showAlphaFoldDBSearchStatus: !!finalStructureSequence && !!finalUniprotId && !isSequenceMode,
88
57
  isLoading,
89
58
  };
90
59
  }
@@ -1,10 +1,15 @@
1
- export default function useAlphaFoldData({ uniprotId, }: {
1
+ import type { Feature } from '@jbrowse/core/util';
2
+ /** The AlphaFold DB model a launch opens for this gene's accession. */
3
+ export default function useAlphaFoldData({ uniprotId, feature, view, }: {
2
4
  uniprotId?: string;
5
+ feature: Feature;
6
+ view?: {
7
+ assemblyNames?: string[];
8
+ };
3
9
  }): {
4
10
  isLoading: boolean;
5
11
  isValidating: boolean;
6
12
  error: any;
7
- url: string | undefined;
8
- confidenceUrl: string | undefined;
9
- structureSequences: string[] | undefined;
13
+ model: import("../services/alphaFoldModels").AlphaFoldModel | undefined;
14
+ noModel: boolean;
10
15
  };
@@ -1,17 +1,19 @@
1
- import useStructureFileSequence from './useStructureFileSequence';
2
- import { getAlphaFoldConfidenceUrl, getAlphaFoldStructureUrl, } from '../utils/structureUrls';
3
- export default function useAlphaFoldData({ uniprotId, }) {
4
- const url = uniprotId ? getAlphaFoldStructureUrl(uniprotId) : undefined;
5
- const confidenceUrl = uniprotId
6
- ? getAlphaFoldConfidenceUrl(uniprotId)
7
- : undefined;
8
- const { sequences, isLoading, isValidating, error } = useStructureFileSequence({ url });
1
+ import { useMemo } from 'react';
2
+ import useSWR from 'swr';
3
+ import { STATIC_SWR_OPTIONS } from './swrOptions';
4
+ import useIsoformProteinSequences from './useIsoformProteinSequences';
5
+ import { fetchAlphaFoldModels, pickAlphaFoldModel, } from '../services/alphaFoldModels';
6
+ /** The AlphaFold DB model a launch opens for this gene's accession. */
7
+ export default function useAlphaFoldData({ uniprotId, feature, view, }) {
8
+ const { data, isLoading, isValidating, error } = useSWR(uniprotId ? ['alphafold-models', uniprotId] : null, ([, id]) => fetchAlphaFoldModels(id), { ...STATIC_SWR_OPTIONS, keepPreviousData: true });
9
+ const { isoformSequences } = useIsoformProteinSequences({ feature, view });
10
+ // with an error, data is the previous accession's (keepPreviousData)
11
+ const model = useMemo(() => data && !error ? pickAlphaFoldModel(data, isoformSequences) : undefined, [data, error, isoformSequences]);
9
12
  return {
10
13
  isLoading,
11
14
  isValidating,
12
15
  error,
13
- url,
14
- confidenceUrl,
15
- structureSequences: sequences,
16
+ model,
17
+ noModel: !!uniprotId && !isLoading && !error && data?.length === 0,
16
18
  };
17
19
  }
@@ -80,12 +80,15 @@ export default function useFoldseekSearch() {
80
80
  }
81
81
  }
82
82
  };
83
+ // the aborted operation's own finally skips these, so reset clears them
83
84
  const reset = () => {
84
85
  abortRef.current?.abort();
85
86
  setResults(undefined);
86
87
  setPredictData(undefined);
87
88
  setError(undefined);
88
89
  setStatusMessage('');
90
+ setIsLoading(false);
91
+ setIsPredicting(false);
89
92
  };
90
93
  return {
91
94
  results,
@@ -1,6 +1,8 @@
1
+ import { useMemo } from 'react';
1
2
  import useIsoformProteinSequences from './useIsoformProteinSequences';
2
3
  import useTranscriptSelection from './useTranscriptSelection';
3
- import { getId, getTranscriptFeatures, pickStructureSequence, } from '../utils/util';
4
+ import { pickStructureSequence } from '../utils/isoformRanking';
5
+ import { getId, getTranscriptFeatures } from '../utils/util';
4
6
  // Bundles the transcript-isoform wiring shared by all three launch tabs:
5
7
  // list transcripts, fetch their protein sequences, pick which chain of the
6
8
  // structure to compare against, auto/manually select a transcript, and resolve
@@ -11,7 +13,8 @@ export default function useTranscriptIsoformSelection({ feature, view, structure
11
13
  feature,
12
14
  view,
13
15
  });
14
- const structureSequence = pickStructureSequence(structureSequences, isoformSequences);
16
+ // one alignment per chain, so not once per render
17
+ const structureSequence = useMemo(() => pickStructureSequence(structureSequences, isoformSequences), [structureSequences, isoformSequences]);
15
18
  const { userSelection, setUserSelection } = useTranscriptSelection({
16
19
  options: transcripts,
17
20
  isoformSequences,
@@ -1,5 +1,5 @@
1
1
  import { useState } from 'react';
2
- import { selectBestTranscript } from '../utils/util';
2
+ import { selectBestTranscript } from '../utils/isoformRanking';
3
3
  export default function useTranscriptSelection({ options, isoformSequences, structureSequence, resetKey, }) {
4
4
  const [userSelection, setUserSelection] = useState();
5
5
  const [prevResetKey, setPrevResetKey] = useState(resetKey);
@@ -4,8 +4,7 @@ import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view';
4
4
  /**
5
5
  * Which UniProt entry a feature is, by the dialog's lookup modes: the
6
6
  * feature's own attribute, the ID-mapping search over its recognised ids and
7
- * gene name, a typed accession, or none (sequence mode, where the structure
8
- * search itself names the entry). Shared by every tab that starts from an
7
+ * gene name, or a typed accession. Shared by every tab that starts from an
9
8
  * accession so they agree on what the gene is.
10
9
  */
11
10
  export default function useUniProtIdLookup({ feature, view, }: {
@@ -21,7 +20,6 @@ export default function useUniProtIdLookup({ feature, view, }: {
21
20
  effectiveTaxonId: number;
22
21
  selectedQueryId: string;
23
22
  setSelectedQueryId: import("react").Dispatch<import("react").SetStateAction<string>>;
24
- selectedUniprotId: string | undefined;
25
23
  setSelectedUniprotId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
26
24
  selectedTableAccession: string | undefined;
27
25
  uniprotEntries: import("../services/lookupMethods").UniProtEntry[];
@@ -32,7 +30,6 @@ export default function useUniProtIdLookup({ feature, view, }: {
32
30
  recognizedIds: string[];
33
31
  geneName: string | undefined;
34
32
  isAutoMode: boolean;
35
- isSequenceMode: boolean;
36
33
  showIdentifierSelector: boolean;
37
34
  searchDescription: string;
38
35
  searchDescriptionOr: string;