jbrowse-plugin-protein3d 0.10.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 (229) hide show
  1. package/README.md +23 -2
  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/LaunchProteinViewDialog.js +7 -3
  10. package/dist/LaunchProteinView/components/PdbResultsTable.d.ts +7 -0
  11. package/dist/LaunchProteinView/components/PdbResultsTable.js +70 -0
  12. package/dist/LaunchProteinView/components/PdbSearch.d.ts +13 -0
  13. package/dist/LaunchProteinView/components/PdbSearch.js +92 -0
  14. package/dist/LaunchProteinView/components/ProteinViewActions.js +4 -3
  15. package/dist/LaunchProteinView/components/TranscriptSelector.js +8 -2
  16. package/dist/LaunchProteinView/components/UniProtIdInput.d.ts +2 -6
  17. package/dist/LaunchProteinView/components/UniProtIdInput.js +9 -14
  18. package/dist/LaunchProteinView/components/proteinTrackSetup.js +7 -4
  19. package/dist/LaunchProteinView/hooks/useAlphaFoldDBSearch.d.ts +24 -28
  20. package/dist/LaunchProteinView/hooks/useAlphaFoldDBSearch.js +30 -140
  21. package/dist/LaunchProteinView/hooks/useAlphaFoldData.d.ts +9 -4
  22. package/dist/LaunchProteinView/hooks/useAlphaFoldData.js +13 -11
  23. package/dist/LaunchProteinView/hooks/useFoldseekSearch.js +3 -0
  24. package/dist/LaunchProteinView/hooks/usePdbBestStructures.d.ts +6 -0
  25. package/dist/LaunchProteinView/hooks/usePdbBestStructures.js +19 -0
  26. package/dist/LaunchProteinView/hooks/useTranscriptIsoformSelection.js +5 -2
  27. package/dist/LaunchProteinView/hooks/useTranscriptSelection.js +1 -1
  28. package/dist/LaunchProteinView/hooks/useUniProtIdLookup.d.ts +36 -0
  29. package/dist/LaunchProteinView/hooks/useUniProtIdLookup.js +98 -0
  30. package/dist/LaunchProteinView/services/alphaFoldModels.d.ts +24 -0
  31. package/dist/LaunchProteinView/services/alphaFoldModels.js +49 -0
  32. package/dist/LaunchProteinView/services/pdbeBestStructures.d.ts +22 -0
  33. package/dist/LaunchProteinView/services/pdbeBestStructures.js +66 -0
  34. package/dist/LaunchProteinView/utils/calculateProteinSequence.d.ts +7 -0
  35. package/dist/LaunchProteinView/utils/calculateProteinSequence.js +19 -6
  36. package/dist/LaunchProteinView/utils/isoformRanking.d.ts +44 -0
  37. package/dist/LaunchProteinView/utils/isoformRanking.js +85 -0
  38. package/dist/LaunchProteinView/utils/launchHelpers.d.ts +2 -1
  39. package/dist/LaunchProteinView/utils/launchHelpers.js +2 -1
  40. package/dist/LaunchProteinView/utils/launchViewUtils.d.ts +1 -2
  41. package/dist/LaunchProteinView/utils/launchViewUtils.js +1 -2
  42. package/dist/LaunchProteinView/utils/structureUrls.d.ts +11 -1
  43. package/dist/LaunchProteinView/utils/structureUrls.js +28 -13
  44. package/dist/LaunchProteinView/utils/util.d.ts +0 -29
  45. package/dist/LaunchProteinView/utils/util.js +0 -46
  46. package/dist/LaunchProteinViewExtensionPoint/index.js +27 -17
  47. package/dist/ProteinView/__fixtures__/structureFixtures.d.ts +10 -0
  48. package/dist/ProteinView/__fixtures__/structureFixtures.js +18 -0
  49. package/dist/ProteinView/addStructureFromData.d.ts +1 -0
  50. package/dist/ProteinView/addStructureFromURL.d.ts +1 -0
  51. package/dist/ProteinView/alignmentQuality.d.ts +44 -0
  52. package/dist/ProteinView/alignmentQuality.js +75 -0
  53. package/dist/ProteinView/applyColorTheme.d.ts +2 -0
  54. package/dist/ProteinView/applyColorTheme.js +4 -0
  55. package/dist/ProteinView/applyLociInteractivity.d.ts +42 -16
  56. package/dist/ProteinView/applyLociInteractivity.js +40 -34
  57. package/dist/ProteinView/chooseMappedEntity.d.ts +22 -10
  58. package/dist/ProteinView/chooseMappedEntity.js +56 -16
  59. package/dist/ProteinView/components/AlignmentRuler.d.ts +5 -4
  60. package/dist/ProteinView/components/AlignmentRuler.js +7 -6
  61. package/dist/ProteinView/components/ChainSelect.js +4 -3
  62. package/dist/ProteinView/components/FeatureBar.js +14 -3
  63. package/dist/ProteinView/components/HeaderStructureInfo.js +14 -2
  64. package/dist/ProteinView/components/ManualAlignmentDialog.js +10 -3
  65. package/dist/ProteinView/components/ProteinAlignment.js +26 -12
  66. package/dist/ProteinView/components/ProteinAlignmentHelpButton.js +1 -2
  67. package/dist/ProteinView/components/ProteinAlignmentHelpDialog.js +2 -1
  68. package/dist/ProteinView/components/ProteinView.js +3 -6
  69. package/dist/ProteinView/components/ProteinViewHeader.js +3 -2
  70. package/dist/ProteinView/connectedHover.d.ts +36 -0
  71. package/dist/ProteinView/connectedHover.js +28 -0
  72. package/dist/ProteinView/coordinates.d.ts +14 -0
  73. package/dist/ProteinView/coordinates.js +21 -0
  74. package/dist/ProteinView/extractStructureSequences.d.ts +66 -3
  75. package/dist/ProteinView/extractStructureSequences.js +139 -10
  76. package/dist/ProteinView/frameSelection.d.ts +32 -0
  77. package/dist/ProteinView/frameSelection.js +46 -0
  78. package/dist/ProteinView/hooks/useProteinFeatureTrackData.js +1 -1
  79. package/dist/ProteinView/hooks/useStructureUniProt.d.ts +9 -5
  80. package/dist/ProteinView/hooks/useStructureUniProt.js +9 -17
  81. package/dist/ProteinView/loadStructureData.d.ts +3 -0
  82. package/dist/ProteinView/loadStructureData.js +13 -3
  83. package/dist/ProteinView/lociChannel.d.ts +27 -0
  84. package/dist/ProteinView/lociChannel.js +31 -0
  85. package/dist/ProteinView/model.d.ts +132 -37
  86. package/dist/ProteinView/model.js +51 -84
  87. package/dist/ProteinView/molstarExports.d.ts +1 -0
  88. package/dist/ProteinView/molstarExports.js +1 -0
  89. package/dist/ProteinView/pairwiseAlignment.d.ts +6 -0
  90. package/dist/ProteinView/pairwiseAlignment.js +21 -7
  91. package/dist/ProteinView/pdbUniProtMapping.d.ts +28 -1
  92. package/dist/ProteinView/pdbUniProtMapping.js +90 -3
  93. package/dist/ProteinView/proteinViewSpec.d.ts +24 -2
  94. package/dist/ProteinView/proteinViewSpec.js +16 -0
  95. package/dist/ProteinView/showLoading.d.ts +1 -1
  96. package/dist/ProteinView/showLoading.js +6 -6
  97. package/dist/ProteinView/storedSettings.d.ts +4 -2
  98. package/dist/ProteinView/storedSettings.js +3 -2
  99. package/dist/ProteinView/structureLoader.js +10 -1
  100. package/dist/ProteinView/structureModel.d.ts +145 -15
  101. package/dist/ProteinView/structureModel.js +252 -87
  102. package/dist/ProteinView/structurePipeline.d.ts +1 -0
  103. package/dist/ProteinView/structurePipeline.js +12 -4
  104. package/dist/ProteinView/structureSuperposer.d.ts +4 -0
  105. package/dist/ProteinView/structureSuperposer.js +10 -6
  106. package/dist/ProteinView/subscribeMolstarInteraction.d.ts +4 -0
  107. package/dist/ProteinView/subscribeMolstarInteraction.js +1 -0
  108. package/dist/ProteinView/superposeStructures.js +15 -12
  109. package/dist/jbrowse-plugin-protein3d.umd.production.min.js +16 -15
  110. package/dist/jbrowse-plugin-protein3d.umd.production.min.js.map +4 -4
  111. package/dist/mappings.d.ts +21 -0
  112. package/dist/mappings.js +106 -10
  113. package/dist/{molstar-chunk-3W2VYRSS.js → molstar-chunk-2XBGYTCA.js} +11 -11
  114. package/dist/test_data/molstarStructure.d.ts +12 -0
  115. package/dist/test_data/molstarStructure.js +37 -0
  116. package/dist/version.d.ts +1 -1
  117. package/dist/version.js +1 -1
  118. package/package.json +4 -2
  119. package/src/AddHighlightModel/HighlightComponents.tsx +0 -2
  120. package/src/AddHighlightModel/proteinViewLookup.ts +0 -15
  121. package/src/LaunchProteinView/components/AlphaFoldDBSearch.tsx +18 -26
  122. package/src/LaunchProteinView/components/AlphaFoldDBSearchStatus.tsx +8 -37
  123. package/src/LaunchProteinView/components/FoldseekSearch.tsx +1 -1
  124. package/src/LaunchProteinView/components/LaunchProteinViewDialog.tsx +15 -3
  125. package/src/LaunchProteinView/components/PdbResultsTable.tsx +117 -0
  126. package/src/LaunchProteinView/components/PdbSearch.tsx +216 -0
  127. package/src/LaunchProteinView/components/ProteinViewActions.tsx +4 -3
  128. package/src/LaunchProteinView/components/TranscriptSelector.tsx +13 -3
  129. package/src/LaunchProteinView/components/UniProtIdInput.tsx +9 -48
  130. package/src/LaunchProteinView/components/proteinTrackSetup.ts +7 -4
  131. package/src/LaunchProteinView/hooks/useAlphaFoldDBSearch.ts +36 -184
  132. package/src/LaunchProteinView/hooks/useAlphaFoldData.ts +30 -15
  133. package/src/LaunchProteinView/hooks/useFoldseekSearch.ts +3 -0
  134. package/src/LaunchProteinView/hooks/usePdbBestStructures.ts +32 -0
  135. package/src/LaunchProteinView/hooks/useTranscriptIsoformSelection.ts +9 -9
  136. package/src/LaunchProteinView/hooks/useTranscriptSelection.ts +1 -1
  137. package/src/LaunchProteinView/hooks/useUniProtIdLookup.ts +129 -0
  138. package/src/LaunchProteinView/services/alphaFoldModels.test.ts +76 -0
  139. package/src/LaunchProteinView/services/alphaFoldModels.ts +87 -0
  140. package/src/LaunchProteinView/services/pdbeBestStructures.test.ts +72 -0
  141. package/src/LaunchProteinView/services/pdbeBestStructures.ts +87 -0
  142. package/src/LaunchProteinView/utils/calculateProteinSequence.ts +26 -6
  143. package/src/LaunchProteinView/utils/isoformRanking.ts +138 -0
  144. package/src/LaunchProteinView/utils/launchHelpers.ts +3 -0
  145. package/src/LaunchProteinView/utils/launchViewUtils.ts +0 -3
  146. package/src/LaunchProteinView/utils/pickStructureSequence.test.ts +36 -7
  147. package/src/LaunchProteinView/utils/selectBestTranscript.test.ts +48 -1
  148. package/src/LaunchProteinView/utils/structureUrls.test.ts +42 -0
  149. package/src/LaunchProteinView/utils/structureUrls.ts +36 -17
  150. package/src/LaunchProteinView/utils/util.ts +0 -81
  151. package/src/LaunchProteinViewExtensionPoint/index.ts +48 -18
  152. package/src/ProteinView/__fixtures__/structureFixtures.ts +35 -0
  153. package/src/ProteinView/alignmentQuality.test.ts +101 -0
  154. package/src/ProteinView/alignmentQuality.ts +101 -0
  155. package/src/ProteinView/applyColorTheme.ts +5 -0
  156. package/src/ProteinView/applyLociInteractivity.ts +81 -49
  157. package/src/ProteinView/chooseMappedEntity.test.ts +89 -0
  158. package/src/ProteinView/chooseMappedEntity.ts +93 -23
  159. package/src/ProteinView/components/AlignmentRuler.tsx +11 -5
  160. package/src/ProteinView/components/ChainSelect.tsx +4 -3
  161. package/src/ProteinView/components/FeatureBar.tsx +31 -3
  162. package/src/ProteinView/components/HeaderStructureInfo.tsx +21 -3
  163. package/src/ProteinView/components/ManualAlignmentDialog.tsx +18 -3
  164. package/src/ProteinView/components/ProteinAlignment.tsx +66 -15
  165. package/src/ProteinView/components/ProteinAlignmentHelpButton.tsx +0 -3
  166. package/src/ProteinView/components/ProteinAlignmentHelpDialog.tsx +15 -1
  167. package/src/ProteinView/components/ProteinView.tsx +3 -6
  168. package/src/ProteinView/components/ProteinViewHeader.tsx +9 -1
  169. package/src/ProteinView/components/rulerTicks.test.ts +16 -2
  170. package/src/ProteinView/connectedHover.test.ts +96 -0
  171. package/src/ProteinView/connectedHover.ts +59 -0
  172. package/src/ProteinView/coordinates.test.ts +20 -0
  173. package/src/ProteinView/coordinates.ts +25 -0
  174. package/src/ProteinView/extractStructureSequences.test.ts +191 -3
  175. package/src/ProteinView/extractStructureSequences.ts +201 -11
  176. package/src/ProteinView/frameSelection.test.ts +147 -0
  177. package/src/ProteinView/frameSelection.ts +71 -0
  178. package/src/ProteinView/hooks/useProteinFeatureTrackData.ts +1 -1
  179. package/src/ProteinView/hooks/useStructureUniProt.ts +19 -34
  180. package/src/ProteinView/loadStructureData.ts +22 -3
  181. package/src/ProteinView/lociChannel.test.ts +102 -0
  182. package/src/ProteinView/lociChannel.ts +54 -0
  183. package/src/ProteinView/model.ts +67 -95
  184. package/src/ProteinView/molstarExports.ts +1 -0
  185. package/src/ProteinView/molstarSelectionQuery.test.ts +20 -75
  186. package/src/ProteinView/pairwiseAlignment.ts +28 -8
  187. package/src/ProteinView/pdbUniProtMapping.test.ts +148 -5
  188. package/src/ProteinView/pdbUniProtMapping.ts +120 -5
  189. package/src/ProteinView/proteinViewSpec.test.ts +23 -3
  190. package/src/ProteinView/proteinViewSpec.ts +34 -1
  191. package/src/ProteinView/showLoading.test.ts +5 -5
  192. package/src/ProteinView/showLoading.ts +7 -9
  193. package/src/ProteinView/storedSettings.ts +9 -5
  194. package/src/ProteinView/structureLoader.test.ts +20 -0
  195. package/src/ProteinView/structureLoader.ts +9 -1
  196. package/src/ProteinView/structureModel.test.ts +314 -1
  197. package/src/ProteinView/structureModel.ts +318 -108
  198. package/src/ProteinView/structurePipeline.ts +14 -6
  199. package/src/ProteinView/structureSuperposer.test.ts +4 -0
  200. package/src/ProteinView/structureSuperposer.ts +14 -6
  201. package/src/ProteinView/subscribeMolstarInteraction.ts +5 -0
  202. package/src/ProteinView/superposeStructures.ts +17 -22
  203. package/src/ProteinView/withStoredSettings.test.ts +21 -2
  204. package/src/mappings.test.ts +77 -0
  205. package/src/mappings.ts +118 -9
  206. package/src/test_data/molstarStructure.ts +51 -0
  207. package/src/version.ts +1 -1
  208. package/dist/AddHighlightModel/ProteinToMsaHoverSync.d.ts +0 -5
  209. package/dist/AddHighlightModel/ProteinToMsaHoverSync.js +0 -84
  210. package/dist/AddHighlightModel/findConnectedMsaView.d.ts +0 -23
  211. package/dist/AddHighlightModel/findConnectedMsaView.js +0 -23
  212. package/dist/AddHighlightModel/msaRowMatch.d.ts +0 -10
  213. package/dist/AddHighlightModel/msaRowMatch.js +0 -16
  214. package/dist/LaunchProteinView/components/SequenceSearchStatus.d.ts +0 -11
  215. package/dist/LaunchProteinView/components/SequenceSearchStatus.js +0 -16
  216. package/dist/LaunchProteinView/hooks/useAlphaFoldSequenceSearch.d.ts +0 -30
  217. package/dist/LaunchProteinView/hooks/useAlphaFoldSequenceSearch.js +0 -31
  218. package/dist/LaunchProteinView/utils/md5.d.ts +0 -1
  219. package/dist/LaunchProteinView/utils/md5.js +0 -130
  220. package/src/AddHighlightModel/ProteinToMsaHoverSync.tsx +0 -150
  221. package/src/AddHighlightModel/findConnectedMsaView.test.ts +0 -53
  222. package/src/AddHighlightModel/findConnectedMsaView.ts +0 -35
  223. package/src/AddHighlightModel/msaHoverSyncGuard.test.ts +0 -153
  224. package/src/AddHighlightModel/msaRowMatch.test.ts +0 -27
  225. package/src/AddHighlightModel/msaRowMatch.ts +0 -20
  226. package/src/LaunchProteinView/components/SequenceSearchStatus.tsx +0 -41
  227. package/src/LaunchProteinView/hooks/useAlphaFoldSequenceSearch.ts +0 -66
  228. package/src/LaunchProteinView/utils/md5.ts +0 -187
  229. /package/dist/{molstar-chunk-3W2VYRSS.js.map → molstar-chunk-2XBGYTCA.js.map} +0 -0
package/README.md CHANGED
@@ -8,8 +8,9 @@ The major workflow enabled by this is
8
8
  mouseover between genome and structure
9
9
 
10
10
  It has features to automatically look up a protein structure of interest using
11
- the UniProt ID mapping API to connect to AlphaFoldDB, and can also use Foldseek
12
- to look up related structures also
11
+ the UniProt ID mapping API to connect to AlphaFoldDB, lists the experimental PDB
12
+ entries SIFTS maps to that UniProt entry, and can also use Foldseek to look up
13
+ related structures
13
14
 
14
15
  ## Coordinate-mapping harness
15
16
 
@@ -28,6 +29,13 @@ Source and details in [harness/](harness/).
28
29
  Example at
29
30
  https://jbrowse.org/code/jb2/latest/?config=%2Fucsc%2Fhg38%2Fconfig.json&session=share-aZOIjR_qs4&password=NT4sa
30
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
+
31
39
  ## Publication
32
40
 
33
41
  If you find this tool useful please cite our work
@@ -48,6 +56,19 @@ use it on any species there
48
56
 
49
57
  See [DEVELOPERS.md](DEVELOPERS.md)
50
58
 
59
+ ## How it works
60
+
61
+ Notes on the parts that are easy to get subtly wrong, written for someone
62
+ extending the plugin or checking what a number on screen means:
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.
68
+ - [Residue numbering](docs/residue-numbering.md): how a paper's R248 becomes
69
+ position 154 in the file, `label_seq_id` 155 for Mol\*, and the codon on
70
+ chr17, and how a session spec names a residue the literature's way.
71
+
51
72
  ## Publishing
