Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FullatomCustomPairDistanceEnergy.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/custom_pair_distance/FullatomCustomPairDistanceEnergy.cc
11 /// @brief
12 /// @author David E Kim
13 
14 
15 // Unit headers
18 
19 
20 // Package headers
23 // AUTO-REMOVED #include <core/scoring/Energies.hh>
24 
25 // Project headers
26 // AUTO-REMOVED #include <core/pose/Pose.hh>
28 // AUTO-REMOVED #include <core/pose/datacache/CacheableDataType.hh>
29 #include <basic/database/open.hh>
32 #include <basic/Tracer.hh>
33 
34 #include <basic/options/option.hh>
35 #include <basic/options/keys/score.OptionKeys.gen.hh>
36 
37 //Auto Headers
39 #include <utility/OrderedTuple.hh>
40 #include <utility/fixedsizearray1.hh>
41 #include <utility/vector1.hh>
42 #include <basic/datacache/CacheableData.hh>
43 
44 // Numeric headers
45 //#include <numeric/deriv/distance_deriv.hh>
46 
47 // option key includes
48 
49 namespace core {
50 namespace scoring {
51 namespace custom_pair_distance {
52 
53 
54 /// @details This must return a fresh instance of the FullatomCustomPairDistanceEnergy class,
55 /// never an instance already in use
59 ) const {
61 }
62 
65  ScoreTypes sts;
66  sts.push_back( fa_cust_pair_dist );
67  return sts;
68 }
69 
70 ////////////////////////////////////////////////////////////////////////////////////////////
71 
72 
73 class RespairInteractions : public basic::datacache::CacheableData
74 {
75 public:
76  typedef utility::fixedsizearray1< Size, 2 > ResAtomIndex;
77  typedef utility::OrderedTuple< ResAtomIndex > ResAtomIndexTuple;
78  typedef std::map< ResAtomIndexTuple, std::list< resatom_and_func_struct > > ResAtomIndexFuncMap;
79 
82  virtual basic::datacache::CacheableDataOP clone() const { return new RespairInteractions( *this ); }
83 
84  void apfc_list( AtomPairFuncListCOP apfclist ) { apfc_list_ = apfclist; }
85  AtomPairFuncList const & apfc_list() const { return *apfc_list_; }
86 private:
88 };
89 
92 
93 ////////////////////////////////////////////////////////////////////////////////////////////
94 
97 
98 
99 void
101 {
102  interacting_atompair_list_.push_back( interacting_pair );
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////////////////
106 
107 
108 static basic::Tracer tr("core.scoring.custom_pair_distance.FullatomCustomPairDistanceEnergy");
109 
110 // constructor
113 {
115 }
116 
118  parent( src ),
119  pair_and_func_map_( src.pair_and_func_map_ ),
120  max_dis_( src.max_dis_ )
121 {
122 }
123 
124 /// clone
127 {
128  return new FullatomCustomPairDistanceEnergy( *this );
129 }
130 
131 
132 ///
133 void
135  conformation::Residue const & rsd1,
136  conformation::Residue const & rsd2,
137  pose::Pose const & /*pose*/,
138  ScoreFunction const &,
139  EnergyMap & emap
140 ) const
141 {
142  //ResTypePair respair;
143  //respair[1] = rsd1.type();
144  //respair[2] = rsd2.type();
145 
146  PairFuncMap::const_iterator respairiter = find( rsd1, rsd2 );
147  if ( respairiter == pair_and_func_map_.end() ) return;
148  assert( (*respairiter).second ); // there should be no null-pointing elements in the pair_and_func_map_
149  Energy score = 0.0;
150  for ( std::list<atoms_and_func_struct>::const_iterator
151  atom_func_iter = (*respairiter).second->ats_n_func_list().begin(),
152  atom_func_iter_end = (*respairiter).second->ats_n_func_list().end();
153  atom_func_iter != atom_func_iter_end; ++atom_func_iter) {
154  Vector const& atom_a_xyz( rsd1.xyz((*atom_func_iter).resA_atom_index_));
155  Vector const& atom_b_xyz( rsd2.xyz((*atom_func_iter).resB_atom_index_));
156  score += (*atom_func_iter).func_->func(atom_a_xyz.distance_squared(atom_b_xyz));
157 
158  //if ((*atom_func_iter).func_->func(atom_a_xyz.distance_squared(atom_b_xyz)) > 0)
159  //tr.Debug << rsd1.name() << " " << rsd1.seqpos() << " " << rsd1.atom_name((*atom_func_iter).resA_atom_index_) << " " <<
160  // rsd2.name() << " " << " " << rsd2.seqpos() << " " << rsd2.atom_name((*atom_func_iter).resB_atom_index_) <<
161  // " score: " << (*atom_func_iter).func_->func(atom_a_xyz.distance_squared(atom_b_xyz)) << " dist_sq: " << atom_a_xyz.distance_squared(atom_b_xyz) << std::endl;
162  }
163  emap[ fa_cust_pair_dist ] += score;
164 }
165 
166 /// @brief FullatomCustomPairDistanceEnergy distance cutoff
167 Distance
169 {
170  return max_dis_;
171 }
172 
173 bool
175  conformation::Residue const & res1,
176  conformation::Residue const & res2,
177  bool res_moving_wrt_eachother
178 ) const
179 {
180  return res_moving_wrt_eachother && interaction_defined( res1, res2 );
181 }
182 
183 bool
185 
186 bool
188 {
189  return true;
190 }
191 
192 void
194  conformation::Residue const & rsd1,
195  conformation::Residue const & rsd2,
196  ResPairMinimizationData const & pair_data,
197  pose::Pose const &,
198  ScoreFunction const &,
199  EnergyMap & emap
200 ) const
201 {
202  assert( rsd1.seqpos() < rsd2.seqpos() );
203  assert( dynamic_cast< RespairInteractions const * > (pair_data.get_data( fa_custom_pair_dist_data )() ));
204 
205  RespairInteractions const & respair_intxns( static_cast< RespairInteractions const & > (pair_data.get_data_ref( fa_custom_pair_dist_data ) ));
206  Energy score( 0.0 );
207  for ( std::list< atoms_and_func_struct >::const_iterator
208  atom_func_iter = respair_intxns.apfc_list().ats_n_func_list().begin(),
209  atom_func_iter_end = respair_intxns.apfc_list().ats_n_func_list().end();
210  atom_func_iter != atom_func_iter_end; ++atom_func_iter) {
211  Vector const& atom_a_xyz( rsd1.xyz((*atom_func_iter).resA_atom_index_));
212  Vector const& atom_b_xyz( rsd2.xyz((*atom_func_iter).resB_atom_index_));
213  score += (*atom_func_iter).func_->func(atom_a_xyz.distance_squared(atom_b_xyz));
214  }
215  emap[ fa_cust_pair_dist ] += score;
216 }
217 
218 void
220  conformation::Residue const & rsd1,
221  conformation::Residue const & rsd2,
222  pose::Pose const &,
223  ScoreFunction const &,
227  ResPairMinimizationData & pair_data
228 ) const
229 {
230  assert( rsd1.seqpos() < rsd2.seqpos() );
231 
232  // update the existing respair_intxns object if one is already present in the pair_data object
233  RespairInteractionsOP respair_intxns = static_cast< RespairInteractions * > ( pair_data.get_data( fa_custom_pair_dist_data )() );
234  if ( ! respair_intxns ) respair_intxns = new RespairInteractions;
235 
236  AtomPairFuncListCOP apfclist = find( rsd1, rsd2 )->second;
237  assert( apfclist );
238  respair_intxns->apfc_list( apfclist );
239  pair_data.set_data( fa_custom_pair_dist_data, respair_intxns );
240 }
241 
242 
243 void
245  conformation::Residue const & rsd1,
246  conformation::Residue const & rsd2,
249  ResPairMinimizationData const & pair_data,
250  pose::Pose const &,
251  EnergyMap const & weights,
252  utility::vector1< DerivVectorPair > & r1_atom_derivs,
253  utility::vector1< DerivVectorPair > & r2_atom_derivs
254 ) const
255 {
256  assert( rsd1.seqpos() < rsd2.seqpos() );
257  assert( rsd1.seqpos() < rsd2.seqpos() );
258  assert( dynamic_cast< RespairInteractions const * > (pair_data.get_data( fa_custom_pair_dist_data )() ));
259 
260  RespairInteractions const & respair_intxns( static_cast< RespairInteractions const & > (pair_data.get_data_ref( fa_custom_pair_dist_data ) ));
261  for ( std::list< atoms_and_func_struct >::const_iterator
262  atom_func_iter = respair_intxns.apfc_list().ats_n_func_list().begin(),
263  atom_func_iter_end = respair_intxns.apfc_list().ats_n_func_list().end();
264  atom_func_iter != atom_func_iter_end; ++atom_func_iter) {
265  Vector const & atom_a_xyz = rsd1.xyz( atom_func_iter->resA_atom_index_ );
266  Vector const & atom_b_xyz = rsd2.xyz( atom_func_iter->resB_atom_index_ );
267 
268  Real dist_sq = atom_a_xyz.distance_squared(atom_b_xyz);
269  if ( dist_sq < atom_func_iter->func_->min_dis() || dist_sq > atom_func_iter->func_->max_dis() ) continue;
270 
271  Vector f1( atom_a_xyz.cross( atom_b_xyz ));
272  Vector f2( atom_a_xyz - atom_b_xyz );
273  Real const dist( f2.length() );
274  if ( dist == 0.0 ) continue;
275 
276  Real deriv = (*atom_func_iter).func_->dfunc(dist_sq);
277  // WRONG f1 *= ( deriv / dist ) * weights[ fa_cust_pair_dist ];
278  // WRONG f2 *= ( deriv / dist ) * weights[ fa_cust_pair_dist ];
279  f1 *= deriv * 2 * weights[ fa_cust_pair_dist ];
280  f2 *= deriv * 2 * weights[ fa_cust_pair_dist ];
281 
282  /* THIS CODE WORKS!
283  Vector f1,f2; Real dis;
284  numeric::deriv::distance_f1_f2_deriv( atom_a_xyz, atom_b_xyz, dis, f1, f2 );
285  Real const dE_dd2 = (*atom_func_iter).func_->dfunc(dis*dis);
286  f1 *= dE_dd2 * 2 * dis * weights[ fa_cust_pair_dist ];
287  f2 *= dE_dd2 * 2 * dis * weights[ fa_cust_pair_dist ];*/
288 
289  // equal and opposite
290  r1_atom_derivs[ atom_func_iter->resA_atom_index_ ].f1() += f1;
291  r1_atom_derivs[ atom_func_iter->resA_atom_index_ ].f2() += f2;
292  r2_atom_derivs[ atom_func_iter->resB_atom_index_ ].f1() -= f1;
293  r2_atom_derivs[ atom_func_iter->resB_atom_index_ ].f2() -= f2;
294  }
295 
296 }
297 
298 
299 /*void
300 FullatomCustomPairDistanceEnergy::setup_for_minimizing(
301  pose::Pose & pose,
302  ScoreFunction const &,
303  kinematics::MinimizerMapBase const &
304 ) const
305 {
306  using namespace basic::datacache;
307 
308  if( !pose.data().has( pose::datacache::CacheableDataType::CUSTOM_PAIR_DIST_SCORE_INFO ) ) {
309  pose.data().set( pose::datacache::CacheableDataType::CUSTOM_PAIR_DIST_SCORE_INFO, new CacheableAtomPairFuncMap );
310  }
311  CacheableDataOP dat( pose.data().get_ptr( pose::datacache::CacheableDataType::CUSTOM_PAIR_DIST_SCORE_INFO ) );
312  CacheableAtomPairFuncMap *cachemap = (CacheableAtomPairFuncMap*)dat();
313  ResAtomIndexFuncMap & resatomfuncmap(cachemap->map());
314 
315  // Identify which residue and atom pairs to evaluate in the pose by looping
316  // through the pair_and_func_map keys (residue pairs to evaluate).
317  // Save the data in the pose data cache for evaluating derivative.
318  for (PairFuncMap::const_iterator respairiter = pair_and_func_map_.begin(),
319  respairiter_end = pair_and_func_map_.end();
320  respairiter != respairiter_end; ++respairiter) {
321  ResTypePair respair = (*respairiter).first.data();
322  for (Size i=1; i<=pose.total_residue(); ++i) {
323  if (chemical::ResidueTypeCOP( & (pose.residue_type(i))) == respair[1]) {
324  for (Size j=1; j<=pose.total_residue(); ++j) {
325  if (chemical::ResidueTypeCOP( & (pose.residue_type(j))) == respair[2]) {
326  for ( std::list<atoms_and_func_struct>::const_iterator iter_a = (*respairiter).second.begin(),
327  iter_end_a = (*respairiter).second.end(); iter_a != iter_end_a; ++iter_a) {
328  if (i == j && (*iter_a).resA_atom_index_ == (*iter_a).resB_atom_index_) continue; // skip same atom
329  // add pair
330  resatom_and_func_struct resatom_b;
331  ResAtomIndex rai_a;
332  rai_a[1] = i;
333  rai_a[2] = (*iter_a).resA_atom_index_;
334  resatom_b.res_index_ = j;
335  resatom_b.atom_index_ = (*iter_a).resB_atom_index_;
336  resatom_b.func_ = (*iter_a).func_;
337  resatomfuncmap[rai_a].push_back( resatom_b );
338  }
339  }
340  }
341  }
342  }
343  }
344 }
345 
346 
347 void
348 FullatomCustomPairDistanceEnergy::eval_atom_derivative(
349  id::AtomID const & id,
350  pose::Pose const & pose,
351  kinematics::DomainMap const &, //domain_map,
352  ScoreFunction const &, // sfxn,
353  EnergyMap const & emap,
354  Vector & F1,
355  Vector & F2
356 ) const
357 {
358  using namespace basic::datacache;
359  ResAtomIndex resatom;
360  resatom[1] = id.rsd();
361  resatom[2] = id.atomno();
362  CacheableDataCOP dat( pose.data().get_const_ptr( pose::datacache::CacheableDataType::CUSTOM_PAIR_DIST_SCORE_INFO ) );
363  CacheableAtomPairFuncMap const *cachemap = (CacheableAtomPairFuncMap const *)dat();
364  ResAtomIndexFuncMap const & resatomfuncmap(cachemap->map());
365  ResAtomIndexFuncMap::const_iterator resatomiter = resatomfuncmap.find( resatom );
366  if ( resatomiter == resatomfuncmap.end() ) return;
367 
368  for ( std::list<resatom_and_func_struct>::const_iterator iter_a = (*resatomiter).second.begin(),
369  iter_end_a = (*resatomiter).second.end(); iter_a != iter_end_a; ++iter_a) {
370  // determine distance squared
371  Vector const& atom_a_xyz( pose.residue(id.rsd()).atom(id.atomno()).xyz() );
372  Vector const& atom_b_xyz( pose.residue((*iter_a).res_index_).atom((*iter_a).atom_index_).xyz() );
373  Real dist_sq = atom_a_xyz.distance_squared(atom_b_xyz);
374  if (dist_sq < (*iter_a).func_->min_dis() || dist_sq > (*iter_a).func_->max_dis()) continue;
375  Vector const f1( atom_a_xyz.cross( atom_b_xyz ));
376  Vector const f2( atom_a_xyz - atom_b_xyz );
377  Real const dist( f2.length() );
378  assert(dist != 0);
379  Real deriv = (*iter_a).func_->dfunc(dist_sq);
380  F1 += ( deriv / dist ) * emap[ fa_cust_pair_dist ] * f1;
381  F2 += ( deriv / dist ) * emap[ fa_cust_pair_dist ] * f2;
382 
383  }
384 }*/
385 
386 FullatomCustomPairDistanceEnergy::PairFuncMap::const_iterator
388  conformation::Residue const & rsd1,
389  conformation::Residue const & rsd2
390 ) const
391 {
392  ResTypePair respair;
393  respair[1] = rsd1.type();
394  respair[2] = rsd2.type();
395  return pair_and_func_map_.find( respair );
396 }
397 
398 
399 bool
401  conformation::Residue const & rsd1,
402  conformation::Residue const & rsd2
403 ) const
404 {
405  return find( rsd1, rsd2 ) != pair_and_func_map_.end();
406 }
407 
408 void
410 {
411  using namespace basic::options;
412  using namespace basic::options::OptionKeys;
413  using namespace chemical;
414 
415  std::string pairfuncfile = (option[score::fa_custom_pair_distance_file].user()) ?
416  option[score::fa_custom_pair_distance_file]() :
417  basic::database::full_name( "scoring/score_functions/custom_pair_distance/fa_custom_pair_distance" );
418 
419  tr.Debug << "Reading fa_custom_pair_distance_file: " << pairfuncfile << std::endl;
420 
421  utility::io::izstream in( pairfuncfile );
422  if ( !in.good() )
423  utility_exit_with_message( "Unable to open fa_custom_pair_distance file: " + pairfuncfile );
424 
425  std::string line, residue_type_set, score_function_name;
426  utility::vector1< std::string > resA, resB, atomA, atomB;
427  max_dis_ = 0.0;
428 
429  while ( getline( in, line ) ) {
430  if ( line.size() < 1 || line[0] == '#' ) continue;
431  std::istringstream l( line );
432  std::string tag;
433  l >> tag;
434  if (tag == "RESIDUE_TYPE_SET") {
435  resA.clear(); resB.clear(); atomA.clear(); atomB.clear();
436  l >> residue_type_set;
437  tr.Debug << "Residue type set: " << residue_type_set << std::endl;
438  continue;
439  }
440  if (tag == "PAIR") {
441  std::string buf;
443  while( l >> buf ) {
444  pair_cols.push_back( buf );
445  }
446  if (pair_cols.size() == 4) {
447  resA.push_back( pair_cols[1] );
448  atomA.push_back( pair_cols[2] );
449  resB.push_back( pair_cols[3] );
450  atomB.push_back( pair_cols[4] );
451  tr.Debug << "Pair: " << pair_cols[1] << " " << pair_cols[2] << " " << pair_cols[3] << " " << pair_cols[4] << std::endl;
452  continue;
453  }
454  }
455  if (tag == "SCORE_FUNCTION") {
456  l >> score_function_name;
457 
458  atoms_and_func_struct pair_func;
459  pair_func.func_ = new DistanceFunc( score_function_name );
460  if (pair_func.func_->max_dis() > max_dis_)
461  max_dis_ = pair_func.func_->max_dis();
462  tr.Debug << "SCORE_FUNCTION: " << score_function_name << " (min: " <<
463  pair_func.func_->min_dis() << " max: " << pair_func.func_->max_dis() << ")" << std::endl;
464 
465  ResidueTypeSetCAP restype_set =
466  ChemicalManager::get_instance()->residue_type_set( residue_type_set );
467 
468  // get all possible residue types for each residue pair
469  for (Size i = 1; i <= resA.size(); ++i) {
470  ResidueTypeCOPs const & possible_res_types_a = restype_set->name3_map( resA[i] );
471  ResidueTypeCOPs const & possible_res_types_b = restype_set->name3_map( resB[i] );
472  for ( Size j = 1; j <= possible_res_types_a.size(); ++j ) {
473  ResidueTypeCOP const & rsd_type_a = possible_res_types_a[ j ];
474  Size atom_index_a = rsd_type_a->atom_index( atomA[i] );
475  for ( Size k = 1; k <= possible_res_types_b.size(); ++k ) {
476  ResidueTypeCOP const & rsd_type_b = possible_res_types_b[ k ];
477  Size atom_index_b = rsd_type_b->atom_index( atomB[i] );
478  ResTypePair respair;
479 
480  respair[1] = rsd_type_a;
481  respair[2] = rsd_type_b;
482  pair_func.resA_atom_index_ = atom_index_a;
483  pair_func.resB_atom_index_ = atom_index_b;
484  AtomPairFuncListOP atpairlist = pair_and_func_map_[ respair ];
485  if ( ! atpairlist ) {
486  //std::cout << "Adding new residue-pair interaction for " << respair[1]->name() << " " << respair[2]->name() << std::endl;
487  atpairlist = new AtomPairFuncList;
488  pair_and_func_map_[ respair ] = atpairlist;
489  } else {
490  //std::cout << "Updating residue-pair interaction for " << respair[1]->name() << " " << respair[2]->name() << std::endl;
491  }
492  atpairlist->add_interaction( pair_func );
493 
494  // save the mirrored pair if the types are not equal so if AB or
495  // BA gets passed to residue_pair_energy they'll be evaluated.
496  // I tried to prevent having to do this by sorting the pair but
497  // couldn't get it to work
498  if (rsd_type_a != rsd_type_b) {
499  respair[1] = rsd_type_b;
500  respair[2] = rsd_type_a;
501  pair_func.resA_atom_index_ = atom_index_b;
502  pair_func.resB_atom_index_ = atom_index_a;
503  atpairlist = pair_and_func_map_[ respair ];
504  if ( ! atpairlist ) {
505  atpairlist = new AtomPairFuncList;
506  pair_and_func_map_[ respair ] = atpairlist;
507  }
508  atpairlist->add_interaction( pair_func );
509  }
510  }
511  }
512  }
513  }
514  }
515  tr << "Added " << pair_and_func_map_.size() << " AtomPairFuncList lists" << std::endl;
516 }
517 
520 {
521  return 1; // Initial versioning
522 }
523 /// NOTE: distance functions should be input in square-distance bins.
524 
526  utility::io::izstream scores_stream;
527  basic::database::open( scores_stream, "scoring/score_functions/custom_pair_distance/" + name);
528  scores_hist_ = new numeric::interpolation::Histogram<Real,Real>( scores_stream() );
529  scores_stream.close();
530 }
531 
533 Real DistanceFunc::func( Real const dist_sq ) const {
534  Real e(0.0);
535  if ( dist_sq < scores_hist_->minimum() ||
536  dist_sq > scores_hist_->maximum() ) return e;
537  scores_hist_->interpolate(dist_sq,e);
538  return e;
539 }
540 
541 Real DistanceFunc::dfunc( Real const dist_sq ) const {
542  Real df(0.0), e(0.0);
543  if ( dist_sq < scores_hist_->minimum() ||
544  dist_sq > scores_hist_->maximum() ) return df;
545  scores_hist_->interpolate(dist_sq,e,df);
546  return df;
547 }
548 
550  return scores_hist_->maximum();
551 }
552 
554  return scores_hist_->minimum();
555 }
556 
557 }
558 }
559 }