Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Interface.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 Interface - information about the interface between to partners
11 /// @brief contains the following information:
12 /// calculate the interface between the two (or other?) partners
13 /// set the packer task to only pack the interface
14 /// @author Monica Berrondo
15 
16 
18 
19 // Rosetta Headers
21 
22 // AUTO-REMOVED #include <core/kinematics/CAlpha.hh>
23 // AUTO-REMOVED #include <core/kinematics/MoveMap.hh>
24 
26 // AUTO-REMOVED #include <core/pack/task/TaskFactory.hh>
27 
28 #include <core/pose/Pose.hh>
29 
31 
32 // AUTO-REMOVED #include <basic/basic.hh>
33 
34 #include <basic/options/option.hh>
35 
36 // ObjexxFCL Headers
37 #include <ObjexxFCL/FArray1D.hh>
38 #include <ObjexxFCL/string.functions.hh>
39 // AUTO-REMOVED #include <ObjexxFCL/format.hh>
40 
41 // C++ Headers
42 
43 //Utility Headers
44 
45 // AUTO-REMOVED #include <numeric/conversions.hh>
46 
47 #include <numeric/trig.functions.hh>
48 #include <numeric/xyzMatrix.fwd.hh>
49 
50 #include <basic/Tracer.hh>
51 
52 // symmetry includes
58 // AUTO-REMOVED #include <core/conformation/symmetry/util.hh>
59 
60 
61 // option key includes
62 
63 #include <basic/options/keys/docking.OptionKeys.gen.hh>
64 #include <basic/options/keys/matdes.OptionKeys.gen.hh>
65 
66 #include <utility/vector1.hh>
67 
68 //Auto Headers
70 
71 
72 using basic::T;
73 using basic::Error;
74 using basic::Warning;
75 using namespace ObjexxFCL;
76 
77 static basic::Tracer TR("core.conformation.Interface");
78 
79 namespace protocols {
80 namespace scoring {
81 
82 static core::Size max_interchain_sites ( 2 );
83 
84 ////////////////////////////////////////////////////////////////////////////////////
85 /// @begin calculate
86 ///
87 /// @brief base for calculating the interface
88 /// @detailed
89 /// decide which type of an interface calculation to use
90 ///
91 /// @authors Monica Berrondo October 19 2007
92 /////////////////////////////////////////////////////////////////////////////////
93 void
94 Interface::calculate( core::pose::Pose const & pose )
95 {
96  /// create a dummy array to initialize all the members of the partner
97  /// and is_interface array to false
98  using namespace core;
99  FArray1D_bool false_array ( pose.total_residue(), false );
100  partner_ = false_array;
101  is_interface_ = false_array;
102  pair_list_.resize( max_interchain_sites );
103  contact_list_.resize( pose.total_residue() );
104  kinematics::FoldTree const & fold_tree ( pose.fold_tree() );
105 
106  // Check if we are symmetric. We don't need the FoldTree partitioning for this
107  // so we check for symmetry here
108  if ( pose::symmetry::is_symmetric( pose.energies() ) ) {
109  symmetric_protein_calculate( pose );
110  return;
111  }
112 
113  // partner is the same as is_upstream of Ian's code in LigandDockProtocol
114  if( !use_input_partners_ )
115  fold_tree.partition_by_jump( jump_number_, partner_ );
116 
117  //for ( Size i=1; i<=pose.total_residue(); ++i ) {
118  // assuming if it is not a polymer residue, it must be a ligand
119  Size upstream_jump_res, downstream_jump_res;
120  upstream_jump_res = fold_tree.upstream_jump_residue( jump_number_ );
121  downstream_jump_res = fold_tree.downstream_jump_residue( jump_number_ );
122  if ( pose.residue( upstream_jump_res ).is_ligand() || pose.residue( downstream_jump_res ).is_ligand() ) {
123  TR.Debug << "One of the residues is a ligand, calculating the interface between ligand and protein" << std::endl;
124  ligand_calculate( pose );
125  return;
126  // check if some sort of nucleic acid
127  } else if ( pose.residue( upstream_jump_res ).is_NA() || pose.residue( downstream_jump_res ).is_NA() ) {
128  TR.Debug << "One of the residues is a nucleic acid, calculating interface of nucleic acids" << std::endl;
129  NA_calculate( pose ); //set to protein_calculate(pose)
130  return;
131  }
132  //}
133  // if it gets through the entire protein and all the residues were of type protein
134  // then use protein-protein interface calculation
135  TR.Debug << "Calculating protein-protein interface" << std::endl;
136  protein_calculate( pose );
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////////
140 /// @begin protein_calculate
141 ///
142 /// @brief calculate the protein-protien interface
143 /// @detailed
144 /// decide which type of an interface calculation to use
145 /// calculate the residues that are at the interface
146 /// this uses the CAlpha class (at least for now) which
147 /// gets the distances between c-alpha atoms
148 /// Returns a vector of bools, true if at interface, false otherwise
149 ///
150 /// This uses partition_by_jump to determine which residues belong
151 /// to each partner those on one side of the jump are set to 0,
152 /// the others are set to 1
153 /// A residue is at the interface if it is within 8A radius of the
154 /// residue in question on the other partner
155 ///
156 /// @references pose_docking_calc_interface from pose_docking.cc
157 ///
158 /// @authors Monica Berrondo June 14 2007
159 ///
160 /// @last_modified October 19 2007
161 /////////////////////////////////////////////////////////////////////////////////
162 void
163 Interface::protein_calculate( core::pose::Pose const & pose )
164 {
165  using namespace core;
166  using namespace conformation;
167 
168  core::scoring::EnergyGraph const & energy_graph( pose.energies().energy_graph() );
169  std::vector< int>::iterator new_end_pos;
170 
171  for ( Size i=1; i<=Size(energy_graph.num_nodes()); ++i ) {
173  iru = energy_graph.get_node(i)->const_upper_edge_list_begin(),
174  irue = energy_graph.get_node(i)->const_upper_edge_list_end();
175  iru != irue; ++iru ) {
176  core::scoring::EnergyEdge const * edge( static_cast< core::scoring::EnergyEdge const *> (*iru) );
177  Size const j( edge->get_second_node_ind() );
178  if ( partner_(i) == partner_(j) ) continue;
179  // if ( is_interface_(i) && is_interface_(j) ) continue;
180  Real const cendist = edge->square_distance();
181  if ( cendist < distance_squared_ ) {
182 // TR << "interface edge: " << i << ' ' << j << ' ' << cendist << std::endl;
183  is_interface_(i) = is_interface_(j) = true;
184  pair_list_[1].push_back(i);
185  pair_list_[2].push_back(j);
186 
187  contact_list_[i].push_back(j);
188  contact_list_[j].push_back(i);
189  } ///< set pack residue to true if within a predetermined distance (default 8A)
190  } ///< for j
191  } ///< for i
192 
193  /// this is really ugly, there has to be a better way of doing this
194  std::sort( pair_list_[1].begin(), pair_list_[1].end() );
195  new_end_pos = std::unique( pair_list_[1].begin(), pair_list_[1].end() );
196  pair_list_[1].erase( new_end_pos, pair_list_[1].end() );
197  std::sort( pair_list_[2].begin(), pair_list_[2].end() );
198  new_end_pos = std::unique( pair_list_[2].begin(), pair_list_[2].end() );
199  pair_list_[2].erase( new_end_pos, pair_list_[2].end() );
200 }
201 
202 // The Rosetta++ criterion for which sidechains repack/minimize in docking:
203 // ligand heavy atom within paircutoff(aa,GLY)+1 of aa's CB
204 // See
205 // docking_minimize.cc docking_MCM_pack_side_chains()
206 // docking_movement.cc docking_repack()
207 // docking_scoring.cc docking_interf_residues()
208 // ligand.cc detect_ligand_interface[_res]()
209 // hetero_atom_amino_acid_distance()
210 // Ian's criterion to approximate this in Mini:
211 // ligand heavy atom within rsd.nbr_radius()+6 of rsd.nbr_atom()
212 // 6A is an eyeballed magic number to get ~ agreement w/ Rosetta++ paircutoffs+1
213 
214 void
215 Interface::NA_calculate( core::pose::Pose const & pose ){ protein_calculate( pose );}
216 
217 void
218 Interface::ligand_calculate(
219  core::pose::Pose const & pose
220 )
221 {
222 
223  using namespace core;
224  for(Size i = 1, i_end = pose.total_residue(); i <= i_end; ++i) {
225  // all residues on ligand side can move
226  if ( ! partner_(i) ) {
227  is_interface_(i) = true;
228  continue;
229  }
230  // on protein side, have to do distance check
231  conformation::Residue const & prot_rsd = pose.residue(i);
232  for(Size j = 1, j_end = pose.total_residue(); j <= j_end; ++j) {
233  if ( partner_(j) ) continue; // compare against only ligand residues
234  conformation::Residue const & lig_rsd = pose.residue(j);
235  for(Size k = 1, k_end = lig_rsd.nheavyatoms(); k <= k_end; ++k) {
236  double dist2 = lig_rsd.xyz(k).distance_squared( prot_rsd.xyz(prot_rsd.nbr_atom()) );
237  double cutoff = prot_rsd.nbr_radius() + 6.0;
238  if ( dist2 <= cutoff * cutoff ) {
239  is_interface_(i) = true;
240 
241  contact_list_[i].push_back(j);
242  contact_list_[j].push_back(i);
243  goto END_LIGRES_LOOP; // C++ lacks multi-level break :(
244  }
245  }
246  }
247  END_LIGRES_LOOP: ; // compiler needs ; as a no-op before end of loop
248  }
249 }
250 
251 /// @begin Interface:closest_interface_residue
252 /// @brief find the nearest residue at the interface to a given residue
253 /// @authors Monica Berrondo November 18, 2010
255 Interface::closest_interface_residue( core::pose::Pose const & pose, Size src_rsd, core::Real & distance )
256 {
257  using namespace core;
258  using namespace conformation;
259 
260  Size ret_rsd (0);
261  Real min_distance (1000000.0);
262 
263  for ( Size i=1; i<=pose.total_residue(); ++i ) {
264  if ( partner_(src_rsd) == partner_(i) ) continue;
265  Real const cendist = pose.residue(i).nbr_atom_xyz().distance(pose.residue(src_rsd).nbr_atom_xyz()) ;
266  if ( cendist < min_distance ) {
267  ret_rsd = i;
268  min_distance = cendist;
269  }
270  } ///< for j
271  distance = min_distance;
272  return ret_rsd;
273 }
274 
275 ////////////////////////////////////////////////////////////////////////////////////
276 /// @begin Interface::print
277 /// @brief print out the interface information
278 /// @authors Monica Berrondo November 07 2007
279 /// @last_modified November 07 2007
280 ////////////////////////////////////////////////////////////////////////////////////
281 void
282 Interface::print( core::pose::Pose const & pose )
283 {
284  show(pose);
285 }
286 
287 void
288 Interface::show( core::pose::Pose const & pose )
289 {
290  TR << "Interface residues:" << std::endl;
291 
292  std::string selection;
293  for ( Size i=1; i<=max_interchain_sites; ++i ) {
294  TR << "Site " << i << std::endl;
295  for ( Size j=1; j<= pair_list_[i].size(); ++j ) {
296  core::conformation::Residue const & rsd = pose.residue( pair_list_[i][j] );
297  TR << " " << rsd.aa() << ' ' << rsd.seqpos() << std::endl;
298  selection += string_of(rsd.seqpos()) + '+';
299  }
300  if (pair_list_[i].size() > 0) {
301  TR << " sele interface" << i << ", resi " << selection << std::endl;
302  }
303  if ( i==1 ) selection.clear();
304  }
305 }
306 
307 ////////////////////////////////////////////////////////////////////////////////////
308 // need to check to make sure that the interface residues are actually interface
309 // residues
310 /// @begin set_pack
311 ///
312 /// @brief sets up which residues are to be packed
313 /// @detailed
314 ///
315 /// @references pose_docking_repack from pose_docking.cc
316 ///
317 /// @authors Monica Berrondo June 14 2007
318 ///
319 /// @last_modified June 29 2007
320 /////////////////////////////////////////////////////////////////////////////////
321 void
322 Interface::set_pack(
323  core::pose::Pose const & pose,
325 )
326 {
327  ///TODO Get rid of dependency on option system
328  using namespace basic::options;
329  using namespace basic::options::OptionKeys;
330 
331  // initially set pack_residue to false for all residues
332  // apl -- this logic is now inverted to start from a task of "repack everything" and to then
333  // produce a task of "repack only a few things"
334  task->restrict_to_repacking();
335  for ( Size ii=1; ii<=pose.total_residue(); ++ii ) {
336  // apl if the residue is set to false (as not being an interface residue), set pack to false
337  // Disable packing completely for ligands, not supported yet.
338  if ( !is_interface_(ii) || pose.residue(ii).is_ligand() ) {
339  task->nonconst_residue_task( ii ).prevent_repacking();
340  }
341  }
342 
343  Size cutpoint ( pose.fold_tree().cutpoint_by_jump( jump_number_ ) );
344  // sc - fixed residue selection for norepack1 and norepack2 options to be compatible with docking foldtree
345  if ( option[ docking::norepack1 ]() ) {
346  for ( Size ii = 1 ; ii <= cutpoint; ++ii ) {
347  task->nonconst_residue_task( ii ).prevent_repacking();
348  }
349  }
350  if ( option[ docking::norepack2 ]() ) {
351  for ( Size ii = cutpoint ; ii <= pose.total_residue(); ++ii ) {
352  task->nonconst_residue_task( ii ).prevent_repacking();
353  }
354  }
355  // set to true for now
356  // TODO fix this
357  task->or_include_current( true );
358 }
359 
360 /// @details
361 /// Function to determine whether two residues are a "pair" for docking-type
362 /// scoring calculations, such as vdw and pair across an interface
363 bool
364 Interface::is_pair(
365  core::conformation::Residue const & rsd1,
366  core::conformation::Residue const & rsd2
367 )
368 {
369  /// this is only necessary for Atom and Residue
370  using namespace core;
371  using namespace core::conformation;
372 
373  bool is_pair = false;
374 
375  for(Size i = 1; i <= contact_list_[rsd1.seqpos()].size(); i++){
376  if (rsd2.seqpos() == contact_list_[rsd1.seqpos()][i]) is_pair = true;
377  }
378 
379  return is_pair;
380 //
381 // Real const cendist ( rsd1.nbr_atom_xyz().distance_squared( rsd2.nbr_atom_xyz() ) );
382 // if ( partner_(rsd1.seqpos()) == partner_(rsd2.seqpos()) ) return false;
383 // if ( is_interface_(rsd1.seqpos()) && is_interface_(rsd2.seqpos())
384 // && (cendist < distance_ * distance_) )
385 // return true;
386 // else
387 // return false;
388 }
389 
390 /////////////////////////////////////////////////////////////////////////////////
391 /// @begin interface_center
392 ///
393 /// @brief calculates the center of mass of interface residues
394 /// @detailed
395 /// calculate the center of mass of the interface
396 /// loops over all residues at the interface and gets the xyz coordinates for
397 /// the c-alpha atom of that residue
398 ///
399 /// @references pose_docking_calc_interface from pose_docking.cc
400 ///
401 /// @authors Monica Berrondo June 14 2007
402 ///
403 /// @last_modified June 29 2007
404 /////////////////////////////////////////////////////////////////////////////////
405 // check to make sure this is working correctly
407 Interface::center (
408  core::pose::Pose const & pose
409 )
410 {
411  int count ( 0 );
412  std::vector < bool > interface ( pose.total_residue(), false );
413  using namespace core;
414  Vector center ( 0.0 );
415 
416  // first, calculate the residues that are at the interface
417  // this should be already calculated?
418 // calculate( pose );
419  for ( Size i=1; i<=pose.total_residue(); ++i ) {
420  if ( interface[i] ) {
421  // the c-alpha atom, this should probably be more generalized so that it can work
422  // with a ligand, surface, or dna.
423  // in that case it wouldn't be the ca atom, it would be something like the backbone
424  // phospate atom from dna, etc.
425  // jec generalized to be residue neighbor atom. Not the same as Ca, but much more general.
426  Vector const nbr_pos( pose.residue( i ).nbr_atom_xyz() );
427  center += nbr_pos;
428  count++;
429  }
430  }
431  center /= (count);
432  return center;
433 }
434 
435 bool Interface::is_interface( core::conformation::Residue const & rsd ) const { return is_interface_( rsd.seqpos() ); }
436 
437 bool Interface::is_interface( Size const position ) const { return is_interface_(position); }
438 void Interface::distance( Real const distance_in ) { distance_squared_ = distance_in * distance_in; }
439 void Interface::jump( Size const jump_num ) { jump_number_ = jump_num; }
440 
441 //returns the number of residues at the interface
442 core::Size Interface::interface_nres()
443 {
444  Size nres = 0;
445  for (Size i=1; i<=is_interface_.size();i++){
446  if (is_interface_(i)) nres++;
447  }
448  return nres;
449 }
450 
451 // symmetric interfaces
452 
453 void
454 Interface::symmetric_protein_calculate( core::pose::Pose const & pose )
455 {
456  using namespace core;
457  using namespace conformation;
458  using namespace conformation::symmetry;
459 
460  SymmetricConformation const & SymmConf (
461  dynamic_cast<SymmetricConformation const &> ( pose.conformation()) );
462  SymmetryInfoCOP symm_info( SymmConf.Symmetry_Info() );
464  ( dynamic_cast< core::scoring::symmetry::SymmetricEnergies const & > ( pose.energies() ) );
465  core::scoring::EnergyGraph const & energy_graph( energies()->energy_graph() );
466 
467  for ( Size i = 1; i <= pose.total_residue(); ++i ) {
468  if ( symm_info->bb_is_independent(i) ) {
469  partner_(i) = true;
470  }
471  }
472  std::vector< int>::iterator new_end_pos;
473 
474  for ( Size i=1; i<=Size(energy_graph.num_nodes()); ++i ) {
476  iru = energy_graph.get_node(i)->const_upper_edge_list_begin(),
477  irue = energy_graph.get_node(i)->const_upper_edge_list_end();
478  iru != irue; ++iru ) {
479  core::scoring::EnergyEdge const * edge( static_cast< core::scoring::EnergyEdge const *> (*iru) );
480  Size const j( edge->get_second_node_ind() );
481  bool symm_add;
482  if (basic::options::option[basic::options::OptionKeys::matdes::num_subs_building_block].user()) {
483  Size num_subs = basic::options::option[basic::options::OptionKeys::matdes::num_subs_building_block]();
484  symm_add = (symm_info->subunit_index(i) <= num_subs && symm_info->subunit_index(j) > num_subs) || (symm_info->subunit_index(j) <= num_subs && symm_info->subunit_index(i) > num_subs); // NK
485  } else {
486  symm_add = ( ( (symm_info->bb_is_independent(i) && !symm_info->bb_is_independent(j)) ||
487  (symm_info->bb_is_independent(i) && !symm_info->bb_is_independent(j)) ) );
488  }
489  if ( !symm_add ) continue;
490  Size i_sym = i;
491  Size j_sym = j;
492  //if ( is_interface_(i_sym) && is_interface_(j_sym) ) continue; //commented out by Sid
493  Real const cendist = edge->square_distance();
494  if ( cendist < distance_squared_ ) {
495  // TR << "interface edge: " << i << ' ' << j << ' ' << cendist << std::endl;
496  is_interface_(i_sym) = is_interface_(j_sym) = true;
497  pair_list_[1].push_back(i_sym);
498  pair_list_[2].push_back(j_sym);
499 
500  contact_list_[i_sym].push_back(j_sym);
501  contact_list_[j_sym].push_back(i_sym);
502 
503  } ///< set pack residue to true if within a predetermined distance (default 8A)
504  } ///< for j
505  } ///< for i
506 
507  /// this is really ugly, there has to be a better way of doing this
508  std::sort( pair_list_[1].begin(), pair_list_[1].end() );
509  new_end_pos = std::unique( pair_list_[1].begin(), pair_list_[1].end() );
510  pair_list_[1].erase( new_end_pos, pair_list_[1].end() );
511  std::sort( pair_list_[2].begin(), pair_list_[2].end() );
512  new_end_pos = std::unique( pair_list_[2].begin(), pair_list_[2].end() );
513  pair_list_[2].erase( new_end_pos, pair_list_[2].end() );
514 }
515 
516 void
517 Interface::set_symmetric_pack(
518  core::pose::Pose const & pose,
520 )
521 {
522  set_pack( pose, task );
523  using namespace core::conformation::symmetry;
524 
525  SymmetricConformation const & SymmConf (
526  dynamic_cast<SymmetricConformation const &> ( pose.conformation()) );
527  SymmetryInfoCOP symm_info( SymmConf.Symmetry_Info() );
528 
529  for ( Size i = 1; i <= pose.total_residue(); ++i ) {
530  if ( !symm_info->chi_is_independent(i) ) {
531  task->nonconst_residue_task( i ).prevent_repacking();
532  }
533  }
534 }
535 
536 } // namespace scoring
537 } // namespace protocols