Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CartesianBondedEnergy.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 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file core/scoring/methods/CartesianBondedEnergy.cc
11 /// @brief Harmonic bondangle/bondlength/torsion constraints
12 /// @author
13 
14 // Unit headers
18 
19 // Package headers
22 
23 // Project headers
33 #include <core/chemical/AA.hh>
34 #include <core/id/DOF_ID.hh>
35 #include <core/id/TorsionID.hh>
41 
44 
46 #include <core/scoring/Energies.hh>
47 #include <core/pose/Pose.hh>
48 #include <basic/Tracer.hh>
49 #include <basic/basic.hh>
50 #include <basic/database/open.hh>
51 
52 // Utility headers
53 #include <utility/string_util.hh>
54 #include <utility/io/izstream.hh>
55 
56 // Numeric headers
57 #include <numeric/constants.hh>
58 #include <numeric/xyz.functions.hh>
59 #include <numeric/deriv/angle_deriv.hh>
60 #include <numeric/deriv/distance_deriv.hh>
61 #include <numeric/deriv/dihedral_deriv.hh>
62 #include <numeric/NumericTraits.hh>
63 #include <numeric/angle.functions.hh>
65 
66 // options
67 #include <basic/options/option.hh>
68 #include <basic/options/keys/score.OptionKeys.gen.hh>
69 #include <basic/options/keys/optE.OptionKeys.gen.hh>
70 #include <basic/options/keys/corrections.OptionKeys.gen.hh>
71 
72 // C++ headers
73 #include <iostream>
74 #include <boost/tuple/tuple.hpp>
75 #include <boost/algorithm/string.hpp>
76 
77 #include <utility/vector1.hh>
78 
79 #include <core/pose/PDBInfo.hh>
80 
81 // cutoff for reporting outliers
82 #define CUTOFF 1
83 
84 namespace boost {
85 namespace tuples {
86 
87 std::size_t hash_value(atm_name_quad const& e) {
88  std::size_t seed = 0;
89  boost::hash_combine(seed, e.get<0>());
90  boost::hash_combine(seed, e.get<1>());
91  boost::hash_combine(seed, e.get<2>());
92  boost::hash_combine(seed, e.get<3>());
93  boost::hash_combine(seed, e.get<4>());
94  return seed;
95 }
96 std::size_t hash_value(atm_name_triple const& e) {
97  std::size_t seed = 0;
98  boost::hash_combine(seed, e.get<0>());
99  boost::hash_combine(seed, e.get<1>());
100  boost::hash_combine(seed, e.get<2>());
101  boost::hash_combine(seed, e.get<3>());
102  return seed;
103 }
104 std::size_t hash_value(atm_name_pair const& e) {
105  std::size_t seed = 0;
106  boost::hash_combine(seed, e.get<0>());
107  boost::hash_combine(seed, e.get<1>());
108  boost::hash_combine(seed, e.get<2>());
109  return seed;
110 }
111 std::size_t hash_value(atm_name_single const& e) {
112  std::size_t seed = 0;
113  boost::hash_combine(seed, e.get<0>());
114  boost::hash_combine(seed, e.get<1>());
115  return seed;
116 }
117 
118 bool operator==(atm_name_quad const& a,atm_name_quad const& b) {
119  return a.get<0>() == b.get<0>() && a.get<1>() == b.get<1>() &&
120  a.get<2>() == b.get<2>() && a.get<3>() == b.get<3>() &&
121  a.get<4>() == b.get<4>();
122 }
124  return a.get<0>() == b.get<0>() && a.get<1>() == b.get<1>() &&
125  a.get<2>() == b.get<2>() && a.get<3>() == b.get<3>();
126 }
127 bool operator==(atm_name_pair const& a,atm_name_pair const& b) {
128  return a.get<0>() == b.get<0>() && a.get<1>() == b.get<1>() &&
129  a.get<2>() == b.get<2>();
130 }
132  return a.get<0>() == b.get<0>() && a.get<1>() == b.get<1>();
133 }
134 
135 }
136 }
137 
138 
139 
140 namespace core {
141 namespace scoring {
142 namespace methods {
143 
144 
145 static basic::Tracer TR("core.scoring.CartesianBondedEnergy");
146 static basic::Tracer GEOMETRIES("core.scoring.CartesianBondedEnergy.GEOMETRIES");
147 
148 // default spring constants
149 // --> only if not specified in config files
150 static const Real K_LENGTH=300.0;
151 static const Real K_ANGLE=80.0;
152 static const Real K_TORSION=20.0;
153 static const Real K_TORSION_PROTON=10.0; // proton chi
154 static const Real K_TORSION_IMPROPER=40.0;
155 
157 
158 
159 //////////////////////
160 /// EnergyMethod Creator
163  methods::EnergyMethodOptions const & options
164 ) const {
165  return new CartesianBondedEnergy( options );
166 }
167 
170  ScoreTypes sts;
171  sts.push_back( cart_bonded );
172  sts.push_back( cart_bonded_angle );
173  sts.push_back( cart_bonded_length );
174  sts.push_back( cart_bonded_torsion );
175  return sts;
176 }
177 
178 
179 ////////////////////////
180 /// helper function
182  using namespace core::chemical;
183 
184  return restype.name3();
185 }
186 
188  bb_N_index_( 0 ),
189  bb_CA_index_( 0 ),
190  bb_C_index_( 0 ),
191  bb_O_index_( 0 ),
192  bb_H_index_( 0 )
193 {}
194 
196 
198 {
199  length_params_.push_back( std::make_pair( atom_inds, params ));
200 }
201 
203 {
204  angle_params_.push_back( std::make_pair( atom_inds, params ));
205 }
206 
208 {
209  torsion_params_.push_back( std::make_pair( atom_inds, params ));
210 }
211 
213 {
214  improper_torsion_params_.push_back( std::make_pair( atom_inds, params ));
215 }
216 
218 {
219  bbdep_length_params_.push_back( std::make_pair( atom_inds, params ));
220 }
221 
223 {
224  bbdep_angle_params_.push_back( std::make_pair( atom_inds, params ));
225 }
226 
228 {
229  lower_connect_angle_params_.push_back( std::make_pair( atom_inds, params ));
230 }
231 
233 {
234  upper_connect_angle_params_.push_back( std::make_pair( atom_inds, params ));
235 }
236 
242 
245 )
246 {
248 }
249 
252 )
253 {
255 }
256 
259 )
260 {
262 }
263 
264 
265 ////////////////////////
266 // constructors
267 IdealParametersDatabase::IdealParametersDatabase(Real k_len_in, Real k_ang_in, Real k_tors_in, Real k_tors_prot_in, Real k_tors_improper_in) {
268  // figure out the defaults given priorities:
269  // 1: energy methods options (constructor args)
270  // 2: command line/options system
271  // 3: fallback defaults
272  Real k_len=K_LENGTH, k_ang=K_ANGLE, k_tors=K_TORSION, k_tors_prot=K_TORSION_PROTON, k_tors_improper=K_TORSION_IMPROPER;
274  if (basic::options::option[ basic::options::OptionKeys::score::bonded_params ].user())
275  params = basic::options::option[ basic::options::OptionKeys::score::bonded_params ]();
276  if ( k_len_in >= 0 ) {
277  k_len = k_len_in;
278  } else if (basic::options::option[ basic::options::OptionKeys::score::bonded_params ].user()) {
279  if (params.size() >= 1) k_len = params[1];
280  }
281 
282  if (k_ang_in >= 0) {
283  k_ang = k_ang_in;
284  } else if (basic::options::option[ basic::options::OptionKeys::score::bonded_params ].user()) {
285  if (params.size() >= 2) k_ang = params[2];
286  }
287 
288  if (basic::options::option[ basic::options::OptionKeys::score::bonded_params ].user()) {
289  if (params.size() >= 3) k_tors = params[3];
290  if (params.size() >= 4) k_tors_prot = params[4];
291  if (params.size() >= 5) k_tors_improper = params[5];
292  }
293  if (k_tors_in >= 0)
294  k_tors = k_tors_in;
295  if (k_tors_prot_in >= 0)
296  k_tors_prot = k_tors_prot_in;
297  if (k_tors_improper_in >= 0)
298  k_tors_improper = k_tors_improper_in;
299 
300  // now that we resolved the defaults, initialize
301  init(k_len, k_ang, k_tors, k_tors_prot, k_tors_improper);
302 }
303 
304 // read bb-dep and bb-indep parameter files from the rosetta database
305 void
307  Real k_len_in,
308  Real k_ang_in,
309  Real k_tors_in,
310  Real k_tors_prot_in,
311  Real k_tors_improper_in
312 ) {
313  TR << "Initializing IdealParametersDatabase with default Ks="
314  << k_len_in << " , " << k_ang_in << " , " << k_tors_in << " , " << k_tors_prot_in << " , " << k_tors_improper_in << std::endl;
315  k_length_ = k_len_in;
316  k_angle_ = k_ang_in;
317  k_torsion_ = k_tors_in;
318  k_torsion_proton_ = k_tors_prot_in;
319  k_torsion_improper_ = k_tors_improper_in;
320 
321  // read bb-independent parameters
322  std::string name3, atom1, atom2, atom3, atom4;
323  Real mu_d, K_d;
324  Size period;
325  std::string libpath = basic::options::option[ basic::options::OptionKeys::score::bonded_params_dir ]();
326  bbdep_bond_params_ = basic::options::option[ basic::options::OptionKeys::corrections::score::bbdep_bond_params ]();
327  bbdep_bond_devs_ = basic::options::option[ basic::options::OptionKeys::corrections::score::bbdep_bond_devs ]();
328 
329  {
330  utility::io::izstream instream;
331  atm_name_pair tuple;
332  basic::database::open( instream, libpath+"/default-lengths.txt");
333  while (instream) {
334  instream >> name3 >> atom1 >> atom2 >> mu_d >> K_d;
335  tuple = boost::make_tuple( name3, atom1, atom2 );
336  CartBondedParametersOP params_i = new BBIndepCartBondedParameters(mu_d, K_d);
337  bondlengths_indep_.insert( std::make_pair( tuple, params_i ) );
338  tuple = boost::make_tuple( name3, atom2, atom1 );
339  params_i = new BBIndepCartBondedParameters(mu_d, K_d);
340  bondlengths_indep_.insert( std::make_pair( tuple, params_i ) );
341  }
342  TR << "Read " << bondlengths_indep_.size() << " bb-independent lengths." << std::endl;
343  }
344 
345  {
346  utility::io::izstream instream;
347  atm_name_triple tuple;
348  basic::database::open( instream, libpath+"/default-angles.txt");
349  while (instream) {
350  instream >> name3 >> atom1 >> atom2 >> atom3 >> mu_d >> K_d;
351  tuple = boost::make_tuple( name3, atom1, atom2, atom3 );
352  CartBondedParametersOP params_i = new BBIndepCartBondedParameters(mu_d, K_d);
353  bondangles_indep_.insert( std::make_pair( tuple, params_i) );
354  tuple = boost::make_tuple( name3, atom3, atom2, atom1 );
355  bondangles_indep_.insert( std::make_pair( tuple, params_i) );
356  }
357  TR << "Read " << bondangles_indep_.size() << " bb-independent lengths." << std::endl;
358  }
359 
360  {
361  utility::io::izstream instream;
362  atm_name_quad tuple;
363  basic::database::open( instream, libpath+"/default-torsions.txt");
364  while (instream) {
365  instream >> name3 >> atom1 >> atom2 >> atom3 >> atom4 >> mu_d >> K_d >> period;
366  tuple = boost::make_tuple( name3, atom1, atom2, atom3, atom4 );
367  CartBondedParametersOP params_i = new BBIndepCartBondedParameters(mu_d, K_d, period);
368  torsions_indep_.insert( std::make_pair( tuple, params_i) );
369  tuple = boost::make_tuple( name3, atom4, atom3, atom2, atom1 );
370  torsions_indep_.insert( std::make_pair( tuple, params_i) );
371  }
372  TR << "Read " << torsions_indep_.size() << " bb-independent lengths." << std::endl;
373  }
374 
375  if (!bbdep_bond_params_) return;
376 
377  // read bb-dep parameters
378  //NOTE this must be read after the bbindep params are read
379  // as deviations for low count rama bins are smoothed using the bb-indep deviations
380  read_bbdep_table( libpath+"/bbdep-all-but-gly-pro-xpro-ile-val.txt", bondlengths_bbdep_def_, bondangles_bbdep_def_, "ALA" );
381  read_bbdep_table( libpath+"/bbdep-graphdata-gly.txt", bondlengths_bbdep_gly_, bondangles_bbdep_gly_, "GLY" );
382  read_bbdep_table( libpath+"/bbdep-graphdata-ile-val.txt", bondlengths_bbdep_valile_, bondangles_bbdep_valile_, "VAL" );
383  read_bbdep_table( libpath+"/bbdep-graphdata-pro.txt", bondlengths_bbdep_pro_, bondangles_bbdep_pro_, "PRO" );
384  read_bbdep_table( libpath+"/bbdep-graphdata-xpro.txt", bondlengths_bbdep_prepro_, bondangles_bbdep_prepro_, "ALA" );
385 }
386 
387 
388 // Read bb independent tables
389 // smooth using bbdep data corresponding to residue 'resbase'
390 void
393  boost::unordered_map< atm_name_single, CartBondedParametersOP > &bondlengths,
394  boost::unordered_map< atm_name_pair, CartBondedParametersOP > &bondangles,
395  std::string resbase )
396 {
397  using numeric::constants::d::pi;
398  using namespace ObjexxFCL;
399 
400  Real DEV_SCALE = 0.1; // scaling factor between bbindep and bbdep spring constants
401  core::Size M = 10; // m estimate to smooth low count bins
402 
403  utility::io::izstream instream;
404  basic::database::open( instream, filename );
405 
406  //PhiStart PhiStop PsiStart PsiStop Observations PhiAvg(i) PhiDev(i) PsiAvg(i) PsiDev(i) OmeAvg(i) OmeDev(i) C(-1)-NAvg(i) C(-1)-NDev(i) N-CAAvg(i)
407  // N-CADev(i) CA-CBAvg(i) CA-CBDev(i) CA-CAvg(i) CA-CDev(i) C-OAvg(i) C-ODev(i) C(-1)-N-CAAvg(i) C(-1)-N-CADev(i) N-CA-CBAvg(i) N-CA-CBDev(i)
408  // N-CA-CAvg(i) N-CA-CDev(i) CB-CA-CAvg(i) CB-CA-CDev(i) CA-C-OAvg(i) CA-C-ODev(i) CA-C-N(+1)Avg(i) CA-C-N(+1)Dev(i) O-C-N(+1)Avg(i) O-C-N(+1)Dev(i)
409  // Chi1Avg(i) Chi1Dev(i) Chi2Avg(i) Chi2Dev(i) Chi3Avg(i) Chi3Dev(i) Chi4Avg(i) Chi4Dev(i) ZetaAvg(i) ZetaDev(i)
410  core::Real phiL,phiH,psiL,psiH,phiAvg,phiDev,psiAvg,psiDev,OmegaAvg,OmegaDev;
411  core::Real CNavg,CNdev, NCAavg,NCAdev, CACBavg,CACBdev, CACavg,CACdev, COavg,COdev;
412  core::Real CNCAavg,CNCAdev, NCACBavg,NCACBdev, NCACavg,NCACdev, CBCACavg,CBCACdev;
413  core::Real CACOavg,CACOdev, CACNavg,CACNdev, OCNavg,OCNdev;
414  core::Real c1avg,c1dev,c2avg,c2dev,c3avg,c3dev,c4avg,c4dev,Zavg,Zdev;
415  core::Size nobs;
416 
417  // the bond angles
418  // their bb-indep angles
420  temp = bondlengths_indep_[boost::make_tuple(resbase,"C", "N")];
421  if (!temp) temp = bondlengths_indep_[boost::make_tuple("*","C", "N")];
422  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
423  core::Real CN_indep_avg=temp->mu(0,0),CN_indep_K=temp->K(0,0);
424 
425  temp = bondlengths_indep_[boost::make_tuple(resbase,"N", "CA")];
426  if (!temp) temp = bondlengths_indep_[boost::make_tuple("*","N", "CA")];
427  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
428  core::Real NCA_indep_avg=temp->mu(0,0),NCA_indep_K=temp->K(0,0);
429 
430  temp = bondlengths_indep_[boost::make_tuple(resbase,"CA", "CB")];
431  if (!temp) temp = bondlengths_indep_[boost::make_tuple("*","CA", "CB")];
432  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
433  core::Real CACB_indep_avg=temp->mu(0,0),CACB_indep_K=temp->K(0,0);
434 
435  temp = bondlengths_indep_[boost::make_tuple(resbase,"CA", "C")];
436  if (!temp) temp = bondlengths_indep_[boost::make_tuple("*","CA", "C")];
437  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
438  core::Real CAC_indep_avg=temp->mu(0,0),CAC_indep_K=temp->K(0,0);
439 
440  temp = bondlengths_indep_[boost::make_tuple(resbase,"C", "O")];
441  if (!temp) temp = bondlengths_indep_[boost::make_tuple("*","C", "O")];
442  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
443  core::Real CO_indep_avg=temp->mu(0,0),CO_indep_K=temp->K(0,0);
444 
445  temp = bondangles_indep_[boost::make_tuple(resbase,"C", "N", "CA")];
446  if (!temp) temp = bondangles_indep_[boost::make_tuple("*","C", "N", "CA")];
447  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
448  core::Real CNCA_indep_avg=temp->mu(0,0),CNCA_indep_K=temp->K(0,0);
449 
450  temp = bondangles_indep_[boost::make_tuple(resbase,"N", "CA", "CB")];
451  if (!temp) temp = bondangles_indep_[boost::make_tuple("*","N", "CA", "CB")];
452  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
453  core::Real NCACB_indep_avg=temp->mu(0,0),NCACB_indep_K=temp->K(0,0);
454 
455  temp = bondangles_indep_[boost::make_tuple(resbase,"N", "CA", "C")];
456  if (!temp) temp = bondangles_indep_[boost::make_tuple("*","N", "CA", "C")];
457  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
458  core::Real NCAC_indep_avg=temp->mu(0,0),NCAC_indep_K=temp->K(0,0);
459 
460  temp = bondangles_indep_[boost::make_tuple(resbase,"CB", "CA", "C")];
461  if (!temp) temp = bondangles_indep_[boost::make_tuple("*","CB", "CA", "C")];
462  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
463  core::Real CBCAC_indep_avg=temp->mu(0,0),CBCAC_indep_K=temp->K(0,0);
464 
465  temp = bondangles_indep_[boost::make_tuple(resbase,"CA", "C", "O")];
466  if (!temp) temp = bondangles_indep_[boost::make_tuple("*","CA", "C", "O")];
467  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
468  core::Real CACO_indep_avg=temp->mu(0,0),CACO_indep_K=temp->K(0,0);
469 
470  temp = bondangles_indep_[boost::make_tuple(resbase,"CA", "C", "N")];
471  if (!temp) temp = bondangles_indep_[boost::make_tuple("*","CA", "C", "N")];
472  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
473  core::Real CACN_indep_avg=temp->mu(0,0),CACN_indep_K=temp->K(0,0);
474 
475  temp = bondangles_indep_[boost::make_tuple(resbase,"O", "C", "N")];
476  if (!temp) temp = bondangles_indep_[boost::make_tuple("*","O", "C", "N")];
477  if (!temp) temp = new BBIndepCartBondedParameters(0,0);
478  core::Real OCN_indep_avg=temp->mu(0,0),OCN_indep_K=temp->K(0,0);
479 
480  // all the relevant tables
481  FArray2D<core::Real> CNavg_tbl(36,36,0.0),CNdev_tbl(36,36,0.0);
482  FArray2D<core::Real> NCAavg_tbl(36,36,0.0),NCAdev_tbl(36,36,0.0);
483  FArray2D<core::Real> CACBavg_tbl(36,36,0.0),CACBdev_tbl(36,36,0.0);
484  FArray2D<core::Real> CACavg_tbl(36,36,0.0),CACdev_tbl(36,36,0.0);
485  FArray2D<core::Real> COavg_tbl(36,36,0.0),COdev_tbl(36,36,0.0);
486  FArray2D<core::Real> CNCAavg_tbl(36,36,0.0),CNCAdev_tbl(36,36,0.0);
487  FArray2D<core::Real> NCACBavg_tbl(36,36,0.0),NCACBdev_tbl(36,36,0.0);
488  FArray2D<core::Real> NCACavg_tbl(36,36,0.0),NCACdev_tbl(36,36,0.0);
489  FArray2D<core::Real> CBCACavg_tbl(36,36,0.0),CBCACdev_tbl(36,36,0.0);
490  FArray2D<core::Real> CACOavg_tbl(36,36,0.0),CACOdev_tbl(36,36,0.0);
491  FArray2D<core::Real> CACNavg_tbl(36,36,0.0),CACNdev_tbl(36,36,0.0);
492  FArray2D<core::Real> OCNavg_tbl(36,36,0.0),OCNdev_tbl(36,36,0.0);
493  FArray2D<core::Size> Ns(DynamicIndexRange(36),DynamicIndexRange(36),(core::Size)0);
494 
495  std::string fileline;
496  while(getline(instream, fileline)) {
497  if(fileline[0] == '#') continue;
498  std::stringstream(fileline) >> phiL >> phiH >> psiL >> psiH >> nobs >> phiAvg >> phiDev >> psiAvg >> psiDev >> OmegaAvg >> OmegaDev >> CNavg >> CNdev
499  >> NCAavg >> NCAdev >> CACBavg >> CACBdev >> CACavg >> CACdev >> COavg >> COdev
500  >> CNCAavg >> CNCAdev >> NCACBavg >> NCACBdev >> NCACavg >> NCACdev >> CBCACavg >> CBCACdev
501  >> CACOavg >> CACOdev >> CACNavg >> CACNdev >> OCNavg >> OCNdev
502  >> c1avg >> c1dev >> c2avg >> c2dev >> c3avg >> c3dev >> c4avg >> c4dev >> Zavg >> Zdev;
503 
504  Size phibin = (Size)std::floor(phiL/10.0 + 0.5);
505  Size psibin = (Size)std::floor(psiL/10.0 + 0.5);
506 
507  CNavg_tbl(phibin+1,psibin+1) = CNavg;
508  NCAavg_tbl(phibin+1,psibin+1) = NCAavg;
509  CACBavg_tbl(phibin+1,psibin+1) = CACBavg;
510  CACavg_tbl(phibin+1,psibin+1) = CACavg;
511  COavg_tbl(phibin+1,psibin+1) = COavg;
512  CNCAavg_tbl(phibin+1,psibin+1) = CNCAavg * pi/180;
513  NCACBavg_tbl(phibin+1,psibin+1) = NCACBavg * pi/180;
514  NCACavg_tbl(phibin+1,psibin+1) = NCACavg * pi/180;
515  CBCACavg_tbl(phibin+1,psibin+1) = CBCACavg * pi/180;
516  CACOavg_tbl(phibin+1,psibin+1) = CACOavg * pi/180;
517  CACNavg_tbl(phibin+1,psibin+1) = CACNavg * pi/180;
518  OCNavg_tbl(phibin+1,psibin+1) = OCNavg * pi/180;
519  Ns(phibin+1,psibin+1) = nobs;
520 
521  if (!bbdep_bond_devs_ || nobs<=3 || CN_indep_K==0) CNdev_tbl(phibin+1,psibin+1) = CN_indep_K;
522  else CNdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/CN_indep_K) + (nobs-1)*( (2*(CNdev)*(CNdev))/DEV_SCALE) )/ (M+nobs-1) );
523 
524  if (!bbdep_bond_devs_ || nobs<=3 || NCA_indep_K==0 ) NCAdev_tbl(phibin+1,psibin+1) = NCA_indep_K;
525  else NCAdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/NCA_indep_K) + (nobs-1)*( (2*(NCAdev)*(NCAdev))/DEV_SCALE) )/ (M+nobs-1) );
526 
527  if (!bbdep_bond_devs_ || nobs<=3 || CACB_indep_K==0 ) CACBdev_tbl(phibin+1,psibin+1) = CACB_indep_K;
528  else CACBdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/CACB_indep_K) + (nobs-1)*( (2*(CACBdev)*(CACBdev))/DEV_SCALE) )/ (M+nobs-1) );
529 
530  if (!bbdep_bond_devs_ || nobs<=3 || CAC_indep_K==0 ) CACdev_tbl(phibin+1,psibin+1) = CAC_indep_K;
531  else CACdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/CAC_indep_K) + (nobs-1)*( (2*(CACdev)*(CACdev))/DEV_SCALE) )/ (M+nobs-1) );
532 
533  if (!bbdep_bond_devs_ || nobs<=3 || CO_indep_K==0 ) COdev_tbl(phibin+1,psibin+1) = CO_indep_K;
534  else COdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/CO_indep_K) + (nobs-1)*( (2*(COdev)*(COdev))/DEV_SCALE) )/ (M+nobs-1) );
535 
536  if (!bbdep_bond_devs_ || nobs<=3 || CNCA_indep_K==0 ) CNCAdev_tbl(phibin+1,psibin+1) = CNCA_indep_K;
537  else CNCAdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/CNCA_indep_K) + (nobs-1)*( (2*(CNCAdev*pi/180)*(CNCAdev*pi/180))/DEV_SCALE) )/ (M+nobs-1) );
538 
539  if (!bbdep_bond_devs_ || nobs<=3 || NCACB_indep_K==0 ) NCACBdev_tbl(phibin+1,psibin+1) = NCACB_indep_K;
540  else NCACBdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/NCACB_indep_K) + (nobs-1)*( (2*(NCACBdev*pi/180)*(NCACBdev*pi/180))/DEV_SCALE) )/ (M+nobs-1) );
541 
542  if (!bbdep_bond_devs_ || nobs<=3 || NCAC_indep_K==0 ) NCACdev_tbl(phibin+1,psibin+1) = NCAC_indep_K;
543  else NCACdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/NCAC_indep_K) + (nobs-1)*( (2*(NCACdev*pi/180)*(NCACdev*pi/180))/DEV_SCALE) )/ (M+nobs-1) );
544 
545  if (!bbdep_bond_devs_ || nobs<=3 || CBCAC_indep_K==0 ) CBCACdev_tbl(phibin+1,psibin+1) = CBCAC_indep_K;
546  else CBCACdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/CBCAC_indep_K) + (nobs-1)*( (2*(CBCACdev*pi/180)*(CBCACdev*pi/180))/DEV_SCALE) )/ (M+nobs-1) );
547 
548  if (!bbdep_bond_devs_ || nobs<=3 || CACO_indep_K==0 ) CACOdev_tbl(phibin+1,psibin+1) = CACO_indep_K;
549  else CACOdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/CACO_indep_K) + (nobs-1)*( (2*(CACOdev*pi/180)*(CACOdev*pi/180))/DEV_SCALE) )/ (M+nobs-1) );
550 
551  if (!bbdep_bond_devs_ || nobs<=3 || CACN_indep_K==0 ) CACNdev_tbl(phibin+1,psibin+1) = CACN_indep_K;
552  else CACNdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/CACN_indep_K) + (nobs-1)*( (2*(CACNdev*pi/180)*(CACNdev*pi/180))/DEV_SCALE) )/ (M+nobs-1) );
553 
554  if (!bbdep_bond_devs_ || nobs<=3 || OCN_indep_K==0 ) OCNdev_tbl(phibin+1,psibin+1) = OCN_indep_K;
555  else OCNdev_tbl(phibin+1,psibin+1) = 1.0 / ( (M*(1/OCN_indep_K) + (nobs-1)*( (2*(OCNdev*pi/180)*(OCNdev*pi/180))/DEV_SCALE) )/ (M+nobs-1) );
556  }
557 
558  // fill in missing values
559  for (int i=1; i<=36; ++i) {
560  for (int j=1; j<=36; ++j) {
561  if (Ns(i,j) == 0) {
562  CNavg_tbl(i,j) = CN_indep_avg; CNdev_tbl(i,j) = CN_indep_K;
563  NCAavg_tbl(i,j) = NCA_indep_avg; NCAdev_tbl(i,j) = NCA_indep_K;
564  CACBavg_tbl(i,j) = CACB_indep_avg; CACBdev_tbl(i,j) = CACB_indep_K;
565  CACavg_tbl(i,j) = CAC_indep_avg; CACdev_tbl(i,j) = CAC_indep_K;
566  COavg_tbl(i,j) = CO_indep_avg; COdev_tbl(i,j) = CO_indep_K;
567  CNCAavg_tbl(i,j) = CNCA_indep_avg; CNCAdev_tbl(i,j) = CNCA_indep_K;
568  NCACBavg_tbl(i,j) = NCACB_indep_avg; NCACBdev_tbl(i,j) = NCACB_indep_K;
569  NCACavg_tbl(i,j) = NCAC_indep_avg; NCACdev_tbl(i,j) = NCAC_indep_K;
570  CBCACavg_tbl(i,j) = CBCAC_indep_avg; CBCACdev_tbl(i,j) = CBCAC_indep_K;
571  CACOavg_tbl(i,j) = CACO_indep_avg; CACOdev_tbl(i,j) = CACO_indep_K;
572  CACNavg_tbl(i,j) = CACN_indep_avg; CACNdev_tbl(i,j) = CACN_indep_K;
573  OCNavg_tbl(i,j) = OCN_indep_avg; OCNdev_tbl(i,j) = OCN_indep_K;
574  }
575  }
576  }
577 
578  // make the database entries
579  bondlengths[boost::make_tuple("N","C")] = bondlengths[boost::make_tuple("C","N")] = new BBDepCartBondedParameters(CNavg_tbl, CNdev_tbl ,"C-N");
580  bondlengths[boost::make_tuple("CA","N")] = bondlengths[boost::make_tuple("N","CA")] = new BBDepCartBondedParameters(NCAavg_tbl, NCAdev_tbl,"CA-N");
581  bondlengths[boost::make_tuple("CB","CA")] = bondlengths[boost::make_tuple("CA","CB")] = new BBDepCartBondedParameters(CACBavg_tbl, CACBdev_tbl,"CB-CA");
582  bondlengths[boost::make_tuple("C","CA")] = bondlengths[boost::make_tuple("CA","C")] = new BBDepCartBondedParameters(CACavg_tbl, CACdev_tbl,"C-CA");
583  bondlengths[boost::make_tuple("O","C")] = bondlengths[boost::make_tuple("C","O")] = new BBDepCartBondedParameters(COavg_tbl, COdev_tbl,"C-O");
584  bondangles[boost::make_tuple("CA","N","C")] = bondangles[boost::make_tuple("C","N","CA")] = new BBDepCartBondedParameters(CNCAavg_tbl, CNCAdev_tbl, "C-N-CA");
585  bondangles[boost::make_tuple("CB","CA","N")] = bondangles[boost::make_tuple("N","CA","CB")] = new BBDepCartBondedParameters(NCACBavg_tbl, NCACBdev_tbl, "N-CA-CB");
586  bondangles[boost::make_tuple("C","CA","N")] = bondangles[boost::make_tuple("N","CA","C")] = new BBDepCartBondedParameters(NCACavg_tbl, NCACdev_tbl, "N-CA-C");
587  bondangles[boost::make_tuple("C","CA","CB")] = bondangles[boost::make_tuple("CB","CA","C")] = new BBDepCartBondedParameters(CBCACavg_tbl, CBCACdev_tbl, "CB-CA-C");
588  bondangles[boost::make_tuple("O","C","CA")] = bondangles[boost::make_tuple("CA","C","O")] = new BBDepCartBondedParameters(CACOavg_tbl, CACOdev_tbl, "CA-C-O");
589  bondangles[boost::make_tuple("N","C","CA")] = bondangles[boost::make_tuple("CA","C","N")] = new BBDepCartBondedParameters(CACNavg_tbl, CACNdev_tbl, "CA-C-N");
590  bondangles[boost::make_tuple("N","C","O")] = bondangles[boost::make_tuple("O","C","N")] = new BBDepCartBondedParameters(OCNavg_tbl, OCNdev_tbl, "O-C-N");
591 }
592 
593 
594 
595 void
597  core::chemical::ResidueType const & restype,
598  int atm1,
599  int atm2,
600  int atm3,
601  Real & Ktheta,
602  Real & theta0
603 ) {
604  Ktheta = k_angle_;
605 
606  // Create mini-conformation for idealized residue
608 
609  // get angle
610  numeric::xyzVector<core::Real> x,y,z; // atom coords
611  if (atm1 > 0) {
612  x = newres->atom( atm1 ).xyz();
613  } else {
614  x = newres->upper_connect().icoor().build( restype );
615  }
616 
617  y = newres->atom( atm2 ).xyz();
618 
619  if (atm3 > 0) {
620  z = newres->atom( atm3 ).xyz();
621  } else {
622  z = newres->lower_connect().icoor().build( restype );
623  }
624 
625  theta0 = numeric::angle_radians ( x,y,z );
626 
627  // EXCEPTIONS
628  // ignore proline C-ND which is handled by pro_close
629  if (restype.aa() == core::chemical::aa_pro) {
630  bool hasCD = (atm1>0 && restype.atom_name(atm1)==" CD ")
631  || (atm2>0 && restype.atom_name(atm2)==" CD ")
632  || (atm3>0 && restype.atom_name(atm3)==" CD ");
633  bool hasN = (atm1>0 && restype.atom_name(atm1)==" N ")
634  || (atm2>0 && restype.atom_name(atm2)==" N ")
635  || (atm3>0 && restype.atom_name(atm3)==" N ");
636  if (hasCD && hasN)
637  Ktheta = theta0 = 0.0;
638  }
639 
640  // fpd ignore centroid angle in ALA and GLY
641  if ( (restype.aa() == core::chemical::aa_ala || restype.aa() == core::chemical::aa_gly) &&
642  ( (atm1>0 && restype.atom_name(atm1) == " CEN") || (atm3>0 && restype.atom_name(atm3) == " CEN") ) ) {
643  Ktheta = theta0 = 0.0;
644  }
645 
646  //fpd cutpoint variants
648  ( (atm1>0 && restype.atom_name(atm1) == "OVU1") || (atm3>0 && restype.atom_name(atm3) == "OVU1") ) ) {
649  Ktheta = theta0 = 0.0;
650  }
652  ( (atm1>0 && restype.atom_name(atm1) == "OVL1") || (atm3>0 && restype.atom_name(atm3) == "OVL1") ) ) {
653  Ktheta = theta0 = 0.0;
654  }
655 }
656 
657 
658 void
660  core::chemical::ResidueType const & restype,
661  int atm1,
662  int atm2,
663  Real &Kd,
664  Real &d0
665 )
666 {
667  Kd = k_length_;
668 
669  // Create mini-conformation for idealized residue
671 
672  // get length
673  numeric::xyzVector<core::Real> x,y,z; // atom coords
674  if (atm1 > 0) {
675  x = newres->atom( atm1 ).xyz();
676  } else {
677  x = newres->upper_connect().icoor().build( restype );
678  }
679 
680  if (atm2 > 0) {
681  y = newres->atom( atm2 ).xyz();
682  } else {
683  y = newres->lower_connect().icoor().build( restype );
684  }
685 
686  d0 = (x-y).length();
687 
688  // ignore proline C-ND which is handled by pro_close
689  if (restype.aa() == core::chemical::aa_pro &&
690  (atm1>0 && atm2>0) &&
691  ( ( restype.atom_name(atm1) == " CD " && restype.atom_name(atm2) == " N ") ||
692  ( restype.atom_name(atm2) == " CD " && restype.atom_name(atm1) == " N ") ) ) {
693  Kd = d0 = 0.0;
694  }
695 }
696 
697 
698 
699 //////////////////////
700 /// Torsion Database
701 // lookup ideal intra-res torsion
702 // torsion DB is unique is that it never tries to build from ideal
705  core::chemical::ResidueType const & restype,
706  std::string const & atm1_name,
707  std::string const & atm2_name,
708  std::string const & atm3_name,
709  std::string const & atm4_name
710 )
711 {
712  using namespace core::chemical;
713 
714  // use 'annotated sequence' to id this restype
715  std::string restag = get_restag( restype );
716 
717  // there is no bb-dep torsion database
718  // lookup in bb-indep table
719  // this can probably be made way faster
720  atm_name_quad tuple1( restag, atm1_name,atm2_name,atm3_name,atm4_name );
721  boost::unordered_map<atm_name_quad,CartBondedParametersOP>::iterator b_it = torsions_indep_.find( tuple1 );
722  if ( b_it != torsions_indep_.end() ) {
723  return b_it->second;
724  }
725 
726  atm_name_quad tuple2( "*", atm1_name,atm2_name,atm3_name,atm4_name );
727  b_it = torsions_indep_.find( tuple2 );
728  if ( b_it != torsions_indep_.end() ) {
729  return b_it->second;
730  }
731 
732  // if we don't find this torsion in the table, it's unconstrained
733  return NULL;
734 }
735 
736 
737 /// Angle Database
738 /// build from ideal if not found
741  core::chemical::ResidueType const & restype,
742  bool pre_proline,
743  std::string const & atm1_name,
744  std::string const & atm2_name,
745  std::string const & atm3_name,
746  int atm1idx,
747  int atm2idx,
748  int atm3idx
749 ) {
750  using namespace core::chemical;
751 
752  std::string restag = get_restag( restype );
753  atm_name_triple tuple( restag, atm1_name,atm2_name,atm3_name );
754 
755  // 1 lookup in bb-dep table
756  // figure out what table to look in
757  boost::unordered_map< atm_name_pair, CartBondedParametersOP > *angle_table;
758  if (restype.aa() == core::chemical::aa_gly) {
759  angle_table = &bondangles_bbdep_gly_;
760  } else if (restype.aa() == core::chemical::aa_pro) {
761  angle_table = &bondangles_bbdep_pro_;
762  } else if ( pre_proline ) {
763  angle_table = &bondangles_bbdep_prepro_;
764  } else if (restype.aa() == core::chemical::aa_ile || restype.aa() == core::chemical::aa_val) {
765  angle_table = &bondangles_bbdep_valile_;
766  } else {
767  angle_table = &bondangles_bbdep_def_;
768  }
769  atm_name_pair alt_tuple( atm1_name,atm2_name,atm3_name );
770  boost::unordered_map<atm_name_pair,CartBondedParametersOP>::iterator a_it = angle_table->find( alt_tuple );
771  if ( a_it != angle_table-> end() ) {
772  return a_it->second;
773  }
774 
775  // 2 lookup in bb-indep table
776  boost::unordered_map<atm_name_triple,CartBondedParametersOP>::iterator b_it = bondangles_indep_.find( tuple );
777  if ( b_it != bondangles_indep_.end() ) {
778  return b_it->second;
779  }
780 
781  atm_name_triple tuple_alt( "*", atm1_name,atm2_name,atm3_name );
782  b_it = bondangles_indep_.find( tuple_alt );
783  if ( b_it != bondangles_indep_.end() ) {
784  return b_it->second;
785  }
786 
787  // 3 build from ideal, add to bb-indep table
788  Real Ktheta, theta0;
789  lookup_bondangle_buildideal( restype, atm1idx, atm2idx, atm3idx, Ktheta, theta0 );
790  bondangles_indep_[ tuple ] = new BBIndepCartBondedParameters( theta0, Ktheta );
791  TR << "Adding undefined angle "
792  << tuple.get<0>() << ": " << tuple.get<1>() << "," << tuple.get<2>() << "," << tuple.get<3>() << " to DB with"
793  << " theta0 = " << theta0 << " , Ktheta = " << Ktheta << std::endl;
794 
795  return bondangles_indep_[ tuple ];
796 }
797 
798 /// BondLength Database
799 /// build from ideal if not found
802  chemical::ResidueType const & restype,
803  bool pre_proline,
804  std::string const & atm1_name,
805  std::string const & atm2_name,
806  int atm1idx,
807  int atm2idx
808 ) {
809 
810  // use 'annotated sequence' to id this restype
811  std::string restag = get_restag( restype );
812  atm_name_pair tuple( restag, atm1_name,atm2_name);
813 
814  // 1 lookup in bb-dep table
815  // figure out what table to look in
816  boost::unordered_map< atm_name_single, CartBondedParametersOP > *length_table;
817  if (restype.aa() == core::chemical::aa_gly) {
818  length_table = &bondlengths_bbdep_gly_;
819  } else if (restype.aa() == core::chemical::aa_pro) {
820  length_table = &bondlengths_bbdep_pro_;
821  } else if (restype.aa() == core::chemical::aa_ile || restype.aa() == core::chemical::aa_val) {
822  length_table = &bondlengths_bbdep_valile_;
823  } else if ( pre_proline ) {
824  length_table = &bondlengths_bbdep_prepro_;
825  } else {
826  length_table = &bondlengths_bbdep_def_;
827  }
828 
829  atm_name_single alt_tuple( atm1_name,atm2_name );
830  boost::unordered_map<atm_name_single,CartBondedParametersOP>::iterator a_it = length_table->find( alt_tuple );
831  if ( a_it != length_table->end() ) {
832  return a_it->second;
833  }
834 
835  // 2 lookup in bb-indep table
836  boost::unordered_map<atm_name_pair,CartBondedParametersOP>::iterator b_it = bondlengths_indep_.find( tuple );
837  if ( b_it != bondlengths_indep_.end() ) {
838  return b_it->second;
839  }
840 
841  atm_name_pair tuple_alt( "*", atm1_name,atm2_name );
842  b_it = bondlengths_indep_.find( tuple_alt );
843  if ( b_it != bondlengths_indep_.end() ) {
844  return b_it->second;
845  }
846 
847  // 3 build from ideal, add to bb-indep table
848  Real Kd, d0;
849  lookup_bondlength_buildideal( restype, atm1idx, atm2idx, Kd, d0 );
850  bondlengths_indep_[ tuple ] = new BBIndepCartBondedParameters( d0, Kd );
851  TR << "Adding undefined length "
852  << tuple.get<0>() << ": " << tuple.get<1>() << "," << tuple.get<2>() << "," << " to DB with"
853  << " d0 = " << d0 << " , Kd = " << Kd << std::endl;
854 
855  return bondlengths_indep_[ tuple ];
856 }
857 
858 
859 
860 // old-style interface to database
861 // somewhat slow as it will always build the ideal residue on the fly
862 void
864  core::chemical::ResidueType const & restype,
865  int atm1,
866  int atm2,
867  int atm3,
868  int atm4,
869  Real & Kphi,
870  Real & phi0,
871  Real &phi_step
872 ) {
873  using namespace core::chemical;
874 
875  Kphi=k_torsion_; // default
876  phi_step=0;
877 
878  if (!restype.is_protein()) {
879  Kphi = phi0 = 0;
880  return;
881  }
882 
883  // use 'annotated sequence' to id this restype
884  std::string restag = get_restag( restype );
885 
886  // Create mini-conformation for idealized residue
888  core::pose::Pose newpose;
889  newpose.append_residue_by_bond(*newres);
890 
891  // figure out if we need to constrain this torsion
892  bool need_to_constrain=true, proton_chi=false;
893 
894  // backbone -- we never need to constrain intrares backbones (for now)
895  if ( atm2 <= (int)newres->last_backbone_atom() && atm3 <= (int)newres->last_backbone_atom()) {
896  need_to_constrain = false;
897  }
898 
899  // chi
900  for ( Size j=1, j_end = restype.nchi(); j<= j_end; ++j ) {
901  id::AtomID n1,n2,n3,n4;
902  newpose.conformation().get_torsion_angle_atom_ids( id::TorsionID(1,id::CHI,j) ,n1,n2,n3,n4);
903  if ( ((int)n2.atomno() == atm2 && (int)n3.atomno() == atm3) || ((int)n2.atomno() == atm3 && (int)n3.atomno() == atm2) ) {
904  if (restype.is_proton_chi( j ) ) {
905  proton_chi = true;
906  } else {
907  need_to_constrain = false;
908  }
909  }
910  }
911 
912  // check if this corresponds to a DOF_ID
913  if ( !need_to_constrain ) {
914  Kphi=0.0;
915  phi0=0.0;
916  } else {
917  // get angle
918  numeric::xyzVector<core::Real> x,y,z, w; // atom coords
919  x = newres->atom( atm1 ).xyz();
920  y = newres->atom( atm2 ).xyz();
921  z = newres->atom( atm3 ).xyz();
922  w = newres->atom( atm4 ).xyz();
923 
924  phi0 = numeric::dihedral_radians ( x,y,z,w );
925 
926  //////// exceptions!
927  // fpd ignore proline C-ND which is handled by pro_close
928  if (restype.aa() == core::chemical::aa_pro) {
929  bool hasCD = (restype.atom_name(atm1)==" CD ") || (restype.atom_name(atm2)==" CD ")
930  || (restype.atom_name(atm3)==" CD ") || (restype.atom_name(atm4)==" CD ");
931  bool hasN = (restype.atom_name(atm1)==" N ") || (restype.atom_name(atm2)==" N ")
932  || (restype.atom_name(atm3)==" N ") || (restype.atom_name(atm4)==" N ");
933  if (hasCD && hasN) {
934  Kphi=0.0; phi0=0.0;
935  }
936  }
938  ( ( restype.atom_name(atm2) == " N " && restype.atom_name(atm3) == " CA ") ||
939  ( restype.atom_name(atm3) == " N " && restype.atom_name(atm2) == " CA ") ) ) {
940  Kphi=0.0; phi0=0.0;
941  }
942  if ( restype.atom_name(atm1) == " CEN" || restype.atom_name(atm4) == " CEN") {
943  Kphi=0.0; phi0=0.0;
944  }
945  if ( restype.aa() == aa_cys && restype.has_variant_type( chemical::DISULFIDE ) &&
946  (restype.atom_name(atm2) == " SG " || restype.atom_name(atm3) == " SG ") ) {
947  Kphi=0.0; phi0=0.0;
948  }
949  if ( restype.aa() == aa_arg &&
950  ( restype.atom_name(atm1) == " NH1" || restype.atom_name(atm4) == " NH1"
951  || restype.atom_name(atm1) == " NH2" || restype.atom_name(atm4) == " NH2") ) {
952  phi_step = numeric::constants::d::pi;
953  }
955  ( ( restype.atom_name(atm2) == " N " && restype.atom_name(atm3) == " CA ") ||
956  ( restype.atom_name(atm3) == " N " && restype.atom_name(atm2) == " CA ") ) ) {
957  Kphi=k_torsion_proton_;
958  phi_step = 2.0*numeric::constants::d::pi/3.0;
959  }
960 
961  if (proton_chi) {
962  Kphi=k_torsion_proton_;
963  utility::vector1< Real > const & v = restype.proton_chi_samples( 1 );
964  phi0 = numeric::constants::d::deg2rad*v[1];
965  phi_step = std::fabs( numeric::constants::d::deg2rad*(v[2]-v[1]) ); // i guess this assumes we have two adjacent samples
966  }
967  }
968 }
969 
970 // old-style interface to database
971 // somewhat slow as it will always build the ideal residue on the fly
972 void
974  core::pose::Pose const & /*pose*/,
975  core::conformation::Residue const & res,
976  int atm1,
977  int atm2,
978  int atm3,
979  Real & Ktheta,
980  Real & theta0
981 ) {
982  using namespace core::chemical;
983 
984  Ktheta=k_angle_;
985  ResidueType const & restype = res.type();
986  std::string restag = get_restag( restype );
987 
988  // Create mini-conformation for idealized residue
990 
991  // use these for mm Ktheta lookup
992  //Size mmatm1, mmatm2, mmatm3;
993 
994  // get angle
995  numeric::xyzVector<core::Real> x,y,z; // atom coords
996  if (atm1 > 0) {
997  x = newres->atom( atm1 ).xyz();
998  }
999  else {
1000  x = newres->residue_connection( -atm1 ).icoor().build( restype );
1001  }
1002  if (atm2 > 0) {
1003  y = newres->atom( atm2 ).xyz();
1004  }
1005  else {
1006  y = newres->residue_connection( -atm2 ).icoor().build( restype );
1007  }
1008  if (atm3 > 0) {
1009  z = newres->atom( atm3 ).xyz();
1010  }
1011  else {
1012  z = newres->residue_connection( -atm3 ).icoor().build( restype );
1013  }
1014 
1015  theta0 = numeric::angle_radians ( x,y,z );
1016 
1017  //fpd ignore proline C-ND which is handled by pro_close
1018  if (restype.aa() == core::chemical::aa_pro) {
1019  bool hasCD = (atm1>0 && restype.atom_name(atm1)==" CD ")
1020  || (atm2>0 && restype.atom_name(atm2)==" CD ")
1021  || (atm3>0 && restype.atom_name(atm3)==" CD ");
1022  bool hasN = (atm1>0 && restype.atom_name(atm1)==" N ")
1023  || (atm2>0 && restype.atom_name(atm2)==" N ")
1024  || (atm3>0 && restype.atom_name(atm3)==" N ");
1025  if (hasCD && hasN)
1026  Ktheta = theta0 = 0.0;
1027  }
1028 
1029  if ( (restype.aa() == core::chemical::aa_ala || restype.aa() == core::chemical::aa_gly) &&
1030  ( (atm1>0 && restype.atom_name(atm1) == " CEN") || (atm3>0 && restype.atom_name(atm3) == " CEN") ) ) {
1031  Ktheta = theta0 = 0.0;
1032  }
1033  if ( restype.has_variant_type(chemical::CUTPOINT_UPPER) &&
1034  ( (atm1>0 && restype.atom_name(atm1) == "OVU1") || (atm3>0 && restype.atom_name(atm3) == "OVU1") ) ) {
1035  Ktheta = theta0 = 0.0;
1036  }
1037  if ( restype.has_variant_type(chemical::CUTPOINT_LOWER) &&
1038  ( (atm1>0 && restype.atom_name(atm1) == "OVL1") || (atm3>0 && restype.atom_name(atm3) == "OVL1") ) ) {
1039  Ktheta = theta0 = 0.0;
1040  }
1041 
1042  return;
1043 }
1044 
1045 // old-style interface to database
1046 // somewhat slow as it will always build the ideal residue on the fly
1047 void
1049  core::pose::Pose const & /*pose*/,
1050  core::conformation::Residue const & res,
1051  int atm1,
1052  int atm2,
1053  Real &Kd,
1054  Real &d0
1055 )
1056 {
1057  using namespace core::chemical;
1058 
1059  Kd=k_length_;
1060  ResidueType const & restype = res.type();
1061  std::string restag = get_restag( restype );
1062 
1063  // Create mini-conformation for idealized residue
1065 
1066  // get length
1067  numeric::xyzVector<core::Real> x,y,z; // atom coords
1068  if (atm1 > 0) {
1069  x = newres->atom( atm1 ).xyz();
1070  }
1071  else {
1072  x = newres->residue_connection( -atm1 ).icoor().build( restype );
1073  }
1074  if (atm2 > 0) {
1075  y = newres->atom( atm2 ).xyz();
1076  }
1077  else {
1078  y = newres->residue_connection( -atm2 ).icoor().build( restype );
1079  }
1080 
1081  d0 = (x-y).length();
1082 
1083  if (restype.aa() == core::chemical::aa_pro &&
1084  (atm1>0 && atm2>0) &&
1085  ( ( restype.atom_name(atm1) == " CD " && restype.atom_name(atm2) == " N ") ||
1086  ( restype.atom_name(atm2) == " CD " && restype.atom_name(atm1) == " N ") ) ) {
1087  Kd = d0 = 0.0;
1088  }
1089 
1090  return;
1091 }
1092 
1095  core::chemical::ResidueType const & restype,
1096  bool prepro
1097 )
1098 {
1099  std::map< chemical::ResidueType const *, ResidueCartBondedParametersOP > const & resdatamap = prepro ?
1101 
1102  std::map< chemical::ResidueType const *, ResidueCartBondedParametersOP >::const_iterator iter = resdatamap.find( & restype );
1103  if ( iter == resdatamap.end() ) {
1104  create_parameters_for_restype( restype, prepro );
1105  std::map< chemical::ResidueType const *, ResidueCartBondedParametersOP >::const_iterator iter2 = resdatamap.find( & restype );
1106  assert ( iter2 != resdatamap.end() );
1107  return *iter2->second;
1108  }
1109  return *iter->second;
1110 }
1111 
1112 
1113 void
1115  core::chemical::ResidueType const & rsd_type,
1116  bool prepro
1117 )
1118 {
1120 
1121  for ( Size dihe = 1; dihe <= rsd_type.ndihe(); ++dihe ){
1122  // get ResidueType ints
1123  Size rt1 = ( rsd_type.dihedral( dihe ) ).key1();
1124  Size rt2 = ( rsd_type.dihedral( dihe ) ).key2();
1125  Size rt3 = ( rsd_type.dihedral( dihe ) ).key3();
1126  Size rt4 = ( rsd_type.dihedral( dihe ) ).key4();
1128  ids[ 1 ] = rt1; ids[ 2 ] = rt2; ids[ 3 ] = rt3; ids[ 4 ] = rt4;
1129 
1130  // lookup Kphi and phi0
1131  std::string atm1name=rsd_type.atom_name(rt1); boost::trim(atm1name);
1132  std::string atm2name=rsd_type.atom_name(rt2); boost::trim(atm2name);
1133  std::string atm3name=rsd_type.atom_name(rt3); boost::trim(atm3name);
1134  std::string atm4name=rsd_type.atom_name(rt4); boost::trim(atm4name);
1135  CartBondedParametersCOP tor_params = lookup_torsion(rsd_type,
1136  atm1name,atm2name,atm3name,atm4name );
1137 
1138  if ( !tor_params || tor_params->is_null() ) continue;
1139 
1140  restype_params->add_torsion_parameter( ids, tor_params );
1141  }
1142 
1143  // for each angle in the residue
1144  for ( Size bondang = 1; bondang <= rsd_type.num_bondangles(); ++bondang ) {
1145  // get ResidueType ints
1146  Size rt1 = ( rsd_type.bondangle( bondang ) ).key1();
1147  Size rt2 = ( rsd_type.bondangle( bondang ) ).key2();
1148  Size rt3 = ( rsd_type.bondangle( bondang ) ).key3();
1150  ids[ 1 ] = rt1; ids[ 2 ] = rt2; ids[ 3 ] = rt3;
1151 
1152  // lookup Ktheta and theta0
1153  std::string atm1name=rsd_type.atom_name(rt1); boost::trim(atm1name);
1154  std::string atm2name=rsd_type.atom_name(rt2); boost::trim(atm2name);
1155  std::string atm3name=rsd_type.atom_name(rt3); boost::trim(atm3name);
1156  CartBondedParametersCOP ang_params = lookup_angle( rsd_type, prepro,
1157  atm1name,atm2name,atm3name, rt1,rt2,rt3 );
1158 
1159  if ( ang_params->is_null() ) continue;
1160 
1161  restype_params->add_angle_parameter( ids, ang_params );
1162  }
1163 
1164  // for each bond
1165  for (Size atm_i=1; atm_i<=rsd_type.natoms(); ++atm_i) {
1166  chemical::AtomIndices atm_nbrs = rsd_type.nbrs( atm_i );
1167  for (Size j=1; j<=atm_nbrs.size(); ++j) {
1168  Size atm_j = atm_nbrs[j];
1169  if ( atm_i < atm_j ) { // only score each bond once -- use restype index to define ordering
1170 
1172  ids[1] = atm_i; ids[2] = atm_j;
1173 
1174  // lookup Kd and d0
1175  std::string atm1name = rsd_type.atom_name(atm_i); boost::trim(atm1name);
1176  std::string atm2name = rsd_type.atom_name(atm_j); boost::trim(atm2name);
1177  CartBondedParametersCOP len_params = lookup_length(rsd_type, prepro,
1178  atm1name,atm2name, atm_i, atm_j );
1179 
1180  if ( len_params->is_null() ) continue;
1181 
1182  restype_params->add_length_parameter( ids, len_params );
1183  }
1184  }
1185  }
1186 
1187  // improper torsions
1188  {
1189  using namespace core::chemical;
1190 
1191  std::string atm1, atm2, atm3, atm4;
1192  if (rsd_type.aa() == aa_asp && rsd_type.has( "CB" ) && rsd_type.has( "CG" ) && rsd_type.has( "OD1" ) && rsd_type.has( "OD2" ) ) {
1193  // asp CB-CG-OD1-OD2
1194  atm1 = "CB"; atm2 = "CG"; atm3 = "OD1"; atm4 = "OD2";
1195  } else if (rsd_type.aa() == aa_glu && rsd_type.has( "CG" ) && rsd_type.has( "CD" ) && rsd_type.has( "OE1" ) && rsd_type.has( "OE2" )) {
1196  // glu CG-CD-OE1-OE2
1197  atm1 = "CG"; atm2 = "CD"; atm3 = "OE1"; atm4 = "OE2";
1198  } else if (rsd_type.aa() == aa_asn && rsd_type.has( "CB" ) && rsd_type.has( "CG" ) && rsd_type.has( "OD1" ) && rsd_type.has( "ND2" )) {
1199  // asn CB-CG-OD-ND
1200  atm1 = "CB"; atm2 = "CG"; atm3 = "OD1"; atm4 = "ND2";
1201  } else if (rsd_type.aa() == aa_gln && rsd_type.has( "CG" ) && rsd_type.has( "CD" ) && rsd_type.has( "OE1" ) && rsd_type.has( "NE2" )) {
1202  // gln CG-CD-OE-NE
1203  atm1 = "CG"; atm2 = "CD"; atm3 = "OE1"; atm4 = "NE2";
1204  }
1205 
1206  if ( atm1 != "" ) {
1208  ids[1] = rsd_type.atom_index(atm1);
1209  ids[2] = rsd_type.atom_index(atm2);
1210  ids[3] = rsd_type.atom_index(atm3);
1211  ids[4] = rsd_type.atom_index(atm4);
1212 
1213  CartBondedParametersCOP tor_params = lookup_torsion( rsd_type, atm1, atm2, atm3, atm4 );
1214  if ( ! tor_params->is_null() ) {
1215  restype_params->add_improper_torsion_parameter( ids, tor_params );
1216  }
1217  }
1218  }
1219 
1220  /// Keep track of the bond angles and lengths that are used in the backbone dependent calculations
1221 
1222  // loop over all bb-dep angles and bonds;
1223  // hardcode the bbdep angles and lengths to save a bit of time
1224  // connection IDs are hardcoded ... is this a problem? APL: Yes, c- or n- terminal disulfides would give you
1225  // trouble, but the connection IDs don't have to be hard coded.
1226 
1227  //fpd protein only
1228  if (rsd_type.is_protein()) {
1229  /// backbone dependent bond lengths
1230  bool is_nterm = rsd_type.aa() <= chemical::num_canonical_aas && rsd_type.has_variant_type( core::chemical::LOWER_TERMINUS );
1231  bool is_cterm = rsd_type.aa() <= chemical::num_canonical_aas && rsd_type.has_variant_type( core::chemical::UPPER_TERMINUS );
1232  for (int i=1; i<=5; ++i) {
1233  if (i==1 && is_nterm) continue;
1234  if (i==3 && rsd_type.aa() == core::chemical::aa_gly) continue;
1235 
1236  std::string atm1,atm2;
1237  core::Size rt1,rt2;
1238  if (i==1) { atm1="C"; atm2="N"; rt1 = 0; rt2 = rsd_type.atom_index(" N ");}
1239  if (i==2) { atm1="N"; atm2="CA"; rt1 = rsd_type.atom_index(" N "); rt2 = rsd_type.atom_index(" CA "); }
1240  if (i==3) { atm1="CA"; atm2="CB"; rt1 = rsd_type.atom_index(" CA "); rt2 = rsd_type.atom_index(" CB "); }
1241  if (i==4) { atm1="CA"; atm2="C"; rt1 = rsd_type.atom_index(" CA "); rt2 = rsd_type.atom_index(" C "); }
1242  if (i==5) { atm1="C"; atm2="O"; rt1 = rsd_type.atom_index(" C "); rt2 = rsd_type.atom_index(" O "); }
1243 
1245  ids[1] = rt1; ids[2] = rt2;
1246 
1247  CartBondedParametersCOP len_params = lookup_length( rsd_type, is_nterm ? false : prepro, atm1, atm2, rt1, rt2 );
1248  restype_params->add_bbdep_length_parameter( ids, len_params );
1249  }
1250 
1251  // backbone dependent bond angles
1252  for (int i=1; i<=7; ++i) {
1253  if ((i==2 || i==4) && rsd_type.aa() == core::chemical::aa_gly) continue;
1254  if (i==1 && is_nterm) continue;
1255  if ((i==6 || i==7) && is_cterm) continue;
1256 
1257  std::string atm1,atm2,atm3;
1258  core::Size rt1,rt2,rt3;
1259  if (i==1) { atm1="C"; atm2="N"; atm3="CA"; rt1=0; rt2=rsd_type.atom_index(" N "); rt3=rsd_type.atom_index(" CA ");}
1260  if (i==2) { atm1="N"; atm2="CA"; atm3="CB"; rt1=rsd_type.atom_index(" N "); rt2=rsd_type.atom_index(" CA "); rt3=rsd_type.atom_index(" CB "); }
1261  if (i==3) { atm1="N"; atm2="CA"; atm3="C"; rt1=rsd_type.atom_index(" N "); rt2=rsd_type.atom_index(" CA "); rt3=rsd_type.atom_index(" C "); }
1262  if (i==4) { atm1="CB"; atm2="CA"; atm3="C"; rt1=rsd_type.atom_index(" CB "); rt2=rsd_type.atom_index(" CA "); rt3=rsd_type.atom_index(" C "); }
1263  if (i==5) { atm1="CA"; atm2="C"; atm3="O"; rt1=rsd_type.atom_index(" CA "); rt2=rsd_type.atom_index(" C "); rt3=rsd_type.atom_index(" O "); }
1264  if (i==6) { atm1="CA"; atm2="C"; atm3="N"; rt1=rsd_type.atom_index(" CA "); rt2=rsd_type.atom_index(" C "); rt3=0; }
1265  if (i==7) { atm1="O"; atm2="C"; atm3="N"; rt1=rsd_type.atom_index(" O "); rt2=rsd_type.atom_index(" C "); rt3=0; }
1266 
1268  ids[1] = rt1; ids[2] = rt2; ids[3] = rt3;
1269 
1270  CartBondedParametersCOP ang_params = lookup_angle(rsd_type, prepro, atm1,atm2,atm3, rt1,rt2,rt3 );
1271  restype_params->add_bbdep_angle_parameter( ids, ang_params );
1272  }
1273  }
1274 
1275  // atom pairs near the upper connect:
1276  {
1277  if ( rsd_type.upper_connect_id() != 0 ) {
1278  utility::vector1< chemical::two_atom_set > const & upconn_ats(
1280  for ( Size ii = 1; ii <= upconn_ats.size(); ++ii ) {
1281 
1282  std::string atm1name=rsd_type.atom_name( upconn_ats[ii].key2() ); boost::trim(atm1name);
1283  std::string atm2name=rsd_type.atom_name( upconn_ats[ii].key1() ); boost::trim(atm2name);
1284  std::string atm3name="N";
1285 
1286  // lookup Ktheta and theta0
1287  CartBondedParametersCOP ang_params = lookup_angle( rsd_type, prepro,
1288  atm1name, atm2name, atm3name, upconn_ats[ii].key2(), upconn_ats[ii].key1(),
1289  -1 * ( (int) rsd_type.upper_connect_id() ));
1291  inds[1] = upconn_ats[ii].key2();
1292  inds[2] = upconn_ats[ii].key1();
1293  inds[3] = 0;
1294  restype_params->add_upper_connect_angle_params( inds, ang_params );
1295  }
1296  }
1297  }
1298 
1299  // atom pairs near the lower connect:
1300  {
1301  if ( rsd_type.lower_connect_id() != 0 ) {
1302  utility::vector1< chemical::two_atom_set > const & loconn_ats(
1304  for ( Size ii = 1; ii <= loconn_ats.size(); ++ii ) {
1305 
1306  std::string atm1name=rsd_type.atom_name( loconn_ats[ii].key2() ); boost::trim(atm1name);
1307  std::string atm2name=rsd_type.atom_name( loconn_ats[ii].key1() ); boost::trim(atm2name);
1308  std::string atm3name="C";
1309 
1310  // lookup Ktheta and theta0
1311  CartBondedParametersCOP ang_params = lookup_angle( rsd_type, prepro,
1312  atm1name, atm2name, atm3name, loconn_ats[ii].key2(), loconn_ats[ii].key1(),
1313  -1 * ( (int) rsd_type.lower_connect_id() ));
1315  inds[1] = loconn_ats[ii].key2();
1316  inds[2] = loconn_ats[ii].key1();
1317  inds[3] = 0;
1318  restype_params->add_lower_connect_angle_params( inds, ang_params );
1319  }
1320  }
1321  }
1322 
1323  /// Atom IDs
1324  if ( rsd_type.has( "N" ) ) {
1325  restype_params->bb_N_index( rsd_type.atom_index( "N" ) );
1326  }
1327  if ( rsd_type.has( "CA" ) ) {
1328  restype_params->bb_CA_index( rsd_type.atom_index( "CA" ) );
1329  }
1330  if ( rsd_type.has( "C" ) ) {
1331  restype_params->bb_C_index( rsd_type.atom_index( "C" ) );
1332  }
1333  if ( rsd_type.has( "O" ) ) {
1334  restype_params->bb_O_index( rsd_type.atom_index( "O" ) );
1335  }
1336  if ( rsd_type.has( "H" ) ) {
1337  restype_params->bb_H_index( rsd_type.atom_index( "H" ) );
1338  }
1339 
1340  /// ca_cprev_n_h improper torsion
1341  if ( restype_params->bb_N_index() != 0 && restype_params->bb_H_index() != 0 && restype_params->bb_CA_index() != 0 ) {
1342  CartBondedParametersCOP tor_params = lookup_torsion( rsd_type, "CA", "C", "N", "H" );
1343  restype_params->ca_cprev_n_h_interres_torsion_params( tor_params );
1344  }
1345 
1346  // ca_nnext_c_o improper torsion
1347  if ( restype_params->bb_C_index() != 0 && restype_params->bb_O_index() != 0 && restype_params->bb_CA_index() != 0 ) {
1348  CartBondedParametersCOP tor_params = lookup_torsion( rsd_type, "CA", "N", "C", "O" );
1349  restype_params->ca_nnext_c_o_interres_torsion_params( tor_params );
1350  }
1351 
1352  // caprev_n bond length
1353  if ( restype_params->bb_N_index() != 0 && rsd_type.lower_connect_id() != 0 ) {
1354  CartBondedParametersCOP len_params = lookup_length( rsd_type, prepro, "N", "C", restype_params->bb_N_index(), -1 * ((int) rsd_type.lower_connect_id() ) );
1355  assert( len_params );
1356  restype_params->cprev_n_bond_length_params( len_params );
1357  }
1358 
1359  if ( prepro ) {
1360  prepro_restype_data_[ & rsd_type ] = restype_params;
1361  } else {
1362  nonprepro_restype_data_[ & rsd_type ] = restype_params;
1363  }
1364 
1365 }
1366 
1367 
1368 
1369 //////////////////////
1370 /// EnergyMethod
1373 {
1374  // if flag _or_ energy method wants a linear potential, make the potential linear
1376  basic::options::option[ basic::options::OptionKeys::score::linear_bonded_potential ]() ||
1377  options.get_cartesian_bonded_linear();
1378 
1379  // initialize databases
1380  core::Real cartbonded_len, cartbonded_ang, cartbonded_tors, cartbonded_proton , cartbonded_improper;
1381  options.get_cartesian_bonded_parameters( cartbonded_len, cartbonded_ang, cartbonded_tors, cartbonded_proton , cartbonded_improper );
1382  if (!db_) {
1383  db_ = new IdealParametersDatabase(cartbonded_len, cartbonded_ang, cartbonded_tors, cartbonded_proton , cartbonded_improper);
1384  }
1385 }
1386 
1389 }
1390 
1392 
1395  return new CartesianBondedEnergy( *this );
1396 }
1397 
1398 
1399 void
1401  pose::Pose & pose,
1402  ScoreFunction const &
1403 ) const {
1404  using namespace methods;
1405 
1406  // create LR energy container
1407  LongRangeEnergyType const & lr_type( long_range_type() );
1408  Energies & energies( pose.energies() );
1409  bool create_new_lre_container( false );
1410 
1411  if ( energies.long_range_container( lr_type ) == 0 ) {
1412  create_new_lre_container = true;
1413  } else {
1414  LREnergyContainerOP lrc = energies.nonconst_long_range_container( lr_type );
1415  PeptideBondedEnergyContainerOP dec( static_cast< PeptideBondedEnergyContainer * > ( lrc.get() ) );
1416  Size nres = pose.total_residue();
1418  nres = core::pose::symmetry::symmetry_info(pose)->num_independent_residues();
1419  if ( dec->size() != nres ) {
1420  create_new_lre_container = true;
1421  }
1422  }
1423 
1424  if ( create_new_lre_container ) {
1425  Size nres = pose.total_residue();
1427  nres = core::pose::symmetry::symmetry_info(pose)->num_independent_residues();
1428  TR << "Creating new peptide-bonded energy container (" << nres << ")" << std::endl;
1430  s_types.push_back( cart_bonded );
1431  s_types.push_back( cart_bonded_angle );
1432  s_types.push_back( cart_bonded_length );
1433  s_types.push_back( cart_bonded_torsion );
1434  LREnergyContainerOP new_dec = new PeptideBondedEnergyContainer( nres, s_types );
1435  energies.set_long_range_container( lr_type, new_dec );
1436  }
1437 }
1438 
1439 bool
1441  pose::Pose const &,
1442  Size res1,
1443  Size res2
1444 ) const {
1445  // is this fn. called?
1446  return ( res1 == (res2+1) || res1 == (res2-1) );
1447 }
1448 
1449 
1450 
1451 void
1453  conformation::Residue const & rsd1,
1454  conformation::Residue const & rsd2,
1455  pose::Pose const & pose,
1456  ScoreFunction const & sf,
1457  EnergyMap & emap
1458 ) const
1459 {
1460  if ( rsd1.seqpos() < rsd2.seqpos() ) {
1461  residue_pair_energy_sorted( rsd1, rsd2, pose, sf, emap );
1462  } else {
1463  residue_pair_energy_sorted( rsd2, rsd1, pose, sf, emap );
1464  }
1465 }
1466 
1467 
1468 // because of preproline potential, everything is done in res_pair
1469 void
1471  conformation::Residue const &,
1472  pose::Pose const &,
1473  ScoreFunction const &,
1474  EnergyMap &
1475 ) const
1476 {
1477 }
1478 
1479 ///////////////////////////
1480 ///
1481 void
1483  conformation::Residue const & rsd1,
1484  conformation::Residue const & rsd2,
1485  ResSingleMinimizationData const &,
1486  ResSingleMinimizationData const &,
1487  ResPairMinimizationData const & /*min_data*/,
1488  pose::Pose const & pose,
1489  EnergyMap const & weights,
1490  utility::vector1< DerivVectorPair > & r1_atom_derivs,
1491  utility::vector1< DerivVectorPair > & r2_atom_derivs
1492 ) const
1493 {
1494  using namespace numeric;
1495 
1496  assert( rsd2.seqpos() > rsd1.seqpos() );
1497  bool preproline = (rsd2.aa()==core::chemical::aa_pro);
1498 
1499  if ( rsd1.aa() == core::chemical::aa_vrt) return;
1500 
1501  ResidueCartBondedParameters const & res1params = db_->parameters_for_restype( rsd1.type(), preproline );
1502  ResidueCartBondedParameters const & res2params = db_->parameters_for_restype( rsd2.type(), false );
1503 
1504  // get phi,psis for bb-dep angles/lengths
1505  Real phi1=0,psi1=0,phi2=0,psi2=0;
1506  if (rsd1.is_protein()) {
1507  phi1 = nonnegative_principal_angle_degrees( rsd1.mainchain_torsion(1));
1508  psi1 = nonnegative_principal_angle_degrees( rsd1.mainchain_torsion(2));
1509  }
1510  if (rsd2.is_protein()) {
1511  phi2 = nonnegative_principal_angle_degrees( rsd2.mainchain_torsion(1));
1512  psi2 = nonnegative_principal_angle_degrees( rsd2.mainchain_torsion(2));
1513  }
1514 
1515  // get subcomponents
1516  eval_singleres_derivatives( rsd1, res1params, phi1, psi1, weights, r1_atom_derivs );
1517 
1518  // cterm special case
1519  Size nres = pose.total_residue();
1520  if( core::pose::symmetry::is_symmetric(pose) ) nres = core::pose::symmetry::symmetry_info(pose)->num_independent_residues();
1521  if (rsd2.seqpos() == nres) {
1522  eval_singleres_derivatives(rsd2, res2params, phi2, psi2, weights, r2_atom_derivs );
1523  }
1524 
1525  // bail out if the residues aren't bonded or we cross a cutpoint
1526  if (!rsd1.is_bonded(rsd2)) { return; }
1527  if ( pose.fold_tree().is_cutpoint( rsd1.seqpos() ) ) { return; }
1528 
1529  eval_improper_torsion_derivatives( rsd1, rsd2, res1params, res2params, weights, r1_atom_derivs, r2_atom_derivs );
1530 
1532  rsd1, rsd2, res1params, res2params, phi1, psi1,
1533  weights, r1_atom_derivs, r2_atom_derivs );
1534 
1536  rsd1, rsd2, res1params, res2params, phi2, psi2,
1537  weights, r1_atom_derivs, r2_atom_derivs );
1538 
1540  rsd1, rsd2, res1params, res2params, phi2, psi2,
1541  weights, r1_atom_derivs, r2_atom_derivs );
1542 }
1543 
1544 /// @details Evaluate dE/dphi and dE/dpsi for the backbone-dependent
1545 /// terms, if they are active.
1546 Real
1548  conformation::Residue const & rsd,
1549  ResSingleMinimizationData const & /*min_data*/,
1550  id::DOF_ID const & /*dof_id*/,
1551  id::TorsionID const & tor_id,
1552  pose::Pose const & pose,
1553  ScoreFunction const & /*sfxn*/,
1554  EnergyMap const & weights
1555 ) const {
1556  using namespace numeric;
1557  using numeric::constants::d::pi;
1558 
1559  // save some time if we're only doing bb-indep
1560  if (!db_->bbdep_bond_params()) return 0.0;
1561 
1562  if ( !tor_id.valid() || tor_id.type()!=id::BB || tor_id.torsion() > 2 || !rsd.is_protein() )
1563  return 0.0;
1564 
1565  core::Size resid = rsd.seqpos();
1566  //bool is_nterm = ((resid==1) || pose.fold_tree().is_cutpoint( resid-1 ));
1567  bool is_cterm = ((resid==pose.total_residue()) || pose.fold_tree().is_cutpoint( resid ));
1568  bool preproline = (!is_cterm && pose.residue( resid+1 ).aa() == core::chemical::aa_pro);
1569 
1570  // phi/psi
1571  Real phi=0,psi=0;
1572  if (rsd.is_protein()) {
1573  phi = nonnegative_principal_angle_degrees( rsd.mainchain_torsion(1));
1574  psi = nonnegative_principal_angle_degrees( rsd.mainchain_torsion(2));
1575  }
1576 
1577  ResidueCartBondedParameters const & resparams = db_->parameters_for_restype( rsd.type(), preproline );
1578 
1579  core::Real deriv=0.0;
1580 
1581  /// Backbone dependent bond lengths
1582  utility::vector1< ResidueCartBondedParameters::length_parameter > const & lps = resparams.bbdep_length_parameters();
1583  for ( Size ii = 1; ii <= lps.size(); ++ii ) {
1584  ResidueCartBondedParameters::Size2 const & atids( lps[ ii ].first );
1585  CartBondedParameters const & len_params( *lps[ ii ].second );
1586 
1587  Real const K = len_params.K(phi,psi);
1588  Real const mu = len_params.mu(phi,psi);
1589  Vector at1xyz, at2xyz( rsd.xyz( atids[2] ));
1590  if ( atids[1] == 0 ) {
1591  // connection atom from previous residue
1592  chemical::ResidueType const & prevrestype = pose.residue_type( rsd.seqpos() - 1 );
1593  Size prev_c_atom = prevrestype.upper_connect().atomno();
1594  at1xyz = pose.xyz( id::AtomID( prev_c_atom, rsd.seqpos() - 1 ));
1595  } else {
1596  at1xyz = rsd.xyz( atids[1] );
1597  }
1598 
1599  Real const d = at1xyz.distance( at2xyz );
1600 
1601  core::Real dmu_dtor, dK_dtor=0.0;
1602  core::Real dscore_dK=0.0, dscore_dmu;
1603 
1604  if (tor_id.torsion()==1) {
1605  dmu_dtor = len_params.dmu_dphi(phi,psi);
1606  } else {
1607  dmu_dtor = len_params.dmu_dpsi(phi,psi);
1608  }
1609  if (linear_bonded_potential_ && std::fabs(d - mu)>1) {
1610  dscore_dmu = -K * ((d - mu)>0 ? 1:-1);
1611  } else {
1612  dscore_dmu = -K * (d - mu);
1613  }
1614  if (db_->bbdep_bond_devs()) {
1615  if (tor_id.torsion()==1) {
1616  dK_dtor = len_params.dK_dphi(phi,psi);
1617  } else {
1618  dK_dtor = len_params.dK_dpsi(phi,psi);
1619  }
1620  if (linear_bonded_potential_ && std::fabs(d - mu)>1) {
1621  dscore_dK = 0.5*std::fabs(d - mu);
1622  } else {
1623  dscore_dK = 0.5*(d - mu)*(d - mu); // currently we have no -log(K) term in our score
1624  }
1625  }
1626 
1627  // derivatives w.r.t. phi/psi
1628  deriv += (weights[ cart_bonded_length ] + weights[ cart_bonded ]) * (dscore_dmu*dmu_dtor + dscore_dK*dK_dtor);
1629  }
1630 
1631  /// Backbone-dependent bond angles
1632  utility::vector1< ResidueCartBondedParameters::angle_parameter > const & aps = resparams.bbdep_angle_parameters();
1633  for ( Size ii = 1; ii <= aps.size(); ++ii ) {
1634  ResidueCartBondedParameters::Size3 const & atids( aps[ ii ].first );
1635  CartBondedParameters const & ang_params( *aps[ ii ].second );
1636 
1637  Real const K = ang_params.K(phi,psi);
1638  Real const mu = ang_params.mu(phi,psi);
1639  Vector at1xyz, at2xyz( rsd.xyz( atids[2] )), at3xyz;
1640  if ( atids[1] == 0 ) {
1641  // connection atom from previous residue
1642  chemical::ResidueType const & prevrestype = pose.residue_type( rsd.seqpos() - 1 );
1643  Size prev_c_atom = prevrestype.upper_connect().atomno();
1644  at1xyz = pose.xyz( id::AtomID( prev_c_atom, rsd.seqpos() - 1 ));
1645  } else {
1646  at1xyz = rsd.xyz( atids[1] );
1647  }
1648  if ( atids[3] == 0 ) {
1649  // connection atom from the next residue
1650  chemical::ResidueType const & nextrestype = pose.residue_type( rsd.seqpos() + 1 );
1651  Size next_n_atom = nextrestype.lower_connect().atomno();
1652  at3xyz = pose.xyz( id::AtomID( next_n_atom, rsd.seqpos() + 1 ));
1653  } else {
1654  at3xyz = rsd.xyz( atids[3] );
1655  }
1656 
1657  Real const angle = numeric::angle_radians(at1xyz,at2xyz,at3xyz);
1658 
1659  core::Real dmu_dtor, dK_dtor=0.0;
1660  core::Real dscore_dK=0.0, dscore_dmu;
1661 
1662  if (tor_id.torsion()==1) {
1663  dmu_dtor = ang_params.dmu_dphi(phi,psi);
1664  } else {
1665  dmu_dtor = ang_params.dmu_dpsi(phi,psi);
1666  }
1667  if (linear_bonded_potential_ && std::fabs(angle - mu)>1) {
1668  dscore_dmu = -K * ((angle - mu)>0 ? 1:-1);
1669  } else {
1670  dscore_dmu = -K * (angle - mu);
1671  }
1672 
1673  if (db_->bbdep_bond_devs()) {
1674  if (tor_id.torsion()==1) {
1675  dK_dtor = ang_params.dK_dphi(phi,psi);
1676  } else {
1677  dK_dtor = ang_params.dK_dpsi(phi,psi);
1678  }
1679  if (linear_bonded_potential_ && std::fabs(angle - mu)>1) {
1680  dscore_dK = 0.5*std::fabs(angle - mu);
1681  } else {
1682  dscore_dK = 0.5*(angle - mu)*(angle - mu); // currently we have no -log(K) term in our score
1683  }
1684  }
1685 
1686  // derivatives w.r.t. phi/psi
1687  deriv += (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * (dscore_dmu*dmu_dtor + dscore_dK*dK_dtor);
1688  }
1689 
1690 
1691 
1692  // loop over all bb-dep angles and bonds, summing dmu_dphi and dK_dphi
1693  // hardcode the bbdep angles and lengths to save a bit of time
1694  // connection IDs are hardcoded ... is this a problem?
1695 
1696  /*
1697  for (int i=1; i<=5; ++i) {
1698  if (i==1 && is_nterm) continue;
1699  if (i==3 && rsd.aa() == core::chemical::aa_gly) continue;
1700 
1701  std::string atm1,atm2;
1702  core::Size rt1,rt2;
1703  if (i==1) { atm1="C"; atm2="N"; rt1=-1; rt2=rsd.atom_index(" N ");}
1704  if (i==2) { atm1="N"; atm2="CA"; rt1=rsd.atom_index(" N "); rt2=rsd.atom_index(" CA "); }
1705  if (i==3) { atm1="CA"; atm2="CB"; rt1=rsd.atom_index(" CA "); rt2=rsd.atom_index(" CB "); }
1706  if (i==4) { atm1="CA"; atm2="C"; rt1=rsd.atom_index(" CA "); rt2=rsd.atom_index(" C "); }
1707  if (i==5) { atm1="C"; atm2="O"; rt1=rsd.atom_index(" C "); rt2=rsd.atom_index(" O "); }
1708 
1709  Vector atom1xyz, atom2xyz = rsd.atom( rt2 ).xyz();
1710  if (i==1)
1711  atom1xyz = pose.residue( resid-1 ).atom(" C ").xyz();
1712  else
1713  atom1xyz = rsd.atom( rt1 ).xyz();
1714  CartBondedParametersCOP len_params = db_->lookup_length(rsd.type(), (i==1)?false:preproline, atm1,atm2, rt1,rt2 );
1715 
1716  Real const d = ( atom2xyz-atom1xyz ).length();
1717  core::Real mu,K, dmu_dtor, dK_dtor=0.0;
1718  core::Real dscore_dK=0.0, dscore_dmu;
1719 
1720  K = len_params->K(phi,psi);
1721  mu = len_params->mu(phi,psi);
1722 
1723  if (tor_id.torsion()==1) {
1724  dmu_dtor = len_params->dmu_dphi(phi,psi);
1725  } else {
1726  dmu_dtor = len_params->dmu_dpsi(phi,psi);
1727  }
1728  if (linear_bonded_potential_ && std::fabs(d - mu)>1) {
1729  dscore_dmu = -K * ((d - mu)>0 ? 1:-1);
1730  } else {
1731  dscore_dmu = -K * (d - mu);
1732  }
1733  if (db_->bbdep_bond_devs()) {
1734  if (tor_id.torsion()==1) {
1735  dK_dtor = len_params->dK_dphi(phi,psi);
1736  } else {
1737  dK_dtor = len_params->dK_dpsi(phi,psi);
1738  }
1739  if (linear_bonded_potential_ && std::fabs(d - mu)>1) {
1740  dscore_dK = 0.5*std::fabs(d - mu);
1741  } else {
1742  dscore_dK = 0.5*(d - mu)*(d - mu); // currently we have no -log(K) term in our score
1743  }
1744  }
1745 
1746  // derivatives w.r.t. phi/psi
1747  deriv += (weights[ cart_bonded_length ] + weights[ cart_bonded ]) * (dscore_dmu*dmu_dtor + dscore_dK*dK_dtor);
1748  }*/
1749 
1750  /*
1751  for (int i=1; i<=7; ++i) {
1752  if ((i==2 || i==4) && rsd.aa() == core::chemical::aa_gly) continue;
1753  if (i==1 && is_nterm) continue;
1754  if ((i==6 || i==7) && is_cterm) continue;
1755 
1756  std::string atm1,atm2,atm3;
1757  core::Size rt1,rt2,rt3;
1758  if (i==1) { atm1="C"; atm2="N";atm3="CA"; rt1=-1; rt2=rsd.atom_index(" N "); rt3=rsd.atom_index(" CA ");}
1759  if (i==2) { atm1="N"; atm2="CA";atm3="CB"; rt1=rsd.atom_index(" N "); rt2=rsd.atom_index(" CA "); rt3=rsd.atom_index(" CB "); }
1760  if (i==3) { atm1="N"; atm2="CA";atm3="C"; rt1=rsd.atom_index(" N "); rt2=rsd.atom_index(" CA "); rt3=rsd.atom_index(" C "); }
1761  if (i==4) { atm1="CB"; atm2="CA";atm3="C"; rt1=rsd.atom_index(" CB "); rt2=rsd.atom_index(" CA "); rt3=rsd.atom_index(" C "); }
1762  if (i==5) { atm1="CA"; atm2="C";atm3="O"; rt1=rsd.atom_index(" CA "); rt2=rsd.atom_index(" C "); rt3=rsd.atom_index(" O "); }
1763  if (i==6) { atm1="CA"; atm2="C";atm3="N"; rt1=rsd.atom_index(" CA "); rt2=rsd.atom_index(" C "); rt3=-2; }
1764  if (i==7) { atm1="O"; atm2="C";atm3="N"; rt1=rsd.atom_index(" O "); rt2=rsd.atom_index(" C "); rt3=-2; }
1765 
1766  Vector atom1xyz, atom2xyz = rsd.atom( rt2 ).xyz(), atom3xyz;
1767  if (i==1)
1768  atom1xyz = pose.residue( resid-1 ).atom(" C ").xyz();
1769  else
1770  atom1xyz = rsd.atom( rt1 ).xyz();
1771  if (i==6 || i==7)
1772  atom3xyz = pose.residue( resid+1 ).atom(" N ").xyz();
1773  else
1774  atom3xyz = rsd.atom( rt3 ).xyz();
1775 
1776  CartBondedParametersCOP ang_params = db_->lookup_angle(rsd.type(), preproline, atm1,atm2,atm3, rt1,rt2,rt3 );
1777 
1778  Real const angle = numeric::angle_radians(atom1xyz,atom2xyz,atom3xyz);
1779 
1780  core::Real mu,K, dmu_dtor, dK_dtor=0.0;
1781  core::Real dscore_dK=0.0, dscore_dmu;
1782 
1783  K = ang_params->K(phi,psi);
1784  mu = ang_params->mu(phi,psi);
1785 
1786  if (tor_id.torsion()==1) {
1787  dmu_dtor = ang_params->dmu_dphi(phi,psi);
1788  } else {
1789  dmu_dtor = ang_params->dmu_dpsi(phi,psi);
1790  }
1791  if (linear_bonded_potential_ && std::fabs(angle - mu)>1) {
1792  dscore_dmu = -K * ((angle - mu)>0 ? 1:-1);
1793  } else {
1794  dscore_dmu = -K * (angle - mu);
1795  }
1796 
1797  if (db_->bbdep_bond_devs()) {
1798  if (tor_id.torsion()==1) {
1799  dK_dtor = ang_params->dK_dphi(phi,psi);
1800  } else {
1801  dK_dtor = ang_params->dK_dpsi(phi,psi);
1802  }
1803  if (linear_bonded_potential_ && std::fabs(angle - mu)>1) {
1804  dscore_dK = 0.5*std::fabs(angle - mu);
1805  } else {
1806  dscore_dK = 0.5*(angle - mu)*(angle - mu); // currently we have no -log(K) term in our score
1807  }
1808  }
1809 
1810  // derivatives w.r.t. phi/psi
1811  deriv += (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * (dscore_dmu*dmu_dtor + dscore_dK*dK_dtor);
1812  }*/
1813  return 180/pi * deriv;
1814 }
1815 
1816 /// @brief CartesianBondedEnergy does not have an atomic interation threshold
1817 Distance
1819  return 0.0;
1820 }
1821 
1822 
1823 /// @brief CartesianBondedEnergy is context independent; indicates that no context graphs are required
1824 void
1826 
1827 
1830 
1831 void
1833  conformation::Residue const & rsd1,
1834  conformation::Residue const & rsd2,
1835  pose::Pose const & pose,
1836  ScoreFunction const &,
1837  EnergyMap & emap
1838 ) const {
1839 
1840  using namespace numeric;
1841 
1842  assert( rsd2.seqpos() > rsd1.seqpos() );
1843 
1844  core::Size resid = rsd1.seqpos();
1845  bool is_cterm = (pose.fold_tree().is_cutpoint( resid ));
1846  bool preproline = (!is_cterm && rsd2.aa() == core::chemical::aa_pro);
1847 
1848  if ( rsd1.aa() == core::chemical::aa_vrt) return;
1849 
1850  ResidueCartBondedParameters const & rsd1params = db_->parameters_for_restype( rsd1.type(), preproline );
1851  ResidueCartBondedParameters const & rsd2params = db_->parameters_for_restype( rsd2.type(), false );
1852 
1853  Real phi1=0,psi1=0,phi2=0,psi2=0;
1854  if (rsd1.is_protein()) {
1855  phi1 = nonnegative_principal_angle_degrees( rsd1.mainchain_torsion(1));
1856  psi1 = nonnegative_principal_angle_degrees( rsd1.mainchain_torsion(2));
1857  }
1858  if (rsd2.is_protein()) {
1859  phi2 = nonnegative_principal_angle_degrees( rsd2.mainchain_torsion(1));
1860  psi2 = nonnegative_principal_angle_degrees( rsd2.mainchain_torsion(2));
1861  }
1862 
1863  // get one body component (but which has two-body influence based on whether or not rsd2 is a proline)
1864  eval_singleres_energy(rsd1, rsd1params, phi1, psi1, pose, emap ); // calls singleres improper
1865 
1866  // last residue won't ever be rsd1, so we need to explicitly call eval_singleres for rsd2 if rsd2 is the
1867  // last residue
1868  Size nres = pose.total_residue();
1869  if( core::pose::symmetry::is_symmetric(pose) ) nres = core::pose::symmetry::symmetry_info(pose)->num_independent_residues();
1870  if (rsd2.seqpos() == nres && rsd2.aa() != core::chemical::aa_vrt) {
1871  // get one body component for the last residue
1872  eval_singleres_energy(rsd2, rsd2params, phi2, psi2, pose, emap );
1873  }
1874 
1875  // bail out if the residues aren't bonded or we cross a cutpoint
1876  if (!rsd1.is_bonded(rsd2)) { return; }
1877  if ( is_cterm ) { return; }
1878 
1879  /// evaluate all the inter-residue energy components
1880  eval_residue_pair_energies( rsd1, rsd2, rsd1params, rsd2params, phi1, psi1, phi2, psi2, pose, emap );
1881 }
1882 
1883 void
1885  conformation::Residue const & rsd,
1886  ResidueCartBondedParameters const & resparams,
1887  Real phi,
1888  Real psi,
1889  pose::Pose const & pose,
1890  EnergyMap & emap
1891 ) const
1892 {
1893  using numeric::constants::d::pi;
1894  using namespace numeric;
1895 
1896  assert ( rsd.aa() != core::chemical::aa_vrt );
1897 
1898  eval_singleres_improper_torsion_energies( rsd, resparams, pose, emap );
1899  eval_singleres_torsion_energies( rsd, resparams, phi, psi, pose, emap );
1900  eval_singleres_angle_energies( rsd, resparams, phi, psi, pose, emap );
1901  eval_singleres_length_energies( rsd, resparams, phi, psi, pose, emap );
1902 
1903 }
1904 
1905 void
1907  conformation::Residue const & rsd,
1908  ResidueCartBondedParameters const & resparams,
1909  pose::Pose const & pose,
1910  EnergyMap & emap
1911 ) const
1912 {
1913  using namespace core::chemical;
1914  using numeric::constants::d::pi;
1915 
1917  resparams.improper_torsion_parameters() );
1918 
1919  for ( Size ii = 1, iiend = itps.size(); ii <= iiend; ++ii ) {
1920  ResidueCartBondedParameters::Size4 const & atids( itps[ ii ].first );
1921  CartBondedParameters const & tor_params( *itps[ ii ].second );
1922  Real Kphi = tor_params.K(0,0);
1923  Real phi0 = tor_params.mu(0,0);
1924  Real phi_step=2 * pi / tor_params.period();
1925  Real angle = numeric::dihedral_radians(
1926  rsd.xyz( atids[1] ), rsd.xyz( atids[2] ), rsd.xyz( atids[3] ), rsd.xyz( atids[4] ) );
1927  Real del_phi = basic::subtract_radian_angles( angle, phi0 );
1928  del_phi = basic::periodic_range( del_phi, phi_step );
1929 
1930  core::Real const energy_torsion = eval_score( del_phi, Kphi, 0 );
1931 
1932  // Send a message to the user about a bad angle, if necessary.
1933  // Make sure not to send output to a tracer in the middle of
1934  // scoring unless that tracer is visible, since that can be very expensive
1935  if ( energy_torsion > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
1936  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd.seqpos() << " pdbpos: " <<
1937  pose.pdb_info()->number(rsd.seqpos()) << " improper torsion: " <<
1938  rsd.name() << " : " <<
1939  rsd.atom_name( atids[1] ) << " , " << rsd.atom_name( atids[2] ) << " , " <<
1940  rsd.atom_name( atids[3] ) << " , " << rsd.atom_name( atids[4] ) << " (" <<
1941  Kphi << ") " << angle << " " << phi0 << " sc=" << energy_torsion << std::endl;
1942  }
1943 
1944  emap[ cart_bonded_torsion ] += energy_torsion;
1945  emap[ cart_bonded ] += energy_torsion; // potential double counting*/
1946  }
1947 }
1948 
1949 /// @brief helper function to handle intrares bond torsions
1950 void
1952  conformation::Residue const & rsd,
1953  ResidueCartBondedParameters const & resparams,
1954  Real const phi,
1955  Real const psi,
1956  pose::Pose const & pose,
1957  EnergyMap & emap
1958 ) const
1959 {
1960  using namespace core::chemical;
1961  using numeric::constants::d::pi;
1962 
1964 
1965  for ( Size ii = 1, iiend = tps.size(); ii <= iiend; ++ii ) {
1966  ResidueCartBondedParameters::Size4 const & atids( tps[ ii ].first );
1967  CartBondedParameters const & tor_params( *tps[ ii ].second );
1968 
1969  Real Kphi = tor_params.K(phi,psi);
1970  Real phi0 = tor_params.mu(phi,psi);
1971  Real phi_step = 2 * pi / tor_params.period();
1972  Real angle = numeric::dihedral_radians(
1973  rsd.xyz( atids[1] ), rsd.xyz( atids[2] ), rsd.xyz( atids[3] ), rsd.xyz( atids[4] ) );
1974  Real del_phi = basic::subtract_radian_angles(angle, phi0);
1975  if ( phi_step > 0 ) del_phi = basic::periodic_range( del_phi, phi_step );
1976 
1977  core::Real const energy_torsion = eval_score( del_phi, Kphi, 0 );
1978 
1979  // Send a message to the user about a bad angle, if necessary.
1980  // Make sure not to send output to a tracer in the middle of
1981  // scoring unless that tracer is visible, since that can be very expensive
1982  if ( energy_torsion > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
1983  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd.seqpos() << " pdbpos: " <<
1984  pose.pdb_info()->number(rsd.seqpos()) << " intrares torsion: " <<
1985  rsd.name() << " : " <<
1986  rsd.atom_name( atids[1] ) << " , " << rsd.atom_name( atids[2] ) << " , " <<
1987  rsd.atom_name( atids[3] ) << " , " << rsd.atom_name( atids[4] ) << " (" <<
1988  Kphi << ") " << angle << " " << phi0 << " sc=" << energy_torsion << std::endl;
1989  }
1990 
1991  emap[ cart_bonded_torsion ] += energy_torsion;
1992  emap[ cart_bonded ] += energy_torsion; // potential double counting*/
1993  }
1994 }
1995 
1996 /// @brief helper function to handle intrares bond angles
1997 void
1999  conformation::Residue const & rsd,
2000  ResidueCartBondedParameters const & resparams,
2001  Real const phi,
2002  Real const psi,
2003  pose::Pose const & pose,
2004  EnergyMap & emap
2005 ) const
2006 {
2007  using namespace core::chemical;
2008 
2010 
2011  for ( Size ii = 1, iiend = aps.size(); ii <= iiend; ++ii ) {
2012  ResidueCartBondedParameters::Size3 const & atids( aps[ ii ].first );
2013  CartBondedParameters const & ang_params( *aps[ ii ].second );
2014  Real Ktheta = ang_params.K(phi,psi);
2015  Real theta0 = ang_params.mu(phi,psi);
2016  Real angle = numeric::angle_radians( rsd.xyz(atids[1]), rsd.xyz(atids[2]), rsd.xyz(atids[3]) );
2017 
2018  Real const energy_angle = eval_score( angle, Ktheta, theta0 );
2019 
2020  // Send a message to the user about a bad angle, if necessary.
2021  // Make sure not to send output to a tracer in the middle of
2022  // scoring unless that tracer is visible, since that can be very expensive
2023  if ( energy_angle > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2024  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd.seqpos() << " pdbpos: " <<
2025  pose.pdb_info()->number(rsd.seqpos()) << " intrares angle: " <<
2026  rsd.name() << " : " <<
2027  rsd.atom_name( atids[1] ) << " , " << rsd.atom_name( atids[2] ) << " , " <<
2028  rsd.atom_name( atids[3] ) << " (" <<
2029  Ktheta << ") " << angle << " " << theta0 << " sc=" <<
2030  energy_angle << std::endl;
2031  }
2032 
2033  // accumulate the energy
2034  emap[ cart_bonded_angle ] += energy_angle;
2035  emap[ cart_bonded ] += energy_angle; // potential double counting*/
2036  }
2037 }
2038 
2039 /// @brief helper function to handle intrares bond lengths
2040 void
2042  conformation::Residue const & rsd,
2043  ResidueCartBondedParameters const & resparams,
2044  Real const phi,
2045  Real const psi,
2046  pose::Pose const & pose,
2047  EnergyMap & emap
2048 ) const
2049 {
2050  using namespace core::chemical;
2051 
2053 
2054  for ( Size ii = 1, iiend = lps.size(); ii <= iiend; ++ii ) {
2055  ResidueCartBondedParameters::Size2 const & atids( lps[ ii ].first );
2056  CartBondedParameters const & len_params( *lps[ ii ].second );
2057  Real const Kd = len_params.K(phi,psi);
2058  Real const d0 = len_params.mu(phi,psi);
2059  Real const d = rsd.xyz(atids[1]).distance( rsd.xyz( atids[2] ));
2060 
2061  Real const energy_length = eval_score( d, Kd, d0 );
2062  // Send a message to the user about a bad angle, if necessary.
2063  // Make sure not to send output to a tracer in the middle of
2064  // scoring unless that tracer is visible, since that can be very expensive
2065  if ( energy_length > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2066  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd.seqpos() << " pdbpos: " << pose.pdb_info()->number(rsd.seqpos()) << " intrares angle: " <<
2067  rsd.type().name() << " : " <<
2068  rsd.atom_name( atids[1] ) << " , " << rsd.atom_name( atids[2] ) << " ("
2069  << Kd << ") " << d << " " << d0
2070  << " sc=" << energy_length << std::endl;
2071  }
2072 
2073  // accumulate the energy
2074  emap[ cart_bonded ] += energy_length;
2075  emap[ cart_bonded_length ] += energy_length;
2076  }
2077 }
2078 
2079 /// @details rsd1.seqpos < rsd2.seqpos, and rsd1&rsd2 should be chemically
2080 /// bonded.
2081 void
2083  conformation::Residue const & rsd1,
2084  conformation::Residue const & rsd2,
2085  ResidueCartBondedParameters const & rsd1params,
2086  ResidueCartBondedParameters const & rsd2params,
2087  Real phi1,
2088  Real psi1,
2089  Real phi2,
2090  Real psi2,
2091  pose::Pose const & pose,
2092  EnergyMap & emap
2093 ) const
2094 {
2095  eval_improper_torsions( rsd1, rsd2, rsd1params, rsd2params, pose, emap );
2096  eval_interresidue_angle_energies_two_from_rsd1( rsd1, rsd2, rsd1params, rsd2params, phi1, psi1, pose, emap );
2097  eval_interresidue_angle_energies_two_from_rsd2( rsd1, rsd2, rsd1params, rsd2params, phi2, psi2, pose, emap );
2098  eval_interresidue_bond_energy( rsd1, rsd2, rsd1params, rsd2params, phi2, psi2, pose, emap );
2099 }
2100 
2101 void
2103  conformation::Residue const & rsd1,
2104  conformation::Residue const & rsd2,
2105  ResidueCartBondedParameters const & rsd1params,
2106  ResidueCartBondedParameters const & rsd2params,
2107  Real phi1,
2108  Real psi1,
2109  pose::Pose const & pose,
2110  EnergyMap & emap
2111 ) const
2112 {
2113  using namespace core::chemical;
2114  if ( rsd1.aa() <= num_canonical_aas && rsd2.aa() <= num_canonical_aas &&
2115  rsd1.residue_connection_partner( rsd1.upper_connect().index() ) == rsd2.seqpos() ) {
2116 
2117  /// Assumption: rsd1 and rsd2 share a peptide bond and only a peptide bond.
2118  assert( rsd2.residue_connection_partner( rsd2.lower_connect().index() ) == rsd1.seqpos() );
2119  assert( rsd1.connections_to_residue( rsd2 ).size() == 1 );
2120 
2122  for ( Size ii = 1, iiend = aps.size(); ii <= iiend; ++ii ) {
2123  ResidueCartBondedParameters::Size3 const & atids( aps[ ii ].first );
2124  CartBondedParameters const & ang_params( *aps[ ii ].second );
2125  Real Ktheta = ang_params.K(phi1,psi1);
2126  Real theta0 = ang_params.mu(phi1,psi1);
2127  Real angle = numeric::angle_radians(
2128  rsd1.xyz(atids[1]), rsd1.xyz(atids[2]),
2129  rsd2.xyz( rsd2params.bb_N_index() ) );
2130 
2131  Real const energy_angle = eval_score( angle, Ktheta, theta0 );
2132  // Send a message to the user about a bad angle, if necessary.
2133  // Make sure not to send output to a tracer in the middle of
2134  // scoring unless that tracer is visible, since that can be very expensive
2135  if ( energy_angle > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2136  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd1.seqpos()
2137  << " pdbpos: " << pose.pdb_info()->number(rsd1.seqpos()) << " angle rsd1: " << rsd1.name()
2138  << ":" << rsd1.atom_name( atids[1] ) << " , "
2139  << rsd1.atom_name( atids[2] ) << " , " << rsd2.atom_name( rsd2params.bb_N_index() )<< " ("
2140  << Ktheta << ") " << angle << " " << theta0
2141  << " sc=" << energy_angle << std::endl;
2142  }
2143 
2144  // accumulate the energy
2145  emap[ cart_bonded_angle ] += energy_angle;
2146  emap[ cart_bonded ] += energy_angle; // potential double counting*/
2147  }
2148 
2149  } else {
2150  // At the time of the writing of this comment, the CartesianBondEnergy is used only
2151  // to evaluate protein energetics, and the only inter-residue bonds it is evaluated
2152  // on is peptide bonds. If that persists, then this "else" clause will never be executed.
2153  // If it does get executed, then this else clause ought to be optimized.
2154  // Before the above "if" and the below "else" clauses got separated, the only code
2155  // executed was the "else" clause and it was rediculously slow. I mean much much
2156  // slower than evaluating the etable energies. REEAAALLLLY SLOW.
2157 
2158  utility::vector1< Size > const & r1_resconn_ids( rsd1.connections_to_residue( rsd2 ) );
2159  for ( Size ii = 1; ii <= r1_resconn_ids.size(); ++ii ) {
2160  Size const resconn_id1( r1_resconn_ids[ii] );
2161  Size const resconn_id2( rsd1.residue_connection_conn_id( resconn_id1 ) );
2162 
2163  Size const resconn_atomno1( rsd1.residue_connection( resconn_id1 ).atomno() );
2164  Size const resconn_atomno2( rsd2.residue_connection( resconn_id2 ).atomno() );
2165 
2166  // compute bond-angle energies with two atoms on rsd1
2167  utility::vector1< chemical::two_atom_set > const & rsd1_atoms_wi1_bond_of_ii(
2168  rsd1.type().atoms_within_one_bond_of_a_residue_connection( resconn_id1 ));
2169  for ( Size jj = 1; jj <= rsd1_atoms_wi1_bond_of_ii.size(); ++jj ) {
2170  assert( rsd1_atoms_wi1_bond_of_ii[ jj ].key1() == resconn_atomno1 );
2171  Size const res1_lower_atomno = rsd1_atoms_wi1_bond_of_ii[ jj ].key2();
2172 
2173  Real const angle = numeric::angle_radians(
2174  rsd1.atom( res1_lower_atomno ).xyz(),
2175  rsd1.atom( resconn_atomno1 ).xyz(),
2176  rsd2.atom( resconn_atomno2 ).xyz() );
2177  std::string atm1name=rsd1.atom_name(res1_lower_atomno); boost::trim(atm1name);
2178  std::string atm2name=rsd1.atom_name(resconn_atomno1); boost::trim(atm2name);
2179  std::string atm3name=rsd2.atom_name(resconn_atomno2); boost::trim(atm3name);
2180 
2181  // lookup Ktheta and theta0
2182  CartBondedParametersCOP ang_params = db_->lookup_angle(rsd1.type(), rsd2.aa() == chemical::aa_pro,
2183  atm1name, atm2name, atm3name, res1_lower_atomno, resconn_atomno1, -resconn_id1);
2184  if (ang_params->is_null()) continue;
2185  Real Ktheta=ang_params->K(phi1,psi1), theta0=ang_params->mu(phi1,psi1);
2186 
2187  Real const energy_angle = eval_score( angle, Ktheta, theta0 );
2188 
2189  // Send a message to the user about a bad angle, if necessary.
2190  // Make sure not to send output to a tracer in the middle of
2191  // scoring unless that tracer is visible, since that can be very expensive
2192  if ( energy_angle > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2193  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd1.seqpos()
2194  << " pdbpos: " << pose.pdb_info()->number(rsd1.seqpos()) << " angle rsd1: " << rsd1.name()
2195  << ":" << rsd1.atom_name( res1_lower_atomno ) << " , "
2196  << rsd1.atom_name( resconn_atomno1 ) << " , " << rsd2.atom_name( resconn_atomno2 )<< " ("
2197  << Ktheta << ") " << angle << " " << theta0
2198  << " sc=" << energy_angle << std::endl;
2199  }
2200 
2201  // accumulate the energy
2202  emap[ cart_bonded_angle ] += energy_angle;
2203  emap[ cart_bonded ] += energy_angle; // potential double counting*/
2204  }
2205  }
2206  }
2207 }
2208 
2209 void
2211  conformation::Residue const & rsd1,
2212  conformation::Residue const & rsd2,
2213  ResidueCartBondedParameters const & rsd1params,
2214  ResidueCartBondedParameters const & rsd2params,
2215  Real phi2,
2216  Real psi2,
2217  pose::Pose const & pose,
2218  EnergyMap & emap
2219 ) const
2220 {
2221  using namespace core::chemical;
2222  if ( rsd1.aa() <= num_canonical_aas && rsd2.aa() <= num_canonical_aas &&
2223  rsd1.residue_connection_partner( rsd1.upper_connect().index() )== rsd2.seqpos() ) {
2224 
2225  /// Assumption: rsd1 and rsd2 share a peptide bond and only a peptide bond.
2226  assert( rsd2.residue_connection_partner( rsd2.lower_connect().index() ) == rsd1.seqpos() );
2227  assert( rsd1.connections_to_residue( rsd2 ).size() == 1 );
2228 
2230  for ( Size ii = 1, iiend = aps.size(); ii <= iiend; ++ii ) {
2231  ResidueCartBondedParameters::Size3 const & atids( aps[ ii ].first );
2232  CartBondedParameters const & ang_params( *aps[ ii ].second );
2233  Real Ktheta = ang_params.K(phi2,psi2);
2234  Real theta0 = ang_params.mu(phi2,psi2);
2235  Real angle = numeric::angle_radians(
2236  rsd2.xyz(atids[1]), rsd2.xyz(atids[2]),
2237  rsd1.xyz( rsd1params.bb_C_index() ) );
2238 
2239  Real const energy_angle = eval_score( angle, Ktheta, theta0 );
2240 
2241  // Send a message to the user about a bad angle, if necessary.
2242  // Make sure not to send output to a tracer in the middle of
2243  // scoring unless that tracer is visible, since that can be very expensive
2244  if ( energy_angle > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2245  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd2.seqpos()
2246  << " pdbpos: " << pose.pdb_info()->number(rsd2.seqpos()) << " angle rsd2: " << rsd2.name()
2247  << ":" << rsd2.atom_name( atids[1] ) << " , "
2248  << rsd2.atom_name( atids[2] ) << " , " << rsd1.atom_name( rsd1params.bb_C_index() )
2249  << " (" << Ktheta << ") " << angle << " " << theta0
2250  << " sc=" << energy_angle << std::endl;
2251  }
2252 
2253  // accumulate the energy
2254  emap[ cart_bonded_angle ] += energy_angle;
2255  emap[ cart_bonded ] += energy_angle; // potential double counting*/
2256  }
2257 
2258  } else {
2259  // At the time of the writing of this comment, the CartesianBondEnergy is used only
2260  // to evaluate protein energetics, and the only inter-residue bonds it is evaluated
2261  // on is peptide bonds. If that persists, then this "else" clause will never be executed.
2262  // If it does get executed, then this else clause ought to be optimized.
2263  // Before the above "if" and the below "else" clauses got separated, the only code
2264  // executed was the "else" clause and it was rediculously slow. I mean much much
2265  // slower than evaluating the etable energies. REEAAALLLLY SLOW.
2266 
2267  utility::vector1< Size > const & r1_resconn_ids( rsd1.connections_to_residue( rsd2 ) );
2268  for ( Size ii = 1; ii <= r1_resconn_ids.size(); ++ii ) {
2269  Size const resconn_id1( r1_resconn_ids[ii] );
2270  Size const resconn_id2( rsd1.residue_connection_conn_id( resconn_id1 ) );
2271 
2272  Size const resconn_atomno1( rsd1.residue_connection( resconn_id1 ).atomno() );
2273  Size const resconn_atomno2( rsd2.residue_connection( resconn_id2 ).atomno() );
2274 
2275  /// compute bond-angle energies with two atoms on rsd2
2276  utility::vector1< chemical::two_atom_set > const & rsd2_atoms_wi1_bond_of_ii(
2277  rsd2.type().atoms_within_one_bond_of_a_residue_connection( resconn_id2 ));
2278  for ( Size jj = 1; jj <= rsd2_atoms_wi1_bond_of_ii.size(); ++jj ) {
2279  assert( rsd2_atoms_wi1_bond_of_ii[ jj ].key1() == resconn_atomno2 );
2280  Size const res2_lower_atomno = rsd2_atoms_wi1_bond_of_ii[ jj ].key2();
2281 
2282  // lookup Ktheta and theta0
2283  // set pre-proline to false here -- it refers to rsd2+1 which would make this three-body
2284  std::string atm1name=rsd2.atom_name(res2_lower_atomno); boost::trim(atm1name);
2285  std::string atm2name=rsd2.atom_name(resconn_atomno2); boost::trim(atm2name);
2286  std::string atm3name=rsd1.atom_name(resconn_atomno1); boost::trim(atm3name);
2287  CartBondedParametersCOP ang_params = db_->lookup_angle(rsd2.type(), false,
2288  atm1name, atm2name, atm3name, res2_lower_atomno, resconn_atomno2, -resconn_id2);
2289  if (ang_params->is_null()) continue;
2290  Real Ktheta=ang_params->K(phi2,psi2), theta0=ang_params->mu(phi2,psi2);
2291 
2292  if (Ktheta == 0.0) continue;
2293  Real const angle = numeric::angle_radians(
2294  rsd2.atom( res2_lower_atomno ).xyz(),
2295  rsd2.atom( resconn_atomno2 ).xyz(),
2296  rsd1.atom( resconn_atomno1 ).xyz() );
2297 
2298  Real const energy_angle = eval_score( angle, Ktheta, theta0 );
2299 
2300  // Send a message to the user about a bad angle, if necessary.
2301  // Make sure not to send output to a tracer in the middle of
2302  // scoring unless that tracer is visible, since that can be very expensive
2303  if ( energy_angle > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2304  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd2.seqpos()
2305  << " pdbpos: " << pose.pdb_info()->number(rsd2.seqpos()) << " angle rsd2: " << rsd2.name()
2306  << ":" << rsd2.atom_name( res2_lower_atomno ) << " , "
2307  << rsd2.atom_name( resconn_atomno2 ) << " , " << rsd1.atom_name( resconn_atomno1 )
2308  << " (" << Ktheta << ") " << angle << " " << theta0
2309  << " sc=" << energy_angle << std::endl;
2310  }
2311 
2312  // accumulate the energy
2313  emap[ cart_bonded_angle ] += energy_angle;
2314  emap[ cart_bonded ] += energy_angle; // potential double counting*/
2315 
2316  }
2317  }
2318  }
2319 }
2320 
2321 void
2323  conformation::Residue const & rsd1,
2324  conformation::Residue const & rsd2,
2325  ResidueCartBondedParameters const & rsd1params,
2326  ResidueCartBondedParameters const & rsd2params,
2327  Real phi2,
2328  Real psi2,
2329  pose::Pose const & pose,
2330  EnergyMap & emap
2331 ) const
2332 {
2333  using namespace core::chemical;
2334  if ( rsd1.aa() <= num_canonical_aas && rsd2.aa() <= num_canonical_aas &&
2335  rsd1.residue_connection_partner( rsd1.upper_connect().index() )== rsd2.seqpos() ) {
2336 
2337  /// Assumption: rsd1 and rsd2 share a peptide bond and only a peptide bond.
2338  assert( rsd2.residue_connection_partner( rsd2.lower_connect().index() ) == rsd1.seqpos() );
2339  assert( rsd1.connections_to_residue( rsd2 ).size() == 1 );
2340 
2341  /////////////
2342  /// finally, compute the bondlength across the interface
2343  Real length = rsd1.xyz( rsd1params.bb_C_index() ).distance( rsd2.xyz( rsd2params.bb_N_index() ) );
2344 
2345  // lookup Kd and d0
2346  CartBondedParametersCOP len_params = rsd2params.cprev_n_bond_length_params();
2347 
2348  if (len_params->is_null()) return;
2349  Real Kd=len_params->K(phi2,psi2), d0=len_params->mu(phi2,psi2);
2350 
2351  Real const energy_length = eval_score( length, Kd, d0 );
2352 
2353  // Send a message to the user about a bad distance, if necessary.
2354  // Make sure not to send output to a tracer in the middle of
2355  // scoring unless that tracer is visible, since that can be very expensive
2356  if ( energy_length > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2357  TR.Debug << pose.pdb_info()->name()
2358  << " pdbpos rsd1: " << pose.pdb_info()->number(rsd1.seqpos()) << " length rsd1 rsd2: " << rsd1.seqpos() << " -- " << rsd2.seqpos() << " "
2359  << rsd1.name() << ":" << rsd1.atom_name( rsd1params.bb_C_index() ) << " , " << rsd2.atom_name( rsd2params.bb_N_index() )<< " ("
2360  << Kd << ") " << length << " " << d0
2361  << " sc=" << energy_length << std::endl;
2362  }
2363 
2364  // accumulate the energy
2365  emap[ cart_bonded ] += energy_length;
2366  emap[ cart_bonded_length ] += energy_length;
2367 
2368  } else {
2369  // At the time of the writing of this comment, the CartesianBondEnergy is used only
2370  // to evaluate protein energetics, and the only inter-residue bonds it is evaluated
2371  // on is peptide bonds. If that persists, then this "else" clause will never be executed.
2372  // If it does get executed, then this else clause ought to be optimized.
2373  // Before the above "if" and the below "else" clauses got separated, the only code
2374  // executed was the "else" clause and it was rediculously slow. I mean much much
2375  // slower than evaluating the etable energies. REEAAALLLLY SLOW.
2376 
2377  utility::vector1< Size > const & r1_resconn_ids( rsd1.connections_to_residue( rsd2 ) );
2378  for ( Size ii = 1; ii <= r1_resconn_ids.size(); ++ii ) {
2379  Size const resconn_id1( r1_resconn_ids[ii] );
2380  Size const resconn_id2( rsd1.residue_connection_conn_id( resconn_id1 ) );
2381 
2382  Size const resconn_atomno1( rsd1.residue_connection( resconn_id1 ).atomno() );
2383  Size const resconn_atomno2( rsd2.residue_connection( resconn_id2 ).atomno() );
2384 
2385  /////////////
2386  /// finally, compute the bondlength across the interface
2387  Real length =
2388  ( rsd2.atom( resconn_atomno2 ).xyz() - rsd1.atom( resconn_atomno1 ).xyz() ).length();
2389 
2390  // lookup Kd and d0
2391  // again, pre-pro == false, definitions are based on pro as rsd2+1
2392  std::string atm1name=rsd2.atom_name(resconn_atomno2); boost::trim(atm1name);
2393  std::string atm2name=rsd1.atom_name(resconn_atomno1); boost::trim(atm2name);
2394  CartBondedParametersCOP len_params = db_->lookup_length(rsd2.type(), false,
2395  atm1name, atm2name, resconn_atomno2, -resconn_id2);
2396 
2397  if (len_params->is_null()) continue;
2398  Real Kd=len_params->K(phi2,psi2), d0=len_params->mu(phi2,psi2);
2399 
2400  Real const energy_length = eval_score( length, Kd, d0 );
2401 
2402  // Send a message to the user about a bad distance, if necessary.
2403  // Make sure not to send output to a tracer in the middle of
2404  // scoring unless that tracer is visible, since that can be very expensive
2405  if ( energy_length > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2406  TR.Debug << pose.pdb_info()->name()
2407  << " pdbpos rsd1: " << pose.pdb_info()->number(rsd1.seqpos()) << " length rsd1 rsd2: " << rsd1.seqpos() << " -- " << rsd2.seqpos() << " "
2408  << rsd1.name() << ":" << rsd1.atom_name( resconn_atomno1 ) << " , " << rsd2.atom_name( resconn_atomno2 )<< " ("
2409  << Kd << ") " << length << " " << d0
2410  << " sc=" << energy_length << std::endl;
2411  }
2412 
2413  // accumulate the energy
2414  emap[ cart_bonded ] += energy_length;
2415  emap[ cart_bonded_length ] += energy_length;
2416  }
2417  }
2418 
2419 }
2420 
2421 void
2423  conformation::Residue const & rsd1,
2424  conformation::Residue const & rsd2,
2425  ResidueCartBondedParameters const & rsd1params,
2426  ResidueCartBondedParameters const & rsd2params,
2427  pose::Pose const & pose,
2428  EnergyMap & emap
2429 ) const
2430 {
2431  using namespace core::chemical;
2432  using numeric::constants::d::pi;
2433 
2434  assert( rsd1.seqpos() < rsd2.seqpos() );
2435 
2436  if ( !rsd1.is_protein() || !rsd2.is_protein()) return;
2437 
2438  // backbone CA-Cprev-N-H
2439  if ( rsd2.aa() != aa_pro && rsd2params.bb_H_index() != 0 ) {
2441  if ( !tor_params->is_null() ) {
2442  Real const Kphi = tor_params->K(0,0);
2443  Real const phi0=tor_params->mu(0,0);
2444  Real const phi_step=2*pi/tor_params->period();
2445  Real angle = numeric::dihedral_radians(
2446  rsd2.xyz( rsd2params.bb_CA_index() ),
2447  rsd1.xyz( rsd1params.bb_C_index() ),
2448  rsd2.xyz( rsd2params.bb_N_index() ),
2449  rsd2.xyz( rsd2params.bb_H_index() )
2450  );
2451  Real del_phi = basic::subtract_radian_angles(angle, phi0);
2452  del_phi = basic::periodic_range( del_phi, phi_step );
2453 
2454  Real energy_torsion = eval_score( del_phi, Kphi, 0 );
2455 
2456  // Send a message to the user about a bad angle, if necessary.
2457  // Make sure not to send output to a tracer in the middle of
2458  // scoring unless that tracer is visible, since that can be very expensive
2459  if ( energy_torsion > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2460  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd1.seqpos() << " pdbpos: " <<
2461  pose.pdb_info()->number(rsd1.seqpos()) << " improper torsion: " <<
2462  rsd1.name() << " : " <<
2463  rsd2.atom_name( rsd2params.bb_CA_index() ) << " , " << rsd1.atom_name( rsd1params.bb_C_index() ) << " , " <<
2464  rsd2.atom_name( rsd2params.bb_N_index() ) << " , " << rsd2.atom_name( rsd2params.bb_H_index() ) << " (" <<
2465  Kphi << ") " << angle << " " << phi0 << " sc=" << energy_torsion << std::endl;
2466  }
2467 
2468  emap[ cart_bonded ] += energy_torsion;
2469  emap[ cart_bonded_torsion ] += energy_torsion;
2470  }
2471 
2472  }
2473 
2474  // backbone CA-Nnext-C-O
2475  {
2477  if ( !tor_params->is_null() ) {
2478  Real const Kphi = tor_params->K(0,0);
2479  Real const phi0=tor_params->mu(0,0);
2480  Real const phi_step=2*pi/tor_params->period();
2481  Real angle = numeric::dihedral_radians(
2482  rsd1.xyz( rsd1params.bb_O_index() ),
2483  rsd1.xyz( rsd1params.bb_C_index() ),
2484  rsd2.xyz( rsd2params.bb_N_index() ),
2485  rsd1.xyz( rsd1params.bb_CA_index() )
2486  );
2487  Real del_phi = basic::subtract_radian_angles(angle, phi0);
2488  del_phi = basic::periodic_range( del_phi, phi_step );
2489 
2490  Real energy_torsion = eval_score( del_phi, Kphi, 0 );
2491 
2492  // Send a message to the user about a bad angle, if necessary.
2493  // Make sure not to send output to a tracer in the middle of
2494  // scoring unless that tracer is visible, since that can be very expensive
2495  if ( energy_torsion > CUTOFF && TR.Debug.visible() && pose.pdb_info() ) {
2496  TR.Debug << pose.pdb_info()->name() << " seqpos: " << rsd1.seqpos() << " pdbpos: " <<
2497  pose.pdb_info()->number(rsd1.seqpos()) << " improper torsion: " <<
2498  rsd1.name() << " : " <<
2499  rsd1.atom_name( rsd1params.bb_O_index() ) << " , " << rsd1.atom_name( rsd1params.bb_C_index() ) << " , " <<
2500  rsd2.atom_name( rsd2params.bb_N_index() ) << " , " << rsd1.atom_name( rsd1params.bb_CA_index() ) << " (" <<
2501  Kphi << ") " << angle << " " << phi0 << " sc=" << energy_torsion << std::endl;
2502  }
2503 
2504  emap[ cart_bonded ] += energy_torsion;
2505  emap[ cart_bonded_torsion ] += energy_torsion;
2506  }
2507  }
2508 
2509 
2510 }
2511 
2512 ///
2513 void
2515  conformation::Residue const & rsd,
2516  ResidueCartBondedParameters const & resparams,
2517  Real phi,
2518  Real psi,
2519  EnergyMap const & weights,
2520  utility::vector1< DerivVectorPair > & r_atom_derivs
2521 ) const {
2522  using numeric::constants::d::pi;
2523  using namespace numeric;
2524 
2525  chemical::ResidueType const & rsd_type = rsd.type();
2526  if ( rsd_type.aa() == core::chemical::aa_vrt) return;
2527 
2528  eval_singleres_improper_torsions_derivatives( rsd, resparams, weights, r_atom_derivs );
2529  eval_singleres_torsion_derivatives( rsd, resparams, phi, psi, weights, r_atom_derivs );
2530  eval_singleres_angle_derivatives( rsd, resparams, phi, psi, weights, r_atom_derivs );
2531  eval_singleres_length_derivatives( rsd, resparams, phi, psi, weights, r_atom_derivs );
2532 
2533 }
2534 
2535 /// @brief helper function to handle intrares bond torsions
2536 void
2538  conformation::Residue const & rsd,
2539  ResidueCartBondedParameters const & resparams,
2540  Real const phi,
2541  Real const psi,
2542  EnergyMap const & weights,
2543  utility::vector1< DerivVectorPair > & r_atom_derivs
2544 ) const
2545 {
2546  using namespace core::chemical;
2547  using numeric::constants::d::pi;
2548 
2550 
2551  Real const weight = weights[ cart_bonded_torsion ] + weights[ cart_bonded ];
2552 
2553  for ( Size ii = 1, iiend = tps.size(); ii <= iiend; ++ii ) {
2554  ResidueCartBondedParameters::Size4 const & atids( tps[ ii ].first );
2555  Size const rt1( atids[1] ), rt2( atids[2] ), rt3( atids[3] ), rt4( atids[4] );
2556  CartBondedParameters const & tor_params( *tps[ ii ].second );
2557 
2558  Real Kphi = tor_params.K(phi,psi);
2559  Real phi0 = tor_params.mu(phi,psi);
2560  Real phi_step = 2 * pi / tor_params.period();
2561 
2562  Vector f1(0.0), f2(0.0);
2563  Real angle(0.0), dE_dphi;
2564 
2565  numeric::deriv::dihedral_p1_cosine_deriv( rsd.xyz( rt1 ), rsd.xyz( rt2 ), rsd.xyz( rt3 ), rsd.xyz( rt4 ), angle, f1, f2 );
2566  Real del_phi = basic::subtract_radian_angles(angle, phi0);
2567  if (phi_step>0) del_phi = basic::periodic_range( del_phi, phi_step );
2568  if (linear_bonded_potential_ && std::fabs(del_phi)>1) {
2569  dE_dphi = weight * Kphi * (del_phi>0? 1 : -1);
2570  } else {
2571  dE_dphi = weight * Kphi * del_phi;
2572  }
2573  r_atom_derivs[ rt1 ].f1() += dE_dphi * f1;
2574  r_atom_derivs[ rt1 ].f2() += dE_dphi * f2;
2575 
2576  f1 = f2 = Vector(0.0);
2577  numeric::deriv::dihedral_p2_cosine_deriv( rsd.xyz( rt1 ), rsd.xyz( rt2 ), rsd.xyz( rt3 ), rsd.xyz( rt4 ), angle, f1, f2 );
2578  r_atom_derivs[ rt2 ].f1() += dE_dphi * f1;
2579  r_atom_derivs[ rt2 ].f2() += dE_dphi * f2;
2580 
2581  f1 = f2 = Vector(0.0);
2582  numeric::deriv::dihedral_p2_cosine_deriv( rsd.xyz( rt4 ), rsd.xyz( rt3 ), rsd.xyz( rt2 ), rsd.xyz( rt1 ), angle, f1, f2 );
2583 
2584  r_atom_derivs[ rt3 ].f1() += dE_dphi * f1;
2585  r_atom_derivs[ rt3 ].f2() += dE_dphi * f2;
2586 
2587  f1 = f2 = Vector(0.0);
2588  numeric::deriv::dihedral_p1_cosine_deriv( rsd.xyz( rt4 ), rsd.xyz( rt3 ), rsd.xyz( rt2 ), rsd.xyz( rt1 ), angle, f1, f2 );
2589  r_atom_derivs[ rt4 ].f1() += dE_dphi * f1;
2590  r_atom_derivs[ rt4 ].f2() += dE_dphi * f2;
2591 
2592  }
2593 }
2594 
2595 /// @brief helper function to handle intrares bond angles
2596 void
2598  conformation::Residue const & rsd,
2599  ResidueCartBondedParameters const & resparams,
2600  Real const phi,
2601  Real const psi,
2602  EnergyMap const & weights,
2603  utility::vector1< DerivVectorPair > & r_atom_derivs
2604 ) const
2605 {
2606  using namespace core::chemical;
2607 
2609  Real const weight = weights[ cart_bonded_angle ] + weights[ cart_bonded ];
2610 
2611  for ( Size ii = 1, iiend = aps.size(); ii <= iiend; ++ii ) {
2612  ResidueCartBondedParameters::Size3 const & atids( aps[ ii ].first );
2613  Size const rt1( atids[1] ), rt2( atids[2] ), rt3( atids[3] );
2614  CartBondedParameters const & ang_params( *aps[ ii ].second );
2615  if (ang_params.is_null()) continue;
2616  Real Ktheta = ang_params.K(phi,psi);
2617  Real theta0 = ang_params.mu(phi,psi);
2618 
2619  Vector f1(0.0), f2(0.0);
2620  Real theta(0.0), dE_dtheta;
2621 
2622  numeric::deriv::angle_p1_deriv( rsd.xyz( rt1 ), rsd.xyz( rt2 ), rsd.xyz( rt3 ), theta, f1, f2 );
2623  if (linear_bonded_potential_ && std::fabs(theta - theta0)>1) {
2624  dE_dtheta = weight * Ktheta * ((theta > theta0)>0? 1 : -1);
2625  } else {
2626  dE_dtheta = weight * Ktheta * (theta - theta0);
2627  }
2628  r_atom_derivs[ rt1 ].f1() += dE_dtheta * f1;
2629  r_atom_derivs[ rt1 ].f2() += dE_dtheta * f2;
2630 
2631  numeric::deriv::angle_p2_deriv( rsd.xyz( rt1 ), rsd.xyz( rt2 ), rsd.xyz( rt3 ), theta, f1, f2 );
2632  r_atom_derivs[ rt2 ].f1() += dE_dtheta * f1;
2633  r_atom_derivs[ rt2 ].f2() += dE_dtheta * f2;
2634 
2635  numeric::deriv::angle_p1_deriv( rsd.xyz( rt3 ), rsd.xyz( rt2 ), rsd.xyz( rt1 ), theta, f1, f2 );
2636  r_atom_derivs[ rt3 ].f1() += dE_dtheta * f1;
2637  r_atom_derivs[ rt3 ].f2() += dE_dtheta * f2;
2638  }
2639 }
2640 
2641 /// @brief helper function to handle intrares bond lengths
2642 void
2644  conformation::Residue const & rsd,
2645  ResidueCartBondedParameters const & resparams,
2646  Real const phi,
2647  Real const psi,
2648  EnergyMap const & weights,
2649  utility::vector1< DerivVectorPair > & r_atom_derivs
2650 ) const
2651 {
2652  using namespace core::chemical;
2653 
2655  Real const weight = weights[ cart_bonded_length ] + weights[ cart_bonded ];
2656 
2657  for ( Size ii = 1, iiend = lps.size(); ii <= iiend; ++ii ) {
2658  ResidueCartBondedParameters::Size2 const & atids( lps[ ii ].first );
2659  Size const rt1( atids[1] ), rt2( atids[2] );
2660  CartBondedParameters const & len_params( *lps[ ii ].second );
2661  if (len_params.is_null() ) continue;
2662 
2663  Real const Kd = len_params.K(phi,psi);
2664  Real const d0 = len_params.mu(phi,psi);
2665 
2666  Vector f1(0.0), f2(0.0);
2667  Real d=0, dE_dd;
2668 
2669  numeric::deriv::distance_f1_f2_deriv( rsd.xyz( rt1 ), rsd.xyz( rt2 ), d, f1, f2 );
2670  if (linear_bonded_potential_ && std::fabs(d - d0)>1) {
2671  dE_dd = weight * Kd * ((d - d0)>0? 1 : -1);
2672  } else {
2673  dE_dd = weight * Kd * (d - d0);
2674  }
2675  r_atom_derivs[ rt1 ].f1() += dE_dd * f1;
2676  r_atom_derivs[ rt1 ].f2() += dE_dd * f2;
2677 
2678  r_atom_derivs[ rt2 ].f1() -= dE_dd * f1;
2679  r_atom_derivs[ rt2 ].f2() -= dE_dd * f2;
2680 
2681  }
2682 }
2683 
2684 // deriv impropers
2685 void
2687  conformation::Residue const & rsd,
2688  ResidueCartBondedParameters const & resparams,
2689  EnergyMap const & weights,
2690  utility::vector1< DerivVectorPair > & r_atom_derivs
2691 ) const {
2692  using namespace core::chemical;
2693  using numeric::constants::d::pi;
2694 
2696  resparams.improper_torsion_parameters() );
2697  Real const weight = weights[ cart_bonded_torsion ] + weights[ cart_bonded ];
2698 
2699  for ( Size ii = 1, iiend = itps.size(); ii <= iiend; ++ii ) {
2700  ResidueCartBondedParameters::Size4 const & atids( itps[ ii ].first );
2701  Size const rt1( atids[1] ), rt2( atids[2] ), rt3( atids[3] ), rt4( atids[4] );
2702  CartBondedParameters const & tor_params( *itps[ ii ].second );
2703  Real Kphi = tor_params.K(0,0);
2704  Real phi0 = tor_params.mu(0,0);
2705  Real phi_step=2 * pi / tor_params.period();
2706 
2707 
2708  Vector f1(0.0), f2(0.0);
2709  Real phi=0, dE_dphi;
2710 
2711  numeric::deriv::dihedral_p1_cosine_deriv(
2712  rsd.xyz( rt1 ), rsd.xyz( rt2 ), rsd.xyz( rt3 ), rsd.xyz( rt4 ), phi, f1, f2 );
2713  Real del_phi = basic::subtract_radian_angles(phi, phi0);
2714  del_phi = basic::periodic_range( del_phi, phi_step );
2715  if (linear_bonded_potential_ && std::fabs(del_phi)>1) {
2716  dE_dphi = weight * Kphi * (del_phi>0? 1 : -1);
2717  } else {
2718  dE_dphi = weight * Kphi * del_phi;
2719  }
2720  r_atom_derivs[ rt1 ].f1() += dE_dphi * f1;
2721  r_atom_derivs[ rt1 ].f2() += dE_dphi * f2;
2722 
2723  f1 = f2 = Vector(0.0);
2724  numeric::deriv::dihedral_p2_cosine_deriv(
2725  rsd.xyz( rt1 ), rsd.xyz( rt2 ), rsd.xyz( rt3 ), rsd.xyz( rt4 ), phi, f1, f2 );
2726  r_atom_derivs[ rt2 ].f1() += dE_dphi * f1;
2727  r_atom_derivs[ rt2 ].f2() += dE_dphi * f2;
2728 
2729  f1 = f2 = Vector(0.0);
2730  numeric::deriv::dihedral_p2_cosine_deriv(
2731  rsd.xyz( rt4 ), rsd.xyz( rt3 ), rsd.xyz( rt2 ), rsd.xyz( rt1 ), phi, f1, f2 );
2732 
2733  r_atom_derivs[ rt3 ].f1() += dE_dphi * f1;
2734  r_atom_derivs[ rt3 ].f2() += dE_dphi * f2;
2735 
2736  f1 = f2 = Vector(0.0);
2737  numeric::deriv::dihedral_p1_cosine_deriv(
2738  rsd.xyz( rt4 ), rsd.xyz( rt3 ), rsd.xyz( rt2 ), rsd.xyz( rt1 ), phi, f1, f2 );
2739  r_atom_derivs[ rt4 ].f1() += dE_dphi * f1;
2740  r_atom_derivs[ rt4 ].f2() += dE_dphi * f2;
2741  }
2742 }
2743 
2744 
2745 
2746 void
2748  conformation::Residue const & rsd1,
2749  conformation::Residue const & rsd2,
2750  ResidueCartBondedParameters const & rsd1params,
2751  ResidueCartBondedParameters const & rsd2params,
2752  Real phi1,
2753  Real psi1,
2754  EnergyMap const & weights,
2755  utility::vector1< DerivVectorPair > & r1_atom_derivs,
2756  utility::vector1< DerivVectorPair > & r2_atom_derivs
2757 ) const
2758 {
2759  using namespace core::chemical;
2760  if ( rsd1.aa() <= num_canonical_aas && rsd2.aa() <= num_canonical_aas &&
2761  rsd1.residue_connection_partner( rsd1.upper_connect().index() ) == rsd2.seqpos() ) {
2762 
2763  /// Assumption: rsd1 and rsd2 share a peptide bond and only a peptide bond.
2764  assert( rsd2.residue_connection_partner( rsd2.lower_connect().index() ) == rsd1.seqpos() );
2765  assert( rsd1.connections_to_residue( rsd2 ).size() == 1 );
2766 
2768  for ( Size ii = 1, iiend = aps.size(); ii <= iiend; ++ii ) {
2769  ResidueCartBondedParameters::Size3 const & atids( aps[ ii ].first );
2770  CartBondedParameters const & ang_params( *aps[ ii ].second );
2771  Real Ktheta = ang_params.K(phi1,psi1);
2772  Real theta0 = ang_params.mu(phi1,psi1);
2773 
2774  // temp -- rename these variables, ok?
2775  Size const res1_lower_atomno = atids[1], resconn_atomno1 = atids[2], resconn_atomno2 = rsd2params.bb_N_index();
2776 
2777  Vector f1(0.0), f2(0.0);
2778  Real theta(0.0), dE_dtheta;
2779  numeric::deriv::angle_p1_deriv(
2780  rsd1.xyz( res1_lower_atomno ), rsd1.xyz( resconn_atomno1 ), rsd2.xyz( resconn_atomno2 ), theta, f1, f2 );
2781  if (linear_bonded_potential_ && std::fabs(theta - theta0)>1) {
2782  dE_dtheta = (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * Ktheta * ((theta - theta0)>0? 1 : -1);
2783  } else {
2784  dE_dtheta = (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * Ktheta * (theta - theta0);
2785  }
2786  r1_atom_derivs[ res1_lower_atomno ].f1() += dE_dtheta * f1;
2787  r1_atom_derivs[ res1_lower_atomno ].f2() += dE_dtheta * f2;
2788 
2789  numeric::deriv::angle_p2_deriv(
2790  rsd1.xyz( res1_lower_atomno ), rsd1.xyz( resconn_atomno1 ), rsd2.xyz( resconn_atomno2 ), theta, f1, f2 );
2791  r1_atom_derivs[ resconn_atomno1 ].f1() += dE_dtheta * f1;
2792  r1_atom_derivs[ resconn_atomno1 ].f2() += dE_dtheta * f2;
2793 
2794  numeric::deriv::angle_p1_deriv(
2795  rsd2.xyz( resconn_atomno2 ), rsd1.xyz( resconn_atomno1 ), rsd1.xyz( res1_lower_atomno ), theta, f1, f2 );
2796  r2_atom_derivs[ resconn_atomno2 ].f1() += dE_dtheta * f1;
2797  r2_atom_derivs[ resconn_atomno2 ].f2() += dE_dtheta * f2;
2798  }
2799 
2800  } else {
2801  // At the time of the writing of this comment, the CartesianBondEnergy is used only
2802  // to evaluate protein energetics, and the only inter-residue bonds it is evaluated
2803  // on is peptide bonds. If that persists, then this "else" clause will never be executed.
2804  // If it does get executed, then this else clause ought to be optimized.
2805  // Before the above "if" and the below "else" clauses got separated, the only code
2806  // executed was the "else" clause and it was rediculously slow. I mean much much
2807  // slower than evaluating the etable energies. REEAAALLLLY SLOW.
2808 
2809  utility::vector1< Size > const & r1_resconn_ids( rsd1.connections_to_residue( rsd2 ) );
2810  for ( Size ii = 1; ii <= r1_resconn_ids.size(); ++ii ) {
2811  Size const resconn_id1( r1_resconn_ids[ii] );
2812  Size const resconn_id2( rsd1.residue_connection_conn_id( resconn_id1 ) );
2813 
2814  Size const resconn_atomno1( rsd1.residue_connection( resconn_id1 ).atomno() );
2815  Size const resconn_atomno2( rsd2.residue_connection( resconn_id2 ).atomno() );
2816 
2817  // compute bond-angle energies with two atoms on rsd1
2818  utility::vector1< chemical::two_atom_set > const & rsd1_atoms_wi1_bond_of_ii(
2819  rsd1.type().atoms_within_one_bond_of_a_residue_connection( resconn_id1 ));
2820  for ( Size jj = 1; jj <= rsd1_atoms_wi1_bond_of_ii.size(); ++jj ) {
2821  assert( rsd1_atoms_wi1_bond_of_ii[ jj ].key1() == resconn_atomno1 );
2822  Size const res1_lower_atomno = rsd1_atoms_wi1_bond_of_ii[ jj ].key2();
2823 
2824  //Real const angle = numeric::angle_radians( // why compute the angle if you're not going to use it?
2825  // rsd1.atom( res1_lower_atomno ).xyz(),
2826  // rsd1.atom( resconn_atomno1 ).xyz(),
2827  // rsd2.atom( resconn_atomno2 ).xyz() );
2828  std::string atm1name=rsd1.atom_name(res1_lower_atomno); boost::trim(atm1name);
2829  std::string atm2name=rsd1.atom_name(resconn_atomno1); boost::trim(atm2name);
2830  std::string atm3name=rsd2.atom_name(resconn_atomno2); boost::trim(atm3name);
2831 
2832  // lookup Ktheta and theta0
2833  CartBondedParametersCOP ang_params = db_->lookup_angle(rsd1.type(), rsd2.aa() == chemical::aa_pro,
2834  atm1name, atm2name, atm3name, res1_lower_atomno, resconn_atomno1, -resconn_id1);
2835  if (ang_params->is_null()) continue;
2836  Real Ktheta=ang_params->K(phi1,psi1), theta0=ang_params->mu(phi1,psi1);
2837 
2838  Vector f1(0.0), f2(0.0);
2839  Real theta(0.0), dE_dtheta;
2840  numeric::deriv::angle_p1_deriv(
2841  rsd1.xyz( res1_lower_atomno ), rsd1.xyz( resconn_atomno1 ), rsd2.xyz( resconn_atomno2 ), theta, f1, f2 );
2842  if (linear_bonded_potential_ && std::fabs(theta - theta0)>1)
2843  dE_dtheta = (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * Ktheta * ((theta - theta0)>0? 1 : -1);
2844  else
2845  dE_dtheta = (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * Ktheta * (theta - theta0);
2846  r1_atom_derivs[ res1_lower_atomno ].f1() += dE_dtheta * f1;
2847  r1_atom_derivs[ res1_lower_atomno ].f2() += dE_dtheta * f2;
2848 
2849  numeric::deriv::angle_p2_deriv(
2850  rsd1.xyz( res1_lower_atomno ), rsd1.xyz( resconn_atomno1 ), rsd2.xyz( resconn_atomno2 ), theta, f1, f2 );
2851  r1_atom_derivs[ resconn_atomno1 ].f1() += dE_dtheta * f1;
2852  r1_atom_derivs[ resconn_atomno1 ].f2() += dE_dtheta * f2;
2853 
2854  numeric::deriv::angle_p1_deriv(
2855  rsd2.xyz( resconn_atomno2 ), rsd1.xyz( resconn_atomno1 ), rsd1.xyz( res1_lower_atomno ), theta, f1, f2 );
2856  r2_atom_derivs[ resconn_atomno2 ].f1() += dE_dtheta * f1;
2857  r2_atom_derivs[ resconn_atomno2 ].f2() += dE_dtheta * f2;
2858  }
2859  }
2860  }
2861 }
2862 
2863 void
2865  conformation::Residue const & rsd1,
2866  conformation::Residue const & rsd2,
2867  ResidueCartBondedParameters const & rsd1params,
2868  ResidueCartBondedParameters const & rsd2params,
2869  Real phi2,
2870  Real psi2,
2871  EnergyMap const & weights,
2872  utility::vector1< DerivVectorPair > & r1_atom_derivs,
2873  utility::vector1< DerivVectorPair > & r2_atom_derivs
2874 ) const
2875 {
2876  using namespace core::chemical;
2877  if ( rsd1.aa() <= num_canonical_aas && rsd2.aa() <= num_canonical_aas &&
2878  rsd1.residue_connection_partner( rsd1.upper_connect().index() ) == rsd2.seqpos() ) {
2879 
2880  /// Assumption: rsd1 and rsd2 share a peptide bond and only a peptide bond.
2881  assert( rsd2.residue_connection_partner( rsd2.lower_connect().index() ) == rsd1.seqpos() );
2882  assert( rsd1.connections_to_residue( rsd2 ).size() == 1 );
2883 
2885  for ( Size ii = 1, iiend = aps.size(); ii <= iiend; ++ii ) {
2886  ResidueCartBondedParameters::Size3 const & atids( aps[ ii ].first );
2887  CartBondedParameters const & ang_params( *aps[ ii ].second );
2888  Real Ktheta = ang_params.K(phi2,psi2);
2889  Real theta0 = ang_params.mu(phi2,psi2);
2890 
2891  // temp -- rename these variables, ok?
2892  Size const res2_lower_atomno = atids[1], resconn_atomno2 = atids[2], resconn_atomno1 = rsd1params.bb_C_index();
2893 
2894  Vector f1(0.0), f2(0.0);
2895  Real theta(0.0), dE_dtheta;
2896  numeric::deriv::angle_p1_deriv(
2897  rsd2.xyz( res2_lower_atomno ), rsd2.xyz( resconn_atomno2 ), rsd1.xyz( resconn_atomno1 ), theta, f1, f2 );
2898  if ( linear_bonded_potential_ && std::fabs(theta - theta0)>1 ) {
2899  dE_dtheta = (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * Ktheta * ((theta - theta0)>0? 1 : -1);
2900  } else {
2901  dE_dtheta = (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * Ktheta * (theta - theta0);
2902  }
2903  r2_atom_derivs[ res2_lower_atomno ].f1() += dE_dtheta * f1;
2904  r2_atom_derivs[ res2_lower_atomno ].f2() += dE_dtheta * f2;
2905 
2906  numeric::deriv::angle_p2_deriv(
2907  rsd2.xyz( res2_lower_atomno ), rsd2.xyz( resconn_atomno2 ), rsd1.xyz( resconn_atomno1 ), theta, f1, f2 );
2908  r2_atom_derivs[ resconn_atomno2 ].f1() += dE_dtheta * f1;
2909  r2_atom_derivs[ resconn_atomno2 ].f2() += dE_dtheta * f2;
2910 
2911  numeric::deriv::angle_p1_deriv(
2912  rsd1.xyz( resconn_atomno1 ), rsd2.xyz( resconn_atomno2 ), rsd2.xyz( res2_lower_atomno ), theta, f1, f2 );
2913  r1_atom_derivs[ resconn_atomno1 ].f1() += dE_dtheta * f1;
2914  r1_atom_derivs[ resconn_atomno1 ].f2() += dE_dtheta * f2;
2915  }
2916 
2917  } else {
2918  // At the time of the writing of this comment, the CartesianBondEnergy is used only
2919  // to evaluate protein energetics, and the only inter-residue bonds it is evaluated
2920  // on is peptide bonds. If that persists, then this "else" clause will never be executed.
2921  // If it does get executed, then this else clause ought to be optimized.
2922  // Before the above "if" and the below "else" clauses got separated, the only code
2923  // executed was the "else" clause and it was rediculously slow. I mean much much
2924  // slower than evaluating the etable energies. REEAAALLLLY SLOW.
2925 
2926  utility::vector1< Size > const & r1_resconn_ids( rsd1.connections_to_residue( rsd2 ) );
2927  for ( Size ii = 1; ii <= r1_resconn_ids.size(); ++ii ) {
2928  Size const resconn_id1( r1_resconn_ids[ii] );
2929  Size const resconn_id2( rsd1.residue_connection_conn_id( resconn_id1 ) );
2930 
2931  Size const resconn_atomno1( rsd1.residue_connection( resconn_id1 ).atomno() );
2932  Size const resconn_atomno2( rsd2.residue_connection( resconn_id2 ).atomno() );
2933 
2934  utility::vector1< chemical::two_atom_set > const & rsd2_atoms_wi1_bond_of_ii(
2935  rsd2.type().atoms_within_one_bond_of_a_residue_connection( resconn_id2 ));
2936  for ( Size jj = 1; jj <= rsd2_atoms_wi1_bond_of_ii.size(); ++jj ) {
2937  assert( rsd2_atoms_wi1_bond_of_ii[ jj ].key1() == resconn_atomno2 );
2938  Size const res2_lower_atomno = rsd2_atoms_wi1_bond_of_ii[ jj ].key2();
2939 
2940  // lookup Ktheta and theta0
2941  // set pre-proline to false here -- it refers to rsd2+1 which would make this three-body
2942  std::string atm1name=rsd2.atom_name(res2_lower_atomno); boost::trim(atm1name);
2943  std::string atm2name=rsd2.atom_name(resconn_atomno2); boost::trim(atm2name);
2944  std::string atm3name=rsd1.atom_name(resconn_atomno1); boost::trim(atm3name);
2945  CartBondedParametersCOP ang_params = db_->lookup_angle(rsd2.type(), false,
2946  atm1name, atm2name, atm3name, res2_lower_atomno, resconn_atomno2, -resconn_id2);
2947  if (ang_params->is_null()) continue;
2948  Real Ktheta=ang_params->K(phi2,psi2), theta0=ang_params->mu(phi2,psi2);
2949 
2950  Vector f1(0.0), f2(0.0);
2951  Real theta(0.0), dE_dtheta;
2952  numeric::deriv::angle_p1_deriv(
2953  rsd2.xyz( res2_lower_atomno ), rsd2.xyz( resconn_atomno2 ), rsd1.xyz( resconn_atomno1 ), theta, f1, f2 );
2954  if (linear_bonded_potential_ && std::fabs(theta - theta0)>1)
2955  dE_dtheta = (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * Ktheta * ((theta - theta0)>0? 1 : -1);
2956  else
2957  dE_dtheta = (weights[ cart_bonded_angle ] + weights[ cart_bonded ]) * Ktheta * (theta - theta0);
2958  r2_atom_derivs[ res2_lower_atomno ].f1() += dE_dtheta * f1;
2959  r2_atom_derivs[ res2_lower_atomno ].f2() += dE_dtheta * f2;
2960 
2961  numeric::deriv::angle_p2_deriv(
2962  rsd2.xyz( res2_lower_atomno ), rsd2.xyz( resconn_atomno2 ), rsd1.xyz( resconn_atomno1 ), theta, f1, f2 );
2963  r2_atom_derivs[ resconn_atomno2 ].f1() += dE_dtheta * f1;
2964  r2_atom_derivs[ resconn_atomno2 ].f2() += dE_dtheta * f2;
2965 
2966  numeric::deriv::angle_p1_deriv(
2967  rsd1.xyz( resconn_atomno1 ), rsd2.xyz( resconn_atomno2 ), rsd2.xyz( res2_lower_atomno ), theta, f1, f2 );
2968  r1_atom_derivs[ resconn_atomno1 ].f1() += dE_dtheta * f1;
2969  r1_atom_derivs[ resconn_atomno1 ].f2() += dE_dtheta * f2;
2970  }
2971  }
2972  }
2973 }
2974 
2975 void
2977  conformation::Residue const & rsd1,
2978  conformation::Residue const & rsd2,
2979  ResidueCartBondedParameters const & rsd1params,
2980  ResidueCartBondedParameters const & rsd2params,
2981  Real phi2,
2982  Real psi2,
2983  EnergyMap const & weights,
2984  utility::vector1< DerivVectorPair > & r1_atom_derivs,
2985  utility::vector1< DerivVectorPair > & r2_atom_derivs
2986 ) const
2987 {
2988  using namespace core::chemical;
2989  if ( rsd1.aa() <= num_canonical_aas && rsd2.aa() <= num_canonical_aas &&
2990  rsd1.residue_connection_partner( rsd1.upper_connect().index() )== rsd2.seqpos() ) {
2991 
2992  /// Assumption: rsd1 and rsd2 share a peptide bond and only a peptide bond.
2993  assert( rsd2.residue_connection_partner( rsd2.lower_connect().index() ) == rsd1.seqpos() );
2994  assert( rsd1.connections_to_residue( rsd2 ).size() == 1 );
2995 
2996  // lookup Kd and d0
2997  CartBondedParametersCOP len_params = rsd2params.cprev_n_bond_length_params();
2998 
2999  if (len_params->is_null()) return;
3000  Real const Kd = len_params->K(phi2,psi2);
3001  Real const d0 = len_params->mu(phi2,psi2);
3002 
3003  Size const r1at = rsd1params.bb_C_index();
3004  Size const r2at = rsd2params.bb_N_index();
3005 
3006  Vector f1(0.0), f2(0.0);
3007  Real d=0, dE_dd;
3008 
3009  numeric::deriv::distance_f1_f2_deriv( rsd2.xyz( r2at ), rsd1.xyz( r1at ), d, f1, f2 );
3010  if (linear_bonded_potential_ && std::fabs(d - d0)>1) {
3011  dE_dd = (weights[ cart_bonded_length ] + weights[ cart_bonded ]) * Kd * ((d - d0)>0? 1 : -1);
3012  } else {
3013  dE_dd = (weights[ cart_bonded_length ] + weights[ cart_bonded ]) * Kd * (d - d0);
3014  }
3015  r2_atom_derivs[ r2at ].f1() += dE_dd * f1;
3016  r2_atom_derivs[ r2at ].f2() += dE_dd * f2;
3017 
3018  r1_atom_derivs[ r1at ].f1() -= dE_dd * f1;
3019  r1_atom_derivs[ r1at ].f2() -= dE_dd * f2;
3020 
3021 
3022  } else {
3023  // At the time of the writing of this comment, the CartesianBondEnergy is used only
3024  // to evaluate protein energetics, and the only inter-residue bonds it is evaluated
3025  // on is peptide bonds. If that persists, then this "else" clause will never be executed.
3026  // If it does get executed, then this else clause ought to be optimized.
3027  // Before the above "if" and the below "else" clauses got separated, the only code
3028  // executed was the "else" clause and it was rediculously slow. I mean much much
3029  // slower than evaluating the etable energies. REEAAALLLLY SLOW.
3030 
3031  utility::vector1< Size > const & r1_resconn_ids( rsd1.connections_to_residue( rsd2 ) );
3032  for ( Size ii = 1; ii <= r1_resconn_ids.size(); ++ii ) {
3033  Size const resconn_id1( r1_resconn_ids[ii] );
3034  Size const resconn_id2( rsd1.residue_connection_conn_id( resconn_id1 ) );
3035 
3036  Size const resconn_atomno1( rsd1.residue_connection( resconn_id1 ).atomno() );
3037  Size const resconn_atomno2( rsd2.residue_connection( resconn_id2 ).atomno() );
3038 
3039  // [3] Bonds across connection
3040  std::string atm1name=rsd2.atom_name(resconn_atomno2); boost::trim(atm1name);
3041  std::string atm2name=rsd1.atom_name(resconn_atomno1); boost::trim(atm2name);
3042  CartBondedParametersCOP len_params = db_->lookup_length(rsd2.type(), false,
3043  atm1name, atm2name, resconn_atomno2, -resconn_id2);
3044 
3045  if (len_params->is_null()) continue;
3046  Real Kd=len_params->K(phi2,psi2), d0=len_params->mu(phi2,psi2);
3047 
3048  Vector f1(0.0), f2(0.0);
3049  Real d=0, dE_dd;
3050 
3051  numeric::deriv::distance_f1_f2_deriv( rsd2.xyz( resconn_atomno2 ), rsd1.xyz( resconn_atomno1 ), d, f1, f2 );
3052  if (linear_bonded_potential_ && std::fabs(d - d0)>1)
3053  dE_dd = (weights[ cart_bonded_length ] + weights[ cart_bonded ]) * Kd * ((d - d0)>0? 1 : -1);
3054  else
3055  dE_dd = (weights[ cart_bonded_length ] + weights[ cart_bonded ]) * Kd * (d - d0);
3056  r2_atom_derivs[ resconn_atomno2 ].f1() += dE_dd * f1;
3057  r2_atom_derivs[ resconn_atomno2 ].f2() += dE_dd * f2;
3058 
3059  numeric::deriv::distance_f1_f2_deriv( rsd1.xyz( resconn_atomno1 ), rsd2.xyz( resconn_atomno2 ), d, f1, f2 );
3060  r1_atom_derivs[ resconn_atomno1 ].f1() += dE_dd * f1;
3061  r1_atom_derivs[ resconn_atomno1 ].f2() += dE_dd * f2;
3062  }
3063  }
3064 }
3065 
3066 // deriv impropers
3067 void
3069  conformation::Residue const & res1,
3070  conformation::Residue const & res2,
3071  ResidueCartBondedParameters const & rsd1params,
3072  ResidueCartBondedParameters const & rsd2params,
3073  EnergyMap const & weights,
3074  utility::vector1< DerivVectorPair > & r1_atom_derivs,
3075  utility::vector1< DerivVectorPair > & r2_atom_derivs
3076 ) const {
3077  using namespace core::chemical;
3078  using numeric::constants::d::pi;
3079 
3080  assert ( res1.seqpos() < res2.seqpos() );
3081 
3082  // backbone C-N-CA-H
3083  if (!res1.is_protein() || !res2.is_protein()) return;
3084  Real weight = weights[ cart_bonded_torsion ] + weights[ cart_bonded ];
3085 
3086  // backbone CA-Cprev-N-H
3087  if ( res2.aa() != aa_pro && rsd2params.bb_H_index() != 0 ) {
3089  if ( !tor_params->is_null() ) {
3090  Real const Kphi = tor_params->K(0,0);
3091  Real const phi0=tor_params->mu(0,0);
3092  Real const phi_step=2*pi/tor_params->period();
3093 
3094  Vector f1(0.0), f2(0.0);
3095  Real phi=0, dE_dphi;
3096 
3097  Size const atm1( rsd2params.bb_CA_index() );
3098  Size const atm2( rsd1params.bb_C_index() );
3099  Size const atm3( rsd2params.bb_N_index() );
3100  Size const atm4( rsd2params.bb_H_index() );
3101 
3102  numeric::deriv::dihedral_p1_cosine_deriv(
3103  res2.xyz( atm1 ), res1.xyz( atm2 ), res2.xyz( atm3 ), res2.xyz( atm4 ), phi, f1, f2 );
3104  Real del_phi = basic::subtract_radian_angles(phi, phi0);
3105  del_phi = basic::periodic_range( del_phi, phi_step );
3106  if (linear_bonded_potential_ && std::fabs(del_phi)>1) {
3107  dE_dphi = weight * Kphi * (del_phi>0? 1 : -1);
3108  } else {
3109  dE_dphi = weight * Kphi * del_phi;
3110  }
3111  r2_atom_derivs[ atm1 ].f1() += dE_dphi * f1;
3112  r2_atom_derivs[ atm1 ].f2() += dE_dphi * f2;
3113 
3114  f1 = f2 = Vector(0.0);
3115  numeric::deriv::dihedral_p2_cosine_deriv(
3116  res2.xyz( atm1 ), res1.xyz( atm2 ), res2.xyz( atm3 ), res2.xyz( atm4 ), phi, f1, f2 );
3117  r1_atom_derivs[ atm2 ].f1() += dE_dphi * f1;
3118  r1_atom_derivs[ atm2 ].f2() += dE_dphi * f2;
3119 
3120  f1 = f2 = Vector(0.0);
3121  numeric::deriv::dihedral_p2_cosine_deriv(
3122  res2.xyz( atm4 ), res2.xyz( atm3 ), res1.xyz( atm2 ), res2.xyz( atm1 ), phi, f1, f2 );
3123  r2_atom_derivs[ atm3 ].f1() += dE_dphi * f1;
3124  r2_atom_derivs[ atm3 ].f2() += dE_dphi * f2;
3125 
3126  f1 = f2 = Vector(0.0);
3127  numeric::deriv::dihedral_p1_cosine_deriv(
3128  res2.xyz( atm4 ), res2.xyz( atm3 ), res1.xyz( atm2 ), res2.xyz( atm1 ), phi, f1, f2 );
3129  r2_atom_derivs[ atm4 ].f1() += dE_dphi * f1;
3130  r2_atom_derivs[ atm4 ].f2() += dE_dphi * f2;
3131  }
3132  }
3133 
3134  // backbone CA-Nnext-C-O
3135  {
3137  if (!tor_params->is_null()) { // however, if it is in the db but with 0 weight, that is OK
3138  core::Size const atm1 = rsd1params.bb_CA_index();
3139  core::Size const atm2 = rsd2params.bb_N_index();
3140  core::Size const atm3 = rsd1params.bb_C_index();
3141  core::Size const atm4 = rsd1params.bb_O_index();
3142 
3143  Real const Kphi = tor_params->K(0,0);
3144  Real const phi0=tor_params->mu(0,0);
3145  Real const phi_step=2*pi/tor_params->period();
3146 
3147  Vector f1(0.0), f2(0.0);
3148  Real phi=0, dE_dphi;
3149 
3150  numeric::deriv::dihedral_p1_cosine_deriv(
3151  res1.xyz( atm1 ), res2.xyz( atm2 ), res1.xyz( atm3 ), res1.xyz( atm4 ), phi, f1, f2 );
3152  Real del_phi = basic::subtract_radian_angles(phi, phi0);
3153  del_phi = basic::periodic_range( del_phi, phi_step );
3154  if (linear_bonded_potential_ && std::fabs(del_phi)>1) {
3155  dE_dphi = (weights[ cart_bonded_torsion ] + weights[ cart_bonded ]) * Kphi * (del_phi>0? 1 : -1);
3156  } else {
3157  dE_dphi = (weights[ cart_bonded_torsion ] + weights[ cart_bonded ]) * Kphi * del_phi;
3158  }
3159  r1_atom_derivs[ atm1 ].f1() += dE_dphi * f1;
3160  r1_atom_derivs[ atm1 ].f2() += dE_dphi * f2;
3161 
3162  f1 = f2 = Vector(0.0);
3163  numeric::deriv::dihedral_p2_cosine_deriv(
3164  res1.xyz( atm1 ), res2.xyz( atm2 ), res1.xyz( atm3 ), res1.xyz( atm4 ), phi, f1, f2 );
3165  r2_atom_derivs[ atm2 ].f1() += dE_dphi * f1;
3166  r2_atom_derivs[ atm2 ].f2() += dE_dphi * f2;
3167 
3168  f1 = f2 = Vector(0.0);
3169  numeric::deriv::dihedral_p2_cosine_deriv(
3170  res1.xyz( atm4 ), res1.xyz( atm3 ), res2.xyz( atm2 ), res1.xyz( atm1 ), phi, f1, f2 );
3171  r1_atom_derivs[ atm3 ].f1() += dE_dphi * f1;
3172  r1_atom_derivs[ atm3 ].f2() += dE_dphi * f2;
3173 
3174  f1 = f2 = Vector(0.0);
3175  numeric::deriv::dihedral_p1_cosine_deriv(
3176  res1.xyz( atm4 ), res1.xyz( atm3 ), res2.xyz( atm2 ), res1.xyz( atm1 ), phi, f1, f2 );
3177  r1_atom_derivs[ atm4 ].f1() += dE_dphi * f1;
3178  r1_atom_derivs[ atm4 ].f2() += dE_dphi * f2;
3179  }
3180  }
3181 }
3182 
3183 
3184 Real
3186  Real val, // actual value
3187  Real K, // spring constant
3188  Real val0 // ideal value
3189 ) const
3190 {
3191  Real const absdiff = std::fabs(val-val0);
3192  if ( linear_bonded_potential_ && absdiff > 1 ) {
3193  return 0.5 * K * absdiff;
3194  } else {
3195  return 0.5 * K * absdiff * absdiff;
3196  }
3197 }
3198 
3199 core::Size
3201  return 1; // Initial versioning
3202 }
3203 
3204 } // namespace methods
3205 } // namespace scoring
3206 } // namespace core