Browse Source

ANVIL runtime updates

JonStargaryen 3 years ago
parent
commit
f2b9dceaab
1 changed files with 23 additions and 31 deletions
  1. 23 31
      src/extensions/anvil/algorithm.ts

+ 23 - 31
src/extensions/anvil/algorithm.ts

@@ -16,6 +16,8 @@ import { AccessibleSurfaceArea } from '../../mol-model-props/computed/accessible
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { MembraneOrientation } from './prop';
 
+const LARGE_CA_THRESHOLD = 5000;
+
 interface ANVILContext {
     structure: Structure,
 
@@ -27,7 +29,7 @@ interface ANVILContext {
     adjust: number,
 
     offsets: ArrayLike<number>,
-    exposed: ArrayLike<boolean>,
+    exposed: ArrayLike<number>,
     centroid: Vec3,
     extent: number
 };
@@ -56,7 +58,6 @@ export function computeANVIL(structure: Structure, props: ANVILProps) {
     });
 }
 
-
 const centroidHelper = new CentroidHelper();
 function initialize(structure: Structure, props: ANVILProps): ANVILContext {
     const l = StructureElement.Location.create(structure);
@@ -65,7 +66,7 @@ function initialize(structure: Structure, props: ANVILProps): ANVILContext {
     centroidHelper.reset();
 
     let offsets = new Array<number>(elementCount);
-    let exposed = new Array<boolean>(elementCount);
+    let exposed = new Array<number>(elementCount);
 
     const accessibleSurfaceArea = structure && AccessibleSurfaceAreaProvider.get(structure);
     const asa = accessibleSurfaceArea.value!;
@@ -73,6 +74,7 @@ function initialize(structure: Structure, props: ANVILProps): ANVILContext {
 
     const vec = Vec3();
     let m = 0;
+    let n = 0;
     for (let i = 0, il = structure.units.length; i < il; ++i) {
         const unit = structure.units[i];
         const { elements } = unit;
@@ -102,15 +104,16 @@ function initialize(structure: Structure, props: ANVILProps): ANVILContext {
             centroidHelper.includeStep(vec);
 
             // keep track of offsets and exposed state to reuse
-            offsets[m] = structure.serialMapping.getSerialIndex(l.unit, l.element);
-            exposed[m] = AccessibleSurfaceArea.getValue(l, asa) / MaxAsa[label_comp_id(l)] > asaCutoff;
-            m++;
+            offsets[m++] = structure.serialMapping.getSerialIndex(l.unit, l.element);
+            if (AccessibleSurfaceArea.getValue(l, asa) / MaxAsa[label_comp_id(l)] > asaCutoff) {
+                exposed[n++] = structure.serialMapping.getSerialIndex(l.unit, l.element);
+            }
         }
     }
 
     // omit potentially empty tail
     offsets = offsets.slice(0, m);
-    exposed = exposed.slice(0, m);
+    exposed = exposed.slice(0, n);
 
     // calculate centroid and extent
     centroidHelper.finishedIncludeStep();
@@ -121,7 +124,6 @@ function initialize(structure: Structure, props: ANVILProps): ANVILContext {
         centroidHelper.radiusStep(vec);
     }
     const extent = Math.sqrt(centroidHelper.radiusSq);
-    console.log(`center: ${centroid}, radius: ${Math.sqrt(centroidHelper.radiusSq)}`);
 
     return {
         ...props,
@@ -139,19 +141,19 @@ export async function calculate(runtime: RuntimeContext, structure: Structure, p
     const initialHphobHphil = HphobHphil.filtered(ctx);
 
     if (runtime.shouldUpdate) {
-        await runtime.update({ message: 'Placing initial membrane...' });
+        await runtime.update({ message: 'Placing initial membrane...', current: 1, max: 3 });
     }
     const initialMembrane = findMembrane(ctx, generateSpherePoints(ctx, ctx.numberOfSpherePoints), initialHphobHphil)!;
 
     if (runtime.shouldUpdate) {
-        await runtime.update({ message: 'Refining membrane placement...' });
+        await runtime.update({ message: 'Refining membrane placement...', current: 2, max: 3 });
     }
     const refinedMembrane = findMembrane(ctx, findProximateAxes(ctx, initialMembrane), initialHphobHphil)!;
     let membrane = initialMembrane.qmax! > refinedMembrane.qmax! ? initialMembrane : refinedMembrane;
 
-    if (ctx.adjust) {
+    if (ctx.adjust && ctx.offsets.length < LARGE_CA_THRESHOLD) {
         if (runtime.shouldUpdate) {
-            await runtime.update({ message: 'Adjusting membrane thickness...' });
+            await runtime.update({ message: 'Adjusting membrane thickness...', current: 3, max: 3 });
         }
         membrane = adjustThickness(ctx, membrane, initialHphobHphil);
     }
@@ -195,7 +197,7 @@ namespace MembraneCandidate {
         return {
             planePoint1: c1,
             planePoint2: c2,
-            stats: stats
+            stats
         };
     }
 
@@ -240,19 +242,14 @@ function findMembrane(ctx: ANVILContext, spherePoints: Vec3[], initialStats: Hph
             const dMax = Math.max(d1, d2);
 
             // evaluate how well this membrane slice embeddeds the peculiar residues
-            const stats = HphobHphil.filtered(ctx, (testPoint: Vec3) => _isInMembranePlane(testPoint, diam, dMin, dMax));
+            const stats = HphobHphil.filtered(ctx, { normalVector: diam, dMin, dMax });
             qvartemp.push(MembraneCandidate.initial(c1, c2, stats));
         }
 
         let jmax = Math.floor((minThickness / stepSize) - 1);
 
         for (let width = 0, widthl = maxThickness; width <= widthl;) {
-            const imax = qvartemp.length - 1 - jmax;
-
-            for (let i = 0, il = imax; i < il; i++) {
-                const c1 = qvartemp[i].planePoint1;
-                const c2 = qvartemp[i + jmax].planePoint2;
-
+            for (let i = 0, il = qvartemp.length - 1 - jmax; i < il; i++) {
                 let hphob = 0;
                 let hphil = 0;
                 for (let j = 0; j < jmax; j++) {
@@ -271,7 +268,7 @@ function findMembrane(ctx: ANVILContext, spherePoints: Vec3[], initialStats: Hph
                     const qvaltest = qValue(stats, initialStats);
                     if (qvaltest >= qmax) {
                         qmax = qvaltest;
-                        membrane = MembraneCandidate.scored(spherePoint, c1, c2, stats, qmax, centroid);
+                        membrane = MembraneCandidate.scored(spherePoint, qvartemp[i].planePoint1, qvartemp[i + jmax].planePoint2, stats, qmax, centroid);
                     }
                 }
             }
@@ -525,25 +522,20 @@ namespace HphobHphil {
     }
 
     const testPoint = Vec3();
-    export function filtered(ctx: ANVILContext, filter?: (test: Vec3) => boolean): HphobHphil {
-        const { offsets, exposed, structure } = ctx;
+    export function filtered(ctx: ANVILContext, filter?: { normalVector: Vec3, dMin: number, dMax: number }): HphobHphil {
+        const { exposed, structure } = ctx;
         const { label_comp_id } = StructureProperties.atom;
         const l = StructureElement.Location.create(structure);
         const { x, y, z } = StructureProperties.atom;
         let hphob = 0;
         let hphil = 0;
-        for (let k = 0, kl = offsets.length; k < kl; k++) {
-            // ignore buried residues
-            if (!exposed[k]) {
-                continue;
-            }
-
-            setLocation(l, structure, offsets[k]);
+        for (let k = 0, kl = exposed.length; k < kl; k++) {
+            setLocation(l, structure, exposed[k]);
 
             // testPoints have to be in putative membrane layer
             if (filter) {
                 Vec3.set(testPoint, x(l), y(l), z(l));
-                if (!filter(testPoint)) {
+                if (!_isInMembranePlane(testPoint, filter.normalVector, filter.dMin, filter.dMax)) {
                     continue;
                 }
             }