52
73
 
53
74
  just push a new tag using e.g.
@@ -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();
@@ -5,6 +5,7 @@ import { Tab, Tabs } from '@mui/material';
5
5
  import AlphaFoldDBSearch from './AlphaFoldDBSearch';
6
6
  import FoldseekSearch from './FoldseekSearch';
7
7
  import HelpButton from './HelpButton';
8
+ import PdbSearch from './PdbSearch';
8
9
  import TabPanel from './TabPanel';
9
10
  import UserProvidedStructure from './UserProvidedStructure';
10
11
  import { DEFAULT_ALIGNMENT_ALGORITHM } from '../../ProteinView/types';
@@ -21,12 +22,15 @@ export default function LaunchProteinViewDialog({ handleClose, feature, model, }
21
22
  setChoice(val);
22
23
  } },
23
24
  React.createElement(Tab, { value: 0, label: "AlphaFoldDB search" }),
24
- React.createElement(Tab, { value: 1, label: "Foldseek search" }),
25
- React.createElement(Tab, { value: 2, label: "Open file manually" })),
25
+ React.createElement(Tab, { value: 1, label: "PDB search" }),
26
+ React.createElement(Tab, { value: 2, label: "Foldseek search" }),
27
+ React.createElement(Tab, { value: 3, label: "Open file manually" })),
26
28
  React.createElement(TabPanel, { value: choice, index: 0 },
27
29
  React.createElement(AlphaFoldDBSearch, { session: session, view: view, feature: feature, handleClose: handleClose, alignmentAlgorithm: alignmentAlgorithm, onAlignmentAlgorithmChange: setAlignmentAlgorithm })),
