jbrowse-plugin-msaview 2.2.8 → 2.3.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 (134) hide show
  1. package/dist/AddHighlightModel/index.d.ts +1 -1
  2. package/dist/AddHighlightModel/index.js.map +1 -1
  3. package/dist/BgzipFastaMsaAdapter/BgzipFastaMsaAdapter.d.ts +2 -1
  4. package/dist/BgzipFastaMsaAdapter/BgzipFastaMsaAdapter.js +1 -1
  5. package/dist/BgzipFastaMsaAdapter/BgzipFastaMsaAdapter.js.map +1 -1
  6. package/dist/BgzipFastaMsaAdapter/configSchema.d.ts +3 -3
  7. package/dist/BgzipFastaMsaAdapter/configSchema.js.map +1 -1
  8. package/dist/BgzipFastaMsaAdapter/index.d.ts +1 -1
  9. package/dist/BgzipFastaMsaAdapter/index.js.map +1 -1
  10. package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.d.ts +1 -1
  11. package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js +1 -1
  12. package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js.map +1 -1
  13. package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.js.map +1 -1
  14. package/dist/LaunchMsaView/components/LaunchMsaViewDialog.d.ts +1 -1
  15. package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js.map +1 -1
  16. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.d.ts +1 -1
  17. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +1 -1
  18. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js.map +1 -1
  19. package/dist/LaunchMsaView/components/ManualMSALoader/launchView.d.ts +1 -1
  20. package/dist/LaunchMsaView/components/ManualMSALoader/launchView.js.map +1 -1
  21. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.d.ts +1 -2
  22. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js +21 -14
  23. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js.map +1 -1
  24. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.d.ts +1 -1
  25. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js +32 -35
  26. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js.map +1 -1
  27. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.d.ts +1 -1
  28. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js +2 -2
  29. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js.map +1 -1
  30. package/dist/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.d.ts +1 -1
  31. package/dist/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.js.map +1 -1
  32. package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.d.ts +2 -0
  33. package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.js +1 -0
  34. package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.js.map +1 -1
  35. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.d.ts +1 -1
  36. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +6 -8
  37. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js.map +1 -1
  38. package/dist/LaunchMsaView/components/PreLoadedMSA/fetchMSAData.d.ts +2 -2
  39. package/dist/LaunchMsaView/components/PreLoadedMSA/fetchMSAData.js.map +1 -1
  40. package/dist/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.d.ts +1 -1
  41. package/dist/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.js.map +1 -1
  42. package/dist/LaunchMsaView/components/TranscriptSelector.d.ts +3 -3
  43. package/dist/LaunchMsaView/components/TranscriptSelector.js +4 -4
  44. package/dist/LaunchMsaView/components/TranscriptSelector.js.map +1 -1
  45. package/dist/LaunchMsaView/components/useTranscriptSelection.d.ts +1 -1
  46. package/dist/LaunchMsaView/components/useTranscriptSelection.js +1 -2
  47. package/dist/LaunchMsaView/components/useTranscriptSelection.js.map +1 -1
  48. package/dist/LaunchMsaView/components/util.js +1 -1
  49. package/dist/LaunchMsaView/components/util.js.map +1 -1
  50. package/dist/LaunchMsaView/index.d.ts +1 -1
  51. package/dist/LaunchMsaView/index.js.map +1 -1
  52. package/dist/LaunchMsaView/util.d.ts +1 -0
  53. package/dist/LaunchMsaView/util.js +10 -0
  54. package/dist/LaunchMsaView/util.js.map +1 -1
  55. package/dist/MsaViewPanel/afterCreateAutoruns.d.ts +10 -0
  56. package/dist/MsaViewPanel/afterCreateAutoruns.js +258 -0
  57. package/dist/MsaViewPanel/afterCreateAutoruns.js.map +1 -0
  58. package/dist/MsaViewPanel/blosum62.d.ts +2 -0
  59. package/dist/MsaViewPanel/blosum62.js +628 -0
  60. package/dist/MsaViewPanel/blosum62.js.map +1 -0
  61. package/dist/MsaViewPanel/components/LoadingBLAST.d.ts +1 -1
  62. package/dist/MsaViewPanel/components/LoadingBLAST.js.map +1 -1
  63. package/dist/MsaViewPanel/components/MsaViewPanel.d.ts +1 -1
  64. package/dist/MsaViewPanel/components/MsaViewPanel.js.map +1 -1
  65. package/dist/MsaViewPanel/doLaunchBlast.d.ts +1 -1
  66. package/dist/MsaViewPanel/doLaunchBlast.js.map +1 -1
  67. package/dist/MsaViewPanel/genomeToMSA.d.ts +1 -1
  68. package/dist/MsaViewPanel/genomeToMSA.js.map +1 -1
  69. package/dist/MsaViewPanel/index.d.ts +1 -1
  70. package/dist/MsaViewPanel/index.js.map +1 -1
  71. package/dist/MsaViewPanel/model.d.ts +31 -39
  72. package/dist/MsaViewPanel/model.js +17 -309
  73. package/dist/MsaViewPanel/model.js.map +1 -1
  74. package/dist/MsaViewPanel/msaDataStore.d.ts +3 -4
  75. package/dist/MsaViewPanel/msaDataStore.js +59 -173
  76. package/dist/MsaViewPanel/msaDataStore.js.map +1 -1
  77. package/dist/MsaViewPanel/pairwiseAlignment.d.ts +0 -7
  78. package/dist/MsaViewPanel/pairwiseAlignment.js +1 -636
  79. package/dist/MsaViewPanel/pairwiseAlignment.js.map +1 -1
  80. package/dist/MsaViewPanel/structureConnection.js +1 -5
  81. package/dist/MsaViewPanel/structureConnection.js.map +1 -1
  82. package/dist/MsaViewPanel/util.d.ts +1 -1
  83. package/dist/index.d.ts +6 -6
  84. package/dist/index.js +21 -22
  85. package/dist/index.js.map +1 -1
  86. package/dist/jbrowse-plugin-msaview.umd.production.min.js +29 -29
  87. package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
  88. package/dist/utils/msa.js +35 -77
  89. package/dist/utils/msa.js.map +1 -1
  90. package/dist/utils/ncbiBlast.js +1 -10
  91. package/dist/utils/ncbiBlast.js.map +1 -1
  92. package/dist/version.d.ts +1 -1
  93. package/dist/version.js +1 -1
  94. package/dist/version.js.map +1 -1
  95. package/package.json +33 -30
  96. package/src/AddHighlightModel/index.tsx +1 -1
  97. package/src/BgzipFastaMsaAdapter/BgzipFastaMsaAdapter.ts +3 -4
  98. package/src/BgzipFastaMsaAdapter/configSchema.ts +2 -1
  99. package/src/BgzipFastaMsaAdapter/index.ts +2 -1
  100. package/src/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.tsx +2 -6
  101. package/src/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.ts +2 -1
  102. package/src/LaunchMsaView/components/LaunchMsaViewDialog.tsx +2 -1
  103. package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +6 -7
  104. package/src/LaunchMsaView/components/ManualMSALoader/launchView.ts +5 -2
  105. package/src/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.tsx +22 -17
  106. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.tsx +40 -52
  107. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.tsx +6 -13
  108. package/src/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.ts +2 -1
  109. package/src/LaunchMsaView/components/NCBIBlastQuery/consts.ts +2 -0
  110. package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +7 -19
  111. package/src/LaunchMsaView/components/PreLoadedMSA/fetchMSAData.ts +2 -2
  112. package/src/LaunchMsaView/components/PreLoadedMSA/preCalculatedLaunchView.ts +1 -2
  113. package/src/LaunchMsaView/components/TranscriptSelector.tsx +7 -6
  114. package/src/LaunchMsaView/components/useTranscriptSelection.ts +1 -6
  115. package/src/LaunchMsaView/components/util.ts +1 -1
  116. package/src/LaunchMsaView/index.ts +6 -5
  117. package/src/LaunchMsaView/util.ts +11 -0
  118. package/src/MsaViewPanel/afterCreateAutoruns.ts +299 -0
  119. package/src/MsaViewPanel/blosum62.ts +628 -0
  120. package/src/MsaViewPanel/components/LoadingBLAST.tsx +2 -1
  121. package/src/MsaViewPanel/components/MsaViewPanel.tsx +2 -1
  122. package/src/MsaViewPanel/doLaunchBlast.ts +1 -1
  123. package/src/MsaViewPanel/genomeToMSA.ts +2 -1
  124. package/src/MsaViewPanel/index.ts +2 -1
  125. package/src/MsaViewPanel/model.ts +30 -392
  126. package/src/MsaViewPanel/msaDataStore.ts +56 -196
  127. package/src/MsaViewPanel/pairwiseAlignment.ts +1 -637
  128. package/src/MsaViewPanel/structureConnection.ts +1 -5
  129. package/src/MsaViewPanel/util.ts +1 -1
  130. package/src/index.ts +5 -4
  131. package/src/utils/msa.ts +45 -100
  132. package/src/utils/ncbiBlast.ts +3 -13
  133. package/src/version.ts +1 -1
  134. package/CHANGELOG.md +0 -101
@@ -7,22 +7,21 @@ import { genomeToTranscriptSeqMapping } from 'g2p_mapper'
7
7
  import { autorun } from 'mobx'
8
8
  import { MSAModelF } from 'react-msaview'
9
9
 
10
- import { doLaunchBlast } from './doLaunchBlast'
10
+ import {
11
+ autoConnectStructures,
12
+ highlightConnectedStructures,
13
+ launchBlastIfNeeded,
14
+ loadStoredData,
15
+ observeProteinHighlights,
16
+ processInit,
17
+ runCleanup,
18
+ storeDataToIndexedDB,
19
+ updateGenomeHighlights,
20
+ } from './afterCreateAutoruns'
11
21
  import { genomeToMSA } from './genomeToMSA'
12
22
  import { msaCoordToGenomeCoord } from './msaCoordToGenomeCoord'
13
- import {
14
- cleanupOldData,
15
- generateDataStoreId,
16
- retrieveMsaData,
17
- storeMsaData,
18
- } from './msaDataStore'
19
23
  import { buildAlignmentMaps, runPairwiseAlignment } from './pairwiseAlignment'
20
- import {
21
- gappedToUngappedPosition,
22
- mapToRecord,
23
- ungappedToGappedPosition,
24
- } from './structureConnection'
25
- import { getUniprotIdFromAlphaFoldUrl } from './util'
24
+ import { mapToRecord, ungappedToGappedPosition } from './structureConnection'
26
25
 
