Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RNA_Util.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 /// @author Rhiju Das
12 
13 // Unit headers
15 #include <core/types.hh>
16 
17 // Package headers
20 #include <core/id/TorsionID.hh>
22 // AUTO-REMOVED #include <core/kinematics/util.hh>
23 #include <core/kinematics/Stub.hh>
27 // AUTO-REMOVED #include <core/conformation/ResidueFactory.hh>
28 #include <core/pose/Pose.hh>
29 #include <core/chemical/AA.hh>
30 
31 // Project headers
32 #include <numeric/constants.hh>
33 
36 #include <utility/vector1.hh>
37 #include <numeric/xyz.functions.hh>
38 
39 #include <ObjexxFCL/string.functions.hh>
40 
41 // Utility headers
42 
43 // C++
44 
45 
46 namespace core {
47 namespace scoring {
48 namespace rna{
49 
50 ///////////////////////////////////////////////////////////////////////////////
51 Size
52 convert_acgu_to_1234( char const c )
53 {
54  if ( c == 'a') return 1;
55  if ( c == 'c') return 2;
56  if ( c == 'g') return 3;
57  if ( c == 'u') return 4;
58  return 0;
59 }
60 
61 /////////////////////////////////////////////////////////////////////////////
62 //This may be used elsewhere -- set up a util.hh?
63 char get_edge_from_num( Size const num ) {
64  if (num == WATSON_CRICK) return 'W';
65  if (num == HOOGSTEEN) return 'H';
66  if (num == SUGAR) return 'S';
67  if (num == O2STAR) return '2';
68  if (num == PHOSPHATE) return 'P';
69  return 'X';
70 }
71 
72 /////////////////////////////////////////////////////////////////////////////
73 std::string //Parin March 7, 2011
75  if (num == WATSON_CRICK) return "WC";
76  if (num == HOOGSTEEN) return "HOOG";
77  if (num == SUGAR) return "SUGAR";
78  if (num == O2STAR) return "O2STAR";
79  if (num == PHOSPHATE) return "PHOS";
80 
81  std::cout << "Invalid edge num= " << num << std::endl;
82  utility_exit_with_message("Invalid edge num!");
83  return "ERROR";
84 
85 }
86 
87 /////////////////////////////////////////////////////////////////////////////
88 //This may be used elsewhere -- set up a util.hh?
89 char get_orientation_from_num( Size const num ) {
90  if (num == 1) return 'A';
91  if (num == 2) return 'P';
92  return 'X';
93 }
94 
95 /////////////////////////////////////////////////////////////////////////////
96 
97 std::string //Parin March 7, 2011
99  if (num == 0) return "BLAH";
100  if (num == 1) return "ANTI";
101  if (num == 2) return "PARA";
102 
103  std::cout << "Invalid orientation num= " << num << std::endl;
104  utility_exit_with_message("Invalid orientation num!");
105  return "ERROR";
106 }
107 
108 std::string //Parin April 19, 2011
110  if (num == 0) return "BLAH ";
111  if (num == 1) return "CIS ";
112  if (num == 2) return "TRANS";
113 
114  std::cout << "Invalid orientation num= " << num << std::endl;
115  utility_exit_with_message("Invalid orientation num!");
116  return "ERROR";
117 }
118 
119 ///////////////////////////////////////////////////////////////////////////////
121  // if (rsd.name1() == 'a' || rsd.name1() == 'g' ) return " N9 ";
122  // return " N1 ";
123  return rsd.atom_name( first_base_atom_index( rsd ) );
124 }
125 
126 ///////////////////////////////////////////////////////////////////////////////
127 bool is_purine( conformation::Residue const & rsd ) {
128  if (rsd.name1() == 'a' || rsd.name1() == 'g' ) return true;
129  return false;
130 }
131 
132 
133 ///////////////////////////////////////////////////////////////////////////////
135  // HEY MAKE THIS MORE GENERAL? Maybe look at chi1?
136  chemical::AtomIndices const & atom_indices = rsd.chi_atoms( 1 /*chi # 1 must be nucleic acid "chi"*/ );
137  return atom_indices[ 3 ]; /* C2' ... C1' ... first base atom ... chi1 torsion atom*/
138 }
139 
140 ///////////////////////////////////////////////////////////////////////////////
142  // if (rsd.name1() == 'a' || rsd.name1() == 'g' ) return " N9 ";
143  // return " N1 ";
144  return rsd.atom_name( chi1_torsion_atom_index( rsd ) );
145 }
146 
147 
148 ///////////////////////////////////////////////////////////////////////////////
150  // HEY MAKE THIS MORE GENERAL? Maybe look at chi1?
151  chemical::AtomIndices const & atom_indices = rsd.chi_atoms( 1 /*chi # 1 must be nucleic acid "chi"*/ );
152  return atom_indices[ 4 ]; /* C2' ... C1' ... first base atom ... chi1 torsion atom*/
153 }
154 
155 
156 ///////////////////////////////////////////////////////////////////////////////
158  if ( rsd.is_RNA() ){
159  if ( !rsd.is_coarse() ){
160  return chi1_torsion_atom( rsd );
161  } else {
162  return " Y ";
163  }
164  }
165  if ( rsd.name3() == " MG" ) return "MG ";
166  if ( rsd.is_virtual_residue() ) return " Y ";
167 
168  std::cerr << "Residue ??? " << rsd.name3() << std::endl;
169  utility_exit_with_message( "Do not know jump atom for this residue" );
170 
171  return "????";
172 }
173 
174 ///////////////////////////////////////////////////////////////////////////////
175 bool
176 possibly_canonical( chemical::AA const & aa1, chemical::AA const & aa2 ) {
177  using namespace core::chemical;
178  return ( (aa1 == na_rgu && aa2 == na_rcy ) ||
179  (aa1 == na_rcy && aa2 == na_rgu ) ||
180  (aa1 == na_rgu && aa2 == na_ura ) ||
181  (aa1 == na_ura && aa2 == na_rgu ) ||
182  (aa1 == na_rad && aa2 == na_ura ) ||
183  (aa1 == na_ura && aa2 == na_rad ) );
184 }
185 
186 ///////////////////////////////////////////////////////////////////////////////
187 //no G-U
188 bool
190  using namespace core::chemical;
191  return ( (aa1 == na_rgu && aa2 == na_rcy ) ||
192  (aa1 == na_rcy && aa2 == na_rgu ) ||
193  (aa1 == na_rad && aa2 == na_ura ) ||
194  (aa1 == na_ura && aa2 == na_rad ) );
195 }
196 
197 ///////////////////////////////////////////////////////////////////////////////
198 void
200  chemical::AA const & aa1,
201  chemical::AA const & aa2,
202  std::string & atom1,
203  std::string & atom2 ) {
204 
205  using namespace core::chemical;
206 
207  if ( aa1==na_rad && aa2==na_ura) {
208  atom1 = " N1 ";
209  atom2 = " N3 ";
210  return;
211  }
212  if ( aa1==na_ura && aa2==na_rad) {
213  atom1 = " N3 ";
214  atom2 = " N1 ";
215  return;
216  }
217  if ( aa1==na_rgu && aa2==na_rcy) {
218  atom1 = " N1 ";
219  atom2 = " N3 ";
220  return;
221  }
222  if ( aa1==na_rcy && aa2==na_rgu) {
223  atom1 = " N3 ";
224  atom2 = " N1 ";
225  return;
226  }
227  if ( aa1==na_rgu && aa2==na_ura) {
228  atom1 = " O6 ";
229  atom2 = " N3 ";
230  return;
231  }
232  if ( aa1==na_ura && aa2==na_rgu) {
233  atom1 = " N3 ";
234  atom2 = " O6 ";
235  return;
236  }
237 
238  atom1 = "XXXX";
239  atom2 = "XXXX";
240  return;
241 }
242 
243 /////////////////////////////////////////////////////////////////////
244 void
246  chemical::AA const & aa1,
247  chemical::AA const & aa2,
249  utility::vector1< std::string > & atom_ids2 )
250 {
251 
252  using namespace chemical;
253 
254  atom_ids1.clear();
255  atom_ids2.clear();
256 
257  if ( aa1==na_rad && aa2==na_ura) {
258  atom_ids1.push_back( " N1 "); atom_ids2.push_back( " H3 ");
259  atom_ids1.push_back( "1H6 "); atom_ids2.push_back( " O4 ");
260  return;
261  } else if ( aa1==na_rgu && aa2==na_rcy) {
262  atom_ids1.push_back( " H1 "); atom_ids2.push_back( " N3 ");
263  atom_ids1.push_back( "2H2 "); atom_ids2.push_back( " O2 ");
264  atom_ids1.push_back( " O6 "); atom_ids2.push_back( "2H4 ");
265  return;
266  } else if ( aa1==na_rgu && aa2==na_ura) {
267  atom_ids1.push_back( " O6 "); atom_ids2.push_back( " H3 ");
268  atom_ids1.push_back( " H1 "); atom_ids2.push_back( " O2 ");
269  return;
270  } else if ( aa2==na_rad && aa1==na_ura) {
271  atom_ids2.push_back( " N1 "); atom_ids1.push_back( " H3 ");
272  atom_ids2.push_back( "1H6 "); atom_ids1.push_back( " O4 ");
273  return;
274  } else if ( aa2==na_rgu && aa1==na_rcy) {
275  atom_ids2.push_back( " H1 "); atom_ids1.push_back( " N3 ");
276  atom_ids2.push_back( "2H2 "); atom_ids1.push_back( " O2 ");
277  atom_ids2.push_back( " O6 "); atom_ids1.push_back( "2H4 ");
278  return;
279  } else if ( aa2==na_rgu && aa1==na_ura) {
280  atom_ids2.push_back( " O6 "); atom_ids1.push_back( " H3 ");
281  atom_ids2.push_back( " H1 "); atom_ids1.push_back( " O2 ");
282  return;
283  }
284 
285 
286 }
287 
288 //////////////////////////////////////////////////////
289 bool
290 is_cutpoint_open( core::pose::Pose const & pose, Size const i ) {
291 
292  if ( i < 1 ) return true; // user may pass zero -- sometimes checking if we are at a chain terminus, and this would corresponde to n-1 with n=1.
293 
294  if ( i >= pose.total_residue() ) return true;
295 
296  if ( ! pose.fold_tree().is_cutpoint(i) ) return false;
297 
299  pose.residue_type( i+1 ).has_variant_type( chemical::CUTPOINT_UPPER ) ) return false;
300 
301  return true;
302 }
303 
304 //////////////////////////////////////////////////////
305 bool
306 is_rna_chainbreak( core::pose::Pose const & pose, Size const i ) {
307 
308  static Real const CHAINBREAK_CUTOFF2 ( 2.5 * 2.5 );
309 
310  if ( i >= pose.total_residue() ) return true;
311  if ( i < 1 ) return true;
312 
313  conformation::Residue const & current_rsd( pose.residue( i ) ) ;
314  conformation::Residue const & next_rsd( pose.residue( i+1 ) ) ;
315 
316  //A little inefficient, since atom indices for these backbone
317  // atoms should be the same for all RNA residue types. I think.
318  Size atom_O3star = current_rsd.atom_index( " O3*" );
319  Size atom_P = next_rsd.atom_index( " P " );
320  Real const dist2 =
321  ( current_rsd.atom( atom_O3star ).xyz() - next_rsd.atom( atom_P ).xyz() ).length_squared();
322 
323  if ( dist2 > CHAINBREAK_CUTOFF2 ) {
324  //std::cout << "Found chainbreak at residue "<< i << " . O3*-P distance: " << sqrt( dist2 ) << std::endl;
325  return true;
326  }
327 
328  return false;
329 
330 }
331 
332 //////////////////////////////////////////////////
334 
335 void
337  static bool init( false );
338  if (init) return;
339 
340  non_main_chain_sugar_atoms.clear();
341  non_main_chain_sugar_atoms.push_back( " C2*" );
342  non_main_chain_sugar_atoms.push_back( " C1*" );
343  non_main_chain_sugar_atoms.push_back( " O4*" );
344 
345  init = true;
346 }
347 
348 ////////////////////////////////////////////////////////////////////////////
349 // Following is quite slow, because it works on a residue in the context
350 // of a full pose -- a lot of time wasted on refolding everything.
351 void
353  utility::vector1< std::string> atoms_for_which_we_need_new_dofs,
355  utility::vector1< Vector > const & non_main_chain_sugar_coords,
356  core::pose::Pose & pose,
357  core::Size const & i )
358 {
359 
360  using namespace core::id;
361 
362  conformation::Residue const & rsd( pose.residue( i ) );
363 
364  //Yup, hard-wired...
365  kinematics::Stub const input_stub( rsd.xyz( " C3*" ), rsd.xyz( " C3*" ), rsd.xyz( " C4*" ), rsd.xyz( " C5*" ) );
366 
367  utility::vector1< Vector > start_vectors;
369 
370  for (Size n = 1; n <= non_main_chain_sugar_atoms.size(); n++ ) {
371  Size const j = rsd.atom_index( non_main_chain_sugar_atoms[ n ] );
372  //Save a copy of starting location
373  Vector v = rsd.xyz( non_main_chain_sugar_atoms[ n ] );
374  start_vectors.push_back( v );
375 
376  //Desired location
377  Vector v2 = input_stub.local2global( non_main_chain_sugar_coords[ n ] );
378  pose.set_xyz( id::AtomID( j,i ), v2 );
379  }
380 
381  for (Size n = 1; n <= atoms_for_which_we_need_new_dofs.size(); n++ ) {
382  utility::vector1< Real > dof_set;
383  Size const j = rsd.atom_index( atoms_for_which_we_need_new_dofs[ n ] );
384  for (Size m = 1; m <= which_dofs[n].size(); m++ ) {
385  dof_set.push_back( pose.atom_tree().dof( DOF_ID( AtomID( j,i) , which_dofs[ n ][ m ] ) ) );
386  }
387  new_dof_sets.push_back( dof_set );
388  }
389 
390 
391  // Now put the ring atoms in the desired spots, but by changing internal DOFS --
392  // rest of the atoms (e.g., in base and 2'-OH) will scoot around as well, preserving
393  // ideal bond lengths and angles.
394  for (Size n = 1; n <= non_main_chain_sugar_atoms.size(); n++ ) {
395  Size const j = rsd.atom_index( non_main_chain_sugar_atoms[ n ] );
396  pose.set_xyz( id::AtomID( j,i ), start_vectors[n] );
397  }
398 
399  for (Size n = 1; n <= atoms_for_which_we_need_new_dofs.size(); n++ ) {
400  Size const j = rsd.atom_index( atoms_for_which_we_need_new_dofs[ n ] );
401 
402  for (Size m = 1; m <= which_dofs[n].size(); m++ ) {
403  pose.set_dof( DOF_ID( AtomID( j,i) , which_dofs[ n ][ m ] ), new_dof_sets[ n ][ m ] );
404  }
405 
406  }
407 }
408 
409 /////////////////////////////////////////////////////////
410 void
412  core::conformation::ResidueOP & scratch_rsd,
413  core::conformation::Residue const & start_rsd,
414  utility::vector1< Vector > const & non_main_chain_sugar_coords,
415  core::pose::Pose const & pose)
416 {
417 
418  for (Size j = 1; j < scratch_rsd->first_sidechain_atom(); j++ ){
419  scratch_rsd->set_xyz( j , start_rsd.xyz( j ) );
420  }
421 
422  //Yup, hard-wired...
423  kinematics::Stub const input_stub( scratch_rsd->xyz( " C3*" ), scratch_rsd->xyz( " C3*" ), scratch_rsd->xyz( " C4*" ), scratch_rsd->xyz( " C5*" ) );
424 
425  for (Size n = 1; n <= non_main_chain_sugar_atoms.size(); n++ ) {
426  //Desired location
427  Size const j = scratch_rsd->atom_index( non_main_chain_sugar_atoms[ n ] );
428  Vector v2 = input_stub.local2global( non_main_chain_sugar_coords[ n ] );
429  scratch_rsd->set_xyz( j, v2 );
430  }
431 
432  Size const o2star_index( scratch_rsd->atom_index( " O2*" ) );
433  scratch_rsd->set_xyz( o2star_index, scratch_rsd->build_atom_ideal( o2star_index, pose.conformation() ) );
434 
435 }
436 
437 
438 /////////////////////////////////////////////////////////
439 void
441  utility::vector1< std::string> atoms_for_which_we_need_new_dofs,
442  utility::vector1< Vector > const & non_main_chain_sugar_coords,
443  core::pose::Pose & pose,
444  core::pose::Pose const & reference_pose,
445  core::Size const & i
446  )
447 {
448 
449  using namespace core::id;
450  using namespace core::conformation;
451  using namespace core::kinematics;
452 
453  conformation::Residue const & start_rsd( reference_pose.residue( i ) );
454 
455  static ResidueOP scratch_rsd( new Residue( start_rsd.type(), false /*dummy arg*/ ) );
456 
457  prepare_scratch_residue( scratch_rsd, start_rsd, non_main_chain_sugar_coords, pose );
458 
459  for (Size n = 1; n <= atoms_for_which_we_need_new_dofs.size(); n++ ) {
460  Size const j = scratch_rsd->atom_index( atoms_for_which_we_need_new_dofs[ n ] );
461 
462  // "Don't do update" --> my hack to prevent lots of refolds. I just want information about whether the
463  // atom is a jump_atom, what its stub atoms are, etc... in principle could try to use input_stub_atom1_id(), etc.
464  core::kinematics::tree::AtomCOP current_atom ( & reference_pose.atom_tree().atom_dont_do_update( AtomID(j,i) ) );
465  core::kinematics::tree::AtomCOP input_stub_atom1( current_atom->input_stub_atom1() );
466 
467  if ( !input_stub_atom1) continue;
468  if ( (input_stub_atom1->id()).rsd() != (current_atom->id()).rsd() ) continue;
469  if ( (input_stub_atom1->id()).atomno() > scratch_rsd->first_sidechain_atom() ) continue;
470 
471  Real const d = ( scratch_rsd->xyz( (input_stub_atom1->id()).atomno() ) -
472  scratch_rsd->xyz( (current_atom->id()).atomno() ) ).length();
473  pose.set_dof( DOF_ID( AtomID( j, i), D), d );
474 
475  if ( input_stub_atom1->is_jump() ) continue;
476 
477  core::kinematics::tree::AtomCOP input_stub_atom2( current_atom->input_stub_atom2() );
478  if ( !input_stub_atom2) continue;
479  if ( (input_stub_atom2->id()).rsd() != (current_atom->id()).rsd() ) continue;
480  if ( (input_stub_atom2->id()).atomno() > scratch_rsd->first_sidechain_atom() ) continue;
481 
482  Real const theta = numeric::angle_radians(
483  scratch_rsd->xyz( (current_atom->id()).atomno() ) ,
484  scratch_rsd->xyz( (input_stub_atom1->id()).atomno() ),
485  scratch_rsd->xyz( (input_stub_atom2->id()).atomno() ) );
486 
487  pose.set_dof( DOF_ID( AtomID( j, i), THETA), numeric::constants::d::pi - theta );
488 
489  // I commented out the following because otherwise, O4* at the 5' end of a pose did not get set properly. (RD, Nov. 2010)
490  // but there may be fallout.
491  // if ( input_stub_atom2->is_jump() ) continue; //HEY NEED TO BE CAREFUL HERE.
492 
493  core::kinematics::tree::AtomCOP input_stub_atom3( current_atom->input_stub_atom3() );
494 
495  if ( !input_stub_atom3) continue;
496  if ( (input_stub_atom3->id()).rsd() != (current_atom->id()).rsd() ) continue;
497  if ( (input_stub_atom3->id()).atomno() > scratch_rsd->first_sidechain_atom() ) continue;
498 
499  Real const phi = numeric::dihedral_radians(
500  scratch_rsd->xyz( (current_atom->id()).atomno() ),
501  scratch_rsd->xyz( (input_stub_atom1->id()).atomno() ),
502  scratch_rsd->xyz( (input_stub_atom2->id()).atomno() ),
503  scratch_rsd->xyz( (input_stub_atom3->id()).atomno() ) );
504 
505  pose.set_dof( DOF_ID( AtomID( j, i), PHI), phi );
506 
507  }
508 }
509 
510 //////////////////////////////////////////////////////////////////////////////
511 void
513  utility::vector1< std::string > & atoms_for_which_we_need_new_dofs,
514  pose::Pose const & pose, Size const & i
515 )
516 {
517 
518  using namespace core::id;
519  using namespace core::scoring::rna;
520  using namespace core::kinematics;
521  using namespace conformation;
522 
523  //
524  // Which way does atom_tree connectivity flow, i.e. is sugar drawn after base,
525  // or after backbone?
526  // This is admittedly very ugly, and very RNA specific.
527  // ... perhaps this will be figured out in the Cartesian Fragment class?
528  //
529  conformation::Residue const & rsd( pose.residue( i ) );
530 
531  core::kinematics::tree::AtomCOP c1star_atom ( & pose.atom_tree().atom( AtomID( rsd.atom_index( " C1*" ), i ) ) );
532  core::kinematics::tree::AtomCOP o2star_atom ( & pose.atom_tree().atom( AtomID( rsd.atom_index( " O2*" ), i ) ) );
533  core::kinematics::tree::AtomCOP c2star_atom ( & pose.atom_tree().atom( AtomID( rsd.atom_index( " C2*" ), i ) ) );
534 
535  if ( (c1star_atom->parent()->id()).atomno() == first_base_atom_index( rsd ) ) {
536  // There's a jump to this residue.
537  //std::cout << "RESIDUE WITH JUMP CONNECTIVITY : " << i << std::endl;
538  atoms_for_which_we_need_new_dofs.push_back( " C2*" );
539  atoms_for_which_we_need_new_dofs.push_back( " C3*" );
540  atoms_for_which_we_need_new_dofs.push_back( " O4*" );
541  atoms_for_which_we_need_new_dofs.push_back( " C4*" );
542  atoms_for_which_we_need_new_dofs.push_back( " C5*" );
543  atoms_for_which_we_need_new_dofs.push_back( " O3*" );
544 
545  } else if ( (c2star_atom->parent()->id()).atomno() == (o2star_atom->id()).atomno() ) {
546 
547  atoms_for_which_we_need_new_dofs.push_back( " C1*" );
548  atoms_for_which_we_need_new_dofs.push_back( " C3*" );
549  atoms_for_which_we_need_new_dofs.push_back( " O4*" );
550  atoms_for_which_we_need_new_dofs.push_back( " C4*" );
551  atoms_for_which_we_need_new_dofs.push_back( " C5*" );
552  atoms_for_which_we_need_new_dofs.push_back( " O3*" );
553 
554  } else {
555 
556  atoms_for_which_we_need_new_dofs.push_back( " C1*" );
557  atoms_for_which_we_need_new_dofs.push_back( " C2*" );
558  atoms_for_which_we_need_new_dofs.push_back( " O4*" );
559 
560  }
561 
562 }
563 
564 
565 /////////////////////////////////////////////////////////////////////
566 //* Passing in a "reference" pose is a dirty trick to prevent
567 // computationally expensive refolds whenever we change a DOF in the pose.
568 void
570  utility::vector1< Vector > const & non_main_chain_sugar_coords,
571  core::pose::Pose & pose,
572  core::pose::Pose const & reference_pose,
573  core::Size const & i
574  )
575 {
576 
577  using namespace core::id;
578  using namespace core::scoring::rna;
579 
580  /////////////////////////////////////////////
581  // Save desired torsion values.
582  utility::vector1< Real > start_torsions;
583  for (Size j = 1; j <= NUM_RNA_TORSIONS; j++) {
584  id::TorsionID rna_torsion_id( i, id::BB, j );
585  if ( j > NUM_RNA_MAINCHAIN_TORSIONS) rna_torsion_id = id::TorsionID( i, id::CHI, j - NUM_RNA_MAINCHAIN_TORSIONS );
586  start_torsions.push_back( reference_pose.torsion( rna_torsion_id ) );
587  }
588 
589  /////////////////////////////////////////////
590  //What DOFS do I need to get the ring atoms where I want them?
592  utility::vector1< std::string > atoms_for_which_we_need_new_dofs;
593 
594  initialize_atoms_for_which_we_need_new_dofs( atoms_for_which_we_need_new_dofs, pose, i );
595 
596  fix_sugar_coords( atoms_for_which_we_need_new_dofs, non_main_chain_sugar_coords, pose, reference_pose, i );
597 
598  /////////////////////////////////////////////
599  // Reapply desired torsion values.
600  for (Size j = 1; j <= NUM_RNA_TORSIONS; j++) {
601  id::TorsionID rna_torsion_id( i, id::BB, j );
602  if ( j > NUM_RNA_MAINCHAIN_TORSIONS) rna_torsion_id = id::TorsionID( i, id::CHI, j - NUM_RNA_MAINCHAIN_TORSIONS );
603  pose.set_torsion( rna_torsion_id, start_torsions[ j ] );
604  }
605 
606 }
607 
608 ////////////////////////////////////////////////////////////////////
609 void
611  core::pose::Pose & pose,
612  core::Size const & i
613  )
614 {
615 
616  //Torsion angles associated with a 2'-endo sugar in 1jj2 (large ribosomal subunit xtal structure ).
617  pose.set_torsion( core::id::TorsionID( i, id::BB, 1), 69.404192 );
618  pose.set_torsion( core::id::TorsionID( i, id::BB, 2), -173.031790 );
619  pose.set_torsion( core::id::TorsionID( i, id::BB, 3), 58.877828 );
620  pose.set_torsion( core::id::TorsionID( i, id::BB, 4), 147.202313 );
621  pose.set_torsion( core::id::TorsionID( i, id::BB, 5), -85.360367 );
622  pose.set_torsion( core::id::TorsionID( i, id::BB, 6), -38.381256 );
623  pose.set_torsion( core::id::TorsionID( i, id::CHI, 1), 111.708846 );
624  pose.set_torsion( core::id::TorsionID( i, id::CHI, 2), -36.423711 );
625  pose.set_torsion( core::id::TorsionID( i, id::CHI, 3), 156.438552 );
626  pose.set_torsion( core::id::TorsionID( i, id::CHI, 4), 179.890442 );
627 
628  utility::vector1< Vector > non_main_chain_sugar_coords;
629  non_main_chain_sugar_coords.push_back( Vector( 0.329122, -0.190929, -1.476983 ) );
630  non_main_chain_sugar_coords.push_back( Vector( -0.783512, -1.142556, -1.905737 ) );
631  non_main_chain_sugar_coords.push_back( Vector( -1.928054, -0.731911, -1.195034 ) );
632 
633  apply_non_main_chain_sugar_coords( non_main_chain_sugar_coords, pose, pose, i );
634 
635 
636 }
637 
638 ///////////////////////////////////////////////////////////////////////////////
639 // Simple cubic spline.
640 void
642  Real const z,
643  Real const cutoff_lower,
644  Real const cutoff_upper,
645  Real const fade_zone,
646  Real & fade_value,
647  Real & fade_deriv )
648 {
649  assert( fade_zone > 0 );
650 
651  fade_value = 1.0;
652  fade_deriv = 0.0;
653 
654  if (z < cutoff_lower || z > cutoff_upper ){
655  fade_value = 0.0;
656  } else if ( z < cutoff_lower + fade_zone ) {
657  //Check little strip near lower cutoff.
658  Real const b = -1.0 * ( z - (cutoff_lower + fade_zone) )/ fade_zone;
659  Real const b2 = b*b;
660  Real const b3 = b2*b;
661  fade_value = ( 2 * b3 - 3 * b2 + 1 );
662  fade_deriv = -1.0 * (6 * b2 - 6 * b ) / fade_zone;
663  } else if ( z > cutoff_upper - fade_zone ) {
664  //Check little strip near upper cutoff.
665  Real const b = ( z - (cutoff_upper - fade_zone) )/ fade_zone;
666  Real const b2 = b*b;
667  Real const b3 = b2*b;
668  fade_value = ( 2 * b3 - 3 * b2 + 1 );
669  fade_deriv = (6 * b2 - 6 * b ) / fade_zone;
670  }
671 
672  return;
673 
674 }
675 
676 ///////////////////////////////////////////////////////////////////////////////////////////////
677 //Unify the version in StepWiseRNA_Utill.cc and RNA_CentroidInfo.cc on June 25, 2011
678 // Also, this copies some code from Phil's dna/base_geometry.cc
679 //Comments (Parin Sep 23 ,2009)...possible problem if every atoms in the nucleotide is virtual...in that case numatoms=0....will this crash the code??
680 
681 Vector
682 get_rna_base_centroid( conformation::Residue const & rsd , bool verbose){
683 
684  if( rsd.is_RNA()==false) utility_exit_with_message("rsd.is_RNA()==false");
685 
686  Vector centroid( 0.0 );
687  Size numatoms = 0;
688 
689  //Consistency check:
690  //if(rsd.type().atom_name(rsd.first_sidechain_atom()) !=" O2*") utility_exit_with_message( "rsd.type().atom_name(rsd.first_sidechain_atom()) !=\" O2*\" " );
691  //if(rsd.atom_name( rsd.first_sidechain_atom() )!=" O2*") utility_exit_with_message("rsd.atom_name( rsd.first_sidechain_atom() )!=\" O2*\"");
692 
693  if( rsd.RNA_type().o2star_index()!=rsd.first_sidechain_atom() ){
694  utility_exit_with_message( "rsd.RNA_info().o2star_index()!=rsd.first_sidechain_atom()");
695  }
696 
697  if(verbose) std::cout << "Base atoms" << std::endl;
698 
699  for ( Size i=rsd.first_sidechain_atom()+1; i<= rsd.nheavyatoms(); ++i ) { //rsd.first_sidechain_atom()+1 to not include the O2star oxygen.
700 
701  if(verbose) std::cout << "atom " << i << " " << "name= " << rsd.type().atom_name(i) << " type= " << rsd.atom_type(i).name() << " " << rsd.atom_type_index(i) << " " << rsd.atomic_charge(i);
702 
703  if(rsd.RNA_type().atom_is_virtual(i)){
704  if(verbose) std::cout << " Virtual type: Ignore! " << std::endl;
705  continue;
706  }
707 
708  if(verbose) std::cout << std::endl;
709 
710  centroid += rsd.xyz(i);
711  numatoms++;
712  }
713 
714  if(numatoms==0){//Centroid not well defined in this case...probably because rsd is a virtual residue...just return 0
715  Vector dummy_centroid( 0.0 );
716  return dummy_centroid;
717  }
718 
719  centroid /= static_cast< Real >( numatoms );
720 
721  return centroid;
722 }
723 
724 
725 
726 
727 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
728 
729 //Unify the version in StepWiseRNA_Utill.cc and RNA_CentroidInfo.cc on June 25, 2011
732 
733  using namespace chemical;
734 
735  if( rsd.is_RNA()==false) utility_exit_with_message("rsd.is_RNA()==false");
736 
737  Size res_type = rsd.aa();
738 
739  Vector x,y,z;
740 
741  // Make an axis pointing from base centroid to Watson-Crick edge.
742  std::string WC_atom;
743  if ( res_type == na_rad ) WC_atom = " N1 ";
744  if ( res_type == na_rcy ) WC_atom = " N3 ";
745  if ( res_type == na_rgu ) WC_atom = " N1 ";
746  if ( res_type == na_ura ) WC_atom = " N3 ";
747 
748  Vector const WC_coord (rsd.xyz( WC_atom ) );
749  x = WC_coord - centroid;
750  x.normalize();
751 
752  // Make a perpendicular axis pointing from centroid towards
753  // Hoogstein edge (e.g., major groove in a double helix).
754  std::string H_atom;
755  if ( res_type == na_rad ) H_atom = "N7";
756  if ( res_type == na_rcy ) H_atom = "C5";
757  if ( res_type == na_rgu ) H_atom = "N7";
758  if ( res_type == na_ura ) H_atom = "C5";
759 
760  Vector const H_coord (rsd.xyz( H_atom ) );
761  y = H_coord - centroid; //not orthonormal yet...
762  z = cross(x, y);
763  z.normalize(); // Should poSize roughly 5' to 3' if in a double helix.
764 
765  y = cross(z, x);
766  y.normalize(); //not necessary but doesn't hurt.
767 
768 
770  return M;
771 
772 }
773 
774 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
775 //Check whether one of the atom beyond to a base and another to a phosphate. Doesn't have to be on the same nucleotide.
776 bool
777 Is_base_phosphate_atom_pair( conformation::Residue const & rsd_1, conformation::Residue const & rsd_2, Size const atomno_1, Size const atomno_2){
778 
779  bool Is_base_phosphate_atom_pair=false;
780 
781  if( ( rsd_1.RNA_type().atom_is_phosphate( atomno_1 ) && (rsd_2.RNA_type().is_RNA_base_atom( atomno_2 ) ) ) ) Is_base_phosphate_atom_pair=true;
782  if( ( rsd_2.RNA_type().atom_is_phosphate( atomno_2 ) && (rsd_1.RNA_type().is_RNA_base_atom( atomno_1 ) ) ) ) Is_base_phosphate_atom_pair=true;
783 
784  if(Is_base_phosphate_atom_pair){ //This Assume that rsd_1 and rsd_2 are the same!!!
785  if( rsd_1.seqpos()==rsd_2.seqpos() && (rsd_1.path_distance( atomno_1, atomno_2 ) < 4) ){ //consistency check!
786  utility_exit_with_message("Is_base_phosphate_atom_pair but rsd.path_distance( " + ObjexxFCL::string_of(atomno_1) + " , " + ObjexxFCL::string_of(atomno_2) + " ) < 4");
787  }
788  }
789 
791 
792 }
793 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
794 
795 } //ns rna
796 } //ns scoring
797 } //ns core