Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PDB.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 /* */
3 /* ---- SPARTA ---- */
4 /* Shifts Prediction from Analogue of Residue type and Torsion Angle */
5 /* Yang Shen and Ad Bax */
6 /* J. Biomol. NMR, 38, 289-302 (2007) */
7 /* NIH, NIDDK, Laboratory of Chemical Physics */
8 /* version, 1.00 (build 2010.0607.00) */
9 /* */
10 /* for any problem, please contact */
11 /* shenyang@niddk.nih.gov */
12 /* */
13 /******************************************************************************/
14 
15 // 01/25/2007, fix the probelm of missed ring atoms for ring current shifts calculation
16 #include <boost/unordered_map.hpp>
17 #include <protocols/sparta/PDB.hh>
18 #include <fstream>
19 // AUTO-REMOVED #include <cmath>
20 #include <sstream>
21 #include <core/pose/Pose.hh>
22 // AUTO-REMOVED #include <utility/exit.hh>
23 // Utility headers
24 #include <basic/Tracer.hh>
25 #include <protocols/sparta/util.hh>
27 
28 #include <utility/vector0.hh>
29 #include <utility/vector1.hh>
30 
31 #include <numeric/NumericTraits.hh>
32 
33 namespace protocols {
34 namespace sparta {
35 
36 static basic::Tracer tr("protocols.sparta");
37 using namespace core;
38 
39 using namespace std;
40 
42 {
43  r1 = 9999; rN = -9999;
44 }
45 
46 
47 PDB::PDB(const string &fileName)
48 {
49  PDBfileName = fileName;
50 
51  r1 = 9999; rN = -9999;
52 
53  loadPDB(fileName);
54 }
55 
56 
57 string PDB::getField(const string &str, int index)
58 {
59  switch(index)
60  {
61  case 1: return str.substr(0,6); //"ATOM"
62  case 2: return str.substr(6,5); //Atom number
63  case 3: return str.substr(11,5); //Atom name
64  case 4: return str.substr(17,4); //Residue name
65  case 5: return str.substr(21,1); //Chain ID
66  case 6: return str.substr(22,4); //Reside seq
67  case 7: return str.substr(30,8); //X
68  case 8: return str.substr(38,8); //Y
69  case 9: return str.substr(46,8); //Z
70  case 10: return str.substr(54,6); //Occupancy
71  case 11: return str.substr(60,6); // B-factor
72  }
73 
74  return NULL;
75 }
76 
77 
78 void PDB::loadPDB_Entry(const string &str, PDB_Entry &entry)
79 {
80  entry.atomNum = atoi( getField(str,2).c_str() );
81 
82  string atomName = simplifyWhiteSpace( getField(str,3).c_str() );
83  entry.atomName = atomName;
84  if ( atomName == "H" ) entry.atomName="HN";
85  if ( atomName[0] >= '1' && atomName[0] <= '3' ) entry.atomName = atomName.substr(1,4) + atomName[0];
86 
87  // remove the charge character '+'
88  entry.resName = simplifyWhiteSpace( getField(str,4).substr(0,3).c_str() );
89  entry.chainName = getField(str,5);
90  entry.resNum = atoi( getField(str,6).c_str() );
91  entry.X = atof( getField(str,7).c_str() );
92  entry.Y = atof( getField(str,8).c_str() );
93  entry.Z = atof( getField(str,9).c_str() );
94  entry.B_Factor = atof( getField(str,11).c_str() );;
95 
96  entry.Coord[0] = entry.X;
97  entry.Coord[1] = entry.Y;
98  entry.Coord[2] = entry.Z;
99 }
100 
101 void PDB::loadPDB(const string &fileName)
102 {
103  PDBfileName = fileName;
104 
105  ifstream file(fileName.c_str());
106  if (! file.is_open() ) {
107  tr.Error << "\tCan't open file " << fileName << " for reading" << endl;
108  exit(0);
109  }
110 
111  loadPDB( file );
112 }
113 
114 void PDB::loadPDB( core::pose::Pose const& pose ) {
115  std::stringstream obuffer;
116  pose.dump_pdb( obuffer, "no_tag" );
117  std::stringstream ibuffer( obuffer.str() );
118  loadPDB( ibuffer );
119 }
120 
121 void PDB::loadPDB(istream &file) {
122 
123  residList.clear();
124  residListOne.clear();
125  ATOMS.clear();
126  Conformers.clear();
127 
128  acceptorList.clear();
129  donorList.clear();
130  HBDistList.clear();
131 
132  int residue_offset = 0;
133  Mol conformer;
134  int conformer_count=1;
135  int lastline_index = 0;
136 
137  while (!file.eof() ) {
138  char buf[1000];
139  file.getline(buf, 1000);
140  string str(buf);
141  if ( str.empty() || str.size() == 0 ) continue;
142  int pos = str.find("ATOM"); //starting of one molecule
143  int pos2 = str.find("TER"), pos3 = str.find("END"); //ending of one molecule
144  if ( pos != 0 && pos2 != 0 && pos3 != 0 ) continue;
145 
146  if ( pos2 == 0 || pos3 == 0) { // this part has never been executed
147  Conformers[conformer_count] = conformer;
148  conformer_count++;
149  conformer.clear();
150  break;
151  // continue;
152  }
153 
154  PDB_Entry temp;
155  loadPDB_Entry(str, temp);
156 
157  if ( lastline_index>1 && temp.chainName != conformer[lastline_index].chainName ) residue_offset = conformer[lastline_index].resNum-temp.resNum+1;
158  //to modify the resNum if more than one chain
159  temp.resNum = temp.resNum + residue_offset;
160 
161  conformer[temp.atomNum] = temp; // table indexed by the atom number
162  lastline_index = temp.atomNum;
163  // tr.Trace << "resNum : "<< temp.resNum << std::endl;
164  // std::cout << "resNum: " << conformer[lastline_index].resNum<<std::endl;
165  ATOMS[conformer_count][temp.resNum][temp.atomName] = temp;
166  // table indexed by the residue number and atom name
167  // fast for obtaining a specific atom with given residue number and atom name
168 
169  residList[temp.resNum] = temp.resName; //resdiue list with three-letter-aa name
170  residListOne[temp.resNum] = getOneAAName(temp.resName); //resdiue list with one-letter-aa name
171 
172  // std::cout << "resNum: to check r1 rN: " << temp.resNum << " r1: " << r1 << " rN: " << rN << std::endl;
173  if ( temp.resNum < r1 ) r1 = temp.resNum;
174  if ( temp.resNum > rN ) rN = temp.resNum;
175  }
176 
177  if(conformer.size() != 0) Conformers[conformer_count] = conformer;
178 
179  //correction of the name cys/CYS accoding to the status of the disulfide bond
180  std::map<int, string> ::iterator it;
181  for ( it=residListOne.begin(); it!=residListOne.end(); it++ ) {
182  if ( it->second == "C" ) {
183  if ( isSSBonded(1, it->first) ) {
184  residListOne[it->first] = "c";
185  residList[it->first] = "cys";
186  }
187  }
188  }
189 }
190 
191 
192 bool PDB::isSSBonded(int /*conformerID*/, int resNum)
193 {
194  if( residListOne[resNum] != "C" && residListOne[resNum] != "c" ) return false;
195 
196  PDB_Entry CYS_SG = getEntry(1,resNum, "SG");
197 
198  std::map<int, string>::iterator it;
199  for ( it = residListOne.begin(); it != residListOne.end(); it++ )
200  {
201  if( (it->second == "C" || it->second == "c") && abs(it->first - resNum) >= 4 )
202  if( getDist(CYS_SG.Coord, ATOMS[1][it->first]["SG"].Coord ) <= 2.5 )
203  return true;
204  }
205 
206  return false;
207 }
208 
209 
210 
211 PDB_Entry PDB::getEntry(int conformerID, int rNum, const string &aName)
212 {
213  return ATOMS[conformerID][rNum][aName];
214 }
215 
216 
217 
218 PDB_Entry PDB::getEntry(int conformerID, int aNum)
219 {
220  return Conformers[conformerID][aNum];
221 }
222 
223 
225 {
226  Vec3 v,v1,v2;
227 
228  Vec3Copy(v,B); Vec3Copy(v1,A); Vec3Copy(v2,C);
229  Vec3Sub(v1,v); // vector BA
230  Vec3Sub(v2,v); // vector BC
231 
232  Vec3Norm(v1); // unit vector BA
233  Vec3Norm(v2); // unit vector BC
234 
235  float c = Vec3Scalar(v1, v2); // scalar products
236  Vec3Cross(v1, v2); // cross product
237  float s = Vec3Abs(v1);
238 
239  return atan2f(s, c)*180.0/numeric::NumericTraits<Real>::pi();
240 }
241 
242 
244 {
245  return getBondAngle(a.Coord, b.Coord, c.Coord);
246 }
247 
248 
250 {
251  double cb[3], n1[3], n2[3];
252  float co;
253  double TEMP, TEMP1, TEMP2, TEMP3, TEMP4, TEMP5;
254 
255  if( (a.atomName).empty() || (b.atomName).empty() || (c.atomName).empty() || (d.atomName).empty() )
256  return SPARTA_MAXNUM;
257 
258  cb[0] = c.X - b.X; cb[1] = c.Y - b.Y; cb[2] = c.Z - b.Z; // vector b->c
259  n1[0] = (b.Y - a.Y) * cb[2] + (a.Z - b.Z) * cb[1]; //normal vector of plane a-b-c
260  n1[1] = (b.Z - a.Z) * cb[0] + (a.X - b.X) * cb[2];
261  n1[2] = (b.X - a.X) * cb[1] + (a.Y - b.Y) * cb[0];
262  n2[0] = cb[1] * (d.Z - c.Z) + cb[2] * (c.Y - d.Y); //normal vector of plane b-c-d
263  n2[1] = cb[2] * (d.X - c.X) + cb[0] * (c.Z - d.Z);
264  n2[2] = cb[0] * (d.Y - c.Y) + cb[1] * (c.X - d.X);
265  TEMP = n1[0]; TEMP1 = n1[1]; TEMP2 = n1[2];
266  TEMP3 = n2[0]; TEMP4 = n2[1]; TEMP5 = n2[2];
267  co = (float)((n1[0] * n2[0] + n1[1] * n2[1] + n1[2] * n2[2]) /
268  sqrt( (TEMP*TEMP + TEMP1*TEMP1 + TEMP2*TEMP2)*(TEMP3*TEMP3 + TEMP4*TEMP4 + TEMP5*TEMP5) ) );
269  // cos(a-b-c-d) = |n1.n2|/|n1|.|n2|
270 
271  return 180./numeric::NumericTraits<Real>::pi()*(arccos_(co)*
272  sgn( (float)( (n1[1]*n2[2] - n1[2]*n2[1])*cb[0] + (n1[2]*n2[0] - n1[0]*n2[2])*cb[1] + (n1[0]*n2[1] - n1[1]*n2[0])*cb[2]) ) );
273 }
274 
275 
276 float PDB::getPhi(int conformerID, int resNum)
277 {
278  return getDihedralAngle(getEntry(conformerID,resNum-1,"C"), \
279  getEntry(conformerID,resNum,"N"), \
280  getEntry(conformerID,resNum,"CA"), \
281  getEntry(conformerID,resNum,"C") );
282 }
283 
284 
285 float PDB::getPsi(int conformerID, int resNum)
286 {
287  return getDihedralAngle(getEntry(conformerID,resNum,"N"), \
288  getEntry(conformerID,resNum,"CA"), \
289  getEntry(conformerID,resNum,"C"), \
290  getEntry(conformerID,resNum+1,"N") );
291 }
292 
293 
294 float PDB::getOmega(int conformerID, int resNum)
295 {
296  return getDihedralAngle(getEntry(conformerID,resNum-1,"CA"), \
297  getEntry(conformerID,resNum-1,"C"), \
298  getEntry(conformerID,resNum,"N"), \
299  getEntry(conformerID,resNum,"CA"));
300 }
301 
302 
303 float PDB::getChi1(int conformerID, int resNum)
304 {
305  string rName = residList[resNum];
306 
307  PDB_Entry R;
308  if( rName == "GLY" || rName == "ALA" )
309  return SPARTA_MAXNUM;
310  else if( rName == "VAL" )
311  R = getEntry(conformerID,resNum,"CG2");
312  else if( rName == "ILE" )
313  R = getEntry(conformerID,resNum,"CG1");
314  else if( rName == "THR" )
315  R = getEntry(conformerID,resNum,"OG1");
316  else if( rName == "SER" )
317  R = getEntry(conformerID,resNum,"OG" );
318  else if( rName == "CYS" || rName == "cys")
319  R = getEntry(conformerID,resNum,"SG" );
320  else
321  R = getEntry(conformerID,resNum,"CG" );
322 
323  return getDihedralAngle(getEntry(conformerID,resNum,"N"), \
324  getEntry(conformerID,resNum,"CA"), \
325  getEntry(conformerID,resNum,"CB"), R);
326 }
327 
328 
329 float PDB::getChi2(int conformerID, int resNum)
330 {
331  string rName = residList[resNum];
332  if( rName.compare("GLY") == 0 || rName.compare("ALA") == 0)
333  return SPARTA_MAXNUM;
334 
335  PDB_Entry R3, R4;
336 
337  if( rName == "VAL" ){ //chi21
338  R3 = getEntry(conformerID,resNum,"CG1");
339  R4 = getEntry(conformerID,resNum,"HG11");
340  }
341  else if( rName == "THR" ) {
342  R3 = getEntry(conformerID,resNum,"CG2");
343  R4 = getEntry(conformerID,resNum,"HG21");
344  }
345  else if( rName == "SER" ) {
346  R3 = getEntry(conformerID,resNum,"OG");
347  R4 = getEntry(conformerID,resNum,"HG");
348  }
349  else if( rName == "ILE" ) { //chi21
350  R3 = getEntry(conformerID,resNum,"CG1" );
351  R4 = getEntry(conformerID,resNum,"CD1" );
352  }
353  else if( rName == "CYS" || rName == "cys") {
354  R3 = getEntry(conformerID,resNum,"SG" );
355  R4 = getEntry(conformerID,resNum,"HG" );
356  }
357  else
358  R3 = getEntry(conformerID,resNum,"CG" );
359 
360  if( rName == "ASN" || rName == "ASP" ) R4 = getEntry(conformerID,resNum,"OD1" );
361  else if( rName == "HIS" ) R4 = getEntry(conformerID,resNum,"ND1" );
362  else if( rName == "MET" ) R4 = getEntry(conformerID,resNum,"SD" );
363  else if( rName == "LEU" || rName == "PHE" || rName == "TYR" || rName == "TRP" )
364  R4 = getEntry(conformerID,resNum,"CD1" );
365  else R4 = getEntry(conformerID,resNum,"CD" );
366 
367  return getDihedralAngle(getEntry(conformerID,resNum,"CA"),getEntry(conformerID,resNum,"CB"),R3, R4);
368 }
369 
370 
371 string PDB::getThreeAAName(char a)
372 {
373  switch(a)
374  {
375  case 'A': return "ALA";
376  case 'C': return "CYS";
377  case 'c': return "cys";
378  case 'D': return "ASP";
379  case 'E': return "GLU";
380  case 'F': return "PHE";
381  case 'G': return "GLY";
382  case 'H': return "HIS";
383  case 'I': return "ILE";
384  case 'K': return "LYS";
385  case 'L': return "LEU";
386  case 'M': return "MET";
387  case 'N': return "ASN";
388  case 'P': return "PRO";
389  case 'Q': return "GLN";
390  case 'R': return "ARG";
391  case 'S': return "SER";
392  case 'T': return "THR";
393  case 'V': return "VAL";
394  case 'W': return "TRP";
395  case 'Y': return "TYR";
396  }
397 
398  return "???";
399 }
400 
401 
402 
403 string PDB::getOneAAName(const string& a)
404 {
405  if( a == "ALA") return "A";
406  else if( a == "CYS") return "C";
407  else if( a == "cys") return "c";
408  else if( a == "ASP") return "D";
409  else if( a == "GLU") return "E";
410  else if( a == "PHE") return "F";
411  else if( a == "GLY") return "G";
412  else if( a == "HIS" || a == "HIS+") return "H";
413  else if( a == "ILE") return "I";
414  else if( a == "LYS" || a == "LYS+") return "K";
415  else if( a == "LEU") return "L";
416  else if( a == "MET") return "M";
417  else if( a == "ASN") return "N";
418  else if( a == "PRO") return "P";
419  else if( a == "GLN") return "Q";
420  else if( a == "ARG" || a == "ARG+") return "R";
421  else if( a == "SER") return "S";
422  else if( a == "THR") return "T";
423  else if( a == "VAL") return "V";
424  else if( a == "TRP") return "W";
425  else if( a == "TYR") return "Y";
426 
427  return "?";
428 }
429 
430 
431 //collet the ring information required for calculating Haigh-Mallion ring shifts
432 //Haigh, C.W. and Mallion, R.B. (1979) Progr. NMR Spectrosc., 13, 303-344
433 //Parameters are taken from Case, D.A. (1995) J. Biomol.NMR, 6, 341-346.
435 
436  Mol conf = Conformers[1];
437 
438  string PF6Atoms[6] = {"CG", "CD1", "CE1", "CZ", "CE2", "CD2" };
439  string W6Atoms[6] = {"CD2", "CE2", "CZ2", "CH2", "CZ3", "CE3" };
440  string H5Atoms[5] = {"CG", "ND1", "CE1", "NE2", "CD2" };
441  string W5Atoms[5] = {"CG", "CD1", "NE1", "CE2", "CD2" };
442 
443  std::map<int, string>::iterator it;
444  Mol::iterator itA;
445 
446  int i;
447  RingNo = 0;
448 
449  for ( it = residList.begin(); it != residList.end(); it++ )
450  {
451  int resID = it->first; //.resNum;
452  string resName = it->second;
453 
454  if( resName == "PHE" || resName == "TYR" || resName == "TRP") // 6-member ring
455  {
456  Rings[RingNo].resID = resID; Rings[RingNo].resName = resName; Rings[RingNo].atomNo = 6;
457  if( resName == "PHE" ) Rings[RingNo].ringFact = 1.46;
458  if( resName == "TYR" ) Rings[RingNo].ringFact = 1.24;
459  if( resName == "TRP" ) Rings[RingNo].ringFact = 1.24;
460 
461  bool NO_MISSED_RING_ATOMS = true;
462 
463  for( i = 0; i < 6; i++ )
464  {
465  PDB_Entry atom;
466  if( resName == "PHE" || resName == "TYR")
467  {
468  atom = getEntry(1,resID,PF6Atoms[i]);
469  if( atom.atomName == PF6Atoms[i] )
470  Vec3Copy(Rings[RingNo].coordA[i], atom.Coord);
471  else NO_MISSED_RING_ATOMS = false; // missed ring atom in coordinates file
472  }
473  else if ( resName == "TRP")
474  {
475  atom = getEntry(1,resID,W6Atoms[i]);
476  if( atom.atomName == W6Atoms[i] )
477  Vec3Copy(Rings[RingNo].coordA[i], atom.Coord);
478  else NO_MISSED_RING_ATOMS = false; // missed ring atom in coordinates file
479  }
480  }
481 
482  if(NO_MISSED_RING_ATOMS) RingNo++;
483  }
484 
485  if( resName == "HIS" || resName == "TRP")
486  { // 5-member ring
487  Rings[RingNo].resID = resID; Rings[RingNo].resName = resName; Rings[RingNo].atomNo = 5;
488  if( resName == "HIS" ) Rings[RingNo].ringFact = 1.35;
489  if( resName == "TRP" ) Rings[RingNo].ringFact = 1.32;
490 
491  bool NO_MISSED_RING_ATOMS = true;
492 
493  for( i = 0; i < 5; i++ )
494  {
495  PDB_Entry atom;
496  if( resName == "HIS" )
497  {
498  atom = getEntry(1,resID,H5Atoms[i]);
499  if( atom.atomName == H5Atoms[i] )
500  Vec3Copy(Rings[RingNo].coordA[i], atom.Coord);
501  else NO_MISSED_RING_ATOMS = false; // missed ring atom in coordinates file
502  }
503  else if ( resName == "TRP" )
504  {
505  atom = getEntry(1,resID,W5Atoms[i]);
506  if( atom.atomName == W5Atoms[i] )
507  Vec3Copy(Rings[RingNo].coordA[i], atom.Coord);
508  else NO_MISSED_RING_ATOMS = false; // missed ring atom in coordinates file
509  }
510  }
511 
512  if(NO_MISSED_RING_ATOMS) RingNo++;
513  }
514  }
515 
516  for(i=0; i < RingNo; i++)
517  calcPlane(&Rings[i]);
518 }
519 
520 
521 //Calculate the parameters for a ring
523 {
524  Vec3 v1, v2;
525  int atomI;
526 
527  Vec3Zero(ringP->center);
528  for(atomI = 0; atomI < ringP->atomNo; atomI++)
529  Vec3Add(ringP->center, ringP->coordA[atomI]);
530  Vec3Scale(ringP->center, 1.0f/ringP->atomNo);
531 
532  Vec3Zero(ringP->norm);
533  ringP->rad = 0.0f;
534  Vec3Copy(v1, ringP->coordA[ringP->atomNo - 1]);
535  Vec3Sub(v1, ringP->center);
536  for(atomI = 0; atomI < ringP->atomNo; atomI++)
537  {
538  Vec3Copy(v2, ringP->coordA[atomI]);
539  Vec3Sub(v2, ringP->center);
540  ringP->rad += Vec3Abs(v2);
541  Vec3Cross(v1, v2);
542  Vec3Add(ringP->norm, v1);
543  Vec3Copy(v1, v2);
544  }
545  Vec3Norm(ringP->norm);
546  ringP->rad /= ringP->atomNo;
547 
548  /* transformation matrix ring plane -> x-y plane */
549  ringP->transM[0][2] = ringP->norm[0];
550  ringP->transM[1][2] = ringP->norm[1];
551  ringP->transM[2][2] = ringP->norm[2];
552 
553  /* vector orthgonal to norm */
554  if (ringP->norm[0] > 0.5f || ringP->norm[0] < -0.5f)
555  {
556  v1[0] = - ringP->norm[1];
557  v1[1] = ringP->norm[0];
558  v1[2] = 0.0f;
559  } else
560  {
561  v1[0] = 0.0f;
562  v1[1] = - ringP->norm[2];
563  v1[2] = ringP->norm[1];
564  }
565  Vec3Norm(v1);
566  ringP->transM[0][1] = v1[0];
567  ringP->transM[1][1] = v1[1];
568  ringP->transM[2][1] = v1[2];
569 
570  Vec3Cross(v1, ringP->norm);
571  ringP->transM[0][0] = v1[0];
572  ringP->transM[1][0] = v1[1];
573  ringP->transM[2][0] = v1[2];
574 }
575 
576 
577 
578 float PDB::getOrbitalShift(int conformerID, int resNum, const string &aName)
579 {
580  Vec3 v;
581 
582  Vec3Copy( v, getEntry(conformerID,resNum,aName).Coord );
583 
584  //cout << RingNo << " " << resNum << " " << aName << endl;
585 
586  float ringShiftSum = 0.0f;
587  //loop over all rings in protein
588  for(int i=0; i < RingNo; i++)
589  {
590  int atomNo, atomI;
591  Vec3 vt, v1, v2;
592  float area, r1, r2, g, b;
593 
594  //exclude the effects from aromatic rings themselves (except for HN atom)
595  if( Rings[i].resID == resNum && aName != "HN" ) continue;
596 
597  atomNo = Rings[i].atomNo;
598  g = 0.0f;
599 
600  //loop over all 6(or 5) atoms in a ring
601  for (atomI = 0; atomI < atomNo; atomI++)
602  {
603  Vec3Copy(v1, Rings[i].coordA[atomI]);
604  Vec3Copy(v2, Rings[i].coordA[(atomI + 1) % atomNo]);
605 
606  r1 = Vec3DiffAbs(v1, v);
607  r2 = Vec3DiffAbs(v2, v);
608 
609  Vec3Copy(vt, v);
610  Vec3Sub(vt, Rings[i].center);
611  Vec3Sub(v1, Rings[i].center);
612  Vec3Sub(v2, Rings[i].center);
613 
614  Mat3VecMult(vt, Rings[i].transM);
615  Mat3VecMult(v1, Rings[i].transM);
616  Mat3VecMult(v2, Rings[i].transM);
617  Vec3Sub(v1, vt);
618  Vec3Sub(v2, vt);
619 
620  area = v1[0] * v2[1] - v1[1] * v2[0];
621  g += area * (1.0f / (r1 * r1 * r1) + 1.0f / (r2 * r2 * r2));
622  //cout << atomI << " " << g << " ";
623  }
624 
625  g *= 0.5f;
626  b = (float) 5.4548e-6;
627 
628  ringShiftSum += Rings[i].ringFact * b * g;
629 
630  //if( Rings[i].ringFact * b * g *((float)-1.0e6) > 0.6)
631  // cout << ringShiftSum << " " << g << " " << Rings[i].resID << resNum << " " << aName << endl;
632  }
633 
634  //cout << ringShiftSum*((float)-1.0e6) << " " << resNum << " " << aName << endl;
635 
636  return ringShiftSum*((float)-1.0e6);
637 }
638 
639 
640 
642 {
643  return getDist(A.Coord, B.Coord);
644 }
645 
646 
647 
649 {
650  Vec3 v;
651 
652  Vec3Copy(v, B);
653  Vec3Sub(v, A);
654 
655  return Vec3Abs(v);
656 }
657 
658 
659 
660 void PDB::initHBond(float /*DIST*/, float /*ANGLE*/)
661 {
662  Mol conf = Conformers[1];
663  Mol::iterator it;
664 
665  acceptorList.clear();
666  donorList.clear();
667  HBDistList.clear();
668 
669  //retreive the donor and acceptor list from coordinates
670  for ( it = conf.begin(); it != conf.end(); it++ ) {
671  PDB_Entry a = isAcceptor(it->second);
672 
673  if( !(a.atomName.empty()) ) acceptorList[it->first] = a.atomNum;
674  else {
675  PDB_Entry temp = isDonor(it->second);
676  if(temp.atomName.empty()) continue;
677  donorList[it->first] = temp.atomNum;
678  }
679  }
680 
681 
682  boost::unordered_map<int, int>::iterator itA, itD;
683  for(itA = acceptorList.begin(); itA != acceptorList.end(); itA++ ) {//loop over acceptor list
684 
685  PDB_Entry A = conf[ itA->first ], A_Heavy = conf[ itA->second ];;
686 
687  //search for donors
688  for( itD = donorList.begin(); itD != donorList.end(); itD++ ) {
689 
690  PDB_Entry D = conf[ itD->first ], D_Heavy = conf[ itD->second ];
691 
692  if( abs( A.resNum - D.resNum) < 2) continue; //minimal 2 residues apart
693 
694  float D_ON = getDist(A,D_Heavy);
695  float D_CH = getDist(A_Heavy,D);
696  float D_OH = getDist(A,D);
697  float D_CN = getDist(A_Heavy,D_Heavy);
698 
699  if( D_OH > D_CN ) continue;
700 
701  float HBond_E = 332.0*0.42*0.20;
702  HBond_E *= ( 1.0/D_ON+1.0/D_CH-1.0/D_OH-1.0/D_CN );
703  //Kabsch, W. and Sander, C. (1983) Biopolymer, 22, 2577-2637.
704 
705  if( HBond_E < -0.5) //is a HB bond
706  {
707  if( HBDistList[A.resNum][A.atomName] == 0 || HBDistList[A.resNum][A.atomName] > D_OH || HBEnergyList[A.resNum][A.atomName] > HBond_E) {
708  HBDistList[A.resNum][A.atomName] = D_OH;
709  HB_DHO_AngleList[A.resNum][A.atomName] = getBondAngle(D_Heavy,D,A);
710  HB_HOA_AngleList[A.resNum][A.atomName] = getBondAngle(D,A,A_Heavy);
711  HBEnergyList[A.resNum][A.atomName] = HBond_E;
712  }
713  // keep the strongest Hbond
714 
715  if( HBDistList[D.resNum][D.atomName] == 0 || HBDistList[D.resNum][D.atomName] > D_OH || HBEnergyList[D.resNum][D.atomName] > HBond_E) {
716  HBDistList[D.resNum][D.atomName] = D_OH;
717  HB_DHO_AngleList[D.resNum][D.atomName] = getBondAngle(D_Heavy,D,A);
718  HB_HOA_AngleList[D.resNum][D.atomName] = getBondAngle(D,A,A_Heavy);
719  HBEnergyList[D.resNum][D.atomName] = HBond_E;
720 
721  }
722  // keep the strongest Hbond
723  }
724  }
725  }
726 
727 }
728 
729 
730 // must run initHBond() first
732 {
733  return HBDistList[D.resNum][D.atomName];
734 }
735 
736 
737 // must run initHBond() first
738 float PDB::getHBondDist(int resNum, string atomName)
739 {
740  return HBDistList[resNum][atomName];
741 }
742 
743 
744 
746 {
747  if(A.atomName == "O" || A.atomName == "OT1" || A.atomName == "OT2" ) return ATOMS[1][A.resNum]["C"];
748 
749  if(A.resName == "ASN" && A.atomName == "OD1") return ATOMS[1][A.resNum]["CG"];
750  if(A.resName == "ASP" && (A.atomName == "OD1" || A.atomName == "OD2") ) return ATOMS[1][A.resNum]["CG"];
751  if((A.resName == "CYS"||A.resName == "cys") && A.atomName == "SG") return ATOMS[1][A.resNum]["CB"];
752  if(A.resName == "GLN" && A.atomName == "OE1") return ATOMS[1][A.resNum]["CD"];
753  if(A.resName == "GLU" && (A.atomName == "OE1" || A.atomName == "OE2") ) return ATOMS[1][A.resNum]["CD"];
754  if(A.resName == "HIS" && (A.atomName == "ND1" || A.atomName == "NE2") ) return ATOMS[1][A.resNum]["CE1"]; // could be CG or CD2
755  if(A.resName == "MET" && A.atomName == "SD") return ATOMS[1][A.resNum]["CG"];
756  if(A.resName == "SER" && A.atomName == "OG") return ATOMS[1][A.resNum]["CB"];
757  if(A.resName == "THR" && A.atomName == "OG1") return ATOMS[1][A.resNum]["CB"];
758  if(A.resName == "TYR" && A.atomName == "OH") return ATOMS[1][A.resNum]["CZ"];
759 
760  return EMPTY;
761 }
762 
763 
765 {
766  if(D.atomName == "HN") return ATOMS[1][D.resNum]["N"];
767 
768  if(D.atomName.find("HA") != string::npos ) return ATOMS[1][D.resNum]["CA"];
769 
770  if(D.resName == "ARG") {
771  if(D.atomName == "HE") return ATOMS[1][D.resNum]["NE"];
772  if(D.atomName == "HH11" || D.atomName == "HH12") return ATOMS[1][D.resNum]["NH1"];
773  if(D.atomName == "HH21" || D.atomName == "HH22") return ATOMS[1][D.resNum]["NH2"];
774  }
775  if(D.resName == "ASP" && (D.atomName == "HD21" || D.atomName == "HD22") ) return ATOMS[1][D.resNum]["ND2"];
776  if( (D.resName == "CYS"||D.resName == "cys") && D.atomName == "HG" ) return ATOMS[1][D.resNum]["SG"];
777  if(D.resName == "GLU" && (D.atomName == "HE21" || D.atomName == "HE22") ) return ATOMS[1][D.resNum]["NE2"];
778  if(D.resName == "HIS") {
779  if(D.atomName == "HD1") return ATOMS[1][D.resNum]["ND1"];
780  if(D.atomName == "HE2") return ATOMS[1][D.resNum]["NE2"];
781  }
782  if(D.resName == "LYS" && (D.atomName == "HZ1" || D.atomName == "HZ2" || D.atomName == "HZ3") ) return ATOMS[1][D.resNum]["NZ"];
783  if(D.resName == "SER" && D.atomName == "HG" ) return ATOMS[1][D.resNum]["OG"];
784  if(D.resName == "THR" && D.atomName == "HG1" ) return ATOMS[1][D.resNum]["OG1"];
785  if(D.resName == "TRP" && D.atomName == "HE1" ) return ATOMS[1][D.resNum]["NE1"];
786  if(D.resName == "TYR" && D.atomName == "HH" ) return ATOMS[1][D.resNum]["OH"];
787 
788  return EMPTY;
789 }
790 
791 
792 
793 long PDB::sgn(float x)
794 {
795  return ((x >= 0.0) - (x < 0.0));
796 }
797 
798 
799 float PDB::arccos_(float x)
800 {
801  const Real SPARTA_PI = numeric::NumericTraits<Real>::pi();
802  if (x > 1.0) x = 1.0;
803  else if (x < -1.0) x = -1.0;
804 
805  if (fabs(x) >= 0.5) {
806  if (x > 0.0)
807  return atan(sqrt(1.0 - x * x) / x);
808  else
809  return (SPARTA_PI + atan(sqrt(1.0 - x * x) / x));
810  }
811  else
812  return (0.5 * SPARTA_PI - atan(x / sqrt(1.0 - x * x)));
813 }
814 
815 
817 {
818  for (int i = 0; i < 3; i++)
819  v[i] = 0.0f;
820 }
821 
822 
823 void PDB::Vec3Copy(Vec3 v1, Vec3 v2)
824 {
825  for (int i = 0; i < 3; i++)
826  v1[i] = v2[i];
827 }
828 
829 
831 {
832  return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
833 }
834 
835 
837 {
838  return sqrtf((v1[0] - v2[0]) * (v1[0] - v2[0]) +
839  (v1[1] - v2[1]) * (v1[1] - v2[1]) +
840  (v1[2] - v2[2]) * (v1[2] - v2[2]));
841 }
842 
843 
845 {
846  float a = Vec3Abs(v);
847  for(int i = 0; i < 3; i++)
848  v[i] /= a;
849 }
850 
851 
852 void PDB::Vec3Scale(Vec3 v, float s)
853 {
854  for(int i = 0; i < 3; i++)
855  v[i] *= s;
856 }
857 
858 
859 void PDB::Vec3Add(Vec3 v1, Vec3 v2)
860 {
861  for(int i = 0; i < 3; i++)
862  v1[i] += v2[i];
863 }
864 
865 
866 void PDB::Vec3Sub(Vec3 v1, Vec3 v2)
867 {
868  for(int i = 0; i < 3; i++)
869  v1[i] -= v2[i];
870 }
871 
872 
873 float PDB::Vec3Scalar(Vec3 v1, Vec3 v2)
874 {
875  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
876 }
877 
878 
880 {
881  Vec3 vRes;
882 
883  vRes[0] = v1[1] * v2[2] - v1[2] * v2[1];
884  vRes[1] = v1[2] * v2[0] - v1[0] * v2[2];
885  vRes[2] = v1[0] * v2[1] - v1[1] * v2[0];
886  Vec3Copy(v1, vRes);
887 }
888 
889 
891 {
892  Vec3 vRes;
893 
894  vRes[0] = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0];
895  vRes[1] = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1];
896  vRes[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2];
897 
898  for(int i = 0; i < 3; i++)
899  v[i] = vRes[i];
900 }
901 
902 
903 void PDB::Vec3ScaleAdd(Vec3 v1, float s, Vec3 v2)
904 {
905  int i;
906 
907  for (i = 0; i < 3; i++)
908  v1[i] += s * v2[i];
909 }
910 
911 
912 
913 
914 
915 
916 
917 
918 // void PDB::initSurface( float rad_sol )
919 // {
920 
921 // float SolventRad = 1.4f;
922 
923 
924 // VDW_RAD["H"] = 1.2; VDW_RAD["HN"] = 1.2;
925 
926 // VDW_RAD["N"] = 1.55; VDW_RAD["ND1"] = 1.55; VDW_RAD["ND2"] = 1.55; VDW_RAD["NE"] = 1.55; VDW_RAD["NE1"] = 1.55; VDW_RAD["NE2"] = 1.55;
927 // VDW_RAD["NH1"] = 1.55; VDW_RAD["NH2"] = 1.55; VDW_RAD["NZ"] = 1.55;
928 
929 // VDW_RAD["C"] = 2.3; //1.1 C-H bond-length + 1.2 H radius
930 // VDW_RAD["CO"] = 1.7;
931 // //VDW_RAD["C"] = 1.7; VDW_RAD["CA"] = 1.7; VDW_RAD["CB"] = 1.7; VDW_RAD["CG"] = 1.7; VDW_RAD["CG1"] = 1.7; VDW_RAD["CG2"] = 1.7;
932 // //VDW_RAD["CD"] = 1.7; VDW_RAD["CD1"] = 1.7; VDW_RAD["CD2"] = 1.7; VDW_RAD["CE"] = 1.7; VDW_RAD["CE1"] = 1.7; VDW_RAD["CE2"] = 1.7;
933 // //VDW_RAD["CZ"] = 1.7; VDW_RAD["CZ2"] = 1.7; VDW_RAD["CZ3"] = 1.7; VDW_RAD["CH2"] = 1.7;
934 
935 // VDW_RAD["O"] = 1.52; VDW_RAD["OD1"] = 1.52; VDW_RAD["OD2"] = 1.52;
936 // VDW_RAD["OG"] = 1.52; VDW_RAD["OG1"] = 1.52; VDW_RAD["OE1"] = 1.52; VDW_RAD["OE2"] = 1.52; VDW_RAD["OH"] = 1.52;
937 
938 // VDW_RAD["SG"] = 1.8; VDW_RAD["SD"] = 1.8;
939 
940 // SurfPrec = 3;
941 // SpherePointNo = 0;
942 
943 
944 // clock_t start, finish;
945 // start = clock();
946 
947 // //cout << "calculate surface points " << endl;
948 // SphereCalcPoints(SurfPrec, &SpherePoints, &SpherePointNo);
949 // finish = clock();
950 // tr.Info << "\t SphereCalcPoints() running time: " << (float)(finish - start)/ CLOCKS_PER_SEC << " seconds" << endl;
951 
952 // //cout << "find neighboring " << endl;
953 // start = clock();
954 // findNeighors( rad_sol);
955 // finish = clock();
956 // tr.Info << "\t findNeighors() running time: " << (float)(finish - start)/ CLOCKS_PER_SEC << " seconds" << endl;
957 
958 // //cout << "calculate surface " << endl;
959 // start = clock();
960 // calcSurface( rad_sol );
961 // finish = clock();
962 // tr.Info << "\t calcSurface() running time: " << (float)(finish - start)/ CLOCKS_PER_SEC << " seconds" << endl;
963 
964 // //for(int i = r1; i <= rN; i++){
965 // //cout << "resID: " << i << "\t" << SurfaceList[i] << endl;
966 // //}
967 
968 // }
969 
970 
971 void PDB::calcSurface( float rad_sol )
972 {
973  const Real SPARTA_PI = numeric::NumericTraits<Real>::pi();
974  Mol conf = Conformers[1];
975  Mol::iterator it;
976 
977  boost::unordered_map<string, float> STD_AREA;
978  /*
979  STD_AREA["ALA"] = 124; STD_AREA["ARG"] = 244; STD_AREA["ASN"] = 161; STD_AREA["ASP"] = 154; STD_AREA["cys"] = 94;
980  STD_AREA["CYS"] = 94; STD_AREA["GLU"] = 187; STD_AREA["GLN"] = 190; STD_AREA["GLY"] = 89;
981  STD_AREA["HIS"] = 201; STD_AREA["ILE"] = 194; STD_AREA["LEU"] = 198; STD_AREA["LYS"] = 214;
982  STD_AREA["MET"] = 215; STD_AREA["PHE"] = 221; STD_AREA["PRO"] = 150; STD_AREA["SER"] = 126;
983  STD_AREA["THR"] = 152; STD_AREA["TRP"] = 265; STD_AREA["TYR"] = 236; STD_AREA["VAL"] = 169;
984 
985  STD_AREA["ALA"] = 28; STD_AREA["ARG"] = 27; STD_AREA["ASN"] = 28; STD_AREA["ASP"] = 25; STD_AREA["cys"] = 25;
986  STD_AREA["CYS"] = 25; STD_AREA["GLU"] = 23; STD_AREA["GLN"] = 26; STD_AREA["GLY"] = 30;
987  STD_AREA["HIS"] = 26; STD_AREA["ILE"] = 23; STD_AREA["LEU"] = 23; STD_AREA["LYS"] = 26;
988  STD_AREA["MET"] = 28; STD_AREA["PHE"] = 26; STD_AREA["PRO"] = 22; STD_AREA["SER"] = 26;
989  STD_AREA["THR"] = 25; STD_AREA["TRP"] = 28; STD_AREA["TYR"] = 25; STD_AREA["VAL"] = 24;
990  */
991 
992  for( it = conf.begin(); it != conf.end(); it++ )
993  {
994  PDB_Entry b = it->second;
995 
996  //if( b.atomName[0] == 'H' && b.atomName!="HN" && b.atomName!="H") continue;
997  if( b.atomName != "HN" && b.atomName!="N" && b.atomName!="CA"&& b.atomName!="CB"&& b.atomName!="C"&& b.atomName!="O") continue;
998 
999  //if( b.atomName[0] == 'H' ) continue; // for all heavy atoms
1000  //if( b.atomName != "O" ) continue; // for Carbonyl O only
1001 
1002  int resID = b.resNum;
1003  utility::vector0<int> Neighnors = NeighborList[ b.atomNum ];
1004 
1005  int fullNo = 0;
1006  int partNo = 0;
1007  bool fullInside, partInside;
1008  Vec3 cent, nCent, x, dx;
1009 
1010 
1011  //cout << "\tatom: " << resID << "\t" << b.atomName << "\ttotal points:" << SpherePointNo << endl;
1012 
1013  string b_atomName = b.atomName;
1014  if( b.atomName[0] == 'C' && b.atomName != "C") b_atomName = "C"; // for all non-C' C
1015  if( b.atomName == "C") b_atomName = "CO"; // for all C'=O C
1016 
1017  float b_rad = VDW_RAD[b_atomName] + rad_sol;
1018  Vec3Copy(cent, b.Coord);
1019  for (int pointI = 0; pointI < SpherePointNo; pointI++)
1020  {
1021  Vec3Copy(x, cent);
1022  Vec3ScaleAdd(x, b_rad, SpherePoints[pointI]);
1023 
1024  fullInside = false;
1025  partInside = false;
1026 
1027  //cout << "\t\tpoint: " << pointI << "\tNeighnors size " << Neighnors.size() << endl;
1028  for (int atomI = 0; atomI < (int)Neighnors.size(); atomI++)
1029  {
1030  PDB_Entry nAtomP = conf[ Neighnors[atomI] ];
1031 
1032  Vec3Copy(nCent, nAtomP.Coord);
1033  Vec3Copy(dx, x);
1034  Vec3Sub(dx, nCent);
1035 
1036  //cout << "\t\t\t" << resID << "\tNeighnor: " << nAtomP.resNum << "\t" << nAtomP.atomName << "\t" << Neighnors.size() << endl;
1037  if( nAtomP.resNum < r1 || nAtomP.resNum > rN ) continue;
1038 
1039 
1040  string nAtomP_atomName = nAtomP.atomName;
1041  if( nAtomP.atomName[0] == 'C' ) nAtomP_atomName = "C";
1042  if( nAtomP.atomName == "C") nAtomP_atomName = "CO"; // for all C'=O C
1043 
1044  float nRad = VDW_RAD[nAtomP_atomName] + rad_sol;
1045  if (dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2] > nRad * nRad)
1046  continue;
1047 
1048  fullInside = true; //break;
1049 
1050 
1051  // for full area, ignored
1052  if( resID == nAtomP.resNum ) //full area
1053  {
1054  partInside = true;
1055  break;
1056  }
1057  }
1058  //cout << endl;
1059  if (! fullInside) fullNo++;
1060 
1061  if (! partInside) partNo++; // full area, ignored
1062  }
1063  //cout << "\tatom: " << resID << "\t" << b.atomName << "\tfull points:" << fullNo*b_rad*b_rad*4.0f * (float) SPARTA_PI / SpherePointNo << "\tpart points:" << partNo*b_rad*b_rad *4.0f * (float) SPARTA_PI / SpherePointNo<<endl;
1064 
1065 
1066  AtomSurfaceFullList[resID][b.atomName] = fullNo * b_rad * b_rad *4.0f * (float) SPARTA_PI / SpherePointNo; // solvent exposed area
1067  AtomSurfacePartList[resID][b.atomName] = partNo * b_rad * b_rad *4.0f * (float) SPARTA_PI / SpherePointNo; // full area
1068 
1069  ResSurfaceFullList[resID] += (fullNo * b_rad * b_rad *4.0f * (float) SPARTA_PI / SpherePointNo); // solvent exposed area * 4.0f * (float) M_SPARTA_PI / SpherePointNo
1070  ResSurfacePartList[resID] += (partNo * b_rad * b_rad *4.0f * (float) SPARTA_PI / SpherePointNo);
1071  }
1072 
1073 
1074  boost::unordered_map< int,float>::iterator itS;
1075  for( itS = ResSurfaceFullList.begin(); itS != ResSurfaceFullList.end(); itS++ )
1076  {
1077  string resName = residList[itS->first];
1078  // SurfaceFullList[ itS->first ] *= ( 4.0f * (float) SPARTA_PI / (SpherePointNo * STD_AREA[resName]) );
1079  // SurfacePartList[ itS->first ] *= ( 4.0f * (float) SPARTA_PI / (SpherePointNo * STD_AREA[resName]) );
1080  }
1081 
1082 }
1083 
1084 
1085 //find the neighoring atoms, distance < rad_a + rad_b + rad_sol, for atoms with given type, for all non-H atoms
1086 void PDB::findNeighors(float rad_sol)
1087 {
1088  Mol conf = Conformers[1];
1089  Mol::iterator it, itA;
1090 
1091  //loop over all atoms
1092  for( itA = conf.begin(); itA != conf.end(); itA++ )
1093  {
1094  PDB_Entry a = itA->second;
1095 
1096  //if( a.atomName[0] == 'H' && a.atomName!="HN" && a.atomName!="H") continue; //skip non-HN H atoms
1097  if( a.atomName != "HN" && a.atomName!="N" && a.atomName!="CA"&& a.atomName!="CB"&& a.atomName!="C"&& a.atomName!="O") continue; //skip non-HN H atoms
1098 
1099  //cout << a.atomName << endl;
1100 
1101  string a_atomName = a.atomName;
1102  if( a.atomName[0] == 'C' ) a_atomName = "C";
1103  if( a.atomName == "C") a_atomName = "CO"; // for all C'=O C
1104  float rad_a = VDW_RAD[ a_atomName ];
1105 
1106  //search for all other atoms
1107  for( it = conf.begin(); it != conf.end(); it++ )
1108  {
1109  PDB_Entry b = it->second;
1110 
1111  if( b.atomName[0] == 'H' && b.atomName!="HN" && b.atomName!="H" ) continue;
1112 
1113  string b_atomName = b.atomName;
1114  if( b.atomName[0] == 'C' ) b_atomName = "C";
1115  if( b.atomName == "C") b_atomName = "CO"; // for all C'=O C
1116 
1117  float rad_b = VDW_RAD[ b_atomName ];
1118 
1119  if( getDist(a,b) < rad_a + rad_b + rad_sol )
1120  {
1121  NeighborList[ a.atomNum ].push_back( b.atomNum );
1122  //cout << a.atomNum << "\t" << b.atomNum << "\t" << b.atomName << endl;
1123  }
1124  }
1125 
1126  }
1127 }
1128 
1129 
1130 // Same model from MOLMOL
1132  double x0, double y0, double z0,
1133  double x1, double y1, double z1,
1134  double x2, double y2, double z2,
1135  int rowStartA[], int rowNo, int quad,
1136  int row0, int ind0, int ind1,
1137  int row2, int ind2,
1138  Vec3 *pointA)
1139 {
1140  if (row0 + 1 == row2 || row2 + 1 == row0) {
1141  int row0Size, row2Size;
1142 
1143  if (row0 == - rowNo || row0 == rowNo)
1144  row0Size = 1;
1145  else if (row0 < 0)
1146  row0Size = rowNo + row0;
1147  else
1148  row0Size = rowNo - row0;
1149 
1150  if (row2 == - rowNo || row2 == rowNo)
1151  row2Size = 1;
1152  else if (row2 < 0)
1153  row2Size = rowNo + row2;
1154  else
1155  row2Size = rowNo - row2;
1156 
1157  if (ind0 < (quad + 1) * row0Size) {
1158  ind0 += rowStartA[rowNo + row0];
1159  pointA[ind0][0] = (float) x0;
1160  pointA[ind0][1] = (float) y0;
1161  pointA[ind0][2] = (float) z0;
1162  }
1163 
1164  if (ind1 < (quad + 1) * row0Size) {
1165  ind1 += rowStartA[rowNo + row0];
1166  pointA[ind1][0] = (float) x1;
1167  pointA[ind1][1] = (float) y1;
1168  pointA[ind1][2] = (float) z1;
1169  }
1170 
1171  if (ind2 < (quad + 1) * row2Size) {
1172  ind2 += rowStartA[rowNo + row2];
1173  pointA[ind2][0] = (float) x2;
1174  pointA[ind2][1] = (float) y2;
1175  pointA[ind2][2] = (float) z2;
1176  }
1177  } else {
1178  double x01, y01, z01;
1179  double x12, y12, z12;
1180  double x20, y20, z20;
1181  double a;
1182  int rowMid, indMid01, indMid02, indMid12;
1183 
1184  x01 = x0 + x1;
1185  y01 = y0 + y1;
1186  z01 = z0 + z1;
1187  a = sqrt(x01 * x01 + y01 * y01 + z01 * z01);
1188  x01 /= a;
1189  y01 /= a;
1190  z01 /= a;
1191 
1192  x12 = x1 + x2;
1193  y12 = y1 + y2;
1194  z12 = z1 + z2;
1195  a = sqrt(x12 * x12 + y12 * y12 + z12 * z12);
1196  x12 /= a;
1197  y12 /= a;
1198  z12 /= a;
1199 
1200  x20 = x2 + x0;
1201  y20 = y2 + y0;
1202  z20 = z2 + z0;
1203  a = sqrt(x20 * x20 + y20 * y20 + z20 * z20);
1204  x20 /= a;
1205  y20 /= a;
1206  z20 /= a;
1207 
1208  rowMid = (row0 + row2) / 2;
1209  indMid01 = (ind0 + ind1) / 2;
1210  indMid02 = (ind0 + ind2) / 2;
1211  indMid12 = (ind1 + ind2) / 2;
1212 
1213  calcTriangles(
1214  x0, y0, z0,
1215  x01, y01, z01,
1216  x20, y20, z20,
1217  rowStartA, rowNo, quad,
1218  row0, ind0, indMid01,
1219  rowMid, indMid02,
1220  pointA);
1221  calcTriangles(
1222  x01, y01, z01,
1223  x1, y1, z1,
1224  x12, y12, z12,
1225  rowStartA, rowNo, quad,
1226  row0, indMid01, ind1,
1227  rowMid, indMid12,
1228  pointA);
1229  calcTriangles(
1230  x20, y20, z20,
1231  x12, y12, z12,
1232  x01, y01, z01,
1233  rowStartA, rowNo, quad,
1234  rowMid, indMid02, indMid12,
1235  row0, indMid01,
1236  pointA);
1237  calcTriangles(
1238  x20, y20, z20,
1239  x12, y12, z12,
1240  x2, y2, z2,
1241  rowStartA, rowNo, quad,
1242  rowMid, indMid02, indMid12,
1243  row2, ind2,
1244  pointA);
1245  }
1246 }
1247 
1248 
1249 // // Same model from MOLMOL
1250 // void PDB::SphereCalcPoints(int divNo, Vec3 **pointAP, int *pointNoP)
1251 // {
1252 // Vec3 *pointA;
1253 // int *rowStartA;
1254 // int pointNo, rowNo, rowSize, i;
1255 // runtime_assert( false );
1256 // rowNo = 1 << divNo;
1257 
1258 // // rowStartA = (int *) malloc((2 * rowNo + 1) * sizeof(*rowStartA));
1259 
1260 
1261 // rowStartA[0] = 0;
1262 // rowStartA[1] = 1;
1263 // rowSize = 4;
1264 // for (i = 2; i <= rowNo; i++) {
1265 // rowStartA[i] = rowStartA[i - 1] + rowSize;
1266 // rowSize += 4;
1267 // }
1268 // for (i = rowNo + 1; i < 2 * rowNo + 1; i++) {
1269 // rowStartA[i] = rowStartA[i - 1] + rowSize;
1270 // rowSize -= 4;
1271 // }
1272 
1273 // pointNo = 4 * rowNo * rowNo + 2;
1274 // // pointA = (Vec3 *) malloc(pointNo * sizeof(*pointA));
1275 
1276 // calcTriangles(
1277 // 1.0, 0.0, 0.0,
1278 // 0.0, 1.0, 0.0,
1279 // 0.0, 0.0, 1.0,
1280 // rowStartA, rowNo, 0,
1281 // 0, 0, rowNo,
1282 // rowNo, 0,
1283 // pointA);
1284 // calcTriangles(
1285 // 0.0, 1.0, 0.0,
1286 // -1.0, 0.0, 0.0,
1287 // 0.0, 0.0, 1.0,
1288 // rowStartA, rowNo, 1,
1289 // 0, rowNo, 2 * rowNo,
1290 // rowNo, 0,
1291 // pointA);
1292 // calcTriangles(
1293 // -1.0, 0.0, 0.0,
1294 // 0.0, -1.0, 0.0,
1295 // 0.0, 0.0, 1.0,
1296 // rowStartA, rowNo, 2,
1297 // 0, 2 * rowNo, 3 * rowNo,
1298 // rowNo, 0,
1299 // pointA);
1300 // calcTriangles(
1301 // 0.0, -1.0, 0.0,
1302 // 1.0, 0.0, 0.0,
1303 // 0.0, 0.0, 1.0,
1304 // rowStartA, rowNo, 3,
1305 // 0, 3 * rowNo, 4 * rowNo,
1306 // rowNo, 0,
1307 // pointA);
1308 // calcTriangles(
1309 // 1.0, 0.0, 0.0,
1310 // 0.0, 1.0, 0.0,
1311 // 0.0, 0.0, -1.0,
1312 // rowStartA, rowNo, 0,
1313 // 0, 0, rowNo,
1314 // - rowNo, 0,
1315 // pointA);
1316 // calcTriangles(
1317 // 0.0, 1.0, 0.0,
1318 // -1.0, 0.0, 0.0,
1319 // 0.0, 0.0, -1.0,
1320 // rowStartA, rowNo, 1,
1321 // 0, rowNo, 2 * rowNo,
1322 // - rowNo, 0,
1323 // pointA);
1324 // calcTriangles(
1325 // -1.0, 0.0, 0.0,
1326 // 0.0, -1.0, 0.0,
1327 // 0.0, 0.0, -1.0,
1328 // rowStartA, rowNo, 2,
1329 // 0, 2 * rowNo, 3 * rowNo,
1330 // - rowNo, 0,
1331 // pointA);
1332 // calcTriangles(
1333 // 0.0, -1.0, 0.0,
1334 // 1.0, 0.0, 0.0,
1335 // 0.0, 0.0, -1.0,
1336 // rowStartA, rowNo, 3,
1337 // 0, 3 * rowNo, 4 * rowNo,
1338 // - rowNo, 0,
1339 // pointA);
1340 
1341 // // free(rowStartA);
1342 
1343 // *pointAP = pointA;
1344 // *pointNoP = pointNo;
1345 // }
1346 
1347 
1348 // Structure-based H-N order parameter
1349 // Zhang&Bruschweiler, 2002, JACS, 12654-12655
1351 {
1352  Mol conf = Conformers[1];
1353  Mol::iterator it;
1354 
1355  //loop over all atoms
1356  std::map<int, string>::iterator itA;
1357 
1358  float S2 = 0;
1359  for ( itA = residList.begin(); itA != residList.end(); itA++ )
1360  {
1361  int resID = itA->first; //.resNum;
1362  string resName = itA->second;
1363 
1364  PDB_Entry O_prev = ATOMS[1][resID-1]["O"];
1365  PDB_Entry H = ATOMS[1][resID]["H"];
1366  PDB_Entry HN = ATOMS[1][resID]["HN"];
1367 
1368  //cout << resName << "\t" << resID << "\t" << O_prev.atomName << endl;
1369 
1370  if( (O_prev.atomName).empty()|| ((H.atomName).empty() && (HN.atomName).empty() && resName != "PRO")) continue; //skip if no O/HN atoms
1371  if( (H.atomName).empty() ) H = HN;
1372  if( resName == "PRO" ) H = ATOMS[1][resID]["N"]; //for Pro
1373 
1374  //search for all other heavy atoms
1375  S2 = 0;
1376  for( it = conf.begin(); it != conf.end(); it++ )
1377  {
1378  PDB_Entry b = it->second;
1379 
1380  int resID2 = b.resNum;
1381  if( resID2 == resID || resID2 == resID-1 || b.atomName[0] == 'H' || (b.atomName[1] == 'H'&&b.atomName[1] != 'N')) continue; //skip all H
1382 
1383  float D_OK = getDist(O_prev,b); // distance between O and heavy atom
1384  float D_HK = getDist(H,b); // distance between O and heavy atom
1385 
1386  S2 += exp(-1.0*D_OK);
1387  S2 += 0.8*exp(-1.0*D_HK);
1388  //cout << resName << "\t" << resID << "\t" << O_prev.atomName << "\t" << b.atomName << "\t" << resID2 ;
1389  //cout << "\t" << D_OK << "\t" << D_HK << "\t" << S2 << endl;
1390  }
1391 
1392  S2 *= 2.656;
1393 
1394  S2 = (exp(S2)-exp(-S2))/(exp(S2)+exp(-S2))-0.1;
1395  //cout << resName << "\t" << S2 << endl;
1396  HN_S2[resID] = S2;
1397  }
1398 
1399  //smooth for terminus
1400  if(HN_S2[r1+2]>0 && HN_S2[r1+1]>0 ) HN_S2[r1] = HN_S2[r1+1]-fabs(HN_S2[r1+1]-HN_S2[r1+2]);
1401  if(HN_S2[rN-2]>0 && HN_S2[rN-1]>0 ) HN_S2[rN] = HN_S2[rN-1]-fabs(HN_S2[rN-1]-HN_S2[rN-2]);
1402 
1403 }
1404 
1405 
1406 // calculate electric field effects
1408 {
1409  const Real SPARTA_PI = numeric::NumericTraits<Real>::pi();
1410  Mol conf = Conformers[1];
1411  Mol::iterator it;
1412 
1413  boost::unordered_map<string, string> targetAtomList;
1414  boost::unordered_map<string, string>::iterator itT;
1415  targetAtomList["HN"]="N";
1416  targetAtomList["HA"]="CA";
1417  //targetAtomList["CA"]="N";
1418 
1419  boost::unordered_map<string, float> Qlist;
1420  Qlist["C"] = -0.9612;
1421  Qlist["O"] = 1.39374;
1422  Qlist["N"] = 0.7209;
1423 
1424  //loop over all atoms
1425  std::map<int, string>::iterator itA;
1426  ElectricField.clear();
1427  for ( itA = residList.begin(); itA != residList.end(); itA++ )
1428  {
1429  int resID = itA->first; //.resNum;
1430  string resName = itA->second;
1431 
1432  // tr.Info << resID << "\t" << resName << endl;
1433  for(itT = targetAtomList.begin(); itT != targetAtomList.end(); itT++)
1434  {
1435  PDB_Entry target = ATOMS[1][resID][itT->first];
1436  PDB_Entry partner = ATOMS[1][resID][itT->second];
1437 
1438  if( (target.atomName).empty() ) continue;
1439 
1440  // tr.Info << resID << "\t" << resName << "\t" << target.atomName << "\t" << target.resNum << endl;
1441  for( it = conf.begin(); it != conf.end(); it++ )
1442  {
1443  PDB_Entry b = it->second;
1444 
1445  int resID2 = b.resNum;
1446  if( fabs((double) (resID2 - resID)) <= 1 ) continue; // FOR WINDOWS BUILD //skip all atoms from present and adjacent residues
1447  string atomName2 = b.atomName;
1448  if( atomName2 == "O" && target.atomName == "HN" ) continue;
1449 
1450  //cout << resID << "\t" << resName << "\t" << target.atomName << "\t" << target.resNum << "\t" << atomName2 << endl;
1451  if( atomName2=="O" || atomName2.substr(0,2)=="OD" || atomName2.substr(0,2)=="OE" || atomName2=="C" || atomName2=="N")
1452  {
1453  float c = cos(getBondAngle(partner,target,b)*SPARTA_PI/180.0);
1454  float dist = getDist(target,b);
1455  if( dist > 3.0 ) continue;
1456  ElectricField[resID][target.atomName] += Qlist[atomName2.substr(0,1)]*c/(dist*dist);
1457  //cout << resName << "\t" << resID << "\t" << target.atomName << "\t" << b.atomName << "\t" << resID2;
1458  //cout << "\t" << c << "\t" << dist << "\t" << ElectricField[resID][target.atomName] << endl;
1459  }
1460  }
1461  }
1462 
1463 
1464  }
1465 }
1466 
1467 
1468 
1470 {
1471  Mol conf = Conformers[1];
1472  Mol::iterator it;
1473 
1474  ElectricField.clear();
1475 
1476  const Real SPARTA_PI = numeric::NumericTraits<Real>::pi();
1477  const Real RADS_PER_DEG = SPARTA_PI / 180.;
1478 
1479  boost::unordered_map<string, string> targetAtomList;
1480  boost::unordered_map<string, string>::iterator itT;
1481  targetAtomList["HN"]="N";
1482  targetAtomList["HA"]="CA";
1483  //targetAtomList["CA"]="N";
1484 
1485  boost::unordered_map<string, float> Qlist;
1486  Qlist["C"] = -0.9612;
1487  Qlist["O"] = 1.39374;
1488  Qlist["N"] = 0.7209;
1489 
1490  //loop over all atoms
1491  std::map<int, string>::iterator itA;
1492 
1493  float S2 = 0;
1494  for ( itA = residList.begin(); itA != residList.end(); itA++ )
1495  {
1496  int resID = itA->first; //.resNum;
1497  string resName = itA->second;
1498 
1499  PDB_Entry O_prev = ATOMS[1][resID-1]["O"];
1500  PDB_Entry H = ATOMS[1][resID]["H"];
1501  PDB_Entry HN = ATOMS[1][resID]["HN"];
1502 
1503  //cout << resName << "\t" << resID << "\t" << O_prev.atomName << endl;
1504 
1505  if( (O_prev.atomName).empty()|| ((H.atomName).empty() && (HN.atomName).empty() && resName != "PRO")) continue; //skip if no O/HN atoms
1506  if( (H.atomName).empty() ) H = HN;
1507  if( resName == "PRO" ) H = ATOMS[1][resID]["N"]; //for Pro
1508 
1509 
1510  PDB_Entry EF_target_HA = ATOMS[1][resID]["HA"];
1511  PDB_Entry EF_partner_HA = ATOMS[1][resID]["CA"];
1512  PDB_Entry EF_target_HN = ATOMS[1][resID]["HN"];
1513  PDB_Entry EF_partner_HN = ATOMS[1][resID]["N"];
1514 
1515  //search for all other heavy atoms
1516  S2 = 0;
1517  for( it = conf.begin(); it != conf.end(); it++ )
1518  {
1519  PDB_Entry b = it->second;
1520 
1521  int resID2 = b.resNum;
1522  // if( resID2 == resID || resID2 == resID-1 || b.atomName[0] == 'H' || (b.atomName[1] == 'H'&&b.atomName[1] != 'N')) continue; //skip all H
1523  if(!( resID2 == resID || resID2 == resID-1 || b.atomName[0] == 'H' || (b.atomName[1] == 'H'&&b.atomName[1] != 'N')) )
1524  {
1525  float D_OK = getDist(O_prev,b); // distance between O and heavy atom
1526  float D_HK = getDist(H,b); // distance between O and heavy atom
1527 
1528  S2 += exp(-1.0*D_OK);
1529  S2 += 0.8*exp(-1.0*D_HK);
1530  //cout << resName << "\t" << resID << "\t" << O_prev.atomName << "\t" << b.atomName << "\t" << resID2 ;
1531  //cout << "\t" << D_OK << "\t" << D_HK << "\t" << S2 << endl;
1532  } // S2 calucalation
1533 
1534  if( fabs( (double) (resID2 - resID)) <= 1 ) continue; // FOR WINDOWS BUILD //skip all atoms from present and adjacent residues
1535  string atomName2 = b.atomName;
1536 
1537  if(!(EF_target_HA.atomName).empty())
1538  {
1539  //cout << resID << "\t" << resName << "\t" << target.atomName << "\t" << target.resNum << "\t" << atomName2 << endl;
1540  if( atomName2=="O" || atomName2.substr(0,2)=="OD" || atomName2.substr(0,2)=="OE" || atomName2=="C" || atomName2=="N")
1541  {
1542  //float c = cos(getBondAngle(EF_partner_HA,EF_target_HA,b)*RADS_PER_DEG);
1543  float dist = getDist(EF_target_HA,b);
1544  if( dist <= 3.0 ) //continue;
1545  ElectricField[resID]["HA"] += Qlist[atomName2.substr(0,1)]*cos(getBondAngle(EF_partner_HA,EF_target_HA,b)*RADS_PER_DEG)/(dist*dist);
1546  //cout << resName << "\t" << resID << "\t" << target.atomName << "\t" << b.atomName << "\t" << resID2;
1547  //cout << "\t" << c << "\t" << dist << "\t" << ElectricField[resID][target.atomName] << endl;
1548  }
1549  }
1550  if(!(EF_target_HN.atomName).empty())
1551  {
1552  //cout << resID << "\t" << resName << "\t" << EF_target_HN.atomName << "\t" << EF_target_HN.resNum << "\t" << atomName2 << endl;
1553  if( atomName2.substr(0,2)=="OD" || atomName2.substr(0,2)=="OE" || atomName2=="C" || atomName2=="N")
1554  {
1555  //float c = cos(getBondAngle(EF_partner_HN,EF_target_HN,b)*RADS_PER_DEG);
1556  float dist = getDist(EF_target_HN,b);
1557  if( dist <= 3.0 ) //continue;
1558  ElectricField[resID]["HN"] += Qlist[atomName2.substr(0,1)]*cos(getBondAngle(EF_partner_HN,EF_target_HN,b)*RADS_PER_DEG)/(dist*dist);
1559  //cout << resName << "\t" << resID << "\t" << EF_target_HN.atomName << "\t" << b.atomName << "\t" << resID2;
1560  //cout << "\t" << c << "\t" << dist << "\t" << ElectricField[resID][EF_target_HN.atomName] << endl;
1561  }
1562  }
1563 
1564  }
1565 
1566  S2 *= 2.656;
1567 
1568  S2 = (exp(S2)-exp(-S2))/(exp(S2)+exp(-S2))-0.1;
1569  //cout << resName << "\t" << S2 << endl;
1570  HN_S2[resID] = S2;
1571  }
1572 
1573  //smooth for terminus
1574  if(HN_S2[r1+2]>0 && HN_S2[r1+1]>0 ) HN_S2[r1] = HN_S2[r1+1]-fabs(HN_S2[r1+1]-HN_S2[r1+2]);
1575  if(HN_S2[rN-2]>0 && HN_S2[rN-1]>0 ) HN_S2[rN] = HN_S2[rN-1]-fabs(HN_S2[rN-1]-HN_S2[rN-2]);
1576 
1577 }
1578 
1579 }
1580 }