27
26
  import type { StructureConnection } from './structureConnection'
28
27
  import type { MafRegion, MsaViewInitState } from './types'
@@ -38,49 +37,6 @@ type LGV = LinearGenomeViewModel
38
37
 
39
38
  type MaybeLGV = LGV | undefined
40
39
 
41
- /**
42
- * Highlights residues in connected protein structures based on current MSA hover position
43
- */
44
- function highlightConnectedStructures(self: JBrowsePluginMsaViewModel) {
45
- const { mouseCol, connectedProteinViews } = self
46
- if (connectedProteinViews.length === 0) {
47
- return
48
- }
49
-
50
- for (const conn of connectedProteinViews) {
51
- const structure = conn.proteinView?.structures?.[conn.structureIdx]
52
- if (!structure) {
53
- continue
54
- }
55
-
56
- // Clear highlight if mouse left MSA
57
- if (mouseCol === undefined) {
58
- structure.clearHighlightFromExternal?.()
59
- continue
60
- }
61
-
62
- const seq = self.getSequenceByRowName(conn.msaRowName)
63
- if (!seq) {
64
- continue
65
- }
66
-
67
- // Convert gapped MSA column to ungapped position
68
- const msaUngapped = gappedToUngappedPosition(seq, mouseCol)
69
- if (msaUngapped === undefined) {
70
- structure.clearHighlightFromExternal?.()
71
- continue
72
- }
73
-
74
- // Map to structure position and highlight
75
- const structurePos = conn.msaToStructure[msaUngapped]
76
- if (structurePos === undefined) {
77
- structure.clearHighlightFromExternal?.()
78
- } else {
79
- structure.highlightFromExternal?.(structurePos)
80
- }
81
- }
82
- }
83
-
84
40
  export interface IRegion {
85
41
  refName: string
86
42
  start: number
@@ -137,7 +93,6 @@ export default function stateModelFactory() {
137
93
 
138
94
  /**
139
95
  * #property
140
- * UniProt ID extracted from AlphaFold MSA URL
141
96
  */
142
97
  uniprotId: types.maybe(types.string),
143
98
 
@@ -148,33 +103,21 @@ export default function stateModelFactory() {
148
103
 
149
104
  /**
150
105
  * #property
151
- * used for loading the MSA view via session snapshots, e.g.
152
- * {
153
- * "type": "MsaView",
154
- * "init": {
155
- * "msaUrl": "https://example.com/alignment.fa",
156
- * "treeUrl": "https://example.com/tree.nh",
157
- * "querySeqName": "ENST00000123_hg38"
158
- * }
159
- * }
160
106
  */
161
107
  init: types.frozen<MsaViewInitState | undefined>(),
162
108
 
163
109
  /**
164
110
  * #property
165
- * connections to protein 3D structure views for synchronized highlighting
166
111
  */
167
112
  connectedStructures: types.array(types.frozen<StructureConnection>()),
168
113
 
169
114
  /**
170
115
  * #property
171
- * Reference ID for MSA data stored in IndexedDB (for large datasets)
172
116
  */
173
117
  dataStoreId: types.maybe(types.string),
174
118
 
175
119
  /**
176
120
  * #property
177
- * MAF region for coordinate mapping (used when launched from MAF viewer)
178
121
  */
179
122
  mafRegion: types.frozen<MafRegion | undefined>(),
180
123
  }),
@@ -195,7 +138,6 @@ export default function stateModelFactory() {
195
138
  error: undefined as unknown,
196
139
  /**
197
140
  * #volatile
198
- * True when loading MSA data from IndexedDB
199
141
  */
200
142
  loadingStoredData: false,
201
143
  }))
