Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RNA_ProtocolUtil.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 relax_protocols
11 /// @brief protocols that are specific to RNA_FragmentMover
12 /// @detailed
13 /// @author Rhiju Das
14 
15 
33 
34 
35 #include <core/pose/Pose.hh>
37 #include <core/pose/util.hh>
40 #include <core/id/AtomID.hh>
41 #include <core/id/NamedAtomID.hh>
42 #include <core/id/TorsionID.hh>
45 // AUTO-REMOVED #include <core/chemical/util.hh>
46 #include <core/types.hh>
47 #include <basic/Tracer.hh>
48 
49 // ObjexxFCL Headers
50 #include <ObjexxFCL/FArray1D.hh>
51 #include <ObjexxFCL/string.functions.hh>
52 
53 // External library headers
54 // AUTO-REMOVED #include <numeric/random/random.hh>
55 #include <utility/io/ozstream.hh>
56 
57 //C++ headers
58 #include <vector>
59 #include <string>
60 #include <sstream>
61 #include <fstream>
62 // AUTO-REMOVED #include <ctime>
63 
65 #include <utility/vector1.hh>
66 #include <numeric/xyz.functions.hh>
67 #include <ObjexxFCL/format.hh>
68 
69 
70 using namespace core;
71 using namespace ObjexxFCL;
72 using namespace ObjexxFCL::fmt;
73 using basic::T;
74 
75 static basic::Tracer TR( "protocols.rna.rna_protocol_util" ) ;
76 
77 namespace protocols {
78 namespace rna {
79 
80 ///////////////////////////////////////////////////////////////////////////////
81 ///////////////////////////////////////////////////////////////////////////////
82 // A bunch of helper functions used in rna apps...
83 ///////////////////////////////////////////////////////////////////////////////
84 ///////////////////////////////////////////////////////////////////////////////
85 ///////////////////////////////////////////////////////////////////////////////
86 void
88 {
89  using namespace core::conformation;
90 
91  //Look for chainbreaks in PDB.
92  Size const nres = pose.total_residue();
93  kinematics::FoldTree f( nres );
94 
95  Size m( 0 );
96 
97  for (Size i=1; i < nres; ++i) {
98 
99  if ( !pose.residue(i).is_RNA() && !pose.residue(i+1).is_RNA() ) continue;
100 
101  if ( ( pose.residue(i).is_RNA() && !pose.residue(i+1).is_RNA() ) ||
102  ( !pose.residue(i).is_RNA() && pose.residue(i+1).is_RNA() ) ) {
103  f.new_jump( i, i+1, i );
104  m++;
105  continue;
106  }
107 
108  if ( scoring::rna::is_rna_chainbreak( pose, i ) ){
109 
110  //std::cout << "CHAINBREAK between " << i << " and " << i+1 << std::endl;
111 
112  f.new_jump( i, i+1, i );
113  m++;
114 
115  Residue const & current_rsd( pose.residue( i ) ) ;
116  Residue const & next_rsd( pose.residue( i+1 ) ) ;
117  // Size dummy( 0 ), jump_atom1( 0 ), jump_atom2( 0 );
118  //rna_basepair_jump_atoms( current_rsd.aa(), jump_atom1, dummy, dummy );
119  //rna_basepair_jump_atoms( next_rsd.aa(), jump_atom2, dummy, dummy );
120  //f.set_jump_atoms( m, current_rsd.atom_name( jump_atom1 ), next_rsd.atom_name( jump_atom2 ) );
121 
122  f.set_jump_atoms( m,
125 
126  }
127 
128  }
129 
130  pose.fold_tree( f );
131 }
132 
133 ///////////////////////////////////////////////////////////////////////////////
134 void
136  Size const & seqpos,
137  char & secstruct,
138  FArray1D <bool> & edge_is_base_pairing ){
139 
140  using namespace core::scoring::rna;
141  using namespace core::chemical;
142  using namespace core::conformation;
143 
144  RNA_ScoringInfo const & rna_scoring_info( rna_scoring_info_from_pose( pose ) );
145  RNA_FilteredBaseBaseInfo const & rna_filtered_base_base_info( rna_scoring_info.rna_filtered_base_base_info() );
146  Energy_base_pair_list const & scored_base_pair_list( rna_filtered_base_base_info.scored_base_pair_list() );
147 
148  edge_is_base_pairing.dimension( 3 );
149  edge_is_base_pairing = false;
150 
151  bool forms_canonical_base_pair( false ), forms_base_pair( false );
152 
153  Size k( 0 ), m( 0 );
154  for ( Energy_base_pair_list::const_iterator it = scored_base_pair_list.begin();
155  it != scored_base_pair_list.end(); ++it ){
156 
157  Base_pair const base_pair = it->second;
158 
159  Size const i = base_pair.res1;
160  Size const j = base_pair.res2;
161 
162  if ( i == seqpos ){
163  k = base_pair.edge1;
164  m = base_pair.edge2;
165  } else if ( j == seqpos ){
166  k = base_pair.edge2;
167  m = base_pair.edge1;
168  } else {
169  continue;
170  }
171 
172  edge_is_base_pairing( k ) = true;
173  forms_base_pair = true;
174 
175  Residue const & rsd_i( pose.residue( i ) );
176  Residue const & rsd_j( pose.residue( j ) );
177 
178  if ( ( k == WATSON_CRICK && m == WATSON_CRICK
179  && base_pair.orientation == 1 ) &&
180  possibly_canonical( rsd_i.aa(), rsd_j.aa() ) ) {
181  std::string atom1, atom2;
182 
183  if ( !rsd_i.is_coarse() ) { // doesn't work for coarse-grained RNA
184  get_watson_crick_base_pair_atoms( rsd_i.aa(), rsd_j.aa(), atom1, atom2 );
185  if ( ( rsd_i.xyz( atom1 ) - rsd_j.xyz( atom2 ) ).length() > 3.5 ) continue;
186  }
187 
188  forms_canonical_base_pair = true;
189 
190  }
191  }
192 
193  secstruct = 'N';
194  if (forms_canonical_base_pair ) {
195  secstruct = 'H';
196  } else if (forms_base_pair ){
197  secstruct = 'P';
198  }
199 }
200 
201 
202 
203 ///////////////////////////////////////////////////////////////////////////////
204 void
206  utility::vector1< std::pair<Size, Size> > & base_pairing_list ){
207 
208  using namespace core::scoring;
209  using namespace core::chemical;
210  using namespace core::conformation;
211  using namespace core::scoring::rna;
212 
213  // Need some stuff to figure out which residues are base paired. First score.
214  ScoreFunctionOP scorefxn( new ScoreFunction );
215  scorefxn->set_weight( rna_base_pair, 1.0 );
216  (*scorefxn)( pose );
217 
218  RNA_ScoringInfo const & rna_scoring_info( rna_scoring_info_from_pose( pose ) );
219  RNA_FilteredBaseBaseInfo const & rna_filtered_base_base_info( rna_scoring_info.rna_filtered_base_base_info() );
220  Energy_base_pair_list const & scored_base_pair_list( rna_filtered_base_base_info.scored_base_pair_list() );
221 
222  // bool forms_canonical_base_pair( false );
223 
224  Size k( 0 ), m( 0 );
225 
226  std::list < std::pair< Size,Size > > base_pair_list0;
227 
228  for ( Energy_base_pair_list::const_iterator it = scored_base_pair_list.begin();
229  it != scored_base_pair_list.end(); ++it ){
230 
231  Base_pair const base_pair = it->second;
232 
233  Size const i = base_pair.res1;
234  Size const j = base_pair.res2;
235 
236  if ( i > j ) continue;
237 
238  k = base_pair.edge1;
239  m = base_pair.edge2;
240 
241  Residue const & rsd_i( pose.residue( i ) );
242  Residue const & rsd_j( pose.residue( j ) );
243 
244  if ( ( k == WATSON_CRICK && m == WATSON_CRICK
245  && base_pair.orientation == 1 ) &&
246  possibly_canonical( rsd_i.aa(), rsd_j.aa() ) ) {
247  std::string atom1, atom2;
248 
249  if ( !rsd_i.is_coarse() ) { // doesn't work for coarse-grained RNA
250  get_watson_crick_base_pair_atoms( rsd_i.aa(), rsd_j.aa(), atom1, atom2 );
251  if ( ( rsd_i.xyz( atom1 ) - rsd_j.xyz( atom2 ) ).length() > 3.5 ) continue;
252  }
253 
254  base_pair_list0.push_back( std::make_pair( i, j ) );
255 
256  }
257  }
258 
259 
260  base_pair_list0.sort();
261  base_pairing_list.clear();
262  for ( std::list< std::pair<Size,Size > >::const_iterator it = base_pair_list0.begin();
263  it != base_pair_list0.end(); ++it ){
264  base_pairing_list.push_back( *it );
265  }
266 
267 }
268 
269 
270 ///////////////////////////////////////////////////////////////////////////////
271 void
273  using namespace core::scoring;
274  using namespace ObjexxFCL;
275 
276  // Need some stuff to figure out which residues are base paired. First score.
277  ScoreFunctionOP scorefxn( new ScoreFunction );
278  scorefxn->set_weight( rna_base_pair, 1.0 );
279  (*scorefxn)( pose );
280 
281  std::string secstruct = "";
282  FArray1D < bool > edge_is_base_pairing( 3, false );
283  char secstruct1( 'X' );
284  for (Size i=1; i <= pose.total_residue() ; ++i) {
285  get_base_pairing_info( pose, i, secstruct1, edge_is_base_pairing );
286  secstruct += secstruct1;
287  }
288 
289  std::cout << "SECSTRUCT: " << secstruct << std::endl;
290 
291  set_rna_secstruct( pose, secstruct );
292 
293 }
294 
295 
296 ///////////////////////////////////////////////////////////////////////////////
297 void
299  utility::io::ozstream & torsions_out,
300  utility::vector1 <Size> const & exclude_res_list )
301 {
302 
303  using namespace core::chemical;
304  using namespace core::scoring;
305  using namespace core::scoring::rna;
306  using namespace protocols::rna;
307 
308  Size const total_residue = pose.total_residue();
309 
311 
312  // Need some stuff to figure out which residues are base paired. First score.
313  ScoreFunctionOP scorefxn( new ScoreFunction );
314  scorefxn->set_weight( rna_base_pair, 1.0 );
315  (*scorefxn)( pose );
316  scorefxn->show( std::cout, pose );
317 
318  bool const idealize_frag( false );
320  idealizer.fast( false /* option[ fast ] */ );
321 
322  // EnergyGraph const & energy_graph( pose.energies().energy_graph() );
323 
325 
326  for (Size i=1; i <= total_residue; ++i) {
327  if ( is_num_in_list(i, exclude_res_list) ) continue;
328 
329  torsions_out << pose.residue( i ).name1() << " " ;
330 
331  if (idealize_frag ) {
332 
333  ////////////////////////////////////////////////
334  // NEW: can we idealize this thing?
335  pose::Pose mini_pose;
336  Size offset = 1;
337  if ( i > 1 ) {
338  mini_pose.append_residue_by_bond( pose.residue( i-1 ) );
339  offset = 2;
340  }
341  mini_pose.append_residue_by_bond( pose.residue( i ) );
342  if ( i < total_residue ){
343  mini_pose.append_residue_by_bond( pose.residue( i+1 ) );
344  }
345 
347  idealizer.apply( mini_pose );
348  idealizer.apply( mini_pose );
349 
351  id::TorsionID my_ID( offset, id::BB, j );
352  torsions_out << F( 12, 6, mini_pose.torsion( my_ID ) );
353  }
354 
355  for (Size j=1; j <= core::scoring::rna::NUM_RNA_CHI_TORSIONS; ++j) {
356  id::TorsionID my_ID( offset, id::CHI, j );
357  torsions_out << F( 12, 6, mini_pose.torsion( my_ID ) ) << " ";
358  }
359 
360  } else {
362  id::TorsionID my_ID( i, id::BB, j );
363  torsions_out << F( 12, 6, pose.torsion( my_ID ) );
364  }
365 
366  for (Size j=1; j <= core::scoring::rna::NUM_RNA_CHI_TORSIONS; ++j) {
367  id::TorsionID my_ID( i, id::CHI, j );
368  torsions_out << F( 12, 6, pose.torsion( my_ID ) ) << " ";
369  }
370 
371  //New (Feb., 2009) ...
372  // x-y-z of coordinates of C2*, C1*, and O4*, in a local coordiante system defined
373  // by C3*, C4*, and C5* (as "stub" atoms).
374  conformation::Residue rsd = pose.residue( i );
375  kinematics::Stub const input_stub( rsd.xyz( " C3*" ), rsd.xyz( " C3*" ), rsd.xyz( " C4*" ), rsd.xyz( " C5*" ) );
376 
377  torsions_out << " S " ;
378  for (Size n = 1; n <= non_main_chain_sugar_atoms.size(); n++ ) {
379  Vector v = input_stub.global2local( rsd.xyz( non_main_chain_sugar_atoms[ n ] ) );
380  torsions_out << F( 12, 6, v.x() ) << " " ;
381  torsions_out << F( 12, 6, v.y() ) << " " ;
382  torsions_out << F( 12, 6, v.z() ) << " " ;
383  }
384 
385  }
386 
387  // "Secondary structure" ==>
388  // H = forming canonical Watson/Crick base pair
389  // P = forming some kind of base pair
390  // N = no base pairs.
391  FArray1D < bool > edge_is_base_pairing( 3, false );
392  char secstruct( 'X' );
393  get_base_pairing_info( pose, i, secstruct, edge_is_base_pairing );
394  torsions_out << secstruct << " " <<
395  edge_is_base_pairing( 1 ) << " " <<
396  edge_is_base_pairing( 2 ) << " " <<
397  edge_is_base_pairing( 3 ) << " ";
398 
399  bool is_cutpoint = false;
400  if ( pose.fold_tree().is_cutpoint( i ) ||
401  is_num_in_list(i + 1, exclude_res_list) ) {
402  is_cutpoint = true;
403  }
404 
405  torsions_out << is_cutpoint << I(6, i) << std::endl;
406  }
407 
408 
409 }
410 
411 ///////////////////////////////////////////////////////////////////////////////
412 void
414  std::string const outfile,
415  utility::vector1 <Size> const & exclude_res_list )
416 {
417  utility::io::ozstream torsions_out ( outfile );
418  create_rna_vall_torsions( pose, torsions_out, exclude_res_list );
419 
420 }
421 
422 
423 
424 //////////////////////////////////////////////////////////////////////////////////////
425 Real
426 get_o1p_o2p_sign( pose::Pose const & pose ) {
427 
428  Real sign= 0;
429  bool found_valid_sign=false;
430 
431  for (Size i = 2; i <= pose.total_residue(); i++ ) {
432 
433  conformation::Residue const & rsd( pose.residue(i) );
434  if (!rsd.is_RNA() ) continue;
435 
436  sign = dot( rsd.xyz( " O5*" ) - rsd.xyz( " P " ), cross( rsd.xyz( " O2P" ) - rsd.xyz( " P " ), rsd.xyz( " O1P" ) - rsd.xyz( " P " ) ) );
437 
438  found_valid_sign=true;
439 
440  break;
441  }
442 
443  if(found_valid_sign==false) utility_exit_with_message("found_valid_sign==false");
444 
445  return sign;
446 }
447 
448 //////////////////////////////////////////////////////////////////////////////////////
449 //This version used to be called get_o1p_o2p_sign_parin()
450 Real
451 get_o1p_o2p_sign( pose::Pose const & pose , Size res_num) {
452 
453  if(res_num > pose.total_residue()) utility_exit_with_message("res_num > pose.total_residue()");
454 
455  conformation::Residue const & rsd( pose.residue(res_num) );
456 
457  if(rsd.is_RNA()==false) utility_exit_with_message("rsd.is_RNA()==false!");
458 
459  Real const sign = dot( rsd.xyz( " O5*" ) - rsd.xyz( " P " ), cross( rsd.xyz( " O2P" ) - rsd.xyz( " P " ), rsd.xyz( " O1P" ) - rsd.xyz( " P " ) ) );
460 
461  return sign;
462 }
463 
464 
465 /////////////////////////////////////////////////////////////////////////////////////////////////////
466 void
468 
469  runtime_assert( pose.total_residue() > 1 );
470 
471  for(Size res_num=1; res_num<=pose.total_residue(); res_num++){
472 
473  Real sign1 = get_o1p_o2p_sign( pose, res_num);
474 
475  pose::Pose mini_pose; //Could move this part outside the for loop
476  make_pose_from_sequence( mini_pose, "aa", pose.residue(res_num).residue_type_set() );
477  Real const sign2 = get_o1p_o2p_sign( mini_pose);
478 
479  if ( sign1 * sign2 < 0 ) {
480 
481  std::cout << "In the assert_phosphate_nomenclature_matches_mini function: phosphate_nomenclature_matches does not match mini! " << std::endl;
482  utility_exit_with_message("In the assert_phosphate_nomenclature_matches_mini function: phosphate_nomenclature_matches does not match mini!");
483 
484  conformation::Residue const & rsd( pose.residue(res_num) );
485 
486  if(rsd.is_RNA()==false){ //Consistency check!
487  std::cout << "residue # " << res_num << " should be a RNA nucleotide" << std::endl;
488  utility_exit_with_message("residue # " + string_of(res_num)+ " should be a RNA nucleotide!");
489  };
490 
491 
492  }
493  }
494 }
495 
496 
497 ////////////////////////////////////////////////////////////////
498 //Jan 08, 2012 Parin S:
499 //To Rhiju, I think this version is buggy and should be deprecated (use make_phosphate_nomenclature_matches_mini instead!)
500 void
502 {
503  runtime_assert( pose.total_residue() > 1 );
504  Real sign1 = get_o1p_o2p_sign( pose );
505 
506  pose::Pose mini_pose;
507  make_pose_from_sequence( mini_pose, "aa", pose.residue(1).residue_type_set() );
508  Real sign2 = get_o1p_o2p_sign( mini_pose );
509 
510  if ( sign1 * sign2 > 0 ) return;
511 
512  std::cout << "*************************************************************" << std::endl;
513  std::cout << " Warning ... flipping O1P <--> O2P to match mini convention " << std::endl;
514  std::cout << "*************************************************************" << std::endl;
515 
516  for (Size i = 1; i <= pose.total_residue(); i++ ) {
517 
518  conformation::Residue const & rsd( pose.residue(i) );
519  if (!rsd.is_RNA() ) continue;
520 
521  if (!rsd.type().has( " O1P")) continue;
522  if (!rsd.type().has( " O2P")) continue;
523 
524  Vector const temp1 = rsd.xyz( " O1P" );
525  Vector const temp2 = rsd.xyz( " O2P" );
526  pose.set_xyz( id::AtomID( rsd.atom_index( " O1P" ), i ), temp2 );
527  pose.set_xyz( id::AtomID( rsd.atom_index( " O2P" ), i ), temp1 );
528  }
529 
530 }
531 
532 ////////////////////////////////////////////////////////////////
533 void
535 {
536 
537 
538  for(Size res_num=1; res_num<=pose.total_residue(); res_num++){
539 
540  if ( !pose.residue( res_num ).is_RNA() ) continue;
541 
542  pose::Pose mini_pose; //Could move this part outside of the for loop
543  make_pose_from_sequence( mini_pose, "aa", pose.residue( res_num ).residue_type_set());
544  Real const sign2 = get_o1p_o2p_sign( mini_pose);
545 
546  Real sign1 = get_o1p_o2p_sign( pose, res_num);
547 
548  if ( sign1 * sign2 < 0 ) {
549 
550  //std::cout << " Flipping O1P <--> O2P " << "res_num " << res_num << " | sign1: " << sign1 << " | sign2: " << sign2 << std::endl;
551 
552  conformation::Residue const & rsd( pose.residue(res_num) );
553 
554  if(rsd.is_RNA()==false){ //Consistency check!
555  std::cout << "residue # " << res_num << " should be a RNA nucleotide!" << std::endl;
556  utility_exit_with_message("residue # " + string_of(res_num)+ " should be a RNA nucleotide!");
557  };
558 
559  Vector const temp1 = rsd.xyz( " O1P" );
560  Vector const temp2 = rsd.xyz( " O2P" );
561  pose.set_xyz( id::AtomID( rsd.atom_index( " O1P" ), res_num ), temp2 );
562  pose.set_xyz( id::AtomID( rsd.atom_index( " O2P" ), res_num ), temp1 );
563  }
564  }
565 }
566 
567 
568 ///////////////////////////////////////////////////////////////////////////////
569 void
570 export_packer_results( utility::vector1< std::pair< Real, std::string > > & results,
572  scoring::ScoreFunctionOP & scorefxn,
573  std::string const & outfile,
574  bool const dump )
575 {
576 
577  utility::io::ozstream out( outfile );
578  for (Size n = 1; n <= results.size() ; n++ ){
579  out << F(8,3,results[n].first) << " " << results[n].second << std::endl;
580  }
581  out.close();
582 
583  using namespace core::io::silent;
584  core::io::silent::SilentFileData silent_file_data;
585 
586  std::string silent_file( outfile );
587  Size pos( silent_file.find( ".txt" ) );
588  silent_file.replace( pos, 4, ".out" );
589 
590  for (Size n = 1; n <= results.size() ; n++ ){
591  pose::Pose & pose( *pose_list[n] );
592  (*scorefxn)( pose );
593  std::string const tag( "S_"+lead_zero_string_of( n, 4 ) );
594  RNA_SilentStruct s( pose, tag );
595  if ( dump ) pose.dump_pdb( tag+".pdb");
596  silent_file_data.write_silent_struct( s, silent_file, true /*write score only*/ );
597  }
598 
599 }
600 
601 
602 ///////////////////////////////////////////////////////////////////////////////
603 void
604 check_base_pair( pose::Pose & pose, FArray1D_int & struct_type )
605 {
606 
607  using namespace core::scoring::rna;
608  using namespace core::scoring;
609  using namespace core::chemical;
610  using namespace core::conformation;
611 
613  (*scorefxn)( pose );
614 
615  RNA_ScoringInfo const & rna_scoring_info( rna_scoring_info_from_pose( pose ) );
616  RNA_FilteredBaseBaseInfo const & rna_filtered_base_base_info( rna_scoring_info.rna_filtered_base_base_info() );
617  Energy_base_pair_list const & scored_base_pair_list( rna_filtered_base_base_info.scored_base_pair_list() );
618 
619  Size const nres( pose.total_residue() );
620  FArray1D_bool forms_noncanonical_base_pair( nres, false );
621  FArray1D_bool forms_canonical_base_pair( nres, false );
622  FArray1D_int WC_base_pair_partner( nres, 0 );
623 
624  for ( Energy_base_pair_list::const_iterator it = scored_base_pair_list.begin();
625  it != scored_base_pair_list.end(); ++it ){
626 
627  Base_pair const base_pair = it->second;
628 
629  Size const i = base_pair.res1;
630  Size const j = base_pair.res2;
631 
632  Residue const & rsd_i( pose.residue( i ) );
633  Residue const & rsd_j( pose.residue( j ) );
634 
635  bool WC_base_pair( false );
636  if ( ( base_pair.edge1 == WATSON_CRICK && base_pair.edge2 == WATSON_CRICK
637  && base_pair.orientation == 1 ) &&
638  possibly_canonical( rsd_i.aa(), rsd_j.aa() ) ) {
639  std::string atom1, atom2;
640  // get_watson_crick_base_pair_atoms( rsd_i.aa(), rsd_j.aa(), atom1, atom2 );
641  // if ( ( rsd_i.xyz( atom1 ) - rsd_j.xyz( atom2 ) ).length() < 3.5 ) {
642  WC_base_pair = true;
643  // }
644  }
645 
646  std::cout << rsd_i.name1() << I(3,i) << "--" << rsd_j.name1() << I(3,j) << " WC:" << WC_base_pair << " score: " << F(10,6,it->first) << std::endl;
647 
648  if ( WC_base_pair ) {
649  forms_canonical_base_pair( i ) = true;
650  forms_canonical_base_pair( j ) = true;
651  WC_base_pair_partner( i ) = j;
652  WC_base_pair_partner( j ) = i;
653  } else {
654  forms_noncanonical_base_pair( i ) = true;
655  forms_noncanonical_base_pair( j ) = true;
656  }
657 
658  }
659 
660 
661  struct_type.dimension( nres );
662  for (Size i = 1; i <= nres; i++ ) {
663  if ( !forms_noncanonical_base_pair(i) && !forms_canonical_base_pair(i) ) {
664  struct_type( i ) = 0;
665  } else if (forms_canonical_base_pair(i) && !forms_noncanonical_base_pair( WC_base_pair_partner(i) ) ) {
666  struct_type( i ) = 1;
667  } else {
668  struct_type( i ) = 2;
669  }
670  }
671 
672 }
673 
674 
675 /////////////////////////////////////////////////////////
676 void
678  pose::Pose & pose,
679  utility::vector1< std::pair< Size, Size > > const & pairings,
680  Real const suppress_factor )
681 {
682 
683  using namespace core::scoring::constraints;
684  using namespace core::scoring::rna;
685 
686  Real const WC_distance( 1.9 );
687  Real const distance_stddev( 0.25 / suppress_factor ); //Hmm. Maybe try linear instead?
688  FuncOP const distance_func( new HarmonicFunc( WC_distance, distance_stddev ) );
689 
690  // Need to force base pairing -- not base stacking!
691  Real const C1star_distance( 10.5 );
692  Real const C1star_distance_stddev( 1.0 / suppress_factor ); //Hmm. Maybe try linear instead?
693  FuncOP const C1star_distance_func( new HarmonicFunc( C1star_distance, C1star_distance_stddev ) );
694 
695  for ( Size n = 1; n <= pairings.size(); n++ ) {
696 
697  Size const & i = pairings[n].first;
698  Size const & j = pairings[n].second;
699 
700  if ( !pose.residue(i).is_RNA() ) continue;
701  if ( !pose.residue(j).is_RNA() ) continue;
702 
703 
704  if ( !pose.residue(i).is_coarse() ) { //fullatom
705  Size const atom1 = pose.residue(i).type().atom_index( " C1*" ) ;
706  Size const atom2 = pose.residue(j).type().atom_index( " C1*" ) ;
708  id::AtomID(atom1,i),
709  id::AtomID(atom2,j),
710  C1star_distance_func ) );
711 
712  utility::vector1< std::string > atom_ids1, atom_ids2;
713  get_watson_crick_base_pair_atoms( pose.residue(i).aa(), pose.residue(j).aa(), atom_ids1, atom_ids2 );
714 
715  for (Size p = 1; p <= atom_ids1.size(); p++ ){
716 
717  Size const atom1 = pose.residue(i).type().atom_index( atom_ids1[p] ) ;
718  Size const atom2 = pose.residue(j).type().atom_index( atom_ids2[p] ) ;
719 
720  TR << "BASEPAIR: Adding rna_force_atom_pair constraint: " << pose.residue(i).name1() << I(3,i) << " <--> " <<
721  pose.residue(j).name1() << I(3,j) << " " <<
722  atom_ids1[p] << " <--> " <<
723  atom_ids2[p] << ". [ " << atom1 << "-" << atom2 << "]" << std::endl;
724 
726  id::AtomID(atom1,i),
727  id::AtomID(atom2,j),
728  distance_func ) );
729  }
730 
731  } else { //coarse-grained RNA
732 
733  static Real const coarse_WC_SUG_distance_min( 12.3 );
734  static Real const coarse_WC_SUG_distance_max( 14.3 );
735  static Real const coarse_WC_SUG_distance_stddev( 2.0 );
736  static Real const coarse_WC_SUG_bonus( -2.5 );
737  static FuncOP const coarse_SUG_distance_func( new FadeFunc( coarse_WC_SUG_distance_min - coarse_WC_SUG_distance_stddev,
738  coarse_WC_SUG_distance_max + coarse_WC_SUG_distance_stddev,
739  coarse_WC_SUG_distance_stddev,
740  coarse_WC_SUG_bonus ) );
741 
742  if ( true ){
743  Size const & atom1 = pose.residue(i).atom_index( " S " );
744  Size const & atom2 = pose.residue(j).atom_index( " S " );
745  TR << "BASEPAIR: Adding rna_force_atom_pair constraint: " << pose.residue(i).name1() << I(3,i) << " <--> " <<
746  pose.residue(j).name1() << I(3,j) << " " <<
747  " S " << " <--> " <<
748  " S " << ". [ " << atom1 << "-" << atom2 << "]" << std::endl;
750  id::AtomID(atom1,i),
751  id::AtomID(atom2,j),
752  coarse_SUG_distance_func ) );
753  }
754 
755  static Real const coarse_WC_CEN_distance( 5.5 );
756  static Real const coarse_WC_CEN_distance_stddev( 3.0 );
757  static Real const coarse_WC_CEN_bonus( -5.0 );
758  static FuncOP const coarse_CEN_distance_func( new FadeFunc( coarse_WC_CEN_distance - coarse_WC_CEN_distance_stddev,
759  coarse_WC_CEN_distance + coarse_WC_CEN_distance_stddev,
760  coarse_WC_CEN_distance_stddev,
761  coarse_WC_CEN_bonus ) );
762 
763  if ( true ){
764  Size const & atom1 = pose.residue(i).atom_index( " CEN" );
765  Size const & atom2 = pose.residue(j).atom_index( " CEN" );
766  TR << "BASEPAIR: Adding rna_force_atom_pair constraint: " << pose.residue(i).name1() << I(3,i) << " <--> " <<
767  pose.residue(j).name1() << I(3,j) << " " <<
768  " CEN" << " <--> " <<
769  " CEN" << ". [ " << atom1 << "-" << atom2 << "]" << std::endl;
771  id::AtomID(atom1,i),
772  id::AtomID(atom2,j),
773  coarse_CEN_distance_func ) );
774  }
775 
776  static Real const coarse_WC_X_distance( 3.5 );
777  static Real const coarse_WC_X_distance_stddev( 2.0 );
778  static Real const coarse_WC_X_bonus( -5.0 );
779  static FuncOP const coarse_X_distance_func( new FadeFunc( coarse_WC_X_distance - coarse_WC_X_distance_stddev,
780  coarse_WC_X_distance + coarse_WC_X_distance_stddev,
781  coarse_WC_X_distance_stddev, coarse_WC_X_bonus ) );
782 
783  {
784  Size const & atom1 = pose.residue(i).atom_index( " X " );
785  Size const & atom2 = pose.residue(j).atom_index( " X " );
786  TR << "BASEPAIR: Adding rna_force_atom_pair constraint: " << pose.residue(i).name1() << I(3,i) << " <--> " <<
787  pose.residue(j).name1() << I(3,j) << " " <<
788  " X " << " <--> " <<
789  " X " << ". [ " << atom1 << "-" << atom2 << "]" << std::endl;
791  id::AtomID(atom1,i),
792  id::AtomID(atom2,j),
793  coarse_X_distance_func ) );
794  }
795  }
796  }
797 }
798 
799 
800 /////////////////////////////////////////////////////////
801 // Following only works for coarse-grained RNA poses --
802 // perhaps should set up something similar for regular RNA
803 // as an alternative to linear_chainbreak.
804 void
806 {
807 
808  using namespace core::scoring::constraints;
809  using namespace core::scoring::rna;
810 
811  if ( !pose.residue_type( n ).has( " S " ) ) return;
812  if ( !pose.residue_type( n ).is_RNA() ) return;
813 
814  std::cout << "Adding CHAINBREAK constraints to " << n << " " << n+1 << std::endl;
815 
816  static Real const S_P_distance_min( 3 );
817  static Real const S_P_distance_max( 4 );
818  static Real const S_P_distance_fade( 1.0 );
819  static Real const S_P_distance_bonus( -10.0 );
820  static FuncOP const S_P_distance_func( new FadeFunc( S_P_distance_min - S_P_distance_fade,
821  S_P_distance_max + S_P_distance_fade,
822  S_P_distance_fade,
823  S_P_distance_bonus ) );
824 
825  // loose long-range constraint too
826  static Real const S_P_distance( 4.0 );
827  static Real const S_P_distance_stdev( 10.0 );
828  static FuncOP const S_P_harmonic_func( new HarmonicFunc( S_P_distance,
829  S_P_distance_stdev ) );
830 
831 
832  static Real const S_S_distance_min( 4.5 );
833  static Real const S_S_distance_max( 7.5 );
834  static Real const S_S_distance_fade( 2.0 );
835  static Real const S_S_distance_bonus( -5.0 );
836  static FuncOP const S_S_distance_func( new FadeFunc( S_S_distance_min - S_S_distance_fade,
837  S_S_distance_max + S_S_distance_fade,
838  S_S_distance_fade,
839  S_S_distance_bonus ) );
840 
841  static Real const P_P_distance_min( 4.5 );
842  static Real const P_P_distance_max( 7.5 );
843  static Real const P_P_distance_fade( 2.0 );
844  static Real const P_P_distance_bonus( -5.0 );
845  static FuncOP const P_P_distance_func( new FadeFunc( P_P_distance_min - P_P_distance_fade,
846  P_P_distance_max + P_P_distance_fade,
847  P_P_distance_fade,
848  P_P_distance_bonus ) );
849 
850  Size const & atom_S1 = pose.residue( n ).atom_index( " S " );
851  Size const & atom_P1 = pose.residue( n ).atom_index( " P " );
852  Size const & atom_S2 = pose.residue( n+1 ).atom_index( " S " );
853  Size const & atom_P2 = pose.residue( n+1 ).atom_index( " P " );
854 
856  id::AtomID(atom_S1, n),
857  id::AtomID(atom_P2, n+1),
858  S_P_distance_func ) );
859 
861  id::AtomID(atom_S1, n),
862  id::AtomID(atom_P2, n+1),
863  S_P_harmonic_func ) );
864 
866  id::AtomID(atom_P1, n),
867  id::AtomID(atom_P2, n+1),
868  P_P_distance_func ) );
869 
871  id::AtomID(atom_S1, n),
872  id::AtomID(atom_S2, n+1),
873  S_S_distance_func ) );
874 
875 }
876 
877 /////////////////////////////////////////////////////////////////////////////////////////////////
878 std::string const
879 convert_based_on_match_type( std::string const RNA_string, Size const type ){
880 
881  std::string RNA_string_local = RNA_string;
882 
883  Size const size = RNA_string.length();
884 
885  //Obey orders to match exactly, match pyrimidine/purine, or match all.
886  if (type == MATCH_ALL){
887 
888  for (Size i = 0; i < size; i++) RNA_string_local[ i ] = 'n';
889 
890  } else if ( type == MATCH_YR ) {
891 
892  for (Size i = 0; i < size; i++) {
893  if (RNA_string[ i ] == 'g' || RNA_string[ i ] == 'a' ){
894  RNA_string_local[ i ] = 'r';
895  } else {
896  runtime_assert( RNA_string[ i ] == 'u' || RNA_string[ i ] == 'c' );
897  RNA_string_local[ i ] = 'y';
898  }
899  }
900 
901  }
902 
903  return RNA_string_local;
904  }
905 
906  /////////////////////////////////////////////////////////////////////////////////////////////////
907  bool
908  compare_RNA_char( char const char1, char const char2 ) {
909  //Man this is silly, there must be a more elegant way to do this.
910  if (char1 == char2) return true;
911  if (char1 == 'n' || char2 == 'n') return true;
912  if (char1 == 'r' && (char2 == 'a' || char2 == 'g')) return true;
913  if (char1 == 'y' && (char2 == 'c' || char2 == 'u')) return true;
914  if (char2 == 'r' && (char1 == 'a' || char1 == 'g')) return true;
915  if (char2 == 'y' && (char1 == 'c' || char1 == 'u')) return true;
916  return false;
917  }
918 
919  /////////////////////////////////////////////////////////////////////////////////////////////////
920  bool
921  compare_RNA_secstruct( char const char1, char const char2 ) {
922  if (char1 == char2) return true;
923  if (char1 == 'X' || char2 == 'X' ) return true;
924  if (char1 == 'L' && ( char2 == 'N' || char2 == 'P') ) return true;
925  if (char2 == 'L' && ( char1 == 'N' || char1 == 'P') ) return true;
926  return false;
927  }
928 
929 ///////////////////////////////////////////////////////////////////////////
930 Vector
932  Vector cen( 0.0 );
933  cen += rsd.xyz( rsd.atom_index( " C1*" ) );
934  cen += rsd.xyz( rsd.atom_index( " C2*" ) );
935  cen += rsd.xyz( rsd.atom_index( " C3*" ) );
936  cen += rsd.xyz( rsd.atom_index( " C4*" ) );
937  cen += rsd.xyz( rsd.atom_index( " O4*" ) );
938  cen /= 5.0;
939  return cen;
940 }
941 
942 /////////////////////////////////////////////////
943 void
944 make_extended_coarse_pose( pose::Pose & coarse_pose, std::string const & full_sequence ){
945 
946  using namespace core::chemical;
947  using namespace core::id;
948 
950 
951  make_pose_from_sequence( coarse_pose, full_sequence, *rsd_set_coarse );
952 
953  for ( Size n = 1; n <= coarse_pose.total_residue(); n++ ) {
954  coarse_pose.set_torsion( TorsionID( n, BB, 1 ), -150.0 );
955  coarse_pose.set_torsion( TorsionID( n, BB, 2 ), 180.0 );
956  }
957 
958 }
959 
960 
961 ///////////////////////////////////////////////////////////////////////////
962 void
963 make_coarse_pose( pose::Pose const & pose, pose::Pose & coarse_pose ){
964 
965  using namespace core::chemical;
966  using namespace core::id;
967  using namespace core::scoring::rna;
968 
969  ResidueTypeSetCAP rsd_set, rsd_set_coarse;
970  RNA_CentroidInfo rna_centroid_info;
971 
973  make_extended_coarse_pose( coarse_pose, pose.sequence() );
974 
975  for ( Size n = 1; n <= pose.total_residue(); n++ ) {
976  coarse_pose.set_xyz( NamedAtomID( " P ", n ), pose.xyz( NamedAtomID( " P ", n )) );
977 
978  //coarse_pose.set_xyz( NamedAtomID( " S ", n ), pose.xyz( NamedAtomID( " C4*", n )) );
979  Vector sugar_centroid = get_sugar_centroid( pose.residue( n ) );
980  coarse_pose.set_xyz( NamedAtomID( " S ", n ), sugar_centroid );
981 
982  Vector base_centroid = rna_centroid_info.get_base_centroid( pose.residue( n ) );
983  kinematics::Stub stub = rna_centroid_info.get_base_coordinate_system( pose.residue( n ), base_centroid );
984 
985  coarse_pose.set_xyz( NamedAtomID( " CEN", n ), base_centroid );
986  coarse_pose.set_xyz( NamedAtomID( " X ", n ), base_centroid + stub.M.col_x() );
987  coarse_pose.set_xyz( NamedAtomID( " Y ", n ), base_centroid + stub.M.col_y() );
988 
989  }
990 
992  for ( Size n = 1; n <= pose.num_jump(); n++ ) {
993  f.set_jump_atoms( n, " Y ", " Y " );
994  }
995  coarse_pose.fold_tree( f );
996 
997 }
998 
999 ////////////////////////////////////////////////////////
1000 void
1002 
1003  using namespace core::chemical;
1004  using namespace core::kinematics;
1005 
1008 
1009  // using namespace protocols::forge::methods;
1010  // FoldTree f( pose.fold_tree() );
1011  // remove_cutpoint( i, f );
1012  // pose.fold_tree( f );
1013 
1014  utility::vector1< int > const & cutpoints = pose.fold_tree().cutpoints();
1015 
1016  Size const num_jump = pose.fold_tree().num_jump();
1017  utility::vector1< Size > upstream_pos, downstream_pos;
1018  for ( Size n = 1; n <= num_jump; n++ ) {
1019  upstream_pos.push_back( pose.fold_tree().upstream_jump_residue( n ) );
1020  downstream_pos.push_back( pose.fold_tree().downstream_jump_residue( n ) );
1021  }
1022 
1023  ObjexxFCL::FArray1D<int> cuts( num_jump-1 );
1024  Size count( 0 );
1025  for ( Size n = 1; n <= num_jump; n++ ) {
1026  if ( cutpoints[n] == static_cast<int>( i ) ) continue;
1027  count++;
1028  cuts( count ) = cutpoints[ n ];
1029  }
1030 
1031  Size const nres( pose.total_residue() );
1032 
1033  // Just brute-force iterate through to find a jump we can remove.
1034  Size jump_to_remove( 0 );
1035  for ( Size k = 1; k <= num_jump; k++ ) {
1036  FArray1D< bool > partition_definition( nres, false );
1037  pose.fold_tree().partition_by_jump( k, partition_definition );
1038  if ( partition_definition( i ) != partition_definition( i+1 ) ){
1039  jump_to_remove = k; break;
1040  }
1041  }
1042 
1043  bool success( false );
1044 
1045  ObjexxFCL::FArray2D<int> jump_point( 2, num_jump-1 );
1046 
1047  count = 0;
1048  for ( Size n = 1; n <= num_jump; n++ ) {
1049  if ( n == jump_to_remove ) continue;
1050  count++;
1051  if ( upstream_pos[ n ] < downstream_pos[ n ] ){
1052  jump_point( 1, count ) = upstream_pos[ n ];
1053  jump_point( 2, count ) = downstream_pos[ n ];
1054  } else {
1055  jump_point( 1, count ) = downstream_pos[ n ];
1056  jump_point( 2, count ) = upstream_pos[ n ];
1057  }
1058  }
1059 
1060  FoldTree f( nres );
1061 
1062  success = f.tree_from_jumps_and_cuts( nres, num_jump-1, jump_point, cuts, 1, false /*verbose*/ );
1063 
1064 
1065 
1066  if ( !success ) utility_exit_with_message( "FAIL to remove cutpoint "+string_of( i ) );
1067 
1068  pose.fold_tree( f );
1069 
1070 }
1071 
1072 ////////////////////////////////////////////////////////
1073 void
1075 
1076  // Make a list of each cutpoint_closed.
1077  for ( Size i = 1; i < pose.total_residue(); i++ ) {
1078 
1079  if ( pose.fold_tree().is_cutpoint( i ) &&
1082  remove_cutpoint_closed( pose, i ); // this will cycle through to find a jump that is removable.
1083  }
1084  }
1085 
1086 }
1087 
1088 ////////////////////////////////////////////////////////
1089 void
1091 
1092  for ( Size i = 1; i < pose.total_residue(); i++ ) {
1093 
1094  if ( i==1 || (( pose.fold_tree().is_cutpoint( i-1 ) &&
1097  pose.residue(i).is_RNA()) ){
1098  pose::add_variant_type_to_pose_residue( pose, "VIRTUAL_PHOSPHATE", i );
1099  }
1100 
1101  }
1102 
1103 }
1104 
1105 ///////////////////////////////////////////////////////////////////////
1106 // One of these days I'll put in residue 1 as well.
1107 void
1109 
1110  using namespace core::id;
1111  using numeric::conversions::degrees;
1112 
1113  for (Size i = 2; i <= pose.total_residue(); i++ ){
1114 
1115  conformation::Residue const & rsd( pose.residue( i ) ) ;
1116 
1117  std::cout << "----------------------------------------------------------------------" << std::endl;
1118  std::cout << "RESIDUE: " << rsd.name3() << " " << rsd.seqpos() << std::endl;
1119 
1120  for (Size j = 1; j <= rsd.natoms(); j++ ){
1121  core::kinematics::tree::AtomCOP current_atom ( & pose.atom_tree().atom( AtomID(j,i) ) );
1122  core::kinematics::tree::AtomCOP input_stub_atom1( current_atom->input_stub_atom1() );
1123  core::kinematics::tree::AtomCOP input_stub_atom2( current_atom->input_stub_atom2() );
1124  core::kinematics::tree::AtomCOP input_stub_atom3( current_atom->input_stub_atom3() );
1125 
1126  if ( !(current_atom && input_stub_atom1 && input_stub_atom2 && input_stub_atom3) ) continue;
1127 
1128  if ( current_atom->is_jump() ) {
1129 
1130  core::kinematics::tree::AtomCOP jump_stub_atom1( current_atom->stub_atom1() );
1131  core::kinematics::tree::AtomCOP jump_stub_atom2( current_atom->stub_atom2() );
1132  core::kinematics::tree::AtomCOP jump_stub_atom3( current_atom->stub_atom3() );
1133 
1134  // Now try to reproduce this jump based on coordinates of atoms.
1135  std::cout << "JUMP! " <<
1136  // A( 5, rsd.atom_name( j )) << " " <<
1137  "STUB ==> " <<
1138  "FROM " << input_stub_atom1->id().rsd() << " " <<
1139  pose.residue( (input_stub_atom1->id()).rsd() ).atom_name( (input_stub_atom1->id()).atomno() ) << " " <<
1140  pose.residue( (input_stub_atom2->id()).rsd() ).atom_name( (input_stub_atom2->id()).atomno() ) << " " <<
1141  pose.residue( (input_stub_atom3->id()).rsd() ).atom_name( (input_stub_atom3->id()).atomno() );
1142  std::cout << "TO " << current_atom->id().rsd() << " " <<
1143  pose.residue( (jump_stub_atom1->id()).rsd() ).atom_name( (jump_stub_atom1->id()).atomno() ) << " " <<
1144  pose.residue( (jump_stub_atom2->id()).rsd() ).atom_name( (jump_stub_atom2->id()).atomno() ) << " " <<
1145  pose.residue( (jump_stub_atom3->id()).rsd() ).atom_name( (jump_stub_atom3->id()).atomno() ) << std::endl;
1146  std::cout << " MY JUMP: " << current_atom->jump() << std::endl;
1147 
1148  kinematics::Stub const input_stub( input_stub_atom1->xyz(), input_stub_atom1->xyz(), input_stub_atom2->xyz(), input_stub_atom3->xyz());
1149  kinematics::Stub const jump_stub ( jump_stub_atom1->xyz(), jump_stub_atom1->xyz(), jump_stub_atom2->xyz(), jump_stub_atom3->xyz());
1150 
1151  std::cout << " MY JUMP: " << kinematics::Jump( input_stub, jump_stub ) << std::endl;
1152 
1153 
1154  } else {
1155  std::cout << "ICOOR_INTERNAL " <<
1156  A( 5, rsd.atom_name( j )) << " " <<
1157  F(11,6, degrees( pose.atom_tree().dof( DOF_ID( current_atom->id(), id::PHI ) ) ) ) << " " <<
1158  F(11,6, degrees( pose.atom_tree().dof( DOF_ID( current_atom->id(), id::THETA ) ) ) ) << " " <<
1159  F(11,6, pose.atom_tree().dof( DOF_ID( current_atom->id(), id::D ) ) ) << " " <<
1160  pose.residue( (input_stub_atom1->id()).rsd() ).atom_name( (input_stub_atom1->id()).atomno() ) << " " <<
1161  pose.residue( (input_stub_atom2->id()).rsd() ).atom_name( (input_stub_atom2->id()).atomno() ) << " " <<
1162  pose.residue( (input_stub_atom3->id()).rsd() ).atom_name( (input_stub_atom3->id()).atomno() ) << " " <<
1163  " [" <<
1164  " " << (input_stub_atom1->id()).rsd() <<
1165  " " << (input_stub_atom2->id()).rsd() <<
1166  " " << (input_stub_atom3->id()).rsd() <<
1167  "]" <<
1168  std::endl;
1169  }
1170 
1171  }
1172 
1173 // /////////////////////////////////
1174 // if ( option[ rsd_type_set]() == "rna" ){
1175 // std::cout << "Give me LOWER-P-O5* " << 180.0 - numeric::conversions::degrees( numeric::angle_radians( pose.residue(i-1).xyz( "O3*" ), rsd.xyz( "P" ), rsd.xyz( "O5*" ) ) ) << std::endl;
1176 // std::cout << "Give me O1P-P-O5* " << 180.0 - numeric::conversions::degrees( numeric::angle_radians( rsd.xyz( "O1P" ), rsd.xyz( "P" ), rsd.xyz( "O5*" ) ) ) << std::endl;
1177 // std::cout << "Give me O2P-P-O5* " << 180.0 - numeric::conversions::degrees( numeric::angle_radians( rsd.xyz( "O2P" ), rsd.xyz( "P" ), rsd.xyz( "O5*" ) ) ) << std::endl;
1178 
1179 // Real main_torsion = numeric::conversions::degrees( numeric::dihedral_radians( pose.residue(i-1).xyz( "O3*" ), rsd.xyz( "P" ), rsd.xyz( "O5*" ), rsd.xyz( "C5*" ) ) );
1180 // Real main_torsion1 = numeric::conversions::degrees( numeric::dihedral_radians( pose.residue(i).xyz( "O1P" ), rsd.xyz( "P" ), rsd.xyz( "O5*" ), rsd.xyz( "C5*" ) ) );
1181 // Real main_torsion2 = numeric::conversions::degrees( numeric::dihedral_radians( pose.residue(i).xyz( "O2P" ), rsd.xyz( "P" ), rsd.xyz( "O5*" ), rsd.xyz( "C5*" ) ) );
1182 
1183 // std::cout << "OFFSETS: " << main_torsion1 - main_torsion << " " << main_torsion2 - main_torsion1 << std::endl;
1184 // }
1185 
1186  }
1187 }
1188 
1189 
1190 ////////////////////////////////////////////////////////////////////////////////////
1191 // Apparently can only reroot the tree at a "vertex", i.e. beginning or end of an "edge".
1192 bool
1194  if ( n == 1 ) return true;
1195  if ( n == f.nres() ) return true;
1196  if ( f.is_cutpoint( n ) ) return true;
1197  if ( f.is_cutpoint( n-1 ) ) return true;
1198  return false;
1199 }
1200 
1201 
1202 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1205 
1206  utility::vector1< Size > rigid_body_jumps;
1207 
1208  TR.Debug << "Initialize RigidBodyMover: Is last residue virtual? " << pose.residue( pose.total_residue() ).name3() << std::endl;
1209 
1210  if ( pose.residue( pose.total_residue() ).name3() != "XXX" ) return rigid_body_jumps; // must have a virtual anchor residue.
1211 
1212  for ( Size n = 1; n <= pose.fold_tree().num_jump(); n++ ){
1213  TR.Debug << "checking jump: " << pose.fold_tree().upstream_jump_residue( n ) << " to " << pose.fold_tree().downstream_jump_residue( n ) << std::endl;
1214  if ( pose.fold_tree().upstream_jump_residue( n ) == (int)pose.total_residue() ||
1215  pose.fold_tree().downstream_jump_residue( n ) == (int)pose.total_residue() ){
1216  TR.Debug << "found jump to virtual anchor at: " << n << std::endl;
1217 
1218  rigid_body_jumps.push_back( n );
1219  if ( rigid_body_jumps.size() > 1 ) {
1220  TR.Debug << "found moveable jump!" << std::endl;
1221  }
1222  }
1223  }
1224 
1225  return rigid_body_jumps;
1226 }
1227 
1228 
1229 ////////////////////////////////////////////////////////////////////////////////////
1230 bool
1232  pose::Pose const & pose,
1233  bool const move_first_rigid_body /* = false */ ){
1234 
1235  utility::vector1< Size > const rigid_body_jumps = get_rigid_body_jumps( pose );
1236  Size const found_jumps = rigid_body_jumps.size();
1237  if ( found_jumps <= 1 ) return false; // nothing to rotate/translate relative to another object.
1238 
1239  Size start = ( move_first_rigid_body ) ? 1 : 2;
1240  for ( Size n = start; n <= rigid_body_jumps.size(); n++ ) movemap.set_jump( rigid_body_jumps[n], true );
1241 
1242  return true;
1243 }
1244 
1245 /////////////////////////////////////////////////////////////////////////////////////
1246 void
1248 
1249  utility::vector1< Size > const rigid_body_jumps = get_rigid_body_jumps( pose );
1250  if ( rigid_body_jumps.size() == 0 ) return;
1251 
1252  Size const nres = pose.total_residue(); // This better be a virtual residue -- checked in get_rigid_body_jumps() above.
1253 
1254  Size anchor_rsd = pose.fold_tree().downstream_jump_residue( rigid_body_jumps[1] );
1255  if ( anchor_rsd == nres ) anchor_rsd = pose.fold_tree().upstream_jump_residue( rigid_body_jumps[1] );
1256 
1257  Vector anchor1 = pose.xyz( id::AtomID( 1, anchor_rsd ) );
1258  Vector root1 = pose.xyz( id::AtomID( 1, nres ) );
1259  Vector const offset = anchor1 - root1;
1260 
1261  for ( Size j = 1; j <= pose.residue( nres ).natoms(); j++ ){
1262  id::AtomID atom_id( j, nres );
1263  pose.set_xyz( atom_id, pose.xyz( atom_id ) + offset );
1264  }
1265 
1266 }
1267 
1268 } // namespace rna
1269 } // namespace protocols