UNPKG

@rcsb/rcsb-saguaro-3d

Version:
234 lines (233 loc) 9.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AlignmentReference = void 0; const tslib_1 = require("tslib"); const lodash_1 = require("lodash"); const TagDelimiter_1 = require("@rcsb/rcsb-api-tools/lib/RcsbUtils/TagDelimiter"); const app_1 = require("@rcsb/rcsb-saguaro-app/lib/app"); class AlignmentReference { constructor() { this.alignmentRefGaps = {}; this.memberRefList = []; this.alignmentMap = new Map(); } init(result) { return tslib_1.__awaiter(this, void 0, void 0, function* () { this.alignmentMap.clear(); this.refId = this.addUniqueAlignmentId(result, 0, 0); const length = (yield this.getSequences())[0].sequence.length; this.alignmentRefMap = Array(length).fill(0).map((v, n) => n + 1); }); } 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); } addUniqueAlignmentId(result, alignmentIndex, pairIndex = 1) { var _a, _b, _c, _d; const res = result.structures[pairIndex]; if (!res.selection) throw new Error("Missing entry_id and name from result"); let entryId = undefined; const asymId = 'asym_id' in res.selection ? res.selection.asym_id : undefined; if ("entry_id" in res && res.entry_id && res.selection && "asym_id" in res.selection) entryId = res.entry_id; else if ("name" in res && res.selection && "asym_id" in res.selection) entryId = res.name; if (!entryId || !asymId) throw new Error("Missing entry_id and name from result"); if (!this.alignmentMap.has(`${entryId}${TagDelimiter_1.TagDelimiter.instance}${asymId}`)) { this.alignmentMap.set(`${entryId}${TagDelimiter_1.TagDelimiter.instance}${asymId}`, { entryId, instanceId: asymId, sequence: (_b = (_a = result.sequence_alignment) === null || _a === void 0 ? void 0 : _a[pairIndex].sequence) !== null && _b !== void 0 ? _b : "", alignmentIndex: alignmentIndex, pairIndex: pairIndex, alignmentId: `${entryId}${TagDelimiter_1.TagDelimiter.instance}${asymId}` }); return `${entryId}${TagDelimiter_1.TagDelimiter.instance}${asymId}`; } else { let tag = 1; while (this.alignmentMap.has(`${entryId}[${tag}]${TagDelimiter_1.TagDelimiter.instance}${asymId}`)) { tag++; } this.alignmentMap.set(`${entryId}[${tag}]${TagDelimiter_1.TagDelimiter.instance}${asymId}`, { entryId, instanceId: asymId, sequence: (_d = (_c = result.sequence_alignment) === null || _c === void 0 ? void 0 : _c[pairIndex].sequence) !== null && _d !== void 0 ? _d : "", alignmentIndex: alignmentIndex, pairIndex: pairIndex, alignmentId: `${entryId}[${tag}]${TagDelimiter_1.TagDelimiter.instance}${asymId}` }); return `${entryId}[${tag}]${TagDelimiter_1.TagDelimiter.instance}${asymId}`; } } getAlignmentEntry(alignmentId) { const pdb = this.alignmentMap.get(alignmentId); if (pdb) return pdb; throw new Error("Alignment Id not found"); } getSequences() { return tslib_1.__awaiter(this, void 0, void 0, function* () { const out = Array.from(this.alignmentMap.values()).filter(v => v.sequence.length > 0).map(v => ({ rcsbId: v.alignmentId, sequence: v.sequence })); const missingSeq = yield app_1.RcsbRequestContextManager.getInstanceSequences(Array.from(this.alignmentMap.values()).filter(v => v.sequence.length == 0).map(v => `${v.entryId}${TagDelimiter_1.TagDelimiter.instance}${v.instanceId}`).filter((value, index, list) => list.indexOf(value) === index)); return out.concat(Array.from(this.alignmentMap.values()).filter(v => v.sequence.length == 0).map(v => { var _a, _b; return ({ rcsbId: v.alignmentId, sequence: (_b = (_a = missingSeq.find(s => s.rcsbId === `${v.entryId}${TagDelimiter_1.TagDelimiter.instance}${v.instanceId}`)) === null || _a === void 0 ? void 0 : _a.sequence) !== null && _b !== void 0 ? _b : "" }); })); }); } 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: begPos + (n - begIndex) }); 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; }