Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
util.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 src/core/scoring/constraints/util.cc
11 /// @brief utility functions for defining constraints. Maybe better placed in src/numeric?
12 /// @author James Thompson
13 
14 #include <core/types.hh>
15 
16 #include <core/pose/Pose.hh>
17 #include <basic/options/option.hh>
26 
28 
29 #include <numeric/random/random_permutation.hh>
30 #include <numeric/random/random.hh>
31 #include <basic/Tracer.hh>
32 
33 #include <ObjexxFCL/FArray2D.hh>
34 
35 // option key includes
36 #include <basic/options/keys/constraints.OptionKeys.gen.hh>
37 
38 #include <utility/vector0.hh>
39 #include <utility/vector1.hh>
40 
41 namespace core {
42 namespace scoring {
43 namespace constraints {
44 
45 static numeric::random::RandomGenerator RG(42015512); // <- Magic number, do not change
46 
47 
48 static basic::Tracer tr("core.scoring.constraints");
49 
50 /// @brief Returns the weighted value of a normal distribution evaluated
51 /// with the given mean, sd, and x values. Returns zero if the weight is
52 /// less than 1e-10.
53 Real logdgaussian( Real x, Real mean, Real sd, Real weight )
54 {
55  using namespace std;
56  Real r = x - mean;
57  static Real sqrt_2pi = 2.50662721600161;
58 
59  Real answer = log(weight / (sd * sqrt_2pi)) - ( r * r / (2*sd*sd) );
60  return answer;
61 }
62 
63 /// @brief Returns the weighted value of a normal distribution evaluated
64 /// with the given mean, sd, and x values. Returns zero if the weight is
65 /// less than 1e-10.
67 {
68  using namespace std;
69  Real r = x - mean;
70  Real answer = - (r / (sd*sd) );
71  return answer;
72 }
73 
74 /// @brief Returns the weighted value of a normal distribution evaluated
75 /// with the given mean, sd, and x values. Returns zero if the weight is
76 /// less than 1e-10.
77 Real dgaussian( Real x, Real mean, Real sd, Real weight ) {
78  if ( weight < 1e-10 ) {
79  return 0;
80  }
81 
82  using namespace std;
83  Real r = x - mean;
84  static Real sqrt_2pi = 2.50662721600161;
85  Real answer = weight * (1 / (sd * sqrt_2pi)) * exp( -1 * r * r / (2*sd*sd) );
86  return answer;
87 }
88 
89 /// @brief Returns the weighted derivative of a normal distribution evaluated
90 /// with the given mean, sd, and x values. Returns zero if the weight is less
91 /// than 1e-10.
92 Real gaussian_deriv( Real x, Real mean, Real sd, Real weight ) {
93  assert( weight >= 0.0 && weight <= 1.0 );
94 
95  if ( weight < 1e-10 ) {
96  return 0;
97  }
98 
99  using namespace std;
100  Real r = abs( x - mean );
101  Real answer = dgaussian( x, mean, sd , weight ) * ( 1 / ( sd * sd ) ) * r;
102  return answer;
103 }
104 
105 /// @brief Returns the weighted value of an exponential distribution
106 /// evaluated with the given anchor, rate, and x values. Returns zero if the
107 /// weight is less than 1e-10.
108 Real dexponential( Real x, Real anchor, Real rate, Real weight ) {
109  assert( weight >= 0.0 && weight <= 1.0 );
110  if ( weight < 1e-10 ) {
111  return 0;
112  }
113 
114  using namespace std;
115  Real r = abs( x - anchor );
116  Real answer = weight * rate * exp( -1 * rate * r );
117  return answer;
118 }
119 
120 /// @brief Returns the weighted derivative of a log-exponential distribution
121 /// evaluated with the given anchor, rate, and x values. Returns zero if the
122 /// weight is less than 1e-10.
123 Real exponential_deriv( Real x, Real anchor, Real rate, Real weight ) {
124  if ( weight < 1e-10 ) {
125  return 0;
126  }
127 
128  using namespace std;
129  Real r = abs( x - anchor );
130  return weight * rate * rate * exp( -1 * rate * r );
131 }
132 
134  Real const x_val,
135  Real const x1,
136  Real const x2,
137  Real const y1,
138  Real const y2
139 ) {
140 
141  if ( x_val == x1 ) return y1;
142  if ( x_val == x2 ) return y2;
143 
144  // calculate slope
145  Real slope = ( y2 - y1 ) / ( x2 - x1 );
146  // walk along line
147  return (x_val - x1) * slope;
148 }
149 
150 void
152  ConstraintCOPs const& target_list,
153  ConstraintCOPs &culled_list,
154  pose::Pose const& filter_pose,
155  core::Real threshold
156 ) {
157  culled_list.clear();
158  for ( ConstraintCOPs::const_iterator it = target_list.begin(),
159  eit = target_list.end(); it != eit; ++it ) {
160  if ( (*it)->show_violations( tr.Debug, filter_pose, 1, threshold ) == 0 ) {
161  culled_list.push_back( *it );
162  }
163  }
164 }
165 
166 
167 ////////// Centroid constraints
169  using namespace basic::options;
170  utility::vector1< std::string> cst_files = option[ OptionKeys::constraints::cst_file ]();
171  core::Size choice=1;
172  if ( cst_files.size() > 1 ) choice=core::Size( RG.random_range( 1,cst_files.size() ) );
173  tr.Info << "Constraint choice: " << cst_files[choice] << std::endl;
174  return cst_files[choice];
175 }
176 
177 //// @brief add constraints if specified by user.
179  using namespace basic::options;
180  using namespace core::scoring::constraints;
181  if ( option[ OptionKeys::constraints::cst_file ].user() ) {
183  pose.constraint_set( cstset_ );
184  }
185 }
186 
187 //// @brief add constraints if specified by user.
189  using namespace basic::options;
190  if ( option[ OptionKeys::constraints::cst_weight ].user() ) {
191  scorefxn_.set_weight( atom_pair_constraint, option[ OptionKeys::constraints::cst_weight ]() );
192  scorefxn_.set_weight( angle_constraint, option[ OptionKeys::constraints::cst_weight ]() );
193  scorefxn_.set_weight( dihedral_constraint, option[ OptionKeys::constraints::cst_weight ]() );
194  scorefxn_.set_weight( coordinate_constraint, option[ OptionKeys::constraints::cst_weight ]() );
195  }
196 }
197 
198 //// @brief add constraints if specified by user.
202 }
203 
204 ////////// FA constraints
206  using namespace basic::options;
208  = option[ OptionKeys::constraints::cst_fa_file ]();
209  core::Size choice=1;
210  if ( cst_files.size() > 1 ) choice=core::Size( RG.random_range( 2,cst_files.size() ) );
211  tr.Info << "Constraint choice: " << cst_files[choice] << std::endl;
212  return cst_files[choice];
213 }
214 
215 /// @brief add constraints if specified by user using the
216 /// -constraints::cst_fa_file flag. Setting appropriate weights for
217 /// ScoreFunction is done elsewhere.
219  using namespace basic::options;
220  using namespace core::scoring::constraints;
221  if ( option[ OptionKeys::constraints::cst_fa_file ].user() ) {
224  );
225  pose.constraint_set( cstset_ );
226  }
227 }
228 
229 /// @brief add constraints if specified by user.
231  using namespace basic::options;
232  if ( option[ OptionKeys::constraints::cst_fa_weight ].user() ) {
233  scorefxn_.set_weight( atom_pair_constraint, option[ OptionKeys::constraints::cst_fa_weight ]() );
234  scorefxn_.set_weight( angle_constraint, option[ OptionKeys::constraints::cst_fa_weight ]() );
235  scorefxn_.set_weight( dihedral_constraint, option[ OptionKeys::constraints::cst_fa_weight ]() );
236  scorefxn_.set_weight( coordinate_constraint, option[ OptionKeys::constraints::cst_fa_weight ]() );
237  }
238 }
239 
240 
241 //// @brief add constraints if specified by user.
243  core::pose::Pose & pose,
244  core::scoring::ScoreFunction & scorefxn_
245 ) {
248 }
249 
250 ///////////////////////////////////////////////////////////////////////////////////////////////
251 void
252 add_coordinate_constraints( pose::Pose & pose, Real const coord_sdev /* = 10.0 */ ) {
253 
254  using namespace core::id;
255  using namespace core::conformation;
256  using namespace core::scoring::constraints;
257 
258  Size const my_anchor( 1 ); //anchor atom on first residue?
259 
260  ConstraintSetOP cst_set = pose.constraint_set()->clone();
261 
262  Size const nres( pose.total_residue() );
263  for ( Size i=1; i<= nres; ++i ) {
264 
265  Residue const & i_rsd( pose.residue(i) );
266 
267  for ( Size ii = 1; ii<= i_rsd.nheavyatoms(); ++ii ) {
268 
269  cst_set->add_constraint( new CoordinateConstraint( AtomID(ii,i), AtomID(1,my_anchor), i_rsd.xyz(ii),
270  new HarmonicFunc( 0.0, coord_sdev ) ) );
271  }
272  }
273 
274  pose.constraint_set( cst_set );
275 
276 }
277 
278 bool combinable( Constraint const& cst, utility::vector1< Size > exclude_res ) {
279  if ( exclude_res.size() == 0 ) return true;
280  utility::vector1< Size > pos_list( cst.residues() );
281  for( core::Size i(1); i <= pos_list.size(); ++i ) {
282  Size const seqpos( pos_list[i] );
283  runtime_assert( seqpos <= exclude_res.size() );
284  if ( !exclude_res[ seqpos ] ) {
285  return true;
286  }
287  }
288  return false;
289 }
290 
291 ///@brief combine constraints randomly into AmbiguousConstraints N -> 1 this greatly decreases the odds to have a wrong constraint
293  for ( utility::vector1< ConstraintCOP >::const_iterator it = in.begin(); it != in.end(); ++it ) {
294  Constraint& cst = const_cast< Constraint& >( (**it) );
296  }
297 }
298 
299 
301  if ( sep < 5 ) return 1;
302  if ( sep < 20 ) return 2;
303  if ( sep < 50 ) return 3;
304  return 4;
305 }
306 
307 ///@brief combine constraints randomly into AmbiguousConstraints N -> 1 this greatly decreases the odds to have a wrong constraint
309  ConstraintCOPs& in,
310  core::Size combine_ratio,
311  utility::vector1< bool > exclude_res,
313 ) {
314 
315  tr.Info << " combine constraints " << combine_ratio << " -> 1 " << std::endl;
316  using namespace scoring::constraints;
317  if ( combine_ratio <= 1 ) return;
318 
319  tr.Trace << "figure out sequence-separation bins" << std::endl;
320  //first bin constraints by effective sequence separation --- combine within bins
321  typedef std::map< core::Size, ConstraintCOPs > SeqSepMap;
322  SeqSepMap seq_sep_map;
323  for ( utility::vector1< ConstraintCOP >::const_iterator it = in.begin(); it != in.end(); ++it ) {
324  Size seq_bin = bin_by_seq_separation( (*it)->effective_sequence_separation( sp_in ) );
325  seq_sep_map[ seq_bin ].push_back( *it );
326  }
327 
328  tr.Trace << "combine within bins..."<< std::endl;
329  // combine constraints within bins
331  for ( SeqSepMap::iterator bin_it=seq_sep_map.begin(); bin_it != seq_sep_map.end(); ++bin_it ) {
332  // random permutation within bin... ensures random combination
333  random_permutation( bin_it->second, RG ); //I don't think a single pass of pairwise exchanges is enough to randomize the vector.
334  random_permutation( bin_it->second, RG );
335  random_permutation( bin_it->second, RG );
336 
337  // combine bin
338  for ( utility::vector1< ConstraintCOP >::const_iterator it = bin_it->second.begin(); it != bin_it->second.end();
339  //DO NOT INCREMENT, already incremented in next loop -- gives segfaults otherwise
340  ) {
341  Size ct( combine_ratio );
342  MultiConstraintOP combined_cst = new AmbiguousConstraint;
343  for ( ; ct > 0 && it != bin_it->second.end(); ++it ) {
344  tr.Trace << " add constraint " << ct << std::endl;
345  //check if constraint is combinable:
346  if ( combinable( **it, exclude_res ) ) {
347  combined_cst->add_individual_constraint( *it );
348  --ct;
349  } else {
350  out.push_back( *it ); //keep uncombined constraints around
351  }
352  }
353  //fill up with more constraints if ct is not 0 yet.
354  if ( ct > 0 ) {
355  tr.Trace << " fill last Ambiguous constraint " << ct << std::endl;
356  for ( ConstraintCOPs::const_iterator it2 = bin_it->second.begin(); ct > 0 && it2 != bin_it->second.end(); ++it2 ) {
357  if ( combinable( **it2, exclude_res ) ) {
358  --ct;
359  combined_cst->add_individual_constraint( *it2 );
360  }
361  }
362  } // ct > 0
363  combined_cst->choose_effective_sequence_separation( sp_in, RG );
364  out.push_back( combined_cst );
365  }
366  } // combination within bin
367  in = out;
368 }
369 
370 //helper function for skip_redundant_cosntraints
371 void count_constraint( ConstraintCOP cst, bool redundant, ObjexxFCL::FArray2D_int& count_matrix, Size influence_width, Size total_residue ){
372 
373  // figure out if it's inter-res, residue_pair, or 3+body
374  utility::vector1< int > pos_list( cst->residues() );
375 
376  if ( pos_list.size() != 2 ) {
377  tr.Error << "problems understanding constraint in skip_redundant_constraints ... ignore and keep this one" << std::endl;
378  for ( utility::vector1< int >::const_iterator it = pos_list.begin(); it != pos_list.end(); ++it ) {
379  tr.Debug << " resid: " << *it << std::endl;
380  }
381  return;
382  }
383 // count_matrix( pos_list[1],pos_list[2] ) = std::max( count_matrix( pos_list[1],pos_list[2] ), redundant ? 1 : 2 );
384 // count_matrix( pos_list[2],pos_list[1] ) = count_matrix( pos_list[1],pos_list[2] );
385  for ( int i=pos_list[1]-influence_width; i<= pos_list[1]+ (int) influence_width ; ++i ) {
386  for ( int j=pos_list[2]-influence_width; j<= pos_list[2]+ (int) influence_width ; ++j ) {
387  if ( i < 1 || j < 1 || i > (int) total_residue || j > (int) total_residue ) continue;
388  count_matrix( i, j ) = std::max( count_matrix( i,j ), redundant ? 1 : 2 );
389  count_matrix( j, i ) = count_matrix( i,j );
390  }
391  }
392 }
393 
394 //helper function for skip_redundant_cosntraints
395 bool keep_constraint( ConstraintCOP cst, bool redundant, ObjexxFCL::FArray2D_int& count_matrix, Size influence_width, Size total_residue ) {
396 
397  // figure out if it's inter-res, residue_pair, or 3+body
398  utility::vector1< int > pos_list( cst->residues() );
399 
400  if ( pos_list.size() != 2 ) {
401  tr.Error << "problems understanding constraint in skip_redundant_constraints ... ignore and keep this one" << std::endl;
402  return true;
403  }
404  bool keep( false );
405 
406  if ( ( !redundant && count_matrix( pos_list[1],pos_list[2] ) == 3 ) || count_matrix( pos_list[1],pos_list[2] ) == ( redundant ? 1 : 2 ) ) {
407  keep = true;
408  for ( int i=pos_list[1]-influence_width; i<= pos_list[1]+ (int) influence_width ; ++i ) {
409  for ( int j=pos_list[2]-influence_width; j<= (int) pos_list[2]+ (int)influence_width ; ++j ) {
410  if ( i < 1 || j < 1 || i > (int) total_residue || j > (int) total_residue ) continue;
411  count_matrix( i, j ) += 2;
412  count_matrix( j, i ) = count_matrix( i,j );
413  }
414  }
415  }
416  // count_matrix( pos_list[1],pos_list[2] ) += 2;
417  // count_matrix( pos_list[2],pos_list[1] ) = count_matrix( pos_list[1],pos_list[2] );
418  return keep;
419 }
420 
421 void skip_redundant_constraints( ConstraintCOPs& in, Size total_residue, Size influence_width ) {
422  if ( influence_width == 0 ) return;
423  --influence_width; //1 means now same residue
424  tr.Info << " skip redundant constraints... starting with " << in.size() << " constraints" << std::endl;
425  using namespace scoring::constraints;
427  ObjexxFCL::FArray2D_int count_matrix( total_residue, total_residue, 0 );
428  using namespace numeric::random;
429  random_permutation( in, RG ); //I don't think a single pass of pairwise exchanges is enough to randomize the vector.
430  random_permutation( in, RG );
431  random_permutation( in, RG );
432 
433  for ( utility::vector1< ConstraintCOP >::const_iterator it = in.begin(); it != in.end(); ++it ) {
434  AmbiguousNMRConstraintCOP cst_in_casted;
435  cst_in_casted = dynamic_cast< AmbiguousNMRConstraint const* >( (*it).get() );
436  if ( cst_in_casted ) {
437  tr.Debug << "casted to AmbiguousNMRConstraint: " << std::endl;
438  for ( utility::vector1< ConstraintCOP >::const_iterator multi_it = cst_in_casted->member_constraints().begin(); multi_it != cst_in_casted->member_constraints().end(); ++multi_it ) {
439  count_constraint( *multi_it, cst_in_casted->member_constraints().size() > 1 , count_matrix, influence_width, total_residue );
440  }
441  } else {
442  count_constraint( *it, false, count_matrix, influence_width, total_residue );
443  }
444  }
445 
446  if ( tr.Trace.visible() ) {
447  for ( Size i=1; i<=total_residue; ++i ) {
448  for ( Size j=i+1; j<=total_residue; ++j ) {
449  tr.Trace << i << " " << j << " " << count_matrix( i, j ) << std::endl;
450  }
451  }
452  }
453 
454  for ( utility::vector1< ConstraintCOP >::const_iterator it = in.begin(); it != in.end(); ++it ) {
455 
456  AmbiguousNMRConstraintCOP cst_in_casted;
457  cst_in_casted = dynamic_cast< AmbiguousNMRConstraint const* >( (*it).get() );
458  bool keep( false );
459  if ( cst_in_casted ) {
460  for ( utility::vector1< ConstraintCOP >::const_iterator multi_it = cst_in_casted->member_constraints().begin(); multi_it != cst_in_casted->member_constraints().end(); ++multi_it ) {
461  keep |= keep_constraint( *multi_it, cst_in_casted->member_constraints().size() > 1, count_matrix, influence_width, total_residue );
462  }
463  } else {
464  keep = keep_constraint( *it, false, count_matrix, influence_width, total_residue );
465  }
466 
467  if ( keep ) {
468  out.push_back( *it );
469  }
470  }
471 
472  in = out;
473 
474  if ( tr.Trace.visible() ) {
475  for ( Size i=1; i<=total_residue; ++i ) {
476  for ( Size j=i+1; j<=total_residue; ++j ) {
477  tr.Trace << i << " " << j << " " << count_matrix( i, j ) << std::endl;
478  }
479  }
480  }
481  tr.Info << "remaining non-redundant constraints " << in.size() << std::endl;
482 }
483 
486  for ( utility::vector1< ConstraintCOP >::const_iterator it = in.begin(); it != in.end(); ++it ) {
487  if ( RG.uniform() >= drop_rate ) {
488  out.push_back( *it );
489  }
490  }
491  in = out;
492 }
493 
494 
495 } // namespace constraints
496 } // namespace scoring
497 } // namespace core