Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RNA_Mg_Energy.cc
Go to the documentation of this file.
1 // INCLUDED_core_scoring_ScoreFunction_HH
2 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
3 // vi: set ts=2 noet:
4 //
5 // (c) Copyright Rosetta Commons Member Institutions.
6 // (c) This file is part of the Rosetta software suite and is made available under license.
7 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
8 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
9 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
10 
11 /// @file core/scoring/rna/RNA_Mg_Energy.cc
12 /// @brief Statistically derived Mg(2+) binding potential for RNA.
13 /// @author Rhiju Das
14 
15 
16 // Unit headers
20 
21 // Package headers
27 #include <core/scoring/Energies.hh>
30 #include <basic/Tracer.hh>
31 
32 // Project headers
33 #include <core/pose/Pose.hh>
35 #include <core/id/AtomID.hh>
36 
37 #include <basic/options/option.hh>
38 #include <basic/options/keys/rescore.OptionKeys.gen.hh>
39 
40 #include <numeric/conversions.hh>
41 #include <utility/vector1.hh>
42 
43 #include <ObjexxFCL/FArray2D.hh>
44 #include <ObjexxFCL/format.hh>
45 
46 using ObjexxFCL::fmt::I;
47 
48 static basic::Tracer tr("core.scoring.rna.RNA_Mg_Energy");
49 
50 namespace core {
51 namespace scoring {
52 namespace rna {
53 
54 
55 /// @details This must return a fresh instance of the RNA_Mg_Energy class,
56 /// never an instance already in use
60 ) const {
61  return new RNA_Mg_Energy;
62 }
63 
66  ScoreTypes sts;
67  sts.push_back( rna_mg );
68  sts.push_back( rna_mg_indirect );
69  return sts;
70 }
71 
72 
75  rna_mg_knowledge_based_potential_( new RNA_Mg_KnowledgeBasedPotential ),
76  hbond_options_( new core::scoring::hbonds::HBondOptions ), // useful helper functions
77  verbose_( basic::options::option[ basic::options::OptionKeys::rescore::verbose ]() )
78 {}
79 
80 
81 /// clone
84 {
85  return new RNA_Mg_Energy;
86 }
87 
88 /////////////////////////////////////////////////////////////////////////////
89 // scoring
90 /////////////////////////////////////////////////////////////////////////////
91 
92 //////////////////////////////////////////////////////////////////////////////////////////
93 void
95 {
97  rna_mg_knowledge_based_potential_->setup_info_for_mg_calculation( pose );
98 }
99 
100 
101 //////////////////////////////////////////////////////////////////////////////////////////
102 void
104 {
106  rna_mg_knowledge_based_potential_->setup_info_for_mg_calculation( pose );
107 }
108 
109 
110 //////////////////////////////////////////////////////////////////////////////////////////
111 void
113 {
115  rna_mg_knowledge_based_potential_->setup_info_for_mg_calculation( pose );
116 }
117 
118 
119 
120 //////////////////////////////////////////////////////////////////////////////////////////
121 void
123  conformation::Residue const & rsd1,
124  conformation::Residue const & rsd2,
125  pose::Pose const & pose,
126  ScoreFunction const &,
127  EnergyMap & emap
128 ) const
129 {
130 
131  rna::RNA_ScoringInfo const & rna_scoring_info( rna::rna_scoring_info_from_pose( pose ) );
132  utility::vector1< bool > const & is_magnesium = rna_scoring_info.is_magnesium();
133 
134  if ( rsd1.is_RNA() && is_magnesium[ rsd2.seqpos() ] ) {
135  residue_pair_energy_one_way( rsd1, rsd2, pose, emap );
136  }
137 
138  if ( rsd2.is_RNA() && is_magnesium[ rsd1.seqpos() ] ) {
139  residue_pair_energy_one_way( rsd2, rsd1, pose, emap );
140  }
141 
142  return;
143 }
144 
145 
146 ////////////////////////////////////////////////////////////////////////////////////////////////////////
147 Real
149  Size const i, Vector const & i_xyz, Vector const & j_xyz ) const
150 {
151 
152  Vector dummy, xyz_base;
153 
154  if ( rsd1.heavyatom_is_an_acceptor(i) ){
155  chemical::Hybridization acc_hybrid( rsd1.atom_type( i ).hybridization());
158  acc_hybrid,
159  rsd1.atom( i ).xyz(),
160  rsd1.xyz( rsd1.atom_base( i ) ),
161  rsd1.xyz( rsd1.abase2( i ) ),
162  xyz_base, dummy );
163  } else if ( rsd1.atom_type( i ).name() == "Hpol" ) {
164  xyz_base = rsd1.xyz( rsd1.atom_base( i ) );
165  } else {
166  return -999; // bogus value
167  }
168 
169  Vector const a = j_xyz - i_xyz;
170  Vector const b = xyz_base - i_xyz;
171 
172  Real cos_theta = dot( a, b )/( a.length() * b.length() );
173 
174  // if ( a.length() < 3.0 ) std::cout << rsd1.name1() << " " << rsd1.seqpos() << " " << rsd1.atom_name(i) << " " << cos_theta << std::endl;
175 
176  return cos_theta;
177 }
178 
179 
180 ////////////////////////////////////////////////////////////////////////////////////////////////////////
181 void
183  conformation::Residue const & rsd1, // The RNA residue
184  conformation::Residue const & rsd2, // The Mg(2+)
185  pose::Pose const & pose,
186  EnergyMap & emap
187  ) const{
188 
189  rna::RNA_ScoringInfo const & rna_scoring_info( rna::rna_scoring_info_from_pose( pose ) );
190  utility::vector1< bool > const & is_magnesium = rna_scoring_info.is_magnesium();
191 
192  runtime_assert( rsd1.is_RNA() );
193  runtime_assert( is_magnesium[ rsd2.seqpos() ] );
194 
195  Real score( 0.0 ), score_indirect( 0.0 );
196 
197  // get magnesium position
198  Size const j = 1; //First atom of Mg2+ residue is assumed to be Mg2+ atom.
199  runtime_assert( rsd2.atom_name( j ) == "MG " );
200  if (rsd2.is_virtual(j) ) return;
201 
202  Vector const & j_xyz = rsd2.xyz(j);
203 
204  // Loop over potential ligand positions.
205  Size const pos1 = rsd1.seqpos();
206 
207  // These should be filled in during a pre-scoring step (setup_info_for_mg_calculation ).
209  atom_numbers_for_mg_calculation( rna_scoring_info.atom_numbers_for_mg_calculation() );
210  utility::vector1< Size > const & atom_numbers1 ( atom_numbers_for_mg_calculation[ pos1 ] );
211 
212 
213  // apply angle cut.
214  bool const apply_angle_potential_( true );
215 
216  //Distance const direct_interaction_cutoff_( 4.0 ), indirect_interaction_cutoff_( 8.0 );
217  Distance const direct_interaction_cutoff_( 999.0 ), indirect_interaction_cutoff_( 999.0 );
218 
219  // direct interactions, including special non-pair-wise handling of phosphate oxygens
220  utility::vector1< Real > phosphate_scores;
221  bool is_phosphate_oxygen( false );
222  for ( Size m = 1; m <= atom_numbers1.size(); ++m ) {
223 
224  Size const i = atom_numbers1[ m ];
225  if (rsd1.is_virtual(i) ) continue;
226  Vector const & i_xyz( rsd1.xyz(i) );
227 
228  Distance d = ( i_xyz - j_xyz ).length();
229 
230  Gaussian_parameter const & mg_potential_gaussian_parameter = rna_mg_knowledge_based_potential_->get_mg_potential_gaussian_parameter( rsd1, i, is_phosphate_oxygen );
231 
232  Real cos_theta( -999.0 );
233  bool get_angle_form_factor = false;
234  if ( apply_angle_potential_ && ( rsd1.heavyatom_is_an_acceptor( i ) || rsd1.atom_type( i ).name() == "Hpol" ) ) get_angle_form_factor = true;
235 
236  if ( d < direct_interaction_cutoff_ && mg_potential_gaussian_parameter.center > 0.0 ){
237 
238  Real binding_score = get_gaussian_potential_score( mg_potential_gaussian_parameter, i_xyz, j_xyz );
239 
240  if ( get_angle_form_factor ){
241  cos_theta = get_cos_theta( rsd1, i, i_xyz, j_xyz );
242  Gaussian_parameter const & mg_potential_costheta_gaussian_parameter = rna_mg_knowledge_based_potential_->get_mg_potential_costheta_gaussian_parameter( rsd1, i );
243  Real const angle_potential = get_gaussian_score( mg_potential_costheta_gaussian_parameter, cos_theta );
244  binding_score *= angle_potential;
245  }
246 
247  if ( verbose_ && std::abs(binding_score) > 0.1 ) tr << "Mg " << rsd2.seqpos() << " direct to ligand " << pos1 << ' ' << rsd1.atom_name(i) << " cos_angle " << cos_theta << " score: " << binding_score << std::endl;
248 
249  if (is_phosphate_oxygen) {
250  phosphate_scores.push_back( binding_score ); // will get added in later
251  } else {
252  score += binding_score;
253  }
254  }
255 
256 
257  // indirect interactions, simple pair-wise
258  Gaussian_parameter const & mg_potential_indirect_gaussian_parameter = rna_mg_knowledge_based_potential_->get_mg_potential_indirect_gaussian_parameter( rsd1, i );
259 
260  if ( d < indirect_interaction_cutoff_ && mg_potential_indirect_gaussian_parameter.center > 0.0 ){
261 
262  if ( mg_potential_indirect_gaussian_parameter.center > 0.0 ){
263  Real binding_score_indirect = get_gaussian_potential_score( mg_potential_indirect_gaussian_parameter, i_xyz, j_xyz );
264 
265  if ( get_angle_form_factor ){
266 
267  if ( cos_theta < -1.0 ) cos_theta = get_cos_theta( rsd1, i, i_xyz, j_xyz );
268 
269  Gaussian_parameter const & mg_potential_costheta_indirect_gaussian_parameter = rna_mg_knowledge_based_potential_->get_mg_potential_costheta_indirect_gaussian_parameter( rsd1, i );
270  Real const angle_potential_indirect = get_gaussian_score( mg_potential_costheta_indirect_gaussian_parameter, cos_theta );
271  binding_score_indirect *= angle_potential_indirect;
272 
273  }
274  score_indirect += binding_score_indirect;
275 
276  if ( verbose_ && std::abs(binding_score_indirect) > 0.1 ) tr << "Mg " << rsd2.seqpos() << " indirect to ligand " << pos1 << ' ' << rsd1.atom_name(i) << " score: " << binding_score_indirect << std::endl;
277 
278  }
279  }
280 
281 
282  }
283 
284  // there appear to be very few (if any) metal ions that bind to both the O1P and O2P of a single phosphate -- so let's use the best of those scores.
285  if ( phosphate_scores.size() == 1 ) phosphate_scores.push_back( 0.0 );
286 
287  if ( phosphate_scores.size() > 1 ){
288  runtime_assert( phosphate_scores.size() == 2 ); // O1P and O2P
289  score += std::min( phosphate_scores[1], phosphate_scores[2] );
290  }
291 
292  emap[ rna_mg ] += score;
293 
294  emap[ rna_mg_indirect ] += score_indirect;
295 
296 
297 }
298 
299 
300 /////////////////////////////////
301 Real
303  Gaussian_parameter const & mg_potential_gaussian_parameter,
304  Vector const & pos1,
305  Vector const & pos2 ) const
306 { // later expand to do derivative calculation
307 
308  Distance const d = ( pos1 - pos2 ).length();
309 
310  return get_gaussian_score( mg_potential_gaussian_parameter, d );
311 }
312 
313 ///////////////////////////////////////////////////
314 Real
316  Gaussian_parameter const & mg_potential_gaussian_parameter,
317  Real const d) const
318 { // later expand to do derivative calculation
319 
320  Real const a = mg_potential_gaussian_parameter.amplitude;
321  Real const d0 = mg_potential_gaussian_parameter.center;
322  Real const sigma = mg_potential_gaussian_parameter.width;
323 
324  Real const score = a * exp( -0.5 * std::pow( ( d - d0 )/sigma, 2 ) );
325  return score;
326 }
327 
328 /////////////////////////////////
329 void
331  id::AtomID const & /*atom_id*/,
332  pose::Pose const & /*pose*/,
333  kinematics::DomainMap const & /*domain_map*/,
334  ScoreFunction const &,
335  EnergyMap const & /*weights*/,
336  Vector & /*F1*/,
337  Vector & /*F2*/
338  ) const
339 {
340  // NEED TO FILL THIS IN LATER!!
341 }
342 
343 
344 
345 /// @brief RNA_Mg_Energy distance cutoff
346 Distance
348 {
349  return 6.0;
350 }
351 
352 /// @brief RNA_Mg_Energy
353 void
355 {
356 }
357 
360 {
361  return 1; // Initial versioning
362 }
363 
364 
365 }
366 }
367 }