UNPKG

@rcsb/rcsb-saguaro-app

Version:
170 lines (169 loc) 5.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AlignmentReference = void 0; const lodash_1 = require("lodash"); class AlignmentReference { constructor(refId, targetId, alignment, target) { this.memberRefList = []; this.alignmentRefMap = (0, lodash_1.cloneDeep)(alignment); this.alignmentRefGaps = findGaps(alignment); if (alignment.length != target.length) throw new Error("Alignment and target length error"); this.refId = refId; this.memberRefList.push({ id: targetId, map: alignment.map((v, n) => n), ref: (0, lodash_1.cloneDeep)(alignment), target }); } addAlignment(id, alignment, target) { const gaps = findGaps(alignment); for (const gapBeg in gaps) { if (this.alignmentRefGaps[gapBeg]) this.extendGap(parseInt(gapBeg), gaps[gapBeg]); else this.addGap(parseInt(gapBeg), gaps[gapBeg]); } const beg = alignment.filter(a => (a && this.alignmentRefMap[0] && a < this.alignmentRefMap[0])); if (beg.length > 0) this.addBeg(beg); const n = this.alignmentRefMap[this.alignmentRefMap.length - 1]; const end = alignment.filter(a => (a && n && a > n)); if (end.length > 0) this.addEnd(end); this.addRef(id, alignment, target); } buildAlignments() { return buildAlignments(this.refId, this.alignmentRefMap, this.memberRefList); } addRef(id, alignment, target) { const map = Array(this.alignmentRefMap.length).fill(undefined); alignment.forEach((v, n) => { if (typeof v === "undefined") return; const index = this.alignmentRefMap.findIndex(e => e === v); if (index >= 0) map[index] = n; }); const gaps = findGaps(alignment); for (const gapBeg in gaps) { const index = this.alignmentRefMap.findIndex(v => v === parseInt(gapBeg)); for (let i = 1; i <= gaps[gapBeg]; i++) { map[index + i] = map[index] + i; } } this.memberRefList.push({ id, map, ref: (0, lodash_1.cloneDeep)(alignment), target: (0, lodash_1.cloneDeep)(target) }); } addEnd(indexList) { const last = this.alignmentRefMap.length; this.alignmentRefMap.splice(last, 0, ...indexList); this.memberRefList.forEach(mr => { mr.map.splice(last, 0, ...Array(indexList.length).fill(undefined)); }); } addBeg(indexList) { this.alignmentRefMap.splice(0, 0, ...indexList); this.memberRefList.forEach(mr => { mr.map.splice(0, 0, ...Array(indexList.length).fill(undefined)); }); } addGap(gapBeg, gapLength) { this.alignmentRefGaps[gapBeg] = gapLength; const i = this.alignmentRefMap.findIndex((v) => v === gapBeg) + 1; this.alignmentRefMap.splice(i, 0, ...Array(gapLength).fill(undefined)); this.memberRefList.forEach(mr => { mr.map.splice(i, 0, ...Array(gapLength).fill(undefined)); }); } extendGap(gapBeg, gapLength) { if (!this.alignmentRefGaps[gapBeg] || this.alignmentRefGaps[gapBeg] >= gapLength) return; const delta = gapLength - this.alignmentRefGaps[gapBeg]; this.alignmentRefGaps[gapBeg] += delta; const i = this.alignmentRefMap.findIndex((v) => v === gapBeg) + 1; this.alignmentRefMap.splice(i, 0, ...Array(delta).fill(undefined)); this.memberRefList.forEach(mr => { mr.map.splice(i, 0, ...Array(delta).fill(undefined)); }); } } exports.AlignmentReference = AlignmentReference; function buildAlignments(refId, alignmentRefMap, alignmentMembers) { const out = {}; out.target_alignments = []; out.target_alignments.push({ aligned_regions: buildRegions(alignmentRefMap), target_id: refId }); alignmentMembers.forEach(am => { var _a; (_a = out.target_alignments) === null || _a === void 0 ? void 0 : _a.push({ target_id: am.id, aligned_regions: buildRegions(am.map.map((v, n) => typeof v === "number" ? am.target[v] : undefined)) }); }); return out; } function buildRegions(alignment) { const out = []; let begIndex = 0; let begPos = 0; alignment.forEach((v, n) => { if (!v) { if (begIndex > 0) { out.push({ query_begin: begIndex, target_begin: begPos, query_end: n, target_end: alignment[n - 1] }); begIndex = 0; begPos = 0; } } else { if (begIndex == 0) { begIndex = n + 1; begPos = v; } } }); if (begPos > 0) { const n = alignment.length; out.push({ query_begin: begIndex, target_begin: begPos, query_end: n, target_end: alignment[n - 1] }); } return out; } function findGaps(alignment) { const out = {}; let gapBeg = 0; let gapLength = 0; alignment.forEach((v, n) => { if (!v) { if (gapBeg == 0) gapBeg = alignment[n - 1]; gapLength++; } else { if (gapLength > 0) { out[gapBeg] = gapLength; gapBeg = 0; gapLength = 0; } } }); if (gapLength > 0) out[gapBeg] = gapLength; return out; }