jbrowse-plugin-protein3d 0.11.0 → 0.11.2

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 (319) hide show
  1. package/README.md +11 -0
  2. package/dist/AddHighlightModel/HighlightComponents.js +1 -3
  3. package/dist/AddHighlightModel/index.js +3 -3
  4. package/dist/AddHighlightModel/proteinViewLookup.js +0 -10
  5. package/dist/LaunchProteinView/components/AlphaFoldDBSearch.js +12 -7
  6. package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.js +3 -17
  7. package/dist/LaunchProteinView/components/FoldseekSearch.js +5 -6
  8. package/dist/LaunchProteinView/components/ProteinViewActions.js +3 -3
  9. package/dist/LaunchProteinView/components/TranscriptSelector.js +8 -2
  10. package/dist/LaunchProteinView/components/UniProtIdInput.js +9 -14
  11. package/dist/LaunchProteinView/components/launchProteinAnnotationView.js +5 -2
  12. package/dist/LaunchProteinView/components/proteinTrackSetup.js +24 -12
  13. package/dist/LaunchProteinView/hooks/useAlphaFoldDBSearch.js +24 -55
  14. package/dist/LaunchProteinView/hooks/useAlphaFoldData.js +13 -11
  15. package/dist/LaunchProteinView/hooks/useFoldseekSearch.js +3 -0
  16. package/dist/LaunchProteinView/hooks/useTranscriptIsoformSelection.js +5 -2
  17. package/dist/LaunchProteinView/hooks/useTranscriptSelection.js +1 -1
  18. package/dist/LaunchProteinView/hooks/useUniProtIdLookup.js +9 -10
  19. package/dist/LaunchProteinView/services/alphaFoldModels.js +49 -0
  20. package/dist/LaunchProteinView/utils/calculateProteinSequence.js +28 -14
  21. package/dist/LaunchProteinView/utils/isoformRanking.js +85 -0
  22. package/dist/LaunchProteinView/utils/launchViewUtils.js +2 -3
  23. package/dist/LaunchProteinView/utils/sessionWithAddTracks.js +6 -0
  24. package/dist/LaunchProteinView/utils/structureUrls.js +9 -13
  25. package/dist/LaunchProteinView/utils/util.js +4 -47
  26. package/dist/LaunchProteinViewExtensionPoint/index.js +29 -25
  27. package/dist/LaunchProteinViewExtensionPoint/resolveShortLaunch.js +4 -2
  28. package/dist/ProteinView/__fixtures__/structureFixtures.js +6 -0
  29. package/dist/ProteinView/alignmentQuality.js +75 -0
  30. package/dist/ProteinView/applyColorTheme.js +4 -0
  31. package/dist/ProteinView/applyLociInteractivity.js +40 -34
  32. package/dist/ProteinView/chooseMappedEntity.js +34 -18
  33. package/dist/ProteinView/components/HeaderStructureInfo.js +9 -5
  34. package/dist/ProteinView/components/ManualAlignmentDialog.js +10 -3
  35. package/dist/ProteinView/components/ProteinAlignment.js +14 -4
  36. package/dist/ProteinView/components/ProteinAlignmentHelpDialog.js +1 -1
  37. package/dist/ProteinView/components/ProteinView.js +3 -6
  38. package/dist/ProteinView/components/ProteinViewHeader.js +3 -2
  39. package/dist/ProteinView/connectedHover.js +28 -0
  40. package/dist/ProteinView/coordinates.js +21 -0
  41. package/dist/ProteinView/extractStructureSequences.js +32 -4
  42. package/dist/ProteinView/frameSelection.js +46 -0
  43. package/dist/ProteinView/hooks/useProteinFeatureTrackData.js +1 -1
  44. package/dist/ProteinView/hooks/useStructureUniProt.js +9 -17
  45. package/dist/ProteinView/loadStructureData.js +13 -3
  46. package/dist/ProteinView/lociChannel.js +31 -0
  47. package/dist/ProteinView/model.js +50 -83
  48. package/dist/ProteinView/molstarExports.js +1 -0
  49. package/dist/ProteinView/pairwiseAlignment.js +21 -7
  50. package/dist/ProteinView/pdbUniProtMapping.js +90 -3
  51. package/dist/ProteinView/proteinViewSpec.js +16 -0
  52. package/dist/ProteinView/showLoading.js +6 -6
  53. package/dist/ProteinView/storedSettings.js +3 -2
  54. package/dist/ProteinView/structureLoader.js +10 -1
  55. package/dist/ProteinView/structureModel.js +201 -82
  56. package/dist/ProteinView/structurePipeline.js +12 -4
  57. package/dist/ProteinView/structureSuperposer.js +10 -6
  58. package/dist/ProteinView/subscribeMolstarInteraction.js +1 -0
  59. package/dist/ProteinView/superposeStructures.js +15 -12
  60. package/dist/ProteinView/util.js +13 -2
  61. package/dist/jbrowse-plugin-protein3d.umd.production.min.js +64 -15
  62. package/dist/jbrowse-plugin-protein3d.umd.production.min.js.map +4 -4
  63. package/dist/mappings.js +106 -10
  64. package/dist/{molstar-chunk-3W2VYRSS.js → molstar-chunk-BYIOCM3L.js} +11 -11
  65. package/dist/{molstar-chunk-3W2VYRSS.js.map → molstar-chunk-BYIOCM3L.js.map} +1 -1
  66. package/dist/test_data/molstarStructure.js +37 -0
  67. package/dist/version.js +1 -1
  68. package/package.json +30 -25
  69. package/src/AddHighlightModel/HighlightComponents.tsx +0 -2
  70. package/src/AddHighlightModel/index.tsx +1 -1
  71. package/src/AddHighlightModel/proteinViewLookup.ts +0 -15
  72. package/src/LaunchProteinView/components/AlphaFoldDBSearch.tsx +18 -26
  73. package/src/LaunchProteinView/components/AlphaFoldDBSearchStatus.tsx +8 -37
  74. package/src/LaunchProteinView/components/FoldseekSearch.tsx +5 -6
  75. package/src/LaunchProteinView/components/ProteinViewActions.tsx +3 -3
  76. package/src/LaunchProteinView/components/TranscriptSelector.tsx +13 -3
  77. package/src/LaunchProteinView/components/UniProtIdInput.tsx +9 -48
  78. package/src/LaunchProteinView/components/launchProteinAnnotationView.ts +11 -4
  79. package/src/LaunchProteinView/components/proteinAssemblySetup.ts +1 -1
  80. package/src/LaunchProteinView/components/proteinTrackSetup.ts +25 -13
  81. package/src/LaunchProteinView/hooks/useAlphaFoldDBSearch.ts +30 -75
  82. package/src/LaunchProteinView/hooks/useAlphaFoldData.ts +30 -15
  83. package/src/LaunchProteinView/hooks/useFoldseekSearch.ts +3 -0
  84. package/src/LaunchProteinView/hooks/useTranscriptIsoformSelection.ts +9 -9
  85. package/src/LaunchProteinView/hooks/useTranscriptSelection.ts +1 -1
  86. package/src/LaunchProteinView/hooks/useUniProtIdLookup.ts +11 -10
  87. package/src/LaunchProteinView/services/alphaFoldModels.test.ts +76 -0
  88. package/src/LaunchProteinView/services/alphaFoldModels.ts +87 -0
  89. package/src/LaunchProteinView/utils/calculateProteinSequence.ts +35 -15
  90. package/src/LaunchProteinView/utils/isoformRanking.ts +138 -0
  91. package/src/LaunchProteinView/utils/launchViewUtils.ts +3 -10
  92. package/src/LaunchProteinView/utils/pickStructureSequence.test.ts +36 -7
  93. package/src/LaunchProteinView/utils/selectBestTranscript.test.ts +48 -1
  94. package/src/LaunchProteinView/utils/sessionWithAddTracks.ts +15 -0
  95. package/src/LaunchProteinView/utils/structureUrls.test.ts +27 -0
  96. package/src/LaunchProteinView/utils/structureUrls.ts +10 -17
  97. package/src/LaunchProteinView/utils/util.ts +5 -82
  98. package/src/LaunchProteinViewExtensionPoint/index.ts +48 -29
  99. package/src/LaunchProteinViewExtensionPoint/resolveShortLaunch.ts +8 -2
  100. package/src/ProteinView/__fixtures__/structureFixtures.ts +12 -0
  101. package/src/ProteinView/alignmentQuality.test.ts +101 -0
  102. package/src/ProteinView/alignmentQuality.ts +101 -0
  103. package/src/ProteinView/applyColorTheme.ts +5 -0
  104. package/src/ProteinView/applyLociInteractivity.ts +81 -49
  105. package/src/ProteinView/chooseMappedEntity.test.ts +26 -0
  106. package/src/ProteinView/chooseMappedEntity.ts +48 -20
  107. package/src/ProteinView/components/HeaderStructureInfo.tsx +10 -6
  108. package/src/ProteinView/components/ManualAlignmentDialog.tsx +18 -3
  109. package/src/ProteinView/components/ProteinAlignment.tsx +41 -7
  110. package/src/ProteinView/components/ProteinAlignmentHelpDialog.tsx +6 -1
  111. package/src/ProteinView/components/ProteinView.tsx +3 -6
  112. package/src/ProteinView/components/ProteinViewHeader.tsx +9 -1
  113. package/src/ProteinView/connectedHover.test.ts +96 -0
  114. package/src/ProteinView/connectedHover.ts +63 -0
  115. package/src/ProteinView/coordinates.test.ts +20 -0
  116. package/src/ProteinView/coordinates.ts +25 -0
  117. package/src/ProteinView/extractStructureSequences.test.ts +48 -2
  118. package/src/ProteinView/extractStructureSequences.ts +58 -5
  119. package/src/ProteinView/frameSelection.test.ts +147 -0
  120. package/src/ProteinView/frameSelection.ts +71 -0
  121. package/src/ProteinView/hooks/useProteinFeatureTrackData.ts +1 -1
  122. package/src/ProteinView/hooks/useStructureUniProt.ts +19 -34
  123. package/src/ProteinView/labelSeqIdIntegration.test.ts +5 -1
  124. package/src/ProteinView/loadStructureData.ts +22 -3
  125. package/src/ProteinView/lociChannel.test.ts +102 -0
  126. package/src/ProteinView/lociChannel.ts +54 -0
  127. package/src/ProteinView/model.ts +66 -94
  128. package/src/ProteinView/molstarExports.ts +1 -0
  129. package/src/ProteinView/molstarSelectionQuery.test.ts +20 -75
  130. package/src/ProteinView/pairwiseAlignment.ts +28 -8
  131. package/src/ProteinView/pdbUniProtMapping.test.ts +148 -5
  132. package/src/ProteinView/pdbUniProtMapping.ts +120 -5
  133. package/src/ProteinView/proteinViewSpec.test.ts +23 -3
  134. package/src/ProteinView/proteinViewSpec.ts +30 -1
  135. package/src/ProteinView/showLoading.test.ts +5 -5
  136. package/src/ProteinView/showLoading.ts +7 -9
  137. package/src/ProteinView/storedSettings.ts +9 -5
  138. package/src/ProteinView/structureLoader.test.ts +25 -0
  139. package/src/ProteinView/structureLoader.ts +9 -1
  140. package/src/ProteinView/structureModel.test.ts +219 -2
  141. package/src/ProteinView/structureModel.ts +258 -105
  142. package/src/ProteinView/structurePipeline.ts +14 -6
  143. package/src/ProteinView/structureSuperposer.test.ts +7 -0
  144. package/src/ProteinView/structureSuperposer.ts +14 -6
  145. package/src/ProteinView/subscribeMolstarInteraction.ts +5 -0
  146. package/src/ProteinView/superposeStructures.ts +17 -22
  147. package/src/ProteinView/util.test.ts +15 -0
  148. package/src/ProteinView/util.ts +13 -1
  149. package/src/ProteinView/withStoredSettings.test.ts +21 -2
  150. package/src/mappings.test.ts +77 -0
  151. package/src/mappings.ts +120 -10
  152. package/src/test_data/molstarStructure.ts +51 -0
  153. package/src/version.ts +1 -1
  154. package/dist/AddHighlightModel/GenomeMouseoverHighlight.d.ts +0 -6
  155. package/dist/AddHighlightModel/GenomeTo1DProteinHoverHighlight.d.ts +0 -6
  156. package/dist/AddHighlightModel/Highlight.d.ts +0 -8
  157. package/dist/AddHighlightModel/HighlightComponents.d.ts +0 -6
  158. package/dist/AddHighlightModel/Protein1DToGenomeHoverHighlight.d.ts +0 -6
  159. package/dist/AddHighlightModel/ProteinToGenomeHighlight.d.ts +0 -8
  160. package/dist/AddHighlightModel/ProteinToGenomeHighlightInner.d.ts +0 -8
  161. package/dist/AddHighlightModel/ProteinToMsaHoverSync.d.ts +0 -5
  162. package/dist/AddHighlightModel/ProteinToMsaHoverSync.js +0 -84
  163. package/dist/AddHighlightModel/findConnectedMsaView.d.ts +0 -23
  164. package/dist/AddHighlightModel/findConnectedMsaView.js +0 -23
  165. package/dist/AddHighlightModel/index.d.ts +0 -2
  166. package/dist/AddHighlightModel/msaRowMatch.d.ts +0 -10
  167. package/dist/AddHighlightModel/msaRowMatch.js +0 -16
  168. package/dist/AddHighlightModel/proteinViewLookup.d.ts +0 -37
  169. package/dist/AddHighlightModel/util.d.ts +0 -20
  170. package/dist/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.d.ts +0 -18
  171. package/dist/AlphaFoldConfidenceAdapter/configSchema.d.ts +0 -3
  172. package/dist/AlphaFoldConfidenceAdapter/index.d.ts +0 -2
  173. package/dist/AlphaMissensePathogenicityAdapter/AlphaMissensePathogenicityAdapter.d.ts +0 -35
  174. package/dist/AlphaMissensePathogenicityAdapter/configSchema.d.ts +0 -3
  175. package/dist/AlphaMissensePathogenicityAdapter/index.d.ts +0 -2
  176. package/dist/BaseProteinAnnotationAdapter.d.ts +0 -29
  177. package/dist/LaunchProteinView/components/AlignmentSettingsButton.d.ts +0 -6
  178. package/dist/LaunchProteinView/components/AlphaFoldDBSearch.d.ts +0 -13
  179. package/dist/LaunchProteinView/components/AlphaFoldDBSearchStatus.d.ts +0 -10
  180. package/dist/LaunchProteinView/components/Checkbox2.d.ts +0 -7
  181. package/dist/LaunchProteinView/components/FoldseekActionMenu.d.ts +0 -17
  182. package/dist/LaunchProteinView/components/FoldseekDatabaseSelector.d.ts +0 -7
  183. package/dist/LaunchProteinView/components/FoldseekResultsTable.d.ts +0 -13
  184. package/dist/LaunchProteinView/components/FoldseekSearch.d.ts +0 -10
  185. package/dist/LaunchProteinView/components/HelpButton.d.ts +0 -2
  186. package/dist/LaunchProteinView/components/HelpDialog.d.ts +0 -4
  187. package/dist/LaunchProteinView/components/IdentifierSelector.d.ts +0 -9
  188. package/dist/LaunchProteinView/components/IsoformSequencesToggle.d.ts +0 -7
  189. package/dist/LaunchProteinView/components/LaunchOptionsMenu.d.ts +0 -13
  190. package/dist/LaunchProteinView/components/LaunchProteinViewDialog.d.ts +0 -7
  191. package/dist/LaunchProteinView/components/LaunchSettingsDialog.d.ts +0 -5
  192. package/dist/LaunchProteinView/components/MSATable.d.ts +0 -7
  193. package/dist/LaunchProteinView/components/PdbResultsTable.d.ts +0 -7
  194. package/dist/LaunchProteinView/components/PdbSearch.d.ts +0 -13
  195. package/dist/LaunchProteinView/components/ProteinViewActions.d.ts +0 -29
  196. package/dist/LaunchProteinView/components/SequenceMismatchNotice.d.ts +0 -6
  197. package/dist/LaunchProteinView/components/SequenceSearchStatus.d.ts +0 -11
  198. package/dist/LaunchProteinView/components/SequenceSearchStatus.js +0 -16
  199. package/dist/LaunchProteinView/components/StructureSourcePicker.d.ts +0 -10
  200. package/dist/LaunchProteinView/components/TabPanel.d.ts +0 -6
  201. package/dist/LaunchProteinView/components/TranscriptSelector.d.ts +0 -12
  202. package/dist/LaunchProteinView/components/UniProtIdInput.d.ts +0 -16
  203. package/dist/LaunchProteinView/components/UniProtResultsTable.d.ts +0 -9
  204. package/dist/LaunchProteinView/components/UserProvidedStructure.d.ts +0 -14
  205. package/dist/LaunchProteinView/components/launchProteinAnnotationView.d.ts +0 -9
  206. package/dist/LaunchProteinView/components/proteinAssemblySetup.d.ts +0 -5
  207. package/dist/LaunchProteinView/components/proteinTrackSetup.d.ts +0 -9
  208. package/dist/LaunchProteinView/hooks/swrOptions.d.ts +0 -5
  209. package/dist/LaunchProteinView/hooks/useAlphaFoldDBSearch.d.ts +0 -53
  210. package/dist/LaunchProteinView/hooks/useAlphaFoldData.d.ts +0 -10
  211. package/dist/LaunchProteinView/hooks/useAlphaFoldSequenceSearch.d.ts +0 -30
  212. package/dist/LaunchProteinView/hooks/useAlphaFoldSequenceSearch.js +0 -31
  213. package/dist/LaunchProteinView/hooks/useDebouncedValue.d.ts +0 -6
  214. package/dist/LaunchProteinView/hooks/useFoldseekSearch.d.ts +0 -16
  215. package/dist/LaunchProteinView/hooks/useIsoformProteinSequences.d.ts +0 -12
  216. package/dist/LaunchProteinView/hooks/useLocalStorage.d.ts +0 -1
  217. package/dist/LaunchProteinView/hooks/usePdbBestStructures.d.ts +0 -6
  218. package/dist/LaunchProteinView/hooks/useSafeLaunch.d.ts +0 -9
  219. package/dist/LaunchProteinView/hooks/useStructureFileSequence.d.ts +0 -9
  220. package/dist/LaunchProteinView/hooks/useTranscriptIsoformSelection.d.ts +0 -19
  221. package/dist/LaunchProteinView/hooks/useTranscriptSelection.d.ts +0 -11
  222. package/dist/LaunchProteinView/hooks/useUniProtIdLookup.d.ts +0 -39
  223. package/dist/LaunchProteinView/hooks/useUniProtSearch.d.ts +0 -14
  224. package/dist/LaunchProteinView/index.d.ts +0 -2
  225. package/dist/LaunchProteinView/services/foldseekApi.d.ts +0 -84
  226. package/dist/LaunchProteinView/services/lookupMethods.d.ts +0 -14
  227. package/dist/LaunchProteinView/services/pdbeBestStructures.d.ts +0 -22
  228. package/dist/LaunchProteinView/utils/caCoordsToPdb.d.ts +0 -18
  229. package/dist/LaunchProteinView/utils/calculateProteinSequence.d.ts +0 -17
  230. package/dist/LaunchProteinView/utils/geneticCodes.d.ts +0 -14
  231. package/dist/LaunchProteinView/utils/getSearchDescription.d.ts +0 -6
  232. package/dist/LaunchProteinView/utils/launchHelpers.d.ts +0 -22
  233. package/dist/LaunchProteinView/utils/launchViewUtils.d.ts +0 -32
  234. package/dist/LaunchProteinView/utils/md5.d.ts +0 -1
  235. package/dist/LaunchProteinView/utils/md5.js +0 -130
  236. package/dist/LaunchProteinView/utils/readStructureFile.d.ts +0 -5
  237. package/dist/LaunchProteinView/utils/sideBySide.d.ts +0 -16
  238. package/dist/LaunchProteinView/utils/structureUrls.d.ts +0 -45
  239. package/dist/LaunchProteinView/utils/util.d.ts +0 -80
  240. package/dist/LaunchProteinViewExtensionPoint/index.d.ts +0 -2
  241. package/dist/LaunchProteinViewExtensionPoint/resolveShortLaunch.d.ts +0 -27
  242. package/dist/Protein1DLinkage/index.d.ts +0 -4
  243. package/dist/Protein1DLinkage/linkage.d.ts +0 -34
  244. package/dist/ProteinView/__fixtures__/structureFixtures.d.ts +0 -14
  245. package/dist/ProteinView/addStructureFromData.d.ts +0 -19
  246. package/dist/ProteinView/addStructureFromURL.d.ts +0 -17
  247. package/dist/ProteinView/applyColorTheme.d.ts +0 -38
  248. package/dist/ProteinView/applyLociInteractivity.d.ts +0 -21
  249. package/dist/ProteinView/autoScroll.d.ts +0 -30
  250. package/dist/ProteinView/chooseMappedEntity.d.ts +0 -52
  251. package/dist/ProteinView/components/AddStructureDialog.d.ts +0 -6
  252. package/dist/ProteinView/components/AlignmentRuler.d.ts +0 -15
  253. package/dist/ProteinView/components/ChainSelect.d.ts +0 -6
  254. package/dist/ProteinView/components/FeatureBar.d.ts +0 -9
  255. package/dist/ProteinView/components/FeatureTypeLabel.d.ts +0 -10
  256. package/dist/ProteinView/components/HeaderStructureInfo.d.ts +0 -6
  257. package/dist/ProteinView/components/HoverMarker.d.ts +0 -6
  258. package/dist/ProteinView/components/ManualAlignmentDialog.d.ts +0 -6
  259. package/dist/ProteinView/components/ProteinAlignment.d.ts +0 -6
  260. package/dist/ProteinView/components/ProteinAlignmentHelpButton.d.ts +0 -5
  261. package/dist/ProteinView/components/ProteinAlignmentHelpDialog.d.ts +0 -4
  262. package/dist/ProteinView/components/ProteinFeatureTrack.d.ts +0 -12
  263. package/dist/ProteinView/components/ProteinView.d.ts +0 -6
  264. package/dist/ProteinView/components/ProteinViewHeader.d.ts +0 -6
  265. package/dist/ProteinView/components/ResidueValueTrack.d.ts +0 -19
  266. package/dist/ProteinView/components/SplitString.d.ts +0 -21
  267. package/dist/ProteinView/constants.d.ts +0 -11
  268. package/dist/ProteinView/coordinates.d.ts +0 -52
  269. package/dist/ProteinView/css/molstar.d.ts +0 -2
  270. package/dist/ProteinView/extractPerResidueConfidence.d.ts +0 -49
  271. package/dist/ProteinView/extractStructureSequences.d.ts +0 -130
  272. package/dist/ProteinView/hooks/useAlignmentColumnHover.d.ts +0 -11
  273. package/dist/ProteinView/hooks/useProteinFeatureTrackData.d.ts +0 -47
  274. package/dist/ProteinView/hooks/useStructureUniProt.d.ts +0 -26
  275. package/dist/ProteinView/hooks/useUniProtFeatures.d.ts +0 -14
  276. package/dist/ProteinView/index.d.ts +0 -2
  277. package/dist/ProteinView/loadMolstar.d.ts +0 -2
  278. package/dist/ProteinView/loadStructureData.d.ts +0 -26
  279. package/dist/ProteinView/model.d.ts +0 -2133
  280. package/dist/ProteinView/molstarExports.d.ts +0 -19
  281. package/dist/ProteinView/pairwiseAlignment.d.ts +0 -29
  282. package/dist/ProteinView/pdbUniProtMapping.d.ts +0 -43
  283. package/dist/ProteinView/proteinAbbreviationMapping.d.ts +0 -7
  284. package/dist/ProteinView/proteinToGenomeMapping.d.ts +0 -55
  285. package/dist/ProteinView/proteinViewSpec.d.ts +0 -87
  286. package/dist/ProteinView/residueTracks.d.ts +0 -21
  287. package/dist/ProteinView/showLoading.d.ts +0 -7
  288. package/dist/ProteinView/storedSettings.d.ts +0 -12
  289. package/dist/ProteinView/structureFormat.d.ts +0 -23
  290. package/dist/ProteinView/structureLoader.d.ts +0 -30
  291. package/dist/ProteinView/structureModel.d.ts +0 -495
  292. package/dist/ProteinView/structurePipeline.d.ts +0 -26
  293. package/dist/ProteinView/structureSuperposer.d.ts +0 -30
  294. package/dist/ProteinView/subscribeMolstarInteraction.d.ts +0 -32
  295. package/dist/ProteinView/superposeStructures.d.ts +0 -2
  296. package/dist/ProteinView/types.d.ts +0 -14
  297. package/dist/ProteinView/useProteinView.d.ts +0 -9
  298. package/dist/ProteinView/util.d.ts +0 -23
  299. package/dist/ProteinView/withTemporaryMolstarPlugin.d.ts +0 -9
  300. package/dist/UniProtVariationAdapter/UniProtVariationAdapter.d.ts +0 -81
  301. package/dist/UniProtVariationAdapter/configSchema.d.ts +0 -3
  302. package/dist/UniProtVariationAdapter/index.d.ts +0 -2
  303. package/dist/components/ExternalLink.d.ts +0 -3
  304. package/dist/extendStateModel.d.ts +0 -4
  305. package/dist/fetchUtils.d.ts +0 -10
  306. package/dist/index.d.ts +0 -8
  307. package/dist/mappings.d.ts +0 -45
  308. package/dist/storage.d.ts +0 -3
  309. package/dist/test_data/gene.d.ts +0 -580
  310. package/dist/version.d.ts +0 -1
  311. package/src/AddHighlightModel/ProteinToMsaHoverSync.tsx +0 -150
  312. package/src/AddHighlightModel/findConnectedMsaView.test.ts +0 -53
  313. package/src/AddHighlightModel/findConnectedMsaView.ts +0 -35
  314. package/src/AddHighlightModel/msaHoverSyncGuard.test.ts +0 -153
  315. package/src/AddHighlightModel/msaRowMatch.test.ts +0 -27
  316. package/src/AddHighlightModel/msaRowMatch.ts +0 -20
  317. package/src/LaunchProteinView/components/SequenceSearchStatus.tsx +0 -41
  318. package/src/LaunchProteinView/hooks/useAlphaFoldSequenceSearch.ts +0 -66
  319. package/src/LaunchProteinView/utils/md5.ts +0 -187
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;
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
2
  import HighlightComponents from './HighlightComponents';
