Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
loops_main.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/loops/loops_main.cc
11 /// @brief loop building tools
12 /// @author Mike Tyka
13 /// @author Chu Wang
14 /// @author Daniel J. Mandell
15 
16 // Unit Headers
18 // AUTO-REMOVED #include <protocols/loops/LoopMover_KIC.hh>
19 // AUTO-REMOVED #include <protocols/loops/LoopMover_CCD.hh>
21 #include <protocols/loops/Loop.hh>
22 #include <protocols/loops/Loops.hh>
23 //#include <protocols/simple_moves/BackboneMover.hh>
24 // AUTO-REMOVED #include <protocols/loops/kinematic_closure/KinematicMover.hh>
25 // AUTO-REMOVED #include <protocols/moves/MonteCarlo.hh>
26 // AUTO-REMOVED #include <protocols/viewer/viewers.hh>
27 
28 
29 // Rosetta Headers
30 #include <core/types.hh>
31 // AUTO-REMOVED #include <core/chemical/ChemicalManager.hh>
33 
37 
39 // AUTO-REMOVED #include <core/chemical/ResidueTypeSet.hh>
40 #include <core/id/TorsionID.hh>
41 // AUTO-REMOVED #include <core/io/pdb/pose_io.hh>
44 #include <basic/options/option.hh>
45 // AUTO-REMOVED #include <core/pack/pack_rotamers.hh>
46 // AUTO-REMOVED #include <core/pack/rotamer_trials.hh>
47 //#include <core/pack/task/TaskFactory.hh>
48 //#include <core/pack/task/PackerTask.hh>
49 //#include <core/pack/task/operation/TaskOperations.hh>
50 #include <core/pose/Pose.hh>
51 #include <core/pose/util.hh>
52 #include <core/pose/util.tmpl.hh>
53 #include <core/scoring/Energies.hh>
54 #include <core/scoring/rms_util.hh>
56 // AUTO-REMOVED #include <core/scoring/ScoreFunction.hh>
57 // AUTO-REMOVED #include <core/scoring/ScoreFunctionFactory.hh>
59 #include <core/fragment/util.hh>
62 
65 
66 
67 #include <numeric/model_quality/rms.hh>
69 // AUTO-REMOVED #include <basic/prof.hh> // profiling
70 #include <basic/Tracer.hh> // tracer output
71 
72 //Utility Headers
73 #include <numeric/random/random.hh>
74 #include <utility/io/izstream.hh>
75 
76 #include <ObjexxFCL/string.functions.hh>
77 
78 // C++ Headers
79 #include <iostream>
80 #include <map>
81 #include <string>
82 
83 // option key includes
84 
85 #include <basic/options/keys/loops.OptionKeys.gen.hh>
86 
89 #include <utility/vector1.hh>
90 #include <ObjexxFCL/format.hh>
91 
92 //Auto Headers
94 
95 
96 
97 using namespace ObjexxFCL;
98 using namespace ObjexxFCL::fmt;
99 
100 namespace protocols {
101 namespace loops {
102 
103 ///////////////////////////////////////////////////////////////////////////////
104 using namespace core;
105 
106 basic::Tracer tt( "protocols.loops.loops_main" );
107 static numeric::random::RandomGenerator RG(31413);
108 
109 
111  std::vector< core::fragment::FragSetOP > & frag_libs
112 ) {
113  using namespace basic::options;
114  using namespace utility::file;
115  using namespace basic::options;
116  using namespace basic::options::OptionKeys;
117  using namespace core::fragment;
118 
119  utility::vector1<int> frag_sizes( option[ OptionKeys::loops::frag_sizes ] );
120  FileVectorOption frag_files( option[ OptionKeys::loops::frag_files ] );
121 
122  if( frag_sizes.size() != frag_files.size() ){
123  utility_exit_with_message( "You must specify as many fragment sizes as fragment file names " );
124  }
125 
126  for ( Size i = 1; i <= frag_sizes.size(); ++i ) {
127  Size const frag_size = Size(frag_sizes[i]);
128 
129  FragSetOP frag_lib_op ( new ConstantLengthFragSet( frag_size ) );
130  //protocols::frags::TorsionFragmentLibraryOP frag_lib_op( new protocols::frags::TorsionFragmentLibrary );
131  tt.Error << "Frag libraries debug " << frag_files[i] << " " << frag_size << std::endl;
132 
133  if ( frag_files[i] != std::string("none") ) {
134  //frag_lib_op->read_fragment_file( frag_files[i] );
135  frag_lib_op = (FragmentIO().read_data( frag_files[i] ));
136  }
137  frag_libs.push_back(frag_lib_op);
138  }
139 
140  Size prev_size(10000);
141  FragSetOP prev_lib_op(0);
142 
143  // Loop over the temporary map to generate missing/noninitialized fragment
144  // libraries
145  for ( std::vector< FragSetOP >::const_iterator
146  it = frag_libs.begin(),
147  it_end = frag_libs.end();
148  it != it_end; it++
149  ) {
150  Size const frag_size( (*it)->max_frag_length() );
151  Size const n_frags( (*it)->size() );
152 
153  if ( frag_size > prev_size ) {
154  //std::cerr << frag_size << " " << prev_size << std::endl;
155  std::string msg;
156  msg += " frag_size = " + string_of( frag_size );
157  msg += " prev_size = " + string_of( prev_size );
158  msg += "\nFragment size must be given in order !!\n";
159  utility_exit_with_message( msg );
160  }
161 
162  if ( (n_frags == 0) && prev_lib_op && (prev_lib_op->size() != 0) ) {
163  tt.Info << "Set up " << frag_size << "-mer library from " << prev_size << "-mer library" << std::endl;
164 
165  chop_fragments( *prev_lib_op, **it );
166  }
167  prev_size = frag_size;
168  prev_lib_op = *it;
169  }
170 
171 
172  // Steal fragments as requested
173 
174  if( option[ OptionKeys::loops::stealfrags ].user() ){
175  utility::vector1< FileName > pdbfiles = option[ OptionKeys::loops::stealfrags ]();
176  utility::vector1< FileName >::iterator file_it = pdbfiles.begin(), file_it_end = pdbfiles.end();
177  // Loop over all the islent input files
178  for ( ; file_it != file_it_end; ++file_it ) {
179  std::string infile = *file_it;
180 
181  core::pose::Pose stealpose;
182  core::import_pose::centroid_pose_from_pdb( stealpose, infile );
183 
184  for ( std::vector< FragSetOP >::const_reverse_iterator
185  it = frag_libs.rbegin(),
186  it_end = frag_libs.rend();
187  it != it_end; it++ ) {
188  tt.Info << "Stealing fragments from " << infile << " "
189  << option[ OptionKeys::loops::stealfrags_times ]() << " times" << std::endl;
190 
191  for(int c=0; c< option[ OptionKeys::loops::stealfrags_times ](); c++ ){
192  //steal_constant_length_frag_set_from_pose ( stealpose, **it );
193  steal_frag_set_from_pose( stealpose, **it, new FragData( new BBTorsionSRFD, (*it)->max_frag_length() ) );
194  }
195  }
196  } // loop over input files
197  } // if stealfrags
198 
199  for ( std::vector< FragSetOP >::const_reverse_iterator
200  it = frag_libs.rbegin(),
201  it_end = frag_libs.rend();
202  it != it_end; it++ ) {
203 
204  Size const frag_size( (*it)->max_frag_length() );
205  Size const n_frags( (*it)->size() );
206  tt.Info << "Fragment libraries: " << frag_size << " " << n_frags
207  << std::endl;
208  }
209 }
210 
211 
214 ) {
215  using std::vector;
216  using utility::vector1;
217 
218  std::vector< core::fragment::FragSetOP > temp_libs;
219  read_loop_fragments( temp_libs );
220  frag_libs.resize( temp_libs.size() );
221  for ( Size i = 1; i <= temp_libs.size(); ++i ) {
222  frag_libs[i] = temp_libs[i-1];
223  }
224 }
225 
226 
227 //////////////////////////////////////////////////////////////////////////////////////////
228 /// @details for each loop defined, add a fixed jump from the residue before loop_start and
229 /// the residue after the loop_end. The cutpoint is from loop_cut. Support terminal loops, i.e.,
230 /// starting at residue 1 or ending at total_residue
231 ////////////////////////////////////////////////////////////////////////////////////////////
232 void
234  core::pose::Pose const & pose,
235  Loops const & loops,
237  bool terminal_cutpoint
238 )
239 {
240  using namespace kinematics;
241 
242  f.clear();
243 
244  // "symmetry-safe" version
246 
247  // nres points to last protein residue;
248  Size totres = f_in.nres();
249  Size nres = totres;
250  if ( nres != pose.total_residue() ) nres--; // only true if pose is symm. ... asymm foldtree is then rooted on VRT
251 
252  // following residues (e.g. ligands) will be attached by jumps
253  while( !pose.residue(nres).is_protein() ) nres -= 1;
254 
255  Loops tmp_loops = loops;
256  tmp_loops.sequential_order();
257 
258  Size jump_num = 0;
259  Size prev_interchain_jump = 0;
260  for( Loops::const_iterator it=tmp_loops.begin(), it_end=tmp_loops.end(),
261  it_next; it != it_end; ++it ) {
262  it_next = it;
263  it_next++;
264 
265  bool is_lower_term = pose.residue( it->start() ).is_lower_terminus();
266  bool is_upper_term = pose.residue( it->stop() ).is_upper_terminus();
267 
268  Size const jump_start =
269  ( is_lower_term ) ? it->start() : it->start() - 1;
270  Size const jump_stop =
271  ( is_upper_term ) ? it->stop() : it->stop() + 1;
272  Size const jump_cut = it->cut();
273  Size const jump_next_start =
274  ( it_next == it_end ) ? nres : it_next->start()-1;
275 
276 
277  if( it->start() == 1 ){
278  if ( ! terminal_cutpoint ) {
279  f.add_edge( jump_start, jump_stop, Edge::PEPTIDE ); // DJM: replacing with following three lines
280  }
281  else {
282  jump_num++;
283  f.add_edge( jump_start, jump_stop, jump_num );
284  f.add_edge( jump_start, jump_cut, Edge::PEPTIDE );
285  f.add_edge( jump_cut+1, jump_stop, Edge::PEPTIDE );
286  }
287  f.add_edge( jump_stop, jump_next_start, Edge::PEPTIDE );
288  continue;
289  } else if( it->stop() == nres ) {
290  if ( ! terminal_cutpoint ) {
291  f.add_edge( jump_start, jump_stop, Edge::PEPTIDE ); // DJM: replacing with following three lines
292  }
293  else {
294  jump_num++;
295  f.add_edge( jump_start, jump_stop, jump_num );
296  f.add_edge( jump_start, jump_cut, Edge::PEPTIDE );
297  f.add_edge( jump_cut+1, jump_stop, Edge::PEPTIDE );
298  }
299  continue;
300  } else if ( is_lower_term ) { // internal chain break
301  // jump from the previous
302  if ( prev_interchain_jump > 0 ) {
303  jump_num++;
304  f.add_edge( prev_interchain_jump, jump_stop, jump_num );
305  } else {
306  jump_num++;
307  f.add_edge( jump_start-1, jump_stop, jump_num );
308  }
309  f.add_edge( jump_start, jump_stop, Edge::PEPTIDE );
310  f.add_edge( jump_stop, jump_next_start, Edge::PEPTIDE );
311  prev_interchain_jump = 0; // reset this
312  continue;
313  } else if ( is_upper_term ) { // internal chain break
314  // if next chain begins with a loop jump must be from before this loop to after next loop
315  // we'll handle the jump when we get there
316  if ( it_next != it_end && it_next->start() == it->stop()+1) {
317  prev_interchain_jump = jump_start;
318  } else {
319  jump_num++;
320  f.add_edge( jump_start, jump_stop+1, jump_num );
321  f.add_edge( jump_stop+1, it_next->start()-1, Edge::PEPTIDE ); // JEC: also need to make a peptide edge to start the next chain (otherwise gets dropped)
322  }
323  f.add_edge( jump_start, jump_stop, Edge::PEPTIDE );
324  continue;
325  }
326 
327 
328  jump_num++;
329  f.add_edge( jump_start, jump_stop, jump_num );
330  f.add_edge( jump_start, jump_cut, Edge::PEPTIDE );
331  f.add_edge( jump_cut+1, jump_stop, Edge::PEPTIDE );
332  // if ( jump_stop < jump_next_start )
333  f.add_edge( jump_stop, jump_next_start, Edge::PEPTIDE );
334  }
335 
336  if ( tmp_loops.size() > 0 ) {
337  Size const first_start =
338  ( tmp_loops.begin()->start() == 1 ) ? tmp_loops.begin()->start() : tmp_loops.begin()->start() - 1;
339  // if ( first_start != 1 )
340  f.add_edge( 1, first_start, Edge::PEPTIDE );
341 
342  // reorder
343  Size root;
344  if( tmp_loops.begin()->start() == 1 &&
345  tmp_loops.begin()->stop() != nres )
346  root = tmp_loops.begin()->stop()+1;
347  else root = 1;
348 
349  f.reorder(root);
350  }
351 
352  // Attach remaining (non-protein) residues by jumps to the tree root.
353  Size jump_anchor = f.root();
354  while( nres < totres ) {
355  nres += 1;
356  f.add_edge( jump_anchor, nres, f.num_jump()+1 );
357  }
358 
359  if ( pose.residue( pose.fold_tree().root() ).aa() == core::chemical::aa_vrt ) {
360  // special case for fold trees rooted on a VRT
361  // symmetry-safe
362  if ( f_in.nres() != pose.total_residue() ) {
363  f.reorder( f_in.nres() );
364  } else {
365  f.reorder( pose.fold_tree().root() );
366  }
367  }
368 
369  // symmetrize the fold tree (which is over asymm unit)
371 }
372 
373 
374 //////////////////////////////////////////////////////////////////////////////////
375 /// @details Make a single fold tree that brackets the loop
377  core::pose::Pose & pose,
378  Loop const & loop
379 )
380 {
381 
382  using namespace kinematics;
383 
384  //setup fold tree for this loop
385  FoldTree f;
386 
387  // "symmetry-safe" version
389 
390  // nres points to last protein residue;
391  Size totres = f_in.nres();
392  Size nres = totres;
393  if ( nres != pose.total_residue() ) nres--;
394  // only true if pose is symm. ... asymm foldtree is then rooted on VRT
395 
396  // following residues (e.g. ligands,VRTs) will be attached by jumps
397  while( !pose.residue(nres).is_protein() ) nres -= 1;
398 
399  // if the fold tree is rooted with a jump from a VRT res, maintain that jump
400  // (i believe) we only need to check if root is vrt (and not for jump)
401  // since vrt reses can't form peptide bonds
402  // the fold tree ensures the absolute coordinates of all nonloop residues
403  // stays unchanged
404  if ( pose.residue( pose.fold_tree().root() ).aa() == core::chemical::aa_vrt ) {
405  int newroot = f_in.root();
406 
407  if( loop.start() == 1 ) {
408  f.add_edge( 1, loop.stop() + 1, Edge::PEPTIDE );
409  f.add_edge( loop.stop() + 1, nres, Edge::PEPTIDE );
410  f.add_edge( loop.stop() + 1, newroot, 1 );
411  } else if ( loop.stop() >= nres) {
412  f.add_edge( 1, nres, Edge::PEPTIDE ); //simple fold tree
413  f.add_edge( 1, newroot, 1 );
414  } else if ( pose.residue( loop.start() ).is_lower_terminus() ) {
415  if (loop.start()-1 != 1)
416  f.add_edge( 1, loop.start() - 1, Edge::PEPTIDE );
417  f.add_edge( loop.start(), nres, Edge::PEPTIDE );
418  f.add_edge( nres, newroot, 1 );
419  f.add_edge( 1, nres, 2 );
420  } else if ( pose.residue( loop.stop() ).is_upper_terminus() ) {
421  f.add_edge( 1, loop.stop(), Edge::PEPTIDE );
422  if (loop.stop() + 1 != nres)
423  f.add_edge( loop.stop() + 1, nres, Edge::PEPTIDE );
424  f.add_edge( 1, newroot, 1 );
425  f.add_edge( 1, nres, 2 );
426  } else {
427  Size jumppoint1 = loop.start() - 2;
428  Size jumppoint2 = loop.stop() + 2;
429  if( jumppoint1 < 1 ) jumppoint1 = 1;
430  if( jumppoint2 > nres) jumppoint2 = nres;
431 
432  if (jumppoint1 != 1)
433  f.add_edge( 1, jumppoint1, Edge::PEPTIDE );
434  f.add_edge( jumppoint1, loop.cut(), Edge::PEPTIDE );
435  f.add_edge( loop.cut() + 1, jumppoint2, Edge::PEPTIDE );
436  if (jumppoint2 != nres)
437  f.add_edge( jumppoint2, nres, Edge::PEPTIDE );
438  f.add_edge( 1, newroot, 1 );
439  f.add_edge( jumppoint1, jumppoint2, 2 );
440  }
441 
442  if( f.reorder( newroot ) == false ){
443  tt.Error << "ERROR During reordering of fold tree - am ignoring this LOOP ! " << std::endl;
444  tt.Error << "Cutpoint chosen " << loop.cut() << std::endl;
445  return; // continuing leads to a segfault - instead ignore this loop !
446  }
447 
448  } else {
449  int newroot = (loop.start() == 1) ? nres : 1;
450  if( loop.start() == 1 || loop.stop() == nres ) {
451  f.add_edge( 1, nres, Edge::PEPTIDE ); //simple fold tree
452  } else if ( pose.residue( loop.start() ).is_lower_terminus() ) {
453 
454  // multi-chain Pose n-term ext
455  if ( loop.start() > 1 ) { // safety, handled above
456  f.add_edge( 1, loop.start() - 1, Edge::PEPTIDE );
457  f.add_edge( loop.start(), nres, Edge::PEPTIDE );
458  f.add_edge( 1, nres, 1 );
459  } else {
460  f.add_edge( 1, nres, Edge::PEPTIDE ); // simple fold tree
461  }
462 
463  } else if ( pose.residue( loop.stop() ).is_upper_terminus() ) {
464 
465  // multi-chain Pose c-term ext
466  if ( loop.stop() < nres ) { // safety, handled above
467  f.add_edge( 1, loop.stop(), Edge::PEPTIDE );
468  f.add_edge( loop.stop() + 1, nres, Edge::PEPTIDE );
469  f.add_edge( 1, nres, 1 );
470  } else {
471  f.add_edge( 1, nres, Edge::PEPTIDE ); // simple fold tree
472  }
473 
474  } else {
475  Size jumppoint1 = loop.start() - 2;
476  Size jumppoint2 = loop.stop() + 2;
477  if( jumppoint1 < 1 ) jumppoint1 = 1;
478  if( jumppoint2 > nres) jumppoint2 = nres;
479 
480  f.add_edge( 1, jumppoint1, Edge::PEPTIDE ); //one jump fold tree
481  f.add_edge( jumppoint1, loop.cut(), Edge::PEPTIDE );
482  f.add_edge( loop.cut() + 1, jumppoint2, Edge::PEPTIDE );
483  f.add_edge( jumppoint2, nres, Edge::PEPTIDE );
484  f.add_edge( jumppoint1, jumppoint2, 1 );
485  }
486 
487  if( f.reorder( newroot ) == false ){
488  tt.Error << "ERROR During reordering of fold tree - am ignoring this LOOP ! " << std::endl;
489  tt.Error << "Cutpoint chosen " << loop.cut() << std::endl;
490  return; // continuing leads to a segfault - instead ignore this loop !
491  }
492  }
493 
494  // Attach remaining (non-protein) residues by jumps to the tree root.
495  Size jump_anchor = f.root();
496  while( nres < totres ) {
497  nres += 1;
498 
499  // if we're rooted on a VRT atom dont add a jump
500  if ( nres != (Size)f.root() )
501  f.add_edge( jump_anchor, nres, f.num_jump()+1 );
502  }
503 
504  tt.Warning << "Pose fold tree " << f << std::endl;
505  //pose.fold_tree( f );
506 
507  // "symmetry-safe" version
509 }
510 
511 
512 
513 
514 /// @details Slide a loop cutpoint to a (potentially) new position
515 /// @note Updates the pose's foldtree, either moving or adding a loop cutpoint
516 /// @note Updates CUTPOINT_UPPER and CUTPOINT_LOWER variant status of residues in loop to match new cutpoint location
517 void
519  Size const new_cutpoint,
520  pose::Pose & pose,
521  Size const loop_begin,
522  Size const loop_end
523  )
524 {
525  using namespace chemical;
526  kinematics::FoldTree f( pose.fold_tree() );
527  if ( f.is_cutpoint( new_cutpoint ) ) return;
528 
529  // find the current cutpoint
530  Size cut(0);
531  for ( Size i=loop_begin-1; i<= loop_end; ++i ) {
532  if ( f.is_cutpoint( i ) ) {
533  if ( cut ) utility_exit_with_message( "multiple cutpoints in single loop!" );
534  cut = i;
535  }
536  // remove cutpoint variants if they're present
539  }
540  if ( !cut ) {
541  tt.Warning << "set_loop_cutpoint_in_pose_fold_tree: no cutpoint in loop, so adding new jump to foldtree between " <<
542  loop_begin-1 << " and " << loop_end +1 << " with cut at " << new_cutpoint << std::endl;
543  f.new_jump( loop_begin-1, loop_end+1, new_cutpoint );
544  } else {
545  f.slide_cutpoint( cut, new_cutpoint );
546  }
547  pose.fold_tree( f );
548 
551 
552 }
553 
554 
555 
556 //////////////////////////////////////////////////////////////////////////////////
557 /// @details Remove cutpoint variants
559  core::pose::Pose & pose,
560  bool force
561 )
562 {
563  using namespace core::chemical;
564  bool pose_changed( false );
565  pose::Pose init_pose = pose;
566  if( force ){
567  for (core::Size ir=1; ir<=pose.total_residue() ; ++ir) {
568  if ( pose.residue(ir).has_variant_type(CUTPOINT_LOWER) ) {
569  pose_changed = true;
571  }
572  if ( pose.residue(ir).has_variant_type(CUTPOINT_UPPER) ) {
574  pose_changed = true;
575  }
576  }
577  }else{
578 
579  for (int i=1; i<=pose.fold_tree().num_cutpoint() ; ++i) {
580  int cutpoint = pose.fold_tree().cutpoint(i);
581  if ( pose.residue(cutpoint).has_variant_type(CUTPOINT_LOWER) ) {
582  pose_changed = true;
584  }
585  if ( pose.residue(cutpoint+1).has_variant_type(CUTPOINT_UPPER) ) {
587  pose_changed = true;
588  }
589  }
590 
591  //WTF ?
592  if ( pose.residue(1).has_variant_type(CUTPOINT_LOWER) ) {
593  pose_changed = true;
595  }
596  if ( pose.residue(2).has_variant_type(CUTPOINT_UPPER) ) {
598  pose_changed = true;
599  }
600  if ( pose.residue(pose.total_residue()-1).has_variant_type(CUTPOINT_LOWER) ) {
601  pose_changed = true;
603  }
604  if ( pose.residue(pose.total_residue()).has_variant_type(CUTPOINT_UPPER) ) {
606  pose_changed = true;
607  }
608  }
609 
610  //I am pretty sure this assignment was a bug, and it was meant to be an equality operator - 4/18/11 SML
611  //if ( pose_changed = true ) pose.constraint_set( init_pose.constraint_set()->remapped_clone( init_pose, pose ) );
612  if ( pose_changed == true ) pose.constraint_set( init_pose.constraint_set()->remapped_clone( init_pose, pose ) );
613 }
614 
615 
616 //////////////////////////////////////////////////////////////////////////////////
617 /// @details Remove cutpoint variants
619  core::pose::Pose & pose
620 )
621 {
622  pose::Pose init_pose = pose;
623  using namespace core::chemical;
624  bool pose_changed( false );
625  for ( int i=1; i <= pose.fold_tree().num_cutpoint() ; ++i ) {
626  int cutpoint = pose.fold_tree().cutpoint( i );
627  bool added_cutpoint_variant = false;
628 
629  //flo may 09: cutpoint and terminus variant types are currently incompatible, so check for presence
630  if ( pose.residue( cutpoint ).is_protein() && !( pose.residue( cutpoint ).is_upper_terminus() ) ) {
632  added_cutpoint_variant = true;
633  }
634  if ( pose.residue( cutpoint+1 ).is_protein() && !( pose.residue( cutpoint+1 ).is_lower_terminus() ) ) {
636  added_cutpoint_variant = true;
637  }
638 
639  if ( added_cutpoint_variant ) {
640  tt.Info << "Added cutpoint variants: RES: " << cutpoint << std::endl;
641  }
642  pose_changed = pose_changed || added_cutpoint_variant;
643  }
644  if ( pose_changed ) pose.constraint_set( init_pose.constraint_set()->remapped_clone( init_pose, pose ) );
645 }
646 
647 
648 
649 //////////////////////////////////////////////////////////////////////////////////
650 /// @details Add cutpoint variant around a sinlge cutpoint (defined by loop)
652  core::pose::Pose & pose,
653  const Loop &loop
654 )
655 {
656  using namespace core::chemical;
657  pose::Pose init_pose = pose;
658  bool changed( false );
659  if ( !pose.residue(loop.cut()).has_variant_type(CUTPOINT_LOWER) ) {
661  changed=true;
662  }
663  if ( !pose.residue(loop.cut()+1).has_variant_type(CUTPOINT_UPPER) ) {
665  changed=true;
666  }
667  if ( changed ) pose.constraint_set( init_pose.constraint_set()->remapped_clone( init_pose, pose ) );
668 }
669 
670 
671 
672 
673 //////////////////////////////////////////////////////////////////////////////////////
674 /// @details omega backbone torsion is always fixed. phi/psi backbone torsions within
675 /// the loop region are flexible. Depending on whether -fix_natsc flag, sidechain DOFs
676 /// of loop residues and/or their neighboring residues in the template will be set as
677 /// movable. Default neighbors are 10A CB dist from loop residues; neighbor_dist can
678 /// be used to further filter the neighbors. This is a wrapper function which determine
679 /// moveable sidechains and then call actual loop_set_move_map function to set up move
680 /// map properly
681 //////////////////////////////////////////////////////////////////////////////////////
682 void
684  pose::Pose & pose,
685  Loops const & loops,
686  bool const fix_template_sc,
688  Real neighbor_dist
689 )
690 {
691  using namespace core::id;
693 
694  utility::vector1<bool> allow_sc_move( pose.total_residue(), false);
695  select_loop_residues( pose, loops, !fix_template_sc, allow_sc_move, neighbor_dist);
696  loops_set_move_map( loops, allow_sc_move,mm);
697 
698  //fpd symmetric version
699  if ( core::pose::symmetry::is_symmetric( pose ) ) {
701  }
702 }
703 
704 //////////////////////////////////////////////////////////////////////////////////////
705 /// @details omega backbone torsion is always fixed. phi/psi backbone torsions within
706 /// the loop region are flexible. Depending on whether -fix_natsc flag, sidechain DOFs
707 /// of loop residues and/or their neighboring residues in the template will be set as
708 /// movable.
709 //////////////////////////////////////////////////////////////////////////////////////
710 void
712  Loops const & loops,
713  utility::vector1<bool> const & allow_sc_move,
715 )
716 {
717  using namespace core::id;
718  using namespace basic::options;
719  using namespace basic::options::OptionKeys;
720 
721  bool const allow_omega_move = basic::options::option[ OptionKeys::loops::allow_omega_move ].user();
722  bool const allow_takeoff_torsion_move = basic::options::option[ OptionKeys::loops::allow_takeoff_torsion_move ].user();
723 
724  // allow chi to move
725  mm.set_bb( false );
726  mm.set_chi( false );
727  mm.set_jump( false );
728  // allow phi/psi in loops to move
729  for( Loops::const_iterator it=loops.begin(), it_end=loops.end();
730  it != it_end; ++it ) {
731 
732  for( Size i=it->start(); i<=it->stop(); ++i ) {
733  mm.set_bb(i, true);
734  if ( !allow_omega_move ) mm.set(TorsionID(i,BB,3), false); // omega is fixed by default
735  mm.set_chi(i, true); // chi of loop residues
736  }
737 
738  if ( allow_takeoff_torsion_move ) {
739  mm.set( TorsionID( it->start()-1, BB, 2 ), true );
740  if ( allow_omega_move ) mm.set( TorsionID( it->start()-1, BB, 3 ), true );
741  mm.set( TorsionID( it->stop()+1, BB, 1 ), true );
742  }
743 
744  }
745  // set chi move map based on the input allow_sc array, which is filled based on fix_natsc info
746  for ( Size i = 1; i <= allow_sc_move.size(); ++i ) {
747  mm.set_chi(i, allow_sc_move[i] );
748  }
749  // chu in case we have ligand attached in fold tree and they need to move. Assuming that
750  // loop jumps come first followed by lig jumps.
751  if ( basic::options::option[ OptionKeys::loops::allow_lig_move ]() ){
752  mm.set_jump( true );
753  for ( Size i = 1; i <= loops.num_loop(); ++i ) {
754  mm.set_jump( i, false );
755  }
756  }
757 
758 
759 }
760 
761 //////////////////////////////////////////////////////////////////////////////////////
762 /// @details omega backbone torsion is always fixed. phi/psi backbone torsions within
763 /// the loop region are flexible. Depending on whether -fix_natsc flag, sidechain DOFs
764 /// of loop residues and/or their neighboring residues in the template will be set as
765 /// movable.
766 //////////////////////////////////////////////////////////////////////////////////////
767 void
769  Loop const & loop,
771 )
772 {
773  using namespace core::id;
774  using namespace basic::options;
775  using namespace basic::options::OptionKeys;
776 
777  bool const allow_omega_move = basic::options::option[ OptionKeys::loops::allow_omega_move ].user();
778  bool const allow_takeoff_torsion_move = basic::options::option[ OptionKeys::loops::allow_takeoff_torsion_move ].user();
779 
780  mm.set_bb( false );
781  mm.set_chi( false );
782  mm.set_jump( false );
783  // allow phi/psi in loops to move
784  for( Size i=loop.start(); i<=loop.stop(); ++i ) {
785  mm.set_bb(i, true);
786  if ( !allow_omega_move ) mm.set( TorsionID( i, BB, 3 ), false ); // omega is fixed
787  mm.set_chi(i, true); // chi of loop residues
788  }
789 
790  if ( allow_takeoff_torsion_move ) {
791  mm.set( TorsionID( loop.start()-1, BB, 2 ), true );
792  if ( allow_omega_move ) mm.set( TorsionID( loop.start()-1, BB, 3 ), true );
793  mm.set( TorsionID( loop.stop()+1, BB, 1 ), true );
794  }
795 
796  // chu in case we have ligand attached in fold tree and they need to move. Assuming that
797  // loop jumps come first followed by lig jumps.
798  if (basic::options::option[ OptionKeys::loops::allow_lig_move ].user() ){
799  mm.set_jump( true );
800  mm.set_jump( 1, false ); //jump for the single loop
801  }
802 
803 
804 }
805 
806 //////////////////////////////////////////////////////////////////////////////////////
807 ///// @details When building loops on a homology model, the qualities of the loop stems are
808 ///// hard to control. Implementing small/shear/ccd movers to them may be too much. One
809 ///// may just want to minimize them when the loop refinement protocl is doing minimization.
810 ///// This is the function to add these extra residues to the movemap. --JQX
811 ////////////////////////////////////////////////////////////////////////////////////////
812 void
814  Loops const & loops,
816  core::Size flank_size
817 ){
818 
819  for( Loops::const_iterator it=loops.begin(), it_end=loops.end(); it != it_end; ++it ) {
820 
821  for(Size i=(it->start()-flank_size); i<=(it->start()-1); i++){
822  mm.set_bb(i, true);
823  }
824 
825  for(Size i=(it->stop()+1); i<=(it->stop()+flank_size); i++){
826  mm.set_bb(i, true);
827  }
828 
829  }
830 
831 }
832 
833 
834 ///////////////////////////////////////////////////////////////////////////////////////////////////
835 /// @details take a pose and loop defintions, close each loop separately by the CCD algorithm. Currently
836 /// hard-code all parameters related to CCD and then call fast_ccd_loop_closure for closing this single
837 /// loop
838 ///////////////////////////////////////////////////////////////////////////////////////////////////
839 void
841  pose::Pose & pose,
842  Loops const & loops,
843  kinematics::MoveMap const& mm
844 )
845 {
846  // param for ccd_closure
847  int const ccd_cycles = { 100 }; // num of cycles of ccd_moves
848  Real const ccd_tol = { 0.01 }; // criterion for a closed loop
849  bool const rama_check = { true };
850  Real const max_rama_score_increase = { 2.0 }; // dummy number when rama_check is false
851  Real const max_total_delta_helix = { 10.0 }; // max overall angle changes for a helical residue
852  Real const max_total_delta_strand = { 50.0 }; // ... for a residue in strand
853  Real const max_total_delta_loop = { 75.0 }; // ... for a residue in loop
854  // output for ccd_closure
855  Real forward_deviation, backward_deviation; // actually loop closure msd, both dirs
856  Real torsion_delta, rama_delta; // actually torsion and rama score changes, averaged by loop_size
857 
858  for( Loops::const_iterator it=loops.begin(), it_end=loops.end();
859  it != it_end; ++it ) {
860  Size const loop_begin = it->start();
861  Size const loop_end = it->stop();
862  Size const cutpoint = it->cut();
863  // ccd close this loop
864  loop_closure::ccd::fast_ccd_loop_closure( pose, mm, loop_begin, loop_end, cutpoint, ccd_cycles,
865  ccd_tol, rama_check, max_rama_score_increase, max_total_delta_helix,
866  max_total_delta_strand, max_total_delta_loop, forward_deviation,
867  backward_deviation, torsion_delta, rama_delta );
868  }
869 }
870 ////////////////////////////////////////////////////////////////////////////////////////////////////////
871 /// @details use TenANeighborGraph. As input, residue_positions[i] is true for residues to be counted.
872 /// As output, residue_position[i] is true for all neighbor residues including orginal input residues.
873 /// The function is used to find all neighboring residues of the loop residues in case they need to be
874 /// repacked or minimized in fullatom refinement.
876  pose::Pose const & pose,
877  utility::vector1<bool> & residue_positions
878 )
879 {
880  //make a local copy first because we will change content in residue_positions
881  utility::vector1<bool> local_residue_positions = residue_positions;
882  core::scoring::TenANeighborGraph const & tenA_neighbor_graph( pose.energies().tenA_neighbor_graph() );
883  for ( Size i=1; i <= local_residue_positions.size(); ++i ) {
884  if ( ! local_residue_positions[i] ) continue;
885  core::graph::Node const * current_node( tenA_neighbor_graph.get_node(i)); // find neighbors for this node
886  for ( core::graph::Node::EdgeListConstIter it = current_node->const_edge_list_begin();
887  it != current_node->const_edge_list_end(); ++it ) {
888  Size pos = (*it)->get_other_ind(i);
889  if (pose.residue(pos).type().name() == "CYD") {
890  residue_positions[ pos ] = false;
891  }
892  else {
893  residue_positions[ pos ] = true;
894  }
895  }
896  }
897 }
898 /////////////////////////////////////////////////////////////////////////////
899 ///@details use 10A CB distance cutoff as neighboring residue defintion. The function
900 ///is used for conveniently setting up sidechain movable residues in loop modeling.
901 ///The 10A residue set is further reduced if neighbor_dist < 10.0
902 /////////////////////////////////////////////////////////////////////////////////
904  pose::Pose const & pose,
905  Loops const & loops,
906  bool const include_neighbors,
908  Real neighbor_dist
909 )
910 {
911  for( Loops::const_iterator it=loops.begin(), it_end=loops.end();
912  it != it_end; ++it ) {
913  for( Size i=it->start(); i<=it->stop(); ++i ) {
914  if (pose.residue(i).type().name() == "CYD") {
915  map[i] = false;
916  }
917  else {
918  map[i] = true;
919  }
920  }
921  }
922 
923  if ( include_neighbors) get_tenA_neighbor_residues( pose, map );
924  // if the neighbor_dist is less than 10A, filter the 10A neighbors to that distance
925  if ( neighbor_dist < 10.0 ) {
926  filter_loop_neighbors_by_distance( pose, map, loops, neighbor_dist );
927  }
928  return;
929 }
930 
931 /////////////////////////////////////////////////////////////////////////////
932 ///@details for one loop only
934  pose::Pose const & pose,
935  Loop const & loop,
936  bool const include_neighbors,
938  Real neighbor_dist
939 )
940 {
941  Loops loops;
942  loops.add_loop( loop );
943  select_loop_residues( pose, loops, include_neighbors, map, neighbor_dist );
944  return;
945 }
946 
947 //////////////////////////////////////////////////////////////////////////////////////
948 ///@details neighbors contains the set of potential neighbors to the loop residues
949 ///given in loops. This set is reduced to only contain neighbors within dist_cutoff
950 ///of any residue in loops.
951 //////////////////////////////////////////////////////////////////////////////////////
953  pose::Pose const & pose,
955  Loops const & loops,
956  Real & dist_cutoff
957 )
958 {
959  //Size orig_neighbs=0, new_neighbs=0;
960  for( Size i=1; i<=map.size(); ++i ) {
961  if ( map[i] == false ) continue; // this residue already isn't a neighbor
962  //++orig_neighbs;
963  map[i] = false;
964  for( Loops::const_iterator it=loops.begin(), it_end=loops.end(); it != it_end; ++it ) {
965  for (Size j=it->start(); j<=it->stop(); ++j ) {
966  // Get the atom vectors for loop and scaffold CB, or CA if GLY
967  numeric::xyzVector< Real > scaffold_res_vec;
968  numeric::xyzVector< Real > loop_res_vec;
969  scaffold_res_vec = pose.residue( i ).xyz( pose.residue( i ).nbr_atom() );
970  loop_res_vec = pose.residue( j ).xyz( pose.residue( j ).nbr_atom() );
971  // only keep as neighbor if dist within cutoff
972  Real dist = scaffold_res_vec.distance( loop_res_vec );
973  if ( dist <= dist_cutoff ) {
974  map[i] = true;
975  }
976  }
977  }
978  }
979 
980  // some debug code to see the effect of this code, requires uncommenting orig_neighbs and new_neighbs above
981  //for( Size z=1; z<=map.size(); ++z ) {
982  // if( map[z]==1 ) ++new_neighbs;
983  //}
984  //tt << "Number of neighbors reduced from " << orig_neighbs << " to " << new_neighbs << std::endl;
985 
986 }
987 
988 ///////////////////////////////////////////////////////////////////////////////////////////
989 // if the pose sequence extends beyond the sequence from the mapping, this will extend the mapping
990 // semi-special-case-HACK, logic needs clarifying
991 //
992 void
994  pose::Pose const & pose,
995  id::SequenceMapping & mapping,
996  std::string & source_seq,
997  std::string & target_seq
998 )
999 {
1000  using namespace conformation;
1001 
1002  runtime_assert( mapping.size1() == source_seq.size() && mapping.size2() == target_seq.size());
1003 
1004  // may not represent the entire pose source sequence
1005  std::string const pose_seq( pose.sequence() );
1006 
1007  if ( source_seq != pose_seq ) {
1008  /// source sequence from align file does not cover entire pdb file sequence
1009 
1010  if ( pose_seq.find( source_seq ) == std::string::npos ) {
1011  tt << "src_seq: " << source_seq << std::endl << "pose_seq: " << pose_seq << std::endl;
1012  utility_exit_with_message( "alignfile source sequence not contained in pose sequence" );
1013  }
1014  Size const offset( pose_seq.find( source_seq ) );
1015 
1016  std::string source_nterm_seq, target_nterm_seq;
1017  for ( Size i=1; i<= offset; ++i ) {
1018  // this is a residue in the input pdb that's not accounted for in the alignment
1019  // if its protein, unalign it
1020  // if its dna, align it
1021  Residue const & rsd( pose.residue( i ) );
1022 
1023  mapping.insert_source_residue( i ); // remains unaligned, ie mapping[i] == 0
1024  source_nterm_seq += rsd.name1();
1025 
1026  bool const align_this_residue( !rsd.is_protein() );
1027 
1028  if ( align_this_residue ) {
1029  target_nterm_seq += rsd.name1();
1030  Size const target_pos( target_nterm_seq.size() );
1031  mapping.insert_target_residue( target_pos );
1032  mapping[i] = target_pos;
1033  }
1034  }
1035 
1036  source_seq = source_nterm_seq + source_seq;
1037  target_seq = target_nterm_seq + target_seq;
1038 
1039  runtime_assert( pose_seq.find( source_seq ) == 0 );
1040 
1041  while( source_seq.size() < pose_seq.size() ) {
1042  runtime_assert( mapping.size1() == source_seq.size() && mapping.size2() == target_seq.size());
1043 
1044  Size const pos( source_seq.size() + 1 );
1045  Residue const & rsd( pose.residue( pos ) );
1046 
1047  char const n1( rsd.name1() );
1048  source_seq += n1;
1049  mapping.push_back( 0 );
1050 
1051  bool const align_this_residue( !rsd.is_protein() );
1052  if ( align_this_residue ) {
1053  target_seq += n1;
1054  mapping.insert_target_residue( target_seq.size() );
1055  mapping[pos] = target_seq.size();
1056  }
1057  }
1058 
1059  runtime_assert( pose_seq == source_seq );
1060  }
1061 
1062 }
1063 
1064 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1065 ///
1066 /// what can we assume about the starting fold_tree??
1067 ///
1068 
1069 void
1071  pose::Pose & pose,
1072  std::string const & target_seq,
1073  id::SequenceMapping const & start_mapping
1074 )
1075 {
1076  using namespace conformation;
1077  using namespace chemical;
1078 
1079  id::SequenceMapping mapping( start_mapping );
1080  runtime_assert( mapping.size1() == pose.total_residue() && mapping.size2() == target_seq.size() );
1081 
1082  tt << "apply_sequence_mapping: start fold tree: " << pose.fold_tree() << std::endl;
1083 
1084  // try skipping this hacky rebuild of a new tree
1085  if ( false && pose.num_jump() ) { // check the current fold_tree
1086  Size const num_jump( pose.num_jump() );
1087  Size const nres( pose.total_residue() );
1088 
1089  Size segment(1);
1090  utility::vector1< int > seg_anchor( num_jump+1, 0 ), seg_end;
1091  for ( Size i=1; i<= nres; ++i ) {
1092  if ( mapping[i] ) {
1093  if ( seg_anchor[ segment ] == 0 ) {
1094  seg_anchor[ segment ] = i;
1095  }
1096  }
1097  if ( i < nres && pose.fold_tree().is_cutpoint( i ) ) {
1098  seg_end.push_back( i );
1099  ++segment;
1100  }
1101  }
1102 
1103  FArray2D_int jumps( 2, num_jump );
1104  FArray1D_int cuts ( num_jump );
1105  for ( Size i=1; i<= num_jump; ++i ) {
1106  jumps(1,i) = seg_anchor[1];
1107  jumps(2,i) = seg_anchor[i+1];
1108  cuts(i) = seg_end[i];
1109  }
1110 
1112  bool valid_tree = f.tree_from_jumps_and_cuts( nres, num_jump, jumps, cuts );
1113  runtime_assert( valid_tree );
1114  f.reorder( jumps(1,1) );
1115  tt << "oldtree: " << pose.fold_tree() << std::endl << "newtree: " << f << std::endl;
1116 
1117  pose.fold_tree( f );
1118  }
1119 
1120 
1121 
1122  tt << "start mapping: " << std::endl;
1123  mapping.show();
1124 
1125 
1126  // alternate approach:
1127 
1128  // first delete all unaligned residues
1129  while ( !mapping.all_aligned() ) {
1130  for ( Size i=1; i<= mapping.size1(); ++i ) {
1131  if ( !mapping[i] ) {
1132  pose.conformation().delete_residue_slow( i );
1133  //pose.conformation().delete_polymer_residue( i );
1134  mapping.delete_source_residue( i );
1135  break; // because the numbering is screwed up now, start the loop again
1136  }
1137  }
1138  }
1139 
1140  // now convert sequence of aligned positions
1141  ResidueTypeSet const & rsd_set( pose.residue(1).residue_type_set() );
1142  {
1143  for ( Size i=1; i<= mapping.size1(); ++i ) {
1144  char const new_seq( target_seq[ mapping[i]-1 ] ); // strings are 0-indexed
1145  if ( new_seq != pose.residue(i).name1() ) {
1146  // will fail if .select(...) returns empty list
1147  ResidueTypeCOP new_rsd_type
1148  ( ResidueSelector().set_name1( new_seq ).match_variants( pose.residue(i).type() ).select( rsd_set )[1] );
1149  ResidueOP new_rsd( ResidueFactory::create_residue( *new_rsd_type, pose.residue(i), pose.conformation() ) );
1150  pose.replace_residue( i, *new_rsd, false );
1151  }
1152  }
1153  }
1154 
1155  // Add jumps+cuts at the loop positions
1156  {
1157  runtime_assert( pose.total_residue() == mapping.size1() );
1158  kinematics::FoldTree f( pose.fold_tree() );
1159  for ( Size i=1; i< pose.total_residue(); ++i ) {
1160  runtime_assert( mapping[i] );
1161  if ( mapping[i+1] != mapping[i]+1 && !f.is_cutpoint(i) ) {
1162  f.new_jump( i, i+1, i );
1163 // } else if ( pose.chain(i) != pose.chain(i+1) ) {
1164 // tt << "chain jump! " << pose.residue(i).name() << ' ' << pose.residue(i+1).name() << std::endl;
1165 // f.new_jump( i, i+1, i );
1166  }
1167  }
1168  pose.fold_tree(f);
1169  tt << "FOldtree: " << f << std::endl;
1170  runtime_assert( f.check_fold_tree() );
1171  }
1172 
1173  // add terminal residues
1174  // nterm
1175 
1176  while ( mapping[ 1 ] != 1 ) {
1177  int const aligned_pos( mapping[1] - 1 );
1178  char const new_seq( target_seq[ aligned_pos-1 ] ); // 0-indexed
1179  ResidueTypeCOP new_rsd_type( ResidueSelector().set_name1( new_seq ).exclude_variants().select( rsd_set )[1] );
1180  ResidueOP new_rsd( ResidueFactory::create_residue( *new_rsd_type ) );
1181  pose.conformation().safely_prepend_polymer_residue_before_seqpos( *new_rsd, 1, true );
1182  pose.set_omega( 1, 180.0 );
1183  mapping.insert_aligned_residue( 1, aligned_pos );
1184  }
1185  // cterm
1186  while ( mapping[ mapping.size1() ] != mapping.size2() ) {
1187  int const seqpos( mapping.size1() + 1 );
1188  int const aligned_pos( mapping[seqpos-1] + 1 );
1189  char const new_seq( target_seq[ aligned_pos-1 ] ); // 0-indexed
1190  ResidueTypeCOP new_rsd_type( ResidueSelector().set_name1( new_seq ).exclude_variants().select( rsd_set )[1] );
1191  ResidueOP new_rsd( ResidueFactory::create_residue( *new_rsd_type ) );
1192  pose.conformation().safely_append_polymer_residue_after_seqpos( *new_rsd, seqpos-1, true );
1193  pose.set_omega( seqpos-1, 180.0 );
1194  mapping.insert_aligned_residue( seqpos, aligned_pos );
1195  }
1196 
1197  // now fill in the breaks
1198  {
1199  for ( Size cut=1; cut<= Size(pose.fold_tree().num_cutpoint()); ++cut ) {
1200  while ( mapping[ pose.fold_tree().cutpoint( cut )+1] != Size(pose.fold_tree().cutpoint( cut )+1 )) {
1201  Size const cutpoint( pose.fold_tree().cutpoint( cut ) );
1202  runtime_assert( mapping[cutpoint] == cutpoint ); // we've fixed everything up til here
1203 
1204  if ( pose.chain( cutpoint ) != pose.chain( cutpoint+1 ) &&
1205  pose.residue( cutpoint ).is_protein() && pose.residue( cutpoint+1 ).is_protein() ) {
1206  utility_exit_with_message( "dont know whether to add residues before or after the cutpoint between chains!" );
1207  }
1208  int const aligned_pos( cutpoint+1 );
1209  char const new_seq( target_seq[ aligned_pos - 1 ] ); // 0-indexed
1210  ResidueTypeCOP new_rsd_type( ResidueSelector().set_name1( new_seq ).exclude_variants().select( rsd_set )[1] );
1211  ResidueOP new_rsd( ResidueFactory::create_residue( *new_rsd_type ) );
1212  mapping.insert_aligned_residue( cutpoint + 1, aligned_pos );
1213  if ( pose.residue( cutpoint ).is_protein() ) {
1214  // add at the nterm of the loop
1215  pose.conformation().safely_append_polymer_residue_after_seqpos( *new_rsd, cutpoint, true );
1216  pose.set_omega( cutpoint, 180.0 );
1217  } else if ( pose.residue( cutpoint + 1 ).is_protein() ) {
1218  /// add at the cterm of the loop
1219  pose.conformation().safely_prepend_polymer_residue_before_seqpos( *new_rsd, cutpoint+1, true );
1220  pose.set_omega( cutpoint+1, 180.0 );
1221  } else {
1222  utility_exit_with_message( "dont know how to add non-protein residues!" );
1223  }
1224  tt.Trace << "added residue " << cutpoint+1 << ' ' << pose.fold_tree();
1225  runtime_assert( pose.fold_tree().check_fold_tree() );
1226  } // while missing residues
1227 
1228  // add cutpoint variants to allow loop modeling
1229  int const cutpoint( pose.fold_tree().cutpoint( cut ) );
1230  if ( pose.chain(cutpoint) == pose.chain(cutpoint+1) ) {
1231  if ( pose.residue( cutpoint ).is_protein() && pose.residue( cutpoint+1 ).is_protein() ) {
1234  } else if ( pose.residue( cutpoint ).is_protein() || pose.residue( cutpoint+1 ).is_protein() ) {
1235  tt.Warning << "Same-chain junction between protein and non-protein!" << std::endl;
1236  }
1237  }
1238  } // cut=1,ncutpoints
1239  } // scope
1240 
1241  runtime_assert( mapping.is_identity() );
1242  runtime_assert( pose.sequence() == target_seq );
1243 
1244 }
1245 
1246 /// @details Given a sequence mapping which may have simple indels, trim back around those indels so that the
1247 /// loops can plausibly be closed.
1248 
1249 void
1251  //pose::Pose const & src_pose,
1252  id::SequenceMapping & mapping,
1253  std::string const & source_seq,
1254  std::string const & target_seq,
1255  Size const min_loop_size
1256  )
1257 {
1258  //Size const min_loop_size( 5 );
1259 
1260  std::string s1( source_seq ), s2( target_seq );
1261 
1262  for ( Size r=1; r<= 2; ++r ) {
1263  runtime_assert( s1.size() == mapping.size1() && s2.size() == mapping.size2() );
1264 
1265  // look for insertions that are going to be hard to close
1266  for ( Size i=2; i<= mapping.size1(); ++i ) {
1267  if ( mapping[i-1] && !mapping[i] ) {
1268  // i is the 1st unaligned residue
1269  // j is the next aligned residue
1270  Size j(i+1);
1271  for ( ; j<= mapping.size1() && !mapping[j]; ++j ) {};
1272  //if ( j > mapping.size1() ) break; // done scanning
1273  if ( j > mapping.size1() ) {
1274  // terminal loop
1275  runtime_assert( j == mapping.size1()+1 );
1276  Size loop_begin( i );
1277  Size loop_size( mapping.size1() - i + 1 );
1278  while ( mapping[ loop_begin-2 ] && loop_size < min_loop_size ) {
1279  runtime_assert( !mapping[ loop_begin ] );
1280  runtime_assert( mapping[ loop_begin-1 ] );
1281  --loop_begin;
1282  mapping[ loop_begin ] = 0;
1283  ++loop_size;
1284  tt.Trace << "trimming back c-terminal loop! from " << i << " to " << loop_begin << std::endl;
1285  }
1286  break;
1287  }
1288 
1289  Size loop_begin( i ), loop_end( j-1 );
1290  while ( true ) {
1291  runtime_assert( !mapping[ loop_begin ] && !mapping[ loop_end ] );
1292  runtime_assert( mapping[ loop_begin-1 ] && mapping[ loop_end + 1 ] );
1293  Size const size1( loop_end - loop_begin + 1 );
1294  Size const size2( mapping[ loop_end+1 ] - mapping[ loop_begin-1 ] - 1 );
1295  Size const min_size( std::min( size1, size2 ) );
1296  //Real const size_difference( std::abs( int(size1) - int(size2) ) );
1297  tt.Trace << "loopseq: " << s1.substr(loop_begin-1,size1) << std::endl;
1298  if ( min_size >= min_loop_size /* && size_difference / min_size <= 1.001 */ ) break;
1299  // trim back on one side or the other
1300  bool const safe_to_trim_backward( loop_begin > 2 && mapping[ loop_begin-2 ] );
1301  bool const safe_to_trim_forward ( loop_end <= mapping.size1()-2 && mapping[ loop_end+2 ] );
1302  if ( safe_to_trim_forward && ( numeric::random::uniform() < 0.5 || !safe_to_trim_backward ) ) {
1303  tt.Trace << "trimming forward " << loop_begin << ' ' << loop_end << ' ' << std::endl;
1304  ++loop_end;
1305  mapping[ loop_end ] = 0;
1306  } else if ( safe_to_trim_backward ) {
1307  tt.Trace << "trimming backward " << loop_begin << ' ' << loop_end << ' ' << std::endl;
1308  --loop_begin;
1309  mapping[ loop_begin ] = 0;
1310  } else {
1311  tt.Warning << "Unable to extend loop to meet criteria! " << loop_begin << ' ' << loop_end << ' '<<
1312  mapping[ loop_begin-1 ] << ' ' << mapping[ loop_end+1 ] << std::endl;
1313  break;
1314  }
1315  }
1316  tt.Trace << "finalloopseq: " << s1.substr(loop_begin-1,loop_end-loop_begin+1) << ' ' << loop_begin << ' ' <<
1317  loop_end;
1318  if ( r==1 ) tt.Trace << " source_insert" << std::endl;
1319  else tt.Trace << " target_insert" << std::endl;
1320  }
1321  }
1322  mapping.reverse();
1323  std::string tmp( s2 );
1324  s2 = s1;
1325  s1 = tmp;
1326  }
1327 }
1328 
1329 
1330 //////////////////////////////////////////////////////////////////
1331 /// @details read in secondary structure definition from a psipred_ss2 file and
1332 /// set that to a Pose. A temporary setup since there is very limited ss support in
1333 /// Pose right now.
1334 ///////////////////////////////////////////////////////////////////
1335 bool
1337  pose::Pose & pose
1338 )
1339 
1340 {
1341  utility::vector1< char > secstructs = read_psipred_ss2_file( pose );
1342  // if don't have a psipred file...
1343  if( secstructs.size() == 0 ){
1344  // instead roughly guess at secondary structure.
1346  return false;
1347  }
1348  tt << "set_secstruct for pose: ";
1349  for ( Size i = 1, iend=secstructs.size(); i <= iend; ++i ) {
1350  pose.set_secstruct( i, secstructs[i] );
1351  tt << pose.secstruct(i);
1352  }
1353  tt << std::endl;
1354 
1355  tt << "set pose secstruct from psipred_ss2 file succesfully " << std::endl;
1356 
1357  return true;
1358 }
1359 
1360 
1361 //////////////////////////////////////////////////////////////////
1362 /// @details read in secondary structure definition from a DSSP file and
1363 /// set that to a Pose. (Rhiju's copy of Chu's psipred reader).
1364 /// Chu, should these functions be moved somewhere to core, along with
1365 /// pdb readers, etc?
1366 ///////////////////////////////////////////////////////////////////
1367 bool
1369  pose::Pose & pose,
1370  std::string const & filename
1371 )
1372 {
1373 
1374  utility::io::izstream data( filename );
1375  if ( !data ) {
1376  tt << "can not open DSSP file " << filename << std::endl;
1377  return false;
1378  }
1379 
1380  utility::vector1< char > secstructs;
1381  std::string line;
1382 
1383  //Sorry, this is the least robust DSSP reader ever.
1384 
1385  //Skip ahead to the good stuff
1386  while( getline( data, line ) ) {
1387  std::istringstream line_stream( line );
1388  char dummy;
1389  line_stream >> dummy;
1390  if ( dummy == '#') break; //yippeeee!
1391  }
1392 
1393  Size count(0);
1394  while( getline( data, line ) ) {
1395  std::istringstream line_stream( line );
1396  //int dummy_int;
1397  char aa,sec;
1398 
1399  line_stream.ignore( 13 );
1400  line_stream.get( aa );
1401  line_stream.ignore( 2 );
1402  line_stream.get( sec );
1403 
1404  if ( aa == '!' ) continue; //skip a chainbreak line
1405 
1406  count++;
1407  if ( aa != oneletter_code_from_aa( pose.aa(count) ) ) {
1408  //std::cerr << " sequence mismatch between pose and dssp " << oneletter_code_from_aa( pose.aa(count) )
1409  // << " vs " << aa << " at seqpos " << count << std::endl;
1410  tt.Error << " sequence mismatch between pose and dssp " << oneletter_code_from_aa( pose.aa(count) )
1411  << " vs " << aa << " at seqpos " << count << std::endl;
1412  return false;
1413  }
1414 
1415  // Follow convention used in Rosetta++, for now.
1416  // Do we want to change this? E.g., why is 'G' (left-handed helix) in the
1417  // same category as 'H' (alpha helix)? Need to discuss
1418  // with Ben Blum.
1419  //
1420  if ( sec == 'E' ) {
1421  secstructs.push_back( 'E' );
1422  } else if ( sec == 'H' || sec == 'I' || sec == 'G' ) {
1423  secstructs.push_back( 'H' );
1424  } else {
1425  secstructs.push_back( 'L' ); //all other B, S, and T
1426  }
1427  }
1428 
1429  runtime_assert( secstructs.size() == pose.total_residue() );
1430  tt.Trace << "set_secstruct for pose: ";
1431  for ( Size i = 1, iend=secstructs.size(); i <= iend; ++i ) {
1432  pose.set_secstruct( i, secstructs[i] );
1433  tt.Trace << pose.secstruct(i);
1434  }
1435  tt.Trace << std::endl;
1436 
1437  tt.Trace << "set pose secstruct from DSSP file succesfully " << std::endl;
1438 
1439  return true;
1440 
1441 }
1442 
1443 //////////////////////////////////////////////////////////////////////////////////
1444 /// @details set ideal BB geometry; this must occur so that loops with missing density work.
1446  core::pose::Pose & pose,
1447  Loop const & loop
1448 )
1449 {
1450  for( Size i = (Size)std::max((int)1,(int)loop.start()); i <= loop.stop(); ++i ) {
1452  }
1453 }
1454 
1455 
1456 
1457 //////////////////////////////////////////////////////////////////////////////////
1458 /// @details Set a loop to extended torsion angles.
1460  core::pose::Pose & pose,
1461  Loop const & loop
1462 )
1463 {
1464  tt.Error << "USING A DEPRECATED FUNCTION!( loops::set_extended_torsions(...) ) " << std::endl;
1465 
1466  Real const init_phi ( -150.0 );
1467  Real const init_psi ( 150.0 );
1468  Real const init_omega( 180.0 );
1469 
1470  static int counter = 0;
1471 
1472  tt.Debug << "Extending loop " << loop.start() << " " << loop.stop() << std::endl;
1473 
1474  idealize_loop(pose, loop );
1475 
1476  Size start_extended = std::max((Size)1,loop.start());
1477  Size end_extended = std::min(pose.total_residue(),loop.stop());
1478  for( Size i = start_extended; i <= end_extended; ++i ) {
1479  if( i != start_extended ) pose.set_phi( i, init_phi );
1480  if( i != end_extended ) pose.set_psi( i, init_psi );
1481  if( ( i != start_extended ) && ( i != end_extended ) ) pose.set_omega( i, init_omega );
1482  }
1483 
1484  counter++;
1485 }
1486 
1487 
1488 
1489 
1490 //////////////////////////////////////////////////////////////////////////////////
1491 /// @details Rebuild a loop via fragment insertion + ccd closure + minimization
1493  core::pose::Pose & pose,
1494  Loop const & loop
1495 )
1496 {
1497  Size cutpoint = loop.cut();
1498  if ( cutpoint== 0 ) cutpoint = (loop.start() + loop.stop()) / 2;
1499  set_single_loop_fold_tree( pose, loop );
1500  set_extended_torsions( pose, loop );
1501 }
1502 
1503 
1504 
1505 
1506 
1508  const core::pose::Pose & native_pose,
1509  const core::pose::Pose & pose,
1510  loops::Loops loops,
1511  int &corelength
1512 ) {
1513 
1514  std::vector< core::Size > residue_exclusion;
1515 
1516  for( core::Size i = 1; i <= loops.size(); i++ ) {
1517  for( core::Size ir = loops[i].start();
1518  ir <= loops[i].stop();
1519  ir ++ ){
1520  residue_exclusion.push_back( ir );
1521  }
1522  }
1523 
1524 
1525  std::list< core::Size > residue_selection;
1526 
1527  for( core::Size ir = 1; ir <= pose.total_residue(); ir ++ ){
1528  if( !pose.residue_type(ir).is_protein() ) continue;
1529  bool exclude = false;
1530  for( core::Size p = 0; p < residue_exclusion.size(); p++ ){
1531  if( ir == residue_exclusion[p] ){
1532  exclude = true;
1533  break;
1534  }
1535  }
1536  if( !exclude ) residue_selection.push_back( ir );
1537  }
1538 
1539  corelength = residue_selection.size();
1540  if ( corelength == 0 ) return 0.0;
1541  else return core::scoring::CA_rmsd( native_pose, pose, residue_selection );
1542 } // native_CA_rmsd
1543 
1544 
1545 
1546 
1547 
1548 /////////////////////////////////////////////////////////////////////////////////////
1549 ///@details pose1 is the reference and pose2 is the structure for which rmsd is calculated.
1550 ///The rmsd is calculated over four backbone atoms of all loop residues, assuming template
1551 ///regions in pose1 and pose2 are already aligned.
1552 //////////////////////////////////////////////////////////////////////////////////////
1553 Real
1555  pose::Pose const & pose1,
1556  pose::Pose const & pose2,
1557  Loops const & loops,
1558  bool CA_only,
1559  bool bb_only
1560 )
1561 
1562 {
1563  Loops core; //empty core -- take all residues for superposition
1564  return loop_rmsd_with_superimpose_core( pose1, pose2, loops, core, CA_only, bb_only );
1565 }
1566 
1567 /////////////////////////////////////////////////////////////////////////////////////
1568 ///@details pose1 is the reference and pose2 is the structure for which rmsd is calculated.
1569 ///The rmsd is calculated over four backbone atoms of all loop residues, assuming template
1570 ///regions in pose1 and pose2 are already aligned.
1571 //////////////////////////////////////////////////////////////////////////////////////
1572 Real
1574  pose::Pose const & pose1,
1575  pose::Pose const & pose2,
1576  Loops const & loops,
1577  Loops const & core,
1578  bool CA_only,
1579  bool bb_only
1580 )
1581 
1582 {
1583  pose::Pose ncpose1 = pose1;
1586  for ( core::Size ir=1; ir <= ncpose1.total_residue(); ++ir ) {
1587  if (ncpose1.residue(ir).aa() == core::chemical::aa_vrt || pose2.residue(ir).aa() == core::chemical::aa_vrt) continue;
1588  if( !loops.is_loop_residue( ir ) && ( core.size()==0 || core.is_loop_residue( ir ) ) ){
1589  id::AtomID const id1( ncpose1.residue(ir).atom_index("CA"), ir );
1590  id::AtomID const id2( pose2.residue(ir).atom_index("CA"), ir );
1591  atom_map.set(id1, id2);
1592  }
1593  }
1594  core::scoring::superimpose_pose( ncpose1, pose2, atom_map );
1595 
1596  core::Real looprms = loop_rmsd( ncpose1, pose2, loops, CA_only, bb_only );
1597 
1598  return looprms;
1599 }
1600 
1601 /////////////////////////////////////////////////////////////////////////////////////
1602 ///@details pose1 is the reference and pose2 is the structure for which rmsd is calculated.
1603 ///The rmsd is calculated over four backbone atoms of all loop residues, assuming template
1604 ///regions in pose1 and pose2 are already aligned.
1605 //////////////////////////////////////////////////////////////////////////////////////
1606 Real
1608  pose::Pose const & pose1,
1609  pose::Pose const & pose2,
1610  Loops const & loops,
1611  bool CA_only,
1612  bool bb_only
1613 )
1614 
1615 {
1616  if(pose1.total_residue() != pose2.total_residue() ){
1617  // strip VRTs from the end, then compare lengths
1618  int nnonvrt_1 = pose1.total_residue();
1619  while ( pose1.residue( nnonvrt_1 ).aa() == core::chemical::aa_vrt ) nnonvrt_1--;
1620 
1621  int nnonvrt_2 = pose2.total_residue();
1622  while ( pose2.residue( nnonvrt_2 ).aa() == core::chemical::aa_vrt ) nnonvrt_2--;
1623  if ( nnonvrt_1 != nnonvrt_2 )
1624  utility_exit_with_message( "Error in loop_rmsd: pose1.total_residue() != pose2.total_residue() ( "
1625  + string_of( nnonvrt_1 ) + "!=" + string_of( nnonvrt_2 )+")" );
1626  }
1627 
1628  Real rms = 0.0;
1629  int atom_count(0);
1630  for ( Loops::const_iterator it=loops.begin(), it_end=loops.end();
1631  it != it_end; ++it ) {
1632  for ( Size i = it->start(); i<=it->stop(); ++i ) {
1633  if ( i > pose1.total_residue() ){
1634  tt.Warning << "[Warning]: Pose1: Loop residue " << i << "exceeds pose1 size " << pose1.total_residue() << std::endl;
1635  continue;
1636  }
1637  if ( i > pose2.total_residue() ){
1638  tt.Warning << "[Warning]: Pose1: Loop residue " << i << "exceeds pose2 size " << pose2.total_residue() << std::endl;
1639  continue;
1640  }
1641  Size start = 1;
1642  Size end = bb_only ? 4 : pose1.residue(i).atoms().size();
1643  if( CA_only ){ // Only include CA atoms
1644  start = 2;
1645  end = 2;
1646  }
1647  for ( Size j = start; j <= end; ++j ) {
1648  atom_count++;
1649  if( j > pose1.residue(i).atoms().size() ){
1650  tt.Warning << "[Warning]: Pose1: Atom " << j << " missing from residue " << i << std::endl;
1651  continue;
1652  }
1653  if( j > pose2.residue(i).atoms().size() ){
1654  tt.Warning << "[Warning]: Pose2: Atom " << j << " missing from residue " << i << std::endl;
1655  continue;
1656  }
1657  rms += pose1.residue(i).xyz(j).distance_squared( pose2.residue(i).xyz(j) );
1658 
1659  } // for each bb atom
1660  } // for each residue
1661  } // for each loop
1662  return atom_count==0 ? 0.0 : std::sqrt(rms/atom_count);
1663 }
1664 
1665 /////////////////////////////////////////////////////////////////////////////////////
1666 ///@details pose1 is the reference and pose2 is the structure for which rmsd is calculated.
1667 ///The rmsd is calculated over four backbone atoms of each loop after fitting it onto the reference
1668 ///loop and when there are multiple loops, return the mean value.
1669 //////////////////////////////////////////////////////////////////////////////////////
1670 Real
1672  pose::Pose const & pose1,
1673  pose::Pose const & pose2,
1674  Loops const & loops
1675 )
1676 {
1677  runtime_assert(pose1.total_residue() == pose2.total_residue() );
1678 
1679  Real rms = 0.0;
1680  if ( loops.num_loop() == 0 ) {
1681  return rms;
1682  }
1683 
1684  for ( Loops::const_iterator it=loops.begin(), it_end=loops.end();
1685  it != it_end; ++it ) {
1686  int natoms = 4 * it->size() ;
1687  //FArray2D_double p1a(3, natoms);
1688  //FArray2D_double p2a(3, natoms);
1689  FArray2D< core::Real > p1a(3, natoms);
1690  FArray2D< core::Real > p2a(3, natoms);
1691 
1692  int atom_count(0);
1693  for ( Size i = it->start(); i<=it->stop(); ++i ) {
1694  for ( Size j = 1; j <= 4; ++j ) {
1695  const numeric::xyzVector< Real > & vec1( pose1.residue(i).xyz( j ) );
1696  const numeric::xyzVector< Real > & vec2( pose2.residue(i).xyz( j ) );
1697  atom_count++;
1698  for ( int k = 0; k < 3; ++k ) { // k = X, Y and Z
1699  p1a(k+1,atom_count) = vec1[k];
1700  p2a(k+1,atom_count) = vec2[k];
1701  } // k
1702  } // j
1703  } // i
1704  rms += numeric::model_quality::rms_wrapper( natoms, p1a, p2a );
1705  }
1706 
1707  return rms / loops.num_loop();
1708 }
1709 
1710 } // namespace loops
1711 } // namespace protocols