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