Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
NumberHBondsCalculator.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/pose/metrics/NumberHBondsCalculator.cc
11 /// @brief number of hbonds calculator class
12 /// @author Florian Richter
13 
14 // Unit headers
16 #include <core/pose/Pose.hh>
17 
18 
19 
20 // Utility headers
21 #include <basic/Tracer.hh>
22 #include <utility/exit.hh>
23 #include <utility/stream_util.hh>
24 #include <utility/string_util.hh>
25 #include <basic/MetricValue.hh>
26 
27 //#include <core/scoring/EnergyGraph.hh>
30 #include <core/scoring/Energies.hh>
37 
38 #include <cassert>
39 
40 #include <utility/vector1.hh>
41 
42 //Auto Headers
44 
45 
46 using namespace core;
47 using namespace core::pose;
48 using namespace core::pose::metrics;
49 
50 
51 
52 namespace protocols{
53 namespace toolbox {
54 namespace pose_metric_calculators {
55 
56 
57 void
58 NumberHBondsCalculator::lookup(
59  std::string const & key,
60  basic::MetricValueBase * valptr
61  ) const
62 {
63 
64  if ( key == "all_Hbonds" ) {
65  basic::check_cast( valptr, &all_Hbonds_, "all_Hbonds expects to return a Size" );
66  (static_cast<basic::MetricValue<Size> *>(valptr))->set( all_Hbonds_ );
67 
68  } else if ( key == "special_region_Hbonds" ) {
69  basic::check_cast( valptr, &special_region_Hbonds_, "special_region_Hbonds expects to return a Size" );
70  (static_cast<basic::MetricValue<Size> *>(valptr))->set( special_region_Hbonds_ );
71 
72  } else if ( key == "atom_Hbonds" ) {
73  basic::check_cast( valptr, &atom_Hbonds_, "atom_Hbonds expects to return a id::AtomID_Map< Size >" );
74  (static_cast<basic::MetricValue<id::AtomID_Map< Size > > *>(valptr))->set( atom_Hbonds_ );
75 
76  } else if ( key == "residue_Hbonds" ) {
77  basic::check_cast( valptr, &residue_Hbonds_, "residue_Hbonds expects to return a utility::vector1< Size >" );
78  (static_cast<basic::MetricValue<utility::vector1< Size > > *>(valptr))->set( residue_Hbonds_ );
79 
80  } else {
81  basic::Error() << "NumberHbondsCalculator cannot compute the requested metric " << key << std::endl;
82  utility_exit();
83  }
84 
85 } //lookup
86 
87 
88 
90 NumberHBondsCalculator::print( std::string const & key ) const
91 {
92 
93  if ( key == "all_Hbonds" ) {
94  return utility::to_string( all_Hbonds_ );
95  } else if ( key == "special_region_Hbonds" ) {
96  return utility::to_string( special_region_Hbonds_ );
97  } else if ( key == "atom_Hbonds" ) {
98  basic::Error() << "id::AtomID_Map< Size > has no output operator, for metric " << key << std::endl;
99  utility_exit();
100  } else if ( key == "residue_Hbonds" ) {
101  return utility::to_string( residue_Hbonds_ );
102  }
103 
104  basic::Error() << "NumberHbondsCalculator cannot compute metric " << key << std::endl;
105  utility_exit();
106  return "";
107 
108 } //print
109 
110 
111 
112 void
113 NumberHBondsCalculator::recompute( Pose const & this_pose )
114 {
115 
116  using namespace core::scoring;
117 
118  //first we have to figure out which of the hbonds to (re)calculate
119  utility::vector1< bool >res_to_recompute( this_pose.total_residue(), false );
120  hbonds::HBondSet hb_set( this_pose.total_residue() );
121 
122  //hbonds::HBondSet test_hb_set( this_pose.total_residue() );
123  //hbonds::fill_hbond_set( this_pose, false, test_hb_set, false);
124 
125  determine_res_to_recompute( this_pose, res_to_recompute );
126  runtime_assert( residue_Hbonds_.size() == res_to_recompute.size() );
127 
128  //set the hbonds vector for all recompute residues to 0
129  for( Size i = 1; i <= res_to_recompute.size(); ++i){
130 
131  if( res_to_recompute[ i ] ) residue_Hbonds_[ i ] = 0;
132  }
133 
134 
135  for( Size i = 1; i <= res_to_recompute.size(); ++i){
136 
137  compute_Hbonds_for_residue( this_pose, i, res_to_recompute, hb_set );
138 
139  } //loop over all residues
140 
141 
142  //some double checking
143  //std::cerr << "comp hbset has " << test_hb_set.nhbonds() << " hbonds, while other has " << hb_set.nhbonds() << std::endl;
144 
145 
146  //now we have to setup the AtomID Map
147  for( Size i = 1; i <= res_to_recompute.size(); ++i){
148 
149  if( !res_to_recompute[i] ) continue;
150 
151  conformation::Residue const & rsd = this_pose.residue( i );
152 
153  for( Size at = 1; at <= rsd.nheavyatoms(); ++at){
154 
155  core::id::AtomID atid( at, i );
156 
157  if( residue_Hbonds_[i] == 0 ){
158  atom_Hbonds_.set( atid, 0 );
159  continue;
160  }
161 
162  if( rsd.atom_type( at ).is_acceptor() && rsd.atom_type( at ).is_donor() ) {
163  Size hbonds_this_donor(0);
164  // count donated hbonds
165  for( Size hcount = rsd.type().attached_H_begin( at ); hcount<= rsd.type().attached_H_end( at ); hcount++ ){
166  hbonds_this_donor = hbonds_this_donor + hb_set.atom_hbonds( core::id::AtomID (hcount, i ) ).size();
167  }
168 
169  // adds accepted hbonds
170  hbonds_this_donor = hbonds_this_donor + hb_set.atom_hbonds( atid ).size();;
171  atom_Hbonds_.set( atid, hbonds_this_donor );
172 
173  }
174 
175  else if( rsd.atom_type( at ).is_acceptor() ){
176 
177  atom_Hbonds_.set( atid, hb_set.atom_hbonds( atid ).size() );
178 
179  }
180  else if( rsd.atom_type( at ).is_donor() ){
181  Size hbonds_this_donor(0);
182 
183  for( Size hcount = rsd.type().attached_H_begin( at ); hcount<= rsd.type().attached_H_end( at ); hcount++ ){
184 
185  hbonds_this_donor = hbonds_this_donor + hb_set.atom_hbonds( core::id::AtomID (hcount, i ) ).size();
186 
187  }
188 
189  atom_Hbonds_.set( atid, hbonds_this_donor );
190  }
191  else atom_Hbonds_.set( atid, 0 );
192  }
193  }
194 
195 
196  //finally, we compute the total number of h-bonds
197  all_Hbonds_ = 0;
198  for( utility::vector1< core::Size >::const_iterator resh_it = residue_Hbonds_.begin();
199  resh_it != residue_Hbonds_.end(); ++resh_it){
200  all_Hbonds_ = all_Hbonds_ + *resh_it;
201  }
202  all_Hbonds_ = all_Hbonds_ / 2; //remember not to overcount
203 
204 } //recompute
205 
206 
207 
208 /// @brief function to figure out which residues to recompute the hydrogen bonds for
209 /// @brief strategy: for each residue, we check whether the internally cached total energies
210 /// @brief correspond to the energies found in the pose for that residue. If they do,
211 /// @brief this means that the number of H-bonds hasn't changed.
212 void
213 NumberHBondsCalculator::determine_res_to_recompute(
214  core::pose::Pose const & pose,
215  utility::vector1< bool > & res_to_recompute)
216 {
217  using namespace core::scoring;
218 
219  //check1: does the internal reference array have the same size as the pose has residues?
220  //if not, means we have to recompute everything
221  if( ref_residue_total_energies_.size() != pose.total_residue() ){
222  atom_Hbonds_.clear();
223  atom_Hbonds_.resize( pose.total_residue() );
224  residue_Hbonds_.resize( pose.total_residue() );
225  ref_residue_total_energies_.resize( pose.total_residue() );
226  for( Size i = 1; i <= pose.total_residue(); ++i){
227  res_to_recompute[ i ] = true;
228  ref_residue_total_energies_[i] = pose.energies().residue_total_energies(i)[ total_score ];
229  }
230 
231  return;
232  }
233 
234 
235  //check2: for each residue, check whether calculator cached residue energies have changed
236  for( Size i = 1; i <= pose.total_residue(); ++i){
237 
238  if( ref_residue_total_energies_[i] != pose.energies().residue_total_energies(i)[ total_score ] ){
239 
240  ref_residue_total_energies_[i] = pose.energies().residue_total_energies(i)[ total_score ];
241  res_to_recompute[ i ] = true;
242  //std::cerr << "res " << i << " needs recomputing." << std::endl;
243  }
244 
245  if( special_region_.find( i ) != special_region_.end() ) res_to_recompute[ i ] = true;
246  }
247 
248 } //determine_res_to_recompute
249 
250 
251 void
252 NumberHBondsCalculator::compute_Hbonds_for_residue(
253  core::pose::Pose const & pose,
254  core::Size i,
255  utility::vector1< bool > const & res_to_recompute,
257 {
258  using namespace core::scoring;
259 
260 
261  conformation::Residue const & rsd1( pose.residue( i ) );
262  int const nb1 = pose.energies().tenA_neighbor_graph().get_node( i )->num_neighbors_counting_self();
263 
264  //go over the neighbours of this residue
265  //in the pose energy graph and see whether there
266  //is an Hbond energy between them
268  egraph_it != pose.energies().energy_graph().get_node( i )->const_upper_edge_list_end(); ++egraph_it) {
269 
270  Size other_node = (*egraph_it)->get_other_ind( i );
271 
272  if( (!res_to_recompute[i]) && !(res_to_recompute[other_node] ) ) continue;
273 
274  //EnergyEdge const * Eedge = static_cast< EnergyEdge const * > (*egraph_it);
275 
276  //if( sum_Hbond_terms( Eedge->energy_map() ) <= 100 ){ //hardcoded cutoff for now
277 
278  //ok, we gotta compute the number of Hbonds between these two residues
279  Size prev_no_hb = hb_set.nhbonds();
280 
281  conformation::Residue const & rsd2( pose.residue( other_node ) );
282 
283  int const nb2 = pose.energies().tenA_neighbor_graph().get_node( other_node )->num_neighbors_counting_self();
284 
285  // rsd1 as donor, rsd2 as acceptor
286  hbonds::identify_hbonds_1way( *hb_database, rsd1, rsd2, nb1, nb2, false /*evaluate derivative*/,
287  false, false, false, false, hb_set);
288  //rsd2 as donor, rsd1 as acceptor
289  hbonds::identify_hbonds_1way( *hb_database, rsd2, rsd1, nb2, nb1, false /*evaluate derivative*/,
290  false, false, false, false, hb_set);
291 
292 
293  Size num_hb_these_two_res = hb_set.nhbonds() - prev_no_hb;
294 
295  if( res_to_recompute[i] ) residue_Hbonds_[ i ] += num_hb_these_two_res;
296  if( res_to_recompute[ other_node ] ) residue_Hbonds_[ other_node ] += num_hb_these_two_res;
297 
298  if( special_region_.find( i ) != special_region_.end() ) special_region_Hbonds_ += num_hb_these_two_res;
299  else if( special_region_.find( other_node ) != special_region_.end() ) special_region_Hbonds_ += num_hb_these_two_res;
300 
301  //std::cerr << "residues " << i << " and " << other_node << " make " << num_hb_this_two_res << " hbonds.\n";
302 
303 
304  //} //if hbond energy between these two residues
305 
306  }//iterator over all neighbors for this residue
307 
308 
309 } //compute_Hbonds_for_residue
310 
311 
313 NumberHBondsCalculator::sum_Hbond_terms(
314  core::scoring::EnergyMap const & emap
315 )
316 {
317  using namespace core::scoring;
318 
319  return emap[ hbond_sr_bb ] + emap[hbond_lr_bb] + emap[ hbond_bb_sc ] + emap[hbond_sc];
320 
321 }
322 
323 } //namespace pose_metric_calculators
324 } //namespace toolbox
325 } //namespace protocols