Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
KinematicPerturber.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/loop_closure/kinematic_closure/KinematicPerturber.cc
11 /// @brief implementations for KinematicPerturbers used by the kinematic mover
12 /// @author Florian Richter, floric@u.washington.edu, march 2009
13 /// @author Rhiju Das, rhiju@stanford.edu, 2011 -- options of cis/trans prolines, and turn off ca bond geometry variation.
14 /// @author Amelie Stein, amelie.stein@ucsf.edu, Oct 2012 -- vicinity sampling refactoring & new perturbers
15 
16 //Unit headers
18 
19 // Project headers
21 
22 // Rosetta Headers
23 #include <core/chemical/AA.hh>
24 
25 #include <core/pose/Pose.hh>
26 
28 
32 
33 #include <basic/Tracer.hh>
34 #include <basic/options/option.hh>
35 
36 // numeric headers
37 #include <numeric/random/random.hh>
38 #include <numeric/random/random_permutation.hh>
39 #include <numeric/conversions.hh>
40 
41 // option key includes
42 #include <basic/options/keys/loops.OptionKeys.gen.hh>
43 
45 #include <utility/vector1.hh>
46 
47 //Auto Headers
48 
49 
50 
51 namespace protocols {
52  namespace loops {
53  namespace loop_closure {
54  namespace kinematic_closure {
55 
56  static numeric::random::RandomGenerator RG(43134);
57  static basic::Tracer TR("protocols.loops.loop_closure.kinematic_closure.KinematicPerturber");
58 
60  : max_sample_iterations_( basic::options::option[ basic::options::OptionKeys::loops::max_kic_perturber_samples ]() )
61  {}
62 
64 
66 
68 
69  void
71  core::pose::Pose & pose,
72  utility::vector1<core::Real> const & torsions,
73  utility::vector1<core::Real> const &, //bond_ang,
74  utility::vector1<core::Real> const &, //bond_len,
75  bool //closure_successful
76  ) const
77  {
78 
79  core::Size start( kinmover_->start_res() );
80 
81  // AS: if any of the (potentially) omega-sampling flags is set, omega needs to be copied from the torsions vector
82  bool also_copy_omega = ( basic::options::option[ basic::options::OptionKeys::loops::sample_omega_at_pre_prolines ]() || basic::options::option[ basic::options::OptionKeys::loops::kic_omega_sampling ]() ) || ( basic::options::option[ basic::options::OptionKeys::loops::restrict_kic_sampling_to_torsion_string ].user() || basic::options::option[ basic::options::OptionKeys::loops::derive_torsion_string_from_native_pose ]() ) ;
83 
84  for( core::Size res = 0; res < kinmover_->segment_length(); res++ ){
85 
86  pose.set_phi( start + res, torsions[ (3*(res+1)) + 1 ] );
87  pose.set_psi( start + res, torsions[ (3*(res+1)) + 2 ] );
88  if ( also_copy_omega ) pose.set_omega( start + res, torsions[ (3*(res+1)) + 3 ] );
89 
90  }
91  } //set_pose_after_closure
92 
93  ///////////////////////////////////////////////////////////////////////////////////////////
94  //////////////////////////////////TorsionSamplingKinematicPerturber////////////////////////
95  ///////////////////////////////////////////////////////////////////////////////////////////
96 
99  vary_ca_bond_angles_(false),
100  sample_omega_for_pre_prolines_( basic::options::option[ basic::options::OptionKeys::loops::sample_omega_at_pre_prolines ]() ),
101  rama_( core::scoring::ScoringManager::get_instance()->get_Ramachandran() )
102  { set_kinmover( kinmover_in ); }
103 
105 
106  ///@details randomly varies the torsions (and possibly the bond angles) for the loop. Respects a MoveMap, if present, for torsions. Does NOT respect the movemap for angles; does NOT cause any sort of interactions between the MoveMap and the KinematicMover's pivot residues.
107  void
109  core::pose::Pose const & pose,
110  utility::vector1<core::Real> & torsions,
111  utility::vector1<core::Real> & bond_ang,
112  utility::vector1<core::Real> & //bond_len
113  )
114  {
116 
117  if( vary_ca_bond_angles_ ){
118 
119  core::Size pvatom3( (3* (kinmover_->segment_length() + 1)) - 1 );
120 
121  core::Real bangle_min( kinmover_->BANGLE_MIN() );
122  core::Real bangle_sd( kinmover_->BANGLE_SD() );
123 
124  //what is this iterating over?
125  for( Size i = 5; i <= pvatom3; i+=3 ) {
126  bond_ang[ i ] = bangle_min + RG.uniform() * bangle_sd;
127  }
128  }
129 
130 
131 
132  core::Size tor_end = torsions.size() - 3;
133 
134  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
135  //if(mm) TR << "current residue " << cur_res << "mm reports " << mm->get_bb(cur_res) << std::endl;
136 
137  if(!mm || mm->get_bb(cur_res)){ //if movemap is null, or (if not null) if movemap says mobile
138 
139  core::Real rama_phi, rama_psi;
140 
141  rama_.random_phipsi_from_rama(pose.aa(cur_res), rama_phi, rama_psi);
142 
143  torsions[i++]=rama_phi; // phi
144  torsions[i++]=rama_psi; // psi
145 
146  i++; // leave omega alone
147 
148  } else {
149  i += 3; //ensure i indexing increases
150  }
151 
152  }
153 
154 
155  // sample omegas?
156  // all omegas before prolines are assumed to be fair game. Note that we're not using move-map, which is phi/psi-specific.
158  // old KIC standard: coin flip between cis and trans
159  static const core::Real OMEGA_MEAN( 179.8 );
160 
161  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
162 
163  if ( pose.aa( cur_res+1 ) == core::chemical::aa_pro ) {
164 
165  i++; //phi
166  i++; //psi
167  torsions[i++] = ( static_cast<int>( RG.uniform()*2 ) ? OMEGA_MEAN : 0.0 ); // flip a coin -- either 179.8 (trans) or 0.0 (cis)
168 
169  } else {
170  i += 3;
171  }
172  }
173  } else if ( basic::options::option[ basic::options::OptionKeys::loops::kic_omega_sampling ]() ) {
174  // actual omega sampling, values from Berkholz et al., PNAS 2012
175  static const core::Real OMEGA_MEAN( 179.1 );
176  static const core::Real OMEGA_STDDEV( 6.3 );
177 
178  // cis or trans? -- cis is much less common than trans, according to data from Matt / top8000, so the current coinflip is probably overestimating cis
179  // as a proxy, using 1/1000 for now
180  static const core::Real cis_prob_threshold = 0.0001;
181 
182  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
183  i++; //phi
184  i++; //psi
185  core::Real trans_prob = 1;
186  if ( pose.aa( cur_res+1 ) == core::chemical::aa_pro ) {
187  trans_prob = RG.uniform();
188  }
189  if ( trans_prob < cis_prob_threshold ) {
190  torsions[i++] = 0; // there's very little variation -- currently not captured here at all
191  } else { // trans
192  torsions[i++] = OMEGA_MEAN + RG.gaussian() * OMEGA_STDDEV;
193  }
194  }
195  }
196  } //perturb_chain
197 
198 
199  void
201  core::pose::Pose & pose,
202  utility::vector1<core::Real> const & torsions,
203  utility::vector1<core::Real> const & bond_ang,
204  utility::vector1<core::Real> const & bond_len,
205  bool closure_successful // what is this used for?
206  ) const
207  {
208 
209  // parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful, sample_omega_for_pre_prolines_ );
210  parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful );
211 
212  if( vary_ca_bond_angles_ ){
213 
214  core::Real offset( 0.0 );
215  for (Size res=kinmover_->start_res(), atom=5; res<= kinmover_->end_res(); res++, atom+=3) {
216 
217  const core::id::AtomID atomid_N (1, res);
218  const core::id::AtomID atomid_CA(2, res);
219  const core::id::AtomID atomid_C (3, res);
220  pose.set_dof(pose.atom_tree().bond_angle_dof_id(atomid_N, atomid_CA, atomid_C, offset ),
221  numeric::conversions::radians(180 - bond_ang[atom]));
222 
223  }
224  }
225  } //TorsionSamplingKinematicPerturber::set_pose_after_closure(
226 
227 
228  ///////////////////////////////////////////////////////////////////////////////////////////
229  //////////////////////////////////VicinitySamplingKinematicPerturber////////////////////////
230  ///////////////////////////////////////////////////////////////////////////////////////////
231 
233  : KinematicPerturber(),
234  vary_ca_bond_angles_(false),
235  degree_vicinity_( basic::options::option[ basic::options::OptionKeys::loops::vicinity_degree ]() ),
236  sample_omega_for_pre_prolines_( basic::options::option[ basic::options::OptionKeys::loops::sample_omega_at_pre_prolines ]() ) // is this respected at all?
237  { set_kinmover( kinmover_in ); }
238 
240 
241  ///@details small variation around the starting phi/psi angles -- order of magnitude is determined by degree_vicinity_
242  void
244  core::pose::Pose const & pose,
245  utility::vector1<core::Real> & torsions,
246  utility::vector1<core::Real> & bond_ang,
247  utility::vector1<core::Real> & //bond_len
248  )
249  {
251 
252  if( vary_ca_bond_angles_ ){
253 
254  core::Size pvatom3( (3* (kinmover_->segment_length() + 1)) - 1 );
255 
256  core::Real bangle_min( kinmover_->BANGLE_MIN() );
257  core::Real bangle_sd( kinmover_->BANGLE_SD() );
258 
259  //what is this iterating over?
260  for( Size i = 5; i <= pvatom3; i+=3 ) {
261  bond_ang[ i ] = bangle_min + RG.uniform() * bangle_sd;
262  }
263  }
264 
265 
266 
267  core::Size tor_end = torsions.size() - 3;
268 
269  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
270  //if(mm) TR << "current residue " << cur_res << "mm reports " << mm->get_bb(cur_res) << std::endl;
271 
272  if(!mm || mm->get_bb(cur_res)){ //if movemap is null, or (if not null) if movemap says mobile
273 
274  core::Real rama_phi, rama_psi;
275 
276  rama_phi = pose.phi( cur_res ) + degree_vicinity_ * RG.gaussian();
277  rama_psi = pose.psi( cur_res ) + degree_vicinity_ * RG.gaussian();
278 
279  torsions[i++]=rama_phi; // phi
280  torsions[i++]=rama_psi; // psi
281 
282  i++; // leave omega alone
283 
284  } else {
285  i += 3; //ensure i indexing increases
286  }
287 
288  }
289 
290  /* [currently] no pre-pro-omega sampling in vicinity mode */
291 
292  } //perturb_chain
293 
294 
295  void
297  core::pose::Pose & pose,
298  utility::vector1<core::Real> const & torsions,
299  utility::vector1<core::Real> const & bond_ang,
300  utility::vector1<core::Real> const & bond_len,
301  bool closure_successful // what is this used for?
302  ) const
303  {
304 
305  // parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful, sample_omega_for_pre_prolines_ );
306  parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful );
307 
308  if( vary_ca_bond_angles_ ){
309 
310  core::Real offset( 0.0 );
311  for (Size res=kinmover_->start_res(), atom=5; res<= kinmover_->end_res(); res++, atom+=3) {
312 
313  const core::id::AtomID atomid_N (1, res);
314  const core::id::AtomID atomid_CA(2, res);
315  const core::id::AtomID atomid_C (3, res);
316  pose.set_dof(pose.atom_tree().bond_angle_dof_id(atomid_N, atomid_CA, atomid_C, offset ),
317  numeric::conversions::radians(180 - bond_ang[atom]));
318 
319  }
320  }
321  } //VicinitySamplingKinematicPerturber::set_pose_after_closure(
322 
323 
324  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
325  ////////////////////////////////TorsionSweepkingKinematicPerturber//////////////////////////////////////////
326  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
327 
330  {}
331 
333 
335  {
336  nonpivot_res_to_sweep_ = resids;
337  }
338 
340  {
341  assert( nonpivot_res_to_sweep_.size() == bbtorids.size() );
342  sweep_torsion_ids_ = bbtorids;
343  }
344 
346  {
347  assert( nonpivot_res_to_sweep_.size() == angles_in_degrees.size() );
348  sweep_nonpivot_torsion_starts_ = angles_in_degrees;
349  }
350 
352  {
353  assert( nonpivot_res_to_sweep_.size() == angle_steps_in_degrees.size() );
354  sweep_step_sizes_ = angle_steps_in_degrees;
355  }
356 
357  /// @details Initializes the LexicographicalIterator
359  {
360  assert( nonpivot_res_to_sweep_.size() == nsteps.size() );
361  sweep_iterator_.set_dimension_sizes( nsteps );
362  }
363 
364 
365  void
367  core::pose::Pose const &, //pose,
368  utility::vector1<core::Real> & torsions,
369  utility::vector1<core::Real> &,// bond_ang,
370  utility::vector1<core::Real> & //bond_len
371  )
372  {
373 
374  if ( sweep_iterator_.at_end() ) {
375  utility_exit_with_message("TorsionSweepingKinematicPerturber asked to perturb chain even though sweep iterator is at end."); }
376 
377  core::Size start( kinmover_->start_res() );
378 
379  for ( Size ii = 1; ii <= nonpivot_res_to_sweep_.size(); ++ii ) {
380  Size torsion_ind = 3 * ( nonpivot_res_to_sweep_[ ii ] - start + 1 ) + sweep_torsion_ids_[ ii ];
381  torsions[ torsion_ind ] = sweep_nonpivot_torsion_starts_[ ii ] + sweep_step_sizes_[ ii ] * ( sweep_iterator_[ ii ] - 1 );
382  //std::cout << " " << nonpivot_res_to_sweep_[ ii ] << " " << sweep_torsion_ids_[ ii ] << " " << torsion_ind << " = " << dt_ang[ torsion_ind ];
383  }
384  //std::cout << std::endl;
385  ++sweep_iterator_;
386  } //TorsionSweepingKinematicPerturber::perturb_chain(
387 
388 
389  ///////////////////////////////////////////////////////////////////////////////////////////
390  ///////////////////// NeighborDependentTorsionSamplingKinematicPerturber //////////////////
391  ///////////////////////////////////////////////////////////////////////////////////////////
392 
394  : KinematicPerturber(),
395  vary_ca_bond_angles_(false),
396  sample_omega_for_pre_prolines_( basic::options::option[ basic::options::OptionKeys::loops::sample_omega_at_pre_prolines ]() ),
397  rama_( core::scoring::ScoringManager::get_instance()->get_Ramachandran2B() )
398  { set_kinmover( kinmover_in ); }
399 
401 
402  ///@details randomly varies the torsions (and possibly the bond angles) for the loop, using phi/psi combinations based on rama2b
403  void
405  core::pose::Pose const & pose,
406  utility::vector1<core::Real> & torsions,
407  utility::vector1<core::Real> & bond_ang,
408  utility::vector1<core::Real> & //bond_len
409  )
410  {
412 
413  if( vary_ca_bond_angles_ ){
414 
415  core::Size pvatom3( (3* (kinmover_->segment_length() + 1)) - 1 );
416 
417  core::Real bangle_min( kinmover_->BANGLE_MIN() );
418  core::Real bangle_sd( kinmover_->BANGLE_SD() );
419 
420  for( Size i = 5; i <= pvatom3; i+=3 ) {
421  bond_ang[ i ] = bangle_min + RG.uniform() * bangle_sd;
422  //TR << "replacing CA bond angle at " << (kinmover_->start_res()+int((i-4)/3)) << std::endl;
423  }
424  }
425 
426 
427 
428  core::Size tor_end = torsions.size() - 3;
429 
430  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
431 
432  if(!mm || mm->get_bb(cur_res)){ //if movemap is null, or (if not null) if movemap says mobile
433 
434  core::Real rama_phi, rama_psi;
435 
436  // warning: not safe for terminal positions -- however, KIC shouldn't actually include any termini anyway...
437 
438  // currently we don't really have data for both neighbors together
439  // -- for now, do a coin flip on which one to use, though later we should implement this such that each side has an individual perturber, and we call both with equal likelihood (should have fewer ifs)
440  static_cast<int>( RG.uniform()*2 ) ? rama_.random_phipsi_from_rama_left(pose.aa(cur_res-1), pose.aa(cur_res),rama_phi, rama_psi) : rama_.random_phipsi_from_rama_right(pose.aa(cur_res), pose.aa(cur_res+1), rama_phi, rama_psi);
441 
442  torsions[i++]=rama_phi; // phi
443  torsions[i++]=rama_psi; // psi
444 
445  i++; // leave omega alone
446 
447  } else {
448  i += 3; //ensure i indexing increases
449  }
450 
451  }
452 
454  // sample omegas. all omegas before prolines are assumed to be fair game. Note that we're not using move-map, which is phi/psi-specific.
455 
456  static const core::Real OMEGA_MEAN( 179.8 );
457 
458  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
459 
460  if ( pose.aa( cur_res+1 ) == core::chemical::aa_pro ) {
461 
462  core::Real rand_omega = ( static_cast<int>( RG.uniform()*2 ) ? OMEGA_MEAN : 0.0 ); // flip a coin -- either 179.8 (trans) or 0.0 (cis)
463 
464  i++; //phi
465  i++; //psi
466  torsions[i++] = rand_omega;
467 
468  } else {
469  i += 3;
470  }
471  }
472 
473  }
474 
475 
476  } //perturb_chain
477 
478 
479 
480  void
482  core::pose::Pose & pose,
483  utility::vector1<core::Real> const & torsions,
484  utility::vector1<core::Real> const & bond_ang,
485  utility::vector1<core::Real> const & bond_len,
486  bool closure_successful // what is this used for?
487  ) const
488  {
489 
490  // parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful, sample_omega_for_pre_prolines_ );
491  parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful );
492 
493  if( vary_ca_bond_angles_ ){
494 
495  core::Real offset( 0.0 );
496  for (Size res=kinmover_->start_res(), atom=5; res<= kinmover_->end_res(); res++, atom+=3) {
497 
498  const core::id::AtomID atomid_N (1, res);
499  const core::id::AtomID atomid_CA(2, res);
500  const core::id::AtomID atomid_C (3, res);
501  pose.set_dof(pose.atom_tree().bond_angle_dof_id(atomid_N, atomid_CA, atomid_C, offset ),
502  numeric::conversions::radians(180 - bond_ang[atom]));
503 
504  }
505  }
506  } //NeighborDependentTorsionSamplingKinematicPerturber::set_pose_after_closure(
507 
508 
509 
510 
511 
512 
513  ///////////////////////////////////////////////////////////////////////////////////////////
514  //////////////////////////////////TorsionRestrictedKinematicPerturber////////////////////////
515  ///////////////////////////////////////////////////////////////////////////////////////////
516 
518  : KinematicPerturber(),
519  vary_ca_bond_angles_(false),
520  sample_omega_for_pre_prolines_( true ), // if the torsion string is lowercase we use cis, otherwise trans -- note that this flag is used by the parent::set_pose_after_closure function and thus needs to be set to true, otherwise omega will be ignored -- this should be fixed in the future though
521  rama_( core::scoring::ScoringManager::get_instance()->get_Ramachandran() )
522  { set_kinmover( kinmover_in );
523  predefined_torsions_ = torsion_bins; // store torsion string provided by the user or derived from the native structure
524  //std::cerr << " predefined torsion string: " << predefined_torsions_ << std::endl;
525  }
526 
528 
529  ///@details randomly varies the torsions within the given torsion bin
530  void
532  core::pose::Pose const & pose,
533  utility::vector1<core::Real> & torsions,
534  utility::vector1<core::Real> & bond_ang,
535  utility::vector1<core::Real> & //bond_len
536  )
537  {
539 
540  if( vary_ca_bond_angles_ ){ // is this appropriate here?
541 
542  core::Size pvatom3( (3* (kinmover_->segment_length() + 1)) - 1 );
543 
544  core::Real bangle_min( kinmover_->BANGLE_MIN() );
545  core::Real bangle_sd( kinmover_->BANGLE_SD() );
546 
547  for( Size i = 5; i <= pvatom3; i+=3 ) {
548  bond_ang[ i ] = bangle_min + RG.uniform() * bangle_sd;
549  //TR << "replacing CA bond angle at " << (kinmover_->start_res()+int((i-4)/3)) << std::endl;
550  }
551  }
552 
553 
554 
555  core::Size tor_end = torsions.size() - 3;
556 
557  core::Size torsion_string_offset = kinmover_->start_res() - kinmover_->loop_begin(); //offset to fetch the torsion bin for the subsegment we're currently sampling -- the string is always for the entire loop -- maybe we should make sure that this doesn't generate a segmentation fault?
558 
559  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
560  if(!mm || mm->get_bb(cur_res)){ //if movemap is null, or (if not null) if movemap says mobile
561 
562  core::Real rama_phi, rama_psi;
563 
564  rama_.random_phipsi_from_rama_by_torsion_bin(pose.aa(cur_res), rama_phi, rama_psi, toupper(predefined_torsions_[(i-4)/3 + torsion_string_offset])); //here we only care about the phi/psi-based torsion bin, omega is set below
565 
566  torsions[i++]=rama_phi; // phi
567  torsions[i++]=rama_psi; // psi
568 
569  i++; // leave omega alone
570 
571  } else {
572  i += 3; //ensure i indexing increases
573  }
574 
575  }
576 
577  // the TorsionRestricted mover will automatically derive cis/trans from the torsion bin string -- sampling for trans omega can be activated via the -loops:kic_omega_sampling flag (but won't affect the cis/trans choice as it does in other perturbers)
578  static const core::Real OLD_OMEGA_MEAN( 179.8 );
579  // values from Berkholz et al., PNAS 2012
580  static const core::Real OMEGA_MEAN( 179.1 );
581  static const core::Real OMEGA_STDDEV( 6.3 );
582  core::Real rand_omega;
583 
584  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){ // note that this ignores any movemaps for now -- usally they just refer to phi/psi, but it'd be better to check
585 
586  if ( basic::options::option[ basic::options::OptionKeys::loops::kic_omega_sampling ]() || pose.aa( cur_res+1 ) == core::chemical::aa_pro) {
587  rand_omega = OLD_OMEGA_MEAN; // mainly for legacy purposes -- at least the means should be adjusted to match
588  if ( pose.aa( cur_res+1 ) == core::chemical::aa_pro && islower(predefined_torsions_[(i-4)/3 + torsion_string_offset]) ) {
589  rand_omega = 0; // lowercase is for cis
590 
591  //std::cerr << "cis proline at " << cur_res << std::endl; // debug
592 
593  } else { // trans
594  if ( basic::options::option[ basic::options::OptionKeys::loops::kic_omega_sampling ]() ) {
595  rand_omega = OMEGA_MEAN + RG.gaussian() * OMEGA_STDDEV;
596  }
597  }
598  i++; //phi
599  i++; //psi
600  torsions[i++] = rand_omega;
601  } else { // not touching omega for this residue
602  i += 3;
603  }
604  }
605 
606  } //perturb_chain
607 
608 
609 
610  void
612  core::pose::Pose & pose,
613  utility::vector1<core::Real> const & torsions,
614  utility::vector1<core::Real> const & bond_ang,
615  utility::vector1<core::Real> const & bond_len,
616  bool closure_successful // what is this used for?
617  ) const
618  {
619 
620  // parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful, sample_omega_for_pre_prolines_ );
621  parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful );
622 
623  if( vary_ca_bond_angles_ ){
624 
625  core::Real offset( 0.0 );
626  for (Size res=kinmover_->start_res(), atom=5; res<= kinmover_->end_res(); res++, atom+=3) {
627 
628  const core::id::AtomID atomid_N (1, res);
629  const core::id::AtomID atomid_CA(2, res);
630  const core::id::AtomID atomid_C (3, res);
631  pose.set_dof(pose.atom_tree().bond_angle_dof_id(atomid_N, atomid_CA, atomid_C, offset ),
632  numeric::conversions::radians(180 - bond_ang[atom]));
633 
634  }
635  }
636  } //TorsionRestrictedKinematicPerturber::set_pose_after_closure(
637 
638 
639 
640 
641  ///////////////////////////////////////////////////////////////////////////////////////////
642  ////////////////////////////////// TabooSamplingKinematicPerturber ////////////////////////
643  ///////////////////////////////////////////////////////////////////////////////////////////
644 
645  // constructor in case we don't know the sequence (e.g. when remodeling multiple loops)
646  // note that you MUST initialize the sequence before calling apply (else segfaults guaranteed)
648  : KinematicPerturber(),
649  vary_ca_bond_angles_(false),
650  sample_omega_for_pre_prolines_( basic::options::option[ basic::options::OptionKeys::loops::sample_omega_at_pre_prolines ]() ),
651  num_strings_(100000), // large numbers could be inefficient here if there are lots of design steps (which invalidate the current torsion strings & taboo map) -- however, generation of the random strings seems to be very fast
652  rama_( core::scoring::ScoringManager::get_instance()->get_Ramachandran() )
653  { set_kinmover( kinmover_in );
654  }
655 
656 
658 
659  void
661  {
662  utility::vector1< std::string > torsion_bins_per_position; // data structure to hold the vector of torsion bins, with frequencies dependent on the amino acid type, for each position in the loop
663  utility::vector1< core::chemical::AA > loop_sequence = kinmover_->get_loop_sequence();
664  torsion_bins_per_position.resize(loop_sequence.size()); // check if we need +1 here somewhere...
665  core::Real ideal_freq, current_freq;
666  for (core::Size i = 1; i <= loop_sequence.size(); i++) {
667  std::map< char, core::Size > entries_per_torsion_bin;
668  rama_.get_entries_per_torsion_bin( loop_sequence[i], entries_per_torsion_bin ); // to be written
669  std::string torsion_bins_for_pos;
670  // then iterate over the map and fill the string accordingly
671  for (std::map< char, core::Size >::const_iterator mcs_i = entries_per_torsion_bin.begin();
672  mcs_i != entries_per_torsion_bin.end(); mcs_i++) {
673  if (mcs_i->first == 'X')
674  continue; // we only keep X in here for the totals
675  ideal_freq = core::Real(mcs_i->second)/entries_per_torsion_bin['X'];
676  current_freq = kinmover_->frequency_in_taboo_map( i-1, mcs_i->first ); // calculated on a string, i.e., base is 0
677 
678  //TR << "for residue " << loop_sequence[i] << ", torsion bin " << mcs_i->first << " has " << mcs_i->second << " entries --> " << ideal_freq << " while current freq is " << current_freq << std::endl;
679 
680  if (current_freq > 0)
681  ideal_freq /= current_freq; // adjust frequency for what has been sampled already -- note that this means that the size of the resulting string isn't necessarily num_strings_ any more
682  std::string this_bin = std::string( ceil(ideal_freq*num_strings_), mcs_i->first );
683  torsion_bins_for_pos += this_bin;
684  }
685  while (torsion_bins_for_pos.size() < num_strings_) { // make sure they all have the same size -- with adjustments the size may vary (slightly)
686  torsion_bins_for_pos += "X";
687  }
688  numeric::random::random_permutation(torsion_bins_for_pos.begin(), torsion_bins_for_pos.end(), numeric::random::RG);
689  torsion_bins_per_position[i] = torsion_bins_for_pos;
690  //if (i == 1)
691  // TR << torsion_bins_for_pos << std::endl; // debug
692  }
693 
694  for (core::Size j = 1; j < num_strings_; j++) {
695 
696  std::string new_torsion_string; // = new std::string(sequence_.size()); // initialize to correct size
697  for (core::Size i = 1; i <= loop_sequence.size(); i++) {
698  new_torsion_string += torsion_bins_per_position[i][j]; // make sure this is correct... though it will happily segfault if not
699  }
700  // check if we have already sampled this string -- if not, add it to the list
701  if ( !( kinmover_->is_in_taboo_map(new_torsion_string) ) )
702  random_torsion_strings_.push_back(new_torsion_string);
703 
704  }
705  }
706 
707 
708 
710  TabooSamplingKinematicPerturber::next_torsion_string() // core::pose::Pose const & pose )
711  {
712 
713  /*
714  // check if the "stack" still contains a string -- if so, return that
715  // if not, generate new torsion strings that should cover the entire space (ha!)
716 
717  -- for each position in the loop, fetch the corresponding residues, and then ask the Rama lookup table for the relative populations of each torsion bin, and generate a string of length n with the frequencies of each letter corresponding to the respective torsion bin's frequency for this residue
718  -- maybe the function to generate a corresponding string can even be part of the Rama function?
719  -- fill up with X if the strings aren't long enough -- they must all have the same length
720  -- for later applications we could think about adjusting the torsion bin frequencies by those that have already been sampled --> we'd need another structure that holds the strings that were already sampled (might be moved there directly the moment they're provided by this function)
721  -- randomly shuffle each string
722  -- generate n random torsion strings for the loop by appending positions 1,2,3... of each of the now randomized strings [for the positions] -- this reflects the respective torsion bin frequencies (because the initial strings do, see above)
723  */
724 
725 
726  if (random_torsion_strings_.size() == 0) {
727  random_torsion_strings_.clear();
729 
730  while (random_torsion_strings_.size() == 0) { // when the taboo map gets fuller, it is possible that all 1000 random strings have already been tried, and thus the map is still empty even after "refilling"
732  }
733  }
734 
735 
736  runtime_assert(random_torsion_strings_.size() > 0); // shouldn't happen any more...
737 
738  // make sure the torsion string we're returning hasn't been tested yet
739  while ( kinmover_->is_in_taboo_map(random_torsion_strings_[random_torsion_strings_.size()]) ) {
740  //TR << random_torsion_strings_[random_torsion_strings_.size()] << " has already been tested, next... " << std::endl;
741  random_torsion_strings_.pop_back();
742  while (random_torsion_strings_.size() == 0) // refill if necessary
744 
745  }
746 
748  //TR << tb << " " << random_torsion_strings_.size() << std::endl; // debug
749 
750  random_torsion_strings_.pop_back();
751 
752  return tb;
753  }
754 
755  void
757  core::pose::Pose const & pose,
758  utility::vector1<core::Real> & torsions,
759  utility::vector1<core::Real> & bond_ang,
760  utility::vector1<core::Real> & //bond_len
761  )
762  {
764 
765  if( vary_ca_bond_angles_ ){ // is this appropriate here?
766 
767  core::Size pvatom3( (3* (kinmover_->segment_length() + 1)) - 1 );
768 
769  core::Real bangle_min( kinmover_->BANGLE_MIN() );
770  core::Real bangle_sd( kinmover_->BANGLE_SD() );
771 
772  //what is this iterating over?
773  for( Size i = 5; i <= pvatom3; i+=3 ) {
774  bond_ang[ i ] = bangle_min + RG.uniform() * bangle_sd;
775  //TR << "replacing CA bond angle at " << (kinmover_->start_res()+int((i-4)/3)) << std::endl;
776  }
777  }
778 
779 
780 
781  core::Size tor_end = torsions.size() - 3;
782 
783  std::string torsion_string = next_torsion_string(); // function to provide the torsion string to be sampled -- to be written
784 
785  core::Size torsion_string_offset = kinmover_->start_res() - kinmover_->loop_begin(); //offset to fetch the torsion bin for the subsegment we're currently sampling -- the string is always for the entire loop -- maybe we should make sure that this doesn't generate a segmentation fault?
786  //std::cerr << "Torsion string is " << torsion_string << ", offset is " << torsion_string_offset << std::endl;
787 
788  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
789  if(!mm || mm->get_bb(cur_res)){ //if movemap is null, or (if not null) if movemap says mobile
790 
791  core::Real rama_phi, rama_psi;
792 
793  rama_.random_phipsi_from_rama_by_torsion_bin(pose.aa(cur_res), rama_phi, rama_psi, toupper(torsion_string[(i-4)/3 + torsion_string_offset])); //here we only care about the phi/psi-based torsion bin, omega is set below
794 
795  torsions[i++]=rama_phi; // phi
796  torsions[i++]=rama_psi; // psi
797 
798  i++; // leave omega alone
799 
800  } else {
801  i += 3; //ensure i indexing increases
802  }
803 
804  }
805 
807  // sample omegas. all omegas before prolines are assumed to be fair game. Note that we're not using move-map, which is phi/psi-specific.
808 
809  static const core::Real OMEGA_MEAN( 179.8 );
810 
811  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
812 
813  if ( pose.aa( cur_res+1 ) == core::chemical::aa_pro ) {
814 
815  core::Real rand_omega = ( static_cast<int>( RG.uniform()*2 ) ? OMEGA_MEAN : 0.0 ); // flip a coin -- either 179.8 (trans) or 0.0 (cis)
816 
817  /*
818  if ( islower(torsion_string[(i-4)/3 + torsion_string_offset]) ) { // actually at the moment this is impossible... use random value instead?
819  rand_omega = 0; // lowercase is for cis
820  } else {
821  rand_omega = OMEGA_MEAN;
822  }
823  //}
824  */
825  i++; //phi
826  i++; //psi
827  torsions[i++] = rand_omega;
828 
829  } else {
830  i += 3;
831  }
832  }
833 
834  } else if ( basic::options::option[ basic::options::OptionKeys::loops::kic_omega_sampling ]() ) {
835  // actual omega sampling, values from Berkholz et al., PNAS 2012
836  static const core::Real OMEGA_MEAN( 179.1 );
837  static const core::Real OMEGA_STDDEV( 6.3 );
838 
839  // cis or trans? -- cis is much less common than trans, according to data from Matt / top8000, so the current coinflip is probably overestimating cis
840  // as a proxy, using 1/1000 for now
841  static const core::Real cis_prob_threshold = 0.0001;
842 
843  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
844  i++; //phi
845  i++; //psi
846  core::Real trans_prob = 1;
847  if ( pose.aa( cur_res+1 ) == core::chemical::aa_pro ) {
848  trans_prob = RG.uniform();
849  }
850  if ( trans_prob < cis_prob_threshold ) {
851  torsions[i++] = 0; // there's very little variation -- currently not captured here at all
852  } else { // trans
853  torsions[i++] = OMEGA_MEAN + RG.gaussian() * OMEGA_STDDEV;
854  }
855  }
856  }
857 
858 
859  } //perturb_chain
860 
861 
862 
863  void
865  core::pose::Pose & pose,
866  utility::vector1<core::Real> const & torsions,
867  utility::vector1<core::Real> const & bond_ang,
868  utility::vector1<core::Real> const & bond_len,
869  bool closure_successful // what is this used for?
870  ) const
871  {
872 
873  // parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful, sample_omega_for_pre_prolines_ );
874  parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful );
875 
876  if( vary_ca_bond_angles_ ){
877 
878  core::Real offset( 0.0 );
879  for (Size res=kinmover_->start_res(), atom=5; res<= kinmover_->end_res(); res++, atom+=3) {
880 
881  const core::id::AtomID atomid_N (1, res);
882  const core::id::AtomID atomid_CA(2, res);
883  const core::id::AtomID atomid_C (3, res);
884  pose.set_dof(pose.atom_tree().bond_angle_dof_id(atomid_N, atomid_CA, atomid_C, offset ),
885  numeric::conversions::radians(180 - bond_ang[atom]));
886 
887  }
888  }
889  } //TabooSamplingKinematicPerturber::set_pose_after_closure(
890 
891 
892 
893 
894 
895 
896 
897  ///////////////////////////////////////////////////////////////////////////////////////////
898  //////////////////// NeighborDependentTabooSamplingKinematicPerturber /////////////////////
899  ///////////////////////////////////////////////////////////////////////////////////////////
900 
902  : KinematicPerturber(),
903  vary_ca_bond_angles_(false),
904  sample_omega_for_pre_prolines_( basic::options::option[ basic::options::OptionKeys::loops::sample_omega_at_pre_prolines ]() ),
905  num_strings_(1000),
906  rama_( core::scoring::ScoringManager::get_instance()->get_Ramachandran2B() )
907  { set_kinmover( kinmover_in );
908  }
909 
911 
912  void
913  NeighborDependentTabooSamplingKinematicPerturber::refill_torsion_string_vector() // the amount of code duplication in here is a shame... can't we have a generic refill_torsion_string_vector() function that takes the respective map as an input? Which class would have to implement this, the parent class? Maybe it'd be good to have a specific parent class for TabooSampling...
914  {
915  utility::vector1< std::string > torsion_bins_per_position; // data structure to hold the vector of torsion bins, with frequencies dependent on the amino acid type, for each position in the loop
916  utility::vector1< core::chemical::AA > loop_sequence = kinmover_->get_loop_sequence();
917  torsion_bins_per_position.resize(loop_sequence.size());
918  core::Real ideal_freq, current_freq;
919  for (core::Size i = 1; i <= loop_sequence.size(); i++) {
920  std::map< char, core::Size > entries_per_torsion_bin;
921 
922 
923  if (i == 1) // we don't know the previous position (and this position is solved analytically anyway)
924  rama_.get_entries_per_torsion_bin_right( loop_sequence[i], loop_sequence[i+1], entries_per_torsion_bin );
925  else if (i == loop_sequence.size())
926  rama_.get_entries_per_torsion_bin_left( loop_sequence[i-1], loop_sequence[i], entries_per_torsion_bin );
927  else {
928  // take the minimum count from both sides -- especially if one of them is 0 we cannot ask for a random phi/psi combination as it won't exist
929  std::map< char, core::Size > left_tb, right_tb;
930  rama_.get_entries_per_torsion_bin_left( loop_sequence[i-1], loop_sequence[i], left_tb );
931  rama_.get_entries_per_torsion_bin_right( loop_sequence[i], loop_sequence[i+1], right_tb );
932  // now iterate over both maps and take the minimum
933  for (std::map< char, core::Size >::const_iterator mcs_i = left_tb.begin(); mcs_i != left_tb.end(); mcs_i++) {
934  entries_per_torsion_bin[mcs_i->first] = std::min(left_tb[mcs_i->first], right_tb[mcs_i->first]);
935  }
936  }
937 
938 
939  std::string torsion_bins_for_pos;
940  // then iterate over the map and fill the string accordingly
941  for (std::map< char, core::Size >::const_iterator mcs_i = entries_per_torsion_bin.begin();
942  mcs_i != entries_per_torsion_bin.end(); mcs_i++) {
943  if (mcs_i->first == 'X')
944  continue; // we only keep X in here for the totals
945  ideal_freq = core::Real(mcs_i->second)/entries_per_torsion_bin['X'];
946  current_freq = kinmover_->frequency_in_taboo_map( i-1, mcs_i->first ); // calculated on a string, i.e., base is 0
947 
948  //TR << "for residue " << core::chemical::AA(loop_sequence[i]) << ", torsion bin " << mcs_i->first << " has " << mcs_i->second << " entries --> " << ideal_freq << " while current freq is " << current_freq << std::endl;
949 
950  if (current_freq > 0)
951  ideal_freq /= current_freq; // adjust frequency for what has been sampled already -- note that this means that the size of the resulting string isn't necessarily num_strings_ any more
952  std::string this_bin = std::string( ceil(ideal_freq*num_strings_), mcs_i->first );
953  torsion_bins_for_pos += this_bin;
954  }
955  while (torsion_bins_for_pos.size() < num_strings_) { // make sure they all have the same size -- with adjustments the size may vary (slightly)
956  torsion_bins_for_pos += "X";
957  }
958  numeric::random::random_permutation(torsion_bins_for_pos.begin(), torsion_bins_for_pos.end(), numeric::random::RG);
959  torsion_bins_per_position[i] = torsion_bins_for_pos;
960  }
961 
962  for (core::Size j = 1; j < num_strings_; j++) {
963 
964  std::string new_torsion_string;
965  for (core::Size i = 1; i <= loop_sequence.size(); i++) {
966  new_torsion_string += torsion_bins_per_position[i][j];
967  }
968  // check if we have already sampled this string -- if not, add it to the list
969  if ( !( kinmover_->is_in_taboo_map(new_torsion_string) ) )
970  random_torsion_strings_.push_back(new_torsion_string);
971  }
972  }
973 
974 
975 
976 
979  {
980 
981 
982  if (random_torsion_strings_.size() == 0) {
983  random_torsion_strings_.clear();
985 
986  while (random_torsion_strings_.size() == 0) { // when the taboo map gets fuller, it is possible that all 1000 random strings have already been tried, and thus the map is still empty even after "refilling"
988  }
989  }
990 
991 
992  runtime_assert(random_torsion_strings_.size() > 0);
993  // make sure the torsion string we're returning hasn't been tested yet
994  while ( kinmover_->is_in_taboo_map(random_torsion_strings_[random_torsion_strings_.size()]) ) {
995  //TR << random_torsion_strings_[random_torsion_strings_.size()] << " has already been tested, next... " << std::endl;
996  random_torsion_strings_.pop_back();
997  while (random_torsion_strings_.size() == 0) // refill if necessary
999 
1000  }
1001 
1003 
1004  random_torsion_strings_.pop_back();
1005 
1006  return tb;
1007  }
1008 
1009  void
1011  core::pose::Pose const & pose,
1012  utility::vector1<core::Real> & torsions,
1013  utility::vector1<core::Real> & bond_ang,
1014  utility::vector1<core::Real> & //bond_len
1015  )
1016  {
1018 
1019  if( vary_ca_bond_angles_ ){
1020 
1021  core::Size pvatom3( (3* (kinmover_->segment_length() + 1)) - 1 );
1022 
1023  core::Real bangle_min( kinmover_->BANGLE_MIN() );
1024  core::Real bangle_sd( kinmover_->BANGLE_SD() );
1025 
1026  for( Size i = 5; i <= pvatom3; i+=3 ) {
1027  bond_ang[ i ] = bangle_min + RG.uniform() * bangle_sd;
1028  //TR << "replacing CA bond angle at " << (kinmover_->start_res()+int((i-4)/3)) << std::endl;
1029  }
1030  }
1031 
1032 
1033 
1034  core::Size tor_end = torsions.size() - 3;
1035 
1036  std::string torsion_string = next_torsion_string();
1037 
1038  core::Size torsion_string_offset = kinmover_->start_res() - kinmover_->loop_begin(); //offset to fetch the torsion bin for the subsegment we're currently sampling -- the string is always for the entire loop -- maybe we should make sure that this doesn't generate a segmentation fault?
1039  //std::cerr << "Torsion string is " << torsion_string << ", offset is " << torsion_string_offset << std::endl;
1040 
1041  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
1042  if(!mm || mm->get_bb(cur_res)){ //if movemap is null, or (if not null) if movemap says mobile
1043 
1044  core::Real rama_phi, rama_psi;
1045 
1046  // coin flip: use information from left or right AA?
1047  // at either end of the loop, use the "inner" neighbor -- mainly because we haven't checked whether there actually is data for the outer neighbor and the corresponding bin [as we don't have access to those positions during setup]
1048  // drawback of this approach: we don't consider the residues directly adjacent to the loop
1049  // -- however, the boundary positions are solved analytically anyway, so this shouldn't matter, practically speaking
1050  if ( cur_res == kinmover_->loop_begin() )
1051  rama_.random_phipsi_from_rama_by_torsion_bin_right(pose.aa(cur_res), pose.aa(cur_res+1), rama_phi, rama_psi, toupper(torsion_string[(i-4)/3 + torsion_string_offset]));
1052  else if ( cur_res == kinmover_->loop_end() )
1053  rama_.random_phipsi_from_rama_by_torsion_bin_left(pose.aa(cur_res-1), pose.aa(cur_res), rama_phi, rama_psi, toupper(torsion_string[(i-4)/3 + torsion_string_offset]));
1054  else
1055  static_cast<int>( RG.uniform()*2 ) ? rama_.random_phipsi_from_rama_by_torsion_bin_left(pose.aa(cur_res-1), pose.aa(cur_res), rama_phi, rama_psi, toupper(torsion_string[(i-4)/3 + torsion_string_offset])) : rama_.random_phipsi_from_rama_by_torsion_bin_right(pose.aa(cur_res), pose.aa(cur_res+1), rama_phi, rama_psi, toupper(torsion_string[(i-4)/3 + torsion_string_offset])); //here we only care about the phi/psi-based torsion bin, omega is set below
1056 
1057  torsions[i++]=rama_phi; // phi
1058  torsions[i++]=rama_psi; // psi
1059 
1060  i++; // leave omega alone
1061 
1062  } else {
1063  i += 3; //ensure i indexing increases
1064  }
1065 
1066  }
1067 
1068  if ( sample_omega_for_pre_prolines_ ) { // this could also be implemented in a parent class -- or is there a specific reason it isn't?
1069  // sample omegas. all omegas before prolines are assumed to be fair game. Note that we're not using move-map, which is phi/psi-specific.
1070 
1071  static const core::Real OMEGA_MEAN( 179.8 );
1072 
1073  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
1074 
1075  if ( pose.aa( cur_res+1 ) == core::chemical::aa_pro ) {
1076 
1077  core::Real rand_omega = ( static_cast<int>( RG.uniform()*2 ) ? OMEGA_MEAN : 0.0 ); // flip a coin -- either 179.8 (trans) or 0.0 (cis)
1078 
1079  i++; //phi
1080  i++; //psi
1081  torsions[i++] = rand_omega;
1082 
1083  } else {
1084  i += 3;
1085  }
1086  }
1087 
1088  } else if ( basic::options::option[ basic::options::OptionKeys::loops::kic_omega_sampling ]() ) {
1089  // actual omega sampling, values from Berkholz et al., PNAS 2012
1090  static const core::Real OMEGA_MEAN( 179.1 );
1091  static const core::Real OMEGA_STDDEV( 6.3 );
1092 
1093  // cis or trans? -- cis is much less common than trans, according to data from Matt / top8000, so the current coinflip is probably overestimating cis
1094  // as a proxy, using 1/1000 for now
1095  static const core::Real cis_prob_threshold = 0.0001;
1096 
1097  for( core::Size i=4, cur_res = kinmover_->start_res(); i<= tor_end; cur_res++ ){
1098  i++; //phi
1099  i++; //psi
1100  core::Real trans_prob = 1;
1101  if ( pose.aa( cur_res+1 ) == core::chemical::aa_pro ) {
1102  trans_prob = RG.uniform();
1103  }
1104  if ( trans_prob < cis_prob_threshold ) {
1105  torsions[i++] = 0; // there's very little variation -- currently not captured here at all
1106  } else { // trans
1107  torsions[i++] = OMEGA_MEAN + RG.gaussian() * OMEGA_STDDEV;
1108  }
1109  }
1110  }
1111 
1112 
1113  } //perturb_chain
1114 
1115 
1116 
1117  void
1119  core::pose::Pose & pose,
1120  utility::vector1<core::Real> const & torsions,
1121  utility::vector1<core::Real> const & bond_ang,
1122  utility::vector1<core::Real> const & bond_len,
1123  bool closure_successful // what is this used for?
1124  ) const
1125  {
1126 
1127  // parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful, sample_omega_for_pre_prolines_ );
1128  parent::set_pose_after_closure( pose, torsions, bond_ang, bond_len, closure_successful );
1129 
1130  if( vary_ca_bond_angles_ ){
1131 
1132  core::Real offset( 0.0 );
1133  for (Size res=kinmover_->start_res(), atom=5; res<= kinmover_->end_res(); res++, atom+=3) {
1134 
1135  const core::id::AtomID atomid_N (1, res);
1136  const core::id::AtomID atomid_CA(2, res);
1137  const core::id::AtomID atomid_C (3, res);
1138  pose.set_dof(pose.atom_tree().bond_angle_dof_id(atomid_N, atomid_CA, atomid_C, offset ),
1139  numeric::conversions::radians(180 - bond_ang[atom]));
1140 
1141  }
1142  }
1143  } //NeighborDependentTabooSamplingKinematicPerturber::set_pose_after_closure(
1144 
1145 
1146 
1147 
1148  } // namespace kinematic_closure
1149  } // namespace loop_closure
1150  } // namespace loops
1151 } // namespace protocols