Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RotamerAssigningAnnealer.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/annealer/RotamerAssigningAnnealer.cc
11 /// @brief Annealer class that assigns rotamers implementation
12 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
13 
14 // Unit Headers
16 
17 // Package headers
19 
20 /// ObjexxFCL headers
21 #include <ObjexxFCL/Fmath.hh>
22 
23 /// Numeric headers
24 #include <numeric/random/random.hh>
25 #include <numeric/random/random_permutation.hh>
26 
27 /// Utility headers
28 #include <utility/exit.hh>
29 
30 /// C++ headers
31 #include <iostream>
32 
33 #include <utility/vector0.hh>
34 #include <utility/vector1.hh>
35 #include <ObjexxFCL/FArray1.hh>
36 
37 
38 using namespace ObjexxFCL;
39 static numeric::random::RandomGenerator RG(62456); // <- Magic number, do not change it!!!
40 
41 namespace core {
42 namespace pack {
43 namespace annealer {
44 
45 RotamerAssigningAnnealer::RotamerAssigningAnnealer(
46  int num_rots_to_pack_in,
47  FArray1D_int & bestrotamer_at_seqpos,
48  core::PackerEnergy & bestenergy,
49  bool start_with_current,
50  FixbbRotamerSetsCOP rotamer_sets,
51  FArray1_int & current_rot_index,
52  bool calc_rot_freq,
53  FArray1D< core::PackerEnergy > & rot_freq
54 ) :
55  SimAnnealerBase(
56  num_rots_to_pack_in,
57  bestrotamer_at_seqpos,
58  bestenergy,
59  start_with_current,
60  current_rot_index,
61  calc_rot_freq,
62  rot_freq
63  ),
64  rotamer_sets_( rotamer_sets ),
65  rot_to_pack_( num_rots_to_pack_in ),
66  current_to_pick_( 1 ),
67  n_assigned_at_start_( 0 ),
68  assign_state_to_all_nodes_immediately_( false )
69 {
70  for (unsigned int ii(1); ii <= rot_to_pack_.size(); ++ii) {
71  rot_to_pack_[ ii-1 ] = ii;
72  }
73  setup_rots_for_node( rotamer_sets );
74 }
75 
76 
78  utility::vector0< int > & rot_to_pack,
79  int num_rots_to_pack_in,
80  FArray1D_int & bestrotamer_at_seqpos,
81  core::PackerEnergy & bestenergy,
82  bool start_with_current,
83  FixbbRotamerSetsCOP rotamer_sets,
84  FArray1_int & current_rot_index,
85  bool calc_rot_freq,
86  FArray1D< core::PackerEnergy > & rot_freq
87 ) :
88  SimAnnealerBase(
89  num_rots_to_pack_in,
90  bestrotamer_at_seqpos,
91  bestenergy,
92  start_with_current,
93  current_rot_index,
94  calc_rot_freq,
95  rot_freq
96  ),
97  rotamer_sets_( rotamer_sets ),
98  current_to_pick_( 1 ),
99  n_assigned_at_start_( 0 ),
100  assign_state_to_all_nodes_immediately_( false )
101 {
102  //ja no need for overloading: just resort to generic behavior if rot_to_pack is empty. Should just have one constructor with an empty default argument for rot_to_pack
103  if ( !rot_to_pack.empty() ) rot_to_pack_ = rot_to_pack;
104  else {
105  // rot_to_pack obtained was empty, use all rotamers
106  num_rots_to_pack( rotamer_sets->nrotamers() ); // important
107  rot_to_pack_.reserve( num_rots_to_pack() );
108  for ( Size rot = 1; rot <= num_rots_to_pack(); ++rot ) {
109  rot_to_pack_.push_back( rot );
110  }
111  }
112  setup_rots_for_node( rotamer_sets );
113 }
114 
115 /// @details if you want to make a single rotamer substitution for a single node
116 /// then you'll want to grab a random rotamer for that node -- this function creates
117 /// a mapping from moltenres id to the set of accessible rotamers for that moltenres.
118 /// It also makes sure that the user has provided a valid set of rotamers: each molten
119 /// residue must have at least one pickable rotamer, or the final rotamer assignment
120 /// will have some molten residues in an unassigned state. Bad user input is most common
121 /// when the annealer is constructed using the rot_to_pack vector.
122 void
124  FixbbRotamerSetsCOP rotamer_sets
125 )
126 {
127  int const nmoltres = rotamer_sets->nmoltenres();
128  utility::vector1< int > npickable_rots_for_node( nmoltres, 0 );
129  rots_for_nodes_.resize( nmoltres );
130  for ( Size ii = 0; ii < rot_to_pack_.size(); ++ii ) {
131  ++npickable_rots_for_node[ rotamer_sets->moltenres_for_rotamer( rot_to_pack_[ ii ] ) ];
132  }
133  for ( int ii = 1; ii <= nmoltres; ++ii ) {
134  /// Error detection -- make sure each molten residue has at least one accessible rotamer
135  /// before SA begins. No point in waiting until after packing has ended to realize that
136  /// the final state assignment has unassigned states.
137  if ( npickable_rots_for_node[ ii ] == 0 ) {
138  std::cerr << "ERROR: No pickable rotamers for molten residue " << ii << " ( seqpos= " <<
139  rotamer_sets->moltenres_2_resid( ii ) << " ) found in rots_to_pack_." << std::endl;
140  std::cerr << "ERROR: Each molten residue must have at least one pickable rotamer." << std::endl;
141  std::cerr << "Provided rotamers: (rotid, moltenresid, moltenres_rotid ) " << std::endl;
142  for ( Size jj = 0; jj < rot_to_pack_.size(); ++jj ) {
143  std::cerr << "( " << jj <<", "
144  << rotamer_sets->moltenres_for_rotamer( rot_to_pack_[ ii ] ) << ", "
145  << rotamer_sets->rotid_on_moltenresidue( rot_to_pack_[ ii ] ) << ") ";
146  if ( jj % 4 == 3 ) std::cerr << "\n";
147  }
148  std::cerr << "\n Exiting." << std::endl;
149  utility_exit();
150  }
151  rots_for_nodes_.reserve( npickable_rots_for_node[ ii ] );
152  }
153  for ( Size ii = 0; ii < rot_to_pack_.size(); ++ii ) {
154  rots_for_nodes_[ rotamer_sets->moltenres_for_rotamer( rot_to_pack_[ ii ] ) ].
155  push_back( rot_to_pack_[ ii ] );
156  }
157 }
158 
160 {}
161 
162 /// @brief pick a rotamer from a list
163 ///
164 /// @details if no rotamer is available, return a nonsense number, like -1
166 {
167  bool start_with_current = get_start_with_current();
168  int ranrotamer = -1;
169  int num = 0;
173  }
174 
175  //bk if quench cycle, pass through all rotamers before
176  //bk repeating a rotamer
177  if ( quench() ){
178  num = mod( cycle - 1, (int) num_rots_to_pack());
179  if (num == 0){
180  numeric::random::random_permutation( rot_to_pack_, RG );
181  }
182  ranrotamer = rot_to_pack_.at(num);
183  //bk if start of run and start_with_current is true then first nres
184  //bk iterations will be used to place the current rotamers
185  }else if (start_with_current && (unsigned int) current_to_pick_ <= current_rot_index().size() ){
186 
187  if ( current_to_pick_ == 1 ){
188  std::cout << "RotamerAssigningAnnealer: recovering current rotamers for start." << std::endl;
189  }
190  if (current_rot_index()(current_to_pick_) != -1 ){
191  ranrotamer = current_rot_index()(current_to_pick_);
192  }else{
193  std::cout << "RotamerAssigningAnnealer: unable to recover current rotamer for moltenres: " << current_to_pick_ << std::endl;
194  ranrotamer = -1;
195  }
197  }else{
198  ranrotamer = rot_to_pack_.at(static_cast<int>( num_rots_to_pack() * RG.uniform() ));
199  }
200  //std::cerr << "ranrotamer: " << ranrotamer << " total: " << current_rot_index_.size() << std::endl;
201  return ranrotamer;
202 }
203 
205 {
206  return rots_for_nodes_[node][ static_cast<int> ( rots_for_nodes_[ node ].size() * RG.uniform() + 1 ) ];
207 }
208 
210 {
212 }
213 
216 {
217  return rot_to_pack_;
218 }
219 
222 
223 
224 } //end namespace annealer
225 } //end namespace pack
226 } //end namespace core