layer1/Shaker.cpp (267 lines of code) (raw):
/*
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information.
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-*
-*
-*
Z* -------------------------------------------------------------------
*/
#include"os_python.h"
#include"os_predef.h"
#include"os_std.h"
#include"os_gl.h"
#include"Base.h"
#include"OOMac.h"
#include"CGO.h"
#include"Map.h"
#include"Shaker.h"
CShaker *ShakerNew(PyMOLGlobals * G)
{
OOAlloc(G, CShaker);
I->G = G;
I->DistCon = VLAlloc(ShakerDistCon, 1000);
I->PyraCon = VLAlloc(ShakerPyraCon, 1000);
I->PlanCon = VLAlloc(ShakerPlanCon, 1000);
I->TorsCon = VLAlloc(ShakerTorsCon, 1000);
I->LineCon = VLAlloc(ShakerLineCon, 100);
I->NDistCon = 0;
I->NPyraCon = 0;
I->NPlanCon = 0;
I->NLineCon = 0;
I->NTorsCon = 0;
return (I);
}
void ShakerReset(CShaker * I)
{
I->NDistCon = 0;
I->NPyraCon = 0;
I->NPlanCon = 0;
I->NLineCon = 0;
I->NTorsCon = 0;
}
void ShakerAddDistCon(CShaker * I, int atom0, int atom1, float target, int type, float wt)
{
ShakerDistCon *sdc;
VLACheck(I->DistCon, ShakerDistCon, I->NDistCon);
sdc = I->DistCon + I->NDistCon;
sdc->at0 = atom0;
sdc->at1 = atom1;
sdc->targ = target;
sdc->type = type;
sdc->weight = wt;
I->NDistCon++;
}
float ShakerGetPyra(float *targ2, float *v0, float *v1, float *v2, float *v3)
{
float d0[3], cp[3], d2[3], d3[3];
float av[3], t0[3];
add3f(v1, v2, av);
subtract3f(v2, v1, d2);
add3f(v3, av, av);
subtract3f(v3, v1, d3);
subtract3f(av, v0, t0);
cross_product3f(d2, d3, cp);
scale3f(av, 0.33333333F, av);
normalize3f(cp);
subtract3f(av, v0, d0);
(*targ2) = length3f(d0);
return (dot_product3f(d0, cp));
}
float ShakerDoPyra(float targ1, float targ2,
float *v0, float *v1, float *v2, float *v3,
float *p0, float *p1, float *p2, float *p3, float wt, float inv_wt)
{
float d0[3], cp[3], d2[3], d3[3];
float av[3], t0[3], push[3];
float cur, dev, sc, result1, result2 = 0.0F;
add3f(v1, v2, av);
subtract3f(v2, v1, d2);
add3f(v3, av, av);
subtract3f(v3, v1, d3);
subtract3f(av, v0, t0);
cross_product3f(d2, d3, cp);
scale3f(av, 0.33333333F, av);
normalize3f(cp);
subtract3f(av, v0, d0);
cur = dot_product3f(d0, cp);
dev = cur - targ1;
result1 = (float) fabs(dev);
if(result1 > R_SMALL8) {
sc = wt * dev;
if((cur * targ1) < 0.0) /* inverted */
sc = sc * inv_wt; /* inversion fixing weight */
scale3f(cp, sc, push);
add3f(push, p0, p0);
scale3f(push, 0.333333F, push);
subtract3f(p1, push, p1);
subtract3f(p2, push, p2);
subtract3f(p3, push, p3);
}
if((targ2 >= 0.0F) && ((cur * targ1 > 0.0) || (fabs(targ1) < 0.1))) {
/* so long as we're not inverted...
also make sure v0 is the right distance from the average point */
cur = length3f(d0);
normalize3f(d0);
dev = cur - targ2;
result2 = (float) fabs(dev);
if(result2 > R_SMALL4) {
sc = wt * dev * 2.0F;
scale3f(d0, sc, push);
add3f(push, p0, p0);
scale3f(push, 0.333333F, push);
subtract3f(p1, push, p1);
subtract3f(p2, push, p2);
subtract3f(p3, push, p3);
}
}
return result1 + result2;
}
float ShakerDoLine(float *v0, float *v1, float *v2,
float *p0, float *p1, float *p2, float wt)
{
/* v0-v1-v2 */
float d0[3], d1[3], cp[3], d2[3], d3[3], d4[3], push[3];
float dev, sc, lcp, result;
subtract3f(v2, v1, d2);
subtract3f(v0, v1, d1);
normalize3f(d2);
normalize23f(d1, d0);
cross_product3f(d2, d0, cp);
lcp = (float) length3f(cp);
if(lcp > R_SMALL4) {
lcp = 1.0F / lcp;
scale3f(cp, lcp, cp); /* axis 0 */
subtract3f(v2, v0, d3);
normalize3f(d3); /* axis 1 */
cross_product3f(cp, d3, d4);
normalize3f(d4); /* displacement direction */
dev = dot_product3f(d1, d4); /* current deviation */
if((result = (float) fabs(dev)) > R_SMALL8) {
sc = wt * dev;
scale3f(d4, sc, push);
add3f(push, p1, p1);
scale3f(push, 0.5F, push);
subtract3f(p0, push, p0);
subtract3f(p2, push, p2);
} else {
result = 0.0;
}
} else
result = 0.0;
return result;
}
float ShakerDoPlan(float *v0, float *v1, float *v2, float *v3,
float *p0, float *p1, float *p2, float *p3,
float target, int fixed, float wt)
{
float result;
float d01[3], d12[3], d23[3], d03[3], cp0[3], cp1[3], dp, sc, dev, d0[3], push[3];
double s01, s12, s23, s03;
subtract3f(v0, v1, d01);
subtract3f(v1, v2, d12);
subtract3f(v2, v3, d23);
subtract3f(v0, v3, d03);
s03 = lengthsq3f(d03);
s01 = lengthsq3f(d01);
s12 = lengthsq3f(d12);
s23 = lengthsq3f(d23);
if((s03 < s01) || (s03 < s12) || (s03 < s23))
return 0.0F;
cross_product3f(d01, d12, cp0);
cross_product3f(d12, d23, cp1);
normalize3f(cp0);
normalize3f(cp1);
dp = dot_product3f(cp0, cp1);
result = (dev = 1.0F - (float) fabs(dp));
if(dev > R_SMALL4) {
/*
add3f(cp0,cp1,d0);
normalize3f(d0);
cross_product3f(cp0,d12,pos);
dp2 = dot_product3f(cp1,pos);
*/
if(fixed && (dp * target < 0.0F)) {
/* fixed & backwards... */
if(dp < 0.0F) {
sc = -wt * dev * 0.5F;
} else {
sc = wt * dev * 0.5F;
}
sc *= 0.02F; /* weaken considerably to allow resolution of
inconsistencies (folded rings, etc.) */
} else if(dp > 0) {
sc = -wt * dev * 0.5F;
} else {
sc = wt * dev * 0.5F;
}
if(fixed && (fixed < 7)) {
/* in small rings, ramp up the planarity factor */
sc *= 8;
} else {
sc *= 0.2F;
}
/* pair-wise nudges */
subtract3f(v0, v3, d0);
normalize3f(d0);
scale3f(d0, sc, push);
add3f(push, p0, p0);
subtract3f(p3, push, p3);
subtract3f(v1, v2, d0);
normalize3f(d0);
scale3f(d0, sc, push);
add3f(push, p1, p1);
subtract3f(p2, push, p2);
sc = -sc;
subtract3f(v0, v2, d0);
normalize3f(d0);
scale3f(d0, sc, push);
add3f(push, p0, p0);
subtract3f(p2, push, p2);
subtract3f(v1, v3, d0);
normalize3f(d0);
scale3f(d0, sc, push);
add3f(push, p1, p1);
subtract3f(p3, push, p3);
} else {
result = 0.0;
}
return result;
}
void ShakerAddPyraCon(CShaker * I, int atom0, int atom1, int atom2, int atom3,
float targ1, float targ2)
{
ShakerPyraCon *spc;
VLACheck(I->PyraCon, ShakerPyraCon, I->NPyraCon);
spc = I->PyraCon + I->NPyraCon;
spc->at0 = atom0;
spc->at1 = atom1;
spc->at2 = atom2;
spc->at3 = atom3;
spc->targ1 = targ1;
spc->targ2 = targ2;
I->NPyraCon++;
}
void ShakerAddTorsCon(CShaker * I, int atom0, int atom1, int atom2, int atom3, int type)
{
ShakerTorsCon *stc;
VLACheck(I->TorsCon, ShakerTorsCon, I->NTorsCon);
stc = I->TorsCon + I->NTorsCon;
stc->at0 = atom0;
stc->at1 = atom1;
stc->at2 = atom2;
stc->at3 = atom3;
stc->type = type;
I->NTorsCon++;
}
void ShakerAddPlanCon(CShaker * I, int atom0, int atom1, int atom2, int atom3,
float target, int fixed)
{
ShakerPlanCon *spc;
VLACheck(I->PlanCon, ShakerPlanCon, I->NPlanCon);
spc = I->PlanCon + I->NPlanCon;
spc->at0 = atom0;
spc->at1 = atom1;
spc->at2 = atom2;
spc->at3 = atom3;
spc->fixed = fixed;
spc->target = target;
I->NPlanCon++;
}
void ShakerAddLineCon(CShaker * I, int atom0, int atom1, int atom2)
{
ShakerLineCon *slc;
VLACheck(I->LineCon, ShakerLineCon, I->NLineCon);
slc = I->LineCon + I->NLineCon;
slc->at0 = atom0;
slc->at1 = atom1;
slc->at2 = atom2;
I->NLineCon++;
}
void ShakerFree(CShaker * I)
{
VLAFreeP(I->PlanCon);
VLAFreeP(I->PyraCon);
VLAFreeP(I->DistCon);
VLAFreeP(I->LineCon);
VLAFreeP(I->TorsCon);
OOFreeP(I);
}