jbrowse-plugin-msaview 2.2.3 → 2.2.5

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 (162) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +229 -0
  3. package/dist/AddHighlightModel/GenomeMouseoverHighlight.js +23 -18
  4. package/dist/AddHighlightModel/GenomeMouseoverHighlight.js.map +1 -1
  5. package/dist/AddHighlightModel/MsaToGenomeHighlight.js +23 -13
  6. package/dist/AddHighlightModel/MsaToGenomeHighlight.js.map +1 -1
  7. package/dist/AddHighlightModel/index.js +8 -1
  8. package/dist/AddHighlightModel/index.js.map +1 -1
  9. package/dist/AddHighlightModel/util.d.ts +2 -2
  10. package/dist/BgzipFastaMsaAdapter/configSchema.d.ts +2 -2
  11. package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js +5 -11
  12. package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js.map +1 -1
  13. package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.js +5 -1
  14. package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.js.map +1 -1
  15. package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js +16 -16
  16. package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js.map +1 -1
  17. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +38 -46
  18. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js.map +1 -1
  19. package/dist/LaunchMsaView/components/ManualMSALoader/launchView.d.ts +4 -3
  20. package/dist/LaunchMsaView/components/ManualMSALoader/launchView.js +4 -3
  21. package/dist/LaunchMsaView/components/ManualMSALoader/launchView.js.map +1 -1
  22. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.d.ts +9 -0
  23. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js +76 -0
  24. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js.map +1 -0
  25. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js +35 -13
  26. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js.map +1 -1
  27. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js +6 -12
  28. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js.map +1 -1
  29. package/dist/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.d.ts +6 -0
  30. package/dist/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.js +15 -0
  31. package/dist/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.js.map +1 -1
  32. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +12 -34
  33. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js.map +1 -1
  34. package/dist/LaunchMsaView/components/PreLoadedMSA/consts.d.ts +1 -0
  35. package/dist/LaunchMsaView/components/PreLoadedMSA/consts.js +1 -0
  36. package/dist/LaunchMsaView/components/PreLoadedMSA/consts.js.map +1 -1
  37. package/dist/LaunchMsaView/components/TabPanel.d.ts +2 -2
  38. package/dist/LaunchMsaView/components/TranscriptSelector.d.ts +2 -2
  39. package/dist/LaunchMsaView/components/TranscriptSelector.js +3 -6
  40. package/dist/LaunchMsaView/components/TranscriptSelector.js.map +1 -1
  41. package/dist/LaunchMsaView/components/useSWRFeatureSequence.js +6 -4
  42. package/dist/LaunchMsaView/components/useSWRFeatureSequence.js.map +1 -1
  43. package/dist/LaunchMsaView/components/useTranscriptSelection.d.ts +16 -0
  44. package/dist/LaunchMsaView/components/useTranscriptSelection.js +31 -0
  45. package/dist/LaunchMsaView/components/useTranscriptSelection.js.map +1 -0
  46. package/dist/LaunchMsaView/components/util.d.ts +3 -1
  47. package/dist/LaunchMsaView/components/util.js +12 -2
  48. package/dist/LaunchMsaView/components/util.js.map +1 -1
  49. package/dist/LaunchMsaView/util.d.ts +2 -0
  50. package/dist/LaunchMsaView/util.js +16 -4
  51. package/dist/LaunchMsaView/util.js.map +1 -1
  52. package/dist/LaunchMsaViewExtensionPoint/index.d.ts +2 -0
  53. package/dist/LaunchMsaViewExtensionPoint/index.js +31 -0
  54. package/dist/LaunchMsaViewExtensionPoint/index.js.map +1 -0
  55. package/dist/MsaViewPanel/components/ConnectStructureDialog.d.ts +7 -0
  56. package/dist/MsaViewPanel/components/ConnectStructureDialog.js +56 -0
  57. package/dist/MsaViewPanel/components/ConnectStructureDialog.js.map +1 -0
  58. package/dist/MsaViewPanel/components/MsaViewPanel.js +4 -2
  59. package/dist/MsaViewPanel/components/MsaViewPanel.js.map +1 -1
  60. package/dist/MsaViewPanel/doLaunchBlast.d.ts +1 -0
  61. package/dist/MsaViewPanel/doLaunchBlast.js +65 -19
  62. package/dist/MsaViewPanel/doLaunchBlast.js.map +1 -1
  63. package/dist/MsaViewPanel/genomeToMSA.d.ts +6 -0
  64. package/dist/MsaViewPanel/genomeToMSA.js +38 -8
  65. package/dist/MsaViewPanel/genomeToMSA.js.map +1 -1
  66. package/dist/MsaViewPanel/genomeToMSA.test.d.ts +1 -0
  67. package/dist/MsaViewPanel/genomeToMSA.test.js +244 -0
  68. package/dist/MsaViewPanel/genomeToMSA.test.js.map +1 -0
  69. package/dist/MsaViewPanel/model.d.ts +719 -226
  70. package/dist/MsaViewPanel/model.js +467 -39
  71. package/dist/MsaViewPanel/model.js.map +1 -1
  72. package/dist/MsaViewPanel/msaCoordToGenomeCoord.d.ts +7 -2
  73. package/dist/MsaViewPanel/msaCoordToGenomeCoord.js +26 -27
  74. package/dist/MsaViewPanel/msaCoordToGenomeCoord.js.map +1 -1
  75. package/dist/MsaViewPanel/msaCoordToGenomeCoord.test.d.ts +1 -0
  76. package/dist/MsaViewPanel/msaCoordToGenomeCoord.test.js +240 -0
  77. package/dist/MsaViewPanel/msaCoordToGenomeCoord.test.js.map +1 -0
  78. package/dist/MsaViewPanel/msaDataStore.d.ts +14 -0
  79. package/dist/MsaViewPanel/msaDataStore.js +197 -0
  80. package/dist/MsaViewPanel/msaDataStore.js.map +1 -0
  81. package/dist/MsaViewPanel/pairwiseAlignment.d.ts +27 -0
  82. package/dist/MsaViewPanel/pairwiseAlignment.js +776 -0
  83. package/dist/MsaViewPanel/pairwiseAlignment.js.map +1 -0
  84. package/dist/MsaViewPanel/pairwiseAlignment.test.d.ts +1 -0
  85. package/dist/MsaViewPanel/pairwiseAlignment.test.js +112 -0
  86. package/dist/MsaViewPanel/pairwiseAlignment.test.js.map +1 -0
  87. package/dist/MsaViewPanel/structureConnection.d.ts +27 -0
  88. package/dist/MsaViewPanel/structureConnection.js +46 -0
  89. package/dist/MsaViewPanel/structureConnection.js.map +1 -0
  90. package/dist/MsaViewPanel/structureConnection.test.d.ts +1 -0
  91. package/dist/MsaViewPanel/structureConnection.test.js +122 -0
  92. package/dist/MsaViewPanel/structureConnection.test.js.map +1 -0
  93. package/dist/MsaViewPanel/types.d.ts +13 -0
  94. package/dist/MsaViewPanel/types.js +2 -0
  95. package/dist/MsaViewPanel/types.js.map +1 -0
  96. package/dist/MsaViewPanel/util.d.ts +7 -0
  97. package/dist/MsaViewPanel/util.js +10 -0
  98. package/dist/MsaViewPanel/util.js.map +1 -1
  99. package/dist/index.d.ts +5 -5
  100. package/dist/index.js +3 -1
  101. package/dist/index.js.map +1 -1
  102. package/dist/jbrowse-plugin-msaview.umd.production.min.js +39 -90
  103. package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
  104. package/dist/utils/blastCache.d.ts +34 -0
  105. package/dist/utils/blastCache.js +58 -0
  106. package/dist/utils/blastCache.js.map +1 -0
  107. package/dist/utils/fetch.d.ts +1 -1
  108. package/dist/utils/fetch.js +1 -1
  109. package/dist/utils/fetch.js.map +1 -1
  110. package/dist/utils/ncbiBlast.d.ts +1 -5
  111. package/dist/utils/taxonomyNames.d.ts +5 -0
  112. package/dist/utils/taxonomyNames.js +79 -0
  113. package/dist/utils/taxonomyNames.js.map +1 -0
  114. package/dist/utils/types.d.ts +8 -5
  115. package/package.json +50 -54
  116. package/src/AddHighlightModel/GenomeMouseoverHighlight.tsx +37 -21
  117. package/src/AddHighlightModel/MsaToGenomeHighlight.tsx +38 -17
  118. package/src/AddHighlightModel/index.tsx +9 -4
  119. package/src/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.tsx +13 -13
  120. package/src/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.ts +6 -0
  121. package/src/LaunchMsaView/components/LaunchMsaViewDialog.tsx +30 -23
  122. package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +64 -51
  123. package/src/LaunchMsaView/components/ManualMSALoader/launchView.ts +9 -6
  124. package/src/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.tsx +146 -0
  125. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.tsx +53 -22
  126. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.tsx +8 -13
  127. package/src/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.ts +25 -0
  128. package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +27 -47
  129. package/src/LaunchMsaView/components/PreLoadedMSA/consts.ts +1 -0
  130. package/src/LaunchMsaView/components/TabPanel.tsx +2 -2
  131. package/src/LaunchMsaView/components/TranscriptSelector.tsx +13 -20
  132. package/src/LaunchMsaView/components/useSWRFeatureSequence.ts +5 -5
  133. package/src/LaunchMsaView/components/useTranscriptSelection.ts +48 -0
  134. package/src/LaunchMsaView/components/util.ts +17 -2
  135. package/src/LaunchMsaView/index.ts +1 -1
  136. package/src/LaunchMsaView/util.ts +25 -6
  137. package/src/LaunchMsaViewExtensionPoint/index.ts +74 -0
  138. package/src/MsaViewPanel/components/ConnectStructureDialog.tsx +156 -0
  139. package/src/MsaViewPanel/components/MsaViewPanel.tsx +6 -1
  140. package/src/MsaViewPanel/doLaunchBlast.ts +83 -23
  141. package/src/MsaViewPanel/genomeToMSA.test.ts +281 -0
  142. package/src/MsaViewPanel/genomeToMSA.ts +43 -10
  143. package/src/MsaViewPanel/model.ts +590 -43
  144. package/src/MsaViewPanel/msaCoordToGenomeCoord.test.ts +256 -0
  145. package/src/MsaViewPanel/msaCoordToGenomeCoord.ts +43 -29
  146. package/src/MsaViewPanel/msaDataStore.ts +236 -0
  147. package/src/MsaViewPanel/pairwiseAlignment.test.ts +140 -0
  148. package/src/MsaViewPanel/pairwiseAlignment.ts +818 -0
  149. package/src/MsaViewPanel/structureConnection.test.ts +143 -0
  150. package/src/MsaViewPanel/structureConnection.ts +72 -0
  151. package/src/MsaViewPanel/types.ts +14 -0
  152. package/src/MsaViewPanel/util.ts +11 -0
  153. package/src/index.ts +3 -1
  154. package/src/utils/blastCache.ts +114 -0
  155. package/src/utils/fetch.ts +1 -1
  156. package/src/utils/taxonomyNames.ts +111 -0
  157. package/src/utils/types.ts +9 -1
  158. package/dist/LaunchMsaView/components/PreLoadedMSA/findValidTranscriptId.d.ts +0 -5
  159. package/dist/LaunchMsaView/components/PreLoadedMSA/findValidTranscriptId.js +0 -16
  160. package/dist/LaunchMsaView/components/PreLoadedMSA/findValidTranscriptId.js.map +0 -1
  161. package/dist/out.js +0 -55381
  162. package/src/LaunchMsaView/components/PreLoadedMSA/findValidTranscriptId.ts +0 -25
