molstar
Version:
A comprehensive macromolecular library.
177 lines (176 loc) • 6.22 kB
JavaScript
/**
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { __assign } from "tslib";
import { SubstitutionMatrices } from './substitution-matrix';
var DefaultAlignmentOptions = {
gapPenalty: -11,
gapExtensionPenalty: -1,
substMatrix: 'default'
};
export function align(seqA, seqB, options) {
if (options === void 0) { options = {}; }
var o = __assign(__assign({}, DefaultAlignmentOptions), options);
var alignment = new Alignment(seqA, seqB, o);
alignment.calculate();
return alignment.trace();
}
var Alignment = /** @class */ (function () {
function Alignment(seqA, seqB, options) {
this.seqA = seqA;
this.seqB = seqB;
this.S = [];
this.V = [];
this.H = [];
this.gapPenalty = options.gapPenalty;
this.gapExtensionPenalty = options.gapExtensionPenalty;
this.substMatrix = options.substMatrix === 'default' ? undefined : SubstitutionMatrices[options.substMatrix];
this.n = this.seqA.length;
this.m = this.seqB.length;
}
Alignment.prototype.initMatrices = function () {
var _a = this, n = _a.n, m = _a.m, gapPenalty = _a.gapPenalty, S = _a.S, V = _a.V, H = _a.H;
for (var i = 0; i <= n; ++i) {
S[i] = [], V[i] = [], H[i] = [];
for (var j = 0; j <= m; ++j) {
S[i][j] = 0, V[i][j] = 0, H[i][j] = 0;
}
}
for (var i = 0; i <= n; ++i) {
S[i][0] = gapPenalty;
H[i][0] = -Infinity;
}
for (var j = 0; j <= m; ++j) {
S[0][j] = gapPenalty;
V[0][j] = -Infinity;
}
S[0][0] = 0;
};
Alignment.prototype.makeScoreFn = function () {
var _a = this, seqA = _a.seqA, seqB = _a.seqB, substMatrix = _a.substMatrix;
if (substMatrix) {
return function score(i, j) {
var _a, _b;
var cA = seqA[i];
var cB = seqB[j];
return (_b = (_a = substMatrix[cA]) === null || _a === void 0 ? void 0 : _a[cB]) !== null && _b !== void 0 ? _b : -4;
};
}
else {
return function scoreNoSubstMat(i, j) {
var cA = seqA[i];
var cB = seqB[j];
return cA === cB ? 5 : -3;
};
}
};
Alignment.prototype.calculate = function () {
this.initMatrices();
var scoreFn = this.makeScoreFn();
var _a = this, V = _a.V, H = _a.H, S = _a.S, n = _a.n, m = _a.m, gapExtensionPenalty = _a.gapExtensionPenalty, gapPenalty = _a.gapPenalty;
var Vi1, Si1, Vi, Hi, Si;
for (var i = 1; i <= n; ++i) {
Si1 = S[i - 1], Vi1 = V[i - 1];
Vi = V[i], Hi = H[i], Si = S[i];
for (var j = 1; j <= m; ++j) {
Vi[j] = Math.max(Si1[j] + gapPenalty, Vi1[j] + gapExtensionPenalty);
Hi[j] = Math.max(Si[j - 1] + gapPenalty, Hi[j - 1] + gapExtensionPenalty);
Si[j] = Math.max(Si1[j - 1] + scoreFn(i - 1, j - 1), // match
Vi[j], // del
Hi[j] // ins
);
}
}
};
Alignment.prototype.trace = function () {
var scoreFn = this.makeScoreFn();
var _a = this, V = _a.V, H = _a.H, S = _a.S, seqA = _a.seqA, seqB = _a.seqB, gapExtensionPenalty = _a.gapExtensionPenalty, gapPenalty = _a.gapPenalty;
var i = this.n;
var j = this.m;
var mat;
var score;
var aliA = '';
var aliB = '';
if (S[i][j] >= V[i][j]) {
mat = 'S';
score = S[i][j];
}
else if (V[i][j] >= H[i][j]) {
mat = 'V';
score = V[i][j];
}
else {
mat = 'H';
score = H[i][j];
}
while (i > 0 && j > 0) {
if (mat === 'S') {
if (S[i][j] === S[i - 1][j - 1] + scoreFn(i - 1, j - 1)) {
aliA = seqA[i - 1] + aliA;
aliB = seqB[j - 1] + aliB;
--i;
--j;
mat = 'S';
}
else if (S[i][j] === V[i][j]) {
mat = 'V';
}
else if (S[i][j] === H[i][j]) {
mat = 'H';
}
else {
--i;
--j;
}
}
else if (mat === 'V') {
if (V[i][j] === V[i - 1][j] + gapExtensionPenalty) {
aliA = seqA[i - 1] + aliA;
aliB = '-' + aliB;
--i;
mat = 'V';
}
else if (V[i][j] === S[i - 1][j] + gapPenalty) {
aliA = seqA[i - 1] + aliA;
aliB = '-' + aliB;
--i;
mat = 'S';
}
else {
--i;
}
}
else if (mat === 'H') {
if (H[i][j] === H[i][j - 1] + gapExtensionPenalty) {
aliA = '-' + aliA;
aliB = seqB[j - 1] + aliB;
--j;
mat = 'H';
}
else if (H[i][j] === S[i][j - 1] + gapPenalty) {
aliA = '-' + aliA;
aliB = seqB[j - 1] + aliB;
--j;
mat = 'S';
}
else {
--j;
}
}
}
while (i > 0) {
aliA = seqA[i - 1] + aliA;
aliB = '-' + aliB;
--i;
}
while (j > 0) {
aliA = '-' + aliA;
aliB = seqB[j - 1] + aliB;
--j;
}
return { aliA: aliA, aliB: aliB, score: score };
};
return Alignment;
}());