Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SegmentRebuild.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 protocols/forge/build/SegmentRebuild.cc
11 /// @brief instruction to rebuild a segment
12 /// @author Yih-En Andrew Ban (yab@u.washington.edu)
13 
14 // unit headers
16 
17 // package headers
21 // AUTO-REMOVED #include <protocols/loops/util.hh>
22 
23 // project headers
24 
30 // AUTO-REMOVED #include <core/chemical/ResidueTypeSet.hh>
31 #include <core/id/TorsionID.hh>
35 #include <core/pose/Pose.hh>
36 #include <basic/options/keys/remodel.OptionKeys.gen.hh>
37 #include <basic/options/option.hh>
38 #include <core/pose/PDBInfo.hh>
39 
40 
41 // numeric headers
42 #include <numeric/random/random.hh>
43 
44 // utility headers
45 #include <utility/vector1.hh>
46 #include <ObjexxFCL/FArray1D.hh>
47 #include <ObjexxFCL/FArray2D.hh>
48 // C++ headers
49 #include <algorithm>
50 #include <iostream>
51 #include <set>
52 
54 
55 
56 
57 namespace protocols {
58 namespace forge {
59 namespace build {
60 
61 
62 static numeric::random::RandomGenerator RG( 313222 ); // magic number, don't change
63 
64 
65 /// @brief default constructor
67  Super(),
68  keep_known_bb_torsions_at_junctions_( false )
69 {}
70 
71 
72 /// @brief sec.struct only constructor (poly-alanine for new region)
73 /// @param[in] interval rebuild this range of residues
74 /// @param[in] ss the secondary structure desired, also defines length of new build region
75 /// @param[in] rts the residue type set to use, default FA_STANDARD
76 /// @param[in] keep_known_bb_torsions_at_junctions Attempt to keep the omega
77 /// at original_interval().left-1, the phi at original_interval().left, and
78 /// the psi+omega at original_interval().right present from the original Pose
79 /// in the modified Pose.
80 /// @remarks length of the *one-letter* aa must equal the length of ss
82  Interval const & i,
83  String const & ss,
85  bool const keep_known_bb_torsions_at_junctions
86 ) :
87  Super( i, rts ),
88  interval_( i ),
89  ss_( ss ),
90  keep_known_bb_torsions_at_junctions_( keep_known_bb_torsions_at_junctions )
91 {
92  // build poly-alanine if empty string
93  if ( aa_.empty() ) {
94  aa_ = String( ss_.length(), 'A' );
95  }
96 
97  runtime_assert( ss_.length() == core::pose::annotated_to_oneletter_sequence( aa_ ).length() );
98 }
99 
100 
101 /// @brief full constructor
102 /// @param[in] interval rebuild this range of residues
103 /// @param[in] ss the secondary structure desired, also defines length of new build region
104 /// @param[in] aa the annotated amino acid sequence desired, default is poly-alanine
105 /// @param[in] rts the residue type set to use, default FA_STANDARD
106 /// @param[in] keep_known_bb_torsions_at_junctions Attempt to keep the omega
107 /// at original_interval().left-1, the phi at original_interval().left, and
108 /// the psi+omega at original_interval().right present from the original Pose
109 /// in the modified Pose.
110 /// @remarks length of the *one-letter* aa must equal the length of ss
112  Interval const & i,
113  String const & ss,
114  String const & aa,
115  ResidueTypeSetCAP rts,
116  bool const keep_known_bb_torsions_at_junctions
117 ) :
118  Super( i, rts ),
119  interval_( i ),
120  ss_( ss ),
121  aa_( aa ),
122  keep_known_bb_torsions_at_junctions_( keep_known_bb_torsions_at_junctions )
123 {
124  // build poly-alanine if empty string
125  if ( aa_.empty() ) {
126  aa_ = String( ss_.length(), 'A' );
127  }
128 
129  runtime_assert( ss_.length() == core::pose::annotated_to_oneletter_sequence( aa_ ).length() );
130 }
131 
132 
133 /// @brief copy constructor
135  Super( rval ),
136  interval_( rval.interval_ ),
137  ss_( rval.ss_ ),
138  aa_( rval.aa_ ),
139  keep_known_bb_torsions_at_junctions_( rval.keep_known_bb_torsions_at_junctions_ )
140 {}
141 
142 
143 /// @brief default destructor
145 
146 
147 /// @brief copy assignment
149  if ( this != &rval ) {
150  Super::operator =( rval );
151 
152  interval_ = rval.interval_;
153  ss_ = rval.ss_;
154  aa_ = rval.aa_;
156  }
157  return *this;
158 }
159 
160 
161 /// @brief clone this object
163  return new SegmentRebuild( *this );
164 }
165 
166 
167 /// @brief return a copy of the set of positions within the new region
168 /// that were pre-existing in the original Pose prior to modify()
169 /// @return An empty set -- no positions are pre-existing.
171  return Positions();
172 }
173 
174 
175 /// @brief return a copy of the set of positions that are "new" and did
176 /// not exist in the original Pose.
177 /// @return A set of positions spanning the entire modified interval -- all
178 /// positions are undefined.
181 
182  Interval const ival = interval();
183  return closed_range( ival.left, ival.right );
184 }
185 
186 
187 /// @brief return a copy of the set of positions within the newly modified
188 /// region that has a defined conformation. E.g. existing or copied residues.
189 /// @return An empty set -- no positions are defined.
190 /// @details This set can change wrt length changes in Pose/Conformation being
191 /// watched.
193  return Positions();
194 }
195 
196 
197 /// @brief return a copy of the set of positions within the newly modified
198 /// region that has an undefined conformation. E.g. newly created residues.
199 /// @return A set of positions spanning the entire modified interval -- all
200 /// positions are undefined.
201 /// @details This set can change wrt length changes in Pose/Conformation being
202 /// watched.
204  // for SegmentRebuild this is the same as the new positions
205  return new_positions();
206 }
207 
208 
209 /// @brief return a copy of the MoveMap that defines the moveable/fixed
210 /// positions/dofs for this instruction
211 /// @return a MoveMap with [interval.left, interval.right] bb & chi set to true
212 /// at the MoveMapTorsionID level
213 /// @details This set can change wrt length changes in Pose/Conformation being
214 /// watched.
216  using core::id::BB;
217  using core::id::phi_torsion;
218  using core::id::psi_torsion;
220  using core::id::TorsionID;
221 
222  MoveMap mm;
223 
224  Interval const ival = interval();
225  Size begin = ival.left;
226  Size end = ival.right;
227 
229  ++begin;
230  --end;
231 
232  // left residue, only psi+omega+chi move
233  mm.set( TorsionID( ival.left, BB, phi_torsion ), false );
234  mm.set( TorsionID( ival.left, BB, psi_torsion ), true );
235  mm.set( TorsionID( ival.left, BB, omega_torsion ), true );
236  mm.set_chi( ival.left, true );
237 
238  // right residue, only phi+chi moves
239  mm.set( TorsionID( ival.right, BB, phi_torsion ), true );
240  mm.set( TorsionID( ival.right, BB, psi_torsion ), false );
241  mm.set( TorsionID( ival.right, BB, omega_torsion ), false );
242  mm.set_chi( ival.right, true );
243  }
244 
245  for ( Size i = begin; i <= end; ++i ) {
246  mm.set_bb( i, true );
247  mm.set_chi( i, true );
248  }
249 
250  return mm;
251 }
252 
253 
254 /// @brief update indexing on residue append
255 /// @remarks left and right endpoints of the interval can travel independently
257  if ( event.position < interval_.left ) {
258  //++interval_.left;
259  interval_.left += event.length_change;
260  }
261 
262  if ( event.position < interval_.right ) {
263  //++interval_.right;
264  interval_.right += event.length_change;
265  }
266 }
267 
268 
269 /// @brief update indexing on residue prepend
270 /// @remarks left and right endpoints of the interval can travel independently
272  if ( event.position <= interval_.left ) {
273  //++interval_.left;
274  interval_.left += event.length_change;
275  }
276 
277  if ( event.position <= interval_.right ) {
278  //++interval_.right;
279  interval_.right += event.length_change;
280  }
281 }
282 
283 
284 /// @brief update indexing on residue delete
285 /// @remarks Left and right endpoints of the interval can travel independently.
287  // event.position == interval.left is not caught below.
288  // It has context dependent consequences and is manually corrected for
289  // during modify().
290  if ( event.position < interval_.left ) { // left
291  //--interval_.left;
292  if( int(interval_.left) + event.length_change < int(event.position) ) interval_.left = event.position;
293  else interval_.left += event.length_change;
294  }
295 
296  if ( event.position < interval_.right ) { // right
297  //--interval_.right;
298  if( int(interval_.right) + event.length_change < int(event.position) ) interval_.right = event.position;
299  else interval_.right += event.length_change;
300  }
301 }
302 
303 
304 /// @brief return the set of positions within the original interval that
305 /// will be kept in this BuildInstruction
306 /// @return An empty set -- no positions are kept.
308  return Positions();
309 }
310 
311 
312 /// @brief return set of positions within the original interval that will
313 /// be deleted in this BuildInstruction
314 /// @return A set containing all positions in the original interval.
318 }
319 
320 
321 /// @brief return set of any fixed positions necessary with respect to the original
322 /// interval and original Pose numbering
323 /// @remarks Used for ensuring build regions for instructions do not overlap and
324 /// so that jumps may be placed correctly. If SegmentRebuild has dependencies,
325 /// the set of positions shrinks from the endpoints of [original_left - 1, original_right + 1]
326 /// down to an empty set in the assumption that the user is requesting an
327 /// advanced feature and knows what they're doing around the endpoints,
328 /// e.g. rebuilding directly adjacent to a swapped out section.
329 /// @return empty set if no fixed positions necessary
331  Positions fixed;
332 
333  // If there are dependencies, then we relax the requirements and assume
334  // that the user might be directing the rebuild section directly adjacent to
335  // an e.g. swapped section and return an empty set. This is an advanced
336  // option, so we assume the user understands what they're doing around the
337  // endpoints.
338 
339  if ( !has_dependencies() ) { // typical case without dependencies
340  fixed.insert( original_interval().left - 1 );
341  fixed.insert( original_interval().right + 1 );
342  }
343 
344  return fixed;
345 }
346 
347 
348 /// @brief return set of any mutable positions necessary with respect to the original
349 /// interval and original Pose numbering
350 /// @remarks Used for ensuring build regions for instructions do not overlap and
351 /// so that jumps may be placed correctly.
352 /// @return empty set if no mutable positions
356 }
357 
358 
359 /// @brief do the actual work of modifying the Pose
360 /// @details There are two cases:
361 /// <ul>
362 /// <li> internal rebuild where no residue of the segment is a terminus
363 /// <li> boundary rebuild where one residue of the segment is a terminus
364 /// </ul>
365 /// In the case of an internal rebuild, the old segment will be removed and
366 /// a new segment containing a random cutpoint will be inserted. The new jump
367 /// will be created between (left-1) and (right+1) of the new segment.
372 
383  using namespace core::conformation;
384 /*
385 
386  //special case for two chain build -- danger, primitive at the moment, only
387  //works with non-N,C term extension. Try placing in SegRebuld
388  if (basic::options::option[basic::options::OptionKeys::remodel::two_chain_tree].user()){
389  Size second_start = basic::options::option[basic::options::OptionKeys::remodel::two_chain_tree];
390  Size nres( pose.total_residue());
391 
392  //FoldTree f(pose.fold_tree());
393  FoldTree f;
394  //make cutpoint
395  f.add_edge(1, second_start-1, Edge::PEPTIDE);
396  f.add_edge(second_start, nres, Edge::PEPTIDE);
397  f.add_edge(second_start-1,second_start,1);//jump across the cut
398  f.reorder(nres);
399  pose.fold_tree(f);
400 
401  protocols:loops::Loops chain_def_loops;
402  chain_def_loops.add_loop(protocols::loops::Loop(1,second_start));
403  chain_def_loops.add_loop(protocols::loops::Loop(second_start,pose.total_residue()));
404 
405  //add virtual residue, as star foldtree requires it
406  if (pose.residue( pose.total_residue()).aa() != core::chemical::aa_vrt){
407  pose.append_residue_by_jump(*core::conformation::ResidueFactory::create_residue( pose.residue(1).residue_type_set().name_map("VRT")), pose.total_residue());
408  }
409 
410  //update foldtree to new foldtree
411  f = pose.fold_tree();
412 
413  //update nres to include the new residue
414  nres = pose.total_residue();
415 
416  f.reorder(nres);
417  pose.fold_tree(f);
418  protocols::forge::methods::make_star_foldtree(pose, chain_def_loops);
419  }
420 */
421  typedef utility::vector1< Edge > Edges;
422 
423  //for nojump operation, need to keep track of the new cuts introduced
424  Size new_cut = 0 ;
425 
426  // there are two cases below:
427  // (1) internal rebuild where the segment may either be continuous or have cutpoints
428  // at any position along [left-1, right]
429  // (2) boundary rebuild where one of the endpoints of the segment is a terminus
430 
431  // cache information from original structure
432  bool const has_lower_terminus = pose.residue( interval_.left ).is_lower_terminus();
433  bool const has_upper_terminus = pose.residue( interval_.right ).is_upper_terminus();
434  Size const old_root = pose.fold_tree().root();
435 
436  // If the following runtime_assert is triggered, that likely means you
437  // tried to replace the entire length of the Pose or an entire chain of
438  // a multi-chain Pose. This class currently doesn't handle those cases
439  // properly and will likely break.
440  // but when only the case of single chain is allowed
441  if( pose.conformation().num_chains() != 1 ){
442  runtime_assert( !( has_lower_terminus && has_upper_terminus ) );
443  }
444 
445  // count # cutpoints along segment [left-1, right]
446  Size n_cutpoints = 0;
447  for ( Size i = interval_.left - 1; i <= interval_.right; ++i ) {
448  if ( pose.fold_tree().is_cutpoint( i ) ) {
449  ++n_cutpoints;
450  }
451  }
452 
453  // save psi @ left-1 and phi @ right+1 to ensure they are set correctly
454  // and not junked after residue deletion, set to 999.0 if not applicable
455  Real const pre_psi = !has_lower_terminus ? pose.psi( interval_.left - 1 ) : 999.0;
456  Real const post_phi = !has_upper_terminus ? pose.phi( interval_.right + 1 ) : 999.0;
457 
458  // Store omega at original_interval().left-1, phi at original_interval().left,
459  // and psi+omega at original_interval().right if user requests keeping them in
460  // the equivalent positions in the modified Pose. Set to 999.0 if not applicable.
461  //
462  // TODO: I think there might be an issue here... if keeping the known
463  // backbone torsions at the junctions, we should consider also keeping
464  // in bond lengths and bond angles surrounding the junction. That's
465  // currently not done.
466  Real left_endpoint_minus_one_omega = 999.0;
467  Real left_endpoint_phi = 999.0;
468  Real right_endpoint_psi = 999.0;
469  Real right_endpoint_omega = 999.0;
471  // on the left
472  if ( !has_lower_terminus && interval_.left > 1 ) {
473  left_endpoint_minus_one_omega = pose.omega( interval_.left - 1 );
474  left_endpoint_phi = pose.phi( interval_.left );
475  }
476 
477  // on the right
478  if ( !has_upper_terminus && interval_.right < pose.n_residue() ) {
479  right_endpoint_psi = pose.psi( interval_.right );
480  right_endpoint_omega = pose.omega( interval_.right );
481  }
482  }
483 
484  // grab residue types from aa string
486  assert( ss_.length() == r_types.size() );
487 
488  // BEGIN INTERVAL SHIFT: after this point, interval_ will begin to shift due to length
489  // changes in the Pose
490 
491  if ( pose.conformation().num_chains() == 1 && has_lower_terminus && has_upper_terminus ) {
492 
493  // Store observer state. If this object was attaached to the Pose, we need
494  // to re-attach.
495  bool const was_connected = length_obs_link().valid();
496 
497  // Catch special case for single chain. FoldTree currently refuses to delete
498  // an entire tree, so we clear the entire Pose.
499  pose.clear();
500 
501  // Clearing the Pose invalidates observers, so we need to re-hook ourselves
502  // back onto the Pose if previously connected.
503  if ( was_connected ) {
504  attach_to( pose );
505  }
506 
507  } else {
508 
509  // Blow away the old segment. delete_residue_range_slow() should keep
510  // all coordinates intact, though the bond lengths/angles adjacent to
511  // the deletion might get funky. Any strange geometry should get resolved
512  // upon append/prepend of residues w/ ideal geometry below
514  assert( interval_.left == interval_.right );
515 
516  }
517 
518 //testing
519 //first identify the number of jups at this stage, this is the number to keep.
520  Size num_jumps_pre_processing (pose.num_jump());
521 
522 
523  // perform the append/prepend operations
524  if ( pose.conformation().num_chains() == 1 && has_lower_terminus && has_upper_terminus ) {
525 
526  --interval_.left;
527  interval_.right = 1; // artificially set to 1 for assertion check
528 
529  // only grow right; termini will not be recovered here due to prior
530  // residue deletions and is corrected for below
531  assert( grow_right_rtype( pose, interval_.left, r_types.begin(), r_types.end() ) == interval_.right - 1 );
532 
533  // set to proper interval
534  assert( ss_.length() == interval_.right - 1);
535  interval_.left = 1;
536  interval_.right = ss_.length(); // or --interval_.right
537 
538  // re-add terminus
539  if ( !pose.residue( interval_.right ).is_upper_terminus() ) {
541  }
542 
543  // re-add terminus
544  if ( !pose.residue( interval_.left ).is_lower_terminus() ) {
546  }
547 
548  } else if ( has_lower_terminus ) { // left boundary rebuild
549 
550  // At this point the endpoints of the interval should both sit at
551  // the anchor position where the prepend operations should happen.
552 
553  // only grow left; termini will not be recovered here due to prior
554  // residue deletions and is corrected for below
555  Size const left_endpoint = grow_left_rtype( pose, interval_.right, r_types.rbegin(), r_types.rend() );
556  assert( left_endpoint == interval_.right - r_types.size() );
557 
558  // correct endpoints of interval to match the actual rebuilt segment
559  interval_.left = left_endpoint;
560  --interval_.right;
561  assert( interval_.right - interval_.left + 1 == r_types.size() );
562 
563  // re-add terminus
564  if ( !pose.residue( interval_.left ).is_lower_terminus() ) {
566  }
567 
568  // re-root tree towards the right
569  if ( original_interval().contains( old_root ) ) {
570  FoldTree ft = pose.fold_tree();
572  pose.fold_tree( ft );
573  }
574 
575  } else if ( has_upper_terminus ) { // right boundary rebuild
576 
577  // At this point the endpoints of the interval should both sit +1
578  // position to where the append operations should happen.
579  // Temporarily shift both endpoints back one to sit at anchor.
580  --interval_.left;
581  --interval_.right;
582 
583  // only grow right; termini will not be recovered here due to prior
584  // residue deletions and is corrected for below
585  Size const right_endpoint = grow_right_rtype( pose, interval_.left, r_types.begin(), r_types.end() );
586  assert( right_endpoint == interval_.left + r_types.size() );
587 
588  // correct endpoints of interval to match the actual rebuilt segment
589  ++interval_.left;
590  interval_.right = right_endpoint;
591  assert( interval_.right - interval_.left + 1 == r_types.size() );
592 
593  // re-add terminus
594  if ( !pose.residue( interval_.right ).is_upper_terminus() ) {
596  }
597 
598  // re-root tree towards the left
599  if ( original_interval().contains( old_root ) ) {
600  FoldTree ft = pose.fold_tree();
602  pose.fold_tree( ft );
603  }
604 
605  } else { // internal rebuild
606 
607  // assign cutpoint, -1 ensures the cut happens internal to the range
608  // TODO: consider using sec.struct to preferentially select a cutpoint
609  Size cut_index = RG.random_range( 1, r_types.size() - 1);
610 
611  //in order to synchronize all cutting, unfortunately this has to be in this
612  //file
613  if (basic::options::option[basic::options::OptionKeys::remodel::RemodelLoopMover::bypass_closure].user()){
614  if (basic::options::option[basic::options::OptionKeys::remodel::RemodelLoopMover::force_cutting_N].user()){
615  cut_index = 1;
616  }
617  else {
618  cut_index = r_types.size()-1;
619  }
620  }
621 
622  // Temporarily shift the endpoints to the anchor points:
623  // The left endpoint goes back one and the right endpoint is
624  // left where it is, so it can travel as the append/prepend operations
625  // occur.
626  --interval_.left;
627  assert( interval_.left + 1 == interval_.right );
628 
629  // Do any necessary chain corrections before growing residues; need to
630  // merge chains if different. Here we check the position currently at
631  // interval.left - 1 and remove it from the chain endings list.
632  if (
633  std::find(
634  pose.conformation().chain_endings().begin(),
635  pose.conformation().chain_endings().end(),
637  ) != pose.conformation().chain_endings().end()
638  )
639  {
641  }
642 
643  // Make a new jump only if the original segment was continuous.
644  // If the original segment had jumps anywhere along [left-1, right]
645  // this should imply there is already a jump connecting the left and right
646  // halves. If the jump existed somewhere in the original segment, the
647  // residue deletion should have shifted the jump to an appropriate place.
648  // In the case of an existing jump that is adjacent to the interval,
649  // we need to modify the jump atoms so that changes in the dihedrals do
650  // not shift the conformation.
651  FoldTree ft = pose.fold_tree();
652  Size const root = ft.root();
653 
654  if ( n_cutpoints == 0 ) { // need a new jump
655  Size const new_jump_number = ft.new_jump( interval_.left, interval_.right, interval_.left );
656 
657  // following ensures changes in dihedral below do not shift the
658  // conformation
659  ft.jump_edge( new_jump_number ).start_atom() = "N";
660  ft.jump_edge( new_jump_number ).stop_atom() = "C";
661 
662  } else { // check/modify existing jump
663 
664  Size const jump = find_connecting_jump( interval_.left, interval_.right, ft );
665 
666  // We only do operations if there happens to be a jump defined
667  // between the segments that 'left' and 'right' live on.
668  if ( jump > 0 ) {
669 
670  Edge jump_edge = ft.jump_edge( jump );
671  ft.delete_edge( jump_edge ); // remove edge
672 
673  // next two 'if' statements ensures changes in dihedral below do
674  // not shift the conformation
675  order( jump_edge );
676 
677  if ( static_cast< Size >( jump_edge.start() ) == interval_.left ) {
678  jump_edge.start_atom() = "N";
679  } else if ( jump_edge.start_atom().empty() ) {
680  // if no existing jump atom, need to fill it in, otherwise
681  // edge will not be recognized as having specific atom
682  // settings
683  jump_edge.start_atom() = pose.residue( jump_edge.start() ).atom_name(
684  get_anchor_atomno( pose.residue( jump_edge.start() ), core::kinematics::dir_jump )
685  );
686  }
687 
688  if ( static_cast< Size >( jump_edge.stop() ) == interval_.right ) {
689  jump_edge.stop_atom() = "C";
690  } else if ( jump_edge.stop_atom().empty() ) {
691  // if no existing jump atom, need to fill it in, otherwise
692  // edge will not be recognized as having specific atom
693  // settings
694  jump_edge.stop_atom() = pose.residue( jump_edge.stop() ).atom_name(
695  get_anchor_atomno( pose.residue( jump_edge.stop() ), core::kinematics::dir_jump )
696  );
697  }
698 
699  ft.add_edge( jump_edge ); // re-add modified edge
700  }
701  }
702 
703  ft.reorder( root );
704 
705  pose.fold_tree( ft );
706 
707  // Append up until & including cutpoint. Since this is an internal
708  // rebuild, tell grow_right_rtype not to maintain any existing termini
709  // variant; this is a safety, since residue deletion should have removed
710  // any such variant.
711  Size left_of_cut = grow_right_rtype(
712  pose, interval_.left,
713  r_types.begin(), r_types.begin() + cut_index,
714  false
715  );
716  new_cut = left_of_cut;
717  //std::cout << "new cuts made: " << left_of_cut << std::endl;
718  // Prepend down until right before cutpoint. Since this is an internal
719  // rebuild, tell grow_left_rtype not to maintain any existing termini
720  // variant; this is a safety, since residue deletion should have removed
721  // any such variant.
722  Size right_of_cut = grow_left_rtype(
723  pose, interval_.right,
724  r_types.rbegin(), r_types.rbegin() + ( r_types.size() - cut_index ),
725  false
726  );
727 
728  runtime_assert( left_of_cut + 1 == right_of_cut );
729  runtime_assert( !pose.residue( left_of_cut ).is_upper_terminus() );
730  runtime_assert( !pose.residue( right_of_cut ).is_lower_terminus() );
731 
732  // correct endpoints of interval to match the actual rebuilt segment
733  ++interval_.left;
734  --interval_.right;
735  assert( interval_.right - interval_.left + 1 == r_types.size() );
736  }
737 
738  // END INTERVAL SHIFT: after this point, interval_ has stabilized and stores
739  // the new endpoints of the rebuilt segment
740 
741  // Handle any jumps that happen to connect to left-1 or right+1. These
742  // need to have their jump atoms altered so that the torsion changes below
743  // don't cause any rigid body shifts.
744  FoldTree ft = pose.fold_tree();
745  bool ft_was_altered = false;
746  for ( FoldTree::const_iterator e = pose.fold_tree().begin(), ee = pose.fold_tree().end(); e != ee; ++e ) {
747  if ( e->label() > 0 ) {
748  Edge tmp = *e;
749  order( tmp );
750 
751  bool start_changed = false;
752  if ( static_cast< Size >( tmp.start() ) == interval_.left - 1 ) {
753  tmp.start_atom() = "N";
754  start_changed = true;
755  }
756 
757  bool stop_changed = false;
758  if ( static_cast< Size >( tmp.stop() ) == interval_.right + 1 ) {
759  tmp.stop_atom() = "C";
760  stop_changed = true;
761  }
762 
763  // Must set opposing atom if it's not already set, otherwise
764  // refold procedure will not recognize this edge as having
765  // custom jump atoms. Using default atom selection from
766  // atom tree routines.
767  if ( start_changed && !stop_changed && tmp.stop_atom().empty() ) {
768  tmp.stop_atom() = pose.residue( tmp.stop() ).atom_name(
770  );
771  stop_changed = true;
772  }
773 
774  if ( !start_changed && stop_changed && tmp.start_atom().empty() ) {
775  tmp.start_atom() = pose.residue( tmp.start() ).atom_name(
777  );
778  start_changed = true;
779  }
780 
781  // re-add the edge only if the edge has been changed
782  if ( start_changed && stop_changed ) {
783  ft.delete_edge( *e );
784  ft.add_edge( tmp );
785  ft_was_altered = true;
786  }
787  }
788  }
789 
790  if ( ft_was_altered ) {
791  ft.reorder( pose.fold_tree().root() );
792  pose.fold_tree( ft );
793  }
794  //std::cout << ft << std::endl;
795 
796  // special case for Remodel
797  if (basic::options::option[basic::options::OptionKeys::remodel::no_jumps]){
798  //ft.simple_tree(pose.total_residue());
799  //idealize across the loop, in case they are not -- a big problem when taking out jumps
800  // protocols:loops::Loops loops_def_for_idealization;
801  // loops_def_for_idealization.add_loop(protocols::loops::Loop(interval_.left-2,interval_.right+2, 1));
802 
806  //debug
807  //std::cout << "num cuts: " << cuts.size() << " num jumps: " << jumps.size() << std::endl;
808  //translate:
809  ObjexxFCL::FArray1D_int Fcuts( num_jumps_pre_processing);
810  ObjexxFCL::FArray2D_int Fjumps(2, num_jumps_pre_processing);
811 
812  for ( Size i = 1; i<= num_jumps_pre_processing; ++i ) { // only keeping the old jumps, wipe new ones
813  //std::cout << (int)jumps[i].first << " " << (int)jumps[i].second << std::endl;
814 
815  Fjumps(1,i) = std::min( (int)jumps[i].first, (int)jumps[i].second);
816  Fjumps(2,i) = std::max( (int)jumps[i].first, (int)jumps[i].second);
817  // DEBUG -- PRINT JUMPS AND CUTS
818  //TR.Error << " jump " << i << " : " << jumps(1,i) << " , " << jumps(2,i) << std::endl;
819  }
820  //for ( Size i = 1; i<= num_jumps_pre_processing; ++i ) {
821  //erase the new cut created
822  for (utility::vector1<Size>::iterator it=cuts.begin(), ite=cuts.end(); it != ite; it++){
823  //std::cout << *it << " vs " << new_cut << std::endl;
824  if (*(it) == new_cut){
825  //std::cout << "erasing " << *it << std::endl;
826  cuts.erase(it);
827  }
828  }
829 
830 
831  for ( Size i = 1; i<= cuts.size(); ++i ) {
832  //std::cout << "cut " << (int)cuts[i] << std::endl;
833  Fcuts(i) = (int)cuts[i];
834  // std::cout << " cut " << i << " : " << cuts(i) << std::endl;
835  }
836 
837  // 4 make the foldtree
838  FoldTree nojump_ft;
839  nojump_ft.tree_from_jumps_and_cuts( pose.total_residue(), num_jumps_pre_processing, Fjumps, Fcuts, ft.root(), true ); // true );
840  //std::cout << nojump_ft << std::endl;
841 
842  pose.fold_tree(nojump_ft);
843  //std::cout << "IDEALIZE " << interval_.left << " to " << interval_.right << std::endl;
844  //protocols::loops::set_extended_torsions_and_idealize_loops( pose, loops_def_for_idealization);
845  for (Size i = interval_.left; i <= interval_.right; i++){
847  }
848 pose.dump_pdb("test_idl.pdb");
849  }
850 
851 
852 
853  // recover psi @ left-1 and phi @ right+1 to ensure they are set correctly
854  // and not junked due to residue deletion, values set to 999.0 if not applicable
855  if ( pre_psi <= 360.0 ) {
856  pose.set_psi( interval_.left - 1, pre_psi );
857  }
858  if ( post_phi <= 360.0 ) {
859  pose.set_phi( interval_.right + 1, post_phi );
860  }
861 
862  // assume proper omega
863  Size const omega_left = ( interval_.left == 1 ) ? interval_.left : interval_.left - 1;
864  Size const omega_right = ( interval_.right == pose.n_residue() ) ? interval_.right - 1 : interval_.right;
865  trans_omega( omega_left, omega_right, pose );
866 
867  // recover old angles at junctions if requested
869 
870  // torsion angles
871  if ( left_endpoint_minus_one_omega <= 360.0 ) {
872  pose.set_omega( interval_.left - 1, left_endpoint_minus_one_omega );
873  }
874 
875  if ( left_endpoint_phi <= 360.0 ) {
876  pose.set_phi( interval_.left, left_endpoint_phi );
877  }
878 
879  if ( right_endpoint_psi <= 360.0 ) {
880  pose.set_psi( interval_.right, right_endpoint_psi );
881  }
882 
883  if ( right_endpoint_omega <= 360.0 ) {
884  pose.set_omega( interval_.right, right_endpoint_omega );
885  }
886 
887  }
888 
889  // set the desired secondary structure
890  for ( Size r = interval_.left, i = 0; r <= interval_.right; ++r, ++i ) {
891  pose.set_secstruct( r, ss_.at( i ) );
892  }
893 
894 // safety, make sure PDBInfo leaves obsolete
895  if ( pose.pdb_info().get() ) {
896  pose.pdb_info()->obsolete( true );
897  }
898 
899 
900 
901 }
902 
903 
904 /// @brief do the actual reset of intervals, positions, etc to initial state
907 }
908 
909 
910 } // namespace build
911 } // namespace forge
912 } // namespace protocols