3
3
  export default function AddHighlightModelF(pluginManager) {
4
- pluginManager.addToExtensionPoint('LinearGenomeView-TracksContainerComponent',
5
- // @ts-expect-error
6
- (rest, { model }) => {
4
+ pluginManager.addToExtensionPoint(
5
+ // @ts-expect-error v4 hosts have no contributeToExtensionPoint
6
+ 'LinearGenomeView-TracksContainerComponent', (rest, { model }) => {
7
7
  return [
8
8
  ...rest,
9
9
  React.createElement(HighlightComponents, { key: "highlight_protein_viewer_protein3d", model: model }),
@@ -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;
@@ -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
  }
@@ -66,18 +66,17 @@ const FoldseekSearch = observer(function FoldseekSearch({ feature, session, view
66
66
  React.createElement(TextField, { label: "Protein sequence (amino acids)", multiline: true, rows: 4, value: sequence, onChange: e => {
67
67
  setUserEditedSequence(e.target.value);
68
68
  invalidatePrediction();
69
- }, placeholder: `MKTVRQERLKSIVRILERSKEPVSGAQLAEEL...`, disabled: isBusy, InputProps: {
70
- className: classes.sequenceInput,
69
+ }, placeholder: `MKTVRQERLKSIVRILERSKEPVSGAQLAEEL...`, disabled: isBusy, slotProps: {
70
+ input: { className: classes.sequenceInput },
71
71
  } }))) : null,
72
72
  di3Sequence ? (React.createElement("div", { className: classes.di3Section },
73
73
  React.createElement(Typography, { variant: "subtitle2" }, "3Di structural alphabet (used for searching):"),
74
- React.createElement(TextField, { multiline: true, rows: 4, value: di3Sequence, InputProps: {
75
- className: classes.sequenceInput,
76
- readOnly: true,
74
+ React.createElement(TextField, { multiline: true, rows: 4, value: di3Sequence, slotProps: {
75
+ input: { className: classes.sequenceInput, readOnly: true },
77
76
  } }))) : null,
78
77
  React.createElement(FoldseekDatabaseSelector, { selected: selectedDatabases, onChange: setSelectedDatabases, disabled: isBusy }),
79
78
  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),
79
+ results ? (React.createElement(FoldseekResultsTable, { results: results, session: session, view: view, feature: feature, selectedTranscript: selectedTranscript, userProvidedTranscriptSequence: selectedIsoformData?.seq, onClose: handleClose })) : null),
81
80
  React.createElement(DialogActions, null,
82
81
  React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => {
83
82
  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,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
  ' ',
@@ -13,10 +13,13 @@ export async function launchProteinAnnotationView({ session, feature, selectedTr
13
13
  const proteinLinkage = connectedViewId && selectedTranscript
14
14
  ? { connectedViewId, feature: selectedTranscript.toJSON(), uniprotId }
15
15
  : undefined;
16
- const view = session.addView('LinearGenomeView', {
16
+ // a named object, because proteinLinkage comes from this plugin's own
17
+ // LinearGenomeView extension, which the launch snapshot type cannot see
18
+ const snapshot = {
17
19
  type: 'LinearGenomeView',
18
20
  displayName: formatViewName('Protein annotations', feature, selectedTranscript, uniprotId),
19
21
  proteinLinkage,
20
- });
22
+ };
23
+ const view = session.addView('LinearGenomeView', snapshot);
21
24
  await view.navToLocString(uniprotId, uniprotId);
22
25
  }
@@ -92,6 +92,18 @@ function addAlphaFoldConfidenceTrack({ session, uniprotId, confidenceUrl, }) {
92
92
  },
93
93
  },
94
94
  assemblyNames: [uniprotId],
95
+ displays: [
96
+ {
97
+ type: 'LinearWiggleDisplay',
98
+ displayId: `${uniprotId}-AlphaFold-confidence-LinearWiggleDisplay`,
99
+ // pLDDT 50 is AlphaFold's own line between low and very low
100
+ // confidence: residues above it in AlphaFold's blue, below in its
101
+ // orange
102
+ bicolorPivot: 50,
103
+ posColor: '#0053d6',
104
+ negColor: '#ff7d45',
105
+ },
106
+ ],
95
107
  });
96
108
  }
97
109
  }
@@ -115,14 +127,11 @@ function addAlphaMissenseTrack({ session, uniprotId, }) {
115
127
  type: 'MultiLinearWiggleDisplay',
116
128
  displayId: `${uniprotId}-AlphaMissense-scores-MultiLinearWiggleDisplay`,
117
129
  defaultRendering: 'multirowdensity',
118
- renderers: {
119
- MultiDensityRenderer: {
120
- type: 'MultiDensityRenderer',
121
- bicolorPivotValue: 0.5,
122
- posColor: 'red',
123
- negColor: 'blue',
124
- },
125
- },
130
+ // AlphaMissense's own reading: likely pathogenic red, likely benign
131
+ // blue, fading to white at the midpoint of its 0-1 score
132
+ bicolorPivot: 0.5,
133
+ posColor: '#d7191c',
134
+ negColor: '#2c7bb6',
126
135
  },
127
136
  ],
128
137
  });
@@ -150,8 +159,11 @@ export async function addAllProteinTracks({ session, uniprotId, confidenceUrl, }
150
159
  uniprotId,
151
160
  confidenceUrl,
152
161
  });
153
- addAlphaMissenseTrack({
154
- session,
155
- uniprotId,
156
- });
162
+ // AlphaFold DB publishes substitution scores for canonical entries only
163
+ if (!uniprotId.includes('-')) {
164
+ addAlphaMissenseTrack({
165
+ session,
166
+ uniprotId,
167
+ });
168
+ }
157
169
  }
