Skip to content
Snippets Groups Projects
Commit e8e79ab0 authored by Sebastian Bittrich's avatar Sebastian Bittrich
Browse files

calculation of atom ASA

parent e94d3a69
No related branches found
No related tags found
No related merge requests found
......@@ -27,25 +27,42 @@ export function computeModelASA(hierarchy: AtomicHierarchy, conformation: Atomic
calculateASA(ctx);
}
const valueForIgnoredAtom = -1.0;
function calculateASA(ctx: ASAContext) {
const { probeSize, spherePoints, cons } = ctx;
const { atoms, residues, residueAtomSegments, derived } = ctx.hierarchy;
const { type_symbol } = atoms;
const { x, y, z } = ctx.conformation;
const radii: number[] = [];
const asa: number[] = [];
const atomAsa: number[] = [];
const residueAsa: number[] = [];
console.log(ctx.hierarchy);
console.log(ctx.conformation);
const position = (i: number, v: Vec3) => Vec3.set(v, x[i], y[i], z[i]);
const a1Pos = Vec3.zero();
const a2Pos = Vec3.zero();
// 1. extract all heavy atoms
// TODO can be more elegant by obtaining residue info once and then using offset to navigate to next residue
for (let i = 0; i < type_symbol.rowCount; ++i) {
// skip hydrogen atoms
if (type_symbol.value(i) === 'H' || type_symbol.value(i) === 'D' || type_symbol.value(i) === 'T')
if (type_symbol.value(i) === 'H' || type_symbol.value(i) === 'D' || type_symbol.value(i) === 'T') {
radii[radii.length] = valueForIgnoredAtom; // -1 is used to signal atoms not to be considered downstream
continue;
}
// determine group this atom belongs to
const groupIndex = residueAtomSegments.index[i];
// skip entities not part of a peptide chain
if (derived.residue.moleculeType[groupIndex] !== 4)
if (derived.residue.moleculeType[groupIndex] !== 4) {
radii[radii.length] = valueForIgnoredAtom;
continue;
}
const atomId = atoms.label_atom_id.value(i);
const compId = residues.label_comp_id.value(groupIndex);
......@@ -54,11 +71,66 @@ function calculateASA(ctx: ASAContext) {
radii[radii.length] = determineRadius(atomId, element, compId);
}
// 3. calculate the individual ASA of each atom
// TODO again might be more elegant to use offsets
// TODO distance is symmetric, omit redudant calcuations
for (let i = 0; i < radii.length; ++i) {
const radius = radii[i];
// skip invalid entries
if (radius === valueForIgnoredAtom) {
atomAsa[atomAsa.length] = valueForIgnoredAtom;
continue;
}
position(i, a1Pos);
// collect all neighboring atoms
const cutoff = probeSize + probeSize + radius;
const neighborIndices: number[] = [];
for (let k = 0; k < radii.length; ++k) {
const radius2 = radii[k];
if (i === k || radius2 === valueForIgnoredAtom)
continue;
position(k, a2Pos);
if (Vec3.distance(a1Pos, a2Pos) < cutoff + radius2) {
neighborIndices[neighborIndices.length] = k;
}
}
const r = probeSize + radius;
let accessiblePoints = 0;
for (let k = 0; k < spherePoints.length; ++k) {
const point = spherePoints[k];
let accessible = true;
const testPoint = [point[0] * r + a1Pos[0], point[1] * r + a1Pos[1], point[2] * r + a1Pos[2]] as Vec3;
for (let j = 0; j < neighborIndices.length; ++j) {
const naI = neighborIndices[j];
// store position of neighboring atom in a2Pos
position(naI, a2Pos);
const neighboringAtomRadius = radii[naI] + probeSize;
if (Vec3.squaredDistance(testPoint, a2Pos) < neighboringAtomRadius * neighboringAtomRadius) {
accessible = false;
break;
}
}
if (accessible) {
++accessiblePoints;
}
}
atomAsa[atomAsa.length] = cons * accessiblePoints * r * r;
}
// 3. for each residue
// 3a. calculate the individual ASA of each atom
// 3b. sum up
// 3c. (optionally) normalize by maximum value expected for a particular amino acid - needs lookup of max values
console.log(atomAsa);
}
/**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment