Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HackAroEnergy.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 core/scoring/hackelec/HackAroEnergy.cc
11 /// @brief Electrostatics energy method for aromatic side chain (stand-in for pi/pi interactions).
12 /// @author Rhiju Das
13 
14 
15 // Unit headers
18 
19 // Package headers
23 #include <core/scoring/Energies.hh>
24 #include <core/kinematics/Stub.hh>
25 #include <core/types.hh>
27 // AUTO-REMOVED #include <core/chemical/AtomType.hh>
28 #include <core/pose/Pose.hh>
29 // AUTO-REMOVED #include <core/conformation/RotamerSetBase.hh>
30 #include <numeric/xyzMatrix.hh>
31 
32 #include <core/id/AtomID.hh>
33 #include <utility/vector1.hh>
34 
35 // ObjexxFCL headers
36 
37 // C++
38 
39 
40 /////////////////////////////////////////////////////////////////////////////////////////
41 // Trying to get more "T-shaped" edge-to-face interactions of aromatic side chains.
42 // This is very similar to Kira's fa_plane in rosetta++, though I haven't bothered
43 // to parameterize as carefully. This is just a hacky functional form whose derivatives
44 // are easy to calculate and smooth.
45 // Perhaps the best approach would be to calculate, e.g., benzene-benzene interactions
46 // with high level quantum calculations -- but note that you need really careful treatment
47 // of electron correlations to get dispersion right -- still not quite feasible for all rigid body
48 // orientations.
49 // (I also tried using hackelec_aro_aro, i.e., coulomb's law between positively charged aromatic
50 // hydrogens and the negative partial charges on aromatic carbons -- it didn't quite give me
51 // what I wanted). Rhiju, Dec. 2009.
52 /////////////////////////////////////////////////////////////////////////////////////////
53 
54 using core::Real;
56 
57 namespace core {
58 namespace scoring {
59 namespace hackaro {
60 
61 
62 /// @details This must return a fresh instance of the HackAroEnergy class,
63 /// never an instance already in use
67 ) const {
68  return new HackAroEnergy;
69 }
70 
73  ScoreTypes sts;
74  sts.push_back( hack_aro );
75  return sts;
76 }
77 
78 /// c-tor
81 {}
82 
83 //clone
86 {
87  return new HackAroEnergy;
88 }
89 
90 
91 ///
92 void
94 {
96 }
97 
98 ///
99 void
101 {
103 }
104 
105 
106 /////////////////////////////////////////////////////////////////////////////
107 // scoring
108 /////////////////////////////////////////////////////////////////////////////
109 
110 ///
111 void
113  conformation::Residue const & rsd1,
114  conformation::Residue const & rsd2,
115  pose::Pose const &,
116  ScoreFunction const &,
117  EnergyMap & emap
118 ) const
119 {
120  // Aromatic means: PHE, TRP, TYR (not HIS, currently).
121  if ( rsd1.is_aromatic() && rsd2.is_aromatic() ) {
122  residue_pair_energy_aro_aro( rsd1, rsd2, emap );
123  }
124 }
125 
126 
127 ///////////////////////////////////////////////////////////////////////////////
128 Vector
130 {
131 
132  Vector centroid( 0.0 );
133  Size numatoms = 0;
134  for ( Size i=rsd.first_sidechain_atom(); i<= rsd.nheavyatoms(); ++i ) {
135  centroid += rsd.xyz(i);
136  numatoms++;
137  }
138  if (numatoms > 0 ) {
139  centroid /= static_cast< Real >( numatoms );
140  } else { //Yo, is this a glycine?
141  assert( rsd.aa() == chemical::aa_gly );
142  centroid = rsd.xyz( "CA" );
143  }
144 
145  return centroid;
146 }
147 
148 /////////////////////////////////////////////////////////////////////////////////
151 {
152  using namespace chemical;
153  Size res_type = rsd.aa();
154 
155  Vector x,y,z;
156 
157  // Make an axis pointing from base centroid to Watson-Crick edge.
158  std::string WC_atom;
159  if ( res_type == aa_phe ) WC_atom = " CZ ";
160  if ( res_type == aa_tyr ) WC_atom = " CZ ";
161  if ( res_type == aa_trp ) WC_atom = " CZ2";
162 
163  Vector const WC_coord (rsd.xyz( WC_atom ) );
164  x = WC_coord - centroid;
165  x.normalize();
166 
167  // Make a perpendicular axis pointing from centroid towards
168  // Hoogstein edge (e.g., major groove in a double helix).
169  std::string H_atom;
170  if ( res_type == aa_phe ) H_atom = " CD1";
171  if ( res_type == aa_tyr ) H_atom = " CD1";
172  if ( res_type == aa_trp ) H_atom = " CD1";
173 
174  Vector const H_coord (rsd.xyz( H_atom ) );
175  y = H_coord - centroid; //not orthonormal yet...
176  z = cross(x, y);
177  z.normalize(); // Should poSize roughly 5' to 3' if in a double helix.
178 
179  y = cross(z, x);
180  y.normalize(); //not necessary but doesn't hurt.
181 
182  // std::cout << "WC : " << WC_coord << " H : " << H_coord << " centroid: " << centroid << std::endl;
183 
184  return kinematics::Stub( Matrix::cols( x, y, z ), centroid );
185 }
186 
187 ///////////////////////////////////////////////////////////////
188 Real
190  Real const cos_theta,
191  Real & deriv ) const{
192 
193  //Size cos_theta_bin;
194 
195  // Favor "T-shaped" arrangements with theta = 90 degrees.
196  // - sin^4 ( theta )
197  Real const value = -1 * ( 1 - cos_theta * cos_theta) * ( 1 - cos_theta * cos_theta);
198  deriv = 4 * ( 1 - cos_theta * cos_theta ) * cos_theta;
199 
200  return value;
201 
202  // DON'T KEEP THIS AROUND!
203  //deriv = 0.0;
204  // return 1.0;
205 
206 }
207 
208 ///////////////////////////////////////////////////////////////
209 Real
211  Real const dist,
212  Real & deriv ) const{
213 
214  using namespace core::scoring::constraints;
215 
216  static Real const lower_bound_( -2.0 );
217  static Real const upper_bound_( 7.0 );
218  static Real const bound_zone_ ( 2.0 ); // bonus is flat below 5.0 Angstroms.
219  static Real const well_depth_ ( 1.0 ); // angular dependence goes negative.
220  static FuncOP dist_func_( new FadeFunc( lower_bound_, upper_bound_, bound_zone_, well_depth_) );
221 
222  Real const value = dist_func_->func( dist );
223  deriv = dist_func_->dfunc( dist );
224 
225  return value;
226 
227  //deriv = 0.0;
228  //return 1.0;
229 
230 }
231 
232 //////////////////////////////////////////////////////////////////////////////////
233 void
235  conformation::Residue const & rsd1,
236  conformation::Residue const & rsd2,
237  EnergyMap & emap
238 ) const
239 {
240 
241  assert( rsd1.is_aromatic() );
242  assert( rsd2.is_aromatic() );
243 
244  Vector centroid1 = get_centroid( rsd1 );
245  kinematics::Stub stub1 = get_base_coordinate_system( rsd1, centroid1 );
246 
247  Vector centroid2 = get_centroid( rsd2 );
248  kinematics::Stub stub2 = get_base_coordinate_system( rsd2, centroid2 );
249 
250  Real const cos_theta = dot( stub1.M.col_z(), stub2.M.col_z() );
251  Real const cen_dist = ( centroid1 - centroid2 ).length();
252 
253  Real dummy( 0.0 );
254  Real const angle_score = get_aro_axis_score_ANGLE( cos_theta, dummy );
255  Real const dist_score = get_aro_axis_score_DIST( cen_dist, dummy );
256 
257  Real const total_score = angle_score * dist_score;
258 
259  emap[ hack_aro ] += total_score;
260 
261 }
262 
263 /////////////////////////////////////////////////////////////
264 Size
266 {
267  chemical::AtomIndices const & atom_indices = rsd.chi_atoms( 2 /*chi # 2 must be torsion that controls aromatic base*/ );
268  return atom_indices[ 4 ]; /* C2' ... C1' ... first base atom ... chi1 torsion atom*/
269 }
270 
271 /////////////////////////////////////////////
272 void
274  id::AtomID const & atom_id,
275  pose::Pose const & pose,
276  kinematics::DomainMap const & domain_map,
277  ScoreFunction const &,
278  EnergyMap const & weights,
279  Vector & F1,
280  Vector & F2
281  ) const
282 {
283 
284  using namespace chemical;
285 
286  Size const pos1( atom_id.rsd() );
287  Size const i ( atom_id.atomno() );
288  conformation::Residue const & rsd1( pose.residue( pos1 ) );
289 
290  if ( !rsd1.is_aromatic() ) return;
291 
292  // Only works for proteins!!!!!!!!!!!!
293  if (i != chi2_torsion_atom_index( rsd1 ) ) return;
294 
295  int const pos1_map( domain_map( pos1 ) );
296  bool const pos1_fixed( pos1_map != 0 );
297 
298  // cached energies object
299  Energies const & energies( pose.energies() );
300 
301  // the neighbor/energy links
302  EnergyGraph const & energy_graph( energies.energy_graph() );
303 
304  // loop over *all* nbrs of rsd1 (not just upper or lower)
306  iru = energy_graph.get_node( pos1 )->const_edge_list_begin(),
307  irue = energy_graph.get_node( pos1 )->const_edge_list_end();
308  iru != irue; ++iru ) {
309  Size const pos2( (*iru)->get_other_ind( pos1 ) );
310 
311  if ( pos1_fixed && pos1_map == domain_map( pos2 ) ) continue; // fixed wrt one another
312 
313  conformation::Residue const & rsd2( pose.residue( pos2 ) );
314 
315  if ( !rsd2.is_aromatic() ) continue;
316 
317  assert( pos2 != pos1 );
318 
319  eval_atom_derivative_aro_aro( rsd1, rsd2, weights, F1, F2 );
320 
321  } // loop over nbrs of rsd1
322 
323 }
324 
325 
326 //////////////////////////////////////////////////
327 void
329  conformation::Residue const & rsd1,
330  conformation::Residue const & rsd2,
331  EnergyMap const & weights,
332  Vector & F1,
333  Vector & F2
334  ) const
335 {
336 
337  assert( rsd1.is_aromatic() );
338  assert( rsd2.is_aromatic() );
339 
340  Vector centroid1 = get_centroid( rsd1 );
341  kinematics::Stub stub1 = get_base_coordinate_system( rsd1, centroid1 );
342 
343  Vector centroid2 = get_centroid( rsd2 );
344  kinematics::Stub stub2 = get_base_coordinate_system( rsd2, centroid2 );
345 
346  Real const cos_theta = dot( stub1.M.col_z(), stub2.M.col_z() );
347  Vector const d_i_j = centroid1 - centroid2;
348  Real const cen_dist = d_i_j.length();
349  Vector const r_i_j = d_i_j / cen_dist;
350 
351  Real angle_deriv( 0.0 ), dist_deriv( 0.0 );
352  Real const angle_score = get_aro_axis_score_ANGLE( cos_theta, angle_deriv );
353  Real const dist_score = get_aro_axis_score_DIST( cen_dist, dist_deriv );
354 
355  //Real const total_score = angle_score * dist_score;
356 
357  // checked my previous wrk for rna_stack_axis, et.c., in RNA_LowResolutionPotential.cc
358  Matrix const & M_i( stub1.M );
359  Vector const & z_i = M_i.col_z();
360  Matrix const & M_j( stub2.M );
361  Vector const & z_j = M_j.col_z();
362 
363  Vector const f2 =
364  -1.0 * angle_score * dist_deriv * r_i_j;
365 
366  Vector const f1 = cross( f2, centroid2 ) + dist_score * angle_deriv * cross( z_i, z_j );
367 
368  F1 -= weights[ hack_aro ] * f1;
369  F2 -= weights[ hack_aro ] * f2;
370 
371 }
372 
373 
374 /// @brief HackAroEnergy is context independent; no context graphs required
375 void
377 {
378 }
379 
380 Distance
382  return 4.0; // pad by 4.0 because these are long sidechains?
383 }
386 {
387  return 1; // Initial versioning
388 }
389 
390 
391 
392 }
393 }
394 }