28
30
  React.createElement(TabPanel, { value: choice, index: 1 },
29
- React.createElement(FoldseekSearch, { session: session, view: view, feature: feature, handleClose: handleClose })),
31
+ React.createElement(PdbSearch, { session: session, view: view, feature: feature, handleClose: handleClose, alignmentAlgorithm: alignmentAlgorithm, onAlignmentAlgorithmChange: setAlignmentAlgorithm })),
30
32
  React.createElement(TabPanel, { value: choice, index: 2 },
33
+ React.createElement(FoldseekSearch, { session: session, view: view, feature: feature, handleClose: handleClose })),
34
+ React.createElement(TabPanel, { value: choice, index: 3 },
31
35
  React.createElement(UserProvidedStructure, { session: session, view: view, feature: feature, handleClose: handleClose, alignmentAlgorithm: alignmentAlgorithm, onAlignmentAlgorithmChange: setAlignmentAlgorithm }))));
32
36
  }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { PdbStructureEntry } from '../services/pdbeBestStructures';
3
+ export default function PdbResultsTable({ entries, selectedPdbId, onSelect, }: {
4
+ entries: PdbStructureEntry[];
5
+ selectedPdbId?: string;
6
+ onSelect: (pdbId: string) => void;
7
+ }): React.JSX.Element;
@@ -0,0 +1,70 @@
1
+ import React from 'react';
2
+ import { Paper, Radio, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography, } from '@mui/material';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import ExternalLink from '../../components/ExternalLink';
5
+ import { rcsbEntryUrl } from '../services/pdbeBestStructures';
6
+ const useStyles = makeStyles()(theme => ({
7
+ tableContainer: {
8
+ maxHeight: 300,
9
+ },
10
+ headerCell: {
11
+ fontWeight: 'bold',
12
+ backgroundColor: theme.palette.mode === 'dark'
13
+ ? theme.palette.grey[900]
14
+ : theme.palette.grey[100],
15
+ },
16
+ selectedRow: {
17
+ backgroundColor: theme.palette.action.selected,
18
+ },
19
+ clickableRow: {
20
+ cursor: 'pointer',
21
+ '&:hover': {
22
+ backgroundColor: theme.palette.action.hover,
23
+ },
24
+ },
25
+ }));
26
+ const MAX_ROWS = 100;
27
+ export default function PdbResultsTable({ entries, selectedPdbId, onSelect, }) {
28
+ const { classes } = useStyles();
29
+ const shown = entries.slice(0, MAX_ROWS);
30
+ return (React.createElement(React.Fragment, null,
31
+ React.createElement(Typography, { variant: "body2", color: "textSecondary" },
32
+ entries.length,
33
+ " PDB entries, ranked by PDBe on coverage and resolution",
34
+ entries.length > shown.length
35
+ ? ` (showing the first ${MAX_ROWS})`
36
+ : ''),
37
+ React.createElement(TableContainer, { component: Paper, className: classes.tableContainer },
38
+ React.createElement(Table, { size: "small", stickyHeader: true, "data-testid": "pdb-results-table" },
39
+ React.createElement(TableHead, null,
40
+ React.createElement(TableRow, null,
41
+ React.createElement(TableCell, { className: classes.headerCell, padding: "checkbox" }),
42
+ React.createElement(TableCell, { className: classes.headerCell }, "PDB ID"),
43
+ React.createElement(TableCell, { className: classes.headerCell }, "Method"),
44
+ React.createElement(TableCell, { className: classes.headerCell }, "Resolution"),
45
+ React.createElement(TableCell, { className: classes.headerCell }, "UniProt residues"),
46
+ React.createElement(TableCell, { className: classes.headerCell }, "Coverage"),
47
+ React.createElement(TableCell, { className: classes.headerCell }, "Chains"))),
48
+ React.createElement(TableBody, null, shown.map(entry => {
49
+ const selected = entry.pdbId === selectedPdbId;
50
+ return (React.createElement(TableRow, { key: entry.pdbId, className: `${classes.clickableRow} ${selected ? classes.selectedRow : ''}`, onClick: () => {
51
+ onSelect(entry.pdbId);
52
+ } },
53
+ React.createElement(TableCell, { padding: "checkbox" },
54
+ React.createElement(Radio, { checked: selected, size: "small" })),
55
+ React.createElement(TableCell, null,
56
+ React.createElement(ExternalLink, { href: rcsbEntryUrl(entry.pdbId) }, entry.pdbId.toUpperCase())),
57
+ React.createElement(TableCell, null, entry.experimentalMethod),
58
+ React.createElement(TableCell, null, entry.resolution === undefined
59
+ ? '-'
60
+ : `${entry.resolution.toFixed(2)} Å`),
61
+ React.createElement(TableCell, null,
62
+ entry.unpStart,
63
+ "-",
64
+ entry.unpEnd),
65
+ React.createElement(TableCell, null,
66
+ (entry.coverage * 100).toFixed(0),
67
+ "%"),
68
+ React.createElement(TableCell, null, entry.chains.join(', '))));
69
+ }))))));
70
+ }
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import type { AlignmentAlgorithm } from '../../ProteinView/types';
3
+ import type { AbstractSessionModel, Feature } from '@jbrowse/core/util';
4
+ import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view';
5
+ declare const PdbSearch: ({ feature, session, view, handleClose, alignmentAlgorithm, onAlignmentAlgorithmChange, }: {
6
+ feature: Feature;
7
+ session: AbstractSessionModel;
8
+ view: LinearGenomeViewModel;
9
+ handleClose: () => void;
10
+ alignmentAlgorithm: AlignmentAlgorithm;
11
+ onAlignmentAlgorithmChange: (algorithm: AlignmentAlgorithm) => void;
12
+ }) => React.JSX.Element;
13
+ export default PdbSearch;
@@ -0,0 +1,92 @@
1
+ import React, { useState } from 'react';
2
+ import { ErrorMessage, LoadingEllipses } from '@jbrowse/core/ui';
3
+ import { DialogActions, DialogContent, TextField, Typography, } from '@mui/material';
4
+ import { observer } from 'mobx-react';
5
+ import { makeStyles } from 'tss-react/mui';
6
+ import IdentifierSelector from './IdentifierSelector';
7
+ import PdbResultsTable from './PdbResultsTable';
8
+ import ProteinViewActions from './ProteinViewActions';
9
+ import TranscriptSelector from './TranscriptSelector';
10
+ import UniProtIdInput from './UniProtIdInput';
11
+ import UniProtResultsTable from './UniProtResultsTable';
12
+ import ExternalLink from '../../components/ExternalLink';
13
+ import usePdbBestStructures from '../hooks/usePdbBestStructures';
14
+ import useTranscriptIsoformSelection from '../hooks/useTranscriptIsoformSelection';
15
+ import useUniProtIdLookup from '../hooks/useUniProtIdLookup';
16
+ import { getPdbStructureUrl, uniprotEntryUrl } from '../utils/structureUrls';
17
+ const useStyles = makeStyles()({
18
+ dialogContent: {
19
+ width: '80em',
20
+ '& > *': {
21
+ marginBottom: 20,
22
+ },
23
+ '& > *:last-child': {
24
+ marginBottom: 0,
25
+ },
26
+ },
27
+ endRow: {
28
+ display: 'flex',
29
+ flexDirection: 'row',
30
+ gap: 12,
31
+ alignItems: 'flex-start',
32
+ },
33
+ });
34
+ // Experimental structures of the gene's protein, found through SIFTS: PDBe
35
+ // lists every entry mapped to the UniProt accession, ranked on coverage and
36
+ // resolution, so a reader who does not know a PDB id can still reach one.
37
+ // A crystal is usually a fragment, often with partners, so the view aligns
38
+ // the transcript to it after launch rather than expecting a sequence match
39
+ // here.
40
+ const PdbSearch = observer(function PdbSearch({ feature, session, view, handleClose, alignmentAlgorithm, onAlignmentAlgorithmChange, }) {
41
+ const { classes } = useStyles();
42
+ const lookup = useUniProtIdLookup({ feature, view });
43
+ const { uniprotId, isAutoMode, isLookupLoading } = lookup;
44
+ const { entries, error: pdbError, isLoading: isPdbLoading, } = usePdbBestStructures(uniprotId);
45
+ const [userPdbId, setUserPdbId] = useState();
46
+ const { transcripts, isoformSequences, isLoading: isIsoformLoading, error: isoformError, selectedTranscriptId, setSelectedTranscriptId, selectedTranscript, selectedIsoform, } = useTranscriptIsoformSelection({ feature, view, resetKey: uniprotId });
47
+ const selectedPdbId = userPdbId && entries?.some(e => e.pdbId === userPdbId)
48
+ ? userPdbId
49
+ : entries?.[0]?.pdbId;
50
+ const loadingStatuses = [
51
+ isLookupLoading && 'Looking up UniProt ID',
52
+ isIsoformLoading && 'Loading protein sequences from transcript isoforms',
53
+ isPdbLoading && 'Listing PDB entries from PDBe',
54
+ ].filter((s) => !!s);
55
+ const isLoading = loadingStatuses.length > 0;
56
+ const error = isLoading
57
+ ? undefined
58
+ : (isoformError ?? lookup.lookupError ?? pdbError);
59
+ return (React.createElement(React.Fragment, null,
60
+ React.createElement(DialogContent, { className: classes.dialogContent },
61
+ error ? React.createElement(ErrorMessage, { error: error }) : null,
62
+ React.createElement(UniProtIdInput, { lookupMode: lookup.lookupMode, onLookupModeChange: lookup.setLookupMode, manualUniprotId: lookup.manualUniprotId, onManualUniprotIdChange: lookup.setManualUniprotId, featureUniprotId: lookup.featureUniprotId, endContent: lookup.showIdentifierSelector ? (React.createElement("div", { className: classes.endRow },
63
+ React.createElement(IdentifierSelector, { recognizedIds: lookup.recognizedIds, geneName: lookup.geneName, selectedId: lookup.selectedQueryId, onSelectedIdChange: lookup.setSelectedQueryId }),
64
+ React.createElement(TextField, { size: "small", label: "Organism (NCBI taxon)", helperText: "Scopes the gene-name search", value: lookup.taxonId, onChange: event => {
65
+ lookup.setTaxonId(event.target.value);
66
+ }, placeholder: String(lookup.effectiveTaxonId), slotProps: { inputLabel: { shrink: true } }, sx: { width: 180 } }))) : null }),
67
+ loadingStatuses.map(status => (React.createElement(LoadingEllipses, { key: status, variant: "subtitle2", message: status }))),
68
+ isAutoMode && lookup.uniprotEntries.length > 0 ? (React.createElement(React.Fragment, null,
69
+ React.createElement(Typography, { variant: "body2", color: "textSecondary" },
70
+ "Searched UniProt by ",
71
+ lookup.searchDescription),
72
+ React.createElement(UniProtResultsTable, { entries: lookup.uniprotEntries, selectedAccession: lookup.selectedTableAccession, onSelect: lookup.setSelectedUniprotId }))) : null,
73
+ isAutoMode &&
74
+ !isLookupLoading &&
75
+ lookup.uniprotEntries.length === 0 ? (React.createElement(Typography, { variant: "body2", color: "textSecondary" },
76
+ "No UniProt entries found for ",
77
+ lookup.searchDescriptionOr,
78
+ ". Try a different identifier above, or search",
79
+ ' ',
80
+ React.createElement(ExternalLink, { href: "https://www.uniprot.org/" }, "UniProt"),
81
+ ' ',
82
+ "directly and use \"Enter manually\".")) : null,
83
+ uniprotId && entries && !isPdbLoading ? (entries.length > 0 ? (React.createElement(PdbResultsTable, { entries: entries, selectedPdbId: selectedPdbId, onSelect: setUserPdbId })) : (React.createElement(Typography, null,
84
+ "PDBe lists no experimental structure for",
85
+ ' ',
86
+ React.createElement(ExternalLink, { href: uniprotEntryUrl(uniprotId) }, uniprotId),
87
+ ". The AlphaFoldDB tab has a predicted one."))) : null,
88
+ isoformSequences && selectedTranscript ? (React.createElement(TranscriptSelector, { val: selectedTranscriptId, setVal: setSelectedTranscriptId, feature: feature, isoforms: transcripts, isoformSequences: isoformSequences })) : null),
89
+ React.createElement(DialogActions, null,
90
+ React.createElement(ProteinViewActions, { handleClose: handleClose, uniprotId: uniprotId, userSelectedProteinSequence: selectedIsoform, selectedTranscript: selectedTranscript, url: selectedPdbId ? getPdbStructureUrl(selectedPdbId) : undefined, feature: feature, view: view, session: session, alignmentAlgorithm: alignmentAlgorithm, onAlignmentAlgorithmChange: onAlignmentAlgorithmChange, isLoading: isLoading, error: error }))));
91
+ });
92
+ export default PdbSearch;
@@ -16,10 +16,11 @@ export default function ProteinViewActions({ handleClose, uniprotId, userSelecte
16
16
  uniprotId,
17
17
  userSelectedProteinSequence,
18
18
  selectedTranscript,
19
+ url,
19
20
  });
