Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ExactOccludedHbondSolEnergy.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 // This file is part of the Rosetta software suite and is made available under license.
5 // The Rosetta software is developed by the contributing members of the Rosetta Commons consortium.
6 // (C) 199x-2009 Rosetta Commons participating institutions and developers.
7 // For more information, see http://www.rosettacommons.org/.
8 
9 /// @brief
10 /// @author jk
11 
12 // Project Headers
15 
16 // AUTO-REMOVED #include <core/init.hh>
17 #include <core/types.hh>
18 // AUTO-REMOVED #include <core/io/pdb/pose_io.hh>
19 #include <core/id/AtomID.hh>
20 // AUTO-REMOVED #include <core/id/AtomID_Map.hh>
21 // AUTO-REMOVED #include <core/id/AtomID_Map.Pose.hh>
22 #include <core/pose/Pose.hh>
23 
27 // AUTO-REMOVED #include <core/chemical/ResidueTypeSet.hh>
28 // AUTO-REMOVED #include <core/conformation/ResidueFactory.hh>
30 #include <core/scoring/Energies.hh>
31 // AUTO-REMOVED #include <core/scoring/rms_util.hh>
32 // AUTO-REMOVED #include <core/scoring/ScoreFunction.hh>
33 // AUTO-REMOVED #include <core/scoring/ScoringManager.hh>
34 // AUTO-REMOVED #include <core/scoring/ScoreFunctionFactory.hh>
36 // AUTO-REMOVED #include <basic/options/util.hh>
37 #include <basic/Tracer.hh>
38 
45 // AUTO-REMOVED #include <core/scoring/hbonds/hbonds.hh> //ws
46 // AUTO-REMOVED #include <core/scoring/hbonds/HBondTypeManager.hh> //ws
47 
48 // AUTO-REMOVED #include <numeric/constants.hh>
49 #include <numeric/xyzVector.hh>
50 #include <numeric/xyzMatrix.hh>
51 
52 //#include <core/scoring/ScoreFunction.hh>
53 //#include <core/scoring/ScoreFunctionFactory.hh>
54 
55 // AUTO-REMOVED #include <basic/options/option_macros.hh>
56 #include <basic/options/keys/score.OptionKeys.gen.hh>
57 
58 // Utility Headers
59 #include <utility/vector1.hh>
60 // AUTO-REMOVED #include <utility/io/ozstream.hh>
61 
62 // C++ Headers
63 #include <cmath>
64 #include <iostream>
65 #include <iomanip>
66 #include <map>
67 #include <vector>
68 
69 //Auto Headers
70 #include <platform/types.hh>
74 #include <core/id/DOF_ID.hh>
77 #include <core/kinematics/Jump.hh>
78 #include <utility/Bound.hh>
79 #include <utility/string_util.hh>
80 #include <utility/vector0_bool.hh>
81 #include <utility/file/FileName.hh>
82 #include <utility/keys/SmallKeyVector.hh>
83 #include <utility/options/BooleanOption.hh>
84 #include <utility/options/OptionCollection.hh>
85 #include <numeric/xyz.functions.hh>
86 #include <ObjexxFCL/FArray3D.hh>
87 #include <basic/options/option.hh>
88 
89 //Vector dummy_res_energy_vector_;
90 
91 static basic::Tracer TR( "core.scoring.geometric_solvation.ExactOccludedHbondSolEnergy" );
92 
93 namespace core {
94 namespace scoring {
95 namespace geometric_solvation {
96 
97 
98 /// @details This must return a fresh instance of the ExactOccludedHbondSolEnergy class,
99 /// never an instance already in use
103 ) const {
104  return new ExactOccludedHbondSolEnergy(
105  basic::options::option[ basic::options::OptionKeys::score::exact_occ_skip_Hbonders ],
106  basic::options::option[ basic::options::OptionKeys::score::exact_occ_include_Hbond_contribution ],
107  basic::options::option[ basic::options::OptionKeys::score::exact_occ_pairwise ],
108  basic::options::option[ basic::options::OptionKeys::score::exact_occ_pairwise_by_res ],
109  basic::options::option[ basic::options::OptionKeys::score::exact_occ_split_between_res ],
110  ! basic::options::option[ basic::options::OptionKeys::score::exact_occ_self_res_no_occ ],
111  basic::options::option[basic::options::OptionKeys::score::exact_occ_radius_scaling]
112  );
113 
114 }
115 
118  ScoreTypes sts;
119  sts.push_back( occ_sol_exact );
120  return sts;
121 }
122 
123 
124 using namespace core;
125 using namespace core::scoring;
126 using namespace core::scoring::hbonds;
127 
128 core::Real const geosol_kT = { 0.593 };
130 
131 
132 // apply this weight to everything, so that scale will match LK
134 core::Real const SKIP_HBONDER_CUT = { -0.1 };
135 
136 GridInfo* GridInfo::instance_( 0 );
137 WaterWeightGridSet* WaterWeightGridSet::instance_( 0 );
138 
139 //singleton class
141 {
142  if ( instance_ == 0 )
143  {
144  instance_ = new GridInfo();
145  }
146  return instance_;
147 }
148 
149 
150 // private constructor
152 
153  // Setup dimensions for water grids - use the same dimensions for all grids
154  core::Real const water_grid_width = 10.;
155  core::Real const water_grid_depth = 8.;
156  // For speed use only 52 thousand points per grid - gives identical results...
157  xnum_points_ = 41;
158  ynum_points_ = 41;
159  znum_points_ = 31;
160  // Note: below gives 51 million points per grid
161  // xnum_points_ = 401;
162  // ynum_points_ = 401;
163  // znum_points_ = 321;
164 
165  xstep_ = water_grid_width / ( xnum_points_ - 1 );
166  ystep_ = water_grid_width / ( ynum_points_ - 1 );
167  zstep_ = water_grid_depth / ( znum_points_ - 1 );
168  // Note: the point at the origin will NOT be considered in calculations - the grid starts AFTER the origin!!
169  xorigin_ = -xstep_ * ( xnum_points_ + 1) / 2.;
170  yorigin_ = -ystep_ * ( ynum_points_ + 1) / 2.;
171  zorigin_ = 0.;
172 
173 }
174 
175 
176 //singleton class
178 {
179  if ( instance_ == 0 )
180  {
181  instance_ = new WaterWeightGridSet();
182  }
183  return instance_;
184 }
185 
186 // private constructor
188  hbondoptions_( new HBondOptions ),
189  hb_database_(HBondDatabase::get_database())
190 {
191  using namespace hbonds;
192  hbondoptions_->use_sp2_chi_penalty(false); // override command line settings
193 
194  // We need water grids for each donor and acceptor type
195  // We could read them in, but let's just compute them from scratch instead
196  // We'll store them as a map keyed on hbonds::HBEvalType, with each value a 3D vector of the weights
197 
198  TR << "computing and storing water weight grids for acceptor types." << std::endl;
199  for(Size i = 1; i <= hbacc_MAX; i++){
201  sum_all_water_weights_[hbe.eval_type()] = fill_water_grid( all_water_weights_[hbe.eval_type()], hbe, *GridInfo::get_instance(), true /*water is donor*/);
202  }
203 
204  TR << "computing and storing water weight grids for donor types." << std::endl;
205  for(Size i = 1; i <= hbdon_MAX; i++){
207  sum_all_water_weights_[hbe.eval_type()] = fill_water_grid( all_water_weights_[hbe.eval_type()], hbe, *GridInfo::get_instance(), false /*water is acceptor*/);
208  }
209 }
210 
211 
212 // Fill in the water grid
214  std::vector < std::vector < std::vector <core::Real> > > & water_weights,
215  hbonds::HBEvalTuple const & hbond_eval_type,
216  GridInfo const & grid_info, bool const water_is_donor)
217 {
218 
219  static Vector const base_to_outer(0,0,1);
220  core::Real const entropy_scaling = 1.0;
221  core::Real const water_O_H_distance = 0.958;
222 
223  // Setup grid, initialize to zero
224  water_weights.clear();
225  water_weights.resize(grid_info.xnum_points());
226  for (core::Size tx=0;tx<grid_info.xnum_points();tx++){
227  water_weights[tx].resize(grid_info.ynum_points());
228  for (core::Size ty=0;ty<grid_info.ynum_points();ty++){
229  water_weights[tx][ty].resize(grid_info.znum_points(), 0.);
230  }
231  }
232 
233  // Fill in the water weight grid
234  core::Real sum_grid_water_weight = 0.;
235  core::Vector water_position(grid_info.xorigin(),grid_info.yorigin(),grid_info.zorigin());
236 
237  for (core::Size tx=0;tx<grid_info.xnum_points();tx++){
238  water_position.x() += grid_info.xstep();
239  water_position.y() = grid_info.yorigin();
240  for (core::Size ty=0;ty<grid_info.ynum_points();ty++){
241  water_position.y() += grid_info.ystep();
242  water_position.z() = grid_info.zorigin();
243  for (core::Size tz=0;tz<grid_info.znum_points();tz++){
244  water_position.z() += grid_info.zstep();
245 
246  // Compute the current geometry
247  core::Real AHdis, xD, xH;
248  if ( water_is_donor ) {
249 
250  // water is the donor, give it perfect geometry
251  xD = 0.9999;
252 
253  // compute the distance to the accepting water proton
254  // subtract the water's OH distance to get the AHdis,
255  // since the distance computed was from the acceptor to the water oxygen
256  // note: water proton lies on the line between the acceptor and the water oxygen
257  AHdis = water_position.length();
258  AHdis -= water_O_H_distance; // water O-H distance
259 
260  // find cosine of the base-acceptor-water_proton angle (xH)
261  // note: this is the same as the base-acceptor-water_oxygen angle
262  // note: careful to normalize-by-copy, since water_position is reused around the loop
263  xH = dot( base_to_outer, water_position.normalized() );
264 
265  } else {
266 
267  // water is the acceptor, give it perfect geometry
268  xH = 1./3.; // perfect geometry is cos( 180 - 109.5 degrees), which is 1/3
269 
270  // compute the distance to the accepting water
271  AHdis = water_position.length();
272 
273  // find the cosine of the base-proton-water angle (xD)
274  // note: careful to normalize-by-copy, since water_position is reused around the loop
275  xD = dot( base_to_outer, water_position.normalized() );
276 
277  }
278 
279  if ( xH < MIN_xH ) continue;
280  if ( xH > MAX_xH ) continue;
281  if ( xD < MIN_xD ) continue;
282  if ( xD > MAX_xD ) continue;
283  if ( AHdis < MIN_R ) continue;
284  if ( AHdis > MAX_R ) continue;
285 
286  // Get the Hbond energy
287  core::Real curr_water_hbond;
288  core::Real dummy_chi( 0.0 );
289  assert( ! hbondoptions_->use_sp2_chi_penalty() ); // APL avoid the new sp2 chi term.
290  hbond_compute_energy(*hb_database_, *hbondoptions_, hbond_eval_type,
291  AHdis, xD, xH, dummy_chi, curr_water_hbond );
292 
293  // Save the Hbond energy
294  curr_water_hbond *= entropy_scaling;
295  if ( curr_water_hbond < 0 ) {
296  core::Real curr_water_weight = exp( - curr_water_hbond / geosol_kT );
297  water_weights[tx][ty][tz] = curr_water_weight;
298  sum_grid_water_weight += curr_water_weight;
299  }
300  }
301  }
302  }
303 
304  return sum_grid_water_weight;
305 }
306 
307 
308 std::vector < std::vector < std::vector <core::Real> > > const &
310  // Check that we have weights for this Hbond type
311  all_water_weights_iterator curr_water_weights_iter = all_water_weights_.find( hbond_eval_type );
312  if ( curr_water_weights_iter == all_water_weights_.end( ) ) {
313  TR << "Could not look up map element" << std::endl;
314  TR << "get_water_weight_grid hbond_eval_type " << hbond_eval_type << std::endl;
315  assert(false);
316  exit(1);
317  }
318  return curr_water_weights_iter->second;
319 }
320 
323 {
324  // Check that we have weights for this Hbond type
325  sum_water_weights_iterator curr_sum_water_weights_iter = sum_all_water_weights_.find( hbond_eval_type );
326  if ( curr_sum_water_weights_iter == sum_all_water_weights_.end( ) ) {
327  TR << "Could not look up map element" << std::endl;
328  TR << "get_sum_water_weight_grid hbond_eval_type " << hbond_eval_type << std::endl;
329  assert(false);
330  exit(1);
331  }
332  return curr_sum_water_weights_iter->second;
333 }
334 
335 
337 
339  bool const exact_occ_skip_Hbonders,
340  bool const exact_occ_include_Hbond_contribution,
341  bool const exact_occ_pairwise,
342  bool const exact_occ_pairwise_by_res,
343  bool const exact_occ_split_between_res,
344  bool const exact_occ_self_res_occ,
345  core::Real const occ_radius_scaling,
346  bool const verbose
347 ) :
349  exact_occ_skip_Hbonders_( exact_occ_skip_Hbonders ),
350  exact_occ_include_Hbond_contribution_( exact_occ_include_Hbond_contribution ),
351  exact_occ_pairwise_( exact_occ_pairwise ),
352  exact_occ_pairwise_by_res_( exact_occ_pairwise_by_res ),
353  exact_occ_split_between_res_( exact_occ_split_between_res ),
354  exact_occ_self_res_occ_( exact_occ_self_res_occ ),
355  occ_radius_scaling_( occ_radius_scaling ),
357  hb_database_(HBondDatabase::get_database()),
358  verbose_( verbose )
359 {
360  hbondoptions_->use_sp2_chi_penalty( false ); // apl preserve old behavior
361 
362  if ( verbose_ ) TR <<"ExactOccludedHbondSolEnergy constructor" << std::endl;
364  TR << "Error - cannot split occ energy between residues unless pairwise calculations are used!" << std::endl;
365  exit(1);
366  }
367 
368  // Keep a copy of the AtomTypeSet (to lookup atomic radii)
370 
371 
372 
373  // Allocate memory for grid of occluded sites
374  occluded_sites_.clear();
375  occluded_sites_.resize(GridInfo::get_instance()->xnum_points());
376  for (core::Size tx=0;tx<GridInfo::get_instance()->xnum_points();tx++){
377  occluded_sites_[tx].resize(GridInfo::get_instance()->ynum_points());
378  for (core::Size ty=0;ty<GridInfo::get_instance()->ynum_points();ty++){
379  occluded_sites_[tx][ty].resize(GridInfo::get_instance()->znum_points());
380  }
381  }
382 
383 }
384 
386  parent( src ),
387  exact_occ_skip_Hbonders_( src.exact_occ_skip_Hbonders_ ),
388  exact_occ_include_Hbond_contribution_( src.exact_occ_include_Hbond_contribution_ ),
389  exact_occ_pairwise_( src.exact_occ_pairwise_ ),
390  exact_occ_pairwise_by_res_( src.exact_occ_pairwise_by_res_ ),
391  exact_occ_split_between_res_( src.exact_occ_split_between_res_ ),
392  exact_occ_self_res_occ_( src.exact_occ_self_res_occ_ ),
393  occ_radius_scaling_( src.occ_radius_scaling_ ),
394  hb_database_(HBondDatabase::get_database()),
395  verbose_( src.verbose_ ),
396  atom_type_set_ptr_( src.atom_type_set_ptr_ )
397 {
398  if ( verbose_ ) TR <<"ExactOccludedHbondSolEnergy constructor" << std::endl;
400  TR << "Error - cannot split occ energy between residues unless pairwise calculations are used!" << std::endl;
401  exit(1);
402  }
403 
404  // Allocate memory for grid of occluded sites
405  occluded_sites_.clear();
406  occluded_sites_.resize(GridInfo::get_instance()->xnum_points());
407  for (core::Size tx=0;tx<GridInfo::get_instance()->xnum_points();tx++){
408  occluded_sites_[tx].resize(GridInfo::get_instance()->ynum_points());
409  for (core::Size ty=0;ty<GridInfo::get_instance()->ynum_points();ty++){
410  occluded_sites_[tx][ty].resize(GridInfo::get_instance()->znum_points());
411  }
412  }
413 
414 }
415 
418 {
419  return new ExactOccludedHbondSolEnergy( *this );
420 }
421 
422 void
424 {
426 }
427 
428 void
430  pose::Pose & pose,
431  utility::vector1< bool > const &,
433 ) const
434 {
436 }
437 
438 void
440 {
441  TR << "Error - cannot compute derivatives for ExactOccludedHbondSolEnergy (occ_sol_exact)" << std::endl;
442  assert(false);
443  exit(1);
444 }
445 
446 void
448 {
449  TR << "Error - cannot compute derivatives for ExactOccludedHbondSolEnergy (occ_sol_exact)" << std::endl;
450  assert(false);
451  exit(1);
452 }
453 
455 
457  conformation::Residue const & polar_rsd,
458  pose::Pose const & pose,
459  EnergyMap & emap
460 ) const {
461 
462  core::Size polar_resnum = (core::Size) polar_rsd.seqpos();
463  core::Real residue_geosol(0.);
464 
465  // loop over donors in polar_rsd
466  for ( chemical::AtomIndices::const_iterator
467  hnum = polar_rsd.Hpos_polar().begin(),
468  hnume = polar_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
469  Size const polar_atom( *hnum );
470  Size const base_atom( polar_rsd.atom_base( polar_atom ) );
471  HBEvalTuple const curr_hbond_eval_type( get_hb_don_chem_type( base_atom, polar_rsd ), hbacc_H2O, seq_sep_other );
472 
473  // Figure out max LK energy
474  std::string const base_atom_name = polar_rsd.atom_name( base_atom );
475  core::Real max_possible_LK = (*atom_type_set_ptr_)[polar_rsd.atom_type_index(base_atom)].lj_radius();
476  if ( ( base_atom_name == " N " ) && polar_rsd.is_lower_terminus() ) max_possible_LK /= 3; // charged N-terminus
477  if ( base_atom_name == " NZ " ) max_possible_LK /= 3; // Lys
478  if ( base_atom_name == " ND2" ) max_possible_LK /= 2; // Asn
479  if ( base_atom_name == " NE2" ) max_possible_LK /= 2; // Gln
480  if ( base_atom_name == " NH1" ) max_possible_LK /= 2; // Arg
481  if ( base_atom_name == " NH2" ) max_possible_LK /= 2; // Arg
482  // Note: inner nitrogen of Arg (NE) is extra strong, since it's the same atom type as the other two but doesn't get
483  // cut in half because there's only one proton...
484  // TR << "jk max LK for donor with base " << base_atom_name << " is " << max_possible_LK << std::endl;
485 
486  // jk INSTEAD OF USING LK dG FREE, SET THEM ALL TO -5.0. THIS IS ALMOST TRUE ANYWAY, AND THE ONES THAT AREN'T SHOULD PROBABLY BE...
487  max_possible_LK = -5.;
488 
489  // Compute Ebulk (using the LK energy)
490  core::Real const Emax_weight = exp( max_possible_LK / geosol_kT );
491  core::Real const sum_water_weights = WaterWeightGridSet::get_instance()->get_sum_water_weight_grid( curr_hbond_eval_type.eval_type());
492  core::Real const Ebulk_weight = ( sum_water_weights * Emax_weight ) / ( 1. - Emax_weight);
493 
494  // This grid constant is the denominator in computing solvation energies,
495  // it depends on the grid dimensions, and sets the max possible solvation energy (in this case to match LK)
496  core::Real const grid_constant = sum_water_weights + Ebulk_weight;
497 
498  core::Real polar_group_energy = 0.;
500  polar_group_energy = compute_polar_group_sol_energy(pose, polar_rsd, polar_atom, *GridInfo::get_instance(),
501  grid_constant, WaterWeightGridSet::get_instance()->get_water_weight_grid( curr_hbond_eval_type.eval_type() ) );
502  } else {
503  // loop over all atoms of neighboring residues, INCLUDING SELF
505  utility::vector1 <core::Size> neighborlist;
506  neighborlist.push_back( polar_resnum);
508  neighbor_iter = graph.get_node( polar_resnum )->const_edge_list_begin(),
509  neighbor_iter_end = graph.get_node( polar_resnum )->const_edge_list_end();
510  neighbor_iter != neighbor_iter_end; ++neighbor_iter ) {
511  neighborlist.push_back( (*neighbor_iter)->get_other_ind( polar_resnum ) );
512  }
513  for ( Size occ_inx = 1; occ_inx <= neighborlist.size(); ++occ_inx ) {
514  core::Size const occ_resnum( neighborlist[occ_inx] );
515  conformation::Residue const occ_rsd = pose.residue(occ_resnum);
517  polar_group_energy += compute_polar_group_sol_energy(pose, polar_rsd, polar_atom, *GridInfo::get_instance(),
518  grid_constant, WaterWeightGridSet::get_instance()->get_water_weight_grid( curr_hbond_eval_type.eval_type() ),
519  true, occ_resnum );
520  } else {
521  for ( Size occ_atomno = 1; occ_atomno <= occ_rsd.natoms(); ++occ_atomno ) {
522  polar_group_energy += compute_polar_group_sol_energy(pose, polar_rsd, polar_atom, *GridInfo::get_instance(),
523  grid_constant, WaterWeightGridSet::get_instance()->get_water_weight_grid( curr_hbond_eval_type.eval_type() ),
524  true, occ_resnum, true, occ_atomno );
525  }
526  }
527  }
528  }
529  residue_geosol += polar_group_energy;
530 
531  //solvation energy for donor
532  // std::cout << "jk EXACT Donor " << base_atom_name << " " << pose.residue(polar_resnum).aa() << " " << polar_resnum << " " << polar_group_energy << std::endl;
533 
534  }
535 
536  // loop over acceptors in polar_rsd
537  for ( chemical::AtomIndices::const_iterator
538  anum = polar_rsd.accpt_pos().begin(),
539  anume = polar_rsd.accpt_pos().end(); anum != anume; ++anum ) {
540  Size const polar_atom( *anum );
541  Size const base_atom ( polar_rsd.atom_base( polar_atom ) );
542  hbonds::HBEvalTuple const curr_hbond_eval_type( hbdon_H2O, get_hb_acc_chem_type( polar_atom, polar_rsd ), seq_sep_other);
543 
544  // Figure out max LK energy
545  std::string const base_atom_name = polar_rsd.atom_name( base_atom );
546  core::Real max_possible_LK = (*atom_type_set_ptr_)[ polar_rsd.atom_type_index( polar_atom ) ].lk_dgfree();
547  // TR << "jk max LK for acceptor " << polar_rsd.atom_name(polar_atom) << " is " << max_possible_LK << std::endl;
548 
549  // jk INSTEAD OF USING LK dG FREE, SET THEM ALL TO -5.0. THIS IS ALMOST TRUE ANYWAY, AND THE ONES THAT AREN'T SHOULD PROBABLY BE...
550  max_possible_LK = -5.;
551 
552  // Compute Ebulk (using the LK energy)
553  core::Real const Emax_weight = exp( max_possible_LK / geosol_kT );
554  core::Real const sum_water_weights = WaterWeightGridSet::get_instance()->get_sum_water_weight_grid( curr_hbond_eval_type.eval_type() );
555  core::Real const Ebulk_weight = ( sum_water_weights * Emax_weight ) / ( 1. - Emax_weight);
556  // This grid constant is the denominator in computing solvation energies,
557  // it depends on the grid dimensions, and sets the max possible solvation energy (in this case to match LK)
558  core::Real const grid_constant = sum_water_weights + Ebulk_weight;
559 
560  core::Real polar_group_energy = 0.;
562  polar_group_energy = compute_polar_group_sol_energy(pose, polar_rsd, polar_atom, *GridInfo::get_instance(),
563  grid_constant, WaterWeightGridSet::get_instance()->get_water_weight_grid( curr_hbond_eval_type.eval_type() ) );
564  } else {
565  // loop over all atoms of neighboring residues, INCLUDING SELF
567  utility::vector1 <core::Size> neighborlist;
568  neighborlist.push_back( polar_resnum);
570  neighbor_iter = graph.get_node( polar_resnum )->const_edge_list_begin(),
571  neighbor_iter_end = graph.get_node( polar_resnum )->const_edge_list_end();
572  neighbor_iter != neighbor_iter_end; ++neighbor_iter ) {
573  neighborlist.push_back( (*neighbor_iter)->get_other_ind( polar_resnum ) );
574  }
575  for ( Size occ_inx = 1; occ_inx <= neighborlist.size(); ++occ_inx ) {
576  core::Size const occ_resnum( neighborlist[occ_inx] );
577  conformation::Residue const occ_rsd = pose.residue(occ_resnum);
579  polar_group_energy += compute_polar_group_sol_energy(pose, polar_rsd, polar_atom, *GridInfo::get_instance(),
580  grid_constant, WaterWeightGridSet::get_instance()->get_water_weight_grid( curr_hbond_eval_type.eval_type() ),
581  true, occ_resnum );
582  } else {
583  for ( Size occ_atomno = 1; occ_atomno <= occ_rsd.natoms(); ++occ_atomno ) {
584  polar_group_energy += compute_polar_group_sol_energy(pose, polar_rsd, polar_atom, *GridInfo::get_instance(),
585  grid_constant, WaterWeightGridSet::get_instance()->get_water_weight_grid( curr_hbond_eval_type.eval_type() ),
586  true, occ_resnum, true, occ_atomno );
587  }
588  }
589  }
590  }
591  residue_geosol += polar_group_energy;
592 
593  //solvation energy for acceptor
594  // std::cout << "jk EXACT Acceptor " << base_atom_name << " " << pose.residue(polar_resnum).aa() << " " << polar_resnum << " " << polar_group_energy << std::endl;
595 
596  }
597 
599  TR << "PAIRWISE OUTPUT FORMAT IS NOT YET SUPPORTED" << std::endl;
600  // Here we need to add contributions from this residue occluding all neighboring polar groups then divide everything by two
601  // note: this will make the code run twice as slow as it otherwise would, but that's okay because it's just for parameterization / analysis
602  exit(1);
603  }
604 
605  emap[ occ_sol_exact ] += LK_MATCHING_WEIGHT_EXACT * residue_geosol;
606 
607 }
608 
609 
611  pose::Pose const & pose,
612  conformation::Residue const & polar_rsd,
613  Size const polar_atom,
614  bool const restrict_to_single_occluding_residue, // = false
615  Size const single_occluding_resinx, // = 0
616  bool const restrict_to_single_occluding_atom, // = false
617  Size const single_occluding_atominx // = 0
618 ) const {
619  Size const base_atom( polar_rsd.atom_base( polar_atom ) );
620 
621  HBEvalTuple curr_hbond_eval_type;
622  if ( polar_rsd.atom_type( base_atom ).is_donor()){
623  curr_hbond_eval_type = HBEvalTuple(get_hb_don_chem_type( base_atom, polar_rsd ), hbacc_H2O, seq_sep_other);
624  } else if( polar_rsd.atom_type( polar_atom).is_acceptor()){
625  curr_hbond_eval_type = HBEvalTuple( hbdon_H2O, get_hb_acc_chem_type( polar_atom, polar_rsd ), seq_sep_other);
626  } else {
627  assert( false ); // Not a donor or an acceptor, don't know what to do.
628  }
629 
630  Real const grid_constant = compute_grid_constant( curr_hbond_eval_type );
632  pose, polar_rsd, polar_atom, *GridInfo::get_instance(),
633  grid_constant, WaterWeightGridSet::get_instance()->get_water_weight_grid( curr_hbond_eval_type.eval_type() ),
634  restrict_to_single_occluding_residue,
635  single_occluding_resinx,
636  restrict_to_single_occluding_atom,
637  single_occluding_atominx);
638 }
639 
640 
642  pose::Pose const & pose,
643  conformation::Residue const & polar_rsd,
644  core::Size const polar_atomno,
645  GridInfo const & grid_info,
646  core::Real const & grid_constant,
647  std::vector < std::vector < std::vector <core::Real> > > const & water_weights,
648  bool const restrict_to_single_occluding_residue, // = false
649  core::Size const single_occluding_resinx, // = 0
650  bool const restrict_to_single_occluding_atom, // = false
651  core::Size const single_occluding_atominx // = 0
652 ) const {
653 
654  // note: the "restrict_to_single_occluding_residue / atom" options are so that pairwise additivity can be enforced (for parameterization / analysis)
655  core::Size const polar_resnum = (core::Size) polar_rsd.seqpos();
656 
657  // jumpout immediately if we're not including self but the single requested residue is self
658  if ( restrict_to_single_occluding_residue && ! exact_occ_self_res_occ_ && ( polar_resnum == single_occluding_resinx ) ) {
659  return 0;
660  }
661 
662  // note: the "restrict_to_single_occluding_residue / atom" options are so that pairwise additivity can be enforced (for parameterization / analysis)
663 
664  Size const base_atom( polar_rsd.atom_base( polar_atomno ) );
665  bool polar_group_is_acceptor = polar_rsd.atom_type( polar_atomno).is_acceptor();
666  bool polar_group_is_donor = polar_rsd.atom_type( base_atom ).is_donor();
667 
668  core::Real polar_group_hb_energy(0.);
669 
670  bool const hydrogens_can_occlude = false;
671  core::Real const water_radius = 1.4;
672 
673  // Reset grid of occluded sites, by setting everything to false (for "not occluded")
674  for (core::Size tx=0;tx<grid_info.xnum_points();tx++){
675  for (core::Size ty=0;ty<grid_info.ynum_points();ty++){
676  for (core::Size tz=0;tz<grid_info.znum_points();tz++){
677  occluded_sites_[tx][ty][tz] = false;
678  }
679  }
680  }
681 
682  // Find the transformation which puts the donor/acceptor of interest onto the existing grid
683  // The plan is to apply this transformation to bring each occluding atom onto the existing grid (translation then matrix multiplication)
684  core::Size const base_atomno( polar_rsd.atom_base( polar_atomno ) );
685  core::Vector const & orig_polar_atom_xyz( polar_rsd.atom( polar_atomno ).xyz() );
686  core::Vector const & orig_base_atom_xyz( polar_rsd.atom( base_atomno ).xyz() );
687  core::Vector const translation_vector = -1.0 * orig_polar_atom_xyz;
688  core::Vector const translated_base_atom = orig_base_atom_xyz + translation_vector;
689 
690  // We want to translate positions of occluding atoms _from_ a cartesian basis set into one using the reference frame of the polar group
691  core::Vector const cartesian_x(1,0,0);
692  core::Vector const cartesian_y(0,1,0);
693  core::Vector const cartesian_z(0,0,1);
694 
695  // There's not a unique solution for this, so we'll arbitrarily pick a second basis vector, requiring that the dot product with desired_z is zero
696  core::Vector desired_z = -1. * translated_base_atom.normalized();
697 
698  // Treat the case where polar_atom.z == base_atom.z ; this leads to desired_z.z == 0
699  core::Real arbitrary_x, arbitrary_y, arbitrary_z;
700  // jk note: we get numerical problems if z-coor is about zero (we divide by it below) - if so then use y to divide by
701  if ( std::abs( desired_z.z() ) > 0.01 ) {
702  arbitrary_x = 1;
703  arbitrary_y = 1;
704  arbitrary_z = -1. * ((arbitrary_x * desired_z.x()) + (arbitrary_y * desired_z.y())) / desired_z.z();
705  } else {
706  if ( std::abs( desired_z.y() ) > 0.01 ) {
707  arbitrary_x = 1;
708  arbitrary_z = 1;
709  arbitrary_y = -1. * ((arbitrary_x * desired_z.x()) + (arbitrary_z * desired_z.z())) / desired_z.y();
710  } else {
711  // jk note: we get numerical problems if z-coor AND y-coor are about zero (it does happen!) - if so then use x to divide by
712  arbitrary_y = 1;
713  arbitrary_z = 1;
714  arbitrary_x = -1. * ((arbitrary_y * desired_z.y()) + (arbitrary_z * desired_z.z())) / desired_z.x();
715  }
716  }
717  core::Vector desired_x(arbitrary_x,arbitrary_y,arbitrary_z);
718  desired_x.normalize();
719  core::Vector desired_y = cross_product( desired_x, desired_z );
720 
721  // The transformation matrix to do this is i.i' i.j', etc. where i,j,k are the unit vectors of the starting system
722  // and i',j',k' are the unit vectors of the target system
723  // for reference see http://kwon3d.com/theory/transform/transform.html
724  numeric::xyzMatrix< Length > transformation_matrix;
725  transformation_matrix.xx( desired_x.dot(cartesian_x) );
726  transformation_matrix.xy( desired_x.dot(cartesian_y) );
727  transformation_matrix.xz( desired_x.dot(cartesian_z) );
728  transformation_matrix.yx( desired_y.dot(cartesian_x) );
729  transformation_matrix.yy( desired_y.dot(cartesian_y) );
730  transformation_matrix.yz( desired_y.dot(cartesian_z) );
731  transformation_matrix.zx( desired_z.dot(cartesian_x) );
732  transformation_matrix.zy( desired_z.dot(cartesian_y) );
733  transformation_matrix.zz( desired_z.dot(cartesian_z) );
734 
735  // Double-check transformation matrix
736  core::Vector new_base_atom_location = transformation_matrix * translated_base_atom;
737  assert( std::abs(new_base_atom_location.normalized().x()) < 0.001 );
738  assert( std::abs(new_base_atom_location.normalized().y()) < 0.001 );
739  assert( std::abs(new_base_atom_location.normalized().z() + 1.) < 0.001 );
740 
741  utility::vector1 <core::Size> neighborlist;
742  if ( restrict_to_single_occluding_residue ) {
743  // consider only a single occluding residue (for pairwise additivity)
744  assert ( single_occluding_resinx > 0 );
745  neighborlist.push_back( single_occluding_resinx );
746  } else {
747  // loop over all atoms of neighboring residues, INCLUDING SELF
749  neighborlist.push_back( polar_resnum);
751  neighbor_iter = graph.get_node( polar_resnum )->const_edge_list_begin(),
752  neighbor_iter_end = graph.get_node( polar_resnum )->const_edge_list_end();
753  neighbor_iter != neighbor_iter_end; ++neighbor_iter ) {
754  neighborlist.push_back( (*neighbor_iter)->get_other_ind( polar_resnum ) );
755  }
756  }
757 
758  for ( Size occ_inx = 1; occ_inx <= neighborlist.size(); ++occ_inx ) {
759  core::Size const occ_resnum( neighborlist[occ_inx] );
760  if ( ! exact_occ_self_res_occ_ && ( polar_resnum == occ_resnum ) ) {
761  continue;
762  }
763  conformation::Residue const occ_rsd = pose.residue(occ_resnum);
764 
765  // loop over all occluding atoms in this residue
766  Size atom_startinx = 1;
767  Size atom_lastinx = occ_rsd.natoms();
768  if ( restrict_to_single_occluding_atom ) {
769  // consider only a single occluding atom (for pairwise additivity)
770  assert ( single_occluding_atominx > 0 );
771  atom_startinx = single_occluding_atominx;
772  atom_lastinx = single_occluding_atominx;
773  }
774 
775  // TR << "computing occlusion of polar residue " << polar_resnum << " by residue " << occ_resnum << std::endl;
776 
777  for ( Size occ_atomno = atom_startinx; occ_atomno <= atom_lastinx; ++occ_atomno ) {
778 
779  bool const occ_atom_is_hydrogen = occ_rsd.atom_is_hydrogen( occ_atomno );
780  if ( occ_atom_is_hydrogen && ! hydrogens_can_occlude ) continue;
781 
782  // can be occluded by atoms directly bonded to this group, but not by self
783  if ( polar_resnum == occ_resnum ) {
784  if ( polar_atomno == occ_atomno ) continue;
785  if ( base_atomno == occ_atomno ) continue;
786  }
787 
788  core::Real occ_radius = (*atom_type_set_ptr_)[occ_rsd.atom_type_index( occ_atomno )].lj_radius();
789  // catch proline NV here (and other virtual atoms, etc.)
790  if ( occ_radius < 0.1 ) continue;
791  occ_radius *= occ_radius_scaling_;
792  core::Real const sq_dist_cut = ( occ_radius + water_radius ) * ( occ_radius + water_radius );
793 
794  // if we're not counting contributions from Hbonded atoms, and atom is Hbonded to our polar group, jump out here
795  // note: this affects secondary structure a lot!
796  // also note: this will not be smoothly differentiable, and will cause problems if ported directly to the fitted function.
797  // for the fitted function, we need a better way to do this, eg. downweight the solvation penalty based on how good the Hbond is
798 
800  bool occ_atom_is_Hbonded(false);
801 
802  // figure out if the occluding atom is a donor base
803  for ( chemical::AtomIndices::const_iterator hnum = occ_rsd.Hpos_polar().begin(), hnume = occ_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
804  Size const don_h_atom( *hnum );
805  Size const base_atom ( occ_rsd.atom_base( don_h_atom ) );
806  if ( occ_atomno == base_atom ) {
807  // make sure the polar atom is an acceptor
808  for ( chemical::AtomIndices::const_iterator anum = polar_rsd.accpt_pos().begin(), anume = polar_rsd.accpt_pos().end(); anum != anume; ++anum ) {
809  Size const acc_atom( *anum );
810  if ( polar_atomno == acc_atom ) {
811  // If so, check if we have an Hbond to the polar group of interest
812  HBDonChemType don_chem_type = get_hb_don_chem_type( occ_atomno, occ_rsd );
813  HBAccChemType acc_chem_type = get_hb_acc_chem_type( polar_atomno, polar_rsd );
814  // Note: this should really test if things are on different chains (comment from Hbond code)
815  HBSeqSep seq_sep(get_seq_sep(don_chem_type, acc_chem_type, polar_resnum - occ_resnum));
816  HBEvalTuple const hbe_type( don_chem_type, acc_chem_type, seq_sep);
817  Real hb_ener(0.);
819  occ_rsd.atom( occ_atomno ).xyz(), occ_rsd.atom( don_h_atom ).xyz(),
820  polar_rsd.atom( polar_atomno ).xyz(), polar_rsd.atom( polar_rsd.atom_base( polar_atomno ) ).xyz(),
821  polar_rsd.atom( polar_rsd.abase2( polar_atomno ) ).xyz(), hb_ener);
822 
823  if ( hb_ener < 0. ) {
824  switch ( get_hbond_weight_type(hbe_type.eval_type()) ) {
825  case hbw_SC:
826  hb_ener *= 1.1;
827  break;
828  case hbw_LR_BB:
829  case hbw_SR_BB:
830  hb_ener *= 1.17;
831  break;
832  default:
833  break;
834  }
835  polar_group_hb_energy += hb_ener;
836  }
837  if ( hb_ener < SKIP_HBONDER_CUT ) {
838  occ_atom_is_Hbonded = true;
839  }
840  }
841  }
842  }
843  }
844  if ( occ_atom_is_Hbonded && ! exact_occ_include_Hbond_contribution_ ) continue;
845 
846  // figure out if the occluding atom is an acceptor
847  for ( chemical::AtomIndices::const_iterator anum = occ_rsd.accpt_pos().begin(), anume = occ_rsd.accpt_pos().end(); anum != anume; ++anum ) {
848  Size const acc_atom( *anum );
849  if ( occ_atomno == acc_atom ) {
850  // make sure the polar atom is a donor
851  for ( chemical::AtomIndices::const_iterator hnum = polar_rsd.Hpos_polar().begin(), hnume = polar_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
852  Size const don_h_atom( *hnum );
853  if ( polar_atomno == don_h_atom ) {
854  Size const base_atom ( polar_rsd.atom_base( don_h_atom ) );
855  // If so, check if we have an Hbond to the polar group of interest
856  HBDonChemType don_chem_type = get_hb_don_chem_type( base_atom, polar_rsd );
857  HBAccChemType acc_chem_type = get_hb_acc_chem_type( occ_atomno, occ_rsd );
858  // Note: this should really test if things are on different chains (comment from Hbond code)
859  HBSeqSep seq_sep(get_seq_sep(don_chem_type, acc_chem_type, occ_resnum - polar_resnum ));
860  HBEvalTuple const hbe_type( don_chem_type, acc_chem_type, seq_sep );
861  Real hb_ener(0.);
862  hb_energy_deriv( *hb_database_, *hbondoptions_, hbe_type, polar_rsd.atom( base_atom ).xyz(), polar_rsd.atom( polar_atomno ).xyz(),
863  occ_rsd.atom( occ_atomno ).xyz(), occ_rsd.atom( occ_rsd.atom_base( occ_atomno ) ).xyz(),
864  occ_rsd.atom( occ_rsd.abase2( occ_atomno ) ).xyz(), hb_ener);
865 
866  if ( hb_ener < 0. ) {
867  switch ( get_hbond_weight_type(hbe_type.eval_type()) ) {
868  case hbw_SC:
869  hb_ener *= 1.1;
870  break;
871  case hbw_LR_BB:
872  case hbw_SR_BB:
873  hb_ener *= 1.17;
874  break;
875  default:
876  break;
877  }
878  polar_group_hb_energy += hb_ener;
879  }
880  if ( hb_ener < SKIP_HBONDER_CUT ) {
881  occ_atom_is_Hbonded = true;
882  }
883  }
884  }
885  }
886  }
887  if ( occ_atom_is_Hbonded && ! exact_occ_include_Hbond_contribution_ ) continue;
888 
889  } // done finding Hbonds for skip_Hbonders and/or including Hbond contribution
890 
891  // Apply the transformation to put this atom onto the current grid
892  core::Vector const & orig_occ_atom_xyz( occ_rsd.atom( occ_atomno ).xyz() );
893  core::Vector const translated_occ_atom_xyz = orig_occ_atom_xyz + translation_vector;
894  core::Vector const transformed_occ_atom_xyz = transformation_matrix * ( orig_occ_atom_xyz + translation_vector );
895 
896  // Double-check transformations
897  assert( std::abs(orig_polar_atom_xyz.distance( orig_occ_atom_xyz ) - transformed_occ_atom_xyz.magnitude()) < 0.001 );
898  assert( std::abs(orig_base_atom_xyz.distance( orig_occ_atom_xyz ) - new_base_atom_location.distance( transformed_occ_atom_xyz )) < 0.001 );
899 
900  // Loop over all water positions, mark those which are occluded by this atom
901  core::Vector water_position(grid_info.xorigin(),grid_info.yorigin(),grid_info.zorigin());
902  for (core::Size wx=0;wx<grid_info.xnum_points();wx++){
903  water_position.x() += grid_info.xstep();
904  core::Real sq_xdist = ( water_position.x() - transformed_occ_atom_xyz.x() ) * ( water_position.x() - transformed_occ_atom_xyz.x() );
905  if ( sq_xdist > sq_dist_cut ) continue;
906  water_position.y() = grid_info.yorigin();
907  for (core::Size wy=0;wy<grid_info.ynum_points();wy++){
908  water_position.y() += grid_info.ystep();
909  core::Real sq_ydist = ( water_position.y() - transformed_occ_atom_xyz.y() ) * ( water_position.y() - transformed_occ_atom_xyz.y() );
910  if ( sq_ydist > sq_dist_cut ) continue;
911  water_position.z() = grid_info.zorigin();
912  for (core::Size wz=0;wz<grid_info.znum_points();wz++){
913  water_position.z() += grid_info.zstep();
914  core::Real sq_zdist = ( water_position.z() - transformed_occ_atom_xyz.z() ) * ( water_position.z() - transformed_occ_atom_xyz.z() );
915  if ( sq_zdist > sq_dist_cut ) continue;
916  core::Real sq_curr_dist = sq_xdist + sq_ydist + sq_zdist;
917  if ( sq_curr_dist < sq_dist_cut ) {
918  // this atom occludes this water site
919  occluded_sites_[wx][wy][wz] = true;
920  }
921  }
922  }
923  }
924 
925  }
926  }
927 
928  // Compute and store the solvation energy for the grid occluded by all nearby atoms
929  // Compute the numerator (the sum of occluded weights)
930  core::Real sum_occluded_weights(0.);
931  for (core::Size tx=0;tx<grid_info.xnum_points();tx++){
932  for (core::Size ty=0;ty<grid_info.ynum_points();ty++){
933  for (core::Size tz=0;tz<grid_info.znum_points();tz++){
934  if ( occluded_sites_[tx][ty][tz] ) {
935  core::Real const curr_water_weight = water_weights[tx][ty][tz];
936  sum_occluded_weights += curr_water_weight;
937  }
938  }
939  }
940  }
941 
942  // Compute the energetic cost of occluding this polar group
943  core::Real geometric_solvation_energy = - geosol_kT * log( 1 - ( sum_occluded_weights / grid_constant ) );
944  core::Real desired_hb_weight = 0.;
945 
947 
948  if ( exact_occ_self_res_occ_ ) {
949 
950  if ( polar_group_is_acceptor ) {
951 
952  HBAccChemType acc_chem_type = get_hb_acc_chem_type( polar_atomno, polar_rsd );
953 
954  switch( acc_chem_type) {
955  case hbacc_PBA:
956  geometric_solvation_energy -= 0.775088;
957  desired_hb_weight = geometric_solvation_energy *0.72908;
958  break;
959  case hbacc_CXA:
960  geometric_solvation_energy -= 0.775088;
961  desired_hb_weight = geometric_solvation_energy *0.94358;
962  break;
963  case hbacc_CXL:
964  geometric_solvation_energy -=0.32359;
965  desired_hb_weight = geometric_solvation_energy *0.83315;
966  break;
967  case hbacc_IMD:
968  geometric_solvation_energy -= 1.07342;
969  desired_hb_weight = geometric_solvation_energy *0.64448;
970  break;
971  case hbacc_IME:
972  geometric_solvation_energy -= 1.67093;
973  desired_hb_weight = geometric_solvation_energy *1.0758;
974  break;
975  case hbacc_AHX:
976  geometric_solvation_energy -= 0.681323;
977  desired_hb_weight = geometric_solvation_energy *0.97637;
978  break;
979  case hbacc_HXL:
980  geometric_solvation_energy -= 0.752036;
981  desired_hb_weight = geometric_solvation_energy *1.2094;
982  break;
983  default:
984  std::cout << "Chemical acceptor type not found: " << acc_chem_type << std::endl;
985  exit(1);
986  break;
987  }
988  }
989  if (polar_group_is_donor ) {
990 
991  HBDonChemType don_chem_type = get_hb_don_chem_type( base_atom, polar_rsd );
992 
993  switch (don_chem_type ) {
994  case hbdon_PBA:
995  geometric_solvation_energy -= 1.56141;
996  desired_hb_weight = geometric_solvation_energy *0.59343;
997  break;
998  case hbdon_CXA:
999  geometric_solvation_energy -= 0.4999125;
1000  desired_hb_weight = geometric_solvation_energy*.8906;
1001  break;
1002  case hbdon_IMD:
1003  geometric_solvation_energy -=0.957797;
1004  desired_hb_weight = geometric_solvation_energy *0.90386;
1005  break;
1006  case hbdon_IME:
1007  geometric_solvation_energy -= 0.591156;
1008  desired_hb_weight = geometric_solvation_energy *0.9971;
1009  break;
1010  case hbdon_IND:
1011  geometric_solvation_energy -=0.854121;
1012  desired_hb_weight = geometric_solvation_energy *0.97701;
1013  break;
1014  case hbdon_AMO:
1015  geometric_solvation_energy -= 0.33501;
1016  desired_hb_weight = geometric_solvation_energy*1.5641;
1017  break;
1018  case hbdon_GDE:
1019  geometric_solvation_energy -= 0.981806;
1020  desired_hb_weight = geometric_solvation_energy *0.8612;
1021  break;
1022  case hbdon_GDH:
1023  geometric_solvation_energy -=0.538248;
1024  desired_hb_weight = geometric_solvation_energy *1.142;
1025  break;
1026  case hbdon_AHX:
1027  geometric_solvation_energy -= 0.681433;
1028  desired_hb_weight = geometric_solvation_energy *1.1076;
1029  break;
1030  case hbdon_HXL:
1031  geometric_solvation_energy -= 0.785331;
1032  desired_hb_weight = geometric_solvation_energy *1.1066;
1033  break;
1034  default:
1035  std::cout << "Chemical donor type not found: " << don_chem_type << std::endl;
1036  exit(1);
1037  break;
1038  }
1039  }
1040 
1041  } else {
1042 
1043  // constant shift (brings non-Hbonded groups to zero), will match Hbonded groups at about zero
1044  if ( geometric_solvation_energy > 0 ) {
1045  if ( polar_group_is_acceptor ) {
1046 
1047  HBAccChemType acc_chem_type = get_hb_acc_chem_type( polar_atomno, polar_rsd );
1048 
1049  switch( acc_chem_type) {
1050  case hbacc_PBA:
1051  geometric_solvation_energy -= 0.624376;
1052  desired_hb_weight = geometric_solvation_energy *0.72832;
1053  break;
1054  case hbacc_CXA:
1055  geometric_solvation_energy -= 0.427747;
1056  desired_hb_weight = geometric_solvation_energy *0.89874;
1057  break;
1058  case hbacc_CXL:
1059  geometric_solvation_energy -= 0.286873;
1060  desired_hb_weight = geometric_solvation_energy *0.82413;
1061  break;
1062  case hbacc_IMD:
1063  geometric_solvation_energy -= 0.725837;
1064  desired_hb_weight = geometric_solvation_energy *0.85228;
1065  break;
1066  case hbacc_IME:
1067  geometric_solvation_energy -= 0.690253;
1068  desired_hb_weight = geometric_solvation_energy *0.91419;
1069  break;
1070  case hbacc_AHX:
1071  geometric_solvation_energy -= 0.64312;
1072  desired_hb_weight = geometric_solvation_energy *1.0239;
1073  break;
1074  case hbacc_HXL:
1075  geometric_solvation_energy -= 0.713553;
1076  desired_hb_weight = geometric_solvation_energy *1.0076;
1077  break;
1078  default:
1079  std::cout << "Chemical acceptor type not found: " << acc_chem_type << std::endl;
1080  exit(1);
1081  break;
1082  }
1083  }
1084  if (polar_group_is_donor ) {
1085 
1086  HBDonChemType don_chem_type = get_hb_don_chem_type( base_atom, polar_rsd );
1087 
1088  switch (don_chem_type ) {
1089  case hbdon_PBA:
1090  geometric_solvation_energy -= 0.794341;
1091  desired_hb_weight = geometric_solvation_energy *0.606;
1092  break;
1093  case hbdon_CXA:
1094  geometric_solvation_energy -= 0.294998;
1095  desired_hb_weight = geometric_solvation_energy*1.0568;
1096  break;
1097  case hbdon_IMD:
1098  geometric_solvation_energy -= 0.426234;
1099  desired_hb_weight = geometric_solvation_energy *0.82543;
1100  break;
1101  case hbdon_IME:
1102  geometric_solvation_energy -= 0.297841;
1103  desired_hb_weight = geometric_solvation_energy *1.1028;
1104  break;
1105  case hbdon_IND:
1106  geometric_solvation_energy -= 0.5463725;
1107  desired_hb_weight = geometric_solvation_energy *0.98083;
1108  break;
1109  case hbdon_AMO:
1110  geometric_solvation_energy -= 0.1029515;
1111  desired_hb_weight = geometric_solvation_energy*1.727;
1112  break;
1113  case hbdon_GDE:
1114  geometric_solvation_energy -= 0.2953195;
1115  desired_hb_weight = geometric_solvation_energy *0.83017;
1116  break;
1117  case hbdon_GDH:
1118  geometric_solvation_energy -= 0.22389;
1119  desired_hb_weight = geometric_solvation_energy *1.5544;
1120  break;
1121  case hbdon_AHX:
1122  geometric_solvation_energy -= 0.494319;
1123  desired_hb_weight = geometric_solvation_energy *0.98647;
1124  break;
1125  case hbdon_HXL:
1126  geometric_solvation_energy -= 0.451273;
1127  desired_hb_weight = geometric_solvation_energy *1.1331;
1128  break;
1129  default:
1130  std::cout << "Chemical donor type not found: " << don_chem_type << std::endl;
1131  exit(1);
1132  break;
1133  }
1134  }
1135  }
1136 
1137  }
1138 
1139  }
1140 
1141  geometric_solvation_energy = geometric_solvation_energy + (desired_hb_weight*polar_group_hb_energy );
1142  return geometric_solvation_energy;
1143 }
1144 
1145 
1147 {
1148 
1149  // // Figure out max LK energy for DONOR
1150  // std::string const base_atom_name = polar_rsd.atom_name( base_atom );
1151  // core::Real max_possible_LK = etable_ptr_->lk_dgfree( polar_rsd.atom_type_index( base_atom ) );
1152  // if ( ( base_atom_name == " N " ) && polar_rsd.is_lower_terminus() ) max_possible_LK /= 3; // charged N-terminus
1153  // if ( base_atom_name == " NZ " ) max_possible_LK /= 3; // Lys
1154  // if ( base_atom_name == " ND2" ) max_possible_LK /= 2; // Asn
1155  // if ( base_atom_name == " NE2" ) max_possible_LK /= 2; // Gln
1156  // if ( base_atom_name == " NH1" ) max_possible_LK /= 2; // Arg
1157  // if ( base_atom_name == " NH2" ) max_possible_LK /= 2; // Arg
1158  // // Note: inner nitrogen of Arg (NE) is extra strong, since it's the same atom type as the other two but doesn't get
1159  // // cut in half because there's only one proton...
1160  // // TR << "jk max LK for donor with base " << base_atom_name << " is " << max_possible_LK << std::endl;
1161  //
1162  // // --OR--
1163  //
1164  // // Figure out max LK energy for ACCEPTOR
1165  // std::string const base_atom_name = polar_rsd.atom_name( base_atom );
1166  // core::Real max_possible_LK = etable_ptr_->lk_dgfree( polar_rsd.atom_type_index( polar_atom ) );
1167  // // TR << "jk max LK for acceptor " << polar_rsd.atom_name(polar_atom) << " is " << max_possible_LK << std::endl;
1168  //
1169  //
1170  // // jk INSTEAD OF USING LK dG FREE, SET THEM ALL TO -5.0. THIS IS ALMOST TRUE ANYWAY, AND THE ONES THAT AREN'T SHOULD PROBABLY BE...
1171  // max_possible_LK = -5.; // -> mjo moved magic number up to namespace level
1172  //
1173  //
1174  // jk LK dG FREE is the energy difference between a completely exposed
1175  // jk and a completely buried polar atom (in the LK model). They get
1176  // jk these numbers from MD simulations in explicit water. The
1177  // jk reference would be the original L+K paper (PMID 10223287), the
1178  // jk numbers themselves are in Table 1 though in Rosetta we use
1179  // jk slightly different numbers.
1180  //
1181  // jk I was originally using these numbers (since I too need to set
1182  // jk the max possible solvation energy for a given functional group),
1183  // jk but then realized that the LK numbers (or at least, their
1184  // jk Rosetta incarnation) are all basically 5 divided by the number
1185  // jk of protons / lone pairs (which I don't think L+K appreciated),
1186  // jk so I just started using this instead of LK dG FREE.
1187  //
1188 
1189  // Compute Ebulk (using the LK energy)
1190  core::Real const Emax_weight = exp( max_possible_LK / geosol_kT );
1191  core::Real const sum_water_weights = WaterWeightGridSet::get_instance()->get_sum_water_weight_grid( hbond_eval_type.eval_type() );
1192  core::Real const Ebulk_weight = ( sum_water_weights * Emax_weight ) / ( 1. - Emax_weight);
1193  // This grid constant is the denominator in computing solvation energies,
1194  // it depends on the grid dimensions, and sets the max possible solvation energy (in this case to match LK)
1195  core::Real const grid_constant = sum_water_weights + Ebulk_weight;
1196 
1197  return grid_constant;
1198 }
1199 core::Size
1201 {
1202  return 1; // Initial versioning
1203 }
1204 
1205 
1206 
1207 } // geometric_solvation
1208 } // scoring
1209 } // core