Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PoissonBoltzmannEnergy.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/PoissonBoltzmannEnergy.cc
11 /// @brief Ramachandran energy method class implementation
12 /// @author Phil Bradley
13 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
14 
15 // Unit Headers
18 
19 // Package Headers
23 #include <core/scoring/Energies.hh>
27 
28 // Project headers
29 #include <core/pose/Pose.hh>
30 #include <core/pose/PDBInfo.hh>
32 
33 // Utility headers
34 #include <basic/Tracer.hh>
35 #include <basic/datacache/CacheableData.hh>
36 #include <basic/datacache/DataCache.hh>
38 
39 // option
40 #include <basic/options/option.hh>
41 #include <basic/options/keys/pb_potential.OptionKeys.gen.hh>
42 
43 // numeric
44 #include <numeric/xyzVector.hh>
45 #include <utility/vector1.hh>
46 
47 
48 static basic::Tracer TR("core.scoring.methods.PoissonBoltzmannEnergy");
49 
50 namespace core {
51 namespace scoring {
52 namespace methods {
53 
54 //*****************************************************************
55 //
56 // PBLifetimeCache: carries cache for the entire runtime cycle.
57 //
58 //*****************************************************************
60 {}
62 {}
63 basic::datacache::CacheableDataOP
65 {
66  return new PBLifetimeCache(*this);
67 }
68 void
69 PBLifetimeCache::set_charged_residues_map( const std::map<std::string, bool> & charged_residues_map )
70 {
71  charged_residues_map_ = charged_residues_map;
72 }
73 void
75 {
76  energy_state_ = energy_state;
77 }
78 void
80  const core::pose::Pose & pose,
82 {
83  pose_by_state_[energy_state] = new core::pose::Pose(pose);
84  pb_by_state_[energy_state] = pbp;
85 }
86 std::map<std::string, bool> &
88 {
89  return charged_residues_map_;
90 }
91 const std::string &
93 {
94  return energy_state_;
95 }
96 
98 PBLifetimeCache::get_pose( const std::string& energy_state )
99 {
100  //TR << "Looking for cached pose for state \"" << energy_state << "\" in PBLifetimeCache " << "{ ";
101  //std::map<std::string, pose::PoseCOP>::const_iterator itr = poses_by_state_.begin();
102  //for(; itr != poses_by_state_.end(); ++itr ){
103  // TR << "(key=" << itr->first << ": val=" << itr->second->pdb_info()->name() << "), ";
104  //}
105  //TR << " }" << std::endl;
106  return pose_by_state_[energy_state];
107 }
109 PBLifetimeCache::get_pbp( const std::string& energy_state )
110 {
111  return pb_by_state_[energy_state];
112 }
113 
114 bool
115 PBLifetimeCache::has_cache( const std::string& energy_state ) const
116 {
117  return pb_by_state_.count(energy_state) && pose_by_state_.count( energy_state);
118 }
119 //*****************************************************************
120 //
121 // PoissonBoltzmannEnergyCreator
122 //
123 //*****************************************************************
124 /// @details This must return a fresh instance of the PoissonBoltzmannEnergy class,
125 /// never an instance already in use
129 ) const {
130  return new PoissonBoltzmannEnergy;
131 }
132 
135  ScoreTypes sts;
136  sts.push_back( PB_elec );
137  return sts;
138 }
139 
140 //*****************************************************************
141 //
142 // PoissonBoltzmannEnergy
143 //
144 //*****************************************************************
145 /// ctor
148  fixed_residue_(1),
149  epsilon_(2.0)
150  //,
151  //poisson_boltzmann_potential_( new scoring::PoissonBoltzmannPotential )
152 
153 {
154  if( basic::options::option[basic::options::OptionKeys::pb_potential::epsilon].user() ) {
155  epsilon_ = basic::options::option[basic::options::OptionKeys::pb_potential::epsilon];
156  }
157 }
158 
159 /// clone
162 {
163  return new PoissonBoltzmannEnergy( *this );
164 }
167 
168 void
170  pose::Pose & pose,
171  ScoreFunction const & scorefxn
172  ) const {
173  using namespace methods;
174 
175  // If the cached object is not in the pose data-cache, it suggests that the setup protocol has not
176  // been called in prior. Warn and get out!
178  TR << "PB_LIFETIME_CACHE object is not initialized. Did you call SetupPoissonBoltzmannPotential mover? Terminaing the program..." << std::endl;
179  TR.flush();
180  // Register the empty cache holder if not done so yet.
183 
184  //runtime_assert(false);
185  }
186  PBLifetimeCacheOP cached_data =
188 
189  // Do we have the map of charged residues by name?
190  charged_residues_ = cached_data->get_charged_residues_map();
191  if( charged_residues_.size() == 0 ){
192  utility::vector1<int> charged_chains
193  = basic::options::option[basic::options::OptionKeys::pb_potential::charged_chains];
194  std::map<std::string, bool> charged_residues;
195  TR << "Charged residues: [ ";
196  for ( Size i=1; i<= pose.total_residue(); ++i ) {
197  core::conformation::Residue const & rsd( pose.residue(i) );
198  bool residue_charged = false;
199  if ( std::find(charged_chains.begin(), charged_chains.end(), rsd.chain()) != charged_chains.end() ) {
200  residue_charged = true;
201  TR << rsd.type().name() << ",";
202  }
203  charged_residues_[rsd.type().name()] = residue_charged;
204  }
205  cached_data->set_charged_residues_map( charged_residues_ );
206  TR << "]" << std::endl;
207  }
208 
210  std::string energy_state = cached_data->get_energy_state();
211 
212  if( energy_state == "" ) {
213  energy_state = "stateless";
214  }
215  TR << "Energy state: \"" << energy_state << "\" for scorefxn: " << scorefxn.get_name() << std::endl;
216 
217  const Size atom_index = 2; // alpha carbon
218 
219  //
220  // Solve PB
221  //
222  // use cached data if the bound comformation hasn't changed.
223  if( cached_data->has_cache( energy_state ) ) {
224  core::pose::PoseCOP prev_pose = cached_data->get_pose( energy_state );
225 
226  // switch to the state's pb
227  poisson_boltzmann_potential_ = cached_data->get_pbp(energy_state);
228  assert(poisson_boltzmann_potential_ != 0);
229 
230  TR << "Found cached pose for state: " << energy_state << std::endl;
231 
232  // re-evaluate only for bound-state.
233  if( energy_state == emoptions.pb_bound_tag() ) {
234 
235  if( !protein_position_equal_within( pose, *prev_pose, atom_index, epsilon_ ) ) {
236  TR << "Atoms (" << atom_index << ") in charged chains moved more than " ;
237  TR << epsilon_ << "A" << std::endl;
238  poisson_boltzmann_potential_->solve_pb(pose, energy_state, charged_residues_);
239  }
240  }
241  }
242  else{
243  TR << "No cached pose for state: " << energy_state << std::endl;
245  poisson_boltzmann_potential_->solve_pb(pose, energy_state, charged_residues_);
246  }
247 
248 
249  // Update the cache
250  cached_data->set_conformational_data( energy_state, pose, poisson_boltzmann_potential_ );
251 
252  // make sure the root of the FoldTree is a virtual atom and is followed by a jump
253  // if not, emit warning
254  //kinematics::Edge const &root_edge ( *pose.fold_tree().begin() );
255  //int virt_res_idx = root_ede.start();
256  //conformation::Residue const &root_res( pose.residue( virt_res_idx ) );
257 
258  //pose_is_proper = true;
259  //if (root_res.aa() != core::chemical::aa_vrt || root_edge.label() < 0) {
260  //utility_exit_with_message("Fold tree is not set properly for density scoring!");
261  //TR.Error << "Fold tree is not set properly for density scoring!" << std::endl;
262  //pose_is_proper = false;
263  //}
264 
265  //
266  // create LR energy container
267  LongRangeEnergyType const & lr_type( long_range_type() );
268  Energies & energies( pose.energies() );
269  bool create_new_lre_container( false );
270 
271  if ( energies.long_range_container( lr_type ) == 0 ) {
272  create_new_lre_container = true;
273  } else {
274  LREnergyContainerOP lrc = energies.nonconst_long_range_container( lr_type );
275  OneToAllEnergyContainerOP dec( static_cast< OneToAllEnergyContainer * > ( lrc.get() ) );
276  // make sure size or root did not change
277  if ( dec->size() != pose.total_residue() ) {
278  create_new_lre_container = true;
279  }
280  }
281 
282  if ( create_new_lre_container ) {
283  TR << "Creating new one-to-all energy container (" << pose.total_residue() << ")" << std::endl;
285  energies.set_long_range_container( lr_type, new_dec );
286  }
287 
288  // allocate space for per-AA stats
289  //int nres = pose.total_residue();
290  //core::scoring::electron_density::getDensityMap().set_nres( nres );
291 }
292 
293 
294 /////////////////////////////////////////////////////////////////////////////
295 // methods
296 /////////////////////////////////////////////////////////////////////////////
297 
299  pose::Pose const &,
300  Size res1,
301  Size res2
302 ) const {
303  return ( res1 == fixed_residue_ || res2 == fixed_residue_ );
304 }
305 
306 void
308  conformation::Residue const &,
309  pose::Pose const &,
310  ScoreFunction const &,
311  EnergyMap &
312 ) const {
313  return;
314 }
315 
316 bool
318 conformation::Residue const & rsd,
320 ) const {
321  for (Size ichain=1; ichain<=chains.size(); ++ichain) {
322  if (rsd.chain() == chains[ichain]) return true;
323  }
324  return false;
325 }
326 
327 Real
329  conformation::Residue const & rsd,
330  pose::Pose const & pose
331 ) const {
332  utility::vector1 <Size> chains = basic::options::option[basic::options::OptionKeys::pb_potential::revamp_near_chain]();
333  Real weight = 1.;
334  Real neighbor_count = 0.;
335  Real threshold = 4.;
336  for (Size j_res = 1; j_res <= pose.total_residue(); ++j_res) {
337  if ( pose.residue(j_res).is_virtual_residue() ) continue;
338 
339  if (residue_in_chains(pose.residue(j_res), chains) ) {
340  bool found_neighbor = false;
341  for (Size i_atom = rsd.last_backbone_atom() + 1; i_atom <= rsd.nheavyatoms(); ++i_atom) {
342  for (Size j_atom = 1; j_atom <= rsd.nheavyatoms(); ++j_atom) {
343  if ( pose.residue(j_res).is_virtual(j_atom) ) continue;
344  Real distance = rsd.xyz(i_atom).distance(pose.residue(j_res).xyz(j_atom));
345  if (distance < threshold) {
346  neighbor_count += 1.;
347  found_neighbor = true;
348  break;
349  }
350  }
351  if (found_neighbor) break;
352  }
353  }
354  }
355  if (neighbor_count > 0) weight = 1./neighbor_count;
356  //using namespace ObjexxFCL::fmt;
357  //TR << "PB_weight:" << I(4,rsd.seqpos()) << F(8, 3, weight) << std::endl;
358  return weight;
359 }
360 
361 void
363  conformation::Residue const & rsd1,
364  conformation::Residue const & rsd2,
365  pose::Pose const & pose,
366  ScoreFunction const &,
367  EnergyMap & emap
368  ) const {
369  //check fixed_residue_
370  conformation::Residue const &rsd (rsd1.seqpos() == fixed_residue_? rsd2 : rsd1 );
371 
372  // If it is part of charged chain, skip.
373  if( const_cast<std::map<std::string, bool>&>(charged_residues_)[rsd.type().name()] ) {
374  return;
375  }
376 
377  Real PB_score_residue, PB_score_backbone, PB_score_sidechain;
378  Real PB_burial_weight(1.0);
379  if (basic::options::option[basic::options::OptionKeys::pb_potential::revamp_near_chain].user()) {
380  PB_burial_weight = revamp_weight_by_burial(rsd, pose);
381  }
382  poisson_boltzmann_potential_->eval_PB_energy_residue(
383  rsd,
384  PB_score_residue,
385  PB_score_backbone,
386  PB_score_sidechain,
387  PB_burial_weight );
388 
389  if (basic::options::option[basic::options::OptionKeys::pb_potential::sidechain_only]()) {
390  emap[ PB_elec ] += PB_score_sidechain;
391  }
392  else {
393  emap[ PB_elec ] += PB_score_residue;
394  }
395 }
396 
397 /// @brief Energy is context independent and thus indicates that no context graphs need to
398 /// be maintained by class Energies
399 void
401  utility::vector1< bool > & /*context_graphs_required*/
402 )
403 const
404 {}
405 
406 
407 ///
408 /// Compare if two poses are close in fold within tolerance.
409 ///
410 /// To be specific, it returns True if for all a in A and b in B,
411 /// sqrt( (a.x-b.x)^2 + (a.y-b.y)^2 + (a.z-b.z)^2 ) <= tol,
412 /// for A and B are sets of all atoms in protein 1 and protein 2, respectively.
413 ///
414 /// @param pose1 A protein's pose
415 /// @param pose2 Another protein's pose
416 /// @param atom_num The atom number
417 /// @param tol Tolerable distance in Angstrom, >= 0.A
418 ///
419 bool
421  pose::Pose const & pose1,
422  pose::Pose const & pose2,
423  Size atom_num,
424  Real tol) const {
425  if( &pose1 == NULL || &pose2 == NULL ) {
426  return false;
427  }
428  if( &pose1 == NULL && &pose2 == NULL ) {
429  return true;
430  }
431  if(pose1.total_residue() != pose2.total_residue()) {
432  return false;
433  }
434 
435  for( Size i=1; i<=pose1.total_residue(); ++i ) {
436 
437  if( pose1.residue(i).is_protein() ){
438  if( ! pose2.residue(i).is_protein() ) {
439  return false;
440  }
441  if( pose1.residue(i).natoms() != pose2.residue(i).natoms() ) {
442  return false;
443  }
444  const core::conformation::Atom atom1 = pose1.residue(i).atom(atom_num);
445  const core::conformation::Atom atom2 = pose2.residue(i).atom(atom_num);
446  const numeric::xyzVector<Real> xyz1 = atom1.xyz();
447  const numeric::xyzVector<Real> xyz2 = atom2.xyz();
448 
449  const Real delta = xyz1.distance(xyz2);
450  if( delta > tol ) {
451  // exceed tolerance
452  return false;
453  }
454  }
455  }
456  return true;
457 }
458 
461 {
462  return 1; // Initial versioning
463 }
464 
465 
466 } // methods
467 } // scoring
468 } // core
469