Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FloppyTailMover.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/floppy_tail/FloppyTailMover.cc
11 /// @brief This app was initially intended for modeling the binding of a long unstructured C-terminal tail to some other part of a protein. It now works for N-terminal, C-terminal, and internal flexible regions. It works best as a method for sampling space to see what is possible, preferably in conjunction with extensive experimental constraints. It is not meant to produce ab-initio style models of folded complexes.
12 /// @author Steven Lewis
13 
14 // Unit Headers
17 
18 // Project Headers
19 //#include <core/conformation/Conformation.hh>
20 
21 #include <core/pose/Pose.hh>
22 #include <core/pose/PDBPoseMap.hh>
23 #include <core/pose/PDBInfo.hh>
24 
26 
29 #include <core/kinematics/util.hh>
30 
32 
35 
38 
40 
42 
43 //movers
44 #include <protocols/simple_moves/BackboneMover.hh> //SmallMover
47 #include <protocols/moves/MoverContainer.hh> //Sequence Mover
50 #include <protocols/simple_moves/SwitchResidueTypeSetMover.hh> //typeset swapping
53 #include <protocols/moves/OutputMovers.hh> //pdbdumpmover
54 
55 //calculators and neighbor detection machinery
59 
60 // //JD headers
63 #include <protocols/jd2/Job.hh>
64 
65 // Utility Headers
66 #include <basic/options/option.hh>
67 #include <basic/Tracer.hh>
68 #include <utility/exit.hh>
69 
70 // option key includes
71 #include <basic/options/keys/run.OptionKeys.gen.hh>
72 #include <basic/options/keys/in.OptionKeys.gen.hh>
73 #include <basic/options/keys/packing.OptionKeys.gen.hh>
74 #include <basic/options/keys/FloppyTail.OptionKeys.gen.hh>
75 
77 #include <utility/vector0.hh>
78 #include <utility/vector1.hh>
79 
80 #if defined(WIN32) || defined(__CYGWIN__)
81  #include <ctime>
82 #endif
83 
84 using basic::T;
85 using basic::Error;
86 using basic::Warning;
87 
88 static basic::Tracer TR("protocols.floppy_tail.FloppyTail");
89 
90 namespace protocols {
91 namespace floppy_tail {
92 
94  start_(0),
95  stop_(0),
96  init_for_input_yet_(false),
97  centroid_scorefunction_(NULL),
98  fullatom_scorefunction_(NULL),
99  task_factory_(NULL),
100  movemap_(NULL),
101  movemap_lesstail_(NULL),
102  foldtree_(NULL),
103  fragset3mer_(NULL)
104 {
105  protocols::moves::Mover::type( "FloppyTail" );
106 
107  //this should be per-input, not in the ctor, if multiple frags files
108  if (basic::options::option[ basic::options::OptionKeys::in::file::frag3].user()){
110  fragset3mer_->read_fragment_file( basic::options::option[ basic::options::OptionKeys::in::file::frag3].value() );
111  }
112 
113  bool const pair_off(basic::options::option[ basic::options::OptionKeys::FloppyTail::pair_off ].value() );
114 
115  //set up centroid scorefunction
116  using namespace core::scoring;
117  if (basic::options::option[ basic::options::OptionKeys::FloppyTail::cen_weights].user()){
118  centroid_scorefunction_ = ScoreFunctionFactory::create_score_function(basic::options::option[ basic::options::OptionKeys::FloppyTail::cen_weights].value());
119  }
120  else{
122  centroid_scorefunction_->set_weight( env, 1.0 );
123  centroid_scorefunction_->set_weight( cbeta, 1.0 );
124  centroid_scorefunction_->set_weight( vdw, 1.0 );
125  centroid_scorefunction_->set_weight( pair, (pair_off ? 0.0 : 1.0) ); //no pair term experiment - not for general use
126  centroid_scorefunction_->set_weight( cenpack, 1.0 );
127  centroid_scorefunction_->set_weight( rama, 1.0 );
128  centroid_scorefunction_->set_weight( hbond_lr_bb, 1.0 );
129  centroid_scorefunction_->set_weight( hbond_sr_bb, 1.0 );
130  }
131 
133  TR << "Using centroid scorefunction\n" << *centroid_scorefunction_;
134 
135  //set up fullatom scorefunction
138  if( pair_off ) fullatom_scorefunction_->set_weight( fa_pair, 0.0 ); //not for general use
139  TR << "Using fullatom scorefunction\n"<< *fullatom_scorefunction_;
140 
141 }
142 
144 
145 ///@brief copy ctor
147  Mover(rhs)
148 {
149  *this = rhs;
150 }
151 
153 
154  //abort self-assignment
155  if (this == &rhs) return *this;
156 
157  start_ = rhs.start_;
158  stop_ = rhs.stop_;
162  task_factory_ = rhs.task_factory_->clone();
163  movemap_ = rhs.movemap_->clone();
164  movemap_lesstail_ = rhs.movemap_lesstail_->clone();
165  foldtree_ = new core::kinematics::FoldTree(rhs.foldtree_); //no clone operation, and no proper copy ctor
167 
168  return *this;
169 }
170 
172  movemap_ = movemap->clone();
173 }
174 
176  fullatom_scorefunction_=fa_scorefxn->clone();
177 }
178 
180  centroid_scorefunction_=cen_scorefxn->clone();
181 }
182 
183 ///@brief init_on_new_input system allows for initializing these details the first time apply() is called. the job distributor will reinitialize the whole mover when the input changes (a freshly constructed mover, which will re-run this on first apply().
185  init_for_input_yet_ = true;
186 
187  //determine where the flexible tail is
188  using namespace basic::options;
189  using namespace basic::options::OptionKeys;
190 
191  if(!option[in::file::movemap].user() && !movemap_){
192  //original code: read from command line options
193  char const chain(option[FloppyTail::flexible_chain].value()[0]); //just take the first one
194  start_ = pose.pdb_info()->pdb2pose().find(chain, option[FloppyTail::flexible_start_resnum].value());
195  if(option[FloppyTail::flexible_stop_resnum].user())
196  stop_ = pose.pdb_info()->pdb2pose().find(chain, option[FloppyTail::flexible_stop_resnum].value());
197  else
198  stop_ = pose.total_residue();
199  TR << "Tail is from " << start_ << " to " << stop_ << std::endl;
200 
201  //setup MoveMap
203  for(core::Size i(start_); i<=stop_; ++i) {
204  movemap_->set_bb(i, true); //backbone mobile
205  movemap_->set_chi(i, true); //chi of mobile residues
206  }
207 
209  if (stop_ == pose.total_residue()){
210  core::Size const taillength = stop_ - start_;
211  core::Size const substop = (start_ + core::Size(core::Real(taillength) * (1.0 - option[ FloppyTail::short_tail::short_tail_fraction ] ) ) );
212  for(core::Size i(start_); i <= substop; ++i) {
213  movemap_lesstail_->set_bb(i, false);
214  movemap_lesstail_->set_chi(i, false);
215  }
216  }
217  } else if ( //these options are incompatible with movemap use; the movemap determines flexible regions
218  option[FloppyTail::flexible_chain].user() ||
219  option[FloppyTail::flexible_stop_resnum].user() ||
220  option[FloppyTail::flexible_chain].user() ||
221  option[FloppyTail::short_tail::short_tail_fraction].user() ||
222  option[FloppyTail::short_tail::short_tail_off].user() ) {
223  utility_exit_with_message("option in::file::movemap not compatible with options flexible_chain, flexible_stop_resnum, flexible_chain, short_tail_fraction, or short_tail off. This is because a manually-defined movemap overrides these options.");
224  } else {
225  //handle user-defined movemap from file or from function; reverse-convert into start_ and stop_
226  if (!movemap_){
228  movemap_->init_from_file(option[in::file::movemap].value());
229  }
231 
232  //calculate effective start_ and stop_. This may be less efficient than the MoveMap's iterators, but it is vastly simpler, less likely to be buggy, and not a performace concern.
233  core::Size const nres(pose.total_residue());
234  for( core::Size i(1); i<=nres; ++i ){
235  if( movemap_->get_bb(i) ){
236  start_ = i;
237  break;
238  }
239  }
240 
241  for( core::Size i(nres); i>=1; --i) {
242  if( movemap_->get_bb(i) ){
243  stop_ = i;
244  break;
245  }
246  }
247 
248  }
249 
250  //error handle: if start_ and stop_ couldn't be set from movemap somehow, freak out
251  if( (start_ == 0) || (stop_ == 0) ){
252  std::ostringstream message;
253  message << "invalid flexible region (start (" << start_ << ") or stop (" << stop_ << ") is undefined) - check your flags or movemap file";
254  utility_exit_with_message( message.str());
255  }
256 
257  //We want to linearize the fold_tree so that internal linkers with noncovalent attachments on both sides will work properly; it will have no effect on terminal tails
258  foldtree_ = new core::kinematics::FoldTree(pose.fold_tree()); //store original fold tree; if we enter neither option below it stays valid
259  if( !((stop_ == pose.total_residue()) || (start_ == 1)) || basic::options::option[ FloppyTail::force_linear_fold_tree].value() ){
260  TR << "non-terminal or N-terminal (C-rooted) floppy section, using a linear fold tree to try to ensure downstream residues follow \nOld tree: " << pose.fold_tree();
262  TR << "new tree: " << *foldtree_ << std::endl;
263  }
264  if( basic::options::option[ FloppyTail::C_root].value() ) {
265  foldtree_->reorder(pose.total_residue());
266  TR << "C-rooted tree: " << *foldtree_ << std::endl;
267  }
268 
269  //setup of TaskFactory
270  //command line and resfile options
271  using namespace core::pack::task;
274  if ( option[ packing::resfile ].user() ) {
275  task_factory_->push_back( new operation::ReadResfile );
276  }
277 
278  //iterate through movemap, determining where regions of flexibility and inflexibility are
279  //Each inflexible region surrounded by two flexible region constitutes a "group" for InterGroupNeighborsCalculator
280  //inclusion of flexible regions into multiple groups ensures they will repack regardless of their neighbors
281  //all group pairs are passed as viable to InterGroupNeighborsCalculator
282  //flexible regions are included in two subsequent groups, ensuring that they'll pack at all times (as their own neighbors)
283  bool previous_state(false); //assume we start with a non-flexible region; new regions are triggered on flexiblity
284  utility::vector1< std::set < core::Size > > regions; //a set of regions to turn into groups for comparison
285  std::set < core::Size > const empty; //easier to add empty sets to the vector than construct-then-add
286  core::Size current_group(1);
287  regions.push_back(empty);
288 
289  //iterate through all residues in the pose/movemap
290  core::Size const nres(pose.total_residue());
291  for(core::Size i(1); i<=nres; ++i) {
292  bool const this_state(movemap_->get_bb(i));
293  if(this_state != previous_state) { //if we are changing regions
294  if( previous_state == false ) { //we are leaving an inflexible region
295  regions.push_back(empty); //add a new group, and start putting residues there
296  ++current_group;
297  }
298  previous_state = this_state; //keep previous_state up to date
299  }
300  regions[current_group].insert(i); //add this residue to the current group
301  if(this_state) regions[current_group-1].insert(i); //add this residue to the previous group, if flexible - this ensures flexible regions always can repack
302  }
303 
304  //make all pairs of groups (without replacement
305  //if you have 1, 2, 3, 4; make 1-2, 1-3, 1-4, 2-3, 2-4, 3-4
306  core::Size const num_regions(regions.size());
307  utility::vector1< std::pair< std::set<core::Size>, std::set<core::Size> > > vector_of_pairs;
308  for(core::Size first_group(1); first_group < num_regions; ++first_group) {
309  for(core::Size second_group(first_group+1); second_group <= num_regions; ++second_group){
310  vector_of_pairs.push_back(std::make_pair(regions[first_group], regions[second_group]));
311  }
312  }
313 
314  //check contents of vector_of_pairs
315  core::Size const num_pairs(vector_of_pairs.size());
316  for(core::Size i(1); i<=num_pairs; ++i){
317  core::Size const
318  onestart(*(vector_of_pairs[i].first.begin())),
319  onestop(*(vector_of_pairs[i].first.rbegin())),
320  twostart(*(vector_of_pairs[i].second.begin())),
321  twostop(*(vector_of_pairs[i].second.rbegin()));
322 
323  TR << "IGNC will compare group " << onestart << "-" << onestop << " with " << twostart << "-" << twostop << std::endl;
324 
325  core::Size guess(onestart);
326  for(std::set<core::Size>::const_iterator iter(vector_of_pairs[i].first.begin()), end(vector_of_pairs[i].first.end()); iter != end; ++iter) {
327  if(guess++ != *iter) TR.Error << "non-contiguous set, debug me!" << std::endl;
328  //TR << *iter << std::endl;
329  }
330  guess = twostart;
331  for(std::set<core::Size>::const_iterator iter(vector_of_pairs[i].second.begin()), end(vector_of_pairs[i].second.end()); iter != end; ++iter) {
332  if(guess++ != *iter) TR.Error << "non-contiguous set, debug me!" << std::endl;
333  //TR << *iter << std::endl;
334  }
335 
336  }
337 
338  //check if calculator exists; create if not
339  std::string const calc("IGNC_FloppyTail");
340  if(core::pose::metrics::CalculatorFactory::Instance().check_calculator_exists(calc)){
342  TR << "removed a PoseMetricCalculator " << calc << ", hopefully this is due to multiple inputs to FloppyTail and not a name clash" << std::endl;
343  }
345 
346  //now that calculator exists, add the sucker to the TaskFactory via RestrictByCalculatorsOperation
348  std::pair< std::string, std::string> IGNC_cmd( calc, "neighbors" );
349  calculators_used.push_back( IGNC_cmd );
351 
352  //debugging: print PackerTask
353  //TR << *(task_factory_->create_task_and_apply_taskoperations( pose )) << std::endl;
354 
355  return;
356 }
357 
359  using namespace basic::options;
360  using namespace basic::options::OptionKeys;
361 
363 
364  //apply fold tree (determined in init_on_new_input) and report
365  pose.fold_tree(*foldtree_);
366  TR << "foldtree, movemap: " << std::endl;
368  if( stop_ == pose.total_residue() ){
369  TR << "foldtree, movemap for first part of refine: " << std::endl;
371  }
372 
373  core::scoring::constraints::add_constraints_from_cmdline_to_pose( pose ); //protected internally if no constraints
374 
375  //centroid
376  clock_t starttime = clock();
377  TR << "entering perturb steps" << std::endl;
378 
379  core::pose::Pose const saved_input_pose( pose ); //used to return sidechains later
380 
382  typeset_swap.apply( pose );
383  //centroid score
384  TR << "centroid score of starting PDB: " << (*centroid_scorefunction_)(pose) << std::endl;
385  centroid_scorefunction_->show( TR, pose );
386  TR << std::flush; //show doesn't flush the buffer
387 
388  /*
389  perturbmover of either type
390  minimize every once in a while
391  MC evaluate
392  */
393 
394  ////////////////////////////////////backbone_mover_cent/////////////////////////////////////
396 
400  small_mover_cen->angle_max( 'H', 180.0 );
401  small_mover_cen->angle_max( 'E', 180.0 );
402  small_mover_cen->angle_max( 'L', 180.0 );
403  backbone_mover_cen->add_mover(small_mover_cen, 1.0);
404 
406  shear_mover_cen->angle_max( 'H', 180.0 );
407  shear_mover_cen->angle_max( 'E', 180.0 );
408  shear_mover_cen->angle_max( 'L', 180.0 );
409  //backbone_mover_cen->add_mover(shear_mover_cen, 1.0); //not yet
410 
411  if(fragset3mer_){ //if we have fragments
413  protocols::simple_moves::ClassicFragmentMoverOP frag_mover = new ClassicFragmentMover(fragset3mer_, movemap_);
414  frag_mover->enable_end_bias_check(false);
415  backbone_mover_cen->add_mover(frag_mover, 0.5);
416  }
417 
418  /////////////////////////minimizer mover/////////////////////////////////////////
422  movemap_,
424  basic::options::option[ basic::options::OptionKeys::run::min_type ].value(),
425  0.01,
426  true /*use_nblist*/ );
427 
428  /////////////////////////Monte Carlo//////////////////////////////////////////////////////////
429  //make the monte carlo object
432  using basic::options::option;
433  MonteCarloOP mc_cen( new MonteCarlo( pose, *centroid_scorefunction_, option[ FloppyTail::perturb_temp ].value() ) );
434 
435  ///////////////////////////////////for loop///////////////////////////////////////////////////
436  protocols::moves::PDBDumpMover cen_out("cen_cycle");
437  core::Size const perturb_applies = option[ FloppyTail::perturb_cycles ].value(); //default 5
438  core::Size shear_on_cyc(core::Size(core::Real(perturb_applies) * option[ FloppyTail::shear_on ]));
439  if(shear_on_cyc == 0) shear_on_cyc = 1; //0 should mean shear on immediately, but the if below never sees 0.
440  TR << "shear on at " << shear_on_cyc << std::endl;
441  TR << " Current Low total cycles =" << perturb_applies << std::endl;
442  for ( core::Size i = 1; i <= perturb_applies; ++i ) {
443  if( i == shear_on_cyc ) backbone_mover_cen->add_mover(shear_mover_cen, 1.0);
444  if( (i % 20 == 0) || (i == perturb_applies) ) min_mover_cen->apply(pose);
445  else backbone_mover_cen->apply(pose);
446 
447  if( option[ FloppyTail::debug ] ) cen_out.apply(pose); //check trajectory
448  mc_cen->boltzmann(pose);
449 
450  TR << i << " " << mc_cen->last_accepted_score() << " " << mc_cen->lowest_score() << std::endl;
451 
452  //constraint report
453  //using core::scoring::atom_pair_constraint;
454  //core::Real const cstscore_in(pose.energies().total_energies()[atom_pair_constraint] * pose.energies().weights()[atom_pair_constraint]);
455  //TR << "cst score " << cstscore_in << std::endl;
456  }//end the exciting for loop
457  mc_cen->recover_low(pose);
458 
459  //filter based on constraints score - if not less than 1 (close to 0), cancel this trajectory
460  // using core::scoring::atom_pair_constraint;
461  // core::Real const cstscore(pose.energies().total_energies()[atom_pair_constraint] * pose.energies().weights()[atom_pair_constraint]);
462  // if (cstscore > 1.0) {
463  // TR << "centroid constraints not satisfied; final constraint score: " << cstscore << ", restarting centroid" << std::endl;
464  // set_last_move_status(protocols::moves::FAIL_RETRY);
465  // return;
466  // }
467 
468  //dump centroid-stage result pose
469  if ( basic::options::option[basic::options::OptionKeys::FloppyTail::perturb_show ].value() ) {
470  using namespace protocols::jd2;
471  JobCOP job_me( JobDistributor::get_instance()->current_job() );
472  JobDistributor::get_instance()->job_outputter()->other_pose( job_me, pose, "centroid");
473  }
474 
475  //show centroid score (duplicates last line above)
476  TR << "centroid score of final perturbed PDB: " << (*centroid_scorefunction_)(pose) << std::endl;
477  centroid_scorefunction_->show( TR, pose );
478  TR << std::flush; //show doesn't flush the buffer
479 
480  clock_t stoptime = clock();
481  TR << "One perturb took " << ((double) stoptime - starttime )/CLOCKS_PER_SEC << " seconds" << std::endl;
482  TR << "perturb steps complete" << std::endl;
483  starttime = clock();
484 
485  ///////////////////////////////////////////////////////////////////////////////////////////////////////
486  ////////////////////////////////////fullatom///////////////////////////////////////////////////////////
487  ///////////////////////////////////////////////////////////////////////////////////////////////////////
488 
489  protocols::simple_moves::ReturnSidechainMover return_sidechains( saved_input_pose );
490  return_sidechains.apply( pose );
491 
492  //remove centroid constraints; add fullatom constraints
493  pose.remove_constraints();
494  core::scoring::constraints::add_fa_constraints_from_cmdline_to_pose(pose); //protected internally if no csts
495 
496  /////////////////////////////generate full repack&minimize mover//////////////////////////////
498  pack_mover->task_factory( task_factory_ );
499  pack_mover->score_function( fullatom_scorefunction_ );
500 
502  movemap_,
504  basic::options::option[ basic::options::OptionKeys::run::min_type ].value(),
505  0.01,
506  true /*use_nblist*/ );
507 
508  //definitely want sidechain minimization here
512 
513  /////////////////////////repack/minimize once to fix sidechains//////////////////////////////////
514  // TR << "packing" << std::endl;
515  pack_mover->apply(pose);
516  // TR << "minimizing" << std::endl;
517  TAmin_mover_fa->apply(pose);
518 
519  //////////////////////////////////////// backbone mover/////////////////////////////////////////
521 
523  small_mover_fa->angle_max( 'H', 4.0 );
524  small_mover_fa->angle_max( 'E', 4.0 );
525  small_mover_fa->angle_max( 'L', 4.0 );
526 
528  shear_mover_fa->angle_max( 'H', 4.0 );
529  shear_mover_fa->angle_max( 'E', 4.0 );
530  shear_mover_fa->angle_max( 'L', 4.0 );
531 
532  backbone_mover_fa->add_mover(small_mover_fa, 1.0);
533  backbone_mover_fa->add_mover(shear_mover_fa, 1.0);
534 
535  /////////////////fullatom Monte Carlo//////////////////////////////////////////////////////////
536  //make the monte carlo object
537  MonteCarloOP mc_fa( new MonteCarlo( pose, *fullatom_scorefunction_, option[ FloppyTail::refine_temp ].value() ) );
538 
539  /////////////////////////////////rotamer trials mover///////////////////////////////////////////
545  mc_fa,
546  0.01 /*energycut*/ ) );
547 
548  /////////////////////////////////////////refine loop///////////////////////////////////////////
549  core::Size const refine_applies = option[ FloppyTail::refine_cycles ].value(); //default 5
550  core::Size const repack_cycles = option[ FloppyTail::refine_repack_cycles ].value();
551  core::Size const min_cycles = repack_cycles/2;
552  core::Size const switch_movemaps(core::Size(core::Real(refine_applies) * option[ FloppyTail::short_tail::short_tail_off ]));
553  TR << " Current Low total cycles =" << refine_applies << std::endl;
554  for ( core::Size i(1); i <= refine_applies; ++i ) {
555  if( i == switch_movemaps ){
556  small_mover_fa->movemap(movemap_);
557  shear_mover_fa->movemap(movemap_);
558  }
559  if( (i % repack_cycles == 0) || (i == refine_applies) ) { //full repack
560  pack_mover->apply(pose);
561  TAmin_mover_fa->apply(pose);
562  } else if ( i % min_cycles == 0 ) { //minimize
563  TAmin_mover_fa->apply(pose);
564  } else {
565  backbone_mover_fa->apply(pose);
566  rt_mover->apply(pose);
567  }
568 
569  mc_fa->boltzmann(pose);
570  TR << i << " " << mc_fa->last_accepted_score() << " " << mc_fa->lowest_score() << std::endl;
571  }//end the exciting for loop
572  mc_fa->recover_low( pose );
573 
574  //let's store some energies/etc of interest
575  //this code is specific to the E2/RING/E3 system for which this code was written; it is refactored elsewhere
576  // BARAK: this line should be commented out if applied to other systems
577  //SML 2/1/11: it's now under commandline control
578  if ( basic::options::option[ basic::options::OptionKeys::FloppyTail::publication].value()) protocols::floppy_tail::create_extra_output(pose, fullatom_scorefunction_);
579 
580  (*fullatom_scorefunction_)(pose);
581  set_last_move_status(protocols::moves::MS_SUCCESS); //this call is unnecessary but let's be safe
582  return;
583 }
584 
585 } //floppy_tail
586 } //protocols