Rosetta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SugarBackboneEnergy.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/methods/carbohydrates/SugarBackboneEnergy.hh
11 /// @brief Method definitions for SugarBackboneEnergy and SugarBackboneEnergyCreator.
12 /// @author Labonte <JWLabonte@jhu.edu>
13 
14 
15 // Unit headers
20 
21 // Package headers
25 
26 // Project headers
27 #include <core/id/TorsionID.hh>
28 #include <core/chemical/VariantType.hh>
32 #include <core/pose/Pose.hh>
34 
35 // Numeric headers
36 #include <numeric/conversions.hh>
37 #include <numeric/angle.functions.hh>
38 
39 // Basic header
40 #include <basic/Tracer.hh>
41 
42 
43 // Construct tracer.
44 static THREAD_LOCAL basic::Tracer TR( "core.scoring.methods.carbohydrates.SugarBackboneEnergy" );
45 
46 
47 namespace core {
48 namespace scoring {
49 namespace methods {
50 namespace carbohydrates {
51 
52 // Public methods /////////////////////////////////////////////////////////////
53 // Standard methods ///////////////////////////////////////////////////////////
54 // Default constructor
57  E_( ScoringManager::get_instance()->get_CHIEnergyFunction() )
58 {}
59 
60 
61 // General EnergyMethod Methods ///////////////////////////////////////////////
64 {
65  return EnergyMethodOP( new SugarBackboneEnergy );
66 }
67 
68 
69 // OneBodyEnergy Methods //////////////////////////////////////////////////////
70 // Evaluate the one-body carbohydrate backbone energies for a particular residue.
71 void
73  conformation::Residue const & rsd,
74  pose::Pose const & pose,
75  EnergyMap & emap ) const
76 {
77  using namespace utility;
78  using namespace chemical::rings;
79  using namespace chemical::carbohydrates;
80  using namespace scoring::carbohydrates;
81 
82  // This is a carbohydrate-only scoring method.
83  if ( ! rsd.is_carbohydrate() ) { return; }
84 
85  // Phi and psi are meaningless for reducing-end sugars.
86  if ( rsd.is_lower_terminus() ) { return; }
87 
88  // Ignore REPLONLY variants.
89  if ( rsd.has_variant_type( core::chemical::REPLONLY ) ) { return; }
90 
91  uint const seqpos( rsd.seqpos() );
92  Angle phi( pose.phi( seqpos ) );
93  Angle psi( pose.psi( seqpos ) );
95 
96  Energy score( 0.0 );
97 
98 
99  // Calculate phi component.
100  if ( info->is_L_sugar() ) {
101  // L-Sugars use the mirror image of the score functions.
102  phi = -phi;
103  }
104  // TODO: Wood's lab assumed that the rings would always be 4C1 chairs. If an alpha sugar is flipped, it should
105  // probably be treated as a beta. I should probably abandon getting the anomeric form and explicitly determine
106  // axial/equatorial here too.
107  if ( info->is_alpha_sugar() ) {
108  score += E_( ALPHA_LINKS, phi );
109  } else if ( info->is_beta_sugar() ) {
110  score += E_( BETA_LINKS, phi );
111  } // ...else it's a linear sugar, and this scoring method does not apply.
112 
113 
114  // Calculate psi component.
115  // For psi, we need to get information from the previous residue.
116  conformation::Residue const & prev_rsd( pose.residue(
118  // If this is not a saccharide residue, do nothing.
119  if ( prev_rsd.is_carbohydrate() ) {
120  CarbohydrateInfoCOP prev_info( prev_rsd.carbohydrate_info() );
121  // If this is not a pyranose, do nothing, because we do not have statistics for this residue.
122  if ( prev_info->is_pyranose() ) {
123  // What is our connecting atom?
124  uint const connect_atom( prev_rsd.connect_atom( rsd ) );
125 
126  // Next, convert the psi to between 0 and 360 (because that's what the function expects).
127  psi = numeric::nonnegative_principal_angle_degrees( psi );
128 
129  if ( prev_info->is_L_sugar() ) {
130  // L-Sugars use the mirror image of the score functions.
131  psi = 360 - psi;
132  }
133 
134  // Now, get the ring atoms.
135  // We can assume that the ring we care about is the 1st ring, since this is a sugar.
136  vector1< uint > const ring_atoms( prev_rsd.type().ring_atoms( 1 ) );
137 
138  // Next, we must figure out which position on the ring has the glycosidic bond.
139  uint position( 0 );
140  vector1< uint > const bonded_heavy_atoms( prev_rsd.get_adjacent_heavy_atoms( connect_atom ) );
141  Size const n_bonded_heavy_atoms( bonded_heavy_atoms.size() );
142  Size const n_ring_atoms( ring_atoms.size() );
143  for ( uint i( 1 ); i <= n_bonded_heavy_atoms; ++i ) {
144  for ( uint j( 1 ); j <= n_ring_atoms; ++ j ) {
145  if ( ring_atoms[ j ] == bonded_heavy_atoms[ i ] ) {
146  // We found the attachment position.
147  position = j;
148  break;
149  }
150  }
151  if ( position != 0 ) {
152  break; // We already found this heavy atom.
153  }
154  }
155 
156  // Finally, check if it's axial or equatorial and call the appropriate function.
157  switch ( is_atom_axial_or_equatorial_to_ring( prev_rsd, connect_atom, ring_atoms ) ) {
158  case AXIAL :
159  if ( position % 2 == 0 ) { // even
160  score += E_( _2AX_3EQ_4AX_LINKS, psi );
161  } else /* odd */ {
162  score += E_( _2EQ_3AX_4EQ_LINKS, psi );
163  }
164  break;
165  case EQUATORIAL :
166  if ( position % 2 == 0 ) { // even
167  score += E_( _2EQ_3AX_4EQ_LINKS, psi );
168  } else /* odd */ {
169  score += E_( _2AX_3EQ_4AX_LINKS, psi );
170  }
171  break;
172  case NEITHER :
173  break;
174  }
175  }
176  }
177  emap[ sugar_bb ] += score;
178 }
179 
180 // Evaluate the DoF derivative for a particular residue.
183  conformation::Residue const & rsd,
184  ResSingleMinimizationData const & /* min_data */,
185  id::DOF_ID const & /* dof_id */,
186  id::TorsionID const & torsion_id,
187  pose::Pose const & pose,
188  ScoreFunction const & /* sf */,
189  EnergyMap const & weights ) const
190 {
191  using namespace std;
192  using namespace numeric;
193  using namespace id;
194  using namespace chemical::rings;
195  using namespace chemical::carbohydrates;
196  using namespace pose::carbohydrates;
197  using namespace scoring::carbohydrates;
198 
199  if ( TR.Debug.visible() ) {
200  TR.Debug << "Evaluating torsion: " << torsion_id << endl;
201  }
202 
203  Real deriv( 0.0 );
204 
205  // Ignore REPLONLY variants.
206  if ( rsd.has_variant_type( chemical::REPLONLY ) ) { return deriv; }
207 
208  // This scoring method only considers glycosidic torsions, which may have either BB, CHI, or BRANCH TorsionIDs.
209  if ( ! torsion_id.valid() ) {
210  if ( TR.Debug.visible() ) {
211  TR.Debug << "Torsion not valid: " << torsion_id << endl;
212  }
213  return deriv;
214  }
215 
216  if ( is_glycosidic_phi_torsion( pose, torsion_id ) ) {
217  // Rosetta defines this torsion angle differently than IUPAC. In addition, this torsion belongs to the next
218  // residue. We need to figure out what that residue is, use pose.phi() to get the value, and see if it's
219  // alpha or beta.
220 
221  // First, what is the next residue?
222  uint next_rsd( 0 );
223  if ( torsion_id.type() == BB ) {
224  // If this is a main-chain torsion, we can be confident that the next residue on this chain MUST be n+1.
225  next_rsd = torsion_id.rsd() + 1;
226  } else if ( torsion_id.type() == BRANCH ) {
227  Size const n_mainchain_connections( rsd.n_polymeric_residue_connections() );
228  next_rsd = rsd.residue_connection_partner( n_mainchain_connections + torsion_id.torsion() );
229  } else {
230  TR.Error << "Torsion " << torsion_id << " cannot be a phi torsion!" << endl;
231  return deriv;
232  }
233 
234  // Now, get the next residue's info and its phi.
235  CarbohydrateInfoCOP info( pose.residue( next_rsd ).carbohydrate_info() );
236  Angle phi( pose.phi( next_rsd ) );
237  if ( TR.Debug.visible() ) {
238  TR.Debug << "Phi: " << phi << endl;
239  }
240  if ( info->is_L_sugar() ) {
241  // L-Sugars use the mirror image of the score functions. The phi functions run from -180 to 180.
242  phi = -phi;
243  }
244 
245  // Finally, we can evaluate.
246  if ( info->is_alpha_sugar() ) {
247  deriv = E_.evaluate_derivative( ALPHA_LINKS, phi );
248  } else if ( info->is_beta_sugar() ) {
249  deriv = E_.evaluate_derivative( BETA_LINKS, phi );
250  } // ...else it's a linear sugar, and this scoring method does not apply.
251  if ( info->is_L_sugar() ) {
252  deriv = -deriv;
253  }
254  } else if ( is_glycosidic_psi_torsion( pose, torsion_id ) ) {
255  // Rosetta defines this torsion angle the same way as IUPAC; however, it is the psi of the following residue.
256  // This should not matter, though, because the CHI energy function only cares about whether the linkage is
257  // axial or equatorial. We can simply convert to a number in degrees between 0 and 360 and call the function.
258 
259  // First, make sure this is a sugar.
260  if ( ! rsd.is_carbohydrate() ) {
261  return deriv;
262  }
263 
264  // Second, if this is not a pyranose, do nothing, because we do not have statistics for this residue.
266  if ( ! info->is_pyranose() ) {
267  return deriv;
268  }
269 
270  // Third, what is our connecting atom?
271  core::uint connect_atom;
272  if ( torsion_id.type() == BB ) {
273  // If this is a main-chain torsion, the connect atom is the UPPER_CONNECT.
274  connect_atom = rsd.upper_connect_atom();
275  } else if ( torsion_id.type() == CHI ) {
276  // If this is a side-chain torsion, the CONNECT atom will be the 3rd atom of the CHI definition.
277  connect_atom = rsd.chi_atoms( torsion_id.torsion() )[ 3 ];
278  } else {
279  TR.Error << "Torsion " << torsion_id << " cannot be a psi torsion!" << endl;
280  return deriv;
281  }
282 
283  // TODO: If I ever add a score for exocyclic psis, I should check if this atom is exocyclic and act
284  // accordingly. For now, the code will just return 0.0, because an exocyclic atom will be NEITHER. ~Labonte
285 
286  // Next, get the psi and convert it to between 0 and 360 (because that's what the function expects).
287  Angle psi( nonnegative_principal_angle_degrees( pose.torsion( torsion_id ) ) );
288  if ( TR.Debug.visible() ) {
289  TR.Debug << "Psi: " << psi << endl;
290  }
291  if ( info->is_L_sugar() ) {
292  // L-Sugars use the mirror image of the score functions.
293  psi = 360 - psi;
294  }
295 
296  // Now, get the ring atoms. We can assume that the ring we care about is the 1st ring, since this is a sugar.
297  utility::vector1< core::uint > const ring_atoms( rsd.type().ring_atoms( 1 ) );
298 
299  // Finally, check if it's axial or equatorial and call the appropriate function.
300  switch ( is_atom_axial_or_equatorial_to_ring( rsd, connect_atom, ring_atoms ) ) {
301  case AXIAL :
302  if ( torsion_id.torsion() % 2 == 0 ) { // even
303  deriv = E_.evaluate_derivative( _2AX_3EQ_4AX_LINKS, psi );
304  } else /* odd */ {
305  deriv = E_.evaluate_derivative( _2EQ_3AX_4EQ_LINKS, psi );
306  }
307  break;
308  case EQUATORIAL :
309  if ( torsion_id.torsion() % 2 == 0 ) { // even
310  deriv = E_.evaluate_derivative( _2EQ_3AX_4EQ_LINKS, psi );
311  } else /* odd */ {
312  deriv = E_.evaluate_derivative( _2AX_3EQ_4AX_LINKS, psi );
313  }
314  break;
315  case NEITHER :
316  break;
317  }
318  if ( info->is_L_sugar() ) {
319  deriv = -deriv;
320  }
321  }
322  return weights[ sugar_bb ] * deriv;
323 }
324 
325 
326 // Creator methods ////////////////////////////////////////////////////////////
327 // Return an up-casted owning pointer (EnergyMethodOP) to the energy method.
330 {
331  return EnergyMethodOP( new SugarBackboneEnergy );
332 }
333 
334 // Return the set of ScoreTypes for which this EnergyMethod is responsible.
337 {
338  ScoreTypes types;
339  types.push_back( sugar_bb );
340  return types;
341 }
342 
343 } // namespace carbohydrates
344 } // namespace methods
345 } // namespace scoring
346 } // namespace core
This object defines a ScoreFunction, it contains methods for calculating the various scoring componen...
virtual core::Real eval_residue_dof_derivative(conformation::Residue const &rsd, ResSingleMinimizationData const &min_data, id::DOF_ID const &dof_id, id::TorsionID const &torsion_id, pose::Pose const &pose, ScoreFunction const &sf, EnergyMap const &weights) const
Evaluate the DoF derivative for a particular residue.
A molecular system including residues, kinematics, and energies.
Definition: Pose.hh:153
bool is_carbohydrate() const
Returns true if this residue is a carbohydrate.
Definition: Residue.hh:1721
Size seqpos() const
Returns the sequence position of this residue.
Definition: Residue.hh:1581
Declarations and simple accessor/mutator definitions for CarbohydrateInfo.
Real Angle
Definition: types.hh:53
Enumerator definition for LinkageType.
std::vector< std::vector< double > > score
Definition: TMalign.cc:61
bool valid() const
Is this id valid?
Definition: TorsionID.hh:120
Real Energy
Definition: types.hh:57
Real evaluate_derivative(LinkageType type, Angle x) const
Size n_polymeric_residue_connections() const
Returns the number of polymeric ResidueConnections on this residue.
Definition: Residue.hh:1155
core::uint find_seqpos_of_saccharides_parent_residue(conformation::Residue const &residue)
Use a saccharide residue's connections to find the residue from which it follows or branches...
Definition: util.cc:70
bool is_lower_terminus() const
Returns true if the residue has a lower terminus variant.
Definition: Residue.hh:1822
platform::Size Size
Definition: types.hh:30
Instance Residue class, used for placed residues and rotamers.
Definition: Residue.hh:90
Size upper_connect_atom() const
Returns the index number of this residue's atom which connects to the residue after it in sequence...
Definition: Residue.hh:775
bool is_glycosidic_phi_torsion(Pose const &pose, id::TorsionID const &torsion_id)
Is this is the phi torsion angle of a glycosidic linkage?
Definition: util.cc:413
utility::pointer::shared_ptr< EnergyMethod > EnergyMethodOP
Utility function declarations for carbohydrate-containing poses.
static THREAD_LOCAL basic::Tracer TR("core.scoring.CartesianBondedEnergy")
Real phi(Size const seqpos) const
Returns the phi torsion angle of residue
Definition: Pose.cc:899
utility::vector1< ScoreType > ScoreTypes
Definition: ScoreType.hh:593
Torsion identifier class.
Definition: TorsionID.hh:50
ResidueType const & type() const
Returns this residue's ResidueType.
Definition: Residue.hh:1109
virtual ScoreTypes score_types_for_method() const
Return the set of ScoreTypes for which this EnergyMethod is responsible.
utility::pointer::shared_ptr< CarbohydrateInfo const > CarbohydrateInfoCOP
uint torsion() const
Return the torsion number of the given type within the residue OR the rigid-body identifier for a JUM...
Definition: TorsionID.hh:108
Method declarations for SugarBackboneEnergyCreator.
Real psi(Size const seqpos) const
Returns the psi torsion angle of residue Note: assumes the residue is an amino acid or monos...
Definition: Pose.cc:955
static THREAD_LOCAL basic::Tracer TR("core.scoring.methods.carbohydrates.SugarBackboneEnergy")
Method declarations for CHIEnergyFunction.
platform::Real Real
Definition: types.hh:35
utility::vector1< AtomIndices > const & chi_atoms() const
Returns the AtomIndices of each set of four atoms defining each chi angle.
Definition: Residue.hh:1492
Kinematics DOF identifier class.
Definition: DOF_ID.hh:34
core::chemical::carbohydrates::CarbohydrateInfoCOP carbohydrate_info() const
Return the CarbohydrateInfo object containing sugar-specific properties for this residue.
Definition: Residue.cc:352
virtual void residue_energy(conformation::Residue const &rsd, pose::Pose const &pose, EnergyMap &emap) const
Evaluate the one-body carbohydrate backbone energies for a particular residue, in the context of the ...
platform::uint uint
Definition: types.hh:32
EnergyMethodCreator allowing the ScoringManager to create a SugarBackboneEnergy method class...
Method declarations and simple accessor definitions for the Residue class.
bool is_glycosidic_psi_torsion(Pose const &pose, id::TorsionID const &torsion_id)
Is this is the psi torsion angle of a glycosidic linkage?
Definition: util.cc:453
Method definitions for SugarBackboneEnergy and SugarBackboneEnergyCreator.
AxEqDesignation is_atom_axial_or_equatorial_to_ring(Coords const &query_atom, Coords const &attachment_atom, utility::vector1< Coords > const &ring_atoms)
Are the query atom coordinates axial or equatorial to the given ring or neither?
Definition: util.cc:54
TorsionType type() const
Return the type (BB, CHI,NU, BRANCH, JUMP) of this torsion.
Definition: TorsionID.hh:97
utility::pointer::shared_ptr< EnergyMethodCreator > EnergyMethodCreatorOP
Scoring manager class header.
Vector of scores declaration.
A vector for storing energy data, initially all values are 0.
Definition: EnergyMap.hh:42
Residue const & residue(Size const seqpos) const
Returns the Residue at position (read access) Note: this method will trigger a refold if eit...
Definition: Pose.cc:868
AtomIndices const & ring_atoms(uint const ring_num) const
Return list of indices of the atoms within this residue's nth cycle, not counting virtual atoms...
Definition: ResidueType.hh:421
Real torsion(TorsionID const &id) const
Returns the Conformation torsion angle identified by
Definition: Pose.cc:1306
virtual EnergyMethodOP create_energy_method(EnergyMethodOptions const &) const
Return an up-casted owning pointer (EnergyMethodOP) to the energy method.
bool has_variant_type(chemical::VariantType const variant_type) const
Generic variant access.
Definition: Residue.hh:1870
Size rsd() const
For this TorsionID, return the Residue number within the complex OR the Jump number for the Pose...
Definition: TorsionID.hh:87
scoring::carbohydrates::CHIEnergyFunction const & E_
Size residue_connection_partner(Size const resconn_index) const
Returns the residue number of a residue connected to this residue at this residue's connection rescon...
Definition: Residue.hh:1234
Pose class.