UNPKG

molstar

Version:

A comprehensive macromolecular library.

177 lines (176 loc) 6.22 kB
/** * 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; }());