Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RNA_StructureParameters.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 RNA de novo fragment assembly Structure Parameters
11 /// @brief User input parameters for RNA structure inference
12 /// @detailed
13 /// @author Rhiju Das
14 
15 
16 // Unit Headers
22 #include <protocols/swa/rna/StepWiseRNA_Util.hh> // for Correctly_position_cutpoint_phosphate_torsions
25 
26 // Package Headers
27 #include <core/pose/Pose.hh>
28 #include <core/pose/util.hh>
29 // AUTO-REMOVED #include <core/chemical/util.hh>
33 #include <core/id/TorsionID.hh>
40 // AUTO-REMOVED #include <core/scoring/constraints/HarmonicFunc.hh>
41 #include <core/id/AtomID.hh>
42 #include <core/id/NamedAtomID.hh>
43 
44 // ObjexxFCL Headers
45 // AUTO-REMOVED #include <ObjexxFCL/ObjexxFCL.hh>
46 #include <ObjexxFCL/FArray1D.hh>
47 #include <ObjexxFCL/FArray2D.hh>
48 #include <ObjexxFCL/format.hh>
49 
50 #include <utility/io/izstream.hh>
51 #include <utility/exit.hh>
52 
53 #include <numeric/random/random.hh>
54 
55 #include <core/types.hh>
56 #include <basic/Tracer.hh>
57 
58 // C++ headers
59 #include <fstream>
60 #include <iostream>
61 #include <list>
62 
64 #include <utility/vector1.hh>
65 
66 //Auto Headers
68 //Auto using namespaces
69 namespace ObjexxFCL { } using namespace ObjexxFCL; // AUTO USING NS
70 namespace ObjexxFCL { namespace fmt { } } using namespace ObjexxFCL::fmt; // AUTO USING NS
71 //Auto using namespaces end
72 
73 
74 namespace protocols{
75 namespace rna{
76 
77 static numeric::random::RandomGenerator RG(144620); // <- Magic number, do not change it!
78 
79 static basic::Tracer tr( "protocols.rna.rna_structure_parameters" ) ;
80 
81 using namespace core;
82 
83 RNA_StructureParameters::RNA_StructureParameters():
84  secstruct_defined_( false ),
85  assume_non_stem_is_loop( false ),
86  root_at_first_rigid_body_( false )
87  {
88  }
89 
91 
92 //////////////////////////////////////////////////////////////////
93 void
95  core::pose::Pose & pose,
96  std::string const rna_params_file,
97  std::string const jump_library_file,
98  bool const ignore_secstruct )
99 {
100 
101 
102  if ( rna_params_file.length() > 0 ) read_parameters_from_file( rna_params_file );
103 
104  if ( rna_pairing_list_.size() > 0 || chain_connections_.size() > 0 ) {
105  rna_jump_library_ = RNA_JumpLibraryOP( new RNA_JumpLibrary( jump_library_file) );
106  }
107 
108  initialize_allow_insert( pose );
109 
110  initialize_secstruct( pose );
111 
112  if ( ignore_secstruct ) override_secstruct( pose );
113 
115 
117 
118 }
119 
120 /////////////////////////////////////////////////////////////////////////////////////
121 void
123  rna_secstruct_ = std::string( pose.total_residue(), 'X' );
124  std::cout << "OVER-RIDING SECONDARY STRUCTURE WITH: " << rna_secstruct_ << std::endl;
126 }
127 /////////////////////////////////////////////////////////////////////////////////////
128 void
130 {
131 
132  if ( virtual_anchor_attachment_points_.size() == 0 ) return;
133 
134  std::cout << "Current last residue is type: " << pose.residue( pose.total_residue() ).name3() << std::endl;
135  std::cout << pose.annotated_sequence() << std::endl;
136  if ( pose.residue( pose.total_residue() ).name3() == "XXX" ) return; //already did virtual residue attachment.
137 
138  // Fix up the pose.
139  core::chemical::ResidueTypeSet const & residue_set = pose.residue_type(1).residue_type_set();
140 
141  // std::cout << " CHECK XXX " << residue_set.name3_map("XXX").size() << std::endl;
142  // std::cout << " CHECK YYY " << residue_set.name3_map("YYY").size() << std::endl;
143  // std::cout << " CHECK VRT " << residue_set.name3_map("VRT").size() << std::endl;
144 
145  core::chemical::ResidueTypeCOPs const & rsd_type_list( residue_set.name3_map("XXX") );
148 
149  Size const virt_res = pose.total_residue();
150 
151  // allow insert.
152  allow_insert_->append_residue( pose, virt_res, false );
153 
154  // Info on pairings and cutpoints.
155  cutpoints_open_.push_back( (virt_res - 1) );
156 
157  for ( Size n = 1; n <= virtual_anchor_attachment_points_.size(); n++ ){
158 
159  RNA_Pairing p;
161  p.pos2 = virt_res;
162  p.edge1 = 'X';
163  p.edge2 = 'X';
164  p.orientation = 'X';
165  rna_pairing_list_.push_back( p );
166 
167  utility::vector1< Size > obligate_pair;
168  obligate_pair.push_back( rna_pairing_list_.size() );
169  obligate_pairing_sets_.push_back( obligate_pair );
170  }
171 
172 
173 }
174 
175 
176 /////////////////////////////////////////////////////////////////////////////////////
177 void
179 {
180 
181  if ( !secstruct_defined_ ) {
182 
183  rna_secstruct_ = std::string( pose.total_residue(), 'X' );
184 
185  if ( rna_pairing_list_.size() > 0 && assume_non_stem_is_loop ){
186  rna_secstruct_ = std::string( pose.total_residue(), 'L' );
187  }
188 
189  for ( Size n = 1; n <= rna_pairing_list_.size(); n++ ){
190  RNA_Pairing const & rna_pairing( rna_pairing_list_[ n ] );
191  if ( rna_pairing.edge1 == 'W' &&
192  rna_pairing.edge2 == 'W' &&
193  rna_pairing.orientation == 'A' &&
194  core::scoring::rna::possibly_canonical( pose.residue( rna_pairing.pos1 ).aa(),
195  pose.residue( rna_pairing.pos2 ).aa() ) ) {
196  rna_secstruct_[ rna_pairing.pos1 - 1 ] = 'H';
197  rna_secstruct_[ rna_pairing.pos2 - 1 ] = 'H';
198  }
199  }
200  }
201 
202  std::cout << "Setting desired secondary structure to: " << rna_secstruct_ << std::endl;
203 
205 }
206 
207 //////////////////////////////////////////////////////////////////////////////
208 std::list< Size >
210 {
211  std::list< Size > in_stem;
212 
213  for ( Size n = 1; n <= rna_pairing_list_.size(); n++ ){
214  RNA_Pairing const & rna_pairing( rna_pairing_list_[ n ] );
215  if ( rna_pairing.edge1 == 'W' &&
216  rna_pairing.edge2 == 'W' &&
217  rna_pairing.orientation == 'A' &&
218  core::scoring::rna::possibly_canonical( pose.residue( rna_pairing.pos1 ).aa(),
219  pose.residue( rna_pairing.pos2 ).aa() ) ) {
220  in_stem.push_back( rna_pairing.pos1 );
221  in_stem.push_back( rna_pairing.pos2 );
222  }
223  }
224 
225  in_stem.sort();
226  in_stem.unique();
227 
228  return in_stem;
229 }
230 
231  /////////////////////////////////////////////////////////////////////////////////////
232 void
234 {
235 
236  allow_insert_ = new toolbox::AllowInsert( pose );
237 
238  if (allow_insert_res_.size() > 0 ) {
239  allow_insert_->set( false );
240  for (Size n = 1; n <= allow_insert_res_.size(); n++ ) {
241  Size const i = allow_insert_res_[ n ];
242  allow_insert_->set( i, true );
243  // new -- make sure loops are moveable (& closeable!) at the 3'-endpoint
244  if ( i < pose.total_residue() ) allow_insert_->set_phosphate( i+1, pose, true );
245  }
246  } else {
247  allow_insert_->set( true );
248  }
249 
250  // std::cout << "ALLOW_INSERT after INITIALIZE " << std::endl;
251  // allow_insert_->show();
252 
253  // We don't trust phosphates at the beginning of chains!
254  // Wait, this it total nonsense... captured by virtual phosphate stuff later on!
255  // allow_insert_->set_phosphate( 1, pose, false );
256  // for ( Size i = 1; i <= cutpoints_open_.size(); i++ ) {
257  // allow_insert_->set_phosphate( cutpoints_open_[i]+1, pose, false );
258  // }
259 
260  // std::cout << "ALLOW_INSERT! ALLOW_INSERT! ALLOW_INSERT!" << std::endl;
261  // for (Size i = 1; i <= pose.total_residue(); i++ ){
262  // std::cout << allow_insert_->get( i );
263  // }
264  // std::cout << std::endl;
265  // std::cout << "ALLOW_INSERT! ALLOW_INSERT! ALLOW_INSERT!"<< std::endl;
266 
267 
268 }
269 
270 /////////////////////////////////////////////////////////////////////////////////////
271 void
273  std::istringstream & line_stream,
274  bool const obligate_pairing_set )
275 {
276 
277  Size a,b;
278  char e1,e2,o;
279  std::string tag;
280 
281  utility::vector1< Size > line_pairings;
282 
283  while ( !line_stream.fail() ) {
284 
285  line_stream >> a >> b ;
286 
287  if ( line_stream.fail() ) {
288  std::cout << "Parse error!!!" << a << ' ' << b << std::endl;
289  }
290 
291  line_stream >> tag;
292  if ( line_stream.fail() || tag == "PAIR" ) {
293  e1 = 'W';
294  e2 = 'W';
295  o = 'A';
296  } else {
297  e1 = tag[0];
298  line_stream >> e2 >> o;
299  if ( line_stream.fail() ) utility_exit_with_message( "Problem with PAIR readin: "+tag );
300  }
301 
302  RNA_Pairing p;
303 
304  if ( a < b ) {
305  p.pos1 = a;
306  p.pos2 = b;
307  } else {
308  p.pos1 = b;
309  p.pos2 = a;
310  }
311 
312  if (a == b) {
313  utility_exit_with_message( "Can't base pair a residue with itself: "+I(3,a)+" "+I(3,b) );
314  }
315 
316  p.edge1 = e1;
317  p.edge2 = e2;
318  p.orientation = o;
319 
320  rna_pairing_list_.push_back( p );
321 
322  line_pairings.push_back( rna_pairing_list_.size() );
323 
324  line_stream >> tag;
325  if ( !line_stream.fail() && tag != "PAIR" ) utility_exit_with_message( "Problem with PAIR readin: " + tag );
326  }
327 
328  if ( obligate_pairing_set ) {
329  obligate_pairing_sets_.push_back( line_pairings );
330  } else {
331  possible_pairing_sets_.push_back( line_pairings );
332  }
333 }
334 
335 ////////////////////////////////////////////////////////////////////////////////////////////////////////
336 void
337 RNA_StructureParameters::read_chain_connection( std::istringstream & line_stream ) {
338 
339  std::string tag;
340  Size pos1( 0 ), pos2( 0 ), which_segment( 1 );
341 
342  utility::vector1< Size > res_list1, res_list2;
343 
344  while ( !line_stream.fail() ) {
345 
346  //Find the next non-whitespace character
347  char checkchar( ' ' );
348  while ( checkchar == ' ' && !line_stream.fail()) checkchar = line_stream.get();
349 
350  if (line_stream.fail() ) break;
351  line_stream.putback( checkchar );
352 
353  if ( checkchar == 'S' ) {
354  line_stream >> tag;
355 
356  if ( tag == "SEGMENT1" ) {
357  which_segment = 1;
358  } else if ( tag == "SEGMENT2" ) {
359  which_segment = 2;
360  } else {
361  utility_exit_with_message( "Looking for SEGMENT1 or SEGMENT2 in CHAIN_CONNECTION line, but got " + tag );
362  }
363 
364  } else { //Better be two numbers.
365 
366  if (!line_stream.fail() ){
367  line_stream >> pos1 >> pos2;
368  runtime_assert( pos2 > pos1 );
369  for (Size i = pos1; i <= pos2; i++ ){
370  if (which_segment == 1 ) res_list1.push_back( i );
371  if (which_segment == 2 ) res_list2.push_back( i );
372  }
373  }
374  }
375  }
376 
377  if ( res_list1.size() == 0 || res_list2.size() == 0 ){
378  utility_exit_with_message( "Did not specify SEGMENT1 or SEGMENT2 in CHAIN_CONNECTION line?" );
379  }
380 
381  chain_connections_.push_back( std::make_pair(res_list1, res_list2) );
382 
383 }
384 
385 
386 /////////////////////////////////////////////////////////////////////////////////////
387 void
389 
390  tr << "Reading RNA parameters file: " << filename << std::endl;
391 
392  Size a;
393 
394  utility::io::izstream pairing_stream( filename );
395  if ( !pairing_stream ) {
396  pairing_stream.close();
397  utility_exit_with_message( "Pairing file? " + filename );
398  }
399 
400  std::string line, tag;
401  // Size num_stems( 0 );
402 
403  while ( getline( pairing_stream, line ) ) {
404 
405  std::istringstream line_stream( line );
406  line_stream >> tag;
407 
408  if (line_stream.fail() ) continue; //Probably a blank line.
409 
410  if (tag == "OBLIGATE" ) {
411 
412  line_stream >> tag;
413  if ( line_stream.fail() || tag != "PAIR" ) utility_exit_with_message( "Problem with STEM readin: " + tag );
414  get_pairings_from_line( line_stream, true /*obligate jump*/ );
415 
416  } else if (tag == "STEM" || tag == "POSSIBLE" ) {
417 
418  line_stream >> tag;
419  if ( line_stream.fail() || tag != "PAIR" ) utility_exit_with_message( "Problem with STEM readin: " + tag );
420  get_pairings_from_line( line_stream, false /*obligate jump*/ );
421 
422  } else if (tag == "ALLOW_INSERT" ) {
423  // deprecated!!! switch to ALLOW_INSERT_RES!!
424  Size pos1, pos2;
425  while ( !line_stream.fail() ) {
426  line_stream >> pos1 >> pos2;
427  runtime_assert( pos2 >= pos1 );
428  for (Size i = pos1; i <= pos2; i++ ) allow_insert_res_.push_back( i );
429  }
430  //utility_exit_with_message( "No longer reading in ALLOW_INSERT from command line. Try using -s <pdb> instead." );
431 
432  } else if (tag == "ALLOW_INSERT_RES" ) {
433 
434  Size pos;
435  while ( !line_stream.fail() ) {
436  line_stream >> pos;
437  allow_insert_res_.push_back( pos );
438  }
439  //utility_exit_with_message( "No longer reading in ALLOW_INSERT from command line. Try using -s <pdb> instead." );
440 
441  } else if (tag == "VIRTUAL_ANCHOR" ) {
442 
443  while ( !line_stream.fail() ) {
444  line_stream >> a;
445  if (!line_stream.fail() ){
446  virtual_anchor_attachment_points_.push_back( a );
447  }
448  }
449 
450 
451  } else if (tag == "CUTPOINT_CLOSED" ) {
452  while ( !line_stream.fail() ) {
453  line_stream >> a;
454  if (!line_stream.fail() ){
455  cutpoints_closed_.push_back( a );
456  }
457  }
458 
459  } else if (tag == "CUTPOINT_OPEN" ) {
460  while ( !line_stream.fail() ) {
461  line_stream >> a;
462  if (!line_stream.fail() ){
463  cutpoints_open_.push_back( a );
464  }
465  }
466 
467  } else if (tag == "CHAIN_CONNECTION" ) {
468 
469  read_chain_connection( line_stream );
470 
471  } else if (tag == "SECSTRUCT" ) {
472  line_stream >> rna_secstruct_;
473  secstruct_defined_ = true;
474 
475  } else if ( tag[0] == '#' ) {
476  continue;
477 
478  } else {
479  utility_exit_with_message( "Unrecognized tag in pairing file: " + tag );
480  }
481  }
482  pairing_stream.close();
483 
484 }
485 
486 
487 /////////////////////////////////////////////////////////////////////////////////////////////////
488 bool
489 in_list( Size const & pos, utility::vector1 < Size > const & res_list )
490 {
491  for (Size n = 1; n <= res_list.size(); n++ ) {
492  if ( res_list[n] == pos ) return true;
493  }
494  return false;
495 }
496 
497 /////////////////////////////////////////////////////////////////////////////////////////////////
498 Size
500 {
501  Size const num_chain_connections( chain_connections_.size() );
502 
503  for (Size n = 1; n <= num_chain_connections ; n++ ){
504  utility::vector1 < Size > const & res_list1( chain_connections_[n].first );
505  utility::vector1 < Size > const & res_list2( chain_connections_[n].second);
506 
507  if ( in_list( pos1, res_list1 ) && in_list( pos2, res_list2) ) return n;
508  if ( in_list( pos2, res_list1 ) && in_list( pos1, res_list2) ) return n;
509 
510  }
511 
512  return 0;
513 }
514 
515 /////////////////////////////////////////////////////////////////////////////////////////////////
516 bool
518  pose::Pose & pose,
519  Size const jump_pos ) const
520 {
521  using namespace core::kinematics::tree;
522 
523  if ( pose.residue( jump_pos ).is_coarse() || !pose.residue( jump_pos ).is_RNA() ) return true;
524 
525  Size atomno = pose.residue( jump_pos ).atom_index( " O5*" );
526  AtomCOP current_atom ( & pose.atom_tree().atom( id::AtomID( atomno,jump_pos) ) );
527  id::AtomID const parent_id( current_atom->parent()->id() );
528  std::string const & parent_name( pose.residue(parent_id.rsd()).atom_name(parent_id.atomno()) );
529  // std::cout << "HELLO ==> " << parent_name << std::endl;
530  if ( parent_name == " P " ) {
531  return true;
532  }
533  return false;
534 }
535 
536 /////////////////////////////////////////////////////////////////////////////////////////////////
537 void
539  pose::Pose & pose,
540  Size const & which_jump,
541  bool & success ) const
542 {
543  kinematics::FoldTree fold_tree( pose.fold_tree() ); //Make a copy.
544 
545  Size const jump_pos1( fold_tree.upstream_jump_residue( which_jump ) );
546  Size const jump_pos2( fold_tree.downstream_jump_residue( which_jump ) );
547 
548  // Later can be smart about virtual residue. (rigid body jumps)
549  if ( !pose.residue( jump_pos1 ).is_RNA() || !pose.residue( jump_pos2 ).is_RNA() ) return;
550 
551  char e1('W') ,e2('W'), o('A');
552  bool found_pairing( false );
553  //bool flip( false ); // wait, why do we need flip? // We don't. ~Labonte
554  for ( Size n = 1; n <= rna_pairing_list_.size(); n++ ){
555  RNA_Pairing pairing = rna_pairing_list_[n];
556  if (pairing.pos1 == jump_pos1 && pairing.pos2 == jump_pos2 ){
557  e1 = pairing.edge1;
558  e2 = pairing.edge2;
559  o = pairing.orientation;
560  found_pairing = true;
561  //flip = false; // set but never used ~Labonte
562  break;
563  }
564  if (pairing.pos1 == jump_pos2 && pairing.pos2 == jump_pos1 ){
565  e1 = pairing.edge2;
566  e2 = pairing.edge1;
567  o = pairing.orientation;
568  found_pairing = true;
569  //flip = true; // set but never used ~Labonte
570  break;
571  }
572  }
573 
574  //The jump may have come from a "chain_connection", which
575  // doesn't know parallel vs. antiparallel..
576  if (!found_pairing) {
577  e1 = 'X';
578  e2 = 'X';
579  o = 'X';
580 
581  // To save time following could be as runtime_assert statement, only
582  // active in debug builds.
583  if (check_in_chain_connections( jump_pos1, jump_pos2 ) > 0) found_pairing = true;
584 
585  }
586 
587  if (!found_pairing){
588  utility_exit_with_message( "Trouble finding foldtree pairing in input pairing list? " + I(3,jump_pos1)+' '+I(3,jump_pos2) );
589  }
590 
591  bool const forward1 = check_forward_backward( pose, jump_pos1 );
592  bool const forward2 = check_forward_backward( pose, jump_pos2 );
593  // std::cout << "FORWARD? " << forward1 << " " << forward2 << std::endl;
594 
595  std::string atom_name1, atom_name2;
596 
597  kinematics::Jump const new_jump = rna_jump_library_->get_random_base_pair_jump(
598  pose.residue(jump_pos1).name1(),
599  pose.residue(jump_pos2).name1(),
600  e1, e2, o,
601  atom_name1, atom_name2,
602  success,
603  forward1, forward2 );
604 
605  // std::cout << "ATOM NAME? " << atom_name1 << " " << atom_name2 << " / " << jump_pos1 << " " << jump_pos2 << " / " << flip << " . " << success << std::endl;
606 
607  if (!success) return; //shh don't do anything.
608 
609  fold_tree.set_jump_atoms( which_jump, atom_name1, atom_name2 );
610 
611  pose.fold_tree( fold_tree );
612 
613  // std::cout << " PUTTING IN NEW JUMP: " << which_jump << " " << atom_name1 << " " << atom_name2 << " " << e1 << " " << e2 << " " << o << "-->" << new_jump << std::endl;
614  pose.set_jump( which_jump, new_jump );
615 
616 
617 }
618 
619 /////////////////////////////////////////////////////////////////////////////////////////////////
620 void
622 {
623  kinematics::FoldTree fold_tree( pose.fold_tree() ); //Make a copy.
624 
625  Size const jump_pos1( fold_tree.upstream_jump_residue( which_jump ) );
626  Size const jump_pos2( fold_tree.downstream_jump_residue( which_jump ) );
627 
628  Size const chain_connection_number = check_in_chain_connections( jump_pos1, jump_pos2 );
629 
630  // Is this jump even part of a chain connection?
631  if ( chain_connection_number < 1 ) return;
632 
633  utility::vector1 < Size > const & res_list1( chain_connections_[chain_connection_number].first );
634  utility::vector1 < Size > const & res_list2( chain_connections_[chain_connection_number].second);
635 
636  //Now shift around the jump positions. Hmm, this is potentially dangerous.
637  Size ntries( 0 );
638  Size const MAX_TRIES( 1000 );
639  bool success( false );
640 
641  // Get ready for a new fold-tree
642  Size const num_jumps( fold_tree.num_jump() );
643  ObjexxFCL::FArray2D <int> jump_points( 2, num_jumps );
644  ObjexxFCL::FArray1D <int> cuts( num_jumps );
645  for (Size n = 1; n <= num_jumps; n++ ){
646  jump_points( 1, n ) = fold_tree.jump_point( 1, n );
647  jump_points( 2, n ) = fold_tree.jump_point( 2, n );
648  cuts( n ) = fold_tree.cutpoint( n );
649  }
650 
651  // IS this necessary? Or does which_jump == which_jump_in_list?
652  Size which_jump_in_list( 0 );
653  for ( which_jump_in_list = 1; which_jump_in_list <= num_jumps; which_jump_in_list++ ){
654  if ( Size( jump_points( 1, which_jump_in_list ) ) == jump_pos1 &&
655  Size( jump_points( 2, which_jump_in_list ) ) == jump_pos2 ) break;
656  if ( Size( jump_points( 1, which_jump_in_list ) ) == jump_pos2 &&
657  Size( jump_points( 2, which_jump_in_list ) ) == jump_pos1 ) break;
658  }
659  if (which_jump_in_list > num_jumps ) {
660  utility_exit_with_message( "Problem with fold tree change --> Jump " + I(3, jump_pos1) + " " + I(3, jump_pos2) );
661  }
662 
663  while( !success && ntries++ < MAX_TRIES ){
664  Size const new1( static_cast<Size>( RG.uniform() * res_list1.size() ) + 1 );
665  Size const new2( static_cast<Size>( RG.uniform() * res_list2.size() ) + 1 );
666  jump_points( 1, which_jump_in_list ) = res_list1[ new1 ];
667  jump_points( 2, which_jump_in_list ) = res_list2[ new2 ];
668  success = fold_tree.tree_from_jumps_and_cuts( pose.total_residue(), num_jumps,
669  jump_points, cuts, 1, false /*verbose*/ );
670  }
671 
672  fill_in_default_jump_atoms( fold_tree, pose );
673 
674  // tr << "Changing fold_tree ==> " << fold_tree << std::endl;
675 
676  if (success) pose.fold_tree( fold_tree );
677 
678 
679 }
680 
681 /////////////////////////////////////////////////////////////////////////////////////////////////
682 void
684 {
685 
686  Size const num_jump( pose.num_jump() );
687 
688  for (Size i = 1; i <= num_jump; i++ ){
689 
690  // Check that we can actually insert here. At least one of the jump partners
691  // should allow moves. (I guess the other one can stay fixed).
692  Size const jump_pos1( pose.fold_tree().upstream_jump_residue( i ) );
693  Size const jump_pos2( pose.fold_tree().downstream_jump_residue( i ) );
694 
695  if (allow_insert_->get( jump_pos1 ) || allow_insert_->get( jump_pos2 ) ) {
696  add_new_RNA_jump( pose, i, success );
697  }
698 
699  //std::cout << "INSERT RANDOM JUMP: " << i << " " << jump_pos1 << " " << jump_pos2 << std::endl;
700 
701  if (!success) return;
702 
703  }
704 
705 }
706 
707 /////////////////////////////////////////////////////////////////////////////////////////////////
708 void
710 {
711  // std::cout << "ABOUT TO SET UP JUMPS " << std::endl;
712  setup_jumps( pose );
713  // std::cout << "ABOUT TO SET UP CHAINBREAKS " << std::endl;
715 
716  tr << pose.annotated_sequence() << std::endl;
717  tr << pose.fold_tree() << std::endl;
718 
719 
720 }
721 
722 ///////////////////////////////////////////////////////////////
723 void
725 {
726 
727  ///////////////////////////////////////////////////////////
728  // Basic setup ==> How many jumps? cuts?
729  ///////////////////////////////////////////////////////////
730  Size const nres = pose.total_residue();
731  kinematics::FoldTree f( nres );
732 
733  Size const num_cuts_closed( cutpoints_closed_.size() );
734  Size const num_cuts_open ( cutpoints_open_.size() );
735  Size const num_cuts_total ( num_cuts_closed + num_cuts_open );
736 
737  Size const num_pairings( rna_pairing_list_.size() );
738  Size const num_obligate_pairing_sets( obligate_pairing_sets_.size() );
739  Size const num_possible_pairing_sets( possible_pairing_sets_.size() );
740  Size const num_chain_connections( chain_connections_.size() );
741  runtime_assert( num_possible_pairing_sets + num_obligate_pairing_sets <= num_pairings );
742 
743  ////////////////////////////////////////////////////////////////////////
744  // Two possibilities for desired fold tree topology:
745  // Jumps dominate, or cuts dominate.
746  Size const num_pairings_to_force = std::max( num_obligate_pairing_sets + num_chain_connections,
747  num_cuts_total );
748 
749  ////////////////////////////////////////////////////////////////////////
750  ObjexxFCL::FArray2D <int> jump_points( 2, num_pairings_to_force );
751  ObjexxFCL::FArray1D <int> cuts( num_pairings_to_force );
752 
753  //////////////////////////////////////////////////////////////////////
754  // Cuts.
755  //////////////////////////////////////////////////////////////////////
756  std::vector< int > obligate_cut_points; //switch this to utility::vector1?
757  for (Size n = 1; n<= num_cuts_closed; n++ ) obligate_cut_points.push_back( cutpoints_closed_[ n ] );
758  for (Size n = 1; n<= num_cuts_open ; n++ ) obligate_cut_points.push_back( cutpoints_open_[n] );
759  // for (Size n = 1; n <= num_cuts_total; n++ ) std::cout << "CUT " << obligate_cut_points[ n-1 ] << std::endl;
760 
761  //////////////////////////////////////////////////////////////////////
762  // If a cut needs to be randomly chosen, will generally try to
763  // place it in a loopy region.
764  FArray1D_float cut_bias( nres, 1.0 );
765  std::string const & rna_secstruct( get_rna_secstruct( pose ) );
766  for ( Size i = 1; i < nres; i++ ) {
767  if ( rna_secstruct[i] == 'H' && rna_secstruct[i+1] == 'H' ) {
768  cut_bias( i ) = 0.1;
769  }
770  if ( !pose.residue(i+1).is_RNA() ||
772  cut_bias( i ) = 0.0;
773  }
774  //std::cout << "CUT_BIAS " << i << " " << cut_bias( i ) << std::endl;
775  }
776 
777  //std::cout << "ALLOW INSERT IN CHECKING CUT_BIAS" << std::endl;
778  // allow_insert_->show();
779 
780  //////////////////////////////////////////////////////////////////////
781  // Jump residues.
782  //////////////////////////////////////////////////////////////////////
783  Size ntries( 0 );
784  Size const MAX_TRIES( 1000 );
785  bool success( false );
786 
787  while (!success && ++ntries < MAX_TRIES ){
788 
789  // First, put in a jump from each obligate pairing set.
790  Size count( 0 );
791 
792  for (Size n = 1; n <= num_obligate_pairing_sets ; n++ ){
793  Size const pairing_index_in_stem( static_cast<Size>( RG.uniform() * obligate_pairing_sets_[n].size() ) + 1 );
794  Size const which_pairing = obligate_pairing_sets_[n][pairing_index_in_stem];
795  count++;
796  jump_points(1, count) = rna_pairing_list_[which_pairing].pos1;
797  jump_points(2, count) = rna_pairing_list_[which_pairing].pos2;
798  // std::cout << "JUMPS1 " << jump_points(1,count) << ' ' << jump_points(2,count ) << std::endl;
799  }
800 
801 
802  // "Chain connections" provide less information about specific residues to pair --
803  // but they're assumed to be obligatory.
804  for (Size n = 1; n <= num_chain_connections ; n++ ){
805  utility::vector1 < Size > const & res_list1( chain_connections_[n].first );
806  utility::vector1 < Size > const & res_list2( chain_connections_[n].second);
807  Size const pairing_index_in_list1( static_cast<Size>( RG.uniform() * res_list1.size() ) + 1 );
808  Size const pairing_index_in_list2( static_cast<Size>( RG.uniform() * res_list2.size() ) + 1 );
809  count++;
810  jump_points(1, count) = res_list1[ pairing_index_in_list1 ];
811  jump_points(2, count) = res_list2[ pairing_index_in_list2 ];
812  // std::cout << "JUMPS2 " << jump_points(1,count) << ' ' << jump_points(2,count ) << std::endl;
813  }
814  // std::cout << std::endl;
815 
816  // Then, to fill out pairings, look at remaining possible pairing sets (these
817  // should typically be Watson-Crick stems, but this setup is general )
818  // Note that there might be three stems defined, but we only want two --
819  // following picks a random set of two.
820  FArray1D < bool > used_set( num_possible_pairing_sets, false );
821  Size num_sets_left( num_possible_pairing_sets );
822 
823  while ( count < num_pairings_to_force ) {
824 
825  // Find a random pairing among what's remaining.
826  Size const set_index( static_cast<Size>( RG.uniform() * num_sets_left ) + 1 );
827  Size m( 0 ), set_count( 0 );
828  for (m = 1; m <= num_possible_pairing_sets; m++ ){
829  if ( !used_set( m ) ) {
830  set_count++;
831  if (set_count == set_index ) break;
832  }
833  }
834 
835  if (m > num_possible_pairing_sets ) {
836  utility_exit_with_message( "Problem with pairing search "+I(3,num_possible_pairing_sets)+" "+I(3,m) );
837  }
838 
839  Size const pairing_index_in_set( static_cast<Size>( RG.uniform() * possible_pairing_sets_[m].size() ) + 1 );
840  Size const which_pairing = possible_pairing_sets_[m][pairing_index_in_set];
841 
842  // std::cout << "USING SET: " << m << " ==> " << pairing_index_in_set << std::endl;
843 
844  count++;
845  jump_points(1, count) = rna_pairing_list_[which_pairing].pos1;
846  jump_points(2, count) = rna_pairing_list_[which_pairing].pos2;
847 
848  used_set( m ) = true;
849  num_sets_left--;
850  }
851 
852  ////////////////////////////////////////////////////////////////////////////////
853  // Do it, get the fold tree. and set up the pose.
854  ////////////////////////////////////////////////////////////////////////////////
855  //f.tree_from_jumps_and_cuts( nres, num_pairings_to_force, jump_points, cuts, true /* verbose */);
856 
857  // std::cout << "Making attempt " << ntries << std::endl;
858  // for (Size n = 1; n <= num_pairings_to_force; n++ ){
859  // std::cout << "JUMPS " << jump_points(1, n) <<
860  // " " << jump_points(2, n) << std::endl;
861  // }
862 
863  success = f.random_tree_from_jump_points( nres, num_pairings_to_force, jump_points, obligate_cut_points, cut_bias, 1, true /*enable 1 or NRES jumps*/ );
864  }
865 
866  if (!success) utility_exit_with_message( "Couldn't find a freaking tree!" );
867 
868  // Hold on to torsion angles in case we need to set up chainbreak residues...
869  pose::Pose pose_copy = pose;
870 
871  fill_in_default_jump_atoms( f, pose );
872 
873  if ( virtual_anchor_attachment_points_.size() > 0 ){
874 
875  f.reorder( pose.total_residue() ); //reroot so that virtual residue is fixed.
876 
878  utility::vector1< Size > rigid_body_jumps = get_rigid_body_jumps( pose );
879  runtime_assert( rigid_body_jumps.size() > 0 );
880  Size const anchor_rsd = pose.fold_tree().upstream_jump_residue( rigid_body_jumps[1] );
881  std::cout << "ROOTING AT RSD" << anchor_rsd << std::endl;
882  f.reorder( anchor_rsd ); //reroot so that partner of virtual residue is fixed
883  }
884 
885  } else {
886 
887  // also useful -- if user has an input pdb, put the root in there, if possible.
888  for (Size n = pose.total_residue(); n >= 1; n-- ){ // not sure why I did this backwards...
889  if ( pose.residue(n).is_RNA() &&
890  allow_insert_->get_domain( named_atom_id_to_atom_id( id::NamedAtomID( " C1*", n ), pose ) ) == 1 /*1 means the first inputted pose*/ &&
891  possible_root(f,n) ) {
892  f.reorder( n );
893  break;
894  }
895  }
896 
897  }
898 
899  pose.fold_tree( f );
900 
901  bool const random_jumps( true ); // For now this is true... perhaps should also have a more deterministic procedure.
902  if (random_jumps) insert_base_pair_jumps( pose, success );
903 
904  // pose.dump_pdb( "insert_jumps.pdb" );
905 
906  if (!success) {
907  utility_exit_with_message( "Trouble inserting base pair jumps into pose -- check residues and edges." );
908  }
909 }
910 
911 
912 
913 ///////////////////////////////////////////////////////////////
914 void
916 {
917 
918  // default atoms for jump connections.
919  for (Size i = 1; i <= f.num_jump(); i++ ){
920  Size const jump_pos1( f.upstream_jump_residue( i ) );
921  Size const jump_pos2( f.downstream_jump_residue( i ) );
922  f.set_jump_atoms( i,
923  scoring::rna::default_jump_atom( pose.residue( jump_pos1 ) ),
924  scoring::rna::default_jump_atom( pose.residue( jump_pos2) ) );
925  }
926 
927 }
928 
929 ///////////////////////////////////////////////////////////////
930 void
932 {
933 
934  pose::Pose pose_copy = pose;
935 
936  // Create cutpoint variants to force chainbreak score computation.
937  for ( Size cutpos = 1; cutpos < pose.total_residue(); cutpos++ ){
938 
939  if ( ! pose.fold_tree().is_cutpoint( cutpos ) ) continue;
940 
941  // Don't assign a chainbreak penalty if user said this was an "open" cutpoint.
942  if ( std::find( cutpoints_open_.begin(), cutpoints_open_.end(), cutpos) != cutpoints_open_.end() ) continue;
943 
944  // if ( !pose.residue( cutpos ).is_coarse() ) {//its regular RNA
945 
946  std::cout << "Adding chainbreak variants to " << cutpos << std::endl;
947 
948  // important! Taken from SWA code.
950 
953 
954  for (Size i = cutpos; i <= cutpos + 1; i++ ){
955  for (Size j = 1; j <= pose.residue( i ).mainchain_torsions().size(); j++ ) {
956  id::TorsionID torsion_id( i, id::BB, j );
957  pose.set_torsion( torsion_id, pose_copy.torsion( torsion_id ) ) ;
958  } // j
959  } // i
960  // } else {
961  // setup_coarse_chainbreak_constraints( pose, cutpos );
962  // }
963  }
964 
965  allow_insert_->renumber_after_variant_changes( pose );
966 
967 }
968 
969 ////////////////////////////////////////////////////////////////////////////////////////
970 // remove this by end of 2012.
971 void
973 {
974 
975  if ( pose.residue( 1 ).is_RNA() ) {
977  allow_insert_->set_phosphate( 1, pose, false );
978  }
979 
980  for ( Size n = 1; n < pose.total_residue(); n++ ){
981 
982  if ( pose.fold_tree().is_cutpoint( n ) &&
985  pose.residue_type( n+1 ).is_RNA() ){
986 
988 
989  // not necessary since virtualizing does not (should not!) change atom numbering.
990  // allow_insert_->renumber_after_variant_changes( pose );
991 
992  allow_insert_->set_phosphate( n+1, pose, false );
993 
994  }
995 
996  }
997 
998 }
999 
1000 
1001 ////////////////////////////////////////////////////////////////////////////////////////
1002 void
1004 {
1005  using namespace id;
1006 
1007  if ( pose.residue( 1 ).is_RNA() ) {
1009  allow_insert_->set_phosphate( 1, pose, false );
1010  }
1011 
1012  for ( Size i = 1; i <= cutpoints_open_.size(); i++ ){
1013 
1014  Size n = cutpoints_open_[ i ];
1015 
1016  if ( n == pose.total_residue() ){
1017  utility_exit_with_message( "Do not specify cutpoint_open at last residue of model" );
1018  }
1019 
1022  utility_exit_with_message( "conflicting cutpoint_open & cutpoint_closed" );
1023  }
1024 
1025  if ( pose.residue_type( n+1 ).is_RNA() ){
1027  allow_insert_->set_phosphate( n+1, pose, false );
1028  // make sure no fragments are wasted on moving this phosphate around...
1029  // perhaps this should go into set_phosphate itself
1030  // allow_insert_->set( named_atom_id_to_atom_id( NamedAtomID( "1H5*", n+1 ), pose ), false );
1031  // allow_insert_->set( named_atom_id_to_atom_id( NamedAtomID( "2H5*", n+1 ), pose ), false );
1032  }
1033 
1034  }
1035 
1036 
1037 }
1038 
1039 /////////////////////////////////////////////////////////
1040 bool
1042 {
1043 
1044  using namespace core::conformation;
1045  using namespace core::scoring::rna;
1046  using namespace core::id;
1047 
1048  // Any jumps in here to tweak?
1049  Size const num_jump = pose.num_jump();
1050  if (num_jump == 0) return false;
1051 
1052  Size ntries( 0 );
1053  Size const MAX_TRIES( 1000 );
1054 
1055  Size which_jump( 0 );
1056 
1057  while ( ntries++ < MAX_TRIES ){
1058  // Randomly pick one.
1059  which_jump = static_cast<Size>( RG.uniform() * num_jump ) + 1 ;
1060 
1061  // Check that we can actually insert here. At least one of the jump partners
1062  // should allow moves. (I guess the other one can stay fixed).
1063  Size const jump_pos1( pose.fold_tree().upstream_jump_residue( which_jump ) );
1064  // Size const jump_pos2( pose.fold_tree().downstream_jump_residue( which_jump ) ); // Unused variable causes warning.
1065 
1066  Residue const & rsd1 = pose.residue( jump_pos1 );
1067  AtomID jump_atom_id1( rsd1.atom_index( default_jump_atom( rsd1 ) ), jump_pos1 );
1068 
1069  // Residue const & rsd2 = pose.residue( jump_pos2 ); // Unused variable causes warning.
1070  // AtomID jump_atom_id2( rsd2.atom_index( default_jump_atom( rsd2 ) ), jump_pos2 ); // Unused variable causes warning.
1071 
1072  if ( allow_insert_->get( jump_atom_id1 ) ||
1073  allow_insert_->get( jump_atom_id1 ) ) break; // found an OK jump.
1074 
1075  }
1076  if (ntries >= MAX_TRIES ) return false;
1077 
1078  //std::cout << "will try to change jump " << which_jump << std::endl;
1079 
1080  // Tweak it -- for connections between chains for which the residue is unknown
1081  // consider alternative connection -- if there aren't any jumps of these types,
1082  // following does nothing.
1083  sample_alternative_chain_connection( pose, which_jump );
1084 
1085  // Shift jump.
1086  bool success( false );
1087  add_new_RNA_jump( pose, which_jump, success );
1088 
1089  return success;
1090 
1091 }
1092 
1093 /////////////////////////////////////////////////////////
1094 bool
1096 {
1097  using namespace scoring::rna;
1098  static RNA_LowResolutionPotential const rna_low_resolution_potential;
1099 
1100  for (Size n = 1; n <= rna_pairing_list_.size(); n++ ){
1101 
1102  RNA_Pairing const & rna_pairing( rna_pairing_list_[ n ] );
1103  Size i( rna_pairing.pos1 );
1104  Size j( rna_pairing.pos2 );
1105  if (i > j ) {
1106  i = rna_pairing.pos2;
1107  j = rna_pairing.pos1;
1108  }
1109 
1110  // are these part of the pose that is actually being moved?
1111  if ( !allow_insert_->get( named_atom_id_to_atom_id( id::NamedAtomID( "C1*", i ), pose ) ) ) continue;
1112  if ( !allow_insert_->get( named_atom_id_to_atom_id( id::NamedAtomID( "C1*", j ), pose ) ) ) continue;
1113 
1114  if ( !rna_low_resolution_potential.check_forming_base_pair(pose,i,j) ) {
1115  tr << "MISSING BASE PAIR " << i << " " << j << std::endl;
1116  return false;
1117  }
1118 
1119  if (rna_pairing.edge1 == 'W' && rna_pairing.edge2 == 'W' && rna_pairing.orientation=='A' ) {
1120 
1121  if ( is_cutpoint_open(pose, i) && is_cutpoint_open( pose, j-1) ) {
1122 
1123  if ( !rna_low_resolution_potential.check_clear_for_stacking( pose, i, +1 /* sign */)) return false;
1124  if ( !rna_low_resolution_potential.check_clear_for_stacking( pose, j, -1 /* sign*/ )) return false;
1125 
1126  } else if ( is_cutpoint_open( pose, i-1 ) && is_cutpoint_open( pose, j) ){
1127 
1128  if ( !rna_low_resolution_potential.check_clear_for_stacking( pose, i, -1 /* sign */)) return false;
1129  if ( !rna_low_resolution_potential.check_clear_for_stacking( pose, j, +1 /* sign*/ )) return false;
1130 
1131  }
1132  }
1133 
1134 
1135  }
1136 
1137  return true;
1138 
1139 }
1140 
1141 ///////////////////////////////////////////////////////////////////////////////////////
1142 void
1144 {
1145 
1146  using namespace core::id;
1147 
1149 
1150  // Go through all pairings and define atom pair constraints that will bring together
1151  // appropriate atoms on bases.
1152  for (Size n = 1; n <= rna_pairing_list_.size(); n++ ){
1153 
1154  RNA_Pairing const & rna_pairing( rna_pairing_list_[ n ] );
1155  Size const & i( rna_pairing.pos1 );
1156  Size const & j( rna_pairing.pos2 );
1157 
1158  //Basic check that its canonical...
1159  if ( !( rna_pairing.edge1 == 'W' && rna_pairing.edge2 == 'W' && rna_pairing.orientation == 'A' ) ) {
1160  tr << "skipping constraints for non-canonical base pair: " << I(3,i) << " " << I(3,j) << " " << rna_pairing.edge1 << " " << rna_pairing.edge2 << " " << rna_pairing.orientation << std::endl;
1161  continue;
1162  }
1163 
1164  if ( !pose.residue(i).is_RNA() ) continue;
1165  if ( !pose.residue(j).is_RNA() ) continue;
1166 
1167  if ( !allow_insert_->get( named_atom_id_to_atom_id( NamedAtomID( "C1*", i ), pose ) ) &&
1168  !allow_insert_->get( named_atom_id_to_atom_id( NamedAtomID( "C1*", j ), pose ) ) ) continue; //assumed to be frozen, so no need to set up constraints?
1169 
1170  pairings.push_back( std::make_pair( i, j ) ) ;
1171  }
1172 
1173  // In RNA_ProtocolUtil.cc :
1175 }
1176 
1177 /////////////////////////////////////////////////////////////////////
1178 std::map< Size, Size >
1180 {
1181 
1182  std::map< Size, Size > connections_local;
1183  for ( Size n = 1; n <= rna_pairing_list_.size(); n++ ) {
1184  RNA_Pairing pairing = rna_pairing_list_[n];
1185  connections_local[ pairing.pos1 ] = pairing.pos2;
1186  connections_local[ pairing.pos2 ] = pairing.pos1;
1187  }
1188  return connections_local;
1189 }
1190 
1191 ////////////////////////////////////////////////////////////////////////////////////////
1192 void
1194 {
1195  allow_insert_ = allow_insert_in;
1196 }
1197 
1198 ////////////////////////////////////////////////////////////////////////////////////////
1201 
1202 ////////////////////////////////////////////////////////////////////////////////////////
1203 void
1205 {
1206  rna_jump_library_ = rna_jump_library;
1207 }
1208 
1209 }
1210 }
1211 
1212 
1213