Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
InterGroupNeighborsCalculator.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/InterGroupNeighborsCalculator.cc
11 /// @brief This is complicated, so pay attention. This calculator is meant for finding interfaces between protein domains - like protein-protein interfaces but within a protein. It's more flexible than that, though. You define groups of residues within a protein (say, the N and C terminal domains). You then define which pairs of groups you are interested in. This calculator returns the union of the sets of residues at the interfaces between these domains/groups. This calculator contains a superset of the functionality of some of the other calculators, but is less efficient in simple cases. The pose does NOT have to have been scored.
12 /// @author Steven Lewis
13 
14 //Unit headers
16 
17 //
18 #include <core/pose/Pose.hh>
19 
20 #include <basic/MetricValue.hh>
21 
24 #include <core/graph/Graph.hh>
25 
26 //Utility headers
27 //#include <basic/options/option.hh>
28 //#include <core/types.hh>
29 #include <basic/Tracer.hh>
30 #include <utility/exit.hh>
31 #include <utility/string_util.hh>
32 
33 // option key includes
34 #include <basic/options/keys/packing.OptionKeys.gen.hh>
35 
36 //Auto Headers
39 #include <utility/vector1.hh>
40 
41 
42 //C++ headers
43 //#include <set>
44 //#include <utility>
45 
46 static basic::Tracer TR("protocols.toolbox.PoseMetricCalculators.InterGroupNeighborsCalculator");
47 
48 namespace protocols{
49 namespace toolbox {
50 namespace pose_metric_calculators {
51 
52 //typedef std::set< core::Size > one_group;
53 //typedef std::pair< onegroup > group_pair;
54 //typedef utility::vector1< group_pair > group_set;
55 
57  : parent(), groups_(groups), dist_cutoff_(dist_cutoff), num_neighbors_(0)
58  //not doing anything to std::set<core::Size> - should initialize empty
59 {}
60 
62  : parent(), groups_(calculator.groups()), dist_cutoff_(calculator.dist_cutoff())
63 {}
64 
66 
68 { return new InterGroupNeighborsCalculator(*this); }
69 
70 void
72  std::string const & key,
73  basic::MetricValueBase * valptr
74 ) const
75 {
76  if ( key == "groups" ) {
77  basic::check_cast( valptr, &groups_, "groups expects to return a utility::vector1< std::pair< std::set< core::Size >, std::set< core::Size > > >" );
78  (static_cast<basic::MetricValue<group_set> *>(valptr))->set( groups_ );
79 
80  } else if ( key == "dist_cutoff" ) {
81  basic::check_cast( valptr, &dist_cutoff_, "dist_cutoff expects to return a core::Real" );
82  (static_cast<basic::MetricValue<core::Real> *>(valptr))->set( dist_cutoff_ );
83 
84  } else if ( key == "num_neighbors" ) {
85  basic::check_cast( valptr, &num_neighbors_, "num_neighbors expects to return a core::Size" );
86  (static_cast<basic::MetricValue<core::Size> *>(valptr))->set( num_neighbors_ );
87 
88  } else if ( key == "neighbors" ) {
89  basic::check_cast( valptr, &neighbors_, "neighbors expects to return a std::set< core::Size >" );
90  (static_cast<basic::MetricValue< std::set< core::Size > > *>(valptr))->set( neighbors_ );
91 
92  } else {
93  basic::Error() << "InterGroupNeighborsCalculator cannot compute metric " << key << std::endl;
94  utility_exit();
95  }
96 
97 } //lookup
98 
101 {
102  if ( key == "dist_cutoff" ) {
103  return utility::to_string( dist_cutoff_ );
104 
105  } else if ( key == "num_neighbors" ) {
106  return utility::to_string( num_neighbors_ );
107 
108  } else if ( key == "groups" || key == "neighbors" ) {
109  //set up big return string for both sets
110  using namespace basic::options; //this lets you get + or (space) as spacer
111  std::string const spacer( option[ OptionKeys::packing::print_pymol_selection].value() ? "+" : " ");
112  std::string nbrs_string("");
113 
114  if ( key == "groups" ) {
115  for( core::Size i(1), vecsize(groups_.size()); i <= vecsize; ++i){
116  nbrs_string += "{ (";
117  for( one_group::const_iterator it(groups_[i].first.begin()), end(groups_[i].first.end()); it != end; ++it)
118  nbrs_string += spacer + utility::to_string(*it);
119  nbrs_string += ") ; (";
120  for( one_group::const_iterator it(groups_[i].second.begin()), end(groups_[i].second.end()); it != end; ++it)
121  nbrs_string += spacer + utility::to_string(*it);
122  nbrs_string += ") }";
123  }
124  return nbrs_string;
125  } else if ( key == "neighbors" ) {
126  for( std::set< core::Size >::const_iterator it(neighbors_.begin()), end(neighbors_.end()); it != end; ++it)
127  nbrs_string += utility::to_string(*it) + spacer;
128  return nbrs_string;
129  }//neighbors or groups
130  }//else
131  basic::Error() << "InterGroupNeighborsCalculator cannot compute metric " << key << std::endl;
132  utility_exit();
133  return "";
134 } //print
135 
136 void
138 {
139  //clear old data
140  neighbors_.clear();
141  num_neighbors_ = 0;
142 
143  //Might be a good idea to error-check that all group residues are within the pose? - can assert < nres later?
144  core::Size const nres(pose.total_residue());
145 
146  //this is the expensive part!
149  core::conformation::find_neighbors<core::conformation::PointGraphVertexData,core::conformation::PointGraphEdgeData>( pg, dist_cutoff_ ); //create edges
150  runtime_assert(nres == pg->num_vertices());
151 
152  //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.
153  core::graph::Graph neighborgraph(nres);
154  for ( core::Size r(1); r <= nres; ++r){
155  for ( core::conformation::PointGraph::UpperEdgeListConstIter edge_iter = pg->get_vertex(r).upper_edge_list_begin(),
156  edge_end_iter = pg->get_vertex(r).upper_edge_list_end(); edge_iter != edge_end_iter; ++edge_iter ) {
157  neighborgraph.add_edge(r, edge_iter->upper_vertex());
158  }
159  }
160  runtime_assert(nres == neighborgraph.num_nodes());
161  runtime_assert(pg->num_edges() == neighborgraph.num_edges());
162 
163  //iterating through the graph is somewhat less expensive. We will need to iterate once per group pair (domain pair)
164  //for each group/domain pair
165  for( core::Size i(1), vecsize(groups_.size()); i <= vecsize; ++i){
166  //for the first member of the group/domain, iterate through its residues
167  for( one_group::const_iterator it(groups_[i].first.begin()), end(groups_[i].first.end()); it != end; ++it){
168  //for all edges of that node
169  for ( core::graph::Graph::EdgeListConstIter edge_iter = neighborgraph.get_node(*it)->const_edge_list_begin(),
170  edge_end_iter = neighborgraph.get_node(*it)->const_edge_list_end();
171  edge_iter != edge_end_iter; ++edge_iter ) {
172  core::Size const other = (*edge_iter)->get_other_ind(*it);
173  //at this point, *it and other are neighbors. *it is in the "first" group, we need to see if other is in the second.
174  if(groups_[i].second.find(other) != groups_[i].second.end()){
175  // *it was in group 1 and other was in group 2 - store them!
176  neighbors_.insert(*it);
177  neighbors_.insert(other);
178  } //if these are cross-group neighbors
179  }//for all edges of a node
180  //we also need to check if a residue is in both groups at once - it is its own neighbor, so this makes it part of the set
181  if(groups_[i].second.find(*it) != groups_[i].second.end()) neighbors_.insert(*it);
182  }// for all residues in a group
183  }//for all group pairs
184 
185  num_neighbors_ = neighbors_.size();
186 
187  return;
188 } //recompute
189 
190 } //namespace pose_metric_calculators
191 } //namespace toolbox
192 } //namespace protocols