@@ -203,7 +145,6 @@ export default function stateModelFactory() {
203
145
  .views(self => ({
204
146
  /**
205
147
  * #method
206
- * Get a row by name, returns [name, sequence] or undefined
207
148
  */
208
149
  getRowByName(rowName: string) {
209
150
  return self.rows.find(r => r[0] === rowName)
@@ -211,7 +152,6 @@ export default function stateModelFactory() {
211
152
 
212
153
  /**
213
154
  * #method
214
- * Get the sequence for a row by name
215
155
  */
216
156
  getSequenceByRowName(rowName: string) {
217
157
  return self.rows.find(r => r[0] === rowName)?.[1]
@@ -245,7 +185,6 @@ export default function stateModelFactory() {
245
185
 
246
186
  /**
247
187
  * #getter
248
- * Get connected protein views with their full model references
249
188
  */
250
189
  get connectedProteinViews() {
251
190
  const { views } = getSession(self)
@@ -263,8 +202,6 @@ export default function stateModelFactory() {
263
202
  .views(self => ({
264
203
  /**
265
204
  * #getter
266
- * Get the MSA column that corresponds to the currently hovered structure position
267
- * Returns the first match from any connected structure
268
205
  */
269
206
  get structureHoverCol(): number | undefined {
270
207
  for (const conn of self.connectedProteinViews) {
@@ -275,7 +212,6 @@ export default function stateModelFactory() {
275
212
  if (msaUngapped !== undefined) {
276
213
  const seq = self.getSequenceByRowName(conn.msaRowName)
277
214
  if (seq) {
278
- // Convert ungapped position to global column, then to visible column
279
215
  const globalCol = ungappedToGappedPosition(seq, msaUngapped)
280
216
  if (globalCol !== undefined) {
281
217
  return self.globalColToVisibleCol(globalCol)
@@ -291,17 +227,12 @@ export default function stateModelFactory() {
291
227
  .views(self => ({
292
228
  /**
293
229
  * #getter
294
- * Returns a secondary highlight column from either:
295
- * 1. Structure hover (from connected protein 3D view)
296
- * 2. Genome hover (from connected linear genome view)
297
230
  */
298
231
  get mouseCol2(): number | undefined {
299
- // Check structure hover first
300
232
  const structureCol = self.structureHoverCol
301
233
  if (structureCol !== undefined) {
302
234
  return structureCol
303
235
  }
304
- // Fall back to genome hover
305
236
  return genomeToMSA({ model: self as JBrowsePluginMsaViewModel })
306
237
  },
307
238
  /**
@@ -422,7 +353,6 @@ export default function stateModelFactory() {
422
353
 
423
354
  /**
424
355
  * #action
425
- * Connect to a protein structure for synchronized highlighting
426
356
  */
427
357
  connectToStructure(
428
358
  proteinViewId: string,
@@ -475,7 +405,6 @@ export default function stateModelFactory() {
475
405
 
476
406
  /**
477
407
  * #action
478
- * Disconnect from a protein structure
479
408
  */
480
409
  disconnectFromStructure(proteinViewId: string, structureIdx: number) {
481
410
  const idx = self.connectedStructures.findIndex(
@@ -490,20 +419,17 @@ export default function stateModelFactory() {
490
419
 
491
420
  /**
492
421
  * #action
493
- * Disconnect from all protein structures
494
422
  */
495
423
  disconnectAllStructures() {
496
424
  self.connectedStructures.clear()
497
425
  },
498
426
  }))
499
427
  .actions(self => {
500
- // store reference to the original action from react-msaview
501
428
  const superSetMouseClickPos = self.setMouseClickPos.bind(self)
502
429
 
503
430
  return {
504
431
  /**
505
432
  * #action
506
- * overrides base setMouseClickPos to trigger navigation
507
433
  */
508
434
  setMouseClickPos(col?: number, row?: number) {
509
435
  superSetMouseClickPos(col, row)
@@ -517,7 +443,6 @@ export default function stateModelFactory() {
517
443
  .views(self => ({
518
444
  /**
519
445
  * #method
520
- * overrides base
521
446
  */
522
447
  extraViewMenuItems() {
523
448
  return [
@@ -557,311 +482,24 @@ export default function stateModelFactory() {
557
482
 
558
483
  .actions(self => ({
559
484
  afterCreate() {
560
- // Clean up old IndexedDB entries on startup
561
- cleanupOldData().catch((e: unknown) => {
562
- console.error('Failed to cleanup old MSA data:', e)
563
- })
564
-
565
- // Load MSA data from IndexedDB if dataStoreId exists and no data loaded
566
- addDisposer(
567
- self,
568
- autorun(async () => {
569
- const { dataStoreId, rows } = self
570
- if (dataStoreId && rows.length === 0) {
571
- try {
572
- self.setLoadingStoredData(true)
573
- const storedData = await retrieveMsaData(dataStoreId)
574
- if (storedData) {
575
- if (storedData.msa) {
576
- self.setMSA(storedData.msa)
577
- }
578
- if (storedData.tree) {
579
- self.setTree(storedData.tree)
580
- }
581
- }
582
- } catch (e) {
583
- console.error('Failed to load MSA data from IndexedDB:', e)
584
- } finally {
585
- self.setLoadingStoredData(false)
586
- }
587
- }
588
- }),
589
- )
590
-
591
- // Store MSA data to IndexedDB when loaded from inline data (no filehandle)
592
- // This ensures data persists across page refreshes even when
593
- // react-msaview's postProcessSnapshot would strip it
594
- addDisposer(
595
- self,
596
- autorun(async () => {
597
- const { rows, dataStoreId } = self
598
- // Only store if we have data and don't already have a dataStoreId
599
- if (rows.length > 0 && !dataStoreId) {
600
- // Only store if there's no filehandle (filehandles can reload from source)
601
- const hasFilehandle = !!(
602
- self.msaFilehandle ?? self.treeFilehandle
603
- )
604
- if (hasFilehandle) {
605
- return
606
- }
607
-
608
- const msaData = self.data.msa
609
- const treeData = self.data.tree
610
-
611
- // Only store if we have actual data
612
- if (msaData || treeData) {
613
- try {
614
- const newId = generateDataStoreId()
615
- const success = await storeMsaData(newId, {
616
- msa: msaData,
617
- tree: treeData,
618
- treeMetadata: self.data.treeMetadata,
619
- })
620
- // Only set dataStoreId if storage was successful
621
- if (success) {
622
- self.setDataStoreId(newId)
623
- }
624
- } catch (e) {
625
- console.error('Failed to store MSA data to IndexedDB:', e)
626
- }
627
- }
628
- }
629
- }),
630
- )
631
-
632
- addDisposer(
633
- self,
634
- autorun(async () => {
635
- if (self.blastParams) {
636
- try {
637
- self.setProgress('Submitting query')
638
- self.setError(undefined)
639
- const data = await doLaunchBlast({
640
- self,
641
- })
642
- self.setData(data)
643
- self.setBlastParams(undefined)
644
- } catch (e) {
645
- self.setError(e)
646
- console.error(e)
647
- } finally {
648
- self.setProgress('')
649
- }
650
- }
651
- }),
652
- )
653
-
654
- // process init parameter for loading MSA from session snapshots
655
- addDisposer(
656
- self,
657
- autorun(async () => {
658
- const { init } = self
659
- if (init) {
660
- try {
661
- self.setError(undefined)
662
- const { msaData, msaUrl, treeData, treeUrl, querySeqName } =
663
- init
664
-
665
- // Extract uniprotId from AlphaFold MSA URL and set querySeqName
666
- if (msaUrl) {
667
- const id = getUniprotIdFromAlphaFoldUrl(msaUrl)
668
- if (id) {
669
- self.setUniprotId(id)
670
- // AlphaFold MSA files use 'query' as the row name
671
- self.setQuerySeqName('query')
672
- }
673
- }
674
-
675
- // User-provided querySeqName takes precedence
676
- if (querySeqName) {
677
- self.setQuerySeqName(querySeqName)
678
- }
679
-
680
- if (msaData) {
681
- self.setMSA(msaData)
682
- } else if (msaUrl) {
683
- const response = await fetch(msaUrl)
684
- if (!response.ok) {
685
- throw new Error(`Failed to fetch MSA: ${response.status}`)
686
- }
687
- const data = await response.text()
688
- self.setMSA(data)
689
- }
690
-
691
- if (treeData) {
692
- self.setTree(treeData)
693
- } else if (treeUrl) {
694
- const response = await fetch(treeUrl)
695
- if (!response.ok) {
696
- throw new Error(`Failed to fetch tree: ${response.status}`)
697
- }
698
- const data = await response.text()
699
- self.setTree(data)
700
- }
701
-
702
- self.setInit(undefined)
703
- } catch (e) {
704
- self.setError(e)
705
- console.error(e)
706
- }
707
- }
708
- }),
709
- )
710
-
711
- // this adds highlights to the genome view when mouse-ing over the MSA
712
- addDisposer(
713
- self,
714
- autorun(() => {
715
- const { mouseCol, mouseClickCol } = self
716
- const r1 =
717
- mouseCol === undefined
718
- ? undefined
719
- : msaCoordToGenomeCoord({ model: self, coord: mouseCol })
720
- const r2 =
721
- mouseClickCol === undefined
722
- ? undefined
723
- : msaCoordToGenomeCoord({ model: self, coord: mouseClickCol })
724
-
725
- self.setConnectedHighlights([r1, r2].filter(f => !!f))
726
- }),
727
- )
728
-
729
- // this highlights residues in connected protein structures when mousing over the MSA
730
- addDisposer(
731
- self,
732
- autorun(() => {
733
- highlightConnectedStructures(self)
734
- }),
735
- )
736
-
737
- // auto-connect to compatible ProteinViews
738
- addDisposer(
739
- self,
740
- autorun(() => {
741
- const { views } = getSession(self)
742
- const { connectedViewId, uniprotId, rows, connectedStructures } =
743
- self
744
-
745
- // Need MSA loaded and a uniprotId to auto-connect
746
- if (!uniprotId || rows.length === 0) {
747
- return
748
- }
749
-
750
- // Find ProteinViews that share the same connectedViewId
751
- for (const view of views) {
752
- const v = view as any
753
- if (v.type !== 'ProteinView' || !v.structures) {
754
- continue
755
- }
756
-
757
- for (
758
- let structureIdx = 0;
759
- structureIdx < v.structures.length;
760
- structureIdx++
761
- ) {
762
- const structure = v.structures[structureIdx]
763
-
764
- // Check if structure shares the same genome view connection
765
- if (structure.connectedViewId !== connectedViewId) {
766
- continue
767
- }
768
-
769
- // Check if structure has matching uniprotId
770
- if (structure.uniprotId !== uniprotId) {
771
- continue
772
- }
773
-
774
- // Check if already connected
775
- const alreadyConnected = connectedStructures.some(
776
- c =>
777
- c.proteinViewId === v.id && c.structureIdx === structureIdx,
778
- )
779
- if (alreadyConnected) {
780
- continue
781
- }
782
-
783
- // Check if structure sequence is available
784
- if (!structure.structureSequences?.[0]) {
785
- continue
786
- }
787
-
788
- // Auto-connect
789
- try {
790
- self.connectToStructure(v.id, structureIdx)
791
- } catch (e) {
792
- console.error('Failed to auto-connect to ProteinView:', e)
793
- }
794
- }
795
- }
796
- }),
797
- )
798
-
799
- // Observe protein3d genome highlights and update MSA highlighted columns
800
- // This enables communication via the linear genome view coordinates
801
- addDisposer(
802
- self,
803
- autorun(() => {
804
- const { views } = getSession(self)
805
- const { connectedViewId, transcriptToMsaMap, querySeqName } = self
806
-
807
- if (!connectedViewId || !transcriptToMsaMap) {
808
- return
809
- }
810
-
811
- const columns: number[] = []
812
-
813
- // Find ProteinViews that share the same connected genome view
814
- for (const view of views) {
815
- const v = view as any
816
- if (v.type !== 'ProteinView' || !v.structures) {
817
- continue
818
- }
819
-
820
- for (const structure of v.structures) {
821
- // Check if structure is connected to same genome view
822
- if (structure.connectedViewId !== connectedViewId) {
823
- continue
824
- }
825
-
826
- // Check if structure has hover genome highlights
827
- const highlights = structure.hoverGenomeHighlights
828
- if (!highlights || highlights.length === 0) {
829
- continue
830
- }
831
-
832
- // Map genome coordinates to MSA columns
833
- const { g2p } = transcriptToMsaMap
834
- for (const highlight of highlights) {
835
- for (
836
- let coord = highlight.start;
837
- coord < highlight.end;
838
- coord++
839
- ) {
840
- const proteinPos = g2p[coord]
841
- if (proteinPos !== undefined) {
842
- const col = self.seqPosToGlobalCol(
843
- querySeqName,
844
- proteinPos,
845
- )
846
- if (!columns.includes(col)) {
847
- columns.push(col)
848
- }
849
- }
850
- }
851
- }
852
- }
853
- }
854
-
855
- // Convert global column indices to visible column indices
856
- const visibleColumns = columns
857
- .map(col => self.globalColToVisibleCol(col))
858
- .filter((col): col is number => col !== undefined)
859
-
860
- self.setHighlightedColumns(
861
- visibleColumns.length > 0 ? visibleColumns : undefined,
862
- )
863
- }),
864
- )
485
+ runCleanup()
486
+ for (const fn of [
487
+ loadStoredData,
488
+ storeDataToIndexedDB,
489
+ launchBlastIfNeeded,
490
+ processInit,
491
+ updateGenomeHighlights,
492
+ highlightConnectedStructures,
493
+ autoConnectStructures,
494
+ observeProteinHighlights,
495
+ ]) {
496
+ addDisposer(
497
+ self,
498
+ autorun(() => {
499
+ fn(self)
500
+ }),
501
+ )
502
+ }
865
503
  },
866
504
  }))
867
505
  }