Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CentroidDisulfidePotential.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 sw=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 core/scoring/disulfides/CentroidDisulfidePotential.cc
11 /// @brief Centroid Disulfide Energy Potentials
12 /// @author Spencer Bliven <blivens@u.washington.edu>
13 /// @date 12/17/08
14 
15 // Unit Headers
17 
18 // Project Headers
23 #include <basic/database/open.hh>
25 
26 // Utility Headers
27 #include <utility/io/izstream.hh>
28 #include <utility/vector1.hh>
29 
30 // Numeric headers
31 #include <numeric/constants.hh>
32 #include <numeric/interpolation/Histogram.hh>
33 
34 
35 #include <basic/Tracer.hh>
36 
37 #include <numeric/xyz.functions.hh>
38 
39 static basic::Tracer TR("core.scoring.disulfides.CentroidDisulfidePotential");
40 
41 
42 using namespace core;
44 using namespace numeric::interpolation;
46 using std::string;
47 using utility::vector1;
48 
49 namespace core {
50 namespace scoring {
51 namespace disulfides {
52 
53 /**
54  * Constructor
55  */
56 CentroidDisulfidePotential::CentroidDisulfidePotential() {}
57 
58 /**
59  * Deconstructor
60  */
61 CentroidDisulfidePotential::~CentroidDisulfidePotential() {}
62 
63 /**
64  * @brief Calculates scoring terms for the disulfide bond specified
65  * @note Equivalent to the expanded form, but discards geometry info
66  */
67 void
68 CentroidDisulfidePotential::score_disulfide(
69  Residue const & res1,
70  Residue const & res2,
71  Energy & cbcb_distance_score,
72  Energy & centroid_distance_score,
73  Energy & cacbcb_angle_1_score,
74  Energy & cacbcb_angle_2_score,
75  Energy & cacbcbca_dihedral_score,
76  Energy & backbone_dihedral_score
77  ) const
78 {
79  Real cbcb_distance_sq, centroid_distance_sq, cacbcb_angle_1, cacbcb_angle_2,
80  cacbcbca_dihedral, backbone_dihedral, score_factor;
81  score_disulfide(res1,
82  res2,
83  cbcb_distance_sq,
84  centroid_distance_sq,
85  cacbcb_angle_1,
86  cacbcb_angle_2,
87  cacbcbca_dihedral,
88  backbone_dihedral,
89  cbcb_distance_score,
90  centroid_distance_score,
91  cacbcb_angle_1_score,
92  cacbcb_angle_2_score,
93  cacbcbca_dihedral_score,
94  backbone_dihedral_score,
95  score_factor
96  );
97 }
98 
99 /**
100  * @brief Calculates scoring terms and geometry
101  *
102  * If a full atom pose is given, centroid_distance_score will be zero.
103  *
104  * If one of the residues is glycine it will be replaced with alanine for
105  * the scores which require a CB atom.
106  *
107  * @note distances are given squared to avoid calling std::sqrt unnecessarily
108  */
109 void
110 CentroidDisulfidePotential::score_disulfide(
111  core::conformation::Residue const & res1,
112  core::conformation::Residue const & res2,
113  core::Real & cbcb_distance_sq,
114  core::Real & centroid_distance_sq,
115  core::Real & cacbcb_angle_1,
116  core::Real & cacbcb_angle_2,
117  core::Real & cacbcbca_dihedral,
118  core::Real & backbone_dihedral,
119  core::Energy & cbcb_distance_score,
120  core::Energy & centroid_distance_score,
121  core::Energy & cacbcb_angle_1_score,
122  core::Energy & cacbcb_angle_2_score,
123  core::Energy & cacbcbca_dihedral_score,
124  core::Energy & backbone_dihedral_score,
125  core::Real & cb_score_factor
126  ) const
127 {
128  //The range of cb distances present in nature (squared)
129  static const Real min_native_cb_dist_sq = 10; //ang^2
130  static const Real max_native_cb_dist_sq = 22; //ang^2
131  //Cutoff to calculate the angle terms
132  static const Real max_cb_dist_sq = 400; //ang^2
133 
134  //Calculate the distances and angles of this disulfide
135  disulfide_params(res1, res2,
136  cbcb_distance_sq,
137  centroid_distance_sq,
138  cacbcb_angle_1,
139  cacbcb_angle_2,
140  cacbcbca_dihedral,
141  backbone_dihedral);
142 
143 
144  //Interpolate scores from the parameters
145  //Do the unscaled scores here, then the reweighted scores
146  cbcb_distance_score = cb_distance_func_->func(cbcb_distance_sq);
147 
148  if(centroid_distance_sq < 0) {
149  //Indicates error, probably full atom mode
150  centroid_distance_score = 0.0;
151  } else {
152  centroid_distance_score = cen_distance_func_->func(centroid_distance_sq);
153  }
154 
155  //Score factor: Reweight angle scores based on the cb distance squared
156  //0-10A^2 0.0
157  //10-22A^2 1.0
158  //22-400A^2 linear function between (22,1) and (400,0)
159  //>400A^2 0.0
160  if( cbcb_distance_sq < min_native_cb_dist_sq || max_cb_dist_sq < cbcb_distance_sq ) {
161  //cb_score_factor = 0.; don't bother scoring
162  cacbcb_angle_1_score = 0.;
163  cacbcb_angle_2_score = 0.;
164  cacbcbca_dihedral_score = 0.;
165  backbone_dihedral_score = 0.;
166  return;
167  }
168  else if( cbcb_distance_sq < max_native_cb_dist_sq ) { //native range
169  cb_score_factor = 1.;
170  }
171  else { //longer than native, so linearly decay to zero
172  //slope = 1/( 22 - 400), x-intercept = 400
173  cb_score_factor = (cbcb_distance_sq - max_cb_dist_sq) /
174  (max_native_cb_dist_sq - max_cb_dist_sq);
175  }
176 
177  cacbcb_angle_1_score = cacbcb_angle_func_->func(cacbcb_angle_1);
178  cacbcb_angle_2_score = cacbcb_angle_func_->func(cacbcb_angle_2);
179  cacbcbca_dihedral_score = cacbcbca_dihedral_func_->func(cacbcbca_dihedral);
180  backbone_dihedral_score = ncacac_dihedral_func_->func(backbone_dihedral);
181 
182  cacbcbca_dihedral_score *= cb_score_factor;
183  backbone_dihedral_score *= cb_score_factor;
184  cacbcb_angle_1_score *= cb_score_factor;
185  cacbcb_angle_2_score *= cb_score_factor;
186 }
187 
188 
189 /**
190  * @brief calculates some degrees of freedom between two centroid cys residues
191  *
192  * If one of the residues is glycine it will be substituted with an idealize
193  * alanine geometry for the calculations which require a Cb molecule.
194  *
195  * centroid_distance requires CEN atoms be defined. If full atom residues
196  * are specified this function returns centroid_distance of -1.
197  *
198  * @param cbcb_distance The distance between Cbetas squared
199  * @param centroid_distance The distance between centroids squared
200  * @param cacbcb_angle_1 The Ca1-Cb1-Cb2 planar angle, in degrees
201  * @param cacbcb_angle_2 The Ca2-Cb2-Cb1 planar angle, in degrees
202  * @param cacbcbca_dihedral The Ca1-Cb1-Cb2-Ca2 dihedral angle
203  * @param backbone_dihedral The N-Ca1-Ca2-C2 dihedral angle
204  */
205 void
206 CentroidDisulfidePotential::disulfide_params(
207  Residue const& res1,
208  Residue const& res2,
209  Real & cbcb_distance_sq,
210  Real & centroid_distance_sq,
211  Real & cacbcb_angle_1,
212  Real & cacbcb_angle_2,
213  Real & cacbcbca_dihedral,
214  Real & backbone_dihedral)
215 {
216  using numeric::constants::d::radians_to_degrees;
217 
218  conformation::ResidueCAP res1_ptr(&res1);
219  conformation::ResidueCAP res2_ptr(&res2);
220  // Glycines pose a problem because they have no CB atom.
221  // Therefor mutate Gly to Ala first
222  if(res1.aa() == chemical::aa_gly) {
223  //dummy conformation; would only be used if bb atoms missing, e.g. Pro
224  conformation::Conformation conformation;
225  chemical::ResidueTypeSetCAP restype_set =
228  restype_set->name_map("ALA"), res1, conformation) );
229  }
230  if(res2.aa() == chemical::aa_gly) {
231  //dummy conformation; would only be used if bb atoms missing, e.g. Pro
232  conformation::Conformation conformation;
233  chemical::ResidueTypeSetCAP restype_set =
236  restype_set->name_map("ALA"), res2, conformation) );
237  }
238  //Make sure they both have CB now
239  assert(res1_ptr->type().has_atom_name("CB"));
240  assert(res2_ptr->type().has_atom_name("CB"));
241 
242  Vector const& calpha_1 ( res1_ptr->xyz("CA") );
243  Vector const& cbeta_1 ( res1_ptr->xyz("CB") );
244  Vector const& n_1 ( res1_ptr->xyz("N") );
245  Vector const& calpha_2 ( res2_ptr->xyz("CA") );
246  Vector const& cbeta_2 ( res2_ptr->xyz("CB") );
247  Vector const& c_2 ( res2_ptr->xyz("C") );
248 
249  cbcb_distance_sq = cbeta_1.distance_squared(cbeta_2);
250  cacbcb_angle_1 = angle_of( calpha_1, cbeta_1, cbeta_2);
251  cacbcb_angle_2 = angle_of( calpha_2, cbeta_2, cbeta_1);
252  cacbcb_angle_1 *= radians_to_degrees; // convert
253  cacbcb_angle_2 *= radians_to_degrees; // convert
254  cacbcbca_dihedral = dihedral_degrees(calpha_1,cbeta_1,cbeta_2,calpha_2);
255  //Use N-Ca-Ca-C instead of N-Ca-Ca-N to follow the fold tree.
256  backbone_dihedral = dihedral_degrees(n_1, calpha_1, calpha_2, c_2);
257 
258  centroid_distance_sq = -1;
259  if( res1_ptr->type().has_atom_name("CEN") &&
260  res2_ptr->type().has_atom_name("CEN") )
261  {
262  Vector const& cen_1( res1_ptr->xyz("CEN"));
263  Vector const& cen_2( res2_ptr->xyz("CEN"));
264  centroid_distance_sq = cen_1.distance_squared(cen_2);
265 
266  //Postcondition validation
267  assert(0. <= centroid_distance_sq );
268  }
269  assert(0. <= cbcb_distance_sq);
270  assert(0. <= cacbcb_angle_1); assert( cacbcb_angle_1 <= 180. );
271  assert(0. <= cacbcb_angle_2); assert( cacbcb_angle_2 <= 180. );
272 }
273 
274 Cb_Distance_FuncCOP CentroidDisulfidePotential::cb_distance_func_ =
275  new Cb_Distance_Func();
276 Cen_Distance_FuncCOP CentroidDisulfidePotential::cen_distance_func_ =
277  new Cen_Distance_Func();
278 CaCbCb_Angle_FuncCOP CentroidDisulfidePotential::cacbcb_angle_func_ =
279  new CaCbCb_Angle_Func();
280 NCaCaC_Dihedral_FuncCOP CentroidDisulfidePotential::ncacac_dihedral_func_ =
281  new NCaCaC_Dihedral_Func();
282 CaCbCbCa_Dihedral_FuncCOP CentroidDisulfidePotential::cacbcbca_dihedral_func_ =
284 
285 /**
286  * @brief Decide whether there is a disulfide bond between two residues.
287  *
288  * Does not require that the residues be cysteines, so if this is important
289  * you should check for CYS first. (The relaxed requirements are useful for
290  * design.)
291  */
292 bool CentroidDisulfidePotential::is_disulfide(
293  Residue const & res1,
294  Residue const & res2) const
295 {
296  //Get Cb distance score
297  Energy cbcb_distance_score,
298  centroid_distance_score,
299  cacbcb_angle_1_score,
300  cacbcb_angle_2_score,
301  cacbcbca_dihedral_score,
302  backbone_dihedral_score;
303  Real cbcb_distance_sq,
304  centroid_distance_sq,
305  cacbcb_angle_1,
306  cacbcb_angle_2,
307  cacbcbca_dihedral,
308  backbone_dihedral,
309  score_factor;
310  score_disulfide(res1,
311  res2,
312  cbcb_distance_sq,
313  centroid_distance_sq,
314  cacbcb_angle_1,
315  cacbcb_angle_2,
316  cacbcbca_dihedral,
317  backbone_dihedral,
318  cbcb_distance_score,
319  centroid_distance_score,
320  cacbcb_angle_1_score,
321  cacbcb_angle_2_score,
322  cacbcbca_dihedral_score,
323  backbone_dihedral_score,
324  score_factor
325  );
326 
327 
328  return cbcb_distance_score <= disulfide_cb_dist_cutoff &&
329  cacbcb_angle_1 >= 60. &&
330  cacbcb_angle_2 >= 60. ;
331 }
332 
333 ///@brief the Cysteines with cb dist scores less than this threshold are
334 /// very likely (99%) to be disulfide bonded.
335 const Real CentroidDisulfidePotential::disulfide_cb_dist_cutoff(4.392);
336 
337 
338 ///////////////////////
339 // Scoring Functions //
340 ///////////////////////
341 
342 /// @brief Helper function for initializing Histograms from the database
343 /// @note The static functions in FullatomDisulfidePotential are a more elegant
344 /// way to initialize the Histograms
345 static HistogramCOP<Real,Real>::Type
346 histogram_from_db(string file) {
347  utility::io::izstream scores_stream;
348  basic::database::open( scores_stream, file);
349  HistogramCOP<Real,Real>::Type scores = new Histogram<Real,Real>( scores_stream() );
350  scores_stream.close();
351  return scores;
352 }
353 
354 //Cb_Distance_Func
355 Cb_Distance_Func::Cb_Distance_Func() {}
356 Cb_Distance_Func::~Cb_Distance_Func() {}
357 Real Cb_Distance_Func::func( Real const cb_dist_sq_) const {
359  Energy score = base_score_;
360  for(Size i = 0; i<3; ++i ) {
361  score -= dgaussian(cb_dist_sq_, means_[i], sds_[i], weights_[i] );
362  }
363 
364  return score;
365 }
366 Real Cb_Distance_Func::dfunc( Real const) const {
367  return 0.0;
368 }
369 const Real Cb_Distance_Func::means_[3] = { 12.445, 15.327, 14.0 };
370 const Real Cb_Distance_Func::sds_[3] = { 1.1737973, 2.1955666, 0.3535534 };
371 const Real Cb_Distance_Func::weights_[3] = {10.8864116, 33.5711622, 0.2658681 };
372 const Real Cb_Distance_Func::base_score_ = 0.0;
373 
374 //Cen_Distance_Func
375 Cen_Distance_Func::Cen_Distance_Func() {}
376 Cen_Distance_Func::~Cen_Distance_Func() {}
377 Real Cen_Distance_Func::func( Real const cen_dist_sq) const {
378  if( centroid_dist_scores_ == 0)
379  centroid_dist_scores_ = histogram_from_db("scoring/score_functions/disulfides/centroid_distance_score");
380  Real e(0.0);
381  centroid_dist_scores_->interpolate(cen_dist_sq,e);
382  return e;
383 }
384 Real Cen_Distance_Func::dfunc( Real const ) const {
385  return 0.0;
386 }
387 HistogramCOP<Real,Real>::Type Cen_Distance_Func::centroid_dist_scores_ = 0;
388 
389 //CaCbCb_Angle_Func
390 CaCbCb_Angle_Func::CaCbCb_Angle_Func() {}
391 CaCbCb_Angle_Func::~CaCbCb_Angle_Func() {}
392 Real CaCbCb_Angle_Func::func( Real const cacbcb_angle) const {
393  if( CaCbCb_angle_scores_ == 0 )
394  CaCbCb_angle_scores_ = histogram_from_db("scoring/score_functions/disulfides/centroid_CaCbCb_angle_score");
395  Real e(0.0);
396  CaCbCb_angle_scores_->interpolate(cacbcb_angle,e);
397  return e;
398 }
399 Real CaCbCb_Angle_Func::dfunc( Real const ) const {
400  return 0.0;
401 }
402 HistogramCOP<core::Real,core::Real>::Type CaCbCb_Angle_Func::CaCbCb_angle_scores_ = 0;
403 
404 
405 //NCaCaC_Dihedral_Func
406 NCaCaC_Dihedral_Func::NCaCaC_Dihedral_Func() {}
407 NCaCaC_Dihedral_Func::~NCaCaC_Dihedral_Func() {}
408 Real NCaCaC_Dihedral_Func::func( Real const backbone_dihedral) const {
409  if( backbone_dihedral_scores_ == 0 )
410  backbone_dihedral_scores_ = histogram_from_db("scoring/score_functions/disulfides/centroid_backbone_dihedral_score");
411  Real e(0.0);
412  backbone_dihedral_scores_->interpolate(backbone_dihedral, e);
413  return e;
414 }
415 Real NCaCaC_Dihedral_Func::dfunc( Real const ) const {
416  return 0.0;
417 }
418 HistogramCOP<core::Real,core::Real>::Type NCaCaC_Dihedral_Func::backbone_dihedral_scores_ = 0;
419 
420 
421 
422 //CaCbCbCa_Dihedral_Func
423 CaCbCbCa_Dihedral_Func::CaCbCbCa_Dihedral_Func() {}
424 CaCbCbCa_Dihedral_Func::~CaCbCbCa_Dihedral_Func() {}
425 Real CaCbCbCa_Dihedral_Func::func( Real const cacbcbca_dihedral) const {
426  if( CaCbCbCa_dihedral_scores_ == 0 )
427  CaCbCbCa_dihedral_scores_ = histogram_from_db("scoring/score_functions/disulfides/centroid_CaCbCbCa_dihedral_score");
428  Real e(0.0);
429  CaCbCbCa_dihedral_scores_->interpolate(cacbcbca_dihedral,e);
430  return e;
431 }
432 Real CaCbCbCa_Dihedral_Func::dfunc( Real const ) const {
433  return 0.0;
434 }
435 HistogramCOP<core::Real,core::Real>::Type CaCbCbCa_Dihedral_Func::CaCbCbCa_dihedral_scores_ = 0;
436 
437 
438 } // disulfides
439 } // scoring
440 } // core