Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
NeighborhoodByDistanceCalculator.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 /src/protocols/toolbox/PoseMetricCalculators/NeighborhoodByDistanceCalculator.cc
11 /// @brief NeighborhoodByDistanceCalculator can determine all the neighbors of group of residues within a certain distance.
12 /// @author Steven Lewis
13 
14 
15 //Unit headers
17 
18 #include <core/pose/Pose.hh>
19 
20 #include <basic/MetricValue.hh>
21 
24 #include <core/graph/Graph.hh>
27 
28 //Utility headers
29 #include <basic/options/option.hh>
30 
31 //#include <core/types.hh>
32 #include <basic/Tracer.hh>
33 #include <utility/exit.hh>
34 #include <utility/string_util.hh>
35 
36 // option key includes
37 #include <basic/options/keys/packing.OptionKeys.gen.hh>
38 #include <basic/options/keys/pose_metrics.OptionKeys.gen.hh>
39 
40 static basic::Tracer TR("protocols.toolbox.PoseMetricCalculators.NeighborhoodByDistanceCalculator");
41 using basic::Error;
42 using basic::Warning;
43 
44 namespace protocols{
45 namespace toolbox {
46 namespace pose_metric_calculators {
47 
48 ///@details
50  : parent(), central_residues_(central_residues), dist_cutoff_ ( basic::options::option[basic::options::OptionKeys::pose_metrics::neighbor_by_distance_cutoff] ), num_neighbors_(0)
51 {
52 
53 }
54 
55 ///@details
56 NeighborhoodByDistanceCalculator::NeighborhoodByDistanceCalculator( std::set< core::Size > central_residues, core::Real dist_cutoff )
57  : parent(), central_residues_(central_residues), dist_cutoff_(dist_cutoff), num_neighbors_(0)
58 {
59 }
60 
61 NeighborhoodByDistanceCalculator::NeighborhoodByDistanceCalculator( NeighborhoodByDistanceCalculator const & calculator ) : parent(), central_residues_(calculator.central_residues_), dist_cutoff_(calculator.dist_cutoff_)
62 {}
63 
65 { return new NeighborhoodByDistanceCalculator(*this); }
66 
67 void
69  std::string const & key,
70  basic::MetricValueBase * valptr
71 ) const
72 {
73  //emacs is having a hissy fit about the tab whitespace in this function (choking on the (<<< >>*>())->() combo), so don't freak out if there are spaces instead of tabs and/or it displays poorly...
74 
75  if ( key == "central_residues" ) {
76  basic::check_cast( valptr, &central_residues_, "central_residues expects to return a std::set< core::Size >" );
77  (static_cast<basic::MetricValue< std::set< core::Size > >* > (valptr))->set( central_residues_ );
78 
79  } else if ( key == "dist_cutoff" ) {
80  basic::check_cast( valptr, &dist_cutoff_, "dist_cutoff expects to return a core::Real" );
81  (static_cast<basic::MetricValue<core::Real> *>(valptr))->set( dist_cutoff_ );
82 
83  } else if ( key == "num_neighbors" ) {
84  basic::check_cast( valptr, &num_neighbors_, "num_neighbors expects to return a core::Size" );
85  (static_cast<basic::MetricValue<core::Size> *>(valptr))->set( num_neighbors_ );
86  } else if ( key == "num_neighbors_map" ) {
87  basic::check_cast( valptr, &num_neighbors_map_, "num_neighbors_map expects to return a std::map<Size, Size>");
88  (static_cast<basic::MetricValue< std::map< core::Size, core::Size > > *>(valptr))->set(num_neighbors_map_);
89  } else if ( key == "neighbors" ) {
90  basic::check_cast( valptr, &neighbors_, "neighbors expects to return a std::set< core::Size >" );
91  (static_cast<basic::MetricValue< std::set< core::Size > > *>(valptr))->set( neighbors_ );
92 
93  } else {
94  basic::Error() << "NeighborhoodByDistanceCalculator cannot compute metric " << key << std::endl;
95  utility_exit();
96  }
97 
98 } //lookup
99 
102 {
103  using namespace basic::options;
104  if ( key == "central_residues" ) {
105  std::string const spacer( option[ OptionKeys::packing::print_pymol_selection].value() ? "+" : " ");
106  std::string res_string("");
107  for( std::set< core::Size >::const_iterator it(central_residues_.begin()), end(central_residues_.end()); it != end; ++it)
108  res_string += utility::to_string(*it) + spacer;
109  return res_string;
110 
111  } else if ( key == "dist_cutoff" ) {
112  return utility::to_string( dist_cutoff_ );
113 
114  } else if ( key == "num_neighbors" ) {
115  return utility::to_string( num_neighbors_ );
116 
117  } else if ( key == "num_neighbors_map" ) {
118  std::string map_string("");
119  for(std::map<core::Size, core::Size>::const_iterator it(num_neighbors_map_.begin()), end(num_neighbors_map_.end()); it != end; ++it)
120  map_string += utility::to_string(it->first) + ":" + utility::to_string(it->second) + " ";
121  return map_string;
122 
123  } else if ( key == "neighbors" ) {
124  using namespace basic::options; //this lets you get + or (space) as spacer
125  std::string const spacer( option[ OptionKeys::packing::print_pymol_selection].value() ? "+" : " ");
126  std::string nbrs_string("");
127  for( std::set< core::Size >::const_iterator it(neighbors_.begin()), end(neighbors_.end()); it != end; ++it)
128  nbrs_string += utility::to_string(*it) + spacer;
129  return nbrs_string;
130 
131  }//else
132  basic::Error() << "NeighborhoodByDistanceCalculator cannot compute metric " << key << std::endl;
133  utility_exit();
134  return "";
135 } //print
136 
137 void
139 {
140 
141  //clear old data
142  neighbors_.clear();
143  num_neighbors_map_.clear();
144  num_neighbors_ = 0;
145 
146  core::Size const nres(pose.total_residue());
147 
148  //this is the expensive part!
151  core::conformation::find_neighbors<core::conformation::PointGraphVertexData,core::conformation::PointGraphEdgeData>( pg, dist_cutoff_ ); //create edges
152  runtime_assert(nres == pg->num_vertices());
153 
154  //PointGraph is the one-way graph, but this is inefficient for group v group calculations - we do not want to iterate over the entire graph each time. Instead we want to visit just the nodes in one group and see if its edges are in the second group, so we need a two-way graph to prevent reiterating the lower half every time.
155  core::graph::Graph neighborgraph(nres);
156  for ( core::Size r(1); r <= nres; ++r){
157  for ( core::conformation::PointGraph::UpperEdgeListConstIter edge_iter = pg->get_vertex(r).upper_edge_list_begin(),
158  edge_end_iter = pg->get_vertex(r).upper_edge_list_end(); edge_iter != edge_end_iter; ++edge_iter ) {
159  neighborgraph.add_edge(r, edge_iter->upper_vertex());
160  }
161  }
162  runtime_assert(nres == neighborgraph.num_nodes());
163  runtime_assert(pg->num_edges() == neighborgraph.num_edges());
164 
165  //iterating through the graph is somewhat less expensive.
166  //for each residue of interest
167  for( std::set< core::Size >::const_iterator it(central_residues_.begin()), end(central_residues_.end()); it != end; ++it){
168  //for all edges of that residue
169  core::Size neighbor_counter = 0;
170  for ( core::graph::Graph::EdgeListConstIter edge_iter = neighborgraph.get_node(*it)->const_edge_list_begin(),
171  edge_end_iter = neighborgraph.get_node(*it)->const_edge_list_end();
172  edge_iter != edge_end_iter; ++edge_iter ) {
173  //the other end of this edge goes in neighbors_
174  neighbors_.insert((*edge_iter)->get_other_ind(*it));
175  neighbor_counter++;
176  }//for all edges of a residue
177  num_neighbors_map_[(*it)] = neighbor_counter;
178  //a residue is its own neighbor, so this makes it part of the set
179  neighbors_.insert(*it);
180  }//for all central_residue_
181 
182  num_neighbors_ = neighbors_.size();
183 
184  return;
185 } //recompute
186 
187 } //namespace pose_metric_calculators
188 } //namespace toolbox
189 } //namespace protocols