@rcsb/rcsb-saguaro-app
Version:
RCSB 1D Saguaro Web App
166 lines • 5.62 kB
JavaScript
import { cloneDeep } from "lodash";
export class AlignmentReference {
constructor(refId, targetId, alignment, target) {
this.memberRefList = [];
this.alignmentRefMap = 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: 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: cloneDeep(alignment),
target: 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));
});
}
}
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;
}
//# sourceMappingURL=AlignmentReference.js.map