Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RNAHackElecEnergy.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/hackelec/RNAHackElecEnergy.cc
11 /// @brief Electrostatics energy method for RNA class implementation
12 /// @author Rhiju Das
13 
14 
15 // Unit headers
18 
19 // Package headers
21 #include <core/scoring/Energies.hh>
22 //#include <core/scoring/ScoringManager.hh>
23 // AUTO-REMOVED #include <core/scoring/methods/EnergyMethodOptions.hh>
27 
28 // Project headers
30 
31 #include <core/pose/Pose.hh>
32 
34 // AUTO-REMOVED #include <core/pack/rotamer_set/RotamerSetFactory.hh>
35 
36 #include <core/id/AtomID.hh>
37 #include <utility/vector1.hh>
38 
39 
40 // ObjexxFCL headers
41 
42 
43 
44 // C++
45 
46 /////////////////////////////////////////////////////////////////////////////////////////
47 ///
48 /// Hacky (hence the name) implementation of 10r dielectric model, cutoff at 5.5A
49 ///
50 ///
51 
52 //
53 // alternatives: WARSHEL (from ligand.cc)
54 // E = 322.0637*q1*q2/r/e(r)
55 // if ( r < 3 ) e(r) = 16.55
56 // else e(r) = 1 + 60*(1-exp(-0.1*r))
57 // Warshel, A. Russell, S. T., Q. Rev. Biophys., 1984, 17, 283-422
58 //
59 //
60 // sigmoidal dielectric: (hingerty 1985)
61 //
62 // e(r) = D - (D-D0)/2 [ (rS)**2 + 2rS + 2]exp(-rS)
63 // with eg:
64 // D = 78, D0 = 1, S = 0.3565 (rouzina&bloomfield)
65 // D = 80, D0 = 4, S = 0.4 (rohs)
66 
67 namespace core {
68 namespace scoring {
69 namespace hackelec {
70 
71 
72 /// @details This must return a fresh instance of the RNAHackElecEnergy class,
73 /// never an instance already in use
76  methods::EnergyMethodOptions const & options
77 ) const {
78  return new RNAHackElecEnergy( options );
79 }
80 
83  ScoreTypes sts;
84  sts.push_back( hack_elec_rna_phos_phos );
85  sts.push_back( hack_elec_rna_phos_sugr );
86  sts.push_back( hack_elec_rna_phos_base );
87  sts.push_back( hack_elec_rna_sugr_sugr );
88  sts.push_back( hack_elec_rna_sugr_base );
89  sts.push_back( hack_elec_rna_base_base );
90  return sts;
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////
95  methods::EnergyMethodOptions const & options
96 ):
97  parent( options )
98 {
100 }
101 
102 
103 ////////////////////////////////////////////////////////////////////////////
105  parent( src )
106 {
108 }
109 
110 /// clone
113 {
114  return new RNAHackElecEnergy( *this );
115 }
116 
117 ///
118 void
120 {
122 }
123 
124 ///
125 void
127 {
129 }
130 
131 
132 // The HackElectEnergy method stores a vector of rotamer trie objects in the Energies
133 // object for use in rapid rotamer/background energy calculations. Overrides default
134 // do-nothing behavior.
135 void
137  pose::Pose &,
138  utility::vector1< bool > const &,
140 ) const
141 {
142  /// noop -- this noop is essential for overriding the base class behavior.
143 }
144 
145 // @brief Creates a rotamer trie for the input set of rotamers and stores the trie
146 // in the rotamer set.
147 void
149  pose::Pose const &,
151 ) const
152 {
153  /// noop -- this noop is essential for overriding the base class behavior.
154 }
155 
156 
157 // @brief Updates the cached rotamer trie for a residue if it has changed during the course of
158 // a repacking
159 void
161  pose::Pose &,
162  Size
163 ) const
164 {
165  /// noop -- this noop is essential for overriding the base class behavior.
166 }
167 
168 /////////////////////////////////////////////////////////////////////////////
169 // scoring
170 /////////////////////////////////////////////////////////////////////////////
171 
172 ///
173 void
175  conformation::Residue const & rsd1,
176  conformation::Residue const & rsd2,
177  pose::Pose const &,
178  ScoreFunction const &,
179  EnergyMap & emap
180 ) const
181 {
182  if ( rsd1.is_RNA() && rsd2.is_RNA() ) {
183  residue_pair_energy_RNA( rsd1, rsd2, emap ); // In the grand spirit of hack_elec hackiness
184  }
185  //std::cout << rsd1.seqpos() << ' ' << rsd2.seqpos() << ' ' << score << std::endl;
186 }
187 
188 
189 //////////////////////////////////////
190 bool is_phosphate( conformation::Residue const & rsd, Size const i )
191 {
192  if ( rsd.atom_is_hydrogen( i ) ) {
193  return is_phosphate( rsd, rsd.atom_base( i ) );
194  } else {
195  //MAGIC NUMBERS! BAD!
196  return ( i==1 || i==2 || i==3 || i==4 || i==9 ); //P, O1P, O2P, O5*, O3*
197  }
198 }
199 
200 //////////////////////////////////////
201 bool is_sugar( conformation::Residue const & rsd, Size const i )
202 {
203  if ( rsd.atom_is_hydrogen( i ) ) {
204  return is_sugar( rsd, rsd.atom_base( i ) );
205  } else {
206  return ( ( i < rsd.first_sidechain_atom() && !is_phosphate(rsd, i) ) ||
207  i==12 );
208  }
209 }
210 
211 //////////////////////////////////////
212 bool is_base( conformation::Residue const & rsd, Size const i )
213 {
214  if ( rsd.atom_is_hydrogen( i ) ) {
215  return is_base( rsd, rsd.atom_base( i ) );
216  } else {
217  return (!is_sugar(rsd, i) && !is_phosphate(rsd, i) );
218  }
219 }
220 
221 //////////////////////////////////////////////////////////////////////////////////
222 // July 22 2011. OK could potentially optimize by calculating the energy for the atom-atom pairs in which the weight term is non-zero.
223 // For example, for standard weight only hack_elec_rna_phos_phos weight is non-zero. So for this case can skip non-phosphate atoms.
224 // Following copies a little code, but at least separates out this inelegant and
225 // probably useless RNA stuff from the usual stuff.
226 Real
228  conformation::Residue const & rsd1,
229  conformation::Residue const & rsd2,
230  EnergyMap & emap
231 ) const
232 {
233  assert( rsd1.is_RNA() );
234  assert( rsd2.is_RNA() );
235 
236  using namespace etable::count_pair;
237 
238  Real total_score( 0.0 );
239 
240  CountPairFunctionOP cpfxn =
241  CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
242 
243  for ( Size i=1, i_end = rsd1.natoms(); i<= i_end; ++i ) {
244  Vector const & i_xyz( rsd1.xyz(i) );
245  Real const i_charge( rsd1.atomic_charge(i) );
246 
247  // NOTE THAT is_base, is_sugar, and is_phosphate contains MAGIC NUMBERS (for speed!)
248  // Might be better to make it precomputed as part of the residue_type definition?
249  bool const atom1_is_base = is_base(rsd1, i);
250  bool const atom1_is_sugar = is_sugar(rsd1, i);
251  bool const atom1_is_phosphate = is_phosphate(rsd1, i);
252  assert( atom1_is_base || atom1_is_sugar || atom1_is_phosphate );
253 
254  // if (atom1_is_base) std::cout << "THIS BETTER BE A BASE ATOM: " << rsd1.atom_name( i ) << std::endl;
255 
256  if ( i_charge == 0.0 ) continue;
257  for ( Size j=1, j_end = rsd2.natoms(); j<= j_end; ++j ) {
258  Real const j_charge( rsd2.atomic_charge(j) );
259  if ( j_charge == 0.0 ) continue;
260  Real weight(1.0);
261  Size path_dist( 0 );
262  if ( cpfxn->count( i, j, weight, path_dist ) ) {
263  Real score = weight *
264  eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge);
265 
266  total_score += score;
267 
268  bool const atom2_is_base = is_base(rsd2, j);
269  bool const atom2_is_sugar = is_sugar(rsd2, j);
270  bool const atom2_is_phosphate = is_phosphate(rsd2, j);
271  assert( atom2_is_base || atom2_is_sugar || atom2_is_phosphate );
272 
273  if ( atom1_is_base && atom2_is_base ) {
274  emap[ hack_elec_rna_base_base ] += score;
275  } else if ( (atom1_is_base && atom2_is_sugar) || (atom1_is_sugar && atom2_is_base) ) {
276  emap[ hack_elec_rna_sugr_base ] += score;
277  } else if ( (atom1_is_base && atom2_is_phosphate) || (atom1_is_phosphate && atom2_is_base) ) {
278  emap[ hack_elec_rna_phos_base ] += score;
279  } else if ( (atom1_is_sugar && atom2_is_phosphate) || (atom1_is_phosphate && atom2_is_sugar) ) {
280  emap[ hack_elec_rna_phos_sugr ] += score;
281  } else if ( (atom1_is_sugar && atom2_is_sugar) ) {
282  emap[ hack_elec_rna_sugr_sugr ] += score;
283  } else if ( (atom1_is_phosphate && atom2_is_phosphate) ) {
284  emap[ hack_elec_rna_phos_phos ] += score;
285  } else {
286  std::cout << "PROBLEM! " << rsd1.atom_name( i ) << " " << rsd2.atom_name( j ) << std::endl;
287  }
288  }
289  }
290  }
291 
292  return total_score;
293 
294 }
295 
296 void
298  conformation::RotamerSetBase const & set1,
299  conformation::RotamerSetBase const & set2,
300  pose::Pose const & pose,
301  ScoreFunction const & sfxn,
302  EnergyMap const & weights,
303  ObjexxFCL::FArray2D< core::PackerEnergy > & energy_table
304 ) const
305 {
306  if ( set1.num_rotamers() >= 1 && set2.num_rotamers() >= 1 &&
307  set1.rotamer(1)->is_RNA() && set2.rotamer(1)->is_RNA() ) {
308  grandparent::evaluate_rotamer_pair_energies( set1, set2, pose, sfxn, weights, energy_table );
309  } // else, non rna rna interaction; early return
310 }
311 
312 void
314  conformation::RotamerSetBase const & set,
315  conformation::Residue const & residue,
316  pose::Pose const & pose,
317  ScoreFunction const & sfxn,
318  EnergyMap const & weights,
320 ) const
321 {
322  if ( set.num_rotamers() >= 1 && set.rotamer(1)->is_RNA() && residue.is_RNA() ) {
323  grandparent::evaluate_rotamer_background_energies( set, residue, pose, sfxn, weights, energy_vector );
324  } // else, non rna rna interaction; early return
325 }
326 
327 
328 void
330  id::AtomID const & atom_id,
331  pose::Pose const & pose,
332  kinematics::DomainMap const & domain_map,
333  ScoreFunction const &,
334  EnergyMap const & weights,
335  Vector & F1,
336  Vector & F2
337  ) const
338 {
339  using namespace etable::count_pair;
340 
341  // what is my charge?
342  Size const pos1( atom_id.rsd() );
343  Size const i ( atom_id.atomno() );
344  conformation::Residue const & rsd1( pose.residue( pos1 ) );
345 
346  if ( ! rsd1.is_RNA() ) return;
347 
348  Real const i_charge( rsd1.atomic_charge( i ) );
349  int const pos1_map( domain_map( pos1 ) );
350  bool const pos1_fixed( pos1_map != 0 );
351 
352 
353  if ( i_charge == 0.0 ) return;
354 
355  //Vector const & i_xyz( rsd1.xyz(i) );
356 
357  // cached energies object
358  Energies const & energies( pose.energies() );
359 
360  // the neighbor/energy links
361  EnergyGraph const & energy_graph( energies.energy_graph() );
362 
363 // kinematics::DomainMap const & domain_map( energies.domain_map() );
364 // bool const pos1_fixed( !energies.res_moved( pos1 ) );
365 // assert( pos1_fixed == ( domain_map(pos1) != 0 ) ); // this is probably not generally true but I'm curious
366 
367  // loop over *all* nbrs of rsd1 (not just upper or lower)
369  iru = energy_graph.get_node( pos1 )->const_edge_list_begin(),
370  irue = energy_graph.get_node( pos1 )->const_edge_list_end();
371  iru != irue; ++iru ) {
372  //EnergyEdge const * edge( static_cast< EnergyEdge const *> (*iru) );
373  //Size const pos2( edge->get_second_node_ind() );
374  Size const pos2( (*iru)->get_other_ind( pos1 ) );
375 
376  if ( pos1_fixed && pos1_map == domain_map( pos2 ) ) continue; // fixed wrt one another
377 
378  conformation::Residue const & rsd2( pose.residue( pos2 ) );
379 
380  assert( pos2 != pos1 );
381 
382  if ( rsd2.is_RNA() ) {
383  eval_atom_derivative_RNA( rsd1, i, rsd2, weights, F1, F2 );
384  }
385 
386  } // loop over nbrs of rsd1
387 
388 }
389 
390 
391 //////////////////////////////////////////////////
392 void
394  conformation::Residue const & rsd1,
395  Size const & i,
396  conformation::Residue const & rsd2,
397  EnergyMap const & weights,
398  Vector & F1,
399  Vector & F2
400  ) const
401 {
402 
403  using namespace etable::count_pair;
404 
405  CountPairFunctionOP cpfxn = CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
406 
407  Real const i_charge( rsd1.atomic_charge( i ) );
408  Vector const & i_xyz( rsd1.xyz(i) );
409 
410 
411  // NOTE THAT is_base, is_sugar, and is_phosphate contains MAGIC NUMBERS (for speed!)
412  // Might be better to make it precomputed as part of the residue_type definition?
413  //This repeats some unnecessary stuff, but hey, derivatives don't have to be that fast.
414  bool const atom1_is_base = is_base(rsd1, i);
415  bool const atom1_is_sugar = is_sugar(rsd1, i);
416  bool const atom1_is_phosphate = is_phosphate(rsd1, i);
417  assert( atom1_is_base || atom1_is_sugar || atom1_is_phosphate );
418 
419  for ( Size j=1, j_end = rsd2.natoms(); j<= j_end; ++j ) {
420  Real const j_charge( rsd2.atomic_charge(j) );
421  if ( j_charge == 0.0 ) continue;
422  Real weight(1.0);
423  Size path_dist( 0 );
424  if ( cpfxn->count( i, j, weight, path_dist ) ) {
425  Vector const & j_xyz( rsd2.xyz(j) );
426  Vector const f2( i_xyz - j_xyz );
427  Real const dis2( f2.length_squared() );
428  Real const dE_dr_over_r = weight *
429  eval_dhack_elecE_dr_over_r( dis2, i_charge, j_charge );
430  if ( dE_dr_over_r != 0.0 ) {
431  Vector const f1( i_xyz.cross( j_xyz ) );
432  //F1 += weights[ hack_elec ] * dE_dr_over_r * f1;
433  //F2 += weights[ hack_elec ] * dE_dr_over_r * f2;
434 
435  bool const atom2_is_base = is_base(rsd2, j);
436  bool const atom2_is_sugar = is_sugar(rsd2, j);
437  bool const atom2_is_phosphate = is_phosphate(rsd2, j);
438  assert( atom2_is_base || atom2_is_sugar || atom2_is_phosphate );
439 
440  if ( atom1_is_base && atom2_is_base ) {
441  F1 += weights[ hack_elec_rna_base_base ] * dE_dr_over_r * f1;
442  F2 += weights[ hack_elec_rna_base_base ] * dE_dr_over_r * f2;
443  } else if ( (atom1_is_base && atom2_is_sugar) || (atom1_is_sugar && atom2_is_base) ) {
444  F1 += weights[ hack_elec_rna_sugr_base ] * dE_dr_over_r * f1;
445  F2 += weights[ hack_elec_rna_sugr_base ] * dE_dr_over_r * f2;
446  } else if ( (atom1_is_base && atom2_is_phosphate) || (atom1_is_phosphate && atom2_is_base) ) {
447  F1 += weights[ hack_elec_rna_phos_base ] * dE_dr_over_r * f1;
448  F2 += weights[ hack_elec_rna_phos_base ] * dE_dr_over_r * f2;
449  } else if ( (atom1_is_sugar && atom2_is_phosphate) || (atom1_is_phosphate && atom2_is_sugar) ) {
450  F1 += weights[ hack_elec_rna_phos_sugr ] * dE_dr_over_r * f1;
451  F2 += weights[ hack_elec_rna_phos_sugr ] * dE_dr_over_r * f2;
452  } else if ( (atom1_is_sugar && atom2_is_sugar) ) {
453  F1 += weights[ hack_elec_rna_sugr_sugr ] * dE_dr_over_r * f1;
454  F2 += weights[ hack_elec_rna_sugr_sugr ] * dE_dr_over_r * f2;
455  } else if ( (atom1_is_phosphate && atom2_is_phosphate) ) {
456  F1 += weights[ hack_elec_rna_phos_phos ] * dE_dr_over_r * f1;
457  F2 += weights[ hack_elec_rna_phos_phos ] * dE_dr_over_r * f2;
458  }
459 
460  }
461  }
462  }
463 }
464 
465 
466 /// @brief RNAHackElecEnergy is context independent; no context graphs required
467 void
469 {
470 }
473 {
474  return 1; // Initial versioning
475 }
476 
477 
478 
479 }
480 }
481 }