Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ElecDensAllAtomCenEnergy.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 // This file is part of the Rosetta software suite and is made available under license.
5 // The Rosetta software is developed by the contributing members of the Rosetta Commons consortium.
6 // (C) 199x-2009 Rosetta Commons participating institutions and developers.
7 // For more information, see http://www.rosettacommons.org/.
8 
9 /// @file core/scoring/methods/ElecDensEnergy.cc
10 /// @brief Scoring a structure's fit to electron density
11 /// @author Frank DiMaio
12 
13 
14 // Unit headers
17 
18 // Package headers
19 #include <core/chemical/AA.hh>
22 #include <core/scoring/Energies.hh>
23 // AUTO-REMOVED #include <core/scoring/EnergyGraph.hh>
26 #include <core/kinematics/Edge.hh>
28 #include <numeric/xyz.functions.hh>
29 #include <numeric/statistics.functions.hh>
32 // AUTO-REMOVED #include <core/conformation/symmetry/util.hh>
33 
34 
35 // Project headers
36 #include <core/pose/Pose.hh>
38 
39 #include <basic/options/option.hh>
40 #include <basic/options/keys/edensity.OptionKeys.gen.hh>
41 
42 // Utility headers
43 
44 //
45 #include <basic/Tracer.hh>
46 
49 #include <utility/vector1.hh>
50 
51 using basic::T;
52 using basic::Error;
53 using basic::Warning;
54 
55 #ifdef WIN32
56  #define _USE_MATH_DEFINES
57  #include <math.h>
58 #endif
59 // C++
60 
61 namespace core {
62 namespace scoring {
63 namespace electron_density {
64 
65 
66 /// @details This must return a fresh instance of the ElecDensCenEnergy class,
67 /// never an instance already in use
71 ) const {
72  return new ElecDensAllAtomCenEnergy;
73 }
74 
77  ScoreTypes sts;
78  sts.push_back( elec_dens_whole_structure_allatom );
79  return sts;
80 }
81 
82 
83 static basic::Tracer TR("core.scoring.methods.ElecDensEnergy");
84 
85 inline core::Real SQ( core::Real N ) { return N*N; }
86 
89 
90 /// c-tor
93 {
94  // load map
96  //TR << "Map loaded? " << core::scoring::electron_density::getDensityMap().isMapLoaded() << std::endl;
97 }
98 
99 
100 /// clone
103  return new ElecDensAllAtomCenEnergy( *this );
104 }
105 
106 
107 /////////////////////////////////////////////////////////////////////////////
108 // scoring
109 /////////////////////////////////////////////////////////////////////////////
110 
111 bool
113  pose::Pose const & pose,
114  Size res1,
115  Size res2
116 ) const {
117  // is this fn. called?
118  return ( pose.residue( res1 ).aa() == core::chemical::aa_vrt || pose.residue( res2 ).aa() == core::chemical::aa_vrt );
119 }
120 
121 
122 void
124  if (!pose.is_fullatom()) return;
127  symminfo = dynamic_cast<const core::conformation::symmetry::SymmetricConformation & >( pose.conformation()).Symmetry_Info();
128  }
130 }
131 
132 
133 void
135  pose::Pose & pose,
136  ScoreFunction const &
137 ) const {
138  using namespace methods;
139 
140  // Do we have a map?
141  if (!map_loaded) {
142  utility_exit_with_message("Density scoring function called but no map loaded.");
143  }
144 
145  // make sure the root of the FoldTree is a virtual atom and is followed by a jump
146  kinematics::Edge const &root_edge ( *pose.fold_tree().begin() );
147  int virt_res_idx = root_edge.start();
148  conformation::Residue const &root_res( pose.residue( virt_res_idx ) );
149 
150  pose_is_proper = true;
151  if (root_res.aa() != core::chemical::aa_vrt || root_edge.label() < 0) {
152  //utility_exit_with_message("Fold tree is not set properly for density scoring!");
153  TR.Error << "Fold tree is not set properly for density scoring!" << std::endl;
154  pose_is_proper = false;
155  }
156 
157  // create LR energy container
158  LongRangeEnergyType const & lr_type( long_range_type() );
159  Energies & energies( pose.energies() );
160  bool create_new_lre_container( false );
161 
162  if ( energies.long_range_container( lr_type ) == 0 ) {
163  create_new_lre_container = true;
164  } else {
165  LREnergyContainerOP lrc = energies.nonconst_long_range_container( lr_type );
166  OneToAllEnergyContainerOP dec( static_cast< OneToAllEnergyContainer * > ( lrc.get() ) );
167  // make sure size or root did not change
168  if ( dec->size() != pose.total_residue() || dec->fixed() != virt_res_idx ) {
169  create_new_lre_container = true;
170  }
171  }
172 
173  if ( create_new_lre_container ) {
174  TR << "Creating new LRE container (" << pose.total_residue() << ")" << std::endl;
176  energies.set_long_range_container( lr_type, new_dec );
177  }
178 
179  // allocate space for per-AA stats
180  int nres = pose.total_residue();
182 
183  // grab symminfo (if defined) from the pose
184  // make a copy
187  symminfo = dynamic_cast<const core::conformation::symmetry::SymmetricConformation & >( pose.conformation()).Symmetry_Info().get();
188  }
189 
190  // do the actual matching here; split scores among individual residues
191  //utility::vector1< conformation::ResidueCAP > reses = pose.conformation().const_residues();
193 
194  // # of NON-VRT residues
195  nreses = 0;
196  for (int i=1; i<=(int)pose.total_residue(); ++i)
197  if (pose.residue(i).aa() != core::chemical::aa_vrt)
198  nreses++;
199 
200  TR.Debug << "ElecDensAllAtomCenEnergy::setup_for_scoring() returns CC = " << structure_score << std::endl;
201 }
202 
203 
204 void
206  conformation::Residue const &,
207  pose::Pose const &,
208  ScoreFunction const &,
209  EnergyMap &
210 ) const {
211  // TO DO: if the pose is improperly set (e.g. no VIRT atom + jump at root) do scoring here
212  return;
213 }
214 
215 
216 void
218  pose::Pose const & ,
219  ScoreFunction const &,
220  EnergyMap &
221 ) const {
222  return;
223 }
224 
225 
226 void
228  conformation::Residue const & rsd1,
229  conformation::Residue const & rsd2,
230  pose::Pose const & , //pose,
231  ScoreFunction const &,
232  EnergyMap & emap
233 ) const {
234  using namespace numeric::statistics;
235 
236  if (!pose_is_proper) return;
237 
238  if (rsd1.aa() != core::chemical::aa_vrt && rsd2.aa() != core::chemical::aa_vrt) return;
239  if (rsd1.aa() == core::chemical::aa_vrt && rsd2.aa() == core::chemical::aa_vrt) return;
240 
241  //Size resid = rsd.seqpos();
243  Real z_CC = cc / 0.1;
244  Real p_null = 0.5 * errfc( z_CC/sqrt(2.0) );
245  Real edensScore = log ( p_null );
246 
247  emap[ elec_dens_whole_structure_allatom ] += edensScore;
248 
249  return;
250 }
251 
252 
253 void
255  id::AtomID const & id,
256  pose::Pose const & pose,
257  kinematics::DomainMap const &, // domain_map,
258  ScoreFunction const & /*sfxn*/,
259  EnergyMap const & weights,
260  Vector & F1,
261  Vector & F2
262 ) const {
263  using namespace numeric::statistics;
264 
265  int resid = id.rsd();
266  int atmid = id.atomno();
267 
268  // derivatives only defined for (non-VRT) heavyatoms
269  if (!pose_is_proper) return;
270  if (!pose.is_fullatom()) return;
271 
272  // if (hydrogen) return
273  if ( pose.residue(resid).aa() != core::chemical::aa_vrt && !pose.residue(resid).atom_type(atmid).is_heavyatom() ) return;
274 
278 
279  // if we're symmetric, but _not_ scoring the symmetric complex,
280  // we need to scale derivatives by the score
282  //////////////////////
283  // SYMMETRIC CASE
284  //////////////////////
286  (dynamic_cast<const core::conformation::symmetry::SymmetricConformation &>(pose.conformation()).Symmetry_Info());
287  core::Size nsubunits = symminfo->subunits();
288  core::Size nres_per = symminfo->num_independent_residues();
289  bool remapSymm = basic::options::option[ basic::options::OptionKeys::edensity::score_symm_complex ]();
290 
291  if ( pose.residue(resid).aa() == core::chemical::aa_vrt && remapSymm) {
292 
293  // derivative is only defined for the 'ORIG' atom in the virtual
294  if (atmid != 2) return;
295 
296  // if not a branch node, we're done
298  int nchildren = edges_i.size();
299  if (nchildren < 2) return;
300 
301  // odd case ... if this vrt is controlled by a cloned jump then we dont have to compute derivs
302  // for now we'll just check the parent, but perhaps we should trace root->here?
303  if ( !pose.fold_tree().is_root( resid ) ) {
304  core::kinematics::Edge edge_incoming = pose.fold_tree().get_residue_edge(resid);
305  if (! symminfo->jump_is_independent( edge_incoming.label() ) )
306  return;
307  }
308 
309  // if any child jumps are cloned such that the clone jump start is ALSO a branching vrt
310  // then we need to aggregate these as well
311  // TO DO: if a jump is _fixed_ we should move downstream to the next movable jump
312  // This isn't a problem with symm files generated by the perl script, however,
313  // it may be a problem in hand-coded ones
315  for (int j=1; j<=nchildren; ++j) {
316  int basejump = edges_i[j].label();
317  if (! symminfo->jump_is_independent( basejump ) )
318  basejump = symminfo->jump_follows( basejump );
319  utility::vector1< core::Size > jumpclones = symminfo->jump_clones( basejump );
320  for (int k=0; k<=(int)jumpclones.size(); ++k) {
321  core::Size upstream = pose.fold_tree().jump_edge( k==0 ? basejump : jumpclones[k] ).start();
322  edges_j = pose.fold_tree().get_outgoing_edges(upstream);
323  if (edges_j.size() > 1 && std::find( vrtclones.begin(), vrtclones.end(), upstream ) == vrtclones.end() ) {
324  vrtclones.push_back( upstream );
325  }
326  }
327  }
328 
329  // loop over all clones of this VRT
330  for (int i=1; i<=(int)vrtclones.size(); ++i) {
331  edges_i = pose.fold_tree().get_outgoing_edges(vrtclones[i]);
332 
333  // STEP 1: subtract children's contribution
334  for (int j=1; j<=nchildren; ++j) {
335  int downstream = edges_i[j].stop();
336  utility::vector1<int> mapping_j;
338  core::scoring::electron_density::getDensityMap().get_symmMap( downstream , mapping_j, R_j );
339 
340  for (int k=1; k<=(int)nsubunits; ++k) {
341  if (mapping_j[k] == 0) continue; // subunit k is not under child j
342 
343  // loop over all atms in reses in subunit k
344  for (int l=1, l_end=nres_per; l<=l_end; ++l) {
345  // there is a mapping from k->mapping_j[k]
346  int source_res = (k-1)*nres_per+l;
347  int target_res = (mapping_j[k]-1)*nres_per+l;
348 
349  for (int m=1, m_end=pose.residue(target_res).nheavyatoms(); m<=m_end; ++m) {
350  numeric::xyzVector<core::Real> X_lm_src = pose.residue(source_res).atom(m).xyz();
351  numeric::xyzVector<core::Real> X_lm_tgt = pose.residue(target_res).atom(m).xyz();
352 
353  core::scoring::electron_density::getDensityMap().dCCdx_aacen( m, source_res, X_lm_src, pose, dCCdx );
354  Real CC = structure_score;
355  Real z_CC = CC / 0.1;
356  Real p_null = 0.5 * errfc( z_CC/sqrt(2.0) );
357  numeric::xyzVector< core::Real > dEdx = 0.5 * ( 1.0 / p_null ) *
358  (-2.0/sqrt(M_PI)) *
359  exp(-SQ( z_CC/sqrt(2.0) )) *
360  1/sqrt(0.02) *
361  nreses * R_j * dCCdx / ((core::Real)nsubunits);
362 
363  numeric::xyzVector<core::Real> atom_x = X_lm_tgt;
364  numeric::xyzVector<core::Real> const f2( dEdx );
365  numeric::xyzVector<core::Real> atom_y = -f2 + atom_x;
366  Vector const f1( atom_x.cross( atom_y ) );
367 
368  //if (m==2)
369  // std::cerr << "at res " << resid << " SUB contribution of "
370  // << target_res << "." << m << " (source=" << source_res << "." << m << ") "
371  // << " f1=" << f1 << " f2=" << f2 << std::endl;
372  F1 -= weights[ elec_dens_whole_structure_allatom ] * f1;
373  F2 -= weights[ elec_dens_whole_structure_allatom ] * f2;
374  }
375  }
376  }
377  }
378 
379  // STEP 2: add my contribution
380  utility::vector1<int> mapping_i;
382  core::scoring::electron_density::getDensityMap().get_symmMap( vrtclones[i] , mapping_i, R_i );
383  for (int k=1; k<=(int)nsubunits; ++k) {
384  if (mapping_i[k] == 0) continue; // subunit k is not under child j
385 
386  // loop over all atms in reses in subunit k
387  for (int l=1, l_end=nres_per; l<=l_end; ++l) {
388  // there is a mapping from k->mapping_i[k]
389  int source_res = (k-1)*nres_per+l;
390  int target_res = (mapping_i[k]-1)*nres_per+l;
391 
392  for (int m=1, m_end=pose.residue(target_res).nheavyatoms(); m<=m_end; ++m) {
393  numeric::xyzVector<core::Real> X_lm_src = pose.residue(source_res).atom(m).xyz();
394  numeric::xyzVector<core::Real> X_lm_tgt = pose.residue(target_res).atom(m).xyz();
395 
396  core::scoring::electron_density::getDensityMap().dCCdx_aacen( m, source_res, X_lm_src, pose, dCCdx );
397  Real CC = structure_score;
398  Real z_CC = CC / 0.1;
399  Real p_null = 0.5 * errfc( z_CC/sqrt(2.0) );
400  numeric::xyzVector< core::Real > dEdx = 0.5 * ( 1.0 / p_null ) *
401  (-2.0/sqrt(M_PI)) *
402  exp(-SQ( z_CC/sqrt(2.0) )) *
403  1/sqrt(0.02) *
404  nreses * R_i * dCCdx / ((core::Real)nsubunits);
405 
406  numeric::xyzVector<core::Real> atom_x = X_lm_tgt;
407  numeric::xyzVector<core::Real> const f2( dEdx );
408  numeric::xyzVector<core::Real> atom_y = -f2 + atom_x;
409  Vector const f1( atom_x.cross( atom_y ) );
410 
411  //if (m==2)
412  // std::cerr << "at res " << resid << " ADD contribution of "
413  // << target_res << "." << m << " (source=" << source_res << "." << m << ") "
414  // << " f1=" << f1 << " f2=" << f2 << std::endl;
415  F1 += weights[ elec_dens_whole_structure_allatom ] * f1;
416  F2 += weights[ elec_dens_whole_structure_allatom ] * f2;
417  }
418  }
419  }
420  }
421  } else { // NON-VRT
422  if (! symminfo->bb_is_independent( resid ) ) return;
423 
424  utility::vector1< Size > myClones = symminfo->bb_clones(resid);
425  for (int i=0; i<=(int)myClones.size(); ++i) {
426  numeric::xyzVector<core::Real> X_i = (i==0) ? X : pose.xyz( id::AtomID( atmid, myClones[i] ) );
427  core::scoring::electron_density::getDensityMap().dCCdx_aacen( atmid, (i==0) ? resid : myClones[i], X_i, pose, dCCdx );
428 
429  // get R
430  if (remapSymm)
431  core::scoring::electron_density::getDensityMap().get_R( symminfo->subunit_index( (i==0) ? resid : myClones[i] ), R );
432 
433  Real CC = structure_score;
434  Real z_CC = CC / 0.1;
435  Real p_null = 0.5 * errfc( z_CC/sqrt(2.0) );
436 
437  // divide by the number of subunits since rosetta will scale up later (??)
438  numeric::xyzVector< core::Real > dEdx = 0.5 * ( 1.0 / p_null ) *
439  (-2.0/sqrt(M_PI)) *
440  exp(-SQ( z_CC/sqrt(2.0) )) *
441  1/sqrt(0.02) *
442  nreses * R * dCCdx / ((core::Real)nsubunits);
443 
444  numeric::xyzVector<core::Real> atom_x = X; //X_i;
445  numeric::xyzVector<core::Real> const f2( dEdx );
446  numeric::xyzVector<core::Real> atom_y = -f2 + atom_x;
447  Vector const f1( atom_x.cross( atom_y ) );
448 
449  //if ( atmid==2)
450  // std::cerr << "at res " << resid
451  // << " f1=" << f1 << " f2=" << f2 << std::endl;
452  F1 += weights[ elec_dens_whole_structure_allatom ] * f1;
453  F2 += weights[ elec_dens_whole_structure_allatom ] * f2;
454  }
455  }
456  } else {
457  //////////////////////
458  // ASYMMETRIC CASE
459  //////////////////////
460 
461  // the derivative of edens _score_ as a function of dCC/dx
462  Real CC = structure_score;
463  Real z_CC = CC / 0.1;
464  Real p_null = 0.5 * errfc( z_CC/sqrt(2.0) );
465 
466  core::scoring::electron_density::getDensityMap().dCCdx_aacen( atmid, resid, X, pose, dCCdx );
467 
468  // divide by the number of subunits since rosetta will scale up later (??)
469  numeric::xyzVector< core::Real > dEdx = ( 1.0 / p_null ) *
470  0.5 *
471  (-2.0/sqrt(M_PI)) *
472  exp(-SQ( z_CC/sqrt(2.0) )) *
473  1/sqrt(0.02) *
474  nreses *
475  dCCdx;
476 
478  numeric::xyzVector<core::Real> const f2( dEdx );
479  numeric::xyzVector<core::Real> atom_y = -f2 + atom_x; // a "fake" atom in the direcion of the gradient
480  Vector const f1( atom_x.cross( atom_y ) );
481 
482  F1 += weights[ elec_dens_whole_structure_allatom ] * f1;
483  F2 += weights[ elec_dens_whole_structure_allatom ] * f2;
484  }
485 
486  //static int counter=1;
487  //TR << "[" << counter++ << "] ElecDensEnergy::eval_atom_deriv(" << id << ")"
488  // << dEdx << " * " << f1[0] << "," << f1[1] << "," << f1[2] << " ||| "
489  // << dEdx << " * " << f2[0] << "," << f2[1] << "," << f2[2] << std::endl;
490 }
493 {
494  return 1; // Initial versioning
495 }
496 
497 }
498 }
499 }