Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RotamerSets.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/pack/RotamerSet/RotamerSets.cc
11 /// @brief RotamerSets class implementation
12 /// @author Andrew Leaver-Fay (leaverfa@email.unc.edu)
13 
14 // Unit Headers
17 
18 // Package Headers
28 
30 #include <core/chemical/AA.hh>
32 #include <core/graph/Graph.hh>
33 #include <core/pose/Pose.hh>
34 #include <core/pose/util.hh>
35 #include <core/scoring/Energies.hh>
40 // AUTO-REMOVED #include <basic/Tracer.hh>
41 #include <core/io/pdb/pose_io.hh>
43 
44 #include <ObjexxFCL/format.hh>
45 
46 // C++
47 #include <fstream>
48 #include <ctime>
49 
50 // ObjexxFCL headers
51 #include <ObjexxFCL/FArray2D.hh>
52 
53 #include <utility/vector1.hh>
54 
55 
56 using namespace ObjexxFCL;
57 
58 
59 namespace core {
60 namespace pack {
61 namespace rotamer_set {
62 
63 RotamerSets::RotamerSets() {}
64 RotamerSets::~RotamerSets() {}
65 
66 void
67 RotamerSets::dump_pdb( pose::Pose const & pose, std::string const & filename ) const
68 {
69  // model 0 -- just the non-moving residues
70  // model N -- Nth rotamer from each set
71  using ObjexxFCL::fmt::I;
72 
73  // open file
74  std::ofstream out( filename.c_str() );
75 
76  // write model 0
77  Size model(0), atom_counter(0);
78 
79  out << "MODEL" << I(9,model) << '\n';
80  for ( Size i=1; i<= pose.total_residue(); ++i ) {
81  if ( task_->pack_residue(i) ) continue;
82  io::pdb::dump_pdb_residue( pose.residue(i), atom_counter, out );
83  }
84  out << "ENDMDL\n";
85 
86  while ( true ) {
87  bool found_a_rotamer( false );
88  ++model;
89 
90  for ( Size ii=1; ii<= nmoltenres_; ++ii ) {
91  //Size const resid( moltenres_2_resid[ ii ] );
92  RotamerSetOP rotset( set_of_rotamer_sets_[ ii ] );
93  if ( rotset->num_rotamers() >= model ) {
94  if ( !found_a_rotamer ) {
95  found_a_rotamer = true;
96  out << "MODEL" << I(9,model) << '\n';
97  }
98  io::pdb::dump_pdb_residue( *(rotset->rotamer( model )), atom_counter, out );
99  }
100  }
101  if ( found_a_rotamer ) {
102  out << "ENDMDL\n";
103  } else {
104  break;
105  }
106  }
107  out.close();
108 }
109 
110 void
111 RotamerSets::set_task( task::PackerTaskCOP task)
112 {
113  task_ = task;
114  nmoltenres_ = task_->num_to_be_packed();
115  total_residue_ = task_->total_residue();
116 
117  resid_2_moltenres_.resize( total_residue_ );
118  moltenres_2_resid_.resize( nmoltenres_ );
119  set_of_rotamer_sets_.resize( nmoltenres_ );
120  nrotamer_offsets_.resize( nmoltenres_ );
121  nrotamers_for_moltenres_.resize( nmoltenres_ );
122 
123  uint count_moltenres = 0;
124  for ( uint ii = 1; ii <= total_residue_; ++ii )
125  {
126  if ( task_->pack_residue( ii ) ) {
127  ++count_moltenres;
128  resid_2_moltenres_[ ii ] = count_moltenres;
129  moltenres_2_resid_[ count_moltenres ] = ii;
130  }
131  else
132  {
133  resid_2_moltenres_[ ii ] = 0; //sentinal value; Andrew, replace this magic number!
134  }
135  }
136  assert( count_moltenres == nmoltenres_ );
137 
138 }
139 
140 void
141 RotamerSets::build_rotamers(
142  pose::Pose const & pose,
143  scoring::ScoreFunction const & sfxn,
144  graph::GraphCOP packer_neighbor_graph
145 )
146 {
147  RotamerSetFactory rsf;
148  for ( uint ii = 1; ii <= nmoltenres_; ++ii )
149  {
150  uint ii_resid = moltenres_2_resid_[ ii ];
151  RotamerSetOP rotset( rsf.create_rotamer_set( pose.residue( ii_resid ) ));
152  rotset->set_resid( ii_resid );
153  rotset->build_rotamers( pose, sfxn, *task_, packer_neighbor_graph );
154 
155  set_of_rotamer_sets_[ ii ] = rotset;
156  }
157 
158  // make sure we have a symmetric RotamerSet_ if we have a symmetric pose
159  if ( core::pose::symmetry::is_symmetric( pose ) ) {
160  if ( set_of_rotamer_sets_.size() > 0 )
161  runtime_assert ( dynamic_cast< core::pack::rotamer_set::symmetry::SymmetricRotamerSet_ const * >( set_of_rotamer_sets_[ 1 ].get() ) );
162  }
163 
164  // now build any additional rotamers that are dependent on placement of other rotamers
165  for ( uint ii = 1; ii <= nmoltenres_; ++ii )
166  {
167  set_of_rotamer_sets_[ ii ]->build_dependent_rotamers( *this, pose, sfxn, *task_, packer_neighbor_graph );
168  }
169 
170  update_offset_data();
171 
172  if (task_->rotamer_links_exist()){
173  //check all the linked positions
174 
175  utility::vector1<bool> visited(pose.total_residue(),false);
176 
177  int expected_rot_count = 0;
178 
179  for ( uint ii = 1; ii <= nmoltenres_; ++ii){
180 
181  utility::vector1<int> copies = task_->rotamer_links()->get_equiv(moltenres_2_resid_[ii]);
182 
183  if ( visited[ moltenres_2_resid_[ii] ]){
184  continue;
185  }
186 
187  int num_rot = 1000000;
188  int smallest_res = 0;
189  for (uint jj = 1; jj <= copies.size(); ++jj){
190  visited[ copies[jj] ] = true;
191  int buffer;
192  buffer = set_of_rotamer_sets_[ resid_2_moltenres_[ copies[jj] ] ]->num_rotamers();
193  if (buffer <= num_rot){
194  num_rot = buffer;
195  smallest_res = copies[jj];
196  }
197  }
198  expected_rot_count += num_rot;
199 
200  //relace rotset with the smallest set
201  RotamerSetCOP bufferset = rotamer_set_for_moltenresidue( resid_2_moltenres_[ smallest_res ]);
202 
203  for (uint jj = 1; jj <= copies.size(); ++jj){
204 
205  if (copies[jj] == smallest_res){
206  //no need to overwrite itself
207  continue;
208  }
209 
210  RotamerSetOP smallset( rsf.create_rotamer_set( pose.residue( 1 ) )) ;
211 
212  for (Rotamers::const_iterator itr = bufferset->begin(), ite = bufferset->end(); itr!=ite; itr++){
213 
214  conformation::ResidueOP cloneRes = new conformation::Residue(*(*itr)->clone());
215 
216  cloneRes->seqpos(copies[jj]);
217 
218  //correct for connections if the smallset is from first or last
219  //residues. These positions don't have a complete connect record.
220 
221  if ((*itr)->seqpos() == 1 && copies[jj] != 1 ){
222  if (cloneRes->has_variant_type("LOWER_TERMINUS")) cloneRes = core::pose::remove_variant_type_from_residue( *cloneRes, chemical::LOWER_TERMINUS, pose);
223  cloneRes->residue_connection_partner(1, copies[jj]-1, 2);
224  cloneRes->residue_connection_partner(2, copies[jj]+1, 1);
225  }
226  else if ((*itr)->seqpos() == 1 && copies[jj] == 1 ){
227  cloneRes->copy_residue_connections( pose.residue(copies[jj]));
228  }
229  else if ( (*itr)->seqpos() == pose.total_residue() && copies[jj] != (int) pose.total_residue() ){
230  if (cloneRes->has_variant_type("UPPER_TERMINUS")) cloneRes = core::pose::remove_variant_type_from_residue( *cloneRes, chemical::UPPER_TERMINUS, pose);
231  cloneRes->residue_connection_partner(1, copies[jj]-1, 2);
232  cloneRes->residue_connection_partner(2, copies[jj]+1, 1);
233  }
234  else if ( (*itr)->seqpos() == pose.total_residue() && copies[jj] == (int) pose.total_residue() ){
235  cloneRes->copy_residue_connections( pose.residue(copies[jj]));
236  }
237  else {
238  cloneRes->copy_residue_connections( pose.residue(copies[jj]));
239  }
240 
241  //debug connectivity
242  //std::cout << "resconn1: " << cloneRes->connected_residue_at_resconn( 1 ) << " ";
243  //std::cout << cloneRes->residue_connection_conn_id(1);
244  //std::cout << " resconn2: " << cloneRes->connected_residue_at_resconn( 2 ) << " ";
245  //std::cout << cloneRes->residue_connection_conn_id(2);
246  //std::cout << " seqpos: " << cloneRes->seqpos() << " for " << copies[jj] << " cloned from " << (*itr)->seqpos() << std::endl;
247 
248  using namespace core::chemical;
249 
250  //if pose is cyclic, it'll have cutpoint variants; in those cases,
251  //leave alone
252  if (copies[jj]==1 && !pose.residue(copies[jj]).has_variant_type(CUTPOINT_UPPER)) {
254  //std::cout << cloneRes->name() << " of variant type lower? " << cloneRes->has_variant_type("LOWER_TERMINUS") << std::endl;
255  }
256  if (copies[jj]== (int) pose.total_residue() && !pose.residue(copies[jj]).has_variant_type(CUTPOINT_LOWER)){
258  //std::cout << cloneRes->name() << " of variant type upper? " << cloneRes->has_variant_type("UPPER_TERMINUS") << std::endl;
259  }
260 
261  cloneRes->place( pose.residue(copies[jj]), pose.conformation());
262 
263  smallset->add_rotamer(*cloneRes);
264 
265  // std::cout << "smallset has " << smallset->num_rotamers() << std::endl;
266  }
267  smallset->set_resid(copies[jj]);
268  set_of_rotamer_sets_[ resid_2_moltenres_[ copies[jj] ]] = smallset;
269  //std::cout << "replacing rotset at " << copies[jj] << " with smallest set from " << smallest_res << std::endl;
270  }
271 
272  //debug
273  /*
274  for (int i =1; i<= set_of_rotamer_sets_.size(); ++i){
275  std::cout << "set of rot set has " << set_of_rotamer_sets_[i]->num_rotamers() << " at " << i << std::endl;
276  }
277  */
278 
279  }
280  std::cout << "expected rotamer count is " << expected_rot_count << std::endl;
281 
282  }
283  update_offset_data();
284 
285 /*
286  // Dump rotamers to the screen.
287  for ( Size ii = 1; ii <= nmoltenres_; ++ii ) {
288  RotamerSetOP rotset( set_of_rotamer_sets_[ ii ] );
289  for ( Size jj = 1; jj <= rotset->num_rotamers(); ++jj ) {
290  conformation::ResidueCOP jjres( rotset->rotamer( jj ) );
291  std::cout << "ROT: " << ii << " " << jj << " " << jjres->name();
292  for ( Size kk = 1; kk <= jjres->nchi(); ++kk ) {
293  std::cout << " " << jjres->chi( kk );
294  }
295  std::cout << std::endl;
296  }
297  }
298 */
299 }
300 
301 void
302 RotamerSets::update_offset_data()
303 {
304  // count rotamers
305  nrotamers_ = 0;
306  for ( uint ii = 1; ii <= nmoltenres_; ++ii )
307  {
308  nrotamers_for_moltenres_[ ii ] = set_of_rotamer_sets_[ii]->num_rotamers();
309  nrotamers_ += set_of_rotamer_sets_[ii]->num_rotamers();
310  if ( ii > 1 ) { nrotamer_offsets_[ ii ] = nrotamer_offsets_[ii - 1] + set_of_rotamer_sets_[ii - 1]->num_rotamers(); }
311  else { nrotamer_offsets_[ ii ] = 0; }
312  }
313 
314  moltenres_for_rotamer_.resize( nrotamers_ );
315  uint count_rots_for_moltenres = 1;
316  uint count_moltenres = 1;
317  for ( uint ii = 1; ii <= nrotamers_; ++ii )
318  {
319  moltenres_for_rotamer_[ ii ] = count_moltenres;
320  if ( count_rots_for_moltenres == nrotamers_for_moltenres_[ count_moltenres ] )
321  {
322  count_rots_for_moltenres = 1;
323  ++count_moltenres;
324  }
325  else
326  {
327  ++count_rots_for_moltenres;
328  }
329  }
330 }
331 
332 // @details For now, this function knows that all RPEs are computed before annealing begins
333 // In not very long, this function will understand that there are different ways to compute
334 // energies and to store them, but for now, it does not.
335 void
336 RotamerSets::compute_energies(
337  pose::Pose const & pose,
338  scoring::ScoreFunction const & scfxn,
339  graph::GraphCOP packer_neighbor_graph,
341 )
342 {
343  using namespace interaction_graph;
344  using namespace scoring;
345 
346  //basic::Tracer tt("core.pack.rotamer_set", basic::t_trace );
347 
348  ig->initialize( *this );
349  compute_one_body_energies( pose, scfxn, packer_neighbor_graph, ig );
350 
352  dynamic_cast< PrecomputedPairEnergiesInteractionGraph * > ( ig.get() );
353  if ( pig ) {
354  precompute_two_body_energies( pose, scfxn, packer_neighbor_graph, pig );
355  } else {
356  /// is this an on the fly graph?
357  OnTheFlyInteractionGraphOP otfig = dynamic_cast< OnTheFlyInteractionGraph * > ( ig.get() );
358  if ( otfig ) {
359  prepare_otf_graph( pose, scfxn, packer_neighbor_graph, otfig );
360  compute_proline_correction_energies_for_otf_graph( pose, scfxn, packer_neighbor_graph, otfig);
361  } else {
362  utility_exit_with_message("Unknown interaction graph type encountered in RotamerSets::compute_energies()");
363  }
364  }
365 
366 }
367 
368 void
369 RotamerSets::compute_one_body_energies(
370  pose::Pose const & pose,
371  scoring::ScoreFunction const & scfxn,
372  graph::GraphCOP packer_neighbor_graph,
374 )
375 {
376  // One body energies -- shared between pigs and otfigs
377  for ( uint ii = 1; ii <= nmoltenres_; ++ii )
378  {
379  utility::vector1< core::PackerEnergy > one_body_energies( set_of_rotamer_sets_[ ii ]->num_rotamers() );
380  set_of_rotamer_sets_[ ii ]->compute_one_body_energies(
381  pose, scfxn, *task_, packer_neighbor_graph, one_body_energies );
382  ig->add_to_nodes_one_body_energy( ii, one_body_energies );
383  }
384 }
385 
386 void
387 RotamerSets::precompute_two_body_energies(
388  pose::Pose const & pose,
389  scoring::ScoreFunction const & scfxn,
390  graph::GraphCOP packer_neighbor_graph,
392  bool const finalize_edges
393 )
394 {
395  using namespace interaction_graph;
396  using namespace scoring;
397 
398  //std::clock_t starttime = clock();
399 
400  // Two body energies
401  //scoring::EnergyGraph const & energy_graph( pose.energies().energy_graph() );
402  for ( uint ii = 1; ii <= nmoltenres_; ++ ii )
403  {
404  //tt << "pairenergies for ii: " << ii << '\n';
405  uint const ii_resid = moltenres_2_resid_[ ii ];
406  //when design comes online, we will want to iterate across
407  //neighbors defined by a larger interaction cutoff
409  uli = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_begin(),
410  ulie = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_end();
411  uli != ulie; ++uli )
412  {
413  uint const jj_resid = (*uli)->get_second_node_ind();
414  uint const jj = resid_2_moltenres_[ jj_resid ]; //pretend we're iterating over jj >= ii
415  if ( jj == 0 ) continue; // Andrew, remove this magic number!
416 
417  FArray2D< core::PackerEnergy > pair_energy_table(
418  nrotamers_for_moltenres_[ jj ],
419  nrotamers_for_moltenres_[ ii ], 0.0 );
420 
421  RotamerSetCOP ii_rotset = set_of_rotamer_sets_[ ii ];
422  RotamerSetCOP jj_rotset = set_of_rotamer_sets_[ jj ];
423 
425  *ii_rotset, *jj_rotset, pose, pair_energy_table );
426 
427  pig->add_edge( ii, jj );
428  pig->add_to_two_body_energies_for_edge( ii, jj, pair_energy_table );
429 
430  if ( finalize_edges && ! scfxn.any_lr_residue_pair_energy(pose, ii, jj) ){
431  pig->declare_edge_energies_final( ii, jj );
432  }
433 
434  }
435  }
436 
437  // Iterate across the long range energy functions and use the iterators generated
438  // by the LRnergy container object
440  lr_iter = scfxn.long_range_energies_begin(),
441  lr_end = scfxn.long_range_energies_end();
442  lr_iter != lr_end; ++lr_iter ) {
443  LREnergyContainerCOP lrec = pose.energies().long_range_container( (*lr_iter)->long_range_type() );
444  if ( !lrec || lrec->empty() ) continue; // only score non-emtpy energies.
445  // Potentially O(N^2) operation...
446 
447  for ( uint ii = 1; ii <= nmoltenres_; ++ ii ) {
448  uint const ii_resid = moltenres_2_resid_[ ii ];
449 
451  rni = lrec->const_upper_neighbor_iterator_begin( ii_resid ),
452  rniend = lrec->const_upper_neighbor_iterator_end( ii_resid );
453  (*rni) != (*rniend); ++(*rni) ) {
454  Size const jj_resid = rni->upper_neighbor_id();
455 
456  uint const jj = resid_2_moltenres_[ jj_resid ]; //pretend we're iterating over jj >= ii
457  if ( jj == 0 ) continue; // Andrew, remove this magic number! (it's the signal that jj_resid is not "molten")
458 
459  FArray2D< core::PackerEnergy > pair_energy_table(
460  nrotamers_for_moltenres_[ jj ],
461  nrotamers_for_moltenres_[ ii ], 0.0 );
462 
463  RotamerSetCOP ii_rotset = set_of_rotamer_sets_[ ii ];
464  RotamerSetCOP jj_rotset = set_of_rotamer_sets_[ jj ];
465 
466  (*lr_iter)->evaluate_rotamer_pair_energies(
467  *ii_rotset, *jj_rotset, pose, scfxn, scfxn.weights(), pair_energy_table );
468 
469  if ( ! pig->get_edge_exists( ii, jj ) ) { pig->add_edge( ii, jj ); }
470  pig->add_to_two_body_energies_for_edge( ii, jj, pair_energy_table );
471  if ( finalize_edges ) pig->declare_edge_energies_final( ii, jj );
472  }
473  }
474  }
475 
476  //std::clock_t stoptime = clock();
477  //std::cout << "Precompute rotamer pair energies took " << ((double) stoptime - starttime)/CLOCKS_PER_SEC << " seconds" << std::endl;
478 }
479 
480 void
481 RotamerSets::prepare_otf_graph(
482  pose::Pose const & pose,
483  scoring::ScoreFunction const & scfxn,
484  graph::GraphCOP packer_neighbor_graph,
486 )
487 {
488  using namespace conformation;
489  using namespace interaction_graph;
490  using namespace scoring;
491 
492  FArray2D_bool sparse_conn_info( otfig->get_num_aatypes(), otfig->get_num_aatypes(), false );
493 
494  /// Mark all-amino-acid nodes as worthy of distinguishing between bb & sc
495  for ( Size ii = 1; ii <= nmoltenres_; ++ii ) {
496  RotamerSetCOP ii_rotset = set_of_rotamer_sets_[ ii ];
497  bool all_canonical_aas( true );
498  for ( Size jj = 1, jje = ii_rotset->get_n_residue_types(); jj <= jje; ++jj ) {
499  ResidueCOP jj_rotamer = ii_rotset->rotamer( ii_rotset->get_residue_type_begin( jj ) );
500  if ( jj_rotamer->aa() > chemical::num_canonical_aas ) {
501  all_canonical_aas = false;
502  }
503  }
504  if ( all_canonical_aas ) {
505  otfig->distinguish_backbone_and_sidechain_for_node( ii, true );
506  }
507  }
508 
509  for ( Size ii = 1; ii <= nmoltenres_; ++ii ) {
510  //tt << "pairenergies for ii: " << ii << '\n';
511  uint const ii_resid = moltenres_2_resid_[ ii ];
513  uli = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_begin(),
514  ulie = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_end();
515  uli != ulie; ++uli ) {
516  uint const jj_resid = (*uli)->get_second_node_ind();
517  uint const jj = resid_2_moltenres_[ jj_resid ]; //pretend we're iterating over jj >= ii
518  if ( jj == 0 ) continue; // Andrew, remove this magic number!
519 
520  bool any_neighbors = false;
521 
522  if ( scfxn.any_lr_residue_pair_energy(pose, ii, jj) ){
523  otfig->note_long_range_interactions_exist_for_edge( ii, jj );
524  // if there are any lr interactions between these two residues, assume, all
525  // residue type pairs interact
526  any_neighbors = true;
527  sparse_conn_info = true;
528  } else {
529 
530  // determine which groups of rotamers are within their interaction distances
531  RotamerSetCOP ii_rotset = set_of_rotamer_sets_[ ii ];
532  RotamerSetCOP jj_rotset = set_of_rotamer_sets_[ jj ];
533 
534  sparse_conn_info = false;
535  Distance const sfxn_reach = scfxn.info()->max_atomic_interaction_distance();
536  for ( Size kk = 1, kk_end = ii_rotset->get_n_residue_types(); kk <= kk_end; ++kk ) {
537  Size kk_example_rotamer_index = ii_rotset->get_residue_type_begin( kk );
538  conformation::Residue const & kk_rotamer( *ii_rotset->rotamer( kk_example_rotamer_index ) );
539 
540  Distance const kk_reach = kk_rotamer.nbr_radius();
541  Vector const kk_nbratom( kk_rotamer.xyz( kk_rotamer.nbr_atom() ) );
542 
543  for ( Size ll = 1, ll_end = jj_rotset->get_n_residue_types(); ll <= ll_end; ++ll ) {
544  Size ll_example_rotamer_index = jj_rotset->get_residue_type_begin( ll );
545  conformation::Residue const & ll_rotamer( *jj_rotset->rotamer( ll_example_rotamer_index ) );
546 
547  Distance const ll_reach( ll_rotamer.nbr_radius() );
548  Vector const ll_nbratom( ll_rotamer.xyz( ll_rotamer.nbr_atom() ) );
549 
550  DistanceSquared const nbrdist2 = kk_nbratom.distance_squared( ll_nbratom );
551  Distance const intxn_cutoff = sfxn_reach + kk_reach + ll_reach;
552 
553  if ( nbrdist2 <= intxn_cutoff * intxn_cutoff ) {
554  any_neighbors = true;
555  sparse_conn_info( ll, kk ) = true; // these two are close enough to interact, according to the score function.
556  }
557  }
558  }
559  }
560 
561  if ( any_neighbors ) {
562  otfig->add_edge( ii, jj );
563  otfig->note_short_range_interactions_exist_for_edge( ii, jj );
564  otfig->set_sparse_aa_info_for_edge( ii, jj, sparse_conn_info );
565  }
566  }
567  }
568 
569  sparse_conn_info = true;
570  // Iterate across the long range energy functions and use the iterators generated
571  // by the LRnergy container object
573  lr_iter = scfxn.long_range_energies_begin(),
574  lr_end = scfxn.long_range_energies_end();
575  lr_iter != lr_end; ++lr_iter ) {
576  LREnergyContainerCOP lrec = pose.energies().long_range_container( (*lr_iter)->long_range_type() );
577  if ( !lrec || lrec->empty() ) continue; // only score non-empty energies.
578  // Potentially O(N^2) operation...
579 
580  for ( uint ii = 1; ii <= nmoltenres_; ++ ii ) {
581  uint const ii_resid = moltenres_2_resid_[ ii ];
582 
584  rni = lrec->const_upper_neighbor_iterator_begin( ii_resid ),
585  rniend = lrec->const_upper_neighbor_iterator_end( ii_resid );
586  (*rni) != (*rniend); ++(*rni) ) {
587  Size const jj_resid = rni->upper_neighbor_id();
588 
589  uint const jj = resid_2_moltenres_[ jj_resid ]; //pretend we're iterating over jj >= ii
590  if ( jj == 0 ) continue; // Andrew, remove this magic number! (it's the signal that jj_resid is not "molten")
591 
592  //RotamerSetCOP ii_rotset = set_of_rotamer_sets_[ ii ];
593  //RotamerSetCOP jj_rotset = set_of_rotamer_sets_[ jj ];
594 
595  //std::cout << "preprare_oft_graph -- long range iterator = " << ii_resid << " " << jj_resid << std::endl;
596 
597  /// figure out how to notify the lrec that it should only consider these two residues neighbors
598  /// for the sake of packing...
599  if ( ! otfig->get_edge_exists( ii, jj ) ) {
600  otfig->add_edge( ii, jj );
601  }
602  otfig->note_long_range_interactions_exist_for_edge( ii, jj );
603  otfig->set_sparse_aa_info_for_edge( ii, jj, sparse_conn_info );
604 
605  }
606  }
607  }
608 
609 }
610 
611 /// @details
612 /// 0. Find example proline and glycine residues where possible.
613 /// 1. Iterate across all edges in the graph
614 /// 2. Calculate proline-correction terms between neighbors
615 void
616 RotamerSets::compute_proline_correction_energies_for_otf_graph(
617  pose::Pose const & pose,
618  scoring::ScoreFunction const & scfxn,
619  graph::GraphCOP packer_neighbor_graph,
621 )
622 {
623  using namespace conformation;
624 
625  utility::vector1< Size > example_gly_rotamers( nmoltenres_, 0 );
626  utility::vector1< Size > example_pro_rotamers( nmoltenres_, 0 );
627 
628  /// 0. Find example proline and glycine residues where possible.
629  for ( Size ii = 1; ii <= nmoltenres_; ++ii ) {
630  RotamerSetCOP ii_rotset = set_of_rotamer_sets_[ ii ];
631  Size potential_gly_replacement( 0 );
632  for ( Size jj = 1, jje = ii_rotset->get_n_residue_types(); jj <= jje; ++jj ) {
633  ResidueCOP jj_rotamer = ii_rotset->rotamer( ii_rotset->get_residue_type_begin( jj ) );
634  if ( jj_rotamer->aa() == chemical::aa_gly ) {
635  example_gly_rotamers[ ii ] = ii_rotset->get_residue_type_begin( jj );
636  } else if ( jj_rotamer->aa() == chemical::aa_pro ) {
637  example_pro_rotamers[ ii ] = ii_rotset->get_residue_type_begin( jj );
638  } else if ( jj_rotamer->is_protein() ) {
639  potential_gly_replacement = ii_rotset->get_residue_type_begin( jj );
640  }
641  }
642  /// failed to find a glycine backbone for this residue, any other
643  /// backbone will do, so long as its a protein backbone.
644  if ( example_gly_rotamers[ ii ] == 0 ) {
645  example_gly_rotamers[ ii ] = potential_gly_replacement;
646  }
647  }
648 
649  /// 1. Iterate across all edges in the graph
650  for ( Size ii = 1; ii <= nmoltenres_; ++ ii ) {
651  Size const ii_resid = moltenres_2_resid_[ ii ];
652  if ( ! otfig->distinguish_backbone_and_sidechain_for_node( ii ) ) continue;
654  uli = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_begin(),
655  ulie = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_end();
656  uli != ulie; ++uli ) {
657  Size const jj_resid = (*uli)->get_second_node_ind();
658  Size const jj = resid_2_moltenres_[ jj_resid ]; //pretend we're iterating over jj >= ii
659  if ( jj == 0 ) continue;
660  if ( ! otfig->distinguish_backbone_and_sidechain_for_node( jj ) ) continue;
661  /// 2. Calculate proline-correction terms between neighbors
662 
663  RotamerSetCOP ii_rotset = set_of_rotamer_sets_[ ii ];
664  RotamerSetCOP jj_rotset = set_of_rotamer_sets_[ jj ];
665 
666  for ( Size kk = 1; kk <= ii_rotset->num_rotamers(); ++kk ) {
667  core::PackerEnergy bb_bbnonproE( 0 ), bb_bbproE( 0 );
668  core::PackerEnergy sc_npbb_energy( 0 ), sc_probb_energy( 0 );
669  //calc sc_npbb_energy;
670  if ( example_gly_rotamers[ jj ] != 0 ) {
671  bb_bbnonproE = get_bb_bbE( pose, scfxn, *ii_rotset->rotamer( kk ), *jj_rotset->rotamer( example_gly_rotamers[ jj ] ) );
672  sc_npbb_energy = get_sc_bbE( pose, scfxn, *ii_rotset->rotamer( kk ), *jj_rotset->rotamer( example_gly_rotamers[ jj ] ) );
673  }
674  //calc sc_probb_energy
675  if ( example_pro_rotamers[ jj ] != 0 ) {
676  bb_bbproE = get_bb_bbE( pose, scfxn, *ii_rotset->rotamer( kk ), *jj_rotset->rotamer( example_pro_rotamers[ jj ] ) );
677  sc_probb_energy = get_sc_bbE( pose, scfxn, *ii_rotset->rotamer( kk ), *jj_rotset->rotamer( example_pro_rotamers[ jj ] ) );
678  }
679  otfig->add_to_one_body_energy_for_node_state( ii, kk, sc_npbb_energy + 0.5 * bb_bbnonproE );
680  otfig->set_ProCorrection_values_for_edge( ii, jj, ii, kk,
681  bb_bbnonproE, bb_bbproE, sc_npbb_energy, sc_probb_energy );
682  }
683 
684  for ( Size kk = 1; kk <= jj_rotset->num_rotamers(); ++kk ) {
685  core::PackerEnergy bb_bbnonproE( 0 ), bb_bbproE( 0 );
686  core::PackerEnergy sc_npbb_energy( 0 ), sc_probb_energy( 0 );
687  //calc sc_npbb_energy;
688  if ( example_gly_rotamers[ ii ] != 0 ) {
689  bb_bbnonproE = get_bb_bbE( pose, scfxn, *jj_rotset->rotamer( kk ), *ii_rotset->rotamer( example_gly_rotamers[ ii ] ) );
690  sc_npbb_energy = get_sc_bbE( pose, scfxn, *jj_rotset->rotamer( kk ), *ii_rotset->rotamer( example_gly_rotamers[ ii ] ) );
691  }
692  //calc sc_probb_energy
693  if ( example_pro_rotamers[ ii ] != 0 ) {
694  bb_bbproE = get_bb_bbE( pose, scfxn, *jj_rotset->rotamer( kk ), *ii_rotset->rotamer( example_pro_rotamers[ ii ] ) );
695  sc_probb_energy = get_sc_bbE( pose, scfxn, *jj_rotset->rotamer( kk ), *ii_rotset->rotamer( example_pro_rotamers[ ii ] ) );
696  }
697  otfig->add_to_one_body_energy_for_node_state( jj, kk, sc_npbb_energy + 0.5 * bb_bbnonproE );
698 
699  otfig->set_ProCorrection_values_for_edge( ii, jj, jj, kk,
700  bb_bbnonproE, bb_bbproE, sc_npbb_energy, sc_probb_energy );
701  }
702 
703  }
704  }
705 
706  /* Giant code duplication ahead! -- when I'm 100% sure this is totally unncessary, I'll delete it... but it took a while to write
707  /// 3. For each molten residue
708  for ( Size ii = 1; ii <= (Size) nmoltenres_; ++ii ) {
709  RotamerSetCOP ii_rotset = set_of_rotamer_sets_[ ii ];
710  /// 4. Calculate one body energies
711  Size const ii_nrots = ii_rotset->num_rotamers();
712  Size const ii_resid = moltenres_2_resid_[ ii ];
713 
714  utility::vector1< core::PackerEnergy > energies( ii_nrots, 0.0 );
715  for ( Size jj = 1; jj <= ii_nrots; ++jj ) {
716  EnergyMap emap;
717  sfxn.eval_ci_1b( *ii_rotset->rotamers( jj ), pose, emap );
718  sfxn.eval_cd_1b( *ii_rotset->rotamers( jj ), pose, emap );
719  energies[ jj ] += static_cast< core::PackerEnergy > ( sfxn.weights().dot( emap ) ); // precision loss here.
720  }
721 
722  sfxn.evaluate_rotamer_intrares_energies( *ii_rotset, pose, energies );
723 
724  /// 5. Iterate across all incident edges for the corresponding vertex in the packer neighbor graph
725  for ( graph::Graph::EdgeListConstIter
726  uli = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_begin(),
727  ulie = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_end();
728  uli != ulie; ++uli ) {
729  Size const jj_resid = (*uli)->get_second_node_ind();
730  Size const jj = resid_2_moltenres_[ jj_resid ]; //pretend we're iterating over jj >= ii
731  if ( jj != 0 ) continue;
732  /// 6. Calculate two-body energies with the background residues
733  Residue const & neighbor( pose.residue( jj_resid ) );
734  sfxn.evaluate_rotamer_background_energies( ii_rotset, neighbor, pose, energies );
735  }
736 
737  /// 7. Iterate across long-range edges
738  for ( ScoreFunction::LR_2B_MethodIterator
739  lr_iter = sf.long_range_energies_begin(),
740  lr_end = sf.long_range_energies_end();
741  lr_iter != lr_end; ++lr_iter ) {
742  LREnergyContainerCOP lrec = pose.energies().long_range_container( (*lr_iter)->long_range_type() );
743  if ( !lrec || lrec->empty() ) continue; // only score non-emtpy energies.
744 
745  // Potentially O(N) operation...
746  for ( ResidueNeighborConstIteratorOP
747  rni = lrec->const_neighbor_iterator_begin( ii_resid ),
748  rniend = lrec->const_neighbor_iterator_end( ii_resid );
749  (*rni) != (*rniend); ++(*rni) ) {
750  Size const neighbor_id = rni->neighbor_id();
751  assert( neighbor_id != theresid );
752  if ( resid_2_moltenres_[ neighbor_id ] != 0 ) continue;
753 
754  (*lr_iter)->evaluate_rotamer_background_energies(
755  *ii_rotset, pose.residue( neighbor_id ), pose, sfxn,
756  sfxn.weights(), energies );
757 
758  } // (potentially) long-range neighbors of ii
759  } // long-range energy functions
760 
761  for ( Size jj = 1; jj <= ii_nrots; ++jj ) {
762  otfig->add_to_one_body_energy_for_node_state( ii, jj, energies[ jj ] );
763  }
764 
765  }*/
766 }
767 
768 
769 
770 uint RotamerSets::nrotamers() const { return nrotamers_;}
771 uint RotamerSets::nrotamers_for_moltenres( uint mresid ) const
772 {
773  return rotamer_set_for_moltenresidue( mresid )->num_rotamers();
774 }
775 
776 uint RotamerSets::nmoltenres() const { return nmoltenres_;}
777 
778 uint RotamerSets::total_residue() const { return total_residue_;}
779 
780 uint
781 RotamerSets::moltenres_2_resid( uint mresid ) const { return moltenres_2_resid_[ mresid ]; }
782 
783 uint
784 RotamerSets::resid_2_moltenres( uint resid ) const { return resid_2_moltenres_[ resid ]; }
785 
786 uint
787 RotamerSets::moltenres_for_rotamer( uint rotid ) const { return moltenres_for_rotamer_[ rotid ]; }
788 
789 uint
790 RotamerSets::res_for_rotamer( uint rotid ) const { return moltenres_2_resid( moltenres_for_rotamer( rotid ) ); }
791 
793 RotamerSets::rotamer( uint rotid ) const
794 {
795  return rotamer_set_for_residue( res_for_rotamer( rotid ) )->rotamer( rotid_on_moltenresidue( rotid ) );
796 }
797 
799 RotamerSets::rotamer_for_moltenres( uint moltenres_id, uint rotamerid ) const
800 {
801  return rotamer_set_for_moltenresidue( moltenres_id )->rotamer( rotamerid );
802 }
803 
804 
805 uint
806 RotamerSets::nrotamer_offset_for_moltenres( uint mresid ) const { return nrotamer_offsets_[ mresid ]; }
807 
809 RotamerSets::rotamer_set_for_residue( uint resid ) const { return set_of_rotamer_sets_[ resid_2_moltenres( resid ) ]; }
810 
812 RotamerSets::rotamer_set_for_residue( uint resid ) { return set_of_rotamer_sets_[ resid_2_moltenres( resid ) ]; }
813 
815 RotamerSets::rotamer_set_for_moltenresidue( uint moltenresid ) const { return set_of_rotamer_sets_[ moltenresid ]; }
816 
817 
819 RotamerSets::rotamer_set_for_moltenresidue( uint moltenresid ) { return set_of_rotamer_sets_[ moltenresid ]; }
820 
821 /// convert rotid in full rotamer enumeration into rotamer id on its source residue
822 uint
823 RotamerSets::rotid_on_moltenresidue( uint rotid ) const
824 {
825  return rotid - nrotamer_offsets_[ moltenres_for_rotamer_[ rotid ] ];
826 }
827 
828 /// convert moltenres rotid to id in full rotamer enumeration
829 uint
830 RotamerSets::moltenres_rotid_2_rotid( uint moltenres, uint moltenresrotid ) const
831 {
832  return moltenresrotid + nrotamer_offsets_[ moltenres ];
833 }
834 
835 /// access to packer_task_
837 RotamerSets::task() const
838 {
839  return task_;
840 }
841 
842 void
843 RotamerSets::prepare_sets_for_packing(
844  pose::Pose const & pose,
845  scoring::ScoreFunction const & sfxn)
846 {
847  for ( Size ii = 1; ii <= nmoltenres(); ++ii )
848  {
849  sfxn.prepare_rotamers_for_packing( pose, *set_of_rotamer_sets_[ ii ] );
850  }
851 }
852 
854 RotamerSets::get_bb_bbE(
855  pose::Pose const & pose,
856  scoring::ScoreFunction const & sfxn,
857  conformation::Residue const & res1,
858  conformation::Residue const & res2
859 )
860 {
861  scoring::EnergyMap emap;
862  sfxn.eval_ci_2b_bb_bb( res1, res2, pose, emap );
863  sfxn.eval_cd_2b_bb_bb( res1, res2, pose, emap );
864  return static_cast< core::PackerEnergy > ( sfxn.weights().dot( emap ) );
865 }
866 
868 RotamerSets::get_sc_bbE(
869  pose::Pose const & pose,
870  scoring::ScoreFunction const & sfxn,
871  conformation::Residue const & res1,
872  conformation::Residue const & res2
873 )
874 {
875  scoring::EnergyMap emap;
876  sfxn.eval_ci_2b_bb_sc( res2, res1, pose, emap );
877  sfxn.eval_cd_2b_bb_sc( res2, res1, pose, emap );
878  return static_cast< core::PackerEnergy > ( sfxn.weights().dot( emap ) );
879 }
880 
881 
882 } // namespace rotamer_set
883 } // namespace pack
884 } // namespace core
885