Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
util.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 util
11 
12 /// @brief Construct a foldtree from a description of the chains
13 /// involved in the interface
14 
15 /// @detailed
16 /// @author Brian Weitzner
17 /// @author Matthew O'Meara
18 
19 
20 // Unit Headers
23 
24 // Platform headers
26 #include <basic/Tracer.hh>
27 #include <basic/datacache/BasicDataCache.hh>
28 #include <basic/database/sql_utils.hh>
30 #include <core/pose/Pose.hh>
32 #include <core/types.hh>
33 #include <core/pose/PDBInfo.hh>
35 
36 // Utility headers
37 #include <utility/vector1.hh>
38 #include <utility/sql_database/DatabaseSessionManager.hh>
39 
40 // External Headers
41 #include <cppdb/frontend.h>
42 
43 // C++ Headers
44 #include <map>
45 #include <sstream>
46 
47 static basic::Tracer TR("protocols.docking.util");
48 
49 namespace protocols {
50 namespace docking {
51 
52 using std::endl;
53 using std::map;
54 using std::min_element;
55 using std::pair;
56 using std::string;
57 using std::stringstream;
58 using cppdb::statement;
59 using cppdb::result;
60 using utility::vector1;
61 using utility::sql_database::sessionOP;
62 using basic::database::safely_prepare_statement;
63 using basic::database::safely_read_from_database;
64 using core::Size;
67 using core::pose::Pose;
70 
71 /// @brief Setup foldtree for across an interface specified by a
72 /// string for the partner chains (using pdb_chain
73 /// identification). The foldtree is set up such that the jump points
74 /// are at the center of masses of the two partners
75 ///
76 /// @detailed
77 /// if partner_chainID == '_' -> use the first movable jump as the cutpoint
78 /// if partner_chainID is of the form (pdb_chain_id)+_(pdb_chain_id)+
79 /// then use the jump between the last chain of the first partner
80 /// and the first chain of the second partner as the cutpoint.
81 /// For example 'ABC_DEF' has chains 'ABC' as the first partner and 'DEF' as
82 /// the second partner.
83 ///
84 /// With the current implementation, all of the chains of the first
85 /// partner must be upstream of the chains of the second partner. If
86 /// this behavior is too limiting, then the behavior can be extended.
87 ///
88 ///
89 /// @return The foldtree in the pose will have a jump from the center
90 /// of mass of the first partner to the center of mass of the second
91 /// partner and no other jumps between residues in different partners
92 ///
93 /// @return the movable_jumps vector contains as it's only entry the
94 /// number of the jump across the interface.
95 void
97  Pose & pose,
98  string const & partner_chainID,
99  DockJumps & movable_jumps
100 ) {
101 
102  PDBInfoCOP pdb_info = pose.pdb_info();
103  movable_jumps.clear();
104 
105  if(!pdb_info){
106  utility_exit_with_message("Attempting to setup foldtree between interface partners, however, the pdb_info object associated with the pose does not exits.");
107  }
108 
109  // identify cutpoint for first movable jump
110  Size cutpoint = 0;
111  FoldTree const & f( pose.fold_tree() );
112  if ( partner_chainID == "_") {
113  // By default, set the first jump as the cutpoint
114 
115  if(f.num_jump() == 0){
116  utility_exit_with_message("Attempting to auto-detect interface partner chains, however the pose contains no jumps.");
117  }
118  cutpoint = f.cutpoint_by_jump(1);
119  movable_jumps.push_back(1);
120  } else {
121  char first_chain_second_partner;
122  for ( Size i=1; i<=partner_chainID.length()-1; i++ ) {
123  if (partner_chainID[i-1] == '_') {
124  first_chain_second_partner = partner_chainID[i];
125  }
126  }
127  for ( Size i=2; i<= pose.total_residue(); ++i ) {
128  if ( pdb_info->chain( i ) == first_chain_second_partner ) {
129  cutpoint = i-1;
130  break;
131  }
132  }
133  if(!cutpoint){
134  utility_exit_with_message(
135  "Attempting to setup foldtree between interface partners, "
136  "however, the cutpoint could not be identified because "
137  "the pdb chain identifier could not be found for "
138  "the first chain of the second partner");
139  }
140 
141  // Specifying chains overrides movable_jumps
142  for (Size i=1; i<=f.num_jump(); ++i) {
143  Size const current_cutpoint = f.cutpoint_by_jump(i);
144  if( current_cutpoint == cutpoint ) {
145  movable_jumps.push_back( i );
146  }
147  }
148 
149 
150  }
151 
152  setup_foldtree(pose, cutpoint, movable_jumps);
153 }
154 
155 /// Here is the protocol that the database should have:
156 ///
157 ///
158 ///CREATE TABLE IF NOT EXISTS interfaces (
159 /// struct_id BLOB,
160 /// interface_id INTEGER,
161 /// FOREIGN KEY (struct_id) REFERENCES structures (struct_id) DEFERRABLE INITIALLY DEFERRED,
162 /// PRIMARY KEY(struct_id, interface_id));
163 ///
164 ///CREATE TABLE IF NOT EXISTS interface_partners (
165 /// interface_id INTEGER,
166 /// partner_id INTEGER,
167 /// FOREIGN KEY (interface_id) REFERENCES interfaces (interface_id) DEFERRABLE INITIALLY DEFERRED,
168 /// PRIMARY KEY(interface_id, partner_id));
169 ///
170 ///CREATE TABLE IF NOT EXISTS interface_partner_chains (
171 /// partner_id INTEGER,
172 /// chain_id INTEGER,
173 /// FOREIGN KEY (interface_interface_id) REFERENCES interface_partners (interface_partner_id) DEFERRABLE INITIALLY DEFERRED,
174 /// PRIMARY KEY(partner_id, chain_id));
175 void
177  Pose & pose,
178  Size const interface_id,
179  sessionOP db_session,
180  DockJumps & movable_jumps
181 ) {
182  string const sele(
183  "SELECT\n"
184  " partner.partner_id AS partner,\n"
185  " chain.chain_id AS chain\n"
186  "FROM\n"
187  " interface_partners AS partner,\n"
188  " interface_partner_chains AS chain\n"
189  "WHERE\n"
190  " partner.interface_id = ? AND\n"
191  " chain.partner_id = partner.partner_id;");
192  statement stmt(safely_prepare_statement(sele, db_session));
193  stmt.bind(1, interface_id);
194  result res(safely_read_from_database(stmt));
195 
196  map<Size, vector1< Size > > partner_to_chains;
197 
198  while(res.next()){
199  Size partner, chain;
200  res >> partner >> chain;
201  partner_to_chains[partner].push_back(chain);
202  }
203 
204  setup_foldtree(pose, partner_to_chains, movable_jumps);
205 }
206 
207 
208 void
210  Pose & pose,
211  map< Size, vector1< Size > > const & partner_to_chains,
212  DockJumps & movable_jumps
213 ) {
214 
215  if(partner_to_chains.size() != 2){
216  stringstream error_msg;
217  error_msg
218  << "The current implementation of setup_foldtree requires "
219  << "that there be exactly two chains at an interface, however, "
220  << "'" << partner_to_chains.size() << "' partners were given.";
221  utility_exit_with_message(error_msg.str());
222  }
223 
224  // The current implementation of the setup_foltree assumes all the
225  // chains of one partner come before all the chains of the second
226  // partner.
227  vector1< pair< Size, Size > > first_and_last_chains;
228  for(map< Size, vector1 < Size > >::const_iterator
229  p_cs = partner_to_chains.begin(),
230  p_cs_end = partner_to_chains.end();
231  p_cs != p_cs_end; ++p_cs){
232 
233  first_and_last_chains.push_back(
234  pair< Size, Size>(
235  *min_element(p_cs->second.begin(), p_cs->second.end()),
236  *max_element(p_cs->second.begin(), p_cs->second.end())));
237  }
238 
239  Size first_chain_second_partner;
240  if(first_and_last_chains[1].second < first_and_last_chains[2].first){
241  first_chain_second_partner = first_and_last_chains[2].first;
242  } else if(first_and_last_chains[2].second < first_and_last_chains[1].first){
243  first_chain_second_partner = first_and_last_chains[1].first;
244  } else {
245  utility_exit_with_message(
246  "The current implementation of setup_foldtree requires "
247  "that the chains of one partner come before all "
248  "the chains of the second partner.");
249  }
250  Size cutpoint = 0;
251  for ( Size i=2; i<= pose.total_residue(); ++i ) {
252  if ( (Size)pose.chain(i) == first_chain_second_partner ) {
253  cutpoint = i-1;
254  break;
255  }
256  }
257  if(!cutpoint){
258  utility_exit_with_message(
259  "Attempting to setup foldtree between interface partners, "
260  "however, the cutpoint could not be identified because "
261  "the pdb chain identifier could not be found for "
262  "the first chain of the second partner");
263  }
264 
265  movable_jumps.clear();
266  FoldTree const & f(pose.fold_tree());
267 
268  // Specifying chains overrides movable_jumps
269  for (Size i=1; i<=f.num_jump(); ++i) {
270  Size const current_cutpoint = f.cutpoint_by_jump(i);
271  if( current_cutpoint == cutpoint ) {
272  movable_jumps.push_back( i );
273  }
274  }
275 
276  setup_foldtree(pose, cutpoint, movable_jumps);
277 
278 }
279 
280 void
282  Pose & pose,
283  Size const cutpoint,
284  DockJumps & movable_jumps
285 ){
286 
287  runtime_assert_string_msg(
288  movable_jumps.size() > 0,
289  "Unable to set up interface foldtree because there are no movable jumps");
290 
291  FoldTree f(pose.fold_tree());
292  Conformation const & conformation(pose.conformation());
293 
294  // first case: two-body docking, one jump movable
295 
296  // SJF The default foldtree (when the pose is read from disk) sets
297  // all the jumps from the first residue to the first residue of each
298  // chain. We want a rigid body jump to be between centres of mass
299  // of the two partners (jump_pos1, 2) and all of the rest of the
300  // jumps to be sequential so that all of the chains are traversed
301  // from the jump position onwards default tree. pas simple...
302  if( movable_jumps.size() == 1 ) {
303 
304  //identify center of masses for jump points
305  Size jump_pos1 ( geometry::residue_center_of_mass( pose, 1, cutpoint ) );
306  Size jump_pos2 ( geometry::residue_center_of_mass( pose, cutpoint+1, pose.total_residue() ) );
307  TR.Debug << "cutpoint: " << cutpoint << std::endl;
308  TR.Debug << "jump1: " << jump_pos1 << std::endl;
309  TR.Debug << "jump2: " << jump_pos2 << std::endl;
310 
311  //setup fold tree based on cutpoints and jump points
312  f.clear();
313  f.simple_tree( pose.total_residue() );
314  f.new_jump( jump_pos1, jump_pos2, cutpoint);
315  movable_jumps.clear();
316  movable_jumps.push_back( 1 );
317 
318  Size chain_begin(0), chain_end(0);
319 
320  //rebuild jumps between chains N-terminal to the docking cutpoint
321  chain_end = cutpoint;
322  chain_begin = conformation.chain_begin( pose.chain(chain_end) );
323  while (chain_begin != 1){
324  chain_end = chain_begin-1;
325  f.new_jump( chain_end, chain_begin, chain_end);
326  chain_begin = conformation.chain_begin( pose.chain(chain_end) );
327  }
328 
329  //rebuild jumps between chains C-terminal to the docking cutpoint
330  chain_begin = cutpoint+1;
331  chain_end = conformation.chain_end( pose.chain(chain_begin) );
332  while (chain_end != pose.total_residue()){
333  chain_begin = chain_end+1;
334  f.new_jump( chain_end, chain_begin, chain_end);
335  chain_end = conformation.chain_end( pose.chain(chain_begin) );
336  }
337  }
338 
339  // second case: multibody docking, more than one jump movable
340 
341  // anchor all jumps relative to the CoM of the "downstream" chains,
342  // which are defined as first sequential chains that are not movable
343  // this will always be at least chain 1, but could be chains 1+2+...
344  // the jumps for all nonmoving chains are left alone -- they anchor
345  // to N terminal residue
346  else {
347  std::sort( movable_jumps.begin(), movable_jumps.end() );
348 
349  Size const base_cutpoint = cutpoint;
350  Size const base_jump_pos( geometry::residue_center_of_mass( pose, 1, base_cutpoint ) );
351  for(DockJumps::const_iterator
352  curr_jump = movable_jumps.begin(),
353  last_movable_jump = movable_jumps.end();
354  curr_jump != last_movable_jump; ++curr_jump ) {
355  Size const curr_cutpoint = f.cutpoint_by_jump( *curr_jump ); // used to get the index of a residue in the moving chain (curr_cutpoint+1)
356  Size const chain_begin = conformation.chain_begin( pose.chain(curr_cutpoint+1) );
357  Size const chain_end = conformation.chain_end( pose.chain(curr_cutpoint+1) );
358  Size const moving_jump_pos( geometry::residue_center_of_mass( pose, chain_begin, chain_end ) );
359  TR.Debug
360  << "Adjusting Jump (cut) for #" << *curr_jump
361  << "(" << curr_cutpoint << "): "
362  << "begin " << chain_begin
363  << " end " << chain_end
364  << " base_cutpoint " << base_cutpoint
365  << " base_jump_pos " << base_jump_pos
366  << " moving_jump_pos " << moving_jump_pos << endl;
367  f.slide_jump( *curr_jump, base_jump_pos, moving_jump_pos );
368  }
369  }
370 
371  // set docking fold tree to the pose
372  f.reorder( 1 );
373  runtime_assert( f.check_fold_tree() );
374  pose.fold_tree( f );
375 
376  //set up InterfaceInfo object in pose to specify which interface(s)
377  //to calculate docking centroid mode scoring components from
378  using namespace core::scoring;
379  using namespace protocols::scoring;
380  //using core::pose::datacache::CacheableDataType::INTERFACE_INFO;
381 
382  InterfaceInfoOP docking_interface = new InterfaceInfo( movable_jumps );
383  pose.data().set(
385  docking_interface);
386 }
387 
388 } //docking
389 } //protocols