@@ -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,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);
@@ -8,8 +8,7 @@ import { extractFeatureIdentifiers, extractTaxonId } from '../utils/util';
8
8
  /**
9
9
  * Which UniProt entry a feature is, by the dialog's lookup modes: the
10
10
  * feature's own attribute, the ID-mapping search over its recognised ids and
11
- * gene name, a typed accession, or none (sequence mode, where the structure
12
- * search itself names the entry). Shared by every tab that starts from an
11
+ * gene name, or a typed accession. Shared by every tab that starts from an
13
12
  * accession so they agree on what the gene is.
14
13
  */
15
14
  export default function useUniProtIdLookup({ feature, view, }) {
@@ -39,7 +38,6 @@ export default function useUniProtIdLookup({ feature, view, }) {
39
38
  const [selectedUniprotId, setSelectedUniprotId] = useState();
40
39
  const featureUniprotId = geneIds.uniprotId;
41
40
  const effectiveLookupMode = lookupMode === 'auto' && featureUniprotId ? 'feature' : lookupMode;
42
- const isSequenceMode = effectiveLookupMode === 'sequence';
43
41
  const isAutoMode = effectiveLookupMode === 'auto';
44
42
  const { entries: uniprotEntries, isLoading: isLookupLoading, error: lookupError, } = useUniProtSearch({
45
43
  recognizedIds: geneIds.recognizedIds,
@@ -52,14 +50,17 @@ export default function useUniProtIdLookup({ feature, view, }) {
52
50
  // Debounce manual entry so fetches don't fire on every keystroke and
53
51
  // pollute the SWR cache with partial-ID 404s.
54
52
  const debouncedManualUniprotId = useDebouncedValue(manualUniprotId, 400);
53
+ // a row picked from an earlier search (another taxon, another identifier)
54
+ // stops counting once the table no longer lists it
55
+ const pickedUniprotId = uniprotEntries.some(e => e.accession === selectedUniprotId)
56
+ ? selectedUniprotId
57
+ : undefined;
55
58
  const autoUniprotId = uniprotEntries[0]?.accession;
56
59
  const uniprotId = effectiveLookupMode === 'feature'
57
60
  ? featureUniprotId
58
61
  : isAutoMode
59
- ? (selectedUniprotId ?? autoUniprotId)
60
- : effectiveLookupMode === 'manual'
61
- ? debouncedManualUniprotId
62
- : undefined;
62
+ ? (pickedUniprotId ?? autoUniprotId)
63
+ : debouncedManualUniprotId;
63
64
  return {
64
65
  lookupMode: effectiveLookupMode,
65
66
  setLookupMode,
@@ -71,9 +72,8 @@ export default function useUniProtIdLookup({ feature, view, }) {
71
72
  effectiveTaxonId: effectiveTaxonId ?? 9606,
72
73
  selectedQueryId,
73
74
  setSelectedQueryId,
74
- selectedUniprotId,
75
75
  setSelectedUniprotId,
76
- selectedTableAccession: selectedUniprotId ?? autoUniprotId,
76
+ selectedTableAccession: pickedUniprotId ?? autoUniprotId,
77
77
  uniprotEntries,
78
78
  isLookupLoading,
79
79
  lookupError,
@@ -82,7 +82,6 @@ export default function useUniProtIdLookup({ feature, view, }) {
82
82
  recognizedIds: geneIds.recognizedIds,
83
83
  geneName: geneIds.geneName,
84
84
  isAutoMode,
85
- isSequenceMode,
86
85
  showIdentifierSelector: isAutoMode && (geneIds.recognizedIds.length > 0 || !!geneIds.geneName),
87
86
  searchDescription: getSearchDescription({
88
87
  selectedQueryId,