Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
InvrotTreeNode.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 // :noTabs=false:tabSize=4:indentSize=4:
4 //
5 // (c) Copyright Rosetta Commons Member Institutions.
6 // (c) This file is part of the Rosetta software suite and is made available under license.
7 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
8 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
9 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
10 
11 /// @file protocols/toolbox/match_enzdes_util/InvrotTreeNode.cc
12 /// @brief .cc file for inverse rotamer tree node
13 /// @author Florian Richter, flosopher@gmail.com, mar 2012
14 
15 
16 //unit headers
18 
19 //package headers
25 
26 //project headers
29 #include <core/pose/Pose.hh>
32 
33 #include <basic/Tracer.hh>
34 
35 //#include <core/io/pdb/pose_io.hh> //debug only include
36 //#include <fstream> //debug only include
37 //#include <utility/string_util.hh> //debug only include
38 
39 //c++ headers
40 
41 namespace protocols {
42 namespace toolbox {
43 namespace match_enzdes_util {
44 
45 static basic::Tracer tr( "protocols.toolbox.match_enzdes_util.InvrotTreeNode" );
46 
48  : InvrotTreeNodeBase( parent ),
49  geom_cst_(0), generate_invrot_csts_(true)
50 {
52 }
53 
55 
56 
57 /// @details
58 /// assumptions: this node represents the upstream_res
59 /// of this geom_cst (invrot_geomcst), and the given
60 /// target_residue corresponds to the downstream_res of
61 /// invrot_geomcst
62 bool
64  core::conformation::Residue const & target_residue,
65  EnzConstraintIOCOP enzcst_io,
66  Size invrot_geomcst,
68 )
69 {
70  invrots_and_next_nodes_.clear(); //safety
71  std::list< core::conformation::ResidueCOP > all_invrots;
72  all_invrots.clear();
73  if( pose ){
74  core::conformation::ResidueCOP cst_res( cst_residue_in_pose( *pose, invrot_geomcst, enzcst_io->mcfi_list( invrot_geomcst )->mcfi( 1 )->upstream_res() ) );
75  if( cst_res ) all_invrots.push_back( cst_res );
76  }
77 
78  //1. create all invrots against target residue
79  //mcfi(1) is hardcoded because matcher can't
80  //deal with upstream-upstream matching when the
81  //target residue has explicit ambiguity
82  //we have to put in an early catch for this somewhere..
83  if( all_invrots.size() == 0 ){
84  all_invrots = enzcst_io->mcfi_list( invrot_geomcst)->inverse_rotamers_against_residue( enzcst_io->mcfi_list( invrot_geomcst )->mcfi( 1 )->downstream_res(), &target_residue );
85 
86  //2. do clash check against all parent residues
87  //if all get removed, this means this is a dead end
88  //and we return false
89  Size num_rots_total( all_invrots.size() );
90  this->remove_invrots_clashing_with_parent_res( all_invrots, enzcst_io->mcfi_list(invrot_geomcst)->mcfi(1)->is_covalent() );
91  Size num_invrots_clashing( num_rots_total - all_invrots.size() );
92  tr << "When initializing a node for geomcst " <<invrot_geomcst << ", " << num_invrots_clashing << " of a total of " << num_rots_total << " inverse rotamers were found to clash with something." << std::endl;
93  if( all_invrots.size() == 0 ){
94  return false;
95  }
96  }
97 
98  return this->initialize_from_enzcst_io_and_invrots( all_invrots, enzcst_io, invrot_geomcst, pose );
99 }
100 
101 bool
103  std::list< core::conformation::ResidueCOP > const & all_invrots,
104  EnzConstraintIOCOP enzcst_io,
105  Size invrot_geomcst,
107 )
108 {
109 
110  geom_cst_ = invrot_geomcst;
111  //3. now we have to figure out if the upstream_res of
112  //this geom_cst (i.e. what this node represents) is the
113  //downstream_res in a later mcfi
114  //i.e. do we need to build inverse rotamers against
115  //the inverse rotamers of this node?
116  utility::vector1< Size > dependent_mcfi;
117  for( Size i = geom_cst_ +1; i <= enzcst_io->num_mcfi_lists(); ++i){
118  std::pair< Size, Size> const & target_res( enzcst_io->target_downstream_res()[i] );
119  if( (target_res.first == geom_cst_) && (target_res.second == 2 ) ) dependent_mcfi.push_back( i );
120  }
121 
122  //if there are no dependent mcfi, we're done
123  //simply put the inverse rots and an empty vector
124  //into the invrots_and_next_nodes_ vector
125  if( dependent_mcfi.size() == 0 ){
126  invrots_and_next_nodes_.push_back( std::pair< std::list<core::conformation::ResidueCOP >, utility::vector1< InvrotTreeNodeOP > > () );
127  invrots_and_next_nodes_[1].first = all_invrots;
128  return true;
129  }
130 
131  //4. if we get here, that means we need to build
132  //inverse_rotamer_trees against the inverse rotamers
133  //in this node
134  //it's gettin' brutishly complicated, because we have to figure
135  //out the redundancy groups of this nodes invrots', i.e. against
136  //how many of the invrots here do we need to build separate
137  //dependent inverse rotamer trees...
138  //ok, let's go
139  //4.1 first invrot is always non redundant
140  invrots_and_next_nodes_.push_back( std::pair< std::list<core::conformation::ResidueCOP >, utility::vector1< InvrotTreeNodeOP > > () );
141  invrots_and_next_nodes_[1].first.push_back( *(all_invrots.begin()) );
142 
143  //4.2 now loop through remaining invrots and
144  //check for redundancy to other invrots with respect to
145  //positioning of dependent inverse rotamer trees
146  std::list<core::conformation::ResidueCOP>::const_iterator invrot_it1 = all_invrots.begin();
147  invrot_it1++; //first one was already taken care of
148  while( invrot_it1 != all_invrots.end() ){
149  bool this_invrot_redundant(false);
150  for( core::Size i = 1; i <= invrots_and_next_nodes_.size(); ++i ){
151 
152  //4.3 really complicated code goes here
153  //let's see: we have to see whether the two rotamers
154  //are redundant according to each of the dependent mcfi,
155  //i.e. we have to ask the downstream EnzCstTemplateRes
156  //of the dependent mcfi whether the two rotamers are redundant
157  core::conformation::Residue const & cur_rot(**invrot_it1), test_rot( **(invrots_and_next_nodes_[i].first.begin()) );
158  bool these_two_redundant(true);
159  for( Size j = 1; j <= dependent_mcfi.size(); ++j){
160 
161  if( !enzcst_io->mcfi_list( dependent_mcfi[j])->mcfi(1)->enz_cst_template_res( enzcst_io->mcfi_list( dependent_mcfi[j])->mcfi(1)->downstream_res() )->residue_conformations_redundant( cur_rot, test_rot ) ){
162  these_two_redundant = false;
163  break;
164  }
165  }
166  if( these_two_redundant ){
167  invrots_and_next_nodes_[i].first.push_back( *invrot_it1 );
168  this_invrot_redundant = true;
169  break;
170  }
171  }//loop over all so-far non redundant rots
172 
173  //if this rotamer is non redundant, we throw it into a new list
174  if( !this_invrot_redundant ){
175  invrots_and_next_nodes_.push_back( std::pair< std::list<core::conformation::ResidueCOP >, utility::vector1< InvrotTreeNodeOP > > () );
176  invrots_and_next_nodes_[invrots_and_next_nodes_.size() ].first.push_back( *invrot_it1 );
177  }
178  invrot_it1++;
179  } //while loop over invrot_it1
180  tr << "Node initialization for geomcst " << geom_cst_ << ". After redundancy determination, " << invrots_and_next_nodes_.size() << " non-redundant sets of inverse rotamers exist." << std::endl;
181  //4.4 redundancy determined, almost done, now we need to
182  //initialize the daughter nodes for each set of non-redundant
183  //invrots. note that if any of these nodes fail to initialize,
184  //that renders the corresponding set of invrots a dead end
185  for( utility::vector1< invrots_node_ptrs_pair >::iterator pair_it( invrots_and_next_nodes_.begin() ); pair_it != invrots_and_next_nodes_.end(); /*increment happening in loop*/ ){
186 
187  core::conformation::Residue const & this_target( **(pair_it->first.begin()) );
188  bool all_initialization_successful(true);
189  for( Size j = 1; j <= dependent_mcfi.size(); ++j ){
190  InvrotTreeNodeOP child = new InvrotTreeNode( this );
191  pair_it->second.push_back( child );
192  if( ! child->initialize_from_enzcst_io( this_target, enzcst_io, dependent_mcfi[j], pose ) ){
193  pair_it = invrots_and_next_nodes_.erase( pair_it ); //note: erasing from vector, not ideal, but the vectors should usually be fairly small and the initialization shenanigans are only called once
194  all_initialization_successful = false;
195  break;
196  }
197  } // loop over dependent mcfi
198  if( all_initialization_successful ){
199  ++pair_it;
200  }
201  }//loop over all non-redundant invrot groups
202  //I guess we have to set the locations in this node in the child nodes
203 
204  tr << "Node initialization for geomcst " << geom_cst_ << ". After child node initialization, " << invrots_and_next_nodes_.size() << " non-redundant sets of inverse rotamers exist." << std::endl;
205  for( Size i =1; i <= invrots_and_next_nodes_.size(); ++i ){
206  tr << invrots_and_next_nodes_[i].first.size() << " inverse rotamers for non-redundant set " << i << std::endl;
207  for( utility::vector1< InvrotTreeNodeBaseOP >::iterator child_it( invrots_and_next_nodes_[i].second.begin() ); child_it != invrots_and_next_nodes_[i].second.end(); ++child_it ){
208  (*child_it)->set_location_in_parent_node( i );
209  }
210  }
211 
212  //4.5 in case there were dead ends only, we return false
213  if( invrots_and_next_nodes_.size() == 0 ) return false;
214 
215  return true;
216 }
217 
218 /// @details the real meat of this thing
219 /// see brief description in .hh file
222  core::pose::Pose const & pose,
223  AllowedSeqposForGeomCstCOP geomcst_seqpos
224 ) const
225 {
226  core::id::AtomID fixed_pt( this->get_fixed_pt( pose ) );
228 
229  if( !generate_invrot_csts_ ) runtime_assert( invrots_and_next_nodes_.size() == 1 ); //sanity check, relation exists because in this case we should only have one invrot
230 
231  for( core::Size i = 1; i <= invrots_and_next_nodes_.size(); ++i ){
232 
233  //utility::vector1< core::scoring::constraints::ConstraintCOP > constraints_this_invrot_set;
234  utility::vector1< core::scoring::constraints::ConstraintCOP > constraints_this_invrot_node_pair;
235 
236  //1a. create the ambiguous constraint for this set of inverse rotamers
237  if( generate_invrot_csts_) constraints_this_invrot_node_pair.push_back( constrain_pose_res_to_invrots( invrots_and_next_nodes_[i].first, geomcst_seqpos->seqpos_for_geomcst( geom_cst_), pose, fixed_pt ) );
238 
239  //1b.
240  for( utility::vector1< InvrotTreeNodeBaseOP >::const_iterator node_it( invrots_and_next_nodes_[i].second.begin() ), node_end( invrots_and_next_nodes_[i].second.end() ); node_it != node_end; ++node_it ){
241  core::scoring::constraints::ConstraintCOP this_child_cst( (*node_it)->generate_constraints( pose, geomcst_seqpos ) );
242  if( this_child_cst) constraints_this_invrot_node_pair.push_back( this_child_cst );
243  }
244 
245  //1c.
246  if( constraints_this_invrot_node_pair.size() == 1 ) constraints_this_node.push_back( constraints_this_invrot_node_pair[1] );
247  else if( constraints_this_invrot_node_pair.size() > 1 ) constraints_this_node.push_back( new core::scoring::constraints::MultiConstraint( constraints_this_invrot_node_pair ) );
248 
249  }//loop over node_pointer_pairs_
250 
251  if( constraints_this_node.size() == 0 ) return NULL;
252 
253  if( constraints_this_node.size() == 1 ) return constraints_this_node[1];
254 
255  return new core::scoring::constraints::AmbiguousConstraint( constraints_this_node );
256 }
257 
258 
259 /// @details approach: get the target residues,
260 /// then find a residue in the pose that has the
261 /// same name as the first target residue and a
262 /// neighbor atom in the same position. this will
263 /// be the fixed point. exit w error if not found
266 {
267  InvrotTreeNodeBaseCAP parent(this->parent_node() );
268  if( !parent ) utility_exit_with_message("the impossible just happened");
269 
270  utility::vector1< std::list< core::conformation::ResidueCOP > > parent_res( parent->all_target_residues( this ) );
271  std::string target_name3( (*parent_res[1].begin())->name3() );
272  core::Vector const & xyz_to_find( (*parent_res[1].begin())->nbr_atom_xyz() );
273 
274  for( Size i = 1; i<= pose.total_residue(); ++i ){
275  if(pose.residue_type(i).name3() == target_name3 ){
276  for( Size j =1; j<= pose.residue(i).atoms().size(); ++j ){
277  if( xyz_to_find.distance_squared( pose.residue(i).atom(j).xyz() ) < 0.1 ){
278  return core::id::AtomID( j, i );
279  }
280  }
281  }
282  }
283  //if we get here, that means no atom was found and shit's fucked up somewhere
284  utility_exit_with_message("No success when trying to find a fixed pt in the InvrotTree that's also in the pose. Shit's fucked up somewhere.");
285  return core::id::AtomID( 0, 0 ); // to pacify compiler
286 }
287 
288 
291 {
292 
294 
295  //1. get the target residues of the parent node
296  InvrotTreeNodeBaseCAP parent(this->parent_node() );
297  if( parent ) to_return = parent->all_target_residues( this );
298  //2. add the target residues from this node
299  //corresponding to the asking child node
300  bool child_found(false);
301  for( Size i =1; i <= invrots_and_next_nodes_.size(); ++i ){
302  for( Size j =1; j <= invrots_and_next_nodes_[i].second.size(); ++j ){
303  if( &(*child_node) == &(*(invrots_and_next_nodes_[i].second[j])) ){
304  to_return.push_back( invrots_and_next_nodes_[i].first );
305  child_found = true;
306  break;
307  }
308  }
309  if( child_found ) break;
310  }
311 
312  return to_return;
313 }
314 
315 
316 /// @details if covalent is true, clashes will not be checked
317 /// for the last vector that comes down from the parent.
318 /// kinda crude, could be made better, i.e. only except the actual
319 /// constrained atoms from clash check
320 void
322  std::list< core::conformation::ResidueCOP > & invrots,
323  bool covalent
324 ) const
325 {
326 
327  InvrotTreeNodeBaseCAP parent(this->parent_node() );
328 
329  //in case there's no parent, i.e. in the unit test
330  //or potential use of this outside the tree, there
331  //are no target to clash with, so we'll return
332  if( !parent ) return;
333 
334  //1. get all parent rotamers
335  utility::vector1< std::list< core::conformation::ResidueCOP > > all_targets ( (*parent).all_target_residues( this ) );
336 
337  if( covalent ) all_targets.pop_back(); //covalent: we ignore the last list, since this represents the immediate parent residues
338 
339  //safety: if for some reason all_targets is empty,
340  //we return
341  if( all_targets.size() == 0 ) return;
342 
343  //2.clash check between invrots and parent residues
344  //all invrots that clash with all rotamers from any
345  //of the all_targets list will be removed
346  for( std::list <core::conformation::ResidueCOP >::iterator invrot_it( invrots.begin() ); invrot_it != invrots.end(); /*increment in loop*/ ){
347  bool cur_invrot_clashes(false);
348 
349  for( Size i =1; i <= all_targets.size(); ++i){
350 
351  //safety: if for some reason this list is empty, we continue
352  if( all_targets[i].size() == 0 ) continue;
353 
354  bool this_list_all_clash( true );
355  for( std::list <core::conformation::ResidueCOP >::const_iterator target_rot_it( all_targets[i].begin() ), target_rot_it_end( all_targets[i].end() ); target_rot_it != target_rot_it_end; ++target_rot_it ){
356 
357  //the actual clash check
358  //hardcoded as hadrsphere here for now, but in the future this could be
359  //combined with matcher filters
360  bool these_two_clash(false);
361  core::Real cutoff_sq = 2.5 * 2.5;
362  core::conformation::Residue const & res1(**invrot_it), res2(**target_rot_it);
363  for( Size res1at = 1; res1at <= res1.nheavyatoms(); ++res1at ){
364  if( res1.type().is_virtual( res1at ) ) continue;
365  for( Size res2at = 1; res2at <= res2.nheavyatoms(); ++res2at){
366  if( res2.type().is_virtual( res2at ) ) continue;
367  if( res1.atom( res1at ).xyz().distance_squared( res2.atom( res2at ).xyz() ) < cutoff_sq ){
368  these_two_clash = true;
369 
370  /* //debug
371  static Size clashrescount(0);
372  clashrescount++;
373  tr << "ACKACK clash num " << clashrescount << " between res1 atom " << res1.type().atom_name( res1at ) << " and res2 atom " << res2.type().atom_name( res2at ) << " which are sqrt(" << res1.atom( res1at ).xyz().distance_squared( res2.atom( res2at ).xyz() ) << " apart." << std::endl;
374  std::ofstream file_out( ("clashno_"+utility::to_string( clashrescount )+".pdb").c_str() );
375  Size atomcounter(0);
376  core::io::pdb::dump_pdb_residue( res1, atomcounter, file_out );
377  core::io::pdb::dump_pdb_residue( res2, atomcounter, file_out );
378  file_out.close();
379  //debug over */
380 
381  break; //breaks loop over res2 atoms
382  }
383  } //loop over res2 atoms
384  if( these_two_clash ) break; //breaks loop over res 1 atoms
385  }//loop over res1 atoms
386  if( !these_two_clash){
387  this_list_all_clash = false;
388  break; //breaks loop over rots in this list
389  }
390  } //for loop over target_rot
391  if( this_list_all_clash ){
392  cur_invrot_clashes = true;
393  break; // breaks loop over target_lists
394  }
395  } //for loop over target_rot_lists
396 
397  if( cur_invrot_clashes ) invrot_it = invrots.erase( invrot_it );
398  else ++invrot_it;
399  } //loop over all invrots
400 }
401 
402 
403 void
405  utility::vector1< InvrotCollectorOP > & invrot_collectors
406 ) const
407 {
408 
409  runtime_assert( invrots_and_next_nodes_.size() != 0 );
410  //1. find all invrot collectors that have stuff from this node's parent
411  //and location in them
412  utility::vector1< Size > empty_parent_collectors;
413  utility::vector1< Size > filled_parent_collectors;
414 
415  for( Size i =1; i <= invrot_collectors.size(); ++i ){
416  std::map< InvrotTreeNodeBaseCOP, Size > const & collector_map( invrot_collectors[i]->owner_nodes_and_locations() );
417  //safety
418  if( collector_map.find( this ) != collector_map.end() ) utility_exit_with_message("InvrotTreeNode being asked to fill a collector that it apparently already previously filled.");
419 
420  std::map< InvrotTreeNodeBaseCOP, Size >::const_iterator map_it( collector_map.find( &(*(this->parent_node())) ) );
421 
422  if( map_it != collector_map.end() ){
423  if( map_it->second == this->location_in_parent_node() ){
424  if( invrot_collectors[i]->invrots()[ geom_cst_].size() == 0 ) empty_parent_collectors.push_back( i );
425  else filled_parent_collectors.push_back( i );
426  }
427  }
428  }
429  tr << "Collecting inverse rotamers for a node from geomcst " << geom_cst_ << ". " << empty_parent_collectors.size() << " empty parent collectors and " << filled_parent_collectors.size() << " filled parent collectors were found." << std::endl;
430 
431  //1.b make sure we found at least one parent
432  Size total_parents( empty_parent_collectors.size() + filled_parent_collectors.size() );
433  runtime_assert( total_parents != 0);
434 
435  //2a for every parent, we need to add rotamers for every definiton
436  utility::vector1< Size > collectors_to_fill( empty_parent_collectors );
437  for( Size i =1; i <= filled_parent_collectors.size(); ++ i ){
438  invrot_collectors.push_back( invrot_collectors[ filled_parent_collectors[i] ]->clone() );
439  collectors_to_fill.push_back( invrot_collectors.size() );
440  }
441 
442  //2b. fill 'er up
443  for( Size i = 1; i <= collectors_to_fill.size(); ++i ){
444  Size overflow_start( invrot_collectors.size());
445  for( Size j = 2; j <= invrots_and_next_nodes_.size(); ++j ){
446  invrot_collectors.push_back( invrot_collectors[ collectors_to_fill[i] ]->clone() );
447  }
448 
449  invrot_collectors[ collectors_to_fill[ i ] ]->set_invrots_for_listnum( geom_cst_, invrots_and_next_nodes_[1].first, this, 1 );
450 
451  for( Size j =2; j <= invrots_and_next_nodes_.size(); ++j ){
452  invrot_collectors[ overflow_start + j - 1 ]->set_invrots_for_listnum( geom_cst_, invrots_and_next_nodes_[j].first, this, j );
453  }
454  }
455 
456  //3. call this shit on all daughter nodes
457  for( Size i = 1; i <= invrots_and_next_nodes_.size(); ++i){
458  for( utility::vector1< InvrotTreeNodeBaseOP >::const_iterator child_it( invrots_and_next_nodes_[i].second.begin() ); child_it != invrots_and_next_nodes_[i].second.end(); ++child_it ){
459  (*child_it)->collect_all_inverse_rotamers( invrot_collectors );
460  }
461  }
462 }
463 
464 }
465 }
466 }