Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
KinematicMover.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 /// @brief Performs a kinematic closure move on a peptide segment
11 /// @author Daniel J. Mandell
12 /// @author Amelie Stein (amelie.stein@ucsf.edu), Oct 2012 -- next-generation KIC
13 
14 // Unit Headers
16 #include <numeric/kinematic_closure/bridgeObjects.hh>
17 #include <numeric/kinematic_closure/kinematic_closure_helpers.hh>
18 //#include <protocols/loops/kinematic_closure/KinematicPerturber.hh>
19 
20 // Rosetta Headers
21 #include <core/conformation/Conformation.hh> // DJM: may go away
23 // AUTO-REMOVED #include <core/chemical/ResidueTypeSet.hh> // DJM: may go away
24 #include <core/conformation/ResidueFactory.hh> // DJM: may go away
26 // AUTO-REMOVED #include <core/fragment/BBTorsionAndAnglesSRFD.hh>
27 // AUTO-REMOVED #include <core/fragment/FragData.hh>
28 #include <core/id/DOF_ID.hh>
29 // AUTO-REMOVED #include <core/kinematics/DomainMap.hh>
30 #include <basic/options/option.hh>
31 #include <core/pose/Pose.hh>
32 //#include <core/scoring/etable/Etable.hh>
33 //#include <core/scoring/etable/EtableEnergy.hh>
34 //#include <core/scoring/etable/count_pair/CountPairAll.hh>
35 //#include <core/scoring/etable/count_pair/CountPairFunction.hh>
36 //#include <core/scoring/etable/count_pair/CountPairFactory.hh>
37 //#include <core/scoring/NeighborList.hh>
40 // AUTO-REMOVED #include <core/scoring/ScoreFunctionFactory.hh>
42 // AUTO-REMOVED #include <basic/basic.hh>
43 #include <basic/Tracer.hh>
44 
45 #include <numeric/random/random.hh>
46 #include <numeric/random/random_permutation.hh>
47 
48 #include <numeric/xyzVector.hh>
49 
50 // option key includes
51 #include <basic/options/keys/loops.OptionKeys.gen.hh>
52 
53 // AUTO-REMOVED #include <basic/options/keys/run.OptionKeys.gen.hh>
54 
56 #include <core/id/TorsionID.hh>
58 #include <utility/vector1.hh>
59 #include <numeric/conversions.hh>
60 #include <boost/foreach.hpp>
61 
62 //Auto Headers
63 #define foreach BOOST_FOREACH
64 static numeric::random::RandomGenerator RG(43135);
65 static basic::Tracer TR("protocols.loops.loop_closure.kinematic_closure.KinematicMover");
66 
67 using namespace numeric::kinematic_closure;
68 using namespace core;
69 using namespace core::kinematics;
70 using namespace core::scoring;
71 
72 namespace protocols {
73 namespace loops {
74 namespace loop_closure {
75 namespace kinematic_closure {
76 
77 // default constructor
78 KinematicMover::KinematicMover() :
79  Mover(),
80  start_res_(2),
81  middle_res_(3),
82  end_res_(4),
83  seg_len_(3), // dummy value -- was previously uninitialized (!)
84  loop_begin_(2), // AS: start of the full loop -- dummy value
85  loop_end_(4),
86  idl_C_N_CA_(121.7),
87  idl_N_CA_C_(111.2),
88  idl_CA_C_N_(116.2),
89  idl_C_N_(1.32869),
90  idl_N_CA_(1.458),
91  idl_CA_C_(1.52326),
92  BANGLE_MEAN_(110.86), // from PDB
93  //BANGLE_MEAN=107.0; // from CHARMM (to coincide with mm_bend potential)
94  BANGLE_SD_(2.48),
95  BANGLE_MIN_(BANGLE_MEAN_ - (0.5 * BANGLE_SD_)),
96  //BANGLE_MIN = BANGLE_MEAN - (2.0 * BANGLE_SD);
97  //BANGLE_MIN = 102.7284756;
98  //BANGLE_MIN = 98.86848; // (to coincide with mm_bend potential)
99  BANGLE_MAX_(118.9353622),
100  //BANGLE_MAX = 115.07536; // (to coincide with mm_bend potential)
101  OMEGA_MEAN_(179.8),
102  OMEGA_SCALE_FACTOR_(2.375), // scale factor parameterized to reproduce pdb loop omega angles
103  //OMEGA_SD=9.15;
104  //OMEGA_MIN = OMEGA_MEAN - (0.5 * OMEGA_SD);
105  //MAX_SAMPLE_ITS_(2000), // DJM: deprecated in favor of loops::max_kic_perturber_samples
106  vary_bond_angles_(false),
107  sample_nonpivot_torsions_(true),
108  sweep_nonpivot_torsion_(false),
109  idealize_loop_first_(false),
110  do_rama_check_(false),
111  do_hardsphere_bump_check_(true),
112  do_sfxn_eval_every_iteration_(false),
113  sfxn_( NULL ),
114  last_move_succeeded_ (false),
115  temperature_(1.0),
116  bump_overlap_factor_( basic::options::option[ basic::options::OptionKeys::loops::kic_bump_overlap_factor ]() ), // 0.6; // 0.8; // 0.8^2, allows some atomic overlap
117  taboo_map_max_capacity_(0.95) // how full can the taboo map get before we re-set it? --> the higher, the more likely are almost-endless loops -- but if the value is too low it's not actual taboo sampling
118 
119  {
121  Mover::type( "KinematicMover" );
122  set_defaults(); // doesn't do anything in this implementation
123  }
124 
125 // default destructor
127 
128 void KinematicMover::set_pivots( Size start_res, Size middle_res, Size end_res )
129 {
132  end_res_ = end_res;
133 
134  seg_len_ = end_res_ - start_res_ + 1;
135  //if these are bad data, we're in trouble!
136  runtime_assert(start_res != 0);
137  runtime_assert(middle_res != 0);
138  runtime_assert(end_res != 0);
139  runtime_assert(start_res != middle_res);
140  runtime_assert(middle_res != end_res);
141  runtime_assert(end_res != start_res);
142 }
143 
144 // boundaries of the current loop, needed for torsion bin lookup and offset in torsion-restricted & taboo sampling
145 void KinematicMover::set_loop_begin_and_end( Size loop_begin, Size loop_end )
146 {
149 }
150 
152 {
154 }
155 
157 {
159 }
160 
161 void
163 {
164  perturber_ = perturber_in;
165  perturber_->set_kinmover( this );
166 }
167 
169 {
171 }
172 
174 {
176 }
177 
179 {
181 }
182 
184 {
186 }
187 
188 void KinematicMover::set_rama_check( bool do_rama )
189 {
191 }
192 
194 {
196 }
197 
199 {
200  do_hardsphere_bump_check_ = do_bump_check;
201 }
202 
204 {
206 }
207 
209 {
210  do_sfxn_eval_every_iteration_ = do_sfxn_eval;
211 }
212 
214 {
215  sfxn_ = sfxn_in;
216 }
217 
218 
219 
221  sweep_nonpivot_torsion_ = sweep;
222 }
223 
224 /// @details This must be set before the other properties
225 /// (torsion angles, starting angles, step sizes, nsteps)
226 /// are set.
228 {
229  nonpivot_res_to_sweep_ = resids;
230 }
231 
233 {
234  assert( nonpivot_res_to_sweep_.size() == bbtorids.size() );
235  sweep_torsion_ids_ = bbtorids;
236 }
237 
239 {
240  assert( nonpivot_res_to_sweep_.size() == angles_in_degrees.size() );
241  sweep_nonpivot_torsion_starts_ = angles_in_degrees;
242 }
243 
245 {
246  assert( nonpivot_res_to_sweep_.size() == angle_steps_in_degrees.size() );
247  sweep_step_sizes_ = angle_steps_in_degrees;
248 }
249 
250 /// @details Initializes the LexicographicalIterator
252 {
253  assert( nonpivot_res_to_sweep_.size() == nsteps.size() );
254  sweep_iterator_.set_dimension_sizes( nsteps );
255 }
256 
258 {
259  return !sweep_iterator_.at_end();
260 }
261 
262 
263 
265 {
266  temperature_=temp_in;
267 }
268 
269 bool KinematicMover::check_rama(Real old_rama_score, Real new_rama_score) {
270  if ( new_rama_score > old_rama_score ) {
271  Real const boltz_factor = (old_rama_score - new_rama_score)/temperature_;
272  Real const probability = std::exp(std::max(Real(-40.0),boltz_factor) );
273  if ( RG.uniform() >= probability ) return( false );
274  }
275  return( true );
276 }
277 
279 {
280  return last_move_succeeded_;
281 }
282 
283 
285 {
286  //scoring::Ramachandran const & rama( core::scoring::ScoringManager::get_instance()->get_Ramachandran() );
287  using numeric::conversions::radians;
288  using numeric::conversions::degrees;
289  using numeric::random::RG;
290  using core::id::AtomID;
291  last_move_succeeded_=false;
292 
293  // DJM: debug
294  //TR << "from " << start_res_ << " to " << end_res_ << std::endl;
295 
296  // inputs to loop closure
298  utility::vector1<Size> pivots (3), order (3);
299  // outputs from loop closure
300  utility::vector1<utility::vector1<Real> > t_ang, b_ang, b_len;
301  int nsol=0;
302  // for eliminating identical solutions
304  utility::vector1<Real> dt_ang, db_len, db_ang, save_t_ang, save_b_len, save_b_ang, R0 (3);
306 
307  Size middle_offset = middle_res_ - start_res_; // is used to set central pivot atom
308  Size seg_len = 1 + end_res_ - start_res_; // length of the closure chain
309  //Size detail_sol = 0; // index of the KIC solution accepted for detailed balance, if > 0
310  atoms.resize((seg_len + 2) * 3); // one extra residue on each side to establish the geometric frame
311 
312  // KC requires 3 backbone atoms 1 residue N-terminal to start pivot and 1 residue C-terminal to end pivot
313  // so check for terminal pivots and compute coordinates from prepended / appended residues if necessary
314  if (pose.residue(start_res_).is_lower_terminus()) {
315  // make a copy of the lower terminal residue
316  conformation::ResidueOP nterm_copy( conformation::ResidueFactory::create_residue(
317  pose.conformation().residue(start_res_).type(),
318  pose.conformation().residue(start_res_),
319  pose.conformation(),
320  false ) );
321  // now create another residue of the same type to prepend
322  conformation::ResidueOP pre_nterm( conformation::ResidueFactory::create_residue(
323  pose.residue(start_res_).type() ) );
324  // create a new conformation containing the n-term copy
326  extn.append_residue_by_bond( *nterm_copy );
327  // attached the pre_nterm residue to the nterm copy
328  extn.safely_prepend_polymer_residue_before_seqpos( *pre_nterm, 1, true );
329  // set ideal omega angle at junction
330  extn.set_torsion( id::TorsionID( 1, id::BB, 3 ), OMEGA_MEAN_);
331  // store the xyz coords for KC from the first 3 atoms of the pre-nterm residue into the first 3 atoms indices
332  Size ind=1;
333  for (Size j=1; j<=3; j++) {
334  atoms[ind].resize(3);
335  atoms[ind][1] = static_cast<Real> (extn.residue(1).xyz(j).x());
336  atoms[ind][2] = static_cast<Real> (extn.residue(1).xyz(j).y());
337  atoms[ind][3] = static_cast<Real> (extn.residue(1).xyz(j).z());
338  ind++;
339  }
340  }
341 
342  // check for upper terminus
343  if (pose.residue(end_res_).is_upper_terminus()) {
344  // make a copy of the upper terminal residue
345  conformation::ResidueOP cterm_copy( conformation::ResidueFactory::create_residue(
346  pose.conformation().residue(end_res_).type(),
347  pose.conformation().residue(end_res_),
348  pose.conformation(),
349  false ) );
350 
351  // now create another residue of the same type to append
352  conformation::ResidueOP post_cterm( conformation::ResidueFactory::create_residue(
353  pose.residue(end_res_).type() ) );
354  // create a new conformation containing the c-term copy
356  extn.append_residue_by_bond( *cterm_copy );
357  // attached the post_cterm residue to the cterm copy
358  extn.safely_append_polymer_residue_after_seqpos( *post_cterm, 1, true );
359  // set ideal omega angle at junction
360  extn.set_torsion( id::TorsionID( 2, id::BB, 3 ), OMEGA_MEAN_);
361  // store the xyz coords for KC from the first 3 atoms of the post-cterm residue into the last 3 atoms indices
362  Size ind=atoms.size()-2;
363  for (Size j=1; j<=3; j++) {
364  atoms[ind].resize(3);
365  atoms[ind][1] = static_cast<Real> (extn.residue(2).xyz(j).x());
366  atoms[ind][2] = static_cast<Real> (extn.residue(2).xyz(j).y());
367  atoms[ind][3] = static_cast<Real> (extn.residue(2).xyz(j).z());
368  ind++;
369  }
370  }
371 
372  // Get the current coords of the loop closure segment (if a pivot is terminal we took the coords above so skip)
373  Size ind = (pose.residue(start_res_).is_lower_terminus() ? 4 : 1);
374  for (Size i = (pose.residue(start_res_).is_lower_terminus() ? start_res_ : start_res_ - 1);
375  i <= (pose.residue(end_res_).is_upper_terminus() ? end_res_ : end_res_ + 1);
376  i++) {
377  conformation::Residue res=pose.residue(i);
378  for (Size j=1; j<=3; j++) { // DJM: just keeping N, CA, C atoms. We assume these are always the first 3. BAD -- PROTEIN ONLY ASSUMPTION -- How about metal ions with only 1 atom?
379  atoms[ind].resize(3);
380  atoms[ind][1] = static_cast<Real> (res.xyz(j).x());
381  atoms[ind][2] = static_cast<Real> (res.xyz(j).y());
382  atoms[ind][3] = static_cast<Real> (res.xyz(j).z());
383  ind++;
384  }
385  }
386 
387  /// Get alternative conformations from from kinematic loop closure
388  // Choose order to solve half-tangents
389  order[1]=1;
390  order[2]=2;
391  order[3]=3;
392  // Set the pivot atoms
393  Size pvatom1=5; // second C-alpha
394  Size pvatom2=5 + (3 * middle_offset); // middle res C-alpha
395  Size pvatom3=(3 * (seg_len+1)) - 1; // second-to-last C-alpha
396  pivots[1]=pvatom1;
397  pivots[2]=pvatom2;
398  pivots[3]=pvatom3;
399 
400 
401  // chainTORS is used to get dt to remove solutions identical to original torsions
402  // DJM: it would be quicker to store the last torsions rather than recomputing them,
403  // but we use db_ang and db_len below so it's worth it for now. However, we should
404  // be able to get the torsions, bond angles, and bond lengths from the atom_tree now.
405  chainTORS(atoms.size(), atoms, dt_ang, db_ang, db_len, R0, Q0);
406 
407  // save the previous torsions, lengths and angles to restore if no solution is found
408  if (! idealize_loop_first_) {
409  save_t_ang.resize(dt_ang.size());
410  save_b_ang.resize(db_ang.size());
411  save_b_len.resize(db_len.size());
412  for (Size i=1; i<=dt_ang.size(); i++) {
413  save_t_ang[i] = dt_ang[i];
414  save_b_ang[i] = db_ang[i];
415  save_b_len[i] = db_len[i];
416  }
417  }
418 
419  // idealize the loop if requested
420  if (idealize_loop_first_) {
421  // save a backbup of the non-ideal residues in case closure fails
422  save_residues.resize(seg_len);
423  for (Size seqpos=start_res_, i=1; seqpos<=end_res_; seqpos++, i++) {
424  conformation::ResidueOP saveres=pose.conformation().residue( seqpos ).clone();
425  save_residues[i]=saveres;
426  }
427 
428  // set all bond lengths, angles, and omegas for closure to ideal values
429 
430  // check sizes to prevent memory crashes:
431  for (Size i=1; i<=atoms.size(); i+=3) {
432  if( db_ang.size() >= (i) ) db_ang[i]=idl_C_N_CA_;
433  if( db_ang.size() >= (i+1) ) db_ang[i+1]=idl_N_CA_C_;
434  if( db_ang.size() >= (i+2) ) db_ang[i+2]=idl_CA_C_N_;
435  if( db_len.size() >= (i) ) db_len[i]=idl_N_CA_;
436  if( db_len.size() >= (i+1) ) db_len[i+1]=idl_CA_C_;
437  if( db_len.size() >= (i+2) ) db_len[i+2]=idl_C_N_;
438  if( dt_ang.size() >= (i+2) ) dt_ang[i+2]=OMEGA_MEAN_;
439  }
440  // setting pose omegas here, don't set them later!
441  for ( Size i= start_res_; i<= end_res_; ++i ) {
442  conformation::idealize_position( i, pose.conformation() ); // this is coupled to above values!
443  pose.set_omega(i, OMEGA_MEAN_);
444  }
445  }
446 
447  // If preserving detailed balance, compute the Rosenbluth factor for the before state
448  // W_before = rosenbluth_factor( atoms, save_t_ang, save_b_ang, save_b_len, pivots, order, t_ang, b_ang, b_len, nsol );
449  // DJM: currently bridgeObjects will be applying save* transformations to atoms, which isn't necessary. Maybe in option in bridge not to?
450 
451  for (Size nits=1; nits <= perturber_->max_sample_iterations(); ++nits ) { // try these pivots until a solution passes all filters or nits > perturber_->max_sample_iterations()
452 
453  //make sure the perturber can still generate solutions
454  if( perturber_->perturber_exhausted() ) break;
455 
456  perturber_->perturb_chain( pose, dt_ang, db_ang, db_len );
457 
458  // Perform loop closure
459  //TR.Debug << "calling bridgeObjects" << std::endl;
460  bridgeObjects(atoms, dt_ang, db_ang, db_len, pivots, order, t_ang, b_ang, b_len, nsol);
461 
462  // If preserving detailed balance, try performing detailed balance move here
463  //if( preserve_detailed_balance_ ) {
464  //detail_sol = check_detailed_balance( W_before, t_ang, b_ang, b_len, nsol ); // DJM: should be able to used chainXYZ to recreate the segments
465  //if detail_sol != 0 { // accepted a move by detailed balance
466  // DJM: next want to pre-screen for detailed balance acceptance, or only consider solns for detailed balance check if pass sterics and Rama
467  //last_move_succeeded_ = true;
468  //return;
469  //}
470  //else continue;
471  //}
472 
473  utility::vector1<Size> pos(nsol);
474  for (int i=1; i<=nsol; i++) {
475  pos[i]=i;
476  }
477 
478  //std::random__shuffle(pos.begin(), pos.end());
479  numeric::random::random_permutation(pos.begin(), pos.end(), RG);
480 
481  // Look for solutions passing NaN, Rama, bump checks and eventual filters
482  for (Size i=nsol; i>=1; i--) {
483  //TR << "KINMOVER checking sol " << nsol - i + 1 << " of " << nsol << " .. "; // DJM: debug
484  // make sure no torsions are NaN, Inf, or otherwise unreasonable
485  if ( ! ( ( -360.0 <= t_ang[pos[i]][pivots[1]-1] ) && (t_ang[pos[i]][pivots[1]-1] <= 360.0) ) ||
486  ! ( ( -360.0 <= t_ang[pos[i]][pivots[1]] ) && (t_ang[pos[i]][pivots[1]] <= 360.0) ) ||
487  ! ( ( -360.0 <= t_ang[pos[i]][pivots[2]-1] ) && (t_ang[pos[i]][pivots[2]-1] <= 360.0) ) ||
488  ! ( ( -360.0 <= t_ang[pos[i]][pivots[2]] ) && (t_ang[pos[i]][pivots[2]] <= 360.0) ) ||
489  ! ( ( -360.0 <= t_ang[pos[i]][pivots[3]-1] ) && (t_ang[pos[i]][pivots[3]-1] <= 360.0) ) ||
490  ! ( ( -360.0 <= t_ang[pos[i]][pivots[3]] ) && (t_ang[pos[i]][pivots[3]] <= 360.0) ) ) {
491  TR << "solution " << i << " of " << nsol << " failed NaN / Inf check. Skipping..." << std::endl;
492  TR << "failed NaN t_ang matrix: " << std::endl;
493  printMatrix(t_ang);
494  continue;
495  }
496 
497  //if (!perform_rama_check(pose, t_ang[i], pivots, start_res, seg_len)) { // checks all loop residues
498  if (!perform_rama_check(pose, t_ang[pos[i]], pivots, start_res_, middle_res_, end_res_)) { // checks only pivot residues
499  //TR << "Rama continue" << std::endl; // DJM: debug
500  continue;
501  }
502  // place the solution into the pose and bump check+eventual filters
503  // set the torsions
504  perturber_->set_pose_after_closure( pose, t_ang[pos[i]], b_ang[pos[i]], b_len[pos[i]], true );
505 
506  // AS: fetch & set the torsion string for Taboo Sampling
508 
509 
510  //now check if the pose passes all the filters
511  if( do_hardsphere_bump_check_ && !perform_bump_check(pose, start_res_, end_res_) ){
512  continue;
513  }
514 
515  if( do_sfxn_eval_every_iteration_ ) (*sfxn_)( pose );
516 
517  if( filters_.size() != 0 ){
518  bool all_filters_passed( true );
519  foreach(protocols::filters::FilterCOP filter, filters_){
520  if( ! filter->apply( pose ) ) {
521  all_filters_passed = false;
522  break;
523  }
524  }
525  if ( !all_filters_passed ){
526  continue;
527  }
528  }
529 
530  last_move_succeeded_ = true;
531  //std::cerr << "kinmover success after " << nits << "... ";
532  return;
533  }
534  } //for (Size nits=1; nits <= MAX_SAMPLE_ITS_; ++nits )
535 
536  // prepare to exit here if no solutions
537  last_move_succeeded_ = false;
538  //TR << "!!!last move not succeeded to pass filters" << std::endl;
539 
540  //// no solution found. restore the old pose
541  if (! idealize_loop_first_) { // if we didn't idealize, we only changed the torsions and N_CA_C bond angles
542 
543  perturber_->set_pose_after_closure( pose, save_t_ang, save_b_ang, save_b_len, false );
544 
545  }
546  else { // loop residues were idealized so restore from saved non-ideal residues
547  for (Size seqpos=start_res_, i=1; seqpos<=end_res_; seqpos++, i++) {
548  pose.conformation().replace_residue(seqpos, *save_residues[i], false);
549  }
550  }
551 
552  //TR << "\tnumber of its: " << nits << std::endl;
553  return;
554 
555 } //new_apply
556 
559  return "KinematicMover";
560 }
561 
562 // checks if pivot solutions are within vicinity degrees of current pivot torsion values
563 // DJM: currently not used because it significantly reduces the number of accepted moves
564  /* AS Oct 03, 2012 -- commenting this out for vicinity refactoring
565 bool KinematicMover::pivots_within_vicinity(
566  core::pose::Pose const & pose,
567  utility::vector1<Real> const & t_ang,
568  utility::vector1<Size> const & pivots,
569  Size const start_res,
570  Size const middle_res,
571  Size const end_res
572  )
573 {
574  Real old_phi, new_phi, old_psi, new_psi; // torsions before and after the move is applied
575 
576  // check start_res
577  new_phi = t_ang[pivots[1]-1];
578  new_psi = t_ang[pivots[1]];
579  old_phi = pose.phi(start_res);
580  old_psi = pose.psi(start_res);
581  if ( ( std::abs( new_phi - old_phi ) > degree_vicinity_ ) || ( std::abs( new_psi - old_psi ) > degree_vicinity_ ) )
582  return false;
583 
584  // check middle_res
585  new_phi = t_ang[pivots[2]-1];
586  new_psi = t_ang[pivots[2]];
587  old_phi = pose.phi(middle_res);
588  old_psi = pose.psi(middle_res);
589  if ( ( std::abs( new_phi - old_phi ) > degree_vicinity_ ) || ( std::abs( new_psi - old_psi ) > degree_vicinity_ ) )
590  return false;
591 
592  // check end_res
593  new_phi = t_ang[pivots[3]-1];
594  new_psi = t_ang[pivots[3]];
595  old_phi = pose.phi(end_res);
596  old_psi = pose.psi(end_res);
597  if ( ( std::abs( new_phi - old_phi ) > degree_vicinity_ ) || ( std::abs( new_psi - old_psi ) > degree_vicinity_ ) )
598  return false;
599 
600  // all passed
601  return true;
602 }
603 */
604 
605 // this version checks rama for all residues in loop segment
607  core::pose::Pose const & pose,
608  utility::vector1<Real> const & t_ang,
609  utility::vector1<Size> const & pivots,
610  Size const start_res,
611  Size const seg_len
612 )
613 {
615  Real old_phi, new_phi, old_psi, new_psi; // torsions before and after the move is applied
616  Real old_rama_score, new_rama_score; // rama scores before and after the move is applied
617 
618  for (Size offset=0; offset<seg_len; offset++) { // offset is natoms into kic segment
619  conformation::Residue const & current_rsd( pose.residue(start_res+offset) );
620  new_phi = t_ang[pivots[1]+(3*offset)-1];
621  new_psi = t_ang[pivots[1]+(3*offset)];
622  new_rama_score = rama.eval_rama_score_residue( current_rsd.aa(), new_phi, new_psi );
623  if (new_rama_score == 20.0) {
624  //std::cout << "Rama fail" << std::endl;
625  return false;
626  }
627  old_psi = pose.psi(start_res+offset);
628  old_phi = pose.phi(start_res+offset);
629  old_rama_score = rama.eval_rama_score_residue( current_rsd.aa(), old_phi, old_psi );
630  if (!check_rama(old_rama_score, new_rama_score)) {
631  // DJM: debug
632  // TR << "Residue " << start_res + offset << " failed Rama. old_rama_score: " << old_rama_score
633  // << " new_rama_score " << new_rama_score << std::endl;
634  ///std::cout << "Rama fail" << std::endl;
635  return false; // failed rama check
636  }
637  }
638  return true; // passed rama check
639 }
640 
641 // this version only checks rama for pivot residues
643  core::pose::Pose const & pose,
644  utility::vector1<Real> const & t_ang,
645  utility::vector1<Size> const & pivots,
646  Size const start_res,
647  Size const middle_res,
648  Size const end_res
649 )
650 {
652  Real old_phi, new_phi, old_psi, new_psi; // torsions before and after the move is applied
653  Real old_rama_score, new_rama_score; // rama scores before and after the move is applied
654 
655  // check start_res
656  conformation::Residue const & start_rsd( pose.residue(start_res) );
657  new_phi = t_ang[pivots[1]-1];
658  new_psi = t_ang[pivots[1]];
659  new_rama_score = rama.eval_rama_score_residue( start_rsd.aa(), new_phi, new_psi );
660  if (new_rama_score == 20.0) {
661  //TR << "score for pivot 1 was 20. returning false" << std::endl;
662  ///std::cout << "Rama fail" << std::endl;
663  return false;
664  }
665  old_phi = pose.phi(start_res);
666  old_psi = pose.psi(start_res);
667  old_rama_score = rama.eval_rama_score_residue( start_rsd.aa(), old_phi, old_psi );
668  // DJM: debug
669  //TR << "new_phi, new_psi, rama score: " << new_phi << " " << new_psi << " " << new_rama_score << std::endl;
670  if (!check_rama(old_rama_score, new_rama_score)) {
671  // DJM: debug
672  // TR << "Residue " << start_res + offset << " failed Rama. old_rama_score: " << old_rama_score
673  // << " new_rama_score " << new_rama_score << std::endl;
674  ///std::cout << "Rama fail" << std::endl;
675  return false; // failed rama check
676  }
677 
678  // check middle_res
679  conformation::Residue const & middle_rsd( pose.residue(middle_res) );
680  new_phi = t_ang[pivots[2]-1];
681  new_psi = t_ang[pivots[2]];
682  new_rama_score = rama.eval_rama_score_residue( middle_rsd.aa(), new_phi, new_psi );
683  if (new_rama_score == 20.0) {
684  //TR << "score for pivot 2 was 20. returning false" << std::endl;
685  //std::cout << "Rama fail" << std::endl;
686  return false;
687  }
688  old_phi = pose.phi(middle_res);
689  old_psi = pose.psi(middle_res);
690  old_rama_score = rama.eval_rama_score_residue( middle_rsd.aa(), old_phi, old_psi );
691  if (!check_rama(old_rama_score, new_rama_score)) {
692  // DJM: debug
693  // TR << "Residue " << start_res + offset << " failed Rama. old_rama_score: " << old_rama_score
694  // << " new_rama_score " << new_rama_score << std::endl;
695  ///std::cout << "Rama fail" << std::endl;
696  return false; // failed rama check
697  }
698 
699  // check end_res
700  conformation::Residue const & end_rsd( pose.residue(end_res) );
701  new_phi = t_ang[pivots[3]-1];
702  new_psi = t_ang[pivots[3]];
703  new_rama_score = rama.eval_rama_score_residue( end_rsd.aa(), new_phi, new_psi );
704  if (new_rama_score == 20.0) {
705  //TR << "score for pivot 3 was 20. returning false" << std::endl;
706  //std::cout << "Rama fail" << std::endl;
707  return false;
708  }
709  old_phi = pose.phi(end_res);
710  old_psi = pose.psi(end_res);
711  old_rama_score = rama.eval_rama_score_residue( end_rsd.aa(), old_phi, old_psi );
712  if (!check_rama(old_rama_score, new_rama_score)) {
713  // DJM: debug
714  // TR << "Residue " << start_res + offset << " failed Rama. old_rama_score: " << old_rama_score
715  // << " new_rama_score " << new_rama_score << std::endl;
716  //std::cout << "Rama fail" << std::endl;
717  return false; // failed rama check
718  }
719 
720  // DJM: debug - print out all the rama score
721 /*
722  TR << "All residues passed Rama. Scores follow:" << std::endl;
723  for (Size i=start_res; i<=end_res; i++) {
724  Real cur_phi = pose.phi(i);
725  Real cur_psi = pose.psi(i);
726  conformation::Residue const & cur_rsd( pose.residue(i) );
727  Real cur_rama_score = rama.eval_rama_score_residue( cur_rsd.aa(), cur_phi, cur_psi);
728  TR << "Res " << i << ": " << cur_rama_score << std::endl;
729  }
730 */
731  return true; // passed rama check
732 }
733 
734 
735 // perform_bump_check
736 // 1. loop over all residues in the loop
737 // 2. for each loop residue, grab the neighbor atom's xyz
738 // 3. for every other residue res2 in the protein:
739 // 4. grab the neighbor atom of res2
740 // 5. grab the neighbor radii of res1.nbratom and res2.nbratom (make sure these are sensible)
741 // 6. see if res1 and res2 are close enough to be considered neighbors. if so:
742 // 7. for each main_chain atom in res1,
743 // 8. for each main_chain atom in res2
744 // 9. if any of these atoms is within dist_cutoff, clash is true
745 
746 // returns true if bump check is passed, false if it fails
747 bool
749  core::pose::Pose const & pose,
750  Size const start_res,
751  Size const end_res
752 )
753 {
754  // iterate over loop residues
755  //bool passed_but_no_neighbor=true; // DJM: neighbor filter
756  //int no_neighbor_res=0; // DJM: neighbor filter
757  for (Size i=start_res; i<= end_res; i++) {
758  conformation::Residue const & rsd1 = pose.conformation().residue(i);
759  // get the xyz vector of the atom of this residue used for neighbor detection
760  Vector const & nbr_i( rsd1.xyz( rsd1.nbr_atom() ) );
761  // iterate over all other residues in the protein
762  //bool had_neighbor = false; // DJM: neighbor filter
763  for (Size j=1; j <= pose.total_residue(); j++ ) {
764  if ((j == i) || (j == i+1) || (j == i-1)) continue; // don't do same or adjacent residues
765  if ((j >= start_res) && (j <= i)) continue; // don't do loop residues multiple times
766  conformation::Residue const & rsd2 = pose.conformation().residue(j);
767  // get the xyz vector fo the atom of this residue used for neighbor detection
768  Vector const & nbr_j( rsd2.xyz( rsd2.nbr_atom() ) );
769  // determine the neighbor cutoff from the radii of the neighbor atoms
770  Real const nbrcutoff = ( rsd1.nbr_radius() + rsd2.nbr_radius()) ;
771  Real const nbrcutoff2 = nbrcutoff * nbrcutoff; // use squared neighbor cutoff
772  //if ( (nbr_i - nbr_j).length_squared() < nbrcutoff2 * 2 ) had_neighbor = true; // DJM: neighbor filter
773  if ( (nbr_i - nbr_j).length_squared() > nbrcutoff2 ) continue;
774  //else had_neighbor = true; // DJM: neighbor filter
775  // now check for clashes between the atoms of the two residues
776  Size max_res1_heavyatoms = std::min( Size (5), rsd1.nheavyatoms() ); // keep N,CA,C,O (and CB if not Gly)
777  for (Size m=1; m<= max_res1_heavyatoms; m++) {
778  Size max_res2_heavyatoms;
779  if ( rsd2.is_protein() ) max_res2_heavyatoms = std::min( Size (5), rsd2.nheavyatoms() );
780  else max_res2_heavyatoms = rsd2.nheavyatoms(); // rsd2 is a ligand, check all atoms
781  for (Size n=1; n<= max_res2_heavyatoms; n++) {
782  Vector const & atom_i( rsd1.xyz( m ) );
783  Vector const & atom_j( rsd2.xyz( n ) );
784  // dist cutoff will be squared sum of LJ radii
785  Real lj_sum = (rsd1.atom_type(m).lj_radius() + rsd2.atom_type(n).lj_radius());
786  //dist_cutoff2 = lj_sum;
787  Real dist_cutoff2 = (lj_sum * lj_sum) * bump_overlap_factor_;
788  Real dist2 = ( atom_i - atom_j ).length_squared();
789  if ( dist2 < dist_cutoff2 ) {
790  // clash
791  //TR << "clash: " << std::endl;
792  //TR << "\t Loop residue " << i << ", atom " << m << ", atom_type " << rsd1.atom_type(m).name() << std::endl;
793  //TR << "\t Other residue " << j << ", atom " << n << ", atom_type " << rsd2.atom_type(n).name() << std::endl;
794  //TR << "dist2 was " << ( atom_i - atom_j ).length_squared() << std::endl;
795  //TR << "and dist_cutoff2 was " << dist_cutoff2 << std::endl;
796  //pose.dump_pdb("clash_test.pdb");
797  //exit(0);
798  //break;
799  //std::cout << "Bump fail" << std::endl;
800  return false;
801  }
802  //else {
803  // TR << "bump check passed res " << i << ", atom " << m << " against res " << j << ", atom " << n << std::endl;
804  //}
805  }
806  }
807  }
808  // DJM: neighbor filter
809  /*
810  if (had_neighbor == false) {
811  passed_but_no_neighbor = true;
812  no_neighbor_res = i;
813  TR << "Pose passed rama and bump check but resid " << no_neighbor_res << " has no neighbors." << std::endl;
814  return false;
815  }
816  */
817  }
818 
819  //TR << "\tNO CLASHES!" << std::endl;
820  //TR << "t_ang" << std::endl;
821  //printVector(t_ang[i]);
822  //TR << "b_ang" << std::endl;
823  //printVector(b_ang[i]);
824  //pose.dump_pdb("no_clash.pdb");
825  //exit(0);
826  return true; // passed bump check
827 }
828 
829 // set default options
830 // AS -- after vicinity refactoring, only the perturber knows about vicinity sampling -- for now this function doesn't do anything any more...
831 void
833  using namespace core;
834  using namespace basic::options;
835 
836  return;
837 }
838 
839  /// @brief Taboo Sampling functions
840  /// @author Amelie Stein
841  /// @date Thu May 17 13:23:52 PDT 2012
842 
843  void
845  {
846 
847  // note: it would be much better to implement this as a vector/map of strings, that then redirect to the corresponding taboo map -- otherwise we lose all information the moment we change loops, which will happen a lot when remodeling multiple loops -- TODO
848  // in other words, this implementation is only intended for remodeling single loops
849 
850  if (sequence != sequence_) { // is there an actual change?
851 
852  if (sequence_.size() > 0) {
853  // store last used taboo_map_ along with the corresponding sequence
854  /*
855  TR << "storing taboo map for "; // debug/testing info
856  for (Size i = 1; i <= sequence_.size(); i++)
857  TR << sequence_[i] << " " ;
858  TR << " (" << loop_begin_ << "-" << loop_end_ << ")" << std::endl; // actually I'm not sure when loop_begin_ and loop_end_ are updated...
859  */
861  }
862 
863  sequence_ = sequence;
864  taboo_map_.clear();
865  if (taboo_master_map_.find(sequence) != taboo_master_map_.end()) {
866  /*
867  TR << "reloading taboo map for "; // debug/testing info
868  for (Size i = 1; i <= sequence.size(); i++)
869  TR << sequence[i];
870  TR << " (" << loop_begin_ << "-" << loop_end_ << ")" << std::endl;
871  */
872  taboo_map_ = taboo_master_map_[sequence]; // reload from previous use, if possible
873  }
874  //random_torsion_strings_.clear();
875  perturber_->clear_torsion_string_stack(); // only affects the TabooSampling perturber for now
876  }
877  }
878 
879  // the TabooSamplingKinematicPerturber must access this to derive the appropriate torsion bins
882  {
883  return sequence_;
884  }
885 
886  void
888  {
889  if (sequence_.size() > 0 && taboo_map_.size() > pow(4, sequence_.size()) * taboo_map_max_capacity_) {
890  TR << "Taboo map filled to " << taboo_map_max_capacity_*100 << "% capacity, clearing the map to avoid almost-endless loops. " << taboo_map_.size() << std::endl;
891  taboo_map_.clear();
892  }
893 
894  taboo_map_[ts] = true;
895  }
896 
897  bool
899  {
900  return taboo_map_.find(ts) != taboo_map_.end();
901  }
902 
903 
904  /// @brief returns the frequency of torsion_bin at position pos in the current taboo map, used for shifting probabilities of sampled torsion bins in later rounds
905  core::Real
906  KinematicMover::frequency_in_taboo_map( core::Size const & pos, char const & torsion_bin ) const {
907 
908  if (taboo_map_.size() == 0)
909  return 0;
910 
911  core::Size counter = 0;
912  if (pos >= sequence_.size()) {
913  TR << "error -- position " << pos << " exceeds the current taboo map string" << std::endl;
914  return counter;
915  } // assumption: all strings in the taboo map have the same size, and pos is within these bounds
916  for (std::map< std::string, bool >::const_iterator mi = taboo_map_.begin(); mi != taboo_map_.end(); mi++) {
917  counter += ( (mi->first)[pos] == torsion_bin ); // this might be slow...
918  }
919  return core::Real(counter)/taboo_map_.size();
920  }
921 
922 
923  ///@brief bin torsion angles as described in http://www.ncbi.nlm.nih.gov/pubmed/19646450
924  ///@detail generates a string with the torsion angle bins, using uppercase letters as in the publication above for omega ~ 180, and lowercase letters for omega ~ 0; to be used in loop sampling analysis -- same as in the LoopMover implementation...
925  ///@author Amelie Stein
926  ///@date April 26, 2012
928  {
929  std::string torsion_bins, pos_bin;
930  // assumption: we have only one loop ...
931  for ( core::Size i = loop_begin_; i <= loop_end_; i++ ) {
932  torsion_bins += core::conformation::get_torsion_bin(pose.phi(i), pose.psi(i), pose.omega(i));
933  }
934  return torsion_bins;
935  } // torsion_features_string
936 
937 
938 } // namespace kinematic_closure
939 } // namespace loop_closure
940 } // namespace loops
941 } // namespace protocols