20 #ifndef INCLUDED_core_scoring_sc_MolecularSurfaceCalculator_cc
21 #define INCLUDED_core_scoring_sc_MolecularSurfaceCalculator_cc
32 #include <numeric/xyzVector.hh>
33 #include <numeric/NumericTraits.hh>
36 #include <utility/vector1.hh>
37 #include <utility/exit.hh>
38 #include <utility/io/izstream.hh>
39 #include <basic/Tracer.hh>
40 #include <basic/database/open.hh>
53 static basic::Tracer
TR(
"core.scoring.sc.MolecularSurfaceCalculator");
84 run_.results.valid = 0;
121 for(std::vector<Atom>::iterator a =
run_.atoms.begin(); a <
run_.atoms.end(); ++a) {
122 a->neighbors.clear();
129 run_.dots[0].clear();
130 run_.dots[1].clear();
132 memset(&
run_.results, 0,
sizeof(
run_.results));
133 memset(&
run_.prevp, 0,
sizeof(
run_.prevp));
158 TR.Error <<
"Jump ID out of bounds (pose has " << pose.
num_jump() <<
" jumps)" << std::endl;
163 ObjexxFCL::FArray1D_bool is_upstream ( pose.
total_residue(), true );
191 basic::gpu::Timer timer(
TR.Debug);
193 run_.results.valid = 0;
195 if(
run_.atoms.empty())
206 TR.Error <<
"Failed: " << e.
error << std::endl;
220 if(
run_.atoms.empty())
226 TR.Debug <<
"Generating molecular surface, " <<
settings.density <<
" dots/A^2" << std::endl;
229 if(
TR.Debug.visible())
231 TR.Debug <<
" Buried atoms (1): " <<
run_.results.surface[0].nBuriedAtoms << std::endl;
232 TR.Debug <<
" Buried atoms (2): " <<
run_.results.surface[1].nBuriedAtoms << std::endl;
233 TR.Debug <<
" Blocked atoms (1): " <<
run_.results.surface[0].nBuriedAtoms << std::endl;
234 TR.Debug <<
" Blocked atoms (2): " <<
run_.results.surface[1].nBuriedAtoms << std::endl;
235 TR.Debug <<
" Convex dots: " <<
run_.results.dots.convex << std::endl;
236 TR.Debug <<
" Toroidal dots: " <<
run_.results.dots.toroidal << std::endl;
237 TR.Debug <<
" Concave dots: " <<
run_.results.dots.concave << std::endl;
238 TR.Debug <<
"Total surface dots (1): " <<
run_.dots[0].size() << std::endl;
239 TR.Debug <<
"Total surface dots (2): " <<
run_.dots[1].size() << std::endl;
240 TR.Debug <<
" Total surface dots: " << (
run_.dots[0].size()+
run_.dots[1].size()) << std::endl;
253 char const *fn =
"scoring/score_functions/sc/sc_radii.lib";
255 utility::io::izstream in;
257 if(!basic::database::open(in, fn)) {
258 TR.Error <<
"Failed to read " << fn << std::endl;
265 memset(&radius, 0,
sizeof(radius));
267 TR.Trace <<
"Atom Radius: " << radius.
residue <<
", " << radius.
atom <<
", " << radius.
radius << std::endl;
272 TR.Trace <<
"Atom radii read: " <<
radii_.size() << std::endl;
339 molecule = (molecule == 1);
344 run_.atoms.push_back(atom);
345 ++
run_.results.surface[molecule].nAtoms;
352 TR.Warning <<
"Failed to assign atom radius for residue "
354 <<
". Skipping atom!" << std::endl;
366 std::vector<ATOM_RADIUS>::const_iterator radius;
369 for(radius =
radii_.begin(); radius !=
radii_.end(); ++radius) {
372 atom.
radius = radius->radius;
387 if((*pattern !=
'*') && (*r != *pattern) && !(*r ==
' ' && !*pattern))
399 std::vector<Atom>::iterator pAtom;
401 for(pAtom = atoms.begin(); pAtom < atoms.end(); ++pAtom)
404 ++
run_.results.surface[pAtom->molecule].nBuriedAtoms;
421 for(std::vector<Atom>::const_iterator pAtom1 =
run_.atoms.begin(); pAtom1 <
run_.atoms.end(); ++pAtom1) {
422 if(pAtom1->radius >
run_.radmax)
423 run_.radmax = pAtom1->radius;
427 for(std::vector<Atom>::iterator pAtom1 =
run_.atoms.begin(); pAtom1 <
run_.atoms.end(); ++pAtom1) {
428 Atom &atom1 = *pAtom1;
473 return d1 < d2 ? -1: (d2 > d1 ? 1 : 0);
496 std::vector<Atom>::iterator iAtom2;
497 std::vector<Atom*> &neighbors = atom1.
neighbors;
503 for(iAtom2 =
run_.atoms.begin(); iAtom2 <
run_.atoms.end(); ++iAtom2) {
504 Atom &atom2 = *iAtom2;
505 if(atom1 == atom2 || atom2.
atten <= 0)
510 d2 = atom1.distance_squared(atom2);
518 if (d2 >= bridge * bridge)
521 neighbors.push_back(&atom2);
528 d2 = atom1.distance_squared(atom2);
533 if (d2 >= bridge * bridge)
536 atom1.
buried.push_back(&atom2);
543 if(neighbors.empty()) {
550 return neighbors.size();
557 ScValue erj, eri, rij, dij, asymm, _far_, contain;
559 std::vector<Atom*> &neighbors = atom1.
neighbors;
563 for(std::vector<Atom*>::iterator iAtom2 = neighbors.begin(); iAtom2 < neighbors.end(); ++iAtom2) {
564 Atom &atom2 = **iAtom2;
571 dij = atom1.distance(atom2);
573 uij = (atom2 - atom1) / dij;
574 asymm = (eri * eri - erj * erj) / dij;
575 between = (
ABS(asymm) < dij);
577 tij = ((atom1 + atom2) * 0.5f) + (uij * (asymm * 0.5f));
579 _far_ = (eri + erj) * (eri + erj) - dij * dij;
589 contain = sqrt(contain);
590 rij = 0.5 * _far_ * contain / dij;
592 if (neighbors.size() <= 1) {
615 std::vector<Atom*> &neighbors = atom1.
neighbors;
616 ScValue eri, erj, erk, djk, dik;
617 ScValue asymm, dt, dtijk2, hijk, isign, wijk, swijk, rkp2;
619 Vec3 uik, dijk, pijk, utb, iujk, tv, tik, bijk, uijk;
624 for(std::vector<Atom*>::iterator iAtom3 = neighbors.begin();
625 iAtom3 < neighbors.end(); ++iAtom3) {
626 Atom &atom3 = **iAtom3;
631 djk = atom2.distance(atom3);
635 dik = atom1.distance(atom3);
642 uik = (atom3 - atom1) / dik;
647 if(dt >= 1.0 || dt <= -1.0 || wijk <= 0.0 || swijk <= 0.0) {
649 dtijk2 = tij.distance(atom3);
650 rkp2 = erk * erk - rij * rij;
657 uijk = uij.cross(uik) / swijk;
658 utb = uijk.cross(uij);
659 asymm = (eri*eri - erk*erk) / dik;
660 tik = (atom1 + atom3)*0.5f + uik*asymm*0.5f;
664 tv.x(uik.x() * tv.x());
665 tv.y(uik.y() * tv.y());
666 tv.z(uik.z() * tv.z());
668 dt = tv.x() + tv.y() + tv.z();
669 bijk = tij + utb * dt / swijk;
670 hijk = eri*eri - bijk.distance_squared(atom1);
676 for(is0 = 1; is0 <= 2; ++is0) {
678 pijk = bijk + uijk * hijk * isign;
697 probe.
alt = uijk * isign;
698 run_.probes.push_back(probe);
714 std::vector<Atom*>
const &atoms)
716 for(std::vector<Atom*>::const_iterator ineighbor = atoms.begin();
717 ineighbor < atoms.end(); ++ineighbor) {
718 Atom const &neighbor = **ineighbor;
719 if(&atom1 == &neighbor || &atom2 == &neighbor)
721 if(pijk.distance_squared(neighbor) <= pow(neighbor.
radius +
settings.rp, 2))
731 std::vector<Atom*>
const &neighbors = atom1.
neighbors;
732 Atom const * neighbor;
734 Vec3 south(0, 0, -1);
736 Vec3 vtemp, vql, uij, tij, pij, cen, pcen;
737 ScValue dt, erj, dij, eri, _far_, contain;
738 ScValue area, asymm, cs, ps, rad, ri, rij, rj;
743 if(!neighbors.empty()) {
745 neighbor = neighbors[0];
747 north = atom1 - *neighbor;
750 vtemp.x(north.y()*north.y() + north.z()*north.z());
751 vtemp.y(north.x()*north.x() + north.z()*north.z());
752 vtemp.z(north.x()*north.x() + north.y()*north.y());
755 dt = vtemp.dot(north);
757 vtemp =
Vec3(1, 0, 0);
759 eqvec = north.cross(vtemp);
761 vql = eqvec.cross(north);
763 rj = neighbor->radius;
764 erj = neighbor->radius +
settings.rp;
765 dij = atom1.distance(*neighbor);
766 uij = (*neighbor - atom1) / dij;
768 asymm = (eri*eri - erj*erj) / dij;
769 tij = ((atom1 + *neighbor) * 0.5f) + (uij * (asymm * 0.5f));
770 _far_ = pow(eri + erj, 2) - dij*dij;
775 contain = pow(dij, 2) - pow(ri - rj, 2);
778 contain = sqrt(contain);
779 rij = 0.5 * _far_ * contain / dij;
780 pij = tij + (vql * rij);
781 south = (pij - atom1) / eri;
783 if(north.cross(south).dot(eqvec) <= 0.0)
788 std::vector<Vec3> lats;
790 cs =
SubArc(o, ri, eqvec, atom1.
density, north, south, lats);
796 std::vector<Vec3> points;
797 for(std::vector<Vec3>::iterator ilat = lats.begin(); ilat < lats.end(); ++ilat) {
798 dt = ilat->dot(north);
799 cen = atom1 + (north*dt);
811 for(std::vector<Vec3>::iterator point = points.begin();
812 point < points.end(); ++point) {
814 pcen = atom1 + ((*point - atom1) * (eri/ri));
821 ++
run_.results.dots.convex;
831 std::vector<Atom*>
const &atoms)
833 for(std::vector<Atom*>::const_iterator ineighbor = atoms.begin()+1;
834 ineighbor < atoms.end(); ++ineighbor) {
835 if(pcen.distance(**ineighbor) <= ((*ineighbor)->radius +
settings.rp))
851 std::vector<Atom*> &neighbors = atom1.
neighbors;
852 ScValue density, rb, rci, rcj, rs, e, edens, eri, erj, erl, dtq, pcusp, dt, ts, ps, area;
853 Vec3 pi, pj, axis, dij, pqi, pqj, qij, qjk, qj;
855 std::vector<Vec3> subs;
864 rci = rij * atom1.
radius / eri;
865 rcj = rij * atom2.
radius / erj;
871 rs = (rci + 2 * rb + rcj) / 4;
875 ts =
SubCir(tij, rij, uij, edens, subs);
879 for(std::vector<Vec3>::iterator isub = subs.begin(); isub < subs.end(); ++isub) {
885 for(std::vector<Atom*>::iterator ineighbor = neighbors.begin();
886 !tooclose && ineighbor < neighbors.end() && !tooclose;
888 Atom const &neighbor = **ineighbor;
889 if(atom2 == neighbor)
892 d2 = sub.distance_squared(neighbor);
893 tooclose = d2 < (erl * erl);
906 pi = (atom1 - pij) / eri;
907 pj = (atom2 - pij) / erj;
911 dtq = pow(
settings.rp, 2) - pow(rij, 2);
912 pcusp = dtq > 0 && between;
916 qij = tij - uij * dtq;
917 qjk = tij + uij * dtq;
929 if(dt >= 1.0 || dt <= -1.0)
934 if(dt >= 1.0 || dt <= -1.0)
940 std::vector<Vec3> points;
942 for(std::vector<Vec3>::iterator point = points.begin(); point < points.end(); ++point) {
944 ++
run_.results.dots.toroidal;
950 std::vector<Vec3> points;
952 for(std::vector<Vec3>::iterator point = points.begin(); point < points.end(); ++point) {
954 ++
run_.results.dots.toroidal;
965 std::vector<PROBE const *> lowprobs, nears;
968 for(std::vector<PROBE>::iterator probe =
run_.probes.begin();
969 probe <
run_.probes.end(); ++probe) {
971 lowprobs.push_back(&(*probe));
974 for(std::vector<PROBE>::iterator probe =
run_.probes.begin();
975 probe <
run_.probes.end(); ++probe) {
977 if( probe->pAtoms[0]->atten ==
ATTEN_6 &&
978 probe->pAtoms[1]->atten ==
ATTEN_6 &&
979 probe->pAtoms[2]->atten ==
ATTEN_6) {
983 Vec3 &pijk = probe->point, &uijk = probe->alt;
986 probe->pAtoms[0]->density +
987 probe->pAtoms[1]->density +
988 probe->pAtoms[2]->density ) / 3;
992 for(std::vector<PROBE const *>::const_iterator lprobe = lowprobs.begin();
993 lprobe < lowprobs.end(); ++lprobe) {
994 if(&(*probe) == *lprobe)
997 ScValue d2 = pijk.distance_squared((*lprobe)->point);
1001 nears.push_back(*lprobe);
1005 Vec3 vp[3], vectors[3];
1006 for(
int i = 0; i < 3; ++i) {
1007 vp[i] = *(probe->pAtoms[i]) - pijk;
1012 vectors[0] = vp[0].cross(vp[1]);
1013 vectors[1] = vp[1].cross(vp[2]);
1014 vectors[2] = vp[2].cross(vp[0]);
1015 vectors[0].normalize();
1016 vectors[1].normalize();
1017 vectors[2].normalize();
1022 for(
int i = 0; i < 3; ++i) {
1032 Vec3 axis = vp[mm].cross(south);
1035 std::vector<Vec3> lats;
1043 std::vector<Vec3> points;
1044 for(std::vector<Vec3>::iterator ilat = lats.begin();
1045 ilat < lats.end(); ++ilat) {
1049 dt = ilat->dot(south);
1051 rad = pow(
settings.rp, 2) - pow(dt, 2);
1057 ps =
SubCir(cen, rad, south, density, points);
1063 for(std::vector<Vec3>::iterator point = points.begin();
1064 point < points.end(); ++point) {
1067 for(
int i = 0; i < 3; ++i) {
1068 ScValue dt = point->dot(vectors[i]);
1079 if((hijk <
settings.rp && !nears.empty()) &&
1086 for(
int i = 0; i < 3; ++i) {
1087 ScValue d = point->distance(*(probe->pAtoms[i])) -
1088 probe->pAtoms[i]->radius;
1096 ++
run_.results.dots.concave;
1097 AddDot(probe->pAtoms[mc]->molecule, 3, *point, area, pijk, *probe->pAtoms[mc]);
1107 std::vector<PROBE const *>
const nears,
1110 for(std::vector<const PROBE*>::const_iterator _near_ = nears.begin();
1111 _near_ < nears.end(); ++_near_) {
1112 if(point.distance_squared((*_near_)->point) < r2)
1128 DOT dot = { coor,
Vec3(), area, 0, type, &atom };
1133 dot.
outnml = coor - atom;
1135 dot.
outnml = (pcen - coor) / pradius;
1140 if(pcen.distance_squared(
run_.prevp) <= 0.0) {
1147 for(std::vector<Atom*>::const_iterator iNeighbor = atom.buried.begin();
1148 iNeighbor < atom.buried.end();
1150 erl = (*iNeighbor)->radius + pradius;
1151 ScValue d = pcen.distance_squared(**iNeighbor);
1163 run_.dots[molecule].push_back(dot);
1173 Vec3 vec = pnt - cen;
1175 ScValue d2 = vec.magnitude_squared() - pow(dt, 2);
1176 return d2 < 0.0 ? 0.0 : sqrt(d2);
1187 std::vector<Vec3> &points)
1196 angle = atan2(dt2, dt1);
1199 angle = angle + 2*
PI;
1201 return SubDiv(cen, rad, x, y, angle, density, points);
1212 std::vector<Vec3> &points)
1217 delta = 1.0 / (sqrt(density) * rad);
1227 points.push_back(
Vec3(cen + x*c + y*s));
1230 if (a + delta < angle)
1233 if (!points.empty())
1234 ps = rad * angle / points.size();
1247 std::vector<Vec3> &points)
1252 v1.x(pow(axis.y(), 2) + pow(axis.z(), 2));
1253 v1.y(pow(axis.x(), 2) + pow(axis.z(), 2));
1254 v1.z(pow(axis.x(), 2) + pow(axis.y(), 2));
1258 if(
ABS(dt) > 0.99) {
1264 v2 = axis.cross(v1);
1270 return SubDiv(cen, rad, x, y, 2.0 *
PI, density, points);
1300 #endif // INCLUDED_core_scoring_sc_MolecularSurfaceCalculator_cc