20
- // Disable launch while loading — SWR's keepPreviousData would otherwise let
21
- // a user click Launch on stale results (wrong UniProt ID) during a refetch.
22
- 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;
23
24
  // Suppress the derived reasons while loading or while a real upstream error
24
25
  // is displayed above via <ErrorMessage> — a duplicate hint would mislead.
25
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,50 +1,46 @@
1
- import type { SequenceSearchType } from './useAlphaFoldSequenceSearch';
2
- import type { LookupMode } from '../components/UniProtIdInput';
3
1
  import type { Feature } from '@jbrowse/core/util';
4
2
  import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view';
5
3
  export default function useAlphaFoldDBSearch({ feature, view, }: {
6
4
  feature: Feature;
7
5
  view: LinearGenomeViewModel;
8
6
  }): {
9
- lookupMode: LookupMode;
10
- setLookupMode: import("react").Dispatch<import("react").SetStateAction<LookupMode>>;
11
- manualUniprotId: string;
12
- setManualUniprotId: import("react").Dispatch<import("react").SetStateAction<string>>;
13
- taxonId: string;
14
- setTaxonId: import("react").Dispatch<import("react").SetStateAction<string>>;
15
- effectiveTaxonId: number;
16
- selectedQueryId: string;
17
- setSelectedQueryId: import("react").Dispatch<import("react").SetStateAction<string>>;
18
- sequenceSearchType: SequenceSearchType;
19
- setSequenceSearchType: import("react").Dispatch<import("react").SetStateAction<SequenceSearchType>>;
20
- selectedUniprotId: string | undefined;
21
- setSelectedUniprotId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
22
7
  userSelection: string | undefined;
23
8
  setUserSelection: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
24
9
  transcriptOptions: Feature[];
25
10
  selectedTranscript: Feature | undefined;
26
11
  isoformSequences: import("../utils/util").IsoformSequences | undefined;
27
12
  userSelectedProteinSequence: import("../utils/util").IsoformSequence | undefined;
28
- uniprotEntries: import("../services/lookupMethods").UniProtEntry[];
29
- recognizedIds: string[];
30
- geneName: string | undefined;
31
- featureUniprotId: string | undefined;
32
- uniprotId: string | undefined;
33
13
  url: string | undefined;
34
14
  confidenceUrl: string | undefined;
15
+ modelAccession: string | undefined;
35
16
  structureSequence: string | undefined;
17
+ noModel: boolean;
36
18
  error: any;
37
19
  loadingStatuses: string[];
38
- isSequenceSearchLoading: boolean;
39
- showIdentifierSelector: boolean;
40
- showStructureSelectors: boolean;
41
20
  sequencesMatch: boolean | undefined;
42
- searchDescription: string;
43
- searchDescriptionOr: string;
44
- selectedTableAccession: string | undefined;
45
21
  showUniprotResults: boolean;
46
22
  showNoResults: boolean;
47
- showSequenceSearchStatus: boolean;
48
- showAlphaFoldDBSearchStatus: boolean;
49
23
  isLoading: boolean;
24
+ lookupMode: import("../components/UniProtIdInput").LookupMode;
25
+ setLookupMode: import("react").Dispatch<import("react").SetStateAction<import("../components/UniProtIdInput").LookupMode>>;
26
+ manualUniprotId: string;
27
+ setManualUniprotId: import("react").Dispatch<import("react").SetStateAction<string>>;
28
+ taxonId: string;
29
+ setTaxonId: import("react").Dispatch<import("react").SetStateAction<string>>;
30
+ effectiveTaxonId: number;
31
+ selectedQueryId: string;
32
+ setSelectedQueryId: import("react").Dispatch<import("react").SetStateAction<string>>;
33
+ setSelectedUniprotId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
34
+ selectedTableAccession: string | undefined;
35
+ uniprotEntries: import("../services/lookupMethods").UniProtEntry[];
36
+ isLookupLoading: boolean;
37
+ lookupError: any;
38
+ uniprotId: string | undefined;
39
+ featureUniprotId: string | undefined;
40
+ recognizedIds: string[];
41
+ geneName: string | undefined;
42
+ isAutoMode: boolean;
43
+ showIdentifierSelector: boolean;
44
+ searchDescription: string;
45
+ searchDescriptionOr: string;
50
46
  };