Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HotspotStubSet.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 protocols/pose/hotspot_hashing/HotspotStubSet.cc
11 /// @brief HotspotStubSet class
12 /// @author Jacob Corn (jecorn@u.washington.edu), John Karanicolas, Sarel Fleishman
13 
14 // Unit headers
17 #include <core/pose/Pose.hh>
18 #include <core/pose/PDBInfo.hh>
19 
23 
26 
28 
29 #include <core/id/AtomID_Map.hh>
30 #include <core/io/pdb/pose_io.hh>
31 #include <core/chemical/AA.hh>
32 
38 
39 #include <core/scoring/Energies.hh>
44 #include <core/scoring/sasa.hh>
46 
51 
52 
54 
55 
57 #include <protocols/moves/Mover.hh>
58 
64 // AUTO-REMOVED #include <core/scoring/constraints/XYZ_Func.hh>
65 #include <core/scoring/rms_util.hh>
68 
69 
70 #include <numeric/xyzVector.hh>
71 #include <numeric/conversions.hh>
72 
73 // Utility headers
74 #include <basic/Tracer.hh>
75 #include <utility/exit.hh>
76 #include <utility/io/ozstream.hh>
77 #include <core/types.hh>
78 
79 #include <core/pose/Remarks.hh>
81 #include <numeric/random/random.hh>
82 #include <utility/vector1.hh>
83 
84 #include <ObjexxFCL/string.functions.hh>
85 
86 // C++ Headers
87 #include <sstream>
88 #include <map>
89 #include <set>
90 #include <cassert>
91 #include <algorithm>
92 #include <cmath>
93 
94 // option key includes
95 
96 #include <basic/options/keys/run.OptionKeys.gen.hh>
97 #include <basic/options/keys/hotspot.OptionKeys.gen.hh>
98 #include <basic/options/keys/packing.OptionKeys.gen.hh>
99 // AUTO-REMOVED #include <basic/options/keys/score.OptionKeys.gen.hh>
100 #include <boost/foreach.hpp>
101 
102 //Auto Headers
104 #include <core/pose/util.hh>
106 #include <utility/vector0.hh>
107 #include <basic/options/option.hh>
108 
109 #include <numeric/random/random.hh>
110 #include <numeric/random/random_permutation.hh>
111 
112 
113 #define foreach BOOST_FOREACH
114 
115 
116 using basic::T;
117 using basic::Error;
118 using basic::Warning;
119 
120 using ObjexxFCL::lead_zero_string_of;
121 
122 static numeric::random::RandomGenerator RG( 101079 );
123 
124 namespace protocols {
125 namespace hotspot_hashing {
127 basic::Tracer TR( "protocols.hotspot_hashing");
128 
130  ReferenceCount(),
131  sc_only_(true),
132  target_resnum_(0),
133  target_distance_(15.0),
134  score_threshold_(-1.0),
135  filter_( new protocols::filters::TrueFilter ),
136  hotspot_length_( 1 )
137 { set_chain_to_design(); }
138 
140  ReferenceCount( init ),
141  stub_set_( init.stub_set_ ),
142  stub_set_vec_( init.stub_set_vec_ ),
143  sc_only_( init.sc_only_ ),
144  target_resnum_( init.target_resnum_ ),
145  target_distance_( init.target_distance_ ),
146  chain_to_design_( init.chain_to_design_ ),
147  score_threshold_( init.score_threshold_ ),
148  filter_( init.filter_ ),
149  hotspot_length_( init.hotspot_length_ )
150 {}
151 
153 
155  stub_set_.clear();
157 }
158 
161  runtime_assert( length > 0 );
162  hotspot_length_ = length;
163 }
165 bool HotspotStubSet::sc_only() const { return sc_only_; }
166 void HotspotStubSet::sc_only( bool const sc_switch ) { sc_only_ = sc_switch; }
167 
169  foreach( Hs_data const hs_data, stubset ) add_stub_( hs_data.second.second );
170 }
171 
172 void HotspotStubSet::score_threshold( core::Real const threshold ) { score_threshold_ = threshold; }
173 
174 /// @brief returns a new stub_set with stub scores recalculated by colony energy (Xiang, Soto, and Honig PNAS 2002)
175 /// @detailed E = -ln (sum exp( -E(j) - rmsd(ij)^3/6L ) )
177  HotspotStubSetOP new_set(new HotspotStubSet);
178  core::pose::PoseOP nonconstpose; // for making our new stubs.
179  if( pose_ ) nonconstpose = new core::pose::Pose( *pose_ );
180 
182  amino_acids.push_back( "ALA" );
183  amino_acids.push_back( "ARG" );
184  amino_acids.push_back( "ASN" );
185  amino_acids.push_back( "ASP" );
186  amino_acids.push_back( "GLU" );
187  amino_acids.push_back( "GLN" );
188  amino_acids.push_back( "HIS" );
189  amino_acids.push_back( "ILE" );
190  amino_acids.push_back( "LEU" );
191  amino_acids.push_back( "LYS" );
192  amino_acids.push_back( "MET" );
193  amino_acids.push_back( "PHE" );
194  amino_acids.push_back( "SER" );
195  amino_acids.push_back( "THR" );
196  amino_acids.push_back( "TRP" );
197  amino_acids.push_back( "TYR" );
198  amino_acids.push_back( "VAL" );
199 
200  TR << "Calculating colony energy..." << std::endl;
201  core::Size const nres(1); // number of residues in our "loop" (single residue stub) this is nonsense in our case, but equates to a constant so shouldn't matter
202  for( utility::vector1< std::string >::const_iterator it = amino_acids.begin(); it != amino_acids.end(); ++it ) {
203  std::string const resname = *it;
204  // Loop over all stubs with this restype
205  Hotspots res_stub_set( retrieve( resname ) );
207  for (std::multimap<core::Real, HotspotStubOP >::const_iterator i = res_stub_set.begin(); i != res_stub_set.end(); ++i) {
208  stub_vec.push_back( i->second );
209  }
210  if( stub_vec.size() == 0 ) continue; // in case we don't have any stubs of that type
211 
212  for (std::multimap<core::Real, HotspotStubOP >::const_iterator i = res_stub_set.begin(); i != res_stub_set.end(); ++i) {
213  core::Real stubi_E(0);
214  HotspotStubCOP stubi = i->second;
215  for (std::multimap<core::Real, HotspotStubOP >::const_iterator j = i; j != res_stub_set.end(); ++j) {
216  HotspotStubCOP stubj = j->second;
217  core::Real const rms = residue_sc_rmsd_no_super( stubi->residue(), stubj->residue() );
218  stubi_E += exp( 0-stubi->bonus_value() - pow(rms,3)/6*nres );
219  }
220 
221  stubi_E = 0-log( stubi_E );
222  HotspotStubCOP new_stub = new HotspotStub( stubi->residue(), stubi_E, nonconstpose, chain_to_design_, filter_ );
223  new_set->add_stub_( new_stub );
224  }
225  }
226  return new_set;
227 }
228 
229 /// @brief clusters all residues within this stubset on a per-restype basis and returns a new clustered stubset
231 
232  bool const fxnal_group = basic::options::option[ basic::options::OptionKeys::hotspot::fxnal_group ]();
233 
234  HotspotStubSetOP new_set(new HotspotStubSet);
236  amino_acids.push_back( "ALA" );
237  amino_acids.push_back( "ARG" );
238  amino_acids.push_back( "ASN" );
239  amino_acids.push_back( "ASP" );
240  amino_acids.push_back( "GLU" );
241  amino_acids.push_back( "GLN" );
242  amino_acids.push_back( "HIS" );
243  amino_acids.push_back( "ILE" );
244  amino_acids.push_back( "LEU" );
245  amino_acids.push_back( "LYS" );
246  amino_acids.push_back( "MET" );
247  amino_acids.push_back( "PHE" );
248  amino_acids.push_back( "SER" );
249  amino_acids.push_back( "THR" );
250  amino_acids.push_back( "TRP" );
251  amino_acids.push_back( "TYR" );
252  amino_acids.push_back( "VAL" );
253 
254  for( utility::vector1< std::string >::const_iterator it = amino_acids.begin(); it != amino_acids.end(); ++it ) {
255  std::string const resname = *it;
256  // Loop over all stubs with this restype
258  {
259  Hotspots res_stub_set( retrieve( resname ) );
260  for (std::multimap<core::Real, HotspotStubOP >::const_iterator i = res_stub_set.begin(); i != res_stub_set.end(); ++i) {
261  stub_vec.push_back( i->second );
262  }
263  }
264  if( stub_vec.size() == 0 ) continue; // in case we don't have any stubs of that type
265 
266  utility::vector1< core::Real > flat_rms; // used to determine minimum rmsd for APCluster self-similarity
267  flat_rms.reserve( (core::Size)pow(stub_vec.size(), 2.0f) );
268 
269  protocols::cluster::APCluster apcluster( stub_vec.size() );
270 
271  core::Size stubidx_i( 1 );
272  // using i,k per APCluster notation
273  for (utility::vector1< HotspotStubCOP >::const_iterator i = stub_vec.begin(); i != stub_vec.end(); ++i) {
274  HotspotStubCOP stub1 = *i;
275  core::Size stubidx_k( stubidx_i );
276  for (utility::vector1< HotspotStubCOP >::const_iterator k = i; k != stub_vec.end(); ++k) {
277  HotspotStubCOP stub2 = *k;
278  core::Real const rms = residue_sc_rmsd_no_super( stub1->residue(), stub2->residue(), fxnal_group ); // do clustering only based on functional group
279  TR.Debug << "rmsd " << stubidx_i << " " << stubidx_k << " " << rms << std::endl;
280 
281  flat_rms.push_back( rms );
282 
283  apcluster.set_sim( stubidx_i, stubidx_k, 0-rms ); // use negative rmsd for clustering (larger values are closer)
284  apcluster.set_sim( stubidx_k, stubidx_i, 0-rms ); // go both ways for symmetry
285  ++stubidx_k;
286  }
287  ++stubidx_i;
288  }
289 
290  // find median rmsd
291  sort( flat_rms.begin(), flat_rms.end() );
292  core::Real const median_rmsd = *(flat_rms.begin() + flat_rms.size() / 2);
293  //core::Real const min_rmsd = *(std::min_element( flat_rms.begin(), flat_rms.end() ) );
294  for( core::Size i = 1; i <= stub_vec.size(); ++i ) {
295  apcluster.set_sim( i, i, 0 - median_rmsd ); // use median_rmsd for self-similarity (see APCluster.hh). Better to use stub score to weight for better stubs?
296  TR.Debug << "Self-sim " << i << " " << 0-median_rmsd << std::endl;
297  }
298 /*
299  for( core::Size i = 1; i <= all_rms.size(); ++i ) {
300  if( all_rms[i][1]==all_rms[i][2] ) { // if self-comparison (see APCluster.hh for special meaning)
301  //TR << all_rms[i][1] << " " << all_rms[i][2] << " " << 0 - median_rmsd << std::endl; // debug output
302 
303  }
304  else {
305  //TR << all_rms[i][1] << " " << all_rms[i][2] << " " << 0 - all_rms[i][3] << std::endl; // debug output
306  apcluster.set_sim( (core::Size)all_rms[i][1], (core::Size) all_rms[i][2], 0 - all_rms[i][3] ); // use negative rmsd for clustering (larger values are closer)
307  apcluster.set_sim( (core::Size)all_rms[i][2], (core::Size)all_rms[i][1], 0 - all_rms[i][3] ); // go both ways for symmetry
308  }
309  }
310 */
311  // these settings are relatively low. clustering may not converge completely, but should be OK
312  core::Size maxits( 1000 );
313  core::Size convits( 10 );
314  core::Real lambda( 0.75 );
315  TR << "Clustering " << resname << " stubs..." << std::endl;
316  bool cluster_success = apcluster.cluster( maxits, convits, lambda );
317  if( !cluster_success ) TR << "Hotspot APClustering did not fully converge... This happens all the time, but just FYI." << std::endl;
318 
319  //the following was used to test convergence of clustering. in the end, just using the max values as defaults worked best
320 /*
321  while( !cluster_success ) {
322  TR << "Hotspot APClustering did not fully converge... This happens all the time, but just FYI." << std::endl;
323  maxits += 500;
324  convits += 100;
325  lambda += 0.1;
326  TR << "maxits=" << maxits << " convits=" << convits << " lambda=" << lambda << std::endl;
327  cluster_success = apcluster.cluster( maxits, convits, lambda );
328  if( maxits >= 4000 || convits >= 400 || lambda >= 0.95 ) {
329  TR << "Hotspot APClustering never fully converged. Using current cluster centers." << std::endl;
330  break;
331  }
332  }
333 */
334 
335  TR << "Finding low energy cluster members..." << std::endl;
336  utility::vector1< core::Size > exemplars; // all exembplars
337  utility::vector1< core::Size > lowE_members; // lowest energy cluster member for each exemplar
338  apcluster.get_all_exemplars( exemplars );
339  // find the lowest energy cluster member for each exemplar
340  for( utility::vector1<core::Size>::const_iterator it = exemplars.begin(); it != exemplars.end(); ++it ) {
341  core::Size lowE_index(0);
342  utility::vector1< core::Size > cluster_members;
343  apcluster.get_cluster_for(*it, cluster_members);
344  core::Real best_score(0);
345  for( utility::vector1<core::Size>::const_iterator it = cluster_members.begin(); it != cluster_members.end(); ++it ) {
346  HotspotStubCOP stub = stub_vec[*it];
347  core::Real const score = stub->bonus_value();
348  if( score < best_score ) {
349  lowE_index = *it;
350  best_score = score;
351  TR.Debug << lowE_index << " " << stub->bonus_value() << " " << score << " " << best_score << std::endl;
352  }
353  }
354  assert( lowE_index != 0 );
355  lowE_members.push_back( lowE_index );
356  }
357 
358  //TR << exemplars << std::endl; // debug output
359  for( utility::vector1<core::Size>::const_iterator it = lowE_members.begin(); it != lowE_members.end(); ++it ) {
360  // TR << "Adding stub number " << *it << std::endl; // debug output
361  new_set->add_stub_( (stub_vec[*it]) );
362  }
363  }
364  return new_set;
365 }
366 
367 // @brief retrieve stubs with a given residue name3
369  std::map< std::string, std::multimap< core::Real, HotspotStubOP > >::iterator ss_iter;
370  ss_iter = stub_set_.find( resname );
371  if (ss_iter == stub_set_.end() ) {
372  Hotspots empty_set;
373  stub_set_.insert( std::make_pair( resname, empty_set ) );
374  ss_iter = stub_set_.find( resname );
375  }
376  TR.Debug << "Retrieving " << ss_iter->second.size() << " " << resname << " stubs." << std::endl;
377  return (ss_iter->second);
378 }
379 
380 // @brief retrieve a subset of stubs with a given residue name3 and score cutoff. If scorecut is negative, treat it as a score. If scorecut is positive, treat it as a fraction.
381 HotspotStubSetOP HotspotStubSet::subset( std::string const & residue_name3, core::Real const scorecut ) {
382 
383  HotspotStubSetOP new_set = new HotspotStubSet;
384  new_set->sc_only_ = sc_only_;
385 
386  Hotspots all_stubs = retrieve(residue_name3);
387  // make a dummy stub with the same residue as the first stub and a user-supplied score
388  //HotspotStub scorecut_stub( all_stubs.begin()->residue(), scorecut );
389 
390  if ( ( scorecut > 0 ) && ( scorecut <=1 ) ) {
391  // add 0.5 to get rounding up
392  Size n_return = static_cast<Size>(all_stubs.size() * scorecut + 0.5);
393  if( n_return < 1 ) n_return = 1;
394  TR << "Finding the top " << n_return << " stubs." << std::endl;
395  Size i = 1;
396  for ( Hotspots::const_iterator stub_iter = all_stubs.begin(); stub_iter != all_stubs.end() ; ++stub_iter ) {
397  if( i <= n_return ) {
398  //core::pose::add_variant_type_to_pose_residue( pose, "VIRTUAL_BB", pose.total_residue() );
399  new_set->add_stub_( stub_iter->second );
400  ++i;
401  }
402  else break;
403  }
404  }
405 
406  else if ( scorecut <=0 ) {
407  for ( Hotspots::const_iterator stub_iter = all_stubs.begin(); stub_iter != all_stubs.upper_bound( scorecut ) ; ++stub_iter ) {
408  if ( stub_iter->second->bonus_value() <= scorecut ) {
409  new_set->add_stub_( stub_iter->second );
410  }
411  }
412  }
413  TR << "Found " << new_set->size() << " stubs better than " << scorecut << std::endl;
414  return new_set;
415 }
416 
417 
418 // @brief retrieve all stubs that pass a score cutoff. If scorecut is negative, treat it as a score. If scorecut is positive, treat it as a fraction.
420 
421  HotspotStubSetOP new_set = new HotspotStubSet;
422  new_set->sc_only_ = sc_only_;
423  // make a dummy stub with the same residue as the first stub and a user-supplied score
424  //HotspotStub scorecut_stub( stub_set_.begin()->second.begin()->residue(), scorecut );
425 
426  for ( Hs_map::const_iterator ss_iter= stub_set_.begin(); ss_iter != stub_set_.end(); ++ss_iter ) {
427 
428  if ( ( scorecut > 0) && ( scorecut <= 1 ) ) {
429  // add 0.5 to get rounding up
430  Size n_return = static_cast<Size>(ss_iter->second.size() * scorecut + 0.5);
431  TR << "Finding the top " << n_return << " stubs." << std::endl;
432  if( n_return < 1 ) n_return = 1;
433  Size i = 1;
434  for ( Hotspots::const_iterator stub_iter = ss_iter->second.begin(); stub_iter != ss_iter->second.end(); ++stub_iter )
435  {
436  if( i <= n_return ) {
437  new_set->add_stub_( stub_iter->second );
438  ++i;
439  }
440  }
441  }
442 
443  else if ( scorecut <= 0 )
444  {
445  for ( Hotspots::const_iterator stub_iter = ss_iter->second.begin(); stub_iter != ss_iter->second.upper_bound( scorecut ) ; ++stub_iter ) {
446 // if( stub_iter->bonus_value() <= scorecut ) {
447  new_set->add_stub_( stub_iter->second );
448 // }
449  }
450  }
451  }
452  TR << "Found " << new_set->size() << " stubs better than " << scorecut << std::endl;
453  return new_set;
454 }
455 
456 
459  core::Real min_energy( 100000.0 );
460  HotspotStubOP ret( NULL );
461  for( Hs_map::const_iterator hs_map_it=stub_set_.begin(); hs_map_it!=stub_set_.end(); ++hs_map_it ) {
462  //typedef std::multimap< core::Real, HotspotStubOP > Hs_multimap;
463  for( Hotspots::const_iterator hs_it=hs_map_it->second.begin(); hs_it!=hs_map_it->second.end(); ++hs_it ){
464  if( min_energy > hs_it->first ) {
465  min_energy = hs_it->first;
466  ret = new HotspotStub( *hs_it->second );
467  }
468  }
469  }
470  runtime_assert( ret );
471  return( ret );
472 }
473 
474 /// @detailed find stub nearest to residue based on CA-CA distance
477  using namespace core::conformation;
478 
479  HotspotStubCOP nearest_stub( NULL );
480  core::Real nearest_distance( 100000.0 );
481  numeric::xyzVector< core::Real > const residue_CA( residue->xyz( "CA" ) );
482  for( Hs_map::const_iterator map_it=stub_set_.begin(); map_it!=stub_set_.end(); ++map_it ){
483  //typedef std::multimap< core::Real, HotspotStubOP > Hs_multimap;
484  for( Hotspots::const_iterator stub_it=map_it->second.begin(); stub_it!=map_it->second.end(); ++stub_it ){
485  numeric::xyzVector< core::Real > const stub_CA( stub_it->second->residue()->xyz( "CA" ) );
486 
487  core::Real const distance( stub_CA.distance( residue_CA ) );
488  if( distance <= nearest_distance ) {
489  nearest_distance = distance;
490  nearest_stub = stub_it->second;
491  }
492  }
493  }
494  runtime_assert( nearest_stub );
495  return( nearest_stub );
496 }
497 
498 std::set< std::pair< std::string, core::Real > >
500  using namespace core::conformation;
501 
502  Residue const stub_rsd( *stub->residue() );
503 
504  std::set< std::pair< std::string, core::Real > > stub_subset;
505 
506  core::Real const dist_threshold( 3.0 );
507 
508  for( Hs_map::const_iterator hs_map_it=stub_set_.begin(); hs_map_it!=stub_set_.end(); ++hs_map_it ) {
509  //typedef std::multimap< core::Real, HotspotStubOP > Hs_multimap;
510  for( Hotspots::const_iterator hs_it=hs_map_it->second.begin(); hs_it!=hs_map_it->second.end(); ++hs_it ){
511  Residue const potential_neighbor( *(hs_it->second->residue()) );
512  for( Atoms::const_iterator stub_atom_it=stub_rsd.atom_begin(); stub_atom_it!=stub_rsd.atom_end(); ++stub_atom_it ) {
513  for( Atoms::const_iterator pot_neigh_it=potential_neighbor.atom_begin(); pot_neigh_it!=potential_neighbor.atom_end(); ++pot_neigh_it ) {
514  core::Real const dist( stub_atom_it->xyz().distance( pot_neigh_it->xyz() ) );
515  if( dist <= dist_threshold ){
516  stub_subset.insert( std::make_pair( hs_map_it->first, hs_it->first ) );
517  break;
518  }
519  }
520  }
521  }
522  }
523  return( stub_subset );
524 }
525 
526 // dangerous to return an OP. Any ideas?
528 HotspotStubSet::get_stub( std::string const residue_name3, core::Real const score ) const
529 {
530  Hs_map::const_iterator hs_it( stub_set_.find( residue_name3 ) );
531  return( hs_it->second.find( score )->second );
532 }
533 
534 ///@details removes the first occurence of stub in the stubset
535 bool
537  //typedef std::multimap< core::Real, HotspotStubOP > HsMultimap;
538  typedef std::pair< std::string, Hotspots > & HsMultimapDatum;
539  for( Hs_map::iterator datum( stub_set_.begin() ); datum!=stub_set_.end(); ++datum ){
540  Hotspots::iterator it( datum->second.begin() );
541  for( ; it!= datum->second.end(); ++it )
542  if( it->second == stub ) break;
543  if( it != datum->second.end() ){
544  datum->second.erase( it );
546  return( true );
547  }
548  }
549  TR.Warning<<"WARNING: Stub "<<stub<<" not found in remove stub"<<std::endl;
550  return( false );
551 }
552 
553 /// @details removes a set of stubs from the stub_set_
554 void
555 HotspotStubSet::remove_stubs_from_set( std::set< std::pair< std::string, core::Real > > const stubs ) {
556  for( std::set< std::pair< std::string, core::Real > >::const_iterator stub_it=stubs.begin(); stub_it!=stubs.end(); ++stub_it ){
557  Hs_map::iterator hs_it( stub_set_.find( stub_it->first ) );
558  hs_it->second.erase( get_stub( stub_it->first, stub_it->second ) );
559  }
561 }
562 
564  return constraints_;
565 }
566 
568  std::string const resname = stub->residue()->name3();
569  Hs_map::iterator ss_iter;
570  ss_iter = stub_set_.find( resname );
571  if (ss_iter == stub_set_.end() ) {
572  Hotspots empty_set;
573  stub_set_.insert( std::make_pair( resname, empty_set ) );
574  ss_iter = stub_set_.find( resname );
575  }
576  (ss_iter->second).insert( std::make_pair(stub->bonus_value(), new HotspotStub( *stub ) ) );
578 }
579 
581  // keep PDB header to preserve REMARKs
582  basic::options::option[ basic::options::OptionKeys::run::preserve_header ].value(true);
583 
584  // read all the poses in filename
586  core::import_pose::pose_from_pdb( poses, filename );
587 
588  core::pose::PoseOP nonconstpose( NULL );//SJF pose will be attached later
589  for ( utility::vector1<core::pose::Pose>::iterator it = poses.begin(); it!= poses.end(); ++it )
590  {
591  // get REMARKS associated with the pose
592  core::pose::PDBInfoCOP pdbinfo = it->pdb_info();
593  core::pose::Remarks const & remarks ( pdbinfo->remarks() );
594  core::Real score = 0;
595  for( std::vector< core::pose::RemarkInfo >::const_iterator remark_it = remarks.begin(); remark_it != remarks.end(); ++remark_it)
596  {
597  // special remark code for theoretical scores
598  if ( remark_it->num == 221 )
599  {
600  score = std::atof( remark_it->value.c_str() );
601  if( score >= -0.0001 )
602  TR<<"****WARNING WARNING**** stub score has zero or higher weight. Reading nonetheless."<<std::endl;
603  break;
604  }
605  }
606 
607  // only keep the pose/residue if we found a valid score
608  //if ( score < 0 )
609  //{
610  // make a stub from the last residue on the pose (which should only have one residue) and add it to the set
611  //using namespace core::chemical;
612  core::conformation::ResidueCOP residue = new core::conformation::Residue( it->residue( it->total_residue() ) );
613  HotspotStubCOP stub = new HotspotStub( residue, score, nonconstpose, chain_to_design_, filter_ );
614  add_stub_( stub );
615  //}
616  }
617  TR << "Read " << size() << " stubs from " << filename << std::endl;
618  return;
619 }
620 
621 void HotspotStubSet::remove_random_stubs_from_set( int const num_to_remove ){
622  if( num_to_remove <= 0 ) return;
623  if( num_to_remove >= ( int ) size() ){
624  TR<<"ERROR: Trying to remove "<< num_to_remove<<" stubs from a set containing "<<size()<<" stubs."<<std::endl;
625  utility_exit();
626  }
627 
628  std::vector< core::Size > to_remove;
629  for( core::Size i = 1; i <= size(); ++i )
630  to_remove.push_back( i );
631 
632  //std::random__shuffle( to_remove.begin(), to_remove.end() );
633  numeric::random::random_permutation(to_remove.begin(), to_remove.end(), numeric::random::RG);
634 
635  std::vector< HotspotStubOP > stubs_to_remove;
636  for( int i = 1; i <= num_to_remove; ++i )
637  stubs_to_remove.push_back( stub_set_vec_[ i ].second.second );
638 
639  foreach( HotspotStubOP hs, stubs_to_remove )
640  remove_stub( hs );
641 
642  TR<<"Removed stubs from set. Current number "<<size()<<std::endl;
643 }
644 
646 {
648  amino_acids.push_back( "ALA" );
649  amino_acids.push_back( "ARG" );
650  amino_acids.push_back( "ASN" );
651  amino_acids.push_back( "ASP" );
652  amino_acids.push_back( "GLU" );
653  amino_acids.push_back( "GLN" );
654  amino_acids.push_back( "HIS" );
655  amino_acids.push_back( "ILE" );
656  amino_acids.push_back( "LEU" );
657  amino_acids.push_back( "LYS" );
658  amino_acids.push_back( "MET" );
659  amino_acids.push_back( "PHE" );
660  amino_acids.push_back( "SER" );
661  amino_acids.push_back( "THR" );
662  amino_acids.push_back( "TRP" );
663  amino_acids.push_back( "TYR" );
664  amino_acids.push_back( "VAL" );
665  for (utility::vector1<std::string>::iterator it = amino_acids.begin(); it != amino_acids.end(); ++it ) {
666  fill( pose, scorefxn, *it, n_stubs );
667  }
668  return;
669 }
670 
671 void HotspotStubSet::autofill( core::pose::Pose const & pose, core::scoring::ScoreFunctionCOP scorefxn, core::Size const target, core::Real const distance, Size const n_stubs )
672 {
673  if( ( target <= pose.total_residue() ) && ( distance > 0 ) )
674  {
675  target_resnum_ = target;
677 
678  autofill( pose, scorefxn, n_stubs );
679  }
680  else
681  {
682  utility_exit_with_message( "Unable to find target residue, or distance less than zero!\n");
683  }
684 
685  return;
686 
687 }
688 
689 // convenience fillers
690 void HotspotStubSet::fill( core::pose::Pose const & pose, core::scoring::ScoreFunctionCOP scorefxn_in, core::Size const target, core::Real const distance, std::string const residue_name3, Size const n_stubs )
691 {
692  if( ( target <= pose.total_residue() ) && ( distance > 0 ) )
693  {
694  target_resnum_ = target;
696 
697  fill( pose, scorefxn_in, residue_name3, n_stubs );
698  }
699  else
700  {
701  utility_exit_with_message( "Unable to find target residue, or distance less than zero!\n");
702  }
703 
704  return;
705 }
706 
707 // MAIN FILLING MACHINERY HERE
708 void HotspotStubSet::fill( core::pose::Pose const & reference_pose, core::scoring::ScoreFunctionCOP scorefxn_in, std::string const residue_name3, Size const n_stubs )
709 {
710 
711  // set up scorefxn's. DISABLE environment-dependent H-bonds
713 
714  core::scoring::ScoreFunctionOP scorefxn = new core::scoring::ScoreFunction( *scorefxn_in );
715 
716 /*
717  core::scoring::ScoreFunctionOP noenvhbond_scorefxn( core::scoring::ScoreFunctionFactory::create_score_function( "score13" ) );
718  core::scoring::methods::EnergyMethodOptions options( noenvhbond_scorefxn->energy_method_options() );
719  options.hbond_options()->use_hb_env_dep( false );
720  noenvhbond_scorefxn->set_energy_method_options( options );
721  noenvhbond_scorefxn->set_weight( core::scoring::fa_dun, 0.1 );
722  noenvhbond_scorefxn->set_weight( core::scoring::envsmooth, 0 );
723  core::scoring::ScoreFunctionOP scorefxn( noenvhbond_scorefxn );
724 */
725 
726  core::pose::Pose pose = reference_pose;
727 
728  for ( Size i = 1; i <= n_stubs; ++i ) {
729  core::Real score = 0;
730  // some counting for output
731  std::stringstream index;
732  index.str("");
733  index << i;
734 
735  // Keep docking until we get a good score
736  runtime_assert( score_threshold_ );
737  while( score > score_threshold_ ) {
738 
739  pose = reference_pose;
740 
741  // make our hotspot
742  create_hotspot_after_pose( pose, residue_name3 );
743 
744  TR.Debug << "old fold tree: " << pose.fold_tree() << std::endl;
745 
746  setup_hotspot_foldtree_( pose );
747 
748  TR.Debug << "Hotspot fold tree: " << pose.fold_tree() << std::endl;
749 
750  // placed_seqpos = position of the hotspot residue of peptide
751  Size const placed_seqpos = pose.total_residue() - stub_offset(); //(hotspot_length()/2.0 == 0.0) ? pose.total_residue() - (hotspot_length()/2) + 1 : pose.total_residue() - (hotspot_length()/2);
752  Size const jump_number = pose.num_jump();
753  core::kinematics::FoldTree old_tree = pose.fold_tree(); // need the old tree to reset after docking
754  core::pose::PoseOP nonconstpose( new core::pose::Pose( pose ) ); // dummy for making stubs and as a pseudo-native for docking
755 
756  // set up docking mover
757  // includes an initial perturbation, so we don't need to keep making a new residue each time.
758  protocols::docking::DockingProtocolOP innerdock = new protocols::docking::DockingProtocol( jump_number, false /*low_res_protocol_only*/, false /*local_refine*/, false /*set_autofoldtree*/, centroid_scorefxn /*lowres*/, scorefxn /*highres*/ );
759  innerdock->set_reporting( false ); // avoid rescoring steps
760  innerdock->set_no_filters( true ); // don't use docking filters
761  /// APL -- reverting a portion of 38676 -- innerdock->set_no_filters( true ); // don't use filters
762  protocols::moves::MoverOP dock = innerdock;
763  dock->set_input_pose( nonconstpose );
764  dock->set_native_pose( nonconstpose );
765 
766  //(*scorefxn)(pose);
767  if( target_resnum_ && target_distance_ ) { // randomize residue and translate target_distance
770  protocols::docking::FaDockingSlideIntoContact slide_together( jump_number );
771  pert.apply( pose );
772  rand2.apply( pose );
773  slide_together.apply( pose );
774  }
775  else { // manually do -randomize1/2 (without commandline flags)
778  protocols::docking::FaDockingSlideIntoContact slide_together( jump_number );
779  rand1.apply( pose );
780  rand2.apply( pose );
781  rand1.apply( pose ); // double-randomize, since I've been seeing weird nonrandom behavior
782  rand2.apply( pose );
783  slide_together.apply( pose );
784  }
785 
786  // check initial distance to target
788  // convenience pointers
789  core::conformation::ResidueCOP const res_target( pose.residue( target_resnum_ ) );
790  core::conformation::ResidueCOP const stub( pose.residue( placed_seqpos ) );
791  // distance check
792  core::Real distance( res_target->xyz( res_target->nbr_atom() ).distance( stub->xyz( stub->nbr_atom() )) );
793  TR << "InitDist: " << distance << "A from res " << target_resnum_;
794  if( !( distance <= target_distance_+5 ) ) {
795  TR << ". Reject." << std::endl;
796  continue;
797  }
798  else TR << ". ";
799  }
800 
801  // reset fold tree from docking modifications. necessary for compatibility with repeated dock->apply calls.
802  dock->apply( pose );
803 
804  // check final distance to target
806  // convenience pointers
807  core::conformation::ResidueCOP const res_target( pose.residue( target_resnum_ ) );
808  core::conformation::ResidueCOP const stub( pose.residue( placed_seqpos ) );
809  // distance check
810  core::Real distance( res_target->xyz( res_target->nbr_atom() ).distance( stub->xyz( stub->nbr_atom() )) );
811  TR << "FinalDist: " << distance << "A from res " << target_resnum_;
812  if( !( distance <= target_distance_ ) ) {
813  TR << ". Reject." << std::endl;
814  continue;
815  }
816  else TR << ". ";
817  }
818 
819  // check angle towards CoM
820  if( basic::options::option[ basic::options::OptionKeys::hotspot::angle ].user() ) {
821  core::conformation::ResidueCOP const stub( pose.residue( placed_seqpos ) );
822  core::Real const threshold = basic::options::option[ basic::options::OptionKeys::hotspot::angle ].value();
823  runtime_assert( threshold > 0 );
824  // angle_res defaults to 0, which causes stub_tgt_angle() to calc and use target center of mass
825  core::Size const angle_res = basic::options::option[ basic::options::OptionKeys::hotspot::angle_res ].value();
826 
827  core::Real const angle = stub_tgt_angle( pose, stub, angle_res );
828  TR << " Stub-target angle: " << angle << "o";
829  if( angle > threshold ) {
830  TR << ". Reject." << std::endl;
831  continue;
832  }
833  else TR << ". ";
834  }
835 
836  score = get_residue_score_( pose, scorefxn, placed_seqpos );
837  TR << "Stub score: " << score;
838  // only keep stub if scores better than/eq a threshold (defaults to -1.0)
839  if ( score <= score_threshold_ ) {
840  core::conformation::ResidueCOP found_residue = new core::conformation::Residue( pose.residue( placed_seqpos ) );
841  HotspotStubCOP stub = new HotspotStub( found_residue, score, nonconstpose, chain_to_design_, filter_ );
842  add_stub_( stub );
843  TR << ". Accept." << std::endl;
844  //pose.dump_pdb( "placed_stub.pdb"); // debug pdb output
845  break; // break out of while( score > -1.0)
846  }
847  else {
848  TR << ". Reject." << std::endl;
849  }
850 
851  } // end while ( score > threshold )
852  TR.flush();
853  } // end for n_stubs
854 
855  return;
856 }
857 
860 
861  HotspotStubSetOP new_set = new HotspotStubSet;
862  new_set->sc_only( sc_only_ );
863 
864  using namespace core;
865  pose::PoseOP nonconstpose = new core::pose::Pose( pose );
866  TR << "Rescoring hotspots...\n";
867  TR << "Original Rescored\n";
868  for ( Hs_map::const_iterator it = stub_set_.begin(); it != stub_set_.end(); ++it ) {
869  for ( Hotspots::const_iterator stub_it = it->second.begin(); stub_it != it->second.end(); ++stub_it ) {
870  pose::Pose working_pose = pose;
871  conformation::ResidueCOP residue = stub_it->second->residue();
872 
873  // append the residue
874  working_pose.append_residue_by_jump( *residue, working_pose.total_residue(), "", "", true );
875  Size const placed_seqpos = working_pose.total_residue();
876 
877  // option to use make backbone invisible
878  if ( new_set->sc_only() ) {
879  core::pose::add_variant_type_to_pose_residue( working_pose, "SHOVE_BB", pose.total_residue() );
880  }
881  core::Real const score = get_residue_score_( working_pose, scorefxn, placed_seqpos );
882  TR << stub_it->first << " " << score << "\n";
883  HotspotStubCOP stub = new HotspotStub( residue, score, nonconstpose, chain_to_design_, filter_ );
884  new_set->add_stub_( stub );
885  }
886  }
887  TR.flush();
888  return new_set;
889 }
890 
892 {
893  utility::io::ozstream outstream;
894  outstream.open( filename.c_str(), std::ios::app );
895  // convenience number. would be better to read the last atom number prior to appending the new residue.
896  Size i = 0;
897  std::string tag( "" );
898  for ( Hs_map::const_iterator it = stub_set_.begin(); it != stub_set_.end(); ++it ) {
899  for ( Hotspots::const_iterator stub_it = it->second.begin(); stub_it != it->second.end(); ++stub_it ) {
900  tag = "S_" + stub_it->second->residue()->name3() + "_" + lead_zero_string_of( i, 9 );
901  write_stub( outstream, stub_it->second, tag );
902  ++i;
903  }
904  }
905  outstream.close();
906  TR << "Wrote " << i << " stubs to " << filename << std::endl;
907  return;
908 }
909 
910 void HotspotStubSet::write_stub( utility::io::ozstream & outstream, HotspotStubCOP stub, std::string const & tag ) const
911 {
912  // convenience number. would be better to read the last atom number prior to appending the new residue.
913  Size atom_number = 10000;
914 
915  outstream << "MODEL " << tag << "\n";
916  outstream << "REMARK 221 " << stub->bonus_value() << " \n";
917  core::io::pdb::dump_pdb_residue( *stub->residue(), atom_number, outstream );
918  outstream << "TER\n";
919  outstream << "ENDMDL\n";
920  return;
921 }
922 
923 /// @brief set up scaffold_status_ for each stub included in this set
925 {
926  pose_ = new core::pose::Pose( pose );
927  chain_to_design_ = partner;
928  filter_ = filter;
929  core::Size const chain_beg( pose_->conformation().chain_begin( chain_to_design_ ) );
930  core::Size const chain_end( pose_->conformation().chain_end( chain_to_design_ ) );
931  std::vector< StubStatus > temp_status( chain_end-chain_beg+1, unchecked );
932 
933  core::pose::PoseOP nonconstpose = new core::pose::Pose( *pose_ );
934  for( Hs_map::iterator set_it=stub_set_.begin(); set_it!=stub_set_.end(); ++set_it ) {
935  for( Hotspots::iterator stub_it = set_it->second.begin(); stub_it != set_it->second.end(); ++stub_it ) {
936  // makes sure contained stubs know their StubSet parent
937 // stub_it->second.set_stub_parent_( *this );
938  // readies stubs for setting of scaffold_status vector
939  stub_it->second->pair_with_scaffold( nonconstpose, filter_, chain_to_design_ );
940  }
941  }
942  TR << "Associated stubs with scaffold chain " << partner << std::endl;
943 }
944 
945 /// @brief how many total stubs are in the set (all residues)?
947 {
948  core::Size n_stubs(0);
949  for( Hs_map::const_iterator it = stub_set_.begin(); it != stub_set_.end(); ++it )
950  {
951  n_stubs += it->second.size();
952  }
953  return n_stubs;
954 }
955 
956 /// @brief how many stubs are in the set by residue?
958 {
959  core::Size n_stubs(0);
960  if( resname != "ALL" )
961  {
962  Hotspots const stubs = retrieve( resname );
963  n_stubs = stubs.size();
964  return n_stubs;
965  }
966  else
967  {
968  n_stubs = size();
969  return n_stubs;
970  }
971 }
972 
973 /// @detailed remove all stubs from stub_set_vec_ and repopulate it with stub_set_
974 void
976  stub_set_vec_.clear();
977  Hs_map::iterator stubset_it;
978  for( stubset_it=stub_set_.begin(); stubset_it!=stub_set_.end(); ++stubset_it ) {
979  std::multimap<core::Real,HotspotStubOP >::iterator hs_it;
980  hs_it = stubset_it->second.begin();
981  for( hs_it = stubset_it->second.begin(); hs_it!=stubset_it->second.end(); ++hs_it ){
982  stub_set_vec_.push_back( std::make_pair( stubset_it->first, std::make_pair( hs_it->first, hs_it->second ) ));
983  }
984  }
985 }
986 
989 {
990  core::Size const stubset_size( size() );
991  core::Size const random_element( ( core::Size )( RG.uniform() * stubset_size ) + 1 );
992 
993  runtime_assert( random_element <= stubset_size );
994  core::Size access_point( random_element );
995  Hs_map::iterator stubset_it;
996  for( stubset_it=stub_set_.begin(); stubset_it!=stub_set_.end(); ++stubset_it ) {
997  core::Size const stub_number( size( stubset_it->first ) );
998  if( stub_number < access_point )
999  access_point -= stub_number;
1000  else
1001  break;
1002  }
1003  std::multimap<core::Real,HotspotStubOP >::iterator hs_it;
1004  runtime_assert( access_point <= stubset_it->second.size() );
1005  runtime_assert( access_point > 0 );
1006  hs_it = stubset_it->second.begin();
1007  for( core::Size i=1; i < access_point; ++i, ++hs_it ) {}
1008  HotspotStubOP returnop = new HotspotStub( *hs_it->second );
1009  return( returnop );
1010 }
1011 
1014 {
1015  std::multimap<core::Real,HotspotStubOP > stubs = retrieve( resname );
1016  core::Size const subset_size( stubs.size() );
1017  core::Size const random_element( ( core::Size ) ( RG.uniform() * subset_size ) + 1 );
1018 
1019  runtime_assert( random_element <= subset_size );
1020  std::multimap<core::Real,HotspotStubOP>::iterator hs_it;
1021  hs_it = stubs.begin();
1022  for( core::Size i=1; i < random_element; ++i, ++hs_it ) {}
1023  HotspotStubOP returnop = new HotspotStub( *hs_it->second );
1024  return( returnop );
1025 }
1026 
1028 {
1030  core::chemical::ResidueTypeSet const & residue_set ( pose.residue(1).residue_type_set() );
1031 
1032  // if we're targeting a residue, make a copy of it to get a nearby location (we'll switch identity later)
1033  if( target_resnum_ && target_distance_ ) {
1034  residue = new core::conformation::Residue( pose.residue(target_resnum_) );
1035  //residue->phi( -150 );
1036  //residue->psi( 150 );
1037  utility::vector1< core::Real > sheet_phipsi;
1038  sheet_phipsi.push_back( -150.0 );
1039  sheet_phipsi.push_back( 150.0 );
1040  sheet_phipsi.push_back( 180.0 );
1041  utility::vector1< core::Real > helix_phipsi; // phi/psi taken from most probable helix, not geometrically pure one
1042  helix_phipsi.push_back( -64.0 );
1043  helix_phipsi.push_back( -41.0 );
1044  helix_phipsi.push_back( 180.0 );
1045 
1046  residue->mainchain_torsions( helix_phipsi );
1047  }
1048  // otherwise, make a new residue from scratch at 0,0,0
1049  else {
1050  core::chemical::ResidueType const & restype( residue_set.name_map( resname ) );
1052  }
1054  core::chemical::ResidueType const & alatype( residue_set.name_map( "ALA" ) );
1056 
1057  // this scorefxn doesn't really matter, since we're just using it to repack the new residue and make sure the pose is scored.
1059 
1060  for( core::Size i = 1; i <= hotspot_length(); ++i ) {
1061  // add multimer and set extended chain parameters, eg - ala-Hotspot-ala-ala
1062  // place hotspot in middle of peptide
1063  if( i == 1 ) {
1064  if( hotspot_length() == 1 ) pose.append_residue_by_jump( *residue, pose.total_residue(), "", "", true );
1065  else pose.append_residue_by_jump( *ala, pose.total_residue(), "", "", true );
1066  }
1067  else if( i == (hotspot_length()/2) + 1 ) { // middle of the peptide
1068  pose.append_residue_by_bond( *residue, true /*ideal geometry*/ );
1069  }
1070  else {
1071  pose.append_residue_by_bond( *ala, true );
1072  }
1073  }
1074  for ( core::Size i = pose.total_residue() - hotspot_length() + 1; i <= pose.total_residue(); ++i ) {
1075  TR.Debug << "i phi/psi/omega " << i << " " << pose.phi(i) << " " << pose.psi(i) << " " << pose.omega(i) << std::endl;
1076  pose.set_phi( i, -64.0 ); // phi/psi for helix
1077  pose.set_psi( i, -41.0 );
1078  pose.set_omega( i, 180 );
1079  TR.Debug << "after i phi/psi/omega " << i << " " << pose.phi(i) << " " << pose.psi(i) << " " << pose.omega(i) << std::endl;
1080  }
1081  // option to use make backbone invisible (defaults true), overridden by threemer
1082  if ( sc_only_ ) {
1083  for( core::Size i = pose.total_residue() - hotspot_length() + 1; i <= pose.total_residue(); ++i ) {
1084  core::pose::add_variant_type_to_pose_residue( pose, "SHOVE_BB", i );
1085  }
1086  }
1087 
1088  // move hotspots slightly off current location, in case we started precisely on another residue (target_res case)
1089  protocols::rigid::RigidBodyTransMover trans_mover( pose, pose.num_jump() );
1090  //trans_mover.trans_axis( trans_mover.trans_axis() );
1091  trans_mover.step_size(1e-5);
1092  trans_mover.apply( pose );
1093 
1094 
1095  //(*scorefxn)(pose);
1097  for ( Size ii=1; ii <= pose.total_residue() - hotspot_length(); ++ii ) {
1098  packer_task->nonconst_residue_task( ii ).prevent_repacking();
1099  }
1100  //make sure our appended aa has the correct identity and has realistic coordinates
1101  utility::vector1<bool> restrict_to_aa(20,false);
1102  restrict_to_aa[ core::chemical::aa_from_name(resname) ] = true;
1103 
1104  for( core::Size i = pose.total_residue()-hotspot_length()+1 ; i <= pose.total_residue(); ++i ) {
1105  packer_task->nonconst_residue_task( i ).restrict_absent_canonical_aas( restrict_to_aa );
1106  }
1107 
1108  //core::pack::pack_rotamers( pose, *scorefxn, packer_task );
1109  protocols::simple_moves::PackRotamersMover packrotamersmover( scorefxn, packer_task, 1 /*nloops*/ );
1110  packrotamersmover.apply( pose );
1111  return;
1112 }
1113 
1114 /// @brief set up foldtree for residue docking. If target_res is defined, takes that as connection point.
1115 /// Assumes hotspot to dock is last res in the pose! Assumes monomeric fold_tree!
1117  core::Size cutpoint = pose.total_residue()-hotspot_length();
1118  runtime_assert( cutpoint );
1119 
1120  core::Size jump_pos1(0);
1121  core::Size jump_pos2(0);
1122 
1123  // calculate jump points from partners
1124  TR.Debug << "cutpoint: " << cutpoint << std::endl;
1125  if( target_resnum_ && target_distance_ ) {
1126  jump_pos1 = target_resnum_;
1127  }
1128  else jump_pos1 = geometry::residue_center_of_mass( pose, 1, cutpoint );
1129  TR.Debug << "jump1: " << jump_pos1 << std::endl;
1130  // hotspot created stub_offset from the end of the pose
1131  jump_pos2 = pose.total_residue() - stub_offset();
1132  TR.Debug << "jump2: " << jump_pos2 << std::endl;
1133 
1134  runtime_assert( jump_pos1 );
1135  runtime_assert( jump_pos2 );
1136 
1138  f.slide_jump( pose.num_jump(), jump_pos1, jump_pos2 ); // make our last jump
1139 
1140  f.reorder( 1 );
1141  f.check_fold_tree();
1142  runtime_assert( f.check_fold_tree() );
1143  pose.fold_tree( f );
1144 }
1145 
1146 /// @brief utility function to find distance of a hotspot from the end of the current pose. Should be in middle or more C-terminal if hotspot_length is even
1148  if( hotspot_length() == 0 ) return 0;
1149  core::Size const offset = (hotspot_length()%2 == 0.0) ? (hotspot_length()/2) - 1 : (hotspot_length()/2);
1150  return offset;
1151 }
1152 
1153 /// @brief utility function to calculate interaction energy for a single residue
1155  protocols::simple_filters::DdgFilter const ddg( 100/*ddg_threshold*/, scorefxn, 1 /*jump__number*/, 3 /*repeats*/ );
1156  /*(*scorefxn)(pose);
1157  core::Real weighted_fa_atr = pose.energies().residue_total_energies( placed_seqpos )[core::scoring::fa_atr] * scorefxn->weights()[core::scoring::fa_atr];
1158  core::Real weighted_fa_rep = pose.energies().residue_total_energies( placed_seqpos )[core::scoring::fa_rep] * scorefxn->weights()[core::scoring::fa_rep];
1159  core::Real weighted_hbond_bb_sc = pose.energies().residue_total_energies( placed_seqpos )[core::scoring::hbond_bb_sc] * scorefxn->weights()[core::scoring::hbond_bb_sc];
1160  core::Real weighted_hbond_sc = pose.energies().residue_total_energies( placed_seqpos )[core::scoring::hbond_sc] * scorefxn->weights()[core::scoring::hbond_sc];
1161  core::Real weighted_fa_sol = pose.energies().residue_total_energies( placed_seqpos )[core::scoring::fa_sol] * scorefxn->weights()[core::scoring::fa_sol];
1162  core::Real weighted_contact_score = weighted_fa_atr + weighted_fa_rep + weighted_hbond_bb_sc + weighted_hbond_sc + weighted_fa_sol;
1163  TR.Debug << pose.energies().residue_total_energies( placed_seqpos ).weighted_string_of( scorefxn->weights() ) << std::endl;
1164  return weighted_contact_score;
1165  */
1166 
1167  core::pose::Pose copy_pose( pose );
1168 
1169  // extract hotspot res from peptide, remove peptide from pose, re-append hotspot res, then score
1170  core::Size const hotspot_start = (hotspot_length() == 1) ? pose.total_residue() : pose.total_residue() - hotspot_length() + 1;
1171  core::Size const hotspot_stop = pose.total_residue();
1172  core::conformation::ResidueOP hotspot( new core::conformation::Residue( copy_pose.residue( seqpos ) ) );
1173  copy_pose.conformation().delete_residue_range_slow( hotspot_start, hotspot_stop );
1174  copy_pose.append_residue_by_jump( *hotspot, copy_pose.total_residue(), "","", true );
1175  (*scorefxn)(copy_pose); // necessary ro get neighbors for the Interface class, which is needed by DdgFilter
1176  core::Real const score = ddg.compute( copy_pose );
1177 
1178  return score;
1179 }
1180 
1181 /// @brief utility function to add hotspot bbcst's to a pose
1182 void
1184  core::pose::Pose & pose,
1185  core::Size const partner,
1186  HotspotStubSetOP hotspot_stub_set,
1187  core::Real const & CB_force_constant,
1188  core::Real const & worst_allowed_stub_bonus,
1189  bool const apply_self_energies,
1190  core::Real const & bump_cutoff,
1191  bool const apply_ambiguous_constraints // = false
1192 ) {
1193 
1194  // Assign a fixed residue (for the stub constraints)
1195  core::Size fixed_res(1);
1196  if ( partner == 1 ) fixed_res = pose.total_residue();
1197  core::id::AtomID fixed_atom_id = core::id::AtomID( pose.residue(fixed_res).atom_index("CA"), fixed_res );
1198 
1199  core::pack::task::PackerTaskOP packer_task = prepare_hashing_packer_task_( pose, partner );
1200 
1202  pose,
1203  fixed_atom_id,
1204  packer_task,
1205  hotspot_stub_set,
1206  CB_force_constant,
1207  worst_allowed_stub_bonus,
1208  apply_self_energies,
1209  bump_cutoff,
1210  apply_ambiguous_constraints );
1211 }
1212 
1213 
1214 void
1216  core::pose::Pose & pose,
1217  core::id::AtomID const & fixed_atom,
1218  core::pack::task::PackerTaskCOP const packer_task,
1219  HotspotStubSetOP hotspot_stub_set,
1220  core::Real const & CB_force_constant,
1221  core::Real const & worst_allowed_stub_bonus,
1222  bool const apply_self_energies,
1223  core::Real const & bump_cutoff,
1224  bool const apply_ambiguous_constraints // = false
1225 ) {
1226 
1227  // Take in a scaffold pose (with PackerTask, for its DesignMap), and a set of stubs.
1228  // Each repacked residue will get one "AmbiguousConstraint".
1229  // This AmbiguousConstraint will contain a series of BackboneStubConstraints (one for each valid stub)
1230 
1231  runtime_assert( CB_force_constant > -1E-6 ); // these can't be negative
1232  runtime_assert( worst_allowed_stub_bonus < 1E-6 ); // these can't be positive
1233  runtime_assert( bump_cutoff > -1E-6 ); // these can't be negative
1234 
1235  // setup for evaluating the stub in the context of the scaffold
1236  core::pose::Pose unbound_pose = pose;
1237  generate_unbound_pose_(unbound_pose);
1238 
1239  // scorefxn for the bump check
1241  bump_scorefxn->reset();
1242  bump_scorefxn->set_weight( core::scoring::fa_rep, 1.0 );
1243 
1244  // set scorefunction.
1245  core::scoring::ScoreFunctionOP noenvhbond_scorefxn;
1246  //if( basic::options::option[ basic::options::OptionKeys::score::weights ].user() ) {
1247  // noenvhbond_scorefxn = core::scoring::getScoreFunction();
1248  //}
1249  //else {
1250  // just use sc12 with no env hbonding. Legacy reasons for this scorefxn, but it's only used for building neighbor graphs, packing ala poses, and bump checking.
1251  noenvhbond_scorefxn = core::scoring::ScoreFunctionFactory::create_score_function( "score13" );
1252  noenvhbond_scorefxn->set_weight( core::scoring::fa_dun, 0.1 );
1253  noenvhbond_scorefxn->set_weight( core::scoring::envsmooth, 0 );
1254  //}
1255  core::scoring::methods::EnergyMethodOptions options( noenvhbond_scorefxn->energy_method_options() );
1256  options.hbond_options().use_hb_env_dep( basic::options::option[ basic::options::OptionKeys::hotspot::envhb]() );
1257  noenvhbond_scorefxn->set_energy_method_options( options );
1258 
1259  core::scoring::ScoreFunctionOP full_scorefxn( noenvhbond_scorefxn );
1260 
1261  // core::scoring::ScoreFunctionOP full_scorefxn( core::scoring::ScoreFunctionFactory::create_score_function( core::scoring::STANDARD_WTS, core::scoring::SCORE12_PATCH) );
1262 
1263  // score the pose, to update the tenA_neighbor_graph and setup Hbond stuff
1264  (*full_scorefxn)(unbound_pose);
1265  core::scoring::TenANeighborGraph const unbound_neighbor_graph = unbound_pose.energies().tenA_neighbor_graph();
1266 
1267  // make an alanine pose to use for checking self energies (since we'll almost always be evaluating stubs in the absence of sidechains)
1268  core::pose::Pose ala_pose = unbound_pose;
1270  allowed_aas[ core::chemical::aa_ala ] = true;
1272  task->initialize_from_command_line().or_include_current( true );
1273  for( core::Size i=1; i<=ala_pose.total_residue(); ++i ) {
1274  if( packer_task->pack_residue(i) )
1275  task->nonconst_residue_task(i).restrict_absent_canonical_aas( allowed_aas );
1276  else
1277  task->nonconst_residue_task(i).prevent_repacking();
1278  }
1279  if( basic::options::option[basic::options::OptionKeys::packing::resfile].user() ) {
1280  core::pack::task::parse_resfile(pose, *task);
1281  }
1282  core::pack::pack_rotamers( ala_pose, *full_scorefxn, task);
1283  (*full_scorefxn)( ala_pose ); // to ensure that 10Aneighborgraph_state==GOOD
1284  core::scoring::TenANeighborGraph const ala_neighbor_graph = ala_pose.energies().tenA_neighbor_graph();
1285 
1286 
1287  // *****associate the stub set with the unbound pose
1288  // *****hotspot_stub_set->pair_with_scaffold( pose, partner );
1289 
1291  for( core::Size resnum=1; resnum <= pose.total_residue(); ++resnum ) {
1292  if (packer_task->pack_residue(resnum) ) {
1293  hotspot_stub_set->pair_with_scaffold( pose, pose.chain( resnum ), true_filter );
1294  break;
1295  }
1296  }
1297 
1298  TR << "Making hotspot constraints..." << std::endl;
1299  //Size scaffold_seqpos(0);
1300  for ( core::Size resnum=1; resnum <= pose.total_residue(); ++resnum ) {
1301 
1302  // Check that this position is allowed to be used for stub constraints
1303  if ( ! packer_task->pack_residue(resnum) ) continue;
1304 
1305  // sets the index used by the hotspot for its associated scaffold
1306  //scaffold_seqpos = resnum - pose.conformation().chain_begin( pose.chain( resnum ) ); // set but never used
1307 
1308  // Start the vector which will become a single AmbiguousConstraint, if apply_ambiguous_constraints is true
1310  // Loop over all allowed AAs at this position
1311  std::list< core::chemical::ResidueTypeCOP > allowed_aas = packer_task->residue_task( resnum ).allowed_residue_types();
1312  for (std::list< core::chemical::ResidueTypeCOP >::const_iterator restype = allowed_aas.begin();
1313  restype != allowed_aas.end(); ++restype) {
1314 
1315  // Loop over all stubs with this restype
1316  Hotspots res_stub_set( hotspot_stub_set->retrieve( (*restype )->name3() ) );
1317  for (std::multimap<core::Real,HotspotStubOP >::iterator hs_stub = res_stub_set.begin();
1318  hs_stub != res_stub_set.end(); ++hs_stub) {
1319 
1320  // prevent Gly/Pro constraints
1321  if ( (hs_stub->second->residue()->aa() == core::chemical::aa_gly) || (hs_stub->second->residue()->aa() == core::chemical::aa_pro && !basic::options::option[basic::options::OptionKeys::hotspot::allow_proline] ) ) {
1322  TR << "ERROR - Gly/Pro stubs cannot be used for constraints." << std::endl;
1323  continue;
1324  }
1325 
1326  // prevent Gly/Pro constraints
1327  if ( (pose.residue(resnum).aa() == core::chemical::aa_gly) || (pose.residue(resnum).aa() == core::chemical::aa_pro && !basic::options::option[basic::options::OptionKeys::hotspot::allow_proline]) ) {
1328  TR.Debug << "ERROR - Position " << resnum << " is currently Gly/Pro and cannot be used for stub constraints." << std::endl;
1329  continue;
1330  }
1331 
1332  core::Real stub_bonus_value = hs_stub->second->bonus_value();
1333  //TR << "stub" << hs_stub->residue()->name3() << " pose" << pose.residue(resnum).name3() << resnum << " StubEnergy=" << stub_bonus_value;
1334  // Evaluate how this stub fits on the scaffold
1335  // orient the stub onto the pose
1336  core::conformation::Residue placed_stub_res = *(hs_stub->second->residue());
1337  placed_stub_res.orient_onto_residue( unbound_pose.residue(resnum) );
1338  // set phi,psi of the placed stub res to match the pose
1339  placed_stub_res.mainchain_torsions()[1] = unbound_pose.phi(resnum);
1340  placed_stub_res.mainchain_torsions()[2] = unbound_pose.psi(resnum);
1341 
1342  core::Real bump_energy = evaluate_stub_bumps_( placed_stub_res, unbound_pose, resnum, unbound_neighbor_graph, bump_scorefxn, bump_cutoff );
1343  if ( bump_energy > bump_cutoff ) {
1344  // force cutoff to fail
1345  stub_bonus_value = worst_allowed_stub_bonus + 0.1;
1346  hs_stub->second->set_scaffold_status( resnum, protocols::hotspot_hashing::reject );
1347  //TR << " FailBumpEnergy=" << bump_energy;
1348  } else if ( apply_self_energies ) {
1349  //TR << " SuccBumpEnergy=" << bump_energy;
1350  // note: if the pose can move, these energies won't be totally accurate (but they'll still be good estimates if the movement is small)
1351  stub_bonus_value += evaluate_stub_self_energy_( placed_stub_res, unbound_pose, resnum, unbound_neighbor_graph, full_scorefxn );
1352  TR.Debug << resnum << " InitBonus " << hs_stub->second->bonus_value() << " SelfEBonus " << stub_bonus_value << std::endl;
1353  }
1354  if ( stub_bonus_value < worst_allowed_stub_bonus ) {
1355  hs_stub->second->set_scaffold_status( resnum, protocols::hotspot_hashing::accept );
1356  //TR << " SuccSelfEnergy=" << stub_bonus_value << std::endl;
1357  // ****** accept the pairing -- do we really want this? better to just reject, since bb fit doesn't necessarily mean good pair
1358  // ****** hs_stub->scaffold_status( resnum, accept );
1359 
1360  // Build a BackboneStubConstraint from this stub
1361  if ( apply_ambiguous_constraints ) {
1362  // Push it onto ambig_csts for this residue
1363  ambig_csts.push_back( new core::scoring::constraints::BackboneStubConstraint( pose, resnum, fixed_atom, *(hs_stub->second->residue()), stub_bonus_value, CB_force_constant ) );
1364  } else {
1365  // Apply it directly
1366  constraints_.push_back( new core::scoring::constraints::BackboneStubConstraint( pose, resnum, fixed_atom, *(hs_stub->second->residue()), stub_bonus_value, CB_force_constant ) );
1367  }
1368  } else hs_stub->second->set_scaffold_status( resnum, protocols::hotspot_hashing::reject );
1369  //else TR << " FailSelfEnergy=" << stub_bonus_value << std::endl;
1370  // ****** reject the pairing
1371  // ******else hs_stub->scaffold_status( resnum, reject );
1372  }
1373  }
1374 
1375  // Finally, add the constraint corresponding to this resnum to the main set
1376  if ( ( apply_ambiguous_constraints ) && ( ambig_csts.size() > 0 ) )
1378  }
1380  TR << "Applied " << constraints_.size() << " hotspot constraints to the pose." << std::endl;
1381  return;
1382 }
1383 
1384 bool
1386 {
1387  bool return_val( pose.remove_constraints( constraints_ ) );
1388  constraints_.empty();
1389  return( return_val ); // returns the state of constraints removal
1390 }
1391 
1392 void HotspotStubSet::set_chain_to_design( core::Size const chain_to_design ) {
1393  chain_to_design_ = chain_to_design;
1394 }
1395 
1396 core::Real
1398  core::conformation::Residue const & placed_stub_residue,
1399  core::pose::Pose const & unbound_pose,
1400  core::Size const resnum,
1401  core::scoring::TenANeighborGraph const & unbound_neighbor_graph,
1402  core::scoring::ScoreFunctionCOP const & bump_scorefxn,
1403  core::Real const & max_bump_energy
1404 ) {
1405 
1406  core::Real bump_energy = 0.;
1409  iter = unbound_neighbor_graph.get_node( resnum )->const_edge_list_begin(),
1410  iter_end = unbound_neighbor_graph.get_node( resnum )->const_edge_list_end();
1411  iter != iter_end; ++iter ) {
1412  Size const neighbor_resnum( (*iter)->get_other_ind( resnum ) );
1413  emap.clear();
1414  bump_scorefxn->bump_check_backbone( placed_stub_residue, unbound_pose.residue(neighbor_resnum), unbound_pose, emap );
1415  bump_energy += emap[ core::scoring::fa_rep ];
1416  if ( bump_energy > max_bump_energy ) break;
1417  }
1418 
1419  return bump_energy;
1420 }
1421 
1422 
1423 core::Real
1425  core::conformation::Residue const & placed_stub_residue,
1426  core::pose::Pose const & unbound_pose,
1427  core::Size const resnum,
1428  core::scoring::TenANeighborGraph const & unbound_neighbor_graph,
1429  core::scoring::ScoreFunctionCOP const & full_scorefxn
1430 ) {
1431 
1432  core::Real self_energy = 0.;
1433  TR.Debug << resnum << " InitStubSelfE " << self_energy << " ";
1434  core::scoring::EnergyMap weights = full_scorefxn->weights();
1435 
1436  // probability of the stub AA given the phi/psi of the (starting) pose
1438  emap.clear();
1439  full_scorefxn->eval_ci_1b( placed_stub_residue, unbound_pose, emap );
1440  self_energy += weights.dot( emap );
1441  TR.Debug << self_energy << " ";
1442 
1444  iter = unbound_neighbor_graph.get_node( resnum )->const_edge_list_begin(),
1445  iter_end = unbound_neighbor_graph.get_node( resnum )->const_edge_list_end();
1446  iter != iter_end; ++iter ) {
1447  Size const neighbor_resnum( (*iter)->get_other_ind( resnum ) );
1448 
1449  // how well the sidechain of the stub fits into the pose
1450  core::scoring::EnergyMap emap_2b;
1451  emap_2b.clear();
1452  // backbone of neighbor, sidechain of stub
1453  full_scorefxn->eval_ci_2b_bb_sc( unbound_pose.residue(neighbor_resnum), placed_stub_residue, unbound_pose, emap_2b );
1454  full_scorefxn->eval_cd_2b_bb_sc( unbound_pose.residue(neighbor_resnum), placed_stub_residue, unbound_pose, emap_2b );
1455  // sidechain of neighbor, sidechain of stub
1456  full_scorefxn->eval_ci_2b_sc_sc( unbound_pose.residue(neighbor_resnum), placed_stub_residue, unbound_pose, emap_2b );
1457  full_scorefxn->eval_cd_2b_sc_sc( unbound_pose.residue(neighbor_resnum), placed_stub_residue, unbound_pose, emap_2b );
1458  self_energy += weights.dot( emap_2b );
1459  TR.Debug << self_energy << " ";
1460  }
1461  TR.Debug << std::endl;
1462  return self_energy;
1463 }
1464 
1467  core::pose::Pose const & pose,
1468  core::Size const chain_to_redesign // default = 2
1469 ) {
1470 
1471  core::pack::task::PackerTaskOP const hotspot_hash_packer_taskOP =
1473 
1474  //in case there is a resfile, information in this resfile can set the packer task, but can be overridden below.
1475  if( basic::options::option[basic::options::OptionKeys::packing::resfile].user() )
1476  core::pack::task::parse_resfile(pose, *hotspot_hash_packer_taskOP);
1477 
1478  // Setup the unbound pose, from which to compute residue sasa
1479  // (move the chains apart first, in case we're starting from a good binding mode)
1480  core::pose::Pose unbound_pose = pose;
1481  generate_unbound_pose_(unbound_pose);
1482 
1483  // Compute residue sasa
1484  core::Real const sasa_thres(2.0);
1485  core::Real const probe_radius(1.4);
1487  utility::vector1< core::Real > residue_sasa;
1488  core::scoring::calc_per_atom_sasa( unbound_pose, atom_sasa, residue_sasa, probe_radius);
1489 
1490  // Specify which chain is the designed one
1491  utility::vector1<bool> allow_stub_constraint( pose.total_residue(), false );
1492  for ( int ii = pose.conformation().chain_begin( chain_to_redesign ),
1493  lastres = pose.conformation().chain_end( chain_to_redesign ); ii <= lastres; ++ii ) {
1494  // don't allow residues that are currently Gly or Pro to land on stubs
1495  if ( pose.residue(ii).aa() != core::chemical::aa_gly && (pose.residue(ii).aa() != core::chemical::aa_pro || basic::options::option[basic::options::OptionKeys::hotspot::allow_proline] ) ) {
1496  if ( residue_sasa.at(ii) > sasa_thres ) {
1497  allow_stub_constraint.at(ii) = true;
1498  }
1499  }
1500  }
1501  hotspot_hash_packer_taskOP->restrict_to_residues( allow_stub_constraint ); //overriding the resfile
1502 
1503  return hotspot_hash_packer_taskOP;
1504 }
1505 
1507  core::Real const unbound_dist = 40.;
1508  Size const rb_jump = 1; // use the first jump as the one between partners
1509  protocols::rigid::RigidBodyTransMover trans_mover( pose, rb_jump );
1510  trans_mover.trans_axis( trans_mover.trans_axis() );
1511  trans_mover.step_size(unbound_dist);
1512  trans_mover.apply( pose );
1513  return;
1514 }
1515 
1516 
1517 /// @details Searches for all ambiguous constraints that have a backbone stub active constraint.
1518 /// and removes them from the pose. Returns a vector of the removed constraints.
1521 {
1522  using namespace core::scoring::constraints;
1523 
1524  ConstraintCOPs original_csts = pose.constraint_set()->get_all_constraints() ;
1525  ConstraintCOPs bb_csts;
1526  for( ConstraintCOPs::const_iterator it = original_csts.begin(), end = original_csts.end(); it != end; ++it ) {
1527  ConstraintCOP cst( *it );
1528  if( cst->type() == "AmbiguousConstraint" ) {
1529  AmbiguousConstraintCOP ambiguous_cst = AmbiguousConstraintCOP( dynamic_cast< AmbiguousConstraint const *>( cst() ) ); //downcast to derived ambiguous constraint
1530  if( ambiguous_cst) { // safety check for downcasting
1531  if( ambiguous_cst->active_constraint()->type() == "BackboneStub" ) {
1532  bb_csts.push_back( ambiguous_cst() ); // add the entire ambiguous cst, since it contained a bbcst
1533  }
1534  }
1535  }
1536  //tricky; some hotspot stub constraints are added directly with no ambiguity
1537  else if( cst->type() == "BackboneStub" )
1538  bb_csts.push_back( cst );
1539  }
1540  pose.remove_constraints( bb_csts ); // remove all the ambigcsts that contain a bbcst
1541  return( bb_csts );
1542 }
1543 
1544 /// @details Iterates over all non-hydrogen sidechain atoms of two residues and returns their rmsd without superposition.
1545 core::Real
1547 {
1548  return core::scoring::residue_sc_rmsd_no_super( res1, res2, fxnal_group_only );
1549 }
1550 
1551 /// @brief utility function to make sure stub's Cbeta is not pointed away from the target.
1552 /// Returns true if stub is pointed generally towards target's center of mass. Returns false otherwise.
1553 /// algorithm: get vector between CA and target center of mass, then CA-CB vector. Check alignment between the two.
1554 /// doesn't take into account hotspots at the end of the pose so might be a little off in CoM. But probably pretty OK
1556  runtime_assert( target_res <= pose.total_residue() );
1557  core::Size angle_res = target_res;
1558  if( angle_res == 0 ) {
1559  angle_res = geometry::residue_center_of_mass( pose, 1, int(pose.total_residue() ) );
1560  }
1561 
1562  core::Size const CA_stub_index = stub->atom_index("CA");
1563  core::Size const CB_stub_index = stub->atom_index("CB");
1564  core::Size const CA_tgt_index = pose.residue( angle_res ).atom_index("CA");
1565 
1566  core::Vector const CA_tgt = stub->xyz( CA_stub_index ) - pose.residue( angle_res ).xyz( CA_tgt_index );
1567  core::Vector const CA_CB = stub->xyz( CA_stub_index ) - stub->xyz( CB_stub_index );
1568  TR.Debug << "CA-target " << CA_tgt.length() << "\n";
1569  TR.Debug << "CA-CB " << CA_CB.length() << "\n"; // should always be 1.533 A
1570  core::Real const angle = numeric::conversions::degrees(angle_of( CA_tgt, CA_CB ));
1571  TR.Debug << "target-CA-CB angle " << angle;
1572 
1573  return angle;
1574 }
1575 
1576 /*
1577 core::scoring::constraints::AngleConstraintOP make_angle_cst( core::pose::Pose const & pose, core::conformation::ResidueCOP stub ) {
1578  core::Size const CoM = geometry::residue_center_of_mass( pose, 1, int(pose.total_residue()) );
1579  core::Size const CA_stub_index = stub->atom_index("CA");
1580  core::Size const CB_stub_index = stub->atom_index("CB");
1581  core::Size const CA_CoM_index = pose.residue( CoM ).atom_index("CA");
1582 
1583  // note: PeriodicFunc has functional form y = ( k * cos(n * (x - x0) ) ) + C.
1584  FuncOP cos_func = new PeriodicFunc(0., 1., 1., 0.);
1585  anglecst = new AngleConstraint( cos_func );
1586  pose.add_constraint( anglecst );
1587 }
1588 */
1589 
1590 
1591 } // hotspot_hashing
1592 } // protocols