@@ -0,0 +1,818 @@
1
+ // Pairwise alignment utilities for MSA-to-structure mapping
2
+ // Based on code from jbrowse-plugin-protein3d
3
+
4
+ // BLOSUM62 scoring matrix for protein sequence alignment
5
+ const BLOSUM62: Record<string, Record<string, number>> = {
6
+ A: {
7
+ A: 4,
8
+ R: -1,
9
+ N: -2,
10
+ D: -2,
11
+ C: 0,
12
+ Q: -1,
13
+ E: -1,
14
+ G: 0,
15
+ H: -2,
16
+ I: -1,
17
+ L: -1,
18
+ K: -1,
19
+ M: -1,
20
+ F: -2,
21
+ P: -1,
22
+ S: 1,
23
+ T: 0,
24
+ W: -3,
25
+ Y: -2,
26
+ V: 0,
27
+ B: -2,
28
+ Z: -1,
29
+ X: 0,
30
+ '*': -4,
31
+ },
32
+ R: {
33
+ A: -1,
34
+ R: 5,
35
+ N: 0,
36
+ D: -2,
37
+ C: -3,
38
+ Q: 1,
39
+ E: 0,
40
+ G: -2,
41
+ H: 0,
42
+ I: -3,
43
+ L: -2,
44
+ K: 2,
45
+ M: -1,
46
+ F: -3,
47
+ P: -2,
48
+ S: -1,
49
+ T: -1,
50
+ W: -3,
51
+ Y: -2,
52
+ V: -3,
53
+ B: -1,
54
+ Z: 0,
55
+ X: -1,
56
+ '*': -4,
57
+ },
58
+ N: {
59
+ A: -2,
60
+ R: 0,
61
+ N: 6,
62
+ D: 1,
63
+ C: -3,
64
+ Q: 0,
65
+ E: 0,
66
+ G: 0,
67
+ H: 1,
68
+ I: -3,
69
+ L: -3,
70
+ K: 0,
71
+ M: -2,
72
+ F: -3,
73
+ P: -2,
74
+ S: 1,
75
+ T: 0,
76
+ W: -4,
77
+ Y: -2,
78
+ V: -3,
79
+ B: 3,
80
+ Z: 0,
81
+ X: -1,
82
+ '*': -4,
83
+ },
84
+ D: {
85
+ A: -2,
86
+ R: -2,
87
+ N: 1,
88
+ D: 6,
89
+ C: -3,
90
+ Q: 0,
91
+ E: 2,
92
+ G: -1,
93
+ H: -1,
94
+ I: -3,
95
+ L: -4,
96
+ K: -1,
97
+ M: -3,
98
+ F: -3,
99
+ P: -1,
100
+ S: 0,
101
+ T: -1,
102
+ W: -4,
103
+ Y: -3,
104
+ V: -3,
105
+ B: 4,
106
+ Z: 1,
107
+ X: -1,
108
+ '*': -4,
109
+ },
110
+ C: {
111
+ A: 0,
112
+ R: -3,
113
+ N: -3,
114
+ D: -3,
115
+ C: 9,
116
+ Q: -3,
117
+ E: -4,
118
+ G: -3,
119
+ H: -3,
120
+ I: -1,
121
+ L: -1,
122
+ K: -3,
123
+ M: -1,
124
+ F: -2,
125
+ P: -3,
126
+ S: -1,
127
+ T: -1,
128
+ W: -2,
129
+ Y: -2,
130
+ V: -1,
131
+ B: -3,
132
+ Z: -3,
133
+ X: -2,
134
+ '*': -4,
135
+ },
136
+ Q: {
137
+ A: -1,
138
+ R: 1,
139
+ N: 0,
140
+ D: 0,
141
+ C: -3,
142
+ Q: 5,
143
+ E: 2,
144
+ G: -2,
145
+ H: 0,
146
+ I: -3,
147
+ L: -2,
148
+ K: 1,
149
+ M: 0,
150
+ F: -3,
151
+ P: -1,
152
+ S: 0,
153
+ T: -1,
154
+ W: -2,
155
+ Y: -1,
156
+ V: -2,
157
+ B: 0,
158
+ Z: 3,
159
+ X: -1,
160
+ '*': -4,
161
+ },
162
+ E: {
163
+ A: -1,
164
+ R: 0,
165
+ N: 0,
166
+ D: 2,
167
+ C: -4,
168
+ Q: 2,
169
+ E: 5,
170
+ G: -2,
171
+ H: 0,
172
+ I: -3,
173
+ L: -3,
174
+ K: 1,
175
+ M: -2,
176
+ F: -3,
177
+ P: -1,
178
+ S: 0,
179
+ T: -1,
180
+ W: -3,
181
+ Y: -2,
182
+ V: -2,
183
+ B: 1,
184
+ Z: 4,
185
+ X: -1,
186
+ '*': -4,
187
+ },
188
+ G: {
189
+ A: 0,
190
+ R: -2,
191
+ N: 0,
192
+ D: -1,
193
+ C: -3,
194
+ Q: -2,
195
+ E: -2,
196
+ G: 6,
197
+ H: -2,
198
+ I: -4,
199
+ L: -4,
200
+ K: -2,
201
+ M: -3,
202
+ F: -3,
203
+ P: -2,
204
+ S: 0,
205
+ T: -2,
206
+ W: -2,
207
+ Y: -3,
208
+ V: -3,
209
+ B: -1,
210
+ Z: -2,
211
+ X: -1,
212
+ '*': -4,
213
+ },
214
+ H: {
215
+ A: -2,
216
+ R: 0,
217
+ N: 1,
218
+ D: -1,
219
+ C: -3,
220
+ Q: 0,
221
+ E: 0,
222
+ G: -2,
223
+ H: 8,
224
+ I: -3,
225
+ L: -3,
226
+ K: -1,
227
+ M: -2,
228
+ F: -1,
229
+ P: -2,
230
+ S: -1,
231
+ T: -2,
232
+ W: -2,
233
+ Y: 2,
234
+ V: -3,
235
+ B: 0,
236
+ Z: 0,
237
+ X: -1,
238
+ '*': -4,
239
+ },
240
+ I: {
241
+ A: -1,
242
+ R: -3,
243
+ N: -3,
244
+ D: -3,
245
+ C: -1,
246
+ Q: -3,
247
+ E: -3,
248
+ G: -4,
249
+ H: -3,
250
+ I: 4,
251
+ L: 2,
252
+ K: -3,
253
+ M: 1,
254
+ F: 0,
255
+ P: -3,
256
+ S: -2,
257
+ T: -1,
258
+ W: -3,
259
+ Y: -1,
260
+ V: 3,
261
+ B: -3,
262
+ Z: -3,
263
+ X: -1,
264
+ '*': -4,
265
+ },
266
+ L: {
267
+ A: -1,
268
+ R: -2,
269
+ N: -3,
270
+ D: -4,
271
+ C: -1,
272
+ Q: -2,
273
+ E: -3,
274
+ G: -4,
275
+ H: -3,
276
+ I: 2,
277
+ L: 4,
278
+ K: -2,
279
+ M: 2,
280
+ F: 0,
281
+ P: -3,
282
+ S: -2,
283
+ T: -1,
284
+ W: -2,
285
+ Y: -1,
286
+ V: 1,
287
+ B: -4,
288
+ Z: -3,
289
+ X: -1,
290
+ '*': -4,
291
+ },
292
+ K: {
293
+ A: -1,
294
+ R: 2,
295
+ N: 0,
296
+ D: -1,
297
+ C: -3,
298
+ Q: 1,
299
+ E: 1,
300
+ G: -2,
301
+ H: -1,
302
+ I: -3,
303
+ L: -2,
304
+ K: 5,
305
+ M: -1,
306
+ F: -3,
307
+ P: -1,
308
+ S: 0,
309
+ T: -1,
310
+ W: -3,
311
+ Y: -2,
312
+ V: -2,
313
+ B: 0,
314
+ Z: 1,
315
+ X: -1,
316
+ '*': -4,
317
+ },
318
+ M: {
319
+ A: -1,
320
+ R: -1,
321
+ N: -2,
322
+ D: -3,
323
+ C: -1,
324
+ Q: 0,
325
+ E: -2,
326
+ G: -3,
327
+ H: -2,
328
+ I: 1,
329
+ L: 2,
330
+ K: -1,
331
+ M: 5,
332
+ F: 0,
333
+ P: -2,
334
+ S: -1,
335
+ T: -1,
336
+ W: -1,
337
+ Y: -1,
338
+ V: 1,
339
+ B: -3,
340
+ Z: -1,
341
+ X: -1,
342
+ '*': -4,
343
+ },
344
+ F: {
345
+ A: -2,
346
+ R: -3,
347
+ N: -3,
348
+ D: -3,
349
+ C: -2,
350
+ Q: -3,
351
+ E: -3,
352
+ G: -3,
353
+ H: -1,
354
+ I: 0,
355
+ L: 0,
356
+ K: -3,
357
+ M: 0,
358
+ F: 6,
359
+ P: -4,
360
+ S: -2,
361
+ T: -2,
362
+ W: 1,
363
+ Y: 3,
364
+ V: -1,
365
+ B: -3,
366
+ Z: -3,
367
+ X: -1,
368
+ '*': -4,
369
+ },
370
+ P: {
371
+ A: -1,
372
+ R: -2,
373
+ N: -2,
374
+ D: -1,
375
+ C: -3,
376
+ Q: -1,
377
+ E: -1,
378
+ G: -2,
379
+ H: -2,
380
+ I: -3,
381
+ L: -3,
382
+ K: -1,
383
+ M: -2,
384
+ F: -4,
385
+ P: 7,
386
+ S: -1,
387
+ T: -1,
388
+ W: -4,
389
+ Y: -3,
390
+ V: -2,
391
+ B: -2,
392
+ Z: -1,
393
+ X: -2,
394
+ '*': -4,
395
+ },
396
+ S: {
397
+ A: 1,
398
+ R: -1,
399
+ N: 1,
400
+ D: 0,
401
+ C: -1,
402
+ Q: 0,
403
+ E: 0,
404
+ G: 0,
405
+ H: -1,
406
+ I: -2,
407
+ L: -2,
408
+ K: 0,
409
+ M: -1,
410
+ F: -2,
411
+ P: -1,
412
+ S: 4,
413
+ T: 1,
414
+ W: -3,
415
+ Y: -2,
416
+ V: -2,
417
+ B: 0,
418
+ Z: 0,
419
+ X: 0,
420
+ '*': -4,
421
+ },
422
+ T: {
423
+ A: 0,
424
+ R: -1,
425
+ N: 0,
426
+ D: -1,
427
+ C: -1,
428
+ Q: -1,
429
+ E: -1,
430
+ G: -2,
431
+ H: -2,
432
+ I: -1,
433
+ L: -1,
434
+ K: -1,
435
+ M: -1,
436
+ F: -2,
437
+ P: -1,
438
+ S: 1,
439
+ T: 5,
440
+ W: -2,
441
+ Y: -2,
442
+ V: 0,
443
+ B: -1,
444
+ Z: -1,
445
+ X: 0,
446
+ '*': -4,
447
+ },
448
+ W: {
449
+ A: -3,
450
+ R: -3,
451
+ N: -4,
452
+ D: -4,
453
+ C: -2,
454
+ Q: -2,
455
+ E: -3,
456
+ G: -2,
457
+ H: -2,
458
+ I: -3,
459
+ L: -2,
460
+ K: -3,
461
+ M: -1,
462
+ F: 1,
463
+ P: -4,
464
+ S: -3,
465
+ T: -2,
466
+ W: 11,
467
+ Y: 2,
468
+ V: -3,
469
+ B: -4,
470
+ Z: -3,
471
+ X: -2,
472
+ '*': -4,
473
+ },
474
+ Y: {
475
+ A: -2,
476
+ R: -2,
477
+ N: -2,
478
+ D: -3,
479
+ C: -2,
480
+ Q: -1,
481
+ E: -2,
482
+ G: -3,
483
+ H: 2,
484
+ I: -1,
485
+ L: -1,
486
+ K: -2,
487
+ M: -1,
488
+ F: 3,
489
+ P: -3,
490
+ S: -2,
491
+ T: -2,
492
+ W: 2,
493
+ Y: 7,
494
+ V: -1,
495
+ B: -3,
496
+ Z: -2,
497
+ X: -1,
498
+ '*': -4,
499
+ },
500
+ V: {
501
+ A: 0,
502
+ R: -3,
503
+ N: -3,
504
+ D: -3,
505
+ C: -1,
506
+ Q: -2,
507
+ E: -2,
508
+ G: -3,
509
+ H: -3,
510
+ I: 3,
511
+ L: 1,
512
+ K: -2,
513
+ M: 1,
514
+ F: -1,
515
+ P: -2,
516
+ S: -2,
517
+ T: 0,
518
+ W: -3,
519
+ Y: -1,
520
+ V: 4,
521
+ B: -3,
522
+ Z: -2,
523
+ X: -1,
524
+ '*': -4,
525
+ },
526
+ B: {
527
+ A: -2,
528
+ R: -1,
529
+ N: 3,
530
+ D: 4,
531
+ C: -3,
532
+ Q: 0,
533
+ E: 1,
534
+ G: -1,
535
+ H: 0,
536
+ I: -3,
537
+ L: -4,
538
+ K: 0,
539
+ M: -3,
540
+ F: -3,
541
+ P: -2,
542
+ S: 0,
543
+ T: -1,
544
+ W: -4,
545
+ Y: -3,
546
+ V: -3,
547
+ B: 4,
548
+ Z: 1,
549
+ X: -1,
550
+ '*': -4,
551
+ },
552
+ Z: {
553
+ A: -1,
554
+ R: 0,
555
+ N: 0,
556
+ D: 1,
557
+ C: -3,
558
+ Q: 3,
559
+ E: 4,
560
+ G: -2,
561
+ H: 0,
562
+ I: -3,
563
+ L: -3,
564
+ K: 1,
565
+ M: -1,
566
+ F: -3,
567
+ P: -1,
568
+ S: 0,
569
+ T: -1,
570
+ W: -3,
571
+ Y: -2,
572
+ V: -2,
573
+ B: 1,
574
+ Z: 4,
575
+ X: -1,
576
+ '*': -4,
577
+ },
578
+ X: {
579
+ A: 0,
580
+ R: -1,
581
+ N: -1,
582
+ D: -1,
583
+ C: -2,
584
+ Q: -1,
585
+ E: -1,
586
+ G: -1,
587
+ H: -1,
588
+ I: -1,
589
+ L: -1,
590
+ K: -1,
591
+ M: -1,
592
+ F: -1,
593
+ P: -2,
594
+ S: 0,
595
+ T: 0,
596
+ W: -2,
597
+ Y: -1,
598
+ V: -1,
599
+ B: -1,
600
+ Z: -1,
601
+ X: -1,
602
+ '*': -4,
603
+ },
604
+ '*': {
605
+ A: -4,
606
+ R: -4,
607
+ N: -4,
608
+ D: -4,
609
+ C: -4,
610
+ Q: -4,
611
+ E: -4,
612
+ G: -4,
613
+ H: -4,
614
+ I: -4,
615
+ L: -4,
616
+ K: -4,
617
+ M: -4,
618
+ F: -4,
619
+ P: -4,
620
+ S: -4,
621
+ T: -4,
622
+ W: -4,
623
+ Y: -4,
624
+ V: -4,
625
+ B: -4,
626
+ Z: -4,
627
+ X: -4,
628
+ '*': 1,
629
+ },
630
+ }
631
+
632
+ function getScore(a: string, b: string) {
633
+ const upper_a = a.toUpperCase()
634
+ const upper_b = b.toUpperCase()
635
+ return BLOSUM62[upper_a]?.[upper_b] ?? -4
636
+ }
637
+
638
+ const GAP_OPEN = -10
639
+ const GAP_EXTEND = -0.5
640
+
641
+ interface AlignmentResult {
642
+ alignedSeq1: string
643
+ alignedSeq2: string
644
+ score: number
645
+ }
646
+
647
+ export interface AlignmentRow {
648
+ id: string
649
+ seq: string
650
+ }
651
+
652
+ export interface PairwiseAlignment {
653
+ consensus: string
654
+ alns: readonly [AlignmentRow, AlignmentRow]
655
+ }
656
+
657
+ /**
658
+ * Needleman-Wunsch global alignment algorithm
659
+ */
660
+ export function needlemanWunsch(
661
+ seq1: string,
662
+ seq2: string,
663
+ gapOpen = GAP_OPEN,
664
+ gapExtend = GAP_EXTEND,
665
+ ): AlignmentResult {
666
+ const m = seq1.length
667
+ const n = seq2.length
668
+
669
+ const M: number[][] = []
670
+ const Ix: number[][] = []
671
+ const Iy: number[][] = []
672
+
673
+ for (let i = 0; i <= m; i++) {
674
+ M[i] = []
675
+ Ix[i] = []
676
+ Iy[i] = []
677
+ for (let j = 0; j <= n; j++) {
678
+ M[i]![j] = -Infinity
679
+ Ix[i]![j] = -Infinity
680
+ Iy[i]![j] = -Infinity
681
+ }
682
+ }
683
+
684
+ M[0]![0] = 0
685
+ for (let i = 1; i <= m; i++) {
686
+ Ix[i]![0] = gapOpen + (i - 1) * gapExtend
687
+ }
688
+ for (let j = 1; j <= n; j++) {
689
+ Iy[0]![j] = gapOpen + (j - 1) * gapExtend
690
+ }
691
+
692
+ for (let i = 1; i <= m; i++) {
693
+ for (let j = 1; j <= n; j++) {
694
+ const matchScore = getScore(seq1[i - 1]!, seq2[j - 1]!)
695
+
696
+ M[i]![j] =
697
+ Math.max(M[i - 1]![j - 1]!, Ix[i - 1]![j - 1]!, Iy[i - 1]![j - 1]!) +
698
+ matchScore
699
+
700
+ Ix[i]![j] = Math.max(M[i - 1]![j]! + gapOpen, Ix[i - 1]![j]! + gapExtend)
701
+ Iy[i]![j] = Math.max(M[i]![j - 1]! + gapOpen, Iy[i]![j - 1]! + gapExtend)
702
+ }
703
+ }
704
+
705
+ let alignedSeq1 = ''
706
+ let alignedSeq2 = ''
707
+ let i = m
708
+ let j = n
709
+
710
+ const finalScores = [M[m]![n]!, Ix[m]![n]!, Iy[m]![n]!]
711
+ const score = Math.max(...finalScores)
712
+ let currentMatrix: 'M' | 'Ix' | 'Iy' =
713
+ score === M[m]![n]! ? 'M' : score === Ix[m]![n]! ? 'Ix' : 'Iy'
714
+
715
+ while (i > 0 || j > 0) {
716
+ if (currentMatrix === 'M' && i > 0 && j > 0) {
717
+ alignedSeq1 = seq1[i - 1] + alignedSeq1
718
+ alignedSeq2 = seq2[j - 1] + alignedSeq2
719
+
720
+ const matchScore = getScore(seq1[i - 1]!, seq2[j - 1]!)
721
+ const prevM = M[i - 1]![j - 1]!
722
+ const prevIx = Ix[i - 1]![j - 1]!
723
+
724
+ if (M[i]![j]! === prevM + matchScore) {
725
+ currentMatrix = 'M'
726
+ } else if (M[i]![j]! === prevIx + matchScore) {
727
+ currentMatrix = 'Ix'
728
+ } else {
729
+ currentMatrix = 'Iy'
730
+ }
731
+ i--
732
+ j--
733
+ } else if (currentMatrix === 'Ix' && i > 0) {
734
+ alignedSeq1 = seq1[i - 1] + alignedSeq1
735
+ alignedSeq2 = '-' + alignedSeq2
736
+
737
+ currentMatrix = Ix[i]![j]! === M[i - 1]![j]! + gapOpen ? 'M' : 'Ix'
738
+ i--
739
+ } else if (j > 0) {
740
+ alignedSeq1 = '-' + alignedSeq1
741
+ alignedSeq2 = seq2[j - 1] + alignedSeq2
742
+
743
+ currentMatrix = Iy[i]![j]! === M[i]![j - 1]! + gapOpen ? 'M' : 'Iy'
744
+ j--
745
+ } else {
746
+ break
747
+ }
748
+ }
749
+
750
+ return { alignedSeq1, alignedSeq2, score }
751
+ }
752
+
753
+ function buildConsensus(alignedSeq1: string, alignedSeq2: string) {
754
+ let consensus = ''
755
+ for (let i = 0; i < alignedSeq1.length; i++) {
756
+ const a = alignedSeq1[i]!
757
+ const b = alignedSeq2[i]!
758
+ if (a === '-' || b === '-') {
759
+ consensus += ' '
760
+ } else if (a.toUpperCase() === b.toUpperCase()) {
761
+ consensus += '|'
762
+ } else {
763
+ consensus += ' '
764
+ }
765
+ }
766
+ return consensus
767
+ }
768
+
769
+ export function runPairwiseAlignment(
770
+ seq1: string,
771
+ seq2: string,
772
+ ): PairwiseAlignment {
773
+ const { alignedSeq1, alignedSeq2 } = needlemanWunsch(seq1, seq2)
774
+
775
+ return {
776
+ consensus: buildConsensus(alignedSeq1, alignedSeq2),
777
+ alns: [
778
+ { id: 'msa', seq: alignedSeq1 },
779
+ { id: 'structure', seq: alignedSeq2 },
780
+ ],
781
+ }
782
+ }
783
+
784
+ /**
785
+ * Build coordinate mappings from a pairwise alignment
786
+ * Maps between ungapped positions in seq1 and seq2
787
+ */
788
+ export function buildAlignmentMaps(pairwiseAlignment: PairwiseAlignment) {
789
+ const seq1 = pairwiseAlignment.alns[0].seq
790
+ const seq2 = pairwiseAlignment.alns[1].seq
791
+
792
+ if (seq1.length !== seq2.length) {
793
+ throw new Error('Aligned sequences must have same length')
794
+ }
795
+
796
+ let pos1 = 0
797
+ let pos2 = 0
798
+ const seq1ToSeq2 = new Map<number, number>()
799
+ const seq2ToSeq1 = new Map<number, number>()
800
+
801
+ for (let i = 0; i < seq1.length; i++) {
802
+ const c1 = seq1[i]
803
+ const c2 = seq2[i]
804
+
805
+ if (c1 !== '-' && c2 !== '-') {
806
+ seq1ToSeq2.set(pos1, pos2)
807
+ seq2ToSeq1.set(pos2, pos1)
808
+ pos1++
809
+ pos2++
810
+ } else if (c1 === '-') {
811
+ pos2++
812
+ } else {
813
+ pos1++
814
+ }
815
+ }
816
+
817
+ return { seq1ToSeq2, seq2ToSeq1 }
818
+ }