Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RNA_LowResolutionPotential.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/RNA_LowResolutionPotential.cc
11 /// @brief Statistically derived rotamer pair potential class implementation
12 /// @author Rhiju Das
13 
14 // Unit headers
16 
17 // Package headers
20 
21 // Project headers
22 #include <core/chemical/AA.hh>
23 // AUTO-REMOVED #include <core/chemical/VariantType.hh>
28 #include <basic/database/open.hh>
29 #include <core/pose/Pose.hh>
30 
36 
37 #include <core/scoring/Energies.hh>
39 
40 // Utility headers
41 #include <utility/io/izstream.hh>
42 // AUTO-REMOVED #include <utility/utility.functions.hh>
43 
44 #include <ObjexxFCL/FArray2A.hh>
45 
46 #include <numeric/conversions.hh>
47 #include <numeric/xyzMatrix.hh>
48 // AUTO-REMOVED #include <numeric/xyz.functions.hh>
49 #include <numeric/interpolation/periodic_range/full/interpolation.hh>
50 
51 // C++
52 
53 #include <basic/Tracer.hh>
54 
55 #include <core/id/AtomID.hh>
56 #include <utility/vector1.hh>
57 #include <ObjexxFCL/format.hh>
58 
59 
60 static basic::Tracer tr( "core.scoring.rna.RNA_LowResolutionPotential" );
61 
62 namespace core {
63 namespace scoring {
64 namespace rna{
65 
67 
69 
70 using namespace ObjexxFCL;
71 using namespace ObjexxFCL::fmt;
72 
73 // Hey should we define a copy constructor and a clone()?
74 
75 //////////////////////////////////////////////////////////////////////////////////////
76 //////////////////////////////////////////////////////////////////////////////////////
78  ////////////////////////////////////////////
79  rna_basepair_radius_cutoff_( 8.0 ),
80  rna_basepair_stagger_cutoff_( 3.0 ),
81  rna_basepair_radius_cutoff2_( rna_basepair_radius_cutoff_ * rna_basepair_radius_cutoff_) , // 64.0
82  basepair_xy_bin_width_( 2.0 ),
83  basepair_xy_num_bins_( 10 ),
84  basepair_xy_table_size_( 10 ),
85  basepair_xy_z_fade_zone_( 0.5 ),
86  ////////////////////////////////////////////
87  base_stack_min_height_( 2.4 ),
88  base_stack_max_height_( 6.0 ),
89  base_stack_radius_( 4.0 ),
90  base_stack_radius2_( base_stack_radius_ * base_stack_radius_ ),
91  base_stack_z_fade_zone_( 0.5 ),
92  base_stack_rho_fade_zone_( 0.5 ),
93  ////////////////////////////////////////////
94  axis_bin_width_( 0.2 ),
95  axis_num_bins_ ( 11 ),
96  ////////////////////////////////////////////
97  stagger_num_bins_( 11 ),
98  stagger_bin_width_( 0.4 ),
99  stagger_distance_cutoff_( 2.0 ),
100  ////////////////////////////////////////////
101  base_backbone_bin_width_( 1.0 ),
102  base_backbone_num_bins_( 16 ),
103  base_backbone_table_size_( 8 ),
104  base_backbone_distance_cutoff_ ( 12.0 ),
105  base_backbone_z_cutoff_ ( 2.0 ),
106  base_backbone_rho_cutoff_( 8.0 ),
107  base_backbone_atom_dist_cutoff_( 4.0 ),
108  base_backbone_z_fade_zone_( 0.25 ),
109  base_backbone_rho_fade_zone_( 0.5 ),
110  base_backbone_check_atom_neighbor_( false ), /*doesn't seem compatible with deriv*/
111  ////////////////////////////////////////////
112  backbone_backbone_bin_width_( 0.25 ),
113  backbone_backbone_distance_cutoff_ ( 6.0 ),
114  backbone_backbone_num_bins_ ( 20 ),
115  ////////////////////////////////////////////
116  rna_repulsive_max_penalty_( 8.0 ),
117  rna_repulsive_screen_scale_( 2.5 ),
118  rna_repulsive_distance_cutoff_( 8.0 ),
119  rna_repulse_all_( true ),
120  num_RNA_base_pair_orientations_( 2 ), /*parallel/anti*/
121  num_RNA_backbone_oxygen_atoms_( 6 ), /*backbone oxygens*/
122  num_RNA_res_types_( 4 ),/*a/c/g/u*/
123  o2star_index_within_special_backbone_atoms_( 6 ),
124  o2p_index_within_special_backbone_atoms_( 2 ),
125  interpolate_( true ), //Turn this off to match Rosetta++, up to bug fixes; turn it on to allow correct derivative calculation.
126  fade_( true ), //Turn this off to match Rosetta++; needed to prevent hard boundaries in base pairing + stacking potentials.
127  rna_verbose_( false ),
128  more_precise_base_pair_classification_( false )
129 {
130  // These don't *have* to be hard-wired numbers.
131  // if we're more clever about the file read-in.
132  // For now, just copy what was in Rosetta++.
134  rna_axis_.dimension( axis_num_bins_ );
135  rna_stagger_.dimension( stagger_num_bins_ );
140 
143 
144  rna_basepair_xy_ = 0.0;
145  rna_axis_ = 0.0;
146  rna_stagger_ = 0.0;
147  rna_base_backbone_xy_ = 0.0;
149  rna_repulsive_weight_ = 0.0;
150 
161 
162 }
163 
164 
165 ////////////////////////////////////////////////////////////////////////////////////////
166 void
168 
169  std::string const filename( "chemical/rna/rna_base_pair_xy.dat" );
170  utility::io::izstream data_stream( basic::database::full_name( filename ) );
171 
172  if ( !data_stream ) {
173  std::cerr << "Can't find specified basepair potential file: " << filename << std::endl;
174  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
175  return;
176  }
177 
178  std::cout << "Reading basepair x-y potential file: " << filename << std::endl;;
179  // read data
180  Size res1, res2, xbin, ybin, direction;
181  Real potential;
182  while ( data_stream >> xbin ) {
183  data_stream >> ybin >> res1 >> res2 >> direction >> potential >> skip ;
184  rna_basepair_xy_( xbin, ybin, res1 , res2, direction) = potential;
185  }
186 
187  std::cout << "Finished reading basepair x-y potential file: " << filename << std::endl;;
188 
189  //close file
190  data_stream.close();
191 }
192 
193 ////////////////////////////////////////////////////////////////////////////////////////
194 // Uh, should put this in a file.
195 void
197  rna_axis_( 1 ) = -3.319;
198  rna_axis_( 2 ) = -0.938;
199  rna_axis_( 3 ) = 0.000;
200  rna_axis_( 4 ) = 0.000;
201  rna_axis_( 5 ) = 0.000;
202  rna_axis_( 6 ) = -0.309;
203  rna_axis_( 7 ) = -0.748;
204  rna_axis_( 8 ) = -1.559;
205  rna_axis_( 9 ) = -2.576;
206  rna_axis_( 10 ) = -3.478;
207  rna_axis_( 11 ) = -3.529;
208 }
209 
210 
211 ///////////////////////////////////////////////////////////////////////////////////////
212 // Uh, should put this in a file.
213 void
215  rna_stagger_( 1 ) = 0.000;
216  rna_stagger_( 2 ) = 0.000;
217  rna_stagger_( 3 ) = -0.062;
218  rna_stagger_( 4 ) = -1.174;
219  rna_stagger_( 5 ) = -2.085;
220  rna_stagger_( 6 ) = -2.897;
221  rna_stagger_( 7 ) = -2.496;
222  rna_stagger_( 8 ) = -2.253;
223  rna_stagger_( 9 ) = -1.156;
224  rna_stagger_( 10 ) = -0.461;
225  // rna_stagger_( 11 ) = -0.354;
226  // This needs to asymptote to zero, or derivatives don't look so nice.
227  rna_stagger_( 11 ) = 0.000;
228 }
229 
230 
231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
232 void
234 
236  RNA_backbone_oxygen_atoms_.push_back( " O1P");
237  RNA_backbone_oxygen_atoms_.push_back( " O2P");
238  RNA_backbone_oxygen_atoms_.push_back( " O5*");
239  RNA_backbone_oxygen_atoms_.push_back( " O4*");
240  RNA_backbone_oxygen_atoms_.push_back( " O3*");
241  RNA_backbone_oxygen_atoms_.push_back( " O2*");
242 
243  //Useful for preventing string lookups:
246 
247 
248 }
249 
250 ////////////////////////////////////////////////////////////////////////////////////////
251 void
253 
254  std::string const filename ( "chemical/rna/rna_base_backbone_xy.dat" );
255 
256  // open file
257  utility::io::izstream data_stream( basic::database::full_name( filename ) );
258 
259  if ( !data_stream ) {
260  std::cerr << "Can't find specified non-base-base potential file: " << filename << std::endl;
261  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
262  return;
263  }
264 
265  std::cout << "Reading non-base-base x-y potential file: " << filename << std::endl;;
266  // read data
267  Size res1, xbin, ybin, atomindex;
268  Real potential;
269  while ( data_stream >> xbin ) {
270  data_stream >> ybin >> res1 >> atomindex >> potential >> skip ;
271  rna_base_backbone_xy_( xbin, ybin, res1 , atomindex) = potential;
272  }
273 
274  //close file
275  data_stream.close();
276 }
277 
278 ///////////////////////////////////////////////////////////////////////////////
279 void
281  rna_backbone_backbone_weight_.dimension( 6 );
283 
284  rna_backbone_backbone_weight_( 1 ) = 1.0; // O1P
285  rna_backbone_backbone_weight_( 2 ) = 1.0; // O2P
286  rna_backbone_backbone_weight_( 6 ) = 2.0; // O2*
287 }
288 
289 
290 //////////////////////////////////////////////////////////////////////////////////
291 void
293 {
294 
295  std::string const filename = "chemical/rna/rna_backbone_backbone.dat";
296 
297  // open file
298  utility::io::izstream data_stream( basic::database::full_name( filename ) );
299 
300  if ( !data_stream ) {
301  std::cerr << "Can't find specified RNA backbone-backbone potential file: " << filename << std::endl;
302  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
303  return;
304  }
305 
306  std::cout << "Reading RNA backbone backbone potential file: " << filename << std::endl;;
307  // read data
308  Size rbin;
309  Real r1,r2,potential;
310  while ( data_stream >> r1 ) {
311  data_stream >> r2 >> rbin >> potential >> skip ;
312  rna_backbone_backbone_potential_( rbin ) = potential;
313  }
314 
315  //close file
316  data_stream.close();
317 }
318 
319 
320 ///////////////////////////////////////////////////////////////////////////////
321 void
323 
324  // Note that unless specified by user "-rna_phosphate_repulse_all"
325  // only O2P-O2P repulsion will be calculated. See eval_rna_phosphate_score().
326  rna_repulsive_weight_( 1 ) = 1.0; // O1P
327  rna_repulsive_weight_( 2 ) = 1.0; // O2P
328  rna_repulsive_weight_( 3 ) = 1.0; // O5*
329  rna_repulsive_weight_( 4 ) = 1.0; // O4*
330  rna_repulsive_weight_( 5 ) = 1.0; // O3*
331  // O2* --> weight stays at zero.
332 }
333 
334 ///////////////////////////////////////////////////////////////////////////////
335 ///////////////////////////////////////////////////////////////////////////////
336 ///////////////////////////////////////////////////////////////////////////////
337 Real
339  Distance const x,
340  Distance const y,
341  Distance const z, // used in fading
342  Real const cos_theta,
343  conformation::Residue const & res_i,
344  conformation::Residue const & res_j,
345  bool const update_deriv /* = true */,
346  Real & deriv_x,
347  Real & deriv_y,
348  Real & deriv_z ) const
349 {
350  Size const theta_bin = (cos_theta < 0) ? 1 : 2;
351 
352  assert( res_i.is_RNA() );
353  assert( res_j.is_RNA() );
354 
355  Size const res_i_bin = convert_acgu_to_1234( res_i.name1() );
356  Size const res_j_bin = convert_acgu_to_1234( res_j.name1() );
357 
358  assert( res_i_bin > 0);
359  assert( res_j_bin > 0);
360 
361  Real value( 0.0 );
362  deriv_x = 0.0;
363  deriv_y = 0.0;
364  deriv_z = 0.0;
365 
366  if ( interpolate_ ) {
367  Real interpolate_value( 0.0 );
368  FArray2A< Real >::IR const zero_index( 0, basepair_xy_num_bins_ - 1);
369  ObjexxFCL::FArray2A< Real > const rna_basepair_xy_for_res_res( rna_basepair_xy_( 1, 1, theta_bin, res_i_bin, res_j_bin ), zero_index, zero_index );
370  using namespace numeric::interpolation::periodic_range::full;
371 
372  if ( update_deriv ) {
373  interpolate_value = bilinearly_interpolated(
378  rna_basepair_xy_for_res_res,
379  deriv_x, deriv_y );
380  } else {
381  interpolate_value = bilinearly_interpolated(
386  rna_basepair_xy_for_res_res );
387  }
388  // std::cout << "BASE_BASE: " << x << " " << y << " ==> " << value << " " << interpolate_value << std::endl;
389 
390  value = interpolate_value;
391 
392  } else { // old Rosetta++-style, no interpolation
393  Size x_bin, y_bin;
394 
395  x_bin = Size( (x + basepair_xy_table_size_) / basepair_xy_bin_width_ ) + 1;
396  y_bin = Size( (y + basepair_xy_table_size_) / basepair_xy_bin_width_ ) + 1;
397 
398  if (x_bin < 1 ) x_bin = 1;
399  if (y_bin < 1 ) y_bin = 1;
400  if (x_bin > basepair_xy_table_size_ ) x_bin = basepair_xy_table_size_;
401  if (y_bin > basepair_xy_table_size_ ) y_bin = basepair_xy_table_size_;
402 
403  value = rna_basepair_xy_( x_bin, y_bin, theta_bin, res_i_bin, res_j_bin );
404 
405  }
406 
407  if ( fade_ ) {
408  Real fade_value( 1.0 ), fade_deriv( 0.0 );
409 
410  //First do z correction
412  basepair_xy_z_fade_zone_ /* 0.5 */, fade_value, fade_deriv );
413 
414  // std::cout << "BASE_BASE: " << x << " " << y << " ==> " << value << " " << fade_value;
415 
416  deriv_x = deriv_x * fade_value;
417  deriv_y = deriv_y * fade_value;
418  deriv_z = value * fade_deriv;
419  value *= fade_value;
420 
421  // Now rho fading ( radial ).
422  Distance const rho = std::sqrt( x*x + y*y );
423  if ( rho > 0.0 ) { //better be!
425  base_stack_rho_fade_zone_ /* 0.5 */, fade_value, fade_deriv );
426 
427  // std::cout << " RHO_FADE " << fade_value << std::endl;
428 
429  deriv_x = fade_value * deriv_x + value * fade_deriv * ( x / rho ) ;
430  deriv_y = fade_value * deriv_y + value * fade_deriv * ( y / rho );
431  deriv_z *= fade_value;
432  value *= fade_value;
433 
434  }
435 
436  }
437 
438  return value;
439 }
440 
441 
442 
443 
444 /////////////////////////////////////////////////////////////////////////////////////////////////////////
445 Real
447  Distance const x, // used in fading
448  Distance const y, // used in fading
449  Distance const z, // used in fading
450  Real & deriv_x,
451  Real & deriv_y,
452  Real & deriv_z ) const
453 {
454  // In Rosetta++, this was just a constant.
455  Real value( -0.5 );
456  deriv_x = 0.0;
457  deriv_y = 0.0;
458  deriv_z = 0.0;
459 
460  if ( fade_ ) {
461  // First do z-fading.
462  Real fade_value( 1.0 ), fade_deriv( 0.0 );
463  if ( z > 0 ) {
465  base_stack_z_fade_zone_ /* 0.5 */, fade_value, fade_deriv );
466  } else {
468  base_stack_z_fade_zone_ /* 0.5 */, fade_value, fade_deriv );
469  }
470 
471  deriv_z = value * fade_deriv;
472  value *= fade_value;
473 
474  // Now rho fading ( radial ).
475  Distance const rho = std::sqrt( x*x + y*y );
476  if ( rho > 0.0 ) { //better be!
478  base_stack_rho_fade_zone_ /* 0.5 */, fade_value, fade_deriv );
479  deriv_x = value * fade_deriv * ( x / rho ) ;
480  deriv_y = value * fade_deriv * ( y / rho );
481  deriv_z *= fade_value;
482  value *= fade_value;
483  }
484 
485  }
486 
487  return value;
488 }
489 
490 
491 
492 ///////////////////////////////////////////////////////////////////////////////
493 //Following could be part of its own class...
494 Real
496  Real const cos_theta,
497  Real & deriv ) const{
498 
499  Size cos_theta_bin;
500  // cos_theta_bin = static_cast<int> ( ( cos_theta + 1.0f)/ axis_bin_width_ ) + 1;
501  // Note that above, which was in Rosetta++ is slightly off.
502  // Bin boundaries are [-1.1,-0.9], [-0.9,-0.7], ... [0.9,1.1]. So should be:
503  cos_theta_bin = static_cast<int> ( ( cos_theta + 1.1f)/ axis_bin_width_ ) + 1;
504 
505  Real value ( 0.0 );
506 
507  if (interpolate_ ) {
508  Real interpolate_value( 0.0 );
509  //interpolate_value_and_deriv( rna_axis_, axis_bin_width_, cos_theta + 1.0, interpolate_value, deriv );
510  interpolate_value_and_deriv( rna_axis_, axis_bin_width_, cos_theta + 1.1, interpolate_value, deriv );
511  value = interpolate_value;
512  //std::cout << "AXIS: " << F(8,3,cos_theta) << " " << F(8,3,value) << " vs. " << F(8,3,interpolate_value ) << std::endl;
513  } else {
514  assert( cos_theta_bin > 0 && cos_theta_bin <= axis_num_bins_ );
515  value = rna_axis_( cos_theta_bin );
516  }
517  return value;
518 }
519 
520 ///////////////////////////////////////////////////////////////////////////////
521 //Following could be part of its own class...
522 Real
524 {
525 
526  Real value( 0.0 );
527  deriv = 0.0;
528 
529 
530  //////////////////////////////////////////////////////////////////////////////////////////
531  // SILLY HACK -- no the problem isn't here.
532  //deriv = 2 * height;
533  //return height * height;
534  //////////////////////////////////////////////////////////////////////////////////////////
535 
536  if ( std::abs( height ) > stagger_distance_cutoff_ ) return 0.0;
537 
538  if ( interpolate_ ) {
539  interpolate_value_and_deriv( rna_stagger_, stagger_bin_width_, height+2.2, value, deriv );
540  // std::cout << "STAGGER: " << F(8,3,height) << " " << F(8,3,value) << " " << F(8,3,interpolate_value) << std::endl;
541  } else {
542  //Following, from Rosetta++, is slightly off. Bins are at [-2.2,-1.8],[-1.8,-1.6],...[1.8,2.2]
543  // Size height_bin = static_cast<int> ( (height + 2.0)/ stagger_bin_width_ ) + 1;
544  Size height_bin = static_cast<int> ( (height + 2.2)/ stagger_bin_width_ ) + 1;
545  if ( height_bin < 1 || height_bin > stagger_num_bins_ ) height_bin = 1;
546  value = rna_stagger_( height_bin );
547  }
548 
549  return value;
550 }
551 
552 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
553 Real
555  Distance const x,
556  Distance const y,
557  Distance const z,
558  conformation::Residue const & res_i,
559  Size const & atom_num_j_bin,
560  bool const update_deriv /* = false */,
561  Real & deriv_x /* = dummy_deriv */,
562  Real & deriv_y /* = dummy_deriv */,
563  Real & deriv_z /* = dummy_deriv */) const
564 {
565 
566  Real value( 0.0 );
567  deriv_x = 0.0;
568  deriv_y = 0.0;
569  deriv_z = 0.0;
570 
571  Size const res_i_bin = convert_acgu_to_1234( res_i.name1() );
572 
573  assert( res_i_bin > 0);
574  assert( atom_num_j_bin > 0);
575 
576  if ( interpolate_ ) {
577  // Real interpolate_value( 0.0 );
578  FArray2A< Real >::IR const zero_index( 0, base_backbone_num_bins_ - 1);
579  ObjexxFCL::FArray2A< Real > const rna_base_backbone_xy_for_res_atom( rna_base_backbone_xy_( 1, 1, res_i_bin, atom_num_j_bin ), zero_index, zero_index );
580  using namespace numeric::interpolation::periodic_range::full;
581 
582  if ( update_deriv || true ) {
583  value = bilinearly_interpolated(
588  rna_base_backbone_xy_for_res_atom,
589  deriv_x, deriv_y );
590  } else {
591  value = bilinearly_interpolated(
596  rna_base_backbone_xy_for_res_atom );
597  }
598  // value = interpolate_value;
599  } else { //old school.
600  Size x_bin, y_bin;
601  x_bin = Size( (x + base_backbone_table_size_) ) + 1;
602  y_bin = Size( (y + base_backbone_table_size_) ) + 1;
603 
604  if (x_bin < 1 ) x_bin = 1;
605  if (y_bin < 1 ) y_bin = 1;
606  if (x_bin > 2 * base_backbone_table_size_) x_bin = 2 * base_backbone_table_size_;
607  if (y_bin > 2 * base_backbone_table_size_) y_bin = 2 * base_backbone_table_size_;
608 
609  value = rna_base_backbone_xy_( x_bin, y_bin, res_i_bin, atom_num_j_bin );
610  }
611 
612 
613  if ( fade_ ) {
614  Real fade_value( 1.0 ), fade_deriv( 0.0 );
615 
616  //First do z correction
618  base_backbone_z_fade_zone_ /* 0.5 */, fade_value, fade_deriv );
619 
620  deriv_x = deriv_x * fade_value;
621  deriv_y = deriv_y * fade_value;
622  deriv_z = value * fade_deriv;
623  value *= fade_value;
624 
625  // std::cout << "BASE_BACKBONE_Z_FADE: " << z << " " << base_backbone_z_cutoff_ << " " << base_backbone_z_fade_zone_ << " ==> " << fade_value << std::endl;
626 
627  // Now rho fading ( radial ).
628  Distance const rho = std::sqrt( x*x + y*y );
629  if ( rho > 0.0 ) { //better be!
631  base_backbone_rho_fade_zone_ /* 0.5 */, fade_value, fade_deriv );
632 
633  deriv_x = fade_value * deriv_x + value * fade_deriv * ( x / rho ) ;
634  deriv_y = fade_value * deriv_y + value * fade_deriv * ( y / rho );
635  deriv_z *= fade_value;
636  value *= fade_value;
637 
638  // std::cout << "BASE_BACKBONE_RHO_FADE: " << rho << " " << base_backbone_rho_cutoff_ << " " << base_backbone_rho_fade_zone_ << " ==> " << fade_value << std::endl;
639  }
640 
641  }
642 
643 
644  // std::cout << "BASE_BACKBONE: " << x << " " << y << " ==> " << value << " " << interpolate_value << std::endl;
645 
646  return value;
647 }
648 
649 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
650 Real
652  Distance const & r,
653  Size const & atom_num_j_bin,
654  Real & deriv /* = 0.0 */
655 ) const
656 {
657 
658  Real value( 0.0 );
659  deriv = 0.0;
660 
661  if ( interpolate_ ) {
663  } else {
664  Size const bin = static_cast< Size> ( r/ backbone_backbone_bin_width_ ) + 1;
666  }
667 
668  value *= rna_backbone_backbone_weight_( atom_num_j_bin );
669  deriv *= rna_backbone_backbone_weight_( atom_num_j_bin );
670 
671  // if ( value < 0.0 ) {
672  // std::cout << "RNA_BACKBONE_BACKBONE: " << value << ". R: " << r << " ATOMNUM: " <<
673  // atom_num_j_bin << std::endl;
674  // }
675 
676  return value;
677 }
678 
679 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
680 Real
682  Distance const & r,
683  Size const & atom_num_j_bin,
684  Real & deriv /* = 0.0 */ ) const
685 {
686 
687  static Real const rna_repulsive_max_penalty_ = 8.0; //In kT.
688  static Real const rna_repulsive_screen_scale_ = 2.5; //In Angstroms
689  static Real const rna_repulsive_distance_cutoff_ = 8.0; //In Angstroms
690 
691  static Real offset = rna_repulsive_max_penalty_ * exp( -1.0 * rna_repulsive_distance_cutoff_ / rna_repulsive_screen_scale_ );
692 
693  deriv = 0.0;
694  if (r < rna_repulsive_distance_cutoff_ ){
695  Real potential = rna_repulsive_max_penalty_ * exp( -1.0 * r/ rna_repulsive_screen_scale_ ) - offset;
696  deriv = -1.0 * (rna_repulsive_max_penalty_ / rna_repulsive_screen_scale_ ) *
697  exp( -1.0 * r/ rna_repulsive_screen_scale_ );
698 
699  potential *= rna_repulsive_weight_( atom_num_j_bin );
700  deriv *= rna_repulsive_weight_( atom_num_j_bin );
701 
702  return potential;
703  }
704 
705  return 0.0;
706 
707 }
708 
709 
710 ///////////////////////////////////////////////////////////////////////////////
711 void
713  pose::Pose & pose
714 ) const
715 {
717  rna::RNA_CentroidInfo & rna_centroid_info( rna_scoring_info.rna_centroid_info() );
718  //Doesn't recalculate stuff if already updated:
719  rna_centroid_info.update( pose );
720 }
721 
722 ///////////////////////////////////////////////////////////////////////////////
723 // DEPRECATED?
724 void
726  pose::Pose & pose
727 ) const
728 {
729 
730  // If we want to play some cache-ing tricks later...
731  // FArray2D_bool const & pair_moved( pose.get_pair_moved() );
732 
734  rna::RNA_CentroidInfo & rna_centroid_info( rna_scoring_info.rna_centroid_info() );
735  //Doesn't recalculate stuff if already updated:
736  rna_centroid_info.update( pose );
737 
738  utility::vector1< Vector > const & base_centroids( rna_centroid_info.base_centroids() );
739  utility::vector1< kinematics::Stub > const & base_stubs( rna_centroid_info.base_stubs() );
740 
741 
742  // Real const Z_CUTOFF( 2.5 );
743 
744  Size const total_residue = pose.total_residue();
745 
746  rna::RNA_RawBaseBaseInfo & rna_raw_base_base_info( rna_scoring_info.rna_raw_base_base_info() );
747  rna_raw_base_base_info.resize( total_residue );
748  // if (rna_raw_base_base_info.calculated()) return;
749 
750  ObjexxFCL::FArray3D< Real > & base_pair_array( rna_raw_base_base_info.base_pair_array() );
751  ObjexxFCL::FArray3D< Real > & base_axis_array( rna_raw_base_base_info.base_axis_array() );
752  ObjexxFCL::FArray3D< Real > & base_stagger_array( rna_raw_base_base_info.base_stagger_array() );
753  ObjexxFCL::FArray2D< Real > & base_stack_array( rna_raw_base_base_info.base_stack_array() );
754  ObjexxFCL::FArray2D< Real > & base_stack_axis_array( rna_raw_base_base_info.base_stack_axis_array() );
755  ObjexxFCL::FArray2D< Real > & base_geometry_orientation_array( rna_raw_base_base_info.base_geometry_orientation_array() );
756  ObjexxFCL::FArray2D< Real > & base_geometry_height_array( rna_raw_base_base_info.base_geometry_height_array() );
757 
758  //Following may change in the future, if we
759  // decide to take advantage of "pair_moved" arrays to
760  // prevent recalculation of energy terms.
761  base_pair_array = 0.0;
762  base_stagger_array = 0.0;
763  base_axis_array = 0.0;
764  base_stack_array = 0.0;
765  base_stack_axis_array = 0.0;
766  base_geometry_orientation_array = 0.0;
767  base_geometry_height_array = 0.0;
768 
769  EnergyGraph const & energy_graph( pose.energies().energy_graph() );
770 
771  //Main loop
772  // NOTE: Following evaluates each base pair from both sides, because base pair
773  // terms are asymmetric in i<->j. So loop is over all neighbors!
774  for (Size i = 1; i <= total_residue; i++ ){
775  conformation::Residue const & res_i( pose.residue( i ) );
776 
777  if ( !res_i.is_RNA() ) continue;
778 
779  //Note that this centroid and stubs could be calculated once at the beginning of the scoring!!!
780  Vector const & centroid_i( base_centroids[i] );
781  kinematics::Stub const & stub_i( base_stubs[i] );
782  Matrix const & M_i( stub_i.M );
783  Vector const & x_i = M_i.col_x();
784  Vector const & y_i = M_i.col_y();
785  Vector const & z_i = M_i.col_z();
786 
788  iter = energy_graph.get_node( i )->const_edge_list_begin();
789  iter != energy_graph.get_node( i )->const_edge_list_end();
790  ++iter ){
791 
792  Size j( (*iter)->get_other_ind( i ) );
793 
794  // if ( !pair_moved(i,j) && rna_array_state_ok ) continue;
795 
796  conformation::Residue const & res_j( pose.residue( j ) );
797  if ( !res_j.is_RNA()) continue;
798 
799  Vector const & centroid_j( base_centroids[j] );
800  kinematics::Stub const & stub_j( base_stubs[j] );
801 
802  Vector d_ij = centroid_j - centroid_i;
803  Real const dist_x = dot_product( d_ij, x_i );
804  Real const dist_y = dot_product( d_ij, y_i );
805  Real const dist_z = dot_product( d_ij, z_i );
806  Real const rho2 = dist_x*dist_x + dist_y*dist_y;
807 
808  //This could all be precomputed, actually.
809  Matrix const & M_j( stub_j.M );
810  // Vector const & x_j = M_j.col_x();
811  // Vector const & y_j = M_j.col_y();
812  Vector const & z_j = M_j.col_z();
813  Real const cos_theta = dot_product( z_i, z_j );
814  //This arc-cosine costs a lot actually:
815  // Real const theta = numeric::conversions::degrees( numeric::arccos( cos_theta ) );
816 
817  //Is it a base-pair, a base-stack, or do we ignore it?
818  Size edge_bin( 1 );
819  if ( ( std::abs(dist_z) < rna_basepair_stagger_cutoff_ ) ){
820  //A possible base pair
821  if ( rho2 < rna_basepair_radius_cutoff2_ ){
822  //BASE PAIR
823  Real temp_rna_bp_score( 0.0 );
824 
825  temp_rna_bp_score = get_rna_basepair_xy(dist_x, dist_y, dist_z, cos_theta, res_i, res_j);
826 
827  // Some of the base pairing scores are 0.0. By default, pad by
828  // a tiny tiny amount to make sure that they're still
829  // counted as very weak base pairs during later book-keeping.
830  temp_rna_bp_score -= 0.0001;
831 
832  Real zeta_hoogsteen_cutoff( 60.0 ), zeta_sugar_cutoff( -60.0 );
833  get_zeta_cutoff( res_i, zeta_hoogsteen_cutoff, zeta_sugar_cutoff );
834 
835  Real const zeta = numeric::conversions::degrees( std::atan2( dist_y, dist_x) );
836  if ( zeta < zeta_hoogsteen_cutoff && zeta > zeta_sugar_cutoff ) edge_bin = WATSON_CRICK; //Watson-Crick edge
837  else if ( zeta > zeta_hoogsteen_cutoff ) edge_bin = HOOGSTEEN; // Hoogsteen edge
838  else edge_bin = SUGAR; // Sugar edge
839 
840  if ( rna_verbose_ ){
841  Real const theta = numeric::conversions::degrees( numeric::arccos( cos_theta ) );
842  std::cout << " Possible base pair: "
843  << res_i.name3() << I(3,i) << "-"
844  << res_j.name3() << I(3,j)
845  << " edge: " << I(1,edge_bin)
846  << " dists " << F(4,2,dist_x)
847  << " " << F(4,2,dist_y)
848  << " " << F(4,2,dist_z)
849  << " theta " << F(5,1, theta)
850  << "; rho " << F(4,2, std::sqrt( rho2) )
851  << "; zeta " << F(4,2, zeta )
852  << "; zeta_cut " << F(4,2, zeta_hoogsteen_cutoff )
853  << " : SCORE " << F(6,4,temp_rna_bp_score)
854  // << " " << get_rna_axis_score( theta) << " " << get_rna_stagger_score( dist_z )
855  << std::endl;
856  }
857 
858  base_pair_array ( i, j, edge_bin ) = temp_rna_bp_score;
859  base_axis_array ( i, j, edge_bin ) = get_rna_axis_score( cos_theta );
860  base_stagger_array ( i, j, edge_bin ) = get_rna_stagger_score( dist_z );
861 
862  }
863  }
864 
865  if ( std::abs(dist_z) >= base_stack_min_height_ &&
866  std::abs(dist_z) <= base_stack_max_height_ &&
867  rho2 < base_stack_radius2_ ) {
868  //Possible BASE STACK1
869  base_stack_array ( i, j ) = get_rna_stack_score( dist_x, dist_y, dist_z );
870  base_stack_axis_array ( i, j ) = get_rna_axis_score( cos_theta );
871  } //basepair
872 
873  base_geometry_orientation_array ( i, j ) = cos_theta;
874  base_geometry_height_array ( i, j ) = dist_z;
875 
876  } //j
877  }//i
878 
879  // rna_raw_base_base_info.set_calculated( true );
880 
881 }
882 
883 void
885  pose::Pose & pose
886 ) const
887 {
888  using namespace core::scoring::rna;
889 
892 
894  rna::RNA_RawBaseBaseInfo & raw_base_base_info( rna_scoring_info.rna_raw_base_base_info() );
895  rna::RNA_FilteredBaseBaseInfo & rna_filtered_base_base_info( rna_scoring_info.rna_filtered_base_base_info() );
896  // Maybe we should put an if statement.
897  rna_filtered_base_base_info.carry_out_filtering( raw_base_base_info );
898 }
899 
900 ///////////////////////////////////////////////////////////////////////////
901 void
903  rna::RNA_RawBaseBaseInfo & rna_raw_base_base_info,
904  conformation::Residue const & rsd1,
905  conformation::Residue const & rsd2,
906  pose::Pose const & pose,
907  Vector const & centroid1,
908  Vector const & centroid2,
909  kinematics::Stub const & stub1,
910  kinematics::Stub const & stub2
911 ) const
912 {
913  // Following fills in arrays inside rna_raw_base_base_info, which you have to
914  // look inside to get computed energies.
915  eval_rna_base_pair_energy_one_way( rna_raw_base_base_info, rsd1, rsd2, pose, centroid1, centroid2, stub1, stub2 );
916  eval_rna_base_pair_energy_one_way( rna_raw_base_base_info, rsd2, rsd1, pose, centroid2, centroid1, stub2, stub1 );
917 }
918 
919 /////////////////////////////////////////////////////////////
920 // These are slightly more sane cutoffs for defining what is
921 // the Watson-Crick edge vs. Hoogsteen edge vs. sugar edge.
922 void
924  std::string const & hoogsteen_cutoff_atom,
925  std::string const & sugar_cutoff_atom
926 )
927 {
928  using namespace core::chemical;
929  using namespace core::conformation;
930 
932  RNA_CentroidInfo rna_centroid_info;
933 
934  ResidueOP rsd = ResidueFactory::create_residue( *(rsd_set->aa_map( na_rad ))[1] );
935  Vector const & centroid_i = rna_centroid_info.get_base_centroid( *rsd );
936  kinematics::Stub const & stub_i = rna_centroid_info.get_base_coordinate_system( *rsd, centroid_i );
937  Matrix const & M_i( stub_i.M );
938  Vector const & x_i = M_i.col_x();
939  Vector const & y_i = M_i.col_y();
940 
941  Size const res_i_bin = convert_acgu_to_1234( rsd->name1() );
942 
943  Real dist_x( 0.0 ), dist_y( 0.0 ), zeta( 0.0 );
944 
945  Vector d_ij_hoogsteen = rsd->xyz( hoogsteen_cutoff_atom ) - centroid_i;
946  dist_x = dot_product( d_ij_hoogsteen, x_i );
947  dist_y = dot_product( d_ij_hoogsteen, y_i );
948  zeta = numeric::conversions::degrees( std::atan2( dist_y, dist_x ) );
949  zeta_hoogsteen_cutoff_precise_( res_i_bin ) = zeta;
950 
951  if ( true ) {
952  Vector d_ij_sugar = rsd->xyz( sugar_cutoff_atom ) - centroid_i;
953  dist_x = dot_product( d_ij_sugar, x_i );
954  dist_y = dot_product( d_ij_sugar, y_i );
955  zeta = numeric::conversions::degrees( std::atan2( dist_y, dist_x ) );
956  zeta_sugar_cutoff_precise_( res_i_bin ) = zeta + 10.0;
957  }
958 
959  //zeta_hoogsteen_cutoff_precise_( res_i_bin ) = zeta_hoogsteen_cutoff_precise_( res_i_bin ) - 120.0;
960 
961  //std::cout << "HEY! PRECISION CUTOFF FOR ZETA: " <<
962  // zeta_hoogsteen_cutoff_precise_( res_i_bin ) << " " <<
963  // zeta_sugar_cutoff_precise_( res_i_bin ) << " " << std::endl;
964 
965 }
966 
967 ////////////////////////////////////////////////////////////////////////////
968 void
969 RNA_LowResolutionPotential::initialize_more_precise_base_pair_cutoffs() //Doesn't do anything if already initialized.
970 {
971 
972  using namespace core::chemical;
973 
974  zeta_hoogsteen_cutoff_precise_.dimension ( 4 );
975  zeta_sugar_cutoff_precise_.dimension ( 4 );
976 
977  setup_precise_zeta_cutoffs( na_rad, "1H6 ", " C2 " );
978  setup_precise_zeta_cutoffs( na_rcy, "1H4 ", " O2 " );
979  setup_precise_zeta_cutoffs( na_rgu, " O6 ", " N2 " );
980  setup_precise_zeta_cutoffs( na_ura, " O4 ", " O2 " );
981 
982 
983 }
984 
985 ////////////////////////////////////////////////////////////////////////////
986 void
988  conformation::Residue const & res_i,
989  Real & zeta_hoogsteen_cutoff,
990  Real & zeta_sugar_cutoff
991 ) const
992 {
994  Size const res_i_bin = convert_acgu_to_1234( res_i.name1() );
995  zeta_hoogsteen_cutoff = zeta_hoogsteen_cutoff_precise_( res_i_bin );
996  zeta_sugar_cutoff = zeta_sugar_cutoff_precise_( res_i_bin );
997  } else {
998  zeta_hoogsteen_cutoff = 60.0;
999  zeta_sugar_cutoff = -60.0;
1000  }
1001 }
1002 
1003 ///////////////////////////////////////////////////////////////////////////
1004 void
1006  rna::RNA_RawBaseBaseInfo & rna_raw_base_base_info,
1007  conformation::Residue const & res_i,
1008  conformation::Residue const & res_j,
1009  pose::Pose const & pose,
1010  Vector const & centroid_i,
1011  Vector const & centroid_j,
1012  kinematics::Stub const & stub_i,
1013  kinematics::Stub const & stub_j
1014 ) const
1015 {
1016 
1017  if ( !res_i.is_RNA() ) return;
1018  if ( !res_j.is_RNA() ) return;
1019 
1020  Size const total_residue = pose.total_residue();
1021 
1022  // Is this necessary?
1023  rna_raw_base_base_info.resize( total_residue );
1024 
1025  ObjexxFCL::FArray3D< Real > & base_pair_array( rna_raw_base_base_info.base_pair_array() );
1026  ObjexxFCL::FArray3D< Real > & base_axis_array( rna_raw_base_base_info.base_axis_array() );
1027  ObjexxFCL::FArray3D< Real > & base_stagger_array( rna_raw_base_base_info.base_stagger_array() );
1028  ObjexxFCL::FArray2D< Real > & base_stack_array( rna_raw_base_base_info.base_stack_array() );
1029  ObjexxFCL::FArray2D< Real > & base_stack_axis_array( rna_raw_base_base_info.base_stack_axis_array() );
1030  ObjexxFCL::FArray2D< Real > & base_geometry_orientation_array( rna_raw_base_base_info.base_geometry_orientation_array() );
1031  ObjexxFCL::FArray2D< Real > & base_geometry_height_array( rna_raw_base_base_info.base_geometry_height_array() );
1032 
1033  Size const i( res_i.seqpos() );
1034  Size const j( res_j.seqpos() );
1035 
1036  // Zero out these arrays for the residue pair of interest.
1037  for (Size k = 1; k <= rna::NUM_EDGES; k++ ){
1038  base_pair_array( i, j, k ) = 0.0;
1039  base_axis_array( i, j, k ) = 0.0;
1040  base_stagger_array( i, j, k ) = 0.0;
1041  }
1042  base_stack_array( i, j ) = 0.0;
1043  base_stack_axis_array( i, j ) = 0.0;
1044  base_geometry_orientation_array( i, j ) = 0.0;
1045  base_geometry_height_array( i, j ) = 0.0;
1046 
1047  Matrix const & M_i( stub_i.M );
1048  Vector const & x_i = M_i.col_x();
1049  Vector const & y_i = M_i.col_y();
1050  Vector const & z_i = M_i.col_z();
1051 
1052  Vector d_ij = centroid_j - centroid_i;
1053  Real const dist_x = dot_product( d_ij, x_i );
1054  Real const dist_y = dot_product( d_ij, y_i );
1055  Real const dist_z = dot_product( d_ij, z_i );
1056  Real const rho2 = dist_x*dist_x + dist_y*dist_y;
1057 
1058  //This could all be precomputed, actually.
1059  Matrix const & M_j( stub_j.M );
1060  // Vector const & x_j = M_j.col_x();
1061  // Vector const & y_j = M_j.col_y();
1062  Vector const & z_j = M_j.col_z();
1063  Real const cos_theta = dot_product( z_i, z_j );
1064  //This arc-cosine costs a lot actually:
1065  // Real const theta = numeric::conversions::degrees( numeric::arccos( cos_theta ) );
1066 
1067  //Is it a base-pair, a base-stack, or do we ignore it?
1068  Size edge_bin( 1 );
1069  if ( ( std::abs(dist_z) < rna_basepair_stagger_cutoff_ ) ){
1070  //A possible base pair
1071  if ( rho2 < rna_basepair_radius_cutoff2_ ){
1072  //BASE PAIR
1073  Real temp_rna_bp_score( 0.0 );
1074 
1075  temp_rna_bp_score = get_rna_basepair_xy(dist_x, dist_y, dist_z, cos_theta, res_i, res_j);
1076 
1077  // Some of the base pairing scores are 0.0. By default, pad by
1078  // a tiny tiny amount to make sure that they're still
1079  // counted as very weak base pairs during later book-keeping.
1080  temp_rna_bp_score -= 0.0001;
1081 
1082  Real zeta_hoogsteen_cutoff( 60.0 ), zeta_sugar_cutoff( -60.0 );
1083  get_zeta_cutoff( res_i, zeta_hoogsteen_cutoff, zeta_sugar_cutoff );
1084 
1085  Real const zeta = numeric::conversions::degrees( std::atan2( dist_y, dist_x) );
1086  if ( zeta < zeta_hoogsteen_cutoff && zeta > zeta_sugar_cutoff ) edge_bin = WATSON_CRICK; //Watson-Crick edge
1087  else if ( zeta > zeta_hoogsteen_cutoff ) edge_bin = HOOGSTEEN; // Hoogsteen edge
1088  else edge_bin = SUGAR; // Sugar edge
1089 
1090  if ( rna_verbose_ ){
1091  Real const theta = numeric::conversions::degrees( numeric::arccos( cos_theta ) );
1092  std::cout << " Possible base pair: "
1093  << res_i.name3() << I(3,i) << "-"
1094  << res_j.name3() << I(3,j)
1095  << " edge: " << I(1,edge_bin)
1096  << " dists " << F(4,2,dist_x)
1097  << " " << F(4,2,dist_y)
1098  << " " << F(4,2,dist_z)
1099  << " Centroid " << centroid_i(1) << " " << centroid_i(2) << " " << centroid_i(3)
1100  << " CENTROID " << centroid_j(1) << " " << centroid_j(2) << " " << centroid_j(3)
1101  << " theta " << F(5,1, theta)
1102  << "; rho " << F(4,2, std::sqrt( rho2) )
1103  << " : SCORE " << F(6,4,temp_rna_bp_score)
1104  // << " " << get_rna_axis_score( theta) << " " << get_rna_stagger_score( dist_z )
1105  << std::endl;
1106  }
1107 
1108  base_pair_array ( i, j, edge_bin ) = temp_rna_bp_score;
1109  base_axis_array ( i, j, edge_bin ) = get_rna_axis_score( cos_theta );
1110  base_stagger_array ( i, j, edge_bin ) = get_rna_stagger_score( dist_z );
1111 
1112  }
1113  }
1114 
1115  if ( std::abs(dist_z) >= base_stack_min_height_ &&
1116  std::abs(dist_z) <= base_stack_max_height_ &&
1117  rho2 < base_stack_radius2_ ) {
1118  //Possible BASE STACK1
1119  base_stack_array ( i, j ) = get_rna_stack_score( dist_x, dist_y, dist_z );
1120  base_stack_axis_array ( i, j ) = get_rna_axis_score( cos_theta );
1121  } //basepair
1122 
1123  base_geometry_orientation_array ( i, j ) = cos_theta;
1124  base_geometry_height_array ( i, j ) = dist_z;
1125 
1126 }
1127 
1128 
1129 ///////////////////////////////////////////////////////////////////////////
1130 void
1132  id::AtomID const & atom_id,
1133  pose::Pose const & pose,
1134  scoring::EnergyMap const & weights,
1135  Vector & F1,
1136  Vector & F2 ) const
1137 {
1138 
1139  Size const & i = atom_id.rsd();
1140  conformation::Residue const & res_i( pose.residue( i ) );
1141  Size const & atom_num_i( atom_id.atomno() );
1142 
1143  if ( !res_i.is_RNA() ) return;
1144 
1145  //First an easy filter -- only need to put derivs on base's torsion.
1146 
1147  if ( atom_num_i != chi1_torsion_atom_index( res_i ) ) return;
1148 
1149  // Information saved from the last score.
1150  rna::RNA_ScoringInfo const & rna_scoring_info( rna::rna_scoring_info_from_pose( pose ) );
1151  // rna::RNA_RawBaseBaseInfo const & raw_base_base_info( rna_scoring_info.rna_raw_base_base_info() );
1152  rna::RNA_FilteredBaseBaseInfo const & rna_filtered_base_base_info( rna_scoring_info.rna_filtered_base_base_info() );
1153 
1154  // assert( rna_filtered_base_base_info.calculated() );
1155 
1156  // Axis and stagger terms will have hard boundaries unless they're
1157  // multiplied by base pair (x,y) or base stack (z) terms.
1158  assert( rna_filtered_base_base_info.scale_axis_stagger() );
1159 
1160  // Yea, this is what we need...
1161  ObjexxFCL::FArray2D< Real > const & filtered_base_pair_array ( rna_filtered_base_base_info.filtered_base_pair_array() );
1162  ObjexxFCL::FArray2D< Real > const & filtered_base_axis_array ( rna_filtered_base_base_info.filtered_base_axis_array() );
1163  ObjexxFCL::FArray2D< Real > const & filtered_base_stagger_array( rna_filtered_base_base_info.filtered_base_stagger_array() );
1164  ObjexxFCL::FArray2D< Real > const & filtered_base_stack_array( rna_filtered_base_base_info.filtered_base_stack_array() );
1165  ObjexxFCL::FArray2D< Real > const & filtered_base_stack_axis_array( rna_filtered_base_base_info.filtered_base_stack_axis_array() );
1166 
1167  rna::RNA_CentroidInfo const & rna_centroid_info( rna_scoring_info.rna_centroid_info() );
1168  // assert( rna_centroid_info.calculated() );
1169  utility::vector1< Vector > const & base_centroids( rna_centroid_info.base_centroids() );
1170  utility::vector1< kinematics::Stub > const & base_stubs( rna_centroid_info.base_stubs() );
1171 
1172  // Vector const & heavy_atom_i_xyz( res_i.xyz( atom_num_i ) ) ;
1173 
1174  Vector const & centroid_i( base_centroids[i] );
1175  kinematics::Stub const & stub_i( base_stubs[i] );
1176  Matrix const & M_i( stub_i.M );
1177  Vector const & x_i = M_i.col_x();
1178  Vector const & y_i = M_i.col_y();
1179  Vector const & z_i = M_i.col_z();
1180 
1181  EnergyGraph const & energy_graph( pose.energies().energy_graph() );
1182 
1184  iter = energy_graph.get_node( i )->const_edge_list_begin();
1185  iter != energy_graph.get_node( i )->const_edge_list_end();
1186  ++iter ){
1187 
1188  Size j( (*iter)->get_other_ind( i ) );
1189 
1190  conformation::Residue const & res_j( pose.residue( j ) );
1191 
1192  Vector const & centroid_j( base_centroids[j] );
1193  kinematics::Stub const & stub_j( base_stubs[j] );
1194 
1195  Matrix const & M_j( stub_j.M );
1196  Vector const & x_j = M_j.col_x();
1197  Vector const & y_j = M_j.col_y();
1198  Vector const & z_j = M_j.col_z();
1199  Real const cos_theta = dot_product( z_i, z_j );
1200  //This arc-cosine costs a lot actually:
1201  // Real const theta = numeric::conversions::degrees( numeric::arccos( cos_theta ) );
1202 
1203  //First cycle through all base pairs that count... anything involving this residue?
1204  if ( filtered_base_pair_array( i, j) < 0.0 ) {
1205 
1206  Real const base_axis_score_unscaled = filtered_base_axis_array(i,j)/filtered_base_pair_array(i,j);
1207  Real const base_stagger_score_unscaled = filtered_base_stagger_array(i,j)/filtered_base_pair_array(i,j);
1208  Real bp_deriv_x( 0.0 ), bp_deriv_y( 0.0 ), bp_deriv_z( 0.0 ), axis_deriv( 0.0 ), stagger_deriv( 0.0 );
1209  Real const & basepair_axis_stagger_scaling( rna_filtered_base_base_info.basepair_axis_stagger_scaling() );
1210 
1211  // If its been scored, all the various geometry cutoffs should already have been satisfied
1212  { // from this base coordinate system to other base.
1213  Vector d_ij = centroid_j - centroid_i;
1214  Real const dist_x = dot_product( d_ij, x_i );
1215  Real const dist_y = dot_product( d_ij, y_i );
1216  Real const dist_z = dot_product( d_ij, z_i );
1217  // Real const rho2 = dist_x*dist_x + dist_y*dist_y;
1218 
1219  get_rna_basepair_xy(dist_x, dist_y, dist_z, cos_theta, res_i, res_j,
1220  true /*update_deriv*/, bp_deriv_x, bp_deriv_y, bp_deriv_z );
1221  get_rna_axis_score( cos_theta, axis_deriv );
1222  get_rna_stagger_score( dist_z, stagger_deriv );
1223 
1224  //Time for the chain rule... to get the total force and torque.
1225  // 1. Correct for scale_axis_stagger craziness.
1226  // 2. I don't fully understand factor of two yet.
1227  Vector const f2 =
1228  ( x_i * bp_deriv_x + y_i * bp_deriv_y + z_i * bp_deriv_z )
1229  * ( weights[ rna_base_pair ] +
1230  weights[ rna_base_axis ] * base_axis_score_unscaled +
1231  weights[ rna_base_stagger ] * base_stagger_score_unscaled )
1232  - z_i * basepair_axis_stagger_scaling * filtered_base_pair_array(i,j) * weights[ rna_base_stagger ] * stagger_deriv;
1233 
1234  Vector const f1 = cross( f2, centroid_j )
1235  - basepair_axis_stagger_scaling * filtered_base_pair_array(i,j) * weights[ rna_base_axis ] * axis_deriv * cross( z_i, z_j );
1236 
1237  F1 -= f1;
1238  F2 -= f2;
1239 
1240  // std::cout << "BASEPAIR_DERIV1: " << i << " " << j << " " << cos_theta << " " << f1(1) << " " << f2(1) << std::endl;
1241  }
1242 
1243  { // from other base coordinate system to this one.
1244  Vector d_ji = centroid_i - centroid_j;
1245  Real const dist_x = dot_product( d_ji, x_j );
1246  Real const dist_y = dot_product( d_ji, y_j );
1247  Real const dist_z = dot_product( d_ji, z_j );
1248  // Real const rho2 = dist_x*dist_x + dist_y*dist_y;
1249 
1250  get_rna_basepair_xy(dist_x, dist_y, dist_z, cos_theta, res_j, res_i,
1251  true /*update_deriv*/, bp_deriv_x, bp_deriv_y, bp_deriv_z );
1252  get_rna_axis_score( cos_theta, axis_deriv );
1253  get_rna_stagger_score( dist_z, stagger_deriv );
1254 
1255  //Time for the chain rule... to get the total force and torque.
1256  // Correct for scale_axis_stagger craziness.
1257  Vector const f2 =
1258  ( x_j * bp_deriv_x + y_j * bp_deriv_y + z_j * bp_deriv_z )
1259  * ( weights[ rna_base_pair ] +
1260  weights[ rna_base_axis ] * base_axis_score_unscaled +
1261  weights[ rna_base_stagger ] * base_stagger_score_unscaled )
1262  - z_j * basepair_axis_stagger_scaling * filtered_base_pair_array(j,i) * weights[ rna_base_stagger ] * stagger_deriv;
1263 
1264  Vector const f1 = cross( f2, centroid_i )
1265  - basepair_axis_stagger_scaling * filtered_base_pair_array(j,i) * weights[ rna_base_axis ] * axis_deriv * cross( z_j, z_i );
1266 
1267  F1 += f1;
1268  F2 += f2;
1269 
1270  // std::cout << "BASEPAIR_DERIV2: " << i << " " << j << " " << cos_theta << " " << f1(1) << " " << f2(1) << std::endl;
1271  }
1272 
1273  } else if ( filtered_base_stack_array( i, j) < 0.0 ) {
1274  //Then cycle through all base stacks that count.
1275 
1276  Real const base_stack_axis_score_unscaled = filtered_base_stack_axis_array(i,j)/filtered_base_stack_array(i,j);
1277  Real bs_deriv_x( 0.0 ), bs_deriv_y( 0.0 ), bs_deriv_z( 0.0 ), axis_deriv( 0.0 );
1278  Real const & basestack_axis_scaling( rna_filtered_base_base_info.basestack_axis_scaling() );
1279 
1280  {
1281  Vector d_ij = centroid_j - centroid_i;
1282  Real const dist_x = dot_product( d_ij, x_i );
1283  Real const dist_y = dot_product( d_ij, y_i );
1284  Real const dist_z = dot_product( d_ij, z_i );
1285 
1286  // If its been scored, all the various geometry cutoffs should already have been satisfied!
1287  get_rna_stack_score( dist_x, dist_y, dist_z, bs_deriv_x, bs_deriv_y, bs_deriv_z );
1288  get_rna_axis_score( cos_theta, axis_deriv );
1289 
1290  Vector const f2 =
1291  ( x_i * bs_deriv_x + y_i * bs_deriv_y + z_i * bs_deriv_z ) *
1292  ( weights[ rna_base_stack ] +
1293  weights[ rna_base_stack_axis ] * base_stack_axis_score_unscaled );
1294  Vector const f1 = cross( f2, centroid_j )
1295  - basestack_axis_scaling * weights[ rna_base_stack_axis ] * filtered_base_stack_array(i,j) * axis_deriv * cross( z_i, z_j );
1296 
1297  F1 -= f1;
1298  F2 -= f2;
1299 
1300  // std::cout << "BASESTACK_DERIV1: " << i << " " << j << " " << cos_theta << " " << f1(1) << " " << f2(1) << std::endl;
1301  }
1302  {
1303  Vector d_ji = centroid_i - centroid_j;
1304  Real const dist_x = dot_product( d_ji, x_j );
1305  Real const dist_y = dot_product( d_ji, y_j );
1306  Real const dist_z = dot_product( d_ji, z_j );
1307 
1308  // If its been scored, all the various geometry cutoffs should already have been satisfied!
1309  get_rna_stack_score( dist_x, dist_y, dist_z, bs_deriv_x, bs_deriv_y, bs_deriv_z );
1310  get_rna_axis_score( cos_theta, axis_deriv );
1311 
1312  // std::cout << "HELLOSTACK --> " << dist_x << " " << dist_y << " " << dist_z << " " << bs_deriv_x << " " << bs_deriv_y << " " << bs_deriv_y << " " << weights[ rna_base_stack_axis ] << " " << base_stack_axis_score_unscaled << std::endl;
1313 
1314  Vector const f2 =
1315  ( x_j * bs_deriv_x + y_j * bs_deriv_y + z_j * bs_deriv_z ) *
1316  ( weights[ rna_base_stack ] +
1317  weights[ rna_base_stack_axis ] * base_stack_axis_score_unscaled );
1318  Vector const f1 = cross( f2, centroid_i )
1319  - basestack_axis_scaling * weights[ rna_base_stack_axis ] * filtered_base_stack_array(j,i) * axis_deriv * cross( z_j, z_i );
1320 
1321  F1 += f1;
1322  F2 += f2;
1323 
1324  // std::cout << "BASESTACK_DERIV2: " << i << " " << j << " " << cos_theta << " " << f1(1) << " " << f2(1) << std::endl;
1325  }
1326  }
1327 
1328  }
1329 
1330 }
1331 
1332 
1333 //////////////////////////////////////////////////////////////////////////////////
1334 // This actually imposes a hard-edge, and in special cases this causes a
1335 // problem with (numerical) derivative calculations, and accumulation at the boundary.
1336 // So I added a weight that is very very close to one unless we're on the edge (within 0.01 A),
1337 // in which case we fade...
1338 // In principle we should also put in the derivative at the edge... but not yet implemented.
1339 bool
1341  conformation::Residue const & rsd1,
1342  Vector const & heavy_atom_j,
1343  Real & atom_cutoff_weight) const
1344 {
1345 
1346  atom_cutoff_weight = 1.0;
1347  if (!base_backbone_check_atom_neighbor_) return true;
1348 
1349  Size const num_heavy_atoms ( rsd1.nheavyatoms() );
1350  Size const rna_base_start ( rsd1.first_sidechain_atom() );
1351 
1352  bool found_a_neighbor = false;
1353  Real min_nbr_dist2( 1000.0 );
1354  for (Size atom_num_i = rna_base_start; atom_num_i <= num_heavy_atoms; atom_num_i++){
1355  Vector const & base_heavy_atom_i( rsd1.xyz( atom_num_i ) );
1356  Real const nbr_dist2 = (heavy_atom_j - base_heavy_atom_i ).length_squared();
1357  if ( nbr_dist2 < min_nbr_dist2 ){
1358  min_nbr_dist2 = nbr_dist2;
1359  // break;
1360  }
1361  }
1362 
1363  Real const min_nbr_dist = std::sqrt( min_nbr_dist2 );
1364  if ( min_nbr_dist < base_backbone_atom_dist_cutoff_ ) found_a_neighbor = true;
1365 
1366  Real deriv_currently_ignored( 0.0 );
1367  if (found_a_neighbor) {
1368  get_fade_correction( min_nbr_dist,
1369  -base_backbone_atom_dist_cutoff_ /*will not come into play*/,
1371  0.02 /*fade boundary*/,
1372  atom_cutoff_weight,
1373  deriv_currently_ignored );
1374  // std::cout << "Hello? NBR_DIST" << nbr_dist << " " << atom_cutoff_weight << std::endl;
1375  }
1376 
1377  return found_a_neighbor;
1378 }
1379 
1380 /////////////////////////////////////////////////////////////////////////////////
1381 Real
1383  conformation::Residue const & rsd1,
1384  conformation::Residue const & rsd2,
1385  Vector const & centroid1,
1386  Vector const & centroid2,
1387  kinematics::Stub const & stub1,
1388  kinematics::Stub const & stub2
1389 ) const
1390 {
1391  return ( rna_base_backbone_pair_energy_one_way( rsd1, rsd2, centroid1, stub1 ) +
1392  rna_base_backbone_pair_energy_one_way( rsd2, rsd1, centroid2, stub2 ) );
1393 }
1394 
1395 //////////////////////////////////////////////////////////////////////////////
1396 Real
1398  conformation::Residue const & rsd1,
1399  conformation::Residue const & rsd2,
1400  Vector const & centroid_i,
1401  kinematics::Stub const & stub_i
1402 ) const
1403 {
1404  ////////////////////////////////////////////////////////////////////////////////
1405  //Hmm, is rsd1 always less than rsd2?
1406 
1407  if ( !rsd1.is_RNA() ) return 0.0;
1408  if ( !rsd2.is_RNA() ) return 0.0;
1409 
1410  if ( rsd1.is_coarse() ) return 0.0; //coarse-grained!
1411  if ( rsd2.is_coarse() ) return 0.0; //coarse-grained!
1412 
1413  Size const i = rsd1.seqpos();
1414  Size const j = rsd2.seqpos();
1415 
1416  if ( abs( static_cast<int> (i - j) ) < 2 ) return 0.0;
1417 
1418  // rna::RNA_ScoringInfo const & rna_scoring_info( rna::rna_scoring_info_from_pose( pose ) );
1419  // rna::RNA_CentroidInfo const & rna_centroid_info( rna_scoring_info.rna_centroid_info() );
1420  // assert( rna_centroid_info.calculated() ); //This needs to all be calculated earlier, dude.
1421 
1422  // utility::vector1< Vector > const & base_centroids( rna_centroid_info.base_centroids() );
1423  // utility::vector1< kinematics::Stub > const & base_stubs( rna_centroid_info.base_stubs() );
1424  // Vector const & centroid_i( base_centroids[i] );
1425  // kinematics::Stub const & stub_i( base_stubs[i] );
1426  Matrix const & M_i( stub_i.M );
1427  Vector const & x_i = M_i.col_x();
1428  Vector const & y_i = M_i.col_y();
1429  Vector const & z_i = M_i.col_z();
1430 
1431  Real total_score( 0.0 );
1432 
1433  //For speed, a cached set of atom numbers that go with RNA_backbone_oxygen_atoms_ (which is a bunch of strings)
1434  // ObjexxFCL::FArray2D< Size > const &
1435  // atom_numbers_for_backbone_score_calculations = rna_scoring_info.atom_numbers_for_backbone_score_calculations();
1436 
1437  // Go over sugar and phosphate oxygen atoms
1438  for (Size m = 1; m <= num_RNA_backbone_oxygen_atoms_; m++ ){
1439 
1440  // std::string const atom_j = RNA_backbone_oxygen_atoms_[ m ];
1441  Size const atom_num_j = atom_numbers_for_backbone_score_calculations_[ m ];//atom_numbers_for_backbone_score_calculations( rsd2.seqpos(), m );
1442 
1443  Vector const heavy_atom_j( rsd2.xyz( atom_num_j ) );
1444 
1445  Vector const d_ij = heavy_atom_j - centroid_i;
1446 
1447  Real const dist_ij = d_ij.length();
1448 
1449  if (dist_ij < base_backbone_distance_cutoff_ ){
1450 
1451  Real const dist_x = dot_product( d_ij, x_i );
1452  Real const dist_y = dot_product( d_ij, y_i );
1453  Real const dist_z = dot_product( d_ij, z_i );
1454 
1455  Real const rho = std::sqrt( dist_x * dist_x + dist_y * dist_y);
1456 
1457  if ( std::abs(dist_z) > base_backbone_z_cutoff_ ) continue; // Look for atoms in the base plane
1458  if ( rho > base_backbone_rho_cutoff_ ) continue; // Look for atoms in the base plane
1459 
1460  //sanity check...
1461  //make sure we're in H-bonding distance of some base atom.
1462  Real atom_cutoff_weight( 1.0 );
1463  if ( !check_for_base_neighbor( rsd1, heavy_atom_j, atom_cutoff_weight ) ) continue;
1464 
1465  Real const score_contribution =
1466  atom_cutoff_weight * get_rna_base_backbone_xy( dist_x, dist_y, dist_z, rsd1, m );
1467 
1468  total_score += score_contribution;
1469 
1470  if ( rna_verbose_ ){
1471  std::cout <<
1472  "BASE-BACKBONE " <<
1473  rsd1.name3() <<
1474  I(3,i) << " " <<
1475  rsd2.atom_name( atom_num_j ) << " " <<
1476  I(3,j) << " " <<
1477  " [" << F(4,2,rho) << ", " << F(4,2,dist_z) << "]: " <<
1478  F(6,2,score_contribution) <<
1479  std::endl;
1480  }
1481 
1482  }
1483 
1484  }
1485 
1486  return total_score;
1487 
1488 }
1489 
1490 
1491 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1492 // Lot of code copying here -- should minirosetta++ derivative calculation be refactored?
1493 // Not so much for speed but due to code redundancy in defining loops, etc.
1494 //
1495 void
1497  id::AtomID const & atom_id,
1498  pose::Pose const & pose,
1499  Vector & F1,
1500  Vector & F2 ) const
1501 {
1502 
1503  Size const & i = atom_id.rsd();
1504  conformation::Residue const & rsd1( pose.residue( i ) );
1505  Size const & atom_num_i( atom_id.atomno() );
1506 
1507  F1 = 0.0;
1508  F2 = 0.0;
1509 
1510  if ( !rsd1.is_RNA() ) return;
1511  assert( interpolate_ );
1512 
1513  //For speed, a cached set of atom numbers that go with RNA_backbone_oxygen_atoms_ (which is a bunch of strings)
1514  rna::RNA_ScoringInfo const & rna_scoring_info( rna::rna_scoring_info_from_pose( pose ) );
1515  // ObjexxFCL::FArray2D< Size > const &
1516  // atom_numbers_for_backbone_score_calculations = rna_scoring_info.atom_numbers_for_backbone_score_calculations();
1517  rna::RNA_CentroidInfo const & rna_centroid_info( rna_scoring_info.rna_centroid_info() );
1518 
1519  utility::vector1< Vector > const & base_centroids( rna_centroid_info.base_centroids() );
1520  utility::vector1< kinematics::Stub > const & base_stubs( rna_centroid_info.base_stubs() );
1521 
1522  EnergyGraph const & energy_graph( pose.energies().energy_graph() );
1523 
1524  //Either we're a backbone oxygen atom, or we're the RNA first base atom (N1 or N9).
1525 
1526  // std::cout << rsd1.aa() << " CHI1 TORSION ATOM ==> " << chi1_torsion_atom_index( rsd1 ) << " " << chi1_torsion_atom( rsd1 ) << std::endl;
1527  if ( atom_num_i == chi1_torsion_atom_index( rsd1 ) ) {
1528 
1529  Vector const & centroid_i( base_centroids[i] );
1530  kinematics::Stub const & stub_i( base_stubs[i] );
1531  Matrix const & M_i( stub_i.M );
1532  Vector const & x_i = M_i.col_x();
1533  Vector const & y_i = M_i.col_y();
1534  Vector const & z_i = M_i.col_z();
1535 
1536  // Size const num_heavy_atoms ( rsd1.nheavyatoms() );
1537  // Size const rna_base_start( rsd1.first_sidechain_atom() );
1538 
1540  iter = energy_graph.get_node( i )->const_edge_list_begin();
1541  iter != energy_graph.get_node( i )->const_edge_list_end();
1542  ++iter ){
1543 
1544  Size j( (*iter)->get_other_ind( i ) );
1545 
1546  if ( abs( static_cast<int>(i - j) ) < 2 ) continue;
1547 
1548  conformation::Residue const & rsd2( pose.residue( j ) );
1549  if ( !rsd2.is_RNA() ) continue;
1550 
1551  // Go over sugar and phosphate oxygen atoms
1552  for (Size m = 1; m <= num_RNA_backbone_oxygen_atoms_; m++ ){
1553 
1554  // std::string const atom_j = RNA_backbone_oxygen_atoms_[ m ];
1555  Size const atom_num_j = atom_numbers_for_backbone_score_calculations_[ m ];//atom_numbers_for_backbone_score_calculations( rsd2.seqpos(), m );
1556 
1557  Vector const heavy_atom_j( rsd2.xyz( atom_num_j ) );
1558 
1559  Vector const d_ij = heavy_atom_j - centroid_i;
1560 
1561  Real const dist_ij = d_ij.length();
1562 
1563  if (dist_ij >= base_backbone_distance_cutoff_ ) continue;
1564 
1565  Real const dist_x = dot_product( d_ij, x_i );
1566  Real const dist_y = dot_product( d_ij, y_i );
1567  Real const dist_z = dot_product( d_ij, z_i );
1568 
1569  Real const rho = std::sqrt( dist_x * dist_x + dist_y * dist_y);
1570 
1571  if ( std::abs(dist_z) > base_backbone_z_cutoff_ ) continue; // Look for atoms in the base plane
1572  if ( rho > base_backbone_rho_cutoff_ ) continue; // Look for atoms in the base plane
1573 
1574  //sanity check...
1575  //make sure we're in H-bonding distance of some base atom.
1576  Real atom_cutoff_weight( 1.0 );
1577  if (!check_for_base_neighbor( rsd1, heavy_atom_j, atom_cutoff_weight ) ) continue;
1578 
1579  Real deriv_x( 0.0 ), deriv_y( 0.0 ), deriv_z( 0.0 );
1580  get_rna_base_backbone_xy( dist_x, dist_y, dist_z, rsd1, m, true /*update_deriv*/, deriv_x, deriv_y, deriv_z );
1581 
1582  Vector const f2 = -1.0 * ( x_i * deriv_x + y_i * deriv_y + z_i * deriv_z);
1583  Vector const f1 = cross( f2, heavy_atom_j );
1584 
1585  F1 += f1;
1586  F2 += f2;
1587 
1588  // std::cout << "BACKBONEBASE_DERIV1 " << f2(1) << std::endl;
1589 
1590  } // m
1591  } // nbrs
1592  } else {
1593 
1594  Size n = find_backbone_oxygen_atom( atom_num_i );
1595 
1596  Vector const heavy_atom_i( rsd1.xyz( atom_num_i ) );
1597 
1598  if ( n > 0 ){
1599 
1601  iter = energy_graph.get_node( i )->const_edge_list_begin();
1602  iter != energy_graph.get_node( i )->const_edge_list_end();
1603  ++iter ){
1604 
1605  Size j( (*iter)->get_other_ind( i ) );
1606 
1607  if ( abs( static_cast<int>(i - j) ) < 2 ) continue;
1608 
1609  conformation::Residue const & rsd2( pose.residue( j ) );
1610  if ( !rsd2.is_RNA() ) continue;
1611 
1612  Vector const & centroid_j( base_centroids[j] );
1613  kinematics::Stub const & stub_j( base_stubs[j] );
1614  Matrix const & M_j( stub_j.M );
1615  Vector const & x_j = M_j.col_x();
1616  Vector const & y_j = M_j.col_y();
1617  Vector const & z_j = M_j.col_z();
1618 
1619  Vector const d_ij = heavy_atom_i - centroid_j;
1620 
1621  Real const dist_ij = d_ij.length();
1622 
1623  if (dist_ij >= base_backbone_distance_cutoff_ ) continue;
1624 
1625  Real const dist_x = dot_product( d_ij, x_j );
1626  Real const dist_y = dot_product( d_ij, y_j );
1627  Real const dist_z = dot_product( d_ij, z_j );
1628 
1629  Real const rho = std::sqrt( dist_x * dist_x + dist_y * dist_y);
1630 
1631  if ( std::abs(dist_z) > base_backbone_z_cutoff_ ) continue; // Look for atoms in the base plane
1632  if ( rho > base_backbone_rho_cutoff_ ) continue; // Look for atoms in the base plane
1633 
1634  //sanity check...
1635  //make sure we're in H-bonding distance of some base atom.
1636  Real atom_cutoff_weight( 1.0 );
1637  if (!check_for_base_neighbor( rsd2, heavy_atom_i, atom_cutoff_weight ) ) continue;
1638 
1639  Real deriv_x( 0.0 ), deriv_y( 0.0 ), deriv_z( 0.0 );
1640 
1641  get_rna_base_backbone_xy( dist_x, dist_y, dist_z, rsd2, n, true /*update_deriv*/, deriv_x, deriv_y, deriv_z );
1642 
1643  Vector const f2 = x_j * deriv_x + y_j * deriv_y + z_j * deriv_z;
1644  Vector const f1 = cross( f2, heavy_atom_i );
1645 
1646  F1 += f1;
1647  F2 += f2;
1648 
1649  // std::cout << "BACKBONEBASE_DERIV2 " << f1(1) << std::endl;
1650 
1651  } // n
1652  } // nbrs
1653 
1654  }
1655 
1656  // std::cout << "BACKBONEBASE_DERIV_SUM " << F1(1) << std::endl;
1657 
1658 }
1659 
1660 ///////////////////////////////////////////////////////////////////////////////
1661 Real
1663  conformation::Residue const & rsd1,
1664  conformation::Residue const & rsd2
1665 ) const
1666 {
1667  return ( rna_backbone_backbone_pair_energy_one_way( rsd1, rsd2 ) +
1669 }
1670 
1671 ///////////////////////////////////////////////////////////////////////////////
1672 Real
1674  conformation::Residue const & rsd1,
1675  conformation::Residue const & rsd2
1676 ) const
1677 {
1678 
1679  if ( !rsd1.is_RNA() ) return 0.0;
1680  if ( !rsd2.is_RNA() ) return 0.0;
1681 
1682  if ( rsd1.is_coarse() ) return 0.0; //coarse-grained!
1683  if ( rsd2.is_coarse() ) return 0.0; //coarse-grained!
1684 
1685  Real rna_backbone_backbone_score = 0.0;
1686 
1687  // static Real const dist_cutoff ( 6.0 );
1688 
1689  // std::string const atom_i = " O2*";
1690 
1691  Size const i( rsd1.seqpos() );
1692  Size const j( rsd2.seqpos() );
1693 
1694  if ( abs( static_cast<int>(i - j) ) <= 2 ) return 0.0;
1695 
1696  //For speed, a cached set of atom numbers that go with RNA_backbone_oxygen_atoms_ (which is a bunch of strings)
1697  // rna::RNA_ScoringInfo const & rna_scoring_info( rna::rna_scoring_info_from_pose( pose ) );
1698  // ObjexxFCL::FArray2D< Size > const &
1699  // atom_numbers_for_backbone_score_calculations = rna_scoring_info.atom_numbers_for_backbone_score_calculations();
1700 
1702  Vector const & heavy_atom_i = rsd1.xyz( atom_num_i );
1703 
1704  // Go over sugar and phosphate oxygen atoms!
1705  for (Size m = 1; m <= num_RNA_backbone_oxygen_atoms_; m++ ){
1706 
1707  if ( rna_backbone_backbone_weight_( m ) < 0.001 ) continue;
1708 
1709  Size const atom_num_j = atom_numbers_for_backbone_score_calculations_[ m ];
1710 
1711  //Don't double-count 2'-OH <--> 2'-OH interactions
1712  if ( atom_num_j == atom_num_i && j < i) continue;
1713 
1714  Vector const & heavy_atom_j = rsd2.xyz( atom_num_j );
1715  Vector const d_ij = heavy_atom_j - heavy_atom_i;
1716  Distance const dist_ij = d_ij.length();
1717 
1718  if ( dist_ij > backbone_backbone_distance_cutoff_ ) continue;
1719 
1720  Real const score_contribution = get_rna_backbone_backbone_score( dist_ij, m );
1721  rna_backbone_backbone_score += score_contribution;
1722 
1723  if ( rna_verbose_ && score_contribution < -0.01 ){
1724  std::string const atom_j = RNA_backbone_oxygen_atoms_[ m ];
1725  std::cout <<
1726  "BACKBONE_BACKBONE " <<
1727  rsd1.name1() <<
1728  I(3,i) << " " <<
1729  rsd1.atom_name(atom_num_i) <<
1730  " " << rsd1.xyz( atom_num_i )[1] <<
1731  " -- " <<
1732  rsd2.name1() <<
1733  I(3,j) << " " <<
1734  rsd2.atom_name(atom_num_j) << " " <<
1735  " " << rsd2.xyz( atom_num_j )[1] <<
1736  F(6,2,score_contribution) << " [" << dist_ij << "]" <<
1737  std::endl;
1738  }
1739 
1740  }
1741 
1742  return rna_backbone_backbone_score;
1743 
1744 }
1745 
1746 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1747 Size
1749  ObjexxFCL::FArray2D< Size > const & atom_numbers_for_backbone_score_calculations,
1750  Size const & i,
1751  Size const & atom_num_i ) const
1752 {
1753 
1754  Size n( 0 );
1755  bool is_backbone_oxygen_atom( false );
1756 
1757  for (n = 1; n <= num_RNA_backbone_oxygen_atoms_; n++ ){
1758  if ( atom_numbers_for_backbone_score_calculations(i, n) == atom_num_i ) {
1759  is_backbone_oxygen_atom = true; break;
1760  }
1761  }
1762  if (!is_backbone_oxygen_atom) return 0;
1763 
1764  return n;
1765 }
1766 
1767 
1768 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1769 Size
1771  Size const & atom_num_i ) const
1772 {
1773 
1774  Size n( 0 );
1775  bool is_backbone_oxygen_atom( false );
1776 
1777  for (n = 1; n <= num_RNA_backbone_oxygen_atoms_; n++ ){
1778  if ( atom_numbers_for_backbone_score_calculations_[ n ] == atom_num_i ) {
1779  is_backbone_oxygen_atom = true; break;
1780  }
1781  }
1782  if (!is_backbone_oxygen_atom) return 0;
1783 
1784  return n;
1785 }
1786 
1787 
1788 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1789 // Lot of code copying here -- should minirosetta++ derivative calculation be refactored?
1790 // Not so much for speed but due to code redundancy in defining loops, etc.
1791 //
1792 void
1794  id::AtomID const & atom_id,
1795  pose::Pose const & pose,
1796  Vector & F1,
1797  Vector & F2 ) const
1798 {
1799 
1800  Size const & i = atom_id.rsd();
1801  conformation::Residue const & rsd1( pose.residue( i ) );
1802  Size const & atom_num_i( atom_id.atomno() );
1803 
1804  F1 = 0.0;
1805  F2 = 0.0;
1806 
1807  if ( !rsd1.is_RNA() ) return;
1808 
1809  assert( interpolate_ );
1810 
1811  //For speed, a cached set of atom numbers that go with RNA_backbone_oxygen_atoms_ (which is a bunch of strings)
1812  // rna::RNA_ScoringInfo const & rna_scoring_info( rna::rna_scoring_info_from_pose( pose ) );
1813  // ObjexxFCL::FArray2D< Size > const &
1814  // atom_numbers_for_backbone_score_calculations = rna_scoring_info.atom_numbers_for_backbone_score_calculations();
1815 
1816  // FIRST WAY, check if this atom is O2P, cycle over other oxygen atoms.
1818 
1819  EnergyGraph const & energy_graph( pose.energies().energy_graph() );
1820 
1821  if ( atom_num_i == atom_num_o2star ) {
1822  // FIRST WAY, check if this atom is 2'-OH, cycle over other oxygen atoms.
1823 
1824  Vector const & heavy_atom_i = rsd1.xyz( atom_num_i );
1825 
1827  iter = energy_graph.get_node( i )->const_edge_list_begin();
1828  iter != energy_graph.get_node( i )->const_edge_list_end();
1829  ++iter ){
1830 
1831  Size j( (*iter)->get_other_ind( i ) );
1832 
1833  if ( abs( static_cast<int>(i - j) ) <= 2 ) continue;
1834 
1835  conformation::Residue const & rsd2( pose.residue( j ) );
1836  if ( !rsd2.is_RNA() ) continue;
1837 
1838  // Go over sugar and phosphate oxygen atoms!
1839  for (Size m = 1; m <= num_RNA_backbone_oxygen_atoms_; m++ ){
1840 
1841  if ( rna_backbone_backbone_weight_( m ) < 0.001 ) continue;
1842 
1843  Size const atom_num_j = atom_numbers_for_backbone_score_calculations_[ m ];
1844 
1845  //Don't double-count 2'-OH <--> 2'-OH interactions
1846  // if ( atom_num_j == atom_num_i && j < i) continue;
1847 
1848  Vector const & heavy_atom_j = rsd2.xyz( atom_num_j );
1849  Vector const d_ij = heavy_atom_j - heavy_atom_i;
1850  Distance const dist_ij = d_ij.length();
1851 
1852  if ( dist_ij > backbone_backbone_distance_cutoff_ ) continue;
1853 
1854  Real deriv( 0.0 );
1855  get_rna_backbone_backbone_score( dist_ij, m, deriv );
1856 
1857  Vector const f2( -1.0 * deriv * d_ij/ dist_ij );
1858  Vector const f1( 1.0 * cross( f2, heavy_atom_j ) );
1859 
1860  // std::cout << "BACKB_DERIV1 " << i << " " << atom_num_i << " " << j << " " << atom_num_j << " " << dist_ij << " ==> " << energy << " " << f1(1) << std::endl;
1861 
1862  F1 += f1;
1863  F2 += f2;
1864  }
1865  }
1866  } else {
1867 
1868  // SECOND WAY, check if this atom is a backbone oxygen atoms, cycle over other 2'-OH's.
1869  Size const n = find_backbone_oxygen_atom( atom_num_i );
1870 
1871  if ( n > 0 && rna_backbone_backbone_weight_( n ) >= 0.001 ) {
1872 
1873  Vector const heavy_atom_i = rsd1.xyz( atom_num_i );
1874 
1876  iter = energy_graph.get_node( i )->const_edge_list_begin();
1877  iter != energy_graph.get_node( i )->const_edge_list_end();
1878  ++iter ){
1879 
1880  Size j( (*iter)->get_other_ind( i ) );
1881 
1882  if ( abs ( static_cast<int>(i - j) ) <= 2 ) continue;
1883 
1884  conformation::Residue const & rsd2( pose.residue( j ) );
1885 
1886  // Go over 2'-OH atoms.
1888  Size const atom_num_j = atom_numbers_for_backbone_score_calculations_[ m ];
1889 
1890  Vector const & heavy_atom_j = rsd2.xyz( atom_num_j );
1891  Vector const d_ij = heavy_atom_j - heavy_atom_i;
1892  Distance const dist_ij = d_ij.length();
1893 
1894  if ( dist_ij > backbone_backbone_distance_cutoff_ ) continue;
1895 
1896  Real deriv( 0.0 );
1897  get_rna_backbone_backbone_score( dist_ij, n, deriv );
1898 
1899  Vector const f2( -1.0 * deriv * d_ij/ dist_ij );
1900  Vector const f1( 1.0 * cross( f2, heavy_atom_j ) );
1901 
1902  // std::cout << "BACKB_DERIV2 " << i << " " << atom_num_i << " " << j << " " << atom_num_j << " " << dist_ij << " ==> " << energy << " " << f1(1) << std::endl;
1903 
1904  F1 += f1;
1905  F2 += f2;
1906 
1907 
1908  }
1909  }
1910  }
1911 
1912  // std::cout << "BACKB_DERIV_SUM " << F1( 1) << " " << F2( 1 ) << std::endl;
1913 
1914 }
1915 
1916 ///////////////////////////////////////////////////////////////////////////////
1917 Real
1919  conformation::Residue const & rsd1,
1920  conformation::Residue const & rsd2
1921 ) const
1922 {
1923  return ( rna_repulsive_pair_energy_one_way( rsd1, rsd2 ) +
1924  rna_repulsive_pair_energy_one_way( rsd2, rsd1 ) ) ;
1925 }
1926 
1927 ///////////////////////////////////////////////////////////////////////////////
1928 Real
1930  conformation::Residue const & rsd1,
1931  conformation::Residue const & rsd2
1932 ) const
1933 {
1934 
1935  if ( !rsd1.is_RNA() ) return 0.0;
1936  if ( !rsd2.is_RNA() ) return 0.0;
1937 
1938  if ( rsd1.is_coarse() ) return 0.0; //coarse-grained!
1939  if ( rsd2.is_coarse() ) return 0.0; //coarse-grained!
1940 
1941  //Could use pair-moved to make this faster.
1942 
1943  Real rna_repulsive_score( 0.0 );
1944 
1945  //For speed, a cached set of atom numbers that go with RNA_backbone_oxygen_atoms_ (which is a bunch of strings)
1946  //rna::RNA_ScoringInfo const & rna_scoring_info( rna::rna_scoring_info_from_pose( pose ) );
1947  // ObjexxFCL::FArray2D< Size > const &
1948  // atom_numbers_for_backbone_score_calculations = rna_scoring_info.atom_numbers_for_backbone_score_calculations();
1949 
1950  Size const i = rsd1.seqpos();
1951  Size const j = rsd2.seqpos();
1952 
1953  // std::string const atom_i = " O2P";
1955 
1956  Vector const heavy_atom_i = rsd1.xyz( atom_num_i );
1957 
1958  if ( abs( static_cast<int>( i - j ) ) <= 2 ) return 0.0;
1959 
1960  // Go over sugar and phosphate oxygen atoms!
1961  for (Size m = 1; m <= num_RNA_backbone_oxygen_atoms_; m++ ){
1962 
1963  if ( rna_repulsive_weight_( m ) < 0.001 ) continue;
1964 
1965  Size const atom_num_j = atom_numbers_for_backbone_score_calculations_[ m ];
1966 
1967  //By default only repel o2p.
1969 
1970  //Don't double-count O2P <--> O2P interactions
1971  if (atom_num_j == atom_num_i && j < i) continue;
1972 
1973  Vector const heavy_atom_j( rsd2.xyz( atom_num_j ) );
1974 
1975  Vector const d_ij = heavy_atom_j - heavy_atom_i;
1976 
1977  Real const dist_ij = d_ij.length();
1978 
1979  if ( dist_ij > rna_repulsive_distance_cutoff_ ) continue;
1980 
1981  Real const score_contribution = get_rna_repulsive_score( dist_ij, m );
1982  rna_repulsive_score += score_contribution;
1983 
1984  if ( rna_verbose_ && score_contribution > 0.01 ){
1985  std::cout <<
1986  "REPULSIVE " <<
1987  rsd1.name3() <<
1988  I(3,i) << " " <<
1989  rsd2.atom_name( atom_num_i ) << " " <<
1990  rsd2.name3() <<
1991  I(3,j) << " " <<
1992  rsd2.atom_name( atom_num_j ) << " " <<
1993  F(6,2,score_contribution) << " [" << dist_ij << "]" <<
1994  std::endl;
1995  }
1996 
1997  }
1998 
1999  return rna_repulsive_score;
2000 
2001 }
2002 
2003 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2004 // Lot of code copying here -- should minirosetta++ derivative calculation be refactored?
2005 // Not so much for speed but due to code redundancy in defining loops, etc.
2006 //
2007 void
2009  id::AtomID const & atom_id,
2010  pose::Pose const & pose,
2011  Vector & F1,
2012  Vector & F2 ) const
2013 {
2014 
2015  Size const & i = atom_id.rsd();
2016  conformation::Residue const & rsd1( pose.residue( i ) );
2017  Size const & atom_num_i( atom_id.atomno() );
2018 
2019  F1 = 0.0;
2020  F2 = 0.0;
2021 
2022  if ( !rsd1.is_RNA() ) return;
2023 
2024  //For speed, a cached set of atom numbers that go with RNA_backbone_oxygen_atoms_ (which is a bunch of strings)
2025  // Need to do something different for the packer, dude. Maybe keep residue-type-specific indices
2026  // within the potential, determine by string lookup at the very beginning...
2027  //
2028  // rna::RNA_ScoringInfo const & rna_scoring_info( rna::rna_scoring_info_from_pose( pose ) );
2029  // ObjexxFCL::FArray2D< Size > const &
2030  // atom_numbers_for_backbone_score_calculations = rna_scoring_info.atom_numbers_for_backbone_score_calculations();
2031 
2033 
2034  EnergyGraph const & energy_graph( pose.energies().energy_graph() );
2035 
2036  if ( atom_num_i == atom_num_o2p ) {
2037  // FIRST WAY, check if this atom is O2P, cycle over other oxygen atoms.
2038 
2039  Vector const heavy_atom_i = rsd1.xyz( atom_num_i );
2040 
2042  iter = energy_graph.get_node( i )->const_edge_list_begin();
2043  iter != energy_graph.get_node( i )->const_edge_list_end();
2044  ++iter ){
2045 
2046  Size j( (*iter)->get_other_ind( i ) );
2047 
2048  if ( abs( static_cast<int>(i - j) ) <= 2 ) continue;
2049 
2050  conformation::Residue const & rsd2( pose.residue( j ) );
2051  if ( !rsd2.is_RNA() ) continue;
2052 
2053  // Go over sugar and phosphate oxygen atoms!
2054  for (Size m = 1; m <= num_RNA_backbone_oxygen_atoms_; m++ ){
2055 
2056  if ( rna_repulsive_weight_( m ) < 0.001 ) continue;
2057 
2058  //By default only repel o2p.
2060 
2061  Size const atom_num_j = atom_numbers_for_backbone_score_calculations_[ m ];
2062 
2063  // Don't double-count O2P <--> O2P interactions
2064  // if (atom_num_j == atom_num_i && j < i) continue;
2065 
2066  Vector const heavy_atom_j( rsd2.xyz( atom_num_j ) );
2067 
2068  Vector const d_ij = heavy_atom_j - heavy_atom_i;
2069 
2070  Real const dist_ij = d_ij.length();
2071 
2072  if ( dist_ij > rna_repulsive_distance_cutoff_ ) continue;
2073 
2074  Real deriv( 0.0 );
2075  get_rna_repulsive_score( dist_ij, m, deriv );
2076 
2077  Vector const f2( -1.0 * deriv * d_ij/ dist_ij );
2078  Vector const f1( 1.0 * cross( f2, heavy_atom_j ) );
2079 
2080  // std::cout << "DERIV1 " << i << " " << atom_num_i << " " << j << " " << atom_num_j << " " << f1(1) << std::endl;
2081 
2082  F1 += f1;
2083  F2 += f2;
2084 
2085  }
2086 
2087  }
2088  } else {
2089 
2090  // SECOND WAY, check if this atom is a backbone oxygen atoms, cycle over other O2P's.
2091  Size n = find_backbone_oxygen_atom( atom_num_i );
2092 
2093  if ( n > 0 && rna_repulsive_weight_( n ) >= 0.001 ) {
2094 
2095  Vector const heavy_atom_i = rsd1.xyz( atom_num_i );
2096 
2098  iter = energy_graph.get_node( i )->const_edge_list_begin();
2099  iter != energy_graph.get_node( i )->const_edge_list_end();
2100  ++iter ){
2101 
2102  Size j( (*iter)->get_second_node_ind() );
2103 
2104  //Edges always have first node < second node. Just in case we picked the wrong one:
2105  if (i == j) j = (*iter)->get_first_node_ind();
2106 
2107  if ( abs( static_cast<int>(i - j) ) <= 2 ) continue;
2108 
2109  conformation::Residue const & rsd2( pose.residue( j ) );
2110  if ( !rsd2.is_RNA() ) continue;
2111 
2112  // Go over O2P atoms.
2114  Size const atom_num_j = atom_numbers_for_backbone_score_calculations_[ m ];
2115 
2116  //By default only repel o2p.
2118 
2119  // Don't double-count O2P <--> O2P interactions
2120  // if (atom_num_j == atom_num_i && j < i) continue;
2121 
2122  Vector const heavy_atom_j( rsd2.xyz( atom_num_j ) );
2123 
2124  Vector const d_ij = heavy_atom_j - heavy_atom_i;
2125 
2126  Real const dist_ij = d_ij.length();
2127 
2128  if ( dist_ij > rna_repulsive_distance_cutoff_ ) continue;
2129 
2130  Real deriv( 0.0 );
2131  get_rna_repulsive_score( dist_ij, n, deriv );
2132 
2133  Vector const f2( -1.0 * deriv * d_ij/ dist_ij );
2134  Vector const f1( cross( f2, heavy_atom_j ) );
2135 
2136  // std::cout << "DERIV2 " << i << " " << atom_num_i << " " << j << " " << atom_num_j << " " << f1(1) << std::endl;
2137 
2138  F1 += f1;
2139  F2 += f2;
2140 
2141  }
2142 
2143  }
2144 
2145  }
2146 
2147  return;
2148 
2149 }
2150 
2151 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2152 void
2154 {
2155  //We don't know a priori which atom numbers correspond to which
2156  // atom names... can we assume that all RNA residues are the same, though?
2157 
2158  using namespace core::chemical;
2159  ResidueTypeSetCAP rsd_set;
2161 
2162  // will Guanosine work?
2164 
2165  // std::cout << "HELLO?" << check_atom_numbers_for_backbone_oxygens( rsd_set, na_rad ) << std::endl;
2166  // std::cout << "HELLO? " << check_atom_numbers_for_backbone_oxygens( rsd_set, na_rcy ) << std::endl;
2167  // std::cout << "HELLO? " << check_atom_numbers_for_backbone_oxygens( rsd_set, na_ura ) << std::endl;
2168 
2169  assert( check_atom_numbers_for_backbone_oxygens( rsd_set, na_rad ) );
2170  assert( check_atom_numbers_for_backbone_oxygens( rsd_set, na_rcy ) );
2171  assert( check_atom_numbers_for_backbone_oxygens( rsd_set, na_ura ) );
2172 
2173 }
2174 
2175 /////////////////////////////////////////////////////
2176 void
2178 {
2179  using namespace core::chemical;
2180 
2181  ResidueTypeCOPs const & rsd_types( rsd_set->aa_map( aa ) );
2182  ResidueTypeCOP const & rsd_type = rsd_types[ 1 ]; //This better work.
2183 
2184  for (Size m = 1; m <= num_RNA_backbone_oxygen_atoms_; m++ ) {
2185  atom_numbers_for_backbone_score_calculations_.push_back( rsd_type->atom_index( RNA_backbone_oxygen_atoms_[ m ] ) );
2186  }
2187 
2188 }
2189 
2190 /////////////////////////////////////////////////////
2191 bool
2193 {
2194  using namespace core::chemical;
2195 
2196  ResidueTypeCOPs const & rsd_types( rsd_set->aa_map( aa ) );
2197  ResidueTypeCOP const & rsd_type = rsd_types[ 1 ]; //This better work.
2198 
2199  for (Size m = 1; m <= num_RNA_backbone_oxygen_atoms_; m++ ) {
2200  if ( atom_numbers_for_backbone_score_calculations_[m] != rsd_type->atom_index( RNA_backbone_oxygen_atoms_[ m ] ) ) return false;
2201  }
2202 
2203  return true;
2204 }
2205 
2206 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2207 // DEPRECATED.
2208 // void
2209 // RNA_LowResolutionPotential::initialize_atom_numbers_for_backbone_score_calculations( pose::Pose & pose ) const
2210 // {
2211 // //We don't know a priori which atom numbers correspond to which
2212 // // atom names (e.g., O2* on an adenosine could be different depending
2213 // // on whether its at a chainbreak, terminus, etc.)
2214 // //Better to do a quick setup every time to pinpoint atoms that require
2215 // // monitoring for VDW clashes.
2216 
2217 // rna::RNA_ScoringInfo & rna_scoring_info( rna::nonconst_rna_scoring_info_from_pose( pose ) );
2218 // ObjexxFCL::FArray2D< Size > &
2219 // atom_numbers_for_backbone_score_calculations( rna_scoring_info.atom_numbers_for_backbone_score_calculations() );
2220 
2221 // Size const total_residue( pose.total_residue() );
2222 
2223 // atom_numbers_for_backbone_score_calculations.dimension( total_residue, num_RNA_backbone_oxygen_atoms_ );
2224 // atom_numbers_for_backbone_score_calculations = 0;
2225 
2226 // for (Size i = 1; i <= total_residue; i++ ) {
2227 // conformation::Residue const & rsd( pose.residue( i ) );
2228 
2229 // if ( rsd.is_RNA() ) {
2230 // for (Size m = 1; m <= num_RNA_backbone_oxygen_atoms_; m++ ) {
2231 // atom_numbers_for_backbone_score_calculations( i, m ) = rsd.atom_index( RNA_backbone_oxygen_atoms_[ m ] );
2232 // }
2233 // }
2234 // }
2235 
2236 // }
2237 
2238 //////////////////////////////////////////////////////////////////////////////////
2239 void
2241 {
2242  // ALL THIS "CALCULATED" BOOK-KEEPING WAS CONFUSING, AND NOW DOES NOT BUY ME MUCH.
2243 // rna::RNA_ScoringInfo & rna_scoring_info( rna::nonconst_rna_scoring_info_from_pose( pose ) );
2244 
2245 // rna::RNA_CentroidInfo & rna_centroid_info( rna_scoring_info.rna_centroid_info() );
2246 // rna_centroid_info.calculated() = false;
2247 
2248 // rna::RNA_RawBaseBaseInfo & rna_raw_base_base_info( rna_scoring_info.rna_raw_base_base_info() );
2249 // rna_raw_base_base_info.calculated() = false;
2250 }
2251 
2252 //////////////////////////////////////////////////////////
2253 bool
2255  pose::Pose & pose,
2256  Size const & i,
2257  int const & sign
2258 ) const
2259 {
2260 
2261  rna::RNA_ScoringInfo & rna_scoring_info( rna::nonconst_rna_scoring_info_from_pose( pose ) );
2262  rna::RNA_CentroidInfo & rna_centroid_info( rna_scoring_info.rna_centroid_info() );
2263  //Doesn't recalculate stuff if already updated:
2264  rna_centroid_info.update( pose );
2265 
2266  utility::vector1< Vector > const & base_centroids( rna_centroid_info.base_centroids() );
2267  utility::vector1< kinematics::Stub > const & base_stubs( rna_centroid_info.base_stubs() );
2268 
2269 
2270  // Real const Z_CUTOFF( 2.5 );
2271 
2272  // Size const total_residue = pose.total_residue();
2273  conformation::Residue const & res_i( pose.residue( i ) );
2274 
2275  if ( !res_i.is_RNA() ) return true;
2276 
2277  //Note that this centroid and stubs could be calculated once at the beginning of the scoring!!!
2278  Vector const & centroid_i( base_centroids[i] );
2279  kinematics::Stub const & stub_i( base_stubs[i] );
2280  Matrix const & M_i( stub_i.M );
2281  Vector const & x_i = M_i.col_x();
2282  Vector const & y_i = M_i.col_y();
2283  Vector const & z_i = M_i.col_z();
2284 
2285  for (Size j = 1; j <= pose.total_residue(); j++ ) {
2286  conformation::Residue const & res_j( pose.residue(j) );
2287 
2288  if (i==j) continue;
2289 
2290  for (Size m = 1; m <= res_j.natoms(); m++ ) {
2291 
2292  Vector const & atom_j( res_j.xyz( m ) );
2293 
2294  Vector d_ij = atom_j - centroid_i;
2295  Real const dist_x = dot_product( d_ij, x_i );
2296  Real const dist_y = dot_product( d_ij, y_i );
2297  Real const dist_z = dot_product( d_ij, z_i );
2298  Real const rho2 = dist_x*dist_x + dist_y*dist_y;
2299 
2300  // if (d_ij.length() < 6.0) std::cout << dist_z << " " << rho2 << std::endl;
2301  if ( (sign * dist_z) >= base_stack_min_height_ &&
2302  (sign * dist_z) <= base_stack_max_height_ &&
2303  rho2 < base_stack_radius2_ ) {
2304  //Possible BASE STACK1
2305  tr << "Found stacking atom on base " << i << ": " << j << " " << res_j.atom_name( m ) << std::endl;
2306  return false;
2307  } //basepair
2308 
2309  } //j
2310  }//i
2311 
2312  return true;
2313 }
2314 
2315 
2316 //////////////////////////////////////////////////////////
2317 bool
2319  pose::Pose & pose,
2320  Size const & i,
2321  Size const & j
2322 ) const
2323 {
2324 
2325  rna::RNA_ScoringInfo & rna_scoring_info( rna::nonconst_rna_scoring_info_from_pose( pose ) );
2326  rna::RNA_CentroidInfo & rna_centroid_info( rna_scoring_info.rna_centroid_info() );
2327  //Doesn't recalculate stuff if already updated:
2328  rna_centroid_info.update( pose );
2329 
2330  utility::vector1< Vector > const & base_centroids( rna_centroid_info.base_centroids() );
2331  utility::vector1< kinematics::Stub > const & base_stubs( rna_centroid_info.base_stubs() );
2332 
2333 
2334  // Real const Z_CUTOFF( 2.5 );
2335 
2336  // Size const total_residue = pose.total_residue();
2337  conformation::Residue const & res_i( pose.residue( i ) );
2338  conformation::Residue const & res_j( pose.residue( j ) );
2339 
2340  if ( !res_i.is_RNA() ) return false;
2341  if ( !res_j.is_RNA() ) return false;
2342 
2343  if (i==j) return false;
2344 
2345  //Note that this centroid and stubs could be calculated once at the beginning of the scoring!!!
2346  Vector const & centroid_i( base_centroids[i] );
2347  kinematics::Stub const & stub_i( base_stubs[i] );
2348  Matrix const & M_i( stub_i.M );
2349  Vector const & x_i = M_i.col_x();
2350  Vector const & y_i = M_i.col_y();
2351  Vector const & z_i = M_i.col_z();
2352 
2353  Vector const & centroid_j( base_centroids[j] );
2354  //kinematics::Stub const & stub_j( base_stubs[j] );
2355 
2356  // Matrix const & M_j( stub_j.M );
2357  // Vector const & x_j = M_j.col_x();
2358  // Vector const & y_j = M_j.col_y();
2359  // Vector const & z_j = M_j.col_z();
2360  // Real const cos_theta = dot_product( z_i, z_j );
2361 
2362  Vector d_ij = centroid_j - centroid_i;
2363  Real const dist_x = dot_product( d_ij, x_i );
2364  Real const dist_y = dot_product( d_ij, y_i );
2365  Real const dist_z = dot_product( d_ij, z_i );
2366  Real const rho2 = dist_x*dist_x + dist_y*dist_y;
2367 
2368  //Is it a base-pair, a base-stack, or do we ignore it?
2369  //Size edge_bin( 1 );
2370  if ( ( std::abs(dist_z) < rna_basepair_stagger_cutoff_ ) ){
2371  //A possible base pair
2372  if ( rho2 < rna_basepair_radius_cutoff2_ ){
2373  return true;
2374  }
2375  }
2376 
2377 
2378  return false;
2379 }
2380 
2381 
2382 
2383 }
2384 }
2385 }