p2s_mapper 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +148 -0
- package/dist/alignmentQuality.d.ts +58 -0
- package/dist/alignmentQuality.js +108 -0
- package/dist/alignmentQuality.js.map +1 -0
- package/dist/alphaFoldModels.d.ts +29 -0
- package/dist/alphaFoldModels.js +60 -0
- package/dist/alphaFoldModels.js.map +1 -0
- package/dist/caCoordsToPdb.d.ts +18 -0
- package/dist/caCoordsToPdb.js +95 -0
- package/dist/caCoordsToPdb.js.map +1 -0
- package/dist/chooseMappedEntity.d.ts +55 -0
- package/dist/chooseMappedEntity.js +140 -0
- package/dist/chooseMappedEntity.js.map +1 -0
- package/dist/coordinates.d.ts +66 -0
- package/dist/coordinates.js +66 -0
- package/dist/coordinates.js.map +1 -0
- package/dist/dbIds.d.ts +16 -0
- package/dist/dbIds.js +42 -0
- package/dist/dbIds.js.map +1 -0
- package/dist/extractPerResidueConfidence.d.ts +49 -0
- package/dist/extractPerResidueConfidence.js +42 -0
- package/dist/extractPerResidueConfidence.js.map +1 -0
- package/dist/extractStructureSequences.d.ts +142 -0
- package/dist/extractStructureSequences.js +217 -0
- package/dist/extractStructureSequences.js.map +1 -0
- package/dist/fetchUtils.d.ts +34 -0
- package/dist/fetchUtils.js +91 -0
- package/dist/fetchUtils.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/invertMap.d.ts +2 -0
- package/dist/invertMap.js +8 -0
- package/dist/invertMap.js.map +1 -0
- package/dist/isoformRanking.d.ts +47 -0
- package/dist/isoformRanking.js +91 -0
- package/dist/isoformRanking.js.map +1 -0
- package/dist/mappings.d.ts +58 -0
- package/dist/mappings.js +193 -0
- package/dist/mappings.js.map +1 -0
- package/dist/package.json +1 -0
- package/dist/pairwiseAlignment.d.ts +35 -0
- package/dist/pairwiseAlignment.js +337 -0
- package/dist/pairwiseAlignment.js.map +1 -0
- package/dist/pdbUniProtMapping.d.ts +75 -0
- package/dist/pdbUniProtMapping.js +241 -0
- package/dist/pdbUniProtMapping.js.map +1 -0
- package/dist/pdbeBestStructures.d.ts +23 -0
- package/dist/pdbeBestStructures.js +79 -0
- package/dist/pdbeBestStructures.js.map +1 -0
- package/dist/pdbeEntryMolecules.d.ts +7 -0
- package/dist/pdbeEntryMolecules.js +39 -0
- package/dist/pdbeEntryMolecules.js.map +1 -0
- package/dist/siftsNumbering.d.ts +23 -0
- package/dist/siftsNumbering.js +44 -0
- package/dist/siftsNumbering.js.map +1 -0
- package/dist/stripStopCodon.d.ts +15 -0
- package/dist/stripStopCodon.js +24 -0
- package/dist/stripStopCodon.js.map +1 -0
- package/dist/structureFormat.d.ts +40 -0
- package/dist/structureFormat.js +54 -0
- package/dist/structureFormat.js.map +1 -0
- package/dist/structureSources.d.ts +28 -0
- package/dist/structureSources.js +76 -0
- package/dist/structureSources.js.map +1 -0
- package/dist/structureUrls.d.ts +54 -0
- package/dist/structureUrls.js +147 -0
- package/dist/structureUrls.js.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.js +27 -0
- package/dist/types.js.map +1 -0
- package/dist/uniProtSearch.d.ts +32 -0
- package/dist/uniProtSearch.js +114 -0
- package/dist/uniProtSearch.js.map +1 -0
- package/esm/alignmentQuality.d.ts +58 -0
- package/esm/alignmentQuality.js +100 -0
- package/esm/alignmentQuality.js.map +1 -0
- package/esm/alphaFoldModels.d.ts +29 -0
- package/esm/alphaFoldModels.js +55 -0
- package/esm/alphaFoldModels.js.map +1 -0
- package/esm/caCoordsToPdb.d.ts +18 -0
- package/esm/caCoordsToPdb.js +91 -0
- package/esm/caCoordsToPdb.js.map +1 -0
- package/esm/chooseMappedEntity.d.ts +55 -0
- package/esm/chooseMappedEntity.js +134 -0
- package/esm/chooseMappedEntity.js.map +1 -0
- package/esm/coordinates.d.ts +66 -0
- package/esm/coordinates.js +58 -0
- package/esm/coordinates.js.map +1 -0
- package/esm/dbIds.d.ts +16 -0
- package/esm/dbIds.js +35 -0
- package/esm/dbIds.js.map +1 -0
- package/esm/extractPerResidueConfidence.d.ts +49 -0
- package/esm/extractPerResidueConfidence.js +38 -0
- package/esm/extractPerResidueConfidence.js.map +1 -0
- package/esm/extractStructureSequences.d.ts +142 -0
- package/esm/extractStructureSequences.js +205 -0
- package/esm/extractStructureSequences.js.map +1 -0
- package/esm/fetchUtils.d.ts +34 -0
- package/esm/fetchUtils.js +82 -0
- package/esm/fetchUtils.js.map +1 -0
- package/esm/index.d.ts +23 -0
- package/esm/index.js +30 -0
- package/esm/index.js.map +1 -0
- package/esm/invertMap.d.ts +2 -0
- package/esm/invertMap.js +5 -0
- package/esm/invertMap.js.map +1 -0
- package/esm/isoformRanking.d.ts +47 -0
- package/esm/isoformRanking.js +86 -0
- package/esm/isoformRanking.js.map +1 -0
- package/esm/mappings.d.ts +58 -0
- package/esm/mappings.js +179 -0
- package/esm/mappings.js.map +1 -0
- package/esm/pairwiseAlignment.d.ts +35 -0
- package/esm/pairwiseAlignment.js +328 -0
- package/esm/pairwiseAlignment.js.map +1 -0
- package/esm/pdbUniProtMapping.d.ts +75 -0
- package/esm/pdbUniProtMapping.js +231 -0
- package/esm/pdbUniProtMapping.js.map +1 -0
- package/esm/pdbeBestStructures.d.ts +23 -0
- package/esm/pdbeBestStructures.js +73 -0
- package/esm/pdbeBestStructures.js.map +1 -0
- package/esm/pdbeEntryMolecules.d.ts +7 -0
- package/esm/pdbeEntryMolecules.js +35 -0
- package/esm/pdbeEntryMolecules.js.map +1 -0
- package/esm/siftsNumbering.d.ts +23 -0
- package/esm/siftsNumbering.js +40 -0
- package/esm/siftsNumbering.js.map +1 -0
- package/esm/stripStopCodon.d.ts +15 -0
- package/esm/stripStopCodon.js +20 -0
- package/esm/stripStopCodon.js.map +1 -0
- package/esm/structureFormat.d.ts +40 -0
- package/esm/structureFormat.js +48 -0
- package/esm/structureFormat.js.map +1 -0
- package/esm/structureSources.d.ts +28 -0
- package/esm/structureSources.js +71 -0
- package/esm/structureSources.js.map +1 -0
- package/esm/structureUrls.d.ts +54 -0
- package/esm/structureUrls.js +134 -0
- package/esm/structureUrls.js.map +1 -0
- package/esm/types.d.ts +14 -0
- package/esm/types.js +23 -0
- package/esm/types.js.map +1 -0
- package/esm/uniProtSearch.d.ts +32 -0
- package/esm/uniProtSearch.js +110 -0
- package/esm/uniProtSearch.js.map +1 -0
- package/package.json +63 -0
- package/src/alignmentQuality.ts +132 -0
- package/src/alphaFoldModels.ts +91 -0
- package/src/caCoordsToPdb.ts +111 -0
- package/src/chooseMappedEntity.ts +198 -0
- package/src/coordinates.ts +119 -0
- package/src/dbIds.ts +46 -0
- package/src/extractPerResidueConfidence.ts +88 -0
- package/src/extractStructureSequences.ts +342 -0
- package/src/fetchUtils.ts +110 -0
- package/src/index.ts +34 -0
- package/src/invertMap.ts +4 -0
- package/src/isoformRanking.ts +139 -0
- package/src/mappings.ts +230 -0
- package/src/pairwiseAlignment.ts +423 -0
- package/src/pdbUniProtMapping.ts +320 -0
- package/src/pdbeBestStructures.ts +94 -0
- package/src/pdbeEntryMolecules.ts +37 -0
- package/src/siftsNumbering.ts +61 -0
- package/src/stripStopCodon.ts +20 -0
- package/src/structureFormat.ts +70 -0
- package/src/structureSources.ts +101 -0
- package/src/structureUrls.ts +171 -0
- package/src/types.ts +30 -0
- package/src/uniProtSearch.ts +212 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
// BLOSUM62 scoring matrix — standard 20 amino acids + B, Z, X, *
|
|
2
|
+
// prettier-ignore
|
|
3
|
+
const AMINO_ACIDS = ['A', 'R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F', 'P', 'S', 'T', 'W', 'Y', 'V', 'B', 'Z', 'X', '*'];
|
|
4
|
+
// prettier-ignore
|
|
5
|
+
const BLOSUM62_RAW = [
|
|
6
|
+
// A R N D C Q E G H I L K M F P S T W Y V B Z X *
|
|
7
|
+
[4, -1, -2, -2, 0, -1, -1, 0, -2, -1, -1, -1, -1, -2, -1, 1, 0, -3, -2, 0, -2, -1, 0, -4], // A
|
|
8
|
+
[-1, 5, 0, -2, -3, 1, 0, -2, 0, -3, -2, 2, -1, -3, -2, -1, -1, -3, -2, -3, -1, 0, -1, -4], // R
|
|
9
|
+
[-2, 0, 6, 1, -3, 0, 0, 0, 1, -3, -3, 0, -2, -3, -2, 1, 0, -4, -2, -3, 3, 0, -1, -4], // N
|
|
10
|
+
[-2, -2, 1, 6, -3, 0, 2, -1, -1, -3, -4, -1, -3, -3, -1, 0, -1, -4, -3, -3, 4, 1, -1, -4], // D
|
|
11
|
+
[0, -3, -3, -3, 9, -3, -4, -3, -3, -1, -1, -3, -1, -2, -3, -1, -1, -2, -2, -1, -3, -3, -2, -4], // C
|
|
12
|
+
[-1, 1, 0, 0, -3, 5, 2, -2, 0, -3, -2, 1, 0, -3, -1, 0, -1, -2, -1, -2, 0, 3, -1, -4], // Q
|
|
13
|
+
[-1, 0, 0, 2, -4, 2, 5, -2, 0, -3, -3, 1, -2, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1, -4], // E
|
|
14
|
+
[0, -2, 0, -1, -3, -2, -2, 6, -2, -4, -4, -2, -3, -3, -2, 0, -2, -2, -3, -3, -1, -2, -1, -4], // G
|
|
15
|
+
[-2, 0, 1, -1, -3, 0, 0, -2, 8, -3, -3, -1, -2, -1, -2, -1, -2, -2, 2, -3, 0, 0, -1, -4], // H
|
|
16
|
+
[-1, -3, -3, -3, -1, -3, -3, -4, -3, 4, 2, -3, 1, 0, -3, -2, -1, -3, -1, 3, -3, -3, -1, -4], // I
|
|
17
|
+
[-1, -2, -3, -4, -1, -2, -3, -4, -3, 2, 4, -2, 2, 0, -3, -2, -1, -2, -1, 1, -4, -3, -1, -4], // L
|
|
18
|
+
[-1, 2, 0, -1, -3, 1, 1, -2, -1, -3, -2, 5, -1, -3, -1, 0, -1, -3, -2, -2, 0, 1, -1, -4], // K
|
|
19
|
+
[-1, -1, -2, -3, -1, 0, -2, -3, -2, 1, 2, -1, 5, 0, -2, -1, -1, -1, -1, 1, -3, -1, -1, -4], // M
|
|
20
|
+
[-2, -3, -3, -3, -2, -3, -3, -3, -1, 0, 0, -3, 0, 6, -4, -2, -2, 1, 3, -1, -3, -3, -1, -4], // F
|
|
21
|
+
[-1, -2, -2, -1, -3, -1, -1, -2, -2, -3, -3, -1, -2, -4, 7, -1, -1, -4, -3, -2, -2, -1, -2, -4], // P
|
|
22
|
+
[1, -1, 1, 0, -1, 0, 0, 0, -1, -2, -2, 0, -1, -2, -1, 4, 1, -3, -2, -2, 0, 0, 0, -4], // S
|
|
23
|
+
[0, -1, 0, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1, -2, -1, 1, 5, -2, -2, 0, -1, -1, 0, -4], // T
|
|
24
|
+
[-3, -3, -4, -4, -2, -2, -3, -2, -2, -3, -2, -3, -1, 1, -4, -3, -2, 11, 2, -3, -4, -3, -2, -4], // W
|
|
25
|
+
[-2, -2, -2, -3, -2, -1, -2, -3, 2, -1, -1, -2, -1, 3, -3, -2, -2, 2, 7, -1, -3, -2, -1, -4], // Y
|
|
26
|
+
[0, -3, -3, -3, -1, -2, -2, -3, -3, 3, 1, -2, 1, -1, -2, -2, 0, -3, -1, 4, -3, -2, -1, -4], // V
|
|
27
|
+
[-2, -1, 3, 4, -3, 0, 1, -1, 0, -3, -4, 0, -3, -3, -2, 0, -1, -4, -3, -3, 4, 1, -1, -4], // B
|
|
28
|
+
[-1, 0, 0, 1, -3, 3, 4, -2, 0, -3, -3, 1, -1, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1, -4], // Z
|
|
29
|
+
[0, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 0, 0, -2, -1, -1, -1, -1, -1, -4], // X
|
|
30
|
+
[-4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, 1], // *
|
|
31
|
+
];
|
|
32
|
+
// Score of a residue pair that isn't in the matrix at all.
|
|
33
|
+
const UNKNOWN_PAIR_SCORE = -4;
|
|
34
|
+
// The DP reads the matrix once per cell, so both the residue→row lookup and the
|
|
35
|
+
// matrix itself are flat typed arrays keyed by char code: charCodeToRow maps
|
|
36
|
+
// 'a'/'A' to the same row, and unknown residues to -1 (scored as unknown).
|
|
37
|
+
const N_AA = AMINO_ACIDS.length;
|
|
38
|
+
const charCodeToRow = new Int8Array(128).fill(-1);
|
|
39
|
+
for (let i = 0; i < N_AA; i++) {
|
|
40
|
+
const aa = AMINO_ACIDS[i];
|
|
41
|
+
charCodeToRow[aa.charCodeAt(0)] = i;
|
|
42
|
+
charCodeToRow[aa.toLowerCase().charCodeAt(0)] = i;
|
|
43
|
+
}
|
|
44
|
+
const BLOSUM62 = new Int8Array(N_AA * N_AA);
|
|
45
|
+
for (let i = 0; i < N_AA; i++) {
|
|
46
|
+
for (let j = 0; j < N_AA; j++) {
|
|
47
|
+
BLOSUM62[i * N_AA + j] = BLOSUM62_RAW[i][j];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const rowOf = (c) => {
|
|
51
|
+
const code = c.charCodeAt(0);
|
|
52
|
+
return code < 128 ? charCodeToRow[code] : -1;
|
|
53
|
+
};
|
|
54
|
+
function getScore(a, b) {
|
|
55
|
+
const i = rowOf(a);
|
|
56
|
+
const j = rowOf(b);
|
|
57
|
+
return i < 0 || j < 0 ? UNKNOWN_PAIR_SCORE : BLOSUM62[i * N_AA + j];
|
|
58
|
+
}
|
|
59
|
+
// Default gap penalties (matching EMBOSS defaults)
|
|
60
|
+
const GAP_OPEN = -10;
|
|
61
|
+
const GAP_EXTEND = -0.5;
|
|
62
|
+
/**
|
|
63
|
+
* Ceiling on the dynamic-programming table, in cells. Both algorithms are
|
|
64
|
+
* O(m*n) time and hold one byte of traceback per cell, so this bounds the
|
|
65
|
+
* alignment at ~40 MB and roughly a second of main-thread work. Without it a
|
|
66
|
+
* titin-sized transcript or a long nucleic-acid chain locks up or OOMs the tab.
|
|
67
|
+
* Callers that have several candidates to align should check `alignmentTooLarge`
|
|
68
|
+
* and skip the oversized ones rather than let this throw.
|
|
69
|
+
*/
|
|
70
|
+
export const MAX_ALIGNMENT_CELLS = 40_000_000;
|
|
71
|
+
export function alignmentTooLarge(len1, len2) {
|
|
72
|
+
return (len1 + 1) * (len2 + 1) > MAX_ALIGNMENT_CELLS;
|
|
73
|
+
}
|
|
74
|
+
function assertAlignable(len1, len2) {
|
|
75
|
+
if (alignmentTooLarge(len1, len2)) {
|
|
76
|
+
throw new Error(`Sequences too long to align (${len1} x ${len2} residues exceeds the ${MAX_ALIGNMENT_CELLS} cell limit)`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Traceback states. Each cell stores, for each of the three matrices, which
|
|
80
|
+
// matrix its best predecessor came from — 2 bits per matrix, packed into one
|
|
81
|
+
// byte. Storing pointers instead of re-deriving them by comparing scores keeps
|
|
82
|
+
// traceback exact under Float32 rounding and lets the score matrices collapse
|
|
83
|
+
// to two rows.
|
|
84
|
+
const FROM_M = 0;
|
|
85
|
+
const FROM_IX = 1;
|
|
86
|
+
const FROM_IY = 2;
|
|
87
|
+
// Smith-Waterman only: the local alignment restarts here, so traceback stops.
|
|
88
|
+
const FROM_NONE = 3;
|
|
89
|
+
const M_SHIFT = 0;
|
|
90
|
+
const IX_SHIFT = 2;
|
|
91
|
+
const IY_SHIFT = 4;
|
|
92
|
+
const readPointer = (trace, at, shift) => ((trace[at] >> shift) & 0b11);
|
|
93
|
+
/**
|
|
94
|
+
* Fill the affine-gap DP tables for both algorithms; `local` switches
|
|
95
|
+
* Needleman-Wunsch (global, ends at the corner) to Smith-Waterman (restarts at
|
|
96
|
+
* 0, ends at the best-scoring cell). Only the previous and current score rows
|
|
97
|
+
* are kept — the full traceback lives in the packed `trace` byte array.
|
|
98
|
+
*/
|
|
99
|
+
function fillMatrices(seq1, seq2, gapOpen, gapExtend, local) {
|
|
100
|
+
const m = seq1.length;
|
|
101
|
+
const n = seq2.length;
|
|
102
|
+
assertAlignable(m, n);
|
|
103
|
+
const width = n + 1;
|
|
104
|
+
const trace = new Uint8Array((m + 1) * width);
|
|
105
|
+
// Row 0. Global: only M[0][0] is reachable and Iy[0][j] is the leading-gap
|
|
106
|
+
// base case. Local: M starts at 0 everywhere, gaps are unreachable.
|
|
107
|
+
let prevM = new Float32Array(width);
|
|
108
|
+
let prevIx = new Float32Array(width).fill(-Infinity);
|
|
109
|
+
let prevIy = new Float32Array(width).fill(-Infinity);
|
|
110
|
+
let curM = new Float32Array(width);
|
|
111
|
+
let curIx = new Float32Array(width);
|
|
112
|
+
let curIy = new Float32Array(width);
|
|
113
|
+
if (!local) {
|
|
114
|
+
prevM.fill(-Infinity);
|
|
115
|
+
prevM[0] = 0;
|
|
116
|
+
for (let j = 1; j <= n; j++) {
|
|
117
|
+
prevIy[j] = gapOpen + (j - 1) * gapExtend;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
let bestScore = local ? 0 : -Infinity;
|
|
121
|
+
let bestI = 0;
|
|
122
|
+
let bestJ = 0;
|
|
123
|
+
let bestMatrix = FROM_M;
|
|
124
|
+
// Resolve seq2 to matrix rows once instead of once per cell.
|
|
125
|
+
const cols = new Int8Array(n);
|
|
126
|
+
for (let j = 0; j < n; j++) {
|
|
127
|
+
cols[j] = rowOf(seq2[j]);
|
|
128
|
+
}
|
|
129
|
+
for (let i = 1; i <= m; i++) {
|
|
130
|
+
// Column 0, mirroring row 0.
|
|
131
|
+
curM[0] = local ? 0 : -Infinity;
|
|
132
|
+
curIx[0] = local ? -Infinity : gapOpen + (i - 1) * gapExtend;
|
|
133
|
+
curIy[0] = -Infinity;
|
|
134
|
+
const rowBase = i * width;
|
|
135
|
+
const scoreRow = rowOf(seq1[i - 1]);
|
|
136
|
+
const scoreBase = scoreRow * N_AA;
|
|
137
|
+
for (let j = 1; j <= n; j++) {
|
|
138
|
+
const col = cols[j - 1];
|
|
139
|
+
const matchScore = scoreRow < 0 || col < 0
|
|
140
|
+
? UNKNOWN_PAIR_SCORE
|
|
141
|
+
: BLOSUM62[scoreBase + col];
|
|
142
|
+
const dM = prevM[j - 1];
|
|
143
|
+
const dIx = prevIx[j - 1];
|
|
144
|
+
const dIy = prevIy[j - 1];
|
|
145
|
+
// Ties resolve M > Ix > Iy, matching the previous implementation.
|
|
146
|
+
const bestDiag = Math.max(dM, dIx, dIy);
|
|
147
|
+
const diagFrom = bestDiag === dM ? FROM_M : bestDiag === dIx ? FROM_IX : FROM_IY;
|
|
148
|
+
const mScore = bestDiag + matchScore;
|
|
149
|
+
const restart = local && mScore <= 0;
|
|
150
|
+
curM[j] = restart ? 0 : mScore;
|
|
151
|
+
const openIx = prevM[j] + gapOpen;
|
|
152
|
+
const extendIx = prevIx[j] + gapExtend;
|
|
153
|
+
curIx[j] = Math.max(openIx, extendIx);
|
|
154
|
+
const openIy = curM[j - 1] + gapOpen;
|
|
155
|
+
const extendIy = curIy[j - 1] + gapExtend;
|
|
156
|
+
curIy[j] = Math.max(openIy, extendIy);
|
|
157
|
+
trace[rowBase + j] =
|
|
158
|
+
((restart ? FROM_NONE : diagFrom) << M_SHIFT) |
|
|
159
|
+
((openIx >= extendIx ? FROM_M : FROM_IX) << IX_SHIFT) |
|
|
160
|
+
((openIy >= extendIy ? FROM_M : FROM_IY) << IY_SHIFT);
|
|
161
|
+
if (local) {
|
|
162
|
+
const cellMax = Math.max(curM[j], curIx[j], curIy[j]);
|
|
163
|
+
if (cellMax > bestScore) {
|
|
164
|
+
bestScore = cellMax;
|
|
165
|
+
bestI = i;
|
|
166
|
+
bestJ = j;
|
|
167
|
+
bestMatrix =
|
|
168
|
+
cellMax === curM[j]
|
|
169
|
+
? FROM_M
|
|
170
|
+
: cellMax === curIx[j]
|
|
171
|
+
? FROM_IX
|
|
172
|
+
: FROM_IY;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
;
|
|
177
|
+
[prevM, curM] = [curM, prevM];
|
|
178
|
+
[prevIx, curIx] = [curIx, prevIx];
|
|
179
|
+
[prevIy, curIy] = [curIy, prevIy];
|
|
180
|
+
}
|
|
181
|
+
if (local) {
|
|
182
|
+
return {
|
|
183
|
+
trace,
|
|
184
|
+
width,
|
|
185
|
+
score: bestScore,
|
|
186
|
+
startI: bestI,
|
|
187
|
+
startJ: bestJ,
|
|
188
|
+
startMatrix: bestMatrix,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// prev* now holds row m.
|
|
192
|
+
const finalM = prevM[n];
|
|
193
|
+
const finalIx = prevIx[n];
|
|
194
|
+
const finalIy = prevIy[n];
|
|
195
|
+
const score = Math.max(finalM, finalIx, finalIy);
|
|
196
|
+
return {
|
|
197
|
+
trace,
|
|
198
|
+
width,
|
|
199
|
+
score,
|
|
200
|
+
startI: m,
|
|
201
|
+
startJ: n,
|
|
202
|
+
startMatrix: score === finalM ? FROM_M : score === finalIx ? FROM_IX : FROM_IY,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Walk the packed traceback back to an edge. Rows are built back-to-front into
|
|
207
|
+
* arrays and reversed once, rather than prepending onto a string per residue
|
|
208
|
+
* (which is quadratic in the alignment length).
|
|
209
|
+
*/
|
|
210
|
+
function traceback(seq1, seq2, filled) {
|
|
211
|
+
const { trace, width, startI, startJ, score } = filled;
|
|
212
|
+
// Reversed: pushing here is prepending to the final string.
|
|
213
|
+
const out1 = [];
|
|
214
|
+
const out2 = [];
|
|
215
|
+
// Residues past the aligned region (the whole sequences when the local
|
|
216
|
+
// alignment is empty) hang off the end as gaps.
|
|
217
|
+
for (let k = seq1.length; k > startI; k--) {
|
|
218
|
+
out1.push(seq1[k - 1]);
|
|
219
|
+
out2.push('-');
|
|
220
|
+
}
|
|
221
|
+
for (let k = seq2.length; k > startJ; k--) {
|
|
222
|
+
out1.push('-');
|
|
223
|
+
out2.push(seq2[k - 1]);
|
|
224
|
+
}
|
|
225
|
+
let i = startI;
|
|
226
|
+
let j = startJ;
|
|
227
|
+
let matrix = filled.startMatrix;
|
|
228
|
+
while (i > 0 && j > 0) {
|
|
229
|
+
const at = i * width + j;
|
|
230
|
+
if (matrix === FROM_M) {
|
|
231
|
+
const next = readPointer(trace, at, M_SHIFT);
|
|
232
|
+
if (next === FROM_NONE) {
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
out1.push(seq1[i - 1]);
|
|
236
|
+
out2.push(seq2[j - 1]);
|
|
237
|
+
matrix = next;
|
|
238
|
+
i--;
|
|
239
|
+
j--;
|
|
240
|
+
}
|
|
241
|
+
else if (matrix === FROM_IX) {
|
|
242
|
+
out1.push(seq1[i - 1]);
|
|
243
|
+
out2.push('-');
|
|
244
|
+
matrix = readPointer(trace, at, IX_SHIFT);
|
|
245
|
+
i--;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
out1.push('-');
|
|
249
|
+
out2.push(seq2[j - 1]);
|
|
250
|
+
matrix = readPointer(trace, at, IY_SHIFT);
|
|
251
|
+
j--;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Whatever is left runs into an edge, so it can only be gaps.
|
|
255
|
+
while (i > 0) {
|
|
256
|
+
out1.push(seq1[i - 1]);
|
|
257
|
+
out2.push('-');
|
|
258
|
+
i--;
|
|
259
|
+
}
|
|
260
|
+
while (j > 0) {
|
|
261
|
+
out1.push('-');
|
|
262
|
+
out2.push(seq2[j - 1]);
|
|
263
|
+
j--;
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
alignedSeq1: out1.reverse().join(''),
|
|
267
|
+
alignedSeq2: out2.reverse().join(''),
|
|
268
|
+
score,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Needleman-Wunsch global alignment algorithm
|
|
273
|
+
* Aligns entire sequences end-to-end
|
|
274
|
+
*/
|
|
275
|
+
export function needlemanWunsch(seq1, seq2, gapOpen = GAP_OPEN, gapExtend = GAP_EXTEND) {
|
|
276
|
+
return traceback(seq1, seq2, fillMatrices(seq1, seq2, gapOpen, gapExtend, false));
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Smith-Waterman local alignment algorithm
|
|
280
|
+
* Finds the best local alignment between subsequences
|
|
281
|
+
*/
|
|
282
|
+
export function smithWaterman(seq1, seq2, gapOpen = GAP_OPEN, gapExtend = GAP_EXTEND) {
|
|
283
|
+
return traceback(seq1, seq2, fillMatrices(seq1, seq2, gapOpen, gapExtend, true));
|
|
284
|
+
}
|
|
285
|
+
function buildConsensus(alignedSeq1, alignedSeq2) {
|
|
286
|
+
const chars = [];
|
|
287
|
+
for (let i = 0; i < alignedSeq1.length; i++) {
|
|
288
|
+
const a = alignedSeq1[i];
|
|
289
|
+
const b = alignedSeq2[i];
|
|
290
|
+
if (a !== '-' && b !== '-' && a.toUpperCase() === b.toUpperCase()) {
|
|
291
|
+
chars.push('|');
|
|
292
|
+
}
|
|
293
|
+
else if (a !== '-' && b !== '-' && getScore(a, b) > 0) {
|
|
294
|
+
chars.push(':');
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
chars.push(' ');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return chars.join('');
|
|
301
|
+
}
|
|
302
|
+
/** The score of a sequence aligned to itself with no gaps. */
|
|
303
|
+
export function selfScore(seq) {
|
|
304
|
+
let score = 0;
|
|
305
|
+
for (const c of seq) {
|
|
306
|
+
score += getScore(c, c);
|
|
307
|
+
}
|
|
308
|
+
return score;
|
|
309
|
+
}
|
|
310
|
+
export function scoredAlignment(seq1, seq2, algorithm) {
|
|
311
|
+
const { alignedSeq1, alignedSeq2, score } = algorithm === 'smith_waterman'
|
|
312
|
+
? smithWaterman(seq1, seq2)
|
|
313
|
+
: needlemanWunsch(seq1, seq2);
|
|
314
|
+
return {
|
|
315
|
+
alignment: {
|
|
316
|
+
consensus: buildConsensus(alignedSeq1, alignedSeq2),
|
|
317
|
+
alns: [
|
|
318
|
+
{ id: 'a', seq: alignedSeq1 },
|
|
319
|
+
{ id: 'b', seq: alignedSeq2 },
|
|
320
|
+
],
|
|
321
|
+
},
|
|
322
|
+
score,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
export function runLocalAlignment(seq1, seq2, algorithm) {
|
|
326
|
+
return scoredAlignment(seq1, seq2, algorithm).alignment;
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=pairwiseAlignment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairwiseAlignment.js","sourceRoot":"","sources":["../src/pairwiseAlignment.ts"],"names":[],"mappings":"AAGA,iEAAiE;AACjE,kBAAkB;AAClB,MAAM,WAAW,GAAG,CAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,CAAC,CAAA;AACrH,kBAAkB;AAClB,MAAM,YAAY,GAAG;IACrB,iGAAiG;IAC/F,CAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAE,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAE,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAE,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;IACtG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAA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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { FetchOptions } from './fetchUtils.ts';
|
|
2
|
+
/** One contiguous UniProt <-> structure correspondence for a single entity.
|
|
3
|
+
* `unp*` are 1-based UniProt positions; `struct*` are 0-based inclusive
|
|
4
|
+
* structure-sequence positions, this plugin's native coordinate. */
|
|
5
|
+
export interface UniProtStructureSegment {
|
|
6
|
+
entityId: string;
|
|
7
|
+
/** author chain id, when the response names it */
|
|
8
|
+
chainId?: string;
|
|
9
|
+
unpStart: number;
|
|
10
|
+
unpEnd: number;
|
|
11
|
+
structStart: number;
|
|
12
|
+
structEnd: number;
|
|
13
|
+
/** the endpoints' author residue numbers, the numbering a paper cites and a
|
|
14
|
+
* Mol* hover shows; absent when the response omits them */
|
|
15
|
+
authorStart?: number;
|
|
16
|
+
authorEnd?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface UniProtStructureMapping {
|
|
19
|
+
accession: string;
|
|
20
|
+
/** UniProt entry name, e.g. "P53_HUMAN" */
|
|
21
|
+
name?: string;
|
|
22
|
+
segments: UniProtStructureSegment[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Maps a 1-based UniProt position to a 0-based structure-sequence position.
|
|
26
|
+
* Returns undefined for positions outside the modeled region, so callers drop
|
|
27
|
+
* the feature instead of drawing it somewhere misleading.
|
|
28
|
+
*/
|
|
29
|
+
export type MapUniProtPosition = (uniprotPos: number) => number | undefined;
|
|
30
|
+
export declare function pdbeSiftsUrl(pdbId: string): string;
|
|
31
|
+
/** SIFTS for an entry, retried twice: one failed request would otherwise
|
|
32
|
+
* leave a fusion construct mapped onto its partner for the whole session. */
|
|
33
|
+
export declare function fetchUniProtStructureMappings(pdbId: string, opts?: FetchOptions): Promise<UniProtStructureMapping[]>;
|
|
34
|
+
/**
|
|
35
|
+
* Parses a PDBe `mappings/uniprot/{pdbId}` response into one entry per UniProt
|
|
36
|
+
* accession. Unparseable segments are skipped rather than failing the whole
|
|
37
|
+
* response — a chimera with one malformed segment still maps its other chains.
|
|
38
|
+
* The response is keyed by pdb id, so the single entry is taken whatever its key.
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseUniProtStructureMappings(json: unknown): UniProtStructureMapping[];
|
|
41
|
+
/** The entity a SIFTS segment is matched against: its mmCIF id and the author
|
|
42
|
+
* chains carrying it. */
|
|
43
|
+
export interface SegmentEntity {
|
|
44
|
+
entityId: string;
|
|
45
|
+
chains: readonly string[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Picks the UniProt entry that describes a given entity, with its segments
|
|
49
|
+
* narrowed to that entity. Only the entity the plugin has mapped to the
|
|
50
|
+
* transcript is relevant — a heteromer maps each of its chains to a different
|
|
51
|
+
* accession, and using the wrong one would silently annotate the wrong protein.
|
|
52
|
+
* When several accessions cover the same entity (a chimeric construct) the one
|
|
53
|
+
* contributing the most residues wins.
|
|
54
|
+
*/
|
|
55
|
+
export declare function chooseUniProtMappingForEntity(mappings: UniProtStructureMapping[], entity: SegmentEntity | undefined): UniProtStructureMapping | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Mapped structure positions that SIFTS assigns to a protein other than the
|
|
58
|
+
* transcript's, on a chain that fuses two. Local alignment bridges a fusion
|
|
59
|
+
* boundary, and on every GPCR fusion construct checked it scattered receptor
|
|
60
|
+
* residues onto the partner, 33 of them onto T4 lysozyme in 2RH1.
|
|
61
|
+
*
|
|
62
|
+
* `mapped` is each mapped structure position and whether its pair is
|
|
63
|
+
* identical. The transcript's own accession is the one whose covered positions
|
|
64
|
+
* are most often identical, plus a pseudocount, as the chain picker scores
|
|
65
|
+
* chains. A count of covered positions would not do: TP53's 11-residue peptide
|
|
66
|
+
* fused to CDK2 covers 11 positions against 224 chance hits on the kinase, and
|
|
67
|
+
* counting unmapped the peptide. Unless that accession reaches half identity
|
|
68
|
+
* the transcript is taken to be neither protein, and nothing is unmapped.
|
|
69
|
+
* Residues SIFTS assigns to no accession, such as tags, stay mapped.
|
|
70
|
+
*/
|
|
71
|
+
export declare function fusionPartnerPositions(mappings: UniProtStructureMapping[], entity: SegmentEntity | undefined, mapped: ReadonlyMap<number, boolean>): Set<number>;
|
|
72
|
+
/** 1-based UniProt position -> 0-based structure position, for an AlphaFold
|
|
73
|
+
* model whose sequence is the UniProt sequence. */
|
|
74
|
+
export declare const identityUniProtPositionMap: MapUniProtPosition;
|
|
75
|
+
export declare function makeUniProtPositionMap(segments: UniProtStructureSegment[]): MapUniProtPosition;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
// SIFTS UniProt <-> PDB residue mapping.
|
|
2
|
+
//
|
|
3
|
+
// UniProt feature coordinates are positions in the UniProt canonical sequence.
|
|
4
|
+
// For an AlphaFold model that *is* the structure's own sequence, so a feature at
|
|
5
|
+
// UniProt position p sits at structure position p - 1. For an experimental PDB
|
|
6
|
+
// entry it is not: the deposited construct is usually a fragment, often with
|
|
7
|
+
// tags or engineered residues, so the two numberings differ by a per-segment
|
|
8
|
+
// offset (1TUP's p53 chain starts at UniProt 94; 6VXX's spike SEQRES 33 is
|
|
9
|
+
// UniProt 14). SIFTS is the authoritative alignment between the two, published
|
|
10
|
+
// per entity/chain by PDBe.
|
|
11
|
+
//
|
|
12
|
+
// `residue_number` in the PDBe response is the 1-based index into the entity's
|
|
13
|
+
// SEQRES, i.e. label_seq_id, which is exactly this plugin's structure-sequence
|
|
14
|
+
// position + 1 (see applyLociInteractivity.ts for the other place that boundary
|
|
15
|
+
// is crossed).
|
|
16
|
+
import { jsonfetch, timeout } from "./fetchUtils.js";
|
|
17
|
+
export function pdbeSiftsUrl(pdbId) {
|
|
18
|
+
return `https://www.ebi.ac.uk/pdbe/api/mappings/uniprot/${pdbId.toLowerCase()}`;
|
|
19
|
+
}
|
|
20
|
+
const SIFTS_RETRY_DELAYS_MS = [1000, 3000];
|
|
21
|
+
// bounded, since a view reports itself loading until SIFTS answers
|
|
22
|
+
const SIFTS_TIMEOUT_MS = 20_000;
|
|
23
|
+
/** SIFTS for an entry, retried twice: one failed request would otherwise
|
|
24
|
+
* leave a fusion construct mapped onto its partner for the whole session. */
|
|
25
|
+
export async function fetchUniProtStructureMappings(pdbId, opts) {
|
|
26
|
+
const { signal: caller, ...rest } = opts ?? {};
|
|
27
|
+
const signal = caller ?? undefined;
|
|
28
|
+
const deadline = () => signal
|
|
29
|
+
? AbortSignal.any([signal, AbortSignal.timeout(SIFTS_TIMEOUT_MS)])
|
|
30
|
+
: AbortSignal.timeout(SIFTS_TIMEOUT_MS);
|
|
31
|
+
for (let attempt = 0;; attempt++) {
|
|
32
|
+
try {
|
|
33
|
+
return parseUniProtStructureMappings(await jsonfetch(pdbeSiftsUrl(pdbId), { ...rest, signal: deadline() }));
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
const delay = SIFTS_RETRY_DELAYS_MS[attempt];
|
|
37
|
+
if (delay === undefined) {
|
|
38
|
+
throw e;
|
|
39
|
+
}
|
|
40
|
+
await timeout(delay, signal);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isRecord(value) {
|
|
45
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
46
|
+
}
|
|
47
|
+
function finiteNumber(value) {
|
|
48
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
49
|
+
}
|
|
50
|
+
function residueNumber(endpoint) {
|
|
51
|
+
return isRecord(endpoint) ? finiteNumber(endpoint.residue_number) : undefined;
|
|
52
|
+
}
|
|
53
|
+
function authorResidueNumber(endpoint) {
|
|
54
|
+
return isRecord(endpoint)
|
|
55
|
+
? finiteNumber(endpoint.author_residue_number)
|
|
56
|
+
: undefined;
|
|
57
|
+
}
|
|
58
|
+
function parseSegment(mapping) {
|
|
59
|
+
if (!isRecord(mapping)) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
const entityId = finiteNumber(mapping.entity_id);
|
|
63
|
+
const unpStart = finiteNumber(mapping.unp_start);
|
|
64
|
+
const unpEnd = finiteNumber(mapping.unp_end);
|
|
65
|
+
const structStart = residueNumber(mapping.start);
|
|
66
|
+
const structEnd = residueNumber(mapping.end);
|
|
67
|
+
const authorStart = authorResidueNumber(mapping.start);
|
|
68
|
+
const authorEnd = authorResidueNumber(mapping.end);
|
|
69
|
+
return entityId === undefined ||
|
|
70
|
+
unpStart === undefined ||
|
|
71
|
+
unpEnd === undefined ||
|
|
72
|
+
structStart === undefined ||
|
|
73
|
+
structEnd === undefined
|
|
74
|
+
? undefined
|
|
75
|
+
: {
|
|
76
|
+
entityId: String(entityId),
|
|
77
|
+
...(typeof mapping.chain_id === 'string'
|
|
78
|
+
? { chainId: mapping.chain_id }
|
|
79
|
+
: {}),
|
|
80
|
+
unpStart,
|
|
81
|
+
unpEnd,
|
|
82
|
+
// SEQRES/label_seq_id is 1-based, structure positions are 0-based
|
|
83
|
+
structStart: structStart - 1,
|
|
84
|
+
structEnd: structEnd - 1,
|
|
85
|
+
...(authorStart === undefined ? {} : { authorStart }),
|
|
86
|
+
...(authorEnd === undefined ? {} : { authorEnd }),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Parses a PDBe `mappings/uniprot/{pdbId}` response into one entry per UniProt
|
|
91
|
+
* accession. Unparseable segments are skipped rather than failing the whole
|
|
92
|
+
* response — a chimera with one malformed segment still maps its other chains.
|
|
93
|
+
* The response is keyed by pdb id, so the single entry is taken whatever its key.
|
|
94
|
+
*/
|
|
95
|
+
export function parseUniProtStructureMappings(json) {
|
|
96
|
+
const entry = isRecord(json) ? Object.values(json)[0] : undefined;
|
|
97
|
+
const uniprot = isRecord(entry) ? entry.UniProt : undefined;
|
|
98
|
+
if (!isRecord(uniprot)) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const result = [];
|
|
102
|
+
for (const [accession, value] of Object.entries(uniprot)) {
|
|
103
|
+
const mappings = isRecord(value) ? value.mappings : undefined;
|
|
104
|
+
const segments = Array.isArray(mappings)
|
|
105
|
+
? mappings.map(parseSegment).filter(s => s !== undefined)
|
|
106
|
+
: [];
|
|
107
|
+
if (segments.length > 0) {
|
|
108
|
+
result.push({
|
|
109
|
+
accession,
|
|
110
|
+
name: isRecord(value) && typeof value.name === 'string'
|
|
111
|
+
? value.name
|
|
112
|
+
: undefined,
|
|
113
|
+
segments,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
function coveredResidues(segments) {
|
|
120
|
+
return segments.reduce((a, s) => a + (s.structEnd - s.structStart + 1), 0);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The segments of one accession that describe this entity. SIFTS numbers
|
|
124
|
+
* entities as the mmCIF does, and a PDB-format file loaded through Mol* numbers
|
|
125
|
+
* them per chain (1H26.pdb's chain C is entity 2, which in SIFTS is cyclin A),
|
|
126
|
+
* so a segment naming its chain is matched by chain.
|
|
127
|
+
*/
|
|
128
|
+
function segmentsForEntity(mapping, entity) {
|
|
129
|
+
return dedupeSegments(mapping.segments.filter(s => s.chainId === undefined
|
|
130
|
+
? s.entityId === entity.entityId
|
|
131
|
+
: entity.chains.includes(s.chainId)));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Picks the UniProt entry that describes a given entity, with its segments
|
|
135
|
+
* narrowed to that entity. Only the entity the plugin has mapped to the
|
|
136
|
+
* transcript is relevant — a heteromer maps each of its chains to a different
|
|
137
|
+
* accession, and using the wrong one would silently annotate the wrong protein.
|
|
138
|
+
* When several accessions cover the same entity (a chimeric construct) the one
|
|
139
|
+
* contributing the most residues wins.
|
|
140
|
+
*/
|
|
141
|
+
export function chooseUniProtMappingForEntity(mappings, entity) {
|
|
142
|
+
if (entity === undefined) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
let best;
|
|
146
|
+
for (const mapping of mappings) {
|
|
147
|
+
const segments = segmentsForEntity(mapping, entity);
|
|
148
|
+
if (segments.length > 0 &&
|
|
149
|
+
(!best || coveredResidues(segments) > coveredResidues(best.segments))) {
|
|
150
|
+
best = { ...mapping, segments };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return best;
|
|
154
|
+
}
|
|
155
|
+
const OWN_PSEUDOCOUNT = 5;
|
|
156
|
+
const MIN_OWN_IDENTITY = 0.5;
|
|
157
|
+
/**
|
|
158
|
+
* Mapped structure positions that SIFTS assigns to a protein other than the
|
|
159
|
+
* transcript's, on a chain that fuses two. Local alignment bridges a fusion
|
|
160
|
+
* boundary, and on every GPCR fusion construct checked it scattered receptor
|
|
161
|
+
* residues onto the partner, 33 of them onto T4 lysozyme in 2RH1.
|
|
162
|
+
*
|
|
163
|
+
* `mapped` is each mapped structure position and whether its pair is
|
|
164
|
+
* identical. The transcript's own accession is the one whose covered positions
|
|
165
|
+
* are most often identical, plus a pseudocount, as the chain picker scores
|
|
166
|
+
* chains. A count of covered positions would not do: TP53's 11-residue peptide
|
|
167
|
+
* fused to CDK2 covers 11 positions against 224 chance hits on the kinase, and
|
|
168
|
+
* counting unmapped the peptide. Unless that accession reaches half identity
|
|
169
|
+
* the transcript is taken to be neither protein, and nothing is unmapped.
|
|
170
|
+
* Residues SIFTS assigns to no accession, such as tags, stay mapped.
|
|
171
|
+
*/
|
|
172
|
+
export function fusionPartnerPositions(mappings, entity, mapped) {
|
|
173
|
+
const partners = new Set();
|
|
174
|
+
const byAccession = entity
|
|
175
|
+
? mappings
|
|
176
|
+
.map(m => segmentsForEntity(m, entity))
|
|
177
|
+
.filter(segments => segments.length > 0)
|
|
178
|
+
: [];
|
|
179
|
+
if (byAccession.length < 2) {
|
|
180
|
+
return partners;
|
|
181
|
+
}
|
|
182
|
+
const covers = (segments, pos) => segments.some(s => pos >= s.structStart && pos <= s.structEnd);
|
|
183
|
+
const identity = byAccession.map(segments => {
|
|
184
|
+
let covered = 0;
|
|
185
|
+
let identical = 0;
|
|
186
|
+
for (const [pos, same] of mapped) {
|
|
187
|
+
if (covers(segments, pos)) {
|
|
188
|
+
covered++;
|
|
189
|
+
identical += same ? 1 : 0;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return identical / (covered + OWN_PSEUDOCOUNT);
|
|
193
|
+
});
|
|
194
|
+
const ownIdentity = Math.max(...identity);
|
|
195
|
+
if (ownIdentity < MIN_OWN_IDENTITY) {
|
|
196
|
+
return partners;
|
|
197
|
+
}
|
|
198
|
+
const own = byAccession[identity.indexOf(ownIdentity)];
|
|
199
|
+
for (const pos of mapped.keys()) {
|
|
200
|
+
if (!covers(own, pos) &&
|
|
201
|
+
byAccession.some(segments => segments !== own && covers(segments, pos))) {
|
|
202
|
+
partners.add(pos);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return partners;
|
|
206
|
+
}
|
|
207
|
+
// SIFTS lists one mapping per *chain*, so the several chains of a homodimer
|
|
208
|
+
// repeat the same entity-level correspondence. They collapse to one segment.
|
|
209
|
+
function dedupeSegments(segments) {
|
|
210
|
+
const seen = new Set();
|
|
211
|
+
return segments.filter(s => {
|
|
212
|
+
const key = `${s.unpStart}-${s.unpEnd}-${s.structStart}-${s.structEnd}`;
|
|
213
|
+
const isNew = !seen.has(key);
|
|
214
|
+
seen.add(key);
|
|
215
|
+
return isNew;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
/** 1-based UniProt position -> 0-based structure position, for an AlphaFold
|
|
219
|
+
* model whose sequence is the UniProt sequence. */
|
|
220
|
+
export const identityUniProtPositionMap = uniprotPos => uniprotPos - 1;
|
|
221
|
+
export function makeUniProtPositionMap(segments) {
|
|
222
|
+
return uniprotPos => {
|
|
223
|
+
const segment = segments.find(s => uniprotPos >= s.unpStart && uniprotPos <= s.unpEnd);
|
|
224
|
+
if (!segment) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
const pos = segment.structStart + (uniprotPos - segment.unpStart);
|
|
228
|
+
return pos <= segment.structEnd ? pos : undefined;
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=pdbUniProtMapping.js.map
|