Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SymmetricRotamerSets.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // This file is part of the Rosetta software suite and is made available under license.
5 // The Rosetta software is developed by the contributing members of the Rosetta Commons consortium.
6 // (C) 199x-2009 Rosetta Commons participating institutions and developers.
7 // For more information, see http://www.rosettacommons.org/.
8 
9 /// @file core/pack/RotamerSet/RotamerSets.cc
10 /// @brief RotamerSets class implementation, for symmetric packing
11 /// @author Ingemar Andre
12 
13 // Unit Headers
15 
16 // Package Headers
24 
28 #include <core/chemical/AA.hh>
29 #include <core/graph/Graph.hh>
30 #include <core/pose/Pose.hh>
31 #include <core/scoring/Energies.hh>
33 // AUTO-REMOVED #include <core/scoring/ScoreFunctionInfo.hh>
36 // AUTO-REMOVED #include <basic/Tracer.hh>
37 // AUTO-REMOVED #include <core/io/pdb/pose_io.hh>
38 
39 
40 // C++
41 // AUTO-REMOVED #include <fstream>
42 
43 // ObjexxFCL headers
44 #include <ObjexxFCL/FArray2D.hh>
45 
46 #include <utility/vector1.hh>
47 
48 
49 using namespace ObjexxFCL;
50 
51 
52 namespace core {
53 namespace pack {
54 namespace rotamer_set {
55 namespace symmetry {
56 
57 SymmetricRotamerSets::SymmetricRotamerSets() {}
58 SymmetricRotamerSets::~SymmetricRotamerSets() {}
59 
60 // @details For now, this function knows that all RPEs are computed before annealing begins
61 // In not very long, this function will understand that there are different ways to compute
62 // energies and to store them, but for now, it does not.
63 // symmetrical version of RotamerSets::compute_energies.
64 void
65 SymmetricRotamerSets::compute_energies(
66  pose::Pose const & pose,
67  scoring::ScoreFunction const & scfxn,
68  graph::GraphCOP packer_neighbor_graph,
70 )
71 {
72  using namespace interaction_graph;
73  using namespace scoring;
74 
75  //basic::Tracer tt("core.pack.rotamer_set", basic::t_trace );
76 
77  ig->initialize( *this );
78  compute_one_body_energies( pose, scfxn, packer_neighbor_graph, ig );
79 
81  dynamic_cast< PrecomputedPairEnergiesInteractionGraph * > ( ig.get() );
82  if ( pig ) {
83  precompute_two_body_energies( pose, scfxn, packer_neighbor_graph, pig );
84  } else {
86  dynamic_cast< SymmOnTheFlyInteractionGraph * > ( ig.get() );
87  if ( symotfig ) {
88  prepare_symm_otf_interaction_graph( pose, scfxn, packer_neighbor_graph, symotfig );
89  } else {
90  utility_exit_with_message( "Encountered incompatible interaction graph type in SymmetricRotamerSets::compute_energies" );
91  }
92  }
93 
94 }
95 
96 // @details compute all rotamer one-body interactions for a symmetrical rotamer_sets
97 void
98 SymmetricRotamerSets::compute_one_body_energies(
99  pose::Pose const & pose,
100  scoring::ScoreFunction const & scfxn,
101  graph::GraphCOP packer_neighbor_graph,
103 )
104 {
105  // One body energies -- shared between pigs and otfigs
106  for ( uint ii = 1; ii <= nmoltenres(); ++ii )
107  {
108  utility::vector1< core::PackerEnergy > one_body_energies( rotamer_set_for_moltenresidue( ii )->num_rotamers() );
109  rotamer_set_for_moltenresidue( ii )->compute_one_body_energies(
110  pose, scfxn, *task(), packer_neighbor_graph, one_body_energies );
111  ig->add_to_nodes_one_body_energy( ii, one_body_energies );
112  }
113 }
114 
115 // @details calculate all rotamer two body interactions and place them in a ig. Adds in
116 // energies for symmetrical clone residues into the energy of the master residues. The
117 // idea is the following:
118 void
119 SymmetricRotamerSets::precompute_two_body_energies(
120  pose::Pose const & pose,
121  scoring::ScoreFunction const & scfxn,
122  graph::GraphCOP packer_neighbor_graph,
124  bool const finalize_edges
125 )
126 {
127  using namespace interaction_graph;
128  using namespace scoring;
129 
130  // find SymmInfo
131  SymmetricConformation const & SymmConf (
132  dynamic_cast<SymmetricConformation const &> ( pose.conformation()) );
133  SymmetryInfoCOP symm_info( SymmConf.Symmetry_Info() );
134 
135  // Two body energies
136  for ( uint ii = 1; ii <= nmoltenres(); ++ii )
137  {
138  //tt << "pairenergies for ii: " << ii << '\n';
139  uint ii_resid = moltenres_2_resid( ii );
140  // observe that we will loop over only one subunit here
142  uli = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_begin(),
143  ulie = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_end();
144  uli != ulie; ++uli )
145  {
146  uint jj_resid = (*uli)->get_second_node_ind();
147  uint jj = resid_2_moltenres( jj_resid ); //pretend we're iterating over jj >= ii
148  // if jj_resid is not repackable and jj_resid is not in a different subunit continue
149  if ( jj == 0 && symm_info->chi_follows( jj_resid ) == 0 ) continue;
150  // if jj_resid is in a different subunit we need to know its master
151  uint jj_resid_master = jj_resid;
152  if ( symm_info->chi_follows( jj_resid ) != 0 ) jj_resid_master = symm_info->chi_follows( jj_resid );
153  // find out the moltenres id for the master
154  uint jj_master = resid_2_moltenres( jj_resid_master );
155  // if the master is not repackable continue
156  if ( jj_master == 0 ) continue;
157  // if we the ii_resid and jj_resid_master have an edge this intersubunit
158  // interaction is already being calculated
159 // if ( packer_neighbor_graph->get_edge_exists(ii_resid,jj_resid_master ) && jj == 0 ) continue;
160 
161  uint ii_master = ii;
162  uint ii_resid_master = ii_resid;
163 
164  // the self interaction energy is already calculated in the one-body ter,
165  if ( ii_master == jj_master ) continue;
166  // swap the order of the nodes that form the edge if jj_resid_master < ii_resid.
167  // Edges are always stored as pairs (a, b) where a > b. This only happens if we
168  // are calculation interactions from the controling subunit to another subunit
169  bool swap( false );
170  if ( jj_resid_master < ii_resid ) {
171  swap = true;
172  uint temp_ii = ii_master;
173  uint temp_ii_resid = ii_resid_master;
174  ii_master = jj_master;
175  ii_resid_master = jj_resid_master;
176  jj_master = temp_ii;
177  jj_resid_master = temp_ii_resid;
178  }
179 
180  // make a pair energy table to store use jj_master and ii_master
181  // to size the array ( if we have have a intersubunit interaction)
182  FArray2D< core::PackerEnergy > pair_energy_table(
183  nrotamers_for_moltenres( jj_master ),
184  nrotamers_for_moltenres( ii_master ), 0.0 );
185 
186  RotamerSetOP ii_rotset = rotamer_set_for_moltenresidue( ii_master );
187  RotamerSetOP jj_rotset = rotamer_set_for_moltenresidue( jj_master );
188 
189  // we have a intersubunit interaction then calculate the interaction
190  // here instead of the intrasubunit interaction. If jj == 0 then we will calculate
191  // intrasubunit interaction. If we swapped the order we have to orient ii instead of jj
192  if ( symm_info->chi_follows( jj_resid ) != 0 && jj == 0 ) {
193  if ( swap ) {
194  RotamerSetOP rotated_ii_rotset(
195  orient_rotamer_set_to_symmetric_partner(pose,ii_resid_master,jj_resid) );
196  ii_rotset = rotated_ii_rotset;
197  scfxn.prepare_rotamers_for_packing( pose, *ii_rotset );
198  } else {
199  RotamerSetOP rotated_jj_rotset(
200  orient_rotamer_set_to_symmetric_partner(pose,jj_resid_master,jj_resid) );
201  jj_rotset = rotated_jj_rotset;
202  scfxn.prepare_rotamers_for_packing( pose, *jj_rotset );
203  }
204  }
206  *ii_rotset, *jj_rotset, pose, pair_energy_table );
207 
208  // Apply the multiplication factors
209  pair_energy_table *= symm_info->score_multiply(ii_resid,jj_resid);
210  if ( !pig->get_edge_exists( ii_master, jj_master ) ) {
211  pig->add_edge( ii_master, jj_master );
212  }
213  pig->add_to_two_body_energies_for_edge( ii_master, jj_master, pair_energy_table );
214 
215  // finalize the edge
216  if ( finalize_edges && ! scfxn.any_lr_residue_pair_energy(pose, ii_master, jj_master )
217  && final_visit_to_edge( pose, packer_neighbor_graph, ii_resid, jj_resid ) ){
218  pig->declare_edge_energies_final( ii_master, jj_master );
219  }
220  }
221  }
222 
223  // Iterate across the long range energy functions and use the iterators generated
224  // by the LRnergy container object
225  // The logic here is exactly the same as for the non-lr energy calculation in terms of symmetry
227  lr_iter = scfxn.long_range_energies_begin(),
228  lr_end = scfxn.long_range_energies_end();
229  lr_iter != lr_end; ++lr_iter ) {
230  LREnergyContainerCOP lrec = pose.energies().long_range_container( (*lr_iter)->long_range_type() );
231  if ( !lrec || lrec->empty() ) continue; // only score non-emtpy energies.
232  // Potentially O(N^2) operation...
233 
234  for ( uint ii = 1; ii <= nmoltenres(); ++ ii ) {
235  uint const ii_resid = moltenres_2_resid( ii );
236 
238  rni = lrec->const_upper_neighbor_iterator_begin( ii_resid ),
239  rniend = lrec->const_upper_neighbor_iterator_end( ii_resid );
240  (*rni) != (*rniend); ++(*rni) ) {
241  Size jj_resid = rni->upper_neighbor_id();
242 
243  uint jj = resid_2_moltenres( jj_resid ); //pretend we're iterating over jj >= ii
244 // if ( jj == 0 ) continue; // Andrew, remove this magic number! (it's the signal that jj_resid is not "molten")
245  // if jj_resid is not repackable and jj_resid is not in a different subunit continue
246  if ( jj == 0 && symm_info->chi_follows( jj_resid ) == 0 ) continue;
247  // if jj_resid is in a different subunit we need to know its master
248  uint jj_resid_master = jj_resid;
249  if ( symm_info->chi_follows( jj_resid ) != 0 ) jj_resid_master = symm_info->chi_follows( jj_resid );
250  // find out the moltenres id for the master
251  uint jj_master = resid_2_moltenres( jj_resid_master );
252  // if the master is not repackable continue
253  if ( jj_master == 0 ) continue;
254  // if we the ii_resid and jj_resid_master have an edge this intersubunit
255  // interaction is already being calculated
256 // if ( packer_neighbor_graph->get_edge_exists(ii_resid,jj_resid_master ) && jj == 0 ) continue;
257 
258  uint ii_master = ii;
259  uint ii_resid_master = ii_resid;
260 
261  // the self interaction energy is already calculated in the one-body ter,
262  if ( ii_master == jj_master ) continue;
263  // swap the order of the nodes that form the edge if jj_resid_master < ii_resid.
264  // Edges are always stored as pairs (a, b) where a > b. This only happens if we
265  // are calculation interactions from the controling subunit to another subunit
266  bool swap( false );
267  if ( jj_resid_master < ii_resid ) {
268  swap = true;
269  uint temp_ii = ii_master;
270  uint temp_ii_resid = ii_resid_master;
271  ii_master = jj_master;
272  ii_resid_master = jj_resid_master;
273  jj_master = temp_ii;
274  jj_resid_master = temp_ii_resid;
275  }
276 
277  // make a pair energy table to store use jj_master and ii_master
278  // to size the array ( if we have have a intersubunit interaction)
279  FArray2D< core::PackerEnergy > pair_energy_table(
280  nrotamers_for_moltenres( jj_master ),
281  nrotamers_for_moltenres( ii_master ), 0.0 );
282 
283  RotamerSetOP ii_rotset = rotamer_set_for_moltenresidue( ii_master );
284  RotamerSetOP jj_rotset = rotamer_set_for_moltenresidue( jj_master );
285 
286  // we have a intersubunit interaction then calculate the interaction
287  // here instead of the intrasubunit interaction. If jj == 0 then we will calculate
288  // intrasubunit interaction. If we swapped the order we have to orient ii instead of jj
289  if ( symm_info->chi_follows( jj_resid ) != 0 && jj == 0 ) {
290  if ( swap ) {
291  RotamerSetOP rotated_ii_rotset(
292  orient_rotamer_set_to_symmetric_partner(pose,ii_resid_master,jj_resid) );
293  ii_rotset = rotated_ii_rotset;
294  scfxn.prepare_rotamers_for_packing( pose, *ii_rotset );
295  } else {
296  RotamerSetOP rotated_jj_rotset(
297  orient_rotamer_set_to_symmetric_partner(pose,jj_resid_master,jj_resid) );
298  jj_rotset = rotated_jj_rotset;
299  scfxn.prepare_rotamers_for_packing( pose, *jj_rotset );
300  }
301  }
302  (*lr_iter)->evaluate_rotamer_pair_energies(
303  *ii_rotset, *jj_rotset, pose, scfxn, scfxn.weights(), pair_energy_table );
304 
305  pair_energy_table *= symm_info->score_multiply(ii_resid,jj_resid);
306 
307  if ( ! pig->get_edge_exists( ii_master, jj_master ) ) { pig->add_edge( ii_master, jj_master ); }
308  pig->add_to_two_body_energies_for_edge( ii_master, jj_master, pair_energy_table );
309  if ( finalize_edges && final_visit_to_edge( pose, packer_neighbor_graph, ii_resid, jj_resid ) )
310  pig->declare_edge_energies_final( ii_master, jj_master );
311  }
312  }
313  }
314 }
315 
316 /// @details Add edges between all adjacent nodes in the
317 /// interaction graph, and note which of the subunit pairs are interacting.
318 void
319 SymmetricRotamerSets::prepare_symm_otf_interaction_graph(
320  pose::Pose const & pose,
321  scoring::ScoreFunction const & sfxn,
322  graph::GraphCOP packer_neighbor_graph,
324 )
325 {
326  // find SymmInfo
327  SymmetricConformation const & SymmConf (
328  dynamic_cast<SymmetricConformation const &> ( pose.conformation()) );
329  SymmetryInfoCOP symm_info( SymmConf.Symmetry_Info() );
330 
331 
332  /// Mark all-amino-acid nodes as worthy of distinguishing between bb & sc
333  for ( Size ii = 1; ii <= nmoltenres(); ++ii ) {
334  RotamerSetCOP ii_rotset = rotamer_set_for_moltenresidue( ii );
335  bool all_canonical_aas( true );
336  for ( Size jj = 1, jje = ii_rotset->get_n_residue_types(); jj <= jje; ++jj ) {
337  conformation::ResidueCOP jj_rotamer = ii_rotset->rotamer( ii_rotset->get_residue_type_begin( jj ) );
338  if ( jj_rotamer->aa() > chemical::num_canonical_aas ) {
339  all_canonical_aas = false;
340  }
341  }
342  if ( all_canonical_aas ) {
343  ig->distinguish_backbone_and_sidechain_for_node( ii, true );
344  }
345  }
346 
347  for ( Size ii = 1; ii <= nmoltenres(); ++ii ) {
348  Size ii_resid = moltenres_2_resid( ii );
350  uli = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_begin(),
351  ulie = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_end(); uli != ulie; ++uli ) {
352  Size jj_resid = (*uli)->get_second_node_ind();
353  Size jj = resid_2_moltenres( jj_resid );
354 
355  // skip jj if this is a background residue. This is true
356  // if jj == 0 (i.e. not a moltenresidue) and if jj_resid
357  // is in the asymmetric unit (i.e. chi_follows(jj_resid) == 0 )
358  // If jj is not in the asymmetric unit, and its master is
359  // also not a molten residue
360  if ( jj == 0 && symm_info->chi_follows( jj_resid ) == 0 ) { /*std::cout << "jj==0 && symm_info->chi_follows( jj_resid ) == 0" << std::endl;*/ continue; }
361  Size jj_resid_master = symm_info->chi_follows( jj_resid ) == 0 ? jj_resid : symm_info->chi_follows( jj_resid );
362  Size jj_master = jj == 0 ? resid_2_moltenres( jj_resid_master ) : jj;
363  // ok, jj_resid's master is also not a molten residue
364  if ( jj_master == 0 ) { /*std::cout << "jj_master == 0" << std::endl;*/ continue; }
365  // or if jj_master == ii, then we're looking at a residue interacting with its symmetric clone, which
366  // in the context of packing, is qualified as a one-body interaction,
367  if ( jj_master == ii ) { /*std::cout << "jj_master == ii" << std::endl;*/ continue; }
368 
369  // OK: ii_resid interacts with jj_resid and their interaction
370  // needs to be counted as part of the interaction graph.
371  Size ii_master( ii ), ii_resid_master( ii_resid );
372  bool swap( false );
373  if ( jj_resid_master < ii_resid_master ) {
374  Size temp;
375  temp = ii_master; ii_master = jj_master; jj_master = temp;
376  temp = ii_resid_master; ii_resid_master =jj_resid_master; jj_resid_master = temp;
377  swap = true;
378  }
379  //std::cout << "OK we have a winner: " << ii_master << " " << jj_master << " from " << ii_resid << " " << jj_resid << std::endl;
380 
381  // next, check if the edge already exists, and, if it does,
382  // then continue
383  if ( ! ig->get_edge_exists( ii_master, jj_master ) ) {
384  ig->add_edge( ii_master, jj_master );
385  ig->note_short_range_interactions_exist_for_edge( ii_master, jj_master );
386  }
387  // now let's inform the graph that, for this ii_resid / jj_resid pair that
388  // an interaction exists.
389 
390  assert( ii_resid <= symm_info->num_independent_residues() || jj_resid <= symm_info->num_independent_residues() );
391 
392  ig->set_residues_adjacent_for_subunit_pair_for_edge( ii_master, jj_master,
393  swap ? 2 : 1,
394  symm_info->subunit_index( (*uli)->get_second_node_ind() ));
395  }
396  }
397 
398  // Iterate across the long range energy functions and use the iterators generated
399  // by the LRnergy container object
401  lr_iter = sfxn.long_range_energies_begin(),
402  lr_end = sfxn.long_range_energies_end();
403  lr_iter != lr_end; ++lr_iter ) {
404  scoring::LREnergyContainerCOP lrec = pose.energies().long_range_container( (*lr_iter)->long_range_type() );
405  if ( !lrec || lrec->empty() ) continue; // only score non-empty energies.
406  // Potentially O(N^2) operation...
407 
408  for ( uint ii = 1; ii <= nmoltenres(); ++ ii ) {
409  Size const ii_resid = moltenres_2_resid( ii );
410 
412  rni = lrec->const_upper_neighbor_iterator_begin( ii_resid ),
413  rniend = lrec->const_upper_neighbor_iterator_end( ii_resid );
414  (*rni) != (*rniend); ++(*rni) ) {
415 
416  Size jj_resid = rni->upper_neighbor_id();
417  Size jj = resid_2_moltenres( jj_resid );
418 
419  // skip jj if this is a background residue. This is true
420  // if jj == 0 (i.e. not a moltenresidue) and if jj_resid
421  // is in the asymmetric unit (i.e. chi_follows(jj_resid) == 0 )
422  // or if jj is not in the asymmetric unit, and its master is
423  // also not a molten residue
424  if ( jj == 0 && symm_info->chi_follows( jj_resid ) == 0 ) { /*std::cout << "jj==0 && symm_info->chi_follows( jj_resid ) == 0" << std::endl;*/ continue; }
425  Size jj_resid_master = symm_info->chi_follows( jj_resid ) == 0 ? jj_resid : symm_info->chi_follows( jj_resid );
426  Size jj_master = jj == 0 ? resid_2_moltenres( jj_resid_master ) : jj;
427  // ok, jj_resid's master is also not a molten residue
428  if ( jj_master == 0 ) { /*std::cout << "jj_master == 0" << std::endl;*/ continue; }
429  // or if jj_master == ii, then we're looking at a residue interacting with its symmetric clone, which
430  // in the context of packing, is qualified as a one-body interaction,
431  if ( jj_master == ii ) { /*std::cout << "jj_master == ii" << std::endl;*/ continue; }
432 
433  // OK: ii_resid interacts with jj_resid and their interaction
434  // needs to be counted as part of the interaction graph.
435  Size ii_master( ii ), ii_resid_master( ii_resid );
436  if ( jj_resid_master < ii_resid_master ) {
437  std::swap( ii_master, jj_master );
438  }
439  //std::cout << "OK we have a winner: " << ii_master << " " << jj_master << " from " << ii_resid << " " << jj_resid << std::endl;
440 
441  /// figure out how to notify the lrec that it should only consider these two residues neighbors
442  /// for the sake of packing...
443  if ( ! ig->get_edge_exists( ii_master, jj_master ) ) {
444  ig->add_edge( ii_master, jj_master );
445  }
446  ig->note_long_range_interactions_exist_for_edge( ii_master, jj_master );
447  }
448  }
449  }
450 
451  compute_proline_correction_energies_for_otf_graph( pose, symm_info, sfxn, packer_neighbor_graph, ig );
452 }
453 
454 void
455 SymmetricRotamerSets::compute_proline_correction_energies_for_otf_graph(
456  pose::Pose const & pose,
458  scoring::ScoreFunction const & scfxn,
459  graph::GraphCOP packer_neighbor_graph,
461 )
462 {
463  using namespace conformation;
464  using namespace conformation::symmetry;
465  using namespace interaction_graph;
466 
467  Size const nsubunits = symm_info->subunits();
468 
469  utility::vector1< Size > example_gly_rotamer_inds( nmoltenres(), 0 );
470  utility::vector1< Size > example_pro_rotamer_inds( nmoltenres(), 0 );
471  utility::vector1< utility::vector1< ResidueOP > > example_gly_rotamers( nsubunits );
472  utility::vector1< utility::vector1< ResidueOP > > example_pro_rotamers( nsubunits );
473  for ( Size ii = 1; ii <= nsubunits; ++ii ) {
474  example_gly_rotamers[ ii ].resize( nmoltenres() );
475  example_pro_rotamers[ ii ].resize( nmoltenres() );
476  }
477 
478  /// 0. Find example proline and glycine residues where possible.
479  for ( Size ii = 1; ii <= nmoltenres(); ++ii ) {
480  RotamerSetCOP ii_rotset = rotamer_set_for_moltenresidue( ii );
481 
482  Size potential_gly_replacement( 0 );
483  for ( Size jj = 1, jje = ii_rotset->get_n_residue_types(); jj <= jje; ++jj ) {
484  ResidueCOP jj_rotamer = ii_rotset->rotamer( ii_rotset->get_residue_type_begin( jj ) );
485  if ( jj_rotamer->aa() == chemical::aa_gly ) {
486  example_gly_rotamer_inds[ ii ] = ii_rotset->get_residue_type_begin( jj );
487  } else if ( jj_rotamer->aa() == chemical::aa_pro ) {
488  example_pro_rotamer_inds[ ii ] = ii_rotset->get_residue_type_begin( jj );
489  } else if ( jj_rotamer->is_protein() ) {
490  potential_gly_replacement = ii_rotset->get_residue_type_begin( jj );
491  }
492  }
493  /// failed to find a glycine backbone for this residue, any other
494  /// backbone will do, so long as its a protein backbone.
495  if ( example_gly_rotamer_inds[ ii ] == 0 ) {
496  example_gly_rotamer_inds[ ii ] = potential_gly_replacement;
497  }
498  /// clone a representative rotamer from each of the subunits from the symotofig
499  for ( Size jj = 1; jj <= nsubunits; ++jj ) {
500  if ( example_pro_rotamer_inds[ ii ] != 0 ) {
501  example_pro_rotamers[ jj ][ ii ] = otfig->get_on_the_fly_node( ii )->get_rotamer( example_pro_rotamer_inds[ ii ], jj ).clone();
502  }
503  if ( example_gly_rotamer_inds[ ii ] != 0 ) {
504  example_gly_rotamers[ jj ][ ii ] = otfig->get_on_the_fly_node( ii )->get_rotamer( example_gly_rotamer_inds[ ii ], jj ).clone();
505  }
506  }
507  }
508 
509  /// 1. Iterate across all edges in the graph
510  for ( Size ii = 1; ii <= nmoltenres(); ++ ii ) {
511  Size const ii_resid = moltenres_2_resid( ii );
512  if ( ! otfig->distinguish_backbone_and_sidechain_for_node( ii ) ) continue;
514  uli = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_begin(),
515  ulie = packer_neighbor_graph->get_node( ii_resid )->const_upper_edge_list_end();
516  uli != ulie; ++uli ) {
517  Size jj_resid = (*uli)->get_second_node_ind();
518  Size jj = resid_2_moltenres( jj_resid ); //pretend we're iterating over jj >= ii
519  if ( jj == 0 && symm_info->chi_follows( jj_resid ) == 0 ) continue;
520  Size jj_resid_master = symm_info->chi_follows( jj_resid ) == 0 ? jj_resid : symm_info->chi_follows( jj_resid );
521  Size jj_master = jj == 0 ? resid_2_moltenres( jj_resid_master ) : jj;
522  if ( jj_master == 0 ) continue;
523  if ( jj_master == ii ) continue;
524  if ( ! otfig->distinguish_backbone_and_sidechain_for_node( jj_master ) ) continue;
525 
526  Size ii_master( ii ), ii_resid_master( ii_resid );
527  Size ii_subunit = 1; Size jj_subunit = (jj_resid-1) / symm_info->num_independent_residues() + 1;
528  //bool swap( false );
529  if ( jj_resid_master < ii_resid_master ) {
530  Size temp;
531  temp = ii_master; ii_master = jj_master; jj_master = temp;
532  temp = ii_resid_master; ii_resid_master =jj_resid_master; jj_resid_master = temp;
533  temp = ii_subunit; ii_subunit = jj_subunit; jj_subunit = temp;
534  //swap = true; // set but never used ~Labonte
535  }
536 
537  /// 2. Calculate proline-correction terms between neighbors
538 
539  RotamerSetCOP ii_rotset = rotamer_set_for_moltenresidue( ii_master );
540  RotamerSetCOP jj_rotset = rotamer_set_for_moltenresidue( jj_master );
541 
542  Size const iijj_scale = symm_info->score_multiply( ii_resid, jj_resid );
543  if ( iijj_scale == 0 ) continue;
544 
545  //std::cout << "SymmetricRotamerSets::compute_proline_corrections " << (*uli)->get_first_node_ind() << " " << (*uli)->get_second_node_ind() << " " << ii_master << " " << jj_master << " " << ii_subunit << " " << jj_subunit << std::endl;
546 
547  SymmOnTheFlyNode * iinode = otfig->get_on_the_fly_node( ii_master );
548  SymmOnTheFlyNode * jjnode = otfig->get_on_the_fly_node( jj_master );
549 
550  for ( Size kk = 1; kk <= ii_rotset->num_rotamers(); ++kk ) {
551  core::PackerEnergy bb_bbnonproE( iijj_scale ), bb_bbproE( iijj_scale );
552  core::PackerEnergy sc_npbb_energy( iijj_scale ), sc_probb_energy( iijj_scale );
553  //calc sc_npbb_energy;
554  if ( example_gly_rotamer_inds[ jj_master ] != 0 ) {
555  bb_bbnonproE *= get_bb_bbE( pose, scfxn, iinode->get_rotamer( kk, ii_subunit ), *example_gly_rotamers[ jj_subunit ][ jj_master ] );
556  sc_npbb_energy *= get_sc_bbE( pose, scfxn, iinode->get_rotamer( kk, ii_subunit ), *example_gly_rotamers[ jj_subunit ][ jj_master ] );
557  } else {
558  bb_bbnonproE = sc_npbb_energy = 0;
559  }
560  //calc sc_probb_energy
561  if ( example_pro_rotamer_inds[ jj_master ] != 0 ) {
562  bb_bbproE *= get_bb_bbE( pose, scfxn, iinode->get_rotamer( kk, ii_subunit ), *example_pro_rotamers[ jj_subunit ][ jj_master ] );
563  sc_probb_energy *= get_sc_bbE( pose, scfxn, iinode->get_rotamer( kk, ii_subunit ), *example_pro_rotamers[ jj_subunit ][ jj_master ] );
564  } else {
565  bb_bbproE = sc_probb_energy = 0;
566  }
567  //std::cout << " procorr: " << ii_master << " " << jj_master << " 1 kk: " << kk << " " << bb_bbnonproE << " " << sc_npbb_energy << " " << bb_bbproE << " " << sc_probb_energy << " add1b: " << sc_npbb_energy + 0.5 * bb_bbnonproE << std::endl;
568  otfig->add_to_one_body_energy_for_node_state( ii_master, kk, sc_npbb_energy + 0.5 * bb_bbnonproE );
569  otfig->add_ProCorrection_values_for_edge( ii_master, jj_master, ii_master, kk,
570  bb_bbnonproE, bb_bbproE, sc_npbb_energy, sc_probb_energy );
571  }
572 
573  for ( Size kk = 1; kk <= jj_rotset->num_rotamers(); ++kk ) {
574  core::PackerEnergy bb_bbnonproE( iijj_scale ), bb_bbproE( iijj_scale );
575  core::PackerEnergy sc_npbb_energy( iijj_scale ), sc_probb_energy( iijj_scale );
576  //calc sc_npbb_energy;
577  if ( example_gly_rotamer_inds[ ii_master ] != 0 ) {
578  bb_bbnonproE *= get_bb_bbE( pose, scfxn, jjnode->get_rotamer( kk, jj_subunit ), *example_gly_rotamers[ ii_subunit ][ ii_master ] );
579  sc_npbb_energy *= get_sc_bbE( pose, scfxn, jjnode->get_rotamer( kk, jj_subunit ), *example_gly_rotamers[ ii_subunit ][ ii_master ] );
580  } else {
581  bb_bbnonproE = sc_npbb_energy = 0;
582  }
583  //calc sc_probb_energy
584  if ( example_pro_rotamer_inds[ ii_master ] != 0 ) {
585  bb_bbproE *= get_bb_bbE( pose, scfxn, jjnode->get_rotamer( kk, jj_subunit ), *example_pro_rotamers[ ii_subunit ][ ii_master ] );
586  sc_probb_energy *= get_sc_bbE( pose, scfxn, jjnode->get_rotamer( kk, jj_subunit ), *example_pro_rotamers[ ii_subunit ][ ii_master ] );
587  } else {
588  bb_bbproE = sc_probb_energy = 0;
589  }
590  //std::cout << " procorr: " << ii_master << " " << jj_master << " 2 kk: " << kk << " " << bb_bbnonproE << " " << sc_npbb_energy << " " << bb_bbproE << " " << sc_probb_energy << " add1b: " << sc_npbb_energy + 0.5 * bb_bbnonproE << std::endl;
591  otfig->add_to_one_body_energy_for_node_state( jj_master, kk, sc_npbb_energy + 0.5 * bb_bbnonproE );
592 
593  otfig->add_ProCorrection_values_for_edge( ii_master, jj_master, jj_master, kk,
594  bb_bbnonproE, bb_bbproE, sc_npbb_energy, sc_probb_energy );
595  }
596  }
597  }
598 
599 }
600 
601 // @details orients all rotamers in a rotamer_set to a different (symmetrical) position
603 SymmetricRotamerSets::orient_rotamer_set_to_symmetric_partner(
604  pose::Pose const & pose,
605  uint const & seqpos,
606  uint const & sympos
607 )
608 {
609 
610  RotamerSetCOP rotset_in = rotamer_set_for_residue( seqpos );
612  RotamerSetOP sym_rotamer_set = rsf.create_rotamer_set( pose.residue( seqpos ) );
613  sym_rotamer_set->set_resid(sympos);
614  for (Rotamers::const_iterator
615  rot = rotset_in->begin(),
616  rot_end = rotset_in->end();
617  rot != rot_end; ++rot) {
618  conformation::ResidueOP target_rsd( (*rot)->clone() /*pose.residue( seqpos )*/ );
619  target_rsd->orient_onto_residue( pose.residue( sympos ) );
620  sym_rotamer_set->add_rotamer( *target_rsd );
621  }
622  return sym_rotamer_set;
623 }
624 
625 // @details is this the final visit to an edge?
626 bool
627 SymmetricRotamerSets::final_visit_to_edge(
628  pose::Pose const & pose,
629  graph::GraphCOP packer_neighbor_graph,
630  uint ii_resid,
631  uint jj_resid
632  )
633 {
634  // find SymmInfo
635  SymmetricConformation const & SymmConf (
636  dynamic_cast<SymmetricConformation const &> ( pose.conformation()) );
637  SymmetryInfoCOP symm_info( SymmConf.Symmetry_Info() );
638 
639  // find the highest jj clone sequence number we could have
640  uint jj_highest(jj_resid);
641  for ( std::vector< Size>::const_iterator
642  clone = symm_info->chi_clones( jj_resid ).begin(),
643  clone_end = symm_info->chi_clones( jj_resid ).end();
644  clone != clone_end; ++clone ){
645  if ( *clone > jj_highest &&
646  packer_neighbor_graph->get_edge_exists(ii_resid, *clone) )
647  jj_highest = *clone;
648  }
649  // find the highest jj clone sequence number we could have
650  uint ii_highest(ii_resid);
651  for ( std::vector< Size>::const_iterator
652  clone = symm_info->chi_clones( ii_resid ).begin(),
653  clone_end = symm_info->chi_clones( ii_resid ).end();
654  clone != clone_end; ++clone ){
655  if ( *clone > ii_highest &&
656  packer_neighbor_graph->get_edge_exists(*clone, jj_resid) )
657  ii_highest = *clone;
658  }
659  if ( ii_resid == ii_highest && jj_resid == jj_highest ) return true;
660  else return false;
661 }
662 
663 } // namespace symmetry
664 } // namespace rotamer_set
665 } // namespace pack
666 } // namespace core
667